@notabene/verify-proof 1.0.0-preview.4 → 1.0.0-preview.7
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +4 -4
- package/dist/bitcoin.d.ts +12 -0
- package/dist/eth.d.ts +2 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -92
- 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 +2 -0
- package/dist/tests/bitcoin.test.d.ts +1 -0
- package/dist/tests/eth.test.d.ts +1 -0
- package/dist/tests/index.test.d.ts +1 -0
- package/dist/tests/solana.test.d.ts +1 -0
- package/package.json +21 -4
- package/src/bitcoin.ts +166 -0
- package/src/eth.ts +22 -0
- package/src/index.ts +18 -130
- package/src/solana.ts +30 -0
- package/src/tests/bitcoin.test.ts +99 -0
- package/src/tests/eth.test.ts +60 -0
- package/src/{index.test.ts → tests/index.test.ts} +4 -4
- package/src/tests/solana.test.ts +61 -0
package/README.md
CHANGED
@@ -36,10 +36,10 @@ async function checkProof(proof: OwnershipProof) {
|
|
36
36
|
|
37
37
|
- Checkbox Confirmation (`ProofTypes.CheckboxConfirmation`)
|
38
38
|
- Screenshot (`ProofTypes.Screenshot`)
|
39
|
-
- Personal Sign EIP191 (`ProofTypes.
|
40
|
-
- Personal Sign EIP712 (`ProofTypes.
|
41
|
-
- Personal Sign BIP137 (`ProofTypes.
|
42
|
-
- Personal Sign XPUB (`ProofTypes.
|
39
|
+
- Personal Sign EIP191 (`ProofTypes.EIP191`)
|
40
|
+
- Personal Sign EIP712 (`ProofTypes.EIP712`)
|
41
|
+
- Personal Sign BIP137 (`ProofTypes.BIP137`)
|
42
|
+
- Personal Sign XPUB (`ProofTypes.XPUB`)
|
43
43
|
- Micro Transfer (`ProofTypes.MicroTransfer`)
|
44
44
|
|
45
45
|
## Development
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { SignatureProof } from "@notabene/javascript-sdk/src/types";
|
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
|
+
}
|
12
|
+
export declare function verifyBTCSignature(proof: SignatureProof): Promise<SignatureProof>;
|
package/dist/eth.d.ts
ADDED
package/dist/index.cjs
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
var e,r,
|
1
|
+
var e=require("@notabene/javascript-sdk/src/types"),r=require("bitcoinjs-message"),t=require("viem"),o=require("@solana/web3.js"),s=require("tweetnacl"),a=require("@stablelib/base64");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach(function(t){if("default"!==t){var o=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,o.get?o:{enumerable:!0,get:function(){return e[t]}})}}),r.default=e,r}var i,c=/*#__PURE__*/u(r),f=/*#__PURE__*/n(s);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 o in t)({}).hasOwnProperty.call(t,o)&&(e[o]=t[o])}return e},P.apply(null,arguments)}!function(e){e.LEGACY="Legacy",e.NATIVE="Native SegWit",e.SEGWIT="SegWit",e.P2SH_SEGWIT="p2sh",e.BCH="Bitcoin Cash",e.ETHEREUM="Ethereum",e.DOGECOIN="Dogecoin",e.UNKNOWN="Unknown"}(i||(i={})),exports.verifyProof=function(r){try{switch(r.type){case e.ProofTypes.SelfDeclaration:return Promise.resolve(P({},r,{status:r.confirmed?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}));case e.ProofTypes.Screenshot:return Promise.resolve(P({},r,{status:r.url?e.ProofStatus.FLAGGED:e.ProofStatus.FAILED}));case e.ProofTypes.EIP191:return Promise.resolve(function(r){try{var o=r.address.split(/:/),s=o[2];return"eip155"!==o[0]?Promise.resolve(P({},r,{status:e.ProofStatus.FAILED})):Promise.resolve(t.verifyMessage({address:s,message:r.attestation,signature:r.proof})).then(function(t){return P({},r,{status:t?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(/:/),s=t[2];if("solana"!==t[0])return Promise.resolve(P({},r,{status:e.ProofStatus.FAILED}));try{var n=new o.PublicKey(s),u=(new TextEncoder).encode(r.attestation),i=a.decode(r.proof),c=f.default.sign.detached.verify(u,i,n.toBytes());return Promise.resolve(P({},r,{status:c?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(t){return Promise.resolve(P({},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 t=r.address.split(/:/),o=t[2];if("bip122"!==t[0])return Promise.resolve(P({},r,{status:e.ProofStatus.FAILED}));try{var s=[i.SEGWIT,i.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return i.NATIVE;if(e.match("^[32M].*"))return i.SEGWIT;if(e.match("^[1nmL].*"))return i.LEGACY;if(e.match("^(D).*"))return i.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(o)),a=c.verify(r.attestation,o,r.proof,void 0,s);return Promise.resolve(P({},r,{status:a?e.ProofStatus.VERIFIED:e.ProofStatus.FAILED}))}catch(t){return Promise.resolve(P({},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/index.ts"],"sourcesContent":["import {
|
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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"}
|
package/dist/index.d.ts
CHANGED
@@ -1,93 +1,2 @@
|
|
1
|
-
|
2
|
-
export type CAIP10 = `${CAIP2}:${string}`;
|
3
|
-
export type CAIP19 = `${CAIP2}/${string}:${string}`;
|
4
|
-
export type CAIP220 = string;
|
5
|
-
export type DTI = string;
|
6
|
-
export type NotabeneAsset = string;
|
7
|
-
/**
|
8
|
-
* The asset of a transaction either a Notabene asset, a CAIP-19 asset, or a DTI.
|
9
|
-
*
|
10
|
-
* @public
|
11
|
-
*/
|
12
|
-
export type TransactionAsset = NotabeneAsset | CAIP19 | DTI;
|
13
|
-
export type BlockchainAddress = string;
|
14
|
-
export type TravelAddress = string;
|
15
|
-
/**
|
16
|
-
* The destination of a transaction either a blockchain address, a CAIP-19 address, or a travel address.
|
17
|
-
* @public
|
18
|
-
*/
|
19
|
-
export type Destination = BlockchainAddress | CAIP10 | TravelAddress;
|
20
|
-
export type Source = BlockchainAddress | CAIP10;
|
21
|
-
export type URI = string;
|
22
|
-
export type DID = `did:${string}:${string}`;
|
23
|
-
/**
|
24
|
-
* Status of the proof
|
25
|
-
* @public
|
26
|
-
*/
|
27
|
-
export declare enum ProofStatus {
|
28
|
-
PENDING = "pending",// Verification is pending
|
29
|
-
FAILED = "rejected",// Rejected
|
30
|
-
FLAGGED = "flagged",// Flagged for manual review
|
31
|
-
VERIFIED = "verified"
|
32
|
-
}
|
33
|
-
/**
|
34
|
-
* The type of Proofs supported
|
35
|
-
* @public
|
36
|
-
**/
|
37
|
-
export declare enum ProofTypes {
|
38
|
-
SelfDeclaration = "self-declaration",
|
39
|
-
PersonalSignEIP191 = "eip-191",
|
40
|
-
PersonalSignEIP712 = "eip-712",
|
41
|
-
PersonalSignBIP137 = "bip-137",
|
42
|
-
PersonalSignXPUB = "xpub",
|
43
|
-
MicroTransfer = "microtransfer",
|
44
|
-
Screenshot = "screenshot"
|
45
|
-
}
|
46
|
-
/**
|
47
|
-
* Ownership Proof
|
48
|
-
* @public
|
49
|
-
*/
|
50
|
-
export interface OwnershipProof {
|
51
|
-
type: ProofTypes;
|
52
|
-
status: ProofStatus;
|
53
|
-
did: DID;
|
54
|
-
address: CAIP10;
|
55
|
-
}
|
56
|
-
/**
|
57
|
-
* Ownership Proof using Message Signature
|
58
|
-
* @public
|
59
|
-
*/
|
60
|
-
export interface SignatureProof extends OwnershipProof {
|
61
|
-
type: ProofTypes.PersonalSignEIP191 | ProofTypes.PersonalSignEIP712 | ProofTypes.PersonalSignBIP137 | ProofTypes.PersonalSignXPUB;
|
62
|
-
proof: string;
|
63
|
-
attestation: string;
|
64
|
-
wallet_provider: string;
|
65
|
-
}
|
66
|
-
/**
|
67
|
-
* Ownership Proof using Self Declaration
|
68
|
-
* @public
|
69
|
-
*/
|
70
|
-
export interface DeclarationProof extends OwnershipProof {
|
71
|
-
type: ProofTypes.SelfDeclaration;
|
72
|
-
attestation: string;
|
73
|
-
confirmed: boolean;
|
74
|
-
}
|
75
|
-
/**
|
76
|
-
* Ownership Proof using Micro Transfer
|
77
|
-
* @public
|
78
|
-
*/
|
79
|
-
export interface MicroTransferProof extends OwnershipProof {
|
80
|
-
type: ProofTypes.MicroTransfer;
|
81
|
-
txhash: string;
|
82
|
-
chain: CAIP2;
|
83
|
-
amount: number;
|
84
|
-
}
|
85
|
-
/**
|
86
|
-
* Ownership Proof using Screenshot
|
87
|
-
* @public
|
88
|
-
*/
|
89
|
-
export interface ScreenshotProof extends OwnershipProof {
|
90
|
-
type: ProofTypes.Screenshot;
|
91
|
-
url: string;
|
92
|
-
}
|
1
|
+
import { type OwnershipProof } from "@notabene/javascript-sdk/src/types";
|
93
2
|
export declare function verifyProof(proof: OwnershipProof): Promise<OwnershipProof>;
|
package/dist/index.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
import{
|
1
|
+
import{ProofStatus as r,ProofTypes as e}from"@notabene/javascript-sdk/src/types";import*as t from"bitcoinjs-message";import{verifyMessage as s}from"viem";import{PublicKey as o}from"@solana/web3.js";import n from"tweetnacl";import{decode as a}from"@stablelib/base64";function i(){return i=Object.assign?Object.assign.bind():function(r){for(var e=1;e<arguments.length;e++){var t=arguments[e];for(var s in t)({}).hasOwnProperty.call(t,s)&&(r[s]=t[s])}return r},i.apply(null,arguments)}var c;!function(r){r.LEGACY="Legacy",r.NATIVE="Native SegWit",r.SEGWIT="SegWit",r.P2SH_SEGWIT="p2sh",r.BCH="Bitcoin Cash",r.ETHEREUM="Ethereum",r.DOGECOIN="Dogecoin",r.UNKNOWN="Unknown"}(c||(c={}));var u=function(u){try{switch(u.type){case e.SelfDeclaration:return Promise.resolve(i({},u,{status:u.confirmed?r.VERIFIED:r.FAILED}));case e.Screenshot:return Promise.resolve(i({},u,{status:u.url?r.FLAGGED:r.FAILED}));case e.EIP191:return Promise.resolve(function(e){try{var t=e.address.split(/:/),o=t[2];return"eip155"!==t[0]?Promise.resolve(i({},e,{status:r.FAILED})):Promise.resolve(s({address:o,message:e.attestation,signature:e.proof})).then(function(t){return i({},e,{status:t?r.VERIFIED:r.FAILED})})}catch(r){return Promise.reject(r)}}(u));case e.ED25519:return Promise.resolve(function(e){try{var t=e.address.split(/:/),s=t[2];if("solana"!==t[0])return Promise.resolve(i({},e,{status:r.FAILED}));try{var c=new o(s),u=(new TextEncoder).encode(e.attestation),m=a(e.proof),E=n.sign.detached.verify(u,m,c.toBytes());return Promise.resolve(i({},e,{status:E?r.VERIFIED:r.FAILED}))}catch(t){return Promise.resolve(i({},e,{status:r.FAILED}))}}catch(r){return Promise.reject(r)}}(u));case e.EIP712:case e.BIP137:return Promise.resolve(function(e){try{var s=e.address.split(/:/),o=s[2];if("bip122"!==s[0])return Promise.resolve(i({},e,{status:r.FAILED}));try{var n=[c.SEGWIT,c.NATIVE].includes(function(r){if(r.match("^(bc1|tb1|ltc1).*"))return c.NATIVE;if(r.match("^[32M].*"))return c.SEGWIT;if(r.match("^[1nmL].*"))return c.LEGACY;if(r.match("^(D).*"))return c.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(r).concat(" is not a valid or a supported address"))}(o)),a=t.verify(e.attestation,o,e.proof,void 0,n);return Promise.resolve(i({},e,{status:a?r.VERIFIED:r.FAILED}))}catch(t){return Promise.resolve(i({},e,{status:r.FAILED}))}}catch(r){return Promise.reject(r)}}(u))}return Promise.resolve(u)}catch(r){return Promise.reject(r)}};export{u as verifyProof};
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import {
|
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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"}
|
package/dist/index.modern.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
import{verifyMessage as e}from"viem";function
|
1
|
+
import{ProofStatus as t,ProofTypes as r}from"@notabene/javascript-sdk/src/types";import*as s from"bitcoinjs-message";import{verifyMessage as e}from"viem";import{PublicKey as n}from"@solana/web3.js";import a from"tweetnacl";import{decode as o}from"@stablelib/base64";function c(){return c=Object.assign?Object.assign.bind():function(t){for(var r=1;r<arguments.length;r++){var s=arguments[r];for(var e in s)({}).hasOwnProperty.call(s,e)&&(t[e]=s[e])}return t},c.apply(null,arguments)}var i;async function u(u){switch(u.type){case r.SelfDeclaration:return c({},u,{status:u.confirmed?t.VERIFIED:t.FAILED});case r.Screenshot:return c({},u,{status:u.url?t.FLAGGED:t.FAILED});case r.EIP191:return async function(r){const[s,n,a]=r.address.split(/:/);return c({},r,"eip155"!==s?{status:t.FAILED}:{status:await e({address:a,message:r.attestation,signature:r.proof})?t.VERIFIED:t.FAILED})}(u);case r.ED25519:return async function(r){const[s,e,i]=r.address.split(/:/);if("solana"!==s)return c({},r,{status:t.FAILED});try{const s=new n(i),e=(new TextEncoder).encode(r.attestation),u=o(r.proof);return c({},r,{status:a.sign.detached.verify(e,u,s.toBytes())?t.VERIFIED:t.FAILED})}catch(s){return c({},r,{status:t.FAILED})}}(u);case r.EIP712:case r.BIP137:return async function(r){const[e,n,a]=r.address.split(/:/);if("bip122"!==e)return c({},r,{status:t.FAILED});try{const e=[i.SEGWIT,i.NATIVE].includes(function(t){if(t.match("^(bc1|tb1|ltc1).*"))return i.NATIVE;if(t.match("^[32M].*"))return i.SEGWIT;if(t.match("^[1nmL].*"))return i.LEGACY;if(t.match("^(D).*"))return i.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(t).concat(" is not a valid or a supported address"))}(a));return c({},r,{status:s.verify(r.attestation,a,r.proof,void 0,e)?t.VERIFIED:t.FAILED})}catch(s){return c({},r,{status:t.FAILED})}}(u)}return u}!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"}(i||(i={}));export{u 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/index.ts"],"sourcesContent":["import {
|
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"}
|
package/dist/index.umd.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
!function(e,
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@notabene/javascript-sdk/src/types"),require("bitcoinjs-message"),require("viem"),require("@solana/web3.js"),require("tweetnacl"),require("@stablelib/base64")):"function"==typeof define&&define.amd?define(["exports","@notabene/javascript-sdk/src/types","bitcoinjs-message","viem","@solana/web3.js","tweetnacl","@stablelib/base64"],t):t((e||self).verifyProof={},e.types,e.bitcoinjsMessage,e.viem,e.web3_js,e.tweetnacl,e.base64)}(this,function(e,t,r,s,o,a,n){function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach(function(r){if("default"!==r){var s=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,s.get?s:{enumerable:!0,get:function(){return e[r]}})}}),t.default=e,t}var c,f=/*#__PURE__*/u(r),l=/*#__PURE__*/i(a);function P(){return P=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var s in r)({}).hasOwnProperty.call(r,s)&&(e[s]=r[s])}return e},P.apply(null,arguments)}!function(e){e.LEGACY="Legacy",e.NATIVE="Native SegWit",e.SEGWIT="SegWit",e.P2SH_SEGWIT="p2sh",e.BCH="Bitcoin Cash",e.ETHEREUM="Ethereum",e.DOGECOIN="Dogecoin",e.UNKNOWN="Unknown"}(c||(c={})),e.verifyProof=function(e){try{switch(e.type){case t.ProofTypes.SelfDeclaration:return Promise.resolve(P({},e,{status:e.confirmed?t.ProofStatus.VERIFIED:t.ProofStatus.FAILED}));case t.ProofTypes.Screenshot:return Promise.resolve(P({},e,{status:e.url?t.ProofStatus.FLAGGED:t.ProofStatus.FAILED}));case t.ProofTypes.EIP191:return Promise.resolve(function(e){try{var r=e.address.split(/:/),o=r[2];return"eip155"!==r[0]?Promise.resolve(P({},e,{status:t.ProofStatus.FAILED})):Promise.resolve(s.verifyMessage({address:o,message:e.attestation,signature:e.proof})).then(function(r){return P({},e,{status:r?t.ProofStatus.VERIFIED:t.ProofStatus.FAILED})})}catch(e){return Promise.reject(e)}}(e));case t.ProofTypes.ED25519:return Promise.resolve(function(e){try{var r=e.address.split(/:/),s=r[2];if("solana"!==r[0])return Promise.resolve(P({},e,{status:t.ProofStatus.FAILED}));try{var a=new o.PublicKey(s),i=(new TextEncoder).encode(e.attestation),u=n.decode(e.proof),c=l.default.sign.detached.verify(i,u,a.toBytes());return Promise.resolve(P({},e,{status:c?t.ProofStatus.VERIFIED:t.ProofStatus.FAILED}))}catch(r){return Promise.resolve(P({},e,{status:t.ProofStatus.FAILED}))}}catch(e){return Promise.reject(e)}}(e));case t.ProofTypes.EIP712:case t.ProofTypes.BIP137:return Promise.resolve(function(e){try{var r=e.address.split(/:/),s=r[2];if("bip122"!==r[0])return Promise.resolve(P({},e,{status:t.ProofStatus.FAILED}));try{var o=[c.SEGWIT,c.NATIVE].includes(function(e){if(e.match("^(bc1|tb1|ltc1).*"))return c.NATIVE;if(e.match("^[32M].*"))return c.SEGWIT;if(e.match("^[1nmL].*"))return c.LEGACY;if(e.match("^(D).*"))return c.DOGECOIN;throw new Error("INVALID ADDRESS: ".concat(e).concat(" is not a valid or a supported address"))}(s)),a=f.verify(e.attestation,s,e.proof,void 0,o);return Promise.resolve(P({},e,{status:a?t.ProofStatus.VERIFIED:t.ProofStatus.FAILED}))}catch(r){return Promise.resolve(P({},e,{status:t.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/index.ts"],"sourcesContent":["import {
|
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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"}
|
package/dist/solana.d.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
package/package.json
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
{
|
2
2
|
"name": "@notabene/verify-proof",
|
3
|
-
"version": "1.0.0-preview.
|
3
|
+
"version": "1.0.0-preview.7",
|
4
4
|
"description": "Verify ownership proofs",
|
5
5
|
"source": "src/index.ts",
|
6
6
|
"type": "module",
|
7
7
|
"module": "dist/index.js",
|
8
|
+
"types": "dist/index.d.ts",
|
8
9
|
"main": "dist/index.cjs",
|
9
10
|
"author": "Pelle Braendgaard",
|
10
11
|
"license": "Apache-2.0",
|
@@ -22,13 +23,29 @@
|
|
22
23
|
"test": "vitest"
|
23
24
|
},
|
24
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",
|
25
31
|
"eslint": "^9.9.0",
|
26
32
|
"microbundle": "^0.15.1",
|
33
|
+
"tiny-secp256k1": "^2.2.3",
|
27
34
|
"typescript": "^5.5.4",
|
28
|
-
"
|
35
|
+
"vite": "^5.4.11",
|
36
|
+
"vitest": "^2.0.5",
|
37
|
+
"bitcoinjs-message": "^2.2.0",
|
38
|
+
"ox": "^0.1.4"
|
29
39
|
},
|
30
40
|
"dependencies": {
|
31
|
-
"
|
32
|
-
"
|
41
|
+
"@bitauth/libauth": "^3.0.0",
|
42
|
+
"@notabene/javascript-sdk": "^2.0.2",
|
43
|
+
"@stablelib/base64": "^2.0.0",
|
44
|
+
"bech32": "^2.0.0",
|
45
|
+
"bigi": "^1.4.2",
|
46
|
+
"bs58": "^6.0.0",
|
47
|
+
"tweetnacl": "^1.0.3",
|
48
|
+
"varuint-bitcoin": "^2.0.0",
|
49
|
+
"viem": "^2.21.44"
|
33
50
|
}
|
34
51
|
}
|
package/src/bitcoin.ts
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
import {
|
2
|
+
ProofStatus,
|
3
|
+
SignatureProof,
|
4
|
+
} from "@notabene/javascript-sdk/src/types";
|
5
|
+
import { bech32 } from "bech32";
|
6
|
+
|
7
|
+
import {
|
8
|
+
secp256k1,
|
9
|
+
hash160,
|
10
|
+
hash256,
|
11
|
+
RecoveryId,
|
12
|
+
encodeBase58AddressFormat,
|
13
|
+
} from "@bitauth/libauth";
|
14
|
+
import { encode as encodeLength } from "varuint-bitcoin";
|
15
|
+
import { decode as decodeBase64 } from "@stablelib/base64";
|
16
|
+
|
17
|
+
enum SEGWIT_TYPES {
|
18
|
+
P2WPKH = "p2wpkh",
|
19
|
+
P2SH_P2WPKH = "p2sh(p2wpkh)",
|
20
|
+
}
|
21
|
+
|
22
|
+
const messagePrefix = "\u0018Bitcoin Signed Message:\n";
|
23
|
+
|
24
|
+
export enum DerivationMode {
|
25
|
+
LEGACY = "Legacy",
|
26
|
+
NATIVE = "Native SegWit",
|
27
|
+
SEGWIT = "SegWit",
|
28
|
+
P2SH_SEGWIT = "p2sh",
|
29
|
+
BCH = "Bitcoin Cash",
|
30
|
+
ETHEREUM = "Ethereum",
|
31
|
+
DOGECOIN = "Dogecoin",
|
32
|
+
UNKNOWN = "Unknown",
|
33
|
+
}
|
34
|
+
|
35
|
+
export async function verifyBTCSignature(
|
36
|
+
proof: SignatureProof,
|
37
|
+
): Promise<SignatureProof> {
|
38
|
+
const [ns, _, address] = proof.address.split(/:/);
|
39
|
+
if (ns !== "bip122") return { ...proof, status: ProofStatus.FAILED };
|
40
|
+
try {
|
41
|
+
// const messageToBeSigned = message.replace(/\s+/g, " ").trim();
|
42
|
+
const segwit = [DerivationMode.SEGWIT, DerivationMode.NATIVE].includes(
|
43
|
+
getDerivationMode(address),
|
44
|
+
);
|
45
|
+
const verified = verify(proof.attestation, address, proof.proof, segwit);
|
46
|
+
|
47
|
+
return {
|
48
|
+
...proof,
|
49
|
+
status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,
|
50
|
+
};
|
51
|
+
} catch (error) {
|
52
|
+
return { ...proof, status: ProofStatus.FAILED };
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
function getDerivationMode(address: string) {
|
57
|
+
if (address.match("^(bc1|tb1|ltc1).*")) {
|
58
|
+
return DerivationMode.NATIVE;
|
59
|
+
} else if (address.match("^[32M].*")) {
|
60
|
+
return DerivationMode.SEGWIT;
|
61
|
+
} else if (address.match("^[1nmL].*")) {
|
62
|
+
return DerivationMode.LEGACY;
|
63
|
+
} else if (address.match("^(D).*")) {
|
64
|
+
return DerivationMode.DOGECOIN;
|
65
|
+
} else {
|
66
|
+
throw new Error(
|
67
|
+
"INVALID ADDRESS: "
|
68
|
+
.concat(address)
|
69
|
+
.concat(" is not a valid or a supported address"),
|
70
|
+
);
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
type DecodedSignature = {
|
75
|
+
compressed: boolean;
|
76
|
+
segwitType?: SEGWIT_TYPES;
|
77
|
+
recovery: RecoveryId;
|
78
|
+
signature: Uint8Array;
|
79
|
+
};
|
80
|
+
function decodeSignature(proof: string): DecodedSignature {
|
81
|
+
const signature = decodeBase64(proof);
|
82
|
+
if (signature.length !== 65) throw new Error("Invalid signature length");
|
83
|
+
|
84
|
+
const flagByte = signature[0] - 27;
|
85
|
+
if (flagByte > 15 || flagByte < 0) {
|
86
|
+
throw new Error("Invalid signature parameter");
|
87
|
+
}
|
88
|
+
|
89
|
+
return {
|
90
|
+
compressed: !!(flagByte & 12),
|
91
|
+
segwitType: !(flagByte & 8)
|
92
|
+
? undefined
|
93
|
+
: !(flagByte & 4)
|
94
|
+
? SEGWIT_TYPES.P2SH_P2WPKH
|
95
|
+
: SEGWIT_TYPES.P2WPKH,
|
96
|
+
recovery: (flagByte & 3) as RecoveryId,
|
97
|
+
signature: signature.slice(1),
|
98
|
+
};
|
99
|
+
}
|
100
|
+
|
101
|
+
function verify(
|
102
|
+
attestation: string,
|
103
|
+
address: string,
|
104
|
+
proof: string,
|
105
|
+
checkSegwitAlways: boolean,
|
106
|
+
) {
|
107
|
+
const { compressed, segwitType, recovery, signature } =
|
108
|
+
decodeSignature(proof);
|
109
|
+
if (checkSegwitAlways && !compressed) {
|
110
|
+
throw new Error(
|
111
|
+
"checkSegwitAlways can only be used with a compressed pubkey signature flagbyte",
|
112
|
+
);
|
113
|
+
}
|
114
|
+
|
115
|
+
const hash = magicHash(attestation);
|
116
|
+
const publicKey: Uint8Array | string = compressed
|
117
|
+
? secp256k1.recoverPublicKeyCompressed(signature, recovery, hash)
|
118
|
+
: secp256k1.recoverPublicKeyUncompressed(signature, recovery, hash);
|
119
|
+
if (typeof publicKey === "string") throw new Error(publicKey);
|
120
|
+
const publicKeyHash = hash160(publicKey);
|
121
|
+
let actual: string = "";
|
122
|
+
|
123
|
+
if (segwitType) {
|
124
|
+
if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {
|
125
|
+
actual = encodeBech32Address(publicKeyHash);
|
126
|
+
} else {
|
127
|
+
// parsed.segwitType === SEGWIT_TYPES.P2WPKH
|
128
|
+
// must be true since we only return null, P2SH_P2WPKH, or P2WPKH
|
129
|
+
// from the decodeSignature function.
|
130
|
+
actual = encodeBech32Address(publicKeyHash);
|
131
|
+
}
|
132
|
+
} else {
|
133
|
+
if (checkSegwitAlways) {
|
134
|
+
try {
|
135
|
+
actual = encodeBech32Address(publicKeyHash);
|
136
|
+
// if address is bech32 it is not p2sh
|
137
|
+
} catch (e) {
|
138
|
+
actual = encodeBech32Address(publicKeyHash);
|
139
|
+
// base58 can be p2pkh or p2sh-p2wpkh
|
140
|
+
}
|
141
|
+
} else {
|
142
|
+
actual = encodeBase58AddressFormat(0, publicKeyHash);
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
return actual === address;
|
147
|
+
}
|
148
|
+
|
149
|
+
export function magicHash(attestation: string) {
|
150
|
+
const prefix = new TextEncoder().encode(messagePrefix);
|
151
|
+
const message = new TextEncoder().encode(attestation);
|
152
|
+
const length = encodeLength(message.length).buffer;
|
153
|
+
const buffer = new Uint8Array(
|
154
|
+
prefix.length + length.byteLength + message.length,
|
155
|
+
);
|
156
|
+
buffer.set(prefix);
|
157
|
+
buffer.set(new Uint8Array(length), prefix.length);
|
158
|
+
buffer.set(message, prefix.length + length.byteLength);
|
159
|
+
return hash256(buffer);
|
160
|
+
}
|
161
|
+
|
162
|
+
function encodeBech32Address(publicKeyHash: Uint8Array): string {
|
163
|
+
const bwords = bech32.toWords(publicKeyHash);
|
164
|
+
bwords.unshift(0);
|
165
|
+
return bech32.encode("bc", bwords);
|
166
|
+
}
|
package/src/eth.ts
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
import {
|
2
|
+
ProofStatus,
|
3
|
+
SignatureProof,
|
4
|
+
} from "@notabene/javascript-sdk/src/types";
|
5
|
+
import { verifyMessage } from "viem";
|
6
|
+
|
7
|
+
export async function verifyPersonalSignEIP191(
|
8
|
+
proof: SignatureProof,
|
9
|
+
): Promise<SignatureProof> {
|
10
|
+
const [ns, _, address] = proof.address.split(/:/);
|
11
|
+
if (ns !== "eip155") return { ...proof, status: ProofStatus.FAILED };
|
12
|
+
|
13
|
+
const verified = await verifyMessage({
|
14
|
+
address: address as `0x${string}`,
|
15
|
+
message: proof.attestation,
|
16
|
+
signature: proof.proof as `0x${string}`,
|
17
|
+
});
|
18
|
+
return {
|
19
|
+
...proof,
|
20
|
+
status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,
|
21
|
+
};
|
22
|
+
}
|
package/src/index.ts
CHANGED
@@ -1,112 +1,14 @@
|
|
1
|
-
import {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
* The asset of a transaction either a Notabene asset, a CAIP-19 asset, or a DTI.
|
13
|
-
*
|
14
|
-
* @public
|
15
|
-
*/
|
16
|
-
|
17
|
-
export type TransactionAsset = NotabeneAsset | CAIP19 | DTI;
|
18
|
-
|
19
|
-
export type BlockchainAddress = string;
|
20
|
-
export type TravelAddress = string;
|
21
|
-
|
22
|
-
/**
|
23
|
-
* The destination of a transaction either a blockchain address, a CAIP-19 address, or a travel address.
|
24
|
-
* @public
|
25
|
-
*/
|
26
|
-
export type Destination = BlockchainAddress | CAIP10 | TravelAddress;
|
27
|
-
export type Source = BlockchainAddress | CAIP10;
|
28
|
-
export type URI = string;
|
29
|
-
export type DID = `did:${string}:${string}`;
|
30
|
-
|
31
|
-
/**
|
32
|
-
* Status of the proof
|
33
|
-
* @public
|
34
|
-
*/
|
35
|
-
export enum ProofStatus {
|
36
|
-
PENDING = "pending", // Verification is pending
|
37
|
-
FAILED = "rejected", // Rejected
|
38
|
-
FLAGGED = "flagged", // Flagged for manual review
|
39
|
-
VERIFIED = "verified", // Verified
|
40
|
-
}
|
41
|
-
|
42
|
-
/**
|
43
|
-
* The type of Proofs supported
|
44
|
-
* @public
|
45
|
-
**/
|
46
|
-
export enum ProofTypes {
|
47
|
-
SelfDeclaration = "self-declaration",
|
48
|
-
PersonalSignEIP191 = "eip-191",
|
49
|
-
PersonalSignEIP712 = "eip-712",
|
50
|
-
PersonalSignBIP137 = "bip-137",
|
51
|
-
PersonalSignXPUB = "xpub",
|
52
|
-
MicroTransfer = "microtransfer",
|
53
|
-
Screenshot = "screenshot",
|
54
|
-
}
|
55
|
-
/**
|
56
|
-
* Ownership Proof
|
57
|
-
* @public
|
58
|
-
*/
|
59
|
-
export interface OwnershipProof {
|
60
|
-
type: ProofTypes;
|
61
|
-
status: ProofStatus;
|
62
|
-
did: DID;
|
63
|
-
address: CAIP10;
|
64
|
-
}
|
65
|
-
|
66
|
-
/**
|
67
|
-
* Ownership Proof using Message Signature
|
68
|
-
* @public
|
69
|
-
*/
|
70
|
-
export interface SignatureProof extends OwnershipProof {
|
71
|
-
type:
|
72
|
-
| ProofTypes.PersonalSignEIP191
|
73
|
-
| ProofTypes.PersonalSignEIP712
|
74
|
-
| ProofTypes.PersonalSignBIP137
|
75
|
-
| ProofTypes.PersonalSignXPUB;
|
76
|
-
proof: string;
|
77
|
-
attestation: string;
|
78
|
-
wallet_provider: string;
|
79
|
-
}
|
80
|
-
|
81
|
-
/**
|
82
|
-
* Ownership Proof using Self Declaration
|
83
|
-
* @public
|
84
|
-
*/
|
85
|
-
export interface DeclarationProof extends OwnershipProof {
|
86
|
-
type: ProofTypes.SelfDeclaration;
|
87
|
-
attestation: string;
|
88
|
-
confirmed: boolean;
|
89
|
-
}
|
90
|
-
|
91
|
-
/**
|
92
|
-
* Ownership Proof using Micro Transfer
|
93
|
-
* @public
|
94
|
-
*/
|
95
|
-
export interface MicroTransferProof extends OwnershipProof {
|
96
|
-
type: ProofTypes.MicroTransfer;
|
97
|
-
txhash: string;
|
98
|
-
chain: CAIP2;
|
99
|
-
amount: number;
|
100
|
-
}
|
101
|
-
|
102
|
-
/**
|
103
|
-
* Ownership Proof using Screenshot
|
104
|
-
* @public
|
105
|
-
*/
|
106
|
-
export interface ScreenshotProof extends OwnershipProof {
|
107
|
-
type: ProofTypes.Screenshot;
|
108
|
-
url: string;
|
109
|
-
}
|
1
|
+
import {
|
2
|
+
type OwnershipProof,
|
3
|
+
SignatureProof,
|
4
|
+
DeclarationProof,
|
5
|
+
ScreenshotProof,
|
6
|
+
ProofTypes,
|
7
|
+
ProofStatus,
|
8
|
+
} from "@notabene/javascript-sdk/src/types";
|
9
|
+
import { verifyBTCSignature } from "./bitcoin";
|
10
|
+
import { verifyPersonalSignEIP191 } from "./eth";
|
11
|
+
import { verifySolanaSignature } from "./solana";
|
110
12
|
|
111
13
|
export async function verifyProof(
|
112
14
|
proof: OwnershipProof,
|
@@ -126,29 +28,15 @@ export async function verifyProof(
|
|
126
28
|
? ProofStatus.FLAGGED
|
127
29
|
: ProofStatus.FAILED,
|
128
30
|
};
|
129
|
-
case ProofTypes.
|
31
|
+
case ProofTypes.EIP191:
|
130
32
|
return verifyPersonalSignEIP191(proof as SignatureProof);
|
131
|
-
case ProofTypes.
|
132
|
-
|
133
|
-
case ProofTypes.
|
33
|
+
case ProofTypes.ED25519:
|
34
|
+
return verifySolanaSignature(proof as SignatureProof);
|
35
|
+
case ProofTypes.EIP712:
|
36
|
+
case ProofTypes.BIP137:
|
37
|
+
return verifyBTCSignature(proof as SignatureProof);
|
38
|
+
case ProofTypes.BIP137_XPUB:
|
134
39
|
case ProofTypes.MicroTransfer:
|
135
40
|
}
|
136
41
|
return proof;
|
137
42
|
}
|
138
|
-
|
139
|
-
async function verifyPersonalSignEIP191(
|
140
|
-
proof: SignatureProof,
|
141
|
-
): Promise<SignatureProof> {
|
142
|
-
const [ns, _, address] = proof.address.split(/:/);
|
143
|
-
if (ns !== "eip155") return { ...proof, status: ProofStatus.FAILED };
|
144
|
-
|
145
|
-
const verified = await verifyMessage({
|
146
|
-
address: address as `0x${string}`,
|
147
|
-
message: proof.attestation,
|
148
|
-
signature: proof.proof as `0x${string}`,
|
149
|
-
});
|
150
|
-
return {
|
151
|
-
...proof,
|
152
|
-
status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,
|
153
|
-
};
|
154
|
-
}
|
package/src/solana.ts
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
import nacl from "tweetnacl";
|
2
|
+
import {
|
3
|
+
ProofStatus,
|
4
|
+
SignatureProof,
|
5
|
+
} from "@notabene/javascript-sdk/src/types";
|
6
|
+
import { decode as decodeBase64 } from "@stablelib/base64";
|
7
|
+
import bs58 from "bs58";
|
8
|
+
export async function verifySolanaSignature(
|
9
|
+
proof: SignatureProof,
|
10
|
+
): Promise<SignatureProof> {
|
11
|
+
const [ns, _, address] = proof.address.split(/:/);
|
12
|
+
if (ns !== "solana") return { ...proof, status: ProofStatus.FAILED };
|
13
|
+
try {
|
14
|
+
const publicKey = bs58.decode(address);
|
15
|
+
const messageBytes = new TextEncoder().encode(proof.attestation);
|
16
|
+
const signatureBytes = decodeBase64(proof.proof);
|
17
|
+
const verified = nacl.sign.detached.verify(
|
18
|
+
messageBytes,
|
19
|
+
signatureBytes,
|
20
|
+
publicKey,
|
21
|
+
);
|
22
|
+
|
23
|
+
return {
|
24
|
+
...proof,
|
25
|
+
status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,
|
26
|
+
};
|
27
|
+
} catch (error) {
|
28
|
+
return { ...proof, status: ProofStatus.FAILED };
|
29
|
+
}
|
30
|
+
}
|
@@ -0,0 +1,99 @@
|
|
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
|
+
|
6
|
+
import { verifyBTCSignature } from "../bitcoin";
|
7
|
+
import {
|
8
|
+
type SignatureProof,
|
9
|
+
ProofStatus,
|
10
|
+
ProofTypes,
|
11
|
+
} from "@notabene/javascript-sdk/src/types";
|
12
|
+
|
13
|
+
function rng() {
|
14
|
+
return Buffer.from("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");
|
15
|
+
}
|
16
|
+
|
17
|
+
function signMessage(
|
18
|
+
toAddress: (kp: bitcoin.ECPair) => string,
|
19
|
+
): SignatureProof {
|
20
|
+
const keyPair = bitcoin.ECPair.makeRandom({ rng: rng });
|
21
|
+
const address = toAddress(keyPair);
|
22
|
+
const sigOptions: bitcoinMessage.SignatureOptions | undefined =
|
23
|
+
address.startsWith("bc1") ? { segwitType: "p2wpkh" } : undefined;
|
24
|
+
const privateKey = keyPair.d.toBuffer(32);
|
25
|
+
var attestation = "This is an example of a signed message.";
|
26
|
+
|
27
|
+
var proof = bitcoinMessage
|
28
|
+
.sign(attestation, privateKey, keyPair.compressed, sigOptions)
|
29
|
+
.toString("base64");
|
30
|
+
// console.log("signMessage", { proof, address });
|
31
|
+
return {
|
32
|
+
type: ProofTypes.BIP137,
|
33
|
+
address: `bip122:000000000019d6689c085ae165831e93:${address}`,
|
34
|
+
did: `did:pkh:bip122:000000000019d6689c085ae165831e93:${address}`,
|
35
|
+
attestation,
|
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
|
+
}
|
55
|
+
|
56
|
+
describe("verifyBTCSignature", () => {
|
57
|
+
it("handles native segwit addresses", async () => {
|
58
|
+
const proof: SignatureProof = signSegWitMessage();
|
59
|
+
const result = await verifyBTCSignature(proof);
|
60
|
+
expect(result.status).toBe(ProofStatus.VERIFIED);
|
61
|
+
});
|
62
|
+
|
63
|
+
it("verifies legacy bitcoin address signature", async () => {
|
64
|
+
const proof: SignatureProof = signP2PKHMessage();
|
65
|
+
const result = await verifyBTCSignature(proof);
|
66
|
+
expect(result.status).toBe(ProofStatus.VERIFIED);
|
67
|
+
});
|
68
|
+
|
69
|
+
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
|
+
};
|
80
|
+
|
81
|
+
const result = await verifyBTCSignature(proof);
|
82
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
83
|
+
});
|
84
|
+
|
85
|
+
it("returns failed proof for non-BIP122 address", async () => {
|
86
|
+
const proof: SignatureProof = {
|
87
|
+
type: ProofTypes.EIP191,
|
88
|
+
status: ProofStatus.PENDING,
|
89
|
+
did: "did:example:123",
|
90
|
+
address: "eip155:1:0x1234567890123456789012345678901234567890",
|
91
|
+
proof: "0x1234567890",
|
92
|
+
attestation: "I own this address",
|
93
|
+
wallet_provider: "MetaMask",
|
94
|
+
};
|
95
|
+
|
96
|
+
const result = await verifyBTCSignature(proof);
|
97
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
98
|
+
});
|
99
|
+
});
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
2
|
+
import { verifyPersonalSignEIP191 } from "../eth";
|
3
|
+
import {
|
4
|
+
type SignatureProof,
|
5
|
+
ProofStatus,
|
6
|
+
ProofTypes,
|
7
|
+
} from "@notabene/javascript-sdk/src/types";
|
8
|
+
|
9
|
+
import { Hex, Address, PersonalMessage, Secp256k1, Signature } from "ox";
|
10
|
+
|
11
|
+
const privateKey = Secp256k1.randomPrivateKey();
|
12
|
+
const address = Address.fromPublicKey(Secp256k1.getPublicKey({ privateKey }));
|
13
|
+
|
14
|
+
function personalSign(): SignatureProof {
|
15
|
+
const attestation = "I agree";
|
16
|
+
const payload = PersonalMessage.getSignPayload(Hex.fromString(attestation));
|
17
|
+
const proof = Signature.toHex(Secp256k1.sign({ payload, privateKey }));
|
18
|
+
return {
|
19
|
+
type: ProofTypes.EIP191,
|
20
|
+
address: `eip155:1:${address}`,
|
21
|
+
did: `did:pkh:eip155:1:${address}`,
|
22
|
+
attestation,
|
23
|
+
proof,
|
24
|
+
status: ProofStatus.PENDING,
|
25
|
+
wallet_provider: "MetaMask",
|
26
|
+
};
|
27
|
+
}
|
28
|
+
|
29
|
+
describe("verifyPersonalSignEIP191", () => {
|
30
|
+
it("returns verified proof when valid message and address", async () => {
|
31
|
+
const proof = personalSign();
|
32
|
+
const result = await verifyPersonalSignEIP191(proof);
|
33
|
+
|
34
|
+
expect(result.status).toBe(ProofStatus.VERIFIED);
|
35
|
+
});
|
36
|
+
|
37
|
+
it("returns failed proof when invalid message or address", async () => {
|
38
|
+
const proof = { ...personalSign(), attestation: "evil text" };
|
39
|
+
const result = await verifyPersonalSignEIP191(proof);
|
40
|
+
|
41
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
42
|
+
});
|
43
|
+
|
44
|
+
it("returns failed proof for non-EIP155 address", async () => {
|
45
|
+
const proof: SignatureProof = {
|
46
|
+
type: ProofTypes.EIP191,
|
47
|
+
did: `did:pkh:bip122:000000000019d6689c085ae165831e93:128Lkh3S7CkDTBZ8W7BbpsN3YYizJMp8p6`,
|
48
|
+
wallet_provider: "metamask",
|
49
|
+
address:
|
50
|
+
"bip122:000000000019d6689c085ae165831e93:128Lkh3S7CkDTBZ8W7BbpsN3YYizJMp8p6",
|
51
|
+
attestation: "test message",
|
52
|
+
proof: "0xabcd",
|
53
|
+
status: ProofStatus.PENDING,
|
54
|
+
};
|
55
|
+
|
56
|
+
const result = await verifyPersonalSignEIP191(proof);
|
57
|
+
|
58
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
59
|
+
});
|
60
|
+
});
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { describe, it, expect, vi } from "vitest";
|
2
|
-
import { verifyProof } from "
|
2
|
+
import { verifyProof } from "../index";
|
3
3
|
import {
|
4
4
|
type DeclarationProof,
|
5
5
|
type ScreenshotProof,
|
@@ -89,7 +89,7 @@ describe("verifyProof", () => {
|
|
89
89
|
|
90
90
|
it("should verify a valid PersonalSignEIP191 proof", async () => {
|
91
91
|
const proof: SignatureProof = {
|
92
|
-
type: ProofTypes.
|
92
|
+
type: ProofTypes.EIP191,
|
93
93
|
status: ProofStatus.PENDING,
|
94
94
|
did: "did:example:123",
|
95
95
|
address: "eip155:1:0x1234567890123456789012345678901234567890",
|
@@ -113,7 +113,7 @@ describe("verifyProof", () => {
|
|
113
113
|
|
114
114
|
it("should fail an invalid PersonalSignEIP191 proof", async () => {
|
115
115
|
const proof: SignatureProof = {
|
116
|
-
type: ProofTypes.
|
116
|
+
type: ProofTypes.EIP191,
|
117
117
|
status: ProofStatus.PENDING,
|
118
118
|
did: "did:example:123",
|
119
119
|
address: "eip155:1:0x1234567890123456789012345678901234567890",
|
@@ -137,7 +137,7 @@ describe("verifyProof", () => {
|
|
137
137
|
|
138
138
|
it("should fail if not eip155 proof", async () => {
|
139
139
|
const proof: SignatureProof = {
|
140
|
-
type: ProofTypes.
|
140
|
+
type: ProofTypes.EIP191,
|
141
141
|
status: ProofStatus.PENDING,
|
142
142
|
did: "did:example:123",
|
143
143
|
address:
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
2
|
+
import bs58 from "bs58";
|
3
|
+
import nacl from "tweetnacl";
|
4
|
+
import {
|
5
|
+
ProofStatus,
|
6
|
+
ProofTypes,
|
7
|
+
SignatureProof,
|
8
|
+
} from "@notabene/javascript-sdk/src/types";
|
9
|
+
import { verifySolanaSignature } from "../solana";
|
10
|
+
|
11
|
+
describe("verifySolanaSignature", () => {
|
12
|
+
const keypair = nacl.sign.keyPair();
|
13
|
+
const address = bs58.encode(keypair.publicKey);
|
14
|
+
it("verifies valid Solana signature", async () => {
|
15
|
+
// Generate a test keypair
|
16
|
+
const message = "Test message";
|
17
|
+
const messageBytes = new TextEncoder().encode(message);
|
18
|
+
const signature = nacl.sign.detached(messageBytes, keypair.secretKey);
|
19
|
+
const proof: SignatureProof = {
|
20
|
+
type: ProofTypes.ED25519,
|
21
|
+
status: ProofStatus.PENDING,
|
22
|
+
did: `did:pkh:solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:${address}`,
|
23
|
+
address: `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:${address}`,
|
24
|
+
attestation: message,
|
25
|
+
proof: Buffer.from(signature).toString("base64"),
|
26
|
+
wallet_provider: "Phantom",
|
27
|
+
};
|
28
|
+
const result = await verifySolanaSignature(proof);
|
29
|
+
expect(result.status).toBe(ProofStatus.VERIFIED);
|
30
|
+
});
|
31
|
+
|
32
|
+
it("fails for invalid signature", async () => {
|
33
|
+
const proof: SignatureProof = {
|
34
|
+
type: ProofTypes.ED25519,
|
35
|
+
status: ProofStatus.PENDING,
|
36
|
+
did: `did:pkh:solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:${address}`,
|
37
|
+
address: `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:${address}`,
|
38
|
+
attestation: "Test message",
|
39
|
+
proof: "invalid_signature",
|
40
|
+
wallet_provider: "Phantom",
|
41
|
+
};
|
42
|
+
|
43
|
+
const result = await verifySolanaSignature(proof);
|
44
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
45
|
+
});
|
46
|
+
|
47
|
+
it("fails for non-Solana address", async () => {
|
48
|
+
const proof: SignatureProof = {
|
49
|
+
type: ProofTypes.ED25519,
|
50
|
+
status: ProofStatus.PENDING,
|
51
|
+
did: "did:pkh:eth:0x1234567890123456789012345678901234567890",
|
52
|
+
address: "eth:1:0x1234567890123456789012345678901234567890",
|
53
|
+
attestation: "Test message",
|
54
|
+
proof: "some_signature",
|
55
|
+
wallet_provider: "MetaMask",
|
56
|
+
};
|
57
|
+
|
58
|
+
const result = await verifySolanaSignature(proof);
|
59
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
60
|
+
});
|
61
|
+
});
|