@ledgerhq/coin-aptos 1.9.0-next.0 → 2.0.0-nightly.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.
Files changed (159) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +36 -10
  3. package/lib/__tests__/api/index.test.js +61 -5
  4. package/lib/__tests__/api/index.test.js.map +1 -1
  5. package/lib/__tests__/bridge/buildTransaction.test.js +57 -2
  6. package/lib/__tests__/bridge/buildTransaction.test.js.map +1 -1
  7. package/lib/__tests__/bridge/getFeesForTransaction.test.js +109 -8
  8. package/lib/__tests__/bridge/getFeesForTransaction.test.js.map +1 -1
  9. package/lib/__tests__/bridge/getTransactionStatus.test.js +175 -37
  10. package/lib/__tests__/bridge/getTransactionStatus.test.js.map +1 -1
  11. package/lib/__tests__/bridge/logic.test.js +889 -115
  12. package/lib/__tests__/bridge/logic.test.js.map +1 -1
  13. package/lib/__tests__/bridge/signOperation.test.js +128 -2
  14. package/lib/__tests__/bridge/signOperation.test.js.map +1 -1
  15. package/lib/__tests__/bridge/synchronisation.test.js +1214 -67
  16. package/lib/__tests__/bridge/synchronisation.test.js.map +1 -1
  17. package/lib/api/graphql/queries.js +6 -6
  18. package/lib/api/graphql/types.d.ts +9 -9
  19. package/lib/api/graphql/types.d.ts.map +1 -1
  20. package/lib/api/index.d.ts +5 -2
  21. package/lib/api/index.d.ts.map +1 -1
  22. package/lib/api/index.js +30 -4
  23. package/lib/api/index.js.map +1 -1
  24. package/lib/bridge/bridge.fixture.d.ts +2 -0
  25. package/lib/bridge/bridge.fixture.d.ts.map +1 -1
  26. package/lib/bridge/bridge.fixture.js +85 -13
  27. package/lib/bridge/bridge.fixture.js.map +1 -1
  28. package/lib/bridge/buildTransaction.d.ts.map +1 -1
  29. package/lib/bridge/buildTransaction.js +29 -3
  30. package/lib/bridge/buildTransaction.js.map +1 -1
  31. package/lib/bridge/estimateMaxSpendable.js +1 -1
  32. package/lib/bridge/estimateMaxSpendable.js.map +1 -1
  33. package/lib/bridge/getFeesForTransaction.d.ts.map +1 -1
  34. package/lib/bridge/getFeesForTransaction.js +12 -7
  35. package/lib/bridge/getFeesForTransaction.js.map +1 -1
  36. package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
  37. package/lib/bridge/getTransactionStatus.js +28 -14
  38. package/lib/bridge/getTransactionStatus.js.map +1 -1
  39. package/lib/bridge/logic.d.ts +13 -8
  40. package/lib/bridge/logic.d.ts.map +1 -1
  41. package/lib/bridge/logic.js +152 -54
  42. package/lib/bridge/logic.js.map +1 -1
  43. package/lib/bridge/prepareTransaction.d.ts.map +1 -1
  44. package/lib/bridge/prepareTransaction.js +2 -2
  45. package/lib/bridge/prepareTransaction.js.map +1 -1
  46. package/lib/bridge/signOperation.d.ts.map +1 -1
  47. package/lib/bridge/signOperation.js +17 -3
  48. package/lib/bridge/signOperation.js.map +1 -1
  49. package/lib/bridge/synchronisation.d.ts +15 -0
  50. package/lib/bridge/synchronisation.d.ts.map +1 -1
  51. package/lib/bridge/synchronisation.js +127 -4
  52. package/lib/bridge/synchronisation.js.map +1 -1
  53. package/lib/constants.d.ts +5 -1
  54. package/lib/constants.d.ts.map +1 -1
  55. package/lib/constants.js +6 -2
  56. package/lib/constants.js.map +1 -1
  57. package/lib/test/bot-specs.d.ts.map +1 -1
  58. package/lib/test/bot-specs.js +40 -1
  59. package/lib/test/bot-specs.js.map +1 -1
  60. package/lib/test/bridgeDatasetTest.d.ts.map +1 -1
  61. package/lib/test/bridgeDatasetTest.js +43 -62
  62. package/lib/test/bridgeDatasetTest.js.map +1 -1
  63. package/lib/test/speculos-deviceActions.d.ts +1 -0
  64. package/lib/test/speculos-deviceActions.d.ts.map +1 -1
  65. package/lib/test/speculos-deviceActions.js +37 -5
  66. package/lib/test/speculos-deviceActions.js.map +1 -1
  67. package/lib/types/index.d.ts +18 -7
  68. package/lib/types/index.d.ts.map +1 -1
  69. package/lib-es/__tests__/api/index.test.js +61 -5
  70. package/lib-es/__tests__/api/index.test.js.map +1 -1
  71. package/lib-es/__tests__/bridge/buildTransaction.test.js +58 -3
  72. package/lib-es/__tests__/bridge/buildTransaction.test.js.map +1 -1
  73. package/lib-es/__tests__/bridge/getFeesForTransaction.test.js +110 -9
  74. package/lib-es/__tests__/bridge/getFeesForTransaction.test.js.map +1 -1
  75. package/lib-es/__tests__/bridge/getTransactionStatus.test.js +177 -39
  76. package/lib-es/__tests__/bridge/getTransactionStatus.test.js.map +1 -1
  77. package/lib-es/__tests__/bridge/logic.test.js +891 -117
  78. package/lib-es/__tests__/bridge/logic.test.js.map +1 -1
  79. package/lib-es/__tests__/bridge/signOperation.test.js +128 -2
  80. package/lib-es/__tests__/bridge/signOperation.test.js.map +1 -1
  81. package/lib-es/__tests__/bridge/synchronisation.test.js +1213 -69
  82. package/lib-es/__tests__/bridge/synchronisation.test.js.map +1 -1
  83. package/lib-es/api/graphql/queries.js +6 -6
  84. package/lib-es/api/graphql/types.d.ts +9 -9
  85. package/lib-es/api/graphql/types.d.ts.map +1 -1
  86. package/lib-es/api/index.d.ts +5 -2
  87. package/lib-es/api/index.d.ts.map +1 -1
  88. package/lib-es/api/index.js +30 -4
  89. package/lib-es/api/index.js.map +1 -1
  90. package/lib-es/bridge/bridge.fixture.d.ts +2 -0
  91. package/lib-es/bridge/bridge.fixture.d.ts.map +1 -1
  92. package/lib-es/bridge/bridge.fixture.js +82 -12
  93. package/lib-es/bridge/bridge.fixture.js.map +1 -1
  94. package/lib-es/bridge/buildTransaction.d.ts.map +1 -1
  95. package/lib-es/bridge/buildTransaction.js +30 -4
  96. package/lib-es/bridge/buildTransaction.js.map +1 -1
  97. package/lib-es/bridge/estimateMaxSpendable.js +1 -1
  98. package/lib-es/bridge/estimateMaxSpendable.js.map +1 -1
  99. package/lib-es/bridge/getFeesForTransaction.d.ts.map +1 -1
  100. package/lib-es/bridge/getFeesForTransaction.js +13 -8
  101. package/lib-es/bridge/getFeesForTransaction.js.map +1 -1
  102. package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
  103. package/lib-es/bridge/getTransactionStatus.js +28 -14
  104. package/lib-es/bridge/getTransactionStatus.js.map +1 -1
  105. package/lib-es/bridge/logic.d.ts +13 -8
  106. package/lib-es/bridge/logic.d.ts.map +1 -1
  107. package/lib-es/bridge/logic.js +146 -52
  108. package/lib-es/bridge/logic.js.map +1 -1
  109. package/lib-es/bridge/prepareTransaction.d.ts.map +1 -1
  110. package/lib-es/bridge/prepareTransaction.js +2 -2
  111. package/lib-es/bridge/prepareTransaction.js.map +1 -1
  112. package/lib-es/bridge/signOperation.d.ts.map +1 -1
  113. package/lib-es/bridge/signOperation.js +17 -3
  114. package/lib-es/bridge/signOperation.js.map +1 -1
  115. package/lib-es/bridge/synchronisation.d.ts +15 -0
  116. package/lib-es/bridge/synchronisation.d.ts.map +1 -1
  117. package/lib-es/bridge/synchronisation.js +123 -3
  118. package/lib-es/bridge/synchronisation.js.map +1 -1
  119. package/lib-es/constants.d.ts +5 -1
  120. package/lib-es/constants.d.ts.map +1 -1
  121. package/lib-es/constants.js +5 -1
  122. package/lib-es/constants.js.map +1 -1
  123. package/lib-es/test/bot-specs.d.ts.map +1 -1
  124. package/lib-es/test/bot-specs.js +41 -2
  125. package/lib-es/test/bot-specs.js.map +1 -1
  126. package/lib-es/test/bridgeDatasetTest.d.ts.map +1 -1
  127. package/lib-es/test/bridgeDatasetTest.js +43 -59
  128. package/lib-es/test/bridgeDatasetTest.js.map +1 -1
  129. package/lib-es/test/speculos-deviceActions.d.ts +1 -0
  130. package/lib-es/test/speculos-deviceActions.d.ts.map +1 -1
  131. package/lib-es/test/speculos-deviceActions.js +36 -4
  132. package/lib-es/test/speculos-deviceActions.js.map +1 -1
  133. package/lib-es/types/index.d.ts +18 -7
  134. package/lib-es/types/index.d.ts.map +1 -1
  135. package/package.json +9 -8
  136. package/src/__tests__/api/index.test.ts +75 -5
  137. package/src/__tests__/bridge/buildTransaction.test.ts +85 -3
  138. package/src/__tests__/bridge/getFeesForTransaction.test.ts +144 -9
  139. package/src/__tests__/bridge/getTransactionStatus.test.ts +217 -38
  140. package/src/__tests__/bridge/logic.test.ts +922 -118
  141. package/src/__tests__/bridge/signOperation.test.ts +141 -2
  142. package/src/__tests__/bridge/synchronisation.test.ts +1265 -71
  143. package/src/api/graphql/queries.ts +6 -6
  144. package/src/api/graphql/types.ts +9 -9
  145. package/src/api/index.ts +32 -5
  146. package/src/bridge/bridge.fixture.ts +91 -12
  147. package/src/bridge/buildTransaction.ts +39 -6
  148. package/src/bridge/estimateMaxSpendable.ts +1 -1
  149. package/src/bridge/getFeesForTransaction.ts +14 -9
  150. package/src/bridge/getTransactionStatus.ts +35 -13
  151. package/src/bridge/logic.ts +202 -63
  152. package/src/bridge/prepareTransaction.ts +4 -3
  153. package/src/bridge/signOperation.ts +19 -3
  154. package/src/bridge/synchronisation.ts +170 -3
  155. package/src/constants.ts +12 -1
  156. package/src/test/bot-specs.ts +63 -3
  157. package/src/test/bridgeDatasetTest.ts +45 -59
  158. package/src/test/speculos-deviceActions.ts +40 -4
  159. package/src/types/index.ts +15 -1
