@rhinestone/1auth 0.6.8 → 0.6.10

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.
Files changed (51) hide show
  1. package/README.md +171 -12
  2. package/dist/chunk-GUAI55LL.mjs +179 -0
  3. package/dist/chunk-GUAI55LL.mjs.map +1 -0
  4. package/dist/chunk-IHBVEU33.mjs +20 -0
  5. package/dist/chunk-IHBVEU33.mjs.map +1 -0
  6. package/dist/chunk-IIACVHR3.mjs +28 -0
  7. package/dist/chunk-IIACVHR3.mjs.map +1 -0
  8. package/dist/chunk-N6KE5CII.mjs +72 -0
  9. package/dist/chunk-N6KE5CII.mjs.map +1 -0
  10. package/dist/{chunk-SXISYG2P.mjs → chunk-THKG3FAG.mjs} +137 -255
  11. package/dist/chunk-THKG3FAG.mjs.map +1 -0
  12. package/dist/{client-BrMrhetG.d.mts → client-B_CzDa_I.d.ts} +360 -857
  13. package/dist/{client-BrMrhetG.d.ts → client-F4DnFM8d.d.mts} +360 -857
  14. package/dist/headless.d.mts +109 -0
  15. package/dist/headless.d.ts +109 -0
  16. package/dist/headless.js +467 -0
  17. package/dist/headless.js.map +1 -0
  18. package/dist/headless.mjs +382 -0
  19. package/dist/headless.mjs.map +1 -0
  20. package/dist/index.d.mts +96 -144
  21. package/dist/index.d.ts +96 -144
  22. package/dist/index.js +3212 -756
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.mjs +3010 -705
  25. package/dist/index.mjs.map +1 -1
  26. package/dist/{provider-CDl9wYEc.d.mts → provider-Cd7Ip5L-.d.ts} +6 -5
  27. package/dist/{provider-Dgv533YQ.d.ts → provider-IvYXPMpk.d.mts} +6 -5
  28. package/dist/react.d.mts +42 -2
  29. package/dist/react.d.ts +42 -2
  30. package/dist/react.js +92 -2
  31. package/dist/react.js.map +1 -1
  32. package/dist/react.mjs +66 -1
  33. package/dist/react.mjs.map +1 -1
  34. package/dist/server.d.mts +118 -0
  35. package/dist/server.d.ts +118 -0
  36. package/dist/server.js +356 -0
  37. package/dist/server.js.map +1 -0
  38. package/dist/server.mjs +282 -0
  39. package/dist/server.mjs.map +1 -0
  40. package/dist/types-U_dwxbtS.d.mts +1488 -0
  41. package/dist/types-U_dwxbtS.d.ts +1488 -0
  42. package/dist/verify-BLgZzwmJ.d.ts +150 -0
  43. package/dist/verify-C8-a5c3K.d.mts +150 -0
  44. package/dist/wagmi.d.mts +5 -2
  45. package/dist/wagmi.d.ts +5 -2
  46. package/dist/wagmi.js +138 -43
  47. package/dist/wagmi.js.map +1 -1
  48. package/dist/wagmi.mjs +3 -1
  49. package/dist/wagmi.mjs.map +1 -1
  50. package/package.json +15 -2
  51. package/dist/chunk-SXISYG2P.mjs.map +0 -1
