@ledgerhq/coin-polkadot 6.13.1-nightly.20251202023925 → 6.14.0-nightly.20251203101856

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 (53) hide show
  1. package/CHANGELOG.md +10 -6
  2. package/lib/bridge/preload.d.ts.map +1 -1
  3. package/lib/bridge/preload.js +7 -1
  4. package/lib/bridge/preload.js.map +1 -1
  5. package/lib/network/index.d.ts +3 -3
  6. package/lib/network/index.d.ts.map +1 -1
  7. package/lib/network/index.js.map +1 -1
  8. package/lib/network/node/validators.d.ts.map +1 -1
  9. package/lib/network/node/validators.js +7 -3
  10. package/lib/network/node/validators.js.map +1 -1
  11. package/lib/network/sidecar.d.ts +4 -4
  12. package/lib/network/sidecar.d.ts.map +1 -1
  13. package/lib/network/sidecar.js +14 -3
  14. package/lib/network/sidecar.js.map +1 -1
  15. package/lib/network/sidecar.mock.d.ts +1 -1
  16. package/lib/network/sidecar.mock.d.ts.map +1 -1
  17. package/lib/network/sidecar.mock.js +1 -1
  18. package/lib/network/sidecar.mock.js.map +1 -1
  19. package/lib/test/bridgeDatasetTest.d.ts.map +1 -1
  20. package/lib/test/bridgeDatasetTest.js +10 -17
  21. package/lib/test/bridgeDatasetTest.js.map +1 -1
  22. package/lib-es/bridge/preload.d.ts.map +1 -1
  23. package/lib-es/bridge/preload.js +7 -1
  24. package/lib-es/bridge/preload.js.map +1 -1
  25. package/lib-es/network/index.d.ts +3 -3
  26. package/lib-es/network/index.d.ts.map +1 -1
  27. package/lib-es/network/index.js.map +1 -1
  28. package/lib-es/network/node/validators.d.ts.map +1 -1
  29. package/lib-es/network/node/validators.js +7 -3
  30. package/lib-es/network/node/validators.js.map +1 -1
  31. package/lib-es/network/sidecar.d.ts +4 -4
  32. package/lib-es/network/sidecar.d.ts.map +1 -1
  33. package/lib-es/network/sidecar.js +14 -3
  34. package/lib-es/network/sidecar.js.map +1 -1
  35. package/lib-es/network/sidecar.mock.d.ts +1 -1
  36. package/lib-es/network/sidecar.mock.d.ts.map +1 -1
  37. package/lib-es/network/sidecar.mock.js +1 -1
  38. package/lib-es/network/sidecar.mock.js.map +1 -1
  39. package/lib-es/test/bridgeDatasetTest.d.ts.map +1 -1
  40. package/lib-es/test/bridgeDatasetTest.js +10 -17
  41. package/lib-es/test/bridgeDatasetTest.js.map +1 -1
  42. package/package.json +5 -5
  43. package/src/api/index.integ.test.ts +7 -7
  44. package/src/bridge/preload.ts +8 -1
  45. package/src/bridge/synchronization.test.ts +167 -0
  46. package/src/logic/broadcast.test.ts +11 -8
  47. package/src/network/index.ts +2 -2
  48. package/src/network/node/validators.ts +8 -3
  49. package/src/network/sidecar.integ.test.ts +249 -90
  50. package/src/network/sidecar.mock.ts +1 -1
  51. package/src/network/sidecar.ts +19 -7
  52. package/src/network/sidecar.unit.test.ts +7 -6
  53. package/src/test/bridgeDatasetTest.ts +10 -17
@@ -183,6 +183,173 @@ describe("getAccountShape", () => {
183
183
  expect(shape.operationsCount).toEqual(0);
184
184
  expect(shape.operations).toEqual([]);
185
185
  });
