From a945f3b45da992b8efc1df08cb8b82cc583ca81f Mon Sep 17 00:00:00 2001 From: thloyi Date: Thu, 20 Nov 2025 17:56:45 +0800 Subject: [PATCH] punm parser --- budget.go | 46 + checking.go | 368 +++ consts.go | 180 ++ convert.go | 1 + discriminator.go | 10 + enum.go | 106 + example/geyser/Makefile | 7 + example/geyser/cmd/main.go | 94 + example/geyser/error.go | 277 ++ example/geyser/message.go | 22 + example/geyser/proto/geyser.pb.go | 3113 +++++++++++++++++++++ example/geyser/proto/geyser.proto | 272 ++ example/geyser/proto/geyser_grpc.pb.go | 344 +++ example/geyser/proto/solana-storage.pb.go | 1547 ++++++++++ example/geyser/proto/solana-storage.proto | 149 + example/geyser/pump.go | 60 + example/geyser/yellowstone.go | 527 ++++ example/tx.go | 229 ++ globals.go | 67 + go.mod | 46 + go.sum | 344 +++ meta.go | 73 + parser.go | 97 + pump.go | 439 +++ pumpamm.go | 513 ++++ pumpamm_test.go | 41 + rawtx.go | 443 +++ system.go | 83 + tx.go | 167 ++ 29 files changed, 9665 insertions(+) create mode 100644 budget.go create mode 100644 checking.go create mode 100644 consts.go create mode 100644 convert.go create mode 100644 discriminator.go create mode 100644 enum.go create mode 100644 example/geyser/Makefile create mode 100644 example/geyser/cmd/main.go create mode 100644 example/geyser/error.go create mode 100644 example/geyser/message.go create mode 100644 example/geyser/proto/geyser.pb.go create mode 100644 example/geyser/proto/geyser.proto create mode 100644 example/geyser/proto/geyser_grpc.pb.go create mode 100644 example/geyser/proto/solana-storage.pb.go create mode 100644 example/geyser/proto/solana-storage.proto create mode 100644 example/geyser/pump.go create mode 100644 example/geyser/yellowstone.go create mode 100644 example/tx.go create mode 100644 globals.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 meta.go create mode 100644 parser.go create mode 100644 pump.go create mode 100644 pumpamm.go create mode 100644 pumpamm_test.go create mode 100644 rawtx.go create mode 100644 system.go create mode 100644 tx.go diff --git a/budget.go b/budget.go new file mode 100644 index 0000000..9c823c6 --- /dev/null +++ b/budget.go @@ -0,0 +1,46 @@ +package pump_parser + +import ( + "encoding/binary" + + "github.com/shopspring/decimal" +) + +type setComputeData struct { + Units uint64 +} + +func budgetParser(result *RawTx, instr Instruction, innerInstructions InnerInstructions, offset [2]uint, tx *Tx) ([2]uint, error) { + if offset[1] != 0 { + return increaseOffset(offset), nil + } + decode := result.Transaction.Message.Instructions[offset[0]].Data + discriminator := decode[0] + + switch discriminator { + case setComputeUnitLimitDiscriminator: + return computeUnitLimitParser(result, offset, tx, decode[1:]) + case setComputeUnitPriceDiscriminator: + return computeUnitPriceParser(result, offset, tx, decode[1:]) + default: + return increaseOffset(offset), nil + } +} + +func computeUnitLimitParser(_ *RawTx, offset [2]uint, _ *Tx, decodedData []byte) ([2]uint, error) { + if len(decodedData) < 8 { + return increaseOffset(offset), nil + } + return increaseOffset(offset), nil +} + +func computeUnitPriceParser(_ *RawTx, offset [2]uint, tx *Tx, decodedData []byte) ([2]uint, error) { + if len(decodedData) < 8 { + return increaseOffset(offset), nil + } + + cuPrice := binary.LittleEndian.Uint64(decodedData[:8]) + tx.CUPrice = decimal.NewFromInt(int64(cuPrice)).Div(decimal.NewFromInt(1000000)) // cu decimals + + return increaseOffset(offset), nil +} diff --git a/checking.go b/checking.go new file mode 100644 index 0000000..a301165 --- /dev/null +++ b/checking.go @@ -0,0 +1,368 @@ +package pump_parser + +import ( + "log" + "strings" + + "github.com/gagliardetto/solana-go" +) + +func checkBonkGmgnBuy(rawTx *RawTx) bool { + + // 检查交易版本 + var version, _ = rawTx.Version.(solana.MessageVersion) + if version != solana.MessageVersionLegacy { + return false + } + + // 检查交易指令数量 + if len(rawTx.Transaction.Message.Instructions) != 10 && len(rawTx.Transaction.Message.Instructions) != 9 { + return false + } + accountList := rawTx.getAccountList() + // 检查 cu limit + { + instruction := rawTx.Transaction.Message.Instructions[0] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.ComputeBudget { + return false + } + + if len(instruction.Accounts) != 1 { + return false + } + + accountId := accountList[instruction.Accounts[0]].String() + if !strings.HasPrefix(accountId, "jitodontfront1111111111151111111111111655") { + return false + } + } + + // 检查 cu price + { + instruction := rawTx.Transaction.Message.Instructions[1] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.ComputeBudget { + return false + } + } + + // 检查 ata.createIdempotent + { + instruction := rawTx.Transaction.Message.Instructions[2] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.SPLAssociatedTokenAccountProgramID { + return false + } + + if instruction.Data.String() != "2" { + return false + } + + if len(instruction.Accounts) < 4 { + return false + } + + // gmgn 会先创建 wsol 账户, 而不是 token 账户 + accountId := accountList[instruction.Accounts[3]] + if accountId != solana.WrappedSol { + return false + } + } + + // 检查 transfer + { + instruction := rawTx.Transaction.Message.Instructions[3] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.SystemProgramID { + return false + } + + if len(instruction.Data) == 0 || instruction.Data[0] != 2 { + return false + } + } + + // 检查 token.syncNative + { + instruction := rawTx.Transaction.Message.Instructions[4] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.TokenProgramID { + return false + } + + if instruction.Data.String() != "J" { + return false + } + } + + offset := 5 + if len(rawTx.Transaction.Message.Instructions) == 10 { + // 检查 ata.create + { + instruction := rawTx.Transaction.Message.Instructions[offset] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.SPLAssociatedTokenAccountProgramID { + return false + } + + if instruction.Data.String() != "1" { + return false + } + } + + offset++ + } + + // 检查 bonk.buy + { + instruction := rawTx.Transaction.Message.Instructions[offset] + programId := accountList[instruction.ProgramIDIndex] + if programId != raydiumLaunchLabProgramID { + return false + } + } + + offset++ + + // 检查 token.closeAccount + { + instruction := rawTx.Transaction.Message.Instructions[offset] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.TokenProgramID { + return false + } + + if instruction.Data.String() != "A" { + return false + } + } + + offset++ + + // 检查 transfer + { + instruction := rawTx.Transaction.Message.Instructions[offset] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.SystemProgramID { + return false + } + + if len(instruction.Data) == 0 || instruction.Data[0] != 2 { + return false + } + } + + offset++ + + // 检查 transfer + { + instruction := rawTx.Transaction.Message.Instructions[offset] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.SystemProgramID { + return false + } + + if len(instruction.Data) == 0 || instruction.Data[0] != 2 { + return false + } + } + + return true +} + +var ( + axiomTxLoopupTable = solana.MustPublicKeyFromBase58("7RKtfATWCe98ChuwecNq8XCzAzfoK3DtZTprFsPMGtio") +) + +func checkBonkAxiomBuy(rawTx *RawTx) bool { + + // 检查交易版本 + var version, _ = rawTx.Version.(solana.MessageVersion) + if version == solana.MessageVersionLegacy || len(rawTx.Transaction.Message.AddressTableLookups) != 1 { + log.Printf("CheckBonkAxiomBuy: Invalid transaction version or address table lookups: %v %v %v", rawTx.Transaction.Signatures[0].String(), version, len(rawTx.Transaction.Message.AddressTableLookups)) + return false + } + + // 检查 addressLookupTable 是否是 Axiom 的 + if rawTx.Transaction.Message.AddressTableLookups[0].AccountKey != axiomTxLoopupTable { + log.Printf("CheckBonkAxiomBuy: Invalid address lookup table: %v", rawTx.Transaction.Signatures[0].String()) + return false + } + + // 检查交易指令数量 + if len(rawTx.Transaction.Message.Instructions) != 10 { + return false + } + accountList := rawTx.getAccountList() + // 检查 cu limit + { + instruction := rawTx.Transaction.Message.Instructions[0] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.ComputeBudget { + log.Printf("CheckBonkAxiomBuy: Invalid program ID for ComputeBudget: %v", programId) + return false + } + + if len(instruction.Accounts) != 1 { + log.Printf("CheckBonkAxiomBuy: Invalid number of accounts for ComputeBudget: %v", len(instruction.Accounts)) + return false + } + + accountId := accountList[instruction.Accounts[0]].String() + if !strings.HasPrefix(accountId, "jitodontfront") || !strings.HasSuffix(accountId, "TradeWithAxiomDotTrade") { + log.Printf("CheckBonkAxiomBuy: Invalid account ID for ComputeBudget: %v", accountId) + return false + } + } + + // 检查 cu price + { + instruction := rawTx.Transaction.Message.Instructions[1] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.ComputeBudget { + log.Printf("CheckBonkAxiomBuy: Invalid program ID for ComputeBudget: %v", programId) + return false + } + } + + // 检查 ata.createIdempotent + { + instruction := rawTx.Transaction.Message.Instructions[2] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.SPLAssociatedTokenAccountProgramID { + log.Printf("CheckBonkAxiomBuy: Invalid program ID for SPLAssociatedTokenAccount: %v", programId) + return false + } + + if instruction.Data.String() != "2" { + log.Printf("CheckBonkAxiomBuy: Invalid data for SPLAssociatedTokenAccount: %v", instruction.Data.String()) + return false + } + + if len(instruction.Accounts) < 4 { + log.Printf("CheckBonkAxiomBuy: Invalid number of accounts for SPLAssociatedTokenAccount: %v", len(instruction.Accounts)) + return false + } + + // axiom 会先创建 token 账户, 而不是 wsol 账户 + accountId := accountList[instruction.Accounts[3]] + if accountId == solana.WrappedSol { + log.Printf("CheckBonkAxiomBuy: Invalid account ID for SPLAssociatedTokenAccount, expected token account but got wsol: %v", accountId) + return false + } + } + + // 检查 ata.createIdempotent + { + instruction := rawTx.Transaction.Message.Instructions[3] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.SPLAssociatedTokenAccountProgramID { + log.Printf("CheckBonkAxiomBuy: Invalid program ID for SPLAssociatedTokenAccount2: %v", programId) + return false + } + + if instruction.Data.String() != "2" { + log.Printf("CheckBonkAxiomBuy: Invalid data for SPLAssociatedTokenAccount2: %v", instruction.Data.String()) + return false + } + + if len(instruction.Accounts) < 4 { + log.Printf("CheckBonkAxiomBuy: Invalid number of accounts for SPLAssociatedTokenAccount2: %v", len(instruction.Accounts)) + return false + } + + // axiom 会先创建 token 账户, 而不是 wsol 账户 + accountId := accountList[instruction.Accounts[3]] + if accountId != solana.WrappedSol { + log.Printf("CheckBonkAxiomBuy: Invalid account ID for SPLAssociatedTokenAccount2, expected wsol but got: %v", accountId) + return false + } + } + + // 检查 transfer + { + instruction := rawTx.Transaction.Message.Instructions[4] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.SystemProgramID { + log.Printf("CheckBonkAxiomBuy: Invalid program ID for SystemProgram3: %v", programId) + return false + } + + if len(instruction.Data) == 0 || instruction.Data[0] != 2 { + log.Printf("CheckBonkAxiomBuy: Invalid data for SystemProgram transfer3: %v", instruction.Data) + return false + } + } + + // 检查 token.syncNative + { + instruction := rawTx.Transaction.Message.Instructions[5] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.TokenProgramID { + log.Printf("CheckBonkAxiomBuy: Invalid program ID for TokenProgram3: %v", programId) + return false + } + + if instruction.Data.String() != "J" { + log.Printf("CheckBonkAxiomBuy: Invalid data for TokenProgram syncNative3: %v", instruction.Data.String()) + return false + } + } + + // 检查 bonk.buy + { + instruction := rawTx.Transaction.Message.Instructions[6] + programId := accountList[instruction.ProgramIDIndex] + if programId != raydiumLaunchLabProgramID { + return false + } + } + + // 检查 token.closeAccount + { + instruction := rawTx.Transaction.Message.Instructions[7] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.TokenProgramID { + log.Printf("CheckBonkAxiomBuy: Invalid program ID for TokenProgram closeAccount: %v", programId) + return false + } + + if instruction.Data.String() != "A" { + log.Printf("CheckBonkAxiomBuy: Invalid data for TokenProgram closeAccount: %v", instruction.Data.String()) + return false + } + } + + // 检查 transfer + { + instruction := rawTx.Transaction.Message.Instructions[8] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.SystemProgramID { + log.Printf("CheckBonkAxiomBuy: Invalid program ID for SystemProgram transfer4: %v", programId) + return false + } + + if len(instruction.Data) == 0 || instruction.Data[0] != 2 { + log.Printf("CheckBonkAxiomBuy: Invalid data for SystemProgram transfer4: %v", instruction.Data) + return false + } + } + + // 检查 transfer + { + instruction := rawTx.Transaction.Message.Instructions[9] + programId := accountList[instruction.ProgramIDIndex] + if programId != solana.SystemProgramID { + log.Printf("CheckBonkAxiomBuy: Invalid program ID for SystemProgram transfer5: %v", programId) + return false + } + + if len(instruction.Data) == 0 || instruction.Data[0] != 2 { + log.Printf("CheckBonkAxiomBuy: Invalid data for SystemProgram transfer5: %v", instruction.Data) + return false + } + } + + return true +} diff --git a/consts.go b/consts.go new file mode 100644 index 0000000..8588971 --- /dev/null +++ b/consts.go @@ -0,0 +1,180 @@ +package pump_parser + +import "github.com/gagliardetto/solana-go" + +var platformFeeAddresses = map[solana.PublicKey]string{ + solana.MustPublicKeyFromBase58("BB5dnY55FXS1e1NXqZDwCzgdYJdMCj3B92PU6Q5Fb6DT"): PlatformGMGN, + solana.MustPublicKeyFromBase58("AVUCZyuT35YSuj4RH7fwiyPu82Djn2Hfg7y2ND2XcnZH"): PlatformPhoton, + solana.MustPublicKeyFromBase58("7LCZckF6XXGQ1hDY6HFXBKWAtiUgL9QY5vj1C4Bn1Qjj"): PlatformAxiom, + solana.MustPublicKeyFromBase58("4V65jvcDG9DSQioUVqVPiUcUY9v6sb6HKtMnsxSKEz5S"): PlatformAxiom, + solana.MustPublicKeyFromBase58("CeA3sPZfWWToFEBmw5n1Y93tnV66Vmp8LacLzsVprgxZ"): PlatformAxiom, + solana.MustPublicKeyFromBase58("AaG6of1gbj1pbDumvbSiTuJhRCRkkUNaWVxijSbWvTJW"): PlatformAxiom, + solana.MustPublicKeyFromBase58("7oi1L8U9MRu5zDz5syFahsiLUric47LzvJBQX6r827ws"): PlatformAxiom, + solana.MustPublicKeyFromBase58("9kPrgLggBJ69tx1czYAbp7fezuUmL337BsqQTKETUEhP"): PlatformAxiom, + solana.MustPublicKeyFromBase58("DKyUs1xXMDy8Z11zNsLnUg3dy9HZf6hYZidB6WodcaGy"): PlatformAxiom, + solana.MustPublicKeyFromBase58("4FobGn5ZWYquoJkxMzh2VUAWvV36xMgxQ3M7uG1pGGhd"): PlatformAxiom, + solana.MustPublicKeyFromBase58("76sxKrPtgoJHDJvxwFHqb3cAXWfRHFLe3VpKcLCAHSEf"): PlatformAxiom, + solana.MustPublicKeyFromBase58("H2cDR3EkJjtTKDQKk8SJS48du9mhsdzQhy8xJx5UMqQK"): PlatformAxiom, + solana.MustPublicKeyFromBase58("8m5GkL7nVy95G4YVUbs79z873oVKqg2afgKRmqxsiiRm"): PlatformAxiom, + solana.MustPublicKeyFromBase58("4kuG6NsAFJNwqEkac8GFDMMheCGKUPEbaRVHHyFHSwWz"): PlatformAxiom, + solana.MustPublicKeyFromBase58("8vFGAKdwpn4hk7kc1cBgfWZzpyW3MEMDATDzVZhddeQb"): PlatformAxiom, + solana.MustPublicKeyFromBase58("86Vh4XGLW2b6nvWbRyDs4ScgMXbuvRCHT7WbUT3RFxKG"): PlatformAxiom, + solana.MustPublicKeyFromBase58("DZfEurFKFtSbdWZsKSDTqpqsQgvXxmESpvRtXkAdgLwM"): PlatformAxiom, + solana.MustPublicKeyFromBase58("5L2QKqDn5ukJSWGyqR4RPvFvwnBabKWqAqMzH4heaQNB"): PlatformAxiom, + solana.MustPublicKeyFromBase58("DYVeNgXGLAhZdeLMMYnCw1nPnMxkBN7fJnNpHmizTrrF"): PlatformAxiom, + solana.MustPublicKeyFromBase58("Hbj6XdxX6eV4nfbYTseysibp4zZJtVRRPn2J3BhGRuK9"): PlatformAxiom, + solana.MustPublicKeyFromBase58("846ah7iBSu9ApuCyEhA5xpnjHHX7d4QJKetWLbwzmJZ8"): PlatformAxiom, + solana.MustPublicKeyFromBase58("5BqYhuD4q1YD3DMAYkc1FeTu9vqQVYYdfBAmkZjamyZg"): PlatformAxiom, + solana.MustPublicKeyFromBase58("G9PhF9C9H83mAjjkdJz4MDqkufiTPMJkx7TnKE1kFyCp"): PlatformPepe, + solana.MustPublicKeyFromBase58("9RYJ3qr5eU5xAooqVcbmdeusjcViL5Nkiq7Gske3tiKq"): PlatformBullX, + solana.MustPublicKeyFromBase58("F4hJ3Ee3c5UuaorKAMfELBjYCjiiLH75haZTKqTywRP3"): PlatformBullX, + solana.MustPublicKeyFromBase58("47hEzz83VFR23rLTEeVm9A7eFzjJwjvdupPPmX3cePqF"): PlatformBanana, + solana.MustPublicKeyFromBase58("9yMwSPk9mrXSN7yDHUuZurAh1sjbJsfpUqjZ7SvVtdco"): PlatformTrojan, + solana.MustPublicKeyFromBase58("4mih95RmBqfHYvEfqq6uGGLp1Fr3gVS3VNSEa3JVRfQK"): PlatformRaybot, + solana.MustPublicKeyFromBase58("3udvfL24waJcLhskRAsStNMoNUvtyXdxrWQz4hgi953N"): PlatformMoonshot, + solana.MustPublicKeyFromBase58("3kxSQybWEeQZsMuNWMRJH4TxrhwoDwfv41TNMLRzFP5A"): PlatformMEVX, + solana.MustPublicKeyFromBase58("BS3CyJ9rRC4Tp8G7f86r6hGvuu3XdrVGNVpbNM9U5WRZ"): PlatformMEVX, + solana.MustPublicKeyFromBase58("97VmzkjX9w8gMFS2RnHTSjtMEDbifGXBq9pgosFdFnM"): PlatformTradeWiz, + solana.MustPublicKeyFromBase58("F34kcgMgCF7mYWkwLN3WN7KrFprr2NbwxuLvXx4fbztj"): PlatformSolTradingBot, + solana.MustPublicKeyFromBase58("96aFQc9qyqpjMfqdUeurZVYRrrwPJG2uPV6pceu4B1yb"): PlatformSolTradingBot, + solana.MustPublicKeyFromBase58("5wkyL2FLEcyUUgc3UeGntHTAfWfzDrVuxMnaMm7792Gk"): PlatformMoonshotMoney, + solana.MustPublicKeyFromBase58("MaestroUL88UBnZr3wfoN7hqmNWFi3ZYCGqZoJJHE36"): PlatformMaestro, + solana.MustPublicKeyFromBase58("ZG98FUCjb8mJ824Gbs6RsgVmr1FhXb2oNiJHa2dwmPd"): PlatformBonkBot, +} + +var mevAgentFeeAddresses = map[solana.PublicKey]string{ + solana.MustPublicKeyFromBase58("96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5"): MevAgentJito, + solana.MustPublicKeyFromBase58("HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe"): MevAgentJito, + solana.MustPublicKeyFromBase58("Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY"): MevAgentJito, + solana.MustPublicKeyFromBase58("ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49"): MevAgentJito, + solana.MustPublicKeyFromBase58("DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh"): MevAgentJito, + solana.MustPublicKeyFromBase58("ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt"): MevAgentJito, + solana.MustPublicKeyFromBase58("DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL"): MevAgentJito, + solana.MustPublicKeyFromBase58("3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT"): MevAgentJito, + solana.MustPublicKeyFromBase58("6fQaVhYZA4w3MBSXjJ81Vf6W1EDYeUPXpgVQ6UQyU1Av"): MevAgent0slot, + solana.MustPublicKeyFromBase58("4HiwLEP2Bzqj3hM2ENxJuzhcPCdsafwiet3oGkMkuQY4"): MevAgent0slot, + solana.MustPublicKeyFromBase58("7toBU3inhmrARGngC7z6SjyP85HgGMmCTEwGNRAcYnEK"): MevAgent0slot, + solana.MustPublicKeyFromBase58("8mR3wB1nh4D6J9RUCugxUpc6ya8w38LPxZ3ZjcBhgzws"): MevAgent0slot, + solana.MustPublicKeyFromBase58("6SiVU5WEwqfFapRuYCndomztEwDjvS5xgtEof3PLEGm9"): MevAgent0slot, + solana.MustPublicKeyFromBase58("TpdxgNJBWZRL8UXF5mrEsyWxDWx9HQexA9P1eTWQ42p"): MevAgent0slot, + solana.MustPublicKeyFromBase58("D8f3WkQu6dCF33cZxuAsrKHrGsqGP2yvAHf8mX6RXnwf"): MevAgent0slot, + solana.MustPublicKeyFromBase58("GQPFicsy3P3NXxB5piJohoxACqTvWE9fKpLgdsMduoHE"): MevAgent0slot, + solana.MustPublicKeyFromBase58("Ey2JEr8hDkgN8qKJGrLf2yFjRhW7rab99HVxwi5rcvJE"): MevAgent0slot, + solana.MustPublicKeyFromBase58("4iUgjMT8q2hNZnLuhpqZ1QtiV8deFPy2ajvvjEpKKgsS"): MevAgent0slot, + solana.MustPublicKeyFromBase58("3Rz8uD83QsU8wKvZbgWAPvCNDU6Fy8TSZTMcPm3RB6zt"): MevAgent0slot, + solana.MustPublicKeyFromBase58("DiTmWENJsHQdawVUUKnUXkconcpW4Jv52TnMWhkncF6t"): MevAgent0slot, + solana.MustPublicKeyFromBase58("HRyRhQ86t3H4aAtgvHVpUJmw64BDrb61gRiKcdKUXs5c"): MevAgent0slot, + solana.MustPublicKeyFromBase58("7y4whZmw388w1ggjToDLSBLv47drw5SUXcLk6jtmwixd"): MevAgent0slot, + solana.MustPublicKeyFromBase58("J9BMEWFbCBEjtQ1fG5Lo9kouX1HfrKQxeUxetwXrifBw"): MevAgent0slot, + solana.MustPublicKeyFromBase58("8U1JPQh3mVQ4F5jwRdFTBzvNRQaYFQppHQYoH38DJGSQ"): MevAgent0slot, + solana.MustPublicKeyFromBase58("Eb2KpSC8uMt9GmzyAEm5Eb1AAAgTjRaXWFjKyFXHZxF3"): MevAgent0slot, + solana.MustPublicKeyFromBase58("FCjUJZ1qozm1e8romw216qyfQMaaWKxWsuySnumVCCNe"): MevAgent0slot, + solana.MustPublicKeyFromBase58("ENxTEjSQ1YabmUpXAdCgevnHQ9MHdLv8tzFiuiYJqa13"): MevAgent0slot, + solana.MustPublicKeyFromBase58("6rYLG55Q9RpsPGvqdPNJs4z5WTxJVatMB8zV3WJhs5EK"): MevAgent0slot, + solana.MustPublicKeyFromBase58("Cix2bHfqPcKcM233mzxbLk14kSggUUiz2A87fJtGivXr"): MevAgent0slot, + solana.MustPublicKeyFromBase58("HWEoBxYs7ssKuudEjzjmpfJVX7Dvi7wescFsVx2L5yoY"): MevAgentBlocxRoute, + solana.MustPublicKeyFromBase58("7ks326H4LbMVaUC8nW5FpC5EoAf5eK5pf4Dsx4HDQLpq"): MevAgentBlocxRoute, + solana.MustPublicKeyFromBase58("95cfoy472fcQHaw4tPGBTKpn6ZQnfEPfBgDQx6gcRmRg"): MevAgentBlocxRoute, + solana.MustPublicKeyFromBase58("6GZVKMaoWry4UFiydjeQU9nmAxj3hEARAStQ7Hc2z6TB"): MevAgentBlocxRoute, + solana.MustPublicKeyFromBase58("HZTmLyC683y74TW3HtGbNX5orxjm2sPuZBEYwwSgAM8v"): MevAgentBlocxRoute, + solana.MustPublicKeyFromBase58("FogxVNs6Mm2w9rnGL1vkARSwJxvLE8mujTv3LK8RnUhF"): MevAgentBlocxRoute, + solana.MustPublicKeyFromBase58("3UQUKjhMKaY2S6bjcQD6yHB7utcZt5bfarRCmctpRtUd"): MevAgentBlocxRoute, + solana.MustPublicKeyFromBase58("TEMPaMeCRFAS9EKF53Jd6KpHxgL47uWLcpFArU1Fanq"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("noz3jAjPiHuBPqiSPkkugaJDkJscPuRhYnSpbi8UvC4"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("noz3str9KXfpKknefHji8L1mPgimezaiUyCHYMDv1GE"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("noz6uoYCDijhu1V7cutCpwxNiSovEwLdRHPwmgCGDNo"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("noz9EPNcT7WH6Sou3sr3GGjHQYVkN3DNirpbvDkv9YJ"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("nozc5yT15LazbLTFVZzoNZCwjh3yUtW86LoUyqsBu4L"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("nozFrhfnNGoyqwVuwPAW4aaGqempx4PU6g6D9CJMv7Z"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("nozievPk7HyK1Rqy1MPJwVQ7qQg2QoJGyP71oeDwbsu"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("noznbgwYnBLDHu8wcQVCEw6kDrXkPdKkydGJGNXGvL7"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("nozNVWs5N8mgzuD3qigrCG2UoKxZttxzZ85pvAQVrbP"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("nozpEGbwx4BcGp6pvEdAh1JoC2CQGZdU6HbNP1v2p6P"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("nozrhjhkCr3zXT3BiT4WCodYCUFeQvcdUkM7MqhKqge"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("nozrwQtWhEdrA6W8dkbt9gnUaMs52PdAv5byipnadq3"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("nozUacTVWub3cL4mJmGCYjKZTnE9RbdY5AP46iQgbPJ"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("nozWCyTPppJjRuw2fpzDhhWbW355fzosWSzrrMYB1Qk"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("nozWNju6dY353eMkMqURqwQEoM3SFgEKC6psLCSfUne"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("nozxNBgWohjR75vdspfxR5H9ceC7XXH99xpxhVGt3Bb"): MevAgentNozomi, + solana.MustPublicKeyFromBase58("NextbLoCkVtMGcV47JzewQdvBpLqT9TxQFozQkN98pE"): MevAgentNextBlock, + solana.MustPublicKeyFromBase58("NexTbLoCkWykbLuB1NkjXgFWkX9oAtcoagQegygXXA2"): MevAgentNextBlock, + solana.MustPublicKeyFromBase58("NeXTBLoCKs9F1y5PJS9CKrFNNLU1keHW71rfh7KgA1X"): MevAgentNextBlock, + solana.MustPublicKeyFromBase58("NexTBLockJYZ7QD7p2byrUa6df8ndV2WSd8GkbWqfbb"): MevAgentNextBlock, + solana.MustPublicKeyFromBase58("neXtBLock1LeC67jYd1QdAa32kbVeubsfPNTJC1V5At"): MevAgentNextBlock, + solana.MustPublicKeyFromBase58("nEXTBLockYgngeRmRrjDV31mGSekVPqZoMGhQEZtPVG"): MevAgentNextBlock, + solana.MustPublicKeyFromBase58("NEXTbLoCkB51HpLBLojQfpyVAMorm3zzKg7w9NFdqid"): MevAgentNextBlock, + solana.MustPublicKeyFromBase58("nextBLoCkPMgmG8ZgJtABeScP35qLa2AMCNKntAP7Xc"): MevAgentNextBlock, + solana.MustPublicKeyFromBase58("4ACfpUFoaSD9bfPdeu6DBt89gB6ENTeHBXCAi87NhDEE"): MevAgentHelius, + solana.MustPublicKeyFromBase58("D2L6yPZ2FmmmTKPgzaMKdhu6EWZcTpLy1Vhx8uvZe7NZ"): MevAgentHelius, + solana.MustPublicKeyFromBase58("9bnz4RShgq1hAnLnZbP8kbgBg1kEmcJBYQq3gQbmnSta"): MevAgentHelius, + solana.MustPublicKeyFromBase58("5VY91ws6B2hMmBFRsXkoAAdsPHBJwRfBht4DXox3xkwn"): MevAgentHelius, + solana.MustPublicKeyFromBase58("2nyhqdwKcJZR2vcqCyrYsaPVdAnFoJjiksCXJ7hfEYgD"): MevAgentHelius, + solana.MustPublicKeyFromBase58("2q5pghRs6arqVjRvT5gfgWfWcHWmw1ZuCzphgd5KfWGJ"): MevAgentHelius, + solana.MustPublicKeyFromBase58("wyvPkWjVZz1M8fHQnMMCDTQDbkManefNNhweYk5WkcF"): MevAgentHelius, + solana.MustPublicKeyFromBase58("3KCKozbAaF75qEU33jtzozcJ29yJuaLJTy2jFdzUY8bT"): MevAgentHelius, + solana.MustPublicKeyFromBase58("4vieeGHPYPG2MmyPRcYjdiDmmhN3ww7hsFNap8pVN3Ey"): MevAgentHelius, + solana.MustPublicKeyFromBase58("4TQLFNWK8AovT1gFvda5jfw2oJeRMKEmw7aH6MGBJ3or"): MevAgentHelius, + solana.MustPublicKeyFromBase58("node1PqAa3BWWzUnTHVbw8NJHC874zn9ngAkXjgWEej"): MevAgentNode1, + solana.MustPublicKeyFromBase58("node1UzzTxAAeBTpfZkQPJXBAqixsbdth11ba1NXLBG"): MevAgentNode1, + solana.MustPublicKeyFromBase58("node1Qm1bV4fwYnCurP8otJ9s5yrkPq7SPZ5uhj3Tsv"): MevAgentNode1, + solana.MustPublicKeyFromBase58("node1PUber6SFmSQgvf2ECmXsHP5o3boRSGhvJyPMX1"): MevAgentNode1, + solana.MustPublicKeyFromBase58("node1AyMbeqiVN6eoQzEAwCA6Pk826hrdqdAHR7cdJ3"): MevAgentNode1, + solana.MustPublicKeyFromBase58("node1YtWCoTwwVYTFLfS19zquRQzYX332hs1HEuRBjC"): MevAgentNode1, + solana.MustPublicKeyFromBase58("FLasHstqx11M8W56zrSEqkCyhMCCpr6ze6Mjdvqope5s"): MevAgentFlashBlock, + solana.MustPublicKeyFromBase58("FLasHXTqrbNvpWFB6grN47HGZfK6pze9HLNTgbukfPSk"): MevAgentFlashBlock, + solana.MustPublicKeyFromBase58("FLashhsorBmM9dLpuq6qATawcpqk1Y2aqaZfkd48iT3W"): MevAgentFlashBlock, + solana.MustPublicKeyFromBase58("FLASHRzANfcAKDuQ3RXv9hbkBy4WVEKDzoAgxJ56DiE4"): MevAgentFlashBlock, + solana.MustPublicKeyFromBase58("FLAsHZTRcf3Dy1APaz6j74ebdMC6Xx4g6i9YxjyrDybR"): MevAgentFlashBlock, + solana.MustPublicKeyFromBase58("FLAshyAyBcKb39KPxSzXcepiS8iDYUhDGwJcJDPX4g2B"): MevAgentFlashBlock, + solana.MustPublicKeyFromBase58("FLaSHJNm5dWYzEgnHJWWJP5ccu128Mu61NJLxUf7mUXU"): MevAgentFlashBlock, + solana.MustPublicKeyFromBase58("FLaSHR4Vv7sttd6TyDF4yR1bJyAxRwWKbohDytEMu3wL"): MevAgentFlashBlock, + solana.MustPublicKeyFromBase58("FLaShB3iXXTWE1vu9wQsChUKq3HFtpMAhb8kAh1pf1wi"): MevAgentFlashBlock, + solana.MustPublicKeyFromBase58("FLAShWTjcweNT4NSotpjpxAkwxUr2we3eXQGhpTVzRwy"): MevAgentFlashBlock, + solana.MustPublicKeyFromBase58("FjmZZrFvhnqqb9ThCuMVnENaM3JGVuGWNyCAxRJcFpg9"): MevAgentBlockRazor, + solana.MustPublicKeyFromBase58("6No2i3aawzHsjtThw81iq1EXPJN6rh8eSJCLaYZfKDTG"): MevAgentBlockRazor, + solana.MustPublicKeyFromBase58("A9cWowVAiHe9pJfKAj3TJiN9VpbzMUq6E4kEvf5mUT22"): MevAgentBlockRazor, + solana.MustPublicKeyFromBase58("Gywj98ophM7GmkDdaWs4isqZnDdFCW7B46TXmKfvyqSm"): MevAgentBlockRazor, + solana.MustPublicKeyFromBase58("68Pwb4jS7eZATjDfhmTXgRJjCiZmw1L7Huy4HNpnxJ3o"): MevAgentBlockRazor, + solana.MustPublicKeyFromBase58("4ABhJh5rZPjv63RBJBuyWzBK3g9gWMUQdTZP2kiW31V9"): MevAgentBlockRazor, + solana.MustPublicKeyFromBase58("B2M4NG5eyZp5SBQrSdtemzk5TqVuaWGQnowGaCBt8GyM"): MevAgentBlockRazor, + solana.MustPublicKeyFromBase58("5jA59cXMKQqZAVdtopv8q3yyw9SYfiE3vUCbt7p8MfVf"): MevAgentBlockRazor, + solana.MustPublicKeyFromBase58("5YktoWygr1Bp9wiS1xtMtUki1PeYuuzuCF98tqwYxf61"): MevAgentBlockRazor, + solana.MustPublicKeyFromBase58("295Avbam4qGShBYK7E9H5Ldew4B3WyJGmgmXfiWdeeyV"): MevAgentBlockRazor, + solana.MustPublicKeyFromBase58("EDi4rSy2LZgKJX74mbLTFk4mxoTgT6F7HxxzG2HBAFyK"): MevAgentBlockRazor, + solana.MustPublicKeyFromBase58("BnGKHAC386n4Qmv9xtpBVbRaUTKixjBe3oagkPFKtoy6"): MevAgentBlockRazor, + solana.MustPublicKeyFromBase58("Dd7K2Fp7AtoN8xCghKDRmyqr5U169t48Tw5fEd3wT9mq"): MevAgentBlockRazor, + solana.MustPublicKeyFromBase58("AP6qExwrbRgBAVaehg4b5xHENX815sMabtBzUzVB4v8S"): MevAgentBlockRazor, +} + +var entryContractAddresses = map[solana.PublicKey]string{ + solana.MustPublicKeyFromBase58("pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA"): EntryContractPumpFunAMM, + solana.MustPublicKeyFromBase58("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"): EntryContractPumpFun, + solana.MustPublicKeyFromBase58("GMgnVFR8Jb39LoXsEVzb3DvBy3ywCmdmJquHUy1Lrkqb"): EntryContractGMGN, + solana.MustPublicKeyFromBase58("Axiom3a2w1UbMt2SMgqSvRiuJFTPusDhwKamNgPTeNQ9"): EntryContractAxiom, + solana.MustPublicKeyFromBase58("AxiomfHaWDemCFBLBayqnEnNwE6b7B2Qz3UmzMpgbMG6"): EntryContractAxiom, + solana.MustPublicKeyFromBase58("AxiomxSitiyXyPjKgJ9XSrdhsydtZsskZTEDam3PxKcC"): EntryContractAxiom, + solana.MustPublicKeyFromBase58("BANANAjs7FJiPQqJTGFzkZJndT9o7UmKiYYGaJz6frGu"): EntryContractBananaGun, + solana.MustPublicKeyFromBase58("MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG"): EntryContractMoonshot, + solana.MustPublicKeyFromBase58("troY36YiPGqMyAYCNbEqYCdN2tb91Zf7bHcQt7KUi61"): EntryContractTrojan, + solana.MustPublicKeyFromBase58("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"): EntryContractRaydiumAMMV4, + solana.MustPublicKeyFromBase58("routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS"): EntryContractRaydiumAMMRouting, + solana.MustPublicKeyFromBase58("CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK"): EntryContractRaydiumConcetratedLiquidity, + solana.MustPublicKeyFromBase58("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"): EntryContractRaydiumCPMM, + solana.MustPublicKeyFromBase58("LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo"): EntryContractMeteoraDLMM, + solana.MustPublicKeyFromBase58("Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB"): EntryContractMeteoraPools, + solana.MustPublicKeyFromBase58("JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"): EntryContractJupiterAggregatorV6, + solana.MustPublicKeyFromBase58("PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu"): EntryContractJupiterPerps, + solana.MustPublicKeyFromBase58("obriQD1zbpyLz95G5n7nJe6a4DPjpFwa5XYPoNm113y"): EntryContractObricV2, + solana.MustPublicKeyFromBase58("1oopBoJG58DgkUVKkEzKgyG9dvRmpgeEm1AVjoHkF78"): EntryContractLoopscale, + solana.MustPublicKeyFromBase58("fragnAis7Bp6FTsMoa6YcH8UffhEw43Ph79qAiK3iF3"): EntryContractFragmetricLiquidStaking, + solana.MustPublicKeyFromBase58("BSfD6SHZigAfDWSjzD5Q41jw8LmKwtmjskPH9XW1mrRW"): EntryContractPhoton, + solana.MustPublicKeyFromBase58("2wT8Yq49kHgDzXuPxZSaeLaH1qbmGXtEyPy64bL7aD3c"): EntryContractLfinitySwapV2, + solana.MustPublicKeyFromBase58("SoLFiHG9TfgtdUXUjWAxi3LtvYuFyDLVhBWxdMZxyCe"): EntryContractSolFi, + solana.MustPublicKeyFromBase58("NUMERUNsFCP3kuNmWZuXtm1AaQCPj9uw6Guv2Ekoi5P"): EntryContractNumeraire, + solana.MustPublicKeyFromBase58("b1oomGGqPKGD6errbyfbVMBuzSC8WtAAYo8MwNafWW1"): EntryContractBloomRouter, + solana.MustPublicKeyFromBase58("6m2CDdhRgxpH4WjvdzxAYbGxwdGUz5MziiL5jek2kBma"): EntryContractOKXAggregatorV2, + solana.MustPublicKeyFromBase58("FLUXubRmkEi2q6K3Y9kBPg9248ggaZVsoSFhtJHSrm1X"): EntryContractFluxbeamDEX, + solana.MustPublicKeyFromBase58("NoVA1TmDUqksaj2hB1nayFkPysjJbFiU76dT4qPw2wm"): EntryContractNovaBotsProgram, + solana.MustPublicKeyFromBase58("E6YoRP3adE5XYneSseLee15wJshDxCsmyD2WtLvAmfLi"): EntryContractTaggedSearcher, + solana.MustPublicKeyFromBase58("MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e"): EntryContractMayhem, +} diff --git a/convert.go b/convert.go new file mode 100644 index 0000000..4ef4d31 --- /dev/null +++ b/convert.go @@ -0,0 +1 @@ +package pump_parser diff --git a/discriminator.go b/discriminator.go new file mode 100644 index 0000000..1551763 --- /dev/null +++ b/discriminator.go @@ -0,0 +1,10 @@ +package pump_parser + +import "crypto/sha256" + +func calculateDiscriminator(instructionName string) [8]byte { + hash := sha256.Sum256([]byte(instructionName)) + var discriminator [8]byte + copy(discriminator[:], hash[:8]) + return discriminator +} diff --git a/enum.go b/enum.go new file mode 100644 index 0000000..552c95b --- /dev/null +++ b/enum.go @@ -0,0 +1,106 @@ +package pump_parser + +const ( + MevAgentJito = "jito" + MevAgent0slot = "0slot" + MevAgentBlocxRoute = "blocxroute" + MevAgentNozomi = "nozomi" + MevAgentNextBlock = "nextblock" + MevAgentHelius = "helius" + MevAgentNode1 = "node1" + MevAgentFlashBlock = "flashBlock" + MevAgentUnknown = "unknown" + MevAgentBlockRazor = "blockrazor" +) + +const ( + EntryContractPumpFunAMM = "pumpFunAMM" + EntryContractPumpFun = "pumpFun" + EntryContractGMGN = "gmgn" + EntryContractAxiom = "axiom" + EntryContractBananaGun = "bananaGun" + EntryContractMoonshot = "moonshot" + EntryContractTrojan = "trojan" + EntryContractRaydiumAMMV4 = "raydiumAMMV4" + EntryContractRaydiumAMMRouting = "raydiumAMMRouting" + EntryContractRaydiumConcetratedLiquidity = "raydiumConcetratedLiquidity" + EntryContractRaydiumCPMM = "raydiumCPMM" + EntryContractMeteoraDLMM = "meteoraDLMM" + EntryContractMeteoraPools = "meteoraPools" + EntryContractJupiterAggregatorV6 = "jupiterAggregatorV6" + EntryContractJupiterPerps = "jupiterPerps" + EntryContractObricV2 = "obricV2" + EntryContractLoopscale = "loopscale" + EntryContractFragmetricLiquidStaking = "fragmetricLiquidStaking" + EntryContractPhoton = "photon" + EntryContractLfinitySwapV2 = "lfinitySwapV2" + EntryContractSolFi = "solFi" + EntryContractNumeraire = "numeraire" + EntryContractBloomRouter = "bloomRouter" + EntryContractOKXAggregatorV2 = "oKXAggregatorV2" + EntryContractFluxbeamDEX = "fluxbeamDEX" + EntryContractNovaBotsProgram = "novaBotsProgram" + EntryContractTaggedSearcher = "taggedSearcher" + EntryContractMayhem = "pumpMayhem" + EntryContractUnknown = "unknown" +) + +const ( + PlatformGMGN = "gmgn" + PlatformPhoton = "photon" + PlatformAxiom = "axiom" + PlatformPepe = "pepe" // pepeboost & xxyy + PlatformBullX = "bullx" + PlatformBanana = "banana" + PlatformTrojan = "trojan" + PlatformRaybot = "raybot" + PlatformMoonshot = "moonshot" + PlatformMEVX = "mevx" + PlatformTradeWiz = "tradewiz" + PlatformSolTradingBot = "soltradingbot" + PlatformMoonshotMoney = "moonshot.money" + PlatformMaestro = "maestro" + PlatformBonkBot = "bonkbot" + + // used to flag transactions impersonating platform users + PlatformFake = "fake" + PlatformNone = "none" +) + +const ( + SolProgramPump = "Pump" + SolProgramRaydiumV4 = "RaydiumV4" + SolProgramRaydiumCLMM = "RaydiumCLMM" + SolProgramRaydiumCPMM = "RaydiumCPMM" + SolProgramMeteoraDLMM = "MeteoraDLMM" + SolProgramOrcaWhirPool = "OrcaWhirPool" + SolProgramPumpAMM = "PumpAMM" + SolProgramMeteoraAmmV2 = "MeteoraAmmV2" + SolProgramMeteoraBondingCurve = "MeteoraBondingCurve" + SolProgramMeteoraPools = "MeteoraPools" + SolProgramRaydiumLaunchLab = "RaydiumLaunchLab" + SolProgramRaydiumLaunchLabBonk = "RaydiumLaunchLab-Bonk" +) + +// PUMP +const ( + NewPump = "pump" + NewRaydium = "raydium" + GraduatedSoon = "graduatedsoon" +) + +func GetConditionByProgram(program string) []string { + if program == SolProgramRaydiumLaunchLabBonk { + return []string{SolProgramRaydiumLaunchLabBonk, SolProgramRaydiumV4, SolProgramRaydiumCPMM} + } + + return []string{SolProgramPump, SolProgramPumpAMM} +} + +const ( + TxEventAddLP = "add" + TxEventRemoveLP = "remove" + TxEventBuy = "buy" + TxEventSell = "sell" + TxEventBurn = "burn" +) diff --git a/example/geyser/Makefile b/example/geyser/Makefile new file mode 100644 index 0000000..572190d --- /dev/null +++ b/example/geyser/Makefile @@ -0,0 +1,7 @@ +protoc: + protoc \ + --go_out=./proto \ + --go_opt=paths=source_relative \ + --go-grpc_out=./proto \ + --go-grpc_opt=paths=source_relative \ + --proto_path ./proto/ ./proto/*.proto diff --git a/example/geyser/cmd/main.go b/example/geyser/cmd/main.go new file mode 100644 index 0000000..bc6f3e1 --- /dev/null +++ b/example/geyser/cmd/main.go @@ -0,0 +1,94 @@ +package main + +import ( + "context" + "fmt" + "time" + + parser "github.com/thloyi/pump-parser" + example "github.com/thloyi/pump-parser/example" + "github.com/thloyi/pump-parser/example/geyser" +) + +func main() { + //pool, err := ants.NewPool(100, ants.WithPreAlloc(true), ants.WithNonblocking(true)) + //if err != nil { + // panic(err) + //} + //xt := tracker.NewTwitterTracker(nil) // Initialize Twitter tracker if needed + // laserstream-mainnet-slc.helius-rpc.com:80 + + ch := make(chan geyser.SubscriptionMessage, 1) + go geyser.RunLoopWithReConnect(context.Background(), "127.0.0.1:10001", parser.SolProgramPump, ch) + // var tokenTxs = make(map[string]*types.Tx) + currentBlock := uint64(0) + for msg := range ch { + if msg.Tx == nil { + block := msg.Block + if block.Slot%100 == 0 { + fmt.Printf("slot: %d, hash: %s, time: %s, height: %d, estimate delay second: %d\n", + block.Slot, block.BlockHash, time.Unix(block.BlockTime, 0).Format("2006-01-02 15:04:05"), block.Height, msg.EstimateDelaySecond) + } + continue + } + ptx := msg.Tx + //data, _ := json.Marshal(tx) + //fmt.Println(string(data)) + //continue + + //if tx.Token0Address != "HRHLDjqFBhNeyTXUuZQE9gTy5z2112qeQBS9U79NHyyp" { + // continue + //} + //if tx.Program != parser.SolProgramPump { + // continue + //} + if currentBlock == ptx.Block { + continue + } + + // 处理交易 + txErr, ok := ptx.Err.(*geyser.TransactionError) + var customerErrCode uint32 + var instructorErrIndex uint8 + if ok { + instructorErrIndex, customerErrCode, _ = txErr.GetCustomErrorCode() + fmt.Printf("now: %s, block: %d, tx: %s, errInstr Code: %d, errInstrIndex: %d, err: %v\n", time.Now().Format("2006-01-02 15:04:05"), ptx.Block, ptx.GetTxHash(), customerErrCode, instructorErrIndex, ptx.Err) + } else { + txs := example.FromTx(ptx, msg.RawTx) + if len(txs) == 0 { + fmt.Printf("tx is empty, block: %d, tx %s \n", ptx.Block, ptx.GetTxHash()) + continue + } + printed := false + for _, tx := range txs { + if tx.Program != parser.SolProgramPump { + continue + } + printed = true + fmt.Printf("t: %s, block: %d, hash: %s, signer: %s, program: %s, event: %s, token1: %s, cuPrice: %s, mevAgent: %s, mevFee: %s, platform: %s, platformFee: %s, entryContract: %s, mayhem: %t\n", + time.Now().Format(time.RFC3339Nano), + tx.Block, tx.GetTxHash(), tx.Maker, tx.Program, tx.Event, tx.Token1Amount, tx.CUPrice, tx.MevAgent, tx.MevAgentFee, tx.Platform, tx.PlatformFee, tx.EntryContract, tx.Mayhem) + break + } + if !printed { + continue + } + //fmt.Printf("t: %s, block: %d, hash: %s, signer: %s, program: %s, event: %s, token0: %s, token1: %s, signer before sol :%s, after sol: %s, after token: %s, tokencreator: %s, tokenprogram: %s, mayhem: %t\n", + // time.Now().Format(time.RFC3339Nano), + // tx.Block, tx.GetTxHash(), tx.Maker, tx.Program, tx.Event, tx.Token0Amount.String(), tx.Token1Amount.String(), + // tx.BeforeSolBalance, tx.AfterSOLBalance, tx.AfterSignerToken0Balance, tx.TokenCreator, tx.Token0Program, tx.Mayhem) + + } + currentBlock = ptx.Block + // + //if tx.Event == "create" { + // if err := pool.Submit(func() { + // now := time.Now() + // xt.AddToken(tx.Token) + // log.Printf("Add token %s, cost: %s %s %v %v", tx.Token.Address, time.Since(now), tx.Token.Twitter, xt.DuplicateCount(tx.Token.Address), xt.HasTwitter(tx.Token.Address)) + // }); err != nil { + // fmt.Println(err) + // } + //} + } +} diff --git a/example/geyser/error.go b/example/geyser/error.go new file mode 100644 index 0000000..d441fae --- /dev/null +++ b/example/geyser/error.go @@ -0,0 +1,277 @@ +package geyser + +import ( + "encoding/binary" + "errors" +) + +type TransactionErrorVariant uint32 +type InstructionErrorVariant uint32 + +type InstructionErrorEnum struct { + Index uint8 + Variant InstructionErrorVariant + rest []byte +} + +type CustomInstructionErrorEnum struct { + Code uint32 +} + +const ( + AccountInUse TransactionErrorVariant = iota + AccountLoadedTwice + AccountNotFound + ProgramAccountNotFound + InsufficientFundsForFee + InvalidAccountForFee + AlreadyProcessed + BlockhashNotFound + + InstructionError //InstructionError(u8, InstructionError), + + CallChainTooDeep + MissingSignatureForFee + InvalidAccountIndex + SignatureFailure + InvalidProgramForExecution + SanitizeFailure + ClusterMaintenance + AccountBorrowOutstanding + WouldExceedMaxBlockCostLimit + UnsupportedVersion + InvalidWritableAccount + WouldExceedMaxAccountCostLimit + WouldExceedAccountDataBlockLimit + TooManyAccountLocks + AddressLookupTableNotFound + InvalidAddressLookupTableOwner + InvalidAddressLookupTableData + InvalidAddressLookupTableIndex + InvalidRentPayingAccount + WouldExceedMaxVoteCostLimit + WouldExceedAccountDataTotalLimit + + DuplicateInstruction //DuplicateInstruction(u8), + + /* + InsufficientFundsForRent { + account_index: u8, + }, + */ + InsufficientFundsForRent + + MaxLoadedAccountsDataSizeExceeded + InvalidLoadedAccountsDataSizeLimit + ResanitizationNeeded + + /* + ProgramExecutionTemporarilyRestricted { + account_index: u8, + }, + */ + ProgramExecutionTemporarilyRestricted + + UnbalancedTransaction + ProgramCacheHitMaxLimit + CommitCancelled +) + +const ( + GenericError InstructionErrorVariant = iota + /// The arguments provided to a program were invalid + InvalidArgument + /// An instruction's data contents were invalid + InvalidInstructionData + /// An account's data contents was invalid + InvalidAccountData + /// An account's data was too small + AccountDataTooSmall + /// An account's balance was too small to complete the instruction + InsufficientFunds + /// The account did not have the expected program id + IncorrectProgramId + /// A signature was required but not found + MissingRequiredSignature + /// An initialize instruction was sent to an account that has already been initialized. + AccountAlreadyInitialized + /// An attempt to operate on an account that hasn't been initialized. + UninitializedAccount + /// Program's instruction lamport balance does not equal the balance after the instruction + UnbalancedInstruction + /// Program illegally modified an account's program id + ModifiedProgramId + /// Program spent the lamports of an account that doesn't belong to it + ExternalAccountLamportSpend + /// Program modified the data of an account that doesn't belong to it + ExternalAccountDataModified + /// Read-only account's lamports modified + ReadonlyLamportChange + /// Read-only account's data was modified + ReadonlyDataModified + /// An account was referenced more than once in a single instruction + // Deprecated, instructions can now contain duplicate accounts + DuplicateAccountIndex + /// Executable bit on account changed, but shouldn't have + ExecutableModified + /// Rent_epoch account changed, but shouldn't have + RentEpochModified + /// The instruction expected additional account keys + NotEnoughAccountKeys + /// Program other than the account's owner changed the size of the account data + AccountDataSizeChanged + /// The instruction expected an executable account + AccountNotExecutable + /// Failed to borrow a reference to account data, already borrowed + AccountBorrowFailed + /// Account data has an outstanding reference after a program's execution + InstructionAccountBorrowOutstanding + /// The same account was multiply passed to an on-chain program's entrypoint, but the program + /// modified them differently. A program can only modify one instance of the account because + /// the runtime cannot determine which changes to pick or how to merge them if both are modified + DuplicateAccountOutOfSync + /// Allows on-chain programs to implement program-specific error types and see them returned + /// by the Solana runtime. A program-specific error may be any type that is represented as + /// or serialized to a u32 integer. + + Custom // Custom(u32), + + /// The return value from the program was invalid. Valid errors are either a defined builtin + /// error value or a user-defined error in the lower 32 bits. + InvalidError + /// Executable account's data was modified + ExecutableDataModified + /// Executable account's lamports modified + ExecutableLamportChange + /// Executable accounts must be rent exempt + ExecutableAccountNotRentExempt + /// Unsupported program id + UnsupportedProgramId + /// Cross-program invocation call depth too deep + CallDepth + /// An account required by the instruction is missing + MissingAccount + /// Cross-program invocation reentrancy not allowed for this instruction + ReentrancyNotAllowed + /// Length of the seed is too long for address generation + MaxSeedLengthExceeded + /// Provided seeds do not result in a valid address + InvalidSeeds + /// Failed to reallocate account data of this length + InvalidRealloc + /// Computational budget exceeded + ComputationalBudgetExceeded + /// Cross-program invocation with unauthorized signer or writable account + PrivilegeEscalation + /// Failed to create program execution environment + ProgramEnvironmentSetupFailure + /// Program failed to complete + ProgramFailedToComplete + /// Program failed to compile + ProgramFailedToCompile + /// Account is immutable + Immutable + /// Incorrect authority provided + IncorrectAuthority + /// Failed to serialize or deserialize account data + /// + /// Warning: This error should never be emitted by the runtime. + /// + /// This error includes strings from the underlying 3rd party Borsh crate + /// which can be dangerous because the error strings could change across + /// Borsh versions. Only programs can use this error because they are + /// consistent across Solana software versions. + /// string values from this error should not be used in + + BorshIoError // BorshIoError(String) + + // An account does not have enough lamports to be rent-exempt + AccountNotRentExempt + /// Invalid account owner + InvalidAccountOwner + /// Program arithmetic overflowed + ArithmeticOverflow + /// Unsupported sysvar + UnsupportedSysvar + /// Illegal account owner + IllegalOwner + /// Accounts data allocations exceeded the maximum allowed per transaction + MaxAccountsDataAllocationsExceeded + /// Max accounts exceeded + MaxAccountsExceeded + /// Max instruction trace length exceeded + MaxInstructionTraceLengthExceeded + /// Builtin programs must consume compute units + BuiltinProgramsMustConsumeComputeUnits +) + +type TransactionError struct { + Variant TransactionErrorVariant + rest []byte +} + +var ( + ErrInvalidTransactionError = errors.New("invalid transaction error") + NotAnInstructionError = errors.New("not an instruction error") + NotACustomInstructionError = errors.New("not a custom instruction error") + UnsupportedInstructionError = errors.New("unsupported instruction error") +) + +func DecodeTransactionError(data []byte) (*TransactionError, error) { + if len(data) < 4 { + return nil, ErrInvalidTransactionError + } + + var err TransactionError + variant := binary.LittleEndian.Uint32(data[:4]) + if variant > uint32(CommitCancelled) { + return nil, UnsupportedInstructionError + } + err.Variant = TransactionErrorVariant(variant) + err.rest = data[4:] + + return &err, nil +} + +func (e *TransactionError) GetCustomErrorCode() (uint8, uint32, error) { + instr, err := e.GetInstructionError() + if err != nil { + return 0, 0, err + } + custom, err := instr.Custom() + if err != nil { + return 0, 0, err + } + return instr.Index, custom.Code, nil +} + +func (e *TransactionError) GetInstructionError() (*InstructionErrorEnum, error) { + if e.Variant != InstructionError { + return nil, NotAnInstructionError + } + if len(e.rest) < 5 { + return nil, NotAnInstructionError + } + + var err InstructionErrorEnum + err.Index = e.rest[0] + variant := binary.LittleEndian.Uint32(e.rest[1:5]) + if variant > uint32(BuiltinProgramsMustConsumeComputeUnits) { + return nil, UnsupportedInstructionError + } + err.Variant = InstructionErrorVariant(binary.LittleEndian.Uint32(e.rest[1:5])) + err.rest = e.rest[5:] + return &err, nil +} + +func (e *InstructionErrorEnum) Custom() (*CustomInstructionErrorEnum, error) { + if e.Variant != Custom { + return nil, NotACustomInstructionError + } + if len(e.rest) < 4 { + return nil, NotACustomInstructionError + } + var custom CustomInstructionErrorEnum + custom.Code = binary.LittleEndian.Uint32(e.rest[:4]) + return &custom, nil +} diff --git a/example/geyser/message.go b/example/geyser/message.go new file mode 100644 index 0000000..227f4fb --- /dev/null +++ b/example/geyser/message.go @@ -0,0 +1,22 @@ +package geyser + +import ( + "github.com/thloyi/pump-parser" +) + +type BlockInfo struct { + Slot uint64 + BlockTime int64 + BlockHash string + Height uint64 +} + +type SubscriptionMessage struct { + EstimateDelaySecond int64 + + Reconnect bool + + Block *BlockInfo + Tx *pump_parser.Tx + RawTx *pump_parser.RawTx +} diff --git a/example/geyser/proto/geyser.pb.go b/example/geyser/proto/geyser.pb.go new file mode 100644 index 0000000..62b1c79 --- /dev/null +++ b/example/geyser/proto/geyser.pb.go @@ -0,0 +1,3113 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.6 +// protoc v5.29.3 +// source: geyser.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type CommitmentLevel int32 + +const ( + CommitmentLevel_PROCESSED CommitmentLevel = 0 + CommitmentLevel_CONFIRMED CommitmentLevel = 1 + CommitmentLevel_FINALIZED CommitmentLevel = 2 +) + +// Enum value maps for CommitmentLevel. +var ( + CommitmentLevel_name = map[int32]string{ + 0: "PROCESSED", + 1: "CONFIRMED", + 2: "FINALIZED", + } + CommitmentLevel_value = map[string]int32{ + "PROCESSED": 0, + "CONFIRMED": 1, + "FINALIZED": 2, + } +) + +func (x CommitmentLevel) Enum() *CommitmentLevel { + p := new(CommitmentLevel) + *p = x + return p +} + +func (x CommitmentLevel) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (CommitmentLevel) Descriptor() protoreflect.EnumDescriptor { + return file_geyser_proto_enumTypes[0].Descriptor() +} + +func (CommitmentLevel) Type() protoreflect.EnumType { + return &file_geyser_proto_enumTypes[0] +} + +func (x CommitmentLevel) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use CommitmentLevel.Descriptor instead. +func (CommitmentLevel) EnumDescriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{0} +} + +type SlotStatus int32 + +const ( + SlotStatus_SLOT_PROCESSED SlotStatus = 0 + SlotStatus_SLOT_CONFIRMED SlotStatus = 1 + SlotStatus_SLOT_FINALIZED SlotStatus = 2 + SlotStatus_SLOT_FIRST_SHRED_RECEIVED SlotStatus = 3 + SlotStatus_SLOT_COMPLETED SlotStatus = 4 + SlotStatus_SLOT_CREATED_BANK SlotStatus = 5 + SlotStatus_SLOT_DEAD SlotStatus = 6 +) + +// Enum value maps for SlotStatus. +var ( + SlotStatus_name = map[int32]string{ + 0: "SLOT_PROCESSED", + 1: "SLOT_CONFIRMED", + 2: "SLOT_FINALIZED", + 3: "SLOT_FIRST_SHRED_RECEIVED", + 4: "SLOT_COMPLETED", + 5: "SLOT_CREATED_BANK", + 6: "SLOT_DEAD", + } + SlotStatus_value = map[string]int32{ + "SLOT_PROCESSED": 0, + "SLOT_CONFIRMED": 1, + "SLOT_FINALIZED": 2, + "SLOT_FIRST_SHRED_RECEIVED": 3, + "SLOT_COMPLETED": 4, + "SLOT_CREATED_BANK": 5, + "SLOT_DEAD": 6, + } +) + +func (x SlotStatus) Enum() *SlotStatus { + p := new(SlotStatus) + *p = x + return p +} + +func (x SlotStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SlotStatus) Descriptor() protoreflect.EnumDescriptor { + return file_geyser_proto_enumTypes[1].Descriptor() +} + +func (SlotStatus) Type() protoreflect.EnumType { + return &file_geyser_proto_enumTypes[1] +} + +func (x SlotStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SlotStatus.Descriptor instead. +func (SlotStatus) EnumDescriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{1} +} + +type SubscribeRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Accounts map[string]*SubscribeRequestFilterAccounts `protobuf:"bytes,1,rep,name=accounts,proto3" json:"accounts,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Slots map[string]*SubscribeRequestFilterSlots `protobuf:"bytes,2,rep,name=slots,proto3" json:"slots,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Transactions map[string]*SubscribeRequestFilterTransactions `protobuf:"bytes,3,rep,name=transactions,proto3" json:"transactions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + TransactionsStatus map[string]*SubscribeRequestFilterTransactions `protobuf:"bytes,10,rep,name=transactions_status,json=transactionsStatus,proto3" json:"transactions_status,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Blocks map[string]*SubscribeRequestFilterBlocks `protobuf:"bytes,4,rep,name=blocks,proto3" json:"blocks,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + BlocksMeta map[string]*SubscribeRequestFilterBlocksMeta `protobuf:"bytes,5,rep,name=blocks_meta,json=blocksMeta,proto3" json:"blocks_meta,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Entry map[string]*SubscribeRequestFilterEntry `protobuf:"bytes,8,rep,name=entry,proto3" json:"entry,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Commitment *CommitmentLevel `protobuf:"varint,6,opt,name=commitment,proto3,enum=geyser.CommitmentLevel,oneof" json:"commitment,omitempty"` + AccountsDataSlice []*SubscribeRequestAccountsDataSlice `protobuf:"bytes,7,rep,name=accounts_data_slice,json=accountsDataSlice,proto3" json:"accounts_data_slice,omitempty"` + Ping *SubscribeRequestPing `protobuf:"bytes,9,opt,name=ping,proto3,oneof" json:"ping,omitempty"` + FromSlot *uint64 `protobuf:"varint,11,opt,name=from_slot,json=fromSlot,proto3,oneof" json:"from_slot,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeRequest) Reset() { + *x = SubscribeRequest{} + mi := &file_geyser_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeRequest) ProtoMessage() {} + +func (x *SubscribeRequest) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeRequest.ProtoReflect.Descriptor instead. +func (*SubscribeRequest) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{0} +} + +func (x *SubscribeRequest) GetAccounts() map[string]*SubscribeRequestFilterAccounts { + if x != nil { + return x.Accounts + } + return nil +} + +func (x *SubscribeRequest) GetSlots() map[string]*SubscribeRequestFilterSlots { + if x != nil { + return x.Slots + } + return nil +} + +func (x *SubscribeRequest) GetTransactions() map[string]*SubscribeRequestFilterTransactions { + if x != nil { + return x.Transactions + } + return nil +} + +func (x *SubscribeRequest) GetTransactionsStatus() map[string]*SubscribeRequestFilterTransactions { + if x != nil { + return x.TransactionsStatus + } + return nil +} + +func (x *SubscribeRequest) GetBlocks() map[string]*SubscribeRequestFilterBlocks { + if x != nil { + return x.Blocks + } + return nil +} + +func (x *SubscribeRequest) GetBlocksMeta() map[string]*SubscribeRequestFilterBlocksMeta { + if x != nil { + return x.BlocksMeta + } + return nil +} + +func (x *SubscribeRequest) GetEntry() map[string]*SubscribeRequestFilterEntry { + if x != nil { + return x.Entry + } + return nil +} + +func (x *SubscribeRequest) GetCommitment() CommitmentLevel { + if x != nil && x.Commitment != nil { + return *x.Commitment + } + return CommitmentLevel_PROCESSED +} + +func (x *SubscribeRequest) GetAccountsDataSlice() []*SubscribeRequestAccountsDataSlice { + if x != nil { + return x.AccountsDataSlice + } + return nil +} + +func (x *SubscribeRequest) GetPing() *SubscribeRequestPing { + if x != nil { + return x.Ping + } + return nil +} + +func (x *SubscribeRequest) GetFromSlot() uint64 { + if x != nil && x.FromSlot != nil { + return *x.FromSlot + } + return 0 +} + +type SubscribeRequestFilterAccounts struct { + state protoimpl.MessageState `protogen:"open.v1"` + Account []string `protobuf:"bytes,2,rep,name=account,proto3" json:"account,omitempty"` + Owner []string `protobuf:"bytes,3,rep,name=owner,proto3" json:"owner,omitempty"` + Filters []*SubscribeRequestFilterAccountsFilter `protobuf:"bytes,4,rep,name=filters,proto3" json:"filters,omitempty"` + NonemptyTxnSignature *bool `protobuf:"varint,5,opt,name=nonempty_txn_signature,json=nonemptyTxnSignature,proto3,oneof" json:"nonempty_txn_signature,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeRequestFilterAccounts) Reset() { + *x = SubscribeRequestFilterAccounts{} + mi := &file_geyser_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeRequestFilterAccounts) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeRequestFilterAccounts) ProtoMessage() {} + +func (x *SubscribeRequestFilterAccounts) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeRequestFilterAccounts.ProtoReflect.Descriptor instead. +func (*SubscribeRequestFilterAccounts) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{1} +} + +func (x *SubscribeRequestFilterAccounts) GetAccount() []string { + if x != nil { + return x.Account + } + return nil +} + +func (x *SubscribeRequestFilterAccounts) GetOwner() []string { + if x != nil { + return x.Owner + } + return nil +} + +func (x *SubscribeRequestFilterAccounts) GetFilters() []*SubscribeRequestFilterAccountsFilter { + if x != nil { + return x.Filters + } + return nil +} + +func (x *SubscribeRequestFilterAccounts) GetNonemptyTxnSignature() bool { + if x != nil && x.NonemptyTxnSignature != nil { + return *x.NonemptyTxnSignature + } + return false +} + +type SubscribeRequestFilterAccountsFilter struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Filter: + // + // *SubscribeRequestFilterAccountsFilter_Memcmp + // *SubscribeRequestFilterAccountsFilter_Datasize + // *SubscribeRequestFilterAccountsFilter_TokenAccountState + // *SubscribeRequestFilterAccountsFilter_Lamports + Filter isSubscribeRequestFilterAccountsFilter_Filter `protobuf_oneof:"filter"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeRequestFilterAccountsFilter) Reset() { + *x = SubscribeRequestFilterAccountsFilter{} + mi := &file_geyser_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeRequestFilterAccountsFilter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeRequestFilterAccountsFilter) ProtoMessage() {} + +func (x *SubscribeRequestFilterAccountsFilter) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeRequestFilterAccountsFilter.ProtoReflect.Descriptor instead. +func (*SubscribeRequestFilterAccountsFilter) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{2} +} + +func (x *SubscribeRequestFilterAccountsFilter) GetFilter() isSubscribeRequestFilterAccountsFilter_Filter { + if x != nil { + return x.Filter + } + return nil +} + +func (x *SubscribeRequestFilterAccountsFilter) GetMemcmp() *SubscribeRequestFilterAccountsFilterMemcmp { + if x != nil { + if x, ok := x.Filter.(*SubscribeRequestFilterAccountsFilter_Memcmp); ok { + return x.Memcmp + } + } + return nil +} + +func (x *SubscribeRequestFilterAccountsFilter) GetDatasize() uint64 { + if x != nil { + if x, ok := x.Filter.(*SubscribeRequestFilterAccountsFilter_Datasize); ok { + return x.Datasize + } + } + return 0 +} + +func (x *SubscribeRequestFilterAccountsFilter) GetTokenAccountState() bool { + if x != nil { + if x, ok := x.Filter.(*SubscribeRequestFilterAccountsFilter_TokenAccountState); ok { + return x.TokenAccountState + } + } + return false +} + +func (x *SubscribeRequestFilterAccountsFilter) GetLamports() *SubscribeRequestFilterAccountsFilterLamports { + if x != nil { + if x, ok := x.Filter.(*SubscribeRequestFilterAccountsFilter_Lamports); ok { + return x.Lamports + } + } + return nil +} + +type isSubscribeRequestFilterAccountsFilter_Filter interface { + isSubscribeRequestFilterAccountsFilter_Filter() +} + +type SubscribeRequestFilterAccountsFilter_Memcmp struct { + Memcmp *SubscribeRequestFilterAccountsFilterMemcmp `protobuf:"bytes,1,opt,name=memcmp,proto3,oneof"` +} + +type SubscribeRequestFilterAccountsFilter_Datasize struct { + Datasize uint64 `protobuf:"varint,2,opt,name=datasize,proto3,oneof"` +} + +type SubscribeRequestFilterAccountsFilter_TokenAccountState struct { + TokenAccountState bool `protobuf:"varint,3,opt,name=token_account_state,json=tokenAccountState,proto3,oneof"` +} + +type SubscribeRequestFilterAccountsFilter_Lamports struct { + Lamports *SubscribeRequestFilterAccountsFilterLamports `protobuf:"bytes,4,opt,name=lamports,proto3,oneof"` +} + +func (*SubscribeRequestFilterAccountsFilter_Memcmp) isSubscribeRequestFilterAccountsFilter_Filter() {} + +func (*SubscribeRequestFilterAccountsFilter_Datasize) isSubscribeRequestFilterAccountsFilter_Filter() { +} + +func (*SubscribeRequestFilterAccountsFilter_TokenAccountState) isSubscribeRequestFilterAccountsFilter_Filter() { +} + +func (*SubscribeRequestFilterAccountsFilter_Lamports) isSubscribeRequestFilterAccountsFilter_Filter() { +} + +type SubscribeRequestFilterAccountsFilterMemcmp struct { + state protoimpl.MessageState `protogen:"open.v1"` + Offset uint64 `protobuf:"varint,1,opt,name=offset,proto3" json:"offset,omitempty"` + // Types that are valid to be assigned to Data: + // + // *SubscribeRequestFilterAccountsFilterMemcmp_Bytes + // *SubscribeRequestFilterAccountsFilterMemcmp_Base58 + // *SubscribeRequestFilterAccountsFilterMemcmp_Base64 + Data isSubscribeRequestFilterAccountsFilterMemcmp_Data `protobuf_oneof:"data"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeRequestFilterAccountsFilterMemcmp) Reset() { + *x = SubscribeRequestFilterAccountsFilterMemcmp{} + mi := &file_geyser_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeRequestFilterAccountsFilterMemcmp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeRequestFilterAccountsFilterMemcmp) ProtoMessage() {} + +func (x *SubscribeRequestFilterAccountsFilterMemcmp) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeRequestFilterAccountsFilterMemcmp.ProtoReflect.Descriptor instead. +func (*SubscribeRequestFilterAccountsFilterMemcmp) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{3} +} + +func (x *SubscribeRequestFilterAccountsFilterMemcmp) GetOffset() uint64 { + if x != nil { + return x.Offset + } + return 0 +} + +func (x *SubscribeRequestFilterAccountsFilterMemcmp) GetData() isSubscribeRequestFilterAccountsFilterMemcmp_Data { + if x != nil { + return x.Data + } + return nil +} + +func (x *SubscribeRequestFilterAccountsFilterMemcmp) GetBytes() []byte { + if x != nil { + if x, ok := x.Data.(*SubscribeRequestFilterAccountsFilterMemcmp_Bytes); ok { + return x.Bytes + } + } + return nil +} + +func (x *SubscribeRequestFilterAccountsFilterMemcmp) GetBase58() string { + if x != nil { + if x, ok := x.Data.(*SubscribeRequestFilterAccountsFilterMemcmp_Base58); ok { + return x.Base58 + } + } + return "" +} + +func (x *SubscribeRequestFilterAccountsFilterMemcmp) GetBase64() string { + if x != nil { + if x, ok := x.Data.(*SubscribeRequestFilterAccountsFilterMemcmp_Base64); ok { + return x.Base64 + } + } + return "" +} + +type isSubscribeRequestFilterAccountsFilterMemcmp_Data interface { + isSubscribeRequestFilterAccountsFilterMemcmp_Data() +} + +type SubscribeRequestFilterAccountsFilterMemcmp_Bytes struct { + Bytes []byte `protobuf:"bytes,2,opt,name=bytes,proto3,oneof"` +} + +type SubscribeRequestFilterAccountsFilterMemcmp_Base58 struct { + Base58 string `protobuf:"bytes,3,opt,name=base58,proto3,oneof"` +} + +type SubscribeRequestFilterAccountsFilterMemcmp_Base64 struct { + Base64 string `protobuf:"bytes,4,opt,name=base64,proto3,oneof"` +} + +func (*SubscribeRequestFilterAccountsFilterMemcmp_Bytes) isSubscribeRequestFilterAccountsFilterMemcmp_Data() { +} + +func (*SubscribeRequestFilterAccountsFilterMemcmp_Base58) isSubscribeRequestFilterAccountsFilterMemcmp_Data() { +} + +func (*SubscribeRequestFilterAccountsFilterMemcmp_Base64) isSubscribeRequestFilterAccountsFilterMemcmp_Data() { +} + +type SubscribeRequestFilterAccountsFilterLamports struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Cmp: + // + // *SubscribeRequestFilterAccountsFilterLamports_Eq + // *SubscribeRequestFilterAccountsFilterLamports_Ne + // *SubscribeRequestFilterAccountsFilterLamports_Lt + // *SubscribeRequestFilterAccountsFilterLamports_Gt + Cmp isSubscribeRequestFilterAccountsFilterLamports_Cmp `protobuf_oneof:"cmp"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeRequestFilterAccountsFilterLamports) Reset() { + *x = SubscribeRequestFilterAccountsFilterLamports{} + mi := &file_geyser_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeRequestFilterAccountsFilterLamports) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeRequestFilterAccountsFilterLamports) ProtoMessage() {} + +func (x *SubscribeRequestFilterAccountsFilterLamports) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeRequestFilterAccountsFilterLamports.ProtoReflect.Descriptor instead. +func (*SubscribeRequestFilterAccountsFilterLamports) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{4} +} + +func (x *SubscribeRequestFilterAccountsFilterLamports) GetCmp() isSubscribeRequestFilterAccountsFilterLamports_Cmp { + if x != nil { + return x.Cmp + } + return nil +} + +func (x *SubscribeRequestFilterAccountsFilterLamports) GetEq() uint64 { + if x != nil { + if x, ok := x.Cmp.(*SubscribeRequestFilterAccountsFilterLamports_Eq); ok { + return x.Eq + } + } + return 0 +} + +func (x *SubscribeRequestFilterAccountsFilterLamports) GetNe() uint64 { + if x != nil { + if x, ok := x.Cmp.(*SubscribeRequestFilterAccountsFilterLamports_Ne); ok { + return x.Ne + } + } + return 0 +} + +func (x *SubscribeRequestFilterAccountsFilterLamports) GetLt() uint64 { + if x != nil { + if x, ok := x.Cmp.(*SubscribeRequestFilterAccountsFilterLamports_Lt); ok { + return x.Lt + } + } + return 0 +} + +func (x *SubscribeRequestFilterAccountsFilterLamports) GetGt() uint64 { + if x != nil { + if x, ok := x.Cmp.(*SubscribeRequestFilterAccountsFilterLamports_Gt); ok { + return x.Gt + } + } + return 0 +} + +type isSubscribeRequestFilterAccountsFilterLamports_Cmp interface { + isSubscribeRequestFilterAccountsFilterLamports_Cmp() +} + +type SubscribeRequestFilterAccountsFilterLamports_Eq struct { + Eq uint64 `protobuf:"varint,1,opt,name=eq,proto3,oneof"` +} + +type SubscribeRequestFilterAccountsFilterLamports_Ne struct { + Ne uint64 `protobuf:"varint,2,opt,name=ne,proto3,oneof"` +} + +type SubscribeRequestFilterAccountsFilterLamports_Lt struct { + Lt uint64 `protobuf:"varint,3,opt,name=lt,proto3,oneof"` +} + +type SubscribeRequestFilterAccountsFilterLamports_Gt struct { + Gt uint64 `protobuf:"varint,4,opt,name=gt,proto3,oneof"` +} + +func (*SubscribeRequestFilterAccountsFilterLamports_Eq) isSubscribeRequestFilterAccountsFilterLamports_Cmp() { +} + +func (*SubscribeRequestFilterAccountsFilterLamports_Ne) isSubscribeRequestFilterAccountsFilterLamports_Cmp() { +} + +func (*SubscribeRequestFilterAccountsFilterLamports_Lt) isSubscribeRequestFilterAccountsFilterLamports_Cmp() { +} + +func (*SubscribeRequestFilterAccountsFilterLamports_Gt) isSubscribeRequestFilterAccountsFilterLamports_Cmp() { +} + +type SubscribeRequestFilterSlots struct { + state protoimpl.MessageState `protogen:"open.v1"` + FilterByCommitment *bool `protobuf:"varint,1,opt,name=filter_by_commitment,json=filterByCommitment,proto3,oneof" json:"filter_by_commitment,omitempty"` + InterslotUpdates *bool `protobuf:"varint,2,opt,name=interslot_updates,json=interslotUpdates,proto3,oneof" json:"interslot_updates,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeRequestFilterSlots) Reset() { + *x = SubscribeRequestFilterSlots{} + mi := &file_geyser_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeRequestFilterSlots) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeRequestFilterSlots) ProtoMessage() {} + +func (x *SubscribeRequestFilterSlots) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeRequestFilterSlots.ProtoReflect.Descriptor instead. +func (*SubscribeRequestFilterSlots) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{5} +} + +func (x *SubscribeRequestFilterSlots) GetFilterByCommitment() bool { + if x != nil && x.FilterByCommitment != nil { + return *x.FilterByCommitment + } + return false +} + +func (x *SubscribeRequestFilterSlots) GetInterslotUpdates() bool { + if x != nil && x.InterslotUpdates != nil { + return *x.InterslotUpdates + } + return false +} + +type SubscribeRequestFilterTransactions struct { + state protoimpl.MessageState `protogen:"open.v1"` + Vote *bool `protobuf:"varint,1,opt,name=vote,proto3,oneof" json:"vote,omitempty"` + Failed *bool `protobuf:"varint,2,opt,name=failed,proto3,oneof" json:"failed,omitempty"` + Signature *string `protobuf:"bytes,5,opt,name=signature,proto3,oneof" json:"signature,omitempty"` + AccountInclude []string `protobuf:"bytes,3,rep,name=account_include,json=accountInclude,proto3" json:"account_include,omitempty"` + AccountExclude []string `protobuf:"bytes,4,rep,name=account_exclude,json=accountExclude,proto3" json:"account_exclude,omitempty"` + AccountRequired []string `protobuf:"bytes,6,rep,name=account_required,json=accountRequired,proto3" json:"account_required,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeRequestFilterTransactions) Reset() { + *x = SubscribeRequestFilterTransactions{} + mi := &file_geyser_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeRequestFilterTransactions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeRequestFilterTransactions) ProtoMessage() {} + +func (x *SubscribeRequestFilterTransactions) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeRequestFilterTransactions.ProtoReflect.Descriptor instead. +func (*SubscribeRequestFilterTransactions) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{6} +} + +func (x *SubscribeRequestFilterTransactions) GetVote() bool { + if x != nil && x.Vote != nil { + return *x.Vote + } + return false +} + +func (x *SubscribeRequestFilterTransactions) GetFailed() bool { + if x != nil && x.Failed != nil { + return *x.Failed + } + return false +} + +func (x *SubscribeRequestFilterTransactions) GetSignature() string { + if x != nil && x.Signature != nil { + return *x.Signature + } + return "" +} + +func (x *SubscribeRequestFilterTransactions) GetAccountInclude() []string { + if x != nil { + return x.AccountInclude + } + return nil +} + +func (x *SubscribeRequestFilterTransactions) GetAccountExclude() []string { + if x != nil { + return x.AccountExclude + } + return nil +} + +func (x *SubscribeRequestFilterTransactions) GetAccountRequired() []string { + if x != nil { + return x.AccountRequired + } + return nil +} + +type SubscribeRequestFilterBlocks struct { + state protoimpl.MessageState `protogen:"open.v1"` + AccountInclude []string `protobuf:"bytes,1,rep,name=account_include,json=accountInclude,proto3" json:"account_include,omitempty"` + IncludeTransactions *bool `protobuf:"varint,2,opt,name=include_transactions,json=includeTransactions,proto3,oneof" json:"include_transactions,omitempty"` + IncludeAccounts *bool `protobuf:"varint,3,opt,name=include_accounts,json=includeAccounts,proto3,oneof" json:"include_accounts,omitempty"` + IncludeEntries *bool `protobuf:"varint,4,opt,name=include_entries,json=includeEntries,proto3,oneof" json:"include_entries,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeRequestFilterBlocks) Reset() { + *x = SubscribeRequestFilterBlocks{} + mi := &file_geyser_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeRequestFilterBlocks) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeRequestFilterBlocks) ProtoMessage() {} + +func (x *SubscribeRequestFilterBlocks) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeRequestFilterBlocks.ProtoReflect.Descriptor instead. +func (*SubscribeRequestFilterBlocks) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{7} +} + +func (x *SubscribeRequestFilterBlocks) GetAccountInclude() []string { + if x != nil { + return x.AccountInclude + } + return nil +} + +func (x *SubscribeRequestFilterBlocks) GetIncludeTransactions() bool { + if x != nil && x.IncludeTransactions != nil { + return *x.IncludeTransactions + } + return false +} + +func (x *SubscribeRequestFilterBlocks) GetIncludeAccounts() bool { + if x != nil && x.IncludeAccounts != nil { + return *x.IncludeAccounts + } + return false +} + +func (x *SubscribeRequestFilterBlocks) GetIncludeEntries() bool { + if x != nil && x.IncludeEntries != nil { + return *x.IncludeEntries + } + return false +} + +type SubscribeRequestFilterBlocksMeta struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeRequestFilterBlocksMeta) Reset() { + *x = SubscribeRequestFilterBlocksMeta{} + mi := &file_geyser_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeRequestFilterBlocksMeta) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeRequestFilterBlocksMeta) ProtoMessage() {} + +func (x *SubscribeRequestFilterBlocksMeta) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeRequestFilterBlocksMeta.ProtoReflect.Descriptor instead. +func (*SubscribeRequestFilterBlocksMeta) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{8} +} + +type SubscribeRequestFilterEntry struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeRequestFilterEntry) Reset() { + *x = SubscribeRequestFilterEntry{} + mi := &file_geyser_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeRequestFilterEntry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeRequestFilterEntry) ProtoMessage() {} + +func (x *SubscribeRequestFilterEntry) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeRequestFilterEntry.ProtoReflect.Descriptor instead. +func (*SubscribeRequestFilterEntry) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{9} +} + +type SubscribeRequestAccountsDataSlice struct { + state protoimpl.MessageState `protogen:"open.v1"` + Offset uint64 `protobuf:"varint,1,opt,name=offset,proto3" json:"offset,omitempty"` + Length uint64 `protobuf:"varint,2,opt,name=length,proto3" json:"length,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeRequestAccountsDataSlice) Reset() { + *x = SubscribeRequestAccountsDataSlice{} + mi := &file_geyser_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeRequestAccountsDataSlice) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeRequestAccountsDataSlice) ProtoMessage() {} + +func (x *SubscribeRequestAccountsDataSlice) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeRequestAccountsDataSlice.ProtoReflect.Descriptor instead. +func (*SubscribeRequestAccountsDataSlice) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{10} +} + +func (x *SubscribeRequestAccountsDataSlice) GetOffset() uint64 { + if x != nil { + return x.Offset + } + return 0 +} + +func (x *SubscribeRequestAccountsDataSlice) GetLength() uint64 { + if x != nil { + return x.Length + } + return 0 +} + +type SubscribeRequestPing struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeRequestPing) Reset() { + *x = SubscribeRequestPing{} + mi := &file_geyser_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeRequestPing) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeRequestPing) ProtoMessage() {} + +func (x *SubscribeRequestPing) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeRequestPing.ProtoReflect.Descriptor instead. +func (*SubscribeRequestPing) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{11} +} + +func (x *SubscribeRequestPing) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +type SubscribeUpdate struct { + state protoimpl.MessageState `protogen:"open.v1"` + Filters []string `protobuf:"bytes,1,rep,name=filters,proto3" json:"filters,omitempty"` + // Types that are valid to be assigned to UpdateOneof: + // + // *SubscribeUpdate_Account + // *SubscribeUpdate_Slot + // *SubscribeUpdate_Transaction + // *SubscribeUpdate_TransactionStatus + // *SubscribeUpdate_Block + // *SubscribeUpdate_Ping + // *SubscribeUpdate_Pong + // *SubscribeUpdate_BlockMeta + // *SubscribeUpdate_Entry + UpdateOneof isSubscribeUpdate_UpdateOneof `protobuf_oneof:"update_oneof"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeUpdate) Reset() { + *x = SubscribeUpdate{} + mi := &file_geyser_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeUpdate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeUpdate) ProtoMessage() {} + +func (x *SubscribeUpdate) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeUpdate.ProtoReflect.Descriptor instead. +func (*SubscribeUpdate) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{12} +} + +func (x *SubscribeUpdate) GetFilters() []string { + if x != nil { + return x.Filters + } + return nil +} + +func (x *SubscribeUpdate) GetUpdateOneof() isSubscribeUpdate_UpdateOneof { + if x != nil { + return x.UpdateOneof + } + return nil +} + +func (x *SubscribeUpdate) GetAccount() *SubscribeUpdateAccount { + if x != nil { + if x, ok := x.UpdateOneof.(*SubscribeUpdate_Account); ok { + return x.Account + } + } + return nil +} + +func (x *SubscribeUpdate) GetSlot() *SubscribeUpdateSlot { + if x != nil { + if x, ok := x.UpdateOneof.(*SubscribeUpdate_Slot); ok { + return x.Slot + } + } + return nil +} + +func (x *SubscribeUpdate) GetTransaction() *SubscribeUpdateTransaction { + if x != nil { + if x, ok := x.UpdateOneof.(*SubscribeUpdate_Transaction); ok { + return x.Transaction + } + } + return nil +} + +func (x *SubscribeUpdate) GetTransactionStatus() *SubscribeUpdateTransactionStatus { + if x != nil { + if x, ok := x.UpdateOneof.(*SubscribeUpdate_TransactionStatus); ok { + return x.TransactionStatus + } + } + return nil +} + +func (x *SubscribeUpdate) GetBlock() *SubscribeUpdateBlock { + if x != nil { + if x, ok := x.UpdateOneof.(*SubscribeUpdate_Block); ok { + return x.Block + } + } + return nil +} + +func (x *SubscribeUpdate) GetPing() *SubscribeUpdatePing { + if x != nil { + if x, ok := x.UpdateOneof.(*SubscribeUpdate_Ping); ok { + return x.Ping + } + } + return nil +} + +func (x *SubscribeUpdate) GetPong() *SubscribeUpdatePong { + if x != nil { + if x, ok := x.UpdateOneof.(*SubscribeUpdate_Pong); ok { + return x.Pong + } + } + return nil +} + +func (x *SubscribeUpdate) GetBlockMeta() *SubscribeUpdateBlockMeta { + if x != nil { + if x, ok := x.UpdateOneof.(*SubscribeUpdate_BlockMeta); ok { + return x.BlockMeta + } + } + return nil +} + +func (x *SubscribeUpdate) GetEntry() *SubscribeUpdateEntry { + if x != nil { + if x, ok := x.UpdateOneof.(*SubscribeUpdate_Entry); ok { + return x.Entry + } + } + return nil +} + +func (x *SubscribeUpdate) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +type isSubscribeUpdate_UpdateOneof interface { + isSubscribeUpdate_UpdateOneof() +} + +type SubscribeUpdate_Account struct { + Account *SubscribeUpdateAccount `protobuf:"bytes,2,opt,name=account,proto3,oneof"` +} + +type SubscribeUpdate_Slot struct { + Slot *SubscribeUpdateSlot `protobuf:"bytes,3,opt,name=slot,proto3,oneof"` +} + +type SubscribeUpdate_Transaction struct { + Transaction *SubscribeUpdateTransaction `protobuf:"bytes,4,opt,name=transaction,proto3,oneof"` +} + +type SubscribeUpdate_TransactionStatus struct { + TransactionStatus *SubscribeUpdateTransactionStatus `protobuf:"bytes,10,opt,name=transaction_status,json=transactionStatus,proto3,oneof"` +} + +type SubscribeUpdate_Block struct { + Block *SubscribeUpdateBlock `protobuf:"bytes,5,opt,name=block,proto3,oneof"` +} + +type SubscribeUpdate_Ping struct { + Ping *SubscribeUpdatePing `protobuf:"bytes,6,opt,name=ping,proto3,oneof"` +} + +type SubscribeUpdate_Pong struct { + Pong *SubscribeUpdatePong `protobuf:"bytes,9,opt,name=pong,proto3,oneof"` +} + +type SubscribeUpdate_BlockMeta struct { + BlockMeta *SubscribeUpdateBlockMeta `protobuf:"bytes,7,opt,name=block_meta,json=blockMeta,proto3,oneof"` +} + +type SubscribeUpdate_Entry struct { + Entry *SubscribeUpdateEntry `protobuf:"bytes,8,opt,name=entry,proto3,oneof"` +} + +func (*SubscribeUpdate_Account) isSubscribeUpdate_UpdateOneof() {} + +func (*SubscribeUpdate_Slot) isSubscribeUpdate_UpdateOneof() {} + +func (*SubscribeUpdate_Transaction) isSubscribeUpdate_UpdateOneof() {} + +func (*SubscribeUpdate_TransactionStatus) isSubscribeUpdate_UpdateOneof() {} + +func (*SubscribeUpdate_Block) isSubscribeUpdate_UpdateOneof() {} + +func (*SubscribeUpdate_Ping) isSubscribeUpdate_UpdateOneof() {} + +func (*SubscribeUpdate_Pong) isSubscribeUpdate_UpdateOneof() {} + +func (*SubscribeUpdate_BlockMeta) isSubscribeUpdate_UpdateOneof() {} + +func (*SubscribeUpdate_Entry) isSubscribeUpdate_UpdateOneof() {} + +type SubscribeUpdateAccount struct { + state protoimpl.MessageState `protogen:"open.v1"` + Account *SubscribeUpdateAccountInfo `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"` + Slot uint64 `protobuf:"varint,2,opt,name=slot,proto3" json:"slot,omitempty"` + IsStartup bool `protobuf:"varint,3,opt,name=is_startup,json=isStartup,proto3" json:"is_startup,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeUpdateAccount) Reset() { + *x = SubscribeUpdateAccount{} + mi := &file_geyser_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeUpdateAccount) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeUpdateAccount) ProtoMessage() {} + +func (x *SubscribeUpdateAccount) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeUpdateAccount.ProtoReflect.Descriptor instead. +func (*SubscribeUpdateAccount) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{13} +} + +func (x *SubscribeUpdateAccount) GetAccount() *SubscribeUpdateAccountInfo { + if x != nil { + return x.Account + } + return nil +} + +func (x *SubscribeUpdateAccount) GetSlot() uint64 { + if x != nil { + return x.Slot + } + return 0 +} + +func (x *SubscribeUpdateAccount) GetIsStartup() bool { + if x != nil { + return x.IsStartup + } + return false +} + +type SubscribeUpdateAccountInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Lamports uint64 `protobuf:"varint,2,opt,name=lamports,proto3" json:"lamports,omitempty"` + Owner []byte `protobuf:"bytes,3,opt,name=owner,proto3" json:"owner,omitempty"` + Executable bool `protobuf:"varint,4,opt,name=executable,proto3" json:"executable,omitempty"` + RentEpoch uint64 `protobuf:"varint,5,opt,name=rent_epoch,json=rentEpoch,proto3" json:"rent_epoch,omitempty"` + Data []byte `protobuf:"bytes,6,opt,name=data,proto3" json:"data,omitempty"` + WriteVersion uint64 `protobuf:"varint,7,opt,name=write_version,json=writeVersion,proto3" json:"write_version,omitempty"` + TxnSignature []byte `protobuf:"bytes,8,opt,name=txn_signature,json=txnSignature,proto3,oneof" json:"txn_signature,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeUpdateAccountInfo) Reset() { + *x = SubscribeUpdateAccountInfo{} + mi := &file_geyser_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeUpdateAccountInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeUpdateAccountInfo) ProtoMessage() {} + +func (x *SubscribeUpdateAccountInfo) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeUpdateAccountInfo.ProtoReflect.Descriptor instead. +func (*SubscribeUpdateAccountInfo) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{14} +} + +func (x *SubscribeUpdateAccountInfo) GetPubkey() []byte { + if x != nil { + return x.Pubkey + } + return nil +} + +func (x *SubscribeUpdateAccountInfo) GetLamports() uint64 { + if x != nil { + return x.Lamports + } + return 0 +} + +func (x *SubscribeUpdateAccountInfo) GetOwner() []byte { + if x != nil { + return x.Owner + } + return nil +} + +func (x *SubscribeUpdateAccountInfo) GetExecutable() bool { + if x != nil { + return x.Executable + } + return false +} + +func (x *SubscribeUpdateAccountInfo) GetRentEpoch() uint64 { + if x != nil { + return x.RentEpoch + } + return 0 +} + +func (x *SubscribeUpdateAccountInfo) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +func (x *SubscribeUpdateAccountInfo) GetWriteVersion() uint64 { + if x != nil { + return x.WriteVersion + } + return 0 +} + +func (x *SubscribeUpdateAccountInfo) GetTxnSignature() []byte { + if x != nil { + return x.TxnSignature + } + return nil +} + +type SubscribeUpdateSlot struct { + state protoimpl.MessageState `protogen:"open.v1"` + Slot uint64 `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty"` + Parent *uint64 `protobuf:"varint,2,opt,name=parent,proto3,oneof" json:"parent,omitempty"` + Status SlotStatus `protobuf:"varint,3,opt,name=status,proto3,enum=geyser.SlotStatus" json:"status,omitempty"` + DeadError *string `protobuf:"bytes,4,opt,name=dead_error,json=deadError,proto3,oneof" json:"dead_error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeUpdateSlot) Reset() { + *x = SubscribeUpdateSlot{} + mi := &file_geyser_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeUpdateSlot) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeUpdateSlot) ProtoMessage() {} + +func (x *SubscribeUpdateSlot) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeUpdateSlot.ProtoReflect.Descriptor instead. +func (*SubscribeUpdateSlot) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{15} +} + +func (x *SubscribeUpdateSlot) GetSlot() uint64 { + if x != nil { + return x.Slot + } + return 0 +} + +func (x *SubscribeUpdateSlot) GetParent() uint64 { + if x != nil && x.Parent != nil { + return *x.Parent + } + return 0 +} + +func (x *SubscribeUpdateSlot) GetStatus() SlotStatus { + if x != nil { + return x.Status + } + return SlotStatus_SLOT_PROCESSED +} + +func (x *SubscribeUpdateSlot) GetDeadError() string { + if x != nil && x.DeadError != nil { + return *x.DeadError + } + return "" +} + +type SubscribeUpdateTransaction struct { + state protoimpl.MessageState `protogen:"open.v1"` + Transaction *SubscribeUpdateTransactionInfo `protobuf:"bytes,1,opt,name=transaction,proto3" json:"transaction,omitempty"` + Slot uint64 `protobuf:"varint,2,opt,name=slot,proto3" json:"slot,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeUpdateTransaction) Reset() { + *x = SubscribeUpdateTransaction{} + mi := &file_geyser_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeUpdateTransaction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeUpdateTransaction) ProtoMessage() {} + +func (x *SubscribeUpdateTransaction) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeUpdateTransaction.ProtoReflect.Descriptor instead. +func (*SubscribeUpdateTransaction) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{16} +} + +func (x *SubscribeUpdateTransaction) GetTransaction() *SubscribeUpdateTransactionInfo { + if x != nil { + return x.Transaction + } + return nil +} + +func (x *SubscribeUpdateTransaction) GetSlot() uint64 { + if x != nil { + return x.Slot + } + return 0 +} + +type SubscribeUpdateTransactionInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` + IsVote bool `protobuf:"varint,2,opt,name=is_vote,json=isVote,proto3" json:"is_vote,omitempty"` + Transaction *Transaction `protobuf:"bytes,3,opt,name=transaction,proto3" json:"transaction,omitempty"` + Meta *TransactionStatusMeta `protobuf:"bytes,4,opt,name=meta,proto3" json:"meta,omitempty"` + Index uint64 `protobuf:"varint,5,opt,name=index,proto3" json:"index,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeUpdateTransactionInfo) Reset() { + *x = SubscribeUpdateTransactionInfo{} + mi := &file_geyser_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeUpdateTransactionInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeUpdateTransactionInfo) ProtoMessage() {} + +func (x *SubscribeUpdateTransactionInfo) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeUpdateTransactionInfo.ProtoReflect.Descriptor instead. +func (*SubscribeUpdateTransactionInfo) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{17} +} + +func (x *SubscribeUpdateTransactionInfo) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +func (x *SubscribeUpdateTransactionInfo) GetIsVote() bool { + if x != nil { + return x.IsVote + } + return false +} + +func (x *SubscribeUpdateTransactionInfo) GetTransaction() *Transaction { + if x != nil { + return x.Transaction + } + return nil +} + +func (x *SubscribeUpdateTransactionInfo) GetMeta() *TransactionStatusMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *SubscribeUpdateTransactionInfo) GetIndex() uint64 { + if x != nil { + return x.Index + } + return 0 +} + +type SubscribeUpdateTransactionStatus struct { + state protoimpl.MessageState `protogen:"open.v1"` + Slot uint64 `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` + IsVote bool `protobuf:"varint,3,opt,name=is_vote,json=isVote,proto3" json:"is_vote,omitempty"` + Index uint64 `protobuf:"varint,4,opt,name=index,proto3" json:"index,omitempty"` + Err *TransactionError `protobuf:"bytes,5,opt,name=err,proto3" json:"err,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeUpdateTransactionStatus) Reset() { + *x = SubscribeUpdateTransactionStatus{} + mi := &file_geyser_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeUpdateTransactionStatus) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeUpdateTransactionStatus) ProtoMessage() {} + +func (x *SubscribeUpdateTransactionStatus) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeUpdateTransactionStatus.ProtoReflect.Descriptor instead. +func (*SubscribeUpdateTransactionStatus) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{18} +} + +func (x *SubscribeUpdateTransactionStatus) GetSlot() uint64 { + if x != nil { + return x.Slot + } + return 0 +} + +func (x *SubscribeUpdateTransactionStatus) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +func (x *SubscribeUpdateTransactionStatus) GetIsVote() bool { + if x != nil { + return x.IsVote + } + return false +} + +func (x *SubscribeUpdateTransactionStatus) GetIndex() uint64 { + if x != nil { + return x.Index + } + return 0 +} + +func (x *SubscribeUpdateTransactionStatus) GetErr() *TransactionError { + if x != nil { + return x.Err + } + return nil +} + +type SubscribeUpdateBlock struct { + state protoimpl.MessageState `protogen:"open.v1"` + Slot uint64 `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty"` + Blockhash string `protobuf:"bytes,2,opt,name=blockhash,proto3" json:"blockhash,omitempty"` + Rewards *Rewards `protobuf:"bytes,3,opt,name=rewards,proto3" json:"rewards,omitempty"` + BlockTime *UnixTimestamp `protobuf:"bytes,4,opt,name=block_time,json=blockTime,proto3" json:"block_time,omitempty"` + BlockHeight *BlockHeight `protobuf:"bytes,5,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` + ParentSlot uint64 `protobuf:"varint,7,opt,name=parent_slot,json=parentSlot,proto3" json:"parent_slot,omitempty"` + ParentBlockhash string `protobuf:"bytes,8,opt,name=parent_blockhash,json=parentBlockhash,proto3" json:"parent_blockhash,omitempty"` + ExecutedTransactionCount uint64 `protobuf:"varint,9,opt,name=executed_transaction_count,json=executedTransactionCount,proto3" json:"executed_transaction_count,omitempty"` + Transactions []*SubscribeUpdateTransactionInfo `protobuf:"bytes,6,rep,name=transactions,proto3" json:"transactions,omitempty"` + UpdatedAccountCount uint64 `protobuf:"varint,10,opt,name=updated_account_count,json=updatedAccountCount,proto3" json:"updated_account_count,omitempty"` + Accounts []*SubscribeUpdateAccountInfo `protobuf:"bytes,11,rep,name=accounts,proto3" json:"accounts,omitempty"` + EntriesCount uint64 `protobuf:"varint,12,opt,name=entries_count,json=entriesCount,proto3" json:"entries_count,omitempty"` + Entries []*SubscribeUpdateEntry `protobuf:"bytes,13,rep,name=entries,proto3" json:"entries,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeUpdateBlock) Reset() { + *x = SubscribeUpdateBlock{} + mi := &file_geyser_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeUpdateBlock) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeUpdateBlock) ProtoMessage() {} + +func (x *SubscribeUpdateBlock) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeUpdateBlock.ProtoReflect.Descriptor instead. +func (*SubscribeUpdateBlock) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{19} +} + +func (x *SubscribeUpdateBlock) GetSlot() uint64 { + if x != nil { + return x.Slot + } + return 0 +} + +func (x *SubscribeUpdateBlock) GetBlockhash() string { + if x != nil { + return x.Blockhash + } + return "" +} + +func (x *SubscribeUpdateBlock) GetRewards() *Rewards { + if x != nil { + return x.Rewards + } + return nil +} + +func (x *SubscribeUpdateBlock) GetBlockTime() *UnixTimestamp { + if x != nil { + return x.BlockTime + } + return nil +} + +func (x *SubscribeUpdateBlock) GetBlockHeight() *BlockHeight { + if x != nil { + return x.BlockHeight + } + return nil +} + +func (x *SubscribeUpdateBlock) GetParentSlot() uint64 { + if x != nil { + return x.ParentSlot + } + return 0 +} + +func (x *SubscribeUpdateBlock) GetParentBlockhash() string { + if x != nil { + return x.ParentBlockhash + } + return "" +} + +func (x *SubscribeUpdateBlock) GetExecutedTransactionCount() uint64 { + if x != nil { + return x.ExecutedTransactionCount + } + return 0 +} + +func (x *SubscribeUpdateBlock) GetTransactions() []*SubscribeUpdateTransactionInfo { + if x != nil { + return x.Transactions + } + return nil +} + +func (x *SubscribeUpdateBlock) GetUpdatedAccountCount() uint64 { + if x != nil { + return x.UpdatedAccountCount + } + return 0 +} + +func (x *SubscribeUpdateBlock) GetAccounts() []*SubscribeUpdateAccountInfo { + if x != nil { + return x.Accounts + } + return nil +} + +func (x *SubscribeUpdateBlock) GetEntriesCount() uint64 { + if x != nil { + return x.EntriesCount + } + return 0 +} + +func (x *SubscribeUpdateBlock) GetEntries() []*SubscribeUpdateEntry { + if x != nil { + return x.Entries + } + return nil +} + +type SubscribeUpdateBlockMeta struct { + state protoimpl.MessageState `protogen:"open.v1"` + Slot uint64 `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty"` + Blockhash string `protobuf:"bytes,2,opt,name=blockhash,proto3" json:"blockhash,omitempty"` + Rewards *Rewards `protobuf:"bytes,3,opt,name=rewards,proto3" json:"rewards,omitempty"` + BlockTime *UnixTimestamp `protobuf:"bytes,4,opt,name=block_time,json=blockTime,proto3" json:"block_time,omitempty"` + BlockHeight *BlockHeight `protobuf:"bytes,5,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` + ParentSlot uint64 `protobuf:"varint,6,opt,name=parent_slot,json=parentSlot,proto3" json:"parent_slot,omitempty"` + ParentBlockhash string `protobuf:"bytes,7,opt,name=parent_blockhash,json=parentBlockhash,proto3" json:"parent_blockhash,omitempty"` + ExecutedTransactionCount uint64 `protobuf:"varint,8,opt,name=executed_transaction_count,json=executedTransactionCount,proto3" json:"executed_transaction_count,omitempty"` + EntriesCount uint64 `protobuf:"varint,9,opt,name=entries_count,json=entriesCount,proto3" json:"entries_count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeUpdateBlockMeta) Reset() { + *x = SubscribeUpdateBlockMeta{} + mi := &file_geyser_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeUpdateBlockMeta) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeUpdateBlockMeta) ProtoMessage() {} + +func (x *SubscribeUpdateBlockMeta) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeUpdateBlockMeta.ProtoReflect.Descriptor instead. +func (*SubscribeUpdateBlockMeta) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{20} +} + +func (x *SubscribeUpdateBlockMeta) GetSlot() uint64 { + if x != nil { + return x.Slot + } + return 0 +} + +func (x *SubscribeUpdateBlockMeta) GetBlockhash() string { + if x != nil { + return x.Blockhash + } + return "" +} + +func (x *SubscribeUpdateBlockMeta) GetRewards() *Rewards { + if x != nil { + return x.Rewards + } + return nil +} + +func (x *SubscribeUpdateBlockMeta) GetBlockTime() *UnixTimestamp { + if x != nil { + return x.BlockTime + } + return nil +} + +func (x *SubscribeUpdateBlockMeta) GetBlockHeight() *BlockHeight { + if x != nil { + return x.BlockHeight + } + return nil +} + +func (x *SubscribeUpdateBlockMeta) GetParentSlot() uint64 { + if x != nil { + return x.ParentSlot + } + return 0 +} + +func (x *SubscribeUpdateBlockMeta) GetParentBlockhash() string { + if x != nil { + return x.ParentBlockhash + } + return "" +} + +func (x *SubscribeUpdateBlockMeta) GetExecutedTransactionCount() uint64 { + if x != nil { + return x.ExecutedTransactionCount + } + return 0 +} + +func (x *SubscribeUpdateBlockMeta) GetEntriesCount() uint64 { + if x != nil { + return x.EntriesCount + } + return 0 +} + +type SubscribeUpdateEntry struct { + state protoimpl.MessageState `protogen:"open.v1"` + Slot uint64 `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty"` + Index uint64 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` + NumHashes uint64 `protobuf:"varint,3,opt,name=num_hashes,json=numHashes,proto3" json:"num_hashes,omitempty"` + Hash []byte `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"` + ExecutedTransactionCount uint64 `protobuf:"varint,5,opt,name=executed_transaction_count,json=executedTransactionCount,proto3" json:"executed_transaction_count,omitempty"` + StartingTransactionIndex uint64 `protobuf:"varint,6,opt,name=starting_transaction_index,json=startingTransactionIndex,proto3" json:"starting_transaction_index,omitempty"` // added in v1.18, for solana 1.17 value is always 0 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeUpdateEntry) Reset() { + *x = SubscribeUpdateEntry{} + mi := &file_geyser_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeUpdateEntry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeUpdateEntry) ProtoMessage() {} + +func (x *SubscribeUpdateEntry) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeUpdateEntry.ProtoReflect.Descriptor instead. +func (*SubscribeUpdateEntry) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{21} +} + +func (x *SubscribeUpdateEntry) GetSlot() uint64 { + if x != nil { + return x.Slot + } + return 0 +} + +func (x *SubscribeUpdateEntry) GetIndex() uint64 { + if x != nil { + return x.Index + } + return 0 +} + +func (x *SubscribeUpdateEntry) GetNumHashes() uint64 { + if x != nil { + return x.NumHashes + } + return 0 +} + +func (x *SubscribeUpdateEntry) GetHash() []byte { + if x != nil { + return x.Hash + } + return nil +} + +func (x *SubscribeUpdateEntry) GetExecutedTransactionCount() uint64 { + if x != nil { + return x.ExecutedTransactionCount + } + return 0 +} + +func (x *SubscribeUpdateEntry) GetStartingTransactionIndex() uint64 { + if x != nil { + return x.StartingTransactionIndex + } + return 0 +} + +type SubscribeUpdatePing struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeUpdatePing) Reset() { + *x = SubscribeUpdatePing{} + mi := &file_geyser_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeUpdatePing) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeUpdatePing) ProtoMessage() {} + +func (x *SubscribeUpdatePing) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[22] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeUpdatePing.ProtoReflect.Descriptor instead. +func (*SubscribeUpdatePing) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{22} +} + +type SubscribeUpdatePong struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeUpdatePong) Reset() { + *x = SubscribeUpdatePong{} + mi := &file_geyser_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeUpdatePong) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeUpdatePong) ProtoMessage() {} + +func (x *SubscribeUpdatePong) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[23] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeUpdatePong.ProtoReflect.Descriptor instead. +func (*SubscribeUpdatePong) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{23} +} + +func (x *SubscribeUpdatePong) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +type PingRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Count int32 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PingRequest) Reset() { + *x = PingRequest{} + mi := &file_geyser_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PingRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingRequest) ProtoMessage() {} + +func (x *PingRequest) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[24] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingRequest.ProtoReflect.Descriptor instead. +func (*PingRequest) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{24} +} + +func (x *PingRequest) GetCount() int32 { + if x != nil { + return x.Count + } + return 0 +} + +type PongResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Count int32 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PongResponse) Reset() { + *x = PongResponse{} + mi := &file_geyser_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PongResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PongResponse) ProtoMessage() {} + +func (x *PongResponse) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[25] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PongResponse.ProtoReflect.Descriptor instead. +func (*PongResponse) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{25} +} + +func (x *PongResponse) GetCount() int32 { + if x != nil { + return x.Count + } + return 0 +} + +type GetLatestBlockhashRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Commitment *CommitmentLevel `protobuf:"varint,1,opt,name=commitment,proto3,enum=geyser.CommitmentLevel,oneof" json:"commitment,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetLatestBlockhashRequest) Reset() { + *x = GetLatestBlockhashRequest{} + mi := &file_geyser_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetLatestBlockhashRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetLatestBlockhashRequest) ProtoMessage() {} + +func (x *GetLatestBlockhashRequest) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[26] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetLatestBlockhashRequest.ProtoReflect.Descriptor instead. +func (*GetLatestBlockhashRequest) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{26} +} + +func (x *GetLatestBlockhashRequest) GetCommitment() CommitmentLevel { + if x != nil && x.Commitment != nil { + return *x.Commitment + } + return CommitmentLevel_PROCESSED +} + +type GetLatestBlockhashResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Slot uint64 `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty"` + Blockhash string `protobuf:"bytes,2,opt,name=blockhash,proto3" json:"blockhash,omitempty"` + LastValidBlockHeight uint64 `protobuf:"varint,3,opt,name=last_valid_block_height,json=lastValidBlockHeight,proto3" json:"last_valid_block_height,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetLatestBlockhashResponse) Reset() { + *x = GetLatestBlockhashResponse{} + mi := &file_geyser_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetLatestBlockhashResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetLatestBlockhashResponse) ProtoMessage() {} + +func (x *GetLatestBlockhashResponse) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[27] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetLatestBlockhashResponse.ProtoReflect.Descriptor instead. +func (*GetLatestBlockhashResponse) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{27} +} + +func (x *GetLatestBlockhashResponse) GetSlot() uint64 { + if x != nil { + return x.Slot + } + return 0 +} + +func (x *GetLatestBlockhashResponse) GetBlockhash() string { + if x != nil { + return x.Blockhash + } + return "" +} + +func (x *GetLatestBlockhashResponse) GetLastValidBlockHeight() uint64 { + if x != nil { + return x.LastValidBlockHeight + } + return 0 +} + +type GetBlockHeightRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Commitment *CommitmentLevel `protobuf:"varint,1,opt,name=commitment,proto3,enum=geyser.CommitmentLevel,oneof" json:"commitment,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetBlockHeightRequest) Reset() { + *x = GetBlockHeightRequest{} + mi := &file_geyser_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetBlockHeightRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBlockHeightRequest) ProtoMessage() {} + +func (x *GetBlockHeightRequest) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[28] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetBlockHeightRequest.ProtoReflect.Descriptor instead. +func (*GetBlockHeightRequest) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{28} +} + +func (x *GetBlockHeightRequest) GetCommitment() CommitmentLevel { + if x != nil && x.Commitment != nil { + return *x.Commitment + } + return CommitmentLevel_PROCESSED +} + +type GetBlockHeightResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + BlockHeight uint64 `protobuf:"varint,1,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetBlockHeightResponse) Reset() { + *x = GetBlockHeightResponse{} + mi := &file_geyser_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetBlockHeightResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBlockHeightResponse) ProtoMessage() {} + +func (x *GetBlockHeightResponse) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[29] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetBlockHeightResponse.ProtoReflect.Descriptor instead. +func (*GetBlockHeightResponse) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{29} +} + +func (x *GetBlockHeightResponse) GetBlockHeight() uint64 { + if x != nil { + return x.BlockHeight + } + return 0 +} + +type GetSlotRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Commitment *CommitmentLevel `protobuf:"varint,1,opt,name=commitment,proto3,enum=geyser.CommitmentLevel,oneof" json:"commitment,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetSlotRequest) Reset() { + *x = GetSlotRequest{} + mi := &file_geyser_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetSlotRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSlotRequest) ProtoMessage() {} + +func (x *GetSlotRequest) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[30] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSlotRequest.ProtoReflect.Descriptor instead. +func (*GetSlotRequest) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{30} +} + +func (x *GetSlotRequest) GetCommitment() CommitmentLevel { + if x != nil && x.Commitment != nil { + return *x.Commitment + } + return CommitmentLevel_PROCESSED +} + +type GetSlotResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Slot uint64 `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetSlotResponse) Reset() { + *x = GetSlotResponse{} + mi := &file_geyser_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetSlotResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSlotResponse) ProtoMessage() {} + +func (x *GetSlotResponse) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[31] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSlotResponse.ProtoReflect.Descriptor instead. +func (*GetSlotResponse) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{31} +} + +func (x *GetSlotResponse) GetSlot() uint64 { + if x != nil { + return x.Slot + } + return 0 +} + +type GetVersionRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetVersionRequest) Reset() { + *x = GetVersionRequest{} + mi := &file_geyser_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetVersionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetVersionRequest) ProtoMessage() {} + +func (x *GetVersionRequest) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[32] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetVersionRequest.ProtoReflect.Descriptor instead. +func (*GetVersionRequest) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{32} +} + +type GetVersionResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetVersionResponse) Reset() { + *x = GetVersionResponse{} + mi := &file_geyser_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetVersionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetVersionResponse) ProtoMessage() {} + +func (x *GetVersionResponse) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[33] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetVersionResponse.ProtoReflect.Descriptor instead. +func (*GetVersionResponse) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{33} +} + +func (x *GetVersionResponse) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +type IsBlockhashValidRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Blockhash string `protobuf:"bytes,1,opt,name=blockhash,proto3" json:"blockhash,omitempty"` + Commitment *CommitmentLevel `protobuf:"varint,2,opt,name=commitment,proto3,enum=geyser.CommitmentLevel,oneof" json:"commitment,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *IsBlockhashValidRequest) Reset() { + *x = IsBlockhashValidRequest{} + mi := &file_geyser_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *IsBlockhashValidRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IsBlockhashValidRequest) ProtoMessage() {} + +func (x *IsBlockhashValidRequest) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[34] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IsBlockhashValidRequest.ProtoReflect.Descriptor instead. +func (*IsBlockhashValidRequest) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{34} +} + +func (x *IsBlockhashValidRequest) GetBlockhash() string { + if x != nil { + return x.Blockhash + } + return "" +} + +func (x *IsBlockhashValidRequest) GetCommitment() CommitmentLevel { + if x != nil && x.Commitment != nil { + return *x.Commitment + } + return CommitmentLevel_PROCESSED +} + +type IsBlockhashValidResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Slot uint64 `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty"` + Valid bool `protobuf:"varint,2,opt,name=valid,proto3" json:"valid,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *IsBlockhashValidResponse) Reset() { + *x = IsBlockhashValidResponse{} + mi := &file_geyser_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *IsBlockhashValidResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IsBlockhashValidResponse) ProtoMessage() {} + +func (x *IsBlockhashValidResponse) ProtoReflect() protoreflect.Message { + mi := &file_geyser_proto_msgTypes[35] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IsBlockhashValidResponse.ProtoReflect.Descriptor instead. +func (*IsBlockhashValidResponse) Descriptor() ([]byte, []int) { + return file_geyser_proto_rawDescGZIP(), []int{35} +} + +func (x *IsBlockhashValidResponse) GetSlot() uint64 { + if x != nil { + return x.Slot + } + return 0 +} + +func (x *IsBlockhashValidResponse) GetValid() bool { + if x != nil { + return x.Valid + } + return false +} + +var File_geyser_proto protoreflect.FileDescriptor + +const file_geyser_proto_rawDesc = "" + + "\n" + + "\fgeyser.proto\x12\x06geyser\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x14solana-storage.proto\"\xed\v\n" + + "\x10SubscribeRequest\x12B\n" + + "\baccounts\x18\x01 \x03(\v2&.geyser.SubscribeRequest.AccountsEntryR\baccounts\x129\n" + + "\x05slots\x18\x02 \x03(\v2#.geyser.SubscribeRequest.SlotsEntryR\x05slots\x12N\n" + + "\ftransactions\x18\x03 \x03(\v2*.geyser.SubscribeRequest.TransactionsEntryR\ftransactions\x12a\n" + + "\x13transactions_status\x18\n" + + " \x03(\v20.geyser.SubscribeRequest.TransactionsStatusEntryR\x12transactionsStatus\x12<\n" + + "\x06blocks\x18\x04 \x03(\v2$.geyser.SubscribeRequest.BlocksEntryR\x06blocks\x12I\n" + + "\vblocks_meta\x18\x05 \x03(\v2(.geyser.SubscribeRequest.BlocksMetaEntryR\n" + + "blocksMeta\x129\n" + + "\x05entry\x18\b \x03(\v2#.geyser.SubscribeRequest.EntryEntryR\x05entry\x12<\n" + + "\n" + + "commitment\x18\x06 \x01(\x0e2\x17.geyser.CommitmentLevelH\x00R\n" + + "commitment\x88\x01\x01\x12Y\n" + + "\x13accounts_data_slice\x18\a \x03(\v2).geyser.SubscribeRequestAccountsDataSliceR\x11accountsDataSlice\x125\n" + + "\x04ping\x18\t \x01(\v2\x1c.geyser.SubscribeRequestPingH\x01R\x04ping\x88\x01\x01\x12 \n" + + "\tfrom_slot\x18\v \x01(\x04H\x02R\bfromSlot\x88\x01\x01\x1ac\n" + + "\rAccountsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12<\n" + + "\x05value\x18\x02 \x01(\v2&.geyser.SubscribeRequestFilterAccountsR\x05value:\x028\x01\x1a]\n" + + "\n" + + "SlotsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x129\n" + + "\x05value\x18\x02 \x01(\v2#.geyser.SubscribeRequestFilterSlotsR\x05value:\x028\x01\x1ak\n" + + "\x11TransactionsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12@\n" + + "\x05value\x18\x02 \x01(\v2*.geyser.SubscribeRequestFilterTransactionsR\x05value:\x028\x01\x1aq\n" + + "\x17TransactionsStatusEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12@\n" + + "\x05value\x18\x02 \x01(\v2*.geyser.SubscribeRequestFilterTransactionsR\x05value:\x028\x01\x1a_\n" + + "\vBlocksEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12:\n" + + "\x05value\x18\x02 \x01(\v2$.geyser.SubscribeRequestFilterBlocksR\x05value:\x028\x01\x1ag\n" + + "\x0fBlocksMetaEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12>\n" + + "\x05value\x18\x02 \x01(\v2(.geyser.SubscribeRequestFilterBlocksMetaR\x05value:\x028\x01\x1a]\n" + + "\n" + + "EntryEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x129\n" + + "\x05value\x18\x02 \x01(\v2#.geyser.SubscribeRequestFilterEntryR\x05value:\x028\x01B\r\n" + + "\v_commitmentB\a\n" + + "\x05_pingB\f\n" + + "\n" + + "_from_slot\"\xee\x01\n" + + "\x1eSubscribeRequestFilterAccounts\x12\x18\n" + + "\aaccount\x18\x02 \x03(\tR\aaccount\x12\x14\n" + + "\x05owner\x18\x03 \x03(\tR\x05owner\x12F\n" + + "\afilters\x18\x04 \x03(\v2,.geyser.SubscribeRequestFilterAccountsFilterR\afilters\x129\n" + + "\x16nonempty_txn_signature\x18\x05 \x01(\bH\x00R\x14nonemptyTxnSignature\x88\x01\x01B\x19\n" + + "\x17_nonempty_txn_signature\"\xa2\x02\n" + + "$SubscribeRequestFilterAccountsFilter\x12L\n" + + "\x06memcmp\x18\x01 \x01(\v22.geyser.SubscribeRequestFilterAccountsFilterMemcmpH\x00R\x06memcmp\x12\x1c\n" + + "\bdatasize\x18\x02 \x01(\x04H\x00R\bdatasize\x120\n" + + "\x13token_account_state\x18\x03 \x01(\bH\x00R\x11tokenAccountState\x12R\n" + + "\blamports\x18\x04 \x01(\v24.geyser.SubscribeRequestFilterAccountsFilterLamportsH\x00R\blamportsB\b\n" + + "\x06filter\"\x98\x01\n" + + "*SubscribeRequestFilterAccountsFilterMemcmp\x12\x16\n" + + "\x06offset\x18\x01 \x01(\x04R\x06offset\x12\x16\n" + + "\x05bytes\x18\x02 \x01(\fH\x00R\x05bytes\x12\x18\n" + + "\x06base58\x18\x03 \x01(\tH\x00R\x06base58\x12\x18\n" + + "\x06base64\x18\x04 \x01(\tH\x00R\x06base64B\x06\n" + + "\x04data\"}\n" + + ",SubscribeRequestFilterAccountsFilterLamports\x12\x10\n" + + "\x02eq\x18\x01 \x01(\x04H\x00R\x02eq\x12\x10\n" + + "\x02ne\x18\x02 \x01(\x04H\x00R\x02ne\x12\x10\n" + + "\x02lt\x18\x03 \x01(\x04H\x00R\x02lt\x12\x10\n" + + "\x02gt\x18\x04 \x01(\x04H\x00R\x02gtB\x05\n" + + "\x03cmp\"\xb5\x01\n" + + "\x1bSubscribeRequestFilterSlots\x125\n" + + "\x14filter_by_commitment\x18\x01 \x01(\bH\x00R\x12filterByCommitment\x88\x01\x01\x120\n" + + "\x11interslot_updates\x18\x02 \x01(\bH\x01R\x10interslotUpdates\x88\x01\x01B\x17\n" + + "\x15_filter_by_commitmentB\x14\n" + + "\x12_interslot_updates\"\x9c\x02\n" + + "\"SubscribeRequestFilterTransactions\x12\x17\n" + + "\x04vote\x18\x01 \x01(\bH\x00R\x04vote\x88\x01\x01\x12\x1b\n" + + "\x06failed\x18\x02 \x01(\bH\x01R\x06failed\x88\x01\x01\x12!\n" + + "\tsignature\x18\x05 \x01(\tH\x02R\tsignature\x88\x01\x01\x12'\n" + + "\x0faccount_include\x18\x03 \x03(\tR\x0eaccountInclude\x12'\n" + + "\x0faccount_exclude\x18\x04 \x03(\tR\x0eaccountExclude\x12)\n" + + "\x10account_required\x18\x06 \x03(\tR\x0faccountRequiredB\a\n" + + "\x05_voteB\t\n" + + "\a_failedB\f\n" + + "\n" + + "_signature\"\x9f\x02\n" + + "\x1cSubscribeRequestFilterBlocks\x12'\n" + + "\x0faccount_include\x18\x01 \x03(\tR\x0eaccountInclude\x126\n" + + "\x14include_transactions\x18\x02 \x01(\bH\x00R\x13includeTransactions\x88\x01\x01\x12.\n" + + "\x10include_accounts\x18\x03 \x01(\bH\x01R\x0fincludeAccounts\x88\x01\x01\x12,\n" + + "\x0finclude_entries\x18\x04 \x01(\bH\x02R\x0eincludeEntries\x88\x01\x01B\x17\n" + + "\x15_include_transactionsB\x13\n" + + "\x11_include_accountsB\x12\n" + + "\x10_include_entries\"\"\n" + + " SubscribeRequestFilterBlocksMeta\"\x1d\n" + + "\x1bSubscribeRequestFilterEntry\"S\n" + + "!SubscribeRequestAccountsDataSlice\x12\x16\n" + + "\x06offset\x18\x01 \x01(\x04R\x06offset\x12\x16\n" + + "\x06length\x18\x02 \x01(\x04R\x06length\"&\n" + + "\x14SubscribeRequestPing\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x05R\x02id\"\x9d\x05\n" + + "\x0fSubscribeUpdate\x12\x18\n" + + "\afilters\x18\x01 \x03(\tR\afilters\x12:\n" + + "\aaccount\x18\x02 \x01(\v2\x1e.geyser.SubscribeUpdateAccountH\x00R\aaccount\x121\n" + + "\x04slot\x18\x03 \x01(\v2\x1b.geyser.SubscribeUpdateSlotH\x00R\x04slot\x12F\n" + + "\vtransaction\x18\x04 \x01(\v2\".geyser.SubscribeUpdateTransactionH\x00R\vtransaction\x12Y\n" + + "\x12transaction_status\x18\n" + + " \x01(\v2(.geyser.SubscribeUpdateTransactionStatusH\x00R\x11transactionStatus\x124\n" + + "\x05block\x18\x05 \x01(\v2\x1c.geyser.SubscribeUpdateBlockH\x00R\x05block\x121\n" + + "\x04ping\x18\x06 \x01(\v2\x1b.geyser.SubscribeUpdatePingH\x00R\x04ping\x121\n" + + "\x04pong\x18\t \x01(\v2\x1b.geyser.SubscribeUpdatePongH\x00R\x04pong\x12A\n" + + "\n" + + "block_meta\x18\a \x01(\v2 .geyser.SubscribeUpdateBlockMetaH\x00R\tblockMeta\x124\n" + + "\x05entry\x18\b \x01(\v2\x1c.geyser.SubscribeUpdateEntryH\x00R\x05entry\x129\n" + + "\n" + + "created_at\x18\v \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAtB\x0e\n" + + "\fupdate_oneof\"\x89\x01\n" + + "\x16SubscribeUpdateAccount\x12<\n" + + "\aaccount\x18\x01 \x01(\v2\".geyser.SubscribeUpdateAccountInfoR\aaccount\x12\x12\n" + + "\x04slot\x18\x02 \x01(\x04R\x04slot\x12\x1d\n" + + "\n" + + "is_startup\x18\x03 \x01(\bR\tisStartup\"\x9a\x02\n" + + "\x1aSubscribeUpdateAccountInfo\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\fR\x06pubkey\x12\x1a\n" + + "\blamports\x18\x02 \x01(\x04R\blamports\x12\x14\n" + + "\x05owner\x18\x03 \x01(\fR\x05owner\x12\x1e\n" + + "\n" + + "executable\x18\x04 \x01(\bR\n" + + "executable\x12\x1d\n" + + "\n" + + "rent_epoch\x18\x05 \x01(\x04R\trentEpoch\x12\x12\n" + + "\x04data\x18\x06 \x01(\fR\x04data\x12#\n" + + "\rwrite_version\x18\a \x01(\x04R\fwriteVersion\x12(\n" + + "\rtxn_signature\x18\b \x01(\fH\x00R\ftxnSignature\x88\x01\x01B\x10\n" + + "\x0e_txn_signature\"\xb0\x01\n" + + "\x13SubscribeUpdateSlot\x12\x12\n" + + "\x04slot\x18\x01 \x01(\x04R\x04slot\x12\x1b\n" + + "\x06parent\x18\x02 \x01(\x04H\x00R\x06parent\x88\x01\x01\x12*\n" + + "\x06status\x18\x03 \x01(\x0e2\x12.geyser.SlotStatusR\x06status\x12\"\n" + + "\n" + + "dead_error\x18\x04 \x01(\tH\x01R\tdeadError\x88\x01\x01B\t\n" + + "\a_parentB\r\n" + + "\v_dead_error\"z\n" + + "\x1aSubscribeUpdateTransaction\x12H\n" + + "\vtransaction\x18\x01 \x01(\v2&.geyser.SubscribeUpdateTransactionInfoR\vtransaction\x12\x12\n" + + "\x04slot\x18\x02 \x01(\x04R\x04slot\"\x85\x02\n" + + "\x1eSubscribeUpdateTransactionInfo\x12\x1c\n" + + "\tsignature\x18\x01 \x01(\fR\tsignature\x12\x17\n" + + "\ais_vote\x18\x02 \x01(\bR\x06isVote\x12L\n" + + "\vtransaction\x18\x03 \x01(\v2*.solana.storage.ConfirmedBlock.TransactionR\vtransaction\x12H\n" + + "\x04meta\x18\x04 \x01(\v24.solana.storage.ConfirmedBlock.TransactionStatusMetaR\x04meta\x12\x14\n" + + "\x05index\x18\x05 \x01(\x04R\x05index\"\xc6\x01\n" + + " SubscribeUpdateTransactionStatus\x12\x12\n" + + "\x04slot\x18\x01 \x01(\x04R\x04slot\x12\x1c\n" + + "\tsignature\x18\x02 \x01(\fR\tsignature\x12\x17\n" + + "\ais_vote\x18\x03 \x01(\bR\x06isVote\x12\x14\n" + + "\x05index\x18\x04 \x01(\x04R\x05index\x12A\n" + + "\x03err\x18\x05 \x01(\v2/.solana.storage.ConfirmedBlock.TransactionErrorR\x03err\"\xcd\x05\n" + + "\x14SubscribeUpdateBlock\x12\x12\n" + + "\x04slot\x18\x01 \x01(\x04R\x04slot\x12\x1c\n" + + "\tblockhash\x18\x02 \x01(\tR\tblockhash\x12@\n" + + "\arewards\x18\x03 \x01(\v2&.solana.storage.ConfirmedBlock.RewardsR\arewards\x12K\n" + + "\n" + + "block_time\x18\x04 \x01(\v2,.solana.storage.ConfirmedBlock.UnixTimestampR\tblockTime\x12M\n" + + "\fblock_height\x18\x05 \x01(\v2*.solana.storage.ConfirmedBlock.BlockHeightR\vblockHeight\x12\x1f\n" + + "\vparent_slot\x18\a \x01(\x04R\n" + + "parentSlot\x12)\n" + + "\x10parent_blockhash\x18\b \x01(\tR\x0fparentBlockhash\x12<\n" + + "\x1aexecuted_transaction_count\x18\t \x01(\x04R\x18executedTransactionCount\x12J\n" + + "\ftransactions\x18\x06 \x03(\v2&.geyser.SubscribeUpdateTransactionInfoR\ftransactions\x122\n" + + "\x15updated_account_count\x18\n" + + " \x01(\x04R\x13updatedAccountCount\x12>\n" + + "\baccounts\x18\v \x03(\v2\".geyser.SubscribeUpdateAccountInfoR\baccounts\x12#\n" + + "\rentries_count\x18\f \x01(\x04R\fentriesCount\x126\n" + + "\aentries\x18\r \x03(\v2\x1c.geyser.SubscribeUpdateEntryR\aentries\"\xd9\x03\n" + + "\x18SubscribeUpdateBlockMeta\x12\x12\n" + + "\x04slot\x18\x01 \x01(\x04R\x04slot\x12\x1c\n" + + "\tblockhash\x18\x02 \x01(\tR\tblockhash\x12@\n" + + "\arewards\x18\x03 \x01(\v2&.solana.storage.ConfirmedBlock.RewardsR\arewards\x12K\n" + + "\n" + + "block_time\x18\x04 \x01(\v2,.solana.storage.ConfirmedBlock.UnixTimestampR\tblockTime\x12M\n" + + "\fblock_height\x18\x05 \x01(\v2*.solana.storage.ConfirmedBlock.BlockHeightR\vblockHeight\x12\x1f\n" + + "\vparent_slot\x18\x06 \x01(\x04R\n" + + "parentSlot\x12)\n" + + "\x10parent_blockhash\x18\a \x01(\tR\x0fparentBlockhash\x12<\n" + + "\x1aexecuted_transaction_count\x18\b \x01(\x04R\x18executedTransactionCount\x12#\n" + + "\rentries_count\x18\t \x01(\x04R\fentriesCount\"\xef\x01\n" + + "\x14SubscribeUpdateEntry\x12\x12\n" + + "\x04slot\x18\x01 \x01(\x04R\x04slot\x12\x14\n" + + "\x05index\x18\x02 \x01(\x04R\x05index\x12\x1d\n" + + "\n" + + "num_hashes\x18\x03 \x01(\x04R\tnumHashes\x12\x12\n" + + "\x04hash\x18\x04 \x01(\fR\x04hash\x12<\n" + + "\x1aexecuted_transaction_count\x18\x05 \x01(\x04R\x18executedTransactionCount\x12<\n" + + "\x1astarting_transaction_index\x18\x06 \x01(\x04R\x18startingTransactionIndex\"\x15\n" + + "\x13SubscribeUpdatePing\"%\n" + + "\x13SubscribeUpdatePong\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x05R\x02id\"#\n" + + "\vPingRequest\x12\x14\n" + + "\x05count\x18\x01 \x01(\x05R\x05count\"$\n" + + "\fPongResponse\x12\x14\n" + + "\x05count\x18\x01 \x01(\x05R\x05count\"h\n" + + "\x19GetLatestBlockhashRequest\x12<\n" + + "\n" + + "commitment\x18\x01 \x01(\x0e2\x17.geyser.CommitmentLevelH\x00R\n" + + "commitment\x88\x01\x01B\r\n" + + "\v_commitment\"\x85\x01\n" + + "\x1aGetLatestBlockhashResponse\x12\x12\n" + + "\x04slot\x18\x01 \x01(\x04R\x04slot\x12\x1c\n" + + "\tblockhash\x18\x02 \x01(\tR\tblockhash\x125\n" + + "\x17last_valid_block_height\x18\x03 \x01(\x04R\x14lastValidBlockHeight\"d\n" + + "\x15GetBlockHeightRequest\x12<\n" + + "\n" + + "commitment\x18\x01 \x01(\x0e2\x17.geyser.CommitmentLevelH\x00R\n" + + "commitment\x88\x01\x01B\r\n" + + "\v_commitment\";\n" + + "\x16GetBlockHeightResponse\x12!\n" + + "\fblock_height\x18\x01 \x01(\x04R\vblockHeight\"]\n" + + "\x0eGetSlotRequest\x12<\n" + + "\n" + + "commitment\x18\x01 \x01(\x0e2\x17.geyser.CommitmentLevelH\x00R\n" + + "commitment\x88\x01\x01B\r\n" + + "\v_commitment\"%\n" + + "\x0fGetSlotResponse\x12\x12\n" + + "\x04slot\x18\x01 \x01(\x04R\x04slot\"\x13\n" + + "\x11GetVersionRequest\".\n" + + "\x12GetVersionResponse\x12\x18\n" + + "\aversion\x18\x01 \x01(\tR\aversion\"\x84\x01\n" + + "\x17IsBlockhashValidRequest\x12\x1c\n" + + "\tblockhash\x18\x01 \x01(\tR\tblockhash\x12<\n" + + "\n" + + "commitment\x18\x02 \x01(\x0e2\x17.geyser.CommitmentLevelH\x00R\n" + + "commitment\x88\x01\x01B\r\n" + + "\v_commitment\"D\n" + + "\x18IsBlockhashValidResponse\x12\x12\n" + + "\x04slot\x18\x01 \x01(\x04R\x04slot\x12\x14\n" + + "\x05valid\x18\x02 \x01(\bR\x05valid*>\n" + + "\x0fCommitmentLevel\x12\r\n" + + "\tPROCESSED\x10\x00\x12\r\n" + + "\tCONFIRMED\x10\x01\x12\r\n" + + "\tFINALIZED\x10\x02*\xa1\x01\n" + + "\n" + + "SlotStatus\x12\x12\n" + + "\x0eSLOT_PROCESSED\x10\x00\x12\x12\n" + + "\x0eSLOT_CONFIRMED\x10\x01\x12\x12\n" + + "\x0eSLOT_FINALIZED\x10\x02\x12\x1d\n" + + "\x19SLOT_FIRST_SHRED_RECEIVED\x10\x03\x12\x12\n" + + "\x0eSLOT_COMPLETED\x10\x04\x12\x15\n" + + "\x11SLOT_CREATED_BANK\x10\x05\x12\r\n" + + "\tSLOT_DEAD\x10\x062\x93\x04\n" + + "\x06Geyser\x12D\n" + + "\tSubscribe\x12\x18.geyser.SubscribeRequest\x1a\x17.geyser.SubscribeUpdate\"\x00(\x010\x01\x123\n" + + "\x04Ping\x12\x13.geyser.PingRequest\x1a\x14.geyser.PongResponse\"\x00\x12]\n" + + "\x12GetLatestBlockhash\x12!.geyser.GetLatestBlockhashRequest\x1a\".geyser.GetLatestBlockhashResponse\"\x00\x12Q\n" + + "\x0eGetBlockHeight\x12\x1d.geyser.GetBlockHeightRequest\x1a\x1e.geyser.GetBlockHeightResponse\"\x00\x12<\n" + + "\aGetSlot\x12\x16.geyser.GetSlotRequest\x1a\x17.geyser.GetSlotResponse\"\x00\x12W\n" + + "\x10IsBlockhashValid\x12\x1f.geyser.IsBlockhashValidRequest\x1a .geyser.IsBlockhashValidResponse\"\x00\x12E\n" + + "\n" + + "GetVersion\x12\x19.geyser.GetVersionRequest\x1a\x1a.geyser.GetVersionResponse\"\x00B;Z9github.com/rpcpool/yellowstone-grpc/examples/golang/protoP\x01b\x06proto3" + +var ( + file_geyser_proto_rawDescOnce sync.Once + file_geyser_proto_rawDescData []byte +) + +func file_geyser_proto_rawDescGZIP() []byte { + file_geyser_proto_rawDescOnce.Do(func() { + file_geyser_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_geyser_proto_rawDesc), len(file_geyser_proto_rawDesc))) + }) + return file_geyser_proto_rawDescData +} + +var file_geyser_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_geyser_proto_msgTypes = make([]protoimpl.MessageInfo, 43) +var file_geyser_proto_goTypes = []any{ + (CommitmentLevel)(0), // 0: geyser.CommitmentLevel + (SlotStatus)(0), // 1: geyser.SlotStatus + (*SubscribeRequest)(nil), // 2: geyser.SubscribeRequest + (*SubscribeRequestFilterAccounts)(nil), // 3: geyser.SubscribeRequestFilterAccounts + (*SubscribeRequestFilterAccountsFilter)(nil), // 4: geyser.SubscribeRequestFilterAccountsFilter + (*SubscribeRequestFilterAccountsFilterMemcmp)(nil), // 5: geyser.SubscribeRequestFilterAccountsFilterMemcmp + (*SubscribeRequestFilterAccountsFilterLamports)(nil), // 6: geyser.SubscribeRequestFilterAccountsFilterLamports + (*SubscribeRequestFilterSlots)(nil), // 7: geyser.SubscribeRequestFilterSlots + (*SubscribeRequestFilterTransactions)(nil), // 8: geyser.SubscribeRequestFilterTransactions + (*SubscribeRequestFilterBlocks)(nil), // 9: geyser.SubscribeRequestFilterBlocks + (*SubscribeRequestFilterBlocksMeta)(nil), // 10: geyser.SubscribeRequestFilterBlocksMeta + (*SubscribeRequestFilterEntry)(nil), // 11: geyser.SubscribeRequestFilterEntry + (*SubscribeRequestAccountsDataSlice)(nil), // 12: geyser.SubscribeRequestAccountsDataSlice + (*SubscribeRequestPing)(nil), // 13: geyser.SubscribeRequestPing + (*SubscribeUpdate)(nil), // 14: geyser.SubscribeUpdate + (*SubscribeUpdateAccount)(nil), // 15: geyser.SubscribeUpdateAccount + (*SubscribeUpdateAccountInfo)(nil), // 16: geyser.SubscribeUpdateAccountInfo + (*SubscribeUpdateSlot)(nil), // 17: geyser.SubscribeUpdateSlot + (*SubscribeUpdateTransaction)(nil), // 18: geyser.SubscribeUpdateTransaction + (*SubscribeUpdateTransactionInfo)(nil), // 19: geyser.SubscribeUpdateTransactionInfo + (*SubscribeUpdateTransactionStatus)(nil), // 20: geyser.SubscribeUpdateTransactionStatus + (*SubscribeUpdateBlock)(nil), // 21: geyser.SubscribeUpdateBlock + (*SubscribeUpdateBlockMeta)(nil), // 22: geyser.SubscribeUpdateBlockMeta + (*SubscribeUpdateEntry)(nil), // 23: geyser.SubscribeUpdateEntry + (*SubscribeUpdatePing)(nil), // 24: geyser.SubscribeUpdatePing + (*SubscribeUpdatePong)(nil), // 25: geyser.SubscribeUpdatePong + (*PingRequest)(nil), // 26: geyser.PingRequest + (*PongResponse)(nil), // 27: geyser.PongResponse + (*GetLatestBlockhashRequest)(nil), // 28: geyser.GetLatestBlockhashRequest + (*GetLatestBlockhashResponse)(nil), // 29: geyser.GetLatestBlockhashResponse + (*GetBlockHeightRequest)(nil), // 30: geyser.GetBlockHeightRequest + (*GetBlockHeightResponse)(nil), // 31: geyser.GetBlockHeightResponse + (*GetSlotRequest)(nil), // 32: geyser.GetSlotRequest + (*GetSlotResponse)(nil), // 33: geyser.GetSlotResponse + (*GetVersionRequest)(nil), // 34: geyser.GetVersionRequest + (*GetVersionResponse)(nil), // 35: geyser.GetVersionResponse + (*IsBlockhashValidRequest)(nil), // 36: geyser.IsBlockhashValidRequest + (*IsBlockhashValidResponse)(nil), // 37: geyser.IsBlockhashValidResponse + nil, // 38: geyser.SubscribeRequest.AccountsEntry + nil, // 39: geyser.SubscribeRequest.SlotsEntry + nil, // 40: geyser.SubscribeRequest.TransactionsEntry + nil, // 41: geyser.SubscribeRequest.TransactionsStatusEntry + nil, // 42: geyser.SubscribeRequest.BlocksEntry + nil, // 43: geyser.SubscribeRequest.BlocksMetaEntry + nil, // 44: geyser.SubscribeRequest.EntryEntry + (*timestamppb.Timestamp)(nil), // 45: google.protobuf.Timestamp + (*Transaction)(nil), // 46: solana.storage.ConfirmedBlock.Transaction + (*TransactionStatusMeta)(nil), // 47: solana.storage.ConfirmedBlock.TransactionStatusMeta + (*TransactionError)(nil), // 48: solana.storage.ConfirmedBlock.TransactionError + (*Rewards)(nil), // 49: solana.storage.ConfirmedBlock.Rewards + (*UnixTimestamp)(nil), // 50: solana.storage.ConfirmedBlock.UnixTimestamp + (*BlockHeight)(nil), // 51: solana.storage.ConfirmedBlock.BlockHeight +} +var file_geyser_proto_depIdxs = []int32{ + 38, // 0: geyser.SubscribeRequest.accounts:type_name -> geyser.SubscribeRequest.AccountsEntry + 39, // 1: geyser.SubscribeRequest.slots:type_name -> geyser.SubscribeRequest.SlotsEntry + 40, // 2: geyser.SubscribeRequest.transactions:type_name -> geyser.SubscribeRequest.TransactionsEntry + 41, // 3: geyser.SubscribeRequest.transactions_status:type_name -> geyser.SubscribeRequest.TransactionsStatusEntry + 42, // 4: geyser.SubscribeRequest.blocks:type_name -> geyser.SubscribeRequest.BlocksEntry + 43, // 5: geyser.SubscribeRequest.blocks_meta:type_name -> geyser.SubscribeRequest.BlocksMetaEntry + 44, // 6: geyser.SubscribeRequest.entry:type_name -> geyser.SubscribeRequest.EntryEntry + 0, // 7: geyser.SubscribeRequest.commitment:type_name -> geyser.CommitmentLevel + 12, // 8: geyser.SubscribeRequest.accounts_data_slice:type_name -> geyser.SubscribeRequestAccountsDataSlice + 13, // 9: geyser.SubscribeRequest.ping:type_name -> geyser.SubscribeRequestPing + 4, // 10: geyser.SubscribeRequestFilterAccounts.filters:type_name -> geyser.SubscribeRequestFilterAccountsFilter + 5, // 11: geyser.SubscribeRequestFilterAccountsFilter.memcmp:type_name -> geyser.SubscribeRequestFilterAccountsFilterMemcmp + 6, // 12: geyser.SubscribeRequestFilterAccountsFilter.lamports:type_name -> geyser.SubscribeRequestFilterAccountsFilterLamports + 15, // 13: geyser.SubscribeUpdate.account:type_name -> geyser.SubscribeUpdateAccount + 17, // 14: geyser.SubscribeUpdate.slot:type_name -> geyser.SubscribeUpdateSlot + 18, // 15: geyser.SubscribeUpdate.transaction:type_name -> geyser.SubscribeUpdateTransaction + 20, // 16: geyser.SubscribeUpdate.transaction_status:type_name -> geyser.SubscribeUpdateTransactionStatus + 21, // 17: geyser.SubscribeUpdate.block:type_name -> geyser.SubscribeUpdateBlock + 24, // 18: geyser.SubscribeUpdate.ping:type_name -> geyser.SubscribeUpdatePing + 25, // 19: geyser.SubscribeUpdate.pong:type_name -> geyser.SubscribeUpdatePong + 22, // 20: geyser.SubscribeUpdate.block_meta:type_name -> geyser.SubscribeUpdateBlockMeta + 23, // 21: geyser.SubscribeUpdate.entry:type_name -> geyser.SubscribeUpdateEntry + 45, // 22: geyser.SubscribeUpdate.created_at:type_name -> google.protobuf.Timestamp + 16, // 23: geyser.SubscribeUpdateAccount.account:type_name -> geyser.SubscribeUpdateAccountInfo + 1, // 24: geyser.SubscribeUpdateSlot.status:type_name -> geyser.SlotStatus + 19, // 25: geyser.SubscribeUpdateTransaction.transaction:type_name -> geyser.SubscribeUpdateTransactionInfo + 46, // 26: geyser.SubscribeUpdateTransactionInfo.transaction:type_name -> solana.storage.ConfirmedBlock.Transaction + 47, // 27: geyser.SubscribeUpdateTransactionInfo.meta:type_name -> solana.storage.ConfirmedBlock.TransactionStatusMeta + 48, // 28: geyser.SubscribeUpdateTransactionStatus.err:type_name -> solana.storage.ConfirmedBlock.TransactionError + 49, // 29: geyser.SubscribeUpdateBlock.rewards:type_name -> solana.storage.ConfirmedBlock.Rewards + 50, // 30: geyser.SubscribeUpdateBlock.block_time:type_name -> solana.storage.ConfirmedBlock.UnixTimestamp + 51, // 31: geyser.SubscribeUpdateBlock.block_height:type_name -> solana.storage.ConfirmedBlock.BlockHeight + 19, // 32: geyser.SubscribeUpdateBlock.transactions:type_name -> geyser.SubscribeUpdateTransactionInfo + 16, // 33: geyser.SubscribeUpdateBlock.accounts:type_name -> geyser.SubscribeUpdateAccountInfo + 23, // 34: geyser.SubscribeUpdateBlock.entries:type_name -> geyser.SubscribeUpdateEntry + 49, // 35: geyser.SubscribeUpdateBlockMeta.rewards:type_name -> solana.storage.ConfirmedBlock.Rewards + 50, // 36: geyser.SubscribeUpdateBlockMeta.block_time:type_name -> solana.storage.ConfirmedBlock.UnixTimestamp + 51, // 37: geyser.SubscribeUpdateBlockMeta.block_height:type_name -> solana.storage.ConfirmedBlock.BlockHeight + 0, // 38: geyser.GetLatestBlockhashRequest.commitment:type_name -> geyser.CommitmentLevel + 0, // 39: geyser.GetBlockHeightRequest.commitment:type_name -> geyser.CommitmentLevel + 0, // 40: geyser.GetSlotRequest.commitment:type_name -> geyser.CommitmentLevel + 0, // 41: geyser.IsBlockhashValidRequest.commitment:type_name -> geyser.CommitmentLevel + 3, // 42: geyser.SubscribeRequest.AccountsEntry.value:type_name -> geyser.SubscribeRequestFilterAccounts + 7, // 43: geyser.SubscribeRequest.SlotsEntry.value:type_name -> geyser.SubscribeRequestFilterSlots + 8, // 44: geyser.SubscribeRequest.TransactionsEntry.value:type_name -> geyser.SubscribeRequestFilterTransactions + 8, // 45: geyser.SubscribeRequest.TransactionsStatusEntry.value:type_name -> geyser.SubscribeRequestFilterTransactions + 9, // 46: geyser.SubscribeRequest.BlocksEntry.value:type_name -> geyser.SubscribeRequestFilterBlocks + 10, // 47: geyser.SubscribeRequest.BlocksMetaEntry.value:type_name -> geyser.SubscribeRequestFilterBlocksMeta + 11, // 48: geyser.SubscribeRequest.EntryEntry.value:type_name -> geyser.SubscribeRequestFilterEntry + 2, // 49: geyser.Geyser.Subscribe:input_type -> geyser.SubscribeRequest + 26, // 50: geyser.Geyser.Ping:input_type -> geyser.PingRequest + 28, // 51: geyser.Geyser.GetLatestBlockhash:input_type -> geyser.GetLatestBlockhashRequest + 30, // 52: geyser.Geyser.GetBlockHeight:input_type -> geyser.GetBlockHeightRequest + 32, // 53: geyser.Geyser.GetSlot:input_type -> geyser.GetSlotRequest + 36, // 54: geyser.Geyser.IsBlockhashValid:input_type -> geyser.IsBlockhashValidRequest + 34, // 55: geyser.Geyser.GetVersion:input_type -> geyser.GetVersionRequest + 14, // 56: geyser.Geyser.Subscribe:output_type -> geyser.SubscribeUpdate + 27, // 57: geyser.Geyser.Ping:output_type -> geyser.PongResponse + 29, // 58: geyser.Geyser.GetLatestBlockhash:output_type -> geyser.GetLatestBlockhashResponse + 31, // 59: geyser.Geyser.GetBlockHeight:output_type -> geyser.GetBlockHeightResponse + 33, // 60: geyser.Geyser.GetSlot:output_type -> geyser.GetSlotResponse + 37, // 61: geyser.Geyser.IsBlockhashValid:output_type -> geyser.IsBlockhashValidResponse + 35, // 62: geyser.Geyser.GetVersion:output_type -> geyser.GetVersionResponse + 56, // [56:63] is the sub-list for method output_type + 49, // [49:56] is the sub-list for method input_type + 49, // [49:49] is the sub-list for extension type_name + 49, // [49:49] is the sub-list for extension extendee + 0, // [0:49] is the sub-list for field type_name +} + +func init() { file_geyser_proto_init() } +func file_geyser_proto_init() { + if File_geyser_proto != nil { + return + } + file_solana_storage_proto_init() + file_geyser_proto_msgTypes[0].OneofWrappers = []any{} + file_geyser_proto_msgTypes[1].OneofWrappers = []any{} + file_geyser_proto_msgTypes[2].OneofWrappers = []any{ + (*SubscribeRequestFilterAccountsFilter_Memcmp)(nil), + (*SubscribeRequestFilterAccountsFilter_Datasize)(nil), + (*SubscribeRequestFilterAccountsFilter_TokenAccountState)(nil), + (*SubscribeRequestFilterAccountsFilter_Lamports)(nil), + } + file_geyser_proto_msgTypes[3].OneofWrappers = []any{ + (*SubscribeRequestFilterAccountsFilterMemcmp_Bytes)(nil), + (*SubscribeRequestFilterAccountsFilterMemcmp_Base58)(nil), + (*SubscribeRequestFilterAccountsFilterMemcmp_Base64)(nil), + } + file_geyser_proto_msgTypes[4].OneofWrappers = []any{ + (*SubscribeRequestFilterAccountsFilterLamports_Eq)(nil), + (*SubscribeRequestFilterAccountsFilterLamports_Ne)(nil), + (*SubscribeRequestFilterAccountsFilterLamports_Lt)(nil), + (*SubscribeRequestFilterAccountsFilterLamports_Gt)(nil), + } + file_geyser_proto_msgTypes[5].OneofWrappers = []any{} + file_geyser_proto_msgTypes[6].OneofWrappers = []any{} + file_geyser_proto_msgTypes[7].OneofWrappers = []any{} + file_geyser_proto_msgTypes[12].OneofWrappers = []any{ + (*SubscribeUpdate_Account)(nil), + (*SubscribeUpdate_Slot)(nil), + (*SubscribeUpdate_Transaction)(nil), + (*SubscribeUpdate_TransactionStatus)(nil), + (*SubscribeUpdate_Block)(nil), + (*SubscribeUpdate_Ping)(nil), + (*SubscribeUpdate_Pong)(nil), + (*SubscribeUpdate_BlockMeta)(nil), + (*SubscribeUpdate_Entry)(nil), + } + file_geyser_proto_msgTypes[14].OneofWrappers = []any{} + file_geyser_proto_msgTypes[15].OneofWrappers = []any{} + file_geyser_proto_msgTypes[26].OneofWrappers = []any{} + file_geyser_proto_msgTypes[28].OneofWrappers = []any{} + file_geyser_proto_msgTypes[30].OneofWrappers = []any{} + file_geyser_proto_msgTypes[34].OneofWrappers = []any{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_geyser_proto_rawDesc), len(file_geyser_proto_rawDesc)), + NumEnums: 2, + NumMessages: 43, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_geyser_proto_goTypes, + DependencyIndexes: file_geyser_proto_depIdxs, + EnumInfos: file_geyser_proto_enumTypes, + MessageInfos: file_geyser_proto_msgTypes, + }.Build() + File_geyser_proto = out.File + file_geyser_proto_goTypes = nil + file_geyser_proto_depIdxs = nil +} diff --git a/example/geyser/proto/geyser.proto b/example/geyser/proto/geyser.proto new file mode 100644 index 0000000..88d193b --- /dev/null +++ b/example/geyser/proto/geyser.proto @@ -0,0 +1,272 @@ +syntax = "proto3"; + +import "google/protobuf/timestamp.proto"; +import public "solana-storage.proto"; + +option go_package = "github.com/rpcpool/yellowstone-grpc/examples/golang/proto"; + +package geyser; + +service Geyser { + rpc Subscribe(stream SubscribeRequest) returns (stream SubscribeUpdate) {} + rpc Ping(PingRequest) returns (PongResponse) {} + rpc GetLatestBlockhash(GetLatestBlockhashRequest) returns (GetLatestBlockhashResponse) {} + rpc GetBlockHeight(GetBlockHeightRequest) returns (GetBlockHeightResponse) {} + rpc GetSlot(GetSlotRequest) returns (GetSlotResponse) {} + rpc IsBlockhashValid(IsBlockhashValidRequest) returns (IsBlockhashValidResponse) {} + rpc GetVersion(GetVersionRequest) returns (GetVersionResponse) {} +} + +enum CommitmentLevel { + PROCESSED = 0; + CONFIRMED = 1; + FINALIZED = 2; +} + +enum SlotStatus { + SLOT_PROCESSED = 0; + SLOT_CONFIRMED = 1; + SLOT_FINALIZED = 2; + SLOT_FIRST_SHRED_RECEIVED = 3; + SLOT_COMPLETED = 4; + SLOT_CREATED_BANK = 5; + SLOT_DEAD = 6; +} + +message SubscribeRequest { + map accounts = 1; + map slots = 2; + map transactions = 3; + map transactions_status = 10; + map blocks = 4; + map blocks_meta = 5; + map entry = 8; + optional CommitmentLevel commitment = 6; + repeated SubscribeRequestAccountsDataSlice accounts_data_slice = 7; + optional SubscribeRequestPing ping = 9; + optional uint64 from_slot = 11; +} + +message SubscribeRequestFilterAccounts { + repeated string account = 2; + repeated string owner = 3; + repeated SubscribeRequestFilterAccountsFilter filters = 4; + optional bool nonempty_txn_signature = 5; +} + +message SubscribeRequestFilterAccountsFilter { + oneof filter { + SubscribeRequestFilterAccountsFilterMemcmp memcmp = 1; + uint64 datasize = 2; + bool token_account_state = 3; + SubscribeRequestFilterAccountsFilterLamports lamports = 4; + } +} + +message SubscribeRequestFilterAccountsFilterMemcmp { + uint64 offset = 1; + oneof data { + bytes bytes = 2; + string base58 = 3; + string base64 = 4; + } +} + +message SubscribeRequestFilterAccountsFilterLamports { + oneof cmp { + uint64 eq = 1; + uint64 ne = 2; + uint64 lt = 3; + uint64 gt = 4; + } +} + +message SubscribeRequestFilterSlots { + optional bool filter_by_commitment = 1; + optional bool interslot_updates = 2; +} + +message SubscribeRequestFilterTransactions { + optional bool vote = 1; + optional bool failed = 2; + optional string signature = 5; + repeated string account_include = 3; + repeated string account_exclude = 4; + repeated string account_required = 6; +} + +message SubscribeRequestFilterBlocks { + repeated string account_include = 1; + optional bool include_transactions = 2; + optional bool include_accounts = 3; + optional bool include_entries = 4; +} + +message SubscribeRequestFilterBlocksMeta {} + +message SubscribeRequestFilterEntry {} + +message SubscribeRequestAccountsDataSlice { + uint64 offset = 1; + uint64 length = 2; +} + +message SubscribeRequestPing { + int32 id = 1; +} + +message SubscribeUpdate { + repeated string filters = 1; + oneof update_oneof { + SubscribeUpdateAccount account = 2; + SubscribeUpdateSlot slot = 3; + SubscribeUpdateTransaction transaction = 4; + SubscribeUpdateTransactionStatus transaction_status = 10; + SubscribeUpdateBlock block = 5; + SubscribeUpdatePing ping = 6; + SubscribeUpdatePong pong = 9; + SubscribeUpdateBlockMeta block_meta = 7; + SubscribeUpdateEntry entry = 8; + } + google.protobuf.Timestamp created_at = 11; +} + +message SubscribeUpdateAccount { + SubscribeUpdateAccountInfo account = 1; + uint64 slot = 2; + bool is_startup = 3; +} + +message SubscribeUpdateAccountInfo { + bytes pubkey = 1; + uint64 lamports = 2; + bytes owner = 3; + bool executable = 4; + uint64 rent_epoch = 5; + bytes data = 6; + uint64 write_version = 7; + optional bytes txn_signature = 8; +} + +message SubscribeUpdateSlot { + uint64 slot = 1; + optional uint64 parent = 2; + SlotStatus status = 3; + optional string dead_error = 4; +} + +message SubscribeUpdateTransaction { + SubscribeUpdateTransactionInfo transaction = 1; + uint64 slot = 2; +} + +message SubscribeUpdateTransactionInfo { + bytes signature = 1; + bool is_vote = 2; + solana.storage.ConfirmedBlock.Transaction transaction = 3; + solana.storage.ConfirmedBlock.TransactionStatusMeta meta = 4; + uint64 index = 5; +} + +message SubscribeUpdateTransactionStatus { + uint64 slot = 1; + bytes signature = 2; + bool is_vote = 3; + uint64 index = 4; + solana.storage.ConfirmedBlock.TransactionError err = 5; +} + +message SubscribeUpdateBlock { + uint64 slot = 1; + string blockhash = 2; + solana.storage.ConfirmedBlock.Rewards rewards = 3; + solana.storage.ConfirmedBlock.UnixTimestamp block_time = 4; + solana.storage.ConfirmedBlock.BlockHeight block_height = 5; + uint64 parent_slot = 7; + string parent_blockhash = 8; + uint64 executed_transaction_count = 9; + repeated SubscribeUpdateTransactionInfo transactions = 6; + uint64 updated_account_count = 10; + repeated SubscribeUpdateAccountInfo accounts = 11; + uint64 entries_count = 12; + repeated SubscribeUpdateEntry entries = 13; +} + +message SubscribeUpdateBlockMeta { + uint64 slot = 1; + string blockhash = 2; + solana.storage.ConfirmedBlock.Rewards rewards = 3; + solana.storage.ConfirmedBlock.UnixTimestamp block_time = 4; + solana.storage.ConfirmedBlock.BlockHeight block_height = 5; + uint64 parent_slot = 6; + string parent_blockhash = 7; + uint64 executed_transaction_count = 8; + uint64 entries_count = 9; +} + +message SubscribeUpdateEntry { + uint64 slot = 1; + uint64 index = 2; + uint64 num_hashes = 3; + bytes hash = 4; + uint64 executed_transaction_count = 5; + uint64 starting_transaction_index = 6; // added in v1.18, for solana 1.17 value is always 0 +} + +message SubscribeUpdatePing {} + +message SubscribeUpdatePong { + int32 id = 1; +} + +// non-streaming methods + +message PingRequest { + int32 count = 1; +} + +message PongResponse { + int32 count = 1; +} + +message GetLatestBlockhashRequest { + optional CommitmentLevel commitment = 1; +} + +message GetLatestBlockhashResponse { + uint64 slot = 1; + string blockhash = 2; + uint64 last_valid_block_height = 3; +} + +message GetBlockHeightRequest { + optional CommitmentLevel commitment = 1; +} + +message GetBlockHeightResponse { + uint64 block_height = 1; +} + +message GetSlotRequest { + optional CommitmentLevel commitment = 1; +} + +message GetSlotResponse { + uint64 slot = 1; +} + +message GetVersionRequest {} + +message GetVersionResponse { + string version = 1; +} + +message IsBlockhashValidRequest { + string blockhash = 1; + optional CommitmentLevel commitment = 2; +} + +message IsBlockhashValidResponse { + uint64 slot = 1; + bool valid = 2; +} \ No newline at end of file diff --git a/example/geyser/proto/geyser_grpc.pb.go b/example/geyser/proto/geyser_grpc.pb.go new file mode 100644 index 0000000..be90ab8 --- /dev/null +++ b/example/geyser/proto/geyser_grpc.pb.go @@ -0,0 +1,344 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc v5.29.3 +// source: geyser.proto + +package proto + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + Geyser_Subscribe_FullMethodName = "/geyser.Geyser/Subscribe" + Geyser_Ping_FullMethodName = "/geyser.Geyser/Ping" + Geyser_GetLatestBlockhash_FullMethodName = "/geyser.Geyser/GetLatestBlockhash" + Geyser_GetBlockHeight_FullMethodName = "/geyser.Geyser/GetBlockHeight" + Geyser_GetSlot_FullMethodName = "/geyser.Geyser/GetSlot" + Geyser_IsBlockhashValid_FullMethodName = "/geyser.Geyser/IsBlockhashValid" + Geyser_GetVersion_FullMethodName = "/geyser.Geyser/GetVersion" +) + +// GeyserClient is the client API for Geyser service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type GeyserClient interface { + Subscribe(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[SubscribeRequest, SubscribeUpdate], error) + Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PongResponse, error) + GetLatestBlockhash(ctx context.Context, in *GetLatestBlockhashRequest, opts ...grpc.CallOption) (*GetLatestBlockhashResponse, error) + GetBlockHeight(ctx context.Context, in *GetBlockHeightRequest, opts ...grpc.CallOption) (*GetBlockHeightResponse, error) + GetSlot(ctx context.Context, in *GetSlotRequest, opts ...grpc.CallOption) (*GetSlotResponse, error) + IsBlockhashValid(ctx context.Context, in *IsBlockhashValidRequest, opts ...grpc.CallOption) (*IsBlockhashValidResponse, error) + GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error) +} + +type geyserClient struct { + cc grpc.ClientConnInterface +} + +func NewGeyserClient(cc grpc.ClientConnInterface) GeyserClient { + return &geyserClient{cc} +} + +func (c *geyserClient) Subscribe(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[SubscribeRequest, SubscribeUpdate], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &Geyser_ServiceDesc.Streams[0], Geyser_Subscribe_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[SubscribeRequest, SubscribeUpdate]{ClientStream: stream} + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type Geyser_SubscribeClient = grpc.BidiStreamingClient[SubscribeRequest, SubscribeUpdate] + +func (c *geyserClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PongResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PongResponse) + err := c.cc.Invoke(ctx, Geyser_Ping_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *geyserClient) GetLatestBlockhash(ctx context.Context, in *GetLatestBlockhashRequest, opts ...grpc.CallOption) (*GetLatestBlockhashResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetLatestBlockhashResponse) + err := c.cc.Invoke(ctx, Geyser_GetLatestBlockhash_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *geyserClient) GetBlockHeight(ctx context.Context, in *GetBlockHeightRequest, opts ...grpc.CallOption) (*GetBlockHeightResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetBlockHeightResponse) + err := c.cc.Invoke(ctx, Geyser_GetBlockHeight_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *geyserClient) GetSlot(ctx context.Context, in *GetSlotRequest, opts ...grpc.CallOption) (*GetSlotResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetSlotResponse) + err := c.cc.Invoke(ctx, Geyser_GetSlot_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *geyserClient) IsBlockhashValid(ctx context.Context, in *IsBlockhashValidRequest, opts ...grpc.CallOption) (*IsBlockhashValidResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(IsBlockhashValidResponse) + err := c.cc.Invoke(ctx, Geyser_IsBlockhashValid_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *geyserClient) GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetVersionResponse) + err := c.cc.Invoke(ctx, Geyser_GetVersion_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GeyserServer is the server API for Geyser service. +// All implementations must embed UnimplementedGeyserServer +// for forward compatibility. +type GeyserServer interface { + Subscribe(grpc.BidiStreamingServer[SubscribeRequest, SubscribeUpdate]) error + Ping(context.Context, *PingRequest) (*PongResponse, error) + GetLatestBlockhash(context.Context, *GetLatestBlockhashRequest) (*GetLatestBlockhashResponse, error) + GetBlockHeight(context.Context, *GetBlockHeightRequest) (*GetBlockHeightResponse, error) + GetSlot(context.Context, *GetSlotRequest) (*GetSlotResponse, error) + IsBlockhashValid(context.Context, *IsBlockhashValidRequest) (*IsBlockhashValidResponse, error) + GetVersion(context.Context, *GetVersionRequest) (*GetVersionResponse, error) + mustEmbedUnimplementedGeyserServer() +} + +// UnimplementedGeyserServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedGeyserServer struct{} + +func (UnimplementedGeyserServer) Subscribe(grpc.BidiStreamingServer[SubscribeRequest, SubscribeUpdate]) error { + return status.Errorf(codes.Unimplemented, "method Subscribe not implemented") +} +func (UnimplementedGeyserServer) Ping(context.Context, *PingRequest) (*PongResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented") +} +func (UnimplementedGeyserServer) GetLatestBlockhash(context.Context, *GetLatestBlockhashRequest) (*GetLatestBlockhashResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetLatestBlockhash not implemented") +} +func (UnimplementedGeyserServer) GetBlockHeight(context.Context, *GetBlockHeightRequest) (*GetBlockHeightResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetBlockHeight not implemented") +} +func (UnimplementedGeyserServer) GetSlot(context.Context, *GetSlotRequest) (*GetSlotResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetSlot not implemented") +} +func (UnimplementedGeyserServer) IsBlockhashValid(context.Context, *IsBlockhashValidRequest) (*IsBlockhashValidResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method IsBlockhashValid not implemented") +} +func (UnimplementedGeyserServer) GetVersion(context.Context, *GetVersionRequest) (*GetVersionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetVersion not implemented") +} +func (UnimplementedGeyserServer) mustEmbedUnimplementedGeyserServer() {} +func (UnimplementedGeyserServer) testEmbeddedByValue() {} + +// UnsafeGeyserServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GeyserServer will +// result in compilation errors. +type UnsafeGeyserServer interface { + mustEmbedUnimplementedGeyserServer() +} + +func RegisterGeyserServer(s grpc.ServiceRegistrar, srv GeyserServer) { + // If the following call pancis, it indicates UnimplementedGeyserServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&Geyser_ServiceDesc, srv) +} + +func _Geyser_Subscribe_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(GeyserServer).Subscribe(&grpc.GenericServerStream[SubscribeRequest, SubscribeUpdate]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type Geyser_SubscribeServer = grpc.BidiStreamingServer[SubscribeRequest, SubscribeUpdate] + +func _Geyser_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PingRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GeyserServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Geyser_Ping_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GeyserServer).Ping(ctx, req.(*PingRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Geyser_GetLatestBlockhash_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetLatestBlockhashRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GeyserServer).GetLatestBlockhash(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Geyser_GetLatestBlockhash_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GeyserServer).GetLatestBlockhash(ctx, req.(*GetLatestBlockhashRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Geyser_GetBlockHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetBlockHeightRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GeyserServer).GetBlockHeight(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Geyser_GetBlockHeight_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GeyserServer).GetBlockHeight(ctx, req.(*GetBlockHeightRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Geyser_GetSlot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetSlotRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GeyserServer).GetSlot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Geyser_GetSlot_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GeyserServer).GetSlot(ctx, req.(*GetSlotRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Geyser_IsBlockhashValid_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(IsBlockhashValidRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GeyserServer).IsBlockhashValid(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Geyser_IsBlockhashValid_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GeyserServer).IsBlockhashValid(ctx, req.(*IsBlockhashValidRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Geyser_GetVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetVersionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GeyserServer).GetVersion(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Geyser_GetVersion_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GeyserServer).GetVersion(ctx, req.(*GetVersionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Geyser_ServiceDesc is the grpc.ServiceDesc for Geyser service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Geyser_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "geyser.Geyser", + HandlerType: (*GeyserServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Ping", + Handler: _Geyser_Ping_Handler, + }, + { + MethodName: "GetLatestBlockhash", + Handler: _Geyser_GetLatestBlockhash_Handler, + }, + { + MethodName: "GetBlockHeight", + Handler: _Geyser_GetBlockHeight_Handler, + }, + { + MethodName: "GetSlot", + Handler: _Geyser_GetSlot_Handler, + }, + { + MethodName: "IsBlockhashValid", + Handler: _Geyser_IsBlockhashValid_Handler, + }, + { + MethodName: "GetVersion", + Handler: _Geyser_GetVersion_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Subscribe", + Handler: _Geyser_Subscribe_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "geyser.proto", +} diff --git a/example/geyser/proto/solana-storage.pb.go b/example/geyser/proto/solana-storage.pb.go new file mode 100644 index 0000000..7f95d44 --- /dev/null +++ b/example/geyser/proto/solana-storage.pb.go @@ -0,0 +1,1547 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.6 +// protoc v5.29.3 +// source: solana-storage.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type RewardType int32 + +const ( + RewardType_Unspecified RewardType = 0 + RewardType_Fee RewardType = 1 + RewardType_Rent RewardType = 2 + RewardType_Staking RewardType = 3 + RewardType_Voting RewardType = 4 +) + +// Enum value maps for RewardType. +var ( + RewardType_name = map[int32]string{ + 0: "Unspecified", + 1: "Fee", + 2: "Rent", + 3: "Staking", + 4: "Voting", + } + RewardType_value = map[string]int32{ + "Unspecified": 0, + "Fee": 1, + "Rent": 2, + "Staking": 3, + "Voting": 4, + } +) + +func (x RewardType) Enum() *RewardType { + p := new(RewardType) + *p = x + return p +} + +func (x RewardType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RewardType) Descriptor() protoreflect.EnumDescriptor { + return file_solana_storage_proto_enumTypes[0].Descriptor() +} + +func (RewardType) Type() protoreflect.EnumType { + return &file_solana_storage_proto_enumTypes[0] +} + +func (x RewardType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RewardType.Descriptor instead. +func (RewardType) EnumDescriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{0} +} + +type ConfirmedBlock struct { + state protoimpl.MessageState `protogen:"open.v1"` + PreviousBlockhash string `protobuf:"bytes,1,opt,name=previous_blockhash,json=previousBlockhash,proto3" json:"previous_blockhash,omitempty"` + Blockhash string `protobuf:"bytes,2,opt,name=blockhash,proto3" json:"blockhash,omitempty"` + ParentSlot uint64 `protobuf:"varint,3,opt,name=parent_slot,json=parentSlot,proto3" json:"parent_slot,omitempty"` + Transactions []*ConfirmedTransaction `protobuf:"bytes,4,rep,name=transactions,proto3" json:"transactions,omitempty"` + Rewards []*Reward `protobuf:"bytes,5,rep,name=rewards,proto3" json:"rewards,omitempty"` + BlockTime *UnixTimestamp `protobuf:"bytes,6,opt,name=block_time,json=blockTime,proto3" json:"block_time,omitempty"` + BlockHeight *BlockHeight `protobuf:"bytes,7,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` + NumPartitions *NumPartitions `protobuf:"bytes,8,opt,name=num_partitions,json=numPartitions,proto3" json:"num_partitions,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConfirmedBlock) Reset() { + *x = ConfirmedBlock{} + mi := &file_solana_storage_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConfirmedBlock) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfirmedBlock) ProtoMessage() {} + +func (x *ConfirmedBlock) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfirmedBlock.ProtoReflect.Descriptor instead. +func (*ConfirmedBlock) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{0} +} + +func (x *ConfirmedBlock) GetPreviousBlockhash() string { + if x != nil { + return x.PreviousBlockhash + } + return "" +} + +func (x *ConfirmedBlock) GetBlockhash() string { + if x != nil { + return x.Blockhash + } + return "" +} + +func (x *ConfirmedBlock) GetParentSlot() uint64 { + if x != nil { + return x.ParentSlot + } + return 0 +} + +func (x *ConfirmedBlock) GetTransactions() []*ConfirmedTransaction { + if x != nil { + return x.Transactions + } + return nil +} + +func (x *ConfirmedBlock) GetRewards() []*Reward { + if x != nil { + return x.Rewards + } + return nil +} + +func (x *ConfirmedBlock) GetBlockTime() *UnixTimestamp { + if x != nil { + return x.BlockTime + } + return nil +} + +func (x *ConfirmedBlock) GetBlockHeight() *BlockHeight { + if x != nil { + return x.BlockHeight + } + return nil +} + +func (x *ConfirmedBlock) GetNumPartitions() *NumPartitions { + if x != nil { + return x.NumPartitions + } + return nil +} + +type ConfirmedTransaction struct { + state protoimpl.MessageState `protogen:"open.v1"` + Transaction *Transaction `protobuf:"bytes,1,opt,name=transaction,proto3" json:"transaction,omitempty"` + Meta *TransactionStatusMeta `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConfirmedTransaction) Reset() { + *x = ConfirmedTransaction{} + mi := &file_solana_storage_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConfirmedTransaction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfirmedTransaction) ProtoMessage() {} + +func (x *ConfirmedTransaction) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfirmedTransaction.ProtoReflect.Descriptor instead. +func (*ConfirmedTransaction) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{1} +} + +func (x *ConfirmedTransaction) GetTransaction() *Transaction { + if x != nil { + return x.Transaction + } + return nil +} + +func (x *ConfirmedTransaction) GetMeta() *TransactionStatusMeta { + if x != nil { + return x.Meta + } + return nil +} + +type Transaction struct { + state protoimpl.MessageState `protogen:"open.v1"` + Signatures [][]byte `protobuf:"bytes,1,rep,name=signatures,proto3" json:"signatures,omitempty"` + Message *Message `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Transaction) Reset() { + *x = Transaction{} + mi := &file_solana_storage_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Transaction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Transaction) ProtoMessage() {} + +func (x *Transaction) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Transaction.ProtoReflect.Descriptor instead. +func (*Transaction) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{2} +} + +func (x *Transaction) GetSignatures() [][]byte { + if x != nil { + return x.Signatures + } + return nil +} + +func (x *Transaction) GetMessage() *Message { + if x != nil { + return x.Message + } + return nil +} + +type Message struct { + state protoimpl.MessageState `protogen:"open.v1"` + Header *MessageHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + AccountKeys [][]byte `protobuf:"bytes,2,rep,name=account_keys,json=accountKeys,proto3" json:"account_keys,omitempty"` + RecentBlockhash []byte `protobuf:"bytes,3,opt,name=recent_blockhash,json=recentBlockhash,proto3" json:"recent_blockhash,omitempty"` + Instructions []*CompiledInstruction `protobuf:"bytes,4,rep,name=instructions,proto3" json:"instructions,omitempty"` + Versioned bool `protobuf:"varint,5,opt,name=versioned,proto3" json:"versioned,omitempty"` + AddressTableLookups []*MessageAddressTableLookup `protobuf:"bytes,6,rep,name=address_table_lookups,json=addressTableLookups,proto3" json:"address_table_lookups,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Message) Reset() { + *x = Message{} + mi := &file_solana_storage_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Message) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Message) ProtoMessage() {} + +func (x *Message) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Message.ProtoReflect.Descriptor instead. +func (*Message) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{3} +} + +func (x *Message) GetHeader() *MessageHeader { + if x != nil { + return x.Header + } + return nil +} + +func (x *Message) GetAccountKeys() [][]byte { + if x != nil { + return x.AccountKeys + } + return nil +} + +func (x *Message) GetRecentBlockhash() []byte { + if x != nil { + return x.RecentBlockhash + } + return nil +} + +func (x *Message) GetInstructions() []*CompiledInstruction { + if x != nil { + return x.Instructions + } + return nil +} + +func (x *Message) GetVersioned() bool { + if x != nil { + return x.Versioned + } + return false +} + +func (x *Message) GetAddressTableLookups() []*MessageAddressTableLookup { + if x != nil { + return x.AddressTableLookups + } + return nil +} + +type MessageHeader struct { + state protoimpl.MessageState `protogen:"open.v1"` + NumRequiredSignatures uint32 `protobuf:"varint,1,opt,name=num_required_signatures,json=numRequiredSignatures,proto3" json:"num_required_signatures,omitempty"` + NumReadonlySignedAccounts uint32 `protobuf:"varint,2,opt,name=num_readonly_signed_accounts,json=numReadonlySignedAccounts,proto3" json:"num_readonly_signed_accounts,omitempty"` + NumReadonlyUnsignedAccounts uint32 `protobuf:"varint,3,opt,name=num_readonly_unsigned_accounts,json=numReadonlyUnsignedAccounts,proto3" json:"num_readonly_unsigned_accounts,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MessageHeader) Reset() { + *x = MessageHeader{} + mi := &file_solana_storage_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MessageHeader) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MessageHeader) ProtoMessage() {} + +func (x *MessageHeader) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MessageHeader.ProtoReflect.Descriptor instead. +func (*MessageHeader) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{4} +} + +func (x *MessageHeader) GetNumRequiredSignatures() uint32 { + if x != nil { + return x.NumRequiredSignatures + } + return 0 +} + +func (x *MessageHeader) GetNumReadonlySignedAccounts() uint32 { + if x != nil { + return x.NumReadonlySignedAccounts + } + return 0 +} + +func (x *MessageHeader) GetNumReadonlyUnsignedAccounts() uint32 { + if x != nil { + return x.NumReadonlyUnsignedAccounts + } + return 0 +} + +type MessageAddressTableLookup struct { + state protoimpl.MessageState `protogen:"open.v1"` + AccountKey []byte `protobuf:"bytes,1,opt,name=account_key,json=accountKey,proto3" json:"account_key,omitempty"` + WritableIndexes []byte `protobuf:"bytes,2,opt,name=writable_indexes,json=writableIndexes,proto3" json:"writable_indexes,omitempty"` + ReadonlyIndexes []byte `protobuf:"bytes,3,opt,name=readonly_indexes,json=readonlyIndexes,proto3" json:"readonly_indexes,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MessageAddressTableLookup) Reset() { + *x = MessageAddressTableLookup{} + mi := &file_solana_storage_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MessageAddressTableLookup) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MessageAddressTableLookup) ProtoMessage() {} + +func (x *MessageAddressTableLookup) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MessageAddressTableLookup.ProtoReflect.Descriptor instead. +func (*MessageAddressTableLookup) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{5} +} + +func (x *MessageAddressTableLookup) GetAccountKey() []byte { + if x != nil { + return x.AccountKey + } + return nil +} + +func (x *MessageAddressTableLookup) GetWritableIndexes() []byte { + if x != nil { + return x.WritableIndexes + } + return nil +} + +func (x *MessageAddressTableLookup) GetReadonlyIndexes() []byte { + if x != nil { + return x.ReadonlyIndexes + } + return nil +} + +type TransactionStatusMeta struct { + state protoimpl.MessageState `protogen:"open.v1"` + Err *TransactionError `protobuf:"bytes,1,opt,name=err,proto3" json:"err,omitempty"` + Fee uint64 `protobuf:"varint,2,opt,name=fee,proto3" json:"fee,omitempty"` + PreBalances []uint64 `protobuf:"varint,3,rep,packed,name=pre_balances,json=preBalances,proto3" json:"pre_balances,omitempty"` + PostBalances []uint64 `protobuf:"varint,4,rep,packed,name=post_balances,json=postBalances,proto3" json:"post_balances,omitempty"` + InnerInstructions []*InnerInstructions `protobuf:"bytes,5,rep,name=inner_instructions,json=innerInstructions,proto3" json:"inner_instructions,omitempty"` + InnerInstructionsNone bool `protobuf:"varint,10,opt,name=inner_instructions_none,json=innerInstructionsNone,proto3" json:"inner_instructions_none,omitempty"` + LogMessages []string `protobuf:"bytes,6,rep,name=log_messages,json=logMessages,proto3" json:"log_messages,omitempty"` + LogMessagesNone bool `protobuf:"varint,11,opt,name=log_messages_none,json=logMessagesNone,proto3" json:"log_messages_none,omitempty"` + PreTokenBalances []*TokenBalance `protobuf:"bytes,7,rep,name=pre_token_balances,json=preTokenBalances,proto3" json:"pre_token_balances,omitempty"` + PostTokenBalances []*TokenBalance `protobuf:"bytes,8,rep,name=post_token_balances,json=postTokenBalances,proto3" json:"post_token_balances,omitempty"` + Rewards []*Reward `protobuf:"bytes,9,rep,name=rewards,proto3" json:"rewards,omitempty"` + LoadedWritableAddresses [][]byte `protobuf:"bytes,12,rep,name=loaded_writable_addresses,json=loadedWritableAddresses,proto3" json:"loaded_writable_addresses,omitempty"` + LoadedReadonlyAddresses [][]byte `protobuf:"bytes,13,rep,name=loaded_readonly_addresses,json=loadedReadonlyAddresses,proto3" json:"loaded_readonly_addresses,omitempty"` + ReturnData *ReturnData `protobuf:"bytes,14,opt,name=return_data,json=returnData,proto3" json:"return_data,omitempty"` + ReturnDataNone bool `protobuf:"varint,15,opt,name=return_data_none,json=returnDataNone,proto3" json:"return_data_none,omitempty"` + // Sum of compute units consumed by all instructions. + // Available since Solana v1.10.35 / v1.11.6. + // Set to `None` for txs executed on earlier versions. + ComputeUnitsConsumed *uint64 `protobuf:"varint,16,opt,name=compute_units_consumed,json=computeUnitsConsumed,proto3,oneof" json:"compute_units_consumed,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TransactionStatusMeta) Reset() { + *x = TransactionStatusMeta{} + mi := &file_solana_storage_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TransactionStatusMeta) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStatusMeta) ProtoMessage() {} + +func (x *TransactionStatusMeta) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStatusMeta.ProtoReflect.Descriptor instead. +func (*TransactionStatusMeta) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{6} +} + +func (x *TransactionStatusMeta) GetErr() *TransactionError { + if x != nil { + return x.Err + } + return nil +} + +func (x *TransactionStatusMeta) GetFee() uint64 { + if x != nil { + return x.Fee + } + return 0 +} + +func (x *TransactionStatusMeta) GetPreBalances() []uint64 { + if x != nil { + return x.PreBalances + } + return nil +} + +func (x *TransactionStatusMeta) GetPostBalances() []uint64 { + if x != nil { + return x.PostBalances + } + return nil +} + +func (x *TransactionStatusMeta) GetInnerInstructions() []*InnerInstructions { + if x != nil { + return x.InnerInstructions + } + return nil +} + +func (x *TransactionStatusMeta) GetInnerInstructionsNone() bool { + if x != nil { + return x.InnerInstructionsNone + } + return false +} + +func (x *TransactionStatusMeta) GetLogMessages() []string { + if x != nil { + return x.LogMessages + } + return nil +} + +func (x *TransactionStatusMeta) GetLogMessagesNone() bool { + if x != nil { + return x.LogMessagesNone + } + return false +} + +func (x *TransactionStatusMeta) GetPreTokenBalances() []*TokenBalance { + if x != nil { + return x.PreTokenBalances + } + return nil +} + +func (x *TransactionStatusMeta) GetPostTokenBalances() []*TokenBalance { + if x != nil { + return x.PostTokenBalances + } + return nil +} + +func (x *TransactionStatusMeta) GetRewards() []*Reward { + if x != nil { + return x.Rewards + } + return nil +} + +func (x *TransactionStatusMeta) GetLoadedWritableAddresses() [][]byte { + if x != nil { + return x.LoadedWritableAddresses + } + return nil +} + +func (x *TransactionStatusMeta) GetLoadedReadonlyAddresses() [][]byte { + if x != nil { + return x.LoadedReadonlyAddresses + } + return nil +} + +func (x *TransactionStatusMeta) GetReturnData() *ReturnData { + if x != nil { + return x.ReturnData + } + return nil +} + +func (x *TransactionStatusMeta) GetReturnDataNone() bool { + if x != nil { + return x.ReturnDataNone + } + return false +} + +func (x *TransactionStatusMeta) GetComputeUnitsConsumed() uint64 { + if x != nil && x.ComputeUnitsConsumed != nil { + return *x.ComputeUnitsConsumed + } + return 0 +} + +type TransactionError struct { + state protoimpl.MessageState `protogen:"open.v1"` + Err []byte `protobuf:"bytes,1,opt,name=err,proto3" json:"err,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TransactionError) Reset() { + *x = TransactionError{} + mi := &file_solana_storage_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TransactionError) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionError) ProtoMessage() {} + +func (x *TransactionError) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionError.ProtoReflect.Descriptor instead. +func (*TransactionError) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{7} +} + +func (x *TransactionError) GetErr() []byte { + if x != nil { + return x.Err + } + return nil +} + +type InnerInstructions struct { + state protoimpl.MessageState `protogen:"open.v1"` + Index uint32 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` + Instructions []*InnerInstruction `protobuf:"bytes,2,rep,name=instructions,proto3" json:"instructions,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InnerInstructions) Reset() { + *x = InnerInstructions{} + mi := &file_solana_storage_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InnerInstructions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InnerInstructions) ProtoMessage() {} + +func (x *InnerInstructions) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InnerInstructions.ProtoReflect.Descriptor instead. +func (*InnerInstructions) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{8} +} + +func (x *InnerInstructions) GetIndex() uint32 { + if x != nil { + return x.Index + } + return 0 +} + +func (x *InnerInstructions) GetInstructions() []*InnerInstruction { + if x != nil { + return x.Instructions + } + return nil +} + +type InnerInstruction struct { + state protoimpl.MessageState `protogen:"open.v1"` + ProgramIdIndex uint32 `protobuf:"varint,1,opt,name=program_id_index,json=programIdIndex,proto3" json:"program_id_index,omitempty"` + Accounts []byte `protobuf:"bytes,2,opt,name=accounts,proto3" json:"accounts,omitempty"` + Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` + // Invocation stack height of an inner instruction. + // Available since Solana v1.14.6 + // Set to `None` for txs executed on earlier versions. + StackHeight *uint32 `protobuf:"varint,4,opt,name=stack_height,json=stackHeight,proto3,oneof" json:"stack_height,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InnerInstruction) Reset() { + *x = InnerInstruction{} + mi := &file_solana_storage_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InnerInstruction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InnerInstruction) ProtoMessage() {} + +func (x *InnerInstruction) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InnerInstruction.ProtoReflect.Descriptor instead. +func (*InnerInstruction) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{9} +} + +func (x *InnerInstruction) GetProgramIdIndex() uint32 { + if x != nil { + return x.ProgramIdIndex + } + return 0 +} + +func (x *InnerInstruction) GetAccounts() []byte { + if x != nil { + return x.Accounts + } + return nil +} + +func (x *InnerInstruction) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +func (x *InnerInstruction) GetStackHeight() uint32 { + if x != nil && x.StackHeight != nil { + return *x.StackHeight + } + return 0 +} + +type CompiledInstruction struct { + state protoimpl.MessageState `protogen:"open.v1"` + ProgramIdIndex uint32 `protobuf:"varint,1,opt,name=program_id_index,json=programIdIndex,proto3" json:"program_id_index,omitempty"` + Accounts []byte `protobuf:"bytes,2,opt,name=accounts,proto3" json:"accounts,omitempty"` + Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CompiledInstruction) Reset() { + *x = CompiledInstruction{} + mi := &file_solana_storage_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CompiledInstruction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CompiledInstruction) ProtoMessage() {} + +func (x *CompiledInstruction) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CompiledInstruction.ProtoReflect.Descriptor instead. +func (*CompiledInstruction) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{10} +} + +func (x *CompiledInstruction) GetProgramIdIndex() uint32 { + if x != nil { + return x.ProgramIdIndex + } + return 0 +} + +func (x *CompiledInstruction) GetAccounts() []byte { + if x != nil { + return x.Accounts + } + return nil +} + +func (x *CompiledInstruction) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type TokenBalance struct { + state protoimpl.MessageState `protogen:"open.v1"` + AccountIndex uint32 `protobuf:"varint,1,opt,name=account_index,json=accountIndex,proto3" json:"account_index,omitempty"` + Mint string `protobuf:"bytes,2,opt,name=mint,proto3" json:"mint,omitempty"` + UiTokenAmount *UiTokenAmount `protobuf:"bytes,3,opt,name=ui_token_amount,json=uiTokenAmount,proto3" json:"ui_token_amount,omitempty"` + Owner string `protobuf:"bytes,4,opt,name=owner,proto3" json:"owner,omitempty"` + ProgramId string `protobuf:"bytes,5,opt,name=program_id,json=programId,proto3" json:"program_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TokenBalance) Reset() { + *x = TokenBalance{} + mi := &file_solana_storage_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TokenBalance) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TokenBalance) ProtoMessage() {} + +func (x *TokenBalance) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TokenBalance.ProtoReflect.Descriptor instead. +func (*TokenBalance) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{11} +} + +func (x *TokenBalance) GetAccountIndex() uint32 { + if x != nil { + return x.AccountIndex + } + return 0 +} + +func (x *TokenBalance) GetMint() string { + if x != nil { + return x.Mint + } + return "" +} + +func (x *TokenBalance) GetUiTokenAmount() *UiTokenAmount { + if x != nil { + return x.UiTokenAmount + } + return nil +} + +func (x *TokenBalance) GetOwner() string { + if x != nil { + return x.Owner + } + return "" +} + +func (x *TokenBalance) GetProgramId() string { + if x != nil { + return x.ProgramId + } + return "" +} + +type UiTokenAmount struct { + state protoimpl.MessageState `protogen:"open.v1"` + UiAmount float64 `protobuf:"fixed64,1,opt,name=ui_amount,json=uiAmount,proto3" json:"ui_amount,omitempty"` + Decimals uint32 `protobuf:"varint,2,opt,name=decimals,proto3" json:"decimals,omitempty"` + Amount string `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount,omitempty"` + UiAmountString string `protobuf:"bytes,4,opt,name=ui_amount_string,json=uiAmountString,proto3" json:"ui_amount_string,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UiTokenAmount) Reset() { + *x = UiTokenAmount{} + mi := &file_solana_storage_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UiTokenAmount) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UiTokenAmount) ProtoMessage() {} + +func (x *UiTokenAmount) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UiTokenAmount.ProtoReflect.Descriptor instead. +func (*UiTokenAmount) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{12} +} + +func (x *UiTokenAmount) GetUiAmount() float64 { + if x != nil { + return x.UiAmount + } + return 0 +} + +func (x *UiTokenAmount) GetDecimals() uint32 { + if x != nil { + return x.Decimals + } + return 0 +} + +func (x *UiTokenAmount) GetAmount() string { + if x != nil { + return x.Amount + } + return "" +} + +func (x *UiTokenAmount) GetUiAmountString() string { + if x != nil { + return x.UiAmountString + } + return "" +} + +type ReturnData struct { + state protoimpl.MessageState `protogen:"open.v1"` + ProgramId []byte `protobuf:"bytes,1,opt,name=program_id,json=programId,proto3" json:"program_id,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ReturnData) Reset() { + *x = ReturnData{} + mi := &file_solana_storage_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ReturnData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReturnData) ProtoMessage() {} + +func (x *ReturnData) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReturnData.ProtoReflect.Descriptor instead. +func (*ReturnData) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{13} +} + +func (x *ReturnData) GetProgramId() []byte { + if x != nil { + return x.ProgramId + } + return nil +} + +func (x *ReturnData) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type Reward struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Lamports int64 `protobuf:"varint,2,opt,name=lamports,proto3" json:"lamports,omitempty"` + PostBalance uint64 `protobuf:"varint,3,opt,name=post_balance,json=postBalance,proto3" json:"post_balance,omitempty"` + RewardType RewardType `protobuf:"varint,4,opt,name=reward_type,json=rewardType,proto3,enum=solana.storage.ConfirmedBlock.RewardType" json:"reward_type,omitempty"` + Commission string `protobuf:"bytes,5,opt,name=commission,proto3" json:"commission,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Reward) Reset() { + *x = Reward{} + mi := &file_solana_storage_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Reward) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Reward) ProtoMessage() {} + +func (x *Reward) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Reward.ProtoReflect.Descriptor instead. +func (*Reward) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{14} +} + +func (x *Reward) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *Reward) GetLamports() int64 { + if x != nil { + return x.Lamports + } + return 0 +} + +func (x *Reward) GetPostBalance() uint64 { + if x != nil { + return x.PostBalance + } + return 0 +} + +func (x *Reward) GetRewardType() RewardType { + if x != nil { + return x.RewardType + } + return RewardType_Unspecified +} + +func (x *Reward) GetCommission() string { + if x != nil { + return x.Commission + } + return "" +} + +type Rewards struct { + state protoimpl.MessageState `protogen:"open.v1"` + Rewards []*Reward `protobuf:"bytes,1,rep,name=rewards,proto3" json:"rewards,omitempty"` + NumPartitions *NumPartitions `protobuf:"bytes,2,opt,name=num_partitions,json=numPartitions,proto3" json:"num_partitions,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Rewards) Reset() { + *x = Rewards{} + mi := &file_solana_storage_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Rewards) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Rewards) ProtoMessage() {} + +func (x *Rewards) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Rewards.ProtoReflect.Descriptor instead. +func (*Rewards) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{15} +} + +func (x *Rewards) GetRewards() []*Reward { + if x != nil { + return x.Rewards + } + return nil +} + +func (x *Rewards) GetNumPartitions() *NumPartitions { + if x != nil { + return x.NumPartitions + } + return nil +} + +type UnixTimestamp struct { + state protoimpl.MessageState `protogen:"open.v1"` + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UnixTimestamp) Reset() { + *x = UnixTimestamp{} + mi := &file_solana_storage_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UnixTimestamp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnixTimestamp) ProtoMessage() {} + +func (x *UnixTimestamp) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnixTimestamp.ProtoReflect.Descriptor instead. +func (*UnixTimestamp) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{16} +} + +func (x *UnixTimestamp) GetTimestamp() int64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +type BlockHeight struct { + state protoimpl.MessageState `protogen:"open.v1"` + BlockHeight uint64 `protobuf:"varint,1,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BlockHeight) Reset() { + *x = BlockHeight{} + mi := &file_solana_storage_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BlockHeight) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlockHeight) ProtoMessage() {} + +func (x *BlockHeight) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BlockHeight.ProtoReflect.Descriptor instead. +func (*BlockHeight) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{17} +} + +func (x *BlockHeight) GetBlockHeight() uint64 { + if x != nil { + return x.BlockHeight + } + return 0 +} + +type NumPartitions struct { + state protoimpl.MessageState `protogen:"open.v1"` + NumPartitions uint64 `protobuf:"varint,1,opt,name=num_partitions,json=numPartitions,proto3" json:"num_partitions,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *NumPartitions) Reset() { + *x = NumPartitions{} + mi := &file_solana_storage_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NumPartitions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NumPartitions) ProtoMessage() {} + +func (x *NumPartitions) ProtoReflect() protoreflect.Message { + mi := &file_solana_storage_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NumPartitions.ProtoReflect.Descriptor instead. +func (*NumPartitions) Descriptor() ([]byte, []int) { + return file_solana_storage_proto_rawDescGZIP(), []int{18} +} + +func (x *NumPartitions) GetNumPartitions() uint64 { + if x != nil { + return x.NumPartitions + } + return 0 +} + +var File_solana_storage_proto protoreflect.FileDescriptor + +const file_solana_storage_proto_rawDesc = "" + + "\n" + + "\x14solana-storage.proto\x12\x1dsolana.storage.ConfirmedBlock\"\x89\x04\n" + + "\x0eConfirmedBlock\x12-\n" + + "\x12previous_blockhash\x18\x01 \x01(\tR\x11previousBlockhash\x12\x1c\n" + + "\tblockhash\x18\x02 \x01(\tR\tblockhash\x12\x1f\n" + + "\vparent_slot\x18\x03 \x01(\x04R\n" + + "parentSlot\x12W\n" + + "\ftransactions\x18\x04 \x03(\v23.solana.storage.ConfirmedBlock.ConfirmedTransactionR\ftransactions\x12?\n" + + "\arewards\x18\x05 \x03(\v2%.solana.storage.ConfirmedBlock.RewardR\arewards\x12K\n" + + "\n" + + "block_time\x18\x06 \x01(\v2,.solana.storage.ConfirmedBlock.UnixTimestampR\tblockTime\x12M\n" + + "\fblock_height\x18\a \x01(\v2*.solana.storage.ConfirmedBlock.BlockHeightR\vblockHeight\x12S\n" + + "\x0enum_partitions\x18\b \x01(\v2,.solana.storage.ConfirmedBlock.NumPartitionsR\rnumPartitions\"\xae\x01\n" + + "\x14ConfirmedTransaction\x12L\n" + + "\vtransaction\x18\x01 \x01(\v2*.solana.storage.ConfirmedBlock.TransactionR\vtransaction\x12H\n" + + "\x04meta\x18\x02 \x01(\v24.solana.storage.ConfirmedBlock.TransactionStatusMetaR\x04meta\"o\n" + + "\vTransaction\x12\x1e\n" + + "\n" + + "signatures\x18\x01 \x03(\fR\n" + + "signatures\x12@\n" + + "\amessage\x18\x02 \x01(\v2&.solana.storage.ConfirmedBlock.MessageR\amessage\"\x81\x03\n" + + "\aMessage\x12D\n" + + "\x06header\x18\x01 \x01(\v2,.solana.storage.ConfirmedBlock.MessageHeaderR\x06header\x12!\n" + + "\faccount_keys\x18\x02 \x03(\fR\vaccountKeys\x12)\n" + + "\x10recent_blockhash\x18\x03 \x01(\fR\x0frecentBlockhash\x12V\n" + + "\finstructions\x18\x04 \x03(\v22.solana.storage.ConfirmedBlock.CompiledInstructionR\finstructions\x12\x1c\n" + + "\tversioned\x18\x05 \x01(\bR\tversioned\x12l\n" + + "\x15address_table_lookups\x18\x06 \x03(\v28.solana.storage.ConfirmedBlock.MessageAddressTableLookupR\x13addressTableLookups\"\xcd\x01\n" + + "\rMessageHeader\x126\n" + + "\x17num_required_signatures\x18\x01 \x01(\rR\x15numRequiredSignatures\x12?\n" + + "\x1cnum_readonly_signed_accounts\x18\x02 \x01(\rR\x19numReadonlySignedAccounts\x12C\n" + + "\x1enum_readonly_unsigned_accounts\x18\x03 \x01(\rR\x1bnumReadonlyUnsignedAccounts\"\x92\x01\n" + + "\x19MessageAddressTableLookup\x12\x1f\n" + + "\vaccount_key\x18\x01 \x01(\fR\n" + + "accountKey\x12)\n" + + "\x10writable_indexes\x18\x02 \x01(\fR\x0fwritableIndexes\x12)\n" + + "\x10readonly_indexes\x18\x03 \x01(\fR\x0freadonlyIndexes\"\xd9\a\n" + + "\x15TransactionStatusMeta\x12A\n" + + "\x03err\x18\x01 \x01(\v2/.solana.storage.ConfirmedBlock.TransactionErrorR\x03err\x12\x10\n" + + "\x03fee\x18\x02 \x01(\x04R\x03fee\x12!\n" + + "\fpre_balances\x18\x03 \x03(\x04R\vpreBalances\x12#\n" + + "\rpost_balances\x18\x04 \x03(\x04R\fpostBalances\x12_\n" + + "\x12inner_instructions\x18\x05 \x03(\v20.solana.storage.ConfirmedBlock.InnerInstructionsR\x11innerInstructions\x126\n" + + "\x17inner_instructions_none\x18\n" + + " \x01(\bR\x15innerInstructionsNone\x12!\n" + + "\flog_messages\x18\x06 \x03(\tR\vlogMessages\x12*\n" + + "\x11log_messages_none\x18\v \x01(\bR\x0flogMessagesNone\x12Y\n" + + "\x12pre_token_balances\x18\a \x03(\v2+.solana.storage.ConfirmedBlock.TokenBalanceR\x10preTokenBalances\x12[\n" + + "\x13post_token_balances\x18\b \x03(\v2+.solana.storage.ConfirmedBlock.TokenBalanceR\x11postTokenBalances\x12?\n" + + "\arewards\x18\t \x03(\v2%.solana.storage.ConfirmedBlock.RewardR\arewards\x12:\n" + + "\x19loaded_writable_addresses\x18\f \x03(\fR\x17loadedWritableAddresses\x12:\n" + + "\x19loaded_readonly_addresses\x18\r \x03(\fR\x17loadedReadonlyAddresses\x12J\n" + + "\vreturn_data\x18\x0e \x01(\v2).solana.storage.ConfirmedBlock.ReturnDataR\n" + + "returnData\x12(\n" + + "\x10return_data_none\x18\x0f \x01(\bR\x0ereturnDataNone\x129\n" + + "\x16compute_units_consumed\x18\x10 \x01(\x04H\x00R\x14computeUnitsConsumed\x88\x01\x01B\x19\n" + + "\x17_compute_units_consumed\"$\n" + + "\x10TransactionError\x12\x10\n" + + "\x03err\x18\x01 \x01(\fR\x03err\"~\n" + + "\x11InnerInstructions\x12\x14\n" + + "\x05index\x18\x01 \x01(\rR\x05index\x12S\n" + + "\finstructions\x18\x02 \x03(\v2/.solana.storage.ConfirmedBlock.InnerInstructionR\finstructions\"\xa5\x01\n" + + "\x10InnerInstruction\x12(\n" + + "\x10program_id_index\x18\x01 \x01(\rR\x0eprogramIdIndex\x12\x1a\n" + + "\baccounts\x18\x02 \x01(\fR\baccounts\x12\x12\n" + + "\x04data\x18\x03 \x01(\fR\x04data\x12&\n" + + "\fstack_height\x18\x04 \x01(\rH\x00R\vstackHeight\x88\x01\x01B\x0f\n" + + "\r_stack_height\"o\n" + + "\x13CompiledInstruction\x12(\n" + + "\x10program_id_index\x18\x01 \x01(\rR\x0eprogramIdIndex\x12\x1a\n" + + "\baccounts\x18\x02 \x01(\fR\baccounts\x12\x12\n" + + "\x04data\x18\x03 \x01(\fR\x04data\"\xd2\x01\n" + + "\fTokenBalance\x12#\n" + + "\raccount_index\x18\x01 \x01(\rR\faccountIndex\x12\x12\n" + + "\x04mint\x18\x02 \x01(\tR\x04mint\x12T\n" + + "\x0fui_token_amount\x18\x03 \x01(\v2,.solana.storage.ConfirmedBlock.UiTokenAmountR\ruiTokenAmount\x12\x14\n" + + "\x05owner\x18\x04 \x01(\tR\x05owner\x12\x1d\n" + + "\n" + + "program_id\x18\x05 \x01(\tR\tprogramId\"\x8a\x01\n" + + "\rUiTokenAmount\x12\x1b\n" + + "\tui_amount\x18\x01 \x01(\x01R\buiAmount\x12\x1a\n" + + "\bdecimals\x18\x02 \x01(\rR\bdecimals\x12\x16\n" + + "\x06amount\x18\x03 \x01(\tR\x06amount\x12(\n" + + "\x10ui_amount_string\x18\x04 \x01(\tR\x0euiAmountString\"?\n" + + "\n" + + "ReturnData\x12\x1d\n" + + "\n" + + "program_id\x18\x01 \x01(\fR\tprogramId\x12\x12\n" + + "\x04data\x18\x02 \x01(\fR\x04data\"\xcb\x01\n" + + "\x06Reward\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\x12\x1a\n" + + "\blamports\x18\x02 \x01(\x03R\blamports\x12!\n" + + "\fpost_balance\x18\x03 \x01(\x04R\vpostBalance\x12J\n" + + "\vreward_type\x18\x04 \x01(\x0e2).solana.storage.ConfirmedBlock.RewardTypeR\n" + + "rewardType\x12\x1e\n" + + "\n" + + "commission\x18\x05 \x01(\tR\n" + + "commission\"\x9f\x01\n" + + "\aRewards\x12?\n" + + "\arewards\x18\x01 \x03(\v2%.solana.storage.ConfirmedBlock.RewardR\arewards\x12S\n" + + "\x0enum_partitions\x18\x02 \x01(\v2,.solana.storage.ConfirmedBlock.NumPartitionsR\rnumPartitions\"-\n" + + "\rUnixTimestamp\x12\x1c\n" + + "\ttimestamp\x18\x01 \x01(\x03R\ttimestamp\"0\n" + + "\vBlockHeight\x12!\n" + + "\fblock_height\x18\x01 \x01(\x04R\vblockHeight\"6\n" + + "\rNumPartitions\x12%\n" + + "\x0enum_partitions\x18\x01 \x01(\x04R\rnumPartitions*I\n" + + "\n" + + "RewardType\x12\x0f\n" + + "\vUnspecified\x10\x00\x12\a\n" + + "\x03Fee\x10\x01\x12\b\n" + + "\x04Rent\x10\x02\x12\v\n" + + "\aStaking\x10\x03\x12\n" + + "\n" + + "\x06Voting\x10\x04B;Z9github.com/rpcpool/yellowstone-grpc/examples/golang/protob\x06proto3" + +var ( + file_solana_storage_proto_rawDescOnce sync.Once + file_solana_storage_proto_rawDescData []byte +) + +func file_solana_storage_proto_rawDescGZIP() []byte { + file_solana_storage_proto_rawDescOnce.Do(func() { + file_solana_storage_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_solana_storage_proto_rawDesc), len(file_solana_storage_proto_rawDesc))) + }) + return file_solana_storage_proto_rawDescData +} + +var file_solana_storage_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_solana_storage_proto_msgTypes = make([]protoimpl.MessageInfo, 19) +var file_solana_storage_proto_goTypes = []any{ + (RewardType)(0), // 0: solana.storage.ConfirmedBlock.RewardType + (*ConfirmedBlock)(nil), // 1: solana.storage.ConfirmedBlock.ConfirmedBlock + (*ConfirmedTransaction)(nil), // 2: solana.storage.ConfirmedBlock.ConfirmedTransaction + (*Transaction)(nil), // 3: solana.storage.ConfirmedBlock.Transaction + (*Message)(nil), // 4: solana.storage.ConfirmedBlock.Message + (*MessageHeader)(nil), // 5: solana.storage.ConfirmedBlock.MessageHeader + (*MessageAddressTableLookup)(nil), // 6: solana.storage.ConfirmedBlock.MessageAddressTableLookup + (*TransactionStatusMeta)(nil), // 7: solana.storage.ConfirmedBlock.TransactionStatusMeta + (*TransactionError)(nil), // 8: solana.storage.ConfirmedBlock.TransactionError + (*InnerInstructions)(nil), // 9: solana.storage.ConfirmedBlock.InnerInstructions + (*InnerInstruction)(nil), // 10: solana.storage.ConfirmedBlock.InnerInstruction + (*CompiledInstruction)(nil), // 11: solana.storage.ConfirmedBlock.CompiledInstruction + (*TokenBalance)(nil), // 12: solana.storage.ConfirmedBlock.TokenBalance + (*UiTokenAmount)(nil), // 13: solana.storage.ConfirmedBlock.UiTokenAmount + (*ReturnData)(nil), // 14: solana.storage.ConfirmedBlock.ReturnData + (*Reward)(nil), // 15: solana.storage.ConfirmedBlock.Reward + (*Rewards)(nil), // 16: solana.storage.ConfirmedBlock.Rewards + (*UnixTimestamp)(nil), // 17: solana.storage.ConfirmedBlock.UnixTimestamp + (*BlockHeight)(nil), // 18: solana.storage.ConfirmedBlock.BlockHeight + (*NumPartitions)(nil), // 19: solana.storage.ConfirmedBlock.NumPartitions +} +var file_solana_storage_proto_depIdxs = []int32{ + 2, // 0: solana.storage.ConfirmedBlock.ConfirmedBlock.transactions:type_name -> solana.storage.ConfirmedBlock.ConfirmedTransaction + 15, // 1: solana.storage.ConfirmedBlock.ConfirmedBlock.rewards:type_name -> solana.storage.ConfirmedBlock.Reward + 17, // 2: solana.storage.ConfirmedBlock.ConfirmedBlock.block_time:type_name -> solana.storage.ConfirmedBlock.UnixTimestamp + 18, // 3: solana.storage.ConfirmedBlock.ConfirmedBlock.block_height:type_name -> solana.storage.ConfirmedBlock.BlockHeight + 19, // 4: solana.storage.ConfirmedBlock.ConfirmedBlock.num_partitions:type_name -> solana.storage.ConfirmedBlock.NumPartitions + 3, // 5: solana.storage.ConfirmedBlock.ConfirmedTransaction.transaction:type_name -> solana.storage.ConfirmedBlock.Transaction + 7, // 6: solana.storage.ConfirmedBlock.ConfirmedTransaction.meta:type_name -> solana.storage.ConfirmedBlock.TransactionStatusMeta + 4, // 7: solana.storage.ConfirmedBlock.Transaction.message:type_name -> solana.storage.ConfirmedBlock.Message + 5, // 8: solana.storage.ConfirmedBlock.Message.header:type_name -> solana.storage.ConfirmedBlock.MessageHeader + 11, // 9: solana.storage.ConfirmedBlock.Message.instructions:type_name -> solana.storage.ConfirmedBlock.CompiledInstruction + 6, // 10: solana.storage.ConfirmedBlock.Message.address_table_lookups:type_name -> solana.storage.ConfirmedBlock.MessageAddressTableLookup + 8, // 11: solana.storage.ConfirmedBlock.TransactionStatusMeta.err:type_name -> solana.storage.ConfirmedBlock.TransactionError + 9, // 12: solana.storage.ConfirmedBlock.TransactionStatusMeta.inner_instructions:type_name -> solana.storage.ConfirmedBlock.InnerInstructions + 12, // 13: solana.storage.ConfirmedBlock.TransactionStatusMeta.pre_token_balances:type_name -> solana.storage.ConfirmedBlock.TokenBalance + 12, // 14: solana.storage.ConfirmedBlock.TransactionStatusMeta.post_token_balances:type_name -> solana.storage.ConfirmedBlock.TokenBalance + 15, // 15: solana.storage.ConfirmedBlock.TransactionStatusMeta.rewards:type_name -> solana.storage.ConfirmedBlock.Reward + 14, // 16: solana.storage.ConfirmedBlock.TransactionStatusMeta.return_data:type_name -> solana.storage.ConfirmedBlock.ReturnData + 10, // 17: solana.storage.ConfirmedBlock.InnerInstructions.instructions:type_name -> solana.storage.ConfirmedBlock.InnerInstruction + 13, // 18: solana.storage.ConfirmedBlock.TokenBalance.ui_token_amount:type_name -> solana.storage.ConfirmedBlock.UiTokenAmount + 0, // 19: solana.storage.ConfirmedBlock.Reward.reward_type:type_name -> solana.storage.ConfirmedBlock.RewardType + 15, // 20: solana.storage.ConfirmedBlock.Rewards.rewards:type_name -> solana.storage.ConfirmedBlock.Reward + 19, // 21: solana.storage.ConfirmedBlock.Rewards.num_partitions:type_name -> solana.storage.ConfirmedBlock.NumPartitions + 22, // [22:22] is the sub-list for method output_type + 22, // [22:22] is the sub-list for method input_type + 22, // [22:22] is the sub-list for extension type_name + 22, // [22:22] is the sub-list for extension extendee + 0, // [0:22] is the sub-list for field type_name +} + +func init() { file_solana_storage_proto_init() } +func file_solana_storage_proto_init() { + if File_solana_storage_proto != nil { + return + } + file_solana_storage_proto_msgTypes[6].OneofWrappers = []any{} + file_solana_storage_proto_msgTypes[9].OneofWrappers = []any{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_solana_storage_proto_rawDesc), len(file_solana_storage_proto_rawDesc)), + NumEnums: 1, + NumMessages: 19, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_solana_storage_proto_goTypes, + DependencyIndexes: file_solana_storage_proto_depIdxs, + EnumInfos: file_solana_storage_proto_enumTypes, + MessageInfos: file_solana_storage_proto_msgTypes, + }.Build() + File_solana_storage_proto = out.File + file_solana_storage_proto_goTypes = nil + file_solana_storage_proto_depIdxs = nil +} diff --git a/example/geyser/proto/solana-storage.proto b/example/geyser/proto/solana-storage.proto new file mode 100644 index 0000000..5cf4bde --- /dev/null +++ b/example/geyser/proto/solana-storage.proto @@ -0,0 +1,149 @@ +syntax = "proto3"; + +package solana.storage.ConfirmedBlock; + +option go_package = "github.com/rpcpool/yellowstone-grpc/examples/golang/proto"; + +message ConfirmedBlock { + string previous_blockhash = 1; + string blockhash = 2; + uint64 parent_slot = 3; + repeated ConfirmedTransaction transactions = 4; + repeated Reward rewards = 5; + UnixTimestamp block_time = 6; + BlockHeight block_height = 7; + NumPartitions num_partitions = 8; +} + +message ConfirmedTransaction { + Transaction transaction = 1; + TransactionStatusMeta meta = 2; +} + +message Transaction { + repeated bytes signatures = 1; + Message message = 2; +} + +message Message { + MessageHeader header = 1; + repeated bytes account_keys = 2; + bytes recent_blockhash = 3; + repeated CompiledInstruction instructions = 4; + bool versioned = 5; + repeated MessageAddressTableLookup address_table_lookups = 6; +} + +message MessageHeader { + uint32 num_required_signatures = 1; + uint32 num_readonly_signed_accounts = 2; + uint32 num_readonly_unsigned_accounts = 3; +} + +message MessageAddressTableLookup { + bytes account_key = 1; + bytes writable_indexes = 2; + bytes readonly_indexes = 3; +} + +message TransactionStatusMeta { + TransactionError err = 1; + uint64 fee = 2; + repeated uint64 pre_balances = 3; + repeated uint64 post_balances = 4; + repeated InnerInstructions inner_instructions = 5; + bool inner_instructions_none = 10; + repeated string log_messages = 6; + bool log_messages_none = 11; + repeated TokenBalance pre_token_balances = 7; + repeated TokenBalance post_token_balances = 8; + repeated Reward rewards = 9; + repeated bytes loaded_writable_addresses = 12; + repeated bytes loaded_readonly_addresses = 13; + ReturnData return_data = 14; + bool return_data_none = 15; + + // Sum of compute units consumed by all instructions. + // Available since Solana v1.10.35 / v1.11.6. + // Set to `None` for txs executed on earlier versions. + optional uint64 compute_units_consumed = 16; +} + +message TransactionError { + bytes err = 1; +} + +message InnerInstructions { + uint32 index = 1; + repeated InnerInstruction instructions = 2; +} + +message InnerInstruction { + uint32 program_id_index = 1; + bytes accounts = 2; + bytes data = 3; + + // Invocation stack height of an inner instruction. + // Available since Solana v1.14.6 + // Set to `None` for txs executed on earlier versions. + optional uint32 stack_height = 4; +} + +message CompiledInstruction { + uint32 program_id_index = 1; + bytes accounts = 2; + bytes data = 3; +} + +message TokenBalance { + uint32 account_index = 1; + string mint = 2; + UiTokenAmount ui_token_amount = 3; + string owner = 4; + string program_id = 5; +} + +message UiTokenAmount { + double ui_amount = 1; + uint32 decimals = 2; + string amount = 3; + string ui_amount_string = 4; +} + +message ReturnData { + bytes program_id = 1; + bytes data = 2; +} + +enum RewardType { + Unspecified = 0; + Fee = 1; + Rent = 2; + Staking = 3; + Voting = 4; +} + +message Reward { + string pubkey = 1; + int64 lamports = 2; + uint64 post_balance = 3; + RewardType reward_type = 4; + string commission = 5; +} + +message Rewards { + repeated Reward rewards = 1; + NumPartitions num_partitions = 2; +} + +message UnixTimestamp { + int64 timestamp = 1; +} + +message BlockHeight { + uint64 block_height = 1; +} + +message NumPartitions { + uint64 num_partitions = 1; +} \ No newline at end of file diff --git a/example/geyser/pump.go b/example/geyser/pump.go new file mode 100644 index 0000000..1b6f325 --- /dev/null +++ b/example/geyser/pump.go @@ -0,0 +1,60 @@ +package geyser + +import ( + "fmt" + + "github.com/shopspring/decimal" + types "github.com/thloyi/pump-parser" +) + +type PumpHandler struct { + callback func(*types.Tx, *types.RawTx) +} + +func NewPumpHandler(cb func(*types.Tx, *types.RawTx)) *PumpHandler { + return &PumpHandler{ + callback: func(tx *types.Tx, tx2 *types.RawTx) { + //tx.Check(tx2) + cb(tx, tx2) + }, + } +} + +func (h *PumpHandler) HandleMessage(rawTx *types.RawTx) { + if rawTx.Meta.Err != nil { + // Notify the channel about the failed transaction + beforeSolBalance := decimal.Zero + afterSolBalance := decimal.Zero + if rawTx.Meta.PreBalances != nil && len(rawTx.Meta.PreBalances) > 0 { + beforeSolBalance = decimal.NewFromUint64(rawTx.Meta.PreBalances[0]).Div(decimal.NewFromInt(1e9)) + } + if rawTx.Meta.PostBalances != nil && len(rawTx.Meta.PostBalances) > 0 { + afterSolBalance = decimal.NewFromUint64(rawTx.Meta.PostBalances[0]).Div(decimal.NewFromInt(1e9)) + } + h.callback(&types.Tx{ + TxHash: (*[64]byte)((rawTx.Transaction.Signatures[0][:])), + Err: rawTx.Meta.Err, + Signer: rawTx.GetSigner(), + Block: rawTx.Slot, + BlockIndex: uint64(rawTx.IndexWithinBlock), + + BeforeSolBalance: beforeSolBalance, + AfterSOLBalance: afterSolBalance, + }, rawTx) + return + } + + parsedTx, err := types.Parser(rawTx) + if err != nil { + fmt.Printf("parser error: %s, block: %d tx: %s\n", err, rawTx.Slot, rawTx.TxHash()) + return + } + if len(parsedTx.Swaps) == 0 { + // no swap, ignore + return + } + // fmt.Println(parsedTx.GetTxHash(), len(parsedTx.Swaps)) + if h.callback != nil { + h.callback(parsedTx, rawTx) + } +} diff --git a/example/geyser/yellowstone.go b/example/geyser/yellowstone.go new file mode 100644 index 0000000..3c8e928 --- /dev/null +++ b/example/geyser/yellowstone.go @@ -0,0 +1,527 @@ +package geyser + +import ( + "context" + "crypto/x509" + "encoding/json" + "fmt" + "io" + "log" + "time" + + solana2 "github.com/gagliardetto/solana-go" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/keepalive" + "google.golang.org/grpc/metadata" + + types "github.com/thloyi/pump-parser" + pb "github.com/thloyi/pump-parser/example/geyser/proto" +) + +type Handler interface { + HandleMessage(rawTx *types.RawTx) +} + +var kacp = keepalive.ClientParameters{ + Time: 10 * time.Second, // send pings every 10 seconds if there is no activity + Timeout: time.Second, // wait 1 second for ping ack before considering the connection dead + PermitWithoutStream: true, // send pings even without active streams +} + +type Client struct { + ch chan SubscriptionMessage + endpoint string + conn *grpc.ClientConn + ctx context.Context + lastReceiveTime time.Time + backoffFactor float64 + + subscription *pb.SubscribeRequest + subStatus bool + + leastBlock BlockInfo + + firstMessage bool + + handler Handler +} + +func NewClientWithPumpSwap(endpoint string, ch chan SubscriptionMessage) *Client { + var subscription pb.SubscribeRequest + + var failed = false + var vote = false + subscription.Transactions = make(map[string]*pb.SubscribeRequestFilterTransactions) + subscription.Transactions["transactions_sub"] = &pb.SubscribeRequestFilterTransactions{ + Failed: &failed, + Vote: &vote, + } + + subscription.Transactions["transactions_sub"].AccountInclude = []string{ + "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", //Pump AMM + "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", //Pump + } + subscription.BlocksMeta = make(map[string]*pb.SubscribeRequestFilterBlocksMeta) + subscription.BlocksMeta["block_meta"] = &pb.SubscribeRequestFilterBlocksMeta{} + + c := &Client{ + backoffFactor: 1.5, + ch: ch, + endpoint: endpoint, + lastReceiveTime: time.Now(), + subStatus: false, + subscription: &subscription, + } + c.handler = NewPumpHandler(func(tx *types.Tx, tx2 *types.RawTx) { + c.sendTx(tx, tx2) + }) + return c +} + +func NewClientWithLaunchLab(endpoint string, ch chan SubscriptionMessage) *Client { + var subscription pb.SubscribeRequest + + var failed = false + var vote = false + subscription.Transactions = make(map[string]*pb.SubscribeRequestFilterTransactions) + subscription.Transactions["transactions_sub"] = &pb.SubscribeRequestFilterTransactions{ + Failed: &failed, + Vote: &vote, + } + + subscription.Transactions["transactions_sub"].AccountInclude = []string{ + "LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj", //LaunchLab + "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C", //CPMM + //"675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8", //V4 + } + subscription.BlocksMeta = make(map[string]*pb.SubscribeRequestFilterBlocksMeta) + subscription.BlocksMeta["block_meta"] = &pb.SubscribeRequestFilterBlocksMeta{} + + c := &Client{ + backoffFactor: 1.5, + ch: ch, + endpoint: endpoint, + lastReceiveTime: time.Now(), + subStatus: false, + subscription: &subscription, + } + c.handler = NewPumpHandler(func(tx *types.Tx, tx2 *types.RawTx) { + c.sendTx(tx, tx2) + }) + return c +} + +func RunLoopWithReConnect(ctx context.Context, endpoint, program string, ch chan SubscriptionMessage) { + var client *Client + if program == types.SolProgramRaydiumLaunchLab { + client = NewClientWithLaunchLab(endpoint, ch) + } else { + client = NewClientWithPumpSwap(endpoint, ch) + } + for { + select { + case <-ctx.Done(): + log.Println("Context done, exiting loop") + return + default: + } + err := client.Connect(ctx) + if err != nil { + log.Printf("Failed to connect: %v", err) + time.Sleep(5 * time.Second) + continue + } + // should not reach here, because Connect will block + panic("geyser already connected, waiting for messages...") + } +} + +func (c *Client) SetSubscribe(subscription *pb.SubscribeRequest) { + c.subscription = subscription +} + +func (c *Client) Connect(ctx context.Context) error { + + c.ctx = ctx + if c.conn == nil { + // 连接到 geyser + conn, err := c.grpcConnect(c.endpoint, true) + if err != nil { + return err + } + c.conn = conn + } + + if c.subStatus { + return nil // 已经订阅了 + } + // 订阅交易 + err := c.grpcSubscribe(ctx, c.conn) + if err != nil { + if c.conn != nil { + c.conn.Close() + } + c.conn = nil + c.subStatus = false + log.Printf("Failed to subscribe: %v", err) + return err + } + + return nil +} + +func (c *Client) grpcConnect(address string, plaintext bool) (*grpc.ClientConn, error) { + var opts []grpc.DialOption + if plaintext { + opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) + } else { + pool, _ := x509.SystemCertPool() + creds := credentials.NewClientTLSFromCert(pool, "") + opts = append(opts, grpc.WithTransportCredentials(creds)) + } + + opts = append(opts, grpc.WithKeepaliveParams(kacp)) + + log.Println("Starting grpc client, connecting to", address) + conn, err := grpc.NewClient(address, opts...) + if err != nil { + return nil, fmt.Errorf("fail to dial: %v", err) + } + + return conn, nil +} + +func (c *Client) grpcSubscribe(ctx context.Context, conn *grpc.ClientConn) error { + var err error + client := pb.NewGeyserClient(conn) + + //subscription.Transactions["transactions_sub"].AccountExclude = transactionsAccountsExclude + + subscriptionJson, err := json.Marshal(c.subscription) + if err != nil { + log.Printf("Failed to marshal subscription request: %v", subscriptionJson) + return err + } + log.Printf("Subscription request: %s", string(subscriptionJson)) + + // Set up the subscription request + //if *token != "" { + // md := metadata.New(map[string]string{"x-token": *token}) + // ctx = metadata.NewOutgoingContext(ctx, md) + //} + md := metadata.New(map[string]string{"x-token": "5adcf1f9-5719-43d1-bf3f-c2d4e1e5f94d"}) + ctx = metadata.NewOutgoingContext(ctx, md) + + stream, err := client.Subscribe(ctx) + if err != nil { + return err + } + err = stream.Send(c.subscription) + if err != nil { + return err + } + c.subStatus = true + c.firstMessage = true + for { + resp, err := stream.Recv() + + if err == io.EOF { + return err + } + if err != nil { + return fmt.Errorf("error occurred in receiving update: %s", err) + } + + txn := resp.GetTransaction() + if txn == nil { + blockMeta := resp.GetBlockMeta() + if blockMeta != nil && c.ch != nil { + c.sendBlock(blockMeta) + } + continue + } + rawTx, err := ConvertYellowstoneGrpcTransactionToSolanaTransaction(txn, resp.GetCreatedAt().Seconds) + if err != nil { + log.Printf("Failed to convert transaction: %v", err) + continue + } + c.handler.HandleMessage(rawTx) + } +} + +func (c *Client) computeDelay(slot uint64) int64 { + if c.leastBlock.Slot == 0 { + return 0 + } + if slot < c.leastBlock.Slot { + return 0 + } + delay := time.Now().Unix() - c.leastBlock.BlockTime - (4 * int64(slot-c.leastBlock.Slot) / 10) + return delay +} + +func (c *Client) sendTx(t *types.Tx, tx *types.RawTx) { + c.ch <- SubscriptionMessage{ + Reconnect: c.firstMessage, + EstimateDelaySecond: c.computeDelay(tx.Slot), + Block: nil, + Tx: t, + RawTx: tx, + } + c.firstMessage = false +} + +func (c *Client) sendBlock(blockMeta *pb.SubscribeUpdateBlockMeta) { + c.leastBlock.Slot = blockMeta.GetSlot() + c.leastBlock.BlockTime = blockMeta.GetBlockTime().Timestamp + c.leastBlock.BlockHash = blockMeta.Blockhash + c.leastBlock.Height = blockMeta.BlockHeight.BlockHeight + c.ch <- SubscriptionMessage{ + EstimateDelaySecond: time.Now().Unix() - blockMeta.GetBlockTime().Timestamp, + Reconnect: c.firstMessage, + Block: &BlockInfo{ + Slot: c.leastBlock.Slot, + BlockTime: c.leastBlock.BlockTime, + BlockHash: c.leastBlock.BlockHash, + Height: c.leastBlock.Height, + }, + Tx: nil, + RawTx: nil, + } + c.firstMessage = false +} + +func ConvertYellowstoneGrpcTransactionToSolanaTransaction(y *pb.SubscribeUpdateTransaction, created int64) (*types.RawTx, error) { + sTx := &types.RawTx{ + BlockTime: created, + Slot: y.Slot, + IndexWithinBlock: int64(y.Transaction.Index), + Meta: types.Meta{ + Err: nil, + Fee: 0, + InnerInstructions: nil, + LoadedAddresses: types.LoadedAddresses{}, + LogMessages: nil, + PostBalances: nil, + PostTokenBalances: nil, + PreBalances: nil, + PreTokenBalances: nil, + Rewards: nil, + }, + //Transaction: types.Transaction{ + // Message: types.Message{ + // AccountKeys: nil, + // AddressTableLookups: nil, + // Header: types.Header{}, + // Instructions: nil, + // RecentBlockHash: "", + // }, + // Signatures: nil, + //}, + //Version: nil, + } + meta := y.Transaction.GetMeta() + yTx := y.Transaction.Transaction + + if meta.Err != nil && len(meta.Err.GetErr()) > 0 { + // If the transaction has an error, we set the error in the Meta + transError, err := DecodeTransactionError(meta.Err.GetErr()) + if err != nil { + sTx.Meta.Err = err + } else { + sTx.Meta.Err = transError + } + // sTx.Meta.Err = meta.Err.GetErr() + } + sTx.Meta.Fee = meta.Fee + //sTx.Meta.InnerInstructions = meta.InnerInstructions + + for _, innerInstr := range meta.InnerInstructions { + var instrs []types.Instruction + for _, instr := range innerInstr.Instructions { + instrs = append(instrs, types.Instruction{ + ProgramIDIndex: int(instr.ProgramIdIndex), + Accounts: func() []int { + var out []int + for i := range instr.Accounts { + out = append(out, int(instr.Accounts[i])) + } + return out + }(), + Data: instr.Data, + }) + } + sTx.Meta.InnerInstructions = append(sTx.Meta.InnerInstructions, types.InnerInstructions{ + Index: int(innerInstr.Index), + Instructions: instrs, + }) + } + sTx.Meta.LogMessages = meta.LogMessages + sTx.Meta.PostBalances = meta.PostBalances + sTx.Meta.PostTokenBalances = grpcTokenBalance(meta.PostTokenBalances) + sTx.Meta.PreBalances = meta.PreBalances + sTx.Meta.PreTokenBalances = grpcTokenBalance(meta.PreTokenBalances) + sTx.Meta.Rewards = nil + sTx.Meta.LoadedAddresses.Readonly = byteSlicesToKeySlices(meta.LoadedReadonlyAddresses) + sTx.Meta.LoadedAddresses.Writable = byteSlicesToKeySlices(meta.LoadedWritableAddresses) + + // copy signatures + for i := range yTx.Signatures { + sTx.Transaction.Signatures = append(sTx.Transaction.Signatures, solana2.SignatureFromBytes(yTx.Signatures[i])) + } + // copy message + sTx.Transaction.Message = types.Message{ + RecentBlockHash: solana2.HashFromBytes(yTx.Message.RecentBlockhash).String(), + } + // copy message.AccountKeys + //stopAt := len(yTx.Message.AccountKeys) - sTx.Message.NumLookups() + stopAt := len(yTx.Message.AccountKeys) + for accIndex, acc := range yTx.Message.AccountKeys { + sTx.Transaction.Message.AccountKeys = append(sTx.Transaction.Message.AccountKeys, solana2.PublicKeyFromBytes(acc)) + if accIndex == stopAt-1 { + break + } + } + // copy message.Header + sTx.Transaction.Message.Header = types.Header{ + NumRequiredSignatures: int(yTx.Message.Header.NumRequiredSignatures), + NumReadonlySignedAccounts: int(yTx.Message.Header.NumReadonlySignedAccounts), + NumReadonlyUnsignedAccounts: int(yTx.Message.Header.NumReadonlyUnsignedAccounts), + } + + // copy message.versioned + if yTx.Message.Versioned { + sTx.Version = solana2.MessageVersionV0 + } else { + sTx.Version = solana2.MessageVersionLegacy + } + + // copy address table lookups + { + tables := map[solana2.PublicKey]solana2.PublicKeySlice{} + writable := byteSlicesToKeySlices(meta.LoadedWritableAddresses) + readonly := byteSlicesToKeySlices(meta.LoadedReadonlyAddresses) + for _, addr := range yTx.Message.AddressTableLookups { + sTx.Transaction.Message.AddressTableLookups = append(sTx.Transaction.Message.AddressTableLookups, solana2.MessageAddressTableLookup{ + AccountKey: solana2.PublicKeyFromBytes(addr.AccountKey), + WritableIndexes: addr.WritableIndexes, + ReadonlyIndexes: addr.ReadonlyIndexes, + }) + numTakeWritable := len(addr.WritableIndexes) + numTakeReadonly := len(addr.ReadonlyIndexes) + tableKey := solana2.PublicKeyFromBytes(addr.AccountKey) + { + // now need to rebuild the address table taking into account the indexes, and put the keys into the tables + maxIndex := 0 + for _, indexB := range addr.WritableIndexes { + index := int(indexB) + if index > maxIndex { + maxIndex = index + } + } + for _, indexB := range addr.ReadonlyIndexes { + index := int(indexB) + if index > maxIndex { + maxIndex = index + } + } + tables[tableKey] = make([]solana2.PublicKey, maxIndex+1) + } + if numTakeWritable > 0 { + writableForTable := writable[:numTakeWritable] + for i, indexB := range addr.WritableIndexes { + index := int(indexB) + tables[tableKey][index] = writableForTable[i] + } + writable = writable[numTakeWritable:] + } + if numTakeReadonly > 0 { + readableForTable := readonly[:numTakeReadonly] + for i, indexB := range addr.ReadonlyIndexes { + index := int(indexB) + tables[tableKey][index] = readableForTable[i] + } + readonly = readonly[numTakeReadonly:] + } + + } + } + + // copy instructions + for _, instr := range yTx.Message.Instructions { + sTx.Transaction.Message.Instructions = append(sTx.Transaction.Message.Instructions, types.Instruction{ + ProgramIDIndex: int(instr.ProgramIdIndex), + Accounts: func() []int { + var out []int + for i := range instr.Accounts { + out = append(out, int(instr.Accounts[i])) + } + return out + }(), + Data: instr.Data, + }) + } + + // resolve the lookups + //{ + // if sTx.Transaction.Message.IsVersioned() { + // // only versioned transactions have address table lookups + // err := sTx.Transaction.Message.ResolveLookups() + // if err != nil { + // return sTx, fmt.Errorf("failed to resolve lookups: %w", err) + // } + // } + //} + + return sTx, nil +} + +func byteSlicesToKeySlices(keys [][]byte) []solana2.PublicKey { + var out []solana2.PublicKey + for _, key := range keys { + var k solana2.PublicKey + copy(k[:], key) + out = append(out, k) + } + return out +} + +func grpcTokenBalance(src []*pb.TokenBalance) []types.TokenBalance { + out := make([]types.TokenBalance, len(src)) + for i, tb := range src { + var ( + mintAccount solana2.PublicKey + ownerAccount solana2.PublicKey + programIDAccount solana2.PublicKey + ) + + if tb.Mint != "" { + mintAccount, _ = solana2.PublicKeyFromBase58(tb.Mint) + } + if tb.Owner != "" { + ownerAccount, _ = solana2.PublicKeyFromBase58(tb.Owner) + } + if tb.ProgramId != "" { + programIDAccount, _ = solana2.PublicKeyFromBase58(tb.ProgramId) + } + + out[i] = types.TokenBalance{ + AccountIndex: int(tb.AccountIndex), + MintAccount: mintAccount, + OwnerAccount: &ownerAccount, + ProgramIDAccount: programIDAccount, + Mint: tb.Mint, + Owner: tb.Owner, + ProgramID: tb.ProgramId, + UITokenAmount: types.UITokenAmount{ + Amount: tb.UiTokenAmount.Amount, + Decimals: uint64(tb.UiTokenAmount.Decimals), + UIAmount: tb.UiTokenAmount.UiAmount, + UIAmountString: tb.UiTokenAmount.UiAmountString, + }, + } + } + return out +} diff --git a/example/tx.go b/example/tx.go new file mode 100644 index 0000000..a8f0ed2 --- /dev/null +++ b/example/tx.go @@ -0,0 +1,229 @@ +package example + +import ( + "time" + + "github.com/gagliardetto/solana-go" + "github.com/jackc/pgtype" + "github.com/mr-tron/base58" + "github.com/shopspring/decimal" + parser "github.com/thloyi/pump-parser" +) + +type Tx struct { + Err interface{} `json:"err,omitempty" gorm:"-"` + BondingCurve string `json:"bonding_curve" gorm:"-"` + PairAddress string `json:"pair_address"` + Maker string `json:"maker"` + Token0Address string `json:"token0_address"` + Token0Program string `json:"token0_program" gorm:"-"` + Token0Decimals uint8 `json:"token0_decimals" gorm:"-"` + Token1Address string `json:"token1_address"` + Token0Amount decimal.Decimal `json:"token0Amount" gorm:"column:token0_amount;type:numeric"` + Token1Amount decimal.Decimal `json:"token1Amount" gorm:"column:token1_amount;type:numeric"` + PriceUsd decimal.Decimal `json:"price_usd" gorm:"column:price_usd;type:numeric"` + AmountUsd decimal.Decimal `json:"amount_usd" gorm:"column:amount_usd;type:numeric"` + Block uint64 `json:"block"` + BlockIndex uint64 `json:"index"` + Event string `json:"event"` + CachedTxHash string `json:"tx_hash" gorm:"column:tx_hash"` + txHash *[64]byte `gorm:"-"` + TxIndex uint64 `json:"topic_index"` + Program string `json:"program"` + BlockAt pgtype.Timestamptz `gorm:"column:block_at;default:NULL" json:"block_at"` + CreatedAt *pgtype.Timestamptz `gorm:"autoCreateTime" json:"-"` + TotalSupply string `gorm:"total_supply"` + AfterReserve0 string `gorm:"after_reserve0"` + AfterReserve1 string `gorm:"after_reserve1"` + PositionChange int64 `gorm:"position_change"` + QuoteIsToken0 bool `gorm:"-"` + CurrentPrice decimal.Decimal `gorm:"-"` + TokenCreator string `gorm:"-"` + Platform string `gorm:"column:tx_platform;type:platform;default:'none'" json:"platform"` + MevAgent string `gorm:"column:tx_mev_agent;type:mev_agent;default:'none'" json:"tx_mev_agent"` + MevAgentFee decimal.Decimal `gorm:"column:tx_mev_agent_fee;type:numeric" json:"tx_mev_agent_fee"` + CUPrice decimal.Decimal `gorm:"column:tx_cu_price;type:numeric" json:"tx_cu_price"` + PlatformFee decimal.Decimal `gorm:"-"` + + AfterSignerToken0Balance decimal.Decimal `gorm:"-" json:"-"` + BeforeSolBalance decimal.Decimal `gorm:"-" json:"-"` + AfterSOLBalance decimal.Decimal `gorm:"column:after_sol_balance;type:numeric" json:"after_sol_balance"` + EntryContract string `gorm:"column:tx_entry_contract;type:entry_contract;default:'none'" json:"tx_entry_contract"` + + Mayhem bool +} + +func (tx *Tx) GetTxHash() string { + if tx.CachedTxHash != "" { + return tx.CachedTxHash + } + if tx.txHash == nil { + return "" + } + tx.CachedTxHash = base58.Encode(tx.txHash[:]) + return tx.CachedTxHash +} + +func FromTx(tx *parser.Tx, raw *parser.RawTx) []*Tx { + var txs []*Tx = make([]*Tx, 0, len(tx.Swaps)) + mev, mevFee := tx.CheckMevAgent() + for i, s := range tx.Swaps { + var newTx *Tx + platform, platformFee := tx.CheckPlatform(s, raw) + token0Program := s.BaseTokenProgram + token0Address := s.BaseMint + if s.Program == "Pump" { + newTx = &Tx{ + Err: nil, + BondingCurve: s.Pool.String(), + //PairAddress: s.Pool.String(), + Maker: s.User.String(), + Token0Address: s.BaseMint.String(), + Token0Program: s.BaseTokenProgram.String(), + Token0Decimals: s.BaseMintDecimals, + Token1Address: "", + Token0Amount: s.BaseAmount.Div(decimal.NewFromInt(1e6)), + Token1Amount: s.QuoteAmount.Div(decimal.NewFromInt(1e9)), + Block: tx.Block, + BlockIndex: tx.BlockIndex, + Event: s.Event, + CachedTxHash: "", + txHash: tx.TxHash, + TxIndex: uint64(i), + Program: s.Program, + BlockAt: pgtype.Timestamptz{ + Time: time.Unix(tx.BlockAt, 0), + }, + //CreatedAt: nil, + TotalSupply: "1000000000", + AfterReserve0: s.BaseReserve.Div(decimal.New(1, int32(s.BaseMintDecimals))).String(), + AfterReserve1: s.QuoteReserve.Div(decimal.New(1, int32(s.QuoteMintDecimals))).String(), + QuoteIsToken0: false, + // CurrentPrice: decimal.Decimal{}, + TokenCreator: s.Creator.String(), + Platform: platform, + PlatformFee: platformFee, + + MevAgent: mev, + MevAgentFee: mevFee, + CUPrice: tx.CUPrice, + + AfterSignerToken0Balance: s.UserBaseBalance.Div(decimal.New(1, int32(s.BaseMintDecimals))), + + BeforeSolBalance: tx.BeforeSolBalance, + AfterSOLBalance: tx.AfterSOLBalance, + + EntryContract: s.CheckEntryContract(), + Mayhem: s.Mayhem, + } + } else if s.Program == "PumpAMM" { + if s.BaseMint.Equals(solana.WrappedSol) { + eventName := s.Event + if s.Event == "buy" { + eventName = "sell" + } else if s.Event == "sell" { + eventName = "buy" + } + token0Program = s.QuoteTokenProgram + token0Address = s.QuoteMint + newTx = &Tx{ + Err: nil, + //BondingCurve: s.Pool.String(), + PairAddress: s.Pool.String(), + Maker: s.User.String(), + Token1Address: s.BaseMint.String(), + Token0Program: s.QuoteTokenProgram.String(), + Token0Decimals: s.QuoteMintDecimals, + Token0Address: s.QuoteMint.String(), + Token1Amount: s.BaseAmount.Div(decimal.New(1, int32(s.BaseMintDecimals))), + Token0Amount: s.QuoteAmount.Div(decimal.New(1, int32(s.QuoteMintDecimals))), + Block: tx.Block, + BlockIndex: tx.BlockIndex, + Event: eventName, + CachedTxHash: "", + txHash: tx.TxHash, + TxIndex: uint64(i), + Program: s.Program, + BlockAt: pgtype.Timestamptz{ + Time: time.Unix(tx.BlockAt, 0), + }, + //CreatedAt: nil, + TotalSupply: "1000000000", + AfterReserve1: s.BaseReserve.Div(decimal.New(1, int32(s.BaseMintDecimals))).String(), + AfterReserve0: s.QuoteReserve.Div(decimal.New(1, int32(s.QuoteMintDecimals))).String(), + QuoteIsToken0: true, + // CurrentPrice: decimal.Decimal{}, + TokenCreator: s.Creator.String(), + Platform: platform, + PlatformFee: platformFee, + + MevAgent: mev, + MevAgentFee: mevFee, + CUPrice: tx.CUPrice, + + AfterSignerToken0Balance: s.UserQuoteBalance.Div(decimal.New(1, int32(s.QuoteMintDecimals))), + + BeforeSolBalance: tx.BeforeSolBalance, + AfterSOLBalance: tx.AfterSOLBalance, + + EntryContract: s.CheckEntryContract(), + Mayhem: s.Mayhem, + } + } else { + newTx = &Tx{ + Err: nil, + //BondingCurve: s.Pool.String(), + PairAddress: s.Pool.String(), + Maker: s.User.String(), + Token0Address: s.BaseMint.String(), + Token0Program: s.BaseTokenProgram.String(), + Token0Decimals: s.BaseMintDecimals, + Token1Address: s.QuoteMint.String(), + Token0Amount: s.BaseAmount.Div(decimal.New(1, int32(s.BaseMintDecimals))), + Token1Amount: s.QuoteAmount.Div(decimal.New(1, int32(s.QuoteMintDecimals))), + Block: tx.Block, + BlockIndex: tx.BlockIndex, + Event: s.Event, + CachedTxHash: "", + txHash: tx.TxHash, + TxIndex: uint64(i), + Program: s.Program, + BlockAt: pgtype.Timestamptz{ + Time: time.Unix(tx.BlockAt, 0), + }, + //CreatedAt: nil, + TotalSupply: "1000000000", + AfterReserve0: s.BaseReserve.Div(decimal.New(1, int32(s.BaseMintDecimals))).String(), + AfterReserve1: s.QuoteReserve.Div(decimal.New(1, int32(s.QuoteMintDecimals))).String(), + QuoteIsToken0: false, + // CurrentPrice: decimal.Decimal{}, + TokenCreator: s.Creator.String(), + Platform: platform, + PlatformFee: platformFee, + + MevAgent: mev, + MevAgentFee: mevFee, + CUPrice: tx.CUPrice, + + AfterSignerToken0Balance: s.UserBaseBalance.Div(decimal.New(1, int32(s.BaseMintDecimals))), + + BeforeSolBalance: tx.BeforeSolBalance, + AfterSOLBalance: tx.AfterSOLBalance, + + EntryContract: s.CheckEntryContract(), + Mayhem: s.Mayhem, + } + } + } + if newTx == nil { + continue + } + if newTx.Maker == "HV1KXxWFaSeriyFvXyx48FqG9BoFbfinB8njCJonqP7K" && newTx.EntryContract == "oKXAggregatorV2" { + newTx.Maker = tx.Signer.String() + newTx.AfterSignerToken0Balance = parser.GetTokenBalanceAfterTx(raw, 0, token0Program, token0Address) + } + + txs = append(txs, newTx) + } + return txs +} diff --git a/globals.go b/globals.go new file mode 100644 index 0000000..8e2d13a --- /dev/null +++ b/globals.go @@ -0,0 +1,67 @@ +package pump_parser + +import ( + "errors" + + "github.com/gagliardetto/solana-go" +) + +var ( + WSOLString = "So11111111111111111111111111111111111111112" + WSOL = solana.MustPublicKeyFromBase58("So11111111111111111111111111111111111111112") + USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" +) + +const ( + SOLDecimals = 9 +) + +var ( + InstructionIgnoredError = errors.New("instruction ignored") +) + +type swapParser func(result *RawTx, instr Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) +type actionParser func(result *RawTx, instr Instruction, innerInstructions InnerInstructions, offset [2]uint, tx *Tx) ([2]uint, error) + +//type PumpComplete struct { +// IsMayhem bool +// IsToken2022 bool +//} + +//type PumpStatusCache map[solana.PublicKey]PumpComplete +// +//var ( +// pumpCompleteCache PumpStatusCache = make(map[solana.PublicKey]PumpComplete) +// pumpCompleteCacheLock sync.Mutex +//) +// +//func getPumpCompleteStatus(pumpToken solana.PublicKey) (PumpComplete, bool) { +// pumpCompleteCacheLock.Lock() +// defer pumpCompleteCacheLock.Unlock() +// status, exists := pumpCompleteCache[pumpToken] +// return status, exists +//} +// +//func setPumpCompleteStatus(pumpToken solana.PublicKey, mayhem bool, token2022 bool) { +// pumpCompleteCacheLock.Lock() +// defer pumpCompleteCacheLock.Unlock() +// pumpCompleteCache[pumpToken] = PumpComplete{ +// IsMayhem: mayhem, +// IsToken2022: token2022, +// } +//} +// +//func removePumpCompleteStatus(pumpToken solana.PublicKey) { +// pumpCompleteCacheLock.Lock() +// defer pumpCompleteCacheLock.Unlock() +// delete(pumpCompleteCache, pumpToken) +//} + +func isMayhemPump(feeAccount solana.PublicKey) bool { + for _, mayhemFeeAccount := range mayhemFeeAccounts { + if feeAccount.Equals(mayhemFeeAccount) { + return true + } + } + return false +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..b75ceed --- /dev/null +++ b/go.mod @@ -0,0 +1,46 @@ +module github.com/thloyi/pump-parser + +go 1.25.1 + +require ( + github.com/gagliardetto/binary v0.8.0 + github.com/gagliardetto/solana-go v1.14.0 + github.com/jackc/pgtype v1.14.4 + github.com/mr-tron/base58 v1.2.0 + github.com/shopspring/decimal v1.4.0 + google.golang.org/grpc v1.77.0 + google.golang.org/protobuf v1.36.10 +) + +require ( + filippo.io/edwards25519 v1.0.0 // indirect + github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect + github.com/blendle/zapdriver v1.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fatih/color v1.9.0 // indirect + github.com/gagliardetto/treeout v0.1.4 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/jackc/pgio v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.13.6 // indirect + github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect + github.com/streamingfast/logging v0.0.0-20250918142248-ac5a1e292845 // indirect + go.mongodb.org/mongo-driver v1.12.2 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/ratelimit v0.2.0 // indirect + go.uber.org/zap v1.21.0 // indirect + golang.org/x/crypto v0.43.0 // indirect + golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/term v0.36.0 // indirect + golang.org/x/text v0.30.0 // indirect + golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..2808d3f --- /dev/null +++ b/go.sum @@ -0,0 +1,344 @@ +filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= +filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= +github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI= +github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= +github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/gagliardetto/binary v0.8.0 h1:U9ahc45v9HW0d15LoN++vIXSJyqR/pWw8DDlhd7zvxg= +github.com/gagliardetto/binary v0.8.0/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= +github.com/gagliardetto/solana-go v1.14.0 h1:3WfAi70jOOjAJ0deFMjdhFYlLXATF4tOQXsDNWJtOLw= +github.com/gagliardetto/solana-go v1.14.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k= +github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= +github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= +github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= +github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= +github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= +github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= +github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag= +github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= +github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= +github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgtype v1.14.4 h1:fKuNiCumbKTAIxQwXfB/nsrnkEI6bPJrrSiMKgbJ2j8= +github.com/jackc/pgtype v1.14.4/go.mod h1:aKeozOde08iifGosdJpz9MBZonJOUJxqNpPBcMJTlVA= +github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= +github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= +github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.18.2 h1:xVpYkNR5pk5bMCZGfClbO962UIqVABcAGt7ha1s/FeU= +github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= +github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= +github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= +github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= +github.com/streamingfast/logging v0.0.0-20250918142248-ac5a1e292845 h1:VMA0pZ3MI8BErRA3kh8dKJThP5d0Xh5vZVk5yFIgH/A= +github.com/streamingfast/logging v0.0.0-20250918142248-ac5a1e292845/go.mod h1:BtDq81Tyc7H8up5aXNi/I95nPmG3C0PLEqGWY/iWQ2E= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= +github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +go.mongodb.org/mongo-driver v1.12.2 h1:gbWY1bJkkmUB9jjZzcdhOL8O85N9H+Vvsf2yFN0RDws= +go.mongodb.org/mongo-driver v1.12.2/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA= +go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= +golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 h1:6/3JGEh1C88g7m+qzzTbl3A0FtsLguXieqofVLU/JAo= +golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba h1:UKgtfRM7Yh93Sya0Fo8ZzhDP4qBckrrxEr2oF5UIVb8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= +google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/meta.go b/meta.go new file mode 100644 index 0000000..fc9e8dd --- /dev/null +++ b/meta.go @@ -0,0 +1,73 @@ +package pump_parser + +import ( + "github.com/gagliardetto/solana-go" +) + +var pumpProgram = solana.MustPublicKeyFromBase58("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P") +var pumpMigrationAccount = solana.MustPublicKeyFromBase58("39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg") +var mayhemFeeAccounts = []solana.PublicKey{ + solana.MustPublicKeyFromBase58("GesfTA3X2arioaHp8bbKdjG9vJtskViWACZoYvxp4twS"), + solana.MustPublicKeyFromBase58("4budycTjhs9fD6xw62VBducVTNgMgJJ5BgtKq7mAZwn6"), + solana.MustPublicKeyFromBase58("4UQeTP1T39KZ9Sfxzo3WR5skgsaP6NZa87BAkuazLEKH"), + solana.MustPublicKeyFromBase58("8SBKzEQU4nLSzcwF4a74F2iaUDQyTfjGndn6qUWBnrpR"), + solana.MustPublicKeyFromBase58("8sNeir4QsLsJdYpc9RZacohhK1Y5FLU3nC5LXgYB4aa6"), + solana.MustPublicKeyFromBase58("Fh9HmeLNUMVCvejxCtCL2DbYaRyBFVJ5xrWkLnMH6fdk"), + solana.MustPublicKeyFromBase58("463MEnMeGyJekNZFQSTUABBEbLnvMTALbT6ZmsxAbAdq"), + solana.MustPublicKeyFromBase58("6AUH3WEHucYZyC61hqpqYUWVto5qA5hjHuNQ32GNnNxA"), +} + +var pumpBuyDiscriminator = calculateDiscriminator("global:buy") +var pumpBuyV2Discriminator = calculateDiscriminator("global:buy_exact_sol_in") +var pumpSellDiscriminator = calculateDiscriminator("global:sell") +var pumpCreateDiscriminator = calculateDiscriminator("global:create") +var pumpCreateV2Discriminator = calculateDiscriminator("global:create_v2") +var pumpAdminSetCreatorDiscriminator = calculateDiscriminator("global:admin_set_creator") +var pumpMigrateDiscriminator = calculateDiscriminator("global:migrate") + +var pumpEventDiscriminator = [8]byte{228, 69, 165, 46, 81, 203, 154, 29} +var pumpTradeEventDiscriminator = [16]byte{228, 69, 165, 46, 81, 203, 154, 29, 189, 219, 127, 211, 78, 230, 97, 238} +var pumpCreateEventDiscriminator = [8]byte{27, 114, 169, 77, 222, 235, 99, 118} +var pumpCompleteEventDiscriminator = [8]byte{95, 114, 97, 156, 212, 46, 152, 8} +var pumpMigrateEventDiscriminator = calculateDiscriminator("event:CompletePumpAmmMigrationEvent") +var pumpBuyEventDiscriminator = [8]byte{189, 219, 127, 211, 78, 230, 97, 238} + +var ( + pumpAmmProgram = solana.MustPublicKeyFromBase58("pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA") + wSolMint = solana.MustPublicKeyFromBase58("So11111111111111111111111111111111111111112") +) + +var ( + pumpAmmBuyDiscriminator = calculateDiscriminator("global:buy") + pumpAmmSellDiscriminator = calculateDiscriminator("global:sell") + pumpAmmCreateDiscriminator = calculateDiscriminator("global:create_pool") + pumpAmmWithdrawDiscriminator = calculateDiscriminator("global:withdraw") + pumpAmmDepositDiscriminator = calculateDiscriminator("global:deposit") + + // UnParsedDiscriminator is the discriminator for unparsed data. + + pumpAmmCreateConfigDiscriminator = calculateDiscriminator("global:create_config") + pumpAmmExtendAccountDiscriminator = calculateDiscriminator("global:extend_account") + pumpAmmUpdateFeeConfigDiscriminator = calculateDiscriminator("global:update_fee_config") + pumpAmmDisableDiscriminator = calculateDiscriminator("global:disable") + + pumpAmmEventDiscriminator = [8]byte{228, 69, 165, 46, 81, 203, 154, 29} + pumpAmmBuyEventDiscriminator = calculateDiscriminator("event:BuyEvent") + pumpAmmSellEventDiscriminator = calculateDiscriminator("event:SellEvent") + pumpAmmCreateEventDiscriminator = calculateDiscriminator("event:CreatePoolEvent") + pumpAmmWithdrawEventDiscriminator = calculateDiscriminator("event:WithdrawEvent") + pumpAmmDepositEventDiscriminator = calculateDiscriminator("event:DepositEvent") +) + +// Program PumpAmm program ID + +var budgGetProgram = solana.MustPublicKeyFromBase58("ComputeBudget111111111111111111111111111111") +var setComputeUnitLimitDiscriminator = uint8(2) +var setComputeUnitPriceDiscriminator = uint8(3) + +var transferDiscriminator = uint32(2) +var createAccountWithSeedDiscriminator = uint32(3) + +var systemProgram = solana.MustPublicKeyFromBase58("11111111111111111111111111111111") + +var raydiumLaunchLabProgramID = solana.MustPublicKeyFromBase58("LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj") diff --git a/parser.go b/parser.go new file mode 100644 index 0000000..e4466ca --- /dev/null +++ b/parser.go @@ -0,0 +1,97 @@ +package pump_parser + +import ( + "errors" + + "github.com/gagliardetto/solana-go" + "github.com/shopspring/decimal" +) + +var swapPrograms = map[solana.PublicKey]swapParser{ + pumpAmmProgram: pumpAmmParser, + pumpProgram: pumpParser, +} + +var actionPrograms = map[solana.PublicKey]actionParser{ + systemProgram: systemParser, + budgGetProgram: budgetParser, +} + +func Parser(rawTx *RawTx) (*Tx, error) { + accountList := rawTx.getAccountList() + var tx = &Tx{ + TxHash: (*[64]byte)((rawTx.Transaction.Signatures[0][:])), + Signer: rawTx.GetSigner(), + Block: rawTx.Slot, + BlockIndex: uint64(rawTx.IndexWithinBlock), + BlockAt: rawTx.BlockTime, + + BeforeSolBalance: decimal.NewFromUint64(rawTx.Meta.PreBalances[0]).Div(decimal.NewFromInt(1e9)), + AfterSOLBalance: decimal.NewFromUint64(rawTx.Meta.PostBalances[0]).Div(decimal.NewFromInt(1e9)), + } + var innersMap = make(map[int]InnerInstructions) + for _, inner := range rawTx.Meta.InnerInstructions { + innersMap[inner.Index] = inner + } + for i, instr := range rawTx.Transaction.Message.Instructions { + programAccount := accountList[instr.ProgramIDIndex] + if p, exists := swapPrograms[programAccount]; exists { + swaps, _, err := p(rawTx, instr, innersMap[i], [2]uint{uint(i), uint(0)}) + if err != nil { + if errors.Is(err, InstructionIgnoredError) { + continue + } + return nil, err + } + tx.Swaps = append(tx.Swaps, swaps...) + } else if p, exists := actionPrograms[programAccount]; exists { + _, err := p(rawTx, instr, innersMap[i], [2]uint{uint(i), uint(0)}, tx) + if err != nil { + if errors.Is(err, InstructionIgnoredError) { + continue + } + return nil, err + } + } else { + ii := i + // unknown program, parser inner instructions + innerLength := len(innersMap[i].Instructions) + for j := 1; j <= innerLength; { + innerInstr := innersMap[i].Instructions[j-1] + innerProgramAccount := accountList[innerInstr.ProgramIDIndex] + + if p, exists := swapPrograms[innerProgramAccount]; exists { + swaps, offset, err := p(rawTx, innerInstr, innersMap[i], [2]uint{uint(i), uint(j)}) + if err != nil { + if errors.Is(err, InstructionIgnoredError) { + j = int(offset[1]) + continue + } + return nil, err + } + tx.Swaps = append(tx.Swaps, swaps...) + j = int(offset[1]) + ii = int(offset[0]) + } else if p, exists := actionPrograms[innerProgramAccount]; exists { + offset, err := p(rawTx, innerInstr, innersMap[i], [2]uint{uint(i), uint(j)}, tx) + if err != nil { + if errors.Is(err, InstructionIgnoredError) { + j = int(offset[1]) + continue + } + return nil, err + } + j = int(offset[1]) + ii = int(offset[0]) + } else { + j++ + } + if j > innerLength || ii > i { + break + } + } + } + } + + return tx, nil +} diff --git a/pump.go b/pump.go new file mode 100644 index 0000000..a3575d5 --- /dev/null +++ b/pump.go @@ -0,0 +1,439 @@ +package pump_parser + +import ( + "bytes" + "fmt" + + agbinary "github.com/gagliardetto/binary" + "github.com/gagliardetto/solana-go" + "github.com/shopspring/decimal" +) + +func increaseOffset(offset [2]uint) [2]uint { + if offset[1] == 0 { + return [2]uint{offset[0] + 1, offset[1]} + } + return [2]uint{offset[0], offset[1] + 1} +} + +// pumpParser // routes pump program instructions to their respective parsers, +// offset is [outerIndex, innerIndex] index of instructions in the transaction, +// if innerIndex == 0 this is outer instruction,if it's an inner instruction, outerIndex is the index of the parent instruction. +func pumpParser(result *RawTx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + + if !result.accountList[instruction.ProgramIDIndex].Equals(pumpProgram) { + return nil, increaseOffset(offset), fmt.Errorf("pump program instruction not found, offset, %d, %d", offset[0], offset[1]) + } + + decode := instruction.Data + if len(decode) < 8 { + offset[1] += 1 + return nil, increaseOffset(offset), fmt.Errorf("pump program instruction data too short, offset, %d, %d", offset[0], offset[1]) + } + + discriminator := *(*[8]byte)(decode[:8]) + + switch discriminator { + case pumpBuyV2Discriminator, pumpBuyDiscriminator, pumpSellDiscriminator: + return BuyOrSellParser(result, instruction, innerInstructions, offset) + case pumpCreateDiscriminator, pumpCreateV2Discriminator: + return CreateParser(result, instruction, innerInstructions, offset) + case pumpMigrateDiscriminator: + return MigrateParser(result, instruction, innerInstructions, offset) + default: + return nil, increaseOffset(offset), InstructionIgnoredError + } +} + +type PumpCreateData struct { + Discriminator uint64 + Name string + Symbol string + Uri string + Creator solana.PublicKey +} + +type PumpCreateV2Data struct { + Discriminator uint64 + Name string + Symbol string + Uri string + + Creator solana.PublicKey + IsMayhem bool +} + +type PumpCreateEvent struct { + Name string + Symbol string + Uri string + + Mint solana.PublicKey + BondingCurve solana.PublicKey + User solana.PublicKey + Creator solana.PublicKey + + Timestamp int64 + VirtualTokenReserves uint64 + VirtualSolReserves uint64 + RealTokenReserves uint64 + TokenTotalSupply uint64 + TokenProgram solana.PublicKey + IsMayhemMode bool +} + +func getInnerInstructions(innerInstructions InnerInstructions, offset uint) ([]Instruction, error) { + var inners []Instruction + var prefixLen = offset + if prefixLen > uint(len(innerInstructions.Instructions)) { + return nil, fmt.Errorf("error inner instruction index out of range") + } + if prefixLen == 0 { + inners = innerInstructions.Instructions + } else { + inners = innerInstructions.Instructions[prefixLen:] + } + return inners, nil +} + +func CreateParser(result *RawTx, instr Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] + + var programIndex = instr.ProgramIDIndex + var err error + + var createEvent PumpCreateEvent + var prefixLen = offset[1] + inners, err := getInnerInstructions(innerInstructions, prefixLen) + if err != nil { + return nil, increaseOffset(offset), fmt.Errorf("pump create get inner instructions error: %v, offset, %d, %d", err, offset[0], offset[1]) + } + for innerIndex, innerInstr := range inners { + if innerInstr.ProgramIDIndex == programIndex && bytes.Equal(innerInstr.Data[:8], pumpEventDiscriminator[:]) && bytes.Equal(innerInstr.Data[8:16], pumpCreateEventDiscriminator[:]) { + err = agbinary.NewBorshDecoder(innerInstr.Data[16:]).Decode(&createEvent) + if offset[1] == 0 { + offset[0] += 1 + } else { + offset[1] += uint(innerIndex) + 1 + prefixLen + } + if err != nil { + return nil, offset, fmt.Errorf("pump create event decode error: %v, offset, %d, %d", err, offset[0], offset[1]) + } + break + } + } + if createEvent == (PumpCreateEvent{}) { + return nil, increaseOffset(offset), fmt.Errorf("pump create event not found, offset, %d, %d", offset[0], offset[1]) + } + userIndex := 0 + if bytes.HasPrefix(instr.Data, pumpCreateV2Discriminator[:]) { + userIndex = instr.Accounts[5] + } else if bytes.HasPrefix(instr.Data, pumpCreateDiscriminator[:]) { + userIndex = instr.Accounts[7] + } + userBase := getAccountBalanceAfterTx(result, userIndex) + userQuote, _ := GetSolAfterTx(result, userIndex) + + return []Swap{ + { + Program: SolProgramPump, + Event: "create", + Pool: createEvent.BondingCurve, + BaseMint: createEvent.Mint, + QuoteMint: solana.PublicKey{}, + BaseTokenProgram: createEvent.TokenProgram, + QuoteTokenProgram: solana.PublicKey{}, + Creator: createEvent.Creator, + BaseMintDecimals: 6, + QuoteMintDecimals: 9, + User: createEvent.User, + BaseAmount: decimal.Zero, + QuoteAmount: decimal.Zero, + BaseReserve: decimal.NewFromUint64(createEvent.RealTokenReserves), + QuoteReserve: decimal.Zero, + Mayhem: createEvent.IsMayhemMode, + UserBaseBalance: userBase, + UserQuoteBalance: decimal.NewFromUint64(userQuote), + EntryContract: entryContract, + }, + }, offset, nil +} + +type PumpTradeEvent struct { + Mint solana.PublicKey + SolAmount uint64 + TokenAmount uint64 + IsBuy bool + User solana.PublicKey + Timestamp int64 + VirtualSolReserves uint64 + VirtualTokenReserves uint64 + + RealSolReserves uint64 + RealTokenReserves uint64 + + FeeRecipient solana.PublicKey + FeeBasisPoints uint64 + Fee uint64 + + Creator solana.PublicKey +} + +type CompleteEvent struct { + User solana.PublicKey + Mint solana.PublicKey + BondingCurve solana.PublicKey + Timestamp int64 +} + +func BuyOrSellParser(result *RawTx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] + var err error + var programIndex = instruction.ProgramIDIndex + + var ( + tradeEvent PumpTradeEvent + completeEvent CompleteEvent + completed bool + newoffset [2]uint + ) + + var prefixLen = offset[1] + inners, err := getInnerInstructions(innerInstructions, prefixLen) + if err != nil { + return nil, increaseOffset(offset), fmt.Errorf("pump create get inner instructions error: %v,offset, %d, %d", err, offset[0], offset[1]) + } + + for innerIndex, innerInstr := range inners { + if innerInstr.ProgramIDIndex == programIndex && bytes.Equal(innerInstr.Data[:8], pumpEventDiscriminator[:]) { + if bytes.Equal(innerInstr.Data[8:16], pumpTradeEventDiscriminator[8:16]) { + err = agbinary.NewBorshDecoder(innerInstr.Data[16:]).Decode(&tradeEvent) + if offset[1] == 0 { + newoffset = [2]uint{offset[0] + 1, offset[1]} + } else { + newoffset = [2]uint{offset[0], prefixLen + uint(innerIndex) + 1} + } + if err != nil { + return nil, newoffset, fmt.Errorf("pump buy event decode error: %v, offset, %d, %d", err, offset[0], offset[1]) + } + if !tradeEvent.IsBuy { + break + } + } else if bytes.Equal(innerInstr.Data[8:16], pumpCompleteEventDiscriminator[:]) { + err = agbinary.NewBorshDecoder(innerInstr.Data[16:]).Decode(&completeEvent) + if offset[1] == 0 { + newoffset = [2]uint{offset[0] + 1, offset[1]} + } else { + newoffset = [2]uint{offset[0], prefixLen + uint(innerIndex) + 1} + } + if err != nil { + return nil, newoffset, fmt.Errorf("pump completeEvent event decode error: %v, offset, %d, %d", err, offset[0], offset[1]) + } + completed = true + break + } + + } + } + if tradeEvent == (PumpTradeEvent{}) { + return nil, increaseOffset(offset), fmt.Errorf("pmp buy/sell event not found, offset, %d, %d", offset[0], offset[1]) + } + + offset = [2]uint{newoffset[0], newoffset[1]} + ataUserIdx := instruction.Accounts[5] + userIndex := instruction.Accounts[6] + + userBase := getAccountBalanceAfterTx(result, ataUserIdx) + userQuote, _ := GetSolAfterTx(result, userIndex) + + event := "" + baseTokenProgram := solana.TokenProgramID + if tradeEvent.IsBuy { + event = "buy" + baseTokenProgram = result.accountList[instruction.Accounts[8]] + } else { + event = "sell" + baseTokenProgram = result.accountList[instruction.Accounts[9]] + } + swaps := []Swap{ + { + Program: SolProgramPump, + Event: event, + Pool: result.accountList[instruction.Accounts[3]], + BaseMint: tradeEvent.Mint, + QuoteMint: solana.PublicKey{}, + BaseTokenProgram: baseTokenProgram, + QuoteTokenProgram: solana.PublicKey{}, + Creator: tradeEvent.Creator, + BaseMintDecimals: 6, + QuoteMintDecimals: 9, + User: tradeEvent.User, + BaseAmount: decimal.NewFromUint64(tradeEvent.TokenAmount), + QuoteAmount: decimal.NewFromUint64(tradeEvent.SolAmount), + BaseReserve: decimal.NewFromUint64(tradeEvent.RealTokenReserves), + QuoteReserve: decimal.NewFromUint64(tradeEvent.RealSolReserves), + Mayhem: isMayhemPump(result.accountList[instruction.Accounts[1]]), + UserBaseBalance: userBase, + UserQuoteBalance: decimal.NewFromUint64(userQuote), + EntryContract: entryContract, + }, + } + if completed { + swaps = append(swaps, Swap{ + Program: SolProgramPump, + Event: "complete", + Pool: result.accountList[instruction.Accounts[3]], + BaseMint: tradeEvent.Mint, + QuoteMint: solana.PublicKey{}, + BaseTokenProgram: result.accountList[instruction.Accounts[8]], + QuoteTokenProgram: solana.PublicKey{}, + Creator: tradeEvent.Creator, + BaseMintDecimals: 6, + QuoteMintDecimals: 9, + User: tradeEvent.User, + Mayhem: isMayhemPump(result.accountList[instruction.Accounts[1]]), + UserBaseBalance: userBase, + UserQuoteBalance: decimal.NewFromUint64(userQuote), + EntryContract: entryContract, + }) + } + return swaps, offset, nil +} + +type MigrateEvent struct { + User solana.PublicKey + Mint solana.PublicKey + //Creator solana.PublicKey + + MintAmount uint64 + SolAmount uint64 + PoolMigrationFee uint64 + //CreatorFee uint64 + BondingCurve solana.PublicKey + TimeStamp int64 + Pool solana.PublicKey +} + +func MigrateParser(result *RawTx, instr Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] + var err error + programIndex := instr.ProgramIDIndex + ammprogramIdx := 0 + for i, b := range result.accountList { + if b.Equals(pumpAmmProgram) { + ammprogramIdx = i + break + } + } + if ammprogramIdx == 0 { + return nil, increaseOffset(offset), fmt.Errorf("pump migrate, amm program id not found in account list, offset, %d, %d", offset[0], offset[1]) + } + var prefixLen = offset[1] + inners, err := getInnerInstructions(innerInstructions, prefixLen) + if err != nil { + return nil, increaseOffset(offset), fmt.Errorf("pump migrate get inner instructions offset, %d, %d", offset[0], offset[1]) + } + var ( + migrateEvent MigrateEvent + createEvent ammCreatePoolEvent + newoffset [2]uint + ) + for innerIndex, innerInstr := range inners { + if innerInstr.ProgramIDIndex == ammprogramIdx && bytes.Equal(innerInstr.Data[:8], pumpAmmEventDiscriminator[:]) { + if bytes.Equal(innerInstr.Data[8:16], pumpAmmCreateEventDiscriminator[:]) { + err = agbinary.NewBorshDecoder(innerInstr.Data[16:]).Decode(&createEvent) + if offset[1] == 0 { + newoffset = [2]uint{offset[0] + 1, offset[1]} + } else { + newoffset = [2]uint{offset[0], prefixLen + uint(innerIndex) + 1} + } + if err != nil { + return nil, newoffset, fmt.Errorf("pump amm createEvent decode error: %v, offset, %d, %d", err, offset[0], offset[1]) + } + } + // + } else if innerInstr.ProgramIDIndex == programIndex && bytes.Equal(innerInstr.Data[:8], pumpEventDiscriminator[:]) { + if bytes.Equal(innerInstr.Data[8:16], pumpMigrateEventDiscriminator[:]) { + err = agbinary.NewBorshDecoder(innerInstr.Data[16:]).Decode(&migrateEvent) + if offset[1] == 0 { + newoffset = [2]uint{offset[0] + 1, offset[1]} + } else { + newoffset = [2]uint{offset[0], prefixLen + uint(innerIndex) + 1} + } + if err != nil { + return nil, newoffset, fmt.Errorf("pump buy event decode error: %v, offset, %d, %d", err, offset[0], offset[1]) + } + break + } + } + } + if migrateEvent == (MigrateEvent{}) || createEvent == (ammCreatePoolEvent{}) { + offset = [2]uint{newoffset[0], newoffset[1]} + return nil, increaseOffset(offset), InstructionIgnoredError + } + + offset = [2]uint{newoffset[0], newoffset[1]} + // verify migrate by checking create pool and migrate event + userIndex := instr.Accounts[5] + ataBondingCurveAccountIndex := instr.Accounts[4] + bc, err := getTokenBalanceAfterTx(result, ataBondingCurveAccountIndex) + if err != nil || bc == nil { + return nil, increaseOffset(offset), fmt.Errorf("pump migrate get bonding curve balance error: %v, offset, %d, %d", err, offset[0], offset[1]) + } + baseTokenProgram := bc.ProgramIDAccount + var userBase decimal.Decimal + if result.accountList[userIndex].Equals(pumpMigrationAccount) { + userBase = decimal.Zero + } else { + userBase = GetTokenBalanceAfterTx(result, userIndex, baseTokenProgram, migrateEvent.Mint) + } + userQuote, _ := GetSolAfterTx(result, userIndex) + + swaps := []Swap{ + { + Program: SolProgramPump, + Event: "migrate", + Pool: migrateEvent.BondingCurve, + BaseMint: migrateEvent.Mint, + QuoteMint: solana.PublicKey{}, + BaseTokenProgram: baseTokenProgram, + QuoteTokenProgram: solana.PublicKey{}, + Creator: createEvent.Creator, + BaseMintDecimals: 6, + QuoteMintDecimals: 9, + User: migrateEvent.User, + //BaseAmount: decimal.Decimal{}, + //QuoteAmount: decimal.Decimal{}, + BaseReserve: decimal.NewFromUint64(migrateEvent.MintAmount), + QuoteReserve: decimal.NewFromUint64(migrateEvent.SolAmount), + Mayhem: createEvent.IsMayhemMode, + UserBaseBalance: userBase, + UserQuoteBalance: decimal.NewFromUint64(userQuote), + EntryContract: entryContract, + }, + } + swaps = append(swaps, Swap{ + Program: SolProgramPumpAMM, + Event: "create", + Pool: migrateEvent.Pool, + BaseMint: migrateEvent.Mint, + QuoteMint: wSolMint, + BaseTokenProgram: baseTokenProgram, + QuoteTokenProgram: solana.TokenProgramID, + Creator: createEvent.Creator, + BaseMintDecimals: 6, + QuoteMintDecimals: 9, + User: migrateEvent.User, + BaseAmount: decimal.NewFromUint64(migrateEvent.MintAmount), + QuoteAmount: decimal.NewFromUint64(migrateEvent.SolAmount), + BaseReserve: decimal.NewFromUint64(migrateEvent.MintAmount), + QuoteReserve: decimal.NewFromUint64(migrateEvent.SolAmount), + Mayhem: createEvent.IsMayhemMode, + UserBaseBalance: userBase, + UserQuoteBalance: decimal.NewFromUint64(userQuote), + EntryContract: entryContract, + }) + + return swaps, offset, nil + +} diff --git a/pumpamm.go b/pumpamm.go new file mode 100644 index 0000000..b638e18 --- /dev/null +++ b/pumpamm.go @@ -0,0 +1,513 @@ +package pump_parser + +import ( + "bytes" + "fmt" + + agbinary "github.com/gagliardetto/binary" + "github.com/gagliardetto/solana-go" + "github.com/shopspring/decimal" +) + +type ammBuyEvent struct { + TimeStamp int64 + BaseAmountOut uint64 + MaxQuoteAmountIn uint64 + UserBaseTokenReserve uint64 + UserQuoteTokenReserve uint64 + PoolBaseTokenReserve uint64 + PoolQuoteTokenReserve uint64 + QuoteAmountIn uint64 + LpFeeBasisPoints uint64 + LpFee uint64 + ProtocolFee uint64 + QuoteAmountInWithLpFee uint64 + UserQuoteAmountIn uint64 + + Pool solana.PublicKey + User solana.PublicKey + UserBaseTokenAccount solana.PublicKey + UserQuoteTokenAccount solana.PublicKey + ProtocolFeeRecipient solana.PublicKey + ProtocolFeeRecipientTokenAccount solana.PublicKey + CoinCreator solana.PublicKey +} + +type ammCreatePoolEvent struct { + TimeStamp int64 + Index uint16 + Creator solana.PublicKey + BaseMint solana.PublicKey + QuoteMint solana.PublicKey + BaseMintDecimals uint8 + QuoteMintDecimals uint8 + BaseAmountIn uint64 + QuoteAmountIn uint64 + PoolBaseAmount uint64 + PoolQuoteAmount uint64 + MinimumLiquidity uint64 + InitialLiquidity uint64 + LpTokenAmountOut uint64 + PoolBump uint8 + + Pool solana.PublicKey + LpMint solana.PublicKey + UserBaseTokenAccount solana.PublicKey + UserQuoteTokenAccount solana.PublicKey + CoinCreator solana.PublicKey + IsMayhemMode bool +} + +type ammDepositEvent struct { + TimeStamp int64 + LpTokenAmountOut uint64 + MaxBaseAmountIn uint64 + MaxQuoteAmountIn uint64 + UserBaseTokenReserves uint64 + UserQuoteTokenReserves uint64 + PoolBaseTokenReserves uint64 + PoolQuoteTokenReserves uint64 + BaseAmountIn uint64 + QuoteAmountIn uint64 + LpMintSupply uint64 + + Pool solana.PublicKey + User solana.PublicKey + UserBaseTokenAccount solana.PublicKey + UserQuoteTokenAccount solana.PublicKey + UserPoolTokenAccount solana.PublicKey +} + +type ammSellEvent struct { + Timestamp int64 + BaseAmountIn uint64 + MinQuoteAmountOut uint64 + UserBaseTokenReserves uint64 + UserQuoteTokenReserves uint64 + PoolBaseTokenReserves uint64 + PoolQuoteTokenReserves uint64 + QuoteAmountOut uint64 + LpFeeBasisPoints uint64 + LpFee uint64 + ProtocolFeeBasisPoints uint64 + ProtocolFee uint64 + QuoteAmountOutWithoutLpFee uint64 + UserQuoteAmountOut uint64 + + Pool solana.PublicKey + User solana.PublicKey + UserBaseTokenAccount solana.PublicKey + UserQuoteTokenAccount solana.PublicKey + ProtocolFeeRecipient solana.PublicKey + ProtocolFeeRecipientTokenAccount solana.PublicKey + CoinCreator solana.PublicKey +} + +type ammWithdrawEvent struct { + Timestamp int64 + LpTokenAmountIn uint64 + MinBaseAmountOut uint64 + MinQuoteAmountOut uint64 + UserBaseTokenReserves uint64 + UserQuoteTokenReserves uint64 + PoolBaseTokenReserves uint64 + PoolQuoteTokenReserves uint64 + BaseAmountOut uint64 + QuoteAmountOut uint64 + LpMintSupply uint64 + + Pool solana.PublicKey + User solana.PublicKey + UserBaseTokenAccount solana.PublicKey + UserQuoteTokenAccount solana.PublicKey + UserPoolTokenAccount solana.PublicKey +} + +func pumpAmmParser(result *RawTx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + + if !result.accountList[instruction.ProgramIDIndex].Equals(pumpAmmProgram) { + return nil, increaseOffset(offset), fmt.Errorf("pump amm program instruction not found, offset: %d, %d", offset[0], offset[1]) + } + decode := instruction.Data + if len(decode) < 8 { + offset[1] += 1 + return nil, increaseOffset(offset), fmt.Errorf("pumpamm program instruction data too short, offset: %d, %d", offset[0], offset[1]) + } + + discriminator := *(*[8]byte)(decode[:8]) + switch discriminator { + case pumpAmmCreateDiscriminator: + return ammCreatePoolParser(result, instruction, innerInstructions, offset) + case pumpAmmBuyDiscriminator: + return ammBuyParser(result, instruction, innerInstructions, offset) + case pumpAmmSellDiscriminator: + return ammSellParser(result, instruction, innerInstructions, offset) + case pumpAmmDepositDiscriminator: + return depositParse(result, instruction, innerInstructions, offset) + case pumpAmmWithdrawDiscriminator: + return withdrawParse(result, instruction, innerInstructions, offset) + default: + return nil, increaseOffset(offset), InstructionIgnoredError + } +} + +func ammCreatePoolParser(result *RawTx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] + var err error + var prefixLen = offset[1] + inners, err := getInnerInstructions(innerInstructions, prefixLen) + if err != nil { + return nil, increaseOffset(offset), fmt.Errorf("pumpamm create get inner instructions error: %v, offset: %d, %d", err, offset[0], prefixLen) + } + var createEvent ammCreatePoolEvent + for innerIndex, innerInstr := range inners { + if innerInstr.ProgramIDIndex == instruction.ProgramIDIndex && + bytes.Equal(innerInstr.Data[:8], pumpAmmEventDiscriminator[:]) && + bytes.Equal(innerInstr.Data[8:16], pumpAmmCreateEventDiscriminator[:]) { + err = agbinary.NewBorshDecoder(innerInstr.Data[16:]).Decode(&createEvent) + if offset[1] == 0 { + offset[0] += 1 + } else { + offset[1] += uint(innerIndex) + 1 + prefixLen + } + if err != nil { + return nil, offset, fmt.Errorf("pump amm create pool event decode error: %v, offset: %d, %d", err, offset[0], prefixLen) + } + break + } + } + if createEvent == (ammCreatePoolEvent{}) { + return nil, increaseOffset(offset), fmt.Errorf("pump amm create pool event not found, offset: %d, %d", offset[0], prefixLen) + } + + baseTokenProgram := result.accountList[instruction.Accounts[13]] + quoteTokenProgram := result.accountList[instruction.Accounts[14]] + return []Swap{ + { + Program: SolProgramPumpAMM, + Event: "create", + Pool: createEvent.Pool, + BaseMint: createEvent.BaseMint, + QuoteMint: createEvent.QuoteMint, + BaseTokenProgram: baseTokenProgram, + QuoteTokenProgram: quoteTokenProgram, + Creator: createEvent.CoinCreator, + BaseMintDecimals: createEvent.BaseMintDecimals, + QuoteMintDecimals: createEvent.QuoteMintDecimals, + User: createEvent.Creator, + BaseAmount: decimal.NewFromUint64(createEvent.BaseAmountIn), + QuoteAmount: decimal.NewFromUint64(createEvent.QuoteAmountIn), + BaseReserve: decimal.NewFromUint64(createEvent.PoolBaseAmount), + QuoteReserve: decimal.NewFromUint64(createEvent.PoolQuoteAmount), + UserBaseBalance: decimal.Decimal{}, + UserQuoteBalance: decimal.Decimal{}, + EntryContract: entryContract, + Mayhem: createEvent.IsMayhemMode, + }, + }, offset, nil + +} + +func ammBuyParser(result *RawTx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] + var err error + var prefixLen = offset[1] + inners, err := getInnerInstructions(innerInstructions, prefixLen) + if err != nil { + return nil, increaseOffset(offset), fmt.Errorf("pumpamm create get inner instructions error: %v, offset: %d, %d", err, offset[0], prefixLen) + } + var event ammBuyEvent + for innerIndex, innerInstr := range inners { + if innerInstr.ProgramIDIndex == instruction.ProgramIDIndex && + bytes.Equal(innerInstr.Data[:8], pumpAmmEventDiscriminator[:]) && + bytes.Equal(innerInstr.Data[8:16], pumpAmmBuyEventDiscriminator[:]) { + err = agbinary.NewBorshDecoder(innerInstr.Data[16:]).Decode(&event) + if offset[1] == 0 { + offset[0] += 1 + } else { + offset[1] += uint(innerIndex) + 1 + prefixLen + } + if err != nil { + return nil, offset, fmt.Errorf("pump amm buy pool event decode error: %v, offset: %d, %d", err, offset[0], prefixLen) + } + break + } + } + if event == (ammBuyEvent{}) { + return nil, increaseOffset(offset), fmt.Errorf("pump amm buy event not found, offset: %d, %d", offset[0], prefixLen) + } + baseMint := result.accountList[instruction.Accounts[3]] + quoteMint := result.accountList[instruction.Accounts[4]] + baseTokenProgram := result.accountList[instruction.Accounts[11]] + quoteTokenProgram := result.accountList[instruction.Accounts[12]] + + poolBaseAccountIdx := instruction.Accounts[7] + poolQuoteAccountIdx := instruction.Accounts[8] + var ( + baseMintDecimals uint8 + quoteMintDecimals uint8 + ) + for _, meta := range result.Meta.PostTokenBalances { + if meta.AccountIndex == poolBaseAccountIdx { + baseMintDecimals = uint8(meta.UITokenAmount.Decimals) + } else if meta.AccountIndex == poolQuoteAccountIdx { + quoteMintDecimals = uint8(meta.UITokenAmount.Decimals) + } + } + return []Swap{ + { + Program: SolProgramPumpAMM, + Event: "buy", + Pool: event.Pool, + BaseMint: baseMint, + QuoteMint: quoteMint, + BaseTokenProgram: baseTokenProgram, + QuoteTokenProgram: quoteTokenProgram, + Creator: event.CoinCreator, + BaseMintDecimals: baseMintDecimals, + QuoteMintDecimals: quoteMintDecimals, + User: event.User, + BaseAmount: decimal.NewFromUint64(event.BaseAmountOut), + QuoteAmount: decimal.NewFromUint64(event.UserQuoteAmountIn), + BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserve - event.BaseAmountOut), + QuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserve + event.QuoteAmountIn), + Mayhem: isMayhemPump(result.accountList[instruction.Accounts[9]]), + UserBaseBalance: decimal.NewFromUint64(event.UserBaseTokenReserve + event.BaseAmountOut), + UserQuoteBalance: decimal.NewFromUint64(event.UserQuoteTokenReserve - event.UserQuoteAmountIn), + EntryContract: entryContract, + }, + }, offset, nil +} + +func ammSellParser(result *RawTx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] + var err error + var prefixLen = offset[1] + inners, err := getInnerInstructions(innerInstructions, prefixLen) + if err != nil { + return nil, increaseOffset(offset), fmt.Errorf("pumpamm sell get inner instructions error: %v, offset: %d, %d", err, offset[0], prefixLen) + } + var event ammSellEvent + for innerIndex, innerInstr := range inners { + if innerInstr.ProgramIDIndex == instruction.ProgramIDIndex && + bytes.Equal(innerInstr.Data[:8], pumpAmmEventDiscriminator[:]) && + bytes.Equal(innerInstr.Data[8:16], pumpAmmSellEventDiscriminator[:]) { + err = agbinary.NewBorshDecoder(innerInstr.Data[16:]).Decode(&event) + if offset[1] == 0 { + offset[0] += 1 + } else { + offset[1] += uint(innerIndex) + 1 + prefixLen + } + if err != nil { + return nil, offset, fmt.Errorf("pump amm sell pool event decode error: %v, offset: %d, %d", err, offset[0], prefixLen) + } + break + } + } + if event == (ammSellEvent{}) { + return nil, increaseOffset(offset), fmt.Errorf("pump amm sell event not found, offset: %d, %d", offset[0], prefixLen) + } + baseMint := result.accountList[instruction.Accounts[3]] + quoteMint := result.accountList[instruction.Accounts[4]] + baseTokenProgram := result.accountList[instruction.Accounts[11]] + quoteTokenProgram := result.accountList[instruction.Accounts[12]] + + poolBaseAccountIdx := instruction.Accounts[7] + poolQuoteAccountIdx := instruction.Accounts[8] + var ( + baseMintDecimals uint8 + quoteMintDecimals uint8 + ) + for _, meta := range result.Meta.PostTokenBalances { + if meta.AccountIndex == poolBaseAccountIdx { + baseMintDecimals = uint8(meta.UITokenAmount.Decimals) + } else if meta.AccountIndex == poolQuoteAccountIdx { + quoteMintDecimals = uint8(meta.UITokenAmount.Decimals) + } + } + return []Swap{ + { + Program: SolProgramPumpAMM, + Event: "sell", + Pool: event.Pool, + BaseMint: baseMint, + QuoteMint: quoteMint, + BaseTokenProgram: baseTokenProgram, + QuoteTokenProgram: quoteTokenProgram, + Creator: event.CoinCreator, + BaseMintDecimals: baseMintDecimals, + QuoteMintDecimals: quoteMintDecimals, + User: event.User, + BaseAmount: decimal.NewFromUint64(event.BaseAmountIn), + QuoteAmount: decimal.NewFromUint64(event.UserQuoteAmountOut), + BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserves + event.BaseAmountIn), + QuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserves - event.QuoteAmountOut), + Mayhem: isMayhemPump(result.accountList[instruction.Accounts[9]]), + UserBaseBalance: decimal.NewFromUint64(event.UserBaseTokenReserves - event.BaseAmountIn), + UserQuoteBalance: decimal.NewFromUint64(event.UserQuoteTokenReserves + event.UserQuoteAmountOut), + EntryContract: entryContract, + }, + }, offset, nil +} + +func depositParse(result *RawTx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] + var err error + var prefixLen = offset[1] + inners, err := getInnerInstructions(innerInstructions, prefixLen) + if err != nil { + return nil, increaseOffset(offset), fmt.Errorf("pumpamm deposit get inner instructions error: %v, offset: %d, %d", err, offset[0], prefixLen) + } + + var event ammDepositEvent + + for innerIndex, innerInstr := range inners { + if innerInstr.ProgramIDIndex == instruction.ProgramIDIndex && + bytes.Equal(innerInstr.Data[:8], pumpAmmEventDiscriminator[:]) && + bytes.Equal(innerInstr.Data[8:16], pumpAmmDepositEventDiscriminator[:]) { + err = agbinary.NewBorshDecoder(innerInstr.Data[16:]).Decode(&event) + if offset[1] == 0 { + offset[0] += 1 + } else { + offset[1] += uint(innerIndex) + 1 + prefixLen + } + if err != nil { + return nil, offset, fmt.Errorf("pump amm deposit pool event decode error: %v, offset: %d, %d", err, offset[0], prefixLen) + } + break + } + } + if event == (ammDepositEvent{}) { + return nil, increaseOffset(offset), fmt.Errorf("pump amm deposit event not found, offset: %d, %d", offset[0], prefixLen) + } + + var ( + poolBaseAccountIdx = instruction.Accounts[9] + poolQuoteAccountIdx = instruction.Accounts[10] + baseMintDecimals uint8 + quoteMintDecimals uint8 + baseMintProgram solana.PublicKey + quoteMintProgram solana.PublicKey + ) + for _, meta := range result.Meta.PostTokenBalances { + if meta.AccountIndex == poolBaseAccountIdx { + baseMintDecimals = uint8(meta.UITokenAmount.Decimals) + baseMintProgram = meta.ProgramIDAccount + if baseMintProgram.IsZero() && meta.ProgramID != "" { + baseMintProgram = solana.MustPublicKeyFromBase58(meta.ProgramID) + } + } + if meta.AccountIndex == poolQuoteAccountIdx { + quoteMintDecimals = uint8(meta.UITokenAmount.Decimals) + quoteMintProgram = meta.ProgramIDAccount + if quoteMintProgram.IsZero() && meta.ProgramID != "" { + quoteMintProgram = solana.MustPublicKeyFromBase58(meta.ProgramID) + } + } + } + + return []Swap{ + { + Program: SolProgramPumpAMM, + Event: "deposit", + Pool: event.Pool, + BaseMint: result.accountList[instruction.Accounts[3]], + QuoteMint: result.accountList[instruction.Accounts[4]], + BaseTokenProgram: baseMintProgram, + QuoteTokenProgram: quoteMintProgram, + //Creator: solana.PublicKey{}, + BaseMintDecimals: baseMintDecimals, + QuoteMintDecimals: quoteMintDecimals, + User: event.User, + BaseAmount: decimal.NewFromUint64(event.BaseAmountIn), + QuoteAmount: decimal.NewFromUint64(event.QuoteAmountIn), + BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserves + event.BaseAmountIn), + QuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserves + event.QuoteAmountIn), + //Mayhem: false, + UserBaseBalance: decimal.NewFromUint64(event.UserBaseTokenReserves - event.BaseAmountIn), + UserQuoteBalance: decimal.NewFromUint64(event.UserQuoteTokenReserves - event.QuoteAmountIn), + EntryContract: entryContract, + }, + }, offset, nil +} + +func withdrawParse(result *RawTx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] + var err error + var prefixLen = offset[1] + inners, err := getInnerInstructions(innerInstructions, prefixLen) + if err != nil { + return nil, increaseOffset(offset), fmt.Errorf("pumpamm withdraw get inner instructions error: %v, offset: %d, %d", err, offset[0], prefixLen) + } + + var event ammWithdrawEvent + + for innerIndex, innerInstr := range inners { + if innerInstr.ProgramIDIndex == instruction.ProgramIDIndex && + bytes.Equal(innerInstr.Data[:8], pumpAmmEventDiscriminator[:]) && + bytes.Equal(innerInstr.Data[8:16], pumpAmmWithdrawEventDiscriminator[:]) { + err = agbinary.NewBorshDecoder(innerInstr.Data[16:]).Decode(&event) + if offset[1] == 0 { + offset[0] += 1 + } else { + offset[1] += uint(innerIndex) + 1 + prefixLen + } + if err != nil { + return nil, offset, fmt.Errorf("pump amm withdraw pool event decode error: %v, offset: %d, %d", err, offset[0], prefixLen) + } + break + } + } + if event == (ammWithdrawEvent{}) { + return nil, increaseOffset(offset), fmt.Errorf("pump amm withdraw event not found, offset: %d, %d", offset[0], prefixLen) + } + + var ( + poolBaseAccountIdx = instruction.Accounts[9] + poolQuoteAccountIdx = instruction.Accounts[10] + baseMintDecimals uint8 + quoteMintDecimals uint8 + baseMintProgram solana.PublicKey + quoteMintProgram solana.PublicKey + ) + for _, meta := range result.Meta.PostTokenBalances { + if meta.AccountIndex == poolBaseAccountIdx { + baseMintDecimals = uint8(meta.UITokenAmount.Decimals) + baseMintProgram = meta.ProgramIDAccount + if baseMintProgram.IsZero() && meta.ProgramID != "" { + baseMintProgram = solana.MustPublicKeyFromBase58(meta.ProgramID) + } + } + if meta.AccountIndex == poolQuoteAccountIdx { + quoteMintDecimals = uint8(meta.UITokenAmount.Decimals) + quoteMintProgram = meta.ProgramIDAccount + if quoteMintProgram.IsZero() && meta.ProgramID != "" { + quoteMintProgram = solana.MustPublicKeyFromBase58(meta.ProgramID) + } + } + } + + return []Swap{ + { + Program: SolProgramPumpAMM, + Event: "withdraw", + Pool: event.Pool, + BaseMint: result.accountList[instruction.Accounts[3]], + QuoteMint: result.accountList[instruction.Accounts[4]], + BaseTokenProgram: baseMintProgram, + QuoteTokenProgram: quoteMintProgram, + //Creator: solana.PublicKey{}, + BaseMintDecimals: baseMintDecimals, + QuoteMintDecimals: quoteMintDecimals, + User: event.User, + BaseAmount: decimal.NewFromUint64(event.BaseAmountOut), + QuoteAmount: decimal.NewFromUint64(event.QuoteAmountOut), + BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserves - event.BaseAmountOut), + QuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserves - event.QuoteAmountOut), + //Mayhem: false, + UserBaseBalance: decimal.NewFromUint64(event.UserBaseTokenReserves + event.BaseAmountOut), + UserQuoteBalance: decimal.NewFromUint64(event.UserQuoteTokenReserves + event.QuoteAmountOut), + EntryContract: entryContract, + }, + }, offset, nil +} diff --git a/pumpamm_test.go b/pumpamm_test.go new file mode 100644 index 0000000..4025428 --- /dev/null +++ b/pumpamm_test.go @@ -0,0 +1,41 @@ +package pump_parser + +import ( + "encoding/base64" + "fmt" + + agbinary "github.com/gagliardetto/binary" + "github.com/gagliardetto/solana-go" + + "testing" +) + +type Pool struct { + Bump uint8 // 1 + Index uint16 // 3 + Creator solana.PublicKey // 35 + BaseMint solana.PublicKey // 67 + QuoteMint solana.PublicKey // 99 + LpMint solana.PublicKey // 131 + PoolBaseTokenAccount solana.PublicKey // 163 + PoolQuoteTokenAccount solana.PublicKey // 195 + LpSupply uint64 // 203 + CoinCreator solana.PublicKey // 235 + IsMayhemMode bool // 236 +} + +func TestDecodePoolData(t *testing.T) { + var base64Data = "8ZptBBGxbbz9AAB/+s6++xNrbunrNkEpE9IY0qfortUqEOB5s3kKGSvL+9H0YLudD5fPy6QWG5FDfdl3FQRE3H804Ivg5J2OnSHvBpuIV/6rgYT7aH9jRhjANdrEOdwa6ztVmKDwAAAAAAGcWzgf1bP0MRLCJXxkgXyazv6CfdxoJGAh01hfNVqrkGoU6aOndSrbraRyP929gjNuQ4qg/nj2RjtLlBazO47we2q7UVSLFd69kGDUes9pm4n4dftp/lIZS068RLXhIR1niGtZ0AMAAFC4Q0TJ2zOhAXgWLRoYc4eSeu9nlTcupLKiXLyIDytOAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + data, _ := base64.StdEncoding.DecodeString(base64Data) + var pool Pool + fmt.Println("data length:", len(data)) + err := agbinary.NewBorshDecoder(data[8:]).Decode(&pool) + if err != nil { + t.Errorf("Failed to decode pool data: %v", err) + } + fmt.Println(pool) +} + +func TestAmmBuyEvent(t *testing.T) { + fmt.Println(pumpAmmBuyEventDiscriminator) +} diff --git a/rawtx.go b/rawtx.go new file mode 100644 index 0000000..3693a39 --- /dev/null +++ b/rawtx.go @@ -0,0 +1,443 @@ +package pump_parser + +import ( + "encoding/json" + "fmt" + "time" + + bin "github.com/gagliardetto/binary" + "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" + "github.com/jackc/pgtype" + "github.com/shopspring/decimal" +) + +func (tx *RawTx) getAccountList() []solana.PublicKey { + if tx.accountList != nil { + return tx.accountList + } + length := len(tx.Transaction.Message.AccountKeys) + + len(tx.Meta.LoadedAddresses.Writable) + + len(tx.Meta.LoadedAddresses.Readonly) + tx.accountList = make([]solana.PublicKey, length) + + var i = 0 + for _, v := range tx.Transaction.Message.AccountKeys { + tx.accountList[i] = v + i++ + } + for _, v := range tx.Meta.LoadedAddresses.Writable { + tx.accountList[i] = v + i++ + } + for _, v := range tx.Meta.LoadedAddresses.Readonly { + tx.accountList[i] = v + i++ + } + return tx.accountList +} + +func (tx *RawTx) GetSigner() solana.PublicKey { + accountList := tx.getAccountList() + if len(accountList) > 0 { + return accountList[0] + } + return solana.PublicKey{} +} + +type RPCResponse struct { + JsonRPC string `json:"jsonrpc"` + Result RawTx `json:"result"` + ID int `json:"id"` +} + +type RawTx struct { + accountList []solana.PublicKey + + BlockTime int64 `json:"blockTime"` + IndexWithinBlock int64 `json:"indexWithinBlock"` + Meta Meta `json:"meta"` + Slot uint64 `json:"slot"` + Transaction Transaction `json:"transaction"` + Version interface{} `json:"version"` + //Platform string `json:"platform,omitempty"` + //PlatformFee decimal.Decimal `json:"-"` + //CUPrice decimal.Decimal `json:"CUPrice,omitempty"` + //MevAgent string `json:"mevAgent,omitempty"` + //MevAgentFee decimal.Decimal `json:"mevAgentFee,omitempty"` + //EntryContract []string `json:"entryContract,omitempty"` +} + +func (tx *RawTx) TxHash() string { + if len(tx.Transaction.Signatures) > 0 { + return tx.Transaction.Signatures[0].String() + } + return "" +} + +func (tx *RawTx) GetSignerAfterBalance() decimal.Decimal { + if len(tx.Meta.PostBalances) > 0 { + return decimal.New(int64(tx.Meta.PostBalances[0]), -9) + } + return decimal.Zero +} + +func (tx *RawTx) GetSignerBeforeBalance() decimal.Decimal { + if len(tx.Meta.PreBalances) > 0 { + return decimal.New(int64(tx.Meta.PreBalances[0]), -9) + } + return decimal.Zero +} + +func (tx *RawTx) GetBlockTime() *pgtype.Timestamptz { + t := pgtype.Timestamptz{} + t.Set(time.Unix(tx.BlockTime, 0)) + return &t +} + +type Instruction struct { + Accounts []int `json:"accounts"` + Data solana.Base58 `json:"data"` + ProgramIDIndex int `json:"programIdIndex"` + StackHeight *int `json:"stackHeight"` +} +type InnerInstructions struct { + Index int `json:"index"` + Instructions []Instruction `json:"instructions"` +} +type LoadedAddresses struct { + Readonly solana.PublicKeySlice `json:"readonly"` + Writable solana.PublicKeySlice `json:"writable"` +} +type UITokenAmount struct { + Amount string `json:"amount"` + Decimals uint64 `json:"decimals"` + UIAmount float64 `json:"uiAmount"` + UIAmountString string `json:"uiAmountString"` +} +type TokenBalance struct { + AccountIndex int `json:"accountIndex"` + + MintAccount solana.PublicKey `json:"mint_account"` + OwnerAccount *solana.PublicKey `json:"owner_account"` + ProgramIDAccount solana.PublicKey `json:"programId_account"` + + Mint string `json:"mint"` + Owner string `json:"owner"` + ProgramID string `json:"programId"` + UITokenAmount UITokenAmount `json:"uiTokenAmount"` +} + +func (tb *TokenBalance) ParseAccount() { + if tb.Mint == "" { + tb.Mint = tb.MintAccount.String() + } + if tb.Owner == "" && tb.OwnerAccount != nil { + tb.Owner = tb.OwnerAccount.String() + } + if tb.ProgramID == "" { + tb.ProgramID = tb.ProgramIDAccount.String() + } +} + +type Meta struct { + Err interface{} `json:"err"` + Fee uint64 `json:"fee"` + InnerInstructions []InnerInstructions `json:"innerInstructions"` + LoadedAddresses LoadedAddresses `json:"loadedAddresses"` + LogMessages []string `json:"logMessages"` + PostBalances []uint64 `json:"postBalances"` + PostTokenBalances []TokenBalance `json:"postTokenBalances"` + PreBalances []uint64 `json:"preBalances"` + PreTokenBalances []TokenBalance `json:"preTokenBalances"` + Rewards []interface{} `json:"rewards"` +} +type Header struct { + NumReadonlySignedAccounts int `json:"numReadonlySignedAccounts"` + NumReadonlyUnsignedAccounts int `json:"numReadonlyUnsignedAccounts"` + NumRequiredSignatures int `json:"numRequiredSignatures"` +} +type Message struct { + AccountKeys solana.PublicKeySlice `json:"accountKeys"` + AddressTableLookups solana.MessageAddressTableLookupSlice `json:"addressTableLookups"` + Header Header `json:"header"` + Instructions []Instruction `json:"instructions"` + RecentBlockHash string `json:"recentBlockhash"` +} + +type Transaction struct { + Message Message `json:"message"` + Signatures []solana.Signature `json:"signatures"` +} + +func (tx *Transaction) UnmarshalJSON(data []byte) error { + if len(data) == 0 || (len(data) == 4 && string(data) == "null") { + // TODO: is this an error? + return nil + } + + firstChar := data[0] + + switch firstChar { + // Check if first character is `[`, standing for a JSON array. + case '[': + // It's base64 (or similar) + { + var asDecodedBinary solana.Data + err := asDecodedBinary.UnmarshalJSON(data) + if err != nil { + return err + } + asParsedTransaction := new(solana.Transaction) + err = asParsedTransaction.UnmarshalWithDecoder(bin.NewBinDecoder(asDecodedBinary.Content)) + if err != nil { + return err + } + tx.Message = Message{ + AccountKeys: asParsedTransaction.Message.AccountKeys, + AddressTableLookups: asParsedTransaction.Message.AddressTableLookups, + Header: Header{ + NumReadonlySignedAccounts: int(asParsedTransaction.Message.Header.NumReadonlySignedAccounts), + NumReadonlyUnsignedAccounts: int(asParsedTransaction.Message.Header.NumReadonlyUnsignedAccounts), + NumRequiredSignatures: int(asParsedTransaction.Message.Header.NumRequiredSignatures), + }, + Instructions: InstructionsFromRpc(asParsedTransaction.Message.Instructions), + RecentBlockHash: asParsedTransaction.Message.RecentBlockhash.String(), + } + tx.Signatures = asParsedTransaction.Signatures + } + case '{': + // It's JSON, most likely. + { + var asParsedTransaction solana.Transaction + err := json.Unmarshal(data, &asParsedTransaction) + if err != nil { + return err + } + tx.Message = Message{ + AccountKeys: asParsedTransaction.Message.AccountKeys, + AddressTableLookups: asParsedTransaction.Message.AddressTableLookups, + Header: Header{ + NumReadonlySignedAccounts: int(asParsedTransaction.Message.Header.NumReadonlySignedAccounts), + NumReadonlyUnsignedAccounts: int(asParsedTransaction.Message.Header.NumReadonlyUnsignedAccounts), + NumRequiredSignatures: int(asParsedTransaction.Message.Header.NumRequiredSignatures), + }, + Instructions: InstructionsFromRpc(asParsedTransaction.Message.Instructions), + RecentBlockHash: asParsedTransaction.Message.RecentBlockhash.String(), + } + tx.Signatures = asParsedTransaction.Signatures + return nil + } + default: + return fmt.Errorf("Unknown kind: %v", data) + } + + return nil +} + +type ParsedTx struct { + AccountData []struct { + Account string `json:"account"` + NativeBalanceChange float64 `json:"nativeBalanceChange"` + TokenBalanceChanges []interface{} `json:"tokenBalanceChanges"` + } `json:"accountData"` + Description string `json:"description"` + Fee int `json:"fee"` + FeePayer string `json:"feePayer"` + Instructions []struct { + Accounts []string `json:"accounts"` + Data string `json:"data"` + InnerInstructions []struct { + Accounts []string `json:"accounts"` + Data string `json:"data"` + ProgramID string `json:"programId"` + } `json:"innerInstructions"` + ProgramID string `json:"programId"` + } `json:"instructions"` + NativeTransfers []struct { + Amount float64 `json:"amount"` + FromUserAccount string `json:"fromUserAccount"` + ToUserAccount string `json:"toUserAccount"` + } `json:"nativeTransfers"` + Signature string `json:"signature"` + Slot int `json:"slot"` + Source string `json:"source"` + Timestamp int `json:"timestamp"` + TokenTransfers []struct { + FromTokenAccount string `json:"fromTokenAccount"` + FromUserAccount string `json:"fromUserAccount"` + Mint string `json:"mint"` + ToTokenAccount string `json:"toTokenAccount"` + ToUserAccount string `json:"toUserAccount"` + TokenAmount float64 `json:"tokenAmount"` + TokenStandard string `json:"tokenStandard"` + } `json:"tokenTransfers"` + TransactionError interface{} `json:"transactionError"` + Type string `json:"type"` +} + +func InstructionsFromRpc(instructions []solana.CompiledInstruction) []Instruction { + var instrs []Instruction = make([]Instruction, len(instructions)) + for i, instruction := range instructions { + instrs[i] = Instruction{ + Accounts: intSliceFromUint16Slice(instruction.Accounts), + Data: instruction.Data, + ProgramIDIndex: int(instruction.ProgramIDIndex), + } + } + return instrs +} + +func InnerInstructionsFromRpc(instructions []rpc.InnerInstruction) []InnerInstructions { + var innerInstructions []InnerInstructions = make([]InnerInstructions, len(instructions)) + for i, instruction := range instructions { + //instruction.Instructions + instrs := make([]Instruction, len(instruction.Instructions)) + for j, instr := range instruction.Instructions { + instrs[j] = Instruction{ + Accounts: intSliceFromUint16Slice(instr.Accounts), + Data: instr.Data, + ProgramIDIndex: int(instr.ProgramIDIndex), + //StackHeight: instr.StackHeight, + } + } + innerInstructions[i] = InnerInstructions{ + Index: int(instruction.Index), + Instructions: instrs, + } + } + return innerInstructions +} + +func intSliceFromUint16Slice(in []uint16) []int { + out := make([]int, len(in)) + for i, v := range in { + out[i] = int(v) + } + return out +} + +func getTokenBalanceAfterTx(result *RawTx, accountIndex int) (*TokenBalance, error) { + var preBalance *TokenBalance + for _, pre := range result.Meta.PreTokenBalances { + if pre.AccountIndex == accountIndex { + preBalance = &pre + break + } + } + var postBalance *TokenBalance + + for _, post := range result.Meta.PostTokenBalances { + if post.AccountIndex == accountIndex { + post.ParseAccount() + postBalance = &post + break + } + } + if preBalance == nil && postBalance == nil { + return nil, fmt.Errorf("account not found") + } + if postBalance == nil { + preBalance.ParseAccount() + return &TokenBalance{ + AccountIndex: preBalance.AccountIndex, + MintAccount: preBalance.MintAccount, + OwnerAccount: preBalance.OwnerAccount, + ProgramIDAccount: preBalance.ProgramIDAccount, + Mint: preBalance.Mint, + Owner: preBalance.Owner, + ProgramID: preBalance.ProgramID, + UITokenAmount: UITokenAmount{ + Amount: "0", + Decimals: preBalance.UITokenAmount.Decimals, + UIAmount: 0, + UIAmountString: "0", + }, + }, nil + } + return postBalance, nil +} + +func getAccountBalanceAfterTx(result *RawTx, accountIndex int) decimal.Decimal { + x, err := getTokenBalanceAfterTx(result, accountIndex) + if err != nil { + return decimal.Zero + } + amount, err := decimal.NewFromString(x.UITokenAmount.Amount) + if err != nil { + return decimal.Zero + } + return amount +} + +func GetTokenBalanceAfterTx(result *RawTx, accountIndex int, tokenProgram, mint solana.PublicKey) decimal.Decimal { + ataAccount, _, _ := solana.FindProgramAddress([][]byte{ + result.accountList[accountIndex][:], + tokenProgram[:], + mint[:], + }, + solana.SPLAssociatedTokenAccountProgramID) + + ataIndex := 0 + for i, account := range result.accountList { + if account.Equals(ataAccount) { + ataIndex = i + break + } + } + if ataIndex == 0 { + return decimal.Zero + } + x, err := getTokenBalanceAfterTx(result, ataIndex) + if err != nil { + return decimal.Zero + } + amount, err := decimal.NewFromString(x.UITokenAmount.Amount) + if err != nil { + return decimal.Zero + } + return amount +} + +func GetSolAfterTx(result *RawTx, accountIndex int) (uint64, error) { + for i, post := range result.Meta.PostBalances { + if i == accountIndex { + return post, nil + } + } + return 0, fmt.Errorf("account not found") +} + +func solSplAccount(owner, mint solana.PublicKey) (solana.PublicKey, error) { + ataAddress, _, err := solana.FindAssociatedTokenAddress(owner, mint) + if err != nil { + return solana.PublicKey{}, err + } + return ataAddress, nil +} + +func solSpl2022Account(owner, mint solana.PublicKey) (solana.PublicKey, error) { + address, _, err := solana.FindProgramAddress([][]byte{ + owner[:], + solana.Token2022ProgramID[:], + mint[:], + }, + solana.SPLAssociatedTokenAccountProgramID, + ) + return address, err +} + +func isAccountOwner(account, owner, mint solana.PublicKey) (bool, error) { + ata, err := solSplAccount(owner, mint) + if err != nil { + return false, err + } + if account == ata { + return true, nil + } + ata, err = solSpl2022Account(owner, mint) + if err != nil { + return false, err + } + return account == ata, nil +} diff --git a/system.go b/system.go new file mode 100644 index 0000000..ea82f71 --- /dev/null +++ b/system.go @@ -0,0 +1,83 @@ +package pump_parser + +import ( + "encoding/binary" + "fmt" + + "github.com/shopspring/decimal" +) + +func systemParser(result *RawTx, instr Instruction, innerInstructions InnerInstructions, offset [2]uint, tx *Tx) ([2]uint, error) { + var instruction Instruction + + var found bool + if offset[1] == 0 { + instruction = result.Transaction.Message.Instructions[offset[0]] + found = true + } else { + for _, innerInstruction := range result.Meta.InnerInstructions { + if innerInstruction.Index == int(offset[0]) { + instruction = innerInstruction.Instructions[offset[1]-1] + found = true + break + } + } + } + if !found { + return increaseOffset(offset), fmt.Errorf("system program instruction not found, block: %d, tx: %s, outerIndex: %d, innerIndex: %d", result.Slot, result.TxHash(), offset[0], offset[1]) + } + + decode := instruction.Data + discriminator := binary.LittleEndian.Uint32(decode[0:4]) + + switch discriminator { + case transferDiscriminator: + return TransferParser(result, instruction, offset, tx, decode[4:]) + default: + return increaseOffset(offset), nil + } +} + +func TransferParser(result *RawTx, instruction Instruction, offset [2]uint, tx *Tx, decodeData []byte) ([2]uint, error) { + if len(decodeData) < 8 { + return increaseOffset(offset), nil + } + var lamports uint64 = binary.LittleEndian.Uint64(decodeData) + + //from := result.accountList[result.Transaction.Message.Instructions[offset[0]].Accounts[0]] + to := result.accountList[instruction.Accounts[1]] + + // load platform by to address + platform, ok := platformFeeAddresses[to] + if ok { + if tx.Platform != nil { + tx.Platform[platform] = platformInfo{ + Platform: platform, + PlatformFee: decimal.NewFromInt(int64(lamports)).Div(decimal.NewFromInt(1e9)), // solana decimals + } + } else { + tx.Platform = make(map[string]platformInfo) + tx.Platform[platform] = platformInfo{ + Platform: platform, + PlatformFee: decimal.NewFromInt(int64(lamports)).Div(decimal.NewFromInt(1e9)), // solana decimals + } + } + + } else if offset[1] == 0 { + // load mev agent by to address + mevAgent, ok := mevAgentFeeAddresses[to] + if !ok { + // mark it as unknown + mevAgent = MevAgentUnknown + } + if tx.MevAgent == nil { + tx.MevAgent = make(map[string]mevInfo) + } + tx.MevAgent[mevAgent] = mevInfo{ + MevAgent: mevAgent, + MevAgentFee: decimal.NewFromInt(int64(lamports)).Div(decimal.NewFromInt(1e9)), // solana decimals + } + } + + return increaseOffset(offset), nil +} diff --git a/tx.go b/tx.go new file mode 100644 index 0000000..052f731 --- /dev/null +++ b/tx.go @@ -0,0 +1,167 @@ +package pump_parser + +import ( + "fmt" + + "github.com/gagliardetto/solana-go" + "github.com/mr-tron/base58" + "github.com/shopspring/decimal" +) + +type Swap struct { + Program string + Event string + + Pool solana.PublicKey + BaseMint solana.PublicKey + QuoteMint solana.PublicKey + + BaseTokenProgram solana.PublicKey + QuoteTokenProgram solana.PublicKey + + Creator solana.PublicKey + + BaseMintDecimals uint8 + QuoteMintDecimals uint8 + + User solana.PublicKey + BaseAmount decimal.Decimal + QuoteAmount decimal.Decimal + + BaseReserve decimal.Decimal + QuoteReserve decimal.Decimal + Mayhem bool + + UserBaseBalance decimal.Decimal + UserQuoteBalance decimal.Decimal + EntryContract solana.PublicKey +} + +type platformInfo struct { + Platform string + PlatformFee decimal.Decimal +} + +type mevInfo struct { + MevAgent string + MevAgentFee decimal.Decimal +} + +type Tx struct { + Signer solana.PublicKey + Err interface{} `json:"err,omitempty"` + Swaps []Swap `json:"swaps,omitempty"` + Block uint64 `json:"block"` + BlockIndex uint64 `json:"index"` + TxHash *[64]byte `json:"-"` + BlockAt int64 `json:"block_at"` + + cachedTxHash string + + Platform map[string]platformInfo `json:"platform"` + MevAgent map[string]mevInfo ` json:"tx_mev_agent"` + CUPrice decimal.Decimal ` json:"tx_cu_price"` + + BeforeSolBalance decimal.Decimal `json:"-"` + AfterSOLBalance decimal.Decimal `json:"after_sol_balance"` + + Token []TokenMeta `gorm:"-"` +} + +type TokenMeta struct { + Address solana.PublicKey `json:"address"` + TokenProgram solana.PublicKey `json:"token_program"` + + Name string + Symbol string + Decimal uint8 + Url string + + TotalSupply *decimal.Decimal + SignerBalance *decimal.Decimal +} + +func (tx *Tx) GetTxHash() string { + if tx.cachedTxHash != "" { + return tx.cachedTxHash + } + if tx.TxHash == nil { + return "" + } + tx.cachedTxHash = base58.Encode(tx.TxHash[:]) + return tx.cachedTxHash +} + +func (tx *Tx) CheckPlatform(swap Swap, rawTx *RawTx) (string, decimal.Decimal) { + // hasSolProgramRaydiumLaunchLabBonk + var platform string + var platformFee decimal.Decimal + if len(tx.Platform) == 0 { + return PlatformNone, decimal.Zero + } + + for p, info := range tx.Platform { + platform = p + platformFee = info.PlatformFee + break + } + if swap.Event == "buy" && swap.Program == SolProgramRaydiumLaunchLabBonk { + for _, p := range tx.Platform { + switch p.Platform { + case PlatformAxiom: + if !checkBonkAxiomBuy(rawTx) { + platform = PlatformFake + } + case PlatformGMGN: + if !checkBonkGmgnBuy(rawTx) { + platform = PlatformFake + } + } + } + + } + + if platform != "" && + platform != PlatformFake { + if (swap.QuoteMint.Equals(wSolMint) || swap.QuoteMint.IsZero()) && + platformFee.LessThan(swap.QuoteAmount.Div(decimal.New(1, int32(swap.QuoteMintDecimals))).Div(decimal.NewFromInt(10000)).Mul(decimal.NewFromInt(9))) { + fmt.Printf("\n amount: %s, platform: %s, fee: %s \n", swap.QuoteAmount.Div(decimal.New(1, int32(swap.QuoteMintDecimals))), platform, platformFee.String()) + platform = PlatformFake + } else if swap.BaseMint.Equals(wSolMint) && + platformFee.LessThan(swap.QuoteAmount.Div(decimal.New(1, int32(swap.QuoteMintDecimals))).Div(decimal.NewFromInt(10000)).Mul(decimal.NewFromInt(9))) { + platform = PlatformFake + } + + } + if platform == "" { + platform = PlatformNone + } + return platform, platformFee +} + +func (tx *Tx) CheckMevAgent() (string, decimal.Decimal) { + var mevAgent = MevAgentUnknown + var mevAgentFee = decimal.Zero + + for m, info := range tx.MevAgent { + if len(tx.MevAgent) > 1 && info.MevAgent == MevAgentUnknown { + continue + } + mevAgent = m + mevAgentFee = info.MevAgentFee + break + } + if len(tx.MevAgent) == 0 && mevAgent == MevAgentUnknown { + // set the mev agent to none if the platform does not exist + return "", decimal.Zero + } + return mevAgent, mevAgentFee +} + +func (s Swap) CheckEntryContract() string { + name, ok := entryContractAddresses[s.EntryContract] + if ok { + return name + } + return EntryContractUnknown +}