signify-ts 0.1.1 → 0.2.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 (115) hide show
  1. package/README.md +96 -47
  2. package/dist/buffer-polyfill.d.ts +1 -0
  3. package/dist/exports.d.ts +40 -0
  4. package/dist/index.d.ts +4 -3
  5. package/dist/keri/app/aiding.d.ts +138 -0
  6. package/dist/keri/app/clienting.d.ts +182 -0
  7. package/dist/keri/app/contacting.d.ts +93 -0
  8. package/dist/keri/app/controller.d.ts +49 -0
  9. package/dist/keri/app/coring.d.ts +121 -0
  10. package/dist/keri/app/credentialing.d.ts +245 -0
  11. package/dist/keri/app/escrowing.d.ts +19 -0
  12. package/dist/keri/app/exchanging.d.ts +60 -0
  13. package/dist/keri/app/grouping.d.ts +44 -0
  14. package/dist/keri/app/habery.d.ts +48 -47
  15. package/dist/keri/app/notifying.d.ts +34 -0
  16. package/dist/keri/core/authing.d.ts +10 -9
  17. package/dist/keri/core/bexter.d.ts +7 -0
  18. package/dist/keri/core/cigar.d.ts +8 -8
  19. package/dist/keri/core/cipher.d.ts +5 -5
  20. package/dist/keri/core/core.d.ts +59 -53
  21. package/dist/keri/core/counter.d.ts +43 -43
  22. package/dist/keri/core/decrypter.d.ts +10 -10
  23. package/dist/keri/core/diger.d.ts +21 -21
  24. package/dist/keri/core/encrypter.d.ts +9 -9
  25. package/dist/keri/core/eventing.d.ts +54 -21
  26. package/dist/keri/core/httping.d.ts +44 -34
  27. package/dist/keri/core/indexer.d.ts +98 -88
  28. package/dist/keri/core/keeping.d.ts +103 -1
  29. package/dist/keri/core/kering.d.ts +5 -5
  30. package/dist/keri/core/manager.d.ts +174 -172
  31. package/dist/keri/core/matter.d.ts +116 -69
  32. package/dist/keri/core/number.d.ts +7 -6
  33. package/dist/keri/core/pather.d.ts +7 -0
  34. package/dist/keri/core/prefixer.d.ts +15 -15
  35. package/dist/keri/core/saider.d.ts +23 -23
  36. package/dist/keri/core/salter.d.ts +23 -23
  37. package/dist/keri/core/seqner.d.ts +15 -0
  38. package/dist/keri/core/serder.d.ts +31 -23
  39. package/dist/keri/core/siger.d.ts +18 -18
  40. package/dist/keri/core/signer.d.ts +34 -34
  41. package/dist/keri/core/tholder.d.ts +29 -14
  42. package/dist/keri/core/utils.d.ts +20 -15
  43. package/dist/keri/core/vdring.d.ts +16 -0
  44. package/dist/keri/core/verfer.d.ts +13 -12
  45. package/dist/keri/end/ending.d.ts +13 -13
  46. package/dist/math.d.ts +1 -0
  47. package/dist/ready.d.ts +1 -0
  48. package/dist/signify-ts.cjs +7842 -0
  49. package/dist/signify-ts.cjs.development.js +6369 -256
  50. package/dist/signify-ts.cjs.development.js.map +1 -1
  51. package/dist/signify-ts.cjs.map +7 -0
  52. package/dist/signify-ts.cjs.production.min.js +1 -1
  53. package/dist/signify-ts.cjs.production.min.js.map +1 -1
  54. package/dist/signify-ts.esm.js +6205 -229
  55. package/dist/signify-ts.esm.js.map +1 -1
  56. package/dist/signify-ts.mjs +7818 -0
  57. package/dist/signify-ts.mjs.map +7 -0
  58. package/package.json +49 -49
  59. package/src/buffer-polyfill.ts +5 -0
  60. package/src/exports.ts +44 -0
  61. package/src/index.ts +4 -5
  62. package/src/keri/app/aiding.ts +493 -0
  63. package/src/keri/app/clienting.ts +492 -0
  64. package/src/keri/app/contacting.ts +188 -0
  65. package/src/keri/app/controller.ts +372 -0
  66. package/src/keri/app/coring.ts +225 -0
  67. package/src/keri/app/credentialing.ts +841 -0
  68. package/src/keri/app/escrowing.ts +34 -0
  69. package/src/keri/app/exchanging.ts +220 -0
  70. package/src/keri/app/grouping.ts +90 -0
  71. package/src/keri/app/habery.ts +118 -85
  72. package/src/keri/app/notifying.ts +69 -0
  73. package/src/keri/core/authing.ts +73 -85
  74. package/src/keri/core/bexter.ts +138 -0
  75. package/src/keri/core/cigar.ts +10 -11
  76. package/src/keri/core/cipher.ts +23 -14
  77. package/src/keri/core/core.ts +223 -81
  78. package/src/keri/core/counter.ts +182 -116
  79. package/src/keri/core/decrypter.ts +48 -34
  80. package/src/keri/core/diger.ts +23 -22
  81. package/src/keri/core/encrypter.ts +37 -27
  82. package/src/keri/core/eventing.ts +468 -106
  83. package/src/keri/core/httping.ts +151 -105
  84. package/src/keri/core/indexer.ts +313 -211
  85. package/src/keri/core/keeping.ts +679 -3
  86. package/src/keri/core/kering.ts +4 -6
  87. package/src/keri/core/manager.ts +660 -499
  88. package/src/keri/core/matter.ts +382 -148
  89. package/src/keri/core/number.ts +56 -11
  90. package/src/keri/core/pather.ts +98 -0
  91. package/src/keri/core/prefixer.ts +122 -101
  92. package/src/keri/core/saider.ts +104 -76
  93. package/src/keri/core/salter.ts +71 -40
  94. package/src/keri/core/seqner.ts +46 -0
  95. package/src/keri/core/serder.ts +102 -38
  96. package/src/keri/core/siger.ts +19 -18
  97. package/src/keri/core/signer.ts +73 -53
  98. package/src/keri/core/tholder.ts +196 -30
  99. package/src/keri/core/utils.ts +121 -50
  100. package/src/keri/core/vdring.ts +94 -0
  101. package/src/keri/core/verfer.ts +22 -9
  102. package/src/keri/end/ending.ts +111 -101
  103. package/src/math.ts +3 -0
  104. package/src/ready.ts +5 -0
  105. package/dist/keri/app/accountant.d.ts +0 -10
  106. package/dist/keri/app/apping.d.ts +0 -1
  107. package/dist/keri/app/client.d.ts +0 -7
  108. package/dist/keri/app/signify.d.ts +0 -6
  109. package/src/keri/app/accountant.ts +0 -35
  110. package/src/keri/app/apping.ts +0 -12
  111. package/src/keri/app/client.ts +0 -30
  112. package/src/keri/app/signify.ts +0 -12
  113. package/src/keri/app/tsconfig.json +0 -100
  114. package/src/keri/core/tsconfig.json +0 -100
  115. package/src/keri/end/tsconfig.json +0 -100
@@ -0,0 +1,492 @@
1
+ import { Agent, Controller } from './controller';
2
+ import { Tier } from '../core/salter';
3
+ import { Authenticater } from '../core/authing';
4
+ import { ExternalModule, KeyManager } from '../core/keeping';
5
+
6
+ import { Identifier } from './aiding';
7
+ import { Contacts, Challenges } from './contacting';
8
+ import { Oobis, Operations, KeyEvents, KeyStates } from './coring';
9
+ import { Credentials, Ipex, Registries, Schemas } from './credentialing';
10
+ import { Notifications } from './notifying';
11
+ import { Escrows } from './escrowing';
12
+ import { Groups } from './grouping';
13
+ import { Exchanges } from './exchanging';
14
+
15
+ const DEFAULT_BOOT_URL = 'http://localhost:3903';
16
+
17
+ class State {
18
+ agent: any | null;
19
+ controller: any | null;
20
+ ridx: number;
21
+ pidx: number;
22
+
23
+ constructor() {
24
+ this.agent = null;
25
+ this.controller = null;
26
+ this.pidx = 0;
27
+ this.ridx = 0;
28
+ }
29
+ }
30
+
31
+ /** SignifyClient */
32
+ export class SignifyClient {
33
+ public controller: Controller;
34
+ public url: string;
35
+ public bran: string;
36
+ public pidx: number;
37
+ public agent: Agent | null;
38
+ public authn: Authenticater | null;
39
+ public manager: KeyManager | null;
40
+ public tier: Tier;
41
+ public bootUrl: string;
42
+ public exteralModules: ExternalModule[];
43
+
44
+ /**
45
+ * SignifyClient constructor
46
+ * @param {string} url KERIA admin interface URL
47
+ * @param {string} bran Base64 21 char string that is used as base material for seed of the client AID
48
+ * @param {Tier} tier Security tier for generating keys of the client AID (high | mewdium | low)
49
+ * @param {string} bootUrl KERIA boot interface URL
50
+ * @param {ExternalModule[]} externalModules list of external modules to load
51
+ */
52
+ constructor(
53
+ url: string,
54
+ bran: string,
55
+ tier: Tier = Tier.low,
56
+ bootUrl: string = DEFAULT_BOOT_URL,
57
+ externalModules: ExternalModule[] = []
58
+ ) {
59
+ this.url = url;
60
+ if (bran.length < 21) {
61
+ throw Error('bran must be 21 characters');
62
+ }
63
+ this.bran = bran;
64
+ this.pidx = 0;
65
+ this.controller = new Controller(bran, tier);
66
+ this.authn = null;
67
+ this.agent = null;
68
+ this.manager = null;
69
+ this.tier = tier;
70
+ this.bootUrl = bootUrl;
71
+ this.exteralModules = externalModules;
72
+ }
73
+
74
+ get data() {
75
+ return [this.url, this.bran, this.pidx, this.authn];
76
+ }
77
+
78
+ /**
79
+ * Boot a KERIA agent
80
+ * @async
81
+ * @returns {Promise<Response>} A promise to the result of the boot
82
+ */
83
+ async boot(): Promise<Response> {
84
+ const [evt, sign] = this.controller?.event ?? [];
85
+ const data = {
86
+ icp: evt.ked,
87
+ sig: sign.qb64,
88
+ stem: this.controller?.stem,
89
+ pidx: 1,
90
+ tier: this.controller?.tier,
91
+ };
92
+
93
+ return await fetch(this.bootUrl + '/boot', {
94
+ method: 'POST',
95
+ body: JSON.stringify(data),
96
+ headers: {
97
+ 'Content-Type': 'application/json',
98
+ },
99
+ });
100
+ }
101
+
102
+ /**
103
+ * Get state of the agent and the client
104
+ * @async
105
+ * @returns {Promise<Response>} A promise to the state
106
+ */
107
+ async state(): Promise<State> {
108
+ const caid = this.controller?.pre;
109
+
110
+ const res = await fetch(this.url + `/agent/${caid}`);
111
+ if (res.status == 404) {
112
+ throw new Error(`agent does not exist for controller ${caid}`);
113
+ }
114
+
115
+ const data = await res.json();
116
+ const state = new State();
117
+ state.agent = data.agent ?? {};
118
+ state.controller = data.controller ?? {};
119
+ state.ridx = data.ridx ?? 0;
120
+ state.pidx = data.pidx ?? 0;
121
+ return state;
122
+ }
123
+
124
+ /** Connect to a KERIA agent
125
+ * @async
126
+ */
127
+ async connect() {
128
+ const state = await this.state();
129
+ this.pidx = state.pidx;
130
+ //Create controller representing the local client AID
131
+ this.controller = new Controller(
132
+ this.bran,
133
+ this.tier,
134
+ 0,
135
+ state.controller
136
+ );
137
+ this.controller.ridx = state.ridx !== undefined ? state.ridx : 0;
138
+ // Create agent representing the AID of KERIA cloud agent
139
+ this.agent = new Agent(state.agent);
140
+ if (this.agent.anchor != this.controller.pre) {
141
+ throw Error(
142
+ 'commitment to controller AID missing in agent inception event'
143
+ );
144
+ }
145
+ if (this.controller.serder.ked.s == 0) {
146
+ await this.approveDelegation();
147
+ }
148
+ this.manager = new KeyManager(
149
+ this.controller.salter,
150
+ this.exteralModules
151
+ );
152
+ this.authn = new Authenticater(
153
+ this.controller.signer,
154
+ this.agent.verfer!
155
+ );
156
+ }
157
+
158
+ /**
159
+ * Fetch a resource from the KERIA agent
160
+ * @async
161
+ * @param {string} path Path to the resource
162
+ * @param {string} method HTTP method
163
+ * @param {any} data Data to be sent in the body of the resource
164
+ * @param {Headers} [extraHeaders] Optional extra headers to be sent with the request
165
+ * @returns {Promise<Response>} A promise to the result of the fetch
166
+ */
167
+ async fetch(
168
+ path: string,
169
+ method: string,
170
+ data: any,
171
+ extraHeaders?: Headers
172
+ ): Promise<Response> {
173
+ const headers = new Headers();
174
+ let signed_headers = new Headers();
175
+ const final_headers = new Headers();
176
+
177
+ headers.set('Signify-Resource', this.controller.pre);
178
+ headers.set(
179
+ 'Signify-Timestamp',
180
+ new Date().toISOString().replace('Z', '000+00:00')
181
+ );
182
+ headers.set('Content-Type', 'application/json');
183
+
184
+ const _body = method == 'GET' ? null : JSON.stringify(data);
185
+ if (_body !== null) {
186
+ headers.set('Content-Length', String(_body.length));
187
+ }
188
+ if (this.authn) {
189
+ signed_headers = this.authn.sign(
190
+ headers,
191
+ method,
192
+ path.split('?')[0]
193
+ );
194
+ } else {
195
+ throw new Error('client need to call connect first');
196
+ }
197
+
198
+ signed_headers.forEach((value, key) => {
199
+ final_headers.set(key, value);
200
+ });
201
+ if (extraHeaders !== undefined) {
202
+ extraHeaders.forEach((value, key) => {
203
+ final_headers.append(key, value);
204
+ });
205
+ }
206
+ const res = await fetch(this.url + path, {
207
+ method: method,
208
+ body: _body,
209
+ headers: final_headers,
210
+ });
211
+ if (!res.ok) {
212
+ const error = await res.text();
213
+ const message = `HTTP ${method} ${path} - ${res.status} ${res.statusText} - ${error}`;
214
+ throw new Error(message);
215
+ }
216
+ const isSameAgent =
217
+ this.agent?.pre === res.headers.get('signify-resource');
218
+ if (!isSameAgent) {
219
+ throw new Error('message from a different remote agent');
220
+ }
221
+
222
+ const verification = this.authn.verify(
223
+ res.headers,
224
+ method,
225
+ path.split('?')[0]
226
+ );
227
+ if (verification) {
228
+ return res;
229
+ } else {
230
+ throw new Error('response verification failed');
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Fetch a resource from from an external URL with headers signed by an AID
236
+ * @async
237
+ * @param {string} url URL of the resource
238
+ * @param {string} path Path to the resource
239
+ * @param {string} method HTTP method
240
+ * @param {any} data Data to be sent in the body of the resource
241
+ * @param {string} aidName Name or alias of the AID to be used for signing
242
+ * @returns {Promise<Response>} A promise to the result of the fetch
243
+ */
244
+ async signedFetch(
245
+ url: string,
246
+ path: string,
247
+ method: string,
248
+ data: any,
249
+ aidName: string
250
+ ): Promise<Response> {
251
+ const hab = await this.identifiers().get(aidName);
252
+ const keeper = this.manager!.get(hab);
253
+
254
+ const authenticator = new Authenticater(
255
+ keeper.signers[0],
256
+ keeper.signers[0].verfer
257
+ );
258
+
259
+ const headers = new Headers();
260
+ headers.set('Signify-Resource', hab.prefix);
261
+ headers.set(
262
+ 'Signify-Timestamp',
263
+ new Date().toISOString().replace('Z', '000+00:00')
264
+ );
265
+
266
+ if (data !== null) {
267
+ headers.set('Content-Length', data.length);
268
+ } else {
269
+ headers.set('Content-Length', '0');
270
+ }
271
+ const signed_headers = authenticator.sign(
272
+ headers,
273
+ method,
274
+ path.split('?')[0]
275
+ );
276
+ let _body = null;
277
+ if (method != 'GET') {
278
+ if (data instanceof FormData) {
279
+ _body = data;
280
+ // do not set the content type, let the browser do it
281
+ // headers.set('Content-Type', 'multipart/form-data')
282
+ } else {
283
+ _body = JSON.stringify(data);
284
+ headers.set('Content-Type', 'application/json');
285
+ }
286
+ } else {
287
+ headers.set('Content-Type', 'application/json');
288
+ }
289
+
290
+ return await fetch(url + path, {
291
+ method: method,
292
+ body: _body,
293
+ headers: signed_headers,
294
+ });
295
+ }
296
+
297
+ /**
298
+ * Approve the delegation of the client AID to the KERIA agent
299
+ * @async
300
+ * @returns {Promise<Response>} A promise to the result of the approval
301
+ */
302
+ async approveDelegation(): Promise<Response> {
303
+ const sigs = this.controller.approveDelegation(this.agent!);
304
+
305
+ const data = {
306
+ ixn: this.controller.serder.ked,
307
+ sigs: sigs,
308
+ };
309
+
310
+ return await fetch(
311
+ this.url + '/agent/' + this.controller.pre + '?type=ixn',
312
+ {
313
+ method: 'PUT',
314
+ body: JSON.stringify(data),
315
+ headers: {
316
+ 'Content-Type': 'application/json',
317
+ },
318
+ }
319
+ );
320
+ }
321
+
322
+ /**
323
+ * Save old client passcode in KERIA agent
324
+ * @async
325
+ * @param {string} passcode Passcode to be saved
326
+ * @returns {Promise<Response>} A promise to the result of the save
327
+ */
328
+ async saveOldPasscode(passcode: string): Promise<Response> {
329
+ const caid = this.controller?.pre;
330
+ const body = { salt: passcode };
331
+ return await fetch(this.url + '/salt/' + caid, {
332
+ method: 'PUT',
333
+ body: JSON.stringify(body),
334
+ headers: {
335
+ 'Content-Type': 'application/json',
336
+ },
337
+ });
338
+ }
339
+
340
+ /**
341
+ * Delete a saved passcode from KERIA agent
342
+ * @async
343
+ * @returns {Promise<Response>} A promise to the result of the deletion
344
+ */
345
+ async deletePasscode(): Promise<Response> {
346
+ const caid = this.controller?.pre;
347
+ return await fetch(this.url + '/salt/' + caid, {
348
+ method: 'DELETE',
349
+ headers: {
350
+ 'Content-Type': 'application/json',
351
+ },
352
+ });
353
+ }
354
+
355
+ /**
356
+ * Rotate the client AID
357
+ * @async
358
+ * @param {string} nbran Base64 21 char string that is used as base material for the new seed
359
+ * @param {Array<string>} aids List of managed AIDs to be rotated
360
+ * @returns {Promise<Response>} A promise to the result of the rotation
361
+ */
362
+ async rotate(nbran: string, aids: string[]): Promise<Response> {
363
+ const data = this.controller.rotate(nbran, aids);
364
+ return await fetch(this.url + '/agent/' + this.controller.pre, {
365
+ method: 'PUT',
366
+ body: JSON.stringify(data),
367
+ headers: {
368
+ 'Content-Type': 'application/json',
369
+ },
370
+ });
371
+ }
372
+
373
+ /**
374
+ * Get identifiers resource
375
+ * @returns {Identifier}
376
+ */
377
+ identifiers(): Identifier {
378
+ return new Identifier(this);
379
+ }
380
+
381
+ /**
382
+ * Get OOBIs resource
383
+ * @returns {Oobis}
384
+ */
385
+ oobis(): Oobis {
386
+ return new Oobis(this);
387
+ }
388
+
389
+ /**
390
+ * Get operations resource
391
+ * @returns {Operations}
392
+ */
393
+ operations(): Operations {
394
+ return new Operations(this);
395
+ }
396
+
397
+ /**
398
+ * Get keyEvents resource
399
+ * @returns {KeyEvents}
400
+ */
401
+ keyEvents(): KeyEvents {
402
+ return new KeyEvents(this);
403
+ }
404
+
405
+ /**
406
+ * Get keyStates resource
407
+ * @returns {KeyStates}
408
+ */
409
+ keyStates(): KeyStates {
410
+ return new KeyStates(this);
411
+ }
412
+
413
+ /**
414
+ * Get credentials resource
415
+ * @returns {Credentials}
416
+ */
417
+ credentials(): Credentials {
418
+ return new Credentials(this);
419
+ }
420
+
421
+ /**
422
+ * Get IPEX resource
423
+ * @returns {Ipex}
424
+ */
425
+ ipex(): Ipex {
426
+ return new Ipex(this);
427
+ }
428
+
429
+ /**
430
+ * Get registries resource
431
+ * @returns {Registries}
432
+ */
433
+ registries(): Registries {
434
+ return new Registries(this);
435
+ }
436
+
437
+ /**
438
+ * Get schemas resource
439
+ * @returns {Schemas}
440
+ */
441
+ schemas(): Schemas {
442
+ return new Schemas(this);
443
+ }
444
+
445
+ /**
446
+ * Get challenges resource
447
+ * @returns {Challenges}
448
+ */
449
+ challenges(): Challenges {
450
+ return new Challenges(this);
451
+ }
452
+
453
+ /**
454
+ * Get contacts resource
455
+ * @returns {Contacts}
456
+ */
457
+ contacts(): Contacts {
458
+ return new Contacts(this);
459
+ }
460
+
461
+ /**
462
+ * Get notifications resource
463
+ * @returns {Notifications}
464
+ */
465
+ notifications(): Notifications {
466
+ return new Notifications(this);
467
+ }
468
+
469
+ /**
470
+ * Get escrows resource
471
+ * @returns {Escrows}
472
+ */
473
+ escrows(): Escrows {
474
+ return new Escrows(this);
475
+ }
476
+
477
+ /**
478
+ * Get groups resource
479
+ * @returns {Groups}
480
+ */
481
+ groups(): Groups {
482
+ return new Groups(this);
483
+ }
484
+
485
+ /**
486
+ * Get exchange resource
487
+ * @returns {Exchanges}
488
+ */
489
+ exchanges(): Exchanges {
490
+ return new Exchanges(this);
491
+ }
492
+ }
@@ -0,0 +1,188 @@
1
+ import { SignifyClient } from './clienting';
2
+ import { Operation } from './coring';
3
+
4
+ /**
5
+ * Contacts
6
+ */
7
+ export class Contacts {
8
+ client: SignifyClient;
9
+ /**
10
+ * Contacts
11
+ * @param {SignifyClient} client
12
+ */
13
+ constructor(client: SignifyClient) {
14
+ this.client = client;
15
+ }
16
+
17
+ /**
18
+ * List contacts
19
+ * @async
20
+ * @param {string} [group] Optional group name to filter contacts
21
+ * @param {string} [filterField] Optional field name to filter contacts
22
+ * @param {string} [filterValue] Optional field value to filter contacts
23
+ * @returns {Promise<any>} A promise to the list of contacts
24
+ */
25
+ async list(
26
+ group?: string,
27
+ filterField?: string,
28
+ filterValue?: string
29
+ ): Promise<any> {
30
+ const params = new URLSearchParams();
31
+ if (group !== undefined) {
32
+ params.append('group', group);
33
+ }
34
+ if (filterField !== undefined && filterValue !== undefined) {
35
+ params.append('filter_field', filterField);
36
+ params.append('filter_value', filterValue);
37
+ }
38
+
39
+ const path = `/contacts` + '?' + params.toString();
40
+ const method = 'GET';
41
+ const res = await this.client.fetch(path, method, null);
42
+ return await res.json();
43
+ }
44
+
45
+ /**
46
+ * Get a contact
47
+ * @async
48
+ * @param {string} pre Prefix of the contact
49
+ * @returns {Promise<any>} A promise to the contact
50
+ */
51
+ async get(pre: string): Promise<any> {
52
+ const path = `/contacts/` + pre;
53
+ const method = 'GET';
54
+ const res = await this.client.fetch(path, method, null);
55
+ return await res.json();
56
+ }
57
+
58
+ /**
59
+ * Add a contact
60
+ * @async
61
+ * @param {string} pre Prefix of the contact
62
+ * @param {any} info Information about the contact
63
+ * @returns {Promise<any>} A promise to the result of the addition
64
+ */
65
+ async add(pre: string, info: any): Promise<any> {
66
+ const path = `/contacts/` + pre;
67
+ const method = 'POST';
68
+
69
+ const res = await this.client.fetch(path, method, info);
70
+ return await res.json();
71
+ }
72
+
73
+ /**
74
+ * Delete a contact
75
+ * @async
76
+ * @param {string} pre Prefix of the contact
77
+ * @returns {Promise<any>} A promise to the result of the deletion
78
+ */
79
+ async delete(pre: string): Promise<any> {
80
+ const path = `/contacts/` + pre;
81
+ const method = 'DELETE';
82
+
83
+ const res = await this.client.fetch(path, method, null);
84
+ return await res.json();
85
+ }
86
+
87
+ /**
88
+ * Update a contact
89
+ * @async
90
+ * @param {string} pre Prefix of the contact
91
+ * @param {any} info Updated information about the contact
92
+ * @returns {Promise<any>} A promise to the result of the update
93
+ */
94
+ async update(pre: string, info: any): Promise<any> {
95
+ const path = `/contacts/` + pre;
96
+ const method = 'PUT';
97
+
98
+ const res = await this.client.fetch(path, method, info);
99
+ return await res.json();
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Challenges
105
+ */
106
+ export class Challenges {
107
+ client: SignifyClient;
108
+ /**
109
+ * Challenges
110
+ * @param {SignifyClient} client
111
+ */
112
+ constructor(client: SignifyClient) {
113
+ this.client = client;
114
+ }
115
+
116
+ /**
117
+ * Generate a random challenge word list based on BIP39
118
+ * @async
119
+ * @param {number} strength Integer representing the strength of the challenge. Typically 128 or 256
120
+ * @returns {Promise<any>} A promise to the list of random words
121
+ */
122
+ async generate(strength: number = 128): Promise<any> {
123
+ const path = `/challenges?strength=${strength.toString()}`;
124
+ const method = 'GET';
125
+ const res = await this.client.fetch(path, method, null);
126
+ return await res.json();
127
+ }
128
+
129
+ /**
130
+ * Respond to a challenge by signing a message with the list of words
131
+ * @async
132
+ * @param {string} name Name or alias of the identifier
133
+ * @param {string} recipient Prefix of the recipient of the response
134
+ * @param {Array<string>} words List of words to embed in the signed response
135
+ * @returns {Promise<Response>} A promise to the result of the response
136
+ */
137
+ async respond(
138
+ name: string,
139
+ recipient: string,
140
+ words: string[]
141
+ ): Promise<Response> {
142
+ const hab = await this.client.identifiers().get(name);
143
+ const exchanges = this.client.exchanges();
144
+ const resp = await exchanges.send(
145
+ name,
146
+ 'challenge',
147
+ hab,
148
+ '/challenge/response',
149
+ { words: words },
150
+ {},
151
+ [recipient]
152
+ );
153
+ return resp;
154
+ }
155
+
156
+ /**
157
+ * Ask Agent to verify a given sender signed the provided words
158
+ * @param {string} source Prefix of the identifier that was challenged
159
+ * @param {Array<string>} words List of challenge words to check for
160
+ * @returns A promise to the long running operation
161
+ */
162
+ async verify(source: string, words: string[]): Promise<Operation<unknown>> {
163
+ const path = `/challenges_verify/${source}`;
164
+ const method = 'POST';
165
+ const data = {
166
+ words: words,
167
+ };
168
+ const res = await this.client.fetch(path, method, data);
169
+
170
+ return await res.json();
171
+ }
172
+
173
+ /**
174
+ * Mark challenge response as signed and accepted
175
+ * @param {string} source Prefix of the identifier that was challenged
176
+ * @param {string} said qb64 AID of exn message representing the signed response
177
+ * @returns {Promise<Response>} A promise to the result
178
+ */
179
+ async responded(source: string, said: string): Promise<Response> {
180
+ const path = `/challenges_verify/${source}`;
181
+ const method = 'PUT';
182
+ const data = {
183
+ said: said,
184
+ };
185
+ const res = await this.client.fetch(path, method, data);
186
+ return res;
187
+ }
188
+ }