186
+
187
+ it("does not migrate when assethub has not been migrated", async () => {
188
+ mockGetCoinConfig.mockImplementation((currency?: CryptoCurrency): any => {
189
+ if (currency?.id === "assethub_polkadot") {
190
+ return {
191
+ hasBeenMigrated: false,
192
+ };
193
+ }
194
+ });
195
+
196
+ const initialAccount = undefined;
197
+ const accountInfo = createAccountInfo();
198
+ mockGetAccount.mockResolvedValue(accountInfo);
199
+ mockGetOperations.mockResolvedValue([]);
200
+
201
+ await getAccountShape(
202
+ {
203
+ index: -1,
204
+ derivationPath: "not used",
205
+ currency: CURRENCY,
206
+ address: "5D4yQHKfqCQYThhHmTfN1JEDi47uyDJc1xg9eZfAG1R7FC7J",
207
+ initialAccount,
208
+ derivationMode: "polkadotbip44",
209
+ },
210
+ { paginationConfig: {} },
211
+ );
212
+
213
+ expect(mockGetAccount).toHaveBeenCalledTimes(1);
214
+ expect(mockGetAccount.mock.lastCall[1]).toEqual(CURRENCY);
215
+ expect(mockGetOperations).toHaveBeenCalledTimes(1);
216
+ expect(mockGetOperations.mock.lastCall[2]).toEqual(CURRENCY);
217
+ });
218
+
219
+ it("does not migrate when currency is not polkadot", async () => {
220
+ const nonPolkadotCurrency = getCryptoCurrencyById("westend");
221
+ mockGetCoinConfig.mockImplementation((currency?: CryptoCurrency): any => {
222
+ if (currency?.id === "assethub_polkadot") {
223
+ return {
224
+ hasBeenMigrated: true,
225
+ };
226
+ }
227
+ });
228
+
229
+ const initialAccount = undefined;
230
+ const accountInfo = createAccountInfo();
231
+ mockGetAccount.mockResolvedValue(accountInfo);
232
+ mockGetOperations.mockResolvedValue([]);
233
+
234
+ await getAccountShape(
235
+ {
236
+ index: -1,
237
+ derivationPath: "not used",
238
+ currency: nonPolkadotCurrency,
239
+ address: "5D4yQHKfqCQYThhHmTfN1JEDi47uyDJc1xg9eZfAG1R7FC7J",
240
+ initialAccount,
241
+ derivationMode: "polkadotbip44",
242
+ },
243
+ { paginationConfig: {} },
244
+ );
245
+
246
+ expect(mockGetAccount).toHaveBeenCalledTimes(1);
247
+ expect(mockGetAccount.mock.lastCall[1]).toEqual(nonPolkadotCurrency);
248
+ expect(mockGetOperations).toHaveBeenCalledTimes(1);
249
+ expect(mockGetOperations.mock.lastCall[2]).toEqual(nonPolkadotCurrency);
250
+ });
251
+
252
+ it("generates correct account ID with migration", async () => {
253
+ const initialAccount = undefined;
254
+ const accountInfo = createAccountInfo();
255
+ mockGetAccount.mockResolvedValue(accountInfo);
256
+ mockGetOperations.mockResolvedValue([]);
257
+
258
+ const shape = await getAccountShape(
259
+ {
260
+ index: -1,
261
+ derivationPath: "not used",
262
+ currency: CURRENCY,
263
+ address: "5D4yQHKfqCQYThhHmTfN1JEDi47uyDJc1xg9eZfAG1R7FC7J",
264
+ initialAccount,
265
+ derivationMode: "polkadotbip44",
266
+ },
267
+ { paginationConfig: {} },
268
+ );
269
+
270
+ expect(shape.id).toEqual(
271
+ "js:2:assethub_polkadot:5D4yQHKfqCQYThhHmTfN1JEDi47uyDJc1xg9eZfAG1R7FC7J:polkadotbip44",
272
+ );
273
+ });
274
+
275
+ it("generates correct account ID without migration", async () => {
276
+ mockGetCoinConfig.mockImplementation((currency?: CryptoCurrency): any => {
277
+ if (currency?.id === "assethub_polkadot") {
278
+ return {
279
+ hasBeenMigrated: false,
280
+ };
281
+ }
282
+ });
283
+
284
+ const initialAccount = undefined;
285
+ const accountInfo = createAccountInfo();
286
+ mockGetAccount.mockResolvedValue(accountInfo);
287
+ mockGetOperations.mockResolvedValue([]);
288
+
289
+ const shape = await getAccountShape(
290
+ {
291
+ index: -1,
292
+ derivationPath: "not used",
293
+ currency: CURRENCY,
294
+ address: "5D4yQHKfqCQYThhHmTfN1JEDi47uyDJc1xg9eZfAG1R7FC7J",
295
+ initialAccount,
296
+ derivationMode: "polkadotbip44",
297
+ },
298
+ { paginationConfig: {} },
299
+ );
300
+
301
+ expect(shape.id).toEqual(
302
+ "js:2:polkadot:5D4yQHKfqCQYThhHmTfN1JEDi47uyDJc1xg9eZfAG1R7FC7J:polkadotbip44",
303
+ );
304
+ });
305
+
306
+ it("returns correct currency in account shape", async () => {
307
+ const accountInfo = createAccountInfo();
308
+ mockGetAccount.mockResolvedValue(accountInfo);
309
+ mockGetOperations.mockResolvedValue([]);
310
+
311
+ const shape = await getAccountShape(
312
+ {
313
+ index: -1,
314
+ derivationPath: "not used",
315
+ currency: CURRENCY,
316
+ address: "5D4yQHKfqCQYThhHmTfN1JEDi47uyDJc1xg9eZfAG1R7FC7J",
317
+ initialAccount: undefined,
318
+ derivationMode: "polkadotbip44",
319
+ },
320
+ { paginationConfig: {} },
321
+ );
322
+
323
+ expect(shape.currency).toEqual(EXPECTED_CURRENCY);
324
+ });
325
+
326
+ it("returns correct currency in account shape without migration", async () => {
327
+ mockGetCoinConfig.mockImplementation((currency?: CryptoCurrency): any => {
328
+ if (currency?.id === "assethub_polkadot") {
329
+ return {
330
+ hasBeenMigrated: false,
331
+ };
332
+ }
333
+ });
334
+
335
+ const accountInfo = createAccountInfo();
336
+ mockGetAccount.mockResolvedValue(accountInfo);
337
+ mockGetOperations.mockResolvedValue([]);
338
+
339
+ const shape = await getAccountShape(
340
+ {
341
+ index: -1,
342
+ derivationPath: "not used",
343
+ currency: CURRENCY,
344
+ address: "5D4yQHKfqCQYThhHmTfN1JEDi47uyDJc1xg9eZfAG1R7FC7J",
345
+ initialAccount: undefined,
346
+ derivationMode: "polkadotbip44",
347
+ },
348
+ { paginationConfig: {} },
349
+ );
350
+
351
+ expect(shape.currency).toEqual(CURRENCY);
352
+ });
186
353
  });
