@inversealtruism/cairn-sdk 0.3.2 → 0.4.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/dist/index.js CHANGED
@@ -3,20 +3,20 @@ import {
3
3
  } from "./chunk-BGJZF7S2.js";
4
4
  import {
5
5
  BoardClient
6
- } from "./chunk-CZWDA3A5.js";
6
+ } from "./chunk-2ZML7IKV.js";
7
7
  import {
8
8
  Chain,
9
9
  LightClient
10
10
  } from "./chunk-C452UODV.js";
11
11
  import {
12
12
  ContentClient
13
- } from "./chunk-JKC5K253.js";
13
+ } from "./chunk-2L5QNDAE.js";
14
14
  import {
15
15
  IndexerClient
16
16
  } from "./chunk-J5J4JEJ6.js";
17
17
  import {
18
18
  CairnController
19
- } from "./chunk-AGU6K5EZ.js";
19
+ } from "./chunk-GTTLMWGY.js";
20
20
  import {
21
21
  WalletConnection,
22
22
  connect,
@@ -24,7 +24,7 @@ import {
24
24
  discoverProviders,
25
25
  getWallet,
26
26
  isInstalled
27
- } from "./chunk-BN3PFJDY.js";
27
+ } from "./chunk-RKR3JMIA.js";
28
28
  import {
29
29
  CairnError,
30
30
  ContentVerificationError,
@@ -38,7 +38,7 @@ import {
38
38
  errorCode,
39
39
  mapProviderError,
40
40
  mapSubmitResultError
41
- } from "./chunk-FMXNJQWL.js";
41
+ } from "./chunk-MREZG2HN.js";
42
42
 
43
43
  // src/http.ts
44
44
  var DEFAULT_MAX_BYTES = 16 * 1024 * 1024;
