@swype-org/react-sdk 0.1.84 → 0.1.85

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.cjs CHANGED
@@ -788,6 +788,66 @@ function createPasskeyViaPopup(options, existingCredentialIds = []) {
788
788
  }
789
789
  });
790
790
  }
791
+ var VERIFY_POPUP_TIMEOUT_MS = 6e4;
792
+ function findDevicePasskeyViaPopup(options) {
793
+ return new Promise((resolve, reject) => {
794
+ const channelId = `swype-pv-${Date.now()}-${Math.random().toString(36).slice(2)}`;
795
+ const payload = { ...options, channelId };
796
+ const encoded = btoa(JSON.stringify(payload));
797
+ const popupUrl = `${window.location.origin}/passkey-verify#${encoded}`;
798
+ const popup = window.open(popupUrl, "swype-passkey-verify");
799
+ if (!popup) {
800
+ reject(new Error("Pop-up blocked. Please allow pop-ups for this site and try again."));
801
+ return;
802
+ }
803
+ let settled = false;
804
+ const channel = typeof BroadcastChannel !== "undefined" ? new BroadcastChannel(channelId) : null;
805
+ const timer = setTimeout(() => {
806
+ cleanup();
807
+ resolve(null);
808
+ }, VERIFY_POPUP_TIMEOUT_MS);
809
+ const closedPoll = setInterval(() => {
810
+ if (popup.closed && !settled) {
811
+ clearInterval(closedPoll);
812
+ setTimeout(() => {
813
+ if (!settled) {
814
+ cleanup();
815
+ resolve(null);
816
+ }
817
+ }, POPUP_CLOSED_GRACE_MS);
818
+ }
819
+ }, POPUP_CLOSED_POLL_MS);
820
+ function handleResult(data) {
821
+ if (settled) return;
822
+ if (!data || typeof data !== "object") return;
823
+ if (data.type !== "swype:passkey-verify-result") return;
824
+ settled = true;
825
+ cleanup();
826
+ if (data.error) {
827
+ resolve(null);
828
+ } else if (data.result && typeof data.result === "object") {
829
+ const result = data.result;
830
+ resolve(result.credentialId ?? null);
831
+ } else {
832
+ resolve(null);
833
+ }
834
+ }
835
+ if (channel) {
836
+ channel.onmessage = (event) => handleResult(event.data);
837
+ }
838
+ const postMessageHandler = (event) => {
839
+ if (event.source !== popup) return;
840
+ handleResult(event.data);
841
+ };
842
+ window.addEventListener("message", postMessageHandler);
843
+ function cleanup() {
844
+ clearTimeout(timer);
845
+ clearInterval(closedPoll);
846
+ window.removeEventListener("message", postMessageHandler);
847
+ channel?.close();
848
+ }
849
+ });
850
+ }
791
851
  async function checkServerForNewPasskey(authToken, apiBaseUrl, existingCredentialIds) {
792
852
  if (!authToken || !apiBaseUrl) return null;
793
853
  const res = await fetch(`${apiBaseUrl}/v1/users/config`, {
@@ -2773,6 +2833,72 @@ var errorBannerStyle2 = (tokens) => ({
2773
2833
  width: "100%",
2774
2834
  textAlign: "left"
2775
2835
  });
2836
+ function VerifyPasskeyScreen({
2837
+ onVerify,
2838
+ onBack,
2839
+ verifying,
2840
+ error
2841
+ }) {
2842
+ const { tokens } = useSwypeConfig();
2843
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2844
+ ScreenLayout,
2845
+ {
2846
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2847
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onVerify, disabled: verifying, loading: verifying, children: "Verify passkey" }),
2848
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2849
+ ] }),
2850
+ children: [
2851
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onBack }),
2852
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle4, children: [
2853
+ /* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "accent", size: 64, children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "36", height: "36", viewBox: "0 0 24 24", fill: "none", children: [
2854
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "3", stroke: tokens.accent, strokeWidth: "1.5", strokeDasharray: "3 2" }),
2855
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "10", r: "1", fill: tokens.accent }),
2856
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "15", cy: "10", r: "1", fill: tokens.accent }),
2857
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 14c0 1.5 1.34 2.5 3 2.5s3-1 3-2.5", stroke: tokens.accent, strokeWidth: "1.2", strokeLinecap: "round" })
2858
+ ] }) }),
2859
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle4(tokens.text), children: "Verify your passkey" }),
2860
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle4(tokens.textSecondary), children: "Your browser requires a separate window to verify your passkey. Tap the button below to continue." }),
2861
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle3(tokens), children: error }),
2862
+ /* @__PURE__ */ jsxRuntime.jsx(InfoBanner, { children: "Your passkey is stored securely on your device. Swype never sees your biometric data." })
2863
+ ] })
2864
+ ]
2865
+ }
2866
+ );
2867
+ }
2868
+ var contentStyle4 = {
2869
+ textAlign: "center",
2870
+ flex: 1,
2871
+ display: "flex",
2872
+ flexDirection: "column",
2873
+ alignItems: "center",
2874
+ paddingTop: 32
2875
+ };
2876
+ var headingStyle4 = (color) => ({
2877
+ fontSize: "1.45rem",
2878
+ fontWeight: 700,
2879
+ letterSpacing: "-0.02em",
2880
+ color,
2881
+ margin: "24px 0 8px"
2882
+ });
2883
+ var subtitleStyle4 = (color) => ({
2884
+ fontSize: "0.9rem",
2885
+ color,
2886
+ margin: "0 0 28px",
2887
+ lineHeight: 1.5,
2888
+ maxWidth: 280
2889
+ });
2890
+ var errorBannerStyle3 = (tokens) => ({
2891
+ background: tokens.errorBg,
2892
+ border: `1px solid ${tokens.error}66`,
2893
+ borderRadius: 16,
2894
+ padding: "11px 14px",
2895
+ color: tokens.error,
2896
+ fontSize: "0.84rem",
2897
+ marginBottom: 14,
2898
+ lineHeight: 1.5,
2899
+ width: "100%",
2900
+ textAlign: "left"
2901
+ });
2776
2902
  var WALLET_EMOJIS = {
2777
2903
  rabby: "\u{1F430}",
2778
2904
  ora: "\u2666\uFE0F",
@@ -2815,8 +2941,8 @@ function WalletPickerScreen({
2815
2941
  children: [
2816
2942
  /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: "Set up Swype", onBack }),
2817
2943
  hasPending && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2818
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle4(tokens.text), children: "Continue where you left off" }),
2819
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle4(tokens.textSecondary), children: "You have a wallet that still needs setup" }),
2944
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle5(tokens.text), children: "Continue where you left off" }),
2945
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle5(tokens.textSecondary), children: "You have a wallet that still needs setup" }),
2820
2946
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: pendingListStyle, children: pendingConnections.map((acct) => {
2821
2947
  const wallet = acct.wallets[0];
2822
2948
  const address = wallet ? truncateAddress(wallet.name) : void 0;
@@ -2856,8 +2982,8 @@ function WalletPickerScreen({
2856
2982
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: dividerStyle2(tokens.border), children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: dividerTextStyle(tokens.textMuted), children: "Or connect a new wallet" }) })
2857
2983
  ] }),
