@swype-org/react-sdk 0.1.35 → 0.1.36

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
@@ -4,6 +4,7 @@ var react = require('react');
4
4
  var reactAuth = require('@privy-io/react-auth');
5
5
  var wagmi = require('wagmi');
6
6
  var chains = require('wagmi/chains');
7
+ var connectors = require('wagmi/connectors');
7
8
  var reactQuery = require('@tanstack/react-query');
8
9
  var jsxRuntime = require('react/jsx-runtime');
9
10
  var viem = require('viem');
@@ -77,6 +78,7 @@ function getTheme(mode) {
77
78
  var SWYPE_PRIVY_APP_ID = "cmlil87uv004n0ck0blwumwek";
78
79
  var wagmiConfig = wagmi.createConfig({
79
80
  chains: [chains.mainnet, chains.arbitrum, chains.base],
81
+ connectors: [connectors.injected()],
80
82
  transports: {
81
83
  [chains.mainnet.id]: wagmi.http(),
82
84
  [chains.arbitrum.id]: wagmi.http(),
@@ -2563,13 +2565,20 @@ var WALLET_EMOJIS = {
2563
2565
  ora: "\u2666\uFE0F",
2564
2566
  phantom: "\u{1F47B}"
2565
2567
  };
2568
+ function truncateAddress(address) {
2569
+ if (address.length <= 10) return address;
2570
+ return `${address.slice(0, 6)}...${address.slice(-4)}`;
2571
+ }
2566
2572
  function WalletPickerScreen({
2567
2573
  providers,
2574
+ pendingConnections,
2568
2575
  onSelectProvider,
2576
+ onContinueConnection,
2569
2577
  onBack
2570
2578
  }) {
2571
2579
  const { tokens } = useSwypeConfig();
2572
2580
  const [hoveredId, setHoveredId] = react.useState(null);
2581
+ const hasPending = pendingConnections != null && pendingConnections.length > 0;
2573
2582
  const displayProviders = providers.length > 0 ? providers : [
2574
2583
  { id: "metamask", name: "MetaMask" },
2575
2584
  { id: "rabby", name: "Rabby" },
@@ -2585,8 +2594,44 @@ function WalletPickerScreen({
2585
2594
  ] }),
2586
2595
  children: [
2587
2596
  /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: "Set up Swype", onBack }),
2588
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle4(tokens.text), children: "Where are your stablecoins?" }),
2589
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle4(tokens.textSecondary), children: "Select the wallet you want to deposit from" }),
2597
+ hasPending && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2598
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle4(tokens.text), children: "Continue where you left off" }),
2599
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle4(tokens.textSecondary), children: "You have a wallet that still needs setup" }),
2600
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: pendingListStyle, children: pendingConnections.map((acct) => {
2601
+ const wallet = acct.wallets[0];
2602
+ const address = wallet ? truncateAddress(wallet.name) : void 0;
2603
+ const isHovered = hoveredId === `pending-${acct.id}`;
2604
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2605
+ "button",
2606
+ {
2607
+ onClick: () => onContinueConnection?.(acct.id),
2608
+ onMouseEnter: () => setHoveredId(`pending-${acct.id}`),
2609
+ onMouseLeave: () => setHoveredId(null),
2610
+ style: pendingCardStyle(tokens, isHovered),
2611
+ children: [
2612
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: pendingCardContentStyle, children: [
2613
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: pendingIconStyle, children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: emojiStyle, children: WALLET_EMOJIS[acct.name.toLowerCase()] ?? acct.name.charAt(0) }) }),
2614
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: pendingInfoStyle, children: [
2615
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: pendingNameStyle(tokens.text), children: acct.name }),
2616
+ address && /* @__PURE__ */ jsxRuntime.jsx("span", { style: pendingAddressStyle(tokens.textMuted), children: address })
2617
+ ] }),
2618
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: pendingBadgeStyle(tokens), children: "Setup incomplete" })
2619
+ ] }),
2620
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: continueRowStyle(tokens), children: [
2621
+ "Continue setup",
2622
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z", fill: "currentColor" }) })
2623
+ ] })
2624
+ ]
2625
+ },
2626
+ acct.id
2627
+ );
2628
+ }) }),
2629
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: dividerStyle2(tokens.border), children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: dividerTextStyle(tokens.textMuted), children: "Or connect a new wallet" }) })
2630
+ ] }),
2631
+ !hasPending && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2632
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle4(tokens.text), children: "Where are your stablecoins?" }),
2633
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle4(tokens.textSecondary), children: "Select the wallet you want to deposit from" })
2634
+ ] }),
2590
2635
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: gridStyle, children: [
2591
2636
  displayProviders.map((p) => {
2592
2637
  const emoji = WALLET_EMOJIS[p.name.toLowerCase()] ?? p.name.charAt(0);
@@ -2690,6 +2735,86 @@ var hintStyle2 = (color) => ({
2690
2735
  color,
2691
2736
  margin: "0 0 4px"
2692
2737
  });
2738
+ var pendingListStyle = {
2739
+ display: "flex",
2740
+ flexDirection: "column",
2741
+ gap: 10,
2742
+ marginBottom: 20
2743
+ };
2744
+ var pendingCardStyle = (tokens, hovered) => ({
2745
+ display: "flex",
2746
+ flexDirection: "column",
2747
+ gap: 0,
2748
+ padding: 0,
2749
+ background: hovered ? tokens.bgHover : tokens.bgInput,
2750
+ border: `1.5px solid ${tokens.warning}44`,
2751
+ borderRadius: 16,
2752
+ cursor: "pointer",
2753
+ fontFamily: "inherit",
2754
+ transition: "background 0.15s ease",
2755
+ outline: "none",
2756
+ overflow: "hidden",
2757
+ textAlign: "left"
2758
+ });
2759
+ var pendingCardContentStyle = {
2760
+ display: "flex",
2761
+ alignItems: "center",
2762
+ gap: 12,
2763
+ padding: "14px 16px"
2764
+ };
2765
+ var pendingIconStyle = {
2766
+ flexShrink: 0
2767
+ };
2768
+ var pendingInfoStyle = {
2769
+ display: "flex",
2770
+ flexDirection: "column",
2771
+ gap: 2,
2772
+ flex: 1,
2773
+ minWidth: 0
2774
+ };
2775
+ var pendingNameStyle = (color) => ({
2776
+ fontSize: "0.92rem",
2777
+ fontWeight: 600,
2778
+ color
2779
+ });
2780
+ var pendingAddressStyle = (color) => ({
2781
+ fontSize: "0.78rem",
2782
+ color,
2783
+ fontFamily: "monospace"
2784
+ });
2785
+ var pendingBadgeStyle = (tokens) => ({
2786
+ fontSize: "0.72rem",
2787
+ fontWeight: 600,
2788
+ color: tokens.warningText ?? tokens.warning,
2789
+ background: tokens.warningBg ?? `${tokens.warning}1a`,
2790
+ padding: "3px 8px",
2791
+ borderRadius: 6,
2792
+ whiteSpace: "nowrap",
2793
+ flexShrink: 0
2794
+ });
2795
+ var continueRowStyle = (tokens) => ({
2796
+ display: "flex",
2797
+ alignItems: "center",
2798
+ justifyContent: "center",
2799
+ gap: 4,
2800
+ padding: "10px 16px",
2801
+ fontSize: "0.84rem",
2802
+ fontWeight: 600,
2803
+ color: tokens.accent,
2804
+ background: `${tokens.accent}0d`,
2805
+ borderTop: `1px solid ${tokens.accent}22`
2806
+ });
2807
+ var dividerStyle2 = (borderColor) => ({
2808
+ display: "flex",
2809
+ alignItems: "center",
2810
+ gap: 12,
2811
+ margin: "4px 0 16px"
2812
+ });
2813
+ var dividerTextStyle = (color) => ({
2814
+ fontSize: "0.82rem",
2815
+ color,
2816
+ whiteSpace: "nowrap"
2817
+ });
2693
2818
  var DEFAULT_MAX = 500;
2694
2819
  var ABSOLUTE_MIN = 1;
2695
2820
  function buildTicks(min, max) {
@@ -3777,6 +3902,7 @@ function SwypePayment({
3777
3902
  const [setupComplete, setSetupComplete] = react.useState(false);
3778
3903
  const [setupStepLabel, setSetupStepLabel] = react.useState(void 0);
3779
3904
  const [mobileFlow, setMobileFlow] = react.useState(false);
3905
+ const [mobileSetupFlow, setMobileSetupFlow] = react.useState(false);
3780
3906
  const pollingTransferIdRef = react.useRef(null);
3781
3907
  const mobileSigningTransferIdRef = react.useRef(null);
3782
3908
  const processingStartedAtRef = react.useRef(null);
@@ -3789,6 +3915,23 @@ function SwypePayment({
3789
3915
  const transferSigning = useTransferSigning();
3790
3916
  const sourceType = connectingNewAccount ? "providerId" : selectedWalletId ? "walletId" : selectedAccountId ? "accountId" : "providerId";
3791
3917
  const sourceId = connectingNewAccount ? selectedProviderId ?? "" : selectedWalletId ? selectedWalletId : selectedAccountId ? selectedAccountId : selectedProviderId ?? "";
3918
+ const reloadAccounts = react.useCallback(async () => {
3919
+ const token = await getAccessToken();
3920
+ if (!token || !activeCredentialId) return;
3921
+ const [accts, prov] = await Promise.all([
3922
+ fetchAccounts(apiBaseUrl, token, activeCredentialId),
3923
+ fetchProviders(apiBaseUrl, token)
3924
+ ]);
3925
+ setAccounts(accts);
3926
+ setProviders(prov);
3927
+ const parsedAmt = depositAmount != null ? depositAmount : 0;
3928
+ const defaults = computeSmartDefaults(accts, parsedAmt);
3929
+ if (defaults) {
3930
+ setSelectedAccountId(defaults.accountId);
3931
+ setSelectedWalletId(defaults.walletId);
3932
+ setConnectingNewAccount(false);
3933
+ }
3934
+ }, [getAccessToken, activeCredentialId, apiBaseUrl, depositAmount]);
3792
3935
  react.useEffect(() => {
3793
3936
  if (depositAmount != null) {
3794
3937
  setAmount(depositAmount.toString());
@@ -3938,7 +4081,10 @@ function SwypePayment({
3938
4081
  } else if (prov.length > 0) {
3939
4082
  setSelectedProviderId(prov[0].id);
3940
4083
  }
3941
- if (accts.length === 0 && step === "deposit") {
4084
+ const hasActiveWallet = accts.some(
4085
+ (a) => a.wallets.some((w) => w.status === "ACTIVE")
4086
+ );
4087
+ if ((accts.length === 0 || !hasActiveWallet) && step === "deposit") {
3942
4088
  setStep("wallet-picker");
3943
4089
  }
3944
4090
  } catch (err) {
@@ -3997,7 +4143,24 @@ function SwypePayment({
3997
4143
  return () => window.clearTimeout(timeoutId);
3998
4144
  }, [step, polling.transfer, transfer, polling.stopPolling, onError]);
3999
4145
  react.useEffect(() => {
4000
- if (!mobileFlow) return;
4146
+ if (!mobileSetupFlow) return;
4147
+ const polledTransfer = polling.transfer;
4148
+ if (!polledTransfer) return;
4149
+ if (polledTransfer.status !== "AUTHORIZED" && polledTransfer.status !== "COMPLETED") return;
4150
+ polling.stopPolling();
4151
+ setMobileFlow(false);
4152
+ setMobileSetupFlow(false);
4153
+ const finishSetup = async () => {
4154
+ try {
4155
+ await reloadAccounts();
4156
+ } catch {
4157
+ }
4158
+ setStep("deposit");
4159
+ };
4160
+ void finishSetup();
4161
+ }, [mobileSetupFlow, polling, reloadAccounts]);
4162
+ react.useEffect(() => {
4163
+ if (!mobileFlow || mobileSetupFlow) return;
4001
4164
  const polledTransfer = polling.transfer;
4002
4165
  if (!polledTransfer || polledTransfer.status !== "AUTHORIZED") return;
4003
4166
  if (transferSigning.signing) return;
@@ -4015,7 +4178,7 @@ function SwypePayment({
4015
4178
  }
4016
4179
  };
4017
4180
  void sign();
4018
- }, [mobileFlow, polling.transfer, transferSigning, onError]);
4181
+ }, [mobileFlow, mobileSetupFlow, polling.transfer, transferSigning, onError]);
4019
4182
  react.useEffect(() => {
4020
4183
  if (!mobileFlow) return;
4021
4184
  const transferIdToResume = pollingTransferIdRef.current ?? transfer?.id;
@@ -4100,6 +4263,12 @@ function SwypePayment({
4100
4263
  },
4101
4264
  [selectSourceChoices, selectSourceRecommended]
4102
4265
  );
4266
+ const pendingConnections = react.useMemo(
4267
+ () => accounts.filter(
4268
+ (a) => a.wallets.length > 0 && !a.wallets.some((w) => w.status === "ACTIVE")
4269
+ ),
4270
+ [accounts]
4271
+ );
4103
4272
  const selectedAccount = accounts.find((a) => a.id === selectedAccountId);
4104
4273
  const selectedWallet = selectedAccount?.wallets.find((w) => w.id === selectedWalletId);
4105
4274
  const sourceName = selectedAccount?.name ?? selectedWallet?.chain.name ?? "Wallet";
@@ -4243,7 +4412,10 @@ function SwypePayment({
4243
4412
  await registerPasskey(apiBaseUrl, token, credentialId, publicKey);
4244
4413
  setActiveCredentialId(credentialId);
4245
4414
  window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
4246
- if (accounts.length === 0) {
4415
+ const hasActiveWallet = accounts.some(
4416
+ (a) => a.wallets.some((w) => w.status === "ACTIVE")
4417
+ );
4418
+ if (accounts.length === 0 || !hasActiveWallet) {
4247
4419
  setStep("wallet-picker");
4248
4420
  } else {
4249
4421
  setStep("deposit");
@@ -4253,14 +4425,17 @@ function SwypePayment({
4253
4425
  } finally {
4254
4426
  setRegisteringPasskey(false);
4255
4427
  }
4256
- }, [getAccessToken, user, apiBaseUrl, accounts.length]);
4428
+ }, [getAccessToken, user, apiBaseUrl, accounts]);
4257
4429
  const handleSkipPasskey = react.useCallback(() => {
4258
- if (accounts.length === 0) {
4430
+ const hasActiveWallet = accounts.some(
4431
+ (a) => a.wallets.some((w) => w.status === "ACTIVE")
4432
+ );
4433
+ if (accounts.length === 0 || !hasActiveWallet) {
4259
4434
  setStep("wallet-picker");
4260
4435
  } else {
4261
4436
  setStep("deposit");
4262
4437
  }
4263
- }, [accounts.length]);
4438
+ }, [accounts]);
4264
4439
  const handleSetupOneTap = react.useCallback(async (limit) => {
4265
4440
  setOneTapLimit(limit);
4266
4441
  setStep("setup-status");
@@ -4273,6 +4448,7 @@ function SwypePayment({
4273
4448
  if (!sourceId) {
4274
4449
  throw new Error("No wallet selected for setup.");
4275
4450
  }
4451
+ await updateUserConfig(apiBaseUrl, token, { defaultAllowance: limit });
4276
4452
  const setupAmount = depositAmount ?? MIN_SEND_AMOUNT_USD;
4277
4453
  const t = await createTransfer(apiBaseUrl, token, {
4278
4454
  id: idempotencyKey,
@@ -4290,11 +4466,16 @@ function SwypePayment({
4290
4466
  });
4291
4467
  if (!shouldUseConnector) {
4292
4468
  setMobileFlow(true);
4469
+ setMobileSetupFlow(true);
4470
+ pollingTransferIdRef.current = t.id;
4471
+ polling.startPolling(t.id);
4293
4472
  window.location.href = t.authorizationSessions[0].uri;
4473
+ return;
4294
4474
  } else {
4295
4475
  await authExecutor.executeSession(t);
4296
4476
  }
4297
4477
  }
4478
+ await reloadAccounts();
4298
4479
  setSetupStepLabel(void 0);
4299
4480
  setSetupComplete(true);
4300
4481
  } catch (err) {
@@ -4313,8 +4494,10 @@ function SwypePayment({
4313
4494
  merchantAuthorization,
4314
4495
  useWalletConnector,
4315
4496
  authExecutor,
4497
+ polling,
4316
4498
  onError,
4317
- depositAmount
4499
+ depositAmount,
4500
+ reloadAccounts
4318
4501
  ]);
4319
4502
  const handleSelectProvider = react.useCallback((providerId) => {
4320
4503
  setSelectedProviderId(providerId);
@@ -4322,12 +4505,23 @@ function SwypePayment({
4322
4505
  setConnectingNewAccount(true);
4323
4506
  setStep("setup");
4324
4507
  }, []);
4508
+ const handleContinueConnection = react.useCallback(
4509
+ (accountId) => {
4510
+ const acct = accounts.find((a) => a.id === accountId);
4511
+ setSelectedAccountId(accountId);
4512
+ setSelectedWalletId(acct?.wallets[0]?.id ?? null);
4513
+ setConnectingNewAccount(false);
4514
+ setStep("setup");
4515
+ },
4516
+ [accounts]
4517
+ );
4325
4518
  const handleNewPayment = react.useCallback(() => {
4326
4519
  setStep("deposit");
4327
4520
  setTransfer(null);
4328
4521
  setError(null);
4329
4522
  setAmount(depositAmount != null ? depositAmount.toString() : "");
4330
4523
  setMobileFlow(false);
4524
+ setMobileSetupFlow(false);
4331
4525
  processingStartedAtRef.current = null;
4332
4526
  pollingTransferIdRef.current = null;
4333
4527
  mobileSigningTransferIdRef.current = null;
@@ -4360,6 +4554,7 @@ function SwypePayment({
4360
4554
  setConnectingNewAccount(false);
4361
4555
  setAmount(depositAmount != null ? depositAmount.toString() : "");
4362
4556
  setMobileFlow(false);
4557
+ setMobileSetupFlow(false);
4363
4558
  setSetupComplete(false);
4364
4559
  resetHeadlessLogin();
4365
4560
  }, [logout, polling, depositAmount, resetHeadlessLogin]);
@@ -4423,7 +4618,9 @@ function SwypePayment({
4423
4618
  WalletPickerScreen,
4424
4619
  {
4425
4620
  providers,
4621
+ pendingConnections,
4426
4622
  onSelectProvider: handleSelectProvider,
4623
+ onContinueConnection: handleContinueConnection,
4427
4624
  onBack: () => setStep("create-passkey")
4428
4625
  }
4429
4626
  );
@@ -4562,6 +4759,16 @@ function SwypePayment({
4562
4759
  return null;
4563
4760
  }
4564
4761
 
4762
+ exports.IconCircle = IconCircle;
4763
+ exports.OutlineButton = OutlineButton;
4764
+ exports.PoweredByFooter = PoweredByFooter;
4765
+ exports.PrimaryButton = PrimaryButton;
4766
+ exports.ScreenHeader = ScreenHeader;
4767
+ exports.ScreenLayout = ScreenLayout;
4768
+ exports.SelectSourceScreen = SelectSourceScreen;
4769
+ exports.SettingsMenu = SettingsMenu;
4770
+ exports.Spinner = Spinner;
4771
+ exports.StepList = StepList;
4565
4772
  exports.SwypePayment = SwypePayment;
4566
4773
  exports.SwypeProvider = SwypeProvider;
4567
4774
  exports.createPasskeyCredential = createPasskeyCredential;