@inversealtruism/cairn-sdk 0.8.1 → 0.8.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/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.8.1";
29
+ var SDK_VERSION = "0.8.2";
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. */
@@ -91,17 +91,22 @@ var UnsupportedMethodError = class extends CairnError {
91
91
  }
92
92
  };
93
93
  var SubmitInFlightError = class extends CairnError {
94
- /** The locally-computed consensus txid to reconcile against the chain (may be undefined if the wallet omitted it). */
94
+ /** The locally-computed consensus txid to reconcile against the chain (undefined when it is not known). */
95
95
  txid;
96
- /** Always true: the tx MAY be in the mempool. Reconcile via `txid`; never blind-retry. */
96
+ /** The signed transaction, set only when `Chain.send` threw this (a wallet write keeps it in the wallet).
97
+ * `chain.submit(nodeJson)` resends it unchanged: the same coins under the same txid, so it cannot pay twice,
98
+ * where a new send may select other coins. */
99
+ nodeJson;
100
+ /** Always true: the tx MAY be in the mempool. Reconcile via `txid` or the balance; never blind-retry. */
97
101
  maybeSent = true;
98
- constructor(message, code, txid) {
99
- super(message, { code, docsPath: "/errors#submit-inflight", retryable: false });
102
+ constructor(message, code, txid, cause, nodeJson) {
103
+ super(message, { code, docsPath: "/errors#submit-inflight", retryable: false, cause });
100
104
  this.txid = txid;
105
+ this.nodeJson = nodeJson;
101
106
  }
102
107
  };
103
108
  var NATIVE_CODES = /* @__PURE__ */ new Set(["FIRST_PARTY_ONLY", "RATE_LIMITED", "FORBIDDEN", "INTERNAL"]);
104
- var NESTED_TRANSIENT = /* @__PURE__ */ new Set(["VERIFY_UNAVAILABLE", "OFFER_UNKNOWN", "WALLET_UNAVAILABLE", "REVIEW_REQUIRED"]);
109
+ var NESTED_TRANSIENT = /* @__PURE__ */ new Set(["VERIFY_UNAVAILABLE", "OFFER_UNKNOWN", "WALLET_UNAVAILABLE", "REVIEW_REQUIRED", "SEAL_NOT_MINED"]);
105
110
  var NESTED_TERMINAL = /* @__PURE__ */ new Set([
106
111
  "FILL_UNSAFE",
107
112
  "FILL_WRONG_TARGET",
@@ -123,7 +128,9 @@ var NESTED_TERMINAL = /* @__PURE__ */ new Set([
123
128
  "OFFER_SOURCE_CONFLICT",
124
129
  "FILL_LEGACY_SUNSET",
125
130
  "VERIFY_HORIZON",
126
- "VERIFY_UNREPRESENTABLE"
131
+ "VERIFY_UNREPRESENTABLE",
132
+ "RESERVATION_DENIED",
133
+ "RPC_BLOCK_MISMATCH"
127
134
  ]);
128
135
  function mapProviderError(error, code) {
129
136
  if (code === "USER_REJECTED" || code === "APPROVAL_CLOSED") return new UserRejectedError(error);
@@ -141,11 +148,15 @@ function mapProviderError(error, code) {
141
148
  function mapSubmitResultError(result) {
142
149
  const code = result?.code;
143
150
  const msg = typeof result?.error === "string" && result.error || code || "The wallet refused the transaction.";
144
- if (code === "SUBMIT_MAYBE_INFLIGHT" || code === "SUBMIT_DUPLICATE") {
151
+ if (code === "SUBMIT_MAYBE_INFLIGHT" || code === "SUBMIT_DUPLICATE" || code === "WALLET_UNAVAILABLE") {
145
152
  return new SubmitInFlightError(msg, code, typeof result?.txid === "string" ? result.txid : void 0);
146
153
  }
147
154
  return mapProviderError(msg, code);
148
155
  }
156
+ function mapWriteProviderError(error, code) {
157
+ if (code === "WALLET_UNAVAILABLE") return new SubmitInFlightError(error || code, code);
158
+ return mapProviderError(error, code);
159
+ }
149
160
 
150
161
  // src/connect.ts
151
162
  var DEFAULT_PROVIDER_TIMEOUT_MS = 10 * 6e4;
@@ -196,7 +207,8 @@ function unwrap(reply) {
196
207
  throw mapProviderError(reply?.error ?? "Unknown wallet error", reply?.code);
197
208
  }
198
209
  function unwrapWrite(reply) {
199
- const result = unwrap(reply);
210
+ if (!reply || !reply.ok) throw mapWriteProviderError(reply?.error ?? "Unknown wallet error", reply?.code);
211
+ const result = reply.result;
200
212
  if (result && typeof result === "object" && result.ok === false) {
201
213
  throw mapSubmitResultError(result);
202
214
  }
@@ -212,10 +224,12 @@ var WalletConnection = class {
212
224
  this.provider = provider;
213
225
  this._timeoutMs = opts.timeoutMs ?? DEFAULT_PROVIDER_TIMEOUT_MS;
214
226
  }
215
- // B7c: race a provider call against the per-call timeout. On timeout, throw a fail-closed CairnError
216
- // (retryable:false: a write may already have reached the wallet, so never invite a blind auto-retry). The
217
- // genuine wallet resolves quickly once the user acts; this only fires on a truly hung/absent response.
218
- call(op, label) {
227
+ // B7c: race a provider call against the per-call timeout. On timeout, throw a fail-closed error
228
+ // (retryable:false). A write's request stays open in the wallet and may still be approved and sent, so its
229
+ // timeout is a maybe-sent SubmitInFlightError (WALLET_TIMEOUT, no txid); while that request stays open, a resend
230
+ // opens a second one, and approving both sends twice. The genuine wallet resolves quickly
231
+ // once the user acts; this only fires on a truly hung/absent response.
232
+ call(op, label, write = false) {
219
233
  const ms = this._timeoutMs;
220
234
  const invoke = () => new Promise((resolve) => {
221
235
  resolve(op());
@@ -223,7 +237,7 @@ var WalletConnection = class {
223
237
  if (!Number.isFinite(ms) || ms <= 0) return invoke();
224
238
  let timer;
225
239
  const timeout = new Promise((_, reject) => {
226
- timer = setTimeout(() => reject(new CairnError(`the wallet did not respond to ${label} within ${ms}ms`, { retryable: false })), ms);
240
+ timer = setTimeout(() => reject(write ? new SubmitInFlightError(`the wallet did not respond to ${label} within ${ms}ms; the request may still be open in the wallet and be sent if approved, so reject it in the wallet and check the chain before sending it again`, "WALLET_TIMEOUT") : new CairnError(`the wallet did not respond to ${label} within ${ms}ms`, { retryable: false })), ms);
227
241
  });
228
242
  return Promise.race([invoke(), timeout]).finally(() => clearTimeout(timer));
229
243
  }
@@ -299,7 +313,7 @@ var WalletConnection = class {
299
313
  return Promise.reject(new UnsupportedMethodError("this wallet predates fillOffer() \u2014 ask the user to update the Cairn Wallet"));
300
314
  }
301
315
  this.adviseFillSpvCapability();
302
- return this.call(() => this.provider.fillOffer(params), "fillOffer").then(unwrapWrite);
316
+ return this.call(() => this.provider.fillOffer(params), "fillOffer", true).then(unwrapWrite);
303
317
  }
304
318
  // P75-5 MF-10: ONE capability advisory per connection. The wallet's on-device fill-SPV (0.2.60+) is the
305
319
  // payment-grade fill boundary; when the provider SELF-REPORTS an older version, warn the integrator once
@@ -347,26 +361,26 @@ var WalletConnection = class {
347
361
  }
348
362
  /** Send CSD (always prompts with clear-signing; wallet picks inputs + returns change to itself). */
349
363
  send(params) {
350
- return this.call(() => this.provider.send(params), "send").then(unwrapWrite);
364
+ return this.call(() => this.provider.send(params), "send", true).then(unwrapWrite);
351
365
  }
352
366
  /** Low-level Propose (always prompts). The caller computes the payload hash, uri and expiry epoch. */
353
367
  propose(params) {
354
- return this.call(() => this.provider.propose(params), "propose").then(unwrapWrite);
368
+ return this.call(() => this.provider.propose(params), "propose", true).then(unwrapWrite);
355
369
  }
356
370
  /** Attest/support a proposal (always prompts). */
357
371
  attest(params) {
358
- return this.call(() => this.provider.attest(params), "attest").then(unwrapWrite);
372
+ return this.call(() => this.provider.attest(params), "attest", true).then(unwrapWrite);
359
373
  }
360
374
  /** Seal a commit-reveal claim (always prompts; salt stays inside the wallet). */
361
375
  sealClaim(params) {
362
- return this.call(() => this.provider.sealClaim(params), "sealClaim").then(unwrapWrite);
376
+ return this.call(() => this.provider.sealClaim(params), "sealClaim", true).then(unwrapWrite);
363
377
  }
364
378
  /** Reveal a previously sealed claim by its sealing txid (always prompts). */
365
379
  revealClaim(txid) {
366
380
  if (typeof txid !== "string" || !txid) {
367
381
  return Promise.reject(new UnsupportedMethodError("revealClaim requires the sealing txid"));
368
382
  }
369
- return this.call(() => this.provider.revealClaim(txid), "revealClaim").then(unwrapWrite);
383
+ return this.call(() => this.provider.revealClaim(txid), "revealClaim", true).then(unwrapWrite);
370
384
  }
371
385
  };
372
386
  async function getWallet(opts = {}) {
package/dist/react.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  CairnController
3
- } from "./chunk-QWGR5J5D.js";
4
- import "./chunk-F3KJPQXM.js";
5
- import "./chunk-X7J6ECNV.js";
3
+ } from "./chunk-AHPXOYCC.js";
4
+ import "./chunk-EVEBQSDK.js";
5
+ import "./chunk-37OHCH7R.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.8.1",
3
+ "version": "0.8.2",
4
4
  "description": "The Compute Substrate dApp kit: one cohesive toolkit to connect the Cairn Wallet, read the chain, the indexer and .csd names, verify self-certifying content, and resolve .csd names. Composes the published csd-* primitives.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -49,16 +49,16 @@
49
49
  "README.md"
50
50
  ],
51
51
  "dependencies": {
52
- "@inversealtruism/cairnx-core": "0.2.3",
52
+ "@inversealtruism/cairnx-core": "0.2.4",
53
53
  "@inversealtruism/csd-client": "0.1.20",
54
54
  "@inversealtruism/csd-codec": "0.1.18",
55
- "@inversealtruism/csd-crypto": "0.1.20",
55
+ "@inversealtruism/csd-crypto": "0.1.21",
56
56
  "@inversealtruism/csd-light": "0.1.26",
57
- "@inversealtruism/csd-tx": "0.1.23"
57
+ "@inversealtruism/csd-tx": "0.1.24"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@biomejs/biome": "2.5.15",
61
- "@inversealtruism/csd-siwc": "0.1.21",
61
+ "@inversealtruism/csd-siwc": "0.1.22",
62
62
  "@types/node": "22.19.20",
63
63
  "esbuild": "0.28.2",
64
64
  "playwright-core": "1.60.0",
@@ -66,6 +66,9 @@
66
66
  "tsx": "4.22.4",
67
67
  "typescript": "5.9.3"
68
68
  },
69
+ "engines": {
70
+ "node": ">=22"
71
+ },
69
72
  "sideEffects": false,
70
73
  "license": "MIT",
71
74
  "publishConfig": {