@swype-org/react-sdk 0.1.112 → 0.1.115

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
@@ -238,7 +238,10 @@ async function createAccount(apiBaseUrl, token, params) {
238
238
  if (!res.ok) await throwApiError(res);
239
239
  return await res.json();
240
240
  }
241
- async function createAccountAuthorizationSession(apiBaseUrl, token, accountId, credentialId) {
241
+ async function createAccountAuthorizationSession(apiBaseUrl, token, accountId, credentialId, options) {
242
+ const body = { credentialId };
243
+ if (options?.tokenAddress) body.tokenAddress = options.tokenAddress;
244
+ if (options?.chainId != null) body.chainId = options.chainId;
242
245
  const res = await fetch(
243
246
  `${apiBaseUrl}/v1/accounts/${accountId}/authorization-sessions`,
244
247
  {
@@ -247,7 +250,7 @@ async function createAccountAuthorizationSession(apiBaseUrl, token, accountId, c
247
250
  "Content-Type": "application/json",
248
251
  Authorization: `Bearer ${token}`
249
252
  },
250
- body: JSON.stringify({ credentialId })
253
+ body: JSON.stringify(body)
251
254
  }
252
255
  );
253
256
  if (!res.ok) await throwApiError(res);
@@ -1929,6 +1932,7 @@ function createInitialState(config) {
1929
1932
  selectedProviderId: null,
1930
1933
  selectedAccountId: null,
1931
1934
  selectedWalletId: null,
1935
+ selectedTokenSymbol: null,
1932
1936
  amount: config.depositAmount != null ? config.depositAmount.toString() : "",
1933
1937
  transfer: null,
1934
1938
  creatingTransfer: false,
@@ -2023,7 +2027,8 @@ function paymentReducer(state, action) {
2023
2027
  ...state,
2024
2028
  selectedProviderId: action.providerId,
2025
2029
  selectedAccountId: null,
2026
- selectedWalletId: null
2030
+ selectedWalletId: null,
2031
+ selectedTokenSymbol: null
2027
2032
  };
2028
2033
  case "SELECT_ACCOUNT":
2029
2034
  return {
@@ -2032,6 +2037,13 @@ function paymentReducer(state, action) {
2032
2037
  selectedWalletId: action.walletId,
2033
2038
  step: "deposit"
2034
2039
  };
2040
+ case "SELECT_TOKEN":
2041
+ return {
2042
+ ...state,
2043
+ selectedWalletId: action.walletId,
2044
+ selectedTokenSymbol: action.tokenSymbol,
2045
+ step: "deposit"
2046
+ };
2035
2047
  // ── Transfer lifecycle ───────────────────────────────────────
2036
2048
  case "PAY_STARTED":
2037
2049
  return {
@@ -4205,7 +4217,8 @@ function DepositScreen({
4205
4217
  selectedAccountId,
4206
4218
  onSelectAccount,
4207
4219
  onAuthorizeAccount,
4208
- onAddProvider
4220
+ onAddProvider,
4221
+ onSelectToken
4209
4222
  }) {
4210
4223
  const { tokens } = useSwypeConfig();
4211
4224
  const amount = initialAmount;
@@ -4335,12 +4348,20 @@ function DepositScreen({
4335
4348
  ] })
4336
4349
  ] })
4337
4350
  ] }),
4338
- tokenCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenBadgeStyle(tokens), children: [
4339
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenDotStyle2(tokens.accent) }),
4340
- tokenCount,
4341
- " ",
4342
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: chevronStyle2, children: ">" })
4343
- ] })
4351
+ tokenCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
4352
+ "button",
4353
+ {
4354
+ type: "button",
4355
+ onClick: onSelectToken,
4356
+ style: tokenBadgeButtonStyle2(tokens, !!onSelectToken),
4357
+ children: [
4358
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenDotStyle2(tokens.accent) }),
4359
+ tokenCount,
4360
+ " ",
4361
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: chevronInlineStyle, children: ">" })
4362
+ ]
4363
+ }
4364
+ )
4344
4365
  ] }),
