tests(integration) add integration test to debug MTID transfer
Updates #14071
This commit is contained in:
parent
a8a943bec9
commit
1d0643e926
|
@ -225,7 +225,7 @@ require (
|
||||||
github.com/status-im/doubleratchet v3.0.0+incompatible // indirect
|
github.com/status-im/doubleratchet v3.0.0+incompatible // indirect
|
||||||
github.com/status-im/go-multiaddr-ethv4 v1.2.5 // indirect
|
github.com/status-im/go-multiaddr-ethv4 v1.2.5 // indirect
|
||||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 // indirect
|
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 // indirect
|
||||||
github.com/status-im/markdown v0.0.0-20231114210825-6c2d15b5dc57 // indirect
|
github.com/status-im/markdown v0.0.0-20240404192634-b7e33c6ac3d4 // indirect
|
||||||
github.com/status-im/migrate/v4 v4.6.2-status.3 // indirect
|
github.com/status-im/migrate/v4 v4.6.2-status.3 // indirect
|
||||||
github.com/status-im/mvds v0.0.27-0.20240111144448-92d364e4be82 // indirect
|
github.com/status-im/mvds v0.0.27-0.20240111144448-92d364e4be82 // indirect
|
||||||
github.com/status-im/rendezvous v1.3.7 // indirect
|
github.com/status-im/rendezvous v1.3.7 // indirect
|
||||||
|
|
|
@ -1992,8 +1992,8 @@ github.com/status-im/gomoji v1.1.3-0.20220213022530-e5ac4a8732d4/go.mod h1:hmpnZ
|
||||||
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
||||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E=
|
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E=
|
||||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
||||||
github.com/status-im/markdown v0.0.0-20231114210825-6c2d15b5dc57 h1:AuJFXERIFVzUjf9rrTb8vamFubB6Ks/e8aUasDr4pOM=
|
github.com/status-im/markdown v0.0.0-20240404192634-b7e33c6ac3d4 h1:KBeXtOoisXjiSCkNVmZcq15kK4NmSi4p1hyZeUcT5dY=
|
||||||
github.com/status-im/markdown v0.0.0-20231114210825-6c2d15b5dc57/go.mod h1:5rjPyv3KffPNVbFjnsVy0NGj9+JeW40WvXLdxH1VKuE=
|
github.com/status-im/markdown v0.0.0-20240404192634-b7e33c6ac3d4/go.mod h1:5rjPyv3KffPNVbFjnsVy0NGj9+JeW40WvXLdxH1VKuE=
|
||||||
github.com/status-im/migrate/v4 v4.6.2-status.3 h1:Khwjb59NzniloUr5i9s9AtkEyqBbQFt1lkoAu66sAu0=
|
github.com/status-im/migrate/v4 v4.6.2-status.3 h1:Khwjb59NzniloUr5i9s9AtkEyqBbQFt1lkoAu66sAu0=
|
||||||
github.com/status-im/migrate/v4 v4.6.2-status.3/go.mod h1:c/kc90n47GZu/58nnz1OMLTf7uE4Da4gZP5qmU+A/v8=
|
github.com/status-im/migrate/v4 v4.6.2-status.3/go.mod h1:c/kc90n47GZu/58nnz1OMLTf7uE4Da4gZP5qmU+A/v8=
|
||||||
github.com/status-im/mvds v0.0.27-0.20240111144448-92d364e4be82 h1:A7jtwOlDMUGUPx5tTwUPewMoIprvo9oN9kU0H1CP+FQ=
|
github.com/status-im/mvds v0.0.27-0.20240111144448-92d364e4be82 h1:A7jtwOlDMUGUPx5tTwUPewMoIprvo9oN9kU0H1CP+FQ=
|
||||||
|
|
|
@ -230,21 +230,14 @@ func WaitForWalletEventGetPayload[T any](eventQueue chan GoEvent, eventName wall
|
||||||
return newPayload, nil
|
return newPayload, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitForTxDownloaderToFinishForAccountsCondition returns a state-full condition function that records every account that has been seen with the events until the entire list is seen
|
// WaitForTxDownloaderToFinishForAccountsCondition returns a stateful condition function that checks that at least on account that has been seen with the events until the entire list is seen.
|
||||||
|
// The loadBlocksAndTransfersCommand.fetchHistoryBlocksForAccount reports only for one account history ready, even though the downloaded history might contain other accounts.
|
||||||
func WaitForTxDownloaderToFinishForAccountsCondition(t *testing.T, accounts []common.Address) func(walletEvent *walletevent.Event) bool {
|
func WaitForTxDownloaderToFinishForAccountsCondition(t *testing.T, accounts []common.Address) func(walletEvent *walletevent.Event) bool {
|
||||||
accs := make([]common.Address, len(accounts))
|
|
||||||
copy(accs, accounts)
|
|
||||||
|
|
||||||
return func(walletEvent *walletevent.Event) bool {
|
return func(walletEvent *walletevent.Event) bool {
|
||||||
eventAccountsLoop:
|
|
||||||
for _, acc := range walletEvent.Accounts {
|
for _, acc := range walletEvent.Accounts {
|
||||||
for i, a := range accs {
|
for _, a := range accounts {
|
||||||
if acc == a {
|
if acc == a {
|
||||||
if len(accs) == 1 {
|
return true
|
||||||
return true
|
|
||||||
}
|
|
||||||
accs = append(accs[:i], accs[i+1:]...)
|
|
||||||
continue eventAccountsLoop
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,6 +380,28 @@ func CallPrivateMethodAndGetTWithTimeout[T any](method string, params []interfac
|
||||||
|
|
||||||
return &res, nil
|
return &res, nil
|
||||||
}
|
}
|
||||||
|
func CallPrivateMethodAndGetSliceOfT[T any](method string, params []interface{}) ([]T, error) {
|
||||||
|
return CallPrivateMethodAndGetSliceOfTWithTimeout[T](method, params, 60*time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CallPrivateMethodAndGetSliceOfTWithTimeout[T any](method string, params []interface{}, timeout time.Duration) ([]T, error) {
|
||||||
|
resJson, err := CallPrivateMethodWithTimeout(method, params, timeout)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res := make([]T, 0)
|
||||||
|
rawJson, err := GetRPCAPIResponseRaw(resJson)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(rawJson, &res); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to unmarshal data: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
HashedPassword string `json:"hashedPassword"`
|
HashedPassword string `json:"hashedPassword"`
|
||||||
|
|
|
@ -24,7 +24,8 @@ func TestActivityIncrementalUpdates_NoFilterNewPendingTransactions(t *testing.T)
|
||||||
td, close := setupAccountsAndTransactions(t)
|
td, close := setupAccountsAndTransactions(t)
|
||||||
defer close()
|
defer close()
|
||||||
|
|
||||||
rawSessionID, err := helpers.CallPrivateMethodAndGetT[int32]("wallet_startActivityFilterSession", []interface{}{[]types.Address{td.operableAccounts[0].Address}, false, []common.ChainID{5}, activity.Filter{}, 3})
|
chainID := common.OptimismSepolia
|
||||||
|
rawSessionID, err := helpers.CallPrivateMethodAndGetT[int32]("wallet_startActivityFilterSession", []interface{}{[]types.Address{td.operableAccounts[0].Address}, false, []common.ChainID{common.ChainID(chainID)}, activity.Filter{}, 3})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, rawSessionID)
|
require.NotNil(t, rawSessionID)
|
||||||
sessionID := activity.SessionID(*rawSessionID)
|
sessionID := activity.SessionID(*rawSessionID)
|
||||||
|
@ -36,7 +37,7 @@ func TestActivityIncrementalUpdates_NoFilterNewPendingTransactions(t *testing.T)
|
||||||
require.Equal(t, 3, len(res.Activities))
|
require.Equal(t, 3, len(res.Activities))
|
||||||
|
|
||||||
// Trigger updating of activity results
|
// Trigger updating of activity results
|
||||||
sendTransaction(t, td)
|
sendTransaction(t, td, chainID)
|
||||||
|
|
||||||
// Wait for EventActivitySessionUpdated signal triggered by the first EventPendingTransactionUpdate
|
// Wait for EventActivitySessionUpdated signal triggered by the first EventPendingTransactionUpdate
|
||||||
update, err := helpers.WaitForWalletEventGetPayload[activity.SessionUpdate](td.eventQueue, activity.EventActivitySessionUpdated, 60*time.Second)
|
update, err := helpers.WaitForWalletEventGetPayload[activity.SessionUpdate](td.eventQueue, activity.EventActivitySessionUpdated, 60*time.Second)
|
||||||
|
@ -51,7 +52,7 @@ func TestActivityIncrementalUpdates_NoFilterNewPendingTransactions(t *testing.T)
|
||||||
// require.True(t, *update.HasNewOnTop)
|
// require.True(t, *update.HasNewOnTop)
|
||||||
|
|
||||||
// Start history download to cleanup pending transactions
|
// Start history download to cleanup pending transactions
|
||||||
_, err = helpers.CallPrivateMethod("wallet_checkRecentHistoryForChainIDs", []interface{}{[]uint64{5}, []types.Address{td.operableAccounts[0].Address, td.watchAccounts[0].Address}})
|
_, err = helpers.CallPrivateMethod("wallet_checkRecentHistoryForChainIDs", []interface{}{[]uint64{chainID}, []types.Address{td.operableAccounts[0].Address, td.watchAccounts[0].Address}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
downloadDoneFn := helpers.WaitForTxDownloaderToFinishForAccountsCondition(t, []eth.Address{eth.Address(td.operableAccounts[0].Address), eth.Address(td.watchAccounts[0].Address)})
|
downloadDoneFn := helpers.WaitForTxDownloaderToFinishForAccountsCondition(t, []eth.Address{eth.Address(td.operableAccounts[0].Address), eth.Address(td.watchAccounts[0].Address)})
|
||||||
|
@ -61,7 +62,7 @@ func TestActivityIncrementalUpdates_NoFilterNewPendingTransactions(t *testing.T)
|
||||||
// It is expected that downloading will generate a EventPendingTransactionUpdate that in turn will generate a second EventActivitySessionUpdated signal marked by the update non nil value
|
// It is expected that downloading will generate a EventPendingTransactionUpdate that in turn will generate a second EventActivitySessionUpdated signal marked by the update non nil value
|
||||||
_, err = helpers.WaitForWalletEventsWithOptionals(
|
_, err = helpers.WaitForWalletEventsWithOptionals(
|
||||||
td.eventQueue,
|
td.eventQueue,
|
||||||
[]walletevent.EventType{transfer.EventRecentHistoryReady},
|
[]walletevent.EventType{activity.EventActivitySessionUpdated},
|
||||||
120*time.Second,
|
120*time.Second,
|
||||||
func(e *walletevent.Event) bool {
|
func(e *walletevent.Event) bool {
|
||||||
if e.Type == activity.EventActivitySessionUpdated {
|
if e.Type == activity.EventActivitySessionUpdated {
|
||||||
|
@ -72,16 +73,16 @@ func TestActivityIncrementalUpdates_NoFilterNewPendingTransactions(t *testing.T)
|
||||||
require.True(t, *update.HasNewOnTop)
|
require.True(t, *update.HasNewOnTop)
|
||||||
//require.NotNil(t, update.Removed)
|
//require.NotNil(t, update.Removed)
|
||||||
//require.True(t, *update.Removed)
|
//require.True(t, *update.Removed)
|
||||||
return false
|
return true
|
||||||
} else if e.Type == transfer.EventFetchingHistoryError {
|
} else if e.Type == transfer.EventFetchingHistoryError {
|
||||||
require.Fail(t, "History download failed")
|
require.Fail(t, "History download failed")
|
||||||
return false
|
return false
|
||||||
} else if downloadDoneFn(e) {
|
} else if downloadDoneFn(e) {
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
[]walletevent.EventType{activity.EventActivitySessionUpdated, transfer.EventFetchingHistoryError},
|
[]walletevent.EventType{transfer.EventFetchingHistoryError},
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, update, "EventActivitySessionUpdated signal was triggered by the second EventPendingTransactionUpdate during history download")
|
require.NotNil(t, update, "EventActivitySessionUpdated signal was triggered by the second EventPendingTransactionUpdate during history download")
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
eth "github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/status-im/status-desktop/test/status-go/integration/helpers"
|
"github.com/status-im/status-desktop/test/status-go/integration/helpers"
|
||||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||||
|
@ -50,11 +50,12 @@ func setupAccountsAndTransactionsWithTimeout(t *testing.T, timeout time.Duration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendTransaction generates multi_transactions and pending entries then it creates and publishes a transaction
|
// sendTransaction generates a Multi Transaction and Bridge entry then
|
||||||
func sendTransaction(t *testing.T, td testUserData) {
|
// calls createMultiTransaction which creates a pending entry and publishes a transaction
|
||||||
|
func sendTransaction(t *testing.T, td testUserData, chainID uint64) {
|
||||||
mTCommand := transfer.MultiTransactionCommand{
|
mTCommand := transfer.MultiTransactionCommand{
|
||||||
FromAddress: common.Address(td.operableAccounts[0].Address),
|
FromAddress: eth.Address(td.operableAccounts[0].Address),
|
||||||
ToAddress: common.Address(td.watchAccounts[0].Address),
|
ToAddress: eth.Address(td.watchAccounts[0].Address),
|
||||||
FromAsset: "ETH",
|
FromAsset: "ETH",
|
||||||
ToAsset: "ETH",
|
ToAsset: "ETH",
|
||||||
FromAmount: (*hexutil.Big)(new(big.Int).SetUint64(100000)),
|
FromAmount: (*hexutil.Big)(new(big.Int).SetUint64(100000)),
|
||||||
|
@ -63,7 +64,7 @@ func sendTransaction(t *testing.T, td testUserData) {
|
||||||
data := []*bridge.TransactionBridge{
|
data := []*bridge.TransactionBridge{
|
||||||
{
|
{
|
||||||
BridgeName: "Transfer",
|
BridgeName: "Transfer",
|
||||||
ChainID: 5,
|
ChainID: chainID,
|
||||||
TransferTx: &transactions.SendTxArgs{
|
TransferTx: &transactions.SendTxArgs{
|
||||||
From: td.operableAccounts[0].Address,
|
From: td.operableAccounts[0].Address,
|
||||||
To: &td.watchAccounts[0].Address,
|
To: &td.watchAccounts[0].Address,
|
||||||
|
|
|
@ -7,13 +7,12 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
eth "github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/status-im/status-desktop/test/status-go/integration/helpers"
|
"github.com/status-im/status-desktop/test/status-go/integration/helpers"
|
||||||
|
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
"github.com/status-im/status-go/services/wallet/transfer"
|
"github.com/status-im/status-go/services/wallet/common"
|
||||||
"github.com/status-im/status-go/services/wallet/walletevent"
|
"github.com/status-im/status-go/services/wallet/walletevent"
|
||||||
"github.com/status-im/status-go/transactions"
|
"github.com/status-im/status-go/transactions"
|
||||||
)
|
)
|
||||||
|
@ -23,7 +22,8 @@ func TestPendingTx_NotificationStatus(t *testing.T) {
|
||||||
td, close := setupAccountsAndTransactions(t)
|
td, close := setupAccountsAndTransactions(t)
|
||||||
defer close()
|
defer close()
|
||||||
|
|
||||||
sendTransaction(t, td)
|
chainID := common.OptimismSepolia
|
||||||
|
sendTransaction(t, td, chainID)
|
||||||
|
|
||||||
// Wait for transaction to be included in block
|
// Wait for transaction to be included in block
|
||||||
confirmationPayloads, err := helpers.WaitForWalletEventsGetMap(
|
confirmationPayloads, err := helpers.WaitForWalletEventsGetMap(
|
||||||
|
@ -45,24 +45,13 @@ func TestPendingTx_NotificationStatus(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start history download ...
|
// Start history download ...
|
||||||
_, err = helpers.CallPrivateMethod("wallet_checkRecentHistoryForChainIDs", []interface{}{[]uint64{5}, []types.Address{td.operableAccounts[0].Address, td.watchAccounts[0].Address}})
|
_, err = helpers.CallPrivateMethod("wallet_checkRecentHistoryForChainIDs", []interface{}{[]uint64{chainID}, []types.Address{td.operableAccounts[0].Address, td.watchAccounts[0].Address}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
downloadDoneFn := helpers.WaitForTxDownloaderToFinishForAccountsCondition(t, []eth.Address{eth.Address(td.operableAccounts[0].Address), eth.Address(td.watchAccounts[0].Address)})
|
// Wait for transaction to be included in block
|
||||||
|
pendingUpdated, err := helpers.WaitForWalletEventGetPayload[transactions.PendingTxUpdatePayload](
|
||||||
// ... and wait for the new transaction download to trigger deletion from pending_transactions
|
td.eventQueue, transactions.EventPendingTransactionUpdate, 60*time.Second)
|
||||||
_, err = helpers.WaitForWalletEventsWithOptionals(
|
|
||||||
td.eventQueue,
|
|
||||||
[]walletevent.EventType{transfer.EventRecentHistoryReady},
|
|
||||||
60*time.Second,
|
|
||||||
func(e *walletevent.Event) bool {
|
|
||||||
if e.Type == transfer.EventFetchingHistoryError {
|
|
||||||
require.Fail(t, "History download failed")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return downloadDoneFn(e)
|
|
||||||
},
|
|
||||||
[]walletevent.EventType{transfer.EventFetchingHistoryError},
|
|
||||||
)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.True(t, pendingUpdated.Deleted)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,16 +5,26 @@ package wallet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
eth "github.com/ethereum/go-ethereum/common"
|
eth "github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/status-im/status-desktop/test/status-go/integration/helpers"
|
"github.com/status-im/status-desktop/test/status-go/integration/helpers"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/contracts/ierc20"
|
||||||
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
"github.com/status-im/status-go/services/wallet"
|
"github.com/status-im/status-go/services/wallet"
|
||||||
|
"github.com/status-im/status-go/services/wallet/activity"
|
||||||
|
"github.com/status-im/status-go/services/wallet/bridge"
|
||||||
"github.com/status-im/status-go/services/wallet/common"
|
"github.com/status-im/status-go/services/wallet/common"
|
||||||
|
"github.com/status-im/status-go/services/wallet/transfer"
|
||||||
|
"github.com/status-im/status-go/services/wallet/walletevent"
|
||||||
|
"github.com/status-im/status-go/transactions"
|
||||||
)
|
)
|
||||||
|
|
||||||
type dataPayload struct {
|
type dataPayload struct {
|
||||||
|
@ -22,7 +32,7 @@ type dataPayload struct {
|
||||||
accountFrom eth.Address
|
accountFrom eth.Address
|
||||||
accountTo eth.Address
|
accountTo eth.Address
|
||||||
amount *hexutil.Big
|
amount *hexutil.Big
|
||||||
tokenIdentity string // Format: "<HexTokenAddress>:<TokenID>"
|
tokenIdentity string // Format: "<HexTokenAddress>:<TokenID>" or "<Symbol>"
|
||||||
disabledFromChainIDs []uint64
|
disabledFromChainIDs []uint64
|
||||||
disabledToChainIDs []uint64
|
disabledToChainIDs []uint64
|
||||||
preferredChainIDs []uint64
|
preferredChainIDs []uint64
|
||||||
|
@ -76,7 +86,7 @@ func erc1155Payload(tokenIdentity string) dataPayload {
|
||||||
return customBasicPayload(wallet.ERC1155Transfer, tokenIdentity)
|
return customBasicPayload(wallet.ERC1155Transfer, tokenIdentity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSendTransaction_Collectible(t *testing.T) {
|
func TestSendTransaction_Collectible_Routes(t *testing.T) {
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -98,3 +108,163 @@ func TestSendTransaction_Collectible(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func gweiToWei(gwei *big.Float) *big.Int {
|
||||||
|
weiMultiplier := big.NewFloat(1e9 /*10^9*/)
|
||||||
|
weiValue := new(big.Float).Mul(gwei, weiMultiplier)
|
||||||
|
res, _ := weiValue.Int(nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestSendTransaction_Assets_KeepMTID is here to debug why the MTID is not kept
|
||||||
|
// when migrating a transaction from pending_transactions to transfers table
|
||||||
|
func TestSendTransaction_Assets_KeepMTID(t *testing.T) {
|
||||||
|
td, close := setupAccountsAndTransactions(t)
|
||||||
|
defer close()
|
||||||
|
|
||||||
|
chainID := common.OptimismSepolia
|
||||||
|
amount, ok := new(big.Int).SetString("0x3e8", 0)
|
||||||
|
require.True(t, ok)
|
||||||
|
info := dataPayload{
|
||||||
|
transferType: wallet.Transfer,
|
||||||
|
tokenIdentity: "USDC",
|
||||||
|
accountFrom: eth.HexToAddress("0xe2d622c817878da5143bbe06866ca8e35273ba8a"),
|
||||||
|
accountTo: eth.HexToAddress("0xbd54a96c0ae19a220c8e1234f54c940dfab34639"),
|
||||||
|
amount: (*hexutil.Big)(amount),
|
||||||
|
disabledFromChainIDs: []uint64{common.OptimismMainnet},
|
||||||
|
disabledToChainIDs: []uint64{common.OptimismMainnet},
|
||||||
|
preferredChainIDs: []uint64{chainID},
|
||||||
|
gasFeeMode: wallet.GasFeeHigh,
|
||||||
|
fromLockedAmount: map[uint64]*hexutil.Big{},
|
||||||
|
}
|
||||||
|
|
||||||
|
payload := dataToCallingPayload(info)
|
||||||
|
res, err := helpers.CallPrivateMethodAndGetT[wallet.SuggestedRoutes]("wallet_getSuggestedRoutes", payload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Greater(t, len(res.Candidates), 0)
|
||||||
|
|
||||||
|
suggested := res.Candidates[0]
|
||||||
|
|
||||||
|
mtCmd := transfer.MultiTransactionCommand{
|
||||||
|
FromAddress: info.accountFrom,
|
||||||
|
ToAddress: info.accountTo,
|
||||||
|
FromAsset: info.tokenIdentity,
|
||||||
|
ToAsset: info.tokenIdentity,
|
||||||
|
FromAmount: info.amount,
|
||||||
|
Type: transfer.MultiTransactionSend,
|
||||||
|
}
|
||||||
|
|
||||||
|
abi, err := abi.JSON(strings.NewReader(ierc20.IERC20ABI))
|
||||||
|
require.NoError(t, err)
|
||||||
|
input, err := abi.Pack("transfer",
|
||||||
|
info.accountTo,
|
||||||
|
info.amount.ToInt(),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
txArgs := transactions.SendTxArgs{
|
||||||
|
From: types.Address(info.accountFrom),
|
||||||
|
To: common.NewAndSet(types.HexToAddress("0x5fd84259d66cd46123540766be93dfe6d43130d7")),
|
||||||
|
Gas: common.NewAndSet(hexutil.Uint64(suggested.GasAmount)),
|
||||||
|
GasPrice: (*hexutil.Big)(gweiToWei(suggested.GasFees.GasPrice)),
|
||||||
|
Value: (*hexutil.Big)(big.NewInt(0)),
|
||||||
|
MaxFeePerGas: (*hexutil.Big)(gweiToWei(suggested.GasFees.MaxFeePerGasHigh)),
|
||||||
|
MaxPriorityFeePerGas: (*hexutil.Big)(gweiToWei(suggested.GasFees.MaxPriorityFeePerGas)),
|
||||||
|
MultiTransactionID: common.NoMultiTransactionID,
|
||||||
|
Symbol: info.tokenIdentity,
|
||||||
|
Data: types.HexBytes(input),
|
||||||
|
}
|
||||||
|
|
||||||
|
bridge := []*bridge.TransactionBridge{{
|
||||||
|
BridgeName: suggested.BridgeName,
|
||||||
|
ChainID: chainID,
|
||||||
|
TransferTx: &txArgs,
|
||||||
|
}}
|
||||||
|
|
||||||
|
sendPayload := []interface{}{mtCmd, bridge, td.hashedPassword}
|
||||||
|
|
||||||
|
// Simulate the transaction creation as a result to SendModal user actions for an asset
|
||||||
|
sendRes, err := helpers.CallPrivateMethodAndGetT[transfer.MultiTransactionCommandResult]("wallet_createMultiTransaction", sendPayload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, sendRes)
|
||||||
|
require.Greater(t, len(sendRes.Hashes), 0)
|
||||||
|
|
||||||
|
// Wait for transaction to be included in block
|
||||||
|
_, err = helpers.WaitForWalletEventsGetMap(
|
||||||
|
td.eventQueue, []walletevent.EventType{
|
||||||
|
transactions.EventPendingTransactionUpdate,
|
||||||
|
transactions.EventPendingTransactionStatusChanged,
|
||||||
|
},
|
||||||
|
20*time.Second,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Start history download
|
||||||
|
_, err = helpers.CallPrivateMethod("wallet_checkRecentHistoryForChainIDs", []interface{}{[]uint64{chainID}, []types.Address{types.Address(info.accountFrom), types.Address(info.accountTo)}})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
newHash := eth.Hash(sendRes.Hashes[chainID][0])
|
||||||
|
// Wait for transaction to be deleted by downloader and also ensure we receive notification that transaction entries
|
||||||
|
// stored in transfers for the sender account
|
||||||
|
_, err = helpers.WaitForWalletEventsWithOptionals(
|
||||||
|
td.eventQueue,
|
||||||
|
[]walletevent.EventType{transactions.EventPendingTransactionUpdate, transfer.EventNewTransfers},
|
||||||
|
60*time.Second,
|
||||||
|
func(e *walletevent.Event) bool {
|
||||||
|
if e.Type == transactions.EventPendingTransactionUpdate {
|
||||||
|
update, err := walletevent.GetPayload[transactions.PendingTxUpdatePayload](*e)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return update.Deleted && update.TxIdentity.Hash == newHash
|
||||||
|
} else if e.Type == transfer.EventNewTransfers {
|
||||||
|
for _, acc := range e.Accounts {
|
||||||
|
if acc == info.accountFrom {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if e.Type == transfer.EventFetchingHistoryError {
|
||||||
|
require.Fail(t, "History download failed")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
[]walletevent.EventType{transfer.EventFetchingHistoryError},
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Ensure the transaction is not pending anymore
|
||||||
|
pendings, err := helpers.CallPrivateMethodAndGetSliceOfT[transactions.PendingTransaction]("wallet_getPendingTransactions", []interface{}{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, pendings, 0)
|
||||||
|
|
||||||
|
_, err = helpers.CallPrivateMethodAndGetT[activity.SessionID]("wallet_startActivityFilterSession", []interface{}{
|
||||||
|
[]eth.Address{info.accountFrom},
|
||||||
|
false, /* allAddresses */
|
||||||
|
[]common.ChainID{common.ChainID(chainID)},
|
||||||
|
activity.Filter{},
|
||||||
|
5,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
newMTID := sendRes.ID
|
||||||
|
// Confirm filtering results have a MT with expected MTID as last entry and the next one is not pending as reported
|
||||||
|
// by #14071 issue
|
||||||
|
resMap, err := helpers.WaitForWalletEventsGetMap(td.eventQueue, []walletevent.EventType{activity.EventActivityFilteringDone}, 5*time.Second)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, resMap, 1)
|
||||||
|
require.Equal(t, resMap[0].EventName, activity.EventActivityFilteringDone)
|
||||||
|
activityRes := resMap[0].JsonData
|
||||||
|
require.Equal(t, activity.ErrorCodeSuccess, activity.ErrorCode(int(activityRes["errorCode"].(float64))))
|
||||||
|
activities := activityRes["activities"].([](interface{}))
|
||||||
|
require.Greater(t, len(activities), 1)
|
||||||
|
lastEntry := activities[0].(map[string]interface{})
|
||||||
|
require.Equal(t, activity.MultiTransactionPT, activity.PayloadType(int(lastEntry["payloadType"].(float64))))
|
||||||
|
require.Equal(t, newMTID, int64(lastEntry["id"].(float64)))
|
||||||
|
if len(activities) > 1 {
|
||||||
|
secondEntry := activities[1].(map[string]interface{})
|
||||||
|
require.NotEqual(t, activity.PendingTransactionPT, activity.PayloadType(int(secondEntry["payloadType"].(float64))))
|
||||||
|
if tr, ok := secondEntry["transaction"]; ok {
|
||||||
|
require.NotEqual(t, newHash, tr.(map[string]interface{})["hash"].(eth.Hash))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue