@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/board.cjs
CHANGED
|
@@ -27,7 +27,7 @@ var import_csd_codec = require("@inversealtruism/csd-codec");
|
|
|
27
27
|
var import_csd_codec2 = require("@inversealtruism/csd-codec");
|
|
28
28
|
|
|
29
29
|
// src/errors.ts
|
|
30
|
-
var SDK_VERSION = "0.
|
|
30
|
+
var SDK_VERSION = "0.4.0";
|
|
31
31
|
var DOCS_BASE = "https://cairn-substrate.com/docs/sdk";
|
|
32
32
|
var CairnError = class extends Error {
|
|
33
33
|
/** Stable machine code for programmatic branching. */
|
package/dist/board.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/errors.ts
|
|
2
|
-
var SDK_VERSION = "0.
|
|
2
|
+
var SDK_VERSION = "0.4.0";
|
|
3
3
|
var DOCS_BASE = "https://cairn-substrate.com/docs/sdk";
|
|
4
4
|
var CairnError = class extends Error {
|
|
5
5
|
/** Stable machine code for programmatic branching. */
|
|
@@ -91,7 +91,7 @@ var SubmitInFlightError = class extends CairnError {
|
|
|
91
91
|
this.txid = txid;
|
|
92
92
|
}
|
|
93
93
|
};
|
|
94
|
-
var NATIVE_CODES = /* @__PURE__ */ new Set(["
|
|
94
|
+
var NATIVE_CODES = /* @__PURE__ */ new Set(["FIRST_PARTY_ONLY", "RATE_LIMITED", "FORBIDDEN", "INTERNAL"]);
|
|
95
95
|
var NESTED_TRANSIENT = /* @__PURE__ */ new Set(["VERIFY_UNAVAILABLE", "OFFER_UNKNOWN"]);
|
|
96
96
|
var NESTED_TERMINAL = /* @__PURE__ */ new Set([
|
|
97
97
|
"FILL_UNSAFE",
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CairnError,
|
|
2
3
|
NotInstalledError,
|
|
3
4
|
UnsupportedMethodError,
|
|
4
5
|
mapProviderError,
|
|
5
6
|
mapSubmitResultError
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-MREZG2HN.js";
|
|
7
8
|
|
|
8
9
|
// src/connect.ts
|
|
10
|
+
var DEFAULT_PROVIDER_TIMEOUT_MS = 10 * 6e4;
|
|
9
11
|
function discoverProviders(opts = {}) {
|
|
10
12
|
const timeoutMs = opts.timeoutMs ?? 1e3;
|
|
11
13
|
return new Promise((resolve) => {
|
|
@@ -85,8 +87,24 @@ function unwrapWrite(reply) {
|
|
|
85
87
|
var WalletConnection = class {
|
|
86
88
|
provider;
|
|
87
89
|
_addr = null;
|
|
88
|
-
|
|
90
|
+
/** B7c: per-call provider timeout (ms). GENEROUS by default so it never rejects an in-flight human
|
|
91
|
+
* approval; 0 disables it. Every provider call (writes especially) races against it. */
|
|
92
|
+
_timeoutMs;
|
|
93
|
+
constructor(provider, opts = {}) {
|
|
89
94
|
this.provider = provider;
|
|
95
|
+
this._timeoutMs = opts.timeoutMs ?? DEFAULT_PROVIDER_TIMEOUT_MS;
|
|
96
|
+
}
|
|
97
|
+
// B7c: race a provider call against the per-call timeout. On timeout, throw a fail-closed CairnError
|
|
98
|
+
// (retryable:false: a write may already have reached the wallet, so never invite a blind auto-retry). The
|
|
99
|
+
// genuine wallet resolves quickly once the user acts; this only fires on a truly hung/absent response.
|
|
100
|
+
call(op, label) {
|
|
101
|
+
const ms = this._timeoutMs;
|
|
102
|
+
if (!Number.isFinite(ms) || ms <= 0) return Promise.resolve(op());
|
|
103
|
+
let timer;
|
|
104
|
+
const timeout = new Promise((_, reject) => {
|
|
105
|
+
timer = setTimeout(() => reject(new CairnError(`the wallet did not respond to ${label} within ${ms}ms`, { retryable: false })), ms);
|
|
106
|
+
});
|
|
107
|
+
return Promise.race([Promise.resolve(op()), timeout]).finally(() => clearTimeout(timer));
|
|
90
108
|
}
|
|
91
109
|
/** The wallet's version string (e.g. "0.2.x"). */
|
|
92
110
|
get version() {
|
|
@@ -98,13 +116,13 @@ var WalletConnection = class {
|
|
|
98
116
|
}
|
|
99
117
|
/** Request connection. First time per origin prompts the user; afterwards may be silent. */
|
|
100
118
|
async connect() {
|
|
101
|
-
const { addr } = unwrap(await this.provider.connect());
|
|
119
|
+
const { addr } = unwrap(await this.call(() => this.provider.connect(), "connect"));
|
|
102
120
|
this._addr = addr;
|
|
103
121
|
return addr;
|
|
104
122
|
}
|
|
105
123
|
/** Get the connected address (does not force a new connection prompt if already consented). */
|
|
106
124
|
async getAddress() {
|
|
107
|
-
const { addr } = unwrap(await this.provider.getAddress());
|
|
125
|
+
const { addr } = unwrap(await this.call(() => this.provider.getAddress(), "getAddress"));
|
|
108
126
|
this._addr = addr;
|
|
109
127
|
return addr;
|
|
110
128
|
}
|
|
@@ -117,7 +135,7 @@ var WalletConnection = class {
|
|
|
117
135
|
if (typeof this.provider.signIn !== "function") {
|
|
118
136
|
return Promise.reject(new UnsupportedMethodError("this wallet does not expose signIn()"));
|
|
119
137
|
}
|
|
120
|
-
return
|
|
138
|
+
return this.call(() => this.provider.signIn(), "signIn").then(unwrap);
|
|
121
139
|
}
|
|
122
140
|
/**
|
|
123
141
|
* Audience-bound "Sign in with CSD" (SIWC) — the secure, replay-resistant third-party login.
|
|
@@ -133,7 +151,7 @@ var WalletConnection = class {
|
|
|
133
151
|
if (typeof this.provider.signInWithCsd !== "function") {
|
|
134
152
|
return Promise.reject(new UnsupportedMethodError("this wallet predates Sign-in-with-CSD \u2014 ask the user to update the Cairn Wallet"));
|
|
135
153
|
}
|
|
136
|
-
return
|
|
154
|
+
return this.call(() => this.provider.signInWithCsd(params), "signInWithCsd").then(unwrap);
|
|
137
155
|
}
|
|
138
156
|
/** True if this wallet supports audience-bound SIWC (safe to call `signInWithCsd`). */
|
|
139
157
|
get supportsSiwc() {
|
|
@@ -143,7 +161,7 @@ var WalletConnection = class {
|
|
|
143
161
|
async getCapabilities() {
|
|
144
162
|
if (typeof this.provider.getCapabilities !== "function") return null;
|
|
145
163
|
try {
|
|
146
|
-
return await this.provider.getCapabilities();
|
|
164
|
+
return await this.call(() => this.provider.getCapabilities(), "getCapabilities");
|
|
147
165
|
} catch {
|
|
148
166
|
return null;
|
|
149
167
|
}
|
|
@@ -159,24 +177,24 @@ var WalletConnection = class {
|
|
|
159
177
|
if (typeof this.provider.fillOffer !== "function") {
|
|
160
178
|
return Promise.reject(new UnsupportedMethodError("this wallet predates fillOffer() \u2014 ask the user to update the Cairn Wallet"));
|
|
161
179
|
}
|
|
162
|
-
return
|
|
180
|
+
return this.call(() => this.provider.fillOffer(params), "fillOffer").then(unwrapWrite);
|
|
163
181
|
}
|
|
164
182
|
/** This origin's current permission grant (EIP-2255-style). Silent; [] if none / unsupported. */
|
|
165
183
|
async getPermissions() {
|
|
166
184
|
if (typeof this.provider.getPermissions !== "function") return [];
|
|
167
|
-
return unwrap(await this.provider.getPermissions());
|
|
185
|
+
return unwrap(await this.call(() => this.provider.getPermissions(), "getPermissions"));
|
|
168
186
|
}
|
|
169
187
|
/** Explicitly request permission to see the address (prompts, like connect). */
|
|
170
188
|
requestPermissions() {
|
|
171
189
|
if (typeof this.provider.requestPermissions !== "function") {
|
|
172
190
|
return Promise.reject(new UnsupportedMethodError("this wallet predates requestPermissions \u2014 use connect()"));
|
|
173
191
|
}
|
|
174
|
-
return
|
|
192
|
+
return this.call(() => this.provider.requestPermissions(), "requestPermissions").then(unwrap);
|
|
175
193
|
}
|
|
176
194
|
/** Revoke THIS origin's own access (silent). Returns { revoked }. Safe no-op on older wallets. */
|
|
177
195
|
async revokePermissions() {
|
|
178
196
|
if (typeof this.provider.revokePermissions !== "function") return { revoked: false };
|
|
179
|
-
return unwrap(await this.provider.revokePermissions());
|
|
197
|
+
return unwrap(await this.call(() => this.provider.revokePermissions(), "revokePermissions"));
|
|
180
198
|
}
|
|
181
199
|
/**
|
|
182
200
|
* Subscribe to provider events. `accountsChanged` fires with `[]` when this site loses access
|
|
@@ -192,26 +210,26 @@ var WalletConnection = class {
|
|
|
192
210
|
}
|
|
193
211
|
/** Send CSD (always prompts with clear-signing; wallet picks inputs + returns change to itself). */
|
|
194
212
|
send(params) {
|
|
195
|
-
return
|
|
213
|
+
return this.call(() => this.provider.send(params), "send").then(unwrapWrite);
|
|
196
214
|
}
|
|
197
215
|
/** Low-level Propose (always prompts). Prefer `cairn.board.propose()` which computes the hash/uri/expiry. */
|
|
198
216
|
propose(params) {
|
|
199
|
-
return
|
|
217
|
+
return this.call(() => this.provider.propose(params), "propose").then(unwrapWrite);
|
|
200
218
|
}
|
|
201
219
|
/** Attest/support a proposal (always prompts). */
|
|
202
220
|
attest(params) {
|
|
203
|
-
return
|
|
221
|
+
return this.call(() => this.provider.attest(params), "attest").then(unwrapWrite);
|
|
204
222
|
}
|
|
205
223
|
/** Seal a commit-reveal claim (always prompts; salt stays inside the wallet). */
|
|
206
224
|
sealClaim(params) {
|
|
207
|
-
return
|
|
225
|
+
return this.call(() => this.provider.sealClaim(params), "sealClaim").then(unwrapWrite);
|
|
208
226
|
}
|
|
209
227
|
/** Reveal a previously sealed claim by its sealing txid (always prompts). */
|
|
210
228
|
revealClaim(txid) {
|
|
211
229
|
if (typeof txid !== "string" || !txid) {
|
|
212
230
|
return Promise.reject(new UnsupportedMethodError("revealClaim requires the sealing txid"));
|
|
213
231
|
}
|
|
214
|
-
return
|
|
232
|
+
return this.call(() => this.provider.revealClaim(txid), "revealClaim").then(unwrapWrite);
|
|
215
233
|
}
|
|
216
234
|
};
|
|
217
235
|
async function getWallet(opts = {}) {
|
package/dist/connect.cjs
CHANGED
|
@@ -30,7 +30,7 @@ __export(connect_exports, {
|
|
|
30
30
|
module.exports = __toCommonJS(connect_exports);
|
|
31
31
|
|
|
32
32
|
// src/errors.ts
|
|
33
|
-
var SDK_VERSION = "0.
|
|
33
|
+
var SDK_VERSION = "0.4.0";
|
|
34
34
|
var DOCS_BASE = "https://cairn-substrate.com/docs/sdk";
|
|
35
35
|
var CairnError = class extends Error {
|
|
36
36
|
/** Stable machine code for programmatic branching. */
|
|
@@ -104,7 +104,7 @@ var SubmitInFlightError = class extends CairnError {
|
|
|
104
104
|
this.txid = txid;
|
|
105
105
|
}
|
|
106
106
|
};
|
|
107
|
-
var NATIVE_CODES = /* @__PURE__ */ new Set(["
|
|
107
|
+
var NATIVE_CODES = /* @__PURE__ */ new Set(["FIRST_PARTY_ONLY", "RATE_LIMITED", "FORBIDDEN", "INTERNAL"]);
|
|
108
108
|
var NESTED_TRANSIENT = /* @__PURE__ */ new Set(["VERIFY_UNAVAILABLE", "OFFER_UNKNOWN"]);
|
|
109
109
|
var NESTED_TERMINAL = /* @__PURE__ */ new Set([
|
|
110
110
|
"FILL_UNSAFE",
|
|
@@ -148,6 +148,7 @@ function mapSubmitResultError(result) {
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
// src/connect.ts
|
|
151
|
+
var DEFAULT_PROVIDER_TIMEOUT_MS = 10 * 6e4;
|
|
151
152
|
function discoverProviders(opts = {}) {
|
|
152
153
|
const timeoutMs = opts.timeoutMs ?? 1e3;
|
|
153
154
|
return new Promise((resolve) => {
|
|
@@ -227,8 +228,24 @@ function unwrapWrite(reply) {
|
|
|
227
228
|
var WalletConnection = class {
|
|
228
229
|
provider;
|
|
229
230
|
_addr = null;
|
|
230
|
-
|
|
231
|
+
/** B7c: per-call provider timeout (ms). GENEROUS by default so it never rejects an in-flight human
|
|
232
|
+
* approval; 0 disables it. Every provider call (writes especially) races against it. */
|
|
233
|
+
_timeoutMs;
|
|
234
|
+
constructor(provider, opts = {}) {
|
|
231
235
|
this.provider = provider;
|
|
236
|
+
this._timeoutMs = opts.timeoutMs ?? DEFAULT_PROVIDER_TIMEOUT_MS;
|
|
237
|
+
}
|
|
238
|
+
// B7c: race a provider call against the per-call timeout. On timeout, throw a fail-closed CairnError
|
|
239
|
+
// (retryable:false: a write may already have reached the wallet, so never invite a blind auto-retry). The
|
|
240
|
+
// genuine wallet resolves quickly once the user acts; this only fires on a truly hung/absent response.
|
|
241
|
+
call(op, label) {
|
|
242
|
+
const ms = this._timeoutMs;
|
|
243
|
+
if (!Number.isFinite(ms) || ms <= 0) return Promise.resolve(op());
|
|
244
|
+
let timer;
|
|
245
|
+
const timeout = new Promise((_, reject) => {
|
|
246
|
+
timer = setTimeout(() => reject(new CairnError(`the wallet did not respond to ${label} within ${ms}ms`, { retryable: false })), ms);
|
|
247
|
+
});
|
|
248
|
+
return Promise.race([Promise.resolve(op()), timeout]).finally(() => clearTimeout(timer));
|
|
232
249
|
}
|
|
233
250
|
/** The wallet's version string (e.g. "0.2.x"). */
|
|
234
251
|
get version() {
|
|
@@ -240,13 +257,13 @@ var WalletConnection = class {
|
|
|
240
257
|
}
|
|
241
258
|
/** Request connection. First time per origin prompts the user; afterwards may be silent. */
|
|
242
259
|
async connect() {
|
|
243
|
-
const { addr } = unwrap(await this.provider.connect());
|
|
260
|
+
const { addr } = unwrap(await this.call(() => this.provider.connect(), "connect"));
|
|
244
261
|
this._addr = addr;
|
|
245
262
|
return addr;
|
|
246
263
|
}
|
|
247
264
|
/** Get the connected address (does not force a new connection prompt if already consented). */
|
|
248
265
|
async getAddress() {
|
|
249
|
-
const { addr } = unwrap(await this.provider.getAddress());
|
|
266
|
+
const { addr } = unwrap(await this.call(() => this.provider.getAddress(), "getAddress"));
|
|
250
267
|
this._addr = addr;
|
|
251
268
|
return addr;
|
|
252
269
|
}
|
|
@@ -259,7 +276,7 @@ var WalletConnection = class {
|
|
|
259
276
|
if (typeof this.provider.signIn !== "function") {
|
|
260
277
|
return Promise.reject(new UnsupportedMethodError("this wallet does not expose signIn()"));
|
|
261
278
|
}
|
|
262
|
-
return
|
|
279
|
+
return this.call(() => this.provider.signIn(), "signIn").then(unwrap);
|
|
263
280
|
}
|
|
264
281
|
/**
|
|
265
282
|
* Audience-bound "Sign in with CSD" (SIWC) — the secure, replay-resistant third-party login.
|
|
@@ -275,7 +292,7 @@ var WalletConnection = class {
|
|
|
275
292
|
if (typeof this.provider.signInWithCsd !== "function") {
|
|
276
293
|
return Promise.reject(new UnsupportedMethodError("this wallet predates Sign-in-with-CSD \u2014 ask the user to update the Cairn Wallet"));
|
|
277
294
|
}
|
|
278
|
-
return
|
|
295
|
+
return this.call(() => this.provider.signInWithCsd(params), "signInWithCsd").then(unwrap);
|
|
279
296
|
}
|
|
280
297
|
/** True if this wallet supports audience-bound SIWC (safe to call `signInWithCsd`). */
|
|
281
298
|
get supportsSiwc() {
|
|
@@ -285,7 +302,7 @@ var WalletConnection = class {
|
|
|
285
302
|
async getCapabilities() {
|
|
286
303
|
if (typeof this.provider.getCapabilities !== "function") return null;
|
|
287
304
|
try {
|
|
288
|
-
return await this.provider.getCapabilities();
|
|
305
|
+
return await this.call(() => this.provider.getCapabilities(), "getCapabilities");
|
|
289
306
|
} catch {
|
|
290
307
|
return null;
|
|
291
308
|
}
|
|
@@ -301,24 +318,24 @@ var WalletConnection = class {
|
|
|
301
318
|
if (typeof this.provider.fillOffer !== "function") {
|
|
302
319
|
return Promise.reject(new UnsupportedMethodError("this wallet predates fillOffer() \u2014 ask the user to update the Cairn Wallet"));
|
|
303
320
|
}
|
|
304
|
-
return
|
|
321
|
+
return this.call(() => this.provider.fillOffer(params), "fillOffer").then(unwrapWrite);
|
|
305
322
|
}
|
|
306
323
|
/** This origin's current permission grant (EIP-2255-style). Silent; [] if none / unsupported. */
|
|
307
324
|
async getPermissions() {
|
|
308
325
|
if (typeof this.provider.getPermissions !== "function") return [];
|
|
309
|
-
return unwrap(await this.provider.getPermissions());
|
|
326
|
+
return unwrap(await this.call(() => this.provider.getPermissions(), "getPermissions"));
|
|
310
327
|
}
|
|
311
328
|
/** Explicitly request permission to see the address (prompts, like connect). */
|
|
312
329
|
requestPermissions() {
|
|
313
330
|
if (typeof this.provider.requestPermissions !== "function") {
|
|
314
331
|
return Promise.reject(new UnsupportedMethodError("this wallet predates requestPermissions \u2014 use connect()"));
|
|
315
332
|
}
|
|
316
|
-
return
|
|
333
|
+
return this.call(() => this.provider.requestPermissions(), "requestPermissions").then(unwrap);
|
|
317
334
|
}
|
|
318
335
|
/** Revoke THIS origin's own access (silent). Returns { revoked }. Safe no-op on older wallets. */
|
|
319
336
|
async revokePermissions() {
|
|
320
337
|
if (typeof this.provider.revokePermissions !== "function") return { revoked: false };
|
|
321
|
-
return unwrap(await this.provider.revokePermissions());
|
|
338
|
+
return unwrap(await this.call(() => this.provider.revokePermissions(), "revokePermissions"));
|
|
322
339
|
}
|
|
323
340
|
/**
|
|
324
341
|
* Subscribe to provider events. `accountsChanged` fires with `[]` when this site loses access
|
|
@@ -334,26 +351,26 @@ var WalletConnection = class {
|
|
|
334
351
|
}
|
|
335
352
|
/** Send CSD (always prompts with clear-signing; wallet picks inputs + returns change to itself). */
|
|
336
353
|
send(params) {
|
|
337
|
-
return
|
|
354
|
+
return this.call(() => this.provider.send(params), "send").then(unwrapWrite);
|
|
338
355
|
}
|
|
339
356
|
/** Low-level Propose (always prompts). Prefer `cairn.board.propose()` which computes the hash/uri/expiry. */
|
|
340
357
|
propose(params) {
|
|
341
|
-
return
|
|
358
|
+
return this.call(() => this.provider.propose(params), "propose").then(unwrapWrite);
|
|
342
359
|
}
|
|
343
360
|
/** Attest/support a proposal (always prompts). */
|
|
344
361
|
attest(params) {
|
|
345
|
-
return
|
|
362
|
+
return this.call(() => this.provider.attest(params), "attest").then(unwrapWrite);
|
|
346
363
|
}
|
|
347
364
|
/** Seal a commit-reveal claim (always prompts; salt stays inside the wallet). */
|
|
348
365
|
sealClaim(params) {
|
|
349
|
-
return
|
|
366
|
+
return this.call(() => this.provider.sealClaim(params), "sealClaim").then(unwrapWrite);
|
|
350
367
|
}
|
|
351
368
|
/** Reveal a previously sealed claim by its sealing txid (always prompts). */
|
|
352
369
|
revealClaim(txid) {
|
|
353
370
|
if (typeof txid !== "string" || !txid) {
|
|
354
371
|
return Promise.reject(new UnsupportedMethodError("revealClaim requires the sealing txid"));
|
|
355
372
|
}
|
|
356
|
-
return
|
|
373
|
+
return this.call(() => this.provider.revealClaim(txid), "revealClaim").then(unwrapWrite);
|
|
357
374
|
}
|
|
358
375
|
};
|
|
359
376
|
async function getWallet(opts = {}) {
|
package/dist/connect.d.cts
CHANGED
|
@@ -208,7 +208,13 @@ declare function isInstalled(): boolean;
|
|
|
208
208
|
declare class WalletConnection {
|
|
209
209
|
readonly provider: CairnProvider;
|
|
210
210
|
private _addr;
|
|
211
|
-
|
|
211
|
+
/** B7c: per-call provider timeout (ms). GENEROUS by default so it never rejects an in-flight human
|
|
212
|
+
* approval; 0 disables it. Every provider call (writes especially) races against it. */
|
|
213
|
+
private readonly _timeoutMs;
|
|
214
|
+
constructor(provider: CairnProvider, opts?: {
|
|
215
|
+
timeoutMs?: number;
|
|
216
|
+
});
|
|
217
|
+
private call;
|
|
212
218
|
/** The wallet's version string (e.g. "0.2.x"). */
|
|
213
219
|
get version(): string;
|
|
214
220
|
/** The connected address, if `connect()`/`getAddress()` has resolved. */
|
package/dist/connect.d.ts
CHANGED
|
@@ -208,7 +208,13 @@ declare function isInstalled(): boolean;
|
|
|
208
208
|
declare class WalletConnection {
|
|
209
209
|
readonly provider: CairnProvider;
|
|
210
210
|
private _addr;
|
|
211
|
-
|
|
211
|
+
/** B7c: per-call provider timeout (ms). GENEROUS by default so it never rejects an in-flight human
|
|
212
|
+
* approval; 0 disables it. Every provider call (writes especially) races against it. */
|
|
213
|
+
private readonly _timeoutMs;
|
|
214
|
+
constructor(provider: CairnProvider, opts?: {
|
|
215
|
+
timeoutMs?: number;
|
|
216
|
+
});
|
|
217
|
+
private call;
|
|
212
218
|
/** The wallet's version string (e.g. "0.2.x"). */
|
|
213
219
|
get version(): string;
|
|
214
220
|
/** The connected address, if `connect()`/`getAddress()` has resolved. */
|
package/dist/connect.js
CHANGED
package/dist/content.cjs
CHANGED
|
@@ -26,7 +26,7 @@ module.exports = __toCommonJS(content_exports);
|
|
|
26
26
|
var import_csd_codec = require("@inversealtruism/csd-codec");
|
|
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. */
|
package/dist/content.js
CHANGED
package/dist/controller.cjs
CHANGED
|
@@ -25,7 +25,7 @@ __export(controller_exports, {
|
|
|
25
25
|
module.exports = __toCommonJS(controller_exports);
|
|
26
26
|
|
|
27
27
|
// src/errors.ts
|
|
28
|
-
var SDK_VERSION = "0.
|
|
28
|
+
var SDK_VERSION = "0.4.0";
|
|
29
29
|
var DOCS_BASE = "https://cairn-substrate.com/docs/sdk";
|
|
30
30
|
var CairnError = class extends Error {
|
|
31
31
|
/** Stable machine code for programmatic branching. */
|
|
@@ -99,7 +99,7 @@ var SubmitInFlightError = class extends CairnError {
|
|
|
99
99
|
this.txid = txid;
|
|
100
100
|
}
|
|
101
101
|
};
|
|
102
|
-
var NATIVE_CODES = /* @__PURE__ */ new Set(["
|
|
102
|
+
var NATIVE_CODES = /* @__PURE__ */ new Set(["FIRST_PARTY_ONLY", "RATE_LIMITED", "FORBIDDEN", "INTERNAL"]);
|
|
103
103
|
var NESTED_TRANSIENT = /* @__PURE__ */ new Set(["VERIFY_UNAVAILABLE", "OFFER_UNKNOWN"]);
|
|
104
104
|
var NESTED_TERMINAL = /* @__PURE__ */ new Set([
|
|
105
105
|
"FILL_UNSAFE",
|
|
@@ -143,6 +143,7 @@ function mapSubmitResultError(result) {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
// src/connect.ts
|
|
146
|
+
var DEFAULT_PROVIDER_TIMEOUT_MS = 10 * 6e4;
|
|
146
147
|
function detectProvider(opts = {}) {
|
|
147
148
|
const timeoutMs = opts.timeoutMs ?? 3e3;
|
|
148
149
|
return new Promise((resolve, reject) => {
|
|
@@ -199,8 +200,24 @@ function unwrapWrite(reply) {
|
|
|
199
200
|
var WalletConnection = class {
|
|
200
201
|
provider;
|
|
201
202
|
_addr = null;
|
|
202
|
-
|
|
203
|
+
/** B7c: per-call provider timeout (ms). GENEROUS by default so it never rejects an in-flight human
|
|
204
|
+
* approval; 0 disables it. Every provider call (writes especially) races against it. */
|
|
205
|
+
_timeoutMs;
|
|
206
|
+
constructor(provider, opts = {}) {
|
|
203
207
|
this.provider = provider;
|
|
208
|
+
this._timeoutMs = opts.timeoutMs ?? DEFAULT_PROVIDER_TIMEOUT_MS;
|
|
209
|
+
}
|
|
210
|
+
// B7c: race a provider call against the per-call timeout. On timeout, throw a fail-closed CairnError
|
|
211
|
+
// (retryable:false: a write may already have reached the wallet, so never invite a blind auto-retry). The
|
|
212
|
+
// genuine wallet resolves quickly once the user acts; this only fires on a truly hung/absent response.
|
|
213
|
+
call(op, label) {
|
|
214
|
+
const ms = this._timeoutMs;
|
|
215
|
+
if (!Number.isFinite(ms) || ms <= 0) return Promise.resolve(op());
|
|
216
|
+
let timer;
|
|
217
|
+
const timeout = new Promise((_, reject) => {
|
|
218
|
+
timer = setTimeout(() => reject(new CairnError(`the wallet did not respond to ${label} within ${ms}ms`, { retryable: false })), ms);
|
|
219
|
+
});
|
|
220
|
+
return Promise.race([Promise.resolve(op()), timeout]).finally(() => clearTimeout(timer));
|
|
204
221
|
}
|
|
205
222
|
/** The wallet's version string (e.g. "0.2.x"). */
|
|
206
223
|
get version() {
|
|
@@ -212,13 +229,13 @@ var WalletConnection = class {
|
|
|
212
229
|
}
|
|
213
230
|
/** Request connection. First time per origin prompts the user; afterwards may be silent. */
|
|
214
231
|
async connect() {
|
|
215
|
-
const { addr } = unwrap(await this.provider.connect());
|
|
232
|
+
const { addr } = unwrap(await this.call(() => this.provider.connect(), "connect"));
|
|
216
233
|
this._addr = addr;
|
|
217
234
|
return addr;
|
|
218
235
|
}
|
|
219
236
|
/** Get the connected address (does not force a new connection prompt if already consented). */
|
|
220
237
|
async getAddress() {
|
|
221
|
-
const { addr } = unwrap(await this.provider.getAddress());
|
|
238
|
+
const { addr } = unwrap(await this.call(() => this.provider.getAddress(), "getAddress"));
|
|
222
239
|
this._addr = addr;
|
|
223
240
|
return addr;
|
|
224
241
|
}
|
|
@@ -231,7 +248,7 @@ var WalletConnection = class {
|
|
|
231
248
|
if (typeof this.provider.signIn !== "function") {
|
|
232
249
|
return Promise.reject(new UnsupportedMethodError("this wallet does not expose signIn()"));
|
|
233
250
|
}
|
|
234
|
-
return
|
|
251
|
+
return this.call(() => this.provider.signIn(), "signIn").then(unwrap);
|
|
235
252
|
}
|
|
236
253
|
/**
|
|
237
254
|
* Audience-bound "Sign in with CSD" (SIWC) — the secure, replay-resistant third-party login.
|
|
@@ -247,7 +264,7 @@ var WalletConnection = class {
|
|
|
247
264
|
if (typeof this.provider.signInWithCsd !== "function") {
|
|
248
265
|
return Promise.reject(new UnsupportedMethodError("this wallet predates Sign-in-with-CSD \u2014 ask the user to update the Cairn Wallet"));
|
|
249
266
|
}
|
|
250
|
-
return
|
|
267
|
+
return this.call(() => this.provider.signInWithCsd(params), "signInWithCsd").then(unwrap);
|
|
251
268
|
}
|
|
252
269
|
/** True if this wallet supports audience-bound SIWC (safe to call `signInWithCsd`). */
|
|
253
270
|
get supportsSiwc() {
|
|
@@ -257,7 +274,7 @@ var WalletConnection = class {
|
|
|
257
274
|
async getCapabilities() {
|
|
258
275
|
if (typeof this.provider.getCapabilities !== "function") return null;
|
|
259
276
|
try {
|
|
260
|
-
return await this.provider.getCapabilities();
|
|
277
|
+
return await this.call(() => this.provider.getCapabilities(), "getCapabilities");
|
|
261
278
|
} catch {
|
|
262
279
|
return null;
|
|
263
280
|
}
|
|
@@ -273,24 +290,24 @@ var WalletConnection = class {
|
|
|
273
290
|
if (typeof this.provider.fillOffer !== "function") {
|
|
274
291
|
return Promise.reject(new UnsupportedMethodError("this wallet predates fillOffer() \u2014 ask the user to update the Cairn Wallet"));
|
|
275
292
|
}
|
|
276
|
-
return
|
|
293
|
+
return this.call(() => this.provider.fillOffer(params), "fillOffer").then(unwrapWrite);
|
|
277
294
|
}
|
|
278
295
|
/** This origin's current permission grant (EIP-2255-style). Silent; [] if none / unsupported. */
|
|
279
296
|
async getPermissions() {
|
|
280
297
|
if (typeof this.provider.getPermissions !== "function") return [];
|
|
281
|
-
return unwrap(await this.provider.getPermissions());
|
|
298
|
+
return unwrap(await this.call(() => this.provider.getPermissions(), "getPermissions"));
|
|
282
299
|
}
|
|
283
300
|
/** Explicitly request permission to see the address (prompts, like connect). */
|
|
284
301
|
requestPermissions() {
|
|
285
302
|
if (typeof this.provider.requestPermissions !== "function") {
|
|
286
303
|
return Promise.reject(new UnsupportedMethodError("this wallet predates requestPermissions \u2014 use connect()"));
|
|
287
304
|
}
|
|
288
|
-
return
|
|
305
|
+
return this.call(() => this.provider.requestPermissions(), "requestPermissions").then(unwrap);
|
|
289
306
|
}
|
|
290
307
|
/** Revoke THIS origin's own access (silent). Returns { revoked }. Safe no-op on older wallets. */
|
|
291
308
|
async revokePermissions() {
|
|
292
309
|
if (typeof this.provider.revokePermissions !== "function") return { revoked: false };
|
|
293
|
-
return unwrap(await this.provider.revokePermissions());
|
|
310
|
+
return unwrap(await this.call(() => this.provider.revokePermissions(), "revokePermissions"));
|
|
294
311
|
}
|
|
295
312
|
/**
|
|
296
313
|
* Subscribe to provider events. `accountsChanged` fires with `[]` when this site loses access
|
|
@@ -306,26 +323,26 @@ var WalletConnection = class {
|
|
|
306
323
|
}
|
|
307
324
|
/** Send CSD (always prompts with clear-signing; wallet picks inputs + returns change to itself). */
|
|
308
325
|
send(params) {
|
|
309
|
-
return
|
|
326
|
+
return this.call(() => this.provider.send(params), "send").then(unwrapWrite);
|
|
310
327
|
}
|
|
311
328
|
/** Low-level Propose (always prompts). Prefer `cairn.board.propose()` which computes the hash/uri/expiry. */
|
|
312
329
|
propose(params) {
|
|
313
|
-
return
|
|
330
|
+
return this.call(() => this.provider.propose(params), "propose").then(unwrapWrite);
|
|
314
331
|
}
|
|
315
332
|
/** Attest/support a proposal (always prompts). */
|
|
316
333
|
attest(params) {
|
|
317
|
-
return
|
|
334
|
+
return this.call(() => this.provider.attest(params), "attest").then(unwrapWrite);
|
|
318
335
|
}
|
|
319
336
|
/** Seal a commit-reveal claim (always prompts; salt stays inside the wallet). */
|
|
320
337
|
sealClaim(params) {
|
|
321
|
-
return
|
|
338
|
+
return this.call(() => this.provider.sealClaim(params), "sealClaim").then(unwrapWrite);
|
|
322
339
|
}
|
|
323
340
|
/** Reveal a previously sealed claim by its sealing txid (always prompts). */
|
|
324
341
|
revealClaim(txid) {
|
|
325
342
|
if (typeof txid !== "string" || !txid) {
|
|
326
343
|
return Promise.reject(new UnsupportedMethodError("revealClaim requires the sealing txid"));
|
|
327
344
|
}
|
|
328
|
-
return
|
|
345
|
+
return this.call(() => this.provider.revealClaim(txid), "revealClaim").then(unwrapWrite);
|
|
329
346
|
}
|
|
330
347
|
};
|
|
331
348
|
async function getWallet(opts = {}) {
|
package/dist/controller.js
CHANGED