@inversealtruism/cairn-sdk 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,6 @@ The **Compute Substrate dApp kit:** one cohesive toolkit for building apps on CS
8
8
  | `cairn.chain` | Node RPC + transaction builders + a verifying **light client** (re-exports the `csd-*` primitives). |
9
9
  | `cairn.index` | The L2 **explorer/indexer**: REST + merkle proofs + live SSE/WS feeds. |
10
10
  | `cairn.content` | **Self-certifying content:** hash for an on-chain Propose, fetch with client-side verification. |
11
- | `cairn.registry` | L3 **peer / gateway / identity** resolution. |
12
11
  | `cairn.names` | **.csd names + CairnX reads:** name resolution, reverse/primary lookup, tokens, offers, bids, canonical state. |
13
12
 
14
13
  ```bash
@@ -57,7 +56,7 @@ try {
57
56
 
58
57
  ## API by namespace
59
58
 
60
- **`cairn.index`:** `tipHeight()`, `block()/blockTxids()`, `tx()/txStatus()/txMerkleProof()`, `address()/addressTxs()/addressUtxo()`, `domains()/domainProposals(domain)`, `proposal()/attestations()`, `reputation()`, `registryPeers()/registryGateways()/identity()`, **`verifyInclusion(txid)`** (trust-minimized), `streamAll()/streamBlocks()/streamDomain()` (SSE), `subscribe()` (WS).
59
+ **`cairn.index`:** `tipHeight()`, `block()/blockTxids()`, `tx()/txStatus()/txMerkleProof()`, `address()/addressTxs()/addressUtxo()`, `domains()/domainProposals(domain)`, `proposal()/attestations()`, `reputation()`, **`verifyInclusion(txid)`** (trust-minimized), `streamAll()/streamBlocks()/streamDomain()` (SSE), `subscribe()` (WS).
61
60
 
62
61
  **`cairn.names`:** `resolve(name)` (display-path name to address), `name(name)`/`nameHistory(name)`, `primary(addr)` (reverse lookup)/`namesOf(addr)`, `names()`, `tokens()/token(ticker)`, `offers()`, `bids()`, `state()` (the canonical CairnX state). Reads go through the public `/trade/api/cairnx/*` proxy; for payment-grade name resolution verify through the wallet or a replaying resolver, not a bare read (see `src/names.ts` header).
63
62
 
@@ -65,13 +64,11 @@ try {
65
64
 
66
65
  **`cairn.chain`:** `tip()`, `utxos(addr)`, `submit(nodeJsonTx)`, `.client` (full `CsdClient`), `.light()` (verifying light client). The package also re-exports the primitives under the `/chain` subpath: `buildSend/buildPropose/buildAttest`, `signTx`, `keygen`, `payloadHash`, `verifyMerkleProof`, `LightClient`, etc.
67
66
 
68
- **`cairn.registry`:** `gateways()`, `peers()`, `resolveName(handle)`, `reverseName(addr)`, `.fromRecords` (deterministic local resolvers).
69
-
70
- Subpath imports are available for tree-shaking: `@inversealtruism/cairn-sdk/{connect,indexer,content,registry,chain,controller,react}`.
67
+ Subpath imports are available for tree-shaking: `@inversealtruism/cairn-sdk/{connect,indexer,content,chain,controller,react}`.
71
68
 
72
69
  ## Examples
73
70
 
74
- - **`examples/read-only.mjs`:** runs today against live mainnet, no wallet, no build: `npm run test:live`. Demonstrates chain/indexer/registry reads + verified merkle inclusion + verified content fetch.
71
+ - **`examples/read-only.mjs`:** runs today against live mainnet, no wallet, no build: `npm run test:live`. Demonstrates chain/indexer reads + verified merkle inclusion + verified content fetch.
75
72
  - **`examples/hello-csd/`:** a no-framework browser dApp (connect → read recent proposals → live feed). Build the bundle with `npm run build:example`, then serve the folder from **localhost** (the wallet injects there) with the Cairn Wallet installed.
76
73
 
77
74
  ## Trust model & honest limits
@@ -79,7 +76,8 @@ Subpath imports are available for tree-shaking: `@inversealtruism/cairn-sdk/{con
79
76
  - **Content is always verified client-side.** `cairn.content.get()` rejects bytes that don't hash to the requested `payloadHash`, an untrusted gateway can't serve tampered content.
80
77
  - **Merkle inclusion is trust-minimized, to the strength of your header source.** `verifyInclusion()` folds the proof and cross-checks its root against a header merkle from `headerMerkleAt`. The default `Cairn` wiring backs that with a light client that PoW-verifies headers forward from a pinned checkpoint, so a match reads `trustLevel: "verified-inclusion"` with `included: true`. A header within 12 blocks of the light client's cached tip is first compared with the header the base serves at that height, so a block orphaned by a reorg stops counting; the hosted base edge-caches rows at or below its tip minus 6, so there this catches reorgs of up to 6 blocks. When no header can be verified (below the checkpoint, header source unreachable, no source configured) the result is `"proof-consistent"` with `included: false` and a `reason`: the indexer alone vouches for it. Gate on `included` or on `trustLevel === "verified-inclusion"`; they agree.
81
78
  - **Balances are RPC-trusted.** Headers don't commit to the UTXO set; balance reads trust the node/proxy (same as every light client).
82
- - **Indexer/swarm run behind the cairn proxy.** By default `cairn.index` and content resolution use the cairn server's hardened, read-only, rate-limited `/explorer/api` reverse proxy (no separate public indexer needed). **SSE works through it; `subscribe()` (WebSocket) needs a direct indexer endpoint:** set `baseUrls.indexer` to a private/localhost indexer for WS.
79
+ - **Content comes from the cairn origin.** `cairn.content` reads `/content/<hash>` on the cairn base and verifies every byte against the hash.
80
+ - **The indexer runs behind the cairn proxy.** By default `cairn.index` uses the cairn server's hardened, read-only, rate-limited `/explorer/api` reverse proxy (no separate public indexer needed). **SSE works through that proxy; `subscribe()` (WebSocket) needs a direct indexer endpoint:** set `baseUrls.indexer` to a private/localhost indexer for WS.
83
81
  - **The wallet injects on every site** (connect-anywhere shipped in 0.2.4x) behind a per-origin consent gate: a site sees nothing until the user approves the connection, and some request kinds stay first-party-only (the `FIRST_PARTY_ONLY` error code).
84
82
 
85
83
  ## Configuration
@@ -91,7 +89,6 @@ new Cairn({
91
89
  cairn: "https://cairn-substrate.com", // /api/rpc proxy + /api/headers + /content origin + names
92
90
  rpc: "https://cairn-substrate.com/api/rpc", // node RPC (proxy)
93
91
  indexer: "https://cairn-substrate.com/explorer/api",
94
- swarm: undefined, // optional direct swarm gateway
95
92
  },
96
93
  fetch, // custom fetch (Node <18, tests)
97
94
  timeoutMs: 15000,
@@ -103,8 +100,8 @@ new Cairn({
103
100
 
104
101
  ```bash
105
102
  pnpm build && pnpm test # unit (offline): error mapping, client paths, content+merkle verify
106
- pnpm test:e2e:read # live reads vs mainnet + adversarial (free)
107
- pnpm test:e2e:wallet # real extension + real connector under Xvfb: connect/consent/sign (free)
103
+ pnpm test:live # examples/read-only.mjs + live reads vs mainnet + adversarial (free)
104
+ pnpm test:live:wallet # real extension + real connector under Xvfb: connect/consent/sign (free)
108
105
  ```
109
106
 
110
107
  See [`test/e2e/README.md`](test/e2e/README.md) for coverage, requirements, and cost of each layer. All three suites are free; none spends CSD.
@@ -4,7 +4,7 @@ import {
4
4
  UnsupportedMethodError,
5
5
  mapProviderError,
6
6
  mapSubmitResultError
7
- } from "./chunk-OSPAN7GX.js";
7
+ } from "./chunk-PBKDSDID.js";
8
8
 
9
9
  // src/connect.ts
10
10
  var DEFAULT_PROVIDER_TIMEOUT_MS = 10 * 6e4;
@@ -69,18 +69,6 @@ var IndexerClient = class {
69
69
  attestations(id) {
70
70
  return this.http.getJson(`/proposal/${encodeURIComponent(id)}/attestations`);
71
71
  }
72
- registryPeers() {
73
- return this.http.getJson("/registry/peers");
74
- }
75
- registryGateways() {
76
- return this.http.getJson("/registry/gateways");
77
- }
78
- identity(handle) {
79
- return this.http.getJson(`/identity/${encodeURIComponent(handle)}`);
80
- }
81
- reverseIdentity(addr) {
82
- return this.http.getJson(`/address/${encodeURIComponent(addr)}/identity`);
83
- }
84
72
  // ---- trust-minimized inclusion ----------------------------------------
85
73
  /**
86
74
  * Verify a tx is included in a block by folding its merkle branch to the root
@@ -1,5 +1,5 @@
1
1
  // src/errors.ts
2
- var SDK_VERSION = "0.5.0";
2
+ var SDK_VERSION = "0.7.0";
3
3
  var DOCS_BASE = "https://cairn-substrate.com/docs/sdk";
4
4
  var CairnError = class extends Error {
5
5
  /** Stable machine code for programmatic branching. */
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  CairnError,
3
3
  ContentVerificationError