2858
2984
  !hasPending && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2859
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle4(tokens.text), children: "Where are your stablecoins?" }),
2860
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle4(tokens.textSecondary), children: "Select the wallet you want to deposit from" })
2985
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle5(tokens.text), children: "Where are your stablecoins?" }),
2986
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle5(tokens.textSecondary), children: "Select the wallet you want to deposit from" })
2861
2987
  ] }),
2862
2988
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: gridStyle, children: [
2863
2989
  displayProviders.map((p) => {
@@ -2910,14 +3036,14 @@ function WalletPickerScreen({
2910
3036
  }
2911
3037
  );
2912
3038
  }
2913
- var headingStyle4 = (color) => ({
3039
+ var headingStyle5 = (color) => ({
2914
3040
  fontSize: "1.35rem",
2915
3041
  fontWeight: 700,
2916
3042
  letterSpacing: "-0.02em",
2917
3043
  color,
2918
3044
  margin: "8px 0 4px"
2919
3045
  });
2920
- var subtitleStyle4 = (color) => ({
3046
+ var subtitleStyle5 = (color) => ({
2921
3047
  fontSize: "0.88rem",
2922
3048
  color,
2923
3049
  margin: "0 0 24px"
@@ -3093,9 +3219,9 @@ function SetupScreen({
3093
3219
  ] }),
3094
3220
  children: [
3095
3221
  /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: "Swype Setup", onBack, right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
3096
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle5(tokens.text), children: "Set up One-Tap deposits" }),
3097
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle5(tokens.textSecondary), children: "Set your limit for instant deposits. Like a contactless card \u2014 you choose the max." }),
3098
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle3(tokens), children: error }),
3222
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle6(tokens.text), children: "Set up One-Tap deposits" }),
3223
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle6(tokens.textSecondary), children: "Set your limit for instant deposits. Like a contactless card \u2014 you choose the max." }),
3224
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle4(tokens), children: error }),
3099
3225
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceRowStyle, children: [
3100
3226
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceLeftStyle, children: [
3101
3227
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: coinIconStyle(tokens.accent), children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [
@@ -3173,20 +3299,20 @@ function SetupScreen({
3173
3299
  }
3174
3300
  );
3175
3301
  }
3176
- var headingStyle5 = (color) => ({
3302
+ var headingStyle6 = (color) => ({
3177
3303
  fontSize: "1.3rem",
3178
3304
  fontWeight: 700,
3179
3305
  letterSpacing: "-0.02em",
3180
3306
  color,
3181
3307
  margin: "8px 0 4px"
3182
3308
  });
3183
- var subtitleStyle5 = (color) => ({
3309
+ var subtitleStyle6 = (color) => ({
3184
3310
  fontSize: "0.86rem",
3185
3311
  color,
3186
3312
  margin: "0 0 24px",
3187
3313
  lineHeight: 1.5
3188
3314
  });
3189
- var errorBannerStyle3 = (tokens) => ({
3315
+ var errorBannerStyle4 = (tokens) => ({
3190
3316
  background: tokens.errorBg,
3191
3317
  border: `1px solid ${tokens.error}66`,
3192
3318
  borderRadius: 16,
@@ -3454,7 +3580,7 @@ function DepositScreen({
3454
3580
  "%)"
3455
3581
  ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: detailRowStyle(tokens.textMuted), children: "Fees calculated at time of transfer" })
3456
3582
  ] }),
3457
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle4(tokens), children: error })
3583
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle5(tokens), children: error })
3458
3584
  ]
3459
3585
  }
3460
3586
  );
