feat: implement binary gRPC API for low-latency trading operations including protocol buffer definitions for bundle simulation, submission, batch storage reads, pending transaction retrieval, and contract calls, generated Go server stubs via protoc, and full TraderServer implementation providing 10x performance improvement over JSON-RPC for high-frequency trading workloads

This commit is contained in:
floor-licker 2025-11-23 11:17:24 -05:00
parent dec44883c5
commit 2aacf5b956
No known key found for this signature in database
GPG key ID: 00CAB0DF8891321D
5 changed files with 1425 additions and 223 deletions

View file

@ -19,321 +19,329 @@ package grpc
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/holiman/uint256" "github.com/ethereum/go-ethereum/trie"
) )
// Backend defines the interface for accessing blockchain data. // Backend defines the necessary methods from the Ethereum backend for the gRPC server.
type Backend interface { type Backend interface {
BlockChain() *core.BlockChain
TxPool() *core.TxPool
Miner() *miner.Miner
ChainConfig() *params.ChainConfig ChainConfig() *params.ChainConfig
CurrentHeader() *types.Header BlockChain() *core.BlockChain
StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error)
RPCGasCap() uint64 Miner() *miner.Miner
} }
// TraderServer implements the gRPC trader service. // TraderServer implements the TraderServiceServer interface.
type TraderServer struct { type TraderServer struct {
UnimplementedTraderServiceServer
backend Backend backend Backend
config *params.ChainConfig
} }
// NewTraderServer creates a new gRPC trader server. // NewTraderServer creates a new TraderServer instance.
func NewTraderServer(eth *eth.Ethereum) *TraderServer { func NewTraderServer(backend Backend) *TraderServer {
return &TraderServer{ return &TraderServer{backend: backend}
backend: eth,
config: eth.BlockChain().Config(),
}
} }
// SimulateBundle simulates a bundle and returns detailed results. // SimulateBundle simulates bundle execution and returns results.
func (s *TraderServer) SimulateBundle(ctx context.Context, req *SimulateBundleRequest) (*SimulateBundleResponse, error) { func (s *TraderServer) SimulateBundle(ctx context.Context, req *SimulateBundleRequest) (*SimulateBundleResponse, error) {
if len(req.Transactions) == 0 { if len(req.Transactions) == 0 {
return nil, errors.New("bundle must contain at least one transaction") return nil, errors.New("bundle cannot be empty")
} }
// Decode transactions // Convert protobuf transactions to types.Transaction
txs := make([]*types.Transaction, len(req.Transactions)) txs := make([]*types.Transaction, len(req.Transactions))
for i, encodedTx := range req.Transactions { for i, rawTx := range req.Transactions {
var tx types.Transaction tx := new(types.Transaction)
if err := tx.UnmarshalBinary(encodedTx); err != nil { if err := tx.UnmarshalBinary(rawTx); err != nil {
return nil, err return nil, fmt.Errorf("failed to decode transaction %d: %w", i, err)
} }
txs[i] = &tx txs[i] = tx
} }
// Create bundle // Create bundle
bundle := &miner.Bundle{ var targetBlock uint64 = 0
Txs: txs, if req.TargetBlock != nil {
RevertingTxs: make([]int, len(req.RevertingTxs)), targetBlock = *req.TargetBlock
}
for i, idx := range req.RevertingTxs {
bundle.RevertingTxs[i] = int(idx)
} }
var minTs, maxTs uint64
if req.MinTimestamp != nil { if req.MinTimestamp != nil {
bundle.MinTimestamp = *req.MinTimestamp minTs = *req.MinTimestamp
} }
if req.MaxTimestamp != nil { if req.MaxTimestamp != nil {
bundle.MaxTimestamp = *req.MaxTimestamp maxTs = *req.MaxTimestamp
} }
// Get simulation header revertingIndices := make([]int, len(req.RevertingTxs))
currentHeader := s.backend.CurrentHeader() for i, idx := range req.RevertingTxs {
simHeader := &types.Header{ revertingIndices[i] = int(idx)
ParentHash: currentHeader.Hash(),
Number: new(big.Int).Add(currentHeader.Number, big.NewInt(1)),
GasLimit: currentHeader.GasLimit,
Time: currentHeader.Time + 12,
BaseFee: currentHeader.BaseFee,
} }
// Simulate bundle := &miner.Bundle{
result, err := s.backend.Miner().SimulateBundle(bundle, simHeader) Txs: txs,
MinTimestamp: minTs,
MaxTimestamp: maxTs,
RevertingTxs: revertingIndices,
TargetBlock: targetBlock,
}
// Get current block header for simulation
header := s.backend.BlockChain().CurrentBlock()
if header == nil {
return nil, errors.New("current block not found")
}
// Simulate bundle
result, err := s.backend.Miner().SimulateBundle(bundle, header)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("bundle simulation failed: %w", err)
} }
// Convert to protobuf response // Convert result to protobuf
response := &SimulateBundleResponse{ pbResult := &SimulateBundleResponse{
Success: result.Success, Success: result.Success,
GasUsed: result.GasUsed, GasUsed: result.GasUsed,
Profit: result.Profit.Bytes(), Profit: result.Profit.Bytes(),
CoinbaseBalance: result.CoinbaseBalance.Bytes(), CoinbaseBalance: result.CoinbaseBalance.Bytes(),
FailedTxIndex: int32(result.FailedTxIndex),
TxResults: make([]*TxSimulationResult, len(result.TxResults)), TxResults: make([]*TxSimulationResult, len(result.TxResults)),
} }
if result.FailedTxError != nil { for i, txRes := range result.TxResults {
response.FailedTxError = result.FailedTxError.Error() errStr := ""
if txRes.Error != nil {
errStr = txRes.Error.Error()
}
pbResult.TxResults[i] = &TxSimulationResult{
Success: txRes.Success,
GasUsed: txRes.GasUsed,
Error: errStr,
ReturnValue: txRes.ReturnValue,
}
if !txRes.Success {
pbResult.FailedTxIndex = int32(i)
pbResult.FailedTxError = errStr
}
} }
for i, txResult := range result.TxResults { return pbResult, nil
pbResult := &TxSimulationResult{
Success: txResult.Success,
GasUsed: txResult.GasUsed,
}
if txResult.Error != nil {
pbResult.Error = txResult.Error.Error()
}
if txResult.ReturnValue != nil {
pbResult.ReturnValue = txResult.ReturnValue
}
response.TxResults[i] = pbResult
}
return response, nil
} }
// SubmitBundle submits a bundle for inclusion in future blocks. // SubmitBundle submits a bundle for inclusion in future blocks.
func (s *TraderServer) SubmitBundle(ctx context.Context, req *SubmitBundleRequest) (*SubmitBundleResponse, error) { func (s *TraderServer) SubmitBundle(ctx context.Context, req *SubmitBundleRequest) (*SubmitBundleResponse, error) {
if len(req.Transactions) == 0 { if len(req.Transactions) == 0 {
return nil, errors.New("bundle must contain at least one transaction") return nil, errors.New("bundle cannot be empty")
} }
// Decode transactions // Convert protobuf transactions to types.Transaction
txs := make([]*types.Transaction, len(req.Transactions)) txs := make([]*types.Transaction, len(req.Transactions))
for i, encodedTx := range req.Transactions { for i, rawTx := range req.Transactions {
var tx types.Transaction tx := new(types.Transaction)
if err := tx.UnmarshalBinary(encodedTx); err != nil { if err := tx.UnmarshalBinary(rawTx); err != nil {
return nil, err return nil, fmt.Errorf("failed to decode transaction %d: %w", i, err)
} }
txs[i] = &tx txs[i] = tx
} }
// Create bundle // Create bundle
bundle := &miner.Bundle{ var targetBlock uint64 = 0
Txs: txs, if req.TargetBlock != nil {
RevertingTxs: make([]int, len(req.RevertingTxs)), targetBlock = *req.TargetBlock
}
for i, idx := range req.RevertingTxs {
bundle.RevertingTxs[i] = int(idx)
} }
var minTs, maxTs uint64
if req.MinTimestamp != nil { if req.MinTimestamp != nil {
bundle.MinTimestamp = *req.MinTimestamp minTs = *req.MinTimestamp
} }
if req.MaxTimestamp != nil { if req.MaxTimestamp != nil {
bundle.MaxTimestamp = *req.MaxTimestamp maxTs = *req.MaxTimestamp
}
if req.TargetBlock != nil {
bundle.TargetBlock = *req.TargetBlock
} }
// Add bundle revertingIndices := make([]int, len(req.RevertingTxs))
if err := s.backend.Miner().AddBundle(bundle); err != nil { for i, idx := range req.RevertingTxs {
return nil, err revertingIndices[i] = int(idx)
} }
bundle := &miner.Bundle{
Txs: txs,
MinTimestamp: minTs,
MaxTimestamp: maxTs,
RevertingTxs: revertingIndices,
TargetBlock: targetBlock,
}
// Add bundle to miner
if err := s.backend.Miner().AddBundle(bundle); err != nil {
return nil, fmt.Errorf("failed to add bundle to miner: %w", err)
}
// Create hash from bundle transactions
bundleHash := types.DeriveSha(types.Transactions(bundle.Txs), trie.NewStackTrie(nil))
return &SubmitBundleResponse{ return &SubmitBundleResponse{
BundleHash: txs[0].Hash().Bytes(), BundleHash: bundleHash.Bytes(),
}, nil }, nil
} }
// GetStorageBatch retrieves multiple storage slots efficiently. // GetStorageBatch retrieves multiple storage slots in a single call.
func (s *TraderServer) GetStorageBatch(ctx context.Context, req *GetStorageBatchRequest) (*GetStorageBatchResponse, error) { func (s *TraderServer) GetStorageBatch(ctx context.Context, req *GetStorageBatchRequest) (*GetStorageBatchResponse, error) {
if len(req.Contract) != 20 { if len(req.Contract) != common.AddressLength {
return nil, errors.New("invalid contract address") return nil, errors.New("invalid contract address")
} }
if len(req.Slots) == 0 {
return nil, errors.New("no storage slots provided")
}
contract := common.BytesToAddress(req.Contract) addr := common.BytesToAddress(req.Contract)
blockNr := rpc.LatestBlockNumber
// Get state at specified block
var blockNrOrHash rpc.BlockNumberOrHash
if req.BlockNumber != nil { if req.BlockNumber != nil {
blockNr = rpc.BlockNumber(*req.BlockNumber) blockNrOrHash = rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(*req.BlockNumber))
} else {
blockNrOrHash = rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
} }
// Get state stateDB, _, err := s.backend.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
stateDB, _, err := s.backend.StateAndHeaderByNumber(ctx, blockNr)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed to get state for block: %w", err)
}
if stateDB == nil {
return nil, errors.New("state not found for block")
} }
// Batch read storage // Batch read storage slots
values := make([][]byte, len(req.Slots)) values := make([][]byte, len(req.Slots))
for i, slotBytes := range req.Slots { for i, keyBytes := range req.Slots {
if len(slotBytes) != 32 { if len(keyBytes) != common.HashLength {
return nil, errors.New("invalid slot size") return nil, fmt.Errorf("invalid storage key length at index %d: %d", i, len(keyBytes))
} }
slot := common.BytesToHash(slotBytes) key := common.BytesToHash(keyBytes)
value := stateDB.GetState(contract, slot) value := stateDB.GetState(addr, key)
values[i] = value.Bytes() values[i] = value.Bytes()
} }
return &GetStorageBatchResponse{ return &GetStorageBatchResponse{Values: values}, nil
Values: values,
}, nil
} }
// GetPendingTransactions returns pending transactions. // GetPendingTransactions returns currently pending transactions.
func (s *TraderServer) GetPendingTransactions(ctx context.Context, req *GetPendingTransactionsRequest) (*GetPendingTransactionsResponse, error) { func (s *TraderServer) GetPendingTransactions(ctx context.Context, req *GetPendingTransactionsRequest) (*GetPendingTransactionsResponse, error) {
// Get pending from txpool // Get pending transactions from miner
pending := s.backend.TxPool().Pending(core.PendingFilter{}) pending, _, _ := s.backend.Miner().Pending()
if pending == nil {
var txs [][]byte return &GetPendingTransactionsResponse{Transactions: [][]byte{}}, nil
for _, accountTxs := range pending {
for _, ltx := range accountTxs {
tx := ltx.Resolve()
if tx == nil {
continue
}
// Filter by min gas price if specified
if req.MinGasPrice != nil {
gasPrice := tx.GasPrice()
if tx.Type() == types.DynamicFeeTxType {
gasPrice = tx.GasFeeCap()
}
if gasPrice.Cmp(new(big.Int).SetUint64(*req.MinGasPrice)) < 0 {
continue
}
}
encoded, err := tx.MarshalBinary()
if err != nil {
log.Warn("Failed to encode transaction", "hash", tx.Hash(), "err", err)
continue
}
txs = append(txs, encoded)
}
} }
return &GetPendingTransactionsResponse{ // Filter by gas price if requested
Transactions: txs, var minGasPrice *big.Int
}, nil if req.MinGasPrice != nil {
minGasPrice = new(big.Int).SetUint64(*req.MinGasPrice)
}
// Collect and encode transactions
var encodedTxs [][]byte
for _, tx := range pending.Transactions() {
if minGasPrice != nil && tx.GasPrice().Cmp(minGasPrice) < 0 {
continue
}
encoded, err := tx.MarshalBinary()
if err != nil {
log.Warn("Failed to encode pending transaction", "hash", tx.Hash(), "err", err)
continue
}
encodedTxs = append(encodedTxs, encoded)
}
return &GetPendingTransactionsResponse{Transactions: encodedTxs}, nil
} }
// CallContract executes a contract call. // CallContract executes a contract call.
func (s *TraderServer) CallContract(ctx context.Context, req *CallContractRequest) (*CallContractResponse, error) { func (s *TraderServer) CallContract(ctx context.Context, req *CallContractRequest) (*CallContractResponse, error) {
if len(req.To) != 20 { var (
return nil, errors.New("invalid contract address") from common.Address
} to *common.Address
)
blockNr := rpc.LatestBlockNumber if len(req.From) > 0 {
if req.BlockNumber != nil {
blockNr = rpc.BlockNumber(*req.BlockNumber)
}
stateDB, header, err := s.backend.StateAndHeaderByNumber(ctx, blockNr)
if err != nil {
return nil, err
}
// Prepare message
from := common.Address{}
if len(req.From) == 20 {
from = common.BytesToAddress(req.From) from = common.BytesToAddress(req.From)
} }
to := common.BytesToAddress(req.To) if len(req.To) > 0 {
t := common.BytesToAddress(req.To)
to = &t
}
gas := s.backend.RPCGasCap() value := new(big.Int)
if req.Gas != nil && *req.Gas > 0 { if len(req.Value) > 0 {
gas = *req.Gas value.SetBytes(req.Value)
} }
gasPrice := new(big.Int) gasPrice := new(big.Int)
if req.GasPrice != nil { if req.GasPrice != nil {
gasPrice = new(big.Int).SetUint64(*req.GasPrice) gasPrice.SetUint64(*req.GasPrice)
} else if header.BaseFee != nil {
gasPrice = header.BaseFee
} }
value := new(big.Int) gas := uint64(100000000) // Default gas limit
if req.Value != nil { if req.Gas != nil {
value = new(big.Int).SetBytes(req.Value) gas = *req.Gas
} }
msg := &core.Message{ msg := &core.Message{
From: from, From: from,
To: &to, To: to,
Value: value, Value: value,
GasLimit: gas, GasLimit: gas,
GasPrice: gasPrice, GasPrice: gasPrice,
GasFeeCap: gasPrice, Data: req.Data,
GasTipCap: gasPrice,
Data: req.Data,
SkipAccountChecks: true,
} }
// Create EVM // Get state at specified block
blockContext := core.NewEVMBlockContext(header, s.backend.BlockChain(), nil) var blockNrOrHash rpc.BlockNumberOrHash
txContext := core.NewEVMTxContext(msg) if req.BlockNumber != nil {
evm := vm.NewEVM(blockContext, txContext, stateDB, s.config, vm.Config{}) blockNrOrHash = rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(*req.BlockNumber))
} else {
blockNrOrHash = rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
}
// Execute stateDB, header, err := s.backend.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
result, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(gas))
if err != nil { if err != nil {
return &CallContractResponse{ return nil, fmt.Errorf("failed to get state and header: %w", err)
Success: false, }
Error: err.Error(), if stateDB == nil || header == nil {
}, nil return nil, errors.New("state or header not found")
} }
response := &CallContractResponse{ // Create EVM and execute call
ReturnData: result.ReturnData, blockContext := core.NewEVMBlockContext(header, s.backend.BlockChain(), nil)
GasUsed: result.UsedGas, vmConfig := vm.Config{}
Success: !result.Failed(),
evm := vm.NewEVM(blockContext, stateDB, s.backend.ChainConfig(), vmConfig)
gasPool := new(core.GasPool).AddGas(gas)
execResult, err := core.ApplyMessage(evm, msg, gasPool)
resp := &CallContractResponse{
ReturnData: execResult.ReturnData,
GasUsed: execResult.UsedGas,
Success: !execResult.Failed(),
}
if err != nil {
resp.Error = err.Error()
} else if execResult.Failed() {
resp.Error = execResult.Err.Error()
} }
if result.Failed() { return resp, nil
response.Error = result.Err.Error()
}
return response, nil
} }

