2023-04-21 11:59:29 +00:00
|
|
|
package transfer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
|
|
|
"fmt"
|
2023-06-16 10:28:16 +00:00
|
|
|
"math/big"
|
2023-04-21 11:59:29 +00:00
|
|
|
"testing"
|
|
|
|
|
2023-05-11 07:50:07 +00:00
|
|
|
eth_common "github.com/ethereum/go-ethereum/common"
|
2023-06-16 10:28:16 +00:00
|
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
2023-05-11 07:50:07 +00:00
|
|
|
"github.com/status-im/status-go/services/wallet/common"
|
|
|
|
"github.com/status-im/status-go/services/wallet/testutils"
|
2023-06-13 09:25:23 +00:00
|
|
|
"github.com/status-im/status-go/services/wallet/token"
|
2023-06-14 19:43:28 +00:00
|
|
|
"github.com/status-im/status-go/sqlite"
|
2023-04-21 11:59:29 +00:00
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
type TestTransaction struct {
|
2023-06-14 16:10:20 +00:00
|
|
|
Hash eth_common.Hash
|
|
|
|
ChainID common.ChainID
|
|
|
|
From eth_common.Address // [sender]
|
|
|
|
Timestamp int64
|
|
|
|
BlkNumber int64
|
|
|
|
Success bool
|
|
|
|
MultiTransactionID MultiTransactionIDType
|
|
|
|
}
|
|
|
|
|
|
|
|
type TestTransfer struct {
|
|
|
|
TestTransaction
|
|
|
|
To eth_common.Address // [address]
|
|
|
|
Value int64
|
2023-06-13 09:25:23 +00:00
|
|
|
Token *token.Token
|
2023-06-14 16:10:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type TestMultiTransaction struct {
|
2023-04-21 11:59:29 +00:00
|
|
|
MultiTransactionID MultiTransactionIDType
|
|
|
|
MultiTransactionType MultiTransactionType
|
2023-06-14 16:10:20 +00:00
|
|
|
FromAddress eth_common.Address
|
|
|
|
ToAddress eth_common.Address
|
|
|
|
FromToken string
|
|
|
|
ToToken string
|
|
|
|
FromAmount int64
|
|
|
|
ToAmount int64
|
|
|
|
Timestamp int64
|
|
|
|
}
|
|
|
|
|
2023-06-13 09:25:23 +00:00
|
|
|
func SeedToToken(seed int) *token.Token {
|
|
|
|
tokenIndex := seed % len(TestTokens)
|
|
|
|
return TestTokens[tokenIndex]
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTrToToken(t *testing.T, tt *TestTransaction) (token *token.Token, isNative bool) {
|
|
|
|
// Sanity check that none of the markers changed and they should be equal to seed
|
|
|
|
require.Equal(t, tt.Timestamp, tt.BlkNumber)
|
|
|
|
|
|
|
|
tokenIndex := int(tt.Timestamp) % len(TestTokens)
|
|
|
|
isNative = testutils.SliceContains(NativeTokenIndices, tokenIndex)
|
|
|
|
|
|
|
|
return TestTokens[tokenIndex], isNative
|
|
|
|
}
|
|
|
|
|
2023-06-14 16:10:20 +00:00
|
|
|
func generateTestTransaction(seed int) TestTransaction {
|
2023-06-13 09:25:23 +00:00
|
|
|
token := SeedToToken(seed)
|
2023-06-14 16:10:20 +00:00
|
|
|
return TestTransaction{
|
|
|
|
Hash: eth_common.HexToHash(fmt.Sprintf("0x1%d", seed)),
|
2023-06-13 09:25:23 +00:00
|
|
|
ChainID: common.ChainID(token.ChainID),
|
2023-06-14 16:10:20 +00:00
|
|
|
From: eth_common.HexToAddress(fmt.Sprintf("0x2%d", seed)),
|
|
|
|
Timestamp: int64(seed),
|
|
|
|
BlkNumber: int64(seed),
|
|
|
|
Success: true,
|
|
|
|
MultiTransactionID: NoMultiTransactionID,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func generateTestTransfer(seed int) TestTransfer {
|
2023-06-13 09:25:23 +00:00
|
|
|
tokenIndex := seed % len(TestTokens)
|
|
|
|
token := TestTokens[tokenIndex]
|
2023-06-14 16:10:20 +00:00
|
|
|
return TestTransfer{
|
|
|
|
TestTransaction: generateTestTransaction(seed),
|
|
|
|
To: eth_common.HexToAddress(fmt.Sprintf("0x3%d", seed)),
|
|
|
|
Value: int64(seed),
|
2023-06-13 09:25:23 +00:00
|
|
|
Token: token,
|
2023-06-14 16:10:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func GenerateTestSendMultiTransaction(tr TestTransfer) TestMultiTransaction {
|
|
|
|
return TestMultiTransaction{
|
|
|
|
MultiTransactionType: MultiTransactionSend,
|
|
|
|
FromAddress: tr.From,
|
|
|
|
ToAddress: tr.To,
|
2023-06-13 09:25:23 +00:00
|
|
|
FromToken: tr.Token.Symbol,
|
|
|
|
ToToken: tr.Token.Symbol,
|
2023-06-14 16:10:20 +00:00
|
|
|
FromAmount: tr.Value,
|
2023-06-16 10:28:16 +00:00
|
|
|
ToAmount: 0,
|
2023-06-14 16:10:20 +00:00
|
|
|
Timestamp: tr.Timestamp,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func GenerateTestSwapMultiTransaction(tr TestTransfer, toToken string, toAmount int64) TestMultiTransaction {
|
|
|
|
return TestMultiTransaction{
|
|
|
|
MultiTransactionType: MultiTransactionSwap,
|
|
|
|
FromAddress: tr.From,
|
|
|
|
ToAddress: tr.To,
|
2023-06-13 09:25:23 +00:00
|
|
|
FromToken: tr.Token.Symbol,
|
2023-06-14 16:10:20 +00:00
|
|
|
ToToken: toToken,
|
|
|
|
FromAmount: tr.Value,
|
|
|
|
ToAmount: toAmount,
|
|
|
|
Timestamp: tr.Timestamp,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func GenerateTestBridgeMultiTransaction(fromTr, toTr TestTransfer) TestMultiTransaction {
|
|
|
|
return TestMultiTransaction{
|
|
|
|
MultiTransactionType: MultiTransactionBridge,
|
|
|
|
FromAddress: fromTr.From,
|
|
|
|
ToAddress: toTr.To,
|
2023-06-13 09:25:23 +00:00
|
|
|
FromToken: fromTr.Token.Symbol,
|
|
|
|
ToToken: toTr.Token.Symbol,
|
2023-06-14 16:10:20 +00:00
|
|
|
FromAmount: fromTr.Value,
|
|
|
|
ToAmount: toTr.Value,
|
|
|
|
Timestamp: fromTr.Timestamp,
|
|
|
|
}
|
2023-04-21 11:59:29 +00:00
|
|
|
}
|
|
|
|
|
2023-06-13 09:25:23 +00:00
|
|
|
// GenerateTestTransfers will generate transaction based on the TestTokens index and roll over if there are more than
|
|
|
|
// len(TestTokens) transactions
|
2023-06-14 16:10:20 +00:00
|
|
|
func GenerateTestTransfers(t *testing.T, db *sql.DB, firstStartIndex int, count int) (result []TestTransfer, fromAddresses, toAddresses []eth_common.Address) {
|
2023-04-21 11:59:29 +00:00
|
|
|
for i := firstStartIndex; i < (firstStartIndex + count); i++ {
|
2023-06-14 16:10:20 +00:00
|
|
|
tr := generateTestTransfer(i)
|
2023-05-28 10:40:50 +00:00
|
|
|
fromAddresses = append(fromAddresses, tr.From)
|
|
|
|
toAddresses = append(toAddresses, tr.To)
|
2023-04-21 11:59:29 +00:00
|
|
|
result = append(result, tr)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-06-13 09:25:23 +00:00
|
|
|
var EthMainnet = token.Token{
|
|
|
|
Address: eth_common.HexToAddress("0x"),
|
|
|
|
Name: "Ether",
|
|
|
|
Symbol: "ETH",
|
|
|
|
ChainID: 1,
|
|
|
|
}
|
|
|
|
|
|
|
|
var EthGoerli = token.Token{
|
|
|
|
Address: eth_common.HexToAddress("0x"),
|
|
|
|
Name: "Ether",
|
|
|
|
Symbol: "ETH",
|
|
|
|
ChainID: 5,
|
|
|
|
}
|
|
|
|
|
|
|
|
var EthOptimism = token.Token{
|
|
|
|
Address: eth_common.HexToAddress("0x"),
|
|
|
|
Name: "Ether",
|
|
|
|
Symbol: "ETH",
|
|
|
|
ChainID: 10,
|
|
|
|
}
|
|
|
|
|
|
|
|
var UsdcMainnet = token.Token{
|
|
|
|
Address: eth_common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"),
|
|
|
|
Name: "USD Coin",
|
|
|
|
Symbol: "USDC",
|
|
|
|
ChainID: 1,
|
|
|
|
}
|
|
|
|
|
|
|
|
var UsdcGoerli = token.Token{
|
|
|
|
Address: eth_common.HexToAddress("0x98339d8c260052b7ad81c28c16c0b98420f2b46a"),
|
|
|
|
Name: "USD Coin",
|
|
|
|
Symbol: "USDC",
|
|
|
|
ChainID: 5,
|
|
|
|
}
|
|
|
|
|
|
|
|
var UsdcOptimism = token.Token{
|
|
|
|
Address: eth_common.HexToAddress("0x7f5c764cbc14f9669b88837ca1490cca17c31607"),
|
|
|
|
Name: "USD Coin",
|
|
|
|
Symbol: "USDC",
|
|
|
|
ChainID: 10,
|
|
|
|
}
|
|
|
|
|
|
|
|
var SntMainnet = token.Token{
|
|
|
|
Address: eth_common.HexToAddress("0x744d70fdbe2ba4cf95131626614a1763df805b9e"),
|
|
|
|
Name: "Status Network Token",
|
|
|
|
Symbol: "SNT",
|
|
|
|
ChainID: 1,
|
|
|
|
}
|
|
|
|
|
|
|
|
var DaiMainnet = token.Token{
|
|
|
|
Address: eth_common.HexToAddress("0xf2edF1c091f683E3fb452497d9a98A49cBA84666"),
|
|
|
|
Name: "DAI Stablecoin",
|
|
|
|
Symbol: "DAI",
|
|
|
|
ChainID: 5,
|
|
|
|
}
|
|
|
|
|
|
|
|
var DaiGoerli = token.Token{
|
|
|
|
Address: eth_common.HexToAddress("0xf2edF1c091f683E3fb452497d9a98A49cBA84666"),
|
|
|
|
Name: "DAI Stablecoin",
|
|
|
|
Symbol: "DAI",
|
|
|
|
ChainID: 5,
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestTokens contains ETH/Mainnet, ETH/Goerli, ETH/Optimism, USDC/Mainnet, USDC/Goerli, USDC/Optimism, SNT/Mainnet, DAI/Mainnet, DAI/Goerli
|
|
|
|
var TestTokens = []*token.Token{
|
|
|
|
&EthMainnet, &EthGoerli, &EthOptimism, &UsdcMainnet, &UsdcGoerli, &UsdcOptimism, &SntMainnet, &DaiMainnet, &DaiGoerli,
|
|
|
|
}
|
|
|
|
|
|
|
|
var NativeTokenIndices = []int{0, 1, 2}
|
|
|
|
|
2023-06-14 16:10:20 +00:00
|
|
|
func InsertTestTransfer(t *testing.T, db *sql.DB, tr *TestTransfer) {
|
2023-06-13 09:25:23 +00:00
|
|
|
token := TestTokens[int(tr.Timestamp)%len(TestTokens)]
|
|
|
|
InsertTestTransferWithToken(t, db, tr, token.Address)
|
|
|
|
}
|
|
|
|
|
|
|
|
func InsertTestTransferWithToken(t *testing.T, db *sql.DB, tr *TestTransfer, tokenAddress eth_common.Address) {
|
2023-05-11 07:50:07 +00:00
|
|
|
tokenType := "eth"
|
2023-06-13 09:25:23 +00:00
|
|
|
if (tokenAddress != eth_common.Address{}) {
|
2023-05-11 07:50:07 +00:00
|
|
|
tokenType = "erc20"
|
|
|
|
}
|
2023-06-13 09:25:23 +00:00
|
|
|
|
|
|
|
// Respect `FOREIGN KEY(network_id,address,blk_hash)` of `transfers` table
|
2023-05-11 07:50:07 +00:00
|
|
|
blkHash := eth_common.HexToHash("4")
|
2023-06-14 19:43:28 +00:00
|
|
|
value := sqlite.Int64ToPadded128BitsStr(tr.Value)
|
|
|
|
|
2023-04-21 11:59:29 +00:00
|
|
|
_, err := db.Exec(`
|
|
|
|
INSERT OR IGNORE INTO blocks(
|
|
|
|
network_id, address, blk_number, blk_hash
|
|
|
|
) VALUES (?, ?, ?, ?);
|
|
|
|
INSERT INTO transfers (network_id, hash, address, blk_hash, tx,
|
|
|
|
sender, receipt, log, type, blk_number, timestamp, loaded,
|
2023-06-13 09:25:23 +00:00
|
|
|
multi_transaction_id, base_gas_fee, status, amount_padded128hex, token_address
|
|
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, 0, ?, ?, ?)`,
|
2023-04-21 11:59:29 +00:00
|
|
|
tr.ChainID, tr.To, tr.BlkNumber, blkHash,
|
2023-06-13 09:25:23 +00:00
|
|
|
tr.ChainID, tr.Hash, tr.To, blkHash, &JSONBlob{}, tr.From, &JSONBlob{}, &JSONBlob{}, tokenType, tr.BlkNumber, tr.Timestamp, tr.MultiTransactionID, tr.Success, value, tokenAddress.Hex())
|
2023-05-11 07:50:07 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2023-06-14 16:10:20 +00:00
|
|
|
func InsertTestPendingTransaction(t *testing.T, db *sql.DB, tr *TestTransfer) {
|
2023-05-11 07:50:07 +00:00
|
|
|
_, err := db.Exec(`
|
|
|
|
INSERT INTO pending_transactions (network_id, hash, timestamp, from_address, to_address,
|
|
|
|
symbol, gas_price, gas_limit, value, data, type, additional_data, multi_transaction_id
|
|
|
|
) VALUES (?, ?, ?, ?, ?, 'ETH', 0, 0, ?, '', 'test', '', ?)`,
|
|
|
|
tr.ChainID, tr.Hash, tr.Timestamp, tr.From, tr.To, tr.Value, tr.MultiTransactionID)
|
2023-04-21 11:59:29 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2023-06-14 16:10:20 +00:00
|
|
|
func InsertTestMultiTransaction(t *testing.T, db *sql.DB, tr *TestMultiTransaction) MultiTransactionIDType {
|
2023-05-11 07:50:07 +00:00
|
|
|
fromTokenType := tr.FromToken
|
|
|
|
if tr.FromToken == "" {
|
|
|
|
fromTokenType = testutils.EthSymbol
|
|
|
|
}
|
|
|
|
toTokenType := tr.ToToken
|
|
|
|
if tr.ToToken == "" {
|
|
|
|
toTokenType = testutils.EthSymbol
|
|
|
|
}
|
2023-06-16 10:28:16 +00:00
|
|
|
fromAmount := (*hexutil.Big)(big.NewInt(tr.FromAmount))
|
|
|
|
toAmount := (*hexutil.Big)(big.NewInt(tr.ToAmount))
|
|
|
|
|
2023-04-21 11:59:29 +00:00
|
|
|
result, err := db.Exec(`
|
2023-06-14 16:10:20 +00:00
|
|
|
INSERT INTO multi_transactions (from_address, from_asset, from_amount, to_address, to_asset, to_amount, type, timestamp
|
|
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
2023-06-16 10:28:16 +00:00
|
|
|
tr.FromAddress, fromTokenType, fromAmount.String(), tr.ToAddress, toTokenType, toAmount.String(), tr.MultiTransactionType, tr.Timestamp)
|
2023-04-21 11:59:29 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
rowID, err := result.LastInsertId()
|
|
|
|
require.NoError(t, err)
|
2023-06-14 16:10:20 +00:00
|
|
|
tr.MultiTransactionID = MultiTransactionIDType(rowID)
|
|
|
|
return tr.MultiTransactionID
|
2023-04-21 11:59:29 +00:00
|
|
|
}
|