@exodus/ethereum-api 2.8.2 → 2.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -3
- package/src/eth-like-util.js +7 -0
- package/src/exodus-eth-server/api.js +6 -0
- package/src/exodus-eth-server/ws.js +18 -8
- package/src/index.js +4 -0
- package/src/tx-log/__tests__/asset-client-interface-test-helper.js +22 -0
- package/src/tx-log/__tests__/assets-for-test-helper.js +30 -0
- package/src/tx-log/__tests__/bsc-history-return-values-for-test-helper.js +94 -0
- package/src/tx-log/__tests__/bsc-monitor.integration.test.js +166 -0
- package/src/tx-log/__tests__/bsc-monitor.test.js +184 -0
- package/src/tx-log/__tests__/ethereum-history-return-values-for-test-helper.js +357 -0
- package/src/tx-log/__tests__/ethereum-monitor.integration.test.js +174 -0
- package/src/tx-log/__tests__/ethereum-monitor.test.js +160 -0
- package/src/tx-log/__tests__/in-memory-asset-client-interface.js +196 -0
- package/src/tx-log/ethereum-monitor.js +271 -0
- package/src/tx-log/index.js +1 -0
- package/src/tx-log/ws-updates.js +75 -0
- package/src/websocket/index.js +23 -3
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
'0xf6c138c36341138ddfc314a11038da8264b7ef09': [
|
|
3
|
+
[
|
|
4
|
+
{
|
|
5
|
+
blockHash: '0x1a7886725a5ebc312d7e407f20988d972fbbbfeabf8b6a98564345aee87e3481',
|
|
6
|
+
blockNumber: '0xe1f4b7',
|
|
7
|
+
timestamp: '0x6286ec8e',
|
|
8
|
+
confirmations: 3712,
|
|
9
|
+
addressIndex: 0,
|
|
10
|
+
hash: '0x2f613acaebb34300a5c1bb25e2fa1c92f48cea469066fedb067d734292f31812',
|
|
11
|
+
nonce: '0x3',
|
|
12
|
+
gasPrice: '0x42426923b',
|
|
13
|
+
gas: '0x5208',
|
|
14
|
+
gasUsed: '0x5208',
|
|
15
|
+
to: '0xf6c138c36341138ddfc314a11038da8264b7ef09',
|
|
16
|
+
from: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
17
|
+
value: '0x1d3353f4626400',
|
|
18
|
+
status: 1,
|
|
19
|
+
error: null,
|
|
20
|
+
internal: [],
|
|
21
|
+
erc20: [],
|
|
22
|
+
erc721: [],
|
|
23
|
+
data: '0x',
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
[],
|
|
27
|
+
],
|
|
28
|
+
'0x90e481d9a664ebbe4be180d9501962255463036d': [
|
|
29
|
+
[
|
|
30
|
+
{
|
|
31
|
+
blockHash: '0x5a28482e44696447a9c2877e4a1493705c27482e22eefbac63cae58e812c6313',
|
|
32
|
+
blockNumber: '0xddae7e',
|
|
33
|
+
timestamp: '0x624ca889',
|
|
34
|
+
confirmations: 283833,
|
|
35
|
+
addressIndex: 0,
|
|
36
|
+
hash: '0x9c700813589ecbb5305305fd8ff39f318bc9908b20c1c08b76e0d6578daf8289',
|
|
37
|
+
nonce: '0x36b824',
|
|
38
|
+
gasPrice: '0x136d414d3c',
|
|
39
|
+
gas: '0x16e8c',
|
|
40
|
+
gasUsed: '0xf6dd',
|
|
41
|
+
to: '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
|
42
|
+
from: '0x2faf487a4414fe77e2327f0bf4ae2a264a776ad2',
|
|
43
|
+
value: '0x0',
|
|
44
|
+
status: 1,
|
|
45
|
+
error: null,
|
|
46
|
+
internal: [],
|
|
47
|
+
erc20: [
|
|
48
|
+
{
|
|
49
|
+
events: true,
|
|
50
|
+
address: '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
|
51
|
+
from: '0x2faf487a4414fe77e2327f0bf4ae2a264a776ad2',
|
|
52
|
+
to: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
53
|
+
value: '0xeafc0',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
erc721: [],
|
|
57
|
+
data:
|
|
58
|
+
'0xa9059cbb00000000000000000000000090e481d9a664ebbe4be180d9501962255463036d00000000000000000000000000000000000000000000000000000000000eafc0',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
blockHash: '0x2395c945108e1ba52586452aee9cd5692e3d08b07414b1c79bca1f91654f5787',
|
|
62
|
+
blockNumber: '0xddae88',
|
|
63
|
+
timestamp: '0x624ca904',
|
|
64
|
+
confirmations: 283823,
|
|
65
|
+
addressIndex: 1,
|
|
66
|
+
hash: '0xa1f9837b6c8cb55ad5b321a94357c1c1860c35916737532c6ea9b644fd172985',
|
|
67
|
+
nonce: '0x192b7e',
|
|
68
|
+
gasPrice: '0x116331c285',
|
|
69
|
+
gas: '0xf618',
|
|
70
|
+
gasUsed: '0x5208',
|
|
71
|
+
to: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
72
|
+
from: '0xc098b2a3aa256d2140208c3de6543aaef5cd3a94',
|
|
73
|
+
value: '0x3202a822f86c00',
|
|
74
|
+
status: 1,
|
|
75
|
+
error: null,
|
|
76
|
+
internal: [],
|
|
77
|
+
erc20: [],
|
|
78
|
+
erc721: [],
|
|
79
|
+
data: '0x',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
blockHash: '0xb44ceddff193a9aa84a39e19d175b768b95c66a5438de8cd11391ce502b34259',
|
|
83
|
+
blockNumber: '0xddbeae',
|
|
84
|
+
timestamp: '0x624d82fe',
|
|
85
|
+
confirmations: 279689,
|
|
86
|
+
addressIndex: 2,
|
|
87
|
+
hash: '0x699b4b708812a6c4237f20079785ef28423e340b07cb78bb93bf30c6a949abc0',
|
|
88
|
+
nonce: '0x36c917',
|
|
89
|
+
gasPrice: '0x986b51fbe',
|
|
90
|
+
gas: '0x11e64',
|
|
91
|
+
gasUsed: '0xb411',
|
|
92
|
+
to: '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
|
93
|
+
from: '0x2faf487a4414fe77e2327f0bf4ae2a264a776ad2',
|
|
94
|
+
value: '0x0',
|
|
95
|
+
status: 1,
|
|
96
|
+
error: null,
|
|
97
|
+
internal: [],
|
|
98
|
+
erc20: [
|
|
99
|
+
{
|
|
100
|
+
events: true,
|
|
101
|
+
address: '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
|
102
|
+
from: '0x2faf487a4414fe77e2327f0bf4ae2a264a776ad2',
|
|
103
|
+
to: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
104
|
+
value: '0xd39548',
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
erc721: [],
|
|
108
|
+
data:
|
|
109
|
+
'0xa9059cbb00000000000000000000000090e481d9a664ebbe4be180d9501962255463036d0000000000000000000000000000000000000000000000000000000000d39548',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
blockHash: '0x46ac08214e4e853c3848e6fdecefaa55845c6068a5b7bd19faa0c921359b2d29',
|
|
113
|
+
blockNumber: '0xddc2f4',
|
|
114
|
+
timestamp: '0x624dbef2',
|
|
115
|
+
confirmations: 278595,
|
|
116
|
+
addressIndex: 3,
|
|
117
|
+
hash: '0xa2c35470993c37547988f44f92d4e12d6a301293223a4daf19a0e68822eddbef',
|
|
118
|
+
nonce: '0x1c2444',
|
|
119
|
+
gasPrice: '0xf099eb19a',
|
|
120
|
+
gas: '0x5208',
|
|
121
|
+
gasUsed: '0x5208',
|
|
122
|
+
to: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
123
|
+
from: '0x59a5208b32e627891c389ebafc644145224006e8',
|
|
124
|
+
value: '0xc0e0570c34a800',
|
|
125
|
+
status: 1,
|
|
126
|
+
error: null,
|
|
127
|
+
internal: [],
|
|
128
|
+
erc20: [],
|
|
129
|
+
erc721: [],
|
|
130
|
+
data: '0x',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
blockHash: '0xfa116b9c4e4d8f66745d7471de5059b7385f2c288a23e7ed27a48cef96dae385',
|
|
134
|
+
blockNumber: '0xde6f3b',
|
|
135
|
+
timestamp: '0x6256d511',
|
|
136
|
+
confirmations: 234492,
|
|
137
|
+
addressIndex: 4,
|
|
138
|
+
hash: '0x4b0b523bb0eca3e2e983f49d2aa33ae297c9402d9fcdcd4816ed20bea067db2c',
|
|
139
|
+
nonce: '0x0',
|
|
140
|
+
gasPrice: '0x11ef52da49',
|
|
141
|
+
gas: '0x11170',
|
|
142
|
+
gasUsed: '0xf6dd',
|
|
143
|
+
to: '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
|
144
|
+
from: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
145
|
+
value: '0x0',
|
|
146
|
+
status: 1,
|
|
147
|
+
error: null,
|
|
148
|
+
internal: [],
|
|
149
|
+
erc20: [
|
|
150
|
+
{
|
|
151
|
+
events: true,
|
|
152
|
+
address: '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
|
153
|
+
from: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
154
|
+
to: '0xfa56417d077a41a20aa190a8fcd841ebefa2859e',
|
|
155
|
+
value: '0x712284',
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
erc721: [],
|
|
159
|
+
data:
|
|
160
|
+
'0xa9059cbb000000000000000000000000fa56417d077a41a20aa190a8fcd841ebefa2859e0000000000000000000000000000000000000000000000000000000000712284',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
blockHash: '0xe9a9b99bbc766294a151b99c0290531b4529957d792b8de40624b3b2086c73f9',
|
|
164
|
+
blockNumber: '0xdeed29',
|
|
165
|
+
timestamp: '0x625d75aa',
|
|
166
|
+
confirmations: 202254,
|
|
167
|
+
addressIndex: 6,
|
|
168
|
+
hash: '0x974f15a3ac3f0692a4f4162e9f827722101b775dd1ca07fbf246ffebbefa43f0',
|
|
169
|
+
nonce: '0x37e5eb',
|
|
170
|
+
gasPrice: '0x9fb0d0b87',
|
|
171
|
+
gas: '0x13950',
|
|
172
|
+
gasUsed: '0xca80',
|
|
173
|
+
to: '0x0d8775f648430679a709e98d2b0cb6250d2887ef',
|
|
174
|
+
from: '0x2faf487a4414fe77e2327f0bf4ae2a264a776ad2',
|
|
175
|
+
value: '0x0',
|
|
176
|
+
status: 1,
|
|
177
|
+
error: null,
|
|
178
|
+
internal: [],
|
|
179
|
+
erc20: [
|
|
180
|
+
{
|
|
181
|
+
events: true,
|
|
182
|
+
address: '0x0d8775f648430679a709e98d2b0cb6250d2887ef',
|
|
183
|
+
from: '0x2faf487a4414fe77e2327f0bf4ae2a264a776ad2',
|
|
184
|
+
to: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
185
|
+
value: '0x74e3b1b53804e000',
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
erc721: [],
|
|
189
|
+
data:
|
|
190
|
+
'0xa9059cbb00000000000000000000000090e481d9a664ebbe4be180d9501962255463036d00000000000000000000000000000000000000000000000074e3b1b53804e000',
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
blockHash: '0x172d411fb1ce30311cd0559925dab284e4eeef58c9a9311fd04760be71e9d084',
|
|
194
|
+
blockNumber: '0xdf50cb',
|
|
195
|
+
timestamp: '0x6262bb5d',
|
|
196
|
+
confirmations: 176748,
|
|
197
|
+
addressIndex: 7,
|
|
198
|
+
hash: '0xf7aade9de387d7866043af8b98169d1502cb288cdf6dda0619e327964febd6df',
|
|
199
|
+
nonce: '0x384afa',
|
|
200
|
+
gasPrice: '0x4286ac8ee',
|
|
201
|
+
gas: '0x137d4',
|
|
202
|
+
gasUsed: '0xc944',
|
|
203
|
+
to: '0x50d1c9771902476076ecfc8b2a83ad6b9355a4c9',
|
|
204
|
+
from: '0x2faf487a4414fe77e2327f0bf4ae2a264a776ad2',
|
|
205
|
+
value: '0x0',
|
|
206
|
+
status: 1,
|
|
207
|
+
error: null,
|
|
208
|
+
internal: [],
|
|
209
|
+
erc20: [
|
|
210
|
+
{
|
|
211
|
+
events: true,
|
|
212
|
+
address: '0x50d1c9771902476076ecfc8b2a83ad6b9355a4c9',
|
|
213
|
+
from: '0x2faf487a4414fe77e2327f0bf4ae2a264a776ad2',
|
|
214
|
+
to: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
215
|
+
value: '0x293d97f33798c00',
|
|
216
|
+
},
|
|
217
|
+
],
|
|
218
|
+
erc721: [],
|
|
219
|
+
data:
|
|
220
|
+
'0xa9059cbb00000000000000000000000090e481d9a664ebbe4be180d9501962255463036d0000000000000000000000000000000000000000000000000293d97f33798c00',
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
blockHash: '0xb71696b1e9c32298967715232c54740a4ec588e41ce3e5ac1ae4e4efe5334323',
|
|
224
|
+
blockNumber: '0xdffe37',
|
|
225
|
+
timestamp: '0x626befa1',
|
|
226
|
+
confirmations: 132352,
|
|
227
|
+
addressIndex: 8,
|
|
228
|
+
hash: '0x9743dc687f388874298e537eb5df9024d532e79e3ff3e5df33528c80baa70018',
|
|
229
|
+
nonce: '0x1',
|
|
230
|
+
gasPrice: '0xcf3015f43',
|
|
231
|
+
gas: '0x2377b',
|
|
232
|
+
gasUsed: '0x153df',
|
|
233
|
+
to: '0xae7ab96520de3a18e5e111b5eaab095312d7fe84',
|
|
234
|
+
from: '0x92f5d6f5b516e0a106c2d1bb802ff7688067bed6',
|
|
235
|
+
value: '0x0',
|
|
236
|
+
status: 1,
|
|
237
|
+
error: null,
|
|
238
|
+
internal: [],
|
|
239
|
+
erc20: [
|
|
240
|
+
{
|
|
241
|
+
events: true,
|
|
242
|
+
address: '0xae7ab96520de3a18e5e111b5eaab095312d7fe84',
|
|
243
|
+
from: '0x92f5d6f5b516e0a106c2d1bb802ff7688067bed6',
|
|
244
|
+
to: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
245
|
+
value: '0xaa87bee538000',
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
erc721: [],
|
|
249
|
+
data:
|
|
250
|
+
'0xa9059cbb00000000000000000000000090e481d9a664ebbe4be180d9501962255463036d000000000000000000000000000000000000000000000000000aa87bee538000',
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
blockHash: '0xc4d649e2d9c38b9cdb23c4f22c5da80d3f07ef88ed38627dd7363cd2f06c92f1',
|
|
254
|
+
blockNumber: '0xdffe3d',
|
|
255
|
+
timestamp: '0x626beff1',
|
|
256
|
+
confirmations: 132346,
|
|
257
|
+
addressIndex: 9,
|
|
258
|
+
hash: '0x53c0b38288585793ba01659e70ead0dd59f18d1360d6ab5a648d3480ccd77168',
|
|
259
|
+
nonce: '0x1',
|
|
260
|
+
gasPrice: '0xec570f72a',
|
|
261
|
+
gas: '0x1c5ed',
|
|
262
|
+
gasUsed: '0x153d3',
|
|
263
|
+
to: '0xae7ab96520de3a18e5e111b5eaab095312d7fe84',
|
|
264
|
+
from: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
265
|
+
value: '0x0',
|
|
266
|
+
status: 1,
|
|
267
|
+
error: null,
|
|
268
|
+
internal: [],
|
|
269
|
+
erc20: [
|
|
270
|
+
{
|
|
271
|
+
events: true,
|
|
272
|
+
address: '0xae7ab96520de3a18e5e111b5eaab095312d7fe84',
|
|
273
|
+
from: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
274
|
+
to: '0xa9866ef5574a256b4b85ad2b80880da2ef1b0011',
|
|
275
|
+
value: '0x38d7ea4c68000',
|
|
276
|
+
},
|
|
277
|
+
],
|
|
278
|
+
erc721: [],
|
|
279
|
+
data:
|
|
280
|
+
'0xa9059cbb000000000000000000000000a9866ef5574a256b4b85ad2b80880da2ef1b001100000000000000000000000000000000000000000000000000038d7ea4c68000',
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
blockHash: '0x719dbca35139355c6c4e38044fa3b26443c9731380b42c77cfb5398b25cfd4a9',
|
|
284
|
+
blockNumber: '0xdfffc6',
|
|
285
|
+
timestamp: '0x626c049a',
|
|
286
|
+
confirmations: 131953,
|
|
287
|
+
addressIndex: 11,
|
|
288
|
+
hash: '0xa4cc4c2e35a9a0a321be60e22c7ab8470b32efd81dbd5f1324f60392465b1b1e',
|
|
289
|
+
nonce: '0x2',
|
|
290
|
+
gasPrice: '0x8e18e8c8c',
|
|
291
|
+
gas: '0x175b7',
|
|
292
|
+
gasUsed: '0x110fb',
|
|
293
|
+
to: '0xae7ab96520de3a18e5e111b5eaab095312d7fe84',
|
|
294
|
+
from: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
295
|
+
value: '0x0',
|
|
296
|
+
status: 1,
|
|
297
|
+
error: null,
|
|
298
|
+
internal: [],
|
|
299
|
+
erc20: [
|
|
300
|
+
{
|
|
301
|
+
events: true,
|
|
302
|
+
address: '0xae7ab96520de3a18e5e111b5eaab095312d7fe84',
|
|
303
|
+
from: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
304
|
+
to: '0xa9866ef5574a256b4b85ad2b80880da2ef1b0011',
|
|
305
|
+
value: '0x5af3107a4000',
|
|
306
|
+
},
|
|
307
|
+
],
|
|
308
|
+
erc721: [],
|
|
309
|
+
data:
|
|
310
|
+
'0xa9059cbb000000000000000000000000a9866ef5574a256b4b85ad2b80880da2ef1b001100000000000000000000000000000000000000000000000000005af3107a4000',
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
blockHash: '0x1953c1bb935f744629f26d794df5280d3b2165aea45057747d75683785cb9f9a',
|
|
314
|
+
blockNumber: '0xe0671e',
|
|
315
|
+
timestamp: '0x62717f3f',
|
|
316
|
+
confirmations: 105497,
|
|
317
|
+
addressIndex: 13,
|
|
318
|
+
hash: '0x35390bc5ff89d3ecad114fe3b2898b8fe4c96ec176fcecc3e29e55a2d8d51d9e',
|
|
319
|
+
nonce: '0x1bba06',
|
|
320
|
+
gasPrice: '0xf41c06ac0',
|
|
321
|
+
gas: '0xf618',
|
|
322
|
+
gasUsed: '0x5208',
|
|
323
|
+
to: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
324
|
+
from: '0xc098b2a3aa256d2140208c3de6543aaef5cd3a94',
|
|
325
|
+
value: '0xfeaf90ad2c000',
|
|
326
|
+
status: 1,
|
|
327
|
+
error: null,
|
|
328
|
+
internal: [],
|
|
329
|
+
erc20: [],
|
|
330
|
+
erc721: [],
|
|
331
|
+
data: '0x',
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
blockHash: '0x1a7886725a5ebc312d7e407f20988d972fbbbfeabf8b6a98564345aee87e3481',
|
|
335
|
+
blockNumber: '0xe1f4b7',
|
|
336
|
+
timestamp: '0x6286ec8e',
|
|
337
|
+
confirmations: 3712,
|
|
338
|
+
addressIndex: 14,
|
|
339
|
+
hash: '0x2f613acaebb34300a5c1bb25e2fa1c92f48cea469066fedb067d734292f31812',
|
|
340
|
+
nonce: '0x3',
|
|
341
|
+
gasPrice: '0x42426923b',
|
|
342
|
+
gas: '0x5208',
|
|
343
|
+
gasUsed: '0x5208',
|
|
344
|
+
to: '0xf6c138c36341138ddfc314a11038da8264b7ef09',
|
|
345
|
+
from: '0x90e481d9a664ebbe4be180d9501962255463036d',
|
|
346
|
+
value: '0x1d3353f4626400',
|
|
347
|
+
status: 1,
|
|
348
|
+
error: null,
|
|
349
|
+
internal: [],
|
|
350
|
+
erc20: [],
|
|
351
|
+
erc721: [],
|
|
352
|
+
data: '0x',
|
|
353
|
+
},
|
|
354
|
+
],
|
|
355
|
+
[],
|
|
356
|
+
],
|
|
357
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { EthereumMonitor } from '../ethereum-monitor'
|
|
2
|
+
import { size, omit } from 'lodash'
|
|
3
|
+
import { AccountState } from '@exodus/models'
|
|
4
|
+
import { once } from 'events'
|
|
5
|
+
import { ethereum as feeData } from '@exodus/ethereum-lib/src/fee-data'
|
|
6
|
+
import assetMap from './assets-for-test-helper'
|
|
7
|
+
import { createAssetClientInterface } from './asset-client-interface-test-helper'
|
|
8
|
+
import { create } from '../../exodus-eth-server/api'
|
|
9
|
+
|
|
10
|
+
const EXODUS_ETH_SERVER_URL = 'https://geth.a.exodus.io/wallet/v1/'
|
|
11
|
+
|
|
12
|
+
jest.setTimeout(10000)
|
|
13
|
+
|
|
14
|
+
export const logger = {
|
|
15
|
+
trace: jest.fn(),
|
|
16
|
+
debug: jest.fn(),
|
|
17
|
+
log: jest.fn(),
|
|
18
|
+
info: jest.fn(),
|
|
19
|
+
warn: jest.fn(),
|
|
20
|
+
error: jest.fn(),
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
Object.values(logger).forEach((fn) => fn.mockReset())
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const { ethereum } = assetMap
|
|
28
|
+
|
|
29
|
+
// Replacing default gasPrice to be sure WS will change it
|
|
30
|
+
const dummyGasPrice = ethereum.currency.Gwei(1) // 1 is the min fee...
|
|
31
|
+
const feeDataMock = feeData.update({ gasPrice: dummyGasPrice.toString() })
|
|
32
|
+
expect(feeDataMock.gasPrice).toEqual(dummyGasPrice)
|
|
33
|
+
|
|
34
|
+
export default class EthereumAccountState extends AccountState {
|
|
35
|
+
static defaults = {
|
|
36
|
+
cursor: '',
|
|
37
|
+
balance: ethereum.currency.ZERO,
|
|
38
|
+
tokenBalances: {},
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
ethereum.api = {
|
|
43
|
+
createAccountState: () => EthereumAccountState,
|
|
44
|
+
getConfirmationsNumber: () => 2,
|
|
45
|
+
getFeeData: () => feeDataMock,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Fernando's dev wallet. Profile 1 and Profile 2
|
|
49
|
+
export const walletPublicKeys = {
|
|
50
|
+
ethereum: [
|
|
51
|
+
Buffer.from('0273c38a3c31c31b361dc8d6b93e56c316e34991c478d3a14ea3fcd1ab552bc25e', 'hex'),
|
|
52
|
+
Buffer.from('02f33b1edf1016f6720518c776da30567fc7b7052ae6b596dd22909e0a87164f8d', 'hex'),
|
|
53
|
+
],
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
describe('ethereum monitor', () => {
|
|
57
|
+
test('can start monitor and update txs', async () => {
|
|
58
|
+
const assetClientInterface = createAssetClientInterface({ logger, walletPublicKeys })
|
|
59
|
+
const server = create(EXODUS_ETH_SERVER_URL)
|
|
60
|
+
const getHistoryV2 = jest.fn(async (...args) => {
|
|
61
|
+
const transactions = await server.getHistoryV2(...args)
|
|
62
|
+
return transactions.filter((tx) => {
|
|
63
|
+
return parseInt(tx.blockNumber, 16) < 14808250
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
const monitor = new EthereumMonitor({
|
|
67
|
+
interval: 20,
|
|
68
|
+
asset: ethereum,
|
|
69
|
+
assetClientInterface,
|
|
70
|
+
logger,
|
|
71
|
+
server: { ...server, getHistoryV2 },
|
|
72
|
+
})
|
|
73
|
+
try {
|
|
74
|
+
await monitor.start()
|
|
75
|
+
expect(logger.error).not.toBeCalled()
|
|
76
|
+
expect(logger.warn).not.toBeCalled()
|
|
77
|
+
const toBalanceFromTx = (txSet) => {
|
|
78
|
+
return txSet.getMutations().slice(-1)[0].balance
|
|
79
|
+
}
|
|
80
|
+
// Sintax sugar
|
|
81
|
+
const txs = (walletAccount, assetName) => {
|
|
82
|
+
return assetClientInterface.getTxLog({ walletAccount, assetName })
|
|
83
|
+
}
|
|
84
|
+
const state = (walletAccount, assetName) => {
|
|
85
|
+
return assetClientInterface.getAccountState({ walletAccount, assetName })
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const expectSameValue = (actual, expected) => {
|
|
89
|
+
expect(actual).toEqual(expected)
|
|
90
|
+
expect(actual.equals(expected)).toEqual(true)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
expect((await txs('exodus0', 'ethereum')).size).toEqual(7)
|
|
94
|
+
expect((await txs('exodus0', 'bat')).size).toEqual(1)
|
|
95
|
+
expect((await txs('exodus0', 'tetherusd')).size).toEqual(3)
|
|
96
|
+
expect((await txs('exodus1', 'ethereum')).size).toEqual(1)
|
|
97
|
+
|
|
98
|
+
expectSameValue(
|
|
99
|
+
toBalanceFromTx(await txs('exodus0', 'ethereum')),
|
|
100
|
+
ethereum.currency.defaultUnit('0.051201488965893697') // string due to floating error
|
|
101
|
+
)
|
|
102
|
+
expectSameValue(
|
|
103
|
+
toBalanceFromTx(await txs('exodus0', 'bat')),
|
|
104
|
+
assetMap.bat.currency.defaultUnit(8.42277112)
|
|
105
|
+
)
|
|
106
|
+
expectSameValue(
|
|
107
|
+
toBalanceFromTx(await txs('exodus0', 'tetherusd')),
|
|
108
|
+
assetMap.tetherusd.currency.defaultUnit(7.414404)
|
|
109
|
+
)
|
|
110
|
+
expectSameValue(
|
|
111
|
+
toBalanceFromTx(await txs('exodus1', 'ethereum')),
|
|
112
|
+
ethereum.currency.defaultUnit(0.00821921)
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
// It seems eth balances and tokenBalances are not being filled. Clients needs to read tx like above
|
|
116
|
+
expectSameValue(
|
|
117
|
+
(await state('exodus0', 'ethereum')).balance,
|
|
118
|
+
ethereum.currency.defaultUnit(0)
|
|
119
|
+
)
|
|
120
|
+
expect((await state('exodus0', 'ethereum')).tokenBalances).toEqual({})
|
|
121
|
+
expectSameValue(
|
|
122
|
+
(await state('exodus1', 'ethereum')).balance,
|
|
123
|
+
ethereum.currency.defaultUnit(0)
|
|
124
|
+
)
|
|
125
|
+
expect((await state('exodus1', 'ethereum')).tokenBalances).toEqual({})
|
|
126
|
+
expect(size(assetClientInterface.states)).toEqual(2)
|
|
127
|
+
} finally {
|
|
128
|
+
await monitor.stop()
|
|
129
|
+
}
|
|
130
|
+
expect(logger.error).not.toBeCalled()
|
|
131
|
+
expect(logger.warn).not.toBeCalled()
|
|
132
|
+
expect(monitor.timer.isRunning).toEqual(false)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
test('can start and update gas price', async () => {
|
|
136
|
+
// ws is not reliable enough to finish on time.
|
|
137
|
+
const server = create(EXODUS_ETH_SERVER_URL)
|
|
138
|
+
const assetClientInterface = createAssetClientInterface({ logger, walletPublicKeys })
|
|
139
|
+
const monitor = new EthereumMonitor({
|
|
140
|
+
interval: 20,
|
|
141
|
+
asset: ethereum,
|
|
142
|
+
assetClientInterface,
|
|
143
|
+
logger,
|
|
144
|
+
server,
|
|
145
|
+
})
|
|
146
|
+
try {
|
|
147
|
+
expect(await assetClientInterface.getFeeData({ assetName: ethereum.name })).toEqual(
|
|
148
|
+
feeDataMock
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
const oncePromise = once(assetClientInterface, 'fee-config-updated')
|
|
152
|
+
await monitor.start()
|
|
153
|
+
await oncePromise
|
|
154
|
+
// Once started, feeData gets updated
|
|
155
|
+
expect(await assetClientInterface.getFeeData({ assetName: ethereum.name })).not.toEqual(
|
|
156
|
+
feeDataMock
|
|
157
|
+
)
|
|
158
|
+
// gas price and origin are the changed ones.
|
|
159
|
+
expect(
|
|
160
|
+
omit(
|
|
161
|
+
await assetClientInterface.getFeeData({ assetName: ethereum.name }),
|
|
162
|
+
'gasPrice',
|
|
163
|
+
'origin'
|
|
164
|
+
)
|
|
165
|
+
).toEqual(omit(feeDataMock, 'gasPrice', 'origin'))
|
|
166
|
+
} finally {
|
|
167
|
+
await monitor.stop()
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
expect(logger.error).not.toBeCalled()
|
|
171
|
+
expect(logger.warn).not.toBeCalled()
|
|
172
|
+
expect(monitor.timer.isRunning).toEqual(false)
|
|
173
|
+
})
|
|
174
|
+
})
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { EthereumMonitor } from '../ethereum-monitor'
|
|
2
|
+
import { encodePublic } from '@exodus/ethereum-lib'
|
|
3
|
+
import { createAssetClientInterface } from './asset-client-interface-test-helper'
|
|
4
|
+
import assetMap from './assets-for-test-helper'
|
|
5
|
+
import { AccountState } from '@exodus/models'
|
|
6
|
+
import { ethereum as feeData } from '@exodus/ethereum-lib/src/fee-data'
|
|
7
|
+
import historyReturnValuesForTest from './ethereum-history-return-values-for-test-helper'
|
|
8
|
+
import { size, cloneDeep } from 'lodash'
|
|
9
|
+
|
|
10
|
+
const { ethereum } = assetMap
|
|
11
|
+
|
|
12
|
+
export default class EthereumAccountState extends AccountState {
|
|
13
|
+
static defaults = {
|
|
14
|
+
cursor: '',
|
|
15
|
+
balance: ethereum.currency.ZERO,
|
|
16
|
+
tokenBalances: {},
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
ethereum.api = {
|
|
21
|
+
createAccountState: () => EthereumAccountState,
|
|
22
|
+
getConfirmationsNumber: () => 2,
|
|
23
|
+
getFeeData: () => feeData,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const logger = {
|
|
27
|
+
trace: jest.fn(),
|
|
28
|
+
debug: jest.fn(),
|
|
29
|
+
log: jest.fn(),
|
|
30
|
+
info: jest.fn(),
|
|
31
|
+
warn: jest.fn(),
|
|
32
|
+
error: jest.fn((...args) => console.error(args)),
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
afterEach(() => {
|
|
36
|
+
Object.values(logger).forEach((fn) => fn.mockReset())
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
// Fernando's dev wallet. Profile 1 and Profile 2
|
|
40
|
+
export const walletPublicKeys = {
|
|
41
|
+
ethereum: [
|
|
42
|
+
Buffer.from('0273c38a3c31c31b361dc8d6b93e56c316e34991c478d3a14ea3fcd1ab552bc25e', 'hex'),
|
|
43
|
+
Buffer.from('02f33b1edf1016f6720518c776da30567fc7b7052ae6b596dd22909e0a87164f8d', 'hex'),
|
|
44
|
+
],
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
describe('ethereum monitor', () => {
|
|
48
|
+
test('can create monitor', () => {
|
|
49
|
+
const server = {
|
|
50
|
+
getURL() {
|
|
51
|
+
return 'https://mockMe'
|
|
52
|
+
},
|
|
53
|
+
ws: { watch: jest.fn(), events: { on: jest.fn() } },
|
|
54
|
+
|
|
55
|
+
getHistoryV2: jest.fn(() => {
|
|
56
|
+
return Promise.resolve([])
|
|
57
|
+
}),
|
|
58
|
+
}
|
|
59
|
+
const monitor = new EthereumMonitor({
|
|
60
|
+
interval: 20,
|
|
61
|
+
asset: ethereum,
|
|
62
|
+
assetClientInterface: createAssetClientInterface({ logger }),
|
|
63
|
+
logger,
|
|
64
|
+
server: server,
|
|
65
|
+
})
|
|
66
|
+
expect(monitor.server.getURL()).toEqual('https://mockMe')
|
|
67
|
+
|
|
68
|
+
expect(logger.warn).not.toBeCalled()
|
|
69
|
+
expect(logger.error).not.toBeCalled()
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
test('can start and stop monitor using simulated data', async () => {
|
|
73
|
+
const assetClientInterface = createAssetClientInterface({ logger, walletPublicKeys })
|
|
74
|
+
|
|
75
|
+
const getHistoryV2Returns = cloneDeep(historyReturnValuesForTest)
|
|
76
|
+
const server = {
|
|
77
|
+
getURL() {
|
|
78
|
+
return 'https://mockMe'
|
|
79
|
+
},
|
|
80
|
+
ws: { watch: jest.fn(), events: { on: jest.fn() }, open: jest.fn() },
|
|
81
|
+
|
|
82
|
+
getHistoryV2: jest.fn((address) => {
|
|
83
|
+
const history = getHistoryV2Returns[address]
|
|
84
|
+
const txPage = history?.shift()
|
|
85
|
+
return Promise.resolve(txPage || [])
|
|
86
|
+
}),
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const monitor = new EthereumMonitor({
|
|
90
|
+
interval: 20,
|
|
91
|
+
asset: ethereum,
|
|
92
|
+
assetClientInterface,
|
|
93
|
+
logger,
|
|
94
|
+
server: server,
|
|
95
|
+
})
|
|
96
|
+
await monitor.start()
|
|
97
|
+
await monitor.stop()
|
|
98
|
+
expect(logger.warn).not.toBeCalled()
|
|
99
|
+
expect(logger.error).not.toBeCalled()
|
|
100
|
+
|
|
101
|
+
const toBalanceFromTx = (txSet) => {
|
|
102
|
+
return txSet.getMutations().slice(-1)[0].balance
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Sintax sugar
|
|
106
|
+
const txs = (walletAccount, assetName) => {
|
|
107
|
+
return assetClientInterface.getTxLog({ walletAccount, assetName })
|
|
108
|
+
}
|
|
109
|
+
const state = (walletAccount, assetName) => {
|
|
110
|
+
return assetClientInterface.getAccountState({ walletAccount, assetName })
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const expectSameValue = (actual, expected) => {
|
|
114
|
+
expect(actual).toEqual(expected)
|
|
115
|
+
expect(actual.equals(expected)).toEqual(true)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
expect((await txs('exodus0', 'ethereum')).size).toEqual(7)
|
|
119
|
+
expect((await txs('exodus0', 'bat')).size).toEqual(1)
|
|
120
|
+
expect((await txs('exodus0', 'tetherusd')).size).toEqual(3)
|
|
121
|
+
expect((await txs('exodus1', 'ethereum')).size).toEqual(1)
|
|
122
|
+
|
|
123
|
+
expectSameValue(
|
|
124
|
+
toBalanceFromTx(await txs('exodus0', 'ethereum')),
|
|
125
|
+
ethereum.currency.defaultUnit('0.051201488965893697') // string due to floating error
|
|
126
|
+
)
|
|
127
|
+
expectSameValue(
|
|
128
|
+
toBalanceFromTx(await txs('exodus0', 'bat')),
|
|
129
|
+
assetMap.bat.currency.defaultUnit(8.42277112)
|
|
130
|
+
)
|
|
131
|
+
expectSameValue(
|
|
132
|
+
toBalanceFromTx(await txs('exodus0', 'tetherusd')),
|
|
133
|
+
assetMap.tetherusd.currency.defaultUnit(7.414404)
|
|
134
|
+
)
|
|
135
|
+
expectSameValue(
|
|
136
|
+
toBalanceFromTx(await txs('exodus1', 'ethereum')),
|
|
137
|
+
ethereum.currency.defaultUnit(0.00821921)
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
// It seems eth balances and tokenBalances are not being filled. Clients needs to read tx like above
|
|
141
|
+
expectSameValue((await state('exodus0', 'ethereum')).balance, ethereum.currency.defaultUnit(0))
|
|
142
|
+
expect((await state('exodus0', 'ethereum')).tokenBalances).toEqual({})
|
|
143
|
+
expectSameValue((await state('exodus1', 'ethereum')).balance, ethereum.currency.defaultUnit(0))
|
|
144
|
+
expect((await state('exodus1', 'ethereum')).tokenBalances).toEqual({})
|
|
145
|
+
expect(size(assetClientInterface.states)).toEqual(2)
|
|
146
|
+
|
|
147
|
+
expect(logger.error).not.toBeCalled()
|
|
148
|
+
expect(logger.warn).not.toBeCalled()
|
|
149
|
+
expect(monitor.timer.isRunning).toEqual(false)
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
test('validate address', () => {
|
|
153
|
+
expect(encodePublic(walletPublicKeys.ethereum[0])).toEqual(
|
|
154
|
+
'0x90E481d9A664ebbE4Be180d9501962255463036d'
|
|
155
|
+
)
|
|
156
|
+
expect(encodePublic(walletPublicKeys.ethereum[1])).toEqual(
|
|
157
|
+
'0xf6c138C36341138dDFC314a11038dA8264B7Ef09'
|
|
158
|
+
)
|
|
159
|
+
})
|
|
160
|
+
})
|