@notabene/verify-proof 1.0.0-preview.7 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bitcoin.d.ts +1 -11
- package/dist/eth.d.ts +3 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +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/dist/solana.d.ts +1 -1
- package/package.json +4 -13
- package/src/bitcoin.ts +4 -6
- package/src/eth.ts +24 -10
- package/src/index.ts +1 -1
- package/src/solana.ts +2 -4
- package/src/tests/bitcoin.test.ts +33 -71
- package/src/tests/eth.test.ts +1 -1
- package/src/tests/index.test.ts +57 -45
- package/src/tests/solana.test.ts +2 -1
package/dist/bitcoin.d.ts
CHANGED
@@ -1,12 +1,2 @@
|
|
1
|
-
import { SignatureProof } from "@notabene/javascript-sdk
|
2
|
-
export declare enum DerivationMode {
|
3
|
-
LEGACY = "Legacy",
|
4
|
-
NATIVE = "Native SegWit",
|
5
|
-
SEGWIT = "SegWit",
|
6
|
-
P2SH_SEGWIT = "p2sh",
|
7
|
-
BCH = "Bitcoin Cash",
|
8
|
-
ETHEREUM = "Ethereum",
|
9
|
-
DOGECOIN = "Dogecoin",
|
10
|
-
UNKNOWN = "Unknown"
|
11
|
-
}
|
1
|
+
import { SignatureProof } from "@notabene/javascript-sdk";
|
12
2
|
export declare function verifyBTCSignature(proof: SignatureProof): Promise<SignatureProof>;
|
package/dist/eth.d.ts
CHANGED
@@ -1,2 +1,4 @@
|
|
1
|
-
import { SignatureProof } from "@notabene/javascript-sdk
|
1
|
+
import { SignatureProof } from "@notabene/javascript-sdk";
|
2
|
+
import { Hex } from "ox";
|
3
|
+
export declare function verifyEIP191(address: Hex.Hex, message: string, proof: Hex.Hex): boolean;
|
2
4
|
export declare function verifyPersonalSignEIP191(proof: SignatureProof): Promise<SignatureProof>;
|
package/dist/index.cjs
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
var e=require("@notabene/javascript-sdk
|
1
|
+
var e=require("@notabene/javascript-sdk"),r=require("bech32"),t=require("@bitauth/libauth"),o=require("varuint-bitcoin"),s=require("@stablelib/base64"),n=require("ox"),a=require("tweetnacl"),i=require("bs58");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var c,f,P=/*#__PURE__*/u(a),l=/*#__PURE__*/u(i);function d(){return d=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var o in t)({}).hasOwnProperty.call(t,o)&&(e[o]=t[o])}return e},d.apply(null,arguments)}function h(e){var t=r.bech32.toWords(e);return t.unshift(0),r.bech32.encode("bc",t)}!function(e){e.P2WPKH="p2wpkh",e.P2SH_P2WPKH="p2sh(p2wpkh)"}(c||(c={})),function(e){e.LEGACY="Legacy",e.NATIVE="Native SegWit",e.SEGWIT="SegWit",e.P2SH_SEGWIT="p2sh",e.BCH="Bitcoin Cash",e.ETHEREUM="Ethereum",e.DOGECOIN="Dogecoin",e.UNKNOWN="Unknown"}(f||(f={})),exports.verifyProof=function(r){try{switch(r.type){case e.ProofTypes.SelfDeclaration:return Promise.resolve(d({},r,{status:r.confirmed?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}));case e.ProofTypes.Screenshot:return Promise.resolve(d({},r,{status:r.url?e.ProofStatus.FLAGGED:e.ProofStatus.FAILED}));case e.ProofTypes.EIP191:return Promise.resolve(function(r){try{var t=r.address.split(/:/),o=t[2];if("eip155"!==t[0])return Promise.resolve(d({},r,{status:e.ProofStatus.FAILED}));var s=function(e,r,t){try{var o=n.PersonalMessage.getSignPayload(n.Hex.fromString(r)),s=n.Signature.fromHex(t),a=n.Secp256k1.recoverPublicKey({payload:o,signature:s});return n.Address.fromPublicKey(a).toString()===e.toString()}catch(e){return!1}}(o,r.attestation,r.proof);return Promise.resolve(d({},r,{status:s?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(e){return Promise.reject(e)}}(r));case e.ProofTypes.ED25519:return Promise.resolve(function(r){try{var t=r.address.split(/:/),o=t[2];if("solana"!==t[0])return Promise.resolve(d({},r,{status:e.ProofStatus.FAILED}));try{var n=l.default.decode(o),a=(new TextEncoder).encode(r.attestation),i=s.decode(r.proof),u=P.default.sign.detached.verify(a,i,n);return Promise.resolve(d({},r,{status:u?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(t){return Promise.resolve(d({},r,{status:e.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(r));case e.ProofTypes.EIP712:case e.ProofTypes.BIP137:return Promise.resolve(function(r){try{var n=r.address.split(/:/),a=n[2];if("bip122"!==n[0])return Promise.resolve(d({},r,{status:e.ProofStatus.FAILED}));try{var i=[f.SEGWIT,f.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return f.NATIVE;if(e.match("^[32M].*"))return f.SEGWIT;if(e.match("^[1nmL].*"))return f.LEGACY;if(e.match("^(D).*"))return f.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(a)),u=function(e,r,n,a){var i=function(e){var r=s.decode(e);if(65!==r.length)throw new Error("Invalid signature length");var t=r[0]-27;if(t>15||t<0)throw new Error("Invalid signature parameter");return{compressed:!!(12&t),segwitType:8&t?4&t?c.P2WPKH:c.P2SH_P2WPKH:void 0,recovery:3&t,signature:r.slice(1)}}(n),u=i.compressed,f=i.segwitType,P=i.recovery,l=i.signature;if(a&&!u)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var d=function(e){var r=(new TextEncoder).encode("Bitcoin Signed Message:\n"),s=(new TextEncoder).encode(e),n=o.encode(s.length).buffer,a=new Uint8Array(r.length+n.byteLength+s.length);return a.set(r),a.set(new Uint8Array(n),r.length),a.set(s,r.length+n.byteLength),t.hash256(a)}(e),v=u?t.secp256k1.recoverPublicKeyCompressed(l,P,d):t.secp256k1.recoverPublicKeyUncompressed(l,P,d);if("string"==typeof v)throw new Error(v);var E=t.hash160(v),p="";if(f)p=h(E);else if(a)try{p=h(E)}catch(e){p=h(E)}else p=t.encodeBase58AddressFormat(0,E);return p===r}(r.attestation,a,r.proof,i);return Promise.resolve(d({},r,{status:u?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(t){return Promise.resolve(d({},r,{status:e.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(r))}return Promise.resolve(r)}catch(e){return Promise.reject(e)}};
|
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 {\n ProofStatus,\n SignatureProof,\n} from \"@notabene/javascript-sdk/src/types\";\nimport * as bitcoinMessage from \"bitcoinjs-message\";\n\nexport enum 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 = bitcoinMessage.verify(\n proof.attestation,\n address,\n proof.proof,\n undefined,\n segwit,\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\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","import {\n type OwnershipProof,\n SignatureProof,\n DeclarationProof,\n ScreenshotProof,\n ProofTypes,\n ProofStatus,\n} from \"@notabene/javascript-sdk/src/types\";\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 {\n ProofStatus,\n SignatureProof,\n} from \"@notabene/javascript-sdk/src/types\";\nimport { verifyMessage } from \"viem\";\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 = await verifyMessage({\n address: address as `0x${string}`,\n message: proof.attestation,\n signature: proof.proof as `0x${string}`,\n });\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n","import { PublicKey } from \"@solana/web3.js\";\nimport nacl from \"tweetnacl\";\nimport {\n ProofStatus,\n SignatureProof,\n} from \"@notabene/javascript-sdk/src/types\";\nimport { decode as decodeBase64 } from \"@stablelib/base64\";\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 = new PublicKey(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.toBytes(),\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":["DerivationMode","proof","type","ProofTypes","SelfDeclaration","Promise","resolve","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","_proof$address$split","address","split","verifyMessage","message","attestation","signature","then","verified","e","reject","verifyPersonalSignEIP191","ED25519","publicKey","PublicKey","messageBytes","TextEncoder","encode","signatureBytes","decodeBase64","nacl","sign","detached","verify","toBytes","error","verifySolanaSignature","EIP712","BIP137","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","bitcoinMessage","undefined","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\";\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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"}
|
package/dist/index.d.ts
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
import { type OwnershipProof } from "@notabene/javascript-sdk
|
1
|
+
import { type OwnershipProof } from "@notabene/javascript-sdk";
|
2
2
|
export declare function verifyProof(proof: OwnershipProof): Promise<OwnershipProof>;
|
package/dist/index.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
import{ProofStatus as
|
1
|
+
import{ProofStatus as e,ProofTypes as r}from"@notabene/javascript-sdk";import{bech32 as t}from"bech32";import{secp256k1 as n,hash160 as o,encodeBase58AddressFormat as s,hash256 as i}from"@bitauth/libauth";import{encode as a}from"varuint-bitcoin";import{decode as c}from"@stablelib/base64";import{PersonalMessage as u,Hex as l,Signature as f,Secp256k1 as m,Address as v}from"ox";import E from"tweetnacl";import h from"bs58";function p(){return p=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var n in t)({}).hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e},p.apply(null,arguments)}var d,P;function g(e){var r=t.toWords(e);return r.unshift(0),t.encode("bc",r)}!function(e){e.P2WPKH="p2wpkh",e.P2SH_P2WPKH="p2sh(p2wpkh)"}(d||(d={})),function(e){e.LEGACY="Legacy",e.NATIVE="Native SegWit",e.SEGWIT="SegWit",e.P2SH_SEGWIT="p2sh",e.BCH="Bitcoin Cash",e.ETHEREUM="Ethereum",e.DOGECOIN="Dogecoin",e.UNKNOWN="Unknown"}(P||(P={}));var I=function(t){try{switch(t.type){case r.SelfDeclaration:return Promise.resolve(p({},t,{status:t.confirmed?e.VERIFIED:e.FAILED}));case r.Screenshot:return Promise.resolve(p({},t,{status:t.url?e.FLAGGED:e.FAILED}));case r.EIP191:return Promise.resolve(function(r){try{var t=r.address.split(/:/),n=t[2];if("eip155"!==t[0])return Promise.resolve(p({},r,{status:e.FAILED}));var o=function(e,r,t){try{var n=u.getSignPayload(l.fromString(r)),o=f.fromHex(t),s=m.recoverPublicKey({payload:n,signature:o});return v.fromPublicKey(s).toString()===e.toString()}catch(e){return!1}}(n,r.attestation,r.proof);return Promise.resolve(p({},r,{status:o?e.VERIFIED:e.FAILED}))}catch(e){return Promise.reject(e)}}(t));case r.ED25519:return Promise.resolve(function(r){try{var t=r.address.split(/:/),n=t[2];if("solana"!==t[0])return Promise.resolve(p({},r,{status:e.FAILED}));try{var o=h.decode(n),s=(new TextEncoder).encode(r.attestation),i=c(r.proof),a=E.sign.detached.verify(s,i,o);return Promise.resolve(p({},r,{status:a?e.VERIFIED:e.FAILED}))}catch(t){return Promise.resolve(p({},r,{status:e.FAILED}))}}catch(e){return Promise.reject(e)}}(t));case r.EIP712:case r.BIP137:return Promise.resolve(function(r){try{var t=r.address.split(/:/),u=t[2];if("bip122"!==t[0])return Promise.resolve(p({},r,{status:e.FAILED}));try{var l=[P.SEGWIT,P.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return P.NATIVE;if(e.match("^[32M].*"))return P.SEGWIT;if(e.match("^[1nmL].*"))return P.LEGACY;if(e.match("^(D).*"))return P.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(u)),f=function(e,r,t,u){var l=function(e){var r=c(e);if(65!==r.length)throw new Error("Invalid signature length");var t=r[0]-27;if(t>15||t<0)throw new Error("Invalid signature parameter");return{compressed:!!(12&t),segwitType:8&t?4&t?d.P2WPKH:d.P2SH_P2WPKH:void 0,recovery:3&t,signature:r.slice(1)}}(t),f=l.compressed,m=l.segwitType,v=l.recovery,E=l.signature;if(u&&!f)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var h=function(e){var r=(new TextEncoder).encode("Bitcoin Signed Message:\n"),t=(new TextEncoder).encode(e),n=a(t.length).buffer,o=new Uint8Array(r.length+n.byteLength+t.length);return o.set(r),o.set(new Uint8Array(n),r.length),o.set(t,r.length+n.byteLength),i(o)}(e),p=f?n.recoverPublicKeyCompressed(E,v,h):n.recoverPublicKeyUncompressed(E,v,h);if("string"==typeof p)throw new Error(p);var P=o(p),I="";if(m)I=g(P);else if(u)try{I=g(P)}catch(e){I=g(P)}else I=s(0,P);return I===r}(r.attestation,u,r.proof,l);return Promise.resolve(p({},r,{status:f?e.VERIFIED:e.FAILED}))}catch(t){return Promise.resolve(p({},r,{status:e.FAILED}))}}catch(e){return Promise.reject(e)}}(t))}return Promise.resolve(t)}catch(e){return Promise.reject(e)}};export{I as verifyProof};
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/bitcoin.ts","../src/eth.ts","../src/index.ts","../src/solana.ts"],"sourcesContent":["import {\n ProofStatus,\n SignatureProof,\n} from \"@notabene/javascript-sdk/src/types\";\nimport * as bitcoinMessage from \"bitcoinjs-message\";\n\nexport enum 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 = bitcoinMessage.verify(\n proof.attestation,\n address,\n proof.proof,\n undefined,\n segwit,\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\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","import {\n ProofStatus,\n SignatureProof,\n} from \"@notabene/javascript-sdk/src/types\";\nimport { verifyMessage } from \"viem\";\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 = await verifyMessage({\n address: address as `0x${string}`,\n message: proof.attestation,\n signature: proof.proof as `0x${string}`,\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/src/types\";\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 { PublicKey } from \"@solana/web3.js\";\nimport nacl from \"tweetnacl\";\nimport {\n ProofStatus,\n SignatureProof,\n} from \"@notabene/javascript-sdk/src/types\";\nimport { decode as decodeBase64 } from \"@stablelib/base64\";\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 = new PublicKey(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.toBytes(),\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":["DerivationMode","verifyProof","proof","type","ProofTypes","SelfDeclaration","Promise","resolve","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","_proof$address$split","address","split","verifyMessage","message","attestation","signature","then","verified","e","reject","verifyPersonalSignEIP191","ED25519","publicKey","PublicKey","messageBytes","TextEncoder","encode","signatureBytes","decodeBase64","nacl","sign","detached","verify","toBytes","error","verifySolanaSignature","EIP712","BIP137","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","bitcoinMessage","undefined","verifyBTCSignature"],"mappings":"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"}
|
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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"}
|
package/dist/index.modern.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
import{ProofStatus as t,ProofTypes as
|
1
|
+
import{ProofStatus as t,ProofTypes as e}from"@notabene/javascript-sdk";import{bech32 as r}from"bech32";import{secp256k1 as n,hash160 as o,encodeBase58AddressFormat as s,hash256 as c}from"@bitauth/libauth";import{encode as i}from"varuint-bitcoin";import{decode as a}from"@stablelib/base64";import{PersonalMessage as u,Hex as f,Signature as E,Secp256k1 as l,Address as p}from"ox";import h from"tweetnacl";import d from"bs58";function g(){return g=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var n in r)({}).hasOwnProperty.call(r,n)&&(t[n]=r[n])}return t},g.apply(null,arguments)}var I,m;function y(t){const e=r.toWords(t);return e.unshift(0),r.encode("bc",e)}async function b(r){switch(r.type){case e.SelfDeclaration:return g({},r,{status:r.confirmed?t.VERIFIED:t.FAILED});case e.Screenshot:return g({},r,{status:r.url?t.FLAGGED:t.FAILED});case e.EIP191:return async function(e){const[r,n,o]=e.address.split(/:/);if("eip155"!==r)return g({},e,{status:t.FAILED});const s=function(t,e,r){try{const n=u.getSignPayload(f.fromString(e)),o=E.fromHex(r),s=l.recoverPublicKey({payload:n,signature:o});return p.fromPublicKey(s).toString()===t.toString()}catch(t){return!1}}(o,e.attestation,e.proof);return g({},e,{status:s?t.VERIFIED:t.FAILED})}(r);case e.ED25519:return async function(e){const[r,n,o]=e.address.split(/:/);if("solana"!==r)return g({},e,{status:t.FAILED});try{const r=d.decode(o),n=(new TextEncoder).encode(e.attestation),s=a(e.proof);return g({},e,{status:h.sign.detached.verify(n,s,r)?t.VERIFIED:t.FAILED})}catch(r){return g({},e,{status:t.FAILED})}}(r);case e.EIP712:case e.BIP137:return async function(e){const[r,u,f]=e.address.split(/:/);if("bip122"!==r)return g({},e,{status:t.FAILED});try{const r=[m.SEGWIT,m.NATIVE].includes(function(t){if(t.match("^(bc1|tb1|ltc1).*"))return m.NATIVE;if(t.match("^[32M].*"))return m.SEGWIT;if(t.match("^[1nmL].*"))return m.LEGACY;if(t.match("^(D).*"))return m.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(t).concat(" is not a valid or a supported address"))}(f)),u=function(t,e,r,u){const{compressed:f,segwitType:E,recovery:l,signature:p}=function(t){const e=a(t);if(65!==e.length)throw new Error("Invalid signature length");const r=e[0]-27;if(r>15||r<0)throw new Error("Invalid signature parameter");return{compressed:!!(12&r),segwitType:8&r?4&r?I.P2WPKH:I.P2SH_P2WPKH:void 0,recovery:3&r,signature:e.slice(1)}}(r);if(u&&!f)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");const h=function(t){const e=(new TextEncoder).encode("Bitcoin Signed Message:\n"),r=(new TextEncoder).encode(t),n=i(r.length).buffer,o=new Uint8Array(e.length+n.byteLength+r.length);return o.set(e),o.set(new Uint8Array(n),e.length),o.set(r,e.length+n.byteLength),c(o)}(t),d=f?n.recoverPublicKeyCompressed(p,l,h):n.recoverPublicKeyUncompressed(p,l,h);if("string"==typeof d)throw new Error(d);const g=o(d);let m="";if(E)m=y(g);else if(u)try{m=y(g)}catch(t){m=y(g)}else m=s(0,g);return m===e}(e.attestation,f,e.proof,r);return g({},e,{status:u?t.VERIFIED:t.FAILED})}catch(r){return g({},e,{status:t.FAILED})}}(r)}return r}!function(t){t.P2WPKH="p2wpkh",t.P2SH_P2WPKH="p2sh(p2wpkh)"}(I||(I={})),function(t){t.LEGACY="Legacy",t.NATIVE="Native SegWit",t.SEGWIT="SegWit",t.P2SH_SEGWIT="p2sh",t.BCH="Bitcoin Cash",t.ETHEREUM="Ethereum",t.DOGECOIN="Dogecoin",t.UNKNOWN="Unknown"}(m||(m={}));export{b as verifyProof};
|
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 {\n ProofStatus,\n SignatureProof,\n} from \"@notabene/javascript-sdk/src/types\";\nimport * as bitcoinMessage from \"bitcoinjs-message\";\n\nexport enum 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 = bitcoinMessage.verify(\n proof.attestation,\n address,\n proof.proof,\n undefined,\n segwit,\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\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","import {\n type OwnershipProof,\n SignatureProof,\n DeclarationProof,\n ScreenshotProof,\n ProofTypes,\n ProofStatus,\n} from \"@notabene/javascript-sdk/src/types\";\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 {\n ProofStatus,\n SignatureProof,\n} from \"@notabene/javascript-sdk/src/types\";\nimport { verifyMessage } from \"viem\";\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 = await verifyMessage({\n address: address as `0x${string}`,\n message: proof.attestation,\n signature: proof.proof as `0x${string}`,\n });\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n","import { PublicKey } from \"@solana/web3.js\";\nimport nacl from \"tweetnacl\";\nimport {\n ProofStatus,\n SignatureProof,\n} from \"@notabene/javascript-sdk/src/types\";\nimport { decode as decodeBase64 } from \"@stablelib/base64\";\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 = new PublicKey(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.toBytes(),\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":["DerivationMode","verifyProof","proof","type","ProofTypes","SelfDeclaration","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","ns","_","address","split","verifyMessage","message","attestation","signature","verifyPersonalSignEIP191","ED25519","async","publicKey","PublicKey","messageBytes","TextEncoder","encode","signatureBytes","decodeBase64","nacl","sign","detached","verify","toBytes","error","verifySolanaSignature","EIP712","BIP137","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","bitcoinMessage","undefined","verifyBTCSignature"],"mappings":"keAMY,IAAAA,iBCMUC,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,sBCxBJb,GAEA,MAAOc,EAAIC,EAAGC,GAAWhB,EAAMgB,QAAQC,MAAM,KAC7C,OAAqBb,EAAA,CAAA,EAAYJ,EAAtB,WAAPc,EAAkC,CAAET,OAAQE,EAAYE,QAQlD,CACRJ,aAPqBa,EAAc,CACnCF,QAASA,EACTG,QAASnB,EAAMoB,YACfC,UAAWrB,EAAMA,QAIEO,EAAYC,SAAWD,EAAYE,QAE1D,CDUaa,CAAyBtB,GAClC,KAAKE,EAAWqB,QACd,OEzBCC,eACLxB,GAEA,MAAOc,EAAIC,EAAGC,GAAWhB,EAAMgB,QAAQC,MAAM,KAC7C,GAAW,WAAPH,EAAiB,OAAAV,EAAA,GAAYJ,EAAOK,CAAAA,OAAQE,EAAYE,SAC5D,IACE,MAAMgB,EAAY,IAAIC,EAAUV,GAC1BW,GAAe,IAAIC,aAAcC,OAAO7B,EAAMoB,aAC9CU,EAAiBC,EAAa/B,EAAMA,OAO1C,OAAAI,EAAA,GACKJ,EAAK,CACRK,OARe2B,EAAKC,KAAKC,SAASC,OAClCR,EACAG,EACAL,EAAUW,WAKS7B,EAAYC,SAAWD,EAAYE,QAE1D,CAAE,MAAO4B,GACP,OAAAjC,EAAYJ,CAAAA,EAAAA,GAAOK,OAAQE,EAAYE,QACzC,CACF,CFGa6B,CAAsBtC,GAC/B,KAAKE,EAAWqC,OAChB,KAAKrC,EAAWsC,OACd,ODnBgBhB,eACpBxB,GAEA,MAAOc,EAAIC,EAAGC,GAAWhB,EAAMgB,QAAQC,MAAM,KAC7C,GAAW,WAAPH,EAAiB,OAAAV,EAAA,GAAYJ,EAAK,CAAEK,OAAQE,EAAYE,SAC5D,IAEE,MAAMgC,EAAS,CAAC3C,EAAe4C,OAAQ5C,EAAe6C,QAAQC,SAoBlE,SAA2B5B,GACzB,GAAIA,EAAQ6B,MAAM,qBAChB,OAAO/C,EAAe6C,OACjB,GAAI3B,EAAQ6B,MAAM,YACvB,OAAO/C,EAAe4C,OACjB,GAAI1B,EAAQ6B,MAAM,aACvB,OAAO/C,EAAegD,OACb9B,GAAAA,EAAQ6B,MAAM,UACvB,OAAO/C,EAAeiD,SAEtB,MAAM,IAAIC,MACR,oBACGC,OAAOjC,GACPiC,OAAO,0CAGhB,CAnCMC,CAAkBlC,IAUpB,OAAAZ,EACKJ,CAAAA,EAAAA,GACHK,OAVe8C,EAAehB,OAC9BnC,EAAMoB,YACNJ,EACAhB,EAAMA,WACNoD,EACAX,GAKmBlC,EAAYC,SAAWD,EAAYE,QAE1D,CAAE,MAAO4B,GACP,OAAAjC,EAAYJ,CAAAA,EAAAA,EAAOK,CAAAA,OAAQE,EAAYE,QACzC,CACF,CCNa4C,CAAmBrD,GAI9B,OAAOA,CACT,EDnCA,SAAYF,GACVA,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,CAAYA,IAAAA,EASX"}
|
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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"}
|
package/dist/index.umd.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
!function(e,
|
1
|
+
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@notabene/javascript-sdk"),require("bech32"),require("@bitauth/libauth"),require("varuint-bitcoin"),require("@stablelib/base64"),require("ox"),require("tweetnacl"),require("bs58")):"function"==typeof define&&define.amd?define(["exports","@notabene/javascript-sdk","bech32","@bitauth/libauth","varuint-bitcoin","@stablelib/base64","ox","tweetnacl","bs58"],r):r((e||self).verifyProof={},e.javascriptSdk,e.bech32,e.libauth,e.varuintBitcoin,e.base64,e.ox,e.tweetnacl,e.bs58)}(this,function(e,r,t,o,s,n,a,i,u){function c(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var f,l,d=/*#__PURE__*/c(i),P=/*#__PURE__*/c(u);function h(){return h=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var o in t)({}).hasOwnProperty.call(t,o)&&(e[o]=t[o])}return e},h.apply(null,arguments)}function p(e){var r=t.bech32.toWords(e);return r.unshift(0),t.bech32.encode("bc",r)}!function(e){e.P2WPKH="p2wpkh",e.P2SH_P2WPKH="p2sh(p2wpkh)"}(f||(f={})),function(e){e.LEGACY="Legacy",e.NATIVE="Native SegWit",e.SEGWIT="SegWit",e.P2SH_SEGWIT="p2sh",e.BCH="Bitcoin Cash",e.ETHEREUM="Ethereum",e.DOGECOIN="Dogecoin",e.UNKNOWN="Unknown"}(l||(l={})),e.verifyProof=function(e){try{switch(e.type){case r.ProofTypes.SelfDeclaration:return Promise.resolve(h({},e,{status:e.confirmed?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}));case r.ProofTypes.Screenshot:return Promise.resolve(h({},e,{status:e.url?r.ProofStatus.FLAGGED:r.ProofStatus.FAILED}));case r.ProofTypes.EIP191:return Promise.resolve(function(e){try{var t=e.address.split(/:/),o=t[2];if("eip155"!==t[0])return Promise.resolve(h({},e,{status:r.ProofStatus.FAILED}));var s=function(e,r,t){try{var o=a.PersonalMessage.getSignPayload(a.Hex.fromString(r)),s=a.Signature.fromHex(t),n=a.Secp256k1.recoverPublicKey({payload:o,signature:s});return a.Address.fromPublicKey(n).toString()===e.toString()}catch(e){return!1}}(o,e.attestation,e.proof);return Promise.resolve(h({},e,{status:s?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}))}catch(e){return Promise.reject(e)}}(e));case r.ProofTypes.ED25519:return Promise.resolve(function(e){try{var t=e.address.split(/:/),o=t[2];if("solana"!==t[0])return Promise.resolve(h({},e,{status:r.ProofStatus.FAILED}));try{var s=P.default.decode(o),a=(new TextEncoder).encode(e.attestation),i=n.decode(e.proof),u=d.default.sign.detached.verify(a,i,s);return Promise.resolve(h({},e,{status:u?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}))}catch(t){return Promise.resolve(h({},e,{status:r.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(e));case r.ProofTypes.EIP712:case r.ProofTypes.BIP137:return Promise.resolve(function(e){try{var t=e.address.split(/:/),a=t[2];if("bip122"!==t[0])return Promise.resolve(h({},e,{status:r.ProofStatus.FAILED}));try{var i=[l.SEGWIT,l.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return l.NATIVE;if(e.match("^[32M].*"))return l.SEGWIT;if(e.match("^[1nmL].*"))return l.LEGACY;if(e.match("^(D).*"))return l.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(a)),u=function(e,r,t,a){var i=function(e){var r=n.decode(e);if(65!==r.length)throw new Error("Invalid signature length");var t=r[0]-27;if(t>15||t<0)throw new Error("Invalid signature parameter");return{compressed:!!(12&t),segwitType:8&t?4&t?f.P2WPKH:f.P2SH_P2WPKH:void 0,recovery:3&t,signature:r.slice(1)}}(t),u=i.compressed,c=i.segwitType,l=i.recovery,d=i.signature;if(a&&!u)throw new Error("checkSegwitAlways can only be used with a compressed pubkey signature flagbyte");var P=function(e){var r=(new TextEncoder).encode("Bitcoin Signed Message:\n"),t=(new TextEncoder).encode(e),n=s.encode(t.length).buffer,a=new Uint8Array(r.length+n.byteLength+t.length);return a.set(r),a.set(new Uint8Array(n),r.length),a.set(t,r.length+n.byteLength),o.hash256(a)}(e),h=u?o.secp256k1.recoverPublicKeyCompressed(d,l,P):o.secp256k1.recoverPublicKeyUncompressed(d,l,P);if("string"==typeof h)throw new Error(h);var v=o.hash160(h),E="";if(c)E=p(v);else if(a)try{E=p(v)}catch(e){E=p(v)}else E=o.encodeBase58AddressFormat(0,v);return E===r}(e.attestation,a,e.proof,i);return Promise.resolve(h({},e,{status:u?r.ProofStatus.VERIFIED:r.ProofStatus.FAILED}))}catch(t){return Promise.resolve(h({},e,{status:r.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(e))}return Promise.resolve(e)}catch(e){return Promise.reject(e)}}});
|
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 {\n ProofStatus,\n SignatureProof,\n} from \"@notabene/javascript-sdk/src/types\";\nimport * as bitcoinMessage from \"bitcoinjs-message\";\n\nexport enum 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 = bitcoinMessage.verify(\n proof.attestation,\n address,\n proof.proof,\n undefined,\n segwit,\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\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","import {\n type OwnershipProof,\n SignatureProof,\n DeclarationProof,\n ScreenshotProof,\n ProofTypes,\n ProofStatus,\n} from \"@notabene/javascript-sdk/src/types\";\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 {\n ProofStatus,\n SignatureProof,\n} from \"@notabene/javascript-sdk/src/types\";\nimport { verifyMessage } from \"viem\";\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 = await verifyMessage({\n address: address as `0x${string}`,\n message: proof.attestation,\n signature: proof.proof as `0x${string}`,\n });\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n","import { PublicKey } from \"@solana/web3.js\";\nimport nacl from \"tweetnacl\";\nimport {\n ProofStatus,\n SignatureProof,\n} from \"@notabene/javascript-sdk/src/types\";\nimport { decode as decodeBase64 } from \"@stablelib/base64\";\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 = new PublicKey(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.toBytes(),\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":["DerivationMode","proof","type","ProofTypes","SelfDeclaration","Promise","resolve","_extends","status","confirmed","ProofStatus","VERIFIED","FAILED","Screenshot","url","FLAGGED","EIP191","_proof$address$split","address","split","verifyMessage","message","attestation","signature","then","verified","e","reject","verifyPersonalSignEIP191","ED25519","publicKey","PublicKey","messageBytes","TextEncoder","encode","signatureBytes","decodeBase64","nacl","sign","detached","verify","toBytes","error","verifySolanaSignature","EIP712","BIP137","segwit","SEGWIT","NATIVE","includes","match","LEGACY","DOGECOIN","Error","concat","getDerivationMode","bitcoinMessage","undefined","verifyBTCSignature"],"mappings":"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"}
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/bitcoin.ts","../src/index.ts","../src/eth.ts","../src/solana.ts"],"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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"}
|
package/dist/solana.d.ts
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
import { SignatureProof } from "@notabene/javascript-sdk
|
1
|
+
import { SignatureProof } from "@notabene/javascript-sdk";
|
2
2
|
export declare function verifySolanaSignature(proof: SignatureProof): Promise<SignatureProof>;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@notabene/verify-proof",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.1",
|
4
4
|
"description": "Verify ownership proofs",
|
5
5
|
"source": "src/index.ts",
|
6
6
|
"type": "module",
|
@@ -23,29 +23,20 @@
|
|
23
23
|
"test": "vitest"
|
24
24
|
},
|
25
25
|
"devDependencies": {
|
26
|
-
"@types/bitcoinjs-lib": "3.4.0",
|
27
|
-
"@types/node": "^22.9.0",
|
28
|
-
"bitcoinjs-lib": "^3.2.0",
|
29
|
-
"buffer": "^6.0.3",
|
30
|
-
"ecpair": "^3.0.0-rc.0",
|
31
26
|
"eslint": "^9.9.0",
|
32
27
|
"microbundle": "^0.15.1",
|
33
|
-
"tiny-secp256k1": "^2.2.3",
|
34
28
|
"typescript": "^5.5.4",
|
35
29
|
"vite": "^5.4.11",
|
36
|
-
"vitest": "^2.0.5"
|
37
|
-
"bitcoinjs-message": "^2.2.0",
|
38
|
-
"ox": "^0.1.4"
|
30
|
+
"vitest": "^2.0.5"
|
39
31
|
},
|
40
32
|
"dependencies": {
|
41
33
|
"@bitauth/libauth": "^3.0.0",
|
42
34
|
"@notabene/javascript-sdk": "^2.0.2",
|
43
35
|
"@stablelib/base64": "^2.0.0",
|
44
36
|
"bech32": "^2.0.0",
|
45
|
-
"bigi": "^1.4.2",
|
46
37
|
"bs58": "^6.0.0",
|
38
|
+
"ox": "^0.2.2",
|
47
39
|
"tweetnacl": "^1.0.3",
|
48
|
-
"varuint-bitcoin": "^2.0.0"
|
49
|
-
"viem": "^2.21.44"
|
40
|
+
"varuint-bitcoin": "^2.0.0"
|
50
41
|
}
|
51
42
|
}
|
package/src/bitcoin.ts
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
import {
|
2
|
-
ProofStatus,
|
3
|
-
SignatureProof,
|
4
|
-
} from "@notabene/javascript-sdk/src/types";
|
1
|
+
import { ProofStatus, SignatureProof } from "@notabene/javascript-sdk";
|
5
2
|
import { bech32 } from "bech32";
|
6
3
|
|
7
4
|
import {
|
@@ -21,7 +18,7 @@ enum SEGWIT_TYPES {
|
|
21
18
|
|
22
19
|
const messagePrefix = "\u0018Bitcoin Signed Message:\n";
|
23
20
|
|
24
|
-
|
21
|
+
enum DerivationMode {
|
25
22
|
LEGACY = "Legacy",
|
26
23
|
NATIVE = "Native SegWit",
|
27
24
|
SEGWIT = "SegWit",
|
@@ -77,6 +74,7 @@ type DecodedSignature = {
|
|
77
74
|
recovery: RecoveryId;
|
78
75
|
signature: Uint8Array;
|
79
76
|
};
|
77
|
+
|
80
78
|
function decodeSignature(proof: string): DecodedSignature {
|
81
79
|
const signature = decodeBase64(proof);
|
82
80
|
if (signature.length !== 65) throw new Error("Invalid signature length");
|
@@ -146,7 +144,7 @@ function verify(
|
|
146
144
|
return actual === address;
|
147
145
|
}
|
148
146
|
|
149
|
-
|
147
|
+
function magicHash(attestation: string) {
|
150
148
|
const prefix = new TextEncoder().encode(messagePrefix);
|
151
149
|
const message = new TextEncoder().encode(attestation);
|
152
150
|
const length = encodeLength(message.length).buffer;
|
package/src/eth.ts
CHANGED
@@ -1,8 +1,22 @@
|
|
1
|
-
import {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
import { ProofStatus, SignatureProof } from "@notabene/javascript-sdk";
|
2
|
+
|
3
|
+
import { Secp256k1, Hex, PersonalMessage, Signature, Address } from "ox";
|
4
|
+
|
5
|
+
export function verifyEIP191(
|
6
|
+
address: Hex.Hex,
|
7
|
+
message: string,
|
8
|
+
proof: Hex.Hex,
|
9
|
+
): boolean {
|
10
|
+
try {
|
11
|
+
const payload = PersonalMessage.getSignPayload(Hex.fromString(message));
|
12
|
+
const signature = Signature.fromHex(proof);
|
13
|
+
const publicKey = Secp256k1.recoverPublicKey({ payload, signature });
|
14
|
+
const recovered = Address.fromPublicKey(publicKey);
|
15
|
+
return recovered.toString() === address.toString();
|
16
|
+
} catch (error) {
|
17
|
+
return false;
|
18
|
+
}
|
19
|
+
}
|
6
20
|
|
7
21
|
export async function verifyPersonalSignEIP191(
|
8
22
|
proof: SignatureProof,
|
@@ -10,11 +24,11 @@ export async function verifyPersonalSignEIP191(
|
|
10
24
|
const [ns, _, address] = proof.address.split(/:/);
|
11
25
|
if (ns !== "eip155") return { ...proof, status: ProofStatus.FAILED };
|
12
26
|
|
13
|
-
const verified =
|
14
|
-
address
|
15
|
-
|
16
|
-
|
17
|
-
|
27
|
+
const verified = verifyEIP191(
|
28
|
+
address as Hex.Hex,
|
29
|
+
proof.attestation,
|
30
|
+
proof.proof as Hex.Hex,
|
31
|
+
);
|
18
32
|
return {
|
19
33
|
...proof,
|
20
34
|
status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,
|
package/src/index.ts
CHANGED
@@ -5,7 +5,7 @@ import {
|
|
5
5
|
ScreenshotProof,
|
6
6
|
ProofTypes,
|
7
7
|
ProofStatus,
|
8
|
-
} from "@notabene/javascript-sdk
|
8
|
+
} from "@notabene/javascript-sdk";
|
9
9
|
import { verifyBTCSignature } from "./bitcoin";
|
10
10
|
import { verifyPersonalSignEIP191 } from "./eth";
|
11
11
|
import { verifySolanaSignature } from "./solana";
|
package/src/solana.ts
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
import nacl from "tweetnacl";
|
2
|
-
import {
|
3
|
-
ProofStatus,
|
4
|
-
SignatureProof,
|
5
|
-
} from "@notabene/javascript-sdk/src/types";
|
2
|
+
import { ProofStatus, SignatureProof } from "@notabene/javascript-sdk";
|
6
3
|
import { decode as decodeBase64 } from "@stablelib/base64";
|
7
4
|
import bs58 from "bs58";
|
5
|
+
|
8
6
|
export async function verifySolanaSignature(
|
9
7
|
proof: SignatureProof,
|
10
8
|
): Promise<SignatureProof> {
|
@@ -1,99 +1,61 @@
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
2
|
-
import * as bitcoin from "bitcoinjs-lib";
|
3
|
-
import * as bitcoinMessage from "bitcoinjs-message";
|
4
|
-
import { Buffer } from "node:buffer";
|
5
2
|
|
6
3
|
import { verifyBTCSignature } from "../bitcoin";
|
7
4
|
import {
|
8
5
|
type SignatureProof,
|
9
6
|
ProofStatus,
|
10
7
|
ProofTypes,
|
11
|
-
} from "@notabene/javascript-sdk
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
proof,
|
37
|
-
status: ProofStatus.PENDING,
|
38
|
-
wallet_provider: "MetaMask",
|
39
|
-
};
|
40
|
-
}
|
41
|
-
|
42
|
-
function signP2PKHMessage(): SignatureProof {
|
43
|
-
return signMessage((kp) => kp.getAddress());
|
44
|
-
}
|
45
|
-
|
46
|
-
function signSegWitMessage(): SignatureProof {
|
47
|
-
return signMessage((kp) =>
|
48
|
-
bitcoin.address.toBech32(
|
49
|
-
bitcoin.crypto.hash160(kp.getPublicKeyBuffer()),
|
50
|
-
0,
|
51
|
-
kp.network.bech32 || "bc",
|
52
|
-
),
|
53
|
-
);
|
54
|
-
}
|
8
|
+
} from "@notabene/javascript-sdk";
|
9
|
+
|
10
|
+
const segwitProof: SignatureProof = {
|
11
|
+
type: ProofTypes.BIP137,
|
12
|
+
address:
|
13
|
+
"bip122:000000000019d6689c085ae165831e93:bc1qnf4kpa62dwhpwm0stsas5yv0skatt3v9s040p8",
|
14
|
+
did: "did:pkh:bip122:000000000019d6689c085ae165831e93:bc1qnf4kpa62dwhpwm0stsas5yv0skatt3v9s040p8",
|
15
|
+
attestation: "This is an example of a signed message.",
|
16
|
+
proof:
|
17
|
+
"J796FDv8f8w3syiaMSGoL6SAwPLRf6t13S+fYNjYA9EnJy3T0jZOY1eHBaGTBufOuW78FVFSwXKyUnrEjYOT9EU=",
|
18
|
+
status: ProofStatus.PENDING,
|
19
|
+
wallet_provider: "BitMask",
|
20
|
+
};
|
21
|
+
|
22
|
+
const legacyProof: SignatureProof = {
|
23
|
+
type: ProofTypes.BIP137,
|
24
|
+
address:
|
25
|
+
"bip122:000000000019d6689c085ae165831e93:1F5VhMHukdnUES9kfXqzPzMeF1GPHKiF64",
|
26
|
+
did: "did:pkh:bip122:000000000019d6689c085ae165831e93:1F5VhMHukdnUES9kfXqzPzMeF1GPHKiF64",
|
27
|
+
attestation: "This is an example of a signed message.",
|
28
|
+
proof:
|
29
|
+
"H796FDv8f8w3syiaMSGoL6SAwPLRf6t13S+fYNjYA9EnJy3T0jZOY1eHBaGTBufOuW78FVFSwXKyUnrEjYOT9EU=",
|
30
|
+
status: ProofStatus.PENDING,
|
31
|
+
wallet_provider: "BitMask",
|
32
|
+
};
|
55
33
|
|
56
34
|
describe("verifyBTCSignature", () => {
|
57
35
|
it("handles native segwit addresses", async () => {
|
58
|
-
const
|
59
|
-
|
60
|
-
expect(result.status).toBe(ProofStatus.VERIFIED);
|
36
|
+
const result = await verifyBTCSignature(segwitProof);
|
37
|
+
expect(result).toEqual({ ...segwitProof, status: ProofStatus.VERIFIED });
|
61
38
|
});
|
62
39
|
|
63
40
|
it("verifies legacy bitcoin address signature", async () => {
|
64
|
-
const
|
65
|
-
|
66
|
-
expect(result.status).toBe(ProofStatus.VERIFIED);
|
41
|
+
const result = await verifyBTCSignature(legacyProof);
|
42
|
+
expect(result).toEqual({ ...legacyProof, status: ProofStatus.VERIFIED });
|
67
43
|
});
|
68
44
|
|
69
45
|
it("fails for invalid bitcoin signature", async () => {
|
70
|
-
const proof: SignatureProof = {
|
71
|
-
type: ProofTypes.BIP137,
|
72
|
-
did: "did:pkh:bip122:000000000019d6689c085ae165831e93:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
|
73
|
-
wallet_provider: "ledger",
|
74
|
-
address:
|
75
|
-
"bip122:000000000019d6689c085ae165831e93:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
|
76
|
-
attestation: "test message",
|
77
|
-
proof: "invalid_signature",
|
78
|
-
status: ProofStatus.PENDING,
|
79
|
-
};
|
46
|
+
const proof: SignatureProof = { ...legacyProof, proof: "invalitd" };
|
80
47
|
|
81
48
|
const result = await verifyBTCSignature(proof);
|
82
|
-
expect(result
|
49
|
+
expect(result).toEqual({ ...proof, status: ProofStatus.FAILED });
|
83
50
|
});
|
84
51
|
|
85
52
|
it("returns failed proof for non-BIP122 address", async () => {
|
86
53
|
const proof: SignatureProof = {
|
87
|
-
|
88
|
-
status: ProofStatus.PENDING,
|
89
|
-
did: "did:example:123",
|
54
|
+
...legacyProof,
|
90
55
|
address: "eip155:1:0x1234567890123456789012345678901234567890",
|
91
|
-
proof: "0x1234567890",
|
92
|
-
attestation: "I own this address",
|
93
|
-
wallet_provider: "MetaMask",
|
94
56
|
};
|
95
57
|
|
96
58
|
const result = await verifyBTCSignature(proof);
|
97
|
-
expect(result
|
59
|
+
expect(result).toEqual({ ...proof, status: ProofStatus.FAILED });
|
98
60
|
});
|
99
61
|
});
|
package/src/tests/eth.test.ts
CHANGED
package/src/tests/index.test.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { describe, it, expect
|
1
|
+
import { describe, it, expect } from "vitest";
|
2
2
|
import { verifyProof } from "../index";
|
3
3
|
import {
|
4
4
|
type DeclarationProof,
|
@@ -6,13 +6,7 @@ import {
|
|
6
6
|
type SignatureProof,
|
7
7
|
ProofStatus,
|
8
8
|
ProofTypes,
|
9
|
-
} from "@notabene/javascript-sdk
|
10
|
-
import { verifyMessage } from "viem";
|
11
|
-
|
12
|
-
// Mock viem's verifyMessage function
|
13
|
-
vi.mock("viem", () => ({
|
14
|
-
verifyMessage: vi.fn(),
|
15
|
-
}));
|
9
|
+
} from "@notabene/javascript-sdk";
|
16
10
|
|
17
11
|
describe("verifyProof", () => {
|
18
12
|
it("should verify a confirmed checkbox proof", async () => {
|
@@ -87,68 +81,86 @@ describe("verifyProof", () => {
|
|
87
81
|
expect(result).toEqual(proof);
|
88
82
|
});
|
89
83
|
|
90
|
-
|
84
|
+
describe("eip191", () => {
|
91
85
|
const proof: SignatureProof = {
|
92
86
|
type: ProofTypes.EIP191,
|
87
|
+
address: "eip155:1:0x772f226b9cc93a2953dc5868864de72f90441caf",
|
88
|
+
did: "did:pkh:eip155:1:0x772f226b9cc93a2953dc5868864de72f90441caf",
|
89
|
+
attestation: "I agree",
|
90
|
+
proof:
|
91
|
+
"0xddd74ca17084728a167b6f99326b50a0ce4a1ce4f80a56da4a60b23b69637c624e6dfb2270de56caece9182200fe38791339cbf097586a4e06a9ef4bd298cc1800",
|
93
92
|
status: ProofStatus.PENDING,
|
94
|
-
did: "did:example:123",
|
95
|
-
address: "eip155:1:0x1234567890123456789012345678901234567890",
|
96
|
-
proof: "0x1234567890",
|
97
|
-
attestation: "I own this address",
|
98
93
|
wallet_provider: "MetaMask",
|
99
94
|
};
|
100
95
|
|
101
|
-
|
102
|
-
|
96
|
+
it("should verify proof", async () => {
|
97
|
+
const result = await verifyProof(proof);
|
98
|
+
expect(result.status).toBe(ProofStatus.VERIFIED);
|
99
|
+
});
|
103
100
|
|
104
|
-
|
101
|
+
it("should fail if not invalid proof", async () => {
|
102
|
+
const result = await verifyProof({
|
103
|
+
...proof,
|
104
|
+
proof: "0x",
|
105
|
+
} as SignatureProof);
|
105
106
|
|
106
|
-
|
107
|
-
expect(verifyMessage).toHaveBeenCalledWith({
|
108
|
-
address: "0x1234567890123456789012345678901234567890",
|
109
|
-
message: proof.attestation,
|
110
|
-
signature: proof.proof,
|
107
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
111
108
|
});
|
112
109
|
});
|
113
110
|
|
114
|
-
|
111
|
+
describe("solana", () => {
|
115
112
|
const proof: SignatureProof = {
|
116
|
-
type: ProofTypes.
|
113
|
+
type: ProofTypes.ED25519,
|
117
114
|
status: ProofStatus.PENDING,
|
118
|
-
did: "did:
|
119
|
-
address:
|
120
|
-
|
121
|
-
attestation: "
|
122
|
-
|
115
|
+
did: "did:pkh:solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:3GgW39JvdBVCAdiK1mafeBcBKXJq8mee5woVoDARRnPq",
|
116
|
+
address:
|
117
|
+
"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:3GgW39JvdBVCAdiK1mafeBcBKXJq8mee5woVoDARRnPq",
|
118
|
+
attestation: "Test message",
|
119
|
+
proof:
|
120
|
+
"8dkeX3S+qisPkadV5QkmLWu2gbom/ljqlEwDAVuEV33HWZbSbPol+KV/zET4NLn8JBvSpu6JROJRg45WAIMPAQ==",
|
121
|
+
wallet_provider: "Phantom",
|
123
122
|
};
|
124
123
|
|
125
|
-
|
126
|
-
|
124
|
+
it("should verify proof", async () => {
|
125
|
+
const result = await verifyProof(proof);
|
126
|
+
expect(result.status).toBe(ProofStatus.VERIFIED);
|
127
|
+
});
|
127
128
|
|
128
|
-
|
129
|
+
it("should fail if not invalid proof", async () => {
|
130
|
+
const result = await verifyProof({
|
131
|
+
...proof,
|
132
|
+
proof: "0x",
|
133
|
+
} as SignatureProof);
|
129
134
|
|
130
|
-
|
131
|
-
expect(verifyMessage).toHaveBeenCalledWith({
|
132
|
-
address: "0x1234567890123456789012345678901234567890",
|
133
|
-
message: proof.attestation,
|
134
|
-
signature: proof.proof,
|
135
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
135
136
|
});
|
136
137
|
});
|
137
138
|
|
138
|
-
|
139
|
+
describe("bitcoin", () => {
|
139
140
|
const proof: SignatureProof = {
|
140
|
-
type: ProofTypes.
|
141
|
+
type: ProofTypes.BIP137,
|
141
142
|
status: ProofStatus.PENDING,
|
142
|
-
did: "did:example:123",
|
143
143
|
address:
|
144
|
-
"bip122:000000000019d6689c085ae165831e93:
|
145
|
-
|
146
|
-
attestation: "
|
147
|
-
|
144
|
+
"bip122:000000000019d6689c085ae165831e93:bc1qnf4kpa62dwhpwm0stsas5yv0skatt3v9s040p8",
|
145
|
+
did: "did:pkh:bip122:000000000019d6689c085ae165831e93:bc1qnf4kpa62dwhpwm0stsas5yv0skatt3v9s040p8",
|
146
|
+
attestation: "This is an example of a signed message.",
|
147
|
+
proof:
|
148
|
+
"J796FDv8f8w3syiaMSGoL6SAwPLRf6t13S+fYNjYA9EnJy3T0jZOY1eHBaGTBufOuW78FVFSwXKyUnrEjYOT9EU=",
|
149
|
+
wallet_provider: "Phantom",
|
148
150
|
};
|
149
151
|
|
150
|
-
|
152
|
+
it("should verify proof", async () => {
|
153
|
+
const result = await verifyProof(proof);
|
154
|
+
expect(result.status).toBe(ProofStatus.VERIFIED);
|
155
|
+
});
|
151
156
|
|
152
|
-
|
157
|
+
it("should fail if not invalid proof", async () => {
|
158
|
+
const result = await verifyProof({
|
159
|
+
...proof,
|
160
|
+
proof: "0x",
|
161
|
+
} as SignatureProof);
|
162
|
+
|
163
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
164
|
+
});
|
153
165
|
});
|
154
166
|
});
|
package/src/tests/solana.test.ts
CHANGED
@@ -5,7 +5,7 @@ import {
|
|
5
5
|
ProofStatus,
|
6
6
|
ProofTypes,
|
7
7
|
SignatureProof,
|
8
|
-
} from "@notabene/javascript-sdk
|
8
|
+
} from "@notabene/javascript-sdk";
|
9
9
|
import { verifySolanaSignature } from "../solana";
|
10
10
|
|
11
11
|
describe("verifySolanaSignature", () => {
|
@@ -25,6 +25,7 @@ describe("verifySolanaSignature", () => {
|
|
25
25
|
proof: Buffer.from(signature).toString("base64"),
|
26
26
|
wallet_provider: "Phantom",
|
27
27
|
};
|
28
|
+
|
28
29
|
const result = await verifySolanaSignature(proof);
|
29
30
|
expect(result.status).toBe(ProofStatus.VERIFIED);
|
30
31
|
});
|