@metamask/keyring-sdk 4.0.0 → 4.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+CAA2C;AAC3C,gCAA4B;AAC5B,+BAA2B;AAC3B,8BAA0B;AAC1B,gCAAsB"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAiC;AACjC,+CAA2C;AAC3C,gCAA4B;AAC5B,+BAA2B;AAC3B,8BAA0B;AAC1B,sCAAkC;AAClC,gCAAsB"}
package/dist/index.mjs CHANGED
@@ -1,6 +1,8 @@
1
+ export * from "./atomic-keyring.mjs";
1
2
  export * from "./keyring-account-registry.mjs";
2
3
  export * from "./migration.mjs";
3
4
  export * from "./mnemonic.mjs";
4
5
  export * from "./entropy.mjs";
6
+ export * from "./read-write-lock.mjs";
5
7
  export * from "./eth/index.mjs";
6
8
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+CAA2C;AAC3C,gCAA4B;AAC5B,+BAA2B;AAC3B,8BAA0B;AAC1B,gCAAsB","sourcesContent":["export * from './keyring-account-registry';\nexport * from './migration';\nexport * from './mnemonic';\nexport * from './entropy';\nexport * from './eth';\n"]}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAiC;AACjC,+CAA2C;AAC3C,gCAA4B;AAC5B,+BAA2B;AAC3B,8BAA0B;AAC1B,sCAAkC;AAClC,gCAAsB","sourcesContent":["export * from './atomic-keyring';\nexport * from './keyring-account-registry';\nexport * from './migration';\nexport * from './mnemonic';\nexport * from './entropy';\nexport * from './read-write-lock';\nexport * from './eth';\n"]}
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _ReadWriteLock_instances, _ReadWriteLock_readerCount, _ReadWriteLock_writerActive, _ReadWriteLock_waiters, _ReadWriteLock_priority, _ReadWriteLock_withLock, _ReadWriteLock_hasWaiters, _ReadWriteLock_isReading, _ReadWriteLock_isWriting, _ReadWriteLock_acquire, _ReadWriteLock_grant, _ReadWriteLock_release, _ReadWriteLock_drain;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.ReadWriteLock = void 0;
16
+ /**
17
+ * A read-write lock: multiple readers may hold the lock simultaneously,
18
+ * while writers hold it exclusively.
19
+ *
20
+ * Grant order is first-in-first-out, and the lock is write-preferring by
21
+ * default: a pending writer blocks new readers, and consecutive queued
22
+ * readers are granted together once the lock turns over to them. Set the
23
+ * `priority` option to `'read'` to let new readers join active readers even
24
+ * while a writer is queued — better read latency, at the cost that
25
+ * continuous reads can starve a queued writer. The lock is always released
26
+ * when the callback settles, whether it resolves or throws.
27
+ */
28
+ class ReadWriteLock {
29
+ /**
30
+ * @param options - Lock options.
31
+ * @param options.priority - Which mode takes priority when both are
32
+ * contended. Defaults to `'write'`.
33
+ */
34
+ constructor(options = {}) {
35
+ _ReadWriteLock_instances.add(this);
36
+ _ReadWriteLock_readerCount.set(this, 0);
37
+ _ReadWriteLock_writerActive.set(this, false);
38
+ _ReadWriteLock_waiters.set(this, []);
39
+ _ReadWriteLock_priority.set(this, void 0);
40
+ __classPrivateFieldSet(this, _ReadWriteLock_priority, options.priority ?? 'write', "f");
41
+ }
42
+ /**
43
+ * Run a read operation — parallel with other readers, exclusive with
44
+ * writers. New readers queue behind any pending writer.
45
+ *
46
+ * @param fn - The operation to run while holding the read lock.
47
+ * @returns Whatever `fn` resolves to.
48
+ */
49
+ async withReadLock(fn) {
50
+ return __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_withLock).call(this, 'read', fn);
51
+ }
52
+ /**
53
+ * Run a write operation — exclusive with readers and other writers.
54
+ *
55
+ * @param fn - The operation to run while holding the write lock.
56
+ * @returns Whatever `fn` resolves to.
57
+ */
58
+ async withWriteLock(fn) {
59
+ return __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_withLock).call(this, 'write', fn);
60
+ }
61
+ }
62
+ exports.ReadWriteLock = ReadWriteLock;
63
+ _ReadWriteLock_readerCount = new WeakMap(), _ReadWriteLock_writerActive = new WeakMap(), _ReadWriteLock_waiters = new WeakMap(), _ReadWriteLock_priority = new WeakMap(), _ReadWriteLock_instances = new WeakSet(), _ReadWriteLock_withLock =
64
+ /**
65
+ * Acquire the lock in the given mode, run the operation, and release the
66
+ * lock — including on a throw, so the lock can never leak.
67
+ *
68
+ * @param mode - The mode in which to hold the lock.
69
+ * @param fn - The operation to run while holding the lock.
70
+ * @returns Whatever `fn` resolves to.
71
+ */
72
+ async function _ReadWriteLock_withLock(mode, fn) {
73
+ await __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_acquire).call(this, mode);
74
+ try {
75
+ return await fn();
76
+ }
77
+ finally {
78
+ __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_release).call(this, mode);
79
+ }
80
+ }, _ReadWriteLock_hasWaiters = function _ReadWriteLock_hasWaiters() {
81
+ return __classPrivateFieldGet(this, _ReadWriteLock_waiters, "f").length > 0;
82
+ }, _ReadWriteLock_isReading = function _ReadWriteLock_isReading() {
83
+ return __classPrivateFieldGet(this, _ReadWriteLock_readerCount, "f") > 0;
84
+ }, _ReadWriteLock_isWriting = function _ReadWriteLock_isWriting() {
85
+ return __classPrivateFieldGet(this, _ReadWriteLock_writerActive, "f");
86
+ }, _ReadWriteLock_acquire =
87
+ /**
88
+ * Acquire the lock in the given mode, queuing when it cannot be granted
89
+ * immediately.
90
+ *
91
+ * @param mode - The mode to acquire.
92
+ * @returns A promise that resolves once the lock is held.
93
+ */
94
+ async function _ReadWriteLock_acquire(mode) {
95
+ return new Promise((resolve) => {
96
+ // Writing is exclusive, so we cannot acquire the lock if a writer is active.
97
+ const blockedByWriter = __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_isWriting).call(this);
98
+ // Writing is exclusive with readers, so we cannot acquire the lock if any reader is active.
99
+ const blockedByReaders = mode === 'write' && __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_isReading).call(this);
100
+ // We cannot acquire the lock for reading if there are waiters, unless priority is 'read'.
101
+ const blockedByWriterPriority = mode === 'read' && __classPrivateFieldGet(this, _ReadWriteLock_priority, "f") === 'write' && __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_hasWaiters).call(this); // We might have pending write requests in the queue.
102
+ const acquire = !(blockedByWriter ||
103
+ blockedByReaders ||
104
+ blockedByWriterPriority);
105
+ if (acquire) {
106
+ __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_grant).call(this, mode);
107
+ resolve();
108
+ }
109
+ else {
110
+ // We cannot grant the lock immediately, so we queue the waiter.
111
+ __classPrivateFieldGet(this, _ReadWriteLock_waiters, "f").push({ mode, resolve });
112
+ }
113
+ });
114
+ }, _ReadWriteLock_grant = function _ReadWriteLock_grant(mode) {
115
+ if (mode === 'read') {
116
+ __classPrivateFieldSet(this, _ReadWriteLock_readerCount, __classPrivateFieldGet(this, _ReadWriteLock_readerCount, "f") + 1, "f");
117
+ }
118
+ else {
119
+ __classPrivateFieldSet(this, _ReadWriteLock_writerActive, true, "f");
120
+ }
121
+ }, _ReadWriteLock_release = function _ReadWriteLock_release(mode) {
122
+ if (mode === 'read') {
123
+ __classPrivateFieldSet(this, _ReadWriteLock_readerCount, __classPrivateFieldGet(this, _ReadWriteLock_readerCount, "f") - 1, "f");
124
+ }
125
+ else {
126
+ __classPrivateFieldSet(this, _ReadWriteLock_writerActive, false, "f");
127
+ }
128
+ __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_drain).call(this);
129
+ }, _ReadWriteLock_drain = function _ReadWriteLock_drain() {
130
+ let waiter = __classPrivateFieldGet(this, _ReadWriteLock_waiters, "f").shift();
131
+ while (waiter !== undefined) {
132
+ // Writing is exclusive, so we cannot acquire the lock if a writer is active.
133
+ const blockedByWriter = __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_isWriting).call(this);
134
+ // Reading blocks a writer, so we cannot acquire the lock for writing if any reader is active.
135
+ const blockedByReaders = waiter.mode === 'write' && __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_isReading).call(this);
136
+ const acquire = !(blockedByWriter || blockedByReaders);
137
+ if (acquire) {
138
+ // Grant the front waiter and continue with the next one, so consecutive queued readers are granted together.
139
+ __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_grant).call(this, waiter.mode);
140
+ waiter.resolve();
141
+ waiter = __classPrivateFieldGet(this, _ReadWriteLock_waiters, "f").shift();
142
+ }
143
+ else {
144
+ // The waiter is blocked by an active holder; put it back at the front and stop.
145
+ __classPrivateFieldGet(this, _ReadWriteLock_waiters, "f").unshift(waiter);
146
+ return;
147
+ }
148
+ }
149
+ };
150
+ //# sourceMappingURL=read-write-lock.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-write-lock.cjs","sourceRoot":"","sources":["../src/read-write-lock.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A mode in which the lock can be held: shared (`'read'`) or exclusive\n * (`'write'`).\n */\ntype LockMode = 'read' | 'write';\n\n/**\n * A queued lock-acquisition request.\n */\ntype LockWaiter = {\n /** The mode being acquired. */\n mode: LockMode;\n /** Resolves once the lock has been granted. */\n resolve: () => void;\n};\n\n/**\n * Which mode a {@link ReadWriteLock} prioritizes when both are contended.\n */\nexport type ReadWriteLockPriority = 'read' | 'write';\n\n/**\n * Options for constructing a {@link ReadWriteLock}.\n */\nexport type ReadWriteLockOptions = {\n /**\n * Which mode takes priority when both are contended. Defaults to\n * `'write'`.\n *\n * - `'write'`: a pending writer blocks new readers, so a steady stream of\n * reads cannot starve a long write.\n * - `'read'`: new readers join active readers even while a writer is\n * queued, for better read latency — at the cost that a continuous stream\n * of reads can starve a queued writer.\n */\n priority?: ReadWriteLockPriority;\n};\n\n/**\n * A read-write lock: multiple readers may hold the lock simultaneously,\n * while writers hold it exclusively.\n *\n * Grant order is first-in-first-out, and the lock is write-preferring by\n * default: a pending writer blocks new readers, and consecutive queued\n * readers are granted together once the lock turns over to them. Set the\n * `priority` option to `'read'` to let new readers join active readers even\n * while a writer is queued — better read latency, at the cost that\n * continuous reads can starve a queued writer. The lock is always released\n * when the callback settles, whether it resolves or throws.\n */\nexport class ReadWriteLock {\n #readerCount: number = 0;\n\n #writerActive: boolean = false;\n\n readonly #waiters: LockWaiter[] = [];\n\n readonly #priority: ReadWriteLockPriority;\n\n /**\n * @param options - Lock options.\n * @param options.priority - Which mode takes priority when both are\n * contended. Defaults to `'write'`.\n */\n constructor(options: ReadWriteLockOptions = {}) {\n this.#priority = options.priority ?? 'write';\n }\n\n /**\n * Run a read operation — parallel with other readers, exclusive with\n * writers. New readers queue behind any pending writer.\n *\n * @param fn - The operation to run while holding the read lock.\n * @returns Whatever `fn` resolves to.\n */\n async withReadLock<Result>(fn: () => Promise<Result>): Promise<Result> {\n return this.#withLock('read', fn);\n }\n\n /**\n * Run a write operation — exclusive with readers and other writers.\n *\n * @param fn - The operation to run while holding the write lock.\n * @returns Whatever `fn` resolves to.\n */\n async withWriteLock<Result>(fn: () => Promise<Result>): Promise<Result> {\n return this.#withLock('write', fn);\n }\n\n /**\n * Acquire the lock in the given mode, run the operation, and release the\n * lock — including on a throw, so the lock can never leak.\n *\n * @param mode - The mode in which to hold the lock.\n * @param fn - The operation to run while holding the lock.\n * @returns Whatever `fn` resolves to.\n */\n async #withLock<Result>(\n mode: LockMode,\n fn: () => Promise<Result>,\n ): Promise<Result> {\n await this.#acquire(mode);\n try {\n return await fn();\n } finally {\n this.#release(mode);\n }\n }\n\n /**\n * Whether any acquisition request is queued, waiting for the lock to turn\n * over to it. A queued waiter always blocks newcomers, which keeps the\n * grant order first-in-first-out.\n *\n * @returns Whether any acquisition request is queued.\n */\n #hasWaiters(): boolean {\n return this.#waiters.length > 0;\n }\n\n /**\n * Whether the lock is currently held for reading. Readers hold the lock\n * in parallel, so this does not mean an exclusive hold.\n *\n * @returns Whether any reader is active.\n */\n #isReading(): boolean {\n return this.#readerCount > 0;\n }\n\n /**\n * Whether the lock is currently held for writing. A writer holds the lock\n * exclusively: while writing, no other holder — reader or writer — can\n * be active.\n *\n * @returns Whether a writer is active.\n */\n #isWriting(): boolean {\n return this.#writerActive;\n }\n\n /**\n * Acquire the lock in the given mode, queuing when it cannot be granted\n * immediately.\n *\n * @param mode - The mode to acquire.\n * @returns A promise that resolves once the lock is held.\n */\n async #acquire(mode: LockMode): Promise<void> {\n return new Promise<void>((resolve) => {\n // Writing is exclusive, so we cannot acquire the lock if a writer is active.\n const blockedByWriter = this.#isWriting();\n // Writing is exclusive with readers, so we cannot acquire the lock if any reader is active.\n const blockedByReaders = mode === 'write' && this.#isReading();\n // We cannot acquire the lock for reading if there are waiters, unless priority is 'read'.\n const blockedByWriterPriority =\n mode === 'read' && this.#priority === 'write' && this.#hasWaiters(); // We might have pending write requests in the queue.\n\n const acquire = !(\n blockedByWriter ||\n blockedByReaders ||\n blockedByWriterPriority\n );\n\n if (acquire) {\n this.#grant(mode);\n resolve();\n } else {\n // We cannot grant the lock immediately, so we queue the waiter.\n this.#waiters.push({ mode, resolve });\n }\n });\n }\n\n /**\n * Grant the lock in the given mode. Only called when the grant is legal.\n *\n * @param mode - The mode to grant.\n */\n #grant(mode: LockMode): void {\n if (mode === 'read') {\n this.#readerCount += 1;\n } else {\n this.#writerActive = true;\n }\n }\n\n /**\n * Release the lock in the given mode, then grant queued waiters in order.\n *\n * @param mode - The mode being released.\n */\n #release(mode: LockMode): void {\n if (mode === 'read') {\n this.#readerCount -= 1;\n } else {\n this.#writerActive = false;\n }\n this.#drain();\n }\n\n /**\n * Grant queued waiters, in order, while the front of the queue can be\n * granted. Consecutive queued readers are granted together; a granted\n * writer blocks everything behind it. Unlike a newcomer, the front\n * waiter is never blocked by queued waiters — everyone behind it\n * arrived later — so only active holders block a grant here.\n */\n #drain(): void {\n let waiter: LockWaiter | undefined = this.#waiters.shift();\n while (waiter !== undefined) {\n // Writing is exclusive, so we cannot acquire the lock if a writer is active.\n const blockedByWriter = this.#isWriting();\n // Reading blocks a writer, so we cannot acquire the lock for writing if any reader is active.\n const blockedByReaders = waiter.mode === 'write' && this.#isReading();\n\n const acquire = !(blockedByWriter || blockedByReaders);\n\n if (acquire) {\n // Grant the front waiter and continue with the next one, so consecutive queued readers are granted together.\n this.#grant(waiter.mode);\n waiter.resolve();\n waiter = this.#waiters.shift();\n } else {\n // The waiter is blocked by an active holder; put it back at the front and stop.\n this.#waiters.unshift(waiter);\n return;\n }\n }\n }\n}\n"]}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Which mode a {@link ReadWriteLock} prioritizes when both are contended.
3
+ */
4
+ export type ReadWriteLockPriority = 'read' | 'write';
5
+ /**
6
+ * Options for constructing a {@link ReadWriteLock}.
7
+ */
8
+ export type ReadWriteLockOptions = {
9
+ /**
10
+ * Which mode takes priority when both are contended. Defaults to
11
+ * `'write'`.
12
+ *
13
+ * - `'write'`: a pending writer blocks new readers, so a steady stream of
14
+ * reads cannot starve a long write.
15
+ * - `'read'`: new readers join active readers even while a writer is
16
+ * queued, for better read latency — at the cost that a continuous stream
17
+ * of reads can starve a queued writer.
18
+ */
19
+ priority?: ReadWriteLockPriority;
20
+ };
21
+ /**
22
+ * A read-write lock: multiple readers may hold the lock simultaneously,
23
+ * while writers hold it exclusively.
24
+ *
25
+ * Grant order is first-in-first-out, and the lock is write-preferring by
26
+ * default: a pending writer blocks new readers, and consecutive queued
27
+ * readers are granted together once the lock turns over to them. Set the
28
+ * `priority` option to `'read'` to let new readers join active readers even
29
+ * while a writer is queued — better read latency, at the cost that
30
+ * continuous reads can starve a queued writer. The lock is always released
31
+ * when the callback settles, whether it resolves or throws.
32
+ */
33
+ export declare class ReadWriteLock {
34
+ #private;
35
+ /**
36
+ * @param options - Lock options.
37
+ * @param options.priority - Which mode takes priority when both are
38
+ * contended. Defaults to `'write'`.
39
+ */
40
+ constructor(options?: ReadWriteLockOptions);
41
+ /**
42
+ * Run a read operation — parallel with other readers, exclusive with
43
+ * writers. New readers queue behind any pending writer.
44
+ *
45
+ * @param fn - The operation to run while holding the read lock.
46
+ * @returns Whatever `fn` resolves to.
47
+ */
48
+ withReadLock<Result>(fn: () => Promise<Result>): Promise<Result>;
49
+ /**
50
+ * Run a write operation — exclusive with readers and other writers.
51
+ *
52
+ * @param fn - The operation to run while holding the write lock.
53
+ * @returns Whatever `fn` resolves to.
54
+ */
55
+ withWriteLock<Result>(fn: () => Promise<Result>): Promise<Result>;
56
+ }
57
+ //# sourceMappingURL=read-write-lock.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-write-lock.d.cts","sourceRoot":"","sources":["../src/read-write-lock.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,OAAO,CAAC;AAErD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,qBAAa,aAAa;;IASxB;;;;OAIG;gBACS,OAAO,GAAE,oBAAyB;IAI9C;;;;;;OAMG;IACG,YAAY,CAAC,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAItE;;;;;OAKG;IACG,aAAa,CAAC,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;CAiJxE"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Which mode a {@link ReadWriteLock} prioritizes when both are contended.
3
+ */
4
+ export type ReadWriteLockPriority = 'read' | 'write';
5
+ /**
6
+ * Options for constructing a {@link ReadWriteLock}.
7
+ */
8
+ export type ReadWriteLockOptions = {
9
+ /**
10
+ * Which mode takes priority when both are contended. Defaults to
11
+ * `'write'`.
12
+ *
13
+ * - `'write'`: a pending writer blocks new readers, so a steady stream of
14
+ * reads cannot starve a long write.
15
+ * - `'read'`: new readers join active readers even while a writer is
16
+ * queued, for better read latency — at the cost that a continuous stream
17
+ * of reads can starve a queued writer.
18
+ */
19
+ priority?: ReadWriteLockPriority;
20
+ };
21
+ /**
22
+ * A read-write lock: multiple readers may hold the lock simultaneously,
23
+ * while writers hold it exclusively.
24
+ *
25
+ * Grant order is first-in-first-out, and the lock is write-preferring by
26
+ * default: a pending writer blocks new readers, and consecutive queued
27
+ * readers are granted together once the lock turns over to them. Set the
28
+ * `priority` option to `'read'` to let new readers join active readers even
29
+ * while a writer is queued — better read latency, at the cost that
30
+ * continuous reads can starve a queued writer. The lock is always released
31
+ * when the callback settles, whether it resolves or throws.
32
+ */
33
+ export declare class ReadWriteLock {
34
+ #private;
35
+ /**
36
+ * @param options - Lock options.
37
+ * @param options.priority - Which mode takes priority when both are
38
+ * contended. Defaults to `'write'`.
39
+ */
40
+ constructor(options?: ReadWriteLockOptions);
41
+ /**
42
+ * Run a read operation — parallel with other readers, exclusive with
43
+ * writers. New readers queue behind any pending writer.
44
+ *
45
+ * @param fn - The operation to run while holding the read lock.
46
+ * @returns Whatever `fn` resolves to.
47
+ */
48
+ withReadLock<Result>(fn: () => Promise<Result>): Promise<Result>;
49
+ /**
50
+ * Run a write operation — exclusive with readers and other writers.
51
+ *
52
+ * @param fn - The operation to run while holding the write lock.
53
+ * @returns Whatever `fn` resolves to.
54
+ */
55
+ withWriteLock<Result>(fn: () => Promise<Result>): Promise<Result>;
56
+ }
57
+ //# sourceMappingURL=read-write-lock.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-write-lock.d.mts","sourceRoot":"","sources":["../src/read-write-lock.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,OAAO,CAAC;AAErD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,qBAAa,aAAa;;IASxB;;;;OAIG;gBACS,OAAO,GAAE,oBAAyB;IAI9C;;;;;;OAMG;IACG,YAAY,CAAC,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAItE;;;;;OAKG;IACG,aAAa,CAAC,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;CAiJxE"}
@@ -0,0 +1,146 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _ReadWriteLock_instances, _ReadWriteLock_readerCount, _ReadWriteLock_writerActive, _ReadWriteLock_waiters, _ReadWriteLock_priority, _ReadWriteLock_withLock, _ReadWriteLock_hasWaiters, _ReadWriteLock_isReading, _ReadWriteLock_isWriting, _ReadWriteLock_acquire, _ReadWriteLock_grant, _ReadWriteLock_release, _ReadWriteLock_drain;
13
+ /**
14
+ * A read-write lock: multiple readers may hold the lock simultaneously,
15
+ * while writers hold it exclusively.
16
+ *
17
+ * Grant order is first-in-first-out, and the lock is write-preferring by
18
+ * default: a pending writer blocks new readers, and consecutive queued
19
+ * readers are granted together once the lock turns over to them. Set the
20
+ * `priority` option to `'read'` to let new readers join active readers even
21
+ * while a writer is queued — better read latency, at the cost that
22
+ * continuous reads can starve a queued writer. The lock is always released
23
+ * when the callback settles, whether it resolves or throws.
24
+ */
25
+ export class ReadWriteLock {
26
+ /**
27
+ * @param options - Lock options.
28
+ * @param options.priority - Which mode takes priority when both are
29
+ * contended. Defaults to `'write'`.
30
+ */
31
+ constructor(options = {}) {
32
+ _ReadWriteLock_instances.add(this);
33
+ _ReadWriteLock_readerCount.set(this, 0);
34
+ _ReadWriteLock_writerActive.set(this, false);
35
+ _ReadWriteLock_waiters.set(this, []);
36
+ _ReadWriteLock_priority.set(this, void 0);
37
+ __classPrivateFieldSet(this, _ReadWriteLock_priority, options.priority ?? 'write', "f");
38
+ }
39
+ /**
40
+ * Run a read operation — parallel with other readers, exclusive with
41
+ * writers. New readers queue behind any pending writer.
42
+ *
43
+ * @param fn - The operation to run while holding the read lock.
44
+ * @returns Whatever `fn` resolves to.
45
+ */
46
+ async withReadLock(fn) {
47
+ return __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_withLock).call(this, 'read', fn);
48
+ }
49
+ /**
50
+ * Run a write operation — exclusive with readers and other writers.
51
+ *
52
+ * @param fn - The operation to run while holding the write lock.
53
+ * @returns Whatever `fn` resolves to.
54
+ */
55
+ async withWriteLock(fn) {
56
+ return __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_withLock).call(this, 'write', fn);
57
+ }
58
+ }
59
+ _ReadWriteLock_readerCount = new WeakMap(), _ReadWriteLock_writerActive = new WeakMap(), _ReadWriteLock_waiters = new WeakMap(), _ReadWriteLock_priority = new WeakMap(), _ReadWriteLock_instances = new WeakSet(), _ReadWriteLock_withLock =
60
+ /**
61
+ * Acquire the lock in the given mode, run the operation, and release the
62
+ * lock — including on a throw, so the lock can never leak.
63
+ *
64
+ * @param mode - The mode in which to hold the lock.
65
+ * @param fn - The operation to run while holding the lock.
66
+ * @returns Whatever `fn` resolves to.
67
+ */
68
+ async function _ReadWriteLock_withLock(mode, fn) {
69
+ await __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_acquire).call(this, mode);
70
+ try {
71
+ return await fn();
72
+ }
73
+ finally {
74
+ __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_release).call(this, mode);
75
+ }
76
+ }, _ReadWriteLock_hasWaiters = function _ReadWriteLock_hasWaiters() {
77
+ return __classPrivateFieldGet(this, _ReadWriteLock_waiters, "f").length > 0;
78
+ }, _ReadWriteLock_isReading = function _ReadWriteLock_isReading() {
79
+ return __classPrivateFieldGet(this, _ReadWriteLock_readerCount, "f") > 0;
80
+ }, _ReadWriteLock_isWriting = function _ReadWriteLock_isWriting() {
81
+ return __classPrivateFieldGet(this, _ReadWriteLock_writerActive, "f");
82
+ }, _ReadWriteLock_acquire =
83
+ /**
84
+ * Acquire the lock in the given mode, queuing when it cannot be granted
85
+ * immediately.
86
+ *
87
+ * @param mode - The mode to acquire.
88
+ * @returns A promise that resolves once the lock is held.
89
+ */
90
+ async function _ReadWriteLock_acquire(mode) {
91
+ return new Promise((resolve) => {
92
+ // Writing is exclusive, so we cannot acquire the lock if a writer is active.
93
+ const blockedByWriter = __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_isWriting).call(this);
94
+ // Writing is exclusive with readers, so we cannot acquire the lock if any reader is active.
95
+ const blockedByReaders = mode === 'write' && __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_isReading).call(this);
96
+ // We cannot acquire the lock for reading if there are waiters, unless priority is 'read'.
97
+ const blockedByWriterPriority = mode === 'read' && __classPrivateFieldGet(this, _ReadWriteLock_priority, "f") === 'write' && __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_hasWaiters).call(this); // We might have pending write requests in the queue.
98
+ const acquire = !(blockedByWriter ||
99
+ blockedByReaders ||
100
+ blockedByWriterPriority);
101
+ if (acquire) {
102
+ __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_grant).call(this, mode);
103
+ resolve();
104
+ }
105
+ else {
106
+ // We cannot grant the lock immediately, so we queue the waiter.
107
+ __classPrivateFieldGet(this, _ReadWriteLock_waiters, "f").push({ mode, resolve });
108
+ }
109
+ });
110
+ }, _ReadWriteLock_grant = function _ReadWriteLock_grant(mode) {
111
+ if (mode === 'read') {
112
+ __classPrivateFieldSet(this, _ReadWriteLock_readerCount, __classPrivateFieldGet(this, _ReadWriteLock_readerCount, "f") + 1, "f");
113
+ }
114
+ else {
115
+ __classPrivateFieldSet(this, _ReadWriteLock_writerActive, true, "f");
116
+ }
117
+ }, _ReadWriteLock_release = function _ReadWriteLock_release(mode) {
118
+ if (mode === 'read') {
119
+ __classPrivateFieldSet(this, _ReadWriteLock_readerCount, __classPrivateFieldGet(this, _ReadWriteLock_readerCount, "f") - 1, "f");
120
+ }
121
+ else {
122
+ __classPrivateFieldSet(this, _ReadWriteLock_writerActive, false, "f");
123
+ }
124
+ __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_drain).call(this);
125
+ }, _ReadWriteLock_drain = function _ReadWriteLock_drain() {
126
+ let waiter = __classPrivateFieldGet(this, _ReadWriteLock_waiters, "f").shift();
127
+ while (waiter !== undefined) {
128
+ // Writing is exclusive, so we cannot acquire the lock if a writer is active.
129
+ const blockedByWriter = __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_isWriting).call(this);
130
+ // Reading blocks a writer, so we cannot acquire the lock for writing if any reader is active.
131
+ const blockedByReaders = waiter.mode === 'write' && __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_isReading).call(this);
132
+ const acquire = !(blockedByWriter || blockedByReaders);
133
+ if (acquire) {
134
+ // Grant the front waiter and continue with the next one, so consecutive queued readers are granted together.
135
+ __classPrivateFieldGet(this, _ReadWriteLock_instances, "m", _ReadWriteLock_grant).call(this, waiter.mode);
136
+ waiter.resolve();
137
+ waiter = __classPrivateFieldGet(this, _ReadWriteLock_waiters, "f").shift();
138
+ }
139
+ else {
140
+ // The waiter is blocked by an active holder; put it back at the front and stop.
141
+ __classPrivateFieldGet(this, _ReadWriteLock_waiters, "f").unshift(waiter);
142
+ return;
143
+ }
144
+ }
145
+ };
146
+ //# sourceMappingURL=read-write-lock.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-write-lock.mjs","sourceRoot":"","sources":["../src/read-write-lock.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A mode in which the lock can be held: shared (`'read'`) or exclusive\n * (`'write'`).\n */\ntype LockMode = 'read' | 'write';\n\n/**\n * A queued lock-acquisition request.\n */\ntype LockWaiter = {\n /** The mode being acquired. */\n mode: LockMode;\n /** Resolves once the lock has been granted. */\n resolve: () => void;\n};\n\n/**\n * Which mode a {@link ReadWriteLock} prioritizes when both are contended.\n */\nexport type ReadWriteLockPriority = 'read' | 'write';\n\n/**\n * Options for constructing a {@link ReadWriteLock}.\n */\nexport type ReadWriteLockOptions = {\n /**\n * Which mode takes priority when both are contended. Defaults to\n * `'write'`.\n *\n * - `'write'`: a pending writer blocks new readers, so a steady stream of\n * reads cannot starve a long write.\n * - `'read'`: new readers join active readers even while a writer is\n * queued, for better read latency — at the cost that a continuous stream\n * of reads can starve a queued writer.\n */\n priority?: ReadWriteLockPriority;\n};\n\n/**\n * A read-write lock: multiple readers may hold the lock simultaneously,\n * while writers hold it exclusively.\n *\n * Grant order is first-in-first-out, and the lock is write-preferring by\n * default: a pending writer blocks new readers, and consecutive queued\n * readers are granted together once the lock turns over to them. Set the\n * `priority` option to `'read'` to let new readers join active readers even\n * while a writer is queued — better read latency, at the cost that\n * continuous reads can starve a queued writer. The lock is always released\n * when the callback settles, whether it resolves or throws.\n */\nexport class ReadWriteLock {\n #readerCount: number = 0;\n\n #writerActive: boolean = false;\n\n readonly #waiters: LockWaiter[] = [];\n\n readonly #priority: ReadWriteLockPriority;\n\n /**\n * @param options - Lock options.\n * @param options.priority - Which mode takes priority when both are\n * contended. Defaults to `'write'`.\n */\n constructor(options: ReadWriteLockOptions = {}) {\n this.#priority = options.priority ?? 'write';\n }\n\n /**\n * Run a read operation — parallel with other readers, exclusive with\n * writers. New readers queue behind any pending writer.\n *\n * @param fn - The operation to run while holding the read lock.\n * @returns Whatever `fn` resolves to.\n */\n async withReadLock<Result>(fn: () => Promise<Result>): Promise<Result> {\n return this.#withLock('read', fn);\n }\n\n /**\n * Run a write operation — exclusive with readers and other writers.\n *\n * @param fn - The operation to run while holding the write lock.\n * @returns Whatever `fn` resolves to.\n */\n async withWriteLock<Result>(fn: () => Promise<Result>): Promise<Result> {\n return this.#withLock('write', fn);\n }\n\n /**\n * Acquire the lock in the given mode, run the operation, and release the\n * lock — including on a throw, so the lock can never leak.\n *\n * @param mode - The mode in which to hold the lock.\n * @param fn - The operation to run while holding the lock.\n * @returns Whatever `fn` resolves to.\n */\n async #withLock<Result>(\n mode: LockMode,\n fn: () => Promise<Result>,\n ): Promise<Result> {\n await this.#acquire(mode);\n try {\n return await fn();\n } finally {\n this.#release(mode);\n }\n }\n\n /**\n * Whether any acquisition request is queued, waiting for the lock to turn\n * over to it. A queued waiter always blocks newcomers, which keeps the\n * grant order first-in-first-out.\n *\n * @returns Whether any acquisition request is queued.\n */\n #hasWaiters(): boolean {\n return this.#waiters.length > 0;\n }\n\n /**\n * Whether the lock is currently held for reading. Readers hold the lock\n * in parallel, so this does not mean an exclusive hold.\n *\n * @returns Whether any reader is active.\n */\n #isReading(): boolean {\n return this.#readerCount > 0;\n }\n\n /**\n * Whether the lock is currently held for writing. A writer holds the lock\n * exclusively: while writing, no other holder — reader or writer — can\n * be active.\n *\n * @returns Whether a writer is active.\n */\n #isWriting(): boolean {\n return this.#writerActive;\n }\n\n /**\n * Acquire the lock in the given mode, queuing when it cannot be granted\n * immediately.\n *\n * @param mode - The mode to acquire.\n * @returns A promise that resolves once the lock is held.\n */\n async #acquire(mode: LockMode): Promise<void> {\n return new Promise<void>((resolve) => {\n // Writing is exclusive, so we cannot acquire the lock if a writer is active.\n const blockedByWriter = this.#isWriting();\n // Writing is exclusive with readers, so we cannot acquire the lock if any reader is active.\n const blockedByReaders = mode === 'write' && this.#isReading();\n // We cannot acquire the lock for reading if there are waiters, unless priority is 'read'.\n const blockedByWriterPriority =\n mode === 'read' && this.#priority === 'write' && this.#hasWaiters(); // We might have pending write requests in the queue.\n\n const acquire = !(\n blockedByWriter ||\n blockedByReaders ||\n blockedByWriterPriority\n );\n\n if (acquire) {\n this.#grant(mode);\n resolve();\n } else {\n // We cannot grant the lock immediately, so we queue the waiter.\n this.#waiters.push({ mode, resolve });\n }\n });\n }\n\n /**\n * Grant the lock in the given mode. Only called when the grant is legal.\n *\n * @param mode - The mode to grant.\n */\n #grant(mode: LockMode): void {\n if (mode === 'read') {\n this.#readerCount += 1;\n } else {\n this.#writerActive = true;\n }\n }\n\n /**\n * Release the lock in the given mode, then grant queued waiters in order.\n *\n * @param mode - The mode being released.\n */\n #release(mode: LockMode): void {\n if (mode === 'read') {\n this.#readerCount -= 1;\n } else {\n this.#writerActive = false;\n }\n this.#drain();\n }\n\n /**\n * Grant queued waiters, in order, while the front of the queue can be\n * granted. Consecutive queued readers are granted together; a granted\n * writer blocks everything behind it. Unlike a newcomer, the front\n * waiter is never blocked by queued waiters — everyone behind it\n * arrived later — so only active holders block a grant here.\n */\n #drain(): void {\n let waiter: LockWaiter | undefined = this.#waiters.shift();\n while (waiter !== undefined) {\n // Writing is exclusive, so we cannot acquire the lock if a writer is active.\n const blockedByWriter = this.#isWriting();\n // Reading blocks a writer, so we cannot acquire the lock for writing if any reader is active.\n const blockedByReaders = waiter.mode === 'write' && this.#isReading();\n\n const acquire = !(blockedByWriter || blockedByReaders);\n\n if (acquire) {\n // Grant the front waiter and continue with the next one, so consecutive queued readers are granted together.\n this.#grant(waiter.mode);\n waiter.resolve();\n waiter = this.#waiters.shift();\n } else {\n // The waiter is blocked by an active holder; put it back at the front and stop.\n this.#waiters.unshift(waiter);\n return;\n }\n }\n }\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.KeyringV1Adapter = void 0;
3
+ exports.isKeyringV1Adapter = exports.KeyringV1Adapter = void 0;
4
+ const utils_1 = require("@metamask/utils");
4
5
  /**
5
6
  * Generic adapter that wraps a v2 {@link KeyringV2} instance and exposes it
6
7
  * through the v1 {@link BaseKeyring} interface expected by `KeyringController`.
@@ -81,4 +82,28 @@ class KeyringV1Adapter {
81
82
  }
82
83
  }
83
84
  exports.KeyringV1Adapter = KeyringV1Adapter;
85
+ /**
86
+ * Check whether the given value is a {@link KeyringV1Adapter}, including
87
+ * subclasses such as `EthKeyringV1Adapter` or `SnapKeyringV1Adapter`.
88
+ *
89
+ * This is a structural check on the adapter's public surface, not an
90
+ * `instanceof` check: a consumer may hold a different copy of this package
91
+ * than the one that constructed the adapter (a split dependency tree), in
92
+ * which case `instanceof` is always `false`. `unwrap` is the distinguishing
93
+ * API — no v1 or v2 keyring exposes it — and it is the method consumers call
94
+ * to retrieve the inner v2 instance.
95
+ *
96
+ * @param value - The value to check.
97
+ * @returns Whether the value is a `KeyringV1Adapter`.
98
+ */
99
+ function isKeyringV1Adapter(value) {
100
+ if (!(0, utils_1.isObject)(value)) {
101
+ return false;
102
+ }
103
+ // Property access rather than `hasProperty`: `unwrap` is a prototype
104
+ // method, not an own property, so own-property checks miss it.
105
+ const { type, unwrap } = value;
106
+ return typeof type === 'string' && typeof unwrap === 'function';
107
+ }
108
+ exports.isKeyringV1Adapter = isKeyringV1Adapter;
84
109
  //# sourceMappingURL=keyring-v1-adapter.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"keyring-v1-adapter.cjs","sourceRoot":"","sources":["../../src/v2/keyring-v1-adapter.ts"],"names":[],"mappings":";;;AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAa,gBAAgB;IAU3B,YAAY,KAAmB;QAC7B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAED;;;;;;;OAOG;IACH,MAAM;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,WAAW;QACf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QAChD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAuB,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACpE,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;IAChC,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,WAAW,CAAC,KAAW;QAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;CACF;AA9DD,4CA8DC","sourcesContent":["import type { KeyringAccount } from '@metamask/keyring-api';\nimport type { Keyring as KeyringV2 } from '@metamask/keyring-api/v2';\nimport type { BaseKeyring } from '@metamask/keyring-utils';\nimport type { Json } from '@metamask/utils';\n\n/**\n * Generic adapter that wraps a v2 {@link KeyringV2} instance and exposes it\n * through the v1 {@link BaseKeyring} interface expected by `KeyringController`.\n *\n * ## Why this exists\n *\n * `KeyringController` interacts with all keyrings via the v1 `BaseKeyring`\n * interface — notably `getAccounts()` which must return `Promise<string[]>`\n * (addresses). The v2 `Keyring` interface returns `Promise<KeyringAccount[]>`\n * from `getAccounts()`, an incompatible signature.\n *\n * ## Architecture\n *\n * This class holds a v2 `Keyring` instance and exposes it via {@link unwrap}.\n * `KeyringController` stores this adapter as the v1 keyring entry; its\n * `KeyringV2Builder` calls `unwrap()` to retrieve the same inner instance for\n * the v2 entry — no state duplication.\n *\n * ```\n * KeyringEntry {\n * keyring: KeyringV1Adapter ← v1 face (this class)\n * keyringV2: InnerKeyring ← v2 face (same instance via unwrap())\n * }\n * ```\n *\n * @typeParam InnerKeyring - The concrete v2 keyring type being wrapped.\n * Defaults to the base {@link KeyringV2} interface. Specifying a concrete\n * subtype preserves full type information through {@link unwrap}.\n */\nexport class KeyringV1Adapter<\n InnerKeyring extends KeyringV2 = KeyringV2,\n> implements BaseKeyring {\n /**\n * Keyring type identifier, mirroring the inner v2 instance's type.\n */\n readonly type: string;\n\n protected readonly inner: InnerKeyring;\n\n constructor(inner: InnerKeyring) {\n this.inner = inner;\n this.type = inner.type;\n }\n\n /**\n * Returns the inner v2 {@link KeyringV2} instance.\n *\n * Intended for use by `KeyringController`'s `KeyringV2Builder` so that both\n * the v1 and v2 keyring entries in a `KeyringEntry` share the same object.\n *\n * @returns The inner v2 keyring instance.\n */\n unwrap(): InnerKeyring {\n return this.inner;\n }\n\n /**\n * Returns the addresses of all accounts in this keyring.\n *\n * Adapts the v2 `getAccounts()` (which returns `KeyringAccount[]`) to the\n * v1 `BaseKeyring` interface (`string[]`).\n *\n * @returns A promise resolving to the list of account addresses.\n */\n async getAccounts(): Promise<string[]> {\n const accounts = await this.inner.getAccounts();\n return accounts.map((account: KeyringAccount) => account.address);\n }\n\n /**\n * Serializes the keyring state.\n *\n * Delegates to the inner v2 instance.\n *\n * @returns A promise resolving to the serialized state.\n */\n async serialize(): Promise<Json> {\n return this.inner.serialize();\n }\n\n /**\n * Restores keyring state from a serialized snapshot.\n *\n * Delegates to the inner v2 instance.\n *\n * @param state - The serialized state to restore.\n * @returns A promise that resolves when deserialization is complete.\n */\n async deserialize(state: Json): Promise<void> {\n return this.inner.deserialize(state);\n }\n}\n"]}
