cojson 0.2.3 → 0.3.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.
- package/dist/account.d.ts +1 -1
- package/dist/coValue.d.ts +5 -13
- package/dist/coValue.js +14 -7
- package/dist/coValue.js.map +1 -1
- package/dist/coValueCore.d.ts +6 -6
- package/dist/coValueCore.js +11 -14
- package/dist/coValueCore.js.map +1 -1
- package/dist/coValues/coList.d.ts +99 -34
- package/dist/coValues/coList.js +162 -72
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.d.ts +96 -31
- package/dist/coValues/coMap.js +157 -114
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coStream.d.ts +67 -23
- package/dist/coValues/coStream.js +131 -59
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/crypto.d.ts +8 -3
- package/dist/crypto.js +6 -6
- package/dist/crypto.js.map +1 -1
- package/dist/group.d.ts +57 -23
- package/dist/group.js +75 -33
- package/dist/group.js.map +1 -1
- package/dist/index.d.ts +8 -6
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/{node.d.ts → localNode.d.ts} +16 -8
- package/dist/{node.js → localNode.js} +48 -40
- package/dist/localNode.js.map +1 -0
- package/dist/permissions.js +6 -3
- package/dist/permissions.js.map +1 -1
- package/dist/queriedCoValues/queriedCoList.d.ts +66 -0
- package/dist/queriedCoValues/queriedCoList.js +120 -0
- package/dist/queriedCoValues/queriedCoList.js.map +1 -0
- package/dist/queriedCoValues/queriedCoMap.d.ts +47 -0
- package/dist/queriedCoValues/queriedCoMap.js +83 -0
- package/dist/queriedCoValues/queriedCoMap.js.map +1 -0
- package/dist/queriedCoValues/queriedCoStream.d.ts +40 -0
- package/dist/queriedCoValues/queriedCoStream.js +72 -0
- package/dist/queriedCoValues/queriedCoStream.js.map +1 -0
- package/dist/queries.d.ts +29 -112
- package/dist/queries.js +44 -227
- package/dist/queries.js.map +1 -1
- package/dist/sync.d.ts +1 -1
- package/dist/sync.js +1 -1
- package/dist/sync.js.map +1 -1
- package/dist/tests/testUtils.d.ts +1 -1
- package/dist/tests/testUtils.js +3 -3
- package/dist/tests/testUtils.js.map +1 -1
- package/package.json +2 -2
- package/src/account.ts +1 -1
- package/src/coValue.ts +25 -20
- package/src/coValueCore.ts +17 -21
- package/src/coValues/coList.ts +242 -128
- package/src/coValues/coMap.ts +293 -162
- package/src/coValues/coStream.ts +227 -94
- package/src/crypto.ts +37 -24
- package/src/group.ts +90 -63
- package/src/index.ts +35 -25
- package/src/{node.ts → localNode.ts} +64 -64
- package/src/permissions.ts +15 -18
- package/src/queriedCoValues/queriedCoList.ts +248 -0
- package/src/queriedCoValues/queriedCoMap.ts +180 -0
- package/src/queriedCoValues/queriedCoStream.ts +125 -0
- package/src/queries.ts +83 -460
- package/src/sync.ts +2 -2
- package/src/tests/account.test.ts +3 -6
- package/src/tests/coValue.test.ts +116 -110
- package/src/tests/coValueCore.test.ts +1 -1
- package/src/tests/crypto.test.ts +19 -21
- package/src/tests/permissions.test.ts +255 -242
- package/src/tests/queries.test.ts +57 -40
- package/src/tests/sync.test.ts +30 -30
- package/src/tests/testUtils.ts +3 -3
- package/dist/coValues/static.d.ts +0 -14
- package/dist/coValues/static.js +0 -20
- package/dist/coValues/static.js.map +0 -1
- package/dist/node.js.map +0 -1
- package/src/coValues/static.ts +0 -31
package/src/coValues/coStream.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { JsonObject, JsonValue } from "../jsonValue.js";
|
|
|
2
2
|
import { CoValue, CoID, isCoValue } from "../coValue.js";
|
|
3
3
|
import { CoValueCore, accountOrAgentIDfromSessionID } from "../coValueCore.js";
|
|
4
4
|
import { Group } from "../group.js";
|
|
5
|
-
import { SessionID } from "../ids.js";
|
|
5
|
+
import { AgentID, SessionID, TransactionID } from "../ids.js";
|
|
6
6
|
import { base64URLtoBytes, bytesToBase64url } from "../base64url.js";
|
|
7
|
-
import { AccountID
|
|
7
|
+
import { AccountID } from "../account.js";
|
|
8
8
|
import { parseJSON } from "../jsonStringify.js";
|
|
9
9
|
|
|
10
10
|
export type BinaryStreamInfo = {
|
|
@@ -33,13 +33,14 @@ export type BinaryStreamItem =
|
|
|
33
33
|
| BinaryStreamChunk
|
|
34
34
|
| BinaryStreamEnd;
|
|
35
35
|
|
|
36
|
-
export type CoStreamItem<
|
|
37
|
-
|
|
36
|
+
export type CoStreamItem<Item extends JsonValue | CoValue> = {
|
|
37
|
+
value: Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>;
|
|
38
|
+
tx: TransactionID;
|
|
38
39
|
madeAt: number;
|
|
39
40
|
};
|
|
40
41
|
|
|
41
|
-
export class
|
|
42
|
-
|
|
42
|
+
export class CoStreamView<
|
|
43
|
+
Item extends JsonValue | CoValue,
|
|
43
44
|
Meta extends JsonObject | null = null
|
|
44
45
|
> implements CoValue
|
|
45
46
|
{
|
|
@@ -47,8 +48,9 @@ export class CoStream<
|
|
|
47
48
|
type = "costream" as const;
|
|
48
49
|
core: CoValueCore;
|
|
49
50
|
items: {
|
|
50
|
-
[key: SessionID]: CoStreamItem<
|
|
51
|
+
[key: SessionID]: CoStreamItem<Item>[];
|
|
51
52
|
};
|
|
53
|
+
readonly _item!: Item;
|
|
52
54
|
|
|
53
55
|
constructor(core: CoValueCore) {
|
|
54
56
|
this.id = core.id as CoID<this>;
|
|
@@ -65,6 +67,11 @@ export class CoStream<
|
|
|
65
67
|
return this.core.getGroup();
|
|
66
68
|
}
|
|
67
69
|
|
|
70
|
+
/** Not yet implemented */
|
|
71
|
+
atTime(_time: number): this {
|
|
72
|
+
throw new Error("Not yet implemented");
|
|
73
|
+
}
|
|
74
|
+
|
|
68
75
|
/** @internal */
|
|
69
76
|
protected fillFromCoValue() {
|
|
70
77
|
this.items = {};
|
|
@@ -75,21 +82,21 @@ export class CoStream<
|
|
|
75
82
|
changes,
|
|
76
83
|
} of this.core.getValidSortedTransactions()) {
|
|
77
84
|
for (const changeUntyped of parseJSON(changes)) {
|
|
78
|
-
const change = changeUntyped as
|
|
79
|
-
? CoID<
|
|
80
|
-
: Exclude<
|
|
85
|
+
const change = changeUntyped as Item extends CoValue
|
|
86
|
+
? CoID<Item>
|
|
87
|
+
: Exclude<Item, CoValue>;
|
|
81
88
|
let entries = this.items[txID.sessionID];
|
|
82
89
|
if (!entries) {
|
|
83
90
|
entries = [];
|
|
84
91
|
this.items[txID.sessionID] = entries;
|
|
85
92
|
}
|
|
86
|
-
entries.push({
|
|
93
|
+
entries.push({ value: change, madeAt, tx: txID });
|
|
87
94
|
}
|
|
88
95
|
}
|
|
89
96
|
}
|
|
90
97
|
|
|
91
98
|
getSingleStream():
|
|
92
|
-
| (
|
|
99
|
+
| (Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>)[]
|
|
93
100
|
| undefined {
|
|
94
101
|
if (Object.keys(this.items).length === 0) {
|
|
95
102
|
return undefined;
|
|
@@ -99,78 +106,134 @@ export class CoStream<
|
|
|
99
106
|
);
|
|
100
107
|
}
|
|
101
108
|
|
|
102
|
-
return Object.values(this.items)[0]?.map((item) => item.
|
|
109
|
+
return Object.values(this.items)[0]?.map((item) => item.value);
|
|
103
110
|
}
|
|
104
111
|
|
|
105
|
-
|
|
106
|
-
[
|
|
107
|
-
|
|
108
|
-
| undefined;
|
|
109
|
-
} {
|
|
110
|
-
const result: { [account: AccountID]: CoStreamItem<T> | undefined } =
|
|
111
|
-
{};
|
|
112
|
+
sessions(): SessionID[] {
|
|
113
|
+
return Object.keys(this.items) as SessionID[];
|
|
114
|
+
}
|
|
112
115
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
);
|
|
117
|
-
if (!isAccountID(account)) continue;
|
|
118
|
-
if (items.length > 0) {
|
|
119
|
-
const lastItemOfSession = items[items.length - 1]!;
|
|
120
|
-
if (
|
|
121
|
-
!result[account] ||
|
|
122
|
-
lastItemOfSession.madeAt > result[account]!.madeAt
|
|
123
|
-
) {
|
|
124
|
-
result[account] = lastItemOfSession;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
116
|
+
accounts(): Set<AccountID | AgentID> {
|
|
117
|
+
return new Set(this.sessions().map(accountOrAgentIDfromSessionID));
|
|
118
|
+
}
|
|
128
119
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
120
|
+
nthItemIn(
|
|
121
|
+
sessionID: SessionID,
|
|
122
|
+
n: number
|
|
123
|
+
):
|
|
124
|
+
| {
|
|
125
|
+
by: AccountID | AgentID;
|
|
126
|
+
tx: TransactionID;
|
|
127
|
+
at: Date;
|
|
128
|
+
value: Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>;
|
|
129
|
+
}
|
|
130
|
+
| undefined {
|
|
131
|
+
const items = this.items[sessionID];
|
|
132
|
+
if (!items) return;
|
|
133
|
+
|
|
134
|
+
const item = items[n];
|
|
135
|
+
if (!item) return;
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
by: accountOrAgentIDfromSessionID(sessionID),
|
|
139
|
+
tx: item.tx,
|
|
140
|
+
at: new Date(item.madeAt),
|
|
141
|
+
value: item.value,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
lastItemIn(sessionID: SessionID):
|
|
146
|
+
| {
|
|
147
|
+
by: AccountID | AgentID;
|
|
148
|
+
tx: TransactionID;
|
|
149
|
+
at: Date;
|
|
150
|
+
value: Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>;
|
|
151
|
+
}
|
|
152
|
+
| undefined {
|
|
153
|
+
const items = this.items[sessionID];
|
|
154
|
+
if (!items) return;
|
|
155
|
+
return this.nthItemIn(sessionID, items.length - 1);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
*itemsIn(sessionID: SessionID) {
|
|
159
|
+
const items = this.items[sessionID];
|
|
160
|
+
if (!items) return;
|
|
161
|
+
for (const item of items) {
|
|
162
|
+
yield {
|
|
163
|
+
by: accountOrAgentIDfromSessionID(sessionID),
|
|
164
|
+
tx: item.tx,
|
|
165
|
+
at: new Date(item.madeAt),
|
|
166
|
+
value: item.value,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
135
169
|
}
|
|
136
170
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
171
|
+
lastItemBy(account: AccountID | AgentID):
|
|
172
|
+
| {
|
|
173
|
+
by: AccountID | AgentID;
|
|
174
|
+
tx: TransactionID;
|
|
175
|
+
at: Date;
|
|
176
|
+
value: Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>;
|
|
177
|
+
}
|
|
178
|
+
| undefined {
|
|
179
|
+
let latestItem:
|
|
180
|
+
| {
|
|
181
|
+
by: AccountID | AgentID;
|
|
182
|
+
tx: TransactionID;
|
|
183
|
+
at: Date;
|
|
184
|
+
value: Item extends CoValue
|
|
185
|
+
? CoID<Item>
|
|
186
|
+
: Exclude<Item, CoValue>;
|
|
187
|
+
}
|
|
188
|
+
| undefined;
|
|
141
189
|
|
|
142
|
-
for (const
|
|
190
|
+
for (const sessionID of Object.keys(this.items)) {
|
|
143
191
|
if (sessionID.startsWith(account)) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
192
|
+
const item = this.lastItemIn(sessionID as SessionID);
|
|
193
|
+
if (!item) continue;
|
|
194
|
+
if (!latestItem || item.at > latestItem.at) {
|
|
195
|
+
latestItem = {
|
|
196
|
+
by: item.by,
|
|
197
|
+
tx: item.tx,
|
|
198
|
+
at: item.at,
|
|
199
|
+
value: item.value,
|
|
200
|
+
};
|
|
152
201
|
}
|
|
153
202
|
}
|
|
154
203
|
}
|
|
155
204
|
|
|
156
|
-
return
|
|
205
|
+
return latestItem;
|
|
157
206
|
}
|
|
158
207
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
208
|
+
*itemsBy(account: AccountID | AgentID) {
|
|
209
|
+
// TODO: this can be made more lazy without a huge collect and sort
|
|
210
|
+
const items = [
|
|
211
|
+
...Object.keys(this.items).flatMap((sessionID) =>
|
|
212
|
+
sessionID.startsWith(account)
|
|
213
|
+
? [...this.itemsIn(sessionID as SessionID)].map((item) => ({
|
|
214
|
+
in: sessionID as SessionID,
|
|
215
|
+
...item,
|
|
216
|
+
}))
|
|
217
|
+
: []
|
|
218
|
+
),
|
|
219
|
+
];
|
|
220
|
+
|
|
221
|
+
items.sort((a, b) => a.at.getTime() - b.at.getTime());
|
|
222
|
+
|
|
223
|
+
for (const item of items) {
|
|
224
|
+
yield item;
|
|
225
|
+
}
|
|
165
226
|
}
|
|
166
227
|
|
|
167
228
|
toJSON(): {
|
|
168
|
-
[key: SessionID]: (
|
|
229
|
+
[key: SessionID]: (Item extends CoValue
|
|
230
|
+
? CoID<Item>
|
|
231
|
+
: Exclude<Item, CoValue>)[];
|
|
169
232
|
} {
|
|
170
233
|
return Object.fromEntries(
|
|
171
234
|
Object.entries(this.items).map(([sessionID, items]) => [
|
|
172
235
|
sessionID,
|
|
173
|
-
items.map((item) => item.
|
|
236
|
+
items.map((item) => item.value),
|
|
174
237
|
])
|
|
175
238
|
);
|
|
176
239
|
}
|
|
@@ -180,20 +243,57 @@ export class CoStream<
|
|
|
180
243
|
listener(content as this);
|
|
181
244
|
});
|
|
182
245
|
}
|
|
246
|
+
}
|
|
183
247
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
248
|
+
export class CoStream<
|
|
249
|
+
Item extends JsonValue | CoValue,
|
|
250
|
+
Meta extends JsonObject | null = null
|
|
251
|
+
>
|
|
252
|
+
extends CoStreamView<Item, Meta>
|
|
253
|
+
implements CoValue
|
|
254
|
+
{
|
|
255
|
+
push(
|
|
256
|
+
item: Item extends CoValue ? Item | CoID<Item> : Item,
|
|
257
|
+
privacy: "private" | "trusting" = "private"
|
|
258
|
+
): this {
|
|
259
|
+
this.core.makeTransaction([isCoValue(item) ? item.id : item], privacy);
|
|
187
260
|
return new CoStream(this.core) as this;
|
|
188
261
|
}
|
|
262
|
+
|
|
263
|
+
mutate(mutator: (mutable: MutableCoStream<Item, Meta>) => void): this {
|
|
264
|
+
const mutable = new MutableCoStream<Item, Meta>(this.core);
|
|
265
|
+
mutator(mutable);
|
|
266
|
+
return new CoStream(this.core) as this;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** @deprecated Use `mutate` instead. */
|
|
270
|
+
edit(mutator: (mutable: MutableCoStream<Item, Meta>) => void): this {
|
|
271
|
+
return this.mutate(mutator);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export class MutableCoStream<
|
|
276
|
+
Item extends JsonValue | CoValue,
|
|
277
|
+
Meta extends JsonObject | null = null
|
|
278
|
+
>
|
|
279
|
+
extends CoStreamView<Item, Meta>
|
|
280
|
+
implements CoValue
|
|
281
|
+
{
|
|
282
|
+
push(
|
|
283
|
+
item: Item extends CoValue ? Item | CoID<Item> : Item,
|
|
284
|
+
privacy: "private" | "trusting" = "private"
|
|
285
|
+
) {
|
|
286
|
+
this.core.makeTransaction([isCoValue(item) ? item.id : item], privacy);
|
|
287
|
+
this.fillFromCoValue();
|
|
288
|
+
}
|
|
189
289
|
}
|
|
190
290
|
|
|
191
291
|
const binary_U_prefixLength = 8; // "binary_U".length;
|
|
192
292
|
|
|
193
|
-
export class
|
|
293
|
+
export class BinaryCoStreamView<
|
|
194
294
|
Meta extends BinaryCoStreamMeta = { type: "binary" }
|
|
195
295
|
>
|
|
196
|
-
extends
|
|
296
|
+
extends CoStreamView<BinaryStreamItem, Meta>
|
|
197
297
|
implements CoValue
|
|
198
298
|
{
|
|
199
299
|
id!: CoID<this>;
|
|
@@ -256,52 +356,85 @@ export class BinaryCoStream<
|
|
|
256
356
|
finished,
|
|
257
357
|
};
|
|
258
358
|
}
|
|
259
|
-
|
|
260
|
-
edit(changer: (editable: WriteableBinaryCoStream<Meta>) => void): this {
|
|
261
|
-
const editable = new WriteableBinaryCoStream<Meta>(this.core);
|
|
262
|
-
changer(editable);
|
|
263
|
-
return new BinaryCoStream(this.core) as this;
|
|
264
|
-
}
|
|
265
359
|
}
|
|
266
360
|
|
|
267
|
-
export class
|
|
268
|
-
|
|
269
|
-
Meta extends JsonObject | null = null
|
|
361
|
+
export class BinaryCoStream<
|
|
362
|
+
Meta extends BinaryCoStreamMeta = { type: "binary" }
|
|
270
363
|
>
|
|
271
|
-
extends
|
|
364
|
+
extends BinaryCoStreamView<Meta>
|
|
272
365
|
implements CoValue
|
|
273
366
|
{
|
|
274
367
|
/** @internal */
|
|
275
|
-
|
|
276
|
-
|
|
368
|
+
push(
|
|
369
|
+
item: BinaryStreamItem,
|
|
370
|
+
privacy: "private" | "trusting" = "private"
|
|
371
|
+
): this {
|
|
372
|
+
this.core.makeTransaction([item], privacy);
|
|
373
|
+
return new BinaryCoStream(this.core) as this;
|
|
277
374
|
}
|
|
278
375
|
|
|
279
|
-
|
|
280
|
-
|
|
376
|
+
startBinaryStream(
|
|
377
|
+
settings: BinaryStreamInfo,
|
|
281
378
|
privacy: "private" | "trusting" = "private"
|
|
282
|
-
) {
|
|
283
|
-
this.
|
|
284
|
-
|
|
379
|
+
): this {
|
|
380
|
+
return this.push(
|
|
381
|
+
{
|
|
382
|
+
type: "start",
|
|
383
|
+
...settings,
|
|
384
|
+
} satisfies BinaryStreamStart,
|
|
285
385
|
privacy
|
|
286
386
|
);
|
|
287
|
-
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
pushBinaryStreamChunk(
|
|
390
|
+
chunk: Uint8Array,
|
|
391
|
+
privacy: "private" | "trusting" = "private"
|
|
392
|
+
): this {
|
|
393
|
+
// const before = performance.now();
|
|
394
|
+
return this.push(
|
|
395
|
+
{
|
|
396
|
+
type: "chunk",
|
|
397
|
+
chunk: `binary_U${bytesToBase64url(chunk)}`,
|
|
398
|
+
} satisfies BinaryStreamChunk,
|
|
399
|
+
privacy
|
|
400
|
+
);
|
|
401
|
+
// const after = performance.now();
|
|
402
|
+
// console.log(
|
|
403
|
+
// "pushBinaryStreamChunk bandwidth in MB/s",
|
|
404
|
+
// (1000 * chunk.length) / (after - before) / (1024 * 1024)
|
|
405
|
+
// );
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
endBinaryStream(privacy: "private" | "trusting" = "private"): this {
|
|
409
|
+
return this.push(
|
|
410
|
+
{
|
|
411
|
+
type: "end",
|
|
412
|
+
} satisfies BinaryStreamEnd,
|
|
413
|
+
privacy
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
mutate(mutator: (mutable: MutableBinaryCoStream<Meta>) => void): this {
|
|
418
|
+
const mutable = new MutableBinaryCoStream<Meta>(this.core);
|
|
419
|
+
mutator(mutable);
|
|
420
|
+
return new BinaryCoStream(this.core) as this;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/** @deprecated Use `mutate` instead. */
|
|
424
|
+
edit(mutator: (mutable: MutableBinaryCoStream<Meta>) => void): this {
|
|
425
|
+
return this.mutate(mutator);
|
|
288
426
|
}
|
|
289
427
|
}
|
|
290
428
|
|
|
291
|
-
export class
|
|
429
|
+
export class MutableBinaryCoStream<
|
|
292
430
|
Meta extends BinaryCoStreamMeta = { type: "binary" }
|
|
293
431
|
>
|
|
294
|
-
extends
|
|
432
|
+
extends BinaryCoStreamView<Meta>
|
|
295
433
|
implements CoValue
|
|
296
434
|
{
|
|
297
|
-
/** @internal */
|
|
298
|
-
edit(_changer: (editable: WriteableBinaryCoStream<Meta>) => void): this {
|
|
299
|
-
throw new Error("Already editing.");
|
|
300
|
-
}
|
|
301
|
-
|
|
302
435
|
/** @internal */
|
|
303
436
|
push(item: BinaryStreamItem, privacy: "private" | "trusting" = "private") {
|
|
304
|
-
|
|
437
|
+
MutableCoStream.prototype.push.call(this, item, privacy);
|
|
305
438
|
}
|
|
306
439
|
|
|
307
440
|
startBinaryStream(
|
package/src/crypto.ts
CHANGED
|
@@ -6,33 +6,39 @@ import { randomBytes } from "@noble/ciphers/webcrypto/utils";
|
|
|
6
6
|
import { AgentID, RawCoID, TransactionID } from "./ids.js";
|
|
7
7
|
import { base64URLtoBytes, bytesToBase64url } from "./base64url.js";
|
|
8
8
|
|
|
9
|
-
import { createBLAKE3 } from
|
|
9
|
+
import { createBLAKE3 } from "hash-wasm";
|
|
10
10
|
import { Stringified, parseJSON, stableStringify } from "./jsonStringify.js";
|
|
11
11
|
|
|
12
12
|
let blake3Instance: Awaited<ReturnType<typeof createBLAKE3>>;
|
|
13
13
|
let blake3HashOnce: (data: Uint8Array) => Uint8Array;
|
|
14
|
-
let blake3HashOnceWithContext: (
|
|
15
|
-
|
|
14
|
+
let blake3HashOnceWithContext: (
|
|
15
|
+
data: Uint8Array,
|
|
16
|
+
{ context }: { context: Uint8Array }
|
|
17
|
+
) => Uint8Array;
|
|
18
|
+
let blake3incrementalUpdateSLOW_WITH_DEVTOOLS: (
|
|
19
|
+
state: Uint8Array,
|
|
20
|
+
data: Uint8Array
|
|
21
|
+
) => Uint8Array;
|
|
16
22
|
let blake3digestForState: (state: Uint8Array) => Uint8Array;
|
|
17
23
|
|
|
18
24
|
export const cryptoReady = new Promise<void>((resolve) => {
|
|
19
|
-
createBLAKE3().then(bl3 => {
|
|
25
|
+
createBLAKE3().then((bl3) => {
|
|
20
26
|
blake3Instance = bl3;
|
|
21
27
|
blake3HashOnce = (data) => {
|
|
22
|
-
return bl3.init().update(data).digest(
|
|
23
|
-
}
|
|
24
|
-
blake3HashOnceWithContext = (data, {context}) => {
|
|
25
|
-
return bl3.init().update(context).update(data).digest(
|
|
26
|
-
}
|
|
28
|
+
return bl3.init().update(data).digest("binary");
|
|
29
|
+
};
|
|
30
|
+
blake3HashOnceWithContext = (data, { context }) => {
|
|
31
|
+
return bl3.init().update(context).update(data).digest("binary");
|
|
32
|
+
};
|
|
27
33
|
blake3incrementalUpdateSLOW_WITH_DEVTOOLS = (state, data) => {
|
|
28
34
|
bl3.load(state).update(data);
|
|
29
35
|
return bl3.save();
|
|
30
|
-
}
|
|
36
|
+
};
|
|
31
37
|
blake3digestForState = (state) => {
|
|
32
|
-
return bl3.load(state).digest(
|
|
33
|
-
}
|
|
38
|
+
return bl3.load(state).digest("binary");
|
|
39
|
+
};
|
|
34
40
|
resolve();
|
|
35
|
-
})
|
|
41
|
+
});
|
|
36
42
|
});
|
|
37
43
|
|
|
38
44
|
export type SignerSecret = `signerSecret_z${string}`;
|
|
@@ -149,12 +155,17 @@ export function getAgentSealerSecret(agentSecret: AgentSecret): SealerSecret {
|
|
|
149
155
|
return agentSecret.split("/")[0] as SealerSecret;
|
|
150
156
|
}
|
|
151
157
|
|
|
152
|
-
export function seal<T extends JsonValue>(
|
|
153
|
-
message
|
|
154
|
-
from
|
|
155
|
-
to
|
|
156
|
-
nOnceMaterial
|
|
157
|
-
|
|
158
|
+
export function seal<T extends JsonValue>({
|
|
159
|
+
message,
|
|
160
|
+
from,
|
|
161
|
+
to,
|
|
162
|
+
nOnceMaterial,
|
|
163
|
+
}: {
|
|
164
|
+
message: T;
|
|
165
|
+
from: SealerSecret;
|
|
166
|
+
to: SealerID;
|
|
167
|
+
nOnceMaterial: { in: RawCoID; tx: TransactionID };
|
|
168
|
+
}): Sealed<T> {
|
|
158
169
|
const nOnce = blake3HashOnce(
|
|
159
170
|
textEncoder.encode(stableStringify(nOnceMaterial))
|
|
160
171
|
).slice(0, 24);
|
|
@@ -220,9 +231,12 @@ export class StreamingHash {
|
|
|
220
231
|
}
|
|
221
232
|
|
|
222
233
|
update(value: JsonValue) {
|
|
223
|
-
const encoded = textEncoder.encode(stableStringify(value))
|
|
234
|
+
const encoded = textEncoder.encode(stableStringify(value));
|
|
224
235
|
// const before = performance.now();
|
|
225
|
-
this.state = blake3incrementalUpdateSLOW_WITH_DEVTOOLS(
|
|
236
|
+
this.state = blake3incrementalUpdateSLOW_WITH_DEVTOOLS(
|
|
237
|
+
this.state,
|
|
238
|
+
encoded
|
|
239
|
+
);
|
|
226
240
|
// const after = performance.now();
|
|
227
241
|
// console.log(`Hashing throughput in MB/s`, 1000 * (encoded.length / (after - before)) / (1024 * 1024));
|
|
228
242
|
}
|
|
@@ -333,8 +347,7 @@ function decryptRaw<T extends JsonValue, N extends JsonValue>(
|
|
|
333
347
|
);
|
|
334
348
|
const plaintext = xsalsa20(keySecretBytes, nOnce, ciphertext);
|
|
335
349
|
|
|
336
|
-
|
|
337
|
-
|
|
350
|
+
return textDecoder.decode(plaintext) as Stringified<T>;
|
|
338
351
|
}
|
|
339
352
|
|
|
340
353
|
function decrypt<T extends JsonValue, N extends JsonValue>(
|
|
@@ -345,7 +358,7 @@ function decrypt<T extends JsonValue, N extends JsonValue>(
|
|
|
345
358
|
try {
|
|
346
359
|
return parseJSON(decryptRaw(encrypted, keySecret, nOnceMaterial));
|
|
347
360
|
} catch (e) {
|
|
348
|
-
console.error("Decryption error", e)
|
|
361
|
+
console.error("Decryption error", e);
|
|
349
362
|
return undefined;
|
|
350
363
|
}
|
|
351
364
|
}
|