4
- } from "./chunk-OSPAN7GX.js";
4
+ } from "./chunk-PBKDSDID.js";
5
5
 
6
6
  // src/content.ts
7
7
  import { payloadHash, canonicalJson, verifyContentBytes } from "@inversealtruism/csd-codec";
8
8
  var ContentClient = class {
9
- sources;
9
+ cairn;
10
10
  constructor(opts) {
11
- this.sources = [];
12
- if (opts.swarm) this.sources.push({ name: "swarm", http: opts.swarm, path: (h) => `/content/${h}` });
13
- if (opts.indexer) this.sources.push({ name: "indexer", http: opts.indexer, path: (h) => `/content/${h}` });
14
- if (opts.cairn) this.sources.push({ name: "cairn", http: opts.cairn, path: (h) => `/content/${h}` });
11
+ if (!opts?.cairn || typeof opts.cairn.getBytes !== "function") {
12
+ throw new TypeError("ContentClient needs a `cairn` Http client (the swarm and indexer sources were removed in 0.7.0)");
13
+ }
14
+ this.cairn = opts.cairn;
15
15
  }
16
16
  /**
17
17
  * Compute the canonical hash + bytes for an object, ready to anchor on-chain.
@@ -35,31 +35,21 @@ var ContentClient = class {
35
35
  }
36
36
  /**
37
37
  * Fetch content by hash and VERIFY it self-certifies (sha256(bytes) == hash).
38
- * Tries each configured source in order; a source that is unreachable, lacks
39
- * the content or serves bytes that don't match the hash is skipped. Returns the
40
- * first verified bytes, or null if no source holds it. Throws
41
- * ContentVerificationError only when no source served verified bytes and at
42
- * least one served mismatching bytes (tampering / wrong object).
38
+ * Returns the verified bytes, or null when the origin does not hold the content
39
+ * or cannot be reached (as 0.6.0 did when every source failed). Throws
40
+ * ContentVerificationError when the origin serves bytes that don't match the hash.
43
41
  */
44
42
  async getBytes(hash) {
45
43
  const h = normalizeHash(hash);
46
- let mismatched = false;
47
- for (const src of this.sources) {
48
- let got = null;
49
- try {
50
- got = await src.http.getBytes(src.path(h));
51
- } catch {
52
- continue;
53
- }
54
- if (!got) continue;
55
- if (!verifyContentBytes(got.bytes, h)) {
56
- mismatched = true;
57
- continue;
58
- }
59
- return got.bytes;
44
+ let got = null;
45
+ try {
46
+ got = await this.cairn.getBytes(`/content/${h}`);
47
+ } catch {
48
+ return null;
60
49
  }
61
- if (mismatched) throw new ContentVerificationError(h);
62
- return null;
50
+ if (!got) return null;
51
+ if (!verifyContentBytes(got.bytes, h)) throw new ContentVerificationError(h);
52
+ return got.bytes;
63
53
  }
64
54
  /** Fetch + verify + parse as UTF-8 JSON. Returns null if not found. Throws a CairnError with code
65
55
  * CONTENT_NOT_JSON when the verified bytes are not JSON. */
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getWallet
3
- } from "./chunk-5RGFC2JR.js";
3
+ } from "./chunk-4FFLCCL4.js";
4
4
 