1
+ {"version":3,"file":"keyring-v1-adapter.cjs","sourceRoot":"","sources":["../../src/v2/keyring-v1-adapter.ts"],"names":[],"mappings":";;;AAGA,2CAA2C;AAG3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAa,gBAAgB;IAU3B,YAAY,KAAmB;QAC7B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAED;;;;;;;OAOG;IACH,MAAM;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,WAAW;QACf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QAChD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAuB,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACpE,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;IAChC,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,WAAW,CAAC,KAAW;QAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;CACF;AA9DD,4CA8DC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,kBAAkB,CAChC,KAAc;IAEd,IAAI,CAAC,IAAA,gBAAQ,EAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,qEAAqE;IACrE,+DAA+D;IAC/D,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAA6C,CAAC;IAEvE,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,UAAU,CAAC;AAClE,CAAC;AAZD,gDAYC","sourcesContent":["import type { KeyringAccount } from '@metamask/keyring-api';\nimport type { Keyring as KeyringV2 } from '@metamask/keyring-api/v2';\nimport type { BaseKeyring } from '@metamask/keyring-utils';\nimport { isObject } from '@metamask/utils';\nimport type { Json } from '@metamask/utils';\n\n/**\n * Generic adapter that wraps a v2 {@link KeyringV2} instance and exposes it\n * through the v1 {@link BaseKeyring} interface expected by `KeyringController`.\n *\n * ## Why this exists\n *\n * `KeyringController` interacts with all keyrings via the v1 `BaseKeyring`\n * interface — notably `getAccounts()` which must return `Promise<string[]>`\n * (addresses). The v2 `Keyring` interface returns `Promise<KeyringAccount[]>`\n * from `getAccounts()`, an incompatible signature.\n *\n * ## Architecture\n *\n * This class holds a v2 `Keyring` instance and exposes it via {@link unwrap}.\n * `KeyringController` stores this adapter as the v1 keyring entry; its\n * `KeyringV2Builder` calls `unwrap()` to retrieve the same inner instance for\n * the v2 entry — no state duplication.\n *\n * ```\n * KeyringEntry {\n * keyring: KeyringV1Adapter ← v1 face (this class)\n * keyringV2: InnerKeyring ← v2 face (same instance via unwrap())\n * }\n * ```\n *\n * @typeParam InnerKeyring - The concrete v2 keyring type being wrapped.\n * Defaults to the base {@link KeyringV2} interface. Specifying a concrete\n * subtype preserves full type information through {@link unwrap}.\n */\nexport class KeyringV1Adapter<\n InnerKeyring extends KeyringV2 = KeyringV2,\n> implements BaseKeyring {\n /**\n * Keyring type identifier, mirroring the inner v2 instance's type.\n */\n readonly type: string;\n\n protected readonly inner: InnerKeyring;\n\n constructor(inner: InnerKeyring) {\n this.inner = inner;\n this.type = inner.type;\n }\n\n /**\n * Returns the inner v2 {@link KeyringV2} instance.\n *\n * Intended for use by `KeyringController`'s `KeyringV2Builder` so that both\n * the v1 and v2 keyring entries in a `KeyringEntry` share the same object.\n *\n * @returns The inner v2 keyring instance.\n */\n unwrap(): InnerKeyring {\n return this.inner;\n }\n\n /**\n * Returns the addresses of all accounts in this keyring.\n *\n * Adapts the v2 `getAccounts()` (which returns `KeyringAccount[]`) to the\n * v1 `BaseKeyring` interface (`string[]`).\n *\n * @returns A promise resolving to the list of account addresses.\n */\n async getAccounts(): Promise<string[]> {\n const accounts = await this.inner.getAccounts();\n return accounts.map((account: KeyringAccount) => account.address);\n }\n\n /**\n * Serializes the keyring state.\n *\n * Delegates to the inner v2 instance.\n *\n * @returns A promise resolving to the serialized state.\n */\n async serialize(): Promise<Json> {\n return this.inner.serialize();\n }\n\n /**\n * Restores keyring state from a serialized snapshot.\n *\n * Delegates to the inner v2 instance.\n *\n * @param state - The serialized state to restore.\n * @returns A promise that resolves when deserialization is complete.\n */\n async deserialize(state: Json): Promise<void> {\n return this.inner.deserialize(state);\n }\n}\n\n/**\n * Check whether the given value is a {@link KeyringV1Adapter}, including\n * subclasses such as `EthKeyringV1Adapter` or `SnapKeyringV1Adapter`.\n *\n * This is a structural check on the adapter's public surface, not an\n * `instanceof` check: a consumer may hold a different copy of this package\n * than the one that constructed the adapter (a split dependency tree), in\n * which case `instanceof` is always `false`. `unwrap` is the distinguishing\n * API — no v1 or v2 keyring exposes it — and it is the method consumers call\n * to retrieve the inner v2 instance.\n *\n * @param value - The value to check.\n * @returns Whether the value is a `KeyringV1Adapter`.\n */\nexport function isKeyringV1Adapter<InnerKeyring extends KeyringV2 = KeyringV2>(\n value: unknown,\n): value is KeyringV1Adapter<InnerKeyring> {\n if (!isObject(value)) {\n return false;\n }\n\n // Property access rather than `hasProperty`: `unwrap` is a prototype\n // method, not an own property, so own-property checks miss it.\n const { type, unwrap } = value as { type?: unknown; unwrap?: unknown };\n\n return typeof type === 'string' && typeof unwrap === 'function';\n}\n"]}
@@ -73,4 +73,19 @@ export declare class KeyringV1Adapter<InnerKeyring extends KeyringV2 = KeyringV2
73
73
  */
