@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/board.cjs +1 -1
- package/dist/board.js +2 -2
- package/dist/{chunk-JKC5K253.js → chunk-2L5QNDAE.js} +1 -1
- package/dist/{chunk-CZWDA3A5.js → chunk-2ZML7IKV.js} +1 -1
- package/dist/{chunk-AGU6K5EZ.js → chunk-GTTLMWGY.js} +1 -1
- package/dist/{chunk-FMXNJQWL.js → chunk-MREZG2HN.js} +2 -2
- package/dist/{chunk-BN3PFJDY.js → chunk-RKR3JMIA.js} +34 -16
- package/dist/connect.cjs +34 -17
- package/dist/connect.d.cts +7 -1
- package/dist/connect.d.ts +7 -1
- package/dist/connect.js +2 -2
- package/dist/content.cjs +1 -1
- package/dist/content.js +2 -2
- package/dist/controller.cjs +34 -17
- package/dist/controller.js +3 -3
- package/dist/index.cjs +157 -31
- package/dist/index.d.cts +39 -13
- package/dist/index.d.ts +39 -13
- package/dist/index.js +134 -19
- package/dist/react.cjs +34 -17
- package/dist/react.js +3 -3
- package/package.json +18 -25
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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 {
|
|
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
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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
|
|
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({
|
|
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.
|
|
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(["
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
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
|
+
"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.
|
|
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
|
+
}
|