@dynamic-labs-wallet/btc-utils 1.0.106 → 1.0.108

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/index.cjs CHANGED
@@ -1267,6 +1267,30 @@ function _instanceof$2(left, right) {
1267
1267
  };
1268
1268
  };
1269
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
+
1270
1294
  function _instanceof$1(left, right) {
1271
1295
  if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
1272
1296
  return !!right[Symbol.hasInstance](left);
@@ -1275,12 +1299,63 @@ function _instanceof$1(left, right) {
1275
1299
  }
1276
1300
  }
1277
1301
  /**
1278
- * 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.
1279
1352
  * @param input - The PSBT input (from psbt.data.inputs)
1280
1353
  * @param address - The address to check against
1281
1354
  * @param network - The Bitcoin network
1282
- * @returns True if the input belongs to the address, false otherwise
1283
- */ 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) {
1284
1359
  if (!input.witnessUtxo) {
1285
1360
  return false;
1286
1361
  }
@@ -1304,6 +1379,10 @@ function _instanceof$1(left, right) {
1304
1379
  }).address === address;
1305
1380
  });
1306
1381
  }
1382
+ // Try P2WSH - script is OP_0 <32-byte sha256(witnessScript)>
1383
+ if (isP2wshOutputScript(script)) {
1384
+ return matchesAllowedP2wshMultisig(input, script, publicKey, allowedWitnessScripts);
1385
+ }
1307
1386
  // Try P2TR (Taproot) - script is OP_1 <32-byte x-only pubkey>
1308
1387
  if (script.length === 34 && script[0] === 0x51 && script[1] === 0x20) {
1309
1388
  return networksToTry.some(function(bitcoinNetwork) {
@@ -1325,6 +1404,73 @@ function _instanceof$1(left, right) {
1325
1404
  }
1326
1405
  };
1327
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
+
1328
1474
  /**
1329
1475
  * Resolves the sighash type for a PSBT input.
1330
1476
  *
@@ -1477,9 +1623,13 @@ function _type_of(obj) {
1477
1623
  * Extracts sighashes from a PSBT for validation.
1478
1624
  * This is used to verify that the message being signed matches the PSBT context.
1479
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
+ *
1480
1630
  * @param psbtBase64 - PSBT in base64 format
1481
1631
  * @param network - 'mainnet' or 'testnet' or BitcoinNetwork enum (defaults to 'mainnet')
1482
- * @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
1483
1633
  */ var extractPsbtSighashes = function(psbtBase64) {
1484
1634
  var network = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 'mainnet';
1485
1635
  // Convert string network to BitcoinNetwork enum
@@ -1501,23 +1651,19 @@ function _type_of(obj) {
1501
1651
  // sighash type, defaulting to SIGHASH_DEFAULT
1502
1652
  var hash = tx.hashForWitnessV1(i, prevOutScripts, values, getSigHashType(input, true));
1503
1653
  sighashes.push(Buffer.from(hash).toString('hex'));
1504
- } else {
1505
- // Native SegWit (BIP-143) - uses hashForWitnessV0 with the input's
1506
- // declared sighash type, defaulting to SIGHASH_ALL
1507
- // witnessUtxo is guaranteed to exist from collectPSBTInputData validation
1508
- var _input_witnessUtxo = input.witnessUtxo, script = _input_witnessUtxo.script, value = _input_witnessUtxo.value;
1509
- // Build P2PKH script code from the pubkey hash in the witness program
1510
- var p2pkh = bitcoin__namespace.payments.p2pkh({
1511
- hash: new Uint8Array(toBuffer(script).subarray(2)),
1512
- network: bitcoinNetwork
1513
- });
1514
- var scriptCode = p2pkh.output;
1515
- if (!scriptCode) {
1516
- throw new Error("Failed to generate scriptCode for input ".concat(i));
1517
- }
1518
- var hash1 = tx.hashForWitnessV0(i, scriptCode, value, getSigHashType(input, false));
1519
- 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;
1520
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'));
1521
1667
  }
1522
1668
  return sighashes;
1523
1669
  };
@@ -1572,14 +1718,17 @@ exports.doesInputBelongToAddress = doesInputBelongToAddress;
1572
1718
  exports.encodeBip322Signature = encodeBip322Signature;
1573
1719
  exports.extractPsbtSighashes = extractPsbtSighashes;
1574
1720
  exports.extractPublicKeyHex = extractPublicKeyHex;
1721
+ exports.filterInputsBySigningIndexes = filterInputsBySigningIndexes;
1575
1722
  exports.getAddressTypeFromDerivationPath = getAddressTypeFromDerivationPath;
1576
1723
  exports.getBitcoinNetwork = getBitcoinNetwork;
1577
1724
  exports.getDefaultRpcUrl = getDefaultRpcUrl;
1578
1725
  exports.getFeeRates = getFeeRates;
1579
1726
  exports.getPublicKeyFromPrivateKey = getPublicKeyFromPrivateKey;
1727
+ exports.getSegwitV0ScriptCode = getSegwitV0ScriptCode;
1580
1728
  exports.getSigHashType = getSigHashType;
1581
1729
  exports.getUTXOs = getUTXOs;
1582
1730
  exports.initEccLib = initEccLib;
1731
+ exports.isP2wshOutputScript = isP2wshOutputScript;
1583
1732
  exports.normalizeForCompressed = normalizeForCompressed;
1584
1733
  exports.normalizeForTaproot = normalizeForTaproot;
1585
1734
  exports.normalizePublicKey = normalizePublicKey;
package/index.esm.js CHANGED
@@ -1247,6 +1247,30 @@ function _instanceof$2(left, right) {
1247
1247
  };
1248
1248
  };
1249
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
+
1250
1274
  function _instanceof$1(left, right) {
1251
1275
  if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
1252
1276
  return !!right[Symbol.hasInstance](left);
@@ -1255,12 +1279,63 @@ function _instanceof$1(left, right) {
1255
1279
  }
1256
1280
  }
1257
1281
  /**
1258
- * 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.
1259
1332
  * @param input - The PSBT input (from psbt.data.inputs)
1260
1333
  * @param address - The address to check against
1261
1334
  * @param network - The Bitcoin network
1262
- * @returns True if the input belongs to the address, false otherwise
1263
- */ 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) {
1264
1339
  if (!input.witnessUtxo) {
1265
1340
  return false;
1266
1341
  }
@@ -1284,6 +1359,10 @@ function _instanceof$1(left, right) {
1284
1359
  }).address === address;