@@ -3522,7 +3648,7 @@ var detailRowStyle = (color) => ({
3522
3648
  color,
3523
3649
  marginBottom: 4
3524
3650
  });
3525
- var errorBannerStyle4 = (tokens) => ({
3651
+ var errorBannerStyle5 = (tokens) => ({
3526
3652
  background: tokens.errorBg,
3527
3653
  border: `1px solid ${tokens.error}66`,
3528
3654
  borderRadius: 16,
@@ -3621,22 +3747,22 @@ function SuccessScreen({
3621
3747
  right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout })
3622
3748
  }
3623
3749
  ),
3624
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle4, children: [
3750
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle5, children: [
3625
3751
  succeeded ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3626
3752
  /* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "success", size: 64, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z", fill: tokens.success }) }) }),
3627
- /* @__PURE__ */ jsxRuntime.jsxs("h2", { style: headingStyle6(tokens.text), children: [
3753
+ /* @__PURE__ */ jsxRuntime.jsxs("h2", { style: headingStyle7(tokens.text), children: [
3628
3754
  "$",
3629
3755
  amount.toFixed(2),
3630
3756
  " deposited"
3631
3757
  ] }),
3632
- merchantName && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: subtitleStyle6(tokens.textSecondary), children: [
3758
+ merchantName && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: subtitleStyle7(tokens.textSecondary), children: [
3633
3759
  "to ",
3634
3760
  merchantName
3635
3761
  ] })
3636
3762
  ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3637
3763
  /* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "error", size: 64, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z", fill: tokens.error }) }) }),
3638
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle6(tokens.text), children: "Transfer failed" }),
3639
- error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle6(tokens.error), children: error })
3764
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle7(tokens.text), children: "Transfer failed" }),
3765
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle7(tokens.error), children: error })
3640
3766
  ] }),
3641
3767
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryCardStyle(tokens), children: [
3642
3768
  sourceName && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryRowStyle, children: [
@@ -3668,21 +3794,21 @@ function SuccessScreen({
3668
3794
  }
3669
3795
  );
3670
3796
  }
3671
- var contentStyle4 = {
3797
+ var contentStyle5 = {
3672
3798
  flex: 1,
3673
3799
  display: "flex",
3674
3800
  flexDirection: "column",
3675
3801
  alignItems: "center",
3676
3802
  paddingTop: 16
3677
3803
  };
3678
- var headingStyle6 = (color) => ({
3804
+ var headingStyle7 = (color) => ({
3679
3805
  fontSize: "1.5rem",
3680
3806
  fontWeight: 700,
3681
3807
  letterSpacing: "-0.02em",
3682
3808
  color,
3683
3809
  margin: "20px 0 4px"
3684
3810
  });
3685
- var subtitleStyle6 = (color) => ({
3811
+ var subtitleStyle7 = (color) => ({
3686
3812
  fontSize: "0.9rem",
3687
3813
  color,
3688
3814
  margin: "0 0 20px"
@@ -3788,7 +3914,7 @@ function SelectSourceScreen({
3788
3914
  right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout })
3789
3915
  }
3790
3916
  ),
3791
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle7(tokens.textMuted), children: "Choose which chain and token to pay from." }),
3917
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle8(tokens.textMuted), children: "Choose which chain and token to pay from." }),
3792
3918
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle2(tokens.textSecondary), children: "Chain" }),
3793
3919
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: optionListStyle, children: choices.map((chain) => {
3794
3920
  const isSelected = chain.chainName === selectedChainName;
@@ -3845,7 +3971,7 @@ function SelectSourceScreen({
3845
3971
  }
3846
3972
  );
3847
3973
  }
3848
- var subtitleStyle7 = (color) => ({
3974
+ var subtitleStyle8 = (color) => ({
3849
3975
  fontSize: "0.85rem",
3850
3976
  color,
3851
3977
  margin: "0 0 20px",
@@ -3960,8 +4086,8 @@ function AdvancedSourceScreen({
3960
4086
  right: /* @__PURE__ */ jsxRuntime.jsx("span", { style: advancedBadgeStyle(tokens.accent), children: "Advanced" })
3961
4087
  }
3962
4088
  ),
3963
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle7(tokens.text), children: "Set up One-Tap deposits" }),
3964
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle8(tokens.textSecondary), children: "Select a token source for your One-Tap deposits." }),
4089
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle8(tokens.text), children: "Set up One-Tap deposits" }),
4090
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle9(tokens.textSecondary), children: "Select a token source for your One-Tap deposits." }),
3965
4091
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle3(tokens.textSecondary), children: "Select tokens to approve" }),
3966
4092
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: chainListStyle, children: choices.map((chain) => {
3967
4093
  const isExpanded = expandedChain === chain.chainName;
@@ -4024,14 +4150,14 @@ var advancedBadgeStyle = (color) => ({
4024
4150
  padding: "3px 10px",
4025
4151
  letterSpacing: "0.02em"
4026
4152
  });
4027
- var headingStyle7 = (color) => ({
4153
+ var headingStyle8 = (color) => ({
4028
4154
  fontSize: "1.3rem",
4029
4155
  fontWeight: 700,
4030
4156
  letterSpacing: "-0.02em",
4031
4157
  color,
4032
4158
  margin: "8px 0 4px"
4033
4159
  });
4034
- var subtitleStyle8 = (color) => ({
4160
+ var subtitleStyle9 = (color) => ({
4035
4161
  fontSize: "0.86rem",
4036
4162
  color,
4037
4163
  margin: "0 0 20px",
@@ -4159,16 +4285,16 @@ function TransferStatusScreen({
4159
4285
  const steps = buildSteps(phase);
4160
4286
  return /* @__PURE__ */ jsxRuntime.jsxs(ScreenLayout, { children: [
4161
4287
  /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
4162
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle5, children: [
4288
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle6, children: [
4163
4289
  /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 48 }),
4164
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle8(tokens.text), children: "Processing Transfer..." }),
4165
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle5(tokens), children: error }),
4290
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle9(tokens.text), children: "Processing Transfer..." }),
4291
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle6(tokens), children: error }),
4166
4292
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: stepsWrapStyle, children: /* @__PURE__ */ jsxRuntime.jsx(StepList, { steps }) }),
4167
4293
  /* @__PURE__ */ jsxRuntime.jsx("p", { style: waitHintStyle(tokens.textMuted), children: "Usually takes a few seconds" })
4168
4294
  ] })
