@ledgerhq/coin-evm 2.8.0 → 2.9.0-nightly.0

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 (42) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/lib/__tests__/coin-tester/indexer.js +1 -1
  3. package/lib/__tests__/coin-tester/indexer.js.map +1 -1
  4. package/lib/__tests__/unit/synchronization.unit.test.js +98 -5
  5. package/lib/__tests__/unit/synchronization.unit.test.js.map +1 -1
  6. package/lib/api/explorer/etherscan.d.ts.map +1 -1
  7. package/lib/api/explorer/etherscan.js +4 -0
  8. package/lib/api/explorer/etherscan.js.map +1 -1
  9. package/lib/api/explorer/index.d.ts.map +1 -1
  10. package/lib/api/explorer/index.js +3 -0
  11. package/lib/api/explorer/index.js.map +1 -1
  12. package/lib/api/explorer/none.d.ts +8 -0
  13. package/lib/api/explorer/none.d.ts.map +1 -0
  14. package/lib/api/explorer/none.js +29 -0
  15. package/lib/api/explorer/none.js.map +1 -0
  16. package/lib/config.d.ts +4 -0
  17. package/lib/config.d.ts.map +1 -1
  18. package/lib/config.js.map +1 -1
  19. package/lib-es/__tests__/coin-tester/indexer.js +1 -1
  20. package/lib-es/__tests__/coin-tester/indexer.js.map +1 -1
  21. package/lib-es/__tests__/unit/synchronization.unit.test.js +98 -5
  22. package/lib-es/__tests__/unit/synchronization.unit.test.js.map +1 -1
  23. package/lib-es/api/explorer/etherscan.d.ts.map +1 -1
  24. package/lib-es/api/explorer/etherscan.js +4 -0
  25. package/lib-es/api/explorer/etherscan.js.map +1 -1
  26. package/lib-es/api/explorer/index.d.ts.map +1 -1
  27. package/lib-es/api/explorer/index.js +3 -0
  28. package/lib-es/api/explorer/index.js.map +1 -1
  29. package/lib-es/api/explorer/none.d.ts +8 -0
  30. package/lib-es/api/explorer/none.d.ts.map +1 -0
  31. package/lib-es/api/explorer/none.js +25 -0
  32. package/lib-es/api/explorer/none.js.map +1 -0
  33. package/lib-es/config.d.ts +4 -0
  34. package/lib-es/config.d.ts.map +1 -1
  35. package/lib-es/config.js.map +1 -1
  36. package/package.json +4 -4
  37. package/src/__tests__/coin-tester/indexer.ts +1 -1
  38. package/src/__tests__/unit/synchronization.unit.test.ts +134 -7
  39. package/src/api/explorer/etherscan.ts +5 -0
  40. package/src/api/explorer/index.ts +3 -0
  41. package/src/api/explorer/none.ts +19 -0
  42. package/src/config.ts +5 -0
@@ -1,14 +1,17 @@
1
1
  import { AssertionError, fail } from "assert";
2
2
  import BigNumber from "bignumber.js";
3
3
  import { getEnv } from "@ledgerhq/live-env";
4
+ import { TokenAccount } from "@ledgerhq/types-live";
5
+ import { TokenCurrency } from "@ledgerhq/types-cryptoassets";
4
6
  import { decodeAccountId } from "@ledgerhq/coin-framework/account/accountId";
5
7
  import { AccountShapeInfo } from "@ledgerhq/coin-framework/bridge/jsHelpers";
6
- import { TokenCurrency } from "@ledgerhq/types-cryptoassets";
7
- import { TokenAccount } from "@ledgerhq/types-live";
8
8
  import { makeTokenAccount } from "../fixtures/common.fixtures";
9
9
  import * as etherscanAPI from "../../api/explorer/etherscan";
10
+ import { UnknownExplorer, UnknownNode } from "../../errors";
10
11
  import * as synchronization from "../../synchronization";
12
+ import * as noneExplorer from "../../api/explorer/none";
11
13
  import * as nodeApi from "../../api/node/rpc.common";