4345
4366
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: detailsStyle, children: [
4346
4367
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: detailRowStyle(tokens.textMuted), children: [
@@ -4398,7 +4419,7 @@ var balanceAmountStyle = {
4398
4419
  fontSize: "1rem",
4399
4420
  fontWeight: 700
4400
4421
  };
4401
- var tokenBadgeStyle = (tokens) => ({
4422
+ var tokenBadgeButtonStyle2 = (tokens, clickable) => ({
4402
4423
  display: "flex",
4403
4424
  alignItems: "center",
4404
4425
  gap: 4,
@@ -4406,7 +4427,10 @@ var tokenBadgeStyle = (tokens) => ({
4406
4427
  color: tokens.textMuted,
4407
4428
  border: `1px solid ${tokens.border}`,
4408
4429
  borderRadius: 999,
4409
- padding: "4px 10px"
4430
+ padding: "4px 10px",
4431
+ background: "transparent",
4432
+ fontFamily: "inherit",
4433
+ cursor: clickable ? "pointer" : "default"
4410
4434
  });
4411
4435
  var tokenDotStyle2 = (color) => ({
4412
4436
  width: 8,
@@ -4415,7 +4439,7 @@ var tokenDotStyle2 = (color) => ({
4415
4439
  background: color,
4416
4440
  display: "inline-block"
4417
4441
  });
4418
- var chevronStyle2 = { fontSize: "0.68rem", marginLeft: 2 };
4442
+ var chevronInlineStyle = { fontSize: "0.68rem", marginLeft: 2 };
4419
4443
  var detailsStyle = {
4420
4444
  textAlign: "center",
4421
4445
  marginTop: 12,
@@ -5304,6 +5328,236 @@ var errorStyle2 = (color) => ({
5304
5328
  color: "#ef4444",
5305
5329
  margin: "8px 0 0"
5306
5330
  });
5331
+ function TokenPickerScreen({
5332
+ account,
5333
+ chains,
5334
+ onSelectAuthorized,
5335
+ onAuthorizeToken,
5336
+ onBack
5337
+ }) {
5338
+ const { tokens: themeTokens } = useSwypeConfig();
5339
+ const [selectedIndex, setSelectedIndex] = react.useState(null);
5340
+ const entries = [];
5341
+ for (const wallet of account.wallets) {
5342
+ for (const source of wallet.sources) {
5343
+ entries.push({
5344
+ walletId: wallet.id,
5345
+ chainName: wallet.chain.name,
5346
+ tokenSymbol: source.token.symbol,
5347
+ tokenAddress: source.address,
5348
+ balance: source.balance.total.amount,
5349
+ status: source.token.status
5350
+ });
5351
+ }
5352
+ }
5353
+ const selected = selectedIndex != null ? entries[selectedIndex] : null;
5354
+ const isAuthorized = selected?.status === "AUTHORIZED";
5355
+ const handleConfirm = () => {
5356
+ if (!selected) return;
5357
+ if (isAuthorized) {
5358
+ onSelectAuthorized(selected.walletId, selected.tokenSymbol);
5359
+ } else {
5360
+ const chain = chains.find((c) => c.name === selected.chainName);
5361
+ const evmChainId = chain?.commonId;
5362
+ if (evmChainId == null) return;
5363
+ onAuthorizeToken(selected.walletId, selected.tokenAddress, evmChainId, selected.tokenSymbol);
5364
+ }
5365
+ };
5366
+ const chainGroups = /* @__PURE__ */ new Map();
5367
+ for (const entry of entries) {
5368
+ const group = chainGroups.get(entry.chainName);
5369
+ if (group) {
5370
+ group.push(entry);
5371
+ } else {
5372
+ chainGroups.set(entry.chainName, [entry]);
5373
+ }
5374
+ }
5375
+ const [expandedChain, setExpandedChain] = react.useState(
5376
+ entries.length > 0 ? entries[0].chainName : null
5377
+ );
5378
+ return /* @__PURE__ */ jsxRuntime.jsxs(
5379
+ ScreenLayout,
5380
+ {
5381
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5382
+ /* @__PURE__ */ jsxRuntime.jsx(
5383
+ PrimaryButton,
5384
+ {
5385
+ onClick: handleConfirm,
5386
+ disabled: selected == null,
5387
+ children: selected == null ? "Select a token" : isAuthorized ? "Select Source" : "Authorize Token"
5388
+ }
5389
+ ),
5390
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
5391
+ ] }),
5392
+ children: [
5393
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: "Select Token", onBack }),
5394
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle11(themeTokens.textSecondary), children: "Choose a token to deposit with. Tokens that haven't been authorized yet will require a one-time wallet approval." }),
5395
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: chainListStyle2, children: [...chainGroups.entries()].map(([chainName, chainEntries]) => {
5396
+ const isExpanded = expandedChain === chainName;
5397
+ const chainTotal = chainEntries.reduce((sum, e) => sum + e.balance, 0);
5398
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: chainCardStyle2(themeTokens), children: [
5399
+ /* @__PURE__ */ jsxRuntime.jsxs(
5400
+ "button",
5401
+ {
5402
+ type: "button",
5403
+ onClick: () => setExpandedChain((prev) => prev === chainName ? null : chainName),
5404
+ style: chainHeaderStyle2(themeTokens),
5405
+ children: [
5406
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: chainHeaderLeftStyle2, children: [
5407
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: chainNameStyle2(themeTokens.text), children: chainName }),
5408
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: chainBalanceStyle2(themeTokens.textMuted), children: [
5409
+ "$",
5410
+ chainTotal.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
5411
+ ] })
5412
+ ] }),
5413
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: chevronStyle2(themeTokens.textMuted), children: isExpanded ? "\u25BE" : "\u25B8" })
5414
+ ]
5415
+ }
5416
+ ),
5417
+ isExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenListStyle2, children: chainEntries.map((entry) => {
5418
+ const globalIdx = entries.indexOf(entry);
5419
+ const isSelected = selectedIndex === globalIdx;
5420
+ const authorized = entry.status === "AUTHORIZED";
5421
+ return /* @__PURE__ */ jsxRuntime.jsxs(
5422
+ "button",
5423
+ {
5424
+ type: "button",
5425
+ onClick: () => setSelectedIndex(globalIdx),
5426
+ style: tokenRowStyle2(themeTokens, isSelected),
5427
+ children: [
5428
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenInfoStyle2, children: [
5429
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenHeaderRowStyle, children: [
5430
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenSymbolStyle2(themeTokens.text), children: entry.tokenSymbol }),
5431
+ authorized ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: statusBadgeStyle(themeTokens.success), children: "Authorized" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: statusBadgeStyle(themeTokens.textMuted), children: "Not authorized" })
5432
+ ] }),
5433
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: tokenBalStyle2(themeTokens.textMuted), children: [
5434
+ "$",
5435
+ entry.balance.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
5436
+ ] })
5437
+ ] }),
5438
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: radioStyle3(themeTokens, isSelected), children: isSelected && /* @__PURE__ */ jsxRuntime.jsx("div", { style: radioDotStyle3(themeTokens.accent) }) })
5439
+ ]
5440
+ },
5441
+ `${entry.walletId}-${entry.tokenSymbol}`
5442
+ );
5443
+ }) })
5444
+ ] }, chainName);
5445
+ }) })
5446
+ ]
5447
+ }
5448
+ );
5449
+ }
5450
+ var subtitleStyle11 = (color) => ({
5451
+ fontSize: "0.86rem",
5452
+ color,
5453
+ margin: "0 0 20px",
5454
+ lineHeight: 1.5
5455
+ });
5456
+ var chainListStyle2 = {
5457
+ display: "flex",
5458
+ flexDirection: "column",
5459
+ gap: 10
5460
+ };
5461
+ var chainCardStyle2 = (tokens) => ({
5462
+ border: `1px solid ${tokens.border}`,
5463
+ borderRadius: 14,
5464
+ overflow: "hidden",
5465
+ background: tokens.bgInput
5466
+ });
5467
+ var chainHeaderStyle2 = (tokens) => ({
5468
+ display: "flex",
5469
+ alignItems: "center",
5470
+ justifyContent: "space-between",
5471
+ width: "100%",
5472
+ padding: "14px 16px",
5473
+ background: tokens.bgInput,
5474
+ border: "none",
5475
+ cursor: "pointer",
5476
+ fontFamily: "inherit",
5477
+ textAlign: "left"
5478
+ });
5479
+ var chainHeaderLeftStyle2 = {
5480
+ display: "flex",
5481
+ flexDirection: "column",
5482
+ gap: 2
5483
+ };
5484
+ var chainNameStyle2 = (color) => ({
5485
+ fontSize: "0.92rem",
5486
+ fontWeight: 600,
5487
+ color
5488
+ });
5489
+ var chainBalanceStyle2 = (color) => ({
5490
+ fontSize: "0.76rem",
5491
+ color
5492
+ });
5493
+ var chevronStyle2 = (color) => ({
5494
+ fontSize: "0.9rem",
5495
+ color
5496
+ });
5497
+ var tokenListStyle2 = {
5498
+ padding: "0 12px 12px",
5499
+ display: "flex",
5500
+ flexDirection: "column",
5501
+ gap: 6
5502
+ };
5503
+ var tokenRowStyle2 = (tokens, selected) => ({
5504
+ display: "flex",
5505
+ alignItems: "center",
5506
+ justifyContent: "space-between",
5507
+ padding: "12px 14px",
5508
+ background: tokens.bgCard,
5509
+ border: `1.5px solid ${selected ? tokens.accent : tokens.border}`,
5510
+ borderRadius: 10,
5511
+ cursor: "pointer",
5512
+ fontFamily: "inherit",
5513
+ textAlign: "left",
5514
+ transition: "border-color 0.15s ease"
5515
+ });
5516
+ var tokenInfoStyle2 = {
5517
+ display: "flex",
5518
+ flexDirection: "column",
5519
+ gap: 4,
5520
+ flex: 1
5521
+ };
5522
+ var tokenHeaderRowStyle = {
5523
+ display: "flex",
5524
+ alignItems: "center",
5525
+ gap: 8
5526
+ };
5527
+ var tokenSymbolStyle2 = (color) => ({
5528
+ fontSize: "0.88rem",
5529
+ fontWeight: 600,
5530
+ color
5531
+ });
5532
+ var statusBadgeStyle = (color) => ({
5533
+ fontSize: "0.65rem",
5534
+ fontWeight: 600,
5535
+ color,
5536
+ border: `1px solid ${color}44`,
5537
+ borderRadius: 999,
5538
+ padding: "1px 7px",
5539
+ letterSpacing: "0.02em"
5540
+ });
5541
+ var tokenBalStyle2 = (color) => ({
5542
+ fontSize: "0.74rem",
5543
+ color
5544
+ });
5545
+ var radioStyle3 = (tokens, selected) => ({
5546
+ width: 20,
5547
+ height: 20,
5548
+ borderRadius: "50%",
5549
+ border: `2px solid ${selected ? tokens.accent : tokens.border}`,
5550
+ display: "flex",
5551
+ alignItems: "center",
5552
+ justifyContent: "center",
5553
+ flexShrink: 0
5554
+ });
5555
+ var radioDotStyle3 = (color) => ({
5556
+ width: 10,
5557
+ height: 10,
5558
+ borderRadius: "50%",
5559
+ background: color
5560
+ });
5307
5561
  function StepRenderer({
5308
5562
  state,
5309
5563
  ready,
@@ -5322,6 +5576,7 @@ function StepRenderer({
5322
5576
  maxSourceBalance,
5323
5577
  tokenCount,
5324
5578
  selectedAccount,
5579
+ selectedSource,
5325
5580
  selectSourceChoices,
5326
5581
  selectSourceRecommended,
5327
5582
  authInput,
@@ -5431,7 +5686,7 @@ function StepRenderer({
5431
5686
  return /* @__PURE__ */ jsxRuntime.jsx(
5432
5687
  SetupScreen,
5433
5688
  {
5434
- availableBalance: selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : maxSourceBalance,
5689
+ availableBalance: selectedSource ? selectedSource.balance.available.amount : selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : maxSourceBalance,
5435
5690
  tokenCount,
5436
5691
  sourceName,
5437
5692
  onSetupOneTap: handlers.onSetupOneTap,
@@ -5467,8 +5722,8 @@ function StepRenderer({
5467
5722
  sourceName,
5468
5723
  sourceAddress,
5469
5724
  sourceVerified,
5470
- availableBalance: selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : maxSourceBalance,
5471
- remainingLimit: selectedAccount?.remainingAllowance ?? state.oneTapLimit,
5725
+ availableBalance: selectedSource ? selectedSource.balance.available.amount : selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : maxSourceBalance,
5726
+ remainingLimit: selectedSource?.remainingAllowance ?? selectedAccount?.remainingAllowance ?? state.oneTapLimit,
5472
5727
  tokenCount,
5473
5728
  initialAmount: parsedAmt,
5474
5729
  processing: state.creatingTransfer,
@@ -5483,7 +5738,23 @@ function StepRenderer({
5483
5738
  selectedAccountId: state.selectedAccountId,
5484
5739
  onSelectAccount: handlers.onSelectAccount,
5485
5740
  onAuthorizeAccount: handlers.onContinueConnection,
5486
- onAddProvider: () => handlers.onNavigate("wallet-picker")
5741
+ onAddProvider: () => handlers.onNavigate("wallet-picker"),
5742
+ onSelectToken: handlers.onSelectToken
5743
+ }
5744
+ );
5745
+ }
5746
+ if (step === "token-picker") {
5747
+ if (!selectedAccount) {
5748
+ return /* @__PURE__ */ jsxRuntime.jsx(SwypeLoadingScreen, {});
5749
+ }
5750
+ return /* @__PURE__ */ jsxRuntime.jsx(
5751
+ TokenPickerScreen,
5752
+ {
5753
+ account: selectedAccount,
5754
+ chains: state.chains,
5755
+ onSelectAuthorized: handlers.onSelectAuthorizedToken,
5756
+ onAuthorizeToken: handlers.onAuthorizeToken,
5757
+ onBack: () => handlers.onNavigate("deposit")
5487
5758
  }
5488
5759
  );
5489
5760
  }
@@ -5528,7 +5799,7 @@ function StepRenderer({
5528
5799
  merchantName,
5529
5800
  sourceName,
5530
5801
  remainingLimit: succeeded ? (() => {
5531
- const limit = selectedAccount?.remainingAllowance ?? state.oneTapLimit;
5802
+ const limit = selectedSource?.remainingAllowance ?? selectedAccount?.remainingAllowance ?? state.oneTapLimit;
5532
5803
  return limit > displayAmount ? limit - displayAmount : 0;
5533
5804
  })() : void 0,
5534
5805
  onDone: onDismiss ?? handlers.onNewPayment,
@@ -5546,7 +5817,7 @@ function StepRenderer({
5546
5817
  sourceAddress,
5547
5818
  sourceVerified,
5548
5819
  availableBalance: 0,
5549
- remainingLimit: selectedAccount?.remainingAllowance ?? state.oneTapLimit,
5820
+ remainingLimit: selectedSource?.remainingAllowance ?? selectedAccount?.remainingAllowance ?? state.oneTapLimit,
5550
5821
  tokenCount,
5551
5822
  initialAmount: depositAmount ?? 5,
5552
5823
  processing: false,
@@ -5682,6 +5953,7 @@ function SwypePaymentInner({
5682
5953
  const processingStartedAtRef = react.useRef(null);
5683
5954
  const initializedSelectSourceActionRef = react.useRef(null);
5684
5955
  const preSelectSourceStepRef = react.useRef(null);
5956
+ const pendingTokenAuthRef = react.useRef(null);
5685
5957
  const checkingPasskeyRef = react.useRef(false);
5686
5958
  const onCompleteRef = react.useRef(onComplete);
5687
5959
  onCompleteRef.current = onComplete;
@@ -5704,6 +5976,15 @@ function SwypePaymentInner({
5704
5976
  const selectedWallet = selectedAccount?.wallets.find(
5705
5977
  (w) => w.id === state.selectedWalletId
5706
5978
  );
5979
+ const selectedSource = react.useMemo(() => {
5980
+ if (!selectedWallet) return null;
5981
+ if (state.selectedTokenSymbol) {
5982
+ return selectedWallet.sources.find(
5983
+ (s) => s.token.symbol === state.selectedTokenSymbol
5984
+ ) ?? null;
5985
+ }
5986
+ return selectedWallet.sources.find((s) => s.token.status === "AUTHORIZED") ?? selectedWallet.sources[0] ?? null;
5987
+ }, [selectedWallet, state.selectedTokenSymbol]);
5707
5988
  const sourceName = selectedAccount?.name ?? selectedWallet?.chain.name ?? "Wallet";
5708
5989
  const sourceAddress = selectedWallet ? `${selectedWallet.name.slice(0, 6)}...${selectedWallet.name.slice(-4)}` : void 0;
5709
5990
  const sourceVerified = selectedWallet?.status === "ACTIVE";
@@ -6109,6 +6390,84 @@ function SwypePaymentInner({
6109
6390
  reloadAccounts,
6110
6391
  onError
6111
6392
  ]);
6393
+ const handleNavigateToTokenPicker = react.useCallback(() => {
6394
+ dispatch({ type: "NAVIGATE", step: "token-picker" });
6395
+ }, []);
6396
+ const handleSelectAuthorizedToken = react.useCallback((walletId, tokenSymbol) => {
6397
+ dispatch({ type: "SELECT_TOKEN", walletId, tokenSymbol });
6398
+ }, []);
6399
+ const handleAuthorizeToken = react.useCallback(async (_walletId, tokenAddress, chainId, tokenSymbol) => {
6400
+ if (!state.selectedAccountId) {
6401
+ dispatch({ type: "SET_ERROR", error: "No account selected." });
6402
+ return;
6403
+ }
6404
+ if (!state.activeCredentialId) {
6405
+ dispatch({ type: "SET_ERROR", error: "Create a passkey on this device before continuing." });
6406
+ dispatch({ type: "NAVIGATE", step: "create-passkey" });
6407
+ return;
6408
+ }
6409
+ const acct = state.accounts.find((a) => a.id === state.selectedAccountId);
6410
+ const matchedProvider = acct ? state.providers.find((p) => p.name === acct.name) : void 0;
6411
+ if (matchedProvider) {
6412
+ dispatch({ type: "SELECT_PROVIDER", providerId: matchedProvider.id });
6413
+ }
6414
+ dispatch({ type: "SET_ERROR", error: null });
6415
+ dispatch({ type: "SET_INCREASING_LIMIT", value: true });
6416
+ pendingTokenAuthRef.current = { tokenAddress, chainId, tokenSymbol, walletId: _walletId };
6417
+ try {
6418
+ const token = await getAccessToken();
6419
+ if (!token) throw new Error("Not authenticated");
6420
+ const session = await createAccountAuthorizationSession(
6421
+ apiBaseUrl,
6422
+ token,
6423
+ state.selectedAccountId,
6424
+ state.activeCredentialId,
6425
+ { tokenAddress, chainId }
6426
+ );
6427
+ const isMobile = !shouldUseWalletConnector({
6428
+ useWalletConnector: useWalletConnectorProp,
6429
+ userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
6430
+ });
6431
+ if (isMobile) {
6432
+ handlingMobileReturnRef.current = false;
6433
+ mobileSetupFlowRef.current = true;
6434
+ setupAccountIdRef.current = state.selectedAccountId;
6435
+ persistMobileFlowState({
6436
+ accountId: state.selectedAccountId,
6437
+ sessionId: session.id,
6438
+ deeplinkUri: session.uri,
6439
+ providerId: matchedProvider?.id ?? null,
6440
+ isSetup: true
6441
+ });
6442
+ dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
6443
+ triggerDeeplink(session.uri);
6444
+ } else {
6445
+ dispatch({ type: "NAVIGATE", step: "setup-status" });
6446
+ await authExecutor.executeSessionById(session.id);
6447
+ await reloadAccounts();
6448
+ dispatch({ type: "SELECT_TOKEN", walletId: _walletId, tokenSymbol });
6449
+ }
6450
+ } catch (err) {
6451
+ captureException(err);
6452
+ const msg = err instanceof Error ? err.message : "Failed to authorize token";
6453
+ dispatch({ type: "SET_ERROR", error: msg });
6454
+ onError?.(msg);
6455
+ } finally {
6456
+ pendingTokenAuthRef.current = null;
6457
+ dispatch({ type: "SET_INCREASING_LIMIT", value: false });
6458
+ }
6459
+ }, [
6460
+ state.selectedAccountId,
6461
+ state.activeCredentialId,
6462
+ state.accounts,
6463
+ state.providers,
6464
+ apiBaseUrl,
6465
+ getAccessToken,
6466
+ authExecutor,
6467
+ useWalletConnectorProp,
6468
+ reloadAccounts,
6469
+ onError
6470
+ ]);
6112
6471
  const handleConfirmSign = react.useCallback(async () => {
6113
6472
  const t = state.transfer ?? polling.transfer;
6114
6473
  if (!t) return;
@@ -6698,6 +7057,21 @@ function SwypePaymentInner({
6698
7057
  preSelectSourceStepRef.current = null;
6699
7058
  }
6700
7059
  }, [pendingSelectSourceAction, state.step]);
7060
+ react.useEffect(() => {
7061
+ if (!pendingSelectSourceAction || !pendingTokenAuthRef.current) return;
7062
+ const { tokenAddress, chainId } = pendingTokenAuthRef.current;
7063
+ const chainIdHex = `0x${chainId.toString(16)}`;
7064
+ const options = pendingSelectSourceAction.metadata?.options ?? [];
7065
+ const match = options.find(
7066
+ (opt) => opt.tokenAddress.toLowerCase() === tokenAddress.toLowerCase() && opt.chainId.toLowerCase() === chainIdHex.toLowerCase()
7067
+ );
7068
+ if (match) {
7069
+ authExecutor.resolveSelectSource({
7070
+ chainName: match.chainName,
7071
+ tokenSymbol: match.tokenSymbol
7072
+ });
7073
+ }
7074
+ }, [pendingSelectSourceAction, authExecutor]);
6701
7075
  const handlers = react.useMemo(() => ({
6702
7076
  onSendLoginCode: handleSendLoginCode,
6703
7077
  onVerifyLoginCode: handleVerifyLoginCode,
@@ -6727,7 +7101,10 @@ function SwypePaymentInner({
6727
7101
  onSelectSourceChainChange: handleSelectSourceChainChange,
6728
7102
  onSetSelectSourceTokenSymbol: setSelectSourceTokenSymbol,
6729
7103
  onConfirmSelectSource: handleConfirmSelectSource,
6730
- onSetupOneTap: handleSetupOneTap
7104
+ onSetupOneTap: handleSetupOneTap,
7105
+ onSelectToken: handleNavigateToTokenPicker,
7106
+ onSelectAuthorizedToken: handleSelectAuthorizedToken,
7107
+ onAuthorizeToken: handleAuthorizeToken
6731
7108
  }), [
6732
7109
  handleSendLoginCode,
6733
7110
  handleVerifyLoginCode,
@@ -6746,7 +7123,10 @@ function SwypePaymentInner({
6746
7123
  handleNewPayment,
6747
7124
  handleSelectSourceChainChange,
6748
7125
  handleConfirmSelectSource,
6749
- handleSetupOneTap
7126
+ handleSetupOneTap,
7127
+ handleNavigateToTokenPicker,
7128
+ handleSelectAuthorizedToken,
7129
+ handleAuthorizeToken
6750
7130
  ]);
6751
7131
  return /* @__PURE__ */ jsxRuntime.jsx(
6752
7132
  StepRenderer,
@@ -6768,6 +7148,7 @@ function SwypePaymentInner({
6768
7148
  maxSourceBalance,
6769
7149
  tokenCount,
6770
7150
  selectedAccount,
7151
+ selectedSource,
6771
7152
  selectSourceChoices,
6772
7153
  selectSourceRecommended,
6773
7154
  authInput,
@@ -6802,6 +7183,7 @@ exports.StepList = StepList;
6802
7183
  exports.SwypeLoadingScreen = SwypeLoadingScreen;
6803
7184
  exports.SwypePayment = SwypePayment;
6804
7185
  exports.SwypeProvider = SwypeProvider;
7186
+ exports.TokenPickerScreen = TokenPickerScreen;
6805
7187
  exports.buildPasskeyPopupOptions = buildPasskeyPopupOptions;
6806
7188
  exports.createPasskeyCredential = createPasskeyCredential;
6807
7189
  exports.createPasskeyViaPopup = createPasskeyViaPopup;