@ledgerhq/live-common 21.15.0 → 21.16.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 (34) hide show
  1. package/lib/currencies/sortByMarketcap.d.ts.map +1 -1
  2. package/lib/currencies/sortByMarketcap.js +8 -1
  3. package/lib/currencies/sortByMarketcap.js.map +1 -1
  4. package/lib/families/bitcoin/js-synchronisation.d.ts.map +1 -1
  5. package/lib/families/bitcoin/js-synchronisation.js +6 -17
  6. package/lib/families/bitcoin/js-synchronisation.js.map +1 -1
  7. package/lib/families/bitcoin/logic.d.ts +1 -1
  8. package/lib/families/bitcoin/logic.d.ts.map +1 -1
  9. package/lib/families/bitcoin/logic.js +6 -0
  10. package/lib/families/bitcoin/logic.js.map +1 -1
  11. package/lib/families/bitcoin/specs.d.ts.map +1 -1
  12. package/lib/families/bitcoin/specs.js +2 -1
  13. package/lib/families/bitcoin/specs.js.map +1 -1
  14. package/lib/families/bitcoin/wallet-btc/pickingstrategies/CoinSelect.js +3 -3
  15. package/lib/families/bitcoin/wallet-btc/pickingstrategies/DeepFirst.js +5 -5
  16. package/lib/families/bitcoin/wallet-btc/pickingstrategies/Merge.js +5 -5
  17. package/lib/families/bitcoin/wallet-btc/utils.d.ts +1 -0
  18. package/lib/families/bitcoin/wallet-btc/utils.d.ts.map +1 -1
  19. package/lib/families/bitcoin/wallet-btc/utils.js +8 -4
  20. package/lib/families/bitcoin/wallet-btc/utils.js.map +1 -1
  21. package/lib/families/bitcoin/wallet-btc/wallet.d.ts.map +1 -1
  22. package/lib/families/bitcoin/wallet-btc/wallet.js +4 -2
  23. package/lib/families/bitcoin/wallet-btc/wallet.js.map +1 -1
  24. package/package.json +11 -11
  25. package/src/__tests__/__snapshots__/all.libcore.ts.snap +50567 -51469
  26. package/src/currencies/sortByMarketcap.ts +9 -1
  27. package/src/families/bitcoin/js-synchronisation.ts +9 -23
  28. package/src/families/bitcoin/logic.ts +7 -2
  29. package/src/families/bitcoin/specs.ts +6 -1
  30. package/src/families/bitcoin/wallet-btc/pickingstrategies/CoinSelect.ts +3 -3
  31. package/src/families/bitcoin/wallet-btc/pickingstrategies/DeepFirst.ts +5 -5
  32. package/src/families/bitcoin/wallet-btc/pickingstrategies/Merge.ts +5 -5
  33. package/src/families/bitcoin/wallet-btc/utils.ts +14 -3
  34. package/src/families/bitcoin/wallet-btc/wallet.ts +3 -1
