@swype-org/react-sdk 0.1.287 → 0.1.300

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
@@ -5,9 +5,9 @@ import { mainnet, arbitrum, base, polygon, bsc } from 'wagmi/chains';
5
5
  import { injected } from 'wagmi/connectors';
6
6
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
7
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
- import { recoverTypedDataAddress, decodeAbiParameters, walletActions, hexToString, createClient, custom } from 'viem';
9
- import { parseErc6492Signature, parseAccount, getAddress } from 'viem/utils';
10
- import { waitForTransactionReceipt as waitForTransactionReceipt$1, getTransaction, call } from 'viem/actions';
8
+ import { getAccount, getWalletClient, waitForTransactionReceipt } from '@wagmi/core';
9
+ import { recoverTypedDataAddress, decodeAbiParameters } from 'viem';
10
+ import { parseErc6492Signature } from 'viem/utils';
11
11
 
12
12
  var __defProp = Object.defineProperty;
13
13
  var __export = (target, all) => {
@@ -485,13 +485,14 @@ __export(api_exports, {
485
485
  fetchAuthorizationSessionByToken: () => fetchAuthorizationSessionByToken,
486
486
  fetchChains: () => fetchChains,
487
487
  fetchGuestAccount: () => fetchGuestAccount,
488
- fetchGuestTransferBalances: () => fetchGuestTransferBalances,
489
488
  fetchMerchantPublicKey: () => fetchMerchantPublicKey,
490
489
  fetchProviders: () => fetchProviders,
491
490
  fetchTransfer: () => fetchTransfer,
492
491
  fetchUserConfig: () => fetchUserConfig,
493
492
  getGuestTransfer: () => getGuestTransfer,
494
493
  getTransferByGuestToken: () => getTransferByGuestToken,
494
+ postGuestTransferFeeQuote: () => postGuestTransferFeeQuote,
495
+ putGuestTransferSender: () => putGuestTransferSender,
495
496
  registerPasskey: () => registerPasskey,
496
497
  reportActionCompletion: () => reportActionCompletion,
497
498
  reportPasskeyActivity: () => reportPasskeyActivity,
@@ -746,18 +747,37 @@ async function getTransferByGuestToken(apiBaseUrl, guestToken) {
746
747
  if (!res.ok) await throwApiError(res);
747
748
  return await res.json();
748
749
  }
749
- async function setTransferSender(apiBaseUrl, transferId, guestSessionToken, senderAddress, sourceChainId, sourceToken) {
750
+ async function postGuestTransferFeeQuote(apiBaseUrl, transferId, guestSessionToken, senderAddress, sourceChainId, sourceToken) {
751
+ const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}/quotes`, {
752
+ method: "POST",
753
+ headers: {
754
+ "Content-Type": "application/json",
755
+ "x-guest-session-token": guestSessionToken
756
+ },
757
+ body: JSON.stringify({ senderAddress, sourceChainId, sourceToken })
758
+ });
759
+ if (!res.ok) await throwApiError(res);
760
+ return await res.json();
761
+ }
762
+ async function putGuestTransferSender(apiBaseUrl, transferId, guestSessionToken, body) {
750
763
  const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}/sender`, {
751
764
  method: "PUT",
752
765
  headers: {
753
766
  "Content-Type": "application/json",
754
767
  "x-guest-session-token": guestSessionToken
755
768
  },
756
- body: JSON.stringify({ senderAddress, sourceChainId, sourceToken })
769
+ body: JSON.stringify(body)
757
770
  });
758
771
  if (!res.ok) await throwApiError(res);
759
772
  return await res.json();
760
773
  }
774
+ async function setTransferSender(apiBaseUrl, transferId, guestSessionToken, senderAddress, sourceChainId, sourceToken) {
775
+ return putGuestTransferSender(apiBaseUrl, transferId, guestSessionToken, {
776
+ senderAddress,
777
+ sourceChainId,
778
+ sourceToken
779
+ });
780
+ }
761
781
  async function signGuestTransfer(apiBaseUrl, transferId, guestSessionToken, originTxHash) {
762
782
  const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}`, {
763
783
  method: "PATCH",
@@ -779,20 +799,6 @@ async function getGuestTransfer(apiBaseUrl, transferId, guestSessionToken) {
779
799
  if (!res.ok) await throwApiError(res);
780
800
  return await res.json();
781
801
  }
782
- async function fetchGuestTransferBalances(apiBaseUrl, transferId, guestSessionToken, walletAddress) {
783
- const params = new URLSearchParams({ walletAddress });
784
- const res = await fetch(
785
- `${apiBaseUrl}/v1/transfers/${transferId}/balances?${params.toString()}`,
786
- {
787
- headers: {
788
- "x-guest-session-token": guestSessionToken
789
- }
790
- }
791
- );
792
- if (!res.ok) await throwApiError(res);
793
- const data = await res.json();
794
- return data.items;
795
- }
796
802
  async function fetchGuestAccount(apiBaseUrl, guestToken) {
797
803
  const params = new URLSearchParams({ guestToken });
798
804
  const res = await fetch(`${apiBaseUrl}/v1/accounts?${params.toString()}`);
@@ -907,304 +913,6 @@ function useTransferPolling(intervalMs = 3e3) {
907
913
  useEffect(() => () => stopPolling(), [stopPolling]);
908
914
  return { transfer, error, isPolling, startPolling, stopPolling };
909
915
  }
910
-
911
- // node_modules/@wagmi/core/dist/esm/utils/getAction.js
912
- function getAction(client, actionFn, name) {
913
- const action_implicit = client[actionFn.name];
914
- if (typeof action_implicit === "function")
915
- return action_implicit;
916
- const action_explicit = client[name];
917
- if (typeof action_explicit === "function")
918
- return action_explicit;
919
- return (params) => actionFn(client, params);
920
- }
921
-
922
- // node_modules/@wagmi/core/dist/esm/version.js
923
- var version = "2.22.1";
924
-
925
- // node_modules/@wagmi/core/dist/esm/utils/getVersion.js
926
- var getVersion = () => `@wagmi/core@${version}`;
927
-
928
- // node_modules/@wagmi/core/dist/esm/errors/base.js
929
- var __classPrivateFieldGet = function(receiver, state, kind, f) {
930
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
931
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
932
- };
933
- var _BaseError_instances;
934
- var _BaseError_walk;
935
- var BaseError = class _BaseError extends Error {
936
- get docsBaseUrl() {
937
- return "https://wagmi.sh/core";
938
- }
939
- get version() {
940
- return getVersion();
941
- }
942
- constructor(shortMessage, options = {}) {
943
- super();
944
- _BaseError_instances.add(this);
945
- Object.defineProperty(this, "details", {
946
- enumerable: true,
947
- configurable: true,
948
- writable: true,
949
- value: void 0
950
- });
951
- Object.defineProperty(this, "docsPath", {
952
- enumerable: true,
953
- configurable: true,
954
- writable: true,
955
- value: void 0
956
- });
957
- Object.defineProperty(this, "metaMessages", {
958
- enumerable: true,
959
- configurable: true,
960
- writable: true,
961
- value: void 0
962
- });
963
- Object.defineProperty(this, "shortMessage", {
964
- enumerable: true,
965
- configurable: true,
966
- writable: true,
967
- value: void 0
968
- });
969
- Object.defineProperty(this, "name", {
970
- enumerable: true,
971
- configurable: true,
972
- writable: true,
973
- value: "WagmiCoreError"
974
- });
975
- const details = options.cause instanceof _BaseError ? options.cause.details : options.cause?.message ? options.cause.message : options.details;
976
- const docsPath = options.cause instanceof _BaseError ? options.cause.docsPath || options.docsPath : options.docsPath;
977
- this.message = [
978
- shortMessage || "An error occurred.",
979
- "",
980
- ...options.metaMessages ? [...options.metaMessages, ""] : [],
981
- ...docsPath ? [
982
- `Docs: ${this.docsBaseUrl}${docsPath}.html${options.docsSlug ? `#${options.docsSlug}` : ""}`
983
- ] : [],
984
- ...details ? [`Details: ${details}`] : [],
985
- `Version: ${this.version}`
986
- ].join("\n");
987
- if (options.cause)
988
- this.cause = options.cause;
989
- this.details = details;
990
- this.docsPath = docsPath;
991
- this.metaMessages = options.metaMessages;
992
- this.shortMessage = shortMessage;
993
- }
994
- walk(fn) {
995
- return __classPrivateFieldGet(this, _BaseError_instances, "m", _BaseError_walk).call(this, this, fn);
996
- }
997
- };
998
- _BaseError_instances = /* @__PURE__ */ new WeakSet(), _BaseError_walk = function _BaseError_walk2(err, fn) {
999
- if (fn?.(err))
1000
- return err;
1001
- if (err.cause)
1002
- return __classPrivateFieldGet(this, _BaseError_instances, "m", _BaseError_walk2).call(this, err.cause, fn);
1003
- return err;
1004
- };
1005
-
1006
- // node_modules/@wagmi/core/dist/esm/errors/config.js
1007
- var ConnectorNotConnectedError = class extends BaseError {
1008
- constructor() {
1009
- super("Connector not connected.");
1010
- Object.defineProperty(this, "name", {
1011
- enumerable: true,
1012
- configurable: true,
1013
- writable: true,
1014
- value: "ConnectorNotConnectedError"
1015
- });
1016
- }
1017
- };
1018
- var ConnectorAccountNotFoundError = class extends BaseError {
1019
- constructor({ address, connector }) {
1020
- super(`Account "${address}" not found for connector "${connector.name}".`);
1021
- Object.defineProperty(this, "name", {
1022
- enumerable: true,
1023
- configurable: true,
1024
- writable: true,
1025
- value: "ConnectorAccountNotFoundError"
1026
- });
1027
- }
1028
- };
1029
- var ConnectorChainMismatchError = class extends BaseError {
1030
- constructor({ connectionChainId, connectorChainId }) {
1031
- super(`The current chain of the connector (id: ${connectorChainId}) does not match the connection's chain (id: ${connectionChainId}).`, {
1032
- metaMessages: [
1033
- `Current Chain ID: ${connectorChainId}`,
1034
- `Expected Chain ID: ${connectionChainId}`
1035
- ]
1036
- });
1037
- Object.defineProperty(this, "name", {
1038
- enumerable: true,
1039
- configurable: true,
1040
- writable: true,
1041
- value: "ConnectorChainMismatchError"
1042
- });
1043
- }
1044
- };
1045
- var ConnectorUnavailableReconnectingError = class extends BaseError {
1046
- constructor({ connector }) {
1047
- super(`Connector "${connector.name}" unavailable while reconnecting.`, {
1048
- details: [
1049
- "During the reconnection step, the only connector methods guaranteed to be available are: `id`, `name`, `type`, `uid`.",
1050
- "All other methods are not guaranteed to be available until reconnection completes and connectors are fully restored.",
1051
- "This error commonly occurs for connectors that asynchronously inject after reconnection has already started."
1052
- ].join(" ")
1053
- });
1054
- Object.defineProperty(this, "name", {
1055
- enumerable: true,
1056
- configurable: true,
1057
- writable: true,
1058
- value: "ConnectorUnavailableReconnectingError"
1059
- });
1060
- }
1061
- };
1062
- async function getConnectorClient(config, parameters = {}) {
1063
- const { assertChainId = true } = parameters;
1064
- let connection;
1065
- if (parameters.connector) {
1066
- const { connector: connector2 } = parameters;
1067
- if (config.state.status === "reconnecting" && !connector2.getAccounts && !connector2.getChainId)
1068
- throw new ConnectorUnavailableReconnectingError({ connector: connector2 });
1069
- const [accounts, chainId2] = await Promise.all([
1070
- connector2.getAccounts().catch((e) => {
1071
- if (parameters.account === null)
1072
- return [];
1073
- throw e;
1074
- }),
1075
- connector2.getChainId()
1076
- ]);
1077
- connection = {
1078
- accounts,
1079
- chainId: chainId2,
1080
- connector: connector2
1081
- };
1082
- } else
1083
- connection = config.state.connections.get(config.state.current);
1084
- if (!connection)
1085
- throw new ConnectorNotConnectedError();
1086
- const chainId = parameters.chainId ?? connection.chainId;
1087
- const connectorChainId = await connection.connector.getChainId();
1088
- if (assertChainId && connectorChainId !== chainId)
1089
- throw new ConnectorChainMismatchError({
1090
- connectionChainId: chainId,
1091
- connectorChainId
1092
- });
1093
- const connector = connection.connector;
1094
- if (connector.getClient)
1095
- return connector.getClient({ chainId });
1096
- const account = parseAccount(parameters.account ?? connection.accounts[0]);
1097
- if (account)
1098
- account.address = getAddress(account.address);
1099
- if (parameters.account && !connection.accounts.some((x) => x.toLowerCase() === account.address.toLowerCase()))
1100
- throw new ConnectorAccountNotFoundError({
1101
- address: account.address,
1102
- connector
1103
- });
1104
- const chain = config.chains.find((chain2) => chain2.id === chainId);
1105
- const provider = await connection.connector.getProvider({ chainId });
1106
- return createClient({
1107
- account,
1108
- chain,
1109
- name: "Connector Client",
1110
- transport: (opts) => custom(provider)({ ...opts, retryCount: 0 })
1111
- });
1112
- }
1113
-
1114
- // node_modules/@wagmi/core/dist/esm/actions/getAccount.js
1115
- function getAccount(config) {
1116
- const uid = config.state.current;
1117
- const connection = config.state.connections.get(uid);
1118
- const addresses = connection?.accounts;
1119
- const address = addresses?.[0];
1120
- const chain = config.chains.find((chain2) => chain2.id === connection?.chainId);
1121
- const status = config.state.status;
1122
- switch (status) {
1123
- case "connected":
1124
- return {
1125
- address,
1126
- addresses,
1127
- chain,
1128
- chainId: connection?.chainId,
1129
- connector: connection?.connector,
1130
- isConnected: true,
1131
- isConnecting: false,
1132
- isDisconnected: false,
1133
- isReconnecting: false,
1134
- status
1135
- };
1136
- case "reconnecting":
1137
- return {
1138
- address,
1139
- addresses,
1140
- chain,
1141
- chainId: connection?.chainId,
1142
- connector: connection?.connector,
1143
- isConnected: !!address,
1144
- isConnecting: false,
1145
- isDisconnected: false,
1146
- isReconnecting: true,
1147
- status
1148
- };
1149
- case "connecting":
1150
- return {
1151
- address,
1152
- addresses,
1153
- chain,
1154
- chainId: connection?.chainId,
1155
- connector: connection?.connector,
1156
- isConnected: false,
1157
- isConnecting: true,
1158
- isDisconnected: false,
1159
- isReconnecting: false,
1160
- status
1161
- };
1162
- case "disconnected":
1163
- return {
1164
- address: void 0,
1165
- addresses: void 0,
1166
- chain: void 0,
1167
- chainId: void 0,
1168
- connector: void 0,
1169
- isConnected: false,
1170
- isConnecting: false,
1171
- isDisconnected: true,
1172
- isReconnecting: false,
1173
- status
1174
- };
1175
- }
1176
- }
1177
- async function getWalletClient(config, parameters = {}) {
1178
- const client = await getConnectorClient(config, parameters);
1179
- return client.extend(walletActions);
1180
- }
1181
- async function waitForTransactionReceipt(config, parameters) {
1182
- const { chainId, timeout = 0, ...rest } = parameters;
1183
- const client = config.getClient({ chainId });
1184
- const action = getAction(client, waitForTransactionReceipt$1, "waitForTransactionReceipt");
1185
- const receipt = await action({ ...rest, timeout });
1186
- if (receipt.status === "reverted") {
1187
- const action_getTransaction = getAction(client, getTransaction, "getTransaction");
1188
- const { from: account, ...txn } = await action_getTransaction({
1189
- hash: receipt.transactionHash
1190
- });
1191
- const action_call = getAction(client, call, "call");
1192
- const code = await action_call({
1193
- ...txn,
1194
- account,
1195
- data: txn.input,
1196
- gasPrice: txn.type !== "eip1559" ? txn.gasPrice : void 0,
1197
- maxFeePerGas: txn.type === "eip1559" ? txn.maxFeePerGas : void 0,
1198
- maxPriorityFeePerGas: txn.type === "eip1559" ? txn.maxPriorityFeePerGas : void 0
1199
- });
1200
- const reason = code?.data ? hexToString(`0x${code.data.substring(138)}`) : "unknown reason";
1201
- throw new Error(reason);
1202
- }
1203
- return {
1204
- ...receipt,
1205
- chainId: client.chain.id
1206
- };
1207
- }
1208
916
  var ERC_6492_MAGIC_SUFFIX = "6492649264926492649264926492649264926492649264926492649264926492";
