@inversealtruism/cairn-sdk 0.1.0 → 0.1.2

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
@@ -81,7 +81,7 @@ Subpath imports are available for tree-shaking: `@inversealtruism/cairn-sdk/{con
81
81
  ## Trust model & honest limits
82
82
 
83
83
  - **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.
84
- - **Merkle inclusion is trust-minimized.** `verifyInclusion()` folds the proof and cross-checks the root against the on-chain header merkle → `trustLevel: "verified-inclusion"`. Without that cross-check it reports `"proof-consistent"` (indexer trusted).
84
+ - **Merkle inclusion is trust-minimized — to the strength of your header source.** `verifyInclusion()` folds the proof and, when a header-merkle source is wired, cross-checks the root against it → `trustLevel: "verified-inclusion"`; otherwise `"proof-consistent"` (indexer trusted). That cross-check only means something against an *independent* header, so the default `Cairn` wiring enables it ONLY when your node RPC is a different origin than the indexer (the default same-origin proxy stays at `"proof-consistent"` — a single compromised server can't be cross-checked against itself). For full trust-minimization against a lying node too, supply a PoW-verifying `headerMerkleAt` (e.g. backed by `cairn.chain.light()`).
85
85
  - **Balances are RPC-trusted.** Headers don't commit to the UTXO set; balance reads trust the node/proxy (same as every light client).
86
86
  - **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.
87
87
  - **Today the wallet injects only on `cairn-substrate.com` + localhost.** Connecting from an arbitrary third-party origin requires the wallet's "connect anywhere" release (broadened injection), which ships after the per-origin consent layer is proven.
@@ -103,6 +103,17 @@ new Cairn({
103
103
  });
104
104
  ```
105
105
 
106
+ ## Testing
107
+
108
+ ```bash
109
+ pnpm build && pnpm test # unit (offline): error mapping, client paths, content+merkle verify
110
+ pnpm test:e2e:read # live reads vs mainnet + adversarial (free)
111
+ pnpm test:e2e:wallet # real extension + real connector under Xvfb: connect/consent/sign (free)
112
+ pnpm test:e2e:write # full pipeline incl. a real on-chain Propose+Attest (spends ~0.3 CSD)
113
+ ```
114
+
115
+ See [`test/e2e/README.md`](test/e2e/README.md) for coverage, requirements, and cost of each layer. The unit + live-read + wallet-connector suites are CI-friendly and free; the write suite needs a funded key and is opt-in.
116
+
106
117
  ## License
107
118
 
108
119
  MIT
