diff --git a/next-env.d.ts b/next-env.d.ts
index fd36f94..4f11a03 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,6 +1,5 @@
///
///
-///
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/src/app/api/lock/route.ts b/src/app/api/lock/route.ts
index 422e0ae..fdd607a 100644
--- a/src/app/api/lock/route.ts
+++ b/src/app/api/lock/route.ts
@@ -1,172 +1,67 @@
import { NextRequest, NextResponse } from "next/server";
-import { Connection, Keypair, ParsedInstruction, ParsedTransactionWithMeta, PartiallyDecodedInstruction, PublicKey } from "@solana/web3.js";
+import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import { createLock } from "../../../utils/create-lock";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
-import assert from "assert";
import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes";
-import { BN, min } from "bn.js";
+import { BN } from "bn.js";
+import Big from 'big.js';
-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 MTM_MINT_ADDRESS = process.env.NEXT_PUBLIC_MTM_TOKEN_MINT;
-
-function isParsedInstruction(
- instruction: ParsedInstruction | PartiallyDecodedInstruction
- ): instruction is ParsedInstruction {
- return (instruction as ParsedInstruction).parsed !== undefined;
+async function extractInfo(transactionSignature: string) {
+ const transaction = await connection.getParsedTransaction(transactionSignature, 'confirmed');
+ if (!transaction) {
+ throw new Error('Transaction not found');
}
-async function extractMTMTransferDetails(
-connection: Connection,
-signature: string,
-mtmMintAddress: string // Mint address of the MTM token
-) {
-try {
- // Fetch the transaction details using the signature
- const transaction: ParsedTransactionWithMeta | null = await connection.getParsedTransaction(signature, {
- maxSupportedTransactionVersion: 0, // Ensure compatibility with legacy transactions
- });
+ const transferInstruction = transaction.transaction.message.instructions.find(
+ (instr) => 'parsed' in instr && instr.programId.equals(TOKEN_PROGRAM_ID)
+ );
- if (!transaction) {
- throw new Error('Transaction not found');
- }
+ if (!transferInstruction || !('parsed' in transferInstruction)) {
+ throw new Error('Transfer instruction not found');
+ }
- // Extract the "from", "to", and "amount" for the MTM token transfer
- let fromAddress: string | null = null;
- let toAddress: string | null = null;
- let tokenAmount: number | null = null;
-
- // Function to process instructions
- const processInstructions = (instructions: ParsedInstruction[]) => {
- instructions.forEach((instruction: ParsedInstruction) => {
- if (instruction.programId.equals(new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'))) {
- // Check if the instruction is a transfer instruction
- if (instruction.parsed.type === 'transfer' || instruction.parsed.type === 'transferChecked') {
- const parsedInfo = instruction.parsed.info;
- const mint = parsedInfo.mint;
-
- // Check if the mint address matches the provided MTM mint address
- if (mint === mtmMintAddress) {
- fromAddress = parsedInfo.source;
- toAddress = parsedInfo.destination;
- tokenAmount = parsedInfo.amount;
- }
- }
- }
- });
- };
-
- // Filter out PartiallyDecodedInstruction and process only ParsedInstruction
- const parsedInstructions = transaction.transaction.message.instructions.filter(isParsedInstruction);
-
- // Process top-level instructions
- processInstructions(parsedInstructions);
-
- // Process inner instructions (if any)
- if (transaction.meta?.innerInstructions) {
- transaction.meta.innerInstructions.forEach((inner) => {
- const innerParsedInstructions = inner.instructions.filter(isParsedInstruction);
- processInstructions(innerParsedInstructions);
- });
- }
-
- if (!fromAddress || !toAddress || !tokenAmount) {
- throw new Error('No matching MTM token transfer found in the transaction');
- }
-
- return { fromAddress, toAddress, tokenAmount };
-} catch (error) {
- console.error('Error extracting MTM transfer details:', error);
- throw error;
+ const { info: { amount, authority } } = transferInstruction.parsed;
+ return { authority, amount };
}
+
+async function createRewardLock(authority: string, amount: string) {
+ const { USER_PRIVATE_KEY, CLIFF_TIME, WSOL_MINT, NEXT_PUBLIC_MTM_TOKEN_MINT, REWARD_MULTIPLIER } = process.env;
+ if (!USER_PRIVATE_KEY || !CLIFF_TIME || !WSOL_MINT || !NEXT_PUBLIC_MTM_TOKEN_MINT || !REWARD_MULTIPLIER) {
+ throw new Error('Missing required environment variables');
+ }
+
+ const duration = new BN(CLIFF_TIME).add(new BN(Math.floor(Date.now() / 1000)));
+ const tokenLockerKeypair = Keypair.fromSecretKey(bs58.decode(USER_PRIVATE_KEY));
+ const recipientPublicKey = new PublicKey(authority);
+
+ const url = `https://api.jup.ag/price/v2?ids=${NEXT_PUBLIC_MTM_TOKEN_MINT}&vsToken=${WSOL_MINT}`;
+ const response = await fetch(url);
+ const { data } = await response.json();
+
+ const priceWSOLFor1MTM = new Big(data[NEXT_PUBLIC_MTM_TOKEN_MINT].price).toFixed(9);
+ const mtmAmount = new Big(amount).div(new Big(10).pow(6));
+ const wsolAmount = new BN(new Big(mtmAmount).times(priceWSOLFor1MTM).times(new Big(10).pow(9)).times(REWARD_MULTIPLIER).toFixed(0));
+
+ return createLock(tokenLockerKeypair, recipientPublicKey, duration, wsolAmount);
}
export async function GET(req: NextRequest) {
- try {
- // Get signature from URL params
- const { searchParams } = new URL(req.url);
- const signature = searchParams.get('signature') || '4HBtnoNUuMGpmbhD9cPiJtbxkhux31pfZs3HYud5eopAU69RaC4UbJsYdj83eafFxV6eH8pSaRgqELrwyjrWp7yz';
- let amount = new BN(0);
+ try {
+ const { searchParams } = new URL(req.url);
+ const signature = searchParams.get('signature') || '4HBtnoNUuMGpmbhD9cPiJtbxkhux31pfZs3HYud5eopAU69RaC4UbJsYdj83eafFxV6eH8pSaRgqELrwyjrWp7yz';
- if (!signature) {
- return NextResponse.json(
- { error: "Transaction signature is required" },
- { status: 400 }
- );
- }
-
- if (!MTM_MINT_ADDRESS) {
- return NextResponse.json(
- { error: "MTM_MINT_ADDRESS environment variable is not set" },
- { status: 500 }
- );
- }
-
- // Extract transaction details
- // const result = await extractMTMTransferDetails(
- // connection,
- // signature,
- // MTM_MINT_ADDRESS
- // );
-
- // if (!result) {
- // return NextResponse.json(
- // { error: "Failed to extract transaction details" },
- // { status: 500 }
- // );
- // }
-
- // console.log({ result });
-
- // // Validate extracted values
- // if (!result.fromAddress || result.tokenAmount <= 0) {
- // return NextResponse.json(
- // { error: "Invalid transaction details extracted" },
- // { status: 400 }
- // );
- // }
-
- assert(process.env.USER_PRIVATE_KEY, 'USER_PRIVATE_KEY is required');
- assert(process.env.CLIFF_TIME, 'CLIFF_TIME is required');
-
- const USER_PRIVATE_KEY = process.env.USER_PRIVATE_KEY;
- const CLIFF_TIME = process.env.CLIFF_TIME;
-
- const duration = new BN(CLIFF_TIME).add(new BN(Math.floor(Date.now() / 1000)));
- const tokenLockerKeypair = Keypair.fromSecretKey(bs58.decode(USER_PRIVATE_KEY));
- const recipientPublicKey = new PublicKey('Bnnq8n3rRKZe8NJAYn4vBkxp1v8Bnc6zXpUPpDeujCu');
-
- amount = amount.add(new BN(1000000));
-
- // Call createLock function with extracted values
- let escrow;
- try {
- escrow = await createLock(tokenLockerKeypair, recipientPublicKey, duration, amount);
- } catch (error) {
- console.error('Error creating lock:', error);
- return NextResponse.json(
- { error: "Failed to create lock" },
- { status: 500 }
- );
- }
-
- console.log({ escrow });
-
- // Return successful response
- return NextResponse.json({
- success: true,
- data: {
- sender: recipientPublicKey,
- amount: amount,
- }
- });
-
- } catch (error) {
- console.error('API route error:', error);
- return NextResponse.json(
- { error: "Internal server error" },
- { status: 500 }
- );
+ const { authority, amount } = await extractInfo(signature);
+ if (!authority || Number(amount) <= 0) {
+ return NextResponse.json({ error: "Invalid transaction details" }, { status: 400 });
}
-}
+
+ const escrow = await createRewardLock(authority, amount);
+ return NextResponse.json({ success: true, data: { escrow } });
+
+ } catch (error) {
+ console.error('API route error:', error);
+ return NextResponse.json({ error: "Internal server error" }, { status: 500 });
+ }
+}
\ No newline at end of file
diff --git a/src/utils/create-lock.ts b/src/utils/create-lock.ts
index 8b540f6..ad300a0 100644
--- a/src/utils/create-lock.ts
+++ b/src/utils/create-lock.ts
@@ -14,16 +14,16 @@ import { createVestingPlanV2 } from '../locker-utils';
assert(process.env.RPC_ENDPOINT);
assert(process.env.USER_PRIVATE_KEY);
//assert(process.env.RECIPIENT_PUBLIC_KEY);
-assert(process.env.MTM_MINT);
+assert(process.env.WSOL_MINT);
const RPC_ENDPOINT= process.env.RPC_ENDPOINT;
-const MTM_MINT = process.env.MTM_MINT;
+const WSOL_MINT = process.env.WSOL_MINT;
const USER_PRIVATE_KEY = process.env.USER_PRIVATE_KEY;
const userKP = anchor.web3.Keypair.fromSecretKey(bs58.decode(USER_PRIVATE_KEY));
const connection = new Connection(RPC_ENDPOINT);
-const token = new PublicKey(MTM_MINT);
+const token = new PublicKey(WSOL_MINT);
const provider = new anchor.AnchorProvider(
connection,
@@ -35,7 +35,7 @@ const provider = new anchor.AnchorProvider(
anchor.setProvider(provider);
export async function getMTMBalance (senderKeypair: anchor.web3.Keypair): Promise {
- const mintPublicKey = new PublicKey(MTM_MINT);
+ const mintPublicKey = new PublicKey(WSOL_MINT);
const publicKey = senderKeypair.publicKey;
const tokenAccounts = await connection.getTokenAccountsByOwner(publicKey, { mint: mintPublicKey });