@dignetwork/dig-sdk 0.0.1-alpha.99 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/LICENSE +21 -7
  2. package/README.md +267 -0
  3. package/dist/adapters.cjs +315 -0
  4. package/dist/adapters.cjs.map +1 -0
  5. package/dist/adapters.d.cts +20 -0
  6. package/dist/adapters.d.ts +20 -0
  7. package/dist/adapters.js +306 -0
  8. package/dist/adapters.js.map +1 -0
  9. package/dist/dev-shim-Bgw8X2E9.d.cts +118 -0
  10. package/dist/dev-shim-Bgw8X2E9.d.ts +118 -0
  11. package/dist/dig-client-entry-BIzuZ7Rs.d.cts +263 -0
  12. package/dist/dig-client-entry-BIzuZ7Rs.d.ts +263 -0
  13. package/dist/dig-client.cjs +330 -0
  14. package/dist/dig-client.cjs.map +1 -0
  15. package/dist/dig-client.d.cts +1 -0
  16. package/dist/dig-client.d.ts +1 -0
  17. package/dist/dig-client.js +319 -0
  18. package/dist/dig-client.js.map +1 -0
  19. package/dist/index.cjs +754 -0
  20. package/dist/index.cjs.map +1 -0
  21. package/dist/index.d.cts +192 -0
  22. package/dist/index.d.ts +192 -5
  23. package/dist/index.js +731 -19
  24. package/dist/index.js.map +1 -0
  25. package/dist/next.cjs +326 -0
  26. package/dist/next.cjs.map +1 -0
  27. package/dist/next.d.cts +23 -0
  28. package/dist/next.d.ts +23 -0
  29. package/dist/next.js +319 -0
  30. package/dist/next.js.map +1 -0
  31. package/dist/spend.cjs +14 -0
  32. package/dist/spend.cjs.map +1 -0
  33. package/dist/spend.d.cts +1 -0
  34. package/dist/spend.d.ts +1 -0
  35. package/dist/spend.js +3 -0
  36. package/dist/spend.js.map +1 -0
  37. package/dist/vite.cjs +338 -0
  38. package/dist/vite.cjs.map +1 -0
  39. package/dist/vite.d.cts +35 -0
  40. package/dist/vite.d.ts +35 -0
  41. package/dist/vite.js +332 -0
  42. package/dist/vite.js.map +1 -0
  43. package/package.json +87 -59
  44. package/vendor/PROVENANCE.md +102 -0
  45. package/vendor/dig_client.d.ts +150 -0
  46. package/vendor/dig_client.mjs +805 -0
  47. package/vendor/dig_client_bg.wasm +0 -0
  48. package/dist/DataIntegrityTree/DataIntegrityTree.d.ts +0 -163
  49. package/dist/DataIntegrityTree/DataIntegrityTree.d.ts.map +0 -1
  50. package/dist/DataIntegrityTree/DataIntegrityTree.js +0 -707
  51. package/dist/DataIntegrityTree/DataLayerError.d.ts +0 -6
  52. package/dist/DataIntegrityTree/DataLayerError.d.ts.map +0 -1
  53. package/dist/DataIntegrityTree/DataLayerError.js +0 -17
  54. package/dist/DataIntegrityTree/index.d.ts +0 -2
  55. package/dist/DataIntegrityTree/index.d.ts.map +0 -1
  56. package/dist/DataIntegrityTree/index.js +0 -17
  57. package/dist/DigNetwork/ContentServer.d.ts +0 -31
  58. package/dist/DigNetwork/ContentServer.d.ts.map +0 -1
  59. package/dist/DigNetwork/ContentServer.js +0 -176
  60. package/dist/DigNetwork/DigChallenge.d.ts +0 -82
  61. package/dist/DigNetwork/DigChallenge.d.ts.map +0 -1
  62. package/dist/DigNetwork/DigChallenge.js +0 -144
  63. package/dist/DigNetwork/DigNetwork.d.ts +0 -14
  64. package/dist/DigNetwork/DigNetwork.d.ts.map +0 -1
  65. package/dist/DigNetwork/DigNetwork.js +0 -169
  66. package/dist/DigNetwork/DigPeer.d.ts +0 -24
  67. package/dist/DigNetwork/DigPeer.d.ts.map +0 -1
  68. package/dist/DigNetwork/DigPeer.js +0 -118
  69. package/dist/DigNetwork/IncentiveServer.d.ts +0 -13
  70. package/dist/DigNetwork/IncentiveServer.d.ts.map +0 -1
  71. package/dist/DigNetwork/IncentiveServer.js +0 -76
  72. package/dist/DigNetwork/PropagationServer.d.ts +0 -81
  73. package/dist/DigNetwork/PropagationServer.d.ts.map +0 -1
  74. package/dist/DigNetwork/PropagationServer.js +0 -563
  75. package/dist/DigNetwork/index.d.ts +0 -4
  76. package/dist/DigNetwork/index.d.ts.map +0 -1
  77. package/dist/DigNetwork/index.js +0 -19
  78. package/dist/blockchain/DataStore.d.ts +0 -67
  79. package/dist/blockchain/DataStore.d.ts.map +0 -1
  80. package/dist/blockchain/DataStore.js +0 -413
  81. package/dist/blockchain/DataStoreSerializer.d.ts +0 -52
  82. package/dist/blockchain/DataStoreSerializer.d.ts.map +0 -1
  83. package/dist/blockchain/DataStoreSerializer.js +0 -109
  84. package/dist/blockchain/FullNodePeer.d.ts +0 -31
  85. package/dist/blockchain/FullNodePeer.d.ts.map +0 -1
  86. package/dist/blockchain/FullNodePeer.js +0 -295
  87. package/dist/blockchain/ServerCoin.d.ts +0 -29
  88. package/dist/blockchain/ServerCoin.d.ts.map +0 -1
  89. package/dist/blockchain/ServerCoin.js +0 -324
  90. package/dist/blockchain/Wallet.d.ts +0 -28
  91. package/dist/blockchain/Wallet.d.ts.map +0 -1
  92. package/dist/blockchain/Wallet.js +0 -253
  93. package/dist/blockchain/coins.d.ts +0 -6
  94. package/dist/blockchain/coins.d.ts.map +0 -1
  95. package/dist/blockchain/coins.js +0 -102
  96. package/dist/blockchain/index.d.ts +0 -8
  97. package/dist/blockchain/index.d.ts.map +0 -1
  98. package/dist/blockchain/index.js +0 -36
  99. package/dist/index.d.ts.map +0 -1
  100. package/dist/prompts.d.ts +0 -21
  101. package/dist/prompts.d.ts.map +0 -1
  102. package/dist/prompts.js +0 -149
  103. package/dist/types.d.ts +0 -64
  104. package/dist/types.d.ts.map +0 -1
  105. package/dist/types.js +0 -2
  106. package/dist/utils/ContentScanner.d.ts +0 -63
  107. package/dist/utils/ContentScanner.d.ts.map +0 -1
  108. package/dist/utils/ContentScanner.js +0 -175
  109. package/dist/utils/Environment.d.ts +0 -18
  110. package/dist/utils/Environment.d.ts.map +0 -1
  111. package/dist/utils/Environment.js +0 -85
  112. package/dist/utils/FileCache.d.ts +0 -11
  113. package/dist/utils/FileCache.d.ts.map +0 -1
  114. package/dist/utils/FileCache.js +0 -58
  115. package/dist/utils/FileTransfer.d.ts +0 -47
  116. package/dist/utils/FileTransfer.d.ts.map +0 -1
  117. package/dist/utils/FileTransfer.js +0 -209
  118. package/dist/utils/NconfManager.d.ts +0 -11
  119. package/dist/utils/NconfManager.d.ts.map +0 -1
  120. package/dist/utils/NconfManager.js +0 -56
  121. package/dist/utils/StoreArchiveManager.d.ts +0 -45
  122. package/dist/utils/StoreArchiveManager.d.ts.map +0 -1
  123. package/dist/utils/StoreArchiveManager.js +0 -153
  124. package/dist/utils/asyncPool.d.ts +0 -9
  125. package/dist/utils/asyncPool.d.ts.map +0 -1
  126. package/dist/utils/asyncPool.js +0 -23
  127. package/dist/utils/config.d.ts +0 -68
  128. package/dist/utils/config.d.ts.map +0 -1
  129. package/dist/utils/config.js +0 -223
  130. package/dist/utils/connectionUtils.d.ts +0 -10
  131. package/dist/utils/connectionUtils.d.ts.map +0 -1
  132. package/dist/utils/connectionUtils.js +0 -18
  133. package/dist/utils/credentialsUtils.d.ts +0 -8
  134. package/dist/utils/credentialsUtils.d.ts.map +0 -1
  135. package/dist/utils/credentialsUtils.js +0 -122
  136. package/dist/utils/directoryUtils.d.ts +0 -9
  137. package/dist/utils/directoryUtils.d.ts.map +0 -1
  138. package/dist/utils/directoryUtils.js +0 -110
  139. package/dist/utils/encryption.d.ts +0 -8
  140. package/dist/utils/encryption.d.ts.map +0 -1
  141. package/dist/utils/encryption.js +0 -55
  142. package/dist/utils/hashUtils.d.ts +0 -8
  143. package/dist/utils/hashUtils.d.ts.map +0 -1
  144. package/dist/utils/hashUtils.js +0 -44
  145. package/dist/utils/index.d.ts +0 -14
  146. package/dist/utils/index.d.ts.map +0 -1
  147. package/dist/utils/index.js +0 -29
  148. package/dist/utils/merkle.d.ts +0 -2
  149. package/dist/utils/merkle.d.ts.map +0 -1
  150. package/dist/utils/merkle.js +0 -28
  151. package/dist/utils/network.d.ts +0 -2
  152. package/dist/utils/network.d.ts.map +0 -1
  153. package/dist/utils/network.js +0 -54
  154. package/dist/utils/spinnerUtils.d.ts +0 -2
  155. package/dist/utils/spinnerUtils.d.ts.map +0 -1
  156. package/dist/utils/spinnerUtils.js +0 -47
  157. package/dist/utils/ssl.d.ts +0 -5
  158. package/dist/utils/ssl.d.ts.map +0 -1
  159. package/dist/utils/ssl.js +0 -50
  160. package/dist/utils/validationUtils.d.ts +0 -9
  161. package/dist/utils/validationUtils.d.ts.map +0 -1
  162. package/dist/utils/validationUtils.js +0 -55