@@ -1,10 +1,19 @@
1
- import { AccountShapeInfo } from "@ledgerhq/coin-framework/bridge/jsHelpers";
1
+ import { AccountShapeInfo, mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers";
2
2
  import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/index";
3
- import { Account, SyncConfig } from "@ledgerhq/types-live";
4
- import { encodeAccountId } from "@ledgerhq/coin-framework/account";
5
- import { mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers";
3
+ import { Account, Operation, SyncConfig, TokenAccount } from "@ledgerhq/types-live";
4
+ import { decodeTokenAccountId } from "@ledgerhq/coin-framework/account";
5
+ import { emptyHistoryCache } from "@ledgerhq/coin-framework/account/index";
6
6
  import { AptosAPI } from "../../api";
7
- import { getAccountShape } from "../../bridge/synchronisation";
7
+ import {
8
+ getAccountShape,
9
+ mergeSubAccounts,
10
+ getSubAccountShape,
11
+ getSubAccounts,
12
+ } from "../../bridge/synchronisation";
13
+ import BigNumber from "bignumber.js";
14
+ import { createFixtureAccount } from "../../bridge/bridge.fixture";
15
+ import { CryptoCurrency, TokenCurrency } from "@ledgerhq/types-cryptoassets";
16
+ import { txsToOps } from "../../bridge/logic";
8
17
 
9
18
  jest.mock("@ledgerhq/coin-framework/account", () => {
10
19
  const originalModule = jest.requireActual("@ledgerhq/coin-framework/account");
@@ -18,22 +27,25 @@ jest.mock("@ledgerhq/coin-framework/account", () => {
18
27
  return {
19
28
  ...partialMockedModule,
20
29
  // mock all except these
30
+ encodeAccountId: originalModule.encodeAccountId,
21
31
  decodeAccountId: originalModule.decodeAccountId,
32
+ encodeTokenAccountId: originalModule.encodeTokenAccountId,
22
33
  };
23
34
  });
24
35
 
25
- const mockedEncodeAccountId = jest.mocked(encodeAccountId);
36
+ const mockedDecodeTokenAccountId = jest.mocked(decodeTokenAccountId);
37
+
38
+ jest.mock("@ledgerhq/coin-framework/bridge/jsHelpers");
39
+ jest.mock("invariant", () => jest.fn());
26
40
 
27
41
  jest.mock("../../api");
28
42
  let mockedAptosAPI: jest.Mocked<any>;
29
43
 
30
- jest.mock("@ledgerhq/coin-framework/bridge/jsHelpers");
31
- jest.mock("invariant", () => jest.fn());
44
+ jest.mock("../../bridge/logic");
32
45
 
33
46
  describe("getAccountShape", () => {
34
47
  beforeEach(() => {
35
48
  mockedAptosAPI = jest.mocked(AptosAPI);
36
- jest.mocked(mergeOps).mockReturnValue([]);
37
49
  });
38
50
 
39
51
  afterEach(() => {
@@ -51,6 +63,9 @@ describe("getAccountShape", () => {
51
63
  }));
52
64
  const mockGetAccountSpy = jest.spyOn({ getAccount: mockGetAccountInfo }, "getAccount");
53
65
 
66
+ jest.mocked(mergeOps).mockReturnValue([]);
67
+ jest.mocked(txsToOps).mockReturnValue([[], []]);
68
+
54
69
  const account = await getAccountShape(
55
70
  {
56
71
  id: "1",
@@ -87,9 +102,8 @@ describe("getAccountShape", () => {
87
102
  );
88
103
 
89
104
  expect(account.xpub).toEqual("address");
90
- expect(mockedEncodeAccountId).toHaveBeenCalledTimes(1);
91
105
  expect(mockedAptosAPI).toHaveBeenCalledTimes(1);
92
- expect(mockGetAccountSpy).toHaveBeenCalledWith("address", undefined);
106
+ expect(mockGetAccountSpy).toHaveBeenCalledWith("address");
93
107
  });
94
108
 
95
109
  it("account without xpub", async () => {
@@ -103,6 +117,9 @@ describe("getAccountShape", () => {
103
117
  }));
104
118
  const mockGetAccountSpy = jest.spyOn({ getAccount: mockGetAccountInfo }, "getAccount");
105
119
 
120
+ jest.mocked(mergeOps).mockReturnValue([]);
121
+ jest.mocked(txsToOps).mockReturnValue([[], []]);
122
+
106
123
  const account = await getAccountShape(
107
124
  {
108
125
  id: "1",
@@ -138,9 +155,8 @@ describe("getAccountShape", () => {
138
155
  );
139
156
 
140
157
  expect(account.xpub).toEqual("1");
141
- expect(mockedEncodeAccountId).toHaveBeenCalledTimes(1);
142
158
  expect(mockedAptosAPI).toHaveBeenCalledTimes(1);
143
- expect(mockGetAccountSpy).toHaveBeenCalledWith("address", undefined);
159
+ expect(mockGetAccountSpy).toHaveBeenCalledWith("address");
144
160
  });
145
161
 
146
162
  it("without initialAccount", async () => {
@@ -154,6 +170,9 @@ describe("getAccountShape", () => {
154
170
  }));
155
171
  const mockGetAccountSpy = jest.spyOn({ getAccount: mockGetAccountInfo }, "getAccount");
156
172
 
173
+ jest.mocked(mergeOps).mockReturnValue([]);
174
+ jest.mocked(txsToOps).mockReturnValue([[], []]);
175
+
157
176
  const account = await getAccountShape(
158
177
  {
159
178
  id: "1",
@@ -169,9 +188,8 @@ describe("getAccountShape", () => {
169
188
  );
170
189
 
171
190
  expect(account.xpub).toEqual("");
172
- expect(mockedEncodeAccountId).toHaveBeenCalledTimes(1);
173
191
  expect(mockedAptosAPI).toHaveBeenCalledTimes(1);
174
- expect(mockGetAccountSpy).toHaveBeenCalledWith("address", undefined);
192
+ expect(mockGetAccountSpy).toHaveBeenCalledWith("address");
175
193
  });
176
194
 
177
195
  it("initialAccount with operations", async () => {
@@ -185,6 +203,9 @@ describe("getAccountShape", () => {
185
203
  }));
186
204
  const mockGetAccountSpy = jest.spyOn({ getAccount: mockGetAccountInfo }, "getAccount");
187
205
 
206
+ jest.mocked(mergeOps).mockReturnValue([]);
207
+ jest.mocked(txsToOps).mockReturnValue([[], []]);
208
+
188
209
  const account = await getAccountShape(
189
210
  {
190
211
  id: "1",
@@ -208,22 +229,8 @@ describe("getAccountShape", () => {
208
229
  creationDate: new Date(),
209
230
  blockHeight: 0,
210
231
  currency: getCryptoCurrencyById("aptos"),
211
- t: 1,
212
- operations: [
213
- {
214
- id: "1",
215
- hash: "hash",
216
- type: "OUT",
217
- value: BigInt(10),
218
- fee: BigInt(0),
219
- blockHeight: 0,
220
- blockHash: "blockHash",
221
- accountId: "1",
222
- senders: ["sender"],
223
- recipients: ["recipient"],
224
- date: new Date(),
225
- },
226
- ],
232
+ operationsCount: 0,
233
+ operations: [],
227
234
  pendingOperations: [],
228
235
  lastSyncDate: new Date(),
229
236
  balanceHistoryCache: {},
@@ -234,9 +241,8 @@ describe("getAccountShape", () => {
234
241
  );
235
242
 
236
243
  expect(account.xpub).toEqual("1");
237
- expect(mockedEncodeAccountId).toHaveBeenCalledTimes(1);
238
244
  expect(mockedAptosAPI).toHaveBeenCalledTimes(1);
239
- expect(mockGetAccountSpy).toHaveBeenCalledWith("address", undefined);
245
+ expect(mockGetAccountSpy).toHaveBeenCalledWith("address");
240
246
  });
241
247
 
242
248
  it("initialAccount with operations with extra", async () => {
@@ -250,6 +256,9 @@ describe("getAccountShape", () => {
250
256
  }));
251
257
  const mockGetAccountSpy = jest.spyOn({ getAccount: mockGetAccountInfo }, "getAccount");
252
258
 
259
+ jest.mocked(mergeOps).mockReturnValue([]);
260
+ jest.mocked(txsToOps).mockReturnValue([[], []]);
261
+
253
262
  const account = await getAccountShape(
254
263
  {
255
264
  id: "1",
@@ -273,23 +282,8 @@ describe("getAccountShape", () => {
273
282
  creationDate: new Date(),
274
283
  blockHeight: 0,
275
284
  currency: getCryptoCurrencyById("aptos"),
276
- t: 1,
277
- operations: [
278
- {
279
- id: "1",
280
- hash: "hash",
281
- type: "OUT",
282
- value: BigInt(10),
283
- fee: BigInt(0),
284
- blockHeight: 0,
285
- blockHash: "blockHash",
286
- accountId: "1",
287
- senders: ["sender"],
288
- recipients: ["recipient"],
289
- date: new Date(),
290
- extra: { version: 1 },
291
- },
292
- ],
285
+ operationsCount: 0,
286
+ operations: [],
293
287
  pendingOperations: [],
294
288
  lastSyncDate: new Date(),
295
289
  balanceHistoryCache: {},
@@ -300,9 +294,8 @@ describe("getAccountShape", () => {
300
294
  );
301
295
 
302
296
  expect(account.xpub).toEqual("1");
303
- expect(mockedEncodeAccountId).toHaveBeenCalledTimes(1);
304
297
  expect(mockedAptosAPI).toHaveBeenCalledTimes(1);
305
- expect(mockGetAccountSpy).toHaveBeenCalledWith("address", 1);
298
+ expect(mockGetAccountSpy).toHaveBeenCalledWith("address");
306
299
  });
307
300
 
308
301
  it("get publicKey from rest", async () => {
@@ -316,6 +309,9 @@ describe("getAccountShape", () => {
316
309
  }));
317
310
  const mockGetAccountSpy = jest.spyOn({ getAccount: mockGetAccountInfo }, "getAccount");
318
311
 
312
+ jest.mocked(mergeOps).mockReturnValue([]);
313
+ jest.mocked(txsToOps).mockReturnValue([[], []]);
314
+
319
315
  const account = await getAccountShape(
320
316
  {
321
317
  id: "1",
@@ -339,23 +335,8 @@ describe("getAccountShape", () => {
339
335
  creationDate: new Date(),
340
336
  blockHeight: 0,
341
337
  currency: getCryptoCurrencyById("aptos"),
342
- t: 1,
343
- operations: [
344
- {
345
- id: "1",
346
- hash: "hash",
347
- type: "OUT",
348
- value: BigInt(10),
349
- fee: BigInt(0),
350
- blockHeight: 0,
351
- blockHash: "blockHash",
352
- accountId: "1",
353
- senders: ["sender"],
354
- recipients: ["recipient"],
355
- date: new Date(),
356
- extra: { version: 1 },
357
- },
358
- ],
338
+ operationsCount: 0,
339
+ operations: [],
359
340
  pendingOperations: [],
360
341
  lastSyncDate: new Date(),
361
342
  balanceHistoryCache: {},
@@ -367,8 +348,1221 @@ describe("getAccountShape", () => {
367
348
  );
368
349
 
369
350
  expect(account.xpub).toEqual("restPublicKey");
370
- expect(mockedEncodeAccountId).toHaveBeenCalledTimes(1);
371
351
  expect(mockedAptosAPI).toHaveBeenCalledTimes(1);
372
- expect(mockGetAccountSpy).toHaveBeenCalledWith("address", 1);
352
+ expect(mockGetAccountSpy).toHaveBeenCalledWith("address");
353
+ });
354
+
355
+ it("initialAccount with operations with subOperations", async () => {
356
+ const mockGetAccountInfo = jest.fn().mockImplementation(async () => ({
357
+ balance: BigNumber(68254118),
358
+ transactions: [
359
+ {
360
+ version: "2532591427",
361
+ hash: "0x3f35",
362
+ state_change_hash: "0xb480",
363
+ event_root_hash: "0x3fa1",
364
+ state_checkpoint_hash: null,
365
+ gas_used: "12",
366
+ success: true,
367
+ vm_status: "Executed successfully",
368
+ accumulator_root_hash: "0x319f",
369
+ changes: [
370
+ {
371
+ address: "0x4e5e",
372
+ state_key_hash: "0x3c0c",
373
+ data: {
374
+ type: "0x1::coin::CoinStore<0xd111::staked_coin::StakedAptos>",
375
+ data: {
376
+ coin: {
377
+ value: "4000000",
378
+ },
379
+ deposit_events: {
380
+ counter: "9",
381
+ guid: {
382
+ id: {
383
+ addr: "0x4e5e",
384
+ creation_num: "4",
385
+ },
386
+ },
387
+ },
388
+ frozen: false,
389
+ withdraw_events: {
390
+ counter: "6",
391
+ guid: {
392
+ id: {
393
+ addr: "0x4e5e",
394
+ creation_num: "5",
395
+ },
396
+ },
397
+ },
398
+ },
399
+ },
400
+ type: "write_resource",
401
+ },
402
+ {
403
+ address: "0xa0d8",
404
+ state_key_hash: "0x1709",
405
+ data: {
406
+ type: "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>",
407
+ data: {
408
+ coin: {
409
+ value: "68254118",
410
+ },
411
+ deposit_events: {
412
+ counter: "46",
413
+ guid: {
414
+ id: {
415
+ addr: "0xa0d8",
416
+ creation_num: "2",
417
+ },
418
+ },
419
+ },
420
+ frozen: false,
421
+ withdraw_events: {
422
+ counter: "89",
423
+ guid: {
424
+ id: {
425
+ addr: "0xa0d8",
426
+ creation_num: "3",
427
+ },
428
+ },
429
+ },
430
+ },
431
+ },
432
+ type: "write_resource",
433
+ },
434
+ {
435
+ address: "0xa0d8",
436
+ state_key_hash: "0x5520",
437
+ data: {
438
+ type: "0x1::coin::CoinStore<0xd111::staked_coin::StakedAptos>",
439
+ data: {
440
+ coin: {
441
+ value: "1000000",
442
+ },
443
+ deposit_events: {
444
+ counter: "7",
445
+ guid: {
446
+ id: {
447
+ addr: "0xa0d8",
448
+ creation_num: "10",
449
+ },
450
+ },
451
+ },
452
+ frozen: false,
453
+ withdraw_events: {
454
+ counter: "13",
455
+ guid: {
456
+ id: {
457
+ addr: "0xa0d8",
458
+ creation_num: "11",
459
+ },
460
+ },
461
+ },
462
+ },
463
+ },
464
+ type: "write_resource",
465
+ },
466
+ {
467
+ address: "0xa0d8",
468
+ state_key_hash: "0x6f1e",
469
+ data: {
470
+ type: "0x1::account::Account",
471
+ data: {
472
+ authentication_key: "0xa0d8",
473
+ coin_register_events: {
474
+ counter: "5",
475
+ guid: {
476
+ id: {
477
+ addr: "0xa0d8",
478
+ creation_num: "0",
479
+ },
480
+ },
481
+ },
482
+ guid_creation_num: "12",
483
+ key_rotation_events: {
484
+ counter: "0",
485
+ guid: {
486
+ id: {
487
+ addr: "0xa0d8",
488
+ creation_num: "1",
489
+ },
490
+ },
491
+ },
492
+ rotation_capability_offer: {
493
+ for: {
494
+ vec: [],
495
+ },
496
+ },
497
+ sequence_number: "122",
498
+ signer_capability_offer: {
499
+ for: {
500
+ vec: [],
501
+ },
502
+ },
503
+ },
504
+ },
505
+ type: "write_resource",
506
+ },
507
+ {
508
+ state_key_hash: "0x6e4b",
509
+ handle: "0x1b85",
510
+ key: "0x0619",
511
+ value: "0x1ddaf8da3b1497010000000000000000",
512
+ data: null,
513
+ type: "write_table_item",
514
+ },
515
+ ],
516
+ sender: "0xa0d8",
517
+ sequence_number: "121",
518
+ max_gas_amount: "12",
519
+ gas_unit_price: "100",
520
+ expiration_timestamp_secs: "1743177404",
521
+ payload: {
522
+ function: "0x1::aptos_account::transfer_coins",
523
+ type_arguments: ["0xd111::staked_coin::StakedAptos"],
524
+ arguments: ["0x4e5e", "1500000"],
525
+ type: "entry_function_payload",
526
+ },
527
+ signature: {
528
+ public_key: "0x474d",
529
+ signature: "0x0ad8",
530
+ type: "ed25519_signature",
531
+ },
532
+ events: [
533
+ {
534
+ guid: {
535
+ creation_number: "11",
536
+ account_address: "0xa0d8",
537
+ },
538
+ sequence_number: "12",
539
+ type: "0x1::coin::WithdrawEvent",
540
+ data: {
541
+ amount: "1500000",
542
+ },
543
+ },
544
+ {
545
+ guid: {
546
+ creation_number: "4",
547
+ account_address: "0x4e5e",
548
+ },
549
+ sequence_number: "8",
550
+ type: "0x1::coin::DepositEvent",
551
+ data: {
552
+ amount: "1500000",
553
+ },
554
+ },
555
+ {
556
+ guid: {
557
+ creation_number: "0",
558
+ account_address: "0x0",
559
+ },
560
+ sequence_number: "0",
561
+ type: "0x1::transaction_fee::FeeStatement",
562
+ data: {
563
+ execution_gas_units: "6",
564
+ io_gas_units: "6",
565
+ storage_fee_octas: "0",
566
+ storage_fee_refund_octas: "0",
567
+ total_charge_gas_units: "12",
568
+ },
569
+ },
570
+ ],
571
+ timestamp: "1743177360481259",
572
+ type: "user_transaction",
573
+ block: {
574
+ height: 311948147,
575
+ hash: "0x6d02",
576
+ },
577
+ },
578
+ {
579
+ version: "2532549325",
580
+ hash: "0x9a6b",
581
+ state_change_hash: "0xa424",
582
+ event_root_hash: "0x0321",
583
+ state_checkpoint_hash: null,
584
+ gas_used: "12",
585
+ success: true,
586
+ vm_status: "Executed successfully",
587
+ accumulator_root_hash: "0xede9",
588
+ changes: [
589
+ {
590
+ address: "0x4e5e",
591
+ state_key_hash: "0x3c0c",
592
+ data: {
593
+ type: "0x1::coin::CoinStore<0xd111::staked_coin::StakedAptos>",
594
+ data: {
595
+ coin: {
596
+ value: "2500000",
597
+ },
598
+ deposit_events: {
599
+ counter: "8",
600
+ guid: {
601
+ id: {
602
+ addr: "0x4e5e",
603
+ creation_num: "4",
604
+ },
605
+ },
606
+ },
607
+ frozen: false,
608
+ withdraw_events: {
609
+ counter: "6",
610
+ guid: {
611
+ id: {
612
+ addr: "0x4e5e",
613
+ creation_num: "5",
614
+ },
615
+ },
616
+ },
617
+ },
618
+ },
619
+ type: "write_resource",
620
+ },
621
+ {
622
+ address: "0xa0d8",
623
+ state_key_hash: "0x1709",
624
+ data: {
625
+ type: "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>",
626
+ data: {
627
+ coin: {
628
+ value: "68255318",
629
+ },
630
+ deposit_events: {
631
+ counter: "46",
632
+ guid: {
633
+ id: {
634
+ addr: "0xa0d8",
635
+ creation_num: "2",
636
+ },
637
+ },
638
+ },
639
+ frozen: false,
640
+ withdraw_events: {
641
+ counter: "89",
642
+ guid: {
643
+ id: {
644
+ addr: "0xa0d8",
645
+ creation_num: "3",
646
+ },
647
+ },
648
+ },
649
+ },
650
+ },
651
+ type: "write_resource",
652
+ },
653
+ {
654
+ address: "0xa0d8",
655
+ state_key_hash: "0x5520",
656
+ data: {
657
+ type: "0x1::coin::CoinStore<0xd111::staked_coin::StakedAptos>",
658
+ data: {
659
+ coin: {
660
+ value: "2500000",
661
+ },
662
+ deposit_events: {
663
+ counter: "7",
664
+ guid: {
665
+ id: {
666
+ addr: "0xa0d8",
667
+ creation_num: "10",
668
+ },
669
+ },
670
+ },
671
+ frozen: false,
672
+ withdraw_events: {
673
+ counter: "12",
674
+ guid: {
675
+ id: {
676
+ addr: "0xa0d8",
677
+ creation_num: "11",
678
+ },
679
+ },
680
+ },
681
+ },
682
+ },
683
+ type: "write_resource",
684
+ },
685
+ {
686
+ address: "0xa0d8",
687
+ state_key_hash: "0x6f1e",
688
+ data: {
689
+ type: "0x1::account::Account",
690
+ data: {
691
+ authentication_key: "0xa0d8",
692
+ coin_register_events: {
693
+ counter: "5",
694
+ guid: {
695
+ id: {
696
+ addr: "0xa0d8",
697
+ creation_num: "0",
698
+ },
699
+ },
700
+ },
701
+ guid_creation_num: "12",
702
+ key_rotation_events: {
703
+ counter: "0",
704
+ guid: {
705
+ id: {
706
+ addr: "0xa0d8",
707
+ creation_num: "1",
708
+ },
709
+ },
710
+ },
711
+ rotation_capability_offer: {
712
+ for: {
713
+ vec: [],
714
+ },
715
+ },
716
+ sequence_number: "121",
717
+ signer_capability_offer: {
718
+ for: {
719
+ vec: [],
720
+ },
721
+ },
722
+ },
723
+ },
724
+ type: "write_resource",
725
+ },
726
+ {
727
+ state_key_hash: "0x6e4b",
728
+ handle: "0x1b85",
729
+ key: "0x0619",
730
+ value: "0xe86e0039581497010000000000000000",
731
+ data: null,
732
+ type: "write_table_item",
733
+ },
734
+ ],
735
+ sender: "0xa0d8",
736
+ sequence_number: "120",
737
+ max_gas_amount: "12",
738
+ gas_unit_price: "100",
739
+ expiration_timestamp_secs: "1743176706",
740
+ payload: {
741
+ function: "0x1::aptos_account::transfer_coins",
742
+ type_arguments: ["0xd111::staked_coin::StakedAptos"],
743
+ arguments: ["0x4e5e", "2500000"],
744
+ type: "entry_function_payload",
745
+ },
746
+ signature: {
747
+ public_key: "0x474d",
748
+ signature: "0xb70e",
749
+ type: "ed25519_signature",
750
+ },
751
+ events: [
752
+ {
753
+ guid: {
754
+ creation_number: "11",
755
+ account_address: "0xa0d8",
756
+ },
757
+ sequence_number: "11",
758
+ type: "0x1::coin::WithdrawEvent",
759
+ data: {
760
+ amount: "2500000",
761
+ },
762
+ },
763
+ {
764
+ guid: {
765
+ creation_number: "4",
766
+ account_address: "0x4e5e",
767
+ },
768
+ sequence_number: "7",
769
+ type: "0x1::coin::DepositEvent",
770
+ data: {
771
+ amount: "2500000",
772
+ },
773
+ },
774
+ {
775
+ guid: {
776
+ creation_number: "0",
777
+ account_address: "0x0",
778
+ },
779
+ sequence_number: "0",
780
+ type: "0x1::transaction_fee::FeeStatement",
781
+ data: {
782
+ execution_gas_units: "6",
783
+ io_gas_units: "6",
784
+ storage_fee_octas: "0",
785
+ storage_fee_refund_octas: "0",
786
+ total_charge_gas_units: "12",
787
+ },
788
+ },
789
+ ],
790
+ timestamp: "1743176594693251",
791
+ type: "user_transaction",
792
+ block: {
793
+ height: 311942427,
794
+ hash: "0x8655",
795
+ },
796
+ },
797
+ ],
798
+ blockHeight: 316278241,
799
+ }));
800
+
801
+ const mockGetBalance = jest.fn().mockImplementation(() => BigNumber(5000000));
802
+ mockedAptosAPI.mockImplementation(() => ({
803
+ getAccountInfo: mockGetAccountInfo,
804
+ getBalance: mockGetBalance,
805
+ }));
806
+
807
+ const mockGetAccountSpy = jest.spyOn({ getAccount: mockGetAccountInfo }, "getAccount");
808
+
809
+ mockedDecodeTokenAccountId.mockReturnValue({
810
+ token: {
811
+ type: "TokenCurrency",
812
+ id: "aptos/coin/dstapt_0xd111::staked_coin::stakedaptos",
813
+ contractAddress: "0xd111::staked_coin::StakedAptos",
814
+ parentCurrency: {
815
+ type: "CryptoCurrency",
816
+ id: "aptos",
817
+ coinType: 637,
818
+ name: "Aptos",
819
+ managerAppName: "Aptos",
820
+ ticker: "APT",
821
+ scheme: "aptos",
822
+ color: "#231F20",
823
+ family: "aptos",
824
+ units: [
825
+ {
826
+ name: "APT",
827
+ code: "APT",
828
+ magnitude: 8,
829
+ },
830
+ ],
831
+ explorerViews: [
832
+ {
833
+ address: "https://explorer.aptoslabs.com/account/$address?network=mainnet",
834
+ tx: "https://explorer.aptoslabs.com/txn/$hash?network=mainnet",
835
+ },
836
+ ],
837
+ },
838
+ name: "dstAPT",
839
+ tokenType: "coin",
840
+ ticker: "dstAPT",
841
+ disableCountervalue: false,
842
+ delisted: false,
843
+ units: [
844
+ {
845
+ name: "dstAPT",
846
+ code: "dstAPT",
847
+ magnitude: 8,
848
+ },
849
+ ],
850
+ },
851
+ accountId: "js:2:aptos:6415:aptos",
852
+ });
853
+
854
+ const operations = [
855
+ {
856
+ id: "js:2:aptos:474d:aptos-0x3f35-OUT",
857
+ hash: "0x3f35",
858
+ type: "FEES",
859
+ value: BigNumber(1200),
860
+ fee: BigNumber(1200),
861
+ blockHash: "0x6d02",
862
+ blockHeight: 311948147,
863
+ senders: ["0xa0d8"],
864
+ recipients: ["0x4e5e"],
865
+ accountId: "js:2:aptos:474d:aptos",
866
+ date: new Date("2025-03-28T15:56:00.481Z"),
867
+ extra: {
868
+ version: "2532591427",
869
+ },
870
+ transactionSequenceNumber: 121,
871
+ hasFailed: false,
872
+ },
873
+ {
874
+ id: "js:2:aptos:474d:aptos-0x9a6b-OUT",
875
+ hash: "0x9a6b",
876
+ type: "FEES",
877
+ value: BigNumber(1200),
878
+ fee: BigNumber(1200),
879
+ blockHash: "0x8655",
880
+ blockHeight: 311942427,
881
+ senders: ["0xa0d8"],
882
+ recipients: ["0x4e5e"],
883
+ accountId: "js:2:aptos:474d:aptos",
884
+ date: new Date("2025-03-28T15:43:14.693Z"),
885
+ extra: {
886
+ version: "2532549325",
887
+ },
888
+ transactionSequenceNumber: 120,
889
+ hasFailed: false,
890
+ },
891
+ ] as Operation[];
892
+ const tokenOperations = [
893
+ {
894
+ id: "js:2:aptos:474d:aptos-0x3f35-OUT",
895
+ hash: "0x3f35",
896
+ type: "OUT",
897
+ value: BigNumber(1500000),
898
+ fee: BigNumber(1200),
899
+ blockHash: "0x6d02",
900
+ blockHeight: 311948147,
901
+ senders: ["0xa0d8"],
902
+ recipients: ["0x4e5e"],
903
+ accountId:
904
+ "js:2:aptos:474d:aptos+aptos%2Fcoin%2Fdstapt~!underscore!~0xd111%3A%3Astaked~!underscore!~coin%3A%3Astakedaptos",
905
+ date: new Date("2025-03-28T15:56:00.481Z"),
906
+ extra: {
907
+ version: "2532591427",
908
+ },
909
+ transactionSequenceNumber: 121,
910
+ hasFailed: false,
911
+ },
912
+ {
913
+ id: "js:2:aptos:474d:aptos-0x9a6b-OUT",
914
+ hash: "0x9a6b",
915
+ type: "OUT",
916
+ value: BigNumber(2500000),
917
+ fee: BigNumber(1200),
918
+ blockHash: "0x8655",
919
+ blockHeight: 311942427,
920
+ senders: ["0xa0d8"],
921
+ recipients: ["0x4e5e"],
922
+ accountId:
923
+ "js:2:aptos:474d:aptos+aptos%2Fcoin%2Fdstapt~!underscore!~0xd111%3A%3Astaked~!underscore!~coin%3A%3Astakedaptos",
924
+ date: new Date("2025-03-28T15:43:14.693Z"),
925
+ extra: {
926
+ version: "2532549325",
927
+ },
928
+ transactionSequenceNumber: 120,
929
+ hasFailed: false,
930
+ },
931
+ ] as Operation[];
932
+ jest.mocked(mergeOps).mockReturnValue(operations);
933
+ jest.mocked(txsToOps).mockReturnValue([operations, tokenOperations]);
934
+
935
+ const info = {
936
+ currency: {
937
+ type: "CryptoCurrency",
938
+ id: "aptos",
939
+ coinType: 637,
940
+ name: "Aptos",
941
+ managerAppName: "Aptos",
942
+ ticker: "APT",
943
+ scheme: "aptos",
944
+ color: "#231F20",
945
+ family: "aptos",
946
+ units: [
947
+ {
948
+ name: "APT",
949
+ code: "APT",
950
+ magnitude: 8,
951
+ },
952
+ ],
953
+ },
954
+ index: 0,
955
+ address: "0xa0d8",
956
+ derivationPath: "44'/637'/0'",
957
+ derivationMode: "aptos",
958
+ initialAccount: {
959
+ type: "Account",
960
+ id: "js:2:aptos:474d:aptos",
961
+ used: true,
962
+ seedIdentifier: "3086",
963
+ derivationMode: "aptos",
964
+ index: 0,
965
+ freshAddress: "0xa0d8",
966
+ freshAddressPath: "44'/637'/0'/0'/0'",
967
+ blockHeight: 316272224,
968
+ creationDate: "2025-01-16T14:17:41.076Z",
969
+ balance: BigNumber(68254118),
970
+ spendableBalance: BigNumber(68254118),
971
+ operations: [],
972
+ operationsCount: 0,
973
+ pendingOperations: [],
974
+ currency: {
975
+ type: "CryptoCurrency",
976
+ id: "aptos",
977
+ coinType: 637,
978
+ name: "Aptos",
979
+ managerAppName: "Aptos",
980
+ ticker: "APT",
981
+ scheme: "aptos",
982
+ color: "#231F20",
983
+ family: "aptos",
984
+ units: [
985
+ {
986
+ name: "APT",
987
+ code: "APT",
988
+ magnitude: 8,
989
+ },
990
+ ],
991
+ },
992
+ lastSyncDate: new Date(),
993
+ swapHistory: [],
994
+ balanceHistoryCache: emptyHistoryCache,
995
+ xpub: "474d",
996
+ subAccounts: [
997
+ {
998
+ type: "TokenAccount",
999
+ id: "js:2:aptos:474d:aptos+aptos%2Fcoin%2Fdstapt~!underscore!~0xd111%3A%3Astaked~!underscore!~coin%3A%3Astakedaptos",
1000
+ parentId: "js:2:aptos:474d:aptos",
1001
+ token: {
1002
+ type: "TokenCurrency",
1003
+ id: "aptos/coin/dstapt_0xd111::staked_coin::stakedaptos",
1004
+ contractAddress: "0xd111::staked_coin::StakedAptos",
1005
+ parentCurrency: {
1006
+ type: "CryptoCurrency",
1007
+ id: "aptos",
1008
+ coinType: 637,
1009
+ name: "Aptos",
1010
+ managerAppName: "Aptos",
1011
+ ticker: "APT",
1012
+ scheme: "aptos",
1013
+ color: "#231F20",
1014
+ family: "aptos",
1015
+ units: [
1016
+ {
1017
+ name: "APT",
1018
+ code: "APT",
1019
+ magnitude: 8,
1020
+ },
1021
+ ],
1022
+ },
1023
+ name: "dstAPT",
1024
+ tokenType: "coin",
1025
+ ticker: "dstAPT",
1026
+ disableCountervalue: false,
1027
+ delisted: false,
1028
+ units: [
1029
+ {
1030
+ name: "dstAPT",
1031
+ code: "dstAPT",
1032
+ magnitude: 8,
1033
+ },
1034
+ ],
1035
+ },
1036
+ balance: BigNumber(5000000),
1037
+ spendableBalance: BigNumber(5000000),
1038
+ creationDate: "2025-03-11T09:33:46.840Z",
1039
+ operations: [],
1040
+ operationsCount: 0,
1041
+ pendingOperations: [],
1042
+ swapHistory: [],
1043
+ balanceHistoryCache: emptyHistoryCache,
1044
+ },
1045
+ ],
1046
+ },
1047
+ } as unknown as AccountShapeInfo<Account>;
1048
+
1049
+ const result = await getAccountShape(info, {} as SyncConfig);
1050
+
1051
+ expect(result.operations).toHaveLength(2);
1052
+ expect(result.operations?.at(0)?.subOperations).toHaveLength(2);
1053
+ expect(result.operations?.at(1)?.subOperations).toHaveLength(2);
1054
+ expect(result.subAccounts).toHaveLength(1);
1055
+ expect(mockedAptosAPI).toHaveBeenCalledTimes(2);
1056
+ expect(mockGetAccountSpy).toHaveBeenCalledWith("0xa0d8");
1057
+ });
1058
+ });
1059
+
1060
+ describe("mergeSubAccounts", () => {
1061
+ const initialSubAccount = {
1062
+ type: "TokenAccount",
1063
+ id: "subAccountId",
1064
+ parentId: "accountId",
1065
+ token: {
1066
+ type: "TokenCurrency",
1067
+ id: "aptos/coin/dstapt_0xd111::staked_coin::stakedaptos",
1068
+ contractAddress: "0xd111::staked_coin::StakedAptos",
1069
+ parentCurrency: {
1070
+ type: "CryptoCurrency",
1071
+ id: "aptos",
1072
+ coinType: 637,
1073
+ name: "Aptos",
1074
+ managerAppName: "Aptos",
1075
+ ticker: "APT",
1076
+ scheme: "aptos",
1077
+ color: "#231F20",
1078
+ family: "aptos",
1079
+ units: [
1080
+ {
1081
+ name: "APT",
1082
+ code: "APT",
1083
+ magnitude: 8,
1084
+ },
1085
+ ],
1086
+ explorerViews: [
1087
+ {
1088
+ address: "https://explorer.aptoslabs.com/account/$address?network=mainnet",
1089
+ tx: "https://explorer.aptoslabs.com/txn/$hash?network=mainnet",
1090
+ },
1091
+ ],
1092
+ },
1093
+ name: "dstAPT",
1094
+ tokenType: "coin",
1095
+ ticker: "dstAPT",
1096
+ disableCountervalue: false,
1097
+ delisted: false,
1098
+ units: [
1099
+ {
1100
+ name: "dstAPT",
1101
+ code: "dstAPT",
1102
+ magnitude: 8,
1103
+ },
1104
+ ],
1105
+ },
1106
+ balance: BigNumber(100),
1107
+ spendableBalance: BigNumber(100),
1108
+ creationDate: new Date(),
1109
+ operationsCount: 0,
1110
+ operations: [],
1111
+ pendingOperations: [],
1112
+ balanceHistoryCache: emptyHistoryCache,
1113
+ swapHistory: [],
1114
+ } as TokenAccount;
1115
+
1116
+ const initialAccount = createFixtureAccount({
1117
+ subAccounts: [initialSubAccount],
1118
+ });
1119
+
1120
+ it("return new subAccount if no old subAccounts", () => {
1121
+ expect(mergeSubAccounts(undefined, [initialSubAccount])).toEqual([initialSubAccount]);
1122
+ });
1123
+
1124
+ it("merge subAccounts properly if initialAccount has the same as new subAccounts", () => {
1125
+ expect(mergeSubAccounts(initialAccount, [initialSubAccount])).toEqual([initialSubAccount]);
1126
+ });
1127
+
1128
+ it("adds new sub account to initialAccount properly", () => {
1129
+ const newSubAccount = {
1130
+ type: "TokenAccount",
1131
+ id: "js:2:aptos:474d:aptos+aptos%2Ffungible~!underscore!~asset%2Fcellana~!underscore!~0x2ebb",
1132
+ parentId: "js:2:aptos:474d:aptos",
1133
+ token: {
1134
+ type: "TokenCurrency",
1135
+ id: "aptos/fungible_asset/cellana_0x2ebb",
1136
+ contractAddress: "0x2ebb",
1137
+ parentCurrency: {
1138
+ type: "CryptoCurrency",
1139
+ id: "aptos",
1140
+ coinType: 637,
1141
+ name: "Aptos",
1142
+ managerAppName: "Aptos",
1143
+ ticker: "APT",
1144
+ scheme: "aptos",
1145
+ color: "#231F20",
1146
+ family: "aptos",
1147
+ units: [
1148
+ {
1149
+ name: "APT",
1150
+ code: "APT",
1151
+ magnitude: 8,
1152
+ },
1153
+ ],
1154
+ explorerViews: [
1155
+ {
1156
+ address: "https://explorer.aptoslabs.com/account/$address?network=mainnet",
1157
+ tx: "https://explorer.aptoslabs.com/txn/$hash?network=mainnet",
1158
+ },
1159
+ ],
1160
+ },
1161
+ name: "CELLANA",
1162
+ tokenType: "fungible_asset",
1163
+ ticker: "CELL",
1164
+ disableCountervalue: false,
1165
+ delisted: false,
1166
+ units: [
1167
+ {
1168
+ name: "CELLANA",
1169
+ code: "CELL",
1170
+ magnitude: 8,
1171
+ },
1172
+ ],
1173
+ },
1174
+ balance: BigNumber(22980368),
1175
+ spendableBalance: BigNumber(22980368),
1176
+ creationDate: new Date(),
1177
+ operationsCount: 0,
1178
+ operations: [],
1179
+ pendingOperations: [],
1180
+ swapHistory: [],
1181
+ balanceHistoryCache: emptyHistoryCache,
1182
+ } as TokenAccount;
1183
+ expect(mergeSubAccounts(initialAccount, [newSubAccount])).toEqual([
1184
+ initialSubAccount,
1185
+ newSubAccount,
1186
+ ]);
1187
+ });
1188
+
1189
+ it("merge subAccounts properly when new subAccounts is different", () => {
1190
+ expect(
1191
+ mergeSubAccounts(initialAccount, [{ ...initialSubAccount, balance: BigNumber(150) }]),
1192
+ ).toEqual([{ ...initialSubAccount, balance: BigNumber(150) }]);
1193
+ });
1194
+ });
1195
+
1196
+ describe("getSubAccountShape", () => {
1197
+ beforeEach(() => {
1198
+ mockedAptosAPI = jest.mocked(AptosAPI);
1199
+ });
1200
+
1201
+ afterEach(() => {
1202
+ jest.resetAllMocks();
1203
+ });
1204
+
1205
+ const currency = {
1206
+ type: "CryptoCurrency",
1207
+ id: "aptos",
1208
+ coinType: 637,
1209
+ name: "Aptos",
1210
+ managerAppName: "Aptos",
1211
+ ticker: "APT",
1212
+ scheme: "aptos",
1213
+ color: "#231F20",
1214
+ family: "aptos",
1215
+ units: [
1216
+ {
1217
+ name: "APT",
1218
+ code: "APT",
1219
+ magnitude: 8,
1220
+ },
1221
+ ],
1222
+ explorerViews: [
1223
+ {
1224
+ address: "https://explorer.aptoslabs.com/account/$address?network=mainnet",
1225
+ tx: "https://explorer.aptoslabs.com/txn/$hash?network=mainnet",
1226
+ },
1227
+ ],
1228
+ } as CryptoCurrency;
1229
+ const address = "0xa0d8";
1230
+ const parentId = "js:2:aptos:474d:aptos";
1231
+ const token = {
1232
+ type: "TokenCurrency",
1233
+ id: "aptos/coin/dstapt_0xd111::staked_coin::stakedaptos",
1234
+ contractAddress: "0xd111::staked_coin::StakedAptos",
1235
+ parentCurrency: {
1236
+ type: "CryptoCurrency",
1237
+ id: "aptos",
1238
+ coinType: 637,
1239
+ name: "Aptos",
1240
+ managerAppName: "Aptos",
1241
+ ticker: "APT",
1242
+ scheme: "aptos",
1243
+ color: "#231F20",
1244
+ family: "aptos",
1245
+ units: [
1246
+ {
1247
+ name: "APT",
1248
+ code: "APT",
1249
+ magnitude: 8,
1250
+ },
1251
+ ],
1252
+ explorerViews: [
1253
+ {
1254
+ address: "https://explorer.aptoslabs.com/account/$address?network=mainnet",
1255
+ tx: "https://explorer.aptoslabs.com/txn/$hash?network=mainnet",
1256
+ },
1257
+ ],
1258
+ },
1259
+ name: "dstAPT",
1260
+ tokenType: "coin",
1261
+ ticker: "dstAPT",
1262
+ disableCountervalue: false,
1263
+ delisted: false,
1264
+ units: [
1265
+ {
1266
+ name: "dstAPT",
1267
+ code: "dstAPT",
1268
+ magnitude: 8,
1269
+ },
1270
+ ],
1271
+ } as TokenCurrency;
1272
+ const firstOperationDate = new Date(10);
1273
+ const operations = [
1274
+ {
1275
+ id: "js:2:aptos:474d:aptos-0x2011-IN",
1276
+ hash: "0x2011",
1277
+ type: "IN",
1278
+ value: BigNumber(2000000),
1279
+ fee: BigNumber(1200),
1280
+ blockHash: "0xf29363a5a78d784c702a8ea352ac3e1461092cc2347b305adcace14aa7b15d60",
1281
+ blockHeight: 315151047,
1282
+ senders: ["0x4e5e"],
1283
+ recipients: ["0xa0d8"],
1284
+ accountId:
1285
+ "js:2:aptos:474d:aptos+aptos%2Fcoin%2Fdstapt~!underscore!~0xd111%3A%3Astaked~!underscore!~coin%3A%3Astakedaptos",
1286
+ date: new Date(1000),
1287
+ extra: {
1288
+ version: "2553182323",
1289
+ },
1290
+ transactionSequenceNumber: 32,
1291
+ hasFailed: false,
1292
+ },
1293
+ {
1294
+ id: "js:2:aptos:474d:aptos-0x06a6-IN",
1295
+ hash: "0x06a6",
1296
+ type: "IN",
1297
+ value: BigNumber(2000000),
1298
+ fee: BigNumber(1200),
1299
+ blockHash: "0xbae2",
1300
+ blockHeight: 313836935,
1301
+ senders: ["0x4e5e"],
1302
+ recipients: ["0xa0d8"],
1303
+ accountId:
1304
+ "js:2:aptos:474d:aptos+aptos%2Fcoin%2Fdstapt~!underscore!~0xd111%3A%3Astaked~!underscore!~coin%3A%3Astakedaptos",
1305
+ date: firstOperationDate,
1306
+ extra: {
1307
+ version: "2544815758",
1308
+ },
1309
+ transactionSequenceNumber: 31,
1310
+ hasFailed: false,
1311
+ },
1312
+ ] as Operation[];
1313
+
1314
+ it("returns the correct information", async () => {
1315
+ const mockGetBalance = jest.fn().mockImplementation(() => BigNumber(1234567));
1316
+ mockedAptosAPI.mockImplementation(() => ({
1317
+ getBalance: mockGetBalance,
1318
+ }));
1319
+
1320
+ const subAccount = await getSubAccountShape(currency, address, parentId, token, operations);
1321
+
1322
+ expect(subAccount).toEqual({
1323
+ type: "TokenAccount",
1324
+ id: "js:2:aptos:474d:aptos+aptos%2Fcoin%2Fdstapt~!underscore!~0xd111%3A%3Astaked~!underscore!~coin%3A%3Astakedaptos",
1325
+ parentId,
1326
+ token,
1327
+ balance: BigNumber(1234567),
1328
+ spendableBalance: BigNumber(1234567),
1329
+ creationDate: firstOperationDate,
1330
+ operations,
1331
+ operationsCount: operations.length,
1332
+ pendingOperations: [],
1333
+ balanceHistoryCache: emptyHistoryCache,
1334
+ swapHistory: [],
1335
+ });
1336
+
1337
+ expect(mockedAptosAPI).toHaveBeenCalledTimes(1);
1338
+ });
1339
+ });
1340
+
1341
+ describe("getSubAccounts", () => {
1342
+ beforeEach(() => {
1343
+ mockedAptosAPI = jest.mocked(AptosAPI);
1344
+ });
1345
+
1346
+ afterEach(() => {
1347
+ jest.resetAllMocks();
1348
+ });
1349
+
1350
+ const address = "0x4e5e";
1351
+ const infos = {
1352
+ currency: {
1353
+ type: "CryptoCurrency",
1354
+ id: "aptos",
1355
+ coinType: 637,
1356
+ name: "Aptos",
1357
+ managerAppName: "Aptos",
1358
+ ticker: "APT",
1359
+ scheme: "aptos",
1360
+ color: "#231F20",
1361
+ family: "aptos",
1362
+ units: [
1363
+ {
1364
+ name: "APT",
1365
+ code: "APT",
1366
+ magnitude: 8,
1367
+ },
1368
+ ],
1369
+ explorerViews: [
1370
+ {
1371
+ address: "https://explorer.aptoslabs.com/account/$address?network=mainnet",
1372
+ tx: "https://explorer.aptoslabs.com/txn/$hash?network=mainnet",
1373
+ },
1374
+ ],
1375
+ },
1376
+ address,
1377
+ index: 1,
1378
+ derivationPath: "44'/637'/0'",
1379
+ derivationMode: "aptos",
1380
+ } as AccountShapeInfo<Account>;
1381
+ const accountId = "js:2:aptos:3282:aptos";
1382
+ const lastTokenOperations = [
1383
+ {
1384
+ id: "js:2:aptos:474d:aptos-0x2011-IN",
1385
+ hash: "0x2011",
1386
+ type: "IN",
1387
+ value: BigNumber(2000000),
1388
+ fee: BigNumber(1200),
1389
+ blockHash: "0xf29363a5a78d784c702a8ea352ac3e1461092cc2347b305adcace14aa7b15d60",
1390
+ blockHeight: 315151047,
1391
+ senders: ["0x4e5e"],
1392
+ recipients: ["0xa0d8"],
1393
+ accountId:
1394
+ "js:2:aptos:474d:aptos+aptos%2Fcoin%2Fdstapt~!underscore!~0xd111%3A%3Astaked~!underscore!~coin%3A%3Astakedaptos",
1395
+ date: new Date(1000),
1396
+ extra: {
1397
+ version: "2553182323",
1398
+ },
1399
+ transactionSequenceNumber: 32,
1400
+ hasFailed: false,
1401
+ },
1402
+ {
1403
+ id: "js:2:aptos:474d:aptos-0x06a6-IN",
1404
+ hash: "0x06a6",
1405
+ type: "IN",
1406
+ value: BigNumber(2000000),
1407
+ fee: BigNumber(1200),
1408
+ blockHash: "0xbae2",
1409
+ blockHeight: 313836935,
1410
+ senders: ["0x4e5e"],
1411
+ recipients: ["0xa0d8"],
1412
+ accountId:
1413
+ "js:2:aptos:474d:aptos+aptos%2Fcoin%2Fdstapt~!underscore!~0xd111%3A%3Astaked~!underscore!~coin%3A%3Astakedaptos",
1414
+ date: new Date(10),
1415
+ extra: {
1416
+ version: "2544815758",
1417
+ },
1418
+ transactionSequenceNumber: 31,
1419
+ hasFailed: false,
1420
+ },
1421
+ ] as Operation[];
1422
+
1423
+ it("returns the correct information", async () => {
1424
+ const mockGetBalance = jest.fn().mockImplementation(() => BigNumber(1234567));
1425
+ mockedAptosAPI.mockImplementation(() => ({
1426
+ getBalance: mockGetBalance,
1427
+ }));
1428
+
1429
+ mockedDecodeTokenAccountId.mockReturnValue({
1430
+ token: {
1431
+ type: "TokenCurrency",
1432
+ id: "aptos/coin/dstapt_0xd111::staked_coin::stakedaptos",
1433
+ contractAddress: "0xd111::staked_coin::StakedAptos",
1434
+ parentCurrency: {
1435
+ type: "CryptoCurrency",
1436
+ id: "aptos",
1437
+ coinType: 637,
1438
+ name: "Aptos",
1439
+ managerAppName: "Aptos",
1440
+ ticker: "APT",
1441
+ scheme: "aptos",
1442
+ color: "#231F20",
1443
+ family: "aptos",
1444
+ units: [
1445
+ {
1446
+ name: "APT",
1447
+ code: "APT",
1448
+ magnitude: 8,
1449
+ },
1450
+ ],
1451
+ explorerViews: [
1452
+ {
1453
+ address: "https://explorer.aptoslabs.com/account/$address?network=mainnet",
1454
+ tx: "https://explorer.aptoslabs.com/txn/$hash?network=mainnet",
1455
+ },
1456
+ ],
1457
+ },
1458
+ name: "dstAPT",
1459
+ tokenType: "coin",
1460
+ ticker: "dstAPT",
1461
+ disableCountervalue: false,
1462
+ delisted: false,
1463
+ units: [
1464
+ {
1465
+ name: "dstAPT",
1466
+ code: "dstAPT",
1467
+ magnitude: 8,
1468
+ },
1469
+ ],
1470
+ },
1471
+ accountId: "js:2:aptos:6415:aptos",
1472
+ });
1473
+
1474
+ const result = await getSubAccounts(infos, address, accountId, lastTokenOperations);
1475
+
1476
+ expect(result).toEqual([
1477
+ {
1478
+ type: "TokenAccount",
1479
+ id: "js:2:aptos:3282:aptos+aptos%2Fcoin%2Fdstapt~!underscore!~0xd111%3A%3Astaked~!underscore!~coin%3A%3Astakedaptos",
1480
+ parentId: "js:2:aptos:3282:aptos",
1481
+ token: {
1482
+ type: "TokenCurrency",
1483
+ id: "aptos/coin/dstapt_0xd111::staked_coin::stakedaptos",
1484
+ contractAddress: "0xd111::staked_coin::StakedAptos",
1485
+ parentCurrency: {
1486
+ type: "CryptoCurrency",
1487
+ id: "aptos",
1488
+ coinType: 637,
1489
+ name: "Aptos",
1490
+ managerAppName: "Aptos",
1491
+ ticker: "APT",
1492
+ scheme: "aptos",
1493
+ color: "#231F20",
1494
+ family: "aptos",
1495
+ units: [
1496
+ {
1497
+ name: "APT",
1498
+ code: "APT",
1499
+ magnitude: 8,
1500
+ },
1501
+ ],
1502
+ explorerViews: [
1503
+ {
1504
+ address: "https://explorer.aptoslabs.com/account/$address?network=mainnet",
1505
+ tx: "https://explorer.aptoslabs.com/txn/$hash?network=mainnet",
1506
+ },
1507
+ ],
1508
+ },
1509
+ name: "dstAPT",
1510
+ tokenType: "coin",
1511
+ ticker: "dstAPT",
1512
+ disableCountervalue: false,
1513
+ delisted: false,
1514
+ units: [
1515
+ {
1516
+ name: "dstAPT",
1517
+ code: "dstAPT",
1518
+ magnitude: 8,
1519
+ },
1520
+ ],
1521
+ },
1522
+ balance: BigNumber(1234567),
1523
+ spendableBalance: BigNumber(1234567),
1524
+ creationDate: new Date(10),
1525
+ operations: [
1526
+ {
1527
+ accountId:
1528
+ "js:2:aptos:474d:aptos+aptos%2Fcoin%2Fdstapt~!underscore!~0xd111%3A%3Astaked~!underscore!~coin%3A%3Astakedaptos",
1529
+ blockHash: "0xf29363a5a78d784c702a8ea352ac3e1461092cc2347b305adcace14aa7b15d60",
1530
+ blockHeight: 315151047,
1531
+ date: new Date(1000),
1532
+ extra: { version: "2553182323" },
1533
+ fee: BigNumber(1200),
1534
+ hasFailed: false,
1535
+ hash: "0x2011",
1536
+ id: "js:2:aptos:474d:aptos-0x2011-IN",
1537
+ recipients: ["0xa0d8"],
1538
+ senders: ["0x4e5e"],
1539
+ transactionSequenceNumber: 32,
1540
+ type: "IN",
1541
+ value: BigNumber(2000000),
1542
+ },
1543
+ {
1544
+ accountId:
1545
+ "js:2:aptos:474d:aptos+aptos%2Fcoin%2Fdstapt~!underscore!~0xd111%3A%3Astaked~!underscore!~coin%3A%3Astakedaptos",
1546
+ blockHash: "0xbae2",
1547
+ blockHeight: 313836935,
1548
+ date: new Date(10),
1549
+ fee: BigNumber(1200),
1550
+ extra: { version: "2544815758" },
1551
+ hasFailed: false,
1552
+ hash: "0x06a6",
1553
+ id: "js:2:aptos:474d:aptos-0x06a6-IN",
1554
+ recipients: ["0xa0d8"],
1555
+ senders: ["0x4e5e"],
1556
+ transactionSequenceNumber: 31,
1557
+ type: "IN",
1558
+ value: BigNumber(2000000),
1559
+ },
1560
+ ],
1561
+ operationsCount: 2,
1562
+ pendingOperations: [],
1563
+ balanceHistoryCache: emptyHistoryCache,
1564
+ swapHistory: [],
1565
+ },
1566
+ ]);
373
1567
  });
374
1568
  });