@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.
- package/lib/__tests__/families/bitcoin/wallet-btc/utils.test.js +85 -0
- package/lib/__tests__/families/bitcoin/wallet-btc/utils.test.js.map +1 -1
- package/lib/__tests__/families/bitcoin/wallet-btc/wallet.estimateMaxSpendable.test.js +1 -1
- package/lib/__tests__/families/bitcoin/wallet-btc/wallet.estimateMaxSpendable.test.js.map +1 -1
- package/lib/__tests__/families/bitcoin/wallet-btc/wallet.integration.test.js +2 -2
- package/lib/__tests__/families/bitcoin/wallet-btc/wallet.integration.test.js.map +1 -1
- package/lib/__tests__/families/bitcoin/wallet-btc/xpub.pickingStrategies.integration.test.js +20 -10
- package/lib/__tests__/families/bitcoin/wallet-btc/xpub.pickingStrategies.integration.test.js.map +1 -1
- package/lib/__tests__/families/bitcoin/wallet-btc/xpub.txs.NP2WPKH.integration.test.js +1 -1
- package/lib/__tests__/families/bitcoin/wallet-btc/xpub.txs.NP2WPKH.integration.test.js.map +1 -1
- package/lib/__tests__/families/bitcoin/wallet-btc/xpub.txs.P2WPKH.integration.test.js +1 -1
- package/lib/__tests__/families/bitcoin/wallet-btc/xpub.txs.P2WPKH.integration.test.js.map +1 -1
- package/lib/__tests__/families/bitcoin/wallet-btc/xpub.txs.integration.test.js +2 -2
- package/lib/__tests__/families/bitcoin/wallet-btc/xpub.txs.integration.test.js.map +1 -1
- package/lib/apps/polyfill.d.ts.map +1 -1
- package/lib/apps/polyfill.js +3 -0
- package/lib/apps/polyfill.js.map +1 -1
- package/lib/currencies/support.d.ts.map +1 -1
- package/lib/currencies/support.js.map +1 -1
- package/lib/families/bitcoin/js-buildTransaction.d.ts.map +1 -1
- package/lib/families/bitcoin/js-buildTransaction.js +1 -1
- package/lib/families/bitcoin/js-buildTransaction.js.map +1 -1
- package/lib/families/bitcoin/js-estimateMaxSpendable.d.ts.map +1 -1
- package/lib/families/bitcoin/js-estimateMaxSpendable.js +1 -1
- package/lib/families/bitcoin/js-estimateMaxSpendable.js.map +1 -1
- package/lib/families/bitcoin/js-synchronisation.d.ts.map +1 -1
- package/lib/families/bitcoin/js-synchronisation.js +3 -2
- package/lib/families/bitcoin/js-synchronisation.js.map +1 -1
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/CoinSelect.d.ts +2 -1
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/CoinSelect.d.ts.map +1 -1
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/CoinSelect.js +16 -12
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/CoinSelect.js.map +1 -1
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/DeepFirst.d.ts +2 -1
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/DeepFirst.d.ts.map +1 -1
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/DeepFirst.js +12 -7
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/DeepFirst.js.map +1 -1
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/Merge.d.ts +2 -1
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/Merge.d.ts.map +1 -1
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/Merge.js +12 -7
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/Merge.js.map +1 -1
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/types.d.ts +2 -1
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/types.d.ts.map +1 -1
- package/lib/families/bitcoin/wallet-btc/pickingstrategies/types.js.map +1 -1
- package/lib/families/bitcoin/wallet-btc/utils.d.ts +38 -2
- package/lib/families/bitcoin/wallet-btc/utils.d.ts.map +1 -1
- package/lib/families/bitcoin/wallet-btc/utils.js +103 -35
- package/lib/families/bitcoin/wallet-btc/utils.js.map +1 -1
- package/lib/families/bitcoin/wallet-btc/wallet.d.ts +1 -1
- package/lib/families/bitcoin/wallet-btc/wallet.d.ts.map +1 -1
- package/lib/families/bitcoin/wallet-btc/wallet.js +6 -5
- package/lib/families/bitcoin/wallet-btc/wallet.js.map +1 -1
- package/lib/families/bitcoin/wallet-btc/xpub.js +2 -2
- package/lib/families/bitcoin/wallet-btc/xpub.js.map +1 -1
- package/lib/operation.js +1 -1
- package/lib/operation.js.map +1 -1
- package/package.json +5 -5
- package/src/.DS_Store +0 -0
- package/src/__tests__/__snapshots__/all.libcore.ts.snap +1188 -630
- package/src/__tests__/families/bitcoin/wallet-btc/utils.test.ts +105 -0
- package/src/__tests__/families/bitcoin/wallet-btc/wallet.estimateMaxSpendable.test.ts +3 -2
- package/src/__tests__/families/bitcoin/wallet-btc/wallet.integration.test.ts +2 -2
- package/src/__tests__/families/bitcoin/wallet-btc/xpub.pickingStrategies.integration.test.ts +35 -31
- package/src/__tests__/families/bitcoin/wallet-btc/xpub.txs.NP2WPKH.integration.test.ts +3 -2
- package/src/__tests__/families/bitcoin/wallet-btc/xpub.txs.P2WPKH.integration.test.ts +3 -2
- package/src/__tests__/families/bitcoin/wallet-btc/xpub.txs.integration.test.ts +6 -4
- package/src/apps/polyfill.ts +3 -0
- package/src/currencies/.DS_Store +0 -0
- package/src/currencies/__snapshots__/sortByMarketcap.test.ts.snap +3 -1
- package/src/currencies/support.ts +1 -0
- package/src/families/bitcoin/js-buildTransaction.ts +2 -1
- package/src/families/bitcoin/js-estimateMaxSpendable.ts +2 -1
- package/src/families/bitcoin/js-synchronisation.ts +4 -2
- package/src/families/bitcoin/wallet-btc/pickingstrategies/CoinSelect.ts +34 -22
- package/src/families/bitcoin/wallet-btc/pickingstrategies/DeepFirst.ts +30 -9
- package/src/families/bitcoin/wallet-btc/pickingstrategies/Merge.ts +30 -9
- package/src/families/bitcoin/wallet-btc/pickingstrategies/types.ts +3 -3
- package/src/families/bitcoin/wallet-btc/utils.ts +113 -41
- package/src/families/bitcoin/wallet-btc/wallet.ts +9 -6
- package/src/families/bitcoin/wallet-btc/xpub.ts +5 -5
- 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.
|
|
60
|
+
utils.maxTxSizeCeil(
|
|
61
61
|
2,
|
|
62
|
-
|
|
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(
|
|
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(
|
|
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 () => {
|
package/src/__tests__/families/bitcoin/wallet-btc/xpub.pickingStrategies.integration.test.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
181
|
+
utils.maxTxSizeCeil(
|
|
182
182
|
inputs.length,
|
|
183
|
-
outputs.
|
|
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.
|
|
170
|
+
utils.maxTxSizeCeil(
|
|
171
171
|
inputs.length,
|
|
172
|
-
outputs.
|
|
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.
|
|
151
|
+
utils.maxTxSizeCeil(
|
|
152
152
|
inputs.length,
|
|
153
|
-
outputs.
|
|
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.
|
|
284
|
+
utils.maxTxSizeCeil(
|
|
284
285
|
inputs.length,
|
|
285
|
-
outputs.
|
|
286
|
+
outputs.map((o) => o.address),
|
|
287
|
+
false,
|
|
286
288
|
crypto,
|
|
287
289
|
DerivationModes.LEGACY
|
|
288
290
|
) * 100;
|
package/src/apps/polyfill.ts
CHANGED
|
@@ -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 (
|
|
143
|
-
// The
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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 *
|
|
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.
|
|
121
|
+
utils.maxTxSizeCeil(
|
|
106
122
|
nbInput,
|
|
107
|
-
|
|
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.
|
|
133
|
+
utils.maxTxSizeCeil(
|
|
117
134
|
nbInput,
|
|
118
|
-
|
|
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.
|
|
191
|
+
utils.maxTxSizeCeil(
|
|
174
192
|
unspentUtxoSelected.length,
|
|
175
|
-
|
|
176
|
-
|
|
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
|
-
|
|
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.
|
|
37
|
+
const txSizeNoInput = utils.maxTxSize(
|
|
37
38
|
0,
|
|
38
|
-
|
|
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.
|
|
45
|
-
|
|
53
|
+
utils.maxTxSize(1, [], false, this.crypto, this.derivationMode) -
|
|
54
|
+
emptyTxSize;
|
|
46
55
|
|
|
47
56
|
const sizePerOutput =
|
|
48
|
-
|
|
49
|
-
|
|
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]) {
|