@orbinum/sdk 2.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -259,30 +259,27 @@ same `selfEphCounter` derive the same ephemeral index and publish the same
259
259
  ephemeral point, which publicly links the two notes. That is a privacy leak, not
260
260
  a lost update.
261
261
 
262
- ### Moving notes between clients
262
+ ### Backing notes up
263
263
 
264
- `orbinum://notes/v1/` is the format for handing notes from one Orbinum client to
265
- another desktop to mobile, as scannable pages. Both halves ship here so the
266
- encoder and decoder cannot drift apart:
264
+ A backup is **JSON**, and it is closed: each entry carries the note's
265
+ commitment and its encrypted memo, never a spending key. Ownership is proved on
266
+ import by decrypting the memo, so a backup file that leaks reveals nothing an
267
+ observer could not already read off the chain.
267
268
 
268
269
  ```ts
269
- import {
270
- encodeNoteTransferPages,
271
- decodeNoteTransferPage,
272
- assembleNoteTransfer,
273
- } from '@orbinum/sdk';
270
+ import { encodeNoteBackup, decodeNoteBackup, importNotesFromBackup } from '@orbinum/sdk';
274
271
 
275
- const pages = encodeNoteTransferPages(notes); // render each as a QR
276
- const entries = assembleNoteTransfer(scanned.map(decodeNoteTransferPage));
272
+ const file = JSON.stringify(encodeNoteBackup(notes));
273
+ const mine = importNotesFromBackup(decodeNoteBackup(file), {
274
+ viewingSecretKey,
275
+ spendingKey,
276
+ ownerPk,
277
+ });
277
278
  ```
278
279
 
279
- `assembleNoteTransfer` refuses an incomplete or mixed batch rather than importing
280
- what it has a partial import looks like a successful one, and the user would
281
- never learn which notes never arrived.
282
-
283
- The payload carries **spending keys**: anyone who scans these codes can spend the
284
- notes. It is for an in-person transfer between two devices the same person owns,
285
- and a host must say so before showing one.
280
+ `importNotesFromBackup` silently skips entries that do not decrypt they belong
281
+ to someone else. A malformed entry is rejected by `decodeNoteBackup` before that,
282
+ so a hand-edited file cannot plant a note with a broken commitment.
286
283
 
287
284
  ### Porting to another platform
288
285
 
@@ -1,4 +1,4 @@
1
- import { V as VaultStorage, a as VaultConfigRecord, E as EncryptedNoteRecord, b as EncryptedTxRecord, C as CachedNullifier, N as NullifierSyncMeta, S as SpendDetails, D as DeviceKeyStore, c as SecretStore } from '../../secretStore-CF6Nse__.mjs';
1
+ import { V as VaultStorage, a as VaultConfigRecord, E as EncryptedNoteRecord, b as EncryptedTxRecord, C as CachedNullifier, N as NullifierSyncMeta, S as SpendDetails, D as DeviceKeyStore, c as SecretStore } from '../../secretStore-CCYo4hna.mjs';
2
2
 
3
3
  /**
4
4
  * `VaultStorage` over IndexedDB — the browser's copy of a wallet's notes.
@@ -112,9 +112,9 @@ declare class IndexedDbVaultStorage implements VaultStorage {
112
112
  * A `DeviceKeyStore` backed by a tiny dedicated IndexedDB.
113
113
  *
114
114
  * IndexedDB rather than localStorage because it stores a `CryptoKey` HANDLE via
115
- * structured clone. The key is generated non-extractable, so its material never
116
- * becomes visible to JavaScript — a storage dump yields an opaque handle, not
117
- * bytes. localStorage can only hold strings, which would mean exporting the key.
115
+ * structured clone, so the material never becomes visible to JavaScript and a
116
+ * storage dump yields an opaque handle. localStorage holds only strings, which
117
+ * would mean exporting the key to store it at all.
118
118
  *
119
119
  * Its own database, separate from the vault: the device key outlives any single
120
120
  * vault and must survive one being dropped.
@@ -136,16 +136,16 @@ declare const getOrCreateIndexedDbDeviceKey: () => Promise<CryptoKey>;
136
136
  * No IndexedDB involved — it ships from this entry point because a consumer
137
137
  * reaching for browser persistence wants both adapters together, and splitting
138
138
  * them across two subpaths would buy nothing.
139
+ *
140
+ * Values arrive already encrypted; see `sessionCache`.
139
141
  */