74
74
  deserialize(state: Json): Promise<void>;
75
75
  }
76
+ /**
77
+ * Check whether the given value is a {@link KeyringV1Adapter}, including
78
+ * subclasses such as `EthKeyringV1Adapter` or `SnapKeyringV1Adapter`.
79
+ *
80
+ * This is a structural check on the adapter's public surface, not an
81
+ * `instanceof` check: a consumer may hold a different copy of this package
82
+ * than the one that constructed the adapter (a split dependency tree), in
83
+ * which case `instanceof` is always `false`. `unwrap` is the distinguishing
84
+ * API — no v1 or v2 keyring exposes it — and it is the method consumers call
85
+ * to retrieve the inner v2 instance.
86
+ *
87
+ * @param value - The value to check.
88
+ * @returns Whether the value is a `KeyringV1Adapter`.
89
+ */
90
+ export declare function isKeyringV1Adapter<InnerKeyring extends KeyringV2 = KeyringV2>(value: unknown): value is KeyringV1Adapter<InnerKeyring>;
76
91
  //# sourceMappingURL=keyring-v1-adapter.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"keyring-v1-adapter.d.cts","sourceRoot":"","sources":["../../src/v2/keyring-v1-adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,IAAI,SAAS,EAAE,iCAAiC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,gCAAgC;AAC3D,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,gBAAgB,CAC3B,YAAY,SAAS,SAAS,GAAG,SAAS,CAC1C,YAAW,WAAW;IACtB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;gBAE3B,KAAK,EAAE,YAAY;IAK/B;;;;;;;OAOG;IACH,MAAM,IAAI,YAAY;IAItB;;;;;;;OAOG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKtC;;;;;;OAMG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC;;;;;;;OAOG;IACG,WAAW,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAG9C"}
