test(wallet)_: created Transactor interface
- Moved some methods from Transactor to users of it to clean interface. - Mocked Bridge interface and Transactor interface for tests - Wrote unit tests for SendTransaction
This commit is contained in:
parent
4d1149100f
commit
a135b27980
2
Makefile
2
Makefile
|
@ -342,6 +342,8 @@ mock: ##@other Regenerate mocks
|
||||||
mockgen -package=fake -destination=transactions/fake/mock.go -source=transactions/fake/txservice.go
|
mockgen -package=fake -destination=transactions/fake/mock.go -source=transactions/fake/txservice.go
|
||||||
mockgen -package=status -destination=services/status/account_mock.go -source=services/status/service.go
|
mockgen -package=status -destination=services/status/account_mock.go -source=services/status/service.go
|
||||||
mockgen -package=peer -destination=services/peer/discoverer_mock.go -source=services/peer/service.go
|
mockgen -package=peer -destination=services/peer/discoverer_mock.go -source=services/peer/service.go
|
||||||
|
mockgen -package=mock_transactor -destination=transactions/mock_transactor/transactor.go -source=transactions/transactor.go
|
||||||
|
mockgen -package=mock_bridge -destination=services/wallet/bridge/mock_bridge/bridge.go -source=services/wallet/bridge/bridge.go
|
||||||
|
|
||||||
docker-test: ##@tests Run tests in a docker container with golang.
|
docker-test: ##@tests Run tests in a docker container with golang.
|
||||||
docker run --privileged --rm -it -v "$(PWD):$(DOCKER_TEST_WORKDIR)" -w "$(DOCKER_TEST_WORKDIR)" $(DOCKER_TEST_IMAGE) go test ${ARGS}
|
docker run --privileged --rm -it -v "$(PWD):$(DOCKER_TEST_WORKDIR)" -w "$(DOCKER_TEST_WORKDIR)" $(DOCKER_TEST_IMAGE) go test ${ARGS}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
|
|
||||||
"github.com/imdario/mergo"
|
"github.com/imdario/mergo"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
@ -1950,7 +1951,12 @@ func (b *GethStatusBackend) SendTransactionWithChainID(chainID uint64, sendArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *GethStatusBackend) SendTransactionWithSignature(sendArgs transactions.SendTxArgs, sig []byte) (hash types.Hash, err error) {
|
func (b *GethStatusBackend) SendTransactionWithSignature(sendArgs transactions.SendTxArgs, sig []byte) (hash types.Hash, err error) {
|
||||||
return b.transactor.BuildTransactionAndSendWithSignature(b.transactor.NetworkID(), sendArgs, sig)
|
txWithSignature, err := b.transactor.BuildTransactionWithSignature(b.transactor.NetworkID(), sendArgs, sig)
|
||||||
|
if err != nil {
|
||||||
|
return hash, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.transactor.SendTransactionWithSignature(common.Address(sendArgs.From), sendArgs.Symbol, sendArgs.MultiTransactionID, txWithSignature)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HashTransaction validate the transaction and returns new sendArgs and the transaction hash.
|
// HashTransaction validate the transaction and returns new sendArgs and the transaction hash.
|
||||||
|
|
|
@ -602,13 +602,13 @@ func (api *API) SendTransactionWithSignature(ctx context.Context, chainID uint64
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return hash, err
|
return hash, err
|
||||||
}
|
}
|
||||||
return api.s.transactionManager.SendTransactionWithSignature(chainID, txType, params, sig)
|
return api.s.transactionManager.SendTransactionWithSignature(chainID, params, sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) CreateMultiTransaction(ctx context.Context, multiTransactionCommand *transfer.MultiTransactionCommand, data []*bridge.TransactionBridge, password string) (*transfer.MultiTransactionCommandResult, error) {
|
func (api *API) CreateMultiTransaction(ctx context.Context, multiTransactionCommand *transfer.MultiTransactionCommand, data []*bridge.TransactionBridge, password string) (*transfer.MultiTransactionCommandResult, error) {
|
||||||
log.Debug("[WalletAPI:: CreateMultiTransaction] create multi transaction")
|
log.Debug("[WalletAPI:: CreateMultiTransaction] create multi transaction")
|
||||||
|
|
||||||
cmd, err := api.s.transactionManager.CreateMultiTransactionFromCommand(ctx, multiTransactionCommand, data)
|
cmd, err := api.s.transactionManager.CreateMultiTransactionFromCommand(multiTransactionCommand, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,13 +43,13 @@ type CBridgeTxArgs struct {
|
||||||
type CBridge struct {
|
type CBridge struct {
|
||||||
rpcClient *rpc.Client
|
rpcClient *rpc.Client
|
||||||
httpClient *thirdparty.HTTPClient
|
httpClient *thirdparty.HTTPClient
|
||||||
transactor *transactions.Transactor
|
transactor transactions.TransactorIface
|
||||||
tokenManager *token.Manager
|
tokenManager *token.Manager
|
||||||
prodTransferConfig *cbridge.GetTransferConfigsResponse
|
prodTransferConfig *cbridge.GetTransferConfigsResponse
|
||||||
testTransferConfig *cbridge.GetTransferConfigsResponse
|
testTransferConfig *cbridge.GetTransferConfigsResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCbridge(rpcClient *rpc.Client, transactor *transactions.Transactor, tokenManager *token.Manager) *CBridge {
|
func NewCbridge(rpcClient *rpc.Client, transactor transactions.TransactorIface, tokenManager *token.Manager) *CBridge {
|
||||||
return &CBridge{
|
return &CBridge{
|
||||||
rpcClient: rpcClient,
|
rpcClient: rpcClient,
|
||||||
httpClient: thirdparty.NewHTTPClient(),
|
httpClient: thirdparty.NewHTTPClient(),
|
||||||
|
|
|
@ -30,10 +30,10 @@ type ERC1155TransferTxArgs struct {
|
||||||
|
|
||||||
type ERC1155TransferBridge struct {
|
type ERC1155TransferBridge struct {
|
||||||
rpcClient *rpc.Client
|
rpcClient *rpc.Client
|
||||||
transactor *transactions.Transactor
|
transactor transactions.TransactorIface
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewERC1155TransferBridge(rpcClient *rpc.Client, transactor *transactions.Transactor) *ERC1155TransferBridge {
|
func NewERC1155TransferBridge(rpcClient *rpc.Client, transactor transactions.TransactorIface) *ERC1155TransferBridge {
|
||||||
return &ERC1155TransferBridge{rpcClient: rpcClient, transactor: transactor}
|
return &ERC1155TransferBridge{rpcClient: rpcClient, transactor: transactor}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,10 @@ type ERC721TransferTxArgs struct {
|
||||||
|
|
||||||
type ERC721TransferBridge struct {
|
type ERC721TransferBridge struct {
|
||||||
rpcClient *rpc.Client
|
rpcClient *rpc.Client
|
||||||
transactor *transactions.Transactor
|
transactor transactions.TransactorIface
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewERC721TransferBridge(rpcClient *rpc.Client, transactor *transactions.Transactor) *ERC721TransferBridge {
|
func NewERC721TransferBridge(rpcClient *rpc.Client, transactor transactions.TransactorIface) *ERC721TransferBridge {
|
||||||
return &ERC721TransferBridge{rpcClient: rpcClient, transactor: transactor}
|
return &ERC721TransferBridge{rpcClient: rpcClient, transactor: transactor}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,14 +107,14 @@ func (bf *BonderFee) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type HopBridge struct {
|
type HopBridge struct {
|
||||||
transactor *transactions.Transactor
|
transactor transactions.TransactorIface
|
||||||
httpClient *thirdparty.HTTPClient
|
httpClient *thirdparty.HTTPClient
|
||||||
tokenManager *token.Manager
|
tokenManager *token.Manager
|
||||||
contractMaker *contracts.ContractMaker
|
contractMaker *contracts.ContractMaker
|
||||||
bonderFee *BonderFee
|
bonderFee *BonderFee
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHopBridge(rpcClient *rpc.Client, transactor *transactions.Transactor, tokenManager *token.Manager) *HopBridge {
|
func NewHopBridge(rpcClient *rpc.Client, transactor transactions.TransactorIface, tokenManager *token.Manager) *HopBridge {
|
||||||
return &HopBridge{
|
return &HopBridge{
|
||||||
contractMaker: &contracts.ContractMaker{RPCClient: rpcClient},
|
contractMaker: &contracts.ContractMaker{RPCClient: rpcClient},
|
||||||
httpClient: thirdparty.NewHTTPClient(),
|
httpClient: thirdparty.NewHTTPClient(),
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# To generate mocks, from status-go root directory:
|
||||||
|
mockgen -source=services/wallet/bridge/bridge.go -destination=services/wallet/bridge/mock_bridge/bridge.go -package=mock_bridge
|
|
@ -0,0 +1,192 @@
|
||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: services/wallet/bridge/bridge.go
|
||||||
|
|
||||||
|
// Package mock_bridge is a generated GoMock package.
|
||||||
|
package mock_bridge
|
||||||
|
|
||||||
|
import (
|
||||||
|
big "math/big"
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
common "github.com/ethereum/go-ethereum/common"
|
||||||
|
types "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
account "github.com/status-im/status-go/account"
|
||||||
|
types0 "github.com/status-im/status-go/eth-node/types"
|
||||||
|
params "github.com/status-im/status-go/params"
|
||||||
|
bridge "github.com/status-im/status-go/services/wallet/bridge"
|
||||||
|
token "github.com/status-im/status-go/services/wallet/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockBridge is a mock of Bridge interface.
|
||||||
|
type MockBridge struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockBridgeMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockBridgeMockRecorder is the mock recorder for MockBridge.
|
||||||
|
type MockBridgeMockRecorder struct {
|
||||||
|
mock *MockBridge
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockBridge creates a new mock instance.
|
||||||
|
func NewMockBridge(ctrl *gomock.Controller) *MockBridge {
|
||||||
|
mock := &MockBridge{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockBridgeMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockBridge) EXPECT() *MockBridgeMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// AvailableFor mocks base method.
|
||||||
|
func (m *MockBridge) AvailableFor(from, to *params.Network, token, toToken *token.Token) (bool, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "AvailableFor", from, to, token, toToken)
|
||||||
|
ret0, _ := ret[0].(bool)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// AvailableFor indicates an expected call of AvailableFor.
|
||||||
|
func (mr *MockBridgeMockRecorder) AvailableFor(from, to, token, toToken interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AvailableFor", reflect.TypeOf((*MockBridge)(nil).AvailableFor), from, to, token, toToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildTransaction mocks base method.
|
||||||
|
func (m *MockBridge) BuildTransaction(sendArgs *bridge.TransactionBridge) (*types.Transaction, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "BuildTransaction", sendArgs)
|
||||||
|
ret0, _ := ret[0].(*types.Transaction)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildTransaction indicates an expected call of BuildTransaction.
|
||||||
|
func (mr *MockBridgeMockRecorder) BuildTransaction(sendArgs interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BuildTransaction", reflect.TypeOf((*MockBridge)(nil).BuildTransaction), sendArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildTx mocks base method.
|
||||||
|
func (m *MockBridge) BuildTx(fromNetwork, toNetwork *params.Network, fromAddress, toAddress common.Address, token *token.Token, amountIn, bonderFee *big.Int) (*types.Transaction, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "BuildTx", fromNetwork, toNetwork, fromAddress, toAddress, token, amountIn, bonderFee)
|
||||||
|
ret0, _ := ret[0].(*types.Transaction)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildTx indicates an expected call of BuildTx.
|
||||||
|
func (mr *MockBridgeMockRecorder) BuildTx(fromNetwork, toNetwork, fromAddress, toAddress, token, amountIn, bonderFee interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BuildTx", reflect.TypeOf((*MockBridge)(nil).BuildTx), fromNetwork, toNetwork, fromAddress, toAddress, token, amountIn, bonderFee)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CalculateAmountOut mocks base method.
|
||||||
|
func (m *MockBridge) CalculateAmountOut(from, to *params.Network, amountIn *big.Int, symbol string) (*big.Int, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "CalculateAmountOut", from, to, amountIn, symbol)
|
||||||
|
ret0, _ := ret[0].(*big.Int)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// CalculateAmountOut indicates an expected call of CalculateAmountOut.
|
||||||
|
func (mr *MockBridgeMockRecorder) CalculateAmountOut(from, to, amountIn, symbol interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CalculateAmountOut", reflect.TypeOf((*MockBridge)(nil).CalculateAmountOut), from, to, amountIn, symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CalculateFees mocks base method.
|
||||||
|
func (m *MockBridge) CalculateFees(from, to *params.Network, token *token.Token, amountIn *big.Int) (*big.Int, *big.Int, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "CalculateFees", from, to, token, amountIn)
|
||||||
|
ret0, _ := ret[0].(*big.Int)
|
||||||
|
ret1, _ := ret[1].(*big.Int)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CalculateFees indicates an expected call of CalculateFees.
|
||||||
|
func (mr *MockBridgeMockRecorder) CalculateFees(from, to, token, amountIn interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CalculateFees", reflect.TypeOf((*MockBridge)(nil).CalculateFees), from, to, token, amountIn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EstimateGas mocks base method.
|
||||||
|
func (m *MockBridge) EstimateGas(fromNetwork, toNetwork *params.Network, from, to common.Address, token, toToken *token.Token, amountIn *big.Int) (uint64, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "EstimateGas", fromNetwork, toNetwork, from, to, token, toToken, amountIn)
|
||||||
|
ret0, _ := ret[0].(uint64)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// EstimateGas indicates an expected call of EstimateGas.
|
||||||
|
func (mr *MockBridgeMockRecorder) EstimateGas(fromNetwork, toNetwork, from, to, token, toToken, amountIn interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EstimateGas", reflect.TypeOf((*MockBridge)(nil).EstimateGas), fromNetwork, toNetwork, from, to, token, toToken, amountIn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetContractAddress mocks base method.
|
||||||
|
func (m *MockBridge) GetContractAddress(network *params.Network, token *token.Token) (common.Address, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "GetContractAddress", network, token)
|
||||||
|
ret0, _ := ret[0].(common.Address)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetContractAddress indicates an expected call of GetContractAddress.
|
||||||
|
func (mr *MockBridgeMockRecorder) GetContractAddress(network, token interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetContractAddress", reflect.TypeOf((*MockBridge)(nil).GetContractAddress), network, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name mocks base method.
|
||||||
|
func (m *MockBridge) Name() string {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Name")
|
||||||
|
ret0, _ := ret[0].(string)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name indicates an expected call of Name.
|
||||||
|
func (mr *MockBridgeMockRecorder) Name() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockBridge)(nil).Name))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackTxInputData mocks base method.
|
||||||
|
func (m *MockBridge) PackTxInputData(contractType string, fromNetwork, toNetwork *params.Network, from, to common.Address, token *token.Token, amountIn *big.Int) ([]byte, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "PackTxInputData", contractType, fromNetwork, toNetwork, from, to, token, amountIn)
|
||||||
|
ret0, _ := ret[0].([]byte)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackTxInputData indicates an expected call of PackTxInputData.
|
||||||
|
func (mr *MockBridgeMockRecorder) PackTxInputData(contractType, fromNetwork, toNetwork, from, to, token, amountIn interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PackTxInputData", reflect.TypeOf((*MockBridge)(nil).PackTxInputData), contractType, fromNetwork, toNetwork, from, to, token, amountIn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send mocks base method.
|
||||||
|
func (m *MockBridge) Send(sendArgs *bridge.TransactionBridge, verifiedAccount *account.SelectedExtKey) (types0.Hash, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Send", sendArgs, verifiedAccount)
|
||||||
|
ret0, _ := ret[0].(types0.Hash)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send indicates an expected call of Send.
|
||||||
|
func (mr *MockBridgeMockRecorder) Send(sendArgs, verifiedAccount interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockBridge)(nil).Send), sendArgs, verifiedAccount)
|
||||||
|
}
|
|
@ -28,10 +28,10 @@ type SwapTxArgs struct {
|
||||||
type SwapParaswap struct {
|
type SwapParaswap struct {
|
||||||
paraswapClient *paraswap.ClientV5
|
paraswapClient *paraswap.ClientV5
|
||||||
priceRoute paraswap.Route
|
priceRoute paraswap.Route
|
||||||
transactor *transactions.Transactor
|
transactor transactions.TransactorIface
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSwapParaswap(rpcClient *rpc.Client, transactor *transactions.Transactor, tokenManager *walletToken.Manager) *SwapParaswap {
|
func NewSwapParaswap(rpcClient *rpc.Client, transactor transactions.TransactorIface, tokenManager *walletToken.Manager) *SwapParaswap {
|
||||||
return &SwapParaswap{
|
return &SwapParaswap{
|
||||||
paraswapClient: paraswap.NewClientV5(walletCommon.EthereumMainnet),
|
paraswapClient: paraswap.NewClientV5(walletCommon.EthereumMainnet),
|
||||||
transactor: transactor,
|
transactor: transactor,
|
||||||
|
|
|
@ -21,10 +21,10 @@ import (
|
||||||
|
|
||||||
type TransferBridge struct {
|
type TransferBridge struct {
|
||||||
rpcClient *rpc.Client
|
rpcClient *rpc.Client
|
||||||
transactor *transactions.Transactor
|
transactor transactions.TransactorIface
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTransferBridge(rpcClient *rpc.Client, transactor *transactions.Transactor) *TransferBridge {
|
func NewTransferBridge(rpcClient *rpc.Client, transactor transactions.TransactorIface) *TransferBridge {
|
||||||
return &TransferBridge{rpcClient: rpcClient, transactor: transactor}
|
return &TransferBridge{rpcClient: rpcClient, transactor: transactor}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ func (tm *TransactionManager) removeMultiTransactionByAddress(address common.Add
|
||||||
|
|
||||||
details := NewMultiTxDetails()
|
details := NewMultiTxDetails()
|
||||||
details.FromAddress = address
|
details.FromAddress = address
|
||||||
mtxs, err := tm.storage.ReadMultiTransactionsByDetails(details)
|
mtxs, err := tm.storage.ReadMultiTransactions(details)
|
||||||
|
|
||||||
ids := make([]wallet_common.MultiTransactionIDType, 0)
|
ids := make([]wallet_common.MultiTransactionIDType, 0)
|
||||||
for _, mtx := range mtxs {
|
for _, mtx := range mtxs {
|
||||||
|
|
|
@ -9,20 +9,38 @@ import (
|
||||||
wallet_common "github.com/status-im/status-go/services/wallet/common"
|
wallet_common "github.com/status-im/status-go/services/wallet/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DO NOT CREATE IT MANUALLY! Use NewMultiTxDetails() instead
|
// Since we already use MultitransactionIDType in DB, and its default value is 0 (Send)
|
||||||
|
// this type is used to with default value 0 to represent invalid type to avoid bugs
|
||||||
|
// when devs forget to call NewMultiTxDetails()
|
||||||
|
type MultiTransactionDBType MultiTransactionType
|
||||||
|
|
||||||
|
const (
|
||||||
|
MultiTransactionDBTypeInvalid = 0
|
||||||
|
MultiTransactionDBSend = iota
|
||||||
|
MultiTransactionDBSwap
|
||||||
|
MultiTransactionDBBridge
|
||||||
|
)
|
||||||
|
|
||||||
|
func mtDBTypeToMTType(mtDBType MultiTransactionDBType) MultiTransactionType {
|
||||||
|
if mtDBType == MultiTransactionDBTypeInvalid {
|
||||||
|
return MultiTransactionTypeInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
return MultiTransactionType(mtDBType - 1)
|
||||||
|
}
|
||||||
|
|
||||||
type MultiTxDetails struct {
|
type MultiTxDetails struct {
|
||||||
|
IDs []wallet_common.MultiTransactionIDType
|
||||||
AnyAddress common.Address
|
AnyAddress common.Address
|
||||||
FromAddress common.Address
|
FromAddress common.Address
|
||||||
ToAddress common.Address
|
ToAddress common.Address
|
||||||
ToChainID uint64
|
ToChainID uint64
|
||||||
CrossTxID string
|
CrossTxID string
|
||||||
Type MultiTransactionType
|
Type MultiTransactionDBType
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMultiTxDetails() *MultiTxDetails {
|
func NewMultiTxDetails() *MultiTxDetails {
|
||||||
details := &MultiTxDetails{}
|
return &MultiTxDetails{}
|
||||||
details.Type = MultiTransactionTypeInvalid
|
|
||||||
return details
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type MultiTransactionDB struct {
|
type MultiTransactionDB struct {
|
||||||
|
@ -65,34 +83,7 @@ func (mtDB *MultiTransactionDB) CreateMultiTransaction(multiTransaction *MultiTr
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mtDB *MultiTransactionDB) ReadMultiTransactions(ids []wallet_common.MultiTransactionIDType) ([]*MultiTransaction, error) {
|
func (mtDB *MultiTransactionDB) ReadMultiTransactions(details *MultiTxDetails) ([]*MultiTransaction, error) {
|
||||||
placeholders := make([]string, len(ids))
|
|
||||||
args := make([]interface{}, len(ids))
|
|
||||||
for i, v := range ids {
|
|
||||||
placeholders[i] = "?"
|
|
||||||
args[i] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt, err := mtDB.db.Prepare(fmt.Sprintf(`SELECT %s
|
|
||||||
FROM multi_transactions
|
|
||||||
WHERE id in (%s)`,
|
|
||||||
selectMultiTransactionColumns,
|
|
||||||
strings.Join(placeholders, ",")))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer stmt.Close()
|
|
||||||
|
|
||||||
rows, err := stmt.Query(args...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
return rowsToMultiTransactions(rows)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mtDB *MultiTransactionDB) ReadMultiTransactionsByDetails(details *MultiTxDetails) ([]*MultiTransaction, error) {
|
|
||||||
if details == nil {
|
if details == nil {
|
||||||
return nil, fmt.Errorf("details is nil")
|
return nil, fmt.Errorf("details is nil")
|
||||||
}
|
}
|
||||||
|
@ -101,6 +92,14 @@ func (mtDB *MultiTransactionDB) ReadMultiTransactionsByDetails(details *MultiTxD
|
||||||
|
|
||||||
args := []interface{}{}
|
args := []interface{}{}
|
||||||
|
|
||||||
|
if len(details.IDs) > 0 {
|
||||||
|
placeholders := make([]string, len(details.IDs))
|
||||||
|
for i, v := range details.IDs {
|
||||||
|
placeholders[i] = "?"
|
||||||
|
args = append(args, v)
|
||||||
|
}
|
||||||
|
whereClause += fmt.Sprintf("id in (%s) AND ", strings.Join(placeholders, ","))
|
||||||
|
}
|
||||||
if (details.AnyAddress != common.Address{}) {
|
if (details.AnyAddress != common.Address{}) {
|
||||||
whereClause += "(from_address=? OR to_address=?) AND "
|
whereClause += "(from_address=? OR to_address=?) AND "
|
||||||
args = append(args, details.AnyAddress, details.AnyAddress)
|
args = append(args, details.AnyAddress, details.AnyAddress)
|
||||||
|
@ -121,9 +120,9 @@ func (mtDB *MultiTransactionDB) ReadMultiTransactionsByDetails(details *MultiTxD
|
||||||
whereClause += "cross_tx_id=? AND "
|
whereClause += "cross_tx_id=? AND "
|
||||||
args = append(args, details.CrossTxID)
|
args = append(args, details.CrossTxID)
|
||||||
}
|
}
|
||||||
if details.Type != MultiTransactionTypeInvalid {
|
if details.Type != MultiTransactionDBTypeInvalid {
|
||||||
whereClause += "type=? AND "
|
whereClause += "type=? AND "
|
||||||
args = append(args, details.Type)
|
args = append(args, mtDBTypeToMTType(details.Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt, err := mtDB.db.Prepare(fmt.Sprintf(`SELECT %s
|
stmt, err := mtDB.db.Prepare(fmt.Sprintf(`SELECT %s
|
||||||
|
|
|
@ -32,7 +32,9 @@ func TestCreateMultiTransaction(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Add assertions here to verify the result of the CreateMultiTransaction method
|
// Add assertions here to verify the result of the CreateMultiTransaction method
|
||||||
mtx, err := mtDB.ReadMultiTransactions([]wallet_common.MultiTransactionIDType{multiTransaction.ID})
|
details := NewMultiTxDetails()
|
||||||
|
details.IDs = []wallet_common.MultiTransactionIDType{multiTransaction.ID}
|
||||||
|
mtx, err := mtDB.ReadMultiTransactions(details)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, mtx, 1)
|
require.Len(t, mtx, 1)
|
||||||
require.True(t, areMultiTransactionsEqual(&multiTransaction, mtx[0]))
|
require.True(t, areMultiTransactionsEqual(&multiTransaction, mtx[0]))
|
||||||
|
@ -50,6 +52,9 @@ func TestReadMultiTransactions(t *testing.T) {
|
||||||
tr3 := generateTestTransfer(3)
|
tr3 := generateTestTransfer(3)
|
||||||
mt3 := GenerateTestSwapMultiTransaction(tr3, "SNT", 100)
|
mt3 := GenerateTestSwapMultiTransaction(tr3, "SNT", 100)
|
||||||
|
|
||||||
|
require.NotEqual(t, mt1.ID, mt2.ID)
|
||||||
|
require.NotEqual(t, mt1.ID, mt3.ID)
|
||||||
|
|
||||||
err := mtDB.CreateMultiTransaction(&mt1)
|
err := mtDB.CreateMultiTransaction(&mt1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = mtDB.CreateMultiTransaction(&mt2)
|
err = mtDB.CreateMultiTransaction(&mt2)
|
||||||
|
@ -58,8 +63,9 @@ func TestReadMultiTransactions(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Read multi transactions
|
// Read multi transactions
|
||||||
ids := []wallet_common.MultiTransactionIDType{mt1.ID, mt2.ID, mt3.ID}
|
details := NewMultiTxDetails()
|
||||||
mtx, err := mtDB.ReadMultiTransactions(ids)
|
details.IDs = []wallet_common.MultiTransactionIDType{mt1.ID, mt2.ID, mt3.ID}
|
||||||
|
mtx, err := mtDB.ReadMultiTransactions(details)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, mtx, 3)
|
require.Len(t, mtx, 3)
|
||||||
require.True(t, areMultiTransactionsEqual(&mt1, mtx[0]))
|
require.True(t, areMultiTransactionsEqual(&mt1, mtx[0]))
|
||||||
|
@ -96,7 +102,9 @@ func TestUpdateMultiTransaction(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Read the updated multi transaction
|
// Read the updated multi transaction
|
||||||
mtx, err := mtDB.ReadMultiTransactions([]wallet_common.MultiTransactionIDType{multiTransaction.ID})
|
details := NewMultiTxDetails()
|
||||||
|
details.IDs = []wallet_common.MultiTransactionIDType{multiTransaction.ID}
|
||||||
|
mtx, err := mtDB.ReadMultiTransactions(details)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, mtx, 1)
|
require.Len(t, mtx, 1)
|
||||||
require.True(t, areMultiTransactionsEqual(&multiTransaction, mtx[0]))
|
require.True(t, areMultiTransactionsEqual(&multiTransaction, mtx[0]))
|
||||||
|
@ -118,7 +126,8 @@ func TestDeleteMultiTransaction(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Read the deleted multi transaction
|
// Read the deleted multi transaction
|
||||||
mtx, err := mtDB.ReadMultiTransactions([]wallet_common.MultiTransactionIDType{multiTransaction.ID})
|
mtx, err := mtDB.ReadMultiTransactions(&MultiTxDetails{
|
||||||
|
IDs: []wallet_common.MultiTransactionIDType{multiTransaction.ID}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, mtx, 0)
|
require.Len(t, mtx, 0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,11 @@ type TestTransfer struct {
|
||||||
Token *token.Token
|
Token *token.Token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TestCollectibleTransfer struct {
|
||||||
|
TestTransfer
|
||||||
|
TestCollectible
|
||||||
|
}
|
||||||
|
|
||||||
func SeedToToken(seed int) *token.Token {
|
func SeedToToken(seed int) *token.Token {
|
||||||
tokenIndex := seed % len(TestTokens)
|
tokenIndex := seed % len(TestTokens)
|
||||||
return TestTokens[tokenIndex]
|
return TestTokens[tokenIndex]
|
||||||
|
@ -79,6 +84,28 @@ func generateTestTransfer(seed int) TestTransfer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Will be used in tests to generate a collectible transfer
|
||||||
|
// nolint:unused
|
||||||
|
func generateTestCollectibleTransfer(seed int) TestCollectibleTransfer {
|
||||||
|
collectibleIndex := seed % len(TestCollectibles)
|
||||||
|
collectible := TestCollectibles[collectibleIndex]
|
||||||
|
tr := TestCollectibleTransfer{
|
||||||
|
TestTransfer: TestTransfer{
|
||||||
|
TestTransaction: generateTestTransaction(seed),
|
||||||
|
To: eth_common.HexToAddress(fmt.Sprintf("0x3%d", seed)),
|
||||||
|
Value: int64(seed),
|
||||||
|
Token: &token.Token{
|
||||||
|
Address: collectible.TokenAddress,
|
||||||
|
Name: "Collectible",
|
||||||
|
ChainID: uint64(collectible.ChainID),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TestCollectible: collectible,
|
||||||
|
}
|
||||||
|
tr.TestTransaction.ChainID = collectible.ChainID
|
||||||
|
return tr
|
||||||
|
}
|
||||||
|
|
||||||
func GenerateTestSendMultiTransaction(tr TestTransfer) MultiTransaction {
|
func GenerateTestSendMultiTransaction(tr TestTransfer) MultiTransaction {
|
||||||
return MultiTransaction{
|
return MultiTransaction{
|
||||||
ID: multiTransactionIDGenerator(),
|
ID: multiTransactionIDGenerator(),
|
||||||
|
@ -422,21 +449,13 @@ func (s *InMemMultiTransactionStorage) DeleteMultiTransaction(id common.MultiTra
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InMemMultiTransactionStorage) ReadMultiTransactions(ids []common.MultiTransactionIDType) ([]*MultiTransaction, error) {
|
func (s *InMemMultiTransactionStorage) ReadMultiTransactions(details *MultiTxDetails) ([]*MultiTransaction, error) {
|
||||||
var multiTxs []*MultiTransaction
|
|
||||||
for _, id := range ids {
|
|
||||||
multiTx, ok := s.storage[id]
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
multiTxs = append(multiTxs, multiTx)
|
|
||||||
}
|
|
||||||
return multiTxs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InMemMultiTransactionStorage) ReadMultiTransactionsByDetails(details *MultiTxDetails) ([]*MultiTransaction, error) {
|
|
||||||
var multiTxs []*MultiTransaction
|
var multiTxs []*MultiTransaction
|
||||||
for _, multiTx := range s.storage {
|
for _, multiTx := range s.storage {
|
||||||
|
if len(details.IDs) > 0 && !testutils.SliceContains(details.IDs, multiTx.ID) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if (details.AnyAddress != eth_common.Address{}) &&
|
if (details.AnyAddress != eth_common.Address{}) &&
|
||||||
(multiTx.FromAddress != details.AnyAddress && multiTx.ToAddress != details.AnyAddress) {
|
(multiTx.FromAddress != details.AnyAddress && multiTx.ToAddress != details.AnyAddress) {
|
||||||
continue
|
continue
|
||||||
|
@ -454,7 +473,7 @@ func (s *InMemMultiTransactionStorage) ReadMultiTransactionsByDetails(details *M
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if details.Type != MultiTransactionTypeInvalid && multiTx.Type != details.Type {
|
if details.Type != MultiTransactionDBTypeInvalid && multiTx.Type != mtDBTypeToMTType(details.Type) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ type TransactionDescription struct {
|
||||||
type TransactionManager struct {
|
type TransactionManager struct {
|
||||||
storage MultiTransactionStorage
|
storage MultiTransactionStorage
|
||||||
gethManager *account.GethManager
|
gethManager *account.GethManager
|
||||||
transactor *transactions.Transactor
|
transactor transactions.TransactorIface
|
||||||
config *params.NodeConfig
|
config *params.NodeConfig
|
||||||
accountsDB *accounts.Database
|
accountsDB *accounts.Database
|
||||||
pendingTracker *transactions.PendingTxTracker
|
pendingTracker *transactions.PendingTxTracker
|
||||||
|
@ -49,8 +49,7 @@ type TransactionManager struct {
|
||||||
|
|
||||||
type MultiTransactionStorage interface {
|
type MultiTransactionStorage interface {
|
||||||
CreateMultiTransaction(tx *MultiTransaction) error
|
CreateMultiTransaction(tx *MultiTransaction) error
|
||||||
ReadMultiTransactions(ids []wallet_common.MultiTransactionIDType) ([]*MultiTransaction, error)
|
ReadMultiTransactions(details *MultiTxDetails) ([]*MultiTransaction, error)
|
||||||
ReadMultiTransactionsByDetails(details *MultiTxDetails) ([]*MultiTransaction, error)
|
|
||||||
UpdateMultiTransaction(tx *MultiTransaction) error
|
UpdateMultiTransaction(tx *MultiTransaction) error
|
||||||
DeleteMultiTransaction(id wallet_common.MultiTransactionIDType) error
|
DeleteMultiTransaction(id wallet_common.MultiTransactionIDType) error
|
||||||
}
|
}
|
||||||
|
@ -58,7 +57,7 @@ type MultiTransactionStorage interface {
|
||||||
func NewTransactionManager(
|
func NewTransactionManager(
|
||||||
storage MultiTransactionStorage,
|
storage MultiTransactionStorage,
|
||||||
gethManager *account.GethManager,
|
gethManager *account.GethManager,
|
||||||
transactor *transactions.Transactor,
|
transactor transactions.TransactorIface,
|
||||||
config *params.NodeConfig,
|
config *params.NodeConfig,
|
||||||
accountsDB *accounts.Database,
|
accountsDB *accounts.Database,
|
||||||
pendingTxManager *transactions.PendingTxTracker,
|
pendingTxManager *transactions.PendingTxTracker,
|
||||||
|
|
|
@ -23,7 +23,7 @@ func (tm *TransactionManager) UpdateMultiTransaction(multiTransaction *MultiTran
|
||||||
return tm.storage.UpdateMultiTransaction(multiTransaction)
|
return tm.storage.UpdateMultiTransaction(multiTransaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tm *TransactionManager) CreateMultiTransactionFromCommand(ctx context.Context, command *MultiTransactionCommand,
|
func (tm *TransactionManager) CreateMultiTransactionFromCommand(command *MultiTransactionCommand,
|
||||||
data []*bridge.TransactionBridge) (*MultiTransaction, error) {
|
data []*bridge.TransactionBridge) (*MultiTransaction, error) {
|
||||||
|
|
||||||
multiTransaction := multiTransactionFromCommand(command)
|
multiTransaction := multiTransactionFromCommand(command)
|
||||||
|
@ -107,7 +107,7 @@ func (tm *TransactionManager) ProceedWithTransactionsSignatures(ctx context.Cont
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tm *TransactionManager) GetMultiTransactions(ctx context.Context, ids []wallet_common.MultiTransactionIDType) ([]*MultiTransaction, error) {
|
func (tm *TransactionManager) GetMultiTransactions(ctx context.Context, ids []wallet_common.MultiTransactionIDType) ([]*MultiTransaction, error) {
|
||||||
return tm.storage.ReadMultiTransactions(ids)
|
return tm.storage.ReadMultiTransactions(&MultiTxDetails{IDs: ids})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tm *TransactionManager) GetBridgeOriginMultiTransaction(ctx context.Context, toChainID uint64, crossTxID string) (*MultiTransaction, error) {
|
func (tm *TransactionManager) GetBridgeOriginMultiTransaction(ctx context.Context, toChainID uint64, crossTxID string) (*MultiTransaction, error) {
|
||||||
|
@ -115,7 +115,7 @@ func (tm *TransactionManager) GetBridgeOriginMultiTransaction(ctx context.Contex
|
||||||
details.ToChainID = toChainID
|
details.ToChainID = toChainID
|
||||||
details.CrossTxID = crossTxID
|
details.CrossTxID = crossTxID
|
||||||
|
|
||||||
multiTxs, err := tm.storage.ReadMultiTransactionsByDetails(details)
|
multiTxs, err := tm.storage.ReadMultiTransactions(details)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ func (tm *TransactionManager) GetBridgeDestinationMultiTransaction(ctx context.C
|
||||||
details.ToChainID = toChainID
|
details.ToChainID = toChainID
|
||||||
details.CrossTxID = crossTxID
|
details.CrossTxID = crossTxID
|
||||||
|
|
||||||
multiTxs, err := tm.storage.ReadMultiTransactionsByDetails(details)
|
multiTxs, err := tm.storage.ReadMultiTransactions(details)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
package transfer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/status-im/status-go/account"
|
||||||
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
|
"github.com/status-im/status-go/rpc"
|
||||||
|
"github.com/status-im/status-go/services/wallet/bridge"
|
||||||
|
"github.com/status-im/status-go/services/wallet/bridge/mock_bridge"
|
||||||
|
"github.com/status-im/status-go/transactions"
|
||||||
|
"github.com/status-im/status-go/transactions/mock_transactor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func deepCopy(tx *transactions.SendTxArgs) *transactions.SendTxArgs {
|
||||||
|
return &transactions.SendTxArgs{
|
||||||
|
From: tx.From,
|
||||||
|
To: tx.To,
|
||||||
|
Value: tx.Value,
|
||||||
|
Data: tx.Data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deepCopyTransactionBridgeWithTransferTx(tx *bridge.TransactionBridge) *bridge.TransactionBridge {
|
||||||
|
return &bridge.TransactionBridge{
|
||||||
|
BridgeName: tx.BridgeName,
|
||||||
|
ChainID: tx.ChainID,
|
||||||
|
TransferTx: deepCopy(tx.TransferTx),
|
||||||
|
HopTx: tx.HopTx,
|
||||||
|
CbridgeTx: tx.CbridgeTx,
|
||||||
|
ERC721TransferTx: tx.ERC721TransferTx,
|
||||||
|
ERC1155TransferTx: tx.ERC1155TransferTx,
|
||||||
|
SwapTx: tx.SwapTx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupTransactionManager(t *testing.T) (*TransactionManager, *mock_transactor.MockTransactorIface, *gomock.Controller) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
// Create a mock transactor
|
||||||
|
transactor := mock_transactor.NewMockTransactorIface(ctrl)
|
||||||
|
// Create a new instance of the TransactionManager
|
||||||
|
tm := NewTransactionManager(NewInMemMultiTransactionStorage(), nil, transactor, nil, nil, nil, nil)
|
||||||
|
|
||||||
|
return tm, transactor, ctrl
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupAccount(_ *testing.T, address common.Address) *account.SelectedExtKey {
|
||||||
|
// Dummy account
|
||||||
|
return &account.SelectedExtKey{
|
||||||
|
Address: types.Address(address),
|
||||||
|
AccountKey: &types.Key{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupTransactionData(_ *testing.T, transactor transactions.TransactorIface) (*MultiTransaction, []*bridge.TransactionBridge, map[string]bridge.Bridge, []*bridge.TransactionBridge) {
|
||||||
|
SetMultiTransactionIDGenerator(StaticIDCounter())
|
||||||
|
|
||||||
|
// Create mock data for the test
|
||||||
|
ethTransfer := generateTestTransfer(0)
|
||||||
|
multiTransaction := GenerateTestSendMultiTransaction(ethTransfer)
|
||||||
|
|
||||||
|
// Initialize the bridges
|
||||||
|
var rpcClient *rpc.Client = nil
|
||||||
|
bridges := make(map[string]bridge.Bridge)
|
||||||
|
transferBridge := bridge.NewTransferBridge(rpcClient, transactor)
|
||||||
|
bridges[transferBridge.Name()] = transferBridge
|
||||||
|
|
||||||
|
data := []*bridge.TransactionBridge{
|
||||||
|
{
|
||||||
|
ChainID: 1,
|
||||||
|
BridgeName: transferBridge.Name(),
|
||||||
|
TransferTx: &transactions.SendTxArgs{
|
||||||
|
From: types.Address(ethTransfer.From),
|
||||||
|
To: (*types.Address)(ðTransfer.To),
|
||||||
|
Value: (*hexutil.Big)(big.NewInt(ethTransfer.Value / 3)),
|
||||||
|
Data: types.HexBytes("0x0"),
|
||||||
|
// Symbol: multiTransaction.FromAsset, // This will be set by transaction manager
|
||||||
|
// MultiTransactionID: multiTransaction.ID, // This will be set by transaction manager
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ChainID: 420,
|
||||||
|
BridgeName: transferBridge.Name(),
|
||||||
|
TransferTx: &transactions.SendTxArgs{
|
||||||
|
From: types.Address(ethTransfer.From),
|
||||||
|
To: (*types.Address)(ðTransfer.To),
|
||||||
|
Value: (*hexutil.Big)(big.NewInt(ethTransfer.Value * 2 / 3)),
|
||||||
|
Data: types.HexBytes("0x0"),
|
||||||
|
// Symbol: multiTransaction.FromAsset, // This will be set by transaction manager
|
||||||
|
// MultiTransactionID: multiTransaction.ID, // This will be set by transaction manager
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedData := make([]*bridge.TransactionBridge, 0)
|
||||||
|
for _, tx := range data {
|
||||||
|
txCopy := deepCopyTransactionBridgeWithTransferTx(tx)
|
||||||
|
updateDataFromMultiTx([]*bridge.TransactionBridge{txCopy}, &multiTransaction)
|
||||||
|
expectedData = append(expectedData, txCopy)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &multiTransaction, data, bridges, expectedData
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSendTransactionsETHSuccess(t *testing.T) {
|
||||||
|
tm, transactor, _ := setupTransactionManager(t)
|
||||||
|
account := setupAccount(t, common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678"))
|
||||||
|
multiTransaction, data, bridges, expectedData := setupTransactionData(t, transactor)
|
||||||
|
|
||||||
|
// Verify that the SendTransactionWithChainID method is called for each transaction with proper arguments
|
||||||
|
// Return values are not checked, because they must be checked in Transactor tests
|
||||||
|
for _, tx := range expectedData {
|
||||||
|
transactor.EXPECT().SendTransactionWithChainID(tx.ChainID, *(tx.TransferTx), account).Return(types.Hash{}, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the SendTransactions method
|
||||||
|
_, err := tm.SendTransactions(context.Background(), multiTransaction, data, bridges, account)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSendTransactionsETHFailOnBridge(t *testing.T) {
|
||||||
|
tm, transactor, ctrl := setupTransactionManager(t)
|
||||||
|
account := setupAccount(t, common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678"))
|
||||||
|
multiTransaction, data, _, _ := setupTransactionData(t, transactor)
|
||||||
|
|
||||||
|
// Initialize the bridges
|
||||||
|
bridges := make(map[string]bridge.Bridge)
|
||||||
|
transferBridge := mock_bridge.NewMockBridge(ctrl)
|
||||||
|
|
||||||
|
// Set bridge name for the mock to the one used in data
|
||||||
|
transferBridge.EXPECT().Name().Return(data[0].BridgeName).AnyTimes()
|
||||||
|
bridges[transferBridge.Name()] = transferBridge
|
||||||
|
|
||||||
|
expectedErr := transactions.ErrInvalidTxSender // Any error to verify
|
||||||
|
// In case of bridge error, verify that the error is returned
|
||||||
|
transferBridge.EXPECT().Send(gomock.Any(), gomock.Any()).Return(types.Hash{}, transactions.ErrInvalidTxSender)
|
||||||
|
|
||||||
|
// Call the SendTransactions method
|
||||||
|
_, err := tm.SendTransactions(context.Background(), multiTransaction, data, bridges, account)
|
||||||
|
require.Error(t, expectedErr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSendTransactionsETHFailOnTransactor(t *testing.T) {
|
||||||
|
tm, transactor, _ := setupTransactionManager(t)
|
||||||
|
account := setupAccount(t, common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678"))
|
||||||
|
multiTransaction, data, bridges, expectedData := setupTransactionData(t, transactor)
|
||||||
|
|
||||||
|
// Verify that the SendTransactionWithChainID method is called for each transaction with proper arguments
|
||||||
|
// Return values are not checked, because they must be checked in Transactor tests. Only error propagation matters here
|
||||||
|
expectedErr := transactions.ErrInvalidTxSender // Any error to verify
|
||||||
|
transactor.EXPECT().SendTransactionWithChainID(expectedData[0].ChainID, *(expectedData[0].TransferTx), account).Return(types.Hash{}, nil)
|
||||||
|
transactor.EXPECT().SendTransactionWithChainID(expectedData[1].ChainID, *(expectedData[1].TransferTx), account).Return(types.Hash{}, expectedErr)
|
||||||
|
|
||||||
|
// Call the SendTransactions method
|
||||||
|
_, err := tm.SendTransactions(context.Background(), multiTransaction, data, bridges, account)
|
||||||
|
require.Error(t, expectedErr, err)
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
# To generate mocks, from status-go root directory:
|
||||||
|
mockgen -source=transactions/transactor.go -destination=transactions/mock_transactor/transactor.go -package=mock_transactor
|
|
@ -0,0 +1,177 @@
|
||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: transactions/transactor.go
|
||||||
|
|
||||||
|
// Package mock_transactor is a generated GoMock package.
|
||||||
|
package mock_transactor
|
||||||
|
|
||||||
|
import (
|
||||||
|
big "math/big"
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
common "github.com/ethereum/go-ethereum/common"
|
||||||
|
types "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
account "github.com/status-im/status-go/account"
|
||||||
|
types0 "github.com/status-im/status-go/eth-node/types"
|
||||||
|
params "github.com/status-im/status-go/params"
|
||||||
|
rpc "github.com/status-im/status-go/rpc"
|
||||||
|
common0 "github.com/status-im/status-go/services/wallet/common"
|
||||||
|
transactions "github.com/status-im/status-go/transactions"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockTransactorIface is a mock of TransactorIface interface.
|
||||||
|
type MockTransactorIface struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockTransactorIfaceMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockTransactorIfaceMockRecorder is the mock recorder for MockTransactorIface.
|
||||||
|
type MockTransactorIfaceMockRecorder struct {
|
||||||
|
mock *MockTransactorIface
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockTransactorIface creates a new mock instance.
|
||||||
|
func NewMockTransactorIface(ctrl *gomock.Controller) *MockTransactorIface {
|
||||||
|
mock := &MockTransactorIface{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockTransactorIfaceMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockTransactorIface) EXPECT() *MockTransactorIfaceMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSignatureToTransaction mocks base method.
|
||||||
|
func (m *MockTransactorIface) AddSignatureToTransaction(chainID uint64, tx *types.Transaction, sig []byte) (*types.Transaction, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "AddSignatureToTransaction", chainID, tx, sig)
|
||||||
|
ret0, _ := ret[0].(*types.Transaction)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSignatureToTransaction indicates an expected call of AddSignatureToTransaction.
|
||||||
|
func (mr *MockTransactorIfaceMockRecorder) AddSignatureToTransaction(chainID, tx, sig interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSignatureToTransaction", reflect.TypeOf((*MockTransactorIface)(nil).AddSignatureToTransaction), chainID, tx, sig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildTransactionWithSignature mocks base method.
|
||||||
|
func (m *MockTransactorIface) BuildTransactionWithSignature(chainID uint64, args transactions.SendTxArgs, sig []byte) (*types.Transaction, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "BuildTransactionWithSignature", chainID, args, sig)
|
||||||
|
ret0, _ := ret[0].(*types.Transaction)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildTransactionWithSignature indicates an expected call of BuildTransactionWithSignature.
|
||||||
|
func (mr *MockTransactorIfaceMockRecorder) BuildTransactionWithSignature(chainID, args, sig interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BuildTransactionWithSignature", reflect.TypeOf((*MockTransactorIface)(nil).BuildTransactionWithSignature), chainID, args, sig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EstimateGas mocks base method.
|
||||||
|
func (m *MockTransactorIface) EstimateGas(network *params.Network, from, to common.Address, value *big.Int, input []byte) (uint64, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "EstimateGas", network, from, to, value, input)
|
||||||
|
ret0, _ := ret[0].(uint64)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// EstimateGas indicates an expected call of EstimateGas.
|
||||||
|
func (mr *MockTransactorIfaceMockRecorder) EstimateGas(network, from, to, value, input interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EstimateGas", reflect.TypeOf((*MockTransactorIface)(nil).EstimateGas), network, from, to, value, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextNonce mocks base method.
|
||||||
|
func (m *MockTransactorIface) NextNonce(rpcClient *rpc.Client, chainID uint64, from types0.Address) (uint64, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "NextNonce", rpcClient, chainID, from)
|
||||||
|
ret0, _ := ret[0].(uint64)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextNonce indicates an expected call of NextNonce.
|
||||||
|
func (mr *MockTransactorIfaceMockRecorder) NextNonce(rpcClient, chainID, from interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NextNonce", reflect.TypeOf((*MockTransactorIface)(nil).NextNonce), rpcClient, chainID, from)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendRawTransaction mocks base method.
|
||||||
|
func (m *MockTransactorIface) SendRawTransaction(chainID uint64, rawTx string) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "SendRawTransaction", chainID, rawTx)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendRawTransaction indicates an expected call of SendRawTransaction.
|
||||||
|
func (mr *MockTransactorIfaceMockRecorder) SendRawTransaction(chainID, rawTx interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendRawTransaction", reflect.TypeOf((*MockTransactorIface)(nil).SendRawTransaction), chainID, rawTx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendTransaction mocks base method.
|
||||||
|
func (m *MockTransactorIface) SendTransaction(sendArgs transactions.SendTxArgs, verifiedAccount *account.SelectedExtKey) (types0.Hash, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "SendTransaction", sendArgs, verifiedAccount)
|
||||||
|
ret0, _ := ret[0].(types0.Hash)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendTransaction indicates an expected call of SendTransaction.
|
||||||
|
func (mr *MockTransactorIfaceMockRecorder) SendTransaction(sendArgs, verifiedAccount interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendTransaction", reflect.TypeOf((*MockTransactorIface)(nil).SendTransaction), sendArgs, verifiedAccount)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendTransactionWithChainID mocks base method.
|
||||||
|
func (m *MockTransactorIface) SendTransactionWithChainID(chainID uint64, sendArgs transactions.SendTxArgs, verifiedAccount *account.SelectedExtKey) (types0.Hash, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "SendTransactionWithChainID", chainID, sendArgs, verifiedAccount)
|
||||||
|
ret0, _ := ret[0].(types0.Hash)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendTransactionWithChainID indicates an expected call of SendTransactionWithChainID.
|
||||||
|
func (mr *MockTransactorIfaceMockRecorder) SendTransactionWithChainID(chainID, sendArgs, verifiedAccount interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendTransactionWithChainID", reflect.TypeOf((*MockTransactorIface)(nil).SendTransactionWithChainID), chainID, sendArgs, verifiedAccount)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendTransactionWithSignature mocks base method.
|
||||||
|
func (m *MockTransactorIface) SendTransactionWithSignature(from common.Address, symbol string, multiTransactionID common0.MultiTransactionIDType, tx *types.Transaction) (types0.Hash, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "SendTransactionWithSignature", from, symbol, multiTransactionID, tx)
|
||||||
|
ret0, _ := ret[0].(types0.Hash)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendTransactionWithSignature indicates an expected call of SendTransactionWithSignature.
|
||||||
|
func (mr *MockTransactorIfaceMockRecorder) SendTransactionWithSignature(from, symbol, multiTransactionID, tx interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendTransactionWithSignature", reflect.TypeOf((*MockTransactorIface)(nil).SendTransactionWithSignature), from, symbol, multiTransactionID, tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateAndBuildTransaction mocks base method.
|
||||||
|
func (m *MockTransactorIface) ValidateAndBuildTransaction(chainID uint64, sendArgs transactions.SendTxArgs) (*types.Transaction, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ValidateAndBuildTransaction", chainID, sendArgs)
|
||||||
|
ret0, _ := ret[0].(*types.Transaction)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateAndBuildTransaction indicates an expected call of ValidateAndBuildTransaction.
|
||||||
|
func (mr *MockTransactorIfaceMockRecorder) ValidateAndBuildTransaction(chainID, sendArgs interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateAndBuildTransaction", reflect.TypeOf((*MockTransactorIface)(nil).ValidateAndBuildTransaction), chainID, sendArgs)
|
||||||
|
}
|
|
@ -44,6 +44,19 @@ func (e *ErrBadNonce) Error() string {
|
||||||
return fmt.Sprintf("bad nonce. expected %d, got %d", e.expectedNonce, e.nonce)
|
return fmt.Sprintf("bad nonce. expected %d, got %d", e.expectedNonce, e.nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transactor is an interface that defines the methods for validating and sending transactions.
|
||||||
|
type TransactorIface interface {
|
||||||
|
NextNonce(rpcClient *rpc.Client, chainID uint64, from types.Address) (uint64, error)
|
||||||
|
EstimateGas(network *params.Network, from common.Address, to common.Address, value *big.Int, input []byte) (uint64, error)
|
||||||
|
SendTransaction(sendArgs SendTxArgs, verifiedAccount *account.SelectedExtKey) (hash types.Hash, err error)
|
||||||
|
SendTransactionWithChainID(chainID uint64, sendArgs SendTxArgs, verifiedAccount *account.SelectedExtKey) (hash types.Hash, err error)
|
||||||
|
ValidateAndBuildTransaction(chainID uint64, sendArgs SendTxArgs) (tx *gethtypes.Transaction, err error)
|
||||||
|
AddSignatureToTransaction(chainID uint64, tx *gethtypes.Transaction, sig []byte) (*gethtypes.Transaction, error)
|
||||||
|
SendRawTransaction(chainID uint64, rawTx string) error
|
||||||
|
BuildTransactionWithSignature(chainID uint64, args SendTxArgs, sig []byte) (*gethtypes.Transaction, error)
|
||||||
|
SendTransactionWithSignature(from common.Address, symbol string, multiTransactionID wallet_common.MultiTransactionIDType, tx *gethtypes.Transaction) (hash types.Hash, err error)
|
||||||
|
}
|
||||||
|
|
||||||
// Transactor validates, signs transactions.
|
// Transactor validates, signs transactions.
|
||||||
// It uses upstream to propagate transactions to the Ethereum network.
|
// It uses upstream to propagate transactions to the Ethereum network.
|
||||||
type Transactor struct {
|
type Transactor struct {
|
||||||
|
@ -218,29 +231,9 @@ func (t *Transactor) SendTransactionWithSignature(from common.Address, symbol st
|
||||||
return t.sendTransaction(rpcWrapper, from, symbol, multiTransactionID, tx)
|
return t.sendTransaction(rpcWrapper, from, symbol, multiTransactionID, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transactor) AddSignatureToTransactionAndSend(chainID uint64, from common.Address, symbol string,
|
// BuildTransactionAndSendWithSignature receive a transaction and a signature, serialize them together
|
||||||
multiTransactionID wallet_common.MultiTransactionIDType, tx *gethtypes.Transaction, sig []byte) (hash types.Hash, err error) {
|
|
||||||
txWithSignature, err := t.AddSignatureToTransaction(chainID, tx, sig)
|
|
||||||
if err != nil {
|
|
||||||
return hash, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return t.SendTransactionWithSignature(from, symbol, multiTransactionID, txWithSignature)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildTransactionAndSendWithSignature receive a transaction and a signature, serialize them together and propage it to the network.
|
|
||||||
// It's different from eth_sendRawTransaction because it receives a signature and not a serialized transaction with signature.
|
// It's different from eth_sendRawTransaction because it receives a signature and not a serialized transaction with signature.
|
||||||
// Since the transactions is already signed, we assume it was validated and used the right nonce.
|
// Since the transactions is already signed, we assume it was validated and used the right nonce.
|
||||||
func (t *Transactor) BuildTransactionAndSendWithSignature(chainID uint64, args SendTxArgs, sig []byte) (hash types.Hash, err error) {
|
|
||||||
txWithSignature, err := t.BuildTransactionWithSignature(chainID, args, sig)
|
|
||||||
if err != nil {
|
|
||||||
return hash, err
|
|
||||||
}
|
|
||||||
|
|
||||||
hash, err = t.SendTransactionWithSignature(common.Address(args.From), args.Symbol, args.MultiTransactionID, txWithSignature)
|
|
||||||
return hash, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Transactor) BuildTransactionWithSignature(chainID uint64, args SendTxArgs, sig []byte) (*gethtypes.Transaction, error) {
|
func (t *Transactor) BuildTransactionWithSignature(chainID uint64, args SendTxArgs, sig []byte) (*gethtypes.Transaction, error) {
|
||||||
if !args.Valid() {
|
if !args.Valid() {
|
||||||
return nil, ErrInvalidSendTxArgs
|
return nil, ErrInvalidSendTxArgs
|
||||||
|
|
|
@ -313,11 +313,18 @@ func (s *TransactorSuite) TestSendTransactionWithSignature() {
|
||||||
Return(common.Hash{}, nil)
|
Return(common.Hash{}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = s.manager.BuildTransactionAndSendWithSignature(s.nodeConfig.NetworkID, args, sig)
|
tx, err = s.manager.BuildTransactionWithSignature(s.nodeConfig.NetworkID, args, sig)
|
||||||
if scenario.expectError {
|
if scenario.expectError {
|
||||||
s.Error(err)
|
s.Error(err)
|
||||||
} else {
|
} else {
|
||||||
s.NoError(err)
|
s.NoError(err)
|
||||||
|
|
||||||
|
_, err = s.manager.SendTransactionWithSignature(common.Address(args.From), args.Symbol, args.MultiTransactionID, tx)
|
||||||
|
if scenario.expectError {
|
||||||
|
s.Error(err)
|
||||||
|
} else {
|
||||||
|
s.NoError(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -325,7 +332,7 @@ func (s *TransactorSuite) TestSendTransactionWithSignature() {
|
||||||
|
|
||||||
func (s *TransactorSuite) TestSendTransactionWithSignature_InvalidSignature() {
|
func (s *TransactorSuite) TestSendTransactionWithSignature_InvalidSignature() {
|
||||||
args := SendTxArgs{}
|
args := SendTxArgs{}
|
||||||
_, err := s.manager.BuildTransactionAndSendWithSignature(1, args, []byte{})
|
_, err := s.manager.BuildTransactionWithSignature(1, args, []byte{})
|
||||||
s.Equal(ErrInvalidSignatureSize, err)
|
s.Equal(ErrInvalidSignatureSize, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue