@dynamic-labs-wallet/btc-utils 1.0.105 → 1.0.107

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/index.cjs +269 -31
  2. package/index.esm.js +265 -32
  3. package/package.json +2 -2
  4. package/src/assertSighashAllowed/assertSighashAllowed.d.ts +21 -0
  5. package/src/assertSighashAllowed/assertSighashAllowed.d.ts.map +1 -0
  6. package/src/assertSighashAllowed/index.d.ts +2 -0
  7. package/src/assertSighashAllowed/index.d.ts.map +1 -0
  8. package/src/bytesEqual/bytesEqual.d.ts +10 -0
  9. package/src/bytesEqual/bytesEqual.d.ts.map +1 -0
  10. package/src/bytesEqual/index.d.ts +2 -0
  11. package/src/bytesEqual/index.d.ts.map +1 -0
  12. package/src/convertSignatureToDER/convertSignatureToDER.d.ts +4 -1
  13. package/src/convertSignatureToDER/convertSignatureToDER.d.ts.map +1 -1
  14. package/src/convertSignatureToTaprootBuffer/convertSignatureToTaprootBuffer.d.ts +5 -2
  15. package/src/convertSignatureToTaprootBuffer/convertSignatureToTaprootBuffer.d.ts.map +1 -1
  16. package/src/doesInputBelongToAddress/doesInputBelongToAddress.d.ts +14 -3
  17. package/src/doesInputBelongToAddress/doesInputBelongToAddress.d.ts.map +1 -1
  18. package/src/extractPsbtSighashes/extractPsbtSighashes.d.ts +6 -2
  19. package/src/extractPsbtSighashes/extractPsbtSighashes.d.ts.map +1 -1
  20. package/src/filterInputsBySigningIndexes/filterInputsBySigningIndexes.d.ts +12 -0
  21. package/src/filterInputsBySigningIndexes/filterInputsBySigningIndexes.d.ts.map +1 -0
  22. package/src/filterInputsBySigningIndexes/index.d.ts +2 -0
  23. package/src/filterInputsBySigningIndexes/index.d.ts.map +1 -0
  24. package/src/getSegwitV0ScriptCode/getSegwitV0ScriptCode.d.ts +20 -0
  25. package/src/getSegwitV0ScriptCode/getSegwitV0ScriptCode.d.ts.map +1 -0
  26. package/src/getSegwitV0ScriptCode/index.d.ts +2 -0
  27. package/src/getSegwitV0ScriptCode/index.d.ts.map +1 -0
  28. package/src/getSigHashType/getSigHashType.d.ts +21 -0
  29. package/src/getSigHashType/getSigHashType.d.ts.map +1 -0
  30. package/src/getSigHashType/index.d.ts +2 -0
  31. package/src/getSigHashType/index.d.ts.map +1 -0
  32. package/src/index.d.ts +5 -0
  33. package/src/index.d.ts.map +1 -1
  34. package/src/isP2wshOutputScript/index.d.ts +2 -0
  35. package/src/isP2wshOutputScript/index.d.ts.map +1 -0
  36. package/src/isP2wshOutputScript/isP2wshOutputScript.d.ts +10 -0
  37. package/src/isP2wshOutputScript/isP2wshOutputScript.d.ts.map +1 -0
package/index.cjs CHANGED
@@ -726,8 +726,12 @@ function _instanceof$3(left, right) {
726
726
  * Converts an ECDSA signature to DER format
727
727
  *
728
728
  * @param signature - The ECDSA signature
729
+ * @param sighashType - The sighash type to append as the DER trailing byte.
730
+ * Must match the type the signing hash was built with, or the signature will
731
+ * fail verification at finalize/broadcast. Defaults to SIGHASH_ALL.
729
732
  * @returns The DER encoded signature
730
733
  */ var convertSignatureToDER = function(signature) {
734
+ var sighashType = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : bitcoin__namespace.Transaction.SIGHASH_ALL;
731
735
  var r = _instanceof$3(signature.r, Uint8Array) ? signature.r : new Uint8Array(signature.r);
732
736
  var s = _instanceof$3(signature.s, Uint8Array) ? signature.s : new Uint8Array(signature.s);
733
737
  var r32 = new Uint8Array(32);
@@ -739,7 +743,7 @@ function _instanceof$3(left, right) {
739
743
  var rawSignature = new Uint8Array(64);
740
744
  rawSignature.set(r32, 0);
741
745
  rawSignature.set(s32, 32);
742
- var derSignature = bitcoin__namespace.script.signature.encode(rawSignature, bitcoin__namespace.Transaction.SIGHASH_ALL);
746
+ var derSignature = bitcoin__namespace.script.signature.encode(rawSignature, sighashType);
743
747
  return derSignature;
744
748
  };
745
749
 
@@ -1210,19 +1214,34 @@ function _instanceof$2(left, right) {
1210
1214
  * Converts a signature to a Buffer format suitable for Taproot (BIP340/Schnorr)
1211
1215
  *
1212
1216
  * @param signature - The signature from MPC (can be Uint8Array, Buffer, or EcdsaSignature object)
1213
- * @returns A Buffer containing the 64-byte Schnorr signature
1217
+ * @param sighashType - The sighash type the signing hash was built with. Per
1218
+ * BIP-341 the signature stays 64 bytes for SIGHASH_DEFAULT and gains the
1219
+ * sighash type as a 65th byte for any other type. Defaults to SIGHASH_DEFAULT.
1220
+ * @returns A Buffer containing the 64-byte (or 65-byte) Schnorr signature
1214
1221
  */ var convertSignatureToTaprootBuffer = function(signature) {
1222
+ var sighashType = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : bitcoin__namespace.Transaction.SIGHASH_DEFAULT;
1223
+ var schnorrSignature;
1215
1224
  if (_instanceof$2(signature, Uint8Array) || Buffer.isBuffer(signature)) {
1216
- return Buffer.from(signature);
1225
+ schnorrSignature = Buffer.from(signature);
1226
+ } else {
1227
+ var r = signature.r;
1228
+ var s = signature.s;
1229
+ var rBuf = Buffer.isBuffer(r) ? r : Buffer.from(r);
1230
+ var sBuf = Buffer.isBuffer(s) ? s : Buffer.from(s);
1231
+ // Safe: creates Uint8Array views over Buffer's underlying memory without copying
1232
+ schnorrSignature = Buffer.concat([
1233
+ new Uint8Array(rBuf),
1234
+ new Uint8Array(sBuf)
1235
+ ]);
1236
+ }
1237
+ if (sighashType === bitcoin__namespace.Transaction.SIGHASH_DEFAULT) {
1238
+ return schnorrSignature;
1217
1239
  }
1218
- var r = signature.r;
1219
- var s = signature.s;
1220
- var rBuf = Buffer.isBuffer(r) ? r : Buffer.from(r);
1221
- var sBuf = Buffer.isBuffer(s) ? s : Buffer.from(s);
1222
- // Safe: creates Uint8Array views over Buffer's underlying memory without copying
1223
1240
  return Buffer.concat([
1224
- new Uint8Array(rBuf),
1225
- new Uint8Array(sBuf)
1241
+ new Uint8Array(schnorrSignature),
1242
+ new Uint8Array([
1243
+ sighashType
1244
+ ])
1226
1245
  ]);
1227
1246
  };
1228
1247
 
@@ -1248,6 +1267,30 @@ function _instanceof$2(left, right) {
1248
1267
  };
1249
1268
  };
1250
1269
 
1270
+ /**
1271
+ * Checks if an output script (scriptPubKey) is P2WSH: OP_0 <32-byte sha256(witnessScript)>
1272
+ *
1273
+ * ArrayLike keeps this callable with Buffer or Uint8Array — the iframe build
1274
+ * compiles with browser typings where Buffer is not assignable to Uint8Array.
1275
+ * @param script - The output script to check
1276
+ * @returns True if the script has the P2WSH shape
1277
+ */ var isP2wshOutputScript = function(script) {
1278
+ return script.length === 34 && script[0] === 0x00 && script[1] === 0x20;
1279
+ };
1280
+
1281
+ /**
1282
+ * Constant-shape byte equality without Buffer — the iframe build compiles
1283
+ * this package with browser typings where Buffer is not assignable to
1284
+ * Uint8Array.
1285
+ * @param a - First byte array
1286
+ * @param b - Second byte array
1287
+ * @returns True if both arrays have identical length and contents
1288
+ */ var bytesEqual = function(a, b) {
1289
+ return a.length === b.length && a.every(function(byte, index) {
1290
+ return byte === b[index];
1291
+ });
1292
+ };
1293
+
1251
1294
  function _instanceof$1(left, right) {
1252
1295
  if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
1253
1296
  return !!right[Symbol.hasInstance](left);
@@ -1256,12 +1299,63 @@ function _instanceof$1(left, right) {
1256
1299
  }
1257
1300
  }
1258
1301
  /**
1259
- * Checks if a PSBT input belongs to a specific address
1302
+ * P2WSH ownership: the caller allowlisted the witnessScript, it hashes to the
1303
+ * scriptPubKey commitment, and it is a canonical m-of-n CHECKMULTISIG with
1304
+ * `publicKey` in a signing position.
1305
+ */ var matchesAllowedP2wshMultisig = function(input, script, publicKey, allowedWitnessScripts) {
1306
+ if (!publicKey || !input.witnessScript || !(allowedWitnessScripts === null || allowedWitnessScripts === void 0 ? void 0 : allowedWitnessScripts.length)) {
1307
+ return false;
1308
+ }
1309
+ var witnessScript = Uint8Array.from(input.witnessScript);
1310
+ // P2WSH co-signing is opt-in: the wallet only signs arrangements the
1311
+ // caller explicitly named in this request.
1312
+ var witnessScriptHex = Buffer.from(witnessScript).toString('hex');
1313
+ if (!allowedWitnessScripts.some(function(hex) {
1314
+ return hex.toLowerCase() === witnessScriptHex;
1315
+ })) {
1316
+ return false;
1317
+ }
1318
+ // The scriptPubKey commits to the witnessScript; a mismatch means the
1319
+ // PSBT is lying about the script this signature would authorize.
1320
+ if (!bytesEqual(sha256.sha256(witnessScript), Uint8Array.from(script).subarray(2))) {
1321
+ return false;
1322
+ }
1323
+ // p2ms throws unless the script is exactly OP_m <keys...> OP_n
1324
+ // OP_CHECKMULTISIG, so the key must occupy a signing position.
1325
+ var multisigPubkeys;
1326
+ try {
1327
+ multisigPubkeys = bitcoin__namespace.payments.p2ms({
1328
+ output: witnessScript
1329
+ }).pubkeys;
1330
+ } catch (e) {
1331
+ return false;
1332
+ }
1333
+ if (!multisigPubkeys) {
1334
+ return false;
1335
+ }
1336
+ var publicKeyBytes = Uint8Array.from(publicKey);
1337
+ return multisigPubkeys.some(function(key) {
1338
+ return bytesEqual(Uint8Array.from(key), publicKeyBytes);
1339
+ });
1340
+ };
1341
+ /**
1342
+ * Checks if a PSBT input belongs to a specific address.
1343
+ *
1344
+ * For P2WSH inputs address equality cannot work (the address commits to the
1345
+ * script, not our key), so ownership is opt-in and means ALL of: the caller
1346
+ * explicitly allowlisted the witnessScript, it hashes to the scriptPubKey
1347
+ * commitment, and it is a canonical m-of-n CHECKMULTISIG script with
1348
+ * `publicKey` in a signing position. Any other script shape is rejected even
1349
+ * if the key appears in it, so a hostile PSBT cannot obtain a signature over
1350
+ * an arbitrary script that merely name-drops the wallet key, and the wallet
1351
+ * never co-signs a multisig arrangement the caller did not name.
1260
1352
  * @param input - The PSBT input (from psbt.data.inputs)
1261
1353
  * @param address - The address to check against
1262
1354
  * @param network - The Bitcoin network
1263
- * @returns True if the input belongs to the address, false otherwise
1264
- */ var doesInputBelongToAddress = function(input, address, network) {
1355
+ * @param publicKey - The wallet's compressed ECDSA public key; required to match P2WSH inputs
1356
+ * @param allowedWitnessScripts - Hex-encoded witnessScripts the caller consents to co-sign; required to match P2WSH inputs
1357
+ * @returns True if the input belongs to the address (or public key, for P2WSH), false otherwise
1358
+ */ var doesInputBelongToAddress = function(input, address, network, publicKey, allowedWitnessScripts) {
1265
1359
  if (!input.witnessUtxo) {
1266
1360
  return false;
1267
1361
  }
@@ -1285,6 +1379,10 @@ function _instanceof$1(left, right) {
1285
1379
  }).address === address;
1286
1380
  });
1287
1381
  }
1382
+ // Try P2WSH - script is OP_0 <32-byte sha256(witnessScript)>
1383
+ if (isP2wshOutputScript(script)) {
1384
+ return matchesAllowedP2wshMultisig(input, script, publicKey, allowedWitnessScripts);
1385
+ }
1288
1386
  // Try P2TR (Taproot) - script is OP_1 <32-byte x-only pubkey>
1289
1387
  if (script.length === 34 && script[0] === 0x51 && script[1] === 0x20) {
1290
1388
  return networksToTry.some(function(bitcoinNetwork) {
@@ -1306,6 +1404,139 @@ function _instanceof$1(left, right) {
1306
1404
  }
1307
1405
  };
1308
1406
 
1407
+ /**
1408
+ * Resolves the BIP-143 scriptCode for a segwit v0 input. Shared by the signer
1409
+ * and the sighash-verification helper so both derive the identical digest.
1410
+ *
1411
+ * P2WSH inputs sign over the full witnessScript, verified against the
1412
+ * scriptPubKey commitment so a PSBT cannot substitute a script the UTXO does
1413
+ * not commit to. P2WPKH inputs sign over the implied P2PKH script.
1414
+ *
1415
+ * @param input - The PSBT input (from psbt.data.inputs)
1416
+ * @param script - The input's witnessUtxo scriptPubKey
1417
+ * @param index - The input index (for error messages)
1418
+ * @param bitcoinNetwork - The bitcoinjs-lib network for P2PKH reconstruction
1419
+ * @returns The scriptCode to feed hashForWitnessV0
1420
+ * @throws Error if a P2WSH input is missing its witnessScript, the witnessScript
1421
+ * does not hash to the scriptPubKey commitment, or scriptCode generation fails
1422
+ */ var getSegwitV0ScriptCode = function(input, script, index, bitcoinNetwork) {
1423
+ if (isP2wshOutputScript(script)) {
1424
+ if (!input.witnessScript) {
1425
+ throw new Error("Input ".concat(index, " is P2WSH but missing witnessScript"));
1426
+ }
1427
+ var witnessScript = Uint8Array.from(input.witnessScript);
1428
+ // The scriptPubKey commits to the witnessScript; refuse to compute a
1429
+ // sighash over a script the UTXO does not commit to.
1430
+ if (!bytesEqual(sha256.sha256(witnessScript), Uint8Array.from(script).subarray(2))) {
1431
+ throw new Error("Input ".concat(index, " witnessScript does not match the P2WSH scriptPubKey commitment"));
1432
+ }
1433
+ return witnessScript;
1434
+ }
1435
+ // Build P2PKH script code from the pubkey hash in the witness program
1436
+ var p2pkh = bitcoin__namespace.payments.p2pkh({
1437
+ hash: Uint8Array.from(script).subarray(2),
1438
+ network: bitcoinNetwork
1439
+ });
1440
+ if (!p2pkh.output) {
1441
+ throw new Error("Failed to generate scriptCode for input ".concat(index));
1442
+ }
1443
+ return p2pkh.output;
1444
+ };
1445
+
1446
+ /**
1447
+ * Restricts wallet-owned PSBT inputs to an explicitly requested subset.
1448
+ *
1449
+ * @param inputsToSign - Wallet-owned inputs, each carrying its PSBT index
1450
+ * @param signingIndexes - Optional subset of input indexes the caller wants signed
1451
+ * @returns The requested subset, or all inputs when signingIndexes is omitted/empty
1452
+ * @throws Error if signingIndexes references an input the wallet does not own
1453
+ */ var filterInputsBySigningIndexes = function(inputsToSign, signingIndexes) {
1454
+ if (!(signingIndexes === null || signingIndexes === void 0 ? void 0 : signingIndexes.length)) {
1455
+ return inputsToSign;
1456
+ }
1457
+ var walletOwnedIndexSet = new Set(inputsToSign.map(function(param) {
1458
+ var index = param.index;
1459
+ return index;
1460
+ }));
1461
+ var invalidIndexes = signingIndexes.filter(function(i) {
1462
+ return !walletOwnedIndexSet.has(i);
1463
+ });
1464
+ if (invalidIndexes.length > 0) {
1465
+ throw new Error("signingIndexes contains indexes that do not belong to the signing address: ".concat(invalidIndexes.join(', ')));
1466
+ }
1467
+ var requestedIndexSet = new Set(signingIndexes);
1468
+ return inputsToSign.filter(function(param) {
1469
+ var index = param.index;
1470
+ return requestedIndexSet.has(index);
1471
+ });
1472
+ };
1473
+
1474
+ /**
1475
+ * Resolves the sighash type for a PSBT input.
1476
+ *
1477
+ * The type is read from the PSBT itself (BIP-174 `PSBT_IN_SIGHASH_TYPE`), never
1478
+ * supplied by the caller — the signing hash and the policy layer's verification
1479
+ * hash must be derived from the same bytes, or every non-default signature
1480
+ * would be rejected as tampered.
1481
+ *
1482
+ * When the input declares nothing, falls back to the historical default:
1483
+ * SIGHASH_DEFAULT (0x00) for Taproot, SIGHASH_ALL (0x01) otherwise.
1484
+ *
1485
+ * @param input - The PSBT input to resolve the sighash type for
1486
+ * @param isTaproot - Whether the input is spent as Taproot. Defaults to
1487
+ * detecting `tapInternalKey`; pass explicitly when the caller already knows
1488
+ * which signing branch it is on, so the fallback matches the hash function
1489
+ * actually used.
1490
+ * @returns The sighash type to build and encode the signature with
1491
+ */ var getSigHashType = function(input) {
1492
+ var isTaproot = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : Boolean(input.tapInternalKey);
1493
+ var _input_sighashType;
1494
+ return (_input_sighashType = input.sighashType) !== null && _input_sighashType !== void 0 ? _input_sighashType : isTaproot ? bitcoin__namespace.Transaction.SIGHASH_DEFAULT : bitcoin__namespace.Transaction.SIGHASH_ALL;
1495
+ };
1496
+
1497
+ /**
1498
+ * Throws unless every input's PSBT-declared sighash type is in the allow-list.
1499
+ *
1500
+ * Call this before any signing begins — inputs are signed in parallel, so
1501
+ * throwing partway through would leave a partially signed PSBT behind.
1502
+ *
1503
+ * An empty array permits nothing rather than everything: a caller whose
1504
+ * allow-list computes to empty must not silently get the guard disabled. Omit
1505
+ * the parameter entirely to permit any declared type.
1506
+ *
1507
+ * @param inputsToSign - The wallet-owned inputs about to be signed, with their PSBT indexes
1508
+ * @param isTaproot - Whether signing takes the Taproot branch, so the fallback
1509
+ * sighash type matches the hash function actually used
1510
+ * @param allowedSighash - Optional allow-list of permitted sighash types
1511
+ */ var assertSighashAllowed = function(inputsToSign, isTaproot, allowedSighash) {
1512
+ if (!allowedSighash) {
1513
+ return;
1514
+ }
1515
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1516
+ try {
1517
+ for(var _iterator = inputsToSign[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1518
+ var _step_value = _step.value, input = _step_value.input, index = _step_value.index;
1519
+ var sigHashType = getSigHashType(input, isTaproot);
1520
+ if (!allowedSighash.includes(sigHashType)) {
1521
+ throw new Error("Input ".concat(index, " declares sighash type ").concat(sigHashType, ", which is not in allowedSighash: ").concat(allowedSighash.join(', ') || '(empty)'));
1522
+ }
1523
+ }
1524
+ } catch (err) {
1525
+ _didIteratorError = true;
1526
+ _iteratorError = err;
1527
+ } finally{
1528
+ try {
1529
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1530
+ _iterator.return();
1531
+ }
1532
+ } finally{
1533
+ if (_didIteratorError) {
1534
+ throw _iteratorError;
1535
+ }
1536
+ }
1537
+ }
1538
+ };
1539
+
1309
1540
  function _instanceof(left, right) {
1310
1541
  if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
1311
1542
  return !!right[Symbol.hasInstance](left);
@@ -1392,9 +1623,13 @@ function _type_of(obj) {
1392
1623
  * Extracts sighashes from a PSBT for validation.
1393
1624
  * This is used to verify that the message being signed matches the PSBT context.
1394
1625
  *
1626
+ * P2WSH inputs whose witnessScript is absent yield `null` instead of a hash:
1627
+ * finalization strips witnessScript from completed inputs, so a co-signer's
1628
+ * already-finalized input must not block validation of the remaining inputs.
1629
+ *
1395
1630
  * @param psbtBase64 - PSBT in base64 format
1396
1631
  * @param network - 'mainnet' or 'testnet' or BitcoinNetwork enum (defaults to 'mainnet')
1397
- * @returns Array of sighash hex strings for each input
1632
+ * @returns Array of sighash hex strings, aligned by input index; `null` for inputs whose sighash cannot be derived
1398
1633
  */ var extractPsbtSighashes = function(psbtBase64) {
1399
1634
  var network = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 'mainnet';
1400
1635
  // Convert string network to BitcoinNetwork enum
@@ -1412,25 +1647,23 @@ function _type_of(obj) {
1412
1647
  for(var i = 0; i < psbt.inputCount; i++){
1413
1648
  var input = psbt.data.inputs[i];
1414
1649
  if (input.tapInternalKey) {
1415
- // Taproot (BIP-341) - uses hashForWitnessV1 with SIGHASH_DEFAULT
1416
- var hash = tx.hashForWitnessV1(i, prevOutScripts, values, bitcoin__namespace.Transaction.SIGHASH_DEFAULT);
1650
+ // Taproot (BIP-341) - uses hashForWitnessV1 with the input's declared
1651
+ // sighash type, defaulting to SIGHASH_DEFAULT
1652
+ var hash = tx.hashForWitnessV1(i, prevOutScripts, values, getSigHashType(input, true));
1417
1653
  sighashes.push(Buffer.from(hash).toString('hex'));
1418
- } else {
1419
- // Native SegWit (BIP-143) - uses hashForWitnessV0 with SIGHASH_ALL
1420
- // witnessUtxo is guaranteed to exist from collectPSBTInputData validation
1421
- var _input_witnessUtxo = input.witnessUtxo, script = _input_witnessUtxo.script, value = _input_witnessUtxo.value;
1422
- // Build P2PKH script code from the pubkey hash in the witness program
1423
- var p2pkh = bitcoin__namespace.payments.p2pkh({
1424
- hash: new Uint8Array(toBuffer(script).subarray(2)),
1425
- network: bitcoinNetwork
1426
- });
1427
- var scriptCode = p2pkh.output;
1428
- if (!scriptCode) {
1429
- throw new Error("Failed to generate scriptCode for input ".concat(i));
1430
- }
1431
- var hash1 = tx.hashForWitnessV0(i, scriptCode, value, bitcoin__namespace.Transaction.SIGHASH_ALL);
1432
- sighashes.push(Buffer.from(hash1).toString('hex'));
1654
+ continue;
1655
+ }
1656
+ // Native SegWit (BIP-143) - uses hashForWitnessV0 with the input's
1657
+ // declared sighash type, defaulting to SIGHASH_ALL
1658
+ // witnessUtxo is guaranteed to exist from collectPSBTInputData validation
1659
+ var _input_witnessUtxo = input.witnessUtxo, script = _input_witnessUtxo.script, value = _input_witnessUtxo.value;
1660
+ if (isP2wshOutputScript(script) && !input.witnessScript) {
1661
+ sighashes.push(null);
1662
+ continue;
1433
1663
  }
1664
+ var scriptCode = getSegwitV0ScriptCode(input, script, i, bitcoinNetwork);
1665
+ var hash1 = tx.hashForWitnessV0(i, scriptCode, value, getSigHashType(input, false));
1666
+ sighashes.push(Buffer.from(hash1).toString('hex'));
1434
1667
  }
1435
1668
  return sighashes;
1436
1669
  };
@@ -1470,6 +1703,7 @@ function _type_of(obj) {
1470
1703
  return Buffer.from(formattedMessage).toString('hex');
1471
1704
  };
1472
1705
 
1706
+ exports.assertSighashAllowed = assertSighashAllowed;
1473
1707
  exports.calculateBip322Hash = calculateBip322Hash;
1474
1708
  exports.calculateTaprootTweak = calculateTaprootTweak;
1475
1709
  exports.collectPSBTInputData = collectPSBTInputData;
@@ -1484,13 +1718,17 @@ exports.doesInputBelongToAddress = doesInputBelongToAddress;
1484
1718
  exports.encodeBip322Signature = encodeBip322Signature;
1485
1719
  exports.extractPsbtSighashes = extractPsbtSighashes;
1486
1720
  exports.extractPublicKeyHex = extractPublicKeyHex;
1721
+ exports.filterInputsBySigningIndexes = filterInputsBySigningIndexes;
1487
1722
  exports.getAddressTypeFromDerivationPath = getAddressTypeFromDerivationPath;
1488
1723
  exports.getBitcoinNetwork = getBitcoinNetwork;
1489
1724
  exports.getDefaultRpcUrl = getDefaultRpcUrl;
1490
1725
  exports.getFeeRates = getFeeRates;
1491
1726
  exports.getPublicKeyFromPrivateKey = getPublicKeyFromPrivateKey;
1727
+ exports.getSegwitV0ScriptCode = getSegwitV0ScriptCode;
1728
+ exports.getSigHashType = getSigHashType;
1492
1729
  exports.getUTXOs = getUTXOs;
1493
1730
  exports.initEccLib = initEccLib;
1731
+ exports.isP2wshOutputScript = isP2wshOutputScript;
1494
1732
  exports.normalizeForCompressed = normalizeForCompressed;
1495
1733
  exports.normalizeForTaproot = normalizeForTaproot;
1496
1734
  exports.normalizePublicKey = normalizePublicKey;
package/index.esm.js CHANGED
@@ -706,8 +706,12 @@ function _instanceof$3(left, right) {
706
706
  * Converts an ECDSA signature to DER format
707
707
  *
708
708
  * @param signature - The ECDSA signature
709
+ * @param sighashType - The sighash type to append as the DER trailing byte.
710
+ * Must match the type the signing hash was built with, or the signature will
711
+ * fail verification at finalize/broadcast. Defaults to SIGHASH_ALL.
709
712
  * @returns The DER encoded signature
710
713
  */ var convertSignatureToDER = function(signature) {
714
+ var sighashType = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : bitcoin.Transaction.SIGHASH_ALL;
711
715
  var r = _instanceof$3(signature.r, Uint8Array) ? signature.r : new Uint8Array(signature.r);
712
716
  var s = _instanceof$3(signature.s, Uint8Array) ? signature.s : new Uint8Array(signature.s);
713
717
  var r32 = new Uint8Array(32);
@@ -719,7 +723,7 @@ function _instanceof$3(left, right) {
719
723
  var rawSignature = new Uint8Array(64);
720
724
  rawSignature.set(r32, 0);
721
725
  rawSignature.set(s32, 32);
722
- var derSignature = bitcoin.script.signature.encode(rawSignature, bitcoin.Transaction.SIGHASH_ALL);
726
+ var derSignature = bitcoin.script.signature.encode(rawSignature, sighashType);
723
727
  return derSignature;
724
728
  };
725
729
 
@@ -1190,19 +1194,34 @@ function _instanceof$2(left, right) {
1190
1194
  * Converts a signature to a Buffer format suitable for Taproot (BIP340/Schnorr)
1191
1195
  *
1192
1196
  * @param signature - The signature from MPC (can be Uint8Array, Buffer, or EcdsaSignature object)
1193
- * @returns A Buffer containing the 64-byte Schnorr signature
1197
+ * @param sighashType - The sighash type the signing hash was built with. Per
1198
+ * BIP-341 the signature stays 64 bytes for SIGHASH_DEFAULT and gains the
1199
+ * sighash type as a 65th byte for any other type. Defaults to SIGHASH_DEFAULT.
1200
+ * @returns A Buffer containing the 64-byte (or 65-byte) Schnorr signature
1194
1201
  */ var convertSignatureToTaprootBuffer = function(signature) {
1202
+ var sighashType = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : bitcoin.Transaction.SIGHASH_DEFAULT;
1203
+ var schnorrSignature;
1195
1204
  if (_instanceof$2(signature, Uint8Array) || Buffer.isBuffer(signature)) {
1196
- return Buffer.from(signature);
1205
+ schnorrSignature = Buffer.from(signature);
1206
+ } else {
1207
+ var r = signature.r;
1208
+ var s = signature.s;
1209
+ var rBuf = Buffer.isBuffer(r) ? r : Buffer.from(r);
1210
+ var sBuf = Buffer.isBuffer(s) ? s : Buffer.from(s);
1211
+ // Safe: creates Uint8Array views over Buffer's underlying memory without copying
1212
+ schnorrSignature = Buffer.concat([
1213
+ new Uint8Array(rBuf),
1214
+ new Uint8Array(sBuf)
1215
+ ]);
1216
+ }
1217
+ if (sighashType === bitcoin.Transaction.SIGHASH_DEFAULT) {
1218
+ return schnorrSignature;
1197
1219
  }
1198
- var r = signature.r;
1199
- var s = signature.s;
1200
- var rBuf = Buffer.isBuffer(r) ? r : Buffer.from(r);
1201
- var sBuf = Buffer.isBuffer(s) ? s : Buffer.from(s);
1202
- // Safe: creates Uint8Array views over Buffer's underlying memory without copying
1203
1220
  return Buffer.concat([
1204
- new Uint8Array(rBuf),
1205
- new Uint8Array(sBuf)
1221
+ new Uint8Array(schnorrSignature),
1222
+ new Uint8Array([
1223
+ sighashType
1224
+ ])
1206
1225
  ]);
1207
1226
  };
1208
1227
 
@@ -1228,6 +1247,30 @@ function _instanceof$2(left, right) {
1228
1247
  };
1229
1248
  };
1230
1249
 
1250
+ /**
1251
+ * Checks if an output script (scriptPubKey) is P2WSH: OP_0 <32-byte sha256(witnessScript)>
1252
+ *
1253
+ * ArrayLike keeps this callable with Buffer or Uint8Array — the iframe build
1254
+ * compiles with browser typings where Buffer is not assignable to Uint8Array.
1255
+ * @param script - The output script to check
1256
+ * @returns True if the script has the P2WSH shape
1257
+ */ var isP2wshOutputScript = function(script) {
1258
+ return script.length === 34 && script[0] === 0x00 && script[1] === 0x20;
1259
+ };
1260
+
1261
+ /**
1262
+ * Constant-shape byte equality without Buffer — the iframe build compiles
1263
+ * this package with browser typings where Buffer is not assignable to
1264
+ * Uint8Array.
1265
+ * @param a - First byte array
1266
+ * @param b - Second byte array
1267
+ * @returns True if both arrays have identical length and contents
1268
+ */ var bytesEqual = function(a, b) {
1269
+ return a.length === b.length && a.every(function(byte, index) {
1270
+ return byte === b[index];
1271
+ });
1272
+ };
1273
+
1231
1274
  function _instanceof$1(left, right) {
1232
1275
  if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
1233
1276
  return !!right[Symbol.hasInstance](left);
@@ -1236,12 +1279,63 @@ function _instanceof$1(left, right) {
1236
1279
  }
1237
1280
  }
1238
1281
  /**
1239
- * Checks if a PSBT input belongs to a specific address
1282
+ * P2WSH ownership: the caller allowlisted the witnessScript, it hashes to the
1283
+ * scriptPubKey commitment, and it is a canonical m-of-n CHECKMULTISIG with
1284
+ * `publicKey` in a signing position.
1285
+ */ var matchesAllowedP2wshMultisig = function(input, script, publicKey, allowedWitnessScripts) {
1286
+ if (!publicKey || !input.witnessScript || !(allowedWitnessScripts === null || allowedWitnessScripts === void 0 ? void 0 : allowedWitnessScripts.length)) {
1287
+ return false;
1288
+ }
1289
+ var witnessScript = Uint8Array.from(input.witnessScript);
1290
+ // P2WSH co-signing is opt-in: the wallet only signs arrangements the
1291
+ // caller explicitly named in this request.
1292
+ var witnessScriptHex = Buffer.from(witnessScript).toString('hex');
1293
+ if (!allowedWitnessScripts.some(function(hex) {
1294
+ return hex.toLowerCase() === witnessScriptHex;
1295
+ })) {
1296
+ return false;
1297
+ }
1298
+ // The scriptPubKey commits to the witnessScript; a mismatch means the
1299
+ // PSBT is lying about the script this signature would authorize.
1300
+ if (!bytesEqual(sha256(witnessScript), Uint8Array.from(script).subarray(2))) {
1301
+ return false;
1302
+ }
1303
+ // p2ms throws unless the script is exactly OP_m <keys...> OP_n
1304
+ // OP_CHECKMULTISIG, so the key must occupy a signing position.
1305
+ var multisigPubkeys;
1306
+ try {
1307
+ multisigPubkeys = bitcoin.payments.p2ms({
1308
+ output: witnessScript
1309
+ }).pubkeys;
1310
+ } catch (e) {
1311
+ return false;
1312
+ }
1313
+ if (!multisigPubkeys) {
1314
+ return false;
1315
+ }
1316
+ var publicKeyBytes = Uint8Array.from(publicKey);
1317
+ return multisigPubkeys.some(function(key) {
1318
+ return bytesEqual(Uint8Array.from(key), publicKeyBytes);
1319
+ });
1320
+ };
1321
+ /**
1322
+ * Checks if a PSBT input belongs to a specific address.
1323
+ *
1324
+ * For P2WSH inputs address equality cannot work (the address commits to the
1325
+ * script, not our key), so ownership is opt-in and means ALL of: the caller
1326
+ * explicitly allowlisted the witnessScript, it hashes to the scriptPubKey
1327
+ * commitment, and it is a canonical m-of-n CHECKMULTISIG script with
1328
+ * `publicKey` in a signing position. Any other script shape is rejected even
1329
+ * if the key appears in it, so a hostile PSBT cannot obtain a signature over
1330
+ * an arbitrary script that merely name-drops the wallet key, and the wallet
1331
+ * never co-signs a multisig arrangement the caller did not name.
1240
1332
  * @param input - The PSBT input (from psbt.data.inputs)
1241
1333
  * @param address - The address to check against
1242
1334
  * @param network - The Bitcoin network
1243
- * @returns True if the input belongs to the address, false otherwise
1244
- */ var doesInputBelongToAddress = function(input, address, network) {
1335
+ * @param publicKey - The wallet's compressed ECDSA public key; required to match P2WSH inputs
1336
+ * @param allowedWitnessScripts - Hex-encoded witnessScripts the caller consents to co-sign; required to match P2WSH inputs
1337
+ * @returns True if the input belongs to the address (or public key, for P2WSH), false otherwise
1338
+ */ var doesInputBelongToAddress = function(input, address, network, publicKey, allowedWitnessScripts) {
1245
1339
  if (!input.witnessUtxo) {
1246
1340
  return false;
1247
1341
  }
@@ -1265,6 +1359,10 @@ function _instanceof$1(left, right) {
1265
1359
  }).address === address;
1266
1360
  });
1267
1361
  }
1362
+ // Try P2WSH - script is OP_0 <32-byte sha256(witnessScript)>
1363
+ if (isP2wshOutputScript(script)) {
1364
+ return matchesAllowedP2wshMultisig(input, script, publicKey, allowedWitnessScripts);
1365
+ }
1268
1366
  // Try P2TR (Taproot) - script is OP_1 <32-byte x-only pubkey>
1269
1367
  if (script.length === 34 && script[0] === 0x51 && script[1] === 0x20) {
1270
1368
  return networksToTry.some(function(bitcoinNetwork) {
@@ -1286,6 +1384,139 @@ function _instanceof$1(left, right) {
1286
1384
  }
1287
1385
  };
1288
1386
 
1387
+ /**
1388
+ * Resolves the BIP-143 scriptCode for a segwit v0 input. Shared by the signer
1389
+ * and the sighash-verification helper so both derive the identical digest.
1390
+ *
1391
+ * P2WSH inputs sign over the full witnessScript, verified against the
1392
+ * scriptPubKey commitment so a PSBT cannot substitute a script the UTXO does
1393
+ * not commit to. P2WPKH inputs sign over the implied P2PKH script.
1394
+ *
1395
+ * @param input - The PSBT input (from psbt.data.inputs)
1396
+ * @param script - The input's witnessUtxo scriptPubKey
1397
+ * @param index - The input index (for error messages)
1398
+ * @param bitcoinNetwork - The bitcoinjs-lib network for P2PKH reconstruction
1399
+ * @returns The scriptCode to feed hashForWitnessV0
1400
+ * @throws Error if a P2WSH input is missing its witnessScript, the witnessScript
1401
+ * does not hash to the scriptPubKey commitment, or scriptCode generation fails
1402
+ */ var getSegwitV0ScriptCode = function(input, script, index, bitcoinNetwork) {
1403
+ if (isP2wshOutputScript(script)) {
1404
+ if (!input.witnessScript) {
1405
+ throw new Error("Input ".concat(index, " is P2WSH but missing witnessScript"));
1406
+ }
1407
+ var witnessScript = Uint8Array.from(input.witnessScript);
1408
+ // The scriptPubKey commits to the witnessScript; refuse to compute a
1409
+ // sighash over a script the UTXO does not commit to.
1410
+ if (!bytesEqual(sha256(witnessScript), Uint8Array.from(script).subarray(2))) {
1411
+ throw new Error("Input ".concat(index, " witnessScript does not match the P2WSH scriptPubKey commitment"));
1412
+ }
1413
+ return witnessScript;
1414
+ }
1415
+ // Build P2PKH script code from the pubkey hash in the witness program
1416
+ var p2pkh = bitcoin.payments.p2pkh({
1417
+ hash: Uint8Array.from(script).subarray(2),
1418
+ network: bitcoinNetwork
1419
+ });
1420
+ if (!p2pkh.output) {
1421
+ throw new Error("Failed to generate scriptCode for input ".concat(index));
1422
+ }
1423
+ return p2pkh.output;
1424
+ };
1425
+
1426
+ /**
1427
+ * Restricts wallet-owned PSBT inputs to an explicitly requested subset.
1428
+ *
1429
+ * @param inputsToSign - Wallet-owned inputs, each carrying its PSBT index
1430
+ * @param signingIndexes - Optional subset of input indexes the caller wants signed
1431
+ * @returns The requested subset, or all inputs when signingIndexes is omitted/empty
1432
+ * @throws Error if signingIndexes references an input the wallet does not own
1433
+ */ var filterInputsBySigningIndexes = function(inputsToSign, signingIndexes) {
1434
+ if (!(signingIndexes === null || signingIndexes === void 0 ? void 0 : signingIndexes.length)) {
1435
+ return inputsToSign;
1436
+ }
1437
+ var walletOwnedIndexSet = new Set(inputsToSign.map(function(param) {
1438
+ var index = param.index;
1439
+ return index;
1440
+ }));
1441
+ var invalidIndexes = signingIndexes.filter(function(i) {
1442
+ return !walletOwnedIndexSet.has(i);
1443
+ });
1444
+ if (invalidIndexes.length > 0) {
1445
+ throw new Error("signingIndexes contains indexes that do not belong to the signing address: ".concat(invalidIndexes.join(', ')));
1446
+ }
1447
+ var requestedIndexSet = new Set(signingIndexes);
1448
+ return inputsToSign.filter(function(param) {
1449
+ var index = param.index;
1450
+ return requestedIndexSet.has(index);
1451
+ });
1452
+ };
1453
+
1454
+ /**
1455
+ * Resolves the sighash type for a PSBT input.
1456
+ *
1457
+ * The type is read from the PSBT itself (BIP-174 `PSBT_IN_SIGHASH_TYPE`), never
1458
+ * supplied by the caller — the signing hash and the policy layer's verification
1459
+ * hash must be derived from the same bytes, or every non-default signature
1460
+ * would be rejected as tampered.
1461
+ *
1462
+ * When the input declares nothing, falls back to the historical default:
1463
+ * SIGHASH_DEFAULT (0x00) for Taproot, SIGHASH_ALL (0x01) otherwise.
1464
+ *
1465
+ * @param input - The PSBT input to resolve the sighash type for
1466
+ * @param isTaproot - Whether the input is spent as Taproot. Defaults to
1467
+ * detecting `tapInternalKey`; pass explicitly when the caller already knows
1468
+ * which signing branch it is on, so the fallback matches the hash function
1469
+ * actually used.
1470
+ * @returns The sighash type to build and encode the signature with
1471
+ */ var getSigHashType = function(input) {
1472
+ var isTaproot = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : Boolean(input.tapInternalKey);
1473
+ var _input_sighashType;
1474
+ return (_input_sighashType = input.sighashType) !== null && _input_sighashType !== void 0 ? _input_sighashType : isTaproot ? bitcoin.Transaction.SIGHASH_DEFAULT : bitcoin.Transaction.SIGHASH_ALL;
1475
+ };
1476
+
1477
+ /**
1478
+ * Throws unless every input's PSBT-declared sighash type is in the allow-list.
1479
+ *
1480
+ * Call this before any signing begins — inputs are signed in parallel, so
1481
+ * throwing partway through would leave a partially signed PSBT behind.
1482
+ *
1483
+ * An empty array permits nothing rather than everything: a caller whose
1484
+ * allow-list computes to empty must not silently get the guard disabled. Omit
1485
+ * the parameter entirely to permit any declared type.
1486
+ *
1487
+ * @param inputsToSign - The wallet-owned inputs about to be signed, with their PSBT indexes
1488
+ * @param isTaproot - Whether signing takes the Taproot branch, so the fallback
1489
+ * sighash type matches the hash function actually used
1490
+ * @param allowedSighash - Optional allow-list of permitted sighash types
1491
+ */ var assertSighashAllowed = function(inputsToSign, isTaproot, allowedSighash) {
1492
+ if (!allowedSighash) {
1493
+ return;
1494
+ }
1495
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1496
+ try {
1497
+ for(var _iterator = inputsToSign[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1498
+ var _step_value = _step.value, input = _step_value.input, index = _step_value.index;
1499
+ var sigHashType = getSigHashType(input, isTaproot);
1500
+ if (!allowedSighash.includes(sigHashType)) {
1501
+ throw new Error("Input ".concat(index, " declares sighash type ").concat(sigHashType, ", which is not in allowedSighash: ").concat(allowedSighash.join(', ') || '(empty)'));
1502
+ }
1503
+ }
1504
+ } catch (err) {
1505
+ _didIteratorError = true;
1506
+ _iteratorError = err;
1507
+ } finally{
1508
+ try {
1509
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1510
+ _iterator.return();
1511
+ }
1512
+ } finally{
1513
+ if (_didIteratorError) {
1514
+ throw _iteratorError;
1515
+ }
1516
+ }
1517
+ }
1518
+ };
1519
+
1289
1520
  function _instanceof(left, right) {
1290
1521
  if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
1291
1522
  return !!right[Symbol.hasInstance](left);
@@ -1372,9 +1603,13 @@ function _type_of(obj) {
1372
1603
  * Extracts sighashes from a PSBT for validation.
1373
1604
  * This is used to verify that the message being signed matches the PSBT context.
1374
1605
  *
1606
+ * P2WSH inputs whose witnessScript is absent yield `null` instead of a hash:
1607
+ * finalization strips witnessScript from completed inputs, so a co-signer's
1608
+ * already-finalized input must not block validation of the remaining inputs.
1609
+ *
1375
1610
  * @param psbtBase64 - PSBT in base64 format
1376
1611
  * @param network - 'mainnet' or 'testnet' or BitcoinNetwork enum (defaults to 'mainnet')
1377
- * @returns Array of sighash hex strings for each input
1612
+ * @returns Array of sighash hex strings, aligned by input index; `null` for inputs whose sighash cannot be derived
1378
1613
  */ var extractPsbtSighashes = function(psbtBase64) {
1379
1614
  var network = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 'mainnet';
1380
1615
  // Convert string network to BitcoinNetwork enum
@@ -1392,25 +1627,23 @@ function _type_of(obj) {
1392
1627
  for(var i = 0; i < psbt.inputCount; i++){
1393
1628
  var input = psbt.data.inputs[i];
1394
1629
  if (input.tapInternalKey) {
1395
- // Taproot (BIP-341) - uses hashForWitnessV1 with SIGHASH_DEFAULT
1396
- var hash = tx.hashForWitnessV1(i, prevOutScripts, values, bitcoin.Transaction.SIGHASH_DEFAULT);
1630
+ // Taproot (BIP-341) - uses hashForWitnessV1 with the input's declared
1631
+ // sighash type, defaulting to SIGHASH_DEFAULT
1632
+ var hash = tx.hashForWitnessV1(i, prevOutScripts, values, getSigHashType(input, true));
1397
1633
  sighashes.push(Buffer.from(hash).toString('hex'));
1398
- } else {
1399
- // Native SegWit (BIP-143) - uses hashForWitnessV0 with SIGHASH_ALL
1400
- // witnessUtxo is guaranteed to exist from collectPSBTInputData validation
1401
- var _input_witnessUtxo = input.witnessUtxo, script = _input_witnessUtxo.script, value = _input_witnessUtxo.value;
1402
- // Build P2PKH script code from the pubkey hash in the witness program
1403
- var p2pkh = bitcoin.payments.p2pkh({
1404
- hash: new Uint8Array(toBuffer(script).subarray(2)),
1405
- network: bitcoinNetwork
1406
- });
1407
- var scriptCode = p2pkh.output;
1408
- if (!scriptCode) {
1409
- throw new Error("Failed to generate scriptCode for input ".concat(i));
1410
- }
1411
- var hash1 = tx.hashForWitnessV0(i, scriptCode, value, bitcoin.Transaction.SIGHASH_ALL);
1412
- sighashes.push(Buffer.from(hash1).toString('hex'));
1634
+ continue;
1635
+ }
1636
+ // Native SegWit (BIP-143) - uses hashForWitnessV0 with the input's
1637
+ // declared sighash type, defaulting to SIGHASH_ALL
1638
+ // witnessUtxo is guaranteed to exist from collectPSBTInputData validation
1639
+ var _input_witnessUtxo = input.witnessUtxo, script = _input_witnessUtxo.script, value = _input_witnessUtxo.value;
1640
+ if (isP2wshOutputScript(script) && !input.witnessScript) {
1641
+ sighashes.push(null);
1642
+ continue;
1413
1643
  }
1644
+ var scriptCode = getSegwitV0ScriptCode(input, script, i, bitcoinNetwork);
1645
+ var hash1 = tx.hashForWitnessV0(i, scriptCode, value, getSigHashType(input, false));
1646
+ sighashes.push(Buffer.from(hash1).toString('hex'));
1414
1647
  }
1415
1648
  return sighashes;
1416
1649
  };
@@ -1450,4 +1683,4 @@ function _type_of(obj) {
1450
1683
  return Buffer.from(formattedMessage).toString('hex');
1451
1684
  };
1452
1685
 
1453
- export { calculateBip322Hash, calculateTaprootTweak, collectPSBTInputData, computeBip322HashHex, convertSignatureToDER, convertSignatureToTaprootBuffer, createLegacyAddress, createNativeSegWitAddress, createSegWitAddress, createTaprootAddress, doesInputBelongToAddress, encodeBip322Signature, extractPsbtSighashes, extractPublicKeyHex, getAddressTypeFromDerivationPath, getBitcoinNetwork, getDefaultRpcUrl, getFeeRates, getPublicKeyFromPrivateKey, getUTXOs, initEccLib, normalizeForCompressed, normalizeForTaproot, normalizePublicKey, privateKeyToWIF, publicKeyToBitcoinAddress, selectUTXOs, toBitcoinNetwork, toBuffer, wifToPrivateKey };
1686
+ export { assertSighashAllowed, calculateBip322Hash, calculateTaprootTweak, collectPSBTInputData, computeBip322HashHex, convertSignatureToDER, convertSignatureToTaprootBuffer, createLegacyAddress, createNativeSegWitAddress, createSegWitAddress, createTaprootAddress, doesInputBelongToAddress, encodeBip322Signature, extractPsbtSighashes, extractPublicKeyHex, filterInputsBySigningIndexes, getAddressTypeFromDerivationPath, getBitcoinNetwork, getDefaultRpcUrl, getFeeRates, getPublicKeyFromPrivateKey, getSegwitV0ScriptCode, getSigHashType, getUTXOs, initEccLib, isP2wshOutputScript, normalizeForCompressed, normalizeForTaproot, normalizePublicKey, privateKeyToWIF, publicKeyToBitcoinAddress, selectUTXOs, toBitcoinNetwork, toBuffer, wifToPrivateKey };
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@dynamic-labs-wallet/btc-utils",
3
- "version": "1.0.105",
3
+ "version": "1.0.107",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "dependencies": {
8
- "@dynamic-labs-wallet/core": "1.0.105",
8
+ "@dynamic-labs-wallet/core": "1.0.107",
9
9
  "bitcoinjs-lib": "^7.0.0",
10
10
  "bip322-js": "^3.0.0",
11
11
  "@noble/hashes": "1.7.1",
@@ -0,0 +1,21 @@
1
+ import type * as bitcoin from 'bitcoinjs-lib';
2
+ /**
3
+ * Throws unless every input's PSBT-declared sighash type is in the allow-list.
4
+ *
5
+ * Call this before any signing begins — inputs are signed in parallel, so
6
+ * throwing partway through would leave a partially signed PSBT behind.
7
+ *
8
+ * An empty array permits nothing rather than everything: a caller whose
9
+ * allow-list computes to empty must not silently get the guard disabled. Omit
10
+ * the parameter entirely to permit any declared type.
11
+ *
12
+ * @param inputsToSign - The wallet-owned inputs about to be signed, with their PSBT indexes
13
+ * @param isTaproot - Whether signing takes the Taproot branch, so the fallback
14
+ * sighash type matches the hash function actually used
15
+ * @param allowedSighash - Optional allow-list of permitted sighash types
16
+ */
17
+ export declare const assertSighashAllowed: (inputsToSign: {
18
+ input: bitcoin.Psbt["data"]["inputs"][number];
19
+ index: number;
20
+ }[], isTaproot: boolean, allowedSighash?: number[]) => void;
21
+ //# sourceMappingURL=assertSighashAllowed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertSighashAllowed.d.ts","sourceRoot":"","sources":["../../src/assertSighashAllowed/assertSighashAllowed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,eAAe,CAAC;AAG9C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,iBACjB;IAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,aACrE,OAAO,mBACD,MAAM,EAAE,KACxB,IAgBF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { assertSighashAllowed } from './assertSighashAllowed.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/assertSighashAllowed/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Constant-shape byte equality without Buffer — the iframe build compiles
3
+ * this package with browser typings where Buffer is not assignable to
4
+ * Uint8Array.
5
+ * @param a - First byte array
6
+ * @param b - Second byte array
7
+ * @returns True if both arrays have identical length and contents
8
+ */
9
+ export declare const bytesEqual: (a: Uint8Array, b: Uint8Array) => boolean;
10
+ //# sourceMappingURL=bytesEqual.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bytesEqual.d.ts","sourceRoot":"","sources":["../../src/bytesEqual/bytesEqual.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,MAAO,UAAU,KAAK,UAAU,KAAG,OACY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { bytesEqual } from './bytesEqual.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bytesEqual/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
@@ -3,7 +3,10 @@ import type { EcdsaSignature } from '#internal/core';
3
3
  * Converts an ECDSA signature to DER format
4
4
  *
5
5
  * @param signature - The ECDSA signature
6
+ * @param sighashType - The sighash type to append as the DER trailing byte.
7
+ * Must match the type the signing hash was built with, or the signature will
8
+ * fail verification at finalize/broadcast. Defaults to SIGHASH_ALL.
6
9
  * @returns The DER encoded signature
7
10
  */
8
- export declare const convertSignatureToDER: (signature: EcdsaSignature) => Uint8Array;
11
+ export declare const convertSignatureToDER: (signature: EcdsaSignature, sighashType?: number) => Uint8Array;
9
12
  //# sourceMappingURL=convertSignatureToDER.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"convertSignatureToDER.d.ts","sourceRoot":"","sources":["../../src/convertSignatureToDER/convertSignatureToDER.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,cAAe,cAAc,eAmB9D,CAAC"}
1
+ {"version":3,"file":"convertSignatureToDER.d.ts","sourceRoot":"","sources":["../../src/convertSignatureToDER/convertSignatureToDER.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,cACrB,cAAc,gBACZ,MAAM,eAoBpB,CAAC"}
@@ -3,7 +3,10 @@ import type { EcdsaSignature } from '#internal/core';
3
3
  * Converts a signature to a Buffer format suitable for Taproot (BIP340/Schnorr)
4
4
  *
5
5
  * @param signature - The signature from MPC (can be Uint8Array, Buffer, or EcdsaSignature object)
6
- * @returns A Buffer containing the 64-byte Schnorr signature
6
+ * @param sighashType - The sighash type the signing hash was built with. Per
7
+ * BIP-341 the signature stays 64 bytes for SIGHASH_DEFAULT and gains the
8
+ * sighash type as a 65th byte for any other type. Defaults to SIGHASH_DEFAULT.
9
+ * @returns A Buffer containing the 64-byte (or 65-byte) Schnorr signature
7
10
  */
8
- export declare const convertSignatureToTaprootBuffer: (signature: EcdsaSignature | Uint8Array | Buffer) => Buffer;
11
+ export declare const convertSignatureToTaprootBuffer: (signature: EcdsaSignature | Uint8Array | Buffer, sighashType?: number) => Buffer;
9
12
  //# sourceMappingURL=convertSignatureToTaprootBuffer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"convertSignatureToTaprootBuffer.d.ts","sourceRoot":"","sources":["../../src/convertSignatureToTaprootBuffer/convertSignatureToTaprootBuffer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,cAAe,cAAc,GAAG,UAAU,GAAG,MAAM,KAAG,MAWjG,CAAC"}
1
+ {"version":3,"file":"convertSignatureToTaprootBuffer.d.ts","sourceRoot":"","sources":["../../src/convertSignatureToTaprootBuffer/convertSignatureToTaprootBuffer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD;;;;;;;;GAQG;AACH,eAAO,MAAM,+BAA+B,cAC/B,cAAc,GAAG,UAAU,GAAG,MAAM,gBAClC,MAAM,KAClB,MAmBF,CAAC"}
@@ -1,11 +1,22 @@
1
1
  import type { Psbt } from 'bitcoinjs-lib';
2
2
  import { BitcoinNetwork } from '@dynamic-labs-wallet/core';
3
3
  /**
4
- * Checks if a PSBT input belongs to a specific address
4
+ * Checks if a PSBT input belongs to a specific address.
5
+ *
6
+ * For P2WSH inputs address equality cannot work (the address commits to the
7
+ * script, not our key), so ownership is opt-in and means ALL of: the caller
8
+ * explicitly allowlisted the witnessScript, it hashes to the scriptPubKey
9
+ * commitment, and it is a canonical m-of-n CHECKMULTISIG script with
10
+ * `publicKey` in a signing position. Any other script shape is rejected even
11
+ * if the key appears in it, so a hostile PSBT cannot obtain a signature over
12
+ * an arbitrary script that merely name-drops the wallet key, and the wallet
13
+ * never co-signs a multisig arrangement the caller did not name.
5
14
  * @param input - The PSBT input (from psbt.data.inputs)
6
15
  * @param address - The address to check against
7
16
  * @param network - The Bitcoin network
8
- * @returns True if the input belongs to the address, false otherwise
17
+ * @param publicKey - The wallet's compressed ECDSA public key; required to match P2WSH inputs
18
+ * @param allowedWitnessScripts - Hex-encoded witnessScripts the caller consents to co-sign; required to match P2WSH inputs
19
+ * @returns True if the input belongs to the address (or public key, for P2WSH), false otherwise
9
20
  */
10
- export declare const doesInputBelongToAddress: (input: Psbt["data"]["inputs"][number], address: string, network: BitcoinNetwork) => boolean;
21
+ export declare const doesInputBelongToAddress: (input: Psbt["data"]["inputs"][number], address: string, network: BitcoinNetwork, publicKey?: ArrayLike<number>, allowedWitnessScripts?: string[]) => boolean;
11
22
  //# sourceMappingURL=doesInputBelongToAddress.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"doesInputBelongToAddress.d.ts","sourceRoot":"","sources":["../../src/doesInputBelongToAddress/doesInputBelongToAddress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,UAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAC5B,MAAM,WACN,cAAc,KACtB,OAkDF,CAAC"}
1
+ {"version":3,"file":"doesInputBelongToAddress.d.ts","sourceRoot":"","sources":["../../src/doesInputBelongToAddress/doesInputBelongToAddress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAmD3D;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,wBAAwB,UAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAC5B,MAAM,WACN,cAAc,cACX,SAAS,CAAC,MAAM,CAAC,0BACL,MAAM,EAAE,KAC/B,OAuDF,CAAC"}
@@ -3,9 +3,13 @@ import type { BitcoinNetwork } from '@dynamic-labs-wallet/core';
3
3
  * Extracts sighashes from a PSBT for validation.
4
4
  * This is used to verify that the message being signed matches the PSBT context.
5
5
  *
6
+ * P2WSH inputs whose witnessScript is absent yield `null` instead of a hash:
7
+ * finalization strips witnessScript from completed inputs, so a co-signer's
8
+ * already-finalized input must not block validation of the remaining inputs.
9
+ *
6
10
  * @param psbtBase64 - PSBT in base64 format
7
11
  * @param network - 'mainnet' or 'testnet' or BitcoinNetwork enum (defaults to 'mainnet')
8
- * @returns Array of sighash hex strings for each input
12
+ * @returns Array of sighash hex strings, aligned by input index; `null` for inputs whose sighash cannot be derived
9
13
  */
10
- export declare const extractPsbtSighashes: (psbtBase64: string, network?: BitcoinNetwork | "mainnet" | "testnet") => string[];
14
+ export declare const extractPsbtSighashes: (psbtBase64: string, network?: BitcoinNetwork | "mainnet" | "testnet") => (string | null)[];
11
15
  //# sourceMappingURL=extractPsbtSighashes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extractPsbtSighashes.d.ts","sourceRoot":"","sources":["../../src/extractPsbtSighashes/extractPsbtSighashes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAMhE;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,eACnB,MAAM,YACT,cAAc,GAAG,SAAS,GAAG,SAAS,KAC9C,MAAM,EA4CR,CAAC"}
1
+ {"version":3,"file":"extractPsbtSighashes.d.ts","sourceRoot":"","sources":["../../src/extractPsbtSighashes/extractPsbtSighashes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQhE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,eACnB,MAAM,YACT,cAAc,GAAG,SAAS,GAAG,SAAS,KAC9C,CAAC,MAAM,GAAG,IAAI,CAAC,EA2CjB,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Restricts wallet-owned PSBT inputs to an explicitly requested subset.
3
+ *
4
+ * @param inputsToSign - Wallet-owned inputs, each carrying its PSBT index
5
+ * @param signingIndexes - Optional subset of input indexes the caller wants signed
6
+ * @returns The requested subset, or all inputs when signingIndexes is omitted/empty
7
+ * @throws Error if signingIndexes references an input the wallet does not own
8
+ */
9
+ export declare const filterInputsBySigningIndexes: <T extends {
10
+ index: number;
11
+ }>(inputsToSign: T[], signingIndexes?: number[]) => T[];
12
+ //# sourceMappingURL=filterInputsBySigningIndexes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filterInputsBySigningIndexes.d.ts","sourceRoot":"","sources":["../../src/filterInputsBySigningIndexes/filterInputsBySigningIndexes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,GAAI,CAAC,SAAS;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,gBACxD,CAAC,EAAE,mBACA,MAAM,EAAE,KACxB,CAAC,EAeH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { filterInputsBySigningIndexes } from './filterInputsBySigningIndexes.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/filterInputsBySigningIndexes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC"}
@@ -0,0 +1,20 @@
1
+ import * as bitcoin from 'bitcoinjs-lib';
2
+ import type { Psbt } from 'bitcoinjs-lib';
3
+ /**
4
+ * Resolves the BIP-143 scriptCode for a segwit v0 input. Shared by the signer
5
+ * and the sighash-verification helper so both derive the identical digest.
6
+ *
7
+ * P2WSH inputs sign over the full witnessScript, verified against the
8
+ * scriptPubKey commitment so a PSBT cannot substitute a script the UTXO does
9
+ * not commit to. P2WPKH inputs sign over the implied P2PKH script.
10
+ *
11
+ * @param input - The PSBT input (from psbt.data.inputs)
12
+ * @param script - The input's witnessUtxo scriptPubKey
13
+ * @param index - The input index (for error messages)
14
+ * @param bitcoinNetwork - The bitcoinjs-lib network for P2PKH reconstruction
15
+ * @returns The scriptCode to feed hashForWitnessV0
16
+ * @throws Error if a P2WSH input is missing its witnessScript, the witnessScript
17
+ * does not hash to the scriptPubKey commitment, or scriptCode generation fails
18
+ */
19
+ export declare const getSegwitV0ScriptCode: (input: Psbt["data"]["inputs"][number], script: ArrayLike<number>, index: number, bitcoinNetwork: bitcoin.networks.Network) => Uint8Array;
20
+ //# sourceMappingURL=getSegwitV0ScriptCode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSegwitV0ScriptCode.d.ts","sourceRoot":"","sources":["../../src/getSegwitV0ScriptCode/getSegwitV0ScriptCode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAK1C;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,qBAAqB,UACzB,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAC7B,SAAS,CAAC,MAAM,CAAC,SAClB,MAAM,kBACG,OAAO,CAAC,QAAQ,CAAC,OAAO,KACvC,UAyBF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { getSegwitV0ScriptCode } from './getSegwitV0ScriptCode.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/getSegwitV0ScriptCode/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,21 @@
1
+ import * as bitcoin from 'bitcoinjs-lib';
2
+ /**
3
+ * Resolves the sighash type for a PSBT input.
4
+ *
5
+ * The type is read from the PSBT itself (BIP-174 `PSBT_IN_SIGHASH_TYPE`), never
6
+ * supplied by the caller — the signing hash and the policy layer's verification
7
+ * hash must be derived from the same bytes, or every non-default signature
8
+ * would be rejected as tampered.
9
+ *
10
+ * When the input declares nothing, falls back to the historical default:
11
+ * SIGHASH_DEFAULT (0x00) for Taproot, SIGHASH_ALL (0x01) otherwise.
12
+ *
13
+ * @param input - The PSBT input to resolve the sighash type for
14
+ * @param isTaproot - Whether the input is spent as Taproot. Defaults to
15
+ * detecting `tapInternalKey`; pass explicitly when the caller already knows
16
+ * which signing branch it is on, so the fallback matches the hash function
17
+ * actually used.
18
+ * @returns The sighash type to build and encode the signature with
19
+ */
20
+ export declare const getSigHashType: (input: bitcoin.Psbt["data"]["inputs"][number], isTaproot?: boolean) => number;
21
+ //# sourceMappingURL=getSigHashType.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSigHashType.d.ts","sourceRoot":"","sources":["../../src/getSigHashType/getSigHashType.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,eAAe,CAAC;AAEzC;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,cAAc,UAClB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,0BAE5C,MAAkH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { getSigHashType } from './getSigHashType.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/getSigHashType/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
package/src/index.d.ts CHANGED
@@ -15,7 +15,12 @@ export { calculateTaprootTweak } from './calculateTaprootTweak/index.js';
15
15
  export { convertSignatureToTaprootBuffer } from './convertSignatureToTaprootBuffer/index.js';
16
16
  export { collectPSBTInputData } from './collectPSBTInputData/index.js';
17
17
  export { doesInputBelongToAddress } from './doesInputBelongToAddress/index.js';
18
+ export { isP2wshOutputScript } from './isP2wshOutputScript/index.js';
19
+ export { getSegwitV0ScriptCode } from './getSegwitV0ScriptCode/index.js';
20
+ export { filterInputsBySigningIndexes } from './filterInputsBySigningIndexes/index.js';
18
21
  export { getBitcoinNetwork } from './getBitcoinNetwork/index.js';
22
+ export { getSigHashType } from './getSigHashType/index.js';
23
+ export { assertSighashAllowed } from './assertSighashAllowed/index.js';
19
24
  export { initEccLib } from './initEccLib/index.js';
20
25
  export { extractPublicKeyHex } from './extractPublicKeyHex/index.js';
21
26
  export type { UTXO } from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../packages/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gCAAgC,EAAE,MAAM,6CAA6C,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,+BAA+B,EAAE,MAAM,4CAA4C,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAG/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../packages/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gCAAgC,EAAE,MAAM,6CAA6C,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,+BAA+B,EAAE,MAAM,4CAA4C,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAG/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { isP2wshOutputScript } from './isP2wshOutputScript.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/isP2wshOutputScript/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Checks if an output script (scriptPubKey) is P2WSH: OP_0 <32-byte sha256(witnessScript)>
3
+ *
4
+ * ArrayLike keeps this callable with Buffer or Uint8Array — the iframe build
5
+ * compiles with browser typings where Buffer is not assignable to Uint8Array.
6
+ * @param script - The output script to check
7
+ * @returns True if the script has the P2WSH shape
8
+ */
9
+ export declare const isP2wshOutputScript: (script: ArrayLike<number>) => boolean;
10
+ //# sourceMappingURL=isP2wshOutputScript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isP2wshOutputScript.d.ts","sourceRoot":"","sources":["../../src/isP2wshOutputScript/isP2wshOutputScript.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,WAAY,SAAS,CAAC,MAAM,CAAC,KAAG,OACE,CAAC"}