package shreder import ( "context" "encoding/hex" "os" "testing" "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" "github.com/near/borsh-go" ) func TestDecodeAxiomArgs(t *testing.T) { tests := []struct { name string hexData string }{ { name: "pump amm sell Test 0", hexData: "00686f08bb1b0000007eb4ac020000000001020200183c", }, { name: "pump amm buy Test 1", hexData: "00c09ee6050000000001c94d882600000000020200323c", }, { name: "pump buy Test 2", hexData: "00d8d3bc0000000000bb7c53f009000000000104185a", }, { name: "pump sell Test 3", hexData: "009bbf69ec08080000830bc61200000000010103a000", }, { name: "pump swap sell Test 4", hexData: "00c98ea7588b0000009adf3b010000000001020200283c", }, { name: "pump swap sell Test 5", hexData: "00d3727f9301000000f9a50b0100000000010202001e00", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { data, err := hex.DecodeString(tt.hexData) if err != nil { t.Fatalf("failed to decode hex string: %v", err) return } var args flasArgs if err := borsh.Deserialize(&args, data[1:]); err != nil { t.Fatalf("failed to decode Axiom args: %v", err) return } t.Logf("Decoded Axiom Args: %+v", args) }) } } func toUpdata(slot uint64, tx *solana.Transaction) *SubscribeUpdateTransaction { signatures := make([][]byte, len(tx.Signatures)) for i, sig := range tx.Signatures { signatures[i] = sig[:] } accountKeys := make([][]byte, len(tx.Message.AccountKeys)) for i, key := range tx.Message.AccountKeys { accountKeys[i] = key[:] } instructions := make([]*CompiledInstruction, len(tx.Message.Instructions)) for i, instr := range tx.Message.Instructions { accounts := make([]byte, len(instr.Accounts)) for j, acc := range instr.Accounts { accounts[j] = byte(acc) } instructions[i] = &CompiledInstruction{ ProgramIdIndex: uint32(instr.ProgramIDIndex), Accounts: accounts, Data: instr.Data[:], } } addressTableLookups := make([]*MessageAddressTableLookup, len(tx.Message.AddressTableLookups)) for i, lookup := range tx.Message.AddressTableLookups { writable := make([]byte, len(lookup.WritableIndexes)) for j, idx := range lookup.WritableIndexes { writable[j] = byte(idx) } readonly := make([]byte, len(lookup.ReadonlyIndexes)) for j, idx := range lookup.ReadonlyIndexes { readonly[j] = byte(idx) } addressTableLookups[i] = &MessageAddressTableLookup{ AccountKey: lookup.AccountKey[:], WritableIndexes: writable, ReadonlyIndexes: readonly, } } return &SubscribeUpdateTransaction{ Transaction: &Transaction{ Signatures: signatures, Message: &Message{ Header: &MessageHeader{ NumRequiredSignatures: uint32(tx.Message.Header.NumRequiredSignatures), NumReadonlySignedAccounts: uint32(tx.Message.Header.NumReadonlySignedAccounts), NumReadonlyUnsignedAccounts: uint32(tx.Message.Header.NumReadonlyUnsignedAccounts), }, AccountKeys: accountKeys, RecentBlockhash: nil, // TODO Instructions: instructions, Versioned: false, // TODO AddressTableLookups: addressTableLookups, }, }, Slot: slot, } } func getTransaction(t *testing.T, client *rpc.Client, signature string) *SubscribeUpdateTransaction { version := uint64(0) tx, err := client.GetTransaction( context.Background(), solana.MustSignatureFromBase58(signature), &rpc.GetTransactionOpts{ Commitment: rpc.CommitmentFinalized, MaxSupportedTransactionVersion: &version, }, ) if err != nil { t.Fatalf("failed to get transaction: %v", err) } _tx, err := tx.Transaction.GetTransaction() if err != nil { t.Fatalf("failed to get transaction: %v", err) } return toUpdata(tx.Slot, _tx) } func TestParseTermBuy(t *testing.T) { rpcUrl := os.Getenv("SOL_RPC_URL") if rpcUrl == "" { t.Fatalf("SOL_RPC_URL is not set") } client := rpc.New(rpcUrl) signals := ParseTransaction( getTransaction(t, client, "5Gz1fa4Qhb35bkg9QCMXpxCX5uuNr7WcjcmrwajGZA7kXsvNS9pDnYe12ggWeSqf1nwZbVPob6DkX6fcwbE9ofBR"), nil, false, ) if len(signals) != 1 { t.Fatalf("expected 1 signal, got %d", len(signals)) } signal := signals[0] if signal.Label != "terminal" { t.Fatalf("expected terminal signal, got %s", signal.Label) } if signal.Event != "buy" { t.Fatalf("expected buy event, got %s", signal.Event) } if signal.Maker != "BaLxyjXzATAnfm7cc5AFhWBpiwnsb71THcnofDLTWAPK" { t.Fatalf("expected maker BaLxyjXzATAnfm7cc5AFhWBpiwnsb71THcnofDLTWAPK, got %s", signal.Maker) } if signal.Token0Address != "5Wgv54peXRKDHYHapAELzgNKEPEh9E5Bf3hUR3sTpump" { t.Fatalf("expected token0 address 5Wgv54peXRKDHYHapAELzgNKEPEh9E5Bf3hUR3sTpump, got %s", signal.Token0Address) } if signal.Token0AmountUint64 != 6952026214256 { t.Fatalf("expected token0 amount 6952026214256, got %d", signal.Token0AmountUint64) } if signal.Token1AmountUint64 != 653333333 { t.Fatalf("expected token1 amount 653333333, got %d", signal.Token1AmountUint64) } } func TestParseBonkBuy(t *testing.T) { rpcUrl := os.Getenv("SOL_RPC_URL") if rpcUrl == "" { t.Fatalf("SOL_RPC_URL is not set") } client := rpc.New(rpcUrl) signals := ParseTransaction( getTransaction(t, client, "3gHF3TA2aA8rpjdmoEs2vA89vrq9J9NnTTUSXHfE6uXcaYP9cJgLtEUjCmsK9EWAyHEg7cEiepehQf4GFv1272jW"), nil, false, ) if len(signals) != 1 { t.Fatalf("expected 1 signal, got %d", len(signals)) } signal := signals[0] if signal.Label != "bonk" { t.Fatalf("expected bonk signal, got %s", signal.Label) } if signal.Event != "buy" { t.Fatalf("expected buy event, got %s", signal.Event) } if signal.Maker != "BFobdhAbdBteBuDvHUdBthsQqJyMuWnG9SGUheW1Ni2C" { t.Fatalf("expected maker BFobdhAbdBteBuDvHUdBthsQqJyMuWnG9SGUheW1Ni2C, got %s", signal.Maker) } if signal.Token0Address != "Awupo9Jxe1fsc7eEtCEcN9D3PoyReQhc9WEuEAHXpump" { t.Fatalf("expected token0 address Awupo9Jxe1fsc7eEtCEcN9D3PoyReQhc9WEuEAHXpump, got %s", signal.Token0Address) } if signal.Token0AmountUint64 != 8616799656436 { t.Fatalf("expected token0 amount 8616799656436, got %d", signal.Token0AmountUint64) } if signal.Token1AmountUint64 != 495000000 { t.Fatalf("expected token1 amount 495000000, got %d", signal.Token1AmountUint64) } } func TestParseBonkSell(t *testing.T) { rpcUrl := os.Getenv("SOL_RPC_URL") if rpcUrl == "" { t.Fatalf("SOL_RPC_URL is not set") } client := rpc.New(rpcUrl) signals := ParseTransaction( getTransaction(t, client, "3XNi6b3j69SSStqLLRQVH5BNGVfEoFxGCzmpdd5FvrY4kmC8T644WGdEhCH9fAdrxWuR2Mtzgywq8K7qetu5MGyb"), nil, false, ) if len(signals) != 1 { t.Fatalf("expected 1 signal, got %d", len(signals)) } signal := signals[0] if signal.Label != "bonk" { t.Fatalf("expected bonk signal, got %s", signal.Label) } if signal.Event != "sell" { t.Fatalf("expected sell event, got %s", signal.Event) } if signal.Maker != "2xTT7XXCEYSCrRb3G4Egc4ZwpCe78qq6r7w6ChZhbTXc" { t.Fatalf("expected maker 2xTT7XXCEYSCrRb3G4Egc4ZwpCe78qq6r7w6ChZhbTXc, got %s", signal.Maker) } if signal.Token0Address != "8pgpJDYuojYXvb8KE4Hv7DCty12FrkqpKChgfHzspump" { t.Fatalf("expected token0 address 8pgpJDYuojYXvb8KE4Hv7DCty12FrkqpKChgfHzspump, got %s", signal.Token0Address) } if signal.Token0AmountUint64 != 6235736929390 { t.Fatalf("expected token0 amount 6235736929390, got %d", signal.Token0AmountUint64) } if signal.Token1AmountUint64 != 1379707703 { t.Fatalf("expected token1 amount 1379707703, got %d", signal.Token1AmountUint64) } } func TestParsePhotonBuy(t *testing.T) { rpcUrl := os.Getenv("SOL_RPC_URL") if rpcUrl == "" { t.Fatalf("SOL_RPC_URL is not set") } client := rpc.New(rpcUrl) signals := ParseTransaction( getTransaction(t, client, "4DCEcXAWBxagXoUNGhWsJ7qfxq5SuE5BG2cBDBqAY7sCHkBopaMJu33ZnXnFHqzPMmWxVxq6666KRF4hMHVB33Ux"), nil, false, ) if len(signals) != 1 { t.Fatalf("expected 1 signal, got %d", len(signals)) } signal := signals[0] if signal.Label != "photon" { t.Fatalf("expected terminal signal, got %s", signal.Label) } if signal.Event != "buy" { t.Fatalf("expected buy event, got %s", signal.Event) } if signal.Maker != "8sUm7sLf3Steu6oVyVQqoA9GpFcMRz6YhrAidd4x7g7a" { t.Fatalf("expected maker 8sUm7sLf3Steu6oVyVQqoA9GpFcMRz6YhrAidd4x7g7a, got %s", signal.Maker) } if signal.Token0Address != "jx4PF2MwC7AK9S8dTeYm29hM3vAN8Rtfs2VX4Vz5UVj" { t.Fatalf("expected token0 address jx4PF2MwC7AK9S8dTeYm29hM3vAN8Rtfs2VX4Vz5UVj, got %s", signal.Token0Address) } if signal.Token0AmountUint64 != 1796593710706 { t.Fatalf("expected token0 amount 1796593710706, got %d", signal.Token0AmountUint64) } if signal.Token1AmountUint64 != 1955555553 { t.Fatalf("expected token1 amount 1955555553, got %d", signal.Token1AmountUint64) } }