@dignetwork/dig-sdk 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +159 -11
  2. package/dist/adapters.cjs +56 -15
  3. package/dist/adapters.cjs.map +1 -1
  4. package/dist/adapters.d.cts +2 -2
  5. package/dist/adapters.d.ts +2 -2
  6. package/dist/adapters.js +56 -15
  7. package/dist/adapters.js.map +1 -1
  8. package/dist/{dev-shim-Bgw8X2E9.d.cts → dev-shim-DfKRA1ok.d.cts} +13 -3
  9. package/dist/{dev-shim-Bgw8X2E9.d.ts → dev-shim-DfKRA1ok.d.ts} +13 -3
  10. package/dist/{dig-client-entry-BIzuZ7Rs.d.cts → dig-client-entry-Bc95rd_t.d.cts} +120 -7
  11. package/dist/{dig-client-entry-BIzuZ7Rs.d.ts → dig-client-entry-Bc95rd_t.d.ts} +120 -7
  12. package/dist/dig-client.cjs +163 -43
  13. package/dist/dig-client.cjs.map +1 -1
  14. package/dist/dig-client.d.cts +1 -1
  15. package/dist/dig-client.d.ts +1 -1
  16. package/dist/dig-client.js +163 -43
  17. package/dist/dig-client.js.map +1 -1
  18. package/dist/index.cjs +495 -56
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +313 -3
  21. package/dist/index.d.ts +313 -3
  22. package/dist/index.js +489 -57
  23. package/dist/index.js.map +1 -1
  24. package/dist/next.cjs +58 -15
  25. package/dist/next.cjs.map +1 -1
  26. package/dist/next.d.cts +1 -1
  27. package/dist/next.d.ts +1 -1
  28. package/dist/next.js +58 -15
  29. package/dist/next.js.map +1 -1
  30. package/dist/vite.cjs +58 -15
  31. package/dist/vite.cjs.map +1 -1
  32. package/dist/vite.d.cts +1 -1
  33. package/dist/vite.d.ts +1 -1
  34. package/dist/vite.js +58 -15
  35. package/dist/vite.js.map +1 -1
  36. package/package.json +5 -6
  37. package/vendor/PROVENANCE.md +0 -102
  38. package/vendor/dig_client.d.ts +0 -150
  39. package/vendor/dig_client.mjs +0 -805
  40. package/vendor/dig_client_bg.wasm +0 -0
@@ -105,6 +105,77 @@ interface ReadResult {
105
105
  /** Did the bytes decrypt+authenticate under this URN's derived key? */
106
106
  decrypted: boolean;
107
107
  }
