Skip to content

Instantly share code, notes, and snippets.

@ngundotra
Last active August 14, 2025 19:14
Show Gist options
  • Save ngundotra/03545235ca3b6f9e6153a2c3c1f4a041 to your computer and use it in GitHub Desktop.
Save ngundotra/03545235ca3b6f9e6153a2c3c1f4a041 to your computer and use it in GitHub Desktop.
Surfpool-Jupiter Transaction
/**
* Jupiter Swap Test Transaction for Surfpool
* Creates a test transaction that can be executed in the Surfpool environment
* bun run surfpool-jupiter-test.ts
*/
import {
Connection,
PublicKey,
VersionedTransaction,
Keypair,
Transaction,
SystemProgram,
LAMPORTS_PER_SOL
} from '@solana/web3.js';
import { NATIVE_MINT } from '@solana/spl-token';
import bs58 from 'bs58';
// This function matches the signature expected by the skill runner
export async function executeSkill(blockhash: string): Promise<string> {
const connection = new Connection('http://localhost:8899');
const kp = Keypair.generate();
connection.requestAirdrop(kp.publicKey, 10 * LAMPORTS_PER_SOL);
// Use a test pubkey (replace with actual agent pubkey in production)
const agentPubkey = kp.publicKey;
console.log('πŸš€ Jupiter Swap - executeSkill');
console.log(' Agent:', agentPubkey.toString());
console.log(' Blockhash:', blockhash);
// Step 1: Get quote from Jupiter
const quoteResponse = await fetch(
'https://quote-api.jup.ag/v6/quote?' +
new URLSearchParams({
inputMint: NATIVE_MINT.toString(),
outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
amount: '1000000', // 0.001 SOL
slippageBps: '100' // 1% slippage
})
);
const quote = await quoteResponse.json();
if (quote.error) {
throw new Error(`Quote error: ${quote.error}`);
}
console.log('βœ… Quote received:');
console.log(' Output:', (parseInt(quote.outAmount) / 1e6).toFixed(6), 'USDC');
console.log(' Routes:', quote.routePlan?.length || 0);
// Step 2: Get swap transaction from Jupiter
const swapResponse = await fetch('https://quote-api.jup.ag/v6/swap', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
quoteResponse: quote,
userPublicKey: agentPubkey.toString(),
wrapAndUnwrapSol: true,
dynamicComputeUnitLimit: true,
prioritizationFeeLamports: 'auto'
})
});
const swapData = await swapResponse.json();
if (!swapData.swapTransaction) {
throw new Error(`Swap error: ${JSON.stringify(swapData)}`);
}
console.log('βœ… Swap transaction received');
// Step 3: Process transaction for Surfpool
const swapTxBuf = Buffer.from(swapData.swapTransaction, 'base64');
const transaction = VersionedTransaction.deserialize(swapTxBuf);
// Update blockhash for Surfpool
transaction.message.recentBlockhash = blockhash;
transaction.sign([kp]);
// Serialize and return
const serialized = Buffer.from(transaction.serialize()).toString('base64');
console.log('βœ… Transaction serialized, length:', serialized.length);
return serialized;
}
// Test function to run the skill
async function testSkill() {
console.log('\n' + '='.repeat(60));
console.log('πŸ§ͺ TESTING JUPITER SWAP SKILL FOR SURFPOOL');
console.log('='.repeat(60) + '\n');
try {
// Connect to Surfpool
const connection = new Connection('http://localhost:8899', 'confirmed');
const { blockhash } = await connection.getLatestBlockhash();
console.log('πŸ“‘ Connected to Surfpool');
console.log(' Blockhash:', blockhash, '\n');
// Execute the skill
const serializedTx = await executeSkill(blockhash);
console.log('\n' + '='.repeat(60));
console.log('βœ… SUCCESS - Transaction ready for Surfpool');
console.log('='.repeat(60));
console.log('\nSerialized transaction (base64):');
console.log(serializedTx);
// Verify transaction structure
const txBuf = Buffer.from(serializedTx, 'base64');
const tx = VersionedTransaction.deserialize(txBuf);
const simulation = await connection.simulateTransaction(tx);
const sig = await connection.sendTransaction(tx);
console.log('Signature:', sig);
// console.log('Simulation:', simulation);
console.log('\nπŸ“‹ Transaction Analysis:');
console.log(' Version:', tx.version === 0 ? 'v0' : 'Legacy');
console.log(' Blockhash matches:', tx.message.recentBlockhash === blockhash);
console.log(' Instructions:', tx.message.compiledInstructions.length);
// Check for Jupiter program
const jupiterProgram = 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4';
const hasJupiter = tx.message.staticAccountKeys.some(
key => key.toString() === jupiterProgram
);
console.log(' Has Jupiter program:', hasJupiter ? 'βœ…' : '❌');
return serializedTx;
} catch (error) {
console.error('\n❌ Test failed:', error);
throw error;
}
}
// Run test if executed directly
if (require.main === module) {
testSkill()
.then(() => {
console.log('\n✨ Test complete!');
process.exit(0);
})
.catch((err) => {
console.error('\nπŸ’₯ Fatal error:', err);
process.exit(1);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment