Skip to content

Commit

Permalink
relayer, update WaitReceipt to return MetaTxnReceipt
Browse files Browse the repository at this point in the history
  • Loading branch information
pkieltyka committed Apr 18, 2024
1 parent 81dc3e2 commit 73f9eff
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 49 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ toolchain go1.22.0
// replace github.com/0xsequence/ethkit => /Users/peter/Dev/0xsequence/ethkit

require (
github.com/0xsequence/ethkit v1.24.9
github.com/0xsequence/ethkit v1.24.10
github.com/0xsequence/go-ethauth v0.13.0
github.com/BurntSushi/toml v1.2.1
github.com/davecgh/go-spew v1.1.1
github.com/gibson042/canonicaljson-go v1.0.3
github.com/goware/breaker v0.1.2
github.com/goware/cachestore v0.8.1
github.com/goware/logger v0.3.0
github.com/shopspring/decimal v1.3.1
Expand All @@ -31,6 +30,7 @@ require (
github.com/go-stack/stack v1.8.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/goware/breaker v0.1.2 // indirect
github.com/goware/calc v0.2.0 // indirect
github.com/goware/channel v0.4.1 // indirect
github.com/goware/singleflight v0.2.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/0xsequence/ethkit v1.24.9 h1:yOVmMc4fJ5NjSPr9piX6rjveqYFsgqKOMxqKRLUiRW4=
github.com/0xsequence/ethkit v1.24.9/go.mod h1:E3eymNtV0oJabgqM9R92xTQYOsT7rVHxFRju8A2CFJw=
github.com/0xsequence/ethkit v1.24.10 h1:aWAbCmadC2GlzoXn96uQ+8V1UWcBxO01F+DtIxsFqXM=
github.com/0xsequence/ethkit v1.24.10/go.mod h1:E3eymNtV0oJabgqM9R92xTQYOsT7rVHxFRju8A2CFJw=
github.com/0xsequence/go-ethauth v0.13.0 h1:ZaqFEEqy574A2b1P7vjpcy5tb4W/izn+A3swwOYi9wA=
github.com/0xsequence/go-ethauth v0.13.0/go.mod h1:f3kx39S9F+W+qvZEB6bkKKbpUstmyB7goUntO3wvlhg=
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
Expand Down
55 changes: 41 additions & 14 deletions receipts.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,13 @@ func (r *Receipt) setNativeReceipt(receipt *types.Receipt) {

// This method is duplicated code from: `compressor/contract.go`
// can't be used directly, because it would create a circular dependency
func DecompressCalldata(ctx context.Context, provider *ethrpc.Provider, transaction *types.Transaction) (common.Address, []byte, error) {
data := transaction.Data()
func DecompressCalldata(
ctx context.Context,
provider *ethrpc.Provider,
toAddress common.Address,
calldata []byte,
) (common.Address, []byte, error) {
data := calldata

if len(data) == 0 {
return common.Address{}, nil, fmt.Errorf("empty transaction data")
Expand All @@ -74,7 +79,7 @@ func DecompressCalldata(ctx context.Context, provider *ethrpc.Provider, transact
c2[0] = byte(0x06)

res, err := provider.CallContract(ctx, ethereum.CallMsg{
To: transaction.To(),
To: &toAddress,
Data: c2,
}, nil)

Expand All @@ -93,18 +98,26 @@ func DecompressCalldata(ctx context.Context, provider *ethrpc.Provider, transact
func TryDecodeCalldata(
ctx context.Context,
provider *ethrpc.Provider,
transaction *types.Transaction,
toAddress common.Address,
calldata []byte,
decompressCzip bool,
) (common.Address, Transactions, *big.Int, []byte, error) {
decodedTransactions, decodedNonce, decodedSignature, err := DecodeExecdata(transaction.Data())
decodedTransactions, decodedNonce, decodedSignature, err := DecodeExecdata(calldata)
if err == nil {
return *transaction.To(), decodedTransactions, decodedNonce, decodedSignature, nil
return toAddress, decodedTransactions, decodedNonce, decodedSignature, nil
}

var addr common.Address
var decompressed []byte
var err2 error

// Try decoding it decompressed
addr, decompressed, err2 := DecompressCalldata(ctx, provider, transaction)
if err2 != nil {
// Don't bubble up the decompression error, as it might not be a decompression error
return common.Address{}, nil, nil, nil, err
if decompressCzip {
addr, decompressed, err2 = DecompressCalldata(ctx, provider, toAddress, calldata)
if err2 != nil {
// Don't bubble up the decompression error, as it might not be a decompression error
return common.Address{}, nil, nil, nil, err
}
}

decodedTransactions, decodedNonce, decodedSignature, err = DecodeExecdata(decompressed)
Expand All @@ -115,19 +128,33 @@ func TryDecodeCalldata(
return addr, decodedTransactions, decodedNonce, decodedSignature, nil
}

func DecodeReceipt(ctx context.Context, receipt *types.Receipt, provider *ethrpc.Provider) ([]*Receipt, []*types.Log, error) {
transaction, _, err := provider.TransactionByHash(ctx, receipt.TxHash)
func DecodeReceipt(
ctx context.Context,
receipt *types.Receipt,
provider *ethrpc.Provider,
calldata []byte,
decompressCzip bool,
) ([]*Receipt, []*types.Log, error) {
if calldata == nil {
transaction, _, err := provider.TransactionByHash(ctx, receipt.TxHash)
if err != nil {
return nil, nil, err
}
calldata = transaction.Data()
}

chainID, err := provider.ChainID(ctx)
if err != nil {
return nil, nil, err
}

wallet, decodedTransactions, decodedNonce, decodedSignature, err := TryDecodeCalldata(ctx, provider, transaction)
wallet, decodedTransactions, decodedNonce, decodedSignature, err := TryDecodeCalldata(ctx, provider, receipt.To, calldata, decompressCzip)
if err != nil {
return nil, nil, err
}

isGuestExecute := decodedNonce != nil && len(decodedSignature) == 0
logs, receipts, err := decodeReceipt(receipt.Logs, decodedTransactions, decodedNonce, wallet, transaction.ChainId(), isGuestExecute)
logs, receipts, err := decodeReceipt(receipt.Logs, decodedTransactions, decodedNonce, wallet, chainID, isGuestExecute)
if err != nil {
return nil, nil, err
}
Expand Down
7 changes: 4 additions & 3 deletions relayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"time"

"github.com/0xsequence/ethkit/ethrpc"
"github.com/0xsequence/ethkit/ethtxn"
"github.com/0xsequence/ethkit/go-ethereum/common"
"github.com/0xsequence/ethkit/go-ethereum/core/types"
"github.com/0xsequence/go-sequence/contracts"
Expand Down Expand Up @@ -68,13 +67,13 @@ type Relayer interface {
// Relay will submit the Sequence signed meta transaction to the relayer. The method will block until the relayer
// responds with the native transaction hash (*types.Transaction), which means the relayer has submitted the transaction
// request to the network. Clients can use WaitReceipt to wait until the metaTxnID has been mined.
Relay(ctx context.Context, signedTxs *SignedTransactions, quote ...*RelayerFeeQuote) (MetaTxnID, *types.Transaction, ethtxn.WaitReceipt, error)
Relay(ctx context.Context, signedTxs *SignedTransactions, quote ...*RelayerFeeQuote) (MetaTxnID, *types.Transaction, WaitReceipt, error)

//
FeeOptions(ctx context.Context, signedTxs *SignedTransactions) ([]*RelayerFeeOption, *RelayerFeeQuote, error)

// ..
Wait(ctx context.Context, metaTxnID MetaTxnID, optTimeout ...time.Duration) (MetaTxnStatus, *types.Receipt, error)
Wait(ctx context.Context, metaTxnID MetaTxnID, optTimeout ...time.Duration) (MetaTxnStatus, *types.Receipt, *proto.MetaTxnReceipt, error)

// ..
Client() proto.Relayer
Expand All @@ -98,6 +97,8 @@ const (
MetaTxnReverted
)

type WaitReceipt func(ctx context.Context) (*types.Receipt, *proto.MetaTxnReceipt, error)

// returns `to` address (either guest or wallet) and `data` of signed-metatx-calldata, aka execdata
func EncodeTransactionsForRelaying(relayer Relayer, walletAddress common.Address, walletConfig core.WalletConfig, walletContext WalletContext, txns Transactions, nonce *big.Int, seqSig []byte) (common.Address, []byte, error) {
// TODO/NOTE: first version, we assume the wallet is deployed, then we can add bundlecreation after.
Expand Down
18 changes: 12 additions & 6 deletions relayer/local_relayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func (r *LocalRelayer) Simulate(ctx context.Context, txs *sequence.SignedTransac
panic("implement me")
}

func (r *LocalRelayer) Relay(ctx context.Context, signedTxs *sequence.SignedTransactions, quote ...*sequence.RelayerFeeQuote) (sequence.MetaTxnID, *types.Transaction, ethtxn.WaitReceipt, error) {
func (r *LocalRelayer) Relay(ctx context.Context, signedTxs *sequence.SignedTransactions, quote ...*sequence.RelayerFeeQuote) (sequence.MetaTxnID, *types.Transaction, sequence.WaitReceipt, error) {
// NOTE: this implementation assumes the wallet is deployed and does not do automatic bundle creation (aka prepending / bundling
// a wallet creation call)

Expand Down Expand Up @@ -208,27 +208,33 @@ func (r *LocalRelayer) Relay(ctx context.Context, signedTxs *sequence.SignedTran
return metaTxnID, nil, nil, err
}

ntx, waitReceipt, err := sender.SendTransaction(ctx, signedTx)
ntx, _, err = sender.SendTransaction(ctx, signedTx)
if err != nil {
return metaTxnID, nil, nil, err
}

waitReceipt := func(ctx context.Context) (*types.Receipt, *proto.MetaTxnReceipt, error) {
// NOTE: to timeout the request, pass a ctx from context.WithTimeout
_, receipt, metaTxnReceipt, err := r.Wait(ctx, sequence.MetaTxnID(metaTxnID))
return receipt, metaTxnReceipt, err
}

return metaTxnID, ntx, waitReceipt, nil
}

func (r *LocalRelayer) Wait(ctx context.Context, metaTxnID sequence.MetaTxnID, optTimeout ...time.Duration) (sequence.MetaTxnStatus, *types.Receipt, error) {
func (r *LocalRelayer) Wait(ctx context.Context, metaTxnID sequence.MetaTxnID, optTimeout ...time.Duration) (sequence.MetaTxnStatus, *types.Receipt, *proto.MetaTxnReceipt, error) {
if r.receiptListener == nil {
return 0, nil, fmt.Errorf("relayer: failed to wait for metaTxnID as receiptListener is not set")
return 0, nil, nil, fmt.Errorf("relayer: failed to wait for metaTxnID as receiptListener is not set")
}
result, receipt, _, err := sequence.FetchMetaTransactionReceipt(ctx, r.receiptListener, metaTxnID, optTimeout...)
if err != nil {
return 0, nil, err
return 0, nil, nil, err
}
var status sequence.MetaTxnStatus
if result != nil {
status = result.Status
}
return status, receipt.Receipt(), nil
return status, receipt.Receipt(), nil, nil // XXXXXX
}

func (r *LocalRelayer) FeeOptions(ctx context.Context, signedTxs *sequence.SignedTransactions) ([]*sequence.RelayerFeeOption, *sequence.RelayerFeeQuote, error) {
Expand Down
29 changes: 15 additions & 14 deletions relayer/rpc_relayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/0xsequence/ethkit"
"github.com/0xsequence/ethkit/ethreceipts"
"github.com/0xsequence/ethkit/ethrpc"
"github.com/0xsequence/ethkit/ethtxn"
"github.com/0xsequence/ethkit/go-ethereum/common"
"github.com/0xsequence/ethkit/go-ethereum/common/hexutil"
"github.com/0xsequence/ethkit/go-ethereum/core/types"
Expand Down Expand Up @@ -144,7 +143,7 @@ func (r *RpcRelayer) Simulate(ctx context.Context, txs *sequence.SignedTransacti
// Relay will submit the Sequence signed meta transaction to the relayer. The method will block until the relayer
// responds with the native transaction hash (*types.Transaction), which means the relayer has submitted the transaction
// request to the network. Clients can use WaitReceipt to wait until the metaTxnID has been mined.
func (r *RpcRelayer) Relay(ctx context.Context, signedTxs *sequence.SignedTransactions, quote ...*sequence.RelayerFeeQuote) (sequence.MetaTxnID, *types.Transaction, ethtxn.WaitReceipt, error) {
func (r *RpcRelayer) Relay(ctx context.Context, signedTxs *sequence.SignedTransactions, quote ...*sequence.RelayerFeeQuote) (sequence.MetaTxnID, *types.Transaction, sequence.WaitReceipt, error) {
walletAddress := signedTxs.WalletAddress
var err error

Expand Down Expand Up @@ -196,10 +195,10 @@ func (r *RpcRelayer) Relay(ctx context.Context, signedTxs *sequence.SignedTransa
return "", nil, nil, proto.Failf("failed to relay meta transaction: server returned empty metaTxnID")
}

waitReceipt := func(ctx context.Context) (*types.Receipt, error) {
waitReceipt := func(ctx context.Context) (*types.Receipt, *proto.MetaTxnReceipt, error) {
// NOTE: to timeout the request, pass a ctx from context.WithTimeout
_, receipt, err := r.Wait(ctx, sequence.MetaTxnID(metaTxnID))
return receipt, err
_, receipt, metaTxnReceipt, err := r.Wait(ctx, sequence.MetaTxnID(metaTxnID))
return receipt, metaTxnReceipt, err
}

// TODO: 2nd argument will be nil, we may even want to remove it from here...
Expand Down Expand Up @@ -232,7 +231,7 @@ func (r *RpcRelayer) FeeOptions(ctx context.Context, signedTxs *sequence.SignedT
}

// ....
func (r *RpcRelayer) Wait(ctx context.Context, metaTxnID sequence.MetaTxnID, optTimeout ...time.Duration) (sequence.MetaTxnStatus, *types.Receipt, error) {
func (r *RpcRelayer) Wait(ctx context.Context, metaTxnID sequence.MetaTxnID, optTimeout ...time.Duration) (sequence.MetaTxnStatus, *types.Receipt, *proto.MetaTxnReceipt, error) {
// Fetch the meta transaction receipt from the relayer service
if r.receiptListener == nil {
return r.waitMetaTxnReceipt(ctx, metaTxnID, optTimeout...)
Expand All @@ -241,16 +240,18 @@ func (r *RpcRelayer) Wait(ctx context.Context, metaTxnID sequence.MetaTxnID, opt
// Fetch the meta transaction receipt from the receipt listener
result, receipt, _, err := sequence.FetchMetaTransactionReceipt(ctx, r.receiptListener, metaTxnID, optTimeout...)
if err != nil {
return 0, nil, err
return 0, nil, nil, err
}
var status sequence.MetaTxnStatus
if result != nil {
status = result.Status
}
return status, receipt.Receipt(), nil
// TODO: need to get from receipt listener result to a sequence meta txn receipt ..
// TODO: can copy bunch of code from GetMetaTxnReceipt .. using sequence.DecodeReceipt(receipt) etc..
return status, receipt.Receipt(), nil, nil // XXXX
}

func (r *RpcRelayer) waitMetaTxnReceipt(ctx context.Context, metaTxnID sequence.MetaTxnID, optTimeout ...time.Duration) (sequence.MetaTxnStatus, *types.Receipt, error) {
func (r *RpcRelayer) waitMetaTxnReceipt(ctx context.Context, metaTxnID sequence.MetaTxnID, optTimeout ...time.Duration) (sequence.MetaTxnStatus, *types.Receipt, *proto.MetaTxnReceipt, error) {
// TODO: in future GetMetaTxnReceipt() will be renamed to WaitTransactionReceipt()

var clear context.CancelFunc
Expand All @@ -264,9 +265,9 @@ func (r *RpcRelayer) waitMetaTxnReceipt(ctx context.Context, metaTxnID sequence.
case <-ctx.Done():
err := ctx.Err()
if err != nil {
return 0, nil, err
return 0, nil, nil, err
}
return 0, nil, nil
return 0, nil, nil, nil
default:
}

Expand All @@ -278,15 +279,15 @@ func (r *RpcRelayer) waitMetaTxnReceipt(ctx context.Context, metaTxnID sequence.
continue
}
if err != nil {
return sequence.MetaTxnStatusUnknown, nil, err
return sequence.MetaTxnStatusUnknown, nil, nil, err
}
txnReceipt := metaTxnReceipt.TxnReceipt
var receipt *types.Receipt
err = json.Unmarshal([]byte(txnReceipt), &receipt)
if err != nil {
return 0, nil, fmt.Errorf("failed to decode txn receipt data: %w", err)
return 0, nil, nil, fmt.Errorf("failed to decode txn receipt data: %w", err)
}
return MetaTxnStatusFromString(metaTxnReceipt.Status), receipt, nil
return MetaTxnStatusFromString(metaTxnReceipt.Status), receipt, metaTxnReceipt, nil
}
}

Expand Down
10 changes: 8 additions & 2 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ import (
"github.com/0xsequence/go-sequence/core"
v1 "github.com/0xsequence/go-sequence/core/v1"
v2 "github.com/0xsequence/go-sequence/core/v2"
"github.com/0xsequence/go-sequence/relayer/proto"
)

var zeroAddress = common.Address{}

func DeploySequenceWallet(sender *ethwallet.Wallet, walletConfig core.WalletConfig, walletContext WalletContext) (common.Address, *types.Transaction, ethtxn.WaitReceipt, error) {
func DeploySequenceWallet(sender *ethwallet.Wallet, walletConfig core.WalletConfig, walletContext WalletContext) (common.Address, *types.Transaction, WaitReceipt, error) {
if sender.GetProvider() == nil {
return common.Address{}, nil, nil, ErrProviderNotSet
}
Expand Down Expand Up @@ -48,7 +49,12 @@ func DeploySequenceWallet(sender *ethwallet.Wallet, walletConfig core.WalletConf

tx, waitReceipt, err := sender.SendTransaction(context.Background(), signedDeployTx)

return walletAddress, tx, waitReceipt, nil
metaTxnWaitReceipt := func(ctx context.Context) (*types.Receipt, *proto.MetaTxnReceipt, error) {
receipt, err := waitReceipt(ctx)
return receipt, nil, err
}

return walletAddress, tx, metaTxnWaitReceipt, err
}

func EncodeWalletDeployment(walletConfig core.WalletConfig, walletContext WalletContext) (common.Address, common.Address, []byte, error) {
Expand Down
4 changes: 2 additions & 2 deletions utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestDeploySequenceWallet(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, tx)

receipt, err := waitReceipt(context.Background())
receipt, _, err := waitReceipt(context.Background())
assert.NoError(t, err)
assert.True(t, receipt.Status == types.ReceiptStatusSuccessful)

Expand Down Expand Up @@ -77,7 +77,7 @@ func TestDeploySequenceWallet(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, tx)

receipt, err := waitReceipt(context.Background())
receipt, _, err := waitReceipt(context.Background())
assert.NoError(t, err)
assert.True(t, receipt.Status == types.ReceiptStatusSuccessful)

Expand Down
7 changes: 3 additions & 4 deletions wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (

"github.com/0xsequence/ethkit/ethcoder"
"github.com/0xsequence/ethkit/ethrpc"
"github.com/0xsequence/ethkit/ethtxn"
"github.com/0xsequence/ethkit/go-ethereum/common"
"github.com/0xsequence/ethkit/go-ethereum/core/types"
"github.com/0xsequence/go-sequence/core"
Expand Down Expand Up @@ -577,11 +576,11 @@ func (w *Wallet[C]) SignTransactions(ctx context.Context, txns Transactions) (*S
}, nil
}

func (w *Wallet[C]) SendTransaction(ctx context.Context, signedTxns *SignedTransactions, feeQuote ...*RelayerFeeQuote) (MetaTxnID, *types.Transaction, ethtxn.WaitReceipt, error) {
func (w *Wallet[C]) SendTransaction(ctx context.Context, signedTxns *SignedTransactions, feeQuote ...*RelayerFeeQuote) (MetaTxnID, *types.Transaction, WaitReceipt, error) {
return w.SendTransactions(ctx, signedTxns, feeQuote...)
}

func (w *Wallet[C]) SendTransactions(ctx context.Context, signedTxns *SignedTransactions, feeQuote ...*RelayerFeeQuote) (MetaTxnID, *types.Transaction, ethtxn.WaitReceipt, error) {
func (w *Wallet[C]) SendTransactions(ctx context.Context, signedTxns *SignedTransactions, feeQuote ...*RelayerFeeQuote) (MetaTxnID, *types.Transaction, WaitReceipt, error) {
if w.relayer == nil {
return "", nil, nil, ErrRelayerNotSet
}
Expand Down Expand Up @@ -654,7 +653,7 @@ func (w *Wallet[C]) IsDeployed() (bool, error) {
return IsWalletDeployed(w.provider, w.Address())
}

func (w *Wallet[C]) Deploy(ctx context.Context) (MetaTxnID, *types.Transaction, ethtxn.WaitReceipt, error) {
func (w *Wallet[C]) Deploy(ctx context.Context) (MetaTxnID, *types.Transaction, WaitReceipt, error) {
if w.relayer == nil {
return "", nil, nil, ErrRelayerNotSet
}
Expand Down

0 comments on commit 73f9eff

Please sign in to comment.