UNPKG

@lifi/sdk

Version:

LI.FI Any-to-Any Cross-Chain-Swap SDK

139 lines 4.46 kB
import { Connection } from '@solana/web3.js'; import { uint8ArrayToBase64 } from '../../../utils/uint8ArrayToBase64.js'; import { JITO_TIP_ACCOUNTS } from './constants.js'; /** * Makes a direct RPC request to an endpoint * */ async function rpcRequest(endpoint, method, params) { const response = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params, }), }); if (!response.ok) { throw new Error(`Jito RPC Error: ${response.status} ${response.statusText}`); } const data = await response.json(); if (data.error) { throw new Error(`Jito RPC Error: ${data.error.message}`); } return data.result; } /** * Extended Connection class with Jito bundle support * Adds simulateBundle, sendBundle, and getTipAccounts methods */ export class JitoConnection extends Connection { tipAccountsCache = null; /** * Check if an RPC endpoint supports Jito bundles * @param rpcUrl - The RPC endpoint URL to check * @returns true if the endpoint supports Jito bundle methods */ static async isJitoRpc(rpcUrl) { try { // method exists if the request is successfull and doesn't throw an error await rpcRequest(rpcUrl, 'getTipAccounts', []); return true; } catch { return false; } } /** * Makes a direct RPC request to the Jito-enabled endpoint */ async rpcRequest(method, params) { try { return await rpcRequest(this.rpcEndpoint, method, params); } catch (error) { console.error(`Jito RPC request failed: ${method}`, { endpoint: this.rpcEndpoint, params, error, }); throw error; } } /** * Serialize a transaction to base64 for RPC submission */ serializeTransaction(transaction) { return uint8ArrayToBase64(transaction.serialize()); } /** * Get the tip accounts from the Jito endpoint, using fallbacks if results are empty * Results are cached to avoid repeated RPC calls */ async getTipAccounts() { if (this.tipAccountsCache) { return this.tipAccountsCache; } try { const accounts = await this.rpcRequest('getTipAccounts', []); if (!accounts.length) { throw new Error('RPC has no tip accounts'); } this.tipAccountsCache = accounts; return accounts; } catch (error) { const fallbackAccounts = JITO_TIP_ACCOUNTS; console.warn(`Failed to fetch tip accounts from RPC, using fallback`, error); return fallbackAccounts; } } /** * Get a random Jito tip account to reduce contention */ async getRandomTipAccount() { const accounts = await this.getTipAccounts(); return accounts[Math.floor(Math.random() * accounts.length)]; } /** * Manually refresh the tip accounts cache * Useful for long-running processes that may need updated tip accounts */ async refreshTipAccounts() { this.tipAccountsCache = null; return this.getTipAccounts(); } /** * Simulate a bundle before sending it * @param bundle - Array of signed transactions * @returns Simulation result */ async simulateBundle(bundle) { const encodedTransactions = bundle.map((tx) => this.serializeTransaction(tx)); return this.rpcRequest('simulateBundle', [ { encodedTransactions }, ]); } /** * Send a bundle to the Jito block engine * @param bundle - Array of signed transactions * @returns Bundle UUID */ async sendBundle(bundle) { const encodedTransactions = bundle.map((tx) => this.serializeTransaction(tx)); return this.rpcRequest('sendBundle', [encodedTransactions]); } /** * Get the status of submitted bundles * @param bundleIds - Array of bundle UUIDs to check * @returns Bundle status information */ async getBundleStatuses(bundleIds) { return this.rpcRequest('getBundleStatuses', [bundleIds]); } } //# sourceMappingURL=JitoConnection.js.map