108
+ /**
109
+ * The on-chain CHIP-0007 metadata of a collection item, as returned by the dig RPC. Hashes are
110
+ * lowercase-hex 32-byte digests (or `null` when absent); URIs are the dig:// / https locations the
111
+ * bytes are served from. Mirrors the on-chain `NftMetadata` (the dig RPC decodes it from the NFT's
112
+ * metadata pointer). All fields optional/nullable so a non-standard metadata updater still parses.
113
+ */
114
+ interface CollectionItemMetadata {
115
+ /** 1-based edition number within the series. */
116
+ edition_number?: number;
117
+ /** Total editions in the series. */
118
+ edition_total?: number;
119
+ /** Primary media URIs (dig:// first, https fallback by convention). */
120
+ data_uris?: string[];
121
+ /** `sha256(media_bytes)`, lowercase hex, or null. */
122
+ data_hash?: string | null;
123
+ /** CHIP-0007 metadata-JSON URIs. */
124
+ metadata_uris?: string[];
125
+ /** `sha256(metadata_json_bytes)`, lowercase hex, or null. */
126
+ metadata_hash?: string | null;
127
+ /** License document URIs. */
128
+ license_uris?: string[];
129
+ /** `sha256(license_bytes)`, lowercase hex, or null. */
130
+ license_hash?: string | null;
131
+ }
132
+ /**
133
+ * One NFT in a collection, resolved to its CURRENT on-chain state by `DigClient.listCollectionItems`
134
+ * (owner-independent: the reported owner is live, walked forward through the singleton lineage, not
135
+ * the mint-time owner). All hashes/ids are lowercase hex.
136
+ */
137
+ interface CollectionItem {
138
+ /** The NFT's stable launcher id (its `nft1…` id encodes this), lowercase hex. */
139
+ launcher_id: string;
140
+ /** The current (unspent) coin id of the NFT singleton, lowercase hex. */
141
+ coin_id: string;
142
+ /** The current assigned owner DID launcher id (lowercase hex), or null when unattributed. */
143
+ owner_did: string | null;
144
+ /** The puzzle hash royalties are paid to in offer trades, lowercase hex. */
145
+ royalty_puzzle_hash: string;
146
+ /** Royalty as hundredths of a percent (300 = 3%). */
147
+ royalty_basis_points: number;
148
+ /** The CURRENT owner (p2) puzzle hash — where the NFT lives now, lowercase hex. */
149
+ owner_puzzle_hash: string;
150
+ /** The decoded on-chain CHIP-0007 metadata, or null when it does not decode. */
151
+ metadata: CollectionItemMetadata | null;
152
+ }
153
+ /** A deterministic, paginated page of collection items, from `DigClient.listCollectionItems`. */
154
+ interface CollectionItemsPage {
155
+ /** This page's items, in the requested (input launcher-id) order. */
156
+ items: CollectionItem[];
157
+ /** The offset this page started at. */
158
+ offset: number;
159
+ /** The page size requested (clamped to the server cap of 200). */
160
+ limit: number;
161
+ /** Total launcher ids in the requested collection set. */
162
+ total: number;
163
+ /** The offset of the next page, or null when this is the last page. */
164
+ next_offset: number | null;
165
+ }
166
+ /** Collection-level facts from `DigClient.getCollection` — derived from the resolved item set. */
167
+ interface CollectionMeta {
168
+ /** The creator DID launcher id the items AGREE on (lowercase hex), or null when mixed/none. */
169
+ did: string | null;
170
+ /** The DID the caller declared, echoed back (lowercase hex), or null. */
171
+ declared_did: string | null;
172
+ /** How many launcher ids were requested. */
173
+ item_count: number;
174
+ /** How many of those resolved to a live on-chain NFT. */
175
+ resolved_count: number;
176
+ /** The royalty (basis points) every item agrees on, or null when mixed. */
177
+ royalty_basis_points: number | null;
178
+ }
108
179
  /** The two root-independent keys a URN maps to (derived client-side, nothing sent to the network). */
109
180
  interface UrnKeys {
110
181
  storeId: string;
@@ -187,13 +258,55 @@ declare class DigClient {
187
258
  root: string;
188
259
  salt?: string | null;
189
260
  }, opts?: ReadOptions): Promise<ReadResult>;
261
+ /**
262
+ * Read a collection's public, owner-independent facts (creator DID, item count, uniform royalty)
263
+ * from the dig RPC (`dig.getCollection`). The collection's item set is its NFT launcher ids — the
264
+ * authoritative, owner-independent anchor the mint produced (a DID-attributed NFT is hinted to its
265
+ * OWNER at mint, not to the creator DID, so launcher ids — not the DID — are the read key). Pass
266
+ * the optional `did` to have it echoed back and recorded as the declared creator.
267
+ *
268
+ * No wallet, no read-crypto wasm — a plain JSON-RPC read. Throws a coded {@link DigSdkError} on a
269
+ * transport/RPC failure (never a "not found": an empty/partly-confirmed set just resolves to fewer
270
+ * items).
271
+ *
272
+ * @example
273
+ * const meta = await dig.getCollection({ launcherIds: ["ab…", "cd…"], did: "ef…" });
274
+ * console.log(meta.resolved_count, meta.royalty_basis_points);
275
+ */
276
+ getCollection(input: {
277
+ launcherIds: string[];
278
+ did?: string | null;
279
+ }, opts?: ReadOptions): Promise<CollectionMeta>;
280
+ /**
281
+ * Read a deterministic, paginated page of a collection's items (`dig.listCollectionItems`), each
282
+ * resolved to its CURRENT on-chain state — current owner, royalty, and CHIP-0007 metadata — by the
283
+ * RPC walking the singleton lineage forward to the live tip (so the owner is never the stale
284
+ * mint-time owner). Items come back in the input launcher-id order. `limit` is clamped to the
285
+ * server cap (200); `offset` defaults to 0.
286
+ *
287
+ * Throws a coded {@link DigSdkError} on a transport/RPC failure.
288
+ *
289
+ * @example
290
+ * let page = await dig.listCollectionItems({ launcherIds, limit: 50 });
291
+ * for (const item of page.items) console.log(item.launcher_id, item.owner_puzzle_hash);
292
+ * // page.next_offset is null on the last page.
293
+ */
294
+ listCollectionItems(input: {
295
+ launcherIds: string[];
296
+ offset?: number;
297
+ limit?: number;
298
+ }, opts?: ReadOptions): Promise<CollectionItemsPage>;
190
299
  private fetchCiphertext;
191
300
  private rpcCall;
192
301
  }
193
302
 
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/. */
303
+ /**
304
+ * SHA-256 (lowercase hex) of `@dignetwork/dig-client`'s `dig_client_bg.wasm` — the SRI digest. It
305
+ * is the canonical trust anchor (pinned regardless of the npm semver), mirrored by the package's
306
+ * `integrity.json` `sha256`. Fail closed on a mismatch.
307
+ */
308
+ declare const DIG_CLIENT_WASM_SHA256 = "8c983561eabca34778abf698ca7c2fba36117f87282ca649079599ef7d1b1156";
309
+ /** Optional explicit wasm inputs, for environments where package resolution can't reach the wasm. */
197
310
  interface WasmConfig {
198
311
  /**
199
312
  * The wasm bytes (already loaded). When provided, SRI is still enforced unless `skipIntegrity`.
@@ -201,13 +314,13 @@ interface WasmConfig {
201
314
  */
202
315
  wasmBytes?: BufferSource;
203
316
  /**
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.
317
+ * URL to the wasm-bindgen `web` glue module for browser dynamic import. When omitted in a browser,
318
+ * the loader imports `@dignetwork/dig-client/web` (the bundler resolves it).
206
319
  */
207
320
  glueUrl?: string;
208
321
  /**
209
322
  * URL to fetch the wasm bytes from (browser) when `wasmBytes` is not supplied. The fetched bytes
210
- * are SRI-verified before init.
323
+ * are SRI-verified before init. Defaults to the package's `dig_client_bg.wasm`.
211
324
  */
212
325
  wasmUrl?: string;
213
326
  /** Skip the SRI check. Only for tests / trusted custom builds — NOT recommended. */
@@ -260,4 +373,4 @@ declare function reconstructUrn(storeId: string, resourceKey: string): string;
260
373
  */
261
374
  declare function reconstructUrnWithRoot(storeId: string, root: string, resourceKey: string): string;
262
375
 
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 };
376
+ export { type CollectionItem as C, 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, type CollectionItemMetadata as b, type CollectionItemsPage as c, type CollectionMeta as d, DIG_CLIENT_WASM_SHA256 as e, DigClient as f, type DigClientOptions as g, type DigClientWasm as h, type ReadResult as i, type WasmConfig as j, configureWasm as k, isUrn as l, loadDigClientWasm as m, reconstructUrnWithRoot as n, parseUrn as p, reconstructUrn as r };
@@ -1,8 +1,28 @@
1
1
  'use strict';
2
2
 
3
3
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
4
+ // src/errors.ts
5
+ var DIG_SDK_ERROR_BRAND = "__dignetwork_dig_sdk_error__";
6
+ var DigSdkError = class _DigSdkError extends Error {
7
+ constructor(code, message, context = {}, options = {}) {
8
+ super(message);
9
+ this.name = "DigSdkError";
10
+ this.code = code;
11
+ this.context = context;
12
+ if (options.cause !== void 0) {
13
+ this.cause = options.cause;
14
+ }
15
+ Object.defineProperty(this, DIG_SDK_ERROR_BRAND, { value: true, enumerable: false });
16
+ Object.setPrototypeOf(this, _DigSdkError.prototype);
17
+ }
18
+ /** A JSON-friendly view of the error: `{ code, message, context }`. */
19
+ toJSON() {
20
+ return { code: this.code, message: this.message, context: this.context };
21
+ }
22
+ };
23
+
4
24
  // src/loader.ts
