@notabene/verify-proof 1.0.1 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- var e=require("@notabene/javascript-sdk"),r=require("bech32"),t=require("@bitauth/libauth"),o=require("varuint-bitcoin"),s=require("@stablelib/base64"),n=require("ox"),a=require("tweetnacl"),i=require("bs58");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var c,f,P=/*#__PURE__*/u(a),l=/*#__PURE__*/u(i);function d(){return d=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},d.apply(null,arguments)}function h(e){var t=r.bech32.toWords(e);return t.unshift(0),r.bech32.encode("bc",t)}!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"}(f||(f={})),exports.verifyProof=function(r){try{switch(r.type){case e.ProofTypes.SelfDeclaration:return Promise.resolve(d({},r,{status:r.confirmed?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}));case e.ProofTypes.Screenshot:return Promise.resolve(d({},r,{status:r.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(d({},r,{status:e.ProofStatus.FAILED}));var s=function(e,r,t){try{var o=n.PersonalMessage.getSignPayload(n.Hex.fromString(r)),s=n.Signature.fromHex(t),a=n.Secp256k1.recoverPublicKey({payload:o,signature:s});return n.Address.fromPublicKey(a).toString()===e.toString()}catch(e){return!1}}(o,r.attestation,r.proof);return Promise.resolve(d({},r,{status:s?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(e){return Promise.reject(e)}}(r));case e.ProofTypes.ED25519:return Promise.resolve(function(r){try{var t=r.address.split(/:/),o=t[2];if("solana"!==t[0])return Promise.resolve(d({},r,{status:e.ProofStatus.FAILED}));try{var n=l.default.decode(o),a=(new TextEncoder).encode(r.attestation),i=s.decode(r.proof),u=P.default.sign.detached.verify(a,i,n);return Promise.resolve(d({},r,{status:u?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(t){return Promise.resolve(d({},r,{status:e.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(r));case e.ProofTypes.EIP712:case e.ProofTypes.BIP137:return Promise.resolve(function(r){try{var n=r.address.split(/:/),a=n[2];if("bip122"!==n[0])return Promise.resolve(d({},r,{status:e.ProofStatus.FAILED}));try{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"))}(a)),u=function(e,r,n,a){var i=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");return{compressed:!!(12&t),segwitType:8&t?4&t?c.P2WPKH:c.P2SH_P2WPKH:void 0,recovery:3&t,signature:r.slice(1)}}(n),u=i.compressed,f=i.segwitType,P=i.recovery,l=i.signature;if(a&&!u)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var d=function(e){var r=(new TextEncoder).encode("Bitcoin Signed Message:\n"),s=(new TextEncoder).encode(e),n=o.encode(s.length).buffer,a=new Uint8Array(r.length+n.byteLength+s.length);return a.set(r),a.set(new Uint8Array(n),r.length),a.set(s,r.length+n.byteLength),t.hash256(a)}(e),v=u?t.secp256k1.recoverPublicKeyCompressed(l,P,d):t.secp256k1.recoverPublicKeyUncompressed(l,P,d);if("string"==typeof v)throw new Error(v);var E=t.hash160(v),p="";if(f)p=h(E);else if(a)try{p=h(E)}catch(e){p=h(E)}else p=t.encodeBase58AddressFormat(0,E);return p===r}(r.attestation,a,r.proof,i);return Promise.resolve(d({},r,{status:u?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(t){return Promise.resolve(d({},r,{status:e.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(r))}return Promise.resolve(r)}catch(e){return Promise.reject(e)}};
1
+ var e=require("@notabene/javascript-sdk"),r=require("@bitauth/libauth"),t=require("varuint-bitcoin"),o=require("@scure/base"),s=require("ox");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var a,i,c=/*#__PURE__*/n(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 o in t)({}).hasOwnProperty.call(t,o)&&(e[o]=t[o])}return e},u.apply(null,arguments)}function f(e){var r=o.bech32.toWords(e);return r.unshift(0),o.bech32.encode("bc",r)}!function(e){e.P2WPKH="p2wpkh",e.P2SH_P2WPKH="p2sh(p2wpkh)"}(a||(a={})),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"}(i||(i={})),exports.verifyProof=function(n){try{switch(n.type){case e.ProofTypes.SelfDeclaration:return Promise.resolve(u({},n,{status:n.confirmed?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}));case e.ProofTypes.Screenshot:return Promise.resolve(u({},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(u({},r,{status:e.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,r.attestation,r.proof);return Promise.resolve(u({},r,{status:n?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(e){return Promise.reject(e)}}(n));case e.ProofTypes.ED25519:return Promise.resolve(function(r){try{var t=r.address.split(/:/),s=t[2];if("solana"!==t[0])return Promise.resolve(u({},r,{status:e.ProofStatus.FAILED}));try{var n=o.base58.decode(s),a=(new TextEncoder).encode(r.attestation),i=o.base64.decode(r.proof),f=c.default.sign.detached.verify(a,i,n);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)}}(n));case e.ProofTypes.EIP712:case e.ProofTypes.BIP137:return Promise.resolve(function(s){try{var n=s.address.split(/:/),c=n[2];if("bip122"!==n[0])return Promise.resolve(u({},s,{status:e.ProofStatus.FAILED}));try{var P=[i.SEGWIT,i.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return i.NATIVE;if(e.match("^[32M].*"))return i.SEGWIT;if(e.match("^[1nmL].*"))return i.LEGACY;if(e.match("^(D).*"))return i.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(c)),l=function(e,s,n,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");return{compressed:!!(12&t),segwitType:8&t?4&t?a.P2WPKH:a.P2SH_P2WPKH:void 0,recovery:3&t,signature:r.slice(1)}}(n),u=c.compressed,P=c.segwitType,l=c.recovery,d=c.signature;if(i&&!u)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var h=function(e){var o=(new TextEncoder).encode("Bitcoin Signed Message:\n"),s=(new TextEncoder).encode(e),n=t.encode(s.length).buffer,a=new Uint8Array(o.length+n.byteLength+s.length);return a.set(o),a.set(new Uint8Array(n),o.length),a.set(s,o.length+n.byteLength),r.hash256(a)}(e),v=u?r.secp256k1.recoverPublicKeyCompressed(d,l,h):r.secp256k1.recoverPublicKeyUncompressed(d,l,h);if("string"==typeof v)throw new Error(v);var E=r.hash160(v),p="";if(P)p=f(E);else if(i)try{p=f(E)}catch(e){p=f(E)}else p=r.encodeBase58AddressFormat(0,E);return p===s}(s.attestation,c,s.proof,P);return Promise.resolve(u({},s,{status:l?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(r){return Promise.resolve(u({},s,{status: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"],"sourcesContent":["import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { bech32 } from \"bech32\";\n\nimport {\n secp256k1,\n hash160,\n hash256,\n RecoveryId,\n encodeBase58AddressFormat,\n} from \"@bitauth/libauth\";\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { decode as decodeBase64 } from \"@stablelib/base64\";\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 // 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 return { ...proof, status: 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 recovery: RecoveryId;\n signature: Uint8Array;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const signature = decodeBase64(proof);\n if (signature.length !== 65) throw new Error(\"Invalid signature length\");\n\n const flagByte = signature[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n\n return {\n compressed: !!(flagByte & 12),\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n recovery: (flagByte & 3) as RecoveryId,\n signature: signature.slice(1),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n) {\n const { compressed, segwitType, recovery, signature } =\n 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\n const hash = magicHash(attestation);\n const publicKey: Uint8Array | string = compressed\n ? secp256k1.recoverPublicKeyCompressed(signature, recovery, hash)\n : secp256k1.recoverPublicKeyUncompressed(signature, recovery, hash);\n if (typeof publicKey === \"string\") throw new Error(publicKey);\n const publicKeyHash = hash160(publicKey);\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\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","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\";\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.BIP137_XPUB:\n case ProofTypes.MicroTransfer:\n }\n return proof;\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\n\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.fromPublicKey(publicKey);\n return recovered.toString() === address.toString();\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 { decode as decodeBase64 } from \"@stablelib/base64\";\nimport bs58 from \"bs58\";\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 = bs58.decode(address);\n const messageBytes = new TextEncoder().encode(proof.attestation);\n const signatureBytes = decodeBase64(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","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","fromPublicKey","toString","error","verifyEIP191","attestation","e","reject","verifyPersonalSignEIP191","ED25519","bs58","decode","messageBytes","TextEncoder","signatureBytes","decodeBase64","nacl","sign","detached","verify","verifySolanaSignature","EIP712","BIP137","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","checkSegwitAlways","_decodeSignature","length","flagByte","compressed","segwitType","P2WPKH","P2SH_P2WPKH","undefined","recovery","slice","decodeSignature","hash","prefix","encodeLength","buffer","Uint8Array","byteLength","set","hash256","magicHash","secp256k1","recoverPublicKeyCompressed","recoverPublicKeyUncompressed","hash160","actual","encodeBase58AddressFormat","verifyBTCSignature"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/bitcoin.ts","../src/index.ts","../src/eth.ts","../src/solana.ts"],"sourcesContent":["import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\n\nimport {\n secp256k1,\n hash160,\n hash256,\n RecoveryId,\n encodeBase58AddressFormat,\n} from \"@bitauth/libauth\";\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { base64, bech32 } from \"@scure/base\";\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 // 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 return { ...proof, status: 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 recovery: RecoveryId;\n signature: Uint8Array;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const signature = base64.decode(proof);\n if (signature.length !== 65) throw new Error(\"Invalid signature length\");\n\n const flagByte = signature[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n\n return {\n compressed: !!(flagByte & 12),\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n recovery: (flagByte & 3) as RecoveryId,\n signature: signature.slice(1),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n) {\n const { compressed, segwitType, recovery, signature } =\n 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\n const hash = magicHash(attestation);\n const publicKey: Uint8Array | string = compressed\n ? secp256k1.recoverPublicKeyCompressed(signature, recovery, hash)\n : secp256k1.recoverPublicKeyUncompressed(signature, recovery, hash);\n if (typeof publicKey === \"string\") throw new Error(publicKey);\n const publicKeyHash = hash160(publicKey);\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\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","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\";\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.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","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","length","flagByte","compressed","segwitType","P2WPKH","P2SH_P2WPKH","undefined","recovery","slice","decodeSignature","hash","prefix","encodeLength","buffer","Uint8Array","byteLength","set","hash256","magicHash","secp256k1","recoverPublicKeyCompressed","recoverPublicKeyUncompressed","hash160","actual","encodeBase58AddressFormat","verifyBTCSignature"],"mappings":"0NAYKA,EAOAC,iQA2IL,SAASC,EAAoBC,GAC3B,IAAMC,EAASC,EAAAA,OAAOC,QAAQH,GAE9B,OADAC,EAAOG,QAAQ,GACRF,EAAMA,OAACG,OAAO,KAAMJ,EAC7B,EAtJA,SAAKJ,GACHA,EAAA,OAAA,SACAA,EAAA,YAAA,cACD,CAHD,CAAKA,IAAAA,EAGJ,CAAA,IAID,SAAKC,GACHA,EAAA,OAAA,SACAA,EAAA,OAAA,gBACAA,EAAA,OAAA,SACAA,EAAA,YAAA,OACAA,EAAA,IAAA,eACAA,EAAA,SAAA,WACAA,EAAA,SAAA,WACAA,EAAA,QAAA,SACD,CATD,CAAKA,IAAAA,EASJ,CAAA,wBChBgC,SAC/BQ,GAAqB,IAErB,OAAQA,EAAMC,MACZ,KAAKC,aAAWC,gBACd,OAAAC,QAAAC,QAAAC,KACKN,EAAK,CACRO,OAASP,EAA2BQ,UAChCC,EAAWA,YAACC,SACZD,cAAYE,UAEpB,KAAKT,EAAUA,WAACU,WACd,OAAAR,QAAAC,QAAAC,EACKN,CAAAA,EAAAA,GACHO,OAASP,EAA0Ba,IAC/BJ,EAAWA,YAACK,QACZL,EAAAA,YAAYE,UAEpB,KAAKT,EAAAA,WAAWa,OACd,OAAAX,QAAAC,QCZwC,SAC5CL,OAEA,IAAAgB,EAAyBhB,EAAMiB,QAAQC,MAAM,KAA/BD,EAAOD,EAAA,GACrB,GAAW,WADFA,EAAEG,GACU,OAAAf,QAAAC,QAAAC,EAAYN,GAAAA,EAAOO,CAAAA,OAAQE,EAAAA,YAAYE,UAE5D,IAAMS,WArBNH,EACAI,EACArB,GAEA,IACE,IAAMsB,EAAUC,kBAAgBC,eAAeC,EAAAA,IAAIC,WAAWL,IACxDM,EAAYC,EAASA,UAACC,QAAQ7B,GAC9B8B,EAAYC,EAASA,UAACC,iBAAiB,CAAEV,QAAAA,EAASK,UAAAA,IAExD,OADkBM,EAAAA,QAAQC,SAASD,EAAAA,QAAQE,cAAcL,IACxCM,aAAeH,EAAAA,QAAQC,SAASjB,EACnD,CAAE,MAAOoB,GACP,OAAO,CACT,CACF,CAQmBC,CACfrB,EACAjB,EAAMuC,YACNvC,EAAMA,OAER,OAAAI,QAAAC,QAAAC,KACKN,EAAK,CACRO,OAAQa,EAAWX,EAAWA,YAACC,SAAWD,EAAWA,YAACE,SAE1D,CAAC,MAAA6B,GAAApC,OAAAA,QAAAqC,OAAAD,EAAA,CAAA,CDHYE,CAAyB1C,IAClC,KAAKE,EAAAA,WAAWyC,QACd,OAAAvC,QAAAC,QE7BqC,SACzCL,GAAqB,IAErB,IAAAgB,EAAyBhB,EAAMiB,QAAQC,MAAM,KAA/BD,EAAOD,EACrB,GAAA,GAAW,WADFA,EAAEG,GACU,OAAAf,QAAAC,QAAAC,EAAYN,GAAAA,GAAOO,OAAQE,EAAWA,YAACE,UAC5D,IACE,IAAMmB,EAAYc,EAAMA,OAACC,OAAO5B,GAC1B6B,GAAe,IAAIC,aAAchD,OAAOC,EAAMuC,aAC9CS,EAAiBC,SAAOJ,OAAO7C,EAAMA,OACrCoB,EAAW8B,UAAKC,KAAKC,SAASC,OAClCP,EACAE,EACAlB,GAGF,OAAA1B,QAAAC,QAAAC,EAAA,CAAA,EACKN,EACHO,CAAAA,OAAQa,EAAWX,EAAWA,YAACC,SAAWD,EAAAA,YAAYE,SAE1D,CAAE,MAAO0B,GACP,OAAAjC,QAAAC,QAAAC,EAAYN,CAAAA,EAAAA,GAAOO,OAAQE,cAAYE,SACzC,CACF,CAAC,MAAA6B,GAAA,OAAApC,QAAAqC,OAAAD,EAAA,CAAA,CFOYc,CAAsBtD,IAC/B,KAAKE,aAAWqD,OAChB,KAAKrD,EAAAA,WAAWsD,OACd,OAAApD,QAAAC,QDNgB,SACpBL,GAAqB,IAErB,IAAAgB,EAAyBhB,EAAMiB,QAAQC,MAAM,KAA/BD,EAAOD,EAAA,GACrB,GAAW,WADFA,EAAEG,GACU,OAAAf,QAAAC,QAAAC,EAAYN,CAAAA,EAAAA,GAAOO,OAAQE,EAAAA,YAAYE,UAC5D,IAEE,IAAM8C,EAAS,CAACjE,EAAekE,OAAQlE,EAAemE,QAAQC,SAclE,SAA2B3C,GACzB,GAAIA,EAAQ4C,MAAM,qBAChB,OAAOrE,EAAemE,OACjB,GAAI1C,EAAQ4C,MAAM,YACvB,OAAOrE,EAAekE,OACjB,GAAIzC,EAAQ4C,MAAM,aACvB,OAAOrE,EAAesE,OACjB,GAAI7C,EAAQ4C,MAAM,UACvB,OAAOrE,EAAeuE,SAEtB,MAAU,IAAAC,MACR,oBACGC,OAAOhD,GACPgD,OAAO,0CAGhB,CA7BMC,CAAkBjD,IAEdG,EAyDV,SACEmB,EACAtB,EACAjB,EACAmE,GAEA,IAAAC,EA3BF,SAAyBpE,GACvB,IAAM2B,EAAYsB,SAAOJ,OAAO7C,GAChC,GAAyB,KAArB2B,EAAU0C,OAAe,UAAUL,MAAM,4BAE7C,IAAMM,EAAW3C,EAAU,GAAK,GAChC,GAAI2C,EAAW,IAAMA,EAAW,EAC9B,MAAM,IAAIN,MAAM,+BAGlB,MAAO,CACLO,cAA0B,GAAXD,GACfE,WAAyB,EAAXF,EAEG,EAAXA,EAEA/E,EAAakF,OADblF,EAAamF,iBAFfC,EAIJC,SAAsB,EAAXN,EACX3C,UAAWA,EAAUkD,MAAM,GAE/B,CASIC,CAAgB9E,GADVuE,EAAUH,EAAVG,WAAYC,EAAUJ,EAAVI,WAAYI,EAAQR,EAARQ,SAAUjD,EAASyC,EAATzC,UAE1C,GAAIwC,IAAsBI,EACxB,MAAU,IAAAP,MACR,kFAIJ,IAAMe,EAkCR,SAAmBxC,GACjB,IAAMyC,GAAS,IAAIjC,aAAchD,OAjIb,8BAkIdsB,GAAU,IAAI0B,aAAchD,OAAOwC,GACnC8B,EAASY,EAAYlF,OAACsB,EAAQgD,QAAQa,OACtCA,EAAS,IAAIC,WACjBH,EAAOX,OAASA,EAAOe,WAAa/D,EAAQgD,QAK9C,OAHAa,EAAOG,IAAIL,GACXE,EAAOG,IAAI,IAAIF,WAAWd,GAASW,EAAOX,QAC1Ca,EAAOG,IAAIhE,EAAS2D,EAAOX,OAASA,EAAOe,YACpCE,EAAOA,QAACJ,EACjB,CA7CeK,CAAUhD,GACjBT,EAAiCyC,EACnCiB,EAASA,UAACC,2BAA2B9D,EAAWiD,EAAUG,GAC1DS,EAASA,UAACE,6BAA6B/D,EAAWiD,EAAUG,GAChE,GAAyB,iBAAdjD,EAAwB,MAAM,IAAIkC,MAAMlC,GACnD,IAAMpC,EAAgBiG,EAAOA,QAAC7D,GAC1B8D,EAAiB,GAErB,GAAIpB,EAEAoB,EAASnG,EAAoBC,QAQ/B,GAAIyE,EACF,IACEyB,EAASnG,EAAoBC,EAE/B,CAAE,MAAO8C,GACPoD,EAASnG,EAAoBC,EAE/B,MAEAkG,EAASC,4BAA0B,EAAGnG,GAI1C,OAAOkG,IAAW3E,CACpB,CAvGqBoC,CAAOrD,EAAMuC,YAAatB,EAASjB,EAAMA,MAAOyD,GAEjE,OAAArD,QAAAC,QAAAC,KACKN,EAAK,CACRO,OAAQa,EAAWX,EAAAA,YAAYC,SAAWD,cAAYE,SAE1D,CAAE,MAAO0B,GACP,OAAAjC,QAAAC,QAAAC,EAAA,CAAA,EAAYN,EAAOO,CAAAA,OAAQE,cAAYE,SACzC,CACF,CAAC,MAAA6B,GAAA,OAAApC,QAAAqC,OAAAD,EArCD,CAAA,CCwBasD,CAAmB9F,IAI9B,OAAAI,QAAAC,QAAOL,EACT,CAAC,MAAAwC,GAAA,OAAApC,QAAAqC,OAAAD,EAAA,CAAA"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{ProofStatus as e,ProofTypes as r}from"@notabene/javascript-sdk";import{bech32 as t}from"bech32";import{secp256k1 as n,hash160 as o,encodeBase58AddressFormat as s,hash256 as i}from"@bitauth/libauth";import{encode as a}from"varuint-bitcoin";import{decode as c}from"@stablelib/base64";import{PersonalMessage as u,Hex as l,Signature as f,Secp256k1 as m,Address as v}from"ox";import E from"tweetnacl";import h from"bs58";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 d,P;function g(e){var r=t.toWords(e);return r.unshift(0),t.encode("bc",r)}!function(e){e.P2WPKH="p2wpkh",e.P2SH_P2WPKH="p2sh(p2wpkh)"}(d||(d={})),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"}(P||(P={}));var I=function(t){try{switch(t.type){case r.SelfDeclaration:return Promise.resolve(p({},t,{status:t.confirmed?e.VERIFIED:e.FAILED}));case r.Screenshot:return Promise.resolve(p({},t,{status:t.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=u.getSignPayload(l.fromString(r)),o=f.fromHex(t),s=m.recoverPublicKey({payload:n,signature:o});return v.fromPublicKey(s).toString()===e.toString()}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)}}(t));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=h.decode(n),s=(new TextEncoder).encode(r.attestation),i=c(r.proof),a=E.sign.detached.verify(s,i,o);return Promise.resolve(p({},r,{status:a?e.VERIFIED:e.FAILED}))}catch(t){return Promise.resolve(p({},r,{status:e.FAILED}))}}catch(e){return Promise.reject(e)}}(t));case r.EIP712:case r.BIP137:return Promise.resolve(function(r){try{var t=r.address.split(/:/),u=t[2];if("bip122"!==t[0])return Promise.resolve(p({},r,{status:e.FAILED}));try{var l=[P.SEGWIT,P.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return P.NATIVE;if(e.match("^[32M].*"))return P.SEGWIT;if(e.match("^[1nmL].*"))return P.LEGACY;if(e.match("^(D).*"))return P.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(u)),f=function(e,r,t,u){var l=function(e){var r=c(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");return{compressed:!!(12&t),segwitType:8&t?4&t?d.P2WPKH:d.P2SH_P2WPKH:void 0,recovery:3&t,signature:r.slice(1)}}(t),f=l.compressed,m=l.segwitType,v=l.recovery,E=l.signature;if(u&&!f)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var h=function(e){var r=(new TextEncoder).encode("Bitcoin Signed Message:\n"),t=(new TextEncoder).encode(e),n=a(t.length).buffer,o=new Uint8Array(r.length+n.byteLength+t.length);return o.set(r),o.set(new Uint8Array(n),r.length),o.set(t,r.length+n.byteLength),i(o)}(e),p=f?n.recoverPublicKeyCompressed(E,v,h):n.recoverPublicKeyUncompressed(E,v,h);if("string"==typeof p)throw new Error(p);var P=o(p),I="";if(m)I=g(P);else if(u)try{I=g(P)}catch(e){I=g(P)}else I=s(0,P);return I===r}(r.attestation,u,r.proof,l);return Promise.resolve(p({},r,{status:f?e.VERIFIED:e.FAILED}))}catch(t){return Promise.resolve(p({},r,{status:e.FAILED}))}}catch(e){return Promise.reject(e)}}(t))}return Promise.resolve(t)}catch(e){return Promise.reject(e)}};export{I as verifyProof};
1
+ import{ProofStatus as e,ProofTypes as r}from"@notabene/javascript-sdk";import{secp256k1 as t,hash160 as n,encodeBase58AddressFormat as o,hash256 as s}from"@bitauth/libauth";import{encode as i}from"varuint-bitcoin";import{bech32 as a,base64 as c,base58 as u}from"@scure/base";import{PersonalMessage as l,Hex as f,Signature as m,Secp256k1 as v,Address as E}from"ox";import h from"tweetnacl";function d(){return d=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},d.apply(null,arguments)}var p,P;function g(e){var r=a.toWords(e);return r.unshift(0),a.encode("bc",r)}!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"}(P||(P={}));var I=function(a){try{switch(a.type){case r.SelfDeclaration:return Promise.resolve(d({},a,{status:a.confirmed?e.VERIFIED:e.FAILED}));case r.Screenshot:return Promise.resolve(d({},a,{status:a.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(d({},r,{status:e.FAILED}));var o=function(e,r,t){try{var n=l.getSignPayload(f.fromString(r)),o=m.fromHex(t),s=v.recoverPublicKey({payload:n,signature:o});return E.checksum(E.fromPublicKey(s)).toString()===E.checksum(e)}catch(e){return!1}}(n,r.attestation,r.proof);return Promise.resolve(d({},r,{status:o?e.VERIFIED:e.FAILED}))}catch(e){return Promise.reject(e)}}(a));case r.ED25519:return Promise.resolve(function(r){try{var t=r.address.split(/:/),n=t[2];if("solana"!==t[0])return Promise.resolve(d({},r,{status:e.FAILED}));try{var o=u.decode(n),s=(new TextEncoder).encode(r.attestation),i=c.decode(r.proof),a=h.sign.detached.verify(s,i,o);return Promise.resolve(d({},r,{status:a?e.VERIFIED:e.FAILED}))}catch(t){return Promise.resolve(d({},r,{status:e.FAILED}))}}catch(e){return Promise.reject(e)}}(a));case r.EIP712:case r.BIP137:return Promise.resolve(function(r){try{var a=r.address.split(/:/),u=a[2];if("bip122"!==a[0])return Promise.resolve(d({},r,{status:e.FAILED}));try{var l=[P.SEGWIT,P.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return P.NATIVE;if(e.match("^[32M].*"))return P.SEGWIT;if(e.match("^[1nmL].*"))return P.LEGACY;if(e.match("^(D).*"))return P.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(u)),f=function(e,r,a,u){var l=function(e){var r=c.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");return{compressed:!!(12&t),segwitType:8&t?4&t?p.P2WPKH:p.P2SH_P2WPKH:void 0,recovery:3&t,signature:r.slice(1)}}(a),f=l.compressed,m=l.segwitType,v=l.recovery,E=l.signature;if(u&&!f)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var h=function(e){var r=(new TextEncoder).encode("Bitcoin Signed Message:\n"),t=(new TextEncoder).encode(e),n=i(t.length).buffer,o=new Uint8Array(r.length+n.byteLength+t.length);return o.set(r),o.set(new Uint8Array(n),r.length),o.set(t,r.length+n.byteLength),s(o)}(e),d=f?t.recoverPublicKeyCompressed(E,v,h):t.recoverPublicKeyUncompressed(E,v,h);if("string"==typeof d)throw new Error(d);var P=n(d),I="";if(m)I=g(P);else if(u)try{I=g(P)}catch(e){I=g(P)}else I=o(0,P);return I===r}(r.attestation,u,r.proof,l);return Promise.resolve(d({},r,{status:f?e.VERIFIED:e.FAILED}))}catch(t){return Promise.resolve(d({},r,{status:e.FAILED}))}}catch(e){return Promise.reject(e)}}(a))}return Promise.resolve(a)}catch(e){return Promise.reject(e)}};export{I 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/index.ts","../src/eth.ts","../src/solana.ts"],"sourcesContent":["import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { bech32 } from \"bech32\";\n\nimport {\n secp256k1,\n hash160,\n hash256,\n RecoveryId,\n encodeBase58AddressFormat,\n} from \"@bitauth/libauth\";\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { decode as decodeBase64 } from \"@stablelib/base64\";\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 // 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 return { ...proof, status: 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 recovery: RecoveryId;\n signature: Uint8Array;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const signature = decodeBase64(proof);\n if (signature.length !== 65) throw new Error(\"Invalid signature length\");\n\n const flagByte = signature[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n\n return {\n compressed: !!(flagByte & 12),\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n recovery: (flagByte & 3) as RecoveryId,\n signature: signature.slice(1),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n) {\n const { compressed, segwitType, recovery, signature } =\n 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\n const hash = magicHash(attestation);\n const publicKey: Uint8Array | string = compressed\n ? secp256k1.recoverPublicKeyCompressed(signature, recovery, hash)\n : secp256k1.recoverPublicKeyUncompressed(signature, recovery, hash);\n if (typeof publicKey === \"string\") throw new Error(publicKey);\n const publicKeyHash = hash160(publicKey);\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\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","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\";\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.BIP137_XPUB:\n case ProofTypes.MicroTransfer:\n }\n return proof;\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\n\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.fromPublicKey(publicKey);\n return recovered.toString() === address.toString();\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 { decode as decodeBase64 } from \"@stablelib/base64\";\nimport bs58 from \"bs58\";\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 = bs58.decode(address);\n const messageBytes = new TextEncoder().encode(proof.attestation);\n const signatureBytes = decodeBase64(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","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","fromPublicKey","toString","error","verifyEIP191","attestation","e","reject","verifyPersonalSignEIP191","ED25519","bs58","decode","messageBytes","TextEncoder","signatureBytes","decodeBase64","nacl","sign","detached","verify","verifySolanaSignature","EIP712","BIP137","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","checkSegwitAlways","_decodeSignature","length","flagByte","compressed","segwitType","P2WPKH","P2SH_P2WPKH","undefined","recovery","slice","decodeSignature","hash","prefix","encodeLength","buffer","Uint8Array","byteLength","set","hash256","magicHash","secp256k1","recoverPublicKeyCompressed","recoverPublicKeyUncompressed","hash160","actual","encodeBase58AddressFormat","verifyBTCSignature"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/bitcoin.ts","../src/eth.ts","../src/index.ts","../src/solana.ts"],"sourcesContent":["import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\n\nimport {\n secp256k1,\n hash160,\n hash256,\n RecoveryId,\n encodeBase58AddressFormat,\n} from \"@bitauth/libauth\";\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { base64, bech32 } from \"@scure/base\";\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 // 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 return { ...proof, status: 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 recovery: RecoveryId;\n signature: Uint8Array;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const signature = base64.decode(proof);\n if (signature.length !== 65) throw new Error(\"Invalid signature length\");\n\n const flagByte = signature[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n\n return {\n compressed: !!(flagByte & 12),\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n recovery: (flagByte & 3) as RecoveryId,\n signature: signature.slice(1),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n) {\n const { compressed, segwitType, recovery, signature } =\n 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\n const hash = magicHash(attestation);\n const publicKey: Uint8Array | string = compressed\n ? secp256k1.recoverPublicKeyCompressed(signature, recovery, hash)\n : secp256k1.recoverPublicKeyUncompressed(signature, recovery, hash);\n if (typeof publicKey === \"string\") throw new Error(publicKey);\n const publicKeyHash = hash160(publicKey);\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\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","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\";\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.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"],"names":["SEGWIT_TYPES","DerivationMode","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","length","flagByte","compressed","segwitType","P2WPKH","P2SH_P2WPKH","undefined","recovery","slice","decodeSignature","hash","prefix","encodeLength","buffer","Uint8Array","byteLength","set","hash256","magicHash","secp256k1","recoverPublicKeyCompressed","recoverPublicKeyUncompressed","hash160","actual","encodeBase58AddressFormat","verifyBTCSignature"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{ProofStatus as t,ProofTypes as e}from"@notabene/javascript-sdk";import{bech32 as r}from"bech32";import{secp256k1 as n,hash160 as o,encodeBase58AddressFormat as s,hash256 as c}from"@bitauth/libauth";import{encode as i}from"varuint-bitcoin";import{decode as a}from"@stablelib/base64";import{PersonalMessage as u,Hex as f,Signature as E,Secp256k1 as l,Address as p}from"ox";import h from"tweetnacl";import d from"bs58";function g(){return g=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var n in r)({}).hasOwnProperty.call(r,n)&&(t[n]=r[n])}return t},g.apply(null,arguments)}var I,m;function y(t){const e=r.toWords(t);return e.unshift(0),r.encode("bc",e)}async function b(r){switch(r.type){case e.SelfDeclaration:return g({},r,{status:r.confirmed?t.VERIFIED:t.FAILED});case e.Screenshot:return g({},r,{status:r.url?t.FLAGGED:t.FAILED});case e.EIP191:return async function(e){const[r,n,o]=e.address.split(/:/);if("eip155"!==r)return g({},e,{status:t.FAILED});const s=function(t,e,r){try{const n=u.getSignPayload(f.fromString(e)),o=E.fromHex(r),s=l.recoverPublicKey({payload:n,signature:o});return p.fromPublicKey(s).toString()===t.toString()}catch(t){return!1}}(o,e.attestation,e.proof);return g({},e,{status:s?t.VERIFIED:t.FAILED})}(r);case e.ED25519:return async function(e){const[r,n,o]=e.address.split(/:/);if("solana"!==r)return g({},e,{status:t.FAILED});try{const r=d.decode(o),n=(new TextEncoder).encode(e.attestation),s=a(e.proof);return g({},e,{status:h.sign.detached.verify(n,s,r)?t.VERIFIED:t.FAILED})}catch(r){return g({},e,{status:t.FAILED})}}(r);case e.EIP712:case e.BIP137:return async function(e){const[r,u,f]=e.address.split(/:/);if("bip122"!==r)return g({},e,{status:t.FAILED});try{const r=[m.SEGWIT,m.NATIVE].includes(function(t){if(t.match("^(bc1|tb1|ltc1).*"))return m.NATIVE;if(t.match("^[32M].*"))return m.SEGWIT;if(t.match("^[1nmL].*"))return m.LEGACY;if(t.match("^(D).*"))return m.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(t).concat(" is not a valid or a supported address"))}(f)),u=function(t,e,r,u){const{compressed:f,segwitType:E,recovery:l,signature:p}=function(t){const e=a(t);if(65!==e.length)throw new Error("Invalid signature length");const r=e[0]-27;if(r>15||r<0)throw new Error("Invalid signature parameter");return{compressed:!!(12&r),segwitType:8&r?4&r?I.P2WPKH:I.P2SH_P2WPKH:void 0,recovery:3&r,signature:e.slice(1)}}(r);if(u&&!f)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");const h=function(t){const e=(new TextEncoder).encode("Bitcoin Signed Message:\n"),r=(new TextEncoder).encode(t),n=i(r.length).buffer,o=new Uint8Array(e.length+n.byteLength+r.length);return o.set(e),o.set(new Uint8Array(n),e.length),o.set(r,e.length+n.byteLength),c(o)}(t),d=f?n.recoverPublicKeyCompressed(p,l,h):n.recoverPublicKeyUncompressed(p,l,h);if("string"==typeof d)throw new Error(d);const g=o(d);let m="";if(E)m=y(g);else if(u)try{m=y(g)}catch(t){m=y(g)}else m=s(0,g);return m===e}(e.attestation,f,e.proof,r);return g({},e,{status:u?t.VERIFIED:t.FAILED})}catch(r){return g({},e,{status:t.FAILED})}}(r)}return r}!function(t){t.P2WPKH="p2wpkh",t.P2SH_P2WPKH="p2sh(p2wpkh)"}(I||(I={})),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"}(m||(m={}));export{b as verifyProof};
1
+ import{ProofStatus as t,ProofTypes as e}from"@notabene/javascript-sdk";import{secp256k1 as r,hash160 as n,encodeBase58AddressFormat as o,hash256 as s}from"@bitauth/libauth";import{encode as c}from"varuint-bitcoin";import{bech32 as i,base64 as a,base58 as u}from"@scure/base";import{PersonalMessage as f,Hex as E,Signature as d,Secp256k1 as h,Address as l}from"ox";import p from"tweetnacl";function g(){return g=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var n in r)({}).hasOwnProperty.call(r,n)&&(t[n]=r[n])}return t},g.apply(null,arguments)}var I,y;function m(t){const e=i.toWords(t);return e.unshift(0),i.encode("bc",e)}async function w(i){switch(i.type){case e.SelfDeclaration:return g({},i,{status:i.confirmed?t.VERIFIED:t.FAILED});case e.Screenshot:return g({},i,{status:i.url?t.FLAGGED:t.FAILED});case e.EIP191:return async function(e){const[r,n,o]=e.address.split(/:/);if("eip155"!==r)return g({},e,{status:t.FAILED});const s=function(t,e,r){try{const n=f.getSignPayload(E.fromString(e)),o=d.fromHex(r),s=h.recoverPublicKey({payload:n,signature:o});return l.checksum(l.fromPublicKey(s)).toString()===l.checksum(t)}catch(t){return!1}}(o,e.attestation,e.proof);return g({},e,{status:s?t.VERIFIED:t.FAILED})}(i);case e.ED25519:return async function(e){const[r,n,o]=e.address.split(/:/);if("solana"!==r)return g({},e,{status:t.FAILED});try{const r=u.decode(o),n=(new TextEncoder).encode(e.attestation),s=a.decode(e.proof);return g({},e,{status:p.sign.detached.verify(n,s,r)?t.VERIFIED:t.FAILED})}catch(r){return g({},e,{status:t.FAILED})}}(i);case e.EIP712:case e.BIP137:return async function(e){const[i,u,f]=e.address.split(/:/);if("bip122"!==i)return g({},e,{status:t.FAILED});try{const i=[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"))}(f)),u=function(t,e,i,u){const{compressed:f,segwitType:E,recovery:d,signature:h}=function(t){const e=a.decode(t);if(65!==e.length)throw new Error("Invalid signature length");const r=e[0]-27;if(r>15||r<0)throw new Error("Invalid signature parameter");return{compressed:!!(12&r),segwitType:8&r?4&r?I.P2WPKH:I.P2SH_P2WPKH:void 0,recovery:3&r,signature:e.slice(1)}}(i);if(u&&!f)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");const l=function(t){const e=(new TextEncoder).encode("Bitcoin Signed Message:\n"),r=(new TextEncoder).encode(t),n=c(r.length).buffer,o=new Uint8Array(e.length+n.byteLength+r.length);return o.set(e),o.set(new Uint8Array(n),e.length),o.set(r,e.length+n.byteLength),s(o)}(t),p=f?r.recoverPublicKeyCompressed(h,d,l):r.recoverPublicKeyUncompressed(h,d,l);if("string"==typeof p)throw new Error(p);const g=n(p);let y="";if(E)y=m(g);else if(u)try{y=m(g)}catch(t){y=m(g)}else y=o(0,g);return y===e}(e.attestation,f,e.proof,i);return g({},e,{status:u?t.VERIFIED:t.FAILED})}catch(r){return g({},e,{status:t.FAILED})}}(i)}return i}!function(t){t.P2WPKH="p2wpkh",t.P2SH_P2WPKH="p2sh(p2wpkh)"}(I||(I={})),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={}));export{w as verifyProof};
2
2
  //# sourceMappingURL=index.modern.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.modern.js","sources":["../src/bitcoin.ts","../src/index.ts","../src/eth.ts","../src/solana.ts"],"sourcesContent":["import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { bech32 } from \"bech32\";\n\nimport {\n secp256k1,\n hash160,\n hash256,\n RecoveryId,\n encodeBase58AddressFormat,\n} from \"@bitauth/libauth\";\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { decode as decodeBase64 } from \"@stablelib/base64\";\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 // 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 return { ...proof, status: 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 recovery: RecoveryId;\n signature: Uint8Array;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const signature = decodeBase64(proof);\n if (signature.length !== 65) throw new Error(\"Invalid signature length\");\n\n const flagByte = signature[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n\n return {\n compressed: !!(flagByte & 12),\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n recovery: (flagByte & 3) as RecoveryId,\n signature: signature.slice(1),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n) {\n const { compressed, segwitType, recovery, signature } =\n 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\n const hash = magicHash(attestation);\n const publicKey: Uint8Array | string = compressed\n ? secp256k1.recoverPublicKeyCompressed(signature, recovery, hash)\n : secp256k1.recoverPublicKeyUncompressed(signature, recovery, hash);\n if (typeof publicKey === \"string\") throw new Error(publicKey);\n const publicKeyHash = hash160(publicKey);\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\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","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\";\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.BIP137_XPUB:\n case ProofTypes.MicroTransfer:\n }\n return proof;\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\n\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.fromPublicKey(publicKey);\n return recovered.toString() === address.toString();\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 { decode as decodeBase64 } from \"@stablelib/base64\";\nimport bs58 from \"bs58\";\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 = bs58.decode(address);\n const messageBytes = new TextEncoder().encode(proof.attestation);\n const signatureBytes = decodeBase64(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","encodeBech32Address","publicKeyHash","bwords","bech32","toWords","unshift","encode","verifyProof","proof","type","ProofTypes","SelfDeclaration","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","ns","_","address","split","verified","message","payload","PersonalMessage","getSignPayload","Hex","fromString","signature","Signature","fromHex","publicKey","Secp256k1","recoverPublicKey","Address","fromPublicKey","toString","error","verifyEIP191","attestation","verifyPersonalSignEIP191","ED25519","bs58","decode","messageBytes","TextEncoder","signatureBytes","decodeBase64","nacl","sign","detached","verify","verifySolanaSignature","EIP712","BIP137","async","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","checkSegwitAlways","compressed","segwitType","recovery","length","flagByte","P2WPKH","P2SH_P2WPKH","undefined","slice","decodeSignature","hash","prefix","encodeLength","buffer","Uint8Array","byteLength","set","hash256","magicHash","secp256k1","recoverPublicKeyCompressed","recoverPublicKeyUncompressed","hash160","actual","e","encodeBase58AddressFormat","verifyBTCSignature"],"mappings":"+nBAaA,IAAKA,EAOAC,EA2IL,SAASC,EAAoBC,GAC3B,MAAMC,EAASC,EAAOC,QAAQH,GAE9B,OADAC,EAAOG,QAAQ,GACRF,EAAOG,OAAO,KAAMJ,EAC7B,gBCvJsBK,EACpBC,GAEA,OAAQA,EAAMC,MACZ,KAAKC,EAAWC,gBACd,OAAAC,EACKJ,CAAAA,EAAAA,EACHK,CAAAA,OAASL,EAA2BM,UAChCC,EAAYC,SACZD,EAAYE,SAEpB,KAAKP,EAAWQ,WACd,OAAAN,EACKJ,GAAAA,GACHK,OAASL,EAA0BW,IAC/BJ,EAAYK,QACZL,EAAYE,SAEpB,KAAKP,EAAWW,OACd,sBCVJb,GAEA,MAAOc,EAAIC,EAAGC,GAAWhB,EAAMgB,QAAQC,MAAM,KAC7C,GAAW,WAAPH,EAAiB,OAAAV,EAAYJ,CAAAA,EAAAA,GAAOK,OAAQE,EAAYE,SAE5D,MAAMS,WArBNF,EACAG,EACAnB,GAEA,IACE,MAAMoB,EAAUC,EAAgBC,eAAeC,EAAIC,WAAWL,IACxDM,EAAYC,EAAUC,QAAQ3B,GAC9B4B,EAAYC,EAAUC,iBAAiB,CAAEV,UAASK,cAExD,OADkBM,EAAQC,cAAcJ,GACvBK,aAAejB,EAAQiB,UAC1C,CAAE,MAAOC,GACP,OAAO,CACT,CACF,CAQmBC,CACfnB,EACAhB,EAAMoC,YACNpC,EAAMA,OAER,OAAAI,EAAA,GACKJ,EACHK,CAAAA,OAAQa,EAAWX,EAAYC,SAAWD,EAAYE,QAE1D,CDJa4B,CAAyBrC,GAClC,KAAKE,EAAWoC,QACd,sBE3BJtC,GAEA,MAAOc,EAAIC,EAAGC,GAAWhB,EAAMgB,QAAQC,MAAM,KAC7C,GAAW,WAAPH,EAAiB,OAAAV,EAAA,CAAA,EAAYJ,EAAK,CAAEK,OAAQE,EAAYE,SAC5D,IACE,MAAMmB,EAAYW,EAAKC,OAAOxB,GACxByB,GAAe,IAAIC,aAAc5C,OAAOE,EAAMoC,aAC9CO,EAAiBC,EAAa5C,EAAMA,OAO1C,OAAAI,EACKJ,CAAAA,EAAAA,EACHK,CAAAA,OARewC,EAAKC,KAAKC,SAASC,OAClCP,EACAE,EACAf,GAKmBrB,EAAYC,SAAWD,EAAYE,QAE1D,CAAE,MAAOyB,GACP,OAAA9B,EAAYJ,CAAAA,EAAAA,GAAOK,OAAQE,EAAYE,QACzC,CACF,CFMawC,CAAsBjD,GAC/B,KAAKE,EAAWgD,OAChB,KAAKhD,EAAWiD,OACd,ODLCC,eACLpD,GAEA,MAAOc,EAAIC,EAAGC,GAAWhB,EAAMgB,QAAQC,MAAM,KAC7C,GAAW,WAAPH,EAAiB,OAAAV,EAAYJ,CAAAA,EAAAA,EAAOK,CAAAA,OAAQE,EAAYE,SAC5D,IAEE,MAAM4C,EAAS,CAAC9D,EAAe+D,OAAQ/D,EAAegE,QAAQC,SAclE,SAA2BxC,GACzB,GAAIA,EAAQyC,MAAM,qBAChB,OAAOlE,EAAegE,OACjB,GAAIvC,EAAQyC,MAAM,YACvB,OAAOlE,EAAe+D,OACjB,GAAItC,EAAQyC,MAAM,aACvB,OAAOlE,EAAemE,OACjB,GAAI1C,EAAQyC,MAAM,UACvB,OAAOlE,EAAeoE,SAEtB,MAAU,IAAAC,MACR,oBACGC,OAAO7C,GACP6C,OAAO,0CAGhB,CA7BMC,CAAkB9C,IAEdE,EAyDV,SACEkB,EACApB,EACAhB,EACA+D,GAEA,MAAMC,WAAEA,EAAUC,WAAEA,EAAUC,SAAEA,EAAQzC,UAAEA,GA3B5C,SAAyBzB,GACvB,MAAMyB,EAAYmB,EAAa5C,GAC/B,GAAyB,KAArByB,EAAU0C,OAAe,MAAM,IAAIP,MAAM,4BAE7C,MAAMQ,EAAW3C,EAAU,GAAK,GAChC,GAAI2C,EAAW,IAAMA,EAAW,EAC9B,MAAM,IAAIR,MAAM,+BAGlB,MAAO,CACLI,cAA0B,GAAXI,GACfH,WAAyB,EAAXG,EAEG,EAAXA,EAEA9E,EAAa+E,OADb/E,EAAagF,iBAFfC,EAIJL,SAAsB,EAAXE,EACX3C,UAAWA,EAAU+C,MAAM,GAE/B,CASIC,CAAgBzE,GAClB,GAAI+D,IAAsBC,EACxB,MAAM,IAAIJ,MACR,kFAIJ,MAAMc,EAkCR,SAAmBtC,GACjB,MAAMuC,GAAS,IAAIjC,aAAc5C,OAjIb,8BAkIdqB,GAAU,IAAIuB,aAAc5C,OAAOsC,GACnC+B,EAASS,EAAazD,EAAQgD,QAAQU,OACtCA,EAAS,IAAIC,WACjBH,EAAOR,OAASA,EAAOY,WAAa5D,EAAQgD,QAK9C,OAHAU,EAAOG,IAAIL,GACXE,EAAOG,IAAI,IAAIF,WAAWX,GAASQ,EAAOR,QAC1CU,EAAOG,IAAI7D,EAASwD,EAAOR,OAASA,EAAOY,YACpCE,EAAQJ,EACjB,CA7CeK,CAAU9C,GACjBR,EAAiCoC,EACnCmB,EAAUC,2BAA2B3D,EAAWyC,EAAUQ,GAC1DS,EAAUE,6BAA6B5D,EAAWyC,EAAUQ,GAChE,GAAyB,iBAAd9C,EAAwB,UAAUgC,MAAMhC,GACnD,MAAMnC,EAAgB6F,EAAQ1D,GAC9B,IAAI2D,EAAiB,GAErB,GAAItB,EAEAsB,EAAS/F,EAAoBC,QAQ/B,GAAIsE,EACF,IACEwB,EAAS/F,EAAoBC,EAE/B,CAAE,MAAO+F,GACPD,EAAS/F,EAAoBC,EAE/B,MAEA8F,EAASE,EAA0B,EAAGhG,GAI1C,OAAO8F,IAAWvE,CACpB,CAvGqBgC,CAAOhD,EAAMoC,YAAapB,EAAShB,EAAMA,MAAOqD,GAEjE,OAAAjD,KACKJ,EAAK,CACRK,OAAQa,EAAWX,EAAYC,SAAWD,EAAYE,QAE1D,CAAE,MAAOyB,GACP,OAAA9B,KAAYJ,EAAK,CAAEK,OAAQE,EAAYE,QACzC,CACF,CCdaiF,CAAmB1F,GAI9B,OAAOA,CACT,ED5BA,SAAKV,GACHA,EAAA,OAAA,SACAA,EAAA,YAAA,cACD,CAHD,CAAKA,IAAAA,EAGJ,KAID,SAAKC,GACHA,EAAA,OAAA,SACAA,EAAA,OAAA,gBACAA,EAAA,OAAA,SACAA,EAAA,YAAA,OACAA,EAAA,IAAA,eACAA,EAAA,SAAA,WACAA,EAAA,SAAA,WACAA,EAAA,QAAA,SACD,CATD,CAAKA,IAAAA,EASJ"}
