@evolu/common 8.16.0 → 8.18.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/src/Bytes.d.ts +31 -14
- package/dist/src/Bytes.d.ts.map +1 -1
- package/dist/src/Bytes.js +48 -8
- package/dist/src/Crypto.d.ts +21 -3
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +18 -2
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +5 -1
- package/dist/src/Polyfills.d.ts.map +1 -1
- package/dist/src/Polyfills.js +3 -2
- package/dist/src/Task.d.ts +4 -3
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +4 -3
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +18 -7
- package/dist/src/local-first/Evolu.d.ts +10 -1
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +5 -1
- package/dist/src/local-first/Owner.d.ts +20 -8
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +23 -10
- package/dist/src/local-first/Protocol.d.ts +215 -93
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +799 -489
- package/dist/src/local-first/Relay.d.ts +9 -1
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Relay.js +41 -36
- package/dist/src/local-first/Schema.d.ts +1 -1
- package/dist/src/local-first/Shared.d.ts +75 -49
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +62 -42
- package/dist/src/local-first/Storage.d.ts +80 -18
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +20 -4
- package/package.json +1 -1
- package/src/Bytes.test.ts +212 -0
- package/src/Bytes.ts +67 -17
- package/src/Crypto.ts +23 -3
- package/src/Error.ts +5 -1
- package/src/Polyfills.ts +3 -2
- package/src/Task.ts +4 -3
- package/src/local-first/Db.ts +29 -14
- package/src/local-first/Evolu.test.ts +43 -12
- package/src/local-first/Evolu.ts +16 -2
- package/src/local-first/Owner.test.ts +52 -1
- package/src/local-first/Owner.ts +26 -7
- package/src/local-first/Protocol.test.ts +1541 -44
- package/src/local-first/Protocol.ts +1070 -605
- package/src/local-first/Relay.ts +80 -69
- package/src/local-first/Shared.ts +106 -67
- package/src/local-first/Storage.ts +100 -27
|
@@ -92,7 +92,7 @@ import { appendToArray, firstInArray, isNonEmptyArray, } from "../Array.js";
|
|
|
92
92
|
import { assert, assertNonEmptyReadonlyArray, assertNonNullable, assertNotUndefined, } from "../Assert.js";
|
|
93
93
|
import { EncryptionKey, } from "../Crypto.js";
|
|
94
94
|
import { createUnknownError } from "../Error.js";
|
|
95
|
-
import { constFalse
|
|
95
|
+
import { constFalse } from "../Function.js";
|
|
96
96
|
import { acquireLeaderLock, acquireLeaderLockCallback, } from "../LockManager.js";
|
|
97
97
|
import { createMutableRecord, getOwnProp, objectToEntries } from "../Object.js";
|
|
98
98
|
import { err, getOk, ok, trySync } from "../Result.js";
|
|
@@ -229,6 +229,7 @@ export const startDbWorker = (self) => async (run) => {
|
|
|
229
229
|
storage.setRequestContext(owner.encryptionKey, context);
|
|
230
230
|
const result = await run.abortable(applyProtocolMessageAsClient(inputMessage, {
|
|
231
231
|
writeKey: owner.writeKey,
|
|
232
|
+
onChangeTooLarge: storage.onChangeTooLarge,
|
|
232
233
|
}));
|
|
233
234
|
postQueuedResponse({
|
|
234
235
|
type: "ForSharedWorker",
|
|
@@ -312,7 +313,8 @@ export const startDbWorker = (self) => async (run) => {
|
|
|
312
313
|
};
|
|
313
314
|
// Stops once the SharedWorker no longer leads for its ID, which the
|
|
314
315
|
// platform releases when it closes, because Firefox can lose a Dispose
|
|
315
|
-
// posted right before that
|
|
316
|
+
// posted right before that
|
|
317
|
+
// (https://bugzilla.mozilla.org/show_bug.cgi?id=2077609).
|
|
316
318
|
const sharedWorkerEnded = acquireLeaderLockCallback(deps)(initMessage.sharedWorkerId, () => resolve(ok()));
|
|
317
319
|
return () => {
|
|
318
320
|
port.onMessage = null;
|
|
@@ -676,9 +678,11 @@ const createClientStorage = (deps) => {
|
|
|
676
678
|
},
|
|
677
679
|
didWriteMessages: () => didWriteMessages,
|
|
678
680
|
skippedError: () => skippedError,
|
|
681
|
+
onChangeTooLarge: (error) => {
|
|
682
|
+
skippedError ??= error;
|
|
683
|
+
},
|
|
679
684
|
// Not implemented yet.
|
|
680
685
|
validateWriteKey: constFalse,
|
|
681
|
-
setWriteKey: constVoid,
|
|
682
686
|
writeMessages: (ownerIdBytes, encryptedMessages) => () => {
|
|
683
687
|
// TODO: Add quota checking for collaborative scenarios.
|
|
684
688
|
// When receiving messages from other owners via relay broadcast,
|
|
@@ -731,10 +735,17 @@ const createClientStorage = (deps) => {
|
|
|
731
735
|
clockTimestamp = nextTimestamp.value;
|
|
732
736
|
}
|
|
733
737
|
let wroteNewMessages = false;
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
+
// SQLite can fail the write, for example on a full disk. The transaction
|
|
739
|
+
// has rolled back, so the route reports the error instead of a throw
|
|
740
|
+
// panicking the DbWorker.
|
|
741
|
+
const written = trySync(() => {
|
|
742
|
+
deps.sqlite.transaction(() => {
|
|
743
|
+
wroteNewMessages = applyMessages(deps)(ownerIdBytesToOwnerId(ownerIdBytes), messages, QuarantineOrigin.ReceivedMessage, now);
|
|
744
|
+
saveClock(deps)(clockTimestamp);
|
|
745
|
+
});
|
|
746
|
+
}, createUnknownError);
|
|
747
|
+
if (!written.ok)
|
|
748
|
+
return written;
|
|
738
749
|
clock.set(clockTimestamp);
|
|
739
750
|
// A batch of duplicates changes no table, so queries need no refresh.
|
|
740
751
|
if (wroteNewMessages)
|
|
@@ -808,7 +808,8 @@ export type DevicePersistence = "Persisted" | "NotPersisted" | "Unknown";
|
|
|
808
808
|
* request, or sent a frame that could not be decoded, the route shows a
|
|
809
809
|
* {@link ProtocolError}. A {@link ProtocolQuotaError} needs more relay quota,
|
|
810
810
|
* then {@link Evolu.requestSync}, and a {@link ProtocolVersionError} needs an app
|
|
811
|
-
* or relay update.
|
|
811
|
+
* or relay update. A route shows an {@link UnknownError} failure when this
|
|
812
|
+
* device could not store received changes, for example on a full disk.
|
|
812
813
|
*
|
|
813
814
|
* A received change that was not created with the owner's encryption key, was
|
|
814
815
|
* altered afterwards, or cannot be decoded by this app version is skipped,
|
|
@@ -833,6 +834,14 @@ export type DevicePersistence = "Persisted" | "NotPersisted" | "Unknown";
|
|
|
833
834
|
* {@link DecryptWithXChaCha20Poly1305Error} and your code creates or shares the
|
|
834
835
|
* owner, check the owner's keys.
|
|
835
836
|
*
|
|
837
|
+
* A {@link ProtocolChangeTooLargeError} skip is a change no protocol message can
|
|
838
|
+
* hold: one this device saved before {@link maxMutationSize} existed, or a
|
|
839
|
+
* crafted one received from a relay. Every route through a relay that lacks it
|
|
840
|
+
* shows it after each sync, and everything else still syncs, but changes
|
|
841
|
+
* received from one relay reach the others only after a reconnect or
|
|
842
|
+
* {@link Evolu.requestSync}. The change is not recovered, and replacing relays
|
|
843
|
+
* does not help.
|
|
844
|
+
*
|
|
836
845
|
* @group Core
|
|
837
846
|
*/
|
|
838
847
|
export type EvoluError = OtherBuildRunningError | UnknownError | UnsupportedDbVersionError;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../../src/local-first/Evolu.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAIL,KAAK,qBAAqB,EAC3B,MAAM,aAAa,CAAC;AAQrB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AAS3B,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AASjE,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAExE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAML,IAAI,EACJ,WAAW,EACX,KAAK,SAAS,EACd,aAAa,EACd,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAEV,yBAAyB,EACzB,uBAAuB,EACxB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,KAAK,EACV,QAAQ,EACR,KAAK,EACL,OAAO,EACP,cAAc,EACd,aAAa,EAEd,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../../src/local-first/Evolu.ts"],"names":[],"mappings":"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"}
|
|
@@ -496,7 +496,11 @@ export const createEvolu = (schema, config) => async (run) => {
|
|
|
496
496
|
// gets it already batched and cannot reach the call site; quarantine,
|
|
497
497
|
// which holds changes stored for sync; and skipping it in sync, which
|
|
498
498
|
// keeps range fingerprints disagreeing. Received changes are not
|
|
499
|
-
// checked
|
|
499
|
+
// checked. Changes saved before this limit can be too large for any
|
|
500
|
+
// protocol message, as can crafted changes on a relay. Their
|
|
501
|
+
// fingerprints disagree either way, so sync skips them, which ends
|
|
502
|
+
// every round instead of retrying forever. A client reports such a
|
|
503
|
+
// change as its route's skippedError, and a relay logs it. They are not
|
|
500
504
|
// recovered, which needs a history-aware design.
|
|
501
505
|
//
|
|
502
506
|
// Local-only tables never sync, so they have no limit.
|
|
@@ -132,17 +132,29 @@ export type OwnerWriteKey = typeof OwnerWriteKey.Output;
|
|
|
132
132
|
*/
|
|
133
133
|
export declare const createOwnerWriteKey: (deps: RandomBytesDep) => OwnerWriteKey;
|
|
134
134
|
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
135
|
+
* BIP-39 entropy used to derive {@link Owner} keys.
|
|
136
|
+
*
|
|
137
|
+
* A {@link Mnemonic} represents an OwnerSecret, so each valid mnemonic converts
|
|
138
|
+
* to exactly one secret with {@link mnemonicToOwnerSecret} and back with
|
|
139
|
+
* {@link ownerSecretToMnemonic}. A 24-word mnemonic holds 32 bytes, a 12-word
|
|
140
|
+
* mnemonic holds 16 bytes, and 15, 18, and 21 words hold 20, 24, and 28 bytes.
|
|
141
|
+
*
|
|
142
|
+
* {@link createOwnerSecret} generates 32 random bytes, which keep the owner
|
|
143
|
+
* post-quantum safe. The {@link OwnerId} is public and derived from the secret,
|
|
144
|
+
* so anyone who stores an owner's encrypted data can test guesses of the secret
|
|
145
|
+
* offline, and a quantum computer needs only about the square root of the
|
|
146
|
+
* guesses. 32 random bytes leave about 128 bits of security, while 16 bytes
|
|
147
|
+
* leave about 64. A secret derived from a smaller root, such as a 20-word
|
|
148
|
+
* SLIP-39 share, is no stronger than that root, whatever its length. Shorter
|
|
149
|
+
* secrets are accepted for owners created outside Evolu, typically from 12-word
|
|
150
|
+
* mnemonics.
|
|
139
151
|
*
|
|
140
152
|
* @group Core
|
|
141
153
|
*/
|
|
142
|
-
export declare const OwnerSecret: import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length32", import("../Type.ts").LengthError<32
|
|
154
|
+
export declare const OwnerSecret: import("../Type.ts").BrandType<import("../Type.ts").UnionType<readonly [import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length16", import("../Type.ts").LengthError<16>>, import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length20", import("../Type.ts").LengthError<20>>, import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length24", import("../Type.ts").LengthError<24>>, import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length28", import("../Type.ts").LengthError<28>>, import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length32", import("../Type.ts").LengthError<32>>]>, "OwnerSecret", never>;
|
|
143
155
|
export type OwnerSecret = typeof OwnerSecret.Output;
|
|
144
156
|
/**
|
|
145
|
-
* Creates a cryptographically random {@link OwnerSecret}.
|
|
157
|
+
* Creates a cryptographically random 32-byte {@link OwnerSecret}.
|
|
146
158
|
*
|
|
147
159
|
* @group Core
|
|
148
160
|
*/
|
|
@@ -152,7 +164,7 @@ export declare const createOwnerSecret: (deps: RandomBytesDep) => OwnerSecret;
|
|
|
152
164
|
*
|
|
153
165
|
* @group Testing
|
|
154
166
|
*/
|
|
155
|
-
export declare const testOwnerSecret: Uint8Array<ArrayBufferLike> & import("../Brand.ts").Brand<"Entropy"> & import("../Brand.ts").Brand<"Length32"> & import("../Brand.ts").Brand<"OwnerSecret">;
|
|
167
|
+
export declare const testOwnerSecret: ((Uint8Array<ArrayBufferLike> & import("../Brand.ts").Brand<"Entropy"> & import("../Brand.ts").Brand<"Length16">) | (Uint8Array<ArrayBufferLike> & import("../Brand.ts").Brand<"Entropy"> & import("../Brand.ts").Brand<"Length20">) | (Uint8Array<ArrayBufferLike> & import("../Brand.ts").Brand<"Entropy"> & import("../Brand.ts").Brand<"Length24">) | (Uint8Array<ArrayBufferLike> & import("../Brand.ts").Brand<"Entropy"> & import("../Brand.ts").Brand<"Length28">) | (Uint8Array<ArrayBufferLike> & import("../Brand.ts").Brand<"Entropy"> & import("../Brand.ts").Brand<"Length32">)) & import("../Brand.ts").Brand<"OwnerSecret">;
|
|
156
168
|
/**
|
|
157
169
|
* Converts an {@link OwnerSecret} to a {@link Mnemonic}.
|
|
158
170
|
*
|
|
@@ -160,7 +172,7 @@ export declare const testOwnerSecret: Uint8Array<ArrayBufferLike> & import("../B
|
|
|
160
172
|
*/
|
|
161
173
|
export declare const ownerSecretToMnemonic: (secret: OwnerSecret) => Mnemonic;
|
|
162
174
|
/**
|
|
163
|
-
* Converts a {@link Mnemonic} to
|
|
175
|
+
* Converts a {@link Mnemonic} to the {@link OwnerSecret} it represents.
|
|
164
176
|
*
|
|
165
177
|
* @group Core
|
|
166
178
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Owner.d.ts","sourceRoot":"","sources":["../../../src/local-first/Owner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAIH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"Owner.d.ts","sourceRoot":"","sources":["../../../src/local-first/Owner.ts"],"names":[],"mappings":"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"}
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
*/
|
|
42
42
|
import * as bip39 from "@scure/bip39";
|
|
43
43
|
import { wordlist } from "@scure/bip39/wordlists/english.js";
|
|
44
|
-
import { createSlip21, EncryptionKey, Entropy16, Entropy32, testCreateRandomBytes, } from "../Crypto.js";
|
|
44
|
+
import { createSlip21, EncryptionKey, Entropy16, Entropy20, Entropy24, Entropy28, Entropy32, testCreateRandomBytes, } from "../Crypto.js";
|
|
45
45
|
import { testCreateRandomLib } from "../Random.js";
|
|
46
46
|
import { getOrNull } from "../Result.js";
|
|
47
|
-
import { brand, Id, IdBytes, idBytesToId, idToIdBytes, Mnemonic, NonNegativeInt, } from "../Type.js";
|
|
47
|
+
import { brand, Id, IdBytes, idBytesToId, idToIdBytes, Mnemonic, NonNegativeInt, union, } from "../Type.js";
|
|
48
48
|
import { TimestampBytes } from "./Timestamp.js";
|
|
49
49
|
/**
|
|
50
50
|
* A branded {@link Id} that uniquely identifies an {@link Owner}.
|
|
@@ -99,16 +99,29 @@ export const OwnerWriteKey = /*#__PURE__*/ brand("OwnerWriteKey", Entropy16);
|
|
|
99
99
|
*/
|
|
100
100
|
export const createOwnerWriteKey = (deps) => deps.randomBytes.create(16);
|
|
101
101
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
102
|
+
* BIP-39 entropy used to derive {@link Owner} keys.
|
|
103
|
+
*
|
|
104
|
+
* A {@link Mnemonic} represents an OwnerSecret, so each valid mnemonic converts
|
|
105
|
+
* to exactly one secret with {@link mnemonicToOwnerSecret} and back with
|
|
106
|
+
* {@link ownerSecretToMnemonic}. A 24-word mnemonic holds 32 bytes, a 12-word
|
|
107
|
+
* mnemonic holds 16 bytes, and 15, 18, and 21 words hold 20, 24, and 28 bytes.
|
|
108
|
+
*
|
|
109
|
+
* {@link createOwnerSecret} generates 32 random bytes, which keep the owner
|
|
110
|
+
* post-quantum safe. The {@link OwnerId} is public and derived from the secret,
|
|
111
|
+
* so anyone who stores an owner's encrypted data can test guesses of the secret
|
|
112
|
+
* offline, and a quantum computer needs only about the square root of the
|
|
113
|
+
* guesses. 32 random bytes leave about 128 bits of security, while 16 bytes
|
|
114
|
+
* leave about 64. A secret derived from a smaller root, such as a 20-word
|
|
115
|
+
* SLIP-39 share, is no stronger than that root, whatever its length. Shorter
|
|
116
|
+
* secrets are accepted for owners created outside Evolu, typically from 12-word
|
|
117
|
+
* mnemonics.
|
|
106
118
|
*
|
|
107
119
|
* @group Core
|
|
108
120
|
*/
|
|
109
|
-
export const OwnerSecret = /*#__PURE__*/ brand("OwnerSecret",
|
|
121
|
+
export const OwnerSecret = /*#__PURE__*/ brand("OwnerSecret",
|
|
122
|
+
/*#__PURE__*/ union(Entropy16, Entropy20, Entropy24, Entropy28, Entropy32));
|
|
110
123
|
/**
|
|
111
|
-
* Creates a cryptographically random {@link OwnerSecret}.
|
|
124
|
+
* Creates a cryptographically random 32-byte {@link OwnerSecret}.
|
|
112
125
|
*
|
|
113
126
|
* @group Core
|
|
114
127
|
*/
|
|
@@ -130,11 +143,11 @@ export const testOwnerSecret = /*#__PURE__*/ createOwnerSecret({
|
|
|
130
143
|
*/
|
|
131
144
|
export const ownerSecretToMnemonic = (secret) => bip39.entropyToMnemonic(secret, wordlist);
|
|
132
145
|
/**
|
|
133
|
-
* Converts a {@link Mnemonic} to
|
|
146
|
+
* Converts a {@link Mnemonic} to the {@link OwnerSecret} it represents.
|
|
134
147
|
*
|
|
135
148
|
* @group Core
|
|
136
149
|
*/
|
|
137
|
-
export const mnemonicToOwnerSecret = (mnemonic) => bip39.mnemonicToEntropy(mnemonic, wordlist);
|
|
150
|
+
export const mnemonicToOwnerSecret = (mnemonic) => OwnerSecret.orThrow(bip39.mnemonicToEntropy(mnemonic, wordlist));
|
|
138
151
|
/**
|
|
139
152
|
* Creates an {@link Owner} from a {@link OwnerSecret} using SLIP-21 key
|
|
140
153
|
* derivation.
|