feat: add transaction amounts to activity entry
This commit is contained in:
parent
86350379b1
commit
e26c2a7095
|
@ -7,10 +7,12 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
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/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
||||||
"github.com/status-im/status-go/services/wallet/common"
|
"github.com/status-im/status-go/services/wallet/common"
|
||||||
|
@ -36,6 +38,8 @@ type Entry struct {
|
||||||
activityType Type
|
activityType Type
|
||||||
activityStatus Status
|
activityStatus Status
|
||||||
tokenType TokenType
|
tokenType TokenType
|
||||||
|
amountOut *hexutil.Big // Used for activityType SendAT, SwapAT, BridgeAT
|
||||||
|
amountIn *hexutil.Big // Used for activityType ReceiveAT, BuyAT, SwapAT, BridgeAT
|
||||||
}
|
}
|
||||||
|
|
||||||
type jsonSerializationTemplate struct {
|
type jsonSerializationTemplate struct {
|
||||||
|
@ -46,6 +50,8 @@ type jsonSerializationTemplate struct {
|
||||||
ActivityType Type `json:"activityType"`
|
ActivityType Type `json:"activityType"`
|
||||||
ActivityStatus Status `json:"activityStatus"`
|
ActivityStatus Status `json:"activityStatus"`
|
||||||
TokenType TokenType `json:"tokenType"`
|
TokenType TokenType `json:"tokenType"`
|
||||||
|
AmountOut *hexutil.Big `json:"amountOut"`
|
||||||
|
AmountIn *hexutil.Big `json:"amountIn"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Entry) MarshalJSON() ([]byte, error) {
|
func (e *Entry) MarshalJSON() ([]byte, error) {
|
||||||
|
@ -57,6 +63,8 @@ func (e *Entry) MarshalJSON() ([]byte, error) {
|
||||||
ActivityType: e.activityType,
|
ActivityType: e.activityType,
|
||||||
ActivityStatus: e.activityStatus,
|
ActivityStatus: e.activityStatus,
|
||||||
TokenType: e.tokenType,
|
TokenType: e.tokenType,
|
||||||
|
AmountOut: e.amountOut,
|
||||||
|
AmountIn: e.amountIn,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,18 +80,20 @@ func (e *Entry) UnmarshalJSON(data []byte) error {
|
||||||
e.id = aux.ID
|
e.id = aux.ID
|
||||||
e.timestamp = aux.Timestamp
|
e.timestamp = aux.Timestamp
|
||||||
e.activityType = aux.ActivityType
|
e.activityType = aux.ActivityType
|
||||||
|
e.amountOut = aux.AmountOut
|
||||||
|
e.amountIn = aux.AmountIn
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newActivityEntryWithPendingTransaction(transaction *transfer.TransactionIdentity, timestamp int64, activityType Type, activityStatus Status) Entry {
|
func newActivityEntryWithPendingTransaction(transaction *transfer.TransactionIdentity, timestamp int64, activityType Type, activityStatus Status, amountIn *hexutil.Big, amountOut *hexutil.Big) Entry {
|
||||||
return newActivityEntryWithTransaction(true, transaction, timestamp, activityType, activityStatus)
|
return newActivityEntryWithTransaction(true, transaction, timestamp, activityType, activityStatus, amountIn, amountOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newActivityEntryWithSimpleTransaction(transaction *transfer.TransactionIdentity, timestamp int64, activityType Type, activityStatus Status) Entry {
|
func newActivityEntryWithSimpleTransaction(transaction *transfer.TransactionIdentity, timestamp int64, activityType Type, activityStatus Status, amountIn *hexutil.Big, amountOut *hexutil.Big) Entry {
|
||||||
return newActivityEntryWithTransaction(false, transaction, timestamp, activityType, activityStatus)
|
return newActivityEntryWithTransaction(false, transaction, timestamp, activityType, activityStatus, amountIn, amountOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newActivityEntryWithTransaction(pending bool, transaction *transfer.TransactionIdentity, timestamp int64, activityType Type, activityStatus Status) Entry {
|
func newActivityEntryWithTransaction(pending bool, transaction *transfer.TransactionIdentity, timestamp int64, activityType Type, activityStatus Status, amountIn *hexutil.Big, amountOut *hexutil.Big) Entry {
|
||||||
payloadType := SimpleTransactionPT
|
payloadType := SimpleTransactionPT
|
||||||
if pending {
|
if pending {
|
||||||
payloadType = PendingTransactionPT
|
payloadType = PendingTransactionPT
|
||||||
|
@ -97,10 +107,12 @@ func newActivityEntryWithTransaction(pending bool, transaction *transfer.Transac
|
||||||
activityType: activityType,
|
activityType: activityType,
|
||||||
activityStatus: activityStatus,
|
activityStatus: activityStatus,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountIn: amountIn,
|
||||||
|
amountOut: amountOut,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewActivityEntryWithMultiTransaction(id transfer.MultiTransactionIDType, timestamp int64, activityType Type, activityStatus Status) Entry {
|
func NewActivityEntryWithMultiTransaction(id transfer.MultiTransactionIDType, timestamp int64, activityType Type, activityStatus Status, amountIn *hexutil.Big, amountOut *hexutil.Big) Entry {
|
||||||
return Entry{
|
return Entry{
|
||||||
payloadType: MultiTransactionPT,
|
payloadType: MultiTransactionPT,
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -108,6 +120,8 @@ func NewActivityEntryWithMultiTransaction(id transfer.MultiTransactionIDType, ti
|
||||||
activityType: activityType,
|
activityType: activityType,
|
||||||
activityStatus: activityStatus,
|
activityStatus: activityStatus,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountIn: amountIn,
|
||||||
|
amountOut: amountOut,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,6 +304,9 @@ const (
|
||||||
|
|
||||||
transfers.sender AS from_address,
|
transfers.sender AS from_address,
|
||||||
transfers.address AS to_address,
|
transfers.address AS to_address,
|
||||||
|
transfers.amount_padded128hex AS tr_amount,
|
||||||
|
NULL AS mt_from_amount,
|
||||||
|
NULL AS mt_to_amount,
|
||||||
|
|
||||||
CASE
|
CASE
|
||||||
WHEN transfers.status IS 1 THEN statusSuccess
|
WHEN transfers.status IS 1 THEN statusSuccess
|
||||||
|
@ -352,6 +369,10 @@ const (
|
||||||
|
|
||||||
pending_transactions.from_address AS from_address,
|
pending_transactions.from_address AS from_address,
|
||||||
pending_transactions.to_address AS to_address,
|
pending_transactions.to_address AS to_address,
|
||||||
|
pending_transactions.value AS tr_amount,
|
||||||
|
NULL AS mt_from_amount,
|
||||||
|
NULL AS mt_to_amount,
|
||||||
|
|
||||||
statusPending AS agg_status,
|
statusPending AS agg_status,
|
||||||
1 AS agg_count
|
1 AS agg_count
|
||||||
FROM pending_transactions, filter_conditions
|
FROM pending_transactions, filter_conditions
|
||||||
|
@ -387,6 +408,9 @@ const (
|
||||||
NULL as tr_type,
|
NULL as tr_type,
|
||||||
multi_transactions.from_address AS from_address,
|
multi_transactions.from_address AS from_address,
|
||||||
multi_transactions.to_address AS to_address,
|
multi_transactions.to_address AS to_address,
|
||||||
|
NULL AS tr_amount,
|
||||||
|
multi_transactions.from_amount AS mt_from_amount,
|
||||||
|
multi_transactions.to_amount AS mt_to_amount,
|
||||||
|
|
||||||
CASE
|
CASE
|
||||||
WHEN tr_status.min_status = 1 AND pending_status.count IS NULL THEN statusSuccess
|
WHEN tr_status.min_status = 1 AND pending_status.count IS NULL THEN statusSuccess
|
||||||
|
@ -423,6 +447,51 @@ const (
|
||||||
noEntriesInTmpTableSQLValues = "(NULL)"
|
noEntriesInTmpTableSQLValues = "(NULL)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func getTrInAndOutAmounts(activityType Type, trAmount sql.NullString) (inAmount *hexutil.Big, outAmount *hexutil.Big) {
|
||||||
|
if trAmount.Valid {
|
||||||
|
amount, ok := new(big.Int).SetString(trAmount.String, 16)
|
||||||
|
if ok {
|
||||||
|
switch activityType {
|
||||||
|
case SendAT:
|
||||||
|
inAmount = (*hexutil.Big)(big.NewInt(0))
|
||||||
|
outAmount = (*hexutil.Big)(amount)
|
||||||
|
return
|
||||||
|
case ReceiveAT:
|
||||||
|
inAmount = (*hexutil.Big)(amount)
|
||||||
|
outAmount = (*hexutil.Big)(big.NewInt(0))
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
log.Warn(fmt.Sprintf("unexpected activity type %d", activityType))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Warn(fmt.Sprintf("could not parse amount %s", trAmount.String))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Warn(fmt.Sprintf("invalid transaction amount for type %d", activityType))
|
||||||
|
}
|
||||||
|
inAmount = (*hexutil.Big)(big.NewInt(0))
|
||||||
|
outAmount = (*hexutil.Big)(big.NewInt(0))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMtInAndOutAmounts(dbFromAmount sql.NullString, dbToAmount sql.NullString) (inAmount *hexutil.Big, outAmount *hexutil.Big) {
|
||||||
|
if dbFromAmount.Valid && dbToAmount.Valid {
|
||||||
|
fromAmount, frOk := new(big.Int).SetString(dbFromAmount.String, 16)
|
||||||
|
toAmount, toOk := new(big.Int).SetString(dbToAmount.String, 16)
|
||||||
|
if frOk && toOk {
|
||||||
|
inAmount = (*hexutil.Big)(toAmount)
|
||||||
|
outAmount = (*hexutil.Big)(fromAmount)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Warn(fmt.Sprintf("could not parse amounts %s %s", dbFromAmount.String, dbToAmount.String))
|
||||||
|
} else {
|
||||||
|
log.Warn("invalid transaction amounts")
|
||||||
|
}
|
||||||
|
inAmount = (*hexutil.Big)(big.NewInt(0))
|
||||||
|
outAmount = (*hexutil.Big)(big.NewInt(0))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// getActivityEntries queries the transfers, pending_transactions, and multi_transactions tables
|
// getActivityEntries queries the transfers, pending_transactions, and multi_transactions tables
|
||||||
// based on filter parameters and arguments
|
// based on filter parameters and arguments
|
||||||
// it returns metadata for all entries ordered by timestamp column
|
// it returns metadata for all entries ordered by timestamp column
|
||||||
|
@ -507,7 +576,9 @@ func getActivityEntries(ctx context.Context, db *sql.DB, addresses []eth.Address
|
||||||
var dbMtType, dbTrType sql.NullByte
|
var dbMtType, dbTrType sql.NullByte
|
||||||
var toAddress, fromAddress eth.Address
|
var toAddress, fromAddress eth.Address
|
||||||
var aggregatedStatus int
|
var aggregatedStatus int
|
||||||
err := rows.Scan(&transferHash, &pendingHash, &chainID, &multiTxID, ×tamp, &dbMtType, &dbTrType, &fromAddress, &toAddress, &aggregatedStatus, &aggregatedCount)
|
var dbTrAmount sql.NullString
|
||||||
|
var dbMtFromAmount, dbMtToAmount sql.NullString
|
||||||
|
err := rows.Scan(&transferHash, &pendingHash, &chainID, &multiTxID, ×tamp, &dbMtType, &dbTrType, &fromAddress, &toAddress, &dbTrAmount, &dbMtFromAmount, &dbMtToAmount, &aggregatedStatus, &aggregatedCount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -530,17 +601,20 @@ func getActivityEntries(ctx context.Context, db *sql.DB, addresses []eth.Address
|
||||||
var entry Entry
|
var entry Entry
|
||||||
if transferHash != nil && chainID.Valid {
|
if transferHash != nil && chainID.Valid {
|
||||||
activityType, filteredAddress := getActivityType(dbTrType)
|
activityType, filteredAddress := getActivityType(dbTrType)
|
||||||
|
inAmount, outAmount := getTrInAndOutAmounts(activityType, dbTrAmount)
|
||||||
entry = newActivityEntryWithSimpleTransaction(
|
entry = newActivityEntryWithSimpleTransaction(
|
||||||
&transfer.TransactionIdentity{ChainID: common.ChainID(chainID.Int64), Hash: eth.BytesToHash(transferHash), Address: filteredAddress},
|
&transfer.TransactionIdentity{ChainID: common.ChainID(chainID.Int64), Hash: eth.BytesToHash(transferHash), Address: filteredAddress},
|
||||||
timestamp, activityType, activityStatus)
|
timestamp, activityType, activityStatus, inAmount, outAmount)
|
||||||
} else if pendingHash != nil && chainID.Valid {
|
} else if pendingHash != nil && chainID.Valid {
|
||||||
activityType, _ := getActivityType(dbTrType)
|
activityType, _ := getActivityType(dbTrType)
|
||||||
|
inAmount, outAmount := getTrInAndOutAmounts(activityType, dbTrAmount)
|
||||||
entry = newActivityEntryWithPendingTransaction(&transfer.TransactionIdentity{ChainID: common.ChainID(chainID.Int64), Hash: eth.BytesToHash(pendingHash)},
|
entry = newActivityEntryWithPendingTransaction(&transfer.TransactionIdentity{ChainID: common.ChainID(chainID.Int64), Hash: eth.BytesToHash(pendingHash)},
|
||||||
timestamp, activityType, activityStatus)
|
timestamp, activityType, activityStatus, inAmount, outAmount)
|
||||||
} else if multiTxID.Valid {
|
} else if multiTxID.Valid {
|
||||||
|
mtInAmount, mtOutAmount := getMtInAndOutAmounts(dbMtFromAmount, dbMtToAmount)
|
||||||
activityType := multiTransactionTypeToActivityType(transfer.MultiTransactionType(dbMtType.Byte))
|
activityType := multiTransactionTypeToActivityType(transfer.MultiTransactionType(dbMtType.Byte))
|
||||||
entry = NewActivityEntryWithMultiTransaction(transfer.MultiTransactionIDType(multiTxID.Int64),
|
entry = NewActivityEntryWithMultiTransaction(transfer.MultiTransactionIDType(multiTxID.Int64),
|
||||||
timestamp, activityType, activityStatus)
|
timestamp, activityType, activityStatus, mtInAmount, mtOutAmount)
|
||||||
} else {
|
} else {
|
||||||
return nil, errors.New("invalid row data")
|
return nil, errors.New("invalid row data")
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package activity
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/status-im/status-go/appdatabase"
|
"github.com/status-im/status-go/appdatabase"
|
||||||
|
@ -14,6 +15,7 @@ import (
|
||||||
|
|
||||||
eth "github.com/ethereum/go-ethereum/common"
|
eth "github.com/ethereum/go-ethereum/common"
|
||||||
eth_common "github.com/ethereum/go-ethereum/common"
|
eth_common "github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -133,6 +135,8 @@ func TestGetActivityEntriesAll(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(td.tr1.Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries))
|
}, entries))
|
||||||
require.True(t, testutils.StructExistsInSlice(Entry{
|
require.True(t, testutils.StructExistsInSlice(Entry{
|
||||||
payloadType: PendingTransactionPT,
|
payloadType: PendingTransactionPT,
|
||||||
|
@ -142,6 +146,8 @@ func TestGetActivityEntriesAll(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: PendingAS,
|
activityStatus: PendingAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(td.pendingTr.Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries))
|
}, entries))
|
||||||
require.True(t, testutils.StructExistsInSlice(Entry{
|
require.True(t, testutils.StructExistsInSlice(Entry{
|
||||||
payloadType: MultiTransactionPT,
|
payloadType: MultiTransactionPT,
|
||||||
|
@ -151,6 +157,8 @@ func TestGetActivityEntriesAll(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(td.multiTx1.FromAmount)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(td.multiTx1.ToAmount)),
|
||||||
}, entries))
|
}, entries))
|
||||||
require.True(t, testutils.StructExistsInSlice(Entry{
|
require.True(t, testutils.StructExistsInSlice(Entry{
|
||||||
payloadType: MultiTransactionPT,
|
payloadType: MultiTransactionPT,
|
||||||
|
@ -160,6 +168,8 @@ func TestGetActivityEntriesAll(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: PendingAS,
|
activityStatus: PendingAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(td.multiTx2.FromAmount)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(td.multiTx2.ToAmount)),
|
||||||
}, entries))
|
}, entries))
|
||||||
|
|
||||||
// Ensure the sub-transactions of the multi-transactions are not returned
|
// Ensure the sub-transactions of the multi-transactions are not returned
|
||||||
|
@ -171,6 +181,8 @@ func TestGetActivityEntriesAll(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(td.multiTx1Tr1.Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries))
|
}, entries))
|
||||||
require.False(t, testutils.StructExistsInSlice(Entry{
|
require.False(t, testutils.StructExistsInSlice(Entry{
|
||||||
payloadType: SimpleTransactionPT,
|
payloadType: SimpleTransactionPT,
|
||||||
|
@ -180,6 +192,8 @@ func TestGetActivityEntriesAll(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(td.multiTx1Tr2.Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries))
|
}, entries))
|
||||||
require.False(t, testutils.StructExistsInSlice(Entry{
|
require.False(t, testutils.StructExistsInSlice(Entry{
|
||||||
payloadType: SimpleTransactionPT,
|
payloadType: SimpleTransactionPT,
|
||||||
|
@ -189,6 +203,8 @@ func TestGetActivityEntriesAll(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(td.multiTx2Tr1.Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries))
|
}, entries))
|
||||||
require.False(t, testutils.StructExistsInSlice(Entry{
|
require.False(t, testutils.StructExistsInSlice(Entry{
|
||||||
payloadType: SimpleTransactionPT,
|
payloadType: SimpleTransactionPT,
|
||||||
|
@ -198,6 +214,8 @@ func TestGetActivityEntriesAll(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(td.multiTx2Tr2.Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries))
|
}, entries))
|
||||||
require.False(t, testutils.StructExistsInSlice(Entry{
|
require.False(t, testutils.StructExistsInSlice(Entry{
|
||||||
payloadType: PendingTransactionPT,
|
payloadType: PendingTransactionPT,
|
||||||
|
@ -207,6 +225,8 @@ func TestGetActivityEntriesAll(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: PendingAS,
|
activityStatus: PendingAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(td.multiTx2PendingTr.Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries))
|
}, entries))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,6 +306,8 @@ func TestGetActivityEntriesFilterByTime(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(trs[5].Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries[0])
|
}, entries[0])
|
||||||
require.Equal(t, Entry{
|
require.Equal(t, Entry{
|
||||||
payloadType: MultiTransactionPT,
|
payloadType: MultiTransactionPT,
|
||||||
|
@ -295,6 +317,8 @@ func TestGetActivityEntriesFilterByTime(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(td.multiTx1.FromAmount)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(td.multiTx1.ToAmount)),
|
||||||
}, entries[7])
|
}, entries[7])
|
||||||
|
|
||||||
// Test complete interval
|
// Test complete interval
|
||||||
|
@ -311,6 +335,8 @@ func TestGetActivityEntriesFilterByTime(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(trs[2].Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries[0])
|
}, entries[0])
|
||||||
require.Equal(t, Entry{
|
require.Equal(t, Entry{
|
||||||
payloadType: MultiTransactionPT,
|
payloadType: MultiTransactionPT,
|
||||||
|
@ -320,6 +346,8 @@ func TestGetActivityEntriesFilterByTime(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(td.multiTx1.FromAmount)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(td.multiTx1.ToAmount)),
|
||||||
}, entries[4])
|
}, entries[4])
|
||||||
|
|
||||||
// Test end only
|
// Test end only
|
||||||
|
@ -336,6 +364,8 @@ func TestGetActivityEntriesFilterByTime(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(trs[2].Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries[0])
|
}, entries[0])
|
||||||
require.Equal(t, Entry{
|
require.Equal(t, Entry{
|
||||||
payloadType: SimpleTransactionPT,
|
payloadType: SimpleTransactionPT,
|
||||||
|
@ -345,6 +375,8 @@ func TestGetActivityEntriesFilterByTime(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(td.tr1.Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries[6])
|
}, entries[6])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,6 +413,8 @@ func TestGetActivityEntriesCheckOffsetAndLimit(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(trs[8].Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries[0])
|
}, entries[0])
|
||||||
require.Equal(t, Entry{
|
require.Equal(t, Entry{
|
||||||
payloadType: SimpleTransactionPT,
|
payloadType: SimpleTransactionPT,
|
||||||
|
@ -390,6 +424,8 @@ func TestGetActivityEntriesCheckOffsetAndLimit(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(trs[6].Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries[2])
|
}, entries[2])
|
||||||
|
|
||||||
// Move window 2 entries forward
|
// Move window 2 entries forward
|
||||||
|
@ -405,6 +441,8 @@ func TestGetActivityEntriesCheckOffsetAndLimit(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(trs[6].Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries[0])
|
}, entries[0])
|
||||||
require.Equal(t, Entry{
|
require.Equal(t, Entry{
|
||||||
payloadType: SimpleTransactionPT,
|
payloadType: SimpleTransactionPT,
|
||||||
|
@ -414,6 +452,8 @@ func TestGetActivityEntriesCheckOffsetAndLimit(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(trs[4].Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries[2])
|
}, entries[2])
|
||||||
|
|
||||||
// Move window 4 more entries to test filter cap
|
// Move window 4 more entries to test filter cap
|
||||||
|
@ -429,6 +469,8 @@ func TestGetActivityEntriesCheckOffsetAndLimit(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(trs[2].Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries[0])
|
}, entries[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,6 +583,8 @@ func TestGetActivityEntriesFilterByAddresses(t *testing.T) {
|
||||||
activityType: ReceiveAT,
|
activityType: ReceiveAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(0)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(trs[4].Value)),
|
||||||
}, entries[0])
|
}, entries[0])
|
||||||
require.Equal(t, Entry{
|
require.Equal(t, Entry{
|
||||||
payloadType: SimpleTransactionPT,
|
payloadType: SimpleTransactionPT,
|
||||||
|
@ -550,6 +594,8 @@ func TestGetActivityEntriesFilterByAddresses(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: CompleteAS,
|
activityStatus: CompleteAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(trs[1].Value)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(0)),
|
||||||
}, entries[1])
|
}, entries[1])
|
||||||
require.Equal(t, Entry{
|
require.Equal(t, Entry{
|
||||||
payloadType: MultiTransactionPT,
|
payloadType: MultiTransactionPT,
|
||||||
|
@ -559,6 +605,8 @@ func TestGetActivityEntriesFilterByAddresses(t *testing.T) {
|
||||||
activityType: SendAT,
|
activityType: SendAT,
|
||||||
activityStatus: PendingAS,
|
activityStatus: PendingAS,
|
||||||
tokenType: AssetTT,
|
tokenType: AssetTT,
|
||||||
|
amountOut: (*hexutil.Big)(big.NewInt(td.multiTx2.FromAmount)),
|
||||||
|
amountIn: (*hexutil.Big)(big.NewInt(td.multiTx2.ToAmount)),
|
||||||
}, entries[2])
|
}, entries[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
eth_common "github.com/ethereum/go-ethereum/common"
|
eth_common "github.com/ethereum/go-ethereum/common"
|
||||||
"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/testutils"
|
"github.com/status-im/status-go/services/wallet/testutils"
|
||||||
|
"github.com/status-im/status-go/sqlite"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -118,16 +119,18 @@ func InsertTestTransfer(t *testing.T, db *sql.DB, tr *TestTransfer) {
|
||||||
tokenType = "erc20"
|
tokenType = "erc20"
|
||||||
}
|
}
|
||||||
blkHash := eth_common.HexToHash("4")
|
blkHash := eth_common.HexToHash("4")
|
||||||
|
value := sqlite.Int64ToPadded128BitsStr(tr.Value)
|
||||||
|
|
||||||
_, err := db.Exec(`
|
_, err := db.Exec(`
|
||||||
INSERT OR IGNORE INTO blocks(
|
INSERT OR IGNORE INTO blocks(
|
||||||
network_id, address, blk_number, blk_hash
|
network_id, address, blk_number, blk_hash
|
||||||
) VALUES (?, ?, ?, ?);
|
) VALUES (?, ?, ?, ?);
|
||||||
INSERT INTO transfers (network_id, hash, address, blk_hash, tx,
|
INSERT INTO transfers (network_id, hash, address, blk_hash, tx,
|
||||||
sender, receipt, log, type, blk_number, timestamp, loaded,
|
sender, receipt, log, type, blk_number, timestamp, loaded,
|
||||||
multi_transaction_id, base_gas_fee, status
|
multi_transaction_id, base_gas_fee, status, amount_padded128hex
|
||||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, 0, ?)`,
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, 0, ?, ?)`,
|
||||||
tr.ChainID, tr.To, tr.BlkNumber, blkHash,
|
tr.ChainID, tr.To, tr.BlkNumber, blkHash,
|
||||||
tr.ChainID, tr.Hash, tr.To, blkHash, &JSONBlob{}, tr.From, &JSONBlob{}, &JSONBlob{}, tokenType, tr.BlkNumber, tr.Timestamp, tr.MultiTransactionID, tr.Success)
|
tr.ChainID, tr.Hash, tr.To, blkHash, &JSONBlob{}, tr.From, &JSONBlob{}, &JSONBlob{}, tokenType, tr.BlkNumber, tr.Timestamp, tr.MultiTransactionID, tr.Success, value)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,3 +87,8 @@ func BigIntToPadded128BitsStr(val *big.Int) *string {
|
||||||
*res = fmt.Sprintf("%032s", hexStr)
|
*res = fmt.Sprintf("%032s", hexStr)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Int64ToPadded128BitsStr(val int64) *string {
|
||||||
|
res := fmt.Sprintf("%032x", val)
|
||||||
|
return &res
|
||||||
|
}
|
||||||
|
|
|
@ -57,3 +57,35 @@ func TestBigIntToPadded128BitsStr(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInt64ToPadded128BitsStr(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
input int64
|
||||||
|
expected *string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "case nonzero",
|
||||||
|
input: 123456,
|
||||||
|
expected: strToPtr("0000000000000000000000000001e240"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "case zero",
|
||||||
|
input: 0,
|
||||||
|
expected: strToPtr("00000000000000000000000000000000"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
result := Int64ToPadded128BitsStr(tc.input)
|
||||||
|
if result != nil && tc.expected != nil {
|
||||||
|
if *result != *tc.expected {
|
||||||
|
t.Errorf("expected %s, got %s", *tc.expected, *result)
|
||||||
|
}
|
||||||
|
} else if result != nil || tc.expected != nil {
|
||||||
|
t.Errorf("expected %v, got %v", tc.expected, result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue