@leather.io/bitcoin 0.18.0 → 0.19.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/.turbo/turbo-build.log +6 -6
- package/CHANGELOG.md +27 -0
- package/dist/index.d.ts +101 -29
- package/dist/index.js +178 -0
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/bitcoin.utils.ts +8 -0
- package/src/index.ts +6 -0
- package/src/psbt/psbt-details.ts +60 -0
- package/src/psbt/psbt-inputs.ts +71 -0
- package/src/psbt/psbt-outputs.ts +49 -0
- package/src/psbt/psbt-totals.ts +58 -0
- package/src/psbt/utils.ts +25 -0
- package/src/transactions/generate-unsigned-transaction.spec.ts +7 -0
- package/src/transactions/generate-unsigned-transaction.ts +4 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @leather.io/bitcoin@0.
|
|
2
|
+
> @leather.io/bitcoin@0.19.0 build /home/runner/work/mono/mono/packages/bitcoin
|
|
3
3
|
> tsup
|
|
4
4
|
|
|
5
5
|
CLI Building entry: src/index.ts
|
|
@@ -8,9 +8,9 @@ CLI tsup v8.1.0
|
|
|
8
8
|
CLI Using tsup config: /home/runner/work/mono/mono/packages/bitcoin/tsup.config.ts
|
|
9
9
|
CLI Target: es2022
|
|
10
10
|
ESM Build start
|
|
11
|
-
ESM dist/index.js
|
|
12
|
-
ESM dist/index.js.map
|
|
13
|
-
ESM ⚡️ Build success in
|
|
11
|
+
ESM dist/index.js 49.89 KB
|
|
12
|
+
ESM dist/index.js.map 97.56 KB
|
|
13
|
+
ESM ⚡️ Build success in 61ms
|
|
14
14
|
DTS Build start
|
|
15
|
-
DTS ⚡️ Build success in
|
|
16
|
-
DTS dist/index.d.ts
|
|
15
|
+
DTS ⚡️ Build success in 4575ms
|
|
16
|
+
DTS dist/index.d.ts 23.04 KB
|
package/CHANGELOG.md
CHANGED
|
@@ -310,6 +310,33 @@
|
|
|
310
310
|
* devDependencies
|
|
311
311
|
* @leather.io/rpc bumped to 2.1.20
|
|
312
312
|
|
|
313
|
+
### Dependencies
|
|
314
|
+
|
|
315
|
+
* The following workspace dependencies were updated
|
|
316
|
+
* dependencies
|
|
317
|
+
* @leather.io/constants bumped to 0.13.7
|
|
318
|
+
* @leather.io/crypto bumped to 1.6.16
|
|
319
|
+
* @leather.io/models bumped to 0.24.0
|
|
320
|
+
* @leather.io/utils bumped to 0.21.0
|
|
321
|
+
* devDependencies
|
|
322
|
+
* @leather.io/rpc bumped to 2.1.22
|
|
323
|
+
|
|
324
|
+
## [0.19.0](https://github.com/leather-io/mono/compare/@leather.io/bitcoin-v0.18.1...@leather.io/bitcoin-v0.19.0) (2024-12-04)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
### Features
|
|
328
|
+
|
|
329
|
+
* add psbt functionality ([6b676a9](https://github.com/leather-io/mono/commit/6b676a971fbd7497e6c285a818374f13745b032c))
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
### Dependencies
|
|
333
|
+
|
|
334
|
+
* The following workspace dependencies were updated
|
|
335
|
+
* dependencies
|
|
336
|
+
* @leather.io/constants bumped to 0.14.0
|
|
337
|
+
* @leather.io/crypto bumped to 1.6.17
|
|
338
|
+
* @leather.io/utils bumped to 0.21.1
|
|
339
|
+
|
|
313
340
|
## [0.18.0](https://github.com/leather-io/mono/compare/@leather.io/bitcoin-v0.17.0...@leather.io/bitcoin-v0.18.0) (2024-11-29)
|
|
314
341
|
|
|
315
342
|
|
package/dist/index.d.ts
CHANGED
|
@@ -2,14 +2,14 @@ import * as ecpair from 'ecpair';
|
|
|
2
2
|
import * as bitcoin from 'bitcoinjs-lib';
|
|
3
3
|
import * as btc from '@scure/btc-signer';
|
|
4
4
|
import * as _leather_io_models from '@leather.io/models';
|
|
5
|
-
import { BitcoinNetworkModes, Money, AverageBitcoinFeeRates, NetworkModes } from '@leather.io/models';
|
|
5
|
+
import { BitcoinNetworkModes, Money, AverageBitcoinFeeRates, NetworkModes, Inscription } from '@leather.io/models';
|
|
6
6
|
import BigNumber from 'bignumber.js';
|
|
7
7
|
import { HDKey, Versions } from '@scure/bip32';
|
|
8
8
|
import * as _scure_btc_signer_payment from '@scure/btc-signer/payment';
|
|
9
9
|
import { P2Ret, P2TROut } from '@scure/btc-signer/payment';
|
|
10
10
|
import { SigHash } from '@scure/btc-signer/transaction';
|
|
11
11
|
import { PaymentTypes, SignatureHash } from '@leather.io/rpc';
|
|
12
|
-
import { TransactionInput, TransactionOutput } from '@scure/btc-signer/psbt';
|
|
12
|
+
import { TransactionInput, TransactionOutput, RawPSBTV0 } from '@scure/btc-signer/psbt';
|
|
13
13
|
import { deriveBip39SeedFromMnemonic, deriveRootBip32Keychain } from '@leather.io/crypto';
|
|
14
14
|
|
|
15
15
|
declare function ecPairFromPrivateKey(key: Uint8Array): ecpair.ECPairInterface;
|
|
@@ -170,32 +170,6 @@ interface BtcSignerNetwork {
|
|
|
170
170
|
declare function getBtcSignerLibNetworkConfigByMode(network: BitcoinNetworkModes): BtcSignerNetwork;
|
|
171
171
|
declare function getBitcoinJsLibNetworkConfigByMode(network: BitcoinNetworkModes): bitcoin.networks.Network;
|
|
172
172
|
|
|
173
|
-
interface GenerateBitcoinUnsignedTransactionArgs {
|
|
174
|
-
feeRate: number;
|
|
175
|
-
isSendingMax?: boolean;
|
|
176
|
-
payerAddress: string;
|
|
177
|
-
payerPublicKey: string;
|
|
178
|
-
network: BtcSignerNetwork;
|
|
179
|
-
recipients: CoinSelectionRecipient[];
|
|
180
|
-
utxos: CoinSelectionUtxo[];
|
|
181
|
-
}
|
|
182
|
-
declare function generateBitcoinUnsignedTransactionNativeSegwit({ feeRate, isSendingMax, payerAddress, payerPublicKey, network, recipients, utxos, }: GenerateBitcoinUnsignedTransactionArgs): Promise<{
|
|
183
|
-
tx: btc.Transaction;
|
|
184
|
-
hex: string;
|
|
185
|
-
psbt: Uint8Array;
|
|
186
|
-
inputs: CoinSelectionUtxo[];
|
|
187
|
-
fee: _leather_io_models.Money;
|
|
188
|
-
} | null>;
|
|
189
|
-
|
|
190
|
-
declare enum BitcoinErrorMessage {
|
|
191
|
-
InsufficientFunds = "Insufficient funds",
|
|
192
|
-
NoInputsToSign = "No inputs to sign",
|
|
193
|
-
NoOutputsToSign = "No outputs to sign"
|
|
194
|
-
}
|
|
195
|
-
declare class BitcoinError extends Error {
|
|
196
|
-
constructor(message: string);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
173
|
interface BitcoinAccount {
|
|
200
174
|
type: PaymentTypes;
|
|
201
175
|
derivationPath: string;
|
|
@@ -273,6 +247,7 @@ declare function getPsbtTxInputs(psbtTx: btc.Transaction): TransactionInput[];
|
|
|
273
247
|
declare function getPsbtTxOutputs(psbtTx: btc.Transaction): TransactionOutput[];
|
|
274
248
|
declare function inferNetworkFromAddress(address: string): BitcoinNetworkModes;
|
|
275
249
|
declare function inferPaymentTypeFromAddress(address: string): SupportedPaymentType;
|
|
250
|
+
declare function getBitcoinInputValue(input: TransactionInput): number;
|
|
276
251
|
|
|
277
252
|
type AllowedSighashTypes = SignatureHash | SigHash;
|
|
278
253
|
interface BitcoinAccountKeychain {
|
|
@@ -378,6 +353,33 @@ declare function serializeKeyOrigin({ fingerprint, path }: BtcSignerDerivationPa
|
|
|
378
353
|
*/
|
|
379
354
|
declare function extractRequiredKeyOrigins(derivation: BtcSignerBip32Derivation[]): string[];
|
|
380
355
|
|
|
356
|
+
interface GenerateBitcoinUnsignedTransactionArgs {
|
|
357
|
+
feeRate: number;
|
|
358
|
+
isSendingMax?: boolean;
|
|
359
|
+
payerAddress: string;
|
|
360
|
+
payerPublicKey: string;
|
|
361
|
+
bip32Derivation: BtcSignerDefaultBip32Derivation[];
|
|
362
|
+
network: BtcSignerNetwork;
|
|
363
|
+
recipients: CoinSelectionRecipient[];
|
|
364
|
+
utxos: CoinSelectionUtxo[];
|
|
365
|
+
}
|
|
366
|
+
declare function generateBitcoinUnsignedTransactionNativeSegwit({ feeRate, isSendingMax, payerAddress, payerPublicKey, bip32Derivation, network, recipients, utxos, }: GenerateBitcoinUnsignedTransactionArgs): Promise<{
|
|
367
|
+
tx: btc.Transaction;
|
|
368
|
+
hex: string;
|
|
369
|
+
psbt: Uint8Array;
|
|
370
|
+
inputs: CoinSelectionUtxo[];
|
|
371
|
+
fee: _leather_io_models.Money;
|
|
372
|
+
} | null>;
|
|
373
|
+
|
|
374
|
+
declare enum BitcoinErrorMessage {
|
|
375
|
+
InsufficientFunds = "Insufficient funds",
|
|
376
|
+
NoInputsToSign = "No inputs to sign",
|
|
377
|
+
NoOutputsToSign = "No outputs to sign"
|
|
378
|
+
}
|
|
379
|
+
declare class BitcoinError extends Error {
|
|
380
|
+
constructor(message: string);
|
|
381
|
+
}
|
|
382
|
+
|
|
381
383
|
declare function makeTaprootAccountDerivationPath(network: BitcoinNetworkModes, accountIndex: number): string;
|
|
382
384
|
/** @deprecated Use makeTaprootAccountDerivationPath */
|
|
383
385
|
declare const getTaprootAccountDerivationPath: typeof makeTaprootAccountDerivationPath;
|
|
@@ -445,4 +447,74 @@ declare function lookupDerivationByAddress(args: LookUpDerivationByAddressArgs):
|
|
|
445
447
|
readonly path?: undefined;
|
|
446
448
|
};
|
|
447
449
|
|
|
448
|
-
|
|
450
|
+
interface PsbtInput {
|
|
451
|
+
address: string;
|
|
452
|
+
index?: number;
|
|
453
|
+
inscription?: Inscription;
|
|
454
|
+
isMutable: boolean;
|
|
455
|
+
toSign: boolean;
|
|
456
|
+
txid: string;
|
|
457
|
+
value: number;
|
|
458
|
+
bip32Derivation: TransactionInput['bip32Derivation'];
|
|
459
|
+
tapBip32Derivation: TransactionInput['tapBip32Derivation'];
|
|
460
|
+
}
|
|
461
|
+
interface GetParsedInputsArgs {
|
|
462
|
+
inputs: TransactionInput[];
|
|
463
|
+
indexesToSign?: number[];
|
|
464
|
+
networkMode: BitcoinNetworkModes;
|
|
465
|
+
psbtAddresses: string[];
|
|
466
|
+
}
|
|
467
|
+
interface GetParsedInputsResponse {
|
|
468
|
+
isPsbtMutable: boolean;
|
|
469
|
+
parsedInputs: PsbtInput[];
|
|
470
|
+
}
|
|
471
|
+
declare function getParsedInputs({ inputs, indexesToSign, networkMode, psbtAddresses, }: GetParsedInputsArgs): GetParsedInputsResponse;
|
|
472
|
+
|
|
473
|
+
interface PsbtOutput {
|
|
474
|
+
address: string;
|
|
475
|
+
isMutable: boolean;
|
|
476
|
+
toSign: boolean;
|
|
477
|
+
value: number;
|
|
478
|
+
}
|
|
479
|
+
interface GetParsedOutputsArgs {
|
|
480
|
+
isPsbtMutable: boolean;
|
|
481
|
+
outputs: TransactionOutput[];
|
|
482
|
+
networkMode: BitcoinNetworkModes;
|
|
483
|
+
psbtAddresses: string[];
|
|
484
|
+
}
|
|
485
|
+
declare function getParsedOutputs({ isPsbtMutable, outputs, networkMode, psbtAddresses, }: GetParsedOutputsArgs): PsbtOutput[];
|
|
486
|
+
|
|
487
|
+
interface GetPsbtTotalsProps {
|
|
488
|
+
psbtAddresses: string[];
|
|
489
|
+
parsedInputs: PsbtInput[];
|
|
490
|
+
parsedOutputs: PsbtOutput[];
|
|
491
|
+
}
|
|
492
|
+
declare function getPsbtTotals({ psbtAddresses, parsedInputs, parsedOutputs }: GetPsbtTotalsProps): {
|
|
493
|
+
inputsTotalNativeSegwit: _leather_io_models.Money;
|
|
494
|
+
inputsTotalTaproot: _leather_io_models.Money;
|
|
495
|
+
outputsTotalNativeSegwit: _leather_io_models.Money;
|
|
496
|
+
outputsTotalTaproot: _leather_io_models.Money;
|
|
497
|
+
psbtInputsTotal: _leather_io_models.Money;
|
|
498
|
+
psbtOutputsTotal: _leather_io_models.Money;
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
interface GetPsbtDetailsArgs {
|
|
502
|
+
psbtHex: string;
|
|
503
|
+
psbtAddresses: string[];
|
|
504
|
+
networkMode: BitcoinNetworkModes;
|
|
505
|
+
indexesToSign?: number[];
|
|
506
|
+
}
|
|
507
|
+
declare function getPsbtDetails({ psbtHex, networkMode, indexesToSign, psbtAddresses, }: GetPsbtDetailsArgs): {
|
|
508
|
+
addressNativeSegwitTotal: _leather_io_models.Money;
|
|
509
|
+
addressTaprootTotal: _leather_io_models.Money;
|
|
510
|
+
fee: _leather_io_models.Money;
|
|
511
|
+
isPsbtMutable: boolean;
|
|
512
|
+
psbtInputs: PsbtInput[];
|
|
513
|
+
psbtOutputs: PsbtOutput[];
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
type RawPsbt = ReturnType<typeof RawPSBTV0.decode>;
|
|
517
|
+
declare function getPsbtAsTransaction(psbt: string | Uint8Array): btc.Transaction;
|
|
518
|
+
declare function getRawPsbt(psbt: string | Uint8Array): ReturnType<typeof RawPSBTV0.decode>;
|
|
519
|
+
|
|
520
|
+
export { type AllowedSighashTypes, type BitcoinAccount, type BitcoinAccountKeychain, BitcoinError, BitcoinErrorMessage, type BitcoinFees, type BitcoinNativeSegwitPayer, type BitcoinPayer, type BitcoinPayerBase, type BitcoinPayerInfo, type BitcoinSigner, type BitcoinTaprootPayer, type BtcSignerDefaultBip32Derivation, type BtcSignerLibPaymentTypeIdentifers, type BtcSignerNetwork, type BtcSignerTapBip32Derivation, type CoinSelectionOutput, type CoinSelectionRecipient, type CoinSelectionUtxo, type DetermineUtxosForSpendArgs, type GenerateBitcoinUnsignedTransactionArgs, type GetBitcoinFeesArgs, type PaymentTypeMap, type PsbtInput, type PsbtOutput, type RawPsbt, type SupportedPaymentType, type SupportedPaymentTypeMap, type WithDerivePayer, bip322TransactionToSignValues, bitcoinNetworkModeToCoreNetworkMode, bitcoinNetworkToCoreNetworkMap, btcSignerLibPaymentTypeToPaymentTypeMap, calculateMaxBitcoinSpend, coinTypeMap, createNativeSegwitBitcoinJsSigner, createTaprootBitcoinJsSigner, createToSpendTx, createWalletIdDecoratedPath, decodeBitcoinTx, decodeCompressedWifPrivateKey, deriveAddressIndexKeychainFromAccount, deriveAddressIndexZeroFromAccount, deriveBitcoinPayerFromAccount, deriveBtcBip49SeedFromMnemonic, deriveNativeSegwitAccountFromRootKeychain, deriveNativeSegwitReceiveAddressIndexZero, deriveRootBtcKeychain, deriveTaprootAccount, deriveTaprootReceiveAddressIndexZero, determineUtxosForSpend, determineUtxosForSpendAll, ecPairFromPrivateKey, ecdsaPublicKeyLength, ecdsaPublicKeyToSchnorr, encodeMessageWitnessData, extractExtendedPublicKeyFromPolicy, extractRequiredKeyOrigins, filterUneconomicalUtxos, generateBitcoinUnsignedTransactionNativeSegwit, getAddressFromOutScript, getBitcoinCoinTypeIndexByNetwork, getBitcoinFees, getBitcoinInputAddress, getBitcoinInputValue, getBitcoinJsLibNetworkConfigByMode, getBitcoinTransactionFee, getBtcSignerLibNetworkConfigByMode, getHdKeyVersionsFromNetwork, getInputPaymentType, getNativeSegwitAccountDerivationPath, getNativeSegwitAddress, getNativeSegwitAddressIndexDerivationPath, getNativeSegwitPaymentFromAddressIndex, getParsedInputs, getParsedOutputs, getPsbtAsTransaction, getPsbtDetails, getPsbtTotals, getPsbtTxInputs, getPsbtTxOutputs, getRawPsbt, getSizeInfo, getSpendableAmount, getTaprootAccountDerivationPath, getTaprootAddress, getTaprootAddressIndexDerivationPath, getTaprootPayment, getTaprootPaymentFromAddressIndex, getUtxoTotal, hashBip322Message, inferNetworkFromAddress, inferNetworkFromPath, inferPaymentTypeFromAddress, inferPaymentTypeFromPath, initBitcoinAccount, initializeBitcoinAccountKeychainFromDescriptor, isBtcSignerLibPaymentType, isSupportedMessageSigningPaymentType, lookUpLedgerKeysByPath, lookupDerivationByAddress, makeNativeSegwitAccountDerivationPath, makeNativeSegwitAddressIndexDerivationPath, makePayToScriptHashAddress, makePayToScriptHashAddressBytes, makePayToScriptHashKeyHash, makeTaprootAccountDerivationPath, makeTaprootAddressIndexDerivationPath, mnemonicToRootNode, parseKnownPaymentType, payToScriptHashTestnetPrefix, payerToBip32Derivation, payerToTapBip32Derivation, paymentTypeMap, publicKeyToPayToScriptHashAddress, serializeKeyOrigin, signBip322MessageSimple, toXOnly, tweakSigner, whenBitcoinNetwork, whenPaymentType, whenSupportedPaymentType };
|
package/dist/index.js
CHANGED
|
@@ -353,6 +353,12 @@ function inferPaymentTypeFromAddress(address2) {
|
|
|
353
353
|
return "p2tr";
|
|
354
354
|
throw new Error("Unable to infer payment type from address");
|
|
355
355
|
}
|
|
356
|
+
function getBitcoinInputValue(input) {
|
|
357
|
+
if (isDefined(input.witnessUtxo)) return Number(input.witnessUtxo.amount);
|
|
358
|
+
if (isDefined(input.nonWitnessUtxo) && isDefined(input.index))
|
|
359
|
+
return Number(input.nonWitnessUtxo.outputs[input.index]?.amount);
|
|
360
|
+
return 0;
|
|
361
|
+
}
|
|
356
362
|
|
|
357
363
|
// src/bip322/bip322-utils.ts
|
|
358
364
|
var bip322MessageTag = "BIP0322-signed-message";
|
|
@@ -964,6 +970,7 @@ async function generateBitcoinUnsignedTransactionNativeSegwit({
|
|
|
964
970
|
isSendingMax,
|
|
965
971
|
payerAddress,
|
|
966
972
|
payerPublicKey,
|
|
973
|
+
bip32Derivation,
|
|
967
974
|
network,
|
|
968
975
|
recipients,
|
|
969
976
|
utxos
|
|
@@ -980,6 +987,7 @@ async function generateBitcoinUnsignedTransactionNativeSegwit({
|
|
|
980
987
|
txid: input.txid,
|
|
981
988
|
index: input.vout,
|
|
982
989
|
sequence: 0,
|
|
990
|
+
bip32Derivation,
|
|
983
991
|
witnessUtxo: {
|
|
984
992
|
// script = 0014 + pubKeyHash
|
|
985
993
|
script: p2wpkh3.script,
|
|
@@ -1173,6 +1181,169 @@ function lookupDerivationByAddress(args) {
|
|
|
1173
1181
|
return { status: "failure" };
|
|
1174
1182
|
};
|
|
1175
1183
|
}
|
|
1184
|
+
|
|
1185
|
+
// src/psbt/psbt-totals.ts
|
|
1186
|
+
import { createMoney as createMoney3, sumNumbers as sumNumbers2 } from "@leather.io/utils";
|
|
1187
|
+
function calculateAddressInputsTotal(addresses, inputs) {
|
|
1188
|
+
const sumsByAddress = addresses.map(
|
|
1189
|
+
(address2) => inputs.filter((input) => input.address === address2).map((input) => input.value).reduce((acc, curVal) => acc + curVal, 0)
|
|
1190
|
+
);
|
|
1191
|
+
return createMoney3(sumNumbers2(sumsByAddress), "BTC");
|
|
1192
|
+
}
|
|
1193
|
+
function calculateAddressOutputsTotal(addresses, outputs) {
|
|
1194
|
+
const sumsByAddress = addresses.map(
|
|
1195
|
+
(address2) => outputs.filter((output) => output.address === address2).map((output) => Number(output.value)).reduce((acc, curVal) => acc + curVal, 0)
|
|
1196
|
+
);
|
|
1197
|
+
return createMoney3(sumNumbers2(sumsByAddress), "BTC");
|
|
1198
|
+
}
|
|
1199
|
+
function calculatePsbtInputsTotal(inputs) {
|
|
1200
|
+
return createMoney3(sumNumbers2(inputs.map((input) => input.value)), "BTC");
|
|
1201
|
+
}
|
|
1202
|
+
function calculatePsbtOutputsTotal(outputs) {
|
|
1203
|
+
return createMoney3(sumNumbers2(outputs.map((output) => output.value)), "BTC");
|
|
1204
|
+
}
|
|
1205
|
+
function getPsbtTotals({ psbtAddresses, parsedInputs, parsedOutputs }) {
|
|
1206
|
+
const nativeSegwitAddresses = psbtAddresses.filter(
|
|
1207
|
+
(addr) => inferPaymentTypeFromAddress(addr) === "p2wpkh"
|
|
1208
|
+
);
|
|
1209
|
+
const taprootAddresses = psbtAddresses.filter(
|
|
1210
|
+
(addr) => inferPaymentTypeFromAddress(addr) === "p2tr"
|
|
1211
|
+
);
|
|
1212
|
+
return {
|
|
1213
|
+
inputsTotalNativeSegwit: calculateAddressInputsTotal(nativeSegwitAddresses, parsedInputs),
|
|
1214
|
+
inputsTotalTaproot: calculateAddressInputsTotal(taprootAddresses, parsedInputs),
|
|
1215
|
+
outputsTotalNativeSegwit: calculateAddressOutputsTotal(nativeSegwitAddresses, parsedOutputs),
|
|
1216
|
+
outputsTotalTaproot: calculateAddressOutputsTotal(taprootAddresses, parsedOutputs),
|
|
1217
|
+
psbtInputsTotal: calculatePsbtInputsTotal(parsedInputs),
|
|
1218
|
+
psbtOutputsTotal: calculatePsbtOutputsTotal(parsedOutputs)
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
// src/psbt/psbt-inputs.ts
|
|
1223
|
+
import { bytesToHex } from "@stacks/common";
|
|
1224
|
+
import { isDefined as isDefined2, isUndefined } from "@leather.io/utils";
|
|
1225
|
+
function getParsedInputs({
|
|
1226
|
+
inputs,
|
|
1227
|
+
indexesToSign,
|
|
1228
|
+
networkMode,
|
|
1229
|
+
psbtAddresses
|
|
1230
|
+
}) {
|
|
1231
|
+
const bitcoinNetwork = getBtcSignerLibNetworkConfigByMode(networkMode);
|
|
1232
|
+
const signAll = isUndefined(indexesToSign);
|
|
1233
|
+
const psbtInputs = inputs.map((input, i) => {
|
|
1234
|
+
const inputAddress = isDefined2(input.index) ? getBitcoinInputAddress(input, bitcoinNetwork) : "";
|
|
1235
|
+
const isCurrentAddress = psbtAddresses.includes(inputAddress);
|
|
1236
|
+
const canChange = isCurrentAddress && !(!input.sighashType || input.sighashType === 0 || input.sighashType === 1);
|
|
1237
|
+
const toSignAll = isCurrentAddress && signAll;
|
|
1238
|
+
const toSignIndex = isCurrentAddress && !signAll && indexesToSign.includes(i);
|
|
1239
|
+
return {
|
|
1240
|
+
address: inputAddress,
|
|
1241
|
+
index: input.index,
|
|
1242
|
+
bip32Derivation: input.bip32Derivation,
|
|
1243
|
+
tapBip32Derivation: input.tapBip32Derivation,
|
|
1244
|
+
// inscription: inscriptions[i],
|
|
1245
|
+
isMutable: canChange,
|
|
1246
|
+
toSign: toSignAll || toSignIndex,
|
|
1247
|
+
txid: input.txid ? bytesToHex(input.txid) : "",
|
|
1248
|
+
value: isDefined2(input.index) ? getBitcoinInputValue(input) : 0
|
|
1249
|
+
};
|
|
1250
|
+
});
|
|
1251
|
+
const isPsbtMutable = psbtInputs.some((input) => input.isMutable);
|
|
1252
|
+
return { isPsbtMutable, parsedInputs: psbtInputs };
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
// src/psbt/psbt-outputs.ts
|
|
1256
|
+
import { isDefined as isDefined3, isUndefined as isUndefined2 } from "@leather.io/utils";
|
|
1257
|
+
function getParsedOutputs({
|
|
1258
|
+
isPsbtMutable,
|
|
1259
|
+
outputs,
|
|
1260
|
+
networkMode,
|
|
1261
|
+
psbtAddresses
|
|
1262
|
+
}) {
|
|
1263
|
+
const bitcoinNetwork = getBtcSignerLibNetworkConfigByMode(networkMode);
|
|
1264
|
+
return outputs.map((output) => {
|
|
1265
|
+
if (isUndefined2(output.script)) {
|
|
1266
|
+
return;
|
|
1267
|
+
}
|
|
1268
|
+
const outputAddress = getAddressFromOutScript(output.script, bitcoinNetwork);
|
|
1269
|
+
const isCurrentAddress = psbtAddresses.includes(outputAddress);
|
|
1270
|
+
return {
|
|
1271
|
+
address: outputAddress,
|
|
1272
|
+
isMutable: isPsbtMutable,
|
|
1273
|
+
toSign: isCurrentAddress,
|
|
1274
|
+
value: Number(output.amount)
|
|
1275
|
+
};
|
|
1276
|
+
}).filter(isDefined3);
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
// src/psbt/psbt-details.ts
|
|
1280
|
+
import { createMoney as createMoney4, subtractMoney } from "@leather.io/utils";
|
|
1281
|
+
|
|
1282
|
+
// src/psbt/utils.ts
|
|
1283
|
+
import { hexToBytes as hexToBytes4 } from "@noble/hashes/utils";
|
|
1284
|
+
import * as btc6 from "@scure/btc-signer";
|
|
1285
|
+
import { RawPSBTV0, RawPSBTV2 } from "@scure/btc-signer/psbt";
|
|
1286
|
+
import { isString as isString2 } from "@leather.io/utils";
|
|
1287
|
+
function getPsbtAsTransaction(psbt) {
|
|
1288
|
+
const bytes = isString2(psbt) ? hexToBytes4(psbt) : psbt;
|
|
1289
|
+
return btc6.Transaction.fromPSBT(bytes);
|
|
1290
|
+
}
|
|
1291
|
+
function getRawPsbt(psbt) {
|
|
1292
|
+
const bytes = isString2(psbt) ? hexToBytes4(psbt) : psbt;
|
|
1293
|
+
try {
|
|
1294
|
+
return RawPSBTV0.decode(bytes);
|
|
1295
|
+
} catch (e1) {
|
|
1296
|
+
try {
|
|
1297
|
+
return RawPSBTV2.decode(bytes);
|
|
1298
|
+
} catch (e2) {
|
|
1299
|
+
throw new Error(`Unable to decode PSBT, ${e1 ?? e2}`);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
// src/psbt/psbt-details.ts
|
|
1305
|
+
function getPsbtDetails({
|
|
1306
|
+
psbtHex,
|
|
1307
|
+
networkMode,
|
|
1308
|
+
indexesToSign,
|
|
1309
|
+
psbtAddresses
|
|
1310
|
+
}) {
|
|
1311
|
+
const tx = getPsbtAsTransaction(psbtHex);
|
|
1312
|
+
const inputs = getPsbtTxInputs(tx);
|
|
1313
|
+
const outputs = getPsbtTxOutputs(tx);
|
|
1314
|
+
const { isPsbtMutable, parsedInputs } = getParsedInputs({
|
|
1315
|
+
inputs,
|
|
1316
|
+
indexesToSign,
|
|
1317
|
+
networkMode,
|
|
1318
|
+
psbtAddresses
|
|
1319
|
+
});
|
|
1320
|
+
const parsedOutputs = getParsedOutputs({ isPsbtMutable, outputs, networkMode, psbtAddresses });
|
|
1321
|
+
const {
|
|
1322
|
+
inputsTotalNativeSegwit,
|
|
1323
|
+
inputsTotalTaproot,
|
|
1324
|
+
outputsTotalNativeSegwit,
|
|
1325
|
+
outputsTotalTaproot,
|
|
1326
|
+
psbtInputsTotal,
|
|
1327
|
+
psbtOutputsTotal
|
|
1328
|
+
} = getPsbtTotals({
|
|
1329
|
+
psbtAddresses,
|
|
1330
|
+
parsedInputs,
|
|
1331
|
+
parsedOutputs
|
|
1332
|
+
});
|
|
1333
|
+
function getFee() {
|
|
1334
|
+
if (psbtInputsTotal.amount.isGreaterThan(psbtOutputsTotal.amount))
|
|
1335
|
+
return subtractMoney(psbtInputsTotal, psbtOutputsTotal);
|
|
1336
|
+
return createMoney4(0, "BTC");
|
|
1337
|
+
}
|
|
1338
|
+
return {
|
|
1339
|
+
addressNativeSegwitTotal: subtractMoney(inputsTotalNativeSegwit, outputsTotalNativeSegwit),
|
|
1340
|
+
addressTaprootTotal: subtractMoney(inputsTotalTaproot, outputsTotalTaproot),
|
|
1341
|
+
fee: getFee(),
|
|
1342
|
+
isPsbtMutable,
|
|
1343
|
+
psbtInputs: parsedInputs,
|
|
1344
|
+
psbtOutputs: parsedOutputs
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1176
1347
|
export {
|
|
1177
1348
|
BitcoinError,
|
|
1178
1349
|
BitcoinErrorMessage,
|
|
@@ -1211,6 +1382,7 @@ export {
|
|
|
1211
1382
|
getBitcoinCoinTypeIndexByNetwork,
|
|
1212
1383
|
getBitcoinFees,
|
|
1213
1384
|
getBitcoinInputAddress,
|
|
1385
|
+
getBitcoinInputValue,
|
|
1214
1386
|
getBitcoinJsLibNetworkConfigByMode,
|
|
1215
1387
|
getBitcoinTransactionFee,
|
|
1216
1388
|
getBtcSignerLibNetworkConfigByMode,
|
|
@@ -1220,8 +1392,14 @@ export {
|
|
|
1220
1392
|
getNativeSegwitAddress,
|
|
1221
1393
|
getNativeSegwitAddressIndexDerivationPath,
|
|
1222
1394
|
getNativeSegwitPaymentFromAddressIndex,
|
|
1395
|
+
getParsedInputs,
|
|
1396
|
+
getParsedOutputs,
|
|
1397
|
+
getPsbtAsTransaction,
|
|
1398
|
+
getPsbtDetails,
|
|
1399
|
+
getPsbtTotals,
|
|
1223
1400
|
getPsbtTxInputs,
|
|
1224
1401
|
getPsbtTxOutputs,
|
|
1402
|
+
getRawPsbt,
|
|
1225
1403
|
getSizeInfo,
|
|
1226
1404
|
getSpendableAmount,
|
|
1227
1405
|
getTaprootAccountDerivationPath,
|