@@ -0,0 +1,263 @@
1
+ /** The read-crypto functions the SDK uses from the dig_client WASM. */
2
+ interface DigClientWasm {
3
+ /** `retrieval_key = SHA-256(canonical rootless urn)`, lowercase hex. Empty key ⇒ index.html. */
4
+ retrievalKey(storeIdHex: string, resourceKey: string): string;
5
+ /** Derive the 32-byte AES-256 content key (lowercase hex). `saltHex` for a private store. */
6
+ deriveKey(storeIdHex: string, resourceKey: string, saltHex?: string | null): string;
7
+ /**
8
+ * Verify `ciphertext` is included under `trustedRootHex` via the base64 merkle `proofB64`.
9
+ * Returns true on success, false on ANY verification failure (a decoy returns false rather than
10
+ * throwing). Throws only on malformed inputs.
11
+ */
12
+ verifyInclusion(ciphertext: Uint8Array, proofB64: string, trustedRootHex: string): boolean;
13
+ /** AES-256-GCM-SIV-open a single chunk under an explicit 32-byte `keyHex`. Throws on tag fail. */
14
+ decryptChunk(keyHex: string, ciphertext: Uint8Array): Uint8Array;
15
+ /**
16
+ * Full read pipeline: gate (inclusion) then decrypt (URN key, split by `chunkLens`), returning
17
+ * plaintext bytes. `chunkLens` may be null/empty for a single-chunk resource.
18
+ */
19
+ decryptResource(storeIdHex: string, resourceKey: string, ciphertext: Uint8Array, proofB64: string, trustedRootHex: string, saltHex?: string | null, chunkLens?: Uint32Array | null): Uint8Array;
20
+ /** As `decryptResource`, returning UTF-8 text. */
21
+ decryptResourceToText(storeIdHex: string, resourceKey: string, ciphertext: Uint8Array, proofB64: string, trustedRootHex: string, saltHex?: string | null, chunkLens?: Uint32Array | null): string;
22
+ /** Seal a resource's plaintext as one GCM-SIV blob under its per-URN key (the encrypt inverse). */
23
+ encryptResource(storeIdHex: string, resourceKey: string, plaintext: Uint8Array, saltHex?: string | null): Uint8Array;
24
+ /** Reconstruct the canonical rootless URN string. */
25
+ reconstructUrn(storeIdHex: string, resourceKey: string): string;
26
+ /** Reconstruct a root-pinned display URN string. */
27
+ reconstructUrnWithRoot(storeIdHex: string, rootHex: string, resourceKey: string): string;
28
+ /** Library version (matches the crate version). */
29
+ version(): string;
30
+ }
31
+
32
+ /** A normalized `{ publicKey, signature }` pair from a wallet sign, both as `0x`-prefixed hex. */
33
+ interface SignResult {
34
+ /** The signing public key (synthetic BLS key), `0x`-prefixed hex. */
35
+ publicKey: string | null;
36
+ /** The BLS signature, `0x`-prefixed hex (or the raw wallet string). */
37
+ signature: string | null;
38
+ }
39
+ /**
40
+ * The minimal injected-provider contract the SDK detects on `window.chia` (the DIG Browser's
41
+ * in-process wallet, or a compatible CHIP-0002 extension). Mirrors the DIG Browser provider:
42
+ * `request({ method, params })` returns the wallet's `data`; `connect(eager)` blocks on per-origin
43
+ * approval; `on`/`off` are EIP-1193-style event hooks.
44
+ */
45
+ interface InjectedChiaProvider {
46
+ /** Unspoofable marker the DIG Browser provider sets; the SDK prefers a provider that has it. */
47
+ isDIG?: boolean;
48
+ /** Some providers expose a connected flag. */
49
+ isConnected?: boolean;
50
+ /** One CHIP-0002 RPC. Bare names auto-prefix to `chip0002_`; `chia_*` passes through. */
51
+ request(args: {
52
+ method: string;
53
+ params?: unknown;
54
+ }): Promise<unknown>;
55
+ /** Ask the wallet to approve this origin. Blocks until approved/rejected. */
56
+ connect?(eager?: boolean): Promise<unknown>;
57
+ on?(event: string, fn: (data: unknown) => void): void;
58
+ off?(event: string, fn: (data: unknown) => void): void;
59
+ }
60
+ declare global {
61
+ var chia: InjectedChiaProvider | undefined;
62
+ interface Window {
63
+ chia?: InjectedChiaProvider;
64
+ }
65
+ }
66
+ /** Which wallet transport is backing a `ChiaProvider`. */
67
+ type WalletBackend = "injected" | "walletconnect";
68
+ /** A connected wallet session, returned by `ChiaProvider.connect()`. */
69
+ interface WalletSession {
70
+ /** The transport backing this session. */
71
+ backend: WalletBackend;
72
+ /** The CAIP-2 chain id (e.g. "chia:mainnet"). */
73
+ chain: string;
74
+ /**
75
+ * The session topic. For WalletConnect this is the real relay topic; for the injected backend
76
+ * it is a stable sentinel ("injected") — callers do not need to inspect it.
77
+ */
78
+ topic: string;
79
+ /** The wallet's receive address, when known at connect time. */
80
+ address?: string | null;
81
+ }
82
+ /** Options for `DigClient.read*` calls — chiefly which dig RPC endpoint to use. */
83
+ interface ReadOptions {
84
+ /** dig RPC endpoint. Defaults to the public `https://rpc.dig.net`. */
85
+ rpc?: string;
86
+ }
87
+ /** The result of reading a resource by URN. */
88
+ interface ReadResult {
89
+ /** Store identity (64-hex). */
90
+ storeId: string;
91
+ /** The on-chain generation root the content was verified against (or null if none supplied). */
92
+ root: string | null;
93
+ /** The resource path within the store. */
94
+ resourceKey: string;
95
+ /** Private-store salt used (or null). */
96
+ salt: string | null;
97
+ /**
98
+ * The resource bytes. When `decrypted` is true these are the authenticated plaintext; when
99
+ * false they are the RAW served ciphertext (a decoy / wrong-key / wrong-salt response is just
100
+ * opaque bytes — the model is oblivious, so this is never a "not found" verdict).
101
+ */
102
+ bytes: Uint8Array;
103
+ /** Advisory: did the served bytes' inclusion proof verify against `root`? */
104
+ verified: boolean;
105
+ /** Did the bytes decrypt+authenticate under this URN's derived key? */
106
+ decrypted: boolean;
107
+ }
108
+ /** The two root-independent keys a URN maps to (derived client-side, nothing sent to the network). */
109
+ interface UrnKeys {
110
+ storeId: string;
111
+ root: string | null;
112
+ resourceKey: string;
113
+ salt: string | null;
114
+ /** `SHA-256(canonical rootless URN)`, lowercase hex — what the dig RPC is addressed by. */
115
+ retrievalKey: string;
116
+ /** The per-URN AES-256-GCM-SIV decryption key, lowercase hex. */
117
+ decryptionKey: string;
118
+ }
119
+
120
+ /** The default public dig RPC endpoint. */
121
+ declare const DEFAULT_RPC = "https://rpc.dig.net";
122
+ /** Options to construct a DigClient. */
123
+ interface DigClientOptions {
124
+ /** dig RPC endpoint. Defaults to the public `https://rpc.dig.net`. */
125
+ rpc?: string;
126
+ /** Override `fetch` (e.g. an instrumented one). Defaults to the global `fetch`. */
127
+ fetch?: typeof fetch;
128
+ }
129
+ /**
130
+ * The read-crypto client. Construct once and reuse — the wasm is loaded + SRI-verified lazily on
131
+ * the first read and memoized process/page-wide.
132
+ *
133
+ * @example
134
+ * const dig = new DigClient();
135
+ * const { bytes, decrypted } = await dig.read({
136
+ * urn: "urn:dig:chia:<storeId>/index.html",
137
+ * root: "<onchain-root-hex>",
138
+ * });
139
+ * if (decrypted) console.log(new TextDecoder().decode(bytes));
140
+ */
141
+ declare class DigClient {
142
+ private readonly rpc;
143
+ private readonly fetchImpl;
144
+ constructor(options?: DigClientOptions);
145
+ /** Load (and SRI-verify) the read-crypto wasm. Exposed for callers that want the raw functions. */
146
+ wasm(): Promise<DigClientWasm>;
147
+ /** `retrieval_key = SHA-256(canonical rootless URN)`, lowercase hex. */
148
+ retrievalKey(storeId: string, resourceKey: string): Promise<string>;
149
+ /** Derive the per-URN AES-256-GCM-SIV key, lowercase hex. `salt` for a private store. */
150
+ deriveKey(storeId: string, resourceKey: string, salt?: string | null): Promise<string>;
151
+ /** Verify served `ciphertext` is included under `root` via the base64 merkle `proof`. */
152
+ verifyInclusion(ciphertext: Uint8Array, proof: string, root: string): Promise<boolean>;
153
+ /** Reconstruct the canonical rootless URN whose SHA-256 is the retrieval key. */
154
+ reconstructUrn(storeId: string, resourceKey: string): Promise<string>;
155
+ /**
156
+ * Derive, client-side, the two root-independent keys a URN maps to (retrieval + decryption).
157
+ * Nothing is sent to the network — pure local derivation via the wasm.
158
+ */
159
+ deriveUrnKeys(input: {
160
+ urn: string;
161
+ salt?: string | null;
162
+ }): Promise<UrnKeys>;
163
+ /**
164
+ * Fetch + verify + decrypt one resource by URN. `root` is the on-chain generation root to verify
165
+ * against (resolved by the caller from the chain); when omitted, the root embedded in the URN is
166
+ * used. Returns the bytes plus advisory `verified`/`decrypted` flags. NEVER throws "not found"
167
+ * (presence is unknowable) — it throws only on a transport failure.
168
+ */
169
+ read(input: {
170
+ urn: string;
171
+ root?: string | null;
172
+ salt?: string | null;
173
+ }, opts?: ReadOptions): Promise<ReadResult>;
174
+ /** As `read`, but decoding the plaintext to a UTF-8 string when it decrypts (else throws). */
175
+ readText(input: {
176
+ urn: string;
177
+ root?: string | null;
178
+ salt?: string | null;
179
+ }, opts?: ReadOptions): Promise<string>;
180
+ /**
181
+ * Read by explicit (storeId, resourceKey, root, salt) rather than a URN string. The oblivious
182
+ * download primitive the URN read is built on.
183
+ */
184
+ readResource(input: {
185
+ storeId: string;
186
+ resourceKey: string;
187
+ root: string;
188
+ salt?: string | null;
189
+ }, opts?: ReadOptions): Promise<ReadResult>;
190
+ private fetchCiphertext;
191
+ private rpcCall;
192
+ }
193
+
194
+ /** SHA-256 (lowercase hex) of vendor/dig_client_bg.wasm — the SRI digest. Fail closed on mismatch. */
195
+ declare const DIG_CLIENT_WASM_SHA256 = "ff486be806f908a2a90780e499a04dbd34e10e3b97be0470cb9ee841a1e49e77";
196
+ /** Optional explicit wasm inputs, for environments where auto-resolution can't find vendor/. */
197
+ interface WasmConfig {
198
+ /**
199
+ * The wasm bytes (already loaded). When provided, SRI is still enforced unless `skipIntegrity`.
200
+ * Pass this in CSP-strict browsers where you fetch + verify the bytes yourself.
201
+ */
202
+ wasmBytes?: BufferSource;
203
+ /**
204
+ * URL to the wasm-bindgen glue module (vendor/dig_client.mjs) for browser dynamic import. When
205
+ * omitted in a browser, the loader tries to import the glue relative to this module.
206
+ */
207
+ glueUrl?: string;
208
+ /**
209
+ * URL to fetch the wasm bytes from (browser) when `wasmBytes` is not supplied. The fetched bytes
210
+ * are SRI-verified before init.
211
+ */
212
+ wasmUrl?: string;
213
+ /** Skip the SRI check. Only for tests / trusted custom builds — NOT recommended. */
214
+ skipIntegrity?: boolean;
215
+ }
216
+ /**
217
+ * Override how the read-crypto wasm is located/loaded. Call BEFORE the first `DigClient` read.
218
+ * Mainly for browsers without a bundler that resolves package files, or CSP-strict apps that fetch
219
+ * + verify the wasm bytes themselves and hand them in. Resets any cached instance.
220
+ */
221
+ declare function configureWasm(config: WasmConfig): void;
222
+ /**
223
+ * Load, SRI-verify, and instantiate the read-crypto wasm, returning its functions. Memoized — at
224
+ * most one init per process/page. Fails closed on an integrity mismatch.
225
+ */
226
+ declare function loadDigClientWasm(): Promise<DigClientWasm>;
227
+
228
+ /** The parts of a parsed DIG URN. `root`/`salt` are null when absent. */
229
+ interface ParsedUrn {
230
+ /** Store identity (64-hex launcher id), lowercased. */
231
+ readonly storeId: string;
232
+ /** Generation root (64-hex), lowercased — or null for the root-independent form. */
233
+ readonly root: string | null;
234
+ /** Resource path within the store (verbatim, not lowercased). */
235
+ readonly resourceKey: string;
236
+ /** Private-store secret salt (hex), lowercased — or null for a public store. */
237
+ readonly salt: string | null;
238
+ }
239
+ /**
240
+ * Parse a DIG URN into its parts. Throws on a malformed URN.
241
+ *
242
+ * @example
243
+ * parseUrn("urn:dig:chia:" + "ab".repeat(32) + "/index.html")
244
+ * // → { storeId: "abab…", root: null, resourceKey: "index.html", salt: null }
245
+ */
246
+ declare function parseUrn(raw: string): ParsedUrn;
247
+ /** True iff `raw` is a syntactically valid DIG URN. Never throws. */
248
+ declare function isUrn(raw: string): boolean;
249
+ /**
250
+ * Reconstruct the canonical, root-INDEPENDENT URN string for a store + resource key:
251
+ * `urn:dig:chia:<store_id>/<resource_key>`. An empty resource key resolves to the default view
252
+ * `index.html`. This is the form whose SHA-256 is the retrieval key and whose bytes seed the AES
253
+ * key — matching the wasm's `reconstructUrn`.
254
+ */
255
+ declare function reconstructUrn(storeId: string, resourceKey: string): string;
256
+ /**
257
+ * Reconstruct a root-PINNED display URN: `urn:dig:chia:<store_id>:<root>/<resource_key>`. Useful
258
+ * for sharing a URN bound to a specific generation; the retrieval/AES keys still use the rootless
259
+ * form (`reconstructUrn`).
260
+ */
261
+ declare function reconstructUrnWithRoot(storeId: string, root: string, resourceKey: string): string;
262
+
263
+ export { DEFAULT_RPC as D, type InjectedChiaProvider as I, type ParsedUrn as P, type ReadOptions as R, type SignResult as S, type UrnKeys as U, type WalletBackend as W, type WalletSession as a, DIG_CLIENT_WASM_SHA256 as b, DigClient as c, type DigClientOptions as d, type DigClientWasm as e, type ReadResult as f, type WasmConfig as g, configureWasm as h, isUrn as i, reconstructUrnWithRoot as j, loadDigClientWasm as l, parseUrn as p, reconstructUrn as r };
@@ -0,0 +1,330 @@
1
+ 'use strict';
2
+
3
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
4
+ // src/loader.ts
5
+ var DIG_CLIENT_WASM_SHA256 = "ff486be806f908a2a90780e499a04dbd34e10e3b97be0470cb9ee841a1e49e77";
6
+ var _config = {};
7
+ var _ready = null;
8
+ function configureWasm(config) {
9
+ _config = { ...config };
10
+ _ready = null;
11
+ }
12
+ var isNode = typeof process !== "undefined" && !!process.versions?.node;
13
+ async function sha256Hex(bytes) {
14
+ if (isNode) {
15
+ const { createHash } = await import('crypto');
16
+ const view = bytes instanceof ArrayBuffer ? new Uint8Array(bytes) : new Uint8Array(
17
+ bytes.buffer,
18
+ bytes.byteOffset,
19
+ bytes.byteLength
20
+ );
21
+ return createHash("sha256").update(view).digest("hex");
22
+ }
23
+ const digest = await crypto.subtle.digest("SHA-256", bytes);
24
+ return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, "0")).join("");
25
+ }
26
+ function assertIntegrity(hex) {
27
+ if (_config.skipIntegrity) return;
28
+ if (hex !== DIG_CLIENT_WASM_SHA256) {
29
+ throw new Error(
30
+ `dig-client wasm integrity check failed \u2014 refusing to run unverified crypto (expected ${DIG_CLIENT_WASM_SHA256}, got ${hex}).`
31
+ );
32
+ }
33
+ }
34
+ async function loadNode() {
35
+ const { readFile } = await import('fs/promises');
36
+ const { fileURLToPath, pathToFileURL } = await import('url');
37
+ const path = await import('path');
38
+ const here = path.dirname(fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('dig-client.cjs', document.baseURI).href))));
39
+ const vendorDir = path.resolve(here, "..", "vendor");
40
+ const wasmPath = path.join(vendorDir, "dig_client_bg.wasm");
41
+ const gluePath = path.join(vendorDir, "dig_client.mjs");
42
+ const buf = await readFile(wasmPath);
43
+ const bytes = new Uint8Array(buf.byteLength);
44
+ bytes.set(buf);
45
+ return { glueHref: pathToFileURL(gluePath).href, bytes };
46
+ }
47
+ async function loadBrowser() {
48
+ const glueHref = _config.glueUrl ?? new URL("../vendor/dig_client.mjs", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('dig-client.cjs', document.baseURI).href))).href;
49
+ let bytes;
50
+ if (_config.wasmBytes) {
51
+ bytes = _config.wasmBytes;
52
+ } else {
53
+ const wasmUrl = _config.wasmUrl ?? new URL("../vendor/dig_client_bg.wasm", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('dig-client.cjs', document.baseURI).href))).href;
54
+ const res = await fetch(wasmUrl);
55
+ if (!res.ok) throw new Error(`dig-client wasm fetch failed (${res.status})`);
56
+ bytes = await res.arrayBuffer();
57
+ }
58
+ return { glueHref, bytes };
59
+ }
60
+ function loadDigClientWasm() {
61
+ if (_ready) return _ready;
62
+ _ready = (async () => {
63
+ const { glueHref, bytes } = isNode ? await loadNode() : await loadBrowser();
64
+ assertIntegrity(await sha256Hex(bytes));
65
+ const mod = await import(
66
+ /* @vite-ignore */
67
+ glueHref
68
+ );
69
+ await mod.default({ module_or_path: bytes });
70
+ return mod;
71
+ })().catch((e) => {
72
+ _ready = null;
73
+ throw e;
74
+ });
75
+ return _ready;
76
+ }
77
+
78
+ // src/urn.ts
79
+ var URN_RE = /^urn:dig:chia:([0-9a-fA-F]{64})(?::([0-9a-fA-F]{64}))?\/(.+?)(?:\?salt=([0-9a-fA-F]+))?$/;
80
+ function parseUrn(raw) {
81
+ const s = String(raw ?? "").trim();
82
+ const m = URN_RE.exec(s);
83
+ if (!m) {
84
+ throw new Error(
85
+ "Not a valid dig URN (expected urn:dig:chia:<store-id>[:<root>]/<path>[?salt=<hex>])."
86
+ );
87
+ }
88
+ return {
89
+ storeId: m[1].toLowerCase(),
90
+ root: m[2] ? m[2].toLowerCase() : null,
91
+ resourceKey: m[3],
92
+ salt: m[4] ? m[4].toLowerCase() : null
93
+ };
94
+ }
95
+ function isUrn(raw) {
96
+ try {
97
+ parseUrn(raw);
98
+ return true;
99
+ } catch {
100
+ return false;
101
+ }
102
+ }
103
+ function reconstructUrn(storeId, resourceKey) {
104
+ const key = resourceKey && resourceKey.length > 0 ? resourceKey : "index.html";
105
+ return `urn:dig:chia:${storeId.toLowerCase()}/${key}`;
106
+ }
107
+ function reconstructUrnWithRoot(storeId, root, resourceKey) {
108
+ const key = resourceKey && resourceKey.length > 0 ? resourceKey : "index.html";
109
+ return `urn:dig:chia:${storeId.toLowerCase()}:${root.toLowerCase()}/${key}`;
110
+ }
111
+
112
+ // src/dig-client.ts
113
+ var DEFAULT_RPC = "https://rpc.dig.net";
114
+ var RPC_CHUNK_BYTES = 3 * 1024 * 1024;
115
+ function b64ToBytes(b64) {
116
+ if (typeof atob === "function") {
117
+ const bin = atob(b64);
118
+ const out = new Uint8Array(bin.length);
119
+ for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
120
+ return out;
121
+ }
122
+ return new Uint8Array(globalThis.Buffer.from(b64, "base64"));
123
+ }
124
+ var DigClient = class {
125
+ constructor(options = {}) {
126
+ this.rpc = options.rpc ?? DEFAULT_RPC;
127
+ this.fetchImpl = options.fetch ?? (typeof fetch === "function" ? fetch.bind(globalThis) : undefinedFetch());
128
+ }
129
+ /** Load (and SRI-verify) the read-crypto wasm. Exposed for callers that want the raw functions. */
130
+ async wasm() {
131
+ return loadDigClientWasm();
132
+ }
133
+ /** `retrieval_key = SHA-256(canonical rootless URN)`, lowercase hex. */
134
+ async retrievalKey(storeId, resourceKey) {
135
+ return (await this.wasm()).retrievalKey(storeId, resourceKey);
136
+ }
137
+ /** Derive the per-URN AES-256-GCM-SIV key, lowercase hex. `salt` for a private store. */
138
+ async deriveKey(storeId, resourceKey, salt) {
139
+ return (await this.wasm()).deriveKey(storeId, resourceKey, salt ?? void 0);
140
+ }
141
+ /** Verify served `ciphertext` is included under `root` via the base64 merkle `proof`. */
142
+ async verifyInclusion(ciphertext, proof, root) {
143
+ return (await this.wasm()).verifyInclusion(ciphertext, proof, root);
144
+ }
145
+ /** Reconstruct the canonical rootless URN whose SHA-256 is the retrieval key. */
146
+ async reconstructUrn(storeId, resourceKey) {
147
+ return (await this.wasm()).reconstructUrn(storeId, resourceKey);
148
+ }
149
+ /**
150
+ * Derive, client-side, the two root-independent keys a URN maps to (retrieval + decryption).
151
+ * Nothing is sent to the network — pure local derivation via the wasm.
152
+ */
153
+ async deriveUrnKeys(input) {
154
+ const parsed = parseUrn(input.urn);
155
+ const wasm = await this.wasm();
156
+ const effSalt = input.salt ?? parsed.salt ?? void 0;
157
+ return {
158
+ storeId: parsed.storeId,
159
+ root: parsed.root,
160
+ resourceKey: parsed.resourceKey,
161
+ salt: effSalt ?? null,
162
+ retrievalKey: wasm.retrievalKey(parsed.storeId, parsed.resourceKey),
163
+ decryptionKey: wasm.deriveKey(parsed.storeId, parsed.resourceKey, effSalt)
164
+ };
165
+ }
166
+ /**
167
+ * Fetch + verify + decrypt one resource by URN. `root` is the on-chain generation root to verify
168
+ * against (resolved by the caller from the chain); when omitted, the root embedded in the URN is
169
+ * used. Returns the bytes plus advisory `verified`/`decrypted` flags. NEVER throws "not found"
170
+ * (presence is unknowable) — it throws only on a transport failure.
171
+ */
172
+ async read(input, opts = {}) {
173
+ const parsed = parseUrn(input.urn);
174
+ const effSalt = input.salt ?? parsed.salt ?? null;
175
+ const effRoot = input.root ?? parsed.root ?? null;
176
+ if (!effRoot) {
177
+ throw new Error(
178
+ "a confirmed on-chain root is required to read content (pass { root } or use a root-pinned URN)"
179
+ );
180
+ }
181
+ return this.readResource(
182
+ { storeId: parsed.storeId, resourceKey: parsed.resourceKey, root: effRoot, salt: effSalt },
183
+ opts
184
+ );
185
+ }
186
+ /** As `read`, but decoding the plaintext to a UTF-8 string when it decrypts (else throws). */
187
+ async readText(input, opts = {}) {
188
+ const r = await this.read(input, opts);
189
+ if (!r.decrypted) {
190
+ throw new Error(
191
+ "resource did not decrypt under this URN \u2014 wrong store/key/salt, or a decoy response"
192
+ );
193
+ }
194
+ return new TextDecoder().decode(r.bytes);
195
+ }
196
+ /**
197
+ * Read by explicit (storeId, resourceKey, root, salt) rather than a URN string. The oblivious
198
+ * download primitive the URN read is built on.
199
+ */
200
+ async readResource(input, opts = {}) {
201
+ const rpc = opts.rpc ?? this.rpc;
202
+ const wasm = await this.wasm();
203
+ const rk = wasm.retrievalKey(input.storeId, input.resourceKey);
204
+ const { ciphertext, proof, chunkLens } = await this.fetchCiphertext(
205
+ input.storeId,
206
+ rk,
207
+ input.root,
208
+ rpc
209
+ );
210
+ let verified = false;
211
+ try {
212
+ verified = !!wasm.verifyInclusion(ciphertext, proof, input.root);
213
+ } catch {
214
+ verified = false;
215
+ }
216
+ const keyHex = wasm.deriveKey(input.storeId, input.resourceKey, input.salt ?? void 0);
217
+ try {
218
+ const bytes = decryptResourceChunks(wasm, keyHex, ciphertext, chunkLens);
219
+ return {
220
+ storeId: input.storeId,
221
+ root: input.root,
222
+ resourceKey: input.resourceKey,
223
+ salt: input.salt ?? null,
224
+ bytes,
225
+ verified,
226
+ decrypted: true
227
+ };
228
+ } catch {
229
+ return {
230
+ storeId: input.storeId,
231
+ root: input.root,
232
+ resourceKey: input.resourceKey,
233
+ salt: input.salt ?? null,
234
+ bytes: ciphertext,
235
+ verified,
236
+ decrypted: false
237
+ };
238
+ }
239
+ }
240
+ // Stream the FULL ciphertext for a resource from the RPC by retrieval key, reassembling 3-MiB
241
+ // chunks. A null result is a TRANSPORT failure, never a presence judgment.
242
+ async fetchCiphertext(storeId, rk, root, rpc) {
243
+ let offset = 0;
244
+ let total = null;
245
+ let buf = null;
246
+ let proof = "";
247
+ let chunkLens = null;
248
+ for (; ; ) {
249
+ const r = await this.rpcCall(rpc, "dig.getContent", {
250
+ store_id: storeId,
251
+ root,
252
+ retrieval_key: rk,
253
+ offset,
254
+ length: RPC_CHUNK_BYTES
255
+ });
256
+ if (!r) throw new Error("The content network returned no data for this request.");
257
+ if (total === null) {
258
+ total = r.total_length >>> 0;
259
+ buf = new Uint8Array(total);
260
+ }
261
+ if (chunkLens === null && Array.isArray(r.chunk_lens)) {
262
+ chunkLens = r.chunk_lens.map((n) => n >>> 0);
263
+ }
264
+ const chunk = b64ToBytes(r.ciphertext ?? "");
265
+ const at = r.offset >>> 0;
266
+ buf.set(chunk.subarray(0, Math.max(0, Math.min(chunk.length, total - at))), at);
267
+ if (r.inclusion_proof) proof = r.inclusion_proof;
268
+ if (r.complete || r.next_offset == null) break;
269
+ offset = r.next_offset >>> 0;
270
+ }
271
+ return { ciphertext: buf ?? new Uint8Array(0), proof, chunkLens };
272
+ }
273
+ // One JSON-RPC 2.0 call. Throws on transport failure or a JSON-RPC error; returns `result`.
274
+ async rpcCall(rpc, method, params) {
275
+ let res;
276
+ try {
277
+ res = await this.fetchImpl(rpc, {
278
+ method: "POST",
279
+ headers: { "content-type": "application/json" },
280
+ body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params })
281
+ });
282
+ } catch {
283
+ throw new Error("Could not reach the content network. Check your connection and try again.");
284
+ }
285
+ if (!res.ok) throw new Error(`dig RPC ${method} failed (${res.status})`);
286
+ const json = await res.json();
287
+ if (json && json.error) throw new Error(`dig RPC ${method}: ${json.error.message ?? "error"}`);
288
+ return json ? json.result ?? null : null;
289
+ }
290
+ };
291
+ function decryptResourceChunks(wasm, keyHex, ciphertext, chunkLens) {
292
+ const lens = chunkLens && chunkLens.length ? chunkLens : [ciphertext.length];
293
+ const total = lens.reduce((a, n) => a + n, 0);
294
+ if (total !== ciphertext.length) {
295
+ throw new Error("served ciphertext length does not match chunk lengths");
296
+ }
297
+ if (lens.length === 1) return wasm.decryptChunk(keyHex, ciphertext);
298
+ const parts = [];
299
+ let p = 0;
300
+ for (const len of lens) {
301
+ parts.push(wasm.decryptChunk(keyHex, ciphertext.subarray(p, p + len)));
302
+ p += len;
303
+ }
304
+ const out = new Uint8Array(parts.reduce((a, x) => a + x.length, 0));
305
+ let q = 0;
306
+ for (const part of parts) {
307
+ out.set(part, q);
308
+ q += part.length;
309
+ }
310
+ return out;
311
+ }
312
+ function undefinedFetch() {
313
+ return (() => {
314
+ throw new Error(
315
+ "No global fetch available. Pass { fetch } to DigClient (Node < 18 needs a fetch polyfill)."
316
+ );
317
+ });
318
+ }
319
+
320
+ exports.DEFAULT_RPC = DEFAULT_RPC;
321
+ exports.DIG_CLIENT_WASM_SHA256 = DIG_CLIENT_WASM_SHA256;
322
+ exports.DigClient = DigClient;
323
+ exports.configureWasm = configureWasm;
324
+ exports.isUrn = isUrn;
325
+ exports.loadDigClientWasm = loadDigClientWasm;
326
+ exports.parseUrn = parseUrn;
327
+ exports.reconstructUrn = reconstructUrn;
328
+ exports.reconstructUrnWithRoot = reconstructUrnWithRoot;
329
+ //# sourceMappingURL=dig-client.cjs.map
330
+ //# sourceMappingURL=dig-client.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/loader.ts","../src/urn.ts","../src/dig-client.ts"],"names":[],"mappings":";;;;AAmBO,IAAM,sBAAA,GACX;AAuBF,IAAI,UAAsB,EAAC;AAC3B,IAAI,MAAA,GAAwC,IAAA;AAOrC,SAAS,cAAc,MAAA,EAA0B;AACtD,EAAA,OAAA,GAAU,EAAE,GAAG,MAAA,EAAO;AACtB,EAAA,MAAA,GAAS,IAAA;AACX;AAEA,IAAM,SACJ,OAAO,OAAA,KAAY,eACnB,CAAC,CAAE,QAA6C,QAAA,EAAU,IAAA;AAG5D,eAAe,UAAU,KAAA,EAAsC;AAC7D,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAM,EAAE,UAAA,EAAW,GAAI,MAAM,OAAO,QAAa,CAAA;AACjD,IAAA,MAAM,OACJ,KAAA,YAAiB,WAAA,GACb,IAAI,UAAA,CAAW,KAAK,IACpB,IAAI,UAAA;AAAA,MACD,KAAA,CAA0B,MAAA;AAAA,MAC1B,KAAA,CAA0B,UAAA;AAAA,MAC1B,KAAA,CAA0B;AAAA,KAC7B;AACN,IAAA,OAAO,WAAW,QAAQ,CAAA,CAAE,OAAO,IAAI,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,EACvD;AACA,EAAA,MAAM,SAAS,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,WAAW,KAAqB,CAAA;AAC1E,EAAA,OAAO,CAAC,GAAG,IAAI,UAAA,CAAW,MAAM,CAAC,CAAA,CAAE,IAAI,CAAC,CAAA,KAAM,EAAE,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AACxF;AAEA,SAAS,gBAAgB,GAAA,EAAmB;AAC1C,EAAA,IAAI,QAAQ,aAAA,EAAe;AAC3B,EAAA,IAAI,QAAQ,sBAAA,EAAwB;AAClC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,0FAAA,EACe,sBAAsB,CAAA,MAAA,EAAS,GAAG,CAAA,EAAA;AAAA,KACnD;AAAA,EACF;AACF;AAGA,eAAe,QAAA,GAA+D;AAC5E,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,OAAO,aAAkB,CAAA;AACpD,EAAA,MAAM,EAAE,aAAA,EAAe,aAAA,EAAc,GAAI,MAAM,OAAO,KAAU,CAAA;AAChE,EAAA,MAAM,IAAA,GAAO,MAAM,OAAO,MAAW,CAAA;AAErC,EAAA,MAAM,OAAO,IAAA,CAAK,OAAA,CAAQ,aAAA,CAAc,gQAAe,CAAC,CAAA;AACxD,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,MAAM,QAAQ,CAAA;AACnD,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,oBAAoB,CAAA;AAC1D,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,gBAAgB,CAAA;AACtD,EAAA,MAAM,GAAA,GAAM,MAAM,QAAA,CAAS,QAAQ,CAAA;AAGnC,EAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,GAAA,CAAI,UAAU,CAAA;AAC3C,EAAA,KAAA,CAAM,IAAI,GAAG,CAAA;AACb,EAAA,OAAO,EAAE,QAAA,EAAU,aAAA,CAAc,QAAQ,CAAA,CAAE,MAAM,KAAA,EAAM;AACzD;AAIA,eAAe,WAAA,GAAkE;AAC/E,EAAA,MAAM,QAAA,GACJ,QAAQ,OAAA,IAAW,IAAI,IAAI,0BAAA,EAA4B,gQAAe,CAAA,CAAE,IAAA;AAC1E,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI,QAAQ,SAAA,EAAW;AACrB,IAAA,KAAA,GAAQ,OAAA,CAAQ,SAAA;AAAA,EAClB,CAAA,MAAO;AACL,IAAA,MAAM,OAAA,GACJ,QAAQ,OAAA,IAAW,IAAI,IAAI,8BAAA,EAAgC,gQAAe,CAAA,CAAE,IAAA;AAC9E,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,OAAO,CAAA;AAC/B,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiC,GAAA,CAAI,MAAM,CAAA,CAAA,CAAG,CAAA;AAC3E,IAAA,KAAA,GAAQ,MAAM,IAAI,WAAA,EAAY;AAAA,EAChC;AACA,EAAA,OAAO,EAAE,UAAU,KAAA,EAAM;AAC3B;AAMO,SAAS,iBAAA,GAA4C;AAC1D,EAAA,IAAI,QAAQ,OAAO,MAAA;AACnB,EAAA,MAAA,GAAA,CAAU,YAAY;AACpB,IAAA,MAAM,EAAE,UAAU,KAAA,EAAM,GAAI,SAAS,MAAM,QAAA,EAAS,GAAI,MAAM,WAAA,EAAY;AAC1E,IAAA,eAAA,CAAgB,MAAM,SAAA,CAAU,KAAK,CAAC,CAAA;AACtC,IAAA,MAAM,MAAO,MAAM;AAAA;AAAA,MAA0B;AAAA,KAAA;AAI7C,IAAA,MAAM,GAAA,CAAI,OAAA,CAAQ,EAAE,cAAA,EAAgB,OAAO,CAAA;AAC3C,IAAA,OAAO,GAAA;AAAA,EACT,CAAA,GAAG,CAAE,KAAA,CAAM,CAAC,CAAA,KAAM;AAChB,IAAA,MAAA,GAAS,IAAA;AACT,IAAA,MAAM,CAAA;AAAA,EACR,CAAC,CAAA;AACD,EAAA,OAAO,MAAA;AACT;;;ACnHA,IAAM,MAAA,GACJ,0FAAA;AASK,SAAS,SAAS,GAAA,EAAwB;AAC/C,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,GAAA,IAAO,EAAE,EAAE,IAAA,EAAK;AACjC,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AACvB,EAAA,IAAI,CAAC,CAAA,EAAG;AACN,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,CAAA,CAAE,CAAC,CAAA,CAAG,WAAA,EAAY;AAAA,IAC3B,IAAA,EAAM,EAAE,CAAC,CAAA,GAAI,EAAE,CAAC,CAAA,CAAE,aAAY,GAAI,IAAA;AAAA,IAClC,WAAA,EAAa,EAAE,CAAC,CAAA;AAAA,IAChB,IAAA,EAAM,EAAE,CAAC,CAAA,GAAI,EAAE,CAAC,CAAA,CAAE,aAAY,GAAI;AAAA,GACpC;AACF;AAGO,SAAS,MAAM,GAAA,EAAsB;AAC1C,EAAA,IAAI;AACF,IAAA,QAAA,CAAS,GAAG,CAAA;AACZ,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAQO,SAAS,cAAA,CAAe,SAAiB,WAAA,EAA6B;AAC3E,EAAA,MAAM,GAAA,GAAM,WAAA,IAAe,WAAA,CAAY,MAAA,GAAS,IAAI,WAAA,GAAc,YAAA;AAClE,EAAA,OAAO,CAAA,aAAA,EAAgB,OAAA,CAAQ,WAAA,EAAa,IAAI,GAAG,CAAA,CAAA;AACrD;AAOO,SAAS,sBAAA,CACd,OAAA,EACA,IAAA,EACA,WAAA,EACQ;AACR,EAAA,MAAM,GAAA,GAAM,WAAA,IAAe,WAAA,CAAY,MAAA,GAAS,IAAI,WAAA,GAAc,YAAA;AAClE,EAAA,OAAO,CAAA,aAAA,EAAgB,QAAQ,WAAA,EAAa,IAAI,IAAA,CAAK,WAAA,EAAa,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA;AAC3E;;;ACjEO,IAAM,WAAA,GAAc;AAI3B,IAAM,eAAA,GAAkB,IAAI,IAAA,GAAO,IAAA;AAqBnC,SAAS,WAAW,GAAA,EAAyB;AAE3C,EAAA,IAAI,OAAO,SAAS,UAAA,EAAY;AAC9B,IAAA,MAAM,GAAA,GAAM,KAAK,GAAG,CAAA;AACpB,IAAA,MAAM,GAAA,GAAM,IAAI,UAAA,CAAW,GAAA,CAAI,MAAM,CAAA;AACrC,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,MAAA,EAAQ,CAAA,EAAA,EAAK,GAAA,CAAI,CAAC,CAAA,GAAI,GAAA,CAAI,UAAA,CAAW,CAAC,CAAA;AAC9D,IAAA,OAAO,GAAA;AAAA,EACT;AAEA,EAAA,OAAO,IAAI,UAAA,CAAY,UAAA,CAAmB,OAAO,IAAA,CAAK,GAAA,EAAK,QAAQ,CAAC,CAAA;AACtE;AAcO,IAAM,YAAN,MAAgB;AAAA,EAIrB,WAAA,CAAY,OAAA,GAA4B,EAAC,EAAG;AAC1C,IAAA,IAAA,CAAK,GAAA,GAAM,QAAQ,GAAA,IAAO,WAAA;AAC1B,IAAA,IAAA,CAAK,SAAA,GACH,OAAA,CAAQ,KAAA,KACP,OAAO,KAAA,KAAU,aAAa,KAAA,CAAM,IAAA,CAAK,UAAU,CAAA,GAAI,cAAA,EAAe,CAAA;AAAA,EAC3E;AAAA;AAAA,EAGA,MAAM,IAAA,GAA+B;AACnC,IAAA,OAAO,iBAAA,EAAkB;AAAA,EAC3B;AAAA;AAAA,EAGA,MAAM,YAAA,CAAa,OAAA,EAAiB,WAAA,EAAsC;AACxE,IAAA,OAAA,CAAQ,MAAM,IAAA,CAAK,IAAA,EAAK,EAAG,YAAA,CAAa,SAAS,WAAW,CAAA;AAAA,EAC9D;AAAA;AAAA,EAGA,MAAM,SAAA,CACJ,OAAA,EACA,WAAA,EACA,IAAA,EACiB;AACjB,IAAA,OAAA,CAAQ,MAAM,KAAK,IAAA,EAAK,EAAG,UAAU,OAAA,EAAS,WAAA,EAAa,QAAQ,MAAS,CAAA;AAAA,EAC9E;AAAA;AAAA,EAGA,MAAM,eAAA,CACJ,UAAA,EACA,KAAA,EACA,IAAA,EACkB;AAClB,IAAA,OAAA,CAAQ,MAAM,IAAA,CAAK,IAAA,IAAQ,eAAA,CAAgB,UAAA,EAAY,OAAO,IAAI,CAAA;AAAA,EACpE;AAAA;AAAA,EAGA,MAAM,cAAA,CAAe,OAAA,EAAiB,WAAA,EAAsC;AAC1E,IAAA,OAAA,CAAQ,MAAM,IAAA,CAAK,IAAA,EAAK,EAAG,cAAA,CAAe,SAAS,WAAW,CAAA;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAc,KAAA,EAAgE;AAClF,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA;AACjC,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,EAAK;AAC7B,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,IAAA,IAAQ,MAAA,CAAO,IAAA,IAAQ,MAAA;AAC7C,IAAA,OAAO;AAAA,MACL,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,MAAM,OAAA,IAAW,IAAA;AAAA,MACjB,cAAc,IAAA,CAAK,YAAA,CAAa,MAAA,CAAO,OAAA,EAAS,OAAO,WAAW,CAAA;AAAA,MAClE,eAAe,IAAA,CAAK,SAAA,CAAU,OAAO,OAAA,EAAS,MAAA,CAAO,aAAa,OAAO;AAAA,KAC3E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAA,CACJ,KAAA,EACA,IAAA,GAAoB,EAAC,EACA;AACrB,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA;AACjC,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,IAAA,IAAQ,MAAA,CAAO,IAAA,IAAQ,IAAA;AAC7C,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,IAAA,IAAQ,MAAA,CAAO,IAAA,IAAQ,IAAA;AAC7C,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,MACV,EAAE,OAAA,EAAS,MAAA,CAAO,OAAA,EAAS,WAAA,EAAa,OAAO,WAAA,EAAa,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,OAAA,EAAQ;AAAA,MACzF;AAAA,KACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,QAAA,CACJ,KAAA,EACA,IAAA,GAAoB,EAAC,EACJ;AACjB,IAAA,MAAM,CAAA,GAAI,MAAM,IAAA,CAAK,IAAA,CAAK,OAAO,IAAI,CAAA;AACrC,IAAA,IAAI,CAAC,EAAE,SAAA,EAAW;AAChB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAO,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,EAAE,KAAK,CAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAAA,CACJ,KAAA,EACA,IAAA,GAAoB,EAAC,EACA;AACrB,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,IAAO,IAAA,CAAK,GAAA;AAC7B,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,EAAK;AAC7B,IAAA,MAAM,KAAK,IAAA,CAAK,YAAA,CAAa,KAAA,CAAM,OAAA,EAAS,MAAM,WAAW,CAAA;AAC7D,IAAA,MAAM,EAAE,UAAA,EAAY,KAAA,EAAO,SAAA,EAAU,GAAI,MAAM,IAAA,CAAK,eAAA;AAAA,MAClD,KAAA,CAAM,OAAA;AAAA,MACN,EAAA;AAAA,MACA,KAAA,CAAM,IAAA;AAAA,MACN;AAAA,KACF;AACA,IAAA,IAAI,QAAA,GAAW,KAAA;AACf,IAAA,IAAI;AACF,MAAA,QAAA,GAAW,CAAC,CAAC,IAAA,CAAK,gBAAgB,UAAA,EAAY,KAAA,EAAO,MAAM,IAAI,CAAA;AAAA,IACjE,CAAA,CAAA,MAAQ;AACN,MAAA,QAAA,GAAW,KAAA;AAAA,IACb;AACA,IAAA,MAAM,MAAA,GAAS,KAAK,SAAA,CAAU,KAAA,CAAM,SAAS,KAAA,CAAM,WAAA,EAAa,KAAA,CAAM,IAAA,IAAQ,MAAS,CAAA;AACvF,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,qBAAA,CAAsB,IAAA,EAAM,MAAA,EAAQ,YAAY,SAAS,CAAA;AACvE,MAAA,OAAO;AAAA,QACL,SAAS,KAAA,CAAM,OAAA;AAAA,QACf,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,aAAa,KAAA,CAAM,WAAA;AAAA,QACnB,IAAA,EAAM,MAAM,IAAA,IAAQ,IAAA;AAAA,QACpB,KAAA;AAAA,QACA,QAAA;AAAA,QACA,SAAA,EAAW;AAAA,OACb;AAAA,IACF,CAAA,CAAA,MAAQ;AAEN,MAAA,OAAO;AAAA,QACL,SAAS,KAAA,CAAM,OAAA;AAAA,QACf,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,aAAa,KAAA,CAAM,WAAA;AAAA,QACnB,IAAA,EAAM,MAAM,IAAA,IAAQ,IAAA;AAAA,QACpB,KAAA,EAAO,UAAA;AAAA,QACP,QAAA;AAAA,QACA,SAAA,EAAW;AAAA,OACb;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA,EAIA,MAAc,eAAA,CACZ,OAAA,EACA,EAAA,EACA,MACA,GAAA,EACgF;AAChF,IAAA,IAAI,MAAA,GAAS,CAAA;AACb,IAAA,IAAI,KAAA,GAAuB,IAAA;AAC3B,IAAA,IAAI,GAAA,GAAyB,IAAA;AAC7B,IAAA,IAAI,KAAA,GAAQ,EAAA;AACZ,IAAA,IAAI,SAAA,GAA6B,IAAA;AACjC,IAAA,WAAS;AACP,MAAA,MAAM,CAAA,GAAI,MAAM,IAAA,CAAK,OAAA,CAA0B,KAAK,gBAAA,EAAkB;AAAA,QACpE,QAAA,EAAU,OAAA;AAAA,QACV,IAAA;AAAA,QACA,aAAA,EAAe,EAAA;AAAA,QACf,MAAA;AAAA,QACA,MAAA,EAAQ;AAAA,OACT,CAAA;AACD,MAAA,IAAI,CAAC,CAAA,EAAG,MAAM,IAAI,MAAM,wDAAwD,CAAA;AAChF,MAAA,IAAI,UAAU,IAAA,EAAM;AAClB,QAAA,KAAA,GAAQ,EAAE,YAAA,KAAiB,CAAA;AAC3B,QAAA,GAAA,GAAM,IAAI,WAAW,KAAK,CAAA;AAAA,MAC5B;AACA,MAAA,IAAI,cAAc,IAAA,IAAQ,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,UAAU,CAAA,EAAG;AACrD,QAAA,SAAA,GAAY,EAAE,UAAA,CAAW,GAAA,CAAI,CAAC,CAAA,KAAM,MAAM,CAAC,CAAA;AAAA,MAC7C;AACA,MAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,CAAA,CAAE,UAAA,IAAc,EAAE,CAAA;AAC3C,MAAA,MAAM,EAAA,GAAK,EAAE,MAAA,KAAW,CAAA;AACxB,MAAA,GAAA,CAAK,IAAI,KAAA,CAAM,QAAA,CAAS,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,QAAQ,KAAA,GAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,CAAA;AAC/E,MAAA,IAAI,CAAA,CAAE,eAAA,EAAiB,KAAA,GAAQ,CAAA,CAAE,eAAA;AACjC,MAAA,IAAI,CAAA,CAAE,QAAA,IAAY,CAAA,CAAE,WAAA,IAAe,IAAA,EAAM;AACzC,MAAA,MAAA,GAAS,EAAE,WAAA,KAAgB,CAAA;AAAA,IAC7B;AACA,IAAA,OAAO,EAAE,YAAY,GAAA,IAAO,IAAI,WAAW,CAAC,CAAA,EAAG,OAAO,SAAA,EAAU;AAAA,EAClE;AAAA;AAAA,EAGA,MAAc,OAAA,CAAW,GAAA,EAAa,MAAA,EAAgB,MAAA,EAAoC;AACxF,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI;AACF,MAAA,GAAA,GAAM,MAAM,IAAA,CAAK,SAAA,CAAU,GAAA,EAAK;AAAA,QAC9B,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,QAC9C,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,OAAA,EAAS,OAAO,EAAA,EAAI,CAAA,EAAG,MAAA,EAAQ,MAAA,EAAQ;AAAA,OAC/D,CAAA;AAAA,IACH,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,MAAM,2EAA2E,CAAA;AAAA,IAC7F;AACA,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,MAAM,CAAA,SAAA,EAAY,GAAA,CAAI,MAAM,CAAA,CAAA,CAAG,CAAA;AACvE,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,IAAI,IAAA,IAAQ,IAAA,CAAK,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,MAAM,CAAA,EAAA,EAAK,IAAA,CAAK,KAAA,CAAM,OAAA,IAAW,OAAO,CAAA,CAAE,CAAA;AAC7F,IAAA,OAAO,IAAA,GAAQ,IAAA,CAAK,MAAA,IAAU,IAAA,GAAQ,IAAA;AAAA,EACxC;AACF;AAKA,SAAS,qBAAA,CACP,IAAA,EACA,MAAA,EACA,UAAA,EACA,SAAA,EACY;AACZ,EAAA,MAAM,OAAO,SAAA,IAAa,SAAA,CAAU,SAAS,SAAA,GAAY,CAAC,WAAW,MAAM,CAAA;AAC3E,EAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,CAAC,GAAG,CAAA,KAAM,CAAA,GAAI,GAAG,CAAC,CAAA;AAC5C,EAAA,IAAI,KAAA,KAAU,WAAW,MAAA,EAAQ;AAC/B,IAAA,MAAM,IAAI,MAAM,uDAAuD,CAAA;AAAA,EACzE;AACA,EAAA,IAAI,KAAK,MAAA,KAAW,CAAA,SAAU,IAAA,CAAK,YAAA,CAAa,QAAQ,UAAU,CAAA;AAClE,EAAA,MAAM,QAAsB,EAAC;AAC7B,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,YAAA,CAAa,MAAA,EAAQ,UAAA,CAAW,SAAS,CAAA,EAAG,CAAA,GAAI,GAAG,CAAC,CAAC,CAAA;AACrE,IAAA,CAAA,IAAK,GAAA;AAAA,EACP;AACA,EAAA,MAAM,GAAA,GAAM,IAAI,UAAA,CAAW,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,MAAA,EAAQ,CAAC,CAAC,CAAA;AAClE,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,GAAA,CAAI,GAAA,CAAI,MAAM,CAAC,CAAA;AACf,IAAA,CAAA,IAAK,IAAA,CAAK,MAAA;AAAA,EACZ;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,cAAA,GAA+B;AACtC,EAAA,QAAQ,MAAM;AACZ,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF,CAAA;AACF","file":"dig-client.cjs","sourcesContent":["// Cross-target loader for the vendored `dig_client` read-crypto WASM.\n//\n// The wasm is the SAME artifact the DIG Browser, extension, companion, and hub all run — vendored\n// under vendor/ with a PROVENANCE note and pinned SRI (see vendor/PROVENANCE.md). We NEVER run it\n// unverified: we obtain the raw bytes, SHA-256 them, compare against the pinned digest, and only\n// then hand the verified bytes to wasm-bindgen's init. A mismatch (tampered / wrong artifact)\n// throws — the reader FAILS CLOSED rather than running unverified crypto.\n//\n// Three runtimes are supported, auto-detected, with an escape hatch (`configureWasm`):\n// • Node / Bun — read vendor/ files from the package directory (fs + node:crypto).\n// • Browser (bundled) — the consumer's bundler can resolve the vendor files; if it can't, the\n// consumer supplies bytes via `configureWasm({ wasmBytes, glueUrl })`.\n// • Browser (no bundler) — `configureWasm` with a URL/bytes you serve yourself.\n//\n// Memoized: the wasm initializes at most once per process/page.\n\nimport type { DigClientWasm } from \"./wasm.js\";\n\n/** SHA-256 (lowercase hex) of vendor/dig_client_bg.wasm — the SRI digest. Fail closed on mismatch. */\nexport const DIG_CLIENT_WASM_SHA256 =\n \"ff486be806f908a2a90780e499a04dbd34e10e3b97be0470cb9ee841a1e49e77\";\n\n/** Optional explicit wasm inputs, for environments where auto-resolution can't find vendor/. */\nexport interface WasmConfig {\n /**\n * The wasm bytes (already loaded). When provided, SRI is still enforced unless `skipIntegrity`.\n * Pass this in CSP-strict browsers where you fetch + verify the bytes yourself.\n */\n wasmBytes?: BufferSource;\n /**\n * URL to the wasm-bindgen glue module (vendor/dig_client.mjs) for browser dynamic import. When\n * omitted in a browser, the loader tries to import the glue relative to this module.\n */\n glueUrl?: string;\n /**\n * URL to fetch the wasm bytes from (browser) when `wasmBytes` is not supplied. The fetched bytes\n * are SRI-verified before init.\n */\n wasmUrl?: string;\n /** Skip the SRI check. Only for tests / trusted custom builds — NOT recommended. */\n skipIntegrity?: boolean;\n}\n\nlet _config: WasmConfig = {};\nlet _ready: Promise<DigClientWasm> | null = null;\n\n/**\n * Override how the read-crypto wasm is located/loaded. Call BEFORE the first `DigClient` read.\n * Mainly for browsers without a bundler that resolves package files, or CSP-strict apps that fetch\n * + verify the wasm bytes themselves and hand them in. Resets any cached instance.\n */\nexport function configureWasm(config: WasmConfig): void {\n _config = { ...config };\n _ready = null;\n}\n\nconst isNode =\n typeof process !== \"undefined\" &&\n !!(process as { versions?: { node?: string } }).versions?.node;\n\n/** SHA-256 a buffer to lowercase hex, using node:crypto or WebCrypto. */\nasync function sha256Hex(bytes: BufferSource): Promise<string> {\n if (isNode) {\n const { createHash } = await import(\"node:crypto\");\n const view =\n bytes instanceof ArrayBuffer\n ? new Uint8Array(bytes)\n : new Uint8Array(\n (bytes as ArrayBufferView).buffer,\n (bytes as ArrayBufferView).byteOffset,\n (bytes as ArrayBufferView).byteLength,\n );\n return createHash(\"sha256\").update(view).digest(\"hex\");\n }\n const digest = await crypto.subtle.digest(\"SHA-256\", bytes as BufferSource);\n return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nfunction assertIntegrity(hex: string): void {\n if (_config.skipIntegrity) return;\n if (hex !== DIG_CLIENT_WASM_SHA256) {\n throw new Error(\n \"dig-client wasm integrity check failed — refusing to run unverified crypto \" +\n `(expected ${DIG_CLIENT_WASM_SHA256}, got ${hex}).`,\n );\n }\n}\n\n// Read the vendored glue URL + wasm bytes for Node from the package's vendor/ directory.\nasync function loadNode(): Promise<{ glueHref: string; bytes: BufferSource }> {\n const { readFile } = await import(\"node:fs/promises\");\n const { fileURLToPath, pathToFileURL } = await import(\"node:url\");\n const path = await import(\"node:path\");\n // This module lives in dist/; vendor/ sits at the package root, one level up.\n const here = path.dirname(fileURLToPath(import.meta.url));\n const vendorDir = path.resolve(here, \"..\", \"vendor\");\n const wasmPath = path.join(vendorDir, \"dig_client_bg.wasm\");\n const gluePath = path.join(vendorDir, \"dig_client.mjs\");\n const buf = await readFile(wasmPath);\n // Copy into a fresh ArrayBuffer-backed view so the type is a plain BufferSource (not the\n // ArrayBufferLike/SharedArrayBuffer union the Node Buffer type widens to).\n const bytes = new Uint8Array(buf.byteLength);\n bytes.set(buf);\n return { glueHref: pathToFileURL(gluePath).href, bytes };\n}\n\n// Resolve the glue URL + wasm bytes for a browser. Prefers explicit config; otherwise resolves\n// the vendored files relative to this module (works when the bundler copies vendor/ alongside).\nasync function loadBrowser(): Promise<{ glueHref: string; bytes: BufferSource }> {\n const glueHref =\n _config.glueUrl ?? new URL(\"../vendor/dig_client.mjs\", import.meta.url).href;\n let bytes: BufferSource;\n if (_config.wasmBytes) {\n bytes = _config.wasmBytes;\n } else {\n const wasmUrl =\n _config.wasmUrl ?? new URL(\"../vendor/dig_client_bg.wasm\", import.meta.url).href;\n const res = await fetch(wasmUrl);\n if (!res.ok) throw new Error(`dig-client wasm fetch failed (${res.status})`);\n bytes = await res.arrayBuffer();\n }\n return { glueHref, bytes };\n}\n\n/**\n * Load, SRI-verify, and instantiate the read-crypto wasm, returning its functions. Memoized — at\n * most one init per process/page. Fails closed on an integrity mismatch.\n */\nexport function loadDigClientWasm(): Promise<DigClientWasm> {\n if (_ready) return _ready;\n _ready = (async () => {\n const { glueHref, bytes } = isNode ? await loadNode() : await loadBrowser();\n assertIntegrity(await sha256Hex(bytes));\n const mod = (await import(/* @vite-ignore */ glueHref)) as {\n default: (input: { module_or_path: BufferSource }) => Promise<unknown>;\n } & Partial<DigClientWasm>;\n // wasm-bindgen default export = async init; accepts raw bytes via { module_or_path }.\n await mod.default({ module_or_path: bytes });\n return mod as unknown as DigClientWasm;\n })().catch((e) => {\n _ready = null; // allow a retry on transient load failure\n throw e;\n });\n return _ready;\n}\n","// DIG URN parsing + canonicalization — PURE, dependency-free, and identical to the parser the\n// hub (apps/web/lib/dig-client.js), the extension, and the companion use. Kept pure (no wasm) so\n// it is trivially unit-testable under `node --test` and usable on any runtime.\n//\n// A DIG URN addresses one resource inside a store:\n//\n// urn:dig:chia:<store_id>[:<root>]/<resource_key>[?salt=<hex>]\n//\n// • <store_id> — 64 hex chars, the singleton launcher id (the store identity).\n// • :<root> — OPTIONAL 64 hex chars, pins a specific on-chain generation. Omit for the\n// canonical, root-INDEPENDENT form. The root is only the trust anchor for\n// inclusion verification; it is NOT a key input (retrieval/decryption keys are\n// root-independent).\n// • <resource_key> — the path within the store (e.g. \"index.html\", \"img/logo.png\"). An empty\n// key resolves to the §8.5 default view \"index.html\".\n// • ?salt=<hex> — OPTIONAL out-of-band secret salt for a PRIVATE store.\n\n/** The parts of a parsed DIG URN. `root`/`salt` are null when absent. */\nexport interface ParsedUrn {\n /** Store identity (64-hex launcher id), lowercased. */\n readonly storeId: string;\n /** Generation root (64-hex), lowercased — or null for the root-independent form. */\n readonly root: string | null;\n /** Resource path within the store (verbatim, not lowercased). */\n readonly resourceKey: string;\n /** Private-store secret salt (hex), lowercased — or null for a public store. */\n readonly salt: string | null;\n}\n\nconst URN_RE =\n /^urn:dig:chia:([0-9a-fA-F]{64})(?::([0-9a-fA-F]{64}))?\\/(.+?)(?:\\?salt=([0-9a-fA-F]+))?$/;\n\n/**\n * Parse a DIG URN into its parts. Throws on a malformed URN.\n *\n * @example\n * parseUrn(\"urn:dig:chia:\" + \"ab\".repeat(32) + \"/index.html\")\n * // → { storeId: \"abab…\", root: null, resourceKey: \"index.html\", salt: null }\n */\nexport function parseUrn(raw: string): ParsedUrn {\n const s = String(raw ?? \"\").trim();\n const m = URN_RE.exec(s);\n if (!m) {\n throw new Error(\n \"Not a valid dig URN (expected urn:dig:chia:<store-id>[:<root>]/<path>[?salt=<hex>]).\",\n );\n }\n return {\n storeId: m[1]!.toLowerCase(),\n root: m[2] ? m[2].toLowerCase() : null,\n resourceKey: m[3]!,\n salt: m[4] ? m[4].toLowerCase() : null,\n };\n}\n\n/** True iff `raw` is a syntactically valid DIG URN. Never throws. */\nexport function isUrn(raw: string): boolean {\n try {\n parseUrn(raw);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Reconstruct the canonical, root-INDEPENDENT URN string for a store + resource key:\n * `urn:dig:chia:<store_id>/<resource_key>`. An empty resource key resolves to the default view\n * `index.html`. This is the form whose SHA-256 is the retrieval key and whose bytes seed the AES\n * key — matching the wasm's `reconstructUrn`.\n */\nexport function reconstructUrn(storeId: string, resourceKey: string): string {\n const key = resourceKey && resourceKey.length > 0 ? resourceKey : \"index.html\";\n return `urn:dig:chia:${storeId.toLowerCase()}/${key}`;\n}\n\n/**\n * Reconstruct a root-PINNED display URN: `urn:dig:chia:<store_id>:<root>/<resource_key>`. Useful\n * for sharing a URN bound to a specific generation; the retrieval/AES keys still use the rootless\n * form (`reconstructUrn`).\n */\nexport function reconstructUrnWithRoot(\n storeId: string,\n root: string,\n resourceKey: string,\n): string {\n const key = resourceKey && resourceKey.length > 0 ? resourceKey : \"index.html\";\n return `urn:dig:chia:${storeId.toLowerCase()}:${root.toLowerCase()}/${key}`;\n}\n","// DigClient — the read side of the SDK. It fetches a resource's served ciphertext from the dig RPC,\n// derives the URN's keys CLIENT-SIDE via the read-crypto wasm, verifies inclusion against an\n// on-chain root, and decrypts — so the serving host stays BLIND (it only ever relays opaque\n// ciphertext + proofs). Genericized from hub.dig.net/apps/web/lib/dig-client.js, with the hub-app\n// coupling removed (no Vite import.meta.env, no window.location origin; the RPC endpoint and the\n// trust root are explicit inputs).\n//\n// HARD BOUNDARY (read sources). Everything read from a .dig — ciphertext, inclusion proofs, the\n// public manifest, metadata — comes ONLY from the dig RPC. The trust ROOT it is verified against\n// comes from the chain (the caller resolves it from coinset.org and passes it in). The host can\n// never become the trust anchor: every content read REQUIRES a caller-supplied root.\n//\n// OBLIVIOUS model. The host returns indistinguishable ciphertext for any retrieval key, so\n// presence is UNKNOWABLE. A read therefore NEVER concludes \"not found\": it returns plaintext when\n// the URN key decrypts the bytes, otherwise the raw ciphertext (a decoy is just opaque bytes). The\n// only thrown error is a transport failure.\n\nimport { loadDigClientWasm } from \"./loader.js\";\nimport type { DigClientWasm } from \"./wasm.js\";\nimport { parseUrn } from \"./urn.js\";\nimport type { ReadOptions, ReadResult, UrnKeys } from \"./types.js\";\n\n/** The default public dig RPC endpoint. */\nexport const DEFAULT_RPC = \"https://rpc.dig.net\";\n\n// The backend caps each dig.getContent chunk at 3 MiB (Lambda/APIGW response ceiling); the client\n// loops chunks until `complete`.\nconst RPC_CHUNK_BYTES = 3 * 1024 * 1024;\n\n/** Options to construct a DigClient. */\nexport interface DigClientOptions {\n /** dig RPC endpoint. Defaults to the public `https://rpc.dig.net`. */\n rpc?: string;\n /** Override `fetch` (e.g. an instrumented one). Defaults to the global `fetch`. */\n fetch?: typeof fetch;\n}\n\ninterface GetContentResult {\n total_length: number;\n offset: number;\n next_offset?: number | null;\n complete?: boolean;\n ciphertext?: string;\n inclusion_proof?: string;\n chunk_lens?: number[];\n}\n\n/** Decode a standard-base64 string (the RPC ciphertext encoding) to bytes — no DOM dependency. */\nfunction b64ToBytes(b64: string): Uint8Array {\n // atob exists in browsers and modern Node; fall back to Buffer in older Node.\n if (typeof atob === \"function\") {\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Uint8Array((globalThis as any).Buffer.from(b64, \"base64\"));\n}\n\n/**\n * The read-crypto client. Construct once and reuse — the wasm is loaded + SRI-verified lazily on\n * the first read and memoized process/page-wide.\n *\n * @example\n * const dig = new DigClient();\n * const { bytes, decrypted } = await dig.read({\n * urn: \"urn:dig:chia:<storeId>/index.html\",\n * root: \"<onchain-root-hex>\",\n * });\n * if (decrypted) console.log(new TextDecoder().decode(bytes));\n */\nexport class DigClient {\n private readonly rpc: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(options: DigClientOptions = {}) {\n this.rpc = options.rpc ?? DEFAULT_RPC;\n this.fetchImpl =\n options.fetch ??\n (typeof fetch === \"function\" ? fetch.bind(globalThis) : undefinedFetch());\n }\n\n /** Load (and SRI-verify) the read-crypto wasm. Exposed for callers that want the raw functions. */\n async wasm(): Promise<DigClientWasm> {\n return loadDigClientWasm();\n }\n\n /** `retrieval_key = SHA-256(canonical rootless URN)`, lowercase hex. */\n async retrievalKey(storeId: string, resourceKey: string): Promise<string> {\n return (await this.wasm()).retrievalKey(storeId, resourceKey);\n }\n\n /** Derive the per-URN AES-256-GCM-SIV key, lowercase hex. `salt` for a private store. */\n async deriveKey(\n storeId: string,\n resourceKey: string,\n salt?: string | null,\n ): Promise<string> {\n return (await this.wasm()).deriveKey(storeId, resourceKey, salt ?? undefined);\n }\n\n /** Verify served `ciphertext` is included under `root` via the base64 merkle `proof`. */\n async verifyInclusion(\n ciphertext: Uint8Array,\n proof: string,\n root: string,\n ): Promise<boolean> {\n return (await this.wasm()).verifyInclusion(ciphertext, proof, root);\n }\n\n /** Reconstruct the canonical rootless URN whose SHA-256 is the retrieval key. */\n async reconstructUrn(storeId: string, resourceKey: string): Promise<string> {\n return (await this.wasm()).reconstructUrn(storeId, resourceKey);\n }\n\n /**\n * Derive, client-side, the two root-independent keys a URN maps to (retrieval + decryption).\n * Nothing is sent to the network — pure local derivation via the wasm.\n */\n async deriveUrnKeys(input: { urn: string; salt?: string | null }): Promise<UrnKeys> {\n const parsed = parseUrn(input.urn);\n const wasm = await this.wasm();\n const effSalt = input.salt ?? parsed.salt ?? undefined;\n return {\n storeId: parsed.storeId,\n root: parsed.root,\n resourceKey: parsed.resourceKey,\n salt: effSalt ?? null,\n retrievalKey: wasm.retrievalKey(parsed.storeId, parsed.resourceKey),\n decryptionKey: wasm.deriveKey(parsed.storeId, parsed.resourceKey, effSalt),\n };\n }\n\n /**\n * Fetch + verify + decrypt one resource by URN. `root` is the on-chain generation root to verify\n * against (resolved by the caller from the chain); when omitted, the root embedded in the URN is\n * used. Returns the bytes plus advisory `verified`/`decrypted` flags. NEVER throws \"not found\"\n * (presence is unknowable) — it throws only on a transport failure.\n */\n async read(\n input: { urn: string; root?: string | null; salt?: string | null },\n opts: ReadOptions = {},\n ): Promise<ReadResult> {\n const parsed = parseUrn(input.urn);\n const effSalt = input.salt ?? parsed.salt ?? null;\n const effRoot = input.root ?? parsed.root ?? null;\n if (!effRoot) {\n throw new Error(\n \"a confirmed on-chain root is required to read content (pass { root } or use a root-pinned URN)\",\n );\n }\n return this.readResource(\n { storeId: parsed.storeId, resourceKey: parsed.resourceKey, root: effRoot, salt: effSalt },\n opts,\n );\n }\n\n /** As `read`, but decoding the plaintext to a UTF-8 string when it decrypts (else throws). */\n async readText(\n input: { urn: string; root?: string | null; salt?: string | null },\n opts: ReadOptions = {},\n ): Promise<string> {\n const r = await this.read(input, opts);\n if (!r.decrypted) {\n throw new Error(\n \"resource did not decrypt under this URN — wrong store/key/salt, or a decoy response\",\n );\n }\n return new TextDecoder().decode(r.bytes);\n }\n\n /**\n * Read by explicit (storeId, resourceKey, root, salt) rather than a URN string. The oblivious\n * download primitive the URN read is built on.\n */\n async readResource(\n input: { storeId: string; resourceKey: string; root: string; salt?: string | null },\n opts: ReadOptions = {},\n ): Promise<ReadResult> {\n const rpc = opts.rpc ?? this.rpc;\n const wasm = await this.wasm();\n const rk = wasm.retrievalKey(input.storeId, input.resourceKey);\n const { ciphertext, proof, chunkLens } = await this.fetchCiphertext(\n input.storeId,\n rk,\n input.root,\n rpc,\n );\n let verified = false;\n try {\n verified = !!wasm.verifyInclusion(ciphertext, proof, input.root);\n } catch {\n verified = false;\n }\n const keyHex = wasm.deriveKey(input.storeId, input.resourceKey, input.salt ?? undefined);\n try {\n const bytes = decryptResourceChunks(wasm, keyHex, ciphertext, chunkLens);\n return {\n storeId: input.storeId,\n root: input.root,\n resourceKey: input.resourceKey,\n salt: input.salt ?? null,\n bytes,\n verified,\n decrypted: true,\n };\n } catch {\n // Not decryptable with this URN/salt — hand back the raw bytes; never a \"not present\" verdict.\n return {\n storeId: input.storeId,\n root: input.root,\n resourceKey: input.resourceKey,\n salt: input.salt ?? null,\n bytes: ciphertext,\n verified,\n decrypted: false,\n };\n }\n }\n\n // Stream the FULL ciphertext for a resource from the RPC by retrieval key, reassembling 3-MiB\n // chunks. A null result is a TRANSPORT failure, never a presence judgment.\n private async fetchCiphertext(\n storeId: string,\n rk: string,\n root: string,\n rpc: string,\n ): Promise<{ ciphertext: Uint8Array; proof: string; chunkLens: number[] | null }> {\n let offset = 0;\n let total: number | null = null;\n let buf: Uint8Array | null = null;\n let proof = \"\";\n let chunkLens: number[] | null = null;\n for (;;) {\n const r = await this.rpcCall<GetContentResult>(rpc, \"dig.getContent\", {\n store_id: storeId,\n root,\n retrieval_key: rk,\n offset,\n length: RPC_CHUNK_BYTES,\n });\n if (!r) throw new Error(\"The content network returned no data for this request.\");\n if (total === null) {\n total = r.total_length >>> 0;\n buf = new Uint8Array(total);\n }\n if (chunkLens === null && Array.isArray(r.chunk_lens)) {\n chunkLens = r.chunk_lens.map((n) => n >>> 0);\n }\n const chunk = b64ToBytes(r.ciphertext ?? \"\");\n const at = r.offset >>> 0;\n buf!.set(chunk.subarray(0, Math.max(0, Math.min(chunk.length, total - at))), at);\n if (r.inclusion_proof) proof = r.inclusion_proof;\n if (r.complete || r.next_offset == null) break;\n offset = r.next_offset >>> 0;\n }\n return { ciphertext: buf ?? new Uint8Array(0), proof, chunkLens };\n }\n\n // One JSON-RPC 2.0 call. Throws on transport failure or a JSON-RPC error; returns `result`.\n private async rpcCall<T>(rpc: string, method: string, params: unknown): Promise<T | null> {\n let res: Response;\n try {\n res = await this.fetchImpl(rpc, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method, params }),\n });\n } catch {\n throw new Error(\"Could not reach the content network. Check your connection and try again.\");\n }\n if (!res.ok) throw new Error(`dig RPC ${method} failed (${res.status})`);\n const json = (await res.json()) as { result?: T; error?: { message?: string } };\n if (json && json.error) throw new Error(`dig RPC ${method}: ${json.error.message ?? \"error\"}`);\n return json ? (json.result ?? null) : null;\n }\n}\n\n// AES-256-GCM-SIV-open a resource's served ciphertext under `keyHex`, splitting the PLAIN-\n// concatenated chunk ciphertexts by `chunkLens` (per-chunk CIPHERTEXT byte lengths) and opening\n// each. Empty/absent chunkLens ⇒ single-chunk resource. Throws if any chunk's tag fails.\nfunction decryptResourceChunks(\n wasm: DigClientWasm,\n keyHex: string,\n ciphertext: Uint8Array,\n chunkLens: number[] | null,\n): Uint8Array {\n const lens = chunkLens && chunkLens.length ? chunkLens : [ciphertext.length];\n const total = lens.reduce((a, n) => a + n, 0);\n if (total !== ciphertext.length) {\n throw new Error(\"served ciphertext length does not match chunk lengths\");\n }\n if (lens.length === 1) return wasm.decryptChunk(keyHex, ciphertext);\n const parts: Uint8Array[] = [];\n let p = 0;\n for (const len of lens) {\n parts.push(wasm.decryptChunk(keyHex, ciphertext.subarray(p, p + len)));\n p += len;\n }\n const out = new Uint8Array(parts.reduce((a, x) => a + x.length, 0));\n let q = 0;\n for (const part of parts) {\n out.set(part, q);\n q += part.length;\n }\n return out;\n}\n\nfunction undefinedFetch(): typeof fetch {\n return (() => {\n throw new Error(\n \"No global fetch available. Pass { fetch } to DigClient (Node < 18 needs a fetch polyfill).\",\n );\n }) as unknown as typeof fetch;\n}\n"]}