@caravan/psbt 1.3.2 → 1.4.1

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/dist/index.d.ts CHANGED
@@ -371,6 +371,22 @@ declare const addGlobalXpubs: (psbt: Psbt, inputs: PsbtInput[], network: Network
371
371
  * to support a newer API and be more PSBT-native.
372
372
  */
373
373
  declare const validateMultisigPsbtSignature: (raw: string | Buffer, inputIndex: number, inputSignature: Buffer, inputAmount?: string) => boolean | string;
374
+ /***
375
+ * These should be deprecated eventually once we have better typescript support
376
+ * and a more api for handling PSBT saga.
377
+ * They are ports over from the legacy psbt code in caravan/bitcoin
378
+ */
379
+ /**
380
+ * Translates a PSBT into inputs/outputs consumable by supported non-PSBT devices in the
381
+ * `@caravan/wallets` library.
382
+ *
383
+ * FIXME - Have only confirmed this is working for P2SH addresses on Ledger on regtest
384
+ */
385
+ declare function translatePSBT(network: any, addressType: any, psbt: string, signingKeyDetails: any): {
386
+ unchainedInputs: any;
387
+ unchainedOutputs: any;
388
+ bip32Derivations: any;
389
+ } | null;
374
390
 
375
391
  /**
376
392
  * @file This file primarily contains utility functions migrated from the
@@ -419,9 +435,13 @@ interface LegacyOutput {
419
435
  }
420
436
  declare const convertLegacyInput: (input: LegacyInput) => PsbtInput;
421
437
  declare const convertLegacyOutput: (output: LegacyOutput) => PsbtOutput;
438
+ /**
439
+ * Given a string, try to create a Psbt object based on MAGIC (hex or Base64)
440
+ */
441
+ declare function autoLoadPSBT(psbtFromFile: any, options?: any): Psbt | null;
422
442
 
423
443
  declare const PSBT_MAGIC_HEX = "70736274ff";
424
444
  declare const PSBT_MAGIC_B64 = "cHNidP8";
425
445
  declare const PSBT_MAGIC_BYTES: Buffer;
426
446
 
427
- export { LegacyInput, LegacyMultisig, LegacyOutput, PSBT_MAGIC_B64, PSBT_MAGIC_BYTES, PSBT_MAGIC_HEX, PsbtInput, PsbtOutput, PsbtV2, addGlobalXpubs, convertLegacyInput, convertLegacyOutput, getPsbtVersionNumber, getUnsignedMultisigPsbtV0, validateMultisigPsbtSignature };
447
+ export { LegacyInput, LegacyMultisig, LegacyOutput, PSBT_MAGIC_B64, PSBT_MAGIC_BYTES, PSBT_MAGIC_HEX, PsbtInput, PsbtOutput, PsbtV2, addGlobalXpubs, autoLoadPSBT, convertLegacyInput, convertLegacyOutput, getPsbtVersionNumber, getUnsignedMultisigPsbtV0, translatePSBT, validateMultisigPsbtSignature };
package/dist/index.js CHANGED
@@ -35,10 +35,12 @@ __export(src_exports, {
35
35
  PSBT_MAGIC_HEX: () => PSBT_MAGIC_HEX,
36
36
  PsbtV2: () => PsbtV2,
37
37
  addGlobalXpubs: () => addGlobalXpubs,
38
+ autoLoadPSBT: () => autoLoadPSBT,
38
39
  convertLegacyInput: () => convertLegacyInput,
39
40
  convertLegacyOutput: () => convertLegacyOutput,
40
41
  getPsbtVersionNumber: () => getPsbtVersionNumber,
41
42
  getUnsignedMultisigPsbtV0: () => getUnsignedMultisigPsbtV0,
43
+ translatePSBT: () => translatePSBT,
42
44
  validateMultisigPsbtSignature: () => validateMultisigPsbtSignature
43
45
  });
44
46
  module.exports = __toCommonJS(src_exports);
@@ -1197,9 +1199,9 @@ var PsbtV2 = class _PsbtV2 extends PsbtV2Maps {
1197
1199
  };
1198
1200
 
1199
1201
  // src/psbtv0/psbt.ts
1200
- var import_bitcoin3 = require("@caravan/bitcoin");
1201
- var import_bitcoinjs_lib_v62 = require("bitcoinjs-lib-v6");
1202
- var import_address = require("bitcoinjs-lib-v6/src/address");
1202
+ var import_bitcoin4 = require("@caravan/bitcoin");
1203
+ var import_bitcoinjs_lib_v63 = require("bitcoinjs-lib-v6");
1204
+ var import_address = require("bitcoinjs-lib-v6/src/address.js");
1203
1205
 
1204
1206
  // vendor/tiny-secp256k1-asmjs/lib/index.js
1205
1207
  var lib_exports = {};
@@ -93703,7 +93705,114 @@ function verifySchnorr2(h6, Q3, signature) {
93703
93705
 
93704
93706
  // src/psbtv0/psbt.ts
93705
93707
  var bitcoin = __toESM(require("bitcoinjs-lib-v6"));
93708
+ var import_bignumber2 = __toESM(require("bignumber.js"));
93709
+ var import_bufferutils = require("bitcoinjs-lib-v6/src/bufferutils.js");
93710
+
93711
+ // src/psbtv0/utils.ts
93712
+ var import_bitcoin3 = require("@caravan/bitcoin");
93713
+
93714
+ // ../multisig/dist/index.mjs
93715
+ var braidDetailsToWalletConfig = (braidDetails) => {
93716
+ return {
93717
+ network: braidDetails.network,
93718
+ extendedPublicKeys: braidDetails.extendedPublicKeys.map((key) => ({
93719
+ xpub: key.base58String,
93720
+ bip32Path: key.path,
93721
+ xfp: key.rootFingerprint
93722
+ })),
93723
+ quorum: {
93724
+ requiredSigners: braidDetails.requiredSigners,
93725
+ totalSigners: braidDetails.extendedPublicKeys.length
93726
+ },
93727
+ name: `${braidDetails.requiredSigners}-of-${braidDetails.extendedPublicKeys.length} ${braidDetails.addressType} ${braidDetails.network} wallet`,
93728
+ addressType: braidDetails.addressType
93729
+ };
93730
+ };
93731
+
93732
+ // src/psbtv0/utils.ts
93706
93733
  var import_bignumber = __toESM(require("bignumber.js"));
93734
+ var import_bitcoinjs_lib_v62 = require("bitcoinjs-lib-v6");
93735
+ var import_bufio4 = require("bufio");
93736
+ var idToHash = (txid) => {
93737
+ return import_buffer.Buffer.from(txid, "hex").reverse();
93738
+ };
93739
+ function psbtMultisigLock(multisig) {
93740
+ if (!multisig) {
93741
+ return {};
93742
+ }
93743
+ const multisigLock = {};
93744
+ switch ((0, import_bitcoin3.multisigAddressType)(multisig)) {
93745
+ case import_bitcoin3.P2SH:
93746
+ multisigLock.redeemScript = (0, import_bitcoin3.multisigRedeemScript)(multisig).output;
93747
+ break;
93748
+ case import_bitcoin3.P2WSH:
93749
+ multisigLock.witnessScript = (0, import_bitcoin3.multisigWitnessScript)(multisig).output;
93750
+ break;
93751
+ case import_bitcoin3.P2SH_P2WSH:
93752
+ multisigLock.witnessScript = (0, import_bitcoin3.multisigWitnessScript)(multisig).output;
93753
+ multisigLock.redeemScript = (0, import_bitcoin3.multisigRedeemScript)(multisig).output;
93754
+ break;
93755
+ }
93756
+ return multisigLock;
93757
+ }
93758
+ function getBip32Derivation(multisig, index = 0) {
93759
+ if (!multisig) {
93760
+ return;
93761
+ }
93762
+ if (multisig.bip32Derivation) {
93763
+ return multisig.bip32Derivation;
93764
+ }
93765
+ const config = JSON.parse((0, import_bitcoin3.multisigBraidDetails)(multisig));
93766
+ const braid = (0, import_bitcoin3.generateBraid)(
93767
+ config.network,
93768
+ config.addressType,
93769
+ config.extendedPublicKeys,
93770
+ config.requiredSigners,
93771
+ config.index
93772
+ );
93773
+ return (0, import_bitcoin3.generateBip32DerivationByIndex)(braid, index);
93774
+ }
93775
+ var convertLegacyInput = (input) => {
93776
+ return {
93777
+ hash: idToHash(input.txid),
93778
+ index: input.index,
93779
+ transactionHex: input.transactionHex,
93780
+ bip32Derivation: input.multisig.bip32Derivation || getBip32Derivation(input.multisig),
93781
+ ...psbtMultisigLock(input.multisig),
93782
+ spendingWallet: getWalletConfigFromInput(input)
93783
+ };
93784
+ };
93785
+ var convertLegacyOutput = (output) => {
93786
+ return {
93787
+ address: output.address,
93788
+ value: new import_bignumber.default(output.amountSats).toNumber(),
93789
+ bip32Derivation: output.bip32Derivation || getBip32Derivation(output.multisig),
93790
+ witnessScript: output.witnessScript,
93791
+ redeemScript: output.redeemScript
93792
+ };
93793
+ };
93794
+ var getWalletConfigFromInput = (input) => {
93795
+ return braidDetailsToWalletConfig(JSON.parse(input.multisig.braidDetails));
93796
+ };
93797
+ function autoLoadPSBT(psbtFromFile, options) {
93798
+ let psbtBuff;
93799
+ try {
93800
+ psbtBuff = bufferize(psbtFromFile);
93801
+ } catch (e8) {
93802
+ return null;
93803
+ }
93804
+ try {
93805
+ const br = new import_bufio4.BufferReader(psbtBuff);
93806
+ if (!br.readBytes(PSBT_MAGIC_BYTES.length, true).equals(PSBT_MAGIC_BYTES)) {
93807
+ return null;
93808
+ }
93809
+ } catch (e8) {
93810
+ return null;
93811
+ }
93812
+ return import_bitcoinjs_lib_v62.Psbt.fromBuffer(psbtBuff, options);
93813
+ }
93814
+
93815
+ // src/psbtv0/psbt.ts
93707
93816
  bitcoin.initEccLib(lib_exports);
93708
93817
  var getUnsignedMultisigPsbtV0 = ({
93709
93818
  network,
@@ -93711,7 +93820,7 @@ var getUnsignedMultisigPsbtV0 = ({
93711
93820
  outputs,
93712
93821
  includeGlobalXpubs = false
93713
93822
  }) => {
93714
- const psbt = new import_bitcoinjs_lib_v62.Psbt({ network: (0, import_bitcoin3.networkData)(network) });
93823
+ const psbt = new import_bitcoinjs_lib_v63.Psbt({ network: (0, import_bitcoin4.networkData)(network) });
93715
93824
  psbt.setVersion(1);
93716
93825
  for (const input of inputs) {
93717
93826
  const inputData = psbtInputFormatter(
@@ -93730,9 +93839,9 @@ var getUnsignedMultisigPsbtV0 = ({
93730
93839
  return psbt;
93731
93840
  };
93732
93841
  var psbtInputFormatter = (input, addressType) => {
93733
- const tx = import_bitcoinjs_lib_v62.Transaction.fromHex(input.transactionHex);
93842
+ const tx = import_bitcoinjs_lib_v63.Transaction.fromHex(input.transactionHex);
93734
93843
  const inputData = { ...input };
93735
- if (addressType === import_bitcoin3.P2SH) {
93844
+ if (addressType === import_bitcoin4.P2SH) {
93736
93845
  const nonWitnessUtxo = tx.toBuffer();
93737
93846
  inputData.nonWitnessUtxo = nonWitnessUtxo;
93738
93847
  } else {
@@ -93746,7 +93855,7 @@ var psbtInputFormatter = (input, addressType) => {
93746
93855
  return inputData;
93747
93856
  };
93748
93857
  var psbtOutputFormatter = (output, network) => {
93749
- const script = (0, import_address.toOutputScript)(output.address, (0, import_bitcoin3.networkData)(network));
93858
+ const script = (0, import_address.toOutputScript)(output.address, (0, import_bitcoin4.networkData)(network));
93750
93859
  const outputData = {
93751
93860
  ...output,
93752
93861
  script,
@@ -93767,7 +93876,7 @@ var addGlobalXpubs = (psbt, inputs, network) => {
93767
93876
  if (!key.bip32Path) {
93768
93877
  return;
93769
93878
  }
93770
- const extendedPublicKey = import_bitcoin3.ExtendedPublicKey.fromBase58(key.xpub);
93879
+ const extendedPublicKey = import_bitcoin4.ExtendedPublicKey.fromBase58(key.xpub);
93771
93880
  extendedPublicKey.network = network;
93772
93881
  extendedPublicKey.path = key.bip32Path;
93773
93882
  extendedPublicKey.rootFingerprint = key.xfp;
@@ -93794,7 +93903,7 @@ var formatGlobalXpub = (extendedPublicKey) => {
93794
93903
  );
93795
93904
  } else if (extendedPublicKey.parentFingerprint) {
93796
93905
  global2.masterFingerprint = import_buffer.Buffer.from(
93797
- (0, import_bitcoin3.fingerprintToFixedLengthHex)(extendedPublicKey.parentFingerprint),
93906
+ (0, import_bitcoin4.fingerprintToFixedLengthHex)(extendedPublicKey.parentFingerprint),
93798
93907
  "hex"
93799
93908
  );
93800
93909
  } else {
@@ -93804,24 +93913,24 @@ var formatGlobalXpub = (extendedPublicKey) => {
93804
93913
  return global2;
93805
93914
  };
93806
93915
  var validateMultisigPsbtSignature = (raw, inputIndex, inputSignature, inputAmount) => {
93807
- const psbt = import_bitcoinjs_lib_v62.Psbt.fromBuffer(bufferize(raw));
93916
+ const psbt = import_bitcoinjs_lib_v63.Psbt.fromBuffer(bufferize(raw));
93808
93917
  if (psbt.inputCount === 0 || psbt.inputCount < inputIndex + 1) {
93809
93918
  throw new Error("Input index is out of range.");
93810
93919
  }
93811
- const signatureBuffer = (0, import_bitcoin3.multisigSignatureBuffer)(
93812
- (0, import_bitcoin3.signatureNoSighashType)(inputSignature.toString("hex"))
93920
+ const signatureBuffer = (0, import_bitcoin4.multisigSignatureBuffer)(
93921
+ (0, import_bitcoin4.signatureNoSighashType)(inputSignature.toString("hex"))
93813
93922
  );
93814
93923
  const input = psbt.data.inputs[inputIndex];
93815
93924
  const msgHash = getHashForSignature(psbt, inputIndex, inputAmount);
93816
93925
  for (const { pubkey } of input.bip32Derivation ?? []) {
93817
- if ((0, import_bitcoin3.isValidSignature)(pubkey, msgHash, signatureBuffer)) {
93926
+ if ((0, import_bitcoin4.isValidSignature)(pubkey, msgHash, signatureBuffer)) {
93818
93927
  return pubkey.toString("hex");
93819
93928
  }
93820
93929
  }
93821
93930
  return false;
93822
93931
  };
93823
- var getHashForSignature = (psbt, inputIndex, inputAmount, sigHashFlag = import_bitcoinjs_lib_v62.Transaction.SIGHASH_ALL) => {
93824
- const tx = import_bitcoinjs_lib_v62.Transaction.fromBuffer(psbt.data.globalMap.unsignedTx.toBuffer());
93932
+ var getHashForSignature = (psbt, inputIndex, inputAmount, sigHashFlag = import_bitcoinjs_lib_v63.Transaction.SIGHASH_ALL) => {
93933
+ const tx = import_bitcoinjs_lib_v63.Transaction.fromBuffer(psbt.data.globalMap.unsignedTx.toBuffer());
93825
93934
  const input = psbt.data.inputs[inputIndex];
93826
93935
  if (!input.witnessScript && input.redeemScript) {
93827
93936
  return tx.hashForSignature(inputIndex, input.redeemScript, sigHashFlag);
@@ -93829,7 +93938,7 @@ var getHashForSignature = (psbt, inputIndex, inputAmount, sigHashFlag = import_b
93829
93938
  if (!inputAmount) {
93830
93939
  throw new Error("Input amount is required for segwit inputs.");
93831
93940
  }
93832
- const amountSats = new import_bignumber.default(inputAmount).toNumber();
93941
+ const amountSats = new import_bignumber2.default(inputAmount).toNumber();
93833
93942
  return tx.hashForWitnessV0(
93834
93943
  inputIndex,
93835
93944
  input.witnessScript,
@@ -93839,91 +93948,67 @@ var getHashForSignature = (psbt, inputIndex, inputAmount, sigHashFlag = import_b
93839
93948
  }
93840
93949
  throw new Error("No redeem or witness script found for input.");
93841
93950
  };
93842
-
93843
- // src/psbtv0/utils.ts
93844
- var import_bitcoin4 = require("@caravan/bitcoin");
93845
-
93846
- // ../multisig/dist/index.mjs
93847
- var braidDetailsToWalletConfig = (braidDetails) => {
93848
- return {
93849
- network: braidDetails.network,
93850
- extendedPublicKeys: braidDetails.extendedPublicKeys.map((key) => ({
93851
- xpub: key.base58String,
93852
- bip32Path: key.path,
93853
- xfp: key.rootFingerprint
93854
- })),
93855
- quorum: {
93856
- requiredSigners: braidDetails.requiredSigners,
93857
- totalSigners: braidDetails.extendedPublicKeys.length
93858
- },
93859
- name: `${braidDetails.requiredSigners}-of-${braidDetails.extendedPublicKeys.length} ${braidDetails.addressType} ${braidDetails.network} wallet`,
93860
- addressType: braidDetails.addressType
93861
- };
93862
- };
93863
-
93864
- // src/psbtv0/utils.ts
93865
- var import_bignumber2 = __toESM(require("bignumber.js"));
93866
- var idToHash = (txid) => {
93867
- return import_buffer.Buffer.from(txid, "hex").reverse();
93868
- };
93869
- function psbtMultisigLock(multisig) {
93870
- if (!multisig) {
93871
- return {};
93872
- }
93873
- const multisigLock = {};
93874
- switch ((0, import_bitcoin4.multisigAddressType)(multisig)) {
93875
- case import_bitcoin4.P2SH:
93876
- multisigLock.redeemScript = (0, import_bitcoin4.multisigRedeemScript)(multisig).output;
93877
- break;
93878
- case import_bitcoin4.P2WSH:
93879
- multisigLock.witnessScript = (0, import_bitcoin4.multisigWitnessScript)(multisig).output;
93880
- break;
93881
- case import_bitcoin4.P2SH_P2WSH:
93882
- multisigLock.witnessScript = (0, import_bitcoin4.multisigWitnessScript)(multisig).output;
93883
- multisigLock.redeemScript = (0, import_bitcoin4.multisigRedeemScript)(multisig).output;
93884
- break;
93885
- }
93886
- return multisigLock;
93887
- }
93888
- function getBip32Derivation(multisig, index = 0) {
93889
- if (!multisig) {
93890
- return;
93891
- }
93892
- if (multisig.bip32Derivation) {
93893
- return multisig.bip32Derivation;
93951
+ function translatePSBT(network, addressType, psbt, signingKeyDetails) {
93952
+ if (addressType !== import_bitcoin4.P2SH) {
93953
+ throw new Error(
93954
+ "Unsupported addressType -- only P2SH is supported right now"
93955
+ );
93894
93956
  }
93895
- const config = JSON.parse((0, import_bitcoin4.multisigBraidDetails)(multisig));
93896
- const braid = (0, import_bitcoin4.generateBraid)(
93897
- config.network,
93898
- config.addressType,
93899
- config.extendedPublicKeys,
93900
- config.requiredSigners,
93901
- config.index
93957
+ const localPSBT = autoLoadPSBT(psbt, { network: (0, import_bitcoin4.networkData)(network) });
93958
+ if (localPSBT === null)
93959
+ return null;
93960
+ const bip32Derivations = filterRelevantBip32Derivations(
93961
+ localPSBT,
93962
+ signingKeyDetails
93902
93963
  );
93903
- return (0, import_bitcoin4.generateBip32DerivationByIndex)(braid, index);
93904
- }
93905
- var convertLegacyInput = (input) => {
93906
- return {
93907
- hash: idToHash(input.txid),
93908
- index: input.index,
93909
- transactionHex: input.transactionHex,
93910
- bip32Derivation: input.multisig.bip32Derivation || getBip32Derivation(input.multisig),
93911
- ...psbtMultisigLock(input.multisig),
93912
- spendingWallet: getWalletConfigFromInput(input)
93913
- };
93914
- };
93915
- var convertLegacyOutput = (output) => {
93964
+ const unchainedInputs = getUnchainedInputsFromPSBT(
93965
+ network,
93966
+ addressType,
93967
+ localPSBT
93968
+ );
93969
+ const unchainedOutputs = getUnchainedOutputsFromPSBT(localPSBT);
93916
93970
  return {
93971
+ unchainedInputs,
93972
+ unchainedOutputs,
93973
+ bip32Derivations
93974
+ };
93975
+ }
93976
+ function getUnchainedInputsFromPSBT(network, addressType, psbt) {
93977
+ return psbt.txInputs.map((input, index) => {
93978
+ const dataInput = psbt.data.inputs[index];
93979
+ const fundingTxHex = dataInput.nonWitnessUtxo.toString("hex");
93980
+ const fundingTx = import_bitcoinjs_lib_v63.Transaction.fromHex(fundingTxHex);
93981
+ const multisig = (0, import_bitcoin4.generateMultisigFromHex)(
93982
+ network,
93983
+ addressType,
93984
+ dataInput.redeemScript.toString("hex")
93985
+ );
93986
+ return {
93987
+ amountSats: fundingTx.outs[input.index].value,
93988
+ index: input.index,
93989
+ transactionHex: fundingTxHex,
93990
+ txid: (0, import_bufferutils.reverseBuffer)(input.hash).toString("hex"),
93991
+ multisig
93992
+ };
93993
+ });
93994
+ }
93995
+ function getUnchainedOutputsFromPSBT(psbt) {
93996
+ return psbt.txOutputs.map((output) => ({
93917
93997
  address: output.address,
93918
- value: new import_bignumber2.default(output.amountSats).toNumber(),
93919
- bip32Derivation: output.bip32Derivation || getBip32Derivation(output.multisig),
93920
- witnessScript: output.witnessScript,
93921
- redeemScript: output.redeemScript
93922
- };
93923
- };
93924
- var getWalletConfigFromInput = (input) => {
93925
- return braidDetailsToWalletConfig(JSON.parse(input.multisig.braidDetails));
93926
- };
93998
+ amountSats: output.value
93999
+ }));
94000
+ }
94001
+ function filterRelevantBip32Derivations(psbt, signingKeyDetails) {
94002
+ return psbt.data.inputs.map((input) => {
94003
+ const bip32Derivation = input.bip32Derivation.filter(
94004
+ (b32d) => b32d.path.startsWith(signingKeyDetails.path) && b32d.masterFingerprint.toString("hex") === signingKeyDetails.xfp
94005
+ );
94006
+ if (!bip32Derivation.length) {
94007
+ throw new Error("Signing key details not included in PSBT");
94008
+ }
94009
+ return bip32Derivation[0];
94010
+ });
94011
+ }
93927
94012
  // Annotate the CommonJS export names for ESM import in node:
93928
94013
  0 && (module.exports = {
93929
94014
  PSBT_MAGIC_B64,
@@ -93931,10 +94016,12 @@ var getWalletConfigFromInput = (input) => {
93931
94016
  PSBT_MAGIC_HEX,
93932
94017
  PsbtV2,
93933
94018
  addGlobalXpubs,
94019
+ autoLoadPSBT,
93934
94020
  convertLegacyInput,
93935
94021
  convertLegacyOutput,
93936
94022
  getPsbtVersionNumber,
93937
94023
  getUnsignedMultisigPsbtV0,
94024
+ translatePSBT,
93938
94025
  validateMultisigPsbtSignature
93939
94026
  });
93940
94027
  /*! Bundled license information:
package/dist/index.mjs CHANGED
@@ -1161,14 +1161,15 @@ var PsbtV2 = class _PsbtV2 extends PsbtV2Maps {
1161
1161
  import {
1162
1162
  ExtendedPublicKey,
1163
1163
  fingerprintToFixedLengthHex,
1164
+ generateMultisigFromHex,
1164
1165
  isValidSignature,
1165
1166
  multisigSignatureBuffer,
1166
1167
  networkData,
1167
- P2SH,
1168
+ P2SH as P2SH2,
1168
1169
  signatureNoSighashType
1169
1170
  } from "@caravan/bitcoin";
1170
- import { Psbt as Psbt2, Transaction } from "bitcoinjs-lib-v6";
1171
- import { toOutputScript } from "bitcoinjs-lib-v6/src/address";
1171
+ import { Psbt as Psbt3, Transaction } from "bitcoinjs-lib-v6";
1172
+ import { toOutputScript } from "bitcoinjs-lib-v6/src/address.js";
1172
1173
 
1173
1174
  // vendor/tiny-secp256k1-asmjs/lib/index.js
1174
1175
  var lib_exports = {};
@@ -93672,7 +93673,124 @@ function verifySchnorr2(h6, Q3, signature) {
93672
93673
 
93673
93674
  // src/psbtv0/psbt.ts
93674
93675
  import * as bitcoin from "bitcoinjs-lib-v6";
93676
+ import BigNumber2 from "bignumber.js";
93677
+ import { reverseBuffer } from "bitcoinjs-lib-v6/src/bufferutils.js";
93678
+
93679
+ // src/psbtv0/utils.ts
93680
+ import {
93681
+ generateBip32DerivationByIndex,
93682
+ generateBraid,
93683
+ multisigAddressType,
93684
+ multisigBraidDetails,
93685
+ multisigRedeemScript,
93686
+ multisigWitnessScript,
93687
+ P2SH,
93688
+ P2SH_P2WSH,
93689
+ P2WSH
93690
+ } from "@caravan/bitcoin";
93691
+
93692
+ // ../multisig/dist/index.mjs
93693
+ var braidDetailsToWalletConfig = (braidDetails) => {
93694
+ return {
93695
+ network: braidDetails.network,
93696
+ extendedPublicKeys: braidDetails.extendedPublicKeys.map((key) => ({
93697
+ xpub: key.base58String,
93698
+ bip32Path: key.path,
93699
+ xfp: key.rootFingerprint
93700
+ })),
93701
+ quorum: {
93702
+ requiredSigners: braidDetails.requiredSigners,
93703
+ totalSigners: braidDetails.extendedPublicKeys.length
93704
+ },
93705
+ name: `${braidDetails.requiredSigners}-of-${braidDetails.extendedPublicKeys.length} ${braidDetails.addressType} ${braidDetails.network} wallet`,
93706
+ addressType: braidDetails.addressType
93707
+ };
93708
+ };
93709
+
93710
+ // src/psbtv0/utils.ts
93675
93711
  import BigNumber from "bignumber.js";
93712
+ import { Psbt as Psbt2 } from "bitcoinjs-lib-v6";
93713
+ import { BufferReader as BufferReader4 } from "bufio";
93714
+ var idToHash = (txid) => {
93715
+ return Buffer2.from(txid, "hex").reverse();
93716
+ };
93717
+ function psbtMultisigLock(multisig) {
93718
+ if (!multisig) {
93719
+ return {};
93720
+ }
93721
+ const multisigLock = {};
93722
+ switch (multisigAddressType(multisig)) {
93723
+ case P2SH:
93724
+ multisigLock.redeemScript = multisigRedeemScript(multisig).output;
93725
+ break;
93726
+ case P2WSH:
93727
+ multisigLock.witnessScript = multisigWitnessScript(multisig).output;
93728
+ break;
93729
+ case P2SH_P2WSH:
93730
+ multisigLock.witnessScript = multisigWitnessScript(multisig).output;
93731
+ multisigLock.redeemScript = multisigRedeemScript(multisig).output;
93732
+ break;
93733
+ }
93734
+ return multisigLock;
93735
+ }
93736
+ function getBip32Derivation(multisig, index = 0) {
93737
+ if (!multisig) {
93738
+ return;
93739
+ }
93740
+ if (multisig.bip32Derivation) {
93741
+ return multisig.bip32Derivation;
93742
+ }
93743
+ const config = JSON.parse(multisigBraidDetails(multisig));
93744
+ const braid = generateBraid(
93745
+ config.network,
93746
+ config.addressType,
93747
+ config.extendedPublicKeys,
93748
+ config.requiredSigners,
93749
+ config.index
93750
+ );
93751
+ return generateBip32DerivationByIndex(braid, index);
93752
+ }
93753
+ var convertLegacyInput = (input) => {
93754
+ return {
93755
+ hash: idToHash(input.txid),
93756
+ index: input.index,
93757
+ transactionHex: input.transactionHex,
93758
+ bip32Derivation: input.multisig.bip32Derivation || getBip32Derivation(input.multisig),
93759
+ ...psbtMultisigLock(input.multisig),
93760
+ spendingWallet: getWalletConfigFromInput(input)
93761
+ };
93762
+ };
93763
+ var convertLegacyOutput = (output) => {
93764
+ return {
93765
+ address: output.address,
93766
+ value: new BigNumber(output.amountSats).toNumber(),
93767
+ bip32Derivation: output.bip32Derivation || getBip32Derivation(output.multisig),
93768
+ witnessScript: output.witnessScript,
93769
+ redeemScript: output.redeemScript
93770
+ };
93771
+ };
93772
+ var getWalletConfigFromInput = (input) => {
93773
+ return braidDetailsToWalletConfig(JSON.parse(input.multisig.braidDetails));
93774
+ };
93775
+ function autoLoadPSBT(psbtFromFile, options) {
93776
+ let psbtBuff;
93777
+ try {
93778
+ psbtBuff = bufferize(psbtFromFile);
93779
+ } catch (e8) {
93780
+ return null;
93781
+ }
93782
+ try {
93783
+ const br = new BufferReader4(psbtBuff);
93784
+ if (!br.readBytes(PSBT_MAGIC_BYTES.length, true).equals(PSBT_MAGIC_BYTES)) {
93785
+ return null;
93786
+ }
93787
+ } catch (e8) {
93788
+ return null;
93789
+ }
93790
+ return Psbt2.fromBuffer(psbtBuff, options);
93791
+ }
93792
+
93793
+ // src/psbtv0/psbt.ts
93676
93794
  bitcoin.initEccLib(lib_exports);
93677
93795
  var getUnsignedMultisigPsbtV0 = ({
93678
93796
  network,
@@ -93680,7 +93798,7 @@ var getUnsignedMultisigPsbtV0 = ({
93680
93798
  outputs,
93681
93799
  includeGlobalXpubs = false
93682
93800
  }) => {
93683
- const psbt = new Psbt2({ network: networkData(network) });
93801
+ const psbt = new Psbt3({ network: networkData(network) });
93684
93802
  psbt.setVersion(1);
93685
93803
  for (const input of inputs) {
93686
93804
  const inputData = psbtInputFormatter(
@@ -93701,7 +93819,7 @@ var getUnsignedMultisigPsbtV0 = ({
93701
93819
  var psbtInputFormatter = (input, addressType) => {
93702
93820
  const tx = Transaction.fromHex(input.transactionHex);
93703
93821
  const inputData = { ...input };
93704
- if (addressType === P2SH) {
93822
+ if (addressType === P2SH2) {
93705
93823
  const nonWitnessUtxo = tx.toBuffer();
93706
93824
  inputData.nonWitnessUtxo = nonWitnessUtxo;
93707
93825
  } else {
@@ -93773,7 +93891,7 @@ var formatGlobalXpub = (extendedPublicKey) => {
93773
93891
  return global2;
93774
93892
  };
93775
93893
  var validateMultisigPsbtSignature = (raw, inputIndex, inputSignature, inputAmount) => {
93776
- const psbt = Psbt2.fromBuffer(bufferize(raw));
93894
+ const psbt = Psbt3.fromBuffer(bufferize(raw));
93777
93895
  if (psbt.inputCount === 0 || psbt.inputCount < inputIndex + 1) {
93778
93896
  throw new Error("Input index is out of range.");
93779
93897
  }
@@ -93798,7 +93916,7 @@ var getHashForSignature = (psbt, inputIndex, inputAmount, sigHashFlag = Transact
93798
93916
  if (!inputAmount) {
93799
93917
  throw new Error("Input amount is required for segwit inputs.");
93800
93918
  }
93801
- const amountSats = new BigNumber(inputAmount).toNumber();
93919
+ const amountSats = new BigNumber2(inputAmount).toNumber();
93802
93920
  return tx.hashForWitnessV0(
93803
93921
  inputIndex,
93804
93922
  input.witnessScript,
@@ -93808,111 +93926,79 @@ var getHashForSignature = (psbt, inputIndex, inputAmount, sigHashFlag = Transact
93808
93926
  }
93809
93927
  throw new Error("No redeem or witness script found for input.");
93810
93928
  };
93811
-
93812
- // src/psbtv0/utils.ts
93813
- import {
93814
- generateBip32DerivationByIndex,
93815
- generateBraid,
93816
- multisigAddressType,
93817
- multisigBraidDetails,
93818
- multisigRedeemScript,
93819
- multisigWitnessScript,
93820
- P2SH as P2SH2,
93821
- P2SH_P2WSH,
93822
- P2WSH
93823
- } from "@caravan/bitcoin";
93824
-
93825
- // ../multisig/dist/index.mjs
93826
- var braidDetailsToWalletConfig = (braidDetails) => {
93827
- return {
93828
- network: braidDetails.network,
93829
- extendedPublicKeys: braidDetails.extendedPublicKeys.map((key) => ({
93830
- xpub: key.base58String,
93831
- bip32Path: key.path,
93832
- xfp: key.rootFingerprint
93833
- })),
93834
- quorum: {
93835
- requiredSigners: braidDetails.requiredSigners,
93836
- totalSigners: braidDetails.extendedPublicKeys.length
93837
- },
93838
- name: `${braidDetails.requiredSigners}-of-${braidDetails.extendedPublicKeys.length} ${braidDetails.addressType} ${braidDetails.network} wallet`,
93839
- addressType: braidDetails.addressType
93840
- };
93841
- };
93842
-
93843
- // src/psbtv0/utils.ts
93844
- import BigNumber2 from "bignumber.js";
93845
- var idToHash = (txid) => {
93846
- return Buffer2.from(txid, "hex").reverse();
93847
- };
93848
- function psbtMultisigLock(multisig) {
93849
- if (!multisig) {
93850
- return {};
93851
- }
93852
- const multisigLock = {};
93853
- switch (multisigAddressType(multisig)) {
93854
- case P2SH2:
93855
- multisigLock.redeemScript = multisigRedeemScript(multisig).output;
93856
- break;
93857
- case P2WSH:
93858
- multisigLock.witnessScript = multisigWitnessScript(multisig).output;
93859
- break;
93860
- case P2SH_P2WSH:
93861
- multisigLock.witnessScript = multisigWitnessScript(multisig).output;
93862
- multisigLock.redeemScript = multisigRedeemScript(multisig).output;
93863
- break;
93864
- }
93865
- return multisigLock;
93866
- }
93867
- function getBip32Derivation(multisig, index = 0) {
93868
- if (!multisig) {
93869
- return;
93870
- }
93871
- if (multisig.bip32Derivation) {
93872
- return multisig.bip32Derivation;
93929
+ function translatePSBT(network, addressType, psbt, signingKeyDetails) {
93930
+ if (addressType !== P2SH2) {
93931
+ throw new Error(
93932
+ "Unsupported addressType -- only P2SH is supported right now"
93933
+ );
93873
93934
  }
93874
- const config = JSON.parse(multisigBraidDetails(multisig));
93875
- const braid = generateBraid(
93876
- config.network,
93877
- config.addressType,
93878
- config.extendedPublicKeys,
93879
- config.requiredSigners,
93880
- config.index
93935
+ const localPSBT = autoLoadPSBT(psbt, { network: networkData(network) });
93936
+ if (localPSBT === null)
93937
+ return null;
93938
+ const bip32Derivations = filterRelevantBip32Derivations(
93939
+ localPSBT,
93940
+ signingKeyDetails
93881
93941
  );
93882
- return generateBip32DerivationByIndex(braid, index);
93883
- }
93884
- var convertLegacyInput = (input) => {
93885
- return {
93886
- hash: idToHash(input.txid),
93887
- index: input.index,
93888
- transactionHex: input.transactionHex,
93889
- bip32Derivation: input.multisig.bip32Derivation || getBip32Derivation(input.multisig),
93890
- ...psbtMultisigLock(input.multisig),
93891
- spendingWallet: getWalletConfigFromInput(input)
93892
- };
93893
- };
93894
- var convertLegacyOutput = (output) => {
93942
+ const unchainedInputs = getUnchainedInputsFromPSBT(
93943
+ network,
93944
+ addressType,
93945
+ localPSBT
93946
+ );
93947
+ const unchainedOutputs = getUnchainedOutputsFromPSBT(localPSBT);
93895
93948
  return {
93949
+ unchainedInputs,
93950
+ unchainedOutputs,
93951
+ bip32Derivations
93952
+ };
93953
+ }
93954
+ function getUnchainedInputsFromPSBT(network, addressType, psbt) {
93955
+ return psbt.txInputs.map((input, index) => {
93956
+ const dataInput = psbt.data.inputs[index];
93957
+ const fundingTxHex = dataInput.nonWitnessUtxo.toString("hex");
93958
+ const fundingTx = Transaction.fromHex(fundingTxHex);
93959
+ const multisig = generateMultisigFromHex(
93960
+ network,
93961
+ addressType,
93962
+ dataInput.redeemScript.toString("hex")
93963
+ );
93964
+ return {
93965
+ amountSats: fundingTx.outs[input.index].value,
93966
+ index: input.index,
93967
+ transactionHex: fundingTxHex,
93968
+ txid: reverseBuffer(input.hash).toString("hex"),
93969
+ multisig
93970
+ };
93971
+ });
93972
+ }
93973
+ function getUnchainedOutputsFromPSBT(psbt) {
93974
+ return psbt.txOutputs.map((output) => ({
93896
93975
  address: output.address,
93897
- value: new BigNumber2(output.amountSats).toNumber(),
93898
- bip32Derivation: output.bip32Derivation || getBip32Derivation(output.multisig),
93899
- witnessScript: output.witnessScript,
93900
- redeemScript: output.redeemScript
93901
- };
93902
- };
93903
- var getWalletConfigFromInput = (input) => {
93904
- return braidDetailsToWalletConfig(JSON.parse(input.multisig.braidDetails));
93905
- };
93976
+ amountSats: output.value
93977
+ }));
93978
+ }
93979
+ function filterRelevantBip32Derivations(psbt, signingKeyDetails) {
93980
+ return psbt.data.inputs.map((input) => {
93981
+ const bip32Derivation = input.bip32Derivation.filter(
93982
+ (b32d) => b32d.path.startsWith(signingKeyDetails.path) && b32d.masterFingerprint.toString("hex") === signingKeyDetails.xfp
93983
+ );
93984
+ if (!bip32Derivation.length) {
93985
+ throw new Error("Signing key details not included in PSBT");
93986
+ }
93987
+ return bip32Derivation[0];
93988
+ });
93989
+ }
93906
93990
  export {
93907
93991
  PSBT_MAGIC_B64,
93908
93992
  PSBT_MAGIC_BYTES,
93909
93993
  PSBT_MAGIC_HEX,
93910
93994
  PsbtV2,
93911
93995
  addGlobalXpubs,
93996
+ autoLoadPSBT,
93912
93997
  convertLegacyInput,
93913
93998
  convertLegacyOutput,
93914
93999
  getPsbtVersionNumber,
93915
94000
  getUnsignedMultisigPsbtV0,
94001
+ translatePSBT,
93916
94002
  validateMultisigPsbtSignature
93917
94003
  };
93918
94004
  /*! Bundled license information:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caravan/psbt",
3
- "version": "1.3.2",
3
+ "version": "1.4.1",
4
4
  "description": "typescript library for working with PSBTs",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -51,8 +51,8 @@
51
51
  "author": "unchained capital",
52
52
  "license": "ISC",
53
53
  "devDependencies": {
54
- "@caravan/multisig": "*",
55
54
  "@caravan/eslint-config": "*",
55
+ "@caravan/multisig": "*",
56
56
  "@caravan/typescript-config": "*",
57
57
  "@inrupt/jest-jsdom-polyfills": "^3.2.1",
58
58
  "@jest/globals": "^29.7.0",
@@ -61,6 +61,7 @@
61
61
  "jest": "^29.4.1",
62
62
  "jsdom": "24.0.0",
63
63
  "jsdom-global": "3.0.2",
64
+ "lodash": "^4.17.21",
64
65
  "react-silence": "^1.0.4",
65
66
  "ts-jest": "^29.1.2",
66
67
  "ts-node": "^10.9.2",