@dstorage-tech/dstorage-sdk 0.0.4

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.
Files changed (106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +530 -0
  3. package/dist/KeypairEncryptionAdapter-AE75YC4W-AOWNSH2M.mjs +9 -0
  4. package/dist/KeypairEncryptionAdapter-AE75YC4W-BAVHRNNJ.mjs +1 -0
  5. package/dist/KeypairEncryptionAdapter-AE75YC4W-BEYO4RUO.mjs +1 -0
  6. package/dist/KeypairEncryptionAdapter-AE75YC4W-VAOH6AAL.mjs +9 -0
  7. package/dist/KeypairEncryptionAdapter-XUKCLRFU-6ERIZN2M.mjs +1 -0
  8. package/dist/KeypairEncryptionAdapter-XUKCLRFU-AYDAZ2TZ.mjs +9 -0
  9. package/dist/KeypairEncryptionAdapter-XUKCLRFU-ERPYK5S4.mjs +8 -0
  10. package/dist/MnemonicEncryptionAdapter-J6IE5OKA-6DFVUVD6.mjs +1 -0
  11. package/dist/MnemonicEncryptionAdapter-J6IE5OKA-O5AJPX42.mjs +1 -0
  12. package/dist/MnemonicEncryptionAdapter-J6IE5OKA-SI6TBLTQ.mjs +9 -0
  13. package/dist/MnemonicEncryptionAdapter-J6IE5OKA-WEPFOTSJ.mjs +9 -0
  14. package/dist/MnemonicEncryptionAdapter-RCHUETBP-DZPBGQG6.mjs +8 -0
  15. package/dist/MnemonicEncryptionAdapter-RCHUETBP-ELAMJMMO.mjs +1 -0
  16. package/dist/MnemonicEncryptionAdapter-RCHUETBP-M7NHGSHO.mjs +9 -0
  17. package/dist/PasswordEncryptionAdapter-CWOXUGR4-2YZ64B4A.mjs +1 -0
  18. package/dist/PasswordEncryptionAdapter-CWOXUGR4-DCEGC2NX.mjs +1 -0
  19. package/dist/PasswordEncryptionAdapter-CWOXUGR4-QEGGYPFJ.mjs +13 -0
  20. package/dist/PasswordEncryptionAdapter-CWOXUGR4-ZYUBUYUI.mjs +13 -0
  21. package/dist/PasswordEncryptionAdapter-ECHND672-3DEFO6FP.mjs +13 -0
  22. package/dist/PasswordEncryptionAdapter-ECHND672-MUTHAMZY.mjs +12 -0
  23. package/dist/PasswordEncryptionAdapter-ECHND672-XVBPHPPT.mjs +1 -0
  24. package/dist/browser.d.mts +2418 -0
  25. package/dist/browser.mjs +5175 -0
  26. package/dist/chunk-25I6ZXUC.mjs +9403 -0
  27. package/dist/chunk-4X5K43JF.mjs +62 -0
  28. package/dist/chunk-4YMF57VY.mjs +1 -0
  29. package/dist/chunk-5MZ7FPPY.mjs +1 -0
  30. package/dist/chunk-5P4EW2YL.mjs +1 -0
  31. package/dist/chunk-5QOKJEH3.mjs +8 -0
  32. package/dist/chunk-5RW7SGA7.mjs +1 -0
  33. package/dist/chunk-62RSKZ6T.mjs +118 -0
  34. package/dist/chunk-6IAQVMSM.mjs +102 -0
  35. package/dist/chunk-BBJCQFWP.mjs +275 -0
  36. package/dist/chunk-BWLEAAFW.mjs +2599 -0
  37. package/dist/chunk-EYF3263P.mjs +2049 -0
  38. package/dist/chunk-FJ7LSZOW.mjs +5537 -0
  39. package/dist/chunk-GUYENY5N.mjs +1 -0
  40. package/dist/chunk-HDD6SUU4.mjs +276 -0
  41. package/dist/chunk-JMPRZK5D.mjs +62 -0
  42. package/dist/chunk-L5QD6GHB.mjs +101 -0
  43. package/dist/chunk-O37NHERH.mjs +17 -0
  44. package/dist/chunk-OLGVVM5Y.mjs +102 -0
  45. package/dist/chunk-PKHRAYFD.mjs +1 -0
  46. package/dist/chunk-PLAOCKSS.mjs +101 -0
  47. package/dist/chunk-QKA2DCR6.mjs +118 -0
  48. package/dist/chunk-RPSRFFXN.mjs +275 -0
  49. package/dist/chunk-TESUOXRJ.mjs +1 -0
  50. package/dist/chunk-TMLXCRJU.mjs +1 -0
  51. package/dist/chunk-TNRKN4LB.mjs +1 -0
  52. package/dist/chunk-TSZ37JDY.mjs +2596 -0
  53. package/dist/chunk-U3MS6KMF.mjs +1 -0
  54. package/dist/chunk-UBALMYIY.mjs +2049 -0
  55. package/dist/chunk-UDYXMII2.mjs +121 -0
  56. package/dist/chunk-UJCSKKID.mjs +30 -0
  57. package/dist/chunk-UOOF4V2Y.mjs +1 -0
  58. package/dist/chunk-VDZ7F7MP.mjs +1329 -0
  59. package/dist/chunk-X4LEBNK6.mjs +276 -0
  60. package/dist/chunk-Z2TH6U4C.mjs +3 -0
  61. package/dist/chunk-Z6DUAI5B.mjs +121 -0
  62. package/dist/chunk-ZEPZ4QDD.mjs +1 -0
  63. package/dist/chunk-ZGUY5EIR.mjs +1 -0
  64. package/dist/cjs-RMZ3L2IO.mjs +5 -0
  65. package/dist/contract-api-AO4RGPLT-4HRCMSCE.mjs +279 -0
  66. package/dist/contract-api-AO4RGPLT-ADH6ZDKC.mjs +279 -0
  67. package/dist/contract-api-AO4RGPLT-ENC72WCG.mjs +280 -0
  68. package/dist/contract-api-AO4RGPLT-PAMIPEI3.mjs +1 -0
  69. package/dist/contract-api-AO4RGPLT-W3RSVP5A.mjs +1 -0
  70. package/dist/contract-api-AO4RGPLT-WENYDV6I.mjs +1 -0
  71. package/dist/contract-api-TJ7JPHZA-6FUBJ6DS.mjs +279 -0
  72. package/dist/contract-api-TJ7JPHZA-ZWP3EH7D.mjs +279 -0
  73. package/dist/contracts/dataregistry/managed/keys/removeReference.prover +0 -0
  74. package/dist/contracts/dataregistry/managed/keys/removeReference.verifier +0 -0
  75. package/dist/contracts/dataregistry/managed/keys/storeReference.prover +0 -0
  76. package/dist/contracts/dataregistry/managed/keys/storeReference.verifier +0 -0
  77. package/dist/contracts/dataregistry/managed/keys/updateReference.prover +0 -0
  78. package/dist/contracts/dataregistry/managed/keys/updateReference.verifier +0 -0
  79. package/dist/contracts/dataregistry/managed/zkir/removeReference.bzkir +0 -0
  80. package/dist/contracts/dataregistry/managed/zkir/removeReference.zkir +138 -0
  81. package/dist/contracts/dataregistry/managed/zkir/storeReference.bzkir +0 -0
  82. package/dist/contracts/dataregistry/managed/zkir/storeReference.zkir +158 -0
  83. package/dist/contracts/dataregistry/managed/zkir/updateReference.bzkir +0 -0
  84. package/dist/contracts/dataregistry/managed/zkir/updateReference.zkir +190 -0
  85. package/dist/dataregistry-simulator-E6RTGGWT-5YEGBW7P.mjs +108 -0
  86. package/dist/dataregistry-simulator-E6RTGGWT-DJS4MHBD.mjs +109 -0
  87. package/dist/dataregistry-simulator-E6RTGGWT-QGCYR3VF.mjs +1 -0
  88. package/dist/dist-655VYUPJ.mjs +1 -0
  89. package/dist/dist-INTAFXQ7.mjs +65 -0
  90. package/dist/dist-MEZZWKP4.mjs +1 -0
  91. package/dist/dist-MOLWJ4Y7.mjs +64 -0
  92. package/dist/dist-UD4WRMYJ.mjs +65 -0
  93. package/dist/errors.d.mts +117 -0
  94. package/dist/errors.d.ts +117 -0
  95. package/dist/errors.js +2308 -0
  96. package/dist/errors.mjs +2278 -0
  97. package/dist/esm5-AGBDHMNS.mjs +1 -0
  98. package/dist/esm5-GFOBLUFI.mjs +350 -0
  99. package/dist/in-memory-private-state-NGOP37V7-DXWZE42Q.mjs +48 -0
  100. package/dist/in-memory-private-state-NGOP37V7-QXT3RUEH.mjs +49 -0
  101. package/dist/in-memory-private-state-NGOP37V7-XFJFNFCQ.mjs +1 -0
  102. package/dist/index.d.mts +2843 -0
  103. package/dist/index.d.ts +2843 -0
  104. package/dist/index.js +19639 -0
  105. package/dist/index.mjs +5177 -0
  106. package/package.json +87 -0
@@ -0,0 +1,2418 @@
1
+ import { PaymentAdapter, PaymentNetworkName, TokenSymbol, NetworkType, PaymentAdapterLogger, PaymentQuote, PaymentInstruction, PaymentReceipt, MidnightWalletProvider, StorageAdapterLogger, StorageAdapter, StorageProviderName, StorageUploadResult, StorageQuote, ChainAdapter, ChainProviderName, DataReferenceSummary } from './types.js';
2
+ export { MidnightWalletProvider, NetworkType, PaymentAdapter, PaymentAdapterLogger, PaymentNetworkName, PaymentQuote, PaymentReceipt, StorageAdapter, StorageAdapterLogger, StorageProviderName, StorageQuote, StorageUploadResult, TOKENS, Token, TokenSymbol } from './types.js';
3
+ import Arweave from 'arweave';
4
+ import Transaction from 'arweave/node/lib/transaction';
5
+ import { JWKInterface } from 'arweave/node/lib/wallet';
6
+ export * from '@dstorage/chain/browser';
7
+ export { ChainErrorCode } from '@dstorage/chain/browser';
8
+ export { MockPaymentAdapter, MockStorageAdapter, MockStorageAdapterConfig } from './adapters/mock.js';
9
+ export { StorageErrorCode } from './errors.js';
10
+
11
+ /**
12
+ * @dstorage/payment — adapters/arweave.ts
13
+ *
14
+ * Arweave payment adapter.
15
+ *
16
+ * ── Sign-then-post flow ───────────────────────────────────────────────────────
17
+ *
18
+ * On Arweave, data and fee share a single transaction object. The fee is
19
+ * deducted automatically when the transaction is posted — there is no
20
+ * separate payment channel.
21
+ *
22
+ * This adapter implements the two-phase flow supported by MetaTransaction:
23
+ *
24
+ * 1. provideUploadData(data, metadata)
25
+ * Called after encryption. Stores the data + metadata tags so that
26
+ * pay() can build the complete transaction without a separate round-trip.
27
+ *
28
+ * 2. pay(instruction, onStatus) [payment_storage step]
29
+ * Creates the Arweave transaction, attaches tags, and prompts the
30
+ * wallet for approval (ArConnect popup / JWK signing). Stores the
31
+ * signed transaction for the upload step to pick up.
32
+ *
33
+ * 3. ArweaveStorageAdapter.store() [store step]
34
+ * Detects the pre-signed transaction via consumeSignedTx() and simply
35
+ * posts it — no additional signing or wallet interaction needed.
36
+ *
37
+ * If provideUploadData() was not called (e.g. direct use outside MetaTransaction),
38
+ * pay() falls back to the pass-through behaviour and store() performs the full
39
+ * create → sign → post flow as before.
40
+ *
41
+ * Docs: https://docs.arweave.org/developers
42
+ */
43
+
44
+ type ArweaveWallet = JWKInterface | "use_wallet";
45
+ interface ArweavePaymentAdapterConfig {
46
+ /**
47
+ * Arweave gateway.
48
+ * Defaults to mainnet (arweave.net).
49
+ * Use { host: 'arweave.dev', port: 443, protocol: 'https' } for testnet.
50
+ * Use { host: 'localhost', port: 1984, protocol: 'http' } for arlocal.
51
+ *
52
+ * Security: always use `protocol: 'https'` (the default) in production.
53
+ * The SDK relies on standard OS/runtime TLS — no DNS or certificate pinning
54
+ * is applied. Users in adversarial network environments should enforce
55
+ * certificate pinning at the runtime level (e.g. a custom Node.js HTTPS
56
+ * agent or a trusted corporate proxy).
57
+ */
58
+ gateway?: {
59
+ host: string;
60
+ port: number;
61
+ protocol: "http" | "https";
62
+ };
63
+ /**
64
+ * JWK wallet key for Node.js server-side usage.
65
+ * In the browser leave undefined — ArConnect is used automatically.
66
+ */
67
+ walletKey?: Record<string, string>;
68
+ /**
69
+ * How long in ms before a quote expires.
70
+ * Defaults to 120_000 (2 minutes) — appropriate for Arweave's volatile pricing.
71
+ */
72
+ quoteValidityMs?: number;
73
+ /**
74
+ * Optional logger for SDK operational output.
75
+ */
76
+ logger?: PaymentAdapterLogger;
77
+ }
78
+ /** Internal state stored between provideUploadData() and pay(). */
79
+ interface PendingUpload {
80
+ data: Uint8Array;
81
+ metadata: Record<string, string>;
82
+ }
83
+ /** Result stored after pay() signs the transaction, consumed by store(). */
84
+ interface SignedArweaveUpload {
85
+ tx: Transaction;
86
+ /** AR cost string (e.g. "0.000001234") for the upload result. */
87
+ arCost: string;
88
+ }
89
+ declare class ArweavePaymentAdapter implements PaymentAdapter {
90
+ readonly network: PaymentNetworkName;
91
+ readonly token: TokenSymbol;
92
+ readonly type: NetworkType;
93
+ protected arweaveClient: Arweave | null;
94
+ protected readonly gateway: ArweavePaymentAdapterConfig["gateway"];
95
+ private readonly walletKey;
96
+ protected readonly quoteValidityMs: number;
97
+ protected readonly logger: PaymentAdapterLogger | undefined;
98
+ protected pendingUpload: PendingUpload | null;
99
+ protected signedUpload: SignedArweaveUpload | null;
100
+ constructor(config?: ArweavePaymentAdapterConfig);
101
+ protected getClient(): Promise<Arweave>;
102
+ protected resolveWallet(): ArweaveWallet;
103
+ /**
104
+ * Store the encrypted upload payload and metadata tags so that pay() can
105
+ * build and sign the complete Arweave transaction in one step.
106
+ * Called by MetaTransaction after the encrypt step, before pay().
107
+ */
108
+ provideUploadData(data: Uint8Array, metadata?: Record<string, string>): void;
109
+ /**
110
+ * Query the Arweave fee oracle for the real upload cost.
111
+ */
112
+ estimateCost(dataSizeBytes: number): Promise<PaymentQuote>;
113
+ /**
114
+ * Sign-then-store flow (when provideUploadData was called):
115
+ * Creates the Arweave transaction with data + tags, prompts the wallet
116
+ * for approval (ArConnect popup or JWK signing), and stores the signed
117
+ * transaction for ArweaveStorageAdapter.store() to post.
118
+ *
119
+ * Pass-through fallback (when provideUploadData was NOT called):
120
+ * Returns a receipt acknowledging that payment is bundled with the upload.
121
+ * ArweaveStorageAdapter.store() performs the full create → sign → post flow.
122
+ */
123
+ pay(instruction: PaymentInstruction, onStatus?: (message: string) => void): Promise<PaymentReceipt>;
124
+ /**
125
+ * Returns the pre-signed transaction produced by pay(), then clears it.
126
+ * Called by ArweaveStorageAdapter.store() to post the already-signed tx.
127
+ * Returns null if pay() did not sign a transaction (pass-through mode).
128
+ */
129
+ consumeSignedUpload(): SignedArweaveUpload | null;
130
+ }
131
+
132
+ /**
133
+ * @dstorage/payment — adapters/managed.ts
134
+ *
135
+ * Managed payment adapter — remote payment via dStorage API services.
136
+ *
137
+ * Routes payment to the correct network-specific flow based on
138
+ * PaymentQuote.network. All networks share the same endpoint:
139
+ * POST {baseUrl}{POST_SIGN_TX_API_PATH}
140
+ * Currently implemented:
141
+ * - "arweave": remote Arweave signing via REST API
142
+ * - "arweave_bundler": remote ANS-104 bundled-upload signing via REST API
143
+ * - "midnight": remote Midnight transaction balancing/signing via REST API
144
+ *
145
+ * ── Arweave flow ──────────────────────────────────────────────────────────────
146
+ *
147
+ * Instead of signing the Arweave transaction locally (ArConnect or JWK),
148
+ * this adapter constructs the Arweave transaction, computes the Merkle tree
149
+ * (data_root) locally, then sends a stripped transaction JSON — containing
150
+ * only metadata, data_root, and data_size but NOT the raw file bytes — to a
151
+ * remote REST API. The server holds a funded Arweave account, signs the
152
+ * stripped transaction, and returns the signature and id. The file content
153
+ * never leaves the client.
154
+ *
155
+ * POST {baseUrl}{POST_SIGN_TX_API_PATH}
156
+ * → { txData: object, network: string, userId: string }
157
+ * txData — Arweave transaction JSON with data stripped (tx.toJSON()
158
+ * after clearing tx.data; data_root + data_size preserved).
159
+ * network — Arweave network identifier (e.g. "arweave", "arlocal").
160
+ * userId — caller identity forwarded to the server.
161
+ * ← { txId: string, signature: string, publicKey: string, txAmount: string, ... }
162
+ * txId — valid 43-char base64url Arweave transaction id.
163
+ * signature — base64url RSA-PSS signature.
164
+ * publicKey — server wallet's RSA modulus n (base64url).
165
+ * The adapter calls tx.setSignature({ id, signature, owner }).
166
+ *
167
+ * ── Integration (Arweave) ─────────────────────────────────────────────────────
168
+ *
169
+ * ManagedPaymentAdapter extends ArweavePaymentAdapter and slots into the
170
+ * same sign-then-post flow used by ArweaveStorageAdapter:
171
+ *
172
+ * MetaTransaction:
173
+ * provideUploadData(data, metadata) ← stores data + tags
174
+ * pay(instruction, onStatus) ← routes by instruction.network, creates tx,
175
+ * sends JSON to server, applies signature
176
+ *
177
+ * ArweaveStorageAdapter.store():
178
+ * consumeSignedUpload() ← picks up the pre-signed tx
179
+ * postWithRetry(arweave, tx) ← broadcasts to Arweave network
180
+ */
181
+
182
+ interface ManagedPaymentAdapterConfig extends Omit<ArweavePaymentAdapterConfig, "walletKey"> {
183
+ /** Which network this adapter is used for */
184
+ network: PaymentNetworkName;
185
+ /** Whether this covers a storage network fee or a chain transaction fee */
186
+ type: NetworkType;
187
+ /**
188
+ * Base URL of the remote signing server (no trailing slash).
189
+ * Example: "https://api.my-server.com"
190
+ */
191
+ signingServerUrl: string;
192
+ /**
193
+ * Bearer token sent as the `Authorization` header to authenticate with the signing server.
194
+ * Must be a non-empty, non-whitespace string — the constructor throws immediately on
195
+ * an empty value so a misconfigured caller (e.g. unresolved env var) fails fast
196
+ * rather than silently sending unauthenticated requests to the signing service.
197
+ */
198
+ authToken: string;
199
+ /**
200
+ * Maximum time in milliseconds to wait for the signing server to respond before
201
+ * aborting the request and throwing. Defaults to 30 000 ms (30 s).
202
+ * Pass `0` to disable the timeout entirely (not recommended for production).
203
+ */
204
+ requestTimeoutMs?: number;
205
+ }
206
+ declare class ManagedPaymentAdapter extends ArweavePaymentAdapter {
207
+ readonly network: PaymentNetworkName;
208
+ readonly type: NetworkType;
209
+ private readonly signingServerUrl;
210
+ private readonly authToken;
211
+ private readonly requestTimeoutMs;
212
+ private readonly ownerPublicKey;
213
+ /**
214
+ * Strip a RSA-4096 modulus suffix from a compound auth token
215
+ * (<credential>.<base64url_683_chars>), returning only the credential.
216
+ * A plain token (no '.' or wrong suffix length) is returned unchanged.
217
+ * This lets ArweaveBundlerStorageAdapter compound tokens be passed directly
218
+ * to any adapter that uses ManagedPaymentAdapter without breaking authentication.
219
+ *
220
+ * lastIndexOf is intentional: the credential part may itself contain dots
221
+ * (e.g. a JWT), so we always split at the *last* dot to reach the modulus.
222
+ */
223
+ private static _parseAuthToken;
224
+ constructor(config: ManagedPaymentAdapterConfig);
225
+ /**
226
+ * Query the Arweave fee oracle for the real upload cost.
227
+ */
228
+ estimateCost(dataSizeBytes: number): Promise<PaymentQuote>;
229
+ /**
230
+ * Routes payment to the correct network-specific handler based on quote.network.
231
+ *
232
+ * The Arweave path falls back to the base-class pass-through if
233
+ * provideUploadData() was not called. An unrecognised network throws.
234
+ */
235
+ pay(instruction: PaymentInstruction, onStatus?: (message: string) => void): Promise<PaymentReceipt>;
236
+ /**
237
+ * Returns a WalletProvider-compatible object for the Midnight chain whose
238
+ * `balanceTx()` is fulfilled by the managed signing server instead of a
239
+ * local wallet. The caller supplies the public keys (from whichever source
240
+ * they have — HD derivation, a server endpoint, etc.); the SDK only handles
241
+ * the signing-server round-trip.
242
+ *
243
+ * The returned object satisfies the @midnight-ntwrk/midnight-js-types
244
+ * WalletProvider interface via structural typing — no Midnight package
245
+ * import is required from the caller's side.
246
+ *
247
+ * @param coinPublicKey Midnight coin public key (hex) for the ZK fee circuit.
248
+ * @param encryptionPublicKey Midnight encryption public key (hex).
249
+ * @param onReceipt Optional callback invoked with the PaymentReceipt
250
+ * after each successful balanceTx call. Used internally
251
+ * by MidnightChainAdapter to capture receipt metadata;
252
+ * external callers can omit it.
253
+ */
254
+ createMidnightWalletProvider(coinPublicKey: string, encryptionPublicKey: string, onReceipt?: (receipt: PaymentReceipt) => void): MidnightWalletProvider;
255
+ /**
256
+ * Arweave remote-signing flow:
257
+ * 1. Creates the Arweave transaction locally (data + tags, no local signing).
258
+ * 2. Calls prepareChunks() to compute data_root (Merkle root) locally.
259
+ * 3. Strips the raw data from the transaction before serialising — only the
260
+ * data_root and data_size (not the actual bytes) are sent to the server.
261
+ * 4. POSTs the stripped transaction JSON to the signing server.
262
+ * 5. Applies the returned id, signature, and owner to the transaction.
263
+ * 6. Restores the raw data so the chunked uploader can post it directly to
264
+ * the Arweave gateway — the server never sees the file content.
265
+ *
266
+ * Falls back to the base-class pass-through if provideUploadData() was not called.
267
+ */
268
+ private _payArweave;
269
+ /**
270
+ * Midnight payment flow:
271
+ * POSTs the fee amount to the dStorage API service, which holds a funded
272
+ * Midnight account and submits the chain transaction on behalf of the user.
273
+ *
274
+ * POST {baseUrl}{POST_SIGN_TX_API_PATH}
275
+ * → { txData: string (hex-serialized UnboundTransaction), network: string, userId: string }
276
+ * ← { txId: string, signature: string (hex-serialized FinalizedTransaction), ... }
277
+ *
278
+ * The hex-serialized FinalizedTransaction is returned in PaymentReceipt.signedTx
279
+ * for the chain adapter to deserialize and pass to submitTx().
280
+ */
281
+ private _payMidnight;
282
+ /**
283
+ * Arweave Bundler
284
+ */
285
+ private _payArweaveBundler;
286
+ /**
287
+ * Managed mock flow:
288
+ * Sends a minimal request to the signing server with the literal network
289
+ * identifier "TEST" — the server treats this as a sandbox/test flow with no
290
+ * real funds involved. The SDK-side network name is "managedmock" to follow
291
+ * the lowercase naming convention; the server-side string is always "TEST".
292
+ */
293
+ private _payManagedMock;
294
+ /**
295
+ * Shared HTTP helper: POSTs a transaction payload to the signing server and
296
+ * returns the parsed SignTxResponse.
297
+ *
298
+ * - Arweave: txJson is the Arweave tx JSON object (from tx.toJSON()); the server
299
+ * signs it and returns the signature + owner in the response fields.
300
+ * - Midnight: txJson is the hex-serialized UnboundTransaction; the server balances
301
+ * and signs it, returning the hex-serialized FinalizedTransaction in the
302
+ * `signature` response field.
303
+ *
304
+ * Throws on network errors or non-2xx HTTP responses.
305
+ */
306
+ private _sendSignTxRequest;
307
+ }
308
+
309
+ /**
310
+ * @dstorage/storage — adapters/arweave.ts
311
+ *
312
+ * Real Arweave storage adapter.
313
+ * Uploads encrypted blobs to the Arweave permaweb — pay once, store forever.
314
+ *
315
+ * ── Runtime environments ──────────────────────────────────────────────────────
316
+ *
317
+ * Browser (ArConnect):
318
+ * const adapter = new ArweaveStorageAdapter();
319
+ * // Requires the ArConnect extension: https://arconnect.io
320
+ *
321
+ * Node.js (JWK wallet file):
322
+ * const adapter = new ArweaveStorageAdapter({
323
+ * walletKey: JSON.parse(fs.readFileSync('wallet.json', 'utf8')),
324
+ * });
325
+ *
326
+ * ── Testnet ───────────────────────────────────────────────────────────────────
327
+ *
328
+ * const adapter = new ArweaveStorageAdapter({
329
+ * gateway: { host: 'arweave.dev', port: 443, protocol: 'https' },
330
+ * });
331
+ *
332
+ * ── Peer dependency ───────────────────────────────────────────────────────────
333
+ * npm install arweave
334
+ *
335
+ * ── Notes ─────────────────────────────────────────────────────────────────────
336
+ *
337
+ * • Arweave transactions are optimistic: a 202 response means accepted, not
338
+ * confirmed. Confirmation (inclusion in a block) typically takes 2–20 minutes.
339
+ * Set waitForConfirmation: true to block until the tx is on-chain.
340
+ *
341
+ * • For large files or high-volume uploads, consider Irys (https://irys.xyz)
342
+ * which bundles many transactions together for cheaper and near-instant
343
+ * finality. An IrysStorageAdapter can be added alongside this one.
344
+ *
345
+ * • storageId (txId) is PUBLIC on Arweave. Data security relies entirely on
346
+ * the XChaCha20-Poly1305 encryption applied by @dstorage/crypto before reaching here.
347
+ */
348
+
349
+ interface ArweaveGatewayConfig {
350
+ host: string;
351
+ port: number;
352
+ protocol: "http" | "https";
353
+ }
354
+ interface ArweaveAdapterConfig {
355
+ /**
356
+ * Arweave gateway to broadcast transactions to.
357
+ * Defaults to mainnet (arweave.net:443).
358
+ *
359
+ * Testnet: { host: 'arweave.dev', port: 443, protocol: 'https' }
360
+ *
361
+ * Security: always use `protocol: 'https'` (the default) in production.
362
+ * The SDK relies on standard OS/runtime TLS — no DNS or certificate pinning
363
+ * is applied. Users in adversarial network environments should enforce
364
+ * certificate pinning at the runtime level (e.g. a custom Node.js HTTPS
365
+ * agent or a trusted corporate proxy).
366
+ */
367
+ gateway?: ArweaveGatewayConfig;
368
+ /**
369
+ * JWK wallet key for Node.js server-side usage.
370
+ * Leave undefined in the browser — ArConnect is used automatically.
371
+ *
372
+ * Obtain a free wallet at https://arweave.app or generate via arweave-js:
373
+ * const jwk = await Arweave.init({}).wallets.generate();
374
+ */
375
+ walletKey?: Record<string, string>;
376
+ /**
377
+ * Base URL of a local ManagedPaymentAdapter signing server.
378
+ * When provided, the adapter uses ManagedPaymentAdapter (remote signing)
379
+ * instead of the default ArweavePaymentAdapter (local signing).
380
+ * Example: "http://localhost:3000"
381
+ */
382
+ signingServerUrl?: string;
383
+ /**
384
+ * Bearer token sent as the `Authorization` header to authenticate with the signing server.
385
+ * Required when `signingServerUrl` is provided.
386
+ */
387
+ authToken?: string;
388
+ /**
389
+ * How many times to retry a failed transaction post before throwing.
390
+ * Uses a simple linear back-off: 1 s, 2 s, 3 s…
391
+ * Defaults to 3.
392
+ */
393
+ maxRetries?: number;
394
+ /**
395
+ * If true, poll Arweave until the transaction is confirmed (block included)
396
+ * before returning from store(). Confirmation typically takes 2–20 minutes.
397
+ *
398
+ * Defaults to false (optimistic — returns as soon as the gateway accepts
399
+ * the transaction with HTTP 200 or 202).
400
+ */
401
+ waitForConfirmation?: boolean;
402
+ /**
403
+ * Polling interval in ms while waiting for confirmation.
404
+ * Defaults to 30_000 (30 seconds).
405
+ */
406
+ confirmationPollMs?: number;
407
+ /**
408
+ * Maximum time in ms to wait for confirmation before throwing a timeout error.
409
+ * Defaults to 1_200_000 (20 minutes).
410
+ */
411
+ confirmationTimeoutMs?: number;
412
+ /**
413
+ * When true, skip the BLAKE3 content-hash check on retrieve.
414
+ * By default (false) the adapter fetches the transaction metadata and verifies
415
+ * that the `X-Content-Hash` tag recorded at upload time matches the retrieved
416
+ * bytes. Set to true only if you trust the gateway entirely or are using an
417
+ * Arweave node that does not expose the transaction metadata endpoint.
418
+ */
419
+ skipIntegrityCheck?: boolean;
420
+ /**
421
+ * Maximum number of bytes allowed in a single retrieve() call.
422
+ * The adapter rejects the download before materialising the blob if the
423
+ * Arweave transaction metadata reports a larger `data_size`, and always
424
+ * rejects after loading if the actual byte count exceeds this value.
425
+ * Defaults to 268_435_456 (256 MB).
426
+ */
427
+ maxRetrieveSizeBytes?: number;
428
+ /**
429
+ * Optional logger for SDK operational output.
430
+ * Pass `logger: console` to see all output, or inject your own logger.
431
+ * Omit to suppress all SDK log output.
432
+ */
433
+ logger?: StorageAdapterLogger;
434
+ }
435
+ declare class ArweaveStorageAdapter implements StorageAdapter {
436
+ readonly name: StorageProviderName;
437
+ readonly providerName: string;
438
+ paymentAdapter: PaymentAdapter;
439
+ private readonly gateway;
440
+ private readonly maxRetries;
441
+ private readonly shouldWaitForConfirm;
442
+ private readonly confirmationPollMs;
443
+ private readonly confirmationTimeoutMs;
444
+ private readonly skipIntegrityCheck;
445
+ private readonly maxRetrieveSizeBytes;
446
+ protected readonly logger: StorageAdapterLogger | undefined;
447
+ private arweaveClient;
448
+ constructor(config?: ArweaveAdapterConfig);
449
+ private getClient;
450
+ store(data: Uint8Array, metadata?: Record<string, string>): Promise<StorageUploadResult>;
451
+ retrieve(id: string): Promise<{
452
+ bytes: Uint8Array;
453
+ tags: Record<string, string>;
454
+ }>;
455
+ estimateCost(dataSizeBytes: number): Promise<StorageQuote>;
456
+ /**
457
+ * Upload a signed transaction using arweave-js getUploader().
458
+ *
459
+ * getUploader() sends just the tx header to /tx, then streams each 256 KB
460
+ * data slice to the /chunk endpoint. This avoids the ~12 MB HTTP body limit
461
+ * of transactions.post() and supports arbitrarily large transactions.
462
+ *
463
+ * Failed slices are retried individually up to maxRetries times with linear
464
+ * back-off, so a transient network error won't restart the entire upload.
465
+ */
466
+ private uploadWithChunker;
467
+ private pollUntilConfirmed;
468
+ }
469
+
470
+ /**
471
+ * @dstorage/storage — adapters/arweave-bundler.ts
472
+ *
473
+ * Arweave Bundler storage adapter — ANS-104 bundled uploads with server-side signing.
474
+ *
475
+ * ── Upload flow (no client-side Arweave wallet needed) ────────────────────────
476
+ *
477
+ * 1. Client creates an ANS-104 data item locally with the already-encrypted data.
478
+ * 2. Computes the 48-byte deep_hash locally — the ANS-104 signing digest.
479
+ * 3. Sends ONLY the hash to the dStorage API signing server.
480
+ * Raw file bytes never leave the client — same privacy invariant as the
481
+ * current managed Arweave flow where only the stripped tx JSON (data_root)
482
+ * goes to the server.
483
+ * 4. Server signs the hash with its Arweave JWK (funded Turbo Credits account).
484
+ * 5. Client assembles the complete signed data item locally.
485
+ * 6. Client POSTs the signed data item directly to the ArDrive bundler.
486
+ * 7. Returns with near-instant finality — txId is available immediately.
487
+ *
488
+ * ── Retrieve flow ─────────────────────────────────────────────────────────────
489
+ * Standard Arweave gateway fetch (identical to ArweaveStorageAdapter.retrieve).
490
+ *
491
+ * ── Peer dependency ───────────────────────────────────────────────────────────
492
+ * No extra install needed — @dha-team/arbundles ships as a dependency of @ardrive/turbo-sdk.
493
+ *
494
+ * ── Server requirements ───────────────────────────────────────────────────────
495
+ * The dStorage API server must expose (auth-protected via Bearer token):
496
+ * POST /api/service/sign-tx → { signature: string, txId: string, success: boolean, … }
497
+ * The server's Arweave wallet must have Turbo Credits funded at https://ardrive.io.
498
+ *
499
+ * ── Auth token format ─────────────────────────────────────────────────────────
500
+ * authToken must be in the format: <credential>.<base64url_modulus>
501
+ * where <base64url_modulus> is the 512-byte RSA-4096 public key modulus
502
+ * base64url-encoded. The adapter validates and pins the key at construction time.
503
+ * Re-issue the token from the signing server to obtain the current key.
504
+ *
505
+ * ── Notes ─────────────────────────────────────────────────────────────────────
506
+ * • The ArDrive bundler provides near-instant finality — unlike the 2–20 min Arweave L1 wait.
507
+ * • The server holds the funded Turbo Credits account; users need no AR tokens.
508
+ * • Only 48 bytes (the deep_hash) go to the server; ciphertext stays on client.
509
+ */
510
+
511
+ interface ArweaveBundlerAdapterConfig {
512
+ /**
513
+ * Base URL of the dStorage API server that holds the funded Turbo Credits account.
514
+ * Example: "https://api.my-dstorage-server.com"
515
+ */
516
+ signingServerUrl?: string;
517
+ /**
518
+ * Bearer token sent as the `Authorization` header to authenticate with the signing server.
519
+ * Required when `signingServerUrl` is provided.
520
+ */
521
+ authToken?: string;
522
+ /**
523
+ * Arweave gateway URL used for data retrieval.
524
+ * Defaults to the public Arweave gateway.
525
+ *
526
+ * Security: always use an `https://` URL (the default) in production.
527
+ * This adapter uses `globalThis.fetch` directly — no DNS or certificate
528
+ * pinning is applied. Users in adversarial network environments can override
529
+ * `globalThis.fetch` before constructing the adapter to inject their own
530
+ * certificate-pinned fetch implementation.
531
+ */
532
+ gateway?: string;
533
+ /**
534
+ * Maximum number of bytes allowed in a single retrieve() call.
535
+ * Rejects if the `Content-Length` response header exceeds this value, and
536
+ * always rejects after loading if the actual byte count exceeds it.
537
+ * Defaults to 268_435_456 (256 MB).
538
+ */
539
+ maxRetrieveSizeBytes?: number;
540
+ /**
541
+ * Skip BLAKE3 content-hash verification on retrieve.
542
+ * Only set to true when connecting to a fully trusted gateway.
543
+ * Defaults to false.
544
+ */
545
+ skipIntegrityCheck?: boolean;
546
+ /**
547
+ * Optional logger for SDK operational output.
548
+ */
549
+ logger?: StorageAdapterLogger;
550
+ }
551
+ /**
552
+ * Stores encrypted data on Arweave via the ArDrive bundler (near-instant finality).
553
+ *
554
+ * Signing is delegated to the dStorage API server, which holds a funded Turbo Credits
555
+ * account. The client sends only a 48-byte ANS-104 deep_hash to the server — the
556
+ * encrypted file bytes never leave the client, preserving the same privacy invariant
557
+ * as the existing managed Arweave flow.
558
+ *
559
+ * @example
560
+ * const adapter = new ArweaveBundlerStorageAdapter({
561
+ * signingServerUrl: "https://api.my-server.com",
562
+ * authToken: "ds_...",
563
+ * });
564
+ * const { id } = await adapter.store(encryptedBytes, { "Content-Type": "application/octet-stream" });
565
+ */
566
+ declare class ArweaveBundlerStorageAdapter implements StorageAdapter {
567
+ readonly name: StorageProviderName;
568
+ readonly providerName = "Arweave (Bundler)";
569
+ readonly paymentAdapter: PaymentAdapter;
570
+ private readonly signingServerUrl;
571
+ private readonly gateway;
572
+ private readonly maxRetrieveSizeBytes;
573
+ private readonly skipIntegrityCheck;
574
+ protected readonly logger: StorageAdapterLogger | undefined;
575
+ /** RSA-4096 public key modulus (512 bytes) parsed from the auth token at construction time. */
576
+ private readonly ownerPublicKey;
577
+ constructor(config?: ArweaveBundlerAdapterConfig);
578
+ store(data: Uint8Array, metadata?: Record<string, string>): Promise<StorageUploadResult>;
579
+ retrieve(id: string): Promise<{
580
+ bytes: Uint8Array;
581
+ tags: Record<string, string>;
582
+ }>;
583
+ estimateCost(dataSizeBytes: number): Promise<StorageQuote>;
584
+ /**
585
+ * Build a minimal signer object compatible with the @dha-team/arbundles DataItem API.
586
+ *
587
+ * The only non-trivial method is sign(): it sends the deep_hash produced by
588
+ * the DataItem's internal ANS-104 signing procedure to the selected payment adapter.
589
+ * The payment adapter responds with the RSA-PSS signature over that hash (512 bytes, ANS-104 type 1).
590
+ * Raw file bytes never leave the client.
591
+ *
592
+ * The owner public key is parsed from the auth token at construction time — no
593
+ * network round-trip is needed here.
594
+ */
595
+ private _buildSigner;
596
+ /**
597
+ * POST the 48-byte ANS-104 deep_hash to the signing server via the shared sign-tx endpoint.
598
+ *
599
+ * Uses network: "arweave_bundler" so the server routes to the bundler-specific signing path.
600
+ * The `dataSizeBytes` field lets the server estimate and quote the upload cost.
601
+ */
602
+ private _signHash;
603
+ /**
604
+ * Parse the compound auth token (<credential>.<base64url_modulus>) issued by the
605
+ * signing server. Validates that the embedded key is exactly 512 bytes (RSA-4096).
606
+ * Throws at construction time if the format is wrong — fail-fast before any network call.
607
+ *
608
+ * lastIndexOf is intentional: the credential part may itself contain dots
609
+ * (e.g. a JWT), so we always split at the *last* dot to reach the modulus.
610
+ */
611
+ private static _parseToken;
612
+ /**
613
+ * POST the complete signed ANS-104 data item bytes directly to the ArDrive bundler.
614
+ * Server Turbo Credits are consumed based on the signing key — no client wallet needed.
615
+ */
616
+ private _uploadToBundler;
617
+ }
618
+
619
+ /**
620
+ * @dstorage/storage — arweave-local.ts
621
+ *
622
+ * Local Arweave testing utilities built on top of arlocal:
623
+ * https://github.com/textury/arlocal
624
+ *
625
+ * arlocal is a zero-configuration local Arweave gateway for integration
626
+ * testing. It accepts transactions without requiring real AR tokens, exposes
627
+ * a /mint endpoint to fund test wallets instantly, and a /mine endpoint to
628
+ * fast-forward block confirmation — all fully offline.
629
+ *
630
+ * ── Quick start ───────────────────────────────────────────────────────────────
631
+ *
632
+ * # 1. Start arlocal (once per dev session) — Docker is recommended:
633
+ * docker run -d --rm -p 1984:1984 --name arlocal textury/arlocal
634
+ * # alternatively, without Docker:
635
+ * npx arlocal
636
+ *
637
+ * # 2. In your code, use ArweaveLocalStorageAdapter instead of the real one
638
+ * const { adapter, walletKey, address } =
639
+ * await ArweaveLocalStorageAdapter.createWithTestWallet();
640
+ *
641
+ * # 3. Mint test tokens
642
+ * await adapter.testnet.mintTokens(address, 5_000_000_000_000n); // 5 AR
643
+ *
644
+ * # 4. Use exactly like ArweaveStorageAdapter
645
+ * const { id } = await adapter.store('my encrypted data');
646
+ * await adapter.testnet.mine(); // confirm the tx instantly
647
+ * const data = await adapter.retrieve(id);
648
+ *
649
+ * ── Exports ───────────────────────────────────────────────────────────────────
650
+ *
651
+ * ARWEAVE_MAINNET — gateway preset for arweave.net
652
+ * ARWEAVE_LOCAL — gateway preset for localhost:1984
653
+ * arlocalGateway(port) — build a custom-port local preset
654
+ * ArweaveLocalHelper — mint / mine / balance / reset helpers
655
+ * ArweaveLocalStorageAdapter — drop-in adapter for local testing
656
+ * ArweaveLocalError — typed error thrown by helper methods
657
+ */
658
+
659
+ /**
660
+ * Local arlocal gateway preset (default port 1984).
661
+ *
662
+ * @example
663
+ * new ArweaveStorageAdapter({ gateway: ARWEAVE_LOCAL, walletKey: testJwk })
664
+ * // or:
665
+ * new ArweaveLocalStorageAdapter({ walletKey: testJwk })
666
+ */
667
+ declare const ARWEAVE_LOCAL: ArweaveGatewayConfig;
668
+ /**
669
+ * Build a local arlocal gateway preset on a non-default port.
670
+ *
671
+ * @example
672
+ * const gw = arlocalGateway(1985);
673
+ * new ArweaveLocalStorageAdapter({ gateway: gw, walletKey: testJwk })
674
+ */
675
+ declare function arlocalGateway(port?: number): ArweaveGatewayConfig;
676
+ interface ArweaveLocalHelperConfig {
677
+ /** Base URL of the arlocal instance. Defaults to 'http://localhost:1984'. */
678
+ url?: string;
679
+ }
680
+ interface ArweaveLocalInfo {
681
+ network: string;
682
+ version: number;
683
+ release: number;
684
+ height: number;
685
+ current: string;
686
+ peers: number;
687
+ queue_length: number;
688
+ node_state_latency: number;
689
+ }
690
+ interface ArweaveLocalBalance {
691
+ /** Raw balance in Winstons (1 AR = 1_000_000_000_000 Winstons). */
692
+ winstons: string;
693
+ /** Human-readable balance, e.g. "5" for 5 AR. */
694
+ ar: string;
695
+ }
696
+ /**
697
+ * Helper for controlling a running arlocal instance.
698
+ *
699
+ * Use this to fund test wallets, fast-forward block confirmations, and
700
+ * inspect state during integration tests.
701
+ *
702
+ * @example
703
+ * const helper = new ArweaveLocalHelper();
704
+ * await helper.mintTokens(address, 1_000_000_000_000n); // 1 AR
705
+ * await helper.mine();
706
+ * const { ar } = await helper.getBalance(address);
707
+ */
708
+ declare class ArweaveLocalHelper {
709
+ private readonly baseUrl;
710
+ constructor(config?: ArweaveLocalHelperConfig);
711
+ /**
712
+ * Credit a wallet address with test AR tokens.
713
+ *
714
+ * The amount is in Winstons (1 AR = 1_000_000_000_000 Winstons).
715
+ * Defaults to 1 AR if not specified.
716
+ *
717
+ * @example
718
+ * await helper.mintTokens(address, 5_000_000_000_000n); // 5 AR
719
+ */
720
+ mintTokens(address: string, winstons?: bigint | number): Promise<void>;
721
+ /**
722
+ * Fast-forward the arlocal blockchain by mining one or more blocks.
723
+ *
724
+ * Pending transactions only become "confirmed" after a block is mined.
725
+ * Call this after uploading if your test checks confirmed status
726
+ * (e.g. when using `waitForConfirmation: true`).
727
+ *
728
+ * @example
729
+ * await helper.mine(); // mine 1 block
730
+ * await helper.mine(3); // mine 3 blocks
731
+ */
732
+ mine(blocks?: number): Promise<void>;
733
+ /**
734
+ * Query the AR token balance of a wallet address on arlocal.
735
+ *
736
+ * @example
737
+ * const { ar, winstons } = await helper.getBalance(address);
738
+ * console.log(`Balance: ${ar} AR (${winstons} winstons)`);
739
+ */
740
+ getBalance(address: string): Promise<ArweaveLocalBalance>;
741
+ /**
742
+ * Retrieve general info about the arlocal instance.
743
+ * Useful for confirming the server is reachable before running tests.
744
+ */
745
+ getInfo(): Promise<ArweaveLocalInfo>;
746
+ /**
747
+ * Returns `true` if the arlocal instance is reachable, `false` otherwise.
748
+ *
749
+ * Use in `beforeAll` to skip integration tests gracefully when arlocal
750
+ * is not running in the local environment.
751
+ *
752
+ * @example
753
+ * beforeAll(async () => {
754
+ * if (!(await helper.isRunning())) {
755
+ * console.warn('arlocal not running — skipping integration tests');
756
+ * }
757
+ * });
758
+ */
759
+ isRunning(): Promise<boolean>;
760
+ /**
761
+ * Drop all transactions and reset arlocal state to a clean slate.
762
+ * Only available when arlocal is started with persistence disabled (the default).
763
+ */
764
+ reset(): Promise<void>;
765
+ private get;
766
+ }
767
+ type ArweaveLocalAdapterConfig = ArweaveAdapterConfig;
768
+ /**
769
+ * A storage adapter for local Arweave integration testing using arlocal.
770
+ *
771
+ * Identical API to `ArweaveStorageAdapter` but pre-configured for a local
772
+ * arlocal instance. Exposes a `.testnet` helper for minting tokens, mining
773
+ * blocks, and inspecting state — without touching the real Arweave network.
774
+ *
775
+ * ── Requirements ──────────────────────────────────────────────────────────────
776
+ *
777
+ * Start arlocal (Docker recommended — no npm install needed):
778
+ * docker run -d --rm -p 1984:1984 --name arlocal textury/arlocal
779
+ * or, via npx (installs arlocal on demand):
780
+ * npx arlocal
781
+ *
782
+ * ── Usage ─────────────────────────────────────────────────────────────────────
783
+ *
784
+ * Option A — static factory (recommended for tests): auto-generates & funds wallet
785
+ *
786
+ * const { adapter, walletKey, address } =
787
+ * await ArweaveLocalStorageAdapter.createWithTestWallet();
788
+ *
789
+ * const ds = new DStorage({
790
+ * storageAdapter: adapter,
791
+ * chainAdapter: new MockChainAdapter(),
792
+ * });
793
+ *
794
+ * Option B — manual config (when you already have a wallet):
795
+ *
796
+ * const adapter = new ArweaveLocalStorageAdapter({ walletKey: myJwk });
797
+ * await adapter.testnet.mintTokens(address, 2_000_000_000_000n); // 2 AR
798
+ *
799
+ * ── Replacing the real adapter ────────────────────────────────────────────────
800
+ *
801
+ * // Development / CI — local arlocal
802
+ * storageAdapter: new ArweaveLocalStorageAdapter({ walletKey: testJwk })
803
+ *
804
+ * // Production — real Arweave mainnet
805
+ * storageAdapter: new ArweaveStorageAdapter({ walletKey: realJwk })
806
+ */
807
+ declare class ArweaveLocalStorageAdapter extends ArweaveStorageAdapter {
808
+ readonly name: StorageProviderName;
809
+ readonly providerName: string;
810
+ /** Access arlocal control methods: mint, mine, balance, reset. */
811
+ readonly testnet: ArweaveLocalHelper;
812
+ /** Resolves when the wallet has been funded on arlocal (if walletKey was provided). */
813
+ private readonly _initMintPromise;
814
+ constructor(config?: ArweaveLocalAdapterConfig);
815
+ /**
816
+ * Extract the 683-char base64url RSA modulus suffix from a compound auth token
817
+ * (<credential>.<modulus>). Returns undefined for plain tokens.
818
+ * Mirrors the same logic in ManagedPaymentAdapter._parseAuthToken.
819
+ */
820
+ private static _extractOwnerKey;
821
+ private _mintWallet;
822
+ private _mintManagedOwner;
823
+ private _mintToOwnerKey;
824
+ /**
825
+ * Factory method: generates a fresh Arweave wallet, mints test AR tokens
826
+ * into it, and returns a fully-configured adapter ready for testing.
827
+ *
828
+ * Requires arlocal to be running at the given URL.
829
+ *
830
+ * @param options.fundAr AR to mint into the test wallet (default: 10)
831
+ * @param options.gateway Override the arlocal gateway (default: localhost:1984)
832
+ *
833
+ * @example
834
+ * const { adapter, walletKey, address } =
835
+ * await ArweaveLocalStorageAdapter.createWithTestWallet({ fundAr: 5 });
836
+ *
837
+ * // Then use adapter in your DStorage instance:
838
+ * const ds = new DStorage({ storageAdapter: adapter, chainAdapter: new MockChainAdapter() });
839
+ */
840
+ static createWithTestWallet(options?: {
841
+ fundAr?: number;
842
+ gateway?: ArweaveGatewayConfig;
843
+ }): Promise<{
844
+ adapter: ArweaveLocalStorageAdapter;
845
+ walletKey: Record<string, string>;
846
+ address: string;
847
+ }>;
848
+ store(data: Uint8Array, metadata?: Record<string, string>): Promise<StorageUploadResult>;
849
+ }
850
+ declare class ArweaveLocalError extends Error {
851
+ readonly statusCode: number;
852
+ constructor(message: string, statusCode: number);
853
+ }
854
+
855
+ declare class DStorageError extends Error {
856
+ readonly code: number;
857
+ readonly httpStatus?: number;
858
+ constructor(code: number, message: string, options?: ErrorOptions & {
859
+ httpStatus?: number;
860
+ });
861
+ }
862
+ declare function isDStorageError(err: unknown): err is DStorageError;
863
+ declare const CryptoErrorCode: {
864
+ readonly WEBCRYPTO_NOT_AVAILABLE: 12000;
865
+ readonly BASE64URL_INVALID: 12001;
866
+ readonly MISSING_KEY_INPUT: 12002;
867
+ readonly MNEMONIC_TOO_SHORT: 12003;
868
+ readonly SEED_INVALID_LENGTH: 12004;
869
+ readonly MNEMONIC_INVALID: 12005;
870
+ readonly HEX_ODD_LENGTH: 12006;
871
+ readonly HEX_INVALID_CHARS: 12007;
872
+ readonly DEK_INVALID_LENGTH: 12008;
873
+ readonly WRAP_KEK_INVALID_LENGTH: 12009;
874
+ readonly UNWRAP_KEK_INVALID_LENGTH: 12010;
875
+ readonly ENVELOPE_EMPTY_WRAPPERS: 12011;
876
+ readonly XCHACHA_INVALID_STORAGE_ID_LEN: 12012;
877
+ readonly XCHACHA_PAYLOAD_MALFORMED: 12013;
878
+ readonly XCHACHA_STORAGE_ID_MALFORMED: 12014;
879
+ readonly MLKEM_SEED_INVALID_LENGTH: 12015;
880
+ readonly MLKEM_MISSING_CIPHERTEXT: 12016;
881
+ readonly MLKEM_UNKNOWN_ALGORITHM: 12017;
882
+ readonly MLKEM_UNKNOWN_VARIANT: 12018;
883
+ };
884
+ type CryptoErrorCode = (typeof CryptoErrorCode)[keyof typeof CryptoErrorCode];
885
+
886
+ /**
887
+ * @dstorage/crypto — types.ts
888
+ *
889
+ * Core types and interfaces for the crypto package:
890
+ * - EncryptionScheme — on-chain scheme identifier
891
+ * - CryptoScheme — interface every scheme implementation must satisfy
892
+ * - base64url helpers — shared encoding utilities used across scheme implementations
893
+ */
894
+ /**
895
+ * Identifies the encryption algorithm used to encrypt a storageId and content.
896
+ * Recorded on-chain in ReferenceEntry.encryptionScheme so the SDK can dispatch
897
+ * the correct decryption function at read time.
898
+ *
899
+ * Values:
900
+ * "xchacha20poly1305-v1" — XChaCha20-Poly1305 (per-upload random DEK, wrapped in keyEnvelope); default
901
+ * "" — No encryption; storageId and content are stored as plaintext (public data)
902
+ */
903
+ type EncryptionScheme = "xchacha20poly1305-v1" | "";
904
+ /**
905
+ * The result of wrapping a DEK under a provider's key material.
906
+ * Returned by every EncryptionAdapter.wrapDek() implementation and
907
+ * stored as a KeyWrapper entry inside the on-chain KeyEnvelope.
908
+ *
909
+ * Symmetric providers set algorithm/kekDerivation for their own scheme and
910
+ * leave kemCiphertext undefined. Asymmetric providers (ML-KEM) additionally
911
+ * populate kemCiphertext with the KEM ciphertext needed for decapsulation.
912
+ */
913
+ interface WrappedDekResult {
914
+ /** Algorithm identifier, e.g. "xchacha20poly1305-v1" or "mlkem768-xchacha20poly1305-v1". */
915
+ algorithm: string;
916
+ /** How the KEK was derived from its source material, e.g. "hkdf-sha256-v1". */
917
+ kekDerivation: string;
918
+ /** base64url-encoded wrapped DEK ciphertext. */
919
+ wrappedDek: string;
920
+ /** base64url-encoded KEM ciphertext — present only for asymmetric providers. */
921
+ kemCiphertext?: string;
922
+ }
923
+ /**
924
+ * Interface for a symmetric encryption scheme.
925
+ *
926
+ * Implementations are instantiated from a random DEK via a static factory
927
+ * (e.g. XChaChaScheme.fromKey(dek)) for per-upload encryption.
928
+ */
929
+ interface CryptoScheme {
930
+ /** Scheme identifier recorded on-chain. */
931
+ readonly schemeName: Exclude<EncryptionScheme, "">;
932
+ /**
933
+ * Encrypt raw bytes and return a self-contained serialized payload
934
+ * ready to be uploaded to off-chain storage.
935
+ *
936
+ * `aad` is bound into the Poly1305 auth tag and must match on decrypt.
937
+ * Use PAYLOAD_AAD for single-shot uploads and manifests; use chunkAad(i, n)
938
+ * for individual chunks so a malicious gateway cannot swap chunk order.
939
+ */
940
+ encryptPayload(bytes: Uint8Array, aad: Uint8Array): Promise<Uint8Array>;
941
+ /**
942
+ * Deserialize and decrypt a payload previously produced by encryptPayload().
943
+ * Throws if the payload format is invalid, the auth tag fails, or the AAD mismatches.
944
+ */
945
+ decryptPayload(data: Uint8Array, aad: Uint8Array): Promise<Uint8Array>;
946
+ /**
947
+ * Encrypt a 43-char base64url storage ID (32 decoded bytes) for on-chain storage.
948
+ * Returns a base64url-encoded encrypted form.
949
+ */
950
+ encryptStorageId(storageId: string): Promise<string>;
951
+ /**
952
+ * Decrypt a storage ID previously encrypted by encryptStorageId().
953
+ * Returns the original 43-char base64url storage ID.
954
+ */
955
+ decryptStorageId(encryptedId: string): Promise<string>;
956
+ }
957
+ /** Decode a base64url string to a Uint8Array. */
958
+ declare function base64urlToBytes(b64url: string): Uint8Array;
959
+ /** Encode a Uint8Array to a base64url string (no padding). */
960
+ declare function bytesToBase64url(bytes: Uint8Array): string;
961
+
962
+ /**
963
+ * @dstorage/crypto — keys.ts
964
+ * Provides seed-based key derivation utilities:
965
+ *
966
+ * - KeyDeriver: resolves a BIP-39 mnemonic or raw hex seed to raw bytes,
967
+ * importing seed bytes as a CryptoKey for use with deriveKek() (keyEnvelope.ts).
968
+ * - hexToBytes: parses a hex string into a Uint8Array.
969
+ */
970
+ /**
971
+ * Resolves a BIP-39 mnemonic or raw hex seed to raw bytes.
972
+ * Implements EncryptionAdapter — pass an instance to DStorage config.
973
+ */
974
+ declare class KeyDeriver {
975
+ private readonly input;
976
+ constructor(input: {
977
+ mnemonic?: string;
978
+ seedHex?: string;
979
+ });
980
+ /**
981
+ * Return the raw seed bytes.
982
+ * Import the result as a non-extractable HKDF CryptoKey before passing to deriveKek().
983
+ */
984
+ getSeed(): Promise<Uint8Array>;
985
+ /** Resolves and validates the seed as a Buffer. */
986
+ private getSeedBuffer;
987
+ }
988
+ declare function hexToBytes(hex: string, label?: string): Uint8Array<ArrayBuffer>;
989
+
990
+ /**
991
+ * @dstorage/crypto — xchacha.ts
992
+ * Symmetric authenticated encryption using XChaCha20-Poly1305.
993
+ *
994
+ * Key derivation:
995
+ * seed bytes (from EncryptionAdapter)
996
+ * → HKDF-SHA-256 (domain-separated, optionally address-bound)
997
+ * → 32-byte symmetric key (KEK)
998
+ * → per-upload random DEK wrapped under KEK
999
+ *
1000
+ * Why XChaCha20-Poly1305:
1001
+ * - 192-bit nonce eliminates birthday-bound collision risk —
1002
+ * safe to generate random nonces indefinitely
1003
+ * - Pure bytes in / bytes out — no WebCrypto CryptoKey ceremony
1004
+ * - Better performance on hardware without AES acceleration (mobile, ARM, IoT)
1005
+ *
1006
+ * Why a single symmetric key instead of a KEM keypair:
1007
+ * A KEM step would only add value if data needed to be
1008
+ * encrypted for a different recipient using their public key. For single-user
1009
+ * self-encryption where the same party encrypts and decrypts, HKDF → XChaCha20
1010
+ * is simpler, has much smaller ciphertext overhead, and provides equivalent
1011
+ * security. If cross-user encryption is required in the future the scheme
1012
+ * can be extended with a KEM layer at that point.
1013
+ *
1014
+ * On-chain storageId format (JSON):
1015
+ * Same envelope as off-chain payloads — handles arbitrary-length string IDs.
1016
+ * { ciphertext: base64, nonce: base64, algorithm: "XChaCha20-Poly1305" }
1017
+ *
1018
+ * Off-chain payload format (JSON):
1019
+ * { ciphertext: base64, nonce: base64, algorithm: "XChaCha20-Poly1305" }
1020
+ */
1021
+
1022
+ /** Encrypted payload stored off-chain (Arweave, etc.). All binary fields are base64. */
1023
+ interface XChaChaPayload {
1024
+ /** base64 — XChaCha20-Poly1305 output: ciphertext || 16-byte Poly1305 tag */
1025
+ ciphertext: string;
1026
+ /** base64 — 24-byte random nonce */
1027
+ nonce: string;
1028
+ /** Algorithm identifier */
1029
+ algorithm: "XChaCha20-Poly1305";
1030
+ }
1031
+ /**
1032
+ * Derive a 32-byte symmetric key for XChaCha20-Poly1305 from arbitrary seed bytes.
1033
+ *
1034
+ * Uses HKDF-SHA-256 with a fixed global salt (domain separator) and a versioned,
1035
+ * context-bound `info` string per RFC 5869:
1036
+ * - `salt` = fixed application-level extraction key ("dstorage-xchacha-v1")
1037
+ * - `info` = versioned label, optionally binding a wallet address
1038
+ *
1039
+ * @param seed High-entropy seed bytes (wallet signature, BIP-39 seed, hex seed, etc.)
1040
+ * @param context Optional wallet address or other per-context binding value.
1041
+ * Incorporated into `info` to bind the derived key to a specific account.
1042
+ */
1043
+ declare function deriveSymmetricKeyFromSeed(seed: Uint8Array, context?: string): Promise<Uint8Array>;
1044
+ /**
1045
+ * Encrypt arbitrary bytes with XChaCha20-Poly1305.
1046
+ *
1047
+ * Non-deterministic: fresh random 24-byte nonce per call.
1048
+ *
1049
+ * @param key 32-byte symmetric key from deriveSymmetricKeyFromSeed()
1050
+ * @param data Arbitrary plaintext bytes
1051
+ * @param aad Additional authenticated data bound to the ciphertext (recommended)
1052
+ */
1053
+ declare function encryptXChaCha(key: Uint8Array, data: Uint8Array, aad?: Uint8Array): Promise<XChaChaPayload>;
1054
+ /**
1055
+ * Decrypt a payload produced by encryptXChaCha().
1056
+ * The `aad` must match exactly what was passed to encryptXChaCha() — the Poly1305
1057
+ * auth tag covers the AAD, so any mismatch causes decryption to throw.
1058
+ *
1059
+ * @param key 32-byte symmetric key (must match the key used to encrypt)
1060
+ * @param payload XChaChaPayload from encryptXChaCha()
1061
+ * @param aad Must match the AAD used during encryption
1062
+ * @throws If Poly1305 auth tag verification fails (wrong key, tampered data, or wrong AAD)
1063
+ */
1064
+ declare function decryptXChaCha(key: Uint8Array, payload: XChaChaPayload, aad?: Uint8Array): Promise<Uint8Array>;
1065
+ /**
1066
+ * Encrypt a 32-byte storage ID for on-chain storage.
1067
+ *
1068
+ * Output is exactly 72 bytes: [ nonce(24) | ciphertext(32) | auth-tag(16) ].
1069
+ *
1070
+ * @param key 32-byte symmetric key from deriveSymmetricKeyFromSeed()
1071
+ * @param storageIdBytes Raw 32-byte storage ID
1072
+ */
1073
+ declare function encryptStorageIdXChaCha(key: Uint8Array, storageIdBytes: Uint8Array): Promise<Uint8Array>;
1074
+ /**
1075
+ * Decrypt a storage ID previously encrypted with encryptStorageIdXChaCha().
1076
+ * Expects exactly 72 bytes.
1077
+ * Throws if the Poly1305 auth tag does not match (tamper-evident).
1078
+ *
1079
+ * @param key 32-byte symmetric key (must match encryption key)
1080
+ * @param encryptedBytes 72-byte on-chain payload
1081
+ */
1082
+ declare function decryptStorageIdXChaCha(key: Uint8Array, encryptedBytes: Uint8Array): Promise<Uint8Array>;
1083
+ /**
1084
+ * Serialize an XChaChaPayload to a compact JSON string.
1085
+ * Safe to pass to off-chain storage APIs.
1086
+ */
1087
+ declare function serializeXChaChaPayload(payload: XChaChaPayload): string;
1088
+ /**
1089
+ * Deserialize a JSON string back to an XChaChaPayload.
1090
+ * Returns null if the input is invalid or missing required fields.
1091
+ */
1092
+ declare function deserializeXChaChaPayload(raw: string): XChaChaPayload | null;
1093
+ /** XChaCha20-Poly1305 scheme. Key derived via HKDF-SHA-256. */
1094
+ declare class XChaChaScheme implements CryptoScheme {
1095
+ readonly schemeName: "xchacha20poly1305-v1";
1096
+ private readonly key;
1097
+ private constructor();
1098
+ /**
1099
+ * Derive a 32-byte XChaCha20-Poly1305 key from seed bytes using HKDF-SHA-256.
1100
+ *
1101
+ * @param seed High-entropy seed bytes (wallet signature, BIP-39 seed, etc.)
1102
+ * @param context Optional wallet address or other binding context.
1103
+ * Incorporated into the HKDF salt to bind the key to a specific account.
1104
+ */
1105
+ static create(seed: Uint8Array, context?: string): Promise<XChaChaScheme>;
1106
+ /**
1107
+ * Create a scheme instance from a pre-generated key (e.g. a random DEK).
1108
+ * Bypasses HKDF derivation — use when the key is already available.
1109
+ *
1110
+ * @param key 32-byte symmetric key
1111
+ */
1112
+ static fromKey(key: Uint8Array): XChaChaScheme;
1113
+ encryptPayload(bytes: Uint8Array, aad: Uint8Array): Promise<Uint8Array>;
1114
+ decryptPayload(data: Uint8Array, aad: Uint8Array): Promise<Uint8Array>;
1115
+ encryptStorageId(storageId: string): Promise<string>;
1116
+ decryptStorageId(encryptedId: string): Promise<string>;
1117
+ }
1118
+
1119
+ /**
1120
+ * @dstorage/crypto — keyEnvelope.ts
1121
+ *
1122
+ * Multi-key wrapping for Data Encryption Keys (DEKs).
1123
+ *
1124
+ * Each private upload generates a fresh random DEK, which is then wrapped
1125
+ * (encrypted) under a Key Encryption Key (KEK) derived from the wallet seed.
1126
+ * The wrapped DEK and its metadata are serialised as a JSON envelope and
1127
+ * stored on-chain in the `keyEnvelope` field of ReferenceEntry.
1128
+ *
1129
+ * This separates the encryption key (random, unique per upload) from the
1130
+ * key-protecting mechanism (wallet-bound), enabling future multi-recipient
1131
+ * access without re-encrypting stored data — just add another wrapper entry.
1132
+ *
1133
+ * Envelope schema (private uploads only — public uploads have no envelope):
1134
+ * {
1135
+ * "v": 1,
1136
+ * "wrappers": [
1137
+ * {
1138
+ * "wrapKeyName": "password", // identifies the wrapping key source
1139
+ * "algorithm": "xchacha20poly1305-v1",
1140
+ * "kekDerivation": "hkdf-sha256-v1",
1141
+ * "wrappedDek": "<base64url 96 chars>"
1142
+ * }
1143
+ * ]
1144
+ * }
1145
+ *
1146
+ * The ownerSecret for private uploads is derived deterministically from the wrapped DEK:
1147
+ * ownerSecret = HKDF-SHA256(ikm=DEK, salt=rawStorageId, info="dstorage:owner-secret:v1")
1148
+ * Any holder of a valid KEK can unwrap the DEK and re-derive the ownerSecret.
1149
+ *
1150
+ * `wrappedDek` binary layout (72 bytes):
1151
+ * [ nonce(24) | ciphertext(32) | auth-tag(16) ]
1152
+ * base64url-encoded → 96 chars — identical to the on-chain storageId layout.
1153
+ */
1154
+
1155
+ interface KeyWrapper extends WrappedDekResult {
1156
+ /** Identifies the wrapping key source (e.g. "password", "mnemonic", "mlkem768"). */
1157
+ wrapKeyName: string;
1158
+ }
1159
+ interface KeyEnvelope {
1160
+ v: 1;
1161
+ /**
1162
+ * Wrappers for the data DEK (content encryption key). Always present in a valid envelope.
1163
+ * The ownerSecret for ownership proofs is derived from the same DEK:
1164
+ * ownerSecret = HKDF-SHA256(DEK, rawStorageId, "dstorage:owner-secret:v1")
1165
+ * Any holder of a valid KEK can unwrap the DEK and re-derive the ownerSecret.
1166
+ * Public uploads have no envelope (keyEnvelope = "").
1167
+ */
1168
+ wrappers: [KeyWrapper, ...KeyWrapper[]];
1169
+ }
1170
+ /**
1171
+ * Generate a cryptographically random 32-byte Data Encryption Key.
1172
+ * Uses the platform CSPRNG (`crypto.getRandomValues`) — safe in both
1173
+ * browser and Node.js 19+.
1174
+ */
1175
+ declare function generateDek(): Uint8Array;
1176
+ /**
1177
+ * Derive a 32-byte Key Encryption Key from a non-extractable HKDF CryptoKey.
1178
+ *
1179
+ * Callers must import their raw seed bytes via `crypto.subtle.importKey("raw", seed,
1180
+ * "HKDF", false, ["deriveBits"])` before calling this function. Accepting only
1181
+ * CryptoKey enforces that raw key material is never held in a JS-accessible heap
1182
+ * variable at this call site.
1183
+ *
1184
+ * Uses the same salt as the data encryption key ("dstorage-xchacha-v1") but a
1185
+ * distinct info string ("dstorage:xchacha20poly1305:kek:v1") to domain-separate
1186
+ * the KEK from all other keys derived from the same seed.
1187
+ *
1188
+ * @param keyMaterial Non-extractable HKDF CryptoKey imported from the seed.
1189
+ * @param context Optional wallet address or other binding context, incorporated
1190
+ * into the info string to bind the KEK to a specific account.
1191
+ */
1192
+ declare function deriveKek(keyMaterial: CryptoKey, context?: string): Promise<Uint8Array>;
1193
+ /**
1194
+ * Wrap (encrypt) a 32-byte DEK under a KEK using XChaCha20-Poly1305.
1195
+ *
1196
+ * Reuses the same 72-byte binary layout as on-chain storageId encryption:
1197
+ * [ nonce(24) | ciphertext(32) | auth-tag(16) ]
1198
+ * base64url-encoded → 96-char string.
1199
+ *
1200
+ * @param dek 32-byte Data Encryption Key to protect
1201
+ * @param kek 32-byte Key Encryption Key (from deriveKek())
1202
+ */
1203
+ declare function wrapKey(dek: Uint8Array, kek: Uint8Array): Promise<string>;
1204
+ /**
1205
+ * Unwrap (decrypt) a wrapped DEK string back to the original 32-byte DEK.
1206
+ *
1207
+ * @param wrappedDek base64url-encoded 96-char string from wrapKey()
1208
+ * @param kek 32-byte Key Encryption Key (from deriveKek())
1209
+ */
1210
+ declare function unwrapKey(wrappedDek: string, kek: Uint8Array): Promise<Uint8Array>;
1211
+ /**
1212
+ * Derive a 32-byte owner secret from the data DEK and the raw storage ID.
1213
+ *
1214
+ * Derivation: HKDF-SHA-256(ikm=dek, salt=rawStorageId, info=OWNER_SECRET_DOMAIN)
1215
+ *
1216
+ * Security properties:
1217
+ * - Post-quantum resistant: HKDF-SHA-256 is purely symmetric (no elliptic-curve math).
1218
+ * - One-way: the DEK cannot be recovered from the ownerSecret (HKDF preimage resistance).
1219
+ * - Key-separated: the ownerSecret cannot be used for data encryption.
1220
+ * - Per-upload unique: different DEK + storageId per upload → different ownerSecret.
1221
+ * - Derivable: any holder of a valid KEK can unwrap the DEK and re-derive the ownerSecret.
1222
+ *
1223
+ * @param ikm 32-byte key material (DEK for private uploads; KEK for public uploads)
1224
+ * @param rawStorageId Raw storage network ID bytes (e.g. Arweave txId encoded as UTF-8)
1225
+ * @param info HKDF info / domain separator (defaults to private-upload domain)
1226
+ */
1227
+ declare function deriveOwnerSecret(ikm: Uint8Array, rawStorageId: Uint8Array, info?: string): Promise<Uint8Array>;
1228
+ /**
1229
+ * Build a v1 key envelope wrapping the data DEK under one or more KEKs.
1230
+ *
1231
+ * Each entry wraps the same random DEK under a different KEK (one per seed
1232
+ * provider), allowing any of the corresponding recipients to independently
1233
+ * decrypt the same content without re-encryption.
1234
+ *
1235
+ * The ownerSecret for ownership proofs is derived from the same DEK:
1236
+ * ownerSecret = HKDF-SHA256(DEK, rawStorageId, "dstorage:owner-secret:v1")
1237
+ * No separate ownership key is needed.
1238
+ *
1239
+ * @param wrappers Non-empty array of `{ wrappedDek, wrapKeyName }` pairs.
1240
+ * `wrappedDek` is the base64url-encoded output of wrapKey().
1241
+ * `wrapKeyName` is a caller-chosen label (e.g. "provider-0").
1242
+ *
1243
+ * @throws if `wrappers` is empty.
1244
+ */
1245
+ declare function buildKeyEnvelope(wrappers: Array<KeyWrapper>): KeyEnvelope;
1246
+ /**
1247
+ * Serialise a KeyEnvelope to the JSON string stored on-chain.
1248
+ */
1249
+ declare function serializeKeyEnvelope(envelope: KeyEnvelope): string;
1250
+ /**
1251
+ * Parse and validate a JSON string from the chain.
1252
+ * Returns null for empty strings or malformed / unrecognised envelopes.
1253
+ */
1254
+ declare function parseKeyEnvelope(raw: string): KeyEnvelope | null;
1255
+ /**
1256
+ * Find a wrapper by its wrapKeyName. Returns null if not found.
1257
+ */
1258
+ declare function findWrapper(envelope: KeyEnvelope, wrapKeyName: string): KeyWrapper | null;
1259
+
1260
+ /**
1261
+ * @dstorage/crypto — mlkem.ts
1262
+ *
1263
+ * Post-quantum DEK wrapping via ML-KEM (CRYSTALS-Kyber, NIST FIPS 203).
1264
+ *
1265
+ * Hybrid encryption pattern:
1266
+ * wrapDek: ML-KEM encapsulate(PK) → sharedSecret → HKDF → KEK → XChaCha20 wraps DEK
1267
+ * unwrapDek: ML-KEM decapsulate(SK, ct) → sharedSecret → HKDF → KEK → XChaCha20 unwraps DEK
1268
+ *
1269
+ * This provides post-quantum confidentiality for the DEK:
1270
+ * - Only the holder of the Secret Key can recover the DEK.
1271
+ * - Encapsulation (upload) requires only the Public Key.
1272
+ * - A quantum computer cannot recover sharedSecret from the KEM ciphertext alone.
1273
+ *
1274
+ * Key sizes (variant mlkem768, NIST recommended):
1275
+ * Public key: 1184 bytes
1276
+ * Secret key: 2400 bytes
1277
+ * Ciphertext: 1088 bytes
1278
+ * Shared secret: 32 bytes
1279
+ */
1280
+
1281
+ type MLKemVariant = "mlkem512" | "mlkem768" | "mlkem1024";
1282
+ /**
1283
+ * Generate a random ML-KEM keypair.
1284
+ *
1285
+ * @param variant ML-KEM variant. Default: "mlkem768" (NIST recommended, 192-bit security).
1286
+ */
1287
+ declare function mlkemGenerateKeypair(variant?: MLKemVariant): {
1288
+ pk: Uint8Array;
1289
+ sk: Uint8Array;
1290
+ };
1291
+ /**
1292
+ * Generate a deterministic ML-KEM keypair from a 64-byte seed (d‖z, per FIPS 203).
1293
+ * The same seed always produces the same keypair.
1294
+ *
1295
+ * Requires exactly 64 bytes — derive via Web Crypto HKDF deriveBits (512 bits) before calling.
1296
+ *
1297
+ * @param seed64 64-byte seed material
1298
+ * @param variant ML-KEM variant. Default: "mlkem768".
1299
+ */
1300
+ declare function mlkemGenerateKeypairFromSeed(seed64: Uint8Array, variant?: MLKemVariant): {
1301
+ pk: Uint8Array;
1302
+ sk: Uint8Array;
1303
+ };
1304
+ /**
1305
+ * Wrap a DEK under a ML-KEM public key.
1306
+ *
1307
+ * Encapsulates a shared secret, derives a KEK from it via HKDF, then wraps
1308
+ * the DEK with the same XChaCha20-Poly1305 scheme used by symmetric providers.
1309
+ * The KEM ciphertext is stored alongside the wrapped DEK so the holder of the
1310
+ * secret key can reverse the process at retrieval time.
1311
+ *
1312
+ * @param dek 32-byte Data Encryption Key to protect
1313
+ * @param pk ML-KEM public key
1314
+ * @param context Domain-separation string bound into the KEK derivation
1315
+ * @param variant ML-KEM variant. Default: "mlkem768".
1316
+ */
1317
+ declare function mlkemWrapDek(dek: Uint8Array, pk: Uint8Array, context: string, variant?: MLKemVariant): Promise<WrappedDekResult>;
1318
+ /**
1319
+ * Unwrap a DEK from a ML-KEM wrapped DEK result.
1320
+ *
1321
+ * The ML-KEM variant is read from `data.algorithm` (e.g. "mlkem768-xchacha20poly1305-v1"),
1322
+ * so the caller does not need to supply it — the key envelope is self-describing.
1323
+ *
1324
+ * @param data WrappedDekResult containing algorithm, kemCiphertext, and wrappedDek
1325
+ * @param sk ML-KEM secret key
1326
+ * @param context Domain-separation string bound into the KEK derivation (must match
1327
+ * the value used to wrap)
1328
+ */
1329
+ declare function mlkemUnwrapDek(data: WrappedDekResult, sk: Uint8Array, context: string): Promise<Uint8Array>;
1330
+
1331
+ /** BLAKE3 hash of `bytes`, returned as a raw 32-byte Uint8Array. */
1332
+ declare function computeBlake3(bytes: Uint8Array): Promise<Uint8Array>;
1333
+ /** BLAKE3 hash of `bytes`, returned as a 64-character lowercase hex string. */
1334
+ declare function computeBlake3Hex(bytes: Uint8Array): Promise<string>;
1335
+
1336
+ declare const EncryptionErrorCode: {
1337
+ readonly KEYPAIR_MISSING_SECRET_KEY: 13001;
1338
+ readonly MNEMONIC_TOO_SHORT: 13002;
1339
+ readonly PASSWORD_UNSUPPORTED_KDF: 13003;
1340
+ readonly PASSWORD_EMPTY_SALT: 13004;
1341
+ readonly PASSWORD_UNKNOWN_PRESET: 13005;
1342
+ readonly PASSWORD_TOO_SHORT: 13006;
1343
+ readonly PASSWORD_TOO_FEW_DISTINCT: 13007;
1344
+ readonly PASSWORD_SEQUENTIAL_RUN: 13008;
1345
+ readonly PASSWORD_KEYBOARD_WALK: 13009;
1346
+ readonly PASSWORD_ENTROPY_TOO_LOW: 13010;
1347
+ };
1348
+ type EncryptionErrorCode = (typeof EncryptionErrorCode)[keyof typeof EncryptionErrorCode];
1349
+
1350
+ /**
1351
+ * @dstorage/encryption — types.ts
1352
+ *
1353
+ * The EncryptionAdapter interface: the unified abstraction for how the
1354
+ * dStorage SDK wraps and unwraps per-upload Data Encryption Keys (DEKs).
1355
+ *
1356
+ * Both symmetric (password, mnemonic) and asymmetric (ML-KEM) adapters implement
1357
+ * this interface, so the core SDK calls wrapDek/unwrapDek uniformly with no
1358
+ * knowledge of which algorithm is in use.
1359
+ *
1360
+ * The result of wrapDek() is stored as a KeyWrapper entry in the on-chain
1361
+ * KeyEnvelope. At retrieval time, the same result is passed back to unwrapDek()
1362
+ * to recover the DEK.
1363
+ */
1364
+
1365
+ /**
1366
+ * Wraps and unwraps per-upload DEKs using adapter-specific key material.
1367
+ *
1368
+ * Implementations:
1369
+ * PasswordEncryptionAdapter — symmetric: scrypt → HKDF → KEK → XChaCha20
1370
+ * MnemonicEncryptionAdapter — symmetric: BIP-39 seed → HKDF → KEK → XChaCha20
1371
+ * KeypairEncryptionAdapter — asymmetric: ML-KEM encapsulate/decapsulate + HKDF + XChaCha20
1372
+ */
1373
+ interface EncryptionAdapter {
1374
+ /** Stable identifier used as wrapKeyName in key envelopes. */
1375
+ readonly name: string;
1376
+ /**
1377
+ * Wrap a DEK under this adapter's key material.
1378
+ * Called once per upload, per adapter.
1379
+ *
1380
+ * @param dek 32-byte Data Encryption Key to protect
1381
+ * @returns WrappedDekResult to store in the on-chain key envelope
1382
+ */
1383
+ wrapDek(dek: Uint8Array): Promise<WrappedDekResult>;
1384
+ /**
1385
+ * Unwrap a DEK from a previously wrapped result.
1386
+ * Called at retrieval time using the same result that wrapDek() returned.
1387
+ *
1388
+ * @param data WrappedDekResult from the on-chain key envelope
1389
+ * @returns 32-byte Data Encryption Key
1390
+ * @throws If the adapter's key material cannot decrypt the wrapped DEK
1391
+ */
1392
+ unwrapDek(data: WrappedDekResult): Promise<Uint8Array>;
1393
+ /**
1394
+ * Zero any raw key bytes held by this adapter and mark it unusable.
1395
+ * Optional — only adapters holding raw byte arrays implement this.
1396
+ * Call after the adapter is no longer needed to minimise the window
1397
+ * during which secret key material sits in GC-reachable memory.
1398
+ */
1399
+ destroy?(): void;
1400
+ }
1401
+
1402
+ declare class KeypairEncryptionAdapter implements EncryptionAdapter {
1403
+ readonly name: string;
1404
+ readonly publicKey: Uint8Array;
1405
+ private secretKey;
1406
+ private readonly variant;
1407
+ private readonly context;
1408
+ private constructor();
1409
+ /**
1410
+ * Upload-only adapter — holds only the Public Key.
1411
+ * wrapDek() works normally; unwrapDek() throws (no SK available).
1412
+ */
1413
+ static fromPublicKey(pk: Uint8Array, context: string, variant?: MLKemVariant): KeypairEncryptionAdapter;
1414
+ /**
1415
+ * Full adapter — holds both Public Key and Secret Key.
1416
+ * Both wrapDek() and unwrapDek() work.
1417
+ */
1418
+ static fromKeypair(pk: Uint8Array, sk: Uint8Array, context: string, variant?: MLKemVariant): KeypairEncryptionAdapter;
1419
+ /**
1420
+ * Generate a fresh random ML-KEM keypair.
1421
+ *
1422
+ * Returns the adapter (with both PK+SK) plus the raw keys so the caller
1423
+ * can persist the secret key and share the public key separately.
1424
+ *
1425
+ * @param context Domain-separation string bound into the KEK derivation
1426
+ * @param variant Default: "mlkem768".
1427
+ */
1428
+ static generateKeypair(context: string, variant?: MLKemVariant): {
1429
+ adapter: KeypairEncryptionAdapter;
1430
+ publicKey: Uint8Array;
1431
+ secretKey: Uint8Array;
1432
+ };
1433
+ /**
1434
+ * Deterministically derive a ML-KEM keypair from a BIP-39 mnemonic phrase or hex seed.
1435
+ *
1436
+ * Delegates to MnemonicEncryptionAdapter.intoKeypairEncryptionAdapter() so all
1437
+ * mnemonic/seed handling lives in a single place.
1438
+ *
1439
+ * Same inputs + variant always produce the same keypair.
1440
+ *
1441
+ * `seedHex` may be either 32 bytes (64 hex chars) or 64 bytes (128 hex chars) —
1442
+ * both are expanded to the 64-byte ML-KEM seed via HKDF.
1443
+ *
1444
+ * @param input { mnemonic } (24-word BIP-39) or { seedHex } (32- or 64-byte hex)
1445
+ * @param context Domain-separation string bound into the KEK derivation
1446
+ * @param variant Default: "mlkem768"
1447
+ */
1448
+ static fromMnemonic(input: {
1449
+ mnemonic?: string;
1450
+ seedHex?: string;
1451
+ }, context: string, variant?: MLKemVariant): Promise<KeypairEncryptionAdapter>;
1452
+ /**
1453
+ * Deterministically derive a ML-KEM keypair from a password and salt.
1454
+ *
1455
+ * Delegates to PasswordEncryptionAdapter.intoKeypairEncryptionAdapter() so all
1456
+ * password handling (scrypt params, entropy validation, 64-byte seed derivation)
1457
+ * lives in a single place.
1458
+ *
1459
+ * Same password + salt + variant always produces the same keypair.
1460
+ *
1461
+ * @param password User password (validated for entropy)
1462
+ * @param salt Domain salt — must not be empty
1463
+ * @param context Domain-separation string bound into the KEK derivation
1464
+ * @param variant Default: "mlkem768"
1465
+ * @param params Optional custom scrypt params
1466
+ */
1467
+ static fromPassword(password: string, salt: string, context: string, variant?: MLKemVariant, params?: {
1468
+ N?: number;
1469
+ r?: number;
1470
+ p?: number;
1471
+ }): Promise<KeypairEncryptionAdapter>;
1472
+ /**
1473
+ * Zero the Secret Key bytes and mark this adapter as read-only.
1474
+ * Call when the adapter is no longer needed to minimise the window
1475
+ * during which raw ML-KEM key material sits in GC-reachable memory.
1476
+ * After destroy(), unwrapDek() will throw.
1477
+ */
1478
+ destroy(): void;
1479
+ wrapDek(dek: Uint8Array): Promise<WrappedDekResult>;
1480
+ unwrapDek(data: WrappedDekResult): Promise<Uint8Array>;
1481
+ }
1482
+
1483
+ declare class MnemonicEncryptionAdapter implements EncryptionAdapter {
1484
+ readonly name = "mnemonic";
1485
+ /**
1486
+ * Non-extractable HKDF CryptoKey imported from the BIP-39 / hex seed.
1487
+ * Raw seed bytes are zeroed immediately after import.
1488
+ */
1489
+ private readonly kekMaterialPromise;
1490
+ constructor(input: {
1491
+ mnemonic?: string;
1492
+ seedHex?: string;
1493
+ });
1494
+ wrapDek(dek: Uint8Array): Promise<WrappedDekResult>;
1495
+ unwrapDek({ wrappedDek }: WrappedDekResult): Promise<Uint8Array>;
1496
+ /**
1497
+ * Deterministically derive a ML-KEM keypair from this adapter's key material.
1498
+ *
1499
+ * Uses Web Crypto HKDF to derive a 64-byte ML-KEM seed from the stored
1500
+ * CryptoKey with info="dstorage:mlkem-seed:v1", domain-separated from the
1501
+ * symmetric KEK derivation path. The same derivation applies to all seed
1502
+ * types (mnemonic or hex), producing consistent, domain-separated keypairs.
1503
+ *
1504
+ * @param context Domain-separation string bound into the KEK derivation
1505
+ * @param variant ML-KEM variant. Default: "mlkem768".
1506
+ */
1507
+ intoKeypairEncryptionAdapter(context: string, variant?: MLKemVariant): Promise<KeypairEncryptionAdapter>;
1508
+ }
1509
+
1510
+ /**
1511
+ * Named scrypt parameter presets. Use these at construction time as a
1512
+ * convenience — they expand to concrete N/r/p values. For persistence,
1513
+ * always store the actual values from `getKdfParams()`, not the preset name.
1514
+ *
1515
+ * "v1" — N=131072, 128 MB, ~500ms–1s — OWASP-recommended minimum.
1516
+ * Use for all sensitive data (default).
1517
+ * "v1-lite" — N=65536, 64 MB, ~200–400ms — half the work factor of "v1".
1518
+ * An offline attacker needs half the resources to brute-force the
1519
+ * same password. Use only on memory-constrained devices (mobile,
1520
+ * low-RAM embedded). Prefer "v1" whenever the environment allows.
1521
+ */
1522
+ declare const KDF_PRESETS: {
1523
+ readonly v1: {
1524
+ readonly N: 131072;
1525
+ readonly r: 8;
1526
+ readonly p: 1;
1527
+ };
1528
+ readonly "v1-lite": {
1529
+ readonly N: 65536;
1530
+ readonly r: 8;
1531
+ readonly p: 1;
1532
+ };
1533
+ };
1534
+ type KdfPreset = keyof typeof KDF_PRESETS;
1535
+ /**
1536
+ * The resolved scrypt parameters to store alongside encrypted data.
1537
+ * Interoperable: any scrypt implementation in any language can re-derive
1538
+ * the key from these values without knowledge of this SDK's preset names.
1539
+ */
1540
+ interface StoredKdfParams {
1541
+ /** Always "scrypt" — identifies the KDF algorithm. */
1542
+ kdf: "scrypt";
1543
+ N: number;
1544
+ r: number;
1545
+ p: number;
1546
+ }
1547
+ interface PasswordEncryptionAdapterConfig {
1548
+ /** The user's password. Validated for entropy at construction time. */
1549
+ password: string;
1550
+ /**
1551
+ * Domain salt — REQUIRED, must not be empty.
1552
+ *
1553
+ * Recommended: an app-specific label combined with a per-user identifier,
1554
+ * e.g. `"myapp:v1:alice@example.com"` or `"myapp:v1:" + tenantId`.
1555
+ *
1556
+ * Using a string is convenient; it is UTF-8 encoded before use.
1557
+ * Pass a Uint8Array if you prefer raw bytes.
1558
+ *
1559
+ * Same password + same salt → same seed, forever. Different salts produce
1560
+ * independent seeds even for identical passwords.
1561
+ */
1562
+ salt: string | Uint8Array;
1563
+ /**
1564
+ * Named scrypt preset. Controls N/r/p parameters.
1565
+ * Default: "v1" (N=131072, 128 MB, ~500ms–1s).
1566
+ *
1567
+ * Takes precedence over `params` when both are provided.
1568
+ * Preset names are convenience shorthands — use `getKdfParams()` to get
1569
+ * the actual values for storage.
1570
+ */
1571
+ preset?: KdfPreset;
1572
+ /**
1573
+ * Custom scrypt parameters. Only used when `preset` is not provided.
1574
+ * Prefer `preset` for well-known configurations.
1575
+ */
1576
+ params?: {
1577
+ N?: number;
1578
+ r?: number;
1579
+ p?: number;
1580
+ };
1581
+ /**
1582
+ * Minimum password length. Default: 12 characters.
1583
+ */
1584
+ minPasswordLength?: number;
1585
+ /**
1586
+ * Minimum estimated entropy in bits (charset-based estimate). Default: 60 bits.
1587
+ *
1588
+ * The built-in estimator uses character pool size × length. It catches trivially
1589
+ * weak passwords but does not detect dictionary words. Use `additionalValidators`
1590
+ * for higher assurance.
1591
+ */
1592
+ minEntropyBits?: number;
1593
+ /**
1594
+ * Optional additional password validator functions. Each receives the password
1595
+ * and should throw an Error with a helpful message if the password is rejected.
1596
+ * Run after the built-in checks. Useful for integrating zxcvbn or a blacklist.
1597
+ *
1598
+ * @example
1599
+ * additionalValidators: [(pw) => {
1600
+ * if (zxcvbn(pw).score < 3) throw new Error("Password is too common.");
1601
+ * }]
1602
+ */
1603
+ additionalValidators?: Array<(password: string) => void>;
1604
+ }
1605
+ /** Config for `PasswordEncryptionAdapter.fromKdfParams()` — reconstructs from stored metadata. */
1606
+ interface FromKdfParamsConfig extends StoredKdfParams {
1607
+ password: string;
1608
+ salt: string | Uint8Array;
1609
+ minPasswordLength?: number;
1610
+ minEntropyBits?: number;
1611
+ additionalValidators?: Array<(password: string) => void>;
1612
+ }
1613
+ declare class PasswordEncryptionAdapter implements EncryptionAdapter {
1614
+ readonly name = "password";
1615
+ private readonly salt;
1616
+ private readonly N;
1617
+ private readonly r;
1618
+ private readonly p;
1619
+ /**
1620
+ * Non-extractable HKDF CryptoKey imported from the scrypt output.
1621
+ * The raw scrypt bytes are zeroed immediately after import; this handle is
1622
+ * the only in-memory representation of the secret from this point on.
1623
+ */
1624
+ private readonly kekMaterialPromise;
1625
+ constructor(config: PasswordEncryptionAdapterConfig);
1626
+ /**
1627
+ * Reconstruct an adapter from parameters previously stored via `getKdfParams()`.
1628
+ * Use this when loading existing encrypted data — ensures the exact same N/r/p
1629
+ * are used regardless of what the current SDK defaults are.
1630
+ *
1631
+ * @example
1632
+ * const adapter = PasswordEncryptionAdapter.fromKdfParams({
1633
+ * password,
1634
+ * salt: meta.salt,
1635
+ * kdf: meta.kdf,
1636
+ * N: meta.N,
1637
+ * r: meta.r,
1638
+ * p: meta.p,
1639
+ * });
1640
+ */
1641
+ static fromKdfParams(config: FromKdfParamsConfig): PasswordEncryptionAdapter;
1642
+ /**
1643
+ * Returns the resolved KDF parameters to store alongside encrypted data.
1644
+ *
1645
+ * These values are language- and SDK-agnostic: any scrypt implementation
1646
+ * can re-derive the key from `{ kdf, N, r, p }` + the original salt and
1647
+ * password, without any knowledge of this SDK's preset names.
1648
+ *
1649
+ * @example
1650
+ * const meta = {
1651
+ * ...adapter.getKdfParams(), // { kdf: "scrypt", N: 131072, r: 8, p: 1 }
1652
+ * salt: "myapp:alice@example.com",
1653
+ * };
1654
+ * await db.save({ encryptedData, meta });
1655
+ */
1656
+ getKdfParams(): StoredKdfParams;
1657
+ wrapDek(dek: Uint8Array): Promise<WrappedDekResult>;
1658
+ unwrapDek({ wrappedDek }: WrappedDekResult): Promise<Uint8Array>;
1659
+ /**
1660
+ * Deterministically derive a ML-KEM keypair from this adapter's key material.
1661
+ *
1662
+ * Uses Web Crypto HKDF to derive a 64-byte ML-KEM seed from the stored
1663
+ * CryptoKey, domain-separated from the symmetric KEK derivation path with
1664
+ * info="dstorage:mlkem-seed:v1". This is equivalent to noble's
1665
+ * hkdf(sha256, scryptOutput, undefined, info, 64) but avoids materialising
1666
+ * the raw scrypt output in a JS-accessible variable.
1667
+ *
1668
+ * Same password + salt + variant always produces the same keypair.
1669
+ *
1670
+ * @param context Domain-separation string bound into the KEK derivation
1671
+ * @param variant ML-KEM variant. Default: "mlkem768".
1672
+ */
1673
+ intoKeypairEncryptionAdapter(context: string, variant?: MLKemVariant): Promise<KeypairEncryptionAdapter>;
1674
+ }
1675
+ /**
1676
+ * Generate a cryptographically random password suitable for use with
1677
+ * `PasswordEncryptionAdapter` when post-quantum-safe key derivation is required.
1678
+ *
1679
+ * Produces 32 random bytes (256 bits of real entropy) encoded as a 43-character
1680
+ * base64url string. When combined with `intoKeypairEncryptionAdapter()`, this
1681
+ * provides a fully recoverable path to ML-KEM 192-bit post-quantum security:
1682
+ * the password is the only secret needed to re-derive the same ML-KEM keypair
1683
+ * on any device, without storing the private key itself.
1684
+ *
1685
+ * @example
1686
+ * const password = generatePqsPassword(); // store this securely
1687
+ * const adapter = new PasswordEncryptionAdapter({ password, salt: "myapp:alice" });
1688
+ * const keypairAdapter = await adapter.intoKeypairEncryptionAdapter("myapp:v1");
1689
+ * await sdk.connect(keypairAdapter); // full 192-bit PQ security
1690
+ */
1691
+ declare function generatePqsPassword(): string;
1692
+
1693
+ /**
1694
+ * @dstorage/core — types.ts
1695
+ * Top-level types for the dStorage SDK public API.
1696
+ */
1697
+
1698
+ /**
1699
+ * Minimal logger interface accepted by every SDK class.
1700
+ * Compatible with `console` — pass `logger: console` for zero-boilerplate logging.
1701
+ * Omit the field entirely to suppress all SDK output.
1702
+ */
1703
+ interface Logger {
1704
+ log(component: string, msg: string): void;
1705
+ warn(component: string, msg: string): void;
1706
+ error(component: string, msg: string): void;
1707
+ debug?(component: string, msg: string): void;
1708
+ }
1709
+ /** Wallet connection info returned after connecting */
1710
+ interface WalletInfo {
1711
+ address: string;
1712
+ chainProvider: ChainProviderName;
1713
+ /** The raw signature (or PBKDF2 seed) used to derive the encryption key (kept in memory only) */
1714
+ _signatureHex: string;
1715
+ }
1716
+ /** Configuration passed to dStorage constructor */
1717
+ interface DStorageConfig {
1718
+ /** Storage adapter to use (MockStorageAdapter | ArweaveStorageAdapter | ...) */
1719
+ storageAdapter: StorageAdapter;
1720
+ /**
1721
+ * Chain adapter to use (MockChainAdapter | MidnightChainAdapter | ...).
1722
+ * When omitted the SDK operates in storage-only mode — uploads store to the
1723
+ * storage backend but no on-chain reference is written.
1724
+ */
1725
+ chainAdapter?: ChainAdapter;
1726
+ /**
1727
+ * Encryption adapters that wrap and unwrap per-upload Data Encryption Keys (DEKs).
1728
+ * Each adapter produces an independent wrapped DEK; any of them can independently decrypt.
1729
+ *
1730
+ * Choose the adapter(s) preferred by the user:
1731
+ * PasswordEncryptionAdapter — scrypt-derived from a user password + salt
1732
+ * MnemonicEncryptionAdapter — BIP-39 mnemonic or hex seed (Node.js / facade mode)
1733
+ * KeypairEncryptionAdapter — post-quantum asymmetric (ML-KEM keypair)
1734
+ *
1735
+ * When omitted or empty, no encryption key is available and all uploaded data
1736
+ * will be stored as plaintext (public).
1737
+ *
1738
+ * @example
1739
+ * // Single adapter (most common)
1740
+ * encryptionAdapters: [new PasswordEncryptionAdapter({ password, salt })]
1741
+ *
1742
+ * @example
1743
+ * // Two adapters — data accessible by either password or mnemonic
1744
+ * encryptionAdapters: [
1745
+ * new PasswordEncryptionAdapter({ password, salt }),
1746
+ * new MnemonicEncryptionAdapter({ mnemonic }),
1747
+ * ]
1748
+ */
1749
+ encryptionAdapters?: EncryptionAdapter[];
1750
+ /**
1751
+ * Optional logger for SDK operational output.
1752
+ * Pass `logger: console` to see all output, or inject your own logger.
1753
+ * Omit to suppress all SDK log output.
1754
+ */
1755
+ logger?: Logger;
1756
+ }
1757
+ /**
1758
+ * Payload included in both `StorePartialError.recovery` and the `"stored"`
1759
+ * phase of `StoreProgress`. Contains enough information to retry a failed
1760
+ * chain write via `registerReference()` without re-uploading.
1761
+ *
1762
+ * `keyEnvelope` is the DEK encrypted under the user's KEK — safe to persist
1763
+ * (e.g. in localStorage or a database). It is `undefined` for public uploads
1764
+ * since their on-chain reference does not depend on a content DEK.
1765
+ */
1766
+ interface StoreRecovery {
1767
+ storageId: string;
1768
+ /** Storage provider that holds the content — required by registerReference(). */
1769
+ storageProvider: StorageProviderName;
1770
+ keyEnvelope: string | undefined;
1771
+ /**
1772
+ * BLAKE3 hash of the ciphertext bytes stored at `storageId`, hex-encoded (64 chars).
1773
+ * Pass to `registerReference()` to preserve the on-chain integrity check on the recovered reference.
1774
+ */
1775
+ contentHash?: string;
1776
+ }
1777
+ interface StoreProgress {
1778
+ phase: "encrypting" | "uploading" | "stored" | "finalizing";
1779
+ chunksUploaded: number;
1780
+ totalChunks: number;
1781
+ bytesUploaded: number;
1782
+ totalBytes: number;
1783
+ /**
1784
+ * Present when `phase === "stored"`. Fired after the storage write succeeds
1785
+ * and before the chain write begins — persist this to recover from a partial
1786
+ * failure without re-uploading.
1787
+ */
1788
+ recovery?: StoreRecovery;
1789
+ }
1790
+ interface StoreOptions {
1791
+ /**
1792
+ * Unencrypted key/value tags forwarded to the storage layer (e.g. Arweave tx tags).
1793
+ * Never written on-chain.
1794
+ */
1795
+ tags?: Record<string, string>;
1796
+ /**
1797
+ * Encrypted key/value metadata stored on-chain alongside the key envelope.
1798
+ * Encrypted with the content DEK — only holders of a valid KEK can read it.
1799
+ * Returned in `RetrieveResult.metadata` after decryption.
1800
+ * Not supported for public (`isPublic: true`) stores.
1801
+ */
1802
+ metadata?: Record<string, string>;
1803
+ onProgress?: (progress: StoreProgress) => void;
1804
+ /** When true, content is stored unencrypted and the storageId is written on-chain as plaintext. */
1805
+ isPublic?: boolean;
1806
+ /**
1807
+ * Optional caller-supplied reference ID, forwarded to the chain adapter as
1808
+ * {@link ChainReference.refId}. Adapters that control their own ID generation
1809
+ * (e.g. mock, HTTP gateway) use this as the stored and returned identifier.
1810
+ * Adapters where the on-chain protocol determines the ID (e.g. Midnight)
1811
+ * ignore this field — the chain-assigned ID is returned instead.
1812
+ */
1813
+ refId?: string;
1814
+ }
1815
+ /**
1816
+ * Aggregated cost estimate for a complete store operation.
1817
+ * Built from two quotes — one from the storage adapter and one from the chain adapter.
1818
+ */
1819
+ interface CostEstimate {
1820
+ storageCost: {
1821
+ amount: string;
1822
+ token: TokenSymbol;
1823
+ };
1824
+ /** Chain cost. Undefined when no chain adapter is configured. */
1825
+ chainCost?: {
1826
+ amount: string;
1827
+ token: TokenSymbol;
1828
+ };
1829
+ /** File size in bytes */
1830
+ fileSizeBytes: number;
1831
+ }
1832
+ /** Result returned from dStorage.store() */
1833
+ interface StoreResult {
1834
+ /**
1835
+ * The primary on-chain reference ID.
1836
+ * Undefined when no chain adapter is configured (storage-only mode).
1837
+ */
1838
+ chainRefId?: string;
1839
+ /** The storage network content ID */
1840
+ storageId: string;
1841
+ /** Storage provider used */
1842
+ storageProvider: StorageProviderName;
1843
+ /** Chain provider used. Undefined when no chain adapter is configured. */
1844
+ chainProvider?: ChainProviderName;
1845
+ /** Timestamp */
1846
+ uploadedAt: number;
1847
+ /**
1848
+ * Encryption algorithm used for the stored data and on-chain storageId.
1849
+ * "xchacha20poly1305-v1" for private (encrypted) stores.
1850
+ * Empty string ("") for public (unencrypted) stores.
1851
+ */
1852
+ encryptionScheme: string;
1853
+ /**
1854
+ * Decryption scheme for the stored content.
1855
+ * Present only for private stores in storage-only mode (no chainAdapter).
1856
+ * In chain mode the scheme is recoverable from the on-chain key envelope instead.
1857
+ * Pass this back to retrieveByStorageId() to decrypt locally.
1858
+ */
1859
+ cryptoScheme?: CryptoScheme;
1860
+ /** Estimated cost of the store operation */
1861
+ costEstimate: CostEstimate;
1862
+ }
1863
+ /** Options for dStorage.listReferences() */
1864
+ interface ListReferencesOptions {
1865
+ /** When provided, only references whose refId appears in this array are returned. */
1866
+ refIds?: string[];
1867
+ }
1868
+ /** Options for dStorage.registerReference() */
1869
+ interface RegisterReferenceOptions {
1870
+ /** The pre-existing storage network ID to register. Omit for metadata-only references. */
1871
+ storageId?: string;
1872
+ /**
1873
+ * Storage provider name recorded in the chain reference.
1874
+ * Defaults to the configured `storageAdapter.name`.
1875
+ */
1876
+ storageProvider?: StorageProviderName;
1877
+ /**
1878
+ * Optional caller-supplied reference ID, forwarded to the chain adapter as
1879
+ * {@link ChainReference.refId}. Adapters that control their own ID generation
1880
+ * (e.g. mock, HTTP gateway) use this as the stored and returned identifier.
1881
+ * Adapters where the on-chain protocol determines the ID (e.g. Midnight)
1882
+ * ignore this field — the chain-assigned ID is returned instead.
1883
+ */
1884
+ refId?: string;
1885
+ /**
1886
+ * Encrypted key/value metadata stored on-chain alongside the key envelope.
1887
+ * Encrypted with the content DEK — only holders of a valid KEK can read it.
1888
+ * Returned in `RetrieveResult.metadata` after decryption via retrieveByRefId().
1889
+ */
1890
+ metadata?: Record<string, string>;
1891
+ /**
1892
+ * Recovery: the `keyEnvelope` from a `StorePartialError` (or from the
1893
+ * `"stored"` phase of `onProgress`). When provided, the DEK is unwrapped
1894
+ * from this envelope and used to encrypt the storageId and derive the
1895
+ * ownerSecret — producing a reference identical to what `store()` would have
1896
+ * written, without requiring a re-upload.
1897
+ */
1898
+ keyEnvelope?: string;
1899
+ /**
1900
+ * BLAKE3 hash of the ciphertext bytes at `storageId`, hex-encoded (64 chars).
1901
+ * When passed from `StorePartialError.recovery.contentHash`, this ensures the
1902
+ * recovered reference carries the same on-chain hash as a normal `store()` write.
1903
+ */
1904
+ contentHash?: string;
1905
+ }
1906
+ /** Result returned from dStorage.registerReference() */
1907
+ interface RegisterReferenceResult {
1908
+ /** The on-chain reference ID — use with retrieveByRefId(). */
1909
+ chainRefId: string;
1910
+ }
1911
+ /** Result returned from dStorage.update() */
1912
+ interface UpdateResult {
1913
+ /** Same refId as the input — updated in place. */
1914
+ chainRefId: string;
1915
+ /** StorageId of the newly stored content. */
1916
+ storageId: string;
1917
+ }
1918
+ /** Result returned from dStorage.retrieveByRefId() / retrieveByStorageId() */
1919
+ interface RetrieveResult {
1920
+ /** The raw decrypted bytes */
1921
+ bytes: Uint8Array;
1922
+ /** Decrypted on-chain metadata (empty when none was provided at upload time or when retrieved without a chain reference) */
1923
+ metadata: Record<string, string>;
1924
+ /** Unencrypted tags attached to the storage-layer upload (e.g. Arweave tx tags) */
1925
+ tags: Record<string, string>;
1926
+ }
1927
+ /** AAD for single-shot payload encryption (non-chunked user content). */
1928
+ declare const PAYLOAD_AAD: Uint8Array;
1929
+ /**
1930
+ * AAD for chunked manifest encryption.
1931
+ * Using a distinct label from PAYLOAD_AAD means a ciphertext produced for a
1932
+ * manifest cannot decrypt successfully under PAYLOAD_AAD and vice versa —
1933
+ * manifest detection is cryptographic, not based on JSON shape inspection.
1934
+ */
1935
+ declare const MANIFEST_AAD: Uint8Array;
1936
+ /** AAD for encrypted on-chain metadata (stored in ChainReference.encryptedMetadata). */
1937
+ declare const METADATA_AAD: Uint8Array;
1938
+ /**
1939
+ * HKDF salt for ownerSecret derivation in metadata-only references (no storageId).
1940
+ * Using a fixed non-empty sentinel avoids RFC 5869's empty-salt substitution
1941
+ * (which silently substitutes zeros(32)) and creates a clear domain boundary
1942
+ * from normal-upload ownerSecrets whose salt is the plaintext storageId.
1943
+ */
1944
+ declare const METADATA_ONLY_OWNER_SECRET_SALT: Uint8Array;
1945
+ /**
1946
+ * Per-chunk AAD that binds a ciphertext to its position in a chunked upload.
1947
+ * A malicious gateway swapping two chunks will produce an AEAD auth failure
1948
+ * because the stored AAD won't match the expected index.
1949
+ */
1950
+ declare const chunkAad: (index: number, total: number) => Uint8Array;
1951
+
1952
+ /**
1953
+ * @dstorage/core — metaTx/types.ts
1954
+ *
1955
+ * All public interfaces and type aliases for the MetaTx orchestrator.
1956
+ */
1957
+
1958
+ type MetaTxStepId = "estimate" | "encrypt" | "payment_storage" | "upload" | "chain_reference" | "complete";
1959
+ type MetaTxStepStatus = "pending" | "running" | "done" | "error";
1960
+ interface MetaTxStepState {
1961
+ id: MetaTxStepId;
1962
+ label: string;
1963
+ description: string;
1964
+ status: MetaTxStepStatus;
1965
+ /** Live detail message updated during the step */
1966
+ detail?: string;
1967
+ /** Duration in ms (set when done) */
1968
+ durationMs?: number;
1969
+ startedAt?: number;
1970
+ }
1971
+ interface MetaTxProgress {
1972
+ steps: MetaTxStepState[];
1973
+ currentStepId: MetaTxStepId | null;
1974
+ overallStatus: "idle" | "awaiting_confirmation" | "running" | "complete" | "error";
1975
+ /** Cost estimate — set after 'estimate' step completes */
1976
+ estimate?: CostEstimate;
1977
+ /** Final receipt — set when complete */
1978
+ receipt?: MetaTxReceipt;
1979
+ /** Error message if overallStatus is 'error' */
1980
+ error?: string;
1981
+ }
1982
+ interface MetaTxReceipt {
1983
+ dataId: string;
1984
+ storageId: string;
1985
+ /** Undefined when no chain adapter is configured (storage-only mode). */
1986
+ chainRefId?: string;
1987
+ /** Original file info */
1988
+ file: {
1989
+ name: string;
1990
+ type: string;
1991
+ sizeBytes: number;
1992
+ };
1993
+ /** Payment receipts */
1994
+ storagePayment: PaymentReceipt;
1995
+ /** Undefined when no chain adapter is configured. */
1996
+ chainPayment?: PaymentReceipt;
1997
+ /** Tokens used */
1998
+ storageToken: TokenSymbol;
1999
+ /** Undefined when no chain adapter is configured. */
2000
+ chainToken?: TokenSymbol;
2001
+ /** Contract invoked (if selected) */
2002
+ contract?: {
2003
+ address: string;
2004
+ name: string;
2005
+ };
2006
+ completedAt: number;
2007
+ /** Duration of the full meta-transaction in ms */
2008
+ totalDurationMs: number;
2009
+ }
2010
+ interface MetaTxConfig {
2011
+ /** Optional metadata to attach to the on-chain reference */
2012
+ metadata?: Record<string, string>;
2013
+ /** Selected contract address (from the contract registry) */
2014
+ contractAddress?: string;
2015
+ /** Selected contract name (for display / receipt) */
2016
+ contractName?: string;
2017
+ }
2018
+ /**
2019
+ * Crypto materials for a single upload: a fresh random DEK wrapped in a
2020
+ * key envelope, ready to encrypt payload and storageId.
2021
+ *
2022
+ * For private uploads: uploadScheme encrypts content; dek is the per-upload
2023
+ * Data Encryption Key used both to encrypt content AND to derive
2024
+ * ownerSecret = HKDF(dek, rawStorageId). Any KEK holder can re-derive the
2025
+ * ownerSecret by unwrapping the envelope DEK.
2026
+ * For public uploads: uploadScheme is null; ownerSeed is a random secret wrapped
2027
+ * under every KEK in keyEnvelope, and ownerSecret = HKDF(ownerSeed, rawStorageId).
2028
+ * Any single KEK holder can re-derive the ownerSecret by unwrapping the envelope.
2029
+ */
2030
+ interface UploadCrypto {
2031
+ /** XChaChaScheme built from a fresh random DEK. null for public uploads. */
2032
+ uploadScheme: CryptoScheme | null;
2033
+ /** JSON-encoded KeyEnvelope wrapping the DEK (private) or ownerSeed (public) under every KEK. */
2034
+ keyEnvelope: string;
2035
+ /** Encryption scheme identifier to record on-chain. "" for public uploads. */
2036
+ encryptionScheme: EncryptionScheme;
2037
+ /**
2038
+ * The raw per-upload DEK for private uploads; undefined for public uploads.
2039
+ * Used by MetaTx to derive ownerSecret = HKDF(dek, rawStorageId) after upload.
2040
+ * Not stored anywhere — must not be persisted.
2041
+ */
2042
+ dek?: Uint8Array;
2043
+ /**
2044
+ * The raw ownerSeed for public uploads; undefined for private uploads.
2045
+ * Used by MetaTx to derive ownerSecret = HKDF(ownerSeed, rawStorageId) after upload.
2046
+ * Not stored anywhere — must not be persisted.
2047
+ */
2048
+ ownerSeed?: Uint8Array;
2049
+ }
2050
+ /**
2051
+ * Minimal SDK surface required by MetaTx.
2052
+ * Implemented by DStorage — MetaTx receives the SDK instance directly
2053
+ * rather than individual adapters/keys/address to avoid redundant constructor args.
2054
+ */
2055
+ interface DStorageContext {
2056
+ readonly storageAdapter: StorageAdapter;
2057
+ readonly chainAdapter: ChainAdapter | undefined;
2058
+ /** Wallet address of the connected user, or null if using init() / facade mode. */
2059
+ readonly connectedAddress: string | null;
2060
+ /**
2061
+ * Generate a fresh random DEK, wrap it under the KEK, and return the
2062
+ * upload crypto materials needed to encrypt payload and storageId.
2063
+ * @param isPublic Pass true to skip encryption (returns null scheme + no envelope).
2064
+ */
2065
+ prepareUploadCrypto(isPublic?: boolean): Promise<UploadCrypto>;
2066
+ /** Estimate the full cost (storage + chain) for a given payload size. */
2067
+ estimateCost(sizeBytes: number): Promise<CostEstimate>;
2068
+ }
2069
+
2070
+ /**
2071
+ * @dstorage/core — metaTx/utils.ts
2072
+ *
2073
+ * Helpers used internally by MetaTx and one exported utility.
2074
+ */
2075
+
2076
+ /**
2077
+ * Return the default chain payment token for a given chain provider name.
2078
+ */
2079
+ declare function defaultChainToken(chainProvider: string): TokenSymbol;
2080
+
2081
+ /**
2082
+ * @dstorage/core — metaTx/MetaTx.ts
2083
+ *
2084
+ * The MetaTx orchestrator.
2085
+ *
2086
+ * Presents a single conceptual action to the user while internally executing:
2087
+ * [0] Estimate → compute storage + chain costs
2088
+ * [1] Encrypt → XChaCha20-Poly1305 encrypt the file client-side
2089
+ * [2] PayStorage → simulate storage payment (AR / MOCK)
2090
+ * [3] Upload → upload encrypted blob to decentralised storage
2091
+ * [4] Reference → pay chain fee + write CID + metadata reference on-chain
2092
+ * [✓] Complete → return full receipt
2093
+ *
2094
+ * Usage:
2095
+ * const metaTx = new MetaTx(dStorage);
2096
+ * metaTx.onProgress((progress) => updateUI(progress));
2097
+ * const receipt = await metaTx.execute(file);
2098
+ */
2099
+
2100
+ declare class MetaTx {
2101
+ private sdk;
2102
+ private progressCallback;
2103
+ private steps;
2104
+ private startedAt;
2105
+ constructor(sdk: DStorageContext);
2106
+ /** Register a progress listener. Called after every step state change. */
2107
+ onProgress(cb: (progress: MetaTxProgress) => void): this;
2108
+ execute(file: File, config?: MetaTxConfig): Promise<MetaTxReceipt>;
2109
+ private startStep;
2110
+ private updateStepDetail;
2111
+ private completeStep;
2112
+ private getStep;
2113
+ private emit;
2114
+ }
2115
+
2116
+ /**
2117
+ * @dstorage/core — dStorage.ts
2118
+ *
2119
+ * The main SDK class. Orchestrates:
2120
+ * 1. Encryption adapter key wrapping (@dstorage/encryption + @dstorage/crypto)
2121
+ * 2. Client-side encryption (@dstorage/crypto)
2122
+ * 3. Decentralised storage (@dstorage/storage)
2123
+ * 4. On-chain reference writing (@dstorage/chain)
2124
+ *
2125
+ * Developer API:
2126
+ * const ds = new DStorage(config);
2127
+ * await ds.init();
2128
+ * const { chainRefId, storageId } = await ds.store(new TextEncoder().encode("hello"));
2129
+ * const { bytes } = await ds.retrieveByRefId(chainRefId);
2130
+ * await ds.listReferences();
2131
+ * await ds.removeReference(chainRefId);
2132
+ */
2133
+
2134
+ declare class DStorage implements DStorageContext {
2135
+ private config;
2136
+ private wallet;
2137
+ /** Encryption adapters — each wraps/unwraps per-upload DEKs using its own algorithm. */
2138
+ private _encryptionProviders;
2139
+ private _initialized;
2140
+ private readonly logger;
2141
+ constructor(config: DStorageConfig);
2142
+ get storageAdapter(): StorageAdapter;
2143
+ get chainAdapter(): ChainAdapter | undefined;
2144
+ /**
2145
+ * Initialize the SDK:
2146
+ * 1. Initialize the chain adapter wallet (if supported), and
2147
+ * deploy a new DataRegistry contract, or connect to an existing one.
2148
+ * 2. Derive an encryption key from the chain adapter's credentials (if supported).
2149
+ *
2150
+ * Returns the address of the DataRegistry contract in use.
2151
+ * Call this instead of connect() when using MidnightChainAdapter directly.
2152
+ */
2153
+ init(): Promise<string | undefined>;
2154
+ /** Tear down active state and clear all in-memory key material. */
2155
+ destroy(): void;
2156
+ get isConnected(): boolean;
2157
+ get connectedAddress(): string | null;
2158
+ /**
2159
+ * Encrypt content client-side, store to decentralised storage,
2160
+ * and write a cryptographic reference on-chain.
2161
+ *
2162
+ * Files larger than CHUNK_SIZE (10 MB) are automatically split into chunks,
2163
+ * each encrypted and stored independently. A manifest file ties them together.
2164
+ * Only the manifest's storageId is written on-chain.
2165
+ *
2166
+ * @param bytes Uint8Array to store
2167
+ * @param options Optional StoreOptions (metadata, onProgress, isPublic, refId)
2168
+ * @returns StoreResult containing the chainRefId/storageId needed to retrieve later
2169
+ */
2170
+ store(bytes: Uint8Array, options?: StoreOptions): Promise<StoreResult>;
2171
+ /**
2172
+ * Register a pre-existing storageId as a new on-chain reference.
2173
+ *
2174
+ * Use this when data has already been uploaded to the storage network by
2175
+ * other means (e.g. a third-party tool or a separate pipeline). The content
2176
+ * is not touched — only the chain reference is created.
2177
+ *
2178
+ * A fresh DEK is generated solely to encrypt the storageId and derive the
2179
+ * ownerSecret. The resulting reference round-trips through retrieveByRefId()
2180
+ * exactly like one created by store().
2181
+ *
2182
+ * Note: chunked manifests are not handled here. For large pre-existing
2183
+ * uploads already split into chunks, register the manifest storageId.
2184
+ */
2185
+ registerReference(options?: RegisterReferenceOptions): Promise<RegisterReferenceResult>;
2186
+ /**
2187
+ * Store new content and update an existing on-chain reference in place.
2188
+ *
2189
+ * Ownership is proved by re-deriving the ownerSecret from the existing
2190
+ * reference — the same mechanism used by removeReference(). A fresh DEK is
2191
+ * generated for the new content; the previous version is not modified and remains
2192
+ * independently decryptable if the caller retained the old storageId.
2193
+ *
2194
+ * Note: chunking is not applied here. For large files use store() to get a
2195
+ * new chunked reference, then removeReference() on the old one.
2196
+ *
2197
+ * @param refId The chain reference to update (returned by a prior store/registerReference).
2198
+ * @param bytes New content to encrypt and store.
2199
+ * @param options Optional StoreOptions. isPublic is ignored.
2200
+ */
2201
+ update(refId: string, bytes: Uint8Array, options?: StoreOptions): Promise<UpdateResult>;
2202
+ /**
2203
+ * Retry only the on-chain reference write after a failed `update()` call.
2204
+ *
2205
+ * Use this when `update()` throws a `StorePartialError` — meaning the new
2206
+ * content was stored successfully but the chain write failed. Call with the
2207
+ * `refId` you passed to `update()` and the `err.recovery` from the caught
2208
+ * error (or the `recovery` emitted via `onProgress` at phase `"stored"`).
2209
+ *
2210
+ * The new content is already in storage; this method re-derives all chain
2211
+ * write parameters from the recovery envelope without re-uploading.
2212
+ */
2213
+ retryUpdate(refId: string, recovery: StoreRecovery): Promise<UpdateResult>;
2214
+ /**
2215
+ * Rotate the encryption adapters protecting an existing reference without
2216
+ * re-uploading the content.
2217
+ *
2218
+ * Useful when you want to:
2219
+ * - Change a password: configure [newPassword, mnemonic] and call rotateKeys().
2220
+ * The mnemonic unwraps the old DEK, the new envelope is wrapped under both
2221
+ * new adapters, and the old password wrapper is dropped.
2222
+ * - Add or remove adapters: any single adapter that matches a wrapper in the
2223
+ * existing key envelope can authorise the rotation. The resulting envelope
2224
+ * is wrapped under exactly the adapters currently configured on this SDK.
2225
+ *
2226
+ * The content in storage is not touched — only the on-chain key envelope is
2227
+ * updated. writtenAt is preserved to reflect the original upload time.
2228
+ */
2229
+ rotateKeys(refId: string): Promise<void>;
2230
+ /**
2231
+ * Retrieve and decrypt data by its storageId.
2232
+ * Decryption happens locally — the SDK never sends plaintext anywhere.
2233
+ *
2234
+ * Automatically detects chunked manifests and reassembles the original file.
2235
+ *
2236
+ * @param storageId The storageId returned from store()
2237
+ */
2238
+ retrieveByStorageId(storageId: string, dekScheme?: CryptoScheme, contentHash?: string): Promise<RetrieveResult>;
2239
+ /**
2240
+ * Unwrap the data DEK from a key envelope and return an XChaChaScheme built from it.
2241
+ * Throws if the KEK is not available or the envelope cannot be parsed.
2242
+ * Only valid for private uploads (envelope.wrappers must be present).
2243
+ */
2244
+ private _getDekScheme;
2245
+ /**
2246
+ * Unwrap the raw DEK bytes from a key envelope using the available KEKs.
2247
+ * The ownerSecret for the reference can be re-derived as HKDF(dek, rawStorageId).
2248
+ * Throws if no wrapper matches any available KEK.
2249
+ */
2250
+ private _unwrapDek;
2251
+ /**
2252
+ * Compute the ownerSecret for an existing on-chain reference.
2253
+ * Used by removeReference/updateReference to derive the ZK witness secret.
2254
+ *
2255
+ * Flow:
2256
+ * 1. Read the reference from chain to get keyEnvelope + storageId
2257
+ * 2. Unwrap the DEK from keyEnvelope using available KEKs
2258
+ * 3. Recover raw storageId (decrypt with DEK if private, plaintext if public)
2259
+ * 4. Return HKDF-SHA256(dek, rawStorageId) for private, or HKDF-SHA256(ownerSeed, rawStorageId) for public
2260
+ */
2261
+ private _computeOwnerSecret;
2262
+ private _decryptAndReassemble;
2263
+ /**
2264
+ * Retrieve and decrypt data using only its on-chain reference ID.
2265
+ *
2266
+ * Flow:
2267
+ * 1. Look up the reference on-chain by refId to obtain the storage network ID.
2268
+ * 2. Fetch the blob from the storage network.
2269
+ * 3. Decrypt locally if an encryption key is available.
2270
+ *
2271
+ * Requires the chain adapter to implement readReference() (part of the
2272
+ * ChainAdapter interface — shared by MidnightChainAdapter, MockChainAdapter, etc.).
2273
+ *
2274
+ * @param refId The chainRefId returned from store()
2275
+ */
2276
+ retrieveByRefId(refId: string): Promise<RetrieveResult>;
2277
+ /**
2278
+ * List references currently available from the configured chain adapter.
2279
+ */
2280
+ listReferences(options?: ListReferencesOptions): Promise<DataReferenceSummary[]>;
2281
+ /**
2282
+ * Remove a reference from the on-chain registry.
2283
+ * Only the owner of the reference can successfully call this — the chain
2284
+ * enforces ownership via ZK proof using the witness-derived ownerSecret.
2285
+ */
2286
+ removeReference(refId: string): Promise<void>;
2287
+ /**
2288
+ * Estimate the full cost (storage + chain) for a given payload size before committing.
2289
+ */
2290
+ estimateCost(sizeBytes: number): Promise<CostEstimate>;
2291
+ /**
2292
+ * Execute a full meta-transaction for a file:
2293
+ * estimate → encrypt → pay storage → upload → pay chain → write reference
2294
+ *
2295
+ * Presents the entire flow as a single action with step-by-step progress.
2296
+ *
2297
+ * @param file The File to encrypt and store
2298
+ * @param onProgress Callback fired on every step state change
2299
+ * @param config Optional token overrides and metadata
2300
+ */
2301
+ executeMetaTransaction(file: File, onProgress: (progress: MetaTxProgress) => void, config?: MetaTxConfig): Promise<MetaTxReceipt>;
2302
+ /**
2303
+ * Generate a fresh random DEK, wrap it under the KEK(s), and return the crypto
2304
+ * materials needed by MetaTx to encrypt payload and storageId.
2305
+ *
2306
+ * For private stores: the DEK is wrapped under every available KEK. The ownerSecret
2307
+ * can later be re-derived as HKDF(dek, rawStorageId) by any KEK holder.
2308
+ * For public stores: a random ownerSeed is generated and wrapped under all KEKs (same pattern).
2309
+ */
2310
+ prepareUploadCrypto(isPublic?: boolean): Promise<UploadCrypto>;
2311
+ /**
2312
+ * Upload large content by splitting into CHUNK_SIZE pieces, encrypting each
2313
+ * independently, and storing a manifest that ties them together.
2314
+ * Only the manifest's storageId is written on-chain.
2315
+ */
2316
+ private _uploadChunked;
2317
+ /**
2318
+ * Reassemble a chunked file from its manifest.
2319
+ * Fetches and decrypts each chunk sequentially to bound memory usage.
2320
+ */
2321
+ private _retrieveChunked;
2322
+ private assertConnected;
2323
+ }
2324
+
2325
+ /**
2326
+ * @dstorage/core — chunked.ts
2327
+ *
2328
+ * Defines the manifest shape and helpers for large-file (chunked) uploads.
2329
+ * SDK-level chunking splits files into CHUNK_SIZE pieces before encryption,
2330
+ * bounding peak memory usage to ~2× the chunk size regardless of file size.
2331
+ */
2332
+
2333
+ /**
2334
+ * Nominal SDK chunk size: 10 MB per piece.
2335
+ *
2336
+ * Each chunk becomes one independent Arweave transaction, so larger chunks
2337
+ * mean fewer transactions and therefore less total base-fee overhead.
2338
+ * 10 MB sits comfortably below the arweave.net gateway POST limit (~12 MB)
2339
+ * while halving transaction count compared to 5 MB.
2340
+ *
2341
+ * The Arweave adapter uses getUploader() which sends each transaction's data
2342
+ * in 256 KB network slices, so 10 MB chunks upload reliably without hitting
2343
+ * any HTTP body size limit.
2344
+ */
2345
+ declare const CHUNK_SIZE: number;
2346
+ interface ChunkEntry {
2347
+ index: number;
2348
+ storageId: string;
2349
+ /** Actual byte count in this chunk (last chunk may be smaller). */
2350
+ size: number;
2351
+ }
2352
+ interface ChunkManifest {
2353
+ v: 1;
2354
+ type: "dstorage-chunked-manifest";
2355
+ totalSize: number;
2356
+ chunkSize: number;
2357
+ chunkCount: number;
2358
+ provider: StorageProviderName;
2359
+ chunks: ChunkEntry[];
2360
+ }
2361
+ declare function isManifest(payload: unknown): payload is ChunkManifest;
2362
+
2363
+ declare const CoreErrorCode: {
2364
+ readonly METADATA_WITH_PUBLIC_UPLOAD: 10001;
2365
+ readonly UPLOAD_NO_PROVIDERS: 10002;
2366
+ readonly PUBLIC_UPLOAD_REQUIRES_SEED_PROVIDER: 10003;
2367
+ readonly CHAIN_WRITE_FAILED: 10004;
2368
+ readonly REGISTER_REF_REQUIRES_CHAIN: 10010;
2369
+ readonly REGISTER_REF_REQUIRES_ENCRYPTION: 10011;
2370
+ readonly UPDATE_UPLOAD_REQUIRES_CHAIN: 10020;
2371
+ readonly UPDATE_UPLOAD_NOT_SUPPORTED: 10021;
2372
+ readonly UPDATE_UPLOAD_REQUIRES_ENCRYPTION: 10022;
2373
+ readonly ROTATE_KEYS_REQUIRES_CHAIN: 10023;
2374
+ readonly ROTATE_KEYS_NOT_SUPPORTED: 10024;
2375
+ readonly ROTATE_KEYS_REQUIRES_ENCRYPTION: 10025;
2376
+ readonly DECRYPT_NO_PROVIDERS: 10030;
2377
+ readonly DECRYPT_ENVELOPE_EMPTY: 10031;
2378
+ readonly DECRYPT_ENVELOPE_MALFORMED: 10032;
2379
+ readonly DECRYPT_NO_WRAPPER_MATCHED: 10033;
2380
+ readonly UNWRAP_DEK_NO_PROVIDERS: 10034;
2381
+ readonly UNWRAP_DEK_ENVELOPE_EMPTY: 10035;
2382
+ readonly UNWRAP_DEK_ENVELOPE_MALFORMED: 10036;
2383
+ readonly UNWRAP_DEK_NO_WRAPPER_MATCHED: 10037;
2384
+ readonly DECRYPT_PAYLOAD_FAILED: 10038;
2385
+ readonly RETRIEVE_BY_REF_ID_REQUIRES_CHAIN: 10050;
2386
+ readonly REF_NOT_FOUND: 10051;
2387
+ readonly STORAGE_ADAPTER_MISMATCH: 10052;
2388
+ readonly RETRIEVE_BY_REF_ID_ENVELOPE_EMPTY: 10053;
2389
+ readonly CONTENT_HASH_MISMATCH: 10054;
2390
+ readonly LIST_REFS_REQUIRES_CHAIN: 10060;
2391
+ readonly LIST_REFS_NOT_SUPPORTED: 10061;
2392
+ readonly REMOVE_REF_REQUIRES_CHAIN: 10070;
2393
+ readonly REMOVE_REF_NOT_SUPPORTED: 10071;
2394
+ readonly META_TX_REQUIRES_ENCRYPTION: 10080;
2395
+ readonly PREPARE_UPLOAD_NO_PROVIDERS: 10081;
2396
+ readonly MANIFEST_INVALID_STRUCTURE: 10090;
2397
+ readonly MANIFEST_CHUNK_COUNT_MISMATCH: 10091;
2398
+ readonly MANIFEST_NOT_CONTIGUOUS: 10092;
2399
+ readonly DECRYPT_CHUNK_FAILED: 10093;
2400
+ readonly CHUNK_OVERFLOWS_TOTAL_SIZE: 10094;
2401
+ readonly REASSEMBLY_SIZE_MISMATCH: 10095;
2402
+ readonly NOT_INITIALIZED: 10100;
2403
+ readonly META_TX_UNKNOWN_STEP: 10200;
2404
+ readonly UNKNOWN_ERROR: 10999;
2405
+ };
2406
+ type CoreErrorCode = (typeof CoreErrorCode)[keyof typeof CoreErrorCode];
2407
+ /**
2408
+ * Thrown when `store()` succeeds at the storage layer but fails to write the
2409
+ * on-chain reference. The content is permanently on the storage network — use
2410
+ * `err.recovery` with `registerReference()` to retry only the chain write.
2411
+ */
2412
+ declare class StorePartialError extends DStorageError {
2413
+ readonly recovery: StoreRecovery;
2414
+ constructor(recovery: StoreRecovery);
2415
+ }
2416
+ declare function isStorePartialError(err: unknown): err is StorePartialError;
2417
+
2418
+ export { ARWEAVE_LOCAL, type ArweaveBundlerAdapterConfig, ArweaveBundlerStorageAdapter, type ArweaveLocalAdapterConfig, type ArweaveLocalBalance, ArweaveLocalError, ArweaveLocalHelper, type ArweaveLocalHelperConfig, type ArweaveLocalInfo, ArweaveLocalStorageAdapter, ArweavePaymentAdapter, ArweaveStorageAdapter, CHUNK_SIZE, type ChunkEntry, type ChunkManifest, CoreErrorCode, type CostEstimate, CryptoErrorCode, type CryptoScheme, DStorage, type DStorageConfig, type DStorageContext, DStorageError, type EncryptionAdapter, EncryptionErrorCode, type EncryptionScheme, type FromKdfParamsConfig, KDF_PRESETS, type KdfPreset, KeyDeriver, type KeyEnvelope, type KeyWrapper, KeypairEncryptionAdapter, type ListReferencesOptions, type Logger, MANIFEST_AAD, METADATA_AAD, METADATA_ONLY_OWNER_SECRET_SALT, type MLKemVariant, ManagedPaymentAdapter, MetaTx, type MetaTxConfig, type MetaTxProgress, type MetaTxReceipt, type MetaTxStepId, type MetaTxStepState, type MetaTxStepStatus, MnemonicEncryptionAdapter, PAYLOAD_AAD, PasswordEncryptionAdapter, type PasswordEncryptionAdapterConfig, type RegisterReferenceOptions, type RegisterReferenceResult, type RetrieveResult, type StoreOptions, StorePartialError, type StoreProgress, type StoreRecovery, type StoreResult, type StoredKdfParams, type UpdateResult, type UploadCrypto, type WalletInfo, type WrappedDekResult, type XChaChaPayload, XChaChaScheme, arlocalGateway, base64urlToBytes, buildKeyEnvelope, bytesToBase64url, chunkAad, computeBlake3, computeBlake3Hex, decryptStorageIdXChaCha, decryptXChaCha, defaultChainToken, deriveKek, deriveOwnerSecret, deriveSymmetricKeyFromSeed, deserializeXChaChaPayload, encryptStorageIdXChaCha, encryptXChaCha, findWrapper, generateDek, generatePqsPassword, hexToBytes, isDStorageError, isManifest, isStorePartialError, mlkemGenerateKeypair, mlkemGenerateKeypairFromSeed, mlkemUnwrapDek, mlkemWrapDek, parseKeyEnvelope, serializeKeyEnvelope, serializeXChaChaPayload, unwrapKey, wrapKey };