我正在为我的应用程序使用 Jupiter api,并且在我的应用程序上我想交换并将交换的代币直接发送到商家帐户。我可以在一笔交易中执行此操作吗?
https://station.jup.ag/docs/apis/ payments-api
从这篇文档中,我认为如果我将destinationTokenAccount设置为商家钱包地址,那么交换的令牌可以直接发送到商家帐户。
// Replace with the Jupiter API endpoint
const JUPITER_QUOTE_API = 'https://quote-api.jup.ag/v6/quote';
const JUPITER_SWAP_API = 'https://quote-api.jup.ag/v6/swap';
// Step 1: Fetch swap info from Jupiter
const fetchSwapInfo = async (inputMint: string, outputMint: string, amount: number) => {
const url = `${JUPITER_QUOTE_API}?inputMint=${inputMint}&outputMint=${outputMint}&amount=${amount}&swapMode=ExactOut&slippageBps=50`;
const response = await fetch(url);
const data = await response.json();
return {
inAmount: data.inAmount,
otherAmountThreshold: data.otherAmountThreshold,
quoteResponse: data,
};
};
// Step 2: Fetch swap transaction from Jupiter
const fetchSwapTransaction = async (
walletAddress: PublicKey | null,
recipientAddress: string,
swapInfo: any
) => {
if (!walletAddress || !recipientAddress || !swapInfo?.quoteResponse) {
throw new Error('Invalid parameters: Ensure walletAddress, recipientAddress, and swapInfo are defined.');
}
const requestBody = {
userPublicKey: walletAddress.toBase58(),
destinationTokenAccount: recipientAddress,
useSharedAccounts: true,
quoteResponse: swapInfo.quoteResponse,
skipUserAccountsRpcCalls: true,
};
const response = await fetch(JUPITER_SWAP_API, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestBody),
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Error fetching swap transaction: ${errorText}`);
}
const { swapTransaction, lastValidBlockHeight } = await response.json();
return { swapTransaction, lastValidBlockHeight };
};
// Step 3: Send transaction to Solana blockchain
const sendTransaction = async (swapTransaction: string, walletAdapter: WalletAdapter) => {
const versionedMessage = VersionedMessage.deserialize(Buffer.from(swapTransaction, 'base64'));
const transaction = new VersionedTransaction(versionedMessage);
const bhInfo = await connection.getLatestBlockhashAndContext({ commitment: "finalized" });
transaction.recentBlockhash = bhInfo.value.blockhash;
transaction.feePayer = walletAdapter.publicKey;
console.log(transaction);
const signedTransaction = await (walletAdapter as any).signTransaction(transaction);
const simulation = await connection.simulateTransaction(transaction, { commitment: "finalized" });
if (simulation.value.err) {
throw new Error(`Simulation failed: ${simulation.value.err.toString()}`);
}
// Send the transaction
try {
const signature = await connection.sendTransaction(transaction, {
// NOTE: Adjusting maxRetries to a lower value for trading, as 20 retries can be too much
// Experiment with different maxRetries values based on your tolerance for slippage and speed
// Reference: https://solana.com/docs/core/transactions#retrying-transactions
maxRetries: 5,
skipPreflight: true,
preflightCommitment: "finalized",
});
// Confirm the transaction
// Using 'finalized' commitment to ensure the transaction is fully confirmed
// Reference: https://solana.com/docs/core/transactions#confirmation
const confirmation = await connection.confirmTransaction({
signature,
blockhash: bhInfo.value.blockhash,
lastValidBlockHeight: bhInfo.value.lastValidBlockHeight,
}, "finalized");
if (confirmation.value.err) {
throw new Error(`Transaction not confirmed: ${confirmation.value.err.toString()}`);
}
console.log("Confirmed: ", signature);
} catch (error) {
console.error("Failed: ", error);
throw error;
}
};
// Step 4: Main function to swap and send token
const swapAndSendToken = async (
walletAdapter: WalletAdapter,
recipientAddress: string,
inputMint: string,
outputMint: string,
amount: number
) => {
try {
const walletPublicKey = walletAdapter.publicKey;
// Step 1: Fetch swap info
const swapInfo = await fetchSwapInfo(inputMint, outputMint, amount);
// Step 2: Fetch the swap transaction
const { swapTransaction, lastValidBlockHeight } = await fetchSwapTransaction(walletPublicKey, recipientAddress, swapInfo);
console.log(swapTransaction);
// Step 3: Send the transaction to the blockchain
await sendTransaction(swapTransaction, walletAdapter);
alert("USDC sent successfully!");
console.log('Swap and send transaction completed successfully.');
} catch (error) {
console.error('Error during swap and send:', error);
//alert("Failed! " + error.message);
}
};
const payCoin = async () => {
const wallets = [
new PhantomWalletAdapter(),
new SolflareWalletAdapter(),
new TrustWalletAdapter(),
];
if(connectedWalletIndex == null) return;
const wallet = wallets[connectedWalletIndex];
try {
await wallet.connect();
if(wallet.publicKey == null) return;
console.log("Connected to wallet:", wallet.publicKey.toString());
const publicKey = wallet.publicKey;
await swapAndSendToken(
wallet,
"ANJt85VAVGhknPAhKBaS2qWVZUWW59rkQSbAg4sW4dFA", // Merchant's USDC address
"Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", // Input mint address
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // Output mint address
0.1 * 1000000 // Example: 0.1 USDC in micro-lamports
);
} catch (error) {
console.error("Failed to connect to wallet:", error);
}
}
这是我实现的代码。
我要与目的地地址交换。 我从https://station.jup.ag/api-v6/post-swap-instructions看到了destinationTokenAccount 是否可以直接从客户帐户转换到商户地址? 我已经尝试过但没有成功。任何人都可以帮助我吗? https://solscan.io/tx/37GAcwzCfEbydZknATZXRMjDEzMPKV5b3TF3VtM2JUD5y6cKoKWipQD5qfpB2MLtmkDsLgVhzyWrU5kdHRi9HRqh 这是失败的交易。
对于“destinationTokenAccount”,请检查您的属性“recipientAddress”。必须是Token账户。这不是存款的钱包地址。您可以使用 RPC 方法 getTokenAccountsByOwner (@solana/web3.js) 或 getAssociatedTokenAddressSync (@solana/spl-token) 来获取它