5
5
  // src/controller.ts
6
6
  var DISCONNECTED = Object.freeze({ status: "disconnected", account: null, error: null });
package/dist/connect.cjs CHANGED
@@ -30,7 +30,7 @@ __export(connect_exports, {
30
30
  module.exports = __toCommonJS(connect_exports);
31
31
 
32
32
  // src/errors.ts
33
- var SDK_VERSION = "0.5.0";
33
+ var SDK_VERSION = "0.7.0";
34
34
  var DOCS_BASE = "https://cairn-substrate.com/docs/sdk";
35
35
  var CairnError = class extends Error {
36
36
  /** Stable machine code for programmatic branching. */
package/dist/connect.js CHANGED
@@ -5,8 +5,8 @@ import {
5
5
  discoverProviders,
6
6
  getWallet,
7
7
  isInstalled
8
- } from "./chunk-5RGFC2JR.js";
9
- import "./chunk-OSPAN7GX.js";
8
+ } from "./chunk-4FFLCCL4.js";
9
+ import "./chunk-PBKDSDID.js";
10
10
  export {
11
11
  WalletConnection,
12
12
  connect,
package/dist/content.cjs CHANGED
@@ -26,7 +26,7 @@ module.exports = __toCommonJS(content_exports);
26
26
  var import_csd_codec = require("@inversealtruism/csd-codec");
27
27
 
28
28
  // src/errors.ts
29
- var SDK_VERSION = "0.5.0";
29
+ var SDK_VERSION = "0.7.0";
30
30
  var DOCS_BASE = "https://cairn-substrate.com/docs/sdk";
31
31
  var CairnError = class extends Error {
32
32
  /** Stable machine code for programmatic branching. */
@@ -80,12 +80,12 @@ var ContentVerificationError = class extends CairnError {
80
80
 
81
81
  // src/content.ts
82
82
  var ContentClient = class {
83
- sources;
83
+ cairn;
84
84
  constructor(opts) {
85
- this.sources = [];
86
- if (opts.swarm) this.sources.push({ name: "swarm", http: opts.swarm, path: (h) => `/content/${h}` });
87
- if (opts.indexer) this.sources.push({ name: "indexer", http: opts.indexer, path: (h) => `/content/${h}` });
88
- if (opts.cairn) this.sources.push({ name: "cairn", http: opts.cairn, path: (h) => `/content/${h}` });
85
+ if (!opts?.cairn || typeof opts.cairn.getBytes !== "function") {
86
+ throw new TypeError("ContentClient needs a `cairn` Http client (the swarm and indexer sources were removed in 0.7.0)");
87
+ }
88
+ this.cairn = opts.cairn;
89
89
  }
90
90
  /**
91
91
  * Compute the canonical hash + bytes for an object, ready to anchor on-chain.
@@ -109,31 +109,21 @@ var ContentClient = class {
109
109
  }
110
110
  /**
111
111
  * Fetch content by hash and VERIFY it self-certifies (sha256(bytes) == hash).
112
- * Tries each configured source in order; a source that is unreachable, lacks
113
- * the content or serves bytes that don't match the hash is skipped. Returns the
114
- * first verified bytes, or null if no source holds it. Throws
115
- * ContentVerificationError only when no source served verified bytes and at
116
- * least one served mismatching bytes (tampering / wrong object).
112
+ * Returns the verified bytes, or null when the origin does not hold the content
113
+ * or cannot be reached (as 0.6.0 did when every source failed). Throws
114
+ * ContentVerificationError when the origin serves bytes that don't match the hash.
117
115
  */
118
116
  async getBytes(hash) {
119
117
  const h = normalizeHash(hash);
120
- let mismatched = false;
121
- for (const src of this.sources) {
122
- let got = null;
123
- try {
124
- got = await src.http.getBytes(src.path(h));
125
- } catch {
126
- continue;
127
- }
128
- if (!got) continue;
129
- if (!(0, import_csd_codec.verifyContentBytes)(got.bytes, h)) {
130
- mismatched = true;
131
- continue;
132
- }
133
- return got.bytes;
118
+ let got = null;
119
+ try {
120
+ got = await this.cairn.getBytes(`/content/${h}`);
121
+ } catch {
122
+ return null;
134
123
  }
135
- if (mismatched) throw new ContentVerificationError(h);
136
- return null;
124
+ if (!got) return null;
125
+ if (!(0, import_csd_codec.verifyContentBytes)(got.bytes, h)) throw new ContentVerificationError(h);
126
+ return got.bytes;
137
127
  }
138
128
  /** Fetch + verify + parse as UTF-8 JSON. Returns null if not found. Throws a CairnError with code
139
129
  * CONTENT_NOT_JSON when the verified bytes are not JSON. */
@@ -1,23 +1,19 @@
1
1
  import { H as Http } from './http-C9C4L4hz.cjs';
2
2
 
3
3
  interface ContentClientOptions {
4
- /** Swarm gateway HTTP client (e.g. https://cairn-substrate.com/swarm). */
5
- swarm?: Http;
6
- /** Cairn origin HTTP client (serves /content as origin + fallback). */
7
- cairn?: Http;
8
- /** Indexer HTTP client (also joins the swarm gateway at /content). */
9
- indexer?: Http;
4
+ /** Cairn origin HTTP client; it serves `/content/<hash>`. */
5
+ cairn: Http;
10
6
  }
11
7
  interface PreparedContent {
12
8
  /** The 0x-prefixed sha256 payload hash that goes on-chain. */
13
9
  payloadHash: string;
14
10
  /** The exact canonical JSON string that was hashed. */
15
11
  canonical: string;
16
- /** UTF-8 bytes of the canonical JSON (what the swarm stores / serves). */
12
+ /** UTF-8 bytes of the canonical JSON (what the origin stores and serves). */
17
13
  bytes: Uint8Array;
18
14
  }
19
15
  declare class ContentClient {
20
- private readonly sources;
16
+ private readonly cairn;
21
17
  constructor(opts: ContentClientOptions);
22
18
  /**
23
19
  * Compute the canonical hash + bytes for an object, ready to anchor on-chain.
@@ -30,11 +26,9 @@ declare class ContentClient {
30
26
  hash(obj: unknown): string;
31
27
  /**
32
28
  * Fetch content by hash and VERIFY it self-certifies (sha256(bytes) == hash).
33
- * Tries each configured source in order; a source that is unreachable, lacks
34
- * the content or serves bytes that don't match the hash is skipped. Returns the
35
- * first verified bytes, or null if no source holds it. Throws
36
- * ContentVerificationError only when no source served verified bytes and at
37
- * least one served mismatching bytes (tampering / wrong object).
29
+ * Returns the verified bytes, or null when the origin does not hold the content
30
+ * or cannot be reached (as 0.6.0 did when every source failed). Throws
31
+ * ContentVerificationError when the origin serves bytes that don't match the hash.
38
32
  */
39
33
  getBytes(hash: string): Promise<Uint8Array | null>;
40
34
  /** Fetch + verify + parse as UTF-8 JSON. Returns null if not found. Throws a CairnError with code
package/dist/content.d.ts CHANGED
@@ -1,23 +1,19 @@
1
1
  import { H as Http } from './http-C9C4L4hz.js';
2
2
 
3
3
  interface ContentClientOptions {
4
- /** Swarm gateway HTTP client (e.g. https://cairn-substrate.com/swarm). */
5
- swarm?: Http;
6
- /** Cairn origin HTTP client (serves /content as origin + fallback). */
7
- cairn?: Http;
8
- /** Indexer HTTP client (also joins the swarm gateway at /content). */
9
- indexer?: Http;
4
+ /** Cairn origin HTTP client; it serves `/content/<hash>`. */
5
+ cairn: Http;
10
6
  }
11
7
  interface PreparedContent {
12
8
  /** The 0x-prefixed sha256 payload hash that goes on-chain. */
13
9
  payloadHash: string;
14
10
  /** The exact canonical JSON string that was hashed. */
15
11
  canonical: string;
16
- /** UTF-8 bytes of the canonical JSON (what the swarm stores / serves). */
12
+ /** UTF-8 bytes of the canonical JSON (what the origin stores and serves). */
17
13
  bytes: Uint8Array;
18
14
  }
19
15
  declare class ContentClient {
20
- private readonly sources;
16
+ private readonly cairn;
21
17
  constructor(opts: ContentClientOptions);
22
18
  /**
23
19
  * Compute the canonical hash + bytes for an object, ready to anchor on-chain.
@@ -30,11 +26,9 @@ declare class ContentClient {
30
26
  hash(obj: unknown): string;
31
27
  /**
32
28
  * Fetch content by hash and VERIFY it self-certifies (sha256(bytes) == hash).
33
- * Tries each configured source in order; a source that is unreachable, lacks
34
- * the content or serves bytes that don't match the hash is skipped. Returns the
35
- * first verified bytes, or null if no source holds it. Throws
36
- * ContentVerificationError only when no source served verified bytes and at
37
- * least one served mismatching bytes (tampering / wrong object).
29
+ * Returns the verified bytes, or null when the origin does not hold the content
30
+ * or cannot be reached (as 0.6.0 did when every source failed). Throws
31
+ * ContentVerificationError when the origin serves bytes that don't match the hash.
38
32
  */
39
33
  getBytes(hash: string): Promise<Uint8Array | null>;
40
34
  /** Fetch + verify + parse as UTF-8 JSON. Returns null if not found. Throws a CairnError with code
package/dist/content.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ContentClient
3
- } from "./chunk-CZAQNZZG.js";
4
- import "./chunk-OSPAN7GX.js";
3
+ } from "./chunk-TDXGYP3G.js";
4
+ import "./chunk-PBKDSDID.js";
5
5
  export {
6
6
  ContentClient
7
7
  };
@@ -25,7 +25,7 @@ __export(controller_exports, {
25
25
  module.exports = __toCommonJS(controller_exports);
26
26
 
27
27
  // src/errors.ts
28
- var SDK_VERSION = "0.5.0";
28
+ var SDK_VERSION = "0.7.0";
29
29
  var DOCS_BASE = "https://cairn-substrate.com/docs/sdk";
30
30
  var CairnError = class extends Error {
31
31
  /** Stable machine code for programmatic branching. */
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  CairnController
3
- } from "./chunk-OE5BEEQY.js";
4
- import "./chunk-5RGFC2JR.js";
5
- import "./chunk-OSPAN7GX.js";
3
+ } from "./chunk-XOGOSGC6.js";
4
+ import "./chunk-4FFLCCL4.js";
5
+ import "./chunk-PBKDSDID.js";
6
6
  export {
7
7
  CairnController
8
8
  };
package/dist/index.cjs CHANGED
@@ -32,7 +32,6 @@ __export(index_exports, {
32
32
  IndexerClient: () => IndexerClient,
33
33
  NamesClient: () => NamesClient,
34
34
  NotInstalledError: () => NotInstalledError,
35
- RegistryClient: () => RegistryClient,
36
35
  SDK_VERSION: () => SDK_VERSION,
37
36
  SubmitInFlightError: () => SubmitInFlightError,
38
37
  UnsupportedMethodError: () => UnsupportedMethodError,
@@ -59,7 +58,7 @@ __export(index_exports, {
59
58
  module.exports = __toCommonJS(index_exports);
60
59
 
61
60
  // src/errors.ts
62
- var SDK_VERSION = "0.5.0";
61
+ var SDK_VERSION = "0.7.0";
63
62
  var DOCS_BASE = "https://cairn-substrate.com/docs/sdk";
64
63
  var CairnError = class extends Error {
65
64
  /** Stable machine code for programmatic branching. */
@@ -502,18 +501,6 @@ var IndexerClient = class {
502
501
  attestations(id) {
503
502
  return this.http.getJson(`/proposal/${encodeURIComponent(id)}/attestations`);
504
503
  }
505
- registryPeers() {
506
- return this.http.getJson("/registry/peers");
507
- }
508
- registryGateways() {
509
- return this.http.getJson("/registry/gateways");
510
- }
511
- identity(handle) {
512
- return this.http.getJson(`/identity/${encodeURIComponent(handle)}`);
513
- }
514
- reverseIdentity(addr) {
515
- return this.http.getJson(`/address/${encodeURIComponent(addr)}/identity`);
516
- }
517
504
  // ---- trust-minimized inclusion ----------------------------------------
518
505
  /**
519
506
  * Verify a tx is included in a block by folding its merkle branch to the root
@@ -708,12 +695,12 @@ function norm(h) {
708
695
  // src/content.ts
709
696
  var import_csd_codec3 = require("@inversealtruism/csd-codec");
710
697
  var ContentClient = class {
711
- sources;
698
+ cairn;
712
699
  constructor(opts) {
713
- this.sources = [];
714
- if (opts.swarm) this.sources.push({ name: "swarm", http: opts.swarm, path: (h) => `/content/${h}` });
715
- if (opts.indexer) this.sources.push({ name: "indexer", http: opts.indexer, path: (h) => `/content/${h}` });
716
- if (opts.cairn) this.sources.push({ name: "cairn", http: opts.cairn, path: (h) => `/content/${h}` });
700
+ if (!opts?.cairn || typeof opts.cairn.getBytes !== "function") {
701
+ throw new TypeError("ContentClient needs a `cairn` Http client (the swarm and indexer sources were removed in 0.7.0)");
702
+ }
703
+ this.cairn = opts.cairn;
717
704
  }
718
705
  /**
719
706
  * Compute the canonical hash + bytes for an object, ready to anchor on-chain.
@@ -737,31 +724,21 @@ var ContentClient = class {
737
724
  }
738
725
  /**
739
726
  * Fetch content by hash and VERIFY it self-certifies (sha256(bytes) == hash).
740
- * Tries each configured source in order; a source that is unreachable, lacks
741
- * the content or serves bytes that don't match the hash is skipped. Returns the
742
- * first verified bytes, or null if no source holds it. Throws
743
- * ContentVerificationError only when no source served verified bytes and at
744
- * least one served mismatching bytes (tampering / wrong object).
727
+ * Returns the verified bytes, or null when the origin does not hold the content
728
+ * or cannot be reached (as 0.6.0 did when every source failed). Throws
729
+ * ContentVerificationError when the origin serves bytes that don't match the hash.
745
730
  */
746
731
  async getBytes(hash) {
747
732
  const h = normalizeHash(hash);
748
- let mismatched = false;
749
- for (const src of this.sources) {
750
- let got = null;
751
- try {
752
- got = await src.http.getBytes(src.path(h));
753
- } catch {
754
- continue;
755
- }
756
- if (!got) continue;
757
- if (!(0, import_csd_codec3.verifyContentBytes)(got.bytes, h)) {
758
- mismatched = true;
759
- continue;
760
- }
761
- return got.bytes;
733
+ let got = null;
734
+ try {
735
+ got = await this.cairn.getBytes(`/content/${h}`);
736
+ } catch {
737
+ return null;
762
738
  }
763
- if (mismatched) throw new ContentVerificationError(h);
764
- return null;
739
+ if (!got) return null;
740
+ if (!(0, import_csd_codec3.verifyContentBytes)(got.bytes, h)) throw new ContentVerificationError(h);
741
+ return got.bytes;
765
742
  }
766
743
  /** Fetch + verify + parse as UTF-8 JSON. Returns null if not found. Throws a CairnError with code
767
744
  * CONTENT_NOT_JSON when the verified bytes are not JSON. */
@@ -785,58 +762,6 @@ function normalizeHash(hash) {
785
762
  return h;
786
763
  }
787
764
 
788
- // src/registry.ts
789
- var import_csd_registry = require("@inversealtruism/csd-registry");
790
- var import_csd_registry2 = require("@inversealtruism/csd-registry");
791
- var RegistryClient = class {
792
- http;
793
- /** Accepts the SDK's hardened Http directly (the Cairn facade path) or the legacy
794
- * { baseUrl, fetch } options (kept for direct constructors; they now get the same
795
- * hardened transport, built internally). */
796
- constructor(src) {
797
- this.http = src instanceof Http ? src : new Http({ baseUrl: src.baseUrl, fetch: src.fetch });
798
- }
799
- /** Discover ranked content/pin gateways (GET /registry/gateways). */
800
- gateways() {
801
- return this.http.getJson("/registry/gateways");
802
- }
803
- /** Discover ranked libp2p peers (GET /registry/peers). */
804
- peers() {
805
- return this.http.getJson("/registry/peers");
806
- }
807
- /**
808
- * Resolve a handle → identity (GET /identity/:handle). Returns null if unresolved.
809
- *
810
- * ⚠ TRUST (CAIRN-SDK-RESOLVE-VERIFIED-FOOTGUN): the returned `verified` flag is the INDEXER's assertion,
811
- * NOT a client-side proof. A hostile/compromised indexer (or a MITM of the read proxy) can return
812
- * `verified:true` for a wrong address. Do NOT use this directly as a payee/login target without either (a)
813
- * recomputing from raw records via `fromRecords.name(...)`, or (b) cross-checking a second independent
814
- * source (the wallet's namespv union cure). Treat `verified` here as a hint, not a guarantee.
815
- */
816
- resolveName(handle) {
817
- return this.getOr404Null(`/identity/${encodeURIComponent(handle)}`);
818
- }
819
- /** Reverse-resolve an address → identity (GET /address/:addr/identity).
820
- * ⚠ Same indexer-trust caveat as resolveName — `verified` is the indexer's claim, not a client proof. */
821
- reverseName(address) {
822
- return this.getOr404Null(`/address/${encodeURIComponent(address)}/identity`);
823
- }
824
- // MF-12: 404 → null (the preserved csd-registry contract for both name resolvers); every other
825
- // failure rethrows the typed HttpError/CairnError the hardened Http raises.
826
- async getOr404Null(path) {
827
- try {
828
- return await this.http.getJson(path);
829
- } catch (e) {
830
- if (e instanceof HttpError && e.status === 404) return null;
831
- return Promise.reject(e);
832
- }
833
- }
834
- /** The deterministic, client-side resolvers (recompute from raw ChainRecord[]). */
835
- get fromRecords() {
836
- return import_csd_registry.fromRecords;
837
- }
838
- };
839
-
840
765
  // src/names.ts
841
766
  var import_cairnx_core = require("@inversealtruism/cairnx-core");
842
767
  var nameOk = (n) => typeof n === "string" && import_cairnx_core.NAME_RE.test(n) && !import_cairnx_core.RESERVED_NAMES.has(n);
@@ -1519,7 +1444,6 @@ var Cairn = class {
1519
1444
  chain;
1520
1445
  index;
1521
1446
  content;
1522
- registry;
1523
1447
  /** .csd names + CairnX market READS (server-trusted display reads; see names.ts trust note). */
1524
1448
  names;
1525
1449
  wallet;
@@ -1543,7 +1467,6 @@ var Cairn = class {
1543
1467
  this.cairnHttp = new Http({ baseUrl: cairn, fetch, timeoutMs });
1544
1468
  this._cairnBase = cairn;
1545
1469
  const indexerHttp = new Http({ baseUrl: indexer, fetch, timeoutMs });
1546
- const swarmHttp = config.baseUrls?.swarm ? new Http({ baseUrl: config.baseUrls.swarm.replace(/\/+$/, ""), fetch, timeoutMs }) : void 0;
1547
1470
  this._spvCp = config.spvCheckpoint ?? DEFAULT_SPV_CHECKPOINT;
1548
1471
  this.chain = new Chain({ rpcUrl: rpc, fetch, timeoutMs });
1549
1472
  this.wallet = config.wallet;
@@ -1552,8 +1475,7 @@ var Cairn = class {
1552
1475
  WebSocketImpl: config.WebSocketImpl,
1553
1476
  headerMerkleAt: (h) => this.verifiedHeaderMerkleAt(h)
1554
1477
  });
1555
- this.content = new ContentClient({ swarm: swarmHttp, indexer: indexerHttp, cairn: this.cairnHttp });
1556
- this.registry = new RegistryClient(indexerHttp);
1478
+ this.content = new ContentClient({ cairn: this.cairnHttp });
1557
1479
  this.names = new NamesClient(this.cairnHttp);
1558
1480
  }
1559
1481
  /**
@@ -1762,7 +1684,6 @@ var Cairn = class {
1762
1684
  IndexerClient,
1763
1685
  NamesClient,
1764
1686
  NotInstalledError,
1765
- RegistryClient,
1766
1687
  SDK_VERSION,
1767
1688
  SubmitInFlightError,
1768
1689
  UnsupportedMethodError,