@ledgerhq/live-common 21.13.2 → 21.14.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 (91) hide show
  1. package/lib/apps/polyfill.d.ts.map +1 -1
  2. package/lib/apps/polyfill.js +1 -0
  3. package/lib/apps/polyfill.js.map +1 -1
  4. package/lib/derivation.js +1 -1
  5. package/lib/derivation.js.map +1 -1
  6. package/lib/env.js +1 -1
  7. package/lib/env.js.map +1 -1
  8. package/lib/families/bitcoin/cache.d.ts +1 -0
  9. package/lib/families/bitcoin/cache.d.ts.map +1 -1
  10. package/lib/families/bitcoin/cache.js +7 -1
  11. package/lib/families/bitcoin/cache.js.map +1 -1
  12. package/lib/families/bitcoin/errors.d.ts +4 -0
  13. package/lib/families/bitcoin/errors.d.ts.map +1 -0
  14. package/lib/families/bitcoin/errors.js +6 -0
  15. package/lib/families/bitcoin/errors.js.map +1 -0
  16. package/lib/families/bitcoin/js-getTransactionStatus.d.ts.map +1 -1
  17. package/lib/families/bitcoin/js-getTransactionStatus.js +24 -11
  18. package/lib/families/bitcoin/js-getTransactionStatus.js.map +1 -1
  19. package/lib/families/bitcoin/js-synchronisation.js +2 -2
  20. package/lib/families/bitcoin/js-synchronisation.js.map +1 -1
  21. package/lib/families/bitcoin/wallet-btc/crypto/base.d.ts +4 -0
  22. package/lib/families/bitcoin/wallet-btc/crypto/base.d.ts.map +1 -1
  23. package/lib/families/bitcoin/wallet-btc/crypto/base.js +35 -5
  24. package/lib/families/bitcoin/wallet-btc/crypto/base.js.map +1 -1
  25. package/lib/families/bitcoin/wallet-btc/crypto/bitcoin.d.ts +1 -0
  26. package/lib/families/bitcoin/wallet-btc/crypto/bitcoin.d.ts.map +1 -1
  27. package/lib/families/bitcoin/wallet-btc/crypto/bitcoin.js +19 -1
  28. package/lib/families/bitcoin/wallet-btc/crypto/bitcoin.js.map +1 -1
  29. package/lib/families/bitcoin/wallet-btc/crypto/bitcoincash.d.ts +1 -0
  30. package/lib/families/bitcoin/wallet-btc/crypto/bitcoincash.d.ts.map +1 -1
  31. package/lib/families/bitcoin/wallet-btc/crypto/bitcoincash.js +4 -0
  32. package/lib/families/bitcoin/wallet-btc/crypto/bitcoincash.js.map +1 -1
  33. package/lib/families/bitcoin/wallet-btc/crypto/types.d.ts +1 -0
  34. package/lib/families/bitcoin/wallet-btc/crypto/types.d.ts.map +1 -1
  35. package/lib/families/bitcoin/wallet-btc/crypto/zec.d.ts +1 -0
  36. package/lib/families/bitcoin/wallet-btc/crypto/zec.d.ts.map +1 -1
  37. package/lib/families/bitcoin/wallet-btc/crypto/zec.js +4 -0
  38. package/lib/families/bitcoin/wallet-btc/crypto/zec.js.map +1 -1
  39. package/lib/families/bitcoin/wallet-btc/crypto/zen.d.ts +1 -0
  40. package/lib/families/bitcoin/wallet-btc/crypto/zen.d.ts.map +1 -1
  41. package/lib/families/bitcoin/wallet-btc/crypto/zen.js +4 -0
  42. package/lib/families/bitcoin/wallet-btc/crypto/zen.js.map +1 -1
  43. package/lib/families/bitcoin/wallet-btc/explorer/index.d.ts.map +1 -1
  44. package/lib/families/bitcoin/wallet-btc/explorer/index.js +0 -3
  45. package/lib/families/bitcoin/wallet-btc/explorer/index.js.map +1 -1
  46. package/lib/families/bitcoin/wallet-btc/index.d.ts +2 -2
  47. package/lib/families/bitcoin/wallet-btc/index.d.ts.map +1 -1
  48. package/lib/families/bitcoin/wallet-btc/index.js +4 -5
  49. package/lib/families/bitcoin/wallet-btc/index.js.map +1 -1
  50. package/lib/families/bitcoin/wallet-btc/utils.d.ts +1 -0
  51. package/lib/families/bitcoin/wallet-btc/utils.d.ts.map +1 -1
  52. package/lib/families/bitcoin/wallet-btc/utils.js +13 -1
  53. package/lib/families/bitcoin/wallet-btc/utils.js.map +1 -1
  54. package/lib/families/bitcoin/wallet-btc/xpub.d.ts +2 -6
  55. package/lib/families/bitcoin/wallet-btc/xpub.d.ts.map +1 -1
  56. package/lib/families/bitcoin/wallet-btc/xpub.js +62 -52
  57. package/lib/families/bitcoin/wallet-btc/xpub.js.map +1 -1
  58. package/lib/families/elrond/js-getTransactionStatus.d.ts.map +1 -1
  59. package/lib/families/elrond/js-getTransactionStatus.js +3 -0
  60. package/lib/families/elrond/js-getTransactionStatus.js.map +1 -1
  61. package/lib/families/elrond/js-signOperation.d.ts.map +1 -1
  62. package/lib/families/elrond/js-signOperation.js +3 -1
  63. package/lib/families/elrond/js-signOperation.js.map +1 -1
  64. package/lib/families/ethereum/specs.d.ts +1 -0
  65. package/lib/families/ethereum/specs.d.ts.map +1 -1
  66. package/lib/families/ethereum/specs.js +41 -0
  67. package/lib/families/ethereum/specs.js.map +1 -1
  68. package/lib/generated/specs.d.ts +1 -0
  69. package/lib/generated/specs.d.ts.map +1 -1
  70. package/package.json +4 -4
  71. package/src/apps/polyfill.ts +1 -0
  72. package/src/currencies/__snapshots__/sortByMarketcap.test.ts.snap +10 -1
  73. package/src/derivation.ts +1 -1
  74. package/src/env.ts +1 -1
  75. package/src/families/bitcoin/cache.ts +12 -0
  76. package/src/families/bitcoin/errors.ts +5 -0
  77. package/src/families/bitcoin/js-getTransactionStatus.ts +15 -1
  78. package/src/families/bitcoin/js-synchronisation.ts +2 -2
  79. package/src/families/bitcoin/wallet-btc/crypto/base.ts +39 -5
  80. package/src/families/bitcoin/wallet-btc/crypto/bitcoin.ts +21 -1
  81. package/src/families/bitcoin/wallet-btc/crypto/bitcoincash.ts +5 -0
  82. package/src/families/bitcoin/wallet-btc/crypto/types.ts +1 -0
  83. package/src/families/bitcoin/wallet-btc/crypto/zec.ts +5 -0
  84. package/src/families/bitcoin/wallet-btc/crypto/zen.ts +5 -0
  85. package/src/families/bitcoin/wallet-btc/explorer/index.ts +0 -5
  86. package/src/families/bitcoin/wallet-btc/index.ts +4 -4
  87. package/src/families/bitcoin/wallet-btc/utils.ts +10 -0
  88. package/src/families/bitcoin/wallet-btc/xpub.ts +37 -53
  89. package/src/families/elrond/js-getTransactionStatus.ts +4 -0
  90. package/src/families/elrond/js-signOperation.ts +3 -1
  91. package/src/families/ethereum/specs.ts +47 -0
