2024-07-18 15:30:10 +00:00
|
|
|
package commands
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2024-09-19 18:24:28 +00:00
|
|
|
"errors"
|
|
|
|
"math/big"
|
2024-07-18 15:30:10 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
2024-07-18 15:30:10 +00:00
|
|
|
"github.com/status-im/status-go/eth-node/types"
|
2024-09-19 18:24:28 +00:00
|
|
|
mock_client "github.com/status-im/status-go/rpc/chain/mock/client"
|
2024-07-18 15:30:10 +00:00
|
|
|
"github.com/status-im/status-go/signal"
|
|
|
|
"github.com/status-im/status-go/transactions"
|
|
|
|
)
|
|
|
|
|
|
|
|
func prepareSendTransactionRequest(dApp signal.ConnectorDApp, from types.Address) (RPCRequest, error) {
|
|
|
|
sendArgs := transactions.SendTxArgs{
|
|
|
|
From: from,
|
|
|
|
To: &types.Address{0x02},
|
|
|
|
Value: &hexutil.Big{},
|
|
|
|
Data: types.HexBytes("0x0"),
|
|
|
|
}
|
|
|
|
|
|
|
|
sendArgsJSON, err := json.Marshal(sendArgs)
|
|
|
|
if err != nil {
|
|
|
|
return RPCRequest{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var sendArgsMap map[string]interface{}
|
|
|
|
err = json.Unmarshal(sendArgsJSON, &sendArgsMap)
|
|
|
|
if err != nil {
|
|
|
|
return RPCRequest{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
params := []interface{}{sendArgsMap}
|
|
|
|
|
|
|
|
return ConstructRPCRequest("eth_sendTransaction", params, &dApp)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestFailToSendTransactionWithoutPermittedDApp(t *testing.T) {
|
2024-09-19 18:24:28 +00:00
|
|
|
state, close := setupCommand(t, Method_EthSendTransaction)
|
|
|
|
t.Cleanup(close)
|
2024-07-18 15:30:10 +00:00
|
|
|
|
|
|
|
// Don't save dApp in the database
|
|
|
|
request, err := prepareSendTransactionRequest(testDAppData, types.Address{0x1})
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
_, err = state.cmd.Execute(state.ctx, request)
|
2024-07-18 15:30:10 +00:00
|
|
|
assert.Equal(t, ErrDAppIsNotPermittedByUser, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestFailToSendTransactionWithWrongAddress(t *testing.T) {
|
2024-09-19 18:24:28 +00:00
|
|
|
state, close := setupCommand(t, Method_EthSendTransaction)
|
|
|
|
t.Cleanup(close)
|
2024-07-18 15:30:10 +00:00
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
err := PersistDAppData(state.walletDb, testDAppData, types.Address{0x01}, uint64(0x1))
|
2024-07-18 15:30:10 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
request, err := prepareSendTransactionRequest(testDAppData, types.Address{0x02})
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
_, err = state.cmd.Execute(state.ctx, request)
|
2024-07-18 15:30:10 +00:00
|
|
|
assert.Equal(t, ErrParamsFromAddressIsNotShared, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSendTransactionWithSignalTimout(t *testing.T) {
|
2024-09-19 18:24:28 +00:00
|
|
|
state, close := setupCommand(t, Method_EthSendTransaction)
|
|
|
|
t.Cleanup(close)
|
2024-07-18 15:30:10 +00:00
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
accountAddress := types.Address{0x01}
|
|
|
|
err := PersistDAppData(state.walletDb, testDAppData, accountAddress, uint64(0x1))
|
2024-07-18 15:30:10 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
request, err := prepareSendTransactionRequest(testDAppData, accountAddress)
|
2024-07-18 15:30:10 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
backupWalletResponseMaxInterval := WalletResponseMaxInterval
|
|
|
|
WalletResponseMaxInterval = 1 * time.Millisecond
|
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
mockedChainClient := mock_client.NewMockClientInterface(state.mockCtrl)
|
|
|
|
state.rpcClient.EXPECT().EthClient(uint64(1)).Times(1).Return(mockedChainClient, nil)
|
|
|
|
mockedChainClient.EXPECT().SuggestGasPrice(state.ctx).Times(1).Return(big.NewInt(1), nil)
|
|
|
|
mockedChainClient.EXPECT().SuggestGasTipCap(state.ctx).Times(1).Return(big.NewInt(0), errors.New("EIP-1559 is not enabled"))
|
|
|
|
state.rpcClient.EXPECT().EthClient(uint64(1)).Times(1).Return(mockedChainClient, nil)
|
|
|
|
mockedChainClient.EXPECT().PendingNonceAt(state.ctx, common.Address(accountAddress)).Times(1).Return(uint64(10), nil)
|
|
|
|
|
|
|
|
_, err = state.cmd.Execute(state.ctx, request)
|
2024-07-18 15:30:10 +00:00
|
|
|
assert.Equal(t, ErrWalletResponseTimeout, err)
|
|
|
|
WalletResponseMaxInterval = backupWalletResponseMaxInterval
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSendTransactionWithSignalAccepted(t *testing.T) {
|
2024-09-19 18:24:28 +00:00
|
|
|
state, close := setupCommand(t, Method_EthSendTransaction)
|
|
|
|
t.Cleanup(close)
|
2024-07-18 15:30:10 +00:00
|
|
|
|
|
|
|
fakedTransactionHash := types.Hash{0x051}
|
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
accountAddress := types.Address{0x01}
|
|
|
|
err := PersistDAppData(state.walletDb, testDAppData, accountAddress, uint64(0x1))
|
2024-07-18 15:30:10 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
request, err := prepareSendTransactionRequest(testDAppData, accountAddress)
|
2024-07-18 15:30:10 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
signal.SetMobileSignalHandler(signal.MobileSignalHandler(func(s []byte) {
|
|
|
|
var evt EventType
|
|
|
|
err := json.Unmarshal(s, &evt)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
switch evt.Type {
|
|
|
|
case signal.EventConnectorSendTransaction:
|
|
|
|
var ev signal.ConnectorSendTransactionSignal
|
|
|
|
err := json.Unmarshal(evt.Event, &ev)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
err = state.handler.SendTransactionAccepted(SendTransactionAcceptedArgs{
|
2024-07-18 15:30:10 +00:00
|
|
|
Hash: fakedTransactionHash,
|
|
|
|
RequestID: ev.RequestID,
|
|
|
|
})
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
}))
|
2024-09-03 08:41:56 +00:00
|
|
|
t.Cleanup(signal.ResetMobileSignalHandler)
|
2024-07-18 15:30:10 +00:00
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
mockedChainClient := mock_client.NewMockClientInterface(state.mockCtrl)
|
|
|
|
state.rpcClient.EXPECT().EthClient(uint64(1)).Times(1).Return(mockedChainClient, nil)
|
|
|
|
mockedChainClient.EXPECT().SuggestGasPrice(state.ctx).Times(1).Return(big.NewInt(1), nil)
|
|
|
|
mockedChainClient.EXPECT().SuggestGasTipCap(state.ctx).Times(1).Return(big.NewInt(0), errors.New("EIP-1559 is not enabled"))
|
|
|
|
state.rpcClient.EXPECT().EthClient(uint64(1)).Times(1).Return(mockedChainClient, nil)
|
|
|
|
mockedChainClient.EXPECT().PendingNonceAt(state.ctx, common.Address(accountAddress)).Times(1).Return(uint64(10), nil)
|
|
|
|
|
|
|
|
response, err := state.cmd.Execute(state.ctx, request)
|
2024-07-18 15:30:10 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, response, fakedTransactionHash.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSendTransactionWithSignalRejected(t *testing.T) {
|
2024-09-19 18:24:28 +00:00
|
|
|
state, close := setupCommand(t, Method_EthSendTransaction)
|
|
|
|
t.Cleanup(close)
|
2024-07-18 15:30:10 +00:00
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
accountAddress := types.Address{0x01}
|
|
|
|
err := PersistDAppData(state.walletDb, testDAppData, accountAddress, uint64(0x1))
|
2024-07-18 15:30:10 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
request, err := prepareSendTransactionRequest(testDAppData, accountAddress)
|
2024-07-18 15:30:10 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
signal.SetMobileSignalHandler(signal.MobileSignalHandler(func(s []byte) {
|
|
|
|
var evt EventType
|
|
|
|
err := json.Unmarshal(s, &evt)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
switch evt.Type {
|
|
|
|
case signal.EventConnectorSendTransaction:
|
|
|
|
var ev signal.ConnectorSendTransactionSignal
|
|
|
|
err := json.Unmarshal(evt.Event, &ev)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
err = state.handler.SendTransactionRejected(RejectedArgs{
|
2024-07-18 15:30:10 +00:00
|
|
|
RequestID: ev.RequestID,
|
|
|
|
})
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
}))
|
2024-09-03 08:41:56 +00:00
|
|
|
t.Cleanup(signal.ResetMobileSignalHandler)
|
2024-07-18 15:30:10 +00:00
|
|
|
|
2024-09-19 18:24:28 +00:00
|
|
|
mockedChainClient := mock_client.NewMockClientInterface(state.mockCtrl)
|
|
|
|
state.rpcClient.EXPECT().EthClient(uint64(1)).Times(1).Return(mockedChainClient, nil)
|
|
|
|
mockedChainClient.EXPECT().SuggestGasPrice(state.ctx).Times(1).Return(big.NewInt(1), nil)
|
|
|
|
mockedChainClient.EXPECT().SuggestGasTipCap(state.ctx).Times(1).Return(big.NewInt(0), errors.New("EIP-1559 is not enabled"))
|
|
|
|
state.rpcClient.EXPECT().EthClient(uint64(1)).Times(1).Return(mockedChainClient, nil)
|
|
|
|
mockedChainClient.EXPECT().PendingNonceAt(state.ctx, common.Address(accountAddress)).Times(1).Return(uint64(10), nil)
|
|
|
|
|
|
|
|
_, err = state.cmd.Execute(state.ctx, request)
|
2024-07-18 15:30:10 +00:00
|
|
|
assert.Equal(t, ErrSendTransactionRejectedByUser, err)
|
|
|
|
}
|