187
354
 
188
355
  function createAccountInfo() {
@@ -15,16 +15,19 @@ describe("broadcast", () => {
15
15
  submitExtrinsicMock.mockClear();
16
16
  });
17
17
 
18
- it("should broadcast using currency when provided", async () => {
19
- const signature = "some random signature";
20
- await broadcast(signature, "polkadot");
18
+ it.each(["polkadot", "assethub_polkadot", "westend", "assethub_westend"])(
19
+ "should broadcast using %s when provided",
20
+ async currencyId => {
21
+ const signature = "some random signature";
22
+ await broadcast(signature, currencyId);
21
23
 
22
- expect(submitExtrinsicMock).toHaveBeenCalledTimes(1);
23
- expect(submitExtrinsicMock.mock.lastCall[0]).toEqual(signature);
24
+ expect(submitExtrinsicMock).toHaveBeenCalledTimes(1);
25
+ expect(submitExtrinsicMock.mock.lastCall[0]).toEqual(signature);
24
26
 
25
- const currency = getCryptoCurrencyById("polkadot");
26
- expect(submitExtrinsicMock.mock.lastCall[1]).toEqual(currency);
27
- });
27
+ const currency = getCryptoCurrencyById(currencyId);
28
+ expect(submitExtrinsicMock.mock.lastCall[1]).toEqual(currency);
29
+ },
30
+ );
28
31
 
29
32
  it("should broadcast using only signature when no currency provided", async () => {
30
33
  const signature = "some random signature";
@@ -99,7 +99,7 @@ const isControllerAddress = makeLRUCache(
99
99
  minutes(5),
100
100
  );
101
101
  const isElectionClosed = makeLRUCache(
102
- (currency: CryptoCurrency | undefined) => sidecarIsElectionClosed(currency),
102
+ (currency: CryptoCurrency) => sidecarIsElectionClosed(currency),
103
103
  () => "",
104
104
  minutes(1),
105
105
  );
@@ -139,7 +139,7 @@ const shortenMetadata = async (transaction: string, currency?: CryptoCurrency):
139
139
  };
140
140
 
141
141
  export default {
142
- getAccount: async (address: string, currency?: CryptoCurrency): Promise<PolkadotAPIAccount> =>
142
+ getAccount: async (address: string, currency: CryptoCurrency): Promise<PolkadotAPIAccount> =>
143
143
  sidecardGetAccount(address, currency),
144
144
  getBalances: async (
145
145
  address: string,
@@ -29,11 +29,16 @@ export const fetchValidators = async (
29
29
  const api = await getApiPromise(currency);
30
30
 
31
31
  const [activeOpt, allStashes, elected] = await Promise.all([
32
- api.query.staking.activeEra(),
33
- api.derive.staking.stashes(),
34
- api.query.session.validators(),
32
+ // staking can be undefined if the currency is not supported
33
+ api.query.staking?.activeEra?.(),
34
+ api.derive.staking?.stashes?.(),
35
+ api.query.session?.validators?.(),
35
36
  ]);
36
37
 
38
+ if (!activeOpt) {
39
+ return [];
40
+ }
41
+
37
42
  const { index: activeEra } = activeOpt.unwrapOrDefault();
38
43
 
39
44
  let selected: string[] = [];
@@ -1,107 +1,266 @@
1
1
  import BigNumber from "bignumber.js";
2
- import { getAccount, getStakingInfo, getStakingProgress, getValidators } from "./sidecar";
2
+ import {
3
+ getAccount,
4
+ getStakingInfo,
5
+ getStakingProgress,
6
+ getValidators,
7
+ getBalances,
8
+ getMinimumBondBalance,
9
+ isElectionClosed,
10
+ isNewAccount,
11
+ isControllerAddress,
12
+ getTransactionParams,
13
+ getRegistry,
14
+ getLastBlock,
15
+ fetchChainSpec,
16
+ } from "./sidecar";
3
17
  import coinConfig from "../config";
4
18
  import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/currencies";
5
19
 
6
- const currency = getCryptoCurrencyById("polkadot");
7
-
8
- describe("sidecar integration test", () => {
9
- beforeAll(() => {
10
- coinConfig.setCoinConfig(() => ({
11
- status: {
12
- type: "active",
20
+ const CURRENCY_CONFIGS = {
21
+ polkadot: {
22
+ currency: getCryptoCurrencyById("polkadot"),
23
+ config: {
24
+ status: { type: "active" as const },
25
+ node: { url: "https://polkadot-rpc.publicnode.com" },
26
+ sidecar: { url: "https://polkadot-sidecar.coin.ledger.com" },
27
+ indexer: { url: "https://polkadot.coin.ledger.com" },
28
+ staking: { electionStatusThreshold: 25 },
29
+ metadataShortener: {
30
+ id: "dot",
31
+ url: "https://polkadot-metadata-shortener.api.live.ledger.com/transaction/metadata",
32
+ },
33
+ metadataHash: {
34
+ url: "https://polkadot-metadata-shortener.api.live.ledger.com/node/metadata/hash",
13
35
  },
14
- node: {
15
- url: "https://polkadot-rpc.publicnode.com",
36
+ },
37
+ testAddress: "163WJAxWrQzsAVEZdn2w6mq4gmT4FmEgvCfex3uEEUHTE9GL",
38
+ },
39
+ assethub_polkadot: {
40
+ currency: getCryptoCurrencyById("assethub_polkadot"),
41
+ config: {
42
+ status: { type: "active" as const },
43
+ sidecar: { url: "https://polkadot-asset-hub-sidecar.coin.ledger.com" },
44
+ node: { url: "https://polkadot-asset-hub-fullnodes.api.live.ledger.com" },
45
+ indexer: { url: "https://explorers.api.live.ledger.com/blockchain/dot_asset_hub" },
46
+ staking: { electionStatusThreshold: 25 },
47
+ metadataShortener: {
48
+ url: "https://polkadot-metadata-shortener.api.live.ledger.com/transaction/metadata",
49
+ id: "dot-hub",
16
50
  },
17
- sidecar: {
18
- url: "https://polkadot-sidecar.coin.ledger.com",
51
+ metadataHash: {
52
+ url: "https://polkadot-metadata-shortener.api.live.ledger.com/node/metadata/hash",
53
+ id: "dot-hub",
19
54
  },
20
- indexer: {
21
- url: "https://polkadot.coin.ledger.com",
55
+ hasBeenMigrated: true,
56
+ },
57
+ testAddress: "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
58
+ },
59
+ westend: {
60
+ currency: getCryptoCurrencyById("westend"),
61
+ config: {
62
+ status: { type: "active" as const },
63
+ sidecar: { url: "https://polkadot-westend-sidecar.coin.ledger.com/rc" },
64
+ node: { url: "https://polkadot-westend-fullnodes.api.live.ledger.com" },
65
+ indexer: { url: "https://explorers.api.live.ledger.com/blockchain/dot_westend" },
66
+ metadataShortener: {
67
+ url: "https://polkadot-westend-metadata-shortener.api.live.ledger.com/transaction/metadata",
68
+ id: "dot-hub",
22
69
  },
23
- staking: {
24
- electionStatusThreshold: 25,
70
+ metadataHash: {
71
+ url: "https://polkadot-westend-metadata-shortener.api.live.ledger.com/node/metadata/hash",
72
+ id: "dot-hub",
25
73
  },
74
+ },
75
+ testAddress: "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
76
+ },
77
+ assethub_westend: {
78
+ currency: getCryptoCurrencyById("assethub_westend"),
79
+ config: {
80
+ status: { type: "active" as const },
81
+ sidecar: { url: "https://polkadot-westend-sidecar.coin.ledger.com" },
82
+ node: { url: "https://polkadot-westend-asset-hub-fullnodes.api.live.ledger.com" },
83
+ indexer: { url: "https://explorers.api.live.ledger.com/blockchain/dot_asset_hub_westend" },
26
84
  metadataShortener: {
27
- id: "dot",
28
- url: "https://polkadot-metadata-shortener.api.live.ledger.com/transaction/metadata",
85
+ url: "https://polkadot-westend-metadata-shortener.api.live.ledger.com/transaction/metadata",
86
+ id: "dot-hub",
29
87
  },
30
88
  metadataHash: {
31
- url: "https://polkadot-metadata-shortener.api.live.ledger.com/node/metadata/hash",
89
+ url: "https://polkadot-westend-metadata-shortener.api.live.ledger.com/node/metadata/hash",
90
+ id: "dot-hub",
32
91
  },
33
- }));
34
- });
35
-
36
- describe("getStakingProgress", () => {
37
- it("returns expected result", async () => {
38
- const result = await getStakingProgress(currency);
39
-
40
- expect(result).toEqual({
41
- activeEra: expect.any(Number),
42
- bondingDuration: 28,
43
- electionClosed: true,
44
- maxNominatorRewardedPerValidator: 128,
92
+ },
93
+ testAddress: "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
94
+ },
95
+ };
96
+
97
+ describe("sidecar integration test", () => {
98
+ describe.each(Object.entries(CURRENCY_CONFIGS))(
99
+ "%s tests",
100
+ (currencyId, { currency, config, testAddress }) => {
101
+ beforeAll(() => {
102
+ coinConfig.setCoinConfig(() => config);
103
+ });
104
+
105
+ describe("getValidators", () => {
106
+ it(`returns expected result with ${currencyId}`, async () => {
107
+ const result = await getValidators(undefined, currency);
108
+
109
+ expect(result).toEqual(
110
+ expect.arrayContaining([
111
+ expect.objectContaining({
112
+ address: expect.any(String),
113
+ commission: expect.any(BigNumber),
114
+ identity: expect.any(String),
115
+ isElected: expect.any(Boolean),
116
+ isOversubscribed: expect.any(Boolean),
117
+ nominatorsCount: expect.any(Number),
118
+ selfBonded: expect.any(BigNumber),
119
+ totalBonded: expect.any(BigNumber),
120
+ }),
121
+ ]),
122
+ );
123
+ }, 10000); // 10 seconds, because more than 5s may be required
124
+ });
125
+
126
+ describe("getAccount", () => {
127
+ it(`works with ${currencyId}`, async () => {
128
+ const result = await getAccount(testAddress, currency);
129
+
130
+ expect(result).toMatchObject({
131
+ balance: expect.any(BigNumber),
132
+ blockHeight: expect.any(Number),
133
+ lockedBalance: expect.any(BigNumber),
134
+ nominations: expect.any(Array),
135
+ nonce: expect.any(Number),
136
+ spendableBalance: expect.any(BigNumber),
137
+ unlockedBalance: expect.any(BigNumber),
138
+ unlockingBalance: expect.any(BigNumber),
139
+ unlockings: expect.any(Array),
140
+ });
141
+ });
142
+ });
143
+
144
+ describe("getStakingInfo", () => {
145
+ it(`works with ${currencyId}`, async () => {
146
+ const result = await getStakingInfo(testAddress, currency);
147
+
148
+ expect(result).toMatchObject({
149
+ unlockedBalance: expect.any(BigNumber),
150
+ unlockingBalance: expect.any(BigNumber),
151
+ unlockings: expect.any(Array),
152
+ });
153
+ });
45
154
  });
46
- });
47
- });
48
-
49
- describe("getStakingInfo", () => {
50
- it("returns expected result", async () => {
51
- const address = "163WJAxWrQzsAVEZdn2w6mq4gmT4FmEgvCfex3uEEUHTE9GL";
52
- const result = await getStakingInfo(address, currency);
53
-
54
- expect(result).toEqual({
55
- controller: "163WJAxWrQzsAVEZdn2w6mq4gmT4FmEgvCfex3uEEUHTE9GL",
56
- numSlashingSpans: 0,
57
- stash: "163WJAxWrQzsAVEZdn2w6mq4gmT4FmEgvCfex3uEEUHTE9GL",
58
- unlockedBalance: BigNumber("0"),
59
- unlockingBalance: BigNumber("0"),
60
- unlockings: [],
155
+
156
+ describe("getStakingProgress", () => {
157
+ it(`works with ${currencyId}`, async () => {
158
+ const result = await getStakingProgress(currency);
159
+
160
+ expect(result).toMatchObject({
161
+ activeEra: expect.any(Number),
162
+ bondingDuration: expect.any(Number),
163
+ electionClosed: expect.any(Boolean),
164
+ maxNominatorRewardedPerValidator: expect.any(Number),
165
+ });
166
+ });
167
+ });
168
+
169
+ describe("getBalances", () => {
170
+ it(`works with ${currencyId}`, async () => {
171
+ const result = await getBalances(testAddress, currency);
172
+
173
+ expect(result).toMatchObject({
174
+ balance: expect.any(BigNumber),
175
+ blockHeight: expect.any(Number),
176
+ lockedBalance: expect.any(BigNumber),
177
+ nonce: expect.any(Number),
178
+ spendableBalance: expect.any(BigNumber),
179
+ });
180
+ });
181
+ });
182
+
183
+ describe("getMinimumBondBalance", () => {
184
+ it(`works with ${currencyId}`, async () => {
185
+ const result = await getMinimumBondBalance(currency);
186
+
187
+ expect(result).toBeInstanceOf(BigNumber);
188
+ expect(result.isGreaterThanOrEqualTo(0)).toBe(true);
189
+ });
190
+ });
191
+
192
+ describe("isElectionClosed", () => {
193
+ it(`works with ${currencyId}`, async () => {
194
+ const result = await isElectionClosed(currency);
195
+
196
+ expect(typeof result).toBe("boolean");
197
+ });
198
+ });
199
+
200
+ describe("isNewAccount", () => {
201
+ it(`works with ${currencyId}`, async () => {
202
+ const result = await isNewAccount(testAddress, currency);
203
+
204
+ expect(typeof result).toBe("boolean");
205
+ });
61
206
  });
62
- });
63
- });
64
-
65
- describe("getAccount", () => {
66
- it("returns expected result", async () => {
67
- const address = "163WJAxWrQzsAVEZdn2w6mq4gmT4FmEgvCfex3uEEUHTE9GL";
68
- const result = await getAccount(address, currency);
69
-
70
- expect(result).toMatchObject({
71
- balance: expect.any(BigNumber),
72
- // blockHeight: expect.any(Number),
73
- controller: "163WJAxWrQzsAVEZdn2w6mq4gmT4FmEgvCfex3uEEUHTE9GL",
74
- lockedBalance: expect.any(BigNumber),
75
- nominations: [],
76
- nonce: expect.any(Number),
77
- numSlashingSpans: 0,
78
- spendableBalance: expect.any(BigNumber),
79
- stash: "163WJAxWrQzsAVEZdn2w6mq4gmT4FmEgvCfex3uEEUHTE9GL",
80
- unlockedBalance: BigNumber("0"),
81
- unlockingBalance: BigNumber("0"),
82
- unlockings: [],
207
+
208
+ describe("isControllerAddress", () => {
209
+ it(`works with ${currencyId}`, async () => {
210
+ const result = await isControllerAddress(testAddress, currency);
211
+
212
+ expect(typeof result).toBe("boolean");
213
+ });
214
+ });
215
+
216
+ describe("getTransactionParams", () => {
217
+ it(`works with ${currencyId}`, async () => {
218
+ const result = await getTransactionParams(currency);
219
+
220
+ expect(result).toMatchObject({
221
+ blockHash: expect.any(String),
222
+ blockNumber: expect.any(String),
223
+ chainName: expect.any(String),
224
+ genesisHash: expect.any(String),
225
+ specName: expect.any(String),
226
+ transactionVersion: expect.any(String),
227
+ specVersion: expect.any(String),
228
+ });
229
+ });
230
+ });
231
+
232
+ describe("getRegistry", () => {
233
+ it(`works with ${currencyId}`, async () => {
234
+ const result = await getRegistry(currency);
235
+
236
+ expect(result).toMatchObject({
237
+ registry: expect.any(Object),
238
+ extrinsics: expect.any(Object),
239
+ });
240
+ });
241
+ });
242
+
243
+ describe("getLastBlock", () => {
244
+ it(`works with ${currencyId}`, async () => {
245
+ const result = await getLastBlock(currency);
246
+
247
+ expect(result).toMatchObject({
248
+ hash: expect.any(String),
249
+ height: expect.any(Number),
250
+ time: expect.any(Date),
251
+ });
252
+ });
253
+ });
254
+
255
+ describe("fetchChainSpec", () => {
256
+ it(`works with ${currencyId}`, async () => {
257
+ const result = await fetchChainSpec(currency);
258
+
259
+ expect(result).toMatchObject({
260
+ properties: expect.any(Object),
261
+ });
262
+ });
83
263
  });
84
- }, 10000);
85
- });
86
-
87
- describe("getValidators", () => {
88
- it.skip("returns expected result", async () => {
89
- const result = await getValidators(undefined, getCryptoCurrencyById("polkadot"));
90
-
91
- expect(result).toEqual(
92
- expect.arrayContaining([
93
- expect.objectContaining({
94
- address: "111B8CxcmnWbuDLyGvgUmRezDCK1brRZmvUuQ6SrFdMyc3S",
95
- commission: BigNumber("1"),
96
- identity: "",
97
- isElected: true,
98
- isOversubscribed: false,
99
- nominatorsCount: expect.any(Number),
100
- selfBonded: BigNumber("0"),
101
- totalBonded: expect.any(BigNumber),
102
- }),
103
- ]),
104
- );
105
- }, 10000); // 10 seconds, because more than 5s may be required
106
- });
264
+ },
265
+ );
107
266
  });
@@ -6,7 +6,7 @@ import {
6
6
  fixtureTxMaterialWithMetadata,
7
7
  } from "./sidecar.fixture";
8
8
 
9
- export const SIDECAR_BASE_URL_TEST = "https://polkadot-sidecar.coin.ledger.com";
9
+ export const SIDECAR_BASE_URL_TEST = "https://polkadot-asset-hub-sidecar.coin.ledger.com";
10
10
 
11
11
  const handlers = [
12
12
  http.get(`${SIDECAR_BASE_URL_TEST}/accounts/:addr/balance-info`, () => {
@@ -48,10 +48,10 @@ const getSidecarUrl = (route: string, currency?: CryptoCurrency): string => {
48
48
  route = `/rc${route}`;
49
49
  } else if (
50
50
  currency?.id === "westend" &&
51
- (route.startsWith("/pallets/staking") || route.startsWith("/transaction/material"))
51
+ (route.startsWith("/pallets/staking") || route.startsWith("/transaction"))
52
52
  ) {
53
53
  // Fetch Staking Info from Westend AssetHub (remove /rc)
54
- sidecarUrl = `${sidecarUrl.slice(0, -3)}`;
54
+ sidecarUrl = sidecarUrl.replace("/rc", "");
55
55
  }
56
56
  return `${sidecarUrl}${route || ""}`;
57
57
  };
@@ -61,6 +61,7 @@ const getElectionOptimisticThreshold = (currency?: CryptoCurrency): number => {
61
61
  };
62
62
 
63
63
  const VALIDATOR_COMISSION_RATIO = 1000000000;
64
+ const UNSUPPORTED_STAKING_NETWORKS = ["polkadot", "westend"];
64
65
 
65
66
  // blocks = 2 minutes 30
66
67
 
@@ -277,7 +278,9 @@ export const fetchChainSpec = async (currency?: CryptoCurrency) => {
277
278
  *
278
279
  * @returns {boolean}
279
280
  */
280
- export const isElectionClosed = async (currency?: CryptoCurrency): Promise<boolean> => {
281
+ export const isElectionClosed = async (currency: CryptoCurrency): Promise<boolean> => {
282
+ if (UNSUPPORTED_STAKING_NETWORKS.includes(currency.id)) return true;
283
+
281
284
  const progress = await fetchStakingProgress(currency);
282
285
  return !progress.electionStatus?.status?.Open;
283
286
  };
@@ -334,7 +337,7 @@ export const verifyValidatorAddresses = async (
334
337
  * @async
335
338
  * @param {*} addr
336
339
  */
337
- export const getAccount = async (addr: string, currency?: CryptoCurrency) => {
340
+ export const getAccount = async (addr: string, currency: CryptoCurrency) => {
338
341
  const balances = await getBalances(addr, currency);
339
342
  const stakingInfo = await getStakingInfo(addr, currency);
340
343
  const nominations = await getNominations(addr);
@@ -371,13 +374,13 @@ export const getBalances = async (addr: string, currency?: CryptoCurrency) => {
371
374
  * @async
372
375
  * @param {*} addr
373
376
  */
374
- export const getStakingInfo = async (addr: string, currency?: CryptoCurrency) => {
377
+ export const getStakingInfo = async (addr: string, currency: CryptoCurrency) => {
375
378
  const [stash, controller] = await Promise.all([
376
379
  fetchStashAddr(addr, currency),
377
380
  fetchControllerAddr(addr, currency),
378
381
  ]);
379
382
  // If account is not a stash, no need to fetch staking-info (it would return an error)
380
- if (!controller || currency?.id === "westend") {
383
+ if (!controller || UNSUPPORTED_STAKING_NETWORKS.includes(currency.id)) {
381
384
  return {
382
385
  controller: null,
383
386
  stash: stash || null,
@@ -566,8 +569,17 @@ export const getValidators = async (
566
569
  * @returns {PolkadotStakingProgress}
567
570
  */
568
571
  export const getStakingProgress = async (
569
- currency?: CryptoCurrency,
572
+ currency: CryptoCurrency,
570
573
  ): Promise<PolkadotStakingProgress> => {
574
+ if (UNSUPPORTED_STAKING_NETWORKS.includes(currency.id)) {
575
+ return {
576
+ electionClosed: true,
577
+ activeEra: 0,
578
+ maxNominatorRewardedPerValidator: 128,
579
+ bondingDuration: 28,
580
+ };
581
+ }
582
+
571
583
  const [progress, consts] = await Promise.all([
572
584
  fetchStakingProgress(currency),
573
585
  getConstants(currency),