Last active
January 17, 2025 22:23
-
-
Save NotoriousPyro/75213c245717bad24813ab5fd96609a4 to your computer and use it in GitHub Desktop.
Jupiter IDL types and decompiling swap data
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const decodedA = await decodeSwapInstructionData<Route["Arguments"]>(swapinstA.swapInstruction.data); | |
const decodedB = await decodeSwapInstructionData<Route["Arguments"]>(swapinstB.swapInstruction.data); | |
// do whatever you want | |
const Route_AccountsStrict: Route["AccountsStrict"] = { | |
tokenProgram: TOKEN_PROGRAM_ID, | |
userTransferAuthority: keypair.publicKey, | |
userSourceTokenAccount: inputMintATA, | |
userDestinationTokenAccount: inputMintATA, | |
destinationTokenAccount: program.programId, | |
destinationMint: new PublicKey(Solana), | |
platformFeeAccount: program.programId, | |
eventAuthority: new PublicKey("D8cy77BBepLMngZx6ZukaTff5hCt1HrWyKk3Hnd9oitf"), // Does it ever change for jupiter? | |
program: program.programId, | |
} | |
const prepared = createSwapInstruction( | |
Route_AccountsStrict, | |
[...swapinstA.swapInstruction.accounts.slice(9), ...swapinstB.swapInstruction.accounts.slice(9)].map( | |
account => ({ | |
...account, | |
pubkey: new PublicKey(account.pubkey), | |
}) | |
), | |
[decodedA.routePlan, decodedB.routePlan].flat(), | |
new BN(amount.toString()), | |
new BN(amount.toString()), | |
keypair | |
) | |
const instruction = prepared.instruction; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import BN from "bn.js"; | |
import { BorshCoder } from "@coral-xyz/anchor"; | |
import { MethodsBuilder } from "@coral-xyz/anchor/dist/cjs/program/namespace/methods"; | |
import { AllInstructions, IdlTypes } from "@coral-xyz/anchor/dist/cjs/program/namespace/types"; | |
import { Keypair, PublicKey } from "@solana/web3.js"; | |
import { program } from '@jup-ag/instruction-parser' | |
export { program } from '@jup-ag/instruction-parser' | |
export const decoder = new BorshCoder(program.idl); | |
export type IDL = typeof program.idl; | |
export class DecodeInstructionError extends Error { | |
constructor(message: string) { | |
super(message); | |
this.name = "DecodeInstructionError"; | |
} | |
} | |
type _AllInstructions = AllInstructions<IDL>; | |
type _AllTypes = IdlTypes<IDL>; | |
type RemainingAccounts = Parameters<MethodsBuilder<IDL, _AllInstructions>["remainingAccounts"]>[0]; | |
type AccountsStrict = Parameters<MethodsBuilder<IDL, _AllInstructions>["accountsStrict"]>[0]; | |
export type RoutePlanStep = _AllTypes["RoutePlanStep"]; | |
export type Route = { | |
AccountsStrict: Pick<AccountsStrict, | |
"tokenProgram" | | |
"userTransferAuthority" | | |
"userSourceTokenAccount" | | |
"userDestinationTokenAccount" | | |
"destinationTokenAccount" | | |
"destinationMint" | | |
"platformFeeAccount" | | |
"eventAuthority" | | |
"program" | |
>; | |
RemainingAccounts: RemainingAccounts; | |
Arguments: { | |
routePlan: RoutePlanStep[], | |
inAmount: BN, | |
quotedOutAmount: BN, | |
slippageBps: number, | |
platformFeeBps: number, | |
} | |
} | |
export const createSwapInstruction = async ( | |
accountsStrict: Route["AccountsStrict"], | |
remainingAccounts: Route["RemainingAccounts"], | |
routePlan: Route["Arguments"]["routePlan"], | |
inAmount: Route["Arguments"]["inAmount"], | |
quotedOutAmount: Route["Arguments"]["quotedOutAmount"], | |
keypair: Keypair | |
) => ( | |
program.methods.route( | |
routePlan, | |
inAmount, // input amount | |
quotedOutAmount, // output amount | |
0, // slippage | |
0, // platform fee | |
) | |
.accountsStrict(accountsStrict) | |
.remainingAccounts(remainingAccounts) | |
.signers([keypair]) | |
).prepare(); | |
export const decodeSwapInstructionData = async <T>( | |
data: string, | |
): Promise<T> => { | |
try { | |
return decoder.instruction.decode( | |
Buffer.from(data, "base64"), | |
"base58" | |
).data as T; | |
} catch (e) { | |
if (e.message.includes("Cannot read properties of null (reading 'property')")) { | |
return Promise.reject(new DecodeInstructionError(`Failed to decode instruction data: ${data}. IDL possibly outdated.`)); | |
} | |
return Promise.reject(e); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment