@notabene/verify-proof 1.12.0-next.4 → 1.12.0-next.6

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.
@@ -79,7 +79,11 @@ async function verifyBTCSignature(proof) {
79
79
  return verifyBIP137(address, proof, chainConfig);
80
80
  }
81
81
  if (chainConfig.isTestnet) {
82
- return verifyBIP322(address, proof);
82
+ try {
83
+ return verifyBIP322(address, proof);
84
+ } catch {
85
+ return { ...proof, status: ProofStatus.FAILED };
86
+ }
83
87
  }
84
88
  const isTaproot = address.startsWith("bc1p") || address.startsWith("tb1p");
85
89
  if (isTaproot && proof.type === ProofTypes.BIP137) {
@@ -123,7 +127,7 @@ function getChainConfig(address) {
123
127
  if (address.startsWith("q")) {
124
128
  return CHAIN_CONFIGS["bitcoincash"];
125
129
  }
126
- if (address.startsWith("tb1")) {
130
+ if (address.startsWith("m") || address.startsWith("n") || address.startsWith("2") || address.startsWith("tb1")) {
127
131
  return CHAIN_CONFIGS["testnet"];
128
132
  }
129
133
  return CHAIN_CONFIGS["bitcoin"];
@@ -215,9 +219,14 @@ function verify(attestation, address, proof, checkSegwitAlways, chainConfig) {
215
219
  }
216
220
  if (segwitType) {
217
221
  if (segwitType === "p2sh(p2wpkh)" /* P2SH_P2WPKH */) {
222
+ const redeemScript = new Uint8Array(22);
223
+ redeemScript[0] = 0;
224
+ redeemScript[1] = 20;
225
+ redeemScript.set(publicKeyHash, 2);
226
+ const redeemScriptHash = hash160(redeemScript);
218
227
  actual = encodeBase58AddressFormat(
219
228
  chainConfig.scriptHashVersion,
220
- publicKeyHash
229
+ redeemScriptHash
221
230
  );
222
231
  } else {
223
232
  if (chainConfig.bech32Prefix) {
@@ -308,5 +317,5 @@ function hash160(buffer) {
308
317
  }
309
318
 
310
319
  export { verifyBTCSignature };
311
- //# sourceMappingURL=bitcoin-QK53ILBF.js.map
312
- //# sourceMappingURL=bitcoin-QK53ILBF.js.map
320
+ //# sourceMappingURL=bitcoin-2BFQZA2L.js.map
321
+ //# sourceMappingURL=bitcoin-2BFQZA2L.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bitcoin.ts"],"names":["encodeLength"],"mappings":"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","file":"bitcoin-2BFQZA2L.js","sourcesContent":["import {\n ProofStatus,\n ProofTypes,\n SignatureProof,\n} from \"@notabene/javascript-sdk\";\n\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { base64, bech32, createBase58check } from \"@scure/base\";\nimport { Hash } from \"ox\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { SignatureType } from \"@noble/curves/abstract/weierstrass\";\nimport { Verifier } from \"bip322-js\";\n\nenum SEGWIT_TYPES {\n P2WPKH = \"p2wpkh\",\n P2SH_P2WPKH = \"p2sh(p2wpkh)\",\n}\n\ninterface ChainConfig {\n messagePrefix: string;\n pubKeyHashVersion: number | Uint8Array;\n scriptHashVersion: number | Uint8Array;\n bech32Prefix?: string;\n isTestnet?: boolean;\n}\n\nconst CHAIN_CONFIGS: Record<string, ChainConfig> = {\n bitcoin: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x00, // 1...\n scriptHashVersion: 0x05, // 3...\n bech32Prefix: \"bc\",\n isTestnet: false,\n },\n bitcoincash: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x00, // 1...\n scriptHashVersion: 0x05, // 3...\n bech32Prefix: \"bc\",\n isTestnet: false,\n },\n litecoin: {\n messagePrefix: \"\\u0019Litecoin Signed Message:\\n\",\n pubKeyHashVersion: 0x30, // L... or M...\n scriptHashVersion: 0x32, // 3... or M...\n bech32Prefix: \"ltc\",\n isTestnet: false,\n },\n dogecoin: {\n messagePrefix: \"\\u0019Dogecoin Signed Message:\\n\",\n pubKeyHashVersion: 0x1e, // D...\n scriptHashVersion: 0x16, // A...\n isTestnet: false,\n },\n dash: {\n messagePrefix: \"\\u0019DarkCoin Signed Message:\\n\",\n pubKeyHashVersion: 0x4c, // X...\n scriptHashVersion: 0x10, // 7...\n isTestnet: false,\n },\n zcash: {\n messagePrefix: \"\\u0018Zcash Signed Message:\\n\",\n pubKeyHashVersion: Uint8Array.from([0x1c, 0xb8]), // <-- FIXED\n scriptHashVersion: Uint8Array.from([0x1c, 0xbd]),\n isTestnet: false,\n },\n\n testnet: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x6f, // m or n\n scriptHashVersion: 0xc4, // 2\n bech32Prefix: \"tb\",\n isTestnet: true,\n },\n};\n\nenum DerivationMode {\n LEGACY = \"Legacy\",\n NATIVE = \"Native SegWit\",\n SEGWIT = \"SegWit\",\n P2SH_SEGWIT = \"p2sh\",\n BCH = \"Bitcoin Cash\",\n ETHEREUM = \"Ethereum\",\n DOGECOIN = \"Dogecoin\",\n UNKNOWN = \"Unknown\",\n}\n\nexport async function verifyBTCSignature(\n proof: SignatureProof\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"bip122\") return { ...proof, status: ProofStatus.FAILED };\n\n // Map chainId to our chain configuration\n const chainConfig = getChainConfig(address);\n if (!chainConfig) return { ...proof, status: ProofStatus.FAILED };\n\n const isZcash = address.startsWith(\"t1\") || address.startsWith(\"t3\");\n if (isZcash) {\n return verifyBIP137(address, proof, chainConfig);\n }\n\n // Use BIP322 for testnet addresses\n if (chainConfig.isTestnet) {\n try {\n return verifyBIP322(address, proof);\n } catch {\n return { ...proof, status: ProofStatus.FAILED };\n }\n }\n\n // Check if this is a Taproot address (bc1p or tb1p)\n const isTaproot = address.startsWith(\"bc1p\") || address.startsWith(\"tb1p\");\n\n // For Taproot addresses with BIP-137 proof type, use BIP-322 verification\n // since BIP-137 doesn't officially support Taproot\n if (isTaproot && proof.type === ProofTypes.BIP137) {\n return verifyBIP322(address, proof);\n }\n\n try {\n switch (proof.type) {\n case ProofTypes.BIP137:\n return verifyBIP137(address, proof, chainConfig);\n case ProofTypes.BIP322:\n return verifyBIP322(address, proof);\n default:\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n } catch {\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n}\n\nfunction getChainConfig(address: string): ChainConfig {\n if (\n address.startsWith(\"1\") ||\n address.startsWith(\"3\") ||\n address.startsWith(\"bc1\")\n ) {\n return CHAIN_CONFIGS[\"bitcoin\"];\n }\n if (address.startsWith(\"t1\") || address.startsWith(\"t3\")) {\n return CHAIN_CONFIGS[\"zcash\"];\n }\n if (\n address.startsWith(\"L\") ||\n address.startsWith(\"M\") ||\n address.startsWith(\"ltc1\")\n ) {\n return CHAIN_CONFIGS[\"litecoin\"];\n }\n if (address.startsWith(\"D\") || address.startsWith(\"A\")) {\n return CHAIN_CONFIGS[\"dogecoin\"];\n }\n if (address.startsWith(\"X\") || address.startsWith(\"7\")) {\n return CHAIN_CONFIGS[\"dash\"];\n }\n if (address.startsWith(\"q\")) {\n return CHAIN_CONFIGS[\"bitcoincash\"];\n }\n // Bitcoin testnet addresses can start with \"m\", \"n\", \"2\", or \"tb1\"\n if (\n address.startsWith(\"m\") ||\n address.startsWith(\"n\") ||\n address.startsWith(\"2\") ||\n address.startsWith(\"tb1\")\n ) {\n return CHAIN_CONFIGS[\"testnet\"]\n }\n\n return CHAIN_CONFIGS[\"bitcoin\"];\n}\n\nfunction verifyBIP322(address: string, proof: SignatureProof) {\n const { attestation, proof: signatureProof } = proof;\n const verified = Verifier.verifySignature(\n address,\n attestation,\n signatureProof\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nfunction verifyBIP137(\n address: string,\n proof: SignatureProof,\n chainConfig: ChainConfig\n) {\n const derivationMode = getDerivationMode(address);\n\n // For legacy addresses (starting with \"1\"), never use SegWit encoding\n // For P2SH addresses (starting with \"3\"), use SegWit encoding if they have bech32 support\n // For native SegWit addresses (bc1, tb1, ltc1), always use SegWit encoding\n const useSegwitEncoding = Boolean(\n chainConfig.bech32Prefix &&\n (derivationMode === DerivationMode.NATIVE ||\n (derivationMode === DerivationMode.SEGWIT && !address.startsWith(\"1\")))\n );\n\n const verified = verify(\n proof.attestation,\n address,\n proof.proof,\n useSegwitEncoding,\n chainConfig\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nfunction getDerivationMode(address: string) {\n if (address.match(\"^(bc1|tb1|ltc1).*\")) {\n return DerivationMode.NATIVE;\n } else if (address.match(\"^[32M].*\")) {\n return DerivationMode.SEGWIT;\n } else if (address.match(\"^[1nmL].*\")) {\n return DerivationMode.LEGACY;\n } else if (address.match(\"^(D).*\")) {\n return DerivationMode.DOGECOIN;\n } else if (address.match(\"^(q).*\")) {\n return DerivationMode.BCH;\n } else if (address.match(\"^(t1|t3).*\")) {\n return DerivationMode.LEGACY; // Zcash addresses\n } else if (address.match(\"^[X7].*\")) {\n return DerivationMode.LEGACY; // Dash addresses\n } else {\n throw new Error(\n \"INVALID ADDRESS: \"\n .concat(address)\n .concat(\" is not a valid or a supported address\")\n );\n }\n}\n\ntype DecodedSignature = {\n compressed: boolean;\n segwitType?: SEGWIT_TYPES;\n signature: SignatureType;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const sigbytes = base64.decode(proof);\n if (sigbytes.length !== 65) throw new Error(\"Invalid signature length\");\n const flagByte = sigbytes[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n const compressed = !!(flagByte & 12); // Are there cases that aren't compressed?\n const recovery = flagByte & 3;\n const signature = secp256k1.Signature.fromCompact(sigbytes.slice(1));\n\n return {\n compressed,\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n signature: signature.addRecoveryBit(recovery),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n chainConfig: ChainConfig\n) {\n const { compressed, segwitType, signature } = decodeSignature(proof);\n if (checkSegwitAlways && !compressed) {\n throw new Error(\n \"checkSegwitAlways can only be used with a compressed pubkey signature flagbyte\"\n );\n }\n const hash = magicHash(attestation, chainConfig.messagePrefix);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyBytes = publicKey.toRawBytes(compressed);\n const publicKeyHash = hash160(publicKeyBytes);\n let actual: string = \"\";\n\n // Special handling for Bitcoin Cash addresses\n if (address.startsWith(\"q\")) {\n // For BCH, we'll compare the public key hash directly since we're getting a CashAddr\n // Convert the CashAddr to legacy format for comparison\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n // Legacy P2PKH addresses in BCH start with '1' just like BTC\n // Source: https://reference.cash/protocol/blockchain/encoding/cashaddr#legacy-address-format\n return actual.startsWith(\"1\");\n }\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n // P2SH-P2WPKH: address is hash160 of the witness redeem script, not the raw pubkey hash\n const redeemScript = new Uint8Array(22);\n redeemScript[0] = 0x00; // OP_0\n redeemScript[1] = 0x14; // push 20 bytes\n redeemScript.set(publicKeyHash, 2);\n const redeemScriptHash = hash160(redeemScript);\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n redeemScriptHash\n );\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n if (chainConfig.bech32Prefix) {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n } else {\n // Fallback to legacy if bech32 not supported\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n }\n } else {\n // For addresses starting with \"3\" (P2SH), try both P2SH-P2WPKH and legacy P2SH encodings if segwitType is undefined\n if (address.startsWith(\"3\") && !segwitType) {\n // P2SH-P2WPKH: script hash of the redeem script (OP_0 <pubkeyhash>)\n const redeemScript = new Uint8Array(22);\n redeemScript[0] = 0x00; // OP_0\n redeemScript[1] = 0x14; // push 20 bytes\n redeemScript.set(publicKeyHash, 2);\n const redeemScriptHash = hash160(redeemScript);\n const p2shP2wpkh = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n redeemScriptHash\n );\n // Legacy P2SH: script hash of the public key\n const legacyP2sh = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n if (address === p2shP2wpkh || address === legacyP2sh) {\n return true;\n }\n actual = legacyP2sh; // fallback for error reporting\n } else if (address.startsWith(\"bc1q\") || address.startsWith(\"tb1q\") || address.startsWith(\"ltc1q\")) {\n // For native SegWit P2WPKH addresses (bc1q/tb1q/ltc1q), always encode as bech32\n // This handles Ledger wallets that sign without segwit flags\n if (chainConfig.bech32Prefix) {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n } else {\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n }\n } else if (checkSegwitAlways && chainConfig.bech32Prefix) {\n try {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n // if address is bech32 it is not p2sh\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (e) {\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(\n version: number | Uint8Array,\n publicKeyHash: Uint8Array\n) {\n const prefixBytes =\n typeof version === \"number\" ? Uint8Array.of(version) : version; // Accept raw Uint8Array for Zcash\n\n const payload = new Uint8Array(prefixBytes.length + publicKeyHash.length);\n payload.set(prefixBytes);\n payload.set(publicKeyHash, prefixBytes.length);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: string, messagePrefix: string) {\n const prefix = new TextEncoder().encode(messagePrefix);\n const message = new TextEncoder().encode(attestation);\n const length = encodeLength(message.length).buffer;\n const buffer = new Uint8Array(\n prefix.length + length.byteLength + message.length\n );\n buffer.set(prefix);\n buffer.set(new Uint8Array(length), prefix.length);\n buffer.set(message, prefix.length + length.byteLength);\n return hash256(buffer);\n}\n\nfunction encodeBech32Address(\n publicKeyHash: Uint8Array,\n prefix: string = \"bc\"\n): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(prefix, bwords);\n}\n\nfunction hash256(buffer: Uint8Array): Uint8Array {\n return Hash.sha256(Hash.sha256(buffer));\n}\n\nfunction hash160(buffer: Uint8Array): Uint8Array {\n return Hash.ripemd160(Hash.sha256(buffer));\n}\n"]}
@@ -81,7 +81,11 @@ async function verifyBTCSignature(proof) {
81
81
  return verifyBIP137(address, proof, chainConfig);
82
82
  }
83
83
  if (chainConfig.isTestnet) {
84
- return verifyBIP322(address, proof);
84
+ try {
85
+ return verifyBIP322(address, proof);
86
+ } catch {
87
+ return { ...proof, status: javascriptSdk.ProofStatus.FAILED };
88
+ }
85
89
  }
86
90
  const isTaproot = address.startsWith("bc1p") || address.startsWith("tb1p");
87
91
  if (isTaproot && proof.type === javascriptSdk.ProofTypes.BIP137) {
@@ -125,7 +129,7 @@ function getChainConfig(address) {
125
129
  if (address.startsWith("q")) {
126
130
  return CHAIN_CONFIGS["bitcoincash"];
127
131
  }
128
- if (address.startsWith("tb1")) {
132
+ if (address.startsWith("m") || address.startsWith("n") || address.startsWith("2") || address.startsWith("tb1")) {
129
133
  return CHAIN_CONFIGS["testnet"];
130
134
  }
131
135
  return CHAIN_CONFIGS["bitcoin"];
@@ -217,9 +221,14 @@ function verify(attestation, address, proof, checkSegwitAlways, chainConfig) {
217
221
  }
218
222
  if (segwitType) {
219
223
  if (segwitType === "p2sh(p2wpkh)" /* P2SH_P2WPKH */) {
224
+ const redeemScript = new Uint8Array(22);
225
+ redeemScript[0] = 0;
226
+ redeemScript[1] = 20;
227
+ redeemScript.set(publicKeyHash, 2);
228
+ const redeemScriptHash = hash160(redeemScript);
220
229
  actual = encodeBase58AddressFormat(
221
230
  chainConfig.scriptHashVersion,
222
- publicKeyHash
231
+ redeemScriptHash
223
232
  );
224
233
  } else {
225
234
  if (chainConfig.bech32Prefix) {
@@ -310,5 +319,5 @@ function hash160(buffer) {
310
319
  }
311
320
 
312
321
  exports.verifyBTCSignature = verifyBTCSignature;
313
- //# sourceMappingURL=bitcoin-3CW4MNAW.cjs.map
314
- //# sourceMappingURL=bitcoin-3CW4MNAW.cjs.map
322
+ //# sourceMappingURL=bitcoin-EUO57CWB.cjs.map
323
+ //# sourceMappingURL=bitcoin-EUO57CWB.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bitcoin.ts"],"names":["ProofStatus","ProofTypes","Verifier","base64","secp256k1","createBase58check","Hash","encodeLength","bech32"],"mappings":"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","file":"bitcoin-EUO57CWB.cjs","sourcesContent":["import {\n ProofStatus,\n ProofTypes,\n SignatureProof,\n} from \"@notabene/javascript-sdk\";\n\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { base64, bech32, createBase58check } from \"@scure/base\";\nimport { Hash } from \"ox\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { SignatureType } from \"@noble/curves/abstract/weierstrass\";\nimport { Verifier } from \"bip322-js\";\n\nenum SEGWIT_TYPES {\n P2WPKH = \"p2wpkh\",\n P2SH_P2WPKH = \"p2sh(p2wpkh)\",\n}\n\ninterface ChainConfig {\n messagePrefix: string;\n pubKeyHashVersion: number | Uint8Array;\n scriptHashVersion: number | Uint8Array;\n bech32Prefix?: string;\n isTestnet?: boolean;\n}\n\nconst CHAIN_CONFIGS: Record<string, ChainConfig> = {\n bitcoin: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x00, // 1...\n scriptHashVersion: 0x05, // 3...\n bech32Prefix: \"bc\",\n isTestnet: false,\n },\n bitcoincash: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x00, // 1...\n scriptHashVersion: 0x05, // 3...\n bech32Prefix: \"bc\",\n isTestnet: false,\n },\n litecoin: {\n messagePrefix: \"\\u0019Litecoin Signed Message:\\n\",\n pubKeyHashVersion: 0x30, // L... or M...\n scriptHashVersion: 0x32, // 3... or M...\n bech32Prefix: \"ltc\",\n isTestnet: false,\n },\n dogecoin: {\n messagePrefix: \"\\u0019Dogecoin Signed Message:\\n\",\n pubKeyHashVersion: 0x1e, // D...\n scriptHashVersion: 0x16, // A...\n isTestnet: false,\n },\n dash: {\n messagePrefix: \"\\u0019DarkCoin Signed Message:\\n\",\n pubKeyHashVersion: 0x4c, // X...\n scriptHashVersion: 0x10, // 7...\n isTestnet: false,\n },\n zcash: {\n messagePrefix: \"\\u0018Zcash Signed Message:\\n\",\n pubKeyHashVersion: Uint8Array.from([0x1c, 0xb8]), // <-- FIXED\n scriptHashVersion: Uint8Array.from([0x1c, 0xbd]),\n isTestnet: false,\n },\n\n testnet: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x6f, // m or n\n scriptHashVersion: 0xc4, // 2\n bech32Prefix: \"tb\",\n isTestnet: true,\n },\n};\n\nenum DerivationMode {\n LEGACY = \"Legacy\",\n NATIVE = \"Native SegWit\",\n SEGWIT = \"SegWit\",\n P2SH_SEGWIT = \"p2sh\",\n BCH = \"Bitcoin Cash\",\n ETHEREUM = \"Ethereum\",\n DOGECOIN = \"Dogecoin\",\n UNKNOWN = \"Unknown\",\n}\n\nexport async function verifyBTCSignature(\n proof: SignatureProof\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"bip122\") return { ...proof, status: ProofStatus.FAILED };\n\n // Map chainId to our chain configuration\n const chainConfig = getChainConfig(address);\n if (!chainConfig) return { ...proof, status: ProofStatus.FAILED };\n\n const isZcash = address.startsWith(\"t1\") || address.startsWith(\"t3\");\n if (isZcash) {\n return verifyBIP137(address, proof, chainConfig);\n }\n\n // Use BIP322 for testnet addresses\n if (chainConfig.isTestnet) {\n try {\n return verifyBIP322(address, proof);\n } catch {\n return { ...proof, status: ProofStatus.FAILED };\n }\n }\n\n // Check if this is a Taproot address (bc1p or tb1p)\n const isTaproot = address.startsWith(\"bc1p\") || address.startsWith(\"tb1p\");\n\n // For Taproot addresses with BIP-137 proof type, use BIP-322 verification\n // since BIP-137 doesn't officially support Taproot\n if (isTaproot && proof.type === ProofTypes.BIP137) {\n return verifyBIP322(address, proof);\n }\n\n try {\n switch (proof.type) {\n case ProofTypes.BIP137:\n return verifyBIP137(address, proof, chainConfig);\n case ProofTypes.BIP322:\n return verifyBIP322(address, proof);\n default:\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n } catch {\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n}\n\nfunction getChainConfig(address: string): ChainConfig {\n if (\n address.startsWith(\"1\") ||\n address.startsWith(\"3\") ||\n address.startsWith(\"bc1\")\n ) {\n return CHAIN_CONFIGS[\"bitcoin\"];\n }\n if (address.startsWith(\"t1\") || address.startsWith(\"t3\")) {\n return CHAIN_CONFIGS[\"zcash\"];\n }\n if (\n address.startsWith(\"L\") ||\n address.startsWith(\"M\") ||\n address.startsWith(\"ltc1\")\n ) {\n return CHAIN_CONFIGS[\"litecoin\"];\n }\n if (address.startsWith(\"D\") || address.startsWith(\"A\")) {\n return CHAIN_CONFIGS[\"dogecoin\"];\n }\n if (address.startsWith(\"X\") || address.startsWith(\"7\")) {\n return CHAIN_CONFIGS[\"dash\"];\n }\n if (address.startsWith(\"q\")) {\n return CHAIN_CONFIGS[\"bitcoincash\"];\n }\n // Bitcoin testnet addresses can start with \"m\", \"n\", \"2\", or \"tb1\"\n if (\n address.startsWith(\"m\") ||\n address.startsWith(\"n\") ||\n address.startsWith(\"2\") ||\n address.startsWith(\"tb1\")\n ) {\n return CHAIN_CONFIGS[\"testnet\"]\n }\n\n return CHAIN_CONFIGS[\"bitcoin\"];\n}\n\nfunction verifyBIP322(address: string, proof: SignatureProof) {\n const { attestation, proof: signatureProof } = proof;\n const verified = Verifier.verifySignature(\n address,\n attestation,\n signatureProof\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nfunction verifyBIP137(\n address: string,\n proof: SignatureProof,\n chainConfig: ChainConfig\n) {\n const derivationMode = getDerivationMode(address);\n\n // For legacy addresses (starting with \"1\"), never use SegWit encoding\n // For P2SH addresses (starting with \"3\"), use SegWit encoding if they have bech32 support\n // For native SegWit addresses (bc1, tb1, ltc1), always use SegWit encoding\n const useSegwitEncoding = Boolean(\n chainConfig.bech32Prefix &&\n (derivationMode === DerivationMode.NATIVE ||\n (derivationMode === DerivationMode.SEGWIT && !address.startsWith(\"1\")))\n );\n\n const verified = verify(\n proof.attestation,\n address,\n proof.proof,\n useSegwitEncoding,\n chainConfig\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nfunction getDerivationMode(address: string) {\n if (address.match(\"^(bc1|tb1|ltc1).*\")) {\n return DerivationMode.NATIVE;\n } else if (address.match(\"^[32M].*\")) {\n return DerivationMode.SEGWIT;\n } else if (address.match(\"^[1nmL].*\")) {\n return DerivationMode.LEGACY;\n } else if (address.match(\"^(D).*\")) {\n return DerivationMode.DOGECOIN;\n } else if (address.match(\"^(q).*\")) {\n return DerivationMode.BCH;\n } else if (address.match(\"^(t1|t3).*\")) {\n return DerivationMode.LEGACY; // Zcash addresses\n } else if (address.match(\"^[X7].*\")) {\n return DerivationMode.LEGACY; // Dash addresses\n } else {\n throw new Error(\n \"INVALID ADDRESS: \"\n .concat(address)\n .concat(\" is not a valid or a supported address\")\n );\n }\n}\n\ntype DecodedSignature = {\n compressed: boolean;\n segwitType?: SEGWIT_TYPES;\n signature: SignatureType;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const sigbytes = base64.decode(proof);\n if (sigbytes.length !== 65) throw new Error(\"Invalid signature length\");\n const flagByte = sigbytes[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n const compressed = !!(flagByte & 12); // Are there cases that aren't compressed?\n const recovery = flagByte & 3;\n const signature = secp256k1.Signature.fromCompact(sigbytes.slice(1));\n\n return {\n compressed,\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n signature: signature.addRecoveryBit(recovery),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n chainConfig: ChainConfig\n) {\n const { compressed, segwitType, signature } = decodeSignature(proof);\n if (checkSegwitAlways && !compressed) {\n throw new Error(\n \"checkSegwitAlways can only be used with a compressed pubkey signature flagbyte\"\n );\n }\n const hash = magicHash(attestation, chainConfig.messagePrefix);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyBytes = publicKey.toRawBytes(compressed);\n const publicKeyHash = hash160(publicKeyBytes);\n let actual: string = \"\";\n\n // Special handling for Bitcoin Cash addresses\n if (address.startsWith(\"q\")) {\n // For BCH, we'll compare the public key hash directly since we're getting a CashAddr\n // Convert the CashAddr to legacy format for comparison\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n // Legacy P2PKH addresses in BCH start with '1' just like BTC\n // Source: https://reference.cash/protocol/blockchain/encoding/cashaddr#legacy-address-format\n return actual.startsWith(\"1\");\n }\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n // P2SH-P2WPKH: address is hash160 of the witness redeem script, not the raw pubkey hash\n const redeemScript = new Uint8Array(22);\n redeemScript[0] = 0x00; // OP_0\n redeemScript[1] = 0x14; // push 20 bytes\n redeemScript.set(publicKeyHash, 2);\n const redeemScriptHash = hash160(redeemScript);\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n redeemScriptHash\n );\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n if (chainConfig.bech32Prefix) {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n } else {\n // Fallback to legacy if bech32 not supported\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n }\n } else {\n // For addresses starting with \"3\" (P2SH), try both P2SH-P2WPKH and legacy P2SH encodings if segwitType is undefined\n if (address.startsWith(\"3\") && !segwitType) {\n // P2SH-P2WPKH: script hash of the redeem script (OP_0 <pubkeyhash>)\n const redeemScript = new Uint8Array(22);\n redeemScript[0] = 0x00; // OP_0\n redeemScript[1] = 0x14; // push 20 bytes\n redeemScript.set(publicKeyHash, 2);\n const redeemScriptHash = hash160(redeemScript);\n const p2shP2wpkh = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n redeemScriptHash\n );\n // Legacy P2SH: script hash of the public key\n const legacyP2sh = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n if (address === p2shP2wpkh || address === legacyP2sh) {\n return true;\n }\n actual = legacyP2sh; // fallback for error reporting\n } else if (address.startsWith(\"bc1q\") || address.startsWith(\"tb1q\") || address.startsWith(\"ltc1q\")) {\n // For native SegWit P2WPKH addresses (bc1q/tb1q/ltc1q), always encode as bech32\n // This handles Ledger wallets that sign without segwit flags\n if (chainConfig.bech32Prefix) {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n } else {\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n }\n } else if (checkSegwitAlways && chainConfig.bech32Prefix) {\n try {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n // if address is bech32 it is not p2sh\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (e) {\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(\n version: number | Uint8Array,\n publicKeyHash: Uint8Array\n) {\n const prefixBytes =\n typeof version === \"number\" ? Uint8Array.of(version) : version; // Accept raw Uint8Array for Zcash\n\n const payload = new Uint8Array(prefixBytes.length + publicKeyHash.length);\n payload.set(prefixBytes);\n payload.set(publicKeyHash, prefixBytes.length);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: string, messagePrefix: string) {\n const prefix = new TextEncoder().encode(messagePrefix);\n const message = new TextEncoder().encode(attestation);\n const length = encodeLength(message.length).buffer;\n const buffer = new Uint8Array(\n prefix.length + length.byteLength + message.length\n );\n buffer.set(prefix);\n buffer.set(new Uint8Array(length), prefix.length);\n buffer.set(message, prefix.length + length.byteLength);\n return hash256(buffer);\n}\n\nfunction encodeBech32Address(\n publicKeyHash: Uint8Array,\n prefix: string = \"bc\"\n): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(prefix, bwords);\n}\n\nfunction hash256(buffer: Uint8Array): Uint8Array {\n return Hash.sha256(Hash.sha256(buffer));\n}\n\nfunction hash160(buffer: Uint8Array): Uint8Array {\n return Hash.ripemd160(Hash.sha256(buffer));\n}\n"]}
package/dist/index.cjs CHANGED
@@ -52,7 +52,7 @@ async function verifyProof(proof, publicKey) {
52
52
  case javascriptSdk.ProofTypes.EIP712:
53
53
  case javascriptSdk.ProofTypes.BIP137:
54
54
  case javascriptSdk.ProofTypes.BIP322: {
55
- const { verifyBTCSignature } = await import('./bitcoin-3CW4MNAW.cjs');
55
+ const { verifyBTCSignature } = await import('./bitcoin-EUO57CWB.cjs');
56
56
  return verifyBTCSignature(proof);
57
57
  }
58
58
  case javascriptSdk.ProofTypes.TIP191: {
package/dist/index.js CHANGED
@@ -50,7 +50,7 @@ async function verifyProof(proof, publicKey) {
50
50
  case ProofTypes.EIP712:
51
51
  case ProofTypes.BIP137:
52
52
  case ProofTypes.BIP322: {
53
- const { verifyBTCSignature } = await import('./bitcoin-QK53ILBF.js');
53
+ const { verifyBTCSignature } = await import('./bitcoin-2BFQZA2L.js');
54
54
  return verifyBTCSignature(proof);
55
55
  }
56
56
  case ProofTypes.TIP191: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notabene/verify-proof",
3
- "version": "1.12.0-next.4",
3
+ "version": "1.12.0-next.6",
4
4
  "description": "Verify ownership proofs",
5
5
  "source": "src/index.ts",
6
6
  "type": "module",
package/src/bitcoin.ts CHANGED
@@ -102,7 +102,11 @@ export async function verifyBTCSignature(
102
102
 
103
103
  // Use BIP322 for testnet addresses
104
104
  if (chainConfig.isTestnet) {
105
- return verifyBIP322(address, proof);
105
+ try {
106
+ return verifyBIP322(address, proof);
107
+ } catch {
108
+ return { ...proof, status: ProofStatus.FAILED };
109
+ }
106
110
  }
107
111
 
108
112
  // Check if this is a Taproot address (bc1p or tb1p)
@@ -161,8 +165,14 @@ function getChainConfig(address: string): ChainConfig {
161
165
  if (address.startsWith("q")) {
162
166
  return CHAIN_CONFIGS["bitcoincash"];
163
167
  }
164
- if (address.startsWith("tb1")) {
165
- return CHAIN_CONFIGS["testnet"];
168
+ // Bitcoin testnet addresses can start with "m", "n", "2", or "tb1"
169
+ if (
170
+ address.startsWith("m") ||
171
+ address.startsWith("n") ||
172
+ address.startsWith("2") ||
173
+ address.startsWith("tb1")
174
+ ) {
175
+ return CHAIN_CONFIGS["testnet"]
166
176
  }
167
177
 
168
178
  return CHAIN_CONFIGS["bitcoin"];
@@ -297,9 +307,15 @@ function verify(
297
307
 
298
308
  if (segwitType) {
299
309
  if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {
310
+ // P2SH-P2WPKH: address is hash160 of the witness redeem script, not the raw pubkey hash
311
+ const redeemScript = new Uint8Array(22);
312
+ redeemScript[0] = 0x00; // OP_0
313
+ redeemScript[1] = 0x14; // push 20 bytes
314
+ redeemScript.set(publicKeyHash, 2);
315
+ const redeemScriptHash = hash160(redeemScript);
300
316
  actual = encodeBase58AddressFormat(
301
317
  chainConfig.scriptHashVersion,
302
- publicKeyHash
318
+ redeemScriptHash
303
319
  );
304
320
  } else {
305
321
  // parsed.segwitType === SEGWIT_TYPES.P2WPKH
@@ -336,6 +336,68 @@ describe("verifyBTCSignature", () => {
336
336
  expect(result).toEqual({ ...testnetProof, status: ProofStatus.VERIFIED });
337
337
  });
338
338
 
339
+ describe("Bitcoin testnet address prefixes", () => {
340
+ it("handles testnet P2PKH addresses starting with 'm'", async () => {
341
+ const testnetMProof: SignatureProof = {
342
+ type: ProofTypes.BIP137,
343
+ address:
344
+ "bip122:000000000933ea01ad0ee984209779ba:mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn",
345
+ did: "did:pkh:bip122:000000000933ea01ad0ee984209779ba:mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn",
346
+ attestation: "Testnet m-address verification",
347
+ proof:
348
+ "H796FDv8f8w3syiaMSGoL6SAwPLRf6t13S+fYNjYA9EnJy3T0jZOY1eHBaGTBufOuW78FVFSwXKyUnrEjYOT9EU=",
349
+ status: ProofStatus.PENDING,
350
+ wallet_provider: "Manual Wallet Signature",
351
+ };
352
+
353
+ const result = await verifyBTCSignature(testnetMProof);
354
+ // Should be recognized as testnet and processed without throwing
355
+ expect([ProofStatus.VERIFIED, ProofStatus.FAILED]).toContain(
356
+ result.status
357
+ );
358
+ });
359
+
360
+ it("handles testnet P2PKH addresses starting with 'n'", async () => {
361
+ const testnetNProof: SignatureProof = {
362
+ type: ProofTypes.BIP137,
363
+ address:
364
+ "bip122:000000000933ea01ad0ee984209779ba:n1bkBJpWfQEa3JGPf8MYwHLny62FPNwJC4",
365
+ did: "did:pkh:bip122:000000000933ea01ad0ee984209779ba:n1bkBJpWfQEa3JGPf8MYwHLny62FPNwJC4",
366
+ attestation: "Testnet n-address verification",
367
+ proof:
368
+ "H796FDv8f8w3syiaMSGoL6SAwPLRf6t13S+fYNjYA9EnJy3T0jZOY1eHBaGTBufOuW78FVFSwXKyUnrEjYOT9EU=",
369
+ status: ProofStatus.PENDING,
370
+ wallet_provider: "Manual Wallet Signature",
371
+ };
372
+
373
+ const result = await verifyBTCSignature(testnetNProof);
374
+ // Should be recognized as testnet and processed without throwing
375
+ expect([ProofStatus.VERIFIED, ProofStatus.FAILED]).toContain(
376
+ result.status
377
+ );
378
+ });
379
+
380
+ it("handles testnet P2SH addresses starting with '2'", async () => {
381
+ const testnet2Proof: SignatureProof = {
382
+ type: ProofTypes.BIP137,
383
+ address:
384
+ "bip122:000000000933ea01ad0ee984209779ba:2MzQwSSnBHWHqSAqtTVQ6v47XtaisrJa1Vc",
385
+ did: "did:pkh:bip122:000000000933ea01ad0ee984209779ba:2MzQwSSnBHWHqSAqtTVQ6v47XtaisrJa1Vc",
386
+ attestation: "Testnet 2-address verification",
387
+ proof:
388
+ "H796FDv8f8w3syiaMSGoL6SAwPLRf6t13S+fYNjYA9EnJy3T0jZOY1eHBaGTBufOuW78FVFSwXKyUnrEjYOT9EU=",
389
+ status: ProofStatus.PENDING,
390
+ wallet_provider: "Manual Wallet Signature",
391
+ };
392
+
393
+ const result = await verifyBTCSignature(testnet2Proof);
394
+ // Should be recognized as testnet and processed without throwing
395
+ expect([ProofStatus.VERIFIED, ProofStatus.FAILED]).toContain(
396
+ result.status
397
+ );
398
+ });
399
+ });
400
+
339
401
  it("handles legacy multisig addresses", async () => {
340
402
  const multisigProof: SignatureProof = {
341
403
  ...legacyProof,
@@ -712,6 +774,32 @@ describe("verifyBTCSignature", () => {
712
774
  });
713
775
  });
714
776
 
777
+ describe("Trezor wallet quirks", () => {
778
+ it("handles Trezor P2SH-P2WPKH signature with segwit flag byte", async () => {
779
+ // Trezor sets the BIP-137 segwit flag (flag byte 35 = 27 + 8) for P2SH-P2WPKH addresses.
780
+ // The P2SH-P2WPKH branch must derive the address via hash160(redeemScript),
781
+ // not use the raw publicKeyHash directly.
782
+ const trezorP2shP2wpkhProof: SignatureProof = {
783
+ type: ProofTypes.BIP137,
784
+ address:
785
+ "bip122:000000000019d6689c085ae165831e93:3CNuGWYUR9osV6PRdkqHZ7cGBaum2XjYBQ",
786
+ did: "did:pkh:bip122:000000000019d6689c085ae165831e93:3CNuGWYUR9osV6PRdkqHZ7cGBaum2XjYBQ",
787
+ attestation:
788
+ "I certify that\n\nbip122:000000000019d6689c085ae165831e93 account 3CNuGWYUR9osV6PRdkqHZ7cGBaum2XjYBQ\n\nbelonged to undefined\n\non Tue, 17 Feb 2026 14:36:05 GMT",
789
+ proof:
790
+ "I74BHi+4QLDTQgxCJqOUvlWdB3BizwSC/tCPeqrCfvJfaF6pYbBZiOvMp4FWf5iswzpmoZ1MlB7G0HuXk7Anmn0=",
791
+ status: ProofStatus.PENDING,
792
+ wallet_provider: "Trezor",
793
+ };
794
+
795
+ const result = await verifyBTCSignature(trezorP2shP2wpkhProof);
796
+ expect(result).toEqual({
797
+ ...trezorP2shP2wpkhProof,
798
+ status: ProofStatus.VERIFIED,
799
+ });
800
+ });
801
+ });
802
+
715
803
  describe("Ledger wallet quirks", () => {
716
804
  it("handles Ledger bc1q signature without segwit flag", async () => {
717
805
  // Ledger signs bc1q addresses without setting segwit flag byte
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/bitcoin.ts"],"names":["ProofStatus","ProofTypes","Verifier","base64","secp256k1","createBase58check","Hash","encodeLength","bech32"],"mappings":"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","file":"bitcoin-3CW4MNAW.cjs","sourcesContent":["import {\n ProofStatus,\n ProofTypes,\n SignatureProof,\n} from \"@notabene/javascript-sdk\";\n\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { base64, bech32, createBase58check } from \"@scure/base\";\nimport { Hash } from \"ox\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { SignatureType } from \"@noble/curves/abstract/weierstrass\";\nimport { Verifier } from \"bip322-js\";\n\nenum SEGWIT_TYPES {\n P2WPKH = \"p2wpkh\",\n P2SH_P2WPKH = \"p2sh(p2wpkh)\",\n}\n\ninterface ChainConfig {\n messagePrefix: string;\n pubKeyHashVersion: number | Uint8Array;\n scriptHashVersion: number | Uint8Array;\n bech32Prefix?: string;\n isTestnet?: boolean;\n}\n\nconst CHAIN_CONFIGS: Record<string, ChainConfig> = {\n bitcoin: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x00, // 1...\n scriptHashVersion: 0x05, // 3...\n bech32Prefix: \"bc\",\n isTestnet: false,\n },\n bitcoincash: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x00, // 1...\n scriptHashVersion: 0x05, // 3...\n bech32Prefix: \"bc\",\n isTestnet: false,\n },\n litecoin: {\n messagePrefix: \"\\u0019Litecoin Signed Message:\\n\",\n pubKeyHashVersion: 0x30, // L... or M...\n scriptHashVersion: 0x32, // 3... or M...\n bech32Prefix: \"ltc\",\n isTestnet: false,\n },\n dogecoin: {\n messagePrefix: \"\\u0019Dogecoin Signed Message:\\n\",\n pubKeyHashVersion: 0x1e, // D...\n scriptHashVersion: 0x16, // A...\n isTestnet: false,\n },\n dash: {\n messagePrefix: \"\\u0019DarkCoin Signed Message:\\n\",\n pubKeyHashVersion: 0x4c, // X...\n scriptHashVersion: 0x10, // 7...\n isTestnet: false,\n },\n zcash: {\n messagePrefix: \"\\u0018Zcash Signed Message:\\n\",\n pubKeyHashVersion: Uint8Array.from([0x1c, 0xb8]), // <-- FIXED\n scriptHashVersion: Uint8Array.from([0x1c, 0xbd]),\n isTestnet: false,\n },\n\n testnet: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x6f, // m or n\n scriptHashVersion: 0xc4, // 2\n bech32Prefix: \"tb\",\n isTestnet: true,\n },\n};\n\nenum DerivationMode {\n LEGACY = \"Legacy\",\n NATIVE = \"Native SegWit\",\n SEGWIT = \"SegWit\",\n P2SH_SEGWIT = \"p2sh\",\n BCH = \"Bitcoin Cash\",\n ETHEREUM = \"Ethereum\",\n DOGECOIN = \"Dogecoin\",\n UNKNOWN = \"Unknown\",\n}\n\nexport async function verifyBTCSignature(\n proof: SignatureProof\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"bip122\") return { ...proof, status: ProofStatus.FAILED };\n\n // Map chainId to our chain configuration\n const chainConfig = getChainConfig(address);\n if (!chainConfig) return { ...proof, status: ProofStatus.FAILED };\n\n const isZcash = address.startsWith(\"t1\") || address.startsWith(\"t3\");\n if (isZcash) {\n return verifyBIP137(address, proof, chainConfig);\n }\n\n // Use BIP322 for testnet addresses\n if (chainConfig.isTestnet) {\n return verifyBIP322(address, proof);\n }\n\n // Check if this is a Taproot address (bc1p or tb1p)\n const isTaproot = address.startsWith(\"bc1p\") || address.startsWith(\"tb1p\");\n\n // For Taproot addresses with BIP-137 proof type, use BIP-322 verification\n // since BIP-137 doesn't officially support Taproot\n if (isTaproot && proof.type === ProofTypes.BIP137) {\n return verifyBIP322(address, proof);\n }\n\n try {\n switch (proof.type) {\n case ProofTypes.BIP137:\n return verifyBIP137(address, proof, chainConfig);\n case ProofTypes.BIP322:\n return verifyBIP322(address, proof);\n default:\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n } catch {\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n}\n\nfunction getChainConfig(address: string): ChainConfig {\n if (\n address.startsWith(\"1\") ||\n address.startsWith(\"3\") ||\n address.startsWith(\"bc1\")\n ) {\n return CHAIN_CONFIGS[\"bitcoin\"];\n }\n if (address.startsWith(\"t1\") || address.startsWith(\"t3\")) {\n return CHAIN_CONFIGS[\"zcash\"];\n }\n if (\n address.startsWith(\"L\") ||\n address.startsWith(\"M\") ||\n address.startsWith(\"ltc1\")\n ) {\n return CHAIN_CONFIGS[\"litecoin\"];\n }\n if (address.startsWith(\"D\") || address.startsWith(\"A\")) {\n return CHAIN_CONFIGS[\"dogecoin\"];\n }\n if (address.startsWith(\"X\") || address.startsWith(\"7\")) {\n return CHAIN_CONFIGS[\"dash\"];\n }\n if (address.startsWith(\"q\")) {\n return CHAIN_CONFIGS[\"bitcoincash\"];\n }\n if (address.startsWith(\"tb1\")) {\n return CHAIN_CONFIGS[\"testnet\"];\n }\n\n return CHAIN_CONFIGS[\"bitcoin\"];\n}\n\nfunction verifyBIP322(address: string, proof: SignatureProof) {\n const { attestation, proof: signatureProof } = proof;\n const verified = Verifier.verifySignature(\n address,\n attestation,\n signatureProof\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nfunction verifyBIP137(\n address: string,\n proof: SignatureProof,\n chainConfig: ChainConfig\n) {\n const derivationMode = getDerivationMode(address);\n\n // For legacy addresses (starting with \"1\"), never use SegWit encoding\n // For P2SH addresses (starting with \"3\"), use SegWit encoding if they have bech32 support\n // For native SegWit addresses (bc1, tb1, ltc1), always use SegWit encoding\n const useSegwitEncoding = Boolean(\n chainConfig.bech32Prefix &&\n (derivationMode === DerivationMode.NATIVE ||\n (derivationMode === DerivationMode.SEGWIT && !address.startsWith(\"1\")))\n );\n\n const verified = verify(\n proof.attestation,\n address,\n proof.proof,\n useSegwitEncoding,\n chainConfig\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nfunction getDerivationMode(address: string) {\n if (address.match(\"^(bc1|tb1|ltc1).*\")) {\n return DerivationMode.NATIVE;\n } else if (address.match(\"^[32M].*\")) {\n return DerivationMode.SEGWIT;\n } else if (address.match(\"^[1nmL].*\")) {\n return DerivationMode.LEGACY;\n } else if (address.match(\"^(D).*\")) {\n return DerivationMode.DOGECOIN;\n } else if (address.match(\"^(q).*\")) {\n return DerivationMode.BCH;\n } else if (address.match(\"^(t1|t3).*\")) {\n return DerivationMode.LEGACY; // Zcash addresses\n } else if (address.match(\"^[X7].*\")) {\n return DerivationMode.LEGACY; // Dash addresses\n } else {\n throw new Error(\n \"INVALID ADDRESS: \"\n .concat(address)\n .concat(\" is not a valid or a supported address\")\n );\n }\n}\n\ntype DecodedSignature = {\n compressed: boolean;\n segwitType?: SEGWIT_TYPES;\n signature: SignatureType;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const sigbytes = base64.decode(proof);\n if (sigbytes.length !== 65) throw new Error(\"Invalid signature length\");\n const flagByte = sigbytes[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n const compressed = !!(flagByte & 12); // Are there cases that aren't compressed?\n const recovery = flagByte & 3;\n const signature = secp256k1.Signature.fromCompact(sigbytes.slice(1));\n\n return {\n compressed,\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n signature: signature.addRecoveryBit(recovery),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n chainConfig: ChainConfig\n) {\n const { compressed, segwitType, signature } = decodeSignature(proof);\n if (checkSegwitAlways && !compressed) {\n throw new Error(\n \"checkSegwitAlways can only be used with a compressed pubkey signature flagbyte\"\n );\n }\n const hash = magicHash(attestation, chainConfig.messagePrefix);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyBytes = publicKey.toRawBytes(compressed);\n const publicKeyHash = hash160(publicKeyBytes);\n let actual: string = \"\";\n\n // Special handling for Bitcoin Cash addresses\n if (address.startsWith(\"q\")) {\n // For BCH, we'll compare the public key hash directly since we're getting a CashAddr\n // Convert the CashAddr to legacy format for comparison\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n // Legacy P2PKH addresses in BCH start with '1' just like BTC\n // Source: https://reference.cash/protocol/blockchain/encoding/cashaddr#legacy-address-format\n return actual.startsWith(\"1\");\n }\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n if (chainConfig.bech32Prefix) {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n } else {\n // Fallback to legacy if bech32 not supported\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n }\n } else {\n // For addresses starting with \"3\" (P2SH), try both P2SH-P2WPKH and legacy P2SH encodings if segwitType is undefined\n if (address.startsWith(\"3\") && !segwitType) {\n // P2SH-P2WPKH: script hash of the redeem script (OP_0 <pubkeyhash>)\n const redeemScript = new Uint8Array(22);\n redeemScript[0] = 0x00; // OP_0\n redeemScript[1] = 0x14; // push 20 bytes\n redeemScript.set(publicKeyHash, 2);\n const redeemScriptHash = hash160(redeemScript);\n const p2shP2wpkh = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n redeemScriptHash\n );\n // Legacy P2SH: script hash of the public key\n const legacyP2sh = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n if (address === p2shP2wpkh || address === legacyP2sh) {\n return true;\n }\n actual = legacyP2sh; // fallback for error reporting\n } else if (address.startsWith(\"bc1q\") || address.startsWith(\"tb1q\") || address.startsWith(\"ltc1q\")) {\n // For native SegWit P2WPKH addresses (bc1q/tb1q/ltc1q), always encode as bech32\n // This handles Ledger wallets that sign without segwit flags\n if (chainConfig.bech32Prefix) {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n } else {\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n }\n } else if (checkSegwitAlways && chainConfig.bech32Prefix) {\n try {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n // if address is bech32 it is not p2sh\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (e) {\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(\n version: number | Uint8Array,\n publicKeyHash: Uint8Array\n) {\n const prefixBytes =\n typeof version === \"number\" ? Uint8Array.of(version) : version; // Accept raw Uint8Array for Zcash\n\n const payload = new Uint8Array(prefixBytes.length + publicKeyHash.length);\n payload.set(prefixBytes);\n payload.set(publicKeyHash, prefixBytes.length);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: string, messagePrefix: string) {\n const prefix = new TextEncoder().encode(messagePrefix);\n const message = new TextEncoder().encode(attestation);\n const length = encodeLength(message.length).buffer;\n const buffer = new Uint8Array(\n prefix.length + length.byteLength + message.length\n );\n buffer.set(prefix);\n buffer.set(new Uint8Array(length), prefix.length);\n buffer.set(message, prefix.length + length.byteLength);\n return hash256(buffer);\n}\n\nfunction encodeBech32Address(\n publicKeyHash: Uint8Array,\n prefix: string = \"bc\"\n): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(prefix, bwords);\n}\n\nfunction hash256(buffer: Uint8Array): Uint8Array {\n return Hash.sha256(Hash.sha256(buffer));\n}\n\nfunction hash160(buffer: Uint8Array): Uint8Array {\n return Hash.ripemd160(Hash.sha256(buffer));\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/bitcoin.ts"],"names":["encodeLength"],"mappings":"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","file":"bitcoin-QK53ILBF.js","sourcesContent":["import {\n ProofStatus,\n ProofTypes,\n SignatureProof,\n} from \"@notabene/javascript-sdk\";\n\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { base64, bech32, createBase58check } from \"@scure/base\";\nimport { Hash } from \"ox\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { SignatureType } from \"@noble/curves/abstract/weierstrass\";\nimport { Verifier } from \"bip322-js\";\n\nenum SEGWIT_TYPES {\n P2WPKH = \"p2wpkh\",\n P2SH_P2WPKH = \"p2sh(p2wpkh)\",\n}\n\ninterface ChainConfig {\n messagePrefix: string;\n pubKeyHashVersion: number | Uint8Array;\n scriptHashVersion: number | Uint8Array;\n bech32Prefix?: string;\n isTestnet?: boolean;\n}\n\nconst CHAIN_CONFIGS: Record<string, ChainConfig> = {\n bitcoin: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x00, // 1...\n scriptHashVersion: 0x05, // 3...\n bech32Prefix: \"bc\",\n isTestnet: false,\n },\n bitcoincash: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x00, // 1...\n scriptHashVersion: 0x05, // 3...\n bech32Prefix: \"bc\",\n isTestnet: false,\n },\n litecoin: {\n messagePrefix: \"\\u0019Litecoin Signed Message:\\n\",\n pubKeyHashVersion: 0x30, // L... or M...\n scriptHashVersion: 0x32, // 3... or M...\n bech32Prefix: \"ltc\",\n isTestnet: false,\n },\n dogecoin: {\n messagePrefix: \"\\u0019Dogecoin Signed Message:\\n\",\n pubKeyHashVersion: 0x1e, // D...\n scriptHashVersion: 0x16, // A...\n isTestnet: false,\n },\n dash: {\n messagePrefix: \"\\u0019DarkCoin Signed Message:\\n\",\n pubKeyHashVersion: 0x4c, // X...\n scriptHashVersion: 0x10, // 7...\n isTestnet: false,\n },\n zcash: {\n messagePrefix: \"\\u0018Zcash Signed Message:\\n\",\n pubKeyHashVersion: Uint8Array.from([0x1c, 0xb8]), // <-- FIXED\n scriptHashVersion: Uint8Array.from([0x1c, 0xbd]),\n isTestnet: false,\n },\n\n testnet: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x6f, // m or n\n scriptHashVersion: 0xc4, // 2\n bech32Prefix: \"tb\",\n isTestnet: true,\n },\n};\n\nenum DerivationMode {\n LEGACY = \"Legacy\",\n NATIVE = \"Native SegWit\",\n SEGWIT = \"SegWit\",\n P2SH_SEGWIT = \"p2sh\",\n BCH = \"Bitcoin Cash\",\n ETHEREUM = \"Ethereum\",\n DOGECOIN = \"Dogecoin\",\n UNKNOWN = \"Unknown\",\n}\n\nexport async function verifyBTCSignature(\n proof: SignatureProof\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"bip122\") return { ...proof, status: ProofStatus.FAILED };\n\n // Map chainId to our chain configuration\n const chainConfig = getChainConfig(address);\n if (!chainConfig) return { ...proof, status: ProofStatus.FAILED };\n\n const isZcash = address.startsWith(\"t1\") || address.startsWith(\"t3\");\n if (isZcash) {\n return verifyBIP137(address, proof, chainConfig);\n }\n\n // Use BIP322 for testnet addresses\n if (chainConfig.isTestnet) {\n return verifyBIP322(address, proof);\n }\n\n // Check if this is a Taproot address (bc1p or tb1p)\n const isTaproot = address.startsWith(\"bc1p\") || address.startsWith(\"tb1p\");\n\n // For Taproot addresses with BIP-137 proof type, use BIP-322 verification\n // since BIP-137 doesn't officially support Taproot\n if (isTaproot && proof.type === ProofTypes.BIP137) {\n return verifyBIP322(address, proof);\n }\n\n try {\n switch (proof.type) {\n case ProofTypes.BIP137:\n return verifyBIP137(address, proof, chainConfig);\n case ProofTypes.BIP322:\n return verifyBIP322(address, proof);\n default:\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n } catch {\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n}\n\nfunction getChainConfig(address: string): ChainConfig {\n if (\n address.startsWith(\"1\") ||\n address.startsWith(\"3\") ||\n address.startsWith(\"bc1\")\n ) {\n return CHAIN_CONFIGS[\"bitcoin\"];\n }\n if (address.startsWith(\"t1\") || address.startsWith(\"t3\")) {\n return CHAIN_CONFIGS[\"zcash\"];\n }\n if (\n address.startsWith(\"L\") ||\n address.startsWith(\"M\") ||\n address.startsWith(\"ltc1\")\n ) {\n return CHAIN_CONFIGS[\"litecoin\"];\n }\n if (address.startsWith(\"D\") || address.startsWith(\"A\")) {\n return CHAIN_CONFIGS[\"dogecoin\"];\n }\n if (address.startsWith(\"X\") || address.startsWith(\"7\")) {\n return CHAIN_CONFIGS[\"dash\"];\n }\n if (address.startsWith(\"q\")) {\n return CHAIN_CONFIGS[\"bitcoincash\"];\n }\n if (address.startsWith(\"tb1\")) {\n return CHAIN_CONFIGS[\"testnet\"];\n }\n\n return CHAIN_CONFIGS[\"bitcoin\"];\n}\n\nfunction verifyBIP322(address: string, proof: SignatureProof) {\n const { attestation, proof: signatureProof } = proof;\n const verified = Verifier.verifySignature(\n address,\n attestation,\n signatureProof\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nfunction verifyBIP137(\n address: string,\n proof: SignatureProof,\n chainConfig: ChainConfig\n) {\n const derivationMode = getDerivationMode(address);\n\n // For legacy addresses (starting with \"1\"), never use SegWit encoding\n // For P2SH addresses (starting with \"3\"), use SegWit encoding if they have bech32 support\n // For native SegWit addresses (bc1, tb1, ltc1), always use SegWit encoding\n const useSegwitEncoding = Boolean(\n chainConfig.bech32Prefix &&\n (derivationMode === DerivationMode.NATIVE ||\n (derivationMode === DerivationMode.SEGWIT && !address.startsWith(\"1\")))\n );\n\n const verified = verify(\n proof.attestation,\n address,\n proof.proof,\n useSegwitEncoding,\n chainConfig\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nfunction getDerivationMode(address: string) {\n if (address.match(\"^(bc1|tb1|ltc1).*\")) {\n return DerivationMode.NATIVE;\n } else if (address.match(\"^[32M].*\")) {\n return DerivationMode.SEGWIT;\n } else if (address.match(\"^[1nmL].*\")) {\n return DerivationMode.LEGACY;\n } else if (address.match(\"^(D).*\")) {\n return DerivationMode.DOGECOIN;\n } else if (address.match(\"^(q).*\")) {\n return DerivationMode.BCH;\n } else if (address.match(\"^(t1|t3).*\")) {\n return DerivationMode.LEGACY; // Zcash addresses\n } else if (address.match(\"^[X7].*\")) {\n return DerivationMode.LEGACY; // Dash addresses\n } else {\n throw new Error(\n \"INVALID ADDRESS: \"\n .concat(address)\n .concat(\" is not a valid or a supported address\")\n );\n }\n}\n\ntype DecodedSignature = {\n compressed: boolean;\n segwitType?: SEGWIT_TYPES;\n signature: SignatureType;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const sigbytes = base64.decode(proof);\n if (sigbytes.length !== 65) throw new Error(\"Invalid signature length\");\n const flagByte = sigbytes[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n const compressed = !!(flagByte & 12); // Are there cases that aren't compressed?\n const recovery = flagByte & 3;\n const signature = secp256k1.Signature.fromCompact(sigbytes.slice(1));\n\n return {\n compressed,\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n signature: signature.addRecoveryBit(recovery),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n chainConfig: ChainConfig\n) {\n const { compressed, segwitType, signature } = decodeSignature(proof);\n if (checkSegwitAlways && !compressed) {\n throw new Error(\n \"checkSegwitAlways can only be used with a compressed pubkey signature flagbyte\"\n );\n }\n const hash = magicHash(attestation, chainConfig.messagePrefix);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyBytes = publicKey.toRawBytes(compressed);\n const publicKeyHash = hash160(publicKeyBytes);\n let actual: string = \"\";\n\n // Special handling for Bitcoin Cash addresses\n if (address.startsWith(\"q\")) {\n // For BCH, we'll compare the public key hash directly since we're getting a CashAddr\n // Convert the CashAddr to legacy format for comparison\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n // Legacy P2PKH addresses in BCH start with '1' just like BTC\n // Source: https://reference.cash/protocol/blockchain/encoding/cashaddr#legacy-address-format\n return actual.startsWith(\"1\");\n }\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n if (chainConfig.bech32Prefix) {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n } else {\n // Fallback to legacy if bech32 not supported\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n }\n } else {\n // For addresses starting with \"3\" (P2SH), try both P2SH-P2WPKH and legacy P2SH encodings if segwitType is undefined\n if (address.startsWith(\"3\") && !segwitType) {\n // P2SH-P2WPKH: script hash of the redeem script (OP_0 <pubkeyhash>)\n const redeemScript = new Uint8Array(22);\n redeemScript[0] = 0x00; // OP_0\n redeemScript[1] = 0x14; // push 20 bytes\n redeemScript.set(publicKeyHash, 2);\n const redeemScriptHash = hash160(redeemScript);\n const p2shP2wpkh = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n redeemScriptHash\n );\n // Legacy P2SH: script hash of the public key\n const legacyP2sh = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n if (address === p2shP2wpkh || address === legacyP2sh) {\n return true;\n }\n actual = legacyP2sh; // fallback for error reporting\n } else if (address.startsWith(\"bc1q\") || address.startsWith(\"tb1q\") || address.startsWith(\"ltc1q\")) {\n // For native SegWit P2WPKH addresses (bc1q/tb1q/ltc1q), always encode as bech32\n // This handles Ledger wallets that sign without segwit flags\n if (chainConfig.bech32Prefix) {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n } else {\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n }\n } else if (checkSegwitAlways && chainConfig.bech32Prefix) {\n try {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n // if address is bech32 it is not p2sh\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (e) {\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(\n version: number | Uint8Array,\n publicKeyHash: Uint8Array\n) {\n const prefixBytes =\n typeof version === \"number\" ? Uint8Array.of(version) : version; // Accept raw Uint8Array for Zcash\n\n const payload = new Uint8Array(prefixBytes.length + publicKeyHash.length);\n payload.set(prefixBytes);\n payload.set(publicKeyHash, prefixBytes.length);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: string, messagePrefix: string) {\n const prefix = new TextEncoder().encode(messagePrefix);\n const message = new TextEncoder().encode(attestation);\n const length = encodeLength(message.length).buffer;\n const buffer = new Uint8Array(\n prefix.length + length.byteLength + message.length\n );\n buffer.set(prefix);\n buffer.set(new Uint8Array(length), prefix.length);\n buffer.set(message, prefix.length + length.byteLength);\n return hash256(buffer);\n}\n\nfunction encodeBech32Address(\n publicKeyHash: Uint8Array,\n prefix: string = \"bc\"\n): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(prefix, bwords);\n}\n\nfunction hash256(buffer: Uint8Array): Uint8Array {\n return Hash.sha256(Hash.sha256(buffer));\n}\n\nfunction hash160(buffer: Uint8Array): Uint8Array {\n return Hash.ripemd160(Hash.sha256(buffer));\n}\n"]}