1209
917
  function normalizeSignature(sig) {
1210
918
  const hex = sig.startsWith("0x") ? sig.slice(2) : sig;
@@ -2077,8 +1785,8 @@ function resolvePhase(state) {
2077
1785
  const needsPasskeyBootstrap = state.privyAuthenticated && !state.activeCredentialId;
2078
1786
  const guestPreauthPinsCurrentPhase = transferCompleted && state.guestPreauthorizing && !state.verificationTarget && isGuestPreauthCompletedTransferPinPhase(currentPhase);
2079
1787
  const guestPostPayLogin = transferCompleted && state.isGuestFlow && state.guestPreauthSessionId != null && !state.guestPreauthorizing && !state.verificationTarget && !state.privyAuthenticated;
2080
- const isFundingSourceSubflow = !state.loginRequested && (currentPhase.step === "token-picker" || currentPhase.step === "one-tap-setup" || currentPhase.step === "select-source" || currentPhase.step === "confirm-sign" || currentPhase.step === "guest-token-picker");
2081
1788
  const guestTokenPickerEligible = state.isGuestFlow && state.selectedProviderId != null && !state.transfer && !state.guestPreauthAccountId;
1789
+ const isFundingSourceSubflow = !state.loginRequested && (currentPhase.step === "token-picker" || currentPhase.step === "one-tap-setup" || currentPhase.step === "select-source" || currentPhase.step === "confirm-sign" || currentPhase.step === "guest-token-picker" && guestTokenPickerEligible);
2082
1790
  const walletPickerSwitchEligible = currentPhase.step === "wallet-picker" && currentPhase.reason === "switch" && !state.creatingTransfer && !(state.mobileFlow && state.deeplinkUri);
2083
1791
  const missingActivePasskeyCredential = state.passkeyConfigLoaded && !state.activeCredentialId;
2084
1792
  const shouldPromptPasskeyVerification = missingActivePasskeyCredential && state.knownCredentialIds.length > 0 && state.passkeyPopupNeeded;
@@ -3510,10 +3218,15 @@ function LoginScreen({
3510
3218
  error,
3511
3219
  onBack,
3512
3220
  merchantInitials,
3513
- onSocialLogin
3221
+ onSocialLogin,
3222
+ heroTitle,
3223
+ heroSubtitle,
3224
+ inputPlaceholder
3514
3225
  }) {
3515
3226
  const { tokens } = useBlinkConfig();
3516
3227
  const disabled = authInput.trim().length === 0 || sending;
3228
+ const heading = heroTitle ?? "Your Money. Any App.\nOne Tap.";
3229
+ const placeholder = inputPlaceholder ?? "Email or phone number";
3517
3230
  return /* @__PURE__ */ jsxs(
3518
3231
  ScreenLayout,
3519
3232
  {
@@ -3548,7 +3261,8 @@ function LoginScreen({
3548
3261
  ),
3549
3262
  /* @__PURE__ */ jsxs("div", { style: contentStyle, children: [
3550
3263
  /* @__PURE__ */ jsx("img", { src: BLINK_LOGO, alt: "Blink", style: logoStyle }),
3551
- /* @__PURE__ */ jsx("h2", { style: headingStyle(tokens.text), children: "Your Money. Any App.\nOne Tap." }),
3264
+ /* @__PURE__ */ jsx("h2", { style: headingStyle(tokens.text), children: heading }),
3265
+ heroSubtitle ? /* @__PURE__ */ jsx("p", { style: subtitleStyle(tokens.textMuted), children: heroSubtitle }) : null,
3552
3266
  error && /* @__PURE__ */ jsx("div", { style: errorStyle(tokens), children: error }),
3553
3267
  /* @__PURE__ */ jsx(
3554
3268
  "input",
@@ -3557,7 +3271,7 @@ function LoginScreen({
3557
3271
  type: "text",
3558
3272
  inputMode: "text",
3559
3273
  autoComplete: "username",
3560
- placeholder: "Email or phone number",
3274
+ placeholder,
3561
3275
  value: authInput,
3562
3276
  onChange: (e) => onAuthInputChange(e.target.value),
3563
3277
  onKeyDown: (e) => {
@@ -3602,6 +3316,14 @@ var headingStyle = (color) => ({
3602
3316
  margin: "20px 0 8px",
3603
3317
  whiteSpace: "pre-line"
3604
3318
  });
3319
+ var subtitleStyle = (color) => ({
3320
+ fontSize: "0.9rem",
3321
+ fontWeight: 500,
3322
+ lineHeight: 1.45,
3323
+ color,
3324
+ margin: "0 0 16px",
3325
+ maxWidth: 320
3326
+ });
3605
3327
  var inputStyle2 = (tokens) => ({
3606
3328
  width: "100%",
3607
3329
  padding: "15px 16px",
@@ -3724,7 +3446,7 @@ function OtpVerifyScreen({
3724
3446
  /* @__PURE__ */ jsx(ScreenHeader, { onBack }),
3725
3447
  /* @__PURE__ */ jsxs("div", { style: contentStyle2, children: [
3726
3448
  /* @__PURE__ */ jsx("h2", { style: headingStyle2(tokens.text), children: "Confirm it is you" }),
3727
- /* @__PURE__ */ jsxs("p", { style: subtitleStyle(tokens.textSecondary), children: [
3449
+ /* @__PURE__ */ jsxs("p", { style: subtitleStyle2(tokens.textSecondary), children: [
3728
3450
  "We sent a 6-digit code to",
3729
3451
  "\n",
3730
3452
  /* @__PURE__ */ jsx("strong", { children: maskedIdentifier })
@@ -3760,7 +3482,7 @@ var headingStyle2 = (color) => ({
3760
3482
  color,
3761
3483
  margin: "20px 0 8px"
3762
3484
  });
3763
- var subtitleStyle = (color) => ({
3485
+ var subtitleStyle2 = (color) => ({
3764
3486
  fontSize: "0.88rem",
3765
3487
  color,
3766
3488
  margin: "0 0 28px",
@@ -3813,7 +3535,7 @@ function PasskeyScreen({
3813
3535
  /* @__PURE__ */ jsx(ScreenHeader, { onBack, onLogout }),
3814
3536
  /* @__PURE__ */ jsxs("div", { style: contentStyle3, children: [
3815
3537
  /* @__PURE__ */ jsx("h2", { style: headingStyle3(tokens.text), children: "Secure your account with a passkey" }),
3816
- /* @__PURE__ */ jsx("p", { style: subtitleStyle2(tokens.textSecondary), children: "This enables secure one-tap deposits on this device" }),
3538
+ /* @__PURE__ */ jsx("p", { style: subtitleStyle3(tokens.textSecondary), children: "This enables secure one-tap deposits on this device" }),
3817
3539
  error && /* @__PURE__ */ jsx("div", { style: errorBannerStyle2(tokens), children: error })
3818
3540
  ] })
3819
3541
  ]
@@ -3835,7 +3557,7 @@ var headingStyle3 = (color) => ({
3835
3557
  color,
3836
3558
  margin: "24px 0 8px"
3837
3559
  });
3838
- var subtitleStyle2 = (color) => ({
3560
+ var subtitleStyle3 = (color) => ({
3839
3561
  fontSize: "0.86rem",
3840
3562
  color,
3841
3563
  margin: "0 0 20px",
@@ -3853,6 +3575,72 @@ var errorBannerStyle2 = (tokens) => ({
3853
3575
  width: "100%",
3854
3576
  textAlign: "left"
3855
3577
  });
3578
+ function VerifyPasskeyScreen({
3579
+ onVerify,
3580
+ onBack,
3581
+ verifying,
3582
+ error
3583
+ }) {
3584
+ const { tokens } = useBlinkConfig();
3585
+ return /* @__PURE__ */ jsxs(
3586
+ ScreenLayout,
3587
+ {
3588
+ footer: /* @__PURE__ */ jsxs(Fragment, { children: [
3589
+ /* @__PURE__ */ jsx(PrimaryButton, { onClick: onVerify, disabled: verifying, loading: verifying, children: "Verify passkey" }),
3590
+ /* @__PURE__ */ jsx(PoweredByFooter, {})
3591
+ ] }),
3592
+ children: [
3593
+ /* @__PURE__ */ jsx(ScreenHeader, { onBack }),
3594
+ /* @__PURE__ */ jsxs("div", { style: contentStyle4, children: [
3595
+ /* @__PURE__ */ jsx(IconCircle, { variant: "accent", size: 64, children: /* @__PURE__ */ jsxs("svg", { width: "36", height: "36", viewBox: "0 0 24 24", fill: "none", children: [
3596
+ /* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "3", stroke: tokens.accent, strokeWidth: "1.5", strokeDasharray: "3 2" }),
3597
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "10", r: "1", fill: tokens.accent }),
3598
+ /* @__PURE__ */ jsx("circle", { cx: "15", cy: "10", r: "1", fill: tokens.accent }),
3599
+ /* @__PURE__ */ 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" })
3600
+ ] }) }),
3601
+ /* @__PURE__ */ jsx("h2", { style: headingStyle4(tokens.text), children: "Verify your passkey" }),
3602
+ /* @__PURE__ */ jsx("p", { style: subtitleStyle4(tokens.textSecondary), children: "Your browser requires a separate window to verify your passkey. Tap the button below to continue." }),
3603
+ error && /* @__PURE__ */ jsx("div", { style: errorBannerStyle3(tokens), children: error }),
3604
+ /* @__PURE__ */ jsx(InfoBanner, { children: "Your passkey is stored securely on your device. Blink never sees your biometric data." })
3605
+ ] })
3606
+ ]
3607
+ }
3608
+ );
3609
+ }
3610
+ var contentStyle4 = {
3611
+ textAlign: "center",
3612
+ flex: 1,
3613
+ display: "flex",
3614
+ flexDirection: "column",
3615
+ alignItems: "center",
3616
+ paddingTop: 32
3617
+ };
3618
+ var headingStyle4 = (color) => ({
3619
+ fontSize: "1.45rem",
3620
+ fontWeight: 700,
3621
+ letterSpacing: "-0.02em",
3622
+ color,
3623
+ margin: "24px 0 8px"
3624
+ });
3625
+ var subtitleStyle4 = (color) => ({
3626
+ fontSize: "0.9rem",
3627
+ color,
3628
+ margin: "0 0 28px",
3629
+ lineHeight: 1.5,
3630
+ maxWidth: 280
3631
+ });
3632
+ var errorBannerStyle3 = (tokens) => ({
3633
+ background: tokens.errorBg,
3634
+ border: `1px solid ${tokens.error}66`,
3635
+ borderRadius: 16,
3636
+ padding: "11px 14px",
3637
+ color: tokens.error,
3638
+ fontSize: "0.84rem",
3639
+ marginBottom: 14,
3640
+ lineHeight: 1.5,
3641
+ width: "100%",
3642
+ textAlign: "left"
3643
+ });
3856
3644
  function Spinner({ size = 40, label }) {
3857
3645
  const { tokens } = useBlinkConfig();
3858
3646
  return /* @__PURE__ */ jsxs(
@@ -3996,8 +3784,8 @@ function WalletPickerScreen({
3996
3784
  children: [
3997
3785
  /* @__PURE__ */ jsx(ScreenHeader, { title: "Set up Blink", onBack, onLogout }),
3998
3786
  hasPending && /* @__PURE__ */ jsxs(Fragment, { children: [
3999
- /* @__PURE__ */ jsx("h2", { style: headingStyle4(tokens.text), children: "Continue where you left off" }),
4000
- /* @__PURE__ */ jsx("p", { style: subtitleStyle3(tokens.textSecondary), children: "You have a wallet that still needs setup" }),
3787
+ /* @__PURE__ */ jsx("h2", { style: headingStyle5(tokens.text), children: "Continue where you left off" }),
3788
+ /* @__PURE__ */ jsx("p", { style: subtitleStyle5(tokens.textSecondary), children: "You have a wallet that still needs setup" }),
4001
3789
  /* @__PURE__ */ jsx("div", { style: pendingListStyle, children: pendingConnections.map((acct) => {
4002
3790
  const wallet = acct.wallets[0];
4003
3791
  const address = wallet ? truncateAddress(wallet.name) : void 0;
@@ -4036,7 +3824,7 @@ function WalletPickerScreen({
4036
3824
  }) }),
4037
3825
  /* @__PURE__ */ jsx("div", { style: dividerStyle2(tokens.border), children: /* @__PURE__ */ jsx("span", { style: dividerTextStyle(tokens.textMuted), children: "Or connect a new wallet" }) })
4038
3826
  ] }),
4039
- !hasPending && /* @__PURE__ */ jsx("h2", { style: headingStyle4(tokens.text), children: "Where is your money?" }),
3827
+ !hasPending && /* @__PURE__ */ jsx("h2", { style: headingStyle5(tokens.text), children: "Where is your money?" }),
4040
3828
  /* @__PURE__ */ jsxs(
4041
3829
  "button",
4042
3830
  {
@@ -4107,14 +3895,14 @@ function WalletPickerScreen({
4107
3895
  }
4108
3896
  );
4109
3897
  }
4110
- var headingStyle4 = (color) => ({
3898
+ var headingStyle5 = (color) => ({
4111
3899
  fontSize: "1.35rem",
4112
3900
  fontWeight: 700,
4113
3901
  letterSpacing: "-0.02em",
4114
3902
  color,
4115
3903
  margin: "8px 0 4px"
4116
3904
  });
4117
- var subtitleStyle3 = (color) => ({
3905
+ var subtitleStyle5 = (color) => ({
4118
3906
  fontSize: "0.88rem",
4119
3907
  color,
4120
3908
  margin: "0 0 24px"
@@ -4293,6 +4081,9 @@ var loginButtonStyle = (accentColor) => ({
4293
4081
  var DEFAULT_MAX = 1e7;
4294
4082
  var ABSOLUTE_MIN = 0.01;
4295
4083
  var PRESETS = [100, 250, 1e3];
4084
+ function tokenOptionKey(opt) {
4085
+ return `${opt.chainName}-${opt.symbol}`;
4086
+ }
4296
4087
  function SetupScreen({
4297
4088
  availableBalance,
4298
4089
  onSetupOneTap,
@@ -4301,16 +4092,43 @@ function SetupScreen({
4301
4092
  onAdvanced,
4302
4093
  loading,
4303
4094
  error,
4304
- selectedTokenSymbol
4095
+ selectedTokenSymbol,
4096
+ tokenOptions,
4097
+ onSelectToken
4305
4098
  }) {
4306
4099
  const { tokens } = useBlinkConfig();
4307
4100
  const effectiveMax = DEFAULT_MAX;
4308
4101
  const effectiveMin = Math.min(ABSOLUTE_MIN, effectiveMax);
4309
4102
  const [limit, setLimit] = useState(() => Math.min(availableBalance, effectiveMax));
4310
4103
  const [activePreset, setActivePreset] = useState(null);
4104
+ const [showAdvanced, setShowAdvanced] = useState(false);
4311
4105
  const [editing, setEditing] = useState(false);
4312
4106
  const [inputValue, setInputValue] = useState("");
4313
4107
  const inputRef = useRef(null);
4108
+ const hasDropdown = tokenOptions != null && tokenOptions.length > 0 && onSelectToken != null;
4109
+ const [tokenDropdownOpen, setTokenDropdownOpen] = useState(false);
4110
+ const pickerRef = useRef(null);
4111
+ useEffect(() => {
4112
+ if (!tokenDropdownOpen) return;
4113
+ const handleMouseDown = (e) => {
4114
+ if (pickerRef.current && !pickerRef.current.contains(e.target)) {
4115
+ setTokenDropdownOpen(false);
4116
+ }
4117
+ };
4118
+ document.addEventListener("mousedown", handleMouseDown);
4119
+ return () => document.removeEventListener("mousedown", handleMouseDown);
4120
+ }, [tokenDropdownOpen]);
4121
+ const handleTokenRowClick = useCallback(() => {
4122
+ if (hasDropdown) {
4123
+ setTokenDropdownOpen((v) => !v);
4124
+ } else {
4125
+ onAdvanced?.();
4126
+ }
4127
+ }, [hasDropdown, onAdvanced]);
4128
+ const handlePickToken = useCallback((opt) => {
4129
+ onSelectToken?.(opt.symbol, opt.chainName, opt.walletId);
4130
+ setTokenDropdownOpen(false);
4131
+ }, [onSelectToken]);
4314
4132
  const startEditing = useCallback(() => {
4315
4133
  setInputValue(limit.toFixed(2));
4316
4134
  setEditing(true);
@@ -4333,6 +4151,7 @@ function SetupScreen({
4333
4151
  setLimit(Math.min(availableBalance, effectiveMax));
4334
4152
  setActivePreset("max");
4335
4153
  };
4154
+ const selectedOption = tokenOptions?.find((o) => o.symbol === selectedTokenSymbol);
4336
4155
  return /* @__PURE__ */ jsxs(
4337
4156
  ScreenLayout,
4338
4157
  {
@@ -4343,17 +4162,90 @@ function SetupScreen({
4343
4162
  onClick: () => onSetupOneTap(limit),
4344
4163
  disabled: loading,
4345
4164
  loading,
4346
- children: "Approve"
4165
+ children: "Continue"
4347
4166
  }
4348
4167
  ),
4349
4168
  /* @__PURE__ */ jsx(PoweredByFooter, {})
4350
4169
  ] }),
4351
4170
  children: [
4352
4171
  /* @__PURE__ */ jsx(ScreenHeader, { onBack, onLogout }),
4353
- /* @__PURE__ */ jsx("h2", { style: headingStyle5(tokens.text), children: "Set Spending Limit" }),
4354
- error && /* @__PURE__ */ jsx("div", { style: errorBannerStyle3(tokens), children: error }),
4355
- /* @__PURE__ */ jsxs("div", { style: amountRowStyle, children: [
4356
- /* @__PURE__ */ jsx("div", { style: { flex: 1 }, children: editing ? /* @__PURE__ */ jsxs("div", { style: limitValueStyle(tokens.text), children: [
4172
+ /* @__PURE__ */ jsx("img", { src: BLINK_LOGO, alt: "Blink", width: 56, height: 56, style: mascotStyle2 }),
4173
+ /* @__PURE__ */ jsx("p", { style: descriptionStyle(tokens.text), children: "Set a limit for one-tap deposits. You'll still confirm each one with your passkey." }),
4174
+ error && /* @__PURE__ */ jsx("div", { style: errorBannerStyle4(tokens), children: error }),
4175
+ /* @__PURE__ */ jsxs("div", { ref: pickerRef, children: [
4176
+ /* @__PURE__ */ jsxs(
4177
+ "button",
4178
+ {
4179
+ type: "button",
4180
+ onClick: handleTokenRowClick,
4181
+ style: tokenRowTriggerStyle(tokens, hasDropdown || !!onAdvanced),
4182
+ "aria-expanded": hasDropdown ? tokenDropdownOpen : void 0,
4183
+ "aria-haspopup": hasDropdown ? "listbox" : void 0,
4184
+ children: [
4185
+ /* @__PURE__ */ jsx("span", { style: tokenRowLabelStyle(tokens.text), children: "Token for one tap" }),
4186
+ /* @__PURE__ */ jsxs("div", { style: tokenRowRightStyle, children: [
4187
+ selectedOption && /* @__PURE__ */ jsxs("span", { style: tokenRowSymbolStyle(tokens.textSecondary), children: [
4188
+ selectedOption.symbol,
4189
+ " \xB7 ",
4190
+ selectedOption.chainName
4191
+ ] }),
4192
+ /* @__PURE__ */ jsx("div", { style: tokenIconWrapStyle, children: selectedTokenSymbol && TOKEN_LOGOS[selectedTokenSymbol] ? /* @__PURE__ */ jsx("img", { src: TOKEN_LOGOS[selectedTokenSymbol], alt: selectedTokenSymbol, width: 36, height: 36, style: { borderRadius: "50%" } }) : /* @__PURE__ */ jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", children: [
4193
+ /* @__PURE__ */ jsx("circle", { cx: "18", cy: "18", r: "18", fill: "#2DB84B" }),
4194
+ /* @__PURE__ */ jsx("text", { x: "18", y: "23", textAnchor: "middle", fontSize: "18", fill: "#fff", fontWeight: "700", children: "$" })
4195
+ ] }) }),
4196
+ /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", style: { opacity: 0.5 }, children: tokenDropdownOpen ? /* @__PURE__ */ jsx("path", { d: "M18 15l-6-6-6 6", stroke: tokens.textMuted, strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }) : /* @__PURE__ */ jsx("path", { d: "M6 9l6 6 6-6", stroke: tokens.textMuted, strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
4197
+ ] })
4198
+ ]
4199
+ }
4200
+ ),
4201
+ tokenDropdownOpen && tokenOptions && tokenOptions.length > 0 && /* @__PURE__ */ jsxs("div", { style: dropdownOuterStyle(tokens), children: [
4202
+ /* @__PURE__ */ jsx("div", { style: dropdownLabelStyle(tokens.textMuted), children: "Choose token" }),
4203
+ /* @__PURE__ */ jsx("div", { style: dropdownInnerStyle(tokens), children: tokenOptions.map((opt, index) => {
4204
+ const selected = opt.symbol === selectedTokenSymbol;
4205
+ const isLast = index === tokenOptions.length - 1;
4206
+ return /* @__PURE__ */ jsxs(
4207
+ "button",
4208
+ {
4209
+ type: "button",
4210
+ onClick: () => handlePickToken(opt),
4211
+ style: dropdownRowStyle(tokens, selected, isLast),
4212
+ children: [
4213
+ /* @__PURE__ */ jsxs("div", { style: dropdownRowLeftStyle, children: [
4214
+ /* @__PURE__ */ jsx("div", { style: dropdownTokenIconStyle(tokens, !!TOKEN_LOGOS[opt.symbol]), children: TOKEN_LOGOS[opt.symbol] ? /* @__PURE__ */ jsx("img", { src: TOKEN_LOGOS[opt.symbol], alt: opt.symbol, style: dropdownTokenLogoStyle }) : /* @__PURE__ */ jsx("span", { style: dropdownTokenFallbackStyle(tokens.textMuted), children: "$" }) }),
4215
+ /* @__PURE__ */ jsxs("div", { style: dropdownTokenInfoStyle, children: [
4216
+ /* @__PURE__ */ jsxs("div", { style: dropdownTokenNameRowStyle, children: [
4217
+ /* @__PURE__ */ jsx("span", { style: dropdownTokenSymbolStyle(tokens.text), children: opt.symbol }),
4218
+ /* @__PURE__ */ jsx("span", { style: dropdownTokenDotStyle(tokens.textMuted), children: "\xB7" }),
4219
+ /* @__PURE__ */ jsx("span", { style: dropdownTokenChainStyle(tokens.textMuted), children: opt.chainName })
4220
+ ] }),
4221
+ opt.balance != null && /* @__PURE__ */ jsxs("span", { style: dropdownTokenBalanceStyle(tokens.textMuted), children: [
4222
+ "$",
4223
+ opt.balance.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
4224
+ ] })
4225
+ ] })
4226
+ ] }),
4227
+ selected ? /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 22 22", fill: "none", children: [
4228
+ /* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "11", fill: tokens.success }),
4229
+ /* @__PURE__ */ jsx("path", { d: "M7 11l3 3 5-5", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })
4230
+ ] }) : /* @__PURE__ */ jsx("div", { style: dropdownRadioEmptyStyle(tokens.border) })
4231
+ ]
4232
+ },
4233
+ tokenOptionKey(opt)
4234
+ );
4235
+ }) })
4236
+ ] })
4237
+ ] }),
4238
+ /* @__PURE__ */ jsx(
4239
+ "button",
4240
+ {
4241
+ type: "button",
4242
+ onClick: () => setShowAdvanced((v) => !v),
4243
+ style: advancedToggleStyle(tokens.accent),
4244
+ children: "Advanced"
4245
+ }
4246
+ ),
4247
+ showAdvanced && /* @__PURE__ */ jsxs(Fragment, { children: [
4248
+ /* @__PURE__ */ jsx("div", { style: amountSectionStyle, children: editing ? /* @__PURE__ */ jsxs("div", { style: limitValueStyle(tokens.text), children: [
4357
4249
  "$",
4358
4250
  /* @__PURE__ */ jsx(
4359
4251
  "input",
@@ -4378,63 +4270,94 @@ function SetupScreen({
4378
4270
  onClick: startEditing,
4379
4271
  children: [
4380
4272
  "$",
4381
- limit.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
4273
+ limit.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 }),
4274
+ /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", style: { marginLeft: 8, opacity: 0.45 }, children: /* @__PURE__ */ jsx("path", { d: "M16.47 3.53a2.74 2.74 0 0 1 3.88 0l.12.12a2.74 2.74 0 0 1 0 3.88L8.84 19.16a2 2 0 0 1-.9.52l-4.56 1.3a.75.75 0 0 1-.93-.93l1.3-4.56a2 2 0 0 1 .52-.9L16.47 3.53Z", stroke: tokens.textMuted, strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) })
4382
4275
  ]
4383
4276
  }
4384
4277
  ) }),
4385
- /* @__PURE__ */ jsxs(
4386
- "button",
4387
- {
4388
- type: "button",
4389
- onClick: onAdvanced,
4390
- style: tokenIconButtonStyle(!!onAdvanced),
4391
- children: [
4392
- /* @__PURE__ */ jsx("div", { style: tokenIconWrapStyle, children: selectedTokenSymbol && TOKEN_LOGOS[selectedTokenSymbol] ? /* @__PURE__ */ jsx("img", { src: TOKEN_LOGOS[selectedTokenSymbol], alt: selectedTokenSymbol, width: 36, height: 36, style: { borderRadius: "50%" } }) : /* @__PURE__ */ jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", children: [
4393
- /* @__PURE__ */ jsx("circle", { cx: "18", cy: "18", r: "18", fill: "#2DB84B" }),
4394
- /* @__PURE__ */ jsx("text", { x: "18", y: "23", textAnchor: "middle", fontSize: "18", fill: "#fff", fontWeight: "700", children: "$" })
4395
- ] }) }),
4396
- /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", style: { opacity: 0.5 }, children: /* @__PURE__ */ jsx("path", { d: "M6 9l6 6 6-6", stroke: tokens.textMuted, strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
4397
- ]
4398
- }
4399
- )
4400
- ] }),
4401
- /* @__PURE__ */ jsxs("div", { style: presetsRowStyle, children: [
4402
- PRESETS.map((value) => /* @__PURE__ */ jsxs(
4403
- "button",
4404
- {
4405
- type: "button",
4406
- onClick: () => selectPreset(value),
4407
- style: presetButtonStyle(tokens, activePreset === value),
4408
- children: [
4409
- "$",
4410
- value.toLocaleString()
4411
- ]
4412
- },
4413
- value
4414
- )),
4415
- /* @__PURE__ */ jsx(
4416
- "button",
4417
- {
4418
- type: "button",
4419
- onClick: selectMax,
4420
- style: presetButtonStyle(tokens, activePreset === "max"),
4421
- children: "Max"
4422
- }
4423
- )
4278
+ /* @__PURE__ */ jsxs("div", { style: presetsRowStyle, children: [
4279
+ PRESETS.map((value) => /* @__PURE__ */ jsxs(
4280
+ "button",
4281
+ {
4282
+ type: "button",
4283
+ onClick: () => selectPreset(value),
4284
+ style: presetButtonStyle(tokens, activePreset === value),
4285
+ children: [
4286
+ "$",
4287
+ value.toLocaleString()
4288
+ ]
4289
+ },
4290
+ value
4291
+ )),
4292
+ /* @__PURE__ */ jsx(
4293
+ "button",
4294
+ {
4295
+ type: "button",
4296
+ onClick: selectMax,
4297
+ style: presetButtonStyle(tokens, activePreset === "max"),
4298
+ children: "Max"
4299
+ }
4300
+ )
4301
+ ] })
4424
4302
  ] })
4425
4303
  ]
4426
4304
  }
4427
4305
  );
4428
4306
  }
4429
- var headingStyle5 = (color) => ({
4430
- fontSize: "1.1rem",
4431
- fontWeight: 700,
4432
- letterSpacing: "-0.02em",
4307
+ var mascotStyle2 = {
4308
+ display: "block",
4309
+ margin: "0 auto 12px"
4310
+ };
4311
+ var descriptionStyle = (color) => ({
4312
+ fontSize: "1.05rem",
4313
+ fontWeight: 600,
4314
+ lineHeight: 1.45,
4433
4315
  color,
4434
- margin: "8px 0 24px",
4316
+ margin: "0 0 24px",
4435
4317
  textAlign: "center"
4436
4318
  });
4437
- var errorBannerStyle3 = (tokens) => ({
4319
+ var tokenRowTriggerStyle = (themeTokens, clickable) => ({
4320
+ display: "flex",
4321
+ alignItems: "center",
4322
+ justifyContent: "space-between",
4323
+ width: "100%",
4324
+ padding: "10px 14px",
4325
+ borderRadius: 999,
4326
+ background: themeTokens.bgCard,
4327
+ border: `1px solid ${themeTokens.border}`,
4328
+ cursor: clickable ? "pointer" : "default",
4329
+ fontFamily: "inherit",
4330
+ marginBottom: 8
4331
+ });
4332
+ var tokenRowLabelStyle = (color) => ({
4333
+ fontSize: "0.95rem",
4334
+ fontWeight: 500,
4335
+ color
4336
+ });
4337
+ var tokenRowRightStyle = {
4338
+ display: "flex",
4339
+ alignItems: "center",
4340
+ gap: 6,
4341
+ flexShrink: 0
4342
+ };
4343
+ var tokenRowSymbolStyle = (color) => ({
4344
+ fontSize: "0.84rem",
4345
+ fontWeight: 500,
4346
+ color
4347
+ });
4348
+ var advancedToggleStyle = (accentColor) => ({
4349
+ display: "block",
4350
+ margin: "4px auto 24px",
4351
+ background: "transparent",
4352
+ border: "none",
4353
+ color: accentColor,
4354
+ fontSize: "0.92rem",
4355
+ fontWeight: 600,
4356
+ fontFamily: "inherit",
4357
+ cursor: "pointer",
4358
+ padding: "4px 8px"
4359
+ });
4360
+ var errorBannerStyle4 = (tokens) => ({
4438
4361
  background: tokens.errorBg,
4439
4362
  border: `1px solid ${tokens.error}66`,
4440
4363
  borderRadius: 16,
@@ -4444,27 +4367,25 @@ var errorBannerStyle3 = (tokens) => ({
4444
4367
  marginBottom: 14,
4445
4368
  lineHeight: 1.5
4446
4369
  });
4447
- var amountRowStyle = {
4448
- display: "flex",
4449
- alignItems: "center",
4450
- justifyContent: "space-between",
4451
- marginBottom: 24,
4452
- gap: 12
4370
+ var amountSectionStyle = {
4371
+ textAlign: "center",
4372
+ marginBottom: 16
4453
4373
  };
4454
4374
  var limitValueStyle = (color) => ({
4455
- fontSize: "2.4rem",
4375
+ fontSize: "2.8rem",
4456
4376
  fontWeight: 700,
4457
4377
  color,
4458
4378
  letterSpacing: "-0.02em",
4459
4379
  display: "flex",
4460
- alignItems: "baseline"
4380
+ alignItems: "center",
4381
+ justifyContent: "center"
4461
4382
  });
4462
4383
  var editableLimitStyle = (color) => ({
4463
4384
  ...limitValueStyle(color),
4464
4385
  cursor: "pointer"
4465
4386
  });
4466
4387
  var limitInputStyle = (color) => ({
4467
- fontSize: "2.4rem",
4388
+ fontSize: "2.8rem",
4468
4389
  fontWeight: 700,
4469
4390
  color,
4470
4391
  background: "transparent",
@@ -4474,25 +4395,117 @@ var limitInputStyle = (color) => ({
4474
4395
  width: "6ch",
4475
4396
  fontFamily: "inherit",
4476
4397
  padding: 0,
4477
- letterSpacing: "-0.02em"
4398
+ letterSpacing: "-0.02em",
4399
+ textAlign: "center"
4478
4400
  });
4479
- var tokenIconButtonStyle = (clickable) => ({
4401
+ var tokenIconWrapStyle = {
4402
+ position: "relative",
4403
+ width: 36,
4404
+ height: 36
4405
+ };
4406
+ var dropdownOuterStyle = (themeTokens) => ({
4407
+ marginTop: 4,
4408
+ marginBottom: 12,
4409
+ background: themeTokens.bgCard,
4410
+ border: `1px solid ${themeTokens.border}`,
4411
+ borderRadius: themeTokens.radiusLg,
4412
+ boxShadow: themeTokens.shadowLg,
4413
+ padding: "12px 14px 14px"
4414
+ });
4415
+ var dropdownLabelStyle = (color) => ({
4416
+ fontSize: "0.78rem",
4417
+ fontWeight: 500,
4418
+ color,
4419
+ marginBottom: 8
4420
+ });
4421
+ var dropdownInnerStyle = (themeTokens) => ({
4422
+ background: themeTokens.bgInput,
4423
+ border: `1px solid ${themeTokens.border}`,
4424
+ borderRadius: themeTokens.radiusLg,
4425
+ overflow: "hidden"
4426
+ });
4427
+ var dropdownRowStyle = (themeTokens, isSelected, isLast) => ({
4480
4428
  display: "flex",
4481
4429
  alignItems: "center",
4482
- gap: 4,
4483
- background: "transparent",
4430
+ justifyContent: "space-between",
4431
+ width: "100%",
4432
+ padding: "14px 16px",
4433
+ background: isSelected ? `${themeTokens.accent}18` : "transparent",
4484
4434
  border: "none",
4485
- cursor: clickable ? "pointer" : "default",
4486
- padding: 0,
4487
- flexShrink: 0
4435
+ borderBottom: isLast ? "none" : `1px solid ${themeTokens.border}`,
4436
+ cursor: "pointer",
4437
+ fontFamily: "inherit",
4438
+ textAlign: "left",
4439
+ outline: "none"
4488
4440
  });
4489
- var tokenIconWrapStyle = {
4490
- position: "relative",
4441
+ var dropdownRowLeftStyle = {
4442
+ display: "flex",
4443
+ alignItems: "center",
4444
+ gap: 12,
4445
+ minWidth: 0,
4446
+ flex: 1
4447
+ };
4448
+ var dropdownTokenIconStyle = (themeTokens, hasLogo) => ({
4491
4449
  width: 36,
4492
- height: 36
4450
+ height: 36,
4451
+ borderRadius: "50%",
4452
+ border: hasLogo ? "none" : `1.5px solid ${themeTokens.border}`,
4453
+ display: "flex",
4454
+ alignItems: "center",
4455
+ justifyContent: "center",
4456
+ flexShrink: 0,
4457
+ overflow: "hidden"
4458
+ });
4459
+ var dropdownTokenLogoStyle = {
4460
+ width: 36,
4461
+ height: 36,
4462
+ borderRadius: "50%",
4463
+ objectFit: "cover"
4493
4464
  };
4465
+ var dropdownTokenFallbackStyle = (color) => ({
4466
+ fontSize: "1rem",
4467
+ fontWeight: 700,
4468
+ color
4469
+ });
4470
+ var dropdownTokenInfoStyle = {
4471
+ display: "flex",
4472
+ flexDirection: "column",
4473
+ gap: 2,
4474
+ minWidth: 0
4475
+ };
4476
+ var dropdownTokenNameRowStyle = {
4477
+ display: "flex",
4478
+ alignItems: "center",
4479
+ gap: 4
4480
+ };
4481
+ var dropdownTokenSymbolStyle = (color) => ({
4482
+ fontSize: "0.92rem",
4483
+ fontWeight: 600,
4484
+ color
4485
+ });
4486
+ var dropdownTokenDotStyle = (color) => ({
4487
+ fontSize: "0.8rem",
4488
+ color
4489
+ });
4490
+ var dropdownTokenChainStyle = (color) => ({
4491
+ fontSize: "0.84rem",
4492
+ fontWeight: 400,
4493
+ color
4494
+ });
4495
+ var dropdownTokenBalanceStyle = (color) => ({
4496
+ fontSize: "0.78rem",
4497
+ color
4498
+ });
4499
+ var dropdownRadioEmptyStyle = (borderColor) => ({
4500
+ width: 22,
4501
+ height: 22,
4502
+ borderRadius: "50%",
4503
+ border: `2px solid ${borderColor}`,
4504
+ flexShrink: 0
4505
+ });
4494
4506
  var presetsRowStyle = {
4495
4507
  display: "flex",
4508
+ justifyContent: "center",
4496
4509
  gap: 10,
4497
4510
  marginBottom: 24
4498
4511
  };
@@ -4525,10 +4538,10 @@ function SetupStatusScreen({
4525
4538
  if (complete) {
4526
4539
  return /* @__PURE__ */ jsxs(ScreenLayout, { footer: /* @__PURE__ */ jsx(PoweredByFooter, {}), children: [
4527
4540
  /* @__PURE__ */ jsx(ScreenHeader, { onBack: onContinue }),
4528
- /* @__PURE__ */ jsxs("div", { style: contentStyle4, children: [
4529
- /* @__PURE__ */ jsx("img", { src: BLINK_LOGO, alt: "Blink", style: mascotStyle2 }),
4541
+ /* @__PURE__ */ jsxs("div", { style: contentStyle5, children: [
4542
+ /* @__PURE__ */ jsx("img", { src: BLINK_LOGO, alt: "Blink", style: mascotStyle3 }),
4530
4543
  /* @__PURE__ */ jsx("h2", { style: headingStyle6(tokens.text), children: "Done!" }),
4531
- /* @__PURE__ */ jsx("p", { style: subtitleStyle4(tokens.textSecondary), children: "Return to the app to try one-tap deposits." })
4544
+ /* @__PURE__ */ jsx("p", { style: subtitleStyle6(tokens.textSecondary), children: "Return to the app to try one-tap deposits." })
4532
4545
  ] })
4533
4546
  ] });
4534
4547
  }
@@ -4538,16 +4551,16 @@ function SetupStatusScreen({
4538
4551
  ];
4539
4552
  return /* @__PURE__ */ jsxs(ScreenLayout, { children: [
4540
4553
  /* @__PURE__ */ jsx(ScreenHeader, { onLogout }),
4541
- /* @__PURE__ */ jsxs("div", { style: contentStyle4, children: [
4554
+ /* @__PURE__ */ jsxs("div", { style: contentStyle5, children: [
4542
4555
  /* @__PURE__ */ jsx(Spinner, { size: 48 }),
4543
4556
  /* @__PURE__ */ jsx("h2", { style: headingStyle6(tokens.text), children: "Setting up One-Tap..." }),
4544
- error && /* @__PURE__ */ jsx("div", { style: errorBannerStyle4(tokens), children: error }),
4557
+ error && /* @__PURE__ */ jsx("div", { style: errorBannerStyle5(tokens), children: error }),
4545
4558
  /* @__PURE__ */ jsx("div", { style: stepsWrapStyle, children: /* @__PURE__ */ jsx(StepList, { steps }) }),
4546
4559
  /* @__PURE__ */ jsx("p", { style: waitHintStyle(tokens.textMuted), children: "Usually takes a few seconds" })
4547
4560
  ] })
4548
4561
  ] });
4549
4562
  }
4550
- var contentStyle4 = {
4563
+ var contentStyle5 = {
4551
4564
  flex: 1,
4552
4565
  display: "flex",
4553
4566
  flexDirection: "column",
@@ -4556,7 +4569,7 @@ var contentStyle4 = {
4556
4569
  textAlign: "center",
4557
4570
  padding: "0 24px 32px"
4558
4571
  };
4559
- var mascotStyle2 = {
4572
+ var mascotStyle3 = {
4560
4573
  width: 56,
4561
4574
  height: 56
4562
4575
  };
@@ -4567,14 +4580,14 @@ var headingStyle6 = (color) => ({
4567
4580
  color,
4568
4581
  margin: "20px 0 8px"
4569
4582
  });
4570
- var subtitleStyle4 = (color) => ({
4583
+ var subtitleStyle6 = (color) => ({
4571
4584
  fontSize: "0.9rem",
4572
4585
  color,
4573
4586
  margin: "0 0 28px",
4574
4587
  lineHeight: 1.5,
4575
4588
  maxWidth: 260
4576
4589
  });
4577
- var errorBannerStyle4 = (tokens) => ({
4590
+ var errorBannerStyle5 = (tokens) => ({
4578
4591
  background: tokens.errorBg,
4579
4592
  border: `1px solid ${tokens.error}66`,
4580
4593
  borderRadius: 16,
@@ -4654,7 +4667,7 @@ function DepositScreen({
4654
4667
  /* @__PURE__ */ jsxs("div", { ref: pickerRef, style: depositCardWrapStyle, children: [
4655
4668
  /* @__PURE__ */ jsxs("div", { children: [
4656
4669
  /* @__PURE__ */ jsx("div", { style: depositLabelStyle(tokens.textMuted), children: "Depositing" }),
4657
- /* @__PURE__ */ jsxs("div", { style: amountRowStyle2, children: [
4670
+ /* @__PURE__ */ jsxs("div", { style: amountRowStyle, children: [
4658
4671
  /* @__PURE__ */ jsxs("div", { style: amountValueStyle(tokens.text), children: [
4659
4672
  "$",
4660
4673
  amount.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
@@ -4664,7 +4677,7 @@ function DepositScreen({
4664
4677
  {
4665
4678
  type: "button",
4666
4679
  onClick: onSelectToken,
4667
- style: tokenIconButtonStyle2(!!onSelectToken),
4680
+ style: tokenIconButtonStyle(!!onSelectToken),
4668
4681
  children: [
4669
4682
  /* @__PURE__ */ jsx("div", { style: tokenIconWrapStyle2, children: selectedTokenSymbol && TOKEN_LOGOS[selectedTokenSymbol] ? /* @__PURE__ */ jsx("img", { src: TOKEN_LOGOS[selectedTokenSymbol], alt: selectedTokenSymbol, width: 36, height: 36, style: { borderRadius: "50%" } }) : /* @__PURE__ */ jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", children: [
4670
4683
  /* @__PURE__ */ jsx("circle", { cx: "18", cy: "18", r: "18", fill: "#2DB84B" }),
@@ -4779,7 +4792,7 @@ function DepositScreen({
4779
4792
  minDepositFloor.toFixed(2),
4780
4793
  " to deposit via One-Tap."
4781
4794
  ] }),
4782
- error && /* @__PURE__ */ jsx("div", { style: errorBannerStyle5(tokens), children: error })
4795
+ error && /* @__PURE__ */ jsx("div", { style: errorBannerStyle6(tokens), children: error })
4783
4796
  ]
4784
4797
  }
4785
4798
  );
@@ -4794,7 +4807,7 @@ var depositLabelStyle = (color) => ({
4794
4807
  color,
4795
4808
  marginBottom: 4
4796
4809
  });
4797
- var amountRowStyle2 = {
4810
+ var amountRowStyle = {
4798
4811
  display: "flex",
4799
4812
  alignItems: "center",
4800
4813
  justifyContent: "space-between",
@@ -4806,7 +4819,7 @@ var amountValueStyle = (color) => ({
4806
4819
  letterSpacing: "-0.02em",
4807
4820
  color
4808
4821
  });
4809
- var tokenIconButtonStyle2 = (clickable) => ({
4822
+ var tokenIconButtonStyle = (clickable) => ({
4810
4823
  display: "flex",
4811
4824
  alignItems: "center",
4812
4825
  gap: 4,
@@ -4965,7 +4978,7 @@ var spendingLimitStyle = (color) => ({
4965
4978
  color,
4966
4979
  marginBottom: 8
4967
4980
  });
4968
- var errorBannerStyle5 = (tokens) => ({
4981
+ var errorBannerStyle6 = (tokens) => ({
4969
4982
  background: tokens.errorBg,
4970
4983
  border: `1px solid ${tokens.error}66`,
4971
4984
  borderRadius: 16,
@@ -5010,7 +5023,7 @@ function SuccessScreen({
5010
5023
  ] }),
5011
5024
  children: [
5012
5025
  /* @__PURE__ */ jsx(ScreenHeader, { onLogout }),
5013
- /* @__PURE__ */ jsxs("div", { style: contentStyle5, children: [
5026
+ /* @__PURE__ */ jsxs("div", { style: contentStyle6, children: [
5014
5027
  succeeded ? /* @__PURE__ */ jsxs(Fragment, { children: [
5015
5028
  /* @__PURE__ */ jsx(IconCircle, { variant: "success", size: 64, children: /* @__PURE__ */ jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z", fill: tokens.success }) }) }),
5016
5029
  /* @__PURE__ */ jsxs("h2", { style: headingStyle7(tokens.text), children: [
@@ -5018,14 +5031,14 @@ function SuccessScreen({
5018
5031
  amount.toFixed(2),
5019
5032
  " deposited"
5020
5033
  ] }),
5021
- merchantName && /* @__PURE__ */ jsxs("p", { style: subtitleStyle5(tokens.textSecondary), children: [
5034
+ merchantName && /* @__PURE__ */ jsxs("p", { style: subtitleStyle7(tokens.textSecondary), children: [
5022
5035
  "to ",
5023
5036
  merchantName
5024
5037
  ] })
5025
5038
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
5026
5039
  /* @__PURE__ */ jsx(IconCircle, { variant: "error", size: 64, children: /* @__PURE__ */ jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ 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 }) }) }),
5027
5040
  /* @__PURE__ */ jsx("h2", { style: headingStyle7(tokens.text), children: "Transfer failed" }),
5028
- error && /* @__PURE__ */ jsx("p", { style: subtitleStyle5(tokens.error), children: error })
5041
+ error && /* @__PURE__ */ jsx("p", { style: subtitleStyle7(tokens.error), children: error })
5029
5042
  ] }),
5030
5043
  /* @__PURE__ */ jsxs("div", { style: summaryCardStyle(tokens), children: [
5031
5044
  sourceName && /* @__PURE__ */ jsxs("div", { style: summaryRowStyle, children: [
@@ -5057,7 +5070,7 @@ function SuccessScreen({
5057
5070
  }
5058
5071
  );
5059
5072
  }
5060
- var contentStyle5 = {
5073
+ var contentStyle6 = {
5061
5074
  flex: 1,
5062
5075
  display: "flex",
5063
5076
  flexDirection: "column",
@@ -5071,7 +5084,7 @@ var headingStyle7 = (color) => ({
5071
5084
  color,
5072
5085
  margin: "20px 0 4px"
5073
5086
  });
5074
- var subtitleStyle5 = (color) => ({
5087
+ var subtitleStyle7 = (color) => ({
5075
5088
  fontSize: "0.9rem",
5076
5089
  color,
5077
5090
  margin: "0 0 20px"
@@ -5185,7 +5198,7 @@ function SelectSourceScreen({
5185
5198
  onLogout
5186
5199
  }
5187
5200
  ),
5188
- /* @__PURE__ */ jsx("p", { style: subtitleStyle6(tokens.textMuted), children: "Choose which chain and token to pay from." }),
5201
+ /* @__PURE__ */ jsx("p", { style: subtitleStyle8(tokens.textMuted), children: "Choose which chain and token to pay from." }),
5189
5202
  /* @__PURE__ */ jsx("label", { style: labelStyle4(tokens.textSecondary), children: "Chain" }),
5190
5203
  /* @__PURE__ */ jsx("div", { style: optionListStyle, children: choices.map((chain) => {
5191
5204
  const isSelected = chain.chainName === selectedChainName;
@@ -5246,7 +5259,7 @@ function SelectSourceScreen({
5246
5259
  }
5247
5260
  );
5248
5261
  }
5249
- var subtitleStyle6 = (color) => ({
5262
+ var subtitleStyle8 = (color) => ({
5250
5263
  fontSize: "0.85rem",
5251
5264
  color,
5252
5265
  margin: "0 0 20px",
@@ -5389,7 +5402,7 @@ function AdvancedSourceScreen({
5389
5402
  }
5390
5403
  ),
5391
5404
  /* @__PURE__ */ jsx("h2", { style: headingStyle8(tokens.text), children: "Set up One-Tap deposits" }),
5392
- /* @__PURE__ */ jsx("p", { style: subtitleStyle7(tokens.textSecondary), children: "Select a token source for your One-Tap deposits." }),
5405
+ /* @__PURE__ */ jsx("p", { style: subtitleStyle9(tokens.textSecondary), children: "Select a token source for your One-Tap deposits." }),
5393
5406
  /* @__PURE__ */ jsx("label", { style: labelStyle5(tokens.textSecondary), children: "Select tokens to approve" }),
5394
5407
  /* @__PURE__ */ jsx("div", { style: chainListStyle, children: choices.map((chain) => {
5395
5408
  const isExpanded = expandedChain === chain.chainName;
@@ -5459,7 +5472,7 @@ var headingStyle8 = (color) => ({
5459
5472
  color,
5460
5473
  margin: "8px 0 4px"
5461
5474
  });
5462
- var subtitleStyle7 = (color) => ({
5475
+ var subtitleStyle9 = (color) => ({
5463
5476
  fontSize: "0.86rem",
5464
5477
  color,
5465
5478
  margin: "0 0 20px",
@@ -5587,15 +5600,15 @@ function TransferStatusScreen({
5587
5600
  const steps = buildSteps(phase);
5588
5601
  return /* @__PURE__ */ jsxs(ScreenLayout, { footer: /* @__PURE__ */ jsx(PoweredByFooter, {}), children: [
5589
5602
  /* @__PURE__ */ jsx(ScreenHeader, { onLogout }),
5590
- /* @__PURE__ */ jsxs("div", { style: contentStyle6, children: [
5603
+ /* @__PURE__ */ jsxs("div", { style: contentStyle7, children: [
5591
5604
  /* @__PURE__ */ jsx(Spinner, { size: 64 }),
5592
5605
  /* @__PURE__ */ jsx("h2", { style: headingStyle9(tokens.text), children: "Depositing your money..." }),
5593
- error && /* @__PURE__ */ jsx("div", { style: errorBannerStyle6(tokens), children: error }),
5606
+ error && /* @__PURE__ */ jsx("div", { style: errorBannerStyle7(tokens), children: error }),
5594
5607
  /* @__PURE__ */ jsx("div", { style: stepsWrapStyle2, children: /* @__PURE__ */ jsx(StepList, { steps }) })
5595
5608
  ] })
5596
5609
  ] });
5597
5610
  }
5598
- var contentStyle6 = {
5611
+ var contentStyle7 = {
5599
5612
  flex: 1,
5600
5613
  display: "flex",
5601
5614
  flexDirection: "column",
@@ -5611,7 +5624,7 @@ var headingStyle9 = (color) => ({
5611
5624
  color,
5612
5625
  margin: "20px 0 16px"
5613
5626
  });
5614
- var errorBannerStyle6 = (tokens) => ({
5627
+ var errorBannerStyle7 = (tokens) => ({
5615
5628
  background: tokens.errorBg,
5616
5629
  border: `1px solid ${tokens.error}66`,
5617
5630
  borderRadius: 16,
@@ -5665,14 +5678,14 @@ function OpenWalletScreen({
5665
5678
  ] }),
5666
5679
  children: [
5667
5680
  /* @__PURE__ */ jsx(ScreenHeader, { onLogout }),
5668
- /* @__PURE__ */ jsxs("div", { style: contentStyle7, children: [
5681
+ /* @__PURE__ */ jsxs("div", { style: contentStyle8, children: [
5669
5682
  /* @__PURE__ */ jsx("div", { style: logoCircleStyle(tokens.bgInput), children: logoSrc ? /* @__PURE__ */ jsx("img", { src: logoSrc, alt: displayName, style: logoStyle2 }) : /* @__PURE__ */ jsx(Spinner, { size: 32 }) }),
5670
5683
  /* @__PURE__ */ jsxs("h2", { style: headingStyle10(tokens.text), children: [
5671
5684
  "Setting up ",
5672
5685
  displayName,
5673
5686
  "..."
5674
5687
  ] }),
5675
- /* @__PURE__ */ jsx("p", { style: subtitleStyle8(tokens.textSecondary), children: "Approve the connection in your wallet extension." }),
5688
+ /* @__PURE__ */ jsx("p", { style: subtitleStyle10(tokens.textSecondary), children: "Approve the connection in your wallet extension." }),
5676
5689
  /* @__PURE__ */ jsxs("div", { style: waitingBadgeStyle(tokens), children: [
5677
5690
  /* @__PURE__ */ jsx(Spinner, { size: 14 }),
5678
5691
  /* @__PURE__ */ jsx("span", { children: "Waiting for authorization..." })
@@ -5698,10 +5711,10 @@ function OpenWalletScreen({
5698
5711
  ] }),
5699
5712
  children: [
5700
5713
  /* @__PURE__ */ jsx(ScreenHeader, { onBack, onLogout }),
5701
- /* @__PURE__ */ jsxs("div", { style: contentStyle7, children: [
5714
+ /* @__PURE__ */ jsxs("div", { style: contentStyle8, children: [
5702
5715
  /* @__PURE__ */ jsx("div", { style: logoCircleStyle(tokens.bgInput), children: logoSrc ? /* @__PURE__ */ jsx("img", { src: logoSrc, alt: displayName, style: logoStyle2 }) : /* @__PURE__ */ jsx(Spinner, { size: 32 }) }),
5703
5716
  /* @__PURE__ */ jsx("h2", { style: headingStyle10(tokens.text), children: loading ? "Connecting..." : `Open ${displayName}` }),
5704
- /* @__PURE__ */ jsx("p", { style: subtitleStyle8(tokens.textSecondary), children: loading ? "Creating transfer and preparing your wallet link..." : `Continue in ${displayName} to authorize this connection.` }),
5717
+ /* @__PURE__ */ jsx("p", { style: subtitleStyle10(tokens.textSecondary), children: loading ? "Creating transfer and preparing your wallet link..." : `Continue in ${displayName} to authorize this connection.` }),
5705
5718
  !loading && /* @__PURE__ */ jsxs("div", { style: waitingBadgeStyle(tokens), children: [
5706
5719
  /* @__PURE__ */ jsx(Spinner, { size: 14 }),
5707
5720
  /* @__PURE__ */ jsx("span", { children: "Waiting for authorization..." })
@@ -5711,7 +5724,7 @@ function OpenWalletScreen({
5711
5724
  }
5712
5725
  );
5713
5726
  }
5714
- var contentStyle7 = {
5727
+ var contentStyle8 = {
5715
5728
  flex: 1,
5716
5729
  display: "flex",
5717
5730
  flexDirection: "column",
@@ -5748,7 +5761,7 @@ var headingStyle10 = (color) => ({
5748
5761
  color,
5749
5762
  margin: "20px 0 8px"
5750
5763
  });
5751
- var subtitleStyle8 = (color) => ({
5764
+ var subtitleStyle10 = (color) => ({
5752
5765
  fontSize: "0.9rem",
5753
5766
  color,
5754
5767
  margin: "0 0 24px",
@@ -5797,10 +5810,10 @@ function ConfirmSignScreen({
5797
5810
  ] }),
5798
5811
  children: [
5799
5812
  /* @__PURE__ */ jsx(ScreenHeader, { onLogout }),
5800
- /* @__PURE__ */ jsxs("div", { style: contentStyle8, children: [
5813
+ /* @__PURE__ */ jsxs("div", { style: contentStyle9, children: [
5801
5814
  logoSrc ? /* @__PURE__ */ jsx("img", { src: logoSrc, alt: displayName, style: logoStyle3 }) : /* @__PURE__ */ jsx(Spinner, { size: 48 }),
5802
5815
  /* @__PURE__ */ jsx("h2", { style: headingStyle11(tokens.text), children: "Wallet authorized" }),
5803
- /* @__PURE__ */ jsxs("p", { style: subtitleStyle9(tokens.textSecondary), children: [
5816
+ /* @__PURE__ */ jsxs("p", { style: subtitleStyle11(tokens.textSecondary), children: [
5804
5817
  displayName,
5805
5818
  " approved the connection. Tap below to confirm your payment."
5806
5819
  ] }),
@@ -5813,7 +5826,7 @@ function ConfirmSignScreen({
5813
5826
  }
5814
5827
  );
5815
5828
  }
5816
- var contentStyle8 = {
5829
+ var contentStyle9 = {
5817
5830
  flex: 1,
5818
5831
  display: "flex",
5819
5832
  flexDirection: "column",
@@ -5835,7 +5848,7 @@ var headingStyle11 = (color) => ({
5835
5848
  color,
5836
5849
  margin: "20px 0 8px"
5837
5850
  });
5838
- var subtitleStyle9 = (color) => ({
5851
+ var subtitleStyle11 = (color) => ({
5839
5852
  fontSize: "0.9rem",
5840
5853
  color,
5841
5854
  margin: "0 0 24px",
@@ -5919,7 +5932,7 @@ function TokenPickerScreen({
5919
5932
  {
5920
5933
  type: "button",
5921
5934
  onClick: onBack,
5922
- style: tokenIconButtonStyle3,
5935
+ style: tokenIconButtonStyle2,
5923
5936
  children: [
5924
5937
  /* @__PURE__ */ jsx("div", { style: tokenIconWrapStyle3, children: selectedTokenSymbol && TOKEN_LOGOS[selectedTokenSymbol] ? /* @__PURE__ */ jsx("img", { src: TOKEN_LOGOS[selectedTokenSymbol], alt: selectedTokenSymbol, width: 36, height: 36, style: { borderRadius: "50%" } }) : /* @__PURE__ */ jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", children: [
5925
5938
  /* @__PURE__ */ jsx("circle", { cx: "18", cy: "18", r: "18", fill: "#2DB84B" }),
@@ -5982,7 +5995,7 @@ var depositAmountStyle = (color) => ({
5982
5995
  letterSpacing: "-0.02em",
5983
5996
  color
5984
5997
  });
5985
- var tokenIconButtonStyle3 = {
5998
+ var tokenIconButtonStyle2 = {
5986
5999
  display: "flex",
5987
6000
  alignItems: "center",
5988
6001
  gap: 4,
@@ -6105,60 +6118,243 @@ var selectCircleSelectedStyle = (color) => ({
6105
6118
  justifyContent: "center",
6106
6119
  flexShrink: 0
6107
6120
  });
6121
+ function entryKey(entry) {
6122
+ return `${entry.sourceChainId}-${entry.tokenAddress.toLowerCase()}`;
6123
+ }
6124
+ function isPreciseMoneyNonPositive(fee) {
6125
+ const raw = fee.value.trim();
6126
+ if (!/^-?\d+(\.\d*)?$/.test(raw)) return false;
6127
+ const n = Number(raw);
6128
+ return Number.isFinite(n) && n <= 0;
6129
+ }
6130
+ function formatNonPositiveFeeDisplay(fee) {
6131
+ if (fee.currency === "USD") return "Under $0.01";
6132
+ return `Less than 0.01 ${fee.currency}`;
6133
+ }
6134
+ function formatPreciseMoneyForDisplay(fee) {
6135
+ const raw = fee.value.trim();
6136
+ if (fee.currency === "USD") {
6137
+ if (!/^\d+(\.\d*)?$/.test(raw)) {
6138
+ return `$${raw}`;
6139
+ }
6140
+ const [whole, frac = ""] = raw.split(".");
6141
+ const dec = `${frac}00`.slice(0, 2);
6142
+ const intFmt = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
6143
+ return `$${intFmt}.${dec}`;
6144
+ }
6145
+ return `${raw} ${fee.currency}`;
6146
+ }
6108
6147
  function GuestTokenPickerScreen({
6109
6148
  entries,
6110
6149
  loading,
6111
6150
  setting,
6112
6151
  depositAmount,
6113
6152
  error,
6153
+ pendingEntry,
6154
+ quoteFee,
6155
+ quoteLoading,
6114
6156
  onSelect,
6115
- onBack
6157
+ onConfirm,
6158
+ onBack,
6159
+ defaultTokenListExpanded = false
6116
6160
  }) {
6117
6161
  const { tokens: t } = useBlinkConfig();
6162
+ const pendingKey = pendingEntry ? entryKey(pendingEntry) : null;
6163
+ const [tokenListOpen, setTokenListOpen] = useState(defaultTokenListExpanded);
6164
+ const pickerRef = useRef(null);
6165
+ useEffect(() => {
6166
+ if (!tokenListOpen) return;
6167
+ const handleMouseDown = (e) => {
6168
+ if (pickerRef.current && !pickerRef.current.contains(e.target)) {
6169
+ setTokenListOpen(false);
6170
+ }
6171
+ };
6172
+ document.addEventListener("mousedown", handleMouseDown);
6173
+ return () => document.removeEventListener("mousedown", handleMouseDown);
6174
+ }, [tokenListOpen]);
6118
6175
  if (loading) {
6119
6176
  return /* @__PURE__ */ jsxs(ScreenLayout, { children: [
6120
- /* @__PURE__ */ jsx(ScreenHeader, { title: "Select Token", onBack }),
6177
+ /* @__PURE__ */ jsx(ScreenHeader, { onBack }),
6121
6178
  /* @__PURE__ */ jsx("div", { style: loadingWrapStyle, children: /* @__PURE__ */ jsx(Spinner, { label: "Loading balances..." }) })
6122
6179
  ] });
6123
6180
  }
6124
- return /* @__PURE__ */ jsxs(ScreenLayout, { footer: /* @__PURE__ */ jsx(PoweredByFooter, {}), children: [
6125
- /* @__PURE__ */ jsx(ScreenHeader, { title: "Select Token", onBack }),
6126
- depositAmount != null && /* @__PURE__ */ jsxs("div", { style: depositHeaderStyle, children: [
6127
- /* @__PURE__ */ jsx("div", { style: depositLabelStyle3(t.textMuted), children: "Depositing" }),
6128
- /* @__PURE__ */ jsxs("div", { style: depositAmountStyle2(t.text), children: [
6129
- "$",
6130
- depositAmount.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
6131
- ] })
6132
- ] }),
6133
- error && /* @__PURE__ */ jsx("p", { style: errorStyle3(t.error), children: error }),
6134
- /* @__PURE__ */ jsx("div", { style: sectionLabelStyle2(t.textMuted), children: "Choose token to pay with" }),
6135
- /* @__PURE__ */ jsx("div", { style: tokenListStyle3, children: entries.map((entry) => /* @__PURE__ */ jsxs(
6136
- "button",
6137
- {
6138
- type: "button",
6139
- onClick: () => onSelect(entry),
6140
- disabled: setting,
6141
- style: tokenRowStyle3(t, setting),
6142
- children: [
6143
- /* @__PURE__ */ jsx("div", { style: tokenIconCircleStyle3(t, !!TOKEN_LOGOS[entry.tokenSymbol]), children: TOKEN_LOGOS[entry.tokenSymbol] ? /* @__PURE__ */ jsx("img", { src: TOKEN_LOGOS[entry.tokenSymbol], alt: entry.tokenSymbol, style: tokenLogoImgStyle3 }) : /* @__PURE__ */ jsx("span", { style: tokenIconTextStyle3(t.textMuted), children: "$" }) }),
6144
- /* @__PURE__ */ jsxs("div", { style: tokenInfoStyle3, children: [
6145
- /* @__PURE__ */ jsxs("div", { style: tokenNameRowStyle2, children: [
6146
- /* @__PURE__ */ jsx("span", { style: tokenSymbolTextStyle2(t.text), children: entry.tokenSymbol }),
6147
- /* @__PURE__ */ jsx("span", { style: tokenChainDotStyle2(t.textMuted), children: "\xB7" }),
6148
- /* @__PURE__ */ jsx("span", { style: tokenChainTextStyle2(t.textMuted), children: entry.chainName })
6149
- ] }),
6150
- /* @__PURE__ */ jsxs("span", { style: tokenBalanceStyle2(t.textMuted), children: [
6151
- "$",
6152
- entry.balance.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
6181
+ const rowBusy = setting || quoteLoading;
6182
+ const displayEntry = pendingEntry ?? entries[0] ?? null;
6183
+ const canConfirm = Boolean(quoteFee && pendingEntry && !quoteLoading);
6184
+ const feeLine = (() => {
6185
+ if (quoteLoading && pendingEntry) {
6186
+ return /* @__PURE__ */ jsx("div", { style: feeRowContainerStyle, "aria-live": "polite", children: /* @__PURE__ */ jsx("span", { style: feeRowLabelStyle(t.textMuted), children: "Getting fee estimate\u2026" }) });
6187
+ }
6188
+ if (quoteFee) {
6189
+ const feeText = isPreciseMoneyNonPositive(quoteFee) ? formatNonPositiveFeeDisplay(quoteFee) : formatPreciseMoneyForDisplay(quoteFee);
6190
+ return /* @__PURE__ */ jsxs("div", { style: feeRowContainerStyle, "aria-live": "polite", children: [
6191
+ /* @__PURE__ */ jsx("span", { style: feeRowLabelStyle(t.textMuted), children: "Fee estimate: " }),
6192
+ /* @__PURE__ */ jsx("span", { style: feeRowAmountStyle(t.textSecondary), children: feeText })
6193
+ ] });
6194
+ }
6195
+ return null;
6196
+ })();
6197
+ return /* @__PURE__ */ jsxs(
6198
+ ScreenLayout,
6199
+ {
6200
+ footer: /* @__PURE__ */ jsxs(Fragment, { children: [
6201
+ canConfirm && /* @__PURE__ */ jsx(PrimaryButton, { onClick: () => void onConfirm(), loading: setting, disabled: setting, children: "Continue" }),
6202
+ /* @__PURE__ */ jsx(PoweredByFooter, {})
6203
+ ] }),
6204
+ children: [
6205
+ /* @__PURE__ */ jsx(ScreenHeader, { onBack }),
6206
+ /* @__PURE__ */ jsxs("div", { ref: pickerRef, children: [
6207
+ /* @__PURE__ */ jsxs("div", { style: depositCardSurfaceStyle(t, tokenListOpen), children: [
6208
+ /* @__PURE__ */ jsx("div", { style: depositLabelStyle3(t.textMuted), children: "Deposit" }),
6209
+ /* @__PURE__ */ jsxs("div", { style: amountBandStyle, children: [
6210
+ /* @__PURE__ */ jsxs("div", { style: amountLeftColStyle, children: [
6211
+ depositAmount != null && /* @__PURE__ */ jsxs("div", { style: depositAmountStyle2(t.text), children: [
6212
+ "$",
6213
+ depositAmount.toLocaleString("en-US", {
6214
+ minimumFractionDigits: 0,
6215
+ maximumFractionDigits: 2
6216
+ })
6217
+ ] }),
6218
+ feeLine
6219
+ ] }),
6220
+ /* @__PURE__ */ jsxs(
6221
+ "button",
6222
+ {
6223
+ type: "button",
6224
+ onClick: () => entries.length > 0 && setTokenListOpen((o) => !o),
6225
+ disabled: entries.length === 0 || rowBusy,
6226
+ style: tokenTriggerStyle(t, entries.length > 0 && !rowBusy),
6227
+ "aria-expanded": tokenListOpen,
6228
+ "aria-haspopup": "listbox",
6229
+ children: [
6230
+ /* @__PURE__ */ jsx("div", { style: tokenTriggerIconsStyle, children: pendingEntry && TOKEN_LOGOS[pendingEntry.tokenSymbol] ? /* @__PURE__ */ jsx(
6231
+ "img",
6232
+ {
6233
+ src: TOKEN_LOGOS[pendingEntry.tokenSymbol],
6234
+ alt: "",
6235
+ width: 28,
6236
+ height: 28,
6237
+ style: triggerLogoStyle(0)
6238
+ }
6239
+ ) : entries[0] && entries[1] && TOKEN_LOGOS[entries[0].tokenSymbol] && TOKEN_LOGOS[entries[1].tokenSymbol] ? /* @__PURE__ */ jsxs(Fragment, { children: [
6240
+ /* @__PURE__ */ jsx(
6241
+ "img",
6242
+ {
6243
+ src: TOKEN_LOGOS[entries[0].tokenSymbol],
6244
+ alt: "",
6245
+ width: 28,
6246
+ height: 28,
6247
+ style: triggerLogoStyle(0)
6248
+ }
6249
+ ),
6250
+ /* @__PURE__ */ jsx(
6251
+ "img",
6252
+ {
6253
+ src: TOKEN_LOGOS[entries[1].tokenSymbol],
6254
+ alt: "",
6255
+ width: 28,
6256
+ height: 28,
6257
+ style: triggerLogoStyle(14)
6258
+ }
6259
+ )
6260
+ ] }) : displayEntry && TOKEN_LOGOS[displayEntry.tokenSymbol] ? /* @__PURE__ */ jsx(
6261
+ "img",
6262
+ {
6263
+ src: TOKEN_LOGOS[displayEntry.tokenSymbol],
6264
+ alt: "",
6265
+ width: 28,
6266
+ height: 28,
6267
+ style: triggerLogoStyle(0)
6268
+ }
6269
+ ) : null }),
6270
+ /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", style: { opacity: 0.5 }, children: tokenListOpen ? /* @__PURE__ */ jsx(
6271
+ "path",
6272
+ {
6273
+ d: "M18 15l-6-6-6 6",
6274
+ stroke: t.textMuted,
6275
+ strokeWidth: "2.5",
6276
+ strokeLinecap: "round",
6277
+ strokeLinejoin: "round"
6278
+ }
6279
+ ) : /* @__PURE__ */ jsx(
6280
+ "path",
6281
+ {
6282
+ d: "M6 9l6 6 6-6",
6283
+ stroke: t.textMuted,
6284
+ strokeWidth: "2.5",
6285
+ strokeLinecap: "round",
6286
+ strokeLinejoin: "round"
6287
+ }
6288
+ ) })
6289
+ ]
6290
+ }
6291
+ )
6153
6292
  ] })
6154
6293
  ] }),
6155
- /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: chevronStyle, children: /* @__PURE__ */ jsx("path", { d: "M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z", fill: t.textMuted }) })
6156
- ]
6157
- },
6158
- `${entry.chainId}-${entry.tokenAddress}`
6159
- )) }),
6160
- entries.length === 0 && /* @__PURE__ */ jsx("p", { style: emptyStyle(t.textMuted), children: "No supported tokens found in your wallet. Please ensure you have USDC or USDT." })
6161
- ] });
6294
+ tokenListOpen && entries.length > 0 && /* @__PURE__ */ jsxs("div", { style: tokenDropdownOuterStyle(t), children: [
6295
+ /* @__PURE__ */ jsx("div", { style: accountDropdownLabelStyle2(t.textMuted), children: "Choose token" }),
6296
+ /* @__PURE__ */ jsx("div", { style: tokenDropdownInnerStyle(t), children: entries.map((entry, index) => {
6297
+ const selected = pendingKey === entryKey(entry);
6298
+ const isLast = index === entries.length - 1;
6299
+ return /* @__PURE__ */ jsxs(
6300
+ "button",
6301
+ {
6302
+ type: "button",
6303
+ onClick: () => {
6304
+ void onSelect(entry);
6305
+ },
6306
+ disabled: rowBusy,
6307
+ style: pickerRowStyle(t, selected, isLast),
6308
+ children: [
6309
+ /* @__PURE__ */ jsxs("div", { style: pickerRowLeftStyle, children: [
6310
+ /* @__PURE__ */ jsx("div", { style: tokenIconCircleStyle3(t, !!TOKEN_LOGOS[entry.tokenSymbol]), children: TOKEN_LOGOS[entry.tokenSymbol] ? /* @__PURE__ */ jsx(
6311
+ "img",
6312
+ {
6313
+ src: TOKEN_LOGOS[entry.tokenSymbol],
6314
+ alt: entry.tokenSymbol,
6315
+ style: tokenLogoImgStyle3
6316
+ }
6317
+ ) : /* @__PURE__ */ jsx("span", { style: tokenIconTextStyle3(t.textMuted), children: "$" }) }),
6318
+ /* @__PURE__ */ jsxs("div", { style: pickerRowInfoStyle, children: [
6319
+ /* @__PURE__ */ jsxs("div", { style: tokenNameRowStyle2, children: [
6320
+ /* @__PURE__ */ jsx("span", { style: tokenSymbolTextStyle2(t.text), children: entry.tokenSymbol }),
6321
+ /* @__PURE__ */ jsx("span", { style: tokenChainDotStyle2(t.textMuted), children: "\xB7" }),
6322
+ /* @__PURE__ */ jsx("span", { style: tokenChainTextStyle2(t.textMuted), children: entry.chainName })
6323
+ ] }),
6324
+ /* @__PURE__ */ jsxs("span", { style: tokenBalanceStyle2(t.textMuted), children: [
6325
+ "$",
6326
+ entry.balance.toLocaleString("en-US", {
6327
+ minimumFractionDigits: 2,
6328
+ maximumFractionDigits: 2
6329
+ })
6330
+ ] })
6331
+ ] })
6332
+ ] }),
6333
+ selected ? /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 22 22", fill: "none", children: [
6334
+ /* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "11", fill: t.success }),
6335
+ /* @__PURE__ */ jsx(
6336
+ "path",
6337
+ {
6338
+ d: "M7 11l3 3 5-5",
6339
+ stroke: "#fff",
6340
+ strokeWidth: "2",
6341
+ strokeLinecap: "round",
6342
+ strokeLinejoin: "round"
6343
+ }
6344
+ )
6345
+ ] }) : /* @__PURE__ */ jsx("div", { style: radioEmptyStyle2(t.border) })
6346
+ ]
6347
+ },
6348
+ entryKey(entry)
6349
+ );
6350
+ }) })
6351
+ ] })
6352
+ ] }),
6353
+ error && /* @__PURE__ */ jsx("p", { style: errorStyle3(t.error), children: error }),
6354
+ entries.length === 0 && /* @__PURE__ */ jsx("p", { style: emptyStyle(t.textMuted), children: "No supported tokens found in your wallet. Please ensure you have USDC or USDT." })
6355
+ ]
6356
+ }
6357
+ );
6162
6358
  }
6163
6359
  var loadingWrapStyle = {
6164
6360
  textAlign: "center",
@@ -6168,52 +6364,133 @@ var loadingWrapStyle = {
6168
6364
  alignItems: "center",
6169
6365
  justifyContent: "center"
6170
6366
  };
6171
- var depositHeaderStyle = {
6172
- marginBottom: 20
6173
- };
6367
+ var depositCardSurfaceStyle = (tokens, listOpen) => ({
6368
+ background: tokens.bgCard,
6369
+ border: `1px solid ${tokens.border}`,
6370
+ borderRadius: tokens.radiusLg,
6371
+ padding: "16px 20px",
6372
+ marginBottom: listOpen ? 4 : 16
6373
+ });
6174
6374
  var depositLabelStyle3 = (color) => ({
6175
6375
  fontSize: "0.75rem",
6176
6376
  fontWeight: 500,
6177
6377
  color,
6178
6378
  marginBottom: 4
6179
6379
  });
6380
+ var amountBandStyle = {
6381
+ display: "flex",
6382
+ alignItems: "flex-start",
6383
+ justifyContent: "space-between",
6384
+ gap: 12
6385
+ };
6386
+ var amountLeftColStyle = {
6387
+ flex: 1,
6388
+ minWidth: 0
6389
+ };
6180
6390
  var depositAmountStyle2 = (color) => ({
6181
6391
  fontSize: "2.4rem",
6182
6392
  fontWeight: 700,
6183
6393
  letterSpacing: "-0.02em",
6184
- color
6185
- });
6186
- var errorStyle3 = (color) => ({
6187
- fontSize: "0.84rem",
6188
6394
  color,
6189
- margin: "0 0 12px",
6190
- lineHeight: 1.5
6395
+ lineHeight: 1.05
6191
6396
  });
6192
- var sectionLabelStyle2 = (color) => ({
6397
+ var feeRowContainerStyle = {
6193
6398
  fontSize: "0.84rem",
6194
6399
  fontWeight: 500,
6400
+ marginTop: 6
6401
+ };
6402
+ var feeRowLabelStyle = (color) => ({ color });
6403
+ var feeRowAmountStyle = (color) => ({
6195
6404
  color,
6196
- marginBottom: 12
6405
+ fontVariantNumeric: "tabular-nums"
6197
6406
  });
6198
- var tokenListStyle3 = {
6407
+ var tokenTriggerStyle = (tokens, interactive) => ({
6199
6408
  display: "flex",
6200
- flexDirection: "column",
6201
- gap: 10
6409
+ alignItems: "center",
6410
+ gap: 6,
6411
+ flexShrink: 0,
6412
+ marginTop: 4,
6413
+ padding: "6px 10px",
6414
+ background: tokens.bgInput,
6415
+ border: `1px solid ${tokens.border}`,
6416
+ borderRadius: 999,
6417
+ cursor: interactive ? "pointer" : "default",
6418
+ fontFamily: "inherit"
6419
+ });
6420
+ var tokenTriggerIconsStyle = {
6421
+ position: "relative",
6422
+ width: 40,
6423
+ height: 28
6202
6424
  };
6203
- var tokenRowStyle3 = (tokens, disabled) => ({
6425
+ var triggerLogoStyle = (left) => ({
6426
+ position: "absolute",
6427
+ left,
6428
+ top: 0,
6429
+ borderRadius: "50%",
6430
+ objectFit: "cover",
6431
+ border: "2px solid rgba(255,255,255,0.9)",
6432
+ boxSizing: "content-box"
6433
+ });
6434
+ var tokenDropdownOuterStyle = (tokens) => ({
6435
+ marginTop: 4,
6436
+ marginBottom: 16,
6437
+ background: tokens.bgCard,
6438
+ border: `1px solid ${tokens.border}`,
6439
+ borderRadius: tokens.radiusLg,
6440
+ boxShadow: tokens.shadowLg,
6441
+ padding: "12px 14px 14px"
6442
+ });
6443
+ var accountDropdownLabelStyle2 = (color) => ({
6444
+ fontSize: "0.78rem",
6445
+ fontWeight: 500,
6446
+ color,
6447
+ marginBottom: 8
6448
+ });
6449
+ var tokenDropdownInnerStyle = (tokens) => ({
6450
+ background: tokens.bgInput,
6451
+ border: `1px solid ${tokens.border}`,
6452
+ borderRadius: tokens.radiusLg,
6453
+ overflow: "hidden"
6454
+ });
6455
+ var pickerRowStyle = (tokens, isSelected, isLast) => ({
6204
6456
  display: "flex",
6205
6457
  alignItems: "center",
6206
- gap: 14,
6458
+ justifyContent: "space-between",
6459
+ width: "100%",
6207
6460
  padding: "14px 16px",
6208
- background: tokens.bgInput,
6209
- border: `1px solid ${tokens.border}`,
6210
- borderRadius: 16,
6211
- cursor: disabled ? "default" : "pointer",
6461
+ background: isSelected ? `${tokens.accent}18` : "transparent",
6462
+ border: "none",
6463
+ borderBottom: isLast ? "none" : `1px solid ${tokens.border}`,
6464
+ cursor: "pointer",
6212
6465
  fontFamily: "inherit",
6213
6466
  textAlign: "left",
6214
- width: "100%",
6215
- opacity: disabled ? 0.6 : 1,
6216
- transition: "opacity 0.15s ease"
6467
+ outline: "none"
6468
+ });
6469
+ var pickerRowLeftStyle = {
6470
+ display: "flex",
6471
+ alignItems: "center",
6472
+ gap: 12,
6473
+ minWidth: 0,
6474
+ flex: 1
6475
+ };
6476
+ var pickerRowInfoStyle = {
6477
+ display: "flex",
6478
+ flexDirection: "column",
6479
+ gap: 2,
6480
+ minWidth: 0
6481
+ };
6482
+ var radioEmptyStyle2 = (borderColor) => ({
6483
+ width: 22,
6484
+ height: 22,
6485
+ borderRadius: "50%",
6486
+ border: `2px solid ${borderColor}`,
6487
+ flexShrink: 0
6488
+ });
6489
+ var errorStyle3 = (color) => ({
6490
+ fontSize: "0.84rem",
6491
+ color,
6492
+ margin: "0 0 12px",
6493
+ lineHeight: 1.5
6217
6494
  });
6218
6495
  var tokenIconCircleStyle3 = (tokens, hasLogo) => ({
6219
6496
  width: 36,
@@ -6237,13 +6514,6 @@ var tokenIconTextStyle3 = (color) => ({
6237
6514
  fontWeight: 700,
6238
6515
  color
6239
6516
  });
6240
- var tokenInfoStyle3 = {
6241
- display: "flex",
6242
- flexDirection: "column",
6243
- gap: 2,
6244
- flex: 1,
6245
- minWidth: 0
6246
- };
6247
6517
  var tokenNameRowStyle2 = {
6248
6518
  display: "flex",
6249
6519
  alignItems: "center",
@@ -6267,10 +6537,6 @@ var tokenBalanceStyle2 = (color) => ({
6267
6537
  fontSize: "0.78rem",
6268
6538
  color
6269
6539
  });
6270
- var chevronStyle = {
6271
- flexShrink: 0,
6272
- opacity: 0.4
6273
- };
6274
6540
  var emptyStyle = (color) => ({
6275
6541
  fontSize: "0.88rem",
6276
6542
  color,
@@ -6292,7 +6558,7 @@ function GuestPreauthSetupCompleteScreen({
6292
6558
  ] }),
6293
6559
  children: [
6294
6560
  /* @__PURE__ */ jsx(ScreenHeader, { onLogout }),
6295
- /* @__PURE__ */ jsxs("div", { style: contentStyle9, children: [
6561
+ /* @__PURE__ */ jsxs("div", { style: contentStyle10, children: [
6296
6562
  /* @__PURE__ */ jsx(IconCircle, { variant: "success", size: 64, children: /* @__PURE__ */ jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
6297
6563
  "path",
6298
6564
  {
@@ -6301,13 +6567,13 @@ function GuestPreauthSetupCompleteScreen({
6301
6567
  }
6302
6568
  ) }) }),
6303
6569
  /* @__PURE__ */ jsx("h2", { style: headingStyle12(tokens.text), children: "Setup complete" }),
6304
- /* @__PURE__ */ jsx("p", { style: subtitleStyle10(tokens.textSecondary), children: "Your account is linked and ready. You can close this window or make another deposit." })
6570
+ /* @__PURE__ */ jsx("p", { style: subtitleStyle12(tokens.textSecondary), children: "Your account is linked and ready. You can close this window or make another deposit." })
6305
6571
  ] })
6306
6572
  ]
6307
6573
  }
6308
6574
  );
6309
6575
  }
6310
- var contentStyle9 = {
6576
+ var contentStyle10 = {
6311
6577
  display: "flex",
6312
6578
  flexDirection: "column",
6313
6579
  alignItems: "center",
@@ -6323,7 +6589,7 @@ function headingStyle12(color) {
6323
6589
  color
6324
6590
  };
6325
6591
  }
6326
- function subtitleStyle10(color) {
6592
+ function subtitleStyle12(color) {
6327
6593
  return {
6328
6594
  margin: 0,
6329
6595
  fontSize: 15,
@@ -6336,14 +6602,14 @@ function GuestPreauthLinkingScreen({ onLogout }) {
6336
6602
  const { tokens } = useBlinkConfig();
6337
6603
  return /* @__PURE__ */ jsxs(ScreenLayout, { children: [
6338
6604
  /* @__PURE__ */ jsx(ScreenHeader, { onLogout }),
6339
- /* @__PURE__ */ jsxs("div", { style: contentStyle10, children: [
6605
+ /* @__PURE__ */ jsxs("div", { style: contentStyle11, children: [
6340
6606
  /* @__PURE__ */ jsx(Spinner, { size: 48 }),
6341
6607
  /* @__PURE__ */ jsx("h2", { style: headingStyle13(tokens.text), children: "Setting up your account..." }),
6342
- /* @__PURE__ */ jsx("p", { style: subtitleStyle11(tokens.textSecondary), children: "Linking your wallet to your Blink account. This usually takes a few seconds." })
6608
+ /* @__PURE__ */ jsx("p", { style: subtitleStyle13(tokens.textSecondary), children: "Linking your wallet to your Blink account. This usually takes a few seconds." })
6343
6609
  ] })
6344
6610
  ] });
6345
6611
  }
6346
- var contentStyle10 = {
6612
+ var contentStyle11 = {
6347
6613
  flex: 1,
6348
6614
  display: "flex",
6349
6615
  flexDirection: "column",
@@ -6361,7 +6627,7 @@ function headingStyle13(color) {
6361
6627
  color
6362
6628
  };
6363
6629
  }
6364
- function subtitleStyle11(color) {
6630
+ function subtitleStyle13(color) {
6365
6631
  return {
6366
6632
  margin: 0,
6367
6633
  fontSize: "0.9rem",
@@ -6453,6 +6719,9 @@ function StepRendererContent({
6453
6719
  guestTokenEntries,
6454
6720
  guestLoadingBalances,
6455
6721
  guestSettingSender,
6722
+ guestPendingEntry,
6723
+ guestQuoteFee,
6724
+ guestQuoteLoading,
6456
6725
  authInput,
6457
6726
  otpCode,
6458
6727
  selectSourceChainName,
@@ -6576,6 +6845,28 @@ function StepRendererContent({
6576
6845
  );
6577
6846
  const effectiveTokenCount = tokenCount > 0 ? tokenCount : selectSourceTokenCount;
6578
6847
  const effectiveSourceLabel = selectedSourceLabel ?? (selectSourceChainName && selectSourceTokenSymbol ? `${selectSourceTokenSymbol} on ${selectSourceChainName}` : void 0);
6848
+ const setupTokenOptions = selectedAccount ? selectedAccount.wallets.flatMap(
6849
+ (w) => w.sources.filter((s) => s.balance.total.amount > 0).map((s) => ({
6850
+ symbol: s.token.symbol,
6851
+ chainName: w.chain.name,
6852
+ balance: s.balance.available.amount,
6853
+ walletId: w.id
6854
+ }))
6855
+ ) : selectSourceChoices.flatMap(
6856
+ (chain) => chain.tokens.map((t) => ({
6857
+ symbol: t.tokenSymbol,
6858
+ chainName: chain.chainName,
6859
+ balance: t.balance
6860
+ }))
6861
+ );
6862
+ const handleSetupSelectToken = (symbol, chainName, walletId) => {
6863
+ if (walletId) {
6864
+ handlers.onSelectAuthorizedToken(walletId, symbol);
6865
+ } else {
6866
+ handlers.onSelectSourceChainChange(chainName);
6867
+ handlers.onSetSelectSourceTokenSymbol(symbol);
6868
+ }
6869
+ };
6579
6870
  return /* @__PURE__ */ jsx(
6580
6871
  SetupScreen,
6581
6872
  {
@@ -6589,7 +6880,9 @@ function StepRendererContent({
6589
6880
  selectedSourceLabel: effectiveSourceLabel,
6590
6881
  loading: savingOneTapLimit,
6591
6882
  error: state.error,
6592
- selectedTokenSymbol: selectedSource?.token.symbol ?? selectSourceTokenSymbol
6883
+ selectedTokenSymbol: selectedSource?.token.symbol ?? selectSourceTokenSymbol,
6884
+ tokenOptions: setupTokenOptions,
6885
+ onSelectToken: handleSetupSelectToken
6593
6886
  }
6594
6887
  );
6595
6888
  }
@@ -6690,7 +6983,11 @@ function StepRendererContent({
6690
6983
  setting: guestSettingSender,
6691
6984
  depositAmount: depositAmount ?? void 0,
6692
6985
  error: state.error,
6986
+ pendingEntry: forms.guestPendingEntry,
6987
+ quoteFee: forms.guestQuoteFee,
6988
+ quoteLoading: forms.guestQuoteLoading,
6693
6989
  onSelect: handlers.onSelectGuestToken,
6990
+ onConfirm: handlers.onConfirmGuestToken,
6694
6991
  onBack: handlers.onGuestBackFromTokenPicker
6695
6992
  }
6696
6993
  );
@@ -7994,8 +8291,8 @@ function useProviderHandlers(deps) {
7994
8291
  }
7995
8292
 
7996
8293
  // src/guestTokens.ts
7997
- function mapBalancesToGuestTokenEntries(options) {
7998
- return options.map((opt) => ({
8294
+ function mapGuestPickerEntries(options) {
8295
+ const mapped = options.map((opt) => ({
7999
8296
  chainId: opt.chainId,
8000
8297
  sourceChainId: opt.sourceChainId,
8001
8298
  chainName: opt.chainName,
@@ -8004,7 +8301,26 @@ function mapBalancesToGuestTokenEntries(options) {
8004
8301
  decimals: opt.decimals,
8005
8302
  rawBalance: opt.rawBalance,
8006
8303
  balance: Number(opt.rawBalance) / 10 ** opt.decimals
8007
- })).filter((entry) => entry.balance > 0).sort((a, b) => b.balance - a.balance);
8304
+ }));
8305
+ const positive = mapped.filter((e) => e.balance > 0).sort((a, b) => b.balance - a.balance);
8306
+ if (positive.length > 0) return positive;
8307
+ return mapped.sort((a, b) => b.balance - a.balance);
8308
+ }
8309
+ function guestEntryMatchingRecommended(balances, recommended) {
8310
+ const raw = balances.find(
8311
+ (b) => b.sourceChainId === recommended.sourceChainId && b.tokenAddress.toLowerCase() === recommended.tokenAddress.toLowerCase()
8312
+ );
8313
+ if (!raw) return null;
8314
+ return {
8315
+ chainId: raw.chainId,
8316
+ sourceChainId: raw.sourceChainId,
8317
+ chainName: raw.chainName,
8318
+ tokenSymbol: raw.tokenSymbol,
8319
+ tokenAddress: raw.tokenAddress,
8320
+ decimals: raw.decimals,
8321
+ rawBalance: raw.rawBalance,
8322
+ balance: Number(raw.rawBalance) / 10 ** raw.decimals
8323
+ };
8008
8324
  }
8009
8325
 
8010
8326
  // src/hooks/useGuestTransferHandlers.ts
@@ -8031,30 +8347,86 @@ function useGuestTransferHandlers(deps) {
8031
8347
  const [guestTokenEntries, setGuestTokenEntries] = useState([]);
8032
8348
  const [loadingBalances, setLoadingBalances] = useState(false);
8033
8349
  const [settingSender, setSettingSender] = useState(false);
8350
+ const [pendingGuestEntry, setPendingGuestEntry] = useState(null);
8351
+ const [guestFee, setGuestFee] = useState(null);
8352
+ const [guestQuoteLoading, setGuestQuoteLoading] = useState(false);
8034
8353
  const executingBridgeRef = useRef(false);
8035
8354
  const fetchedRef = useRef(false);
8036
8355
  const selectedGuestTokenRef = useRef(null);
8356
+ useEffect(() => {
8357
+ if (guestTransferId != null) return;
8358
+ fetchedRef.current = false;
8359
+ setGuestTokenEntries([]);
8360
+ setPendingGuestEntry(null);
8361
+ setGuestFee(null);
8362
+ setGuestQuoteLoading(false);
8363
+ setLoadingBalances(false);
8364
+ }, [guestTransferId]);
8037
8365
  useEffect(() => {
8038
8366
  if (!isGuestFlow || !guestTransferId || !guestSessionToken || fetchedRef.current) return;
8039
8367
  const account = getAccount(wagmiConfig2);
8040
8368
  if (!account.address) return;
8041
8369
  fetchedRef.current = true;
8042
8370
  setLoadingBalances(true);
8043
- fetchGuestTransferBalances(apiBaseUrl, guestTransferId, guestSessionToken, account.address).then((options) => mapBalancesToGuestTokenEntries(options)).then((entries) => {
8371
+ putGuestTransferSender(apiBaseUrl, guestTransferId, guestSessionToken, {
8372
+ senderAddress: account.address
8373
+ }).then(async (res) => {
8374
+ const balances = res.source?.balances;
8375
+ if (!balances?.length) {
8376
+ dispatch({ type: "SET_ERROR", error: "No supported tokens found for this transfer." });
8377
+ return;
8378
+ }
8379
+ const entries = mapGuestPickerEntries(balances);
8044
8380
  setGuestTokenEntries(entries);
8045
8381
  if (entries.length === 0) {
8046
8382
  dispatch({ type: "SET_ERROR", error: "No supported tokens found in your wallet." });
8383
+ return;
8384
+ }
8385
+ const recommended = res.source?.recommended;
8386
+ const autoEntry = recommended ? guestEntryMatchingRecommended(balances, recommended) : null;
8387
+ const pick = autoEntry && entries.some(
8388
+ (e) => e.sourceChainId === autoEntry.sourceChainId && e.tokenAddress.toLowerCase() === autoEntry.tokenAddress.toLowerCase()
8389
+ ) ? autoEntry : entries[0];
8390
+ setPendingGuestEntry(pick);
8391
+ setGuestFee(null);
8392
+ if (res.fee?.quote != null) {
8393
+ setGuestFee(res.fee);
8394
+ return;
8395
+ }
8396
+ setGuestQuoteLoading(true);
8397
+ try {
8398
+ const quote = await postGuestTransferFeeQuote(
8399
+ apiBaseUrl,
8400
+ guestTransferId,
8401
+ guestSessionToken,
8402
+ account.address,
8403
+ pick.sourceChainId,
8404
+ pick.tokenAddress
8405
+ );
8406
+ setGuestFee(quote);
8407
+ } catch (err) {
8408
+ captureException(err);
8409
+ setPendingGuestEntry(null);
8410
+ setGuestFee(null);
8411
+ const msg = err instanceof Error ? err.message : "Failed to load fee estimate";
8412
+ dispatch({ type: "SET_ERROR", error: msg });
8413
+ onError?.(msg);
8414
+ } finally {
8415
+ setGuestQuoteLoading(false);
8047
8416
  }
8048
8417
  }).catch((err) => {
8049
8418
  captureException(err);
8050
- dispatch({ type: "SET_ERROR", error: "Failed to fetch token balances." });
8419
+ dispatch({ type: "SET_ERROR", error: "Failed to load payment sources." });
8051
8420
  }).finally(() => setLoadingBalances(false));
8052
- }, [isGuestFlow, guestTransferId, guestSessionToken, apiBaseUrl, wagmiConfig2, dispatch]);
8421
+ }, [isGuestFlow, guestTransferId, guestSessionToken, apiBaseUrl, wagmiConfig2, dispatch, onError]);
8053
8422
  useEffect(() => {
8054
8423
  if (!isGuestFlow) {
8055
8424
  fetchedRef.current = false;
8056
8425
  selectedGuestTokenRef.current = null;
8057
8426
  setGuestTokenEntries([]);
8427
+ setPendingGuestEntry(null);
8428
+ setGuestFee(null);
8429
+ setGuestQuoteLoading(false);
8058
8430
  }
8059
8431
  }, [isGuestFlow]);
8060
8432
  const handleSelectGuestToken = useCallback(async (entry) => {
@@ -8064,7 +8436,44 @@ function useGuestTransferHandlers(deps) {
8064
8436
  dispatch({ type: "SET_ERROR", error: "Wallet not connected." });
8065
8437
  return;
8066
8438
  }
8439
+ setGuestQuoteLoading(true);
8440
+ dispatch({ type: "SET_ERROR", error: null });
8441
+ setPendingGuestEntry(entry);
8442
+ setGuestFee(null);
8443
+ try {
8444
+ console.info(
8445
+ `[blink-sdk] type=guest Fee quote preview: address=${account.address}, chain=${entry.sourceChainId}, token=${entry.tokenSymbol}`
8446
+ );
8447
+ const quote = await postGuestTransferFeeQuote(
8448
+ apiBaseUrl,
8449
+ guestTransferId,
8450
+ guestSessionToken,
8451
+ account.address,
8452
+ entry.sourceChainId,
8453
+ entry.tokenAddress
8454
+ );
8455
+ setGuestFee(quote);
8456
+ } catch (err) {
8457
+ captureException(err);
8458
+ setPendingGuestEntry(null);
8459
+ setGuestFee(null);
8460
+ const msg = err instanceof Error ? err.message : "Failed to load fee estimate";
8461
+ dispatch({ type: "SET_ERROR", error: msg });
8462
+ onError?.(msg);
8463
+ } finally {
8464
+ setGuestQuoteLoading(false);
8465
+ }
8466
+ }, [guestTransferId, guestSessionToken, wagmiConfig2, apiBaseUrl, dispatch, onError]);
8467
+ const handleConfirmGuestToken = useCallback(async () => {
8468
+ if (!guestTransferId || !guestSessionToken || !pendingGuestEntry) return;
8469
+ const account = getAccount(wagmiConfig2);
8470
+ if (!account.address) {
8471
+ dispatch({ type: "SET_ERROR", error: "Wallet not connected." });
8472
+ return;
8473
+ }
8474
+ const entry = pendingGuestEntry;
8067
8475
  setSettingSender(true);
8476
+ dispatch({ type: "SET_ERROR", error: null });
8068
8477
  try {
8069
8478
  console.info(
8070
8479
  `[blink-sdk] type=guest Setting sender: address=${account.address}, chain=${entry.sourceChainId}, token=${entry.tokenSymbol}`
@@ -8086,7 +8495,15 @@ function useGuestTransferHandlers(deps) {
8086
8495
  } finally {
8087
8496
  setSettingSender(false);
8088
8497
  }
8089
- }, [guestTransferId, guestSessionToken, wagmiConfig2, apiBaseUrl, dispatch, onError]);
8498
+ }, [
8499
+ guestTransferId,
8500
+ guestSessionToken,
8501
+ pendingGuestEntry,
8502
+ wagmiConfig2,
8503
+ apiBaseUrl,
8504
+ dispatch,
8505
+ onError
8506
+ ]);
8090
8507
  useEffect(() => {
8091
8508
  if (!isGuestFlow || !guestTransferId || !guestSessionToken || !selectedGuestTokenRef.current) return;
8092
8509
  if (executingBridgeRef.current) return;
@@ -8194,13 +8611,19 @@ function useGuestTransferHandlers(deps) {
8194
8611
  execute();
8195
8612
  }, [isGuestFlow, guestTransferId, guestSessionToken, settingSender, apiBaseUrl, wagmiConfig2, switchChainAsync, dispatch, onComplete, onError]);
8196
8613
  const handleGuestBackFromTokenPicker = useCallback(() => {
8614
+ setPendingGuestEntry(null);
8615
+ setGuestFee(null);
8197
8616
  dispatch({ type: "GUEST_BACK_FROM_TOKEN_PICKER" });
8198
8617
  }, [dispatch]);
8199
8618
  return {
8200
8619
  guestTokenEntries,
8201
8620
  loadingBalances,
8202
8621
  settingSender,
8622
+ pendingGuestEntry,
8623
+ guestFee,
8624
+ guestQuoteLoading,
8203
8625
  handleSelectGuestToken,
8626
+ handleConfirmGuestToken,
8204
8627
  handleGuestBackFromTokenPicker
8205
8628
  };
8206
8629
  }
@@ -9950,6 +10373,7 @@ function BlinkPaymentInner({
9950
10373
  onSelectAuthorizedToken: provider.handleSelectAuthorizedToken,
9951
10374
  onAuthorizeToken: provider.handleAuthorizeToken,
9952
10375
  onSelectGuestToken: guestTransfer.handleSelectGuestToken,
10376
+ onConfirmGuestToken: guestTransfer.handleConfirmGuestToken,
9953
10377
  onGuestBackFromTokenPicker: guestTransfer.handleGuestBackFromTokenPicker,
9954
10378
  onLogin: () => dispatch({ type: "REQUEST_LOGIN" }),
9955
10379
  onPreauthorize: provider.handlePreauthorize,
@@ -10015,13 +10439,16 @@ function BlinkPaymentInner({
10015
10439
  savingOneTapLimit: oneTapSetup.savingOneTapLimit,
10016
10440
  guestTokenEntries: guestTransfer.guestTokenEntries,
10017
10441
  guestLoadingBalances: guestTransfer.loadingBalances,
10018
- guestSettingSender: guestTransfer.settingSender
10442
+ guestSettingSender: guestTransfer.settingSender,
10443
+ guestPendingEntry: guestTransfer.pendingGuestEntry,
10444
+ guestQuoteFee: guestTransfer.guestFee?.quote ?? null,
10445
+ guestQuoteLoading: guestTransfer.guestQuoteLoading
10019
10446
  },
10020
10447
  handlers
10021
10448
  }
10022
10449
  );
10023
10450
  }
10024
10451
 
10025
- export { AdvancedSourceScreen, BLINK_LOGO, BLINK_MASCOT, BlinkLoadingScreen, BlinkPayment, BlinkProvider, FlowPhaseProvider, IconCircle, InfoBanner, OutlineButton, PasskeyIframeBlockedError, PasskeyScreen, PoweredByFooter, PrimaryButton, ScreenHeader, ScreenLayout, SelectSourceScreen, SettingsMenu, SetupScreen, Spinner, StepList, TokenPickerScreen, api_exports as blinkApi, buildPasskeyPopupOptions, createPasskeyCredential, createPasskeyViaPopup, darkTheme, deviceHasPasskey, findDevicePasskey, findDevicePasskeyViaPopup, getTheme, lightTheme, resolvePasskeyRpId, screenForPhase, useAuthorizationExecutor, useBlinkConfig, useBlinkDepositAmount, useTransferPolling, useTransferSigning };
10452
+ export { AdvancedSourceScreen, BLINK_LOGO, BLINK_MASCOT, BlinkLoadingScreen, BlinkPayment, BlinkProvider, ConfirmSignScreen, DepositScreen, FlowPhaseProvider, GuestPreauthLinkingScreen, GuestPreauthSetupCompleteScreen, GuestTokenPickerScreen, IconCircle, InfoBanner, LoginScreen, OpenWalletScreen, OtpVerifyScreen, OutlineButton, PasskeyIframeBlockedError, PasskeyScreen, PoweredByFooter, PrimaryButton, ScreenHeader, ScreenLayout, SelectSourceScreen, SettingsMenu, SetupScreen, SetupStatusScreen, Spinner, StepList, SuccessScreen, TokenPickerScreen, TransferStatusScreen, VerifyPasskeyScreen, WalletPickerScreen, api_exports as blinkApi, buildPasskeyPopupOptions, createPasskeyCredential, createPasskeyViaPopup, darkTheme, deviceHasPasskey, findDevicePasskey, findDevicePasskeyViaPopup, getTheme, guestEntryMatchingRecommended, lightTheme, mapGuestPickerEntries, resolvePasskeyRpId, screenForPhase, useAuthorizationExecutor, useBlinkConfig, useBlinkDepositAmount, useTransferPolling, useTransferSigning };
10026
10453
  //# sourceMappingURL=index.js.map
10027
10454
  //# sourceMappingURL=index.js.map