@coti-io/coti-wallet-plugin 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -596,6 +596,7 @@ var init_plugin = __esm({
596
596
  defaultNetworkId: void 0,
597
597
  debug: false,
598
598
  clearSessionKeyOnWagmiDisconnect: false,
599
+ waitForBalanceRefreshAfterTransfer: false,
599
600
  onboardingServices: { mode: "disabled" },
600
601
  onboardingGrantMinBalanceWei: 0,
601
602
  onboardingGrantPollIntervalMs: 2e3,
@@ -7518,7 +7519,7 @@ var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
7518
7519
  function useAesKeyProvider(walletTypeInfo) {
7519
7520
  const [isOnboarding, setIsOnboarding] = (0, import_react16.useState)(false);
7520
7521
  const [onboardingError, setOnboardingError] = (0, import_react16.useState)(null);
7521
- const [onboardingWarning, setOnboardingWarning] = (0, import_react16.useState)(null);
7522
+ const [onboardingWarnings, setOnboardingWarnings] = (0, import_react16.useState)({});
7522
7523
  const [wasRestoreCancelled, setWasRestoreCancelled] = (0, import_react16.useState)(false);
7523
7524
  const [currentStep, setCurrentStep] = (0, import_react16.useState)("idle");
7524
7525
  const progressCallbackRef = (0, import_react16.useRef)();
@@ -7539,7 +7540,7 @@ function useAesKeyProvider(walletTypeInfo) {
7539
7540
  progressCallbackRef.current = onProgress ?? options.onProgress;
7540
7541
  setOnboardingError(null);
7541
7542
  debugTraceRef.current.clear();
7542
- setOnboardingWarning(null);
7543
+ setOnboardingWarnings({});
7543
7544
  setWasRestoreCancelled(false);
7544
7545
  const forceContractOnboarding = options?.forceContractOnboarding === true;
7545
7546
  if (!forceContractOnboarding) {
@@ -7648,7 +7649,9 @@ function useAesKeyProvider(walletTypeInfo) {
7648
7649
  }
7649
7650
  } catch (restoreError) {
7650
7651
  if (isUserRejection(restoreError)) {
7651
- setOnboardingWarning("Backup restore was cancelled. Approve the wallet signature to unlock from your encrypted backup.");
7652
+ setOnboardingWarnings({
7653
+ intro: "Backup restore was cancelled. Approve the wallet signature to unlock from your encrypted backup."
7654
+ });
7652
7655
  setWasRestoreCancelled(true);
7653
7656
  options.onRestoreCancelled?.();
7654
7657
  emitStep("idle");
@@ -7657,7 +7660,9 @@ function useAesKeyProvider(walletTypeInfo) {
7657
7660
  const message = restoreError instanceof Error ? restoreError.message : "Encrypted AES backup could not be restored.";
7658
7661
  logger.warn("\u26A0\uFE0F AES backup restore failed, falling back to contract onboarding:", restoreError);
7659
7662
  restoreBackupFailed = true;
7660
- setOnboardingWarning(`Encrypted backup could not be restored. Continuing with onboarding. ${message}`);
7663
+ setOnboardingWarnings({
7664
+ intro: `Encrypted backup could not be restored. Continuing with onboarding. ${message}`
7665
+ });
7661
7666
  }
7662
7667
  }
7663
7668
  if (options.restoreOnly) {
@@ -7818,9 +7823,9 @@ function useAesKeyProvider(walletTypeInfo) {
7818
7823
  savedToSnap = await saveAESKeyToSnap(aesKey, address);
7819
7824
  if (!savedToSnap) {
7820
7825
  logger.warn("\u26A0\uFE0F AES key retrieved but could not persist to Snap");
7821
- setOnboardingWarning(
7822
- "Onboarding succeeded, but the AES key could not be saved to MetaMask Snap. You can retry by unlocking again."
7823
- );
7826
+ setOnboardingWarnings({
7827
+ success: "Onboarding succeeded, but the AES key could not be saved to MetaMask Snap. You can retry by unlocking again."
7828
+ });
7824
7829
  }
7825
7830
  } else if (aesKey && walletTypeInfo.walletType === "metamask" && canPersistAesKeyToSnap() && !walletTypeInfo.isMetaMaskWithSnap) {
7826
7831
  logger.log(
@@ -7842,14 +7847,14 @@ function useAesKeyProvider(walletTypeInfo) {
7842
7847
  "\u26A0\uFE0F AES key retrieved but encrypted backup save failed:",
7843
7848
  backupResult.message
7844
7849
  );
7845
- setOnboardingWarning(
7846
- `Onboarding succeeded, but encrypted backup was not saved. ${backupResult.message}`
7847
- );
7850
+ setOnboardingWarnings({
7851
+ success: `Onboarding succeeded, but encrypted backup was not saved. ${backupResult.message}`
7852
+ });
7848
7853
  } else if (backupResult.status === "cancelled") {
7849
7854
  logger.warn("\u26A0\uFE0F AES key retrieved but encrypted backup save was cancelled");
7850
- setOnboardingWarning(
7851
- "Onboarding succeeded, but encrypted backup save was cancelled. You can save it later by re-entering your AES key."
7852
- );
7855
+ setOnboardingWarnings({
7856
+ success: "Onboarding succeeded, but encrypted backup save was cancelled. You can save it later by re-entering your AES key."
7857
+ });
7853
7858
  }
7854
7859
  }
7855
7860
  if (aesKey && isValidAesKey(aesKey)) {
@@ -7913,7 +7918,7 @@ function useAesKeyProvider(walletTypeInfo) {
7913
7918
  getAesKey,
7914
7919
  isOnboarding,
7915
7920
  onboardingError,
7916
- onboardingWarning,
7921
+ onboardingWarnings,
7917
7922
  wasRestoreCancelled,
7918
7923
  currentStep
7919
7924
  };
@@ -8021,7 +8026,7 @@ var usePrivacyBridgeSessionCore = ({
8021
8026
  getAesKey: getAesKeyFromProvider,
8022
8027
  isOnboarding,
8023
8028
  onboardingError,
8024
- onboardingWarning
8029
+ onboardingWarnings
8025
8030
  } = useAesKeyProvider(walletTypeInfo);
8026
8031
  const { fetchPrivateBalance } = usePrivateTokenBalance();
8027
8032
  (0, import_react18.useEffect)(() => {
@@ -8077,7 +8082,7 @@ var usePrivacyBridgeSessionCore = ({
8077
8082
  fetchPrivateBalance,
8078
8083
  getAesKeyFromProvider,
8079
8084
  onboardingError,
8080
- onboardingWarning
8085
+ onboardingWarnings
8081
8086
  };
8082
8087
  };
8083
8088
 
@@ -8711,6 +8716,7 @@ var usePrivacyBridgeWalletConnection = ({
8711
8716
  // src/context/privacyBridge/usePrivacyBridgeUnlockSession.ts
8712
8717
  var import_react23 = require("react");
8713
8718
  var import_wagmi10 = require("wagmi");
8719
+ init_plugin();
8714
8720
  init_logger();
8715
8721
 
8716
8722
  // src/hooks/privacyBridge/privateValueCrypto.ts
@@ -8980,6 +8986,13 @@ var usePrivacyBridgeUnlockSession = ({
8980
8986
  }, [resolveAesAccess, resolveSessionAesKey, walletAddress, aesKeyChainId, checkSnapStatus, hasAesKeyInSnap, walletTypeInfo.walletType, currentChainId]);
8981
8987
  const refreshPrivateBalances = (0, import_react23.useCallback)(async (aesKeyOptions) => {
8982
8988
  if (!walletAddress) return false;
8989
+ const lockSessionOnAesFailure = !aesKeyOptions?.preserveSessionOnError;
8990
+ const clearSessionAfterAesFailure = () => {
8991
+ setSessionAesKey(null);
8992
+ clearAesKeyValidatedForUnlock(walletAddress);
8993
+ clearSnapCache();
8994
+ setArePrivateBalancesHidden(true);
8995
+ };
8983
8996
  logger.log("Triggering private balance fetch...");
8984
8997
  try {
8985
8998
  const chainOverride = wagmiSyncRef.current ? wagmiChainId : void 0;
@@ -9058,10 +9071,7 @@ var usePrivacyBridgeUnlockSession = ({
9058
9071
  );
9059
9072
  }
9060
9073
  if (errorInfo.message?.includes("ACCOUNT_NOT_ONBOARDED")) {
9061
- setSessionAesKey(null);
9062
- clearAesKeyValidatedForUnlock(walletAddress);
9063
- clearSnapCache();
9064
- setArePrivateBalancesHidden(true);
9074
+ if (lockSessionOnAesFailure) clearSessionAfterAesFailure();
9065
9075
  throw new CotiPluginError(
9066
9076
  "ACCOUNT_NOT_ONBOARDED" /* ACCOUNT_NOT_ONBOARDED */,
9067
9077
  "Account has not been onboarded to the COTI network.",
@@ -9069,17 +9079,11 @@ var usePrivacyBridgeUnlockSession = ({
9069
9079
  );
9070
9080
  }
9071
9081
  if (err instanceof CotiPluginError && err.code === "AES_KEY_MISMATCH" /* AES_KEY_MISMATCH */) {
9072
- setSessionAesKey(null);
9073
- clearAesKeyValidatedForUnlock(walletAddress);
9074
- clearSnapCache();
9075
- setArePrivateBalancesHidden(true);
9082
+ if (lockSessionOnAesFailure) clearSessionAfterAesFailure();
9076
9083
  throw err;
9077
9084
  }
9078
9085
  if (errorInfo.message?.includes("AES key") || errorInfo.message?.includes("onboarding")) {
9079
- setSessionAesKey(null);
9080
- clearAesKeyValidatedForUnlock(walletAddress);
9081
- clearSnapCache();
9082
- setArePrivateBalancesHidden(true);
9086
+ if (lockSessionOnAesFailure) clearSessionAfterAesFailure();
9083
9087
  throw new CotiPluginError(
9084
9088
  "AES_KEY_MISMATCH" /* AES_KEY_MISMATCH */,
9085
9089
  "AES key mismatch or onboarding error.",
@@ -9124,7 +9128,13 @@ var usePrivacyBridgeUnlockSession = ({
9124
9128
  hasSnap: strategy.snapInstalled,
9125
9129
  getAESKeyFromSnap: strategy.snapInstalled ? getAESKeyFromSnap : void 0
9126
9130
  });
9127
- await refreshPrivateBalances();
9131
+ if (getPluginConfig().waitForBalanceRefreshAfterTransfer) {
9132
+ await refreshPrivateBalances();
9133
+ } else {
9134
+ void refreshPrivateBalances({ preserveSessionOnError: true }).catch(
9135
+ (err) => logger.error("Background balance refresh after transfer failed", err)
9136
+ );
9137
+ }
9128
9138
  return result;
9129
9139
  }, [
9130
9140
  walletAddress,
@@ -9274,7 +9284,7 @@ var usePrivacyBridgeSession = ({ modals }) => {
9274
9284
  refreshPublicBalances: unlock.refreshPublicBalances,
9275
9285
  refreshPrivateBalances: unlock.refreshPrivateBalances,
9276
9286
  onboardingError: core.onboardingError,
9277
- onboardingWarning: core.onboardingWarning,
9287
+ onboardingWarnings: core.onboardingWarnings,
9278
9288
  lockPrivateBalances: unlock.lockPrivateBalances,
9279
9289
  saveManualAesKey: unlock.saveManualAesKey,
9280
9290
  sendPrivateToken: unlock.sendPrivateToken,
@@ -9647,6 +9657,40 @@ function deriveOnboardScreen({
9647
9657
 
9648
9658
  // src/components/OnboardModal.tsx
9649
9659
  init_logger();
9660
+
9661
+ // src/lib/onboardModalWarnings.ts
9662
+ function mergeOnboardModalWarnings(...sources) {
9663
+ const merged = {};
9664
+ for (const source of sources) {
9665
+ if (!source) continue;
9666
+ for (const page of Object.keys(source)) {
9667
+ const message = source[page];
9668
+ if (message) {
9669
+ merged[page] = message;
9670
+ }
9671
+ }
9672
+ }
9673
+ return merged;
9674
+ }
9675
+ function getDefaultSuccessWarning(saveBackup) {
9676
+ return saveBackup ? "Important: An encrypted backup can help restore this key later, but you should still store it safely." : "Important: This key will be lost when you refresh the page. Store it in a secure location.";
9677
+ }
9678
+ function resolveOnboardPageWarning(page, options) {
9679
+ const runtime = options.runtimeWarnings?.[page]?.trim();
9680
+ if (runtime) return runtime;
9681
+ const app = options.warnings?.[page]?.trim();
9682
+ if (app) return app;
9683
+ if (page === "success") {
9684
+ return getDefaultSuccessWarning(options.saveBackup ?? true);
9685
+ }
9686
+ return null;
9687
+ }
9688
+ function hasOnboardModalWarnings(warnings) {
9689
+ if (!warnings) return false;
9690
+ return Object.values(warnings).some((message) => !!message?.trim());
9691
+ }
9692
+
9693
+ // src/components/OnboardModal.tsx
9650
9694
  var import_jsx_runtime = require("react/jsx-runtime");
9651
9695
  var defaultStyles = {
9652
9696
  backdrop: {
@@ -9818,28 +9862,23 @@ var defaultStyles = {
9818
9862
  },
9819
9863
  saveOptionBody: {
9820
9864
  flex: 1,
9821
- minWidth: 0
9865
+ minWidth: 0,
9866
+ display: "flex",
9867
+ alignItems: "center",
9868
+ minHeight: "32px"
9822
9869
  },
9823
9870
  saveOptionTitleRow: {
9824
9871
  display: "flex",
9825
9872
  alignItems: "center",
9826
- gap: "5px",
9827
- marginBottom: "2px"
9873
+ gap: "5px"
9828
9874
  },
9829
9875
  saveOptionTitle: {
9830
9876
  fontSize: "13px",
9831
9877
  fontWeight: 600,
9832
- lineHeight: 1.25,
9833
- color: "#ffffff"
9834
- },
9835
- saveOptionDescription: {
9836
- fontSize: "11px",
9837
- lineHeight: 1.3,
9838
- color: "rgba(255, 255, 255, 0.55)",
9839
- margin: 0,
9840
- whiteSpace: "nowrap",
9841
- overflow: "hidden",
9842
- textOverflow: "ellipsis"
9878
+ lineHeight: "14px",
9879
+ color: "#ffffff",
9880
+ display: "inline-flex",
9881
+ alignItems: "center"
9843
9882
  },
9844
9883
  saveOptionSwitchTrack: {
9845
9884
  position: "relative",
@@ -9881,12 +9920,13 @@ var defaultStyles = {
9881
9920
  tooltipButton: {
9882
9921
  width: "14px",
9883
9922
  height: "14px",
9923
+ boxSizing: "border-box",
9884
9924
  borderRadius: "50%",
9885
9925
  border: "1px solid rgba(255, 255, 255, 0.25)",
9886
9926
  backgroundColor: "rgba(255, 255, 255, 0.08)",
9887
9927
  color: "rgba(255, 255, 255, 0.8)",
9888
9928
  fontSize: "9px",
9889
- lineHeight: 1,
9929
+ lineHeight: "12px",
9890
9930
  padding: 0,
9891
9931
  cursor: "help",
9892
9932
  flexShrink: 0,
@@ -10190,8 +10230,7 @@ var MUTED_TEXT_KEYS = [
10190
10230
  "closeButton",
10191
10231
  "tooltipButton",
10192
10232
  "cancelButton",
10193
- "stepDescription",
10194
- "saveOptionDescription"
10233
+ "stepDescription"
10195
10234
  ];
10196
10235
  var ACCENT_TEXT_KEYS = [
10197
10236
  "keyInput",
@@ -10241,7 +10280,8 @@ var LIGHT_INTERACTIVE_SURFACE_KEYS = [
10241
10280
  "saveOptionCard",
10242
10281
  "saveOptionIconWrap",
10243
10282
  "saveOptionSwitchTrackOff",
10244
- "saveOptionSwitchTrackOn"
10283
+ "saveOptionSwitchTrackOn",
10284
+ "tooltipButton"
10245
10285
  ];
10246
10286
  function isDefaultDarkSurfaceBackground(backgroundColor) {
10247
10287
  if (!backgroundColor) return true;
@@ -10325,6 +10365,11 @@ function applyLightInteractiveSurfaceGaps(merged, theme) {
10325
10365
  saveOptionSwitchTrackOn: {
10326
10366
  backgroundColor: primary,
10327
10367
  borderColor: colorWithAlpha(primary, 0.45)
10368
+ },
10369
+ tooltipButton: {
10370
+ color: muted2,
10371
+ backgroundColor: colorWithAlpha(foreground, 0.08),
10372
+ border: `1px solid ${colorWithAlpha(foreground, 0.2)}`
10328
10373
  }
10329
10374
  };
10330
10375
  for (const key of LIGHT_INTERACTIVE_SURFACE_KEYS) {
@@ -10471,7 +10516,8 @@ var OnboardModal = ({
10471
10516
  showSaveBackupOption = true,
10472
10517
  onSaveBackupChange,
10473
10518
  onManualAesKeySubmit,
10474
- warning,
10519
+ warnings,
10520
+ runtimeWarnings,
10475
10521
  theme
10476
10522
  }) => {
10477
10523
  const [copied, setCopied] = (0, import_react27.useState)(false);
@@ -10517,6 +10563,15 @@ var OnboardModal = ({
10517
10563
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles2.iconContainer, children: icon }),
10518
10564
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { id: "onboard-modal-title", style: styles2.title, children: title })
10519
10565
  ] });
10566
+ const renderPageWarning = (page) => {
10567
+ const message = resolveOnboardPageWarning(page, {
10568
+ warnings,
10569
+ runtimeWarnings,
10570
+ saveBackup
10571
+ });
10572
+ if (!message) return null;
10573
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: warningStyles.box, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: warningStyles.text, children: message }) });
10574
+ };
10520
10575
  const renderSaveLocallyOption = () => {
10521
10576
  if (!showSaveBackupOption) return null;
10522
10577
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
@@ -10528,29 +10583,26 @@ var OnboardModal = ({
10528
10583
  },
10529
10584
  children: [
10530
10585
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles2.saveOptionIconWrap, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4" }) }) }),
10531
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles2.saveOptionBody, children: [
10532
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles2.saveOptionTitleRow, children: [
10533
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles2.saveOptionTitle, children: "Save Locally" }),
10534
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles2.tooltipWrap, children: [
10535
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
10536
- "button",
10537
- {
10538
- type: "button",
10539
- "aria-label": "How local save works",
10540
- "aria-describedby": showBackupTooltip ? "backup-details-tooltip" : void 0,
10541
- onMouseEnter: () => setShowBackupTooltip(true),
10542
- onMouseLeave: () => setShowBackupTooltip(false),
10543
- onFocus: () => setShowBackupTooltip(true),
10544
- onBlur: () => setShowBackupTooltip(false),
10545
- style: styles2.tooltipButton,
10546
- children: "?"
10547
- }
10548
- ),
10549
- showBackupTooltip && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { id: "backup-details-tooltip", role: "tooltip", style: styles2.tooltipBubble, children: "Only an encrypted blob is stored locally. Restoring it requires a wallet signature." })
10550
- ] })
10551
- ] }),
10552
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles2.saveOptionDescription, children: "Encrypted locally. Restore via wallet signature." })
10553
- ] }),
10586
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles2.saveOptionBody, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles2.saveOptionTitleRow, children: [
10587
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles2.saveOptionTitle, children: "Save Locally" }),
10588
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles2.tooltipWrap, children: [
10589
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
10590
+ "button",
10591
+ {
10592
+ type: "button",
10593
+ "aria-label": "How local save works",
10594
+ "aria-describedby": showBackupTooltip ? "backup-details-tooltip" : void 0,
10595
+ onMouseEnter: () => setShowBackupTooltip(true),
10596
+ onMouseLeave: () => setShowBackupTooltip(false),
10597
+ onFocus: () => setShowBackupTooltip(true),
10598
+ onBlur: () => setShowBackupTooltip(false),
10599
+ style: styles2.tooltipButton,
10600
+ children: "?"
10601
+ }
10602
+ ),
10603
+ showBackupTooltip && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { id: "backup-details-tooltip", role: "tooltip", style: styles2.tooltipBubble, children: "Only an encrypted blob is stored locally. Restoring it requires a wallet signature." })
10604
+ ] })
10605
+ ] }) }),
10554
10606
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
10555
10607
  "button",
10556
10608
  {
@@ -10746,7 +10798,7 @@ var OnboardModal = ({
10746
10798
  "Onboard User"
10747
10799
  ),
10748
10800
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { id: "onboard-modal-description", style: styles2.description, children: "This will execute a transaction on the COTI Network to retrieve your encryption key." }),
10749
- warning && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: warningStyles.box, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: warningStyles.text, children: warning }) }),
10801
+ renderPageWarning("intro"),
10750
10802
  renderSaveLocallyOption(),
10751
10803
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
10752
10804
  "div",
@@ -10763,7 +10815,7 @@ var OnboardModal = ({
10763
10815
  type: "text",
10764
10816
  value: manualAesKey,
10765
10817
  onChange: (event) => setManualAesKey(event.target.value),
10766
- placeholder: "Paste AES key",
10818
+ placeholder: "Paste key",
10767
10819
  "aria-label": "Manual AES key",
10768
10820
  disabled: isSubmittingManualKey,
10769
10821
  style: { ...styles2.manualKeyInput, ...styles2.actionPrimary },
@@ -10837,7 +10889,7 @@ var OnboardModal = ({
10837
10889
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles2.spinner }),
10838
10890
  getProgressTitle(currentStep)
10839
10891
  ),
10840
- warning && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: warningStyles.box, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: warningStyles.text, children: warning }) }),
10892
+ renderPageWarning("progress"),
10841
10893
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles2.stepperContainer, children: displaySteps.map((step) => {
10842
10894
  const status = getOnboardingStepStatus(step.id, currentStep, !!error, includePersistStep);
10843
10895
  const isActive = status === "active";
@@ -10935,12 +10987,7 @@ var OnboardModal = ({
10935
10987
  )
10936
10988
  ] })
