bsv-bap 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/.babelrc +20 -0
  2. package/.eslintrc +46 -0
  3. package/LICENSE +25 -0
  4. package/README.md +819 -0
  5. package/babel.config.js +6 -0
  6. package/bun.lockb +0 -0
  7. package/coverage/clover.xml +6 -0
  8. package/coverage/coverage-final.json +1 -0
  9. package/coverage/lcov-report/base.css +224 -0
  10. package/coverage/lcov-report/block-navigation.js +87 -0
  11. package/coverage/lcov-report/favicon.png +0 -0
  12. package/coverage/lcov-report/index.html +101 -0
  13. package/coverage/lcov-report/prettify.css +1 -0
  14. package/coverage/lcov-report/prettify.js +2 -0
  15. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  16. package/coverage/lcov-report/sorter.js +196 -0
  17. package/coverage/lcov-report/src/constants.ts.html +113 -0
  18. package/coverage/lcov-report/src/id.ts.html +2207 -0
  19. package/coverage/lcov-report/src/index.html +156 -0
  20. package/coverage/lcov-report/src/index.ts.html +1877 -0
  21. package/coverage/lcov-report/src/utils.ts.html +404 -0
  22. package/coverage/lcov-report/tests/data/index.html +111 -0
  23. package/coverage/lcov-report/tests/data/keys.js.html +86 -0
  24. package/coverage/lcov.info +0 -0
  25. package/dist/jest.config.d.ts +8 -0
  26. package/dist/src/constants.d.ts +8 -0
  27. package/dist/src/id.d.ts +295 -0
  28. package/dist/src/index.d.ts +238 -0
  29. package/dist/src/interface.d.ts +23 -0
  30. package/dist/src/poa.d.ts +6 -0
  31. package/dist/src/utils.d.ts +54 -0
  32. package/dist/typescript-npm-package.cjs.d.ts +554 -0
  33. package/dist/typescript-npm-package.cjs.js +1320 -0
  34. package/dist/typescript-npm-package.cjs.js.map +1 -0
  35. package/dist/typescript-npm-package.esm.d.ts +554 -0
  36. package/dist/typescript-npm-package.esm.js +1312 -0
  37. package/dist/typescript-npm-package.esm.js.map +1 -0
  38. package/dist/typescript-npm-package.umd.d.ts +554 -0
  39. package/dist/typescript-npm-package.umd.js +110193 -0
  40. package/dist/typescript-npm-package.umd.js.map +1 -0
  41. package/jest.config.ts +196 -0
  42. package/jsdoc.json +16 -0
  43. package/package.json +80 -0
  44. package/rollup.config.js +64 -0
  45. package/setup-jest.js +1 -0
  46. package/src/README.md +80 -0
  47. package/src/attributes.json +119 -0
  48. package/src/constants.ts +11 -0
  49. package/src/id.ts +783 -0
  50. package/src/index.ts +631 -0
  51. package/src/interface.ts +26 -0
  52. package/src/poa.ts +9 -0
  53. package/src/utils.ts +111 -0
  54. package/tests/data/ids.json +30 -0
  55. package/tests/data/keys.js +2 -0
  56. package/tests/data/old-ids.json +25 -0
  57. package/tests/data/test-vectors.json +122 -0
  58. package/tests/id.test.js +286 -0
  59. package/tests/index.test.js +335 -0
  60. package/tests/regression.test.js +28 -0
  61. package/tests/utils.test.js +27 -0
  62. package/tsconfig.json +17 -0
@@ -0,0 +1,335 @@
1
+ import { describe, expect, test } from "@jest/globals";
2
+
3
+ import { BAP } from "../src";
4
+ import { SIGNING_PATH_PREFIX, ENCRYPTION_PATH } from "../src/constants";
5
+ import { BAP_ID } from "../src/id";
6
+ import { HD } from "@bsv/sdk";
7
+ import { HDPrivateKey, HDPublicKey } from "./data/keys";
8
+ import fullId from "./data/ids.json";
9
+ import oldFullId from "./data/old-ids.json";
10
+
11
+ const testBAPInstance = (bap) => {
12
+ // TODO ....
13
+ expect(bap).toMatchObject({});
14
+ expect(bap.getHdPublicKey()).toMatch("xpub");
15
+ };
16
+ const identityKey =
17
+ "4a59332b7d81c4c68a6edcb1160f4683037a97286b97cc500b5881632e921849z";
18
+
19
+ describe("bap", () => {
20
+ test("init", () => {
21
+ const randomHDPrivateKey = HD.fromRandom().toString();
22
+ const bap = new BAP(randomHDPrivateKey);
23
+ testBAPInstance(bap);
24
+ });
25
+
26
+ test("init without key", () => {
27
+ expect(() => {
28
+ new BAP();
29
+ }).toThrow();
30
+ });
31
+
32
+ test("with known key", () => {
33
+ const bap = new BAP(HDPrivateKey);
34
+ testBAPInstance(bap);
35
+
36
+ expect(bap.getPublicKey()).toBe(
37
+ "02c23e9fc6a959bb5315159ac7438c5a6bff37c7197326d1060b176e3969d72af5",
38
+ );
39
+ expect(bap.getPublicKey(ENCRYPTION_PATH)).toBe(
40
+ "02fc759e24d922c2d47766710613910c0f40bab7439777af9ad45bff55ec622994",
41
+ );
42
+
43
+ expect(bap.getHdPublicKey()).toBe(HDPublicKey);
44
+ // eslint-disable-next-line max-len
45
+ expect(bap.getHdPublicKey(ENCRYPTION_PATH)).toBe("xpub6CXbFY2NumUP1dVRRbXiAdj6oRhqK3zQjt1vdzsTBfy3jDLjHMTCCE7AX6fz1KqAag9EPGf52KyCAT9iovKrXZ74BSryrDQ2XBHiawuFfsu");
46
+ });
47
+
48
+ test("set BAP_SERVER", () => {
49
+ const bap = new BAP(HDPrivateKey);
50
+ const id = bap.newId();
51
+
52
+ expect(bap.BAP_SERVER).toEqual("https://bap.network/api/v1");
53
+ expect(id.BAP_SERVER).toEqual("https://bap.network/api/v1");
54
+
55
+ const newServer = "https://bapdev.legallychained.com/";
56
+ bap.BAP_SERVER = newServer;
57
+ expect(bap.BAP_SERVER).toEqual(newServer);
58
+ expect(id.BAP_SERVER).toEqual(newServer);
59
+ });
60
+
61
+ test("set BAP_TOKEN", () => {
62
+ const bap = new BAP(HDPrivateKey);
63
+ const id = bap.newId();
64
+
65
+ expect(bap.BAP_TOKEN).toEqual("");
66
+ expect(id.BAP_TOKEN).toEqual("");
67
+
68
+ const newToken = "token_string";
69
+ bap.BAP_TOKEN = newToken;
70
+ expect(bap.BAP_TOKEN).toEqual(newToken);
71
+ expect(id.BAP_TOKEN).toEqual(newToken);
72
+
73
+ const tokenAtInit = "test_token";
74
+ const bap2 = new BAP(HDPrivateKey, tokenAtInit);
75
+ const id2 = bap2.newId();
76
+ expect(bap2.BAP_TOKEN).toEqual(tokenAtInit);
77
+ expect(id2.BAP_TOKEN).toEqual(tokenAtInit);
78
+
79
+ const newToken2 = "token_string2";
80
+ bap2.BAP_TOKEN = newToken2;
81
+ expect(bap2.BAP_TOKEN).toEqual(newToken2);
82
+ expect(id2.BAP_TOKEN).toEqual(newToken2);
83
+ });
84
+
85
+ test("import full ID", () => {
86
+ const bap = new BAP(HDPrivateKey);
87
+ bap.importIds(fullId, false);
88
+ testBAPInstance(bap);
89
+
90
+ expect(bap.listIds()).toStrictEqual([identityKey]);
91
+
92
+ const importedId = bap.getId(identityKey);
93
+ expect(importedId).toBeInstanceOf(BAP_ID);
94
+ expect(importedId.getIdentityKey()).toBe(identityKey);
95
+ });
96
+
97
+ test("import OLD full ID", () => {
98
+ const bap = new BAP(HDPrivateKey);
99
+ bap.importIds(oldFullId, false);
100
+ testBAPInstance(bap);
101
+
102
+ expect(bap.listIds()).toStrictEqual([identityKey]);
103
+
104
+ const importedId = bap.getId(identityKey);
105
+ expect(importedId).toBeInstanceOf(BAP_ID);
106
+ expect(importedId.getIdentityKey()).toBe(identityKey);
107
+ });
108
+
109
+ test("export full ID", () => {
110
+ const bap = new BAP(HDPrivateKey);
111
+ bap.importIds(fullId, false);
112
+ testBAPInstance(bap);
113
+
114
+ const exportData = bap.exportIds(false);
115
+ expect(exportData).toStrictEqual(fullId);
116
+ });
117
+
118
+ test("export/import encrypted ID", () => {
119
+ const bap = new BAP(HDPrivateKey);
120
+ bap.importIds(fullId, false);
121
+ testBAPInstance(bap);
122
+
123
+ const encryptedExportData = bap.exportIds();
124
+ expect(typeof encryptedExportData).toBe("string");
125
+
126
+ const bap2 = new BAP(HDPrivateKey);
127
+ bap2.importIds(encryptedExportData);
128
+ expect(bap2.listIds()).toStrictEqual([identityKey]);
129
+
130
+ const importedId = bap2.getId(identityKey);
131
+ expect(importedId).toBeInstanceOf(BAP_ID);
132
+ expect(importedId.getIdentityKey()).toBe(identityKey);
133
+ });
134
+
135
+ test("checkIdBelongs", () => {
136
+ const randomHDPrivateKey = HD.fromRandom().toString();
137
+ const bap1 = new BAP(randomHDPrivateKey);
138
+ const bap2 = new BAP(HDPrivateKey);
139
+
140
+ const id1 = bap1.newId();
141
+ const id2 = bap2.newId();
142
+
143
+ expect(bap1.checkIdBelongs(id1)).toBe(true);
144
+ expect(() => {
145
+ bap1.checkIdBelongs(id2);
146
+ }).toThrow();
147
+
148
+ expect(bap2.checkIdBelongs(id2)).toBe(true);
149
+ expect(() => {
150
+ bap2.checkIdBelongs(id1);
151
+ }).toThrow();
152
+ });
153
+
154
+ test("getId / setId", () => {
155
+ const bap = new BAP(HDPrivateKey);
156
+ const newId = bap.newId();
157
+ const idKey = newId.getIdentityKey();
158
+ bap.setId(newId);
159
+
160
+ expect(bap.getId("test")).toEqual(null);
161
+ expect(bap.getId(idKey).identityKey).toStrictEqual(idKey);
162
+
163
+ expect(() => {
164
+ bap.setId({});
165
+ }).toThrow();
166
+ });
167
+
168
+ test("listIds", () => {
169
+ const randomHDPrivateKey = HD.fromRandom().toString();
170
+ const bap = new BAP(randomHDPrivateKey);
171
+ expect(bap.listIds()).toStrictEqual([]);
172
+
173
+ const newId = bap.newId();
174
+ const idKey = newId.getIdentityKey();
175
+ bap.setId(newId);
176
+ expect(bap.listIds()).toStrictEqual([idKey]);
177
+ });
178
+
179
+ test("newId", () => {
180
+ const randomHDPrivateKey = HD.fromRandom().toString();
181
+ const bap = new BAP(randomHDPrivateKey);
182
+ const newId = bap.newId();
183
+ expect(newId).toBeInstanceOf(BAP_ID);
184
+ expect(bap.checkIdBelongs(newId)).toBe(true);
185
+ expect(newId.rootPath).toBe(`${SIGNING_PATH_PREFIX}/0'/0'/0'`);
186
+ expect(newId.currentPath).toBe(`${SIGNING_PATH_PREFIX}/0'/0'/1'`);
187
+
188
+ const newId2 = bap.newId("/123/124/0");
189
+ expect(newId2).toBeInstanceOf(BAP_ID);
190
+ expect(bap.checkIdBelongs(newId2)).toBe(true);
191
+ expect(newId2.rootPath).toBe(`${SIGNING_PATH_PREFIX}/123/124/0`);
192
+ expect(newId2.currentPath).toBe(`${SIGNING_PATH_PREFIX}/123/124/1`);
193
+
194
+ // Hardened path given
195
+ const newId3 = bap.newId(`/123'/124'/0`);
196
+ expect(newId3).toBeInstanceOf(BAP_ID);
197
+ expect(bap.checkIdBelongs(newId3)).toBe(true);
198
+ expect(newId3.rootPath).toBe(`${SIGNING_PATH_PREFIX}/123'/124'/0`);
199
+ expect(newId3.currentPath).toBe(`${SIGNING_PATH_PREFIX}/123'/124'/1`);
200
+
201
+ // Hardened full path given
202
+ const newId4 = bap.newId(`/123'/124'/0'`);
203
+ expect(newId4).toBeInstanceOf(BAP_ID);
204
+ expect(bap.checkIdBelongs(newId4)).toBe(true);
205
+ expect(newId4.rootPath).toBe(`${SIGNING_PATH_PREFIX}/123'/124'/0'`);
206
+ expect(newId4.currentPath).toBe(`${SIGNING_PATH_PREFIX}/123'/124'/1'`);
207
+
208
+ expect(() => {
209
+ bap.newId("/123erg/124ggg/0")
210
+ }).toThrow();
211
+ });
212
+
213
+ test("verifyAttestationWithAIP", () => {
214
+ // test in id
215
+ const bap = new BAP(HDPrivateKey);
216
+ expect(() => {
217
+ bap.verifyAttestationWithAIP([]);
218
+ }).toThrow();
219
+ });
220
+
221
+ test("import full BAP doc", () => {
222
+ const fullBap = new BAP(HDPrivateKey);
223
+ fullBap.importIds(fullId, false);
224
+
225
+ const bapId = fullBap.getId(identityKey);
226
+ expect(bapId.getAttribute("name").value).toBe("John Doe");
227
+ expect(bapId.getAttribute("name").nonce).toBe(
228
+ "e2c6fb4063cc04af58935737eaffc938011dff546d47b7fbb18ed346f8c4d4fa",
229
+ );
230
+ expect(bapId.getAttributeUrn("name")).toBe(
231
+ "urn:bap:id:name:John Doe:e2c6fb4063cc04af58935737eaffc938011dff546d47b7fbb18ed346f8c4d4fa",
232
+ );
233
+ });
234
+
235
+ test("sign attestation with AIP", () => {
236
+ const bap = new BAP(HDPrivateKey);
237
+ bap.importIds(fullId, false);
238
+
239
+ const userId = new BAP_ID(HD.fromString(HDPrivateKey), {
240
+ name: {
241
+ value: "John Doe",
242
+ nonce:
243
+ "e2c6fb4063cc04af58935737eaffc938011dff546d47b7fbb18ed346f8c4d4fa",
244
+ },
245
+ });
246
+ const attestationHash = userId.getAttestationHash("name");
247
+ expect(attestationHash).toBe(
248
+ "d6cbf280ad7515e549c7b154a02555fff3eeb05c6b245039813d39d3c0397b4a",
249
+ );
250
+
251
+ // create a signing transaction of the user's hash with our own identity key
252
+ const transaction = bap.signAttestationWithAIP(
253
+ attestationHash,
254
+ identityKey,
255
+ );
256
+ expect(transaction.length).toBe(10);
257
+ const verify = bap.verifyAttestationWithAIP(transaction);
258
+ expect(verify.verified).toBe(true);
259
+ });
260
+
261
+ test("sign attestation with AIP and data", () => {
262
+ const bap = new BAP(HDPrivateKey);
263
+ bap.importIds(fullId, false);
264
+
265
+ const userId = new BAP_ID(HD.fromString(HDPrivateKey), {
266
+ name: {
267
+ value: "John Doe",
268
+ nonce:
269
+ "e2c6fb4063cc04af58935737eaffc938011dff546d47b7fbb18ed346f8c4d4fa",
270
+ },
271
+ });
272
+ const attestationHash = userId.getAttestationHash("name");
273
+ expect(attestationHash).toBe(
274
+ "d6cbf280ad7515e549c7b154a02555fff3eeb05c6b245039813d39d3c0397b4a",
275
+ );
276
+
277
+ // create a signing transaction of the user's hash with our own identity key
278
+ const dataString = "This is a test string to add to the attestation";
279
+ const transaction = bap.signAttestationWithAIP(
280
+ attestationHash,
281
+ identityKey,
282
+ 0,
283
+ dataString,
284
+ );
285
+ expect(transaction.length).toBe(15);
286
+ const verify = bap.verifyAttestationWithAIP(transaction);
287
+ expect(verify.verified).toBe(true);
288
+ });
289
+
290
+ test("lastIdPath", () => {
291
+ const fullBap = new BAP(HDPrivateKey);
292
+ fullBap.importIds(fullId, false);
293
+ expect(fullBap.lastIdPath).toBe("/26562456/876543/345346");
294
+
295
+ const newId = fullBap.newId();
296
+ const idKey = newId.getIdentityKey();
297
+ expect(fullBap.lastIdPath).toBe("/26562456/876544/0");
298
+
299
+ fullBap.removeId(idKey);
300
+ expect(fullBap.lastIdPath).toBe("/26562456/876544/0");
301
+
302
+ const newId2 = fullBap.newId();
303
+ const idKey2 = newId2.getIdentityKey();
304
+ expect(fullBap.lastIdPath).toBe("/26562456/876545/0");
305
+
306
+ fullBap.removeId(idKey2);
307
+ expect(fullBap.lastIdPath).toBe("/26562456/876545/0");
308
+
309
+ const newId3 = fullBap.newId();
310
+ expect(fullBap.lastIdPath).toBe("/26562456/876546/0");
311
+ expect(newId3.currentPath).toBe(`${SIGNING_PATH_PREFIX}/26562456/876546/1`);
312
+
313
+ const idKeys = fullBap.listIds();
314
+ expect(idKeys.length).toBe(2);
315
+ });
316
+
317
+ /*
318
+ test('verifyChallengeSignature', () => {
319
+ const privateKey = bsv.PrivateKey.fromRandom();
320
+ const address = privateKey.publicKey.toAddress().toString();
321
+ const message = 'test message';
322
+ const signature = Message(message).sign(privateKey);
323
+
324
+ const bap = new BAP(HDPrivateKey);
325
+ const result = bap.verifyChallengeSignature(
326
+ identityKey,
327
+ address,
328
+ message,
329
+ signature
330
+ )
331
+ expect(result).toBe(true);
332
+ });
333
+
334
+ */
335
+ });
@@ -0,0 +1,28 @@
1
+ import {
2
+ describe,
3
+ expect,
4
+ it,
5
+ } from '@jest/globals';
6
+ import { BAP } from '../src';
7
+
8
+ import testVectors from './data/test-vectors.json';
9
+
10
+ describe('test-vectors', () => {
11
+ it('regression', () => {
12
+ for (const v of testVectors) {
13
+ const bap = new BAP(v.HDPrivateKey);
14
+ const id = bap.newId();
15
+ expect(id.rootAddress).toBe(v.rootAddress);
16
+ expect(id.getIdentityKey()).toBe(v.idKey);
17
+ expect(id.rootPath).toBe(v.rootPath);
18
+ const tx = id.getInitialIdTransaction();
19
+ expect(typeof tx[8]).toBe('string')
20
+ expect(typeof v.tx[8]).toBe('string')
21
+ // biome-ignore lint/performance/noDelete: <explanation>
22
+ delete tx[8]; // remove the signature, will be different
23
+ // biome-ignore lint/performance/noDelete: <explanation>
24
+ delete v.tx[8]; // remove the signature, will be different
25
+ expect(tx).toStrictEqual(v.tx);
26
+ }
27
+ });
28
+ });
@@ -0,0 +1,27 @@
1
+ import {
2
+ describe,
3
+ expect,
4
+ beforeEach,
5
+ afterEach,
6
+ it,
7
+ test,
8
+ } from '@jest/globals';
9
+ import { Utils } from '../src/utils';
10
+
11
+ describe('random', () => {
12
+ it('should generate random strings', () => {
13
+ const randomString = Utils.getRandomString(32);
14
+ expect(randomString.length).toEqual(64);
15
+
16
+ const randomString2 = Utils.getRandomString(12);
17
+ expect(randomString2.length).toEqual(24);
18
+ });
19
+
20
+ test('getNextPath', () => {
21
+ expect(Utils.getNextPath('/0/0/1')).toBe('/0/0/2');
22
+ expect(Utils.getNextPath('/0/2345/1')).toBe('/0/2345/2');
23
+ expect(Utils.getNextPath('/0\'/2345\'/1\'')).toBe('/0\'/2345\'/2\'');
24
+ expect(Utils.getNextPath('/5765/2345/2342')).toBe('/5765/2345/2343');
25
+ expect(Utils.getNextPath('/5765\'/2345\'/2342\'')).toBe('/5765\'/2345\'/2343\'');
26
+ });
27
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": [
4
+ "dom",
5
+ "dom.iterable",
6
+ "esnext"
7
+ ],
8
+ "target": "es6",
9
+ "module": "esnext",
10
+ "moduleResolution": "node",
11
+ "strict": true,
12
+ "esModuleInterop": true,
13
+ "declaration": true,
14
+ "declarationDir": "dts/",
15
+ "emitDeclarationOnly": true
16
+ }
17
+ }