@@ -81,7 +81,15 @@ export const getMarketcapTickers: () => Promise<string[]> = makeLRUCache(() =>
81
81
  export const useMarketcapTickers = (): string[] | null | undefined => {
82
82
  const [tickers, setMarketcapTickers] = useState(marketcapTickersCache);
83
83
  useEffect(() => {
84
- getMarketcapTickers().then(setMarketcapTickers);
84
+ let isMounted = true;
85
+
86
+ getMarketcapTickers().then((data) => {
87
+ if (isMounted) setMarketcapTickers(data);
88
+ });
89
+
90
+ return () => {
91
+ isMounted = false;
92
+ };
85
93
  }, []);
86
94
  return tickers;
87
95
  };
@@ -128,34 +128,20 @@ const mapTxToOperations = (
128
128
  // All inputs of a same transaction have the same sequence
129
129
  const transactionSequenceNumber =
130
130
  (accountInputs.length > 0 && accountInputs[0].sequence) || undefined;
131
- const hasSpentNothing = value.eq(0);
131
+
132
+ // Change output is the last one
133
+ const changeOutputIndex = tx.outputs
134
+ .map((o) => o.output_index)
135
+ .reduce((p, c) => (p > c ? p : c));
132
136
 
133
137
  for (const output of tx.outputs) {
134
138
  if (output.address) {
135
139
  if (accountAddresses.includes(output.address)) {
136
140
  accountOutputs.push(output);
137
-
138
- if (changeAddresses.includes(output.address)) {
139
- if (
140
- (recipients.length === 0 &&
141
- output.output_hash ===
142
- tx.outputs[tx.outputs.length - 1].output_hash) ||
143
- hasSpentNothing
144
- ) {
145
- recipients.push(
146
- syncReplaceAddress
147
- ? syncReplaceAddress(output.address)
148
- : output.address
149
- );
150
- }
151
- } else {
152
- recipients.push(
153
- syncReplaceAddress
154
- ? syncReplaceAddress(output.address)
155
- : output.address
156
- );
157
- }
158
- } else {
141
+ } else if (
142
+ !changeAddresses.includes(output.address) ||
143
+ output.output_index !== changeOutputIndex
144
+ ) {
159
145
  recipients.push(
160
146
  syncReplaceAddress
161
147
  ? syncReplaceAddress(output.address)
@@ -79,7 +79,7 @@ export function isChangeOutput(output: BitcoinOutput): boolean {
79
79
  type UTXOStatus =
80
80
  | {
81
81
  excluded: true;
82
- reason: "pickUnconfirmedRBF" | "userExclusion";
82
+ reason: "pickUnconfirmedRBF" | "pickPendingNonRBF" | "userExclusion";
83
83
  }
84
84
  | {
85
85
  excluded: false;
@@ -94,7 +94,12 @@ export const getUTXOStatus = (
94
94
  reason: "pickUnconfirmedRBF",
95
95
  };
96
96
  }
97
-
97
+ if (!utxo.rbf && !utxo.blockHeight) {
98
+ return {
99
+ excluded: true,
100
+ reason: "pickPendingNonRBF",
101
+ };
102
+ }
98
103
  if (
99
104
  utxoStrategy.excludeUTXOs.some(
100
105
  (u) => u.hash === utxo.hash && u.outputIndex === utxo.outputIndex
@@ -254,7 +254,12 @@ const bitcoinLikeMutations = ({
254
254
  },
255
255
  recoverBadTransactionStatus,
256
256
  test: ({ account }) => {
257
- expect(account.balance.toString()).toBe("0");
257
+ expect(
258
+ account.bitcoinResources?.utxos
259
+ .filter((u) => u.blockHeight) // Exclude pending UTXOs
260
+ .reduce((p, c) => p.plus(c.value), new BigNumber(0))
261
+ .toString()
262
+ ).toBe("0");
258
263
  },
259
264
  },
260
265
  ];
@@ -34,7 +34,7 @@ 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.estimateTxSize(
37
+ const fixedSize = utils.accurateTxSize(
38
38
  0,
39
39
  0,
40
40
  this.crypto,
@@ -42,10 +42,10 @@ export class CoinSelect extends PickingStrategy {
42
42
  );
43
43
  // Size of only 1 output (without fixed size)
44
44
  const oneOutputSize =
45
- utils.estimateTxSize(0, 1, this.crypto, this.derivationMode) - fixedSize;
45
+ utils.accurateTxSize(0, 1, this.crypto, this.derivationMode) - fixedSize;
46
46
  // Size 1 signed UTXO (signed input)
47
47
  const oneInputSize =
48
- utils.estimateTxSize(1, 0, this.crypto, this.derivationMode) - fixedSize;
48
+ utils.accurateTxSize(1, 0, this.crypto, this.derivationMode) - fixedSize;
49
49
 
50
50
  // Calculate effective value of outputs
51
51
  let currentAvailableValue = 0;
@@ -33,7 +33,7 @@ export class DeepFirst extends PickingStrategy {
33
33
 
34
34
  unspentUtxos = sortBy(unspentUtxos, "block_height");
35
35
  // https://metamug.com/article/security/bitcoin-transaction-fee-satoshi-per-byte.html
36
- const txSizeNoInput = utils.estimateTxSize(
36
+ const txSizeNoInput = utils.accurateTxSize(
37
37
  0,
38
38
  nbOutputsWithoutChange,
39
39
  this.crypto,
@@ -41,12 +41,12 @@ export class DeepFirst extends PickingStrategy {
41
41
  );
42
42
  let fee = txSizeNoInput * feePerByte;
43
43
  const sizePerInput =
44
- utils.estimateTxSize(1, 0, this.crypto, this.derivationMode) -
45
- utils.estimateTxSize(0, 0, this.crypto, this.derivationMode);
44
+ utils.accurateTxSize(1, 0, this.crypto, this.derivationMode) -
45
+ utils.accurateTxSize(0, 0, this.crypto, this.derivationMode);
46
46
 
47
47
  const sizePerOutput =
48
- utils.estimateTxSize(0, 1, this.crypto, this.derivationMode) -
49
- utils.estimateTxSize(0, 0, this.crypto, this.derivationMode);
48
+ utils.accurateTxSize(0, 1, this.crypto, this.derivationMode) -
49
+ utils.accurateTxSize(0, 0, this.crypto, this.derivationMode);
50
50
 
51
51
  let total = new BigNumber(0);
52
52
  const unspentUtxoSelected: Output[] = [];
@@ -32,16 +32,16 @@ export class Merge extends PickingStrategy {
32
32
  );
33
33
 
34
34
  const sizePerInput =
35
- utils.estimateTxSize(1, 0, this.crypto, this.derivationMode) -
36
- utils.estimateTxSize(0, 0, this.crypto, this.derivationMode);
35
+ utils.accurateTxSize(1, 0, this.crypto, this.derivationMode) -
36
+ utils.accurateTxSize(0, 0, this.crypto, this.derivationMode);
37
37
 
38
38
  const sizePerOutput =
39
- utils.estimateTxSize(0, 1, this.crypto, this.derivationMode) -
40
- utils.estimateTxSize(0, 0, this.crypto, this.derivationMode);
39
+ utils.accurateTxSize(0, 1, this.crypto, this.derivationMode) -
40
+ utils.accurateTxSize(0, 0, this.crypto, this.derivationMode);
41
41
 
42
42
  unspentUtxos = sortBy(unspentUtxos, (utxo) => parseInt(utxo.value, 10));
43
43
  // https://metamug.com/article/security/bitcoin-transaction-fee-satoshi-per-byte.html
44
- const txSizeNoInput = utils.estimateTxSize(
44
+ const txSizeNoInput = utils.accurateTxSize(
45
45
  0,
46
46
  nbOutputsWithoutChange,
47
47
  this.crypto,
@@ -92,7 +92,7 @@ export function byteSize(count: number) {
92
92
  }
93
93
 
94
94
  // refer to https://github.com/LedgerHQ/lib-ledger-core/blob/fc9d762b83fc2b269d072b662065747a64ab2816/core/src/wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.cpp#L217
95
- export function estimateTxSize(
95
+ export function accurateTxSize(
96
96
  inputCount: number,
97
97
  outputCount: number,
98
98
  currency: ICrypto,
@@ -114,7 +114,7 @@ export function estimateTxSize(
114
114
  // and https://bitcoinops.org/en/tools/calc-size/
115
115
  if (derivationMode === DerivationModes.TAPROOT) {
116
116
  txSize = fixedSize + 57.75 * inputCount + 43 * outputCount;
117
- return Math.ceil(txSize);
117
+ return txSize;
118
118
  }
119
119
  const isSegwit =
120
120
  derivationMode === DerivationModes.NATIVE_SEGWIT ||
@@ -131,7 +131,18 @@ export function estimateTxSize(
131
131
  } else {
132
132
  txSize = fixedSize + 148 * inputCount + 43 * outputCount;
133
133
  }
134
- return Math.ceil(txSize); // We don't allow floating value
134
+ return txSize;
135
+ }
136
+
137
+ export function estimateTxSize(
138
+ inputCount: number,
139
+ outputCount: number,
140
+ currency: ICrypto,
141
+ derivationMode: string
142
+ ) {
143
+ return Math.ceil(
144
+ accurateTxSize(inputCount, outputCount, currency, derivationMode)
145
+ ); // We don't allow floating value
135
146
  }
136
147
 
137
148
  // refer to https://github.com/LedgerHQ/lib-ledger-core/blob/fc9d762b83fc2b269d072b662065747a64ab2816/core/src/wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.cpp#L253
@@ -133,6 +133,7 @@ class BitcoinLikeWallet {
133
133
  )
134
134
  );
135
135
  let balance = new BigNumber(0);
136
+ let availableUtxoCount = 0;
136
137
  log("btcwallet", "estimateAccountMaxSpendable utxos", utxos);
137
138
  utxos.forEach((utxo) => {
138
139
  if (
@@ -144,6 +145,7 @@ class BitcoinLikeWallet {
144
145
  ) {
145
146
  if ((pickUnconfirmedRBF && utxo.rbf) || utxo.block_height !== null) {
146
147
  balance = balance.plus(utxo.value);
148
+ availableUtxoCount += 1;
147
149
  }
148
150
  }
149
151
  });
@@ -151,7 +153,7 @@ class BitcoinLikeWallet {
151
153
  const fees =
152
154
  feePerByte *
153
155
  utils.estimateTxSize(
154
- utxos.length,
156
+ availableUtxoCount,
155
157
  1,
156
158
  account.xpub.crypto,
157
159
  account.xpub.derivationMode