@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 +7 -10
- package/dist/{chunk-5RGFC2JR.js → chunk-4FFLCCL4.js} +1 -1
- package/dist/{chunk-K5MGEYEU.js → chunk-CI7YODPP.js} +0 -12
- package/dist/{chunk-OSPAN7GX.js → chunk-PBKDSDID.js} +1 -1
- package/dist/{chunk-CZAQNZZG.js → chunk-TDXGYP3G.js} +17 -27
- package/dist/{chunk-OE5BEEQY.js → chunk-XOGOSGC6.js} +1 -1
- package/dist/connect.cjs +1 -1
- package/dist/connect.js +2 -2
- package/dist/content.cjs +17 -27
- package/dist/content.d.cts +7 -13
- package/dist/content.d.ts +7 -13
- package/dist/content.js +2 -2
- package/dist/controller.cjs +1 -1
- package/dist/controller.js +3 -3
- package/dist/index.cjs +18 -97
- package/dist/index.d.cts +7 -15
- package/dist/index.d.ts +7 -15
- package/dist/index.js +174 -17
- package/dist/indexer.cjs +0 -12
- package/dist/indexer.d.cts +0 -4
- package/dist/indexer.d.ts +0 -4
- package/dist/indexer.js +1 -1
- package/dist/react.cjs +1 -1
- package/dist/react.js +3 -3
- package/package.json +23 -26
- package/dist/chunk-BL6VFALH.js +0 -254
- package/dist/registry.cjs +0 -326
- package/dist/registry.d.cts +0 -44
- package/dist/registry.d.ts +0 -44
- package/dist/registry.js +0 -27
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()`,
|
|
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
|
-
|
|
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
|
|
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
|
-
- **
|
|
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:
|
|
107
|
-
pnpm test:
|
|
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.
|
|
@@ -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,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CairnError,
|
|
3
3
|
ContentVerificationError
|
|
4
|
-
} from "./chunk-
|
|
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
|
-
|
|
9
|
+
cairn;
|
|
10
10
|
constructor(opts) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
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
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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 (
|
|
62
|
-
|
|
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. */
|
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.
|
|
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
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.
|
|
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
|
-
|
|
83
|
+
cairn;
|
|
84
84
|
constructor(opts) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
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
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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 (
|
|
136
|
-
|
|
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. */
|
package/dist/content.d.cts
CHANGED
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
import { H as Http } from './http-C9C4L4hz.cjs';
|
|
2
2
|
|
|
3
3
|
interface ContentClientOptions {
|
|
4
|
-
/**
|
|
5
|
-
|
|
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
|
|
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
|
|
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
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
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
|
-
/**
|
|
5
|
-
|
|
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
|
|
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
|
|
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
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
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
package/dist/controller.cjs
CHANGED
|
@@ -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.
|
|
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. */
|
package/dist/controller.js
CHANGED
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.
|
|
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
|
-
|
|
698
|
+
cairn;
|
|
712
699
|
constructor(opts) {
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
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
|
-
*
|
|
741
|
-
*
|
|
742
|
-
*
|
|
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
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
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 (
|
|
764
|
-
|
|
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({
|
|
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,
|