package pump_parser import ( "encoding/json" "os" "path/filepath" "sort" "strings" "testing" "github.com/gagliardetto/solana-go/rpc" ) func TestTxBinaryRealFixtureSizes(t *testing.T) { fixtures, err := filepath.Glob(filepath.Join("testdata", "rpc", "*.json")) if err != nil { t.Fatalf("glob fixtures: %v", err) } if len(fixtures) == 0 { t.Fatal("no rpc fixtures found") } sort.Strings(fixtures) type sizeResult struct { name string swaps int platforms int mevAgents int addresses int encodedBytes int fixtureBytes int txBinaryBytes int } results := make([]sizeResult, 0, len(fixtures)) totalEncoded := 0 for _, fixture := range fixtures { tx, rawTxBytesLen, fixtureBytesLen := mustParseRPCFixtureTxForBinarySize(t, fixture) binaryTx, err := NewTxBinary(tx) if err != nil { t.Fatalf("build tx binary fixture %s: %v", fixture, err) } encoded, err := binaryTx.MarshalBinary() if err != nil { t.Fatalf("encode fixture %s: %v", fixture, err) } result := sizeResult{ name: strings.TrimSuffix(filepath.Base(fixture), filepath.Ext(fixture)), swaps: len(tx.Swaps), platforms: len(tx.Platform), mevAgents: len(tx.MevAgent), addresses: len(binaryTx.AddressTable), encodedBytes: len(encoded), fixtureBytes: fixtureBytesLen, txBinaryBytes: rawTxBytesLen, } results = append(results, result) totalEncoded += result.encodedBytes } for _, result := range results { t.Logf( "%s encoded=%dB swaps=%d platforms=%d mev=%d addresses=%d fixture_json=%dB raw_tx=%dB", result.name, result.encodedBytes, result.swaps, result.platforms, result.mevAgents, result.addresses, result.fixtureBytes, result.txBinaryBytes, ) } minResult := results[0] maxResult := results[0] for _, result := range results[1:] { if result.encodedBytes < minResult.encodedBytes { minResult = result } if result.encodedBytes > maxResult.encodedBytes { maxResult = result } } t.Logf( "summary fixtures=%d avg=%dB min=%dB(%s) max=%dB(%s)", len(results), totalEncoded/len(results), minResult.encodedBytes, minResult.name, maxResult.encodedBytes, maxResult.name, ) } func mustParseRPCFixtureTxForBinarySize(t *testing.T, fixturePath string) (*Tx, int, int) { t.Helper() raw, err := os.ReadFile(fixturePath) if err != nil { t.Fatalf("read fixture %s: %v", fixturePath, err) } var response struct { Result *rpc.GetTransactionResult `json:"result"` } if err := json.Unmarshal(raw, &response); err != nil { t.Fatalf("unmarshal fixture %s: %v", fixturePath, err) } if response.Result == nil || response.Result.Transaction == nil || response.Result.Meta == nil { t.Fatalf("fixture %s is missing transaction data", fixturePath) } rawBinary := response.Result.Transaction.GetBinary() if len(rawBinary) == 0 { t.Fatalf("fixture %s has empty transaction bytes", fixturePath) } txWithMeta := rpc.TransactionWithMeta{ Slot: response.Result.Slot, BlockTime: response.Result.BlockTime, Transaction: rpc.DataBytesOrJSONFromBytes(rawBinary), Meta: response.Result.Meta, Version: response.Result.Version, } var blockTime *uint64 if response.Result.BlockTime != nil { bt := uint64(*response.Result.BlockTime) blockTime = &bt } rawTx, err := FromRpcTransactionWithMeta(txWithMeta, blockTime, response.Result.Slot, 0) if err != nil { t.Fatalf("convert fixture %s: %v", fixturePath, err) } tx, err := ParseRawTx(rawTx) if err != nil { t.Fatalf("parse fixture %s: %v", fixturePath, err) } return tx, len(rawBinary), len(raw) }