@rhinestone/1auth 0.6.5 → 0.6.8
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/{chunk-IP2FG4WQ.mjs → chunk-SXISYG2P.mjs} +10 -24
- package/dist/chunk-SXISYG2P.mjs.map +1 -0
- package/dist/{client-hZxAAhcl.d.mts → client-BrMrhetG.d.mts} +407 -71
- package/dist/{client-hZxAAhcl.d.ts → client-BrMrhetG.d.ts} +407 -71
- package/dist/index.d.mts +114 -9
- package/dist/index.d.ts +114 -9
- package/dist/index.js +434 -122
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +426 -100
- package/dist/index.mjs.map +1 -1
- package/dist/provider-CDl9wYEc.d.mts +88 -0
- package/dist/provider-Dgv533YQ.d.ts +88 -0
- package/dist/react.d.mts +33 -15
- package/dist/react.d.ts +33 -15
- package/dist/react.js +6 -23
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +6 -23
- package/dist/react.mjs.map +1 -1
- package/dist/wagmi.d.mts +39 -3
- package/dist/wagmi.d.ts +39 -3
- package/dist/wagmi.js +107 -25
- package/dist/wagmi.js.map +1 -1
- package/dist/wagmi.mjs +99 -3
- package/dist/wagmi.mjs.map +1 -1
- package/package.json +1 -6
- package/dist/chunk-IP2FG4WQ.mjs.map +0 -1
- package/dist/provider-A89sCgGr.d.ts +0 -27
- package/dist/provider-B9GKBMC5.d.mts +0 -27
- package/dist/server.d.mts +0 -44
- package/dist/server.d.ts +0 -44
- package/dist/server.js +0 -145
- package/dist/server.js.map +0 -1
- package/dist/server.mjs +0 -119
- package/dist/server.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -199,6 +199,17 @@ var DEFAULT_EMBED_WIDTH = "400px";
|
|
|
199
199
|
var DEFAULT_EMBED_HEIGHT = "500px";
|
|
200
200
|
var DEFAULT_PROVIDER_URL = "https://passkey.1auth.box";
|
|
201
201
|
var OneAuthClient = class {
|
|
202
|
+
/**
|
|
203
|
+
* Create a new OneAuthClient.
|
|
204
|
+
*
|
|
205
|
+
* Normalizes the config (filling in default URLs), then immediately injects
|
|
206
|
+
* `<link rel="preconnect">` tags for the passkey domain so that DNS lookup
|
|
207
|
+
* and TLS handshake start before the first dialog is opened, shaving
|
|
208
|
+
* noticeable latency from the first user interaction.
|
|
209
|
+
*
|
|
210
|
+
* @param config - Client configuration including optional providerUrl, dialogUrl,
|
|
211
|
+
* clientId, theme, and redirect settings.
|
|
212
|
+
*/
|
|
202
213
|
constructor(config) {
|
|
203
214
|
const providerUrl = config.providerUrl || DEFAULT_PROVIDER_URL;
|
|
204
215
|
const dialogUrl = config.dialogUrl || providerUrl;
|
|
@@ -218,7 +229,16 @@ var OneAuthClient = class {
|
|
|
218
229
|
this.theme = theme;
|
|
219
230
|
}
|
|
220
231
|
/**
|
|
221
|
-
*
|
|
232
|
+
* Serialize the active theme into URL query parameters for the dialog.
|
|
233
|
+
*
|
|
234
|
+
* Merges the instance-level theme (set via constructor or `setTheme`) with any
|
|
235
|
+
* per-call override, so callers can temporarily change the appearance for a
|
|
236
|
+
* single dialog invocation without mutating shared state.
|
|
237
|
+
*
|
|
238
|
+
* @param overrideTheme - One-shot theme values that take precedence over the
|
|
239
|
+
* instance theme for this call only.
|
|
240
|
+
* @returns A URL-encoded query string (e.g. `"theme=dark&accent=%230090ff"`),
|
|
241
|
+
* or an empty string if no theme properties are set.
|
|
222
242
|
*/
|
|
223
243
|
getThemeParams(overrideTheme) {
|
|
224
244
|
const theme = { ...this.theme, ...overrideTheme };
|
|
@@ -232,15 +252,30 @@ var OneAuthClient = class {
|
|
|
232
252
|
return params.toString();
|
|
233
253
|
}
|
|
234
254
|
/**
|
|
235
|
-
*
|
|
236
|
-
*
|
|
255
|
+
* Resolve the URL of the dialog app (the Vite/Next.js frontend that renders
|
|
256
|
+
* the WebAuthn UI inside the iframe).
|
|
257
|
+
*
|
|
258
|
+
* `dialogUrl` is a separate config option to support split deployments where
|
|
259
|
+
* the API server and the dialog frontend run at different origins. Falls back
|
|
260
|
+
* to `providerUrl` when not explicitly configured — the common case.
|
|
261
|
+
*
|
|
262
|
+
* @returns The base URL used when constructing all dialog endpoint paths.
|
|
237
263
|
*/
|
|
238
264
|
getDialogUrl() {
|
|
239
265
|
return this.config.dialogUrl || this.config.providerUrl;
|
|
240
266
|
}
|
|
241
267
|
/**
|
|
242
|
-
*
|
|
243
|
-
*
|
|
268
|
+
* Extract the trusted origin used to validate incoming postMessage events.
|
|
269
|
+
*
|
|
270
|
+
* All `window.addEventListener("message", ...)` handlers in this class check
|
|
271
|
+
* `event.origin` against this value to prevent cross-origin spoofing. Wraps
|
|
272
|
+
* `getDialogUrl()` in a `new URL()` parse so that paths and query strings are
|
|
273
|
+
* stripped — only the scheme + host + port are compared.
|
|
274
|
+
*
|
|
275
|
+
* Falls back to the raw dialog URL string if URL parsing fails (e.g. during
|
|
276
|
+
* unit tests with non-standard URL formats).
|
|
277
|
+
*
|
|
278
|
+
* @returns The scheme + host + optional port of the dialog app (e.g. `"https://passkey.1auth.box"`).
|
|
244
279
|
*/
|
|
245
280
|
getDialogOrigin() {
|
|
246
281
|
const dialogUrl = this.getDialogUrl();
|
|
@@ -262,6 +297,24 @@ var OneAuthClient = class {
|
|
|
262
297
|
getClientId() {
|
|
263
298
|
return this.config.clientId;
|
|
264
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Poll the intent status endpoint until a transaction hash appears or the
|
|
302
|
+
* intent reaches a terminal failure state.
|
|
303
|
+
*
|
|
304
|
+
* This is used after `sendIntent` resolves (with `waitForHash: true`) to
|
|
305
|
+
* continue waiting for the on-chain hash even after the dialog has been
|
|
306
|
+
* dismissed. It is intentionally separate from the in-dialog polling loop so
|
|
307
|
+
* callers that don't need the hash can skip it entirely.
|
|
308
|
+
*
|
|
309
|
+
* Errors during individual poll attempts are swallowed so that transient
|
|
310
|
+
* network issues don't abort the wait prematurely.
|
|
311
|
+
*
|
|
312
|
+
* @param intentId - The Rhinestone intent ID returned by the execute endpoint.
|
|
313
|
+
* @param options.timeoutMs - Maximum wait time in milliseconds (default 120 000).
|
|
314
|
+
* @param options.intervalMs - Time between polls in milliseconds (default 2 000).
|
|
315
|
+
* @returns The transaction hash string, or `undefined` if the deadline was
|
|
316
|
+
* reached or the intent failed/expired before a hash was produced.
|
|
317
|
+
*/
|
|
265
318
|
async waitForTransactionHash(intentId, options = {}) {
|
|
266
319
|
const timeoutMs = options.timeoutMs ?? 12e4;
|
|
267
320
|
const intervalMs = options.intervalMs ?? 2e3;
|
|
@@ -667,25 +720,7 @@ var OneAuthClient = class {
|
|
|
667
720
|
* ```
|
|
668
721
|
*/
|
|
669
722
|
async sendIntent(options) {
|
|
670
|
-
const
|
|
671
|
-
...options.signedIntent,
|
|
672
|
-
merchantId: options.signedIntent.merchantId || options.signedIntent.developerId
|
|
673
|
-
} : void 0;
|
|
674
|
-
const username = signedIntent?.username || options.username;
|
|
675
|
-
const targetChain = signedIntent?.targetChain || options.targetChain;
|
|
676
|
-
const calls = signedIntent?.calls || options.calls;
|
|
677
|
-
if (signedIntent && !signedIntent.merchantId) {
|
|
678
|
-
return {
|
|
679
|
-
success: false,
|
|
680
|
-
intentId: "",
|
|
681
|
-
status: "failed",
|
|
682
|
-
error: {
|
|
683
|
-
code: "INVALID_OPTIONS",
|
|
684
|
-
message: "Signed intent requires developerId (clientId)"
|
|
685
|
-
}
|
|
686
|
-
};
|
|
687
|
-
}
|
|
688
|
-
const accountAddress = signedIntent?.accountAddress || options.accountAddress;
|
|
723
|
+
const { username, accountAddress, targetChain, calls } = options;
|
|
689
724
|
if (!username && !accountAddress) {
|
|
690
725
|
return {
|
|
691
726
|
success: false,
|
|
@@ -693,7 +728,7 @@ var OneAuthClient = class {
|
|
|
693
728
|
status: "failed",
|
|
694
729
|
error: {
|
|
695
730
|
code: "INVALID_OPTIONS",
|
|
696
|
-
message: "Either username
|
|
731
|
+
message: "Either username or accountAddress is required"
|
|
697
732
|
}
|
|
698
733
|
};
|
|
699
734
|
}
|
|
@@ -704,7 +739,7 @@ var OneAuthClient = class {
|
|
|
704
739
|
status: "failed",
|
|
705
740
|
error: {
|
|
706
741
|
code: "INVALID_OPTIONS",
|
|
707
|
-
message: "targetChain and calls are required
|
|
742
|
+
message: "targetChain and calls are required"
|
|
708
743
|
}
|
|
709
744
|
};
|
|
710
745
|
}
|
|
@@ -713,11 +748,11 @@ var OneAuthClient = class {
|
|
|
713
748
|
amount: r.amount.toString()
|
|
714
749
|
}));
|
|
715
750
|
let prepareResponse;
|
|
716
|
-
const requestBody =
|
|
717
|
-
username
|
|
718
|
-
accountAddress
|
|
719
|
-
targetChain
|
|
720
|
-
calls
|
|
751
|
+
const requestBody = {
|
|
752
|
+
username,
|
|
753
|
+
accountAddress,
|
|
754
|
+
targetChain,
|
|
755
|
+
calls,
|
|
721
756
|
tokenRequests: serializedTokenRequests,
|
|
722
757
|
sourceAssets: options.sourceAssets,
|
|
723
758
|
sourceChainId: options.sourceChainId,
|
|
@@ -833,7 +868,6 @@ var OneAuthClient = class {
|
|
|
833
868
|
dialogOrigin,
|
|
834
869
|
// Refresh callback - called when dialog requests a quote refresh
|
|
835
870
|
async () => {
|
|
836
|
-
console.log("[SDK] Dialog requested quote refresh, re-preparing intent");
|
|
837
871
|
try {
|
|
838
872
|
const refreshResponse = await fetch(`${this.config.providerUrl}/api/intent/prepare`, {
|
|
839
873
|
method: "POST",
|
|
@@ -1215,7 +1249,6 @@ var OneAuthClient = class {
|
|
|
1215
1249
|
if (event.origin !== dialogOrigin) return;
|
|
1216
1250
|
const message = event.data;
|
|
1217
1251
|
if (message?.type === "PASSKEY_REFRESH_QUOTE") {
|
|
1218
|
-
console.log("[SDK] Batch dialog requested quote refresh, re-preparing all intents");
|
|
1219
1252
|
try {
|
|
1220
1253
|
const refreshResponse = await fetch(`${this.config.providerUrl}/api/intent/batch-prepare`, {
|
|
1221
1254
|
method: "POST",
|
|
@@ -1313,7 +1346,22 @@ var OneAuthClient = class {
|
|
|
1313
1346
|
);
|
|
1314
1347
|
}
|
|
1315
1348
|
/**
|
|
1316
|
-
*
|
|
1349
|
+
* Listen for a signing result that belongs to a specific `requestId`.
|
|
1350
|
+
*
|
|
1351
|
+
* Used by legacy server-side signing request flows (popup/embed/modal) where
|
|
1352
|
+
* the dialog was pre-loaded with a signing request created via the API. The
|
|
1353
|
+
* `requestId` filter is needed because multiple dialogs may be open or there
|
|
1354
|
+
* may be stale messages from a previous dialog in the queue.
|
|
1355
|
+
*
|
|
1356
|
+
* Resolves on `PASSKEY_SIGNING_RESULT` matching `requestId`, or on
|
|
1357
|
+
* `PASSKEY_CLOSE` (user dismissed the dialog).
|
|
1358
|
+
*
|
|
1359
|
+
* @param requestId - The signing request ID to match against incoming messages.
|
|
1360
|
+
* @param dialog - The `<dialog>` element (opened before this call) used to
|
|
1361
|
+
* `showModal()` so the dialog becomes interactive.
|
|
1362
|
+
* @param _iframe - Unused; kept for signature consistency with other wait helpers.
|
|
1363
|
+
* @param cleanup - Idempotent teardown function that closes and removes the dialog.
|
|
1364
|
+
* @returns A `SigningResult` discriminated union.
|
|
1317
1365
|
*/
|
|
1318
1366
|
waitForIntentSigningResponse(requestId, dialog, _iframe, cleanup) {
|
|
1319
1367
|
const dialogOrigin = this.getDialogOrigin();
|
|
@@ -1358,18 +1406,30 @@ var OneAuthClient = class {
|
|
|
1358
1406
|
});
|
|
1359
1407
|
}
|
|
1360
1408
|
/**
|
|
1361
|
-
*
|
|
1409
|
+
* Listen for a signing result from the currently open modal dialog.
|
|
1410
|
+
*
|
|
1411
|
+
* Unlike `waitForIntentSigningResponse`, this variant does not filter by
|
|
1412
|
+
* `requestId` because the inline intent flow (sendIntent / signMessage /
|
|
1413
|
+
* signTypedData) owns the dialog exclusively — there is no risk of collisions
|
|
1414
|
+
* from other dialogs.
|
|
1415
|
+
*
|
|
1416
|
+
* Handles two result shapes:
|
|
1417
|
+
* - New "secure flow": dialog executed the intent server-side and returns
|
|
1418
|
+
* only an `intentId` (no signature exposed to the SDK).
|
|
1419
|
+
* - Legacy flow: dialog returns a raw `WebAuthnSignature` for the SDK to
|
|
1420
|
+
* forward to the execute endpoint.
|
|
1421
|
+
*
|
|
1422
|
+
* @param dialog - The `<dialog>` element wrapping the signing iframe.
|
|
1423
|
+
* @param _iframe - Unused; kept for signature consistency with other wait helpers.
|
|
1424
|
+
* @param cleanup - Idempotent teardown that closes and removes the dialog.
|
|
1425
|
+
* @returns A `SigningResult` extended with an optional `signedHash` field
|
|
1426
|
+
* populated when the dialog performs message signing.
|
|
1362
1427
|
*/
|
|
1363
1428
|
waitForSigningResponse(dialog, _iframe, cleanup) {
|
|
1364
1429
|
const dialogOrigin = this.getDialogOrigin();
|
|
1365
|
-
console.log("[SDK] waitForSigningResponse, expecting origin:", dialogOrigin);
|
|
1366
1430
|
return new Promise((resolve) => {
|
|
1367
1431
|
const handleMessage = (event) => {
|
|
1368
|
-
|
|
1369
|
-
if (event.origin !== dialogOrigin) {
|
|
1370
|
-
console.log("[SDK] Origin mismatch, ignoring. Expected:", dialogOrigin, "Got:", event.origin);
|
|
1371
|
-
return;
|
|
1372
|
-
}
|
|
1432
|
+
if (event.origin !== dialogOrigin) return;
|
|
1373
1433
|
const message = event.data;
|
|
1374
1434
|
const payload = message?.data;
|
|
1375
1435
|
if (message?.type === "PASSKEY_SIGNING_RESULT") {
|
|
@@ -1411,17 +1471,34 @@ var OneAuthClient = class {
|
|
|
1411
1471
|
});
|
|
1412
1472
|
}
|
|
1413
1473
|
/**
|
|
1414
|
-
*
|
|
1415
|
-
*
|
|
1474
|
+
* Listen for a signing result while also handling quote-refresh requests.
|
|
1475
|
+
*
|
|
1476
|
+
* Quotes from the Rhinestone orchestrator have a short TTL (typically ~60 s).
|
|
1477
|
+
* When the user takes too long to review and the quote expires, the dialog
|
|
1478
|
+
* sends `PASSKEY_REFRESH_QUOTE`. This method intercepts that message, calls
|
|
1479
|
+
* the provided `onRefresh` callback to fetch a new quote, and replies with
|
|
1480
|
+
* either `PASSKEY_REFRESH_COMPLETE` (success) or `PASSKEY_REFRESH_ERROR`
|
|
1481
|
+
* (failure) — allowing the dialog to stay open and show the updated fees
|
|
1482
|
+
* without requiring a full restart.
|
|
1483
|
+
*
|
|
1484
|
+
* Once the user confirms or rejects, the promise resolves with the signing
|
|
1485
|
+
* result exactly as `waitForSigningResponse` would.
|
|
1486
|
+
*
|
|
1487
|
+
* @param dialog - The `<dialog>` element wrapping the signing iframe.
|
|
1488
|
+
* @param iframe - The iframe element; used to post refresh messages back.
|
|
1489
|
+
* @param cleanup - Idempotent teardown that closes and removes the dialog.
|
|
1490
|
+
* @param dialogOrigin - Trusted origin for message validation (passed in to
|
|
1491
|
+
* avoid redundant `getDialogOrigin()` calls from the hot path).
|
|
1492
|
+
* @param onRefresh - Async callback that fetches a fresh quote and returns the
|
|
1493
|
+
* updated intent fields, or `null` if the refresh failed.
|
|
1494
|
+
* @returns A `SigningResult` extended with an optional `signedHash`.
|
|
1416
1495
|
*/
|
|
1417
1496
|
waitForSigningWithRefresh(dialog, iframe, cleanup, dialogOrigin, onRefresh) {
|
|
1418
|
-
console.log("[SDK] waitForSigningWithRefresh, expecting origin:", dialogOrigin);
|
|
1419
1497
|
return new Promise((resolve) => {
|
|
1420
1498
|
const handleMessage = async (event) => {
|
|
1421
1499
|
if (event.origin !== dialogOrigin) return;
|
|
1422
1500
|
const message = event.data;
|
|
1423
1501
|
if (message?.type === "PASSKEY_REFRESH_QUOTE") {
|
|
1424
|
-
console.log("[SDK] Received quote refresh request from dialog");
|
|
1425
1502
|
const refreshedData = await onRefresh();
|
|
1426
1503
|
if (refreshedData) {
|
|
1427
1504
|
iframe.contentWindow?.postMessage({
|
|
@@ -1476,7 +1553,20 @@ var OneAuthClient = class {
|
|
|
1476
1553
|
});
|
|
1477
1554
|
}
|
|
1478
1555
|
/**
|
|
1479
|
-
* Wait for the dialog to be closed
|
|
1556
|
+
* Wait for the dialog to be explicitly closed by the user or the iframe.
|
|
1557
|
+
*
|
|
1558
|
+
* Resolves on either:
|
|
1559
|
+
* - `PASSKEY_CLOSE` postMessage from the iframe (user clicked the X button
|
|
1560
|
+
* or the dialog programmatically closed itself after showing a result).
|
|
1561
|
+
* - The native `<dialog> close` event (escape key or `dialog.close()` call).
|
|
1562
|
+
*
|
|
1563
|
+
* Calling `cleanup()` before awaiting this is safe — both resolution paths
|
|
1564
|
+
* call `cleanup()` internally but it is idempotent. The primary use case is
|
|
1565
|
+
* keeping the dialog open while the SDK polls for a transaction hash, then
|
|
1566
|
+
* showing the final success/error state before letting the user dismiss.
|
|
1567
|
+
*
|
|
1568
|
+
* @param dialog - The `<dialog>` element to watch.
|
|
1569
|
+
* @param cleanup - Idempotent teardown that closes and removes the dialog.
|
|
1480
1570
|
*/
|
|
1481
1571
|
waitForDialogClose(dialog, cleanup) {
|
|
1482
1572
|
const dialogOrigin = this.getDialogOrigin();
|
|
@@ -1500,7 +1590,17 @@ var OneAuthClient = class {
|
|
|
1500
1590
|
});
|
|
1501
1591
|
}
|
|
1502
1592
|
/**
|
|
1503
|
-
* Inject a preconnect
|
|
1593
|
+
* Inject a `<link rel="preconnect">` tag for the given URL's origin.
|
|
1594
|
+
*
|
|
1595
|
+
* Browsers use preconnect hints to resolve DNS, perform the TCP handshake,
|
|
1596
|
+
* and negotiate TLS before a resource is actually requested, reducing
|
|
1597
|
+
* time-to-first-byte when the dialog iframe loads. The tag is deduplicated —
|
|
1598
|
+
* if one already exists for the same origin it will not be added again.
|
|
1599
|
+
*
|
|
1600
|
+
* Only called in browser environments (guarded by `typeof document` in the
|
|
1601
|
+
* constructor). Invalid URLs are silently ignored.
|
|
1602
|
+
*
|
|
1603
|
+
* @param url - Any URL whose origin should be preconnected to.
|
|
1504
1604
|
*/
|
|
1505
1605
|
injectPreconnect(url) {
|
|
1506
1606
|
try {
|
|
@@ -1515,8 +1615,24 @@ var OneAuthClient = class {
|
|
|
1515
1615
|
}
|
|
1516
1616
|
}
|
|
1517
1617
|
/**
|
|
1518
|
-
* Wait for the dialog iframe to signal ready
|
|
1519
|
-
*
|
|
1618
|
+
* Wait for the dialog iframe to signal ready, but defer sending `PASSKEY_INIT`
|
|
1619
|
+
* until the caller decides the time is right.
|
|
1620
|
+
*
|
|
1621
|
+
* This is the deferred variant of `waitForDialogReady`, used by flows that run
|
|
1622
|
+
* the dialog and a background API call in parallel (the "two-phase" approach).
|
|
1623
|
+
* Rather than blocking until both the iframe is ready AND the API call is done,
|
|
1624
|
+
* this method resolves as soon as `PASSKEY_READY` arrives and returns a
|
|
1625
|
+
* `sendInit` callback. The caller invokes `sendInit` once prepare data is
|
|
1626
|
+
* available, which may happen before or after the iframe is ready.
|
|
1627
|
+
*
|
|
1628
|
+
* Timeout: if the iframe never signals ready within 10 seconds (e.g. network
|
|
1629
|
+
* error, origin mismatch), resolves with `{ ready: false }` and calls cleanup.
|
|
1630
|
+
*
|
|
1631
|
+
* @param dialog - The `<dialog>` element wrapping the iframe.
|
|
1632
|
+
* @param iframe - The iframe element that will receive `PASSKEY_INIT`.
|
|
1633
|
+
* @param cleanup - Idempotent teardown that closes and removes the dialog.
|
|
1634
|
+
* @returns `{ ready: true, sendInit }` when the iframe is ready, or
|
|
1635
|
+
* `{ ready: false }` if the dialog was closed or timed out first.
|
|
1520
1636
|
*/
|
|
1521
1637
|
waitForDialogReadyDeferred(dialog, iframe, cleanup) {
|
|
1522
1638
|
const dialogOrigin = this.getDialogOrigin();
|
|
@@ -1562,8 +1678,23 @@ var OneAuthClient = class {
|
|
|
1562
1678
|
});
|
|
1563
1679
|
}
|
|
1564
1680
|
/**
|
|
1565
|
-
*
|
|
1566
|
-
*
|
|
1681
|
+
* Call the passkey service to obtain a Rhinestone orchestrator quote for an
|
|
1682
|
+
* intent (a single target-chain transaction or swap).
|
|
1683
|
+
*
|
|
1684
|
+
* The service contacts the Rhinestone orchestrator, which returns a signed
|
|
1685
|
+
* `intentOp` structure containing the quote, fees, and a WebAuthn challenge
|
|
1686
|
+
* the user must sign to authorize execution.
|
|
1687
|
+
*
|
|
1688
|
+
* The `X-Origin-Tier` response header is forwarded to the dialog so it can
|
|
1689
|
+
* display tier-specific UI (e.g. "Free" vs "Premium" badge).
|
|
1690
|
+
*
|
|
1691
|
+
* Side effect: if the server returns "User not found", the cached user entry
|
|
1692
|
+
* is removed from `localStorage` to force re-authentication.
|
|
1693
|
+
*
|
|
1694
|
+
* @param requestBody - Serialized intent options (bigint amounts converted to
|
|
1695
|
+
* strings before this call).
|
|
1696
|
+
* @returns On success: `{ success: true, data: PrepareIntentResponse, tier }`.
|
|
1697
|
+
* On failure: `{ success: false, error: { code, message } }`.
|
|
1567
1698
|
*/
|
|
1568
1699
|
async prepareIntent(requestBody) {
|
|
1569
1700
|
try {
|
|
@@ -1599,7 +1730,21 @@ var OneAuthClient = class {
|
|
|
1599
1730
|
}
|
|
1600
1731
|
}
|
|
1601
1732
|
/**
|
|
1602
|
-
*
|
|
1733
|
+
* Call the passkey service to obtain orchestrator quotes for all intents in a
|
|
1734
|
+
* batch, returning a single shared WebAuthn challenge.
|
|
1735
|
+
*
|
|
1736
|
+
* The service prepares each intent independently and assembles a merkle tree
|
|
1737
|
+
* whose root becomes the challenge. Signing that root once authorizes every
|
|
1738
|
+
* intent in the batch. Partially-failed batches are supported: the response
|
|
1739
|
+
* includes both `intents` (succeeded) and `failedIntents` (per-intent errors),
|
|
1740
|
+
* so the dialog can still show the successful subset for signing.
|
|
1741
|
+
*
|
|
1742
|
+
* Side effect: same "User not found" localStorage cleanup as `prepareIntent`.
|
|
1743
|
+
*
|
|
1744
|
+
* @param requestBody - Serialized batch options (bigint amounts converted to
|
|
1745
|
+
* strings before this call).
|
|
1746
|
+
* @returns On success: `{ success: true, data: PrepareBatchIntentResponse, tier }`.
|
|
1747
|
+
* On failure: `{ success: false, error, failedIntents? }`.
|
|
1603
1748
|
*/
|
|
1604
1749
|
async prepareBatchIntent(requestBody) {
|
|
1605
1750
|
try {
|
|
@@ -1627,7 +1772,15 @@ var OneAuthClient = class {
|
|
|
1627
1772
|
}
|
|
1628
1773
|
}
|
|
1629
1774
|
/**
|
|
1630
|
-
*
|
|
1775
|
+
* Forward a prepare-phase error to the dialog iframe so it can display a
|
|
1776
|
+
* human-readable failure message instead of hanging on the loading state.
|
|
1777
|
+
*
|
|
1778
|
+
* The dialog listens for `PASSKEY_PREPARE_ERROR` and transitions to an error
|
|
1779
|
+
* view. The user can then dismiss the dialog, at which point
|
|
1780
|
+
* `waitForDialogClose` resolves and the SDK returns the error to the caller.
|
|
1781
|
+
*
|
|
1782
|
+
* @param iframe - The iframe element to post the error to.
|
|
1783
|
+
* @param error - Human-readable error message from the prepare response.
|
|
1631
1784
|
*/
|
|
1632
1785
|
sendPrepareError(iframe, error) {
|
|
1633
1786
|
const dialogOrigin = this.getDialogOrigin();
|
|
@@ -1810,13 +1963,6 @@ var OneAuthClient = class {
|
|
|
1810
1963
|
};
|
|
1811
1964
|
}
|
|
1812
1965
|
const toTokenAddress = toTokenResult.address;
|
|
1813
|
-
console.log("[SDK sendSwap] Token resolution:", {
|
|
1814
|
-
fromToken: options.fromToken ?? "Any",
|
|
1815
|
-
fromTokenAddress: fromTokenAddress ?? "orchestrator picks",
|
|
1816
|
-
toToken: options.toToken,
|
|
1817
|
-
toTokenAddress,
|
|
1818
|
-
targetChain: options.targetChain
|
|
1819
|
-
});
|
|
1820
1966
|
const formatTokenLabel = (token, fallback) => {
|
|
1821
1967
|
if (!token.startsWith("0x")) {
|
|
1822
1968
|
return token;
|
|
@@ -1845,16 +1991,10 @@ var OneAuthClient = class {
|
|
|
1845
1991
|
const match = getSupportedTokens(chainId).find(
|
|
1846
1992
|
(t) => t.symbol.toUpperCase() === symbol.toUpperCase()
|
|
1847
1993
|
);
|
|
1848
|
-
if (match)
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
}
|
|
1852
|
-
const decimals = (0, import_sdk.getTokenDecimals)(symbol, chainId);
|
|
1853
|
-
console.log(`[SDK] getTokenDecimals(${symbol}, ${chainId}) = ${decimals}`);
|
|
1854
|
-
return decimals;
|
|
1855
|
-
} catch (e) {
|
|
1994
|
+
if (match) return match.decimals;
|
|
1995
|
+
return (0, import_sdk.getTokenDecimals)(symbol, chainId);
|
|
1996
|
+
} catch {
|
|
1856
1997
|
const upperSymbol = symbol.toUpperCase();
|
|
1857
|
-
console.warn(`[SDK] getTokenDecimals failed for ${symbol}, using fallback`, e);
|
|
1858
1998
|
return KNOWN_DECIMALS[upperSymbol] ?? 18;
|
|
1859
1999
|
}
|
|
1860
2000
|
};
|
|
@@ -1864,13 +2004,6 @@ var OneAuthClient = class {
|
|
|
1864
2004
|
token: toTokenAddress,
|
|
1865
2005
|
amount: (0, import_viem2.parseUnits)(options.amount, toDecimals)
|
|
1866
2006
|
}];
|
|
1867
|
-
console.log("[SDK sendSwap] Building intent:", {
|
|
1868
|
-
isBridge,
|
|
1869
|
-
isFromNativeEth,
|
|
1870
|
-
isToNativeEth,
|
|
1871
|
-
toDecimals,
|
|
1872
|
-
tokenRequests
|
|
1873
|
-
});
|
|
1874
2007
|
const result = await this.sendIntent({
|
|
1875
2008
|
username: options.username,
|
|
1876
2009
|
targetChain: options.targetChain,
|
|
@@ -2131,6 +2264,20 @@ var OneAuthClient = class {
|
|
|
2131
2264
|
const iframe = this.createEmbed(request.requestId, embedOptions);
|
|
2132
2265
|
return this.waitForEmbedResponse(request.requestId, iframe, embedOptions);
|
|
2133
2266
|
}
|
|
2267
|
+
/**
|
|
2268
|
+
* Create and append a signing iframe to a caller-supplied container element.
|
|
2269
|
+
*
|
|
2270
|
+
* Used by the `signWithEmbed` flow where the integrator wants the signing UI
|
|
2271
|
+
* to appear inline on their page rather than in a modal overlay. The iframe
|
|
2272
|
+
* loads a pre-created signing request URL and fires `options.onReady` once
|
|
2273
|
+
* the page has loaded.
|
|
2274
|
+
*
|
|
2275
|
+
* @param requestId - The signing request ID; used to construct the iframe src
|
|
2276
|
+
* and give it a stable DOM id for later removal via `removeEmbed`.
|
|
2277
|
+
* @param options - Embed configuration including the container element,
|
|
2278
|
+
* optional dimensions, and lifecycle callbacks.
|
|
2279
|
+
* @returns The created `<iframe>` element (already appended to the container).
|
|
2280
|
+
*/
|
|
2134
2281
|
createEmbed(requestId, options) {
|
|
2135
2282
|
const dialogUrl = this.getDialogUrl();
|
|
2136
2283
|
const iframe = document.createElement("iframe");
|
|
@@ -2148,6 +2295,19 @@ var OneAuthClient = class {
|
|
|
2148
2295
|
options.container.appendChild(iframe);
|
|
2149
2296
|
return iframe;
|
|
2150
2297
|
}
|
|
2298
|
+
/**
|
|
2299
|
+
* Listen for a signing result from an embedded (inline) signing iframe.
|
|
2300
|
+
*
|
|
2301
|
+
* Matches incoming `PASSKEY_SIGNING_RESULT` messages against `requestId`
|
|
2302
|
+
* to avoid reacting to messages from other iframes on the page. On resolution
|
|
2303
|
+
* (success or failure), the iframe is removed from the DOM and
|
|
2304
|
+
* `embedOptions.onClose` is invoked.
|
|
2305
|
+
*
|
|
2306
|
+
* @param requestId - The signing request ID to match against incoming messages.
|
|
2307
|
+
* @param iframe - The embedded signing iframe.
|
|
2308
|
+
* @param embedOptions - Embed configuration; `onClose` is called after cleanup.
|
|
2309
|
+
* @returns A `SigningResult` discriminated union.
|
|
2310
|
+
*/
|
|
2151
2311
|
waitForEmbedResponse(requestId, iframe, embedOptions) {
|
|
2152
2312
|
const dialogOrigin = this.getDialogOrigin();
|
|
2153
2313
|
return new Promise((resolve) => {
|
|
@@ -2242,6 +2402,22 @@ var OneAuthClient = class {
|
|
|
2242
2402
|
const data = await response.json();
|
|
2243
2403
|
return data.passkeys;
|
|
2244
2404
|
}
|
|
2405
|
+
/**
|
|
2406
|
+
* Register a signing request with the passkey service and receive a
|
|
2407
|
+
* short-lived `requestId`.
|
|
2408
|
+
*
|
|
2409
|
+
* Used by the legacy popup, redirect, and embed flows. The passkey service
|
|
2410
|
+
* stores the challenge and metadata server-side so the dialog page can fetch
|
|
2411
|
+
* them by `requestId` without relying on URL parameters alone. This avoids
|
|
2412
|
+
* exposing potentially large challenge payloads in query strings.
|
|
2413
|
+
*
|
|
2414
|
+
* @param options - The signing options (challenge, username, description, etc.).
|
|
2415
|
+
* @param mode - How the dialog will be opened (`"popup"`, `"redirect"`, or `"embed"`).
|
|
2416
|
+
* @param redirectUrl - Only required for `"redirect"` mode; the URL the dialog
|
|
2417
|
+
* will navigate back to after signing.
|
|
2418
|
+
* @returns The created signing request with its unique `requestId`.
|
|
2419
|
+
* @throws If the API call fails.
|
|
2420
|
+
*/
|
|
2245
2421
|
async createSigningRequest(options, mode, redirectUrl) {
|
|
2246
2422
|
const response = await fetch(
|
|
2247
2423
|
`${this.config.providerUrl}/api/sign/request`,
|
|
@@ -2268,6 +2444,17 @@ var OneAuthClient = class {
|
|
|
2268
2444
|
}
|
|
2269
2445
|
return response.json();
|
|
2270
2446
|
}
|
|
2447
|
+
/**
|
|
2448
|
+
* Open a centered popup window for the signing or auth dialog.
|
|
2449
|
+
*
|
|
2450
|
+
* Positions the popup near the top of the current window (50px from the top)
|
|
2451
|
+
* and horizontally centered relative to the browser window. Uses `popup=true`
|
|
2452
|
+
* to request a minimal chrome popup (no address bar) on browsers that support
|
|
2453
|
+
* the Window Management API.
|
|
2454
|
+
*
|
|
2455
|
+
* @param url - The full URL to open in the popup.
|
|
2456
|
+
* @returns The popup `Window` reference, or `null` if the browser blocked it.
|
|
2457
|
+
*/
|
|
2271
2458
|
openPopup(url) {
|
|
2272
2459
|
const left = window.screenX + (window.outerWidth - POPUP_WIDTH) / 2;
|
|
2273
2460
|
const top = window.screenY + 50;
|
|
@@ -2278,9 +2465,24 @@ var OneAuthClient = class {
|
|
|
2278
2465
|
);
|
|
2279
2466
|
}
|
|
2280
2467
|
/**
|
|
2281
|
-
* Wait for the dialog iframe to signal ready, then send init data.
|
|
2282
|
-
*
|
|
2283
|
-
*
|
|
2468
|
+
* Wait for the dialog iframe to signal ready, then immediately send init data.
|
|
2469
|
+
*
|
|
2470
|
+
* This is the synchronous-init variant: `initMessage` is available at call
|
|
2471
|
+
* time, so it can be posted as soon as `PASSKEY_READY` arrives. Use
|
|
2472
|
+
* `waitForDialogReadyDeferred` when init data depends on an in-flight API call.
|
|
2473
|
+
*
|
|
2474
|
+
* Also handles early close (X button, escape key, backdrop click) during the
|
|
2475
|
+
* ready phase so those paths resolve cleanly without leaking event listeners.
|
|
2476
|
+
*
|
|
2477
|
+
* Timeout: resolves `false` after 10 seconds if the iframe never signals ready
|
|
2478
|
+
* (e.g. origin mismatch or network error loading the dialog app).
|
|
2479
|
+
*
|
|
2480
|
+
* @param dialog - The `<dialog>` element wrapping the iframe.
|
|
2481
|
+
* @param iframe - The iframe element that will receive `PASSKEY_INIT`.
|
|
2482
|
+
* @param cleanup - Idempotent teardown that closes and removes the dialog.
|
|
2483
|
+
* @param initMessage - The `PASSKEY_INIT` payload to send when ready.
|
|
2484
|
+
* @returns `true` if the dialog is ready and init was sent; `false` if the
|
|
2485
|
+
* dialog was closed or timed out before becoming ready.
|
|
2284
2486
|
*/
|
|
2285
2487
|
waitForDialogReady(dialog, iframe, cleanup, initMessage) {
|
|
2286
2488
|
const dialogOrigin = this.getDialogOrigin();
|
|
@@ -2323,10 +2525,33 @@ var OneAuthClient = class {
|
|
|
2323
2525
|
});
|
|
2324
2526
|
}
|
|
2325
2527
|
/**
|
|
2326
|
-
* Create a
|
|
2327
|
-
*
|
|
2328
|
-
*
|
|
2329
|
-
*
|
|
2528
|
+
* Create and open a full-viewport `<dialog>` containing a passkey iframe.
|
|
2529
|
+
*
|
|
2530
|
+
* The SDK owns only the transparent outer shell; all visible UI (backdrop,
|
|
2531
|
+
* card, animations, close button) is rendered by the passkey app inside the
|
|
2532
|
+
* iframe. This approach means design changes can be shipped server-side
|
|
2533
|
+
* without updating SDK consumers.
|
|
2534
|
+
*
|
|
2535
|
+
* Lifecycle:
|
|
2536
|
+
* 1. A themed "Loading…" overlay is injected and shown immediately while the
|
|
2537
|
+
* iframe loads, matching the exact visual structure of the passkey app's
|
|
2538
|
+
* TitleBar + IndeterminateLoader so the transition is seamless.
|
|
2539
|
+
* 2. When the iframe sends `PASSKEY_RENDERED`, the overlay fades out and
|
|
2540
|
+
* the iframe becomes fully visible.
|
|
2541
|
+
* 3. The returned `cleanup` function tears down all event listeners,
|
|
2542
|
+
* disconnects the MutationObserver, closes the `<dialog>`, and removes
|
|
2543
|
+
* it from the DOM. It is idempotent — safe to call multiple times.
|
|
2544
|
+
*
|
|
2545
|
+
* Browser quirks handled:
|
|
2546
|
+
* - The 1Password extension sets `inert` on the `<dialog>`, making it
|
|
2547
|
+
* non-interactive. A MutationObserver removes the attribute immediately.
|
|
2548
|
+
* - Password managers may also set `inert` on dialog siblings; cleanup
|
|
2549
|
+
* restores those as well.
|
|
2550
|
+
* - The iframe sandbox includes `allow-popups-to-escape-sandbox` so that
|
|
2551
|
+
* 1Password's popup UI can render outside the sandboxed context.
|
|
2552
|
+
*
|
|
2553
|
+
* @param url - The full URL (including query params) to load in the iframe.
|
|
2554
|
+
* @returns References to the dialog, iframe, and a cleanup function.
|
|
2330
2555
|
*/
|
|
2331
2556
|
createModalDialog(url) {
|
|
2332
2557
|
const dialogUrl = this.getDialogUrl();
|
|
@@ -2524,6 +2749,24 @@ var OneAuthClient = class {
|
|
|
2524
2749
|
};
|
|
2525
2750
|
return { dialog, iframe, cleanup };
|
|
2526
2751
|
}
|
|
2752
|
+
/**
|
|
2753
|
+
* Listen for the auth result from the modal dialog.
|
|
2754
|
+
*
|
|
2755
|
+
* Waits for `PASSKEY_READY` before processing any other messages to avoid
|
|
2756
|
+
* acting on stale `PASSKEY_CLOSE` events that may still be in the event queue
|
|
2757
|
+
* from a previously closed dialog.
|
|
2758
|
+
*
|
|
2759
|
+
* Also handles the `PASSKEY_RETRY_POPUP` message: sent by the dialog when a
|
|
2760
|
+
* password manager (e.g. Bitwarden) intercepts the WebAuthn call inside the
|
|
2761
|
+
* iframe. In that case the SDK seamlessly re-opens a standalone popup window,
|
|
2762
|
+
* where WebAuthn works without cross-origin iframe restrictions, and waits
|
|
2763
|
+
* for the result from there instead.
|
|
2764
|
+
*
|
|
2765
|
+
* @param _dialog - Unused; kept for signature consistency.
|
|
2766
|
+
* @param iframe - The iframe element; used to send `PASSKEY_INIT` on ready.
|
|
2767
|
+
* @param cleanup - Idempotent teardown for the modal dialog.
|
|
2768
|
+
* @returns An `AuthResult` discriminated union.
|
|
2769
|
+
*/
|
|
2527
2770
|
waitForModalAuthResponse(_dialog, iframe, cleanup) {
|
|
2528
2771
|
const dialogOrigin = this.getDialogOrigin();
|
|
2529
2772
|
return new Promise((resolve) => {
|
|
@@ -2640,6 +2883,20 @@ var OneAuthClient = class {
|
|
|
2640
2883
|
window.addEventListener("message", handleMessage);
|
|
2641
2884
|
});
|
|
2642
2885
|
}
|
|
2886
|
+
/**
|
|
2887
|
+
* Listen for the authenticate result from the modal dialog.
|
|
2888
|
+
*
|
|
2889
|
+
* The authenticate flow combines sign-in/sign-up with optional off-chain
|
|
2890
|
+
* challenge signing. The dialog sends `PASSKEY_AUTHENTICATE_RESULT` on
|
|
2891
|
+
* completion with both user details and, if a challenge was requested, the
|
|
2892
|
+
* WebAuthn signature and the hashed challenge value for server-side
|
|
2893
|
+
* verification.
|
|
2894
|
+
*
|
|
2895
|
+
* @param _dialog - Unused; kept for signature consistency.
|
|
2896
|
+
* @param _iframe - Unused; kept for signature consistency.
|
|
2897
|
+
* @param cleanup - Idempotent teardown for the modal dialog.
|
|
2898
|
+
* @returns An `AuthenticateResult` discriminated union.
|
|
2899
|
+
*/
|
|
2643
2900
|
waitForAuthenticateResponse(_dialog, _iframe, cleanup) {
|
|
2644
2901
|
const dialogOrigin = this.getDialogOrigin();
|
|
2645
2902
|
return new Promise((resolve) => {
|
|
@@ -2683,6 +2940,22 @@ var OneAuthClient = class {
|
|
|
2683
2940
|
window.addEventListener("message", handleMessage);
|
|
2684
2941
|
});
|
|
2685
2942
|
}
|
|
2943
|
+
/**
|
|
2944
|
+
* Listen for the connect result from the connect dialog.
|
|
2945
|
+
*
|
|
2946
|
+
* The connect flow is a lightweight "are you still you?" confirmation that
|
|
2947
|
+
* does not require a new passkey ceremony. On success, the dialog returns the
|
|
2948
|
+
* user's username, address, and an `autoConnected` flag indicating whether the
|
|
2949
|
+
* user had previously enabled auto-connect (in which case no UI was shown).
|
|
2950
|
+
*
|
|
2951
|
+
* On failure with `action: "switch"`, the caller should redirect to the full
|
|
2952
|
+
* auth flow because the user has no cached session to confirm.
|
|
2953
|
+
*
|
|
2954
|
+
* @param _dialog - Unused; kept for signature consistency.
|
|
2955
|
+
* @param _iframe - Unused; kept for signature consistency.
|
|
2956
|
+
* @param cleanup - Idempotent teardown for the modal dialog.
|
|
2957
|
+
* @returns A `ConnectResult` discriminated union.
|
|
2958
|
+
*/
|
|
2686
2959
|
waitForConnectResponse(_dialog, _iframe, cleanup) {
|
|
2687
2960
|
const dialogOrigin = this.getDialogOrigin();
|
|
2688
2961
|
return new Promise((resolve) => {
|
|
@@ -2724,6 +2997,23 @@ var OneAuthClient = class {
|
|
|
2724
2997
|
window.addEventListener("message", handleMessage);
|
|
2725
2998
|
});
|
|
2726
2999
|
}
|
|
3000
|
+
/**
|
|
3001
|
+
* Listen for the consent result from the consent dialog.
|
|
3002
|
+
*
|
|
3003
|
+
* The consent dialog shows the user which data fields an app is requesting
|
|
3004
|
+
* access to and lets them approve or deny. On approval, `data` contains the
|
|
3005
|
+
* consented field values (e.g. email address, device names) and `grantedAt`
|
|
3006
|
+
* records when consent was given.
|
|
3007
|
+
*
|
|
3008
|
+
* A `PASSKEY_CLOSE` without a prior `PASSKEY_CONSENT_RESULT` is treated as an
|
|
3009
|
+
* explicit user cancellation (distinct from denial, though both yield
|
|
3010
|
+
* `success: false`).
|
|
3011
|
+
*
|
|
3012
|
+
* @param _dialog - Unused; kept for signature consistency.
|
|
3013
|
+
* @param _iframe - Unused; kept for signature consistency.
|
|
3014
|
+
* @param cleanup - Idempotent teardown for the modal dialog.
|
|
3015
|
+
* @returns A `RequestConsentResult` discriminated union.
|
|
3016
|
+
*/
|
|
2727
3017
|
waitForConsentResponse(_dialog, _iframe, cleanup) {
|
|
2728
3018
|
const dialogOrigin = this.getDialogOrigin();
|
|
2729
3019
|
return new Promise((resolve) => {
|
|
@@ -2763,6 +3053,20 @@ var OneAuthClient = class {
|
|
|
2763
3053
|
window.addEventListener("message", handleMessage);
|
|
2764
3054
|
});
|
|
2765
3055
|
}
|
|
3056
|
+
/**
|
|
3057
|
+
* Listen for a signing result from a server-request-based modal dialog.
|
|
3058
|
+
*
|
|
3059
|
+
* Similar to `waitForIntentSigningResponse` but intended for the older
|
|
3060
|
+
* `signWithModal` path that pre-creates a signing request via the API (rather
|
|
3061
|
+
* than inlining all data in `PASSKEY_INIT`). Filters by `requestId` to handle
|
|
3062
|
+
* the case where stale messages from a previous dialog may still be in flight.
|
|
3063
|
+
*
|
|
3064
|
+
* @param requestId - The signing request ID to match against incoming messages.
|
|
3065
|
+
* @param _dialog - Unused; kept for signature consistency.
|
|
3066
|
+
* @param _iframe - Unused; kept for signature consistency.
|
|
3067
|
+
* @param cleanup - Idempotent teardown that closes and removes the dialog.
|
|
3068
|
+
* @returns A `SigningResult` discriminated union.
|
|
3069
|
+
*/
|
|
2766
3070
|
waitForModalSigningResponse(requestId, _dialog, _iframe, cleanup) {
|
|
2767
3071
|
const dialogOrigin = this.getDialogOrigin();
|
|
2768
3072
|
return new Promise((resolve) => {
|
|
@@ -2802,6 +3106,21 @@ var OneAuthClient = class {
|
|
|
2802
3106
|
window.addEventListener("message", handleMessage);
|
|
2803
3107
|
});
|
|
2804
3108
|
}
|
|
3109
|
+
/**
|
|
3110
|
+
* Listen for a signing result from a popup window.
|
|
3111
|
+
*
|
|
3112
|
+
* Polls for popup closure every 500 ms as a fallback to detect when the user
|
|
3113
|
+
* closes the popup without completing the signing flow (no `PASSKEY_CLOSE`
|
|
3114
|
+
* message is fired in that case because the popup's unload event cannot
|
|
3115
|
+
* reliably postMessage to the opener on all browsers).
|
|
3116
|
+
*
|
|
3117
|
+
* On success or cancellation, the popup is programmatically closed and the
|
|
3118
|
+
* interval is cleared.
|
|
3119
|
+
*
|
|
3120
|
+
* @param requestId - The signing request ID to match against incoming messages.
|
|
3121
|
+
* @param popup - The popup `Window` reference returned by `openPopup`.
|
|
3122
|
+
* @returns A `SigningResult` discriminated union.
|
|
3123
|
+
*/
|
|
2805
3124
|
waitForPopupResponse(requestId, popup) {
|
|
2806
3125
|
const dialogOrigin = this.getDialogOrigin();
|
|
2807
3126
|
return new Promise((resolve) => {
|
|
@@ -2847,6 +3166,17 @@ var OneAuthClient = class {
|
|
|
2847
3166
|
window.addEventListener("message", handleMessage);
|
|
2848
3167
|
});
|
|
2849
3168
|
}
|
|
3169
|
+
/**
|
|
3170
|
+
* Fetch the completed signing result from the passkey service by request ID.
|
|
3171
|
+
*
|
|
3172
|
+
* Used by the redirect flow: after the passkey service redirects back to
|
|
3173
|
+
* `redirectUrl`, the integrator calls `handleRedirectCallback()`, which
|
|
3174
|
+
* extracts `requestId` from the URL query params and delegates here to
|
|
3175
|
+
* retrieve the full signature from the server.
|
|
3176
|
+
*
|
|
3177
|
+
* @param requestId - The signing request ID from the redirect callback URL.
|
|
3178
|
+
* @returns A `SigningResult` discriminated union.
|
|
3179
|
+
*/
|
|
2850
3180
|
async fetchSigningResult(requestId) {
|
|
2851
3181
|
const response = await fetch(
|
|
2852
3182
|
`${this.config.providerUrl}/api/sign/request/${requestId}`,
|
|
@@ -3132,31 +3462,16 @@ function createOneAuthProvider(options) {
|
|
|
3132
3462
|
}
|
|
3133
3463
|
return encodeWebAuthnSignature(result.signature);
|
|
3134
3464
|
};
|
|
3135
|
-
const resolveIntentPayload =
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
tokenRequests: payload.tokenRequests
|
|
3143
|
-
};
|
|
3144
|
-
}
|
|
3145
|
-
if (!payload.username) {
|
|
3146
|
-
throw new Error("Username required for signed intents. Set a username first.");
|
|
3147
|
-
}
|
|
3148
|
-
const signedIntent = await options.signIntent({
|
|
3149
|
-
username: payload.username,
|
|
3150
|
-
accountAddress: payload.accountAddress,
|
|
3151
|
-
targetChain: payload.targetChain,
|
|
3152
|
-
calls: payload.calls,
|
|
3153
|
-
tokenRequests: payload.tokenRequests
|
|
3154
|
-
});
|
|
3155
|
-
return { signedIntent };
|
|
3156
|
-
};
|
|
3465
|
+
const resolveIntentPayload = (payload) => ({
|
|
3466
|
+
username: payload.username,
|
|
3467
|
+
accountAddress: payload.accountAddress,
|
|
3468
|
+
targetChain: payload.targetChain,
|
|
3469
|
+
calls: payload.calls,
|
|
3470
|
+
tokenRequests: payload.tokenRequests
|
|
3471
|
+
});
|
|
3157
3472
|
const sendIntent = async (payload) => {
|
|
3158
3473
|
const closeOn = options.closeOn ?? (options.waitForHash ?? true ? "completed" : "preconfirmed");
|
|
3159
|
-
const intentPayload =
|
|
3474
|
+
const intentPayload = resolveIntentPayload(payload);
|
|
3160
3475
|
const result = await client.sendIntent({
|
|
3161
3476
|
...intentPayload,
|
|
3162
3477
|
tokenRequests: payload.tokenRequests,
|
|
@@ -3317,6 +3632,7 @@ function createOneAuthProvider(options) {
|
|
|
3317
3632
|
receipts: data.transactionHash ? [
|
|
3318
3633
|
{
|
|
3319
3634
|
logs: [],
|
|
3635
|
+
// 0x1 = success, 0x0 = reverted/failed — mirrors EVM receipt status
|
|
3320
3636
|
status: data.status === "completed" ? "0x1" : "0x0",
|
|
3321
3637
|
blockHash: data.blockHash,
|
|
3322
3638
|
blockNumber: data.blockNumber,
|
|
@@ -3430,6 +3746,7 @@ function createPasskeyAccount(client, params) {
|
|
|
3430
3746
|
const domain = {
|
|
3431
3747
|
name: domainInput.name,
|
|
3432
3748
|
version: domainInput.version,
|
|
3749
|
+
// viem uses bigint for chainId in typed data; the passkey service expects number
|
|
3433
3750
|
chainId: typeof domainInput.chainId === "bigint" ? Number(domainInput.chainId) : domainInput.chainId,
|
|
3434
3751
|
verifyingContract: domainInput.verifyingContract,
|
|
3435
3752
|
salt: domainInput.salt
|
|
@@ -3464,6 +3781,7 @@ function createPasskeyAccount(client, params) {
|
|
|
3464
3781
|
var import_viem6 = require("viem");
|
|
3465
3782
|
var import_accounts2 = require("viem/accounts");
|
|
3466
3783
|
function createPasskeyWalletClient(config) {
|
|
3784
|
+
const resolvedUsername = config.username ?? config.accountAddress;
|
|
3467
3785
|
const provider = new OneAuthClient({
|
|
3468
3786
|
providerUrl: config.providerUrl,
|
|
3469
3787
|
clientId: config.clientId,
|
|
@@ -3473,7 +3791,7 @@ function createPasskeyWalletClient(config) {
|
|
|
3473
3791
|
const hash = (0, import_viem6.hashMessage)(message);
|
|
3474
3792
|
const result = await provider.signWithModal({
|
|
3475
3793
|
challenge: hash,
|
|
3476
|
-
username:
|
|
3794
|
+
username: resolvedUsername,
|
|
3477
3795
|
description: "Sign message",
|
|
3478
3796
|
transaction: {
|
|
3479
3797
|
actions: [
|
|
@@ -3504,7 +3822,7 @@ function createPasskeyWalletClient(config) {
|
|
|
3504
3822
|
const hash = hashCalls(calls);
|
|
3505
3823
|
const result = await provider.signWithModal({
|
|
3506
3824
|
challenge: hash,
|
|
3507
|
-
username:
|
|
3825
|
+
username: resolvedUsername,
|
|
3508
3826
|
description: "Sign transaction",
|
|
3509
3827
|
transaction: buildTransactionReview(calls)
|
|
3510
3828
|
});
|
|
@@ -3520,7 +3838,7 @@ function createPasskeyWalletClient(config) {
|
|
|
3520
3838
|
const hash = (0, import_viem6.hashTypedData)(typedData);
|
|
3521
3839
|
const result = await provider.signWithModal({
|
|
3522
3840
|
challenge: hash,
|
|
3523
|
-
username:
|
|
3841
|
+
username: resolvedUsername,
|
|
3524
3842
|
description: "Sign typed data",
|
|
3525
3843
|
transaction: {
|
|
3526
3844
|
actions: [
|
|
@@ -3540,7 +3858,7 @@ function createPasskeyWalletClient(config) {
|
|
|
3540
3858
|
}
|
|
3541
3859
|
return encodeWebAuthnSignature(result.signature);
|
|
3542
3860
|
};
|
|
3543
|
-
const buildIntentPayload = async (calls, targetChainOverride) => {
|
|
3861
|
+
const buildIntentPayload = async (calls, targetChainOverride, extra) => {
|
|
3544
3862
|
const targetChain = targetChainOverride ?? config.chain.id;
|
|
3545
3863
|
const intentCalls = calls.map((call) => ({
|
|
3546
3864
|
to: call.to,
|
|
@@ -3549,17 +3867,9 @@ function createPasskeyWalletClient(config) {
|
|
|
3549
3867
|
label: call.label,
|
|
3550
3868
|
sublabel: call.sublabel
|
|
3551
3869
|
}));
|
|
3552
|
-
if (config.signIntent) {
|
|
3553
|
-
const signedIntent = await config.signIntent({
|
|
3554
|
-
username: config.username,
|
|
3555
|
-
accountAddress: config.accountAddress,
|
|
3556
|
-
targetChain,
|
|
3557
|
-
calls: intentCalls
|
|
3558
|
-
});
|
|
3559
|
-
return { signedIntent };
|
|
3560
|
-
}
|
|
3561
3870
|
return {
|
|
3562
|
-
username:
|
|
3871
|
+
username: resolvedUsername,
|
|
3872
|
+
accountAddress: config.accountAddress,
|
|
3563
3873
|
targetChain,
|
|
3564
3874
|
calls: intentCalls
|
|
3565
3875
|
};
|
|
@@ -3606,12 +3916,14 @@ function createPasskeyWalletClient(config) {
|
|
|
3606
3916
|
* Send multiple calls as a single batched transaction
|
|
3607
3917
|
*/
|
|
3608
3918
|
async sendCalls(params) {
|
|
3609
|
-
const { calls, chainId: targetChain, tokenRequests } = params;
|
|
3919
|
+
const { calls, chainId: targetChain, tokenRequests, sourceAssets, sourceChainId } = params;
|
|
3610
3920
|
const closeOn = config.waitForHash ?? true ? "completed" : "preconfirmed";
|
|
3611
|
-
const intentPayload = await buildIntentPayload(calls, targetChain);
|
|
3921
|
+
const intentPayload = await buildIntentPayload(calls, targetChain, { tokenRequests, sourceAssets });
|
|
3612
3922
|
const result = await provider.sendIntent({
|
|
3613
3923
|
...intentPayload,
|
|
3614
3924
|
tokenRequests,
|
|
3925
|
+
sourceAssets,
|
|
3926
|
+
sourceChainId,
|
|
3615
3927
|
closeOn,
|
|
3616
3928
|
waitForHash: config.waitForHash ?? true,
|
|
3617
3929
|
hashTimeoutMs: config.hashTimeoutMs,
|