1
+ {"version":3,"file":"index.modern.js","sources":["../src/bitcoin.ts","../src/index.ts","../src/eth.ts","../src/solana.ts"],"sourcesContent":["import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\n\nimport {\n secp256k1,\n hash160,\n hash256,\n RecoveryId,\n encodeBase58AddressFormat,\n} from \"@bitauth/libauth\";\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { base64, bech32 } from \"@scure/base\";\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 // 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 return { ...proof, status: 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 recovery: RecoveryId;\n signature: Uint8Array;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const signature = base64.decode(proof);\n if (signature.length !== 65) throw new Error(\"Invalid signature length\");\n\n const flagByte = signature[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n\n return {\n compressed: !!(flagByte & 12),\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n recovery: (flagByte & 3) as RecoveryId,\n signature: signature.slice(1),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n) {\n const { compressed, segwitType, recovery, signature } =\n 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\n const hash = magicHash(attestation);\n const publicKey: Uint8Array | string = compressed\n ? secp256k1.recoverPublicKeyCompressed(signature, recovery, hash)\n : secp256k1.recoverPublicKeyUncompressed(signature, recovery, hash);\n if (typeof publicKey === \"string\") throw new Error(publicKey);\n const publicKeyHash = hash160(publicKey);\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\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","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\";\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.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","encodeBech32Address","publicKeyHash","bwords","bech32","toWords","unshift","encode","verifyProof","proof","type","ProofTypes","SelfDeclaration","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","async","ns","_","address","split","verified","message","payload","PersonalMessage","getSignPayload","Hex","fromString","signature","Signature","fromHex","publicKey","Secp256k1","recoverPublicKey","Address","checksum","fromPublicKey","toString","error","verifyEIP191","attestation","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","compressed","segwitType","recovery","length","flagByte","P2WPKH","P2SH_P2WPKH","undefined","slice","decodeSignature","hash","prefix","encodeLength","buffer","Uint8Array","byteLength","set","hash256","magicHash","secp256k1","recoverPublicKeyCompressed","recoverPublicKeyUncompressed","hash160","actual","e","encodeBase58AddressFormat","verifyBTCSignature"],"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("bech32"),require("@bitauth/libauth"),require("varuint-bitcoin"),require("@stablelib/base64"),require("ox"),require("tweetnacl"),require("bs58")):"function"==typeof define&&define.amd?define(["exports","@notabene/javascript-sdk","bech32","@bitauth/libauth","varuint-bitcoin","@stablelib/base64","ox","tweetnacl","bs58"],r):r((e||self).verifyProof={},e.javascriptSdk,e.bech32,e.libauth,e.varuintBitcoin,e.base64,e.ox,e.tweetnacl,e.bs58)}(this,function(e,r,t,o,s,n,a,i,u){function c(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var f,l,d=/*#__PURE__*/c(i),P=/*#__PURE__*/c(u);function h(){return h=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},h.apply(null,arguments)}function p(e){var r=t.bech32.toWords(e);return r.unshift(0),t.bech32.encode("bc",r)}!function(e){e.P2WPKH="p2wpkh",e.P2SH_P2WPKH="p2sh(p2wpkh)"}(f||(f={})),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"}(l||(l={})),e.verifyProof=function(e){try{switch(e.type){case r.ProofTypes.SelfDeclaration:return Promise.resolve(h({},e,{status:e.confirmed?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}));case r.ProofTypes.Screenshot:return Promise.resolve(h({},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(h({},e,{status:r.ProofStatus.FAILED}));var s=function(e,r,t){try{var o=a.PersonalMessage.getSignPayload(a.Hex.fromString(r)),s=a.Signature.fromHex(t),n=a.Secp256k1.recoverPublicKey({payload:o,signature:s});return a.Address.fromPublicKey(n).toString()===e.toString()}catch(e){return!1}}(o,e.attestation,e.proof);return Promise.resolve(h({},e,{status:s?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(/:/),o=t[2];if("solana"!==t[0])return Promise.resolve(h({},e,{status:r.ProofStatus.FAILED}));try{var s=P.default.decode(o),a=(new TextEncoder).encode(e.attestation),i=n.decode(e.proof),u=d.default.sign.detached.verify(a,i,s);return Promise.resolve(h({},e,{status:u?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}))}catch(t){return Promise.resolve(h({},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 t=e.address.split(/:/),a=t[2];if("bip122"!==t[0])return Promise.resolve(h({},e,{status:r.ProofStatus.FAILED}));try{var i=[l.SEGWIT,l.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return l.NATIVE;if(e.match("^[32M].*"))return l.SEGWIT;if(e.match("^[1nmL].*"))return l.LEGACY;if(e.match("^(D).*"))return l.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(a)),u=function(e,r,t,a){var i=function(e){var r=n.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");return{compressed:!!(12&t),segwitType:8&t?4&t?f.P2WPKH:f.P2SH_P2WPKH:void 0,recovery:3&t,signature:r.slice(1)}}(t),u=i.compressed,c=i.segwitType,l=i.recovery,d=i.signature;if(a&&!u)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var P=function(e){var r=(new TextEncoder).encode("Bitcoin Signed Message:\n"),t=(new TextEncoder).encode(e),n=s.encode(t.length).buffer,a=new Uint8Array(r.length+n.byteLength+t.length);return a.set(r),a.set(new Uint8Array(n),r.length),a.set(t,r.length+n.byteLength),o.hash256(a)}(e),h=u?o.secp256k1.recoverPublicKeyCompressed(d,l,P):o.secp256k1.recoverPublicKeyUncompressed(d,l,P);if("string"==typeof h)throw new Error(h);var v=o.hash160(h),E="";if(c)E=p(v);else if(a)try{E=p(v)}catch(e){E=p(v)}else E=o.encodeBase58AddressFormat(0,v);return E===r}(e.attestation,a,e.proof,i);return Promise.resolve(h({},e,{status:u?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}))}catch(t){return Promise.resolve(h({},e,{status: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("@bitauth/libauth"),require("varuint-bitcoin"),require("@scure/base"),require("ox"),require("tweetnacl")):"function"==typeof define&&define.amd?define(["exports","@notabene/javascript-sdk","@bitauth/libauth","varuint-bitcoin","@scure/base","ox","tweetnacl"],r):r((e||self).verifyProof={},e.javascriptSdk,e.libauth,e.varuintBitcoin,e.base,e.ox,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 d(e){var r=s.bech32.toWords(e);return r.unshift(0),s.bech32.encode("bc",r)}!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={})),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 s=function(e,r,t){try{var o=n.PersonalMessage.getSignPayload(n.Hex.fromString(r)),s=n.Signature.fromHex(t),a=n.Secp256k1.recoverPublicKey({payload:o,signature:s});return n.Address.checksum(n.Address.fromPublicKey(a)).toString()===n.Address.checksum(e)}catch(e){return!1}}(o,e.attestation,e.proof);return Promise.resolve(l({},e,{status:s?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(/:/),o=t[2];if("solana"!==t[0])return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}));try{var n=s.base58.decode(o),a=(new TextEncoder).encode(e.attestation),i=s.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 n=e.address.split(/:/),a=n[2];if("bip122"!==n[0])return Promise.resolve(l({},e,{status:r.ProofStatus.FAILED}));try{var i=[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"))}(a)),f=function(e,r,n,a){var i=function(e){var r=s.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");return{compressed:!!(12&t),segwitType:8&t?4&t?c.P2WPKH:c.P2SH_P2WPKH:void 0,recovery:3&t,signature:r.slice(1)}}(n),u=i.compressed,f=i.segwitType,l=i.recovery,P=i.signature;if(a&&!u)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var h=function(e){var r=(new TextEncoder).encode("Bitcoin Signed Message:\n"),s=(new TextEncoder).encode(e),n=o.encode(s.length).buffer,a=new Uint8Array(r.length+n.byteLength+s.length);return a.set(r),a.set(new Uint8Array(n),r.length),a.set(s,r.length+n.byteLength),t.hash256(a)}(e),p=u?t.secp256k1.recoverPublicKeyCompressed(P,l,h):t.secp256k1.recoverPublicKeyUncompressed(P,l,h);if("string"==typeof p)throw new Error(p);var v=t.hash160(p),E="";if(f)E=d(v);else if(a)try{E=d(v)}catch(e){E=d(v)}else E=t.encodeBase58AddressFormat(0,v);return E===r}(e.attestation,a,e.proof,i);return Promise.resolve(l({},e,{status:f?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}))}catch(t){return Promise.resolve(l({},e,{status: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"],"sourcesContent":["import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { bech32 } from \"bech32\";\n\nimport {\n secp256k1,\n hash160,\n hash256,\n RecoveryId,\n encodeBase58AddressFormat,\n} from \"@bitauth/libauth\";\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { decode as decodeBase64 } from \"@stablelib/base64\";\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 // 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 return { ...proof, status: 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 recovery: RecoveryId;\n signature: Uint8Array;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const signature = decodeBase64(proof);\n if (signature.length !== 65) throw new Error(\"Invalid signature length\");\n\n const flagByte = signature[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n\n return {\n compressed: !!(flagByte & 12),\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n recovery: (flagByte & 3) as RecoveryId,\n signature: signature.slice(1),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n) {\n const { compressed, segwitType, recovery, signature } =\n 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\n const hash = magicHash(attestation);\n const publicKey: Uint8Array | string = compressed\n ? secp256k1.recoverPublicKeyCompressed(signature, recovery, hash)\n : secp256k1.recoverPublicKeyUncompressed(signature, recovery, hash);\n if (typeof publicKey === \"string\") throw new Error(publicKey);\n const publicKeyHash = hash160(publicKey);\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\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","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\";\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.BIP137_XPUB:\n case ProofTypes.MicroTransfer:\n }\n return proof;\n}\n","import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\n\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.fromPublicKey(publicKey);\n return recovered.toString() === address.toString();\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 { decode as decodeBase64 } from \"@stablelib/base64\";\nimport bs58 from \"bs58\";\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 = bs58.decode(address);\n const messageBytes = new TextEncoder().encode(proof.attestation);\n const signatureBytes = decodeBase64(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","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","fromPublicKey","toString","error","verifyEIP191","attestation","e","reject","verifyPersonalSignEIP191","ED25519","bs58","decode","messageBytes","TextEncoder","signatureBytes","decodeBase64","nacl","sign","detached","verify","verifySolanaSignature","EIP712","BIP137","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","checkSegwitAlways","_decodeSignature","length","flagByte","compressed","segwitType","P2WPKH","P2SH_P2WPKH","undefined","recovery","slice","decodeSignature","hash","prefix","encodeLength","buffer","Uint8Array","byteLength","set","hash256","magicHash","secp256k1","recoverPublicKeyCompressed","recoverPublicKeyUncompressed","hash160","actual","encodeBase58AddressFormat","verifyBTCSignature"],"mappings":"wsBAaKA,EAOAC,kQA2IL,SAASC,EAAoBC,GAC3B,IAAMC,EAASC,EAAAA,OAAOC,QAAQH,GAE9B,OADAC,EAAOG,QAAQ,GACRF,EAAMA,OAACG,OAAO,KAAMJ,EAC7B,EAtJA,SAAKJ,GACHA,EAAA,OAAA,SACAA,EAAA,YAAA,cACD,CAHD,CAAKA,IAAAA,EAGJ,CAAA,IAID,SAAKC,GACHA,EAAA,OAAA,SACAA,EAAA,OAAA,gBACAA,EAAA,OAAA,SACAA,EAAA,YAAA,OACAA,EAAA,IAAA,eACAA,EAAA,SAAA,WACAA,EAAA,SAAA,WACAA,EAAA,QAAA,SACD,CATD,CAAKA,IAAAA,EASJ,CAAA,kBCjBgC,SAC/BQ,GAAqB,IAErB,OAAQA,EAAMC,MACZ,KAAKC,aAAWC,gBACd,OAAAC,QAAAC,QAAAC,KACKN,EAAK,CACRO,OAASP,EAA2BQ,UAChCC,EAAWA,YAACC,SACZD,cAAYE,UAEpB,KAAKT,EAAUA,WAACU,WACd,OAAAR,QAAAC,QAAAC,EACKN,CAAAA,EAAAA,GACHO,OAASP,EAA0Ba,IAC/BJ,EAAWA,YAACK,QACZL,EAAAA,YAAYE,UAEpB,KAAKT,EAAAA,WAAWa,OACd,OAAAX,QAAAC,QCXgB,SACpBL,GAAqB,IAErB,IAAAgB,EAAyBhB,EAAMiB,QAAQC,MAAM,KAA/BD,EAAOD,EAAA,GACrB,GAAW,WADFA,EAAEG,GACU,OAAAf,QAAAC,QAAAC,EAAYN,CAAAA,EAAAA,GAAOO,OAAQE,EAAWA,YAACE,UAE5D,IAAMS,WArBNH,EACAI,EACArB,GAEA,IACE,IAAMsB,EAAUC,EAAeA,gBAACC,eAAeC,EAAAA,IAAIC,WAAWL,IACxDM,EAAYC,EAAAA,UAAUC,QAAQ7B,GAC9B8B,EAAYC,EAASA,UAACC,iBAAiB,CAAEV,QAAAA,EAASK,UAAAA,IAExD,OADkBM,EAAOA,QAACC,cAAcJ,GACvBK,aAAelB,EAAQkB,UAC1C,CAAE,MAAOC,GACP,OAAO,CACT,CACF,CAQmBC,CACfpB,EACAjB,EAAMsC,YACNtC,EAAMA,OAER,OAAAI,QAAAC,QAAAC,EACKN,CAAAA,EAAAA,EACHO,CAAAA,OAAQa,EAAWX,EAAAA,YAAYC,SAAWD,EAAWA,YAACE,SAE1D,CAAC,MAAA4B,GAAAnC,OAAAA,QAAAoC,OAAAD,IDJYE,CAAyBzC,IAClC,KAAKE,EAAAA,WAAWwC,QACd,OAAAtC,QAAAC,QE5BqC,SACzCL,GAAqB,IAErB,IAAAgB,EAAyBhB,EAAMiB,QAAQC,MAAM,KAA/BD,EAAOD,EAAA,GACrB,GAAW,WADFA,KACY,OAAAZ,QAAAC,QAAAC,EAAA,GAAYN,EAAOO,CAAAA,OAAQE,EAAWA,YAACE,UAC5D,IACE,IAAMmB,EAAYa,EAAI,QAACC,OAAO3B,GACxB4B,GAAe,IAAIC,aAAc/C,OAAOC,EAAMsC,aAC9CS,EAAiBC,EAAYJ,OAAC5C,EAAMA,OACpCoB,EAAW6B,EAAAA,QAAKC,KAAKC,SAASC,OAClCP,EACAE,EACAjB,GAGF,OAAA1B,QAAAC,QAAAC,EAAA,GACKN,EACHO,CAAAA,OAAQa,EAAWX,cAAYC,SAAWD,EAAWA,YAACE,SAE1D,CAAE,MAAOyB,GACP,OAAAhC,QAAAC,QAAAC,EAAYN,CAAAA,EAAAA,GAAOO,OAAQE,EAAAA,YAAYE,SACzC,CACF,CAAC,MAAA4B,GAAA,OAAAnC,QAAAoC,OAAAD,EAAA,CAAA,CFMYc,CAAsBrD,IAC/B,KAAKE,aAAWoD,OAChB,KAAKpD,EAAAA,WAAWqD,OACd,OAAAnD,QAAAC,QDLkC,SACtCL,OAEA,IAAAgB,EAAyBhB,EAAMiB,QAAQC,MAAM,KAA/BD,EAAOD,EACrB,GAAA,GAAW,WADFA,EAAA,GACY,OAAAZ,QAAAC,QAAAC,KAAYN,EAAK,CAAEO,OAAQE,EAAAA,YAAYE,UAC5D,IAEE,IAAM6C,EAAS,CAAChE,EAAeiE,OAAQjE,EAAekE,QAAQC,SAclE,SAA2B1C,GACzB,GAAIA,EAAQ2C,MAAM,qBAChB,OAAOpE,EAAekE,UACbzC,EAAQ2C,MAAM,YACvB,OAAOpE,EAAeiE,UACbxC,EAAQ2C,MAAM,aACvB,OAAOpE,EAAeqE,OACb5C,GAAAA,EAAQ2C,MAAM,UACvB,OAAOpE,EAAesE,SAEtB,UAAUC,MACR,oBACGC,OAAO/C,GACP+C,OAAO,0CAGhB,CA7BMC,CAAkBhD,IAEdG,EAyDV,SACEkB,EACArB,EACAjB,EACAkE,GAEA,IAAAC,EA3BF,SAAyBnE,GACvB,IAAM2B,EAAYqB,EAAYJ,OAAC5C,GAC/B,GAAyB,KAArB2B,EAAUyC,OAAe,MAAM,IAAIL,MAAM,4BAE7C,IAAMM,EAAW1C,EAAU,GAAK,GAChC,GAAI0C,EAAW,IAAMA,EAAW,EAC9B,MAAU,IAAAN,MAAM,+BAGlB,MAAO,CACLO,cAA0B,GAAXD,GACfE,WAAyB,EAAXF,EAEG,EAAXA,EAEA9E,EAAaiF,OADbjF,EAAakF,iBAFfC,EAIJC,SAAsB,EAAXN,EACX1C,UAAWA,EAAUiD,MAAM,GAE/B,CASIC,CAAgB7E,GADVsE,EAAUH,EAAVG,WAAYC,EAAUJ,EAAVI,WAAYI,EAAQR,EAARQ,SAAUhD,EAASwC,EAATxC,UAE1C,GAAIuC,IAAsBI,EACxB,MAAM,IAAIP,MACR,kFAIJ,IAAMe,EAkCR,SAAmBxC,GACjB,IAAMyC,GAAS,IAAIjC,aAAc/C,OAjIb,8BAkIdsB,GAAU,IAAIyB,aAAc/C,OAAOuC,GACnC8B,EAASY,EAAAA,OAAa3D,EAAQ+C,QAAQa,OACtCA,EAAS,IAAIC,WACjBH,EAAOX,OAASA,EAAOe,WAAa9D,EAAQ+C,QAK9C,OAHAa,EAAOG,IAAIL,GACXE,EAAOG,IAAI,IAAIF,WAAWd,GAASW,EAAOX,QAC1Ca,EAAOG,IAAI/D,EAAS0D,EAAOX,OAASA,EAAOe,YACpCE,EAAOA,QAACJ,EACjB,CA7CeK,CAAUhD,GACjBR,EAAiCwC,EACnCiB,EAAAA,UAAUC,2BAA2B7D,EAAWgD,EAAUG,GAC1DS,YAAUE,6BAA6B9D,EAAWgD,EAAUG,GAChE,GAAyB,iBAAdhD,EAAwB,UAAUiC,MAAMjC,GACnD,IAAMpC,EAAgBgG,EAAAA,QAAQ5D,GAC1B6D,EAAiB,GAErB,GAAIpB,EAEAoB,EAASlG,EAAoBC,QAQ/B,GAAIwE,EACF,IACEyB,EAASlG,EAAoBC,EAE/B,CAAE,MAAO6C,GACPoD,EAASlG,EAAoBC,EAE/B,MAEAiG,EAASC,EAAAA,0BAA0B,EAAGlG,GAI1C,OAAOiG,IAAW1E,CACpB,CAvGqBmC,CAAOpD,EAAMsC,YAAarB,EAASjB,EAAMA,MAAOwD,GAEjE,OAAApD,QAAAC,QAAAC,EAAA,GACKN,EAAK,CACRO,OAAQa,EAAWX,EAAAA,YAAYC,SAAWD,cAAYE,SAE1D,CAAE,MAAOyB,GACP,OAAAhC,QAAAC,QAAAC,EAAYN,CAAAA,EAAAA,EAAOO,CAAAA,OAAQE,cAAYE,SACzC,CACF,CAAC,MAAA4B,UAAAnC,QAAAoC,OAAAD,EAAA,CAAA,CCdYsD,CAAmB7F,IAI9B,OAAAI,QAAAC,QAAOL,EACT,CAAC,MAAAuC,GAAA,OAAAnC,QAAAoC,OAAAD,EAAA,CAAA"}
1
+ {"version":3,"file":"index.umd.js","sources":["../src/bitcoin.ts","../src/index.ts","../src/eth.ts","../src/solana.ts"],"sourcesContent":["import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\n\nimport {\n secp256k1,\n hash160,\n hash256,\n RecoveryId,\n encodeBase58AddressFormat,\n} from \"@bitauth/libauth\";\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { base64, bech32 } from \"@scure/base\";\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 // 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 return { ...proof, status: 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 recovery: RecoveryId;\n signature: Uint8Array;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const signature = base64.decode(proof);\n if (signature.length !== 65) throw new Error(\"Invalid signature length\");\n\n const flagByte = signature[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n\n return {\n compressed: !!(flagByte & 12),\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n recovery: (flagByte & 3) as RecoveryId,\n signature: signature.slice(1),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n) {\n const { compressed, segwitType, recovery, signature } =\n 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\n const hash = magicHash(attestation);\n const publicKey: Uint8Array | string = compressed\n ? secp256k1.recoverPublicKeyCompressed(signature, recovery, hash)\n : secp256k1.recoverPublicKeyUncompressed(signature, recovery, hash);\n if (typeof publicKey === \"string\") throw new Error(publicKey);\n const publicKeyHash = hash160(publicKey);\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\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","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\";\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.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","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","length","flagByte","compressed","segwitType","P2WPKH","P2SH_P2WPKH","undefined","recovery","slice","decodeSignature","hash","prefix","encodeLength","buffer","Uint8Array","byteLength","set","hash256","magicHash","secp256k1","recoverPublicKeyCompressed","recoverPublicKeyUncompressed","hash160","actual","encodeBase58AddressFormat","verifyBTCSignature"],"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.1",
3
+ "version": "1.0.3",
4
4
  "description": "Verify ownership proofs",
5
5
  "source": "src/index.ts",
6
6
  "type": "module",
@@ -32,9 +32,7 @@
32
32
  "dependencies": {
33
33
  "@bitauth/libauth": "^3.0.0",
34
34
  "@notabene/javascript-sdk": "^2.0.2",
35
- "@stablelib/base64": "^2.0.0",
36
- "bech32": "^2.0.0",
37
- "bs58": "^6.0.0",
35
+ "@scure/base": "^1.2.1",
38
36
  "ox": "^0.2.2",
39
37
  "tweetnacl": "^1.0.3",
40
38
  "varuint-bitcoin": "^2.0.0"
package/src/bitcoin.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { ProofStatus, SignatureProof } from "@notabene/javascript-sdk";
2
- import { bech32 } from "bech32";
3
2
 
4
3
  import {
5
4
  secp256k1,
@@ -9,7 +8,7 @@ import {
9
8
  encodeBase58AddressFormat,
10
9
  } from "@bitauth/libauth";
11
10
  import { encode as encodeLength } from "varuint-bitcoin";
12
- import { decode as decodeBase64 } from "@stablelib/base64";
11
+ import { base64, bech32 } from "@scure/base";
13
12
 
14
13
  enum SEGWIT_TYPES {
15
14
  P2WPKH = "p2wpkh",
@@ -76,7 +75,7 @@ type DecodedSignature = {
76
75
  };
77
76
 
78
77
  function decodeSignature(proof: string): DecodedSignature {
79
- const signature = decodeBase64(proof);
78
+ const signature = base64.decode(proof);
80
79
  if (signature.length !== 65) throw new Error("Invalid signature length");
81
80
 
82
81
  const flagByte = signature[0] - 27;
package/src/eth.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { ProofStatus, SignatureProof } from "@notabene/javascript-sdk";
2
-
3
2
  import { Secp256k1, Hex, PersonalMessage, Signature, Address } from "ox";
4
3
 
5
4
  export function verifyEIP191(
@@ -11,8 +10,8 @@ export function verifyEIP191(
11
10
  const payload = PersonalMessage.getSignPayload(Hex.fromString(message));
12
11
  const signature = Signature.fromHex(proof);
13
12
  const publicKey = Secp256k1.recoverPublicKey({ payload, signature });
14
- const recovered = Address.fromPublicKey(publicKey);
15
- return recovered.toString() === address.toString();
13
+ const recovered = Address.checksum(Address.fromPublicKey(publicKey));
14
+ return recovered.toString() === Address.checksum(address);
16
15
  } catch (error) {
17
16
  return false;
18
17
  }
package/src/solana.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import nacl from "tweetnacl";
2
2
  import { ProofStatus, SignatureProof } from "@notabene/javascript-sdk";
3
- import { decode as decodeBase64 } from "@stablelib/base64";
4
- import bs58 from "bs58";
3
+ import { base64, base58 } from "@scure/base";
5
4
 
6
5
  export async function verifySolanaSignature(
7
6
  proof: SignatureProof,
@@ -9,9 +8,9 @@ export async function verifySolanaSignature(
9
8
  const [ns, _, address] = proof.address.split(/:/);
10
9
  if (ns !== "solana") return { ...proof, status: ProofStatus.FAILED };
11
10
  try {
12
- const publicKey = bs58.decode(address);
11
+ const publicKey = base58.decode(address);
13
12
  const messageBytes = new TextEncoder().encode(proof.attestation);
14
- const signatureBytes = decodeBase64(proof.proof);
13
+ const signatureBytes = base64.decode(proof.proof);
15
14
  const verified = nacl.sign.detached.verify(
16
15
  messageBytes,
17
16
  signatureBytes,
@@ -2,6 +2,7 @@ import { describe, it, expect } from "vitest";
2
2
  import { verifyPersonalSignEIP191 } from "../eth";
3
3
  import {
4
4
  type SignatureProof,
5
+ CAIP10,
5
6
  ProofStatus,
6
7
  ProofTypes,
7
8
  } from "@notabene/javascript-sdk";
@@ -9,7 +10,9 @@ import {
9
10
  import { Hex, Address, PersonalMessage, Secp256k1, Signature } from "ox";
10
11
 
11
12
  const privateKey = Secp256k1.randomPrivateKey();
12
- const address = Address.fromPublicKey(Secp256k1.getPublicKey({ privateKey }));
13
+ const address = Address.checksum(
14
+ Address.fromPublicKey(Secp256k1.getPublicKey({ privateKey })),
15
+ );
13
16
 
14
17
  function personalSign(): SignatureProof {
15
18
  const attestation = "I agree";
@@ -34,6 +37,17 @@ describe("verifyPersonalSignEIP191", () => {
34
37
  expect(result.status).toBe(ProofStatus.VERIFIED);
35
38
  });
36
39
 
40
+ it("returns verified proof even when address is not the correct case", async () => {
41
+ const proof = personalSign();
42
+ console.log(proof.address);
43
+ const result = await verifyPersonalSignEIP191({
44
+ ...proof,
45
+ address: proof.address.toLowerCase() as CAIP10,
46
+ });
47
+
48
+ expect(result.status).toBe(ProofStatus.VERIFIED);
49
+ });
50
+
37
51
  it("returns failed proof when invalid message or address", async () => {
38
52
  const proof = { ...personalSign(), attestation: "evil text" };
39
53
  const result = await verifyPersonalSignEIP191(proof);
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from "vitest";
2
- import bs58 from "bs58";
2
+ import { base58 } from "@scure/base";
3
3
  import nacl from "tweetnacl";
4
4
  import {
5
5
  ProofStatus,
@@ -10,7 +10,7 @@ import { verifySolanaSignature } from "../solana";
10
10
 
11
11
  describe("verifySolanaSignature", () => {
12
12
  const keypair = nacl.sign.keyPair();
13
- const address = bs58.encode(keypair.publicKey);
13
+ const address = base58.encode(keypair.publicKey);
14
14
  it("verifies valid Solana signature", async () => {
15
15
  // Generate a test keypair
16
16
  const message = "Test message";
@@ -1 +0,0 @@
1
- export {};