From 1388bcab37fa64be6c1e75fd86bf823ae3779579 Mon Sep 17 00:00:00 2001 From: Renan Date: Tue, 23 Sep 2025 12:36:46 -0300 Subject: [PATCH] refactor(backport): prepare the client interfaces used by the observer-signers for dry-mode (#4213) refactor: prepare the client interfaces of the observer-signers for dry-mode --- changelog.md | 1 + cmd/zetatool/cctx/inbound.go | 5 +- cmd/zetatool/cctx/outbound.go | 6 +- scripts/mocks-generate.sh | 5 +- zetaclient/chains/base/observer.go | 14 +- zetaclient/chains/base/observer_test.go | 8 +- zetaclient/chains/base/signer.go | 10 +- zetaclient/chains/bitcoin/client.go | 13 + zetaclient/chains/bitcoin/common/fee.go | 19 +- zetaclient/chains/bitcoin/observer/db.go | 2 +- .../chains/bitcoin/observer/gas_price.go | 6 +- zetaclient/chains/bitcoin/observer/inbound.go | 6 +- .../chains/bitcoin/observer/inbound_test.go | 2 +- .../bitcoin/observer/inbound_tracker.go | 6 +- zetaclient/chains/bitcoin/observer/mempool.go | 6 +- .../chains/bitcoin/observer/observer.go | 84 +-- .../chains/bitcoin/observer/observer_test.go | 76 +-- .../chains/bitcoin/observer/outbound.go | 11 +- .../chains/bitcoin/observer/outbound_test.go | 10 +- zetaclient/chains/bitcoin/observer/utxos.go | 2 +- zetaclient/chains/bitcoin/observer/witness.go | 8 +- .../chains/bitcoin/signer/fee_bumper.go | 24 +- .../chains/bitcoin/signer/fee_bumper_test.go | 2 +- zetaclient/chains/bitcoin/signer/sign_rbf.go | 4 +- zetaclient/chains/bitcoin/signer/signer.go | 29 +- .../bitcoin/signer/signer_keysign_test.go | 6 +- .../chains/bitcoin/signer/signer_test.go | 2 +- zetaclient/chains/evm/client.go | 11 + zetaclient/chains/evm/client/client.go | 24 +- .../{client_live_test.go => client_test.go} | 0 zetaclient/chains/evm/evm.go | 3 +- .../chains/evm/observer/inbound_test.go | 8 +- zetaclient/chains/evm/observer/observer.go | 56 +- .../chains/evm/observer/observer_test.go | 22 +- zetaclient/chains/evm/observer/outbound.go | 5 +- .../evm/signer/outbound_tracker_reporter.go | 2 +- zetaclient/chains/evm/signer/sign_test.go | 2 +- zetaclient/chains/evm/signer/signer.go | 47 +- zetaclient/chains/evm/signer/signer_test.go | 2 +- zetaclient/chains/interfaces/interfaces.go | 189 ------ zetaclient/chains/interfaces/tss.go | 27 + zetaclient/chains/interfaces/zetacore.go | 122 ++++ zetaclient/chains/solana/client.go | 16 + zetaclient/chains/solana/observer/inbound.go | 23 +- .../chains/solana/observer/inbound_tracker.go | 6 +- zetaclient/chains/solana/observer/observer.go | 89 ++- .../chains/solana/observer/observer_gas.go | 4 +- .../chains/solana/observer/observer_test.go | 12 +- zetaclient/chains/solana/observer/outbound.go | 7 +- .../chains/solana/observer/outbound_test.go | 8 +- .../solana/{rpc/rpc.go => repo/repo.go} | 113 ++-- .../rpc_live_test.go => repo/repo_test.go} | 40 +- zetaclient/chains/solana/signer/execute.go | 26 +- .../chains/solana/signer/execute_spl.go | 42 +- .../chains/solana/signer/fallback_tx_test.go | 4 +- .../chains/solana/signer/increment_nonce.go | 12 +- .../signer/outbound_tracker_reporter.go | 6 +- zetaclient/chains/solana/signer/signer.go | 97 ++- .../chains/solana/signer/signer_test.go | 68 +- zetaclient/chains/solana/signer/whitelist.go | 26 +- zetaclient/chains/solana/signer/withdraw.go | 14 +- .../chains/solana/signer/withdraw_spl.go | 38 +- zetaclient/chains/sui/client.go | 11 + zetaclient/chains/sui/client/client.go | 11 +- .../chains/sui/client/client_live_test.go | 2 +- zetaclient/chains/sui/observer/inbound.go | 6 +- zetaclient/chains/sui/observer/observer.go | 26 +- .../chains/sui/observer/observer_test.go | 2 +- zetaclient/chains/sui/observer/outbound.go | 5 +- zetaclient/chains/sui/signer/signer.go | 59 +- zetaclient/chains/sui/signer/signer_test.go | 2 +- .../chains/sui/signer/signer_tracker.go | 4 +- zetaclient/chains/sui/signer/signer_tx.go | 10 +- .../chains/sui/signer/tss_owned_object.go | 2 +- .../chains/sui/signer/withdraw_and_call.go | 4 +- zetaclient/chains/ton/client.go | 11 + zetaclient/chains/ton/observer/inbound.go | 6 +- zetaclient/chains/ton/observer/observer.go | 66 +- .../chains/ton/observer/observer_test.go | 4 +- zetaclient/chains/ton/observer/outbound.go | 5 +- .../chains/ton/observer/outbound_test.go | 2 +- .../{client_live_test.go => client_test.go} | 2 +- zetaclient/chains/ton/signer/signer.go | 30 +- .../chains/ton/signer/signer_tracker.go | 2 +- zetaclient/orchestrator/bootstrap.go | 35 +- zetaclient/orchestrator/bootstrap_test.go | 2 +- zetaclient/orchestrator/orchestrator_test.go | 2 +- .../preflight_metrics_reporter.go | 8 +- .../mocks/{evm_rpc.go => evm_client.go} | 136 ++-- zetaclient/testutils/mocks/zetacore_client.go | 590 +++++++++--------- zetaclient/zetacore/client_crosschain.go | 19 +- zetaclient/zetacore/client_test.go | 9 +- 92 files changed, 1415 insertions(+), 1196 deletions(-) create mode 100644 zetaclient/chains/bitcoin/client.go create mode 100644 zetaclient/chains/evm/client.go rename zetaclient/chains/evm/client/{client_live_test.go => client_test.go} (100%) delete mode 100644 zetaclient/chains/interfaces/interfaces.go create mode 100644 zetaclient/chains/interfaces/tss.go create mode 100644 zetaclient/chains/interfaces/zetacore.go create mode 100644 zetaclient/chains/solana/client.go rename zetaclient/chains/solana/{rpc/rpc.go => repo/repo.go} (52%) rename zetaclient/chains/solana/{rpc/rpc_live_test.go => repo/repo_test.go} (77%) create mode 100644 zetaclient/chains/sui/client.go create mode 100644 zetaclient/chains/ton/client.go rename zetaclient/chains/ton/rpc/{client_live_test.go => client_test.go} (99%) rename zetaclient/testutils/mocks/{evm_rpc.go => evm_client.go} (76%) diff --git a/changelog.md b/changelog.md index 39b82f4212..e8cb0719fa 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,7 @@ * [4144](https://github.com/zeta-chain/node/pull/4144) - standardize structured logging for zetaclient * [4180](https://github.com/zeta-chain/node/pull/4180) - remove unused loggers and log fields * [4174](https://github.com/zeta-chain/node/pull/4174) - add documentation for ZetaClient logging fields +* [4213](https://github.com/zeta-chain/node/pull/4213) - prepare the client interfaces of the observer-signers for dry mode ### Fixes diff --git a/cmd/zetatool/cctx/inbound.go b/cmd/zetatool/cctx/inbound.go index c41abcbd2a..e9d5d56374 100644 --- a/cmd/zetatool/cctx/inbound.go +++ b/cmd/zetatool/cctx/inbound.go @@ -21,7 +21,7 @@ import ( "github.com/zeta-chain/node/zetaclient/chains/bitcoin/client" zetaevmclient "github.com/zeta-chain/node/zetaclient/chains/evm/client" "github.com/zeta-chain/node/zetaclient/chains/solana/observer" - solanarpc "github.com/zeta-chain/node/zetaclient/chains/solana/rpc" + solrepo "github.com/zeta-chain/node/zetaclient/chains/solana/repo" zetaclientConfig "github.com/zeta-chain/node/zetaclient/config" ) @@ -297,13 +297,14 @@ func (c *TrackingDetails) solanaInboundBallotIdentifier(ctx *context.Context) er if solClient == nil { return fmt.Errorf("error creating rpc client") } + solRepo := solrepo.New(solClient) signature, err := solana.SignatureFromBase58(inboundHash) if err != nil { return fmt.Errorf("error parsing signature: %w", err) } - txResult, err := solanarpc.GetTransaction(goCtx, solClient, signature) + txResult, err := solRepo.GetTransaction(goCtx, signature) if err != nil { return fmt.Errorf("error getting transaction: %w", err) } diff --git a/cmd/zetatool/cctx/outbound.go b/cmd/zetatool/cctx/outbound.go index fbdb85c6c3..a596229675 100644 --- a/cmd/zetatool/cctx/outbound.go +++ b/cmd/zetatool/cctx/outbound.go @@ -13,7 +13,7 @@ import ( "github.com/zeta-chain/node/pkg/chains" "github.com/zeta-chain/node/zetaclient/chains/bitcoin/client" zetaevmclient "github.com/zeta-chain/node/zetaclient/chains/evm/client" - solanarpc "github.com/zeta-chain/node/zetaclient/chains/solana/rpc" + solrepo "github.com/zeta-chain/node/zetaclient/chains/solana/repo" zetaclientConfig "github.com/zeta-chain/node/zetaclient/config" ) @@ -96,9 +96,11 @@ func (c *TrackingDetails) checkSolanaOutboundTx(ctx *context.Context) error { if solClient == nil { return fmt.Errorf("error creating rpc client") } + solRepo := solrepo.New(solClient) + for _, hash := range txHashList { signature := solana.MustSignatureFromBase58(hash) - _, err := solanarpc.GetTransaction(goCtx, solClient, signature) + _, err := solRepo.GetTransaction(goCtx, signature) if err != nil { continue } diff --git a/scripts/mocks-generate.sh b/scripts/mocks-generate.sh index 39105c3700..1b642f36e2 100644 --- a/scripts/mocks-generate.sh +++ b/scripts/mocks-generate.sh @@ -7,8 +7,9 @@ go install github.com/vektra/mockery/v2@v2.53.3 MOCK_DIRS=( "./testutil/keeper/mocks" - "./zetaclient/chains/bitcoin/client" "./zetaclient/chains/interfaces" + "./zetaclient/chains/bitcoin/client" + "./zetaclient/chains/evm/observer" "./zetaclient/chains/ton/observer" "./zetaclient/chains/ton/signer" "./zetaclient/testutils/mocks" @@ -19,4 +20,4 @@ for dir in "${MOCK_DIRS[@]}"; do done # Print a message to indicate completion -echo "Mocks generated." \ No newline at end of file +echo "Mocks generated." diff --git a/zetaclient/chains/base/observer.go b/zetaclient/chains/base/observer.go index 07b90e9d41..b640dcef3e 100644 --- a/zetaclient/chains/base/observer.go +++ b/zetaclient/chains/base/observer.go @@ -46,8 +46,8 @@ type Observer struct { // zetacoreClient is the client to interact with ZetaChain zetacoreClient interfaces.ZetacoreClient - // tss is the TSS signer - tss interfaces.TSSSigner + // tssSigner is the TSS signer + tssSigner interfaces.TSSSigner // lastBlock is the last block height of the observed chain lastBlock uint64 @@ -83,7 +83,7 @@ func NewObserver( chain chains.Chain, chainParams observertypes.ChainParams, zetacoreClient interfaces.ZetacoreClient, - tss interfaces.TSSSigner, + tssSigner interfaces.TSSSigner, blockCacheSize int, ts *metrics.TelemetryServer, database *db.DB, @@ -98,7 +98,7 @@ func NewObserver( chain: chain, chainParams: chainParams, zetacoreClient: zetacoreClient, - tss: tss, + tssSigner: tssSigner, lastBlock: 0, lastBlockScanned: 0, lastTxScanned: "", @@ -183,7 +183,7 @@ func (ob *Observer) ZetacoreClient() interfaces.ZetacoreClient { // TSS returns the tss signer for the observer. func (ob *Observer) TSS() interfaces.TSSSigner { - return ob.tss + return ob.tssSigner } // TSSAddressString returns the TSS address for the chain. @@ -192,13 +192,13 @@ func (ob *Observer) TSS() interfaces.TSSSigner { func (ob *Observer) TSSAddressString() string { switch ob.chain.Consensus { case chains.Consensus_bitcoin: - address, err := ob.tss.PubKey().AddressBTC(ob.Chain().ChainId) + address, err := ob.tssSigner.PubKey().AddressBTC(ob.Chain().ChainId) if err != nil { return "" } return address.EncodeAddress() default: - return ob.tss.PubKey().AddressEVM().String() + return ob.tssSigner.PubKey().AddressEVM().String() } } diff --git a/zetaclient/chains/base/observer_test.go b/zetaclient/chains/base/observer_test.go index c0f4f2e94c..fe9a8015f4 100644 --- a/zetaclient/chains/base/observer_test.go +++ b/zetaclient/chains/base/observer_test.go @@ -113,7 +113,7 @@ func TestNewObserver(t *testing.T) { chainParams observertypes.ChainParams appContext *zctx.AppContext zetacoreClient interfaces.ZetacoreClient - tss interfaces.TSSSigner + tssSigner interfaces.TSSSigner blockCacheSize int fail bool message string @@ -124,7 +124,7 @@ func TestNewObserver(t *testing.T) { chainParams: chainParams, appContext: appContext, zetacoreClient: zetacoreClient, - tss: tss, + tssSigner: tss, blockCacheSize: blockCacheSize, fail: false, }, @@ -134,7 +134,7 @@ func TestNewObserver(t *testing.T) { chainParams: chainParams, appContext: appContext, zetacoreClient: zetacoreClient, - tss: tss, + tssSigner: tss, blockCacheSize: 0, fail: true, message: "error creating block cache", @@ -148,7 +148,7 @@ func TestNewObserver(t *testing.T) { tt.chain, tt.chainParams, tt.zetacoreClient, - tt.tss, + tt.tssSigner, tt.blockCacheSize, nil, database, diff --git a/zetaclient/chains/base/signer.go b/zetaclient/chains/base/signer.go index 3c7a62b6d8..c2a8667f13 100644 --- a/zetaclient/chains/base/signer.go +++ b/zetaclient/chains/base/signer.go @@ -20,8 +20,8 @@ type Signer struct { // chain contains static information about the external chain chain chains.Chain - // tss is the TSS signer - tss interfaces.TSSSigner + // tssSigner is the TSS signer + tssSigner interfaces.TSSSigner // logger contains the loggers used by signer logger Logger @@ -37,7 +37,7 @@ type Signer struct { } // NewSigner creates a new base signer. -func NewSigner(chain chains.Chain, tss interfaces.TSSSigner, logger Logger) *Signer { +func NewSigner(chain chains.Chain, tssSigner interfaces.TSSSigner, logger Logger) *Signer { withLogFields := func(log zerolog.Logger) zerolog.Logger { return log.With(). Str(logs.FieldModule, logs.ModNameSigner). @@ -47,7 +47,7 @@ func NewSigner(chain chains.Chain, tss interfaces.TSSSigner, logger Logger) *Sig return &Signer{ chain: chain, - tss: tss, + tssSigner: tssSigner, outboundBeingReported: make(map[string]bool), activeOutbounds: make(map[string]time.Time), logger: Logger{ @@ -64,7 +64,7 @@ func (s *Signer) Chain() chains.Chain { // TSS returns the tss signer for the signer. func (s *Signer) TSS() interfaces.TSSSigner { - return s.tss + return s.tssSigner } // Logger returns the logger for the signer. diff --git a/zetaclient/chains/bitcoin/client.go b/zetaclient/chains/bitcoin/client.go new file mode 100644 index 0000000000..27eca2a6c1 --- /dev/null +++ b/zetaclient/chains/bitcoin/client.go @@ -0,0 +1,13 @@ +package bitcoin + +import ( + "github.com/zeta-chain/node/zetaclient/chains/bitcoin/common" + "github.com/zeta-chain/node/zetaclient/chains/bitcoin/observer" + "github.com/zeta-chain/node/zetaclient/chains/bitcoin/signer" +) + +type Client interface { + common.BitcoinClient + signer.BitcoinClient + observer.BitcoinClient +} diff --git a/zetaclient/chains/bitcoin/common/fee.go b/zetaclient/chains/bitcoin/common/fee.go index 0e0a8ae521..b35ca2e014 100644 --- a/zetaclient/chains/bitcoin/common/fee.go +++ b/zetaclient/chains/bitcoin/common/fee.go @@ -57,7 +57,7 @@ var ( DefaultDepositorFee = DepositorFee(defaultDepositorFeeRate) ) -type RPC interface { +type BitcoinClient interface { GetBlockCount(ctx context.Context) (int64, error) GetBlockHash(ctx context.Context, blockHeight int64) (*chainhash.Hash, error) GetBlockHeader(ctx context.Context, hash *chainhash.Hash) (*wire.BlockHeader, error) @@ -66,7 +66,7 @@ type RPC interface { } // DepositorFeeCalculator is a function type to calculate the Bitcoin depositor fee -type DepositorFeeCalculator func(context.Context, RPC, *btcjson.TxRawResult, *chaincfg.Params) (float64, error) +type DepositorFeeCalculator func(context.Context, BitcoinClient, *btcjson.TxRawResult, *chaincfg.Params) (float64, error) // FeeRateToSatPerByte converts a fee rate from BTC/KB to sat/vB. func FeeRateToSatPerByte(rate float64) (uint64, error) { @@ -237,7 +237,7 @@ func CalcBlockAvgFeeRate(blockVb *btcjson.GetBlockVerboseTxResult, netParams *ch // CalcDepositorFee calculates the depositor fee for a given tx result func CalcDepositorFee( ctx context.Context, - rpc RPC, + bitcoinClient BitcoinClient, rawResult *btcjson.TxRawResult, netParams *chaincfg.Params, ) (float64, error) { @@ -247,7 +247,7 @@ func CalcDepositorFee( } // get fee rate of the transaction - _, feeRate, err := rpc.GetTransactionFeeAndRate(ctx, rawResult) + _, feeRate, err := bitcoinClient.GetTransactionFeeAndRate(ctx, rawResult) if err != nil { return 0, errors.Wrapf(err, "error getting fee rate for tx %s", rawResult.Txid) } @@ -261,14 +261,17 @@ func CalcDepositorFee( // GetRecentFeeRate gets the highest fee rate from recent blocks // Note: this method should be used for testnet ONLY -func GetRecentFeeRate(ctx context.Context, rpc RPC, netParams *chaincfg.Params) (uint64, error) { +func GetRecentFeeRate(ctx context.Context, + bitcoinClient BitcoinClient, + netParams *chaincfg.Params, +) (uint64, error) { // should avoid using this method for mainnet if netParams.Name == chaincfg.MainNetParams.Name { return 0, errors.New("GetRecentFeeRate should not be used for mainnet") } // get the current block number - blockNumber, err := rpc.GetBlockCount(ctx) + blockNumber, err := bitcoinClient.GetBlockCount(ctx) if err != nil { return 0, err } @@ -277,11 +280,11 @@ func GetRecentFeeRate(ctx context.Context, rpc RPC, netParams *chaincfg.Params) highestRate := int64(0) for i := int64(0); i < feeRateCountBackBlocks; i++ { // get the block - hash, err := rpc.GetBlockHash(ctx, blockNumber-i) + hash, err := bitcoinClient.GetBlockHash(ctx, blockNumber-i) if err != nil { return 0, err } - block, err := rpc.GetBlockVerbose(ctx, hash) + block, err := bitcoinClient.GetBlockVerbose(ctx, hash) if err != nil { return 0, err } diff --git a/zetaclient/chains/bitcoin/observer/db.go b/zetaclient/chains/bitcoin/observer/db.go index 0f4caa70e1..71b406afec 100644 --- a/zetaclient/chains/bitcoin/observer/db.go +++ b/zetaclient/chains/bitcoin/observer/db.go @@ -42,7 +42,7 @@ func (ob *Observer) LoadLastBlockScanned(ctx context.Context) error { // 1. environment variable is set explicitly to "latest" // 2. environment variable is empty and last scanned block is not found in DB if ob.LastBlockScanned() == 0 { - blockNumber, err := ob.rpc.GetBlockCount(ctx) + blockNumber, err := ob.bitcoinClient.GetBlockCount(ctx) if err != nil { return errors.Wrap(err, "unable to get block count") } diff --git a/zetaclient/chains/bitcoin/observer/gas_price.go b/zetaclient/chains/bitcoin/observer/gas_price.go index bfdaa136a2..dd64aa7e16 100644 --- a/zetaclient/chains/bitcoin/observer/gas_price.go +++ b/zetaclient/chains/bitcoin/observer/gas_price.go @@ -25,12 +25,12 @@ func (ob *Observer) PostGasPrice(ctx context.Context) error { feeRateEstimated = client.FeeRateRegnet case chains.NetworkType_testnet: // testnet RPC 'EstimateSmartFee' can return unreasonable high fee rate - feeRateEstimated, err = common.GetRecentFeeRate(ctx, ob.rpc, ob.netParams) + feeRateEstimated, err = common.GetRecentFeeRate(ctx, ob.bitcoinClient, ob.netParams) if err != nil { return errors.Wrapf(err, "unable to get recent fee rate") } case chains.NetworkType_mainnet: - feeRateEstimated, err = ob.rpc.GetEstimatedFeeRate(ctx, 1) + feeRateEstimated, err = ob.bitcoinClient.GetEstimatedFeeRate(ctx, 1) if err != nil { return errors.Wrap(err, "unable to get estimated fee rate") } @@ -39,7 +39,7 @@ func (ob *Observer) PostGasPrice(ctx context.Context) error { } // query the current block number - blockNumber, err := ob.rpc.GetBlockCount(ctx) + blockNumber, err := ob.bitcoinClient.GetBlockCount(ctx) if err != nil { return errors.Wrap(err, "GetBlockCount error") } diff --git a/zetaclient/chains/bitcoin/observer/inbound.go b/zetaclient/chains/bitcoin/observer/inbound.go index 51c2954ab9..4615287e76 100644 --- a/zetaclient/chains/bitcoin/observer/inbound.go +++ b/zetaclient/chains/bitcoin/observer/inbound.go @@ -92,7 +92,7 @@ func (ob *Observer) observeInboundInBlockRange(ctx context.Context, startBlock, // #nosec G115 always positive events, err := FilterAndParseIncomingTx( ctx, - ob.rpc, + ob.bitcoinClient, res.Block.Tx, uint64(res.Block.Height), tssAddress, @@ -142,7 +142,7 @@ func (ob *Observer) observeInboundInBlockRange(ctx context.Context, startBlock, // vout1: OP_RETURN memo, base64 encoded func FilterAndParseIncomingTx( ctx context.Context, - rpc RPC, + bitcoinClient BitcoinClient, txs []btcjson.TxRawResult, blockNumber uint64, tssAddress string, @@ -159,7 +159,7 @@ func FilterAndParseIncomingTx( event, err := GetBtcEventWithWitness( ctx, - rpc, + bitcoinClient, tx, tssAddress, blockNumber, diff --git a/zetaclient/chains/bitcoin/observer/inbound_test.go b/zetaclient/chains/bitcoin/observer/inbound_test.go index 0ad7492a00..c416ba2086 100644 --- a/zetaclient/chains/bitcoin/observer/inbound_test.go +++ b/zetaclient/chains/bitcoin/observer/inbound_test.go @@ -31,7 +31,7 @@ import ( // mockDepositFeeCalculator returns a mock depositor fee calculator that returns the given fee and error. func mockDepositFeeCalculator(fee float64, err error) common.DepositorFeeCalculator { - return func(_ context.Context, _ common.RPC, _ *btcjson.TxRawResult, _ *chaincfg.Params) (float64, error) { + return func(_ context.Context, _ common.BitcoinClient, _ *btcjson.TxRawResult, _ *chaincfg.Params) (float64, error) { return fee, err } } diff --git a/zetaclient/chains/bitcoin/observer/inbound_tracker.go b/zetaclient/chains/bitcoin/observer/inbound_tracker.go index e4f7738ad5..2939cc5e3b 100644 --- a/zetaclient/chains/bitcoin/observer/inbound_tracker.go +++ b/zetaclient/chains/bitcoin/observer/inbound_tracker.go @@ -39,7 +39,7 @@ func (ob *Observer) CheckReceiptForBtcTxHash(ctx context.Context, txHash string, return "", errors.Wrap(err, "error parsing btc tx hash") } - tx, err := ob.rpc.GetRawTransactionVerbose(ctx, hash) + tx, err := ob.bitcoinClient.GetRawTransactionVerbose(ctx, hash) if err != nil { return "", errors.Wrap(err, "error getting btc raw tx verbose") } @@ -49,7 +49,7 @@ func (ob *Observer) CheckReceiptForBtcTxHash(ctx context.Context, txHash string, return "", errors.Wrap(err, "error parsing btc block hash") } - blockVb, err := ob.rpc.GetBlockVerbose(ctx, blockHash) + blockVb, err := ob.bitcoinClient.GetBlockVerbose(ctx, blockHash) if err != nil { return "", errors.Wrap(err, "error getting btc block verbose") } @@ -72,7 +72,7 @@ func (ob *Observer) CheckReceiptForBtcTxHash(ctx context.Context, txHash string, // #nosec G115 always positive event, err := GetBtcEventWithWitness( ctx, - ob.rpc, + ob.bitcoinClient, *tx, tss, uint64(blockVb.Height), diff --git a/zetaclient/chains/bitcoin/observer/mempool.go b/zetaclient/chains/bitcoin/observer/mempool.go index 9762238dc9..892705c379 100644 --- a/zetaclient/chains/bitcoin/observer/mempool.go +++ b/zetaclient/chains/bitcoin/observer/mempool.go @@ -62,7 +62,7 @@ func (ob *Observer) refreshLastStuckOutbound(ctx context.Context) error { Msg("checking last TSS outbound") // step 2: is last tx stuck in mempool? - stuck, stuckFor, err := ob.rpc.IsTxStuckInMempool(ctx, lastTxHash, ob.feeBumpWaitBlocks) + stuck, stuckFor, err := ob.bitcoinClient.IsTxStuckInMempool(ctx, lastTxHash, ob.feeBumpWaitBlocks) if err != nil { return errors.Wrapf(err, "cannot determine if tx %s nonce %d is stuck", lastTxHash, lastNonce) } @@ -156,7 +156,7 @@ func (ob *Observer) getLastPendingOutbound(ctx context.Context) (tx *btcutil.Tx, } // is tx in the mempool? - if _, err = ob.rpc.GetMempoolEntry(ctx, lastHash); err != nil { + if _, err = ob.bitcoinClient.GetMempoolEntry(ctx, lastHash); err != nil { return nil, 0, errors.Wrapf(err, "last tx %s is not in mempool", lastHash) } @@ -175,7 +175,7 @@ func (ob *Observer) getLastPendingOutbound(ctx context.Context) (tx *btcutil.Tx, // 1. it can fetch both stuck tx and non-stuck tx as far as they are valid txs. // 2. it never fetch invalid tx (e.g., old tx replaced by RBF), so we can exclude invalid ones. // 3. zetaclient needs the original tx body of a stuck tx to bump its fee and sign again. - lastTx, err := ob.rpc.GetRawTransactionByStr(ctx, lastHash) + lastTx, err := ob.bitcoinClient.GetRawTransactionByStr(ctx, lastHash) if err != nil { return nil, 0, errors.Wrapf(err, "GetRawTransactionByStr failed for last tx %s nonce %d", lastHash, lastNonce) } diff --git a/zetaclient/chains/bitcoin/observer/observer.go b/zetaclient/chains/bitcoin/observer/observer.go index 4a873a60e1..6d0b6f9b90 100644 --- a/zetaclient/chains/bitcoin/observer/observer.go +++ b/zetaclient/chains/bitcoin/observer/observer.go @@ -21,50 +21,47 @@ import ( "github.com/zeta-chain/node/zetaclient/metrics" ) -type RPC interface { - Healthcheck(ctx context.Context) (time.Time, error) - - GetBlockCount(ctx context.Context) (int64, error) - GetBlockHash(ctx context.Context, blockHeight int64) (*hash.Hash, error) - GetBlockHeader(ctx context.Context, hash *hash.Hash) (*wire.BlockHeader, error) - GetBlockVerbose(ctx context.Context, hash *hash.Hash) (*btcjson.GetBlockVerboseTxResult, error) - - GetRawTransaction(ctx context.Context, hash *hash.Hash) (*btcutil.Tx, error) - GetRawTransactionVerbose(ctx context.Context, hash *hash.Hash) (*btcjson.TxRawResult, error) - GetRawTransactionResult( - ctx context.Context, - hash *hash.Hash, - res *btcjson.GetTransactionResult, +type BitcoinClient interface { + Healthcheck(context.Context) (time.Time, error) + + GetBlockCount(context.Context) (int64, error) + GetBlockHash(_ context.Context, blockHeight int64) (*hash.Hash, error) + GetBlockHeader(context.Context, *hash.Hash) (*wire.BlockHeader, error) + GetBlockVerbose(context.Context, *hash.Hash) (*btcjson.GetBlockVerboseTxResult, error) + + GetRawTransaction(context.Context, *hash.Hash) (*btcutil.Tx, error) + GetRawTransactionVerbose(context.Context, *hash.Hash) (*btcjson.TxRawResult, error) + GetRawTransactionResult(context.Context, + *hash.Hash, + *btcjson.GetTransactionResult, ) (btcjson.TxRawResult, error) - GetMempoolEntry(ctx context.Context, txHash string) (*btcjson.GetMempoolEntryResult, error) + GetMempoolEntry(_ context.Context, txHash string) (*btcjson.GetMempoolEntryResult, error) - GetEstimatedFeeRate(ctx context.Context, confTarget int64) (uint64, error) - GetTransactionFeeAndRate(ctx context.Context, tx *btcjson.TxRawResult) (int64, int64, error) + GetEstimatedFeeRate(_ context.Context, confTarget int64) (uint64, error) + GetTransactionFeeAndRate(_ context.Context, tx *btcjson.TxRawResult) (int64, int64, error) - IsTxStuckInMempool( - ctx context.Context, + IsTxStuckInMempool(_ context.Context, txHash string, maxWaitBlocks int64, ) (stuck bool, pendingFor time.Duration, err error) - EstimateSmartFee( - ctx context.Context, + EstimateSmartFee(_ context.Context, confTarget int64, - mode *btcjson.EstimateSmartFeeMode, + _ *btcjson.EstimateSmartFeeMode, ) (*btcjson.EstimateSmartFeeResult, error) - ListUnspentMinMaxAddresses( - ctx context.Context, - minConf, maxConf int, - addresses []btcutil.Address, + ListUnspentMinMaxAddresses(_ context.Context, + minConf int, + maxConf int, + _ []btcutil.Address, ) ([]btcjson.ListUnspentResult, error) - GetBlockHeightByStr(ctx context.Context, blockHash string) (int64, error) - GetTransactionByStr(ctx context.Context, hash string) (*hash.Hash, *btcjson.GetTransactionResult, error) - GetRawTransactionByStr(ctx context.Context, hash string) (*btcutil.Tx, error) + GetBlockHeightByStr(_ context.Context, blockHash string) (int64, error) + GetTransactionByStr(_ context.Context, hash string) (*hash.Hash, *btcjson.GetTransactionResult, error) + GetRawTransactionByStr(_ context.Context, hash string) (*btcutil.Tx, error) - GetTransactionInputSpender(ctx context.Context, txid string, vout uint32) (string, error) - GetTransactionInitiator(ctx context.Context, txid string) (string, error) + GetTransactionInputSpender(_ context.Context, txid string, vout uint32) (string, error) + GetTransactionInitiator(_ context.Context, txid string) (string, error) } const ( @@ -101,8 +98,8 @@ type Observer struct { // netParams contains the Bitcoin network parameters netParams *chaincfg.Params - // btcClient is the Bitcoin RPC client that interacts with the Bitcoin node - rpc RPC + // bitcoinClient is the Bitcoin RPC client that interacts with the Bitcoin node + bitcoinClient BitcoinClient // pendingNonce is the outbound artificial pending nonce pendingNonce uint64 @@ -135,7 +132,10 @@ type Observer struct { } // New BTC Observer constructor. -func New(chain chains.Chain, baseObserver *base.Observer, rpc RPC) (*Observer, error) { +func New(baseObserver *base.Observer, + bitcoinClient BitcoinClient, + chain chains.Chain, +) (*Observer, error) { // get the bitcoin network params netParams, err := chains.BitcoinNetParamsFromChainID(chain.ChainId) if err != nil { @@ -151,9 +151,9 @@ func New(chain chains.Chain, baseObserver *base.Observer, rpc RPC) (*Observer, e // create bitcoin observer ob := &Observer{ - Observer: baseObserver, - netParams: netParams, - rpc: rpc, + Observer: baseObserver, + netParams: netParams, + bitcoinClient: bitcoinClient, pendingNonce: 0, feeBumpWaitBlocks: int64(feeBumpWaitBlocks), @@ -214,17 +214,17 @@ func (ob *Observer) GetBlockByNumberCached(ctx context.Context, blockNumber int6 } // Get the block hash - hash, err := ob.rpc.GetBlockHash(ctx, blockNumber) + hash, err := ob.bitcoinClient.GetBlockHash(ctx, blockNumber) if err != nil { return nil, err } // Get the block header - header, err := ob.rpc.GetBlockHeader(ctx, hash) + header, err := ob.bitcoinClient.GetBlockHeader(ctx, hash) if err != nil { return nil, err } // Get the block with verbose transactions - block, err := ob.rpc.GetBlockVerbose(ctx, hash) + block, err := ob.bitcoinClient.GetBlockVerbose(ctx, hash) if err != nil { return nil, err } @@ -293,7 +293,7 @@ func (ob *Observer) CheckRPCStatus(ctx context.Context) error { return nil } - blockTime, err := ob.rpc.Healthcheck(ctx) + blockTime, err := ob.bitcoinClient.Healthcheck(ctx) if err != nil { return errors.Wrap(err, "unable to check rpc health") } @@ -310,7 +310,7 @@ func (ob *Observer) isNodeEnabled() bool { // updateLastBlock is a helper function to update the last block number. // Note: keep last block up-to-date helps to avoid inaccurate confirmation. func (ob *Observer) updateLastBlock(ctx context.Context) error { - blockNumber, err := ob.rpc.GetBlockCount(ctx) + blockNumber, err := ob.bitcoinClient.GetBlockCount(ctx) if err != nil { return errors.Wrapf(err, "error getting block number") } diff --git a/zetaclient/chains/bitcoin/observer/observer_test.go b/zetaclient/chains/bitcoin/observer/observer_test.go index c17f9a05a0..8e876819e2 100644 --- a/zetaclient/chains/bitcoin/observer/observer_test.go +++ b/zetaclient/chains/bitcoin/observer/observer_test.go @@ -77,42 +77,42 @@ func Test_NewObserver(t *testing.T) { // test cases tests := []struct { - name string - chain chains.Chain - btcClient *mocks.BitcoinClient - chainParams observertypes.ChainParams - coreClient interfaces.ZetacoreClient - tss interfaces.TSSSigner - logger base.Logger - ts *metrics.TelemetryServer - errorMessage string - before func() - after func() + name string + chain chains.Chain + btcClient *mocks.BitcoinClient + chainParams observertypes.ChainParams + zetacoreClient interfaces.ZetacoreClient + tssSigner interfaces.TSSSigner + logger base.Logger + ts *metrics.TelemetryServer + errorMessage string + before func() + after func() }{ { - name: "should be able to create observer", - chain: chain, - btcClient: btcClient, - chainParams: params, - coreClient: nil, - tss: mocks.NewTSS(t), + name: "should be able to create observer", + chain: chain, + btcClient: btcClient, + chainParams: params, + zetacoreClient: nil, + tssSigner: mocks.NewTSS(t), }, { - name: "should fail if net params is not found", - chain: chains.Chain{ChainId: 111}, // invalid chain id - btcClient: btcClient, - chainParams: params, - coreClient: nil, - tss: mocks.NewTSS(t), - errorMessage: "unable to get BTC net params", + name: "should fail if net params is not found", + chain: chains.Chain{ChainId: 111}, // invalid chain id + btcClient: btcClient, + chainParams: params, + zetacoreClient: nil, + tssSigner: mocks.NewTSS(t), + errorMessage: "unable to get BTC net params", }, { - name: "should fail if env var us invalid", - chain: chain, - btcClient: btcClient, - chainParams: params, - coreClient: nil, - tss: mocks.NewTSS(t), + name: "should fail if env var us invalid", + chain: chain, + btcClient: btcClient, + chainParams: params, + zetacoreClient: nil, + tssSigner: mocks.NewTSS(t), before: func() { envVar := base.EnvVarLatestBlockByChain(chain) os.Setenv(envVar, "invalid") @@ -143,8 +143,8 @@ func Test_NewObserver(t *testing.T) { baseObserver, err := base.NewObserver( tt.chain, tt.chainParams, - tt.coreClient, - tt.tss, + tt.zetacoreClient, + tt.tssSigner, 100, tt.ts, database, @@ -153,7 +153,7 @@ func Test_NewObserver(t *testing.T) { require.NoError(t, err) // create observer - ob, err := New(tt.chain, baseObserver, tt.btcClient) + ob, err := New(baseObserver, tt.btcClient, tt.chain) if tt.errorMessage != "" { require.ErrorContains(t, err, tt.errorMessage) require.Nil(t, ob) @@ -297,11 +297,11 @@ func newTestSuite(t *testing.T, chain chains.Chain, opts ...opt) *testSuite { client := mocks.NewBitcoinClient(t) zetacore := mocks.NewZetacoreClient(t) - var tss interfaces.TSSSigner + var tssSigner interfaces.TSSSigner if chains.IsBitcoinMainnet(chain.ChainId) { - tss = mocks.NewTSS(t).FakePubKey(testutils.TSSPubKeyMainnet) + tssSigner = mocks.NewTSS(t).FakePubKey(testutils.TSSPubKeyMainnet) } else { - tss = mocks.NewTSS(t).FakePubKey(testutils.TSSPubkeyAthens3) + tssSigner = mocks.NewTSS(t).FakePubKey(testutils.TSSPubkeyAthens3) } // create logger @@ -325,7 +325,7 @@ func newTestSuite(t *testing.T, chain chains.Chain, opts ...opt) *testSuite { chain, chainParams, zetacore, - tss, + tssSigner, 100, &metrics.TelemetryServer{}, database, @@ -333,7 +333,7 @@ func newTestSuite(t *testing.T, chain chains.Chain, opts ...opt) *testSuite { ) require.NoError(t, err) - ob, err := New(chain, baseObserver, client) + ob, err := New(baseObserver, client, chain) require.NoError(t, err) ts := &testSuite{ diff --git a/zetaclient/chains/bitcoin/observer/outbound.go b/zetaclient/chains/bitcoin/observer/outbound.go index bc9c81f6c1..32daa9ea98 100644 --- a/zetaclient/chains/bitcoin/observer/outbound.go +++ b/zetaclient/chains/bitcoin/observer/outbound.go @@ -14,7 +14,6 @@ import ( "github.com/zeta-chain/node/pkg/constant" crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" "github.com/zeta-chain/node/zetaclient/chains/bitcoin/common" - "github.com/zeta-chain/node/zetaclient/chains/interfaces" "github.com/zeta-chain/node/zetaclient/compliance" "github.com/zeta-chain/node/zetaclient/logs" "github.com/zeta-chain/node/zetaclient/zetacore" @@ -28,7 +27,7 @@ const ( func (ob *Observer) ProcessOutboundTrackers(ctx context.Context) error { chainID := ob.Chain().ChainId - trackers, err := ob.ZetacoreClient().GetAllOutboundTrackerByChain(ctx, chainID, interfaces.Ascending) + trackers, err := ob.ZetacoreClient().GetOutboundTrackers(ctx, chainID) if err != nil { return errors.Wrap(err, "unable to get all outbound trackers") } @@ -158,7 +157,7 @@ func (ob *Observer) VoteOutboundIfConfirmed(ctx context.Context, cctx *crosschai } // Get outbound block height - blockHeight, err := ob.rpc.GetBlockHeightByStr(ctx, res.BlockHash) + blockHeight, err := ob.bitcoinClient.GetBlockHeightByStr(ctx, res.BlockHash) if err != nil { return false, errors.Wrapf(err, "error getting block height by hash %s", res.BlockHash) } @@ -259,7 +258,7 @@ func (ob *Observer) getOutboundHashByNonce(ctx context.Context, nonce uint64) (s } // make sure it's a real Bitcoin txid - _, getTxResult, err := ob.rpc.GetTransactionByStr(ctx, txid) + _, getTxResult, err := ob.bitcoinClient.GetTransactionByStr(ctx, txid) switch { case err != nil: return "", errors.Wrapf(err, "error getting outbound result for nonce %d hash %s", nonce, txid) @@ -284,7 +283,7 @@ func (ob *Observer) checkTxInclusion( Logger() // fetch tx result - hash, txResult, err := ob.rpc.GetTransactionByStr(ctx, txHash) + hash, txResult, err := ob.bitcoinClient.GetTransactionByStr(ctx, txHash) if err != nil { logger.Warn().Err(err).Msg("call to GetTransactionByStr failed") return nil, false @@ -381,7 +380,7 @@ func (ob *Observer) checkTssOutboundResult( ) error { params := cctx.GetCurrentOutboundParam() nonce := params.TssNonce - rawResult, err := ob.rpc.GetRawTransactionResult(ctx, hash, res) + rawResult, err := ob.bitcoinClient.GetRawTransactionResult(ctx, hash, res) if err != nil { return errors.Wrapf(err, "checkTssOutboundResult: error GetRawTransactionResult %s", hash.String()) } diff --git a/zetaclient/chains/bitcoin/observer/outbound_test.go b/zetaclient/chains/bitcoin/observer/outbound_test.go index d01fe2a757..820a432c72 100644 --- a/zetaclient/chains/bitcoin/observer/outbound_test.go +++ b/zetaclient/chains/bitcoin/observer/outbound_test.go @@ -18,13 +18,13 @@ import ( ) // MockBTCObserverMainnet creates a mock Bitcoin mainnet observer for testing -func MockBTCObserverMainnet(t *testing.T, tss interfaces.TSSSigner) *Observer { +func MockBTCObserverMainnet(t *testing.T, tssSigner interfaces.TSSSigner) *Observer { // setup mock arguments chain := chains.BitcoinMainnet params := mocks.MockChainParams(chain.ChainId, 10) - if tss == nil { - tss = mocks.NewTSS(t).FakePubKey(testutils.TSSPubKeyMainnet) + if tssSigner == nil { + tssSigner = mocks.NewTSS(t).FakePubKey(testutils.TSSPubKeyMainnet) } // create mock rpc client @@ -37,11 +37,11 @@ func MockBTCObserverMainnet(t *testing.T, tss interfaces.TSSSigner) *Observer { logger := zerolog.New(zerolog.NewTestWriter(t)) baseLogger := base.Logger{Std: logger, Compliance: logger} - baseObserver, err := base.NewObserver(chain, params, nil, tss, 100, nil, database, baseLogger) + baseObserver, err := base.NewObserver(chain, params, nil, tssSigner, 100, nil, database, baseLogger) require.NoError(t, err) // create Bitcoin observer - ob, err := New(chain, baseObserver, btcClient) + ob, err := New(baseObserver, btcClient, chain) require.NoError(t, err) return ob diff --git a/zetaclient/chains/bitcoin/observer/utxos.go b/zetaclient/chains/bitcoin/observer/utxos.go index 6bb86e2cfe..0b65d0c119 100644 --- a/zetaclient/chains/bitcoin/observer/utxos.go +++ b/zetaclient/chains/bitcoin/observer/utxos.go @@ -43,7 +43,7 @@ func (ob *Observer) FetchUTXOs(ctx context.Context) error { if err != nil { return err } - utxos, err := ob.rpc.ListUnspentMinMaxAddresses(ctx, 0, 9999999, []btcutil.Address{tssAddr}) + utxos, err := ob.bitcoinClient.ListUnspentMinMaxAddresses(ctx, 0, 9999999, []btcutil.Address{tssAddr}) if err != nil { return err } diff --git a/zetaclient/chains/bitcoin/observer/witness.go b/zetaclient/chains/bitcoin/observer/witness.go index d853e2d6fb..f8a8a5d181 100644 --- a/zetaclient/chains/bitcoin/observer/witness.go +++ b/zetaclient/chains/bitcoin/observer/witness.go @@ -34,7 +34,7 @@ const ( // Note: OP_RETURN based memo is prioritized over tapscript memo if both are present. func GetBtcEventWithWitness( ctx context.Context, - rpc RPC, + bitcoinClient BitcoinClient, tx btcjson.TxRawResult, tssAddress string, blockNumber uint64, @@ -63,7 +63,7 @@ func GetBtcEventWithWitness( } // event found, get sender address - fromAddress, err := rpc.GetTransactionInputSpender(ctx, tx.Vin[0].Txid, tx.Vin[0].Vout) + fromAddress, err := bitcoinClient.GetTransactionInputSpender(ctx, tx.Vin[0].Txid, tx.Vin[0].Vout) if err != nil { return nil, errors.Wrapf(err, "error getting sender address for inbound: %s", tx.Txid) } @@ -80,7 +80,7 @@ func GetBtcEventWithWitness( } // calculate depositor fee - depositorFee, err := feeCalculator(ctx, rpc, &tx, netParams) + depositorFee, err := feeCalculator(ctx, bitcoinClient, &tx, netParams) if err != nil { return nil, errors.Wrapf(err, "error calculating depositor fee for inbound %s", tx.Txid) } @@ -108,7 +108,7 @@ func GetBtcEventWithWitness( logger.Debug().Fields(lf).Str("memo", hex.EncodeToString(memo)).Msg("found inscription memo") // override the sender address with the initiator of the inscription's commit tx - if fromAddress, err = rpc.GetTransactionInitiator(ctx, tx.Vin[0].Txid); err != nil { + if fromAddress, err = bitcoinClient.GetTransactionInitiator(ctx, tx.Vin[0].Txid); err != nil { return nil, errors.Wrap(err, "unable to get inscription initiator") } } else { diff --git a/zetaclient/chains/bitcoin/signer/fee_bumper.go b/zetaclient/chains/bitcoin/signer/fee_bumper.go index d8304574f4..b84630c3b4 100644 --- a/zetaclient/chains/bitcoin/signer/fee_bumper.go +++ b/zetaclient/chains/bitcoin/signer/fee_bumper.go @@ -38,8 +38,8 @@ type CPFPFeeBumper struct { chain chains.Chain - // rpc is the interface to interact with the Bitcoin chain - rpc RPC + // bitcoinClient is the interface to interact with the Bitcoin chain + bitcoinClient BitcoinClient // tx is the stuck transaction to bump tx *btcutil.Tx @@ -69,7 +69,7 @@ type BumpResult struct { // NewCPFPFeeBumper creates a new CPFPFeeBumper func NewCPFPFeeBumper( ctx context.Context, - rpc RPC, + bitcoinClient BitcoinClient, chain chains.Chain, tx *btcutil.Tx, cctxRate uint64, @@ -77,13 +77,13 @@ func NewCPFPFeeBumper( logger zerolog.Logger, ) (*CPFPFeeBumper, error) { fb := &CPFPFeeBumper{ - ctx: ctx, - chain: chain, - rpc: rpc, - tx: tx, - minRelayFee: minRelayFee, - cctxRate: cctxRate, - logger: logger, + ctx: ctx, + chain: chain, + bitcoinClient: bitcoinClient, + tx: tx, + minRelayFee: minRelayFee, + cctxRate: cctxRate, + logger: logger, } err := fb.fetchFeeBumpInfo() @@ -175,7 +175,7 @@ func (b *CPFPFeeBumper) BumpTxFee() (result BumpResult, err error) { // fetchFeeBumpInfo fetches all necessary information needed to bump the stuck tx func (b *CPFPFeeBumper) fetchFeeBumpInfo() error { // query live fee rate - liveRate, err := b.rpc.GetEstimatedFeeRate(b.ctx, 1) + liveRate, err := b.bitcoinClient.GetEstimatedFeeRate(b.ctx, 1) if err != nil { return errors.Wrap(err, "GetEstimatedFeeRate failed") } @@ -186,7 +186,7 @@ func (b *CPFPFeeBumper) fetchFeeBumpInfo() error { defer cancel() // query total fees and sizes of all pending parent TSS txs - txsAndFees, err := b.rpc.GetMempoolTxsAndFees(ctx, b.tx.MsgTx().TxID()) + txsAndFees, err := b.bitcoinClient.GetMempoolTxsAndFees(ctx, b.tx.MsgTx().TxID()) if err != nil { return errors.Wrap(err, "unable to fetch mempool txs info") } diff --git a/zetaclient/chains/bitcoin/signer/fee_bumper_test.go b/zetaclient/chains/bitcoin/signer/fee_bumper_test.go index e9220b5a5a..f3ca079bc8 100644 --- a/zetaclient/chains/bitcoin/signer/fee_bumper_test.go +++ b/zetaclient/chains/bitcoin/signer/fee_bumper_test.go @@ -112,7 +112,7 @@ func Test_NewCPFPFeeBumper(t *testing.T) { require.Nil(t, bumper) require.ErrorContains(t, err, tt.errMsg) } else { - bumper.rpc = nil // ignore the RPC + bumper.bitcoinClient = nil // ignore the RPC require.NoError(t, err) require.Equal(t, tt.expected, bumper) } diff --git a/zetaclient/chains/bitcoin/signer/sign_rbf.go b/zetaclient/chains/bitcoin/signer/sign_rbf.go index 5d29de33d6..c980d84d40 100644 --- a/zetaclient/chains/bitcoin/signer/sign_rbf.go +++ b/zetaclient/chains/bitcoin/signer/sign_rbf.go @@ -37,7 +37,7 @@ func (signer *Signer) SignRBFTx(ctx context.Context, txData *OutboundData, lastT // create fee bumper fb, err := NewCPFPFeeBumper( ctx, - signer.rpc, + signer.bitcoinClient, signer.Chain(), lastTx, cctxRate, @@ -63,7 +63,7 @@ func (signer *Signer) SignRBFTx(ctx context.Context, txData *OutboundData, lastT inAmounts := make([]int64, len(result.NewTx.TxIn)) for i, input := range result.NewTx.TxIn { preOut := input.PreviousOutPoint - preTx, err := signer.rpc.GetRawTransaction(ctx, &preOut.Hash) + preTx, err := signer.bitcoinClient.GetRawTransaction(ctx, &preOut.Hash) if err != nil { return nil, errors.Wrapf(err, "unable to get previous tx %s", preOut.Hash) } diff --git a/zetaclient/chains/bitcoin/signer/signer.go b/zetaclient/chains/bitcoin/signer/signer.go index a4b4e2ede1..25bb3981a5 100644 --- a/zetaclient/chains/bitcoin/signer/signer.go +++ b/zetaclient/chains/bitcoin/signer/signer.go @@ -32,27 +32,28 @@ const ( broadcastRetries = 10 ) -type RPC interface { - GetNetworkInfo(ctx context.Context) (*btcjson.GetNetworkInfoResult, error) - GetRawTransaction(ctx context.Context, hash *chainhash.Hash) (*btcutil.Tx, error) - GetEstimatedFeeRate(ctx context.Context, confTarget int64) (uint64, error) - SendRawTransaction(ctx context.Context, tx *wire.MsgTx, allowHighFees bool) (*chainhash.Hash, error) - GetMempoolTxsAndFees(ctx context.Context, childHash string) (client.MempoolTxsAndFees, error) +type BitcoinClient interface { + GetNetworkInfo(context.Context) (*btcjson.GetNetworkInfoResult, error) + GetRawTransaction(context.Context, *chainhash.Hash) (*btcutil.Tx, error) + GetEstimatedFeeRate(_ context.Context, confTarget int64) (uint64, error) + SendRawTransaction(_ context.Context, _ *wire.MsgTx, allowHighFees bool) (*chainhash.Hash, error) + GetMempoolTxsAndFees(_ context.Context, childHash string) (client.MempoolTxsAndFees, error) } // Signer deals with signing & broadcasting BTC transactions. type Signer struct { *base.Signer - rpc RPC - isRegnet bool + bitcoinClient BitcoinClient + isRegnet bool } // New creates a new Bitcoin signer -func New(baseSigner *base.Signer, rpc RPC) *Signer { +func New(baseSigner *base.Signer, bitcoinClient BitcoinClient) *Signer { + chainID := baseSigner.Chain().ChainId return &Signer{ - Signer: baseSigner, - rpc: rpc, - isRegnet: chains.IsBitcoinRegnet(baseSigner.Chain().ChainId), + Signer: baseSigner, + bitcoinClient: bitcoinClient, + isRegnet: chains.IsBitcoinRegnet(chainID), } } @@ -68,7 +69,7 @@ func (signer *Signer) Broadcast(ctx context.Context, signedTx *wire.MsgTx) error Str("signer_tx_payload", hex.EncodeToString(outBuff.Bytes())). Msg("broadcasting transaction") - _, err := signer.rpc.SendRawTransaction(ctx, signedTx, true) + _, err := signer.bitcoinClient.SendRawTransaction(ctx, signedTx, true) if err != nil { return errors.Wrap(err, "unable to broadcast raw tx") } @@ -113,7 +114,7 @@ func (signer *Signer) TryProcessOutbound( logger := signer.Logger().Std.With().Fields(lf).Logger() // query network info to get minRelayFee (typically 1000 satoshis) - networkInfo, err := signer.rpc.GetNetworkInfo(ctx) + networkInfo, err := signer.bitcoinClient.GetNetworkInfo(ctx) if err != nil { logger.Error().Err(err).Msg("failed get bitcoin network info") return diff --git a/zetaclient/chains/bitcoin/signer/signer_keysign_test.go b/zetaclient/chains/bitcoin/signer/signer_keysign_test.go index 5a546b487d..5ef96cc53c 100644 --- a/zetaclient/chains/bitcoin/signer/signer_keysign_test.go +++ b/zetaclient/chains/bitcoin/signer/signer_keysign_test.go @@ -132,7 +132,7 @@ func getWalletTX( } func getTSSTX( - tss interfaces.TSSSigner, + tssSigner interfaces.TSSSigner, tx *wire.MsgTx, sigHashes *txscript.TxSigHashes, idx int, @@ -147,7 +147,7 @@ func getTSSTX( return "", err } - sig65B, err := tss.Sign(ctx, witnessHash, 10, 10, 0) + sig65B, err := tssSigner.Sign(ctx, witnessHash, 10, 10, 0) R := &btcec.ModNScalar{} R.SetBytes((*[32]byte)(sig65B[:32])) S := &btcec.ModNScalar{} @@ -158,7 +158,7 @@ func getTSSTX( return "", err } - pkCompressed := tss.PubKey().Bytes(true) + pkCompressed := tssSigner.PubKey().Bytes(true) txWitness := wire.TxWitness{append(sig.Serialize(), byte(hashType)), pkCompressed} tx.TxIn[0].Witness = txWitness diff --git a/zetaclient/chains/bitcoin/signer/signer_test.go b/zetaclient/chains/bitcoin/signer/signer_test.go index a5542a7928..3d042873a5 100644 --- a/zetaclient/chains/bitcoin/signer/signer_test.go +++ b/zetaclient/chains/bitcoin/signer/signer_test.go @@ -375,7 +375,7 @@ func (s *testSuite) createObserver(t *testing.T) { baseObserver, err := base.NewObserver(s.Chain(), params, s.zetacoreClient, s.tss, 100, ts, database, baseLogger) require.NoError(t, err) - s.observer, err = observer.New(s.Chain(), baseObserver, s.client) + s.observer, err = observer.New(baseObserver, s.client, s.Chain()) require.NoError(t, err) } diff --git a/zetaclient/chains/evm/client.go b/zetaclient/chains/evm/client.go new file mode 100644 index 0000000000..be9c75d9f0 --- /dev/null +++ b/zetaclient/chains/evm/client.go @@ -0,0 +1,11 @@ +package evm + +import ( + "github.com/zeta-chain/node/zetaclient/chains/evm/observer" + "github.com/zeta-chain/node/zetaclient/chains/evm/signer" +) + +type Client interface { + observer.EVMClient + signer.EVMClient +} diff --git a/zetaclient/chains/evm/client/client.go b/zetaclient/chains/evm/client/client.go index 31512f6e02..9ba1ded83c 100644 --- a/zetaclient/chains/evm/client/client.go +++ b/zetaclient/chains/evm/client/client.go @@ -4,10 +4,10 @@ import ( "context" "time" - ethcommon "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/common" + eth "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" - ethrpc "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" "github.com/zeta-chain/node/zetaclient/metrics" @@ -15,7 +15,8 @@ import ( type Client struct { *ethclient.Client - ethtypes.Signer + + signer eth.Signer } // NewFromEndpoint new Client constructor based on endpoint URL. @@ -25,25 +26,25 @@ func NewFromEndpoint(ctx context.Context, endpoint string) (*Client, error) { return nil, errors.Wrap(err, "unable to get instrumented HTTP client") } - rpc, err := ethrpc.DialOptions(ctx, endpoint, ethrpc.WithHTTPClient(httpClient)) + ethRPC, err := rpc.DialOptions(ctx, endpoint, rpc.WithHTTPClient(httpClient)) if err != nil { return nil, errors.Wrapf(err, "unable to dial EVM client (endpoint %q)", endpoint) } - client := ethclient.NewClient(rpc) + client := ethclient.NewClient(ethRPC) chainID, err := client.ChainID(ctx) if err != nil { return nil, errors.Wrap(err, "unable to get chain ID") } - ethSigner := ethtypes.LatestSignerForChainID(chainID) + ethSigner := eth.LatestSignerForChainID(chainID) return New(client, ethSigner), nil } // New Client constructor. -func New(client *ethclient.Client, signer ethtypes.Signer) *Client { +func New(client *ethclient.Client, signer eth.Signer) *Client { return &Client{client, signer} } @@ -53,7 +54,7 @@ func (c *Client) IsTxConfirmed(ctx context.Context, txHash string, confirmations return false, errors.New("confirmations must be greater than 0") } - hash := ethcommon.HexToHash(txHash) + hash := common.HexToHash(txHash) // query the tx _, isPending, err := c.TransactionByHash(ctx, hash) @@ -104,3 +105,8 @@ func (c *Client) HealthCheck(ctx context.Context) (time.Time, error) { return blockTime, nil } + +// Overrides c.Client ChainID method. +func (c *Client) Signer() eth.Signer { + return c.signer +} diff --git a/zetaclient/chains/evm/client/client_live_test.go b/zetaclient/chains/evm/client/client_test.go similarity index 100% rename from zetaclient/chains/evm/client/client_live_test.go rename to zetaclient/chains/evm/client/client_test.go diff --git a/zetaclient/chains/evm/evm.go b/zetaclient/chains/evm/evm.go index bff9ddbc6a..c018929389 100644 --- a/zetaclient/chains/evm/evm.go +++ b/zetaclient/chains/evm/evm.go @@ -15,7 +15,6 @@ import ( "github.com/zeta-chain/node/zetaclient/chains/base" "github.com/zeta-chain/node/zetaclient/chains/evm/observer" "github.com/zeta-chain/node/zetaclient/chains/evm/signer" - "github.com/zeta-chain/node/zetaclient/chains/interfaces" zctx "github.com/zeta-chain/node/zetaclient/context" "github.com/zeta-chain/node/zetaclient/logs" ) @@ -266,7 +265,7 @@ func (e *EVM) updateChainParams(ctx context.Context) error { func (e *EVM) getTrackerSet(ctx context.Context) (map[uint64]struct{}, error) { chainID := e.observer.Chain().ChainId - trackers, err := e.observer.ZetacoreClient().GetAllOutboundTrackerByChain(ctx, chainID, interfaces.Ascending) + trackers, err := e.observer.ZetacoreClient().GetOutboundTrackers(ctx, chainID) if err != nil { return nil, errors.Wrap(err, "unable to get outbound trackers") } diff --git a/zetaclient/chains/evm/observer/inbound_test.go b/zetaclient/chains/evm/observer/inbound_test.go index e6126cc394..055ff0af43 100644 --- a/zetaclient/chains/evm/observer/inbound_test.go +++ b/zetaclient/chains/evm/observer/inbound_test.go @@ -447,13 +447,13 @@ func Test_ObserveTSSReceiveInBlock(t *testing.T) { // test cases tests := []struct { name string - mockEVMClient func(m *mocks.EVMRPCClient) + mockEVMClient func(m *mocks.EVMClient) mockZetacoreClient func(m *mocks.ZetacoreClient) errMsg string }{ { name: "should observe TSS receive in block", - mockEVMClient: func(m *mocks.EVMRPCClient) { + mockEVMClient: func(m *mocks.EVMClient) { // feed block number and receipt to mock client m.On("BlockNumber", mock.Anything).Return(uint64(1000), nil) m.On("TransactionReceipt", mock.Anything, mock.Anything).Return(receipt, nil) @@ -466,7 +466,7 @@ func Test_ObserveTSSReceiveInBlock(t *testing.T) { }, { name: "should not observe on error getting block", - mockEVMClient: func(m *mocks.EVMRPCClient) { + mockEVMClient: func(m *mocks.EVMClient) { // feed block number to allow construction of observer m.On("BlockNumber", mock.Anything).Unset() m.On("BlockByNumberCustom", mock.Anything, mock.Anything).Unset() @@ -478,7 +478,7 @@ func Test_ObserveTSSReceiveInBlock(t *testing.T) { }, { name: "should not observe on error getting receipt", - mockEVMClient: func(m *mocks.EVMRPCClient) { + mockEVMClient: func(m *mocks.EVMClient) { // feed block number but RPC error on getting receipt m.On("BlockNumber", mock.Anything).Return(uint64(1000), nil) m.On("TransactionReceipt", mock.Anything, mock.Anything).Return(nil, errors.New("RPC error")) diff --git a/zetaclient/chains/evm/observer/observer.go b/zetaclient/chains/evm/observer/observer.go index 7278cd2b4e..bfc7fc05b3 100644 --- a/zetaclient/chains/evm/observer/observer.go +++ b/zetaclient/chains/evm/observer/observer.go @@ -7,9 +7,11 @@ import ( "math" "math/big" "strings" + "time" + ethbind "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" + eth "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" "github.com/zeta-chain/protocol-contracts/pkg/erc20custody.sol" "github.com/zeta-chain/protocol-contracts/pkg/gatewayevm.sol" @@ -19,10 +21,40 @@ import ( "github.com/zeta-chain/node/zetaclient/chains/base" "github.com/zeta-chain/node/zetaclient/chains/evm/client" "github.com/zeta-chain/node/zetaclient/chains/evm/common" - "github.com/zeta-chain/node/zetaclient/chains/interfaces" "github.com/zeta-chain/node/zetaclient/metrics" ) +// EVMClient is the interface for the EVM RPC client +// +//go:generate mockery --name EVMClient --filename evm_client.go --case underscore --output ../../../testutils/mocks +type EVMClient interface { + ethbind.ContractBackend + + SendTransaction(context.Context, *eth.Transaction) error + + SuggestGasPrice(context.Context) (*big.Int, error) + + BlockNumber(context.Context) (uint64, error) + + BlockByNumberCustom(context.Context, *big.Int) (*client.Block, error) + + HeaderByNumber(context.Context, *big.Int) (*eth.Header, error) + + TransactionByHash(context.Context, ethcommon.Hash) (_ *eth.Transaction, isPending bool, _ error) + + TransactionByHashCustom(context.Context, string) (*client.Transaction, error) + + TransactionReceipt(context.Context, ethcommon.Hash) (*eth.Receipt, error) + + TransactionSender(_ context.Context, + _ *eth.Transaction, + block ethcommon.Hash, + index uint, + ) (ethcommon.Address, error) + + HealthCheck(ctx context.Context) (time.Time, error) +} + // Observer is the observer for evm chains type Observer struct { // base.Observer implements the base chain observer @@ -31,13 +63,13 @@ type Observer struct { priorityFeeConfig // evmClient is the EVM client for the observed chain - evmClient interfaces.EVMRPCClient + evmClient EVMClient // outboundConfirmedReceipts is the map to index confirmed receipts by hash - outboundConfirmedReceipts map[string]*ethtypes.Receipt + outboundConfirmedReceipts map[string]*eth.Receipt // outboundConfirmedTransactions is the map to index confirmed transactions by hash - outboundConfirmedTransactions map[string]*ethtypes.Transaction + outboundConfirmedTransactions map[string]*eth.Transaction } // priorityFeeConfig is the configuration for priority fee @@ -51,13 +83,13 @@ type priorityFeeConfig struct { } // New Observer constructor -func New(baseObserver *base.Observer, client interfaces.EVMRPCClient) (*Observer, error) { +func New(baseObserver *base.Observer, evmClient EVMClient) (*Observer, error) { // create evm observer ob := &Observer{ Observer: baseObserver, - evmClient: client, - outboundConfirmedReceipts: make(map[string]*ethtypes.Receipt), - outboundConfirmedTransactions: make(map[string]*ethtypes.Transaction), + evmClient: evmClient, + outboundConfirmedReceipts: make(map[string]*eth.Receipt), + outboundConfirmedTransactions: make(map[string]*eth.Transaction), priorityFeeConfig: priorityFeeConfig{}, } @@ -107,7 +139,7 @@ func (ob *Observer) getGatewayContract() (ethcommon.Address, *gatewayevm.Gateway } // setTxNReceipt sets the receipt and transaction in memory -func (ob *Observer) setTxNReceipt(nonce uint64, receipt *ethtypes.Receipt, transaction *ethtypes.Transaction) { +func (ob *Observer) setTxNReceipt(nonce uint64, receipt *eth.Receipt, transaction *eth.Transaction) { ob.Mu().Lock() defer ob.Mu().Unlock() ob.outboundConfirmedReceipts[ob.OutboundID(nonce)] = receipt @@ -115,7 +147,7 @@ func (ob *Observer) setTxNReceipt(nonce uint64, receipt *ethtypes.Receipt, trans } // getTxNReceipt gets the receipt and transaction from memory -func (ob *Observer) getTxNReceipt(nonce uint64) (*ethtypes.Receipt, *ethtypes.Transaction) { +func (ob *Observer) getTxNReceipt(nonce uint64) (*eth.Receipt, *eth.Transaction) { ob.Mu().Lock() defer ob.Mu().Unlock() receipt := ob.outboundConfirmedReceipts[ob.OutboundID(nonce)] @@ -133,7 +165,7 @@ func (ob *Observer) isTxConfirmed(nonce uint64) bool { } // checkTxInclusion returns nil only if tx is included at the position indicated by the receipt ([block, index]) -func (ob *Observer) checkTxInclusion(ctx context.Context, tx *ethtypes.Transaction, receipt *ethtypes.Receipt) error { +func (ob *Observer) checkTxInclusion(ctx context.Context, tx *eth.Transaction, receipt *eth.Receipt) error { block, err := ob.GetBlockByNumberCached(ctx, receipt.BlockNumber.Uint64()) if err != nil { return errors.Wrapf(err, "GetBlockByNumberCached error for block %d txHash %s nonce %d", diff --git a/zetaclient/chains/evm/observer/observer_test.go b/zetaclient/chains/evm/observer/observer_test.go index dbf375d317..a5bb27e58d 100644 --- a/zetaclient/chains/evm/observer/observer_test.go +++ b/zetaclient/chains/evm/observer/observer_test.go @@ -100,7 +100,7 @@ func Test_NewObserver(t *testing.T) { evmCfg config.EVMConfig chainParams observertypes.ChainParams evmClient *client.Client - tss interfaces.TSSSigner + tssSigner interfaces.TSSSigner logger base.Logger before func() after func() @@ -115,7 +115,7 @@ func Test_NewObserver(t *testing.T) { }, chainParams: params, evmClient: evmClient, - tss: mocks.NewTSS(t), + tssSigner: mocks.NewTSS(t), logger: base.Logger{}, ts: nil, fail: false, @@ -137,11 +137,11 @@ func Test_NewObserver(t *testing.T) { return c }(), - tss: mocks.NewTSS(t), - logger: base.Logger{}, - ts: nil, - fail: true, - message: "json-rpc error", + tssSigner: mocks.NewTSS(t), + logger: base.Logger{}, + ts: nil, + fail: true, + message: "json-rpc error", }, { name: "should fail on invalid ENV var", @@ -150,7 +150,7 @@ func Test_NewObserver(t *testing.T) { }, chainParams: params, evmClient: evmClient, - tss: mocks.NewTSS(t), + tssSigner: mocks.NewTSS(t), before: func() { envVar := base.EnvVarLatestBlockByChain(chain) os.Setenv(envVar, "invalid") @@ -187,7 +187,7 @@ func Test_NewObserver(t *testing.T) { chain, tt.chainParams, zetacoreClient, - tt.tss, + tt.tssSigner, 1000, tt.ts, database, @@ -389,7 +389,7 @@ type testSuite struct { chainParams *observertypes.ChainParams tss *mocks.TSS zetacore *mocks.ZetacoreClient - evmMock *mocks.EVMRPCClient + evmMock *mocks.EVMClient } type testSuiteConfig struct { @@ -412,7 +412,7 @@ func newTestSuite(t *testing.T, opts ...func(*testSuiteConfig)) *testSuite { appContext, _ := getAppContext(t, chain, "", &chainParams) ctx := zctx.WithAppContext(context.Background(), appContext) - evmMock := mocks.NewEVMRPCClient(t) + evmMock := mocks.NewEVMClient(t) evmMock.On("BlockNumber", mock.Anything).Return(uint64(1000), nil).Maybe() zetacore := mocks.NewZetacoreClient(t). diff --git a/zetaclient/chains/evm/observer/outbound.go b/zetaclient/chains/evm/observer/outbound.go index bef8bf72b9..05282e2ee8 100644 --- a/zetaclient/chains/evm/observer/outbound.go +++ b/zetaclient/chains/evm/observer/outbound.go @@ -22,7 +22,6 @@ import ( "github.com/zeta-chain/node/pkg/coin" crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" "github.com/zeta-chain/node/zetaclient/chains/evm/common" - "github.com/zeta-chain/node/zetaclient/chains/interfaces" "github.com/zeta-chain/node/zetaclient/compliance" "github.com/zeta-chain/node/zetaclient/logs" "github.com/zeta-chain/node/zetaclient/zetacore" @@ -30,9 +29,9 @@ import ( // ProcessOutboundTrackers processes outbound trackers func (ob *Observer) ProcessOutboundTrackers(ctx context.Context) error { - trackers, err := ob.ZetacoreClient().GetAllOutboundTrackerByChain(ctx, ob.Chain().ChainId, interfaces.Ascending) + trackers, err := ob.ZetacoreClient().GetOutboundTrackers(ctx, ob.Chain().ChainId) if err != nil { - return errors.Wrap(err, "GetAllOutboundTrackerByChain error") + return errors.Wrap(err, "GetOutboundTrackers error") } // keep last block up-to-date diff --git a/zetaclient/chains/evm/signer/outbound_tracker_reporter.go b/zetaclient/chains/evm/signer/outbound_tracker_reporter.go index 858cc64073..3cb376abfe 100644 --- a/zetaclient/chains/evm/signer/outbound_tracker_reporter.go +++ b/zetaclient/chains/evm/signer/outbound_tracker_reporter.go @@ -74,7 +74,7 @@ func (signer *Signer) reportToOutboundTracker( } // check tx confirmation status - confirmed, err := signer.client.IsTxConfirmed(ctx, outboundHash, common.ReorgProtectBlockCount) + confirmed, err := signer.evmClient.IsTxConfirmed(ctx, outboundHash, common.ReorgProtectBlockCount) if err != nil { logger.Err(err).Msg("unable to check confirmation status of outbound") continue diff --git a/zetaclient/chains/evm/signer/sign_test.go b/zetaclient/chains/evm/signer/sign_test.go index b9f7c0afd3..2ef7f82a21 100644 --- a/zetaclient/chains/evm/signer/sign_test.go +++ b/zetaclient/chains/evm/signer/sign_test.go @@ -48,7 +48,7 @@ func TestSigner_SignConnectorOnReceive(t *testing.T) { require.NoError(t, err) // Verify Signature - verifyTxSender(t, tx, evmSigner.tss.PubKey().AddressEVM(), evmSigner.client.Signer) + verifyTxSender(t, tx, evmSigner.tss.PubKey().AddressEVM(), evmSigner.client.Signer()) // check that by default tx type is legacy tx assert.Equal(t, ethtypes.LegacyTxType, int(tx.Type())) diff --git a/zetaclient/chains/evm/signer/signer.go b/zetaclient/chains/evm/signer/signer.go index 49791d5d4f..8d67b8afa7 100644 --- a/zetaclient/chains/evm/signer/signer.go +++ b/zetaclient/chains/evm/signer/signer.go @@ -11,7 +11,7 @@ import ( "github.com/cenkalti/backoff/v4" ethcommon "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" + eth "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/pkg/errors" "github.com/rs/zerolog" @@ -20,7 +20,6 @@ import ( "github.com/zeta-chain/node/pkg/retry" crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" "github.com/zeta-chain/node/zetaclient/chains/base" - "github.com/zeta-chain/node/zetaclient/chains/evm/client" "github.com/zeta-chain/node/zetaclient/chains/interfaces" zctx "github.com/zeta-chain/node/zetaclient/context" "github.com/zeta-chain/node/zetaclient/logs" @@ -39,17 +38,25 @@ const ( broadcastTimeout = time.Second * 15 ) -var ( - // zeroValue is for outbounds that carry no ETH (gas token) value - zeroValue = big.NewInt(0) -) +// zeroValue is for outbounds that carry no ETH (gas token) value +var zeroValue = big.NewInt(0) + +type EVMClient interface { + NonceAt(_ context.Context, account ethcommon.Address, blockNumber *big.Int) (uint64, error) + + IsTxConfirmed(_ context.Context, txHash string, confirmations uint64) (bool, error) + + SendTransaction(context.Context, *eth.Transaction) error + + Signer() eth.Signer +} // Signer deals with the signing EVM transactions and implements the ChainSigner interface type Signer struct { *base.Signer - // client is the EVM RPC client to interact with the EVM chain - client *client.Client + // evmClient is the EVM RPC client used to interact with the EVM chain + evmClient EVMClient // zetaConnectorAddress is the address of the ZetaConnector contract zetaConnectorAddress ethcommon.Address @@ -64,14 +71,14 @@ type Signer struct { // New Signer constructor func New( baseSigner *base.Signer, - client *client.Client, + evmClient EVMClient, zetaConnectorAddress ethcommon.Address, erc20CustodyAddress ethcommon.Address, gatewayAddress ethcommon.Address, ) (*Signer, error) { return &Signer{ Signer: baseSigner, - client: client, + evmClient: evmClient, zetaConnectorAddress: zetaConnectorAddress, er20CustodyAddress: erc20CustodyAddress, gatewayAddress: gatewayAddress, @@ -156,14 +163,14 @@ func (signer *Signer) Sign( gas Gas, nonce uint64, height uint64, -) (*ethtypes.Transaction, []byte, []byte, error) { +) (*eth.Transaction, []byte, []byte, error) { chainID := big.NewInt(signer.Chain().ChainId) tx, err := newTx(chainID, data, to, amount, gas, nonce) if err != nil { return nil, nil, nil, errors.Wrap(err, "unable to create new tx") } - hashBytes := signer.client.Hash(tx).Bytes() + hashBytes := signer.evmClient.Signer().Hash(tx).Bytes() sig, err := signer.TSS().Sign(ctx, hashBytes, height, nonce, signer.Chain().ChainId) if err != nil { @@ -175,7 +182,7 @@ func (signer *Signer) Sign( return nil, nil, nil, errors.Wrap(err, "unable to derive pub key from signature") } - signedTX, err := tx.WithSignature(signer.client.Signer, sig[:]) + signedTX, err := tx.WithSignature(signer.evmClient.Signer(), sig[:]) if err != nil { return nil, nil, nil, errors.Wrap(err, "unable to set tx signature") } @@ -190,14 +197,14 @@ func newTx( amount *big.Int, gas Gas, nonce uint64, -) (*ethtypes.Transaction, error) { +) (*eth.Transaction, error) { if err := gas.validate(); err != nil { return nil, errors.Wrap(err, "invalid gas parameters") } // https://github.com/zeta-chain/node/issues/3221 //if gas.isLegacy() { - return ethtypes.NewTx(ðtypes.LegacyTx{ + return eth.NewTx(ð.LegacyTx{ To: &to, Value: amount, Data: data, @@ -219,11 +226,11 @@ func newTx( //}), nil } -func (signer *Signer) broadcast(ctx context.Context, tx *ethtypes.Transaction) error { +func (signer *Signer) broadcast(ctx context.Context, tx *eth.Transaction) error { ctx, cancel := context.WithTimeout(ctx, broadcastTimeout) defer cancel() - return signer.client.SendTransaction(ctx, tx) + return signer.evmClient.SendTransaction(ctx, tx) } // TryProcessOutbound - signer interface implementation @@ -334,7 +341,7 @@ func (signer *Signer) SignOutboundFromCCTX( outboundData *OutboundData, zetacoreClient interfaces.ZetacoreClient, _ zctx.Chain, -) (*ethtypes.Transaction, error) { +) (*eth.Transaction, error) { switch { case !signer.PassesCompliance(cctx): // restricted cctx @@ -401,7 +408,7 @@ func (signer *Signer) SignOutboundFromCCTX( // BroadcastOutbound signed transaction through evm rpc client func (signer *Signer) BroadcastOutbound( ctx context.Context, - tx *ethtypes.Transaction, + tx *eth.Transaction, cctx *crosschaintypes.CrossChainTx, logger zerolog.Logger, zetacoreClient interfaces.ZetacoreClient, @@ -440,7 +447,7 @@ func (signer *Signer) BroadcastOutbound( // define broadcast function broadcast := func() error { // get latest TSS account nonce - latestNonce, err := signer.client.NonceAt(ctx, signer.TSS().PubKey().AddressEVM(), nil) + latestNonce, err := signer.evmClient.NonceAt(ctx, signer.TSS().PubKey().AddressEVM(), nil) if err != nil { return errors.Wrap(err, "unable to get latest TSS account nonce") } diff --git a/zetaclient/chains/evm/signer/signer_test.go b/zetaclient/chains/evm/signer/signer_test.go index 64b61682a9..1a32f28511 100644 --- a/zetaclient/chains/evm/signer/signer_test.go +++ b/zetaclient/chains/evm/signer/signer_test.go @@ -75,7 +75,7 @@ func newTestSuite(t *testing.T) *testSuite { } func (ts *testSuite) EvmSigner() ethtypes.Signer { - return ts.client.Signer + return ts.client.Signer() } func getCCTX(t *testing.T) *crosschaintypes.CrossChainTx { diff --git a/zetaclient/chains/interfaces/interfaces.go b/zetaclient/chains/interfaces/interfaces.go deleted file mode 100644 index 2165e9239d..0000000000 --- a/zetaclient/chains/interfaces/interfaces.go +++ /dev/null @@ -1,189 +0,0 @@ -// Package interfaces provides interfaces for clients and signers for the chain to interact with -package interfaces - -import ( - "context" - "math/big" - "time" - - sdkmath "cosmossdk.io/math" - upgradetypes "cosmossdk.io/x/upgrade/types" - cometbfttypes "github.com/cometbft/cometbft/types" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - ethcommon "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/gagliardetto/solana-go" - solrpc "github.com/gagliardetto/solana-go/rpc" - "github.com/zeta-chain/go-tss/blame" - - "github.com/zeta-chain/node/pkg/chains" - crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" - fungibletypes "github.com/zeta-chain/node/x/fungible/types" - observertypes "github.com/zeta-chain/node/x/observer/types" - ethclient "github.com/zeta-chain/node/zetaclient/chains/evm/client" - keyinterfaces "github.com/zeta-chain/node/zetaclient/keys/interfaces" - "github.com/zeta-chain/node/zetaclient/tss" -) - -type Order string - -const ( - NoOrder Order = "" - Ascending Order = "ASC" - Descending Order = "DESC" -) - -type ZetacoreVoter interface { - PostVoteGasPrice( - ctx context.Context, - chain chains.Chain, - gasPrice, priorityFee, blockNum uint64, - ) (string, error) - PostVoteInbound( - ctx context.Context, - gasLimit, retryGasLimit uint64, - msg *crosschaintypes.MsgVoteInbound, - ) (string, string, error) - PostVoteOutbound( - ctx context.Context, - gasLimit, retryGasLimit uint64, - msg *crosschaintypes.MsgVoteOutbound, - ) (string, string, error) - PostVoteBlameData(ctx context.Context, blame *blame.Blame, chainID int64, index string) (string, error) -} - -// ZetacoreClient is the client interface to interact with zetacore -// -//go:generate mockery --name ZetacoreClient --filename zetacore_client.go --case underscore --output ../../testutils/mocks -type ZetacoreClient interface { - ZetacoreVoter - - Chain() chains.Chain - GetKeys() keyinterfaces.ObserverKeys - - GetSupportedChains(ctx context.Context) ([]chains.Chain, error) - GetAdditionalChains(ctx context.Context) ([]chains.Chain, error) - GetChainParams(ctx context.Context) ([]*observertypes.ChainParams, error) - GetForeignCoinsFromAsset( - ctx context.Context, - chainID int64, - assetAddress ethcommon.Address, - ) (fungibletypes.ForeignCoins, error) - - GetKeyGen(ctx context.Context) (observertypes.Keygen, error) - GetTSS(ctx context.Context) (observertypes.TSS, error) - GetTSSHistory(ctx context.Context) ([]observertypes.TSS, error) - PostVoteTSS( - ctx context.Context, - tssPubKey string, - keyGenZetaHeight int64, - status chains.ReceiveStatus, - ) (string, error) - - GetBlockHeight(ctx context.Context) (int64, error) - - ListPendingCCTX(ctx context.Context, chain chains.Chain) ([]*crosschaintypes.CrossChainTx, uint64, error) - ListPendingCCTXWithinRateLimit( - ctx context.Context, - ) (*crosschaintypes.QueryListPendingCctxWithinRateLimitResponse, error) - - GetRateLimiterInput(ctx context.Context, window int64) (*crosschaintypes.QueryRateLimiterInputResponse, error) - GetPendingNoncesByChain(ctx context.Context, chainID int64) (observertypes.PendingNonces, error) - - GetCctxByNonce(ctx context.Context, chainID int64, nonce uint64) (*crosschaintypes.CrossChainTx, error) - GetOutboundTracker(ctx context.Context, chainID int64, nonce uint64) (*crosschaintypes.OutboundTracker, error) - GetAllOutboundTrackerByChain( - ctx context.Context, - chainID int64, - order Order, - ) ([]crosschaintypes.OutboundTracker, error) - GetCrosschainFlags(ctx context.Context) (observertypes.CrosschainFlags, error) - GetRateLimiterFlags(ctx context.Context) (crosschaintypes.RateLimiterFlags, error) - GetOperationalFlags(ctx context.Context) (observertypes.OperationalFlags, error) - GetObserverList(ctx context.Context) ([]string, error) - GetBTCTSSAddress(ctx context.Context, chainID int64) (string, error) - GetZetaHotKeyBalance(ctx context.Context) (sdkmath.Int, error) - GetInboundTrackersForChain(ctx context.Context, chainID int64) ([]crosschaintypes.InboundTracker, error) - - GetUpgradePlan(ctx context.Context) (*upgradetypes.Plan, error) - - PostOutboundTracker(ctx context.Context, chainID int64, nonce uint64, txHash string) (string, error) - NewBlockSubscriber(ctx context.Context) (chan cometbfttypes.EventDataNewBlock, error) - GetBallotByID(ctx context.Context, id string) (*observertypes.QueryBallotByIdentifierResponse, error) - GetCctxByHash(ctx context.Context, sendHash string) (*crosschaintypes.CrossChainTx, error) -} - -// EVMRPCClient is the interface for EVM RPC client -// TODO https://github.com/zeta-chain/node/issues/3107 -// -//go:generate mockery --name EVMRPCClient --filename evm_rpc.go --case underscore --output ../../testutils/mocks -type EVMRPCClient interface { - bind.ContractBackend - SendTransaction(ctx context.Context, tx *ethtypes.Transaction) error - SuggestGasPrice(ctx context.Context) (*big.Int, error) - BlockNumber(ctx context.Context) (uint64, error) - HeaderByNumber(ctx context.Context, number *big.Int) (*ethtypes.Header, error) - TransactionByHash(ctx context.Context, hash ethcommon.Hash) (tx *ethtypes.Transaction, isPending bool, err error) - TransactionReceipt(ctx context.Context, txHash ethcommon.Hash) (*ethtypes.Receipt, error) - TransactionSender( - ctx context.Context, - tx *ethtypes.Transaction, - block ethcommon.Hash, - index uint, - ) (ethcommon.Address, error) - - BlockByNumberCustom(ctx context.Context, number *big.Int) (*ethclient.Block, error) - TransactionByHashCustom(ctx context.Context, hash string) (*ethclient.Transaction, error) - HealthCheck(ctx context.Context) (time.Time, error) -} - -// SolanaRPCClient is the interface for Solana RPC client -type SolanaRPCClient interface { - GetVersion(ctx context.Context) (*solrpc.GetVersionResult, error) - GetHealth(ctx context.Context) (string, error) - GetSlot(ctx context.Context, commitment solrpc.CommitmentType) (uint64, error) - GetBlockTime(ctx context.Context, block uint64) (*solana.UnixTimeSeconds, error) - GetAccountInfo(ctx context.Context, account solana.PublicKey) (*solrpc.GetAccountInfoResult, error) - GetAccountInfoWithOpts( - ctx context.Context, - account solana.PublicKey, - opts *solrpc.GetAccountInfoOpts, - ) (*solrpc.GetAccountInfoResult, error) - GetBalance( - ctx context.Context, - account solana.PublicKey, - commitment solrpc.CommitmentType, - ) (*solrpc.GetBalanceResult, error) - GetLatestBlockhash(ctx context.Context, commitment solrpc.CommitmentType) (*solrpc.GetLatestBlockhashResult, error) - GetRecentPrioritizationFees( - ctx context.Context, - accounts solana.PublicKeySlice, - ) ([]solrpc.PriorizationFeeResult, error) - GetTransaction( - ctx context.Context, - txSig solana.Signature, // transaction signature - opts *solrpc.GetTransactionOpts, - ) (*solrpc.GetTransactionResult, error) - GetConfirmedTransactionWithOpts( - ctx context.Context, - signature solana.Signature, - opts *solrpc.GetTransactionOpts, - ) (*solrpc.TransactionWithMeta, error) - GetSignaturesForAddressWithOpts( - ctx context.Context, - account solana.PublicKey, - opts *solrpc.GetSignaturesForAddressOpts, - ) ([]*solrpc.TransactionSignature, error) - SendTransactionWithOpts( - ctx context.Context, - transaction *solana.Transaction, - opts solrpc.TransactionOpts, - ) (solana.Signature, error) -} - -// TSSSigner is the interface for TSS signer -type TSSSigner interface { - PubKey() tss.PubKey - Sign(ctx context.Context, data []byte, height, nonce uint64, chainID int64) ([65]byte, error) - SignBatch(ctx context.Context, digests [][]byte, height, nonce uint64, chainID int64) ([][65]byte, error) -} diff --git a/zetaclient/chains/interfaces/tss.go b/zetaclient/chains/interfaces/tss.go new file mode 100644 index 0000000000..177a8760a8 --- /dev/null +++ b/zetaclient/chains/interfaces/tss.go @@ -0,0 +1,27 @@ +// Package interfaces provides interfaces for clients and signers for the chain to interact with +package interfaces + +import ( + "context" + + "github.com/zeta-chain/node/zetaclient/tss" +) + +// TSSSigner is the interface for the TSS signer. +type TSSSigner interface { + PubKey() tss.PubKey + + Sign(_ context.Context, + data []byte, + height uint64, + nonce uint64, + chainID int64, + ) ([65]byte, error) + + SignBatch(_ context.Context, + digests [][]byte, + height uint64, + nonce uint64, + chainID int64, + ) ([][65]byte, error) +} diff --git a/zetaclient/chains/interfaces/zetacore.go b/zetaclient/chains/interfaces/zetacore.go new file mode 100644 index 0000000000..fb004b42af --- /dev/null +++ b/zetaclient/chains/interfaces/zetacore.go @@ -0,0 +1,122 @@ +package interfaces + +import ( + "context" + + cosmosmath "cosmossdk.io/math" + upgrade "cosmossdk.io/x/upgrade/types" + cometbft "github.com/cometbft/cometbft/types" + eth "github.com/ethereum/go-ethereum/common" + "github.com/zeta-chain/go-tss/blame" + + "github.com/zeta-chain/node/pkg/chains" + crosschain "github.com/zeta-chain/node/x/crosschain/types" + fungible "github.com/zeta-chain/node/x/fungible/types" + observer "github.com/zeta-chain/node/x/observer/types" + keys "github.com/zeta-chain/node/zetaclient/keys/interfaces" +) + +type ChainID = int64 +type Nonce = uint64 + +type ZetacoreWriter interface { + PostVoteGasPrice(_ context.Context, + _ chains.Chain, + gasPrice uint64, + priorityFee uint64, + blockNum uint64, + ) (string, error) + + PostVoteTSS(_ context.Context, + tssPubKey string, + keyGenZetaHeight int64, + _ chains.ReceiveStatus, + ) (string, error) + + PostVoteBlameData(_ context.Context, + _ *blame.Blame, + _ ChainID, + index string, + ) (string, error) + + PostVoteOutbound(_ context.Context, + gasLimit uint64, + retryGasLimit uint64, + _ *crosschain.MsgVoteOutbound, + ) (string, string, error) + + PostVoteInbound(_ context.Context, + gasLimit uint64, + retryGasLimit uint64, + _ *crosschain.MsgVoteInbound, + ) (string, string, error) + + PostOutboundTracker(_ context.Context, + _ ChainID, + _ Nonce, + txHash string, + ) (string, error) +} + +// ZetacoreClient is the client interface that interacts with zetacore. +// +//go:generate mockery --name ZetacoreClient --filename zetacore_client.go --case underscore --output ../../testutils/mocks +type ZetacoreClient interface { + ZetacoreWriter + + Chain() chains.Chain + + GetKeys() keys.ObserverKeys + + GetSupportedChains(context.Context) ([]chains.Chain, error) + + GetAdditionalChains(context.Context) ([]chains.Chain, error) + + GetChainParams(context.Context) ([]*observer.ChainParams, error) + + GetForeignCoinsFromAsset(context.Context, ChainID, eth.Address) (fungible.ForeignCoins, error) + + GetKeyGen(context.Context) (observer.Keygen, error) + + GetTSS(context.Context) (observer.TSS, error) + GetTSSHistory(context.Context) ([]observer.TSS, error) + + GetBlockHeight(context.Context) (int64, error) + + ListPendingCCTX(context.Context, chains.Chain) ([]*crosschain.CrossChainTx, uint64, error) + + ListPendingCCTXWithinRateLimit(context.Context, + ) (*crosschain.QueryListPendingCctxWithinRateLimitResponse, error) + + GetRateLimiterInput(_ context.Context, + window int64, + ) (*crosschain.QueryRateLimiterInputResponse, error) + + GetPendingNoncesByChain(context.Context, ChainID) (observer.PendingNonces, error) + + GetCctxByNonce(context.Context, ChainID, Nonce) (*crosschain.CrossChainTx, error) + + GetCctxByHash(context.Context, string) (*crosschain.CrossChainTx, error) + + GetBallotByID(context.Context, string) (*observer.QueryBallotByIdentifierResponse, error) + + GetOutboundTracker(context.Context, ChainID, Nonce) (*crosschain.OutboundTracker, error) + + GetOutboundTrackers(context.Context, ChainID) ([]crosschain.OutboundTracker, error) + + GetInboundTrackersForChain(context.Context, ChainID) ([]crosschain.InboundTracker, error) + + GetCrosschainFlags(context.Context) (observer.CrosschainFlags, error) + GetRateLimiterFlags(context.Context) (crosschain.RateLimiterFlags, error) + GetOperationalFlags(context.Context) (observer.OperationalFlags, error) + + GetObserverList(context.Context) ([]string, error) + + GetBTCTSSAddress(context.Context, ChainID) (string, error) + + GetZetaHotKeyBalance(context.Context) (cosmosmath.Int, error) + + GetUpgradePlan(context.Context) (*upgrade.Plan, error) + + NewBlockSubscriber(context.Context) (chan cometbft.EventDataNewBlock, error) +} diff --git a/zetaclient/chains/solana/client.go b/zetaclient/chains/solana/client.go new file mode 100644 index 0000000000..ac65ec96e8 --- /dev/null +++ b/zetaclient/chains/solana/client.go @@ -0,0 +1,16 @@ +package solana + +import ( + "github.com/zeta-chain/node/zetaclient/chains/solana/observer" + "github.com/zeta-chain/node/zetaclient/chains/solana/repo" + "github.com/zeta-chain/node/zetaclient/chains/solana/signer" +) + +// TODO: Replace this interface for a repository interface. +// +// See: https://github.com/zeta-chain/node/issues/4224 +type Client interface { + observer.SolanaClient + signer.SolanaClient + repo.SolanaClient +} diff --git a/zetaclient/chains/solana/observer/inbound.go b/zetaclient/chains/solana/observer/inbound.go index a94de30dd5..b9f6961b31 100644 --- a/zetaclient/chains/solana/observer/inbound.go +++ b/zetaclient/chains/solana/observer/inbound.go @@ -11,42 +11,41 @@ import ( "github.com/rs/zerolog" crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" - solanarpc "github.com/zeta-chain/node/zetaclient/chains/solana/rpc" + "github.com/zeta-chain/node/zetaclient/chains/solana/repo" "github.com/zeta-chain/node/zetaclient/compliance" "github.com/zeta-chain/node/zetaclient/logs" clienttypes "github.com/zeta-chain/node/zetaclient/types" "github.com/zeta-chain/node/zetaclient/zetacore" ) -const ( - // MaxSignaturesPerTicker is the maximum number of signatures to process on a ticker - MaxSignaturesPerTicker = 100 -) +// MaxSignaturesPerTicker is the maximum number of signatures to process on a ticker +const MaxSignaturesPerTicker = 100 // ObserveInbound observes the Solana chain for inbounds and post votes to zetacore. func (ob *Observer) ObserveInbound(ctx context.Context) error { chainID := ob.Chain().ChainId - pageLimit := solanarpc.DefaultPageLimit + pageLimit := repo.DefaultPageLimit // scan from gateway 1st signature if last scanned tx is absent in the database // the 1st gateway signature is typically the program initialization if ob.LastTxScanned() == "" { - lastSig, err := solanarpc.GetFirstSignatureForAddress(ctx, ob.solClient, ob.gatewayID, pageLimit) + lastSig, err := ob.solanaRepo.GetFirstSignatureForAddress(ctx, ob.gatewayID, pageLimit) if err != nil { - return errors.Wrapf(err, "error GetFirstSignatureForAddress for chain %d address %s", chainID, ob.gatewayID) + format := "error GetFirstSignatureForAddress for chain %d address %s" + return errors.Wrapf(err, format, chainID, ob.gatewayID) } ob.WithLastTxScanned(lastSig.String()) } // query last finalized slot - lastSlot, errSlot := ob.solClient.GetSlot(ctx, rpc.CommitmentFinalized) + lastSlot, errSlot := ob.solanaClient.GetSlot(ctx, rpc.CommitmentFinalized) if errSlot != nil { ob.Logger().Inbound.Err(errSlot).Msg("unable to get last slot") } // get all signatures for the gateway address since last scanned signature lastSig := solana.MustSignatureFromBase58(ob.LastTxScanned()) - signatures, err := solanarpc.GetSignaturesForAddressUntil(ctx, ob.solClient, ob.gatewayID, lastSig, pageLimit) + signatures, err := ob.solanaRepo.GetSignaturesForAddressUntil(ctx, ob.gatewayID, lastSig, pageLimit) if err != nil { ob.Logger().Inbound.Err(err).Msg("error calling GetSignaturesForAddressUntil") return err @@ -70,9 +69,9 @@ func (ob *Observer) ObserveInbound(ctx context.Context) error { // process successfully signature only if sig.Err == nil { - txResult, err := solanarpc.GetTransaction(ctx, ob.solClient, sig.Signature) + txResult, err := ob.solanaRepo.GetTransaction(ctx, sig.Signature) switch { - case errors.Is(err, solanarpc.ErrUnsupportedTxVersion): + case errors.Is(err, repo.ErrUnsupportedTxVersion): ob.Logger().Inbound.Warn(). Stringer("tx_signature", sig.Signature). Msg("observe inbound: skip unsupported transaction") diff --git a/zetaclient/chains/solana/observer/inbound_tracker.go b/zetaclient/chains/solana/observer/inbound_tracker.go index 9b2080db53..c389480012 100644 --- a/zetaclient/chains/solana/observer/inbound_tracker.go +++ b/zetaclient/chains/solana/observer/inbound_tracker.go @@ -6,7 +6,7 @@ import ( "github.com/gagliardetto/solana-go" "github.com/pkg/errors" - solanarpc "github.com/zeta-chain/node/zetaclient/chains/solana/rpc" + "github.com/zeta-chain/node/zetaclient/chains/solana/repo" ) // ProcessInboundTrackers processes inbound trackers @@ -20,9 +20,9 @@ func (ob *Observer) ProcessInboundTrackers(ctx context.Context) error { // process inbound trackers for _, tracker := range trackers { signature := solana.MustSignatureFromBase58(tracker.TxHash) - txResult, err := solanarpc.GetTransaction(ctx, ob.solClient, signature) + txResult, err := ob.solanaRepo.GetTransaction(ctx, signature) switch { - case errors.Is(err, solanarpc.ErrUnsupportedTxVersion): + case errors.Is(err, repo.ErrUnsupportedTxVersion): ob.Logger().Inbound.Warn(). Stringer("tx_signature", signature). Msg("skip inbound tracker hash") diff --git a/zetaclient/chains/solana/observer/observer.go b/zetaclient/chains/solana/observer/observer.go index 203f70e35c..265786d9b7 100644 --- a/zetaclient/chains/solana/observer/observer.go +++ b/zetaclient/chains/solana/observer/observer.go @@ -3,51 +3,110 @@ package observer import ( "context" - "github.com/gagliardetto/solana-go" - "github.com/gagliardetto/solana-go/rpc" + sol "github.com/gagliardetto/solana-go" + solrpc "github.com/gagliardetto/solana-go/rpc" "github.com/pkg/errors" contracts "github.com/zeta-chain/node/pkg/contracts/solana" "github.com/zeta-chain/node/zetaclient/chains/base" - "github.com/zeta-chain/node/zetaclient/chains/interfaces" - zetasolrpc "github.com/zeta-chain/node/zetaclient/chains/solana/rpc" + "github.com/zeta-chain/node/zetaclient/chains/solana/repo" "github.com/zeta-chain/node/zetaclient/logs" "github.com/zeta-chain/node/zetaclient/metrics" ) +// SolanaClient is the interface for the Solana RPC client. +type SolanaClient interface { + GetVersion(context.Context) (*solrpc.GetVersionResult, error) + + GetHealth(context.Context) (string, error) + + GetSlot(context.Context, solrpc.CommitmentType) (uint64, error) + + GetBlockTime(_ context.Context, block uint64) (*sol.UnixTimeSeconds, error) + + GetAccountInfo(context.Context, sol.PublicKey) (*solrpc.GetAccountInfoResult, error) + + GetAccountInfoWithOpts( + context.Context, + sol.PublicKey, + *solrpc.GetAccountInfoOpts, + ) (*solrpc.GetAccountInfoResult, error) + + GetBalance(_ context.Context, + account sol.PublicKey, + _ solrpc.CommitmentType, + ) (*solrpc.GetBalanceResult, error) + + GetLatestBlockhash(context.Context, + solrpc.CommitmentType, + ) (*solrpc.GetLatestBlockhashResult, error) + + GetRecentPrioritizationFees(_ context.Context, + accounts sol.PublicKeySlice, + ) ([]solrpc.PriorizationFeeResult, error) + + GetTransaction(context.Context, + sol.Signature, + *solrpc.GetTransactionOpts, + ) (*solrpc.GetTransactionResult, error) + + GetConfirmedTransactionWithOpts(context.Context, + sol.Signature, + *solrpc.GetTransactionOpts, + ) (*solrpc.TransactionWithMeta, error) + + GetSignaturesForAddressWithOpts(context.Context, + sol.PublicKey, + *solrpc.GetSignaturesForAddressOpts, + ) ([]*solrpc.TransactionSignature, error) + + SendTransactionWithOpts(context.Context, + *sol.Transaction, + solrpc.TransactionOpts, + ) (sol.Signature, error) +} + // Observer is the observer for the Solana chain type Observer struct { // base.Observer implements the base chain observer *base.Observer - // solClient is the Solana RPC client that interacts with the Solana chain - solClient interfaces.SolanaRPCClient + // solanaClient is the Solana RPC client that interacts with the Solana chain + solanaClient SolanaClient + + solanaRepo *repo.SolanaRepo // gatewayID is the program ID of gateway program on Solana chain - gatewayID solana.PublicKey + gatewayID sol.PublicKey // pda is the program derived address of the gateway program - pda solana.PublicKey + pda sol.PublicKey // finalizedTxResults indexes tx results with the outbound hash - finalizedTxResults map[string]*rpc.GetTransactionResult + finalizedTxResults map[string]*solrpc.GetTransactionResult } // New Observer constructor -func New(baseObserver *base.Observer, solClient interfaces.SolanaRPCClient, gatewayAddress string) (*Observer, error) { +func New(baseObserver *base.Observer, + solanaClient SolanaClient, + gatewayAddress string, +) (*Observer, error) { // parse gateway ID and PDA gatewayID, pda, err := contracts.ParseGatewayWithPDA(gatewayAddress) if err != nil { return nil, errors.Wrapf(err, "cannot parse gateway address %s", gatewayAddress) } + solanaRepo := repo.New(solanaClient) + // create solana observer ob := &Observer{ Observer: baseObserver, - solClient: solClient, + solanaClient: solanaClient, + solanaRepo: solanaRepo, gatewayID: gatewayID, pda: pda, - finalizedTxResults: make(map[string]*rpc.GetTransactionResult), + finalizedTxResults: make(map[string]*solrpc.GetTransactionResult), } ob.Observer.LoadLastTxScanned() @@ -66,14 +125,14 @@ func (ob *Observer) LoadLastTxScanned() error { } // SetTxResult sets the tx result for the given nonce -func (ob *Observer) SetTxResult(nonce uint64, result *rpc.GetTransactionResult) { +func (ob *Observer) SetTxResult(nonce uint64, result *solrpc.GetTransactionResult) { ob.Mu().Lock() defer ob.Mu().Unlock() ob.finalizedTxResults[ob.OutboundID(nonce)] = result } // GetTxResult returns the tx result for the given nonce -func (ob *Observer) GetTxResult(nonce uint64) *rpc.GetTransactionResult { +func (ob *Observer) GetTxResult(nonce uint64) *solrpc.GetTransactionResult { ob.Mu().Lock() defer ob.Mu().Unlock() return ob.finalizedTxResults[ob.OutboundID(nonce)] @@ -88,7 +147,7 @@ func (ob *Observer) IsTxFinalized(nonce uint64) bool { // CheckRPCStatus checks the RPC status of the Solana chain func (ob *Observer) CheckRPCStatus(ctx context.Context) error { - blockTime, err := zetasolrpc.HealthCheck(ctx, ob.solClient) + blockTime, err := ob.solanaRepo.HealthCheck(ctx) if err != nil { return errors.Wrap(err, "unable to check rpc status") } diff --git a/zetaclient/chains/solana/observer/observer_gas.go b/zetaclient/chains/solana/observer/observer_gas.go index 806852a500..86253b18a2 100644 --- a/zetaclient/chains/solana/observer/observer_gas.go +++ b/zetaclient/chains/solana/observer/observer_gas.go @@ -32,13 +32,13 @@ const ( // PostGasPrice posts gas price to zetacore func (ob *Observer) PostGasPrice(ctx context.Context) error { // get current slot - slot, err := ob.solClient.GetSlot(ctx, rpc.CommitmentConfirmed) + slot, err := ob.solanaClient.GetSlot(ctx, rpc.CommitmentConfirmed) if err != nil { return errors.Wrap(err, "GetSlot error") } // query recent priority fees - recentFees, err := ob.solClient.GetRecentPrioritizationFees(ctx, nil) + recentFees, err := ob.solanaClient.GetRecentPrioritizationFees(ctx, nil) if err != nil { return errors.Wrap(err, "GetRecentPrioritizationFees error") } diff --git a/zetaclient/chains/solana/observer/observer_test.go b/zetaclient/chains/solana/observer/observer_test.go index 117f1b4182..213362c9c4 100644 --- a/zetaclient/chains/solana/observer/observer_test.go +++ b/zetaclient/chains/solana/observer/observer_test.go @@ -20,10 +20,10 @@ import ( func MockSolanaObserver( t *testing.T, chain chains.Chain, - solClient interfaces.SolanaRPCClient, + solanaClient observer.SolanaClient, chainParams observertypes.ChainParams, zetacoreClient interfaces.ZetacoreClient, - tss interfaces.TSSSigner, + tssSigner interfaces.TSSSigner, ) *observer.Observer { // use mock zetacore client if not provided if zetacoreClient == nil { @@ -31,8 +31,8 @@ func MockSolanaObserver( } // use mock tss if not provided - if tss == nil { - tss = mocks.NewTSS(t) + if tssSigner == nil { + tssSigner = mocks.NewTSS(t) } database, err := db.NewFromSqliteInMemory(true) @@ -42,7 +42,7 @@ func MockSolanaObserver( chain, chainParams, zetacoreClient, - tss, + tssSigner, 1000, nil, database, @@ -50,7 +50,7 @@ func MockSolanaObserver( ) require.NoError(t, err) - ob, err := observer.New(baseObserver, solClient, chainParams.GatewayAddress) + ob, err := observer.New(baseObserver, solanaClient, chainParams.GatewayAddress) require.NoError(t, err) return ob diff --git a/zetaclient/chains/solana/observer/outbound.go b/zetaclient/chains/solana/observer/outbound.go index f366eafc38..ac44b68b9c 100644 --- a/zetaclient/chains/solana/observer/outbound.go +++ b/zetaclient/chains/solana/observer/outbound.go @@ -15,7 +15,6 @@ import ( "github.com/zeta-chain/node/pkg/coin" contracts "github.com/zeta-chain/node/pkg/contracts/solana" crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" - "github.com/zeta-chain/node/zetaclient/chains/interfaces" "github.com/zeta-chain/node/zetaclient/compliance" "github.com/zeta-chain/node/zetaclient/logs" "github.com/zeta-chain/node/zetaclient/zetacore" @@ -50,9 +49,9 @@ var ( // ProcessOutboundTrackers processes Solana outbound trackers func (ob *Observer) ProcessOutboundTrackers(ctx context.Context) error { chainID := ob.Chain().ChainId - trackers, err := ob.ZetacoreClient().GetAllOutboundTrackerByChain(ctx, chainID, interfaces.Ascending) + trackers, err := ob.ZetacoreClient().GetOutboundTrackers(ctx, chainID) if err != nil { - return errors.Wrap(err, "GetAllOutboundTrackerByChain error") + return errors.Wrap(err, "GetOutboundTrackers error") } logger := ob.Logger().Outbound @@ -259,7 +258,7 @@ func (ob *Observer) CheckFinalizedTx( } // query transaction using "finalized" commitment to avoid re-org - txResult, err := ob.solClient.GetTransaction(ctx, sig, &rpc.GetTransactionOpts{ + txResult, err := ob.solanaClient.GetTransaction(ctx, sig, &rpc.GetTransactionOpts{ Commitment: rpc.CommitmentFinalized, }) if err != nil { diff --git a/zetaclient/chains/solana/observer/outbound_test.go b/zetaclient/chains/solana/observer/outbound_test.go index 7752db2072..acbc9bedc8 100644 --- a/zetaclient/chains/solana/observer/outbound_test.go +++ b/zetaclient/chains/solana/observer/outbound_test.go @@ -67,8 +67,8 @@ const ( func createTestObserver( t *testing.T, chain chains.Chain, - solClient interfaces.SolanaRPCClient, - tss interfaces.TSSSigner, + solanaClient observer.SolanaClient, + tssSigner interfaces.TSSSigner, ) *observer.Observer { database, err := db.NewFromSqliteInMemory(true) require.NoError(t, err) @@ -80,10 +80,10 @@ func createTestObserver( chainParams := sample.ChainParams(chain.ChainId) chainParams.GatewayAddress = GatewayAddressTest - baseObserver, err := base.NewObserver(chain, *chainParams, nil, tss, 1000, nil, database, logger) + baseObserver, err := base.NewObserver(chain, *chainParams, nil, tssSigner, 1000, nil, database, logger) require.NoError(t, err) - ob, err := observer.New(baseObserver, solClient, chainParams.GatewayAddress) + ob, err := observer.New(baseObserver, solanaClient, chainParams.GatewayAddress) require.NoError(t, err) return ob diff --git a/zetaclient/chains/solana/rpc/rpc.go b/zetaclient/chains/solana/repo/repo.go similarity index 52% rename from zetaclient/chains/solana/rpc/rpc.go rename to zetaclient/chains/solana/repo/repo.go index 029f925122..7ee4213b87 100644 --- a/zetaclient/chains/solana/rpc/rpc.go +++ b/zetaclient/chains/solana/repo/repo.go @@ -1,25 +1,29 @@ -package rpc +// Package repo implements the Repository pattern to provide an abstraction layer over interactions +// with the Solana client. +// +// TODO: This is the start of a modularized repository for Solana, many functions in the +// observer-signer still call the RPC functions directly. We want to move all these usages to inside +// the SolanaRepo structure. +// +// See: https://github.com/zeta-chain/node/issues/4224 +package repo import ( "context" "strings" "time" - "github.com/gagliardetto/solana-go" - "github.com/gagliardetto/solana-go/rpc" + sol "github.com/gagliardetto/solana-go" + solrpc "github.com/gagliardetto/solana-go/rpc" "github.com/pkg/errors" - - "github.com/zeta-chain/node/zetaclient/chains/interfaces" ) const ( + // TODO: this does not need to be exported, and can remove pageLimit from GetFirst... params. + // // defaultPageLimit is the default number of signatures to fetch in one GetSignaturesForAddressWithOpts call DefaultPageLimit = 1000 - // RPCAlertLatency is the default threshold for RPC latency to be considered unhealthy and trigger an alert. - // The 'HEALTH_CHECK_SLOT_DISTANCE' is default to 150 slots, which is 150 * 0.4s = 60s - RPCAlertLatency = time.Duration(60) * time.Second - // see: https://github.com/solana-labs/solana/blob/master/rpc/src/rpc.rs#L7276 errorCodeUnsupportedTransactionVersion = "-32015" ) @@ -27,28 +31,52 @@ const ( // ErrUnsupportedTxVersion is returned when the transaction version is not supported by zetaclient var ErrUnsupportedTxVersion = errors.New("unsupported tx version") +type SolanaClient interface { + GetSlot(context.Context, solrpc.CommitmentType) (uint64, error) + + GetBlockTime(_ context.Context, block uint64) (*sol.UnixTimeSeconds, error) + + GetAccountInfo(context.Context, sol.PublicKey) (*solrpc.GetAccountInfoResult, error) + + GetTransaction(context.Context, + sol.Signature, + *solrpc.GetTransactionOpts, + ) (*solrpc.GetTransactionResult, error) + + GetSignaturesForAddressWithOpts(context.Context, + sol.PublicKey, + *solrpc.GetSignaturesForAddressOpts, + ) ([]*solrpc.TransactionSignature, error) +} + +type SolanaRepo struct { + solanaClient SolanaClient +} + +func New(solanaClient SolanaClient) *SolanaRepo { + return &SolanaRepo{solanaClient: solanaClient} +} + // GetFirstSignatureForAddress searches the first signature for the given address. -// Note: make sure that the rpc provider used has enough transaction history. -func GetFirstSignatureForAddress( - ctx context.Context, - client interfaces.SolanaRPCClient, - address solana.PublicKey, +// Note: make sure that the RPC provider used has enough transaction history. +func (repo SolanaRepo) GetFirstSignatureForAddress(ctx context.Context, + address sol.PublicKey, pageLimit int, -) (solana.Signature, error) { +) (sol.Signature, error) { // search backwards until we find the first signature - var lastSignature solana.Signature + var lastSignature sol.Signature for { - fetchedSignatures, err := client.GetSignaturesForAddressWithOpts( + fetchedSignatures, err := repo.solanaClient.GetSignaturesForAddressWithOpts( ctx, address, - &rpc.GetSignaturesForAddressOpts{ + &solrpc.GetSignaturesForAddressOpts{ Limit: &pageLimit, Before: lastSignature, // exclusive - Commitment: rpc.CommitmentFinalized, + Commitment: solrpc.CommitmentFinalized, }, ) if err != nil { - return solana.Signature{}, errors.Wrapf( + return sol.Signature{}, errors.Wrapf( err, "error GetSignaturesForAddressWithOpts for address %s", address, @@ -72,34 +100,33 @@ func GetFirstSignatureForAddress( return lastSignature, nil } -// GetSignaturesForAddressUntil searches for signatures for the given address until the given signature (exclusive). +// GetSignaturesForAddressUntil searches for signatures for the given address until the given +// signature (exclusive). // Note: make sure that the rpc provider used has enough transaction history. -func GetSignaturesForAddressUntil( - ctx context.Context, - client interfaces.SolanaRPCClient, - address solana.PublicKey, - untilSig solana.Signature, +func (repo SolanaRepo) GetSignaturesForAddressUntil(ctx context.Context, + address sol.PublicKey, + untilSig sol.Signature, pageLimit int, -) ([]*rpc.TransactionSignature, error) { - var lastSignature solana.Signature - var allSignatures []*rpc.TransactionSignature +) ([]*solrpc.TransactionSignature, error) { + var lastSignature sol.Signature + var allSignatures []*solrpc.TransactionSignature // make sure that the 'untilSig' exists to prevent undefined behavior on GetSignaturesForAddressWithOpts - _, err := GetTransaction(ctx, client, untilSig) + _, err := repo.GetTransaction(ctx, untilSig) if err != nil && !errors.Is(err, ErrUnsupportedTxVersion) { return nil, errors.Wrapf(err, "error GetTransaction for untilSig %s", untilSig) } // search backwards until we hit the 'untilSig' signature for { - fetchedSignatures, err := client.GetSignaturesForAddressWithOpts( + fetchedSignatures, err := repo.solanaClient.GetSignaturesForAddressWithOpts( ctx, address, - &rpc.GetSignaturesForAddressOpts{ + &solrpc.GetSignaturesForAddressOpts{ Limit: &pageLimit, Before: lastSignature, // exclusive Until: untilSig, // exclusive - Commitment: rpc.CommitmentFinalized, + Commitment: solrpc.CommitmentFinalized, }, ) if err != nil { @@ -127,14 +154,12 @@ func GetSignaturesForAddressUntil( // GetTransaction fetches a transaction with the given signature. // Note that it might return ErrUnsupportedTxVersion (for tx that we don't support yet). -func GetTransaction( - ctx context.Context, - client interfaces.SolanaRPCClient, - sig solana.Signature, -) (*rpc.GetTransactionResult, error) { - txResult, err := client.GetTransaction(ctx, sig, &rpc.GetTransactionOpts{ - Commitment: rpc.CommitmentFinalized, - MaxSupportedTransactionVersion: &rpc.MaxSupportedTransactionVersion0, +func (repo SolanaRepo) GetTransaction(ctx context.Context, + sig sol.Signature, +) (*solrpc.GetTransactionResult, error) { + txResult, err := repo.solanaClient.GetTransaction(ctx, sig, &solrpc.GetTransactionOpts{ + Commitment: solrpc.CommitmentFinalized, + MaxSupportedTransactionVersion: &solrpc.MaxSupportedTransactionVersion0, }) switch { @@ -148,15 +173,15 @@ func GetTransaction( } // HealthCheck returns the last block time -func HealthCheck(ctx context.Context, client interfaces.SolanaRPCClient) (time.Time, error) { +func (repo SolanaRepo) HealthCheck(ctx context.Context) (time.Time, error) { // query latest slot - slot, err := client.GetSlot(ctx, rpc.CommitmentFinalized) + slot, err := repo.solanaClient.GetSlot(ctx, solrpc.CommitmentFinalized) if err != nil { return time.Time{}, errors.Wrap(err, "unable to get latest slot") } // query latest block time - blockTime, err := client.GetBlockTime(ctx, slot) + blockTime, err := repo.solanaClient.GetBlockTime(ctx, slot) if err != nil { return time.Time{}, errors.Wrap(err, "unable to get latest block time") } diff --git a/zetaclient/chains/solana/rpc/rpc_live_test.go b/zetaclient/chains/solana/repo/repo_test.go similarity index 77% rename from zetaclient/chains/solana/rpc/rpc_live_test.go rename to zetaclient/chains/solana/repo/repo_test.go index 9a193bab48..63619e33c8 100644 --- a/zetaclient/chains/solana/rpc/rpc_live_test.go +++ b/zetaclient/chains/solana/repo/repo_test.go @@ -1,20 +1,20 @@ -package rpc_test +package repo_test import ( "context" "testing" "github.com/gagliardetto/solana-go" - solanarpc "github.com/gagliardetto/solana-go/rpc" + solrpc "github.com/gagliardetto/solana-go/rpc" "github.com/stretchr/testify/require" "github.com/zeta-chain/node/pkg/chains" - "github.com/zeta-chain/node/zetaclient/chains/solana/rpc" + "github.com/zeta-chain/node/zetaclient/chains/solana/repo" "github.com/zeta-chain/node/zetaclient/common" "github.com/zeta-chain/node/zetaclient/testutils" ) -// Test_SolanaRPCLive is a phony test to run all live tests -func Test_SolanaRPCLive(t *testing.T) { +// Test_SolanaRepoLive is a phony test to run all live tests +func Test_SolanaRepoLive(t *testing.T) { if !common.LiveTestEnabled() { return } @@ -42,7 +42,9 @@ func Test_SolanaRPCLive(t *testing.T) { func Run_GetTransactionWithVersion(t *testing.T) { // create a Solana devnet RPC client - client := solanarpc.New(solanarpc.DevNet_RPC) + client := solrpc.New(solrpc.DevNet_RPC) + + repo := repo.New(client) // example transaction of version "0" // https://explorer.solana.com/tx/Wqgj7hAaUUSfLzieN912G7GxyGHijzBZgY135NtuFtPRjevK8DnYjWwQZy7LAKFQZu582wsjuab2QP27VMUJzAi?cluster=devnet @@ -52,7 +54,7 @@ func Run_GetTransactionWithVersion(t *testing.T) { t.Run("should get the transaction if the version is supported", func(t *testing.T) { ctx := context.Background() - txResult, err := rpc.GetTransaction(ctx, client, txSig) + txResult, err := repo.GetTransaction(ctx, txSig) require.NoError(t, err) require.NotNil(t, txResult) }) @@ -60,13 +62,15 @@ func Run_GetTransactionWithVersion(t *testing.T) { func Run_GetFirstSignatureForAddress(t *testing.T) { // create a Solana devnet RPC client - client := solanarpc.New(solanarpc.DevNet_RPC) + client := solrpc.New(solrpc.DevNet_RPC) + + repo := repo.New(client) // program address address := solana.MustPublicKeyFromBase58("2kJndCL9NBR36ySiQ4bmArs4YgWQu67LmCDfLzk5Gb7s") // get the first signature for the address (one by one) - sig, err := rpc.GetFirstSignatureForAddress(context.Background(), client, address, 1) + sig, err := repo.GetFirstSignatureForAddress(context.Background(), address, 1) require.NoError(t, err) // assert @@ -76,7 +80,9 @@ func Run_GetFirstSignatureForAddress(t *testing.T) { func Run_GetSignaturesForAddressUntil(t *testing.T) { // create a Solana devnet RPC client - client := solanarpc.New(solanarpc.DevNet_RPC) + client := solrpc.New(solrpc.DevNet_RPC) + + repo := repo.New(client) // program address address := solana.MustPublicKeyFromBase58("2kJndCL9NBR36ySiQ4bmArs4YgWQu67LmCDfLzk5Gb7s") @@ -85,7 +91,7 @@ func Run_GetSignaturesForAddressUntil(t *testing.T) { ) // get all signatures for the address until the first signature - sigs, err := rpc.GetSignaturesForAddressUntil(context.Background(), client, address, untilSig, 100) + sigs, err := repo.GetSignaturesForAddressUntil(context.Background(), address, untilSig, 100) require.NoError(t, err) // assert @@ -99,7 +105,9 @@ func Run_GetSignaturesForAddressUntil(t *testing.T) { func Run_GetSignaturesForAddressUntil_Version0(t *testing.T) { // create a Solana devnet RPC client - client := solanarpc.New(solanarpc.DevNet_RPC) + client := solrpc.New(solrpc.DevNet_RPC) + + repo := repo.New(client) // program address and signature of version "0" chain := chains.SolanaDevnet @@ -109,16 +117,18 @@ func Run_GetSignaturesForAddressUntil_Version0(t *testing.T) { ) // should get all signatures for the address until a signature of version "0" successfully - _, err := rpc.GetSignaturesForAddressUntil(context.Background(), client, address, untilSig, 100) + _, err := repo.GetSignaturesForAddressUntil(context.Background(), address, untilSig, 100) require.NoError(t, err) } func Run_HealthCheck(t *testing.T) { // create a Solana devnet RPC client - client := solanarpc.New(solanarpc.DevNet_RPC) + client := solrpc.New(solrpc.DevNet_RPC) + + repo := repo.New(client) // check the RPC status ctx := context.Background() - _, err := rpc.HealthCheck(ctx, client) + _, err := repo.HealthCheck(ctx) require.NoError(t, err) } diff --git a/zetaclient/chains/solana/signer/execute.go b/zetaclient/chains/solana/signer/execute.go index a4db6e249d..c9ae7f7635 100644 --- a/zetaclient/chains/solana/signer/execute.go +++ b/zetaclient/chains/solana/signer/execute.go @@ -6,7 +6,7 @@ import ( "cosmossdk.io/errors" "github.com/ethereum/go-ethereum/common" - "github.com/gagliardetto/solana-go" + sol "github.com/gagliardetto/solana-go" "github.com/near/borsh-go" "github.com/rs/zerolog" @@ -81,10 +81,10 @@ func (signer *Signer) createMsgExecute( return nil, nil, errors.Wrap(err, "cannot validate sender") } - remainingAccounts := []*solana.AccountMeta{} + remainingAccounts := []*sol.AccountMeta{} for _, a := range msg.Accounts { - remainingAccounts = append(remainingAccounts, &solana.AccountMeta{ - PublicKey: solana.PublicKey(a.PublicKey), + remainingAccounts = append(remainingAccounts, &sol.AccountMeta{ + PublicKey: sol.PublicKey(a.PublicKey), IsWritable: a.IsWritable, }) } @@ -105,7 +105,7 @@ func (signer *Signer) createMsgExecute( } // createExecuteInstruction wraps the execute 'msg' into a Solana instruction. -func (signer *Signer) createExecuteInstruction(msg contracts.MsgExecute) (*solana.GenericInstruction, error) { +func (signer *Signer) createExecuteInstruction(msg contracts.MsgExecute) (*sol.GenericInstruction, error) { // create execute instruction with program call data discriminator := contracts.DiscriminatorExecute var dataBytes []byte @@ -114,7 +114,7 @@ func (signer *Signer) createExecuteInstruction(msg contracts.MsgExecute) (*solan serializedInst, err := borsh.Serialize(contracts.ExecuteRevertInstructionParams{ Discriminator: discriminator, Amount: msg.Amount(), - Sender: solana.MustPublicKeyFromBase58(msg.Sender()), + Sender: sol.MustPublicKeyFromBase58(msg.Sender()), Data: msg.Data(), Signature: msg.SigRS(), RecoveryID: msg.SigV(), @@ -149,15 +149,15 @@ func (signer *Signer) createExecuteInstruction(msg contracts.MsgExecute) (*solan return nil, errors.Wrap(err, "cannot decode connected pda address") } - predefinedAccounts := []*solana.AccountMeta{ - solana.Meta(signer.relayerKey.PublicKey()).WRITE().SIGNER(), - solana.Meta(signer.pda).WRITE(), - solana.Meta(msg.To()).WRITE(), - solana.Meta(destinationProgramPda).WRITE(), + predefinedAccounts := []*sol.AccountMeta{ + sol.Meta(signer.relayerKey.PublicKey()).WRITE().SIGNER(), + sol.Meta(signer.pda).WRITE(), + sol.Meta(msg.To()).WRITE(), + sol.Meta(destinationProgramPda).WRITE(), } allAccounts := append(predefinedAccounts, msg.RemainingAccounts()...) - inst := &solana.GenericInstruction{ + inst := &sol.GenericInstruction{ ProgID: signer.gatewayID, DataBytes: dataBytes, AccountValues: allAccounts, @@ -178,7 +178,7 @@ func validateSender(sender string, executeType contracts.ExecuteType) (string, e } // for revert execute, sender should be a Solana address - senderSol, err := solana.PublicKeyFromBase58(sender) + senderSol, err := sol.PublicKeyFromBase58(sender) if err != nil { return "", errors.Wrapf(err, "invalid execute revert sender %s", sender) } diff --git a/zetaclient/chains/solana/signer/execute_spl.go b/zetaclient/chains/solana/signer/execute_spl.go index 0e4d176eb5..04906fb4a6 100644 --- a/zetaclient/chains/solana/signer/execute_spl.go +++ b/zetaclient/chains/solana/signer/execute_spl.go @@ -5,7 +5,7 @@ import ( "cosmossdk.io/errors" "github.com/ethereum/go-ethereum/common" - "github.com/gagliardetto/solana-go" + sol "github.com/gagliardetto/solana-go" "github.com/near/borsh-go" "github.com/rs/zerolog" @@ -87,7 +87,7 @@ func (signer *Signer) createMsgExecuteSPL( } // parse mint account - mintAccount, err := solana.PublicKeyFromBase58(cctx.InboundParams.Asset) + mintAccount, err := sol.PublicKeyFromBase58(cctx.InboundParams.Asset) if err != nil { return nil, nil, errors.Wrapf(err, "cannot parse asset public key %s", cctx.InboundParams.Asset) } @@ -98,7 +98,7 @@ func (signer *Signer) createMsgExecuteSPL( return nil, nil, errors.Wrap(err, "cannot decode connected spl pda address") } - destinationProgramPdaAta, _, err := solana.FindAssociatedTokenAddress(destinationProgramPda, mintAccount) + destinationProgramPdaAta, _, err := sol.FindAssociatedTokenAddress(destinationProgramPda, mintAccount) if err != nil { return nil, nil, errors.Wrapf( err, @@ -108,10 +108,10 @@ func (signer *Signer) createMsgExecuteSPL( ) } - remainingAccounts := []*solana.AccountMeta{} + remainingAccounts := []*sol.AccountMeta{} for _, a := range msg.Accounts { - remainingAccounts = append(remainingAccounts, &solana.AccountMeta{ - PublicKey: solana.PublicKey(a.PublicKey), + remainingAccounts = append(remainingAccounts, &sol.AccountMeta{ + PublicKey: sol.PublicKey(a.PublicKey), IsWritable: a.IsWritable, }) } @@ -137,7 +137,7 @@ func (signer *Signer) createMsgExecuteSPL( } // createExecuteSPLInstruction wraps the execute spl 'msg' into a Solana instruction. -func (signer *Signer) createExecuteSPLInstruction(msg contracts.MsgExecuteSPL) (*solana.GenericInstruction, error) { +func (signer *Signer) createExecuteSPLInstruction(msg contracts.MsgExecuteSPL) (*sol.GenericInstruction, error) { // create execute spl instruction with program call data var dataBytes []byte if msg.ExecuteType() == contracts.ExecuteTypeRevert { @@ -145,7 +145,7 @@ func (signer *Signer) createExecuteSPLInstruction(msg contracts.MsgExecuteSPL) ( Discriminator: contracts.DiscriminatorExecuteSPLRevert, Decimals: msg.Decimals(), Amount: msg.Amount(), - Sender: solana.MustPublicKeyFromBase58(msg.Sender()), + Sender: sol.MustPublicKeyFromBase58(msg.Sender()), Data: msg.Data(), Signature: msg.SigRS(), RecoveryID: msg.SigV(), @@ -176,7 +176,7 @@ func (signer *Signer) createExecuteSPLInstruction(msg contracts.MsgExecuteSPL) ( dataBytes = serializedInst } - pdaAta, _, err := solana.FindAssociatedTokenAddress(signer.pda, msg.MintAccount()) + pdaAta, _, err := sol.FindAssociatedTokenAddress(signer.pda, msg.MintAccount()) if err != nil { return nil, errors.Wrapf(err, "cannot find ATA for %s and mint account %s", signer.pda, msg.MintAccount()) } @@ -186,21 +186,21 @@ func (signer *Signer) createExecuteSPLInstruction(msg contracts.MsgExecuteSPL) ( return nil, errors.Wrap(err, "cannot decode connected spl pda address") } - predefinedAccounts := []*solana.AccountMeta{ - solana.Meta(signer.relayerKey.PublicKey()).WRITE().SIGNER(), - solana.Meta(signer.pda).WRITE(), - solana.Meta(pdaAta).WRITE(), - solana.Meta(msg.MintAccount()), - solana.Meta(msg.To()), - solana.Meta(destinationProgramPda).WRITE(), - solana.Meta(msg.RecipientAta()).WRITE(), - solana.Meta(solana.TokenProgramID), - solana.Meta(solana.SPLAssociatedTokenAccountProgramID), - solana.Meta(solana.SystemProgramID), + predefinedAccounts := []*sol.AccountMeta{ + sol.Meta(signer.relayerKey.PublicKey()).WRITE().SIGNER(), + sol.Meta(signer.pda).WRITE(), + sol.Meta(pdaAta).WRITE(), + sol.Meta(msg.MintAccount()), + sol.Meta(msg.To()), + sol.Meta(destinationProgramPda).WRITE(), + sol.Meta(msg.RecipientAta()).WRITE(), + sol.Meta(sol.TokenProgramID), + sol.Meta(sol.SPLAssociatedTokenAccountProgramID), + sol.Meta(sol.SystemProgramID), } allAccounts := append(predefinedAccounts, msg.RemainingAccounts()...) - inst := &solana.GenericInstruction{ + inst := &sol.GenericInstruction{ ProgID: signer.gatewayID, DataBytes: dataBytes, AccountValues: allAccounts, diff --git a/zetaclient/chains/solana/signer/fallback_tx_test.go b/zetaclient/chains/solana/signer/fallback_tx_test.go index 9933705040..24f05b11c8 100644 --- a/zetaclient/chains/solana/signer/fallback_tx_test.go +++ b/zetaclient/chains/solana/signer/fallback_tx_test.go @@ -10,7 +10,7 @@ import ( ) func makeTestRpcError(message string, logs []string) *jsonrpc.RPCError { - var rawLogs []interface{} + var rawLogs []any for _, l := range logs { rawLogs = append(rawLogs, l) } @@ -18,7 +18,7 @@ func makeTestRpcError(message string, logs []string) *jsonrpc.RPCError { return &jsonrpc.RPCError{ Code: -32002, Message: message, - Data: map[string]interface{}{ + Data: map[string]any{ "logs": rawLogs, }, } diff --git a/zetaclient/chains/solana/signer/increment_nonce.go b/zetaclient/chains/solana/signer/increment_nonce.go index 369ce51729..2cae6b82e0 100644 --- a/zetaclient/chains/solana/signer/increment_nonce.go +++ b/zetaclient/chains/solana/signer/increment_nonce.go @@ -4,7 +4,7 @@ import ( "context" "cosmossdk.io/errors" - "github.com/gagliardetto/solana-go" + sol "github.com/gagliardetto/solana-go" "github.com/near/borsh-go" "github.com/rs/zerolog" @@ -95,7 +95,7 @@ func (signer *Signer) createAndSignMsgIncrementNonce( // createIncrementNonceInstruction wraps the increment_nonce 'msg' into a Solana instruction. func (signer *Signer) createIncrementNonceInstruction( msg contracts.MsgIncrementNonce, -) (*solana.GenericInstruction, error) { +) (*sol.GenericInstruction, error) { // create increment_nonce instruction with program call data dataBytes, err := borsh.Serialize(contracts.IncrementNonceInstructionParams{ Discriminator: contracts.DiscriminatorIncrementNonce, @@ -110,12 +110,12 @@ func (signer *Signer) createIncrementNonceInstruction( return nil, errors.Wrap(err, "cannot serialize increment_nonce instruction") } - inst := &solana.GenericInstruction{ + inst := &sol.GenericInstruction{ ProgID: signer.gatewayID, DataBytes: dataBytes, - AccountValues: []*solana.AccountMeta{ - solana.Meta(signer.relayerKey.PublicKey()).WRITE().SIGNER(), - solana.Meta(signer.pda).WRITE(), + AccountValues: []*sol.AccountMeta{ + sol.Meta(signer.relayerKey.PublicKey()).WRITE().SIGNER(), + sol.Meta(signer.pda).WRITE(), }, } diff --git a/zetaclient/chains/solana/signer/outbound_tracker_reporter.go b/zetaclient/chains/solana/signer/outbound_tracker_reporter.go index 9690b11e1f..3859f9a863 100644 --- a/zetaclient/chains/solana/signer/outbound_tracker_reporter.go +++ b/zetaclient/chains/solana/signer/outbound_tracker_reporter.go @@ -4,7 +4,7 @@ import ( "context" "time" - "github.com/gagliardetto/solana-go" + sol "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" "github.com/rs/zerolog" @@ -21,7 +21,7 @@ func (signer *Signer) reportToOutboundTracker( zetacoreClient interfaces.ZetacoreClient, chainID int64, nonce uint64, - txSig solana.Signature, + txSig sol.Signature, logger zerolog.Logger, ) { // prepare logger @@ -59,7 +59,7 @@ func (signer *Signer) reportToOutboundTracker( } // query tx using optimistic commitment level "confirmed" - tx, err := signer.client.GetTransaction(ctx, txSig, &rpc.GetTransactionOpts{ + tx, err := signer.solanaClient.GetTransaction(ctx, txSig, &rpc.GetTransactionOpts{ // commitment "processed" seems to be a better choice but it's not supported // see: https://solana.com/docs/rpc/http/gettransaction Commitment: rpc.CommitmentConfirmed, diff --git a/zetaclient/chains/solana/signer/signer.go b/zetaclient/chains/solana/signer/signer.go index 7e5cb7bda3..0510fbf716 100644 --- a/zetaclient/chains/solana/signer/signer.go +++ b/zetaclient/chains/solana/signer/signer.go @@ -5,9 +5,9 @@ import ( "runtime/debug" "time" - "github.com/gagliardetto/solana-go" + sol "github.com/gagliardetto/solana-go" computebudget "github.com/gagliardetto/solana-go/programs/compute-budget" - "github.com/gagliardetto/solana-go/rpc" + solrpc "github.com/gagliardetto/solana-go/rpc" "github.com/pkg/errors" "github.com/rs/zerolog" @@ -42,14 +42,44 @@ const ( // reduces the expiration of tx by about 13 seconds. The "confirmed" level has very low risk of // belonging to a dropped fork. // see: https://solana.com/developers/guides/advanced/confirmation#use-an-appropriate-preflight-commitment-level - broadcastOutboundCommitment = rpc.CommitmentConfirmed + broadcastOutboundCommitment = solrpc.CommitmentConfirmed // SolanaMaxComputeBudget is the max compute budget for a transaction. SolanaMaxComputeBudget = 1_400_000 ) +// SolanaClient is the interface for the Solana RPC client. +type SolanaClient interface { + GetAccountInfo(context.Context, sol.PublicKey) (*solrpc.GetAccountInfoResult, error) + + GetAccountInfoWithOpts( + context.Context, + sol.PublicKey, + *solrpc.GetAccountInfoOpts, + ) (*solrpc.GetAccountInfoResult, error) + + GetBalance(_ context.Context, + account sol.PublicKey, + _ solrpc.CommitmentType, + ) (*solrpc.GetBalanceResult, error) + + GetLatestBlockhash(context.Context, + solrpc.CommitmentType, + ) (*solrpc.GetLatestBlockhashResult, error) + + GetTransaction(context.Context, + sol.Signature, + *solrpc.GetTransactionOpts, + ) (*solrpc.GetTransactionResult, error) + + SendTransactionWithOpts(context.Context, + *sol.Transaction, + solrpc.TransactionOpts, + ) (sol.Signature, error) +} + type Outbound struct { - Tx *solana.Transaction + Tx *sol.Transaction FallbackMsg *contracts.MsgIncrementNonce } @@ -59,24 +89,23 @@ type outboundGetter func() (*Outbound, error) type Signer struct { *base.Signer - // client is the Solana RPC client that interacts with the Solana chain - client interfaces.SolanaRPCClient + // solanaClient is the Solana RPC client that interacts with the Solana chain + solanaClient SolanaClient // relayerKey is the private key of the relayer account for Solana chain // relayerKey is optional, the signer will not relay transactions if it is not set - relayerKey *solana.PrivateKey + relayerKey *sol.PrivateKey // gatewayID is the program ID of gateway program on Solana chain - gatewayID solana.PublicKey + gatewayID sol.PublicKey // pda is the program derived address of the gateway program - pda solana.PublicKey + pda sol.PublicKey } // New Signer constructor. -func New( - baseSigner *base.Signer, - solClient interfaces.SolanaRPCClient, +func New(baseSigner *base.Signer, + solanaClient SolanaClient, gatewayAddress string, relayerKey *keys.RelayerKey, ) (*Signer, error) { @@ -86,12 +115,12 @@ func New( return nil, errors.Wrapf(err, "cannot parse gateway address %s", gatewayAddress) } - var rk *solana.PrivateKey + var rk *sol.PrivateKey if relayerKey != nil { - pk, err := solana.PrivateKeyFromBase58(relayerKey.PrivateKey) + pk, err := sol.PrivateKeyFromBase58(relayerKey.PrivateKey) if err != nil { - return nil, errors.Wrap(err, "unable to construct solana private key") + return nil, errors.Wrap(err, "unable to construct Solana private key") } rk = &pk @@ -103,11 +132,11 @@ func New( } return &Signer{ - Signer: baseSigner, - client: solClient, - gatewayID: gatewayID, - relayerKey: rk, - pda: pda, + Signer: baseSigner, + solanaClient: solanaClient, + gatewayID: gatewayID, + relayerKey: rk, + pda: pda, }, nil } @@ -250,17 +279,17 @@ func (signer *Signer) TryProcessOutbound( // signTx creates and signs solana tx containing provided instruction with relayer key. func (signer *Signer) signTx( ctx context.Context, - inst *solana.GenericInstruction, + inst *sol.GenericInstruction, limit uint64, -) (*solana.Transaction, error) { +) (*sol.Transaction, error) { // get a recent blockhash - recent, err := signer.client.GetLatestBlockhash(ctx, broadcastOutboundCommitment) + recent, err := signer.solanaClient.GetLatestBlockhash(ctx, broadcastOutboundCommitment) if err != nil { return nil, errors.Wrap(err, "getLatestBlockhash error") } // if limit is provided, prepend compute unit limit instruction - var instructions []solana.Instruction + var instructions []sol.Instruction if limit > 0 { limit = min(limit, SolanaMaxComputeBudget) // #nosec G115 always in range @@ -271,19 +300,19 @@ func (signer *Signer) signTx( instructions = append(instructions, inst) // create a transaction that wraps the instruction - tx, err := solana.NewTransaction( + tx, err := sol.NewTransaction( // TODO: outbound now uses 5K lamports as the fixed fee, we could explore priority fee and compute budget // https://github.com/zeta-chain/node/issues/2599 instructions, recent.Value.Blockhash, - solana.TransactionPayer(signer.relayerKey.PublicKey()), + sol.TransactionPayer(signer.relayerKey.PublicKey()), ) if err != nil { return nil, errors.Wrap(err, "unable to create new tx") } // relayer signs the transaction - _, err = tx.Sign(func(key solana.PublicKey) *solana.PrivateKey { + _, err = tx.Sign(func(key sol.PublicKey) *sol.PrivateKey { if key.Equals(signer.relayerKey.PublicKey()) { return signer.relayerKey } @@ -335,10 +364,10 @@ func (signer *Signer) broadcastOutbound( // broadcast the signed tx to the Solana network with preflight check // the PDA nonce MUST be equal to 'nonce' if arrived here, guaranteed by upstream code - txSig, err := signer.client.SendTransactionWithOpts( + txSig, err := signer.solanaClient.SendTransactionWithOpts( ctx, tx, - rpc.TransactionOpts{PreflightCommitment: broadcastOutboundCommitment}, + solrpc.TransactionOpts{PreflightCommitment: broadcastOutboundCommitment}, ) if err != nil { shouldUseFallbackTx, failureReason := parseRPCErrorForFallback(err, signer.GetGatewayAddress()) @@ -374,7 +403,7 @@ func (signer *Signer) broadcastOutbound( // and signs them with relayer key func (signer *Signer) createOutboundWithFallback( ctx context.Context, - mainInst *solana.GenericInstruction, + mainInst *sol.GenericInstruction, msgIn *contracts.MsgIncrementNonce, computeLimit uint64, ) (*Outbound, error) { @@ -434,12 +463,12 @@ func (signer *Signer) SetRelayerBalanceMetrics(ctx context.Context) { return } - result, err := signer.client.GetBalance(ctx, signer.relayerKey.PublicKey(), rpc.CommitmentFinalized) + result, err := signer.solanaClient.GetBalance(ctx, signer.relayerKey.PublicKey(), solrpc.CommitmentFinalized) if err != nil { signer.Logger().Std.Error().Err(err).Msg("error calling GetBalance") return } - solBalance := float64(result.Value) / float64(solana.LAMPORTS_PER_SOL) + solBalance := float64(result.Value) / float64(sol.LAMPORTS_PER_SOL) metrics.RelayerKeyBalance.WithLabelValues(signer.Chain().Name).Set(solBalance) } @@ -530,10 +559,10 @@ func (signer *Signer) waitExactGatewayNonce(ctx context.Context, nonce uint64) e // getGatewayNonce queries the gateway nonce from the PDA account information func (signer *Signer) getGatewayNonce(ctx context.Context) (uint64, error) { // query the gateway PDA account information - pdaInfo, err := signer.client.GetAccountInfoWithOpts( + pdaInfo, err := signer.solanaClient.GetAccountInfoWithOpts( ctx, signer.pda, - &rpc.GetAccountInfoOpts{Commitment: broadcastOutboundCommitment}, + &solrpc.GetAccountInfoOpts{Commitment: broadcastOutboundCommitment}, ) if err != nil { return 0, errors.Wrap(err, "unable to get gateway PDA account info") diff --git a/zetaclient/chains/solana/signer/signer_test.go b/zetaclient/chains/solana/signer/signer_test.go index d6a8cdfb5d..0b295bdca5 100644 --- a/zetaclient/chains/solana/signer/signer_test.go +++ b/zetaclient/chains/solana/signer/signer_test.go @@ -28,22 +28,22 @@ func Test_NewSigner(t *testing.T) { chainParams.GatewayAddress = testutils.GatewayAddresses[chain.ChainId] tests := []struct { - name string - chain chains.Chain - chainParams observertypes.ChainParams - solClient interfaces.SolanaRPCClient - tss interfaces.TSSSigner - relayerKey *keys.RelayerKey - ts *metrics.TelemetryServer - logger base.Logger - errMessage string + name string + chain chains.Chain + chainParams observertypes.ChainParams + solanaClient signer.SolanaClient + tssSigner interfaces.TSSSigner + relayerKey *keys.RelayerKey + ts *metrics.TelemetryServer + logger base.Logger + errMessage string }{ { - name: "should create solana signer successfully with relayer key", - chain: chain, - chainParams: *chainParams, - solClient: nil, - tss: nil, + name: "should create solana signer successfully with relayer key", + chain: chain, + chainParams: *chainParams, + solanaClient: nil, + tssSigner: nil, relayerKey: &keys.RelayerKey{ PrivateKey: "3EMjCcCJg53fMEGVj13UPQpo6py9AKKyLE2qroR4yL1SvAN2tUznBvDKRYjntw7m6Jof1R2CSqjTddL27rEb6sFQ", }, @@ -51,13 +51,13 @@ func Test_NewSigner(t *testing.T) { logger: base.DefaultLogger(), }, { - name: "should create solana signer successfully without relayer key", - chainParams: *chainParams, - solClient: nil, - tss: nil, - relayerKey: nil, - ts: nil, - logger: base.DefaultLogger(), + name: "should create solana signer successfully without relayer key", + chainParams: *chainParams, + solanaClient: nil, + tssSigner: nil, + relayerKey: nil, + ts: nil, + logger: base.DefaultLogger(), }, { name: "should fail to create solana signer with invalid gateway address", @@ -66,31 +66,31 @@ func Test_NewSigner(t *testing.T) { cp.GatewayAddress = "invalid" return cp }(), - solClient: nil, - tss: nil, - relayerKey: nil, - ts: nil, - logger: base.DefaultLogger(), - errMessage: "cannot parse gateway address", + solanaClient: nil, + tssSigner: nil, + relayerKey: nil, + ts: nil, + logger: base.DefaultLogger(), + errMessage: "cannot parse gateway address", }, { - name: "should fail to create solana signer with invalid relayer key", - chainParams: *chainParams, - solClient: nil, - tss: nil, + name: "should fail to create solana signer with invalid relayer key", + chainParams: *chainParams, + solanaClient: nil, + tssSigner: nil, relayerKey: &keys.RelayerKey{ PrivateKey: "3EMjCcCJg53fMEGVj13", // too short }, ts: nil, logger: base.DefaultLogger(), - errMessage: "unable to construct solana private key", + errMessage: "unable to construct Solana private key", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - baseSigner := base.NewSigner(tt.chain, tt.tss, tt.logger) - s, err := signer.New(baseSigner, tt.solClient, tt.chainParams.GatewayAddress, tt.relayerKey) + baseSigner := base.NewSigner(tt.chain, tt.tssSigner, tt.logger) + s, err := signer.New(baseSigner, tt.solanaClient, tt.chainParams.GatewayAddress, tt.relayerKey) if tt.errMessage != "" { require.ErrorContains(t, err, tt.errMessage) require.Nil(t, s) diff --git a/zetaclient/chains/solana/signer/whitelist.go b/zetaclient/chains/solana/signer/whitelist.go index 2fc1381410..b29e7c2aaa 100644 --- a/zetaclient/chains/solana/signer/whitelist.go +++ b/zetaclient/chains/solana/signer/whitelist.go @@ -6,7 +6,7 @@ import ( "strings" "cosmossdk.io/errors" - "github.com/gagliardetto/solana-go" + sol "github.com/gagliardetto/solana-go" "github.com/near/borsh-go" contracts "github.com/zeta-chain/node/pkg/contracts/solana" @@ -25,13 +25,13 @@ func (signer *Signer) prepareWhitelistTx( return nil, fmt.Errorf("TryProcessOutbound: invalid relayed msg") } - pk, err := solana.PublicKeyFromBase58(relayedMsg[1]) + pk, err := sol.PublicKeyFromBase58(relayedMsg[1]) if err != nil { return nil, errors.Wrapf(err, "publicKeyFromBase58 %s error", relayedMsg[1]) } seed := [][]byte{[]byte("whitelist"), pk.Bytes()} - whitelistEntryPDA, _, err := solana.FindProgramAddress(seed, signer.gatewayID) + whitelistEntryPDA, _, err := sol.FindProgramAddress(seed, signer.gatewayID) if err != nil { return nil, errors.Wrapf(err, "findProgramAddress error for seed %s", seed) } @@ -62,8 +62,8 @@ func (signer *Signer) createAndSignMsgWhitelist( ctx context.Context, params *types.OutboundParams, height uint64, - whitelistCandidate solana.PublicKey, - whitelistEntry solana.PublicKey, + whitelistCandidate sol.PublicKey, + whitelistEntry sol.PublicKey, ) (*contracts.MsgWhitelist, error) { chain := signer.Chain() // #nosec G115 always positive @@ -86,7 +86,7 @@ func (signer *Signer) createAndSignMsgWhitelist( } // createWhitelistInstruction wraps the whitelist 'msg' into a Solana instruction. -func (signer *Signer) createWhitelistInstruction(msg *contracts.MsgWhitelist) (*solana.GenericInstruction, error) { +func (signer *Signer) createWhitelistInstruction(msg *contracts.MsgWhitelist) (*sol.GenericInstruction, error) { // create whitelist_spl_mint instruction with program call data dataBytes, err := borsh.Serialize(contracts.WhitelistInstructionParams{ Discriminator: contracts.DiscriminatorWhitelistSplMint, @@ -99,15 +99,15 @@ func (signer *Signer) createWhitelistInstruction(msg *contracts.MsgWhitelist) (* return nil, errors.Wrap(err, "cannot serialize whitelist_spl_mint instruction") } - inst := &solana.GenericInstruction{ + inst := &sol.GenericInstruction{ ProgID: signer.gatewayID, DataBytes: dataBytes, - AccountValues: []*solana.AccountMeta{ - solana.Meta(signer.relayerKey.PublicKey()).WRITE().SIGNER(), - solana.Meta(signer.pda).WRITE(), - solana.Meta(msg.WhitelistEntry()).WRITE(), - solana.Meta(msg.WhitelistCandidate()), - solana.Meta(solana.SystemProgramID), + AccountValues: []*sol.AccountMeta{ + sol.Meta(signer.relayerKey.PublicKey()).WRITE().SIGNER(), + sol.Meta(signer.pda).WRITE(), + sol.Meta(msg.WhitelistEntry()).WRITE(), + sol.Meta(msg.WhitelistCandidate()), + sol.Meta(sol.SystemProgramID), }, } diff --git a/zetaclient/chains/solana/signer/withdraw.go b/zetaclient/chains/solana/signer/withdraw.go index cc5644d542..72946148a8 100644 --- a/zetaclient/chains/solana/signer/withdraw.go +++ b/zetaclient/chains/solana/signer/withdraw.go @@ -5,7 +5,7 @@ import ( "encoding/hex" "cosmossdk.io/errors" - "github.com/gagliardetto/solana-go" + sol "github.com/gagliardetto/solana-go" "github.com/near/borsh-go" "github.com/rs/zerolog" @@ -101,7 +101,7 @@ func (signer *Signer) createMsgWithdraw( } // createWithdrawInstruction wraps the withdraw 'msg' into a Solana instruction. -func (signer *Signer) createWithdrawInstruction(msg contracts.MsgWithdraw) (*solana.GenericInstruction, error) { +func (signer *Signer) createWithdrawInstruction(msg contracts.MsgWithdraw) (*sol.GenericInstruction, error) { // create withdraw instruction with program call data dataBytes, err := borsh.Serialize(contracts.WithdrawInstructionParams{ Discriminator: contracts.DiscriminatorWithdraw, @@ -115,13 +115,13 @@ func (signer *Signer) createWithdrawInstruction(msg contracts.MsgWithdraw) (*sol return nil, errors.Wrap(err, "cannot serialize withdraw instruction") } - inst := &solana.GenericInstruction{ + inst := &sol.GenericInstruction{ ProgID: signer.gatewayID, DataBytes: dataBytes, - AccountValues: []*solana.AccountMeta{ - solana.Meta(signer.relayerKey.PublicKey()).WRITE().SIGNER(), - solana.Meta(signer.pda).WRITE(), - solana.Meta(msg.To()).WRITE(), + AccountValues: []*sol.AccountMeta{ + sol.Meta(signer.relayerKey.PublicKey()).WRITE().SIGNER(), + sol.Meta(signer.pda).WRITE(), + sol.Meta(msg.To()).WRITE(), }, } diff --git a/zetaclient/chains/solana/signer/withdraw_spl.go b/zetaclient/chains/solana/signer/withdraw_spl.go index bd83b8ee24..98efde193f 100644 --- a/zetaclient/chains/solana/signer/withdraw_spl.go +++ b/zetaclient/chains/solana/signer/withdraw_spl.go @@ -4,7 +4,7 @@ import ( "context" "cosmossdk.io/errors" - "github.com/gagliardetto/solana-go" + sol "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/programs/token" "github.com/near/borsh-go" "github.com/rs/zerolog" @@ -80,13 +80,13 @@ func (signer *Signer) createMsgWithdrawSPL( } // parse mint account - mintAccount, err := solana.PublicKeyFromBase58(cctx.InboundParams.Asset) + mintAccount, err := sol.PublicKeyFromBase58(cctx.InboundParams.Asset) if err != nil { return nil, nil, errors.Wrapf(err, "cannot parse asset public key %s", cctx.InboundParams.Asset) } // get recipient ata - recipientAta, _, err := solana.FindAssociatedTokenAddress(to, mintAccount) + recipientAta, _, err := sol.FindAssociatedTokenAddress(to, mintAccount) if err != nil { return nil, nil, errors.Wrapf(err, "cannot find ATA for %s and mint account %s", to, mintAccount) } @@ -98,7 +98,7 @@ func (signer *Signer) createMsgWithdrawSPL( } // createWithdrawSPLInstruction wraps the withdraw spl 'msg' into a Solana instruction. -func (signer *Signer) createWithdrawSPLInstruction(msg contracts.MsgWithdrawSPL) (*solana.GenericInstruction, error) { +func (signer *Signer) createWithdrawSPLInstruction(msg contracts.MsgWithdrawSPL) (*sol.GenericInstruction, error) { // create withdraw spl instruction with program call data dataBytes, err := borsh.Serialize(contracts.WithdrawSPLInstructionParams{ Discriminator: contracts.DiscriminatorWithdrawSPL, @@ -113,29 +113,29 @@ func (signer *Signer) createWithdrawSPLInstruction(msg contracts.MsgWithdrawSPL) return nil, errors.Wrap(err, "cannot serialize withdraw instruction") } - pdaAta, _, err := solana.FindAssociatedTokenAddress(signer.pda, msg.MintAccount()) + pdaAta, _, err := sol.FindAssociatedTokenAddress(signer.pda, msg.MintAccount()) if err != nil { return nil, errors.Wrapf(err, "cannot find ATA for %s and mint account %s", signer.pda, msg.MintAccount()) } - recipientAta, _, err := solana.FindAssociatedTokenAddress(msg.To(), msg.MintAccount()) + recipientAta, _, err := sol.FindAssociatedTokenAddress(msg.To(), msg.MintAccount()) if err != nil { return nil, errors.Wrapf(err, "cannot find ATA for %s and mint account %s", msg.To(), msg.MintAccount()) } - inst := &solana.GenericInstruction{ + inst := &sol.GenericInstruction{ ProgID: signer.gatewayID, DataBytes: dataBytes, - AccountValues: []*solana.AccountMeta{ - solana.Meta(signer.relayerKey.PublicKey()).WRITE().SIGNER(), - solana.Meta(signer.pda).WRITE(), - solana.Meta(pdaAta).WRITE(), - solana.Meta(msg.MintAccount()), - solana.Meta(msg.To()), - solana.Meta(recipientAta).WRITE(), - solana.Meta(solana.TokenProgramID), - solana.Meta(solana.SPLAssociatedTokenAccountProgramID), - solana.Meta(solana.SystemProgramID), + AccountValues: []*sol.AccountMeta{ + sol.Meta(signer.relayerKey.PublicKey()).WRITE().SIGNER(), + sol.Meta(signer.pda).WRITE(), + sol.Meta(pdaAta).WRITE(), + sol.Meta(msg.MintAccount()), + sol.Meta(msg.To()), + sol.Meta(recipientAta).WRITE(), + sol.Meta(sol.TokenProgramID), + sol.Meta(sol.SPLAssociatedTokenAccountProgramID), + sol.Meta(sol.SystemProgramID), }, } @@ -143,12 +143,12 @@ func (signer *Signer) createWithdrawSPLInstruction(msg contracts.MsgWithdrawSPL) } func (signer *Signer) decodeMintAccountDetails(ctx context.Context, asset string) (token.Mint, error) { - mintPk, err := solana.PublicKeyFromBase58(asset) + mintPk, err := sol.PublicKeyFromBase58(asset) if err != nil { return token.Mint{}, err } - info, err := signer.client.GetAccountInfo(ctx, mintPk) + info, err := signer.solanaClient.GetAccountInfo(ctx, mintPk) if err != nil { return token.Mint{}, err } diff --git a/zetaclient/chains/sui/client.go b/zetaclient/chains/sui/client.go new file mode 100644 index 0000000000..505f4e81ca --- /dev/null +++ b/zetaclient/chains/sui/client.go @@ -0,0 +1,11 @@ +package sui + +import ( + "github.com/zeta-chain/node/zetaclient/chains/sui/observer" + "github.com/zeta-chain/node/zetaclient/chains/sui/signer" +) + +type Client interface { + signer.SuiClient + observer.SuiClient +} diff --git a/zetaclient/chains/sui/client/client.go b/zetaclient/chains/sui/client/client.go index 1c5986a131..5235c6a6b4 100644 --- a/zetaclient/chains/sui/client/client.go +++ b/zetaclient/chains/sui/client/client.go @@ -43,14 +43,9 @@ const ( sharedOwner = "Shared" ) -// NewFromEndpoint Client constructor based on endpoint string. -func NewFromEndpoint(endpoint string) *Client { - return New(sui.NewSuiClient(endpoint)) -} - -// New Client constructor. -func New(client sui.ISuiAPI) *Client { - return &Client{ISuiAPI: client} +// New constructs a new client given an endpoint. +func New(endpoint string) *Client { + return &Client{ISuiAPI: sui.NewSuiClient(endpoint)} } // HealthCheck queries latest checkpoint and returns its timestamp. diff --git a/zetaclient/chains/sui/client/client_live_test.go b/zetaclient/chains/sui/client/client_live_test.go index 7275f2afab..2e1dcd2f9d 100644 --- a/zetaclient/chains/sui/client/client_live_test.go +++ b/zetaclient/chains/sui/client/client_live_test.go @@ -306,7 +306,7 @@ type testSuite struct { func newTestSuite(t *testing.T, endpoint string) *testSuite { ctx := context.Background() - client := NewFromEndpoint(endpoint) + client := New(endpoint) return &testSuite{t: t, ctx: ctx, Client: client} } diff --git a/zetaclient/chains/sui/observer/inbound.go b/zetaclient/chains/sui/observer/inbound.go index 50209ea269..6698edc678 100644 --- a/zetaclient/chains/sui/observer/inbound.go +++ b/zetaclient/chains/sui/observer/inbound.go @@ -32,7 +32,7 @@ func (ob *Observer) ObserveInbound(ctx context.Context) error { } // Sui has a nice access-pattern of scrolling through contract events - events, _, err := ob.client.QueryModuleEvents(ctx, query) + events, _, err := ob.suiClient.QueryModuleEvents(ctx, query) if err != nil { return errors.Wrap(err, "unable to query module events") } @@ -125,7 +125,7 @@ func (ob *Observer) processInboundEvent( if tx == nil { txReq := models.SuiGetTransactionBlockRequest{Digest: event.TxHash} - txFresh, err := ob.client.SuiGetTransactionBlock(ctx, txReq) + txFresh, err := ob.suiClient.SuiGetTransactionBlock(ctx, txReq) if err != nil { return errors.Wrap(errTxNotFound, err.Error()) } @@ -153,7 +153,7 @@ func (ob *Observer) processInboundTracker(ctx context.Context, tracker cctypes.I Options: models.SuiTransactionBlockOptions{ShowEvents: true}, } - tx, err := ob.client.SuiGetTransactionBlock(ctx, req) + tx, err := ob.suiClient.SuiGetTransactionBlock(ctx, req) if err != nil { return errors.Wrapf(err, "unable to get transaction block") } diff --git a/zetaclient/chains/sui/observer/observer.go b/zetaclient/chains/sui/observer/observer.go index 9b58a66108..ab722f85a5 100644 --- a/zetaclient/chains/sui/observer/observer.go +++ b/zetaclient/chains/sui/observer/observer.go @@ -18,7 +18,9 @@ import ( // Observer Sui observer type Observer struct { *base.Observer - client RPC + + suiClient SuiClient + gateway *sui.Gateway // nonce -> sui outbound tx @@ -29,8 +31,8 @@ type Observer struct { gasPriceMu sync.RWMutex } -// RPC represents subset of Sui RPC methods. -type RPC interface { +// SuiClient represents subset of Sui SuiClient methods. +type SuiClient interface { HealthCheck(ctx context.Context) (time.Time, error) GetLatestCheckpoint(ctx context.Context) (models.CheckpointResponse, error) QueryModuleEvents(ctx context.Context, q client.EventQuery) ([]models.SuiEventResponse, string, error) @@ -43,12 +45,12 @@ type RPC interface { } // New Observer constructor. -func New(baseObserver *base.Observer, client RPC, gateway *sui.Gateway) *Observer { +func New(baseObserver *base.Observer, suiClient SuiClient, gateway *sui.Gateway) *Observer { ob := &Observer{ - Observer: baseObserver, - client: client, - gateway: gateway, - txMap: make(map[uint64]models.SuiTransactionBlockResponse), + Observer: baseObserver, + suiClient: suiClient, + gateway: gateway, + txMap: make(map[uint64]models.SuiTransactionBlockResponse), } ob.LoadLastTxScanned() @@ -61,9 +63,9 @@ func (ob *Observer) Gateway() *sui.Gateway { return ob.gateway } // CheckRPCStatus checks the RPC status of the chain. func (ob *Observer) CheckRPCStatus(ctx context.Context) error { - blockTime, err := ob.client.HealthCheck(ctx) + blockTime, err := ob.suiClient.HealthCheck(ctx) if err != nil { - return errors.Wrap(err, "unable to check rpc health") + return errors.Wrap(err, "unable to check Sui client health") } // It's not a "real" block latency as Sui uses concept of "checkpoints" @@ -85,7 +87,7 @@ func (ob *Observer) CheckRPCStatus(ctx context.Context) error { // - "Validators update the ReferencePrice every epoch (~24h)" // - "Storage price is updated infrequently through gov proposals" func (ob *Observer) PostGasPrice(ctx context.Context) error { - checkpoint, err := ob.client.GetLatestCheckpoint(ctx) + checkpoint, err := ob.suiClient.GetLatestCheckpoint(ctx) if err != nil { return errors.Wrap(err, "unable to get latest checkpoint") } @@ -97,7 +99,7 @@ func (ob *Observer) PostGasPrice(ctx context.Context) error { // gas price in MIST. 1 SUI = 10^9 MIST (a billion) // e.g. { "jsonrpc": "2.0", "id": 1, "result": "750" } - gasPrice, err := ob.client.SuiXGetReferenceGasPrice(ctx) + gasPrice, err := ob.suiClient.SuiXGetReferenceGasPrice(ctx) if err != nil { return errors.Wrap(err, "unable to get ref gas price") } diff --git a/zetaclient/chains/sui/observer/observer_test.go b/zetaclient/chains/sui/observer/observer_test.go index 7dca6a14c0..95cf506cfa 100644 --- a/zetaclient/chains/sui/observer/observer_test.go +++ b/zetaclient/chains/sui/observer/observer_test.go @@ -635,7 +635,7 @@ func (ts *testSuite) MockCCTXByNonce(cctx *cctypes.CrossChainTx) *mock.Call { func (ts *testSuite) MockOutboundTrackers(trackers []cctypes.OutboundTracker) *mock.Call { return ts.zetaMock. - On("GetAllOutboundTrackerByChain", mock.Anything, ts.Chain().ChainId, mock.Anything). + On("GetOutboundTrackers", mock.Anything, ts.Chain().ChainId). Return(trackers, nil) } diff --git a/zetaclient/chains/sui/observer/outbound.go b/zetaclient/chains/sui/observer/outbound.go index 543fcc4bc8..10e235b353 100644 --- a/zetaclient/chains/sui/observer/outbound.go +++ b/zetaclient/chains/sui/observer/outbound.go @@ -11,7 +11,6 @@ import ( "github.com/zeta-chain/node/pkg/chains" "github.com/zeta-chain/node/pkg/contracts/sui" cctypes "github.com/zeta-chain/node/x/crosschain/types" - "github.com/zeta-chain/node/zetaclient/chains/interfaces" "github.com/zeta-chain/node/zetaclient/chains/sui/client" "github.com/zeta-chain/node/zetaclient/logs" "github.com/zeta-chain/node/zetaclient/zetacore" @@ -32,7 +31,7 @@ func (ob *Observer) OutboundCreated(nonce uint64) bool { func (ob *Observer) ProcessOutboundTrackers(ctx context.Context) error { chainID := ob.Chain().ChainId - trackers, err := ob.ZetacoreClient().GetAllOutboundTrackerByChain(ctx, chainID, interfaces.Ascending) + trackers, err := ob.ZetacoreClient().GetOutboundTrackers(ctx, chainID) if err != nil { return errors.Wrap(err, "unable to get outbound trackers") } @@ -157,7 +156,7 @@ func (ob *Observer) VoteOutbound(ctx context.Context, cctx *cctypes.CrossChainTx // loadOutboundTx loads cross-chain outbound tx by digest and ensures its authenticity. func (ob *Observer) loadOutboundTx(ctx context.Context, cctx *cctypes.CrossChainTx, digest string) error { - res, err := ob.client.SuiGetTransactionBlock(ctx, models.SuiGetTransactionBlockRequest{ + res, err := ob.suiClient.SuiGetTransactionBlock(ctx, models.SuiGetTransactionBlockRequest{ Digest: digest, Options: models.SuiTransactionBlockOptions{ ShowEvents: true, diff --git a/zetaclient/chains/sui/signer/signer.go b/zetaclient/chains/sui/signer/signer.go index 9a892dfb8a..5625919e68 100644 --- a/zetaclient/chains/sui/signer/signer.go +++ b/zetaclient/chains/sui/signer/signer.go @@ -20,49 +20,64 @@ import ( // Signer Sui outbound transaction signer. type Signer struct { *base.Signer - client RPC + + zetacoreClient interfaces.ZetacoreClient + suiClient SuiClient + gateway *sui.Gateway withdrawCap *tssOwnedObject messageContext *tssOwnedObject - - zetacore interfaces.ZetacoreClient } -// RPC represents Sui rpc. -type RPC interface { +// SuiClient represents the Sui RPC client. +type SuiClient interface { SuiXGetLatestSuiSystemState(ctx context.Context) (models.SuiSystemStateSummary, error) - GetOwnedObjectID(ctx context.Context, ownerAddress, structType string) (string, error) - GetObjectParsedData(ctx context.Context, objectID string) (models.SuiParsedData, error) - SuiMultiGetObjects(ctx context.Context, req models.SuiMultiGetObjectsRequest) ([]*models.SuiObjectResponse, error) - GetSuiCoinObjectRefs(ctx context.Context, owner string, minBalanceMist uint64) ([]*suiptb.ObjectRef, error) - MoveCall(ctx context.Context, req models.MoveCallRequest) (models.TxnMetaData, error) + GetOwnedObjectID(_ context.Context, + ownerAddress string, + structType string, + ) (string, error) + + GetObjectParsedData(_ context.Context, objectID string) (models.SuiParsedData, error) + + SuiMultiGetObjects(context.Context, + models.SuiMultiGetObjectsRequest, + ) ([]*models.SuiObjectResponse, error) + + GetSuiCoinObjectRefs(_ context.Context, + owner string, + minBalanceMist uint64, + ) ([]*suiptb.ObjectRef, error) + + MoveCall(context.Context, models.MoveCallRequest) (models.TxnMetaData, error) + SuiExecuteTransactionBlock( - ctx context.Context, - req models.SuiExecuteTransactionBlockRequest, + context.Context, + models.SuiExecuteTransactionBlockRequest, ) (models.SuiTransactionBlockResponse, error) + InspectTransactionBlock( - ctx context.Context, - req models.SuiDevInspectTransactionBlockRequest, + context.Context, + models.SuiDevInspectTransactionBlockRequest, ) (models.SuiTransactionBlockResponse, error) + SuiGetTransactionBlock( - ctx context.Context, - req models.SuiGetTransactionBlockRequest, + context.Context, + models.SuiGetTransactionBlockRequest, ) (models.SuiTransactionBlockResponse, error) } // New Signer constructor. -func New( - baseSigner *base.Signer, - client RPC, +func New(baseSigner *base.Signer, + zetacoreClient interfaces.ZetacoreClient, + suiClient SuiClient, gateway *sui.Gateway, - zetacore interfaces.ZetacoreClient, ) *Signer { return &Signer{ Signer: baseSigner, - client: client, + zetacoreClient: zetacoreClient, + suiClient: suiClient, gateway: gateway, - zetacore: zetacore, withdrawCap: &tssOwnedObject{}, messageContext: &tssOwnedObject{}, } diff --git a/zetaclient/chains/sui/signer/signer_test.go b/zetaclient/chains/sui/signer/signer_test.go index 8e4e9e0ac0..d104f23334 100644 --- a/zetaclient/chains/sui/signer/signer_test.go +++ b/zetaclient/chains/sui/signer/signer_test.go @@ -342,7 +342,7 @@ func newTestSuite(t *testing.T) *testSuite { require.NoError(t, err) baseSigner := base.NewSigner(chain, tss, logger) - signer := New(baseSigner, suiMock, gw, zetacore) + signer := New(baseSigner, zetacore, suiMock, gw) ts := &testSuite{ t: t, diff --git a/zetaclient/chains/sui/signer/signer_tracker.go b/zetaclient/chains/sui/signer/signer_tracker.go index 4863818107..db5780b2b4 100644 --- a/zetaclient/chains/sui/signer/signer_tracker.go +++ b/zetaclient/chains/sui/signer/signer_tracker.go @@ -59,7 +59,7 @@ func (s *Signer) reportOutboundTracker(ctx context.Context, nonce uint64, digest } attempts++ - res, err := s.client.SuiGetTransactionBlock(ctx, req) + res, err := s.suiClient.SuiGetTransactionBlock(ctx, req) switch { case ctx.Err() != nil: return errors.Wrap(ctx.Err(), "failed to get transaction block") @@ -83,6 +83,6 @@ func (s *Signer) reportOutboundTracker(ctx context.Context, nonce uint64, digest // note that at this point we don't care whether tx was successful or not. func (s *Signer) postTrackerVote(ctx context.Context, nonce uint64, digest string) error { - _, err := s.zetacore.PostOutboundTracker(ctx, s.Chain().ChainId, nonce, digest) + _, err := s.zetacoreClient.PostOutboundTracker(ctx, s.Chain().ChainId, nonce, digest) return err } diff --git a/zetaclient/chains/sui/signer/signer_tx.go b/zetaclient/chains/sui/signer/signer_tx.go index a166d9c080..a115c1a75d 100644 --- a/zetaclient/chains/sui/signer/signer_tx.go +++ b/zetaclient/chains/sui/signer/signer_tx.go @@ -144,7 +144,7 @@ func (s *Signer) buildWithdrawTx( GasBudget: gasBudgetStr, } - return s.client.MoveCall(ctx, req) + return s.suiClient.MoveCall(ctx, req) } // buildWithdrawAndCallTx builds unsigned withdrawAndCall @@ -244,7 +244,7 @@ func (s *Signer) createCancelTxBuilder( } return func(ctx context.Context) (models.TxnMetaData, string, error) { - tx, err := s.client.MoveCall(ctx, req) + tx, err := s.suiClient.MoveCall(ctx, req) if err != nil { return models.TxnMetaData{}, "", errors.Wrap(err, "unable to build cancel tx") } @@ -295,7 +295,7 @@ func (s *Signer) broadcastWithdrawalWithFallback( // broadcast tx // Note: this is the place where the gateway object version mismatch error happens - res, err := s.client.SuiExecuteTransactionBlock(ctx, req) + res, err := s.suiClient.SuiExecuteTransactionBlock(ctx, req) if err != nil { return "", errors.Wrap(err, "unable to execute tx block") } @@ -343,7 +343,7 @@ func (s *Signer) broadcastCancelTx(ctx context.Context, cancelTxBuilder txBuilde } // broadcast cancel tx - res, err := s.client.SuiExecuteTransactionBlock(ctx, reqCancel) + res, err := s.suiClient.SuiExecuteTransactionBlock(ctx, reqCancel) if err != nil { return "", errors.Wrap(err, "unable to execute cancel tx block") } @@ -368,7 +368,7 @@ func getCancelTxGasBudget(params *cctypes.OutboundParams) (string, error) { // getGatewayNonce reads the nonce of the gateway object func (s *Signer) getGatewayNonce(ctx context.Context) (uint64, error) { - data, err := s.client.GetObjectParsedData(ctx, s.gateway.ObjectID()) + data, err := s.suiClient.GetObjectParsedData(ctx, s.gateway.ObjectID()) if err != nil { return 0, errors.Wrap(err, "unable to get parsed data of gateway object") } diff --git a/zetaclient/chains/sui/signer/tss_owned_object.go b/zetaclient/chains/sui/signer/tss_owned_object.go index 953373a285..fcf625dcf7 100644 --- a/zetaclient/chains/sui/signer/tss_owned_object.go +++ b/zetaclient/chains/sui/signer/tss_owned_object.go @@ -62,7 +62,7 @@ func (s *Signer) getWithdrawCapID(ctx context.Context) (string, error) { owner := s.TSS().PubKey().AddressSui() structType := s.gateway.WithdrawCapType() - objectID, err := s.client.GetOwnedObjectID(ctx, owner, structType) + objectID, err := s.suiClient.GetOwnedObjectID(ctx, owner, structType) if err != nil { return "", errors.Wrap(err, "unable to get owned object ID") } diff --git a/zetaclient/chains/sui/signer/withdraw_and_call.go b/zetaclient/chains/sui/signer/withdraw_and_call.go index d465d3e858..e68ab5e7aa 100644 --- a/zetaclient/chains/sui/signer/withdraw_and_call.go +++ b/zetaclient/chains/sui/signer/withdraw_and_call.go @@ -204,7 +204,7 @@ func (s *Signer) getWithdrawAndCallObjectRefs( objectIDs := append([]string{s.gateway.ObjectID(), withdrawCapID /*, msgContextID*/}, onCallObjectIDs...) // query objects in batch - suiObjects, err := s.client.SuiMultiGetObjects(ctx, models.SuiMultiGetObjectsRequest{ + suiObjects, err := s.suiClient.SuiMultiGetObjects(ctx, models.SuiMultiGetObjectsRequest{ ObjectIds: objectIDs, Options: models.SuiObjectDataOptions{ // show owner info in order to retrieve object initial shared version @@ -267,7 +267,7 @@ func (s *Signer) getWithdrawAndCallObjectRefs( } // get latest TSS SUI coin object ref for gas payment - suiCoinObjRefs, err := s.client.GetSuiCoinObjectRefs(ctx, s.TSS().PubKey().AddressSui(), gasBudget) + suiCoinObjRefs, err := s.suiClient.GetSuiCoinObjectRefs(ctx, s.TSS().PubKey().AddressSui(), gasBudget) if err != nil { return withdrawAndCallObjRefs{}, errors.Wrap(err, "unable to get TSS SUI coin objects") } diff --git a/zetaclient/chains/ton/client.go b/zetaclient/chains/ton/client.go new file mode 100644 index 0000000000..efdbfe048d --- /dev/null +++ b/zetaclient/chains/ton/client.go @@ -0,0 +1,11 @@ +package ton + +import ( + "github.com/zeta-chain/node/zetaclient/chains/ton/observer" + "github.com/zeta-chain/node/zetaclient/chains/ton/signer" +) + +type Client interface { + observer.TONClient + signer.TONClient +} diff --git a/zetaclient/chains/ton/observer/inbound.go b/zetaclient/chains/ton/observer/inbound.go index 94e497e2fe..deb2ab505e 100644 --- a/zetaclient/chains/ton/observer/inbound.go +++ b/zetaclient/chains/ton/observer/inbound.go @@ -34,7 +34,7 @@ func (ob *Observer) ObserveInbound(ctx context.Context) error { return errors.Wrap(err, "unable to get last scanned tx") } - txs, err := ob.rpc.GetTransactionsSince(ctx, ob.gateway.AccountID(), lt, hashBits) + txs, err := ob.tonClient.GetTransactionsSince(ctx, ob.gateway.AccountID(), lt, hashBits) if err != nil { return errors.Wrap(err, "unable to get transactions") } @@ -144,7 +144,7 @@ func (ob *Observer) ProcessInboundTrackers(ctx context.Context) error { continue } - raw, err := ob.rpc.GetTransaction(ctx, gatewayAccountID, lt, hash) + raw, err := ob.tonClient.GetTransaction(ctx, gatewayAccountID, lt, hash) if err != nil { ob.logSkippedTracker(txHash, "unable_to_get_tx", err) continue @@ -349,7 +349,7 @@ func (ob *Observer) ensureLastScannedTx(ctx context.Context) (uint64, ton.Bits25 // get last txs from RPC and pick the oldest one const limit = 20 - txs, err := ob.rpc.GetTransactions(ctx, limit, ob.gateway.AccountID(), 0, ton.Bits256{}) + txs, err := ob.tonClient.GetTransactions(ctx, limit, ob.gateway.AccountID(), 0, ton.Bits256{}) switch { case err != nil: return 0, ton.Bits256{}, errors.Wrap(err, "unable to get last scanned tx") diff --git a/zetaclient/chains/ton/observer/observer.go b/zetaclient/chains/ton/observer/observer.go index 0f01ced6a9..af0a61a662 100644 --- a/zetaclient/chains/ton/observer/observer.go +++ b/zetaclient/chains/ton/observer/observer.go @@ -20,7 +20,8 @@ import ( type Observer struct { *base.Observer - rpc RPC + tonClient TONClient + gateway *toncontracts.Gateway outbounds *lru.Cache @@ -30,30 +31,47 @@ type Observer struct { const outboundsCacheSize = 1024 -type RPC interface { - GetConfigParam(ctx context.Context, index uint32) (*boc.Cell, error) - GetBlockHeader(ctx context.Context, blockID rpc.BlockIDExt) (rpc.BlockHeader, error) - GetMasterchainInfo(ctx context.Context) (rpc.MasterchainInfo, error) - HealthCheck(ctx context.Context) (time.Time, error) - GetTransactionsSince(ctx context.Context, acc ton.AccountID, lt uint64, hash ton.Bits256) ([]ton.Transaction, error) - GetTransactions( - ctx context.Context, +type TONClient interface { + GetConfigParam(_ context.Context, index uint32) (*boc.Cell, error) + + GetBlockHeader(_ context.Context, blockID rpc.BlockIDExt) (rpc.BlockHeader, error) + + GetMasterchainInfo(context.Context) (rpc.MasterchainInfo, error) + + HealthCheck(context.Context) (time.Time, error) + + GetTransaction(_ context.Context, + _ ton.AccountID, + lt uint64, + hash ton.Bits256, + ) (ton.Transaction, error) + + GetTransactions(_ context.Context, count uint32, - accountID ton.AccountID, + _ ton.AccountID, + lt uint64, + hash ton.Bits256, + ) ([]ton.Transaction, error) + + GetTransactionsSince(_ context.Context, + _ ton.AccountID, lt uint64, hash ton.Bits256, ) ([]ton.Transaction, error) - GetTransaction(ctx context.Context, acc ton.AccountID, lt uint64, hash ton.Bits256) (ton.Transaction, error) } // New constructor for TON Observer. -func New(bo *base.Observer, rpc RPC, gateway *toncontracts.Gateway) (*Observer, error) { - switch { - case !bo.Chain().IsTONChain(): +func New(baseObserver *base.Observer, + tonClient TONClient, + gateway *toncontracts.Gateway, +) (*Observer, error) { + if !baseObserver.Chain().IsTONChain() { return nil, errors.New("base observer chain is not TON") - case rpc == nil: - return nil, errors.New("rpc is nil") - case gateway == nil: + } + if tonClient == nil { + return nil, errors.New("ton client is nil") + } + if gateway == nil { return nil, errors.New("gateway is nil") } @@ -62,11 +80,11 @@ func New(bo *base.Observer, rpc RPC, gateway *toncontracts.Gateway) (*Observer, return nil, err } - bo.LoadLastTxScanned() + baseObserver.LoadLastTxScanned() return &Observer{ - Observer: bo, - rpc: rpc, + Observer: baseObserver, + tonClient: tonClient, gateway: gateway, outbounds: outbounds, }, nil @@ -74,7 +92,7 @@ func New(bo *base.Observer, rpc RPC, gateway *toncontracts.Gateway) (*Observer, // PostGasPrice fetches on-chain gas config and reports it to Zetacore. func (ob *Observer) PostGasPrice(ctx context.Context) error { - cfg, err := rpc.FetchGasConfigRPC(ctx, ob.rpc) + cfg, err := rpc.FetchGasConfigRPC(ctx, ob.tonClient) if err != nil { return errors.Wrap(err, "failed to fetch gas config") } @@ -84,7 +102,7 @@ func (ob *Observer) PostGasPrice(ctx context.Context) error { return errors.Wrap(err, "failed to parse gas price") } - info, err := ob.rpc.GetMasterchainInfo(ctx) + info, err := ob.tonClient.GetMasterchainInfo(ctx) if err != nil { return errors.Wrap(err, "failed to get masterchain info") } @@ -106,9 +124,9 @@ func (ob *Observer) PostGasPrice(ctx context.Context) error { // CheckRPCStatus checks TON RPC status and alerts if necessary. func (ob *Observer) CheckRPCStatus(ctx context.Context) error { - blockTime, err := ob.rpc.HealthCheck(ctx) + blockTime, err := ob.tonClient.HealthCheck(ctx) if err != nil { - return errors.Wrap(err, "unable to check rpc health") + return errors.Wrap(err, "unable to check TON client health") } metrics.ReportBlockLatency(ob.Chain().Name, blockTime) diff --git a/zetaclient/chains/ton/observer/observer_test.go b/zetaclient/chains/ton/observer/observer_test.go index 1b89c194a5..8ffce7dbcb 100644 --- a/zetaclient/chains/ton/observer/observer_test.go +++ b/zetaclient/chains/ton/observer/observer_test.go @@ -161,9 +161,9 @@ func (ts *testSuite) OnGetTransactionsSince( Return(txs, err) } -func (ts *testSuite) OnGetAllOutboundTrackerByChain(trackers []cc.OutboundTracker) *mock.Call { +func (ts *testSuite) OnGetOutboundTrackers(trackers []cc.OutboundTracker) *mock.Call { return ts.zetacore. - On("GetAllOutboundTrackerByChain", mock.Anything, ts.chain.ChainId, mock.Anything). + On("GetOutboundTrackers", mock.Anything, ts.chain.ChainId). Return(trackers, nil) } diff --git a/zetaclient/chains/ton/observer/outbound.go b/zetaclient/chains/ton/observer/outbound.go index 20a0e0d0aa..6f3aaf6a75 100644 --- a/zetaclient/chains/ton/observer/outbound.go +++ b/zetaclient/chains/ton/observer/outbound.go @@ -10,7 +10,6 @@ import ( "github.com/zeta-chain/node/pkg/coin" toncontracts "github.com/zeta-chain/node/pkg/contracts/ton" cctypes "github.com/zeta-chain/node/x/crosschain/types" - "github.com/zeta-chain/node/zetaclient/chains/interfaces" "github.com/zeta-chain/node/zetaclient/chains/ton/rpc" "github.com/zeta-chain/node/zetaclient/logs" "github.com/zeta-chain/node/zetaclient/zetacore" @@ -53,7 +52,7 @@ func (ob *Observer) ProcessOutboundTrackers(ctx context.Context) error { zetacore = ob.ZetacoreClient() ) - trackers, err := zetacore.GetAllOutboundTrackerByChain(ctx, chainID, interfaces.Ascending) + trackers, err := zetacore.GetOutboundTrackers(ctx, chainID) if err != nil { return errors.Wrap(err, "unable to get outbound trackers") } @@ -105,7 +104,7 @@ func (ob *Observer) processOutboundTracker(ctx context.Context, cctx *cctypes.Cr return errors.Wrap(err, "unable to parse tx hash") } - rawTx, err := ob.rpc.GetTransaction(ctx, ob.gateway.AccountID(), lt, hash) + rawTx, err := ob.tonClient.GetTransaction(ctx, ob.gateway.AccountID(), lt, hash) if err != nil { return errors.Wrap(err, "unable to get tx") } diff --git a/zetaclient/chains/ton/observer/outbound_test.go b/zetaclient/chains/ton/observer/outbound_test.go index 5bc01d9c47..d3f65cf559 100644 --- a/zetaclient/chains/ton/observer/outbound_test.go +++ b/zetaclient/chains/ton/observer/outbound_test.go @@ -50,7 +50,7 @@ func TestOutbound(t *testing.T) { HashList: []*cc.TxHash{{TxHash: rpc.TransactionToHashString(withdrawalTX)}}, } - ts.OnGetAllOutboundTrackerByChain([]cc.OutboundTracker{tracker}) + ts.OnGetOutboundTrackers([]cc.OutboundTracker{tracker}) // Given cctx cctx := sample.CrossChainTx(t, "index456") diff --git a/zetaclient/chains/ton/rpc/client_live_test.go b/zetaclient/chains/ton/rpc/client_test.go similarity index 99% rename from zetaclient/chains/ton/rpc/client_live_test.go rename to zetaclient/chains/ton/rpc/client_test.go index ea0cd94b78..65058daaec 100644 --- a/zetaclient/chains/ton/rpc/client_live_test.go +++ b/zetaclient/chains/ton/rpc/client_test.go @@ -134,7 +134,7 @@ func TestLiveClient(t *testing.T) { require.NoError(t, err) require.Len(t, txs, 3) - for i := 0; i < 2; i++ { + for i := range 2 { // ensure that GetTransactions orders TXs by DESC require.Greater(t, txs[i].Lt, txs[i+1].Lt) } diff --git a/zetaclient/chains/ton/signer/signer.go b/zetaclient/chains/ton/signer/signer.go index c863230864..9b1a9ee0e7 100644 --- a/zetaclient/chains/ton/signer/signer.go +++ b/zetaclient/chains/ton/signer/signer.go @@ -16,17 +16,23 @@ import ( "github.com/zeta-chain/node/zetaclient/logs" ) -type RPC interface { - GetTransactionsSince(ctx context.Context, acc ton.AccountID, lt uint64, hash ton.Bits256) ([]ton.Transaction, error) - GetAccountState(ctx context.Context, accountID ton.AccountID) (rpc.Account, error) - SendMessage(ctx context.Context, payload []byte) (uint32, error) +type TONClient interface { + GetTransactionsSince(_ context.Context, + _ ton.AccountID, + lt uint64, + hash ton.Bits256, + ) ([]ton.Transaction, error) + + GetAccountState(context.Context, ton.AccountID) (rpc.Account, error) + + SendMessage(context.Context, []byte) (uint32, error) } // Signer represents TON signer. type Signer struct { *base.Signer - rpc RPC - gateway *toncontracts.Gateway + tonClient TONClient + gateway *toncontracts.Gateway } // Outcome possible outbound processing outcomes. @@ -39,11 +45,11 @@ const ( ) // New Signer constructor. -func New(baseSigner *base.Signer, rpc RPC, gateway *toncontracts.Gateway) *Signer { +func New(baseSigner *base.Signer, tonClient TONClient, gateway *toncontracts.Gateway) *Signer { return &Signer{ - Signer: baseSigner, - rpc: rpc, - gateway: gateway, + Signer: baseSigner, + tonClient: tonClient, + gateway: gateway, } } @@ -103,7 +109,7 @@ func (s *Signer) ProcessOutbound( return Fail, errors.Wrap(err, "unable to sign withdrawal message") } - gwState, err := s.rpc.GetAccountState(ctx, s.gateway.AccountID()) + gwState, err := s.tonClient.GetAccountState(ctx, s.gateway.AccountID()) if err != nil { return Fail, errors.Wrap(err, "unable to get gateway state") } @@ -113,7 +119,7 @@ func (s *Signer) ProcessOutbound( // // Example: If a cctx has amount of 5 TON, the recipient will receive 5 TON, // and gateway's balance will be decreased by 5 TON + txFees. - exitCode, err := s.gateway.SendExternalMessage(ctx, s.rpc, outbound.message) + exitCode, err := s.gateway.SendExternalMessage(ctx, s.tonClient, outbound.message) if err != nil || exitCode != 0 { return s.handleSendError(exitCode, err, outbound.logFields) } diff --git a/zetaclient/chains/ton/signer/signer_tracker.go b/zetaclient/chains/ton/signer/signer_tracker.go index 168e3f0924..3024ffc2b2 100644 --- a/zetaclient/chains/ton/signer/signer_tracker.go +++ b/zetaclient/chains/ton/signer/signer_tracker.go @@ -47,7 +47,7 @@ func (s *Signer) trackOutbound( ) for time.Since(start) <= timeout { - txs, err := s.rpc.GetTransactionsSince(ctx, acc, lt, hash) + txs, err := s.tonClient.GetTransactionsSince(ctx, acc, lt, hash) if err != nil { return errors.Wrapf(err, "unable to get transactions (lt %d, hash %s)", lt, hash.Hex()) } diff --git a/zetaclient/orchestrator/bootstrap.go b/zetaclient/orchestrator/bootstrap.go index eb6a10c1f3..b9cedfbd3d 100644 --- a/zetaclient/orchestrator/bootstrap.go +++ b/zetaclient/orchestrator/bootstrap.go @@ -14,7 +14,7 @@ import ( toncontracts "github.com/zeta-chain/node/pkg/contracts/ton" "github.com/zeta-chain/node/zetaclient/chains/base" "github.com/zeta-chain/node/zetaclient/chains/bitcoin" - "github.com/zeta-chain/node/zetaclient/chains/bitcoin/client" + btcclient "github.com/zeta-chain/node/zetaclient/chains/bitcoin/client" btcobserver "github.com/zeta-chain/node/zetaclient/chains/bitcoin/observer" btcsigner "github.com/zeta-chain/node/zetaclient/chains/bitcoin/signer" "github.com/zeta-chain/node/zetaclient/chains/evm" @@ -30,7 +30,7 @@ import ( suisigner "github.com/zeta-chain/node/zetaclient/chains/sui/signer" "github.com/zeta-chain/node/zetaclient/chains/ton" tonobserver "github.com/zeta-chain/node/zetaclient/chains/ton/observer" - tonrpc "github.com/zeta-chain/node/zetaclient/chains/ton/rpc" + tonclient "github.com/zeta-chain/node/zetaclient/chains/ton/rpc" tonsigner "github.com/zeta-chain/node/zetaclient/chains/ton/signer" zctx "github.com/zeta-chain/node/zetaclient/context" "github.com/zeta-chain/node/zetaclient/db" @@ -56,10 +56,11 @@ func (oc *Orchestrator) bootstrapBitcoin(ctx context.Context, chain zctx.Chain) return nil, errors.Wrap(errSkipChain, "unable to find btc config") } - rpcClient, err := client.New(cfg, chain.ID(), oc.logger.Logger) + standardBitcoinClient, err := btcclient.New(cfg, chain.ID(), oc.logger.Logger) if err != nil { return nil, errors.Wrap(err, "unable to create rpc client") } + var bitcoinClient bitcoin.Client = standardBitcoinClient var ( rawChain = chain.RawChain() @@ -71,13 +72,13 @@ func (oc *Orchestrator) bootstrapBitcoin(ctx context.Context, chain zctx.Chain) return nil, errors.Wrap(err, "unable to create base observer") } - observer, err := btcobserver.New(*rawChain, baseObserver, rpcClient) + observer, err := btcobserver.New(baseObserver, bitcoinClient, *rawChain) if err != nil { return nil, errors.Wrap(err, "unable to create observer") } baseSigner := oc.newBaseSigner(chain) - signer := btcsigner.New(baseSigner, rpcClient) + signer := btcsigner.New(baseSigner, bitcoinClient) return bitcoin.New(oc.scheduler, observer, signer), nil } @@ -98,10 +99,11 @@ func (oc *Orchestrator) bootstrapEVM(ctx context.Context, chain zctx.Chain) (*ev return nil, errors.Wrap(errSkipChain, "unable to find evm config") } - evmClient, err := evmclient.NewFromEndpoint(ctx, cfg.Endpoint) + standardEvmClient, err := evmclient.NewFromEndpoint(ctx, cfg.Endpoint) if err != nil { return nil, errors.Wrapf(err, "unable to create evm client (%s)", cfg.Endpoint) } + var evmClient evm.Client = standardEvmClient baseObserver, err := oc.newBaseObserver(chain, chain.Name()) if err != nil { @@ -156,12 +158,13 @@ func (oc *Orchestrator) bootstrapSolana(ctx context.Context, chain zctx.Chain) ( gwAddress := chain.Params().GatewayAddress - rpcClient := solrpc.New(cfg.Endpoint) - if rpcClient == nil { + standardSolanaClient := solrpc.New(cfg.Endpoint) + if standardSolanaClient == nil { return nil, errors.New("unable to create rpc client") } + var solanaClient solana.Client = standardSolanaClient - observer, err := solbserver.New(baseObserver, rpcClient, gwAddress) + observer, err := solbserver.New(baseObserver, solanaClient, gwAddress) if err != nil { return nil, errors.Wrap(err, "unable to create observer") } @@ -177,7 +180,7 @@ func (oc *Orchestrator) bootstrapSolana(ctx context.Context, chain zctx.Chain) ( baseSigner := oc.newBaseSigner(chain) // create Solana signer - signer, err := solanasigner.New(baseSigner, rpcClient, gwAddress, relayerKey) + signer, err := solanasigner.New(baseSigner, solanaClient, gwAddress, relayerKey) if err != nil { return nil, errors.Wrap(err, "unable to create signer") } @@ -207,7 +210,8 @@ func (oc *Orchestrator) bootstrapSui(ctx context.Context, chain zctx.Chain) (*su return nil, errors.Wrap(err, "unable to create gateway") } - suiClient := suiclient.NewFromEndpoint(cfg.Endpoint) + standardSuiClient := suiclient.New(cfg.Endpoint) + var suiClient sui.Client = standardSuiClient baseObserver, err := oc.newBaseObserver(chain, chain.Name()) if err != nil { @@ -216,7 +220,7 @@ func (oc *Orchestrator) bootstrapSui(ctx context.Context, chain zctx.Chain) (*su observer := suiobserver.New(baseObserver, suiClient, gateway) - signer := suisigner.New(oc.newBaseSigner(chain), suiClient, gateway, oc.deps.Zetacore) + signer := suisigner.New(oc.newBaseSigner(chain), oc.deps.Zetacore, suiClient, gateway) return sui.New(oc.scheduler, observer, signer), nil } @@ -258,19 +262,20 @@ func (oc *Orchestrator) bootstrapTON(ctx context.Context, chain zctx.Chain) (*to return nil, errors.Wrap(err, "unable to create instrumented rpc client") } - rpc := tonrpc.New(cfg.Endpoint, chain.ID(), tonrpc.WithHTTPClient(rpcClient)) + standardTonClient := tonclient.New(cfg.Endpoint, chain.ID(), tonclient.WithHTTPClient(rpcClient)) + var tonClient ton.Client = standardTonClient baseObserver, err := oc.newBaseObserver(chain, chain.Name()) if err != nil { return nil, errors.Wrap(err, "unable to create base observer") } - observer, err := tonobserver.New(baseObserver, rpc, gw) + observer, err := tonobserver.New(baseObserver, tonClient, gw) if err != nil { return nil, errors.Wrap(err, "unable to create observer") } - signer := tonsigner.New(oc.newBaseSigner(chain), rpc, gw) + signer := tonsigner.New(oc.newBaseSigner(chain), tonClient, gw) return ton.New(oc.scheduler, observer, signer), nil } diff --git a/zetaclient/orchestrator/bootstrap_test.go b/zetaclient/orchestrator/bootstrap_test.go index 8d0535a52e..47775fc1e4 100644 --- a/zetaclient/orchestrator/bootstrap_test.go +++ b/zetaclient/orchestrator/bootstrap_test.go @@ -303,7 +303,7 @@ func mockZetacoreCalls(ts *testSuite) { on(ts.zetacore, "NewBlockSubscriber", 1).Return(blockChan, nil) on(ts.zetacore, "GetInboundTrackersForChain", 2).Return(nil, nil).Maybe() on(ts.zetacore, "GetPendingNoncesByChain", 2).Return(observertypes.PendingNonces{}, nil).Maybe() - on(ts.zetacore, "GetAllOutboundTrackerByChain", 3).Return(nil, nil).Maybe() + on(ts.zetacore, "GetOutboundTrackers", 3).Return(nil, nil).Maybe() on(ts.zetacore, "PostVoteGasPrice", 5).Return("", nil).Maybe() } diff --git a/zetaclient/orchestrator/orchestrator_test.go b/zetaclient/orchestrator/orchestrator_test.go index 7a59c15642..3c6205e53c 100644 --- a/zetaclient/orchestrator/orchestrator_test.go +++ b/zetaclient/orchestrator/orchestrator_test.go @@ -173,7 +173,7 @@ func newTestSuite(t *testing.T) *testSuite { // Mock CCTX-related calls (stubs for now) on(zetacore, "ListPendingCCTX", 2).Return(nil, uint64(0), nil).Maybe() on(zetacore, "GetInboundTrackersForChain", 2).Return(nil, nil).Maybe() - on(zetacore, "GetAllOutboundTrackerByChain", 3).Return(nil, nil).Maybe() + on(zetacore, "GetOutboundTrackers", 2).Return(nil, nil).Maybe() t.Cleanup(ts.Stop) diff --git a/zetaclient/orchestrator/preflight_metrics_reporter.go b/zetaclient/orchestrator/preflight_metrics_reporter.go index 555d1872b2..f501bea8c4 100644 --- a/zetaclient/orchestrator/preflight_metrics_reporter.go +++ b/zetaclient/orchestrator/preflight_metrics_reporter.go @@ -11,7 +11,7 @@ import ( "github.com/zeta-chain/node/pkg/chains" "github.com/zeta-chain/node/zetaclient/chains/bitcoin/client" evmclient "github.com/zeta-chain/node/zetaclient/chains/evm/client" - zetasolrpc "github.com/zeta-chain/node/zetaclient/chains/solana/rpc" + solrepo "github.com/zeta-chain/node/zetaclient/chains/solana/repo" suiclient "github.com/zeta-chain/node/zetaclient/chains/sui/client" tonrpc "github.com/zeta-chain/node/zetaclient/chains/ton/rpc" zctx "github.com/zeta-chain/node/zetaclient/context" @@ -144,7 +144,9 @@ func reportPreflightMetricsSolana(ctx context.Context, app *zctx.AppContext, cha return errors.New("unable to create solana rpc client") } - blockTime, err := zetasolrpc.HealthCheck(ctx, rpcClient) + // TODO: The Solana repositorty should be injected as a dependency into this function. We + // should not have to instantiate the Solana client here. + blockTime, err := solrepo.New(rpcClient).HealthCheck(ctx) if err != nil { return errors.Wrap(err, "unable to get solana last block time") } @@ -177,7 +179,7 @@ func reportPreflightMetricsSui(ctx context.Context, app *zctx.AppContext, chain return nil } - suiClient := suiclient.NewFromEndpoint(cfg.Endpoint) + suiClient := suiclient.New(cfg.Endpoint) blockTime, err := suiClient.HealthCheck(ctx) if err != nil { diff --git a/zetaclient/testutils/mocks/evm_rpc.go b/zetaclient/testutils/mocks/evm_client.go similarity index 76% rename from zetaclient/testutils/mocks/evm_rpc.go rename to zetaclient/testutils/mocks/evm_client.go index 27f8428a43..9eb336b1ea 100644 --- a/zetaclient/testutils/mocks/evm_rpc.go +++ b/zetaclient/testutils/mocks/evm_client.go @@ -19,14 +19,14 @@ import ( types "github.com/ethereum/go-ethereum/core/types" ) -// EVMRPCClient is an autogenerated mock type for the EVMRPCClient type -type EVMRPCClient struct { +// EVMClient is an autogenerated mock type for the EVMClient type +type EVMClient struct { mock.Mock } -// BlockByNumberCustom provides a mock function with given fields: ctx, number -func (_m *EVMRPCClient) BlockByNumberCustom(ctx context.Context, number *big.Int) (*client.Block, error) { - ret := _m.Called(ctx, number) +// BlockByNumberCustom provides a mock function with given fields: _a0, _a1 +func (_m *EVMClient) BlockByNumberCustom(_a0 context.Context, _a1 *big.Int) (*client.Block, error) { + ret := _m.Called(_a0, _a1) if len(ret) == 0 { panic("no return value specified for BlockByNumberCustom") @@ -35,10 +35,10 @@ func (_m *EVMRPCClient) BlockByNumberCustom(ctx context.Context, number *big.Int var r0 *client.Block var r1 error if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*client.Block, error)); ok { - return rf(ctx, number) + return rf(_a0, _a1) } if rf, ok := ret.Get(0).(func(context.Context, *big.Int) *client.Block); ok { - r0 = rf(ctx, number) + r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*client.Block) @@ -46,7 +46,7 @@ func (_m *EVMRPCClient) BlockByNumberCustom(ctx context.Context, number *big.Int } if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { - r1 = rf(ctx, number) + r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) } @@ -54,9 +54,9 @@ func (_m *EVMRPCClient) BlockByNumberCustom(ctx context.Context, number *big.Int return r0, r1 } -// BlockNumber provides a mock function with given fields: ctx -func (_m *EVMRPCClient) BlockNumber(ctx context.Context) (uint64, error) { - ret := _m.Called(ctx) +// BlockNumber provides a mock function with given fields: _a0 +func (_m *EVMClient) BlockNumber(_a0 context.Context) (uint64, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for BlockNumber") @@ -65,16 +65,16 @@ func (_m *EVMRPCClient) BlockNumber(ctx context.Context) (uint64, error) { var r0 uint64 var r1 error if rf, ok := ret.Get(0).(func(context.Context) (uint64, error)); ok { - return rf(ctx) + return rf(_a0) } if rf, ok := ret.Get(0).(func(context.Context) uint64); ok { - r0 = rf(ctx) + r0 = rf(_a0) } else { r0 = ret.Get(0).(uint64) } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -83,7 +83,7 @@ func (_m *EVMRPCClient) BlockNumber(ctx context.Context) (uint64, error) { } // CallContract provides a mock function with given fields: ctx, call, blockNumber -func (_m *EVMRPCClient) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { +func (_m *EVMClient) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { ret := _m.Called(ctx, call, blockNumber) if len(ret) == 0 { @@ -113,7 +113,7 @@ func (_m *EVMRPCClient) CallContract(ctx context.Context, call ethereum.CallMsg, } // CodeAt provides a mock function with given fields: ctx, contract, blockNumber -func (_m *EVMRPCClient) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { +func (_m *EVMClient) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { ret := _m.Called(ctx, contract, blockNumber) if len(ret) == 0 { @@ -143,7 +143,7 @@ func (_m *EVMRPCClient) CodeAt(ctx context.Context, contract common.Address, blo } // EstimateGas provides a mock function with given fields: ctx, call -func (_m *EVMRPCClient) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) { +func (_m *EVMClient) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) { ret := _m.Called(ctx, call) if len(ret) == 0 { @@ -171,7 +171,7 @@ func (_m *EVMRPCClient) EstimateGas(ctx context.Context, call ethereum.CallMsg) } // FilterLogs provides a mock function with given fields: ctx, q -func (_m *EVMRPCClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { +func (_m *EVMClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { ret := _m.Called(ctx, q) if len(ret) == 0 { @@ -200,9 +200,9 @@ func (_m *EVMRPCClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) return r0, r1 } -// HeaderByNumber provides a mock function with given fields: ctx, number -func (_m *EVMRPCClient) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { - ret := _m.Called(ctx, number) +// HeaderByNumber provides a mock function with given fields: _a0, _a1 +func (_m *EVMClient) HeaderByNumber(_a0 context.Context, _a1 *big.Int) (*types.Header, error) { + ret := _m.Called(_a0, _a1) if len(ret) == 0 { panic("no return value specified for HeaderByNumber") @@ -211,10 +211,10 @@ func (_m *EVMRPCClient) HeaderByNumber(ctx context.Context, number *big.Int) (*t var r0 *types.Header var r1 error if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*types.Header, error)); ok { - return rf(ctx, number) + return rf(_a0, _a1) } if rf, ok := ret.Get(0).(func(context.Context, *big.Int) *types.Header); ok { - r0 = rf(ctx, number) + r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*types.Header) @@ -222,7 +222,7 @@ func (_m *EVMRPCClient) HeaderByNumber(ctx context.Context, number *big.Int) (*t } if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { - r1 = rf(ctx, number) + r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) } @@ -231,7 +231,7 @@ func (_m *EVMRPCClient) HeaderByNumber(ctx context.Context, number *big.Int) (*t } // HealthCheck provides a mock function with given fields: ctx -func (_m *EVMRPCClient) HealthCheck(ctx context.Context) (time.Time, error) { +func (_m *EVMClient) HealthCheck(ctx context.Context) (time.Time, error) { ret := _m.Called(ctx) if len(ret) == 0 { @@ -259,7 +259,7 @@ func (_m *EVMRPCClient) HealthCheck(ctx context.Context) (time.Time, error) { } // PendingCodeAt provides a mock function with given fields: ctx, account -func (_m *EVMRPCClient) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { +func (_m *EVMClient) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { ret := _m.Called(ctx, account) if len(ret) == 0 { @@ -289,7 +289,7 @@ func (_m *EVMRPCClient) PendingCodeAt(ctx context.Context, account common.Addres } // PendingNonceAt provides a mock function with given fields: ctx, account -func (_m *EVMRPCClient) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { +func (_m *EVMClient) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { ret := _m.Called(ctx, account) if len(ret) == 0 { @@ -316,9 +316,9 @@ func (_m *EVMRPCClient) PendingNonceAt(ctx context.Context, account common.Addre return r0, r1 } -// SendTransaction provides a mock function with given fields: ctx, tx -func (_m *EVMRPCClient) SendTransaction(ctx context.Context, tx *types.Transaction) error { - ret := _m.Called(ctx, tx) +// SendTransaction provides a mock function with given fields: _a0, _a1 +func (_m *EVMClient) SendTransaction(_a0 context.Context, _a1 *types.Transaction) error { + ret := _m.Called(_a0, _a1) if len(ret) == 0 { panic("no return value specified for SendTransaction") @@ -326,7 +326,7 @@ func (_m *EVMRPCClient) SendTransaction(ctx context.Context, tx *types.Transacti var r0 error if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction) error); ok { - r0 = rf(ctx, tx) + r0 = rf(_a0, _a1) } else { r0 = ret.Error(0) } @@ -335,7 +335,7 @@ func (_m *EVMRPCClient) SendTransaction(ctx context.Context, tx *types.Transacti } // SubscribeFilterLogs provides a mock function with given fields: ctx, q, ch -func (_m *EVMRPCClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { +func (_m *EVMClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { ret := _m.Called(ctx, q, ch) if len(ret) == 0 { @@ -364,9 +364,9 @@ func (_m *EVMRPCClient) SubscribeFilterLogs(ctx context.Context, q ethereum.Filt return r0, r1 } -// SuggestGasPrice provides a mock function with given fields: ctx -func (_m *EVMRPCClient) SuggestGasPrice(ctx context.Context) (*big.Int, error) { - ret := _m.Called(ctx) +// SuggestGasPrice provides a mock function with given fields: _a0 +func (_m *EVMClient) SuggestGasPrice(_a0 context.Context) (*big.Int, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for SuggestGasPrice") @@ -375,10 +375,10 @@ func (_m *EVMRPCClient) SuggestGasPrice(ctx context.Context) (*big.Int, error) { var r0 *big.Int var r1 error if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { - return rf(ctx) + return rf(_a0) } if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { - r0 = rf(ctx) + r0 = rf(_a0) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) @@ -386,7 +386,7 @@ func (_m *EVMRPCClient) SuggestGasPrice(ctx context.Context) (*big.Int, error) { } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -395,7 +395,7 @@ func (_m *EVMRPCClient) SuggestGasPrice(ctx context.Context) (*big.Int, error) { } // SuggestGasTipCap provides a mock function with given fields: ctx -func (_m *EVMRPCClient) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { +func (_m *EVMClient) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { ret := _m.Called(ctx) if len(ret) == 0 { @@ -424,9 +424,9 @@ func (_m *EVMRPCClient) SuggestGasTipCap(ctx context.Context) (*big.Int, error) return r0, r1 } -// TransactionByHash provides a mock function with given fields: ctx, hash -func (_m *EVMRPCClient) TransactionByHash(ctx context.Context, hash common.Hash) (*types.Transaction, bool, error) { - ret := _m.Called(ctx, hash) +// TransactionByHash provides a mock function with given fields: _a0, _a1 +func (_m *EVMClient) TransactionByHash(_a0 context.Context, _a1 common.Hash) (*types.Transaction, bool, error) { + ret := _m.Called(_a0, _a1) if len(ret) == 0 { panic("no return value specified for TransactionByHash") @@ -436,10 +436,10 @@ func (_m *EVMRPCClient) TransactionByHash(ctx context.Context, hash common.Hash) var r1 bool var r2 error if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*types.Transaction, bool, error)); ok { - return rf(ctx, hash) + return rf(_a0, _a1) } if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *types.Transaction); ok { - r0 = rf(ctx, hash) + r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*types.Transaction) @@ -447,13 +447,13 @@ func (_m *EVMRPCClient) TransactionByHash(ctx context.Context, hash common.Hash) } if rf, ok := ret.Get(1).(func(context.Context, common.Hash) bool); ok { - r1 = rf(ctx, hash) + r1 = rf(_a0, _a1) } else { r1 = ret.Get(1).(bool) } if rf, ok := ret.Get(2).(func(context.Context, common.Hash) error); ok { - r2 = rf(ctx, hash) + r2 = rf(_a0, _a1) } else { r2 = ret.Error(2) } @@ -461,9 +461,9 @@ func (_m *EVMRPCClient) TransactionByHash(ctx context.Context, hash common.Hash) return r0, r1, r2 } -// TransactionByHashCustom provides a mock function with given fields: ctx, hash -func (_m *EVMRPCClient) TransactionByHashCustom(ctx context.Context, hash string) (*client.Transaction, error) { - ret := _m.Called(ctx, hash) +// TransactionByHashCustom provides a mock function with given fields: _a0, _a1 +func (_m *EVMClient) TransactionByHashCustom(_a0 context.Context, _a1 string) (*client.Transaction, error) { + ret := _m.Called(_a0, _a1) if len(ret) == 0 { panic("no return value specified for TransactionByHashCustom") @@ -472,10 +472,10 @@ func (_m *EVMRPCClient) TransactionByHashCustom(ctx context.Context, hash string var r0 *client.Transaction var r1 error if rf, ok := ret.Get(0).(func(context.Context, string) (*client.Transaction, error)); ok { - return rf(ctx, hash) + return rf(_a0, _a1) } if rf, ok := ret.Get(0).(func(context.Context, string) *client.Transaction); ok { - r0 = rf(ctx, hash) + r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*client.Transaction) @@ -483,7 +483,7 @@ func (_m *EVMRPCClient) TransactionByHashCustom(ctx context.Context, hash string } if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, hash) + r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) } @@ -491,9 +491,9 @@ func (_m *EVMRPCClient) TransactionByHashCustom(ctx context.Context, hash string return r0, r1 } -// TransactionReceipt provides a mock function with given fields: ctx, txHash -func (_m *EVMRPCClient) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - ret := _m.Called(ctx, txHash) +// TransactionReceipt provides a mock function with given fields: _a0, _a1 +func (_m *EVMClient) TransactionReceipt(_a0 context.Context, _a1 common.Hash) (*types.Receipt, error) { + ret := _m.Called(_a0, _a1) if len(ret) == 0 { panic("no return value specified for TransactionReceipt") @@ -502,10 +502,10 @@ func (_m *EVMRPCClient) TransactionReceipt(ctx context.Context, txHash common.Ha var r0 *types.Receipt var r1 error if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*types.Receipt, error)); ok { - return rf(ctx, txHash) + return rf(_a0, _a1) } if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *types.Receipt); ok { - r0 = rf(ctx, txHash) + r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*types.Receipt) @@ -513,7 +513,7 @@ func (_m *EVMRPCClient) TransactionReceipt(ctx context.Context, txHash common.Ha } if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { - r1 = rf(ctx, txHash) + r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) } @@ -521,9 +521,9 @@ func (_m *EVMRPCClient) TransactionReceipt(ctx context.Context, txHash common.Ha return r0, r1 } -// TransactionSender provides a mock function with given fields: ctx, tx, block, index -func (_m *EVMRPCClient) TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) { - ret := _m.Called(ctx, tx, block, index) +// TransactionSender provides a mock function with given fields: _a0, _a1, block, index +func (_m *EVMClient) TransactionSender(_a0 context.Context, _a1 *types.Transaction, block common.Hash, index uint) (common.Address, error) { + ret := _m.Called(_a0, _a1, block, index) if len(ret) == 0 { panic("no return value specified for TransactionSender") @@ -532,10 +532,10 @@ func (_m *EVMRPCClient) TransactionSender(ctx context.Context, tx *types.Transac var r0 common.Address var r1 error if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, common.Hash, uint) (common.Address, error)); ok { - return rf(ctx, tx, block, index) + return rf(_a0, _a1, block, index) } if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, common.Hash, uint) common.Address); ok { - r0 = rf(ctx, tx, block, index) + r0 = rf(_a0, _a1, block, index) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(common.Address) @@ -543,7 +543,7 @@ func (_m *EVMRPCClient) TransactionSender(ctx context.Context, tx *types.Transac } if rf, ok := ret.Get(1).(func(context.Context, *types.Transaction, common.Hash, uint) error); ok { - r1 = rf(ctx, tx, block, index) + r1 = rf(_a0, _a1, block, index) } else { r1 = ret.Error(1) } @@ -551,13 +551,13 @@ func (_m *EVMRPCClient) TransactionSender(ctx context.Context, tx *types.Transac return r0, r1 } -// NewEVMRPCClient creates a new instance of EVMRPCClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// NewEVMClient creates a new instance of EVMClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. -func NewEVMRPCClient(t interface { +func NewEVMClient(t interface { mock.TestingT Cleanup(func()) -}) *EVMRPCClient { - mock := &EVMRPCClient{} +}) *EVMClient { + mock := &EVMClient{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/zetaclient/testutils/mocks/zetacore_client.go b/zetaclient/testutils/mocks/zetacore_client.go index 73608f8609..4bdb14204a 100644 --- a/zetaclient/testutils/mocks/zetacore_client.go +++ b/zetaclient/testutils/mocks/zetacore_client.go @@ -12,9 +12,9 @@ import ( context "context" - fungibletypes "github.com/zeta-chain/node/x/fungible/types" + crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" - interfaces "github.com/zeta-chain/node/zetaclient/chains/interfaces" + fungibletypes "github.com/zeta-chain/node/x/fungible/types" keysinterfaces "github.com/zeta-chain/node/zetaclient/keys/interfaces" @@ -22,9 +22,7 @@ import ( mock "github.com/stretchr/testify/mock" - observertypes "github.com/zeta-chain/node/x/observer/types" - - types "github.com/zeta-chain/node/x/crosschain/types" + types "github.com/zeta-chain/node/x/observer/types" upgradetypes "cosmossdk.io/x/upgrade/types" ) @@ -52,9 +50,9 @@ func (_m *ZetacoreClient) Chain() chains.Chain { return r0 } -// GetAdditionalChains provides a mock function with given fields: ctx -func (_m *ZetacoreClient) GetAdditionalChains(ctx context.Context) ([]chains.Chain, error) { - ret := _m.Called(ctx) +// GetAdditionalChains provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) GetAdditionalChains(_a0 context.Context) ([]chains.Chain, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for GetAdditionalChains") @@ -63,10 +61,10 @@ func (_m *ZetacoreClient) GetAdditionalChains(ctx context.Context) ([]chains.Cha var r0 []chains.Chain var r1 error if rf, ok := ret.Get(0).(func(context.Context) ([]chains.Chain, error)); ok { - return rf(ctx) + return rf(_a0) } if rf, ok := ret.Get(0).(func(context.Context) []chains.Chain); ok { - r0 = rf(ctx) + r0 = rf(_a0) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]chains.Chain) @@ -74,37 +72,7 @@ func (_m *ZetacoreClient) GetAdditionalChains(ctx context.Context) ([]chains.Cha } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetAllOutboundTrackerByChain provides a mock function with given fields: ctx, chainID, order -func (_m *ZetacoreClient) GetAllOutboundTrackerByChain(ctx context.Context, chainID int64, order interfaces.Order) ([]types.OutboundTracker, error) { - ret := _m.Called(ctx, chainID, order) - - if len(ret) == 0 { - panic("no return value specified for GetAllOutboundTrackerByChain") - } - - var r0 []types.OutboundTracker - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, interfaces.Order) ([]types.OutboundTracker, error)); ok { - return rf(ctx, chainID, order) - } - if rf, ok := ret.Get(0).(func(context.Context, int64, interfaces.Order) []types.OutboundTracker); ok { - r0 = rf(ctx, chainID, order) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]types.OutboundTracker) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, int64, interfaces.Order) error); ok { - r1 = rf(ctx, chainID, order) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -112,9 +80,9 @@ func (_m *ZetacoreClient) GetAllOutboundTrackerByChain(ctx context.Context, chai return r0, r1 } -// GetBTCTSSAddress provides a mock function with given fields: ctx, chainID -func (_m *ZetacoreClient) GetBTCTSSAddress(ctx context.Context, chainID int64) (string, error) { - ret := _m.Called(ctx, chainID) +// GetBTCTSSAddress provides a mock function with given fields: _a0, _a1 +func (_m *ZetacoreClient) GetBTCTSSAddress(_a0 context.Context, _a1 int64) (string, error) { + ret := _m.Called(_a0, _a1) if len(ret) == 0 { panic("no return value specified for GetBTCTSSAddress") @@ -123,16 +91,16 @@ func (_m *ZetacoreClient) GetBTCTSSAddress(ctx context.Context, chainID int64) ( var r0 string var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64) (string, error)); ok { - return rf(ctx, chainID) + return rf(_a0, _a1) } if rf, ok := ret.Get(0).(func(context.Context, int64) string); ok { - r0 = rf(ctx, chainID) + r0 = rf(_a0, _a1) } else { r0 = ret.Get(0).(string) } if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { - r1 = rf(ctx, chainID) + r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) } @@ -140,29 +108,29 @@ func (_m *ZetacoreClient) GetBTCTSSAddress(ctx context.Context, chainID int64) ( return r0, r1 } -// GetBallotByID provides a mock function with given fields: ctx, id -func (_m *ZetacoreClient) GetBallotByID(ctx context.Context, id string) (*observertypes.QueryBallotByIdentifierResponse, error) { - ret := _m.Called(ctx, id) +// GetBallotByID provides a mock function with given fields: _a0, _a1 +func (_m *ZetacoreClient) GetBallotByID(_a0 context.Context, _a1 string) (*types.QueryBallotByIdentifierResponse, error) { + ret := _m.Called(_a0, _a1) if len(ret) == 0 { panic("no return value specified for GetBallotByID") } - var r0 *observertypes.QueryBallotByIdentifierResponse + var r0 *types.QueryBallotByIdentifierResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (*observertypes.QueryBallotByIdentifierResponse, error)); ok { - return rf(ctx, id) + if rf, ok := ret.Get(0).(func(context.Context, string) (*types.QueryBallotByIdentifierResponse, error)); ok { + return rf(_a0, _a1) } - if rf, ok := ret.Get(0).(func(context.Context, string) *observertypes.QueryBallotByIdentifierResponse); ok { - r0 = rf(ctx, id) + if rf, ok := ret.Get(0).(func(context.Context, string) *types.QueryBallotByIdentifierResponse); ok { + r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*observertypes.QueryBallotByIdentifierResponse) + r0 = ret.Get(0).(*types.QueryBallotByIdentifierResponse) } } if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, id) + r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) } @@ -170,9 +138,9 @@ func (_m *ZetacoreClient) GetBallotByID(ctx context.Context, id string) (*observ return r0, r1 } -// GetBlockHeight provides a mock function with given fields: ctx -func (_m *ZetacoreClient) GetBlockHeight(ctx context.Context) (int64, error) { - ret := _m.Called(ctx) +// GetBlockHeight provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) GetBlockHeight(_a0 context.Context) (int64, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for GetBlockHeight") @@ -181,16 +149,16 @@ func (_m *ZetacoreClient) GetBlockHeight(ctx context.Context) (int64, error) { var r0 int64 var r1 error if rf, ok := ret.Get(0).(func(context.Context) (int64, error)); ok { - return rf(ctx) + return rf(_a0) } if rf, ok := ret.Get(0).(func(context.Context) int64); ok { - r0 = rf(ctx) + r0 = rf(_a0) } else { r0 = ret.Get(0).(int64) } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -198,29 +166,29 @@ func (_m *ZetacoreClient) GetBlockHeight(ctx context.Context) (int64, error) { return r0, r1 } -// GetCctxByHash provides a mock function with given fields: ctx, sendHash -func (_m *ZetacoreClient) GetCctxByHash(ctx context.Context, sendHash string) (*types.CrossChainTx, error) { - ret := _m.Called(ctx, sendHash) +// GetCctxByHash provides a mock function with given fields: _a0, _a1 +func (_m *ZetacoreClient) GetCctxByHash(_a0 context.Context, _a1 string) (*crosschaintypes.CrossChainTx, error) { + ret := _m.Called(_a0, _a1) if len(ret) == 0 { panic("no return value specified for GetCctxByHash") } - var r0 *types.CrossChainTx + var r0 *crosschaintypes.CrossChainTx var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (*types.CrossChainTx, error)); ok { - return rf(ctx, sendHash) + if rf, ok := ret.Get(0).(func(context.Context, string) (*crosschaintypes.CrossChainTx, error)); ok { + return rf(_a0, _a1) } - if rf, ok := ret.Get(0).(func(context.Context, string) *types.CrossChainTx); ok { - r0 = rf(ctx, sendHash) + if rf, ok := ret.Get(0).(func(context.Context, string) *crosschaintypes.CrossChainTx); ok { + r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.CrossChainTx) + r0 = ret.Get(0).(*crosschaintypes.CrossChainTx) } } if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, sendHash) + r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) } @@ -228,29 +196,29 @@ func (_m *ZetacoreClient) GetCctxByHash(ctx context.Context, sendHash string) (* return r0, r1 } -// GetCctxByNonce provides a mock function with given fields: ctx, chainID, nonce -func (_m *ZetacoreClient) GetCctxByNonce(ctx context.Context, chainID int64, nonce uint64) (*types.CrossChainTx, error) { - ret := _m.Called(ctx, chainID, nonce) +// GetCctxByNonce provides a mock function with given fields: _a0, _a1, _a2 +func (_m *ZetacoreClient) GetCctxByNonce(_a0 context.Context, _a1 int64, _a2 uint64) (*crosschaintypes.CrossChainTx, error) { + ret := _m.Called(_a0, _a1, _a2) if len(ret) == 0 { panic("no return value specified for GetCctxByNonce") } - var r0 *types.CrossChainTx + var r0 *crosschaintypes.CrossChainTx var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, uint64) (*types.CrossChainTx, error)); ok { - return rf(ctx, chainID, nonce) + if rf, ok := ret.Get(0).(func(context.Context, int64, uint64) (*crosschaintypes.CrossChainTx, error)); ok { + return rf(_a0, _a1, _a2) } - if rf, ok := ret.Get(0).(func(context.Context, int64, uint64) *types.CrossChainTx); ok { - r0 = rf(ctx, chainID, nonce) + if rf, ok := ret.Get(0).(func(context.Context, int64, uint64) *crosschaintypes.CrossChainTx); ok { + r0 = rf(_a0, _a1, _a2) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.CrossChainTx) + r0 = ret.Get(0).(*crosschaintypes.CrossChainTx) } } if rf, ok := ret.Get(1).(func(context.Context, int64, uint64) error); ok { - r1 = rf(ctx, chainID, nonce) + r1 = rf(_a0, _a1, _a2) } else { r1 = ret.Error(1) } @@ -258,29 +226,29 @@ func (_m *ZetacoreClient) GetCctxByNonce(ctx context.Context, chainID int64, non return r0, r1 } -// GetChainParams provides a mock function with given fields: ctx -func (_m *ZetacoreClient) GetChainParams(ctx context.Context) ([]*observertypes.ChainParams, error) { - ret := _m.Called(ctx) +// GetChainParams provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) GetChainParams(_a0 context.Context) ([]*types.ChainParams, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for GetChainParams") } - var r0 []*observertypes.ChainParams + var r0 []*types.ChainParams var r1 error - if rf, ok := ret.Get(0).(func(context.Context) ([]*observertypes.ChainParams, error)); ok { - return rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) ([]*types.ChainParams, error)); ok { + return rf(_a0) } - if rf, ok := ret.Get(0).(func(context.Context) []*observertypes.ChainParams); ok { - r0 = rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) []*types.ChainParams); ok { + r0 = rf(_a0) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]*observertypes.ChainParams) + r0 = ret.Get(0).([]*types.ChainParams) } } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -288,27 +256,27 @@ func (_m *ZetacoreClient) GetChainParams(ctx context.Context) ([]*observertypes. return r0, r1 } -// GetCrosschainFlags provides a mock function with given fields: ctx -func (_m *ZetacoreClient) GetCrosschainFlags(ctx context.Context) (observertypes.CrosschainFlags, error) { - ret := _m.Called(ctx) +// GetCrosschainFlags provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) GetCrosschainFlags(_a0 context.Context) (types.CrosschainFlags, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for GetCrosschainFlags") } - var r0 observertypes.CrosschainFlags + var r0 types.CrosschainFlags var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (observertypes.CrosschainFlags, error)); ok { - return rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) (types.CrosschainFlags, error)); ok { + return rf(_a0) } - if rf, ok := ret.Get(0).(func(context.Context) observertypes.CrosschainFlags); ok { - r0 = rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) types.CrosschainFlags); ok { + r0 = rf(_a0) } else { - r0 = ret.Get(0).(observertypes.CrosschainFlags) + r0 = ret.Get(0).(types.CrosschainFlags) } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -316,9 +284,9 @@ func (_m *ZetacoreClient) GetCrosschainFlags(ctx context.Context) (observertypes return r0, r1 } -// GetForeignCoinsFromAsset provides a mock function with given fields: ctx, chainID, assetAddress -func (_m *ZetacoreClient) GetForeignCoinsFromAsset(ctx context.Context, chainID int64, assetAddress common.Address) (fungibletypes.ForeignCoins, error) { - ret := _m.Called(ctx, chainID, assetAddress) +// GetForeignCoinsFromAsset provides a mock function with given fields: _a0, _a1, _a2 +func (_m *ZetacoreClient) GetForeignCoinsFromAsset(_a0 context.Context, _a1 int64, _a2 common.Address) (fungibletypes.ForeignCoins, error) { + ret := _m.Called(_a0, _a1, _a2) if len(ret) == 0 { panic("no return value specified for GetForeignCoinsFromAsset") @@ -327,16 +295,16 @@ func (_m *ZetacoreClient) GetForeignCoinsFromAsset(ctx context.Context, chainID var r0 fungibletypes.ForeignCoins var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64, common.Address) (fungibletypes.ForeignCoins, error)); ok { - return rf(ctx, chainID, assetAddress) + return rf(_a0, _a1, _a2) } if rf, ok := ret.Get(0).(func(context.Context, int64, common.Address) fungibletypes.ForeignCoins); ok { - r0 = rf(ctx, chainID, assetAddress) + r0 = rf(_a0, _a1, _a2) } else { r0 = ret.Get(0).(fungibletypes.ForeignCoins) } if rf, ok := ret.Get(1).(func(context.Context, int64, common.Address) error); ok { - r1 = rf(ctx, chainID, assetAddress) + r1 = rf(_a0, _a1, _a2) } else { r1 = ret.Error(1) } @@ -344,29 +312,29 @@ func (_m *ZetacoreClient) GetForeignCoinsFromAsset(ctx context.Context, chainID return r0, r1 } -// GetInboundTrackersForChain provides a mock function with given fields: ctx, chainID -func (_m *ZetacoreClient) GetInboundTrackersForChain(ctx context.Context, chainID int64) ([]types.InboundTracker, error) { - ret := _m.Called(ctx, chainID) +// GetInboundTrackersForChain provides a mock function with given fields: _a0, _a1 +func (_m *ZetacoreClient) GetInboundTrackersForChain(_a0 context.Context, _a1 int64) ([]crosschaintypes.InboundTracker, error) { + ret := _m.Called(_a0, _a1) if len(ret) == 0 { panic("no return value specified for GetInboundTrackersForChain") } - var r0 []types.InboundTracker + var r0 []crosschaintypes.InboundTracker var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64) ([]types.InboundTracker, error)); ok { - return rf(ctx, chainID) + if rf, ok := ret.Get(0).(func(context.Context, int64) ([]crosschaintypes.InboundTracker, error)); ok { + return rf(_a0, _a1) } - if rf, ok := ret.Get(0).(func(context.Context, int64) []types.InboundTracker); ok { - r0 = rf(ctx, chainID) + if rf, ok := ret.Get(0).(func(context.Context, int64) []crosschaintypes.InboundTracker); ok { + r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]types.InboundTracker) + r0 = ret.Get(0).([]crosschaintypes.InboundTracker) } } if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { - r1 = rf(ctx, chainID) + r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) } @@ -374,27 +342,27 @@ func (_m *ZetacoreClient) GetInboundTrackersForChain(ctx context.Context, chainI return r0, r1 } -// GetKeyGen provides a mock function with given fields: ctx -func (_m *ZetacoreClient) GetKeyGen(ctx context.Context) (observertypes.Keygen, error) { - ret := _m.Called(ctx) +// GetKeyGen provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) GetKeyGen(_a0 context.Context) (types.Keygen, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for GetKeyGen") } - var r0 observertypes.Keygen + var r0 types.Keygen var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (observertypes.Keygen, error)); ok { - return rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) (types.Keygen, error)); ok { + return rf(_a0) } - if rf, ok := ret.Get(0).(func(context.Context) observertypes.Keygen); ok { - r0 = rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) types.Keygen); ok { + r0 = rf(_a0) } else { - r0 = ret.Get(0).(observertypes.Keygen) + r0 = ret.Get(0).(types.Keygen) } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -422,9 +390,9 @@ func (_m *ZetacoreClient) GetKeys() keysinterfaces.ObserverKeys { return r0 } -// GetObserverList provides a mock function with given fields: ctx -func (_m *ZetacoreClient) GetObserverList(ctx context.Context) ([]string, error) { - ret := _m.Called(ctx) +// GetObserverList provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) GetObserverList(_a0 context.Context) ([]string, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for GetObserverList") @@ -433,10 +401,10 @@ func (_m *ZetacoreClient) GetObserverList(ctx context.Context) ([]string, error) var r0 []string var r1 error if rf, ok := ret.Get(0).(func(context.Context) ([]string, error)); ok { - return rf(ctx) + return rf(_a0) } if rf, ok := ret.Get(0).(func(context.Context) []string); ok { - r0 = rf(ctx) + r0 = rf(_a0) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]string) @@ -444,7 +412,7 @@ func (_m *ZetacoreClient) GetObserverList(ctx context.Context) ([]string, error) } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -452,27 +420,27 @@ func (_m *ZetacoreClient) GetObserverList(ctx context.Context) ([]string, error) return r0, r1 } -// GetOperationalFlags provides a mock function with given fields: ctx -func (_m *ZetacoreClient) GetOperationalFlags(ctx context.Context) (observertypes.OperationalFlags, error) { - ret := _m.Called(ctx) +// GetOperationalFlags provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) GetOperationalFlags(_a0 context.Context) (types.OperationalFlags, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for GetOperationalFlags") } - var r0 observertypes.OperationalFlags + var r0 types.OperationalFlags var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (observertypes.OperationalFlags, error)); ok { - return rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) (types.OperationalFlags, error)); ok { + return rf(_a0) } - if rf, ok := ret.Get(0).(func(context.Context) observertypes.OperationalFlags); ok { - r0 = rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) types.OperationalFlags); ok { + r0 = rf(_a0) } else { - r0 = ret.Get(0).(observertypes.OperationalFlags) + r0 = ret.Get(0).(types.OperationalFlags) } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -480,29 +448,59 @@ func (_m *ZetacoreClient) GetOperationalFlags(ctx context.Context) (observertype return r0, r1 } -// GetOutboundTracker provides a mock function with given fields: ctx, chainID, nonce -func (_m *ZetacoreClient) GetOutboundTracker(ctx context.Context, chainID int64, nonce uint64) (*types.OutboundTracker, error) { - ret := _m.Called(ctx, chainID, nonce) +// GetOutboundTracker provides a mock function with given fields: _a0, _a1, _a2 +func (_m *ZetacoreClient) GetOutboundTracker(_a0 context.Context, _a1 int64, _a2 uint64) (*crosschaintypes.OutboundTracker, error) { + ret := _m.Called(_a0, _a1, _a2) if len(ret) == 0 { panic("no return value specified for GetOutboundTracker") } - var r0 *types.OutboundTracker + var r0 *crosschaintypes.OutboundTracker var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, uint64) (*types.OutboundTracker, error)); ok { - return rf(ctx, chainID, nonce) + if rf, ok := ret.Get(0).(func(context.Context, int64, uint64) (*crosschaintypes.OutboundTracker, error)); ok { + return rf(_a0, _a1, _a2) } - if rf, ok := ret.Get(0).(func(context.Context, int64, uint64) *types.OutboundTracker); ok { - r0 = rf(ctx, chainID, nonce) + if rf, ok := ret.Get(0).(func(context.Context, int64, uint64) *crosschaintypes.OutboundTracker); ok { + r0 = rf(_a0, _a1, _a2) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.OutboundTracker) + r0 = ret.Get(0).(*crosschaintypes.OutboundTracker) } } if rf, ok := ret.Get(1).(func(context.Context, int64, uint64) error); ok { - r1 = rf(ctx, chainID, nonce) + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetOutboundTrackers provides a mock function with given fields: _a0, _a1 +func (_m *ZetacoreClient) GetOutboundTrackers(_a0 context.Context, _a1 int64) ([]crosschaintypes.OutboundTracker, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for GetOutboundTrackers") + } + + var r0 []crosschaintypes.OutboundTracker + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int64) ([]crosschaintypes.OutboundTracker, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, int64) []crosschaintypes.OutboundTracker); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]crosschaintypes.OutboundTracker) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) } @@ -510,27 +508,27 @@ func (_m *ZetacoreClient) GetOutboundTracker(ctx context.Context, chainID int64, return r0, r1 } -// GetPendingNoncesByChain provides a mock function with given fields: ctx, chainID -func (_m *ZetacoreClient) GetPendingNoncesByChain(ctx context.Context, chainID int64) (observertypes.PendingNonces, error) { - ret := _m.Called(ctx, chainID) +// GetPendingNoncesByChain provides a mock function with given fields: _a0, _a1 +func (_m *ZetacoreClient) GetPendingNoncesByChain(_a0 context.Context, _a1 int64) (types.PendingNonces, error) { + ret := _m.Called(_a0, _a1) if len(ret) == 0 { panic("no return value specified for GetPendingNoncesByChain") } - var r0 observertypes.PendingNonces + var r0 types.PendingNonces var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64) (observertypes.PendingNonces, error)); ok { - return rf(ctx, chainID) + if rf, ok := ret.Get(0).(func(context.Context, int64) (types.PendingNonces, error)); ok { + return rf(_a0, _a1) } - if rf, ok := ret.Get(0).(func(context.Context, int64) observertypes.PendingNonces); ok { - r0 = rf(ctx, chainID) + if rf, ok := ret.Get(0).(func(context.Context, int64) types.PendingNonces); ok { + r0 = rf(_a0, _a1) } else { - r0 = ret.Get(0).(observertypes.PendingNonces) + r0 = ret.Get(0).(types.PendingNonces) } if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { - r1 = rf(ctx, chainID) + r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) } @@ -538,27 +536,27 @@ func (_m *ZetacoreClient) GetPendingNoncesByChain(ctx context.Context, chainID i return r0, r1 } -// GetRateLimiterFlags provides a mock function with given fields: ctx -func (_m *ZetacoreClient) GetRateLimiterFlags(ctx context.Context) (types.RateLimiterFlags, error) { - ret := _m.Called(ctx) +// GetRateLimiterFlags provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) GetRateLimiterFlags(_a0 context.Context) (crosschaintypes.RateLimiterFlags, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for GetRateLimiterFlags") } - var r0 types.RateLimiterFlags + var r0 crosschaintypes.RateLimiterFlags var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (types.RateLimiterFlags, error)); ok { - return rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) (crosschaintypes.RateLimiterFlags, error)); ok { + return rf(_a0) } - if rf, ok := ret.Get(0).(func(context.Context) types.RateLimiterFlags); ok { - r0 = rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) crosschaintypes.RateLimiterFlags); ok { + r0 = rf(_a0) } else { - r0 = ret.Get(0).(types.RateLimiterFlags) + r0 = ret.Get(0).(crosschaintypes.RateLimiterFlags) } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -566,29 +564,29 @@ func (_m *ZetacoreClient) GetRateLimiterFlags(ctx context.Context) (types.RateLi return r0, r1 } -// GetRateLimiterInput provides a mock function with given fields: ctx, window -func (_m *ZetacoreClient) GetRateLimiterInput(ctx context.Context, window int64) (*types.QueryRateLimiterInputResponse, error) { - ret := _m.Called(ctx, window) +// GetRateLimiterInput provides a mock function with given fields: _a0, window +func (_m *ZetacoreClient) GetRateLimiterInput(_a0 context.Context, window int64) (*crosschaintypes.QueryRateLimiterInputResponse, error) { + ret := _m.Called(_a0, window) if len(ret) == 0 { panic("no return value specified for GetRateLimiterInput") } - var r0 *types.QueryRateLimiterInputResponse + var r0 *crosschaintypes.QueryRateLimiterInputResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64) (*types.QueryRateLimiterInputResponse, error)); ok { - return rf(ctx, window) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*crosschaintypes.QueryRateLimiterInputResponse, error)); ok { + return rf(_a0, window) } - if rf, ok := ret.Get(0).(func(context.Context, int64) *types.QueryRateLimiterInputResponse); ok { - r0 = rf(ctx, window) + if rf, ok := ret.Get(0).(func(context.Context, int64) *crosschaintypes.QueryRateLimiterInputResponse); ok { + r0 = rf(_a0, window) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.QueryRateLimiterInputResponse) + r0 = ret.Get(0).(*crosschaintypes.QueryRateLimiterInputResponse) } } if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { - r1 = rf(ctx, window) + r1 = rf(_a0, window) } else { r1 = ret.Error(1) } @@ -596,9 +594,9 @@ func (_m *ZetacoreClient) GetRateLimiterInput(ctx context.Context, window int64) return r0, r1 } -// GetSupportedChains provides a mock function with given fields: ctx -func (_m *ZetacoreClient) GetSupportedChains(ctx context.Context) ([]chains.Chain, error) { - ret := _m.Called(ctx) +// GetSupportedChains provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) GetSupportedChains(_a0 context.Context) ([]chains.Chain, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for GetSupportedChains") @@ -607,10 +605,10 @@ func (_m *ZetacoreClient) GetSupportedChains(ctx context.Context) ([]chains.Chai var r0 []chains.Chain var r1 error if rf, ok := ret.Get(0).(func(context.Context) ([]chains.Chain, error)); ok { - return rf(ctx) + return rf(_a0) } if rf, ok := ret.Get(0).(func(context.Context) []chains.Chain); ok { - r0 = rf(ctx) + r0 = rf(_a0) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]chains.Chain) @@ -618,7 +616,7 @@ func (_m *ZetacoreClient) GetSupportedChains(ctx context.Context) ([]chains.Chai } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -626,27 +624,27 @@ func (_m *ZetacoreClient) GetSupportedChains(ctx context.Context) ([]chains.Chai return r0, r1 } -// GetTSS provides a mock function with given fields: ctx -func (_m *ZetacoreClient) GetTSS(ctx context.Context) (observertypes.TSS, error) { - ret := _m.Called(ctx) +// GetTSS provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) GetTSS(_a0 context.Context) (types.TSS, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for GetTSS") } - var r0 observertypes.TSS + var r0 types.TSS var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (observertypes.TSS, error)); ok { - return rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) (types.TSS, error)); ok { + return rf(_a0) } - if rf, ok := ret.Get(0).(func(context.Context) observertypes.TSS); ok { - r0 = rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) types.TSS); ok { + r0 = rf(_a0) } else { - r0 = ret.Get(0).(observertypes.TSS) + r0 = ret.Get(0).(types.TSS) } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -654,29 +652,29 @@ func (_m *ZetacoreClient) GetTSS(ctx context.Context) (observertypes.TSS, error) return r0, r1 } -// GetTSSHistory provides a mock function with given fields: ctx -func (_m *ZetacoreClient) GetTSSHistory(ctx context.Context) ([]observertypes.TSS, error) { - ret := _m.Called(ctx) +// GetTSSHistory provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) GetTSSHistory(_a0 context.Context) ([]types.TSS, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for GetTSSHistory") } - var r0 []observertypes.TSS + var r0 []types.TSS var r1 error - if rf, ok := ret.Get(0).(func(context.Context) ([]observertypes.TSS, error)); ok { - return rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) ([]types.TSS, error)); ok { + return rf(_a0) } - if rf, ok := ret.Get(0).(func(context.Context) []observertypes.TSS); ok { - r0 = rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) []types.TSS); ok { + r0 = rf(_a0) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]observertypes.TSS) + r0 = ret.Get(0).([]types.TSS) } } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -684,9 +682,9 @@ func (_m *ZetacoreClient) GetTSSHistory(ctx context.Context) ([]observertypes.TS return r0, r1 } -// GetUpgradePlan provides a mock function with given fields: ctx -func (_m *ZetacoreClient) GetUpgradePlan(ctx context.Context) (*upgradetypes.Plan, error) { - ret := _m.Called(ctx) +// GetUpgradePlan provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) GetUpgradePlan(_a0 context.Context) (*upgradetypes.Plan, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for GetUpgradePlan") @@ -695,10 +693,10 @@ func (_m *ZetacoreClient) GetUpgradePlan(ctx context.Context) (*upgradetypes.Pla var r0 *upgradetypes.Plan var r1 error if rf, ok := ret.Get(0).(func(context.Context) (*upgradetypes.Plan, error)); ok { - return rf(ctx) + return rf(_a0) } if rf, ok := ret.Get(0).(func(context.Context) *upgradetypes.Plan); ok { - r0 = rf(ctx) + r0 = rf(_a0) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*upgradetypes.Plan) @@ -706,7 +704,7 @@ func (_m *ZetacoreClient) GetUpgradePlan(ctx context.Context) (*upgradetypes.Pla } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -714,9 +712,9 @@ func (_m *ZetacoreClient) GetUpgradePlan(ctx context.Context) (*upgradetypes.Pla return r0, r1 } -// GetZetaHotKeyBalance provides a mock function with given fields: ctx -func (_m *ZetacoreClient) GetZetaHotKeyBalance(ctx context.Context) (math.Int, error) { - ret := _m.Called(ctx) +// GetZetaHotKeyBalance provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) GetZetaHotKeyBalance(_a0 context.Context) (math.Int, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for GetZetaHotKeyBalance") @@ -725,16 +723,16 @@ func (_m *ZetacoreClient) GetZetaHotKeyBalance(ctx context.Context) (math.Int, e var r0 math.Int var r1 error if rf, ok := ret.Get(0).(func(context.Context) (math.Int, error)); ok { - return rf(ctx) + return rf(_a0) } if rf, ok := ret.Get(0).(func(context.Context) math.Int); ok { - r0 = rf(ctx) + r0 = rf(_a0) } else { r0 = ret.Get(0).(math.Int) } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -742,36 +740,36 @@ func (_m *ZetacoreClient) GetZetaHotKeyBalance(ctx context.Context) (math.Int, e return r0, r1 } -// ListPendingCCTX provides a mock function with given fields: ctx, chain -func (_m *ZetacoreClient) ListPendingCCTX(ctx context.Context, chain chains.Chain) ([]*types.CrossChainTx, uint64, error) { - ret := _m.Called(ctx, chain) +// ListPendingCCTX provides a mock function with given fields: _a0, _a1 +func (_m *ZetacoreClient) ListPendingCCTX(_a0 context.Context, _a1 chains.Chain) ([]*crosschaintypes.CrossChainTx, uint64, error) { + ret := _m.Called(_a0, _a1) if len(ret) == 0 { panic("no return value specified for ListPendingCCTX") } - var r0 []*types.CrossChainTx + var r0 []*crosschaintypes.CrossChainTx var r1 uint64 var r2 error - if rf, ok := ret.Get(0).(func(context.Context, chains.Chain) ([]*types.CrossChainTx, uint64, error)); ok { - return rf(ctx, chain) + if rf, ok := ret.Get(0).(func(context.Context, chains.Chain) ([]*crosschaintypes.CrossChainTx, uint64, error)); ok { + return rf(_a0, _a1) } - if rf, ok := ret.Get(0).(func(context.Context, chains.Chain) []*types.CrossChainTx); ok { - r0 = rf(ctx, chain) + if rf, ok := ret.Get(0).(func(context.Context, chains.Chain) []*crosschaintypes.CrossChainTx); ok { + r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]*types.CrossChainTx) + r0 = ret.Get(0).([]*crosschaintypes.CrossChainTx) } } if rf, ok := ret.Get(1).(func(context.Context, chains.Chain) uint64); ok { - r1 = rf(ctx, chain) + r1 = rf(_a0, _a1) } else { r1 = ret.Get(1).(uint64) } if rf, ok := ret.Get(2).(func(context.Context, chains.Chain) error); ok { - r2 = rf(ctx, chain) + r2 = rf(_a0, _a1) } else { r2 = ret.Error(2) } @@ -779,29 +777,29 @@ func (_m *ZetacoreClient) ListPendingCCTX(ctx context.Context, chain chains.Chai return r0, r1, r2 } -// ListPendingCCTXWithinRateLimit provides a mock function with given fields: ctx -func (_m *ZetacoreClient) ListPendingCCTXWithinRateLimit(ctx context.Context) (*types.QueryListPendingCctxWithinRateLimitResponse, error) { - ret := _m.Called(ctx) +// ListPendingCCTXWithinRateLimit provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) ListPendingCCTXWithinRateLimit(_a0 context.Context) (*crosschaintypes.QueryListPendingCctxWithinRateLimitResponse, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for ListPendingCCTXWithinRateLimit") } - var r0 *types.QueryListPendingCctxWithinRateLimitResponse + var r0 *crosschaintypes.QueryListPendingCctxWithinRateLimitResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (*types.QueryListPendingCctxWithinRateLimitResponse, error)); ok { - return rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) (*crosschaintypes.QueryListPendingCctxWithinRateLimitResponse, error)); ok { + return rf(_a0) } - if rf, ok := ret.Get(0).(func(context.Context) *types.QueryListPendingCctxWithinRateLimitResponse); ok { - r0 = rf(ctx) + if rf, ok := ret.Get(0).(func(context.Context) *crosschaintypes.QueryListPendingCctxWithinRateLimitResponse); ok { + r0 = rf(_a0) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.QueryListPendingCctxWithinRateLimitResponse) + r0 = ret.Get(0).(*crosschaintypes.QueryListPendingCctxWithinRateLimitResponse) } } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -809,9 +807,9 @@ func (_m *ZetacoreClient) ListPendingCCTXWithinRateLimit(ctx context.Context) (* return r0, r1 } -// NewBlockSubscriber provides a mock function with given fields: ctx -func (_m *ZetacoreClient) NewBlockSubscriber(ctx context.Context) (chan cometbfttypes.EventDataNewBlock, error) { - ret := _m.Called(ctx) +// NewBlockSubscriber provides a mock function with given fields: _a0 +func (_m *ZetacoreClient) NewBlockSubscriber(_a0 context.Context) (chan cometbfttypes.EventDataNewBlock, error) { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for NewBlockSubscriber") @@ -820,10 +818,10 @@ func (_m *ZetacoreClient) NewBlockSubscriber(ctx context.Context) (chan cometbft var r0 chan cometbfttypes.EventDataNewBlock var r1 error if rf, ok := ret.Get(0).(func(context.Context) (chan cometbfttypes.EventDataNewBlock, error)); ok { - return rf(ctx) + return rf(_a0) } if rf, ok := ret.Get(0).(func(context.Context) chan cometbfttypes.EventDataNewBlock); ok { - r0 = rf(ctx) + r0 = rf(_a0) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(chan cometbfttypes.EventDataNewBlock) @@ -831,7 +829,7 @@ func (_m *ZetacoreClient) NewBlockSubscriber(ctx context.Context) (chan cometbft } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -839,9 +837,9 @@ func (_m *ZetacoreClient) NewBlockSubscriber(ctx context.Context) (chan cometbft return r0, r1 } -// PostOutboundTracker provides a mock function with given fields: ctx, chainID, nonce, txHash -func (_m *ZetacoreClient) PostOutboundTracker(ctx context.Context, chainID int64, nonce uint64, txHash string) (string, error) { - ret := _m.Called(ctx, chainID, nonce, txHash) +// PostOutboundTracker provides a mock function with given fields: _a0, _a1, _a2, txHash +func (_m *ZetacoreClient) PostOutboundTracker(_a0 context.Context, _a1 int64, _a2 uint64, txHash string) (string, error) { + ret := _m.Called(_a0, _a1, _a2, txHash) if len(ret) == 0 { panic("no return value specified for PostOutboundTracker") @@ -850,16 +848,16 @@ func (_m *ZetacoreClient) PostOutboundTracker(ctx context.Context, chainID int64 var r0 string var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64, uint64, string) (string, error)); ok { - return rf(ctx, chainID, nonce, txHash) + return rf(_a0, _a1, _a2, txHash) } if rf, ok := ret.Get(0).(func(context.Context, int64, uint64, string) string); ok { - r0 = rf(ctx, chainID, nonce, txHash) + r0 = rf(_a0, _a1, _a2, txHash) } else { r0 = ret.Get(0).(string) } if rf, ok := ret.Get(1).(func(context.Context, int64, uint64, string) error); ok { - r1 = rf(ctx, chainID, nonce, txHash) + r1 = rf(_a0, _a1, _a2, txHash) } else { r1 = ret.Error(1) } @@ -867,9 +865,9 @@ func (_m *ZetacoreClient) PostOutboundTracker(ctx context.Context, chainID int64 return r0, r1 } -// PostVoteBlameData provides a mock function with given fields: ctx, _a1, chainID, index -func (_m *ZetacoreClient) PostVoteBlameData(ctx context.Context, _a1 *blame.Blame, chainID int64, index string) (string, error) { - ret := _m.Called(ctx, _a1, chainID, index) +// PostVoteBlameData provides a mock function with given fields: _a0, _a1, _a2, index +func (_m *ZetacoreClient) PostVoteBlameData(_a0 context.Context, _a1 *blame.Blame, _a2 int64, index string) (string, error) { + ret := _m.Called(_a0, _a1, _a2, index) if len(ret) == 0 { panic("no return value specified for PostVoteBlameData") @@ -878,16 +876,16 @@ func (_m *ZetacoreClient) PostVoteBlameData(ctx context.Context, _a1 *blame.Blam var r0 string var r1 error if rf, ok := ret.Get(0).(func(context.Context, *blame.Blame, int64, string) (string, error)); ok { - return rf(ctx, _a1, chainID, index) + return rf(_a0, _a1, _a2, index) } if rf, ok := ret.Get(0).(func(context.Context, *blame.Blame, int64, string) string); ok { - r0 = rf(ctx, _a1, chainID, index) + r0 = rf(_a0, _a1, _a2, index) } else { r0 = ret.Get(0).(string) } if rf, ok := ret.Get(1).(func(context.Context, *blame.Blame, int64, string) error); ok { - r1 = rf(ctx, _a1, chainID, index) + r1 = rf(_a0, _a1, _a2, index) } else { r1 = ret.Error(1) } @@ -895,9 +893,9 @@ func (_m *ZetacoreClient) PostVoteBlameData(ctx context.Context, _a1 *blame.Blam return r0, r1 } -// PostVoteGasPrice provides a mock function with given fields: ctx, chain, gasPrice, priorityFee, blockNum -func (_m *ZetacoreClient) PostVoteGasPrice(ctx context.Context, chain chains.Chain, gasPrice uint64, priorityFee uint64, blockNum uint64) (string, error) { - ret := _m.Called(ctx, chain, gasPrice, priorityFee, blockNum) +// PostVoteGasPrice provides a mock function with given fields: _a0, _a1, gasPrice, priorityFee, blockNum +func (_m *ZetacoreClient) PostVoteGasPrice(_a0 context.Context, _a1 chains.Chain, gasPrice uint64, priorityFee uint64, blockNum uint64) (string, error) { + ret := _m.Called(_a0, _a1, gasPrice, priorityFee, blockNum) if len(ret) == 0 { panic("no return value specified for PostVoteGasPrice") @@ -906,16 +904,16 @@ func (_m *ZetacoreClient) PostVoteGasPrice(ctx context.Context, chain chains.Cha var r0 string var r1 error if rf, ok := ret.Get(0).(func(context.Context, chains.Chain, uint64, uint64, uint64) (string, error)); ok { - return rf(ctx, chain, gasPrice, priorityFee, blockNum) + return rf(_a0, _a1, gasPrice, priorityFee, blockNum) } if rf, ok := ret.Get(0).(func(context.Context, chains.Chain, uint64, uint64, uint64) string); ok { - r0 = rf(ctx, chain, gasPrice, priorityFee, blockNum) + r0 = rf(_a0, _a1, gasPrice, priorityFee, blockNum) } else { r0 = ret.Get(0).(string) } if rf, ok := ret.Get(1).(func(context.Context, chains.Chain, uint64, uint64, uint64) error); ok { - r1 = rf(ctx, chain, gasPrice, priorityFee, blockNum) + r1 = rf(_a0, _a1, gasPrice, priorityFee, blockNum) } else { r1 = ret.Error(1) } @@ -923,9 +921,9 @@ func (_m *ZetacoreClient) PostVoteGasPrice(ctx context.Context, chain chains.Cha return r0, r1 } -// PostVoteInbound provides a mock function with given fields: ctx, gasLimit, retryGasLimit, msg -func (_m *ZetacoreClient) PostVoteInbound(ctx context.Context, gasLimit uint64, retryGasLimit uint64, msg *types.MsgVoteInbound) (string, string, error) { - ret := _m.Called(ctx, gasLimit, retryGasLimit, msg) +// PostVoteInbound provides a mock function with given fields: _a0, gasLimit, retryGasLimit, _a3 +func (_m *ZetacoreClient) PostVoteInbound(_a0 context.Context, gasLimit uint64, retryGasLimit uint64, _a3 *crosschaintypes.MsgVoteInbound) (string, string, error) { + ret := _m.Called(_a0, gasLimit, retryGasLimit, _a3) if len(ret) == 0 { panic("no return value specified for PostVoteInbound") @@ -934,23 +932,23 @@ func (_m *ZetacoreClient) PostVoteInbound(ctx context.Context, gasLimit uint64, var r0 string var r1 string var r2 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, *types.MsgVoteInbound) (string, string, error)); ok { - return rf(ctx, gasLimit, retryGasLimit, msg) + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, *crosschaintypes.MsgVoteInbound) (string, string, error)); ok { + return rf(_a0, gasLimit, retryGasLimit, _a3) } - if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, *types.MsgVoteInbound) string); ok { - r0 = rf(ctx, gasLimit, retryGasLimit, msg) + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, *crosschaintypes.MsgVoteInbound) string); ok { + r0 = rf(_a0, gasLimit, retryGasLimit, _a3) } else { r0 = ret.Get(0).(string) } - if rf, ok := ret.Get(1).(func(context.Context, uint64, uint64, *types.MsgVoteInbound) string); ok { - r1 = rf(ctx, gasLimit, retryGasLimit, msg) + if rf, ok := ret.Get(1).(func(context.Context, uint64, uint64, *crosschaintypes.MsgVoteInbound) string); ok { + r1 = rf(_a0, gasLimit, retryGasLimit, _a3) } else { r1 = ret.Get(1).(string) } - if rf, ok := ret.Get(2).(func(context.Context, uint64, uint64, *types.MsgVoteInbound) error); ok { - r2 = rf(ctx, gasLimit, retryGasLimit, msg) + if rf, ok := ret.Get(2).(func(context.Context, uint64, uint64, *crosschaintypes.MsgVoteInbound) error); ok { + r2 = rf(_a0, gasLimit, retryGasLimit, _a3) } else { r2 = ret.Error(2) } @@ -958,9 +956,9 @@ func (_m *ZetacoreClient) PostVoteInbound(ctx context.Context, gasLimit uint64, return r0, r1, r2 } -// PostVoteOutbound provides a mock function with given fields: ctx, gasLimit, retryGasLimit, msg -func (_m *ZetacoreClient) PostVoteOutbound(ctx context.Context, gasLimit uint64, retryGasLimit uint64, msg *types.MsgVoteOutbound) (string, string, error) { - ret := _m.Called(ctx, gasLimit, retryGasLimit, msg) +// PostVoteOutbound provides a mock function with given fields: _a0, gasLimit, retryGasLimit, _a3 +func (_m *ZetacoreClient) PostVoteOutbound(_a0 context.Context, gasLimit uint64, retryGasLimit uint64, _a3 *crosschaintypes.MsgVoteOutbound) (string, string, error) { + ret := _m.Called(_a0, gasLimit, retryGasLimit, _a3) if len(ret) == 0 { panic("no return value specified for PostVoteOutbound") @@ -969,23 +967,23 @@ func (_m *ZetacoreClient) PostVoteOutbound(ctx context.Context, gasLimit uint64, var r0 string var r1 string var r2 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, *types.MsgVoteOutbound) (string, string, error)); ok { - return rf(ctx, gasLimit, retryGasLimit, msg) + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, *crosschaintypes.MsgVoteOutbound) (string, string, error)); ok { + return rf(_a0, gasLimit, retryGasLimit, _a3) } - if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, *types.MsgVoteOutbound) string); ok { - r0 = rf(ctx, gasLimit, retryGasLimit, msg) + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, *crosschaintypes.MsgVoteOutbound) string); ok { + r0 = rf(_a0, gasLimit, retryGasLimit, _a3) } else { r0 = ret.Get(0).(string) } - if rf, ok := ret.Get(1).(func(context.Context, uint64, uint64, *types.MsgVoteOutbound) string); ok { - r1 = rf(ctx, gasLimit, retryGasLimit, msg) + if rf, ok := ret.Get(1).(func(context.Context, uint64, uint64, *crosschaintypes.MsgVoteOutbound) string); ok { + r1 = rf(_a0, gasLimit, retryGasLimit, _a3) } else { r1 = ret.Get(1).(string) } - if rf, ok := ret.Get(2).(func(context.Context, uint64, uint64, *types.MsgVoteOutbound) error); ok { - r2 = rf(ctx, gasLimit, retryGasLimit, msg) + if rf, ok := ret.Get(2).(func(context.Context, uint64, uint64, *crosschaintypes.MsgVoteOutbound) error); ok { + r2 = rf(_a0, gasLimit, retryGasLimit, _a3) } else { r2 = ret.Error(2) } @@ -993,9 +991,9 @@ func (_m *ZetacoreClient) PostVoteOutbound(ctx context.Context, gasLimit uint64, return r0, r1, r2 } -// PostVoteTSS provides a mock function with given fields: ctx, tssPubKey, keyGenZetaHeight, status -func (_m *ZetacoreClient) PostVoteTSS(ctx context.Context, tssPubKey string, keyGenZetaHeight int64, status chains.ReceiveStatus) (string, error) { - ret := _m.Called(ctx, tssPubKey, keyGenZetaHeight, status) +// PostVoteTSS provides a mock function with given fields: _a0, tssPubKey, keyGenZetaHeight, _a3 +func (_m *ZetacoreClient) PostVoteTSS(_a0 context.Context, tssPubKey string, keyGenZetaHeight int64, _a3 chains.ReceiveStatus) (string, error) { + ret := _m.Called(_a0, tssPubKey, keyGenZetaHeight, _a3) if len(ret) == 0 { panic("no return value specified for PostVoteTSS") @@ -1004,16 +1002,16 @@ func (_m *ZetacoreClient) PostVoteTSS(ctx context.Context, tssPubKey string, key var r0 string var r1 error if rf, ok := ret.Get(0).(func(context.Context, string, int64, chains.ReceiveStatus) (string, error)); ok { - return rf(ctx, tssPubKey, keyGenZetaHeight, status) + return rf(_a0, tssPubKey, keyGenZetaHeight, _a3) } if rf, ok := ret.Get(0).(func(context.Context, string, int64, chains.ReceiveStatus) string); ok { - r0 = rf(ctx, tssPubKey, keyGenZetaHeight, status) + r0 = rf(_a0, tssPubKey, keyGenZetaHeight, _a3) } else { r0 = ret.Get(0).(string) } if rf, ok := ret.Get(1).(func(context.Context, string, int64, chains.ReceiveStatus) error); ok { - r1 = rf(ctx, tssPubKey, keyGenZetaHeight, status) + r1 = rf(_a0, tssPubKey, keyGenZetaHeight, _a3) } else { r1 = ret.Error(1) } diff --git a/zetaclient/zetacore/client_crosschain.go b/zetaclient/zetacore/client_crosschain.go index 2155f10bd6..09df1212ee 100644 --- a/zetaclient/zetacore/client_crosschain.go +++ b/zetaclient/zetacore/client_crosschain.go @@ -9,7 +9,6 @@ import ( "github.com/zeta-chain/node/pkg/chains" "github.com/zeta-chain/node/x/crosschain/types" - "github.com/zeta-chain/node/zetaclient/chains/interfaces" "github.com/zeta-chain/node/zetaclient/metrics" ) @@ -25,11 +24,9 @@ func (c *Client) ListPendingCCTX(ctx context.Context, chain chains.Chain) ([]*ty return list, total, err } -// GetAllOutboundTrackerByChain returns all outbound trackers for a chain -func (c *Client) GetAllOutboundTrackerByChain( - ctx context.Context, +// GetOutboundTrackers returns all outbound trackers for a chain in ascending order. +func (c *Client) GetOutboundTrackers(ctx context.Context, chainID int64, - order interfaces.Order, ) ([]types.OutboundTracker, error) { in := &types.QueryAllOutboundTrackerByChainRequest{ Chain: chainID, @@ -47,15 +44,9 @@ func (c *Client) GetAllOutboundTrackerByChain( return nil, errors.Wrap(err, "failed to get all outbound trackers") } - if order == interfaces.Ascending { - sort.SliceStable(resp.OutboundTracker, func(i, j int) bool { - return resp.OutboundTracker[i].Nonce < resp.OutboundTracker[j].Nonce - }) - } else if order == interfaces.Descending { - sort.SliceStable(resp.OutboundTracker, func(i, j int) bool { - return resp.OutboundTracker[i].Nonce > resp.OutboundTracker[j].Nonce - }) - } + sort.SliceStable(resp.OutboundTracker, func(i, j int) bool { + return resp.OutboundTracker[i].Nonce < resp.OutboundTracker[j].Nonce + }) return resp.OutboundTracker, nil } diff --git a/zetaclient/zetacore/client_test.go b/zetaclient/zetacore/client_test.go index cea0a6e851..7ba16cc385 100644 --- a/zetaclient/zetacore/client_test.go +++ b/zetaclient/zetacore/client_test.go @@ -18,7 +18,6 @@ import ( "github.com/rs/zerolog" "github.com/stretchr/testify/require" "github.com/zeta-chain/node/pkg/chains" - "github.com/zeta-chain/node/zetaclient/chains/interfaces" keyinterfaces "github.com/zeta-chain/node/zetaclient/keys/interfaces" "go.nhat.io/grpcmock" "go.nhat.io/grpcmock/planner" @@ -199,7 +198,7 @@ func TestZetacore_GetZetaHotKeyBalance(t *testing.T) { require.Equal(t, sdkmath.ZeroInt(), resp) } -func TestZetacore_GetAllOutboundTrackerByChain(t *testing.T) { +func TestZetacore_GetOutboundTrackers(t *testing.T) { ctx := context.Background() chain := chains.BscMainnet @@ -233,11 +232,7 @@ func TestZetacore_GetAllOutboundTrackerByChain(t *testing.T) { withAccountRetriever(t, 5, 4), ) - resp, err := client.GetAllOutboundTrackerByChain(ctx, chain.ChainId, interfaces.Ascending) - require.NoError(t, err) - require.Equal(t, expectedOutput.OutboundTracker, resp) - - resp, err = client.GetAllOutboundTrackerByChain(ctx, chain.ChainId, interfaces.Descending) + resp, err := client.GetOutboundTrackers(ctx, chain.ChainId) require.NoError(t, err) require.Equal(t, expectedOutput.OutboundTracker, resp) }