14
+ import { createSwapHistoryMap } from "../../logic";
12
15
  import {
13
16
  account,
14
17
  coinOperations,
@@ -23,10 +26,8 @@ import {
23
26
  internalOperations,
24
27
  swapHistory,
25
28
  } from "../fixtures/synchronization.fixtures";
26
- import { UnknownNode } from "../../errors";
27
- import * as logic from "../../logic";
28
29
  import { getCoinConfig } from "../../config";
29
- import { createSwapHistoryMap } from "../../logic";
30
+ import * as logic from "../../logic";
30
31
 
31
32
  jest.mock("../../api/node/rpc.common");
32
33
  jest.useFakeTimers().setSystemTime(new Date("2014-04-21"));
@@ -102,9 +103,13 @@ describe("EVM Family", () => {
102
103
  });
103
104
 
104
105
  it("should throw for currency with unsupported explorer", async () => {
105
- mockGetConfig.mockImplementationOnce((): any => {
106
+ mockGetConfig.mockImplementation((): any => {
106
107
  return {
107
108
  info: {
109
+ node: {
110
+ type: "external",
111
+ uri: "https://my-rpc.com",
112
+ },
108
113
  explorer: {
109
114
  uri: "http://nope.com",
110
115
  type: "unsupported" as any,
@@ -131,12 +136,54 @@ describe("EVM Family", () => {
131
136
  if (e instanceof AssertionError) {
132
137
  throw e;
133
138
  }
134
- expect(e).toBeInstanceOf(UnknownNode);
139
+ expect(e).toBeInstanceOf(UnknownExplorer);
135
140
  }
136
141
  });
137
142
 
143
+ it("shouldn't throw for none explorer config", async () => {
144
+ mockGetConfig.mockImplementation((): any => {
145
+ return {
146
+ info: {
147
+ node: {
148
+ type: "external",
149
+ uri: "https://my-rpc.com",
150
+ },
151
+ explorer: {
152
+ type: "none",
153
+ },
154
+ },
155
+ };
156
+ });
157
+ const spy = jest.spyOn(noneExplorer?.default, "getLastOperations");
158
+
159
+ await synchronization.getAccountShape(
160
+ {
161
+ ...getAccountShapeParameters,
162
+ currency: {
163
+ ...currency,
164
+ ethereumLikeInfo: {
165
+ chainId: 1,
166
+ } as any,
167
+ },
168
+ },
169
+ {} as any,
170
+ );
171
+
172
+ expect(spy).toHaveBeenCalledTimes(1);
173
+ expect(spy).toHaveReturnedWith(
174
+ Promise.resolve({
175
+ lastCoinOperations: [],
176
+ lastTokenOperations: [],
177
+ lastNftOperations: [],
178
+ lastInternalOperations: [],
179
+ }),
180
+ );
181
+ });
182
+
138
183
  describe("With no transactions fetched", () => {
139
184
  beforeAll(() => {
185
+ // @ts-expect-error reseting cache
186
+ etherscanAPI?.default.getLastOperations.reset();
140
187
  jest.spyOn(etherscanAPI, "getLastOperations").mockImplementation(() =>
141
188
  Promise.resolve({
142
189
  lastCoinOperations: [],
@@ -265,6 +312,8 @@ describe("EVM Family", () => {
265
312
 
266
313
  describe("With transactions fetched", () => {
267
314
  beforeAll(() => {
315
+ // @ts-expect-error reseting cache
316
+ etherscanAPI?.default.getLastOperations.reset();
268
317
  jest
269
318
  .spyOn(etherscanAPI, "getLastCoinOperations")
270
319
  .mockImplementation(() =>
@@ -524,6 +573,84 @@ describe("EVM Family", () => {
524
573
  expect(accountShape.operations).toEqual([coinOperations[0]]);
525
574
  });
526
575
  });
576
+
577
+ describe("With Blockscout", () => {
578
+ beforeAll(() => {
579
+ // @ts-expect-error reseting cache
580
+ etherscanAPI?.default.getLastOperations.reset();
581
+ jest
582
+ .spyOn(etherscanAPI, "getLastCoinOperations")
583
+ .mockImplementation(() =>
584
+ Promise.resolve([{ ...coinOperations[0] }, { ...coinOperations[1] }]),
585
+ );
586
+ jest
587
+ .spyOn(etherscanAPI, "getLastTokenOperations")
588
+ .mockImplementation(() =>
589
+ Promise.resolve([{ ...tokenOperations[0] }, { ...tokenOperations[1] }]),
590
+ );
591
+
592
+ jest
593
+ .spyOn(etherscanAPI, "getLastERC721Operations")
594
+ .mockImplementation(() =>
595
+ Promise.resolve([
596
+ { ...erc721Operations[0] },
597
+ { ...erc721Operations[1] },
598
+ { ...erc721Operations[2] },
599
+ ]),
600
+ );
601
+ jest
602
+ .spyOn(etherscanAPI, "getLastInternalOperations")
603
+ .mockImplementation(() =>
604
+ Promise.resolve([
605
+ { ...internalOperations[0] },
606
+ { ...internalOperations[1] },
607
+ { ...internalOperations[2] },
608
+ ]),
609
+ );
610
+ jest
611
+ .spyOn(nodeApi, "getTokenBalance")
612
+ .mockImplementation(async (a, b, contractAddress) => {
613
+ if (contractAddress === tokenCurrencies[0].contractAddress) {
614
+ return new BigNumber(10000);
615
+ }
616
+ throw new Error("Shouldn't be trying to fetch this token balance");
617
+ });
618
+ });
619
+
620
+ afterAll(() => {
621
+ jest.restoreAllMocks();
622
+ });
623
+
624
+ it("should never call ERC1155 endpoint", async () => {
625
+ mockGetConfig.mockImplementation((): any => {
626
+ return {
627
+ info: {
628
+ node: {
629
+ type: "external",
630
+ uri: "https://my-rpc.com",
631
+ },
632
+ explorer: {
633
+ type: "blockscout",
634
+ uri: "https://api.com",
635
+ },
636
+ },
637
+ };
638
+ });
639
+ console.log(etherscanAPI?.default.getLastOperations);
640
+ const spy = jest.spyOn(etherscanAPI, "getLastERC1155Operations");
641
+
642
+ await synchronization.getAccountShape(
643
+ {
644
+ ...getAccountShapeParameters,
645
+ initialAccount: account,
646
+ },
647
+ {} as any,
648
+ );
649
+
650
+ expect(spy).toHaveBeenCalledTimes(1);
651
+ expect(spy).toHaveReturnedWith(Promise.resolve([]));
652
+ });
653
+ });
527
654
  });
528
655
 
529
656
  describe("getSubAccounts", () => {
@@ -211,6 +211,11 @@ export const getLastERC1155Operations = async (
211
211
  throw new EtherscanLikeExplorerUsedIncorrectly();
212
212
  }
213
213
 
214
+ // Blockscout has no ERC1155 support yet
215
+ if (explorer.type === "blockscout") {
216
+ return [];
217
+ }
218
+
214
219
  const ops = await fetchWithRetries<EtherscanERC1155Event[]>({
215
220
  method: "GET",
216
221
  url: `${explorer.uri}?module=account&action=token1155tx&address=${address}`,
@@ -4,6 +4,7 @@ import { getCoinConfig } from "../../config";
4
4
  import etherscanLikeApi from "./etherscan";
5
5
  import ledgerExplorerApi from "./ledger";
6
6
  import { ExplorerApi } from "./types";
7
+ import noExplorerAPI from "./none";
7
8
 
8
9
  /**
9
10
  * Switch to select one of the compatible explorer
@@ -20,6 +21,8 @@ export const getExplorerApi = (currency: CryptoCurrency): ExplorerApi => {
20
21
  return etherscanLikeApi;
21
22
  case "ledger":
22
23
  return ledgerExplorerApi;
24
+ case "none":
25
+ return noExplorerAPI;
23
26
 
24
27
  default:
25
28
  throw new UnknownExplorer(`Unknown explorer for currency: ${currency.id}`);
@@ -0,0 +1,19 @@
1
+ import { ExplorerApi } from "./types";
2
+
3
+ /**
4
+ * Returns all operation types from an address
5
+ */
6
+ export const getLastOperations: ExplorerApi["getLastOperations"] = async () => {
7
+ return {
8
+ lastCoinOperations: [],
9
+ lastTokenOperations: [],
10
+ lastNftOperations: [],
11
+ lastInternalOperations: [],
12
+ };
13
+ };
14
+
15
+ const noExplorerAPI: ExplorerApi = {
16
+ getLastOperations,
17
+ };
18
+
19
+ export default noExplorerAPI;
package/src/config.ts CHANGED
@@ -19,6 +19,11 @@ type EvmConfig = {
19
19
  | {
20
20
  type: "ledger";
21
21
  explorerId: LedgerExplorerId;
22
+ }
23
+ | {
24
+ type: "none";
25
+ uri?: never;
26
+ explorerId?: never;
22
27
  };
23
28
  gasTracker?: {
24
29
  type: "ledger";