@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/board.cjs +33 -2
- package/dist/board.js +2 -2
- package/dist/chain.cjs +29 -0
- package/dist/chain.d.cts +23 -2
- package/dist/chain.d.ts +23 -2
- package/dist/chain.js +5 -1
- package/dist/{chunk-6VWLWF7R.js → chunk-5KAUQH72.js} +31 -2
- package/dist/{chunk-OGP2W7DL.js → chunk-645CYBVN.js} +1 -1
- package/dist/chunk-G4OZKZSJ.js +213 -0
- package/dist/{chunk-BZVJVL4Q.js → chunk-OSXS26RA.js} +1 -1
- package/dist/chunk-UMGWVOOT.js +99 -0
- package/dist/chunk-ZAE2BIH5.js +78 -0
- package/dist/connect.cjs +145 -18
- package/dist/connect.d.cts +134 -2
- package/dist/connect.d.ts +134 -2
- package/dist/connect.js +4 -2
- package/dist/content.cjs +34 -3
- package/dist/content.js +2 -2
- package/dist/controller.cjs +337 -0
- package/dist/controller.d.cts +36 -0
- package/dist/controller.d.ts +36 -0
- package/dist/controller.js +8 -0
- package/dist/index.cjs +256 -22
- package/dist/index.d.cts +33 -4
- package/dist/index.d.ts +33 -4
- package/dist/index.js +27 -15
- package/dist/react.cjs +353 -0
- package/dist/react.d.cts +30 -0
- package/dist/react.d.ts +30 -0
- package/dist/react.js +23 -0
- package/package.json +31 -27
- package/dist/chunk-PHMU3CG5.js +0 -63
- package/dist/chunk-SMAPCKVG.js +0 -118
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getWallet
|
|
3
|
+
} from "./chunk-G4OZKZSJ.js";
|
|
4
|
+
|
|
5
|
+
// src/controller.ts
|
|
6
|
+
var DISCONNECTED = Object.freeze({ status: "disconnected", account: null, error: null });
|
|
7
|
+
var CairnController = class {
|
|
8
|
+
state = DISCONNECTED;
|
|
9
|
+
conn = null;
|
|
10
|
+
listeners = /* @__PURE__ */ new Set();
|
|
11
|
+
getWalletFn;
|
|
12
|
+
detectOpts;
|
|
13
|
+
constructor(opts = {}) {
|
|
14
|
+
const { getWallet: gw, ...detect } = opts;
|
|
15
|
+
this.getWalletFn = gw ?? getWallet;
|
|
16
|
+
this.detectOpts = detect;
|
|
17
|
+
}
|
|
18
|
+
/** useSyncExternalStore-compatible. Returns an unsubscribe fn. */
|
|
19
|
+
subscribe = (cb) => {
|
|
20
|
+
this.listeners.add(cb);
|
|
21
|
+
return () => {
|
|
22
|
+
this.listeners.delete(cb);
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
/** useSyncExternalStore-compatible snapshot — stable reference until the state actually changes. */
|
|
26
|
+
getSnapshot = () => this.state;
|
|
27
|
+
/** The underlying WalletConnection (for advanced use: send/propose/permissions/…). Null until connect(). */
|
|
28
|
+
get connection() {
|
|
29
|
+
return this.conn;
|
|
30
|
+
}
|
|
31
|
+
setState(patch) {
|
|
32
|
+
const next = { ...this.state, ...patch };
|
|
33
|
+
if (next.status === this.state.status && next.account === this.state.account && next.error === this.state.error) return;
|
|
34
|
+
this.state = Object.freeze(next);
|
|
35
|
+
for (const l of [...this.listeners]) l();
|
|
36
|
+
}
|
|
37
|
+
onAccounts = (accounts) => {
|
|
38
|
+
if (!Array.isArray(accounts) || accounts.length === 0) this.setState({ status: "disconnected", account: null });
|
|
39
|
+
else this.setState({ status: "connected", account: String(accounts[0]), error: null });
|
|
40
|
+
};
|
|
41
|
+
onDisconnect = () => {
|
|
42
|
+
this.setState({ status: "disconnected", account: null });
|
|
43
|
+
};
|
|
44
|
+
/** Detect + connect (prompts the user the first time per origin). Resolves the connected address. */
|
|
45
|
+
connect = async () => {
|
|
46
|
+
this.setState({ status: "connecting", error: null });
|
|
47
|
+
try {
|
|
48
|
+
if (!this.conn) {
|
|
49
|
+
this.conn = await this.getWalletFn(this.detectOpts);
|
|
50
|
+
this.conn.on("accountsChanged", this.onAccounts);
|
|
51
|
+
this.conn.on("disconnect", this.onDisconnect);
|
|
52
|
+
}
|
|
53
|
+
const addr = await this.conn.connect();
|
|
54
|
+
this.setState({ status: "connected", account: addr, error: null });
|
|
55
|
+
return addr;
|
|
56
|
+
} catch (e) {
|
|
57
|
+
this.setState({ status: "disconnected", account: null, error: e?.message ?? String(e) });
|
|
58
|
+
throw e;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
/** Forget the connection locally AND revoke this origin's wallet-side permission (best-effort). */
|
|
62
|
+
disconnect = async () => {
|
|
63
|
+
try {
|
|
64
|
+
await this.conn?.revokePermissions();
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
67
|
+
this.setState({ status: "disconnected", account: null, error: null });
|
|
68
|
+
};
|
|
69
|
+
/** Audience-bound sign-in (must connect() first). Returns the signed artifact to verify server-side. */
|
|
70
|
+
signInWithCsd = (params) => {
|
|
71
|
+
if (!this.conn) return Promise.reject(new Error("call connect() before signInWithCsd()"));
|
|
72
|
+
return this.conn.signInWithCsd(params);
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export {
|
|
77
|
+
CairnController
|
|
78
|
+
};
|
package/dist/connect.cjs
CHANGED
|
@@ -23,47 +23,99 @@ __export(connect_exports, {
|
|
|
23
23
|
WalletConnection: () => WalletConnection,
|
|
24
24
|
connect: () => connect,
|
|
25
25
|
detectProvider: () => detectProvider,
|
|
26
|
+
discoverProviders: () => discoverProviders,
|
|
26
27
|
getWallet: () => getWallet,
|
|
27
28
|
isInstalled: () => isInstalled
|
|
28
29
|
});
|
|
29
30
|
module.exports = __toCommonJS(connect_exports);
|
|
30
31
|
|
|
31
32
|
// src/errors.ts
|
|
33
|
+
var SDK_VERSION = "0.1.2";
|
|
34
|
+
var DOCS_BASE = "https://cairn-substrate.com/docs/sdk";
|
|
32
35
|
var CairnError = class extends Error {
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
/** Stable machine code for programmatic branching. */
|
|
37
|
+
code;
|
|
38
|
+
/** The human message without the appended docs/version footer. */
|
|
39
|
+
shortMessage;
|
|
40
|
+
/** Relative docs path (under the SDK docs base), if any. */
|
|
41
|
+
docsPath;
|
|
42
|
+
/** The cairn-sdk version that produced this error. */
|
|
43
|
+
version = SDK_VERSION;
|
|
44
|
+
constructor(shortMessage, opts = {}) {
|
|
45
|
+
const docs = opts.docsPath;
|
|
46
|
+
super(
|
|
47
|
+
[shortMessage, docs ? `Docs: ${DOCS_BASE}${docs}` : "", `Version: cairn-sdk@${SDK_VERSION}`].filter(Boolean).join("\n"),
|
|
48
|
+
{ cause: opts.cause }
|
|
49
|
+
);
|
|
35
50
|
this.name = new.target.name;
|
|
51
|
+
this.code = opts.code ?? "UNKNOWN";
|
|
52
|
+
this.shortMessage = shortMessage;
|
|
53
|
+
this.docsPath = docs;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Walk the `cause` chain. With a predicate, returns the FIRST matching error (or null). Without one,
|
|
57
|
+
* returns the DEEPEST cause (the root). Mirrors viem's `BaseError.walk()`.
|
|
58
|
+
*/
|
|
59
|
+
walk(fn) {
|
|
60
|
+
let current = this;
|
|
61
|
+
let last = this;
|
|
62
|
+
while (current != null) {
|
|
63
|
+
if (fn && fn(current)) return current;
|
|
64
|
+
last = current;
|
|
65
|
+
current = current?.cause;
|
|
66
|
+
}
|
|
67
|
+
return fn ? null : last;
|
|
36
68
|
}
|
|
37
69
|
};
|
|
38
70
|
var NotInstalledError = class extends CairnError {
|
|
39
71
|
constructor(message = "Cairn Wallet not detected. Install it from cairn-substrate.com.") {
|
|
40
|
-
super(message);
|
|
72
|
+
super(message, { code: "NOT_INSTALLED", docsPath: "/install" });
|
|
41
73
|
}
|
|
42
74
|
};
|
|
43
75
|
var UserRejectedError = class extends CairnError {
|
|
44
76
|
constructor(message = "Request rejected by user.") {
|
|
45
|
-
super(message);
|
|
77
|
+
super(message, { code: "USER_REJECTED", docsPath: "/errors#user-rejected" });
|
|
46
78
|
}
|
|
47
79
|
};
|
|
48
80
|
var WalletLockedError = class extends CairnError {
|
|
49
81
|
constructor(message = "Wallet is locked.") {
|
|
50
|
-
super(message);
|
|
82
|
+
super(message, { code: "WALLET_LOCKED", docsPath: "/errors#wallet-locked" });
|
|
51
83
|
}
|
|
52
84
|
};
|
|
53
85
|
var UnsupportedMethodError = class extends CairnError {
|
|
54
86
|
constructor(message = "Method not supported by the wallet.") {
|
|
55
|
-
super(message);
|
|
87
|
+
super(message, { code: "UNSUPPORTED_METHOD", docsPath: "/errors#unsupported-method" });
|
|
56
88
|
}
|
|
57
89
|
};
|
|
58
90
|
function mapProviderError(error) {
|
|
59
91
|
const e = String(error || "").toLowerCase();
|
|
60
92
|
if (e.includes("rejected by user")) return new UserRejectedError(error);
|
|
61
93
|
if (e.includes("wallet locked")) return new WalletLockedError(error);
|
|
62
|
-
if (e.includes("unsupported dapp method")) return new UnsupportedMethodError(error);
|
|
94
|
+
if (e.includes("unsupported dapp method") || e.includes("predates") || e.includes("too old")) return new UnsupportedMethodError(error);
|
|
63
95
|
return new CairnError(error || "Unknown wallet error");
|
|
64
96
|
}
|
|
65
97
|
|
|
66
98
|
// src/connect.ts
|
|
99
|
+
function discoverProviders(opts = {}) {
|
|
100
|
+
const timeoutMs = opts.timeoutMs ?? 1e3;
|
|
101
|
+
return new Promise((resolve) => {
|
|
102
|
+
if (typeof window === "undefined") {
|
|
103
|
+
resolve([]);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const found = /* @__PURE__ */ new Map();
|
|
107
|
+
const onAnnounce = (ev) => {
|
|
108
|
+
const d = ev?.detail;
|
|
109
|
+
if (d?.info?.uuid && d?.provider?.isCairn) found.set(d.info.uuid, d);
|
|
110
|
+
};
|
|
111
|
+
window.addEventListener("csd:announceProvider", onAnnounce);
|
|
112
|
+
window.dispatchEvent(new CustomEvent("csd:requestProvider"));
|
|
113
|
+
setTimeout(() => {
|
|
114
|
+
window.removeEventListener("csd:announceProvider", onAnnounce);
|
|
115
|
+
resolve([...found.values()]);
|
|
116
|
+
}, timeoutMs);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
67
119
|
function detectProvider(opts = {}) {
|
|
68
120
|
const timeoutMs = opts.timeoutMs ?? 3e3;
|
|
69
121
|
return new Promise((resolve, reject) => {
|
|
@@ -71,18 +123,19 @@ function detectProvider(opts = {}) {
|
|
|
71
123
|
reject(new NotInstalledError("Not running in a browser \u2014 `window.cairn` is unavailable."));
|
|
72
124
|
return;
|
|
73
125
|
}
|
|
74
|
-
if (window.cairn?.isCairn) {
|
|
75
|
-
resolve(window.cairn);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
126
|
let done = false;
|
|
79
|
-
const
|
|
127
|
+
const finish = (p) => {
|
|
80
128
|
if (done) return;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
129
|
+
done = true;
|
|
130
|
+
cleanup();
|
|
131
|
+
resolve(p);
|
|
132
|
+
};
|
|
133
|
+
const onInit = () => {
|
|
134
|
+
if (!done && window.cairn?.isCairn) finish(window.cairn);
|
|
135
|
+
};
|
|
136
|
+
const onAnnounce = (ev) => {
|
|
137
|
+
const p = ev?.detail?.provider;
|
|
138
|
+
if (p?.isCairn) finish(p);
|
|
86
139
|
};
|
|
87
140
|
const timer = setTimeout(() => {
|
|
88
141
|
if (done) return;
|
|
@@ -93,8 +146,15 @@ function detectProvider(opts = {}) {
|
|
|
93
146
|
const cleanup = () => {
|
|
94
147
|
clearTimeout(timer);
|
|
95
148
|
window.removeEventListener("cairn#initialized", onInit);
|
|
149
|
+
window.removeEventListener("csd:announceProvider", onAnnounce);
|
|
96
150
|
};
|
|
97
151
|
window.addEventListener("cairn#initialized", onInit);
|
|
152
|
+
window.addEventListener("csd:announceProvider", onAnnounce);
|
|
153
|
+
if (window.cairn?.isCairn) {
|
|
154
|
+
finish(window.cairn);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
window.dispatchEvent(new CustomEvent("csd:requestProvider"));
|
|
98
158
|
onInit();
|
|
99
159
|
});
|
|
100
160
|
}
|
|
@@ -131,10 +191,76 @@ var WalletConnection = class {
|
|
|
131
191
|
this._addr = addr;
|
|
132
192
|
return addr;
|
|
133
193
|
}
|
|
134
|
-
/**
|
|
194
|
+
/**
|
|
195
|
+
* @deprecated First-party-only legacy login (it authenticates against the wallet's own configured
|
|
196
|
+
* server and is rejected from third-party origins). Use {@link signInWithCsd} for any site.
|
|
197
|
+
* Passwordless sign-in: a signature over a login nonce (always prompts; structurally cannot sign a tx).
|
|
198
|
+
*/
|
|
135
199
|
signIn() {
|
|
136
200
|
return Promise.resolve(this.provider.signIn()).then(unwrap);
|
|
137
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Audience-bound "Sign in with CSD" (SIWC) — the secure, replay-resistant third-party login.
|
|
204
|
+
* The wallet binds the REAL requesting origin + your single-use server `nonce` into the signed
|
|
205
|
+
* message and returns the artifact; it never mints a session. VERIFY the result SERVER-SIDE with
|
|
206
|
+
* `verifySiwc` from `@inversealtruism/csd-siwc` (domain/nonce/chain/time/signature/account), then
|
|
207
|
+
* issue your OWN session. The signature is proof-of-control, NOT a bearer token. Always prompts.
|
|
208
|
+
*/
|
|
209
|
+
signInWithCsd(params) {
|
|
210
|
+
if (!params || typeof params.nonce !== "string" || !params.nonce) {
|
|
211
|
+
return Promise.reject(new UnsupportedMethodError("signInWithCsd requires a server-issued { nonce }"));
|
|
212
|
+
}
|
|
213
|
+
if (typeof this.provider.signInWithCsd !== "function") {
|
|
214
|
+
return Promise.reject(new UnsupportedMethodError("this wallet predates Sign-in-with-CSD \u2014 ask the user to update the Cairn Wallet"));
|
|
215
|
+
}
|
|
216
|
+
return Promise.resolve(this.provider.signInWithCsd(params)).then(unwrap);
|
|
217
|
+
}
|
|
218
|
+
/** True if this wallet supports audience-bound SIWC (safe to call `signInWithCsd`). */
|
|
219
|
+
get supportsSiwc() {
|
|
220
|
+
return typeof this.provider.signInWithCsd === "function";
|
|
221
|
+
}
|
|
222
|
+
/** Feature/capability detection. Returns null if the wallet predates `getCapabilities`. */
|
|
223
|
+
async getCapabilities() {
|
|
224
|
+
if (typeof this.provider.getCapabilities !== "function") return null;
|
|
225
|
+
try {
|
|
226
|
+
return await this.provider.getCapabilities();
|
|
227
|
+
} catch {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/** Atomic fill (CairnX DvP): pay + attest in ONE tx. Always prompts with clear-signing. */
|
|
232
|
+
fillOffer(params) {
|
|
233
|
+
return Promise.resolve(this.provider.fillOffer(params)).then(unwrap);
|
|
234
|
+
}
|
|
235
|
+
/** This origin's current permission grant (EIP-2255-style). Silent; [] if none / unsupported. */
|
|
236
|
+
async getPermissions() {
|
|
237
|
+
if (typeof this.provider.getPermissions !== "function") return [];
|
|
238
|
+
return unwrap(await this.provider.getPermissions());
|
|
239
|
+
}
|
|
240
|
+
/** Explicitly request permission to see the address (prompts, like connect). */
|
|
241
|
+
requestPermissions() {
|
|
242
|
+
if (typeof this.provider.requestPermissions !== "function") {
|
|
243
|
+
return Promise.reject(new UnsupportedMethodError("this wallet predates requestPermissions \u2014 use connect()"));
|
|
244
|
+
}
|
|
245
|
+
return Promise.resolve(this.provider.requestPermissions()).then(unwrap);
|
|
246
|
+
}
|
|
247
|
+
/** Revoke THIS origin's own access (silent). Returns { revoked }. Safe no-op on older wallets. */
|
|
248
|
+
async revokePermissions() {
|
|
249
|
+
if (typeof this.provider.revokePermissions !== "function") return { revoked: false };
|
|
250
|
+
return unwrap(await this.provider.revokePermissions());
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Subscribe to provider events. `accountsChanged` fires with `[]` when this site loses access
|
|
254
|
+
* (wallet lock / account switch / revoke) — re-call connect() to (re)share; `disconnect` likewise.
|
|
255
|
+
* No-op if the wallet predates events. Use the SAME handler reference with off() to unsubscribe.
|
|
256
|
+
*/
|
|
257
|
+
on(event, handler) {
|
|
258
|
+
this.provider.on?.(event, handler);
|
|
259
|
+
}
|
|
260
|
+
/** Remove a previously-added event handler (must be the same reference passed to on()). */
|
|
261
|
+
off(event, handler) {
|
|
262
|
+
this.provider.removeListener?.(event, handler);
|
|
263
|
+
}
|
|
138
264
|
/** Send CSD (always prompts with clear-signing; wallet picks inputs + returns change to itself). */
|
|
139
265
|
send(params) {
|
|
140
266
|
return Promise.resolve(this.provider.send(params)).then(unwrap);
|
|
@@ -172,6 +298,7 @@ async function connect(opts = {}) {
|
|
|
172
298
|
WalletConnection,
|
|
173
299
|
connect,
|
|
174
300
|
detectProvider,
|
|
301
|
+
discoverProviders,
|
|
175
302
|
getWallet,
|
|
176
303
|
isInstalled
|
|
177
304
|
});
|
package/dist/connect.d.cts
CHANGED
|
@@ -49,18 +49,94 @@ interface SealClaimParams {
|
|
|
49
49
|
claim: string;
|
|
50
50
|
fee?: number;
|
|
51
51
|
}
|
|
52
|
+
/** Atomic fill (CairnX delivery-vs-payment): an Attest + payment outputs in ONE tx. */
|
|
53
|
+
interface FillParams {
|
|
54
|
+
proposalId: string;
|
|
55
|
+
outputs: {
|
|
56
|
+
to: string;
|
|
57
|
+
value: number;
|
|
58
|
+
}[];
|
|
59
|
+
score?: number;
|
|
60
|
+
confidence?: number;
|
|
61
|
+
fee?: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Audience-bound "Sign in with CSD" (SIWC) params — the secure third-party login. The wallet binds
|
|
65
|
+
* the REAL requesting origin as the message `domain` (from the unforgeable sender.origin, NEVER this
|
|
66
|
+
* field) plus your server `nonce`, chain id, and a validity window, and returns only the signed
|
|
67
|
+
* artifact. The relying party MUST verify it server-side (see below).
|
|
68
|
+
*/
|
|
69
|
+
interface SiwcParams {
|
|
70
|
+
/** Server-issued, single-use, >=8 alphanumeric (use `generateNonce()` from @inversealtruism/csd-siwc). */
|
|
71
|
+
nonce: string;
|
|
72
|
+
/** Optional one-line human statement shown in the wallet (no newline). */
|
|
73
|
+
statement?: string;
|
|
74
|
+
/** Subject URI; defaults to the origin root. If given, MUST be on the requesting site. */
|
|
75
|
+
uri?: string;
|
|
76
|
+
/** Validity window in seconds (wallet clamps 60..3600, default 600). */
|
|
77
|
+
expirationSecs?: number;
|
|
78
|
+
notBeforeSecs?: number;
|
|
79
|
+
requestId?: string;
|
|
80
|
+
resources?: string[];
|
|
81
|
+
/** Optional cross-check only — if set it MUST equal the requesting origin's host, else refused. */
|
|
82
|
+
domain?: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* SIWC result — the signed artifact. VERIFY SERVER-SIDE with `verifySiwc` from
|
|
86
|
+
* `@inversealtruism/csd-siwc` (check domain==your-origin, nonce==your-issued-single-use-nonce,
|
|
87
|
+
* chainId, time window, signature, hash160(pub33)==account), THEN issue your OWN session. The
|
|
88
|
+
* signature is proof-of-control, NEVER a bearer token.
|
|
89
|
+
*/
|
|
90
|
+
interface SiwcResult {
|
|
91
|
+
account: string;
|
|
92
|
+
pub33: string;
|
|
93
|
+
sig64: string;
|
|
94
|
+
/** The exact canonical SIWC message that was signed (verify the signature over this). */
|
|
95
|
+
message: string;
|
|
96
|
+
/** CAIP-2 chain id the sign-in is bound to. */
|
|
97
|
+
chainId: string;
|
|
98
|
+
}
|
|
99
|
+
/** Wallet feature/capability descriptor (feature-detection; older wallets may not expose it). */
|
|
100
|
+
interface WalletCapabilities {
|
|
101
|
+
version: string;
|
|
102
|
+
/** SIWC byte-contract version, e.g. "1", when audience-bound sign-in is supported. */
|
|
103
|
+
siwc?: string;
|
|
104
|
+
methods?: string[];
|
|
105
|
+
[k: string]: unknown;
|
|
106
|
+
}
|
|
107
|
+
/** An EIP-2255-style per-origin permission grant. */
|
|
108
|
+
interface WalletPermission {
|
|
109
|
+
invoker: string;
|
|
110
|
+
accounts: string[];
|
|
111
|
+
grantedAt: number;
|
|
112
|
+
}
|
|
52
113
|
/** The raw provider object the extension injects at `window.cairn`. */
|
|
53
114
|
interface CairnProvider {
|
|
54
115
|
isCairn: true;
|
|
55
116
|
version: string;
|
|
56
117
|
connect(): Promise<ProviderReply<ConnectResult>>;
|
|
57
118
|
getAddress(): Promise<ProviderReply<ConnectResult>>;
|
|
119
|
+
/** @deprecated First-party-only legacy login. Third parties MUST use `signInWithCsd`. */
|
|
58
120
|
signIn(): Promise<ProviderReply<SignInResult>>;
|
|
121
|
+
/** Audience-bound "Sign in with CSD" — the secure third-party login. */
|
|
122
|
+
signInWithCsd(p: SiwcParams): Promise<ProviderReply<SiwcResult>>;
|
|
59
123
|
propose(p: ProposeParams): Promise<ProviderReply<TxResult>>;
|
|
60
124
|
attest(p: AttestParams): Promise<ProviderReply<TxResult>>;
|
|
61
125
|
send(p: SendParams): Promise<ProviderReply<TxResult>>;
|
|
126
|
+
fillOffer(p: FillParams): Promise<ProviderReply<TxResult>>;
|
|
62
127
|
sealClaim(p: SealClaimParams): Promise<ProviderReply<TxResult>>;
|
|
63
128
|
revealClaim(txid: string): Promise<ProviderReply<TxResult>>;
|
|
129
|
+
/** Feature/capability detection (optional; absent on older wallets). */
|
|
130
|
+
getCapabilities?(): Promise<WalletCapabilities>;
|
|
131
|
+
/** EIP-2255-style per-origin permissions (optional; absent on older wallets). */
|
|
132
|
+
getPermissions?(): Promise<ProviderReply<WalletPermission[]>>;
|
|
133
|
+
requestPermissions?(): Promise<ProviderReply<WalletPermission[]>>;
|
|
134
|
+
revokePermissions?(): Promise<ProviderReply<{
|
|
135
|
+
revoked: boolean;
|
|
136
|
+
}>>;
|
|
137
|
+
/** Event subscription (accountsChanged / disconnect) (optional; absent on older wallets). */
|
|
138
|
+
on?(event: string, handler: (data: unknown) => void): void;
|
|
139
|
+
removeListener?(event: string, handler: (data: unknown) => void): void;
|
|
64
140
|
}
|
|
65
141
|
/** Every provider call resolves to this discriminated reply (never rejects). */
|
|
66
142
|
type ProviderReply<T> = {
|
|
@@ -84,6 +160,28 @@ interface DetectOptions {
|
|
|
84
160
|
* content script hasn't injected yet. Throws `NotInstalledError` on timeout or
|
|
85
161
|
* outside a browser.
|
|
86
162
|
*/
|
|
163
|
+
/** EIP-6963-style announced wallet info (Cairn's own `csd:` discovery namespace). */
|
|
164
|
+
interface ProviderInfo {
|
|
165
|
+
uuid: string;
|
|
166
|
+
name: string;
|
|
167
|
+
icon: string;
|
|
168
|
+
rdns: string;
|
|
169
|
+
}
|
|
170
|
+
/** A discovered provider + its display info. */
|
|
171
|
+
interface ProviderDetail {
|
|
172
|
+
info: ProviderInfo;
|
|
173
|
+
provider: CairnProvider;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Enumerate all wallets that announce via the `csd:` discovery handshake (EIP-6963 analog) — for a
|
|
177
|
+
* multi-wallet picker. Resolves with everything announced within `timeoutMs` (default 1000ms).
|
|
178
|
+
*/
|
|
179
|
+
declare function discoverProviders(opts?: DetectOptions): Promise<ProviderDetail[]>;
|
|
180
|
+
/**
|
|
181
|
+
* Resolve `window.cairn`, via three paths that race: an immediate global, the legacy
|
|
182
|
+
* `cairn#initialized` event, or the `csd:announceProvider` discovery handshake (we dispatch
|
|
183
|
+
* `csd:requestProvider`). Throws `NotInstalledError` on timeout or outside a browser.
|
|
184
|
+
*/
|
|
87
185
|
declare function detectProvider(opts?: DetectOptions): Promise<CairnProvider>;
|
|
88
186
|
/** True if the Cairn Wallet is already present (no waiting). */
|
|
89
187
|
declare function isInstalled(): boolean;
|
|
@@ -103,8 +201,42 @@ declare class WalletConnection {
|
|
|
103
201
|
connect(): Promise<string>;
|
|
104
202
|
/** Get the connected address (does not force a new connection prompt if already consented). */
|
|
105
203
|
getAddress(): Promise<string>;
|
|
106
|
-
/**
|
|
204
|
+
/**
|
|
205
|
+
* @deprecated First-party-only legacy login (it authenticates against the wallet's own configured
|
|
206
|
+
* server and is rejected from third-party origins). Use {@link signInWithCsd} for any site.
|
|
207
|
+
* Passwordless sign-in: a signature over a login nonce (always prompts; structurally cannot sign a tx).
|
|
208
|
+
*/
|
|
107
209
|
signIn(): Promise<SignInResult>;
|
|
210
|
+
/**
|
|
211
|
+
* Audience-bound "Sign in with CSD" (SIWC) — the secure, replay-resistant third-party login.
|
|
212
|
+
* The wallet binds the REAL requesting origin + your single-use server `nonce` into the signed
|
|
213
|
+
* message and returns the artifact; it never mints a session. VERIFY the result SERVER-SIDE with
|
|
214
|
+
* `verifySiwc` from `@inversealtruism/csd-siwc` (domain/nonce/chain/time/signature/account), then
|
|
215
|
+
* issue your OWN session. The signature is proof-of-control, NOT a bearer token. Always prompts.
|
|
216
|
+
*/
|
|
217
|
+
signInWithCsd(params: SiwcParams): Promise<SiwcResult>;
|
|
218
|
+
/** True if this wallet supports audience-bound SIWC (safe to call `signInWithCsd`). */
|
|
219
|
+
get supportsSiwc(): boolean;
|
|
220
|
+
/** Feature/capability detection. Returns null if the wallet predates `getCapabilities`. */
|
|
221
|
+
getCapabilities(): Promise<WalletCapabilities | null>;
|
|
222
|
+
/** Atomic fill (CairnX DvP): pay + attest in ONE tx. Always prompts with clear-signing. */
|
|
223
|
+
fillOffer(params: FillParams): Promise<TxResult>;
|
|
224
|
+
/** This origin's current permission grant (EIP-2255-style). Silent; [] if none / unsupported. */
|
|
225
|
+
getPermissions(): Promise<WalletPermission[]>;
|
|
226
|
+
/** Explicitly request permission to see the address (prompts, like connect). */
|
|
227
|
+
requestPermissions(): Promise<WalletPermission[]>;
|
|
228
|
+
/** Revoke THIS origin's own access (silent). Returns { revoked }. Safe no-op on older wallets. */
|
|
229
|
+
revokePermissions(): Promise<{
|
|
230
|
+
revoked: boolean;
|
|
231
|
+
}>;
|
|
232
|
+
/**
|
|
233
|
+
* Subscribe to provider events. `accountsChanged` fires with `[]` when this site loses access
|
|
234
|
+
* (wallet lock / account switch / revoke) — re-call connect() to (re)share; `disconnect` likewise.
|
|
235
|
+
* No-op if the wallet predates events. Use the SAME handler reference with off() to unsubscribe.
|
|
236
|
+
*/
|
|
237
|
+
on(event: "accountsChanged" | "disconnect" | (string & {}), handler: (data: any) => void): void;
|
|
238
|
+
/** Remove a previously-added event handler (must be the same reference passed to on()). */
|
|
239
|
+
off(event: string, handler: (data: any) => void): void;
|
|
108
240
|
/** Send CSD (always prompts with clear-signing; wallet picks inputs + returns change to itself). */
|
|
109
241
|
send(params: SendParams): Promise<TxResult>;
|
|
110
242
|
/** Low-level Propose (always prompts). Prefer `cairn.board.propose()` which computes the hash/uri/expiry. */
|
|
@@ -124,4 +256,4 @@ declare function connect(opts?: DetectOptions): Promise<{
|
|
|
124
256
|
address: string;
|
|
125
257
|
}>;
|
|
126
258
|
|
|
127
|
-
export { type AttestParams, type CairnProvider, type ConnectResult, type DetectOptions, type ProposeParams, type ProviderReply, type SealClaimParams, type SendParams, type SignInResult, type TxResult, WalletConnection, connect, detectProvider, getWallet, isInstalled };
|
|
259
|
+
export { type AttestParams, type CairnProvider, type ConnectResult, type DetectOptions, type FillParams, type ProposeParams, type ProviderDetail, type ProviderInfo, type ProviderReply, type SealClaimParams, type SendParams, type SignInResult, type SiwcParams, type SiwcResult, type TxResult, type WalletCapabilities, WalletConnection, type WalletPermission, connect, detectProvider, discoverProviders, getWallet, isInstalled };
|
package/dist/connect.d.ts
CHANGED
|
@@ -49,18 +49,94 @@ interface SealClaimParams {
|
|
|
49
49
|
claim: string;
|
|
50
50
|
fee?: number;
|
|
51
51
|
}
|
|
52
|
+
/** Atomic fill (CairnX delivery-vs-payment): an Attest + payment outputs in ONE tx. */
|
|
53
|
+
interface FillParams {
|
|
54
|
+
proposalId: string;
|
|
55
|
+
outputs: {
|
|
56
|
+
to: string;
|
|
57
|
+
value: number;
|
|
58
|
+
}[];
|
|
59
|
+
score?: number;
|
|
60
|
+
confidence?: number;
|
|
61
|
+
fee?: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Audience-bound "Sign in with CSD" (SIWC) params — the secure third-party login. The wallet binds
|
|
65
|
+
* the REAL requesting origin as the message `domain` (from the unforgeable sender.origin, NEVER this
|
|
66
|
+
* field) plus your server `nonce`, chain id, and a validity window, and returns only the signed
|
|
67
|
+
* artifact. The relying party MUST verify it server-side (see below).
|
|
68
|
+
*/
|
|
69
|
+
interface SiwcParams {
|
|
70
|
+
/** Server-issued, single-use, >=8 alphanumeric (use `generateNonce()` from @inversealtruism/csd-siwc). */
|
|
71
|
+
nonce: string;
|
|
72
|
+
/** Optional one-line human statement shown in the wallet (no newline). */
|
|
73
|
+
statement?: string;
|
|
74
|
+
/** Subject URI; defaults to the origin root. If given, MUST be on the requesting site. */
|
|
75
|
+
uri?: string;
|
|
76
|
+
/** Validity window in seconds (wallet clamps 60..3600, default 600). */
|
|
77
|
+
expirationSecs?: number;
|
|
78
|
+
notBeforeSecs?: number;
|
|
79
|
+
requestId?: string;
|
|
80
|
+
resources?: string[];
|
|
81
|
+
/** Optional cross-check only — if set it MUST equal the requesting origin's host, else refused. */
|
|
82
|
+
domain?: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* SIWC result — the signed artifact. VERIFY SERVER-SIDE with `verifySiwc` from
|
|
86
|
+
* `@inversealtruism/csd-siwc` (check domain==your-origin, nonce==your-issued-single-use-nonce,
|
|
87
|
+
* chainId, time window, signature, hash160(pub33)==account), THEN issue your OWN session. The
|
|
88
|
+
* signature is proof-of-control, NEVER a bearer token.
|
|
89
|
+
*/
|
|
90
|
+
interface SiwcResult {
|
|
91
|
+
account: string;
|
|
92
|
+
pub33: string;
|
|
93
|
+
sig64: string;
|
|
94
|
+
/** The exact canonical SIWC message that was signed (verify the signature over this). */
|
|
95
|
+
message: string;
|
|
96
|
+
/** CAIP-2 chain id the sign-in is bound to. */
|
|
97
|
+
chainId: string;
|
|
98
|
+
}
|
|
99
|
+
/** Wallet feature/capability descriptor (feature-detection; older wallets may not expose it). */
|
|
100
|
+
interface WalletCapabilities {
|
|
101
|
+
version: string;
|
|
102
|
+
/** SIWC byte-contract version, e.g. "1", when audience-bound sign-in is supported. */
|
|
103
|
+
siwc?: string;
|
|
104
|
+
methods?: string[];
|
|
105
|
+
[k: string]: unknown;
|
|
106
|
+
}
|
|
107
|
+
/** An EIP-2255-style per-origin permission grant. */
|
|
108
|
+
interface WalletPermission {
|
|
109
|
+
invoker: string;
|
|
110
|
+
accounts: string[];
|
|
111
|
+
grantedAt: number;
|
|
112
|
+
}
|
|
52
113
|
/** The raw provider object the extension injects at `window.cairn`. */
|
|
53
114
|
interface CairnProvider {
|
|
54
115
|
isCairn: true;
|
|
55
116
|
version: string;
|
|
56
117
|
connect(): Promise<ProviderReply<ConnectResult>>;
|
|
57
118
|
getAddress(): Promise<ProviderReply<ConnectResult>>;
|
|
119
|
+
/** @deprecated First-party-only legacy login. Third parties MUST use `signInWithCsd`. */
|
|
58
120
|
signIn(): Promise<ProviderReply<SignInResult>>;
|
|
121
|
+
/** Audience-bound "Sign in with CSD" — the secure third-party login. */
|
|
122
|
+
signInWithCsd(p: SiwcParams): Promise<ProviderReply<SiwcResult>>;
|
|
59
123
|
propose(p: ProposeParams): Promise<ProviderReply<TxResult>>;
|
|
60
124
|
attest(p: AttestParams): Promise<ProviderReply<TxResult>>;
|
|
61
125
|
send(p: SendParams): Promise<ProviderReply<TxResult>>;
|
|
126
|
+
fillOffer(p: FillParams): Promise<ProviderReply<TxResult>>;
|
|
62
127
|
sealClaim(p: SealClaimParams): Promise<ProviderReply<TxResult>>;
|
|
63
128
|
revealClaim(txid: string): Promise<ProviderReply<TxResult>>;
|
|
129
|
+
/** Feature/capability detection (optional; absent on older wallets). */
|
|
130
|
+
getCapabilities?(): Promise<WalletCapabilities>;
|
|
131
|
+
/** EIP-2255-style per-origin permissions (optional; absent on older wallets). */
|
|
132
|
+
getPermissions?(): Promise<ProviderReply<WalletPermission[]>>;
|
|
133
|
+
requestPermissions?(): Promise<ProviderReply<WalletPermission[]>>;
|
|
134
|
+
revokePermissions?(): Promise<ProviderReply<{
|
|
135
|
+
revoked: boolean;
|
|
136
|
+
}>>;
|
|
137
|
+
/** Event subscription (accountsChanged / disconnect) (optional; absent on older wallets). */
|
|
138
|
+
on?(event: string, handler: (data: unknown) => void): void;
|
|
139
|
+
removeListener?(event: string, handler: (data: unknown) => void): void;
|
|
64
140
|
}
|
|
65
141
|
/** Every provider call resolves to this discriminated reply (never rejects). */
|
|
66
142
|
type ProviderReply<T> = {
|
|
@@ -84,6 +160,28 @@ interface DetectOptions {
|
|
|
84
160
|
* content script hasn't injected yet. Throws `NotInstalledError` on timeout or
|
|
85
161
|
* outside a browser.
|
|
86
162
|
*/
|
|
163
|
+
/** EIP-6963-style announced wallet info (Cairn's own `csd:` discovery namespace). */
|
|
164
|
+
interface ProviderInfo {
|
|
165
|
+
uuid: string;
|
|
166
|
+
name: string;
|
|
167
|
+
icon: string;
|
|
168
|
+
rdns: string;
|
|
169
|
+
}
|
|
170
|
+
/** A discovered provider + its display info. */
|
|
171
|
+
interface ProviderDetail {
|
|
172
|
+
info: ProviderInfo;
|
|
173
|
+
provider: CairnProvider;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Enumerate all wallets that announce via the `csd:` discovery handshake (EIP-6963 analog) — for a
|
|
177
|
+
* multi-wallet picker. Resolves with everything announced within `timeoutMs` (default 1000ms).
|
|
178
|
+
*/
|
|
179
|
+
declare function discoverProviders(opts?: DetectOptions): Promise<ProviderDetail[]>;
|
|
180
|
+
/**
|
|
181
|
+
* Resolve `window.cairn`, via three paths that race: an immediate global, the legacy
|
|
182
|
+
* `cairn#initialized` event, or the `csd:announceProvider` discovery handshake (we dispatch
|
|
183
|
+
* `csd:requestProvider`). Throws `NotInstalledError` on timeout or outside a browser.
|
|
184
|
+
*/
|
|
87
185
|
declare function detectProvider(opts?: DetectOptions): Promise<CairnProvider>;
|
|
88
186
|
/** True if the Cairn Wallet is already present (no waiting). */
|
|
89
187
|
declare function isInstalled(): boolean;
|
|
@@ -103,8 +201,42 @@ declare class WalletConnection {
|
|
|
103
201
|
connect(): Promise<string>;
|
|
104
202
|
/** Get the connected address (does not force a new connection prompt if already consented). */
|
|
105
203
|
getAddress(): Promise<string>;
|
|
106
|
-
/**
|
|
204
|
+
/**
|
|
205
|
+
* @deprecated First-party-only legacy login (it authenticates against the wallet's own configured
|
|
206
|
+
* server and is rejected from third-party origins). Use {@link signInWithCsd} for any site.
|
|
207
|
+
* Passwordless sign-in: a signature over a login nonce (always prompts; structurally cannot sign a tx).
|
|
208
|
+
*/
|
|
107
209
|
signIn(): Promise<SignInResult>;
|
|
210
|
+
/**
|
|
211
|
+
* Audience-bound "Sign in with CSD" (SIWC) — the secure, replay-resistant third-party login.
|
|
212
|
+
* The wallet binds the REAL requesting origin + your single-use server `nonce` into the signed
|
|
213
|
+
* message and returns the artifact; it never mints a session. VERIFY the result SERVER-SIDE with
|
|
214
|
+
* `verifySiwc` from `@inversealtruism/csd-siwc` (domain/nonce/chain/time/signature/account), then
|
|
215
|
+
* issue your OWN session. The signature is proof-of-control, NOT a bearer token. Always prompts.
|
|
216
|
+
*/
|
|
217
|
+
signInWithCsd(params: SiwcParams): Promise<SiwcResult>;
|
|
218
|
+
/** True if this wallet supports audience-bound SIWC (safe to call `signInWithCsd`). */
|
|
219
|
+
get supportsSiwc(): boolean;
|
|
220
|
+
/** Feature/capability detection. Returns null if the wallet predates `getCapabilities`. */
|
|
221
|
+
getCapabilities(): Promise<WalletCapabilities | null>;
|
|
222
|
+
/** Atomic fill (CairnX DvP): pay + attest in ONE tx. Always prompts with clear-signing. */
|
|
223
|
+
fillOffer(params: FillParams): Promise<TxResult>;
|
|
224
|
+
/** This origin's current permission grant (EIP-2255-style). Silent; [] if none / unsupported. */
|
|
225
|
+
getPermissions(): Promise<WalletPermission[]>;
|
|
226
|
+
/** Explicitly request permission to see the address (prompts, like connect). */
|
|
227
|
+
requestPermissions(): Promise<WalletPermission[]>;
|
|
228
|
+
/** Revoke THIS origin's own access (silent). Returns { revoked }. Safe no-op on older wallets. */
|
|
229
|
+
revokePermissions(): Promise<{
|
|
230
|
+
revoked: boolean;
|
|
231
|
+
}>;
|
|
232
|
+
/**
|
|
233
|
+
* Subscribe to provider events. `accountsChanged` fires with `[]` when this site loses access
|
|
234
|
+
* (wallet lock / account switch / revoke) — re-call connect() to (re)share; `disconnect` likewise.
|
|
235
|
+
* No-op if the wallet predates events. Use the SAME handler reference with off() to unsubscribe.
|
|
236
|
+
*/
|
|
237
|
+
on(event: "accountsChanged" | "disconnect" | (string & {}), handler: (data: any) => void): void;
|
|
238
|
+
/** Remove a previously-added event handler (must be the same reference passed to on()). */
|
|
239
|
+
off(event: string, handler: (data: any) => void): void;
|
|
108
240
|
/** Send CSD (always prompts with clear-signing; wallet picks inputs + returns change to itself). */
|
|
109
241
|
send(params: SendParams): Promise<TxResult>;
|
|
110
242
|
/** Low-level Propose (always prompts). Prefer `cairn.board.propose()` which computes the hash/uri/expiry. */
|
|
@@ -124,4 +256,4 @@ declare function connect(opts?: DetectOptions): Promise<{
|
|
|
124
256
|
address: string;
|
|
125
257
|
}>;
|
|
126
258
|
|
|
127
|
-
export { type AttestParams, type CairnProvider, type ConnectResult, type DetectOptions, type ProposeParams, type ProviderReply, type SealClaimParams, type SendParams, type SignInResult, type TxResult, WalletConnection, connect, detectProvider, getWallet, isInstalled };
|
|
259
|
+
export { type AttestParams, type CairnProvider, type ConnectResult, type DetectOptions, type FillParams, type ProposeParams, type ProviderDetail, type ProviderInfo, type ProviderReply, type SealClaimParams, type SendParams, type SignInResult, type SiwcParams, type SiwcResult, type TxResult, type WalletCapabilities, WalletConnection, type WalletPermission, connect, detectProvider, discoverProviders, getWallet, isInstalled };
|