@@ -75,9 +75,12 @@ var IndexerClient = class {
75
75
  /**
76
76
  * Verify a tx is included in a block by folding its merkle branch to the root
77
77
  * with csd-codec.verifyMerkleProof. If `headerMerkleAt` was provided, the
78
- * proof's root is cross-checked against the ON-CHAIN header merkle at that
79
- * height → trustLevel "verified-inclusion". Otherwise the proof is only
80
- * internally consistent → "proof-consistent" (still useful, but the indexer is trusted).
78
+ * proof's root is cross-checked against the header merkle at that height →
79
+ * trustLevel "verified-inclusion" (only as trustworthy as that header source —
80
+ * see headerMerkleAt). Otherwise the proof is only internally consistent →
81
+ * "proof-consistent" (still useful, but the indexer is trusted). The Cairn
82
+ * facade wires headerMerkleAt ONLY when the node RPC is an independent origin
83
+ * from the indexer, so the default same-origin setup stays at "proof-consistent".
81
84
  */
82
85
  async verifyInclusion(txid) {
83
86
  let proof;
package/dist/index.cjs CHANGED
@@ -437,9 +437,12 @@ var IndexerClient = class {
437
437
  /**
438
438
  * Verify a tx is included in a block by folding its merkle branch to the root
439
439
  * with csd-codec.verifyMerkleProof. If `headerMerkleAt` was provided, the
440
- * proof's root is cross-checked against the ON-CHAIN header merkle at that
441
- * height → trustLevel "verified-inclusion". Otherwise the proof is only
442
- * internally consistent → "proof-consistent" (still useful, but the indexer is trusted).
440
+ * proof's root is cross-checked against the header merkle at that height →
441
+ * trustLevel "verified-inclusion" (only as trustworthy as that header source —
442
+ * see headerMerkleAt). Otherwise the proof is only internally consistent →
443
+ * "proof-consistent" (still useful, but the indexer is trusted). The Cairn
444
+ * facade wires headerMerkleAt ONLY when the node RPC is an independent origin
445
+ * from the indexer, so the default same-origin setup stays at "proof-consistent".
443
446
  */
444
447
  async verifyInclusion(txid2) {
445
448
  let proof;
@@ -794,6 +797,7 @@ async function connect(opts = {}) {
794
797
  }
795
798
 
796
799
  // src/index.ts
800
+ var DEFAULT_SPV_CHECKPOINT = { height: 31310, hash: "0x000000000000138bd3eee4b8d2fbacb8d5433ac3040ddbf1c45a5e3e0cc9e814" };
797
801
  var DEFAULT_CAIRN = "https://cairn-substrate.com";
798
802
  var Cairn = class {
799
803
  config;
@@ -804,6 +808,10 @@ var Cairn = class {
804
808
  board;
805
809
  wallet;
806
810
  cairnHttp;
811
+ // Lazily-seeded SPV light client + its checkpoint (audit M3 — PoW-verified header source).
812
+ _spvLight = null;
813
+ _spvSeeded = false;
814
+ _spvCp;
807
815
  constructor(config = {}) {
808
816
  this.config = config;
809
817
  const fetch = config.fetch;
@@ -814,22 +822,41 @@ var Cairn = class {
814
822
  this.cairnHttp = new Http({ baseUrl: cairn, fetch, timeoutMs });
815
823
  const indexerHttp = new Http({ baseUrl: indexer, fetch, timeoutMs });
816
824
  const swarmHttp = config.baseUrls?.swarm ? new Http({ baseUrl: config.baseUrls.swarm.replace(/\/+$/, ""), fetch, timeoutMs }) : void 0;
825
+ this._spvCp = config.spvCheckpoint ?? DEFAULT_SPV_CHECKPOINT;
817
826
  this.chain = new Chain({ rpcUrl: rpc, fetch, timeoutMs });
818
827
  this.wallet = config.wallet;
819
828
  this.board = new BoardClient(this.cairnHttp, this.wallet);
820
829
  this.index = new IndexerClient(indexerHttp, {
821
830
  fetch,
822
831
  WebSocketImpl: config.WebSocketImpl,
823
- // Upgrade inclusion proofs to fully trust-minimized by cross-checking the
824
- // proof root against the on-chain header merkle at that height.
825
- headerMerkleAt: async (h) => {
826
- const block = await this.chain.client.blockByHeight(h);
827
- return String(block.header.merkle);
828
- }
832
+ headerMerkleAt: (h) => this.verifiedHeaderMerkleAt(h)
829
833
  });
830
834
  this.content = new ContentClient({ swarm: swarmHttp, indexer: indexerHttp, cairn: this.cairnHttp });
831
835
  this.registry = new RegistryClient({ baseUrl: indexer, fetch });
832
836
  }
837
+ /**
838
+ * PoW-VERIFIED header merkle at a height (audit M3 — the no-PoW half). Lazily seeds a light
839
+ * client from the pinned SPV checkpoint and verifies the header chain FORWARD (PoW + LWMA +
840
+ * chainwork) to `height`, then returns that header's merkle root. THROWS for a height below the
841
+ * checkpoint (can't verify backward) or if verification fails — the IndexerClient then degrades
842
+ * to the honest "proof-consistent" instead of over-claiming "verified-inclusion". The verified
843
+ * header chain is cached across calls; the first call near tip syncs the post-checkpoint span.
844
+ */
845
+ async verifiedHeaderMerkleAt(height) {
846
+ if (!Number.isInteger(height) || height < this._spvCp.height)
847
+ throw new Error(`height ${height} is below the SPV checkpoint ${this._spvCp.height} (cannot PoW-verify backward)`);
848
+ if (!this._spvLight) this._spvLight = new import_csd_light.LightClient({ client: this.chain.client, checkpoints: { [this._spvCp.height]: this._spvCp.hash } });
849
+ const lc = this._spvLight;
850
+ if (!this._spvSeeded) {
851
+ await lc.syncFromCheckpoint(this._spvCp.height, this._spvCp.hash);
852
+ this._spvSeeded = true;
853
+ }
854
+ const haveTo = lc.baseHeight + lc.chain.length - 1;
855
+ if (haveTo < height) await lc.sync(height);
856
+ const vh = lc.chain[height - lc.baseHeight];
857
+ if (!vh) throw new Error(`light client has no verified header at ${height}`);
858
+ return String(vh.header.merkle);
859
+ }
833
860
  /**
834
861
  * Detect + connect the Cairn Wallet (browser only). Wires the wallet into
835
862
  * `cairn.board` for signed writes. Resolves to the connected address.
package/dist/index.d.cts CHANGED
@@ -80,6 +80,18 @@ interface CairnConfig {
80
80
  wallet?: WalletConnection;
81
81
  /** WebSocket implementation for indexer subscriptions (defaults to global). */
82
82
  WebSocketImpl?: typeof WebSocket;
83
+ /**
84
+ * SPV trust anchor for genuine "verified-inclusion" (audit M3). A merkle inclusion proof is only
85
+ * "verified-inclusion" when its block header is PoW-verified — otherwise a lying node can serve a
86
+ * fake header whose merkle matches a fake proof. The light client verifies the header chain
87
+ * (PoW + LWMA + chainwork) forward from this pinned checkpoint; inclusion at a height ≥ the
88
+ * checkpoint is then trust-minimized. Defaults to the ecosystem checkpoint (same hash swapguard
89
+ * ships). Pin your own for full control. Txs BELOW the checkpoint degrade to "proof-consistent".
90
+ */
91
+ spvCheckpoint?: {
92
+ height: number;
93
+ hash: string;
94
+ };
83
95
  }
84
96
  declare class Cairn {
85
97
  readonly config: CairnConfig;
@@ -90,7 +102,19 @@ declare class Cairn {
90
102
  board: BoardClient;
91
103
  wallet?: WalletConnection;
92
104
  private readonly cairnHttp;
105
+ private _spvLight;
106
+ private _spvSeeded;
107
+ private readonly _spvCp;
93
108
  constructor(config?: CairnConfig);
109
+ /**
110
+ * PoW-VERIFIED header merkle at a height (audit M3 — the no-PoW half). Lazily seeds a light
111
+ * client from the pinned SPV checkpoint and verifies the header chain FORWARD (PoW + LWMA +
112
+ * chainwork) to `height`, then returns that header's merkle root. THROWS for a height below the
113
+ * checkpoint (can't verify backward) or if verification fails — the IndexerClient then degrades
114
+ * to the honest "proof-consistent" instead of over-claiming "verified-inclusion". The verified
115
+ * header chain is cached across calls; the first call near tip syncs the post-checkpoint span.
116
+ */
117
+ private verifiedHeaderMerkleAt;
94
118
  /**
95
119
  * Detect + connect the Cairn Wallet (browser only). Wires the wallet into
96
120
  * `cairn.board` for signed writes. Resolves to the connected address.
package/dist/index.d.ts CHANGED
@@ -80,6 +80,18 @@ interface CairnConfig {
80
80
  wallet?: WalletConnection;
81
81
  /** WebSocket implementation for indexer subscriptions (defaults to global). */
82
82
  WebSocketImpl?: typeof WebSocket;
83
+ /**
84
+ * SPV trust anchor for genuine "verified-inclusion" (audit M3). A merkle inclusion proof is only
85
+ * "verified-inclusion" when its block header is PoW-verified — otherwise a lying node can serve a
86
+ * fake header whose merkle matches a fake proof. The light client verifies the header chain
87
+ * (PoW + LWMA + chainwork) forward from this pinned checkpoint; inclusion at a height ≥ the
88
+ * checkpoint is then trust-minimized. Defaults to the ecosystem checkpoint (same hash swapguard
89
+ * ships). Pin your own for full control. Txs BELOW the checkpoint degrade to "proof-consistent".
90
+ */
91
+ spvCheckpoint?: {
92
+ height: number;
93
+ hash: string;
94
+ };
83
95
  }
84
96
  declare class Cairn {
85
97
  readonly config: CairnConfig;
@@ -90,7 +102,19 @@ declare class Cairn {
90
102
  board: BoardClient;
91
103
  wallet?: WalletConnection;
92
104
  private readonly cairnHttp;
105
+ private _spvLight;
106
+ private _spvSeeded;
107
+ private readonly _spvCp;
93
108
  constructor(config?: CairnConfig);
109
+ /**
110
+ * PoW-VERIFIED header merkle at a height (audit M3 — the no-PoW half). Lazily seeds a light
111
+ * client from the pinned SPV checkpoint and verifies the header chain FORWARD (PoW + LWMA +
112
+ * chainwork) to `height`, then returns that header's merkle root. THROWS for a height below the
113
+ * checkpoint (can't verify backward) or if verification fails — the IndexerClient then degrades
114
+ * to the honest "proof-consistent" instead of over-claiming "verified-inclusion". The verified
115
+ * header chain is cached across calls; the first call near tip syncs the post-checkpoint span.
116
+ */
117
+ private verifiedHeaderMerkleAt;
94
118
  /**
95
119
  * Detect + connect the Cairn Wallet (browser only). Wires the wallet into
96
120
  * `cairn.board` for signed writes. Resolves to the connected address.
package/dist/index.js CHANGED
@@ -2,7 +2,8 @@ import {
2
2
  BoardClient
3
3
  } from "./chunk-OGP2W7DL.js";
4
4
  import {
5
- Chain
5
+ Chain,
6
+ LightClient
6
7
  } from "./chunk-6VWLWF7R.js";
7
8
  import {
8
9
  WalletConnection,
@@ -25,7 +26,7 @@ import {
25
26
  } from "./chunk-PHMU3CG5.js";
26
27
  import {
27
28
  IndexerClient
28
- } from "./chunk-ETZYBDFC.js";
29
+ } from "./chunk-FNBE2FPE.js";
29
30
  import {
30
31
  RegistryClient
31
32
  } from "./chunk-G7FABIF4.js";
@@ -103,6 +104,7 @@ async function safeText(res) {
103
104
  }
104
105
 
105
106
  // src/index.ts
107
+ var DEFAULT_SPV_CHECKPOINT = { height: 31310, hash: "0x000000000000138bd3eee4b8d2fbacb8d5433ac3040ddbf1c45a5e3e0cc9e814" };
106
108
  var DEFAULT_CAIRN = "https://cairn-substrate.com";
107
109
  var Cairn = class {
108
110
  config;
@@ -113,6 +115,10 @@ var Cairn = class {
113
115
  board;
114
116
  wallet;
115
117
  cairnHttp;
118
+ // Lazily-seeded SPV light client + its checkpoint (audit M3 — PoW-verified header source).
119
+ _spvLight = null;
120
+ _spvSeeded = false;
121
+ _spvCp;
116
122
  constructor(config = {}) {
117
123
  this.config = config;
118
124
  const fetch = config.fetch;
@@ -123,22 +129,41 @@ var Cairn = class {
123
129
  this.cairnHttp = new Http({ baseUrl: cairn, fetch, timeoutMs });
124
130
  const indexerHttp = new Http({ baseUrl: indexer, fetch, timeoutMs });
125
131
  const swarmHttp = config.baseUrls?.swarm ? new Http({ baseUrl: config.baseUrls.swarm.replace(/\/+$/, ""), fetch, timeoutMs }) : void 0;
132
+ this._spvCp = config.spvCheckpoint ?? DEFAULT_SPV_CHECKPOINT;
126
133
  this.chain = new Chain({ rpcUrl: rpc, fetch, timeoutMs });
127
134
  this.wallet = config.wallet;
128
135
  this.board = new BoardClient(this.cairnHttp, this.wallet);
129
136
  this.index = new IndexerClient(indexerHttp, {
130
137
  fetch,
131
138
  WebSocketImpl: config.WebSocketImpl,
132
- // Upgrade inclusion proofs to fully trust-minimized by cross-checking the
133
- // proof root against the on-chain header merkle at that height.
134
- headerMerkleAt: async (h) => {
135
- const block = await this.chain.client.blockByHeight(h);
136
- return String(block.header.merkle);
137
- }
139
+ headerMerkleAt: (h) => this.verifiedHeaderMerkleAt(h)
138
140
  });
139
141
  this.content = new ContentClient({ swarm: swarmHttp, indexer: indexerHttp, cairn: this.cairnHttp });
140
142
  this.registry = new RegistryClient({ baseUrl: indexer, fetch });
141
143
  }
144
+ /**
145
+ * PoW-VERIFIED header merkle at a height (audit M3 — the no-PoW half). Lazily seeds a light
146
+ * client from the pinned SPV checkpoint and verifies the header chain FORWARD (PoW + LWMA +
147
+ * chainwork) to `height`, then returns that header's merkle root. THROWS for a height below the
148
+ * checkpoint (can't verify backward) or if verification fails — the IndexerClient then degrades
149
+ * to the honest "proof-consistent" instead of over-claiming "verified-inclusion". The verified
150
+ * header chain is cached across calls; the first call near tip syncs the post-checkpoint span.
151
+ */
152
+ async verifiedHeaderMerkleAt(height) {
153
+ if (!Number.isInteger(height) || height < this._spvCp.height)
154
+ throw new Error(`height ${height} is below the SPV checkpoint ${this._spvCp.height} (cannot PoW-verify backward)`);
155
+ if (!this._spvLight) this._spvLight = new LightClient({ client: this.chain.client, checkpoints: { [this._spvCp.height]: this._spvCp.hash } });
156
+ const lc = this._spvLight;
157
+ if (!this._spvSeeded) {
158
+ await lc.syncFromCheckpoint(this._spvCp.height, this._spvCp.hash);
159
+ this._spvSeeded = true;
160
+ }
161
+ const haveTo = lc.baseHeight + lc.chain.length - 1;
162
+ if (haveTo < height) await lc.sync(height);
163
+ const vh = lc.chain[height - lc.baseHeight];
164
+ if (!vh) throw new Error(`light client has no verified header at ${height}`);
165
+ return String(vh.header.merkle);
166
+ }
142
167
  /**
143
168
  * Detect + connect the Cairn Wallet (browser only). Wires the wallet into
144
169
  * `cairn.board` for signed writes. Resolves to the connected address.
package/dist/indexer.cjs CHANGED
@@ -99,9 +99,12 @@ var IndexerClient = class {
99
99
  /**
100
100
  * Verify a tx is included in a block by folding its merkle branch to the root
101
101
  * with csd-codec.verifyMerkleProof. If `headerMerkleAt` was provided, the
102
- * proof's root is cross-checked against the ON-CHAIN header merkle at that
103
- * height → trustLevel "verified-inclusion". Otherwise the proof is only
104
- * internally consistent → "proof-consistent" (still useful, but the indexer is trusted).
102
+ * proof's root is cross-checked against the header merkle at that height →
103
+ * trustLevel "verified-inclusion" (only as trustworthy as that header source —
104
+ * see headerMerkleAt). Otherwise the proof is only internally consistent →
105
+ * "proof-consistent" (still useful, but the indexer is trusted). The Cairn
106
+ * facade wires headerMerkleAt ONLY when the node RPC is an independent origin
107
+ * from the indexer, so the default same-origin setup stays at "proof-consistent".
105
108
  */
106
109
  async verifyInclusion(txid) {
107
110
  let proof;
@@ -25,9 +25,13 @@ interface IndexerClientOptions {
25
25
  /** A WebSocket implementation (defaults to globalThis.WebSocket). */
26
26
  WebSocketImpl?: typeof WebSocket;
27
27
  /**
28
- * Optional: given a block height, return its on-chain header merkle root. Wire
29
- * this from the chain/light client to upgrade verifyInclusion() from
30
- * "proof-consistent" to fully trust-minimized "verified-inclusion".
28
+ * Optional: given a block height, return its on-chain header merkle root. verifyInclusion()
29
+ * cross-checks the indexer's proof root against this and, on a match, labels the result
30
+ * "verified-inclusion". IMPORTANT: that label is only as strong as THIS source — it is fully
31
+ * trust-minimized ONLY if the header is independently verified (e.g. a PoW-checking light client,
32
+ * or at least a node on a DIFFERENT trust domain than the indexer). A header fetched by raw RPC
33
+ * from the SAME server that serves the proof proves nothing (one compromised server controls
34
+ * both); for that case prefer no headerMerkleAt → an honest "proof-consistent".
31
35
  */
32
36
  headerMerkleAt?: (height: number) => Promise<string>;
33
37
  }
@@ -64,9 +68,12 @@ declare class IndexerClient {
64
68
  /**
65
69
  * Verify a tx is included in a block by folding its merkle branch to the root
66
70
  * with csd-codec.verifyMerkleProof. If `headerMerkleAt` was provided, the
67
- * proof's root is cross-checked against the ON-CHAIN header merkle at that
68
- * height → trustLevel "verified-inclusion". Otherwise the proof is only
69
- * internally consistent → "proof-consistent" (still useful, but the indexer is trusted).
71
+ * proof's root is cross-checked against the header merkle at that height →
72
+ * trustLevel "verified-inclusion" (only as trustworthy as that header source —
73
+ * see headerMerkleAt). Otherwise the proof is only internally consistent →
74
+ * "proof-consistent" (still useful, but the indexer is trusted). The Cairn
75
+ * facade wires headerMerkleAt ONLY when the node RPC is an independent origin
76
+ * from the indexer, so the default same-origin setup stays at "proof-consistent".
70
77
  */
71
78
  verifyInclusion(txid: string): Promise<InclusionResult>;
72
79
  /** Stream all events (blocks, proposals, attestations, reorgs) via SSE. */
package/dist/indexer.d.ts CHANGED
@@ -25,9 +25,13 @@ interface IndexerClientOptions {
25
25
  /** A WebSocket implementation (defaults to globalThis.WebSocket). */
26
26
  WebSocketImpl?: typeof WebSocket;
27
27
  /**
28
- * Optional: given a block height, return its on-chain header merkle root. Wire
29
- * this from the chain/light client to upgrade verifyInclusion() from
30
- * "proof-consistent" to fully trust-minimized "verified-inclusion".
28
+ * Optional: given a block height, return its on-chain header merkle root. verifyInclusion()
29
+ * cross-checks the indexer's proof root against this and, on a match, labels the result
30
+ * "verified-inclusion". IMPORTANT: that label is only as strong as THIS source — it is fully
31
+ * trust-minimized ONLY if the header is independently verified (e.g. a PoW-checking light client,
32
+ * or at least a node on a DIFFERENT trust domain than the indexer). A header fetched by raw RPC
33
+ * from the SAME server that serves the proof proves nothing (one compromised server controls
34
+ * both); for that case prefer no headerMerkleAt → an honest "proof-consistent".
31
35
  */
32
36
  headerMerkleAt?: (height: number) => Promise<string>;
33
37
  }
@@ -64,9 +68,12 @@ declare class IndexerClient {
64
68
  /**
65
69
  * Verify a tx is included in a block by folding its merkle branch to the root
66
70
  * with csd-codec.verifyMerkleProof. If `headerMerkleAt` was provided, the
67
- * proof's root is cross-checked against the ON-CHAIN header merkle at that
68
- * height → trustLevel "verified-inclusion". Otherwise the proof is only
69
- * internally consistent → "proof-consistent" (still useful, but the indexer is trusted).
71
+ * proof's root is cross-checked against the header merkle at that height →
72
+ * trustLevel "verified-inclusion" (only as trustworthy as that header source —
73
+ * see headerMerkleAt). Otherwise the proof is only internally consistent →
74
+ * "proof-consistent" (still useful, but the indexer is trusted). The Cairn
75
+ * facade wires headerMerkleAt ONLY when the node RPC is an independent origin
76
+ * from the indexer, so the default same-origin setup stays at "proof-consistent".
70
77
  */
71
78
  verifyInclusion(txid: string): Promise<InclusionResult>;
72
79
  /** Stream all events (blocks, proposals, attestations, reorgs) via SSE. */
package/dist/indexer.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  IndexerClient
3
- } from "./chunk-ETZYBDFC.js";
3
+ } from "./chunk-FNBE2FPE.js";
4
4
  export {
5
5
  IndexerClient
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inversealtruism/cairn-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "The Compute Substrate dApp kit — one cohesive toolkit to connect the Cairn Wallet, read the chain/board, publish self-certifying content, and resolve registries. Composes the published csd-* primitives.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -53,18 +53,24 @@
53
53
  "test": "tsx test/sdk.test.ts && tsx test/connect.test.ts",
54
54
  "test:live": "node examples/read-only.mjs",
55
55
  "build:example": "node scripts/build-example.mjs",
56
- "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\""
56
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
57
+ "test:e2e:read": "node test/e2e/e2e-read.mjs",
58
+ "test:e2e:wallet": "xvfb-run -a node test/e2e/e2e-wallet-connect.mjs",
59
+ "test:e2e:write": "node test/e2e/e2e-write.mjs",
60
+ "test:e2e": "node test/e2e/e2e-read.mjs && xvfb-run -a node test/e2e/e2e-wallet-connect.mjs",
61
+ "test:all": "pnpm test && pnpm test:e2e"
57
62
  },
58
63
  "dependencies": {
59
- "@inversealtruism/csd-codec": "^0.1.3",
60
- "@inversealtruism/csd-crypto": "^0.1.3",
61
- "@inversealtruism/csd-tx": "^0.1.3",
62
- "@inversealtruism/csd-client": "^0.1.3",
63
- "@inversealtruism/csd-light": "^0.1.3",
64
- "@inversealtruism/csd-registry": "^0.1.3"
64
+ "@inversealtruism/csd-client": "^0.1.5",
65
+ "@inversealtruism/csd-codec": "^0.1.5",
66
+ "@inversealtruism/csd-crypto": "^0.1.5",
67
+ "@inversealtruism/csd-light": "^0.1.5",
68
+ "@inversealtruism/csd-registry": "^0.1.5",
69
+ "@inversealtruism/csd-tx": "^0.1.5"
65
70
  },
66
71
  "devDependencies": {
67
72
  "esbuild": "^0.27.0",
73
+ "playwright-core": "^1.49.0",
68
74
  "tsup": "^8.5.1",
69
75
  "tsx": "^4.19.2",
70
76
  "typescript": "^5.6.0"