From 423991fb300121e1858d1f3b6106e6d1cd6bfa65 Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 28 Aug 2023 11:02:05 +0200 Subject: [PATCH] chore(wallet) lookup symbols for wallet activity filter Updates status-desktop #11597 --- services/wallet/activity/activity.go | 105 +++++++++++++++------- services/wallet/activity/activity_test.go | 36 ++++++++ 2 files changed, 110 insertions(+), 31 deletions(-) diff --git a/services/wallet/activity/activity.go b/services/wallet/activity/activity.go index cc1fcf415..f7834287d 100644 --- a/services/wallet/activity/activity.go +++ b/services/wallet/activity/activity.go @@ -58,6 +58,8 @@ type Entry struct { amountIn *hexutil.Big // Used for activityType ReceiveAT, BuyAT, SwapAT, BridgeAT tokenOut *Token // Used for activityType SendAT, SwapAT, BridgeAT tokenIn *Token // Used for activityType ReceiveAT, BuyAT, SwapAT, BridgeAT + symbolOut *string + symbolIn *string sender *eth.Address recipient *eth.Address chainIDOut *common.ChainID @@ -76,6 +78,8 @@ type jsonSerializationTemplate struct { AmountIn *hexutil.Big `json:"amountIn"` TokenOut *Token `json:"tokenOut,omitempty"` TokenIn *Token `json:"tokenIn,omitempty"` + SymbolOut *string `json:"symbolOut,omitempty"` + SymbolIn *string `json:"symbolIn,omitempty"` Sender *eth.Address `json:"sender,omitempty"` Recipient *eth.Address `json:"recipient,omitempty"` ChainIDOut *common.ChainID `json:"chainIdOut,omitempty"` @@ -95,6 +99,8 @@ func (e *Entry) MarshalJSON() ([]byte, error) { AmountIn: e.amountIn, TokenOut: e.tokenOut, TokenIn: e.tokenIn, + SymbolOut: e.symbolOut, + SymbolIn: e.symbolIn, Sender: e.sender, Recipient: e.recipient, ChainIDOut: e.chainIDOut, @@ -120,6 +126,8 @@ func (e *Entry) UnmarshalJSON(data []byte) error { e.amountIn = aux.AmountIn e.tokenOut = aux.TokenOut e.tokenIn = aux.TokenIn + e.symbolOut = aux.SymbolOut + e.symbolIn = aux.SymbolIn e.sender = aux.Sender e.recipient = aux.Recipient e.chainIDOut = aux.ChainIDOut @@ -128,6 +136,12 @@ func (e *Entry) UnmarshalJSON(data []byte) error { return nil } +func newAndSet[T any](v T) *T { + res := new(T) + *res = v + return res +} + func newActivityEntryWithPendingTransaction(transaction *transfer.TransactionIdentity, timestamp int64, activityType Type, activityStatus Status) Entry { return newActivityEntryWithTransaction(true, transaction, timestamp, activityType, activityStatus) } @@ -576,9 +590,11 @@ const ( ) type FilterDependencies struct { - db *sql.DB - accountsDb *accounts.Database - tokenSymbol func(token Token) string + db *sql.DB + accountsDb *accounts.Database + // use token.TokenType, token.ChainID and token.Address to find the available symbol + tokenSymbol func(token Token) string + // use the chainID and symbol to look up token.TokenType and token.Address. Return nil if not found tokenFromSymbol func(chainID *common.ChainID, symbol string) *Token } @@ -737,7 +753,6 @@ func getActivityEntries(ctx context.Context, deps FilterDependencies, addresses // Can be mapped directly because the values are injected into the query activityStatus := Status(aggregatedStatus) - var tokenOut, tokenIn *Token var outChainID, inChainID *common.ChainID var entry Entry var tokenID TokenID @@ -761,22 +776,27 @@ func getActivityEntries(ctx context.Context, deps FilterDependencies, addresses involvedToken = &Token{TokenType: Native, ChainID: common.ChainID(chainID.Int64), TokenID: tokenID} } - if activityType == SendAT { - tokenOut = involvedToken - outChainID = new(common.ChainID) - *outChainID = common.ChainID(chainID.Int64) - } else { - tokenIn = involvedToken - inChainID = new(common.ChainID) - *inChainID = common.ChainID(chainID.Int64) - } - entry = newActivityEntryWithSimpleTransaction( &transfer.TransactionIdentity{ChainID: common.ChainID(chainID.Int64), Hash: eth.BytesToHash(transferHash), Address: ownerAddress, }, - timestamp, activityType, activityStatus) + timestamp, activityType, activityStatus, + ) + + // Extract tokens + if activityType == SendAT { + entry.tokenOut = involvedToken + outChainID = new(common.ChainID) + *outChainID = common.ChainID(chainID.Int64) + } else { + entry.tokenIn = involvedToken + inChainID = new(common.ChainID) + *inChainID = common.ChainID(chainID.Int64) + } + + entry.symbolOut, entry.symbolIn = lookupAndFillInTokens(deps, entry.tokenOut, entry.tokenIn) + // Complete the data entry.amountOut = outAmount entry.amountIn = inAmount @@ -786,11 +806,6 @@ func getActivityEntries(ctx context.Context, deps FilterDependencies, addresses inAmount, outAmount := getTrInAndOutAmounts(activityType, dbTrAmount) - // Extract tokens - if tokenCode.Valid { - cID := common.ChainID(chainID.Int64) - tokenOut = deps.tokenFromSymbol(&cID, tokenCode.String) - } outChainID = new(common.ChainID) *outChainID = common.ChainID(chainID.Int64) @@ -798,10 +813,20 @@ func getActivityEntries(ctx context.Context, deps FilterDependencies, addresses &transfer.TransactionIdentity{ChainID: common.ChainID(chainID.Int64), Hash: eth.BytesToHash(pendingHash), }, - timestamp, activityType, activityStatus) + timestamp, activityType, activityStatus, + ) + + // Extract tokens + if tokenCode.Valid { + cID := common.ChainID(chainID.Int64) + entry.tokenOut = deps.tokenFromSymbol(&cID, tokenCode.String) + } + entry.symbolOut, entry.symbolIn = lookupAndFillInTokens(deps, entry.tokenOut, nil) + // Complete the data entry.amountOut = outAmount entry.amountIn = inAmount + } else if multiTxID.Valid { mtInAmount, mtOutAmount := getMtInAndOutAmounts(dbMtFromAmount, dbMtToAmount) @@ -817,25 +842,27 @@ func getActivityEntries(ctx context.Context, deps FilterDependencies, addresses *inChainID = common.ChainID(inChainIDDB.Int64) } - // Extract tokens - if fromTokenCode.Valid { - tokenOut = deps.tokenFromSymbol(outChainID, fromTokenCode.String) - } - if toTokenCode.Valid { - tokenIn = deps.tokenFromSymbol(inChainID, toTokenCode.String) - } - entry = NewActivityEntryWithMultiTransaction(transfer.MultiTransactionIDType(multiTxID.Int64), timestamp, activityType, activityStatus) + + // Extract tokens + if fromTokenCode.Valid { + entry.tokenOut = deps.tokenFromSymbol(outChainID, fromTokenCode.String) + entry.symbolOut = newAndSet(fromTokenCode.String) + } + if toTokenCode.Valid { + entry.tokenIn = deps.tokenFromSymbol(inChainID, toTokenCode.String) + entry.symbolIn = newAndSet(toTokenCode.String) + } + // Complete the data entry.amountOut = mtOutAmount entry.amountIn = mtInAmount } else { return nil, errors.New("invalid row data") } + // Complete common data - entry.tokenOut = tokenOut - entry.tokenIn = tokenIn entry.sender = &fromAddress entry.recipient = &toAddress entry.sender = &fromAddress @@ -955,3 +982,19 @@ func updateKeypairsAccountsTable(accountsDb *accounts.Database, db *sql.DB) erro return nil } + +func lookupAndFillInTokens(deps FilterDependencies, tokenOut *Token, tokenIn *Token) (symbolOut *string, symbolIn *string) { + if tokenOut != nil { + symbol := deps.tokenSymbol(*tokenOut) + if len(symbol) > 0 { + symbolOut = newAndSet(symbol) + } + } + if tokenIn != nil { + symbol := deps.tokenSymbol(*tokenIn) + if len(symbol) > 0 { + symbolIn = newAndSet(symbol) + } + } + return symbolOut, symbolIn +} diff --git a/services/wallet/activity/activity_test.go b/services/wallet/activity/activity_test.go index 69e26ffbb..5e0de7ffa 100644 --- a/services/wallet/activity/activity_test.go +++ b/services/wallet/activity/activity_test.go @@ -225,6 +225,8 @@ func TestGetActivityEntriesAll(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(0)), tokenOut: TTrToToken(t, &td.tr1.TestTransaction), tokenIn: nil, + symbolOut: newAndSet("ETH"), + symbolIn: nil, sender: &td.tr1.From, recipient: &td.tr1.To, chainIDOut: &td.tr1.ChainID, @@ -242,6 +244,8 @@ func TestGetActivityEntriesAll(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(0)), tokenOut: TTrToToken(t, &td.pendingTr.TestTransaction), tokenIn: nil, + symbolOut: newAndSet("ETH"), + symbolIn: nil, sender: &td.pendingTr.From, recipient: &td.pendingTr.To, chainIDOut: &td.pendingTr.ChainID, @@ -259,6 +263,8 @@ func TestGetActivityEntriesAll(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(td.multiTx1.ToAmount)), tokenOut: tokenFromSymbol(nil, td.multiTx1.FromToken), tokenIn: tokenFromSymbol(nil, td.multiTx1.ToToken), + symbolOut: newAndSet("USDC"), + symbolIn: newAndSet("DAI"), sender: &td.multiTx1.FromAddress, recipient: &td.multiTx1.ToAddress, }, entries[1]) @@ -271,6 +277,8 @@ func TestGetActivityEntriesAll(t *testing.T) { activityStatus: PendingAS, amountOut: (*hexutil.Big)(big.NewInt(td.multiTx2.FromAmount)), amountIn: (*hexutil.Big)(big.NewInt(td.multiTx2.ToAmount)), + symbolOut: newAndSet("USDC"), + symbolIn: newAndSet("SNT"), tokenOut: tokenFromSymbol(nil, td.multiTx2.FromToken), tokenIn: tokenFromSymbol(nil, td.multiTx2.ToToken), sender: &td.multiTx2.FromAddress, @@ -358,6 +366,8 @@ func TestGetActivityEntriesFilterByTime(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(0)), tokenOut: TTrToToken(t, &trs[5].TestTransaction), tokenIn: nil, + symbolOut: newAndSet("USDC"), + symbolIn: nil, sender: &trs[5].From, recipient: &trs[5].To, chainIDOut: &trs[5].ChainID, @@ -375,6 +385,8 @@ func TestGetActivityEntriesFilterByTime(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(td.multiTx1.ToAmount)), tokenOut: tokenFromSymbol(nil, td.multiTx1.FromToken), tokenIn: tokenFromSymbol(nil, td.multiTx1.ToToken), + symbolOut: newAndSet("USDC"), + symbolIn: newAndSet("DAI"), sender: &td.multiTx1.FromAddress, recipient: &td.multiTx1.ToAddress, chainIDOut: nil, @@ -400,6 +412,8 @@ func TestGetActivityEntriesFilterByTime(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(0)), tokenOut: TTrToToken(t, &trs[2].TestTransaction), tokenIn: nil, + symbolOut: newAndSet("ETH"), + symbolIn: nil, sender: &trs[2].From, recipient: &trs[2].To, chainIDOut: &trs[2].ChainID, @@ -417,6 +431,8 @@ func TestGetActivityEntriesFilterByTime(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(td.multiTx1.ToAmount)), tokenOut: tokenFromSymbol(nil, td.multiTx1.FromToken), tokenIn: tokenFromSymbol(nil, td.multiTx1.ToToken), + symbolOut: newAndSet("USDC"), + symbolIn: newAndSet("DAI"), sender: &td.multiTx1.FromAddress, recipient: &td.multiTx1.ToAddress, chainIDOut: nil, @@ -441,6 +457,8 @@ func TestGetActivityEntriesFilterByTime(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(0)), tokenOut: TTrToToken(t, &trs[2].TestTransaction), tokenIn: nil, + symbolOut: newAndSet("ETH"), + symbolIn: nil, sender: &trs[2].From, recipient: &trs[2].To, chainIDOut: &trs[2].ChainID, @@ -458,6 +476,8 @@ func TestGetActivityEntriesFilterByTime(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(0)), tokenOut: TTrToToken(t, &td.tr1.TestTransaction), tokenIn: nil, + symbolOut: newAndSet("ETH"), + symbolIn: nil, sender: &td.tr1.From, recipient: &td.tr1.To, chainIDOut: &td.tr1.ChainID, @@ -502,6 +522,8 @@ func TestGetActivityEntriesCheckOffsetAndLimit(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(0)), tokenOut: TTrToToken(t, &trs[8].TestTransaction), tokenIn: nil, + symbolOut: newAndSet("ETH"), + symbolIn: nil, sender: &trs[8].From, recipient: &trs[8].To, chainIDOut: &trs[8].ChainID, @@ -519,6 +541,8 @@ func TestGetActivityEntriesCheckOffsetAndLimit(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(0)), tokenOut: TTrToToken(t, &trs[6].TestTransaction), tokenIn: nil, + symbolOut: newAndSet("DAI"), + symbolIn: nil, sender: &trs[6].From, recipient: &trs[6].To, chainIDOut: &trs[6].ChainID, @@ -542,6 +566,8 @@ func TestGetActivityEntriesCheckOffsetAndLimit(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(0)), tokenOut: TTrToToken(t, &trs[6].TestTransaction), tokenIn: nil, + symbolOut: newAndSet("DAI"), + symbolIn: nil, sender: &trs[6].From, recipient: &trs[6].To, chainIDOut: &trs[6].ChainID, @@ -559,6 +585,8 @@ func TestGetActivityEntriesCheckOffsetAndLimit(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(0)), tokenOut: TTrToToken(t, &trs[4].TestTransaction), tokenIn: nil, + symbolOut: newAndSet("USDC"), + symbolIn: nil, sender: &trs[4].From, recipient: &trs[4].To, chainIDOut: &trs[4].ChainID, @@ -582,6 +610,8 @@ func TestGetActivityEntriesCheckOffsetAndLimit(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(0)), tokenOut: TTrToToken(t, &trs[2].TestTransaction), tokenIn: nil, + symbolOut: newAndSet("USDC"), + symbolIn: nil, sender: &trs[2].From, recipient: &trs[2].To, chainIDOut: &trs[2].ChainID, @@ -702,6 +732,8 @@ func TestGetActivityEntriesFilterByAddresses(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(trs[4].Value)), tokenOut: nil, tokenIn: TTrToToken(t, &trs[4].TestTransaction), + symbolOut: nil, + symbolIn: newAndSet("USDC"), sender: &trs[4].From, recipient: &trs[4].To, chainIDOut: nil, @@ -719,6 +751,8 @@ func TestGetActivityEntriesFilterByAddresses(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(0)), tokenOut: TTrToToken(t, &trs[1].TestTransaction), tokenIn: nil, + symbolOut: newAndSet("ETH"), + symbolIn: nil, sender: &trs[1].From, recipient: &trs[1].To, chainIDOut: &trs[1].ChainID, @@ -736,6 +770,8 @@ func TestGetActivityEntriesFilterByAddresses(t *testing.T) { amountIn: (*hexutil.Big)(big.NewInt(td.multiTx2.ToAmount)), tokenOut: tokenFromSymbol(nil, td.multiTx2.FromToken), tokenIn: tokenFromSymbol(nil, td.multiTx2.ToToken), + symbolOut: newAndSet("USDC"), + symbolIn: newAndSet("SNT"), sender: &td.multiTx2.FromAddress, recipient: &td.multiTx2.ToAddress, chainIDOut: nil,