bsv-bap 0.1.2 → 0.1.3

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.
@@ -0,0 +1,119 @@
1
+ import { PublicKey } from "@bsv/sdk";
2
+ import type { PrivateKey } from "@bsv/sdk";
3
+ import type { IdentityAttribute, IdentityAttributes } from "./interface";
4
+ declare abstract class BaseClass {
5
+ protected identityAttributes: IdentityAttributes;
6
+ /**
7
+ * Abstract method that must be implemented by derived classes to sign messages
8
+ * @param message - The message to sign
9
+ * @param signingPath - Optional signing path for HD wallets
10
+ * @returns Object containing address and signature
11
+ */
12
+ abstract signMessage(message: number[], signingPath?: string): {
13
+ address: string;
14
+ signature: string;
15
+ };
16
+ /**
17
+ * Abstract method that must be implemented by derived classes to get encryption key
18
+ */
19
+ abstract getEncryptionKey(): {
20
+ privKey: PrivateKey;
21
+ pubKey: PublicKey;
22
+ };
23
+ /**
24
+ * Encrypt the given string data with the identity encryption key
25
+ * @param stringData
26
+ * @param counterPartyPublicKey Optional public key of the counterparty
27
+ * @return string Base64
28
+ */
29
+ encrypt(stringData: string, counterPartyPublicKey?: string): string;
30
+ /**
31
+ * Decrypt the given ciphertext with the identity encryption key
32
+ * @param ciphertext
33
+ * @param counterPartyPublicKey Optional public key of the counterparty
34
+ */
35
+ decrypt(ciphertext: string, counterPartyPublicKey?: string): string;
36
+ /**
37
+ * Sign an op_return hex array with AIP
38
+ * Each implementation must handle its own signing path logic
39
+ * @param opReturn {array}
40
+ * @param signingPath {string}
41
+ * @return {number[]}
42
+ */
43
+ signOpReturnWithAIP(opReturn: number[][], signingPath?: string): number[][];
44
+ /**
45
+ * Returns all the attributes in the identity
46
+ * @returns {IdentityAttributes}
47
+ */
48
+ getAttributes(): IdentityAttributes;
49
+ /**
50
+ * Get the value of the given attribute
51
+ * @param attributeName
52
+ * @returns {IdentityAttribute | null}
53
+ */
54
+ getAttribute(attributeName: string): IdentityAttribute | null;
55
+ /**
56
+ * Set the value of the given attribute
57
+ * If an empty value ('' || null || false) is given, the attribute is removed from the ID
58
+ * @param attributeName string
59
+ * @param attributeValue any
60
+ */
61
+ setAttribute(attributeName: string, attributeValue: string | Record<string, string>): void;
62
+ /**
63
+ * Unset the given attribute from the ID
64
+ * @param attributeName
65
+ */
66
+ unsetAttribute(attributeName: string): void;
67
+ /**
68
+ * Add an attribute to this identity
69
+ * @param attributeName
70
+ * @param value
71
+ * @param nonce
72
+ */
73
+ addAttribute(attributeName: string, value: string, nonce?: string): void;
74
+ /**
75
+ * Get all attribute URNs for this ID
76
+ * @returns {string}
77
+ */
78
+ getAttributeUrns(): string;
79
+ /**
80
+ * Create and return the attribute URN for the given attribute
81
+ * @param attributeName
82
+ * @returns {string|null}
83
+ */
84
+ getAttributeUrn(attributeName: string): string | null;
85
+ /**
86
+ * Parse a text of URN string into identity attributes
87
+ * @param urnIdentityAttributes
88
+ */
89
+ protected parseStringUrns(urnIdentityAttributes: string): IdentityAttributes;
90
+ /**
91
+ * Helper function to parse identity attributes
92
+ * @param identityAttributes
93
+ * @returns {IdentityAttributes}
94
+ */
95
+ protected parseAttributes(identityAttributes: IdentityAttributes | string): IdentityAttributes;
96
+ /**
97
+ * Helper method to update an existing attribute
98
+ */
99
+ protected updateExistingAttribute(attributeName: string, attributeValue: string | Record<string, string>): void;
100
+ /**
101
+ * Helper method to create a new attribute
102
+ */
103
+ protected createNewAttribute(attributeName: string, attributeValue: string | Record<string, string>): void;
104
+ /**
105
+ * Construct an AIP buffer from the op return data
106
+ * @param opReturn
107
+ * @returns {number[]} Array of numbers representing the buffer
108
+ */
109
+ protected getAIPMessageBuffer(opReturn: number[][]): number[];
110
+ /**
111
+ * Helper method to format AIP output
112
+ * @param opReturn Original OP_RETURN data
113
+ * @param address Signing address
114
+ * @param signature Base64 signature
115
+ * @returns Formatted AIP output as number[]
116
+ */
117
+ protected formatAIPOutput(opReturnBuffers: number[][], address: string, signature: string): number[][];
118
+ }
119
+ export { BaseClass };
@@ -1,8 +1,10 @@
1
- import { type HD } from "@bsv/sdk";
1
+ import { PublicKey, type PrivateKey } from "@bsv/sdk";
2
+ import type { HD } from "@bsv/sdk";
2
3
  import { type APIFetcher } from "./api";
3
4
  import type { GetAttestationResponse, GetSigningKeysResponse } from "./apiTypes";
4
- import type { Identity, IdentityAttribute, IdentityAttributes, OldIdentity } from "./interface";
5
+ import type { Identity, IdentityAttributes, OldIdentity } from "./interface";
5
6
  import { MemberID, type MemberIdentity } from './MemberID';
7
+ import { BaseClass } from "./BaseClass";
6
8
  /**
7
9
  * MasterID class
8
10
  *
@@ -10,7 +12,7 @@ import { MemberID, type MemberIdentity } from './MemberID';
10
12
  *
11
13
  * @type {MasterID}
12
14
  */