1285
1360
  });
1286
1361
  }
1362
+ // Try P2WSH - script is OP_0 <32-byte sha256(witnessScript)>
1363
+ if (isP2wshOutputScript(script)) {
1364
+ return matchesAllowedP2wshMultisig(input, script, publicKey, allowedWitnessScripts);
1365
+ }
1287
1366
  // Try P2TR (Taproot) - script is OP_1 <32-byte x-only pubkey>
1288
1367
  if (script.length === 34 && script[0] === 0x51 && script[1] === 0x20) {
1289
1368
  return networksToTry.some(function(bitcoinNetwork) {
@@ -1305,6 +1384,73 @@ function _instanceof$1(left, right) {
1305
1384
  }
1306
1385
  };
1307
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
+
1308
1454
  /**
1309
1455
  * Resolves the sighash type for a PSBT input.
1310
1456
  *
@@ -1457,9 +1603,13 @@ function _type_of(obj) {
1457
1603
  * Extracts sighashes from a PSBT for validation.
1458
1604
  * This is used to verify that the message being signed matches the PSBT context.
1459
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
+ *
1460
1610
  * @param psbtBase64 - PSBT in base64 format
1461
1611
  * @param network - 'mainnet' or 'testnet' or BitcoinNetwork enum (defaults to 'mainnet')
1462
- * @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
1463
1613
  */ var extractPsbtSighashes = function(psbtBase64) {
1464
1614
  var network = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 'mainnet';
1465
1615
  // Convert string network to BitcoinNetwork enum
@@ -1481,23 +1631,19 @@ function _type_of(obj) {
1481
1631
  // sighash type, defaulting to SIGHASH_DEFAULT
1482
1632
  var hash = tx.hashForWitnessV1(i, prevOutScripts, values, getSigHashType(input, true));
1483
1633
  sighashes.push(Buffer.from(hash).toString('hex'));
1484
- } else {
1485
- // Native SegWit (BIP-143) - uses hashForWitnessV0 with the input's
1486
- // declared sighash type, defaulting to SIGHASH_ALL
1487
- // witnessUtxo is guaranteed to exist from collectPSBTInputData validation
1488
- var _input_witnessUtxo = input.witnessUtxo, script = _input_witnessUtxo.script, value = _input_witnessUtxo.value;
1489
- // Build P2PKH script code from the pubkey hash in the witness program
1490
- var p2pkh = bitcoin.payments.p2pkh({
1491
- hash: new Uint8Array(toBuffer(script).subarray(2)),
1492
- network: bitcoinNetwork
1493
- });
1494
- var scriptCode = p2pkh.output;
1495
- if (!scriptCode) {
1496
- throw new Error("Failed to generate scriptCode for input ".concat(i));
1497
- }
1498
- var hash1 = tx.hashForWitnessV0(i, scriptCode, value, getSigHashType(input, false));
1499
- 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;
1500
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'));
1501
1647
  }
1502
1648
  return sighashes;
1503
1649
  };
@@ -1537,4 +1683,4 @@ function _type_of(obj) {
1537
1683
  return Buffer.from(formattedMessage).toString('hex');
1538
1684
  };
1539
1685
 
1540
- export { assertSighashAllowed, calculateBip322Hash, calculateTaprootTweak, collectPSBTInputData, computeBip322HashHex, convertSignatureToDER, convertSignatureToTaprootBuffer, createLegacyAddress, createNativeSegWitAddress, createSegWitAddress, createTaprootAddress, doesInputBelongToAddress, encodeBip322Signature, extractPsbtSighashes, extractPublicKeyHex, getAddressTypeFromDerivationPath, getBitcoinNetwork, getDefaultRpcUrl, getFeeRates, getPublicKeyFromPrivateKey, getSigHashType, 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.106",
3
+ "version": "1.0.108",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "dependencies": {
8
- "@dynamic-labs-wallet/core": "1.0.106",
8
+ "@dynamic-labs-wallet/core": "1.0.108",
9
9
  "bitcoinjs-lib": "^7.0.0",
10
10
  "bip322-js": "^3.0.0",
11
11
  "@noble/hashes": "1.7.1",
@@ -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"}
@@ -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;AAOhE;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,eACnB,MAAM,YACT,cAAc,GAAG,SAAS,GAAG,SAAS,KAC9C,MAAM,EA8CR,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"}
package/src/index.d.ts CHANGED
@@ -15,6 +15,9 @@ 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';
19
22
  export { getSigHashType } from './getSigHashType/index.js';
20
23
  export { assertSighashAllowed } from './assertSighashAllowed/index.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,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"}
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"}