@ledgerhq/live-common 21.16.1 → 21.16.2

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 (80) hide show
  1. package/lib/__tests__/families/bitcoin/wallet-btc/utils.test.js +85 -0
  2. package/lib/__tests__/families/bitcoin/wallet-btc/utils.test.js.map +1 -1
  3. package/lib/__tests__/families/bitcoin/wallet-btc/wallet.estimateMaxSpendable.test.js +1 -1
  4. package/lib/__tests__/families/bitcoin/wallet-btc/wallet.estimateMaxSpendable.test.js.map +1 -1
  5. package/lib/__tests__/families/bitcoin/wallet-btc/wallet.integration.test.js +2 -2
  6. package/lib/__tests__/families/bitcoin/wallet-btc/wallet.integration.test.js.map +1 -1
  7. package/lib/__tests__/families/bitcoin/wallet-btc/xpub.pickingStrategies.integration.test.js +20 -10
  8. package/lib/__tests__/families/bitcoin/wallet-btc/xpub.pickingStrategies.integration.test.js.map +1 -1
  9. package/lib/__tests__/families/bitcoin/wallet-btc/xpub.txs.NP2WPKH.integration.test.js +1 -1
  10. package/lib/__tests__/families/bitcoin/wallet-btc/xpub.txs.NP2WPKH.integration.test.js.map +1 -1
  11. package/lib/__tests__/families/bitcoin/wallet-btc/xpub.txs.P2WPKH.integration.test.js +1 -1
  12. package/lib/__tests__/families/bitcoin/wallet-btc/xpub.txs.P2WPKH.integration.test.js.map +1 -1
  13. package/lib/__tests__/families/bitcoin/wallet-btc/xpub.txs.integration.test.js +2 -2
  14. package/lib/__tests__/families/bitcoin/wallet-btc/xpub.txs.integration.test.js.map +1 -1
  15. package/lib/apps/polyfill.d.ts.map +1 -1
  16. package/lib/apps/polyfill.js +3 -0
  17. package/lib/apps/polyfill.js.map +1 -1
  18. package/lib/currencies/support.d.ts.map +1 -1
  19. package/lib/currencies/support.js.map +1 -1
  20. package/lib/families/bitcoin/js-buildTransaction.d.ts.map +1 -1
  21. package/lib/families/bitcoin/js-buildTransaction.js +1 -1
  22. package/lib/families/bitcoin/js-buildTransaction.js.map +1 -1
  23. package/lib/families/bitcoin/js-estimateMaxSpendable.d.ts.map +1 -1
  24. package/lib/families/bitcoin/js-estimateMaxSpendable.js +1 -1
  25. package/lib/families/bitcoin/js-estimateMaxSpendable.js.map +1 -1
  26. package/lib/families/bitcoin/js-synchronisation.d.ts.map +1 -1
  27. package/lib/families/bitcoin/js-synchronisation.js +3 -2
  28. package/lib/families/bitcoin/js-synchronisation.js.map +1 -1
  29. package/lib/families/bitcoin/wallet-btc/pickingstrategies/CoinSelect.d.ts +2 -1
  30. package/lib/families/bitcoin/wallet-btc/pickingstrategies/CoinSelect.d.ts.map +1 -1
  31. package/lib/families/bitcoin/wallet-btc/pickingstrategies/CoinSelect.js +16 -12
  32. package/lib/families/bitcoin/wallet-btc/pickingstrategies/CoinSelect.js.map +1 -1
  33. package/lib/families/bitcoin/wallet-btc/pickingstrategies/DeepFirst.d.ts +2 -1
  34. package/lib/families/bitcoin/wallet-btc/pickingstrategies/DeepFirst.d.ts.map +1 -1
  35. package/lib/families/bitcoin/wallet-btc/pickingstrategies/DeepFirst.js +12 -7
  36. package/lib/families/bitcoin/wallet-btc/pickingstrategies/DeepFirst.js.map +1 -1
  37. package/lib/families/bitcoin/wallet-btc/pickingstrategies/Merge.d.ts +2 -1
  38. package/lib/families/bitcoin/wallet-btc/pickingstrategies/Merge.d.ts.map +1 -1
  39. package/lib/families/bitcoin/wallet-btc/pickingstrategies/Merge.js +12 -7
  40. package/lib/families/bitcoin/wallet-btc/pickingstrategies/Merge.js.map +1 -1
  41. package/lib/families/bitcoin/wallet-btc/pickingstrategies/types.d.ts +2 -1
  42. package/lib/families/bitcoin/wallet-btc/pickingstrategies/types.d.ts.map +1 -1
  43. package/lib/families/bitcoin/wallet-btc/pickingstrategies/types.js.map +1 -1
  44. package/lib/families/bitcoin/wallet-btc/utils.d.ts +38 -2
  45. package/lib/families/bitcoin/wallet-btc/utils.d.ts.map +1 -1
  46. package/lib/families/bitcoin/wallet-btc/utils.js +103 -35
  47. package/lib/families/bitcoin/wallet-btc/utils.js.map +1 -1
  48. package/lib/families/bitcoin/wallet-btc/wallet.d.ts +1 -1
  49. package/lib/families/bitcoin/wallet-btc/wallet.d.ts.map +1 -1
  50. package/lib/families/bitcoin/wallet-btc/wallet.js +6 -5
  51. package/lib/families/bitcoin/wallet-btc/wallet.js.map +1 -1
  52. package/lib/families/bitcoin/wallet-btc/xpub.js +2 -2
  53. package/lib/families/bitcoin/wallet-btc/xpub.js.map +1 -1
  54. package/lib/operation.js +1 -1
  55. package/lib/operation.js.map +1 -1
  56. package/package.json +5 -5
  57. package/src/.DS_Store +0 -0
  58. package/src/__tests__/__snapshots__/all.libcore.ts.snap +1188 -630
  59. package/src/__tests__/families/bitcoin/wallet-btc/utils.test.ts +105 -0
  60. package/src/__tests__/families/bitcoin/wallet-btc/wallet.estimateMaxSpendable.test.ts +3 -2
  61. package/src/__tests__/families/bitcoin/wallet-btc/wallet.integration.test.ts +2 -2
  62. package/src/__tests__/families/bitcoin/wallet-btc/xpub.pickingStrategies.integration.test.ts +35 -31
  63. package/src/__tests__/families/bitcoin/wallet-btc/xpub.txs.NP2WPKH.integration.test.ts +3 -2
  64. package/src/__tests__/families/bitcoin/wallet-btc/xpub.txs.P2WPKH.integration.test.ts +3 -2
  65. package/src/__tests__/families/bitcoin/wallet-btc/xpub.txs.integration.test.ts +6 -4
  66. package/src/apps/polyfill.ts +3 -0
  67. package/src/currencies/.DS_Store +0 -0
  68. package/src/currencies/__snapshots__/sortByMarketcap.test.ts.snap +3 -1
  69. package/src/currencies/support.ts +1 -0
  70. package/src/families/bitcoin/js-buildTransaction.ts +2 -1
  71. package/src/families/bitcoin/js-estimateMaxSpendable.ts +2 -1
  72. package/src/families/bitcoin/js-synchronisation.ts +4 -2
  73. package/src/families/bitcoin/wallet-btc/pickingstrategies/CoinSelect.ts +34 -22
  74. package/src/families/bitcoin/wallet-btc/pickingstrategies/DeepFirst.ts +30 -9
  75. package/src/families/bitcoin/wallet-btc/pickingstrategies/Merge.ts +30 -9
  76. package/src/families/bitcoin/wallet-btc/pickingstrategies/types.ts +3 -3
  77. package/src/families/bitcoin/wallet-btc/utils.ts +113 -41
  78. package/src/families/bitcoin/wallet-btc/wallet.ts +9 -6
  79. package/src/families/bitcoin/wallet-btc/xpub.ts +5 -5
  80. package/src/operation.ts +1 -1
