@rhinestone/1auth 0.6.1 → 0.6.2

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/index.mjs CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  isTestnet,
19
19
  isTokenAddressSupported,
20
20
  resolveTokenAddress
21
- } from "./chunk-N4BLW5UR.mjs";
21
+ } from "./chunk-IP2FG4WQ.mjs";
22
22
 
23
23
  // src/client.ts
24
24
  import { parseUnits, hashTypedData } from "viem";
@@ -214,6 +214,53 @@ var OneAuthClient = class {
214
214
  }
215
215
  return this.waitForConnectResponse(dialog, iframe, cleanup);
216
216
  }
217
+ /**
218
+ * Open the account management dialog.
219
+ *
220
+ * Shows the account overview with guardian status and recovery setup
221
+ * options. The dialog closes when the user clicks the X button or
222
+ * completes their action.
223
+ *
224
+ * @example
225
+ * ```typescript
226
+ * await client.openAccountDialog();
227
+ * ```
228
+ */
229
+ async openAccountDialog(options) {
230
+ const dialogUrl = this.getDialogUrl();
231
+ const params = new URLSearchParams({
232
+ mode: "iframe"
233
+ });
234
+ const themeParams = this.getThemeParams(options?.theme);
235
+ if (themeParams) {
236
+ const themeParsed = new URLSearchParams(themeParams);
237
+ themeParsed.forEach((value, key) => params.set(key, value));
238
+ }
239
+ const url = `${dialogUrl}/dialog/account?${params.toString()}`;
240
+ const { dialog, iframe, cleanup } = this.createModalDialog(url);
241
+ const ready = await this.waitForDialogReady(dialog, iframe, cleanup, {
242
+ mode: "iframe"
243
+ });
244
+ if (!ready) return;
245
+ const dialogOrigin = this.getDialogOrigin();
246
+ return new Promise((resolve) => {
247
+ const handleMessage = (event) => {
248
+ if (event.origin !== dialogOrigin) return;
249
+ if (event.data?.type === "PASSKEY_CLOSE" || event.data?.type === "PASSKEY_DISCONNECT") {
250
+ window.removeEventListener("message", handleMessage);
251
+ dialog.removeEventListener("close", handleClose);
252
+ cleanup();
253
+ resolve();
254
+ }
255
+ };
256
+ const handleClose = () => {
257
+ window.removeEventListener("message", handleMessage);
258
+ resolve();
259
+ };
260
+ window.addEventListener("message", handleMessage);
261
+ dialog.addEventListener("close", handleClose);
262
+ });
263
+ }
217
264
  /**
218
265
  * Check if a user has already granted consent for the requested fields.
219
266
  * This is a read-only check — no dialog is shown.
@@ -509,10 +556,13 @@ var OneAuthClient = class {
509
556
  const themeParams = this.getThemeParams();
510
557
  const signingUrl = `${dialogUrl}/dialog/sign?mode=iframe${themeParams ? `&${themeParams}` : ""}`;
511
558
  const { dialog, iframe, cleanup } = this.createModalDialog(signingUrl);
512
- const [prepareResult, dialogResult] = await Promise.all([
513
- this.prepareIntent(requestBody),
514
- this.waitForDialogReadyDeferred(dialog, iframe, cleanup)
515
- ]);
559
+ const dialogOrigin = this.getDialogOrigin();
560
+ let earlyPrepareResult = null;
561
+ const preparePromise = this.prepareIntent(requestBody).then((r) => {
562
+ earlyPrepareResult = r;
563
+ return r;
564
+ });
565
+ const dialogResult = await this.waitForDialogReadyDeferred(dialog, iframe, cleanup);
516
566
  if (!dialogResult.ready) {
517
567
  return {
518
568
  success: false,
@@ -521,40 +571,85 @@ var OneAuthClient = class {
521
571
  error: { code: "USER_CANCELLED", message: "User closed the dialog" }
522
572
  };
523
573
  }
524
- if (!prepareResult.success) {
525
- this.sendPrepareError(iframe, prepareResult.error.message);
526
- await this.waitForDialogClose(dialog, cleanup);
527
- return {
528
- success: false,
529
- intentId: "",
530
- status: "failed",
531
- error: prepareResult.error
574
+ let currentInitPayload;
575
+ if (earlyPrepareResult) {
576
+ const prepareResult = earlyPrepareResult;
577
+ if (!prepareResult.success) {
578
+ this.sendPrepareError(iframe, prepareResult.error.message);
579
+ await this.waitForDialogClose(dialog, cleanup);
580
+ return {
581
+ success: false,
582
+ intentId: "",
583
+ status: "failed",
584
+ error: prepareResult.error
585
+ };
586
+ }
587
+ prepareResponse = prepareResult.data;
588
+ currentInitPayload = {
589
+ mode: "iframe",
590
+ calls,
591
+ chainId: targetChain,
592
+ transaction: prepareResponse.transaction,
593
+ challenge: prepareResponse.challenge,
594
+ username,
595
+ accountAddress: prepareResponse.accountAddress,
596
+ originMessages: prepareResponse.originMessages,
597
+ tokenRequests: serializedTokenRequests,
598
+ expiresAt: prepareResponse.expiresAt,
599
+ userId: prepareResponse.userId,
600
+ intentOp: prepareResponse.intentOp,
601
+ digestResult: prepareResponse.digestResult,
602
+ tier: prepareResult.tier
603
+ };
604
+ dialogResult.sendInit(currentInitPayload);
605
+ } else {
606
+ currentInitPayload = {
607
+ mode: "iframe",
608
+ calls,
609
+ chainId: targetChain,
610
+ username,
611
+ accountAddress: options.accountAddress,
612
+ tokenRequests: serializedTokenRequests
532
613
  };
614
+ dialogResult.sendInit(currentInitPayload);
615
+ const prepareResult = await preparePromise;
616
+ if (!prepareResult.success) {
617
+ this.sendPrepareError(iframe, prepareResult.error.message);
618
+ await this.waitForDialogClose(dialog, cleanup);
619
+ return {
620
+ success: false,
621
+ intentId: "",
622
+ status: "failed",
623
+ error: prepareResult.error
624
+ };
625
+ }
626
+ prepareResponse = prepareResult.data;
627
+ currentInitPayload = {
628
+ mode: "iframe",
629
+ calls,
630
+ chainId: targetChain,
631
+ transaction: prepareResponse.transaction,
632
+ challenge: prepareResponse.challenge,
633
+ username,
634
+ accountAddress: prepareResponse.accountAddress,
635
+ originMessages: prepareResponse.originMessages,
636
+ tokenRequests: serializedTokenRequests,
637
+ expiresAt: prepareResponse.expiresAt,
638
+ userId: prepareResponse.userId,
639
+ intentOp: prepareResponse.intentOp,
640
+ digestResult: prepareResponse.digestResult,
641
+ tier: prepareResult.tier
642
+ };
643
+ iframe.contentWindow?.postMessage(
644
+ { type: "PASSKEY_INIT", ...currentInitPayload, fullViewport: true },
645
+ dialogOrigin
646
+ );
533
647
  }
534
- prepareResponse = prepareResult.data;
535
- const dialogOrigin = this.getDialogOrigin();
536
- const initPayload = {
537
- mode: "iframe",
538
- calls,
539
- chainId: targetChain,
540
- transaction: prepareResponse.transaction,
541
- challenge: prepareResponse.challenge,
542
- username,
543
- accountAddress: prepareResponse.accountAddress,
544
- originMessages: prepareResponse.originMessages,
545
- tokenRequests: serializedTokenRequests,
546
- expiresAt: prepareResponse.expiresAt,
547
- userId: prepareResponse.userId,
548
- intentOp: prepareResponse.intentOp,
549
- digestResult: prepareResponse.digestResult,
550
- tier: prepareResult.tier
551
- };
552
- dialogResult.sendInit(initPayload);
553
648
  const handleReReady = (event) => {
554
649
  if (event.origin !== dialogOrigin) return;
555
650
  if (event.data?.type === "PASSKEY_READY") {
556
651
  iframe.contentWindow?.postMessage(
557
- { type: "PASSKEY_INIT", ...initPayload, fullViewport: true },
652
+ { type: "PASSKEY_INIT", ...currentInitPayload, fullViewport: true },
558
653
  dialogOrigin
559
654
  );
560
655
  }
@@ -843,10 +938,13 @@ var OneAuthClient = class {
843
938
  const themeParams = this.getThemeParams();
844
939
  const signingUrl = `${dialogUrl}/dialog/sign?mode=iframe${themeParams ? `&${themeParams}` : ""}`;
845
940
  const { dialog, iframe, cleanup } = this.createModalDialog(signingUrl);
846
- const [prepareResult, dialogResult] = await Promise.all([
847
- this.prepareBatchIntent(requestBody),
848
- this.waitForDialogReadyDeferred(dialog, iframe, cleanup)
849
- ]);
941
+ const dialogOrigin = this.getDialogOrigin();
942
+ let earlyBatchResult = null;
943
+ const preparePromise = this.prepareBatchIntent(requestBody).then((r) => {
944
+ earlyBatchResult = r;
945
+ return r;
946
+ });
947
+ const dialogResult = await this.waitForDialogReadyDeferred(dialog, iframe, cleanup);
850
948
  if (!dialogResult.ready) {
851
949
  return {
852
950
  success: false,
@@ -855,7 +953,8 @@ var OneAuthClient = class {
855
953
  failureCount: 0
856
954
  };
857
955
  }
858
- if (!prepareResult.success) {
956
+ let currentBatchPayload;
957
+ const handleBatchPrepareFailure = async (prepareResult) => {
859
958
  const failedIntents = prepareResult.failedIntents;
860
959
  const failureResults = failedIntents?.map((f) => ({
861
960
  index: f.index,
@@ -873,27 +972,68 @@ var OneAuthClient = class {
873
972
  failureCount: failureResults.length,
874
973
  error: prepareResult.error
875
974
  };
876
- }
877
- let prepareResponse = prepareResult.data;
878
- const dialogOrigin = this.getDialogOrigin();
879
- const batchInitPayload = {
880
- mode: "iframe",
881
- batchMode: true,
882
- batchIntents: prepareResponse.intents,
883
- batchFailedIntents: prepareResponse.failedIntents,
884
- challenge: prepareResponse.challenge,
885
- username: options.username,
886
- accountAddress: prepareResponse.accountAddress,
887
- userId: prepareResponse.userId,
888
- expiresAt: prepareResponse.expiresAt,
889
- tier: prepareResult.tier
890
975
  };
891
- dialogResult.sendInit(batchInitPayload);
976
+ let prepareResponse;
977
+ if (earlyBatchResult) {
978
+ const prepareResult = earlyBatchResult;
979
+ if (!prepareResult.success) {
980
+ return handleBatchPrepareFailure(prepareResult);
981
+ }
982
+ prepareResponse = prepareResult.data;
983
+ currentBatchPayload = {
984
+ mode: "iframe",
985
+ batchMode: true,
986
+ batchIntents: prepareResponse.intents,
987
+ batchFailedIntents: prepareResponse.failedIntents,
988
+ challenge: prepareResponse.challenge,
989
+ username: options.username,
990
+ accountAddress: prepareResponse.accountAddress,
991
+ userId: prepareResponse.userId,
992
+ expiresAt: prepareResponse.expiresAt,
993
+ tier: prepareResult.tier
994
+ };
995
+ dialogResult.sendInit(currentBatchPayload);
996
+ } else {
997
+ currentBatchPayload = {
998
+ mode: "iframe",
999
+ batchMode: true,
1000
+ batchIntents: serializedIntents.map((intent, idx) => ({
1001
+ index: idx,
1002
+ targetChain: intent.targetChain,
1003
+ calls: JSON.stringify(intent.calls)
1004
+ // No: transaction, intentOp, expiresAt, originMessages
1005
+ })),
1006
+ username: options.username,
1007
+ accountAddress: options.accountAddress
1008
+ };
1009
+ dialogResult.sendInit(currentBatchPayload);
1010
+ const prepareResult = await preparePromise;
1011
+ if (!prepareResult.success) {
1012
+ return handleBatchPrepareFailure(prepareResult);
1013
+ }
1014
+ prepareResponse = prepareResult.data;
1015
+ currentBatchPayload = {
1016
+ mode: "iframe",
1017
+ batchMode: true,
1018
+ batchIntents: prepareResponse.intents,
1019
+ batchFailedIntents: prepareResponse.failedIntents,
1020
+ challenge: prepareResponse.challenge,
1021
+ username: options.username,
1022
+ accountAddress: prepareResponse.accountAddress,
1023
+ userId: prepareResponse.userId,
1024
+ expiresAt: prepareResponse.expiresAt,
1025
+ tier: prepareResult.tier
1026
+ };
1027
+ iframe.contentWindow?.postMessage(
1028
+ { type: "PASSKEY_INIT", ...currentBatchPayload, fullViewport: true },
1029
+ dialogOrigin
1030
+ );
1031
+ }
892
1032
  const handleBatchReReady = (event) => {
893
1033
  if (event.origin !== dialogOrigin) return;
894
1034
  if (event.data?.type === "PASSKEY_READY") {
895
1035
  iframe.contentWindow?.postMessage(
896
- { type: "PASSKEY_INIT", ...batchInitPayload, fullViewport: true },
1036
+ { type: "PASSKEY_INIT", ...currentBatchPayload, fullViewport: true },
897
1037
  dialogOrigin
898
1038
  );
899
1039
  }
@@ -1631,16 +1771,8 @@ var OneAuthClient = class {
1631
1771
  const themeParams = this.getThemeParams(options?.theme);
1632
1772
  const signingUrl = `${dialogUrl}/dialog/sign?mode=iframe${themeParams ? `&${themeParams}` : ""}`;
1633
1773
  const { dialog, iframe, cleanup } = this.createModalDialog(signingUrl);
1634
- const ready = await this.waitForDialogReady(dialog, iframe, cleanup, {
1635
- mode: "iframe",
1636
- message: options.message,
1637
- challenge: options.challenge || options.message,
1638
- username: options.username,
1639
- accountAddress: options.accountAddress,
1640
- description: options.description,
1641
- metadata: options.metadata
1642
- });
1643
- if (!ready) {
1774
+ const dialogResult = await this.waitForDialogReadyDeferred(dialog, iframe, cleanup);
1775
+ if (!dialogResult.ready) {
1644
1776
  return {
1645
1777
  success: false,
1646
1778
  error: {
@@ -1649,7 +1781,29 @@ var OneAuthClient = class {
1649
1781
  }
1650
1782
  };
1651
1783
  }
1784
+ const initPayload = {
1785
+ mode: "iframe",
1786
+ message: options.message,
1787
+ challenge: options.challenge || options.message,
1788
+ username: options.username,
1789
+ accountAddress: options.accountAddress,
1790
+ description: options.description,
1791
+ metadata: options.metadata
1792
+ };
1793
+ dialogResult.sendInit(initPayload);
1794
+ const dialogOrigin = this.getDialogOrigin();
1795
+ const handleReReady = (event) => {
1796
+ if (event.origin !== dialogOrigin) return;
1797
+ if (event.data?.type === "PASSKEY_READY") {
1798
+ iframe.contentWindow?.postMessage(
1799
+ { type: "PASSKEY_INIT", ...initPayload, fullViewport: true },
1800
+ dialogOrigin
1801
+ );
1802
+ }
1803
+ };
1804
+ window.addEventListener("message", handleReReady);
1652
1805
  const signingResult = await this.waitForSigningResponse(dialog, iframe, cleanup);
1806
+ window.removeEventListener("message", handleReReady);
1653
1807
  cleanup();
1654
1808
  if (signingResult.success) {
1655
1809
  return {
@@ -1717,7 +1871,17 @@ var OneAuthClient = class {
1717
1871
  const themeParams = this.getThemeParams(options?.theme);
1718
1872
  const signingUrl = `${dialogUrl}/dialog/sign?mode=iframe${themeParams ? `&${themeParams}` : ""}`;
1719
1873
  const { dialog, iframe, cleanup } = this.createModalDialog(signingUrl);
1720
- const ready = await this.waitForDialogReady(dialog, iframe, cleanup, {
1874
+ const dialogResult = await this.waitForDialogReadyDeferred(dialog, iframe, cleanup);
1875
+ if (!dialogResult.ready) {
1876
+ return {
1877
+ success: false,
1878
+ error: {
1879
+ code: "USER_REJECTED",
1880
+ message: "User closed the dialog"
1881
+ }
1882
+ };
1883
+ }
1884
+ const initPayload = {
1721
1885
  mode: "iframe",
1722
1886
  signingMode: "typedData",
1723
1887
  typedData: {
@@ -1730,17 +1894,21 @@ var OneAuthClient = class {
1730
1894
  username: options.username,
1731
1895
  accountAddress: options.accountAddress,
1732
1896
  description: options.description
1733
- });
1734
- if (!ready) {
1735
- return {
1736
- success: false,
1737
- error: {
1738
- code: "USER_REJECTED",
1739
- message: "User closed the dialog"
1740
- }
1741
- };
1742
- }
1897
+ };
1898
+ dialogResult.sendInit(initPayload);
1899
+ const dialogOrigin = this.getDialogOrigin();
1900
+ const handleReReady = (event) => {
1901
+ if (event.origin !== dialogOrigin) return;
1902
+ if (event.data?.type === "PASSKEY_READY") {
1903
+ iframe.contentWindow?.postMessage(
1904
+ { type: "PASSKEY_INIT", ...initPayload, fullViewport: true },
1905
+ dialogOrigin
1906
+ );
1907
+ }
1908
+ };
1909
+ window.addEventListener("message", handleReReady);
1743
1910
  const signingResult = await this.waitForSigningResponse(dialog, iframe, cleanup);
1911
+ window.removeEventListener("message", handleReReady);
1744
1912
  cleanup();
1745
1913
  if (signingResult.success) {
1746
1914
  return {
@@ -2144,8 +2312,10 @@ var OneAuthClient = class {
2144
2312
  const hideOverlay = () => {
2145
2313
  if (overlayHidden) return;
2146
2314
  overlayHidden = true;
2147
- overlay.style.display = "none";
2148
2315
  iframe.style.opacity = "1";
2316
+ requestAnimationFrame(() => {
2317
+ overlay.style.display = "none";
2318
+ });
2149
2319
  };
2150
2320
  const handleMessage = (event) => {
2151
2321
  if (event.origin !== hostUrl.origin) return;
@@ -3221,7 +3391,8 @@ function BatchQueueWidget({ onSignAll }) {
3221
3391
  import { keccak256, toBytes } from "viem";
3222
3392
  var ETHEREUM_MESSAGE_PREFIX = "Ethereum Signed Message:\n";
3223
3393
  function hashMessage2(message) {
3224
- const prefixed = ETHEREUM_MESSAGE_PREFIX + message.length.toString() + message;
3394
+ const messageBytes = toBytes(message);
3395
+ const prefixed = ETHEREUM_MESSAGE_PREFIX + messageBytes.length.toString() + message;
3225
3396
  return keccak256(toBytes(prefixed));
3226
3397
  }
3227
3398
  function verifyMessageHash(message, signedHash) {