4169
4295
  ] });
4170
4296
  }
4171
- var contentStyle5 = {
4297
+ var contentStyle6 = {
4172
4298
  flex: 1,
4173
4299
  display: "flex",
4174
4300
  flexDirection: "column",
@@ -4177,14 +4303,14 @@ var contentStyle5 = {
4177
4303
  textAlign: "center",
4178
4304
  padding: "0 24px"
4179
4305
  };
4180
- var headingStyle8 = (color) => ({
4306
+ var headingStyle9 = (color) => ({
4181
4307
  fontSize: "1.45rem",
4182
4308
  fontWeight: 700,
4183
4309
  letterSpacing: "-0.02em",
4184
4310
  color,
4185
4311
  margin: "20px 0 16px"
4186
4312
  });
4187
- var errorBannerStyle5 = (tokens) => ({
4313
+ var errorBannerStyle6 = (tokens) => ({
4188
4314
  background: tokens.errorBg,
4189
4315
  border: `1px solid ${tokens.error}66`,
4190
4316
  borderRadius: 16,
@@ -4244,10 +4370,10 @@ function OpenWalletScreen({
4244
4370
  ] }),
4245
4371
  children: [
4246
4372
  /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
4247
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle6, children: [
4373
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle7, children: [
4248
4374
  logoSrc ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoSrc, alt: displayName, style: logoStyle }) : /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 48 }),
4249
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle9(tokens.text), children: loading ? "Connecting..." : `Open ${displayName}` }),
4250
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle9(tokens.textSecondary), children: loading ? "Creating transfer and preparing your wallet link..." : `Continue in ${displayName} to authorize this connection.` }),
4375
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle10(tokens.text), children: loading ? "Connecting..." : `Open ${displayName}` }),
4376
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle10(tokens.textSecondary), children: loading ? "Creating transfer and preparing your wallet link..." : `Continue in ${displayName} to authorize this connection.` }),
4251
4377
  !loading && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: waitingBadgeStyle(tokens), children: [
4252
4378
  /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 14 }),
