@inversealtruism/cairn-sdk 0.1.2 → 0.1.3

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 ADDED
@@ -0,0 +1,353 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/react.ts
21
+ var react_exports = {};
22
+ __export(react_exports, {
23
+ CairnController: () => CairnController,
24
+ createCairnHooks: () => createCairnHooks
25
+ });
26
+ module.exports = __toCommonJS(react_exports);
27
+
28
+ // src/errors.ts
29
+ var SDK_VERSION = "0.1.2";
30
+ var DOCS_BASE = "https://cairn-substrate.com/docs/sdk";
31
+ var CairnError = class extends Error {
32
+ /** Stable machine code for programmatic branching. */
33
+ code;
34
+ /** The human message without the appended docs/version footer. */
35
+ shortMessage;
36
+ /** Relative docs path (under the SDK docs base), if any. */
37
+ docsPath;
38
+ /** The cairn-sdk version that produced this error. */
39
+ version = SDK_VERSION;
40
+ constructor(shortMessage, opts = {}) {
41
+ const docs = opts.docsPath;
42
+ super(
43
+ [shortMessage, docs ? `Docs: ${DOCS_BASE}${docs}` : "", `Version: cairn-sdk@${SDK_VERSION}`].filter(Boolean).join("\n"),
44
+ { cause: opts.cause }
45
+ );
46
+ this.name = new.target.name;
47
+ this.code = opts.code ?? "UNKNOWN";
48
+ this.shortMessage = shortMessage;
49
+ this.docsPath = docs;
50
+ }
51
+ /**
52
+ * Walk the `cause` chain. With a predicate, returns the FIRST matching error (or null). Without one,
53
+ * returns the DEEPEST cause (the root). Mirrors viem's `BaseError.walk()`.
54
+ */
55
+ walk(fn) {
56
+ let current = this;
57
+ let last = this;
58
+ while (current != null) {
59
+ if (fn && fn(current)) return current;
60
+ last = current;
61
+ current = current?.cause;
62
+ }
63
+ return fn ? null : last;
64
+ }
65
+ };
66
+ var NotInstalledError = class extends CairnError {
67
+ constructor(message = "Cairn Wallet not detected. Install it from cairn-substrate.com.") {
68
+ super(message, { code: "NOT_INSTALLED", docsPath: "/install" });
69
+ }
70
+ };
71
+ var UserRejectedError = class extends CairnError {
72
+ constructor(message = "Request rejected by user.") {
73
+ super(message, { code: "USER_REJECTED", docsPath: "/errors#user-rejected" });
74
+ }
75
+ };
76
+ var WalletLockedError = class extends CairnError {
77
+ constructor(message = "Wallet is locked.") {
78
+ super(message, { code: "WALLET_LOCKED", docsPath: "/errors#wallet-locked" });
79
+ }
80
+ };
81
+ var UnsupportedMethodError = class extends CairnError {
82
+ constructor(message = "Method not supported by the wallet.") {
83
+ super(message, { code: "UNSUPPORTED_METHOD", docsPath: "/errors#unsupported-method" });
84
+ }
85
+ };
86
+ function mapProviderError(error) {
87
+ const e = String(error || "").toLowerCase();
88
+ if (e.includes("rejected by user")) return new UserRejectedError(error);
89
+ if (e.includes("wallet locked")) return new WalletLockedError(error);
90
+ if (e.includes("unsupported dapp method") || e.includes("predates") || e.includes("too old")) return new UnsupportedMethodError(error);
91
+ return new CairnError(error || "Unknown wallet error");
92
+ }
93
+
94
+ // src/connect.ts
95
+ function detectProvider(opts = {}) {
96
+ const timeoutMs = opts.timeoutMs ?? 3e3;
97
+ return new Promise((resolve, reject) => {
98
+ if (typeof window === "undefined") {
99
+ reject(new NotInstalledError("Not running in a browser \u2014 `window.cairn` is unavailable."));
100
+ return;
101
+ }
102
+ let done = false;
103
+ const finish = (p) => {
104
+ if (done) return;
105
+ done = true;
106
+ cleanup();
107
+ resolve(p);
108
+ };
109
+ const onInit = () => {
110
+ if (!done && window.cairn?.isCairn) finish(window.cairn);
111
+ };
112
+ const onAnnounce = (ev) => {
113
+ const p = ev?.detail?.provider;
114
+ if (p?.isCairn) finish(p);
115
+ };
116
+ const timer = setTimeout(() => {
117
+ if (done) return;
118
+ done = true;
119
+ cleanup();
120
+ reject(new NotInstalledError());
121
+ }, timeoutMs);
122
+ const cleanup = () => {
123
+ clearTimeout(timer);
124
+ window.removeEventListener("cairn#initialized", onInit);
125
+ window.removeEventListener("csd:announceProvider", onAnnounce);
126
+ };
127
+ window.addEventListener("cairn#initialized", onInit);
128
+ window.addEventListener("csd:announceProvider", onAnnounce);
129
+ if (window.cairn?.isCairn) {
130
+ finish(window.cairn);
131
+ return;
132
+ }
133
+ window.dispatchEvent(new CustomEvent("csd:requestProvider"));
134
+ onInit();
135
+ });
136
+ }
137
+ function unwrap(reply) {
138
+ if (reply && reply.ok) return reply.result;
139
+ throw mapProviderError(reply?.error ?? "Unknown wallet error");
140
+ }
141
+ var WalletConnection = class {
142
+ provider;
143
+ _addr = null;
144
+ constructor(provider) {
145
+ this.provider = provider;
146
+ }
147
+ /** The wallet's version string (e.g. "0.2.x"). */
148
+ get version() {
149
+ return this.provider.version;
150
+ }
151
+ /** The connected address, if `connect()`/`getAddress()` has resolved. */
152
+ get address() {
153
+ return this._addr;
154
+ }
155
+ /** Request connection. First time per origin prompts the user; afterwards may be silent. */
156
+ async connect() {
157
+ const { addr } = unwrap(await this.provider.connect());
158
+ this._addr = addr;
159
+ return addr;
160
+ }
161
+ /** Get the connected address (does not force a new connection prompt if already consented). */
162
+ async getAddress() {
163
+ const { addr } = unwrap(await this.provider.getAddress());
164
+ this._addr = addr;
165
+ return addr;
166
+ }
167
+ /**
168
+ * @deprecated First-party-only legacy login (it authenticates against the wallet's own configured
169
+ * server and is rejected from third-party origins). Use {@link signInWithCsd} for any site.
170
+ * Passwordless sign-in: a signature over a login nonce (always prompts; structurally cannot sign a tx).
171
+ */
172
+ signIn() {
173
+ return Promise.resolve(this.provider.signIn()).then(unwrap);
174
+ }
175
+ /**
176
+ * Audience-bound "Sign in with CSD" (SIWC) — the secure, replay-resistant third-party login.
177
+ * The wallet binds the REAL requesting origin + your single-use server `nonce` into the signed
178
+ * message and returns the artifact; it never mints a session. VERIFY the result SERVER-SIDE with
179
+ * `verifySiwc` from `@inversealtruism/csd-siwc` (domain/nonce/chain/time/signature/account), then
180
+ * issue your OWN session. The signature is proof-of-control, NOT a bearer token. Always prompts.
181
+ */
182
+ signInWithCsd(params) {
183
+ if (!params || typeof params.nonce !== "string" || !params.nonce) {
184
+ return Promise.reject(new UnsupportedMethodError("signInWithCsd requires a server-issued { nonce }"));
185
+ }
186
+ if (typeof this.provider.signInWithCsd !== "function") {
187
+ return Promise.reject(new UnsupportedMethodError("this wallet predates Sign-in-with-CSD \u2014 ask the user to update the Cairn Wallet"));
188
+ }
189
+ return Promise.resolve(this.provider.signInWithCsd(params)).then(unwrap);
190
+ }
191
+ /** True if this wallet supports audience-bound SIWC (safe to call `signInWithCsd`). */
192
+ get supportsSiwc() {
193
+ return typeof this.provider.signInWithCsd === "function";
194
+ }
195
+ /** Feature/capability detection. Returns null if the wallet predates `getCapabilities`. */
196
+ async getCapabilities() {
197
+ if (typeof this.provider.getCapabilities !== "function") return null;
198
+ try {
199
+ return await this.provider.getCapabilities();
200
+ } catch {
201
+ return null;
202
+ }
203
+ }
204
+ /** Atomic fill (CairnX DvP): pay + attest in ONE tx. Always prompts with clear-signing. */
205
+ fillOffer(params) {
206
+ return Promise.resolve(this.provider.fillOffer(params)).then(unwrap);
207
+ }
208
+ /** This origin's current permission grant (EIP-2255-style). Silent; [] if none / unsupported. */
209
+ async getPermissions() {
210
+ if (typeof this.provider.getPermissions !== "function") return [];
211
+ return unwrap(await this.provider.getPermissions());
212
+ }
213
+ /** Explicitly request permission to see the address (prompts, like connect). */
214
+ requestPermissions() {
215
+ if (typeof this.provider.requestPermissions !== "function") {
216
+ return Promise.reject(new UnsupportedMethodError("this wallet predates requestPermissions \u2014 use connect()"));
217
+ }
218
+ return Promise.resolve(this.provider.requestPermissions()).then(unwrap);
219
+ }
220
+ /** Revoke THIS origin's own access (silent). Returns { revoked }. Safe no-op on older wallets. */
221
+ async revokePermissions() {
222
+ if (typeof this.provider.revokePermissions !== "function") return { revoked: false };
223
+ return unwrap(await this.provider.revokePermissions());
224
+ }
225
+ /**
226
+ * Subscribe to provider events. `accountsChanged` fires with `[]` when this site loses access
227
+ * (wallet lock / account switch / revoke) — re-call connect() to (re)share; `disconnect` likewise.
228
+ * No-op if the wallet predates events. Use the SAME handler reference with off() to unsubscribe.
229
+ */
230
+ on(event, handler) {
231
+ this.provider.on?.(event, handler);
232
+ }
233
+ /** Remove a previously-added event handler (must be the same reference passed to on()). */
234
+ off(event, handler) {
235
+ this.provider.removeListener?.(event, handler);
236
+ }
237
+ /** Send CSD (always prompts with clear-signing; wallet picks inputs + returns change to itself). */
238
+ send(params) {
239
+ return Promise.resolve(this.provider.send(params)).then(unwrap);
240
+ }
241
+ /** Low-level Propose (always prompts). Prefer `cairn.board.propose()` which computes the hash/uri/expiry. */
242
+ propose(params) {
243
+ return Promise.resolve(this.provider.propose(params)).then(unwrap);
244
+ }
245
+ /** Attest/support a proposal (always prompts). */
246
+ attest(params) {
247
+ return Promise.resolve(this.provider.attest(params)).then(unwrap);
248
+ }
249
+ /** Seal a commit-reveal claim (always prompts; salt stays inside the wallet). */
250
+ sealClaim(params) {
251
+ return Promise.resolve(this.provider.sealClaim(params)).then(unwrap);
252
+ }
253
+ /** Reveal a previously sealed claim by its sealing txid (always prompts). */
254
+ revealClaim(txid) {
255
+ if (typeof txid !== "string" || !txid) {
256
+ return Promise.reject(new UnsupportedMethodError("revealClaim requires the sealing txid"));
257
+ }
258
+ return Promise.resolve(this.provider.revealClaim(txid)).then(unwrap);
259
+ }
260
+ };
261
+ async function getWallet(opts = {}) {
262
+ return new WalletConnection(await detectProvider(opts));
263
+ }
264
+
265
+ // src/controller.ts
266
+ var DISCONNECTED = Object.freeze({ status: "disconnected", account: null, error: null });
267
+ var CairnController = class {
268
+ state = DISCONNECTED;
269
+ conn = null;
270
+ listeners = /* @__PURE__ */ new Set();
271
+ getWalletFn;
272
+ detectOpts;
273
+ constructor(opts = {}) {
274
+ const { getWallet: gw, ...detect } = opts;
275
+ this.getWalletFn = gw ?? getWallet;
276
+ this.detectOpts = detect;
277
+ }
278
+ /** useSyncExternalStore-compatible. Returns an unsubscribe fn. */
279
+ subscribe = (cb) => {
280
+ this.listeners.add(cb);
281
+ return () => {
282
+ this.listeners.delete(cb);
283
+ };
284
+ };
285
+ /** useSyncExternalStore-compatible snapshot — stable reference until the state actually changes. */
286
+ getSnapshot = () => this.state;
287
+ /** The underlying WalletConnection (for advanced use: send/propose/permissions/…). Null until connect(). */
288
+ get connection() {
289
+ return this.conn;
290
+ }
291
+ setState(patch) {
292
+ const next = { ...this.state, ...patch };
293
+ if (next.status === this.state.status && next.account === this.state.account && next.error === this.state.error) return;
294
+ this.state = Object.freeze(next);
295
+ for (const l of [...this.listeners]) l();
296
+ }
297
+ onAccounts = (accounts) => {
298
+ if (!Array.isArray(accounts) || accounts.length === 0) this.setState({ status: "disconnected", account: null });
299
+ else this.setState({ status: "connected", account: String(accounts[0]), error: null });
300
+ };
301
+ onDisconnect = () => {
302
+ this.setState({ status: "disconnected", account: null });
303
+ };
304
+ /** Detect + connect (prompts the user the first time per origin). Resolves the connected address. */
305
+ connect = async () => {
306
+ this.setState({ status: "connecting", error: null });
307
+ try {
308
+ if (!this.conn) {
309
+ this.conn = await this.getWalletFn(this.detectOpts);
310
+ this.conn.on("accountsChanged", this.onAccounts);
311
+ this.conn.on("disconnect", this.onDisconnect);
312
+ }
313
+ const addr = await this.conn.connect();
314
+ this.setState({ status: "connected", account: addr, error: null });
315
+ return addr;
316
+ } catch (e) {
317
+ this.setState({ status: "disconnected", account: null, error: e?.message ?? String(e) });
318
+ throw e;
319
+ }
320
+ };
321
+ /** Forget the connection locally AND revoke this origin's wallet-side permission (best-effort). */
322
+ disconnect = async () => {
323
+ try {
324
+ await this.conn?.revokePermissions();
325
+ } catch {
326
+ }
327
+ this.setState({ status: "disconnected", account: null, error: null });
328
+ };
329
+ /** Audience-bound sign-in (must connect() first). Returns the signed artifact to verify server-side. */
330
+ signInWithCsd = (params) => {
331
+ if (!this.conn) return Promise.reject(new Error("call connect() before signInWithCsd()"));
332
+ return this.conn.signInWithCsd(params);
333
+ };
334
+ };
335
+
336
+ // src/react.ts
337
+ function createCairnHooks(React, controllerOrOpts) {
338
+ const controller = controllerOrOpts instanceof CairnController ? controllerOrOpts : new CairnController(controllerOrOpts);
339
+ const useCairnState = () => React.useSyncExternalStore(controller.subscribe, controller.getSnapshot, controller.getSnapshot);
340
+ const useCairnAccount = () => useCairnState().account;
341
+ const useCairn = () => ({
342
+ ...useCairnState(),
343
+ connect: controller.connect,
344
+ disconnect: controller.disconnect,
345
+ signInWithCsd: controller.signInWithCsd
346
+ });
347
+ return { controller, useCairnState, useCairnAccount, useCairn };
348
+ }
349
+ // Annotate the CommonJS export names for ESM import in node:
350
+ 0 && (module.exports = {
351
+ CairnController,
352
+ createCairnHooks
353
+ });
@@ -0,0 +1,30 @@
1
+ import { CairnController, CairnState, CairnControllerOptions } from './controller.cjs';
2
+ import { SiwcParams, SiwcResult } from './connect.cjs';
3
+
4
+ /** The minimal slice of React this adapter uses (so it needs no react dependency / @types/react). */
5
+ interface ReactLike {
6
+ useSyncExternalStore<T>(subscribe: (cb: () => void) => () => void, getSnapshot: () => T, getServerSnapshot?: () => T): T;
7
+ }
8
+ /** Reactive state + bound actions returned by useCairn(). */
9
+ type UseCairnResult = CairnState & {
10
+ connect: () => Promise<string>;
11
+ disconnect: () => Promise<void>;
12
+ signInWithCsd: (params: SiwcParams) => Promise<SiwcResult>;
13
+ };
14
+ interface CairnHooks {
15
+ /** The bound controller (for advanced use outside hooks). */
16
+ controller: CairnController;
17
+ /** Reactive full state: { status, account, error }. */
18
+ useCairnState(): CairnState;
19
+ /** Reactive account (null when disconnected / locked). */
20
+ useCairnAccount(): string | null;
21
+ /** Reactive state + bound actions. */
22
+ useCairn(): UseCairnResult;
23
+ }
24
+ /**
25
+ * Build React hooks bound to a CairnController. Pass your app's `React` (or `{ useSyncExternalStore }`).
26
+ * Optionally pass an existing controller; otherwise one is created from `opts`.
27
+ */
28
+ declare function createCairnHooks(React: ReactLike, controllerOrOpts?: CairnController | CairnControllerOptions): CairnHooks;
29
+
30
+ export { CairnController, CairnControllerOptions, type CairnHooks, CairnState, type ReactLike, type UseCairnResult, createCairnHooks };
@@ -0,0 +1,30 @@
1
+ import { CairnController, CairnState, CairnControllerOptions } from './controller.js';
2
+ import { SiwcParams, SiwcResult } from './connect.js';
3
+
4
+ /** The minimal slice of React this adapter uses (so it needs no react dependency / @types/react). */
5
+ interface ReactLike {
6
+ useSyncExternalStore<T>(subscribe: (cb: () => void) => () => void, getSnapshot: () => T, getServerSnapshot?: () => T): T;
7
+ }
8
+ /** Reactive state + bound actions returned by useCairn(). */
9
+ type UseCairnResult = CairnState & {
10
+ connect: () => Promise<string>;
11
+ disconnect: () => Promise<void>;
12
+ signInWithCsd: (params: SiwcParams) => Promise<SiwcResult>;
13
+ };
14
+ interface CairnHooks {
15
+ /** The bound controller (for advanced use outside hooks). */
16
+ controller: CairnController;
17
+ /** Reactive full state: { status, account, error }. */
18
+ useCairnState(): CairnState;
19
+ /** Reactive account (null when disconnected / locked). */
20
+ useCairnAccount(): string | null;
21
+ /** Reactive state + bound actions. */
22
+ useCairn(): UseCairnResult;
23
+ }
24
+ /**
25
+ * Build React hooks bound to a CairnController. Pass your app's `React` (or `{ useSyncExternalStore }`).
26
+ * Optionally pass an existing controller; otherwise one is created from `opts`.
27
+ */
28
+ declare function createCairnHooks(React: ReactLike, controllerOrOpts?: CairnController | CairnControllerOptions): CairnHooks;
29
+
30
+ export { CairnController, CairnControllerOptions, type CairnHooks, CairnState, type ReactLike, type UseCairnResult, createCairnHooks };
package/dist/react.js ADDED
@@ -0,0 +1,23 @@
1
+ import {
2
+ CairnController
3
+ } from "./chunk-ZAE2BIH5.js";
4
+ import "./chunk-G4OZKZSJ.js";
5
+ import "./chunk-UMGWVOOT.js";
6
+
7
+ // src/react.ts
8
+ function createCairnHooks(React, controllerOrOpts) {
9
+ const controller = controllerOrOpts instanceof CairnController ? controllerOrOpts : new CairnController(controllerOrOpts);
10
+ const useCairnState = () => React.useSyncExternalStore(controller.subscribe, controller.getSnapshot, controller.getSnapshot);
11
+ const useCairnAccount = () => useCairnState().account;
12
+ const useCairn = () => ({
13
+ ...useCairnState(),
14
+ connect: controller.connect,
15
+ disconnect: controller.disconnect,
16
+ signInWithCsd: controller.signInWithCsd
17
+ });
18
+ return { controller, useCairnState, useCairnAccount, useCairn };
19
+ }
20
+ export {
21
+ CairnController,
22
+ createCairnHooks
23
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inversealtruism/cairn-sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
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",
@@ -41,6 +41,16 @@
41
41
  "types": "./dist/chain.d.ts",
42
42
  "import": "./dist/chain.js",
43
43
  "require": "./dist/chain.cjs"
44
+ },
45
+ "./controller": {
46
+ "types": "./dist/controller.d.ts",
47
+ "import": "./dist/controller.js",
48
+ "require": "./dist/controller.cjs"
49
+ },
50
+ "./react": {
51
+ "types": "./dist/react.d.ts",
52
+ "import": "./dist/react.js",
53
+ "require": "./dist/react.cjs"
44
54
  }