5
- var DIG_CLIENT_WASM_SHA256 = "ff486be806f908a2a90780e499a04dbd34e10e3b97be0470cb9ee841a1e49e77";
25
+ var DIG_CLIENT_WASM_SHA256 = "8c983561eabca34778abf698ca7c2fba36117f87282ca649079599ef7d1b1156";
6
26
  var _config = {};
7
27
  var _ready = null;
8
28
  function configureWasm(config) {
@@ -26,49 +46,62 @@ async function sha256Hex(bytes) {
26
46
  function assertIntegrity(hex) {
27
47
  if (_config.skipIntegrity) return;
28
48
  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}).`
49
+ throw new DigSdkError(
50
+ "WASM_INTEGRITY",
51
+ `dig-client wasm integrity check failed \u2014 refusing to run unverified crypto (expected ${DIG_CLIENT_WASM_SHA256}, got ${hex}).`,
52
+ { expected: DIG_CLIENT_WASM_SHA256, actual: hex }
31
53
  );
32
54
  }
33
55
  }
34
56
  async function loadNode() {
57
+ const { createRequire } = await import('module');
35
58
  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");
59
+ const require2 = createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('dig-client.cjs', document.baseURI).href)));
60
+ const wasmPath = require2.resolve("@dignetwork/dig-client/dig_client_bg.wasm");
42
61
  const buf = await readFile(wasmPath);
43
62
  const bytes = new Uint8Array(buf.byteLength);
44
63
  bytes.set(buf);
45
- return { glueHref: pathToFileURL(gluePath).href, bytes };
64
+ assertIntegrity(await sha256Hex(bytes));
65
+ const mod = await import('@dignetwork/dig-client/node');
66
+ return mod;
46
67
  }
47
68
  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;
69
+ const glueHref = _config.glueUrl ?? "@dignetwork/dig-client/web";
70
+ const mod = await import(
71
+ /* @vite-ignore */
72
+ glueHref
73
+ );
74
+ if (typeof mod.default !== "function") {
75
+ throw new DigSdkError(
76
+ "WASM_LOAD_FAILED",
77
+ "dig-client web build exposed no init function (unexpected module shape)",
78
+ {}
79
+ );
80
+ }
81
+ if (_config.wasmBytes || _config.wasmUrl) {
82
+ let bytes;
83
+ if (_config.wasmBytes) {
84
+ bytes = _config.wasmBytes;
85
+ } else {
86
+ const wasmUrl = _config.wasmUrl;
87
+ const res = await fetch(wasmUrl);
88
+ if (!res.ok)
89
+ throw new DigSdkError("WASM_LOAD_FAILED", `dig-client wasm fetch failed (${res.status})`, {
90
+ httpStatus: res.status,
91
+ wasmUrl
92
+ });
93
+ bytes = await res.arrayBuffer();
94
+ }
95
+ assertIntegrity(await sha256Hex(bytes));
96
+ await mod.default({ module_or_path: bytes });
52
97
  } 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();
98
+ await mod.default();
57
99
  }
58
- return { glueHref, bytes };
100
+ return mod;
59
101
  }
60
102
  function loadDigClientWasm() {
61
103
  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) => {
104
+ _ready = (isNode ? loadNode() : loadBrowser()).catch((e) => {
72
105
  _ready = null;
73
106
  throw e;
74
107
  });
@@ -81,8 +114,10 @@ function parseUrn(raw) {
81
114
  const s = String(raw ?? "").trim();
82
115
  const m = URN_RE.exec(s);
83
116
  if (!m) {
84
- throw new Error(
85
- "Not a valid dig URN (expected urn:dig:chia:<store-id>[:<root>]/<path>[?salt=<hex>])."
117
+ throw new DigSdkError(
118
+ "INVALID_ARGUMENT",
119
+ "Not a valid dig URN (expected urn:dig:chia:<store-id>[:<root>]/<path>[?salt=<hex>]).",
120
+ { value: s, expected: "urn:dig:chia:<store-id>[:<root>]/<path>[?salt=<hex>]" }
86
121
  );
87
122
  }
88
123
  return {
@@ -174,8 +209,10 @@ var DigClient = class {
174
209
  const effSalt = input.salt ?? parsed.salt ?? null;
175
210
  const effRoot = input.root ?? parsed.root ?? null;
176
211
  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)"
212
+ throw new DigSdkError(
213
+ "ROOT_REQUIRED",
214
+ "a confirmed on-chain root is required to read content (pass { root } or use a root-pinned URN)",
215
+ { urn: input.urn }
179
216
  );
180
217
  }
181
218
  return this.readResource(
@@ -187,8 +224,10 @@ var DigClient = class {
187
224
  async readText(input, opts = {}) {
188
225
  const r = await this.read(input, opts);
189
226
  if (!r.decrypted) {
190
- throw new Error(
191
- "resource did not decrypt under this URN \u2014 wrong store/key/salt, or a decoy response"
227
+ throw new DigSdkError(
228
+ "DECRYPT_FAILED",
229
+ "resource did not decrypt under this URN \u2014 wrong store/key/salt, or a decoy response",
230
+ { urn: input.urn }
192
231
  );
193
232
  }
194
233
  return new TextDecoder().decode(r.bytes);
@@ -237,6 +276,62 @@ var DigClient = class {
237
276
  };
238
277
  }
239
278
  }
279
+ /**
280
+ * Read a collection's public, owner-independent facts (creator DID, item count, uniform royalty)
281
+ * from the dig RPC (`dig.getCollection`). The collection's item set is its NFT launcher ids — the
282
+ * authoritative, owner-independent anchor the mint produced (a DID-attributed NFT is hinted to its
283
+ * OWNER at mint, not to the creator DID, so launcher ids — not the DID — are the read key). Pass
284
+ * the optional `did` to have it echoed back and recorded as the declared creator.
285
+ *
286
+ * No wallet, no read-crypto wasm — a plain JSON-RPC read. Throws a coded {@link DigSdkError} on a
287
+ * transport/RPC failure (never a "not found": an empty/partly-confirmed set just resolves to fewer
288
+ * items).
289
+ *
290
+ * @example
291
+ * const meta = await dig.getCollection({ launcherIds: ["ab…", "cd…"], did: "ef…" });
292
+ * console.log(meta.resolved_count, meta.royalty_basis_points);
293
+ */
294
+ async getCollection(input, opts = {}) {
295
+ const rpc = opts.rpc ?? this.rpc;
296
+ const params = { launcher_ids: input.launcherIds };
297
+ if (input.did) params.did = input.did;
298
+ const r = await this.rpcCall(rpc, "dig.getCollection", params);
299
+ if (!r)
300
+ throw new DigSdkError(
301
+ "RPC_MALFORMED_RESPONSE",
302
+ "The content network returned no collection facts for this request.",
303
+ { rpcMethod: "dig.getCollection" }
304
+ );
305
+ return r;
306
+ }
307
+ /**
308
+ * Read a deterministic, paginated page of a collection's items (`dig.listCollectionItems`), each
309
+ * resolved to its CURRENT on-chain state — current owner, royalty, and CHIP-0007 metadata — by the
310
+ * RPC walking the singleton lineage forward to the live tip (so the owner is never the stale
311
+ * mint-time owner). Items come back in the input launcher-id order. `limit` is clamped to the
312
+ * server cap (200); `offset` defaults to 0.
313
+ *
314
+ * Throws a coded {@link DigSdkError} on a transport/RPC failure.
315
+ *
316
+ * @example
317
+ * let page = await dig.listCollectionItems({ launcherIds, limit: 50 });
318
+ * for (const item of page.items) console.log(item.launcher_id, item.owner_puzzle_hash);
319
+ * // page.next_offset is null on the last page.
320
+ */
321
+ async listCollectionItems(input, opts = {}) {
322
+ const rpc = opts.rpc ?? this.rpc;
323
+ const params = { launcher_ids: input.launcherIds };
324
+ if (input.offset !== void 0) params.offset = input.offset;
325
+ if (input.limit !== void 0) params.limit = input.limit;
326
+ const r = await this.rpcCall(rpc, "dig.listCollectionItems", params);
327
+ if (!r)
328
+ throw new DigSdkError(
329
+ "RPC_MALFORMED_RESPONSE",
330
+ "The content network returned no collection items for this request.",
331
+ { rpcMethod: "dig.listCollectionItems" }
332
+ );
333
+ return r;
334
+ }
240
335
  // Stream the FULL ciphertext for a resource from the RPC by retrieval key, reassembling 3-MiB
241
336
  // chunks. A null result is a TRANSPORT failure, never a presence judgment.
242
337
  async fetchCiphertext(storeId, rk, root, rpc) {
@@ -253,7 +348,12 @@ var DigClient = class {
253
348
  offset,
254
349
  length: RPC_CHUNK_BYTES
255
350
  });
256
- if (!r) throw new Error("The content network returned no data for this request.");
351
+ if (!r)
352
+ throw new DigSdkError(
353
+ "RPC_MALFORMED_RESPONSE",
354
+ "The content network returned no data for this request.",
355
+ { rpcMethod: "dig.getContent" }
356
+ );
257
357
  if (total === null) {
258
358
  total = r.total_length >>> 0;
259
359
  buf = new Uint8Array(total);
@@ -270,7 +370,8 @@ var DigClient = class {
270
370
  }
271
371
  return { ciphertext: buf ?? new Uint8Array(0), proof, chunkLens };
272
372
  }
273
- // One JSON-RPC 2.0 call. Throws on transport failure or a JSON-RPC error; returns `result`.
373
+ // One JSON-RPC 2.0 call. Throws a coded DigSdkError on transport failure (RPC_TRANSPORT) or a
374
+ // JSON-RPC/HTTP error (RPC_ERROR, carrying rpcMethod/httpStatus/rpcCode context); returns `result`.
274
375
  async rpcCall(rpc, method, params) {
275
376
  let res;
276
377
  try {
@@ -279,12 +380,26 @@ var DigClient = class {
279
380
  headers: { "content-type": "application/json" },
280
381
  body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params })
281
382
  });
282
- } catch {
283
- throw new Error("Could not reach the content network. Check your connection and try again.");
383
+ } catch (e) {
384
+ throw new DigSdkError(
385
+ "RPC_TRANSPORT",
386
+ "Could not reach the content network. Check your connection and try again.",
387
+ { rpcMethod: method },
388
+ { cause: e }
389
+ );
284
390
  }
285
- if (!res.ok) throw new Error(`dig RPC ${method} failed (${res.status})`);
391
+ if (!res.ok)
392
+ throw new DigSdkError("RPC_ERROR", `dig RPC ${method} failed (${res.status})`, {
393
+ rpcMethod: method,
394
+ httpStatus: res.status
395
+ });
286
396
  const json = await res.json();
287
- if (json && json.error) throw new Error(`dig RPC ${method}: ${json.error.message ?? "error"}`);
397
+ if (json && json.error)
398
+ throw new DigSdkError(
399
+ "RPC_ERROR",
400
+ `dig RPC ${method}: ${json.error.message ?? "error"}`,
401
+ { rpcMethod: method, rpcCode: json.error.code }
402
+ );
288
403
  return json ? json.result ?? null : null;
289
404
  }
290
405
  };
@@ -292,7 +407,11 @@ function decryptResourceChunks(wasm, keyHex, ciphertext, chunkLens) {
292
407
  const lens = chunkLens && chunkLens.length ? chunkLens : [ciphertext.length];
293
408
  const total = lens.reduce((a, n) => a + n, 0);
294
409
  if (total !== ciphertext.length) {
295
- throw new Error("served ciphertext length does not match chunk lengths");
410
+ throw new DigSdkError(
411
+ "RPC_MALFORMED_RESPONSE",
412
+ "served ciphertext length does not match chunk lengths",
413
+ { rpcMethod: "dig.getContent", expected: String(total), actual: String(ciphertext.length) }
414
+ );
296
415
  }
297
416
  if (lens.length === 1) return wasm.decryptChunk(keyHex, ciphertext);
298
417
  const parts = [];
@@ -311,7 +430,8 @@ function decryptResourceChunks(wasm, keyHex, ciphertext, chunkLens) {
311
430
  }
312
431
  function undefinedFetch() {
313
432
  return (() => {
314
- throw new Error(
433
+ throw new DigSdkError(
434
+ "INVALID_ARGUMENT",
315
435
  "No global fetch available. Pass { fetch } to DigClient (Node < 18 needs a fetch polyfill)."
316
436
  );
317
437
  });