@@ -102,6 +102,11 @@ class Zen implements ICrypto {
102
102
  (res[1] === 0x89 || res[1] === 0x96)
103
103
  );
104
104
  }
105
+
106
+ // eslint-disable-next-line class-methods-use-this
107
+ isTaprootAddress(address: string): boolean {
108
+ return false;
109
+ }
105
110
  }
106
111
 
107
112
  export default Zen;
@@ -285,12 +285,7 @@ class BitcoinLikeExplorer extends EventEmitter implements IExplorer {
285
285
 
286
286
  // faster than mapping
287
287
  res.txs.forEach((tx) => {
288
- if (!tx.block) {
289
- return;
290
- }
291
-
292
288
  this.hydrateTx(address, tx);
293
-
294
289
  hydratedTxs.push(tx);
295
290
  });
296
291
 
@@ -11,7 +11,7 @@ import { TX, Input, Output } from "./storage/types";
11
11
  import { CoinSelect } from "./pickingstrategies/CoinSelect";
12
12
  import { DeepFirst } from "./pickingstrategies/DeepFirst";
13
13
  import { Merge } from "./pickingstrategies/Merge";
14
- import { isValidAddress } from "./utils";
14
+ import { isValidAddress, isTaprootAddress } from "./utils";
15
15
 
16
16
  import type { Account as WalletAccount } from "./account";
17
17
  import type { Account as LiveAccount } from "./../../../types";
@@ -32,16 +32,16 @@ export {
32
32
  DeepFirst,
33
33
  Merge,
34
34
  isValidAddress,
35
+ isTaprootAddress,
35
36
  Currency,
36
37
  };
37
38
 
38
39
  let wallet: BitcoinLikeWallet | null = null;
39
40
 
40
41
  export const getWalletAccount = (account: LiveAccount): WalletAccount => {
41
- if (account.id.startsWith("libcore")) throw new AccountNeedResync();
42
42
  const walletAccount = account.bitcoinResources?.walletAccount;
43
- if (!walletAccount) {
44
- throw new Error("bitcoin wallet account expected");
43
+ if (account.id.startsWith("libcore") || !walletAccount) {
44
+ throw new AccountNeedResync();
45
45
  }
46
46
  return walletAccount;
47
47
  };
@@ -156,3 +156,13 @@ export function isValidAddress(address: string, currency?: Currency) {
156
156
  const crypto = cryptoFactory(currency);
157
157
  return crypto.validateAddress(address);
158
158
  }
159
+
160
+ export function isTaprootAddress(address: string, currency?: Currency) {
161
+ if (currency === "bitcoin") {
162
+ return cryptoFactory("bitcoin").isTaprootAddress(address);
163
+ } else if (currency === "bitcoin_testnet") {
164
+ return cryptoFactory("bitcoin_testnet").isTaprootAddress(address);
165
+ } else {
166
+ return false;
167
+ }
168
+ }
@@ -1,6 +1,6 @@
1
1
  import { maxBy, range, some } from "lodash";
2
2
  import BigNumber from "bignumber.js";
3
- import { Address, IStorage } from "./storage/types";
3
+ import { TX, Address, IStorage } from "./storage/types";
4
4
  import EventEmitter from "./utils/eventemitter";
5
5
  import { IExplorer } from "./explorer/types";
6
6
  import { ICrypto } from "./crypto/types";
@@ -20,9 +20,9 @@ class Xpub extends EventEmitter {
20
20
 
21
21
  derivationMode: string;
22
22
 
23
- freshAddress: { [key: string]: string } = {};
23
+ freshAddress: string;
24
24
 
25
- freshAddressIndex: { [key: string]: number } = {};
25
+ freshAddressIndex: number;
26
26
 
27
27
  // https://github.com/bitcoinjs/bitcoinjs-lib/blob/27a840aac4a12338f1e40c54f3759bbd7a559944/src/bufferutils.js#L24
28
28
  // only works with number so we need to be sure to pass correct numbers
@@ -54,6 +54,8 @@ class Xpub extends EventEmitter {
54
54
  this.crypto = crypto;
55
55
  this.xpub = xpub;
56
56
  this.derivationMode = derivationMode;
57
+ this.freshAddress = "";
58
+ this.freshAddressIndex = 0;
57
59
  }
58
60
 
59
61
  async syncAddress(account: number, index: number) {
@@ -78,9 +80,7 @@ class Xpub extends EventEmitter {
78
80
 
79
81
  // TODO handle eventual reorg case using lastBlock
80
82
 
81
- let added = 0;
82
83
  let total = 0;
83
-
84
84
  try {
85
85
  // TODO perf: bad : looping in the tx array
86
86
  await this.checkAddressReorg(account, index);
@@ -95,20 +95,7 @@ class Xpub extends EventEmitter {
95
95
  if (hasPendings) {
96
96
  await this.storage.removePendingTxs({ account, index });
97
97
  }
98
-
99
- // eslint-disable-next-line no-cond-assign,no-await-in-loop
100
- while (
101
- (added = await this.fetchHydrateAndStoreNewTxs(address, account, index))
102
- ) {
103
- total += added;
104
- }
105
-
106
- const pendingTxs = await this.explorer.getPendings({
107
- address,
108
- account,
109
- index,
110
- });
111
- await this.storage.appendTxs(pendingTxs);
98
+ total = await this.fetchHydrateAndStoreNewTxs(address, account, index);
112
99
  } catch (e) {
113
100
  this.emitSyncedFailed(data);
114
101
  throw e;
@@ -120,11 +107,8 @@ class Xpub extends EventEmitter {
120
107
  account,
121
108
  index,
122
109
  });
123
- if (lastTx) {
124
- this.freshAddressIndex[account] = Math.max(
125
- this.freshAddressIndex[account],
126
- index + 1
127
- );
110
+ if (account === 0 && lastTx) {
111
+ this.freshAddressIndex = Math.max(this.freshAddressIndex, index + 1);
128
112
  }
129
113
  return !!lastTx;
130
114
  }
@@ -137,13 +121,6 @@ class Xpub extends EventEmitter {
137
121
  }
138
122
 
139
123
  async syncAccount(account: number) {
140
- this.freshAddressIndex[account] = 0;
141
- this.freshAddress[account] = this.crypto.getAddress(
142
- this.derivationMode,
143
- this.xpub,
144
- account,
145
- 0
146
- );
147
124
  await this.whenSynced("account", account.toString());
148
125
 
149
126
  this.emitSyncing({
@@ -174,26 +151,19 @@ class Xpub extends EventEmitter {
174
151
  account,
175
152
  index,
176
153
  });
177
- this.freshAddress[account] = this.crypto.getAddress(
178
- this.derivationMode,
179
- this.xpub,
180
- account,
181
- this.freshAddressIndex[account]
182
- );
183
154
  return index;
184
155
  }
185
156
 
186
157
  // TODO : test fail case + incremental
187
158
  async sync() {
188
159
  await this.whenSynced("all");
189
-
190
160
  this.emitSyncing({ type: "all" });
191
-
161
+ this.freshAddressIndex = 0;
192
162
  let account = 0;
193
-
194
163
  try {
195
164
  // eslint-disable-next-line no-await-in-loop
196
- while (await this.syncAccount(account)) {
165
+ while (account < 2 && (await this.syncAccount(account))) {
166
+ // account=0 for receive address; account=1 for change address. No need to handle account>1
197
167
  account += 1;
198
168
  }
199
169
  } catch (e) {
@@ -202,7 +172,12 @@ class Xpub extends EventEmitter {
202
172
  }
203
173
 
204
174
  this.emitSynced({ type: "all", account });
205
-
175
+ this.freshAddress = this.crypto.getAddress(
176
+ this.derivationMode,
177
+ this.xpub,
178
+ 0,
179
+ this.freshAddressIndex
180
+ );
206
181
  return account;
207
182
  }
208
183
 
@@ -440,18 +415,27 @@ class Xpub extends EventEmitter {
440
415
  account: number,
441
416
  index: number
442
417
  ) {
443
- const lastTx = await this.storage.getLastTx({
444
- account,
445
- index,
446
- confirmed: true,
447
- });
418
+ let pendingTxs: TX[] = [];
419
+ let txs: TX[] = [];
420
+ let inserted = 0;
421
+ do {
422
+ const lastTx = await this.storage.getLastTx({
423
+ account,
424
+ index,
425
+ confirmed: true,
426
+ });
448
427
 
449
- const txs = await this.explorer.getAddressTxsSinceLastTxBlock(
450
- this.txsSyncArraySize,
451
- { address, account, index },
452
- lastTx
453
- );
454
- const inserted = await this.storage.appendTxs(txs);
428
+ txs = await this.explorer.getAddressTxsSinceLastTxBlock(
429
+ this.txsSyncArraySize,
430
+ { address, account, index },
431
+ lastTx
432
+ );
433
+ if (pendingTxs.length === 0) {
434
+ pendingTxs = txs.filter((tx) => !tx.block);
435
+ }
436
+ inserted += await this.storage.appendTxs(txs.filter((tx) => tx.block)); // only insert not pending tx
437
+ } while (txs.length - pendingTxs.length >= this.txsSyncArraySize); // check whether page is full, if not, it is the last page
438
+ inserted += await this.storage.appendTxs(pendingTxs);
455
439
  return inserted;
456
440
  }
457
441
 
@@ -32,6 +32,10 @@ const getTransactionStatus = async (
32
32
  }
33
33
 
34
34
  const estimatedFees = t.fees || new BigNumber(0);
35
+ if (estimatedFees.gt(a.balance)) {
36
+ errors.amount = new NotEnoughBalance();
37
+ }
38
+
35
39
  const totalSpent = useAllAmount
36
40
  ? a.balance
37
41
  : new BigNumber(t.amount).plus(estimatedFees);
@@ -15,7 +15,9 @@ const buildOptimisticOperation = (
15
15
  fee: BigNumber
16
16
  ): Operation => {
17
17
  const type = "OUT";
18
- const value = new BigNumber(transaction.amount);
18
+ const value = transaction.useAllAmount
19
+ ? account.balance.minus(fee)
20
+ : new BigNumber(transaction.amount);
19
21
  const operation: Operation = {
20
22
  id: encodeOperationId(account.id, "", type),
21
23
  hash: "",
@@ -445,8 +445,55 @@ const bsc: AppSpec<Transaction> = {
445
445
  ]),
446
446
  };
447
447
 
448
+ const polygon: AppSpec<Transaction> = {
449
+ name: "Polygon",
450
+ currency: getCryptoCurrencyById("polygon"),
451
+ appQuery: {
452
+ model: DeviceModelId.nanoS,
453
+ appName: "Polygon",
454
+ },
455
+ testTimeout: 2 * 60 * 1000,
456
+ transactionCheck: ({ maxSpendable }) => {
457
+ invariant(
458
+ maxSpendable.gt(
459
+ parseCurrencyUnit(getCryptoCurrencyById("polygon").units[0], "0.005")
460
+ ),
461
+ "balance is too low"
462
+ );
463
+ },
464
+ mutations: ethereumBasicMutations({ maxAccount: 8 }).concat([
465
+ {
466
+ name: "move some ERC20",
467
+ maxRun: 1,
468
+ // @ts-expect-error rxjs stuff
469
+ transaction: ({ account, siblings, bridge }) => {
470
+ const erc20Account = sample(
471
+ (account.subAccounts || []).filter((a) => a.balance.gt(0))
472
+ );
473
+ invariant(erc20Account, "no erc20 account");
474
+ const sibling = pickSiblings(siblings, 3);
475
+ const recipient = sibling.freshAddress;
476
+ return {
477
+ transaction: bridge.createTransaction(account),
478
+ updates: [
479
+ { recipient, subAccountId: erc20Account.id },
480
+ Math.random() < 0.5
481
+ ? { useAllAmount: true }
482
+ : {
483
+ amount: erc20Account.balance
484
+ .times(Math.random())
485
+ .integerValue(),
486
+ },
487
+ ],
488
+ };
489
+ },
490
+ },
491
+ ]),
492
+ };
493
+
448
494
  export default {
449
495
  bsc,
496
+ polygon,
450
497
  ethereum,
451
498
  ethereumClassic,
452
499
  ethereumRopsten,