@notabene/verify-proof 1.8.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notabene/verify-proof",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Verify ownership proofs",
5
5
  "source": "src/index.ts",
6
6
  "type": "module",
package/src/bitcoin.ts CHANGED
@@ -117,7 +117,6 @@ export async function verifyBTCSignature(
117
117
  status: ProofStatus.FAILED,
118
118
  };
119
119
  }
120
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
121
120
  } catch (error) {
122
121
  console.error("error verifying proof", error);
123
122
  return {
@@ -169,10 +168,16 @@ function verifyBIP322(address: string, proof: SignatureProof) {
169
168
  }
170
169
 
171
170
  function verifyBIP137(address: string, proof: SignatureProof, chainConfig: ChainConfig) {
172
- const segwit = Boolean(chainConfig.bech32Prefix && [DerivationMode.SEGWIT, DerivationMode.NATIVE].includes(
173
- getDerivationMode(address)
174
- ));
175
- const verified = verify(proof.attestation, address, proof.proof, segwit, chainConfig);
171
+ const derivationMode = getDerivationMode(address);
172
+
173
+ // For legacy addresses (starting with "1"), never use SegWit encoding
174
+ // For P2SH addresses (starting with "3"), use SegWit encoding if they have bech32 support
175
+ // For native SegWit addresses (bc1, tb1, ltc1), always use SegWit encoding
176
+ const useSegwitEncoding = Boolean(chainConfig.bech32Prefix &&
177
+ (derivationMode === DerivationMode.NATIVE ||
178
+ (derivationMode === DerivationMode.SEGWIT && !address.startsWith("1"))));
179
+
180
+ const verified = verify(proof.attestation, address, proof.proof, useSegwitEncoding, chainConfig);
176
181
 
177
182
  return {
178
183
  ...proof,
@@ -191,6 +196,10 @@ function getDerivationMode(address: string) {
191
196
  return DerivationMode.DOGECOIN;
192
197
  } else if (address.match("^(q).*")) {
193
198
  return DerivationMode.BCH;
199
+ } else if (address.match("^(t1|t3).*")) {
200
+ return DerivationMode.LEGACY; // Zcash addresses
201
+ } else if (address.match("^[X7].*")) {
202
+ return DerivationMode.LEGACY; // Dash addresses
194
203
  } else {
195
204
  throw new Error(
196
205
  "INVALID ADDRESS: "
@@ -271,7 +280,22 @@ function verify(
271
280
  }
272
281
  }
273
282
  } else {
274
- if (checkSegwitAlways && chainConfig.bech32Prefix) {
283
+ // For addresses starting with "3" (P2SH), try both P2SH-P2WPKH and legacy P2SH encodings if segwitType is undefined
284
+ if (address.startsWith("3") && !segwitType) {
285
+ // P2SH-P2WPKH: script hash of the redeem script (OP_0 <pubkeyhash>)
286
+ const redeemScript = new Uint8Array(22);
287
+ redeemScript[0] = 0x00; // OP_0
288
+ redeemScript[1] = 0x14; // push 20 bytes
289
+ redeemScript.set(publicKeyHash, 2);
290
+ const redeemScriptHash = hash160(redeemScript);
291
+ const p2shP2wpkh = encodeBase58AddressFormat(chainConfig.scriptHashVersion, redeemScriptHash);
292
+ // Legacy P2SH: script hash of the public key
293
+ const legacyP2sh = encodeBase58AddressFormat(chainConfig.scriptHashVersion, publicKeyHash);
294
+ if (address === p2shP2wpkh || address === legacyP2sh) {
295
+ return true;
296
+ }
297
+ actual = legacyP2sh; // fallback for error reporting
298
+ } else if (checkSegwitAlways && chainConfig.bech32Prefix) {
275
299
  try {
276
300
  actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);
277
301
  // if address is bech32 it is not p2sh
@@ -7,6 +7,26 @@ import {
7
7
  ProofTypes,
8
8
  } from "@notabene/javascript-sdk";
9
9
 
10
+ const bitcoinP2WPKHProof: SignatureProof = {
11
+ type: ProofTypes.BIP137,
12
+ wallet_provider: "Manual Wallet Signature",
13
+ status: ProofStatus.PENDING,
14
+ address: "bip122:000000000019d6689c085ae165831e93:3Q9jfjfbMDuatto7wZ6Tz2aKaDCRHqWWys",
15
+ did: "did:pkh:bip122:000000000019d6689c085ae165831e93:3Q9jfjfbMDuatto7wZ6Tz2aKaDCRHqWWys",
16
+ attestation: "I certify that the blockchain address 3Q9jfjfbMDuatto7wZ6Tz2aKaDCRHqWWys belongs to did:pkh:bip122:000000000019d6689c085ae165831e93:3Q9jfjfbMDuatto7wZ6Tz2aKaDCRHqWWys on Wed, 09 Jul 2025 20:17:12 GMT",
17
+ proof: "HxPmbzvEnvgu0RYIPYl5bWySkFNXwOF/Jegq3NvzjFZ/Ik/koTdV9rh2A7osXefhzTlniUw8YbZNmCeXB9V9qC8=",
18
+ }
19
+
20
+ const bitcoinP2shProof: SignatureProof = {
21
+ type: ProofTypes.BIP137,
22
+ wallet_provider: "Manual Wallet Signature",
23
+ status: ProofStatus.PENDING,
24
+ address: "bip122:000000000019d6689c085ae165831e93:1ANiqVALaKwadxA9nvmCUHpBhaopVniuVS",
25
+ did: "did:pkh:bip122:000000000019d6689c085ae165831e93:1ANiqVALaKwadxA9nvmCUHpBhaopVniuVS",
26
+ attestation: "I certify that the blockchain address 1ANiqVALaKwadxA9nvmCUHpBhaopVniuVS belongs to did:pkh:bip122:000000000019d6689c085ae165831e93:1ANiqVALaKwadxA9nvmCUHpBhaopVniuVS on Wed, 02 Jul 2025 16:01:44 GMT",
27
+ proof: "IBo2Im6O5NyuXzBJ+coiTMqmUsqG9bv8NzM3+B5e+5XMB2Xp1n/sIsE/73Jy0EdSvcb334t49+3tdjE/X+sXjFw="
28
+ }
29
+
10
30
  const bip322SegwitTestnetProof: SignatureProof = {
11
31
  type: ProofTypes.BIP137,
12
32
  address: "bip122:000000000019d6689c085ae165831e93:tb1q0apvgsh48f3rmw224na3ye5rrg37fd796cm0xf",
@@ -89,6 +109,16 @@ const zcashProof: SignatureProof = {
89
109
  };
90
110
 
91
111
  describe("verifyBTCSignature", () => {
112
+ it("handles bitcoin p2sh addresses", async () => {
113
+ const result = await verifyBTCSignature(bitcoinP2shProof);
114
+ expect(result).toEqual({ ...bitcoinP2shProof, status: ProofStatus.VERIFIED });
115
+ });
116
+
117
+ it("handles bitcoin p2wpkh addresses", async () => {
118
+ const result = await verifyBTCSignature(bitcoinP2WPKHProof);
119
+ expect(result).toEqual({ ...bitcoinP2WPKHProof, status: ProofStatus.VERIFIED });
120
+ });
121
+
92
122
  it("handles bip322 segwit testnet addresses", async () => {
93
123
  const result = await verifyBTCSignature(bip322SegwitTestnetProof);
94
124
  expect(result).toEqual({