forked from mito-systems/sol-mem-gen
Create lock using wsol
This commit is contained in:
parent
303d238d6c
commit
8e7c382473
1
next-env.d.ts
vendored
1
next-env.d.ts
vendored
@ -1,6 +1,5 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference types="next/navigation-types/compat/navigation" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
|
@ -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 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 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 connection = new Connection(process.env.NEXT_PUBLIC_SOLANA_RPC_URL!);
|
||||
|
||||
async function extractInfo(transactionSignature: string) {
|
||||
const transaction = await connection.getParsedTransaction(transactionSignature, 'confirmed');
|
||||
if (!transaction) {
|
||||
throw new Error('Transaction 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;
|
||||
const transferInstruction = transaction.transaction.message.instructions.find(
|
||||
(instr) => 'parsed' in instr && instr.programId.equals(TOKEN_PROGRAM_ID)
|
||||
);
|
||||
|
||||
// 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 (!transferInstruction || !('parsed' in transferInstruction)) {
|
||||
throw new Error('Transfer instruction not found');
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (!signature) {
|
||||
return NextResponse.json(
|
||||
{ error: "Transaction signature is required" },
|
||||
{ status: 400 }
|
||||
);
|
||||
const { authority, amount } = await extractInfo(signature);
|
||||
if (!authority || Number(amount) <= 0) {
|
||||
return NextResponse.json({ error: "Invalid transaction details" }, { 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,
|
||||
}
|
||||
});
|
||||
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 }
|
||||
);
|
||||
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
|
||||
}
|
||||
}
|
@ -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<BN> {
|
||||
const mintPublicKey = new PublicKey(MTM_MINT);
|
||||
const mintPublicKey = new PublicKey(WSOL_MINT);
|
||||
const publicKey = senderKeypair.publicKey;
|
||||
const tokenAccounts = await connection.getTokenAccountsByOwner(publicKey, { mint: mintPublicKey });
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user