cojson 0.7.0-alpha.5 → 0.7.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 (113) hide show
  1. package/.eslintrc.cjs +3 -2
  2. package/.prettierrc.js +9 -0
  3. package/.turbo/turbo-build.log +3 -30
  4. package/.turbo/turbo-lint.log +4 -0
  5. package/.turbo/turbo-test.log +1106 -0
  6. package/CHANGELOG.md +104 -0
  7. package/README.md +3 -1
  8. package/dist/base64url.test.js +25 -0
  9. package/dist/base64url.test.js.map +1 -0
  10. package/dist/coValueCore.js +60 -37
  11. package/dist/coValueCore.js.map +1 -1
  12. package/dist/coValues/account.js +16 -15
  13. package/dist/coValues/account.js.map +1 -1
  14. package/dist/coValues/coList.js +1 -1
  15. package/dist/coValues/coList.js.map +1 -1
  16. package/dist/coValues/coMap.js +17 -8
  17. package/dist/coValues/coMap.js.map +1 -1
  18. package/dist/coValues/group.js +13 -14
  19. package/dist/coValues/group.js.map +1 -1
  20. package/dist/coreToCoValue.js.map +1 -1
  21. package/dist/crypto/PureJSCrypto.js +89 -0
  22. package/dist/crypto/PureJSCrypto.js.map +1 -0
  23. package/dist/crypto/WasmCrypto.js +127 -0
  24. package/dist/crypto/WasmCrypto.js.map +1 -0
  25. package/dist/crypto/crypto.js +151 -0
  26. package/dist/crypto/crypto.js.map +1 -0
  27. package/dist/ids.js +4 -2
  28. package/dist/ids.js.map +1 -1
  29. package/dist/index.js +6 -8
  30. package/dist/index.js.map +1 -1
  31. package/dist/jsonStringify.js.map +1 -1
  32. package/dist/localNode.js +41 -38
  33. package/dist/localNode.js.map +1 -1
  34. package/dist/permissions.js +6 -6
  35. package/dist/permissions.js.map +1 -1
  36. package/dist/storage/FileSystem.js +61 -0
  37. package/dist/storage/FileSystem.js.map +1 -0
  38. package/dist/storage/chunksAndKnownStates.js +97 -0
  39. package/dist/storage/chunksAndKnownStates.js.map +1 -0
  40. package/dist/storage/index.js +265 -0
  41. package/dist/storage/index.js.map +1 -0
  42. package/dist/sync.js +29 -25
  43. package/dist/sync.js.map +1 -1
  44. package/dist/tests/account.test.js +58 -0
  45. package/dist/tests/account.test.js.map +1 -0
  46. package/dist/tests/coList.test.js +76 -0
  47. package/dist/tests/coList.test.js.map +1 -0
  48. package/dist/tests/coMap.test.js +136 -0
  49. package/dist/tests/coMap.test.js.map +1 -0
  50. package/dist/tests/coStream.test.js +172 -0
  51. package/dist/tests/coStream.test.js.map +1 -0
  52. package/dist/tests/coValueCore.test.js +114 -0
  53. package/dist/tests/coValueCore.test.js.map +1 -0
  54. package/dist/tests/crypto.test.js +118 -0
  55. package/dist/tests/crypto.test.js.map +1 -0
  56. package/dist/tests/cryptoImpl.test.js +113 -0
  57. package/dist/tests/cryptoImpl.test.js.map +1 -0
  58. package/dist/tests/group.test.js +34 -0
  59. package/dist/tests/group.test.js.map +1 -0
  60. package/dist/tests/permissions.test.js +1060 -0
  61. package/dist/tests/permissions.test.js.map +1 -0
  62. package/dist/tests/sync.test.js +816 -0
  63. package/dist/tests/sync.test.js.map +1 -0
  64. package/dist/tests/testUtils.js +12 -11
  65. package/dist/tests/testUtils.js.map +1 -1
  66. package/dist/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
  67. package/dist/typeUtils/isAccountID.js.map +1 -1
  68. package/dist/typeUtils/isCoValue.js.map +1 -1
  69. package/package.json +14 -27
  70. package/src/base64url.test.ts +6 -5
  71. package/src/coValue.ts +1 -1
  72. package/src/coValueCore.ts +179 -126
  73. package/src/coValues/account.ts +30 -32
  74. package/src/coValues/coList.ts +11 -11
  75. package/src/coValues/coMap.ts +27 -17
  76. package/src/coValues/coStream.ts +17 -17
  77. package/src/coValues/group.ts +93 -109
  78. package/src/coreToCoValue.ts +5 -2
  79. package/src/crypto/PureJSCrypto.ts +200 -0
  80. package/src/crypto/WasmCrypto.ts +259 -0
  81. package/src/crypto/crypto.ts +336 -0
  82. package/src/ids.ts +8 -7
  83. package/src/index.ts +24 -24
  84. package/src/jsonStringify.ts +6 -4
  85. package/src/jsonValue.ts +2 -2
  86. package/src/localNode.ts +103 -109
  87. package/src/media.ts +3 -3
  88. package/src/permissions.ts +19 -21
  89. package/src/storage/FileSystem.ts +152 -0
  90. package/src/storage/chunksAndKnownStates.ts +139 -0
  91. package/src/storage/index.ts +479 -0
  92. package/src/streamUtils.ts +12 -12
  93. package/src/sync.ts +79 -63
  94. package/src/tests/account.test.ts +15 -15
  95. package/src/tests/coList.test.ts +94 -0
  96. package/src/tests/coMap.test.ts +162 -0
  97. package/src/tests/coStream.test.ts +246 -0
  98. package/src/tests/coValueCore.test.ts +36 -37
  99. package/src/tests/crypto.test.ts +66 -72
  100. package/src/tests/cryptoImpl.test.ts +183 -0
  101. package/src/tests/group.test.ts +16 -17
  102. package/src/tests/permissions.test.ts +269 -283
  103. package/src/tests/sync.test.ts +122 -123
  104. package/src/tests/testUtils.ts +24 -21
  105. package/src/typeUtils/accountOrAgentIDfromSessionID.ts +1 -2
  106. package/src/typeUtils/expectGroup.ts +1 -1
  107. package/src/typeUtils/isAccountID.ts +0 -1
  108. package/src/typeUtils/isCoValue.ts +1 -2
  109. package/tsconfig.json +0 -1
  110. package/dist/crypto.js +0 -254
  111. package/dist/crypto.js.map +0 -1
  112. package/src/crypto.ts +0 -484
  113. package/src/tests/coValue.test.ts +0 -497