10937
10989
  ] }),
10938
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: warningStyles.box, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: warningStyles.text, children: [
10939
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "Important:" }),
10940
- " ",
10941
- saveBackup ? "An encrypted backup can help restore this key later, but you should still store it safely." : "This key will be lost when you refresh the page. Store it in a secure location."
10942
- ] }) }),
10943
- warning && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: warningStyles.box, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: warningStyles.text, children: warning }) }),
10990
+ renderPageWarning("success"),
10944
10991
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
10945
10992
  "button",
10946
10993
  {
@@ -10974,6 +11021,7 @@ var OnboardModal = ({
10974
11021
  ),
10975
11022
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { id: "onboard-modal-description", style: styles2.description, children: "The onboarding process encountered an error. You can retry the signature request." }),
10976
11023
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles2.errorBox, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles2.errorText, children: error || "An unknown error occurred" }) }),
11024
+ renderPageWarning("error"),
10977
11025
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
10978
11026
  "button",
10979
11027
  {
@@ -11084,14 +11132,14 @@ function keepForwardContractProgress(previous, next) {
11084
11132
  return nextOrder >= previousOrder ? next : previous;
11085
11133
  }
11086
11134
  function usePrivateUnlockController(options = {}) {
11087
- const { theme, warning, onUnlocked, onRestoreCancelled, onOnboardingCancelled } = options;
11135
+ const { theme, warnings, onUnlocked, onRestoreCancelled, onOnboardingCancelled } = options;
11088
11136
  const unlock = usePrivacyBridgeUnlock();
11089
11137
  const wallet = usePrivacyBridgeWallet();
11090
11138
  const walletTypeInfo = useWalletType();
11091
11139
  const [showOnboardModal, setShowOnboardModal] = (0, import_react28.useState)(false);
11092
11140
  const [isUnlocking, setIsUnlocking] = (0, import_react28.useState)(false);
11093
11141
  const [modalError, setModalError] = (0, import_react28.useState)(null);
11094
- const [modalWarning, setModalWarning] = (0, import_react28.useState)(null);
11142
+ const [modalRuntimeWarnings, setModalRuntimeWarnings] = (0, import_react28.useState)({});
11095
11143
  const [snapConnectedInModal, setSnapConnectedInModal] = (0, import_react28.useState)(false);
11096
11144
  const [saveBackup, setSaveBackup] = (0, import_react28.useState)(true);
11097
11145
  const [currentStep, setCurrentStep] = (0, import_react28.useState)("idle");
@@ -11128,7 +11176,7 @@ function usePrivateUnlockController(options = {}) {
11128
11176
  pendingActionOwnerRef.current = null;
11129
11177
  setCurrentStep("idle");
11130
11178
  setModalError(null);
11131
- setModalWarning(null);
11179
+ setModalRuntimeWarnings({});
11132
11180
  backupSaveProgressStartedAtRef.current = null;
11133
11181
  pendingCompleteRequestIdRef.current = null;
11134
11182
  contractOnboardingCancelledRef.current = false;
@@ -11157,7 +11205,7 @@ function usePrivateUnlockController(options = {}) {
11157
11205
  setShowOnboardModal(false);
11158
11206
  setCurrentStep("idle");
11159
11207
  setModalError(null);
11160
- setModalWarning(null);
11208
+ setModalRuntimeWarnings({});
11161
11209
  setIsUnlockInProgress(false);
11162
11210
  setIsUnlocking(false);
11163
11211
  backupSaveProgressStartedAtRef.current = null;
@@ -11182,7 +11230,7 @@ function usePrivateUnlockController(options = {}) {
11182
11230
  setShowOnboardModal(false);
11183
11231
  setCurrentStep("idle");
11184
11232
  setModalError(null);
11185
- setModalWarning(null);
11233
+ setModalRuntimeWarnings({});
11186
11234
  unlockInProgressOwnerRef.current = null;
11187
11235
  setIsUnlockInProgress(false);
11188
11236
  setIsUnlocking(false);
@@ -11218,14 +11266,18 @@ function usePrivateUnlockController(options = {}) {
11218
11266
  try {
11219
11267
  const connected = await unlock.requestSnapConnection();
11220
11268
  if (!connected) {
11221
- setModalWarning("Snap connection was skipped or rejected. Continuing without Snap storage.");
11269
+ setModalRuntimeWarnings({
11270
+ intro: "Snap connection was skipped or rejected. Continuing without Snap storage."
11271
+ });
11222
11272
  return false;
11223
11273
  }
11224
11274
  snapConnectedInModalRef.current = true;
11225
11275
  setSnapConnectedInModal(true);
11226
11276
  return true;
11227
11277
  } catch {
11228
- setModalWarning("Snap connection failed. Continuing without Snap storage.");
11278
+ setModalRuntimeWarnings({
11279
+ intro: "Snap connection failed. Continuing without Snap storage."
11280
+ });
11229
11281
  return false;
11230
11282
  }
11231
11283
  }, [canAttemptSnapInstall, unlock]);
@@ -11259,15 +11311,13 @@ function usePrivateUnlockController(options = {}) {
11259
11311
  if (failureMessage) {
11260
11312
  setCurrentStep("error");
11261
11313
  setModalError(failureMessage);
11262
- setModalWarning(unlock.onboardingWarning ?? null);
11263
11314
  releaseUnlockInProgress(requestId);
11264
11315
  return;
11265
11316
  }
11266
11317
  setCurrentStep("error");
11267
11318
  setModalError("Onboarding did not complete. Please retry.");
11268
- setModalWarning(unlock.onboardingWarning ?? null);
11269
11319
  releaseUnlockInProgress(requestId);
11270
- }, [dismissOnboardModal, isActiveUnlockRequest, onOnboardingCancelled, releaseUnlockInProgress, unlock.onboardingWarning]);
11320
+ }, [dismissOnboardModal, isActiveUnlockRequest, onOnboardingCancelled, releaseUnlockInProgress]);
11271
11321
  const handleStaleRestoreCompletion = (0, import_react28.useCallback)((requestId, refreshSucceeded) => {
11272
11322
  clearPendingActionForRequest(requestId);
11273
11323
  const unlocked = refreshSucceeded || isPrivateUnlockedRef.current;
@@ -11283,7 +11333,7 @@ function usePrivateUnlockController(options = {}) {
11283
11333
  setPendingActionForRequest(requestId, pendingAction);
11284
11334
  }
11285
11335
  setModalError(null);
11286
- setModalWarning(null);
11336
+ setModalRuntimeWarnings({});
11287
11337
  inFlightRestoreRequestIdRef.current = requestId;
11288
11338
  setIsUnlocking(true);
11289
11339
  try {
@@ -11317,7 +11367,6 @@ function usePrivateUnlockController(options = {}) {
11317
11367
  return false;
11318
11368
  }
11319
11369
  setCurrentStep("idle");
11320
- setModalWarning(unlock.onboardingWarning ?? null);
11321
11370
  setShowOnboardModal(true);
11322
11371
  return false;
11323
11372
  } catch (error) {
@@ -11379,7 +11428,6 @@ function usePrivateUnlockController(options = {}) {
11379
11428
  contractOnboardingFailureRef.current = failureMessage;
11380
11429
  setCurrentStep("error");
11381
11430
  setModalError(failureMessage);
11382
- setModalWarning(unlock.onboardingWarning ?? null);
11383
11431
  releaseUnlockInProgress(unlockRequestIdRef.current);
11384
11432
  }
11385
11433
  return;
@@ -11391,7 +11439,7 @@ function usePrivateUnlockController(options = {}) {
11391
11439
  if (step === "idle") {
11392
11440
  setModalError(null);
11393
11441
  }
11394
- }, [currentStep, showOnboardModal, releaseUnlockInProgress, unlock.onboardingWarning]);
11442
+ }, [currentStep, showOnboardModal, releaseUnlockInProgress]);
11395
11443
  const showOnboardingComplete = (0, import_react28.useCallback)((requestId) => {
11396
11444
  if (!isActiveUnlockRequest(requestId)) return;
11397
11445
  pendingCompleteRequestIdRef.current = null;
@@ -11409,7 +11457,7 @@ function usePrivateUnlockController(options = {}) {
11409
11457
  if (!connectedAddress) return;
11410
11458
  const requestId = unlockRequestIdRef.current;
11411
11459
  setModalError(null);
11412
- setModalWarning(null);
11460
+ setModalRuntimeWarnings({});
11413
11461
  setIsUnlocking(true);
11414
11462
  setShowOnboardModal(true);
11415
11463
  setCurrentStep("preparing-onboard");
@@ -11444,7 +11492,7 @@ function usePrivateUnlockController(options = {}) {
11444
11492
  currentStep,
11445
11493
  hasSessionAesKey: !!unlock.sessionAesKey,
11446
11494
  hasOnboardingError: !!unlock.onboardingError,
11447
- hasOnboardingWarning: !!unlock.onboardingWarning
11495
+ hasOnboardingWarning: hasOnboardModalWarnings(unlock.onboardingWarnings)
11448
11496
  });
11449
11497
  const backupSaveProgressStartedAt = backupSaveProgressStartedAtRef.current;
11450
11498
  if (backupSaveProgressStartedAt !== null) {
@@ -11560,7 +11608,7 @@ function usePrivateUnlockController(options = {}) {
11560
11608
  onSaveBackupChange: setSaveBackup,
11561
11609
  onManualAesKeySubmit: async (aesKey, { saveBackup: shouldSaveBackup }) => {
11562
11610
  const requestId = unlockRequestIdRef.current;
11563
- setModalWarning(null);
11611
+ setModalRuntimeWarnings({});
11564
11612
  const manualSaveResult = await unlock.saveManualAesKey(aesKey, {
11565
11613
  saveBackup: shouldSaveBackup,
11566
11614
  onProgress: (step) => {
@@ -11581,7 +11629,7 @@ function usePrivateUnlockController(options = {}) {
11581
11629
  return;
11582
11630
  }
11583
11631
  if (manualSaveResult.backupWarning) {
11584
- setModalWarning(manualSaveResult.backupWarning);
11632
+ setModalRuntimeWarnings({ success: manualSaveResult.backupWarning });
11585
11633
  setShowOnboardModal(true);
11586
11634
  setCurrentStep("complete");
11587
11635
  releaseUnlockInProgress(requestId);
@@ -11590,7 +11638,8 @@ function usePrivateUnlockController(options = {}) {
11590
11638
  await completeUnlock(requestId);
11591
11639
  },
11592
11640
  theme,
11593
- warning: modalWarning ?? unlock.onboardingWarning ?? warning ?? null
11641
+ warnings,
11642
+ runtimeWarnings: mergeOnboardModalWarnings(unlock.onboardingWarnings, modalRuntimeWarnings)
11594
11643
  }
11595
11644
  );
11596
11645
  return {
@@ -11763,7 +11812,7 @@ var PrivacyBridgeProvider = ({
11763
11812
  decryptPrivateValue: session.decryptPrivateValue,
11764
11813
  refreshPrivateBalances: session.refreshPrivateBalances,
11765
11814
  onboardingError: session.onboardingError,
11766
- onboardingWarning: session.onboardingWarning,
11815
+ onboardingWarnings: session.onboardingWarnings,
11767
11816
  lockPrivateBalances: session.lockPrivateBalances,
11768
11817
  handleOnboard: session.handleOnboard,
11769
11818
  saveManualAesKey: session.saveManualAesKey,