sol-mem-gen/src/utils/verifyPayment.ts
2025-01-30 14:41:29 +05:30

87 lines
2.6 KiB
TypeScript

import assert from 'assert';
import BN from 'bn.js';
import { Connection } from '@solana/web3.js';
import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
import { AppDataSource } from '../data-source';
import { Payment } from '../entity/Payment';
assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL, 'SOLANA_RPC_URL is required');
const SOLANA_RPC_URL = process.env.NEXT_PUBLIC_SOLANA_RPC_URL;
const SOLANA_WEBSOCKET_URL = process.env.NEXT_PUBLIC_SOLANA_WEBSOCKET_URL;
const connection = new Connection(
SOLANA_RPC_URL,
{
commitment: 'confirmed',
wsEndpoint: SOLANA_WEBSOCKET_URL,
confirmTransactionInitialTimeout: 60000,
}
);
export async function isSignatureUsed(transactionSignature: string): Promise<boolean> {
const paymentRepository = AppDataSource.getRepository(Payment);
const payment = await paymentRepository.findOneBy({ transactionSignature });
if (payment) {
return true;
}
return false;
}
export async function markSignatureAsUsed(transactionSignature: string): Promise<void> {
await AppDataSource.transaction(async (transactionalEntityManager) => {
const paymentRepository = transactionalEntityManager.getRepository(Payment);
// Check if the payment with the given signature already exists
const exists = await paymentRepository.exists({ where: { transactionSignature } });
// If not, create a new payment entry
if (!exists) {
const newPayment = paymentRepository.create({ transactionSignature });
await paymentRepository.save(newPayment);
}
});
}
export async function verifyPayment(
transactionSignature: string,
tokenAmount: BN,
): Promise<boolean> {
try {
// Check if the signature is already used
if (await isSignatureUsed(transactionSignature)) {
return false;
}
const transaction = await connection.getParsedTransaction(transactionSignature, 'confirmed');
if (!transaction) {
throw new Error('Transaction not found');
}
const transferInstruction = transaction.transaction.message.instructions.find(
(instr) => 'parsed' in instr && instr.programId.equals(TOKEN_PROGRAM_ID)
);
if (!transferInstruction || !('parsed' in transferInstruction)) {
throw new Error('Transfer instruction not found');
}
const { parsed } = transferInstruction;
const { info } = parsed;
const { amount } = info;
const transactionAmount = new BN(amount);
if (transactionAmount.gte(tokenAmount)) {
return true;
}
console.log('Transaction amount is less than minimum amount. Rejecting request');
return false;
} catch (error) {
console.error('Verification error:', error);
return false;
}
}