fix: Handle balance for all accounts (#4261)

This commit is contained in:
Cuteivist 2023-11-29 12:20:18 +01:00 committed by GitHub
parent 3ab1afaae8
commit ecbb1cb4e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 217 additions and 102 deletions

View File

@ -132,8 +132,8 @@ func (api *API) FetchDecodedTxData(ctx context.Context, data string) (*thirdpart
}
// GetBalanceHistory retrieves token balance history for token identity on multiple chains
func (api *API) GetBalanceHistory(ctx context.Context, chainIDs []uint64, address common.Address, tokenSymbol string, currencySymbol string, timeInterval history.TimeInterval) ([]*history.ValuePoint, error) {
log.Debug("wallet.api.GetBalanceHistory", "chainIDs", chainIDs, "address", address, "tokenSymbol", tokenSymbol, "currencySymbol", currencySymbol, "timeInterval", timeInterval)
func (api *API) GetBalanceHistory(ctx context.Context, chainIDs []uint64, addresses []common.Address, tokenSymbol string, currencySymbol string, timeInterval history.TimeInterval) ([]*history.ValuePoint, error) {
log.Debug("wallet.api.GetBalanceHistory", "chainIDs", chainIDs, "address", addresses, "tokenSymbol", tokenSymbol, "currencySymbol", currencySymbol, "timeInterval", timeInterval)
var fromTimestamp uint64
now := uint64(time.Now().UTC().Unix())
@ -152,14 +152,14 @@ func (api *API) GetBalanceHistory(ctx context.Context, chainIDs []uint64, addres
return nil, fmt.Errorf("unknown time interval: %v", timeInterval)
}
return api.GetBalanceHistoryRange(ctx, chainIDs, address, tokenSymbol, currencySymbol, fromTimestamp, now)
return api.GetBalanceHistoryRange(ctx, chainIDs, addresses, tokenSymbol, currencySymbol, fromTimestamp, now)
}
// GetBalanceHistoryRange retrieves token balance history for token identity on multiple chains for a time range
// 'toTimestamp' is ignored for now, but will be used in the future to limit the range of the history
func (api *API) GetBalanceHistoryRange(ctx context.Context, chainIDs []uint64, address common.Address, tokenSymbol string, currencySymbol string, fromTimestamp uint64, _ uint64) ([]*history.ValuePoint, error) {
log.Debug("wallet.api.GetBalanceHistoryRange", "chainIDs", chainIDs, "address", address, "tokenSymbol", tokenSymbol, "currencySymbol", currencySymbol, "fromTimestamp", fromTimestamp)
return api.s.history.GetBalanceHistory(ctx, chainIDs, address, tokenSymbol, currencySymbol, fromTimestamp)
func (api *API) GetBalanceHistoryRange(ctx context.Context, chainIDs []uint64, addresses []common.Address, tokenSymbol string, currencySymbol string, fromTimestamp uint64, _ uint64) ([]*history.ValuePoint, error) {
log.Debug("wallet.api.GetBalanceHistoryRange", "chainIDs", chainIDs, "address", addresses, "tokenSymbol", tokenSymbol, "currencySymbol", currencySymbol, "fromTimestamp", fromTimestamp)
return api.s.history.GetBalanceHistory(ctx, chainIDs, addresses, tokenSymbol, currencySymbol, fromTimestamp)
}
func (api *API) GetTokenList(ctx context.Context) ([]*token.List, error) {

View File

@ -58,10 +58,10 @@ func NewBalance(db *BalanceDB) *Balance {
}
// get returns the balance history for the given address from the given timestamp till now
func (b *Balance) get(ctx context.Context, chainID uint64, currency string, address common.Address, fromTimestamp uint64) ([]*entry, error) {
log.Debug("Getting balance history", "chainID", chainID, "currency", currency, "address", address, "fromTimestamp", fromTimestamp)
func (b *Balance) get(ctx context.Context, chainID uint64, currency string, addresses []common.Address, fromTimestamp uint64) ([]*entry, error) {
log.Debug("Getting balance history", "chainID", chainID, "currency", currency, "address", addresses, "fromTimestamp", fromTimestamp)
cached, err := b.db.getNewerThan(&assetIdentity{chainID, address, currency}, fromTimestamp)
cached, err := b.db.getNewerThan(&assetIdentity{chainID, addresses, currency}, fromTimestamp)
if err != nil {
return nil, err
}
@ -69,69 +69,85 @@ func (b *Balance) get(ctx context.Context, chainID uint64, currency string, addr
return cached, nil
}
func (b *Balance) addEdgePoints(chainID uint64, currency string, address common.Address, fromTimestamp, toTimestamp uint64, data []*entry) (res []*entry, err error) {
log.Debug("Adding edge points", "chainID", chainID, "currency", currency, "address", address, "fromTimestamp", fromTimestamp)
func (b *Balance) addEdgePoints(chainID uint64, currency string, addresses []common.Address, fromTimestamp, toTimestamp uint64, data []*entry) (res []*entry, err error) {
log.Debug("Adding edge points", "chainID", chainID, "currency", currency, "address", addresses, "fromTimestamp", fromTimestamp)
var firstEntry *entry
res = data
if len(data) > 0 {
firstEntry = data[0]
} else {
firstEntry = &entry{
chainID: chainID,
address: address,
tokenSymbol: currency,
timestamp: int64(fromTimestamp),
for _, address := range addresses {
var firstEntry *entry
if len(data) > 0 {
for _, entry := range data {
if entry.address == address {
firstEntry = entry
break
}
}
}
}
previous, err := b.db.getEntryPreviousTo(firstEntry)
if err != nil {
return nil, err
}
firstTimestamp, lastTimestamp := timestampBoundaries(fromTimestamp, toTimestamp, data)
if previous != nil {
previous.timestamp = int64(firstTimestamp) // We might need to use another minimal offset respecting the time interval
previous.block = nil
res = append([]*entry{previous}, data...)
} else {
// Add a zero point at the beginning to draw a line from
res = append([]*entry{
{
if firstEntry == nil {
firstEntry = &entry{
chainID: chainID,
address: address,
tokenSymbol: currency,
timestamp: int64(firstTimestamp),
balance: big.NewInt(0),
},
}, data...)
}
timestamp: int64(fromTimestamp),
}
}
if res[len(res)-1].timestamp < int64(lastTimestamp) {
// Add a last point to draw a line to
res = append(res, &entry{
chainID: chainID,
address: address,
tokenSymbol: currency,
timestamp: int64(lastTimestamp),
balance: res[len(res)-1].balance,
})
previous, err := b.db.getEntryPreviousTo(firstEntry)
if err != nil {
return nil, err
}
firstTimestamp, lastTimestamp := timestampBoundaries(fromTimestamp, toTimestamp, address, data)
if previous != nil {
previous.timestamp = int64(firstTimestamp) // We might need to use another minimal offset respecting the time interval
previous.block = nil
res = append([]*entry{previous}, res...)
} else {
// Add a zero point at the beginning to draw a line from
res = append([]*entry{
{
chainID: chainID,
address: address,
tokenSymbol: currency,
timestamp: int64(firstTimestamp),
balance: big.NewInt(0),
},
}, res...)
}
if res[len(res)-1].timestamp < int64(lastTimestamp) {
// Add a last point to draw a line to
res = append(res, &entry{
chainID: chainID,
address: address,
tokenSymbol: currency,
timestamp: int64(lastTimestamp),
balance: res[len(res)-1].balance,
})
}
}
return res, nil
}
func timestampBoundaries(fromTimestamp, toTimestamp uint64, data []*entry) (firstTimestamp, lastTimestamp uint64) {
func timestampBoundaries(fromTimestamp, toTimestamp uint64, address common.Address, data []*entry) (firstTimestamp, lastTimestamp uint64) {
firstTimestamp = fromTimestamp
if fromTimestamp == 0 {
if len(data) > 0 {
if data[0].timestamp == 0 {
panic("data[0].timestamp must never be 0")
for _, entry := range data {
if entry.address == address {
if entry.timestamp == 0 {
panic("data[0].timestamp must never be 0")
}
firstTimestamp = uint64(entry.timestamp) - 1
break
}
}
firstTimestamp = uint64(data[0].timestamp) - 1
} else {
}
if firstTimestamp == fromTimestamp {
firstTimestamp = genesisTimestamp
}
}
@ -145,8 +161,8 @@ func timestampBoundaries(fromTimestamp, toTimestamp uint64, data []*entry) (firs
return firstTimestamp, lastTimestamp
}
func addPaddingPoints(currency string, address common.Address, toTimestamp uint64, data []*entry, limit int) (res []*entry, err error) {
log.Debug("addPaddingPoints start", "currency", currency, "address", address, "len(data)", len(data), "data", data, "limit", limit)
func addPaddingPoints(currency string, addresses []common.Address, toTimestamp uint64, data []*entry, limit int) (res []*entry, err error) {
log.Debug("addPaddingPoints start", "currency", currency, "address", addresses, "len(data)", len(data), "data", data, "limit", limit)
if len(data) < 2 { // Edge points must be added separately during the previous step
return nil, errors.New("slice is empty")
@ -162,6 +178,11 @@ func addPaddingPoints(currency string, address common.Address, toTimestamp uint6
res = make([]*entry, len(data))
copy(res, data)
var address common.Address
if len(addresses) > 0 {
address = addresses[0]
}
for i, j, index := 1, 0, 0; len(res) < limit; index++ {
// Add a last point to draw a line to. For some cases we might not need it,
// but when merging with points from other chains, we might get wrong balance if we don't have it.

View File

@ -2,6 +2,7 @@ package history
import (
"database/sql"
"encoding/hex"
"fmt"
"math/big"
@ -33,10 +34,23 @@ type entry struct {
type assetIdentity struct {
ChainID uint64
Address common.Address
Addresses []common.Address
TokenSymbol string
}
func (a *assetIdentity) addressesToString() string {
var addressesStr string
for i, address := range a.Addresses {
addressStr := hex.EncodeToString(address[:])
if i == 0 {
addressesStr = "X'" + addressStr + "'"
} else {
addressesStr += ", X'" + addressStr + "'"
}
}
return addressesStr
}
func (e *entry) String() string {
return fmt.Sprintf("chainID: %v, address: %v, tokenSymbol: %v, tokenAddress: %v, block: %v, timestamp: %v, balance: %v",
e.chainID, e.address, e.tokenSymbol, e.tokenAddress, e.block, e.timestamp, e.balance)
@ -87,8 +101,9 @@ func (b *BalanceDB) getEntriesWithoutBalances(chainID uint64, address common.Add
func (b *BalanceDB) getNewerThan(identity *assetIdentity, timestamp uint64) (entries []*entry, err error) {
// DISTINCT removes duplicates that can happen when a block has multiple transfers of same token
rawQueryStr := "SELECT DISTINCT block, timestamp, balance FROM balance_history WHERE chain_id = ? AND address = ? AND currency = ? AND timestamp > ? ORDER BY timestamp"
rows, err := b.db.Query(rawQueryStr, identity.ChainID, identity.Address, identity.TokenSymbol, timestamp)
rawQueryStr := "SELECT DISTINCT block, timestamp, balance, address FROM balance_history WHERE chain_id = ? AND address IN (%s) AND currency = ? AND timestamp > ? ORDER BY timestamp"
queryString := fmt.Sprintf(rawQueryStr, identity.addressesToString())
rows, err := b.db.Query(queryString, identity.ChainID, identity.TokenSymbol, timestamp)
if err == sql.ErrNoRows {
return nil, nil
} else if err != nil {
@ -101,12 +116,11 @@ func (b *BalanceDB) getNewerThan(identity *assetIdentity, timestamp uint64) (ent
for rows.Next() {
entry := &entry{
chainID: identity.ChainID,
address: identity.Address,
tokenSymbol: identity.TokenSymbol,
block: new(big.Int),
balance: new(big.Int),
}
err := rows.Scan((*bigint.SQLBigInt)(entry.block), &entry.timestamp, (*bigint.SQLBigIntBytes)(entry.balance))
err := rows.Scan((*bigint.SQLBigInt)(entry.block), &entry.timestamp, (*bigint.SQLBigIntBytes)(entry.balance), &entry.address)
if err != nil {
return nil, err
}

View File

@ -30,7 +30,7 @@ func dbWithEntries(t *testing.T, entries []*entry) *BalanceDB {
func TestBalance_addPaddingPoints(t *testing.T) {
type args struct {
currency string
address common.Address
addresses []common.Address
fromTimestamp uint64
currentTimestamp uint64
data []*entry
@ -46,7 +46,7 @@ func TestBalance_addPaddingPoints(t *testing.T) {
name: "addOnePaddingPointAtMiddle",
args: args{
currency: "ETH",
address: common.Address{1},
addresses: []common.Address{common.Address{1}},
fromTimestamp: 0,
currentTimestamp: 2,
data: []*entry{
@ -91,7 +91,7 @@ func TestBalance_addPaddingPoints(t *testing.T) {
name: "noPaddingEqualsLimit",
args: args{
currency: "ETH",
address: common.Address{1},
addresses: []common.Address{common.Address{1}},
fromTimestamp: 0,
currentTimestamp: 2,
data: []*entry{
@ -134,7 +134,7 @@ func TestBalance_addPaddingPoints(t *testing.T) {
name: "limitLessThanDataSize",
args: args{
currency: "ETH",
address: common.Address{1},
addresses: []common.Address{common.Address{1}},
fromTimestamp: 0,
currentTimestamp: 2,
data: []*entry{
@ -177,7 +177,7 @@ func TestBalance_addPaddingPoints(t *testing.T) {
name: "addMultiplePaddingPoints",
args: args{
currency: "ETH",
address: common.Address{1},
addresses: []common.Address{common.Address{1}},
fromTimestamp: 1,
currentTimestamp: 5,
data: []*entry{
@ -240,7 +240,7 @@ func TestBalance_addPaddingPoints(t *testing.T) {
name: "addMultiplePaddingPointsDuplicateTimestamps",
args: args{
currency: "ETH",
address: common.Address{1},
addresses: []common.Address{common.Address{1}},
fromTimestamp: 1,
currentTimestamp: 5,
data: []*entry{
@ -309,7 +309,7 @@ func TestBalance_addPaddingPoints(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotRes, err := addPaddingPoints(tt.args.currency, tt.args.address, tt.args.currentTimestamp, tt.args.data, tt.args.limit)
gotRes, err := addPaddingPoints(tt.args.currency, tt.args.addresses, tt.args.currentTimestamp, tt.args.data, tt.args.limit)
if (err != nil) != tt.wantErr {
t.Errorf("Balance.addPaddingPoints() error = %v, wantErr %v", err, tt.wantErr)
return
@ -331,7 +331,7 @@ func TestBalance_addEdgePoints(t *testing.T) {
type args struct {
chainID uint64
currency string
address common.Address
addresses []common.Address
fromTimestamp uint64
toTimestamp uint64
data []*entry
@ -351,7 +351,7 @@ func TestBalance_addEdgePoints(t *testing.T) {
args: args{
chainID: 111,
currency: "SNT",
address: common.Address{1},
addresses: []common.Address{common.Address{1}},
fromTimestamp: 1,
toTimestamp: 2,
data: []*entry{},
@ -382,7 +382,7 @@ func TestBalance_addEdgePoints(t *testing.T) {
args: args{
chainID: 111,
currency: "SNT",
address: common.Address{1},
addresses: []common.Address{common.Address{1}},
fromTimestamp: 0, // will set to genesisTimestamp
toTimestamp: genesisTimestamp + 1,
data: []*entry{},
@ -422,7 +422,7 @@ func TestBalance_addEdgePoints(t *testing.T) {
args: args{
chainID: 111,
currency: "SNT",
address: common.Address{1},
addresses: []common.Address{common.Address{1}},
fromTimestamp: 2,
toTimestamp: 4,
data: []*entry{
@ -477,7 +477,7 @@ func TestBalance_addEdgePoints(t *testing.T) {
b := &Balance{
db: tt.fields.db,
}
gotRes, err := b.addEdgePoints(tt.args.chainID, tt.args.currency, tt.args.address, tt.args.fromTimestamp, tt.args.toTimestamp, tt.args.data)
gotRes, err := b.addEdgePoints(tt.args.chainID, tt.args.currency, tt.args.addresses, tt.args.fromTimestamp, tt.args.toTimestamp, tt.args.data)
if (err != nil) != tt.wantErr {
t.Errorf("Balance.addEdgePoints() error = %v, wantErr %v", err, tt.wantErr)
return

View File

@ -108,8 +108,8 @@ func (s *Service) Start() {
}()
}
func (s *Service) mergeChainsBalances(chainIDs []uint64, address common.Address, tokenSymbol string, fromTimestamp uint64, data map[uint64][]*entry) ([]*DataPoint, error) {
log.Debug("Merging balances", "address", address, "tokenSymbol", tokenSymbol, "fromTimestamp", fromTimestamp, "len(data)", len(data))
func (s *Service) mergeChainsBalances(chainIDs []uint64, addresses []common.Address, tokenSymbol string, fromTimestamp uint64, data map[uint64][]*entry) ([]*DataPoint, error) {
log.Debug("Merging balances", "address", addresses, "tokenSymbol", tokenSymbol, "fromTimestamp", fromTimestamp, "len(data)", len(data))
toTimestamp := uint64(time.Now().UTC().Unix())
allData := make([]*entry, 0)
@ -118,7 +118,7 @@ func (s *Service) mergeChainsBalances(chainIDs []uint64, address common.Address,
// Iterate over chainIDs param, not data keys, because data may not contain all the chains, but we need edge points for all of them
for _, chainID := range chainIDs {
// edge points are needed to properly calculate total balance, as they contain the balance for the first and last timestamp
chainData, err := s.balance.addEdgePoints(chainID, tokenSymbol, address, fromTimestamp, toTimestamp, data[chainID])
chainData, err := s.balance.addEdgePoints(chainID, tokenSymbol, addresses, fromTimestamp, toTimestamp, data[chainID])
if err != nil {
return nil, err
}
@ -137,34 +137,60 @@ func (s *Service) mergeChainsBalances(chainIDs []uint64, address common.Address,
// Add padding points to make chart look nice
if len(allData) < minPointsForGraph {
allData, _ = addPaddingPoints(tokenSymbol, address, toTimestamp, allData, minPointsForGraph)
allData, _ = addPaddingPoints(tokenSymbol, addresses, toTimestamp, allData, minPointsForGraph)
}
return entriesToDataPoints(chainIDs, allData)
return entriesToDataPoints(allData)
}
// Expects sorted data
func entriesToDataPoints(chainIDs []uint64, data []*entry) ([]*DataPoint, error) {
func entriesToDataPoints(data []*entry) ([]*DataPoint, error) {
var resSlice []*DataPoint
var groupedEntries []*entry // Entries with the same timestamp
sumBalances := func(entries []*entry) *big.Int {
type AddressKey struct {
Address common.Address
ChainID uint64
}
sumBalances := func(balanceMap map[AddressKey]*big.Int) *big.Int {
// Sum balances of all accounts and chains in current timestamp
sum := big.NewInt(0)
for _, entry := range entries {
sum.Add(sum, entry.balance)
for _, balance := range balanceMap {
sum.Add(sum, balance)
}
return sum
}
// calculate balance for entries with the same timestam and add a single point for them
updateBalanceMap := func(balanceMap map[AddressKey]*big.Int, entries []*entry) map[AddressKey]*big.Int {
// Update balance map for this timestamp
for _, entry := range entries {
if entry.chainID == 0 {
continue
}
key := AddressKey{
Address: entry.address,
ChainID: entry.chainID,
}
balanceMap[key] = entry.balance
}
return balanceMap
}
// Balance map always contains current balance for each address in specific timestamp
// It is required to sum up balances from previous timestamp from accounts not present in current timestamp
balanceMap := make(map[AddressKey]*big.Int)
for _, entry := range data {
if len(groupedEntries) > 0 {
if entry.timestamp == groupedEntries[0].timestamp {
groupedEntries = append(groupedEntries, entry)
continue
} else {
// Calculate balance for the grouped entries
cumulativeBalance := sumBalances(groupedEntries)
// Split grouped entries into addresses
balanceMap = updateBalanceMap(balanceMap, groupedEntries)
// Calculate balance for all the addresses
cumulativeBalance := sumBalances(balanceMap)
// Points in slice contain balances for all chains
resSlice = appendPointToSlice(resSlice, &DataPoint{
Timestamp: uint64(groupedEntries[0].timestamp),
@ -182,7 +208,10 @@ func entriesToDataPoints(chainIDs []uint64, data []*entry) ([]*DataPoint, error)
// If only edge points are present, groupedEntries will be non-empty
if len(groupedEntries) > 0 {
cumulativeBalance := sumBalances(groupedEntries)
// Split grouped entries into addresses
balanceMap = updateBalanceMap(balanceMap, groupedEntries)
// Calculate balance for all the addresses
cumulativeBalance := sumBalances(balanceMap)
resSlice = appendPointToSlice(resSlice, &DataPoint{
Timestamp: uint64(groupedEntries[0].timestamp),
Balance: (*hexutil.Big)(cumulativeBalance),
@ -210,12 +239,12 @@ func appendPointToSlice(slice []*DataPoint, point *DataPoint) []*DataPoint {
}
// GetBalanceHistory returns token count balance
func (s *Service) GetBalanceHistory(ctx context.Context, chainIDs []uint64, address common.Address, tokenSymbol string, currencySymbol string, fromTimestamp uint64) ([]*ValuePoint, error) {
log.Debug("GetBalanceHistory", "chainIDs", chainIDs, "address", address.String(), "tokenSymbol", tokenSymbol, "currencySymbol", currencySymbol, "fromTimestamp", fromTimestamp)
func (s *Service) GetBalanceHistory(ctx context.Context, chainIDs []uint64, addresses []common.Address, tokenSymbol string, currencySymbol string, fromTimestamp uint64) ([]*ValuePoint, error) {
log.Debug("GetBalanceHistory", "chainIDs", chainIDs, "address", addresses, "tokenSymbol", tokenSymbol, "currencySymbol", currencySymbol, "fromTimestamp", fromTimestamp)
chainDataMap := make(map[uint64][]*entry)
for _, chainID := range chainIDs {
chainData, err := s.balance.get(ctx, chainID, tokenSymbol, address, fromTimestamp) // TODO Make chainID a slice?
chainData, err := s.balance.get(ctx, chainID, tokenSymbol, addresses, fromTimestamp) // TODO Make chainID a slice?
if err != nil {
return nil, err
}
@ -228,7 +257,8 @@ func (s *Service) GetBalanceHistory(ctx context.Context, chainIDs []uint64, addr
}
// Need to get balance for all the chains for the first timestamp, otherwise total values will be incorrect
data, err := s.mergeChainsBalances(chainIDs, address, tokenSymbol, fromTimestamp, chainDataMap)
data, err := s.mergeChainsBalances(chainIDs, addresses, tokenSymbol, fromTimestamp, chainDataMap)
if err != nil {
return nil, err
} else if len(data) == 0 {

View File

@ -5,13 +5,13 @@ import (
"reflect"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
func Test_entriesToDataPoints(t *testing.T) {
type args struct {
chainIDs []uint64
data []*entry
data []*entry
}
tests := []struct {
name string
@ -22,7 +22,6 @@ func Test_entriesToDataPoints(t *testing.T) {
{
name: "zeroAllChainsSameTimestamp",
args: args{
chainIDs: []uint64{1, 2},
data: []*entry{
{
chainID: 1,
@ -49,7 +48,6 @@ func Test_entriesToDataPoints(t *testing.T) {
{
name: "oneZeroAllChainsDifferentTimestamp",
args: args{
chainIDs: []uint64{1, 2},
data: []*entry{
{
chainID: 2,
@ -80,7 +78,6 @@ func Test_entriesToDataPoints(t *testing.T) {
{
name: "nonZeroAllChainsDifferentTimestamp",
args: args{
chainIDs: []uint64{1, 2},
data: []*entry{
{
chainID: 2,
@ -100,7 +97,7 @@ func Test_entriesToDataPoints(t *testing.T) {
Timestamp: 1,
},
{
Balance: (*hexutil.Big)(big.NewInt(2)),
Balance: (*hexutil.Big)(big.NewInt(3)),
Timestamp: 2,
},
},
@ -109,7 +106,6 @@ func Test_entriesToDataPoints(t *testing.T) {
{
name: "sameChainDifferentTimestamp",
args: args{
chainIDs: []uint64{1, 2},
data: []*entry{
{
chainID: 1,
@ -149,7 +145,6 @@ func Test_entriesToDataPoints(t *testing.T) {
{
name: "sameChainDifferentTimestampOtherChainsEmpty",
args: args{
chainIDs: []uint64{1, 2},
data: []*entry{
{
chainID: 1,
@ -195,7 +190,6 @@ func Test_entriesToDataPoints(t *testing.T) {
{
name: "onlyEdgePointsOnManyChainsWithPadding",
args: args{
chainIDs: []uint64{1, 2, 3},
data: []*entry{
// Left edge - same timestamp
{
@ -271,11 +265,67 @@ func Test_entriesToDataPoints(t *testing.T) {
},
wantErr: false,
},
{
name: "multipleAddresses",
args: args{
data: []*entry{
{
chainID: 2,
balance: big.NewInt(5),
timestamp: 1,
address: common.Address{1},
},
{
chainID: 1,
balance: big.NewInt(6),
timestamp: 1,
address: common.Address{2},
},
{
chainID: 1,
balance: big.NewInt(1),
timestamp: 2,
address: common.Address{1},
},
{
chainID: 1,
balance: big.NewInt(2),
timestamp: 3,
address: common.Address{2},
},
{
chainID: 1,
balance: big.NewInt(4),
timestamp: 4,
address: common.Address{2},
},
},
},
want: []*DataPoint{
{
Balance: (*hexutil.Big)(big.NewInt(11)),
Timestamp: 1,
},
{
Balance: (*hexutil.Big)(big.NewInt(12)),
Timestamp: 2,
},
{
Balance: (*hexutil.Big)(big.NewInt(8)),
Timestamp: 3,
},
{
Balance: (*hexutil.Big)(big.NewInt(10)),
Timestamp: 4,
},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := entriesToDataPoints(tt.args.chainIDs, tt.args.data)
got, err := entriesToDataPoints(tt.args.data)
if (err != nil) != tt.wantErr {
t.Errorf("entriesToDataPoints() error = %v, wantErr %v", err, tt.wantErr)
return