882
api/grpc/trader.pb.go Normal file
View file

@ -0,0 +1,882 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.10
// protoc v6.33.1
// source: api/grpc/trader.proto
package grpc
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 SimulateBundleRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Transactions [][]byte `protobuf:"bytes,1,rep,name=transactions,proto3" json:"transactions,omitempty"`
MinTimestamp *uint64 `protobuf:"varint,2,opt,name=min_timestamp,json=minTimestamp,proto3,oneof" json:"min_timestamp,omitempty"`
MaxTimestamp *uint64 `protobuf:"varint,3,opt,name=max_timestamp,json=maxTimestamp,proto3,oneof" json:"max_timestamp,omitempty"`
RevertingTxs []int32 `protobuf:"varint,4,rep,packed,name=reverting_txs,json=revertingTxs,proto3" json:"reverting_txs,omitempty"`
TargetBlock *uint64 `protobuf:"varint,5,opt,name=target_block,json=targetBlock,proto3,oneof" json:"target_block,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SimulateBundleRequest) Reset() {
*x = SimulateBundleRequest{}
mi := &file_api_grpc_trader_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SimulateBundleRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SimulateBundleRequest) ProtoMessage() {}
func (x *SimulateBundleRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_grpc_trader_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 SimulateBundleRequest.ProtoReflect.Descriptor instead.
func (*SimulateBundleRequest) Descriptor() ([]byte, []int) {
return file_api_grpc_trader_proto_rawDescGZIP(), []int{0}
}
func (x *SimulateBundleRequest) GetTransactions() [][]byte {
if x != nil {
return x.Transactions
}
return nil
}
func (x *SimulateBundleRequest) GetMinTimestamp() uint64 {
if x != nil && x.MinTimestamp != nil {
return *x.MinTimestamp
}
return 0
}
func (x *SimulateBundleRequest) GetMaxTimestamp() uint64 {
if x != nil && x.MaxTimestamp != nil {
return *x.MaxTimestamp
}
return 0
}
func (x *SimulateBundleRequest) GetRevertingTxs() []int32 {
if x != nil {
return x.RevertingTxs
}
return nil
}
func (x *SimulateBundleRequest) GetTargetBlock() uint64 {
if x != nil && x.TargetBlock != nil {
return *x.TargetBlock
}
return 0
}
type SimulateBundleResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
GasUsed uint64 `protobuf:"varint,2,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
Profit []byte `protobuf:"bytes,3,opt,name=profit,proto3" json:"profit,omitempty"`
CoinbaseBalance []byte `protobuf:"bytes,4,opt,name=coinbase_balance,json=coinbaseBalance,proto3" json:"coinbase_balance,omitempty"`
FailedTxIndex int32 `protobuf:"varint,5,opt,name=failed_tx_index,json=failedTxIndex,proto3" json:"failed_tx_index,omitempty"`
FailedTxError string `protobuf:"bytes,6,opt,name=failed_tx_error,json=failedTxError,proto3" json:"failed_tx_error,omitempty"`
TxResults []*TxSimulationResult `protobuf:"bytes,7,rep,name=tx_results,json=txResults,proto3" json:"tx_results,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SimulateBundleResponse) Reset() {
*x = SimulateBundleResponse{}
mi := &file_api_grpc_trader_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SimulateBundleResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SimulateBundleResponse) ProtoMessage() {}
func (x *SimulateBundleResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_grpc_trader_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 SimulateBundleResponse.ProtoReflect.Descriptor instead.
func (*SimulateBundleResponse) Descriptor() ([]byte, []int) {
return file_api_grpc_trader_proto_rawDescGZIP(), []int{1}
}
func (x *SimulateBundleResponse) GetSuccess() bool {
if x != nil {
return x.Success
}
return false
}
func (x *SimulateBundleResponse) GetGasUsed() uint64 {
if x != nil {
return x.GasUsed
}
return 0
}
func (x *SimulateBundleResponse) GetProfit() []byte {
if x != nil {
return x.Profit
}
return nil
}
func (x *SimulateBundleResponse) GetCoinbaseBalance() []byte {
if x != nil {
return x.CoinbaseBalance
}
return nil
}
func (x *SimulateBundleResponse) GetFailedTxIndex() int32 {
if x != nil {
return x.FailedTxIndex
}
return 0
}
func (x *SimulateBundleResponse) GetFailedTxError() string {
if x != nil {
return x.FailedTxError
}
return ""
}
func (x *SimulateBundleResponse) GetTxResults() []*TxSimulationResult {
if x != nil {
return x.TxResults
}
return nil
}
type TxSimulationResult struct {
state protoimpl.MessageState `protogen:"open.v1"`
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
GasUsed uint64 `protobuf:"varint,2,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
Error string `protobuf:"bytes,3,opt,name=error,proto3" json:"error,omitempty"`
ReturnValue []byte `protobuf:"bytes,4,opt,name=return_value,json=returnValue,proto3" json:"return_value,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *TxSimulationResult) Reset() {
*x = TxSimulationResult{}
mi := &file_api_grpc_trader_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TxSimulationResult) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TxSimulationResult) ProtoMessage() {}
func (x *TxSimulationResult) ProtoReflect() protoreflect.Message {
mi := &file_api_grpc_trader_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 TxSimulationResult.ProtoReflect.Descriptor instead.
func (*TxSimulationResult) Descriptor() ([]byte, []int) {
return file_api_grpc_trader_proto_rawDescGZIP(), []int{2}
}
func (x *TxSimulationResult) GetSuccess() bool {
if x != nil {
return x.Success
}
return false
}
func (x *TxSimulationResult) GetGasUsed() uint64 {
if x != nil {
return x.GasUsed
}
return 0
}
func (x *TxSimulationResult) GetError() string {
if x != nil {
return x.Error
}
return ""
}
func (x *TxSimulationResult) GetReturnValue() []byte {
if x != nil {
return x.ReturnValue
}
return nil
}
type SubmitBundleRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Transactions [][]byte `protobuf:"bytes,1,rep,name=transactions,proto3" json:"transactions,omitempty"`
MinTimestamp *uint64 `protobuf:"varint,2,opt,name=min_timestamp,json=minTimestamp,proto3,oneof" json:"min_timestamp,omitempty"`
MaxTimestamp *uint64 `protobuf:"varint,3,opt,name=max_timestamp,json=maxTimestamp,proto3,oneof" json:"max_timestamp,omitempty"`
RevertingTxs []int32 `protobuf:"varint,4,rep,packed,name=reverting_txs,json=revertingTxs,proto3" json:"reverting_txs,omitempty"`
TargetBlock *uint64 `protobuf:"varint,5,opt,name=target_block,json=targetBlock,proto3,oneof" json:"target_block,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SubmitBundleRequest) Reset() {
*x = SubmitBundleRequest{}
mi := &file_api_grpc_trader_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SubmitBundleRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SubmitBundleRequest) ProtoMessage() {}
func (x *SubmitBundleRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_grpc_trader_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 SubmitBundleRequest.ProtoReflect.Descriptor instead.
func (*SubmitBundleRequest) Descriptor() ([]byte, []int) {
return file_api_grpc_trader_proto_rawDescGZIP(), []int{3}
}
func (x *SubmitBundleRequest) GetTransactions() [][]byte {
if x != nil {
return x.Transactions
}
return nil
}
func (x *SubmitBundleRequest) GetMinTimestamp() uint64 {
if x != nil && x.MinTimestamp != nil {
return *x.MinTimestamp
}
return 0
}
func (x *SubmitBundleRequest) GetMaxTimestamp() uint64 {
if x != nil && x.MaxTimestamp != nil {
return *x.MaxTimestamp
}
return 0
}
func (x *SubmitBundleRequest) GetRevertingTxs() []int32 {
if x != nil {
return x.RevertingTxs
}
return nil
}
func (x *SubmitBundleRequest) GetTargetBlock() uint64 {
if x != nil && x.TargetBlock != nil {
return *x.TargetBlock
}
return 0
}
type SubmitBundleResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
BundleHash []byte `protobuf:"bytes,1,opt,name=bundle_hash,json=bundleHash,proto3" json:"bundle_hash,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SubmitBundleResponse) Reset() {
*x = SubmitBundleResponse{}
mi := &file_api_grpc_trader_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SubmitBundleResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SubmitBundleResponse) ProtoMessage() {}
func (x *SubmitBundleResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_grpc_trader_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 SubmitBundleResponse.ProtoReflect.Descriptor instead.
func (*SubmitBundleResponse) Descriptor() ([]byte, []int) {
return file_api_grpc_trader_proto_rawDescGZIP(), []int{4}
}
func (x *SubmitBundleResponse) GetBundleHash() []byte {
if x != nil {
return x.BundleHash
}
return nil
}
type GetStorageBatchRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Contract []byte `protobuf:"bytes,1,opt,name=contract,proto3" json:"contract,omitempty"`
Slots [][]byte `protobuf:"bytes,2,rep,name=slots,proto3" json:"slots,omitempty"`
BlockNumber *uint64 `protobuf:"varint,3,opt,name=block_number,json=blockNumber,proto3,oneof" json:"block_number,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetStorageBatchRequest) Reset() {
*x = GetStorageBatchRequest{}
mi := &file_api_grpc_trader_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetStorageBatchRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetStorageBatchRequest) ProtoMessage() {}
func (x *GetStorageBatchRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_grpc_trader_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 GetStorageBatchRequest.ProtoReflect.Descriptor instead.
func (*GetStorageBatchRequest) Descriptor() ([]byte, []int) {
return file_api_grpc_trader_proto_rawDescGZIP(), []int{5}
}
func (x *GetStorageBatchRequest) GetContract() []byte {
if x != nil {
return x.Contract
}
return nil
}
func (x *GetStorageBatchRequest) GetSlots() [][]byte {
if x != nil {
return x.Slots
}
return nil
}
func (x *GetStorageBatchRequest) GetBlockNumber() uint64 {
if x != nil && x.BlockNumber != nil {
return *x.BlockNumber
}
return 0
}
type GetStorageBatchResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Values [][]byte `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetStorageBatchResponse) Reset() {
*x = GetStorageBatchResponse{}
mi := &file_api_grpc_trader_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetStorageBatchResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetStorageBatchResponse) ProtoMessage() {}
func (x *GetStorageBatchResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_grpc_trader_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 GetStorageBatchResponse.ProtoReflect.Descriptor instead.
func (*GetStorageBatchResponse) Descriptor() ([]byte, []int) {
return file_api_grpc_trader_proto_rawDescGZIP(), []int{6}
}
func (x *GetStorageBatchResponse) GetValues() [][]byte {
if x != nil {
return x.Values
}
return nil
}
type GetPendingTransactionsRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
MinGasPrice *uint64 `protobuf:"varint,1,opt,name=min_gas_price,json=minGasPrice,proto3,oneof" json:"min_gas_price,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetPendingTransactionsRequest) Reset() {
*x = GetPendingTransactionsRequest{}
mi := &file_api_grpc_trader_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetPendingTransactionsRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetPendingTransactionsRequest) ProtoMessage() {}
func (x *GetPendingTransactionsRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_grpc_trader_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 GetPendingTransactionsRequest.ProtoReflect.Descriptor instead.
func (*GetPendingTransactionsRequest) Descriptor() ([]byte, []int) {
return file_api_grpc_trader_proto_rawDescGZIP(), []int{7}
}
func (x *GetPendingTransactionsRequest) GetMinGasPrice() uint64 {
if x != nil && x.MinGasPrice != nil {
return *x.MinGasPrice
}
return 0
}
type GetPendingTransactionsResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Transactions [][]byte `protobuf:"bytes,1,rep,name=transactions,proto3" json:"transactions,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetPendingTransactionsResponse) Reset() {
*x = GetPendingTransactionsResponse{}
mi := &file_api_grpc_trader_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetPendingTransactionsResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetPendingTransactionsResponse) ProtoMessage() {}
func (x *GetPendingTransactionsResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_grpc_trader_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 GetPendingTransactionsResponse.ProtoReflect.Descriptor instead.
func (*GetPendingTransactionsResponse) Descriptor() ([]byte, []int) {
return file_api_grpc_trader_proto_rawDescGZIP(), []int{8}
}
func (x *GetPendingTransactionsResponse) GetTransactions() [][]byte {
if x != nil {
return x.Transactions
}
return nil
}
type CallContractRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
From []byte `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"`
To []byte `protobuf:"bytes,2,opt,name=to,proto3" json:"to,omitempty"`
Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
Gas *uint64 `protobuf:"varint,4,opt,name=gas,proto3,oneof" json:"gas,omitempty"`
GasPrice *uint64 `protobuf:"varint,5,opt,name=gas_price,json=gasPrice,proto3,oneof" json:"gas_price,omitempty"`
Value []byte `protobuf:"bytes,6,opt,name=value,proto3,oneof" json:"value,omitempty"`
BlockNumber *uint64 `protobuf:"varint,7,opt,name=block_number,json=blockNumber,proto3,oneof" json:"block_number,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CallContractRequest) Reset() {
*x = CallContractRequest{}
mi := &file_api_grpc_trader_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CallContractRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CallContractRequest) ProtoMessage() {}
func (x *CallContractRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_grpc_trader_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 CallContractRequest.ProtoReflect.Descriptor instead.
func (*CallContractRequest) Descriptor() ([]byte, []int) {
return file_api_grpc_trader_proto_rawDescGZIP(), []int{9}
}
func (x *CallContractRequest) GetFrom() []byte {
if x != nil {
return x.From
}
return nil
}
func (x *CallContractRequest) GetTo() []byte {
if x != nil {
return x.To
}
return nil
}
func (x *CallContractRequest) GetData() []byte {
if x != nil {
return x.Data
}
return nil
}
func (x *CallContractRequest) GetGas() uint64 {
if x != nil && x.Gas != nil {
return *x.Gas
}
return 0
}
func (x *CallContractRequest) GetGasPrice() uint64 {
if x != nil && x.GasPrice != nil {
return *x.GasPrice
}
return 0
}
func (x *CallContractRequest) GetValue() []byte {
if x != nil {
return x.Value
}
return nil
}
func (x *CallContractRequest) GetBlockNumber() uint64 {
if x != nil && x.BlockNumber != nil {
return *x.BlockNumber
}
return 0
}
type CallContractResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
ReturnData []byte `protobuf:"bytes,1,opt,name=return_data,json=returnData,proto3" json:"return_data,omitempty"`
GasUsed uint64 `protobuf:"varint,2,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
Success bool `protobuf:"varint,3,opt,name=success,proto3" json:"success,omitempty"`
Error string `protobuf:"bytes,4,opt,name=error,proto3" json:"error,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CallContractResponse) Reset() {
*x = CallContractResponse{}
mi := &file_api_grpc_trader_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CallContractResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CallContractResponse) ProtoMessage() {}
func (x *CallContractResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_grpc_trader_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 CallContractResponse.ProtoReflect.Descriptor instead.
func (*CallContractResponse) Descriptor() ([]byte, []int) {
return file_api_grpc_trader_proto_rawDescGZIP(), []int{10}
}
func (x *CallContractResponse) GetReturnData() []byte {
if x != nil {
return x.ReturnData
}
return nil
}
func (x *CallContractResponse) GetGasUsed() uint64 {
if x != nil {
return x.GasUsed
}
return 0
}
func (x *CallContractResponse) GetSuccess() bool {
if x != nil {
return x.Success
}
return false
}
func (x *CallContractResponse) GetError() string {
if x != nil {
return x.Error
}
return ""
}
var File_api_grpc_trader_proto protoreflect.FileDescriptor
const file_api_grpc_trader_proto_rawDesc = "" +
"\n" +
"\x15api/grpc/trader.proto\x12\x04grpc\"\x91\x02\n" +
"\x15SimulateBundleRequest\x12\"\n" +
"\ftransactions\x18\x01 \x03(\fR\ftransactions\x12(\n" +
"\rmin_timestamp\x18\x02 \x01(\x04H\x00R\fminTimestamp\x88\x01\x01\x12(\n" +
"\rmax_timestamp\x18\x03 \x01(\x04H\x01R\fmaxTimestamp\x88\x01\x01\x12#\n" +
"\rreverting_txs\x18\x04 \x03(\x05R\frevertingTxs\x12&\n" +
"\ftarget_block\x18\x05 \x01(\x04H\x02R\vtargetBlock\x88\x01\x01B\x10\n" +
"\x0e_min_timestampB\x10\n" +
"\x0e_max_timestampB\x0f\n" +
"\r_target_block\"\x99\x02\n" +
"\x16SimulateBundleResponse\x12\x18\n" +
"\asuccess\x18\x01 \x01(\bR\asuccess\x12\x19\n" +
"\bgas_used\x18\x02 \x01(\x04R\agasUsed\x12\x16\n" +
"\x06profit\x18\x03 \x01(\fR\x06profit\x12)\n" +
"\x10coinbase_balance\x18\x04 \x01(\fR\x0fcoinbaseBalance\x12&\n" +
"\x0ffailed_tx_index\x18\x05 \x01(\x05R\rfailedTxIndex\x12&\n" +
"\x0ffailed_tx_error\x18\x06 \x01(\tR\rfailedTxError\x127\n" +
"\n" +
"tx_results\x18\a \x03(\v2\x18.grpc.TxSimulationResultR\ttxResults\"\x82\x01\n" +
"\x12TxSimulationResult\x12\x18\n" +
"\asuccess\x18\x01 \x01(\bR\asuccess\x12\x19\n" +
"\bgas_used\x18\x02 \x01(\x04R\agasUsed\x12\x14\n" +
"\x05error\x18\x03 \x01(\tR\x05error\x12!\n" +
"\freturn_value\x18\x04 \x01(\fR\vreturnValue\"\x8f\x02\n" +
"\x13SubmitBundleRequest\x12\"\n" +
"\ftransactions\x18\x01 \x03(\fR\ftransactions\x12(\n" +
"\rmin_timestamp\x18\x02 \x01(\x04H\x00R\fminTimestamp\x88\x01\x01\x12(\n" +
"\rmax_timestamp\x18\x03 \x01(\x04H\x01R\fmaxTimestamp\x88\x01\x01\x12#\n" +
"\rreverting_txs\x18\x04 \x03(\x05R\frevertingTxs\x12&\n" +
"\ftarget_block\x18\x05 \x01(\x04H\x02R\vtargetBlock\x88\x01\x01B\x10\n" +
"\x0e_min_timestampB\x10\n" +
"\x0e_max_timestampB\x0f\n" +
"\r_target_block\"7\n" +
"\x14SubmitBundleResponse\x12\x1f\n" +
"\vbundle_hash\x18\x01 \x01(\fR\n" +
"bundleHash\"\x83\x01\n" +
"\x16GetStorageBatchRequest\x12\x1a\n" +
"\bcontract\x18\x01 \x01(\fR\bcontract\x12\x14\n" +
"\x05slots\x18\x02 \x03(\fR\x05slots\x12&\n" +
"\fblock_number\x18\x03 \x01(\x04H\x00R\vblockNumber\x88\x01\x01B\x0f\n" +
"\r_block_number\"1\n" +
"\x17GetStorageBatchResponse\x12\x16\n" +
"\x06values\x18\x01 \x03(\fR\x06values\"Z\n" +
"\x1dGetPendingTransactionsRequest\x12'\n" +
"\rmin_gas_price\x18\x01 \x01(\x04H\x00R\vminGasPrice\x88\x01\x01B\x10\n" +
"\x0e_min_gas_price\"D\n" +
"\x1eGetPendingTransactionsResponse\x12\"\n" +
"\ftransactions\x18\x01 \x03(\fR\ftransactions\"\xfa\x01\n" +
"\x13CallContractRequest\x12\x12\n" +
"\x04from\x18\x01 \x01(\fR\x04from\x12\x0e\n" +
"\x02to\x18\x02 \x01(\fR\x02to\x12\x12\n" +
"\x04data\x18\x03 \x01(\fR\x04data\x12\x15\n" +
"\x03gas\x18\x04 \x01(\x04H\x00R\x03gas\x88\x01\x01\x12 \n" +
"\tgas_price\x18\x05 \x01(\x04H\x01R\bgasPrice\x88\x01\x01\x12\x19\n" +
"\x05value\x18\x06 \x01(\fH\x02R\x05value\x88\x01\x01\x12&\n" +
"\fblock_number\x18\a \x01(\x04H\x03R\vblockNumber\x88\x01\x01B\x06\n" +
"\x04_gasB\f\n" +
"\n" +
"_gas_priceB\b\n" +
"\x06_valueB\x0f\n" +
"\r_block_number\"\x82\x01\n" +
"\x14CallContractResponse\x12\x1f\n" +
"\vreturn_data\x18\x01 \x01(\fR\n" +
"returnData\x12\x19\n" +
"\bgas_used\x18\x02 \x01(\x04R\agasUsed\x12\x18\n" +
"\asuccess\x18\x03 \x01(\bR\asuccess\x12\x14\n" +
"\x05error\x18\x04 \x01(\tR\x05error2\x9f\x03\n" +
"\rTraderService\x12K\n" +
"\x0eSimulateBundle\x12\x1b.grpc.SimulateBundleRequest\x1a\x1c.grpc.SimulateBundleResponse\x12E\n" +
"\fSubmitBundle\x12\x19.grpc.SubmitBundleRequest\x1a\x1a.grpc.SubmitBundleResponse\x12N\n" +
"\x0fGetStorageBatch\x12\x1c.grpc.GetStorageBatchRequest\x1a\x1d.grpc.GetStorageBatchResponse\x12c\n" +
"\x16GetPendingTransactions\x12#.grpc.GetPendingTransactionsRequest\x1a$.grpc.GetPendingTransactionsResponse\x12E\n" +
"\fCallContract\x12\x19.grpc.CallContractRequest\x1a\x1a.grpc.CallContractResponseB*Z(github.com/ethereum/go-ethereum/api/grpcb\x06proto3"
var (
file_api_grpc_trader_proto_rawDescOnce sync.Once
file_api_grpc_trader_proto_rawDescData []byte
)
func file_api_grpc_trader_proto_rawDescGZIP() []byte {
file_api_grpc_trader_proto_rawDescOnce.Do(func() {
file_api_grpc_trader_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_grpc_trader_proto_rawDesc), len(file_api_grpc_trader_proto_rawDesc)))
})
return file_api_grpc_trader_proto_rawDescData
}
var file_api_grpc_trader_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_api_grpc_trader_proto_goTypes = []any{
(*SimulateBundleRequest)(nil), // 0: grpc.SimulateBundleRequest
(*SimulateBundleResponse)(nil), // 1: grpc.SimulateBundleResponse
(*TxSimulationResult)(nil), // 2: grpc.TxSimulationResult
(*SubmitBundleRequest)(nil), // 3: grpc.SubmitBundleRequest
(*SubmitBundleResponse)(nil), // 4: grpc.SubmitBundleResponse
(*GetStorageBatchRequest)(nil), // 5: grpc.GetStorageBatchRequest
(*GetStorageBatchResponse)(nil), // 6: grpc.GetStorageBatchResponse
(*GetPendingTransactionsRequest)(nil), // 7: grpc.GetPendingTransactionsRequest
(*GetPendingTransactionsResponse)(nil), // 8: grpc.GetPendingTransactionsResponse
(*CallContractRequest)(nil), // 9: grpc.CallContractRequest
(*CallContractResponse)(nil), // 10: grpc.CallContractResponse
}
var file_api_grpc_trader_proto_depIdxs = []int32{
2, // 0: grpc.SimulateBundleResponse.tx_results:type_name -> grpc.TxSimulationResult
0, // 1: grpc.TraderService.SimulateBundle:input_type -> grpc.SimulateBundleRequest
3, // 2: grpc.TraderService.SubmitBundle:input_type -> grpc.SubmitBundleRequest
5, // 3: grpc.TraderService.GetStorageBatch:input_type -> grpc.GetStorageBatchRequest
7, // 4: grpc.TraderService.GetPendingTransactions:input_type -> grpc.GetPendingTransactionsRequest
9, // 5: grpc.TraderService.CallContract:input_type -> grpc.CallContractRequest
1, // 6: grpc.TraderService.SimulateBundle:output_type -> grpc.SimulateBundleResponse
4, // 7: grpc.TraderService.SubmitBundle:output_type -> grpc.SubmitBundleResponse
6, // 8: grpc.TraderService.GetStorageBatch:output_type -> grpc.GetStorageBatchResponse
8, // 9: grpc.TraderService.GetPendingTransactions:output_type -> grpc.GetPendingTransactionsResponse
10, // 10: grpc.TraderService.CallContract:output_type -> grpc.CallContractResponse
6, // [6:11] is the sub-list for method output_type
1, // [1:6] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_api_grpc_trader_proto_init() }
func file_api_grpc_trader_proto_init() {
if File_api_grpc_trader_proto != nil {
return
}
file_api_grpc_trader_proto_msgTypes[0].OneofWrappers = []any{}
file_api_grpc_trader_proto_msgTypes[3].OneofWrappers = []any{}
file_api_grpc_trader_proto_msgTypes[5].OneofWrappers = []any{}
file_api_grpc_trader_proto_msgTypes[7].OneofWrappers = []any{}
file_api_grpc_trader_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_api_grpc_trader_proto_rawDesc), len(file_api_grpc_trader_proto_rawDesc)),
NumEnums: 0,
NumMessages: 11,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_api_grpc_trader_proto_goTypes,
DependencyIndexes: file_api_grpc_trader_proto_depIdxs,
MessageInfos: file_api_grpc_trader_proto_msgTypes,
}.Build()
File_api_grpc_trader_proto = out.File
file_api_grpc_trader_proto_goTypes = nil
file_api_grpc_trader_proto_depIdxs = nil
}

287
api/grpc/trader_grpc.pb.go Normal file
View file

@ -0,0 +1,287 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v6.33.1
// source: api/grpc/trader.proto
package grpc
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 (
TraderService_SimulateBundle_FullMethodName = "/grpc.TraderService/SimulateBundle"
TraderService_SubmitBundle_FullMethodName = "/grpc.TraderService/SubmitBundle"
TraderService_GetStorageBatch_FullMethodName = "/grpc.TraderService/GetStorageBatch"
TraderService_GetPendingTransactions_FullMethodName = "/grpc.TraderService/GetPendingTransactions"
TraderService_CallContract_FullMethodName = "/grpc.TraderService/CallContract"
)
// TraderServiceClient is the client API for TraderService 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.
//
// TraderService provides low-latency APIs for trading operations.
type TraderServiceClient interface {
// SimulateBundle simulates bundle execution and returns results
SimulateBundle(ctx context.Context, in *SimulateBundleRequest, opts ...grpc.CallOption) (*SimulateBundleResponse, error)
// SubmitBundle submits a bundle for inclusion in future blocks
SubmitBundle(ctx context.Context, in *SubmitBundleRequest, opts ...grpc.CallOption) (*SubmitBundleResponse, error)
// GetStorageBatch retrieves multiple storage slots in a single call
GetStorageBatch(ctx context.Context, in *GetStorageBatchRequest, opts ...grpc.CallOption) (*GetStorageBatchResponse, error)
// GetPendingTransactions returns currently pending transactions
GetPendingTransactions(ctx context.Context, in *GetPendingTransactionsRequest, opts ...grpc.CallOption) (*GetPendingTransactionsResponse, error)
// CallContract executes a contract call
CallContract(ctx context.Context, in *CallContractRequest, opts ...grpc.CallOption) (*CallContractResponse, error)
}
type traderServiceClient struct {
cc grpc.ClientConnInterface
}
func NewTraderServiceClient(cc grpc.ClientConnInterface) TraderServiceClient {
return &traderServiceClient{cc}
}
func (c *traderServiceClient) SimulateBundle(ctx context.Context, in *SimulateBundleRequest, opts ...grpc.CallOption) (*SimulateBundleResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SimulateBundleResponse)
err := c.cc.Invoke(ctx, TraderService_SimulateBundle_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *traderServiceClient) SubmitBundle(ctx context.Context, in *SubmitBundleRequest, opts ...grpc.CallOption) (*SubmitBundleResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SubmitBundleResponse)
err := c.cc.Invoke(ctx, TraderService_SubmitBundle_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *traderServiceClient) GetStorageBatch(ctx context.Context, in *GetStorageBatchRequest, opts ...grpc.CallOption) (*GetStorageBatchResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetStorageBatchResponse)
err := c.cc.Invoke(ctx, TraderService_GetStorageBatch_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *traderServiceClient) GetPendingTransactions(ctx context.Context, in *GetPendingTransactionsRequest, opts ...grpc.CallOption) (*GetPendingTransactionsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetPendingTransactionsResponse)
err := c.cc.Invoke(ctx, TraderService_GetPendingTransactions_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *traderServiceClient) CallContract(ctx context.Context, in *CallContractRequest, opts ...grpc.CallOption) (*CallContractResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CallContractResponse)
err := c.cc.Invoke(ctx, TraderService_CallContract_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// TraderServiceServer is the server API for TraderService service.
// All implementations must embed UnimplementedTraderServiceServer
// for forward compatibility.
//
// TraderService provides low-latency APIs for trading operations.
type TraderServiceServer interface {
// SimulateBundle simulates bundle execution and returns results
SimulateBundle(context.Context, *SimulateBundleRequest) (*SimulateBundleResponse, error)
// SubmitBundle submits a bundle for inclusion in future blocks
SubmitBundle(context.Context, *SubmitBundleRequest) (*SubmitBundleResponse, error)
// GetStorageBatch retrieves multiple storage slots in a single call
GetStorageBatch(context.Context, *GetStorageBatchRequest) (*GetStorageBatchResponse, error)
// GetPendingTransactions returns currently pending transactions
GetPendingTransactions(context.Context, *GetPendingTransactionsRequest) (*GetPendingTransactionsResponse, error)
// CallContract executes a contract call
CallContract(context.Context, *CallContractRequest) (*CallContractResponse, error)
mustEmbedUnimplementedTraderServiceServer()
}
// UnimplementedTraderServiceServer 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 UnimplementedTraderServiceServer struct{}
func (UnimplementedTraderServiceServer) SimulateBundle(context.Context, *SimulateBundleRequest) (*SimulateBundleResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SimulateBundle not implemented")
}
func (UnimplementedTraderServiceServer) SubmitBundle(context.Context, *SubmitBundleRequest) (*SubmitBundleResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SubmitBundle not implemented")
}
func (UnimplementedTraderServiceServer) GetStorageBatch(context.Context, *GetStorageBatchRequest) (*GetStorageBatchResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetStorageBatch not implemented")
}
func (UnimplementedTraderServiceServer) GetPendingTransactions(context.Context, *GetPendingTransactionsRequest) (*GetPendingTransactionsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPendingTransactions not implemented")
}
func (UnimplementedTraderServiceServer) CallContract(context.Context, *CallContractRequest) (*CallContractResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CallContract not implemented")
}
func (UnimplementedTraderServiceServer) mustEmbedUnimplementedTraderServiceServer() {}
func (UnimplementedTraderServiceServer) testEmbeddedByValue() {}
// UnsafeTraderServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to TraderServiceServer will
// result in compilation errors.
type UnsafeTraderServiceServer interface {
mustEmbedUnimplementedTraderServiceServer()
}
func RegisterTraderServiceServer(s grpc.ServiceRegistrar, srv TraderServiceServer) {
// If the following call pancis, it indicates UnimplementedTraderServiceServer 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(&TraderService_ServiceDesc, srv)
}
func _TraderService_SimulateBundle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SimulateBundleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TraderServiceServer).SimulateBundle(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TraderService_SimulateBundle_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TraderServiceServer).SimulateBundle(ctx, req.(*SimulateBundleRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TraderService_SubmitBundle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SubmitBundleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TraderServiceServer).SubmitBundle(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TraderService_SubmitBundle_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TraderServiceServer).SubmitBundle(ctx, req.(*SubmitBundleRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TraderService_GetStorageBatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetStorageBatchRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TraderServiceServer).GetStorageBatch(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TraderService_GetStorageBatch_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TraderServiceServer).GetStorageBatch(ctx, req.(*GetStorageBatchRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TraderService_GetPendingTransactions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetPendingTransactionsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TraderServiceServer).GetPendingTransactions(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TraderService_GetPendingTransactions_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TraderServiceServer).GetPendingTransactions(ctx, req.(*GetPendingTransactionsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TraderService_CallContract_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CallContractRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TraderServiceServer).CallContract(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TraderService_CallContract_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TraderServiceServer).CallContract(ctx, req.(*CallContractRequest))
}
return interceptor(ctx, in, info, handler)
}
// TraderService_ServiceDesc is the grpc.ServiceDesc for TraderService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var TraderService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "grpc.TraderService",
HandlerType: (*TraderServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "SimulateBundle",
Handler: _TraderService_SimulateBundle_Handler,
},
{
MethodName: "SubmitBundle",
Handler: _TraderService_SubmitBundle_Handler,
},
{
MethodName: "GetStorageBatch",
Handler: _TraderService_GetStorageBatch_Handler,
},
{
MethodName: "GetPendingTransactions",
Handler: _TraderService_GetPendingTransactions_Handler,
},
{
MethodName: "CallContract",
Handler: _TraderService_CallContract_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "api/grpc/trader.proto",
}

21
go.mod
View file

@ -33,7 +33,7 @@ require (
github.com/golang-jwt/jwt/v4 v4.5.2 github.com/golang-jwt/jwt/v4 v4.5.2
github.com/golang/snappy v1.0.0 github.com/golang/snappy v1.0.0
github.com/google/gofuzz v1.2.0 github.com/google/gofuzz v1.2.0
github.com/google/uuid v1.3.0 github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/graph-gophers/graphql-go v1.3.0 github.com/graph-gophers/graphql-go v1.3.0
github.com/hashicorp/go-bexpr v0.1.10 github.com/hashicorp/go-bexpr v0.1.10
@ -65,18 +65,21 @@ require (
github.com/urfave/cli/v2 v2.27.5 github.com/urfave/cli/v2 v2.27.5
go.uber.org/automaxprocs v1.5.2 go.uber.org/automaxprocs v1.5.2
go.uber.org/goleak v1.3.0 go.uber.org/goleak v1.3.0
golang.org/x/crypto v0.36.0 golang.org/x/crypto v0.43.0
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df
golang.org/x/sync v0.12.0 golang.org/x/sync v0.17.0
golang.org/x/sys v0.36.0 golang.org/x/sys v0.37.0
golang.org/x/text v0.23.0 golang.org/x/text v0.30.0
golang.org/x/time v0.9.0 golang.org/x/time v0.9.0
golang.org/x/tools v0.29.0 golang.org/x/tools v0.37.0
google.golang.org/protobuf v1.34.2 google.golang.org/grpc v1.77.0
google.golang.org/protobuf v1.36.10
gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
require google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba // indirect
require ( require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
@ -144,8 +147,8 @@ require (
github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect github.com/tklauser/numcpus v0.6.1 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
golang.org/x/mod v0.22.0 // indirect golang.org/x/mod v0.28.0 // indirect
golang.org/x/net v0.38.0 // indirect golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
) )

62
go.sum
View file

@ -140,6 +140,10 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
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-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
@ -174,16 +178,16 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U=
github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@ -370,6 +374,18 @@ github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBi
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
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/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME= go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME=
go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@ -382,16 +398,16 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/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.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/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.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/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -407,8 +423,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 h1:6/3JGEh1C88g7m+qzzTbl3A0FtsLguXieqofVLU/JAo=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -417,8 +433,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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.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/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -451,8 +467,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 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-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-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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -470,8 +486,8 @@ 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.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.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
@ -483,21 +499,27 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 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/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/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-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-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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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 v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 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 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/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=