@notabene/verify-proof 1.0.5 → 1.0.7

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/README.md CHANGED
@@ -39,6 +39,7 @@ async function checkProof(proof: OwnershipProof) {
39
39
  - Personal Sign EIP191 (`ProofTypes.EIP191`)
40
40
  - Personal Sign EIP712 (`ProofTypes.EIP712`)
41
41
  - Personal Sign BIP137 (`ProofTypes.BIP137`)
42
+ - BIP322 Signature (`ProofTypes.BIP322`)
42
43
  - Personal Sign XPUB (`ProofTypes.XPUB`)
43
44
  - Micro Transfer (`ProofTypes.MicroTransfer`)
44
45
 
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- var e=require("@notabene/javascript-sdk"),r=require("varuint-bitcoin"),t=require("@scure/base"),s=require("ox"),o=require("@noble/curves/secp256k1");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n,c,i=/*#__PURE__*/a(require("tweetnacl"));function u(){return u=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var s in t)({}).hasOwnProperty.call(t,s)&&(e[s]=t[s])}return e},u.apply(null,arguments)}!function(e){e.P2WPKH="p2wpkh",e.P2SH_P2WPKH="p2sh(p2wpkh)"}(n||(n={})),function(e){e.LEGACY="Legacy",e.NATIVE="Native SegWit",e.SEGWIT="SegWit",e.P2SH_SEGWIT="p2sh",e.BCH="Bitcoin Cash",e.ETHEREUM="Ethereum",e.DOGECOIN="Dogecoin",e.UNKNOWN="Unknown"}(c||(c={}));var f=t.createBase58check(s.Hash.sha256);function P(e){var r=t.bech32.toWords(e);return r.unshift(0),t.bech32.encode("bc",r)}exports.verifyProof=function(a){try{switch(a.type){case e.ProofTypes.SelfDeclaration:return Promise.resolve(u({},a,{status:a.confirmed?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}));case e.ProofTypes.Screenshot:return Promise.resolve(u({},a,{status:a.url?e.ProofStatus.FLAGGED:e.ProofStatus.FAILED}));case e.ProofTypes.EIP191:return Promise.resolve(function(r){try{var t=r.address.split(/:/),o=t[2];if("eip155"!==t[0])return Promise.resolve(u({},r,{status:e.ProofStatus.FAILED}));var a=function(e,r,t){try{var o=s.PersonalMessage.getSignPayload(s.Hex.fromString(r)),a=s.Signature.fromHex(t),n=s.Secp256k1.recoverPublicKey({payload:o,signature:a});return s.Address.checksum(s.Address.fromPublicKey(n)).toString()===s.Address.checksum(e)}catch(e){return!1}}(o,r.attestation,r.proof);return Promise.resolve(u({},r,{status:a?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(e){return Promise.reject(e)}}(a));case e.ProofTypes.ED25519:return Promise.resolve(function(r){try{var s=r.address.split(/:/),o=s[2];if("solana"!==s[0])return Promise.resolve(u({},r,{status:e.ProofStatus.FAILED}));try{var a=t.base58.decode(o),n=(new TextEncoder).encode(r.attestation),c=t.base64.decode(r.proof),f=i.default.sign.detached.verify(n,c,a);return Promise.resolve(u({},r,{status:f?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(t){return Promise.resolve(u({},r,{status:e.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(a));case e.ProofTypes.EIP712:case e.ProofTypes.BIP137:return Promise.resolve(function(a){try{var i=a.address.split(/:/),l=i[2];if("bip122"!==i[0])return Promise.resolve(u({},a,{status:e.ProofStatus.FAILED}));try{var h=[c.SEGWIT,c.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return c.NATIVE;if(e.match("^[32M].*"))return c.SEGWIT;if(e.match("^[1nmL].*"))return c.LEGACY;if(e.match("^(D).*"))return c.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(l)),d=function(e,a,c,i){var u=function(e){var r=t.base64.decode(e);if(65!==r.length)throw new Error("Invalid signature length");var s=r[0]-27;if(s>15||s<0)throw new Error("Invalid signature parameter");var a=!!(12&s),c=3&s,i=o.secp256k1.Signature.fromCompact(r.slice(1));return{compressed:a,segwitType:8&s?4&s?n.P2WPKH:n.P2SH_P2WPKH:void 0,signature:i.addRecoveryBit(c)}}(c),l=u.segwitType,h=u.signature;if(i&&!u.compressed)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var d,v=function(e){var t=(new TextEncoder).encode("Bitcoin Signed Message:\n"),o=(new TextEncoder).encode(e),a=r.encode(o.length).buffer,n=new Uint8Array(t.length+a.byteLength+o.length);return n.set(t),n.set(new Uint8Array(a),t.length),n.set(o,t.length+a.byteLength),function(e){return s.Hash.sha256(s.Hash.sha256(e))}(n)}(e),E=(d=h.recoverPublicKey(v).toRawBytes(),s.Hash.ripemd160(s.Hash.sha256(d))),y="";if(l)y=P(E);else if(i)try{y=P(E)}catch(e){y=P(E)}else y=function(e,r){var t=new Uint8Array([0].concat(r));return f.encode(t)}(0,E);return y===a}(a.attestation,l,a.proof,h);return Promise.resolve(u({},a,{status:d?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(r){return Promise.resolve(u({},a,{status:e.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(a));case e.ProofTypes.TIP191:return Promise.resolve(function(r){try{var o=r.address.split(/:/),a=o[2];if("tron"!==o[0])return Promise.resolve(u({},r,{status:e.ProofStatus.FAILED}));var n=function(e,r,o){try{var a=(l=s.Hex.fromString(r),s.Hash.keccak256(function(e){var r=s.Hex.from(e);return s.Hex.concat("0x19",s.Hex.fromString("TRON Signed Message:\n"+s.Hex.size(r)),r)}(l))),n=s.Signature.fromHex(o),c=s.Secp256k1.recoverPublicKey({payload:a,signature:n}),i="0x41"+s.Hash.keccak256("0x"+s.PublicKey.toHex(c).slice(4)).substring(26),u=s.Bytes.from(i),f=s.Bytes.from(s.Hash.sha256(s.Hash.sha256(i))).slice(0,4),P=s.Bytes.concat(u,f);return t.base58.encode(P)===e}catch(e){return!1}var l}(a,r.attestation,r.proof);return Promise.resolve(u({},r,{status:n?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(e){return Promise.reject(e)}}(a))}return Promise.resolve(a)}catch(e){return Promise.reject(e)}};
1
+ var e=require("@notabene/javascript-sdk"),r=require("varuint-bitcoin"),t=require("@scure/base"),s=require("ox"),o=require("@noble/curves/secp256k1"),a=require("bip322-js");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var i,c,u=/*#__PURE__*/n(require("tweetnacl"));function f(){return f=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var s in t)({}).hasOwnProperty.call(t,s)&&(e[s]=t[s])}return e},f.apply(null,arguments)}!function(e){e.P2WPKH="p2wpkh",e.P2SH_P2WPKH="p2sh(p2wpkh)"}(i||(i={})),function(e){e.LEGACY="Legacy",e.NATIVE="Native SegWit",e.SEGWIT="SegWit",e.P2SH_SEGWIT="p2sh",e.BCH="Bitcoin Cash",e.ETHEREUM="Ethereum",e.DOGECOIN="Dogecoin",e.UNKNOWN="Unknown"}(c||(c={}));var P=t.createBase58check(s.Hash.sha256);function l(e){var r=t.bech32.toWords(e);return r.unshift(0),t.bech32.encode("bc",r)}exports.verifyProof=function(n){try{switch(n.type){case e.ProofTypes.SelfDeclaration:return Promise.resolve(f({},n,{status:n.confirmed?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}));case e.ProofTypes.Screenshot:return Promise.resolve(f({},n,{status:n.url?e.ProofStatus.FLAGGED:e.ProofStatus.FAILED}));case e.ProofTypes.EIP191:return Promise.resolve(function(r){try{var t=r.address.split(/:/),o=t[2];if("eip155"!==t[0])return Promise.resolve(f({},r,{status:e.ProofStatus.FAILED}));var a=function(e,r,t){try{var o=s.PersonalMessage.getSignPayload(s.Hex.fromString(r)),a=s.Signature.fromHex(t),n=s.Secp256k1.recoverPublicKey({payload:o,signature:a});return s.Address.checksum(s.Address.fromPublicKey(n)).toString()===s.Address.checksum(e)}catch(e){return!1}}(o,r.attestation,r.proof);return Promise.resolve(f({},r,{status:a?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(e){return Promise.reject(e)}}(n));case e.ProofTypes.ED25519:return Promise.resolve(function(r){try{var s=r.address.split(/:/),o=s[2];if("solana"!==s[0])return Promise.resolve(f({},r,{status:e.ProofStatus.FAILED}));try{var a=t.base58.decode(o),n=(new TextEncoder).encode(r.attestation),i=t.base64.decode(r.proof),c=u.default.sign.detached.verify(n,i,a);return Promise.resolve(f({},r,{status:c?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(t){return Promise.resolve(f({},r,{status:e.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(n));case e.ProofTypes.EIP712:case e.ProofTypes.BIP137:case e.ProofTypes.BIP322:return Promise.resolve(function(n){try{var u=n.address.split(/:/),h=u[2];if("bip122"!==u[0])return Promise.resolve(f({},n,{status:e.ProofStatus.FAILED}));try{switch(n.type){case e.ProofTypes.BIP137:return Promise.resolve(function(a,n){var u=[c.SEGWIT,c.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return c.NATIVE;if(e.match("^[32M].*"))return c.SEGWIT;if(e.match("^[1nmL].*"))return c.LEGACY;if(e.match("^(D).*"))return c.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(a)),h=function(e,a,n,c){var u=function(e){var r=t.base64.decode(e);if(65!==r.length)throw new Error("Invalid signature length");var s=r[0]-27;if(s>15||s<0)throw new Error("Invalid signature parameter");var a=!!(12&s),n=3&s,c=o.secp256k1.Signature.fromCompact(r.slice(1));return{compressed:a,segwitType:8&s?4&s?i.P2WPKH:i.P2SH_P2WPKH:void 0,signature:c.addRecoveryBit(n)}}(n),f=u.compressed,h=u.segwitType,d=u.signature;if(c&&!f)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var v,p=function(e){var t=(new TextEncoder).encode("Bitcoin Signed Message:\n"),o=(new TextEncoder).encode(e),a=r.encode(o.length).buffer,n=new Uint8Array(t.length+a.byteLength+o.length);return n.set(t),n.set(new Uint8Array(a),t.length),n.set(o,t.length+a.byteLength),function(e){return s.Hash.sha256(s.Hash.sha256(e))}(n)}(e),y=(v=d.recoverPublicKey(p).toRawBytes(f),s.Hash.ripemd160(s.Hash.sha256(v))),E="";if(h)E=l(y);else if(c)try{E=l(y)}catch(e){E=l(y)}else E=function(e,r){var t=new Uint8Array([0].concat(r));return P.encode(t)}(0,y);return E===a}(n.attestation,a,n.proof,u);return f({},n,{status:h?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED})}(h,n));case e.ProofTypes.BIP322:return Promise.resolve(function(r,t){return f({},t,{status:a.Verifier.verifySignature(r,t.attestation,t.proof)?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED})}(h,n));default:return Promise.resolve(f({},n,{status:e.ProofStatus.FAILED}))}}catch(r){return Promise.resolve(f({},n,{status:e.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(n));case e.ProofTypes.TIP191:return Promise.resolve(function(r){try{var o=r.address.split(/:/),a=o[2];if("tron"!==o[0])return Promise.resolve(f({},r,{status:e.ProofStatus.FAILED}));var n=function(e,r,o){try{var a=(l=s.Hex.fromString(r),s.Hash.keccak256(function(e){var r=s.Hex.from(e);return s.Hex.concat("0x19",s.Hex.fromString("TRON Signed Message:\n"+s.Hex.size(r)),r)}(l))),n=s.Signature.fromHex(o),i=s.Secp256k1.recoverPublicKey({payload:a,signature:n}),c="0x41"+s.Hash.keccak256("0x"+s.PublicKey.toHex(i).slice(4)).substring(26),u=s.Bytes.from(c),f=s.Bytes.from(s.Hash.sha256(s.Hash.sha256(c))).slice(0,4),P=s.Bytes.concat(u,f);return t.base58.encode(P)===e}catch(e){return!1}var l}(a,r.attestation,r.proof);return Promise.resolve(f({},r,{status:n?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(e){return Promise.reject(e)}}(n))}return Promise.resolve(n)}catch(e){return Promise.reject(e)}};
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/bitcoin.ts","../src/index.ts","../src/eth.ts","../src/solana.ts","../src/tron.ts"],"sourcesContent":["import { ProofStatus, SignatureProof } 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\";\nenum SEGWIT_TYPES {\n P2WPKH = \"p2wpkh\",\n P2SH_P2WPKH = \"p2sh(p2wpkh)\",\n}\n\nconst messagePrefix = \"\\u0018Bitcoin Signed Message:\\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 try {\n // const messageToBeSigned = message.replace(/\\s+/g, \" \").trim();\n const segwit = [DerivationMode.SEGWIT, DerivationMode.NATIVE].includes(\n getDerivationMode(address),\n );\n const verified = verify(proof.attestation, address, proof.proof, segwit);\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n } catch (error) {\n // console.error(\"error verifying proof\", error);\n return {\n ...proof,\n status: ProofStatus.FAILED,\n // error: error.message || error,\n };\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 {\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) {\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);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyHash = hash160(publicKey.toRawBytes());\n let actual: string = \"\";\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n actual = encodeBech32Address(publicKeyHash);\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n // must be true since we only return null, P2SH_P2WPKH, or P2WPKH\n // from the decodeSignature function.\n actual = encodeBech32Address(publicKeyHash);\n }\n } else {\n if (checkSegwitAlways) {\n try {\n actual = encodeBech32Address(publicKeyHash);\n // if address is bech32 it is not p2sh\n } catch (e) {\n actual = encodeBech32Address(publicKeyHash);\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(0, publicKeyHash);\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(version: number, publicKeyHash: Uint8Array) {\n const payload = new Uint8Array([version, ...publicKeyHash]);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: 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(publicKeyHash: Uint8Array): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(\"bc\", 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","import {\n type OwnershipProof,\n SignatureProof,\n DeclarationProof,\n ScreenshotProof,\n ProofTypes,\n ProofStatus,\n} from \"@notabene/javascript-sdk\";\nimport { verifyBTCSignature } from \"./bitcoin\";\nimport { verifyPersonalSignEIP191 } from \"./eth\";\nimport { verifySolanaSignature } from \"./solana\";\nimport { verifyPersonalSignTIP191 } from \"./tron\";\n\nexport async function verifyProof(\n proof: OwnershipProof,\n): Promise<OwnershipProof> {\n switch (proof.type) {\n case ProofTypes.SelfDeclaration:\n return {\n ...proof,\n status: (proof as DeclarationProof).confirmed\n ? ProofStatus.VERIFIED\n : ProofStatus.FAILED,\n };\n case ProofTypes.Screenshot:\n return {\n ...proof,\n status: (proof as ScreenshotProof).url\n ? ProofStatus.FLAGGED\n : ProofStatus.FAILED,\n };\n case ProofTypes.EIP191:\n return verifyPersonalSignEIP191(proof as SignatureProof);\n case ProofTypes.ED25519:\n return verifySolanaSignature(proof as SignatureProof);\n case ProofTypes.EIP712:\n case ProofTypes.BIP137:\n return verifyBTCSignature(proof as SignatureProof);\n case ProofTypes.TIP191:\n return verifyPersonalSignTIP191(proof as SignatureProof);\n case ProofTypes.BIP137_XPUB:\n case ProofTypes.MicroTransfer:\n }\n return proof;\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, PersonalMessage, Signature, Address } from \"ox\";\n\nexport function verifyEIP191(\n address: Hex.Hex,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = PersonalMessage.getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const recovered = Address.checksum(Address.fromPublicKey(publicKey));\n return recovered.toString() === Address.checksum(address);\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignEIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, _, address] = proof.address.split(/:/);\n if (ns !== \"eip155\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyEIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n","import nacl from \"tweetnacl\";\nimport { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { base64, base58 } from \"@scure/base\";\n\nexport async function verifySolanaSignature(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, _, address] = proof.address.split(/:/);\n if (ns !== \"solana\") return { ...proof, status: ProofStatus.FAILED };\n try {\n const publicKey = base58.decode(address);\n const messageBytes = new TextEncoder().encode(proof.attestation);\n const signatureBytes = base64.decode(proof.proof);\n const verified = nacl.sign.detached.verify(\n messageBytes,\n signatureBytes,\n publicKey,\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n } catch (error) {\n return { ...proof, status: ProofStatus.FAILED };\n }\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, Signature, Hash, Bytes, PublicKey } from \"ox\";\nimport { base58 } from \"@scure/base\";\n\nexport function verifyTIP191(\n address: string,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const hex: Hex.Hex = `0x41${Hash.keccak256(\n `0x${PublicKey.toHex(publicKey).slice(4)}`,\n ).substring(26)}`;\n const bytes = Bytes.from(hex);\n const checksum = Bytes.from(Hash.sha256(Hash.sha256(hex))).slice(0, 4);\n const checked = Bytes.concat(bytes, checksum);\n const b58 = base58.encode(checked);\n return b58 === address;\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignTIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, _, address] = proof.address.split(/:/);\n if (ns !== \"tron\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyTIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nexport function encode(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n const message = Hex.from(data);\n return Hex.concat(\n // Personal Sign Format: `0x19 ‖ \"Ethereum Signed Message:\\n\" ‖ message.length ‖ message`\n \"0x19\",\n Hex.fromString(\"TRON Signed Message:\\n\" + Hex.size(message)),\n message,\n );\n}\nexport function getSignPayload(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n return Hash.keccak256(encode(data));\n}\n"],"names":["SEGWIT_TYPES","DerivationMode","base58check","createBase58check","Hash","sha256","encodeBech32Address","publicKeyHash","bwords","bech32","toWords","unshift","encode","proof","type","ProofTypes","SelfDeclaration","Promise","resolve","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","_proof$address$split","address","split","_","verified","message","payload","PersonalMessage","getSignPayload","Hex","fromString","signature","Signature","fromHex","publicKey","Secp256k1","recoverPublicKey","Address","checksum","fromPublicKey","toString","error","verifyEIP191","attestation","e","reject","verifyPersonalSignEIP191","ED25519","base58","decode","messageBytes","TextEncoder","signatureBytes","base64","nacl","sign","detached","verify","verifySolanaSignature","EIP712","BIP137","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","checkSegwitAlways","_decodeSignature","sigbytes","length","flagByte","compressed","recovery","secp256k1","fromCompact","slice","segwitType","P2WPKH","P2SH_P2WPKH","undefined","addRecoveryBit","decodeSignature","buffer","hash","prefix","encodeLength","Uint8Array","byteLength","set","hash256","magicHash","toRawBytes","ripemd160","actual","version","encodeBase58AddressFormat","verifyBTCSignature","TIP191","data","keccak256","from","size","hex","PublicKey","toHex","substring","bytes","Bytes","checked","verifyTIP191","verifyPersonalSignTIP191"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/bitcoin.ts","../src/index.ts","../src/eth.ts","../src/solana.ts","../src/tron.ts"],"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\nconst messagePrefix = \"\\u0018Bitcoin Signed Message:\\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 try {\n switch (proof.type) {\n case ProofTypes.BIP137:\n return verifyBIP137(address, proof);\n case ProofTypes.BIP322:\n return verifyBIP322(address, proof);\n default:\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n // console.error(\"error verifying proof\", error);\n return {\n ...proof,\n status: ProofStatus.FAILED,\n // error: error.message || error,\n };\n }\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(address: string, proof: SignatureProof) {\n // const messageToBeSigned = message.replace(/\\s+/g, \" \").trim();\n const segwit = [DerivationMode.SEGWIT, DerivationMode.NATIVE].includes(\n getDerivationMode(address)\n );\n const verified = verify(proof.attestation, address, proof.proof, segwit);\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 {\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) {\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);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyBytes = publicKey.toRawBytes(compressed);\n const publicKeyHash = hash160(publicKeyBytes);\n let actual: string = \"\";\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n actual = encodeBech32Address(publicKeyHash);\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n // must be true since we only return null, P2SH_P2WPKH, or P2WPKH\n // from the decodeSignature function.\n actual = encodeBech32Address(publicKeyHash);\n }\n } else {\n if (checkSegwitAlways) {\n try {\n actual = encodeBech32Address(publicKeyHash);\n // if address is bech32 it is not p2sh\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (e) {\n actual = encodeBech32Address(publicKeyHash);\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(0, publicKeyHash);\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(version: number, publicKeyHash: Uint8Array) {\n const payload = new Uint8Array([version, ...publicKeyHash]);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: 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(publicKeyHash: Uint8Array): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(\"bc\", 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","import {\n type OwnershipProof,\n SignatureProof,\n DeclarationProof,\n ScreenshotProof,\n ProofTypes,\n ProofStatus,\n} from \"@notabene/javascript-sdk\";\nimport { verifyBTCSignature } from \"./bitcoin\";\nimport { verifyPersonalSignEIP191 } from \"./eth\";\nimport { verifySolanaSignature } from \"./solana\";\nimport { verifyPersonalSignTIP191 } from \"./tron\";\n\nexport async function verifyProof(\n proof: OwnershipProof\n): Promise<OwnershipProof> {\n switch (proof.type) {\n case ProofTypes.SelfDeclaration:\n return {\n ...proof,\n status: (proof as DeclarationProof).confirmed\n ? ProofStatus.VERIFIED\n : ProofStatus.FAILED,\n };\n case ProofTypes.Screenshot:\n return {\n ...proof,\n status: (proof as ScreenshotProof).url\n ? ProofStatus.FLAGGED\n : ProofStatus.FAILED,\n };\n case ProofTypes.EIP191:\n return verifyPersonalSignEIP191(proof as SignatureProof);\n case ProofTypes.ED25519:\n return verifySolanaSignature(proof as SignatureProof);\n case ProofTypes.EIP712:\n case ProofTypes.BIP137:\n case ProofTypes.BIP322:\n return verifyBTCSignature(proof as SignatureProof);\n case ProofTypes.TIP191:\n return verifyPersonalSignTIP191(proof as SignatureProof);\n case ProofTypes.BIP137_XPUB:\n case ProofTypes.MicroTransfer:\n }\n return proof;\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, PersonalMessage, Signature, Address } from \"ox\";\n\nexport function verifyEIP191(\n address: Hex.Hex,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = PersonalMessage.getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const recovered = Address.checksum(Address.fromPublicKey(publicKey));\n return recovered.toString() === Address.checksum(address);\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignEIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"eip155\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyEIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n","import nacl from \"tweetnacl\";\nimport { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { base64, base58 } from \"@scure/base\";\n\nexport async function verifySolanaSignature(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"solana\") return { ...proof, status: ProofStatus.FAILED };\n try {\n const publicKey = base58.decode(address);\n const messageBytes = new TextEncoder().encode(proof.attestation);\n const signatureBytes = base64.decode(proof.proof);\n const verified = nacl.sign.detached.verify(\n messageBytes,\n signatureBytes,\n publicKey,\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return { ...proof, status: ProofStatus.FAILED };\n }\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, Signature, Hash, Bytes, PublicKey } from \"ox\";\nimport { base58 } from \"@scure/base\";\n\nexport function verifyTIP191(\n address: string,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const hex: Hex.Hex = `0x41${Hash.keccak256(\n `0x${PublicKey.toHex(publicKey).slice(4)}`,\n ).substring(26)}`;\n const bytes = Bytes.from(hex);\n const checksum = Bytes.from(Hash.sha256(Hash.sha256(hex))).slice(0, 4);\n const checked = Bytes.concat(bytes, checksum);\n const b58 = base58.encode(checked);\n return b58 === address;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignTIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"tron\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyTIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nexport function encode(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n const message = Hex.from(data);\n return Hex.concat(\n // Personal Sign Format: `0x19 ‖ \"Ethereum Signed Message:\\n\" ‖ message.length ‖ message`\n \"0x19\",\n Hex.fromString(\"TRON Signed Message:\\n\" + Hex.size(message)),\n message,\n );\n}\nexport function getSignPayload(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n return Hash.keccak256(encode(data));\n}\n"],"names":["SEGWIT_TYPES","DerivationMode","base58check","createBase58check","Hash","sha256","encodeBech32Address","publicKeyHash","bwords","bech32","toWords","unshift","encode","proof","type","ProofTypes","SelfDeclaration","Promise","resolve","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","_proof$address$split","address","split","verified","message","payload","PersonalMessage","getSignPayload","Hex","fromString","signature","Signature","fromHex","publicKey","Secp256k1","recoverPublicKey","Address","checksum","fromPublicKey","toString","error","verifyEIP191","attestation","e","reject","verifyPersonalSignEIP191","ED25519","base58","decode","messageBytes","TextEncoder","signatureBytes","base64","nacl","sign","detached","verify","verifySolanaSignature","EIP712","BIP137","BIP322","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","checkSegwitAlways","_decodeSignature","sigbytes","length","flagByte","compressed","recovery","secp256k1","fromCompact","slice","segwitType","P2WPKH","P2SH_P2WPKH","undefined","addRecoveryBit","decodeSignature","buffer","hash","prefix","encodeLength","Uint8Array","byteLength","set","hash256","magicHash","toRawBytes","ripemd160","actual","version","encodeBase58AddressFormat","verifyBIP137","Verifier","verifySignature","verifyBIP322","verifyBTCSignature","TIP191","data","keccak256","from","size","hex","PublicKey","toHex","substring","bytes","Bytes","checked","verifyTIP191","verifyPersonalSignTIP191"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{ProofStatus as e,ProofTypes as r}from"@notabene/javascript-sdk";import{encode as t}from"varuint-bitcoin";import{createBase58check as n,bech32 as o,base64 as s,base58 as a}from"@scure/base";import{Hash as i,PersonalMessage as c,Hex as u,Signature as f,Secp256k1 as l,Address as m,PublicKey as v,Bytes as d}from"ox";import{secp256k1 as h}from"@noble/curves/secp256k1";import E from"tweetnacl";function P(){return P=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var n in t)({}).hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e},P.apply(null,arguments)}var p,g;!function(e){e.P2WPKH="p2wpkh",e.P2SH_P2WPKH="p2sh(p2wpkh)"}(p||(p={})),function(e){e.LEGACY="Legacy",e.NATIVE="Native SegWit",e.SEGWIT="SegWit",e.P2SH_SEGWIT="p2sh",e.BCH="Bitcoin Cash",e.ETHEREUM="Ethereum",e.DOGECOIN="Dogecoin",e.UNKNOWN="Unknown"}(g||(g={}));var I=n(i.sha256);function y(e){var r=o.toWords(e);return r.unshift(0),o.encode("bc",r)}var D=function(n){try{switch(n.type){case r.SelfDeclaration:return Promise.resolve(P({},n,{status:n.confirmed?e.VERIFIED:e.FAILED}));case r.Screenshot:return Promise.resolve(P({},n,{status:n.url?e.FLAGGED:e.FAILED}));case r.EIP191:return Promise.resolve(function(r){try{var t=r.address.split(/:/),n=t[2];if("eip155"!==t[0])return Promise.resolve(P({},r,{status:e.FAILED}));var o=function(e,r,t){try{var n=c.getSignPayload(u.fromString(r)),o=f.fromHex(t),s=l.recoverPublicKey({payload:n,signature:o});return m.checksum(m.fromPublicKey(s)).toString()===m.checksum(e)}catch(e){return!1}}(n,r.attestation,r.proof);return Promise.resolve(P({},r,{status:o?e.VERIFIED:e.FAILED}))}catch(e){return Promise.reject(e)}}(n));case r.ED25519:return Promise.resolve(function(r){try{var t=r.address.split(/:/),n=t[2];if("solana"!==t[0])return Promise.resolve(P({},r,{status:e.FAILED}));try{var o=a.decode(n),i=(new TextEncoder).encode(r.attestation),c=s.decode(r.proof),u=E.sign.detached.verify(i,c,o);return Promise.resolve(P({},r,{status:u?e.VERIFIED:e.FAILED}))}catch(t){return Promise.resolve(P({},r,{status:e.FAILED}))}}catch(e){return Promise.reject(e)}}(n));case r.EIP712:case r.BIP137:return Promise.resolve(function(r){try{var n=r.address.split(/:/),o=n[2];if("bip122"!==n[0])return Promise.resolve(P({},r,{status:e.FAILED}));try{var a=[g.SEGWIT,g.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return g.NATIVE;if(e.match("^[32M].*"))return g.SEGWIT;if(e.match("^[1nmL].*"))return g.LEGACY;if(e.match("^(D).*"))return g.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(o)),c=function(e,r,n,o){var a=function(e){var r=s.decode(e);if(65!==r.length)throw new Error("Invalid signature length");var t=r[0]-27;if(t>15||t<0)throw new Error("Invalid signature parameter");var n=!!(12&t),o=3&t,a=h.Signature.fromCompact(r.slice(1));return{compressed:n,segwitType:8&t?4&t?p.P2WPKH:p.P2SH_P2WPKH:void 0,signature:a.addRecoveryBit(o)}}(n),c=a.segwitType,u=a.signature;if(o&&!a.compressed)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var f,l=function(e){var r=(new TextEncoder).encode("Bitcoin Signed Message:\n"),n=(new TextEncoder).encode(e),o=t(n.length).buffer,s=new Uint8Array(r.length+o.byteLength+n.length);return s.set(r),s.set(new Uint8Array(o),r.length),s.set(n,r.length+o.byteLength),function(e){return i.sha256(i.sha256(e))}(s)}(e),m=(f=u.recoverPublicKey(l).toRawBytes(),i.ripemd160(i.sha256(f))),v="";if(c)v=y(m);else if(o)try{v=y(m)}catch(e){v=y(m)}else v=function(e,r){var t=new Uint8Array([0].concat(r));return I.encode(t)}(0,m);return v===r}(r.attestation,o,r.proof,a);return Promise.resolve(P({},r,{status:c?e.VERIFIED:e.FAILED}))}catch(t){return Promise.resolve(P({},r,{status:e.FAILED}))}}catch(e){return Promise.reject(e)}}(n));case r.TIP191:return Promise.resolve(function(r){try{var t=r.address.split(/:/),n=t[2];if("tron"!==t[0])return Promise.resolve(P({},r,{status:e.FAILED}));var o=function(e,r,t){try{var n=(P=u.fromString(r),i.keccak256(function(e){var r=u.from(e);return u.concat("0x19",u.fromString("TRON Signed Message:\n"+u.size(r)),r)}(P))),o=f.fromHex(t),s=l.recoverPublicKey({payload:n,signature:o}),c="0x41"+i.keccak256("0x"+v.toHex(s).slice(4)).substring(26),m=d.from(c),h=d.from(i.sha256(i.sha256(c))).slice(0,4),E=d.concat(m,h);return a.encode(E)===e}catch(e){return!1}var P}(n,r.attestation,r.proof);return Promise.resolve(P({},r,{status:o?e.VERIFIED:e.FAILED}))}catch(e){return Promise.reject(e)}}(n))}return Promise.resolve(n)}catch(e){return Promise.reject(e)}};export{D as verifyProof};
1
+ import{ProofStatus as e,ProofTypes as r}from"@notabene/javascript-sdk";import{encode as t}from"varuint-bitcoin";import{createBase58check as n,bech32 as o,base64 as s,base58 as a}from"@scure/base";import{Hash as i,PersonalMessage as c,Hex as u,Signature as f,Secp256k1 as l,Address as m,PublicKey as v,Bytes as E}from"ox";import{secp256k1 as d}from"@noble/curves/secp256k1";import{Verifier as h}from"bip322-js";import P from"tweetnacl";function p(){return p=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var n in t)({}).hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e},p.apply(null,arguments)}var I,g;!function(e){e.P2WPKH="p2wpkh",e.P2SH_P2WPKH="p2sh(p2wpkh)"}(I||(I={})),function(e){e.LEGACY="Legacy",e.NATIVE="Native SegWit",e.SEGWIT="SegWit",e.P2SH_SEGWIT="p2sh",e.BCH="Bitcoin Cash",e.ETHEREUM="Ethereum",e.DOGECOIN="Dogecoin",e.UNKNOWN="Unknown"}(g||(g={}));var y=n(i.sha256);function D(e){var r=o.toWords(e);return r.unshift(0),o.encode("bc",r)}var w=function(n){try{switch(n.type){case r.SelfDeclaration:return Promise.resolve(p({},n,{status:n.confirmed?e.VERIFIED:e.FAILED}));case r.Screenshot:return Promise.resolve(p({},n,{status:n.url?e.FLAGGED:e.FAILED}));case r.EIP191:return Promise.resolve(function(r){try{var t=r.address.split(/:/),n=t[2];if("eip155"!==t[0])return Promise.resolve(p({},r,{status:e.FAILED}));var o=function(e,r,t){try{var n=c.getSignPayload(u.fromString(r)),o=f.fromHex(t),s=l.recoverPublicKey({payload:n,signature:o});return m.checksum(m.fromPublicKey(s)).toString()===m.checksum(e)}catch(e){return!1}}(n,r.attestation,r.proof);return Promise.resolve(p({},r,{status:o?e.VERIFIED:e.FAILED}))}catch(e){return Promise.reject(e)}}(n));case r.ED25519:return Promise.resolve(function(r){try{var t=r.address.split(/:/),n=t[2];if("solana"!==t[0])return Promise.resolve(p({},r,{status:e.FAILED}));try{var o=a.decode(n),i=(new TextEncoder).encode(r.attestation),c=s.decode(r.proof),u=P.sign.detached.verify(i,c,o);return Promise.resolve(p({},r,{status:u?e.VERIFIED:e.FAILED}))}catch(t){return Promise.resolve(p({},r,{status:e.FAILED}))}}catch(e){return Promise.reject(e)}}(n));case r.EIP712:case r.BIP137:case r.BIP322:return Promise.resolve(function(n){try{var o=n.address.split(/:/),a=o[2];if("bip122"!==o[0])return Promise.resolve(p({},n,{status:e.FAILED}));try{switch(n.type){case r.BIP137:return Promise.resolve(function(r,n){var o=[g.SEGWIT,g.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return g.NATIVE;if(e.match("^[32M].*"))return g.SEGWIT;if(e.match("^[1nmL].*"))return g.LEGACY;if(e.match("^(D).*"))return g.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(r)),a=function(e,r,n,o){var a=function(e){var r=s.decode(e);if(65!==r.length)throw new Error("Invalid signature length");var t=r[0]-27;if(t>15||t<0)throw new Error("Invalid signature parameter");var n=!!(12&t),o=3&t,a=d.Signature.fromCompact(r.slice(1));return{compressed:n,segwitType:8&t?4&t?I.P2WPKH:I.P2SH_P2WPKH:void 0,signature:a.addRecoveryBit(o)}}(n),c=a.compressed,u=a.segwitType,f=a.signature;if(o&&!c)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var l,m=function(e){var r=(new TextEncoder).encode("Bitcoin Signed Message:\n"),n=(new TextEncoder).encode(e),o=t(n.length).buffer,s=new Uint8Array(r.length+o.byteLength+n.length);return s.set(r),s.set(new Uint8Array(o),r.length),s.set(n,r.length+o.byteLength),function(e){return i.sha256(i.sha256(e))}(s)}(e),v=(l=f.recoverPublicKey(m).toRawBytes(c),i.ripemd160(i.sha256(l))),E="";if(u)E=D(v);else if(o)try{E=D(v)}catch(e){E=D(v)}else E=function(e,r){var t=new Uint8Array([0].concat(r));return y.encode(t)}(0,v);return E===r}(n.attestation,r,n.proof,o);return p({},n,{status:a?e.VERIFIED:e.FAILED})}(a,n));case r.BIP322:return Promise.resolve(function(r,t){return p({},t,{status:h.verifySignature(r,t.attestation,t.proof)?e.VERIFIED:e.FAILED})}(a,n));default:return Promise.resolve(p({},n,{status:e.FAILED}))}}catch(r){return Promise.resolve(p({},n,{status:e.FAILED}))}}catch(e){return Promise.reject(e)}}(n));case r.TIP191:return Promise.resolve(function(r){try{var t=r.address.split(/:/),n=t[2];if("tron"!==t[0])return Promise.resolve(p({},r,{status:e.FAILED}));var o=function(e,r,t){try{var n=(P=u.fromString(r),i.keccak256(function(e){var r=u.from(e);return u.concat("0x19",u.fromString("TRON Signed Message:\n"+u.size(r)),r)}(P))),o=f.fromHex(t),s=l.recoverPublicKey({payload:n,signature:o}),c="0x41"+i.keccak256("0x"+v.toHex(s).slice(4)).substring(26),m=E.from(c),d=E.from(i.sha256(i.sha256(c))).slice(0,4),h=E.concat(m,d);return a.encode(h)===e}catch(e){return!1}var P}(n,r.attestation,r.proof);return Promise.resolve(p({},r,{status:o?e.VERIFIED:e.FAILED}))}catch(e){return Promise.reject(e)}}(n))}return Promise.resolve(n)}catch(e){return Promise.reject(e)}};export{w as verifyProof};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/bitcoin.ts","../src/eth.ts","../src/index.ts","../src/solana.ts","../src/tron.ts"],"sourcesContent":["import { ProofStatus, SignatureProof } 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\";\nenum SEGWIT_TYPES {\n P2WPKH = \"p2wpkh\",\n P2SH_P2WPKH = \"p2sh(p2wpkh)\",\n}\n\nconst messagePrefix = \"\\u0018Bitcoin Signed Message:\\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 try {\n // const messageToBeSigned = message.replace(/\\s+/g, \" \").trim();\n const segwit = [DerivationMode.SEGWIT, DerivationMode.NATIVE].includes(\n getDerivationMode(address),\n );\n const verified = verify(proof.attestation, address, proof.proof, segwit);\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n } catch (error) {\n // console.error(\"error verifying proof\", error);\n return {\n ...proof,\n status: ProofStatus.FAILED,\n // error: error.message || error,\n };\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 {\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) {\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);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyHash = hash160(publicKey.toRawBytes());\n let actual: string = \"\";\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n actual = encodeBech32Address(publicKeyHash);\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n // must be true since we only return null, P2SH_P2WPKH, or P2WPKH\n // from the decodeSignature function.\n actual = encodeBech32Address(publicKeyHash);\n }\n } else {\n if (checkSegwitAlways) {\n try {\n actual = encodeBech32Address(publicKeyHash);\n // if address is bech32 it is not p2sh\n } catch (e) {\n actual = encodeBech32Address(publicKeyHash);\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(0, publicKeyHash);\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(version: number, publicKeyHash: Uint8Array) {\n const payload = new Uint8Array([version, ...publicKeyHash]);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: 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(publicKeyHash: Uint8Array): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(\"bc\", 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","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, PersonalMessage, Signature, Address } from \"ox\";\n\nexport function verifyEIP191(\n address: Hex.Hex,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = PersonalMessage.getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const recovered = Address.checksum(Address.fromPublicKey(publicKey));\n return recovered.toString() === Address.checksum(address);\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignEIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, _, address] = proof.address.split(/:/);\n if (ns !== \"eip155\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyEIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n","import {\n type OwnershipProof,\n SignatureProof,\n DeclarationProof,\n ScreenshotProof,\n ProofTypes,\n ProofStatus,\n} from \"@notabene/javascript-sdk\";\nimport { verifyBTCSignature } from \"./bitcoin\";\nimport { verifyPersonalSignEIP191 } from \"./eth\";\nimport { verifySolanaSignature } from \"./solana\";\nimport { verifyPersonalSignTIP191 } from \"./tron\";\n\nexport async function verifyProof(\n proof: OwnershipProof,\n): Promise<OwnershipProof> {\n switch (proof.type) {\n case ProofTypes.SelfDeclaration:\n return {\n ...proof,\n status: (proof as DeclarationProof).confirmed\n ? ProofStatus.VERIFIED\n : ProofStatus.FAILED,\n };\n case ProofTypes.Screenshot:\n return {\n ...proof,\n status: (proof as ScreenshotProof).url\n ? ProofStatus.FLAGGED\n : ProofStatus.FAILED,\n };\n case ProofTypes.EIP191:\n return verifyPersonalSignEIP191(proof as SignatureProof);\n case ProofTypes.ED25519:\n return verifySolanaSignature(proof as SignatureProof);\n case ProofTypes.EIP712:\n case ProofTypes.BIP137:\n return verifyBTCSignature(proof as SignatureProof);\n case ProofTypes.TIP191:\n return verifyPersonalSignTIP191(proof as SignatureProof);\n case ProofTypes.BIP137_XPUB:\n case ProofTypes.MicroTransfer:\n }\n return proof;\n}\n","import nacl from \"tweetnacl\";\nimport { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { base64, base58 } from \"@scure/base\";\n\nexport async function verifySolanaSignature(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, _, address] = proof.address.split(/:/);\n if (ns !== \"solana\") return { ...proof, status: ProofStatus.FAILED };\n try {\n const publicKey = base58.decode(address);\n const messageBytes = new TextEncoder().encode(proof.attestation);\n const signatureBytes = base64.decode(proof.proof);\n const verified = nacl.sign.detached.verify(\n messageBytes,\n signatureBytes,\n publicKey,\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n } catch (error) {\n return { ...proof, status: ProofStatus.FAILED };\n }\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, Signature, Hash, Bytes, PublicKey } from \"ox\";\nimport { base58 } from \"@scure/base\";\n\nexport function verifyTIP191(\n address: string,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const hex: Hex.Hex = `0x41${Hash.keccak256(\n `0x${PublicKey.toHex(publicKey).slice(4)}`,\n ).substring(26)}`;\n const bytes = Bytes.from(hex);\n const checksum = Bytes.from(Hash.sha256(Hash.sha256(hex))).slice(0, 4);\n const checked = Bytes.concat(bytes, checksum);\n const b58 = base58.encode(checked);\n return b58 === address;\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignTIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, _, address] = proof.address.split(/:/);\n if (ns !== \"tron\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyTIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nexport function encode(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n const message = Hex.from(data);\n return Hex.concat(\n // Personal Sign Format: `0x19 ‖ \"Ethereum Signed Message:\\n\" ‖ message.length ‖ message`\n \"0x19\",\n Hex.fromString(\"TRON Signed Message:\\n\" + Hex.size(message)),\n message,\n );\n}\nexport function getSignPayload(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n return Hash.keccak256(encode(data));\n}\n"],"names":["SEGWIT_TYPES","DerivationMode","base58check","createBase58check","Hash","sha256","encodeBech32Address","publicKeyHash","bwords","bech32","toWords","unshift","encode","verifyProof","proof","type","ProofTypes","SelfDeclaration","Promise","resolve","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","_proof$address$split","address","split","_","verified","message","payload","PersonalMessage","getSignPayload","Hex","fromString","signature","Signature","fromHex","publicKey","Secp256k1","recoverPublicKey","Address","checksum","fromPublicKey","toString","error","verifyEIP191","attestation","e","reject","verifyPersonalSignEIP191","ED25519","base58","decode","messageBytes","TextEncoder","signatureBytes","base64","nacl","sign","detached","verify","verifySolanaSignature","EIP712","BIP137","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","checkSegwitAlways","_decodeSignature","sigbytes","length","flagByte","compressed","recovery","secp256k1","fromCompact","slice","segwitType","P2WPKH","P2SH_P2WPKH","undefined","addRecoveryBit","decodeSignature","buffer","hash","prefix","encodeLength","Uint8Array","byteLength","set","hash256","magicHash","toRawBytes","ripemd160","actual","version","encodeBase58AddressFormat","verifyBTCSignature","TIP191","data","keccak256","from","size","hex","PublicKey","toHex","substring","bytes","Bytes","checked","verifyTIP191","verifyPersonalSignTIP191"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/bitcoin.ts","../src/eth.ts","../src/index.ts","../src/solana.ts","../src/tron.ts"],"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\nconst messagePrefix = \"\\u0018Bitcoin Signed Message:\\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 try {\n switch (proof.type) {\n case ProofTypes.BIP137:\n return verifyBIP137(address, proof);\n case ProofTypes.BIP322:\n return verifyBIP322(address, proof);\n default:\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n // console.error(\"error verifying proof\", error);\n return {\n ...proof,\n status: ProofStatus.FAILED,\n // error: error.message || error,\n };\n }\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(address: string, proof: SignatureProof) {\n // const messageToBeSigned = message.replace(/\\s+/g, \" \").trim();\n const segwit = [DerivationMode.SEGWIT, DerivationMode.NATIVE].includes(\n getDerivationMode(address)\n );\n const verified = verify(proof.attestation, address, proof.proof, segwit);\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 {\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) {\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);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyBytes = publicKey.toRawBytes(compressed);\n const publicKeyHash = hash160(publicKeyBytes);\n let actual: string = \"\";\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n actual = encodeBech32Address(publicKeyHash);\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n // must be true since we only return null, P2SH_P2WPKH, or P2WPKH\n // from the decodeSignature function.\n actual = encodeBech32Address(publicKeyHash);\n }\n } else {\n if (checkSegwitAlways) {\n try {\n actual = encodeBech32Address(publicKeyHash);\n // if address is bech32 it is not p2sh\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (e) {\n actual = encodeBech32Address(publicKeyHash);\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(0, publicKeyHash);\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(version: number, publicKeyHash: Uint8Array) {\n const payload = new Uint8Array([version, ...publicKeyHash]);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: 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(publicKeyHash: Uint8Array): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(\"bc\", 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","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, PersonalMessage, Signature, Address } from \"ox\";\n\nexport function verifyEIP191(\n address: Hex.Hex,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = PersonalMessage.getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const recovered = Address.checksum(Address.fromPublicKey(publicKey));\n return recovered.toString() === Address.checksum(address);\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignEIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"eip155\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyEIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n","import {\n type OwnershipProof,\n SignatureProof,\n DeclarationProof,\n ScreenshotProof,\n ProofTypes,\n ProofStatus,\n} from \"@notabene/javascript-sdk\";\nimport { verifyBTCSignature } from \"./bitcoin\";\nimport { verifyPersonalSignEIP191 } from \"./eth\";\nimport { verifySolanaSignature } from \"./solana\";\nimport { verifyPersonalSignTIP191 } from \"./tron\";\n\nexport async function verifyProof(\n proof: OwnershipProof\n): Promise<OwnershipProof> {\n switch (proof.type) {\n case ProofTypes.SelfDeclaration:\n return {\n ...proof,\n status: (proof as DeclarationProof).confirmed\n ? ProofStatus.VERIFIED\n : ProofStatus.FAILED,\n };\n case ProofTypes.Screenshot:\n return {\n ...proof,\n status: (proof as ScreenshotProof).url\n ? ProofStatus.FLAGGED\n : ProofStatus.FAILED,\n };\n case ProofTypes.EIP191:\n return verifyPersonalSignEIP191(proof as SignatureProof);\n case ProofTypes.ED25519:\n return verifySolanaSignature(proof as SignatureProof);\n case ProofTypes.EIP712:\n case ProofTypes.BIP137:\n case ProofTypes.BIP322:\n return verifyBTCSignature(proof as SignatureProof);\n case ProofTypes.TIP191:\n return verifyPersonalSignTIP191(proof as SignatureProof);\n case ProofTypes.BIP137_XPUB:\n case ProofTypes.MicroTransfer:\n }\n return proof;\n}\n","import nacl from \"tweetnacl\";\nimport { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { base64, base58 } from \"@scure/base\";\n\nexport async function verifySolanaSignature(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"solana\") return { ...proof, status: ProofStatus.FAILED };\n try {\n const publicKey = base58.decode(address);\n const messageBytes = new TextEncoder().encode(proof.attestation);\n const signatureBytes = base64.decode(proof.proof);\n const verified = nacl.sign.detached.verify(\n messageBytes,\n signatureBytes,\n publicKey,\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return { ...proof, status: ProofStatus.FAILED };\n }\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, Signature, Hash, Bytes, PublicKey } from \"ox\";\nimport { base58 } from \"@scure/base\";\n\nexport function verifyTIP191(\n address: string,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const hex: Hex.Hex = `0x41${Hash.keccak256(\n `0x${PublicKey.toHex(publicKey).slice(4)}`,\n ).substring(26)}`;\n const bytes = Bytes.from(hex);\n const checksum = Bytes.from(Hash.sha256(Hash.sha256(hex))).slice(0, 4);\n const checked = Bytes.concat(bytes, checksum);\n const b58 = base58.encode(checked);\n return b58 === address;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignTIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"tron\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyTIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nexport function encode(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n const message = Hex.from(data);\n return Hex.concat(\n // Personal Sign Format: `0x19 ‖ \"Ethereum Signed Message:\\n\" ‖ message.length ‖ message`\n \"0x19\",\n Hex.fromString(\"TRON Signed Message:\\n\" + Hex.size(message)),\n message,\n );\n}\nexport function getSignPayload(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n return Hash.keccak256(encode(data));\n}\n"],"names":["SEGWIT_TYPES","DerivationMode","base58check","createBase58check","Hash","sha256","encodeBech32Address","publicKeyHash","bwords","bech32","toWords","unshift","encode","verifyProof","proof","type","ProofTypes","SelfDeclaration","Promise","resolve","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","_proof$address$split","address","split","verified","message","payload","PersonalMessage","getSignPayload","Hex","fromString","signature","Signature","fromHex","publicKey","Secp256k1","recoverPublicKey","Address","checksum","fromPublicKey","toString","error","verifyEIP191","attestation","e","reject","verifyPersonalSignEIP191","ED25519","base58","decode","messageBytes","TextEncoder","signatureBytes","base64","nacl","sign","detached","verify","verifySolanaSignature","EIP712","BIP137","BIP322","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","checkSegwitAlways","_decodeSignature","sigbytes","length","flagByte","compressed","recovery","secp256k1","fromCompact","slice","segwitType","P2WPKH","P2SH_P2WPKH","undefined","addRecoveryBit","decodeSignature","buffer","hash","prefix","encodeLength","Uint8Array","byteLength","set","hash256","magicHash","toRawBytes","ripemd160","actual","version","encodeBase58AddressFormat","verifyBIP137","Verifier","verifySignature","verifyBIP322","verifyBTCSignature","TIP191","data","keccak256","from","size","hex","PublicKey","toHex","substring","bytes","Bytes","checked","verifyTIP191","verifyPersonalSignTIP191"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{ProofStatus as t,ProofTypes as e}from"@notabene/javascript-sdk";import{encode as n}from"varuint-bitcoin";import{createBase58check as r,bech32 as s,base64 as o,base58 as c}from"@scure/base";import{Hash as a,PersonalMessage as i,Hex as u,Signature as f,Secp256k1 as d,Address as E,PublicKey as h,Bytes as l}from"ox";import{secp256k1 as p}from"@noble/curves/secp256k1";import g from"tweetnacl";function I(){return I=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)({}).hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t},I.apply(null,arguments)}var m,y;!function(t){t.P2WPKH="p2wpkh",t.P2SH_P2WPKH="p2sh(p2wpkh)"}(m||(m={})),function(t){t.LEGACY="Legacy",t.NATIVE="Native SegWit",t.SEGWIT="SegWit",t.P2SH_SEGWIT="p2sh",t.BCH="Bitcoin Cash",t.ETHEREUM="Ethereum",t.DOGECOIN="Dogecoin",t.UNKNOWN="Unknown"}(y||(y={}));const D=r(a.sha256);function w(t){const e=s.toWords(t);return e.unshift(0),s.encode("bc",e)}function A(t,e,n){try{const s=(r=u.fromString(e),a.keccak256(function(t){const e=u.from(t);return u.concat("0x19",u.fromString("TRON Signed Message:\n"+u.size(e)),e)}(r))),o=f.fromHex(n),i=d.recoverPublicKey({payload:s,signature:o}),E=`0x41${a.keccak256(`0x${h.toHex(i).slice(4)}`).substring(26)}`,p=l.from(E),g=l.from(a.sha256(a.sha256(E))).slice(0,4),I=l.concat(p,g);return c.encode(I)===t}catch(t){return!1}var r}async function b(r){switch(r.type){case e.SelfDeclaration:return I({},r,{status:r.confirmed?t.VERIFIED:t.FAILED});case e.Screenshot:return I({},r,{status:r.url?t.FLAGGED:t.FAILED});case e.EIP191:return async function(e){const[n,r,s]=e.address.split(/:/);if("eip155"!==n)return I({},e,{status:t.FAILED});const o=function(t,e,n){try{const r=i.getSignPayload(u.fromString(e)),s=f.fromHex(n),o=d.recoverPublicKey({payload:r,signature:s});return E.checksum(E.fromPublicKey(o)).toString()===E.checksum(t)}catch(t){return!1}}(s,e.attestation,e.proof);return I({},e,{status:o?t.VERIFIED:t.FAILED})}(r);case e.ED25519:return async function(e){const[n,r,s]=e.address.split(/:/);if("solana"!==n)return I({},e,{status:t.FAILED});try{const n=c.decode(s),r=(new TextEncoder).encode(e.attestation),a=o.decode(e.proof);return I({},e,{status:g.sign.detached.verify(r,a,n)?t.VERIFIED:t.FAILED})}catch(n){return I({},e,{status:t.FAILED})}}(r);case e.EIP712:case e.BIP137:return async function(e){const[r,s,c]=e.address.split(/:/);if("bip122"!==r)return I({},e,{status:t.FAILED});try{const r=[y.SEGWIT,y.NATIVE].includes(function(t){if(t.match("^(bc1|tb1|ltc1).*"))return y.NATIVE;if(t.match("^[32M].*"))return y.SEGWIT;if(t.match("^[1nmL].*"))return y.LEGACY;if(t.match("^(D).*"))return y.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(t).concat(" is not a valid or a supported address"))}(c)),s=function(t,e,r,s){const{compressed:c,segwitType:i,signature:u}=function(t){const e=o.decode(t);if(65!==e.length)throw new Error("Invalid signature length");const n=e[0]-27;if(n>15||n<0)throw new Error("Invalid signature parameter");const r=!!(12&n),s=3&n,c=p.Signature.fromCompact(e.slice(1));return{compressed:r,segwitType:8&n?4&n?m.P2WPKH:m.P2SH_P2WPKH:void 0,signature:c.addRecoveryBit(s)}}(r);if(s&&!c)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");const f=function(t){const e=(new TextEncoder).encode("Bitcoin Signed Message:\n"),r=(new TextEncoder).encode(t),s=n(r.length).buffer,o=new Uint8Array(e.length+s.byteLength+r.length);return o.set(e),o.set(new Uint8Array(s),e.length),o.set(r,e.length+s.byteLength),function(t){return a.sha256(a.sha256(t))}(o)}(t),d=(E=u.recoverPublicKey(f).toRawBytes(),a.ripemd160(a.sha256(E)));var E;let h="";if(i)h=w(d);else if(s)try{h=w(d)}catch(t){h=w(d)}else h=function(t,e){const n=new Uint8Array([0,...e]);return D.encode(n)}(0,d);return h===e}(e.attestation,c,e.proof,r);return I({},e,{status:s?t.VERIFIED:t.FAILED})}catch(n){return I({},e,{status:t.FAILED})}}(r);case e.TIP191:return async function(e){const[n,r,s]=e.address.split(/:/);return I({},e,"tron"!==n?{status:t.FAILED}:{status:A(s,e.attestation,e.proof)?t.VERIFIED:t.FAILED})}(r)}return r}export{b as verifyProof};
1
+ import{ProofStatus as t,ProofTypes as e}from"@notabene/javascript-sdk";import{encode as n}from"varuint-bitcoin";import{createBase58check as r,bech32 as s,base64 as o,base58 as c}from"@scure/base";import{Hash as a,PersonalMessage as i,Hex as u,Signature as f,Secp256k1 as E,Address as d,PublicKey as p,Bytes as I}from"ox";import{secp256k1 as h}from"@noble/curves/secp256k1";import{Verifier as l}from"bip322-js";import g from"tweetnacl";function m(){return m=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)({}).hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t},m.apply(null,arguments)}var y,D;!function(t){t.P2WPKH="p2wpkh",t.P2SH_P2WPKH="p2sh(p2wpkh)"}(y||(y={})),function(t){t.LEGACY="Legacy",t.NATIVE="Native SegWit",t.SEGWIT="SegWit",t.P2SH_SEGWIT="p2sh",t.BCH="Bitcoin Cash",t.ETHEREUM="Ethereum",t.DOGECOIN="Dogecoin",t.UNKNOWN="Unknown"}(D||(D={}));const w=r(a.sha256);function A(t){const e=s.toWords(t);return e.unshift(0),s.encode("bc",e)}function P(t,e,n){try{const s=(r=u.fromString(e),a.keccak256(function(t){const e=u.from(t);return u.concat("0x19",u.fromString("TRON Signed Message:\n"+u.size(e)),e)}(r))),o=f.fromHex(n),i=E.recoverPublicKey({payload:s,signature:o}),d=`0x41${a.keccak256(`0x${p.toHex(i).slice(4)}`).substring(26)}`,h=I.from(d),l=I.from(a.sha256(a.sha256(d))).slice(0,4),g=I.concat(h,l);return c.encode(g)===t}catch(t){return!1}var r}async function b(r){switch(r.type){case e.SelfDeclaration:return m({},r,{status:r.confirmed?t.VERIFIED:t.FAILED});case e.Screenshot:return m({},r,{status:r.url?t.FLAGGED:t.FAILED});case e.EIP191:return async function(e){const[n,,r]=e.address.split(/:/);if("eip155"!==n)return m({},e,{status:t.FAILED});const s=function(t,e,n){try{const r=i.getSignPayload(u.fromString(e)),s=f.fromHex(n),o=E.recoverPublicKey({payload:r,signature:s});return d.checksum(d.fromPublicKey(o)).toString()===d.checksum(t)}catch(t){return!1}}(r,e.attestation,e.proof);return m({},e,{status:s?t.VERIFIED:t.FAILED})}(r);case e.ED25519:return async function(e){const[n,,r]=e.address.split(/:/);if("solana"!==n)return m({},e,{status:t.FAILED});try{const n=c.decode(r),s=(new TextEncoder).encode(e.attestation),a=o.decode(e.proof);return m({},e,{status:g.sign.detached.verify(s,a,n)?t.VERIFIED:t.FAILED})}catch(n){return m({},e,{status:t.FAILED})}}(r);case e.EIP712:case e.BIP137:case e.BIP322:return async function(r){const[s,,c]=r.address.split(/:/);if("bip122"!==s)return m({},r,{status:t.FAILED});try{switch(r.type){case e.BIP137:return function(e,r){const s=[D.SEGWIT,D.NATIVE].includes(function(t){if(t.match("^(bc1|tb1|ltc1).*"))return D.NATIVE;if(t.match("^[32M].*"))return D.SEGWIT;if(t.match("^[1nmL].*"))return D.LEGACY;if(t.match("^(D).*"))return D.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(t).concat(" is not a valid or a supported address"))}(e)),c=function(t,e,r,s){const{compressed:c,segwitType:i,signature:u}=function(t){const e=o.decode(t);if(65!==e.length)throw new Error("Invalid signature length");const n=e[0]-27;if(n>15||n<0)throw new Error("Invalid signature parameter");const r=!!(12&n),s=3&n,c=h.Signature.fromCompact(e.slice(1));return{compressed:r,segwitType:8&n?4&n?y.P2WPKH:y.P2SH_P2WPKH:void 0,signature:c.addRecoveryBit(s)}}(r);if(s&&!c)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");const f=function(t){const e=(new TextEncoder).encode("Bitcoin Signed Message:\n"),r=(new TextEncoder).encode(t),s=n(r.length).buffer,o=new Uint8Array(e.length+s.byteLength+r.length);return o.set(e),o.set(new Uint8Array(s),e.length),o.set(r,e.length+s.byteLength),function(t){return a.sha256(a.sha256(t))}(o)}(t),E=(d=u.recoverPublicKey(f).toRawBytes(c),a.ripemd160(a.sha256(d)));var d;let p="";if(i)p=A(E);else if(s)try{p=A(E)}catch(t){p=A(E)}else p=function(t,e){const n=new Uint8Array([0,...e]);return w.encode(n)}(0,E);return p===e}(r.attestation,e,r.proof,s);return m({},r,{status:c?t.VERIFIED:t.FAILED})}(c,r);case e.BIP322:return function(e,n){const{attestation:r,proof:s}=n;return m({},n,{status:l.verifySignature(e,r,s)?t.VERIFIED:t.FAILED})}(c,r);default:return m({},r,{status:t.FAILED})}}catch(e){return m({},r,{status:t.FAILED})}}(r);case e.TIP191:return async function(e){const[n,,r]=e.address.split(/:/);return m({},e,"tron"!==n?{status:t.FAILED}:{status:P(r,e.attestation,e.proof)?t.VERIFIED:t.FAILED})}(r)}return r}export{b as verifyProof};
2
2
  //# sourceMappingURL=index.modern.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.modern.js","sources":["../src/bitcoin.ts","../src/tron.ts","../src/index.ts","../src/eth.ts","../src/solana.ts"],"sourcesContent":["import { ProofStatus, SignatureProof } 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\";\nenum SEGWIT_TYPES {\n P2WPKH = \"p2wpkh\",\n P2SH_P2WPKH = \"p2sh(p2wpkh)\",\n}\n\nconst messagePrefix = \"\\u0018Bitcoin Signed Message:\\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 try {\n // const messageToBeSigned = message.replace(/\\s+/g, \" \").trim();\n const segwit = [DerivationMode.SEGWIT, DerivationMode.NATIVE].includes(\n getDerivationMode(address),\n );\n const verified = verify(proof.attestation, address, proof.proof, segwit);\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n } catch (error) {\n // console.error(\"error verifying proof\", error);\n return {\n ...proof,\n status: ProofStatus.FAILED,\n // error: error.message || error,\n };\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 {\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) {\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);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyHash = hash160(publicKey.toRawBytes());\n let actual: string = \"\";\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n actual = encodeBech32Address(publicKeyHash);\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n // must be true since we only return null, P2SH_P2WPKH, or P2WPKH\n // from the decodeSignature function.\n actual = encodeBech32Address(publicKeyHash);\n }\n } else {\n if (checkSegwitAlways) {\n try {\n actual = encodeBech32Address(publicKeyHash);\n // if address is bech32 it is not p2sh\n } catch (e) {\n actual = encodeBech32Address(publicKeyHash);\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(0, publicKeyHash);\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(version: number, publicKeyHash: Uint8Array) {\n const payload = new Uint8Array([version, ...publicKeyHash]);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: 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(publicKeyHash: Uint8Array): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(\"bc\", 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","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, Signature, Hash, Bytes, PublicKey } from \"ox\";\nimport { base58 } from \"@scure/base\";\n\nexport function verifyTIP191(\n address: string,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const hex: Hex.Hex = `0x41${Hash.keccak256(\n `0x${PublicKey.toHex(publicKey).slice(4)}`,\n ).substring(26)}`;\n const bytes = Bytes.from(hex);\n const checksum = Bytes.from(Hash.sha256(Hash.sha256(hex))).slice(0, 4);\n const checked = Bytes.concat(bytes, checksum);\n const b58 = base58.encode(checked);\n return b58 === address;\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignTIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, _, address] = proof.address.split(/:/);\n if (ns !== \"tron\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyTIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nexport function encode(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n const message = Hex.from(data);\n return Hex.concat(\n // Personal Sign Format: `0x19 ‖ \"Ethereum Signed Message:\\n\" ‖ message.length ‖ message`\n \"0x19\",\n Hex.fromString(\"TRON Signed Message:\\n\" + Hex.size(message)),\n message,\n );\n}\nexport function getSignPayload(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n return Hash.keccak256(encode(data));\n}\n","import {\n type OwnershipProof,\n SignatureProof,\n DeclarationProof,\n ScreenshotProof,\n ProofTypes,\n ProofStatus,\n} from \"@notabene/javascript-sdk\";\nimport { verifyBTCSignature } from \"./bitcoin\";\nimport { verifyPersonalSignEIP191 } from \"./eth\";\nimport { verifySolanaSignature } from \"./solana\";\nimport { verifyPersonalSignTIP191 } from \"./tron\";\n\nexport async function verifyProof(\n proof: OwnershipProof,\n): Promise<OwnershipProof> {\n switch (proof.type) {\n case ProofTypes.SelfDeclaration:\n return {\n ...proof,\n status: (proof as DeclarationProof).confirmed\n ? ProofStatus.VERIFIED\n : ProofStatus.FAILED,\n };\n case ProofTypes.Screenshot:\n return {\n ...proof,\n status: (proof as ScreenshotProof).url\n ? ProofStatus.FLAGGED\n : ProofStatus.FAILED,\n };\n case ProofTypes.EIP191:\n return verifyPersonalSignEIP191(proof as SignatureProof);\n case ProofTypes.ED25519:\n return verifySolanaSignature(proof as SignatureProof);\n case ProofTypes.EIP712:\n case ProofTypes.BIP137:\n return verifyBTCSignature(proof as SignatureProof);\n case ProofTypes.TIP191:\n return verifyPersonalSignTIP191(proof as SignatureProof);\n case ProofTypes.BIP137_XPUB:\n case ProofTypes.MicroTransfer:\n }\n return proof;\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, PersonalMessage, Signature, Address } from \"ox\";\n\nexport function verifyEIP191(\n address: Hex.Hex,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = PersonalMessage.getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const recovered = Address.checksum(Address.fromPublicKey(publicKey));\n return recovered.toString() === Address.checksum(address);\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignEIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, _, address] = proof.address.split(/:/);\n if (ns !== \"eip155\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyEIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n","import nacl from \"tweetnacl\";\nimport { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { base64, base58 } from \"@scure/base\";\n\nexport async function verifySolanaSignature(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, _, address] = proof.address.split(/:/);\n if (ns !== \"solana\") return { ...proof, status: ProofStatus.FAILED };\n try {\n const publicKey = base58.decode(address);\n const messageBytes = new TextEncoder().encode(proof.attestation);\n const signatureBytes = base64.decode(proof.proof);\n const verified = nacl.sign.detached.verify(\n messageBytes,\n signatureBytes,\n publicKey,\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n } catch (error) {\n return { ...proof, status: ProofStatus.FAILED };\n }\n}\n"],"names":["SEGWIT_TYPES","DerivationMode","base58check","createBase58check","Hash","sha256","encodeBech32Address","publicKeyHash","bwords","bech32","toWords","unshift","encode","verifyTIP191","address","message","proof","payload","data","Hex","fromString","keccak256","from","concat","size","signature","Signature","fromHex","publicKey","Secp256k1","recoverPublicKey","hex","PublicKey","toHex","slice","substring","bytes","Bytes","checksum","checked","base58","error","async","verifyProof","type","ProofTypes","SelfDeclaration","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","ns","_","split","verified","PersonalMessage","getSignPayload","Address","fromPublicKey","toString","verifyEIP191","attestation","verifyPersonalSignEIP191","ED25519","decode","messageBytes","TextEncoder","signatureBytes","base64","nacl","sign","detached","verify","verifySolanaSignature","EIP712","BIP137","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","getDerivationMode","checkSegwitAlways","compressed","segwitType","sigbytes","length","flagByte","recovery","secp256k1","fromCompact","P2WPKH","P2SH_P2WPKH","undefined","addRecoveryBit","decodeSignature","hash","prefix","encodeLength","buffer","Uint8Array","byteLength","set","hash256","magicHash","toRawBytes","ripemd160","actual","e","version","encodeBase58AddressFormat","verifyBTCSignature","TIP191","verifyPersonalSignTIP191"],"mappings":"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"}
1
+ {"version":3,"file":"index.modern.js","sources":["../src/bitcoin.ts","../src/tron.ts","../src/index.ts","../src/eth.ts","../src/solana.ts"],"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\nconst messagePrefix = \"\\u0018Bitcoin Signed Message:\\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 try {\n switch (proof.type) {\n case ProofTypes.BIP137:\n return verifyBIP137(address, proof);\n case ProofTypes.BIP322:\n return verifyBIP322(address, proof);\n default:\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n // console.error(\"error verifying proof\", error);\n return {\n ...proof,\n status: ProofStatus.FAILED,\n // error: error.message || error,\n };\n }\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(address: string, proof: SignatureProof) {\n // const messageToBeSigned = message.replace(/\\s+/g, \" \").trim();\n const segwit = [DerivationMode.SEGWIT, DerivationMode.NATIVE].includes(\n getDerivationMode(address)\n );\n const verified = verify(proof.attestation, address, proof.proof, segwit);\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 {\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) {\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);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyBytes = publicKey.toRawBytes(compressed);\n const publicKeyHash = hash160(publicKeyBytes);\n let actual: string = \"\";\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n actual = encodeBech32Address(publicKeyHash);\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n // must be true since we only return null, P2SH_P2WPKH, or P2WPKH\n // from the decodeSignature function.\n actual = encodeBech32Address(publicKeyHash);\n }\n } else {\n if (checkSegwitAlways) {\n try {\n actual = encodeBech32Address(publicKeyHash);\n // if address is bech32 it is not p2sh\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (e) {\n actual = encodeBech32Address(publicKeyHash);\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(0, publicKeyHash);\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(version: number, publicKeyHash: Uint8Array) {\n const payload = new Uint8Array([version, ...publicKeyHash]);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: 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(publicKeyHash: Uint8Array): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(\"bc\", 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","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, Signature, Hash, Bytes, PublicKey } from \"ox\";\nimport { base58 } from \"@scure/base\";\n\nexport function verifyTIP191(\n address: string,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const hex: Hex.Hex = `0x41${Hash.keccak256(\n `0x${PublicKey.toHex(publicKey).slice(4)}`,\n ).substring(26)}`;\n const bytes = Bytes.from(hex);\n const checksum = Bytes.from(Hash.sha256(Hash.sha256(hex))).slice(0, 4);\n const checked = Bytes.concat(bytes, checksum);\n const b58 = base58.encode(checked);\n return b58 === address;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignTIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"tron\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyTIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nexport function encode(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n const message = Hex.from(data);\n return Hex.concat(\n // Personal Sign Format: `0x19 ‖ \"Ethereum Signed Message:\\n\" ‖ message.length ‖ message`\n \"0x19\",\n Hex.fromString(\"TRON Signed Message:\\n\" + Hex.size(message)),\n message,\n );\n}\nexport function getSignPayload(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n return Hash.keccak256(encode(data));\n}\n","import {\n type OwnershipProof,\n SignatureProof,\n DeclarationProof,\n ScreenshotProof,\n ProofTypes,\n ProofStatus,\n} from \"@notabene/javascript-sdk\";\nimport { verifyBTCSignature } from \"./bitcoin\";\nimport { verifyPersonalSignEIP191 } from \"./eth\";\nimport { verifySolanaSignature } from \"./solana\";\nimport { verifyPersonalSignTIP191 } from \"./tron\";\n\nexport async function verifyProof(\n proof: OwnershipProof\n): Promise<OwnershipProof> {\n switch (proof.type) {\n case ProofTypes.SelfDeclaration:\n return {\n ...proof,\n status: (proof as DeclarationProof).confirmed\n ? ProofStatus.VERIFIED\n : ProofStatus.FAILED,\n };\n case ProofTypes.Screenshot:\n return {\n ...proof,\n status: (proof as ScreenshotProof).url\n ? ProofStatus.FLAGGED\n : ProofStatus.FAILED,\n };\n case ProofTypes.EIP191:\n return verifyPersonalSignEIP191(proof as SignatureProof);\n case ProofTypes.ED25519:\n return verifySolanaSignature(proof as SignatureProof);\n case ProofTypes.EIP712:\n case ProofTypes.BIP137:\n case ProofTypes.BIP322:\n return verifyBTCSignature(proof as SignatureProof);\n case ProofTypes.TIP191:\n return verifyPersonalSignTIP191(proof as SignatureProof);\n case ProofTypes.BIP137_XPUB:\n case ProofTypes.MicroTransfer:\n }\n return proof;\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, PersonalMessage, Signature, Address } from \"ox\";\n\nexport function verifyEIP191(\n address: Hex.Hex,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = PersonalMessage.getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const recovered = Address.checksum(Address.fromPublicKey(publicKey));\n return recovered.toString() === Address.checksum(address);\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignEIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"eip155\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyEIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n","import nacl from \"tweetnacl\";\nimport { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { base64, base58 } from \"@scure/base\";\n\nexport async function verifySolanaSignature(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"solana\") return { ...proof, status: ProofStatus.FAILED };\n try {\n const publicKey = base58.decode(address);\n const messageBytes = new TextEncoder().encode(proof.attestation);\n const signatureBytes = base64.decode(proof.proof);\n const verified = nacl.sign.detached.verify(\n messageBytes,\n signatureBytes,\n publicKey,\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return { ...proof, status: ProofStatus.FAILED };\n }\n}\n"],"names":["SEGWIT_TYPES","DerivationMode","base58check","createBase58check","Hash","sha256","encodeBech32Address","publicKeyHash","bwords","bech32","toWords","unshift","encode","verifyTIP191","address","message","proof","payload","data","Hex","fromString","keccak256","from","concat","size","signature","Signature","fromHex","publicKey","Secp256k1","recoverPublicKey","hex","PublicKey","toHex","slice","substring","bytes","Bytes","checksum","checked","base58","error","verifyProof","type","ProofTypes","SelfDeclaration","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","async","ns","split","verified","PersonalMessage","getSignPayload","Address","fromPublicKey","toString","verifyEIP191","attestation","verifyPersonalSignEIP191","ED25519","decode","messageBytes","TextEncoder","signatureBytes","base64","nacl","sign","detached","verify","verifySolanaSignature","EIP712","BIP137","BIP322","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","getDerivationMode","checkSegwitAlways","compressed","segwitType","sigbytes","length","flagByte","recovery","secp256k1","fromCompact","P2WPKH","P2SH_P2WPKH","undefined","addRecoveryBit","decodeSignature","hash","prefix","encodeLength","buffer","Uint8Array","byteLength","set","hash256","magicHash","toRawBytes","ripemd160","actual","e","version","encodeBase58AddressFormat","verifyBIP137","signatureProof","Verifier","verifySignature","verifyBIP322","verifyBTCSignature","TIP191","verifyPersonalSignTIP191"],"mappings":"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"}
package/dist/index.umd.js CHANGED
@@ -1,2 +1,2 @@
1
- !function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@notabene/javascript-sdk"),require("varuint-bitcoin"),require("@scure/base"),require("ox"),require("@noble/curves/secp256k1"),require("tweetnacl")):"function"==typeof define&&define.amd?define(["exports","@notabene/javascript-sdk","varuint-bitcoin","@scure/base","ox","@noble/curves/secp256k1","tweetnacl"],r):r((e||self).verifyProof={},e.javascriptSdk,e.varuintBitcoin,e.base,e.ox,e.secp256k1,e.tweetnacl)}(this,function(e,r,t,o,s,n,a){function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var c,u,f=/*#__PURE__*/i(a);function l(){return l=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var o in t)({}).hasOwnProperty.call(t,o)&&(e[o]=t[o])}return e},l.apply(null,arguments)}!function(e){e.P2WPKH="p2wpkh",e.P2SH_P2WPKH="p2sh(p2wpkh)"}(c||(c={})),function(e){e.LEGACY="Legacy",e.NATIVE="Native SegWit",e.SEGWIT="SegWit",e.P2SH_SEGWIT="p2sh",e.BCH="Bitcoin Cash",e.ETHEREUM="Ethereum",e.DOGECOIN="Dogecoin",e.UNKNOWN="Unknown"}(u||(u={}));var P=o.createBase58check(s.Hash.sha256);function d(e){var r=o.bech32.toWords(e);return r.unshift(0),o.bech32.encode("bc",r)}e.verifyProof=function(e){try{switch(e.type){case r.ProofTypes.SelfDeclaration:return Promise.resolve(l({},e,{status:e.confirmed?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}));case r.ProofTypes.Screenshot:return Promise.resolve(l({},e,{status:e.url?r.ProofStatus.FLAGGED:r.ProofStatus.FAILED}));case r.ProofTypes.EIP191:return Promise.resolve(function(e){try{var t=e.address.split(/:/),o=t[2];if("eip155"!==t[0])return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}));var n=function(e,r,t){try{var o=s.PersonalMessage.getSignPayload(s.Hex.fromString(r)),n=s.Signature.fromHex(t),a=s.Secp256k1.recoverPublicKey({payload:o,signature:n});return s.Address.checksum(s.Address.fromPublicKey(a)).toString()===s.Address.checksum(e)}catch(e){return!1}}(o,e.attestation,e.proof);return Promise.resolve(l({},e,{status:n?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}))}catch(e){return Promise.reject(e)}}(e));case r.ProofTypes.ED25519:return Promise.resolve(function(e){try{var t=e.address.split(/:/),s=t[2];if("solana"!==t[0])return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}));try{var n=o.base58.decode(s),a=(new TextEncoder).encode(e.attestation),i=o.base64.decode(e.proof),c=f.default.sign.detached.verify(a,i,n);return Promise.resolve(l({},e,{status:c?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}))}catch(t){return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(e));case r.ProofTypes.EIP712:case r.ProofTypes.BIP137:return Promise.resolve(function(e){try{var a=e.address.split(/:/),i=a[2];if("bip122"!==a[0])return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}));try{var f=[u.SEGWIT,u.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return u.NATIVE;if(e.match("^[32M].*"))return u.SEGWIT;if(e.match("^[1nmL].*"))return u.LEGACY;if(e.match("^(D).*"))return u.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(i)),h=function(e,r,a,i){var u=function(e){var r=o.base64.decode(e);if(65!==r.length)throw new Error("Invalid signature length");var t=r[0]-27;if(t>15||t<0)throw new Error("Invalid signature parameter");var s=!!(12&t),a=3&t,i=n.secp256k1.Signature.fromCompact(r.slice(1));return{compressed:s,segwitType:8&t?4&t?c.P2WPKH:c.P2SH_P2WPKH:void 0,signature:i.addRecoveryBit(a)}}(a),f=u.segwitType,l=u.signature;if(i&&!u.compressed)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var h,v=function(e){var r=(new TextEncoder).encode("Bitcoin Signed Message:\n"),o=(new TextEncoder).encode(e),n=t.encode(o.length).buffer,a=new Uint8Array(r.length+n.byteLength+o.length);return a.set(r),a.set(new Uint8Array(n),r.length),a.set(o,r.length+n.byteLength),function(e){return s.Hash.sha256(s.Hash.sha256(e))}(a)}(e),p=(h=l.recoverPublicKey(v).toRawBytes(),s.Hash.ripemd160(s.Hash.sha256(h))),y="";if(f)y=d(p);else if(i)try{y=d(p)}catch(e){y=d(p)}else y=function(e,r){var t=new Uint8Array([0].concat(r));return P.encode(t)}(0,p);return y===r}(e.attestation,i,e.proof,f);return Promise.resolve(l({},e,{status:h?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}))}catch(t){return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(e));case r.ProofTypes.TIP191:return Promise.resolve(function(e){try{var t=e.address.split(/:/),n=t[2];if("tron"!==t[0])return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}));var a=function(e,r,t){try{var n=(P=s.Hex.fromString(r),s.Hash.keccak256(function(e){var r=s.Hex.from(e);return s.Hex.concat("0x19",s.Hex.fromString("TRON Signed Message:\n"+s.Hex.size(r)),r)}(P))),a=s.Signature.fromHex(t),i=s.Secp256k1.recoverPublicKey({payload:n,signature:a}),c="0x41"+s.Hash.keccak256("0x"+s.PublicKey.toHex(i).slice(4)).substring(26),u=s.Bytes.from(c),f=s.Bytes.from(s.Hash.sha256(s.Hash.sha256(c))).slice(0,4),l=s.Bytes.concat(u,f);return o.base58.encode(l)===e}catch(e){return!1}var P}(n,e.attestation,e.proof);return Promise.resolve(l({},e,{status:a?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}))}catch(e){return Promise.reject(e)}}(e))}return Promise.resolve(e)}catch(e){return Promise.reject(e)}}});
1
+ !function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@notabene/javascript-sdk"),require("varuint-bitcoin"),require("@scure/base"),require("ox"),require("@noble/curves/secp256k1"),require("bip322-js"),require("tweetnacl")):"function"==typeof define&&define.amd?define(["exports","@notabene/javascript-sdk","varuint-bitcoin","@scure/base","ox","@noble/curves/secp256k1","bip322-js","tweetnacl"],r):r((e||self).verifyProof={},e.javascriptSdk,e.varuintBitcoin,e.base,e.ox,e.secp256k1,e.bip322Js,e.tweetnacl)}(this,function(e,r,t,o,s,n,a,i){function c(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var u,f,P=/*#__PURE__*/c(i);function l(){return l=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var o in t)({}).hasOwnProperty.call(t,o)&&(e[o]=t[o])}return e},l.apply(null,arguments)}!function(e){e.P2WPKH="p2wpkh",e.P2SH_P2WPKH="p2sh(p2wpkh)"}(u||(u={})),function(e){e.LEGACY="Legacy",e.NATIVE="Native SegWit",e.SEGWIT="SegWit",e.P2SH_SEGWIT="p2sh",e.BCH="Bitcoin Cash",e.ETHEREUM="Ethereum",e.DOGECOIN="Dogecoin",e.UNKNOWN="Unknown"}(f||(f={}));var d=o.createBase58check(s.Hash.sha256);function h(e){var r=o.bech32.toWords(e);return r.unshift(0),o.bech32.encode("bc",r)}e.verifyProof=function(e){try{switch(e.type){case r.ProofTypes.SelfDeclaration:return Promise.resolve(l({},e,{status:e.confirmed?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}));case r.ProofTypes.Screenshot:return Promise.resolve(l({},e,{status:e.url?r.ProofStatus.FLAGGED:r.ProofStatus.FAILED}));case r.ProofTypes.EIP191:return Promise.resolve(function(e){try{var t=e.address.split(/:/),o=t[2];if("eip155"!==t[0])return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}));var n=function(e,r,t){try{var o=s.PersonalMessage.getSignPayload(s.Hex.fromString(r)),n=s.Signature.fromHex(t),a=s.Secp256k1.recoverPublicKey({payload:o,signature:n});return s.Address.checksum(s.Address.fromPublicKey(a)).toString()===s.Address.checksum(e)}catch(e){return!1}}(o,e.attestation,e.proof);return Promise.resolve(l({},e,{status:n?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}))}catch(e){return Promise.reject(e)}}(e));case r.ProofTypes.ED25519:return Promise.resolve(function(e){try{var t=e.address.split(/:/),s=t[2];if("solana"!==t[0])return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}));try{var n=o.base58.decode(s),a=(new TextEncoder).encode(e.attestation),i=o.base64.decode(e.proof),c=P.default.sign.detached.verify(a,i,n);return Promise.resolve(l({},e,{status:c?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}))}catch(t){return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(e));case r.ProofTypes.EIP712:case r.ProofTypes.BIP137:case r.ProofTypes.BIP322:return Promise.resolve(function(e){try{var i=e.address.split(/:/),c=i[2];if("bip122"!==i[0])return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}));try{switch(e.type){case r.ProofTypes.BIP137:return Promise.resolve(function(e,a){var i=[f.SEGWIT,f.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return f.NATIVE;if(e.match("^[32M].*"))return f.SEGWIT;if(e.match("^[1nmL].*"))return f.LEGACY;if(e.match("^(D).*"))return f.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(e)),c=function(e,r,a,i){var c=function(e){var r=o.base64.decode(e);if(65!==r.length)throw new Error("Invalid signature length");var t=r[0]-27;if(t>15||t<0)throw new Error("Invalid signature parameter");var s=!!(12&t),a=3&t,i=n.secp256k1.Signature.fromCompact(r.slice(1));return{compressed:s,segwitType:8&t?4&t?u.P2WPKH:u.P2SH_P2WPKH:void 0,signature:i.addRecoveryBit(a)}}(a),f=c.compressed,P=c.segwitType,l=c.signature;if(i&&!f)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var p,v=function(e){var r=(new TextEncoder).encode("Bitcoin Signed Message:\n"),o=(new TextEncoder).encode(e),n=t.encode(o.length).buffer,a=new Uint8Array(r.length+n.byteLength+o.length);return a.set(r),a.set(new Uint8Array(n),r.length),a.set(o,r.length+n.byteLength),function(e){return s.Hash.sha256(s.Hash.sha256(e))}(a)}(e),y=(p=l.recoverPublicKey(v).toRawBytes(f),s.Hash.ripemd160(s.Hash.sha256(p))),E="";if(P)E=h(y);else if(i)try{E=h(y)}catch(e){E=h(y)}else E=function(e,r){var t=new Uint8Array([0].concat(r));return d.encode(t)}(0,y);return E===r}(a.attestation,e,a.proof,i);return l({},a,{status:c?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED})}(c,e));case r.ProofTypes.BIP322:return Promise.resolve(function(e,t){return l({},t,{status:a.Verifier.verifySignature(e,t.attestation,t.proof)?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED})}(c,e));default:return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}))}}catch(t){return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(e));case r.ProofTypes.TIP191:return Promise.resolve(function(e){try{var t=e.address.split(/:/),n=t[2];if("tron"!==t[0])return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}));var a=function(e,r,t){try{var n=(l=s.Hex.fromString(r),s.Hash.keccak256(function(e){var r=s.Hex.from(e);return s.Hex.concat("0x19",s.Hex.fromString("TRON Signed Message:\n"+s.Hex.size(r)),r)}(l))),a=s.Signature.fromHex(t),i=s.Secp256k1.recoverPublicKey({payload:n,signature:a}),c="0x41"+s.Hash.keccak256("0x"+s.PublicKey.toHex(i).slice(4)).substring(26),u=s.Bytes.from(c),f=s.Bytes.from(s.Hash.sha256(s.Hash.sha256(c))).slice(0,4),P=s.Bytes.concat(u,f);return o.base58.encode(P)===e}catch(e){return!1}var l}(n,e.attestation,e.proof);return Promise.resolve(l({},e,{status:a?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}))}catch(e){return Promise.reject(e)}}(e))}return Promise.resolve(e)}catch(e){return Promise.reject(e)}}});
2
2
  //# sourceMappingURL=index.umd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.js","sources":["../src/bitcoin.ts","../src/index.ts","../src/eth.ts","../src/solana.ts","../src/tron.ts"],"sourcesContent":["import { ProofStatus, SignatureProof } 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\";\nenum SEGWIT_TYPES {\n P2WPKH = \"p2wpkh\",\n P2SH_P2WPKH = \"p2sh(p2wpkh)\",\n}\n\nconst messagePrefix = \"\\u0018Bitcoin Signed Message:\\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 try {\n // const messageToBeSigned = message.replace(/\\s+/g, \" \").trim();\n const segwit = [DerivationMode.SEGWIT, DerivationMode.NATIVE].includes(\n getDerivationMode(address),\n );\n const verified = verify(proof.attestation, address, proof.proof, segwit);\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n } catch (error) {\n // console.error(\"error verifying proof\", error);\n return {\n ...proof,\n status: ProofStatus.FAILED,\n // error: error.message || error,\n };\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 {\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) {\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);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyHash = hash160(publicKey.toRawBytes());\n let actual: string = \"\";\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n actual = encodeBech32Address(publicKeyHash);\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n // must be true since we only return null, P2SH_P2WPKH, or P2WPKH\n // from the decodeSignature function.\n actual = encodeBech32Address(publicKeyHash);\n }\n } else {\n if (checkSegwitAlways) {\n try {\n actual = encodeBech32Address(publicKeyHash);\n // if address is bech32 it is not p2sh\n } catch (e) {\n actual = encodeBech32Address(publicKeyHash);\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(0, publicKeyHash);\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(version: number, publicKeyHash: Uint8Array) {\n const payload = new Uint8Array([version, ...publicKeyHash]);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: 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(publicKeyHash: Uint8Array): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(\"bc\", 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","import {\n type OwnershipProof,\n SignatureProof,\n DeclarationProof,\n ScreenshotProof,\n ProofTypes,\n ProofStatus,\n} from \"@notabene/javascript-sdk\";\nimport { verifyBTCSignature } from \"./bitcoin\";\nimport { verifyPersonalSignEIP191 } from \"./eth\";\nimport { verifySolanaSignature } from \"./solana\";\nimport { verifyPersonalSignTIP191 } from \"./tron\";\n\nexport async function verifyProof(\n proof: OwnershipProof,\n): Promise<OwnershipProof> {\n switch (proof.type) {\n case ProofTypes.SelfDeclaration:\n return {\n ...proof,\n status: (proof as DeclarationProof).confirmed\n ? ProofStatus.VERIFIED\n : ProofStatus.FAILED,\n };\n case ProofTypes.Screenshot:\n return {\n ...proof,\n status: (proof as ScreenshotProof).url\n ? ProofStatus.FLAGGED\n : ProofStatus.FAILED,\n };\n case ProofTypes.EIP191:\n return verifyPersonalSignEIP191(proof as SignatureProof);\n case ProofTypes.ED25519:\n return verifySolanaSignature(proof as SignatureProof);\n case ProofTypes.EIP712:\n case ProofTypes.BIP137:\n return verifyBTCSignature(proof as SignatureProof);\n case ProofTypes.TIP191:\n return verifyPersonalSignTIP191(proof as SignatureProof);\n case ProofTypes.BIP137_XPUB:\n case ProofTypes.MicroTransfer:\n }\n return proof;\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, PersonalMessage, Signature, Address } from \"ox\";\n\nexport function verifyEIP191(\n address: Hex.Hex,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = PersonalMessage.getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const recovered = Address.checksum(Address.fromPublicKey(publicKey));\n return recovered.toString() === Address.checksum(address);\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignEIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, _, address] = proof.address.split(/:/);\n if (ns !== \"eip155\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyEIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n","import nacl from \"tweetnacl\";\nimport { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { base64, base58 } from \"@scure/base\";\n\nexport async function verifySolanaSignature(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, _, address] = proof.address.split(/:/);\n if (ns !== \"solana\") return { ...proof, status: ProofStatus.FAILED };\n try {\n const publicKey = base58.decode(address);\n const messageBytes = new TextEncoder().encode(proof.attestation);\n const signatureBytes = base64.decode(proof.proof);\n const verified = nacl.sign.detached.verify(\n messageBytes,\n signatureBytes,\n publicKey,\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n } catch (error) {\n return { ...proof, status: ProofStatus.FAILED };\n }\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, Signature, Hash, Bytes, PublicKey } from \"ox\";\nimport { base58 } from \"@scure/base\";\n\nexport function verifyTIP191(\n address: string,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const hex: Hex.Hex = `0x41${Hash.keccak256(\n `0x${PublicKey.toHex(publicKey).slice(4)}`,\n ).substring(26)}`;\n const bytes = Bytes.from(hex);\n const checksum = Bytes.from(Hash.sha256(Hash.sha256(hex))).slice(0, 4);\n const checked = Bytes.concat(bytes, checksum);\n const b58 = base58.encode(checked);\n return b58 === address;\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignTIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, _, address] = proof.address.split(/:/);\n if (ns !== \"tron\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyTIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nexport function encode(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n const message = Hex.from(data);\n return Hex.concat(\n // Personal Sign Format: `0x19 ‖ \"Ethereum Signed Message:\\n\" ‖ message.length ‖ message`\n \"0x19\",\n Hex.fromString(\"TRON Signed Message:\\n\" + Hex.size(message)),\n message,\n );\n}\nexport function getSignPayload(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n return Hash.keccak256(encode(data));\n}\n"],"names":["SEGWIT_TYPES","DerivationMode","base58check","createBase58check","Hash","sha256","encodeBech32Address","publicKeyHash","bwords","bech32","toWords","unshift","encode","proof","type","ProofTypes","SelfDeclaration","Promise","resolve","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","_proof$address$split","address","split","_","verified","message","payload","PersonalMessage","getSignPayload","Hex","fromString","signature","Signature","fromHex","publicKey","Secp256k1","recoverPublicKey","Address","checksum","fromPublicKey","toString","error","verifyEIP191","attestation","e","reject","verifyPersonalSignEIP191","ED25519","base58","decode","messageBytes","TextEncoder","signatureBytes","base64","nacl","sign","detached","verify","verifySolanaSignature","EIP712","BIP137","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","checkSegwitAlways","_decodeSignature","sigbytes","length","flagByte","compressed","recovery","secp256k1","fromCompact","slice","segwitType","P2WPKH","P2SH_P2WPKH","undefined","addRecoveryBit","decodeSignature","buffer","hash","prefix","encodeLength","Uint8Array","byteLength","set","hash256","magicHash","toRawBytes","ripemd160","actual","version","encodeBase58AddressFormat","verifyBTCSignature","TIP191","data","keccak256","from","size","hex","PublicKey","toHex","substring","bytes","Bytes","checked","verifyTIP191","verifyPersonalSignTIP191"],"mappings":"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"}
1
+ {"version":3,"file":"index.umd.js","sources":["../src/bitcoin.ts","../src/index.ts","../src/eth.ts","../src/solana.ts","../src/tron.ts"],"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\nconst messagePrefix = \"\\u0018Bitcoin Signed Message:\\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 try {\n switch (proof.type) {\n case ProofTypes.BIP137:\n return verifyBIP137(address, proof);\n case ProofTypes.BIP322:\n return verifyBIP322(address, proof);\n default:\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n // console.error(\"error verifying proof\", error);\n return {\n ...proof,\n status: ProofStatus.FAILED,\n // error: error.message || error,\n };\n }\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(address: string, proof: SignatureProof) {\n // const messageToBeSigned = message.replace(/\\s+/g, \" \").trim();\n const segwit = [DerivationMode.SEGWIT, DerivationMode.NATIVE].includes(\n getDerivationMode(address)\n );\n const verified = verify(proof.attestation, address, proof.proof, segwit);\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 {\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) {\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);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyBytes = publicKey.toRawBytes(compressed);\n const publicKeyHash = hash160(publicKeyBytes);\n let actual: string = \"\";\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n actual = encodeBech32Address(publicKeyHash);\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n // must be true since we only return null, P2SH_P2WPKH, or P2WPKH\n // from the decodeSignature function.\n actual = encodeBech32Address(publicKeyHash);\n }\n } else {\n if (checkSegwitAlways) {\n try {\n actual = encodeBech32Address(publicKeyHash);\n // if address is bech32 it is not p2sh\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (e) {\n actual = encodeBech32Address(publicKeyHash);\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(0, publicKeyHash);\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(version: number, publicKeyHash: Uint8Array) {\n const payload = new Uint8Array([version, ...publicKeyHash]);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: 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(publicKeyHash: Uint8Array): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(\"bc\", 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","import {\n type OwnershipProof,\n SignatureProof,\n DeclarationProof,\n ScreenshotProof,\n ProofTypes,\n ProofStatus,\n} from \"@notabene/javascript-sdk\";\nimport { verifyBTCSignature } from \"./bitcoin\";\nimport { verifyPersonalSignEIP191 } from \"./eth\";\nimport { verifySolanaSignature } from \"./solana\";\nimport { verifyPersonalSignTIP191 } from \"./tron\";\n\nexport async function verifyProof(\n proof: OwnershipProof\n): Promise<OwnershipProof> {\n switch (proof.type) {\n case ProofTypes.SelfDeclaration:\n return {\n ...proof,\n status: (proof as DeclarationProof).confirmed\n ? ProofStatus.VERIFIED\n : ProofStatus.FAILED,\n };\n case ProofTypes.Screenshot:\n return {\n ...proof,\n status: (proof as ScreenshotProof).url\n ? ProofStatus.FLAGGED\n : ProofStatus.FAILED,\n };\n case ProofTypes.EIP191:\n return verifyPersonalSignEIP191(proof as SignatureProof);\n case ProofTypes.ED25519:\n return verifySolanaSignature(proof as SignatureProof);\n case ProofTypes.EIP712:\n case ProofTypes.BIP137:\n case ProofTypes.BIP322:\n return verifyBTCSignature(proof as SignatureProof);\n case ProofTypes.TIP191:\n return verifyPersonalSignTIP191(proof as SignatureProof);\n case ProofTypes.BIP137_XPUB:\n case ProofTypes.MicroTransfer:\n }\n return proof;\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, PersonalMessage, Signature, Address } from \"ox\";\n\nexport function verifyEIP191(\n address: Hex.Hex,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = PersonalMessage.getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const recovered = Address.checksum(Address.fromPublicKey(publicKey));\n return recovered.toString() === Address.checksum(address);\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignEIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"eip155\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyEIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n","import nacl from \"tweetnacl\";\nimport { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { base64, base58 } from \"@scure/base\";\n\nexport async function verifySolanaSignature(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"solana\") return { ...proof, status: ProofStatus.FAILED };\n try {\n const publicKey = base58.decode(address);\n const messageBytes = new TextEncoder().encode(proof.attestation);\n const signatureBytes = base64.decode(proof.proof);\n const verified = nacl.sign.detached.verify(\n messageBytes,\n signatureBytes,\n publicKey,\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return { ...proof, status: ProofStatus.FAILED };\n }\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, Signature, Hash, Bytes, PublicKey } from \"ox\";\nimport { base58 } from \"@scure/base\";\n\nexport function verifyTIP191(\n address: string,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const hex: Hex.Hex = `0x41${Hash.keccak256(\n `0x${PublicKey.toHex(publicKey).slice(4)}`,\n ).substring(26)}`;\n const bytes = Bytes.from(hex);\n const checksum = Bytes.from(Hash.sha256(Hash.sha256(hex))).slice(0, 4);\n const checked = Bytes.concat(bytes, checksum);\n const b58 = base58.encode(checked);\n return b58 === address;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignTIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"tron\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyTIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nexport function encode(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n const message = Hex.from(data);\n return Hex.concat(\n // Personal Sign Format: `0x19 ‖ \"Ethereum Signed Message:\\n\" ‖ message.length ‖ message`\n \"0x19\",\n Hex.fromString(\"TRON Signed Message:\\n\" + Hex.size(message)),\n message,\n );\n}\nexport function getSignPayload(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n return Hash.keccak256(encode(data));\n}\n"],"names":["SEGWIT_TYPES","DerivationMode","base58check","createBase58check","Hash","sha256","encodeBech32Address","publicKeyHash","bwords","bech32","toWords","unshift","encode","proof","type","ProofTypes","SelfDeclaration","Promise","resolve","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","_proof$address$split","address","split","verified","message","payload","PersonalMessage","getSignPayload","Hex","fromString","signature","Signature","fromHex","publicKey","Secp256k1","recoverPublicKey","Address","checksum","fromPublicKey","toString","error","verifyEIP191","attestation","e","reject","verifyPersonalSignEIP191","ED25519","base58","decode","messageBytes","TextEncoder","signatureBytes","base64","nacl","sign","detached","verify","verifySolanaSignature","EIP712","BIP137","BIP322","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","checkSegwitAlways","_decodeSignature","sigbytes","length","flagByte","compressed","recovery","secp256k1","fromCompact","slice","segwitType","P2WPKH","P2SH_P2WPKH","undefined","addRecoveryBit","decodeSignature","buffer","hash","prefix","encodeLength","Uint8Array","byteLength","set","hash256","magicHash","toRawBytes","ripemd160","actual","version","encodeBase58AddressFormat","verifyBIP137","Verifier","verifySignature","verifyBIP322","verifyBTCSignature","TIP191","data","keccak256","from","size","hex","PublicKey","toHex","substring","bytes","Bytes","checked","verifyTIP191","verifyPersonalSignTIP191"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notabene/verify-proof",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Verify ownership proofs",
5
5
  "source": "src/index.ts",
6
6
  "type": "module",
@@ -19,14 +19,17 @@
19
19
  "build:dev": "yarn build && yarn dev",
20
20
  "build:clean": "rm -rf dist",
21
21
  "build": "microbundle",
22
- "lint": "eslint .",
22
+ "lint": "eslint ./src",
23
23
  "test": "vitest"
24
24
  },
25
25
  "devDependencies": {
26
- "eslint": "^9.9.0",
26
+ "@eslint/js": "^9.20.0",
27
+ "eslint": "^9.20.1",
28
+ "globals": "^15.15.0",
27
29
  "microbundle": "^0.15.1",
28
30
  "tronweb": "^6.0.0",
29
31
  "typescript": "^5.5.4",
32
+ "typescript-eslint": "^8.24.1",
30
33
  "vite": "^5.4.11",
31
34
  "vitest": "^2.0.5"
32
35
  },
@@ -34,6 +37,7 @@
34
37
  "@noble/curves": "^1.7.0",
35
38
  "@notabene/javascript-sdk": "^2.3.0",
36
39
  "@scure/base": "^1.2.1",
40
+ "bip322-js": "^2.0.0",
37
41
  "ox": "^0.2.2",
38
42
  "tweetnacl": "^1.0.3",
39
43
  "varuint-bitcoin": "^2.0.0"
package/src/bitcoin.ts CHANGED
@@ -1,10 +1,16 @@
1
- import { ProofStatus, SignatureProof } from "@notabene/javascript-sdk";
1
+ import {
2
+ ProofStatus,
3
+ ProofTypes,
4
+ SignatureProof,
5
+ } from "@notabene/javascript-sdk";
2
6
 
3
7
  import { encode as encodeLength } from "varuint-bitcoin";
4
8
  import { base64, bech32, createBase58check } from "@scure/base";
5
9
  import { Hash } from "ox";
6
10
  import { secp256k1 } from "@noble/curves/secp256k1";
7
11
  import { SignatureType } from "@noble/curves/abstract/weierstrass";
12
+ import { Verifier } from "bip322-js";
13
+
8
14
  enum SEGWIT_TYPES {
9
15
  P2WPKH = "p2wpkh",
10
16
  P2SH_P2WPKH = "p2sh(p2wpkh)",
@@ -24,21 +30,23 @@ enum DerivationMode {
24
30
  }
25
31
 
26
32
  export async function verifyBTCSignature(
27
- proof: SignatureProof,
33
+ proof: SignatureProof
28
34
  ): Promise<SignatureProof> {
29
- const [ns, _, address] = proof.address.split(/:/);
35
+ const [ns, , address] = proof.address.split(/:/);
30
36
  if (ns !== "bip122") return { ...proof, status: ProofStatus.FAILED };
31
37
  try {
32
- // const messageToBeSigned = message.replace(/\s+/g, " ").trim();
33
- const segwit = [DerivationMode.SEGWIT, DerivationMode.NATIVE].includes(
34
- getDerivationMode(address),
35
- );
36
- const verified = verify(proof.attestation, address, proof.proof, segwit);
37
-
38
- return {
39
- ...proof,
40
- status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,
41
- };
38
+ switch (proof.type) {
39
+ case ProofTypes.BIP137:
40
+ return verifyBIP137(address, proof);
41
+ case ProofTypes.BIP322:
42
+ return verifyBIP322(address, proof);
43
+ default:
44
+ return {
45
+ ...proof,
46
+ status: ProofStatus.FAILED,
47
+ };
48
+ }
49
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
42
50
  } catch (error) {
43
51
  // console.error("error verifying proof", error);
44
52
  return {
@@ -49,6 +57,32 @@ export async function verifyBTCSignature(
49
57
  }
50
58
  }
51
59
 
60
+ function verifyBIP322(address: string, proof: SignatureProof) {
61
+ const { attestation, proof: signatureProof } = proof;
62
+ const verified = Verifier.verifySignature(
63
+ address,
64
+ attestation,
65
+ signatureProof
66
+ );
67
+ return {
68
+ ...proof,
69
+ status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,
70
+ };
71
+ }
72
+
73
+ function verifyBIP137(address: string, proof: SignatureProof) {
74
+ // const messageToBeSigned = message.replace(/\s+/g, " ").trim();
75
+ const segwit = [DerivationMode.SEGWIT, DerivationMode.NATIVE].includes(
76
+ getDerivationMode(address)
77
+ );
78
+ const verified = verify(proof.attestation, address, proof.proof, segwit);
79
+
80
+ return {
81
+ ...proof,
82
+ status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,
83
+ };
84
+ }
85
+
52
86
  function getDerivationMode(address: string) {
53
87
  if (address.match("^(bc1|tb1|ltc1).*")) {
54
88
  return DerivationMode.NATIVE;
@@ -62,7 +96,7 @@ function getDerivationMode(address: string) {
62
96
  throw new Error(
63
97
  "INVALID ADDRESS: "
64
98
  .concat(address)
65
- .concat(" is not a valid or a supported address"),
99
+ .concat(" is not a valid or a supported address")
66
100
  );
67
101
  }
68
102
  }
@@ -89,8 +123,8 @@ function decodeSignature(proof: string): DecodedSignature {
89
123
  segwitType: !(flagByte & 8)
90
124
  ? undefined
91
125
  : !(flagByte & 4)
92
- ? SEGWIT_TYPES.P2SH_P2WPKH
93
- : SEGWIT_TYPES.P2WPKH,
126
+ ? SEGWIT_TYPES.P2SH_P2WPKH
127
+ : SEGWIT_TYPES.P2WPKH,
94
128
  signature: signature.addRecoveryBit(recovery),
95
129
  };
96
130
  }
@@ -99,17 +133,18 @@ function verify(
99
133
  attestation: string,
100
134
  address: string,
101
135
  proof: string,
102
- checkSegwitAlways: boolean,
136
+ checkSegwitAlways: boolean
103
137
  ) {
104
138
  const { compressed, segwitType, signature } = decodeSignature(proof);
105
139
  if (checkSegwitAlways && !compressed) {
106
140
  throw new Error(
107
- "checkSegwitAlways can only be used with a compressed pubkey signature flagbyte",
141
+ "checkSegwitAlways can only be used with a compressed pubkey signature flagbyte"
108
142
  );
109
143
  }
110
144
  const hash = magicHash(attestation);
111
145
  const publicKey = signature.recoverPublicKey(hash);
112
- const publicKeyHash = hash160(publicKey.toRawBytes());
146
+ const publicKeyBytes = publicKey.toRawBytes(compressed);
147
+ const publicKeyHash = hash160(publicKeyBytes);
113
148
  let actual: string = "";
114
149
 
115
150
  if (segwitType) {
@@ -126,6 +161,7 @@ function verify(
126
161
  try {
127
162
  actual = encodeBech32Address(publicKeyHash);
128
163
  // if address is bech32 it is not p2sh
164
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
129
165
  } catch (e) {
130
166
  actual = encodeBech32Address(publicKeyHash);
131
167
  // base58 can be p2pkh or p2sh-p2wpkh
@@ -150,7 +186,7 @@ function magicHash(attestation: string) {
150
186
  const message = new TextEncoder().encode(attestation);
151
187
  const length = encodeLength(message.length).buffer;
152
188
  const buffer = new Uint8Array(
153
- prefix.length + length.byteLength + message.length,
189
+ prefix.length + length.byteLength + message.length
154
190
  );
155
191
  buffer.set(prefix);
156
192
  buffer.set(new Uint8Array(length), prefix.length);
package/src/eth.ts CHANGED
@@ -12,6 +12,7 @@ export function verifyEIP191(
12
12
  const publicKey = Secp256k1.recoverPublicKey({ payload, signature });
13
13
  const recovered = Address.checksum(Address.fromPublicKey(publicKey));
14
14
  return recovered.toString() === Address.checksum(address);
15
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
15
16
  } catch (error) {
16
17
  return false;
17
18
  }
@@ -20,7 +21,7 @@ export function verifyEIP191(
20
21
  export async function verifyPersonalSignEIP191(
21
22
  proof: SignatureProof,
22
23
  ): Promise<SignatureProof> {
23
- const [ns, _, address] = proof.address.split(/:/);
24
+ const [ns, , address] = proof.address.split(/:/);
24
25
  if (ns !== "eip155") return { ...proof, status: ProofStatus.FAILED };
25
26
 
26
27
  const verified = verifyEIP191(
package/src/index.ts CHANGED
@@ -12,7 +12,7 @@ import { verifySolanaSignature } from "./solana";
12
12
  import { verifyPersonalSignTIP191 } from "./tron";
13
13
 
14
14
  export async function verifyProof(
15
- proof: OwnershipProof,
15
+ proof: OwnershipProof
16
16
  ): Promise<OwnershipProof> {
17
17
  switch (proof.type) {
18
18
  case ProofTypes.SelfDeclaration:
@@ -35,6 +35,7 @@ export async function verifyProof(
35
35
  return verifySolanaSignature(proof as SignatureProof);
36
36
  case ProofTypes.EIP712:
37
37
  case ProofTypes.BIP137:
38
+ case ProofTypes.BIP322:
38
39
  return verifyBTCSignature(proof as SignatureProof);
39
40
  case ProofTypes.TIP191:
40
41
  return verifyPersonalSignTIP191(proof as SignatureProof);
package/src/solana.ts CHANGED
@@ -5,7 +5,7 @@ import { base64, base58 } from "@scure/base";
5
5
  export async function verifySolanaSignature(
6
6
  proof: SignatureProof,
7
7
  ): Promise<SignatureProof> {
8
- const [ns, _, address] = proof.address.split(/:/);
8
+ const [ns, , address] = proof.address.split(/:/);
9
9
  if (ns !== "solana") return { ...proof, status: ProofStatus.FAILED };
10
10
  try {
11
11
  const publicKey = base58.decode(address);
@@ -21,6 +21,7 @@ export async function verifySolanaSignature(
21
21
  ...proof,
22
22
  status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,
23
23
  };
24
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
24
25
  } catch (error) {
25
26
  return { ...proof, status: ProofStatus.FAILED };
26
27
  }
@@ -7,6 +7,19 @@ import {
7
7
  ProofTypes,
8
8
  } from "@notabene/javascript-sdk";
9
9
 
10
+ const bip322SegwitProof: SignatureProof = {
11
+ did: "did:pkh:bip122:000000000019d6689c085ae165831e93:bc1qcxm70pg5yk9c8pupj93uys5azw5xpt6qeu2z0u",
12
+ status: ProofStatus.PENDING,
13
+ attestation:
14
+ "I certify that bip122:000000000019d6689c085ae165831e93 account bc1qcxm70pg5yk9c8pupj93uys5azw5xpt6qeu2z0u belonged to did:key:z6Mket9c5r7VXswBGVrYX2t67hkh15D8CNpWJScX7ERKVWwD on Tue, 18 Feb 2025 18:29:27 GMT",
15
+ address:
16
+ "bip122:000000000019d6689c085ae165831e93:bc1qcxm70pg5yk9c8pupj93uys5azw5xpt6qeu2z0u",
17
+ proof:
18
+ "AkgwRQIhAIZlTevsH5hTsz8DOFT6hkNCNf+gBH8gjvRaI2x0T1YLAiAuzVHP+T05IO+URv/kJLjb0wDCiZwDA5DUiJPX4O7+aQEhAv9X2d9QIHF2C29QFUk5jWygaMbU3TAhzG+DfrgpI8EU",
19
+ wallet_provider: "Phantom (Wallet Connect)",
20
+ type: ProofTypes.BIP322,
21
+ };
22
+
10
23
  const segwitProof: SignatureProof = {
11
24
  type: ProofTypes.BIP137,
12
25
  address:
@@ -31,7 +44,24 @@ const legacyProof: SignatureProof = {
31
44
  wallet_provider: "BitMask",
32
45
  };
33
46
 
47
+ const uncompressedProof: SignatureProof = {
48
+ type: ProofTypes.BIP137,
49
+ address:
50
+ "bip122:000000000019d6689c085ae165831e93:13W4xRkFbbeDnZA3T7G9MRxcznLwv3UVVQ",
51
+ did: "did:pkh:bip122:000000000019d6689c085ae165831e93:13W4xRkFbbeDnZA3T7G9MRxcznLwv3UVVQ",
52
+ attestation: "A message signed by an uncompressed legacy Bitcoin address",
53
+ proof:
54
+ "HNBf9Xd4eSTBeuq6WXISKM5NqazBW3O546Jq7AaHnGowVtt8I1Ndng4EVlgJl0CPrfeaUxU0QSu73jwzfyOVnWk=",
55
+ status: ProofStatus.PENDING,
56
+ wallet_provider: "BitMask",
57
+ };
58
+
34
59
  describe("verifyBTCSignature", () => {
60
+ it("handles bip322 segwit addresses", async () => {
61
+ const result = await verifyBTCSignature(bip322SegwitProof);
62
+ expect(result).toEqual({ ...bip322SegwitProof, status: ProofStatus.VERIFIED });
63
+ });
64
+
35
65
  it("handles native segwit addresses", async () => {
36
66
  const result = await verifyBTCSignature(segwitProof);
37
67
  expect(result).toEqual({ ...segwitProof, status: ProofStatus.VERIFIED });
@@ -61,4 +91,12 @@ describe("verifyBTCSignature", () => {
61
91
  const result = await verifyBTCSignature(proof);
62
92
  expect(result).toEqual({ ...proof, status: ProofStatus.FAILED });
63
93
  });
94
+
95
+ it("verifies an uncompressed legacy bitcoin address signature", async () => {
96
+ const result = await verifyBTCSignature(uncompressedProof);
97
+ expect(result).toEqual({
98
+ ...uncompressedProof,
99
+ status: ProofStatus.VERIFIED,
100
+ });
101
+ });
64
102
  });
@@ -74,8 +74,7 @@ describe("verifyProof", () => {
74
74
  did: "did:example:123",
75
75
  address: "eip155:1:0x1234567890123456789012345678901234567890",
76
76
  };
77
-
78
- // @ts-ignore
77
+ // @ts-expect-error proof type is not known
79
78
  const result = await verifyProof(proof);
80
79
 
81
80
  expect(result).toEqual(proof);
@@ -149,11 +148,29 @@ describe("verifyProof", () => {
149
148
  wallet_provider: "Phantom",
150
149
  };
151
150
 
151
+ const bip322Proof: SignatureProof = {
152
+ did: "did:pkh:bip122:000000000019d6689c085ae165831e93:bc1qcxm70pg5yk9c8pupj93uys5azw5xpt6qeu2z0u",
153
+ status: ProofStatus.PENDING,
154
+ attestation:
155
+ "I certify that bip122:000000000019d6689c085ae165831e93 account bc1qcxm70pg5yk9c8pupj93uys5azw5xpt6qeu2z0u belonged to did:key:z6Mket9c5r7VXswBGVrYX2t67hkh15D8CNpWJScX7ERKVWwD on Tue, 18 Feb 2025 18:29:27 GMT",
156
+ address:
157
+ "bip122:000000000019d6689c085ae165831e93:bc1qcxm70pg5yk9c8pupj93uys5azw5xpt6qeu2z0u",
158
+ proof:
159
+ "AkgwRQIhAIZlTevsH5hTsz8DOFT6hkNCNf+gBH8gjvRaI2x0T1YLAiAuzVHP+T05IO+URv/kJLjb0wDCiZwDA5DUiJPX4O7+aQEhAv9X2d9QIHF2C29QFUk5jWygaMbU3TAhzG+DfrgpI8EU",
160
+ wallet_provider: "Phantom (Wallet Connect)",
161
+ type: ProofTypes.BIP322,
162
+ };
163
+
152
164
  it("should verify proof", async () => {
153
165
  const result = await verifyProof(proof);
154
166
  expect(result.status).toBe(ProofStatus.VERIFIED);
155
167
  });
156
168
 
169
+ it("should verify bip322 proof", async () => {
170
+ const result = await verifyProof(bip322Proof);
171
+ expect(result.status).toBe(ProofStatus.VERIFIED);
172
+ });
173
+
157
174
  it("should fail if not invalid proof", async () => {
158
175
  const result = await verifyProof({
159
176
  ...proof,
package/src/tron.ts CHANGED
@@ -19,6 +19,7 @@ export function verifyTIP191(
19
19
  const checked = Bytes.concat(bytes, checksum);
20
20
  const b58 = base58.encode(checked);
21
21
  return b58 === address;
22
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
22
23
  } catch (error) {
23
24
  return false;
24
25
  }
@@ -27,7 +28,7 @@ export function verifyTIP191(
27
28
  export async function verifyPersonalSignTIP191(
28
29
  proof: SignatureProof,
29
30
  ): Promise<SignatureProof> {
30
- const [ns, _, address] = proof.address.split(/:/);
31
+ const [ns, , address] = proof.address.split(/:/);
31
32
  if (ns !== "tron") return { ...proof, status: ProofStatus.FAILED };
32
33
 
33
34
  const verified = verifyTIP191(