@@ -0,0 +1,109 @@
1
+ import { P as PasskeyProviderConfig, S as SponsorshipConfig, H as HeadlessIntentOptions, a as HeadlessPrepareResult, b as HeadlessSubmitOptions, c as HeadlessSubmitResult, d as HeadlessIntentStatusResult, I as InstallSmartSessionOptions, e as InstallSmartSessionResult, f as SessionKeyHandle } from './types-U_dwxbtS.mjs';
2
+ export { g as SmartSessionEnableRequest } from './types-U_dwxbtS.mjs';
3
+ import * as _rhinestone_sdk from '@rhinestone/sdk';
4
+ import { Hex, Address } from 'viem';
5
+
6
+ /**
7
+ * Headless 1auth client.
8
+ *
9
+ * Used by integrators that hold their own ECDSA signer in localStorage
10
+ * and produce signatures for an ERC-7579 validator other than the
11
+ * passkey one (typically `@rhinestone/sdk` experimental SmartSession).
12
+ *
13
+ * Responsibilities:
14
+ * - Fetch sponsorship JWTs from the app's own backend.
15
+ * - Call `/api/intent/prepare?signingMode=headless` to get an
16
+ * orchestrator-quoted `intentOp` + `digestResult`.
17
+ * - Forward pre-encoded validator-prefixed signatures to the new
18
+ * `/api/intent/headless-execute` route.
19
+ * - Drive the existing passkey dialog (via {@link OneAuthClient}) for
20
+ * the one-time SmartSession install ceremony.
21
+ *
22
+ * 1auth itself stays ignorant of session keys — the on-chain
23
+ * SmartSession validator is the only authority over what a session key
24
+ * may sign for. The host app persists `{ sessionKeyAddress, permissionId,
25
+ * accountAddress, permissions }` in its own storage.
26
+ */
27
+
28
+ declare class OneAuthHeadlessClient {
29
+ private providerUrl;
30
+ private clientId?;
31
+ private sponsorship;
32
+ constructor(config: PasskeyProviderConfig);
33
+ setSponsorship(sponsorship: SponsorshipConfig | undefined): void;
34
+ private fetchAccessToken;
35
+ private fetchExtensionToken;
36
+ /**
37
+ * Quote an intent without opening any dialog. Returns the orchestrator's
38
+ * `intentOp` plus the digest the caller must sign with their own
39
+ * validator (e.g. SmartSession). The caller is responsible for
40
+ * encoding signatures and submitting via {@link submitIntent}.
41
+ */
42
+ prepareIntent(options: HeadlessIntentOptions): Promise<HeadlessPrepareResult>;
43
+ /**
44
+ * Forward a pre-signed intent to the orchestrator. The caller has
45
+ * already encoded validator-prefixed origin + destination signatures
46
+ * (one origin signature per intent element); 1auth treats them as
47
+ * opaque bytes.
48
+ *
49
+ * If `sponsor` is omitted or `true`, an extension token is fetched
50
+ * just-in-time and bound to the intent. Pass `sponsor: false` for
51
+ * self-paying intents.
52
+ */
53
+ submitIntent(options: HeadlessSubmitOptions): Promise<HeadlessSubmitResult>;
54
+ /**
55
+ * Fetch the latest known status for a submitted headless intent.
56
+ * This is a non-blocking read and may return `pending` before a
57
+ * solver has produced a fill transaction hash.
58
+ */
59
+ getIntentStatus(intentId: string): Promise<HeadlessIntentStatusResult>;
60
+ /**
61
+ * Wait for a submitted headless intent to produce a status update and,
62
+ * when available, the final fill transaction hash. The wait endpoint
63
+ * needs the opaque `transactionResult` returned by submit because 1auth
64
+ * does not persist that SDK object in its database.
65
+ */
66
+ waitForIntent(intentId: string, transactionResult: unknown): Promise<HeadlessIntentStatusResult>;
67
+ /**
68
+ * Resolve the SmartSession install call(s) for `sessionKeyAddress`
69
+ * with the supplied `permissions`.
70
+ *
71
+ * Returns `{ install, sessionKeyHandle }`:
72
+ *
73
+ * - `install` is a `{ targetChain, calls }` pair the caller feeds
74
+ * straight into `OneAuthClient.sendIntent({ targetChain, calls })`
75
+ * so the user passkey-signs the install via the existing dialog.
76
+ * - `sessionKeyHandle` contains the deterministic `permissionId`
77
+ * plus metadata to persist in localStorage. Persist this BEFORE
78
+ * submitting the install so a refresh during signing doesn't
79
+ * lose the handle.
80
+ *
81
+ * If the validator is already installed on the user's account,
82
+ * `install.calls` is empty and `install.alreadyInstalled` is true.
83
+ * The caller should still persist `sessionKeyHandle` — the on-chain
84
+ * session enabling happens at first headless use via SmartSession's
85
+ * ENABLE-mode signature wrapping (see follow-up).
86
+ */
87
+ installSmartSession(options: InstallSmartSessionOptions): Promise<InstallSmartSessionResult>;
88
+ }
89
+
90
+ interface BuildSmartSessionHeadlessSignaturesOptions {
91
+ /** ECDSA private key for the locally-held SmartSession signer. */
92
+ privateKey: Hex;
93
+ /** Smart account address the SmartSession is scoped to. */
94
+ accountAddress: Address;
95
+ /** Persisted handle returned by `grantPermissions` / SmartSession install. */
96
+ sessionKeyHandle: SessionKeyHandle;
97
+ /** Prepared headless intent returned by `OneAuthHeadlessClient.prepareIntent`. */
98
+ prepared: HeadlessPrepareResult;
99
+ }
100
+ /**
101
+ * Builds SmartSession signatures for `OneAuthHeadlessClient.submitIntent`.
102
+ *
103
+ * This intentionally delegates signing and SmartSession signature packing to
104
+ * `@rhinestone/sdk`. 1auth only rebuilds the persisted session descriptor and
105
+ * supplies the SDK-native `SignData` returned by the orchestrator quote.
106
+ */
107
+ declare function buildSmartSessionHeadlessSignatures(options: BuildSmartSessionHeadlessSignaturesOptions): Promise<_rhinestone_sdk.SignedIntentData>;
108
+
109
+ export { type BuildSmartSessionHeadlessSignaturesOptions, HeadlessIntentOptions, HeadlessIntentStatusResult, HeadlessPrepareResult, HeadlessSubmitOptions, HeadlessSubmitResult, InstallSmartSessionOptions, InstallSmartSessionResult, OneAuthHeadlessClient, SessionKeyHandle, buildSmartSessionHeadlessSignatures };
@@ -0,0 +1,109 @@
1
+ import { P as PasskeyProviderConfig, S as SponsorshipConfig, H as HeadlessIntentOptions, a as HeadlessPrepareResult, b as HeadlessSubmitOptions, c as HeadlessSubmitResult, d as HeadlessIntentStatusResult, I as InstallSmartSessionOptions, e as InstallSmartSessionResult, f as SessionKeyHandle } from './types-U_dwxbtS.js';
2
+ export { g as SmartSessionEnableRequest } from './types-U_dwxbtS.js';
3
+ import * as _rhinestone_sdk from '@rhinestone/sdk';
4
+ import { Hex, Address } from 'viem';
5
+
6
+ /**
7
+ * Headless 1auth client.
8
+ *
9
+ * Used by integrators that hold their own ECDSA signer in localStorage
10
+ * and produce signatures for an ERC-7579 validator other than the
11
+ * passkey one (typically `@rhinestone/sdk` experimental SmartSession).
12
+ *
13
+ * Responsibilities:
14
+ * - Fetch sponsorship JWTs from the app's own backend.
15
+ * - Call `/api/intent/prepare?signingMode=headless` to get an
16
+ * orchestrator-quoted `intentOp` + `digestResult`.
17
+ * - Forward pre-encoded validator-prefixed signatures to the new
18
+ * `/api/intent/headless-execute` route.
19
+ * - Drive the existing passkey dialog (via {@link OneAuthClient}) for
20
+ * the one-time SmartSession install ceremony.
21
+ *
22
+ * 1auth itself stays ignorant of session keys — the on-chain
23
+ * SmartSession validator is the only authority over what a session key
24
+ * may sign for. The host app persists `{ sessionKeyAddress, permissionId,
25
+ * accountAddress, permissions }` in its own storage.
26
+ */
27
+
28
+ declare class OneAuthHeadlessClient {
29
+ private providerUrl;
30
+ private clientId?;
31
+ private sponsorship;
32
+ constructor(config: PasskeyProviderConfig);
33
+ setSponsorship(sponsorship: SponsorshipConfig | undefined): void;
34
+ private fetchAccessToken;
35
+ private fetchExtensionToken;
36
+ /**
37
+ * Quote an intent without opening any dialog. Returns the orchestrator's
38
+ * `intentOp` plus the digest the caller must sign with their own
39
+ * validator (e.g. SmartSession). The caller is responsible for
40
+ * encoding signatures and submitting via {@link submitIntent}.
41
+ */
42
+ prepareIntent(options: HeadlessIntentOptions): Promise<HeadlessPrepareResult>;
43
+ /**
44
+ * Forward a pre-signed intent to the orchestrator. The caller has
45
+ * already encoded validator-prefixed origin + destination signatures
46
+ * (one origin signature per intent element); 1auth treats them as
47
+ * opaque bytes.
48
+ *
49
+ * If `sponsor` is omitted or `true`, an extension token is fetched
50
+ * just-in-time and bound to the intent. Pass `sponsor: false` for
51
+ * self-paying intents.
52
+ */
53
+ submitIntent(options: HeadlessSubmitOptions): Promise<HeadlessSubmitResult>;
54
+ /**
55
+ * Fetch the latest known status for a submitted headless intent.
56
+ * This is a non-blocking read and may return `pending` before a
57
+ * solver has produced a fill transaction hash.
58
+ */
59
+ getIntentStatus(intentId: string): Promise<HeadlessIntentStatusResult>;
60
+ /**
61
+ * Wait for a submitted headless intent to produce a status update and,
62
+ * when available, the final fill transaction hash. The wait endpoint
63
+ * needs the opaque `transactionResult` returned by submit because 1auth
64
+ * does not persist that SDK object in its database.
65
+ */
66
+ waitForIntent(intentId: string, transactionResult: unknown): Promise<HeadlessIntentStatusResult>;
67
+ /**
68
+ * Resolve the SmartSession install call(s) for `sessionKeyAddress`
69
+ * with the supplied `permissions`.
70
+ *
71
+ * Returns `{ install, sessionKeyHandle }`:
72
+ *
73
+ * - `install` is a `{ targetChain, calls }` pair the caller feeds
74
+ * straight into `OneAuthClient.sendIntent({ targetChain, calls })`
75
+ * so the user passkey-signs the install via the existing dialog.
76
+ * - `sessionKeyHandle` contains the deterministic `permissionId`
77
+ * plus metadata to persist in localStorage. Persist this BEFORE
78
+ * submitting the install so a refresh during signing doesn't
79
+ * lose the handle.
80
+ *
81
+ * If the validator is already installed on the user's account,
82
+ * `install.calls` is empty and `install.alreadyInstalled` is true.
83
+ * The caller should still persist `sessionKeyHandle` — the on-chain
84
+ * session enabling happens at first headless use via SmartSession's
85
+ * ENABLE-mode signature wrapping (see follow-up).
86
+ */
87
+ installSmartSession(options: InstallSmartSessionOptions): Promise<InstallSmartSessionResult>;
88
+ }
89
+
90
+ interface BuildSmartSessionHeadlessSignaturesOptions {
91
+ /** ECDSA private key for the locally-held SmartSession signer. */
92
+ privateKey: Hex;
93
+ /** Smart account address the SmartSession is scoped to. */
94
+ accountAddress: Address;
95
+ /** Persisted handle returned by `grantPermissions` / SmartSession install. */
96
+ sessionKeyHandle: SessionKeyHandle;
97
+ /** Prepared headless intent returned by `OneAuthHeadlessClient.prepareIntent`. */
98
+ prepared: HeadlessPrepareResult;
99
+ }
100
+ /**
101
+ * Builds SmartSession signatures for `OneAuthHeadlessClient.submitIntent`.
102
+ *
103
+ * This intentionally delegates signing and SmartSession signature packing to
104
+ * `@rhinestone/sdk`. 1auth only rebuilds the persisted session descriptor and
105
+ * supplies the SDK-native `SignData` returned by the orchestrator quote.
106
+ */
107
+ declare function buildSmartSessionHeadlessSignatures(options: BuildSmartSessionHeadlessSignaturesOptions): Promise<_rhinestone_sdk.SignedIntentData>;
108
+
109
+ export { type BuildSmartSessionHeadlessSignaturesOptions, HeadlessIntentOptions, HeadlessIntentStatusResult, HeadlessPrepareResult, HeadlessSubmitOptions, HeadlessSubmitResult, InstallSmartSessionOptions, InstallSmartSessionResult, OneAuthHeadlessClient, SessionKeyHandle, buildSmartSessionHeadlessSignatures };
@@ -0,0 +1,467 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/headless.ts
31
+ var headless_exports = {};
32
+ __export(headless_exports, {
33
+ OneAuthHeadlessClient: () => OneAuthHeadlessClient,
34
+ buildSmartSessionHeadlessSignatures: () => buildSmartSessionHeadlessSignatures
35
+ });
36
+ module.exports = __toCommonJS(headless_exports);
37
+
38
+ // src/sponsorship-fetch.ts
39
+ async function extractServerReason(response) {
40
+ try {
41
+ const text = await response.clone().text();
42
+ if (!text) return response.statusText;
43
+ try {
44
+ const data = JSON.parse(text);
45
+ const reason = data.error ?? data.message;
46
+ if (typeof reason === "string" && reason.trim()) return reason;
47
+ } catch {
48
+ }
49
+ return text.slice(0, 200);
50
+ } catch {
51
+ return response.statusText;
52
+ }
53
+ }
54
+ async function tokenFetchError(label, response) {
55
+ const reason = await extractServerReason(response);
56
+ const suffix = reason ? `: ${reason}` : "";
57
+ return new Error(
58
+ `Failed to fetch ${label} (${response.status} ${response.statusText})${suffix}`
59
+ );
60
+ }
61
+
62
+ // src/headless-client.ts
63
+ var DEFAULT_PROVIDER_URL = "https://passkey.1auth.box";
64
+ var MISSING_APP_CREDENTIALS_MESSAGE = "No sponsorship configured on OneAuthHeadlessClient. Every user intent must carry the app's JWT \u2014 pass `sponsorship: { accessToken, getExtensionToken }` (or URL form) to the constructor.";
65
+ function normalizeSponsorship(config) {
66
+ if (!config) return null;
67
+ if ("accessToken" in config && "getExtensionToken" in config) {
68
+ return config;
69
+ }
70
+ const { accessTokenUrl, extensionTokenUrl } = config;
71
+ return {
72
+ accessToken: async () => {
73
+ const response = await fetch(accessTokenUrl, { credentials: "include" });
74
+ if (!response.ok) {
75
+ throw await tokenFetchError("access token", response);
76
+ }
77
+ const data = await response.json();
78
+ if (!data.token) {
79
+ throw new Error("Access token response missing `token` field");
80
+ }
81
+ return data.token;
82
+ },
83
+ getExtensionToken: async (intentOp) => {
84
+ const response = await fetch(extensionTokenUrl, {
85
+ method: "POST",
86
+ credentials: "include",
87
+ headers: { "Content-Type": "application/json" },
88
+ body: JSON.stringify({ intentOp })
89
+ });
90
+ if (!response.ok) {
91
+ throw await tokenFetchError("extension token", response);
92
+ }
93
+ const data = await response.json();
94
+ if (!data.token) {
95
+ throw new Error("Extension token response missing `token` field");
96
+ }
97
+ return data.token;
98
+ }
99
+ };
100
+ }
101
+ var OneAuthHeadlessClient = class {
102
+ constructor(config) {
103
+ this.providerUrl = config.providerUrl || DEFAULT_PROVIDER_URL;
104
+ this.clientId = config.clientId;
105
+ this.sponsorship = normalizeSponsorship(config.sponsorship);
106
+ }
107
+ setSponsorship(sponsorship) {
108
+ this.sponsorship = normalizeSponsorship(sponsorship);
109
+ }
110
+ // ---------------------------------------------------------------------------
111
+ // Sponsorship JWT fetchers
112
+ // ---------------------------------------------------------------------------
113
+ async fetchAccessToken() {
114
+ if (!this.sponsorship) {
115
+ return {
116
+ ok: false,
117
+ code: "MISSING_APP_CREDENTIALS",
118
+ message: MISSING_APP_CREDENTIALS_MESSAGE
119
+ };
120
+ }
121
+ try {
122
+ const accessToken = await this.sponsorship.accessToken();
123
+ return { ok: true, accessToken };
124
+ } catch (err) {
125
+ return {
126
+ ok: false,
127
+ message: err instanceof Error ? err.message : String(err)
128
+ };
129
+ }
130
+ }
131
+ async fetchExtensionToken(intentOp, sponsor) {
132
+ if (!sponsor) return { ok: true, extensionToken: void 0 };
133
+ if (!this.sponsorship) {
134
+ return { ok: false, message: MISSING_APP_CREDENTIALS_MESSAGE };
135
+ }
136
+ try {
137
+ const token = await this.sponsorship.getExtensionToken(intentOp);
138
+ return { ok: true, extensionToken: token };
139
+ } catch (err) {
140
+ return {
141
+ ok: false,
142
+ message: err instanceof Error ? err.message : String(err)
143
+ };
144
+ }
145
+ }
146
+ // ---------------------------------------------------------------------------
147
+ // Intent prepare / submit
148
+ // ---------------------------------------------------------------------------
149
+ /**
150
+ * Quote an intent without opening any dialog. Returns the orchestrator's
151
+ * `intentOp` plus the digest the caller must sign with their own
152
+ * validator (e.g. SmartSession). The caller is responsible for
153
+ * encoding signatures and submitting via {@link submitIntent}.
154
+ */
155
+ async prepareIntent(options) {
156
+ if (!options.username && !options.accountAddress) {
157
+ throw new Error("prepareIntent requires either `username` or `accountAddress`");
158
+ }
159
+ const accessTokenResult = await this.fetchAccessToken();
160
+ if (!accessTokenResult.ok) {
161
+ throw new Error(`Sponsorship access token fetch failed: ${accessTokenResult.message}`);
162
+ }
163
+ const tokenRequests = options.tokenRequests?.map((tr) => ({
164
+ token: tr.token,
165
+ amount: tr.amount.toString()
166
+ }));
167
+ const body = {
168
+ username: options.username,
169
+ accountAddress: options.accountAddress,
170
+ targetChain: options.targetChain,
171
+ calls: options.calls,
172
+ tokenRequests,
173
+ sourceAssets: options.sourceAssets,
174
+ sourceChainId: options.sourceChainId,
175
+ sessionKeyHandle: options.sessionKeyHandle,
176
+ clientId: this.clientId,
177
+ signingMode: "headless",
178
+ auth: { accessToken: accessTokenResult.accessToken }
179
+ };
180
+ const response = await fetch(`${this.providerUrl}/api/intent/prepare`, {
181
+ method: "POST",
182
+ headers: { "Content-Type": "application/json" },
183
+ body: JSON.stringify(body)
184
+ });
185
+ if (!response.ok) {
186
+ const errorData = await response.json().catch(() => ({}));
187
+ throw new Error(errorData.error || `Prepare failed (${response.status})`);
188
+ }
189
+ return await response.json();
190
+ }
191
+ /**
192
+ * Forward a pre-signed intent to the orchestrator. The caller has
193
+ * already encoded validator-prefixed origin + destination signatures
194
+ * (one origin signature per intent element); 1auth treats them as
195
+ * opaque bytes.
196
+ *
197
+ * If `sponsor` is omitted or `true`, an extension token is fetched
198
+ * just-in-time and bound to the intent. Pass `sponsor: false` for
199
+ * self-paying intents.
200
+ */
201
+ async submitIntent(options) {
202
+ const sponsor = options.sponsor ?? true;
203
+ const accessTokenResult = await this.fetchAccessToken();
204
+ if (!accessTokenResult.ok) {
205
+ throw new Error(`Sponsorship access token fetch failed: ${accessTokenResult.message}`);
206
+ }
207
+ const extensionResult = await this.fetchExtensionToken(options.intentOp, sponsor);
208
+ if (!extensionResult.ok) {
209
+ throw new Error(`Sponsorship extension token fetch failed: ${extensionResult.message}`);
210
+ }
211
+ const body = {
212
+ intentOp: options.intentOp,
213
+ accountAddress: options.accountAddress,
214
+ targetChain: options.targetChain,
215
+ calls: options.calls,
216
+ expiresAt: options.expiresAt,
217
+ originSignatures: options.originSignatures,
218
+ destinationSignature: options.destinationSignature,
219
+ targetExecutionSignature: options.targetExecutionSignature,
220
+ auth: {
221
+ accessToken: accessTokenResult.accessToken,
222
+ ...extensionResult.extensionToken && { extensionToken: extensionResult.extensionToken }
223
+ }
224
+ };
225
+ const response = await fetch(`${this.providerUrl}/api/intent/headless-execute`, {
226
+ method: "POST",
227
+ headers: { "Content-Type": "application/json" },
228
+ body: JSON.stringify(body)
229
+ });
230
+ if (!response.ok) {
231
+ const errorData = await response.json().catch(() => ({}));
232
+ throw new Error(errorData.error || `Headless execute failed (${response.status})`);
233
+ }
234
+ return await response.json();
235
+ }
236
+ // ---------------------------------------------------------------------------
237
+ // Status / wait — proxies to the existing routes (no headless variant needed).
238
+ // ---------------------------------------------------------------------------
239
+ /**
240
+ * Fetch the latest known status for a submitted headless intent.
241
+ * This is a non-blocking read and may return `pending` before a
242
+ * solver has produced a fill transaction hash.
243
+ */
244
+ async getIntentStatus(intentId) {
245
+ const response = await fetch(`${this.providerUrl}/api/intent/status/${intentId}`);
246
+ if (!response.ok) {
247
+ throw new Error(`Status fetch failed (${response.status})`);
248
+ }
249
+ return await response.json();
250
+ }
251
+ /**
252
+ * Wait for a submitted headless intent to produce a status update and,
253
+ * when available, the final fill transaction hash. The wait endpoint
254
+ * needs the opaque `transactionResult` returned by submit because 1auth
255
+ * does not persist that SDK object in its database.
256
+ */
257
+ async waitForIntent(intentId, transactionResult) {
258
+ if (!transactionResult) {
259
+ throw new Error("waitForIntent requires submitResult.transactionResult");
260
+ }
261
+ const response = await fetch(`${this.providerUrl}/api/intent/wait/${intentId}`, {
262
+ method: "POST",
263
+ headers: { "Content-Type": "application/json" },
264
+ body: JSON.stringify({ transactionResult })
265
+ });
266
+ if (!response.ok) {
267
+ const errorData = await response.json().catch(() => ({}));
268
+ throw new Error(
269
+ errorData.details || errorData.error || `Wait fetch failed (${response.status})`
270
+ );
271
+ }
272
+ return await response.json();
273
+ }
274
+ // ---------------------------------------------------------------------------
275
+ // SmartSession install (one-time, passkey-signed)
276
+ // ---------------------------------------------------------------------------
277
+ /**
278
+ * Resolve the SmartSession install call(s) for `sessionKeyAddress`
279
+ * with the supplied `permissions`.
280
+ *
281
+ * Returns `{ install, sessionKeyHandle }`:
282
+ *
283
+ * - `install` is a `{ targetChain, calls }` pair the caller feeds
284
+ * straight into `OneAuthClient.sendIntent({ targetChain, calls })`
285
+ * so the user passkey-signs the install via the existing dialog.
286
+ * - `sessionKeyHandle` contains the deterministic `permissionId`
287
+ * plus metadata to persist in localStorage. Persist this BEFORE
288
+ * submitting the install so a refresh during signing doesn't
289
+ * lose the handle.
290
+ *
291
+ * If the validator is already installed on the user's account,
292
+ * `install.calls` is empty and `install.alreadyInstalled` is true.
293
+ * The caller should still persist `sessionKeyHandle` — the on-chain
294
+ * session enabling happens at first headless use via SmartSession's
295
+ * ENABLE-mode signature wrapping (see follow-up).
296
+ */
297
+ async installSmartSession(options) {
298
+ if (!options.username && !options.accountAddress) {
299
+ throw new Error(
300
+ "installSmartSession requires either `username` or `accountAddress`"
301
+ );
302
+ }
303
+ const accessTokenResult = await this.fetchAccessToken();
304
+ if (!accessTokenResult.ok) {
305
+ throw new Error(
306
+ `Sponsorship access token fetch failed: ${accessTokenResult.message}`
307
+ );
308
+ }
309
+ const body = {
310
+ username: options.username,
311
+ accountAddress: options.accountAddress,
312
+ targetChain: options.targetChain,
313
+ sessionKeyAddress: options.sessionKeyAddress,
314
+ permissions: options.permissions,
315
+ validUntil: options.validUntil,
316
+ validAfter: options.validAfter,
317
+ maxUses: options.maxUses,
318
+ enableSessionSignature: options.enableSessionSignature,
319
+ label: options.label,
320
+ auth: { accessToken: accessTokenResult.accessToken }
321
+ };
322
+ const response = await fetch(`${this.providerUrl}/api/sessions/install`, {
323
+ method: "POST",
324
+ headers: { "Content-Type": "application/json" },
325
+ body: JSON.stringify(body)
326
+ });
327
+ if (!response.ok) {
328
+ const errorData = await response.json().catch(() => ({}));
329
+ throw new Error(errorData.error || `Install failed (${response.status})`);
330
+ }
331
+ return await response.json();
332
+ }
333
+ };
334
+
335
+ // src/smart-session-signatures.ts
336
+ var import_accounts = require("viem/accounts");
337
+ var import_sdk = require("@rhinestone/sdk");
338
+ var import_smart_sessions = require("@rhinestone/sdk/smart-sessions");
339
+
340
+ // src/registry.ts
341
+ var import_viem = require("viem");
342
+ var viemChains = __toESM(require("viem/chains"));
343
+ var import_shared_configs = require("@rhinestone/shared-configs");
344
+ var env = typeof process !== "undefined" ? process.env : {};
345
+ var VIEM_CHAIN_BY_ID = /* @__PURE__ */ new Map();
346
+ for (const value of Object.values(viemChains)) {
347
+ if (typeof value !== "object" || value === null || !("id" in value) || !("name" in value)) continue;
348
+ const chain = value;
349
+ const existing = VIEM_CHAIN_BY_ID.get(chain.id);
350
+ if (!existing || existing.testnet && !chain.testnet) {
351
+ VIEM_CHAIN_BY_ID.set(chain.id, chain);
352
+ }
353
+ }
354
+ function isEvmRegistryEntry(entry) {
355
+ return entry?.vmType === "evm";
356
+ }
357
+ var REGISTRY_CHAIN_IDS = Object.entries(import_shared_configs.chainRegistry).filter(([, entry]) => isEvmRegistryEntry(entry)).map(([id]) => Number(id));
358
+ var SUPPORTED_CHAIN_IDS = new Set(REGISTRY_CHAIN_IDS);
359
+ function getChainById(chainId) {
360
+ if (!SUPPORTED_CHAIN_IDS.has(chainId)) {
361
+ throw new Error(`Unsupported chain ID: ${chainId}`);
362
+ }
363
+ const chain = VIEM_CHAIN_BY_ID.get(chainId);
364
+ if (!chain) {
365
+ throw new Error(`Unsupported chain ID: ${chainId}`);
366
+ }
367
+ return chain;
368
+ }
369
+
370
+ // src/smart-session-signatures.ts
371
+ function reviveBigIntStrings(value) {
372
+ if (Array.isArray(value)) return value.map((entry) => reviveBigIntStrings(entry));
373
+ if (value && typeof value === "object") {
374
+ return Object.fromEntries(
375
+ Object.entries(value).map(([key, entry]) => [key, reviveBigIntStrings(entry)])
376
+ );
377
+ }
378
+ if (typeof value === "string" && value.startsWith("__bigint:")) {
379
+ return BigInt(value.slice("__bigint:".length));
380
+ }
381
+ if (typeof value === "string" && /^\d+$/.test(value)) return BigInt(value);
382
+ return value;
383
+ }
384
+ function parsePreparedSignData(value) {
385
+ const prepared = JSON.parse(value, (_key, nested) => reviveBigIntStrings(nested));
386
+ const signData = prepared.quotes?.best?.signData;
387
+ if (!signData) {
388
+ throw new Error("Prepared headless intent is missing quotes.best.signData");
389
+ }
390
+ return signData;
391
+ }
392
+ function chainIdFromSignDataDomain(domainChainId) {
393
+ if (typeof domainChainId === "number" && Number.isSafeInteger(domainChainId)) {
394
+ return domainChainId;
395
+ }
396
+ if (typeof domainChainId === "bigint") return Number(domainChainId);
397
+ if (typeof domainChainId === "string" && /^\d+$/.test(domainChainId)) {
398
+ return Number(domainChainId);
399
+ }
400
+ return void 0;
401
+ }
402
+ function buildSessionForChain(args) {
403
+ return (0, import_smart_sessions.toSession)(
404
+ {
405
+ chain: getChainById(args.chainId),
406
+ owners: { type: "ecdsa", accounts: [(0, import_accounts.privateKeyToAccount)(args.privateKey)] },
407
+ permissions: reviveBigIntStrings(args.handle.permissions ?? []),
408
+ crossChainPermits: reviveBigIntStrings(args.handle.crossChainPermits ?? [])
409
+ },
410
+ // The production SmartSession module is deployed on testnets too. Never opt
411
+ // into SDK dev contracts for 1auth headless permissions.
412
+ { useDevContracts: false }
413
+ );
414
+ }
415
+ function buildSessionSigners(args) {
416
+ const chainIds = /* @__PURE__ */ new Set([args.prepared.targetChain]);
417
+ for (const typedData of args.signData.origin) {
418
+ const chainId = chainIdFromSignDataDomain(typedData.domain?.chainId);
419
+ if (chainId) chainIds.add(chainId);
420
+ }
421
+ const targetExecutionChainId = chainIdFromSignDataDomain(
422
+ args.signData.targetExecution?.domain?.chainId
423
+ );
424
+ if (targetExecutionChainId) chainIds.add(targetExecutionChainId);
425
+ return {
426
+ type: "experimental_session",
427
+ sessions: Object.fromEntries(
428
+ [...chainIds].map((chainId) => [
429
+ chainId,
430
+ {
431
+ session: buildSessionForChain({
432
+ privateKey: args.privateKey,
433
+ handle: args.handle,
434
+ chainId
435
+ })
436
+ }
437
+ ])
438
+ )
439
+ };
440
+ }
441
+ async function buildSmartSessionHeadlessSignatures(options) {
442
+ const signData = parsePreparedSignData(options.prepared.intentOp);
443
+ const account = await (0, import_sdk.createRhinestoneAccount)({
444
+ initData: { address: options.accountAddress },
445
+ owners: {
446
+ type: "ecdsa",
447
+ accounts: [(0, import_accounts.privateKeyToAccount)(options.privateKey)]
448
+ },
449
+ experimental_sessions: { enabled: true }
450
+ });
451
+ return account.signIntent(
452
+ signData,
453
+ getChainById(options.prepared.targetChain),
454
+ buildSessionSigners({
455
+ privateKey: options.privateKey,
456
+ handle: options.sessionKeyHandle,
457
+ prepared: options.prepared,
458
+ signData
459
+ })
460
+ );
461
+ }
462
+ // Annotate the CommonJS export names for ESM import in node:
463
+ 0 && (module.exports = {
464
+ OneAuthHeadlessClient,
465
+ buildSmartSessionHeadlessSignatures
466
+ });
467
+ //# sourceMappingURL=headless.js.map