@shapeshiftoss/swap-widget 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,9 +1,22 @@
1
1
  // src/components/SwapWidget.tsx
2
2
  import { useAppKitAccount as useAppKitAccount3 } from "@reown/appkit/react";
3
- import { useCallback as useCallback11, useEffect as useEffect10, useMemo as useMemo12, useRef as useRef7, useState as useState8 } from "react";
3
+ import { useCallback as useCallback14, useEffect as useEffect14, useLayoutEffect as useLayoutEffect3, useMemo as useMemo15, useRef as useRef12, useState as useState11 } from "react";
4
4
 
5
5
  // src/api/client.ts
6
6
  var DEFAULT_API_BASE_URL = "https://api.shapeshift.com";
7
+ var ApiError = class extends Error {
8
+ constructor(status, code, message) {
9
+ super(message);
10
+ this.status = status;
11
+ this.code = code;
12
+ this.name = "ApiError";
13
+ }
14
+ };
15
+ var readErrorCode = async (response) => {
16
+ const body = await response.json().catch(() => void 0);
17
+ const code = body?.code;
18
+ return typeof code === "string" ? code : void 0;
19
+ };
7
20
  var getTradeAmount = (params) => params.buyAmountCryptoBaseUnit !== void 0 ? { buyAmountCryptoBaseUnit: params.buyAmountCryptoBaseUnit } : { sellAmountCryptoBaseUnit: params.sellAmountCryptoBaseUnit };
8
21
  var createApiClient = (config = {}) => {
9
22
  const baseUrl = config.baseUrl ?? DEFAULT_API_BASE_URL;
@@ -33,7 +46,11 @@ var createApiClient = (config = {}) => {
33
46
  clearTimeout(timeoutId);
34
47
  });
35
48
  if (!response.ok) {
36
- throw new Error(`API error: ${response.status} ${response.statusText}`);
49
+ throw new ApiError(
50
+ response.status,
51
+ await readErrorCode(response),
52
+ `API error: ${response.status} ${response.statusText}`
53
+ );
37
54
  }
38
55
  return response.json();
39
56
  };
@@ -513,36 +530,35 @@ var useBitcoinSigning = () => {
513
530
  );
514
531
  };
515
532
 
