@scure/btc-signer 1.3.2 → 1.4.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.
- package/README.md +2 -5
- package/_type_test.d.ts.map +1 -0
- package/_type_test.js.map +1 -0
- package/esm/_type_test.d.ts +2 -0
- package/esm/_type_test.js.map +1 -0
- package/{lib → esm}/index.d.ts +2 -2
- package/esm/index.d.ts.map +1 -0
- package/{lib/esm → esm}/index.js +1 -1
- package/esm/index.js.map +1 -0
- package/{lib → esm}/payment.d.ts.map +1 -1
- package/{lib/esm → esm}/payment.js +1 -1
- package/esm/payment.js.map +1 -0
- package/{lib → esm}/psbt.d.ts +0 -14
- package/esm/psbt.d.ts.map +1 -0
- package/{lib/esm → esm}/psbt.js +4 -5
- package/esm/psbt.js.map +1 -0
- package/{lib → esm}/script.d.ts +14 -0
- package/{lib → esm}/script.d.ts.map +1 -1
- package/{lib/esm → esm}/script.js +7 -0
- package/esm/script.js.map +1 -0
- package/{lib → esm}/transaction.d.ts +15 -9
- package/esm/transaction.d.ts.map +1 -0
- package/{lib/esm → esm}/transaction.js +33 -7
- package/esm/transaction.js.map +1 -0
- package/{lib → esm}/utils.d.ts +3 -3
- package/esm/utils.d.ts.map +1 -0
- package/esm/utils.js.map +1 -0
- package/{lib → esm}/utxo.d.ts +16 -19
- package/esm/utxo.d.ts.map +1 -0
- package/{lib/esm → esm}/utxo.js +65 -27
- package/esm/utxo.js.map +1 -0
- package/index.d.ts +20 -0
- package/index.d.ts.map +1 -0
- package/{lib/index.js → index.js} +2 -1
- package/index.js.map +1 -0
- package/package.json +43 -43
- package/payment.d.ts +177 -0
- package/payment.d.ts.map +1 -0
- package/{lib/payment.js → payment.js} +12 -12
- package/payment.js.map +1 -0
- package/psbt.d.ts +820 -0
- package/psbt.d.ts.map +1 -0
- package/{lib/psbt.js → psbt.js} +10 -11
- package/psbt.js.map +1 -0
- package/script.d.ts +168 -0
- package/script.d.ts.map +1 -0
- package/{lib/script.js → script.js} +10 -3
- package/script.js.map +1 -0
- package/src/index.ts +1 -1
- package/src/payment.ts +3 -3
- package/src/psbt.ts +4 -5
- package/src/script.ts +7 -0
- package/src/transaction.ts +38 -7
- package/src/utxo.ts +80 -23
- package/transaction.d.ts +229 -0
- package/transaction.d.ts.map +1 -0
- package/{lib/transaction.js → transaction.js} +45 -19
- package/transaction.js.map +1 -0
- package/utils.d.ts +30 -0
- package/utils.d.ts.map +1 -0
- package/{lib/utils.js → utils.js} +7 -7
- package/utils.js.map +1 -0
- package/utxo.d.ts +248 -0
- package/utxo.d.ts.map +1 -0
- package/{lib/utxo.js → utxo.js} +70 -32
- package/utxo.js.map +1 -0
- package/lib/_type_test.js.map +0 -1
- package/lib/esm/_type_test.js.map +0 -1
- package/lib/esm/index.js.map +0 -1
- package/lib/esm/payment.js.map +0 -1
- package/lib/esm/psbt.js.map +0 -1
- package/lib/esm/script.js.map +0 -1
- package/lib/esm/transaction.js.map +0 -1
- package/lib/esm/utils.js.map +0 -1
- package/lib/esm/utxo.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/payment.js.map +0 -1
- package/lib/psbt.d.ts.map +0 -1
- package/lib/psbt.js.map +0 -1
- package/lib/script.js.map +0 -1
- package/lib/transaction.d.ts.map +0 -1
- package/lib/transaction.js.map +0 -1
- package/lib/utils.d.ts.map +0 -1
- package/lib/utils.js.map +0 -1
- package/lib/utxo.d.ts.map +0 -1
- package/lib/utxo.js.map +0 -1
- /package/{lib/_type_test.d.ts → _type_test.d.ts} +0 -0
- /package/{lib/_type_test.js → _type_test.js} +0 -0
- /package/{lib → esm}/_type_test.d.ts.map +0 -0
- /package/{lib/esm → esm}/_type_test.js +0 -0
- /package/{lib/esm → esm}/package.json +0 -0
- /package/{lib → esm}/payment.d.ts +0 -0
- /package/{lib/esm → esm}/utils.js +0 -0
package/src/utxo.ts
CHANGED
|
@@ -268,7 +268,10 @@ export type EstimatorOpts = TxOpts & {
|
|
|
268
268
|
bip69?: boolean; // https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki
|
|
269
269
|
network?: typeof NETWORK;
|
|
270
270
|
dust?: number; // how much vbytes considered dust?
|
|
271
|
+
dustRelayFeeRate?: bigint; // fee per dust byte (DUST_RELAY_TX_FEE)
|
|
271
272
|
createTx?: boolean; // Create tx inside selection
|
|
273
|
+
requiredInputs?: psbt.TransactionInputUpdate[]; // these inputs always will be used
|
|
274
|
+
allowSameUtxo?: boolean; // allow using UTXO multiple times (for test purposes)
|
|
272
275
|
};
|
|
273
276
|
|
|
274
277
|
function getScript(o: Output, opts: TxOpts = {}, network = NETWORK) {
|
|
@@ -282,7 +285,12 @@ function getScript(o: Output, opts: TxOpts = {}, network = NETWORK) {
|
|
|
282
285
|
script = OutScript.encode(Address(network).decode(o.address));
|
|
283
286
|
}
|
|
284
287
|
if (!script) throw new Error('Estimator: wrong output script');
|
|
285
|
-
if (typeof o.amount !== 'bigint')
|
|
288
|
+
if (typeof o.amount !== 'bigint')
|
|
289
|
+
throw new Error(
|
|
290
|
+
`Estimator: wrong output amount=${
|
|
291
|
+
o.amount
|
|
292
|
+
}, should be of type bigint but got ${typeof o.amount}.`
|
|
293
|
+
);
|
|
286
294
|
if (script && !opts.allowUnknownOutputs && OutScript.decode(script).type === 'unknown') {
|
|
287
295
|
throw new Error(
|
|
288
296
|
'Estimator: unknown output script type, there is a chance that input is unspendable. Pass allowUnknownOutputs=true, if you sure'
|
|
@@ -310,6 +318,7 @@ export class _Estimator {
|
|
|
310
318
|
private baseWeight: number;
|
|
311
319
|
private changeWeight: number;
|
|
312
320
|
private amount: bigint;
|
|
321
|
+
private requiredIndices: number[] = [];
|
|
313
322
|
private normalizedInputs: {
|
|
314
323
|
inputType: ReturnType<typeof getInputType>;
|
|
315
324
|
normalized: ReturnType<typeof normalizeInput>;
|
|
@@ -317,24 +326,51 @@ export class _Estimator {
|
|
|
317
326
|
value: bigint;
|
|
318
327
|
estimate: { weight: number; hasWitnesses: boolean };
|
|
319
328
|
}[];
|
|
320
|
-
// https://github.com/bitcoin/bitcoin/blob/f90603ac6d24f5263649675d51233f1fce8b2ecd/src/policy/policy.cpp#L44
|
|
321
|
-
// 32 + 4 + 1 + 107 + 4
|
|
322
329
|
// Dust used in accumExact + change address algo
|
|
323
330
|
// - change address: can be smaller for segwit
|
|
324
331
|
// - accumExact: ???
|
|
325
|
-
private dust
|
|
326
|
-
|
|
332
|
+
private dust: bigint; // total dust limit (3||opts.dustRelayFeeRate * 182||opts.dust). Default: 546
|
|
327
333
|
constructor(
|
|
328
|
-
|
|
334
|
+
inputs: psbt.TransactionInputUpdate[],
|
|
329
335
|
private outputs: Output[],
|
|
330
336
|
private opts: EstimatorOpts
|
|
331
337
|
) {
|
|
332
338
|
if (typeof opts.feePerByte !== 'bigint')
|
|
333
|
-
throw new Error(
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
339
|
+
throw new Error(
|
|
340
|
+
`Estimator: wrong feePerByte=${
|
|
341
|
+
opts.feePerByte
|
|
342
|
+
}, should be of type bigint but got ${typeof opts.feePerByte}.`
|
|
343
|
+
);
|
|
344
|
+
// Dust stuff
|
|
345
|
+
// TODO: think about this more:
|
|
346
|
+
// - current dust filters tx which cannot be relayed by core
|
|
347
|
+
// - but actual dust meaning is 'can be this amount spent?'
|
|
348
|
+
// - dust contains full tx size. but we can use other inputs to pay for outputDust (and parially inputsDust)?
|
|
349
|
+
// - not sure if we can spent anything with feePerByte: 3. It will be relayed, but will it be mined?
|
|
350
|
+
// - for now it works exactly as bitcoin-core. But will create change/outputs which cannot be spent (reasonable).
|
|
351
|
+
// Number of bytes needed to create and spend a UTXO.
|
|
352
|
+
// https://github.com/bitcoin/bitcoin/blob/27a770b34b8f1dbb84760f442edb3e23a0c2420b/src/policy/policy.cpp#L28-L41
|
|
353
|
+
const inputsDust = 32 + 4 + 1 + 107 + 4; // NOTE: can be smaller for segwit tx?
|
|
354
|
+
const outputDust = 34; // NOTE: 'nSize = GetSerializeSize(txout)'
|
|
355
|
+
const dustBytes = opts.dust === undefined ? BigInt(inputsDust + outputDust) : opts.dust;
|
|
356
|
+
if (typeof dustBytes !== 'bigint') {
|
|
357
|
+
throw new Error(
|
|
358
|
+
`Estimator: wrong dust=${opts.dust}, should be of type bigint but got ${typeof opts.dust}.`
|
|
359
|
+
);
|
|
337
360
|
}
|
|
361
|
+
// 3 sat/vb is the default minimum fee rate used to calculate dust thresholds by bitcoin core.
|
|
362
|
+
// 3000 sat/kvb -> 3 sat/vb.
|
|
363
|
+
// https://github.com/bitcoin/bitcoin/blob/27a770b34b8f1dbb84760f442edb3e23a0c2420b/src/policy/policy.h#L55
|
|
364
|
+
const dustFee = opts.dustRelayFeeRate === undefined ? 3n : opts.dustRelayFeeRate;
|
|
365
|
+
if (typeof dustFee !== 'bigint') {
|
|
366
|
+
throw new Error(
|
|
367
|
+
`Estimator: wrong dustRelayFeeRate=${opts.dustRelayFeeRate}, should be of type bigint but got ${typeof opts.dustRelayFeeRate}.`
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
// Dust uses feePerbyte by default, but we allow separate dust fee if needed
|
|
371
|
+
this.dust = dustBytes * dustFee;
|
|
372
|
+
if (opts.requiredInputs !== undefined && !Array.isArray(opts.requiredInputs))
|
|
373
|
+
throw new Error(`Estimator: wrong required inputs=${opts.requiredInputs}`);
|
|
338
374
|
const network = opts.network || NETWORK;
|
|
339
375
|
let amount = 0n;
|
|
340
376
|
// Base weight: tx with outputs, no inputs
|
|
@@ -356,9 +392,19 @@ export class _Estimator {
|
|
|
356
392
|
this.baseWeight = baseWeight;
|
|
357
393
|
this.changeWeight = changeWeight;
|
|
358
394
|
this.amount = amount;
|
|
359
|
-
|
|
395
|
+
const allInputs = Array.from(inputs);
|
|
396
|
+
if (opts.requiredInputs) {
|
|
397
|
+
for (let i = 0; i < opts.requiredInputs.length; i++)
|
|
398
|
+
this.requiredIndices.push(allInputs.push(opts.requiredInputs[i]) - 1);
|
|
399
|
+
}
|
|
400
|
+
const inputKeys = new Set();
|
|
401
|
+
this.normalizedInputs = allInputs.map((i) => {
|
|
360
402
|
const normalized = normalizeInput(i, undefined, undefined, opts.disableScriptCheck);
|
|
361
403
|
inputBeforeSign(normalized); // check fields
|
|
404
|
+
const key = `${hex.encode(normalized.txid!)}:${normalized.index}`;
|
|
405
|
+
if (!opts.allowSameUtxo && inputKeys.has(key))
|
|
406
|
+
throw new Error(`Estimator: same input passed multiple times: ${key}`);
|
|
407
|
+
inputKeys.add(key);
|
|
362
408
|
const inputType = getInputType(normalized, opts.allowLegacyWitnessUtxo);
|
|
363
409
|
const prev = getPrevOut(normalized);
|
|
364
410
|
const estimate = estimateInput(inputType, normalized, this.opts);
|
|
@@ -367,7 +413,7 @@ export class _Estimator {
|
|
|
367
413
|
});
|
|
368
414
|
}
|
|
369
415
|
private checkInputIdx(idx: number) {
|
|
370
|
-
if (!Number.isSafeInteger(idx) || 0 > idx || idx >= this.
|
|
416
|
+
if (!Number.isSafeInteger(idx) || 0 > idx || idx >= this.normalizedInputs.length)
|
|
371
417
|
throw new Error(`Wrong input index=${idx}`);
|
|
372
418
|
return idx;
|
|
373
419
|
}
|
|
@@ -397,7 +443,7 @@ export class _Estimator {
|
|
|
397
443
|
|
|
398
444
|
// Sort by value instead of amount
|
|
399
445
|
get biggest() {
|
|
400
|
-
return this.
|
|
446
|
+
return this.normalizedInputs
|
|
401
447
|
.map((_i, j) => j)
|
|
402
448
|
.sort((a, b) => _cmpBig(this.normalizedInputs[b].value, this.normalizedInputs[a].value));
|
|
403
449
|
}
|
|
@@ -408,7 +454,7 @@ export class _Estimator {
|
|
|
408
454
|
// Otherwise, we have no way to know which tx is oldest
|
|
409
455
|
// Explorers usually give UTXO in this order.
|
|
410
456
|
get oldest() {
|
|
411
|
-
return this.
|
|
457
|
+
return this.normalizedInputs.map((_i, j) => j);
|
|
412
458
|
}
|
|
413
459
|
get newest() {
|
|
414
460
|
return this.oldest.reverse();
|
|
@@ -417,7 +463,6 @@ export class _Estimator {
|
|
|
417
463
|
// exact(biggest) will select one big utxo which is closer to targetValue+dust, if possible.
|
|
418
464
|
// If not, it will accumulate largest utxo until value is close to targetValue+dust.
|
|
419
465
|
accumulate(indices: number[], exact = false, skipNegative = true, all = false) {
|
|
420
|
-
const { feePerByte } = this.opts;
|
|
421
466
|
// TODO: how to handle change addresses?
|
|
422
467
|
// - cost of input
|
|
423
468
|
// - cost of change output (if input requires change)
|
|
@@ -433,6 +478,22 @@ export class _Estimator {
|
|
|
433
478
|
const targetAmount = this.amount;
|
|
434
479
|
const res = [];
|
|
435
480
|
let fee;
|
|
481
|
+
for (const idx of this.requiredIndices) {
|
|
482
|
+
this.checkInputIdx(idx);
|
|
483
|
+
const { estimate, amount } = this.normalizedInputs[idx];
|
|
484
|
+
let newWeight = weight + estimate.weight;
|
|
485
|
+
if (!hasWitnesses && estimate.hasWitnesses) newWeight += 2; // enable witness if needed
|
|
486
|
+
const totalWeight = newWeight + 4 * CompactSizeLen.encode(num).length; // number of outputs can change weight
|
|
487
|
+
fee = this.getSatoshi(totalWeight);
|
|
488
|
+
weight = newWeight;
|
|
489
|
+
if (estimate.hasWitnesses) hasWitnesses = true;
|
|
490
|
+
num++;
|
|
491
|
+
inputsAmount += amount;
|
|
492
|
+
res.push(idx);
|
|
493
|
+
// inputsAmount is enough to cover cost of tx
|
|
494
|
+
if (!all && targetAmount + fee <= inputsAmount)
|
|
495
|
+
return { indices: res, fee, weight: totalWeight, total: inputsAmount };
|
|
496
|
+
}
|
|
436
497
|
for (const idx of indices) {
|
|
437
498
|
this.checkInputIdx(idx);
|
|
438
499
|
const { estimate, amount, value } = this.normalizedInputs[idx];
|
|
@@ -441,11 +502,7 @@ export class _Estimator {
|
|
|
441
502
|
const totalWeight = newWeight + 4 * CompactSizeLen.encode(num).length; // number of outputs can change weight
|
|
442
503
|
fee = this.getSatoshi(totalWeight);
|
|
443
504
|
// Best case scenario exact(biggest) -> we find biggest output, less than target+threshold
|
|
444
|
-
if (exact)
|
|
445
|
-
const dust = this.dust * feePerByte;
|
|
446
|
-
// skip if added value is bigger than dust
|
|
447
|
-
if (amount + inputsAmount > targetAmount + fee + dust) continue;
|
|
448
|
-
}
|
|
505
|
+
if (exact && amount + inputsAmount > targetAmount + fee + this.dust) continue; // skip if added value is bigger than dust
|
|
449
506
|
// Negative: cost of using input is more than value provided (negative)
|
|
450
507
|
// By default 'blackjack' mode in coinselect doesn't use that, which means
|
|
451
508
|
// it will use negative output if sorted by 'smallest'
|
|
@@ -456,7 +513,7 @@ export class _Estimator {
|
|
|
456
513
|
inputsAmount += amount;
|
|
457
514
|
res.push(idx);
|
|
458
515
|
// inputsAmount is enough to cover cost of tx
|
|
459
|
-
if (!all && targetAmount + fee
|
|
516
|
+
if (!all && targetAmount + fee <= inputsAmount)
|
|
460
517
|
return { indices: res, fee, weight: totalWeight, total: inputsAmount };
|
|
461
518
|
}
|
|
462
519
|
if (all) {
|
|
@@ -477,7 +534,7 @@ export class _Estimator {
|
|
|
477
534
|
private select(strategy: SelectionStrategy) {
|
|
478
535
|
if (strategy === 'all') {
|
|
479
536
|
return this.accumulate(
|
|
480
|
-
this.
|
|
537
|
+
this.normalizedInputs.map((_, j) => j),
|
|
481
538
|
false,
|
|
482
539
|
true,
|
|
483
540
|
true
|
|
@@ -531,7 +588,7 @@ export class _Estimator {
|
|
|
531
588
|
outputs = this.sortOutputs(outputs).map((i) => outputs[i]);
|
|
532
589
|
}
|
|
533
590
|
const res = {
|
|
534
|
-
inputs: inputs.map((i) => this.
|
|
591
|
+
inputs: inputs.map((i) => this.normalizedInputs[i].normalized),
|
|
535
592
|
outputs,
|
|
536
593
|
fee,
|
|
537
594
|
weight: this.opts.alwaysChange ? s.weight : changeWeight,
|
package/transaction.d.ts
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import * as P from 'micro-packed';
|
|
2
|
+
import { CustomScript } from './payment.js';
|
|
3
|
+
import * as psbt from './psbt.js';
|
|
4
|
+
import { Bytes } from './utils.js';
|
|
5
|
+
interface HDKey {
|
|
6
|
+
publicKey: Bytes;
|
|
7
|
+
privateKey: Bytes;
|
|
8
|
+
fingerprint: number;
|
|
9
|
+
derive(path: string): HDKey;
|
|
10
|
+
deriveChild(index: number): HDKey;
|
|
11
|
+
sign(hash: Bytes): Bytes;
|
|
12
|
+
}
|
|
13
|
+
export type Signer = Bytes | HDKey;
|
|
14
|
+
export declare const PRECISION = 8;
|
|
15
|
+
export declare const DEFAULT_VERSION = 2;
|
|
16
|
+
export declare const DEFAULT_LOCKTIME = 0;
|
|
17
|
+
export declare const DEFAULT_SEQUENCE = 4294967295;
|
|
18
|
+
export declare const Decimal: {
|
|
19
|
+
encode: (from: bigint) => string;
|
|
20
|
+
decode: (to: string) => bigint;
|
|
21
|
+
};
|
|
22
|
+
export declare const def: <T>(value: T | undefined, def: T) => T;
|
|
23
|
+
export declare function cloneDeep<T>(obj: T): T;
|
|
24
|
+
export type TxOpts = {
|
|
25
|
+
version?: number;
|
|
26
|
+
lockTime?: number;
|
|
27
|
+
PSBTVersion?: number;
|
|
28
|
+
/** @deprecated Use `allowUnknownOutputs` */
|
|
29
|
+
allowUnknowOutput?: boolean;
|
|
30
|
+
allowUnknownOutputs?: boolean;
|
|
31
|
+
/** @deprecated Use `allowUnknownInputs` */
|
|
32
|
+
allowUnknowInput?: boolean;
|
|
33
|
+
allowUnknownInputs?: boolean;
|
|
34
|
+
disableScriptCheck?: boolean;
|
|
35
|
+
bip174jsCompat?: boolean;
|
|
36
|
+
allowLegacyWitnessUtxo?: boolean;
|
|
37
|
+
lowR?: boolean;
|
|
38
|
+
customScripts?: CustomScript[];
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Internal, exported only for backwards-compat. Use `SigHash` instead.
|
|
42
|
+
* @deprecated
|
|
43
|
+
*/
|
|
44
|
+
export declare enum SignatureHash {
|
|
45
|
+
DEFAULT = 0,
|
|
46
|
+
ALL = 1,
|
|
47
|
+
NONE = 2,
|
|
48
|
+
SINGLE = 3,
|
|
49
|
+
ANYONECANPAY = 128
|
|
50
|
+
}
|
|
51
|
+
export declare enum SigHash {
|
|
52
|
+
DEFAULT = 0,
|
|
53
|
+
ALL = 1,
|
|
54
|
+
NONE = 2,
|
|
55
|
+
SINGLE = 3,
|
|
56
|
+
DEFAULT_ANYONECANPAY = 128,
|
|
57
|
+
ALL_ANYONECANPAY = 129,
|
|
58
|
+
NONE_ANYONECANPAY = 130,
|
|
59
|
+
SINGLE_ANYONECANPAY = 131
|
|
60
|
+
}
|
|
61
|
+
export type TransactionInputRequired = {
|
|
62
|
+
txid: Bytes;
|
|
63
|
+
index: number;
|
|
64
|
+
sequence: number;
|
|
65
|
+
finalScriptSig: Bytes;
|
|
66
|
+
};
|
|
67
|
+
export declare function inputBeforeSign(i: psbt.TransactionInput): TransactionInputRequired;
|
|
68
|
+
declare function validateOpts(opts: TxOpts): Readonly<{
|
|
69
|
+
version: number;
|
|
70
|
+
lockTime: number;
|
|
71
|
+
PSBTVersion: number;
|
|
72
|
+
/** @deprecated Use `allowUnknownOutputs` */
|
|
73
|
+
allowUnknowOutput?: boolean;
|
|
74
|
+
allowUnknownOutputs?: boolean;
|
|
75
|
+
/** @deprecated Use `allowUnknownInputs` */
|
|
76
|
+
allowUnknowInput?: boolean;
|
|
77
|
+
allowUnknownInputs?: boolean;
|
|
78
|
+
disableScriptCheck?: boolean;
|
|
79
|
+
bip174jsCompat?: boolean;
|
|
80
|
+
allowLegacyWitnessUtxo?: boolean;
|
|
81
|
+
lowR?: boolean;
|
|
82
|
+
customScripts?: CustomScript[];
|
|
83
|
+
}>;
|
|
84
|
+
export declare class Transaction {
|
|
85
|
+
private global;
|
|
86
|
+
private inputs;
|
|
87
|
+
private outputs;
|
|
88
|
+
readonly opts: ReturnType<typeof validateOpts>;
|
|
89
|
+
constructor(opts?: TxOpts);
|
|
90
|
+
static fromRaw(raw: Bytes, opts?: TxOpts): Transaction;
|
|
91
|
+
static fromPSBT(psbt_: Bytes, opts?: TxOpts): Transaction;
|
|
92
|
+
toPSBT(PSBTVersion?: number): Uint8Array;
|
|
93
|
+
get lockTime(): number;
|
|
94
|
+
get version(): number;
|
|
95
|
+
private inputStatus;
|
|
96
|
+
private inputSighash;
|
|
97
|
+
private signStatus;
|
|
98
|
+
get isFinal(): boolean;
|
|
99
|
+
get hasWitnesses(): boolean;
|
|
100
|
+
get weight(): number;
|
|
101
|
+
get vsize(): number;
|
|
102
|
+
toBytes(withScriptSig?: boolean, withWitness?: boolean): Uint8Array;
|
|
103
|
+
get unsignedTx(): Bytes;
|
|
104
|
+
get hex(): string;
|
|
105
|
+
get hash(): string;
|
|
106
|
+
get id(): string;
|
|
107
|
+
private checkInputIdx;
|
|
108
|
+
getInput(idx: number): psbt.PSBTKeyMapKeys<{
|
|
109
|
+
readonly nonWitnessUtxo: readonly [0, false, P.CoderType<P.StructInput<{
|
|
110
|
+
version: number;
|
|
111
|
+
segwitFlag: boolean | undefined;
|
|
112
|
+
inputs: P.StructInput<{
|
|
113
|
+
txid: any;
|
|
114
|
+
index: any;
|
|
115
|
+
finalScriptSig: any;
|
|
116
|
+
sequence: any;
|
|
117
|
+
}>[];
|
|
118
|
+
outputs: P.StructInput<{
|
|
119
|
+
amount: any;
|
|
120
|
+
script: any;
|
|
121
|
+
}>[];
|
|
122
|
+
witnesses: P.Option<Uint8Array[][]>;
|
|
123
|
+
lockTime: number;
|
|
124
|
+
}>>, readonly [], readonly [0, 2], false];
|
|
125
|
+
readonly witnessUtxo: readonly [1, false, P.CoderType<P.StructInput<{
|
|
126
|
+
amount: bigint;
|
|
127
|
+
script: Uint8Array;
|
|
128
|
+
}>>, readonly [], readonly [0, 2], false];
|
|
129
|
+
readonly partialSig: readonly [2, P.CoderType<Uint8Array>, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
130
|
+
readonly sighashType: readonly [3, false, P.CoderType<number>, readonly [], readonly [0, 2], false];
|
|
131
|
+
readonly redeemScript: readonly [4, false, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
132
|
+
readonly witnessScript: readonly [5, false, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
133
|
+
readonly bip32Derivation: readonly [6, P.CoderType<Uint8Array>, P.CoderType<P.StructInput<{
|
|
134
|
+
fingerprint: number;
|
|
135
|
+
path: number[];
|
|
136
|
+
}>>, readonly [], readonly [0, 2], false];
|
|
137
|
+
readonly finalScriptSig: readonly [7, false, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
138
|
+
readonly finalScriptWitness: readonly [8, false, P.CoderType<Uint8Array[]>, readonly [], readonly [0, 2], false];
|
|
139
|
+
readonly porCommitment: readonly [9, false, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
140
|
+
readonly ripemd160: readonly [10, P.CoderType<Uint8Array>, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
141
|
+
readonly sha256: readonly [11, P.CoderType<Uint8Array>, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
142
|
+
readonly hash160: readonly [12, P.CoderType<Uint8Array>, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
143
|
+
readonly hash256: readonly [13, P.CoderType<Uint8Array>, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
144
|
+
readonly txid: readonly [14, false, P.CoderType<Uint8Array>, readonly [2], readonly [2], true];
|
|
145
|
+
readonly index: readonly [15, false, P.CoderType<number>, readonly [2], readonly [2], true];
|
|
146
|
+
readonly sequence: readonly [16, false, P.CoderType<number>, readonly [], readonly [2], true];
|
|
147
|
+
readonly requiredTimeLocktime: readonly [17, false, P.CoderType<number>, readonly [], readonly [2], false];
|
|
148
|
+
readonly requiredHeightLocktime: readonly [18, false, P.CoderType<number>, readonly [], readonly [2], false];
|
|
149
|
+
readonly tapKeySig: readonly [19, false, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
150
|
+
readonly tapScriptSig: readonly [20, P.CoderType<P.StructInput<{
|
|
151
|
+
pubKey: Uint8Array;
|
|
152
|
+
leafHash: Uint8Array;
|
|
153
|
+
}>>, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
154
|
+
readonly tapLeafScript: readonly [21, P.CoderType<P.StructInput<{
|
|
155
|
+
version: number;
|
|
156
|
+
internalKey: Uint8Array;
|
|
157
|
+
merklePath: Uint8Array[];
|
|
158
|
+
}>>, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
159
|
+
readonly tapBip32Derivation: readonly [22, P.CoderType<Uint8Array>, P.CoderType<P.StructInput<{
|
|
160
|
+
hashes: Uint8Array[];
|
|
161
|
+
der: P.StructInput<{
|
|
162
|
+
fingerprint: any;
|
|
163
|
+
path: any;
|
|
164
|
+
}>;
|
|
165
|
+
}>>, readonly [], readonly [0, 2], false];
|
|
166
|
+
readonly tapInternalKey: readonly [23, false, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
167
|
+
readonly tapMerkleRoot: readonly [24, false, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
168
|
+
readonly proprietary: readonly [252, P.CoderType<Uint8Array>, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
169
|
+
}>;
|
|
170
|
+
get inputsLength(): number;
|
|
171
|
+
addInput(input: psbt.TransactionInputUpdate, _ignoreSignStatus?: boolean): number;
|
|
172
|
+
updateInput(idx: number, input: psbt.TransactionInputUpdate, _ignoreSignStatus?: boolean): void;
|
|
173
|
+
private checkOutputIdx;
|
|
174
|
+
getOutput(idx: number): psbt.PSBTKeyMapKeys<{
|
|
175
|
+
readonly redeemScript: readonly [0, false, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
176
|
+
readonly witnessScript: readonly [1, false, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
177
|
+
readonly bip32Derivation: readonly [2, P.CoderType<Uint8Array>, P.CoderType<P.StructInput<{
|
|
178
|
+
fingerprint: number;
|
|
179
|
+
path: number[];
|
|
180
|
+
}>>, readonly [], readonly [0, 2], false];
|
|
181
|
+
readonly amount: readonly [3, false, P.CoderType<bigint>, readonly [2], readonly [2], true];
|
|
182
|
+
readonly script: readonly [4, false, P.CoderType<Uint8Array>, readonly [2], readonly [2], true];
|
|
183
|
+
readonly tapInternalKey: readonly [5, false, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
184
|
+
readonly tapTree: readonly [6, false, P.CoderType<P.StructInput<{
|
|
185
|
+
depth: number;
|
|
186
|
+
version: number;
|
|
187
|
+
script: Uint8Array;
|
|
188
|
+
}>[]>, readonly [], readonly [0, 2], false];
|
|
189
|
+
readonly tapBip32Derivation: readonly [7, P.CoderType<Uint8Array>, P.CoderType<P.StructInput<{
|
|
190
|
+
hashes: Uint8Array[];
|
|
191
|
+
der: P.StructInput<{
|
|
192
|
+
fingerprint: any;
|
|
193
|
+
path: any;
|
|
194
|
+
}>;
|
|
195
|
+
}>>, readonly [], readonly [0, 2], false];
|
|
196
|
+
readonly proprietary: readonly [252, P.CoderType<Uint8Array>, P.CoderType<Uint8Array>, readonly [], readonly [0, 2], false];
|
|
197
|
+
}>;
|
|
198
|
+
getOutputAddress(idx: number, network?: {
|
|
199
|
+
bech32: string;
|
|
200
|
+
pubKeyHash: number;
|
|
201
|
+
scriptHash: number;
|
|
202
|
+
wif: number;
|
|
203
|
+
}): string | undefined;
|
|
204
|
+
get outputsLength(): number;
|
|
205
|
+
private normalizeOutput;
|
|
206
|
+
addOutput(o: psbt.TransactionOutputUpdate, _ignoreSignStatus?: boolean): number;
|
|
207
|
+
updateOutput(idx: number, output: psbt.TransactionOutputUpdate, _ignoreSignStatus?: boolean): void;
|
|
208
|
+
addOutputAddress(address: string, amount: bigint, network?: {
|
|
209
|
+
bech32: string;
|
|
210
|
+
pubKeyHash: number;
|
|
211
|
+
scriptHash: number;
|
|
212
|
+
wif: number;
|
|
213
|
+
}): number;
|
|
214
|
+
get fee(): bigint;
|
|
215
|
+
private preimageLegacy;
|
|
216
|
+
preimageWitnessV0(idx: number, prevOutScript: Bytes, hashType: number, amount: bigint): Uint8Array;
|
|
217
|
+
preimageWitnessV1(idx: number, prevOutScript: Bytes[], hashType: number, amount: bigint[], codeSeparator?: number, leafScript?: Bytes, leafVer?: number, annex?: Bytes): Uint8Array;
|
|
218
|
+
signIdx(privateKey: Signer, idx: number, allowedSighash?: SigHash[], _auxRand?: Bytes): boolean;
|
|
219
|
+
sign(privateKey: Signer, allowedSighash?: number[], _auxRand?: Bytes): number;
|
|
220
|
+
finalizeIdx(idx: number): void;
|
|
221
|
+
finalize(): void;
|
|
222
|
+
extract(): Uint8Array;
|
|
223
|
+
combine(other: Transaction): this;
|
|
224
|
+
clone(): Transaction;
|
|
225
|
+
}
|
|
226
|
+
export declare function PSBTCombine(psbts: Bytes[]): Bytes;
|
|
227
|
+
export declare function bip32Path(path: string): number[];
|
|
228
|
+
export {};
|
|
229
|
+
//# sourceMappingURL=transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["src/transaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.Transaction = exports.SigHash = exports.SignatureHash = exports.def = exports.Decimal = exports.DEFAULT_SEQUENCE = exports.DEFAULT_LOCKTIME = exports.DEFAULT_VERSION = exports.PRECISION = void 0;
|
|
4
|
+
exports.cloneDeep = cloneDeep;
|
|
5
|
+
exports.inputBeforeSign = inputBeforeSign;
|
|
6
|
+
exports.PSBTCombine = PSBTCombine;
|
|
7
|
+
exports.bip32Path = bip32Path;
|
|
4
8
|
const P = require("micro-packed");
|
|
5
9
|
const base_1 = require("@scure/base");
|
|
6
10
|
const payment_js_1 = require("./payment.js");
|
|
7
11
|
const psbt = require("./psbt.js"); // circular
|
|
8
12
|
const script_js_1 = require("./script.js");
|
|
13
|
+
const script_js_2 = require("./script.js");
|
|
9
14
|
const utils_js_1 = require("./utils.js");
|
|
10
15
|
const u = require("./utils.js");
|
|
11
16
|
const utxo_js_1 = require("./utxo.js"); // circular
|
|
@@ -40,7 +45,6 @@ function cloneDeep(obj) {
|
|
|
40
45
|
}
|
|
41
46
|
throw new Error(`cloneDeep: unknown type=${obj} (${typeof obj})`);
|
|
42
47
|
}
|
|
43
|
-
exports.cloneDeep = cloneDeep;
|
|
44
48
|
/**
|
|
45
49
|
* Internal, exported only for backwards-compat. Use `SigHash` instead.
|
|
46
50
|
* @deprecated
|
|
@@ -88,7 +92,6 @@ function inputBeforeSign(i) {
|
|
|
88
92
|
finalScriptSig: (0, exports.def)(i.finalScriptSig, P.EMPTY),
|
|
89
93
|
};
|
|
90
94
|
}
|
|
91
|
-
exports.inputBeforeSign = inputBeforeSign;
|
|
92
95
|
function cleanFinalInput(i) {
|
|
93
96
|
for (const _k in i) {
|
|
94
97
|
const k = _k;
|
|
@@ -177,7 +180,7 @@ class Transaction {
|
|
|
177
180
|
}
|
|
178
181
|
// Import
|
|
179
182
|
static fromRaw(raw, opts = {}) {
|
|
180
|
-
const parsed =
|
|
183
|
+
const parsed = script_js_2.RawTx.decode(raw);
|
|
181
184
|
const tx = new Transaction({ ...opts, version: parsed.version, lockTime: parsed.lockTime });
|
|
182
185
|
for (const o of parsed.outputs)
|
|
183
186
|
tx.addOutput(o);
|
|
@@ -231,6 +234,11 @@ class Transaction {
|
|
|
231
234
|
toPSBT(PSBTVersion = this.opts.PSBTVersion) {
|
|
232
235
|
if (PSBTVersion !== 0 && PSBTVersion !== 2)
|
|
233
236
|
throw new Error(`Wrong PSBT version=${PSBTVersion}`);
|
|
237
|
+
// if (PSBTVersion === 0 && this.inputs.length === 0) {
|
|
238
|
+
// throw new Error(
|
|
239
|
+
// 'PSBT version=0 export for transaction without inputs disabled, please use version=2. Please check `toPSBT` method for explanation.'
|
|
240
|
+
// );
|
|
241
|
+
// }
|
|
234
242
|
const inputs = this.inputs.map((i) => psbt.cleanPSBTFields(PSBTVersion, psbt.PSBTInput, i));
|
|
235
243
|
for (const inp of inputs) {
|
|
236
244
|
// Don't serialize empty fields
|
|
@@ -244,7 +252,21 @@ class Transaction {
|
|
|
244
252
|
const outputs = this.outputs.map((i) => psbt.cleanPSBTFields(PSBTVersion, psbt.PSBTOutput, i));
|
|
245
253
|
const global = { ...this.global };
|
|
246
254
|
if (PSBTVersion === 0) {
|
|
247
|
-
|
|
255
|
+
/*
|
|
256
|
+
- Bitcoin raw transaction expects to have at least 1 input because it uses case with zero inputs as marker for SegWit
|
|
257
|
+
- this means we cannot serialize raw tx with zero inputs since it will be parsed as SegWit tx
|
|
258
|
+
- Parsing of PSBTv0 depends on unsignedTx (it looks for input count here)
|
|
259
|
+
- BIP-174 requires old serialization format (without witnesses) inside global, which solves this
|
|
260
|
+
*/
|
|
261
|
+
global.unsignedTx = script_js_2.RawOldTx.decode(script_js_2.RawOldTx.encode({
|
|
262
|
+
version: this.version,
|
|
263
|
+
lockTime: this.lockTime,
|
|
264
|
+
inputs: this.inputs.map(inputBeforeSign).map((i) => ({
|
|
265
|
+
...i,
|
|
266
|
+
finalScriptSig: P.EMPTY,
|
|
267
|
+
})),
|
|
268
|
+
outputs: this.outputs.map(outputBeforeSign),
|
|
269
|
+
}));
|
|
248
270
|
delete global.fallbackLocktime;
|
|
249
271
|
delete global.txVersion;
|
|
250
272
|
}
|
|
@@ -390,7 +412,7 @@ class Transaction {
|
|
|
390
412
|
for (const i of this.inputs) {
|
|
391
413
|
out += 160 + 4 * script_js_1.VarBytes.encode(i.finalScriptSig || P.EMPTY).length;
|
|
392
414
|
if (this.hasWitnesses && i.finalScriptWitness)
|
|
393
|
-
out +=
|
|
415
|
+
out += script_js_2.RawWitness.encode(i.finalScriptWitness).length;
|
|
394
416
|
}
|
|
395
417
|
return out;
|
|
396
418
|
}
|
|
@@ -398,7 +420,7 @@ class Transaction {
|
|
|
398
420
|
return (0, utxo_js_1.toVsize)(this.weight);
|
|
399
421
|
}
|
|
400
422
|
toBytes(withScriptSig = false, withWitness = false) {
|
|
401
|
-
return
|
|
423
|
+
return script_js_2.RawTx.encode({
|
|
402
424
|
version: this.version,
|
|
403
425
|
lockTime: this.lockTime,
|
|
404
426
|
inputs: this.inputs.map(inputBeforeSign).map((i) => ({
|
|
@@ -464,6 +486,12 @@ class Transaction {
|
|
|
464
486
|
this.checkOutputIdx(idx);
|
|
465
487
|
return cloneDeep(this.outputs[idx]);
|
|
466
488
|
}
|
|
489
|
+
getOutputAddress(idx, network = utils_js_1.NETWORK) {
|
|
490
|
+
const out = this.getOutput(idx);
|
|
491
|
+
if (!out.script)
|
|
492
|
+
return;
|
|
493
|
+
return (0, payment_js_1.Address)(network).encode(payment_js_1.OutScript.decode(out.script));
|
|
494
|
+
}
|
|
467
495
|
get outputsLength() {
|
|
468
496
|
return this.outputs.length;
|
|
469
497
|
}
|
|
@@ -472,7 +500,7 @@ class Transaction {
|
|
|
472
500
|
if (amount === undefined)
|
|
473
501
|
amount = cur?.amount;
|
|
474
502
|
if (typeof amount !== 'bigint')
|
|
475
|
-
throw new Error(
|
|
503
|
+
throw new Error(`Wrong amount type, should be of type bigint in sats, but got ${amount} of type ${typeof amount}`);
|
|
476
504
|
if (typeof script === 'string')
|
|
477
505
|
script = base_1.hex.decode(script);
|
|
478
506
|
if (script === undefined)
|
|
@@ -555,7 +583,7 @@ class Transaction {
|
|
|
555
583
|
else if (isSingle) {
|
|
556
584
|
outputs = outputs.slice(0, idx).fill(EMPTY_OUTPUT).concat([outputs[idx]]);
|
|
557
585
|
}
|
|
558
|
-
const tmpTx =
|
|
586
|
+
const tmpTx = script_js_2.RawTx.encode({
|
|
559
587
|
lockTime: this.lockTime,
|
|
560
588
|
version: this.version,
|
|
561
589
|
segwitFlag: false,
|
|
@@ -576,10 +604,10 @@ class Transaction {
|
|
|
576
604
|
if (!isAny && !isSingle && !isNone)
|
|
577
605
|
sequenceHash = u.sha256x2(...inputs.map((i) => P.U32LE.encode(i.sequence)));
|
|
578
606
|
if (!isSingle && !isNone) {
|
|
579
|
-
outputHash = u.sha256x2(...outputs.map(
|
|
607
|
+
outputHash = u.sha256x2(...outputs.map(script_js_2.RawOutput.encode));
|
|
580
608
|
}
|
|
581
609
|
else if (isSingle && idx < outputs.length)
|
|
582
|
-
outputHash = u.sha256x2(
|
|
610
|
+
outputHash = u.sha256x2(script_js_2.RawOutput.encode(outputs[idx]));
|
|
583
611
|
const input = inputs[idx];
|
|
584
612
|
return u.sha256x2(P.I32LE.encode(this.version), inputHash, sequenceHash, P.bytes(32, true).encode(input.txid), P.U32LE.encode(input.index), script_js_1.VarBytes.encode(prevOutScript), P.U64LE.encode(amount), P.U32LE.encode(input.sequence), outputHash, P.U32LE.encode(this.lockTime), P.U32LE.encode(hashType));
|
|
585
613
|
}
|
|
@@ -607,7 +635,7 @@ class Transaction {
|
|
|
607
635
|
].map((i) => u.sha256((0, utils_js_1.concatBytes)(...i))));
|
|
608
636
|
}
|
|
609
637
|
if (outType === SignatureHash.ALL) {
|
|
610
|
-
out.push(u.sha256((0, utils_js_1.concatBytes)(...outputs.map(
|
|
638
|
+
out.push(u.sha256((0, utils_js_1.concatBytes)(...outputs.map(script_js_2.RawOutput.encode))));
|
|
611
639
|
}
|
|
612
640
|
const spendType = (annex ? 1 : 0) | (leafScript ? 2 : 0);
|
|
613
641
|
out.push(new Uint8Array([spendType]));
|
|
@@ -620,7 +648,7 @@ class Transaction {
|
|
|
620
648
|
if (spendType & 1)
|
|
621
649
|
out.push(u.sha256(script_js_1.VarBytes.encode(annex || P.EMPTY)));
|
|
622
650
|
if (outType === SignatureHash.SINGLE)
|
|
623
|
-
out.push(idx < outputs.length ? u.sha256(
|
|
651
|
+
out.push(idx < outputs.length ? u.sha256(script_js_2.RawOutput.encode(outputs[idx])) : EMPTY32);
|
|
624
652
|
if (leafScript)
|
|
625
653
|
out.push((0, payment_js_1.tapLeafHash)(leafScript, leafVer), P.U8.encode(0), P.I32LE.encode(codeSeparator));
|
|
626
654
|
return u.tagSchnorr('TapSighash', ...out);
|
|
@@ -676,8 +704,6 @@ class Transaction {
|
|
|
676
704
|
// Taproot
|
|
677
705
|
const prevOut = (0, utxo_js_1.getPrevOut)(input);
|
|
678
706
|
if (inputType.txType === 'taproot') {
|
|
679
|
-
if (input.tapBip32Derivation)
|
|
680
|
-
throw new Error('tapBip32Derivation unsupported');
|
|
681
707
|
const prevOuts = this.inputs.map(utxo_js_1.getPrevOut);
|
|
682
708
|
const prevOutScript = prevOuts.map((i) => i.script);
|
|
683
709
|
const amount = prevOuts.map((i) => i.amount);
|
|
@@ -969,8 +995,10 @@ class Transaction {
|
|
|
969
995
|
throw new Error(`Transaction/combine: different ${k} length this=${this[k].length} other=${other[k].length}`);
|
|
970
996
|
}
|
|
971
997
|
}
|
|
972
|
-
const thisUnsigned = this.global.unsignedTx ?
|
|
973
|
-
const otherUnsigned = other.global.unsignedTx
|
|
998
|
+
const thisUnsigned = this.global.unsignedTx ? script_js_2.RawOldTx.encode(this.global.unsignedTx) : P.EMPTY;
|
|
999
|
+
const otherUnsigned = other.global.unsignedTx
|
|
1000
|
+
? script_js_2.RawOldTx.encode(other.global.unsignedTx)
|
|
1001
|
+
: P.EMPTY;
|
|
974
1002
|
if (!(0, utils_js_1.equalBytes)(thisUnsigned, otherUnsigned))
|
|
975
1003
|
throw new Error(`Transaction/combine: different unsigned tx`);
|
|
976
1004
|
this.global = psbt.mergeKeyMap(psbt.PSBTGlobal, this.global, other.global);
|
|
@@ -994,7 +1022,6 @@ function PSBTCombine(psbts) {
|
|
|
994
1022
|
tx.combine(Transaction.fromPSBT(psbts[i]));
|
|
995
1023
|
return tx.toPSBT();
|
|
996
1024
|
}
|
|
997
|
-
exports.PSBTCombine = PSBTCombine;
|
|
998
1025
|
// Copy-pasted from bip32 derive, maybe do something like 'bip32.parsePath'?
|
|
999
1026
|
const HARDENED_OFFSET = 0x80000000;
|
|
1000
1027
|
function bip32Path(path) {
|
|
@@ -1018,5 +1045,4 @@ function bip32Path(path) {
|
|
|
1018
1045
|
}
|
|
1019
1046
|
return out;
|
|
1020
1047
|
}
|
|
1021
|
-
exports.bip32Path = bip32Path;
|
|
1022
1048
|
//# sourceMappingURL=transaction.js.map
|