@@ -273,10 +273,38 @@ var NamesClient = class {
273
273
  // src/fillverify.ts
274
274
  import { rpcTxToTx } from "@inversealtruism/csd-client";
275
275
  import { txid, payloadHash } from "@inversealtruism/csd-codec";
276
- import { parseRecord, feeBpsAt, bindOfferTerms } from "@inversealtruism/cairnx-core";
276
+ import {
277
+ parseRecord,
278
+ feeBpsAt,
279
+ bindOfferTerms,
280
+ provenOfferTerms,
281
+ fillOutputPlan,
282
+ isTokenWant,
283
+ fillEndorsement,
284
+ fillIsSafe,
285
+ requiredFillOutputs,
286
+ previewFill
287
+ } from "@inversealtruism/cairnx-core";
277
288
  var ADDR = /^0x[0-9a-f]{40}$/;
278
289
  var HASH = /^0x[0-9a-f]{64}$/;
279
290
  var COINBASE = "0x" + "00".repeat(32);
291
+ function bindPlannedSums(planned, proven) {
292
+ const provenMap = new Map(proven.map((o) => [o.to.toLowerCase(), o.value]));
293
+ const plannedMap = /* @__PURE__ */ new Map();
294
+ try {
295
+ for (const [a, v] of Object.entries(planned)) {
296
+ const k = String(a).toLowerCase();
297
+ plannedMap.set(k, (plannedMap.get(k) ?? 0n) + BigInt(v));
298
+ }
299
+ } catch {
300
+ return "invalid plannedOutputs (amounts must be base-unit integers)";
301
+ }
302
+ for (const k of /* @__PURE__ */ new Set([...provenMap.keys(), ...plannedMap.keys()])) {
303
+ if ((provenMap.get(k) ?? 0n) !== (plannedMap.get(k) ?? 0n))
304
+ return `your planned payment doesn't match the proven fill outputs (${k}: planned ${(plannedMap.get(k) ?? 0n).toString()}, proven ${(provenMap.get(k) ?? 0n).toString()}) - refusing (an overpay past the proven amount is unrecoverable, and a missing or low leg is a doomed underpay)`;
305
+ }
306
+ return void 0;
307
+ }
280
308
  async function provenAuthor(client, provenTx) {
281
309
  const in0 = provenTx.inputs?.[0];
282
310
  if (!in0 || String(in0.prevTxid).toLowerCase() === COINBASE && Number(in0.vout) === 4294967295) return null;
@@ -332,17 +360,35 @@ async function preverifyOffer(opts) {
332
360
  return { ok: false, trust: "unverified", reason: "the offer record doesn't match the on-chain (merkle-proven) commitment" };
333
361
  const seller = await provenAuthor(opts.client, provenTx);
334
362
  if (!seller) return { ok: false, trust: "verified", transient: true, blockHeight, reason: "couldn't prove the offer's on-chain author yet; the chain view may be catching up, try again" };
363
+ const offerRec = rec;
335
364
  const w = rec.want ?? {};
336
365
  const payto = w.payto && ADDR.test(String(w.payto).toLowerCase()) ? String(w.payto).toLowerCase() : seller;
337
- const terms = {
338
- height: blockHeight,
339
- feeBps: feeBpsAt(blockHeight),
340
- value: w.value !== void 0 ? String(w.value) : void 0,
341
- taker: rec.taker !== void 0 ? String(rec.taker).toLowerCase() : void 0,
342
- bid: rec.bid !== void 0 ? String(rec.bid).toLowerCase() : void 0,
343
- min: rec.min !== void 0 ? String(rec.min) : void 0
344
- };
345
- const base = { payto, seller, terms, blockHeight };
366
+ const terms = provenOfferTerms(offerRec, blockHeight);
367
+ let outputPlan;
368
+ let sumsMismatch;
369
+ if (opts.pay !== void 0 && opts.pay !== null && !isTokenWant(offerRec.want) && offerRec.min === void 0) {
370
+ const provenState = {
371
+ id,
372
+ seller,
373
+ give: offerRec.give,
374
+ want: offerRec.want,
375
+ taker: offerRec.taker,
376
+ bid: offerRec.bid,
377
+ status: "open",
378
+ expiresEpoch: 0,
379
+ height: blockHeight,
380
+ feeBps: terms.feeBps
381
+ };
382
+ const plan = fillOutputPlan(provenState, opts.pay);
383
+ if (plan.kind === "csd-outputs") {
384
+ outputPlan = plan.outputs;
385
+ if (opts.plannedOutputs !== void 0 && opts.plannedOutputs !== null)
386
+ sumsMismatch = bindPlannedSums(opts.plannedOutputs, plan.outputs);
387
+ } else if (plan.kind === "undeliverable") {
388
+ sumsMismatch = `this pay would not deliver against the proven offer (${plan.reason}) - refusing (the CSD would be lost)`;
389
+ }
390
+ }
391
+ const base = { payto, seller, terms, blockHeight, ...outputPlan ? { outputPlan } : {} };
346
392
  if (opts.servedOffer !== void 0 && opts.servedOffer !== null) {
347
393
  const so = opts.servedOffer;
348
394
  const servedPayto = so?.want?.payto !== void 0 && so?.want?.payto !== null ? String(so.want.payto).toLowerCase() : "";
@@ -350,15 +396,20 @@ async function preverifyOffer(opts) {
350
396
  return { ok: false, trust: "verified", reason: "the served payment recipient doesn't match the offer's on-chain author/record", ...base };
351
397
  if (so?.seller !== void 0 && so?.seller !== null && String(so.seller).toLowerCase() !== seller)
352
398
  return { ok: false, trust: "verified", reason: "the served seller doesn't match the offer's on-chain author (a lying resolver may be redirecting your payment)", ...base };
353
- if (bindOfferTerms(opts.servedOffer, terms))
354
- return { ok: false, trust: "verified", reason: "the served fee/rebate/partial terms don't match the offer's on-chain record (a lying resolver could mis-size the fill, causing a rejected fill after your payment)", ...base };
399
+ if (bindOfferTerms(opts.servedOffer, terms, { give: true, wantType: true }))
400
+ return { ok: false, trust: "verified", reason: "the served terms don't match the offer's on-chain record (fee, rebate, partial sizing, the give, or the want type - a lying resolver could mis-size or re-route the fill, redirecting or burning your payment)", ...base };
355
401
  }
402
+ if (sumsMismatch) return { ok: false, trust: "verified", reason: sumsMismatch, ...base };
356
403
  return { ok: true, trust: "verified", ...base };
357
404
  }
358
405
 
359
406
  // src/index.ts
360
407
  var DEFAULT_SPV_CHECKPOINT = { height: 38142, hash: "0x00000000000140f023cc0ee1457a40833f2fcb4de44291b9d373e50f17b97232" };
361
408
  var DEFAULT_CAIRN = "https://cairn-substrate.com";
409
+ var SPV_HTTP_TIMEOUT_MS = 15e3;
410
+ var SPV_HTTP_MAX_RETRIES = 4;
411
+ var spvSleep = (ms) => new Promise((r) => setTimeout(r, ms));
412
+ var spvRetryDelayMs = (attempt, retryAfterSecs) => Math.min(4e3, Math.max(700 * (attempt + 1), retryAfterSecs * 1e3));
362
413
  var Cairn = class {
363
414
  config;
364
415
  chain;
@@ -374,6 +425,8 @@ var Cairn = class {
374
425
  _spvLight = null;
375
426
  _spvSeeded = false;
376
427
  _spvCp;
428
+ // W12: the cairn base the SPV header-batch provider fetches /api/headers from (same base the rest of the SDK uses).
429
+ _cairnBase;
377
430
  constructor(config = {}) {
378
431
  this.config = config;
379
432
  const fetch = config.fetch;
@@ -382,6 +435,7 @@ var Cairn = class {
382
435
  const rpc = config.baseUrls?.rpc ?? `${cairn}/api/rpc`;
383
436
  const indexer = (config.baseUrls?.indexer ?? `${cairn}/explorer/api`).replace(/\/+$/, "");
384
437
  this.cairnHttp = new Http({ baseUrl: cairn, fetch, timeoutMs });
438
+ this._cairnBase = cairn;
385
439
  const indexerHttp = new Http({ baseUrl: indexer, fetch, timeoutMs });
386
440
  const swarmHttp = config.baseUrls?.swarm ? new Http({ baseUrl: config.baseUrls.swarm.replace(/\/+$/, ""), fetch, timeoutMs }) : void 0;
387
441
  this._spvCp = config.spvCheckpoint ?? DEFAULT_SPV_CHECKPOINT;
@@ -418,13 +472,69 @@ var Cairn = class {
418
472
  /** The PoW-verifying SPV light client, seeded ONCE from the pinned checkpoint (shared by the M3 header-merkle
419
473
  * bind and the F13 offer pre-verify). Reused across calls; the first call near tip syncs the post-checkpoint span. */
420
474
  async seededSpvLight() {
421
- if (!this._spvLight) this._spvLight = new LightClient({ client: this.chain.client, checkpoints: { [this._spvCp.height]: this._spvCp.hash } });
475
+ if (!this._spvLight) this._spvLight = new LightClient({
476
+ client: this.chain.client,
477
+ checkpoints: { [this._spvCp.height]: this._spvCp.hash },
478
+ headersBatchProvider: (from, count) => this.fetchHeadersBatch(from, count)
479
+ });
422
480
  if (!this._spvSeeded) {
423
481
  await this._spvLight.syncFromCheckpoint(this._spvCp.height, this._spvCp.hash);
482
+ try {
483
+ const tipHeight = Number((await this.chain.tip()).height);
484
+ const have = this._spvLight.baseHeight + this._spvLight.chain.length - 1;
485
+ if (Number.isFinite(tipHeight) && tipHeight > have) await this._spvLight.sync(tipHeight);
486
+ } catch {
487
+ }
424
488
  this._spvSeeded = true;
425
489
  }
426
490
  return this._spvLight;
427
491
  }
492
+ /**
493
+ * W12 batch header transport for the checkpoint..tip forward sync, backed by the cairn server's
494
+ * `/api/headers/:from/:count`. Carries ZERO trust: the LightClient re-verifies every header's PoW /
495
+ * prev-link / LWMA, so a forged or stale row fails closed and retrying transport proves nothing new.
496
+ * Retry budget: a 429 (per-IP header budget) or 502/503 (a height past the lagging indexer, or the
497
+ * server's 10s deadline) is a transient data-availability hiccup; back off (honouring Retry-After) a
498
+ * bounded number of times, then THROW so `sync()` fails closed. A non-dense range is rejected.
499
+ *
500
+ * B7d / F6 DEPENDENCY: `/api/headers` serves no Access-Control-Allow-Origin today (`corsPublic` is
501
+ * mounted on `/explorer/api`, `/trade/api` and `/api/rpc`, not here). A SAME-ORIGIN dApp (hosted on the
502
+ * cairn base) reaches it now; a CROSS-ORIGIN third-party dApp cannot until B7d adds the CORS mount and
503
+ * restarts the cairn service. This code is correct as written; it becomes reachable cross-origin only
504
+ * once B7d ships. This is a recorded dependency, not a blocker for authoring/testing.
505
+ */
506
+ async fetchHeadersBatch(from, count) {
507
+ const g = this.config.fetch ?? globalThis.fetch;
508
+ if (!g) throw new Error("No fetch available for SPV header sync - pass `fetch` in the SDK options.");
509
+ const doFetch = this.config.fetch ? this.config.fetch : g.bind(globalThis);
510
+ const url = `${this._cairnBase}/api/headers/${from}/${count}`;
511
+ for (let attempt = 0; ; attempt++) {
512
+ let res;
513
+ const ctrl = new AbortController();
514
+ const timer = setTimeout(() => ctrl.abort(), SPV_HTTP_TIMEOUT_MS);
515
+ try {
516
+ res = await doFetch(url, { signal: ctrl.signal });
517
+ } catch (e) {
518
+ if (attempt >= SPV_HTTP_MAX_RETRIES) throw e;
519
+ await spvSleep(spvRetryDelayMs(attempt, 0));
520
+ continue;
521
+ } finally {
522
+ clearTimeout(timer);
523
+ }
524
+ if (res.ok) {
525
+ const rows = (await res.json())?.headers;
526
+ if (!Array.isArray(rows) || rows.length !== count) throw new Error(`/api/headers: non-dense range (${from}/${count})`);
527
+ return rows.map((r) => ({ header: r.header, hash: r.hash }));
528
+ }
529
+ if ((res.status === 429 || res.status === 502 || res.status === 503) && attempt < SPV_HTTP_MAX_RETRIES) {
530
+ res.body?.cancel?.().catch(() => {
531
+ });
532
+ await spvSleep(spvRetryDelayMs(attempt, Number(res.headers.get("retry-after")) || 0));
533
+ continue;
534
+ }
535
+ throw new Error(`/api/headers ${res.status}`);
536
+ }
537
+ }
428
538
  /**
429
539
  * F13 — corroborate an offer ON-CHAIN before building a `fillOffer` payment's `outputs`. Merkle-proves the
430
540
  * offer into the PoW-verified header chain (from the pinned SPV checkpoint), binds the record to its on-chain
@@ -487,9 +597,14 @@ export {
487
597
  discoverProviders,
488
598
  errorCode,
489
599
  feeBpsAt,
600
+ fillEndorsement,
601
+ fillIsSafe,
602
+ fillOutputPlan,
490
603
  getWallet,
491
604
  isInstalled,
492
605
  mapProviderError,
493
606
  mapSubmitResultError,
494
- preverifyOffer
607
+ preverifyOffer,
608
+ previewFill,
609
+ requiredFillOutputs
495
610
  };
package/dist/react.cjs CHANGED
@@ -26,7 +26,7 @@ __export(react_exports, {
26
26
  module.exports = __toCommonJS(react_exports);
27
27
 
28
28
  // src/errors.ts
29
- var SDK_VERSION = "0.3.2";
29
+ var SDK_VERSION = "0.4.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. */
@@ -100,7 +100,7 @@ var SubmitInFlightError = class extends CairnError {
100
100
  this.txid = txid;
101
101
  }
102
102
  };
103
- var NATIVE_CODES = /* @__PURE__ */ new Set(["ACCOUNT_CHANGED", "FIRST_PARTY_ONLY", "RATE_LIMITED", "APPROVAL_CLOSED", "FORBIDDEN", "INTERNAL"]);
103
+ var NATIVE_CODES = /* @__PURE__ */ new Set(["FIRST_PARTY_ONLY", "RATE_LIMITED", "FORBIDDEN", "INTERNAL"]);
104
104
  var NESTED_TRANSIENT = /* @__PURE__ */ new Set(["VERIFY_UNAVAILABLE", "OFFER_UNKNOWN"]);
105
105
  var NESTED_TERMINAL = /* @__PURE__ */ new Set([
106
106
  "FILL_UNSAFE",
@@ -144,6 +144,7 @@ function mapSubmitResultError(result) {
144
144
  }
145
145
 
146
146
  // src/connect.ts
147
+ var DEFAULT_PROVIDER_TIMEOUT_MS = 10 * 6e4;
147
148
  function detectProvider(opts = {}) {
148
149
  const timeoutMs = opts.timeoutMs ?? 3e3;
149
150
  return new Promise((resolve, reject) => {
@@ -200,8 +201,24 @@ function unwrapWrite(reply) {
200
201
  var WalletConnection = class {
201
202
  provider;
202
203
  _addr = null;
203
- constructor(provider) {
204
+ /** B7c: per-call provider timeout (ms). GENEROUS by default so it never rejects an in-flight human
205
+ * approval; 0 disables it. Every provider call (writes especially) races against it. */
206
+ _timeoutMs;
207
+ constructor(provider, opts = {}) {
204
208
  this.provider = provider;
209
+ this._timeoutMs = opts.timeoutMs ?? DEFAULT_PROVIDER_TIMEOUT_MS;
210
+ }
211
+ // B7c: race a provider call against the per-call timeout. On timeout, throw a fail-closed CairnError
212
+ // (retryable:false: a write may already have reached the wallet, so never invite a blind auto-retry). The
213
+ // genuine wallet resolves quickly once the user acts; this only fires on a truly hung/absent response.
214
+ call(op, label) {
215
+ const ms = this._timeoutMs;
216
+ if (!Number.isFinite(ms) || ms <= 0) return Promise.resolve(op());
217
+ let timer;
218
+ const timeout = new Promise((_, reject) => {
219
+ timer = setTimeout(() => reject(new CairnError(`the wallet did not respond to ${label} within ${ms}ms`, { retryable: false })), ms);
220
+ });
221
+ return Promise.race([Promise.resolve(op()), timeout]).finally(() => clearTimeout(timer));
205
222
  }
206
223
  /** The wallet's version string (e.g. "0.2.x"). */
207
224
  get version() {
@@ -213,13 +230,13 @@ var WalletConnection = class {
213
230
  }
214
231
  /** Request connection. First time per origin prompts the user; afterwards may be silent. */
215
232
  async connect() {
216
- const { addr } = unwrap(await this.provider.connect());
233
+ const { addr } = unwrap(await this.call(() => this.provider.connect(), "connect"));
217
234
  this._addr = addr;
218
235
  return addr;
219
236
  }
220
237
  /** Get the connected address (does not force a new connection prompt if already consented). */
221
238
  async getAddress() {
222
- const { addr } = unwrap(await this.provider.getAddress());
239
+ const { addr } = unwrap(await this.call(() => this.provider.getAddress(), "getAddress"));
223
240
  this._addr = addr;
224
241
  return addr;
225
242
  }
@@ -232,7 +249,7 @@ var WalletConnection = class {
232
249
  if (typeof this.provider.signIn !== "function") {
233
250
  return Promise.reject(new UnsupportedMethodError("this wallet does not expose signIn()"));
234
251
  }
235
- return Promise.resolve(this.provider.signIn()).then(unwrap);
252
+ return this.call(() => this.provider.signIn(), "signIn").then(unwrap);
236
253
  }
237
254
  /**
238
255
  * Audience-bound "Sign in with CSD" (SIWC) — the secure, replay-resistant third-party login.
@@ -248,7 +265,7 @@ var WalletConnection = class {
248
265
  if (typeof this.provider.signInWithCsd !== "function") {
249
266
  return Promise.reject(new UnsupportedMethodError("this wallet predates Sign-in-with-CSD \u2014 ask the user to update the Cairn Wallet"));
250
267
  }
251
- return Promise.resolve(this.provider.signInWithCsd(params)).then(unwrap);
268
+ return this.call(() => this.provider.signInWithCsd(params), "signInWithCsd").then(unwrap);
252
269
  }
253
270
  /** True if this wallet supports audience-bound SIWC (safe to call `signInWithCsd`). */
254
271
  get supportsSiwc() {
@@ -258,7 +275,7 @@ var WalletConnection = class {
258
275
  async getCapabilities() {
259
276
  if (typeof this.provider.getCapabilities !== "function") return null;
260
277
  try {
261
- return await this.provider.getCapabilities();
278
+ return await this.call(() => this.provider.getCapabilities(), "getCapabilities");
262
279
  } catch {
263
280
  return null;
264
281
  }
@@ -274,24 +291,24 @@ var WalletConnection = class {
274
291
  if (typeof this.provider.fillOffer !== "function") {
275
292
  return Promise.reject(new UnsupportedMethodError("this wallet predates fillOffer() \u2014 ask the user to update the Cairn Wallet"));
276
293
  }
277
- return Promise.resolve(this.provider.fillOffer(params)).then(unwrapWrite);
294
+ return this.call(() => this.provider.fillOffer(params), "fillOffer").then(unwrapWrite);
278
295
  }
279
296
  /** This origin's current permission grant (EIP-2255-style). Silent; [] if none / unsupported. */
280
297
  async getPermissions() {
281
298
  if (typeof this.provider.getPermissions !== "function") return [];
282
- return unwrap(await this.provider.getPermissions());
299
+ return unwrap(await this.call(() => this.provider.getPermissions(), "getPermissions"));
283
300
  }
284
301
  /** Explicitly request permission to see the address (prompts, like connect). */
285
302
  requestPermissions() {
286
303
  if (typeof this.provider.requestPermissions !== "function") {
287
304
  return Promise.reject(new UnsupportedMethodError("this wallet predates requestPermissions \u2014 use connect()"));
288
305
  }
289
- return Promise.resolve(this.provider.requestPermissions()).then(unwrap);
306
+ return this.call(() => this.provider.requestPermissions(), "requestPermissions").then(unwrap);
290
307
  }
291
308
  /** Revoke THIS origin's own access (silent). Returns { revoked }. Safe no-op on older wallets. */
292
309
  async revokePermissions() {
293
310
  if (typeof this.provider.revokePermissions !== "function") return { revoked: false };
294
- return unwrap(await this.provider.revokePermissions());
311
+ return unwrap(await this.call(() => this.provider.revokePermissions(), "revokePermissions"));
295
312
  }
296
313
  /**
297
314
  * Subscribe to provider events. `accountsChanged` fires with `[]` when this site loses access
@@ -307,26 +324,26 @@ var WalletConnection = class {
307
324
  }
308
325
  /** Send CSD (always prompts with clear-signing; wallet picks inputs + returns change to itself). */
309
326
  send(params) {
310
- return Promise.resolve(this.provider.send(params)).then(unwrapWrite);
327
+ return this.call(() => this.provider.send(params), "send").then(unwrapWrite);
311
328
  }
312
329
  /** Low-level Propose (always prompts). Prefer `cairn.board.propose()` which computes the hash/uri/expiry. */
313
330
  propose(params) {
314
- return Promise.resolve(this.provider.propose(params)).then(unwrapWrite);
331
+ return this.call(() => this.provider.propose(params), "propose").then(unwrapWrite);
315
332
  }
316
333
  /** Attest/support a proposal (always prompts). */
317
334
  attest(params) {
318
- return Promise.resolve(this.provider.attest(params)).then(unwrapWrite);
335
+ return this.call(() => this.provider.attest(params), "attest").then(unwrapWrite);
319
336
  }
320
337
  /** Seal a commit-reveal claim (always prompts; salt stays inside the wallet). */
321
338
  sealClaim(params) {
322
- return Promise.resolve(this.provider.sealClaim(params)).then(unwrapWrite);
339
+ return this.call(() => this.provider.sealClaim(params), "sealClaim").then(unwrapWrite);
323
340
  }
324
341
  /** Reveal a previously sealed claim by its sealing txid (always prompts). */
325
342
  revealClaim(txid) {
326
343
  if (typeof txid !== "string" || !txid) {
327
344
  return Promise.reject(new UnsupportedMethodError("revealClaim requires the sealing txid"));
328
345
  }
329
- return Promise.resolve(this.provider.revealClaim(txid)).then(unwrapWrite);
346
+ return this.call(() => this.provider.revealClaim(txid), "revealClaim").then(unwrapWrite);
330
347
  }
331
348
  };
332
349
  async function getWallet(opts = {}) {
package/dist/react.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  CairnController
3
- } from "./chunk-AGU6K5EZ.js";
4
- import "./chunk-BN3PFJDY.js";
5
- import "./chunk-FMXNJQWL.js";
3
+ } from "./chunk-GTTLMWGY.js";
4
+ import "./chunk-RKR3JMIA.js";
5
+ import "./chunk-MREZG2HN.js";
6
6
 
7
7
  // src/react.ts
8
8
  function createCairnHooks(React, controllerOrOpts) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inversealtruism/cairn-sdk",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
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",
@@ -58,21 +58,8 @@
58
58
  "LICENSE",
59
59
  "README.md"
60
60
  ],
61
- "scripts": {
62
- "build": "tsup src/index.ts src/connect.ts src/board.ts src/indexer.ts src/content.ts src/registry.ts src/chain.ts src/controller.ts src/react.ts --format esm,cjs --dts --clean",
63
- "test": "node test/run.mjs",
64
- "test:live": "node examples/read-only.mjs",
65
- "build:example": "node scripts/build-example.mjs",
66
- "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
67
- "test:e2e:read": "node test/e2e/e2e-read.mjs",
68
- "test:e2e:wallet": "xvfb-run -a node test/e2e/e2e-wallet-connect.mjs",
69
- "test:e2e:write": "node test/e2e/e2e-write.mjs",
70
- "test:e2e": "node test/e2e/e2e-read.mjs && xvfb-run -a node test/e2e/e2e-wallet-connect.mjs",
71
- "test:all": "pnpm test && pnpm test:e2e",
72
- "prepublishOnly": "npm run build && npm test"
73
- },
74
61
  "dependencies": {
75
- "@inversealtruism/cairnx-core": "0.1.38",
62
+ "@inversealtruism/cairnx-core": "0.1.40",
76
63
  "@inversealtruism/csd-client": "0.1.15",
77
64
  "@inversealtruism/csd-codec": "0.1.15",
78
65
  "@inversealtruism/csd-crypto": "0.1.15",
@@ -81,20 +68,14 @@
81
68
  "@inversealtruism/csd-tx": "0.1.17"
82
69
  },
83
70
  "devDependencies": {
71
+ "@inversealtruism/csd-siwc": "0.1.15",
84
72
  "esbuild": "^0.27.0",
85
73
  "playwright-core": "^1.49.0",
86
74
  "tsup": "^8.5.1",
87
75
  "tsx": "^4.19.2",
88
- "typescript": "^5.6.0",
89
- "@inversealtruism/csd-siwc": "0.1.15"
76
+ "typescript": "^5.6.0"
90
77
  },
91
78
  "sideEffects": false,
92
- "packageManager": "pnpm@10.32.1",
93
- "pnpm": {
94
- "onlyBuiltDependencies": [
95
- "esbuild"
96
- ]
97
- },
98
79
  "license": "MIT",
99
80
  "publishConfig": {
100
81
  "access": "public"
@@ -112,5 +93,17 @@
112
93
  "dapp",
113
94
  "sdk",
114
95
  "blockchain"
115
- ]
116
- }
96
+ ],
97
+ "scripts": {
98
+ "build": "tsup src/index.ts src/connect.ts src/board.ts src/indexer.ts src/content.ts src/registry.ts src/chain.ts src/controller.ts src/react.ts --format esm,cjs --dts --clean",
99
+ "test": "node test/run.mjs",
100
+ "test:live": "node examples/read-only.mjs",
101
+ "build:example": "node scripts/build-example.mjs",
102
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
103
+ "test:e2e:read": "node test/e2e/e2e-read.mjs",
104
+ "test:e2e:wallet": "xvfb-run -a node test/e2e/e2e-wallet-connect.mjs",
105
+ "test:e2e:write": "node test/e2e/e2e-write.mjs",
106
+ "test:e2e": "node test/e2e/e2e-read.mjs && xvfb-run -a node test/e2e/e2e-wallet-connect.mjs",
107
+ "test:all": "pnpm test && pnpm test:e2e"
108
+ }
109
+ }