diff --git a/lib/mock/relayer.mock.go b/lib/mock/relayer.mock.go index b6eaa9bd..2bcf745d 100644 --- a/lib/mock/relayer.mock.go +++ b/lib/mock/relayer.mock.go @@ -1,9 +1,9 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: ../../relayer/proto (interfaces: RelayerClient) +// Source: ./relayer/proto (interfaces: RelayerClient) // // Generated by this command: // -// mockgen -destination relayer.mock.go -package mock -mock_names RelayerClient=Relayer ../../relayer/proto RelayerClient +// mockgen -destination lib/mock/relayer.mock.go -package mock -mock_names RelayerClient=Relayer ./relayer/proto RelayerClient // // Package mock is a generated GoMock package. @@ -122,9 +122,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, bridgeGas *string) ([]*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, bridgeGas) ret0, _ := ret[0].([]*proto.FeeOption) ret1, _ := ret[1].(bool) ret2, _ := ret[2].(*string) @@ -133,9 +133,9 @@ 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, bridgeGas 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, bridgeGas) } // FeeTokens mocks base method. @@ -445,6 +445,22 @@ func (mr *RelayerMockRecorder) SendMetaTxn(ctx, call, quote, projectID, precondi return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMetaTxn", reflect.TypeOf((*Relayer)(nil).SendMetaTxn), ctx, call, quote, projectID, preconditions) } +// SendMetaTxnWithBridgeGas mocks base method. +func (m *Relayer) SendMetaTxnWithBridgeGas(ctx context.Context, call *proto.MetaTxn, bridgeGas string, quote *string, projectID *uint64, preconditions []*proto.TransactionPrecondition) (bool, string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendMetaTxnWithBridgeGas", ctx, call, bridgeGas, quote, projectID, preconditions) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// SendMetaTxnWithBridgeGas indicates an expected call of SendMetaTxnWithBridgeGas. +func (mr *RelayerMockRecorder) SendMetaTxnWithBridgeGas(ctx, call, bridgeGas, quote, projectID, preconditions any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMetaTxnWithBridgeGas", reflect.TypeOf((*Relayer)(nil).SendMetaTxnWithBridgeGas), ctx, call, bridgeGas, quote, projectID, 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() diff --git a/relayer/proto/relayer.gen.go b/relayer/proto/relayer.gen.go index 06a88147..e5b4d827 100644 --- a/relayer/proto/relayer.gen.go +++ b/relayer/proto/relayer.gen.go @@ -1,4 +1,4 @@ -// sequence-relayer v0.4.1 7f8a4b83b00e0b6849c76c2ff0e23931e26b3d9f +// sequence-relayer v0.4.1 a868298438a2fab314581c4ba7e21b0dcca1db60 // -- // Code generated by webrpc-gen@v0.31.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 "7f8a4b83b00e0b6849c76c2ff0e23931e26b3d9f" + return "a868298438a2fab314581c4ba7e21b0dcca1db60" } // @@ -55,6 +55,9 @@ type RelayerClient interface { // 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) + // Internal endpoint for service-to-service calls that require bridge gas fronting + // Used by Trails/Excalibur for LayerZero OFT bridge transactions + SendMetaTxnWithBridgeGas(ctx context.Context, call *MetaTxn, bridgeGas string, 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 @@ -68,7 +71,9 @@ 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) + // Used for bridge fees (e.g., LayerZero messaging fees) that require msg.value to be fronted at runtime. + // This value will be included in the fee calculation so the relayer gets reimbursed. + FeeOptions(ctx context.Context, wallet string, to string, data string, simulate *bool, bridgeGas *string) ([]*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) GetMetaTransactions(ctx context.Context, projectId uint64, page *Page) (*Page, []*MetaTxnLog, error) @@ -122,6 +127,8 @@ const ( ETHTxnStatus_FAILED ETHTxnStatus = 6 // txn accepted by relayer, waiting for preconditions to be satisfied ETHTxnStatus_PENDING_PRECONDITION ETHTxnStatus = 7 + // waiting for receipt + ETHTxnStatus_MINED ETHTxnStatus = 8 ) var ETHTxnStatus_name = map[uint]string{ @@ -133,6 +140,7 @@ var ETHTxnStatus_name = map[uint]string{ 5: "PARTIALLY_FAILED", 6: "FAILED", 7: "PENDING_PRECONDITION", + 8: "MINED", } var ETHTxnStatus_value = map[string]uint{ @@ -144,6 +152,7 @@ var ETHTxnStatus_value = map[string]uint{ "PARTIALLY_FAILED": 5, "FAILED": 6, "PENDING_PRECONDITION": 7, + "MINED": 8, } func (x ETHTxnStatus) String() string { @@ -458,6 +467,9 @@ type MetaTxn struct { Contract string `json:"contract" db:"to_address"` // TODO: rename to 'execdata' Input string `json:"input" db:"tx_data"` + // Bridge gas (in wei) to be fronted at runtime with the transaction. + // Used for bridge fees (e.g., LayerZero messaging fees) that require msg.value. + BridgeGas *prototyp.BigInt `json:"bridgeGas" db:"bridge_gas"` } // TODO: review @@ -480,6 +492,9 @@ type MetaTxnLog struct { MinedAt *time.Time `json:"minedAt" db:"mined_at,omitempty"` Target prototyp.Hash `json:"target" db:"target"` Input prototyp.Hash `json:"input" db:"input"` + // Bridge gas (in wei) to be fronted at runtime with the transaction. + // Used for bridge fees (e.g., LayerZero messaging fees) that require msg.value. + BridgeGas *prototyp.BigInt `json:"bridgeGas" db:"bridge_gas"` // TODO: review this field.. we may not want it.. what goes in here..? is it just // the input/target from MetaTxn above? we already have these as separate columns.. TxnArgs map[string]interface{} `json:"txnArgs" db:"txn_args"` @@ -631,18 +646,19 @@ const RelayerPathPrefix = "/rpc/Relayer/" type relayerClient struct { client HTTPClient - urls [33]string + urls [34]string } func NewRelayerClient(addr string, client HTTPClient) RelayerClient { prefix := urlBase(addr) + RelayerPathPrefix - urls := [33]string{ + urls := [34]string{ prefix + "Ping", prefix + "Version", prefix + "RuntimeStatus", prefix + "GetSequenceContext", prefix + "GetChainID", prefix + "SendMetaTxn", + prefix + "SendMetaTxnWithBridgeGas", prefix + "GetMetaTxnNonce", prefix + "GetMetaTxnReceipt", prefix + "Simulate", @@ -780,6 +796,30 @@ func (c *relayerClient) SendMetaTxn(ctx context.Context, call *MetaTxn, quote *s return out.Ret0, out.Ret1, err } +func (c *relayerClient) SendMetaTxnWithBridgeGas(ctx context.Context, call *MetaTxn, bridgeGas string, quote *string, projectID *uint64, preconditions []*TransactionPrecondition) (bool, string, error) { + in := struct { + Arg0 *MetaTxn `json:"call"` + Arg1 string `json:"bridgeGas"` + Arg2 *string `json:"quote"` + Arg3 *uint64 `json:"projectID"` + Arg4 []*TransactionPrecondition `json:"preconditions"` + }{call, bridgeGas, quote, projectID, preconditions} + out := struct { + Ret0 bool `json:"status"` + Ret1 string `json:"txnHash"` + }{} + + resp, err := doHTTPRequest(ctx, c.client, c.urls[6], 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) GetMetaTxnNonce(ctx context.Context, walletContractAddress string, space *string) (string, error) { in := struct { Arg0 string `json:"walletContractAddress"` @@ -789,7 +829,7 @@ func (c *relayerClient) GetMetaTxnNonce(ctx context.Context, walletContractAddre Ret0 string `json:"nonce"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[6], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[7], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -808,7 +848,7 @@ func (c *relayerClient) GetMetaTxnReceipt(ctx context.Context, metaTxID string) Ret0 *MetaTxnReceipt `json:"receipt"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[7], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[8], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -828,7 +868,7 @@ func (c *relayerClient) Simulate(ctx context.Context, wallet string, transaction Ret0 []*SimulateResult `json:"results"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[8], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[9], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -848,7 +888,7 @@ func (c *relayerClient) SimulateV3(ctx context.Context, wallet string, calls str Ret0 []*SimulateV3Result `json:"results"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[9], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[10], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -869,7 +909,7 @@ func (c *relayerClient) UpdateMetaTxnGasLimits(ctx context.Context, walletAddres Ret0 string `json:"payload"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[10], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[11], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -887,7 +927,7 @@ func (c *relayerClient) FeeTokens(ctx context.Context) (bool, []*FeeToken, strin Ret2 string `json:"paymentAddress"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[11], nil, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[12], nil, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -898,20 +938,21 @@ 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, bridgeGas *string) ([]*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 *string `json:"bridgeGas"` + }{wallet, to, data, simulate, bridgeGas} out := struct { Ret0 []*FeeOption `json:"options"` Ret1 bool `json:"sponsored"` Ret2 *string `json:"quote"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[12], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[13], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -931,7 +972,7 @@ func (c *relayerClient) GetMetaTxnNetworkFeeOptions(ctx context.Context, walletC Ret0 []*FeeOption `json:"options"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[13], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[14], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -952,7 +993,7 @@ func (c *relayerClient) GetMetaTransactions(ctx context.Context, projectId uint6 Ret1 []*MetaTxnLog `json:"transactions"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[14], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[15], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -973,7 +1014,7 @@ func (c *relayerClient) GetTransactionCost(ctx context.Context, projectId uint64 Ret0 float64 `json:"cost"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[15], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[16], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -994,7 +1035,7 @@ func (c *relayerClient) SentTransactions(ctx context.Context, filter *SentTransa Ret1 []*Transaction `json:"transactions"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[16], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[17], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1014,7 +1055,7 @@ func (c *relayerClient) PendingTransactions(ctx context.Context, page *Page) (*P Ret1 []*Transaction `json:"transactions"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[17], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[18], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1033,7 +1074,7 @@ func (c *relayerClient) GetGasTank(ctx context.Context, id uint64) (*GasTank, er Ret0 *GasTank `json:"gasTank"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[18], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[19], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1055,7 +1096,7 @@ func (c *relayerClient) AddGasTank(ctx context.Context, name string, feeMarkupFa Ret1 *GasTank `json:"gasTank"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[19], in, &out) + resp, err := doHTTPRequest(ctx, c.client, c.urls[20], in, &out) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1078,7 +1119,7 @@ func (c *relayerClient) UpdateGasTank(ctx context.Context, id uint64, name *stri Ret1 *GasTank `json:"gasTank"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[20], 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 { @@ -1097,7 +1138,7 @@ func (c *relayerClient) NextGasTankBalanceAdjustmentNonce(ctx context.Context, i Ret0 uint64 `json:"nonce"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[21], 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 { @@ -1119,7 +1160,7 @@ func (c *relayerClient) AdjustGasTankBalance(ctx context.Context, id uint64, non Ret1 *GasTankBalanceAdjustment `json:"adjustment"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[22], 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 { @@ -1139,7 +1180,7 @@ func (c *relayerClient) GetGasTankBalanceAdjustment(ctx context.Context, id uint Ret0 *GasTankBalanceAdjustment `json:"adjustment"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[23], 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 { @@ -1160,7 +1201,7 @@ func (c *relayerClient) ListGasTankBalanceAdjustments(ctx context.Context, id ui Ret1 []*GasTankBalanceAdjustment `json:"adjustments"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[24], 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 { @@ -1181,7 +1222,7 @@ func (c *relayerClient) ListGasSponsors(ctx context.Context, projectId uint64, p Ret1 []*GasSponsor `json:"gasSponsors"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[25], 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 { @@ -1201,7 +1242,7 @@ func (c *relayerClient) GetGasSponsor(ctx context.Context, projectId uint64, id Ret0 *GasSponsor `json:"gasSponsor"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[26], 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 { @@ -1224,7 +1265,7 @@ func (c *relayerClient) AddGasSponsor(ctx context.Context, projectId uint64, add Ret1 *GasSponsor `json:"gasSponsor"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[27], 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 { @@ -1247,7 +1288,7 @@ func (c *relayerClient) UpdateGasSponsor(ctx context.Context, projectId uint64, Ret1 *GasSponsor `json:"gasSponsor"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[28], 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 { @@ -1267,7 +1308,7 @@ func (c *relayerClient) RemoveGasSponsor(ctx context.Context, projectId uint64, Ret0 bool `json:"status"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[29], 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 { @@ -1288,7 +1329,7 @@ func (c *relayerClient) AddressGasSponsors(ctx context.Context, address string, Ret1 []*GasSponsor `json:"gasSponsors"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[30], 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 { @@ -1307,7 +1348,7 @@ func (c *relayerClient) GetProjectBalance(ctx context.Context, projectId uint64) Ret0 float64 `json:"balance"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[31], 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 { @@ -1328,7 +1369,7 @@ func (c *relayerClient) AdjustProjectBalance(ctx context.Context, projectId uint Ret0 float64 `json:"balance"` }{} - resp, err := doHTTPRequest(ctx, c.client, c.urls[32], 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 { diff --git a/relayer/relayer.go b/relayer/relayer.go index 723b8832..4e903070 100644 --- a/relayer/relayer.go +++ b/relayer/relayer.go @@ -283,6 +283,7 @@ func (r *Client) FeeOptions(ctx context.Context, signedTxs *sequence.SignedTrans signedTxs.WalletAddress.String(), "0x"+common.Bytes2Hex(data), nil, + nil, ) if err != nil { return nil, nil, err