13
- declare class MasterID {
15
+ declare class MasterID extends BaseClass {
14
16
  #private;
15
17
  idName: string;
16
18
  description: string;
@@ -47,59 +49,6 @@ declare class MasterID {
47
49
  * @returns {*|string}
48
50
  */
49
51
  getIdentityKey(): string;
50
- /**
51
- * Returns all the attributes in the identity
52
- *
53
- * @returns {*}
54
- */
55
- getAttributes(): IdentityAttributes;
56
- /**
57
- * Get the value of the given attribute
58
- *
59
- * @param attributeName
60
- * @returns {{}|null}
61
- */
62
- getAttribute(attributeName: string): IdentityAttribute | null;
63
- /**
64
- * Set the value of the given attribute
65
- *
66
- * If an empty value ('' || null || false) is given, the attribute is removed from the ID
67
- *
68
- * @param attributeName string
69
- * @param attributeValue any
70
- * @returns {{}|null}
71
- */
72
- setAttribute(attributeName: string, attributeValue: string | Record<string, string>): void;
73
- private updateExistingAttribute;
74
- private createNewAttribute;
75
- /**
76
- * Unset the given attribute from the ID
77
- *
78
- * @param attributeName
79
- * @returns {{}|null}
80
- */
81
- unsetAttribute(attributeName: string): void;
82
- /**
83
- * Get all attribute urn's for this id
84
- *
85
- * @returns {string}
86
- */
87
- getAttributeUrns(): string;
88
- /**
89
- * Create an return the attribute urn for the given attribute
90
- *
91
- * @param attributeName
92
- * @returns {string|null}
93
- */
94
- getAttributeUrn(attributeName: string): string | null;
95
- /**
96
- * Add an attribute to this identity
97
- *
98
- * @param attributeName
99
- * @param value
100
- * @param nonce
101
- */
102
- addAttribute(attributeName: string, value: string, nonce?: string): void;
103
52
  /**
104
53
  * This should be called with the last part of the signing path (/.../.../...)
105
54
  * This library assumes the first part is m/424150'/0'/0' as defined at the top of this file
@@ -143,13 +92,13 @@ declare class MasterID {
143
92
  *
144
93
  * @returns {[]}
145
94
  */
146
- getInitialIdTransaction(): string[];
95
+ getInitialIdTransaction(): number[][];
147
96
  /**
148
97
  * Get the OP_RETURN for the ID transaction of the current address / path
149
98
  *
150
99
  * @returns {[]}
151
100
  */
152
- getIdTransaction(previousPath?: string): string[];
101
+ getIdTransaction(previousPath?: string): number[][];
153
102
  /**
154
103
  * Get address for given path
155
104
  *
@@ -163,6 +112,20 @@ declare class MasterID {
163
112
  * @returns {*}
164
113
  */
165
114
  getCurrentAddress(): string;
115
+ /**
116
+ * Get the encryption key pair for this identity
117
+ */
118
+ getEncryptionKey(): {
119
+ privKey: PrivateKey;
120
+ pubKey: PublicKey;
121
+ };
122
+ /**
123
+ * Get the encryption key using type 42 (different key / incompatible with above)
124
+ */
125
+ getEncryptionKeyType42(): {
126
+ privKey: PrivateKey;
127
+ pubKey: PublicKey;
128
+ };
166
129
  /**
167
130
  * Get the public key for encrypting data for this identity
168
131
  */
@@ -220,7 +183,7 @@ declare class MasterID {
220
183
  * @param signingPath
221
184
  * @returns {{address: string, signature: string}}
222
185
  */
223
- signMessage(message: string | Buffer, signingPath?: string): {
186
+ signMessage(message: number[], signingPath?: string): {
224
187
  address: string;
225
188
  signature: string;
226
189
  };
@@ -244,16 +207,9 @@ declare class MasterID {
244
207
  * Sign an op_return hex array with AIP
245
208
  * @param opReturn {array}
246
209
  * @param signingPath {string}
247
- * @param outputType {string}
248
- * @return {[]}
249
- */
250
- signOpReturnWithAIP(opReturn: string[], signingPath?: string, outputType?: BufferEncoding): string[];
251
- /**
252
- * Construct an AIP buffer from the op return data
253
- * @param opReturn
254
- * @returns {Buffer}
210
+ * @return {number[]}
255
211
  */
256
- getAIPMessageBuffer(opReturn: string[]): Buffer;
212
+ signOpReturnWithAIP(opReturn: number[][], signingPath?: string): number[][];
257
213
  /**
258
214
  * Get all signing keys for this identity
259
215
  */
@@ -1,27 +1,38 @@
1
- import { PrivateKey } from "@bsv/sdk";
1
+ import { type PublicKey, PrivateKey } from "@bsv/sdk";
2
+ import { BaseClass } from "./BaseClass";
2
3
  import type { IdentityAttributes } from "./interface";
3
4
  export interface MemberIdentity {
4
5
  name: string;
5
6
  description: string;
6
7
  derivedPrivateKey: string;
7
8
  address: string;
8
- identityAttributes: IdentityAttributes;
9
+ identityAttributes?: IdentityAttributes;
9
10
  }
10
- declare class MemberID {
11
+ export declare class MemberID extends BaseClass {
11
12
  private key;
12
- identityAttributes: IdentityAttributes;
13
- address: string;
14
13
  idName: string;
15
14
  description: string;
16
- constructor(key: PrivateKey, identityAttributes?: IdentityAttributes | string);
17
- signMessage(message: string | Buffer): {
15
+ address: string;
16
+ constructor(key: PrivateKey, identityAttributes?: IdentityAttributes);
17
+ signMessage(message: number[], _signingPath?: string): {
18
18
  address: string;
19
19
  signature: string;
20
20
  };
21
+ signOpReturnWithAIP(opReturn: number[][], _signingPath?: string): number[][];
21
22
  getPublicKey(): string;
22
23
  import(identity: MemberIdentity): void;
23
- static fromImport(identity: MemberIdentity): MemberID;
24
+ static fromBackup(identity: MemberIdentity): MemberID;
24
25
  export(): MemberIdentity;
25
- private parseStringUrns;
26
+ /**
27
+ * Get the encryption key pair for this identity
28
+ * We use the same key for both signing and encryption for simplicity
29
+ */
30
+ getEncryptionKey(): {
31
+ privKey: PrivateKey;
32
+ pubKey: PublicKey;
33
+ };
34
+ /**
35
+ * Get the public key for encrypting data for this identity
36
+ */
37
+ getEncryptionPublicKey(): string;
26
38
  }
27
- export { MemberID };
package/dist/index.d.ts CHANGED
@@ -147,7 +147,7 @@ export declare class BAP {
147
147
  * @param dataString Optional data string that will be appended to the BAP attestation
148
148
  * @returns {string[]}
149
149
  */
150
- signAttestationWithAIP(attestationHash: string, identityKey: string, counter?: number, dataString?: string): string[];
150
+ signAttestationWithAIP(attestationHash: string, identityKey: string, counter?: number, dataString?: string): number[][];
151
151
  /**
152
152
  * Verify an AIP signed attestation for a user
153
153
  *
@@ -167,7 +167,7 @@ export declare class BAP {
167
167
  * @param tx Array of hex values for the OP_RETURN values
168
168
  * @returns {{}}
169
169
  */
170
- verifyAttestationWithAIP(tx: string[]): Attestation;
170
+ verifyAttestationWithAIP(tx: number[][]): Attestation;
171
171
  /**
172
172
  * For BAP attestations we use all fields for the attestation
173
173
  *
@@ -176,28 +176,28 @@ export declare class BAP {
176
176
  * @param address
177
177
  * @param signature
178
178
  * @param dataString Optional data string that will be appended to the BAP attestation
179
- * @returns {[string]}
179
+ * @returns {number[]}
180
180
  */
181
- createAttestationTransaction(attestationHash: string, counter: number, address: string, signature: string, dataString?: string): string[];
181
+ createAttestationTransaction(attestationHash: string, counter: number, address: string, signature: string, dataString?: string): number[][];
182
182
  /**
183
183
  * This is a re-creation of how the bitcoinfiles-sdk creates a hash to sign for AIP
184
184
  *
185
185
  * @param attestationHash
186
186
  * @param counter
187
187
  * @param dataString Optional data string
188
- * @returns {Buffer}
188
+ * @returns {number[]}
189
189
  */
190
- getAttestationBuffer(attestationHash: string, counter?: number, dataString?: string): Buffer;
190
+ getAttestationBuffer(attestationHash: string, counter?: number, dataString?: string): number[];
191
191
  /**
192
192
  * Verify that the identity challenge is signed by the address
193
193
  *
194
- * @param message Buffer or utf-8 string
194
+ * @param message Buffer, number[] or utf-8 string
195
195
  * @param address Bitcoin address of signee
196
196
  * @param signature Signature base64 string
197
197
  *
198
198
  * @return boolean
199
199
  */
200
- verifySignature(message: string | Buffer, address: string, signature: string): boolean;
200
+ verifySignature(message: string | number[], address: string, signature: string): boolean;
201
201
  /**
202
202
  * Check whether the given transaction (BAP OP_RETURN) is valid, is signed and that the
203
203
  * identity signing is also valid at the time of signing
@@ -217,7 +217,7 @@ export declare class BAP {
217
217
  * @param tx
218
218
  * @returns {Promise<boolean|*>}
219
219
  */
220
- isValidAttestationTransaction(tx: string[]): Promise<AttestationValidResponse | false>;
220
+ isValidAttestationTransaction(tx: number[][]): Promise<AttestationValidResponse | false>;
221
221
  /**
222
222
  * Get all signing keys for the given idKey
223
223
  *
@@ -1,8 +1,8 @@
1
1
  // @bun
2
- import{BSM as N,BigNumber as n,ECIES as d,HD as s,Signature as r}from"@bsv/sdk";import{Utils as i}from"@bsv/sdk";var l=async(j,$,J,q)=>{let Q=`${J}${j}`;return(await fetch(Q,{method:"post",headers:{"Content-type":"application/json; charset=utf-8",token:q,format:"json"},body:JSON.stringify($)})).json()},R=(j,$)=>async(J,q)=>{return l(J,q,j,$)};var Y="1BAPSuaPnfGnSBM3GLV9yhxUdYe4vGbdMT",H=`0x${Buffer.from("1BAPSuaPnfGnSBM3GLV9yhxUdYe4vGbdMT").toString("hex")}`,x="15PciHG22SNLQJXMoSUaWVi7WSqc7hCfva",qj=`0x${Buffer.from("15PciHG22SNLQJXMoSUaWVi7WSqc7hCfva").toString("hex")}`,V="https://api.sigmaidentity.com/v1",F=2147483647,C="m/424150'/0'/0'",G="m/424150'/2147483647'/2147483647'";import{BSM as M,Utils as h,BigNumber as D,ECIES as y,Hash as X,PublicKey as _}from"@bsv/sdk";import{randomBytes as b}from"crypto";var W={hexEncode(j){return`0x${Buffer.from(j).toString("hex")}`},hexDecode(j,$="utf8"){return Buffer.from(j.replace("0x",""),"hex").toString($)},getRandomString(j=32){return b(j).toString("hex")},isHex(j){if(typeof j!=="string")return!1;return/^[0-9a-fA-F]+$/.test(j)},getSigningPathFromHex(j,$=!0){let J="m",q=j.match(/.{1,8}/g);if(!q)throw new Error("Invalid hex string");let Q=2147483647;for(let z of q){let Z=Number(`0x${z}`);if(Z>Q)Z-=Q;J+=`/${Z}${$?"'":""}`}return J},getNextIdentityPath(j){let $=j.split("/"),J=$[$.length-2],q=!1;if(J.match("'"))q=!0;let Q=(Number(J.replace(/[^0-9]/g,""))+1).toString();return $[$.length-2]=Q+(q?"'":""),$[$.length-1]=`0${q?"'":""}`,$.join("/")},getNextPath(j){let $=j.split("/"),J=$[$.length-1],q=!1;if(J.match("'"))q=!0;let Q=(Number(J.replace(/[^0-9]/g,""))+1).toString();return $[$.length-1]=Q+(q?"'":""),$.join("/")}};import{BSM as T,BigNumber as p,PrivateKey as S,Utils as P}from"@bsv/sdk";var{toHex:wj,toBase58:Yj,toArray:B}=P,{magicHash:o}=T;class f{key;identityAttributes;address;idName;description;constructor(j,$={}){this.key=j,this.identityAttributes=typeof $==="string"?this.parseStringUrns($):$,this.address=this.key.toAddress(),this.idName="Member ID 1",this.description=""}signMessage(j){let $=typeof j==="string"?Buffer.from(j):j,J=this.key,q=J.toPublicKey().toString(),Q=T.sign(B($),J,"raw"),z=new p(o(B($,"utf8"))),Z=Q.CalculateRecoveryFactor(J.toPublicKey(),z),L=T.sign(B($),J,"raw").toCompact(Z,!0,"base64");return{address:q,signature:L}}getPublicKey(){return this.key.toPublicKey().toString()}import(j){this.idName=j.name,this.description=j.description,this.key=S.fromString(j.derivedPrivateKey),this.address=this.key.toAddress(),this.identityAttributes=j.identityAttributes}static fromImport(j){let $=new f(S.fromString(j.derivedPrivateKey));return $.import(j),$}export(){return{name:this.idName,description:this.description,derivedPrivateKey:this.key.toString(),address:this.address,identityAttributes:this.identityAttributes}}parseStringUrns(j){let $={},J=j.replace(/^[ \t]+/gm,"").trim().split(`
3
- `);for(let q of J){let Q=q.split(":");if(Q.length>=6&&Q[0]==="urn"&&Q[1]==="bap"&&Q[2]==="id")$[Q[3]]={value:Q[4],nonce:Q[5]}}return $}}var{toArray:w,toHex:O,toBase58:u,toUTF8:I,toBase64:A}=h,{electrumDecrypt:K,electrumEncrypt:g}=y,{magicHash:m}=M;class U{#j;#J=V;#Q="";#$;#q;#z;#W;idName;description;rootAddress;identityKey;identityAttributes;getApiData;constructor(j,$={},J=""){if(this.#W=J,J){let z=O(X.sha256(J,"utf8")),Z=W.getSigningPathFromHex(z);this.#j=j.derive(Z)}else this.#j=j;this.idName="ID 1",this.description="",this.#$=`${C}/0/0/0`,this.#q=`${C}/0/0/0`,this.#z=`${C}/0/0/1`;let q=this.#j.derive(this.#$);this.rootAddress=q.privKey.toPublicKey().toAddress(),this.identityKey=this.deriveIdentityKey(this.rootAddress);let Q={...$};this.identityAttributes=this.parseAttributes(Q),this.getApiData=R(this.#J,this.#Q)}set BAP_SERVER(j){this.#J=j}get BAP_SERVER(){return this.#J}set BAP_TOKEN(j){this.#Q=j}get BAP_TOKEN(){return this.#Q}deriveIdentityKey(j){let $=O(X.sha256(j,"utf8"));return u(X.ripemd160($,"hex"))}parseAttributes(j){if(typeof j==="string")return this.parseStringUrns(j);for(let $ in j)if(!j[$].value||!j[$].nonce)throw new Error("Invalid identity attribute");return j||{}}parseStringUrns(j){let $={},J=j.replace(/^\s+/g,"").replace(/\r/gm,"").split(`
4
- `);for(let q of J){let z=q.replace(/^\s+/g,"").replace(/\s+$/g,"").split(":");if(z[0]==="urn"&&z[1]==="bap"&&z[2]==="id"&&z[3]&&z[4]&&z[5])$[z[3]]={value:z[4],nonce:z[5]}}return $}getIdentityKey(){return this.identityKey}getAttributes(){return this.identityAttributes}getAttribute(j){if(this.identityAttributes[j])return this.identityAttributes[j];return null}setAttribute(j,$){if(!$)return;if(this.identityAttributes[j])this.updateExistingAttribute(j,$);else this.createNewAttribute(j,$)}updateExistingAttribute(j,$){if(typeof $==="string"){this.identityAttributes[j].value=$;return}if(this.identityAttributes[j].value=$.value||"",$.nonce)this.identityAttributes[j].nonce=$.nonce}createNewAttribute(j,$){if(typeof $==="string"){this.addAttribute(j,$);return}this.addAttribute(j,$.value||"",$.nonce)}unsetAttribute(j){delete this.identityAttributes[j]}getAttributeUrns(){let j="";for(let $ in this.identityAttributes){let J=this.getAttributeUrn($);if(J)j+=`${J}
5
- `}return j}getAttributeUrn(j){let $=this.identityAttributes[j];if($)return`urn:bap:id:${j}:${$.value}:${$.nonce}`;return null}addAttribute(j,$,J=""){let q=J;if(!J)q=W.getRandomString();this.identityAttributes[j]={value:$,nonce:q}}set rootPath(j){if(this.#j){let $=j;if(j.split("/").length<5)$=`${C}${j}`;if(!this.validatePath($))throw new Error(`invalid signing path given ${$}`);this.#$=$;let J=this.#j.derive($);this.rootAddress=J.pubKey.toAddress(),this.identityKey=this.deriveIdentityKey(this.rootAddress),this.#q=$,this.#z=$}}get rootPath(){return this.#$}getRootPath(){return this.#$}set currentPath(j){let $=j;if(j.split("/").length<5)$=`${C}${j}`;if(!this.validatePath($))throw new Error("invalid signing path given");this.#q=this.#z,this.#z=$}get currentPath(){return this.#z}get previousPath(){return this.#q}get idSeed(){return this.#W}incrementPath(){this.currentPath=W.getNextPath(this.currentPath)}validatePath(j){if(j.match(/\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?/)){let $=j.split("/");if($.length===7&&Number($[1].replace("'",""))<=F&&Number($[2].replace("'",""))<=F&&Number($[3].replace("'",""))<=F&&Number($[4].replace("'",""))<=F&&Number($[5].replace("'",""))<=F&&Number($[6].replace("'",""))<=F)return!0}return!1}getInitialIdTransaction(){return this.getIdTransaction(this.#$)}getIdTransaction(j=""){if(this.#z===this.#$)throw new Error("Current path equals rootPath. ID was probably not initialized properly");let $=[Buffer.from(Y).toString("hex"),Buffer.from("ID").toString("hex"),Buffer.from(this.identityKey).toString("hex"),Buffer.from(this.getCurrentAddress()).toString("hex")];return this.signOpReturnWithAIP($,j||this.#q)}getAddress(j){return this.#j.derive(j).privKey.toPublicKey().toAddress()}getCurrentAddress(){return this.getAddress(this.#z)}getEncryptionPublicKey(){return this.#j.derive(this.#$).derive(G).privKey.toPublicKey().toString()}getEncryptionPublicKeyWithSeed(j){return this.getEncryptionPrivateKeyWithSeed(j).toPublicKey().toString("hex")}encrypt(j,$){let Q=this.#j.derive(this.#$).derive(G).privKey.toPublicKey(),z=$?_.fromString($):Q;return A(g(w(j),z,null))}decrypt(j,$){let q=this.#j.derive(this.#$).derive(G).privKey,Q=void 0;if($)Q=_.fromString($);return I(K(w(j,"base64"),q,Q))}encryptWithSeed(j,$,J){let q=this.getEncryptionPrivateKeyWithSeed($),Q=q.toPublicKey(),z=J?_.fromString(J):Q;return A(g(w(j),z,q))}decryptWithSeed(j,$,J){let q=this.getEncryptionPrivateKeyWithSeed($),Q=void 0;if(J)Q=_.fromString(J);return I(K(w(j,"base64"),q,Q))}getEncryptionPrivateKeyWithSeed(j){let $=O(X.sha256(j,"utf8")),J=W.getSigningPathFromHex($);return this.#j.derive(this.#$).derive(J).privKey}getAttestation(j){let $=X.sha256(j,"utf8");return`bap:attest:${O($)}:${this.getIdentityKey()}`}getAttestationHash(j){let $=this.getAttributeUrn(j);if(!$)return null;let J=this.getAttestation($),q=X.sha256(J,"utf8");return O(q)}signMessage(j,$=""){let J;if(!(j instanceof Buffer))J=Buffer.from(j);else J=j;let q=$||this.#z,Q=this.#j.derive(q).privKey,z=Q.toAddress(),Z=M.sign(w(j),Q,"raw"),L=new D(m(w(j,"utf8"))),k=Z.CalculateRecoveryFactor(Q.toPublicKey(),L),E=M.sign(w(J),Q,"raw").toCompact(k,!0,"base64");return{address:z,signature:E}}signMessageWithSeed(j,$){let J=O(X.sha256($,"utf8")),q=W.getSigningPathFromHex(J),z=this.#j.derive(this.#$).derive(q),Z=z.privKey.toPublicKey().toAddress(),L=M.sign(w(j),z.privKey,"raw"),k=new D(m(w(j,"utf8"))),E=L.CalculateRecoveryFactor(z.privKey.toPublicKey(),k),c=M.sign(w(Buffer.from(j)),z.privKey,"raw").toCompact(E,!0,"base64");return{address:Z,signature:c}}signOpReturnWithAIP(j,$="",J="hex"){let q=this.getAIPMessageBuffer(j),{address:Q,signature:z}=this.signMessage(q,$);return j.concat([Buffer.from("|").toString(J),Buffer.from(x).toString(J),Buffer.from("BITCOIN_ECDSA").toString(J),Buffer.from(Q).toString(J),Buffer.from(z,"base64").toString(J)])}getAIPMessageBuffer(j){let $=[];if(j[0].replace("0x","")!=="6a")$.push(Buffer.from("6a","hex"));for(let J of j)$.push(Buffer.from(J.replace("0x",""),"hex"));return $.push(Buffer.from("|")),Buffer.concat([...$])}async getIdSigningKeys(){let j=await this.getApiData("/signing-keys",{idKey:this.identityKey});return console.log("getIdSigningKeys",j),j}async getAttributeAttestations(j){let $=this.getAttestationHash(j),J=await this.getApiData("/attestation/get",{hash:$});return console.log("getAttestations",j,$,J),J}import(j){this.idName=j.name,this.description=j.description||"",this.identityKey=j.identityKey,this.#$=j.rootPath,this.rootAddress=j.rootAddress,this.#q=j.previousPath,this.#z=j.currentPath,this.#W=("idSeed"in j?j.idSeed:"")||"",this.identityAttributes=this.parseAttributes(j.identityAttributes)}export(){return{name:this.idName,description:this.description,identityKey:this.identityKey,rootPath:this.#$,rootAddress:this.rootAddress,previousPath:this.#q,currentPath:this.#z,idSeed:this.#W,identityAttributes:this.getAttributes(),lastIdPath:""}}exportMemberBackup(){let j=this.#j.derive(this.#z).privKey;return{name:this.idName,description:this.description,derivedPrivateKey:j.toString(),address:j.toPublicKey().toAddress(),identityAttributes:this.getAttributes()}}newId(){this.incrementPath();let j=this.#j.derive(this.#z).privKey;return new f(j,this.getAttributes())}}var{toArray:v,toUTF8:a,toBase64:e}=i,{electrumEncrypt:t,electrumDecrypt:jj}=d;class $j{#j;#J={};#Q=V;#$="";#q="";getApiData;constructor(j,$="",J=""){if(!j)throw new Error("No HDPrivateKey given");if(this.#j=s.fromString(j),$)this.#$=$;if(J)this.#Q=J;this.getApiData=R(this.#Q,this.#$)}get lastIdPath(){return this.#q}getPublicKey(j=""){if(j)return this.#j.derive(j).pubKey.toString();return this.#j.pubKey.toString()}getHdPublicKey(j=""){if(j)return this.#j.derive(j).toPublic().toString();return this.#j.toPublic().toString()}set BAP_SERVER(j){this.#Q=j;for(let $ in this.#J)this.#J[$].BAP_SERVER=j}get BAP_SERVER(){return this.#Q}set BAP_TOKEN(j){this.#$=j;for(let $ in this.#J)this.#J[$].BAP_TOKEN=j}get BAP_TOKEN(){return this.#$}checkIdBelongs(j){if(this.#j.derive(j.rootPath).pubKey.toAddress()!==j.rootAddress)throw new Error("ID does not belong to this private key");return!0}listIds(){return Object.keys(this.#J)}newId(j,$={},J=""){let q;if(!j)q=this.getNextValidPath();else q=j;let Q=new U(this.#j,$,J);Q.BAP_SERVER=this.#Q,Q.BAP_TOKEN=this.#$,Q.rootPath=q,Q.currentPath=W.getNextPath(q);let z=Q.getIdentityKey();return this.#J[z]=Q,this.#q=q,this.#J[z]}removeId(j){delete this.#J[j]}getNextValidPath(){if(this.#q)return W.getNextIdentityPath(this.#q);return`/0'/${Object.keys(this.#J).length}'/0'`}getId(j){return this.#J[j]||null}setId(j){this.checkIdBelongs(j),this.#J[j.getIdentityKey()]=j}importIds(j,$=!0){if($&&typeof j==="string"){this.importEncryptedIds(j);return}let J=j;if(!J.lastIdPath)throw new Error("ID cannot be imported as it is not complete");if(!J.ids)throw new Error(`ID data is not in the correct format: ${j}`);let q=j.lastIdPath;for(let Q of J.ids){if(!Q.identityKey||!Q.identityAttributes||!Q.rootAddress)throw new Error("ID cannot be imported as it is not complete");let z=new U(this.#j,{},Q.idSeed);if(z.BAP_SERVER=this.#Q,z.BAP_TOKEN=this.#$,z.import(Q),q==="")q=z.currentPath;this.checkIdBelongs(z),this.#J[z.getIdentityKey()]=z}this.#q=q}importEncryptedIds(j){let $=this.decrypt(j),J=JSON.parse($);if(Array.isArray(J)){console.log(`Importing old format:
6
- `,J),this.importOldIds(J);return}if(typeof J!=="object")throw new Error("decrypted, but found unrecognized identities format");this.importIds(J,!1)}importOldIds(j){for(let $ of j){let J=new U(this.#j,{},$.idSeed??"");J.BAP_SERVER=this.#Q,J.BAP_TOKEN=this.#$,J.import($),this.checkIdBelongs(J),this.#J[J.getIdentityKey()]=J,this.#q=J.currentPath}}exportIds(j,$=!0){let J={lastIdPath:this.#q,ids:[]},q=j||Object.keys(this.#J);for(let Q of q){if(!this.#J[Q])throw new Error(`Identity ${Q} not found`);J.ids.push(this.#J[Q].export())}if($)return this.encrypt(JSON.stringify(J));return J}exportId(j,$=!0){let J={lastIdPath:this.#q,ids:[]};if(J.ids.push(this.#J[j].export()),$)return this.encrypt(JSON.stringify(J));return J}encrypt(j){let $=this.#j.derive(G);return e(t(v(j),$.pubKey,null))}decrypt(j){let $=this.#j.derive(G);return a(jj(v(j,"base64"),$.privKey))}signAttestationWithAIP(j,$,J=0,q=""){let Q=this.getId($);if(!Q)throw new Error("Could not find identity to attest with");let z=this.getAttestationBuffer(j,J,q),{address:Z,signature:L}=Q.signMessage(z);return this.createAttestationTransaction(j,J,Z,L,q)}verifyAttestationWithAIP(j){if(!Array.isArray(j)||j[0]!=="0x6a"||j[1]!==H)throw new Error("Not a valid BAP transaction");let $=j[7]==="0x44415441"?5:0,J={type:W.hexDecode(j[2]),hash:W.hexDecode(j[3]),sequence:W.hexDecode(j[4]),signingProtocol:W.hexDecode(j[7+$]),signingAddress:W.hexDecode(j[8+$]),signature:W.hexDecode(j[9+$],"base64")};if($&&j[3]===j[8])J.data=W.hexDecode(j[9]);try{let q=[];for(let z=0;z<6+$;z++)q.push(Buffer.from(j[z].replace("0x",""),"hex"));let Q=Buffer.concat(q);J.verified=this.verifySignature(Q,J.signingAddress,J.signature)}catch(q){J.verified=!1}return J}createAttestationTransaction(j,$,J,q,Q=""){let z=["0x6a",W.hexEncode(Y)];if(z.push(W.hexEncode("ATTEST")),z.push(W.hexEncode(j)),z.push(W.hexEncode(`${$}`)),z.push("0x7c"),Q)z.push(W.hexEncode(Y)),z.push(W.hexEncode("DATA")),z.push(W.hexEncode(j)),z.push(W.hexEncode(Q)),z.push("0x7c");return z.push(W.hexEncode(x)),z.push(W.hexEncode("BITCOIN_ECDSA")),z.push(W.hexEncode(J)),z.push(`0x${Buffer.from(q,"base64").toString("hex")}`),z}getAttestationBuffer(j,$=0,J=""){let q=Buffer.from("");if(J)q=Buffer.concat([Buffer.from(Y),Buffer.from("DATA"),Buffer.from(j),Buffer.from(J),Buffer.from("7c","hex")]);return Buffer.concat([Buffer.from("6a","hex"),Buffer.from(Y),Buffer.from("ATTEST"),Buffer.from(j),Buffer.from(`${$}`),Buffer.from("7c","hex"),q])}verifySignature(j,$,J){let q=Buffer.isBuffer(j)?j:Buffer.from(j),Q=r.fromCompact(J,"base64"),z,Z=v(q.toString("hex"),"hex");for(let L=0;L<4;L++)try{if(z=Q.RecoverPublicKey(L,new n(N.magicHash(Z))),N.verify(Z,Q,z)&&z.toAddress()===$)return!0}catch(k){}return!1}async verifyChallengeSignature(j,$,J,q){if(!this.verifySignature(J,$,q))return!1;try{let z=await this.getApiData("/attestation/valid",{idKey:j,address:$,challenge:J,signature:q});if(z?.status==="success"&&z?.result?.valid===!0)return!0;return!1}catch(z){return console.error("API call failed:",z),!1}}async isValidAttestationTransaction(j){if(this.verifyAttestationWithAIP(j))return this.getApiData("/attestation/valid",{tx:j});return!1}async getIdentityFromAddress(j){return this.getApiData("/identity/from-address",{address:j})}async getIdentity(j){return this.getApiData("/identity/get",{idKey:j})}async getAttestationsForHash(j){return this.getApiData("/attestations",{hash:j})}}export{f as MemberID,U as MasterID,$j as BAP};
2
+ import{BSM as D,BigNumber as Lj,ECIES as wj,HD as Yj,OP as H,Signature as Gj}from"@bsv/sdk";import{Utils as Fj}from"@bsv/sdk";var s=async(j,$,J,q)=>{let z=`${J}${j}`;return(await fetch(z,{method:"post",headers:{"Content-type":"application/json; charset=utf-8",token:q,format:"json"},body:JSON.stringify($)})).json()},E=(j,$)=>async(J,q)=>{return s(J,q,j,$)};import{Utils as r}from"@bsv/sdk";var{toHex:I,toArray:g}=r,X="1BAPSuaPnfGnSBM3GLV9yhxUdYe4vGbdMT",K=I(g(X)),O="15PciHG22SNLQJXMoSUaWVi7WSqc7hCfva",Oj=I(g(O)),T="https://api.sigmaidentity.com/v1",G=2147483647,k="m/424150'/0'/0'",w=`m/424150'/${G}'/${G}'`;import{BSM as x,Utils as Qj,ECIES as Wj,Hash as C,PublicKey as N,BigNumber as l}from"@bsv/sdk";import{randomBytes as i}from"crypto";var Y={getRandomString(j=32){return i(j).toString("hex")},getSigningPathFromHex(j,$=!0){let J="m",q=j.match(/.{1,8}/g);if(!q)throw new Error("Invalid hex string");let z=2147483647;for(let Q of q){let Z=Number(`0x${Q}`);if(Z>z)Z-=z;J+=`/${Z}${$?"'":""}`}return J},getNextIdentityPath(j){let $=j.split("/"),J=$[$.length-2],q=!1;if(J.match("'"))q=!0;let z=(Number(J.replace(/[^0-9]/g,""))+1).toString();return $[$.length-2]=z+(q?"'":""),$[$.length-1]=`0${q?"'":""}`,$.join("/")},getNextPath(j){let $=j.split("/"),J=$[$.length-1],q=!1;if(J.match("'"))q=!0;let z=(Number(J.replace(/[^0-9]/g,""))+1).toString();return $[$.length-1]=z+(q?"'":""),$.join("/")}};import{BSM as S,Utils as Bj,PrivateKey as A,BigNumber as qj}from"@bsv/sdk";import{ECIES as a,Utils as e,OP as m,PublicKey as c}from"@bsv/sdk";var{toArray:f,toUTF8:t,toBase64:jj}=e,{electrumDecrypt:$j,electrumEncrypt:Jj}=a;class M{identityAttributes={};encrypt(j,$){let{privKey:J,pubKey:q}=this.getEncryptionKey(),z=$?c.fromString($):q;return jj(Jj(f(j),z,J))}decrypt(j,$){let{privKey:J}=this.getEncryptionKey(),q=void 0;if($)q=c.fromString($);return t($j(f(j,"base64"),J,q))}signOpReturnWithAIP(j,$){let J=this.getAIPMessageBuffer(j),{address:q,signature:z}=this.signMessage(J,$);return this.formatAIPOutput(j,q,z)}getAttributes(){return this.identityAttributes}getAttribute(j){if(this.identityAttributes[j])return this.identityAttributes[j];return null}setAttribute(j,$){if(!$)return;if(this.identityAttributes[j])this.updateExistingAttribute(j,$);else this.createNewAttribute(j,$)}unsetAttribute(j){delete this.identityAttributes[j]}addAttribute(j,$,J=""){let q=J;if(!J)q=Y.getRandomString();this.identityAttributes[j]={value:$,nonce:q}}getAttributeUrns(){let j="";for(let $ in this.identityAttributes){let J=this.getAttributeUrn($);if(J)j+=`${J}
3
+ `}return j}getAttributeUrn(j){let $=this.identityAttributes[j];if($)return`urn:bap:id:${j}:${$.value}:${$.nonce}`;return null}parseStringUrns(j){let $={},J=j.replace(/^\s+/g,"").replace(/\r/gm,"").split(`
4
+ `);for(let q of J){let Q=q.replace(/^\s+/g,"").replace(/\s+$/g,"").split(":");if(Q[0]==="urn"&&Q[1]==="bap"&&Q[2]==="id"&&Q[3]&&Q[4]&&Q[5])$[Q[3]]={value:Q[4],nonce:Q[5]}}return $}parseAttributes(j){if(typeof j==="string")return this.parseStringUrns(j);for(let $ in j)if(!j[$].value||!j[$].nonce)throw new Error("Invalid identity attribute");return j||{}}updateExistingAttribute(j,$){if(typeof $==="string"){this.identityAttributes[j].value=$;return}if(this.identityAttributes[j].value=$.value||"",$.nonce)this.identityAttributes[j].nonce=$.nonce}createNewAttribute(j,$){if(typeof $==="string"){this.addAttribute(j,$);return}this.addAttribute(j,$.value||"",$.nonce)}getAIPMessageBuffer(j){let $=[];if(j[0][0]!==m.OP_RETURN)$.push(m.OP_RETURN);for(let J of j)$.push(...J);return $.concat(f("|"))}formatAIPOutput(j,$,J){let q=[f("|"),f(O),f("BITCOIN_ECDSA"),f($),f(J,"base64")];return[...j,...q]}}var{magicHash:zj}=S;class V extends M{key;idName;description;address;constructor(j,$={}){super();this.key=j,this.address=j.toAddress(),this.idName="Member ID 1",this.description="",this.identityAttributes=this.parseAttributes($)}signMessage(j,$){let J=this.key,q=J.toPublicKey().toString(),z=S.sign(j,J,"raw"),Q=new qj(zj(j)),Z=z.CalculateRecoveryFactor(J.toPublicKey(),Q),L=S.sign(j,J,"raw").toCompact(Z,!0,"base64");return{address:q,signature:L}}signOpReturnWithAIP(j,$){let J=this.getAIPMessageBuffer(j),{address:q,signature:z}=this.signMessage(J);return this.formatAIPOutput(j,q,z)}getPublicKey(){return this.key.toPublicKey().toString()}import(j){this.idName=j.name,this.description=j.description,this.key=A.fromWif(j.derivedPrivateKey),this.address=this.key.toAddress(),this.identityAttributes=j.identityAttributes||{}}static fromBackup(j){let $=new V(A.fromWif(j.derivedPrivateKey));return $.import(j),$}export(){return{name:this.idName,description:this.description,derivedPrivateKey:this.key.toWif(),address:this.address,identityAttributes:this.getAttributes()}}getEncryptionKey(){return{privKey:this.key.deriveChild(this.key.toPublicKey(),w),pubKey:this.key.deriveChild(this.key.toPublicKey(),w).toPublicKey()}}getEncryptionPublicKey(){let{pubKey:j}=this.getEncryptionKey();return j.toString()}}var{toArray:F,toHex:U,toBase58:Zj,toUTF8:p,toBase64:b}=Qj,{electrumDecrypt:h,electrumEncrypt:P}=Wj,{magicHash:o}=x;class _ extends M{#j;#J=T;#Q="";#$;#q;#z;#W;idName;description;rootAddress;identityKey;identityAttributes;getApiData;constructor(j,$={},J=""){super();if(J){let Q=U(C.sha256(J,"utf8")),Z=Y.getSigningPathFromHex(Q);this.#j=j.derive(Z)}else this.#j=j;this.#W=J,this.idName="ID 1",this.description="",this.#$=`${k}/0/0/0`,this.#q=`${k}/0/0/0`,this.#z=`${k}/0/0/1`;let q=this.#j.derive(this.#$);this.rootAddress=q.privKey.toPublicKey().toAddress(),this.identityKey=this.deriveIdentityKey(this.rootAddress);let z={...$};this.identityAttributes=this.parseAttributes(z),this.getApiData=E(this.#J,this.#Q)}set BAP_SERVER(j){this.#J=j}get BAP_SERVER(){return this.#J}set BAP_TOKEN(j){this.#Q=j}get BAP_TOKEN(){return this.#Q}deriveIdentityKey(j){let $=U(C.sha256(j,"utf8"));return Zj(C.ripemd160($,"hex"))}parseAttributes(j){if(typeof j==="string")return this.parseStringUrns(j);for(let $ in j)if(!j[$].value||!j[$].nonce)throw new Error("Invalid identity attribute");return j||{}}parseStringUrns(j){let $={},J=j.replace(/^\s+/g,"").replace(/\r/gm,"").split(`
5
+ `);for(let q of J){let Q=q.replace(/^\s+/g,"").replace(/\s+$/g,"").split(":");if(Q[0]==="urn"&&Q[1]==="bap"&&Q[2]==="id"&&Q[3]&&Q[4]&&Q[5])$[Q[3]]={value:Q[4],nonce:Q[5]}}return $}getIdentityKey(){return this.identityKey}set rootPath(j){if(this.#j){let $=j;if(j.split("/").length<5)$=`${k}${j}`;if(!this.validatePath($))throw new Error(`invalid signing path given ${$}`);this.#$=$;let J=this.#j.derive($);this.rootAddress=J.pubKey.toAddress(),this.identityKey=this.deriveIdentityKey(this.rootAddress),this.#q=$,this.#z=$}}get rootPath(){return this.#$}getRootPath(){return this.#$}set currentPath(j){let $=j;if(j.split("/").length<5)$=`${k}${j}`;if(!this.validatePath($))throw new Error("invalid signing path given");this.#q=this.#z,this.#z=$}get currentPath(){return this.#z}get previousPath(){return this.#q}get idSeed(){return this.#W}incrementPath(){this.currentPath=Y.getNextPath(this.currentPath)}validatePath(j){if(j.match(/\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?/)){let $=j.split("/");if($.length===7&&Number($[1].replace("'",""))<=G&&Number($[2].replace("'",""))<=G&&Number($[3].replace("'",""))<=G&&Number($[4].replace("'",""))<=G&&Number($[5].replace("'",""))<=G&&Number($[6].replace("'",""))<=G)return!0}return!1}getInitialIdTransaction(){return this.getIdTransaction(this.#$)}getIdTransaction(j=""){if(this.#z===this.#$)throw new Error("Current path equals rootPath. ID was probably not initialized properly");let $=[F(X),F("ID"),F(this.identityKey),F(this.getCurrentAddress())];return this.signOpReturnWithAIP($,j||this.#q)}getAddress(j){return this.#j.derive(j).privKey.toPublicKey().toAddress()}getCurrentAddress(){return this.getAddress(this.#z)}getEncryptionKey(){let $=this.#j.derive(this.#$).derive(w).privKey;return{privKey:$,pubKey:$.toPublicKey()}}getEncryptionKeyType42(){let j=this.#j.derive(this.#$),$=j.privKey.deriveChild(j.toPublic().pubKey,w);return{privKey:$,pubKey:$.toPublicKey()}}getEncryptionPublicKey(){let{pubKey:j}=this.getEncryptionKey();return j.toString()}getEncryptionPublicKeyWithSeed(j){return this.getEncryptionPrivateKeyWithSeed(j).toPublicKey().toString()}encrypt(j,$){let z=this.#j.derive(this.#$).derive(w).privKey.toPublicKey(),Q=$?N.fromString($):z;return b(P(F(j),Q,null))}decrypt(j,$){let q=this.#j.derive(this.#$).derive(w).privKey,z=void 0;if($)z=N.fromString($);return p(h(F(j,"base64"),q,z))}encryptWithSeed(j,$,J){let q=this.getEncryptionPrivateKeyWithSeed($),z=q.toPublicKey(),Q=J?N.fromString(J):z;return b(P(F(j),Q,q))}decryptWithSeed(j,$,J){let q=this.getEncryptionPrivateKeyWithSeed($),z=void 0;if(J)z=N.fromString(J);return p(h(F(j,"base64"),q,z))}getEncryptionPrivateKeyWithSeed(j){let $=U(C.sha256(j,"utf8")),J=Y.getSigningPathFromHex($);return this.#j.derive(this.#$).derive(J).privKey}getAttestation(j){let $=C.sha256(j,"utf8");return`bap:attest:${U($)}:${this.getIdentityKey()}`}getAttestationHash(j){let $=this.getAttributeUrn(j);if(!$)return null;let J=this.getAttestation($),q=C.sha256(J,"utf8");return U(q)}signMessage(j,$){let J=$||this.#z,q=this.#j.derive(J).privKey,z=q.toAddress(),Q=x.sign(j,q,"raw"),Z=new l(o(j)),L=Q.CalculateRecoveryFactor(q.toPublicKey(),Z),v=x.sign(j,q,"raw").toCompact(L,!0,"base64");return{address:z,signature:v}}signMessageWithSeed(j,$){let J=U(C.sha256($,"utf8")),q=Y.getSigningPathFromHex(J),Q=this.#j.derive(this.#$).derive(q),Z=Q.privKey.toPublicKey().toAddress(),L=F(j,"utf8"),v=x.sign(L,Q.privKey,"raw"),u=new l(o(L)),n=v.CalculateRecoveryFactor(Q.privKey.toPublicKey(),u),d=x.sign(L,Q.privKey,"raw").toCompact(n,!0,"base64");return{address:Z,signature:d}}signOpReturnWithAIP(j,$=""){let J=this.#z,q=this.getAIPMessageBuffer(j),{address:z,signature:Q}=this.signMessage(q,$);return this.formatAIPOutput(j,z,Q)}async getIdSigningKeys(){let j=await this.getApiData("/signing-keys",{idKey:this.identityKey});return console.log("getIdSigningKeys",j),j}async getAttributeAttestations(j){let $=this.getAttestationHash(j),J=await this.getApiData("/attestation/get",{hash:$});return console.log("getAttestations",j,$,J),J}import(j){this.idName=j.name,this.description=j.description||"",this.identityKey=j.identityKey,this.#$=j.rootPath,this.rootAddress=j.rootAddress,this.#q=j.previousPath,this.#z=j.currentPath,this.#W=("idSeed"in j?j.idSeed:"")||"",this.identityAttributes=this.parseAttributes(j.identityAttributes)}export(){return{name:this.idName,description:this.description,identityKey:this.identityKey,rootPath:this.#$,rootAddress:this.rootAddress,previousPath:this.#q,currentPath:this.#z,idSeed:this.#W,identityAttributes:this.getAttributes(),lastIdPath:""}}exportMemberBackup(){let j=this.#j.derive(this.#z).privKey;return{name:this.idName,description:this.description,derivedPrivateKey:j.toWif(),address:j.toPublicKey().toAddress(),identityAttributes:this.getAttributes()}}newId(){this.incrementPath();let j=this.#j.derive(this.#z).privKey;return new V(j)}}var{toArray:W,toUTF8:R,toBase64:y,toHex:B}=Fj,{electrumEncrypt:Xj,electrumDecrypt:fj}=wj;class Cj{#j;#J={};#Q=T;#$="";#q="";getApiData;constructor(j,$="",J=""){if(!j)throw new Error("No HDPrivateKey given");if(this.#j=Yj.fromString(j),$)this.#$=$;if(J)this.#Q=J;this.getApiData=E(this.#Q,this.#$)}get lastIdPath(){return this.#q}getPublicKey(j=""){if(j)return this.#j.derive(j).pubKey.toString();return this.#j.pubKey.toString()}getHdPublicKey(j=""){if(j)return this.#j.derive(j).toPublic().toString();return this.#j.toPublic().toString()}set BAP_SERVER(j){this.#Q=j;for(let $ in this.#J)this.#J[$].BAP_SERVER=j}get BAP_SERVER(){return this.#Q}set BAP_TOKEN(j){this.#$=j;for(let $ in this.#J)this.#J[$].BAP_TOKEN=j}get BAP_TOKEN(){return this.#$}checkIdBelongs(j){if(this.#j.derive(j.rootPath).pubKey.toAddress()!==j.rootAddress)throw new Error("ID does not belong to this private key");return!0}listIds(){return Object.keys(this.#J)}newId(j,$={},J=""){let q;if(!j)q=this.getNextValidPath();else q=j;let z=new _(this.#j,$,J);z.BAP_SERVER=this.#Q,z.BAP_TOKEN=this.#$,z.rootPath=q,z.currentPath=Y.getNextPath(q);let Q=z.getIdentityKey();return this.#J[Q]=z,this.#q=q,this.#J[Q]}removeId(j){delete this.#J[j]}getNextValidPath(){if(this.#q)return Y.getNextIdentityPath(this.#q);return`/0'/${Object.keys(this.#J).length}'/0'`}getId(j){return this.#J[j]||null}setId(j){this.checkIdBelongs(j),this.#J[j.getIdentityKey()]=j}importIds(j,$=!0){if($&&typeof j==="string"){this.importEncryptedIds(j);return}let J=j;if(!J.lastIdPath)throw new Error("ID cannot be imported as it is not complete");if(!J.ids)throw new Error(`ID data is not in the correct format: ${j}`);let q=j.lastIdPath;for(let z of J.ids){if(!z.identityKey||!z.identityAttributes||!z.rootAddress)throw new Error("ID cannot be imported as it is not complete");let Q=new _(this.#j,{},z.idSeed);if(Q.BAP_SERVER=this.#Q,Q.BAP_TOKEN=this.#$,Q.import(z),q==="")q=Q.currentPath;this.checkIdBelongs(Q),this.#J[Q.getIdentityKey()]=Q}this.#q=q}importEncryptedIds(j){let $=this.decrypt(j),J=JSON.parse($);if(Array.isArray(J)){console.log(`Importing old format:
6
+ `,J),this.importOldIds(J);return}if(typeof J!=="object")throw new Error("decrypted, but found unrecognized identities format");this.importIds(J,!1)}importOldIds(j){for(let $ of j){let J=new _(this.#j,{},$.idSeed??"");J.BAP_SERVER=this.#Q,J.BAP_TOKEN=this.#$,J.import($),this.checkIdBelongs(J),this.#J[J.getIdentityKey()]=J,this.#q=J.currentPath}}exportIds(j,$=!0){let J={lastIdPath:this.#q,ids:[]},q=j||Object.keys(this.#J);for(let z of q){if(!this.#J[z])throw new Error(`Identity ${z} not found`);J.ids.push(this.#J[z].export())}if($)return this.encrypt(JSON.stringify(J));return J}exportId(j,$=!0){let J={lastIdPath:this.#q,ids:[]};if(J.ids.push(this.#J[j].export()),$)return this.encrypt(JSON.stringify(J));return J}encrypt(j){let $=this.#j.derive(w);return y(Xj(W(j),$.pubKey,null))}decrypt(j){let $=this.#j.derive(w);return R(fj(W(j,"base64"),$.privKey))}signAttestationWithAIP(j,$,J=0,q=""){let z=this.getId($);if(!z)throw new Error("Could not find identity to attest with");let Q=this.getAttestationBuffer(j,J,q),{address:Z,signature:L}=z.signMessage(Q);return this.createAttestationTransaction(j,J,Z,L,q)}verifyAttestationWithAIP(j){if(!j.every((q)=>Array.isArray(q))||j[0][0]!==H.OP_RETURN||B(j[1])!==K)throw new Error("Not a valid BAP transaction");let $=B(j[7])==="44415441"?5:0,J={type:R(j[2]),hash:B(j[3]),sequence:R(j[4]),signingProtocol:R(j[7+$]),signingAddress:R(j[8+$]),signature:y(j[9+$])};if($&&j[3]===j[8])J.data=B(j[9]);console.log({attestation:J});try{let q=[];for(let z=0;z<6+$;z++)q.push(j[z]);J.verified=this.verifySignature(q.flat(),J.signingAddress,J.signature)}catch(q){J.verified=!1}return J}createAttestationTransaction(j,$,J,q,z=""){let Q=[[H.OP_RETURN],W(X),W("ATTEST"),W(j),W(`${$}`),W("|")];if(z)Q.push(W(X),W("DATA"),W(j),W(z),W("|"));return Q.push(W(O),W("BITCOIN_ECDSA"),W(J),W(q,"base64")),console.log({elements:Q}),Q}getAttestationBuffer(j,$=0,J=""){let q=[[H.OP_RETURN],W(X),W("ATTEST"),W(j),W(`${$}`),W("|")];if(J)q.push(W(X),W("DATA"),W(j),W(J),W("|"));return q.flat()}verifySignature(j,$,J){let q;if(Array.isArray(j))q=j;else if(Buffer.isBuffer(j))q=[...j];else q=W(j,"utf8");let z=Gj.fromCompact(J,"base64"),Q;for(let Z=0;Z<4;Z++)try{if(Q=z.RecoverPublicKey(Z,new Lj(D.magicHash(q))),D.verify(q,z,Q)&&Q.toAddress()===$)return!0}catch(L){}return!1}async verifyChallengeSignature(j,$,J,q){if(!this.verifySignature(J,$,q))return!1;try{let Q=await this.getApiData("/attestation/valid",{idKey:j,address:$,challenge:J,signature:q});if(Q?.status==="success"&&Q?.result?.valid===!0)return!0;return!1}catch(Q){return console.error("API call failed:",Q),!1}}async isValidAttestationTransaction(j){if(this.verifyAttestationWithAIP(j))return this.getApiData("/attestation/valid",{tx:j});return!1}async getIdentityFromAddress(j){return this.getApiData("/identity/from-address",{address:j})}async getIdentity(j){return this.getApiData("/identity/get",{idKey:j})}async getAttestationsForHash(j){return this.getApiData("/attestations",{hash:j})}}export{V as MemberID,_ as MasterID,Cj as BAP};
7
7
 
8
- //# debugId=6A60A376E5A4A51E64756E2164756E21
8
+ //# debugId=81012A300D9BB71864756E2164756E21