@mblaney/holster 2.0.2 → 2.1.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/README.md +37 -6
- package/build/holster.js +3 -3
- package/build/holster.js.map +3 -3
- package/dist/holster.js +3 -3
- package/dist/holster.js.map +3 -3
- package/package.json +1 -1
- package/src/ham.js +10 -3
- package/src/holster.js +36 -25
- package/src/radisk.js +26 -12
- package/src/user.js +92 -101
- package/src/wire.js +298 -104
- package/ts/src/array.ts +10 -13
- package/ts/src/buffer.ts +40 -20
- package/ts/src/get.ts +5 -6
- package/ts/src/ham.ts +47 -28
- package/ts/src/holster.ts +277 -132
- package/ts/src/index.ts +14 -15
- package/ts/src/radisk.ts +122 -37
- package/ts/src/radix.ts +50 -34
- package/ts/src/schemas.ts +44 -24
- package/ts/src/sea-utils.ts +7 -11
- package/ts/src/sea.ts +51 -54
- package/ts/src/store.ts +48 -42
- package/ts/src/user.ts +136 -113
- package/ts/src/utils.ts +36 -11
- package/ts/src/wire.ts +453 -232
package/ts/src/sea.ts
CHANGED
|
@@ -3,14 +3,10 @@
|
|
|
3
3
|
* Cryptographic functions for signing, verification, encryption, and decryption
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {userPublicKey, userSignature} from "./utils.ts"
|
|
7
7
|
import * as utils from "./sea-utils.ts"
|
|
8
8
|
import SafeBuffer from "./buffer.ts"
|
|
9
|
-
import type {
|
|
10
|
-
UserPair,
|
|
11
|
-
EncryptedData,
|
|
12
|
-
SignedData,
|
|
13
|
-
} from "./schemas.ts"
|
|
9
|
+
import type {UserPair, EncryptedData, SignedData} from "./schemas.ts"
|
|
14
10
|
|
|
15
11
|
type Callback<T> = (result: T) => void
|
|
16
12
|
|
|
@@ -24,7 +20,7 @@ const SEA = {
|
|
|
24
20
|
pair: async (cb?: Callback<UserPair>): Promise<UserPair> => {
|
|
25
21
|
// ECDSA keys for signing/verifying
|
|
26
22
|
const ecdsa = await utils.subtle
|
|
27
|
-
.generateKey({
|
|
23
|
+
.generateKey({name: "ECDSA", namedCurve: "P-256"}, true, [
|
|
28
24
|
"sign",
|
|
29
25
|
"verify",
|
|
30
26
|
])
|
|
@@ -38,7 +34,7 @@ const SEA = {
|
|
|
38
34
|
|
|
39
35
|
// ECDH keys for encryption/decryption
|
|
40
36
|
const ecdh = await utils.subtle
|
|
41
|
-
.generateKey({
|
|
37
|
+
.generateKey({name: "ECDH", namedCurve: "P-256"}, true, ["deriveKey"])
|
|
42
38
|
.then(async keys => {
|
|
43
39
|
const pub = await utils.subtle.exportKey("jwk", keys.publicKey)
|
|
44
40
|
return {
|
|
@@ -63,14 +59,14 @@ const SEA = {
|
|
|
63
59
|
encrypt: async (
|
|
64
60
|
data: unknown,
|
|
65
61
|
pair: Partial<UserPair> | null,
|
|
66
|
-
cb?: Callback<EncryptedData | null
|
|
62
|
+
cb?: Callback<EncryptedData | null>,
|
|
67
63
|
): Promise<EncryptedData | null> => {
|
|
68
64
|
if (!pair || !pair.epriv) {
|
|
69
65
|
if (cb) cb(null)
|
|
70
66
|
return null
|
|
71
67
|
}
|
|
72
68
|
|
|
73
|
-
const rand = {
|
|
69
|
+
const rand = {s: utils.random(9), iv: utils.random(15)}
|
|
74
70
|
const ct = await utils.aeskey(pair.epriv, rand.s).then(aes => {
|
|
75
71
|
return utils.subtle.encrypt(
|
|
76
72
|
{
|
|
@@ -78,7 +74,7 @@ const SEA = {
|
|
|
78
74
|
iv: new Uint8Array(rand.iv),
|
|
79
75
|
},
|
|
80
76
|
aes,
|
|
81
|
-
new TextEncoder().encode(utils.stringify(data))
|
|
77
|
+
new TextEncoder().encode(utils.stringify(data)),
|
|
82
78
|
)
|
|
83
79
|
})
|
|
84
80
|
const enc: EncryptedData = {
|
|
@@ -96,7 +92,7 @@ const SEA = {
|
|
|
96
92
|
decrypt: async (
|
|
97
93
|
enc: Partial<EncryptedData> | null,
|
|
98
94
|
pair: Partial<UserPair> | null,
|
|
99
|
-
cb?: Callback<unknown | null
|
|
95
|
+
cb?: Callback<unknown | null>,
|
|
100
96
|
): Promise<unknown | null> => {
|
|
101
97
|
if (!enc || !enc.ct || !enc.iv || !enc.s || !pair || !pair.epriv) {
|
|
102
98
|
if (cb) cb(null)
|
|
@@ -117,7 +113,7 @@ const SEA = {
|
|
|
117
113
|
tagLength: 128,
|
|
118
114
|
},
|
|
119
115
|
aes,
|
|
120
|
-
new Uint8Array(data.ct)
|
|
116
|
+
new Uint8Array(data.ct),
|
|
121
117
|
)
|
|
122
118
|
})
|
|
123
119
|
const dec = utils.parse(new TextDecoder("utf8").decode(ct))
|
|
@@ -136,7 +132,7 @@ const SEA = {
|
|
|
136
132
|
verify: async (
|
|
137
133
|
data: string | SignedData,
|
|
138
134
|
pair: Partial<UserPair> | null,
|
|
139
|
-
cb?: Callback<unknown | null
|
|
135
|
+
cb?: Callback<unknown | null>,
|
|
140
136
|
): Promise<unknown | null> => {
|
|
141
137
|
if (!pair || !pair.pub) {
|
|
142
138
|
if (cb) cb(null)
|
|
@@ -149,9 +145,9 @@ const SEA = {
|
|
|
149
145
|
const key = await utils.subtle.importKey(
|
|
150
146
|
"jwk",
|
|
151
147
|
utils.jwk(pair.pub),
|
|
152
|
-
{
|
|
148
|
+
{name: "ECDSA", namedCurve: "P-256"},
|
|
153
149
|
false,
|
|
154
|
-
["verify"]
|
|
150
|
+
["verify"],
|
|
155
151
|
)
|
|
156
152
|
|
|
157
153
|
let msg: string | Record<string, unknown> = {}
|
|
@@ -162,13 +158,13 @@ const SEA = {
|
|
|
162
158
|
// (which should not be part of signature, so not verified)
|
|
163
159
|
for (const k of Object.keys(signed.m).sort()) {
|
|
164
160
|
if (k !== "_" && k !== userPublicKey && k !== userSignature) {
|
|
165
|
-
(msg as Record<string, unknown>)[k] = signed.m[k]
|
|
161
|
+
;(msg as Record<string, unknown>)[k] = signed.m[k]
|
|
166
162
|
}
|
|
167
163
|
}
|
|
168
164
|
}
|
|
169
165
|
const hash = await utils.sha256(msg)
|
|
170
166
|
const sig = new Uint8Array(SafeBuffer.from(signed.s, "base64"))
|
|
171
|
-
const alg = {
|
|
167
|
+
const alg = {name: "ECDSA", hash: {name: "SHA-256"}}
|
|
172
168
|
if (await utils.subtle.verify(alg, key, sig, new Uint8Array(hash))) {
|
|
173
169
|
const verified = utils.parse(signed.m as string)
|
|
174
170
|
if (cb) cb(verified)
|
|
@@ -185,7 +181,7 @@ const SEA = {
|
|
|
185
181
|
sign: async (
|
|
186
182
|
data: string | Record<string, unknown>,
|
|
187
183
|
pair: Partial<UserPair> | null,
|
|
188
|
-
cb?: Callback<SignedData | null
|
|
184
|
+
cb?: Callback<SignedData | null>,
|
|
189
185
|
): Promise<SignedData | null> => {
|
|
190
186
|
if (!pair || !pair.pub || !pair.priv) {
|
|
191
187
|
if (cb) cb(null)
|
|
@@ -199,21 +195,21 @@ const SEA = {
|
|
|
199
195
|
const check = utils.parse(data as never) as Record<string, unknown>
|
|
200
196
|
for (const k of Object.keys(check).sort()) {
|
|
201
197
|
if (k !== "_" && k !== userPublicKey && k !== userSignature) {
|
|
202
|
-
(msg as Record<string, unknown>)[k] = check[k]
|
|
198
|
+
;(msg as Record<string, unknown>)[k] = check[k]
|
|
203
199
|
}
|
|
204
200
|
}
|
|
205
201
|
}
|
|
206
202
|
const hash = await utils.sha256(msg)
|
|
207
203
|
const jwk = utils.jwk(pair.pub, pair.priv)
|
|
208
|
-
const alg = {
|
|
204
|
+
const alg = {name: "ECDSA", namedCurve: "P-256"}
|
|
209
205
|
const sig = await utils.subtle
|
|
210
206
|
.importKey("jwk", jwk, alg, false, ["sign"])
|
|
211
207
|
.then(key =>
|
|
212
208
|
utils.subtle.sign(
|
|
213
|
-
{
|
|
209
|
+
{name: "ECDSA", hash: {name: "SHA-256"}},
|
|
214
210
|
key,
|
|
215
|
-
new Uint8Array(hash)
|
|
216
|
-
)
|
|
211
|
+
new Uint8Array(hash),
|
|
212
|
+
),
|
|
217
213
|
)
|
|
218
214
|
const signed: SignedData = {
|
|
219
215
|
m: msg,
|
|
@@ -230,7 +226,7 @@ const SEA = {
|
|
|
230
226
|
signTimestamp: async (
|
|
231
227
|
timestamp: number,
|
|
232
228
|
pair: Partial<UserPair> | null,
|
|
233
|
-
cb?: Callback<string | null
|
|
229
|
+
cb?: Callback<string | null>,
|
|
234
230
|
): Promise<string | null> => {
|
|
235
231
|
if (!pair || !pair.pub || !pair.priv) {
|
|
236
232
|
if (cb) cb(null)
|
|
@@ -241,16 +237,16 @@ const SEA = {
|
|
|
241
237
|
const timestampStr = timestamp.toString()
|
|
242
238
|
const hash = await utils.sha256(timestampStr)
|
|
243
239
|
const jwk = utils.jwk(pair.pub, pair.priv)
|
|
244
|
-
const alg = {
|
|
240
|
+
const alg = {name: "ECDSA", namedCurve: "P-256"}
|
|
245
241
|
|
|
246
242
|
const sig = await utils.subtle
|
|
247
243
|
.importKey("jwk", jwk, alg, false, ["sign"])
|
|
248
244
|
.then(key =>
|
|
249
245
|
utils.subtle.sign(
|
|
250
|
-
{
|
|
246
|
+
{name: "ECDSA", hash: {name: "SHA-256"}},
|
|
251
247
|
key,
|
|
252
|
-
new Uint8Array(hash)
|
|
253
|
-
)
|
|
248
|
+
new Uint8Array(hash),
|
|
249
|
+
),
|
|
254
250
|
)
|
|
255
251
|
|
|
256
252
|
const signature = SafeBuffer.from(sig, "binary").toString("base64")
|
|
@@ -266,7 +262,7 @@ const SEA = {
|
|
|
266
262
|
timestamp: number,
|
|
267
263
|
signature: string,
|
|
268
264
|
publicKey: string,
|
|
269
|
-
cb?: Callback<boolean
|
|
265
|
+
cb?: Callback<boolean>,
|
|
270
266
|
): Promise<boolean> => {
|
|
271
267
|
if (!publicKey || !timestamp || !signature) {
|
|
272
268
|
if (cb) cb(false)
|
|
@@ -281,25 +277,27 @@ const SEA = {
|
|
|
281
277
|
const key = await utils.subtle.importKey(
|
|
282
278
|
"jwk",
|
|
283
279
|
utils.jwk(publicKey),
|
|
284
|
-
{
|
|
280
|
+
{name: "ECDSA", namedCurve: "P-256"},
|
|
285
281
|
false,
|
|
286
|
-
["verify"]
|
|
282
|
+
["verify"],
|
|
287
283
|
)
|
|
288
284
|
|
|
289
285
|
const sig = new Uint8Array(SafeBuffer.from(signature, "base64"))
|
|
290
|
-
const alg = {
|
|
286
|
+
const alg = {name: "ECDSA", hash: {name: "SHA-256"}}
|
|
291
287
|
|
|
292
288
|
const isValid = await utils.subtle.verify(
|
|
293
289
|
alg,
|
|
294
290
|
key,
|
|
295
291
|
sig,
|
|
296
|
-
new Uint8Array(hash)
|
|
292
|
+
new Uint8Array(hash),
|
|
297
293
|
)
|
|
298
294
|
|
|
299
295
|
if (cb) cb(isValid)
|
|
300
296
|
return isValid
|
|
301
297
|
} catch (err) {
|
|
302
|
-
console.log(
|
|
298
|
+
console.log(
|
|
299
|
+
`error verifying timestamp signature: ${(err as Error).message}`,
|
|
300
|
+
)
|
|
303
301
|
if (cb) cb(false)
|
|
304
302
|
return false
|
|
305
303
|
}
|
|
@@ -311,13 +309,13 @@ const SEA = {
|
|
|
311
309
|
work: async (
|
|
312
310
|
data: unknown,
|
|
313
311
|
salt?: unknown,
|
|
314
|
-
cb?: Callback<{
|
|
315
|
-
): Promise<{
|
|
312
|
+
cb?: Callback<{epriv: string}>,
|
|
313
|
+
): Promise<{epriv: string}> => {
|
|
316
314
|
let _cb = cb
|
|
317
315
|
let _salt = salt
|
|
318
316
|
|
|
319
317
|
if (typeof salt === "function") {
|
|
320
|
-
_cb = salt as Callback<{
|
|
318
|
+
_cb = salt as Callback<{epriv: string}>
|
|
321
319
|
_salt = undefined
|
|
322
320
|
}
|
|
323
321
|
if (typeof _salt === "undefined") _salt = utils.random(9)
|
|
@@ -325,19 +323,19 @@ const SEA = {
|
|
|
325
323
|
const key = await utils.subtle.importKey(
|
|
326
324
|
"raw",
|
|
327
325
|
new TextEncoder().encode(utils.stringify(data)),
|
|
328
|
-
{
|
|
326
|
+
{name: "PBKDF2"},
|
|
329
327
|
false,
|
|
330
|
-
["deriveBits"]
|
|
328
|
+
["deriveBits"],
|
|
331
329
|
)
|
|
332
330
|
const alg = {
|
|
333
331
|
name: "PBKDF2",
|
|
334
332
|
iterations: 100000,
|
|
335
333
|
salt: new TextEncoder().encode(_salt as string),
|
|
336
|
-
hash: {
|
|
334
|
+
hash: {name: "SHA-256"},
|
|
337
335
|
}
|
|
338
336
|
const work = await utils.subtle.deriveBits(alg, key, 512)
|
|
339
337
|
// Use "pair" format so that work can be used as epriv by decrypt
|
|
340
|
-
const pair = {
|
|
338
|
+
const pair = {epriv: SafeBuffer.from(work, "binary").toString("base64")}
|
|
341
339
|
if (_cb) _cb(pair)
|
|
342
340
|
return pair
|
|
343
341
|
},
|
|
@@ -348,41 +346,40 @@ const SEA = {
|
|
|
348
346
|
secret: async (
|
|
349
347
|
to: Partial<UserPair> | null,
|
|
350
348
|
from: Partial<UserPair> | null,
|
|
351
|
-
cb?: Callback<{
|
|
352
|
-
): Promise<{
|
|
349
|
+
cb?: Callback<{epriv: string} | null>,
|
|
350
|
+
): Promise<{epriv: string} | null> => {
|
|
353
351
|
if (!to || !to.epub || !from || !from.epub || !from.epriv) {
|
|
354
352
|
if (cb) cb(null)
|
|
355
353
|
return null
|
|
356
354
|
}
|
|
357
355
|
|
|
358
|
-
const alg = {
|
|
356
|
+
const alg = {name: "ECDH", namedCurve: "P-256"}
|
|
359
357
|
const pub = utils.jwk(to.epub)
|
|
360
358
|
const pubKey = await utils.subtle.importKey("jwk", pub, alg, true, [])
|
|
361
359
|
const priv = utils.jwk(from.epub, from.epriv)
|
|
362
360
|
// utils.jwk provides default key_ops but it shouldn't be used here
|
|
363
|
-
delete (priv as {
|
|
361
|
+
delete (priv as {key_ops?: unknown}).key_ops
|
|
364
362
|
const derived = await utils.subtle
|
|
365
363
|
.importKey("jwk", priv, alg, false, ["deriveBits"])
|
|
366
364
|
.then(async key => {
|
|
367
365
|
const derivedBits = await utils.subtle.deriveBits(
|
|
368
|
-
{
|
|
366
|
+
{public: pubKey, name: "ECDH", namedCurve: "P-256"} as never,
|
|
369
367
|
key,
|
|
370
|
-
256
|
|
368
|
+
256,
|
|
371
369
|
)
|
|
372
370
|
const derivedKey = await utils.subtle.importKey(
|
|
373
371
|
"raw",
|
|
374
372
|
new Uint8Array(derivedBits),
|
|
375
|
-
{
|
|
373
|
+
{name: "AES-GCM", length: 256},
|
|
376
374
|
true,
|
|
377
|
-
["encrypt", "decrypt"]
|
|
375
|
+
["encrypt", "decrypt"],
|
|
378
376
|
)
|
|
379
|
-
return utils.subtle.exportKey("jwk", derivedKey).then(({
|
|
377
|
+
return utils.subtle.exportKey("jwk", derivedKey).then(({k}) => k!)
|
|
380
378
|
})
|
|
381
379
|
// Use "pair" format so that secret can be used as epriv by encrypt
|
|
382
|
-
if (cb) cb({
|
|
383
|
-
return {
|
|
380
|
+
if (cb) cb({epriv: derived})
|
|
381
|
+
return {epriv: derived}
|
|
384
382
|
},
|
|
385
383
|
}
|
|
386
384
|
|
|
387
385
|
export default SEA
|
|
388
|
-
|
package/ts/src/store.ts
CHANGED
|
@@ -18,9 +18,7 @@ import type {
|
|
|
18
18
|
const isNode = typeof process !== "undefined" && process.versions?.node != null
|
|
19
19
|
|
|
20
20
|
// Dynamic import for Node.js fs module - won't execute in browser/service worker
|
|
21
|
-
const fs = isNode
|
|
22
|
-
? await import(/*webpackIgnore: true*/ "node:fs")
|
|
23
|
-
: undefined
|
|
21
|
+
const fs = isNode ? await import(/*webpackIgnore: true*/ "node:fs") : undefined
|
|
24
22
|
|
|
25
23
|
// ASCII character for enquiry
|
|
26
24
|
const enq = String.fromCharCode(5)
|
|
@@ -41,39 +39,49 @@ const fileSystem = (opt: StoreOptions): FileSystemInterface => {
|
|
|
41
39
|
|
|
42
40
|
return {
|
|
43
41
|
get: (file, cb) => {
|
|
44
|
-
fs!.readFile(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
fs!.readFile(
|
|
43
|
+
dir + "/" + file,
|
|
44
|
+
(err: NodeJS.ErrnoException | null, data?: Buffer) => {
|
|
45
|
+
if (err) {
|
|
46
|
+
if ((err as {code?: string}).code === "ENOENT") {
|
|
47
|
+
cb()
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
console.log("fs.readFile error:", err)
|
|
49
51
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
})
|
|
52
|
+
const dataStr = data ? data.toString() : undefined
|
|
53
|
+
cb(err as never, dataStr)
|
|
54
|
+
},
|
|
55
|
+
)
|
|
55
56
|
},
|
|
56
57
|
put: (file, data, cb) => {
|
|
57
58
|
const tmp = file + "." + utils.text.random(9) + ".tmp"
|
|
58
|
-
fs!.writeFile(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
fs!.writeFile(
|
|
60
|
+
tmp,
|
|
61
|
+
data as string,
|
|
62
|
+
(err: NodeJS.ErrnoException | null) => {
|
|
63
|
+
if (err) {
|
|
64
|
+
console.log("fs.writeFile error:", err)
|
|
65
|
+
cb(err as never)
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
fs!.rename(tmp, dir + "/" + file, cb as never)
|
|
69
|
+
},
|
|
70
|
+
)
|
|
66
71
|
},
|
|
67
72
|
list: cb => {
|
|
68
|
-
fs!.readdir(
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
fs!.readdir(
|
|
74
|
+
dir,
|
|
75
|
+
(err: NodeJS.ErrnoException | null, files?: string[]) => {
|
|
76
|
+
if (err) {
|
|
77
|
+
console.log("fs.readdir error:", err)
|
|
78
|
+
cb()
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
if (files) files.forEach(cb)
|
|
71
82
|
cb()
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (files) files.forEach(cb)
|
|
75
|
-
cb()
|
|
76
|
-
})
|
|
83
|
+
},
|
|
84
|
+
)
|
|
77
85
|
},
|
|
78
86
|
}
|
|
79
87
|
}
|
|
@@ -122,7 +130,10 @@ const fileSystem = (opt: StoreOptions): FileSystemInterface => {
|
|
|
122
130
|
|
|
123
131
|
return {
|
|
124
132
|
get: (file, cb) => {
|
|
125
|
-
const _get = (
|
|
133
|
+
const _get = (
|
|
134
|
+
file: string,
|
|
135
|
+
cb: (err?: string | null, data?: string) => void,
|
|
136
|
+
) => {
|
|
126
137
|
const tx = db.transaction([dir], "readonly")
|
|
127
138
|
const req = tx.objectStore(dir).get(file)
|
|
128
139
|
req.onerror = () => {
|
|
@@ -146,7 +157,7 @@ const fileSystem = (opt: StoreOptions): FileSystemInterface => {
|
|
|
146
157
|
const _put = (
|
|
147
158
|
file: string,
|
|
148
159
|
data: string,
|
|
149
|
-
cb: (err?: string | null) => void
|
|
160
|
+
cb: (err?: string | null) => void,
|
|
150
161
|
) => {
|
|
151
162
|
const tx = db.transaction([dir], "readwrite")
|
|
152
163
|
const req = tx.objectStore(dir).put(data, file)
|
|
@@ -209,10 +220,7 @@ const fileSystem = (opt: StoreOptions): FileSystemInterface => {
|
|
|
209
220
|
}
|
|
210
221
|
|
|
211
222
|
export interface StoreInterface {
|
|
212
|
-
get: (
|
|
213
|
-
lex: Lex,
|
|
214
|
-
cb: (err?: string | null, graph?: Graph) => void,
|
|
215
|
-
) => void
|
|
223
|
+
get: (lex: Lex, cb: (err?: string | null, graph?: Graph) => void) => void
|
|
216
224
|
put: (graph: Graph, cb: (err?: string | null) => void) => void
|
|
217
225
|
}
|
|
218
226
|
|
|
@@ -244,7 +252,7 @@ const Store = (opt?: StoreOptions): StoreInterface => {
|
|
|
244
252
|
const each = (value: EncodedValue, k: string): void => {
|
|
245
253
|
if (k !== utils.userPublicKey && !utils.match(lex["."], k)) return
|
|
246
254
|
|
|
247
|
-
if (!node) node = {
|
|
255
|
+
if (!node) node = {_: {"#": soul, ">": {}}}
|
|
248
256
|
node[k] = value[0]
|
|
249
257
|
node._[">"][k] = value[1]
|
|
250
258
|
// If signature is present, store it in _["s"]
|
|
@@ -262,7 +270,7 @@ const Store = (opt?: StoreOptions): StoreInterface => {
|
|
|
262
270
|
const finish = (err: string | null | undefined): void => {
|
|
263
271
|
if (err && !cbErr) cbErr = err
|
|
264
272
|
if (--pending > 0) return
|
|
265
|
-
const graph: Graph = {
|
|
273
|
+
const graph: Graph = {[soul]: node!}
|
|
266
274
|
if (node && Object.keys(signatures).length > 0) {
|
|
267
275
|
node._["s"] = signatures
|
|
268
276
|
}
|
|
@@ -281,7 +289,8 @@ const Store = (opt?: StoreOptions): StoreInterface => {
|
|
|
281
289
|
|
|
282
290
|
if (needsPubKey) {
|
|
283
291
|
radisk(soul + enq + utils.userPublicKey, (err, value) => {
|
|
284
|
-
if (value && !utils.obj.is(value))
|
|
292
|
+
if (value && !utils.obj.is(value))
|
|
293
|
+
each(value as EncodedValue, utils.userPublicKey)
|
|
285
294
|
finish(err)
|
|
286
295
|
})
|
|
287
296
|
}
|
|
@@ -319,9 +328,7 @@ const Store = (opt?: StoreOptions): StoreInterface => {
|
|
|
319
328
|
const value = node[key]!
|
|
320
329
|
const state = node._[">"][key]!
|
|
321
330
|
const sig = node._["s"] && node._["s"][state]
|
|
322
|
-
const data: EncodedValue = sig
|
|
323
|
-
? [value, state, sig]
|
|
324
|
-
: [value, state]
|
|
331
|
+
const data: EncodedValue = sig ? [value, state, sig] : [value, state]
|
|
325
332
|
radisk(soul + enq + key, data, ack)
|
|
326
333
|
})
|
|
327
334
|
})
|
|
@@ -330,4 +337,3 @@ const Store = (opt?: StoreOptions): StoreInterface => {
|
|
|
330
337
|
}
|
|
331
338
|
|
|
332
339
|
export default Store
|
|
333
|
-
|