From bf7d32c1a6030541ad61f50da366fbfa969b4502 Mon Sep 17 00:00:00 2001 From: Patryk Kalinowski Date: Fri, 17 Apr 2026 17:41:41 +0200 Subject: [PATCH 1/5] Add support for relayer EIP-7702 authorizations --- go.work.sum | 2 + lib/mock/relayer.mock.go | 65 +- relayer/proto/relayer.gen.go | 2634 +++++++++++++++++++++++++++++++--- relayer/relayer.go | 27 + transactions.go | 3 + 5 files changed, 2522 insertions(+), 209 deletions(-) diff --git a/go.work.sum b/go.work.sum index 570ec8e20..353520b2d 100644 --- a/go.work.sum +++ b/go.work.sum @@ -504,6 +504,7 @@ golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -756,6 +757,7 @@ golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= +golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= diff --git a/lib/mock/relayer.mock.go b/lib/mock/relayer.mock.go index de652db91..051d26faf 100644 --- a/lib/mock/relayer.mock.go +++ b/lib/mock/relayer.mock.go @@ -138,9 +138,9 @@ func (mr *RelayerMockRecorder) AdjustProjectBalance(ctx, projectId, amount, iden } // FeeOptions mocks base method. -func (m *Relayer) FeeOptions(ctx context.Context, wallet, to, data string, simulate *bool) ([]*proto.FeeOption, bool, *string, error) { +func (m *Relayer) FeeOptions(ctx context.Context, wallet, to, data string, simulate *bool, authorization *proto.EIP7702Authorization) ([]*proto.FeeOption, bool, *string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FeeOptions", ctx, wallet, to, data, simulate) + ret := m.ctrl.Call(m, "FeeOptions", ctx, wallet, to, data, simulate, authorization) ret0, _ := ret[0].([]*proto.FeeOption) ret1, _ := ret[1].(bool) ret2, _ := ret[2].(*string) @@ -149,15 +149,15 @@ func (m *Relayer) FeeOptions(ctx context.Context, wallet, to, data string, simul } // FeeOptions indicates an expected call of FeeOptions. -func (mr *RelayerMockRecorder) FeeOptions(ctx, wallet, to, data, simulate any) *gomock.Call { +func (mr *RelayerMockRecorder) FeeOptions(ctx, wallet, to, data, simulate, authorization any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeeOptions", reflect.TypeOf((*Relayer)(nil).FeeOptions), ctx, wallet, to, data, simulate) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeeOptions", reflect.TypeOf((*Relayer)(nil).FeeOptions), ctx, wallet, to, data, simulate, authorization) } // FeeOptionsWithBridgeGas mocks base method. -func (m *Relayer) FeeOptionsWithBridgeGas(ctx context.Context, wallet, to, data string, simulate *bool, bridgeGas string) ([]*proto.FeeOption, bool, *string, error) { +func (m *Relayer) FeeOptionsWithBridgeGas(ctx context.Context, wallet, to, data string, simulate *bool, bridgeGas string, authorization *proto.EIP7702Authorization) ([]*proto.FeeOption, bool, *string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FeeOptionsWithBridgeGas", ctx, wallet, to, data, simulate, bridgeGas) + ret := m.ctrl.Call(m, "FeeOptionsWithBridgeGas", ctx, wallet, to, data, simulate, bridgeGas, authorization) ret0, _ := ret[0].([]*proto.FeeOption) ret1, _ := ret[1].(bool) ret2, _ := ret[2].(*string) @@ -166,9 +166,9 @@ func (m *Relayer) FeeOptionsWithBridgeGas(ctx context.Context, wallet, to, data } // FeeOptionsWithBridgeGas indicates an expected call of FeeOptionsWithBridgeGas. -func (mr *RelayerMockRecorder) FeeOptionsWithBridgeGas(ctx, wallet, to, data, simulate, bridgeGas any) *gomock.Call { +func (mr *RelayerMockRecorder) FeeOptionsWithBridgeGas(ctx, wallet, to, data, simulate, bridgeGas, authorization any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeeOptionsWithBridgeGas", reflect.TypeOf((*Relayer)(nil).FeeOptionsWithBridgeGas), ctx, wallet, to, data, simulate, bridgeGas) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeeOptionsWithBridgeGas", reflect.TypeOf((*Relayer)(nil).FeeOptionsWithBridgeGas), ctx, wallet, to, data, simulate, bridgeGas, authorization) } // FeeTokens mocks base method. @@ -432,22 +432,6 @@ func (mr *RelayerMockRecorder) NextGasTankBalanceAdjustmentNonce(ctx, id any) *g return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NextGasTankBalanceAdjustmentNonce", reflect.TypeOf((*Relayer)(nil).NextGasTankBalanceAdjustmentNonce), ctx, id) } -// PendingTransactions mocks base method. -func (m *Relayer) PendingTransactions(ctx context.Context, page *proto.Page) (*proto.Page, []*proto.Transaction, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PendingTransactions", ctx, page) - ret0, _ := ret[0].(*proto.Page) - ret1, _ := ret[1].([]*proto.Transaction) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// PendingTransactions indicates an expected call of PendingTransactions. -func (mr *RelayerMockRecorder) PendingTransactions(ctx, page any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PendingTransactions", reflect.TypeOf((*Relayer)(nil).PendingTransactions), ctx, page) -} - // Ping mocks base method. func (m *Relayer) Ping(ctx context.Context) (bool, error) { m.ctrl.T.Helper() @@ -493,19 +477,18 @@ func (mr *RelayerMockRecorder) RemoveGasSponsor(ctx, projectId, id any) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveGasSponsor", reflect.TypeOf((*Relayer)(nil).RemoveGasSponsor), ctx, projectId, id) } -// ResetSender mocks base method. -func (m *Relayer) ResetSender(ctx context.Context, sender int) (uint64, error) { +// RepairSender mocks base method. +func (m *Relayer) RepairSender(ctx context.Context, sender int, nonce uint64, operation proto.RepairOperation) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ResetSender", ctx, sender) - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret := m.ctrl.Call(m, "RepairSender", ctx, sender, nonce, operation) + ret0, _ := ret[0].(error) + return ret0 } -// ResetSender indicates an expected call of ResetSender. -func (mr *RelayerMockRecorder) ResetSender(ctx, sender any) *gomock.Call { +// RepairSender indicates an expected call of RepairSender. +func (mr *RelayerMockRecorder) RepairSender(ctx, sender, nonce, operation any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetSender", reflect.TypeOf((*Relayer)(nil).ResetSender), ctx, sender) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RepairSender", reflect.TypeOf((*Relayer)(nil).RepairSender), ctx, sender, nonce, operation) } // RuntimeStatus mocks base method. @@ -555,22 +538,6 @@ func (mr *RelayerMockRecorder) SendMetaTxnWithBridgeGas(ctx, call, quote, projec return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMetaTxnWithBridgeGas", reflect.TypeOf((*Relayer)(nil).SendMetaTxnWithBridgeGas), ctx, call, quote, projectID, bridgeGas, preconditions) } -// SentTransactions mocks base method. -func (m *Relayer) SentTransactions(ctx context.Context, filter *proto.SentTransactionsFilter, page *proto.Page) (*proto.Page, []*proto.Transaction, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SentTransactions", ctx, filter, page) - ret0, _ := ret[0].(*proto.Page) - ret1, _ := ret[1].([]*proto.Transaction) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// SentTransactions indicates an expected call of SentTransactions. -func (mr *RelayerMockRecorder) SentTransactions(ctx, filter, page any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SentTransactions", reflect.TypeOf((*Relayer)(nil).SentTransactions), ctx, filter, page) -} - // Simulate mocks base method. func (m *Relayer) Simulate(ctx context.Context, wallet, transactions string) ([]*proto.SimulateResult, error) { m.ctrl.T.Helper() diff --git a/relayer/proto/relayer.gen.go b/relayer/proto/relayer.gen.go index 9dc744716..43b83c59a 100644 --- a/relayer/proto/relayer.gen.go +++ b/relayer/proto/relayer.gen.go @@ -1,8 +1,8 @@ -// sequence-relayer v0.4.1 fb3b85b73856f333cbba355861050f23c7b2af48 +// sequence-relayer v0.4.1 5f4ba9cfea3872be7073167aaef21a647ec36e52 // -- -// Code generated by webrpc-gen@v0.31.2 with golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.32.2 with golang generator. DO NOT EDIT. // -// webrpc-gen -schema=relayer.ridl -target=golang -pkg=proto -client -out=./clients/relayer.gen.go +// webrpc-gen -schema=relayer.ridl -target=golang -pkg=proto -server -client -out=./relayer.gen.go package proto import ( @@ -35,7 +35,7 @@ func WebRPCSchemaVersion() string { // Schema hash generated from your RIDL schema func WebRPCSchemaHash() string { - return "fb3b85b73856f333cbba355861050f23c7b2af48" + return "5f4ba9cfea3872be7073167aaef21a647ec36e52" } // @@ -68,12 +68,12 @@ type RelayerClient interface { // TODO: deprecated, to be removed by https://github.com/0xsequence/stack/pull/356 at a later date UpdateMetaTxnGasLimits(ctx context.Context, walletAddress string, walletConfig interface{}, payload string) (string, error) FeeTokens(ctx context.Context) (bool, []*FeeToken, string, error) - FeeOptions(ctx context.Context, wallet string, to string, data string, simulate *bool) ([]*FeeOption, bool, *string, error) + FeeOptions(ctx context.Context, wallet string, to string, data string, simulate *bool, authorization *EIP7702Authorization) ([]*FeeOption, bool, *string, error) // Bridge gas endpoints for S2S calls // Used for bridge fees (e.g., LayerZero messaging fees) that require msg.value to be fronted at runtime. // bridgeGas will be included in fee calculation so the relayer gets reimbursed. SendMetaTxnWithBridgeGas(ctx context.Context, call *MetaTxn, quote *string, projectID *uint64, bridgeGas string, preconditions []*TransactionPrecondition) (bool, string, error) - FeeOptionsWithBridgeGas(ctx context.Context, wallet string, to string, data string, simulate *bool, bridgeGas string) ([]*FeeOption, bool, *string, error) + FeeOptionsWithBridgeGas(ctx context.Context, wallet string, to string, data string, simulate *bool, bridgeGas string, authorization *EIP7702Authorization) ([]*FeeOption, bool, *string, error) // TODO: deprecated, to be removed by https://github.com/0xsequence/stack/pull/356 at a later date GetMetaTxnNetworkFeeOptions(ctx context.Context, walletConfig interface{}, payload string) ([]*FeeOption, error) // @@ -81,14 +81,83 @@ type RelayerClient interface { // StartSender(ctx context.Context, sender int) error StopSender(ctx context.Context, sender int) error - ResetSender(ctx context.Context, sender int) (uint64, error) + RepairSender(ctx context.Context, sender int, nonce uint64, operation RepairOperation) error + GetMetaTransactions(ctx context.Context, projectId uint64, page *Page) (*Page, []*MetaTxnLog, error) + GetTransactionCost(ctx context.Context, projectId uint64, from time.Time, to time.Time) (float64, error) + // Legacy Gas Tank + GetGasTank(ctx context.Context, id uint64) (*GasTank, error) + AddGasTank(ctx context.Context, name string, feeMarkupFactor float64, unlimited *bool) (bool, *GasTank, error) + UpdateGasTank(ctx context.Context, id uint64, name *string, feeMarkupFactor *float64, unlimited *bool) (bool, *GasTank, error) + // Legacy Gas Adjustment + NextGasTankBalanceAdjustmentNonce(ctx context.Context, id uint64) (uint64, error) + AdjustGasTankBalance(ctx context.Context, id uint64, nonce uint64, amount float64) (bool, *GasTankBalanceAdjustment, error) + GetGasTankBalanceAdjustment(ctx context.Context, id uint64, nonce uint64) (*GasTankBalanceAdjustment, error) + ListGasTankBalanceAdjustments(ctx context.Context, id uint64, page *Page) (*Page, []*GasTankBalanceAdjustment, error) + // Project-Level Gas Sponsorship + ListGasSponsors(ctx context.Context, projectId uint64, page *Page) (*Page, []*GasSponsor, error) + GetGasSponsor(ctx context.Context, projectId uint64, id uint64) (*GasSponsor, error) + AddGasSponsor(ctx context.Context, projectId uint64, address string, name *string, active *bool) (bool, *GasSponsor, error) + UpdateGasSponsor(ctx context.Context, projectId uint64, id uint64, name *string, active *bool) (bool, *GasSponsor, error) + RemoveGasSponsor(ctx context.Context, projectId uint64, id uint64) (bool, error) + // Ecosystem-level Gas Sponsorship + ListEcosystemGasSponsors(ctx context.Context, ecosystemId uint64, page *Page) (*Page, []*GasSponsor, error) + GetEcosystemGasSponsor(ctx context.Context, ecosystemId uint64, id uint64) (*GasSponsor, error) + AddEcosystemGasSponsor(ctx context.Context, ecosystemId uint64, address string, name *string, active *bool) (bool, *GasSponsor, error) + UpdateEcosystemGasSponsor(ctx context.Context, ecosystemId uint64, id uint64, name *string, active *bool) (bool, *GasSponsor, error) + RemoveEcosystemGasSponsor(ctx context.Context, ecosystemId uint64, id uint64) (bool, error) + // Gas Sponsor Lookup + AddressGasSponsors(ctx context.Context, address string, page *Page) (*Page, []*GasSponsor, error) + // Project Balance + GetProjectBalance(ctx context.Context, projectId uint64) (float64, error) + AdjustProjectBalance(ctx context.Context, projectId uint64, amount float64, identifier string) (float64, error) +} + +// +// Server interface +// + +type RelayerServer interface { + Ping(ctx context.Context) (bool, error) + Version(ctx context.Context) (*Version, error) + RuntimeStatus(ctx context.Context) (*RuntimeStatus, error) + GetSequenceContext(ctx context.Context) (*SequenceContext, error) + GetChainID(ctx context.Context) (uint64, error) + // + // Transactions + // + // TODO (future): rename this to just, 'SendTransaction(txn: MetaTransaction)' or 'SendTransaction(txn: SignedTransaction)', or something.. + // Project ID is only used by service and admin calls. Other clients must have projectID passed via the context + // TODO: rename return txnHash: string to metaTxnID: string + SendMetaTxn(ctx context.Context, call *MetaTxn, quote *string, projectID *uint64, preconditions []*TransactionPrecondition) (bool, string, error) + GetMetaTxnNonce(ctx context.Context, walletContractAddress string, space *string) (string, error) + // TODO: one day, make GetMetaTxnReceipt respond immediately with receipt or not + // and add WaitTransactionReceipt method, which will block and wait, similar to how GetMetaTxnReceipt + // is implemented now. + // For backwards compat, we can leave the current GetMetaTxnReceipt how it is, an deprecate it, and introduce + // new, GetTransactionReceipt and WaitTransactionReceipt methods + // we can also accept metaTxnId and txnHash .. so can take either or.. I wonder if ERC-4337 has any convention on this? + GetMetaTxnReceipt(ctx context.Context, metaTxID string) (*MetaTxnReceipt, error) + Simulate(ctx context.Context, wallet string, transactions string) ([]*SimulateResult, error) + SimulateV3(ctx context.Context, wallet string, calls string) ([]*SimulateV3Result, error) + // TODO: deprecated, to be removed by https://github.com/0xsequence/stack/pull/356 at a later date + UpdateMetaTxnGasLimits(ctx context.Context, walletAddress string, walletConfig interface{}, payload string) (string, error) + FeeTokens(ctx context.Context) (bool, []*FeeToken, string, error) + FeeOptions(ctx context.Context, wallet string, to string, data string, simulate *bool, authorization *EIP7702Authorization) ([]*FeeOption, bool, *string, error) + // Bridge gas endpoints for S2S calls + // Used for bridge fees (e.g., LayerZero messaging fees) that require msg.value to be fronted at runtime. + // bridgeGas will be included in fee calculation so the relayer gets reimbursed. + SendMetaTxnWithBridgeGas(ctx context.Context, call *MetaTxn, quote *string, projectID *uint64, bridgeGas string, preconditions []*TransactionPrecondition) (bool, string, error) + FeeOptionsWithBridgeGas(ctx context.Context, wallet string, to string, data string, simulate *bool, bridgeGas string, authorization *EIP7702Authorization) ([]*FeeOption, bool, *string, error) + // TODO: deprecated, to be removed by https://github.com/0xsequence/stack/pull/356 at a later date + GetMetaTxnNetworkFeeOptions(ctx context.Context, walletConfig interface{}, payload string) ([]*FeeOption, error) + // + // Sender administration + // + StartSender(ctx context.Context, sender int) error + StopSender(ctx context.Context, sender int) error + RepairSender(ctx context.Context, sender int, nonce uint64, operation RepairOperation) error GetMetaTransactions(ctx context.Context, projectId uint64, page *Page) (*Page, []*MetaTxnLog, error) GetTransactionCost(ctx context.Context, projectId uint64, from time.Time, to time.Time) (float64, error) - // Sent transactions from an account. If filter is omitted then it will return all transactions. - SentTransactions(ctx context.Context, filter *SentTransactionsFilter, page *Page) (*Page, []*Transaction, error) - // Pending transactions waiting to be mined for an account. This endpoint is just a sugar of `SentTransactions` - // with the filter set to pending: true. - PendingTransactions(ctx context.Context, page *Page) (*Page, []*Transaction, error) // Legacy Gas Tank GetGasTank(ctx context.Context, id uint64) (*GasTank, error) AddGasTank(ctx context.Context, name string, feeMarkupFactor float64, unlimited *bool) (bool, *GasTank, error) @@ -121,6 +190,51 @@ type RelayerClient interface { // Schema types // +type RepairOperation int + +const ( + RepairOperation_SKIP RepairOperation = 0 + RepairOperation_REQUEUE RepairOperation = 1 + RepairOperation_DROP RepairOperation = 2 +) + +var RepairOperation_name = map[int]string{ + 0: "SKIP", + 1: "REQUEUE", + 2: "DROP", +} + +var RepairOperation_value = map[string]int{ + "SKIP": 0, + "REQUEUE": 1, + "DROP": 2, +} + +func (x RepairOperation) String() string { + return RepairOperation_name[int(x)] +} + +func (x RepairOperation) MarshalText() ([]byte, error) { + return []byte(RepairOperation_name[int(x)]), nil +} + +func (x *RepairOperation) UnmarshalText(b []byte) error { + *x = RepairOperation(RepairOperation_value[string(b)]) + return nil +} + +func (x *RepairOperation) Is(values ...RepairOperation) bool { + if x == nil { + return false + } + for _, v := range values { + if *x == v { + return true + } + } + return false +} + type ETHTxnStatus uint const ( @@ -395,11 +509,34 @@ type RuntimeStatus struct { } type SenderStatus struct { - Index uint32 `json:"index"` - Address string `json:"address"` - EtherBalance float64 `json:"etherBalance"` - Enabled bool `json:"enabled"` - Active bool `json:"active"` + Index uint32 `json:"index"` + Address string `json:"address"` + EtherBalance float64 `json:"etherBalance"` + Enabled bool `json:"enabled"` + Active bool `json:"active"` + Nonce *NonceStatus `json:"nonce,omitempty"` + Current *CurrentStatus `json:"current,omitempty"` +} + +type NonceStatus struct { + Chain uint64 `json:"chain"` + Mempool uint64 `json:"mempool"` +} + +type CurrentStatus struct { + Transaction string `json:"transaction"` + First *TransactionStatus `json:"first"` + Latest *TransactionStatus `json:"latest,omitempty"` +} + +type TransactionStatus struct { + Transaction prototyp.Hash `json:"transaction"` + Gas uint64 `json:"gas"` + GasPrice prototyp.BigInt `json:"gasPrice"` + PriorityFee prototyp.BigInt `json:"priorityFee"` + Time time.Time `json:"time"` + Age string `json:"age"` + Error *string `json:"error,omitempty"` } type RuntimeChecks struct { @@ -465,7 +602,17 @@ type MetaTxn struct { // TODO (later): rename this to `to: string` Contract string `json:"contract" db:"to_address"` // TODO: rename to 'execdata' - Input string `json:"input" db:"tx_data"` + Input string `json:"input" db:"tx_data"` + Authorization *EIP7702Authorization `json:"authorization"` +} + +type EIP7702Authorization struct { + ChainId uint64 `json:"chainId"` + Implementation string `json:"implementation"` + Nonce uint64 `json:"nonce"` + YParity uint64 `json:"yParity"` + R prototyp.BigInt `json:"r"` + S prototyp.BigInt `json:"s"` } // TODO: review @@ -569,11 +716,6 @@ type TxnLogTransfer struct { Amounts []prototyp.BigInt `json:"amounts"` } -type SentTransactionsFilter struct { - Pending *bool `json:"pending"` - Failed *bool `json:"failed"` -} - type SimulateResult struct { Executed bool `json:"executed"` Succeeded bool `json:"succeeded"` @@ -632,12 +774,12 @@ const RelayerPathPrefix = "/rpc/Relayer/" type relayerClient struct { client HTTPClient - urls [43]string + urls [41]string } func NewRelayerClient(addr string, client HTTPClient) RelayerClient { prefix := urlBase(addr) + RelayerPathPrefix - urls := [43]string{ + urls := [41]string{ prefix + "Ping", prefix + "Version", prefix + "RuntimeStatus", @@ -656,11 +798,9 @@ func NewRelayerClient(addr string, client HTTPClient) RelayerClient { prefix + "GetMetaTxnNetworkFeeOptions", prefix + "StartSender", prefix + "StopSender", - prefix + "ResetSender", + prefix + "RepairSender", prefix + "GetMetaTransactions", prefix + "GetTransactionCost", - prefix + "SentTransactions", - prefix + "PendingTransactions", prefix + "GetGasTank", prefix + "AddGasTank", prefix + "UpdateGasTank", @@ -909,13 +1049,14 @@ func (c *relayerClient) FeeTokens(ctx context.Context) (bool, []*FeeToken, strin return out.Ret0, out.Ret1, out.Ret2, err } -func (c *relayerClient) FeeOptions(ctx context.Context, wallet string, to string, data string, simulate *bool) ([]*FeeOption, bool, *string, error) { +func (c *relayerClient) FeeOptions(ctx context.Context, wallet string, to string, data string, simulate *bool, authorization *EIP7702Authorization) ([]*FeeOption, bool, *string, error) { in := struct { - Arg0 string `json:"wallet"` - Arg1 string `json:"to"` - Arg2 string `json:"data"` - Arg3 *bool `json:"simulate"` - }{wallet, to, data, simulate} + Arg0 string `json:"wallet"` + Arg1 string `json:"to"` + Arg2 string `json:"data"` + Arg3 *bool `json:"simulate"` + Arg4 *EIP7702Authorization `json:"authorization"` + }{wallet, to, data, simulate, authorization} out := struct { Ret0 []*FeeOption `json:"options"` Ret1 bool `json:"sponsored"` @@ -957,14 +1098,15 @@ func (c *relayerClient) SendMetaTxnWithBridgeGas(ctx context.Context, call *Meta return out.Ret0, out.Ret1, err } -func (c *relayerClient) FeeOptionsWithBridgeGas(ctx context.Context, wallet string, to string, data string, simulate *bool, bridgeGas string) ([]*FeeOption, bool, *string, error) { +func (c *relayerClient) FeeOptionsWithBridgeGas(ctx context.Context, wallet string, to string, data string, simulate *bool, bridgeGas string, authorization *EIP7702Authorization) ([]*FeeOption, bool, *string, error) { in := struct { - Arg0 string `json:"wallet"` - Arg1 string `json:"to"` - Arg2 string `json:"data"` - Arg3 *bool `json:"simulate"` - Arg4 string `json:"bridgeGas"` - }{wallet, to, data, simulate, bridgeGas} + Arg0 string `json:"wallet"` + Arg1 string `json:"to"` + Arg2 string `json:"data"` + Arg3 *bool `json:"simulate"` + Arg4 string `json:"bridgeGas"` + Arg5 *EIP7702Authorization `json:"authorization"` + }{wallet, to, data, simulate, bridgeGas, authorization} out := struct { Ret0 []*FeeOption `json:"options"` Ret1 bool `json:"sponsored"` @@ -1034,15 +1176,14 @@ func (c *relayerClient) StopSender(ctx context.Context, sender int) error { return err } -func (c *relayerClient) ResetSender(ctx context.Context, sender int) (uint64, error) { +func (c *relayerClient) RepairSender(ctx context.Context, sender int, nonce uint64, operation RepairOperation) error { in := struct { - Arg0 int `json:"sender"` - }{sender} - out := struct { - Ret0 uint64 `json:"deleted"` - }{} + Arg0 int `json:"sender"` + Arg1 uint64 `json:"nonce"` + Arg2 RepairOperation `json:"operation"` + }{sender, nonce, operation} - resp, err := doHTTPRequest(ctx, c.client, c.urls[18], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[18], in, nil) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1050,7 +1191,7 @@ func (c *relayerClient) ResetSender(ctx context.Context, sender int) (uint64, er } } - return out.Ret0, err + return err } func (c *relayerClient) GetMetaTransactions(ctx context.Context, projectId uint64, page *Page) (*Page, []*MetaTxnLog, error) { @@ -1095,47 +1236,6 @@ func (c *relayerClient) GetTransactionCost(ctx context.Context, projectId uint64 return out.Ret0, err } -func (c *relayerClient) SentTransactions(ctx context.Context, filter *SentTransactionsFilter, page *Page) (*Page, []*Transaction, error) { - in := struct { - Arg0 *SentTransactionsFilter `json:"filter"` - Arg1 *Page `json:"page"` - }{filter, page} - out := struct { - Ret0 *Page `json:"page"` - Ret1 []*Transaction `json:"transactions"` - }{} - - resp, err := doHTTPRequest(ctx, c.client, c.urls[21], in, &out) - if resp != nil { - cerr := resp.Body.Close() - if err == nil && cerr != nil { - err = ErrWebrpcRequestFailed.WithCausef("failed to close response body: %w", cerr) - } - } - - return out.Ret0, out.Ret1, err -} - -func (c *relayerClient) PendingTransactions(ctx context.Context, page *Page) (*Page, []*Transaction, error) { - in := struct { - Arg0 *Page `json:"page"` - }{page} - out := struct { - Ret0 *Page `json:"page"` - Ret1 []*Transaction `json:"transactions"` - }{} - - resp, err := doHTTPRequest(ctx, c.client, c.urls[22], in, &out) - if resp != nil { - cerr := resp.Body.Close() - if err == nil && cerr != nil { - err = ErrWebrpcRequestFailed.WithCausef("failed to close response body: %w", cerr) - } - } - - return out.Ret0, out.Ret1, err -} - func (c *relayerClient) GetGasTank(ctx context.Context, id uint64) (*GasTank, error) { in := struct { Arg0 uint64 `json:"id"` @@ -1144,7 +1244,7 @@ func (c *relayerClient) GetGasTank(ctx context.Context, id uint64) (*GasTank, er Ret0 *GasTank `json:"gasTank"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[23], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[21], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1166,7 +1266,7 @@ func (c *relayerClient) AddGasTank(ctx context.Context, name string, feeMarkupFa Ret1 *GasTank `json:"gasTank"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[24], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[22], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1189,7 +1289,7 @@ func (c *relayerClient) UpdateGasTank(ctx context.Context, id uint64, name *stri Ret1 *GasTank `json:"gasTank"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[25], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[23], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1208,7 +1308,7 @@ func (c *relayerClient) NextGasTankBalanceAdjustmentNonce(ctx context.Context, i Ret0 uint64 `json:"nonce"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[26], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[24], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1230,7 +1330,7 @@ func (c *relayerClient) AdjustGasTankBalance(ctx context.Context, id uint64, non Ret1 *GasTankBalanceAdjustment `json:"adjustment"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[27], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[25], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1250,7 +1350,7 @@ func (c *relayerClient) GetGasTankBalanceAdjustment(ctx context.Context, id uint Ret0 *GasTankBalanceAdjustment `json:"adjustment"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[28], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[26], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1271,7 +1371,7 @@ func (c *relayerClient) ListGasTankBalanceAdjustments(ctx context.Context, id ui Ret1 []*GasTankBalanceAdjustment `json:"adjustments"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[29], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[27], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1292,7 +1392,7 @@ func (c *relayerClient) ListGasSponsors(ctx context.Context, projectId uint64, p Ret1 []*GasSponsor `json:"gasSponsors"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[30], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[28], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1312,7 +1412,7 @@ func (c *relayerClient) GetGasSponsor(ctx context.Context, projectId uint64, id Ret0 *GasSponsor `json:"gasSponsor"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[31], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[29], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1335,7 +1435,7 @@ func (c *relayerClient) AddGasSponsor(ctx context.Context, projectId uint64, add Ret1 *GasSponsor `json:"gasSponsor"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[32], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[30], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1358,7 +1458,7 @@ func (c *relayerClient) UpdateGasSponsor(ctx context.Context, projectId uint64, Ret1 *GasSponsor `json:"gasSponsor"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[33], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[31], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1378,7 +1478,7 @@ func (c *relayerClient) RemoveGasSponsor(ctx context.Context, projectId uint64, Ret0 bool `json:"status"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[34], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[32], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1399,7 +1499,7 @@ func (c *relayerClient) ListEcosystemGasSponsors(ctx context.Context, ecosystemI Ret1 []*GasSponsor `json:"gasSponsors"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[35], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[33], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1419,7 +1519,7 @@ func (c *relayerClient) GetEcosystemGasSponsor(ctx context.Context, ecosystemId Ret0 *GasSponsor `json:"gasSponsor"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[36], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[34], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1442,7 +1542,7 @@ func (c *relayerClient) AddEcosystemGasSponsor(ctx context.Context, ecosystemId Ret1 *GasSponsor `json:"gasSponsor"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[37], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[35], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1465,7 +1565,7 @@ func (c *relayerClient) UpdateEcosystemGasSponsor(ctx context.Context, ecosystem Ret1 *GasSponsor `json:"gasSponsor"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[38], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[36], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1485,7 +1585,7 @@ func (c *relayerClient) RemoveEcosystemGasSponsor(ctx context.Context, ecosystem Ret0 bool `json:"status"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[39], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[37], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1506,7 +1606,7 @@ func (c *relayerClient) AddressGasSponsors(ctx context.Context, address string, Ret1 []*GasSponsor `json:"gasSponsors"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[40], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[38], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1525,7 +1625,7 @@ func (c *relayerClient) GetProjectBalance(ctx context.Context, projectId uint64) Ret0 float64 `json:"balance"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[41], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[39], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1546,7 +1646,7 @@ func (c *relayerClient) AdjustProjectBalance(ctx context.Context, projectId uint Ret0 float64 `json:"balance"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[42], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[40], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1558,79 +1658,2266 @@ func (c *relayerClient) AdjustProjectBalance(ctx context.Context, projectId uint } // -// Client helpers +// Server // -// HTTPClient is the interface used by generated clients to send HTTP requests. -// It is fulfilled by *(net/http).Client, which is sufficient for most users. -// Users can provide their own implementation for special retry policies. -type HTTPClient interface { - Do(req *http.Request) (*http.Response, error) +type WebRPCServer interface { + http.Handler } -// urlBase helps ensure that addr specifies a scheme. If it is unparsable -// as a URL, it returns addr unchanged. -func urlBase(addr string) string { - // If the addr specifies a scheme, use it. If not, default to - // http. If url.Parse fails on it, return it unchanged. - url, err := url.Parse(addr) - if err != nil { - return addr - } - if url.Scheme == "" { - url.Scheme = "http" +type relayerService struct { + RelayerServer + OnError func(r *http.Request, rpcErr *WebRPCError) + OnRequest func(w http.ResponseWriter, r *http.Request) error +} + +func NewRelayerServer(svc RelayerServer) *relayerService { + return &relayerService{ + RelayerServer: svc, } - return url.String() } -// newRequest makes an http.Request from a client, adding common headers. -func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { - req, err := http.NewRequestWithContext(ctx, "POST", url, reqBody) - if err != nil { - return nil, err +func (s *relayerService) ServeHTTP(w http.ResponseWriter, r *http.Request) { + defer func() { + // In case of a panic, serve a HTTP 500 error and then panic. + if rr := recover(); rr != nil { + s.sendErrorJSON(w, r, ErrWebrpcServerPanic.WithCausef("%v", rr)) + panic(rr) + } + }() + + w.Header().Set(WebrpcHeader, WebrpcHeaderValue) + + ctx := r.Context() + ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) + ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) + ctx = context.WithValue(ctx, ServiceNameCtxKey, "Relayer") + + r = r.WithContext(ctx) + + var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) + switch r.URL.Path { + case "/rpc/Relayer/Ping": + handler = s.servePingJSON + case "/rpc/Relayer/Version": + handler = s.serveVersionJSON + case "/rpc/Relayer/RuntimeStatus": + handler = s.serveRuntimeStatusJSON + case "/rpc/Relayer/GetSequenceContext": + handler = s.serveGetSequenceContextJSON + case "/rpc/Relayer/GetChainID": + handler = s.serveGetChainIDJSON + case "/rpc/Relayer/SendMetaTxn": + handler = s.serveSendMetaTxnJSON + case "/rpc/Relayer/GetMetaTxnNonce": + handler = s.serveGetMetaTxnNonceJSON + case "/rpc/Relayer/GetMetaTxnReceipt": + handler = s.serveGetMetaTxnReceiptJSON + case "/rpc/Relayer/Simulate": + handler = s.serveSimulateJSON + case "/rpc/Relayer/SimulateV3": + handler = s.serveSimulateV3JSON + case "/rpc/Relayer/UpdateMetaTxnGasLimits": + handler = s.serveUpdateMetaTxnGasLimitsJSON + case "/rpc/Relayer/FeeTokens": + handler = s.serveFeeTokensJSON + case "/rpc/Relayer/FeeOptions": + handler = s.serveFeeOptionsJSON + case "/rpc/Relayer/SendMetaTxnWithBridgeGas": + handler = s.serveSendMetaTxnWithBridgeGasJSON + case "/rpc/Relayer/FeeOptionsWithBridgeGas": + handler = s.serveFeeOptionsWithBridgeGasJSON + case "/rpc/Relayer/GetMetaTxnNetworkFeeOptions": + handler = s.serveGetMetaTxnNetworkFeeOptionsJSON + case "/rpc/Relayer/StartSender": + handler = s.serveStartSenderJSON + case "/rpc/Relayer/StopSender": + handler = s.serveStopSenderJSON + case "/rpc/Relayer/RepairSender": + handler = s.serveRepairSenderJSON + case "/rpc/Relayer/GetMetaTransactions": + handler = s.serveGetMetaTransactionsJSON + case "/rpc/Relayer/GetTransactionCost": + handler = s.serveGetTransactionCostJSON + case "/rpc/Relayer/GetGasTank": + handler = s.serveGetGasTankJSON + case "/rpc/Relayer/AddGasTank": + handler = s.serveAddGasTankJSON + case "/rpc/Relayer/UpdateGasTank": + handler = s.serveUpdateGasTankJSON + case "/rpc/Relayer/NextGasTankBalanceAdjustmentNonce": + handler = s.serveNextGasTankBalanceAdjustmentNonceJSON + case "/rpc/Relayer/AdjustGasTankBalance": + handler = s.serveAdjustGasTankBalanceJSON + case "/rpc/Relayer/GetGasTankBalanceAdjustment": + handler = s.serveGetGasTankBalanceAdjustmentJSON + case "/rpc/Relayer/ListGasTankBalanceAdjustments": + handler = s.serveListGasTankBalanceAdjustmentsJSON + case "/rpc/Relayer/ListGasSponsors": + handler = s.serveListGasSponsorsJSON + case "/rpc/Relayer/GetGasSponsor": + handler = s.serveGetGasSponsorJSON + case "/rpc/Relayer/AddGasSponsor": + handler = s.serveAddGasSponsorJSON + case "/rpc/Relayer/UpdateGasSponsor": + handler = s.serveUpdateGasSponsorJSON + case "/rpc/Relayer/RemoveGasSponsor": + handler = s.serveRemoveGasSponsorJSON + case "/rpc/Relayer/ListEcosystemGasSponsors": + handler = s.serveListEcosystemGasSponsorsJSON + case "/rpc/Relayer/GetEcosystemGasSponsor": + handler = s.serveGetEcosystemGasSponsorJSON + case "/rpc/Relayer/AddEcosystemGasSponsor": + handler = s.serveAddEcosystemGasSponsorJSON + case "/rpc/Relayer/UpdateEcosystemGasSponsor": + handler = s.serveUpdateEcosystemGasSponsorJSON + case "/rpc/Relayer/RemoveEcosystemGasSponsor": + handler = s.serveRemoveEcosystemGasSponsorJSON + case "/rpc/Relayer/AddressGasSponsors": + handler = s.serveAddressGasSponsorsJSON + case "/rpc/Relayer/GetProjectBalance": + handler = s.serveGetProjectBalanceJSON + case "/rpc/Relayer/AdjustProjectBalance": + handler = s.serveAdjustProjectBalanceJSON + default: + err := ErrWebrpcBadRoute.WithCausef("no webrpc method defined for path %v", r.URL.Path) + s.sendErrorJSON(w, r, err) + return } - req.Header.Set("Accept", contentType) - req.Header.Set("Content-Type", contentType) - req.Header.Set(WebrpcHeader, WebrpcHeaderValue) - if headers, ok := HTTPRequestHeaders(ctx); ok { - for k := range headers { - for _, v := range headers[k] { - req.Header.Add(k, v) + + if r.Method != "POST" { + w.Header().Add("Allow", "POST") // RFC 9110. + err := ErrWebrpcBadMethod.WithCausef("unsupported HTTP method %v (only POST is allowed)", r.Method) + s.sendErrorJSON(w, r, err) + return + } + + contentType := r.Header.Get("Content-Type") + if i := strings.Index(contentType, ";"); i >= 0 { + contentType = contentType[:i] + } + contentType = strings.TrimSpace(strings.ToLower(contentType)) + + switch contentType { + case "application/json": + if s.OnRequest != nil { + if err := s.OnRequest(w, r); err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return } } + + handler(ctx, w, r) + default: + err := ErrWebrpcBadRequest.WithCausef("unsupported Content-Type %q (only application/json is allowed)", r.Header.Get("Content-Type")) + s.sendErrorJSON(w, r, err) } - return req, nil } -// doHTTPRequest is common code to make a request to the remote service. -func doHTTPRequest(ctx context.Context, client HTTPClient, url string, in, out interface{}) (*http.Response, error) { - reqBody, err := json.Marshal(in) +func (s *relayerService) servePingJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "Ping") + + // Call service method implementation. + ret0, err := s.RelayerServer.Ping(ctx) if err != nil { - return nil, ErrWebrpcRequestFailed.WithCausef("failed to marshal JSON body: %w", err) + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return } - if err = ctx.Err(); err != nil { - return nil, ErrWebrpcRequestFailed.WithCausef("aborted because context was done: %w", err) + + respPayload := struct { + Ret0 bool `json:"status"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return } - req, err := newRequest(ctx, url, bytes.NewBuffer(reqBody), "application/json") + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveVersionJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "Version") + + // Call service method implementation. + ret0, err := s.RelayerServer.Version(ctx) if err != nil { - return nil, ErrWebrpcRequestFailed.WithCausef("could not build request: %w", err) + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return } - resp, err := client.Do(req) + respPayload := struct { + Ret0 *Version `json:"version"` + }{ret0} + respBody, err := json.Marshal(respPayload) if err != nil { - return nil, ErrWebrpcRequestFailed.WithCause(err) + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return } - if resp.StatusCode != 200 { - respBody, err := io.ReadAll(resp.Body) - if err != nil { - return nil, ErrWebrpcBadResponse.WithCausef("failed to read server error response body: %w", err) - } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} - var rpcErr WebRPCError - if err := json.Unmarshal(respBody, &rpcErr); err != nil { - return nil, ErrWebrpcBadResponse.WithCausef("failed to unmarshal server error: %w", err) +func (s *relayerService) serveRuntimeStatusJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "RuntimeStatus") + + // Call service method implementation. + ret0, err := s.RelayerServer.RuntimeStatus(ctx) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 *RuntimeStatus `json:"status"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveGetSequenceContextJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetSequenceContext") + + // Call service method implementation. + ret0, err := s.RelayerServer.GetSequenceContext(ctx) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 *SequenceContext `json:"data"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveGetChainIDJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetChainID") + + // Call service method implementation. + ret0, err := s.RelayerServer.GetChainID(ctx) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 uint64 `json:"chainID"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveSendMetaTxnJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "SendMetaTxn") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 *MetaTxn `json:"call"` + Arg1 *string `json:"quote"` + Arg2 *uint64 `json:"projectID"` + Arg3 []*TransactionPrecondition `json:"preconditions"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.SendMetaTxn(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2, reqPayload.Arg3) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 bool `json:"status"` + Ret1 string `json:"txnHash"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveGetMetaTxnNonceJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetMetaTxnNonce") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 string `json:"walletContractAddress"` + Arg1 *string `json:"space"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.GetMetaTxnNonce(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 string `json:"nonce"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveGetMetaTxnReceiptJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetMetaTxnReceipt") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 string `json:"metaTxID"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.GetMetaTxnReceipt(ctx, reqPayload.Arg0) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 *MetaTxnReceipt `json:"receipt"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveSimulateJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "Simulate") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 string `json:"wallet"` + Arg1 string `json:"transactions"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.Simulate(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 []*SimulateResult `json:"results"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveSimulateV3JSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "SimulateV3") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 string `json:"wallet"` + Arg1 string `json:"calls"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.SimulateV3(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 []*SimulateV3Result `json:"results"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveUpdateMetaTxnGasLimitsJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "UpdateMetaTxnGasLimits") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 string `json:"walletAddress"` + Arg1 interface{} `json:"walletConfig"` + Arg2 string `json:"payload"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.UpdateMetaTxnGasLimits(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 string `json:"payload"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveFeeTokensJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "FeeTokens") + + // Call service method implementation. + ret0, ret1, ret2, err := s.RelayerServer.FeeTokens(ctx) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 bool `json:"isFeeRequired"` + Ret1 []*FeeToken `json:"tokens"` + Ret2 string `json:"paymentAddress"` + }{ret0, ret1, ret2} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveFeeOptionsJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "FeeOptions") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 string `json:"wallet"` + Arg1 string `json:"to"` + Arg2 string `json:"data"` + Arg3 *bool `json:"simulate"` + Arg4 *EIP7702Authorization `json:"authorization"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, ret2, err := s.RelayerServer.FeeOptions(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2, reqPayload.Arg3, reqPayload.Arg4) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 []*FeeOption `json:"options"` + Ret1 bool `json:"sponsored"` + Ret2 *string `json:"quote"` + }{ret0, ret1, ret2} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveSendMetaTxnWithBridgeGasJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "SendMetaTxnWithBridgeGas") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 *MetaTxn `json:"call"` + Arg1 *string `json:"quote"` + Arg2 *uint64 `json:"projectID"` + Arg3 string `json:"bridgeGas"` + Arg4 []*TransactionPrecondition `json:"preconditions"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.SendMetaTxnWithBridgeGas(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2, reqPayload.Arg3, reqPayload.Arg4) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 bool `json:"status"` + Ret1 string `json:"txnHash"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveFeeOptionsWithBridgeGasJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "FeeOptionsWithBridgeGas") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 string `json:"wallet"` + Arg1 string `json:"to"` + Arg2 string `json:"data"` + Arg3 *bool `json:"simulate"` + Arg4 string `json:"bridgeGas"` + Arg5 *EIP7702Authorization `json:"authorization"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, ret2, err := s.RelayerServer.FeeOptionsWithBridgeGas(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2, reqPayload.Arg3, reqPayload.Arg4, reqPayload.Arg5) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 []*FeeOption `json:"options"` + Ret1 bool `json:"sponsored"` + Ret2 *string `json:"quote"` + }{ret0, ret1, ret2} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveGetMetaTxnNetworkFeeOptionsJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetMetaTxnNetworkFeeOptions") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 interface{} `json:"walletConfig"` + Arg1 string `json:"payload"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.GetMetaTxnNetworkFeeOptions(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 []*FeeOption `json:"options"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveStartSenderJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "StartSender") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 int `json:"sender"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + err = s.RelayerServer.StartSender(ctx, reqPayload.Arg0) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write([]byte("{}")) +} + +func (s *relayerService) serveStopSenderJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "StopSender") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 int `json:"sender"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + err = s.RelayerServer.StopSender(ctx, reqPayload.Arg0) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write([]byte("{}")) +} + +func (s *relayerService) serveRepairSenderJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "RepairSender") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 int `json:"sender"` + Arg1 uint64 `json:"nonce"` + Arg2 RepairOperation `json:"operation"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + err = s.RelayerServer.RepairSender(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write([]byte("{}")) +} + +func (s *relayerService) serveGetMetaTransactionsJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetMetaTransactions") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"projectId"` + Arg1 *Page `json:"page"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.GetMetaTransactions(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 *Page `json:"page"` + Ret1 []*MetaTxnLog `json:"transactions"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveGetTransactionCostJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetTransactionCost") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"projectId"` + Arg1 time.Time `json:"from"` + Arg2 time.Time `json:"to"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.GetTransactionCost(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 float64 `json:"cost"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveGetGasTankJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetGasTank") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"id"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.GetGasTank(ctx, reqPayload.Arg0) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 *GasTank `json:"gasTank"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveAddGasTankJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "AddGasTank") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 string `json:"name"` + Arg1 float64 `json:"feeMarkupFactor"` + Arg2 *bool `json:"unlimited"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.AddGasTank(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 bool `json:"status"` + Ret1 *GasTank `json:"gasTank"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveUpdateGasTankJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "UpdateGasTank") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"id"` + Arg1 *string `json:"name"` + Arg2 *float64 `json:"feeMarkupFactor"` + Arg3 *bool `json:"unlimited"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.UpdateGasTank(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2, reqPayload.Arg3) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 bool `json:"status"` + Ret1 *GasTank `json:"gasTank"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveNextGasTankBalanceAdjustmentNonceJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "NextGasTankBalanceAdjustmentNonce") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"id"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.NextGasTankBalanceAdjustmentNonce(ctx, reqPayload.Arg0) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 uint64 `json:"nonce"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveAdjustGasTankBalanceJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "AdjustGasTankBalance") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"id"` + Arg1 uint64 `json:"nonce"` + Arg2 float64 `json:"amount"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.AdjustGasTankBalance(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 bool `json:"status"` + Ret1 *GasTankBalanceAdjustment `json:"adjustment"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveGetGasTankBalanceAdjustmentJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetGasTankBalanceAdjustment") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"id"` + Arg1 uint64 `json:"nonce"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.GetGasTankBalanceAdjustment(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 *GasTankBalanceAdjustment `json:"adjustment"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveListGasTankBalanceAdjustmentsJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "ListGasTankBalanceAdjustments") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"id"` + Arg1 *Page `json:"page"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.ListGasTankBalanceAdjustments(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 *Page `json:"page"` + Ret1 []*GasTankBalanceAdjustment `json:"adjustments"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveListGasSponsorsJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "ListGasSponsors") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"projectId"` + Arg1 *Page `json:"page"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.ListGasSponsors(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 *Page `json:"page"` + Ret1 []*GasSponsor `json:"gasSponsors"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveGetGasSponsorJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetGasSponsor") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"projectId"` + Arg1 uint64 `json:"id"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.GetGasSponsor(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 *GasSponsor `json:"gasSponsor"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveAddGasSponsorJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "AddGasSponsor") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"projectId"` + Arg1 string `json:"address"` + Arg2 *string `json:"name"` + Arg3 *bool `json:"active"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.AddGasSponsor(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2, reqPayload.Arg3) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 bool `json:"status"` + Ret1 *GasSponsor `json:"gasSponsor"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveUpdateGasSponsorJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "UpdateGasSponsor") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"projectId"` + Arg1 uint64 `json:"id"` + Arg2 *string `json:"name"` + Arg3 *bool `json:"active"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.UpdateGasSponsor(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2, reqPayload.Arg3) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 bool `json:"status"` + Ret1 *GasSponsor `json:"gasSponsor"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveRemoveGasSponsorJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "RemoveGasSponsor") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"projectId"` + Arg1 uint64 `json:"id"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.RemoveGasSponsor(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 bool `json:"status"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveListEcosystemGasSponsorsJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "ListEcosystemGasSponsors") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"ecosystemId"` + Arg1 *Page `json:"page"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.ListEcosystemGasSponsors(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 *Page `json:"page"` + Ret1 []*GasSponsor `json:"gasSponsors"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveGetEcosystemGasSponsorJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetEcosystemGasSponsor") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"ecosystemId"` + Arg1 uint64 `json:"id"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.GetEcosystemGasSponsor(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 *GasSponsor `json:"gasSponsor"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveAddEcosystemGasSponsorJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "AddEcosystemGasSponsor") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"ecosystemId"` + Arg1 string `json:"address"` + Arg2 *string `json:"name"` + Arg3 *bool `json:"active"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.AddEcosystemGasSponsor(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2, reqPayload.Arg3) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 bool `json:"status"` + Ret1 *GasSponsor `json:"gasSponsor"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveUpdateEcosystemGasSponsorJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "UpdateEcosystemGasSponsor") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"ecosystemId"` + Arg1 uint64 `json:"id"` + Arg2 *string `json:"name"` + Arg3 *bool `json:"active"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.UpdateEcosystemGasSponsor(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2, reqPayload.Arg3) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 bool `json:"status"` + Ret1 *GasSponsor `json:"gasSponsor"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveRemoveEcosystemGasSponsorJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "RemoveEcosystemGasSponsor") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"ecosystemId"` + Arg1 uint64 `json:"id"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.RemoveEcosystemGasSponsor(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 bool `json:"status"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveAddressGasSponsorsJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "AddressGasSponsors") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 string `json:"address"` + Arg1 *Page `json:"page"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, ret1, err := s.RelayerServer.AddressGasSponsors(ctx, reqPayload.Arg0, reqPayload.Arg1) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 *Page `json:"page"` + Ret1 []*GasSponsor `json:"gasSponsors"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveGetProjectBalanceJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetProjectBalance") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"projectId"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.GetProjectBalance(ctx, reqPayload.Arg0) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 float64 `json:"balance"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) serveAdjustProjectBalanceJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "AdjustProjectBalance") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to read request data: %w", err)) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 uint64 `json:"projectId"` + Arg1 float64 `json:"amount"` + Arg2 string `json:"identifier"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCausef("failed to unmarshal request data: %w", err)) + return + } + + // Call service method implementation. + ret0, err := s.RelayerServer.AdjustProjectBalance(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + respPayload := struct { + Ret0 float64 `json:"balance"` + }{ret0} + respBody, err := json.Marshal(respPayload) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCausef("failed to marshal json response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(respBody) +} + +func (s *relayerService) sendErrorJSON(w http.ResponseWriter, r *http.Request, rpcErr WebRPCError) { + if s.OnError != nil { + s.OnError(r, &rpcErr) + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(rpcErr.HTTPStatus) + + respBody, _ := json.Marshal(rpcErr) + w.Write(respBody) +} + +func RespondWithError(w http.ResponseWriter, err error) { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(rpcErr.HTTPStatus) + + respBody, _ := json.Marshal(rpcErr) + w.Write(respBody) +} + +type method struct { + name string + service string + annotations map[string]string +} + +func (m *method) Name() string { return m.name } +func (m *method) Service() string { return m.service } +func (m *method) Annotations() map[string]string { return m.annotations } + +var methods = map[string]*method{ + "/rpc/Relayer/Ping": { + name: "Ping", + service: "Relayer", + annotations: map[string]string{"internal": ""}, + }, + "/rpc/Relayer/Version": { + name: "Version", + service: "Relayer", + annotations: map[string]string{"internal": ""}, + }, + "/rpc/Relayer/RuntimeStatus": { + name: "RuntimeStatus", + service: "Relayer", + annotations: map[string]string{"internal": ""}, + }, + "/rpc/Relayer/GetSequenceContext": { + name: "GetSequenceContext", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/GetChainID": { + name: "GetChainID", + service: "Relayer", + annotations: map[string]string{"public": ""}, + }, + "/rpc/Relayer/SendMetaTxn": { + name: "SendMetaTxn", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/GetMetaTxnNonce": { + name: "GetMetaTxnNonce", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/GetMetaTxnReceipt": { + name: "GetMetaTxnReceipt", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/Simulate": { + name: "Simulate", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/SimulateV3": { + name: "SimulateV3", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/UpdateMetaTxnGasLimits": { + name: "UpdateMetaTxnGasLimits", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/FeeTokens": { + name: "FeeTokens", + service: "Relayer", + annotations: map[string]string{"public": ""}, + }, + "/rpc/Relayer/FeeOptions": { + name: "FeeOptions", + service: "Relayer", + annotations: map[string]string{"public": ""}, + }, + "/rpc/Relayer/SendMetaTxnWithBridgeGas": { + name: "SendMetaTxnWithBridgeGas", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/FeeOptionsWithBridgeGas": { + name: "FeeOptionsWithBridgeGas", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/GetMetaTxnNetworkFeeOptions": { + name: "GetMetaTxnNetworkFeeOptions", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/StartSender": { + name: "StartSender", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/StopSender": { + name: "StopSender", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/RepairSender": { + name: "RepairSender", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/GetMetaTransactions": { + name: "GetMetaTransactions", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/GetTransactionCost": { + name: "GetTransactionCost", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/GetGasTank": { + name: "GetGasTank", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/AddGasTank": { + name: "AddGasTank", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/UpdateGasTank": { + name: "UpdateGasTank", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/NextGasTankBalanceAdjustmentNonce": { + name: "NextGasTankBalanceAdjustmentNonce", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/AdjustGasTankBalance": { + name: "AdjustGasTankBalance", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/GetGasTankBalanceAdjustment": { + name: "GetGasTankBalanceAdjustment", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/ListGasTankBalanceAdjustments": { + name: "ListGasTankBalanceAdjustments", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/ListGasSponsors": { + name: "ListGasSponsors", + service: "Relayer", + annotations: map[string]string{"public": ""}, + }, + "/rpc/Relayer/GetGasSponsor": { + name: "GetGasSponsor", + service: "Relayer", + annotations: map[string]string{"public": ""}, + }, + "/rpc/Relayer/AddGasSponsor": { + name: "AddGasSponsor", + service: "Relayer", + annotations: map[string]string{"public": ""}, + }, + "/rpc/Relayer/UpdateGasSponsor": { + name: "UpdateGasSponsor", + service: "Relayer", + annotations: map[string]string{"public": ""}, + }, + "/rpc/Relayer/RemoveGasSponsor": { + name: "RemoveGasSponsor", + service: "Relayer", + annotations: map[string]string{"public": ""}, + }, + "/rpc/Relayer/ListEcosystemGasSponsors": { + name: "ListEcosystemGasSponsors", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/GetEcosystemGasSponsor": { + name: "GetEcosystemGasSponsor", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/AddEcosystemGasSponsor": { + name: "AddEcosystemGasSponsor", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/UpdateEcosystemGasSponsor": { + name: "UpdateEcosystemGasSponsor", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/RemoveEcosystemGasSponsor": { + name: "RemoveEcosystemGasSponsor", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/AddressGasSponsors": { + name: "AddressGasSponsors", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/GetProjectBalance": { + name: "GetProjectBalance", + service: "Relayer", + annotations: map[string]string{}, + }, + "/rpc/Relayer/AdjustProjectBalance": { + name: "AdjustProjectBalance", + service: "Relayer", + annotations: map[string]string{}, + }, +} + +func MethodCtx(ctx context.Context) (*method, bool) { + req := RequestFromContext(ctx) + if req == nil { + return nil, false + } + + m, ok := methods[req.URL.Path] + return m, ok +} + +func WebrpcMethods() map[string]*method { + return methods +} + +var WebRPCServices = map[string][]string{ + "Relayer": { + "Ping", + "Version", + "RuntimeStatus", + "GetSequenceContext", + "GetChainID", + "SendMetaTxn", + "GetMetaTxnNonce", + "GetMetaTxnReceipt", + "Simulate", + "SimulateV3", + "UpdateMetaTxnGasLimits", + "FeeTokens", + "FeeOptions", + "SendMetaTxnWithBridgeGas", + "FeeOptionsWithBridgeGas", + "GetMetaTxnNetworkFeeOptions", + "StartSender", + "StopSender", + "RepairSender", + "GetMetaTransactions", + "GetTransactionCost", + "GetGasTank", + "AddGasTank", + "UpdateGasTank", + "NextGasTankBalanceAdjustmentNonce", + "AdjustGasTankBalance", + "GetGasTankBalanceAdjustment", + "ListGasTankBalanceAdjustments", + "ListGasSponsors", + "GetGasSponsor", + "AddGasSponsor", + "UpdateGasSponsor", + "RemoveGasSponsor", + "ListEcosystemGasSponsors", + "GetEcosystemGasSponsor", + "AddEcosystemGasSponsor", + "UpdateEcosystemGasSponsor", + "RemoveEcosystemGasSponsor", + "AddressGasSponsors", + "GetProjectBalance", + "AdjustProjectBalance", + }, +} + +// +// Client helpers +// + +// HTTPClient is the interface used by generated clients to send HTTP requests. +// It is fulfilled by *(net/http).Client, which is sufficient for most users. +// Users can provide their own implementation for special retry policies. +type HTTPClient interface { + Do(req *http.Request) (*http.Response, error) +} + +// urlBase helps ensure that addr specifies a scheme. If it is unparsable +// as a URL, it returns addr unchanged. +func urlBase(addr string) string { + // If the addr specifies a scheme, use it. If not, default to + // http. If url.Parse fails on it, return it unchanged. + url, err := url.Parse(addr) + if err != nil { + return addr + } + if url.Scheme == "" { + url.Scheme = "http" + } + return url.String() +} + +// newRequest makes an http.Request from a client, adding common headers. +func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { + req, err := http.NewRequestWithContext(ctx, "POST", url, reqBody) + if err != nil { + return nil, err + } + req.Header.Set("Accept", contentType) + req.Header.Set("Content-Type", contentType) + req.Header.Set(WebrpcHeader, WebrpcHeaderValue) + if headers, ok := HTTPRequestHeaders(ctx); ok { + for k := range headers { + for _, v := range headers[k] { + req.Header.Add(k, v) + } + } + } + return req, nil +} + +// doHTTPRequest is common code to make a request to the remote service. +func doHTTPRequest(ctx context.Context, client HTTPClient, url string, in, out interface{}) (*http.Response, error) { + reqBody, err := json.Marshal(in) + if err != nil { + return nil, ErrWebrpcRequestFailed.WithCausef("failed to marshal JSON body: %w", err) + } + if err = ctx.Err(); err != nil { + return nil, ErrWebrpcRequestFailed.WithCausef("aborted because context was done: %w", err) + } + + req, err := newRequest(ctx, url, bytes.NewBuffer(reqBody), "application/json") + if err != nil { + return nil, ErrWebrpcRequestFailed.WithCausef("could not build request: %w", err) + } + + resp, err := client.Do(req) + if err != nil { + return nil, ErrWebrpcRequestFailed.WithCause(err) + } + + if resp.StatusCode != 200 { + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, ErrWebrpcBadResponse.WithCausef("failed to read server error response body: %w", err) + } + + var rpcErr WebRPCError + if err := json.Unmarshal(respBody, &rpcErr); err != nil { + return nil, ErrWebrpcBadResponse.WithCausef("failed to unmarshal server error: %w", err) } if rpcErr.Cause != "" { rpcErr.cause = errors.New(rpcErr.Cause) @@ -1695,9 +3982,36 @@ var ( HTTPClientRequestHeadersCtxKey = &contextKey{"HTTPClientRequestHeaders"} ) +var ( + HTTPResponseWriterCtxKey = &contextKey{"HTTPResponseWriter"} + MethodNameCtxKey = &contextKey{"MethodName"} + HTTPRequestCtxKey = &contextKey{"HTTPRequest"} + ServiceNameCtxKey = &contextKey{"ServiceName"} +) + +func ServiceNameFromContext(ctx context.Context) string { + service, _ := ctx.Value(ServiceNameCtxKey).(string) + return service +} + +func MethodNameFromContext(ctx context.Context) string { + method, _ := ctx.Value(MethodNameCtxKey).(string) + return method +} + +func RequestFromContext(ctx context.Context) *http.Request { + r, _ := ctx.Value(HTTPRequestCtxKey).(*http.Request) + return r +} + // PtrTo is a useful helper when constructing values for optional fields. func PtrTo[T any](v T) *T { return &v } +func ResponseWriterFromContext(ctx context.Context) http.ResponseWriter { + w, _ := ctx.Value(HTTPResponseWriterCtxKey).(http.ResponseWriter) + return w +} + // // BigInt helpers // @@ -1945,7 +4259,7 @@ var ( const WebrpcHeader = "Webrpc" -const WebrpcHeaderValue = "webrpc@v0.31.2;gen-golang@v0.23.3;sequence-relayer@v0.4.1" +const WebrpcHeaderValue = "webrpc@v0.32.2;gen-golang@v0.24.0;sequence-relayer@v0.4.1" type WebrpcGenVersions struct { WebrpcGenVersion string diff --git a/relayer/relayer.go b/relayer/relayer.go index 34fbac340..ec5404f80 100644 --- a/relayer/relayer.go +++ b/relayer/relayer.go @@ -23,6 +23,7 @@ import ( v1 "github.com/0xsequence/go-sequence/core/v1" v2 "github.com/0xsequence/go-sequence/core/v2" v3 "github.com/0xsequence/go-sequence/core/v3" + "github.com/0xsequence/go-sequence/lib/prototyp" "github.com/0xsequence/go-sequence/lib/simulator" "github.com/0xsequence/go-sequence/receipts" "github.com/0xsequence/go-sequence/relayer/proto" @@ -246,10 +247,23 @@ func (r *Client) Relay(ctx context.Context, signedTxs *sequence.SignedTransactio to = signedTxs.WalletContext.GuestModuleAddress } + var authorization *proto.EIP7702Authorization + if signedTxs.Authorization != nil { + authorization = &proto.EIP7702Authorization{ + ChainId: signedTxs.ChainID.Uint64(), + Nonce: signedTxs.Authorization.Nonce, + Implementation: signedTxs.Authorization.Address.Hex(), + YParity: uint64(signedTxs.Authorization.V), + R: prototyp.ToBigInt(signedTxs.Authorization.R.ToBig()), + S: prototyp.ToBigInt(signedTxs.Authorization.S.ToBig()), + } + } + call := &proto.MetaTxn{ Contract: to.Hex(), Input: hexutil.Encode(execdata), WalletAddress: walletAddress.Hex(), + Authorization: authorization, } var txQuote *string @@ -286,12 +300,25 @@ func (r *Client) FeeOptions(ctx context.Context, signedTxs *sequence.SignedTrans return nil, nil, err } + var authorization *proto.EIP7702Authorization + if signedTxs.Authorization != nil { + authorization = &proto.EIP7702Authorization{ + ChainId: signedTxs.ChainID.Uint64(), + Nonce: signedTxs.Authorization.Nonce, + Implementation: signedTxs.Authorization.Address.Hex(), + YParity: uint64(signedTxs.Authorization.V), + R: prototyp.ToBigInt(signedTxs.Authorization.R.ToBig()), + S: prototyp.ToBigInt(signedTxs.Authorization.S.ToBig()), + } + } + options, _, quote, err := r.RelayerClient.FeeOptions( ctx, signedTxs.WalletAddress.String(), signedTxs.WalletAddress.String(), "0x"+common.Bytes2Hex(data), nil, + authorization, ) if err != nil { return nil, nil, err diff --git a/transactions.go b/transactions.go index 602c110a1..86803458b 100644 --- a/transactions.go +++ b/transactions.go @@ -10,6 +10,7 @@ import ( "github.com/0xsequence/ethkit/ethrpc" "github.com/0xsequence/ethkit/go-ethereum/accounts/abi" "github.com/0xsequence/ethkit/go-ethereum/common" + "github.com/0xsequence/ethkit/go-ethereum/core/types" "github.com/0xsequence/go-sequence/contracts" "github.com/0xsequence/go-sequence/core" v1 "github.com/0xsequence/go-sequence/core/v1" @@ -508,6 +509,8 @@ type SignedTransactions struct { WalletConfig core.WalletConfig WalletContext WalletContext + Authorization *types.SetCodeAuthorization // Optional EIP-7702 authorization + Transactions Transactions // The meta-transactions Space *big.Int // Nonce space of the transactions Nonce *big.Int // Nonce of the transactions From 55845764229af92c9b34b979969b4e690f585087 Mon Sep 17 00:00:00 2001 From: Patryk Kalinowski Date: Thu, 23 Apr 2026 19:21:12 +0200 Subject: [PATCH 2/5] relayer: update client --- relayer/proto/relayer.gen.go | 15 +++++++-------- relayer/relayer.go | 17 ++++++++++------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/relayer/proto/relayer.gen.go b/relayer/proto/relayer.gen.go index 43b83c59a..3f29ca2af 100644 --- a/relayer/proto/relayer.gen.go +++ b/relayer/proto/relayer.gen.go @@ -1,4 +1,4 @@ -// sequence-relayer v0.4.1 5f4ba9cfea3872be7073167aaef21a647ec36e52 +// sequence-relayer v0.4.1 17923978b5bea530cea7f2517b8c22eea7e51e57 // -- // Code generated by webrpc-gen@v0.32.2 with golang generator. DO NOT EDIT. // @@ -35,7 +35,7 @@ func WebRPCSchemaVersion() string { // Schema hash generated from your RIDL schema func WebRPCSchemaHash() string { - return "5f4ba9cfea3872be7073167aaef21a647ec36e52" + return "17923978b5bea530cea7f2517b8c22eea7e51e57" } // @@ -607,12 +607,11 @@ type MetaTxn struct { } type EIP7702Authorization struct { - ChainId uint64 `json:"chainId"` - Implementation string `json:"implementation"` - Nonce uint64 `json:"nonce"` - YParity uint64 `json:"yParity"` - R prototyp.BigInt `json:"r"` - S prototyp.BigInt `json:"s"` + ChainId uint64 `json:"chainId"` + Implementation string `json:"implementation"` + Nonce uint64 `json:"nonce"` + // 0x-prefixed 65-byte r || s || yParity signature + Signature string `json:"signature"` } // TODO: review diff --git a/relayer/relayer.go b/relayer/relayer.go index ec5404f80..070f1aa6e 100644 --- a/relayer/relayer.go +++ b/relayer/relayer.go @@ -23,7 +23,6 @@ import ( v1 "github.com/0xsequence/go-sequence/core/v1" v2 "github.com/0xsequence/go-sequence/core/v2" v3 "github.com/0xsequence/go-sequence/core/v3" - "github.com/0xsequence/go-sequence/lib/prototyp" "github.com/0xsequence/go-sequence/lib/simulator" "github.com/0xsequence/go-sequence/receipts" "github.com/0xsequence/go-sequence/relayer/proto" @@ -249,13 +248,15 @@ func (r *Client) Relay(ctx context.Context, signedTxs *sequence.SignedTransactio var authorization *proto.EIP7702Authorization if signedTxs.Authorization != nil { + var sig [65]byte + signedTxs.Authorization.R.WriteToSlice(sig[:32]) + signedTxs.Authorization.S.WriteToSlice(sig[32:64]) + sig[64] = signedTxs.Authorization.V authorization = &proto.EIP7702Authorization{ ChainId: signedTxs.ChainID.Uint64(), Nonce: signedTxs.Authorization.Nonce, Implementation: signedTxs.Authorization.Address.Hex(), - YParity: uint64(signedTxs.Authorization.V), - R: prototyp.ToBigInt(signedTxs.Authorization.R.ToBig()), - S: prototyp.ToBigInt(signedTxs.Authorization.S.ToBig()), + Signature: hexutil.Encode(sig[:]), } } @@ -302,13 +303,15 @@ func (r *Client) FeeOptions(ctx context.Context, signedTxs *sequence.SignedTrans var authorization *proto.EIP7702Authorization if signedTxs.Authorization != nil { + var sig [65]byte + signedTxs.Authorization.R.WriteToSlice(sig[:32]) + signedTxs.Authorization.S.WriteToSlice(sig[32:64]) + sig[64] = signedTxs.Authorization.V authorization = &proto.EIP7702Authorization{ ChainId: signedTxs.ChainID.Uint64(), Nonce: signedTxs.Authorization.Nonce, Implementation: signedTxs.Authorization.Address.Hex(), - YParity: uint64(signedTxs.Authorization.V), - R: prototyp.ToBigInt(signedTxs.Authorization.R.ToBig()), - S: prototyp.ToBigInt(signedTxs.Authorization.S.ToBig()), + Signature: hexutil.Encode(sig[:]), } } From 19cc97cc2ef365e826e82b1454dc2ccc83614755 Mon Sep 17 00:00:00 2001 From: Patryk Kalinowski Date: Thu, 23 Apr 2026 19:41:05 +0200 Subject: [PATCH 3/5] relayer: return error if chain ID is mismatched --- relayer/relayer.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/relayer/relayer.go b/relayer/relayer.go index 070f1aa6e..98e147172 100644 --- a/relayer/relayer.go +++ b/relayer/relayer.go @@ -248,12 +248,16 @@ func (r *Client) Relay(ctx context.Context, signedTxs *sequence.SignedTransactio var authorization *proto.EIP7702Authorization if signedTxs.Authorization != nil { + if signedTxs.ChainID.Uint64() != signedTxs.Authorization.ChainID.Uint64() { + return "", nil, nil, fmt.Errorf("chain ID mismatch between signed transactions and authorization") + } + var sig [65]byte signedTxs.Authorization.R.WriteToSlice(sig[:32]) signedTxs.Authorization.S.WriteToSlice(sig[32:64]) sig[64] = signedTxs.Authorization.V authorization = &proto.EIP7702Authorization{ - ChainId: signedTxs.ChainID.Uint64(), + ChainId: signedTxs.Authorization.ChainID.Uint64(), Nonce: signedTxs.Authorization.Nonce, Implementation: signedTxs.Authorization.Address.Hex(), Signature: hexutil.Encode(sig[:]), @@ -303,12 +307,16 @@ func (r *Client) FeeOptions(ctx context.Context, signedTxs *sequence.SignedTrans var authorization *proto.EIP7702Authorization if signedTxs.Authorization != nil { + if signedTxs.ChainID.Uint64() != signedTxs.Authorization.ChainID.Uint64() { + return nil, nil, fmt.Errorf("chain ID mismatch between signed transactions and authorization") + } + var sig [65]byte signedTxs.Authorization.R.WriteToSlice(sig[:32]) signedTxs.Authorization.S.WriteToSlice(sig[32:64]) sig[64] = signedTxs.Authorization.V authorization = &proto.EIP7702Authorization{ - ChainId: signedTxs.ChainID.Uint64(), + ChainId: signedTxs.Authorization.ChainID.Uint64(), Nonce: signedTxs.Authorization.Nonce, Implementation: signedTxs.Authorization.Address.Hex(), Signature: hexutil.Encode(sig[:]), From 5e28fc2f1cc036701e692c2f3e94db6244152ae8 Mon Sep 17 00:00:00 2001 From: Patryk Kalinowski Date: Thu, 23 Apr 2026 19:50:56 +0200 Subject: [PATCH 4/5] relayer: allow authorizations with chainId=0 --- relayer/relayer.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/relayer/relayer.go b/relayer/relayer.go index 98e147172..e34c644c7 100644 --- a/relayer/relayer.go +++ b/relayer/relayer.go @@ -248,7 +248,8 @@ func (r *Client) Relay(ctx context.Context, signedTxs *sequence.SignedTransactio var authorization *proto.EIP7702Authorization if signedTxs.Authorization != nil { - if signedTxs.ChainID.Uint64() != signedTxs.Authorization.ChainID.Uint64() { + chainID := signedTxs.Authorization.ChainID.Uint64() + if chainID != 0 && signedTxs.ChainID.Uint64() != chainID { return "", nil, nil, fmt.Errorf("chain ID mismatch between signed transactions and authorization") } @@ -257,7 +258,7 @@ func (r *Client) Relay(ctx context.Context, signedTxs *sequence.SignedTransactio signedTxs.Authorization.S.WriteToSlice(sig[32:64]) sig[64] = signedTxs.Authorization.V authorization = &proto.EIP7702Authorization{ - ChainId: signedTxs.Authorization.ChainID.Uint64(), + ChainId: chainID, Nonce: signedTxs.Authorization.Nonce, Implementation: signedTxs.Authorization.Address.Hex(), Signature: hexutil.Encode(sig[:]), @@ -307,7 +308,8 @@ func (r *Client) FeeOptions(ctx context.Context, signedTxs *sequence.SignedTrans var authorization *proto.EIP7702Authorization if signedTxs.Authorization != nil { - if signedTxs.ChainID.Uint64() != signedTxs.Authorization.ChainID.Uint64() { + chainID := signedTxs.Authorization.ChainID.Uint64() + if chainID != 0 && signedTxs.ChainID.Uint64() != chainID { return nil, nil, fmt.Errorf("chain ID mismatch between signed transactions and authorization") } @@ -316,7 +318,7 @@ func (r *Client) FeeOptions(ctx context.Context, signedTxs *sequence.SignedTrans signedTxs.Authorization.S.WriteToSlice(sig[32:64]) sig[64] = signedTxs.Authorization.V authorization = &proto.EIP7702Authorization{ - ChainId: signedTxs.Authorization.ChainID.Uint64(), + ChainId: chainID, Nonce: signedTxs.Authorization.Nonce, Implementation: signedTxs.Authorization.Address.Hex(), Signature: hexutil.Encode(sig[:]), From d8106db7a5b5a89140d374ce42fa783c1c19a819 Mon Sep 17 00:00:00 2001 From: Patryk Kalinowski Date: Thu, 23 Apr 2026 20:14:56 +0200 Subject: [PATCH 5/5] fix potential panic --- relayer/relayer.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/relayer/relayer.go b/relayer/relayer.go index e34c644c7..f9ef1ccf2 100644 --- a/relayer/relayer.go +++ b/relayer/relayer.go @@ -249,7 +249,7 @@ func (r *Client) Relay(ctx context.Context, signedTxs *sequence.SignedTransactio var authorization *proto.EIP7702Authorization if signedTxs.Authorization != nil { chainID := signedTxs.Authorization.ChainID.Uint64() - if chainID != 0 && signedTxs.ChainID.Uint64() != chainID { + if chainID != 0 && signedTxs.ChainID != nil && signedTxs.ChainID.Uint64() != chainID { return "", nil, nil, fmt.Errorf("chain ID mismatch between signed transactions and authorization") } @@ -309,7 +309,7 @@ func (r *Client) FeeOptions(ctx context.Context, signedTxs *sequence.SignedTrans var authorization *proto.EIP7702Authorization if signedTxs.Authorization != nil { chainID := signedTxs.Authorization.ChainID.Uint64() - if chainID != 0 && signedTxs.ChainID.Uint64() != chainID { + if chainID != 0 && signedTxs.ChainID != nil && signedTxs.ChainID.Uint64() != chainID { return nil, nil, fmt.Errorf("chain ID mismatch between signed transactions and authorization") }