@@ -1,6 +1,8 @@
1
1
  import { bech32m, bech32, BechLib } from "bech32";
2
2
  import * as utils from "../../../../families/bitcoin/wallet-btc/utils";
3
3
  import { Currency } from "../../../../families/bitcoin/wallet-btc/crypto/types";
4
+ import cryptoFactory from "../../../../families/bitcoin/wallet-btc/crypto/factory";
5
+ import { DerivationModes } from "../../../../families/bitcoin/wallet-btc";
4
6
 
5
7
  function validateAddrs(
6
8
  addresses: string[],
@@ -208,3 +210,106 @@ describe("Unit tests for various utils functions", () => {
208
210
  validateAddrs(["S6NMcEfYbavHrP3Uo1wbEUvKhAbKeMugaa"], "stealthcoin", false);
209
211
  });
210
212
  });
213
+
214
+ describe("Unit tests for maxTxSize", () => {
215
+ const btc = cryptoFactory("bitcoin_testnet");
216
+ it("Empty tx non-segwit", () => {
217
+ const s = utils.maxTxSizeCeil(0, [], false, btc, DerivationModes.LEGACY);
218
+ expect(s).toEqual(10);
219
+ });
220
+ it("Empty tx segwit", () => {
221
+ const s = utils.maxTxSizeCeil(
222
+ 0,
223
+ [],
224
+ false,
225
+ btc,
226
+ DerivationModes.NATIVE_SEGWIT
227
+ );
228
+ expect(s).toEqual(11);
229
+ });
230
+ it("1 p2wpkh input 1 p2wpkh output", () => {});
231
+
232
+ const tr = "tb1pdedptfps5k6hmzars9ks93ejsujh28kw5dhe06gutt9svap40j8qql2dw2";
233
+ const sh = "2Mv9bnjkBUr1GfCybJc7XmnJ5VG4SAT3shT";
234
+ const pkh = "mkQiYQGCkCC7Wus3vfhfTDjgJzQK554evn";
235
+ const wpkh = "tb1qhff3j7euu6t3lv8s5gsy9t5x82wuhfw5z863gj";
236
+ const p2tr = DerivationModes.TAPROOT;
237
+ const p2sh = DerivationModes.SEGWIT;
238
+ const p2pkh = DerivationModes.LEGACY;
239
+ const p2wpkh = DerivationModes.NATIVE_SEGWIT;
240
+
241
+ test.each([
242
+ // In 148 out 34
243
+ [0, [], false, p2pkh, 10],
244
+ [0, [], true, p2pkh, 44],
245
+ [0, [pkh], false, p2pkh, 44],
246
+ [0, [pkh], true, p2pkh, 78],
247
+ [1, [pkh], true, p2pkh, 226],
248
+ [2, [pkh], true, p2pkh, 374],
249
+ [1, [wpkh], true, p2pkh, 223],
250
+ [1, [sh], true, p2pkh, 224],
251
+ [1, [tr], true, p2pkh, 235],
252
+
253
+ // In 68 out 31
254
+ [0, [], false, p2wpkh, 11],
255
+ [0, [], true, p2wpkh, 42],
256
+ [1, [], false, p2wpkh, 79],
257
+ [1, [], true, p2wpkh, 110],
258
+ [2, [], true, p2wpkh, 178],
259
+
260
+ // In 90 out 32, scriptSig 22
261
+ [0, [], false, p2sh, 11],
262
+ [0, [], true, p2sh, 43],
263
+ [1, [], false, p2sh, 101],
264
+ [1, [sh], false, p2sh, 133],
265
+ [2, [sh], false, p2sh, 223],
266
+
267
+ // Fixed 10.5 In 57.75 out 43
268
+ [0, [], false, p2tr, 11],
269
+ [0, [], true, p2tr, 54],
270
+ [1, [], true, p2tr, Math.ceil(53.5 + 57.75 * 1)],
271
+ [2, [], true, p2tr, Math.ceil(53.5 + 57.75 * 2)],
272
+ [3, [], true, p2tr, Math.ceil(53.5 + 57.75 * 3)],
273
+
274
+ // 0xfc=252 inputs
275
+ [247, [], true, p2tr, Math.ceil(53.5 + 57.75 * 247)],
276
+ [248, [], true, p2tr, Math.ceil(53.5 + 57.75 * 248)],
277
+ [249, [], true, p2tr, Math.ceil(53.5 + 57.75 * 249)],
278
+ [250, [], true, p2tr, Math.ceil(53.5 + 57.75 * 250)],
279
+ [251, [], true, p2tr, Math.ceil(53.5 + 57.75 * 251)],
280
+ [252, [], true, p2tr, Math.ceil(53.5 + 57.75 * 252)],
281
+ // 0xfd=253 inputs will add 2 bytes for >= 0xfd
282
+ [253, [], true, p2tr, Math.ceil(53.5 + 57.75 * 253 + 2)],
283
+ [
284
+ 256 * 256 - 1,
285
+ [],
286
+ true,
287
+ p2tr,
288
+ Math.ceil(53.5 + 57.75 * (256 * 256 - 1) + 2),
289
+ ],
290
+ // 0xffff inputs will add 4 bytes
291
+ [256 * 256, [], true, p2tr, Math.ceil(53.5 + 57.75 * (256 * 256) + 4)],
292
+
293
+ // test address with witness version 16 and witness program [0x01, 0x02] => tb1sqypqyuzpgh
294
+ [
295
+ 2,
296
+ [tr, sh, pkh, wpkh, "tb1sqypqyuzpgh"],
297
+ false,
298
+ p2wpkh,
299
+ Math.ceil(10.5 + 68 * 2 + 43 + 32 + 34 + 31 + 13),
300
+ ],
301
+ ])(
302
+ "%i, %s, %s, %s => %i",
303
+ (inputCount, outputAddrs, useChange, derivationMode, exp) => {
304
+ const s = utils.maxTxSizeCeil(
305
+ inputCount,
306
+ outputAddrs,
307
+ useChange,
308
+ btc,
309
+ derivationMode
310
+ );
311
+ //const s = utils.estimateTxSize(inputCount, outputAddrs.length + (useChange ? 1 : 0), btc, derivationMode);
312
+ expect(s).toEqual(exp);
313
+ }
314
+ );
315
+ });
@@ -57,9 +57,10 @@ describe("testing estimateMaxSpendable", () => {
57
57
  expect(maxSpendable.toNumber()).toEqual(
58
58
  balance -
59
59
  feesPerByte *
60
- utils.estimateTxSize(
60
+ utils.maxTxSizeCeil(
61
61
  2,
62
- 1,
62
+ [],
63
+ true,
63
64
  account.xpub.crypto,
64
65
  account.xpub.derivationMode
65
66
  )
@@ -63,7 +63,7 @@ describe("testing wallet", () => {
63
63
  fromAccount: account,
64
64
  txInfo,
65
65
  });
66
- expect(tx).toEqual("d6154bba4915d07453bb09d4fa02d62e975b4475");
66
+ expect(Buffer.from(tx, "hex")).toHaveLength(20);
67
67
  });
68
68
 
69
69
  it("should allow to build a transaction splitting outputs", async () => {
@@ -87,7 +87,7 @@ describe("testing wallet", () => {
87
87
  fromAccount: account,
88
88
  txInfo,
89
89
  });
90
- expect(tx).toEqual("d922a70d6a66b96cdaba4565270a21f97eb23a6d");
90
+ expect(Buffer.from(tx, "hex")).toHaveLength(20);
91
91
  });
92
92
 
93
93
  it("should throw during sync if there is an error in explorer", async () => {
@@ -3,7 +3,10 @@ import * as bip39 from "bip39";
3
3
  import * as bitcoin from "bitcoinjs-lib";
4
4
  import coininfo from "coininfo";
5
5
  import BigNumber from "bignumber.js";
6
- import { DerivationModes } from "../../../../families/bitcoin/wallet-btc/types";
6
+ import {
7
+ DerivationModes,
8
+ OutputInfo,
9
+ } from "../../../../families/bitcoin/wallet-btc/types";
7
10
  import Xpub from "../../../../families/bitcoin/wallet-btc/xpub";
8
11
  import BitcoinLikeExplorer from "../../../../families/bitcoin/wallet-btc/explorer";
9
12
  import Crypto from "../../../../families/bitcoin/wallet-btc/crypto/bitcoin";
@@ -42,6 +45,17 @@ describe("testing xpub legacy transactions", () => {
42
45
  xpub,
43
46
  };
44
47
 
48
+ function outputs(amount: number): OutputInfo[] {
49
+ return [
50
+ {
51
+ address: "mwXTtHo8Yy3aNKUUZLkBDrTcKT9qG9TqLb",
52
+ isChange: false,
53
+ script: Buffer.from([]),
54
+ value: new BigNumber(amount),
55
+ },
56
+ ];
57
+ }
58
+
45
59
  it("merge output strategy should be correct", async () => {
46
60
  // Initialize the xpub with 2 txs. So that it has 2 utxo
47
61
  dataset.xpub.storage.appendTxs([
@@ -134,17 +148,15 @@ describe("testing xpub legacy transactions", () => {
134
148
  );
135
149
  let res = await utxoPickingStrategy.selectUnspentUtxosToUse(
136
150
  dataset.xpub,
137
- new BigNumber(10000),
138
- 0,
139
- 1
151
+ outputs(10000),
152
+ 0
140
153
  );
141
154
  expect(res.unspentUtxos.length).toEqual(1); // only 1 utxo is enough
142
155
  expect(Number(res.unspentUtxos[0].value)).toEqual(300000000); // use cheaper utxo first
143
156
  res = await utxoPickingStrategy.selectUnspentUtxosToUse(
144
157
  dataset.xpub,
145
- new BigNumber(500000000),
146
- 0,
147
- 1
158
+ outputs(500000000),
159
+ 0
148
160
  );
149
161
  expect(res.unspentUtxos.length).toEqual(2); // need 2 utxo
150
162
  expect(
@@ -161,17 +173,15 @@ describe("testing xpub legacy transactions", () => {
161
173
  );
162
174
  let res = await utxoPickingStrategy.selectUnspentUtxosToUse(
163
175
  dataset.xpub,
164
- new BigNumber(10000),
165
- 0,
166
- 1
176
+ outputs(10000),
177
+ 0
167
178
  );
168
179
  expect(res.unspentUtxos.length).toEqual(1); // only 1 utxo is enough
169
180
  expect(Number(res.unspentUtxos[0].value)).toEqual(5000000000); // use old utxo first
170
181
  res = await utxoPickingStrategy.selectUnspentUtxosToUse(
171
182
  dataset.xpub,
172
- new BigNumber(5200000000),
173
- 0,
174
- 1
183
+ outputs(5200000000),
184
+ 0
175
185
  );
176
186
  expect(res.unspentUtxos.length).toEqual(2); // need 2 utxo
177
187
  expect(
@@ -323,45 +333,40 @@ describe("testing xpub legacy transactions", () => {
323
333
  );
324
334
  let res = await utxoPickingStrategy.selectUnspentUtxosToUse(
325
335
  dataset.xpub,
326
- new BigNumber(10000),
327
- 10,
328
- 1
336
+ outputs(10000),
337
+ 10
329
338
  );
330
339
  expect(res.unspentUtxos.length).toEqual(1);
331
340
  expect(Number(res.unspentUtxos[0].value)).toEqual(100000000);
332
341
 
333
342
  res = await utxoPickingStrategy.selectUnspentUtxosToUse(
334
343
  dataset.xpub,
335
- new BigNumber(290000000),
336
- 10,
337
- 1
344
+ outputs(290000000),
345
+ 10
338
346
  );
339
347
  expect(res.unspentUtxos.length).toEqual(1);
340
348
  expect(Number(res.unspentUtxos[0].value)).toEqual(300000000);
341
349
 
342
350
  res = await utxoPickingStrategy.selectUnspentUtxosToUse(
343
351
  dataset.xpub,
344
- new BigNumber(500000000),
345
- 10,
346
- 1
352
+ outputs(500000000),
353
+ 10
347
354
  );
348
355
  expect(res.unspentUtxos.length).toEqual(1);
349
356
  expect(Number(res.unspentUtxos[0].value)).toEqual(600000000);
350
357
 
351
358
  res = await utxoPickingStrategy.selectUnspentUtxosToUse(
352
359
  dataset.xpub,
353
- new BigNumber(800000000),
354
- 10,
355
- 1
360
+ outputs(800000000),
361
+ 10
356
362
  );
357
363
  expect(res.unspentUtxos.length).toEqual(1);
358
364
  expect(Number(res.unspentUtxos[0].value)).toEqual(5000000000);
359
365
 
360
366
  res = await utxoPickingStrategy.selectUnspentUtxosToUse(
361
367
  dataset.xpub,
362
- new BigNumber(5000000000),
363
- 10,
364
- 1
368
+ outputs(5000000000),
369
+ 10
365
370
  );
366
371
  expect(res.unspentUtxos.length).toEqual(2);
367
372
  expect(
@@ -370,9 +375,8 @@ describe("testing xpub legacy transactions", () => {
370
375
 
371
376
  res = await utxoPickingStrategy.selectUnspentUtxosToUse(
372
377
  dataset.xpub,
373
- new BigNumber(5600000000),
374
- 10,
375
- 1
378
+ outputs(5600000000),
379
+ 10
376
380
  );
377
381
  expect(res.unspentUtxos.length).toEqual(3);
378
382
  expect(
@@ -178,9 +178,10 @@ describe.skip("testing xpub segwit transactions", () => {
178
178
  await xpubs[1].xpub.sync();
179
179
 
180
180
  expectedFee1 =
181
- utils.estimateTxSize(
181
+ utils.maxTxSizeCeil(
182
182
  inputs.length,
183
- outputs.length,
183
+ outputs.map((o) => o.address),
184
+ false,
184
185
  crypto,
185
186
  DerivationModes.SEGWIT
186
187
  ) * 100;
@@ -167,9 +167,10 @@ describe.skip("testing xpub native segwit transactions", () => {
167
167
  await xpubs[1].xpub.sync();
168
168
 
169
169
  expectedFee1 =
170
- utils.estimateTxSize(
170
+ utils.maxTxSizeCeil(
171
171
  inputs.length,
172
- outputs.length,
172
+ outputs.map((o) => o.address),
173
+ false,
173
174
  crypto,
174
175
  DerivationModes.NATIVE_SEGWIT
175
176
  ) * 100;
@@ -148,9 +148,10 @@ describe.skip("testing xpub legacy transactions", () => {
148
148
  }
149
149
 
150
150
  expectedFee1 =
151
- utils.estimateTxSize(
151
+ utils.maxTxSizeCeil(
152
152
  inputs.length,
153
- outputs.length,
153
+ outputs.map((o) => o.address),
154
+ false,
154
155
  crypto,
155
156
  DerivationModes.LEGACY
156
157
  ) * 100;
@@ -280,9 +281,10 @@ describe.skip("testing xpub legacy transactions", () => {
280
281
  await xpubs[1].xpub.sync();
281
282
 
282
283
  expectedFee2 =
283
- utils.estimateTxSize(
284
+ utils.maxTxSizeCeil(
284
285
  inputs.length,
285
- outputs.length,
286
+ outputs.map((o) => o.address),
287
+ false,
286
288
  crypto,
287
289
  DerivationModes.LEGACY
288
290
  ) * 100;
@@ -49,6 +49,9 @@ export const whitelistDependencies = ["Decred", "Decred Testnet"];
49
49
  ["Opensea", "Ethereum"],
50
50
  ["StakeDAO", "Ethereum"],
51
51
  ["Yearn", "Ethereum"],
52
+ ["RocketPool", "Ethereum"],
53
+ ["POAP", "Ethereum"],
54
+ ["OlympusDAO", "Ethereum"],
52
55
  ].forEach(([name, dep]) => declareDep(name, dep));
53
56
  export const getDependencies = (appName: string): string[] =>
54
57
  directDep[appName] || [];
Binary file
@@ -2671,6 +2671,7 @@ Array [
2671
2671
  "ethereum/erc20/ethereum_cell_network",
2672
2672
  "ethereum/erc20/ethereum_dark",
2673
2673
  "ethereum/erc20/ethereum_money",
2674
+ "ethereum/erc20/ethereum_name_service",
2674
2675
  "ethereum/erc20/ethereum_pro",
2675
2676
  "ethereum/erc20/ethereum_push_notification_service",
2676
2677
  "ethereum/erc20/ethereum_stake",
@@ -2994,7 +2995,6 @@ Array [
2994
2995
  "ethereum/erc20/golden_goose",
2995
2996
  "ethereum/erc20/golden_ratio_coin",
2996
2997
  "ethereum/erc20/golden_token",
2997
- "ethereum/erc20/goldenratio",
2998
2998
  "ethereum/erc20/goldenugget_token",
2999
2999
  "ethereum/erc20/golder_coin",
3000
3000
  "ethereum/erc20/goldextoken",
@@ -3018,6 +3018,7 @@ Array [
3018
3018
  "ethereum/erc20/grandpa_fan",
3019
3019
  "ethereum/erc20/grap",
3020
3020
  "ethereum/erc20/grapefruit",
3021
+ "ethereum/erc20/graph_token",
3021
3022
  "ethereum/erc20/graphlinq",
3022
3023
  "ethereum/erc20/graviton",
3023
3024
  "ethereum/erc20/grearn's_token",
@@ -3889,6 +3890,7 @@ Array [
3889
3890
  "ethereum/erc20/par_stablecoin",
3890
3891
  "ethereum/erc20/paralink_network",
3891
3892
  "ethereum/erc20/parallelchain_token",
3893
+ "ethereum/erc20/paraswap",
3892
3894
  "ethereum/erc20/pareto",
3893
3895
  "ethereum/erc20/paribus",
3894
3896
  "ethereum/erc20/parsec_finance",
@@ -9,6 +9,7 @@ import {
9
9
  hasCryptoCurrencyId,
10
10
  } from "@ledgerhq/cryptoassets";
11
11
  import { getEnv } from "../env";
12
+
12
13
  // set by user side effect to precise which currencies are considered supported (typically by live)
13
14
  let userSupportedCurrencies: CryptoCurrency[] = [];
14
15
  let userSupportedFiats: FiatCurrency[] = [];
@@ -44,7 +44,8 @@ export const buildTransaction = async (
44
44
  walletAccount,
45
45
  transaction.feePerByte.toNumber(), //!\ wallet-btc handles fees as JS number
46
46
  transaction.utxoStrategy.excludeUTXOs,
47
- transaction.utxoStrategy.pickUnconfirmedRBF
47
+ transaction.utxoStrategy.pickUnconfirmedRBF,
48
+ [transaction.recipient]
48
49
  );
49
50
  log("btcwallet", "building transaction", transaction);
50
51
  const txInfo = await wallet.buildAccountTx({
@@ -30,7 +30,8 @@ const estimateMaxSpendable = async ({
30
30
  walletAccount,
31
31
  feePerByte.toNumber(), //!\ wallet-btc handles fees as JS number
32
32
  transaction?.utxoStrategy?.excludeUTXOs || [],
33
- transaction?.utxoStrategy?.pickUnconfirmedRBF || false
33
+ transaction?.utxoStrategy?.pickUnconfirmedRBF || false,
34
+ transaction ? [transaction.recipient] : []
34
35
  );
35
36
  return maxSpendable.lt(0) ? new BigNumber(0) : maxSpendable;
36
37
  };
@@ -139,8 +139,10 @@ const mapTxToOperations = (
139
139
  if (output.address) {
140
140
  if (!accountAddresses.includes(output.address)) {
141
141
  // The output doesn't belong to this account
142
- if (output.output_index < changeOutputIndex) {
143
- // The output isn't the change output
142
+ if (
143
+ tx.outputs.length === 1 || // The transaction has only 1 output
144
+ output.output_index < changeOutputIndex // The output isn't the change output
145
+ ) {
144
146
  recipients.push(
145
147
  syncReplaceAddress
146
148
  ? syncReplaceAddress(output.address)
@@ -7,14 +7,14 @@ import { PickingStrategy } from "./types";
7
7
  import * as utils from "../utils";
8
8
  import { DeepFirst } from "./DeepFirst";
9
9
  import { log } from "@ledgerhq/logs";
10
+ import { OutputInfo } from "..";
10
11
 
11
12
  export class CoinSelect extends PickingStrategy {
12
13
  // eslint-disable-next-line class-methods-use-this
13
14
  async selectUnspentUtxosToUse(
14
15
  xpub: Xpub,
15
- amount: BigNumber,
16
- feePerByte: number,
17
- nbOutputsWithoutChange: number
16
+ outputs: OutputInfo[],
17
+ feePerByte: number
18
18
  ) {
19
19
  // get the utxos to use as input
20
20
  // from all addresses of the account
@@ -34,18 +34,30 @@ export class CoinSelect extends PickingStrategy {
34
34
  const TOTAL_TRIES = 100000;
35
35
  log("picking strategy", "utxos", unspentUtxos);
36
36
  // Compute cost of change
37
- const fixedSize = utils.accurateTxSize(
38
- 0,
37
+ const fixedSize = utils.maxTxSize(
39
38
  0,
39
+ [],
40
+ false,
40
41
  this.crypto,
41
42
  this.derivationMode
42
43
  );
44
+ const outputAddresses = outputs.map((o) => o.address);
43
45
  // Size of only 1 output (without fixed size)
44
46
  const oneOutputSize =
45
- utils.accurateTxSize(0, 1, this.crypto, this.derivationMode) - fixedSize;
47
+ outputAddresses.length > 0
48
+ ? utils.maxTxSize(
49
+ 0,
50
+ [outputAddresses[0]],
51
+ false,
52
+ this.crypto,
53
+ this.derivationMode
54
+ ) - fixedSize
55
+ : utils.maxTxSize(0, [], true, this.crypto, this.derivationMode) -
56
+ fixedSize;
46
57
  // Size 1 signed UTXO (signed input)
47
58
  const oneInputSize =
48
- utils.accurateTxSize(1, 0, this.crypto, this.derivationMode) - fixedSize;
59
+ utils.maxTxSize(1, [], false, this.crypto, this.derivationMode) -
60
+ fixedSize;
49
61
 
50
62
  // Calculate effective value of outputs
51
63
  let currentAvailableValue = 0;
@@ -70,12 +82,16 @@ export class CoinSelect extends PickingStrategy {
70
82
  // Get no inputs fees
71
83
  // At beginning, there are no outputs in tx, so noInputFees are fixed fees
72
84
  const notInputFees =
73
- feePerByte * (fixedSize + oneOutputSize * nbOutputsWithoutChange);
85
+ feePerByte * (fixedSize + oneOutputSize * outputs.length);
74
86
 
75
87
  // Start coin selection algorithm (according to SelectCoinBnb from Bitcoin Core)
76
88
  let currentValue = 0;
77
89
  const currentSelection: boolean[] = [];
78
90
 
91
+ const amount = outputs.reduce(
92
+ (sum, output) => sum.plus(output.value),
93
+ new BigNumber(0)
94
+ );
79
95
  // Actual amount we are targetting
80
96
  const actualTarget = notInputFees + amount.toNumber();
81
97
 
@@ -102,9 +118,10 @@ export class CoinSelect extends PickingStrategy {
102
118
  currentSelectionNeedChangeoutput = true;
103
119
  currentWaste =
104
120
  feePerByte *
105
- utils.estimateTxSize(
121
+ utils.maxTxSizeCeil(
106
122
  nbInput,
107
- nbOutputsWithoutChange + 1,
123
+ outputAddresses,
124
+ true,
108
125
  this.crypto,
109
126
  this.derivationMode
110
127
  );
@@ -113,9 +130,10 @@ export class CoinSelect extends PickingStrategy {
113
130
  currentSelectionNeedChangeoutput = false;
114
131
  currentWaste =
115
132
  feePerByte *
116
- utils.estimateTxSize(
133
+ utils.maxTxSizeCeil(
117
134
  nbInput,
118
- nbOutputsWithoutChange,
135
+ outputAddresses,
136
+ false,
119
137
  this.crypto,
120
138
  this.derivationMode
121
139
  ) +
@@ -170,11 +188,10 @@ export class CoinSelect extends PickingStrategy {
170
188
  }
171
189
  const fee =
172
190
  feePerByte *
173
- utils.estimateTxSize(
191
+ utils.maxTxSizeCeil(
174
192
  unspentUtxoSelected.length,
175
- bestSelectionNeedChangeoutput
176
- ? nbOutputsWithoutChange + 1
177
- : nbOutputsWithoutChange,
193
+ outputAddresses,
194
+ bestSelectionNeedChangeoutput,
178
195
  this.crypto,
179
196
  this.derivationMode
180
197
  );
@@ -191,11 +208,6 @@ export class CoinSelect extends PickingStrategy {
191
208
  this.derivationMode,
192
209
  this.excludedUTXOs
193
210
  );
194
- return pickingStrategy.selectUnspentUtxosToUse(
195
- xpub,
196
- amount,
197
- feePerByte,
198
- nbOutputsWithoutChange
199
- );
211
+ return pickingStrategy.selectUnspentUtxosToUse(xpub, outputs, feePerByte);
200
212
  }
201
213
  }
@@ -6,14 +6,14 @@ import Xpub from "../xpub";
6
6
  import { PickingStrategy } from "./types";
7
7
  import * as utils from "../utils";
8
8
  import { log } from "@ledgerhq/logs";
9
+ import { OutputInfo } from "..";
9
10
 
10
11
  export class DeepFirst extends PickingStrategy {
11
12
  // eslint-disable-next-line class-methods-use-this
12
13
  async selectUnspentUtxosToUse(
13
14
  xpub: Xpub,
14
- amount: BigNumber,
15
- feePerByte: number,
16
- nbOutputsWithoutChange: number
15
+ outputs: OutputInfo[],
16
+ feePerByte: number
17
17
  ) {
18
18
  // get the utxos to use as input
19
19
  // from all addresses of the account
@@ -31,26 +31,47 @@ export class DeepFirst extends PickingStrategy {
31
31
  ).length
32
32
  );
33
33
 
34
+ const outputAddresses = outputs.map((o) => o.address);
34
35
  unspentUtxos = sortBy(unspentUtxos, "block_height");
35
36
  // https://metamug.com/article/security/bitcoin-transaction-fee-satoshi-per-byte.html
36
- const txSizeNoInput = utils.accurateTxSize(
37
+ const txSizeNoInput = utils.maxTxSize(
37
38
  0,
38
- nbOutputsWithoutChange,
39
+ outputAddresses,
40
+ false,
39
41
  this.crypto,
40
42
  this.derivationMode
41
43
  );
42
44
  let fee = txSizeNoInput * feePerByte;
45
+ const emptyTxSize = utils.maxTxSizeCeil(
46
+ 0,
47
+ [],
48
+ false,
49
+ this.crypto,
50
+ this.derivationMode
51
+ );
43
52
  const sizePerInput =
44
- utils.accurateTxSize(1, 0, this.crypto, this.derivationMode) -
45
- utils.accurateTxSize(0, 0, this.crypto, this.derivationMode);
53
+ utils.maxTxSize(1, [], false, this.crypto, this.derivationMode) -
54
+ emptyTxSize;
46
55
 
47
56
  const sizePerOutput =
48
- utils.accurateTxSize(0, 1, this.crypto, this.derivationMode) -
49
- utils.accurateTxSize(0, 0, this.crypto, this.derivationMode);
57
+ (outputAddresses[0]
58
+ ? utils.maxTxSize(
59
+ 0,
60
+ [outputAddresses[0]],
61
+ false,
62
+ this.crypto,
63
+ this.derivationMode
64
+ )
65
+ : utils.maxTxSize(0, [], true, this.crypto, this.derivationMode)) -
66
+ emptyTxSize;
50
67
 
51
68
  let total = new BigNumber(0);
52
69
  const unspentUtxoSelected: Output[] = [];
53
70
 
71
+ const amount = outputs.reduce(
72
+ (sum, output) => sum.plus(output.value),
73
+ new BigNumber(0)
74
+ );
54
75
  let i = 0;
55
76
  while (total.lt(amount.plus(fee))) {
56
77
  if (!unspentUtxos[i]) {