From 7aa0d44f61683038d72e4ebc3de9edd3651e2a03 Mon Sep 17 00:00:00 2001 From: AdityaSalunkhe21 Date: Thu, 6 Feb 2025 16:36:11 +0530 Subject: [PATCH] Use BN instead of Big in create lock --- package.json | 2 +- src/app/api/lock/route.ts | 7 ++-- src/locker-utils/index.ts | 77 ++------------------------------------ src/utils/extractTxInfo.ts | 22 +++++++++++ src/utils/verifyPayment.ts | 18 +-------- src/utils/verifyTweet.ts | 5 ++- 6 files changed, 35 insertions(+), 96 deletions(-) create mode 100644 src/utils/extractTxInfo.ts diff --git a/package.json b/package.json index 8a96f4d..2e18549 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "@coral-xyz/anchor": "^0.30.1", "@fal-ai/client": "^1.2.1", "@google/generative-ai": "^0.21.0", - "@solana/spl-token": "^0.3.8", + "@solana/spl-token": "^0.3.11", "@solana/web3.js": "^1.78.4", "big.js": "^6.2.2", "bn.js": "^5.2.0", diff --git a/src/app/api/lock/route.ts b/src/app/api/lock/route.ts index ce4dc3c..ce1f981 100644 --- a/src/app/api/lock/route.ts +++ b/src/app/api/lock/route.ts @@ -1,15 +1,14 @@ import { NextRequest, NextResponse } from "next/server"; -import { Connection} from "@solana/web3.js"; -import { createRewardLock, extractInfo } from "../../../utils/create-lock"; -const connection = new Connection(process.env.NEXT_PUBLIC_SOLANA_RPC_URL!); +import { createRewardLock } from "../../../utils/create-lock"; +import { extractTxInfo } from "../../../utils/extractTxInfo"; export async function GET(req: NextRequest) { try { const { searchParams } = new URL(req.url); const signature = searchParams.get('signature') || '4HBtnoNUuMGpmbhD9cPiJtbxkhux31pfZs3HYud5eopAU69RaC4UbJsYdj83eafFxV6eH8pSaRgqELrwyjrWp7yz'; - const { authority, amount } = await extractInfo(signature); + const { authority, amount } = await extractTxInfo(signature); if (!authority || Number(amount) <= 0) { return NextResponse.json({ error: "Invalid transaction details" }, { status: 400 }); } diff --git a/src/locker-utils/index.ts b/src/locker-utils/index.ts index 52c37fe..58f102a 100644 --- a/src/locker-utils/index.ts +++ b/src/locker-utils/index.ts @@ -14,7 +14,6 @@ import { createAssociatedTokenAccountInstruction, getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID, - TOKEN_PROGRAM_ID, } from '@solana/spl-token'; import { AnchorProvider, @@ -39,12 +38,6 @@ assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL); const connection = new Connection(process.env.NEXT_PUBLIC_SOLANA_RPC_URL); -const ESCROW_USE_SPL_TOKEN = 0; - -const MEMO_PROGRAM = new web3.PublicKey( - "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr" -); - export function createLockerProgram(wallet: Wallet): Program { const provider = new AnchorProvider(connection, wallet, { maxRetries: 3, @@ -80,8 +73,9 @@ export interface CreateVestingPlanParams { // V2 instructions export async function createVestingPlanV2(params: CreateVestingPlanParams) { let { - tokenMint, ownerKeypair, + tokenMint, + isAssertion, vestingStartTime, cliffTime, frequency, @@ -183,7 +177,7 @@ export async function createVestingPlanV2(params: CreateVestingPlanParams) { return escrow; } catch (error) { if (error instanceof TransactionExpiredTimeoutError) { - console.error('Transaction confirmation delayed for',error.signature); + console.error('Transaction confirmation delayed for', error.signature); console.log('Confirming the transaction again...'); const confirmedTransaction = await connection.getTransaction(error.signature, { commitment: 'confirmed', @@ -191,7 +185,7 @@ export async function createVestingPlanV2(params: CreateVestingPlanParams) { }); if(confirmedTransaction === null) { - console.error('Transaction failed for',error.signature); + console.error('Transaction failed for', error.signature); } return escrow; @@ -199,66 +193,3 @@ export async function createVestingPlanV2(params: CreateVestingPlanParams) { throw error; } } - -export interface ClaimTokenParamsV2 { - isAssertion: boolean; - escrow: web3.PublicKey; - recipient: web3.Keypair; - maxAmount: BN; - recipientToken: web3.PublicKey; - tokenProgram: web3.PublicKey; -} - -export async function claimTokenV2(params: ClaimTokenParamsV2) { - let { isAssertion, escrow, recipient, maxAmount, recipientToken } = params; - const program = createLockerProgram(new Wallet(recipient)); - const escrowState = await program.account.vestingEscrow.fetch(escrow); - const tokenProgram = - escrowState.tokenProgramFlag == ESCROW_USE_SPL_TOKEN - ? TOKEN_PROGRAM_ID - : TOKEN_2022_PROGRAM_ID; - - const escrowToken = getAssociatedTokenAddressSync( - escrowState.tokenMint, - escrow, - true, - tokenProgram, - ASSOCIATED_TOKEN_PROGRAM_ID - ); - - let remainingAccountsInfo: OptionRemainingAccountsInfoData | null = null; - let remainingAccounts: AccountMeta[] | undefined = []; - if (tokenProgram == TOKEN_2022_PROGRAM_ID) { - let claimTransferHookAccounts = - await TokenExtensionUtil.getExtraAccountMetasForTransferHook( - program.provider.connection, - escrowState.tokenMint, - escrowToken, - recipientToken, - escrow, - TOKEN_2022_PROGRAM_ID - ); - - [remainingAccountsInfo, remainingAccounts] = new RemainingAccountsBuilder() - .addSlice( - RemainingAccountsType.TransferHookEscrow, - claimTransferHookAccounts - ) - .build(); - } - - const tx = await program.methods - .claimV2(maxAmount, remainingAccountsInfo) - .accounts({ - tokenProgram, - tokenMint: escrowState.tokenMint, - memoProgram: MEMO_PROGRAM, - escrow, - escrowToken, - recipient: recipient.publicKey, - recipientToken, - } as any) - .remainingAccounts(remainingAccounts ? remainingAccounts : []) - .signers([recipient]) - .rpc(); -} diff --git a/src/utils/extractTxInfo.ts b/src/utils/extractTxInfo.ts new file mode 100644 index 0000000..162c390 --- /dev/null +++ b/src/utils/extractTxInfo.ts @@ -0,0 +1,22 @@ +import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; +import { Connection } from "@solana/web3.js"; + +const connection = new Connection(process.env.NEXT_PUBLIC_SOLANA_RPC_URL!); + +export async function extractTxInfo(transactionSignature: string) { + const result = await connection.getParsedTransaction(transactionSignature, 'confirmed'); + if (!result) { + throw new Error('Transaction not found'); + } + + const transferInstruction = result.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 { info: { amount, authority } } = transferInstruction.parsed; + return { authority, amount }; + } \ No newline at end of file diff --git a/src/utils/verifyPayment.ts b/src/utils/verifyPayment.ts index 63dc2e2..efa87c4 100644 --- a/src/utils/verifyPayment.ts +++ b/src/utils/verifyPayment.ts @@ -3,6 +3,7 @@ import BN from 'bn.js'; import { Connection } from '@solana/web3.js'; import { TOKEN_PROGRAM_ID } from '@solana/spl-token'; +import { extractTxInfo } from './extractTxInfo'; assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL, 'SOLANA_RPC_URL is required'); @@ -53,22 +54,7 @@ export async function verifyPayment( 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 { amount } = await extractTxInfo(transactionSignature); const transactionAmount = new BN(amount); diff --git a/src/utils/verifyTweet.ts b/src/utils/verifyTweet.ts index 26c701d..d102944 100644 --- a/src/utils/verifyTweet.ts +++ b/src/utils/verifyTweet.ts @@ -1,7 +1,8 @@ import { DataSource, EntityTarget } from 'typeorm'; import { Tweet } from '../entity/Tweet'; -import { createRewardLock, extractInfo } from './create-lock'; +import { createRewardLock } from './create-lock'; +import { extractTxInfo } from './extractTxInfo'; export async function verifySignatureInTweet(transactionSignature: string): Promise { const paymentRepository = global.appDataSource.getRepository(global.entities.Payment); @@ -34,7 +35,7 @@ export async function processTweet(txSignature: string, memeUrl: string | null) try { if (isFourthUser) { - const { authority, amount } = await extractInfo(txSignature); + const { authority, amount } = await extractTxInfo(txSignature); if (!authority || Number(amount) <= 0) { return { error: "Invalid transaction details" }