Jupiter Swap API와 Helius Sender 사용하기
Helius Sender는 낮은 지연 시간으로 Solana 거래를 전송하는 서비스로, 모든 경로(Helius, Jito, Harmonic, Rakurai 등)를 통해 거래를 전송하여 포함 속도와 성공률을 최대화합니다. Jupiter의 Swap API는 가장 가격 효율적인 스왑 경로를 찾고, 사용 가능한 거래를 생성합니다. 이 두 가지 도구를 결합하면 거래자는 경쟁보다 먼저 거래 기회를 포착하고 스왑 성공 가능성을 높일 수 있습니다.Sender는 공개적으로 사용 가능합니다 — 계획이 필요하지 않습니다.
작동 방식
- 거래 쌍에 대한 Jupiter 견적 받기
- Jupiter의 Swap API를 사용하여 스왑 거래 생성
- Sender 호환성에 맞게 수정
- Helius Sender를 통해 최대 성공률로 전송
요구 사항
- Node.js ≥ 20 (v20.9.0으로 테스트됨)
- TypeScript ≥ 5
- RPC 액세스를 위한 Helius 계정 (무료 또는 유료)
- 거래 수수료 및 팁에 충분한 SOL이 있는 Solana 지갑
전역으로 의존성 설치:
npm i -g typescript구현
1
환경 설정
npx tsc --init
npm install @solana/web3.js bs58
npm install --save-dev @types/node
"types": ["node"]를 tsconfig.json에 설정"type": "module"를 package.json에 설정2
Jupiter Swap Client 생성
다음 코드로
jupiter-swap-sender.ts라는 파일 생성:import {
Keypair,
VersionedTransaction,
Connection,
TransactionMessage,
AddressLookupTableAccount,
SystemProgram,
PublicKey,
LAMPORTS_PER_SOL
} from '@solana/web3.js';
import bs58 from 'bs58';
const PRIV_B58 = 'Your private key in base58';
const HELIUS_API_KEY = 'Your Helius API key';
const SENDER_ENDPOINT = 'http://ewr-sender.helius-rpc.com/fast';
const SWAP_AMOUNT = 1000000; // 0.001 SOL
const SWAP_FROM_TOKEN = "So11111111111111111111111111111111111111112";
const SWAP_TO_TOKEN = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
const SWAP_SLIPPAGE_BPS = 50;
const TIP_ACCOUNTS = [
"4ACfpUFoaSD9bfPdeu6DBt89gB6ENTeHBXCAi87NhDEE",
"D2L6yPZ2FmmmTKPgzaMKdhu6EWZcTpLy1Vhx8uvZe7NZ",
"9bnz4RShgq1hAnLnZbP8kbgBg1kEmcJBYQq3gQbmnSta",
"5VY91ws6B2hMmBFRsXkoAAdsPHBJwRfBht4DXox3xkwn",
"2nyhqdwKcJZR2vcqCyrYsaPVdAnFoJjiksCXJ7hfEYgD",
"2q5pghRs6arqVjRvT5gfgWfWcHWmw1ZuCzphgd5KfWGJ",
"wyvPkWjVZz1M8fHQnMMCDTQDbkManefNNhweYk5WkcF",
"3KCKozbAaF75qEU33jtzozcJ29yJuaLJTy2jFdzUY8bT",
"4vieeGHPYPG2MmyPRcYjdiDmmhN3ww7hsFNap8pVN3Ey",
"4TQLFNWK8AovT1gFvda5jfw2oJeRMKEmw7aH6MGBJ3or"
];
// Use the Jupiter API to get a quote
// https://dev.jup.ag/docs/api/swap-api/quote
async function getQuote(inputMint: string, outputMint: string, amount: number, slippageBps: number) {
console.log("Request Jupiter quote");
const url = `https://lite-api.jup.ag/swap/v1/quote?inputMint=${inputMint}&outputMint=${outputMint}&amount=${amount}&slippageBps=${slippageBps}`
const response = (await fetch(url)).json();
return response
}
// Use the Jupiter API to get a swap transaction, based on the quote response
// https://dev.jup.ag/docs/api/swap-api/swap
async function getSwap(quote: any) {
console.log("Request Jupiter swap");
const user_wallet = Keypair.fromSecretKey(bs58.decode(PRIV_B58));
const url = "https://lite-api.jup.ag/swap/v1/swap"
const args = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
quoteResponse: quote,
userPublicKey: user_wallet.publicKey,
dynamicComputeUnitLimit: true,
prioritizationFeeLamports: {
priorityLevelWithMaxLamports: {
maxLamports: 1000000,
priorityLevel: "veryHigh"
}
}
})
}
const response = (await fetch(url, args)).json();
return response;
}
async function createSenderTransactionFromSwapResponse(swapResponse: any) {
console.log("Create transaction for Sender");
// Deserialize the Jupiter transaction
const transactionBase64 = swapResponse.swapTransaction
const jupiterTransaction = VersionedTransaction.deserialize(Buffer.from(transactionBase64, 'base64'));
// Get the Address Lookup Tables
const connection = new Connection(
'https://mainnet.helius-rpc.com/?api-key=' + HELIUS_API_KEY
);
let altAccountResponses = await Promise.all(
jupiterTransaction.message.addressTableLookups.map(l => connection.getAddressLookupTable(l.accountKey))
);
let altAccounts: AddressLookupTableAccount[] = altAccountResponses.map(item => {
if (item.value == null) throw new Error("ALT is null");
return item.value;
});
// Use the Address Lookup Tables to decompile the transaction
let decompiledMessage = TransactionMessage.decompile(jupiterTransaction.message, {
addressLookupTableAccounts: altAccounts,
});
// Note that Jupiter has already added the Compute Budget instructions
// Nothing needs to be done here
// Add a tip instruction
const user_wallet = Keypair.fromSecretKey(bs58.decode(PRIV_B58));
const transferIx = SystemProgram.transfer({
fromPubkey: user_wallet.publicKey,
toPubkey: new PublicKey(TIP_ACCOUNTS[Math.floor(Math.random() * TIP_ACCOUNTS.length)]!),
lamports: 0.001 * LAMPORTS_PER_SOL,
})
decompiledMessage.instructions.push(transferIx);
// Compile the full transaction
const transaction = new VersionedTransaction(decompiledMessage.compileToV0Message(altAccounts));
// Sign the transaction
transaction.sign([user_wallet]);
return transaction;
}
async function broadcastTransactionWithSender(transaction: VersionedTransaction) {
console.log("Send to Sender");
const connection = new Connection(
'https://mainnet.helius-rpc.com/?api-key=' + HELIUS_API_KEY
);
const response = await fetch(SENDER_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: Date.now().toString(),
method: 'sendTransaction',
params: [
Buffer.from(transaction.serialize()).toString('base64'),
{
encoding: 'base64',
skipPreflight: true, // Optional: skip for lower latency
maxRetries: 0
}
]
})
});
const json = await response.json();
if (json.error) {
throw new Error(json.error.message);
}
console.log("Sender Response:");
console.log(json);
console.log("Wait for confirmation");
const {blockhash, lastValidBlockHeight} = await connection.getLatestBlockhash();
const result = await connection.confirmTransaction({
blockhash,
lastValidBlockHeight,
signature: bs58.encode(transaction.signatures[0]!)
}, 'confirmed');
console.log("Confirmed");
}
async function main() {
const amount = SWAP_AMOUNT.toString();
const quote = await getQuote(SWAP_FROM_TOKEN, SWAP_TO_TOKEN, SWAP_AMOUNT, SWAP_SLIPPAGE_BPS);
const swap = await getSwap(quote);
const senderTransaction = await createSenderTransactionFromSwapResponse(swap);
console.log("Signature:", bs58.encode(senderTransaction.signatures[0]!));
await broadcastTransactionWithSender(senderTransaction);
}
main().catch(console.error);
3
구성
하드코딩된 API 키와 개인 키를 자격 증명으로 교체하세요. 스왑에 대한 올바른 매개변수: 토큰 주소, 금액, 슬리피지를 설정합니다. 서버와 가장 가까운 Sender 엔드포인트를 선택하세요.
4
애플리케이션 실행
Helius Sender를 통해 Jupiter 스왑을 실행하려면 스크립트를 실행하세요:
npx tsx jupiter-swap-sender.ts
샘플 출력
Request Jupiter quote
Request Jupiter swap
Create transaction for Sender
Signature: 2weWhhYyGA9xPqFaXVfR9FdBDAjM3AEbebYzEER2bLQn6JJ7tJ8wwtncbvD9qi2xFJuDxHdDGQWQWQ7m1cUCg74S
Send to Sender
Sender Response:
{
jsonrpc: '2.0',
id: '1758913856910',
result: '2weWhhYyGA9xPqFaXVfR9FdBDAjM3AEbebYzEER2bLQn6JJ7tJ8wwtncbvD9qi2xFJuDxHdDGQWQWQ7m1cUCg74S'
}
Wait for confirmation
Confirmed