package/src/crypto.ts DELETED
@@ -1,484 +0,0 @@
1
- import {
2
- initBundledOnce,
3
- Ed25519SigningKey,
4
- Ed25519VerifyingKey,
5
- X25519StaticSecret,
6
- Memory,
7
- Ed25519Signature,
8
- X25519PublicKey,
9
- } from "@hazae41/berith";
10
- import { xsalsa20_poly1305, xsalsa20 } from "@noble/ciphers/salsa";
11
- import { JsonValue } from "./jsonValue.js";
12
- import { base58 } from "@scure/base";
13
- import { randomBytes } from "@noble/ciphers/webcrypto/utils";
14
- import { AgentID, RawCoID, TransactionID } from "./ids.js";
15
- import { base64URLtoBytes, bytesToBase64url } from "./base64url.js";
16
-
17
- import { createBLAKE3 } from "hash-wasm";
18
- import { Stringified, parseJSON, stableStringify } from "./jsonStringify.js";
19
-
20
- let blake3Instance: Awaited<ReturnType<typeof createBLAKE3>>;
21
- let blake3HashOnce: (data: Uint8Array) => Uint8Array = () => {
22
- throw new Error(
23
- "cojson WASM dependencies not yet loaded; Make sure to import `cojsonReady` from `cojson` and await it before using any cojson functionality:\n\n" +
24
- 'import { cojsonReady } from "cojson";\n' +
25
- "await cojsonReady;\n\n"
26
- );
27
- };
28
- let blake3HashOnceWithContext: (
29
- data: Uint8Array,
30
- { context }: { context: Uint8Array }
31
- ) => Uint8Array;
32
- let blake3incrementalUpdateSLOW_WITH_DEVTOOLS: (
33
- state: Uint8Array,
34
- data: Uint8Array
35
- ) => Uint8Array;
36
- let blake3digestForState: (state: Uint8Array) => Uint8Array;
37
-
38
- export const cryptoReady = Promise.all([
39
- new Promise<void>((resolve) => {
40
- createBLAKE3()
41
- .then((bl3) => {
42
- blake3Instance = bl3;
43
- blake3HashOnce = (data) => {
44
- return bl3.init().update(data).digest("binary");
45
- };
46
- blake3HashOnceWithContext = (data, { context }) => {
47
- return bl3
48
- .init()
49
- .update(context)
50
- .update(data)
51
- .digest("binary");
52
- };
53
- blake3incrementalUpdateSLOW_WITH_DEVTOOLS = (state, data) => {
54
- bl3.load(state).update(data);
55
- return bl3.save();
56
- };
57
- blake3digestForState = (state) => {
58
- return bl3.load(state).digest("binary");
59
- };
60
- resolve();
61
- })
62
- .catch((e) =>
63
- console.error("Failed to load cryptography dependencies", e)
64
- );
65
- }),
66
- initBundledOnce(),
67
- ]);
68
-
69
- export type SignerSecret = `signerSecret_z${string}`;
70
- export type SignerID = `signer_z${string}`;
71
- export type Signature = `signature_z${string}`;
72
-
73
- export type SealerSecret = `sealerSecret_z${string}`;
74
- export type SealerID = `sealer_z${string}`;
75
- export type Sealed<T> = `sealed_U${string}` & { __type: T };
76
-
77
- export type AgentSecret = `${SealerSecret}/${SignerSecret}`;
78
-
79
- const textEncoder = new TextEncoder();
80
- const textDecoder = new TextDecoder();
81
-
82
- export function newRandomSigner(): SignerSecret {
83
- return `signerSecret_z${base58.encode(
84
- new Ed25519SigningKey().to_bytes().copyAndDispose()
85
- )}`;
86
- }
87
-
88
- export function signerSecretToBytes(secret: SignerSecret): Uint8Array {
89
- return base58.decode(secret.substring("signerSecret_z".length));
90
- }
91
-
92
- export function signerSecretFromBytes(bytes: Uint8Array): SignerSecret {
93
- return `signerSecret_z${base58.encode(bytes)}`;
94
- }
95
-
96
- export function getSignerID(secret: SignerSecret): SignerID {
97
- return `signer_z${base58.encode(
98
- Ed25519SigningKey.from_bytes(
99
- new Memory(base58.decode(secret.substring("signerSecret_z".length)))
100
- )
101
- .public()
102
- .to_bytes()
103
- .copyAndDispose()
104
- )}`;
105
- }
106
-
107
- export function sign(secret: SignerSecret, message: JsonValue): Signature {
108
- const signature = Ed25519SigningKey.from_bytes(
109
- new Memory(base58.decode(secret.substring("signerSecret_z".length)))
110
- )
111
- .sign(new Memory(textEncoder.encode(stableStringify(message))))
112
- .to_bytes()
113
- .copyAndDispose();
114
- return `signature_z${base58.encode(signature)}`;
115
- }
116
-
117
- export function verify(
118
- signature: Signature,
119
- message: JsonValue,
120
- id: SignerID
121
- ): boolean {
122
- return new Ed25519VerifyingKey(
123
- new Memory(base58.decode(id.substring("signer_z".length)))
124
- ).verify(
125
- new Memory(textEncoder.encode(stableStringify(message))),
126
- new Ed25519Signature(
127
- new Memory(base58.decode(signature.substring("signature_z".length)))
128
- )
129
- );
130
- }
131
-
132
- export function newRandomSealer(): SealerSecret {
133
- return `sealerSecret_z${base58.encode(
134
- new X25519StaticSecret().to_bytes().copyAndDispose()
135
- )}`;
136
- }
137
-
138
- export function sealerSecretToBytes(secret: SealerSecret): Uint8Array {
139
- return base58.decode(secret.substring("sealerSecret_z".length));
140
- }
141
-
142
- export function sealerSecretFromBytes(bytes: Uint8Array): SealerSecret {
143
- return `sealerSecret_z${base58.encode(bytes)}`;
144
- }
145
-
146
- export function getSealerID(secret: SealerSecret): SealerID {
147
- return `sealer_z${base58.encode(
148
- X25519StaticSecret.from_bytes(
149
- new Memory(base58.decode(secret.substring("sealerSecret_z".length)))
150
- )
151
- .to_public()
152
- .to_bytes()
153
- .copyAndDispose()
154
- )}`;
155
- }
156
-
157
- export function newRandomAgentSecret(): AgentSecret {
158
- return `${newRandomSealer()}/${newRandomSigner()}`;
159
- }
160
-
161
- export function agentSecretToBytes(secret: AgentSecret): Uint8Array {
162
- const [sealerSecret, signerSecret] = secret.split("/");
163
- return new Uint8Array([
164
- ...sealerSecretToBytes(sealerSecret as SealerSecret),
165
- ...signerSecretToBytes(signerSecret as SignerSecret),
166
- ]);
167
- }
168
-
169
- export function agentSecretFromBytes(bytes: Uint8Array): AgentSecret {
170
- const sealerSecret = sealerSecretFromBytes(bytes.slice(0, 32));
171
- const signerSecret = signerSecretFromBytes(bytes.slice(32));
172
- return `${sealerSecret}/${signerSecret}`;
173
- }
174
-
175
- export function getAgentID(secret: AgentSecret): AgentID {
176
- const [sealerSecret, signerSecret] = secret.split("/");
177
- return `${getSealerID(sealerSecret as SealerSecret)}/${getSignerID(
178
- signerSecret as SignerSecret
179
- )}`;
180
- }
181
-
182
- export function getAgentSignerID(agentId: AgentID): SignerID {
183
- return agentId.split("/")[1] as SignerID;
184
- }
185
-
186
- export function getAgentSignerSecret(agentSecret: AgentSecret): SignerSecret {
187
- return agentSecret.split("/")[1] as SignerSecret;
188
- }
189
-
190
- export function getAgentSealerID(agentId: AgentID): SealerID {
191
- return agentId.split("/")[0] as SealerID;
192
- }
193
-
194
- export function getAgentSealerSecret(agentSecret: AgentSecret): SealerSecret {
195
- return agentSecret.split("/")[0] as SealerSecret;
196
- }
197
-
198
- export function seal<T extends JsonValue>({
199
- message,
200
- from,
201
- to,
202
- nOnceMaterial,
203
- }: {
204
- message: T;
205
- from: SealerSecret;
206
- to: SealerID;
207
- nOnceMaterial: { in: RawCoID; tx: TransactionID };
208
- }): Sealed<T> {
209
- const nOnce = blake3HashOnce(
210
- textEncoder.encode(stableStringify(nOnceMaterial))
211
- ).slice(0, 24);
212
-
213
- const sealerPub = base58.decode(to.substring("sealer_z".length));
214
-
215
- const senderPriv = base58.decode(from.substring("sealerSecret_z".length));
216
-
217
- const plaintext = textEncoder.encode(stableStringify(message));
218
-
219
- const sharedSecret = X25519StaticSecret.from_bytes(new Memory(senderPriv))
220
- .diffie_hellman(X25519PublicKey.from_bytes(new Memory(sealerPub)))
221
- .to_bytes()
222
- .copyAndDispose();
223
-
224
- const sealedBytes = xsalsa20_poly1305(sharedSecret, nOnce).encrypt(
225
- plaintext
226
- );
227
-
228
- return `sealed_U${bytesToBase64url(sealedBytes)}` as Sealed<T>;
229
- }
230
-
231
- export function unseal<T extends JsonValue>(
232
- sealed: Sealed<T>,
233
- sealer: SealerSecret,
234
- from: SealerID,
235
- nOnceMaterial: { in: RawCoID; tx: TransactionID }
236
- ): T | undefined {
237
- const nOnce = blake3HashOnce(
238
- textEncoder.encode(stableStringify(nOnceMaterial))
239
- ).slice(0, 24);
240
-
241
- const sealerPriv = base58.decode(sealer.substring("sealerSecret_z".length));
242
-
243
- const senderPub = base58.decode(from.substring("sealer_z".length));
244
-
245
- const sealedBytes = base64URLtoBytes(sealed.substring("sealed_U".length));
246
-
247
- const sharedSecret = X25519StaticSecret.from_bytes(new Memory(sealerPriv))
248
- .diffie_hellman(X25519PublicKey.from_bytes(new Memory(senderPub)))
249
- .to_bytes()
250
- .copyAndDispose();
251
-
252
- const plaintext = xsalsa20_poly1305(sharedSecret, nOnce).decrypt(
253
- sealedBytes
254
- );
255
-
256
- try {
257
- return JSON.parse(textDecoder.decode(plaintext));
258
- } catch (e) {
259
- console.error("Failed to decrypt/parse sealed message", e);
260
- return undefined;
261
- }
262
- }
263
-
264
- export type Hash = `hash_z${string}`;
265
-
266
- export function secureHash(value: JsonValue): Hash {
267
- return `hash_z${base58.encode(
268
- blake3HashOnce(textEncoder.encode(stableStringify(value)))
269
- )}`;
270
- }
271
-
272
- export class StreamingHash {
273
- state: Uint8Array;
274
-
275
- constructor(fromClone?: Uint8Array) {
276
- this.state = fromClone || blake3Instance.init().save();
277
- }
278
-
279
- update(value: JsonValue) {
280
- const encoded = textEncoder.encode(stableStringify(value));
281
- // const before = performance.now();
282
- this.state = blake3incrementalUpdateSLOW_WITH_DEVTOOLS(
283
- this.state,
284
- encoded
285
- );
286
- // const after = performance.now();
287
- // console.log(`Hashing throughput in MB/s`, 1000 * (encoded.length / (after - before)) / (1024 * 1024));
288
- }
289
-
290
- digest(): Hash {
291
- const hash = blake3digestForState(this.state);
292
- return `hash_z${base58.encode(hash)}`;
293
- }
294
-
295
- clone(): StreamingHash {
296
- return new StreamingHash(new Uint8Array(this.state));
297
- }
298
- }
299
-
300
- export type ShortHash = `shortHash_z${string}`;
301
- export const shortHashLength = 19;
302
-
303
- export function shortHash(value: JsonValue): ShortHash {
304
- return `shortHash_z${base58.encode(
305
- blake3HashOnce(textEncoder.encode(stableStringify(value))).slice(
306
- 0,
307
- shortHashLength
308
- )
309
- )}`;
310
- }
311
-
312
- export type Encrypted<
313
- T extends JsonValue,
314
- N extends JsonValue
315
- > = `encrypted_U${string}` & { __type: T; __nOnceMaterial: N };
316
-
317
- export type KeySecret = `keySecret_z${string}`;
318
- export type KeyID = `key_z${string}`;
319
-
320
- export function newRandomKeySecret(): { secret: KeySecret; id: KeyID } {
321
- return {
322
- secret: `keySecret_z${base58.encode(randomBytes(32))}`,
323
- id: `key_z${base58.encode(randomBytes(12))}`,
324
- };
325
- }
326
-
327
- function encrypt<T extends JsonValue, N extends JsonValue>(
328
- value: T,
329
- keySecret: KeySecret,
330
- nOnceMaterial: N
331
- ): Encrypted<T, N> {
332
- const keySecretBytes = base58.decode(
333
- keySecret.substring("keySecret_z".length)
334
- );
335
- const nOnce = blake3HashOnce(
336
- textEncoder.encode(stableStringify(nOnceMaterial))
337
- ).slice(0, 24);
338
-
339
- const plaintext = textEncoder.encode(stableStringify(value));
340
- const ciphertext = xsalsa20(keySecretBytes, nOnce, plaintext);
341
- return `encrypted_U${bytesToBase64url(ciphertext)}` as Encrypted<T, N>;
342
- }
343
-
344
- export function encryptForTransaction<T extends JsonValue>(
345
- value: T,
346
- keySecret: KeySecret,
347
- nOnceMaterial: { in: RawCoID; tx: TransactionID }
348
- ): Encrypted<T, { in: RawCoID; tx: TransactionID }> {
349
- return encrypt(value, keySecret, nOnceMaterial);
350
- }
351
-
352
- export function encryptKeySecret(keys: {
353
- toEncrypt: { id: KeyID; secret: KeySecret };
354
- encrypting: { id: KeyID; secret: KeySecret };
355
- }): {
356
- encryptedID: KeyID;
357
- encryptingID: KeyID;
358
- encrypted: Encrypted<
359
- KeySecret,
360
- { encryptedID: KeyID; encryptingID: KeyID }
361
- >;
362
- } {
363
- const nOnceMaterial = {
364
- encryptedID: keys.toEncrypt.id,
365
- encryptingID: keys.encrypting.id,
366
- };
367
-
368
- return {
369
- encryptedID: keys.toEncrypt.id,
370
- encryptingID: keys.encrypting.id,
371
- encrypted: encrypt(
372
- keys.toEncrypt.secret,
373
- keys.encrypting.secret,
374
- nOnceMaterial
375
- ),
376
- };
377
- }
378
-
379
- function decryptRaw<T extends JsonValue, N extends JsonValue>(
380
- encrypted: Encrypted<T, N>,
381
- keySecret: KeySecret,
382
- nOnceMaterial: N
383
- ): Stringified<T> {
384
- const keySecretBytes = base58.decode(
385
- keySecret.substring("keySecret_z".length)
386
- );
387
- const nOnce = blake3HashOnce(
388
- textEncoder.encode(stableStringify(nOnceMaterial))
389
- ).slice(0, 24);
390
-
391
- const ciphertext = base64URLtoBytes(
392
- encrypted.substring("encrypted_U".length)
393
- );
394
- const plaintext = xsalsa20(keySecretBytes, nOnce, ciphertext);
395
-
396
- return textDecoder.decode(plaintext) as Stringified<T>;
397
- }
398
-
399
- function decrypt<T extends JsonValue, N extends JsonValue>(
400
- encrypted: Encrypted<T, N>,
401
- keySecret: KeySecret,
402
- nOnceMaterial: N
403
- ): T | undefined {
404
- try {
405
- return parseJSON(decryptRaw(encrypted, keySecret, nOnceMaterial));
406
- } catch (e) {
407
- console.error("Decryption error", e);
408
- return undefined;
409
- }
410
- }
411
-
412
- export function decryptRawForTransaction<T extends JsonValue>(
413
- encrypted: Encrypted<T, { in: RawCoID; tx: TransactionID }>,
414
- keySecret: KeySecret,
415
- nOnceMaterial: { in: RawCoID; tx: TransactionID }
416
- ): Stringified<T> | undefined {
417
- return decryptRaw(encrypted, keySecret, nOnceMaterial);
418
- }
419
-
420
- export function decryptForTransaction<T extends JsonValue>(
421
- encrypted: Encrypted<T, { in: RawCoID; tx: TransactionID }>,
422
- keySecret: KeySecret,
423
- nOnceMaterial: { in: RawCoID; tx: TransactionID }
424
- ): T | undefined {
425
- return decrypt(encrypted, keySecret, nOnceMaterial);
426
- }
427
-
428
- export function decryptKeySecret(
429
- encryptedInfo: {
430
- encryptedID: KeyID;
431
- encryptingID: KeyID;
432
- encrypted: Encrypted<
433
- KeySecret,
434
- { encryptedID: KeyID; encryptingID: KeyID }
435
- >;
436
- },
437
- sealingSecret: KeySecret
438
- ): KeySecret | undefined {
439
- const nOnceMaterial = {
440
- encryptedID: encryptedInfo.encryptedID,
441
- encryptingID: encryptedInfo.encryptingID,
442
- };
443
-
444
- return decrypt(encryptedInfo.encrypted, sealingSecret, nOnceMaterial);
445
- }
446
-
447
- export function uniquenessForHeader(): `z${string}` {
448
- return `z${base58.encode(randomBytes(12))}`;
449
- }
450
-
451
- export function createdNowUnique(): {
452
- createdAt: `2${string}`;
453
- uniqueness: `z${string}`;
454
- } {
455
- const createdAt = new Date().toISOString() as `2${string}`;
456
- return {
457
- createdAt,
458
- uniqueness: uniquenessForHeader(),
459
- };
460
- }
461
-
462
- export const secretSeedLength = 32;
463
-
464
- export function newRandomSecretSeed(): Uint8Array {
465
- return randomBytes(secretSeedLength);
466
- }
467
-
468
- export function agentSecretFromSecretSeed(secretSeed: Uint8Array): AgentSecret {
469
- if (secretSeed.length !== secretSeedLength) {
470
- throw new Error(
471
- `Secret seed needs to be ${secretSeedLength} bytes long`
472
- );
473
- }
474
-
475
- return `sealerSecret_z${base58.encode(
476
- blake3HashOnceWithContext(secretSeed, {
477
- context: textEncoder.encode("seal"),
478
- })
479
- )}/signerSecret_z${base58.encode(
480
- blake3HashOnceWithContext(secretSeed, {
481
- context: textEncoder.encode("sign"),
482
- })
483
- )}`;
484
- }