4253
4379
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Waiting for authorization..." })
@@ -4257,7 +4383,7 @@ function OpenWalletScreen({
4257
4383
  }
4258
4384
  );
4259
4385
  }
4260
- var contentStyle6 = {
4386
+ var contentStyle7 = {
4261
4387
  flex: 1,
4262
4388
  display: "flex",
4263
4389
  flexDirection: "column",
@@ -4277,14 +4403,14 @@ var logoStyle = {
4277
4403
  borderRadius: 14,
4278
4404
  objectFit: "contain"
4279
4405
  };
4280
- var headingStyle9 = (color) => ({
4406
+ var headingStyle10 = (color) => ({
4281
4407
  fontSize: "1.45rem",
4282
4408
  fontWeight: 700,
4283
4409
  letterSpacing: "-0.02em",
4284
4410
  color,
4285
4411
  margin: "20px 0 8px"
4286
4412
  });
4287
- var subtitleStyle9 = (color) => ({
4413
+ var subtitleStyle10 = (color) => ({
4288
4414
  fontSize: "0.9rem",
4289
4415
  color,
4290
4416
  margin: "0 0 24px",
@@ -4328,10 +4454,10 @@ function ConfirmSignScreen({
4328
4454
  ] }),
4329
4455
  children: [
4330
4456
  /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
4331
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle7, children: [
4457
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle8, children: [
4332
4458
  logoSrc ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoSrc, alt: displayName, style: logoStyle2 }) : /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 48 }),
4333
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle10(tokens.text), children: "Wallet authorized" }),
4334
- /* @__PURE__ */ jsxRuntime.jsxs("p", { style: subtitleStyle10(tokens.textSecondary), children: [
4459
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle11(tokens.text), children: "Wallet authorized" }),
4460
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: subtitleStyle11(tokens.textSecondary), children: [
4335
4461
  displayName,
4336
4462
  " approved the connection. Tap below to confirm your payment."
4337
4463
  ] }),
@@ -4344,7 +4470,7 @@ function ConfirmSignScreen({
4344
4470
  }
4345
4471
  );
4346
4472
  }
4347
- var contentStyle7 = {
4473
+ var contentStyle8 = {
4348
4474
  flex: 1,
4349
4475
  display: "flex",
4350
4476
  flexDirection: "column",
@@ -4359,14 +4485,14 @@ var logoStyle2 = {
4359
4485
  borderRadius: 14,
4360
4486
  objectFit: "contain"
4361
4487
  };
4362
- var headingStyle10 = (color) => ({
4488
+ var headingStyle11 = (color) => ({
4363
4489
  fontSize: "1.45rem",
4364
4490
  fontWeight: 700,
4365
4491
  letterSpacing: "-0.02em",
4366
4492
  color,
4367
4493
  margin: "20px 0 8px"
4368
4494
  });
4369
- var subtitleStyle10 = (color) => ({
4495
+ var subtitleStyle11 = (color) => ({
4370
4496
  fontSize: "0.9rem",
4371
4497
  color,
4372
4498
  margin: "0 0 24px",
@@ -4425,7 +4551,7 @@ var PaymentErrorBoundary = class extends react.Component {
4425
4551
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 8v5", stroke: "#ef4444", strokeWidth: "1.5", strokeLinecap: "round" }),
4426
4552
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "16", r: "0.75", fill: "#ef4444" })
4427
4553
  ] }) }),
4428
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle11, children: "Something went wrong" }),
4554
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle12, children: "Something went wrong" }),
4429
4555
  /* @__PURE__ */ jsxRuntime.jsx("p", { style: messageStyle, children: "An unexpected error occurred. Please try again." }),