45
55
  },
46
56
  "files": [
@@ -48,25 +58,13 @@
48
58
  "LICENSE",
49
59
  "README.md"
50
60
  ],
51
- "scripts": {
52
- "build": "tsup src/index.ts src/connect.ts src/board.ts src/indexer.ts src/content.ts src/registry.ts src/chain.ts --format esm,cjs --dts --clean",
53
- "test": "tsx test/sdk.test.ts && tsx test/connect.test.ts",
54
- "test:live": "node examples/read-only.mjs",
55
- "build:example": "node scripts/build-example.mjs",
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"
62
- },
63
61
  "dependencies": {
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"
62
+ "@inversealtruism/csd-client": "0.1.13",
63
+ "@inversealtruism/csd-codec": "0.1.13",
64
+ "@inversealtruism/csd-crypto": "0.1.13",
65
+ "@inversealtruism/csd-light": "0.1.13",
66
+ "@inversealtruism/csd-registry": "0.1.13",
67
+ "@inversealtruism/csd-tx": "0.1.13"
70
68
  },
71
69
  "devDependencies": {
72
70
  "esbuild": "^0.27.0",
@@ -76,12 +74,6 @@
76
74
  "typescript": "^5.6.0"
77
75
  },
78
76
  "sideEffects": false,
79
- "packageManager": "pnpm@10.32.1",
80
- "pnpm": {
81
- "onlyBuiltDependencies": [
82
- "esbuild"
83
- ]
84
- },
85
77
  "license": "MIT",
