forked from mito-systems/sol-mem-gen
Use BN instead of Big in create lock
This commit is contained in:
parent
e04c43baca
commit
7aa0d44f61
@ -12,7 +12,7 @@
|
|||||||
"@coral-xyz/anchor": "^0.30.1",
|
"@coral-xyz/anchor": "^0.30.1",
|
||||||
"@fal-ai/client": "^1.2.1",
|
"@fal-ai/client": "^1.2.1",
|
||||||
"@google/generative-ai": "^0.21.0",
|
"@google/generative-ai": "^0.21.0",
|
||||||
"@solana/spl-token": "^0.3.8",
|
"@solana/spl-token": "^0.3.11",
|
||||||
"@solana/web3.js": "^1.78.4",
|
"@solana/web3.js": "^1.78.4",
|
||||||
"big.js": "^6.2.2",
|
"big.js": "^6.2.2",
|
||||||
"bn.js": "^5.2.0",
|
"bn.js": "^5.2.0",
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
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) {
|
export async function GET(req: NextRequest) {
|
||||||
try {
|
try {
|
||||||
const { searchParams } = new URL(req.url);
|
const { searchParams } = new URL(req.url);
|
||||||
const signature = searchParams.get('signature') || '4HBtnoNUuMGpmbhD9cPiJtbxkhux31pfZs3HYud5eopAU69RaC4UbJsYdj83eafFxV6eH8pSaRgqELrwyjrWp7yz';
|
const signature = searchParams.get('signature') || '4HBtnoNUuMGpmbhD9cPiJtbxkhux31pfZs3HYud5eopAU69RaC4UbJsYdj83eafFxV6eH8pSaRgqELrwyjrWp7yz';
|
||||||
|
|
||||||
const { authority, amount } = await extractInfo(signature);
|
const { authority, amount } = await extractTxInfo(signature);
|
||||||
if (!authority || Number(amount) <= 0) {
|
if (!authority || Number(amount) <= 0) {
|
||||||
return NextResponse.json({ error: "Invalid transaction details" }, { status: 400 });
|
return NextResponse.json({ error: "Invalid transaction details" }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ import {
|
|||||||
createAssociatedTokenAccountInstruction,
|
createAssociatedTokenAccountInstruction,
|
||||||
getAssociatedTokenAddressSync,
|
getAssociatedTokenAddressSync,
|
||||||
TOKEN_2022_PROGRAM_ID,
|
TOKEN_2022_PROGRAM_ID,
|
||||||
TOKEN_PROGRAM_ID,
|
|
||||||
} from '@solana/spl-token';
|
} from '@solana/spl-token';
|
||||||
import {
|
import {
|
||||||
AnchorProvider,
|
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 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<Locker> {
|
export function createLockerProgram(wallet: Wallet): Program<Locker> {
|
||||||
const provider = new AnchorProvider(connection, wallet, {
|
const provider = new AnchorProvider(connection, wallet, {
|
||||||
maxRetries: 3,
|
maxRetries: 3,
|
||||||
@ -80,8 +73,9 @@ export interface CreateVestingPlanParams {
|
|||||||
// V2 instructions
|
// V2 instructions
|
||||||
export async function createVestingPlanV2(params: CreateVestingPlanParams) {
|
export async function createVestingPlanV2(params: CreateVestingPlanParams) {
|
||||||
let {
|
let {
|
||||||
tokenMint,
|
|
||||||
ownerKeypair,
|
ownerKeypair,
|
||||||
|
tokenMint,
|
||||||
|
isAssertion,
|
||||||
vestingStartTime,
|
vestingStartTime,
|
||||||
cliffTime,
|
cliffTime,
|
||||||
frequency,
|
frequency,
|
||||||
@ -183,7 +177,7 @@ export async function createVestingPlanV2(params: CreateVestingPlanParams) {
|
|||||||
return escrow;
|
return escrow;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof TransactionExpiredTimeoutError) {
|
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...');
|
console.log('Confirming the transaction again...');
|
||||||
const confirmedTransaction = await connection.getTransaction(error.signature, {
|
const confirmedTransaction = await connection.getTransaction(error.signature, {
|
||||||
commitment: 'confirmed',
|
commitment: 'confirmed',
|
||||||
@ -191,7 +185,7 @@ export async function createVestingPlanV2(params: CreateVestingPlanParams) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if(confirmedTransaction === null) {
|
if(confirmedTransaction === null) {
|
||||||
console.error('Transaction failed for',error.signature);
|
console.error('Transaction failed for', error.signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
return escrow;
|
return escrow;
|
||||||
@ -199,66 +193,3 @@ export async function createVestingPlanV2(params: CreateVestingPlanParams) {
|
|||||||
throw error;
|
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();
|
|
||||||
}
|
|
||||||
|
22
src/utils/extractTxInfo.ts
Normal file
22
src/utils/extractTxInfo.ts
Normal file
@ -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 };
|
||||||
|
}
|
@ -3,6 +3,7 @@ import BN from 'bn.js';
|
|||||||
|
|
||||||
import { Connection } from '@solana/web3.js';
|
import { Connection } from '@solana/web3.js';
|
||||||
import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
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');
|
assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL, 'SOLANA_RPC_URL is required');
|
||||||
|
|
||||||
@ -53,22 +54,7 @@ export async function verifyPayment(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const transaction = await connection.getParsedTransaction(transactionSignature, 'confirmed');
|
const { amount } = await extractTxInfo(transactionSignature);
|
||||||
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);
|
const transactionAmount = new BN(amount);
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { DataSource, EntityTarget } from 'typeorm';
|
import { DataSource, EntityTarget } from 'typeorm';
|
||||||
|
|
||||||
import { Tweet } from '../entity/Tweet';
|
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<boolean> {
|
export async function verifySignatureInTweet(transactionSignature: string): Promise<boolean> {
|
||||||
const paymentRepository = global.appDataSource.getRepository(global.entities.Payment);
|
const paymentRepository = global.appDataSource.getRepository(global.entities.Payment);
|
||||||
@ -34,7 +35,7 @@ export async function processTweet(txSignature: string, memeUrl: string | null)
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (isFourthUser) {
|
if (isFourthUser) {
|
||||||
const { authority, amount } = await extractInfo(txSignature);
|
const { authority, amount } = await extractTxInfo(txSignature);
|
||||||
|
|
||||||
if (!authority || Number(amount) <= 0) {
|
if (!authority || Number(amount) <= 0) {
|
||||||
return { error: "Invalid transaction details" }
|
return { error: "Invalid transaction details" }
|
||||||
|
Loading…
Reference in New Issue
Block a user