4430
4556
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: this.handleReset, style: buttonStyle3, children: "Try again" })
4431
4557
  ] });
@@ -4445,7 +4571,7 @@ var containerStyle8 = {
4445
4571
  var iconStyle4 = {
4446
4572
  marginBottom: 20
4447
4573
  };
4448
- var headingStyle11 = {
4574
+ var headingStyle12 = {
4449
4575
  fontSize: "1.25rem",
4450
4576
  fontWeight: 700,
4451
4577
  color: "#1a1a1a",
@@ -4608,6 +4734,7 @@ function SwypePaymentInner({
4608
4734
  const [transfer, setTransfer] = react.useState(null);
4609
4735
  const [creatingTransfer, setCreatingTransfer] = react.useState(false);
4610
4736
  const [registeringPasskey, setRegisteringPasskey] = react.useState(false);
4737
+ const [verifyingPasskeyPopup, setVerifyingPasskeyPopup] = react.useState(false);
4611
4738
  const [passkeyPopupNeeded, setPasskeyPopupNeeded] = react.useState(
4612
4739
  () => isSafari() && isInCrossOriginIframe()
4613
4740
  );
@@ -4916,6 +5043,10 @@ function SwypePaymentInner({
4916
5043
  }
4917
5044
  if (cancelled) return;
4918
5045
  const credentialIds = allPasskeys.map((p) => p.credentialId);
5046
+ if (isSafari() && isInCrossOriginIframe()) {
5047
+ setStep("verify-passkey");
5048
+ return;
5049
+ }
4919
5050
  const matched = await findDevicePasskey(credentialIds);
4920
5051
  if (cancelled) return;
4921
5052
  if (matched) {
@@ -5442,6 +5573,27 @@ function SwypePaymentInner({
5442
5573
  setRegisteringPasskey(false);
5443
5574
  }
5444
5575
  }, [user, completePasskeyRegistration, getAccessToken, apiBaseUrl, knownCredentialIds]);
5576
+ const handleVerifyPasskeyViaPopup = react.useCallback(async () => {
5577
+ setVerifyingPasskeyPopup(true);
5578
+ setError(null);
5579
+ try {
5580
+ const matched = await findDevicePasskeyViaPopup({
5581
+ credentialIds: knownCredentialIds,
5582
+ rpId: resolvePasskeyRpId()
5583
+ });
5584
+ if (matched) {
5585
+ setActiveCredentialId(matched);
5586
+ window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, matched);
5587
+ setStep("login");
5588
+ } else {
5589
+ setStep("create-passkey");
5590
+ }
5591
+ } catch {
5592
+ setStep("create-passkey");
5593
+ } finally {
5594
+ setVerifyingPasskeyPopup(false);
5595
+ }
5596
+ }, [knownCredentialIds]);
5445
5597
  const handleSelectProvider = react.useCallback((providerId) => {
5446
5598
  setSelectedProviderId(providerId);
5447
5599
  setSelectedAccountId(null);
@@ -5573,6 +5725,17 @@ function SwypePaymentInner({
5573
5725
  if ((step === "login" || step === "otp-verify") && authenticated) {
5574
5726
  return /* @__PURE__ */ jsxRuntime.jsx(ScreenLayout, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", padding: "48px 0", flex: 1, display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { label: "Verifying your passkey..." }) }) });
5575
5727
  }
5728
+ if (step === "verify-passkey") {
5729
+ return /* @__PURE__ */ jsxRuntime.jsx(
5730
+ VerifyPasskeyScreen,
5731
+ {
5732
+ onVerify: handleVerifyPasskeyViaPopup,
5733
+ onBack: handleLogout,
5734
+ verifying: verifyingPasskeyPopup,
5735
+ error
5736
+ }
5737
+ );
5738
+ }
5576
5739
  if (step === "create-passkey") {
5577
5740
  return /* @__PURE__ */ jsxRuntime.jsx(
5578
5741
  CreatePasskeyScreen,
@@ -5757,8 +5920,10 @@ exports.createPasskeyViaPopup = createPasskeyViaPopup;
5757
5920
  exports.darkTheme = darkTheme;
5758
5921
  exports.deviceHasPasskey = deviceHasPasskey;
5759
5922
  exports.findDevicePasskey = findDevicePasskey;
5923
+ exports.findDevicePasskeyViaPopup = findDevicePasskeyViaPopup;
5760
5924
  exports.getTheme = getTheme;
5761
5925
  exports.lightTheme = lightTheme;
5926
+ exports.resolvePasskeyRpId = resolvePasskeyRpId;
5762
5927
  exports.swypeApi = api_exports;
5763
5928
  exports.useAuthorizationExecutor = useAuthorizationExecutor;
5764
5929
  exports.useSwypeConfig = useSwypeConfig;