@optimystic/db-p2p-storage-web 0.24.2 → 0.25.1

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 CHANGED
@@ -1,108 +1,110 @@
1
- # @optimystic/db-p2p-storage-web
2
-
3
- IndexedDB-backed storage backend for Optimystic browser peers. Provides:
4
-
5
- - **`IndexedDBRawStorage`** — implements `IRawStorage` so a browser node persists
6
- block metadata, revisions, pending transactions, committed transactions, and
7
- materialized blocks across page reloads.
8
- - **`IndexedDBKVStore`** implements `IKVStore` for the persistent transaction
9
- state used to recover crashed two-phase commits.
10
- - **`loadOrCreateBrowserPeerKey`** generates an Ed25519 libp2p private key on
11
- first run and persists it in the same IndexedDB database, giving the browser
12
- peer a stable, reload-surviving identity.
13
-
14
- This package is browser-only — it imports no Node built-ins. Counterparts:
15
-
16
- - `@optimystic/db-p2p-storage-rn` — React Native (MMKV)
17
- - `@optimystic/db-p2p-storage-fs` — Node filesystem
18
-
19
- ## Install
20
-
21
- ```bash
22
- yarn add @optimystic/db-p2p-storage-web @optimystic/db-p2p @optimystic/db-core
23
- ```
24
-
25
- `@optimystic/db-p2p` is consumed via its `react-native` / `./rn` entry point so
26
- the Node-only filesystem code does not get bundled into the browser:
27
-
28
- ```ts
29
- import { createLibp2pNode } from '@optimystic/db-p2p/rn';
30
- ```
31
-
32
- ## Usage
33
-
34
- ```ts
35
- import { createLibp2pNode } from '@optimystic/db-p2p/rn';
36
- import {
37
- openOptimysticWebDb,
38
- IndexedDBRawStorage,
39
- IndexedDBKVStore,
40
- loadOrCreateBrowserPeerKey,
41
- } from '@optimystic/db-p2p-storage-web';
42
-
43
- const db = await openOptimysticWebDb(); // single shared handle
44
- const rawStorage = new IndexedDBRawStorage(db); // IRawStorage
45
- const kvStore = new IndexedDBKVStore(db); // → IKVStore (txn recovery)
46
- const privateKey = await loadOrCreateBrowserPeerKey(db);
47
-
48
- const libp2p = await createLibp2pNode({
49
- bootstrapNodes: [/* */],
50
- networkName: 'my-network',
51
- privateKey,
52
- });
53
- ```
54
-
55
- The same `IDBPDatabase` handle is shared by all three consumers — IndexedDB
56
- permits concurrent transactions across disjoint object stores, so the storage
57
- layer parallelises naturally.
58
-
59
- ## Persistence semantics
60
-
61
- The package opens a single IndexedDB database (`optimystic` by default) with
62
- six object stores. `IndexedDBRawStorage` is a thin shell over the shared
63
- `KvRawStorage` kernel driven by an `IndexedDBStoreDriver`: the kernel owns all
64
- JSON/UTF-8 serialization, so the five block-storage stores now hold opaque
65
- kernel-encoded `Uint8Array` bytes rather than live objects. The keys and the
66
- logical types the kernel decodes them back into are unchanged:
67
-
68
- | Store | Key | Stored value | Decoded (logical) type |
69
- |----------------|----------------------|--------------|------------------------|
70
- | `metadata` | `blockId` | `Uint8Array` | `BlockMetadata` |
71
- | `revisions` | `[blockId, rev]` | `Uint8Array` | `ActionId` |
72
- | `pending` | `[blockId, actionId]`| `Uint8Array` | `Transform` |
73
- | `transactions` | `[blockId, actionId]`| `Uint8Array` | `Transform` |
74
- | `materialized` | `[blockId, actionId]`| `Uint8Array` | `IBlock` |
75
- | `kv` | `key` | `string` or `Uint8Array` | — (not kernel-backed) |
76
-
77
- `listRevisions` and `listPendingTransactions` use real IndexedDB range cursors
78
- — never `getAllKeys()` + JS filter — so list latency stays bounded as the store
79
- grows. `promotePendingTransaction` runs as a single `readwrite` transaction
80
- spanning `pending` and `transactions`, so the move is atomic across crashes.
81
-
82
- `getApproximateBytesUsed()` returns `(await navigator.storage.estimate()).usage`,
83
- which is **per-origin**, not per-database. That is adequate for `StorageMonitor`
84
- which uses the figure as an advisory ring-selection input — but is not a
85
- precise per-database accounting.
86
-
87
- ## Identity
88
-
89
- `loadOrCreateBrowserPeerKey(db, keyName?)` writes the libp2p private key as
90
- raw protobuf bytes (`Uint8Array`) under `keyName` in the `kv` store
91
- (default `peer-private-key`). IndexedDB stores typed arrays natively, so no
92
- base64 round-trip is needed. To rotate the identity, delete that one key:
93
-
94
- ```ts
95
- await db.delete('kv', 'peer-private-key');
96
- ```
97
-
98
- To wipe the entire backing store (debugging / dev reset):
99
-
100
- ```ts
101
- indexedDB.deleteDatabase('optimystic');
102
- ```
103
-
104
- ## Tests
105
-
106
- `yarn test` runs the spec suite under [`fake-indexeddb`](https://www.npmjs.com/package/fake-indexeddb)
107
- in Node so CI doesn't need a real browser. Production code only uses the
108
- IndexedDB W3C API, so fake-indexeddb is a faithful behavioural surrogate.
1
+ # @optimystic/db-p2p-storage-web
2
+
3
+ IndexedDB-backed storage backend for Optimystic browser peers. Provides:
4
+
5
+ - **`IndexedDBRawStorage`** — implements `IRawStorage` so a browser node persists
6
+ block metadata, revisions, pending transactions, committed transactions,
7
+ commit proofs, and
8
+ materialized blocks across page reloads.
9
+ - **`IndexedDBKVStore`** implements `IKVStore` for the persistent transaction
10
+ state used to recover crashed two-phase commits.
11
+ - **`loadOrCreateBrowserPeerKey`** generates an Ed25519 libp2p private key on
12
+ first run and persists it in the same IndexedDB database, giving the browser
13
+ peer a stable, reload-surviving identity.
14
+
15
+ This package is browser-only — it imports no Node built-ins. Counterparts:
16
+
17
+ - `@optimystic/db-p2p-storage-rn` — React Native (MMKV)
18
+ - `@optimystic/db-p2p-storage-fs` — Node filesystem
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ yarn add @optimystic/db-p2p-storage-web @optimystic/db-p2p @optimystic/db-core
24
+ ```
25
+
26
+ `@optimystic/db-p2p` is consumed via its `react-native` / `./rn` entry point so
27
+ the Node-only filesystem code does not get bundled into the browser:
28
+
29
+ ```ts
30
+ import { createLibp2pNode } from '@optimystic/db-p2p/rn';
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ```ts
36
+ import { createLibp2pNode } from '@optimystic/db-p2p/rn';
37
+ import {
38
+ openOptimysticWebDb,
39
+ IndexedDBRawStorage,
40
+ IndexedDBKVStore,
41
+ loadOrCreateBrowserPeerKey,
42
+ } from '@optimystic/db-p2p-storage-web';
43
+
44
+ const db = await openOptimysticWebDb(); // single shared handle
45
+ const rawStorage = new IndexedDBRawStorage(db); // → IRawStorage
46
+ const kvStore = new IndexedDBKVStore(db); // → IKVStore (txn recovery)
47
+ const privateKey = await loadOrCreateBrowserPeerKey(db);
48
+
49
+ const libp2p = await createLibp2pNode({
50
+ bootstrapNodes: [/* … */],
51
+ networkName: 'my-network',
52
+ privateKey,
53
+ });
54
+ ```
55
+
56
+ The same `IDBPDatabase` handle is shared by all three consumers — IndexedDB
57
+ permits concurrent transactions across disjoint object stores, so the storage
58
+ layer parallelises naturally.
59
+
60
+ ## Persistence semantics
61
+
62
+ The package opens a single IndexedDB database (`optimystic` by default) with
63
+ seven object stores. `IndexedDBRawStorage` is a thin shell over the shared
64
+ `KvRawStorage` kernel driven by an `IndexedDBStoreDriver`: the kernel owns all
65
+ JSON/UTF-8 serialization, so the six block-storage stores now hold opaque
66
+ kernel-encoded `Uint8Array` bytes rather than live objects. The keys and the
67
+ logical types the kernel decodes them back into are unchanged:
68
+
69
+ | Store | Key | Stored value | Decoded (logical) type |
70
+ |----------------|----------------------|--------------|------------------------|
71
+ | `metadata` | `blockId` | `Uint8Array` | `BlockMetadata` |
72
+ | `revisions` | `[blockId, rev]` | `Uint8Array` | `ActionId` |
73
+ | `pending` | `[blockId, actionId]`| `Uint8Array` | `Transform` |
74
+ | `transactions` | `[blockId, actionId]`| `Uint8Array` | `Transform` |
75
+ | `proofs` | `[blockId, rev]` | `Uint8Array` | `BlockCommitProof` |
76
+ | `materialized` | `[blockId, actionId]`| `Uint8Array` | `IBlock` |
77
+ | `kv` | `key` | `string` or `Uint8Array` | (not kernel-backed) |
78
+
79
+ `listRevisions` and `listPendingTransactions` use real IndexedDB range cursors
80
+ never `getAllKeys()` + JS filter — so list latency stays bounded as the store
81
+ grows. `promotePendingTransaction` runs as a single `readwrite` transaction
82
+ spanning `pending` and `transactions`, so the move is atomic across crashes.
83
+
84
+ `getApproximateBytesUsed()` returns `(await navigator.storage.estimate()).usage`,
85
+ which is **per-origin**, not per-database. That is adequate for `StorageMonitor`
86
+ — which uses the figure as an advisory ring-selection input — but is not a
87
+ precise per-database accounting.
88
+
89
+ ## Identity
90
+
91
+ `loadOrCreateBrowserPeerKey(db, keyName?)` writes the libp2p private key as
92
+ raw protobuf bytes (`Uint8Array`) under `keyName` in the `kv` store
93
+ (default `peer-private-key`). IndexedDB stores typed arrays natively, so no
94
+ base64 round-trip is needed. To rotate the identity, delete that one key:
95
+
96
+ ```ts
97
+ await db.delete('kv', 'peer-private-key');
98
+ ```
99
+
100
+ To wipe the entire backing store (debugging / dev reset):
101
+
102
+ ```ts
103
+ indexedDB.deleteDatabase('optimystic');
104
+ ```
105
+
106
+ ## Tests
107
+
108
+ `yarn test` runs the spec suite under [`fake-indexeddb`](https://www.npmjs.com/package/fake-indexeddb)
109
+ in Node so CI doesn't need a real browser. Production code only uses the
110
+ IndexedDB W3C API, so fake-indexeddb is a faithful behavioural surrogate.
package/dist/src/db.d.ts CHANGED
@@ -3,7 +3,7 @@ import type { ActionId, BlockId } from '@optimystic/db-core';
3
3
  /**
4
4
  * IndexedDB schema for the Optimystic browser storage backend.
5
5
  *
6
- * The five block-storage stores keep their original object stores and compound
6
+ * The six block-storage stores keep their original object stores and compound
7
7
  * array keys, but their values are now opaque `Uint8Array` blobs: the shared
8
8
  * `KvRawStorage` kernel owns JSON (de)serialization, so `IndexedDBStoreDriver`
9
9
  * only ever hands IndexedDB kernel-encoded bytes. IndexedDB stores a
@@ -16,6 +16,9 @@ import type { ActionId, BlockId } from '@optimystic/db-core';
16
16
  * - `pending`: pending transform bytes keyed by `[blockId, actionId]`. Listing pending
17
17
  * transactions for a block uses a key cursor over `[blockId, ...]`.
18
18
  * - `transactions`: committed transform bytes keyed by `[blockId, actionId]`.
19
+ * - `proofs`: `BlockCommitProof` bytes keyed by `[blockId, rev]` — the same key shape
20
+ * as `revisions`, deliberately NOT the action keyspace (an action id is caller-chosen,
21
+ * so no reserved id could be relied on).
19
22
  * - `materialized`: materialized block bytes keyed by `[blockId, actionId]`. Deleting
20
23
  * the row is a driver `delete`, not a stored `undefined`.
21
24
  * - `kv`: a generic string keyspace shared by `IndexedDBKVStore` and the
@@ -40,6 +43,10 @@ export interface OptimysticWebDB extends DBSchema {
40
43
  key: [BlockId, ActionId];
41
44
  value: Uint8Array;
42
45
  };
46
+ proofs: {
47
+ key: [BlockId, number];
48
+ value: Uint8Array;
49
+ };
43
50
  materialized: {
44
51
  key: [BlockId, ActionId];
45
52
  value: Uint8Array;
@@ -50,7 +57,7 @@ export interface OptimysticWebDB extends DBSchema {
50
57
  };
51
58
  }
52
59
  export declare const DEFAULT_DB_NAME = "optimystic";
53
- export declare const DEFAULT_DB_VERSION = 1;
60
+ export declare const DEFAULT_DB_VERSION = 2;
54
61
  export type OptimysticWebDBHandle = IDBPDatabase<OptimysticWebDB>;
55
62
  /**
56
63
  * Opens (and creates if necessary) the Optimystic IndexedDB database used by
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,KAAK,CAAC;AAC/D,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,eAAgB,SAAQ,QAAQ;IAChD,QAAQ,EAAE;QACT,GAAG,EAAE,OAAO,CAAC;QACb,KAAK,EAAE,UAAU,CAAC;KAClB,CAAC;IACF,SAAS,EAAE;QACV,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvB,KAAK,EAAE,UAAU,CAAC;KAClB,CAAC;IACF,OAAO,EAAE;QACR,GAAG,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACzB,KAAK,EAAE,UAAU,CAAC;KAClB,CAAC;IACF,YAAY,EAAE;QACb,GAAG,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACzB,KAAK,EAAE,UAAU,CAAC;KAClB,CAAC;IACF,YAAY,EAAE;QACb,GAAG,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACzB,KAAK,EAAE,UAAU,CAAC;KAClB,CAAC;IACF,EAAE,EAAE;QACH,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,GAAG,UAAU,CAAC;KAC3B,CAAC;CACF;AAED,eAAO,MAAM,eAAe,eAAe,CAAC;AAC5C,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,MAAM,MAAM,qBAAqB,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;AAElE;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACxC,IAAI,GAAE,MAAwB,EAC9B,OAAO,GAAE,MAA2B,GAClC,OAAO,CAAC,qBAAqB,CAAC,CAuBhC"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,KAAK,CAAC;AAC/D,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,eAAgB,SAAQ,QAAQ;IAChD,QAAQ,EAAE;QACT,GAAG,EAAE,OAAO,CAAC;QACb,KAAK,EAAE,UAAU,CAAC;KAClB,CAAC;IACF,SAAS,EAAE;QACV,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvB,KAAK,EAAE,UAAU,CAAC;KAClB,CAAC;IACF,OAAO,EAAE;QACR,GAAG,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACzB,KAAK,EAAE,UAAU,CAAC;KAClB,CAAC;IACF,YAAY,EAAE;QACb,GAAG,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACzB,KAAK,EAAE,UAAU,CAAC;KAClB,CAAC;IACF,MAAM,EAAE;QACP,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvB,KAAK,EAAE,UAAU,CAAC;KAClB,CAAC;IACF,YAAY,EAAE;QACb,GAAG,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACzB,KAAK,EAAE,UAAU,CAAC;KAClB,CAAC;IACF,EAAE,EAAE;QACH,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,GAAG,UAAU,CAAC;KAC3B,CAAC;CACF;AAED,eAAO,MAAM,eAAe,eAAe,CAAC;AAG5C,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,MAAM,MAAM,qBAAqB,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;AAElE;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACxC,IAAI,GAAE,MAAwB,EAC9B,OAAO,GAAE,MAA2B,GAClC,OAAO,CAAC,qBAAqB,CAAC,CA0BhC"}
package/dist/src/db.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { openDB } from 'idb';
2
2
  export const DEFAULT_DB_NAME = 'optimystic';
3
- export const DEFAULT_DB_VERSION = 1;
3
+ // Bumped to 2 when the `proofs` object store was added. The `upgrade` hook is guarded
4
+ // by `objectStoreNames.contains`, so an existing v1 database gains only the new store.
5
+ export const DEFAULT_DB_VERSION = 2;
4
6
  /**
5
7
  * Opens (and creates if necessary) the Optimystic IndexedDB database used by
6
8
  * `IndexedDBRawStorage`, `IndexedDBKVStore`, and `loadOrCreateBrowserPeerKey`.
@@ -23,6 +25,9 @@ export async function openOptimysticWebDb(name = DEFAULT_DB_NAME, version = DEFA
23
25
  if (!db.objectStoreNames.contains('transactions')) {
24
26
  db.createObjectStore('transactions');
25
27
  }
28
+ if (!db.objectStoreNames.contains('proofs')) {
29
+ db.createObjectStore('proofs');
30
+ }
26
31
  if (!db.objectStoreNames.contains('materialized')) {
27
32
  db.createObjectStore('materialized');
28
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAoC,MAAM,KAAK,CAAC;AAqD/D,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC;AAC5C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAIpC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACxC,OAAe,eAAe,EAC9B,UAAkB,kBAAkB;IAEpC,OAAO,MAAM,CAAkB,IAAI,EAAE,OAAO,EAAE;QAC7C,OAAO,CAAC,EAAE;YACT,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/C,EAAE,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAClC,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAChD,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACnC,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC9C,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;YACjC,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBACnD,EAAE,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;YACtC,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBACnD,EAAE,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;YACtC,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzC,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;QACF,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAoC,MAAM,KAAK,CAAC;AA4D/D,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC;AAC5C,sFAAsF;AACtF,uFAAuF;AACvF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAIpC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACxC,OAAe,eAAe,EAC9B,UAAkB,kBAAkB;IAEpC,OAAO,MAAM,CAAkB,IAAI,EAAE,OAAO,EAAE;QAC7C,OAAO,CAAC,EAAE;YACT,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/C,EAAE,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAClC,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAChD,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACnC,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC9C,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;YACjC,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBACnD,EAAE,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;YACtC,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC7C,EAAE,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAChC,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBACnD,EAAE,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;YACtC,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzC,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;QACF,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
@@ -1,11 +1,10 @@
1
1
  import type { ActionId, BlockId } from '@optimystic/db-core';
2
- import { KvRawStorage, type RawStoreDriver } from '@optimystic/db-p2p';
2
+ import { KvRawStorage, type RawStoreDriver, type StoreIdentity } from '@optimystic/db-p2p';
3
3
  import type { OptimysticWebDBHandle } from './db.js';
4
4
  /**
5
- * IndexedDB {@link RawStoreDriver}: the five logical block-storage stores mapped
6
- * to the five IndexedDB object stores (`metadata`, `revisions`, `pending`,
7
- * `transactions`, `materialized`) with their original compound array keys. This
8
- * is a code refactor, not a storage-format change at the key level.
5
+ * IndexedDB {@link RawStoreDriver}: the six logical block-storage stores mapped
6
+ * to the six IndexedDB object stores (`metadata`, `revisions`, `pending`,
7
+ * `transactions`, `proofs`, `materialized`) with their compound array keys.
9
8
  *
10
9
  * `KvRawStorage` now owns all JSON serialization, so this driver only ever
11
10
  * reads/writes `Uint8Array` values — IndexedDB stores a typed array natively via
@@ -15,7 +14,9 @@ import type { OptimysticWebDBHandle } from './db.js';
15
14
  */
16
15
  export declare class IndexedDBStoreDriver implements RawStoreDriver {
17
16
  private readonly db;
17
+ private readonly identity;
18
18
  constructor(db: OptimysticWebDBHandle);
19
+ storeIdentity(): StoreIdentity;
19
20
  getMetadata(blockId: BlockId): Promise<Uint8Array | undefined>;
20
21
  putMetadata(blockId: BlockId, value: Uint8Array): Promise<void>;
21
22
  getRevision(blockId: BlockId, rev: number): Promise<Uint8Array | undefined>;
@@ -27,6 +28,8 @@ export declare class IndexedDBStoreDriver implements RawStoreDriver {
27
28
  listPendingActionIds(blockId: BlockId): AsyncIterable<ActionId>;
28
29
  getTransaction(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined>;
29
30
  putTransaction(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void>;
31
+ getProof(blockId: BlockId, rev: number): Promise<Uint8Array | undefined>;
32
+ putProof(blockId: BlockId, rev: number, value: Uint8Array): Promise<void>;
30
33
  getMaterialized(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined>;
31
34
  putMaterialized(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void>;
32
35
  deleteMaterialized(blockId: BlockId, actionId: ActionId): Promise<void>;
@@ -49,6 +52,7 @@ export declare class IndexedDBStoreDriver implements RawStoreDriver {
49
52
  export declare class IndexedDBRawStorage extends KvRawStorage {
50
53
  listBlockIds: () => AsyncIterable<BlockId>;
51
54
  getApproximateBytesUsed: () => Promise<number>;
55
+ getStoreIdentity: () => StoreIdentity;
52
56
  constructor(db: OptimysticWebDBHandle);
53
57
  }
54
58
  //# sourceMappingURL=indexeddb-storage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"indexeddb-storage.d.ts","sourceRoot":"","sources":["../../src/indexeddb-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAKrD;;;;;;;;;;;GAWG;AACH,qBAAa,oBAAqB,YAAW,cAAc;IAC9C,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,qBAAqB;IAIhD,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAI9D,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/D,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAI3E,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3E,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,aAAa,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAsBhH,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAIjF,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlF,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC;IAuBhE,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAIrF,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtF,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAItF,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvF,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB3D,YAAY,IAAI,aAAa,CAAC,OAAO,CAAC;IAWvC,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;CAS7C;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,mBAAoB,SAAQ,YAAY;IAC5C,YAAY,EAAE,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;IAC3C,uBAAuB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;gBAE3C,EAAE,EAAE,qBAAqB;CAGrC"}
1
+ {"version":3,"file":"indexeddb-storage.d.ts","sourceRoot":"","sources":["../../src/indexeddb-storage.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,10 @@
1
- import { KvRawStorage } from '@optimystic/db-p2p';
1
+ import { KvRawStorage, identityForHandle } from '@optimystic/db-p2p';
2
2
  import { createLogger } from './logger.js';
3
3
  const log = createLogger('storage:indexeddb');
4
4
  /**
5
- * IndexedDB {@link RawStoreDriver}: the five logical block-storage stores mapped
6
- * to the five IndexedDB object stores (`metadata`, `revisions`, `pending`,
7
- * `transactions`, `materialized`) with their original compound array keys. This
8
- * is a code refactor, not a storage-format change at the key level.
5
+ * IndexedDB {@link RawStoreDriver}: the six logical block-storage stores mapped
6
+ * to the six IndexedDB object stores (`metadata`, `revisions`, `pending`,
7
+ * `transactions`, `proofs`, `materialized`) with their compound array keys.
9
8
  *
10
9
  * `KvRawStorage` now owns all JSON serialization, so this driver only ever
11
10
  * reads/writes `Uint8Array` values — IndexedDB stores a typed array natively via
@@ -15,8 +14,17 @@ const log = createLogger('storage:indexeddb');
15
14
  */
16
15
  export class IndexedDBStoreDriver {
17
16
  db;
17
+ // NOTE: identity is the HANDLE object, so two handles opened over the same IndexedDB database
18
+ // NAME read as two identities. Resolving that would mean naming the underlying database,
19
+ // which `OptimysticWebDBHandle` does not expose. The package opener (`db.ts`) hands out one
20
+ // handle per database name in practice, so this is the reachable case, not the complete one.
21
+ identity;
18
22
  constructor(db) {
19
23
  this.db = db;
24
+ this.identity = identityForHandle('idb-handle', db);
25
+ }
26
+ storeIdentity() {
27
+ return this.identity;
20
28
  }
21
29
  // --- metadata ---
22
30
  async getMetadata(blockId) {
@@ -88,6 +96,13 @@ export class IndexedDBStoreDriver {
88
96
  async putTransaction(blockId, actionId, value) {
89
97
  await this.db.put('transactions', value, [blockId, actionId]);
90
98
  }
99
+ // --- proofs (keyed [blockId, rev] like revisions; no delete — see RawStoreDriver.getProof) ---
100
+ async getProof(blockId, rev) {
101
+ return this.db.get('proofs', [blockId, rev]);
102
+ }
103
+ async putProof(blockId, rev, value) {
104
+ await this.db.put('proofs', value, [blockId, rev]);
105
+ }
91
106
  // --- materialized ---
92
107
  async getMaterialized(blockId, actionId) {
93
108
  return this.db.get('materialized', [blockId, actionId]);
@@ -1 +1 @@
1
- {"version":3,"file":"indexeddb-storage.js","sourceRoot":"","sources":["../../src/indexeddb-storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"indexeddb-storage.js","sourceRoot":"","sources":["../../src/indexeddb-storage.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optimystic/db-p2p-storage-web",
3
- "version": "0.24.2",
3
+ "version": "0.25.1",
4
4
  "type": "module",
5
5
  "description": "Browser IndexedDB storage backend for @optimystic/db-p2p",
6
6
  "main": "dist/src/index.js",
@@ -54,8 +54,8 @@
54
54
  "typescript": "^5.9.3"
55
55
  },
56
56
  "dependencies": {
57
- "@optimystic/db-core": "^0.24.2",
58
- "@optimystic/db-p2p": "^0.24.2",
57
+ "@optimystic/db-core": "^0.25.1",
58
+ "@optimystic/db-p2p": "^0.25.1",
59
59
  "debug": "^4.4.3",
60
60
  "idb": "^8.0.3"
61
61
  },
package/src/db.ts CHANGED
@@ -1,92 +1,104 @@
1
- import { openDB, type DBSchema, type IDBPDatabase } from 'idb';
2
- import type { ActionId, BlockId } from '@optimystic/db-core';
3
-
4
- /**
5
- * IndexedDB schema for the Optimystic browser storage backend.
6
- *
7
- * The five block-storage stores keep their original object stores and compound
8
- * array keys, but their values are now opaque `Uint8Array` blobs: the shared
9
- * `KvRawStorage` kernel owns JSON (de)serialization, so `IndexedDBStoreDriver`
10
- * only ever hands IndexedDB kernel-encoded bytes. IndexedDB stores a
11
- * `Uint8Array` natively via structured clone and returns a `Uint8Array`, so the
12
- * bytes round-trip without a codec here.
13
- *
14
- * - `metadata`: per-block metadata bytes keyed by `blockId`.
15
- * - `revisions`: revision lookup keyed by `[blockId, rev]` mapping to actionId bytes.
16
- * Range scans use `IDBKeyRange.bound([blockId, startRev], [blockId, endRev])`.
17
- * - `pending`: pending transform bytes keyed by `[blockId, actionId]`. Listing pending
18
- * transactions for a block uses a key cursor over `[blockId, ...]`.
19
- * - `transactions`: committed transform bytes keyed by `[blockId, actionId]`.
20
- * - `materialized`: materialized block bytes keyed by `[blockId, actionId]`. Deleting
21
- * the row is a driver `delete`, not a stored `undefined`.
22
- * - `kv`: a generic string keyspace shared by `IndexedDBKVStore` and the
23
- * identity helper. Identity keys are stored as raw `Uint8Array` blobs (under
24
- * a separate logical store from string-only `IKVStore` data, but the same
25
- * IndexedDB object store IndexedDB stores typed arrays natively).
26
- */
27
- export interface OptimysticWebDB extends DBSchema {
28
- metadata: {
29
- key: BlockId;
30
- value: Uint8Array;
31
- };
32
- revisions: {
33
- key: [BlockId, number];
34
- value: Uint8Array;
35
- };
36
- pending: {
37
- key: [BlockId, ActionId];
38
- value: Uint8Array;
39
- };
40
- transactions: {
41
- key: [BlockId, ActionId];
42
- value: Uint8Array;
43
- };
44
- materialized: {
45
- key: [BlockId, ActionId];
46
- value: Uint8Array;
47
- };
48
- kv: {
49
- key: string;
50
- value: string | Uint8Array;
51
- };
52
- }
53
-
54
- export const DEFAULT_DB_NAME = 'optimystic';
55
- export const DEFAULT_DB_VERSION = 1;
56
-
57
- export type OptimysticWebDBHandle = IDBPDatabase<OptimysticWebDB>;
58
-
59
- /**
60
- * Opens (and creates if necessary) the Optimystic IndexedDB database used by
61
- * `IndexedDBRawStorage`, `IndexedDBKVStore`, and `loadOrCreateBrowserPeerKey`.
62
- *
63
- * The same handle can be safely shared across all three — IndexedDB connections
64
- * support concurrent transactions across disjoint object stores.
65
- */
66
- export async function openOptimysticWebDb(
67
- name: string = DEFAULT_DB_NAME,
68
- version: number = DEFAULT_DB_VERSION,
69
- ): Promise<OptimysticWebDBHandle> {
70
- return openDB<OptimysticWebDB>(name, version, {
71
- upgrade(db) {
72
- if (!db.objectStoreNames.contains('metadata')) {
73
- db.createObjectStore('metadata');
74
- }
75
- if (!db.objectStoreNames.contains('revisions')) {
76
- db.createObjectStore('revisions');
77
- }
78
- if (!db.objectStoreNames.contains('pending')) {
79
- db.createObjectStore('pending');
80
- }
81
- if (!db.objectStoreNames.contains('transactions')) {
82
- db.createObjectStore('transactions');
83
- }
84
- if (!db.objectStoreNames.contains('materialized')) {
85
- db.createObjectStore('materialized');
86
- }
87
- if (!db.objectStoreNames.contains('kv')) {
88
- db.createObjectStore('kv');
89
- }
90
- },
91
- });
92
- }
1
+ import { openDB, type DBSchema, type IDBPDatabase } from 'idb';
2
+ import type { ActionId, BlockId } from '@optimystic/db-core';
3
+
4
+ /**
5
+ * IndexedDB schema for the Optimystic browser storage backend.
6
+ *
7
+ * The six block-storage stores keep their original object stores and compound
8
+ * array keys, but their values are now opaque `Uint8Array` blobs: the shared
9
+ * `KvRawStorage` kernel owns JSON (de)serialization, so `IndexedDBStoreDriver`
10
+ * only ever hands IndexedDB kernel-encoded bytes. IndexedDB stores a
11
+ * `Uint8Array` natively via structured clone and returns a `Uint8Array`, so the
12
+ * bytes round-trip without a codec here.
13
+ *
14
+ * - `metadata`: per-block metadata bytes keyed by `blockId`.
15
+ * - `revisions`: revision lookup keyed by `[blockId, rev]` mapping to actionId bytes.
16
+ * Range scans use `IDBKeyRange.bound([blockId, startRev], [blockId, endRev])`.
17
+ * - `pending`: pending transform bytes keyed by `[blockId, actionId]`. Listing pending
18
+ * transactions for a block uses a key cursor over `[blockId, ...]`.
19
+ * - `transactions`: committed transform bytes keyed by `[blockId, actionId]`.
20
+ * - `proofs`: `BlockCommitProof` bytes keyed by `[blockId, rev]` — the same key shape
21
+ * as `revisions`, deliberately NOT the action keyspace (an action id is caller-chosen,
22
+ * so no reserved id could be relied on).
23
+ * - `materialized`: materialized block bytes keyed by `[blockId, actionId]`. Deleting
24
+ * the row is a driver `delete`, not a stored `undefined`.
25
+ * - `kv`: a generic string keyspace shared by `IndexedDBKVStore` and the
26
+ * identity helper. Identity keys are stored as raw `Uint8Array` blobs (under
27
+ * a separate logical store from string-only `IKVStore` data, but the same
28
+ * IndexedDB object store — IndexedDB stores typed arrays natively).
29
+ */
30
+ export interface OptimysticWebDB extends DBSchema {
31
+ metadata: {
32
+ key: BlockId;
33
+ value: Uint8Array;
34
+ };
35
+ revisions: {
36
+ key: [BlockId, number];
37
+ value: Uint8Array;
38
+ };
39
+ pending: {
40
+ key: [BlockId, ActionId];
41
+ value: Uint8Array;
42
+ };
43
+ transactions: {
44
+ key: [BlockId, ActionId];
45
+ value: Uint8Array;
46
+ };
47
+ proofs: {
48
+ key: [BlockId, number];
49
+ value: Uint8Array;
50
+ };
51
+ materialized: {
52
+ key: [BlockId, ActionId];
53
+ value: Uint8Array;
54
+ };
55
+ kv: {
56
+ key: string;
57
+ value: string | Uint8Array;
58
+ };
59
+ }
60
+
61
+ export const DEFAULT_DB_NAME = 'optimystic';
62
+ // Bumped to 2 when the `proofs` object store was added. The `upgrade` hook is guarded
63
+ // by `objectStoreNames.contains`, so an existing v1 database gains only the new store.
64
+ export const DEFAULT_DB_VERSION = 2;
65
+
66
+ export type OptimysticWebDBHandle = IDBPDatabase<OptimysticWebDB>;
67
+
68
+ /**
69
+ * Opens (and creates if necessary) the Optimystic IndexedDB database used by
70
+ * `IndexedDBRawStorage`, `IndexedDBKVStore`, and `loadOrCreateBrowserPeerKey`.
71
+ *
72
+ * The same handle can be safely shared across all three — IndexedDB connections
73
+ * support concurrent transactions across disjoint object stores.
74
+ */
75
+ export async function openOptimysticWebDb(
76
+ name: string = DEFAULT_DB_NAME,
77
+ version: number = DEFAULT_DB_VERSION,
78
+ ): Promise<OptimysticWebDBHandle> {
79
+ return openDB<OptimysticWebDB>(name, version, {
80
+ upgrade(db) {
81
+ if (!db.objectStoreNames.contains('metadata')) {
82
+ db.createObjectStore('metadata');
83
+ }
84
+ if (!db.objectStoreNames.contains('revisions')) {
85
+ db.createObjectStore('revisions');
86
+ }
87
+ if (!db.objectStoreNames.contains('pending')) {
88
+ db.createObjectStore('pending');
89
+ }
90
+ if (!db.objectStoreNames.contains('transactions')) {
91
+ db.createObjectStore('transactions');
92
+ }
93
+ if (!db.objectStoreNames.contains('proofs')) {
94
+ db.createObjectStore('proofs');
95
+ }
96
+ if (!db.objectStoreNames.contains('materialized')) {
97
+ db.createObjectStore('materialized');
98
+ }
99
+ if (!db.objectStoreNames.contains('kv')) {
100
+ db.createObjectStore('kv');
101
+ }
102
+ },
103
+ });
104
+ }
@@ -1,15 +1,14 @@
1
1
  import type { ActionId, BlockId } from '@optimystic/db-core';
2
- import { KvRawStorage, type RawStoreDriver } from '@optimystic/db-p2p';
2
+ import { KvRawStorage, identityForHandle, type RawStoreDriver, type StoreIdentity } from '@optimystic/db-p2p';
3
3
  import type { OptimysticWebDBHandle } from './db.js';
4
4
  import { createLogger } from './logger.js';
5
5
 
6
6
  const log = createLogger('storage:indexeddb');
7
7
 
8
8
  /**
9
- * IndexedDB {@link RawStoreDriver}: the five logical block-storage stores mapped
10
- * to the five IndexedDB object stores (`metadata`, `revisions`, `pending`,
11
- * `transactions`, `materialized`) with their original compound array keys. This
12
- * is a code refactor, not a storage-format change at the key level.
9
+ * IndexedDB {@link RawStoreDriver}: the six logical block-storage stores mapped
10
+ * to the six IndexedDB object stores (`metadata`, `revisions`, `pending`,
11
+ * `transactions`, `proofs`, `materialized`) with their compound array keys.
13
12
  *
14
13
  * `KvRawStorage` now owns all JSON serialization, so this driver only ever
15
14
  * reads/writes `Uint8Array` values — IndexedDB stores a typed array natively via
@@ -18,7 +17,19 @@ const log = createLogger('storage:indexeddb');
18
17
  * yielding), and the single `readwrite` transaction that makes `promote` atomic.
19
18
  */
20
19
  export class IndexedDBStoreDriver implements RawStoreDriver {
21
- constructor(private readonly db: OptimysticWebDBHandle) {}
20
+ // NOTE: identity is the HANDLE object, so two handles opened over the same IndexedDB database
21
+ // NAME read as two identities. Resolving that would mean naming the underlying database,
22
+ // which `OptimysticWebDBHandle` does not expose. The package opener (`db.ts`) hands out one
23
+ // handle per database name in practice, so this is the reachable case, not the complete one.
24
+ private readonly identity: StoreIdentity;
25
+
26
+ constructor(private readonly db: OptimysticWebDBHandle) {
27
+ this.identity = identityForHandle('idb-handle', db);
28
+ }
29
+
30
+ storeIdentity(): StoreIdentity {
31
+ return this.identity;
32
+ }
22
33
 
23
34
  // --- metadata ---
24
35
 
@@ -105,6 +116,16 @@ export class IndexedDBStoreDriver implements RawStoreDriver {
105
116
  await this.db.put('transactions', value, [blockId, actionId]);
106
117
  }
107
118
 
119
+ // --- proofs (keyed [blockId, rev] like revisions; no delete — see RawStoreDriver.getProof) ---
120
+
121
+ async getProof(blockId: BlockId, rev: number): Promise<Uint8Array | undefined> {
122
+ return this.db.get('proofs', [blockId, rev]);
123
+ }
124
+
125
+ async putProof(blockId: BlockId, rev: number, value: Uint8Array): Promise<void> {
126
+ await this.db.put('proofs', value, [blockId, rev]);
127
+ }
128
+
108
129
  // --- materialized ---
109
130
 
110
131
  async getMaterialized(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined> {
@@ -181,6 +202,7 @@ export class IndexedDBStoreDriver implements RawStoreDriver {
181
202
  export class IndexedDBRawStorage extends KvRawStorage {
182
203
  declare listBlockIds: () => AsyncIterable<BlockId>;
183
204
  declare getApproximateBytesUsed: () => Promise<number>;
205
+ declare getStoreIdentity: () => StoreIdentity;
184
206
 
185
207
  constructor(db: OptimysticWebDBHandle) {
186
208
  super(new IndexedDBStoreDriver(db));