@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 +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +1 -1
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/package.json +2 -4
- package/src/bitcoin.ts +2 -3
- package/src/eth.ts +2 -3
- package/src/solana.ts +3 -4
- package/src/tests/eth.test.ts +15 -1
- package/src/tests/solana.test.ts +2 -2
- package/dist/index.test.d.ts +0 -1
package/dist/index.cjs
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
var e=require("@notabene/javascript-sdk"),r=require("
|
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
|
package/dist/index.cjs.map
CHANGED
@@ -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":"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"}
|
package/dist/index.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
import{ProofStatus as e,ProofTypes as r}from"@notabene/javascript-sdk";import{
|
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":"imBAYKA,EAOAC,EA2IL,SAASC,EAAoBC,GAC3B,IAAMC,EAASC,EAAOC,QAAQH,GAE9B,OADAC,EAAOG,QAAQ,GACRF,EAAOG,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,ICTD,ICPsBQ,EAAW,SAC/BC,GAAqB,IAErB,OAAQA,EAAMC,MACZ,KAAKC,EAAWC,gBACd,OAAAC,QAAAC,QAAAC,KACKN,EAAK,CACRO,OAASP,EAA2BQ,UAChCC,EAAYC,SACZD,EAAYE,UAEpB,KAAKT,EAAWU,WACd,OAAAR,QAAAC,QAAAC,EACKN,CAAAA,EAAAA,GACHO,OAASP,EAA0Ba,IAC/BJ,EAAYK,QACZL,EAAYE,UAEpB,KAAKT,EAAWa,OACd,OAAAX,QAAAC,QDZwC,SAC5CL,OAEA,IAAAgB,EAAyBhB,EAAMiB,QAAQC,MAAM,KAA/BD,EAAOD,EAAA,GACrB,GAAW,WADFA,EAAEG,GACU,OAAAf,QAAAC,QAAAC,EAAYN,GAAAA,EAAOO,CAAAA,OAAQE,EAAYE,UAE5D,IAAMS,WArBNH,EACAI,EACArB,GAEA,IACE,IAAMsB,EAAUC,EAAgBC,eAAeC,EAAIC,WAAWL,IACxDM,EAAYC,EAAUC,QAAQ7B,GAC9B8B,EAAYC,EAAUC,iBAAiB,CAAEV,QAAAA,EAASK,UAAAA,IAExD,OADkBM,EAAQC,SAASD,EAAQE,cAAcL,IACxCM,aAAeH,EAAQC,SAASjB,EACnD,CAAE,MAAOoB,GACP,OAAO,CACT,CACF,CAQmBC,CACfrB,EACAjB,EAAMuC,YACNvC,EAAMA,OAER,OAAAI,QAAAC,QAAAC,KACKN,EAAK,CACRO,OAAQa,EAAWX,EAAYC,SAAWD,EAAYE,SAE1D,CAAC,MAAA6B,GAAApC,OAAAA,QAAAqC,OAAAD,EAAA,CAAA,CCHYE,CAAyB1C,IAClC,KAAKE,EAAWyC,QACd,OAAAvC,QAAAC,QC7BqC,SACzCL,GAAqB,IAErB,IAAAgB,EAAyBhB,EAAMiB,QAAQC,MAAM,KAA/BD,EAAOD,EACrB,GAAA,GAAW,WADFA,EAAEG,GACU,OAAAf,QAAAC,QAAAC,EAAYN,GAAAA,GAAOO,OAAQE,EAAYE,UAC5D,IACE,IAAMmB,EAAYc,EAAOC,OAAO5B,GAC1B6B,GAAe,IAAIC,aAAcjD,OAAOE,EAAMuC,aAC9CS,EAAiBC,EAAOJ,OAAO7C,EAAMA,OACrCoB,EAAW8B,EAAKC,KAAKC,SAASC,OAClCP,EACAE,EACAlB,GAGF,OAAA1B,QAAAC,QAAAC,EAAA,CAAA,EACKN,EACHO,CAAAA,OAAQa,EAAWX,EAAYC,SAAWD,EAAYE,SAE1D,CAAE,MAAO0B,GACP,OAAAjC,QAAAC,QAAAC,EAAYN,CAAAA,EAAAA,GAAOO,OAAQE,EAAYE,SACzC,CACF,CAAC,MAAA6B,GAAA,OAAApC,QAAAqC,OAAAD,EAAA,CAAA,CDOYc,CAAsBtD,IAC/B,KAAKE,EAAWqD,OAChB,KAAKrD,EAAWsD,OACd,OAAApD,QAAAC,QFNgB,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,EAAYE,UAC5D,IAEE,IAAM8C,EAAS,CAAClE,EAAemE,OAAQnE,EAAeoE,QAAQC,SAclE,SAA2B3C,GACzB,GAAIA,EAAQ4C,MAAM,qBAChB,OAAOtE,EAAeoE,OACjB,GAAI1C,EAAQ4C,MAAM,YACvB,OAAOtE,EAAemE,OACjB,GAAIzC,EAAQ4C,MAAM,aACvB,OAAOtE,EAAeuE,OACjB,GAAI7C,EAAQ4C,MAAM,UACvB,OAAOtE,EAAewE,SAEtB,MAAU,IAAAC,MACR,oBACGC,OAAOhD,GACPgD,OAAO,0CAGhB,CA7BMC,CAAkBjD,IAEdG,EAyDV,SACEmB,EACAtB,EACAjB,EACAmE,GAEA,IAAAC,EA3BF,SAAyBpE,GACvB,IAAM2B,EAAYsB,EAAOJ,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,EAEAhF,EAAamF,OADbnF,EAAaoF,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,aAAcjD,OAjIb,8BAkIduB,GAAU,IAAI0B,aAAcjD,OAAOyC,GACnC8B,EAASY,EAAa5D,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,EAAQJ,EACjB,CA7CeK,CAAUhD,GACjBT,EAAiCyC,EACnCiB,EAAUC,2BAA2B9D,EAAWiD,EAAUG,GAC1DS,EAAUE,6BAA6B/D,EAAWiD,EAAUG,GAChE,GAAyB,iBAAdjD,EAAwB,MAAM,IAAIkC,MAAMlC,GACnD,IAAMrC,EAAgBkG,EAAQ7D,GAC1B8D,EAAiB,GAErB,GAAIpB,EAEAoB,EAASpG,EAAoBC,QAQ/B,GAAI0E,EACF,IACEyB,EAASpG,EAAoBC,EAE/B,CAAE,MAAO+C,GACPoD,EAASpG,EAAoBC,EAE/B,MAEAmG,EAASC,EAA0B,EAAGpG,GAI1C,OAAOmG,IAAW3E,CACpB,CAvGqBoC,CAAOrD,EAAMuC,YAAatB,EAASjB,EAAMA,MAAOyD,GAEjE,OAAArD,QAAAC,QAAAC,KACKN,EAAK,CACRO,OAAQa,EAAWX,EAAYC,SAAWD,EAAYE,SAE1D,CAAE,MAAO0B,GACP,OAAAjC,QAAAC,QAAAC,EAAA,CAAA,EAAYN,EAAOO,CAAAA,OAAQE,EAAYE,SACzC,CACF,CAAC,MAAA6B,GAAA,OAAApC,QAAAqC,OAAAD,EArCD,CAAA,CEwBasD,CAAmB9F,IAI9B,OAAAI,QAAAC,QAAOL,EACT,CAAC,MAAAwC,GAAA,OAAApC,QAAAqC,OAAAD,EAAA,CAAA"}
|
package/dist/index.modern.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
import{ProofStatus as t,ProofTypes as e}from"@notabene/javascript-sdk";import{
|
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
|
package/dist/index.modern.js.map
CHANGED
@@ -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":"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"}
|
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":"6lBAYA,IAAKA,EAOAC,EA2IL,SAASC,EAAoBC,GAC3B,MAAMC,EAASC,EAAOC,QAAQH,GAE9B,OADAC,EAAOG,QAAQ,GACRF,EAAOG,OAAO,KAAMJ,EAC7B,gBCtJsBK,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,OCZCC,eACLd,GAEA,MAAOe,EAAIC,EAAGC,GAAWjB,EAAMiB,QAAQC,MAAM,KAC7C,GAAW,WAAPH,EAAiB,OAAAX,EAAYJ,CAAAA,EAAAA,GAAOK,OAAQE,EAAYE,SAE5D,MAAMU,WArBNF,EACAG,EACApB,GAEA,IACE,MAAMqB,EAAUC,EAAgBC,eAAeC,EAAIC,WAAWL,IACxDM,EAAYC,EAAUC,QAAQ5B,GAC9B6B,EAAYC,EAAUC,iBAAiB,CAAEV,UAASK,cAExD,OADkBM,EAAQC,SAASD,EAAQE,cAAcL,IACxCM,aAAeH,EAAQC,SAAShB,EACnD,CAAE,MAAOmB,GACP,OACF,CAAA,CACF,CAQmBC,CACfpB,EACAjB,EAAMsC,YACNtC,EAAMA,OAER,OAAAI,EAAA,CAAA,EACKJ,EACHK,CAAAA,OAAQc,EAAWZ,EAAYC,SAAWD,EAAYE,QAE1D,CDHa8B,CAAyBvC,GAClC,KAAKE,EAAWsC,QACd,OE7BC1B,eACLd,GAEA,MAAOe,EAAIC,EAAGC,GAAWjB,EAAMiB,QAAQC,MAAM,KAC7C,GAAW,WAAPH,EAAiB,OAAAX,EAAYJ,GAAAA,EAAOK,CAAAA,OAAQE,EAAYE,SAC5D,IACE,MAAMoB,EAAYY,EAAOC,OAAOzB,GAC1B0B,GAAe,IAAIC,aAAc9C,OAAOE,EAAMsC,aAC9CO,EAAiBC,EAAOJ,OAAO1C,EAAMA,OAO3C,OAAAI,KACKJ,EAAK,CACRK,OARe0C,EAAKC,KAAKC,SAASC,OAClCP,EACAE,EACAhB,GAKmBtB,EAAYC,SAAWD,EAAYE,QAE1D,CAAE,MAAO2B,GACP,OAAAhC,EAAA,CAAA,EAAYJ,EAAK,CAAEK,OAAQE,EAAYE,QACzC,CACF,CFOa0C,CAAsBnD,GAC/B,KAAKE,EAAWkD,OAChB,KAAKlD,EAAWmD,OACd,ODNCvC,eACLd,GAEA,MAAOe,EAAIC,EAAGC,GAAWjB,EAAMiB,QAAQC,MAAM,KAC7C,GAAW,WAAPH,EAAiB,OAAAX,EAAYJ,CAAAA,EAAAA,GAAOK,OAAQE,EAAYE,SAC5D,IAEE,MAAM6C,EAAS,CAAC/D,EAAegE,OAAQhE,EAAeiE,QAAQC,SAclE,SAA2BxC,GACzB,GAAIA,EAAQyC,MAAM,qBAChB,OAAOnE,EAAeiE,UACbvC,EAAQyC,MAAM,YACvB,OAAOnE,EAAegE,UACbtC,EAAQyC,MAAM,aACvB,OAAOnE,EAAeoE,OACb1C,GAAAA,EAAQyC,MAAM,UACvB,OAAOnE,EAAeqE,SAEtB,UAAUC,MACR,oBACGC,OAAO7C,GACP6C,OAAO,0CAGhB,CA7BMC,CAAkB9C,IAEdE,EAyDV,SACEmB,EACArB,EACAjB,EACAgE,GAEA,MAAMC,WAAEA,EAAUC,WAAEA,EAAUC,SAAEA,EAAQzC,UAAEA,GA3B5C,SAAyB1B,GACvB,MAAM0B,EAAYoB,EAAOJ,OAAO1C,GAChC,GAAyB,KAArB0B,EAAU0C,OAAe,UAAUP,MAAM,4BAE7C,MAAMQ,EAAW3C,EAAU,GAAK,GAChC,GAAI2C,EAAW,IAAMA,EAAW,EAC9B,UAAUR,MAAM,+BAGlB,MAAO,CACLI,cAA0B,GAAXI,GACfH,WAAyB,EAAXG,EAEG,EAAXA,EAEA/E,EAAagF,OADbhF,EAAaiF,iBAFfC,EAIJL,SAAsB,EAAXE,EACX3C,UAAWA,EAAU+C,MAAM,GAE/B,CASIC,CAAgB1E,GAClB,GAAIgE,IAAsBC,EACxB,UAAUJ,MACR,kFAIJ,MAAMc,EAkCR,SAAmBrC,GACjB,MAAMsC,GAAS,IAAIhC,aAAc9C,OAjIb,8BAkIdsB,GAAU,IAAIwB,aAAc9C,OAAOwC,GACnC8B,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,CAAU7C,GACjBT,EAAiCoC,EACnCmB,EAAUC,2BAA2B3D,EAAWyC,EAAUQ,GAC1DS,EAAUE,6BAA6B5D,EAAWyC,EAAUQ,GAChE,GAAyB,iBAAd9C,EAAwB,MAAM,IAAIgC,MAAMhC,GACnD,MAAMpC,EAAgB8F,EAAQ1D,GAC9B,IAAI2D,EAAiB,GAErB,GAAItB,EAEAsB,EAAShG,EAAoBC,QAQ/B,GAAIuE,EACF,IACEwB,EAAShG,EAAoBC,EAE/B,CAAE,MAAOgG,GACPD,EAAShG,EAAoBC,EAE/B,MAEA+F,EAASE,EAA0B,EAAGjG,GAI1C,OAAO+F,IAAWvE,CACpB,CAvGqBiC,CAAOlD,EAAMsC,YAAarB,EAASjB,EAAMA,MAAOsD,GAEjE,OAAAlD,EACKJ,CAAAA,EAAAA,GACHK,OAAQc,EAAWZ,EAAYC,SAAWD,EAAYE,QAE1D,CAAE,MAAO2B,GACP,OAAAhC,EAAYJ,CAAAA,EAAAA,GAAOK,OAAQE,EAAYE,QACzC,CACF,CCbakF,CAAmB3F,GAI9B,OAAOA,CACT,ED7BA,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,CAAA"}
|
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("
|
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
|
package/dist/index.umd.js.map
CHANGED
@@ -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.
|
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
|
-
"@
|
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 {
|
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 =
|
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() ===
|
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 {
|
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 =
|
11
|
+
const publicKey = base58.decode(address);
|
13
12
|
const messageBytes = new TextEncoder().encode(proof.attestation);
|
14
|
-
const signatureBytes =
|
13
|
+
const signatureBytes = base64.decode(proof.proof);
|
15
14
|
const verified = nacl.sign.detached.verify(
|
16
15
|
messageBytes,
|
17
16
|
signatureBytes,
|
package/src/tests/eth.test.ts
CHANGED
@@ -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.
|
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);
|
package/src/tests/solana.test.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
2
|
-
import
|
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 =
|
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";
|
package/dist/index.test.d.ts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export {};
|