commit a945f3b45da992b8efc1df08cb8b82cc583ca81f Author: thloyi Date: Thu Nov 20 17:56:45 2025 +0800 punm parser 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 +}