Skip to content

Instantly share code, notes, and snippets.

@zhe-t
Last active January 9, 2025 17:15
Show Gist options
  • Save zhe-t/60938c69e29276b7a9f098e1b0672c79 to your computer and use it in GitHub Desktop.
Save zhe-t/60938c69e29276b7a9f098e1b0672c79 to your computer and use it in GitHub Desktop.
Smart send a transaction using Jito dedicated endpoint
import { Connection, SendOptions } from '@solana/web3.js';
export type JitoRegion = 'mainnet' | 'amsterdam' | 'frankfurt' | 'ny' | 'tokyo';
export const JitoEndpoints = {
mainnet: 'https://mainnet.block-engine.jito.wtf/api/v1/transactions',
amsterdam: 'https://amsterdam.mainnet.block-engine.jito.wtf/api/v1/transactions',
frankfurt: 'https://frankfurt.mainnet.block-engine.jito.wtf/api/v1/transactions',
ny: 'https://ny.mainnet.block-engine.jito.wtf/api/v1/transactions',
tokyo: 'https://tokyo.mainnet.block-engine.jito.wtf/api/v1/transactions',
};
export function getJitoEndpoint(region: JitoRegion) {
return JitoEndpoints[region];
}
/**
* Send a transaction using Jito. This only supports sending a single transaction on mainnet only.
* See https://jito-labs.gitbook.io/mev/searcher-resources/json-rpc-api-reference/transactions-endpoint/sendtransaction.
* @param args.serialisedTx - A single transaction to be sent, in serialised form
* @param args.region - The region of the Jito endpoint to use
*/
export async function sendTxUsingJito({
serializedTx,
region = 'mainnet'
}: {
serializedTx: Uint8Array | Buffer | number[];
region: JitoRegion;
}) {
let rpcEndpoint = getJitoEndpoint(region);
let encodedTx = bs58.encode(serializedTx);
let payload = {
jsonrpc: "2.0",
id: 1,
method: "sendTransaction",
params: [encodedTx]
};
let res = await fetch(`${rpcEndpoint}?bundleOnly=true`, {
method: 'POST',
body: JSON.stringify(payload),
headers: { 'Content-Type': 'application/json' }
});
let json = await res.json();
if (json.error) {
throw new Error(json.error.message);
}
return json;
}
@HIOXOIH
Copy link

HIOXOIH commented Nov 3, 2024

I am getting this issue

Error: 7 PERMISSION_DENIED: The supplied pubkey is not authorized to generate a token.

configurations I am using BLOCK_ENGINE_URL=block-engine.mainnet.frankfurt.jito.wtf AUTH_KEYPAIR_PATH=/home/xyz/wallet/keypair1.json BUNDLE_TRANSACTION_LIMIT=5 RPC_URL=my_own_rpc While using sendBundle on mainnet

` const sendBundle = async ( c: SearcherClient, instructions1:TransactionInstruction[], instructions2:TransactionInstruction[], bundleTransactionLimit: number, keypair: Keypair, conn:Connection )=>{ const _tipAccount = ( await c.getTipAccounts())[0]; console.log("tipAccount: ",_tipAccount);

const tipAccount = new PublicKey(_tipAccount);
const balance  = await conn.getBalance(keypair.publicKey);
console.log("current account has balance: ",balance);

let isLeaderSlot = false;

while(!isLeaderSlot){
    const next_leader = await c.getNextScheduledLeader();
    const num_slots = next_leader.nextLeaderSlot - next_leader.currentSlot;
    isLeaderSlot = num_slots <=2;
    console.log(`next jito leader slot in ${num_slots} slots`)
    await new Promise(r=> setTimeout(r,500));
}

const blockHash = await conn.getLatestBlockhash();
const b = new Bundle([],bundleTransactionLimit);
 
console.log(blockHash.blockhash);

const bundles = [b];

let maybeBundle = b.addTransactions(
buildMemoTransaction(keypair,instructions1,blockHash.blockhash),
buildMemoTransaction(keypair,instructions2,blockHash.blockhash)
);

if (isError(maybeBundle)){
    throw maybeBundle;
}

maybeBundle = maybeBundle.addTipTx(
    keypair,
    100_000,
    tipAccount,
    blockHash.blockhash
);

if (isError(maybeBundle)) {
    throw maybeBundle;
  }

bundles.map( async b => {
    try {
        const resp = await c.sendBundle(b);
        console.log('resp: ',resp);
    } catch (error) {
        console.error('error sending bundle:', error);

    }
});

}`

bro have you solved this? i encountered the same issue.

@youngqqcn
Copy link

jito do not need auth key now, so remove authKeypair when creating searcherClient, e.g:

update

const c = searcherClient(blockEngineUrl, authKeypair);

to

const c = searcherClient(blockEngineUrl);

@winer328
Copy link

Yes, you are exactly right.

@growwnoww
Copy link

growwnoww commented Dec 3, 2024

@youngqqcn thank you. i sent my bundle . it returns me bundleId . but after that there nothing on terminal why here is my code
export async function sendBundle(bundledTxns: VersionedTransaction[]) { try { console.log('controlled reached') const bundleId = await searcherClient.sendBundle(new JitoBundle(bundledTxns, bundledTxns.length)); console.log(Bundle ${bundleId} sent.`);

	///*
	// Assuming onBundleResult returns a Promise<BundleResult>
	const result = await new Promise((resolve, reject) => {
		searcherClient.onBundleResult(
			(result) => {
				console.log("Received bundle result:", result);
				resolve(result); // Resolve the promise with the result
			},
			(e: Error) => {
				console.error("Error receiving bundle result:", e);
				reject(e); // Reject the promise if there's an error
			}
		);
	});

	console.log("Result:", result);
	//*/
} catch (error) {
	const err = error as any;
	console.error("Error sending bundle:", err.message);

	if (err?.message?.includes("Bundle Dropped, no connected leader up soon")) {
		console.error("Error sending bundle: Bundle Dropped, no connected leader up soon.");
	} else {
		console.error("An unexpected error occurred:", err.message);
	}
}

}
`

@ankitzm
Copy link

ankitzm commented Jan 9, 2025

Did anyone got here txn success with jito using api call. How did you sent the transaction from frontend ?

@winer328
Copy link

winer328 commented Jan 9, 2025

it's same as be.

Did anyone got here txn success with jito using api call. How did you sent the transaction from frontend ?

@ankitzm
Copy link

ankitzm commented Jan 9, 2025

Sorry, I didn't understand.
sendBundle calls the api to get bundleId, but how it it send on chain from frontend ?

@winer328
Copy link

winer328 commented Jan 9, 2025

Sorry, I didn't understand. sendBundle calls the api to get bundleId, but how it it send on chain from frontend ?

we implement jito bundle with api request.
so also we can call it as api request.
Only sign tx with wallet in fe is different from be.
@Cool0328 (TG)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment