signify-ts 0.1.0 → 0.2.0

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 (105) hide show
  1. package/README.md +101 -5
  2. package/dist/buffer-polyfill.d.ts +1 -0
  3. package/dist/exports.d.ts +40 -0
  4. package/dist/index.d.ts +4 -1
  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 +239 -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 -0
  15. package/dist/keri/app/notifying.d.ts +34 -0
  16. package/dist/keri/core/authing.d.ts +10 -0
  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 -68
  21. package/dist/keri/core/counter.d.ts +43 -0
  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 -0
  26. package/dist/keri/core/httping.d.ts +44 -0
  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 -151
  31. package/dist/keri/core/matter.d.ts +116 -47
  32. package/dist/keri/core/number.d.ts +7 -0
  33. package/dist/keri/core/pather.d.ts +7 -0
  34. package/dist/keri/core/prefixer.d.ts +15 -0
  35. package/dist/keri/core/saider.d.ts +23 -0
  36. package/dist/keri/core/salter.d.ts +23 -0
  37. package/dist/keri/core/seqner.d.ts +15 -0
  38. package/dist/keri/core/serder.d.ts +31 -0
  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 -0
  42. package/dist/keri/core/utils.d.ts +20 -14
  43. package/dist/keri/core/vdring.d.ts +16 -0
  44. package/dist/keri/core/verfer.d.ts +13 -0
  45. package/dist/keri/end/ending.d.ts +13 -0
  46. package/dist/math.d.ts +1 -0
  47. package/dist/ready.d.ts +1 -0
  48. package/dist/signify-ts.cjs +7835 -0
  49. package/dist/signify-ts.cjs.development.js +9493 -5
  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 +9341 -5
  55. package/dist/signify-ts.esm.js.map +1 -1
  56. package/dist/signify-ts.mjs +7811 -0
  57. package/dist/signify-ts.mjs.map +7 -0
  58. package/package.json +51 -49
  59. package/src/buffer-polyfill.ts +5 -0
  60. package/src/exports.ts +44 -0
  61. package/src/index.ts +4 -6
  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 +820 -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 +185 -0
  72. package/src/keri/app/notifying.ts +69 -0
  73. package/src/keri/core/authing.ts +117 -0
  74. package/src/keri/core/bexter.ts +138 -0
  75. package/src/keri/core/cigar.ts +11 -12
  76. package/src/keri/core/cipher.ts +23 -14
  77. package/src/keri/core/core.ts +249 -97
  78. package/src/keri/core/counter.ts +273 -0
  79. package/src/keri/core/decrypter.ts +48 -34
  80. package/src/keri/core/diger.ts +25 -24
  81. package/src/keri/core/encrypter.ts +37 -27
  82. package/src/keri/core/eventing.ts +581 -0
  83. package/src/keri/core/httping.ts +209 -0
  84. package/src/keri/core/indexer.ts +314 -211
  85. package/src/keri/core/keeping.ts +679 -4
  86. package/src/keri/core/kering.ts +4 -6
  87. package/src/keri/core/manager.ts +759 -450
  88. package/src/keri/core/matter.ts +404 -135
  89. package/src/keri/core/number.ts +66 -0
  90. package/src/keri/core/pather.ts +98 -0
  91. package/src/keri/core/prefixer.ts +233 -0
  92. package/src/keri/core/saider.ts +186 -0
  93. package/src/keri/core/salter.ts +76 -41
  94. package/src/keri/core/seqner.ts +46 -0
  95. package/src/keri/core/serder.ts +163 -0
  96. package/src/keri/core/siger.ts +19 -18
  97. package/src/keri/core/signer.ts +74 -53
  98. package/src/keri/core/tholder.ts +218 -0
  99. package/src/keri/core/utils.ts +120 -45
  100. package/src/keri/core/vdring.ts +94 -0
  101. package/src/keri/core/verfer.ts +25 -11
  102. package/src/keri/end/ending.ts +170 -0
  103. package/src/math.ts +3 -0
  104. package/src/ready.ts +5 -0
  105. package/src/keri/core/tsconfig.json +0 -100
@@ -0,0 +1,34 @@
1
+ import { SignifyClient } from './clienting';
2
+
3
+ /**
4
+ * Escrows
5
+ */
6
+ export class Escrows {
7
+ client: SignifyClient;
8
+
9
+ /**
10
+ * Escrows
11
+ * @param {SignifyClient} client
12
+ */
13
+ constructor(client: SignifyClient) {
14
+ this.client = client;
15
+ }
16
+
17
+ /**
18
+ * List replay messages
19
+ * @async
20
+ * @param {string} [route] Optional route in the replay message
21
+ * @returns {Promise<any>} A promise to the list of replay messages
22
+ */
23
+ async listReply(route?: string): Promise<any> {
24
+ const params = new URLSearchParams();
25
+ if (route !== undefined) {
26
+ params.append('route', route);
27
+ }
28
+
29
+ const path = `/escrows/rpy` + '?' + params.toString();
30
+ const method = 'GET';
31
+ const res = await this.client.fetch(path, method, null);
32
+ return await res.json();
33
+ }
34
+ }
@@ -0,0 +1,220 @@
1
+ import { SignifyClient } from './clienting';
2
+ import { b, d, Dict, Ident, Ilks, Serials, versify } from '../core/core';
3
+ import { Serder } from '../core/serder';
4
+ import { nowUTC } from '../core/utils';
5
+ import { Pather } from '../core/pather';
6
+ import { Counter, CtrDex } from '../core/counter';
7
+ import { Saider } from '../core/saider';
8
+
9
+ /**
10
+ * Exchanges
11
+ */
12
+ export class Exchanges {
13
+ client: SignifyClient;
14
+
15
+ /**
16
+ * Exchanges
17
+ * @param {SignifyClient} client
18
+ */
19
+ constructor(client: SignifyClient) {
20
+ this.client = client;
21
+ }
22
+
23
+ /**
24
+ * Create exn message
25
+ * @async
26
+ * @returns {Promise<any>} A promise to the list of replay messages
27
+ * @param sender
28
+ * @param route
29
+ * @param payload
30
+ * @param embeds
31
+ * @param recipient
32
+ * @param datetime
33
+ * @param dig
34
+ */
35
+ async createExchangeMessage(
36
+ sender: Dict<any>,
37
+ route: string,
38
+ payload: Dict<any>,
39
+ embeds: Dict<any>,
40
+ recipient?: string,
41
+ datetime?: string,
42
+ dig?: string
43
+ ): Promise<[Serder, string[], string]> {
44
+ const keeper = this.client.manager!.get(sender);
45
+ const [exn, end] = exchange(
46
+ route,
47
+ payload,
48
+ sender['prefix'],
49
+ recipient,
50
+ datetime,
51
+ dig,
52
+ undefined,
53
+ embeds
54
+ );
55
+
56
+ const sigs = await keeper.sign(b(exn.raw));
57
+ return [exn, sigs, d(end)];
58
+ }
59
+
60
+ /**
61
+ * Send exn messages to list of recipients
62
+ * @async
63
+ * @returns {Promise<any>} A promise to the list of replay messages
64
+ * @param name
65
+ * @param topic
66
+ * @param sender
67
+ * @param route
68
+ * @param payload
69
+ * @param embeds
70
+ * @param recipients
71
+ */
72
+ async send(
73
+ name: string,
74
+ topic: string,
75
+ sender: Dict<any>,
76
+ route: string,
77
+ payload: Dict<any>,
78
+ embeds: Dict<any>,
79
+ recipients: string[]
80
+ ): Promise<any> {
81
+ const [exn, sigs, atc] = await this.createExchangeMessage(
82
+ sender,
83
+ route,
84
+ payload,
85
+ embeds
86
+ );
87
+ return await this.sendFromEvents(
88
+ name,
89
+ topic,
90
+ exn,
91
+ sigs,
92
+ atc,
93
+ recipients
94
+ );
95
+ }
96
+
97
+ /**
98
+ * Send exn messaget to list of recipients
99
+ * @async
100
+ * @returns {Promise<any>} A promise to the list of replay messages
101
+ * @param name
102
+ * @param topic
103
+ * @param exn
104
+ * @param sigs
105
+ * @param atc
106
+ * @param recipients
107
+ */
108
+ async sendFromEvents(
109
+ name: string,
110
+ topic: string,
111
+ exn: Serder,
112
+ sigs: string[],
113
+ atc: string,
114
+ recipients: string[]
115
+ ): Promise<any> {
116
+ const path = `/identifiers/${name}/exchanges`;
117
+ const method = 'POST';
118
+ const data: any = {
119
+ tpc: topic,
120
+ exn: exn.ked,
121
+ sigs: sigs,
122
+ atc: atc,
123
+ rec: recipients,
124
+ };
125
+
126
+ const res = await this.client.fetch(path, method, data);
127
+ return await res.json();
128
+ }
129
+
130
+ /**
131
+ * Get exn message by said
132
+ * @async
133
+ * @returns A promise to the exn message
134
+ * @param said The said of the exn message
135
+ */
136
+ async get(said: string): Promise<any> {
137
+ const path = `/exchanges/${said}`;
138
+ const method = 'GET';
139
+ const res = await this.client.fetch(path, method, null);
140
+ return await res.json();
141
+ }
142
+ }
143
+
144
+ export function exchange(
145
+ route: string,
146
+ payload: Dict<any>,
147
+ sender: string,
148
+ recipient?: string,
149
+ date?: string,
150
+ dig?: string,
151
+ modifiers?: Dict<any>,
152
+ embeds?: Dict<any>
153
+ ): [Serder, Uint8Array] {
154
+ const vs = versify(Ident.KERI, undefined, Serials.JSON, 0);
155
+ const ilk = Ilks.exn;
156
+ const dt =
157
+ date !== undefined
158
+ ? date
159
+ : nowUTC().toISOString().replace('Z', '000+00:00');
160
+ const p = dig !== undefined ? dig : '';
161
+ const q = modifiers !== undefined ? modifiers : {};
162
+ const ems = embeds != undefined ? embeds : {};
163
+
164
+ let e = {} as Dict<any>;
165
+ let end = '';
166
+ Object.entries(ems).forEach(([key, value]) => {
167
+ const serder = value[0];
168
+ const atc = value[1];
169
+ e[key] = serder.ked;
170
+
171
+ if (atc == undefined) {
172
+ return;
173
+ }
174
+ let pathed = '';
175
+ const pather = new Pather({}, undefined, ['e', key]);
176
+ pathed += pather.qb64;
177
+ pathed += atc;
178
+
179
+ const counter = new Counter({
180
+ code: CtrDex.PathedMaterialQuadlets,
181
+ count: Math.floor(pathed.length / 4),
182
+ });
183
+ end += counter.qb64;
184
+ end += pathed;
185
+ });
186
+
187
+ if (Object.keys(e).length > 0) {
188
+ e['d'] = '';
189
+ [, e] = Saider.saidify(e);
190
+ }
191
+
192
+ const attrs = {} as Dict<any>;
193
+
194
+ if (recipient !== undefined) {
195
+ attrs['i'] = recipient;
196
+ }
197
+
198
+ const a = {
199
+ ...attrs,
200
+ ...payload,
201
+ };
202
+
203
+ const _ked = {
204
+ v: vs,
205
+ t: ilk,
206
+ d: '',
207
+ i: sender,
208
+ p: p,
209
+ dt: dt,
210
+ r: route,
211
+ q: q,
212
+ a: a,
213
+ e: e,
214
+ };
215
+ const [, ked] = Saider.saidify(_ked);
216
+
217
+ const exn = new Serder(ked);
218
+
219
+ return [exn, b(end)];
220
+ }
@@ -0,0 +1,90 @@
1
+ import { SignifyClient } from './clienting';
2
+ import { Dict } from '../core/core';
3
+
4
+ /**
5
+ * Groups
6
+ */
7
+ export class Groups {
8
+ client: SignifyClient;
9
+
10
+ /**
11
+ * Groups
12
+ * @param {SignifyClient} client
13
+ */
14
+ constructor(client: SignifyClient) {
15
+ this.client = client;
16
+ }
17
+
18
+ /**
19
+ * Get group request messages
20
+ * @async
21
+ * @param {string} [said] SAID of exn message to load
22
+ * @returns {Promise<any>} A promise to the list of replay messages
23
+ */
24
+ async getRequest(said: string): Promise<any> {
25
+ const path = `/multisig/request/` + said;
26
+ const method = 'GET';
27
+ const res = await this.client.fetch(path, method, null);
28
+ return await res.json();
29
+ }
30
+
31
+ /**
32
+ * Send multisig exn request messages to other group members
33
+ * @async
34
+ * @param {string} [name] human readable name of group AID
35
+ * @param {Dict<any>} [exn] exn message to send to other members
36
+ * @param {string[]} [sigs] signature of the participant over the exn
37
+ * @param {string} [atc] additional attachments from embedded events in exn
38
+ * @returns {Promise<any>} A promise to the list of replay messages
39
+ */
40
+ async sendRequest(
41
+ name: string,
42
+ exn: Dict<any>,
43
+ sigs: string[],
44
+ atc: string
45
+ ): Promise<any> {
46
+ const path = `/identifiers/${name}/multisig/request`;
47
+ const method = 'POST';
48
+ const data = {
49
+ exn: exn,
50
+ sigs: sigs,
51
+ atc: atc,
52
+ };
53
+ const res = await this.client.fetch(path, method, data);
54
+ return await res.json();
55
+ }
56
+
57
+ /**
58
+ * Join multisig group using rotation event.
59
+ * This can be used by participants being asked to contribute keys to a rotation event to join an existing group.
60
+ * @async
61
+ * @param {string} [name] human readable name of group AID
62
+ * @param {any} [rot] rotation event
63
+ * @param {any} [sigs] signatures
64
+ * @param {string} [gid] prefix
65
+ * @param {string[]} [smids] array of particpants
66
+ * @param {string[]} [rmids] array of particpants
67
+ * @returns {Promise<any>} A promise to the list of replay messages
68
+ */
69
+ async join(
70
+ name: string,
71
+ rot: any,
72
+ sigs: any, //string[],
73
+ gid: string,
74
+ smids: string[],
75
+ rmids: string[]
76
+ ): Promise<any> {
77
+ const path = `/identifiers/${name}/multisig/join`;
78
+ const method = 'POST';
79
+ const data = {
80
+ tpc: 'multisig',
81
+ rot: rot.ked,
82
+ sigs: sigs,
83
+ gid: gid,
84
+ smids: smids,
85
+ rmids: rmids,
86
+ };
87
+ const res = await this.client.fetch(path, method, data);
88
+ return await res.json();
89
+ }
90
+ }
@@ -0,0 +1,185 @@
1
+ import { Algos, Manager } from '../core/manager';
2
+ import { MtrDex } from '../core/matter';
3
+ import { Salter } from '../core/salter';
4
+ import { Verfer } from '../core/verfer';
5
+ import { Diger } from '../core/diger';
6
+ import { incept } from '../core/eventing';
7
+ import { Serder } from '../core/serder';
8
+
9
+ export class TraitCodex {
10
+ EstOnly: string = 'EO'; // Only allow establishment events
11
+ DoNotDelegate: string = 'DND'; // Dot not allow delegated identifiers
12
+ NoBackers: string = 'NB'; // Do not allow backers
13
+ }
14
+
15
+ export const TraitDex = new TraitCodex();
16
+
17
+ export interface HaberyArgs {
18
+ name: string;
19
+ passcode?: string;
20
+ seed?: string | undefined;
21
+ aeid?: string | undefined;
22
+ pidx?: number | undefined;
23
+ salt?: string | undefined;
24
+ tier?: string | undefined;
25
+ }
26
+
27
+ export interface MakeHabArgs {
28
+ code?: string;
29
+ transferable?: boolean;
30
+ isith?: string;
31
+ icount?: number;
32
+ nsith?: string;
33
+ ncount?: number;
34
+ toad?: string | number;
35
+ wits?: Array<string>;
36
+ delpre?: string;
37
+ estOnly?: boolean;
38
+ DnD?: boolean;
39
+ data?: any;
40
+ }
41
+
42
+ export class Hab {
43
+ public name: string;
44
+ public serder: Serder;
45
+
46
+ constructor(name: string, icp: Serder) {
47
+ this.name = name;
48
+ this.serder = icp;
49
+ }
50
+
51
+ get pre(): string {
52
+ return this.serder.ked['i'];
53
+ }
54
+ }
55
+
56
+ export class Habery {
57
+ private readonly _name: string;
58
+ private readonly _mgr: Manager;
59
+ private readonly _habs: Map<string, Hab> = new Map<string, Hab>();
60
+
61
+ constructor({ name, passcode, seed, aeid, pidx, salt }: HaberyArgs) {
62
+ this._name = name;
63
+ if (passcode != undefined && seed == undefined) {
64
+ if (passcode.length < 21) {
65
+ throw new Error('Bran (passcode seed material) too short.');
66
+ }
67
+
68
+ const bran = MtrDex.Salt_128 + 'A' + passcode.substring(0, 21); // qb64 salt for seed
69
+ const signer = new Salter({ qb64: bran }).signer(
70
+ MtrDex.Ed25519_Seed,
71
+ false
72
+ );
73
+ seed = signer.qb64;
74
+ if (aeid == undefined) {
75
+ aeid = signer.verfer.qb64; // lest it remove encryption
76
+ }
77
+ }
78
+ let algo;
79
+ const salter =
80
+ salt != undefined ? new Salter({ qb64: salt }) : undefined;
81
+ if (salt != undefined) {
82
+ algo = Algos.salty;
83
+ } else {
84
+ algo = Algos.randy;
85
+ }
86
+
87
+ this._mgr = new Manager({
88
+ seed: seed,
89
+ aeid: aeid,
90
+ pidx: pidx,
91
+ algo: algo,
92
+ salter: salter,
93
+ });
94
+ }
95
+
96
+ get mgr(): Manager {
97
+ return this._mgr;
98
+ }
99
+
100
+ get habs(): Array<Hab> {
101
+ return Array.from(this._habs.values());
102
+ }
103
+
104
+ habByName(name: string): Hab | undefined {
105
+ return this._habs.get(name);
106
+ }
107
+
108
+ makeHab(
109
+ name: string,
110
+ {
111
+ code = MtrDex.Blake3_256,
112
+ transferable = true,
113
+ isith = undefined,
114
+ icount = 1,
115
+ nsith = undefined,
116
+ ncount = undefined,
117
+ toad = undefined,
118
+ wits = undefined,
119
+ delpre = undefined,
120
+ estOnly = false,
121
+ DnD = false,
122
+ data = undefined,
123
+ }: MakeHabArgs
124
+ ): Hab {
125
+ if (nsith == undefined) {
126
+ nsith = isith;
127
+ }
128
+ if (ncount == undefined) {
129
+ ncount = icount;
130
+ }
131
+ if (!transferable) {
132
+ ncount = 0;
133
+ nsith = '0';
134
+ code = MtrDex.Ed25519N;
135
+ }
136
+
137
+ const [verfers, digers] = this._mgr.incept({
138
+ icount: icount,
139
+ ncount: ncount,
140
+ stem: this.name,
141
+ transferable: transferable,
142
+ temp: false,
143
+ });
144
+
145
+ icount = verfers.length;
146
+ ncount = digers != undefined ? digers.length : 0;
147
+ if (isith == undefined) {
148
+ isith = `${Math.max(1, Math.ceil(icount / 2)).toString(16)}`;
149
+ }
150
+ if (nsith == undefined) {
151
+ nsith = `${Math.max(1, Math.ceil(ncount / 2)).toString(16)}`;
152
+ }
153
+
154
+ const cnfg = new Array<string>();
155
+ if (estOnly) {
156
+ cnfg.push(TraitDex.EstOnly);
157
+ }
158
+ if (DnD) {
159
+ cnfg.push(TraitDex.DoNotDelegate);
160
+ }
161
+
162
+ const keys = Array.from(verfers, (verfer: Verfer) => verfer.qb64);
163
+ const ndigs = Array.from(digers, (diger: Diger) => diger.qb64);
164
+
165
+ const icp = incept({
166
+ keys,
167
+ isith,
168
+ ndigs,
169
+ nsith,
170
+ toad,
171
+ wits,
172
+ cnfg,
173
+ data,
174
+ code,
175
+ delpre,
176
+ });
177
+ const hab = new Hab(name, icp);
178
+ this._habs.set(name, hab);
179
+ return hab;
180
+ }
181
+
182
+ get name(): string {
183
+ return this._name;
184
+ }
185
+ }
@@ -0,0 +1,69 @@
1
+ import { SignifyClient } from './clienting';
2
+ import { parseRangeHeaders } from '../core/httping';
3
+
4
+ /**
5
+ * Notifications
6
+ */
7
+ export class Notifications {
8
+ client: SignifyClient;
9
+
10
+ /**
11
+ * Notifications
12
+ * @param {SignifyClient} client
13
+ */
14
+ constructor(client: SignifyClient) {
15
+ this.client = client;
16
+ }
17
+
18
+ /**
19
+ * List notifications
20
+ * @async
21
+ * @param {number} [start=0] Start index of list of notifications, defaults to 0
22
+ * @param {number} [end=24] End index of list of notifications, defaults to 24
23
+ * @returns {Promise<any>} A promise to the list of notifications
24
+ */
25
+ async list(start: number = 0, end: number = 24): Promise<any> {
26
+ const extraHeaders = new Headers();
27
+ extraHeaders.append('Range', `notes=${start}-${end}`);
28
+
29
+ const path = `/notifications`;
30
+ const method = 'GET';
31
+ const res = await this.client.fetch(path, method, null, extraHeaders);
32
+
33
+ const cr = res.headers.get('content-range');
34
+ const range = parseRangeHeaders(cr, 'notes');
35
+ const notes = await res.json();
36
+
37
+ return {
38
+ start: range.start,
39
+ end: range.end,
40
+ total: range.total,
41
+ notes: notes,
42
+ };
43
+ }
44
+
45
+ /**
46
+ * Mark a notification as read
47
+ * @async
48
+ * @param {string} said SAID of the notification
49
+ * @returns {Promise<string>} A promise to the result of the marking
50
+ */
51
+ async mark(said: string): Promise<string> {
52
+ const path = `/notifications/` + said;
53
+ const method = 'PUT';
54
+ const res = await this.client.fetch(path, method, null);
55
+ return await res.text();
56
+ }
57
+
58
+ /**
59
+ * Delete a notification
60
+ * @async
61
+ * @param {string} said SAID of the notification
62
+ * @returns {Promise<any>} A promise to the result of the deletion
63
+ */
64
+ async delete(said: string): Promise<void> {
65
+ const path = `/notifications/` + said;
66
+ const method = 'DELETE';
67
+ await this.client.fetch(path, method, null);
68
+ }
69
+ }
@@ -0,0 +1,117 @@
1
+ import { Signer } from './signer';
2
+ import { Verfer } from './verfer';
3
+ import { desiginput, normalize, siginput } from './httping';
4
+ import { Signage, signature, designature } from '../end/ending';
5
+ import { Cigar } from './cigar';
6
+ import { Siger } from './siger';
7
+ export class Authenticater {
8
+ static DefaultFields = [
9
+ '@method',
10
+ '@path',
11
+ 'signify-resource',
12
+ 'signify-timestamp',
13
+ ];
14
+ private _verfer: Verfer;
15
+ private readonly _csig: Signer;
16
+
17
+ constructor(csig: Signer, verfer: Verfer) {
18
+ this._csig = csig;
19
+ this._verfer = verfer;
20
+ }
21
+
22
+ verify(headers: Headers, method: string, path: string): boolean {
23
+ const siginput = headers.get('Signature-Input');
24
+ if (siginput == null) {
25
+ return false;
26
+ }
27
+ const signature = headers.get('Signature');
28
+ if (signature == null) {
29
+ return false;
30
+ }
31
+ let inputs = desiginput(siginput);
32
+ inputs = inputs.filter((input) => input.name == 'signify');
33
+ if (inputs.length == 0) {
34
+ return false;
35
+ }
36
+ inputs.forEach((input) => {
37
+ const items = new Array<string>();
38
+ input.fields!.forEach((field: string) => {
39
+ if (field.startsWith('@')) {
40
+ if (field == '@method') {
41
+ items.push(`"${field}": ${method}`);
42
+ } else if (field == '@path') {
43
+ items.push(`"${field}": ${path}`);
44
+ }
45
+ } else {
46
+ if (headers.has(field)) {
47
+ const value = normalize(headers.get(field) as string);
48
+ items.push(`"${field}": ${value}`);
49
+ }
50
+ }
51
+ });
52
+ const values = new Array<string>();
53
+ values.push(`(${input.fields!.join(' ')})`);
54
+ values.push(`created=${input.created}`);
55
+ if (input.expires != undefined) {
56
+ values.push(`expires=${input.expires}`);
57
+ }
58
+ if (input.nonce != undefined) {
59
+ values.push(`nonce=${input.nonce}`);
60
+ }
61
+ if (input.keyid != undefined) {
62
+ values.push(`keyid=${input.keyid}`);
63
+ }
64
+ if (input.context != undefined) {
65
+ values.push(`context=${input.context}`);
66
+ }
67
+ if (input.alg != undefined) {
68
+ values.push(`alg=${input.alg}`);
69
+ }
70
+ const params = values.join(';');
71
+ items.push(`"@signature-params: ${params}"`);
72
+ const ser = items.join('\n');
73
+ const signage = designature(signature!);
74
+ const cig = signage[0].markers.get(input.name);
75
+ if (!this._verfer.verify(cig.raw, ser)) {
76
+ throw new Error(`Signature for ${input.keyid} invalid.`);
77
+ }
78
+ });
79
+
80
+ return true;
81
+ }
82
+
83
+ sign(
84
+ headers: Headers,
85
+ method: string,
86
+ path: string,
87
+ fields?: Array<string>
88
+ ): Headers {
89
+ if (fields == undefined) {
90
+ fields = Authenticater.DefaultFields;
91
+ }
92
+
93
+ const [header, sig] = siginput(this._csig, {
94
+ name: 'signify',
95
+ method,
96
+ path,
97
+ headers,
98
+ fields,
99
+ alg: 'ed25519',
100
+ keyid: this._csig.verfer.qb64,
101
+ });
102
+
103
+ header.forEach((value, key) => {
104
+ headers.append(key, value);
105
+ });
106
+
107
+ const markers = new Map<string, Siger | Cigar>();
108
+ markers.set('signify', sig);
109
+ const signage = new Signage(markers, false);
110
+ const signed = signature([signage]);
111
+ signed.forEach((value, key) => {
112
+ headers.append(key, value);
113
+ });
114
+
115
+ return headers;
116
+ }
117
+ }