ShredParser¶
ShredParser decodes DEX instructions from their arguments, without relying on execution results. It is meant for data that arrives before execution, where DexParser has nothing to work with.
Input sources¶
| Source | What the transaction contains | What ShredParser sees |
|---|---|---|
Jito ShredStream entries (DecodeShredEntries), any transaction without meta | message only, no meta | outer instructions only: CPI calls made by bots, routers and aggregators are invisible |
Yellowstone gRPC transaction updates (ConvertGeyserTransaction), RPC results | executed transaction with meta | outer and inner instructions; DexParser gives the executed amounts for the same data |
DecodeShredEntries decodes the entries bytes of a ShredStream Entry message (a bincode Vec<Entry>) into transactions (legacy, v0 and v1). They have no meta and Slot 0: set it from Entry.slot. A malformed transaction stops decoding; the transactions before it are returned with the error.
// data is Entry.entries of a SubscribeEntries message, slot is Entry.slot
var data []byte
var slot uint64
txs, err := dexparser.DecodeShredEntries(data)
if err != nil {
log.Println("partial entry:", err)
}
for _, tx := range txs {
tx.Slot = slot
result := shredParser.ParseAll(tx, nil)
for _, ins := range result.ParsedInstructions {
fmt.Println(result.Signature, ins.Idx, ins.ProgramName, ins.Action)
}
}
Example¶
tx := loadTransaction(txFile)
// Pre-execution sources (e.g. Jito ShredStream, see DecodeShredEntries)
// deliver no meta; drop it to see what ShredParser gets from them.
tx.Meta = nil
result := dexparser.NewShredParser().ParseAll(tx, nil)
fmt.Println("status:", result.TxStatus)
for _, ins := range result.ParsedInstructions {
fmt.Printf("%s %s %s", ins.Idx, ins.ProgramName, ins.Action)
if t := ins.Trade; t != nil {
fmt.Printf(": %s %s (%s) -> %s (%s)", t.Type,
t.InputToken.AmountRaw, ins.InputAmountKind,
t.OutputToken.AmountRaw, ins.OutputAmountKind)
}
fmt.Println()
}
Output:
status: unknown
1 System transfer
3 Pumpfun create
5 Pumpfun buy: BUY 2020000000 (max) -> 67062499999999 (exact)
The buy asks for exactly 67062499999999 tokens and allows at most 2020000000 lamports. DexParser reports what the buyer paid in the same transaction: 2020000000, that is 2000000000 into the bonding curve plus the 1% fee of 20000000 transferred to the fee recipient CebN5WGQ…, which is the trade's Fee. loadTransaction stands for the file reading of the Quick Start; tx is the Pump.fun create + buy 4Cod1cNG….
Result¶
types.ParseShredResult:
| Field | Content |
|---|---|
ParsedInstructions | typed instructions of every program, in execution order |
Instructions | the older per-program format: program name ("Pumpfun", "Jupiter", "System", "Token", …) -> decoded events, each program's in execution order. Programs without decoded instructions are left out |
TxStatus | unknown without meta, else success or failed |
HasUnresolvedAccounts | some lookup-table accounts could not be resolved |
Warnings | why the result may be incomplete: ALTsFetcher / TokenAccountsFetcher errors and unresolved lookup-table accounts |
State, Msg, Signature, Slot, Timestamp, Signer | as in ParseResult |
types.ParsedShredInstruction has ProgramID, ProgramName, Action (the instruction name), Idx, Accounts, Data (the decoded arguments) and one of Trade, Liquidity, Transfer or MemeEvent.
Semantics¶
- Amounts are instruction arguments, often slippage limits.
InputAmountKindandOutputAmountKindtell what the trade's (or meme event's) amounts mean:
| Kind | Meaning |
|---|---|
exact | the exact amount sent or received |
max | a slippage limit: the most the user may send |
min | a slippage limit: the least the user accepts |
quote | the router's expected amount; the limit follows from SlippageBps |
unknown | known only after execution; reported as 0 |
- Mints are never guessed. A mint the transaction does not reveal is
"", with decimals 0. - Decimals come from the transaction's token balances or
constants.TOKEN_DECIMALS, else 0 (unknown). Pump.fun bonding-curve tokens always have 6. - Trade type is
SWAPwhen the direction cannot be determined: for Jupiter and DFlow routes whenever a mint is unknown or both are the same (circular arbitrage). Raydium V4 trades with one known mint areBUYfor WSOL in andSELLfor WSOL out. PumpSwap trades follow the SOL/stablecoin rule too, not the instruction name: abuyin a pool whose base is WSOL and whose quote is a token isSELL. - Lookup tables: v0 accounts resolve from
meta.loadedAddresses,ParseConfig.AddressLookupTablesor anALTsFetcher(see Getting Started). Unresolved accounts are"", andUnresolvedAccountsis set on the instruction (andunresolvedAccountson the older events). - Failed transactions (meta.err set) give no instructions and
Msg="transaction failed"unlessIncludeFailedTxsis set. - Idx is
"N"for outer and"N-M"for inner instructions. - A nil config means
TryUnknownDEXon;ProgramIdsandIgnoreProgramIdsselect programs.ShredParser.ParseAllnever returns nil.
Protocols¶
| Protocol | Decoded instructions | Typed output |
|---|---|---|
| Pump.fun | buy, sell, buy_exact_sol_in, buy_v2, sell_v2, buy_exact_quote_in_v2, create, create_v2, migrate, migrate_v2 | Trade + MemeEvent; MemeEvent for create and migrate |
| PumpSwap | buy, sell, buy_exact_quote_in, create_pool, deposit, withdraw | Trade; PoolEvent |
| Jupiter v6 | route, route_with_token_ledger, exact_out_route, the shared_accounts_* routes and the *_v2 routes | Trade (ExactOut, PlatformFeeBps, slippage in Data) |
| Raydium V4 | swap (tags 9, 11, 16, 17), initialize2, deposit, withdraw | Trade; PoolEvent |
| Raydium LaunchLab | buy/sell exact in and out, initialize (v2, Token-2022), migrate_to_amm, migrate_to_cpswap | MemeEvent |
| Meteora DBC | swap, swap2 (with transfer hook), pool initializers, DAMM migrations | MemeEvent |
| DFlow | swap, swap2 and their _with_destination and _native forms | Trade |
| Photon | Pump.fun (v1, v2), PumpSwap and Moonit swaps, hop_two_swap, collect_fee | Trade |
| System, Token, Token-2022 | transfers | Transfer |
gRPC input¶
Yellowstone gRPC updates are executed transactions: convert them with ConvertGeyserTransaction (see Getting Started). For them DexParser gives executed amounts; ShredParser is useful when you want the signed limits. An update without meta (YellowstoneTransaction.NoMeta, deshred transactions) converts to a transaction without meta, as ShredParser expects for pre-execution input.