140
142
 
141
143
  /**
142
- * A `SecretStore` over Web Storage.
143
- *
144
- * Reads fall back to `sessionStorage` so a value written by an older build, or
145
- * by a deliberately session-scoped flow, is still found. Writes always go to the
146
- * durable store and clear the session copy, so one key never lives in both.
144
+ * Durable by default, with `sessionStorage` as a READ fallback so a value left
145
+ * by an older build or a session-scoped flow is still found.
147
146
  *
148
- * Values are encrypted before they arrive here see `sessionCache`.
147
+ * Every write goes to the durable area and drops the session copy, so one key
148
+ * never lives in both and a stale session value cannot shadow a fresh one.
149
149
  */
150
150
  declare function createWebStorageSecretStore(storage?: Storage, sessionStorageArea?: Storage | null): SecretStore;
151
151
 
@@ -1,4 +1,4 @@
1
- import { V as VaultStorage, a as VaultConfigRecord, E as EncryptedNoteRecord, b as EncryptedTxRecord, C as CachedNullifier, N as NullifierSyncMeta, S as SpendDetails, D as DeviceKeyStore, c as SecretStore } from '../../secretStore-CF6Nse__.js';
1
+ import { V as VaultStorage, a as VaultConfigRecord, E as EncryptedNoteRecord, b as EncryptedTxRecord, C as CachedNullifier, N as NullifierSyncMeta, S as SpendDetails, D as DeviceKeyStore, c as SecretStore } from '../../secretStore-CCYo4hna.js';
2
2
 
3
3
  /**
4
4
  * `VaultStorage` over IndexedDB — the browser's copy of a wallet's notes.
@@ -112,9 +112,9 @@ declare class IndexedDbVaultStorage implements VaultStorage {
112
112
  * A `DeviceKeyStore` backed by a tiny dedicated IndexedDB.
113
113
  *
114
114
  * IndexedDB rather than localStorage because it stores a `CryptoKey` HANDLE via
115
- * structured clone. The key is generated non-extractable, so its material never
116
- * becomes visible to JavaScript — a storage dump yields an opaque handle, not
117
- * bytes. localStorage can only hold strings, which would mean exporting the key.
115
+ * structured clone, so the material never becomes visible to JavaScript and a
116
+ * storage dump yields an opaque handle. localStorage holds only strings, which
117
+ * would mean exporting the key to store it at all.
118
118
  *
119
119
  * Its own database, separate from the vault: the device key outlives any single
120
120
  * vault and must survive one being dropped.
@@ -136,16 +136,16 @@ declare const getOrCreateIndexedDbDeviceKey: () => Promise<CryptoKey>;
136
136
  * No IndexedDB involved — it ships from this entry point because a consumer
137
137
  * reaching for browser persistence wants both adapters together, and splitting
138
138
  * them across two subpaths would buy nothing.
139
+ *
140
+ * Values arrive already encrypted; see `sessionCache`.
139
141
  */
140
142
 
141
143
  /**
142
- * A `SecretStore` over Web Storage.
143
- *
144
- * Reads fall back to `sessionStorage` so a value written by an older build, or
145
- * by a deliberately session-scoped flow, is still found. Writes always go to the
146
- * durable store and clear the session copy, so one key never lives in both.
144
+ * Durable by default, with `sessionStorage` as a READ fallback so a value left
145
+ * by an older build or a session-scoped flow is still found.
147
146
  *
148
- * Values are encrypted before they arrive here see `sessionCache`.
147
+ * Every write goes to the durable area and drops the session copy, so one key
148
+ * never lives in both and a stale session value cannot shadow a fresh one.
149
149
  */
150
150
  declare function createWebStorageSecretStore(storage?: Storage, sessionStorageArea?: Storage | null): SecretStore;
151
151