86
78
  "publishConfig": {
87
79
  "access": "public"
@@ -99,5 +91,17 @@
99
91
  "dapp",
100
92
  "sdk",
101
93
  "blockchain"
102
- ]
103
- }
94
+ ],
95
+ "scripts": {
96
+ "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",
97
+ "test": "tsx test/sdk.test.ts && tsx test/connect.test.ts && tsx test/errors.test.ts && tsx test/controller.test.ts && tsx test/react.test.ts",
98
+ "test:live": "node examples/read-only.mjs",
99
+ "build:example": "node scripts/build-example.mjs",
100
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
101
+ "test:e2e:read": "node test/e2e/e2e-read.mjs",
102
+ "test:e2e:wallet": "xvfb-run -a node test/e2e/e2e-wallet-connect.mjs",
103
+ "test:e2e:write": "node test/e2e/e2e-write.mjs",
104
+ "test:e2e": "node test/e2e/e2e-read.mjs && xvfb-run -a node test/e2e/e2e-wallet-connect.mjs",
105
+ "test:all": "pnpm test && pnpm test:e2e"
106
+ }
107
+ }
@@ -1,63 +0,0 @@
1
- // src/errors.ts
2
- var CairnError = class extends Error {
3
- constructor(message) {
4
- super(message);
5
- this.name = new.target.name;
6
- }
7
- };
8
- var NotInstalledError = class extends CairnError {
9
- constructor(message = "Cairn Wallet not detected. Install it from cairn-substrate.com.") {
10
- super(message);
11
- }
12
- };
13
- var UserRejectedError = class extends CairnError {
14
- constructor(message = "Request rejected by user.") {
15
- super(message);
16
- }
17
- };
18
- var WalletLockedError = class extends CairnError {
19
- constructor(message = "Wallet is locked.") {
20
- super(message);
21
- }
22
- };
23
- var UnsupportedMethodError = class extends CairnError {
24
- constructor(message = "Method not supported by the wallet.") {
25
- super(message);
26
- }
27
- };
28
- var HttpError = class extends CairnError {
29
- status;
30
- url;
31
- body;
32
- constructor(status, url, body) {
33
- super(`HTTP ${status} for ${url}${body ? `: ${String(body).slice(0, 200)}` : ""}`);
34
- this.status = status;
35
- this.url = url;
36
- this.body = body;
37
- }
38
- };
39
- var ContentVerificationError = class extends CairnError {
40
- expected;
41
- constructor(expected) {
42
- super(`Content does not match its payload hash ${expected} \u2014 bytes were tampered with in transit.`);
43
- this.expected = expected;
44
- }
45
- };
46
- function mapProviderError(error) {
47
- const e = String(error || "").toLowerCase();
48
- if (e.includes("rejected by user")) return new UserRejectedError(error);
49
- if (e.includes("wallet locked")) return new WalletLockedError(error);
50
- if (e.includes("unsupported dapp method")) return new UnsupportedMethodError(error);
51
- return new CairnError(error || "Unknown wallet error");
52
- }
53
-
54
- export {
55
- CairnError,
56
- NotInstalledError,
57
- UserRejectedError,
58
- WalletLockedError,
59
- UnsupportedMethodError,
60
- HttpError,
61
- ContentVerificationError,
62
- mapProviderError
63
- };