1
+ {"version":3,"file":"keyring-v1-adapter.d.cts","sourceRoot":"","sources":["../../src/v2/keyring-v1-adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,IAAI,SAAS,EAAE,iCAAiC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,gCAAgC;AAE3D,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,gBAAgB,CAC3B,YAAY,SAAS,SAAS,GAAG,SAAS,CAC1C,YAAW,WAAW;IACtB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;gBAE3B,KAAK,EAAE,YAAY;IAK/B;;;;;;;OAOG;IACH,MAAM,IAAI,YAAY;IAItB;;;;;;;OAOG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKtC;;;;;;OAMG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC;;;;;;;OAOG;IACG,WAAW,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAG9C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,SAAS,SAAS,GAAG,SAAS,EAC3E,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,gBAAgB,CAAC,YAAY,CAAC,CAUzC"}
@@ -73,4 +73,19 @@ export declare class KeyringV1Adapter<InnerKeyring extends KeyringV2 = KeyringV2
73
73
  */
74
74
  deserialize(state: Json): Promise<void>;
75
75
  }
76
+ /**
77
+ * Check whether the given value is a {@link KeyringV1Adapter}, including
78
+ * subclasses such as `EthKeyringV1Adapter` or `SnapKeyringV1Adapter`.
79
+ *
80
+ * This is a structural check on the adapter's public surface, not an
81
+ * `instanceof` check: a consumer may hold a different copy of this package
82
+ * than the one that constructed the adapter (a split dependency tree), in
83
+ * which case `instanceof` is always `false`. `unwrap` is the distinguishing
84
+ * API — no v1 or v2 keyring exposes it — and it is the method consumers call
85
+ * to retrieve the inner v2 instance.
86
+ *
87
+ * @param value - The value to check.
88
+ * @returns Whether the value is a `KeyringV1Adapter`.
89
+ */
90
+ export declare function isKeyringV1Adapter<InnerKeyring extends KeyringV2 = KeyringV2>(value: unknown): value is KeyringV1Adapter<InnerKeyring>;
76
91
  //# sourceMappingURL=keyring-v1-adapter.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"keyring-v1-adapter.d.mts","sourceRoot":"","sources":["../../src/v2/keyring-v1-adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,IAAI,SAAS,EAAE,iCAAiC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,gCAAgC;AAC3D,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,gBAAgB,CAC3B,YAAY,SAAS,SAAS,GAAG,SAAS,CAC1C,YAAW,WAAW;IACtB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;gBAE3B,KAAK,EAAE,YAAY;IAK/B;;;;;;;OAOG;IACH,MAAM,IAAI,YAAY;IAItB;;;;;;;OAOG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKtC;;;;;;OAMG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC;;;;;;;OAOG;IACG,WAAW,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAG9C"}
1
+ {"version":3,"file":"keyring-v1-adapter.d.mts","sourceRoot":"","sources":["../../src/v2/keyring-v1-adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,IAAI,SAAS,EAAE,iCAAiC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,gCAAgC;AAE3D,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,gBAAgB,CAC3B,YAAY,SAAS,SAAS,GAAG,SAAS,CAC1C,YAAW,WAAW;IACtB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;gBAE3B,KAAK,EAAE,YAAY;IAK/B;;;;;;;OAOG;IACH,MAAM,IAAI,YAAY;IAItB;;;;;;;OAOG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKtC;;;;;;OAMG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC;;;;;;;OAOG;IACG,WAAW,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAG9C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,SAAS,SAAS,GAAG,SAAS,EAC3E,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,gBAAgB,CAAC,YAAY,CAAC,CAUzC"}