hermez-node/api/account_test.go
api/account_test.goRaw
1package api
2
3import (
4 "fmt"
5 "strconv"
6 "testing"
7
8 "github.com/hermeznetwork/hermez-node/apitypes"
9 "github.com/hermeznetwork/hermez-node/common"
10 "github.com/hermeznetwork/hermez-node/db/historydb"
11 "github.com/mitchellh/copystructure"
12 "github.com/stretchr/testify/assert"
13 "github.com/stretchr/testify/require"
14)
15
16type testAccount struct {
17 ItemID uint64 `json:"itemId"`
18 Idx apitypes.HezIdx `json:"accountIndex"`
19 BatchNum common.BatchNum `json:"batchNum"`
20 PublicKey apitypes.HezBJJ `json:"bjj"`
21 EthAddr apitypes.HezEthAddr `json:"hezEthereumAddress"`
22 Nonce common.Nonce `json:"nonce"`
23 Balance *apitypes.BigIntStr `json:"balance"`
24 Token historydb.TokenWithUSD `json:"token"`
25}
26
27type testAccountsResponse struct {
28 Accounts []testAccount `json:"accounts"`
29 PendingItems uint64 `json:"pendingItems"`
30}
31
32func (t testAccountsResponse) GetPending() (pendingItems, lastItemID uint64) {
33 pendingItems = t.PendingItems
34 lastItemID = t.Accounts[len(t.Accounts)-1].ItemID
35 return pendingItems, lastItemID
36}
37
38func (t *testAccountsResponse) Len() int { return len(t.Accounts) }
39
40func (t testAccountsResponse) New() Pendinger { return &testAccountsResponse{} }
41
42func genTestAccounts(accounts []common.Account, tokens []historydb.TokenWithUSD) []testAccount {
43 tAccounts := []testAccount{}
44 for x, account := range accounts {
45 token := getTokenByID(account.TokenID, tokens)
46 tAccount := testAccount{
47 ItemID: uint64(x + 1),
48 Idx: apitypes.HezIdx(idxToHez(account.Idx, token.Symbol)),
49 PublicKey: apitypes.NewHezBJJ(account.BJJ),
50 EthAddr: apitypes.NewHezEthAddr(account.EthAddr),
51 Nonce: account.Nonce,
52 Balance: apitypes.NewBigIntStr(account.Balance),
53 Token: token,
54 }
55 tAccounts = append(tAccounts, tAccount)
56 }
57 return tAccounts
58}
59
60func TestGetAccounts(t *testing.T) {
61 endpoint := apiURL + "accounts"
62 fetchedAccounts := []testAccount{}
63
64 appendIter := func(intr interface{}) {
65 for i := 0; i < len(intr.(*testAccountsResponse).Accounts); i++ {
66 tmp, err := copystructure.Copy(intr.(*testAccountsResponse).Accounts[i])
67 if err != nil {
68 panic(err)
69 }
70 fetchedAccounts = append(fetchedAccounts, tmp.(testAccount))
71 }
72 }
73
74 limit := 5
75 stringIds := strconv.Itoa(int(tc.tokens[2].TokenID)) + "," + strconv.Itoa(int(tc.tokens[5].TokenID)) + "," + strconv.Itoa(int(tc.tokens[6].TokenID))
76
77 // Filter by BJJ
78 path := fmt.Sprintf("%s?BJJ=%s&limit=%d", endpoint, tc.accounts[0].PublicKey, limit)
79 err := doGoodReqPaginated(path, historydb.OrderAsc, &testAccountsResponse{}, appendIter)
80 require.NoError(t, err)
81 assert.Greater(t, len(fetchedAccounts), 0)
82 assert.LessOrEqual(t, len(fetchedAccounts), len(tc.accounts))
83 fetchedAccounts = []testAccount{}
84 // Filter by ethAddr
85 path = fmt.Sprintf("%s?hezEthereumAddress=%s&limit=%d", endpoint, tc.accounts[3].EthAddr, limit)
86 err = doGoodReqPaginated(path, historydb.OrderAsc, &testAccountsResponse{}, appendIter)
87 require.NoError(t, err)
88 assert.Greater(t, len(fetchedAccounts), 0)
89 assert.LessOrEqual(t, len(fetchedAccounts), len(tc.accounts))
90 fetchedAccounts = []testAccount{}
91 // both filters (incompatible)
92 path = fmt.Sprintf("%s?hezEthereumAddress=%s&BJJ=%s&limit=%d", endpoint, tc.accounts[0].EthAddr, tc.accounts[0].PublicKey, limit)
93 err = doBadReq("GET", path, nil, 400)
94 require.NoError(t, err)
95 fetchedAccounts = []testAccount{}
96 // Filter by token IDs
97 path = fmt.Sprintf("%s?tokenIds=%s&limit=%d", endpoint, stringIds, limit)
98 err = doGoodReqPaginated(path, historydb.OrderAsc, &testAccountsResponse{}, appendIter)
99 require.NoError(t, err)
100 assert.Greater(t, len(fetchedAccounts), 0)
101 assert.LessOrEqual(t, len(fetchedAccounts), len(tc.accounts))
102 fetchedAccounts = []testAccount{}
103 // Token Ids + bjj
104 path = fmt.Sprintf("%s?tokenIds=%s&BJJ=%s&limit=%d", endpoint, stringIds, tc.accounts[10].PublicKey, limit)
105 err = doGoodReqPaginated(path, historydb.OrderAsc, &testAccountsResponse{}, appendIter)
106 require.NoError(t, err)
107 assert.Greater(t, len(fetchedAccounts), 0)
108 assert.LessOrEqual(t, len(fetchedAccounts), len(tc.accounts))
109 fetchedAccounts = []testAccount{}
110 // No filters (checks response content)
111 path = fmt.Sprintf("%s?limit=%d", endpoint, limit)
112 err = doGoodReqPaginated(path, historydb.OrderAsc, &testAccountsResponse{}, appendIter)
113 require.NoError(t, err)
114 assert.Equal(t, len(tc.accounts), len(fetchedAccounts))
115 for i := 0; i < len(fetchedAccounts); i++ {
116 fetchedAccounts[i].Token.ItemID = 0
117 if tc.accounts[i].Token.USDUpdate != nil {
118 assert.Less(t, fetchedAccounts[i].Token.USDUpdate.Unix()-3, tc.accounts[i].Token.USDUpdate.Unix())
119 fetchedAccounts[i].Token.USDUpdate = tc.accounts[i].Token.USDUpdate
120 }
121 assert.Equal(t, tc.accounts[i], fetchedAccounts[i])
122 }
123
124 // No filters Reverse Order (checks response content)
125 reversedAccounts := []testAccount{}
126 appendIter = func(intr interface{}) {
127 for i := 0; i < len(intr.(*testAccountsResponse).Accounts); i++ {
128 tmp, err := copystructure.Copy(intr.(*testAccountsResponse).Accounts[i])
129 if err != nil {
130 panic(err)
131 }
132 reversedAccounts = append(reversedAccounts, tmp.(testAccount))
133 }
134 }
135 err = doGoodReqPaginated(path, historydb.OrderDesc, &testAccountsResponse{}, appendIter)
136 require.NoError(t, err)
137 assert.Equal(t, len(reversedAccounts), len(fetchedAccounts))
138 for i := 0; i < len(fetchedAccounts); i++ {
139 reversedAccounts[i].Token.ItemID = 0
140 fetchedAccounts[len(fetchedAccounts)-1-i].Token.ItemID = 0
141 if reversedAccounts[i].Token.USDUpdate != nil {
142 assert.Less(t, fetchedAccounts[len(fetchedAccounts)-1-i].Token.USDUpdate.Unix()-3, reversedAccounts[i].Token.USDUpdate.Unix())
143 fetchedAccounts[len(fetchedAccounts)-1-i].Token.USDUpdate = reversedAccounts[i].Token.USDUpdate
144 }
145 assert.Equal(t, reversedAccounts[i], fetchedAccounts[len(fetchedAccounts)-1-i])
146 }
147
148 // 400
149 path = fmt.Sprintf("%s?hezEthereumAddress=hez:0x123456", endpoint)
150 err = doBadReq("GET", path, nil, 400)
151 require.NoError(t, err)
152
153 // Test GetAccount
154 path = fmt.Sprintf("%s/%s", endpoint, fetchedAccounts[2].Idx)
155 account := testAccount{}
156 require.NoError(t, doGoodReq("GET", path, nil, &account))
157 account.Token.ItemID = 0
158 assert.Equal(t, fetchedAccounts[2], account)
159
160 // 400
161 path = fmt.Sprintf("%s/hez:12345", endpoint)
162 err = doBadReq("GET", path, nil, 400)
163 require.NoError(t, err)
164 // 404
165 path = fmt.Sprintf("%s/hez:10:12345", endpoint)
166 err = doBadReq("GET", path, nil, 404)
167 require.NoError(t, err)
168}