516
- // src/hooks/useEvmSigning.ts
517
- import { useAppKitAccount as useAppKitAccount2, useAppKitProvider as useAppKitProvider2 } from "@reown/appkit/react";
518
- import { useMemo as useMemo2 } from "react";
519
- import { createWalletClient, custom, getAddress, isAddress } from "viem";
520
- var useEvmSigning = () => {
521
- const { walletProvider } = useAppKitProvider2("eip155");
522
- const { address, isConnected } = useAppKitAccount2({ namespace: "eip155" });
523
- const checksummedAddress = useMemo2(() => {
524
- if (!address || !isAddress(address)) return void 0;
525
- return getAddress(address);
526
- }, [address]);
527
- const walletClient = useMemo2(() => {
528
- if (!walletProvider || !checksummedAddress) return void 0;
529
- return createWalletClient({
530
- account: checksummedAddress,
531
- transport: custom(walletProvider)
532
- });
533
- }, [walletProvider, checksummedAddress]);
534
- return useMemo2(
535
- () => ({
536
- walletClient,
537
- address: checksummedAddress,
538
- isConnected: !!(isConnected && checksummedAddress)
539
- }),
540
- [walletClient, checksummedAddress, isConnected]
533
+ // src/hooks/useCustomAddress.ts
534
+ import { useCallback as useCallback2, useEffect, useRef, useState as useState2 } from "react";
535
+
536
+ // src/utils/addressSpace.ts
537
+ import { CHAIN_NAMESPACE, fromChainId } from "@shapeshiftoss/caip";
538
+ var sharesAddressSpace = (chainId, otherChainId) => chainId === otherChainId || fromChainId(chainId).chainNamespace === CHAIN_NAMESPACE.Evm && fromChainId(otherChainId).chainNamespace === CHAIN_NAMESPACE.Evm;
539
+
540
+ // src/hooks/useCustomAddress.ts
541
+ var useCustomAddress = (chainId) => {
542
+ const [scoped, setScoped] = useState2({ address: "", chainId });
543
+ const chainIdRef = useRef(chainId);
544
+ chainIdRef.current = chainId;
545
+ const setAddress = useCallback2(
546
+ (address, forChainId = chainIdRef.current) => setScoped({ address, chainId: forChainId }),
547
+ []
541
548
  );
549
+ const previousChainIdRef = useRef(chainId);
550
+ useEffect(() => {
551
+ if (previousChainIdRef.current === chainId) return;
552
+ previousChainIdRef.current = chainId;
553
+ setScoped(
554
+ (current) => current.address && !sharesAddressSpace(current.chainId, chainId) ? { address: "", chainId } : current
555
+ );
556
+ }, [chainId]);
557
+ return [sharesAddressSpace(scoped.chainId, chainId) ? scoped.address : "", setAddress];
542
558
  };
543
559
 
544
- // src/hooks/useSellFiatSync.ts
545
- import { useEffect } from "react";
560
+ // src/hooks/useDepositPolling.ts
561
+ import { useEffect as useEffect2, useRef as useRef2 } from "react";
546
562
 
547
563
  // src/machines/SwapMachineContext.ts
548
564
  import { createActorContext } from "@xstate/react";
@@ -558,11 +574,11 @@ import {
558
574
  bchChainId,
559
575
  bscChainId,
560
576
  btcChainId,
561
- CHAIN_NAMESPACE,
577
+ CHAIN_NAMESPACE as CHAIN_NAMESPACE2,
562
578
  cosmosChainId,
563
579
  dogeChainId,
564
580
  ethChainId as ethChainId2,
565
- fromChainId,
581
+ fromChainId as fromChainId2,
566
582
  gnosisChainId,
567
583
  hyperEvmChainId,
568
584
  katanaChainId,
@@ -589,6 +605,7 @@ var SwapperName = /* @__PURE__ */ ((SwapperName2) => {
589
605
  SwapperName2["Relay"] = "Relay";
590
606
  SwapperName2["Thorchain"] = "THORChain";
591
607
  SwapperName2["Mayachain"] = "MAYAChain";
608
+ SwapperName2["Chainflip"] = "Chainflip";
592
609
  return SwapperName2;
593
610
  })(SwapperName || {});
594
611
  var EVM_CHAIN_IDS = {
@@ -629,23 +646,23 @@ var REDIRECT_ONLY_CHAIN_IDS = {
629
646
  starknet: starknetChainId
630
647
  };
631
648
  var isEvmChainId = (chainId) => {
632
- const { chainNamespace } = fromChainId(chainId);
633
- return chainNamespace === CHAIN_NAMESPACE.Evm;
649
+ const { chainNamespace } = fromChainId2(chainId);
650
+ return chainNamespace === CHAIN_NAMESPACE2.Evm;
634
651
  };
635
652
  var getEvmNetworkId = (chainId) => {
636
- const { chainReference } = fromChainId(chainId);
653
+ const { chainReference } = fromChainId2(chainId);
637
654
  return parseInt(chainReference, 10);
638
655
  };
639
656
  var getChainType = (chainId) => {
640
- const { chainNamespace } = fromChainId(chainId);
657
+ const { chainNamespace } = fromChainId2(chainId);
641
658
  switch (chainNamespace) {
642
- case CHAIN_NAMESPACE.Evm:
659
+ case CHAIN_NAMESPACE2.Evm:
643
660
  return "evm";
644
- case CHAIN_NAMESPACE.Utxo:
661
+ case CHAIN_NAMESPACE2.Utxo:
645
662
  return "utxo";
646
- case CHAIN_NAMESPACE.CosmosSdk:
663
+ case CHAIN_NAMESPACE2.CosmosSdk:
647
664
  return "cosmos";
648
- case CHAIN_NAMESPACE.Solana:
665
+ case CHAIN_NAMESPACE2.Solana:
649
666
  return "solana";
650
667
  default:
651
668
  return "other";
@@ -723,11 +740,13 @@ var createInitialContext = (input) => {
723
740
  selectedRate: null,
724
741
  quote: null,
725
742
  txHash: null,
743
+ depositObservedAt: null,
726
744
  approvalTxHash: null,
727
745
  error: null,
728
746
  errorSource: null,
729
747
  retryCount: 0,
730
748
  chainType: sellChainType,
749
+ isDepositFlow: false,
731
750
  slippage: input?.slippage ?? "0.5",
732
751
  sendAddress: void 0,
733
752
  receiveAddress: void 0,
@@ -750,6 +769,15 @@ var swapMachine = setup({
750
769
  const namespace = context.sellAsset.assetId.split("/")[1]?.split(":")[0];
751
770
  return namespace === "erc20";
752
771
  },
772
+ isDepositQuote: ({ context, event }) => {
773
+ const { quote } = event;
774
+ return context.isDepositFlow && !!quote?.depositAddress;
775
+ },
776
+ isDepositFlowWithoutAddress: ({ context, event }) => {
777
+ const { quote } = event;
778
+ return context.isDepositFlow && !quote?.depositAddress;
779
+ },
780
+ isRestoredDepositFunded: ({ event }) => !!event.txHash,
753
781
  canRetry: ({ context }) => canRetry(context),
754
782
  isQuoteError: ({ context }) => context.errorSource === "QUOTE_ERROR",
755
783
  isApprovalError: ({ context }) => context.errorSource === "APPROVAL_ERROR",
@@ -831,6 +859,54 @@ var swapMachine = setup({
831
859
  assignTxHash: assign(({ event }) => ({
832
860
  txHash: event.txHash
833
861
  })),
862
+ assignDepositFlow: assign(({ event }) => ({
863
+ isDepositFlow: event.isDepositFlow === true
864
+ })),
865
+ assignDepositTxHash: assign(({ event }) => {
866
+ const { txHash, observedAt } = event;
867
+ return { txHash, depositObservedAt: observedAt };
868
+ }),
869
+ assignDepositUnavailableError: assign(() => ({
870
+ error: "This route needs a connected wallet",
871
+ errorSource: "QUOTE_ERROR"
872
+ })),
873
+ assignTrackingTimeout: assign(() => ({
874
+ error: "Check your receive address - the provider may still settle this swap",
875
+ errorSource: "TRACKING_TIMEOUT"
876
+ })),
877
+ assignRestoredDeposit: assign(({ event }) => {
878
+ const {
879
+ quote,
880
+ sendAddress,
881
+ receiveAddress,
882
+ sellAmountBaseUnit,
883
+ buyAmountBaseUnit,
884
+ txHash,
885
+ depositObservedAt
886
+ } = event;
887
+ const { sellAsset, buyAsset } = quote;
888
+ return {
889
+ quote,
890
+ sendAddress,
891
+ receiveAddress,
892
+ txHash: txHash ?? null,
893
+ depositObservedAt: depositObservedAt ?? null,
894
+ isDepositFlow: true,
895
+ sellAsset,
896
+ buyAsset,
897
+ sellAmountBaseUnit,
898
+ sellAmount: sellAmountBaseUnit ? formatAmountForInput(sellAmountBaseUnit, sellAsset.precision) : "",
899
+ buyAmountBaseUnit,
900
+ buyAmount: buyAmountBaseUnit ? formatAmountForInput(buyAmountBaseUnit, buyAsset.precision) : "",
901
+ chainType: getChainType(sellAsset.chainId),
902
+ isSellAssetEvm: isWidgetExecutableEvmChainId(sellAsset.chainId),
903
+ isSellAssetUtxo: isWidgetExecutableUtxoChainId(sellAsset.chainId),
904
+ isSellAssetSolana: isWidgetExecutableSolanaChainId(sellAsset.chainId),
905
+ isBuyAssetEvm: getChainType(buyAsset.chainId) === "evm",
906
+ error: null,
907
+ errorSource: null
908
+ };
909
+ }),
834
910
  assignExecuteError: assign(({ event }) => ({
835
911
  error: event.error,
836
912
  errorSource: "EXECUTE_ERROR"
@@ -871,16 +947,22 @@ var swapMachine = setup({
871
947
  incrementRetryCount: assign(({ context }) => ({
872
948
  retryCount: context.retryCount + 1,
873
949
  error: null,
874
- errorSource: null
950
+ errorSource: null,
951
+ // Every retry re-quotes or re-signs, so a carried-over hash would mark the next one funded
952
+ txHash: null,
953
+ depositObservedAt: null,
954
+ approvalTxHash: null
875
955
  })),
876
956
  resetSwapState: assign(({ context }) => ({
877
957
  quote: null,
878
958
  txHash: null,
959
+ depositObservedAt: null,
879
960
  approvalTxHash: null,
880
961
  error: null,
881
962
  errorSource: null,
882
963
  retryCount: 0,
883
964
  selectedRate: null,
965
+ isDepositFlow: false,
884
966
  sellAsset: context.sellAsset,
885
967
  buyAsset: context.buyAsset,
886
968
  sellAmount: context.sellAmount,
@@ -912,15 +994,34 @@ var swapMachine = setup({
912
994
  SET_SEND_ADDRESS: { actions: "assignSendAddress" },
913
995
  SET_RECEIVE_ADDRESS: { actions: "assignReceiveAddress" },
914
996
  UPDATE_CHAIN_INFO: { actions: "assignChainInfo" },
997
+ RESTORE_DEPOSIT: [
998
+ {
999
+ target: "polling_status",
1000
+ guard: "isRestoredDepositFunded",
1001
+ actions: "assignRestoredDeposit"
1002
+ },
1003
+ { target: "awaiting_deposit", actions: "assignRestoredDeposit" }
1004
+ ],
915
1005
  FETCH_QUOTE: {
916
1006
  target: "quoting",
917
- guard: "hasValidInput"
1007
+ guard: "hasValidInput",
1008
+ actions: "assignDepositFlow"
918
1009
  }
919
1010
  }
920
1011
  },
921
1012
  quoting: {
922
1013
  on: {
923
1014
  QUOTE_SUCCESS: [
1015
+ {
1016
+ target: "awaiting_deposit",
1017
+ guard: "isDepositQuote",
1018
+ actions: "assignQuote"
1019
+ },
1020
+ {
1021
+ target: "error",
1022
+ guard: "isDepositFlowWithoutAddress",
1023
+ actions: "assignDepositUnavailableError"
1024
+ },
924
1025
  {
925
1026
  target: "approval_needed",
926
1027
  guard: "isApprovalRequired",
@@ -967,13 +1068,39 @@ var swapMachine = setup({
967
1068
  }
968
1069
  }
969
1070
  },
1071
+ // Both deposit states take a terminal status - a provider can settle or refund without a hash
1072
+ awaiting_deposit: {
1073
+ on: {
1074
+ DEPOSIT_DETECTED: { target: "polling_status", actions: "assignDepositTxHash" },
1075
+ DEPOSIT_EXPIRED: { target: "deposit_expired" },
1076
+ STATUS_CONFIRMED: { target: "complete" },
1077
+ STATUS_FAILED: { target: "error", actions: "assignStatusFailed" },
1078
+ RESET: { target: "input", actions: "resetSwapState" }
1079
+ }
1080
+ },
1081
+ deposit_expired: {
1082
+ on: {
1083
+ DEPOSIT_DETECTED: { target: "polling_status", actions: "assignDepositTxHash" },
1084
+ STATUS_CONFIRMED: { target: "complete" },
1085
+ STATUS_FAILED: { target: "error", actions: "assignStatusFailed" },
1086
+ RETRY: { target: "quoting", actions: "incrementRetryCount" },
1087
+ RESET: { target: "input", actions: "resetSwapState" }
1088
+ }
1089
+ },
970
1090
  polling_status: {
971
1091
  on: {
972
1092
  STATUS_CONFIRMED: { target: "complete" },
973
1093
  STATUS_FAILED: {
974
1094
  target: "error",
975
1095
  actions: "assignStatusFailed"
976
- }
1096
+ },
1097
+ // The one deposit screen with no controls of its own, so it can't be left spinning
1098
+ DEPOSIT_TRACKING_TIMEOUT: {
1099
+ target: "error",
1100
+ actions: "assignTrackingTimeout"
1101
+ },
1102
+ // A deposit swap settles server-side whether or not anyone watches it
1103
+ RESET: { target: "input", actions: "resetSwapState" }
977
1104
  }
978
1105
  },
979
1106
  complete: {
@@ -1014,6 +1141,114 @@ var swapMachine = setup({
1014
1141
  // src/machines/SwapMachineContext.ts
1015
1142
  var SwapMachineCtx = createActorContext(swapMachine);
1016
1143
 
1144
+ // src/utils/depositStatus.ts
1145
+ var resolveDepositStatusEvent = (response, hasDetectedDeposit, observedAt) => {
1146
+ if (!hasDetectedDeposit && response.txHash) {
1147
+ return { type: "DEPOSIT_DETECTED", txHash: response.txHash, observedAt };
1148
+ }
1149
+ if (response.status === "failed") return { type: "STATUS_FAILED", error: "Swap failed" };
1150
+ if (response.status === "confirmed") return { type: "STATUS_CONFIRMED" };
1151
+ };
1152
+ var UNFUNDED_DEPOSIT_TRACKING_MS = 60 * 60 * 1e3;
1153
+ var SETTLEMENT_TRACKING_MS = 24 * 60 * 60 * 1e3;
1154
+ var shouldKeepTrackingDeposit = ({
1155
+ quoteDeadline,
1156
+ depositObservedAt,
1157
+ now
1158
+ }) => depositObservedAt ? now <= depositObservedAt + SETTLEMENT_TRACKING_MS : now <= quoteDeadline + UNFUNDED_DEPOSIT_TRACKING_MS;
1159
+
1160
+ // src/hooks/useDepositPolling.ts
1161
+ var POLL_INTERVAL_MS = 1e4;
1162
+ var isQuoteNotFound = (error) => error instanceof ApiError && error.code === "QUOTE_NOT_FOUND";
1163
+ var useDepositPolling = ({ apiClient }) => {
1164
+ const stateValue = SwapMachineCtx.useSelector((s) => s.value);
1165
+ const actorRef = SwapMachineCtx.useActorRef();
1166
+ const pollingRef = useRef2(false);
1167
+ useEffect2(() => {
1168
+ const snap = actorRef.getSnapshot();
1169
+ const isDepositTracking = snap.context.isDepositFlow && (snap.matches("awaiting_deposit") || snap.matches("deposit_expired") || snap.matches("polling_status"));
1170
+ if (!isDepositTracking) {
1171
+ pollingRef.current = false;
1172
+ return;
1173
+ }
1174
+ if (pollingRef.current) return;
1175
+ pollingRef.current = true;
1176
+ let stopped = false;
1177
+ let timer;
1178
+ const depositObservedAt = snap.context.depositObservedAt ?? void 0;
1179
+ const poll = async () => {
1180
+ if (stopped) return;
1181
+ const quoteId = actorRef.getSnapshot().context.quote?.quoteId;
1182
+ if (quoteId) {
1183
+ try {
1184
+ const response = await apiClient.getSwapStatus({ quoteId });
1185
+ if (stopped) return;
1186
+ const event = resolveDepositStatusEvent(response, !!depositObservedAt, Date.now());
1187
+ if (event) {
1188
+ actorRef.send(event);
1189
+ return;
1190
+ }
1191
+ } catch (error) {
1192
+ if (stopped) return;
1193
+ if (isQuoteNotFound(error)) {
1194
+ actorRef.send(
1195
+ depositObservedAt ? { type: "DEPOSIT_TRACKING_TIMEOUT" } : { type: "DEPOSIT_EXPIRED" }
1196
+ );
1197
+ return;
1198
+ }
1199
+ }
1200
+ }
1201
+ const { quote } = actorRef.getSnapshot().context;
1202
+ if (quote && !shouldKeepTrackingDeposit({
1203
+ quoteDeadline: quote.expiresAt,
1204
+ depositObservedAt,
1205
+ now: Date.now()
1206
+ })) {
1207
+ actorRef.send({ type: "DEPOSIT_TRACKING_TIMEOUT" });
1208
+ return;
1209
+ }
1210
+ timer = setTimeout(poll, POLL_INTERVAL_MS);
1211
+ };
1212
+ poll();
1213
+ return () => {
1214
+ stopped = true;
1215
+ pollingRef.current = false;
1216
+ clearTimeout(timer);
1217
+ };
1218
+ }, [stateValue]);
1219
+ };
1220
+
1221
+ // src/hooks/useEvmSigning.ts
1222
+ import { useAppKitAccount as useAppKitAccount2, useAppKitProvider as useAppKitProvider2 } from "@reown/appkit/react";
1223
+ import { useMemo as useMemo2 } from "react";
1224
+ import { createWalletClient, custom, getAddress, isAddress } from "viem";
1225
+ var useEvmSigning = () => {
1226
+ const { walletProvider } = useAppKitProvider2("eip155");
1227
+ const { address, isConnected } = useAppKitAccount2({ namespace: "eip155" });
1228
+ const checksummedAddress = useMemo2(() => {
1229
+ if (!address || !isAddress(address)) return void 0;
1230
+ return getAddress(address);
1231
+ }, [address]);
1232
+ const walletClient = useMemo2(() => {
1233
+ if (!walletProvider || !checksummedAddress) return void 0;
1234
+ return createWalletClient({
1235
+ account: checksummedAddress,
1236
+ transport: custom(walletProvider)
1237
+ });
1238
+ }, [walletProvider, checksummedAddress]);
1239
+ return useMemo2(
1240
+ () => ({
1241
+ walletClient,
1242
+ address: checksummedAddress,
1243
+ isConnected: !!(isConnected && checksummedAddress)
1244
+ }),
1245
+ [walletClient, checksummedAddress, isConnected]
1246
+ );
1247
+ };
1248
+
1249
+ // src/hooks/useSellFiatSync.ts
1250
+ import { useEffect as useEffect3 } from "react";
1251
+
1017
1252
  // src/utils/fiatConversion.ts
1018
1253
  import { BigAmount as BigAmount2, bn } from "@shapeshiftoss/utils";
1019
1254
  var fiatToCrypto = (fiat, price, precision) => {
@@ -1050,7 +1285,7 @@ var useSellFiatSync = (sellAssetUsdPrice) => {
1050
1285
  const sellAmountFiat = SwapMachineCtx.useSelector((s) => s.context.sellAmountFiat);
1051
1286
  const sellAmountBaseUnit = SwapMachineCtx.useSelector((s) => s.context.sellAmountBaseUnit);
1052
1287
  const sellPrecision = SwapMachineCtx.useSelector((s) => s.context.sellAsset.precision);
1053
- useEffect(() => {
1288
+ useEffect3(() => {
1054
1289
  const action = computeSellFiatSyncAction({
1055
1290
  isSellAmountFiat,
1056
1291
  sellAmountFiat,
@@ -1072,12 +1307,12 @@ var useSellFiatSync = (sellAssetUsdPrice) => {
1072
1307
  // src/hooks/useSolanaSigning.ts
1073
1308
  import { useAppKitProvider as useAppKitProvider3 } from "@reown/appkit/react";
1074
1309
  import { useAppKitConnection } from "@reown/appkit-adapter-solana/react";
1075
- import { useCallback as useCallback2, useMemo as useMemo3, useState as useState2 } from "react";
1310
+ import { useCallback as useCallback3, useMemo as useMemo3, useState as useState3 } from "react";
1076
1311
  var useSolanaSigning = () => {
1077
1312
  const { walletProvider } = useAppKitProvider3("solana");
1078
1313
  const provider = walletProvider;
1079
1314
  const { connection } = useAppKitConnection();
1080
- const [state, setState] = useState2({
1315
+ const [state, setState] = useState3({
1081
1316
  isLoading: false,
1082
1317
  error: void 0,
1083
1318
  signature: void 0
@@ -1097,7 +1332,7 @@ var useSolanaSigning = () => {
1097
1332
  return void 0;
1098
1333
  }
1099
1334
  }, [provider]);
1100
- const sendTransaction = useCallback2(
1335
+ const sendTransaction = useCallback3(
1101
1336
  async (params) => {
1102
1337
  if (!provider?.sendTransaction) {
1103
1338
  throw new Error("Solana wallet not connected");
@@ -1129,7 +1364,7 @@ var useSolanaSigning = () => {
1129
1364
  },
1130
1365
  [provider, connection]
1131
1366
  );
1132
- const signTransaction = useCallback2(
1367
+ const signTransaction = useCallback3(
1133
1368
  async (transaction) => {
1134
1369
  if (!provider?.signTransaction) {
1135
1370
  throw new Error("Solana wallet not connected or does not support signTransaction");
@@ -1151,7 +1386,7 @@ var useSolanaSigning = () => {
1151
1386
  },
1152
1387
  [provider]
1153
1388
  );
1154
- const signMessage = useCallback2(
1389
+ const signMessage = useCallback3(
1155
1390
  async (params) => {
1156
1391
  if (!provider?.signMessage) {
1157
1392
  throw new Error("Solana wallet not connected or does not support signMessage");
@@ -1178,14 +1413,14 @@ var useSolanaSigning = () => {
1178
1413
  },
1179
1414
  [provider]
1180
1415
  );
1181
- const reset = useCallback2(() => {
1416
+ const reset = useCallback3(() => {
1182
1417
  setState({
1183
1418
  isLoading: false,
1184
1419
  error: void 0,
1185
1420
  signature: void 0
1186
1421
  });
1187
1422
  }, []);
1188
- const checkTxStatus = useCallback2(
1423
+ const checkTxStatus = useCallback3(
1189
1424
  (signature) => {
1190
1425
  if (!connection) {
1191
1426
  return Promise.resolve({
@@ -1200,7 +1435,7 @@ var useSolanaSigning = () => {
1200
1435
  },
1201
1436
  [connection]
1202
1437
  );
1203
- const waitForConfirmation = useCallback2(
1438
+ const waitForConfirmation = useCallback3(
1204
1439
  (signature, commitment = "confirmed") => {
1205
1440
  if (!connection) {
1206
1441
  return Promise.resolve({
@@ -1246,24 +1481,18 @@ var useSolanaSigning = () => {
1246
1481
  };
1247
1482
 
1248
1483
  // src/hooks/useStatusPolling.ts
1249
- import { useEffect as useEffect2, useRef } from "react";
1250
- var POLL_INTERVAL_MS = 5e3;
1251
- var useStatusPolling = ({
1252
- apiClient,
1253
- onSwapSuccess,
1254
- onSwapError,
1255
- refetchSellBalance,
1256
- refetchBuyBalance
1257
- }) => {
1484
+ import { useEffect as useEffect4, useRef as useRef3 } from "react";
1485
+ var POLL_INTERVAL_MS2 = 5e3;
1486
+ var useStatusPolling = ({ apiClient }) => {
1258
1487
  const stateValue = SwapMachineCtx.useSelector((s) => s.value);
1259
1488
  const context = SwapMachineCtx.useSelector((s) => s.context);
1260
1489
  const actorRef = SwapMachineCtx.useActorRef();
1490
+ const pollingRef = useRef3(false);
1261
1491
  const { solana: solana3 } = useSwapWallet();
1262
1492
  const solanaConnection = solana3.connection;
1263
- const pollingRef = useRef(false);
1264
- useEffect2(() => {
1493
+ useEffect4(() => {
1265
1494
  const snap = actorRef.getSnapshot();
1266
- if (!snap.matches("polling_status")) {
1495
+ if (!snap.matches("polling_status") || snap.context.isDepositFlow) {
1267
1496
  pollingRef.current = false;
1268
1497
  return;
1269
1498
  }
@@ -1316,7 +1545,7 @@ var useStatusPolling = ({
1316
1545
  actorRef.send({ type: "STATUS_FAILED", error: result.error ?? "Transaction failed" });
1317
1546
  return;
1318
1547
  }
1319
- setTimeout(poll, POLL_INTERVAL_MS);
1548
+ setTimeout(poll, POLL_INTERVAL_MS2);
1320
1549
  } catch (err) {
1321
1550
  if (stopped) return;
1322
1551
  const errorMessage = err instanceof Error ? err.message : "Unknown polling error";
@@ -1329,36 +1558,10 @@ var useStatusPolling = ({
1329
1558
  pollingRef.current = false;
1330
1559
  };
1331
1560
  }, [stateValue]);
1332
- const completionRef = useRef(false);
1333
- useEffect2(() => {
1334
- const snap = actorRef.getSnapshot();
1335
- if (!snap.matches("complete")) {
1336
- completionRef.current = false;
1337
- return;
1338
- }
1339
- if (completionRef.current) return;
1340
- completionRef.current = true;
1341
- if (context.txHash) {
1342
- onSwapSuccess?.(context.txHash);
1343
- }
1344
- refetchSellBalance?.();
1345
- refetchBuyBalance?.();
1346
- }, [stateValue]);
1347
- const errorRef = useRef(false);
1348
- useEffect2(() => {
1349
- const snap = actorRef.getSnapshot();
1350
- if (!snap.matches("error")) {
1351
- errorRef.current = false;
1352
- return;
1353
- }
1354
- if (errorRef.current) return;
1355
- errorRef.current = true;
1356
- onSwapError?.(new Error(context.error ?? "Unknown error"));
1357
- }, [stateValue]);
1358
1561
  };
1359
1562
 
1360
1563
  // src/hooks/useSwapApproval.ts
1361
- import { useEffect as useEffect3, useRef as useRef2 } from "react";
1564
+ import { useEffect as useEffect5, useRef as useRef4 } from "react";
1362
1565
  import { createPublicClient as createPublicClient2, http as http2 } from "viem";
1363
1566
 
1364
1567
  // src/constants/chains.ts
@@ -1461,8 +1664,8 @@ var useSwapApproval = () => {
1461
1664
  const actorRef = SwapMachineCtx.useActorRef();
1462
1665
  const { evm } = useSwapWallet();
1463
1666
  const { walletClient, address: walletAddress } = evm;
1464
- const approvingRef = useRef2(false);
1465
- useEffect3(() => {
1667
+ const approvingRef = useRef4(false);
1668
+ useEffect5(() => {
1466
1669
  if (stateValue !== "approving" || approvingRef.current) return;
1467
1670
  approvingRef.current = true;
1468
1671
  const executeApproval = async () => {
@@ -1540,10 +1743,50 @@ var useSwapApproval = () => {
1540
1743
  }, [stateValue]);
1541
1744
  };
1542
1745
 
1746
+ // src/hooks/useSwapCallbacks.ts
1747
+ import { useEffect as useEffect6, useRef as useRef5 } from "react";
1748
+ var useSwapCallbacks = ({
1749
+ onSwapSuccess,
1750
+ onSwapError,
1751
+ refetchSellBalance,
1752
+ refetchBuyBalance
1753
+ }) => {
1754
+ const stateValue = SwapMachineCtx.useSelector((s) => s.value);
1755
+ const actorRef = SwapMachineCtx.useActorRef();
1756
+ const completionRef = useRef5(false);
1757
+ useEffect6(() => {
1758
+ const snap = actorRef.getSnapshot();
1759
+ if (!snap.matches("complete")) {
1760
+ completionRef.current = false;
1761
+ return;
1762
+ }
1763
+ if (completionRef.current) return;
1764
+ completionRef.current = true;
1765
+ if (snap.context.txHash) onSwapSuccess?.(snap.context.txHash);
1766
+ refetchSellBalance?.();
1767
+ refetchBuyBalance?.();
1768
+ }, [stateValue]);
1769
+ const errorRef = useRef5(false);
1770
+ useEffect6(() => {
1771
+ const snap = actorRef.getSnapshot();
1772
+ if (!snap.matches("error")) {
1773
+ errorRef.current = false;
1774
+ return;
1775
+ }
1776
+ if (errorRef.current) return;
1777
+ errorRef.current = true;
1778
+ onSwapError?.(new Error(snap.context.error ?? "Unknown error"));
1779
+ }, [stateValue]);
1780
+ };
1781
+
1543
1782
  // src/hooks/useSwapDisplayValues.ts
1544
1783
  import { bn as bn3 } from "@shapeshiftoss/utils";
1545
1784
  import { useMemo as useMemo5 } from "react";
1546
1785
 
1786
+ // src/utils/ratesPolling.ts
1787
+ var RATES_CONSUMING_STATES = /* @__PURE__ */ new Set(["idle", "input", "quoting", "error", "deposit_expired"]);
1788
+ var shouldPollRates = (stateValue) => typeof stateValue === "string" && RATES_CONSUMING_STATES.has(stateValue);
1789
+
1547
1790
  // src/hooks/useAssets.ts
1548
1791
  import { ASSET_NAMESPACE, fromAssetId } from "@shapeshiftoss/caip";
1549
1792
  import { useQuery } from "@tanstack/react-query";
@@ -1663,12 +1906,12 @@ var useAssetSearch = (query, chainId) => {
1663
1906
 
1664
1907
  // src/hooks/useBalances.ts
1665
1908
  import { useAppKitConnection as useAppKitConnection2 } from "@reown/appkit-adapter-solana/react";
1666
- import { ASSET_NAMESPACE as ASSET_NAMESPACE2, CHAIN_NAMESPACE as CHAIN_NAMESPACE2, fromAssetId as fromAssetId2 } from "@shapeshiftoss/caip";
1909
+ import { ASSET_NAMESPACE as ASSET_NAMESPACE2, CHAIN_NAMESPACE as CHAIN_NAMESPACE3, fromAssetId as fromAssetId2 } from "@shapeshiftoss/caip";
1667
1910
  import { Connection, PublicKey } from "@solana/web3.js";
1668
1911
  import { useQueries, useQueryClient } from "@tanstack/react-query";
1669
1912
  import { getBalance, readContract } from "@wagmi/core";
1670
1913
  import PQueue from "p-queue";
1671
- import { useCallback as useCallback3, useMemo as useMemo4 } from "react";
1914
+ import { useCallback as useCallback4, useMemo as useMemo4 } from "react";
1672
1915
  import { erc20Abi as erc20Abi2 } from "viem";
1673
1916
  import { useConfig } from "wagmi";
1674
1917
  var CONCURRENCY_LIMIT = 5;
@@ -1685,7 +1928,7 @@ var parseAssetIdMultiChain = (assetId) => {
1685
1928
  const { chainNamespace, chainReference, assetNamespace, assetReference } = fromAssetId2(assetId);
1686
1929
  const chainId = assetId.split("/")[0];
1687
1930
  const chainType = isWidgetExecutableEvmChainId(chainId) ? "evm" : isWidgetExecutableUtxoChainId(chainId) ? "utxo" : isWidgetExecutableSolanaChainId(chainId) ? "solana" : void 0;
1688
- if (chainType === "evm" && chainNamespace === CHAIN_NAMESPACE2.Evm) {
1931
+ if (chainType === "evm" && chainNamespace === CHAIN_NAMESPACE3.Evm) {
1689
1932
  const evmChainId = Number(chainReference);
1690
1933
  if (assetNamespace === ASSET_NAMESPACE2.erc20) {
1691
1934
  return {
@@ -1696,10 +1939,10 @@ var parseAssetIdMultiChain = (assetId) => {
1696
1939
  }
1697
1940
  return { chainType: "evm", evmChainId };
1698
1941
  }
1699
- if (chainType === "utxo" && chainNamespace === CHAIN_NAMESPACE2.Utxo) {
1942
+ if (chainType === "utxo" && chainNamespace === CHAIN_NAMESPACE3.Utxo) {
1700
1943
  return { chainType: "utxo", chainReference };
1701
1944
  }
1702
- if (chainType === "solana" && chainNamespace === CHAIN_NAMESPACE2.Solana) {
1945
+ if (chainType === "solana" && chainNamespace === CHAIN_NAMESPACE3.Solana) {
1703
1946
  if (assetNamespace === ASSET_NAMESPACE2.splToken) {
1704
1947
  return { chainType: "solana", tokenAddress: assetReference };
1705
1948
  }
@@ -2112,7 +2355,7 @@ var useMultiChainBalances = (evmAddress, utxoAddress, solanaAddress, assetIds, a
2112
2355
  });
2113
2356
  return loading;
2114
2357
  }, [evmQueries, utxoQueries, solanaQueries, groupedAssets]);
2115
- const refetch = useCallback3(() => {
2358
+ const refetch = useCallback4(() => {
2116
2359
  queryClient2.invalidateQueries({
2117
2360
  predicate: (query) => {
2118
2361
  const key = query.queryKey;
@@ -2120,7 +2363,7 @@ var useMultiChainBalances = (evmAddress, utxoAddress, solanaAddress, assetIds, a
2120
2363
  }
2121
2364
  });
2122
2365
  }, [queryClient2]);
2123
- const refetchSpecific = useCallback3(
2366
+ const refetchSpecific = useCallback4(
2124
2367
  (targetAssetIds) => {
2125
2368
  queryClient2.invalidateQueries({
2126
2369
  predicate: (query) => {
@@ -2355,15 +2598,8 @@ var useSwapDisplayValues = ({
2355
2598
  ratesRefetchInterval
2356
2599
  }) => {
2357
2600
  const context = SwapMachineCtx.useSelector((s) => s.context);
2358
- const {
2359
- sellAsset,
2360
- buyAsset,
2361
- buyAmountBaseUnit,
2362
- isSellAssetEvm,
2363
- isSellAssetUtxo,
2364
- isSellAssetSolana,
2365
- selectedRate
2366
- } = context;
2601
+ const isPollingRates = SwapMachineCtx.useSelector((s) => shouldPollRates(s.value));
2602
+ const { sellAsset, buyAsset, buyAmountBaseUnit, selectedRate } = context;
2367
2603
  const { receiveAddress, isReceiveAddressBlocked, evm, bitcoin: bitcoin3, solana: solana3 } = useSwapWallet();
2368
2604
  const evmAddress = evm.address;
2369
2605
  const bitcoinAddress = bitcoin3.address;
@@ -2383,7 +2619,7 @@ var useSwapDisplayValues = ({
2383
2619
  allowedSwapperNames,
2384
2620
  refetchInterval: ratesRefetchInterval,
2385
2621
  // Rates need no destination, but a locked one the buy chain rejects can never be quoted
2386
- enabled: !!amountBaseUnit && amountBaseUnit !== "0" && !isReceiveAddressBlocked && (isSellAssetEvm || isSellAssetUtxo || isSellAssetSolana)
2622
+ enabled: isPollingRates && !!amountBaseUnit && amountBaseUnit !== "0" && !isReceiveAddressBlocked
2387
2623
  });
2388
2624
  const {
2389
2625
  data: sellAssetBalance,
@@ -2515,7 +2751,7 @@ var useSwapDisplayValues = ({
2515
2751
  };
2516
2752
 
2517
2753
  // src/hooks/useSwapExecution.ts
2518
- import { useEffect as useEffect4, useRef as useRef3 } from "react";
2754
+ import { useEffect as useEffect7, useRef as useRef6 } from "react";
2519
2755
  import { getAddress as getAddress2 } from "viem";
2520
2756
  var executeEvm = async (txData, walletClient, walletAddress) => {
2521
2757
  if (!walletClient || !walletAddress) throw new Error("No wallet connected");
@@ -2617,8 +2853,8 @@ var useSwapExecution = () => {
2617
2853
  const actorRef = SwapMachineCtx.useActorRef();
2618
2854
  const { evm, bitcoin: bitcoin3, solana: solana3 } = useSwapWallet();
2619
2855
  const { walletClient, address: walletAddress } = evm;
2620
- const executingRef = useRef3(false);
2621
- useEffect4(() => {
2856
+ const executingRef = useRef6(false);
2857
+ useEffect7(() => {
2622
2858
  if (stateValue !== "executing" || executingRef.current) return;
2623
2859
  executingRef.current = true;
2624
2860
  const executeSwap = async () => {
@@ -2684,7 +2920,7 @@ var useSwapExecution = () => {
2684
2920
 
2685
2921
  // src/hooks/useSwapHandlers.ts
2686
2922
  import { useAppKit } from "@reown/appkit/react";
2687
- import { useCallback as useCallback4 } from "react";
2923
+ import { useCallback as useCallback5 } from "react";
2688
2924
 
2689
2925
  // src/utils/redirect.ts
2690
2926
  var SHAPESHIFT_APP_URL = "https://app.shapeshift.com";
@@ -2709,25 +2945,25 @@ var useSwapHandlers = ({
2709
2945
  const actorRef = SwapMachineCtx.useActorRef();
2710
2946
  const { evm, bitcoin: bitcoin3, solana: solana3 } = useSwapWallet();
2711
2947
  const { open: openAppKit } = useAppKit();
2712
- const handleSwapTokens = useCallback4(() => {
2948
+ const handleSwapTokens = useCallback5(() => {
2713
2949
  const snap = actorRef.getSnapshot();
2714
2950
  actorRef.send({ type: "SET_SELL_ASSET", asset: snap.context.buyAsset });
2715
2951
  actorRef.send({ type: "SET_BUY_ASSET", asset: snap.context.sellAsset });
2716
2952
  actorRef.send({ type: "SET_SELL_AMOUNT", amount: "", amountBaseUnit: void 0, fiatValue: "" });
2717
2953
  }, [actorRef]);
2718
- const handleSellAssetSelect = useCallback4(
2954
+ const handleSellAssetSelect = useCallback5(
2719
2955
  (asset) => {
2720
2956
  actorRef.send({ type: "SET_SELL_ASSET", asset });
2721
2957
  },
2722
2958
  [actorRef]
2723
2959
  );
2724
- const handleBuyAssetSelect = useCallback4(
2960
+ const handleBuyAssetSelect = useCallback5(
2725
2961
  (asset) => {
2726
2962
  actorRef.send({ type: "SET_BUY_ASSET", asset });
2727
2963
  },
2728
2964
  [actorRef]
2729
2965
  );
2730
- const handleSellAmountChange = useCallback4(
2966
+ const handleSellAmountChange = useCallback5(
2731
2967
  (value, sellAssetUsdPrice) => {
2732
2968
  const snap = actorRef.getSnapshot();
2733
2969
  const { sellAsset, isSellAmountFiat } = snap.context;
@@ -2745,7 +2981,7 @@ var useSwapHandlers = ({
2745
2981
  },
2746
2982
  [actorRef]
2747
2983
  );
2748
- const handleBuyAmountChange = useCallback4(
2984
+ const handleBuyAmountChange = useCallback5(
2749
2985
  (value) => {
2750
2986
  const { buyAsset } = actorRef.getSnapshot().context;
2751
2987
  const amountBaseUnit = value ? parseAmount(value, buyAsset.precision) : void 0;
@@ -2753,7 +2989,7 @@ var useSwapHandlers = ({
2753
2989
  },
2754
2990
  [actorRef]
2755
2991
  );
2756
- const handleToggleSellFiat = useCallback4(
2992
+ const handleToggleSellFiat = useCallback5(
2757
2993
  (sellAssetUsdPrice) => {
2758
2994
  if (!sellAssetUsdPrice) return;
2759
2995
  const snap = actorRef.getSnapshot();
@@ -2777,19 +3013,19 @@ var useSwapHandlers = ({
2777
3013
  },
2778
3014
  [actorRef]
2779
3015
  );
2780
- const handleSelectRate = useCallback4(
3016
+ const handleSelectRate = useCallback5(
2781
3017
  (rate) => {
2782
3018
  actorRef.send({ type: "SELECT_RATE", rate });
2783
3019
  },
2784
3020
  [actorRef]
2785
3021
  );
2786
- const handleSlippageChange = useCallback4(
3022
+ const handleSlippageChange = useCallback5(
2787
3023
  (value) => {
2788
3024
  actorRef.send({ type: "SET_SLIPPAGE", slippage: value });
2789
3025
  },
2790
3026
  [actorRef]
2791
3027
  );
2792
- const redirectToShapeShift = useCallback4(() => {
3028
+ const redirectToShapeShift = useCallback5(() => {
2793
3029
  const snap = actorRef.getSnapshot();
2794
3030
  const sellAmountBaseUnit = snap.context.sellAmount ? parseAmount(snap.context.sellAmount, snap.context.sellAsset.precision) : void 0;
2795
3031
  const url = buildShapeShiftTradeUrl({
@@ -2800,42 +3036,45 @@ var useSwapHandlers = ({
2800
3036
  });
2801
3037
  window.open(url, "_blank", "noopener,noreferrer");
2802
3038
  }, [actorRef, partnerCode]);
2803
- const handleButtonClick = useCallback4(() => {
2804
- const snap = actorRef.getSnapshot();
2805
- if (snap.context.isSellAssetUtxo && !bitcoin3.isConnected) {
2806
- openAppKit({ namespace: "bip122" });
2807
- return;
2808
- }
2809
- if (snap.context.isSellAssetSolana && !solana3.isConnected) {
2810
- openAppKit({ namespace: "solana" });
2811
- return;
2812
- }
2813
- if (snap.context.isSellAssetEvm && !evm.isConnected) {
2814
- openAppKit({ namespace: "eip155" });
2815
- return;
2816
- }
2817
- if (!snap.context.isSellAssetEvm && !snap.context.isSellAssetUtxo && !snap.context.isSellAssetSolana) {
2818
- if (!allowShapeshiftRedirect) return;
2819
- const sellAmountBaseUnit = snap.context.sellAmount ? parseAmount(snap.context.sellAmount, snap.context.sellAsset.precision) : void 0;
2820
- const url = buildShapeShiftTradeUrl({
2821
- sellAssetId: snap.context.sellAsset.assetId,
2822
- buyAssetId: snap.context.buyAsset.assetId,
2823
- sellAmountBaseUnit,
2824
- partnerCode
2825
- });
2826
- window.open(url, "_blank", "noopener,noreferrer");
2827
- return;
2828
- }
2829
- actorRef.send({ type: "FETCH_QUOTE" });
2830
- }, [
2831
- actorRef,
2832
- bitcoin3.isConnected,
2833
- solana3.isConnected,
2834
- evm.isConnected,
2835
- openAppKit,
2836
- partnerCode,
2837
- allowShapeshiftRedirect
2838
- ]);
3039
+ const handleButtonClick = useCallback5(
3040
+ (action) => {
3041
+ if (action === "deposit") {
3042
+ actorRef.send({ type: "FETCH_QUOTE", isDepositFlow: true });
3043
+ return;
3044
+ }
3045
+ if (action === "quote") {
3046
+ actorRef.send({ type: "FETCH_QUOTE" });
3047
+ return;
3048
+ }
3049
+ if (action === "redirect") {
3050
+ if (!allowShapeshiftRedirect) return;
3051
+ redirectToShapeShift();
3052
+ return;
3053
+ }
3054
+ if (action !== "connect") return;
3055
+ const snap = actorRef.getSnapshot();
3056
+ if (snap.context.isSellAssetUtxo && !bitcoin3.isConnected) {
3057
+ openAppKit({ namespace: "bip122" });
3058
+ return;
3059
+ }
3060
+ if (snap.context.isSellAssetSolana && !solana3.isConnected) {
3061
+ openAppKit({ namespace: "solana" });
3062
+ return;
3063
+ }
3064
+ if (snap.context.isSellAssetEvm && !evm.isConnected) {
3065
+ openAppKit({ namespace: "eip155" });
3066
+ }
3067
+ },
3068
+ [
3069
+ actorRef,
3070
+ bitcoin3.isConnected,
3071
+ solana3.isConnected,
3072
+ evm.isConnected,
3073
+ openAppKit,
3074
+ allowShapeshiftRedirect,
3075
+ redirectToShapeShift
3076
+ ]
3077
+ );
2839
3078
  return {
2840
3079
  handleSwapTokens,
2841
3080
  handleSellAssetSelect,
@@ -2851,21 +3090,31 @@ var useSwapHandlers = ({
2851
3090
  };
2852
3091
 
2853
3092
  // src/hooks/useSwapQuoting.ts
2854
- import { useEffect as useEffect5, useRef as useRef4 } from "react";
3093
+ import { useEffect as useEffect8, useRef as useRef7 } from "react";
3094
+
3095
+ // src/utils/depositFlow.ts
3096
+ var isExternalPaymentRate = (rate) => rate.supportsExternalPayment === true;
3097
+ var shouldUseDepositFlow = ({
3098
+ rate,
3099
+ hasWalletForSellChain
3100
+ }) => !hasWalletForSellChain && !!rate && isExternalPaymentRate(rate);
3101
+ var pickDepositRate = (rates, swapperName) => rates?.find((rate) => rate.swapperName === swapperName && isExternalPaymentRate(rate)) ?? rates?.find(isExternalPaymentRate);
3102
+
3103
+ // src/hooks/useSwapQuoting.ts
2855
3104
  var useSwapQuoting = ({ apiClient, rates, sellAssetBalance }) => {
2856
3105
  const stateValue = SwapMachineCtx.useSelector((s) => s.value);
2857
3106
  const context = SwapMachineCtx.useSelector((s) => s.context);
2858
3107
  const actorRef = SwapMachineCtx.useActorRef();
2859
3108
  const { sendAddress, receiveAddress } = useSwapWallet();
2860
- const quotingRef = useRef4(false);
2861
- useEffect5(() => {
3109
+ const quotingRef = useRef7(false);
3110
+ useEffect8(() => {
2862
3111
  const snap = actorRef.getSnapshot();
2863
3112
  if (!snap.matches("quoting") || quotingRef.current) return;
2864
3113
  quotingRef.current = true;
2865
3114
  const fetchQuote = async () => {
2866
3115
  try {
2867
3116
  const isExactOutput2 = !!context.buyAmountBaseUnit;
2868
- const rateToUse = context.selectedRate ?? rates?.[0];
3117
+ const rateToUse = context.selectedRate ?? (context.isDepositFlow ? pickDepositRate(rates, context.quote?.swapperName) : rates?.[0]);
2869
3118
  const sellAmountBaseUnit = isExactOutput2 ? rateToUse?.sellAmountCryptoBaseUnit : context.sellAmountBaseUnit;
2870
3119
  if (sellAssetBalance?.balance && sellAmountBaseUnit) {
2871
3120
  const balanceBigInt = BigInt(sellAssetBalance.balance);
@@ -2887,11 +3136,13 @@ var useSwapQuoting = ({ apiClient, rates, sellAssetBalance }) => {
2887
3136
  return;
2888
3137
  }
2889
3138
  if (!sendAddress) {
2890
- actorRef.send({ type: "QUOTE_ERROR", error: "No wallet address available" });
3139
+ actorRef.send({
3140
+ type: "QUOTE_ERROR",
3141
+ error: context.isDepositFlow ? "No refund address available" : "No wallet address available"
3142
+ });
2891
3143
  return;
2892
3144
  }
2893
- const resolvedReceiveAddress = receiveAddress || sendAddress;
2894
- if (!resolvedReceiveAddress) {
3145
+ if (!receiveAddress) {
2895
3146
  actorRef.send({ type: "QUOTE_ERROR", error: "No receive address available" });
2896
3147
  return;
2897
3148
  }
@@ -2900,7 +3151,7 @@ var useSwapQuoting = ({ apiClient, rates, sellAssetBalance }) => {
2900
3151
  buyAssetId: context.buyAsset.assetId,
2901
3152
  ...isExactOutput2 ? { buyAmountCryptoBaseUnit: amountBaseUnit } : { sellAmountCryptoBaseUnit: amountBaseUnit },
2902
3153
  sendAddress,
2903
- receiveAddress: resolvedReceiveAddress,
3154
+ receiveAddress,
2904
3155
  swapperName: rateToUse.swapperName,
2905
3156
  slippageTolerancePercentageDecimal: slippageDecimal
2906
3157
  });
@@ -2917,25 +3168,31 @@ var useSwapQuoting = ({ apiClient, rates, sellAssetBalance }) => {
2917
3168
  };
2918
3169
 
2919
3170
  // src/utils/addressValidation.ts
2920
- import { CHAIN_NAMESPACE as CHAIN_NAMESPACE3, CHAIN_REFERENCE, fromChainId as fromChainId2 } from "@shapeshiftoss/caip";
3171
+ import { CHAIN_NAMESPACE as CHAIN_NAMESPACE4, CHAIN_REFERENCE, fromChainId as fromChainId3 } from "@shapeshiftoss/caip";
2921
3172
  import { PublicKey as PublicKey2 } from "@solana/web3.js";
2922
3173
  import { bech32, bech32m } from "bech32";
2923
3174
  import bs58check from "bs58check";
2924
3175
  import { decode as decodeCashAddr } from "cashaddrjs";
2925
3176
  import { isAddress as isAddress2 } from "viem";
2926
3177
  var VERSION_BYTES = {
2927
- bitcoinP2PKH: 0,
2928
- bitcoinP2SH: 5,
2929
- litecoinP2PKH: 48,
2930
- litecoinP2SH: 50,
2931
- litecoinP2SHLegacy: 5,
2932
- dogecoinP2PKH: 30,
2933
- dogecoinP2SH: 22
2934
- };
2935
- var isValidBase58Check = (address, allowedVersionBytes) => {
3178
+ bitcoinP2PKH: [0],
3179
+ bitcoinP2SH: [5],
3180
+ litecoinP2PKH: [48],
3181
+ litecoinP2SH: [50],
3182
+ litecoinP2SHLegacy: [5],
3183
+ dogecoinP2PKH: [30],
3184
+ dogecoinP2SH: [22],
3185
+ zcashP2PKH: [28, 184],
3186
+ zcashP2SH: [28, 189],
3187
+ tron: [65]
3188
+ };
3189
+ var HASH160_LENGTH = 20;
3190
+ var isValidBase58Check = (address, versionPrefixes) => {
2936
3191
  try {
2937
3192
  const decoded = bs58check.decode(address);
2938
- return allowedVersionBytes.includes(decoded[0]);
3193
+ return versionPrefixes.some(
3194
+ (prefix) => decoded.length === prefix.length + HASH160_LENGTH && prefix.every((byte, index) => decoded[index] === byte)
3195
+ );
2939
3196
  } catch {
2940
3197
  return false;
2941
3198
  }
@@ -2964,8 +3221,12 @@ var isValidSegwit = (address, expectedHrp) => {
2964
3221
  if (prefix !== expectedHrp) continue;
2965
3222
  if (words.length === 0) continue;
2966
3223
  const witnessVersion = words[0];
3224
+ if (witnessVersion > 16) continue;
2967
3225
  if (witnessVersion === 0 && codec !== bech32) continue;
2968
3226
  if (witnessVersion >= 1 && codec !== bech32m) continue;
3227
+ const program = codec.fromWords(words.slice(1));
3228
+ if (program.length < 2 || program.length > 40) continue;
3229
+ if (witnessVersion === 0 && program.length !== 20 && program.length !== 32) continue;
2969
3230
  return true;
2970
3231
  } catch {
2971
3232
  }
@@ -2980,7 +3241,46 @@ var isValidLitecoinAddress = (address) => isValidBase58Check(address, [
2980
3241
  VERSION_BYTES.litecoinP2SHLegacy
2981
3242
  ]) || isValidSegwit(address, "ltc");
2982
3243
  var isValidDogecoinAddress = (address) => isValidBase58Check(address, [VERSION_BYTES.dogecoinP2PKH, VERSION_BYTES.dogecoinP2SH]);
2983
- var UTXO_VALIDATORS = {
3244
+ var isValidZcashAddress = (address) => isValidBase58Check(address, [VERSION_BYTES.zcashP2PKH, VERSION_BYTES.zcashP2SH]);
3245
+ var isValidTronAddress = (address) => isValidBase58Check(address, [VERSION_BYTES.tron]);
3246
+ var crc16Xmodem = (data) => {
3247
+ let crc = 0;
3248
+ for (const byte of data) {
3249
+ crc ^= byte << 8;
3250
+ for (let bit = 0; bit < 8; bit++) {
3251
+ crc = crc & 32768 ? (crc << 1 ^ 4129) & 65535 : crc << 1 & 65535;
3252
+ }
3253
+ }
3254
+ return crc;
3255
+ };
3256
+ var TON_TAG_BOUNCEABLE = 17;
3257
+ var TON_TAG_NON_BOUNCEABLE = 81;
3258
+ var isValidTonAddress = (address) => {
3259
+ if (/^(0|-1):[0-9a-fA-F]{64}$/.test(address)) return true;
3260
+ if (!/^[A-Za-z0-9+/_-]{48}$/.test(address)) return false;
3261
+ try {
3262
+ const base64 = address.replace(/-/g, "+").replace(/_/g, "/");
3263
+ const bytes = Uint8Array.from(atob(base64), (character) => character.charCodeAt(0));
3264
+ if (bytes.length !== 36) return false;
3265
+ if (bytes[0] !== TON_TAG_BOUNCEABLE && bytes[0] !== TON_TAG_NON_BOUNCEABLE) return false;
3266
+ if (bytes[1] !== 0 && bytes[1] !== 255) return false;
3267
+ return crc16Xmodem(bytes.subarray(0, 34)) === (bytes[34] << 8 | bytes[35]);
3268
+ } catch {
3269
+ return false;
3270
+ }
3271
+ };
3272
+ var isValidSuiAddress = (address) => /^0x[0-9a-fA-F]{64}$/.test(address);
3273
+ var STARKNET_ADDRESS_BOUND = 2n ** 251n - 256n;
3274
+ var isValidStarknetAddress = (address) => {
3275
+ if (!/^0x[0-9a-fA-F]{1,64}$/.test(address)) return false;
3276
+ const value = BigInt(address);
3277
+ return value > 0n && value < STARKNET_ADDRESS_BOUND;
3278
+ };
3279
+ var isValidNearAddress = (address) => {
3280
+ if (/^[0-9a-f]{64}$/.test(address)) return true;
3281
+ return /^(?=.{2,64}$)[a-z0-9]+([-_.][a-z0-9]+)*$/.test(address);
3282
+ };
3283
+ var UTXO_VALIDATORS = {
2984
3284
  [CHAIN_REFERENCE.BitcoinMainnet]: {
2985
3285
  check: isValidBitcoinAddress,
2986
3286
  label: "Bitcoin",
@@ -3000,6 +3300,11 @@ var UTXO_VALIDATORS = {
3000
3300
  check: isValidDogecoinAddress,
3001
3301
  label: "Dogecoin",
3002
3302
  hint: "D..."
3303
+ },
3304
+ [CHAIN_REFERENCE.ZcashMainnet]: {
3305
+ check: isValidZcashAddress,
3306
+ label: "Zcash",
3307
+ hint: "t1... or t3..."
3003
3308
  }
3004
3309
  };
3005
3310
  var COSMOS_SDK_VALIDATORS = {
@@ -3010,22 +3315,22 @@ var COSMOS_SDK_VALIDATORS = {
3010
3315
  var validateAddress = (address, chainId) => {
3011
3316
  if (!address) return { valid: false, error: "Address is required" };
3012
3317
  const invalid = (label) => ({ valid: false, error: `Invalid ${label} address` });
3013
- const { chainNamespace, chainReference } = fromChainId2(chainId);
3318
+ const { chainNamespace, chainReference } = fromChainId3(chainId);
3014
3319
  switch (chainNamespace) {
3015
- case CHAIN_NAMESPACE3.Evm: {
3320
+ case CHAIN_NAMESPACE4.Evm: {
3016
3321
  return isAddress2(address, { strict: false }) ? { valid: true } : invalid("EVM");
3017
3322
  }
3018
- case CHAIN_NAMESPACE3.Utxo: {
3323
+ case CHAIN_NAMESPACE4.Utxo: {
3019
3324
  const utxo = UTXO_VALIDATORS[chainReference];
3020
3325
  if (!utxo) return { valid: false, error: "Unsupported UTXO chain" };
3021
3326
  return utxo.check(address) ? { valid: true } : invalid(utxo.label);
3022
3327
  }
3023
- case CHAIN_NAMESPACE3.CosmosSdk: {
3328
+ case CHAIN_NAMESPACE4.CosmosSdk: {
3024
3329
  const cosmosSdk = COSMOS_SDK_VALIDATORS[chainReference];
3025
3330
  if (!cosmosSdk) return { valid: false, error: "Unsupported CosmosSdk chain" };
3026
3331
  return isValidBech32(address, cosmosSdk.hrp) ? { valid: true } : invalid(cosmosSdk.label);
3027
3332
  }
3028
- case CHAIN_NAMESPACE3.Solana: {
3333
+ case CHAIN_NAMESPACE4.Solana: {
3029
3334
  try {
3030
3335
  new PublicKey2(address);
3031
3336
  return { valid: true };
@@ -3033,39 +3338,122 @@ var validateAddress = (address, chainId) => {
3033
3338
  return invalid("Solana");
3034
3339
  }
3035
3340
  }
3341
+ case CHAIN_NAMESPACE4.Tron:
3342
+ return isValidTronAddress(address) ? { valid: true } : invalid("Tron");
3343
+ case CHAIN_NAMESPACE4.Sui:
3344
+ return isValidSuiAddress(address) ? { valid: true } : invalid("Sui");
3345
+ case CHAIN_NAMESPACE4.Ton:
3346
+ return isValidTonAddress(address) ? { valid: true } : invalid("TON");
3347
+ case CHAIN_NAMESPACE4.Near: {
3348
+ if (isValidNearAddress(address)) return { valid: true };
3349
+ if (isValidNearAddress(address.toLowerCase())) {
3350
+ return { valid: false, error: "Invalid NEAR address - must be lowercase" };
3351
+ }
3352
+ return invalid("NEAR");
3353
+ }
3354
+ case CHAIN_NAMESPACE4.Starknet:
3355
+ return isValidStarknetAddress(address) ? { valid: true } : invalid("Starknet");
3036
3356
  default:
3037
3357
  return { valid: false, error: "Unsupported chain type" };
3038
3358
  }
3039
3359
  };
3040
3360
  var getAddressFormatHint = (chainId) => {
3041
- const { chainNamespace, chainReference } = fromChainId2(chainId);
3361
+ const { chainNamespace, chainReference } = fromChainId3(chainId);
3042
3362
  switch (chainNamespace) {
3043
- case CHAIN_NAMESPACE3.Evm:
3363
+ case CHAIN_NAMESPACE4.Evm:
3044
3364
  return "0x...";
3045
- case CHAIN_NAMESPACE3.Utxo:
3365
+ case CHAIN_NAMESPACE4.Utxo:
3046
3366
  return UTXO_VALIDATORS[chainReference]?.hint ?? "Enter address";
3047
- case CHAIN_NAMESPACE3.CosmosSdk: {
3367
+ case CHAIN_NAMESPACE4.CosmosSdk: {
3048
3368
  const cosmosSdk = COSMOS_SDK_VALIDATORS[chainReference];
3049
3369
  return cosmosSdk ? `${cosmosSdk.hrp}1...` : "Enter address";
3050
3370
  }
3051
- case CHAIN_NAMESPACE3.Solana:
3371
+ case CHAIN_NAMESPACE4.Solana:
3052
3372
  return "Enter Solana address";
3373
+ case CHAIN_NAMESPACE4.Tron:
3374
+ return "T...";
3375
+ case CHAIN_NAMESPACE4.Ton:
3376
+ return "UQ... or EQ...";
3377
+ case CHAIN_NAMESPACE4.Sui:
3378
+ case CHAIN_NAMESPACE4.Starknet:
3379
+ return "0x...";
3380
+ case CHAIN_NAMESPACE4.Near:
3381
+ return "name.near or 64 hex chars";
3053
3382
  default:
3054
3383
  return "Enter address";
3055
3384
  }
3056
3385
  };
3057
3386
 
3387
+ // src/utils/pendingDeposit.ts
3388
+ var STORAGE_KEY = "ssw:pendingDeposit";
3389
+ var isRestorableAsset = (value) => {
3390
+ const asset = value;
3391
+ return typeof asset?.chainId === "string" && typeof asset.precision === "number";
3392
+ };
3393
+ var isPendingDeposit = (value) => {
3394
+ const candidate = value;
3395
+ const quote = candidate?.quote;
3396
+ return !!quote?.depositAddress && typeof quote.quoteId === "string" && typeof quote.expiresAt === "number" && typeof quote.sellAmountCryptoBaseUnit === "string" && typeof quote.buyAmountAfterFeesCryptoBaseUnit === "string" && isRestorableAsset(quote.sellAsset) && isRestorableAsset(quote.buyAsset) && typeof candidate?.refundAddress === "string" && typeof candidate.receiveAddress === "string" && // A funded deposit without its observation time has no settlement window to resume
3397
+ (!candidate.txHash || typeof candidate.depositObservedAt === "number");
3398
+ };
3399
+ var clearPendingDeposit = () => {
3400
+ try {
3401
+ localStorage.removeItem(STORAGE_KEY);
3402
+ } catch {
3403
+ }
3404
+ };
3405
+ var savePendingDeposit = (deposit) => {
3406
+ try {
3407
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(deposit));
3408
+ } catch {
3409
+ }
3410
+ };
3411
+ var loadPendingDeposit = (now) => {
3412
+ try {
3413
+ const raw = localStorage.getItem(STORAGE_KEY);
3414
+ if (!raw) return;
3415
+ const parsed = JSON.parse(raw);
3416
+ const isRestorable = isPendingDeposit(parsed) && shouldKeepTrackingDeposit({
3417
+ quoteDeadline: parsed.quote.expiresAt,
3418
+ depositObservedAt: parsed.depositObservedAt,
3419
+ now
3420
+ });
3421
+ if (!isRestorable) {
3422
+ clearPendingDeposit();
3423
+ return;
3424
+ }
3425
+ return parsed;
3426
+ } catch {
3427
+ clearPendingDeposit();
3428
+ }
3429
+ };
3430
+
3058
3431
  // src/utils/receiveAddress.ts
3059
3432
  var resolveReceiveAddress = ({
3060
3433
  isLocked,
3061
3434
  defaultAddress,
3435
+ defaultAddressChainId,
3062
3436
  customAddress,
3063
3437
  walletAddress,
3064
3438
  buyChainId
3065
3439
  }) => {
3066
3440
  const isValidForBuyChain = (address) => !!address && validateAddress(address, buyChainId).valid;
3067
- if (isLocked) return isValidForBuyChain(defaultAddress) ? defaultAddress : void 0;
3068
- return isValidForBuyChain(customAddress) ? customAddress : walletAddress;
3441
+ if (isLocked) {
3442
+ const isUsable = sharesAddressSpace(defaultAddressChainId, buyChainId) && isValidForBuyChain(defaultAddress);
3443
+ return isUsable ? defaultAddress : void 0;
3444
+ }
3445
+ if (isValidForBuyChain(customAddress)) return customAddress;
3446
+ return isValidForBuyChain(walletAddress) ? walletAddress : void 0;
3447
+ };
3448
+
3449
+ // src/utils/sendAddress.ts
3450
+ var resolveSendAddress = ({
3451
+ customAddress,
3452
+ walletAddress,
3453
+ sellChainId
3454
+ }) => {
3455
+ if (walletAddress && validateAddress(walletAddress, sellChainId).valid) return walletAddress;
3456
+ return validateAddress(customAddress, sellChainId).valid ? customAddress : void 0;
3069
3457
  };
3070
3458
 
3071
3459
  // src/components/ApprovalStep.tsx
@@ -3165,10 +3553,373 @@ var ApprovalStep = () => {
3165
3553
  ] });
3166
3554
  };
3167
3555
 
3556
+ // src/components/DepositStep.tsx
3557
+ import { buildPaymentUri } from "@shapeshiftoss/utils";
3558
+ import { useCallback as useCallback6, useEffect as useEffect9, useId, useMemo as useMemo7, useRef as useRef8, useState as useState4 } from "react";
3559
+
3560
+ // src/utils/countdown.ts
3561
+ var formatCountdown = (msRemaining) => {
3562
+ const totalSeconds = Math.max(0, Math.floor(msRemaining / 1e3));
3563
+ const hours = Math.floor(totalSeconds / 3600);
3564
+ const minutes = Math.floor(totalSeconds % 3600 / 60);
3565
+ const seconds = totalSeconds % 60;
3566
+ const paddedSeconds = seconds.toString().padStart(2, "0");
3567
+ if (hours === 0) return `${minutes}:${paddedSeconds}`;
3568
+ return `${hours}:${minutes.toString().padStart(2, "0")}:${paddedSeconds}`;
3569
+ };
3570
+
3571
+ // src/components/QrCode.tsx
3572
+ import qrcodeGenerator from "qrcode-generator";
3573
+ import { useMemo as useMemo6 } from "react";
3574
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
3575
+ var LOGO_SCALE = 0.2;
3576
+ var QrCode = ({ value, logo, size = 180 }) => {
3577
+ const { path, dimension } = useMemo6(() => {
3578
+ const qr = qrcodeGenerator(0, "H");
3579
+ qr.addData(value);
3580
+ qr.make();
3581
+ const count = qr.getModuleCount();
3582
+ const margin = 4;
3583
+ const segments = [];
3584
+ for (let row = 0; row < count; row++) {
3585
+ for (let col = 0; col < count; col++) {
3586
+ if (qr.isDark(row, col)) segments.push(`M${col + margin} ${row + margin}h1v1h-1z`);
3587
+ }
3588
+ }
3589
+ return { path: segments.join(""), dimension: count + margin * 2 };
3590
+ }, [value]);
3591
+ const logoBox = useMemo6(() => {
3592
+ const width = dimension * LOGO_SCALE;
3593
+ const padding = width * 0.12;
3594
+ const plate = width + padding * 2;
3595
+ const offset = (dimension - plate) / 2;
3596
+ return { width, plate, offset, inset: offset + padding, radius: plate * 0.22 };
3597
+ }, [dimension]);
3598
+ return /* @__PURE__ */ jsxs2(
3599
+ "svg",
3600
+ {
3601
+ className: "ssw-qr",
3602
+ width: size,
3603
+ height: size,
3604
+ viewBox: `0 0 ${dimension} ${dimension}`,
3605
+ role: "img",
3606
+ "aria-label": "Deposit address QR code",
3607
+ children: [
3608
+ /* @__PURE__ */ jsx2("rect", { width: dimension, height: dimension, fill: "#ffffff" }),
3609
+ /* @__PURE__ */ jsx2("path", { d: path, fill: "#000000" }),
3610
+ logo && /* @__PURE__ */ jsxs2(Fragment, { children: [
3611
+ /* @__PURE__ */ jsx2(
3612
+ "rect",
3613
+ {
3614
+ x: logoBox.offset,
3615
+ y: logoBox.offset,
3616
+ width: logoBox.plate,
3617
+ height: logoBox.plate,
3618
+ rx: logoBox.radius,
3619
+ fill: "#ffffff"
3620
+ }
3621
+ ),
3622
+ /* @__PURE__ */ jsx2(
3623
+ "image",
3624
+ {
3625
+ x: logoBox.inset,
3626
+ y: logoBox.inset,
3627
+ width: logoBox.width,
3628
+ height: logoBox.width,
3629
+ href: logo,
3630
+ preserveAspectRatio: "xMidYMid meet"
3631
+ }
3632
+ )
3633
+ ] })
3634
+ ]
3635
+ }
3636
+ );
3637
+ };
3638
+
3639
+ // src/components/DepositStep.tsx
3640
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
3641
+ var CopyField = ({ label, display, value }) => {
3642
+ const [hasCopied, setHasCopied] = useState4(false);
3643
+ const handleCopy = useCallback6(() => {
3644
+ if (!navigator.clipboard) return;
3645
+ navigator.clipboard.writeText(value).then(() => {
3646
+ setHasCopied(true);
3647
+ setTimeout(() => setHasCopied(false), 2e3);
3648
+ }).catch(() => {
3649
+ });
3650
+ }, [value]);
3651
+ return /* @__PURE__ */ jsxs3("div", { className: "ssw-deposit-field", children: [
3652
+ /* @__PURE__ */ jsx3("span", { className: "ssw-deposit-field-label", children: label }),
3653
+ /* @__PURE__ */ jsxs3(
3654
+ "button",
3655
+ {
3656
+ className: "ssw-deposit-value",
3657
+ onClick: handleCopy,
3658
+ type: "button",
3659
+ "aria-label": `Copy ${label.toLowerCase()}`,
3660
+ children: [
3661
+ /* @__PURE__ */ jsx3("span", { children: display }),
3662
+ /* @__PURE__ */ jsx3("span", { className: "ssw-deposit-copy", children: hasCopied ? "Copied" : "Copy" })
3663
+ ]
3664
+ }
3665
+ )
3666
+ ] });
3667
+ };
3668
+ var DepositStep = () => {
3669
+ const context = SwapMachineCtx.useSelector((s) => s.context);
3670
+ const isExpired = SwapMachineCtx.useSelector((s) => s.matches("deposit_expired"));
3671
+ const isRequoting = SwapMachineCtx.useSelector((s) => s.matches("quoting"));
3672
+ const actorRef = SwapMachineCtx.useActorRef();
3673
+ const { quote, sendAddress, receiveAddress } = context;
3674
+ const [msRemaining, setMsRemaining] = useState4(() => quote ? quote.expiresAt - Date.now() : 0);
3675
+ const [isAmountInQr, setIsAmountInQr] = useState4(false);
3676
+ const [isQrInfoOpen, setIsQrInfoOpen] = useState4(false);
3677
+ const [isQrInfoDismissed, setIsQrInfoDismissed] = useState4(false);
3678
+ const qrInfoId = useId();
3679
+ const qrControlsRef = useRef8(null);
3680
+ useEffect9(() => {
3681
+ if (!quote || isRequoting) return;
3682
+ const tick = () => {
3683
+ const remaining = quote.expiresAt - Date.now();
3684
+ setMsRemaining(remaining);
3685
+ if (remaining <= 0 && !isExpired) actorRef.send({ type: "DEPOSIT_EXPIRED" });
3686
+ };
3687
+ tick();
3688
+ const interval = setInterval(tick, 1e3);
3689
+ return () => clearInterval(interval);
3690
+ }, [quote, isExpired, isRequoting, actorRef]);
3691
+ const handleNewSwap = useCallback6(() => actorRef.send({ type: "RESET" }), [actorRef]);
3692
+ const handleNewQuote = useCallback6(() => actorRef.send({ type: "RETRY" }), [actorRef]);
3693
+ const handleShowAddressOnly = useCallback6(() => {
3694
+ setIsAmountInQr(false);
3695
+ setIsQrInfoOpen(false);
3696
+ }, []);
3697
+ const handleShowWithAmount = useCallback6(() => {
3698
+ setIsAmountInQr(true);
3699
+ setIsQrInfoOpen(false);
3700
+ }, []);
3701
+ const handleToggleQrInfo = useCallback6(() => {
3702
+ setIsQrInfoDismissed(false);
3703
+ setIsQrInfoOpen((isOpen) => !isOpen);
3704
+ }, []);
3705
+ const handleResetQrInfo = useCallback6(() => {
3706
+ setIsQrInfoOpen(false);
3707
+ setIsQrInfoDismissed(false);
3708
+ }, []);
3709
+ const handleQrInfoMouseLeave = useCallback6(() => setIsQrInfoDismissed(false), []);
3710
+ useEffect9(() => {
3711
+ const handleKeyDown = (event) => {
3712
+ if (event.key !== "Escape") return;
3713
+ setIsQrInfoOpen(false);
3714
+ if (qrControlsRef.current?.matches(":hover, :focus-within")) setIsQrInfoDismissed(true);
3715
+ };
3716
+ const handlePointerDown = (event) => {
3717
+ if (qrControlsRef.current?.contains(event.target)) return;
3718
+ setIsQrInfoOpen(false);
3719
+ };
3720
+ document.addEventListener("keydown", handleKeyDown);
3721
+ document.addEventListener("pointerdown", handlePointerDown);
3722
+ return () => {
3723
+ document.removeEventListener("keydown", handleKeyDown);
3724
+ document.removeEventListener("pointerdown", handlePointerDown);
3725
+ };
3726
+ }, []);
3727
+ const paymentUri = useMemo7(() => {
3728
+ if (!quote?.depositAddress) return;
3729
+ try {
3730
+ return buildPaymentUri({
3731
+ address: quote.depositAddress,
3732
+ asset: quote.sellAsset,
3733
+ amountCryptoPrecision: formatAmountForInput(
3734
+ quote.sellAmountCryptoBaseUnit,
3735
+ quote.sellAsset.precision
3736
+ )
3737
+ });
3738
+ } catch {
3739
+ return;
3740
+ }
3741
+ }, [quote]);
3742
+ if (!quote?.depositAddress) return null;
3743
+ const isStillWatching = shouldKeepTrackingDeposit({
3744
+ quoteDeadline: quote.expiresAt,
3745
+ depositObservedAt: void 0,
3746
+ now: quote.expiresAt - msRemaining
3747
+ });
3748
+ const sellAmount = formatAmountForInput(quote.sellAmountCryptoBaseUnit, quote.sellAsset.precision);
3749
+ const buyAmount = formatAmount(quote.buyAmountAfterFeesCryptoBaseUnit, quote.buyAsset.precision);
3750
+ const canIncludeAmount = !!paymentUri && paymentUri !== quote.depositAddress;
3751
+ if (isRequoting) {
3752
+ return /* @__PURE__ */ jsxs3("div", { className: "ssw-step-screen", children: [
3753
+ /* @__PURE__ */ jsx3("div", { className: "ssw-step-icon-circle ssw-ic-accent", children: /* @__PURE__ */ jsxs3(
3754
+ "svg",
3755
+ {
3756
+ className: "ssw-spinner",
3757
+ width: "32",
3758
+ height: "32",
3759
+ viewBox: "0 0 24 24",
3760
+ fill: "none",
3761
+ stroke: "currentColor",
3762
+ strokeWidth: "2",
3763
+ children: [
3764
+ /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "10", opacity: "0.25" }),
3765
+ /* @__PURE__ */ jsx3("path", { d: "M12 2a10 10 0 0 1 10 10" })
3766
+ ]
3767
+ }
3768
+ ) }),
3769
+ /* @__PURE__ */ jsx3("div", { className: "ssw-step-title", children: "Requesting New Quote" })
3770
+ ] });
3771
+ }
3772
+ if (isExpired) {
3773
+ return /* @__PURE__ */ jsxs3("div", { className: "ssw-step-screen", children: [
3774
+ /* @__PURE__ */ jsx3("div", { className: "ssw-step-icon-circle ssw-ic-error", children: /* @__PURE__ */ jsxs3(
3775
+ "svg",
3776
+ {
3777
+ width: "32",
3778
+ height: "32",
3779
+ viewBox: "0 0 24 24",
3780
+ fill: "none",
3781
+ stroke: "currentColor",
3782
+ strokeWidth: "2",
3783
+ children: [
3784
+ /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "10" }),
3785
+ /* @__PURE__ */ jsx3("path", { d: "M12 7v5l3 2" })
3786
+ ]
3787
+ }
3788
+ ) }),
3789
+ /* @__PURE__ */ jsx3("div", { className: "ssw-step-title", children: "Quote Expired" }),
3790
+ /* @__PURE__ */ jsx3("div", { className: "ssw-step-subtitle", children: "Don't send to the previous address. Request a new quote to continue." }),
3791
+ /* @__PURE__ */ jsx3("div", { className: "ssw-deposit-watching", children: isStillWatching ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
3792
+ /* @__PURE__ */ jsxs3(
3793
+ "svg",
3794
+ {
3795
+ className: "ssw-spinner",
3796
+ width: "14",
3797
+ height: "14",
3798
+ viewBox: "0 0 24 24",
3799
+ fill: "none",
3800
+ stroke: "currentColor",
3801
+ strokeWidth: "2",
3802
+ children: [
3803
+ /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "10", opacity: "0.25" }),
3804
+ /* @__PURE__ */ jsx3("path", { d: "M12 2a10 10 0 0 1 10 10" })
3805
+ ]
3806
+ }
3807
+ ),
3808
+ /* @__PURE__ */ jsx3("span", { children: "Already sent? Still watching for your deposit - this screen will update." })
3809
+ ] }) : /* @__PURE__ */ jsx3("span", { children: "Already sent? The provider may still settle or refund it - check your receive and refund addresses." }) }),
3810
+ /* @__PURE__ */ jsxs3("div", { className: "ssw-step-actions", children: [
3811
+ /* @__PURE__ */ jsx3("button", { className: "ssw-action-btn", onClick: handleNewQuote, type: "button", children: "Request New Quote" }),
3812
+ /* @__PURE__ */ jsx3("button", { className: "ssw-action-btn ssw-secondary", onClick: handleNewSwap, type: "button", children: "New Swap" })
3813
+ ] })
3814
+ ] });
3815
+ }
3816
+ return /* @__PURE__ */ jsxs3("div", { className: "ssw-deposit", children: [
3817
+ /* @__PURE__ */ jsx3("span", { className: "ssw-deposit-title", children: "Awaiting Deposit" }),
3818
+ /* @__PURE__ */ jsx3(
3819
+ QrCode,
3820
+ {
3821
+ value: canIncludeAmount && isAmountInQr && paymentUri ? paymentUri : quote.depositAddress,
3822
+ logo: getChainIcon(quote.sellAsset.chainId)
3823
+ }
3824
+ ),
3825
+ canIncludeAmount && /* @__PURE__ */ jsxs3("div", { className: "ssw-deposit-qr-controls", ref: qrControlsRef, children: [
3826
+ /* @__PURE__ */ jsxs3("div", { className: "ssw-deposit-qr-mode", role: "group", "aria-label": "QR code contents", children: [
3827
+ /* @__PURE__ */ jsx3("button", { type: "button", "aria-pressed": !isAmountInQr, onClick: handleShowAddressOnly, children: "Address only" }),
3828
+ /* @__PURE__ */ jsx3("button", { type: "button", "aria-pressed": isAmountInQr, onClick: handleShowWithAmount, children: "With amount" })
3829
+ ] }),
3830
+ /* @__PURE__ */ jsx3(
3831
+ "button",
3832
+ {
3833
+ type: "button",
3834
+ className: "ssw-deposit-qr-info",
3835
+ "aria-label": "About the QR code options",
3836
+ "aria-describedby": qrInfoId,
3837
+ onClick: handleToggleQrInfo,
3838
+ onBlur: handleResetQrInfo,
3839
+ onMouseLeave: handleQrInfoMouseLeave,
3840
+ children: /* @__PURE__ */ jsxs3(
3841
+ "svg",
3842
+ {
3843
+ width: "14",
3844
+ height: "14",
3845
+ viewBox: "0 0 24 24",
3846
+ fill: "none",
3847
+ stroke: "currentColor",
3848
+ strokeWidth: "2",
3849
+ children: [
3850
+ /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "10" }),
3851
+ /* @__PURE__ */ jsx3("path", { d: "M12 16v-4M12 8h.01" })
3852
+ ]
3853
+ }
3854
+ )
3855
+ }
3856
+ ),
3857
+ /* @__PURE__ */ jsxs3(
3858
+ "span",
3859
+ {
3860
+ id: qrInfoId,
3861
+ role: "tooltip",
3862
+ className: `ssw-deposit-qr-tooltip${isQrInfoOpen ? " ssw-open" : ""}${isQrInfoDismissed ? " ssw-dismissed" : ""}`,
3863
+ children: [
3864
+ /* @__PURE__ */ jsxs3("span", { children: [
3865
+ /* @__PURE__ */ jsx3("strong", { children: "Address only:" }),
3866
+ " Enter the exact amount in your wallet."
3867
+ ] }),
3868
+ /* @__PURE__ */ jsxs3("span", { children: [
3869
+ /* @__PURE__ */ jsx3("strong", { children: "With amount:" }),
3870
+ " Also fills in the amount, if your wallet supports it."
3871
+ ] })
3872
+ ]
3873
+ }
3874
+ )
3875
+ ] }),
3876
+ /* @__PURE__ */ jsx3(
3877
+ CopyField,
3878
+ {
3879
+ label: "Send exactly",
3880
+ display: `${sellAmount} ${quote.sellAsset.symbol}`,
3881
+ value: sellAmount
3882
+ }
3883
+ ),
3884
+ /* @__PURE__ */ jsx3(
3885
+ CopyField,
3886
+ {
3887
+ label: "To this address",
3888
+ display: truncateAddress(quote.depositAddress, 8),
3889
+ value: quote.depositAddress
3890
+ }
3891
+ ),
3892
+ /* @__PURE__ */ jsxs3("span", { className: "ssw-deposit-countdown", children: [
3893
+ "Expires in ",
3894
+ formatCountdown(msRemaining)
3895
+ ] }),
3896
+ /* @__PURE__ */ jsxs3("div", { className: "ssw-deposit-summary", children: [
3897
+ /* @__PURE__ */ jsxs3("div", { className: "ssw-deposit-row", children: [
3898
+ /* @__PURE__ */ jsx3("span", { children: "You get" }),
3899
+ /* @__PURE__ */ jsxs3("span", { children: [
3900
+ "~",
3901
+ buyAmount,
3902
+ " ",
3903
+ quote.buyAsset.symbol
3904
+ ] })
3905
+ ] }),
3906
+ /* @__PURE__ */ jsxs3("div", { className: "ssw-deposit-row", children: [
3907
+ /* @__PURE__ */ jsx3("span", { children: "Receive address" }),
3908
+ /* @__PURE__ */ jsx3("span", { children: truncateAddress(receiveAddress ?? "", 6) })
3909
+ ] }),
3910
+ /* @__PURE__ */ jsxs3("div", { className: "ssw-deposit-row", children: [
3911
+ /* @__PURE__ */ jsx3("span", { children: "Refund address" }),
3912
+ /* @__PURE__ */ jsx3("span", { children: truncateAddress(sendAddress ?? "", 6) })
3913
+ ] })
3914
+ ] }),
3915
+ /* @__PURE__ */ jsx3("button", { className: "ssw-action-btn ssw-secondary", onClick: handleNewSwap, type: "button", children: "New Swap" })
3916
+ ] });
3917
+ };
3918
+
3168
3919
  // src/components/ExecutionStep.tsx
3169
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
3170
- var ExecutionStep = () => /* @__PURE__ */ jsxs2("div", { className: "ssw-step-screen", children: [
3171
- /* @__PURE__ */ jsx2("div", { className: "ssw-step-icon-circle ssw-ic-accent", children: /* @__PURE__ */ jsxs2(
3920
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
3921
+ var ExecutionStep = () => /* @__PURE__ */ jsxs4("div", { className: "ssw-step-screen", children: [
3922
+ /* @__PURE__ */ jsx4("div", { className: "ssw-step-icon-circle ssw-ic-accent", children: /* @__PURE__ */ jsxs4(
3172
3923
  "svg",
3173
3924
  {
3174
3925
  className: "ssw-spinner",
@@ -3179,20 +3930,53 @@ var ExecutionStep = () => /* @__PURE__ */ jsxs2("div", { className: "ssw-step-sc
3179
3930
  stroke: "currentColor",
3180
3931
  strokeWidth: "2",
3181
3932
  children: [
3182
- /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "10", opacity: "0.25" }),
3183
- /* @__PURE__ */ jsx2("path", { d: "M12 2a10 10 0 0 1 10 10" })
3933
+ /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "10", opacity: "0.25" }),
3934
+ /* @__PURE__ */ jsx4("path", { d: "M12 2a10 10 0 0 1 10 10" })
3184
3935
  ]
3185
3936
  }
3186
3937
  ) }),
3187
- /* @__PURE__ */ jsx2("div", { className: "ssw-step-title", children: "Confirm in Wallet" }),
3188
- /* @__PURE__ */ jsx2("div", { className: "ssw-step-subtitle", children: "Please sign the transaction in your wallet" })
3938
+ /* @__PURE__ */ jsx4("div", { className: "ssw-step-title", children: "Confirm in Wallet" }),
3939
+ /* @__PURE__ */ jsx4("div", { className: "ssw-step-subtitle", children: "Please sign the transaction in your wallet" })
3189
3940
  ] });
3190
3941
 
3191
3942
  // src/components/InputStep.tsx
3192
- import { useMemo as useMemo9 } from "react";
3943
+ import { useMemo as useMemo12 } from "react";
3944
+
3945
+ // src/utils/inputCta.ts
3946
+ var getUnsupportedCta = (allowShapeshiftRedirect) => allowShapeshiftRedirect ? { text: "Proceed on ShapeShift", disabled: false, action: "redirect" } : { text: "Route not supported", disabled: true, action: "none" };
3947
+ var getInputCta = ({
3948
+ isDepositRoute,
3949
+ hasWalletForSellChain,
3950
+ isSellChainTypeConnected,
3951
+ isUnsupportedChain,
3952
+ allowShapeshiftRedirect,
3953
+ hasReceiveAddress: hasReceiveAddress2,
3954
+ hasSendAddress: hasSendAddress2,
3955
+ hasAmount,
3956
+ isLoadingRates,
3957
+ hasRates,
3958
+ hasRatesError
3959
+ }) => {
3960
+ if (isUnsupportedChain && !isDepositRoute) return getUnsupportedCta(allowShapeshiftRedirect);
3961
+ if (!hasAmount) return { text: "Enter an amount", disabled: true, action: "none" };
3962
+ if (isLoadingRates) return { text: "Finding rates...", disabled: true, action: "none" };
3963
+ if (hasRatesError) return { text: "No routes available", disabled: true, action: "none" };
3964
+ if (!hasRates) return { text: "No routes found", disabled: true, action: "none" };
3965
+ if (isDepositRoute) {
3966
+ if (!hasReceiveAddress2) return { text: "Enter receive address", disabled: true, action: "none" };
3967
+ if (!hasSendAddress2) return { text: "Enter refund address", disabled: true, action: "none" };
3968
+ return { text: "Continue without a wallet", disabled: false, action: "deposit" };
3969
+ }
3970
+ if (!hasWalletForSellChain) {
3971
+ if (isSellChainTypeConnected) return getUnsupportedCta(allowShapeshiftRedirect);
3972
+ return { text: "Connect Wallet", disabled: false, action: "connect" };
3973
+ }
3974
+ if (!hasReceiveAddress2) return { text: "Enter receive address", disabled: true, action: "none" };
3975
+ return { text: "Swap", disabled: false, action: "quote" };
3976
+ };
3193
3977
 
3194
3978
  // src/components/QuoteSelector.tsx
3195
- import { useCallback as useCallback6, useMemo as useMemo7, useState as useState3 } from "react";
3979
+ import { useCallback as useCallback8, useMemo as useMemo9, useState as useState5 } from "react";
3196
3980
 
3197
3981
  // src/constants/swappers.ts
3198
3982
  var SWAPPER_ICONS = {
@@ -3229,10 +4013,10 @@ var getSwapperColor = (swapperName) => {
3229
4013
  };
3230
4014
 
3231
4015
  // src/components/QuotesModal.tsx
3232
- import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo6 } from "react";
3233
- import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
4016
+ import { useCallback as useCallback7, useEffect as useEffect10, useMemo as useMemo8 } from "react";
4017
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
3234
4018
  var useLockBodyScroll = (isLocked) => {
3235
- useEffect6(() => {
4019
+ useEffect10(() => {
3236
4020
  if (!isLocked) return;
3237
4021
  const originalOverflow = document.body.style.overflow;
3238
4022
  document.body.style.overflow = "hidden";
@@ -3256,7 +4040,7 @@ var QuotesModal = ({
3256
4040
  buyAssetUsdPrice
3257
4041
  }) => {
3258
4042
  useLockBodyScroll(isOpen);
3259
- const handleBackdropClick = useCallback5(
4043
+ const handleBackdropClick = useCallback7(
3260
4044
  (e) => {
3261
4045
  if (e.target === e.currentTarget) {
3262
4046
  onClose();
@@ -3264,22 +4048,22 @@ var QuotesModal = ({
3264
4048
  },
3265
4049
  [onClose]
3266
4050
  );
3267
- const handleSelectRate = useCallback5(
4051
+ const handleSelectRate = useCallback7(
3268
4052
  (rate) => {
3269
4053
  onSelectRate(rate);
3270
4054
  onClose();
3271
4055
  },
3272
4056
  [onSelectRate, onClose]
3273
4057
  );
3274
- const sortedRates = useMemo6(() => sortRatesByValue(rates, isExactOutput2), [rates, isExactOutput2]);
3275
- const bestRate = useMemo6(() => sortedRates[0], [sortedRates]);
4058
+ const sortedRates = useMemo8(() => sortRatesByValue(rates, isExactOutput2), [rates, isExactOutput2]);
4059
+ const bestRate = useMemo8(() => sortedRates[0], [sortedRates]);
3276
4060
  const bestAmountBaseUnit = bestRate ? getRateAmountBaseUnit(bestRate, isExactOutput2) : "0";
3277
4061
  const asset = isExactOutput2 ? sellAsset : buyAsset;
3278
4062
  const usdPrice = isExactOutput2 ? sellAssetUsdPrice : buyAssetUsdPrice;
3279
4063
  if (!isOpen) return null;
3280
4064
  return (
3281
4065
  // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
3282
- /* @__PURE__ */ jsx3(
4066
+ /* @__PURE__ */ jsx5(
3283
4067
  "div",
3284
4068
  {
3285
4069
  className: "ssw-quotes-modal-backdrop",
@@ -3288,17 +4072,17 @@ var QuotesModal = ({
3288
4072
  role: "dialog",
3289
4073
  "aria-modal": "true",
3290
4074
  "aria-labelledby": "quotes-modal-title",
3291
- children: /* @__PURE__ */ jsxs3("div", { className: "ssw-quotes-modal", children: [
3292
- /* @__PURE__ */ jsxs3("div", { className: "ssw-quotes-modal-header", children: [
3293
- /* @__PURE__ */ jsxs3("div", { className: "ssw-quotes-header-content", children: [
3294
- /* @__PURE__ */ jsx3("h2", { id: "quotes-modal-title", className: "ssw-quotes-modal-title", children: "Select Route" }),
3295
- /* @__PURE__ */ jsx3("span", { className: "ssw-quotes-modal-subtitle", children: isExactOutput2 ? /* @__PURE__ */ jsxs3(Fragment, { children: [
4075
+ children: /* @__PURE__ */ jsxs5("div", { className: "ssw-quotes-modal", children: [
4076
+ /* @__PURE__ */ jsxs5("div", { className: "ssw-quotes-modal-header", children: [
4077
+ /* @__PURE__ */ jsxs5("div", { className: "ssw-quotes-header-content", children: [
4078
+ /* @__PURE__ */ jsx5("h2", { id: "quotes-modal-title", className: "ssw-quotes-modal-title", children: "Select Route" }),
4079
+ /* @__PURE__ */ jsx5("span", { className: "ssw-quotes-modal-subtitle", children: isExactOutput2 ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
3296
4080
  sellAsset.symbol,
3297
4081
  " \u2192 ",
3298
4082
  formatAmount(buyAmountBaseUnit, buyAsset.precision),
3299
4083
  " ",
3300
4084
  buyAsset.symbol
3301
- ] }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
4085
+ ] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
3302
4086
  formatAmount(sellAmountBaseUnit, sellAsset.precision),
3303
4087
  " ",
3304
4088
  sellAsset.symbol,
@@ -3307,7 +4091,7 @@ var QuotesModal = ({
3307
4091
  buyAsset.symbol
3308
4092
  ] }) })
3309
4093
  ] }),
3310
- /* @__PURE__ */ jsx3("button", { className: "ssw-quotes-modal-close", onClick: onClose, type: "button", children: /* @__PURE__ */ jsx3(
4094
+ /* @__PURE__ */ jsx5("button", { className: "ssw-quotes-modal-close", onClick: onClose, type: "button", children: /* @__PURE__ */ jsx5(
3311
4095
  "svg",
3312
4096
  {
3313
4097
  width: "20",
@@ -3316,11 +4100,11 @@ var QuotesModal = ({
3316
4100
  fill: "none",
3317
4101
  stroke: "currentColor",
3318
4102
  strokeWidth: "2",
3319
- children: /* @__PURE__ */ jsx3("path", { d: "M18 6L6 18M6 6l12 12" })
4103
+ children: /* @__PURE__ */ jsx5("path", { d: "M18 6L6 18M6 6l12 12" })
3320
4104
  }
3321
4105
  ) })
3322
4106
  ] }),
3323
- /* @__PURE__ */ jsx3("div", { className: "ssw-quotes-modal-list", children: sortedRates.map((rate, index) => {
4107
+ /* @__PURE__ */ jsx5("div", { className: "ssw-quotes-modal-list", children: sortedRates.map((rate, index) => {
3324
4108
  const amountBaseUnit = getRateAmountBaseUnit(rate, isExactOutput2);
3325
4109
  const estimatedTime = rate.estimatedExecutionTimeMs;
3326
4110
  const isBest = index === 0;
@@ -3332,15 +4116,15 @@ var QuotesModal = ({
3332
4116
  const diffPercent = isBest ? null : getRateDiffPercent(bestAmountBaseUnit, amountBaseUnit, isExactOutput2);
3333
4117
  const estimatedSeconds = estimatedTime ? Math.round(estimatedTime / 1e3) : 0;
3334
4118
  const hasTime = estimatedSeconds > 0;
3335
- return /* @__PURE__ */ jsxs3(
4119
+ return /* @__PURE__ */ jsxs5(
3336
4120
  "button",
3337
4121
  {
3338
4122
  className: `ssw-quote-row ${isSelected ? "ssw-selected" : ""} ${isBest ? "ssw-best" : ""}`,
3339
4123
  onClick: () => handleSelectRate(rate),
3340
4124
  type: "button",
3341
4125
  children: [
3342
- /* @__PURE__ */ jsxs3("div", { className: "ssw-quote-row-left", children: [
3343
- swapperIcon ? /* @__PURE__ */ jsx3("img", { src: swapperIcon, alt: rate.swapperName, className: "ssw-quote-row-icon" }) : /* @__PURE__ */ jsx3(
4126
+ /* @__PURE__ */ jsxs5("div", { className: "ssw-quote-row-left", children: [
4127
+ swapperIcon ? /* @__PURE__ */ jsx5("img", { src: swapperIcon, alt: rate.swapperName, className: "ssw-quote-row-icon" }) : /* @__PURE__ */ jsx5(
3344
4128
  "div",
3345
4129
  {
3346
4130
  className: "ssw-quote-row-icon-placeholder",
@@ -3348,30 +4132,30 @@ var QuotesModal = ({
3348
4132
  children: rate.swapperName.charAt(0)
3349
4133
  }
3350
4134
  ),
3351
- /* @__PURE__ */ jsxs3("div", { className: "ssw-quote-row-info", children: [
3352
- /* @__PURE__ */ jsxs3("div", { className: "ssw-quote-row-name-row", children: [
3353
- /* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-name", children: rate.swapperName }),
3354
- isBest && /* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-best", children: "Best" }),
3355
- diffPercent && /* @__PURE__ */ jsxs3("span", { className: "ssw-quote-row-diff", children: [
4135
+ /* @__PURE__ */ jsxs5("div", { className: "ssw-quote-row-info", children: [
4136
+ /* @__PURE__ */ jsxs5("div", { className: "ssw-quote-row-name-row", children: [
4137
+ /* @__PURE__ */ jsx5("span", { className: "ssw-quote-row-name", children: rate.swapperName }),
4138
+ isBest && /* @__PURE__ */ jsx5("span", { className: "ssw-quote-row-best", children: "Best" }),
4139
+ diffPercent && /* @__PURE__ */ jsxs5("span", { className: "ssw-quote-row-diff", children: [
3356
4140
  isExactOutput2 ? "+" : "-",
3357
4141
  diffPercent,
3358
4142
  "%"
3359
4143
  ] })
3360
4144
  ] }),
3361
- hasTime && /* @__PURE__ */ jsxs3("span", { className: "ssw-quote-row-time", children: [
4145
+ hasTime && /* @__PURE__ */ jsxs5("span", { className: "ssw-quote-row-time", children: [
3362
4146
  "~",
3363
4147
  estimatedSeconds,
3364
4148
  "s"
3365
4149
  ] })
3366
4150
  ] })
3367
4151
  ] }),
3368
- /* @__PURE__ */ jsxs3("div", { className: "ssw-quote-row-right", children: [
3369
- /* @__PURE__ */ jsxs3("span", { className: "ssw-quote-row-amount", children: [
4152
+ /* @__PURE__ */ jsxs5("div", { className: "ssw-quote-row-right", children: [
4153
+ /* @__PURE__ */ jsxs5("span", { className: "ssw-quote-row-amount", children: [
3370
4154
  formattedAmount,
3371
4155
  " ",
3372
- /* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-symbol", children: asset.symbol })
4156
+ /* @__PURE__ */ jsx5("span", { className: "ssw-quote-row-symbol", children: asset.symbol })
3373
4157
  ] }),
3374
- /* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-usd", children: usdValue })
4158
+ /* @__PURE__ */ jsx5("span", { className: "ssw-quote-row-usd", children: usdValue })
3375
4159
  ] })
3376
4160
  ]
3377
4161
  },
@@ -3385,7 +4169,7 @@ var QuotesModal = ({
3385
4169
  };
3386
4170
 
3387
4171
  // src/components/QuoteSelector.tsx
3388
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
4172
+ import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
3389
4173
  var QuoteSelector = ({
3390
4174
  rates,
3391
4175
  selectedRate,
@@ -3399,27 +4183,27 @@ var QuoteSelector = ({
3399
4183
  sellAssetUsdPrice,
3400
4184
  buyAssetUsdPrice
3401
4185
  }) => {
3402
- const [isModalOpen, setIsModalOpen] = useState3(false);
3403
- const bestRate = useMemo7(() => rates[0], [rates]);
3404
- const alternativeRatesCount = useMemo7(() => Math.max(0, rates.length - 1), [rates]);
3405
- const handleOpenModal = useCallback6(() => {
4186
+ const [isModalOpen, setIsModalOpen] = useState5(false);
4187
+ const bestRate = useMemo9(() => rates[0], [rates]);
4188
+ const alternativeRatesCount = useMemo9(() => Math.max(0, rates.length - 1), [rates]);
4189
+ const handleOpenModal = useCallback8(() => {
3406
4190
  if (rates.length > 0) {
3407
4191
  setIsModalOpen(true);
3408
4192
  }
3409
4193
  }, [rates.length]);
3410
- const handleCloseModal = useCallback6(() => {
4194
+ const handleCloseModal = useCallback8(() => {
3411
4195
  setIsModalOpen(false);
3412
4196
  }, []);
3413
- const handleSelectRate = useCallback6(
4197
+ const handleSelectRate = useCallback8(
3414
4198
  (rate) => {
3415
4199
  onSelectRate(rate);
3416
4200
  },
3417
4201
  [onSelectRate]
3418
4202
  );
3419
4203
  if (isLoading) {
3420
- return /* @__PURE__ */ jsx4("div", { className: "ssw-quote-selector ssw-loading", children: /* @__PURE__ */ jsxs4("div", { className: "ssw-quote-loading", children: [
3421
- /* @__PURE__ */ jsx4("div", { className: "ssw-spinner-small" }),
3422
- /* @__PURE__ */ jsx4("span", { children: "Finding best rates..." })
4204
+ return /* @__PURE__ */ jsx6("div", { className: "ssw-quote-selector ssw-loading", children: /* @__PURE__ */ jsxs6("div", { className: "ssw-quote-loading", children: [
4205
+ /* @__PURE__ */ jsx6("div", { className: "ssw-spinner-small" }),
4206
+ /* @__PURE__ */ jsx6("span", { children: "Finding best rates..." })
3423
4207
  ] }) });
3424
4208
  }
3425
4209
  if (!bestRate) {
@@ -3436,18 +4220,18 @@ var QuoteSelector = ({
3436
4220
  asset.precision,
3437
4221
  isExactOutput2 ? sellAssetUsdPrice : buyAssetUsdPrice
3438
4222
  );
3439
- return /* @__PURE__ */ jsxs4(Fragment2, { children: [
3440
- /* @__PURE__ */ jsxs4("button", { className: "ssw-quote-selector", onClick: handleOpenModal, type: "button", children: [
3441
- /* @__PURE__ */ jsxs4("div", { className: "ssw-quote-left", children: [
3442
- /* @__PURE__ */ jsxs4("div", { className: "ssw-quote-provider", children: [
3443
- swapperIcon ? /* @__PURE__ */ jsx4(
4223
+ return /* @__PURE__ */ jsxs6(Fragment4, { children: [
4224
+ /* @__PURE__ */ jsxs6("button", { className: "ssw-quote-selector", onClick: handleOpenModal, type: "button", children: [
4225
+ /* @__PURE__ */ jsxs6("div", { className: "ssw-quote-left", children: [
4226
+ /* @__PURE__ */ jsxs6("div", { className: "ssw-quote-provider", children: [
4227
+ swapperIcon ? /* @__PURE__ */ jsx6(
3444
4228
  "img",
3445
4229
  {
3446
4230
  src: swapperIcon,
3447
4231
  alt: displayRate.swapperName,
3448
4232
  className: "ssw-quote-provider-icon"
3449
4233
  }
3450
- ) : /* @__PURE__ */ jsx4(
4234
+ ) : /* @__PURE__ */ jsx6(
3451
4235
  "div",
3452
4236
  {
3453
4237
  className: "ssw-quote-provider-icon-placeholder",
@@ -3455,21 +4239,21 @@ var QuoteSelector = ({
3455
4239
  children: displayRate.swapperName.charAt(0)
3456
4240
  }
3457
4241
  ),
3458
- /* @__PURE__ */ jsx4("span", { className: "ssw-quote-provider-name", children: displayRate.swapperName }),
3459
- displayRate === bestRate && /* @__PURE__ */ jsx4("span", { className: "ssw-quote-best-tag", children: "Best" })
4242
+ /* @__PURE__ */ jsx6("span", { className: "ssw-quote-provider-name", children: displayRate.swapperName }),
4243
+ displayRate === bestRate && /* @__PURE__ */ jsx6("span", { className: "ssw-quote-best-tag", children: "Best" })
3460
4244
  ] }),
3461
- /* @__PURE__ */ jsx4("span", { className: "ssw-quote-usd", children: usdValue })
4245
+ /* @__PURE__ */ jsx6("span", { className: "ssw-quote-usd", children: usdValue })
3462
4246
  ] }),
3463
- /* @__PURE__ */ jsxs4("div", { className: "ssw-quote-right", children: [
3464
- /* @__PURE__ */ jsxs4("div", { className: "ssw-quote-amount-row", children: [
3465
- /* @__PURE__ */ jsx4("span", { className: "ssw-quote-amount", children: formattedAmount }),
3466
- /* @__PURE__ */ jsx4("span", { className: "ssw-quote-symbol", children: asset.symbol })
4247
+ /* @__PURE__ */ jsxs6("div", { className: "ssw-quote-right", children: [
4248
+ /* @__PURE__ */ jsxs6("div", { className: "ssw-quote-amount-row", children: [
4249
+ /* @__PURE__ */ jsx6("span", { className: "ssw-quote-amount", children: formattedAmount }),
4250
+ /* @__PURE__ */ jsx6("span", { className: "ssw-quote-symbol", children: asset.symbol })
3467
4251
  ] }),
3468
- alternativeRatesCount > 0 && /* @__PURE__ */ jsxs4("span", { className: "ssw-quote-more", children: [
4252
+ alternativeRatesCount > 0 && /* @__PURE__ */ jsxs6("span", { className: "ssw-quote-more", children: [
3469
4253
  "+",
3470
4254
  alternativeRatesCount,
3471
4255
  " more",
3472
- /* @__PURE__ */ jsx4(
4256
+ /* @__PURE__ */ jsx6(
3473
4257
  "svg",
3474
4258
  {
3475
4259
  width: "12",
@@ -3478,13 +4262,13 @@ var QuoteSelector = ({
3478
4262
  fill: "none",
3479
4263
  stroke: "currentColor",
3480
4264
  strokeWidth: "2.5",
3481
- children: /* @__PURE__ */ jsx4("path", { d: "M9 18l6-6-6-6" })
4265
+ children: /* @__PURE__ */ jsx6("path", { d: "M9 18l6-6-6-6" })
3482
4266
  }
3483
4267
  )
3484
4268
  ] })
3485
4269
  ] })
3486
4270
  ] }),
3487
- /* @__PURE__ */ jsx4(
4271
+ /* @__PURE__ */ jsx6(
3488
4272
  QuotesModal,
3489
4273
  {
3490
4274
  isOpen: isModalOpen,
@@ -3505,8 +4289,8 @@ var QuoteSelector = ({
3505
4289
  };
3506
4290
 
3507
4291
  // src/components/ReceiveAddressRow.tsx
3508
- import { useCallback as useCallback7, useLayoutEffect, useMemo as useMemo8, useRef as useRef5, useState as useState4 } from "react";
3509
- import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
4292
+ import { useCallback as useCallback9, useLayoutEffect, useMemo as useMemo10, useRef as useRef9, useState as useState6 } from "react";
4293
+ import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
3510
4294
  var ReceiveAddressRow = ({
3511
4295
  receiveAddress,
3512
4296
  isResolving,
@@ -3514,10 +4298,10 @@ var ReceiveAddressRow = ({
3514
4298
  isLocked,
3515
4299
  onSetCustomReceiveAddress
3516
4300
  }) => {
3517
- const [isEditing, setIsEditing] = useState4(false);
3518
- const [draft, setDraft] = useState4("");
3519
- const [hasInteracted, setHasInteracted] = useState4(false);
3520
- const inputRef = useRef5(null);
4301
+ const [isEditing, setIsEditing] = useState6(false);
4302
+ const [draft, setDraft] = useState6("");
4303
+ const [hasInteracted, setHasInteracted] = useState6(false);
4304
+ const inputRef = useRef9(null);
3521
4305
  const needsAddress = !receiveAddress;
3522
4306
  const showInput = !isLocked && (needsAddress && !isResolving || isEditing);
3523
4307
  const showAttention = needsAddress && !isResolving;
@@ -3529,33 +4313,33 @@ var ReceiveAddressRow = ({
3529
4313
  setHasInteracted(false);
3530
4314
  setIsEditing(false);
3531
4315
  }, [buyChainId]);
3532
- const trimmedDraft = useMemo8(() => draft.trim(), [draft]);
3533
- const validation = useMemo8(() => {
4316
+ const trimmedDraft = useMemo10(() => draft.trim(), [draft]);
4317
+ const validation = useMemo10(() => {
3534
4318
  if (!trimmedDraft || !hasInteracted) return { valid: true, error: void 0 };
3535
4319
  return validateAddress(trimmedDraft, buyChainId);
3536
4320
  }, [trimmedDraft, hasInteracted, buyChainId]);
3537
- const canAccept = useMemo8(
4321
+ const canAccept = useMemo10(
3538
4322
  () => !!trimmedDraft && validateAddress(trimmedDraft, buyChainId).valid,
3539
4323
  [trimmedDraft, buyChainId]
3540
4324
  );
3541
- const formatHint = useMemo8(() => getAddressFormatHint(buyChainId), [buyChainId]);
3542
- const chainName = useMemo8(() => getChainName(buyChainId), [buyChainId]);
3543
- const startEditing = useCallback7(() => {
4325
+ const formatHint = useMemo10(() => getAddressFormatHint(buyChainId), [buyChainId]);
4326
+ const chainName = useMemo10(() => getChainName(buyChainId), [buyChainId]);
4327
+ const startEditing = useCallback9(() => {
3544
4328
  setDraft(receiveAddress ?? "");
3545
4329
  setHasInteracted(false);
3546
4330
  setIsEditing(true);
3547
4331
  }, [receiveAddress]);
3548
- const handleChange = useCallback7((value) => {
4332
+ const handleChange = useCallback9((value) => {
3549
4333
  setDraft(value);
3550
4334
  setHasInteracted(true);
3551
4335
  }, []);
3552
- const handleAccept = useCallback7(() => {
4336
+ const handleAccept = useCallback9(() => {
3553
4337
  if (!validateAddress(trimmedDraft, buyChainId).valid) return;
3554
4338
  onSetCustomReceiveAddress(trimmedDraft);
3555
4339
  setIsEditing(false);
3556
4340
  setHasInteracted(false);
3557
4341
  }, [trimmedDraft, buyChainId, onSetCustomReceiveAddress]);
3558
- const handleReset = useCallback7(() => {
4342
+ const handleReset = useCallback9(() => {
3559
4343
  onSetCustomReceiveAddress("");
3560
4344
  setDraft("");
3561
4345
  setHasInteracted(false);
@@ -3563,132 +4347,284 @@ var ReceiveAddressRow = ({
3563
4347
  }, [onSetCustomReceiveAddress]);
3564
4348
  const showReset = !!draft || isEditing;
3565
4349
  if (!showInput) {
3566
- return /* @__PURE__ */ jsxs5(
4350
+ return /* @__PURE__ */ jsxs7("div", { className: "ssw-receive-row-resolved", children: [
4351
+ /* @__PURE__ */ jsx7("span", { className: "ssw-receive-label", children: "Receive address" }),
4352
+ /* @__PURE__ */ jsx7("div", { className: "ssw-receive-resolved-value", children: isResolving ? /* @__PURE__ */ jsx7("span", { className: "ssw-balance-skeleton" }) : showAttention ? (
4353
+ // Locked only - an unlocked row with no address shows the input instead
4354
+ /* @__PURE__ */ jsxs7("span", { className: "ssw-receive-error", children: [
4355
+ "Not valid for ",
4356
+ chainName
4357
+ ] })
4358
+ ) : /* @__PURE__ */ jsxs7(Fragment5, { children: [
4359
+ /* @__PURE__ */ jsx7("span", { className: "ssw-receive-address", children: truncateAddress(receiveAddress ?? "", 6) }),
4360
+ !isLocked && /* @__PURE__ */ jsx7(
4361
+ "button",
4362
+ {
4363
+ className: "ssw-receive-edit-btn",
4364
+ onClick: startEditing,
4365
+ type: "button",
4366
+ "aria-label": "Edit receive address",
4367
+ children: /* @__PURE__ */ jsxs7(
4368
+ "svg",
4369
+ {
4370
+ width: "14",
4371
+ height: "14",
4372
+ viewBox: "0 0 24 24",
4373
+ fill: "none",
4374
+ stroke: "currentColor",
4375
+ strokeWidth: "2",
4376
+ children: [
4377
+ /* @__PURE__ */ jsx7("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
4378
+ /* @__PURE__ */ jsx7("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
4379
+ ]
4380
+ }
4381
+ )
4382
+ }
4383
+ )
4384
+ ] }) })
4385
+ ] });
4386
+ }
4387
+ return /* @__PURE__ */ jsxs7("div", { className: "ssw-receive-row-input", children: [
4388
+ /* @__PURE__ */ jsx7("div", { className: "ssw-receive-header", children: /* @__PURE__ */ jsx7("span", { className: "ssw-receive-label", children: "Receive address" }) }),
4389
+ /* @__PURE__ */ jsxs7(
3567
4390
  "div",
3568
4391
  {
3569
- className: `ssw-receive-row ssw-receive-row-resolved${showAttention ? " ssw-receive-row-invalid" : ""}`,
4392
+ className: `ssw-receive-input-wrapper${!validation.valid && hasInteracted ? " ssw-invalid" : ""}`,
3570
4393
  children: [
3571
- /* @__PURE__ */ jsx5("span", { className: "ssw-receive-label", children: "Receive address" }),
3572
- /* @__PURE__ */ jsx5("div", { className: "ssw-receive-resolved-value", children: isResolving ? /* @__PURE__ */ jsx5("span", { className: "ssw-balance-skeleton" }) : showAttention ? (
3573
- // Locked only - an unlocked row with no address shows the input instead
3574
- /* @__PURE__ */ jsxs5("span", { className: "ssw-receive-error", children: [
3575
- "Not valid for ",
3576
- chainName
3577
- ] })
3578
- ) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
3579
- /* @__PURE__ */ jsx5("span", { className: "ssw-receive-address", children: truncateAddress(receiveAddress ?? "", 6) }),
3580
- !isLocked && /* @__PURE__ */ jsx5(
4394
+ /* @__PURE__ */ jsx7(
4395
+ "input",
4396
+ {
4397
+ ref: inputRef,
4398
+ type: "text",
4399
+ className: "ssw-receive-input",
4400
+ placeholder: formatHint,
4401
+ value: draft,
4402
+ onChange: (e) => handleChange(e.target.value),
4403
+ spellCheck: false,
4404
+ autoComplete: "off",
4405
+ "aria-label": "Receive address"
4406
+ }
4407
+ ),
4408
+ /* @__PURE__ */ jsxs7("div", { className: "ssw-receive-inline-actions", children: [
4409
+ /* @__PURE__ */ jsx7(
3581
4410
  "button",
3582
4411
  {
3583
- className: "ssw-receive-edit-btn",
3584
- onClick: startEditing,
4412
+ className: "ssw-receive-icon-btn ssw-receive-accept",
4413
+ onClick: handleAccept,
4414
+ onMouseDown: (e) => e.preventDefault(),
4415
+ disabled: !canAccept,
3585
4416
  type: "button",
3586
- "aria-label": "Edit receive address",
3587
- children: /* @__PURE__ */ jsxs5(
4417
+ "aria-label": "Accept address",
4418
+ children: /* @__PURE__ */ jsx7(
3588
4419
  "svg",
3589
4420
  {
3590
- width: "14",
3591
- height: "14",
4421
+ width: "16",
4422
+ height: "16",
3592
4423
  viewBox: "0 0 24 24",
3593
4424
  fill: "none",
3594
4425
  stroke: "currentColor",
3595
- strokeWidth: "2",
3596
- children: [
3597
- /* @__PURE__ */ jsx5("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
3598
- /* @__PURE__ */ jsx5("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
3599
- ]
4426
+ strokeWidth: "2.5",
4427
+ children: /* @__PURE__ */ jsx7("path", { d: "M20 6L9 17l-5-5" })
4428
+ }
4429
+ )
4430
+ }
4431
+ ),
4432
+ showReset && /* @__PURE__ */ jsx7(
4433
+ "button",
4434
+ {
4435
+ className: "ssw-receive-icon-btn ssw-receive-reset",
4436
+ onClick: handleReset,
4437
+ onMouseDown: (e) => e.preventDefault(),
4438
+ type: "button",
4439
+ "aria-label": "Reset address",
4440
+ children: /* @__PURE__ */ jsx7(
4441
+ "svg",
4442
+ {
4443
+ width: "16",
4444
+ height: "16",
4445
+ viewBox: "0 0 24 24",
4446
+ fill: "none",
4447
+ stroke: "currentColor",
4448
+ strokeWidth: "2.5",
4449
+ children: /* @__PURE__ */ jsx7("path", { d: "M18 6L6 18M6 6l12 12" })
3600
4450
  }
3601
4451
  )
3602
4452
  }
3603
4453
  )
3604
- ] }) })
4454
+ ] })
3605
4455
  ]
3606
4456
  }
3607
- );
3608
- }
3609
- return /* @__PURE__ */ jsxs5(
3610
- "div",
3611
- {
3612
- className: `ssw-receive-row ssw-receive-row-input${showAttention ? " ssw-attention" : ""}`,
3613
- children: [
3614
- /* @__PURE__ */ jsx5("div", { className: "ssw-receive-header", children: /* @__PURE__ */ jsx5("span", { className: "ssw-receive-label", children: "Receive address" }) }),
3615
- /* @__PURE__ */ jsxs5(
3616
- "div",
4457
+ ),
4458
+ !validation.valid && hasInteracted && validation.error && /* @__PURE__ */ jsx7("span", { className: "ssw-receive-error", children: validation.error })
4459
+ ] });
4460
+ };
4461
+
4462
+ // src/components/RefundAddressRow.tsx
4463
+ import { useCallback as useCallback10, useLayoutEffect as useLayoutEffect2, useMemo as useMemo11, useRef as useRef10, useState as useState7 } from "react";
4464
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
4465
+ var RefundAddressRow = ({
4466
+ refundAddress,
4467
+ sellChainId,
4468
+ onSetCustomRefundAddress
4469
+ }) => {
4470
+ const [isEditing, setIsEditing] = useState7(false);
4471
+ const [draft, setDraft] = useState7("");
4472
+ const [hasInteracted, setHasInteracted] = useState7(false);
4473
+ const inputRef = useRef10(null);
4474
+ const showInput = !refundAddress || isEditing;
4475
+ useLayoutEffect2(() => {
4476
+ if (isEditing) inputRef.current?.focus();
4477
+ }, [isEditing]);
4478
+ useLayoutEffect2(() => {
4479
+ setDraft("");
4480
+ setHasInteracted(false);
4481
+ setIsEditing(false);
4482
+ }, [sellChainId]);
4483
+ const trimmedDraft = useMemo11(() => draft.trim(), [draft]);
4484
+ const validation = useMemo11(() => {
4485
+ if (!trimmedDraft || !hasInteracted) return { valid: true, error: void 0 };
4486
+ return validateAddress(trimmedDraft, sellChainId);
4487
+ }, [trimmedDraft, hasInteracted, sellChainId]);
4488
+ const canAccept = useMemo11(
4489
+ () => !!trimmedDraft && validateAddress(trimmedDraft, sellChainId).valid,
4490
+ [trimmedDraft, sellChainId]
4491
+ );
4492
+ const formatHint = useMemo11(() => getAddressFormatHint(sellChainId), [sellChainId]);
4493
+ const chainName = useMemo11(() => getChainName(sellChainId), [sellChainId]);
4494
+ const startEditing = useCallback10(() => {
4495
+ setDraft(refundAddress ?? "");
4496
+ setHasInteracted(false);
4497
+ setIsEditing(true);
4498
+ }, [refundAddress]);
4499
+ const handleChange = useCallback10((value) => {
4500
+ setDraft(value);
4501
+ setHasInteracted(true);
4502
+ }, []);
4503
+ const handleAccept = useCallback10(() => {
4504
+ if (!validateAddress(trimmedDraft, sellChainId).valid) return;
4505
+ onSetCustomRefundAddress(trimmedDraft);
4506
+ setIsEditing(false);
4507
+ setHasInteracted(false);
4508
+ }, [trimmedDraft, sellChainId, onSetCustomRefundAddress]);
4509
+ const handleReset = useCallback10(() => {
4510
+ onSetCustomRefundAddress("");
4511
+ setDraft("");
4512
+ setHasInteracted(false);
4513
+ setIsEditing(false);
4514
+ }, [onSetCustomRefundAddress]);
4515
+ if (!showInput) {
4516
+ return /* @__PURE__ */ jsxs8("div", { className: "ssw-receive-row-resolved", children: [
4517
+ /* @__PURE__ */ jsx8("span", { className: "ssw-receive-label", children: "Refund address" }),
4518
+ /* @__PURE__ */ jsxs8("div", { className: "ssw-receive-resolved-value", children: [
4519
+ /* @__PURE__ */ jsx8("span", { className: "ssw-receive-address", children: truncateAddress(refundAddress ?? "", 6) }),
4520
+ /* @__PURE__ */ jsx8(
4521
+ "button",
3617
4522
  {
3618
- className: `ssw-receive-input-wrapper${!validation.valid && hasInteracted ? " ssw-invalid" : ""}`,
3619
- children: [
3620
- /* @__PURE__ */ jsx5(
3621
- "input",
3622
- {
3623
- ref: inputRef,
3624
- type: "text",
3625
- className: "ssw-receive-input",
3626
- placeholder: formatHint,
3627
- value: draft,
3628
- onChange: (e) => handleChange(e.target.value),
3629
- spellCheck: false,
3630
- autoComplete: "off",
3631
- "aria-label": "Receive address"
3632
- }
3633
- ),
3634
- /* @__PURE__ */ jsxs5("div", { className: "ssw-receive-inline-actions", children: [
3635
- /* @__PURE__ */ jsx5(
3636
- "button",
4523
+ className: "ssw-receive-edit-btn",
4524
+ onClick: startEditing,
4525
+ type: "button",
4526
+ "aria-label": "Edit refund address",
4527
+ children: /* @__PURE__ */ jsxs8(
4528
+ "svg",
4529
+ {
4530
+ width: "14",
4531
+ height: "14",
4532
+ viewBox: "0 0 24 24",
4533
+ fill: "none",
4534
+ stroke: "currentColor",
4535
+ strokeWidth: "2",
4536
+ children: [
4537
+ /* @__PURE__ */ jsx8("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
4538
+ /* @__PURE__ */ jsx8("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
4539
+ ]
4540
+ }
4541
+ )
4542
+ }
4543
+ )
4544
+ ] })
4545
+ ] });
4546
+ }
4547
+ return /* @__PURE__ */ jsxs8("div", { className: "ssw-receive-row-input", children: [
4548
+ /* @__PURE__ */ jsx8("div", { className: "ssw-receive-header", children: /* @__PURE__ */ jsx8("span", { className: "ssw-receive-label", children: "Refund address" }) }),
4549
+ /* @__PURE__ */ jsxs8(
4550
+ "div",
4551
+ {
4552
+ className: `ssw-receive-input-wrapper${!validation.valid && hasInteracted ? " ssw-invalid" : ""}`,
4553
+ children: [
4554
+ /* @__PURE__ */ jsx8(
4555
+ "input",
4556
+ {
4557
+ ref: inputRef,
4558
+ type: "text",
4559
+ className: "ssw-receive-input",
4560
+ placeholder: formatHint,
4561
+ value: draft,
4562
+ onChange: (e) => handleChange(e.target.value),
4563
+ spellCheck: false,
4564
+ autoComplete: "off",
4565
+ "aria-label": "Refund address"
4566
+ }
4567
+ ),
4568
+ /* @__PURE__ */ jsxs8("div", { className: "ssw-receive-inline-actions", children: [
4569
+ /* @__PURE__ */ jsx8(
4570
+ "button",
4571
+ {
4572
+ className: "ssw-receive-icon-btn ssw-receive-accept",
4573
+ onClick: handleAccept,
4574
+ onMouseDown: (e) => e.preventDefault(),
4575
+ disabled: !canAccept,
4576
+ type: "button",
4577
+ "aria-label": "Accept refund address",
4578
+ children: /* @__PURE__ */ jsx8(
4579
+ "svg",
3637
4580
  {
3638
- className: "ssw-receive-icon-btn ssw-receive-accept",
3639
- onClick: handleAccept,
3640
- onMouseDown: (e) => e.preventDefault(),
3641
- disabled: !canAccept,
3642
- type: "button",
3643
- "aria-label": "Accept address",
3644
- children: /* @__PURE__ */ jsx5(
3645
- "svg",
3646
- {
3647
- width: "16",
3648
- height: "16",
3649
- viewBox: "0 0 24 24",
3650
- fill: "none",
3651
- stroke: "currentColor",
3652
- strokeWidth: "2.5",
3653
- children: /* @__PURE__ */ jsx5("path", { d: "M20 6L9 17l-5-5" })
3654
- }
3655
- )
4581
+ width: "16",
4582
+ height: "16",
4583
+ viewBox: "0 0 24 24",
4584
+ fill: "none",
4585
+ stroke: "currentColor",
4586
+ strokeWidth: "2.5",
4587
+ children: /* @__PURE__ */ jsx8("path", { d: "M20 6L9 17l-5-5" })
3656
4588
  }
3657
- ),
3658
- showReset && /* @__PURE__ */ jsx5(
3659
- "button",
4589
+ )
4590
+ }
4591
+ ),
4592
+ (!!draft || isEditing) && /* @__PURE__ */ jsx8(
4593
+ "button",
4594
+ {
4595
+ className: "ssw-receive-icon-btn ssw-receive-reset",
4596
+ onClick: handleReset,
4597
+ onMouseDown: (e) => e.preventDefault(),
4598
+ type: "button",
4599
+ "aria-label": "Reset refund address",
4600
+ children: /* @__PURE__ */ jsx8(
4601
+ "svg",
3660
4602
  {
3661
- className: "ssw-receive-icon-btn ssw-receive-reset",
3662
- onClick: handleReset,
3663
- onMouseDown: (e) => e.preventDefault(),
3664
- type: "button",
3665
- "aria-label": "Reset address",
3666
- children: /* @__PURE__ */ jsx5(
3667
- "svg",
3668
- {
3669
- width: "16",
3670
- height: "16",
3671
- viewBox: "0 0 24 24",
3672
- fill: "none",
3673
- stroke: "currentColor",
3674
- strokeWidth: "2.5",
3675
- children: /* @__PURE__ */ jsx5("path", { d: "M18 6L6 18M6 6l12 12" })
3676
- }
3677
- )
4603
+ width: "16",
4604
+ height: "16",
4605
+ viewBox: "0 0 24 24",
4606
+ fill: "none",
4607
+ stroke: "currentColor",
4608
+ strokeWidth: "2.5",
4609
+ children: /* @__PURE__ */ jsx8("path", { d: "M18 6L6 18M6 6l12 12" })
3678
4610
  }
3679
4611
  )
3680
- ] })
3681
- ]
3682
- }
3683
- ),
3684
- !validation.valid && hasInteracted && validation.error && /* @__PURE__ */ jsx5("span", { className: "ssw-receive-error", children: validation.error })
3685
- ]
3686
- }
3687
- );
4612
+ }
4613
+ )
4614
+ ] })
4615
+ ]
4616
+ }
4617
+ ),
4618
+ !validation.valid && hasInteracted && validation.error ? /* @__PURE__ */ jsx8("span", { className: "ssw-receive-error", children: validation.error }) : /* @__PURE__ */ jsxs8("span", { className: "ssw-receive-hint", children: [
4619
+ "Your ",
4620
+ chainName,
4621
+ " address - funds return here if the swap fails"
4622
+ ] })
4623
+ ] });
3688
4624
  };
3689
4625
 
3690
4626
  // src/components/InputStep.tsx
3691
- import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
4627
+ import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
3692
4628
  var InputStep = ({
3693
4629
  displayValues,
3694
4630
  onOpenTokenModal,
@@ -3707,8 +4643,11 @@ var InputStep = ({
3707
4643
  const isQuoting = SwapMachineCtx.useSelector((s) => s.matches("quoting"));
3708
4644
  const {
3709
4645
  sendAddress,
4646
+ walletSendAddress,
4647
+ setCustomRefundAddress,
3710
4648
  receiveAddress,
3711
4649
  isReceiveAddressResolving,
4650
+ isReceiveAddressBlocked,
3712
4651
  setCustomReceiveAddress,
3713
4652
  evm,
3714
4653
  bitcoin: bitcoin3,
@@ -3722,11 +4661,11 @@ var InputStep = ({
3722
4661
  const isSellAmountReadOnly = displayValues.isExactOutput && isBuyAmountLocked;
3723
4662
  const isSellAmountPending = displayValues.isExactOutput && displayValues.isLoadingRates;
3724
4663
  const isBuyAmountPending = !displayValues.isExactOutput && displayValues.isLoadingRates;
3725
- const sellAmountCrypto = useMemo9(
4664
+ const sellAmountCrypto = useMemo12(
3726
4665
  () => displayValues.sellAmountBaseUnit ? formatAmount(displayValues.sellAmountBaseUnit, context.sellAsset.precision, 6) : "",
3727
4666
  [displayValues.sellAmountBaseUnit, context.sellAsset.precision]
3728
4667
  );
3729
- const buyAmountValue = useMemo9(() => {
4668
+ const buyAmountValue = useMemo12(() => {
3730
4669
  if (displayValues.isExactOutput) return context.buyAmount;
3731
4670
  if (!displayValues.buyAmount) return "";
3732
4671
  return formatAmount(displayValues.buyAmount, context.buyAsset.precision);
@@ -3736,7 +4675,7 @@ var InputStep = ({
3736
4675
  context.buyAmount,
3737
4676
  context.buyAsset.precision
3738
4677
  ]);
3739
- const sellAmountValue = useMemo9(() => {
4678
+ const sellAmountValue = useMemo12(() => {
3740
4679
  if (!displayValues.isExactOutput) {
3741
4680
  return context.isSellAmountFiat ? context.sellAmountFiat : context.sellAmount;
3742
4681
  }
@@ -3756,24 +4695,40 @@ var InputStep = ({
3756
4695
  context.sellAsset.precision,
3757
4696
  sellAmountCrypto
3758
4697
  ]);
3759
- const { text: buttonText, disabled: isButtonDisabled } = useMemo9(() => {
3760
- if (isUnsupportedChain) {
3761
- if (!allowShapeshiftRedirect) return { text: "Route not supported", disabled: true };
3762
- return { text: "Proceed on ShapeShift", disabled: false };
3763
- }
3764
- if (!sendAddress) return { text: "Connect Wallet", disabled: false };
3765
- if (!receiveAddress) return { text: "Enter receive address", disabled: true };
4698
+ const selectedRate = context.selectedRate ?? displayValues.rates?.[0];
4699
+ const isDepositFlowAvailable = shouldUseDepositFlow({
4700
+ rate: selectedRate,
4701
+ hasWalletForSellChain: !!walletSendAddress
4702
+ });
4703
+ const isSellChainTypeConnected = context.isSellAssetEvm ? evm.isConnected : context.isSellAssetUtxo ? bitcoin3.isConnected : context.isSellAssetSolana ? solana3.isConnected : false;
4704
+ const needsAnAddress = !receiveAddress && !isReceiveAddressResolving || isDepositFlowAvailable && !sendAddress;
4705
+ const {
4706
+ text: buttonText,
4707
+ disabled: isButtonDisabled,
4708
+ action: buttonAction
4709
+ } = useMemo12(() => {
3766
4710
  const drivingAmount = displayValues.isExactOutput ? context.buyAmountBaseUnit : context.sellAmount;
3767
- if (!drivingAmount || drivingAmount === "0") return { text: "Enter an amount", disabled: true };
3768
- if (displayValues.isLoadingRates) return { text: "Finding rates...", disabled: true };
3769
- if (displayValues.ratesError) return { text: "No routes available", disabled: true };
3770
- if (!displayValues.rates?.length) return { text: "No routes found", disabled: true };
3771
- return { text: "Swap", disabled: false };
4711
+ return getInputCta({
4712
+ isDepositRoute: isDepositFlowAvailable,
4713
+ hasWalletForSellChain: !!walletSendAddress,
4714
+ isSellChainTypeConnected,
4715
+ isUnsupportedChain,
4716
+ allowShapeshiftRedirect,
4717
+ hasReceiveAddress: !!receiveAddress,
4718
+ hasSendAddress: !!sendAddress,
4719
+ hasAmount: !!drivingAmount && drivingAmount !== "0",
4720
+ isLoadingRates: displayValues.isLoadingRates,
4721
+ hasRates: !!displayValues.rates?.length,
4722
+ hasRatesError: !!displayValues.ratesError
4723
+ });
3772
4724
  }, [
4725
+ isDepositFlowAvailable,
4726
+ walletSendAddress,
4727
+ isSellChainTypeConnected,
3773
4728
  isUnsupportedChain,
3774
4729
  allowShapeshiftRedirect,
3775
- sendAddress,
3776
4730
  receiveAddress,
4731
+ sendAddress,
3777
4732
  context.sellAmount,
3778
4733
  displayValues.isExactOutput,
3779
4734
  context.buyAmountBaseUnit,
@@ -3781,13 +4736,13 @@ var InputStep = ({
3781
4736
  displayValues.ratesError,
3782
4737
  displayValues.rates
3783
4738
  ]);
3784
- return /* @__PURE__ */ jsxs6(Fragment4, { children: [
3785
- /* @__PURE__ */ jsxs6("div", { className: "ssw-swap-container", children: [
3786
- /* @__PURE__ */ jsxs6("div", { className: "ssw-token-section ssw-sell", children: [
3787
- /* @__PURE__ */ jsx6("div", { className: "ssw-section-header", children: /* @__PURE__ */ jsx6("span", { className: "ssw-section-label", children: "Sell" }) }),
3788
- /* @__PURE__ */ jsxs6("div", { className: "ssw-input-row", children: [
3789
- context.isSellAmountFiat && /* @__PURE__ */ jsx6("span", { className: "ssw-fiat-prefix", children: "$" }),
3790
- /* @__PURE__ */ jsx6(
4739
+ return /* @__PURE__ */ jsxs9(Fragment6, { children: [
4740
+ /* @__PURE__ */ jsxs9("div", { className: "ssw-swap-container", children: [
4741
+ /* @__PURE__ */ jsxs9("div", { className: "ssw-token-section ssw-sell", children: [
4742
+ /* @__PURE__ */ jsx9("div", { className: "ssw-section-header", children: /* @__PURE__ */ jsx9("span", { className: "ssw-section-label", children: "Sell" }) }),
4743
+ /* @__PURE__ */ jsxs9("div", { className: "ssw-input-row", children: [
4744
+ context.isSellAmountFiat && /* @__PURE__ */ jsx9("span", { className: "ssw-fiat-prefix", children: "$" }),
4745
+ /* @__PURE__ */ jsx9(
3791
4746
  "input",
3792
4747
  {
3793
4748
  type: "text",
@@ -3803,26 +4758,26 @@ var InputStep = ({
3803
4758
  }
3804
4759
  }
3805
4760
  ),
3806
- /* @__PURE__ */ jsxs6(
4761
+ /* @__PURE__ */ jsxs9(
3807
4762
  "button",
3808
4763
  {
3809
4764
  className: "ssw-token-btn",
3810
4765
  onClick: () => onOpenTokenModal("sell"),
3811
4766
  type: "button",
3812
4767
  children: [
3813
- context.sellAsset.icon ? /* @__PURE__ */ jsx6(
4768
+ context.sellAsset.icon ? /* @__PURE__ */ jsx9(
3814
4769
  "img",
3815
4770
  {
3816
4771
  src: context.sellAsset.icon,
3817
4772
  alt: context.sellAsset.symbol,
3818
4773
  className: "ssw-token-icon"
3819
4774
  }
3820
- ) : /* @__PURE__ */ jsx6("div", { className: "ssw-token-icon-placeholder", children: context.sellAsset.symbol.charAt(0) }),
3821
- /* @__PURE__ */ jsxs6("div", { className: "ssw-token-info", children: [
3822
- /* @__PURE__ */ jsx6("span", { className: "ssw-token-symbol", children: context.sellAsset.symbol }),
3823
- /* @__PURE__ */ jsx6("span", { className: "ssw-token-chain", children: displayValues.sellChainInfo?.name ?? context.sellAsset.networkName ?? context.sellAsset.name })
4775
+ ) : /* @__PURE__ */ jsx9("div", { className: "ssw-token-icon-placeholder", children: context.sellAsset.symbol.charAt(0) }),
4776
+ /* @__PURE__ */ jsxs9("div", { className: "ssw-token-info", children: [
4777
+ /* @__PURE__ */ jsx9("span", { className: "ssw-token-symbol", children: context.sellAsset.symbol }),
4778
+ /* @__PURE__ */ jsx9("span", { className: "ssw-token-chain", children: displayValues.sellChainInfo?.name ?? context.sellAsset.networkName ?? context.sellAsset.name })
3824
4779
  ] }),
3825
- /* @__PURE__ */ jsx6(
4780
+ /* @__PURE__ */ jsx9(
3826
4781
  "svg",
3827
4782
  {
3828
4783
  width: "16",
@@ -3831,23 +4786,23 @@ var InputStep = ({
3831
4786
  fill: "none",
3832
4787
  stroke: "currentColor",
3833
4788
  strokeWidth: "2",
3834
- children: /* @__PURE__ */ jsx6("path", { d: "M9 18l6-6-6-6" })
4789
+ children: /* @__PURE__ */ jsx9("path", { d: "M9 18l6-6-6-6" })
3835
4790
  }
3836
4791
  )
3837
4792
  ]
3838
4793
  }
3839
4794
  )
3840
4795
  ] }),
3841
- /* @__PURE__ */ jsxs6("div", { className: "ssw-section-footer", children: [
3842
- !displayValues.sellAssetUsdPrice ? /* @__PURE__ */ jsx6("span", { className: "ssw-usd-value" }) : /* @__PURE__ */ jsxs6(
4796
+ /* @__PURE__ */ jsxs9("div", { className: "ssw-section-footer", children: [
4797
+ !displayValues.sellAssetUsdPrice ? /* @__PURE__ */ jsx9("span", { className: "ssw-usd-value" }) : /* @__PURE__ */ jsxs9(
3843
4798
  "button",
3844
4799
  {
3845
4800
  type: "button",
3846
4801
  className: "ssw-usd-value ssw-usd-value-toggle",
3847
4802
  onClick: () => onToggleSellFiat(displayValues.sellAssetUsdPrice),
3848
4803
  children: [
3849
- /* @__PURE__ */ jsx6("span", { children: context.isSellAmountFiat ? `\u2248 ${sellAmountCrypto || "0"} ${context.sellAsset.symbol}` : displayValues.sellUsdValue }),
3850
- /* @__PURE__ */ jsx6(
4804
+ /* @__PURE__ */ jsx9("span", { children: context.isSellAmountFiat ? `\u2248 ${sellAmountCrypto || "0"} ${context.sellAsset.symbol}` : displayValues.sellUsdValue }),
4805
+ /* @__PURE__ */ jsx9(
3851
4806
  "svg",
3852
4807
  {
3853
4808
  width: "12",
@@ -3857,16 +4812,16 @@ var InputStep = ({
3857
4812
  stroke: "currentColor",
3858
4813
  strokeWidth: "2",
3859
4814
  "aria-hidden": "true",
3860
- children: /* @__PURE__ */ jsx6("path", { d: "M7 16V4M7 4L3 8M7 4l4 4M17 8v12M17 20l4-4M17 20l-4-4" })
4815
+ children: /* @__PURE__ */ jsx9("path", { d: "M7 16V4M7 4L3 8M7 4l4 4M17 8v12M17 20l4-4M17 20l-4-4" })
3861
4816
  }
3862
4817
  )
3863
4818
  ]
3864
4819
  }
3865
4820
  ),
3866
- hasAnyWalletAddress && (displayValues.isSellBalanceLoading ? /* @__PURE__ */ jsx6("span", { className: "ssw-balance-skeleton" }) : displayValues.sellAssetBalance ? /* @__PURE__ */ jsxs6("span", { className: "ssw-balance", children: [
4821
+ hasAnyWalletAddress && (displayValues.isSellBalanceLoading ? /* @__PURE__ */ jsx9("span", { className: "ssw-balance-skeleton" }) : displayValues.sellAssetBalance ? /* @__PURE__ */ jsxs9("span", { className: "ssw-balance", children: [
3867
4822
  "Balance: ",
3868
4823
  displayValues.sellAssetBalance.balanceFormatted,
3869
- displayValues.sellBalanceFiatValue && /* @__PURE__ */ jsxs6("span", { className: "ssw-balance-fiat", children: [
4824
+ displayValues.sellBalanceFiatValue && /* @__PURE__ */ jsxs9("span", { className: "ssw-balance-fiat", children: [
3870
4825
  " ",
3871
4826
  "(",
3872
4827
  displayValues.sellBalanceFiatValue,
@@ -3875,14 +4830,14 @@ var InputStep = ({
3875
4830
  ] }) : null)
3876
4831
  ] })
3877
4832
  ] }),
3878
- /* @__PURE__ */ jsx6("div", { className: "ssw-swap-divider", children: /* @__PURE__ */ jsx6(
4833
+ /* @__PURE__ */ jsx9("div", { className: "ssw-swap-divider", children: /* @__PURE__ */ jsx9(
3879
4834
  "button",
3880
4835
  {
3881
4836
  className: "ssw-swap-btn",
3882
4837
  onClick: isBuyAssetLocked ? void 0 : onSwapTokens,
3883
4838
  disabled: isBuyAssetLocked,
3884
4839
  type: "button",
3885
- children: /* @__PURE__ */ jsx6(
4840
+ children: /* @__PURE__ */ jsx9(
3886
4841
  "svg",
3887
4842
  {
3888
4843
  width: "16",
@@ -3891,15 +4846,15 @@ var InputStep = ({
3891
4846
  fill: "none",
3892
4847
  stroke: "currentColor",
3893
4848
  strokeWidth: "2",
3894
- children: /* @__PURE__ */ jsx6("path", { d: "M12 5v14M5 12l7 7 7-7" })
4849
+ children: /* @__PURE__ */ jsx9("path", { d: "M12 5v14M5 12l7 7 7-7" })
3895
4850
  }
3896
4851
  )
3897
4852
  }
3898
4853
  ) }),
3899
- /* @__PURE__ */ jsxs6("div", { className: "ssw-token-section ssw-buy", children: [
3900
- /* @__PURE__ */ jsx6("div", { className: "ssw-section-header", children: /* @__PURE__ */ jsx6("span", { className: "ssw-section-label", children: "Buy" }) }),
3901
- /* @__PURE__ */ jsxs6("div", { className: "ssw-input-row", children: [
3902
- /* @__PURE__ */ jsx6(
4854
+ /* @__PURE__ */ jsxs9("div", { className: "ssw-token-section ssw-buy", children: [
4855
+ /* @__PURE__ */ jsx9("div", { className: "ssw-section-header", children: /* @__PURE__ */ jsx9("span", { className: "ssw-section-label", children: "Buy" }) }),
4856
+ /* @__PURE__ */ jsxs9("div", { className: "ssw-input-row", children: [
4857
+ /* @__PURE__ */ jsx9(
3903
4858
  "input",
3904
4859
  {
3905
4860
  type: "text",
@@ -3914,7 +4869,7 @@ var InputStep = ({
3914
4869
  }
3915
4870
  }
3916
4871
  ),
3917
- /* @__PURE__ */ jsxs6(
4872
+ /* @__PURE__ */ jsxs9(
3918
4873
  "button",
3919
4874
  {
3920
4875
  className: `ssw-token-btn${isBuyAssetLocked ? " ssw-token-btn-locked" : ""}`,
@@ -3922,19 +4877,19 @@ var InputStep = ({
3922
4877
  disabled: isBuyAssetLocked,
3923
4878
  type: "button",
3924
4879
  children: [
3925
- context.buyAsset.icon ? /* @__PURE__ */ jsx6(
4880
+ context.buyAsset.icon ? /* @__PURE__ */ jsx9(
3926
4881
  "img",
3927
4882
  {
3928
4883
  src: context.buyAsset.icon,
3929
4884
  alt: context.buyAsset.symbol,
3930
4885
  className: "ssw-token-icon"
3931
4886
  }
3932
- ) : /* @__PURE__ */ jsx6("div", { className: "ssw-token-icon-placeholder", children: context.buyAsset.symbol.charAt(0) }),
3933
- /* @__PURE__ */ jsxs6("div", { className: "ssw-token-info", children: [
3934
- /* @__PURE__ */ jsx6("span", { className: "ssw-token-symbol", children: context.buyAsset.symbol }),
3935
- /* @__PURE__ */ jsx6("span", { className: "ssw-token-chain", children: displayValues.buyChainInfo?.name ?? context.buyAsset.networkName ?? context.buyAsset.name })
4887
+ ) : /* @__PURE__ */ jsx9("div", { className: "ssw-token-icon-placeholder", children: context.buyAsset.symbol.charAt(0) }),
4888
+ /* @__PURE__ */ jsxs9("div", { className: "ssw-token-info", children: [
4889
+ /* @__PURE__ */ jsx9("span", { className: "ssw-token-symbol", children: context.buyAsset.symbol }),
4890
+ /* @__PURE__ */ jsx9("span", { className: "ssw-token-chain", children: displayValues.buyChainInfo?.name ?? context.buyAsset.networkName ?? context.buyAsset.name })
3936
4891
  ] }),
3937
- !isBuyAssetLocked && /* @__PURE__ */ jsx6(
4892
+ !isBuyAssetLocked && /* @__PURE__ */ jsx9(
3938
4893
  "svg",
3939
4894
  {
3940
4895
  width: "16",
@@ -3943,19 +4898,19 @@ var InputStep = ({
3943
4898
  fill: "none",
3944
4899
  stroke: "currentColor",
3945
4900
  strokeWidth: "2",
3946
- children: /* @__PURE__ */ jsx6("path", { d: "M9 18l6-6-6-6" })
4901
+ children: /* @__PURE__ */ jsx9("path", { d: "M9 18l6-6-6-6" })
3947
4902
  }
3948
4903
  )
3949
4904
  ]
3950
4905
  }
3951
4906
  )
3952
4907
  ] }),
3953
- /* @__PURE__ */ jsxs6("div", { className: "ssw-section-footer", children: [
3954
- /* @__PURE__ */ jsx6("span", { className: "ssw-usd-value", children: displayValues.buyUsdValue }),
3955
- hasAnyWalletAddress && (displayValues.isBuyBalanceLoading ? /* @__PURE__ */ jsx6("span", { className: "ssw-balance-skeleton" }) : displayValues.buyAssetBalance ? /* @__PURE__ */ jsxs6("span", { className: "ssw-balance", children: [
4908
+ /* @__PURE__ */ jsxs9("div", { className: "ssw-section-footer", children: [
4909
+ /* @__PURE__ */ jsx9("span", { className: "ssw-usd-value", children: displayValues.buyUsdValue }),
4910
+ hasAnyWalletAddress && (displayValues.isBuyBalanceLoading ? /* @__PURE__ */ jsx9("span", { className: "ssw-balance-skeleton" }) : displayValues.buyAssetBalance ? /* @__PURE__ */ jsxs9("span", { className: "ssw-balance", children: [
3956
4911
  "Balance: ",
3957
4912
  displayValues.buyAssetBalance.balanceFormatted,
3958
- displayValues.buyBalanceFiatValue && /* @__PURE__ */ jsxs6("span", { className: "ssw-balance-fiat", children: [
4913
+ displayValues.buyBalanceFiatValue && /* @__PURE__ */ jsxs9("span", { className: "ssw-balance-fiat", children: [
3959
4914
  " (",
3960
4915
  displayValues.buyBalanceFiatValue,
3961
4916
  ")"
@@ -3963,18 +4918,34 @@ var InputStep = ({
3963
4918
  ] }) : null)
3964
4919
  ] })
3965
4920
  ] }),
3966
- !isUnsupportedChain && hasActiveWallet && /* @__PURE__ */ jsx6(
3967
- ReceiveAddressRow,
4921
+ (!isUnsupportedChain && hasActiveWallet || isDepositFlowAvailable) && /* @__PURE__ */ jsxs9(
4922
+ "div",
3968
4923
  {
3969
- receiveAddress,
3970
- isResolving: isReceiveAddressResolving,
3971
- buyChainId,
3972
- isLocked: isReceiveAddressLocked,
3973
- onSetCustomReceiveAddress: setCustomReceiveAddress
4924
+ className: `ssw-address-group${needsAnAddress ? " ssw-attention" : ""}${isReceiveAddressBlocked ? " ssw-address-group-invalid" : ""}`,
4925
+ children: [
4926
+ /* @__PURE__ */ jsx9(
4927
+ ReceiveAddressRow,
4928
+ {
4929
+ receiveAddress,
4930
+ isResolving: isReceiveAddressResolving,
4931
+ buyChainId,
4932
+ isLocked: isReceiveAddressLocked,
4933
+ onSetCustomReceiveAddress: setCustomReceiveAddress
4934
+ }
4935
+ ),
4936
+ isDepositFlowAvailable && /* @__PURE__ */ jsx9(
4937
+ RefundAddressRow,
4938
+ {
4939
+ refundAddress: sendAddress,
4940
+ sellChainId: context.sellAsset.chainId,
4941
+ onSetCustomRefundAddress: setCustomRefundAddress
4942
+ }
4943
+ )
4944
+ ]
3974
4945
  }
3975
4946
  )
3976
4947
  ] }),
3977
- amountBaseUnit && amountBaseUnit !== "0" && (displayValues.rates?.length || displayValues.isLoadingRates) && /* @__PURE__ */ jsx6("div", { className: "ssw-quotes", children: /* @__PURE__ */ jsx6(
4948
+ amountBaseUnit && amountBaseUnit !== "0" && (displayValues.rates?.length || displayValues.isLoadingRates) && /* @__PURE__ */ jsx9("div", { className: "ssw-quotes", children: /* @__PURE__ */ jsx9(
3978
4949
  QuoteSelector,
3979
4950
  {
3980
4951
  rates: displayValues.rates ?? [],
@@ -3990,20 +4961,20 @@ var InputStep = ({
3990
4961
  buyAssetUsdPrice: displayValues.buyAssetUsdPrice
3991
4962
  }
3992
4963
  ) }),
3993
- displayValues.networkFeeDisplay && /* @__PURE__ */ jsxs6("div", { className: "ssw-network-fee", children: [
3994
- /* @__PURE__ */ jsx6("span", { className: "ssw-network-fee-label", children: "Est. network fee" }),
3995
- /* @__PURE__ */ jsx6("span", { className: "ssw-network-fee-value", children: displayValues.networkFeeDisplay })
4964
+ displayValues.networkFeeDisplay && /* @__PURE__ */ jsxs9("div", { className: "ssw-network-fee", children: [
4965
+ /* @__PURE__ */ jsx9("span", { className: "ssw-network-fee-label", children: "Est. network fee" }),
4966
+ /* @__PURE__ */ jsx9("span", { className: "ssw-network-fee-value", children: displayValues.networkFeeDisplay })
3996
4967
  ] }),
3997
- /* @__PURE__ */ jsx6(
4968
+ /* @__PURE__ */ jsx9(
3998
4969
  "button",
3999
4970
  {
4000
- className: `ssw-action-btn ${isUnsupportedChain ? "ssw-secondary" : ""}`,
4971
+ className: `ssw-action-btn ${buttonAction === "redirect" ? "ssw-secondary" : ""}`,
4001
4972
  disabled: isButtonDisabled || isQuoting,
4002
- onClick: onButtonClick,
4973
+ onClick: () => onButtonClick(buttonAction),
4003
4974
  type: "button",
4004
4975
  style: isQuoting ? { opacity: 0.7 } : void 0,
4005
- children: isQuoting ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
4006
- /* @__PURE__ */ jsxs6(
4976
+ children: isQuoting ? /* @__PURE__ */ jsxs9(Fragment6, { children: [
4977
+ /* @__PURE__ */ jsxs9(
4007
4978
  "svg",
4008
4979
  {
4009
4980
  className: "ssw-spinner",
@@ -4015,24 +4986,37 @@ var InputStep = ({
4015
4986
  strokeWidth: "2",
4016
4987
  style: { display: "inline-block", verticalAlign: "middle", marginRight: "6px" },
4017
4988
  children: [
4018
- /* @__PURE__ */ jsx6("circle", { cx: "12", cy: "12", r: "10", opacity: "0.25" }),
4019
- /* @__PURE__ */ jsx6("path", { d: "M12 2a10 10 0 0 1 10 10" })
4989
+ /* @__PURE__ */ jsx9("circle", { cx: "12", cy: "12", r: "10", opacity: "0.25" }),
4990
+ /* @__PURE__ */ jsx9("path", { d: "M12 2a10 10 0 0 1 10 10" })
4020
4991
  ]
4021
4992
  }
4022
4993
  ),
4023
4994
  "Fetching Quote\u2026"
4024
4995
  ] }) : buttonText
4025
4996
  }
4026
- )
4997
+ ),
4998
+ isUnsupportedChain && isDepositFlowAvailable && allowShapeshiftRedirect && buttonAction !== "redirect" && /* @__PURE__ */ jsxs9(Fragment6, { children: [
4999
+ /* @__PURE__ */ jsx9("div", { className: "ssw-or-divider", "aria-hidden": "true", children: /* @__PURE__ */ jsx9("span", { children: "or" }) }),
5000
+ /* @__PURE__ */ jsx9(
5001
+ "button",
5002
+ {
5003
+ className: "ssw-action-btn ssw-secondary",
5004
+ disabled: isQuoting,
5005
+ onClick: () => onButtonClick("redirect"),
5006
+ type: "button",
5007
+ children: "Proceed on ShapeShift"
5008
+ }
5009
+ )
5010
+ ] })
4027
5011
  ] });
4028
5012
  };
4029
5013
 
4030
5014
  // src/components/SettingsModal.tsx
4031
- import { useCallback as useCallback8, useEffect as useEffect7, useState as useState5 } from "react";
4032
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
5015
+ import { useCallback as useCallback11, useEffect as useEffect11, useState as useState8 } from "react";
5016
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
4033
5017
  var SLIPPAGE_PRESETS = ["0.1", "0.5", "1.0"];
4034
5018
  var useLockBodyScroll2 = (isLocked) => {
4035
- useEffect7(() => {
5019
+ useEffect11(() => {
4036
5020
  if (!isLocked) return;
4037
5021
  const originalOverflow = document.body.style.overflow;
4038
5022
  document.body.style.overflow = "hidden";
@@ -4044,9 +5028,9 @@ var useLockBodyScroll2 = (isLocked) => {
4044
5028
  var SettingsModal = ({ isOpen, onClose, onSlippageChange }) => {
4045
5029
  const slippage = SwapMachineCtx.useSelector((s) => s.context.slippage);
4046
5030
  useLockBodyScroll2(isOpen);
4047
- const [customSlippage, setCustomSlippage] = useState5("");
4048
- const [isCustom, setIsCustom] = useState5(!SLIPPAGE_PRESETS.includes(slippage));
4049
- const handlePresetClick = useCallback8(
5031
+ const [customSlippage, setCustomSlippage] = useState8("");
5032
+ const [isCustom, setIsCustom] = useState8(!SLIPPAGE_PRESETS.includes(slippage));
5033
+ const handlePresetClick = useCallback11(
4050
5034
  (preset) => {
4051
5035
  setIsCustom(false);
4052
5036
  setCustomSlippage("");
@@ -4054,7 +5038,7 @@ var SettingsModal = ({ isOpen, onClose, onSlippageChange }) => {
4054
5038
  },
4055
5039
  [onSlippageChange]
4056
5040
  );
4057
- const handleCustomChange = useCallback8(
5041
+ const handleCustomChange = useCallback11(
4058
5042
  (value) => {
4059
5043
  const sanitized = value.replace(/[^0-9.]/g, "");
4060
5044
  const parts = sanitized.split(".");
@@ -4068,7 +5052,7 @@ var SettingsModal = ({ isOpen, onClose, onSlippageChange }) => {
4068
5052
  },
4069
5053
  [onSlippageChange]
4070
5054
  );
4071
- const handleBackdropClick = useCallback8(
5055
+ const handleBackdropClick = useCallback11(
4072
5056
  (e) => {
4073
5057
  if (e.target === e.currentTarget) {
4074
5058
  onClose();
@@ -4082,7 +5066,7 @@ var SettingsModal = ({ isOpen, onClose, onSlippageChange }) => {
4082
5066
  const isVeryHighSlippage = currentSlippageNum > 5;
4083
5067
  return (
4084
5068
  // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
4085
- /* @__PURE__ */ jsx7(
5069
+ /* @__PURE__ */ jsx10(
4086
5070
  "div",
4087
5071
  {
4088
5072
  className: "ssw-modal-backdrop",
@@ -4091,10 +5075,10 @@ var SettingsModal = ({ isOpen, onClose, onSlippageChange }) => {
4091
5075
  role: "dialog",
4092
5076
  "aria-modal": "true",
4093
5077
  "aria-labelledby": "settings-modal-title",
4094
- children: /* @__PURE__ */ jsxs7("div", { className: "ssw-settings-modal", children: [
4095
- /* @__PURE__ */ jsxs7("div", { className: "ssw-modal-header", children: [
4096
- /* @__PURE__ */ jsx7("h2", { id: "settings-modal-title", className: "ssw-modal-title", children: "Settings" }),
4097
- /* @__PURE__ */ jsx7("button", { className: "ssw-modal-close", onClick: onClose, type: "button", children: /* @__PURE__ */ jsx7(
5078
+ children: /* @__PURE__ */ jsxs10("div", { className: "ssw-settings-modal", children: [
5079
+ /* @__PURE__ */ jsxs10("div", { className: "ssw-modal-header", children: [
5080
+ /* @__PURE__ */ jsx10("h2", { id: "settings-modal-title", className: "ssw-modal-title", children: "Settings" }),
5081
+ /* @__PURE__ */ jsx10("button", { className: "ssw-modal-close", onClick: onClose, type: "button", children: /* @__PURE__ */ jsx10(
4098
5082
  "svg",
4099
5083
  {
4100
5084
  width: "20",
@@ -4103,20 +5087,20 @@ var SettingsModal = ({ isOpen, onClose, onSlippageChange }) => {
4103
5087
  fill: "none",
4104
5088
  stroke: "currentColor",
4105
5089
  strokeWidth: "2",
4106
- children: /* @__PURE__ */ jsx7("path", { d: "M18 6L6 18M6 6l12 12" })
5090
+ children: /* @__PURE__ */ jsx10("path", { d: "M18 6L6 18M6 6l12 12" })
4107
5091
  }
4108
5092
  ) })
4109
5093
  ] }),
4110
- /* @__PURE__ */ jsx7("div", { className: "ssw-settings-content", children: /* @__PURE__ */ jsxs7("div", { className: "ssw-settings-section", children: [
4111
- /* @__PURE__ */ jsxs7("div", { className: "ssw-settings-label", children: [
4112
- /* @__PURE__ */ jsx7("span", { children: "Slippage Tolerance" }),
4113
- /* @__PURE__ */ jsx7(
5094
+ /* @__PURE__ */ jsx10("div", { className: "ssw-settings-content", children: /* @__PURE__ */ jsxs10("div", { className: "ssw-settings-section", children: [
5095
+ /* @__PURE__ */ jsxs10("div", { className: "ssw-settings-label", children: [
5096
+ /* @__PURE__ */ jsx10("span", { children: "Slippage Tolerance" }),
5097
+ /* @__PURE__ */ jsx10(
4114
5098
  "button",
4115
5099
  {
4116
5100
  className: "ssw-info-btn",
4117
5101
  type: "button",
4118
5102
  title: "Maximum price difference you're willing to accept",
4119
- children: /* @__PURE__ */ jsxs7(
5103
+ children: /* @__PURE__ */ jsxs10(
4120
5104
  "svg",
4121
5105
  {
4122
5106
  width: "14",
@@ -4126,16 +5110,16 @@ var SettingsModal = ({ isOpen, onClose, onSlippageChange }) => {
4126
5110
  stroke: "currentColor",
4127
5111
  strokeWidth: "2",
4128
5112
  children: [
4129
- /* @__PURE__ */ jsx7("circle", { cx: "12", cy: "12", r: "10" }),
4130
- /* @__PURE__ */ jsx7("path", { d: "M12 16v-4M12 8h.01" })
5113
+ /* @__PURE__ */ jsx10("circle", { cx: "12", cy: "12", r: "10" }),
5114
+ /* @__PURE__ */ jsx10("path", { d: "M12 16v-4M12 8h.01" })
4131
5115
  ]
4132
5116
  }
4133
5117
  )
4134
5118
  }
4135
5119
  )
4136
5120
  ] }),
4137
- /* @__PURE__ */ jsxs7("div", { className: "ssw-slippage-options", children: [
4138
- SLIPPAGE_PRESETS.map((preset) => /* @__PURE__ */ jsxs7(
5121
+ /* @__PURE__ */ jsxs10("div", { className: "ssw-slippage-options", children: [
5122
+ SLIPPAGE_PRESETS.map((preset) => /* @__PURE__ */ jsxs10(
4139
5123
  "button",
4140
5124
  {
4141
5125
  className: `ssw-slippage-btn ${!isCustom && slippage === preset ? "ssw-selected" : ""}`,
@@ -4148,8 +5132,8 @@ var SettingsModal = ({ isOpen, onClose, onSlippageChange }) => {
4148
5132
  },
4149
5133
  preset
4150
5134
  )),
4151
- /* @__PURE__ */ jsxs7("div", { className: `ssw-slippage-custom ${isCustom ? "ssw-selected" : ""}`, children: [
4152
- /* @__PURE__ */ jsx7(
5135
+ /* @__PURE__ */ jsxs10("div", { className: `ssw-slippage-custom ${isCustom ? "ssw-selected" : ""}`, children: [
5136
+ /* @__PURE__ */ jsx10(
4153
5137
  "input",
4154
5138
  {
4155
5139
  type: "text",
@@ -4162,11 +5146,11 @@ var SettingsModal = ({ isOpen, onClose, onSlippageChange }) => {
4162
5146
  }
4163
5147
  }
4164
5148
  ),
4165
- /* @__PURE__ */ jsx7("span", { className: "ssw-slippage-suffix", children: "%" })
5149
+ /* @__PURE__ */ jsx10("span", { className: "ssw-slippage-suffix", children: "%" })
4166
5150
  ] })
4167
5151
  ] }),
4168
- isHighSlippage && /* @__PURE__ */ jsxs7("div", { className: `ssw-slippage-warning ${isVeryHighSlippage ? "ssw-error" : ""}`, children: [
4169
- /* @__PURE__ */ jsx7(
5152
+ isHighSlippage && /* @__PURE__ */ jsxs10("div", { className: `ssw-slippage-warning ${isVeryHighSlippage ? "ssw-error" : ""}`, children: [
5153
+ /* @__PURE__ */ jsx10(
4170
5154
  "svg",
4171
5155
  {
4172
5156
  width: "16",
@@ -4175,10 +5159,10 @@ var SettingsModal = ({ isOpen, onClose, onSlippageChange }) => {
4175
5159
  fill: "none",
4176
5160
  stroke: "currentColor",
4177
5161
  strokeWidth: "2",
4178
- children: /* @__PURE__ */ jsx7("path", { d: "M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0zM12 9v4M12 17h.01" })
5162
+ children: /* @__PURE__ */ jsx10("path", { d: "M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0zM12 9v4M12 17h.01" })
4179
5163
  }
4180
5164
  ),
4181
- /* @__PURE__ */ jsx7("span", { children: isVeryHighSlippage ? "Very high slippage. Your transaction may be frontrun." : "High slippage may result in unfavorable rates." })
5165
+ /* @__PURE__ */ jsx10("span", { children: isVeryHighSlippage ? "Very high slippage. Your transaction may be frontrun." : "High slippage may result in unfavorable rates." })
4182
5166
  ] })
4183
5167
  ] }) })
4184
5168
  ] })
@@ -4188,11 +5172,11 @@ var SettingsModal = ({ isOpen, onClose, onSlippageChange }) => {
4188
5172
  };
4189
5173
 
4190
5174
  // src/components/StatusStep.tsx
4191
- import { useMemo as useMemo10 } from "react";
4192
- import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
4193
- var ExplorerLink = ({ url }) => /* @__PURE__ */ jsxs8("a", { href: url, target: "_blank", rel: "noopener noreferrer", className: "ssw-step-explorer-link", children: [
4194
- "View on Explorer",
4195
- /* @__PURE__ */ jsx8(
5175
+ import { useMemo as useMemo13 } from "react";
5176
+ import { Fragment as Fragment7, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
5177
+ var ExplorerLink = ({ url, label }) => /* @__PURE__ */ jsxs11("a", { href: url, target: "_blank", rel: "noopener noreferrer", className: "ssw-step-explorer-link", children: [
5178
+ label,
5179
+ /* @__PURE__ */ jsx11(
4196
5180
  "svg",
4197
5181
  {
4198
5182
  width: "12",
@@ -4201,7 +5185,7 @@ var ExplorerLink = ({ url }) => /* @__PURE__ */ jsxs8("a", { href: url, target:
4201
5185
  fill: "none",
4202
5186
  stroke: "currentColor",
4203
5187
  strokeWidth: "2",
4204
- children: /* @__PURE__ */ jsx8("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6M15 3h6v6M10 14L21 3" })
5188
+ children: /* @__PURE__ */ jsx11("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6M15 3h6v6M10 14L21 3" })
4205
5189
  }
4206
5190
  )
4207
5191
  ] });
@@ -4211,20 +5195,33 @@ var StatusStep = ({ isPayment }) => {
4211
5195
  const isComplete = SwapMachineCtx.useSelector((s) => s.matches("complete"));
4212
5196
  const isError = SwapMachineCtx.useSelector((s) => s.matches("error"));
4213
5197
  const { send } = SwapMachineCtx.useActorRef();
4214
- const { sellAsset, buyAsset, txHash, error, retryCount, isSellAssetUtxo, isSellAssetSolana } = context;
4215
- const explorerUrl = useMemo10(() => {
5198
+ const {
5199
+ sellAsset,
5200
+ buyAsset,
5201
+ quote,
5202
+ txHash,
5203
+ error,
5204
+ errorSource,
5205
+ retryCount,
5206
+ isSellAssetUtxo,
5207
+ isSellAssetSolana,
5208
+ isDepositFlow
5209
+ } = context;
5210
+ const explorerLabel = isDepositFlow ? "View deposit" : "View on Explorer";
5211
+ const hasStoppedTracking = errorSource === "TRACKING_TIMEOUT";
5212
+ const explorerUrl = useMemo13(() => {
4216
5213
  if (!txHash) return void 0;
4217
5214
  if (isSellAssetUtxo) return `https://mempool.space/tx/${txHash}`;
4218
5215
  if (isSellAssetSolana) return `https://solscan.io/tx/${txHash}`;
4219
5216
  return `${sellAsset.explorerTxLink ?? "https://etherscan.io/tx/"}${txHash}`;
4220
5217
  }, [txHash, isSellAssetUtxo, isSellAssetSolana, sellAsset.explorerTxLink]);
4221
- const truncatedError = useMemo10(
5218
+ const truncatedError = useMemo13(
4222
5219
  () => error && error.length > 100 ? `${error.slice(0, 100)}\u2026` : error,
4223
5220
  [error]
4224
5221
  );
4225
- return /* @__PURE__ */ jsxs8("div", { className: "ssw-step-screen", children: [
4226
- isPolling && /* @__PURE__ */ jsxs8(Fragment5, { children: [
4227
- /* @__PURE__ */ jsx8("div", { className: "ssw-step-icon-circle ssw-ic-accent", children: /* @__PURE__ */ jsxs8(
5222
+ return /* @__PURE__ */ jsxs11("div", { className: "ssw-step-screen", children: [
5223
+ isPolling && /* @__PURE__ */ jsxs11(Fragment7, { children: [
5224
+ /* @__PURE__ */ jsx11("div", { className: "ssw-step-icon-circle ssw-ic-accent", children: /* @__PURE__ */ jsxs11(
4228
5225
  "svg",
4229
5226
  {
4230
5227
  className: "ssw-spinner",
@@ -4235,17 +5232,26 @@ var StatusStep = ({ isPayment }) => {
4235
5232
  stroke: "currentColor",
4236
5233
  strokeWidth: "2",
4237
5234
  children: [
4238
- /* @__PURE__ */ jsx8("circle", { cx: "12", cy: "12", r: "10", opacity: "0.25" }),
4239
- /* @__PURE__ */ jsx8("path", { d: "M12 2a10 10 0 0 1 10 10" })
5235
+ /* @__PURE__ */ jsx11("circle", { cx: "12", cy: "12", r: "10", opacity: "0.25" }),
5236
+ /* @__PURE__ */ jsx11("path", { d: "M12 2a10 10 0 0 1 10 10" })
4240
5237
  ]
4241
5238
  }
4242
5239
  ) }),
4243
- /* @__PURE__ */ jsx8("div", { className: "ssw-step-title", children: "Confirming Transaction" }),
4244
- /* @__PURE__ */ jsx8("div", { className: "ssw-step-subtitle", children: "Your swap is being processed\u2026" }),
4245
- explorerUrl && /* @__PURE__ */ jsx8(ExplorerLink, { url: explorerUrl })
5240
+ /* @__PURE__ */ jsx11("div", { className: "ssw-step-title", children: isDepositFlow ? "Swap in Progress" : "Confirming Transaction" }),
5241
+ /* @__PURE__ */ jsx11("div", { className: "ssw-step-subtitle", children: isDepositFlow ? `Deposit received. Waiting for ${quote?.swapperName ?? "the provider"} to send your ${buyAsset.symbol}.` : "Your swap is being processed\u2026" }),
5242
+ explorerUrl && /* @__PURE__ */ jsx11(ExplorerLink, { url: explorerUrl, label: explorerLabel }),
5243
+ isDepositFlow && !isPayment && /* @__PURE__ */ jsx11("div", { className: "ssw-step-actions", children: /* @__PURE__ */ jsx11(
5244
+ "button",
5245
+ {
5246
+ className: "ssw-action-btn ssw-secondary",
5247
+ onClick: () => send({ type: "RESET" }),
5248
+ type: "button",
5249
+ children: "New Swap"
5250
+ }
5251
+ ) })
4246
5252
  ] }),
4247
- isComplete && /* @__PURE__ */ jsxs8(Fragment5, { children: [
4248
- /* @__PURE__ */ jsx8("div", { className: "ssw-step-icon-circle ssw-ic-success", children: /* @__PURE__ */ jsx8(
5253
+ isComplete && /* @__PURE__ */ jsxs11(Fragment7, { children: [
5254
+ /* @__PURE__ */ jsx11("div", { className: "ssw-step-icon-circle ssw-ic-success", children: /* @__PURE__ */ jsx11(
4249
5255
  "svg",
4250
5256
  {
4251
5257
  width: "32",
@@ -4254,18 +5260,18 @@ var StatusStep = ({ isPayment }) => {
4254
5260
  fill: "none",
4255
5261
  stroke: "currentColor",
4256
5262
  strokeWidth: "2.5",
4257
- children: /* @__PURE__ */ jsx8("path", { d: "M20 6L9 17l-5-5" })
5263
+ children: /* @__PURE__ */ jsx11("path", { d: "M20 6L9 17l-5-5" })
4258
5264
  }
4259
5265
  ) }),
4260
- /* @__PURE__ */ jsx8("div", { className: "ssw-step-title", children: "Swap Complete!" }),
4261
- /* @__PURE__ */ jsxs8("div", { className: "ssw-step-subtitle", children: [
5266
+ /* @__PURE__ */ jsx11("div", { className: "ssw-step-title", children: "Swap Complete!" }),
5267
+ /* @__PURE__ */ jsxs11("div", { className: "ssw-step-subtitle", children: [
4262
5268
  "Swapped ",
4263
5269
  sellAsset.symbol,
4264
5270
  " for ",
4265
5271
  buyAsset.symbol
4266
5272
  ] }),
4267
- explorerUrl && /* @__PURE__ */ jsx8(ExplorerLink, { url: explorerUrl }),
4268
- !isPayment && /* @__PURE__ */ jsx8("div", { className: "ssw-step-actions", children: /* @__PURE__ */ jsx8(
5273
+ explorerUrl && /* @__PURE__ */ jsx11(ExplorerLink, { url: explorerUrl, label: explorerLabel }),
5274
+ !isPayment && /* @__PURE__ */ jsx11("div", { className: "ssw-step-actions", children: /* @__PURE__ */ jsx11(
4269
5275
  "button",
4270
5276
  {
4271
5277
  className: "ssw-action-btn",
@@ -4275,26 +5281,33 @@ var StatusStep = ({ isPayment }) => {
4275
5281
  }
4276
5282
  ) })
4277
5283
  ] }),
4278
- isError && /* @__PURE__ */ jsxs8(Fragment5, { children: [
4279
- /* @__PURE__ */ jsx8("div", { className: "ssw-step-icon-circle ssw-ic-error", children: /* @__PURE__ */ jsxs8(
4280
- "svg",
5284
+ isError && /* @__PURE__ */ jsxs11(Fragment7, { children: [
5285
+ /* @__PURE__ */ jsx11(
5286
+ "div",
4281
5287
  {
4282
- width: "32",
4283
- height: "32",
4284
- viewBox: "0 0 24 24",
4285
- fill: "none",
4286
- stroke: "currentColor",
4287
- strokeWidth: "2",
4288
- children: [
4289
- /* @__PURE__ */ jsx8("circle", { cx: "12", cy: "12", r: "10" }),
4290
- /* @__PURE__ */ jsx8("path", { d: "M15 9l-6 6M9 9l6 6" })
4291
- ]
5288
+ className: `ssw-step-icon-circle ${hasStoppedTracking ? "ssw-ic-accent" : "ssw-ic-error"}`,
5289
+ children: /* @__PURE__ */ jsxs11(
5290
+ "svg",
5291
+ {
5292
+ width: "32",
5293
+ height: "32",
5294
+ viewBox: "0 0 24 24",
5295
+ fill: "none",
5296
+ stroke: "currentColor",
5297
+ strokeWidth: "2",
5298
+ children: [
5299
+ /* @__PURE__ */ jsx11("circle", { cx: "12", cy: "12", r: "10" }),
5300
+ /* @__PURE__ */ jsx11("path", { d: hasStoppedTracking ? "M12 7v5l3 2" : "M15 9l-6 6M9 9l6 6" })
5301
+ ]
5302
+ }
5303
+ )
4292
5304
  }
4293
- ) }),
4294
- /* @__PURE__ */ jsx8("div", { className: "ssw-step-title", children: "Transaction Failed" }),
4295
- /* @__PURE__ */ jsx8("div", { className: "ssw-step-subtitle", children: truncatedError ?? "Something went wrong" }),
4296
- /* @__PURE__ */ jsxs8("div", { className: "ssw-step-actions", children: [
4297
- retryCount < 3 && /* @__PURE__ */ jsx8(
5305
+ ),
5306
+ /* @__PURE__ */ jsx11("div", { className: "ssw-step-title", children: hasStoppedTracking ? "Still Processing" : "Transaction Failed" }),
5307
+ /* @__PURE__ */ jsx11("div", { className: "ssw-step-subtitle", children: truncatedError ?? "Something went wrong" }),
5308
+ hasStoppedTracking && explorerUrl && /* @__PURE__ */ jsx11(ExplorerLink, { url: explorerUrl, label: explorerLabel }),
5309
+ /* @__PURE__ */ jsxs11("div", { className: "ssw-step-actions", children: [
5310
+ !hasStoppedTracking && retryCount < 3 && /* @__PURE__ */ jsx11(
4298
5311
  "button",
4299
5312
  {
4300
5313
  className: "ssw-action-btn",
@@ -4303,13 +5316,13 @@ var StatusStep = ({ isPayment }) => {
4303
5316
  children: "Retry"
4304
5317
  }
4305
5318
  ),
4306
- /* @__PURE__ */ jsx8(
5319
+ /* @__PURE__ */ jsx11(
4307
5320
  "button",
4308
5321
  {
4309
5322
  className: "ssw-action-btn ssw-secondary",
4310
5323
  onClick: () => send({ type: "RESET" }),
4311
5324
  type: "button",
4312
- children: "Start Over"
5325
+ children: "New Swap"
4313
5326
  }
4314
5327
  )
4315
5328
  ] })
@@ -4319,12 +5332,12 @@ var StatusStep = ({ isPayment }) => {
4319
5332
 
4320
5333
  // src/components/TokenSelectModal.tsx
4321
5334
  import { bnOrZero as bnOrZero2 } from "@shapeshiftoss/utils";
4322
- import { useCallback as useCallback9, useEffect as useEffect8, useMemo as useMemo11, useRef as useRef6, useState as useState6 } from "react";
5335
+ import { useCallback as useCallback12, useEffect as useEffect12, useMemo as useMemo14, useRef as useRef11, useState as useState9 } from "react";
4323
5336
  import { Virtuoso } from "react-virtuoso";
4324
- import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
5337
+ import { Fragment as Fragment8, jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
4325
5338
  var VISIBLE_BUFFER = 10;
4326
5339
  var useLockBodyScroll3 = (isLocked) => {
4327
- useEffect8(() => {
5340
+ useEffect12(() => {
4328
5341
  if (!isLocked) return;
4329
5342
  const originalOverflow = document.body.style.overflow;
4330
5343
  document.body.style.overflow = "hidden";
@@ -4361,10 +5374,10 @@ var TokenSelectModal = ({
4361
5374
  allowShapeshiftRedirect
4362
5375
  }) => {
4363
5376
  useLockBodyScroll3(isOpen);
4364
- const [searchQuery, setSearchQuery] = useState6("");
4365
- const [chainSearchQuery, setChainSearchQuery] = useState6("");
4366
- const [selectedChainId, setSelectedChainId] = useState6(null);
4367
- const [visibleRange, setVisibleRange] = useState6({
5377
+ const [searchQuery, setSearchQuery] = useState9("");
5378
+ const [chainSearchQuery, setChainSearchQuery] = useState9("");
5379
+ const [selectedChainId, setSelectedChainId] = useState9(null);
5380
+ const [visibleRange, setVisibleRange] = useState9({
4368
5381
  startIndex: 0,
4369
5382
  endIndex: 20
4370
5383
  });
@@ -4375,15 +5388,15 @@ var TokenSelectModal = ({
4375
5388
  const { address: solanaAddress } = useSolanaSigning();
4376
5389
  const sellAssetId = SwapMachineCtx.useSelector((s) => s.context.sellAsset.assetId);
4377
5390
  const buyAssetId = SwapMachineCtx.useSelector((s) => s.context.buyAsset.assetId);
4378
- const currentAssetIds = useMemo11(() => [sellAssetId, buyAssetId], [sellAssetId, buyAssetId]);
4379
- const chainInfoMap = useMemo11(() => {
5391
+ const currentAssetIds = useMemo14(() => [sellAssetId, buyAssetId], [sellAssetId, buyAssetId]);
5392
+ const chainInfoMap = useMemo14(() => {
4380
5393
  const map = /* @__PURE__ */ new Map();
4381
5394
  for (const chain of chains) {
4382
5395
  map.set(chain.chainId, chain);
4383
5396
  }
4384
5397
  return map;
4385
5398
  }, [chains]);
4386
- const allowedAssetChainIds = useMemo11(() => {
5399
+ const allowedAssetChainIds = useMemo14(() => {
4387
5400
  if (!allowedAssetIds || allowedAssetIds.length === 0) return void 0;
4388
5401
  const chainIds = /* @__PURE__ */ new Set();
4389
5402
  for (const asset of allAssets) {
@@ -4393,7 +5406,7 @@ var TokenSelectModal = ({
4393
5406
  }
4394
5407
  return Array.from(chainIds);
4395
5408
  }, [allowedAssetIds, allAssets]);
4396
- const filteredChains = useMemo11(() => {
5409
+ const filteredChains = useMemo14(() => {
4397
5410
  let enabledChains = chains.filter(
4398
5411
  (chain) => isWidgetSupportedChainId(chain.chainId) && !disabledChainIds.includes(chain.chainId)
4399
5412
  );
@@ -4417,7 +5430,7 @@ var TokenSelectModal = ({
4417
5430
  allowedAssetChainIds,
4418
5431
  allowShapeshiftRedirect
4419
5432
  ]);
4420
- const filteredAssets = useMemo11(() => {
5433
+ const filteredAssets = useMemo14(() => {
4421
5434
  let assets = allAssets.filter(
4422
5435
  (asset) => isWidgetSupportedChainId(asset.chainId) && !disabledAssetIds.includes(asset.assetId) && !disabledChainIds.includes(asset.chainId)
4423
5436
  );
@@ -4452,14 +5465,14 @@ var TokenSelectModal = ({
4452
5465
  allowedChainIds,
4453
5466
  allowShapeshiftRedirect
4454
5467
  ]);
4455
- const initialAssetPrecisions = useMemo11(() => {
5468
+ const initialAssetPrecisions = useMemo14(() => {
4456
5469
  const precisions = {};
4457
5470
  for (const asset of filteredAssets.slice(0, 30)) {
4458
5471
  precisions[asset.assetId] = asset.precision;
4459
5472
  }
4460
5473
  return precisions;
4461
5474
  }, [filteredAssets]);
4462
- const initialAssetIds = useMemo11(
5475
+ const initialAssetIds = useMemo14(
4463
5476
  () => filteredAssets.slice(0, 30).map((a) => a.assetId),
4464
5477
  [filteredAssets]
4465
5478
  );
@@ -4474,16 +5487,16 @@ var TokenSelectModal = ({
4474
5487
  initialAssetIds,
4475
5488
  initialAssetPrecisions
4476
5489
  );
4477
- useEffect8(() => {
5490
+ useEffect12(() => {
4478
5491
  if (isOpen && currentAssetIds.length > 0) {
4479
5492
  refetchSpecific?.(currentAssetIds);
4480
5493
  }
4481
5494
  }, [isOpen, currentAssetIds, refetchSpecific]);
4482
5495
  const { data: marketData } = useAllMarketData();
4483
- const balanceSortDoneRef = useRef6(false);
4484
- const sortedAssetsRef = useRef6(filteredAssets);
4485
- const prevFilteredRef = useRef6(filteredAssets);
4486
- const sortedAssets = useMemo11(() => {
5496
+ const balanceSortDoneRef = useRef11(false);
5497
+ const sortedAssetsRef = useRef11(filteredAssets);
5498
+ const prevFilteredRef = useRef11(filteredAssets);
5499
+ const sortedAssets = useMemo14(() => {
4487
5500
  const filterChanged = filteredAssets !== prevFilteredRef.current;
4488
5501
  if (filterChanged) {
4489
5502
  prevFilteredRef.current = filteredAssets;
@@ -4514,17 +5527,17 @@ var TokenSelectModal = ({
4514
5527
  sortedAssetsRef.current = result;
4515
5528
  return result;
4516
5529
  }, [filteredAssets, balances, marketData]);
4517
- const visibleRangeAssetIds = useMemo11(() => {
5530
+ const visibleRangeAssetIds = useMemo14(() => {
4518
5531
  const start = Math.max(0, visibleRange.startIndex - VISIBLE_BUFFER);
4519
5532
  const end = Math.min(sortedAssets.length, visibleRange.endIndex + VISIBLE_BUFFER);
4520
5533
  return sortedAssets.slice(start, end).map((a) => a.assetId);
4521
5534
  }, [sortedAssets, visibleRange]);
4522
- useEffect8(() => {
5535
+ useEffect12(() => {
4523
5536
  if (visibleRangeAssetIds.length > 0) {
4524
5537
  refetchSpecific?.(visibleRangeAssetIds);
4525
5538
  }
4526
5539
  }, [visibleRangeAssetIds, refetchSpecific]);
4527
- const handleAssetSelect = useCallback9(
5540
+ const handleAssetSelect = useCallback12(
4528
5541
  (asset) => {
4529
5542
  onSelect(asset);
4530
5543
  onClose();
@@ -4533,10 +5546,10 @@ var TokenSelectModal = ({
4533
5546
  },
4534
5547
  [onSelect, onClose]
4535
5548
  );
4536
- const handleChainSelect = useCallback9((chainId) => {
5549
+ const handleChainSelect = useCallback12((chainId) => {
4537
5550
  setSelectedChainId(chainId);
4538
5551
  }, []);
4539
- const handleBackdropClick = useCallback9(
5552
+ const handleBackdropClick = useCallback12(
4540
5553
  (e) => {
4541
5554
  if (e.target === e.currentTarget) {
4542
5555
  onClose();
@@ -4548,7 +5561,7 @@ var TokenSelectModal = ({
4548
5561
  const isLoading = isLoadingAssets || isLoadingChains;
4549
5562
  return (
4550
5563
  // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
4551
- /* @__PURE__ */ jsx9(
5564
+ /* @__PURE__ */ jsx12(
4552
5565
  "div",
4553
5566
  {
4554
5567
  className: "ssw-modal-backdrop",
@@ -4557,10 +5570,10 @@ var TokenSelectModal = ({
4557
5570
  role: "dialog",
4558
5571
  "aria-modal": "true",
4559
5572
  "aria-labelledby": "token-modal-title",
4560
- children: /* @__PURE__ */ jsxs9("div", { className: "ssw-modal", children: [
4561
- /* @__PURE__ */ jsxs9("div", { className: "ssw-modal-header", children: [
4562
- /* @__PURE__ */ jsx9("h2", { id: "token-modal-title", className: "ssw-modal-title", children: "Select Token" }),
4563
- /* @__PURE__ */ jsx9("button", { className: "ssw-modal-close", onClick: onClose, type: "button", children: /* @__PURE__ */ jsx9(
5573
+ children: /* @__PURE__ */ jsxs12("div", { className: "ssw-modal", children: [
5574
+ /* @__PURE__ */ jsxs12("div", { className: "ssw-modal-header", children: [
5575
+ /* @__PURE__ */ jsx12("h2", { id: "token-modal-title", className: "ssw-modal-title", children: "Select Token" }),
5576
+ /* @__PURE__ */ jsx12("button", { className: "ssw-modal-close", onClick: onClose, type: "button", children: /* @__PURE__ */ jsx12(
4564
5577
  "svg",
4565
5578
  {
4566
5579
  width: "20",
@@ -4569,14 +5582,14 @@ var TokenSelectModal = ({
4569
5582
  fill: "none",
4570
5583
  stroke: "currentColor",
4571
5584
  strokeWidth: "2",
4572
- children: /* @__PURE__ */ jsx9("path", { d: "M18 6L6 18M6 6l12 12" })
5585
+ children: /* @__PURE__ */ jsx12("path", { d: "M18 6L6 18M6 6l12 12" })
4573
5586
  }
4574
5587
  ) })
4575
5588
  ] }),
4576
- /* @__PURE__ */ jsxs9("div", { className: "ssw-modal-content", children: [
4577
- /* @__PURE__ */ jsxs9("div", { className: "ssw-chain-sidebar", children: [
4578
- /* @__PURE__ */ jsxs9("div", { className: "ssw-search-wrapper", children: [
4579
- /* @__PURE__ */ jsxs9(
5589
+ /* @__PURE__ */ jsxs12("div", { className: "ssw-modal-content", children: [
5590
+ /* @__PURE__ */ jsxs12("div", { className: "ssw-chain-sidebar", children: [
5591
+ /* @__PURE__ */ jsxs12("div", { className: "ssw-search-wrapper", children: [
5592
+ /* @__PURE__ */ jsxs12(
4580
5593
  "svg",
4581
5594
  {
4582
5595
  className: "ssw-search-icon",
@@ -4587,12 +5600,12 @@ var TokenSelectModal = ({
4587
5600
  stroke: "currentColor",
4588
5601
  strokeWidth: "2",
4589
5602
  children: [
4590
- /* @__PURE__ */ jsx9("circle", { cx: "11", cy: "11", r: "8" }),
4591
- /* @__PURE__ */ jsx9("path", { d: "m21 21-4.35-4.35" })
5603
+ /* @__PURE__ */ jsx12("circle", { cx: "11", cy: "11", r: "8" }),
5604
+ /* @__PURE__ */ jsx12("path", { d: "m21 21-4.35-4.35" })
4592
5605
  ]
4593
5606
  }
4594
5607
  ),
4595
- /* @__PURE__ */ jsx9(
5608
+ /* @__PURE__ */ jsx12(
4596
5609
  "input",
4597
5610
  {
4598
5611
  type: "text",
@@ -4603,24 +5616,24 @@ var TokenSelectModal = ({
4603
5616
  }
4604
5617
  )
4605
5618
  ] }),
4606
- /* @__PURE__ */ jsxs9("div", { className: "ssw-chain-list", children: [
4607
- /* @__PURE__ */ jsx9(
5619
+ /* @__PURE__ */ jsxs12("div", { className: "ssw-chain-list", children: [
5620
+ /* @__PURE__ */ jsx12(
4608
5621
  "button",
4609
5622
  {
4610
5623
  className: `ssw-chain-item ${selectedChainId === null ? "ssw-selected" : ""}`,
4611
5624
  onClick: () => handleChainSelect(null),
4612
5625
  type: "button",
4613
- children: /* @__PURE__ */ jsx9("span", { className: "ssw-chain-name", children: "All Chains" })
5626
+ children: /* @__PURE__ */ jsx12("span", { className: "ssw-chain-name", children: "All Chains" })
4614
5627
  }
4615
5628
  ),
4616
- filteredChains.map((chain) => /* @__PURE__ */ jsxs9(
5629
+ filteredChains.map((chain) => /* @__PURE__ */ jsxs12(
4617
5630
  "button",
4618
5631
  {
4619
5632
  className: `ssw-chain-item ${selectedChainId === chain.chainId ? "ssw-selected" : ""}`,
4620
5633
  onClick: () => handleChainSelect(chain.chainId),
4621
5634
  type: "button",
4622
5635
  children: [
4623
- chain.icon ? /* @__PURE__ */ jsx9("img", { src: chain.icon, alt: chain.name, className: "ssw-chain-icon" }) : /* @__PURE__ */ jsx9(
5636
+ chain.icon ? /* @__PURE__ */ jsx12("img", { src: chain.icon, alt: chain.name, className: "ssw-chain-icon" }) : /* @__PURE__ */ jsx12(
4624
5637
  "div",
4625
5638
  {
4626
5639
  className: "ssw-chain-icon-placeholder",
@@ -4628,16 +5641,16 @@ var TokenSelectModal = ({
4628
5641
  children: chain.name.charAt(0)
4629
5642
  }
4630
5643
  ),
4631
- /* @__PURE__ */ jsx9("span", { className: "ssw-chain-name", children: chain.name })
5644
+ /* @__PURE__ */ jsx12("span", { className: "ssw-chain-name", children: chain.name })
4632
5645
  ]
4633
5646
  },
4634
5647
  chain.chainId
4635
5648
  ))
4636
5649
  ] })
4637
5650
  ] }),
4638
- /* @__PURE__ */ jsxs9("div", { className: "ssw-token-panel", children: [
4639
- /* @__PURE__ */ jsxs9("div", { className: "ssw-search-wrapper", children: [
4640
- /* @__PURE__ */ jsxs9(
5651
+ /* @__PURE__ */ jsxs12("div", { className: "ssw-token-panel", children: [
5652
+ /* @__PURE__ */ jsxs12("div", { className: "ssw-search-wrapper", children: [
5653
+ /* @__PURE__ */ jsxs12(
4641
5654
  "svg",
4642
5655
  {
4643
5656
  className: "ssw-search-icon",
@@ -4648,12 +5661,12 @@ var TokenSelectModal = ({
4648
5661
  stroke: "currentColor",
4649
5662
  strokeWidth: "2",
4650
5663
  children: [
4651
- /* @__PURE__ */ jsx9("circle", { cx: "11", cy: "11", r: "8" }),
4652
- /* @__PURE__ */ jsx9("path", { d: "m21 21-4.35-4.35" })
5664
+ /* @__PURE__ */ jsx12("circle", { cx: "11", cy: "11", r: "8" }),
5665
+ /* @__PURE__ */ jsx12("path", { d: "m21 21-4.35-4.35" })
4653
5666
  ]
4654
5667
  }
4655
5668
  ),
4656
- /* @__PURE__ */ jsx9(
5669
+ /* @__PURE__ */ jsx12(
4657
5670
  "input",
4658
5671
  {
4659
5672
  type: "text",
@@ -4665,10 +5678,10 @@ var TokenSelectModal = ({
4665
5678
  }
4666
5679
  )
4667
5680
  ] }),
4668
- /* @__PURE__ */ jsx9("div", { className: "ssw-token-list", children: isLoading ? /* @__PURE__ */ jsxs9("div", { className: "ssw-loading", children: [
4669
- /* @__PURE__ */ jsx9("div", { className: "ssw-spinner" }),
4670
- /* @__PURE__ */ jsx9("span", { children: "Loading assets..." })
4671
- ] }) : sortedAssets.length === 0 ? /* @__PURE__ */ jsx9("div", { className: "ssw-empty", children: "No tokens found" }) : /* @__PURE__ */ jsx9(
5681
+ /* @__PURE__ */ jsx12("div", { className: "ssw-token-list", children: isLoading ? /* @__PURE__ */ jsxs12("div", { className: "ssw-loading", children: [
5682
+ /* @__PURE__ */ jsx12("div", { className: "ssw-spinner" }),
5683
+ /* @__PURE__ */ jsx12("span", { children: "Loading assets..." })
5684
+ ] }) : sortedAssets.length === 0 ? /* @__PURE__ */ jsx12("div", { className: "ssw-empty", children: "No tokens found" }) : /* @__PURE__ */ jsx12(
4672
5685
  Virtuoso,
4673
5686
  {
4674
5687
  data: sortedAssets,
@@ -4677,15 +5690,15 @@ var TokenSelectModal = ({
4677
5690
  itemContent: (_, asset) => {
4678
5691
  const chainInfo = chainInfoMap.get(asset.chainId);
4679
5692
  const balance = balances?.[asset.assetId];
4680
- return /* @__PURE__ */ jsxs9(
5693
+ return /* @__PURE__ */ jsxs12(
4681
5694
  "button",
4682
5695
  {
4683
5696
  className: "ssw-token-item",
4684
5697
  onClick: () => handleAssetSelect(asset),
4685
5698
  type: "button",
4686
5699
  children: [
4687
- /* @__PURE__ */ jsxs9("div", { className: "ssw-token-icon-wrapper", children: [
4688
- asset.icon ? /* @__PURE__ */ jsx9("img", { src: asset.icon, alt: asset.symbol, className: "ssw-token-icon" }) : /* @__PURE__ */ jsx9(
5700
+ /* @__PURE__ */ jsxs12("div", { className: "ssw-token-icon-wrapper", children: [
5701
+ asset.icon ? /* @__PURE__ */ jsx12("img", { src: asset.icon, alt: asset.symbol, className: "ssw-token-icon" }) : /* @__PURE__ */ jsx12(
4689
5702
  "div",
4690
5703
  {
4691
5704
  className: "ssw-token-icon-placeholder",
@@ -4693,7 +5706,7 @@ var TokenSelectModal = ({
4693
5706
  children: asset.symbol?.charAt(0) ?? "?"
4694
5707
  }
4695
5708
  ),
4696
- chainInfo?.icon && /* @__PURE__ */ jsx9(
5709
+ chainInfo?.icon && /* @__PURE__ */ jsx12(
4697
5710
  "img",
4698
5711
  {
4699
5712
  src: chainInfo.icon,
@@ -4702,19 +5715,19 @@ var TokenSelectModal = ({
4702
5715
  }
4703
5716
  )
4704
5717
  ] }),
4705
- /* @__PURE__ */ jsxs9("div", { className: "ssw-token-info", children: [
4706
- /* @__PURE__ */ jsx9("span", { className: "ssw-token-symbol", children: asset.symbol }),
4707
- /* @__PURE__ */ jsx9("span", { className: "ssw-token-name", children: chainInfo?.name ?? asset.networkName ?? asset.name })
5718
+ /* @__PURE__ */ jsxs12("div", { className: "ssw-token-info", children: [
5719
+ /* @__PURE__ */ jsx12("span", { className: "ssw-token-symbol", children: asset.symbol }),
5720
+ /* @__PURE__ */ jsx12("span", { className: "ssw-token-name", children: chainInfo?.name ?? asset.networkName ?? asset.name })
4708
5721
  ] }),
4709
- /* @__PURE__ */ jsx9("div", { className: "ssw-token-right", children: (evmAddress || bitcoinAddress || solanaAddress) && (loadingAssetIds.has(asset.assetId) ? /* @__PURE__ */ jsx9("span", { className: "ssw-token-balance-skeleton" }) : balance && balance.balance !== "0" ? /* @__PURE__ */ jsxs9(Fragment6, { children: [
4710
- marketData?.[asset.assetId]?.price && /* @__PURE__ */ jsxs9("span", { className: "ssw-token-fiat-value", children: [
5722
+ /* @__PURE__ */ jsx12("div", { className: "ssw-token-right", children: (evmAddress || bitcoinAddress || solanaAddress) && (loadingAssetIds.has(asset.assetId) ? /* @__PURE__ */ jsx12("span", { className: "ssw-token-balance-skeleton" }) : balance && balance.balance !== "0" ? /* @__PURE__ */ jsxs12(Fragment8, { children: [
5723
+ marketData?.[asset.assetId]?.price && /* @__PURE__ */ jsxs12("span", { className: "ssw-token-fiat-value", children: [
4711
5724
  "$",
4712
5725
  bnOrZero2(balance.balance).div(bnOrZero2(10).pow(asset.precision)).times(bnOrZero2(marketData[asset.assetId].price)).toNumber().toLocaleString(void 0, {
4713
5726
  minimumFractionDigits: 2,
4714
5727
  maximumFractionDigits: 2
4715
5728
  })
4716
5729
  ] }),
4717
- /* @__PURE__ */ jsx9("span", { className: "ssw-token-balance", children: balance.balanceFormatted })
5730
+ /* @__PURE__ */ jsx12("span", { className: "ssw-token-balance", children: balance.balanceFormatted })
4718
5731
  ] }) : null) })
4719
5732
  ]
4720
5733
  }
@@ -4733,7 +5746,7 @@ var TokenSelectModal = ({
4733
5746
  // src/components/WalletProvider.tsx
4734
5747
  import { useAppKit as useAppKit2 } from "@reown/appkit/react";
4735
5748
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4736
- import { useCallback as useCallback10, useEffect as useEffect9, useState as useState7 } from "react";
5749
+ import { useCallback as useCallback13, useEffect as useEffect13, useState as useState10 } from "react";
4737
5750
  import { WagmiProvider } from "wagmi";
4738
5751
 
4739
5752
  // src/config/appkit.ts
@@ -4802,28 +5815,28 @@ var initializeAppKit = (projectId) => {
4802
5815
  };
4803
5816
 
4804
5817
  // src/components/WalletProvider.tsx
4805
- import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
5818
+ import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
4806
5819
  var queryClient = new QueryClient();
4807
5820
  var AppKitWalletProvider = ({ projectId, children }) => {
4808
- const [wagmiConfig, setWagmiConfig] = useState7(
5821
+ const [wagmiConfig, setWagmiConfig] = useState10(
4809
5822
  () => isAppKitInitialized() ? getActiveWagmiConfig() : void 0
4810
5823
  );
4811
- useEffect9(() => {
5824
+ useEffect13(() => {
4812
5825
  if (projectId && !isAppKitInitialized()) initializeAppKit(projectId);
4813
5826
  if (isAppKitInitialized()) setWagmiConfig(getActiveWagmiConfig());
4814
5827
  }, [projectId]);
4815
5828
  if (!wagmiConfig) return null;
4816
- return /* @__PURE__ */ jsx10(WagmiProvider, { config: wagmiConfig, children: /* @__PURE__ */ jsx10(QueryClientProvider, { client: queryClient, children }) });
5829
+ return /* @__PURE__ */ jsx13(WagmiProvider, { config: wagmiConfig, children: /* @__PURE__ */ jsx13(QueryClientProvider, { client: queryClient, children }) });
4817
5830
  };
4818
5831
  var ConnectWalletButton = () => {
4819
5832
  const { open } = useAppKit2();
4820
- const { sendAddress } = useSwapWallet();
4821
- const handleClick = useCallback10(() => {
5833
+ const { walletSendAddress } = useSwapWallet();
5834
+ const handleClick = useCallback13(() => {
4822
5835
  open();
4823
5836
  }, [open]);
4824
- if (!sendAddress) {
4825
- return /* @__PURE__ */ jsxs10("button", { onClick: handleClick, type: "button", className: "ssw-connect-btn", children: [
4826
- /* @__PURE__ */ jsxs10(
5837
+ if (!walletSendAddress) {
5838
+ return /* @__PURE__ */ jsxs13("button", { onClick: handleClick, type: "button", className: "ssw-connect-btn", children: [
5839
+ /* @__PURE__ */ jsxs13(
4827
5840
  "svg",
4828
5841
  {
4829
5842
  width: "16",
@@ -4833,19 +5846,19 @@ var ConnectWalletButton = () => {
4833
5846
  stroke: "currentColor",
4834
5847
  strokeWidth: "2",
4835
5848
  children: [
4836
- /* @__PURE__ */ jsx10("path", { d: "M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1" }),
4837
- /* @__PURE__ */ jsx10("path", { d: "M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4" })
5849
+ /* @__PURE__ */ jsx13("path", { d: "M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1" }),
5850
+ /* @__PURE__ */ jsx13("path", { d: "M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4" })
4838
5851
  ]
4839
5852
  }
4840
5853
  ),
4841
5854
  "Connect"
4842
5855
  ] });
4843
5856
  }
4844
- return /* @__PURE__ */ jsx10("button", { onClick: handleClick, type: "button", className: "ssw-connect-btn ssw-connected", children: truncateAddress(sendAddress) });
5857
+ return /* @__PURE__ */ jsx13("button", { onClick: handleClick, type: "button", className: "ssw-connect-btn ssw-connected", children: truncateAddress(walletSendAddress) });
4845
5858
  };
4846
5859
 
4847
5860
  // src/components/SwapWidget.tsx
4848
- import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
5861
+ import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
4849
5862
  var SwapWidgetContent = ({
4850
5863
  apiClient,
4851
5864
  theme = "dark",
@@ -4865,8 +5878,11 @@ var SwapWidgetContent = ({
4865
5878
  ratesRefetchInterval
4866
5879
  }) => {
4867
5880
  const state = SwapMachineCtx.useSelector((s) => s);
4868
- const [tokenModalType, setTokenModalType] = useState8(null);
4869
- const [isSettingsOpen, setIsSettingsOpen] = useState8(false);
5881
+ const actorRef = SwapMachineCtx.useActorRef();
5882
+ const isRequotingDeposit = state.matches("quoting") && state.context.isDepositFlow && !!state.context.quote;
5883
+ const canEditSettings = state.matches("idle") || state.matches("input") || state.matches("error") || state.matches("deposit_expired");
5884
+ const [tokenModalType, setTokenModalType] = useState11(null);
5885
+ const [isSettingsOpen, setIsSettingsOpen] = useState11(false);
4870
5886
  const themeMode = typeof theme === "string" ? theme : theme.mode;
4871
5887
  const themeConfig = typeof theme === "object" ? theme : void 0;
4872
5888
  const displayValues = useSwapDisplayValues({
@@ -4889,9 +5905,31 @@ var SwapWidgetContent = ({
4889
5905
  useSwapQuoting({ apiClient, rates, sellAssetBalance });
4890
5906
  useSwapApproval();
4891
5907
  useSwapExecution();
4892
- useStatusPolling({ apiClient, onSwapSuccess, onSwapError, refetchSellBalance, refetchBuyBalance });
5908
+ useStatusPolling({ apiClient });
5909
+ useDepositPolling({ apiClient });
5910
+ useSwapCallbacks({ onSwapSuccess, onSwapError, refetchSellBalance, refetchBuyBalance });
4893
5911
  useSellFiatSync(displayValues.sellAssetUsdPrice);
4894
- const widgetStyle = useMemo12(() => {
5912
+ const hasSavedDepositRef = useRef12(false);
5913
+ useEffect14(() => {
5914
+ const snap = actorRef.getSnapshot();
5915
+ const { quote, sendAddress, receiveAddress, isDepositFlow, txHash, depositObservedAt } = snap.context;
5916
+ const isTrackingDeposit = isDepositFlow && (snap.matches("awaiting_deposit") || snap.matches("deposit_expired") || snap.matches("polling_status"));
5917
+ if (isTrackingDeposit && quote?.depositAddress && sendAddress && receiveAddress) {
5918
+ savePendingDeposit({
5919
+ quote,
5920
+ refundAddress: sendAddress,
5921
+ receiveAddress,
5922
+ sellAmountBaseUnit: snap.context.sellAmountBaseUnit,
5923
+ buyAmountBaseUnit: snap.context.buyAmountBaseUnit,
5924
+ txHash: txHash ?? void 0,
5925
+ depositObservedAt: depositObservedAt ?? void 0
5926
+ });
5927
+ hasSavedDepositRef.current = true;
5928
+ return;
5929
+ }
5930
+ if (hasSavedDepositRef.current) clearPendingDeposit();
5931
+ }, [state.value]);
5932
+ const widgetStyle = useMemo15(() => {
4895
5933
  if (!themeConfig) return void 0;
4896
5934
  const style = {};
4897
5935
  if (themeConfig.accentColor) {
@@ -4938,24 +5976,24 @@ var SwapWidgetContent = ({
4938
5976
  }
4939
5977
  return Object.keys(style).length > 0 ? style : void 0;
4940
5978
  }, [themeConfig]);
4941
- return /* @__PURE__ */ jsxs11(
5979
+ return /* @__PURE__ */ jsxs14(
4942
5980
  "div",
4943
5981
  {
4944
5982
  className: `ssw-widget ${themeMode === "light" ? "ssw-light" : "ssw-dark"}${themeConfig?.buttonVariant === "outline" ? " ssw-btn-outline" : ""}`,
4945
5983
  style: widgetStyle,
4946
5984
  children: [
4947
- /* @__PURE__ */ jsxs11("div", { className: "ssw-header", children: [
4948
- /* @__PURE__ */ jsx11("span", { className: "ssw-header-title", children: "Swap" }),
4949
- /* @__PURE__ */ jsxs11("div", { className: "ssw-header-actions", children: [
4950
- showConnectButton && /* @__PURE__ */ jsx11(ConnectWalletButton, {}),
4951
- /* @__PURE__ */ jsx11(
5985
+ /* @__PURE__ */ jsxs14("div", { className: "ssw-header", children: [
5986
+ /* @__PURE__ */ jsx14("span", { className: "ssw-header-title", children: "Swap" }),
5987
+ /* @__PURE__ */ jsxs14("div", { className: "ssw-header-actions", children: [
5988
+ showConnectButton && /* @__PURE__ */ jsx14(ConnectWalletButton, {}),
5989
+ canEditSettings && /* @__PURE__ */ jsx14(
4952
5990
  "button",
4953
5991
  {
4954
5992
  className: "ssw-settings-btn",
4955
5993
  onClick: () => setIsSettingsOpen(true),
4956
5994
  type: "button",
4957
5995
  title: "Settings",
4958
- children: /* @__PURE__ */ jsxs11(
5996
+ children: /* @__PURE__ */ jsxs14(
4959
5997
  "svg",
4960
5998
  {
4961
5999
  width: "20",
@@ -4965,8 +6003,8 @@ var SwapWidgetContent = ({
4965
6003
  stroke: "currentColor",
4966
6004
  strokeWidth: "2",
4967
6005
  children: [
4968
- /* @__PURE__ */ jsx11("circle", { cx: "12", cy: "12", r: "3" }),
4969
- /* @__PURE__ */ jsx11("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" })
6006
+ /* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "3" }),
6007
+ /* @__PURE__ */ jsx14("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" })
4970
6008
  ]
4971
6009
  }
4972
6010
  )
@@ -4974,8 +6012,8 @@ var SwapWidgetContent = ({
4974
6012
  )
4975
6013
  ] })
4976
6014
  ] }),
4977
- /* @__PURE__ */ jsxs11("div", { className: "ssw-step-container", children: [
4978
- (state.matches("idle") || state.matches("input") || state.matches("quoting")) && /* @__PURE__ */ jsx11(
6015
+ /* @__PURE__ */ jsxs14("div", { className: "ssw-step-container", children: [
6016
+ (state.matches("idle") || state.matches("input") || state.matches("quoting") && !isRequotingDeposit) && /* @__PURE__ */ jsx14(
4979
6017
  InputStep,
4980
6018
  {
4981
6019
  displayValues,
@@ -4992,14 +6030,15 @@ var SwapWidgetContent = ({
4992
6030
  allowShapeshiftRedirect: canRedirectToShapeshift
4993
6031
  }
4994
6032
  ),
4995
- (state.matches("approval_needed") || state.matches("approving")) && /* @__PURE__ */ jsx11(ApprovalStep, {}),
4996
- state.matches("executing") && /* @__PURE__ */ jsx11(ExecutionStep, {}),
4997
- (state.matches("polling_status") || state.matches("complete") || state.matches("error")) && /* @__PURE__ */ jsx11(StatusStep, { isPayment })
6033
+ (state.matches("approval_needed") || state.matches("approving")) && /* @__PURE__ */ jsx14(ApprovalStep, {}),
6034
+ state.matches("executing") && /* @__PURE__ */ jsx14(ExecutionStep, {}),
6035
+ (state.matches("awaiting_deposit") || state.matches("deposit_expired") || isRequotingDeposit) && /* @__PURE__ */ jsx14(DepositStep, {}),
6036
+ (state.matches("polling_status") || state.matches("complete") || state.matches("error")) && /* @__PURE__ */ jsx14(StatusStep, { isPayment })
4998
6037
  ] }),
4999
- showPoweredBy && /* @__PURE__ */ jsxs11("div", { className: "ssw-powered-by", children: [
6038
+ showPoweredBy && /* @__PURE__ */ jsxs14("div", { className: "ssw-powered-by", children: [
5000
6039
  "Powered by",
5001
6040
  " ",
5002
- /* @__PURE__ */ jsxs11(
6041
+ /* @__PURE__ */ jsxs14(
5003
6042
  "a",
5004
6043
  {
5005
6044
  href: "https://shapeshift.com",
@@ -5007,13 +6046,13 @@ var SwapWidgetContent = ({
5007
6046
  rel: "noopener noreferrer",
5008
6047
  className: "ssw-powered-by-link",
5009
6048
  children: [
5010
- /* @__PURE__ */ jsx11("svg", { width: "16", height: "16", viewBox: "0 0 57 62", fill: "currentColor", children: /* @__PURE__ */ jsx11("path", { d: "M51.67 5.1L48.97 21.3L39.37 10L51.67 5.1ZM49.03 28.27L51.43 37.14L33.06 42.2L49.03 28.27ZM9.03 23.8L18.88 10.93H35.99L46.92 23.8H9.03ZM45.66 26.99L27.85 42.53L9.7 26.99H45.66ZM15.58 10.01L6.78 21.51L4.08 5.17L15.58 10.01ZM22.57 42.2L4.02 37.15L6.56 28.48L22.57 42.2ZM25.99 46.43L22.49 50.28C19.53 47.46 16.26 44.96 12.78 42.83L25.99 46.43ZM42.98 42.77C39.5 44.94 36.24 47.47 33.29 50.32L29.72 46.42L42.98 42.77ZM55.73 0.06L36.42 7.75H18.42L0 0L4.18 25.3L0.17 38.99L10.65 45.26C15.61 48.23 20.06 51.94 23.86 56.3L27.94 60.97L32.23 56.06C35.9 51.84 40.18 48.22 44.95 45.29L55.23 38.99L51.52 25.31L55.73 0.06Z" }) }),
6049
+ /* @__PURE__ */ jsx14("svg", { width: "16", height: "16", viewBox: "0 0 57 62", fill: "currentColor", children: /* @__PURE__ */ jsx14("path", { d: "M51.67 5.1L48.97 21.3L39.37 10L51.67 5.1ZM49.03 28.27L51.43 37.14L33.06 42.2L49.03 28.27ZM9.03 23.8L18.88 10.93H35.99L46.92 23.8H9.03ZM45.66 26.99L27.85 42.53L9.7 26.99H45.66ZM15.58 10.01L6.78 21.51L4.08 5.17L15.58 10.01ZM22.57 42.2L4.02 37.15L6.56 28.48L22.57 42.2ZM25.99 46.43L22.49 50.28C19.53 47.46 16.26 44.96 12.78 42.83L25.99 46.43ZM42.98 42.77C39.5 44.94 36.24 47.47 33.29 50.32L29.72 46.42L42.98 42.77ZM55.73 0.06L36.42 7.75H18.42L0 0L4.18 25.3L0.17 38.99L10.65 45.26C15.61 48.23 20.06 51.94 23.86 56.3L27.94 60.97L32.23 56.06C35.9 51.84 40.18 48.22 44.95 45.29L55.23 38.99L51.52 25.31L55.73 0.06Z" }) }),
5011
6050
  "ShapeShift"
5012
6051
  ]
5013
6052
  }
5014
6053
  )
5015
6054
  ] }),
5016
- /* @__PURE__ */ jsx11(
6055
+ /* @__PURE__ */ jsx14(
5017
6056
  TokenSelectModal,
5018
6057
  {
5019
6058
  isOpen: tokenModalType !== null,
@@ -5026,7 +6065,7 @@ var SwapWidgetContent = ({
5026
6065
  allowShapeshiftRedirect: canRedirectToShapeshift
5027
6066
  }
5028
6067
  ),
5029
- /* @__PURE__ */ jsx11(
6068
+ /* @__PURE__ */ jsx14(
5030
6069
  SettingsModal,
5031
6070
  {
5032
6071
  isOpen: isSettingsOpen,
@@ -5064,17 +6103,16 @@ var SwapWidgetCore = ({
5064
6103
  const evm = useEvmSigning();
5065
6104
  const bitcoin3 = useBitcoinSigning();
5066
6105
  const solana3 = useSolanaSigning();
5067
- const [customReceiveAddress, setCustomReceiveAddress] = useState8(
5068
- defaultReceiveAddress ?? ""
5069
- );
5070
6106
  const sellChainId = SwapMachineCtx.useSelector((s) => s.context.sellAsset.chainId);
5071
6107
  const buyChainId = SwapMachineCtx.useSelector((s) => s.context.buyAsset.chainId);
6108
+ const [customReceiveAddress, setCustomReceiveAddress] = useCustomAddress(buyChainId);
6109
+ const [customRefundAddress, setCustomRefundAddress] = useCustomAddress(sellChainId);
5072
6110
  const sellChainType = getChainType(sellChainId);
5073
6111
  const buyChainType = getChainType(buyChainId);
5074
6112
  const { status: evmStatus } = useAppKitAccount3({ namespace: "eip155" });
5075
6113
  const { status: utxoStatus } = useAppKitAccount3({ namespace: "bip122" });
5076
6114
  const { status: solanaStatus } = useAppKitAccount3({ namespace: "solana" });
5077
- const isReceiveAddressResolving = useMemo12(() => {
6115
+ const isReceiveAddressResolving = useMemo15(() => {
5078
6116
  const status = (() => {
5079
6117
  if (buyChainType === "evm") return evmStatus;
5080
6118
  if (buyChainType === "utxo") return utxoStatus;
@@ -5082,27 +6120,39 @@ var SwapWidgetCore = ({
5082
6120
  })();
5083
6121
  return status === "connecting" || status === "reconnecting";
5084
6122
  }, [buyChainType, evmStatus, utxoStatus, solanaStatus]);
5085
- const addressForChain = useCallback11(
5086
- (chainType) => {
5087
- if (chainType === "evm") return evm.address;
5088
- if (chainType === "utxo") return bitcoin3.address;
5089
- if (chainType === "solana") return solana3.address;
5090
- return void 0;
6123
+ const addressForChain = useCallback14(
6124
+ (chainType, chainId) => {
6125
+ const address = (() => {
6126
+ if (chainType === "evm") return evm.address;
6127
+ if (chainType === "utxo") return bitcoin3.address;
6128
+ if (chainType === "solana") return solana3.address;
6129
+ return void 0;
6130
+ })();
6131
+ return address && validateAddress(address, chainId).valid ? address : void 0;
5091
6132
  },
5092
6133
  [evm.address, bitcoin3.address, solana3.address]
5093
6134
  );
5094
- const sendAddress = useMemo12(
5095
- () => addressForChain(sellChainType),
5096
- [addressForChain, sellChainType]
6135
+ const walletSendAddress = useMemo15(
6136
+ () => addressForChain(sellChainType, sellChainId),
6137
+ [addressForChain, sellChainType, sellChainId]
6138
+ );
6139
+ const sendAddress = useMemo15(
6140
+ () => resolveSendAddress({
6141
+ customAddress: customRefundAddress,
6142
+ walletAddress: walletSendAddress,
6143
+ sellChainId
6144
+ }),
6145
+ [customRefundAddress, walletSendAddress, sellChainId]
5097
6146
  );
5098
- const walletReceiveAddress = useMemo12(
5099
- () => addressForChain(buyChainType),
5100
- [addressForChain, buyChainType]
6147
+ const walletReceiveAddress = useMemo15(
6148
+ () => addressForChain(buyChainType, buyChainId),
6149
+ [addressForChain, buyChainType, buyChainId]
5101
6150
  );
5102
- const receiveAddress = useMemo12(
6151
+ const receiveAddress = useMemo15(
5103
6152
  () => resolveReceiveAddress({
5104
6153
  isLocked: isReceiveAddressLocked,
5105
6154
  defaultAddress: defaultReceiveAddress,
6155
+ defaultAddressChainId: defaultBuyAsset.chainId,
5106
6156
  customAddress: customReceiveAddress,
5107
6157
  walletAddress: walletReceiveAddress,
5108
6158
  buyChainId
@@ -5110,12 +6160,13 @@ var SwapWidgetCore = ({
5110
6160
  [
5111
6161
  isReceiveAddressLocked,
5112
6162
  defaultReceiveAddress,
6163
+ defaultBuyAsset.chainId,
5113
6164
  customReceiveAddress,
5114
6165
  walletReceiveAddress,
5115
6166
  buyChainId
5116
6167
  ]
5117
6168
  );
5118
- useEffect10(() => {
6169
+ useEffect14(() => {
5119
6170
  if (!isBuyAmountLocked) return;
5120
6171
  actorRef.send({
5121
6172
  type: "SET_BUY_AMOUNT",
@@ -5123,32 +6174,48 @@ var SwapWidgetCore = ({
5123
6174
  amountBaseUnit: defaultBuyAmountCryptoBaseUnit
5124
6175
  });
5125
6176
  }, [isBuyAmountLocked, defaultBuyAmountCryptoBaseUnit, defaultBuyAsset.precision, actorRef]);
5126
- const initialSyncRef = useRef7(false);
5127
- useEffect10(() => {
6177
+ const initialSyncRef = useRef12(false);
6178
+ useLayoutEffect3(() => {
5128
6179
  if (initialSyncRef.current) return;
5129
6180
  initialSyncRef.current = true;
5130
6181
  actorRef.send({ type: "SET_SELL_ASSET", asset: defaultSellAsset });
5131
6182
  actorRef.send({ type: "SET_BUY_ASSET", asset: defaultBuyAsset });
5132
6183
  actorRef.send({ type: "SET_SLIPPAGE", slippage: defaultSlippage });
6184
+ if (defaultReceiveAddress) {
6185
+ setCustomReceiveAddress(defaultReceiveAddress, defaultBuyAsset.chainId);
6186
+ }
5133
6187
  actorRef.send({
5134
6188
  type: "SET_BUY_AMOUNT",
5135
6189
  amount: defaultBuyAmountCryptoBaseUnit ? formatAmountForInput(defaultBuyAmountCryptoBaseUnit, defaultBuyAsset.precision) : "",
5136
6190
  amountBaseUnit: defaultBuyAmountCryptoBaseUnit
5137
6191
  });
6192
+ const pending = loadPendingDeposit(Date.now());
6193
+ if (pending) {
6194
+ actorRef.send({
6195
+ type: "RESTORE_DEPOSIT",
6196
+ quote: pending.quote,
6197
+ sendAddress: pending.refundAddress,
6198
+ receiveAddress: pending.receiveAddress,
6199
+ sellAmountBaseUnit: pending.sellAmountBaseUnit,
6200
+ buyAmountBaseUnit: pending.buyAmountBaseUnit,
6201
+ txHash: pending.txHash,
6202
+ depositObservedAt: pending.depositObservedAt
6203
+ });
6204
+ setCustomRefundAddress(pending.refundAddress, pending.quote.sellAsset.chainId);
6205
+ setCustomReceiveAddress(pending.receiveAddress, pending.quote.buyAsset.chainId);
6206
+ }
5138
6207
  }, [actorRef]);
5139
- useEffect10(() => {
6208
+ useEffect14(() => {
5140
6209
  actorRef.send({ type: "SET_SEND_ADDRESS", address: sendAddress });
5141
6210
  }, [sendAddress, actorRef]);
5142
- useEffect10(() => {
6211
+ useEffect14(() => {
5143
6212
  actorRef.send({ type: "SET_RECEIVE_ADDRESS", address: receiveAddress });
5144
6213
  }, [receiveAddress, actorRef]);
5145
- useEffect10(() => {
5146
- if (!customReceiveAddress) return;
5147
- if (!validateAddress(customReceiveAddress, buyChainId).valid) setCustomReceiveAddress("");
5148
- }, [buyChainId, customReceiveAddress]);
5149
- const walletValue = useMemo12(
6214
+ const walletValue = useMemo15(
5150
6215
  () => ({
5151
6216
  sendAddress,
6217
+ walletSendAddress,
6218
+ setCustomRefundAddress,
5152
6219
  receiveAddress,
5153
6220
  isReceiveAddressResolving,
5154
6221
  isReceiveAddressBlocked: isReceiveAddressLocked && !receiveAddress,
@@ -5160,10 +6227,13 @@ var SwapWidgetCore = ({
5160
6227
  }),
5161
6228
  [
5162
6229
  sendAddress,
6230
+ walletSendAddress,
5163
6231
  receiveAddress,
5164
6232
  isReceiveAddressResolving,
5165
6233
  isReceiveAddressLocked,
5166
6234
  customReceiveAddress,
6235
+ setCustomReceiveAddress,
6236
+ setCustomRefundAddress,
5167
6237
  evm,
5168
6238
  bitcoin3,
5169
6239
  solana3
@@ -5172,7 +6242,7 @@ var SwapWidgetCore = ({
5172
6242
  const hasLockedBuyAmount = isBuyAmountLocked && !!defaultBuyAmountCryptoBaseUnit;
5173
6243
  const isPayment = hasLockedBuyAmount && isReceiveAddressLocked && !!defaultReceiveAddress;
5174
6244
  const canRedirectToShapeshift = allowShapeshiftRedirect && !hasLockedBuyAmount && !isReceiveAddressLocked;
5175
- return /* @__PURE__ */ jsx11(SwapWalletProvider, { value: walletValue, children: /* @__PURE__ */ jsx11(
6245
+ return /* @__PURE__ */ jsx14(SwapWalletProvider, { value: walletValue, children: /* @__PURE__ */ jsx14(
5176
6246
  SwapWidgetContent,
5177
6247
  {
5178
6248
  apiClient,
@@ -5195,14 +6265,14 @@ var SwapWidgetCore = ({
5195
6265
  ) });
5196
6266
  };
5197
6267
  var SwapWidget = (props) => {
5198
- const apiClient = useMemo12(
6268
+ const apiClient = useMemo15(
5199
6269
  () => createApiClient({
5200
6270
  baseUrl: props.apiBaseUrl,
5201
6271
  partnerCode: props.partnerCode
5202
6272
  }),
5203
6273
  [props.apiBaseUrl, props.partnerCode]
5204
6274
  );
5205
- return /* @__PURE__ */ jsx11(AppKitWalletProvider, { projectId: props.walletConnectProjectId, children: /* @__PURE__ */ jsx11(SwapMachineCtx.Provider, { children: /* @__PURE__ */ jsx11(
6275
+ return /* @__PURE__ */ jsx14(AppKitWalletProvider, { projectId: props.walletConnectProjectId, children: /* @__PURE__ */ jsx14(SwapMachineCtx.Provider, { children: /* @__PURE__ */ jsx14(
5206
6276
  SwapWidgetCore,
5207
6277
  {
5208
6278
  defaultSellAsset: props.defaultSellAsset ?? DEFAULT_SELL_ASSET,