@compass-labs/widgets 0.1.32 → 0.1.34

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
@@ -992,9 +992,52 @@ function ChainSwitcher() {
992
992
  }
993
993
  );
994
994
  }
995
- function truncateAddress(address) {
995
+ function truncateAddr(address) {
996
996
  return `${address.slice(0, 6)}...${address.slice(-4)}`;
997
997
  }
998
+ function CopyableAddress({
999
+ address,
1000
+ label,
1001
+ truncate = true,
1002
+ textSize = "text-xs"
1003
+ }) {
1004
+ const [copied, setCopied] = react.useState(false);
1005
+ const handleCopy = react.useCallback(() => {
1006
+ navigator.clipboard.writeText(address);
1007
+ setCopied(true);
1008
+ setTimeout(() => setCopied(false), 1500);
1009
+ }, [address]);
1010
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "2px" }, children: [
1011
+ label && /* @__PURE__ */ jsxRuntime.jsx(
1012
+ "span",
1013
+ {
1014
+ className: "text-xs",
1015
+ style: { color: "var(--compass-color-text-tertiary)", fontSize: "10px" },
1016
+ children: label
1017
+ }
1018
+ ),
1019
+ /* @__PURE__ */ jsxRuntime.jsxs(
1020
+ "button",
1021
+ {
1022
+ onClick: handleCopy,
1023
+ className: `inline-flex items-center font-mono ${textSize}`,
1024
+ style: {
1025
+ color: "var(--compass-color-text-secondary)",
1026
+ background: "none",
1027
+ border: "none",
1028
+ cursor: "pointer",
1029
+ padding: 0,
1030
+ gap: "4px"
1031
+ },
1032
+ title: copied ? "Copied!" : `Copy: ${address}`,
1033
+ children: [
1034
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: truncate ? truncateAddr(address) : address }),
1035
+ copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 10, className: "flex-shrink-0", style: { color: "var(--compass-color-success)" } }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { size: 10, className: "flex-shrink-0", style: { color: "var(--compass-color-text-tertiary)" } })
1036
+ ]
1037
+ }
1038
+ )
1039
+ ] });
1040
+ }
998
1041
  function WalletStatus({
999
1042
  showFullAddress = false,
1000
1043
  showLogout = true,
@@ -1071,11 +1114,11 @@ function WalletStatus({
1071
1114
  }
1072
1115
  ),
1073
1116
  /* @__PURE__ */ jsxRuntime.jsx(
1074
- "span",
1117
+ CopyableAddress,
1075
1118
  {
1076
- className: `font-mono whitespace-nowrap ${compact ? "text-xs" : "text-sm"}`,
1077
- style: { color: "var(--compass-color-text)" },
1078
- children: showFullAddress ? address : truncateAddress(address)
1119
+ address,
1120
+ truncate: !showFullAddress,
1121
+ textSize: compact ? "text-xs" : "text-sm"
1079
1122
  }
1080
1123
  ),
1081
1124
  showLogout && disconnectFn !== null && /* @__PURE__ */ jsxRuntime.jsx(
@@ -1111,68 +1154,75 @@ function ActionModal({ isOpen, onClose, title, children }) {
1111
1154
  };
1112
1155
  }, [isOpen, onClose]);
1113
1156
  if (!isOpen) return null;
1114
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [
1115
- /* @__PURE__ */ jsxRuntime.jsx(
1116
- "div",
1117
- {
1118
- className: "absolute inset-0",
1119
- style: { backgroundColor: "var(--compass-color-overlay)" },
1120
- onClick: onClose
1121
- }
1122
- ),
1123
- /* @__PURE__ */ jsxRuntime.jsxs(
1124
- "div",
1125
- {
1126
- className: "relative w-full max-w-md mx-4 overflow-hidden",
1127
- style: {
1128
- backgroundColor: "var(--compass-color-surface)",
1129
- boxShadow: "var(--compass-shadow-lg)",
1130
- borderRadius: "var(--compass-border-radius-xl)",
1131
- fontFamily: "var(--compass-font-family)"
1132
- },
1133
- children: [
1134
- /* @__PURE__ */ jsxRuntime.jsxs(
1135
- "div",
1136
- {
1137
- className: "flex items-center justify-between border-b",
1138
- style: {
1139
- borderColor: "var(--compass-color-border)",
1140
- padding: "calc(var(--compass-spacing-card) * 0.75) var(--compass-spacing-card)"
1141
- },
1142
- children: [
1143
- /* @__PURE__ */ jsxRuntime.jsx(
1144
- "h2",
1145
- {
1146
- className: "font-semibold",
1147
- style: {
1148
- fontSize: "var(--compass-font-size-subheading)",
1149
- color: "var(--compass-color-text)"
1150
- },
1151
- children: title
1152
- }
1153
- ),
1154
- /* @__PURE__ */ jsxRuntime.jsx(
1155
- "button",
1156
- {
1157
- onClick: onClose,
1158
- className: "hover:opacity-70",
1159
- style: {
1160
- color: "var(--compass-color-text-secondary)",
1161
- borderRadius: "var(--compass-border-radius-md)",
1162
- padding: "calc(var(--compass-spacing-unit) * 0.25)",
1163
- transition: "var(--compass-transition-normal)"
1164
- },
1165
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 20 })
1166
- }
1167
- )
1168
- ]
1169
- }
1170
- ),
1171
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "var(--compass-spacing-card)" }, children })
1172
- ]
1173
- }
1174
- )
1175
- ] });
1157
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1158
+ "div",
1159
+ {
1160
+ className: "fixed inset-0 z-50 flex items-center justify-center p-4",
1161
+ style: { overflowY: "auto", scrollbarWidth: "none" },
1162
+ children: [
1163
+ /* @__PURE__ */ jsxRuntime.jsx(
1164
+ "div",
1165
+ {
1166
+ className: "absolute inset-0",
1167
+ style: { backgroundColor: "var(--compass-color-overlay)" },
1168
+ onClick: onClose
1169
+ }
1170
+ ),
1171
+ /* @__PURE__ */ jsxRuntime.jsxs(
1172
+ "div",
1173
+ {
1174
+ className: "relative w-full max-w-md",
1175
+ style: {
1176
+ backgroundColor: "var(--compass-color-surface)",
1177
+ boxShadow: "var(--compass-shadow-lg)",
1178
+ borderRadius: "var(--compass-border-radius-xl)",
1179
+ fontFamily: "var(--compass-font-family)"
1180
+ },
1181
+ children: [
1182
+ /* @__PURE__ */ jsxRuntime.jsxs(
1183
+ "div",
1184
+ {
1185
+ className: "flex items-center justify-between border-b",
1186
+ style: {
1187
+ borderColor: "var(--compass-color-border)",
1188
+ padding: "calc(var(--compass-spacing-card) * 0.75) var(--compass-spacing-card)"
1189
+ },
1190
+ children: [
1191
+ /* @__PURE__ */ jsxRuntime.jsx(
1192
+ "h2",
1193
+ {
1194
+ className: "font-semibold",
1195
+ style: {
1196
+ fontSize: "var(--compass-font-size-subheading)",
1197
+ color: "var(--compass-color-text)"
1198
+ },
1199
+ children: title
1200
+ }
1201
+ ),
1202
+ /* @__PURE__ */ jsxRuntime.jsx(
1203
+ "button",
1204
+ {
1205
+ onClick: onClose,
1206
+ className: "hover:opacity-70",
1207
+ style: {
1208
+ color: "var(--compass-color-text-secondary)",
1209
+ borderRadius: "var(--compass-border-radius-md)",
1210
+ padding: "calc(var(--compass-spacing-unit) * 0.25)",
1211
+ transition: "var(--compass-transition-normal)"
1212
+ },
1213
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 20 })
1214
+ }
1215
+ )
1216
+ ]
1217
+ }
1218
+ ),
1219
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "var(--compass-spacing-card)" }, children })
1220
+ ]
1221
+ }
1222
+ )
1223
+ ]
1224
+ }
1225
+ );
1176
1226
  }
1177
1227
  function PnLSummary({ pnl, tokenSymbol, tokenPrice }) {
1178
1228
  const [isExpanded, setIsExpanded] = react.useState(false);
@@ -2233,226 +2283,98 @@ function AccountBalancesModal({
2233
2283
  balances,
2234
2284
  totalUsdValue,
2235
2285
  isLoading = false,
2236
- earnAccountAddress
2286
+ earnAccountAddress,
2287
+ walletAddress
2237
2288
  }) {
2238
- react.useEffect(() => {
2239
- const handleEscape = (e) => {
2240
- if (e.key === "Escape") onClose();
2241
- };
2242
- if (isOpen) {
2243
- document.addEventListener("keydown", handleEscape);
2244
- document.body.style.overflow = "hidden";
2245
- }
2246
- return () => {
2247
- document.removeEventListener("keydown", handleEscape);
2248
- document.body.style.overflow = "";
2249
- };
2250
- }, [isOpen, onClose]);
2251
- if (!isOpen) return null;
2252
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [
2253
- /* @__PURE__ */ jsxRuntime.jsx(
2289
+ return /* @__PURE__ */ jsxRuntime.jsx(ActionModal, { isOpen, onClose, title: "Balance Breakdown", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
2290
+ (walletAddress || earnAccountAddress) && /* @__PURE__ */ jsxRuntime.jsxs(
2254
2291
  "div",
2255
2292
  {
2256
- className: "absolute inset-0",
2257
- style: { backgroundColor: "var(--compass-color-overlay)" },
2258
- onClick: onClose
2293
+ className: "flex flex-col gap-2 pb-3",
2294
+ style: { borderBottom: "1px solid var(--compass-color-border)" },
2295
+ children: [
2296
+ walletAddress && /* @__PURE__ */ jsxRuntime.jsx(CopyableAddress, { address: walletAddress, label: "Wallet" }),
2297
+ earnAccountAddress && /* @__PURE__ */ jsxRuntime.jsx(CopyableAddress, { address: earnAccountAddress, label: "Product Account" })
2298
+ ]
2259
2299
  }
2260
2300
  ),
2261
- /* @__PURE__ */ jsxRuntime.jsxs(
2301
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
2302
+ lucideReact.Loader2,
2303
+ {
2304
+ size: 24,
2305
+ className: "animate-spin",
2306
+ style: { color: "var(--compass-color-primary)" }
2307
+ }
2308
+ ) }) : balances.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2262
2309
  "div",
2263
2310
  {
2264
- className: "relative w-full max-w-md mx-4 overflow-hidden",
2265
- style: {
2266
- backgroundColor: "var(--compass-color-surface)",
2267
- boxShadow: "var(--compass-shadow-lg)",
2268
- borderRadius: "var(--compass-border-radius-xl)",
2269
- fontFamily: "var(--compass-font-family)"
2270
- },
2271
- children: [
2272
- /* @__PURE__ */ jsxRuntime.jsxs(
2273
- "div",
2274
- {
2275
- className: "flex items-center justify-between border-b",
2276
- style: {
2277
- borderColor: "var(--compass-color-border)",
2278
- padding: "calc(var(--compass-spacing-unit) * 0.75) var(--compass-spacing-card)"
2279
- },
2280
- children: [
2281
- /* @__PURE__ */ jsxRuntime.jsxs(
2282
- "h2",
2283
- {
2284
- className: "font-semibold flex items-center gap-2",
2285
- style: {
2286
- fontSize: "var(--compass-font-size-subheading)",
2287
- color: "var(--compass-color-text)"
2288
- },
2289
- children: [
2290
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Coins, { size: 20 }),
2291
- "Account Balances"
2292
- ]
2293
- }
2294
- ),
2295
- /* @__PURE__ */ jsxRuntime.jsx(
2296
- "button",
2297
- {
2298
- onClick: onClose,
2299
- className: "hover:opacity-70",
2300
- style: {
2301
- color: "var(--compass-color-text-secondary)",
2302
- borderRadius: "var(--compass-border-radius-md)",
2303
- padding: "calc(var(--compass-spacing-unit) * 0.25)",
2304
- transition: "var(--compass-transition-normal)"
2305
- },
2306
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 20 })
2307
- }
2308
- )
2309
- ]
2310
- }
2311
- ),
2312
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "var(--compass-spacing-card)" }, children: [
2313
- isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", style: { padding: "calc(var(--compass-spacing-unit) * 2) 0" }, children: /* @__PURE__ */ jsxRuntime.jsx(
2314
- lucideReact.Loader2,
2315
- {
2316
- size: 24,
2317
- className: "animate-spin",
2318
- style: { color: "var(--compass-color-primary)" }
2319
- }
2320
- ) }) : balances.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2321
- "div",
2322
- {
2323
- className: "text-center",
2324
- style: { color: "var(--compass-color-text-secondary)", padding: "calc(var(--compass-spacing-unit) * 2) 0" },
2325
- children: "No token balances found"
2326
- }
2327
- ) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
2328
- /* @__PURE__ */ jsxRuntime.jsxs(
2329
- "div",
2330
- {
2331
- className: "flex items-center justify-between border",
2332
- style: {
2333
- borderColor: "var(--compass-color-border)",
2334
- backgroundColor: "var(--compass-color-surface)",
2335
- borderRadius: "var(--compass-border-radius-lg)",
2336
- padding: "calc(var(--compass-spacing-unit) * 1)",
2337
- marginBottom: "calc(var(--compass-spacing-unit) * 0.5)"
2338
- },
2339
- children: [
2340
- /* @__PURE__ */ jsxRuntime.jsx(
2341
- "span",
2342
- {
2343
- className: "font-medium",
2344
- style: { color: "var(--compass-color-text-secondary)" },
2345
- children: "Total Balance"
2346
- }
2347
- ),
2348
- /* @__PURE__ */ jsxRuntime.jsx(
2349
- "span",
2350
- {
2351
- className: "font-bold text-xl",
2352
- style: { color: "var(--compass-color-text)" },
2353
- children: formatUSD(totalUsdValue)
2354
- }
2355
- )
2356
- ]
2357
- }
2358
- ),
2359
- /* @__PURE__ */ jsxRuntime.jsx(
2360
- "div",
2361
- {
2362
- className: "text-xs font-medium uppercase tracking-wide",
2363
- style: {
2364
- color: "var(--compass-color-text-tertiary)",
2365
- padding: "calc(var(--compass-spacing-unit) * 0.5) 0"
2366
- },
2367
- children: "Token Breakdown"
2368
- }
2369
- ),
2370
- balances.map((token) => /* @__PURE__ */ jsxRuntime.jsxs(
2371
- "div",
2372
- {
2373
- className: "flex items-center justify-between",
2374
- style: {
2375
- backgroundColor: "var(--compass-color-background)",
2376
- borderRadius: "var(--compass-border-radius-lg)",
2377
- padding: "calc(var(--compass-spacing-unit) * 0.75)"
2378
- },
2379
- children: [
2380
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.75)" }, children: [
2381
- /* @__PURE__ */ jsxRuntime.jsx(
2382
- "div",
2383
- {
2384
- className: "w-8 h-8 flex items-center justify-center text-xs font-bold",
2385
- style: {
2386
- backgroundColor: "var(--compass-color-primary-muted)",
2387
- color: "var(--compass-color-primary)",
2388
- borderRadius: "var(--compass-border-radius-full)"
2389
- },
2390
- children: token.symbol.slice(0, 2)
2391
- }
2392
- ),
2393
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2394
- /* @__PURE__ */ jsxRuntime.jsx(
2395
- "div",
2396
- {
2397
- className: "font-medium",
2398
- style: { color: "var(--compass-color-text)" },
2399
- children: token.symbol
2400
- }
2401
- ),
2402
- /* @__PURE__ */ jsxRuntime.jsx(
2403
- "div",
2404
- {
2405
- className: "text-sm font-mono",
2406
- style: { color: "var(--compass-color-text-secondary)" },
2407
- children: formatAmount(token.balance)
2408
- }
2409
- )
2410
- ] })
2411
- ] }),
2412
- /* @__PURE__ */ jsxRuntime.jsx(
2413
- "div",
2414
- {
2415
- className: "font-medium",
2416
- style: { color: "var(--compass-color-text)" },
2417
- children: formatUSD(token.usdValue)
2418
- }
2419
- )
2420
- ]
2421
- },
2422
- token.symbol
2423
- ))
2424
- ] }),
2425
- earnAccountAddress && /* @__PURE__ */ jsxRuntime.jsx(
2311
+ className: "text-center py-4",
2312
+ style: { color: "var(--compass-color-text-tertiary)" },
2313
+ children: "No tokens in account"
2314
+ }
2315
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2316
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
2317
+ /* @__PURE__ */ jsxRuntime.jsx(
2318
+ "span",
2319
+ {
2320
+ className: "text-xs font-medium uppercase tracking-wide",
2321
+ style: { color: "var(--compass-color-text-tertiary)" },
2322
+ children: "Available in Account"
2323
+ }
2324
+ ),
2325
+ /* @__PURE__ */ jsxRuntime.jsx(
2326
+ "div",
2327
+ {
2328
+ className: "flex flex-col gap-2",
2329
+ style: {
2330
+ maxHeight: "50vh",
2331
+ overflowY: "auto",
2332
+ scrollbarWidth: "none"
2333
+ },
2334
+ children: balances.map((token) => /* @__PURE__ */ jsxRuntime.jsxs(
2426
2335
  "div",
2427
2336
  {
2428
- className: "border-t text-center",
2337
+ className: "flex items-center justify-between p-3 rounded-lg",
2429
2338
  style: {
2430
- borderColor: "var(--compass-color-border)",
2431
- marginTop: "var(--compass-spacing-card)",
2432
- paddingTop: "var(--compass-spacing-card)"
2339
+ backgroundColor: "var(--compass-color-surface)",
2340
+ border: "1px solid var(--compass-color-border)",
2341
+ flexShrink: 0
2433
2342
  },
2434
- children: /* @__PURE__ */ jsxRuntime.jsxs(
2435
- "span",
2436
- {
2437
- className: "text-xs",
2438
- style: { color: "var(--compass-color-text-tertiary)" },
2439
- children: [
2440
- "Earn Account: ",
2441
- earnAccountAddress.slice(0, 6),
2442
- "...",
2443
- earnAccountAddress.slice(-4)
2444
- ]
2445
- }
2446
- )
2343
+ children: [
2344
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", style: { color: "var(--compass-color-text)" }, children: token.symbol }),
2345
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end", children: [
2346
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-text)" }, children: formatAmount(token.balance) }),
2347
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: formatUSD(token.usdValue) })
2348
+ ] })
2349
+ ]
2350
+ },
2351
+ token.symbol
2352
+ ))
2353
+ }
2354
+ )
2355
+ ] }),
2356
+ /* @__PURE__ */ jsxRuntime.jsxs(
2357
+ "div",
2358
+ {
2359
+ className: "flex items-center justify-between pt-3 mt-2",
2360
+ style: { borderTop: "2px solid var(--compass-color-border)" },
2361
+ children: [
2362
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", style: { color: "var(--compass-color-text)" }, children: "Total" }),
2363
+ /* @__PURE__ */ jsxRuntime.jsx(
2364
+ "span",
2365
+ {
2366
+ className: "font-bold text-xl",
2367
+ style: { color: "var(--compass-color-text)" },
2368
+ children: formatUSD(totalUsdValue)
2447
2369
  }
2448
2370
  )
2449
- ] })
2450
- ]
2451
- }
2452
- )
2453
- ] });
2371
+ ]
2372
+ }
2373
+ )
2374
+ ] })
2375
+ ] }) });
2454
2376
  }
2455
- var TRANSFER_TOKENS = ["USDC"];
2377
+ var TRANSFER_TOKENS = ["USDC", "SBC"];
2456
2378
  var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
2457
2379
  compact = false,
2458
2380
  hideVisual = false,
@@ -2770,7 +2692,8 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
2770
2692
  balances: tokenBalances,
2771
2693
  totalUsdValue: totalUsdValue.toString(),
2772
2694
  isLoading: balancesLoading,
2773
- earnAccountAddress: earnAccountAddress ?? void 0
2695
+ earnAccountAddress: earnAccountAddress ?? void 0,
2696
+ walletAddress: address ?? void 0
2774
2697
  }
2775
2698
  ),
2776
2699
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2952,7 +2875,459 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
2952
2875
  }
2953
2876
  )
2954
2877
  ] });
2955
- });
2878
+ });
2879
+ function useSwapQuote({ fromToken, toToken, amount, enabled = true }) {
2880
+ const { chainId } = useChain();
2881
+ const { address } = useEmbeddableWallet();
2882
+ const query = reactQuery.useQuery({
2883
+ queryKey: ["swapQuote", chainId, fromToken, toToken, amount, address],
2884
+ queryFn: async () => {
2885
+ if (!fromToken || !toToken || !amount || parseFloat(amount) <= 0 || !address) {
2886
+ return null;
2887
+ }
2888
+ const params = new URLSearchParams({
2889
+ owner: address,
2890
+ chain: chainId,
2891
+ tokenIn: fromToken,
2892
+ tokenOut: toToken,
2893
+ amountIn: amount
2894
+ });
2895
+ const response = await fetch(`/api/compass/swap/quote?${params}`);
2896
+ if (!response.ok) {
2897
+ const errorData = await response.json();
2898
+ const errorMessage = errorData.message || errorData.error || "Failed to get swap quote";
2899
+ throw new Error(errorMessage);
2900
+ }
2901
+ const data = await response.json();
2902
+ const outputAmount = data.estimatedAmountOut || "0";
2903
+ const inputAmountNum = parseFloat(amount);
2904
+ const outputAmountNum = parseFloat(outputAmount);
2905
+ return {
2906
+ inputAmount: amount,
2907
+ outputAmount,
2908
+ rate: inputAmountNum > 0 ? (outputAmountNum / inputAmountNum).toString() : "0"
2909
+ };
2910
+ },
2911
+ enabled: enabled && !!address && !!fromToken && !!toToken && !!amount && parseFloat(amount) > 0,
2912
+ staleTime: 10 * 1e3,
2913
+ refetchInterval: 15 * 1e3,
2914
+ retry: 1
2915
+ });
2916
+ return {
2917
+ quote: query.data,
2918
+ isLoading: query.isLoading,
2919
+ isError: query.isError,
2920
+ error: query.error,
2921
+ refetch: query.refetch
2922
+ };
2923
+ }
2924
+ var COMMON_TOKENS = [
2925
+ "USDC",
2926
+ "USDT",
2927
+ "DAI",
2928
+ "USDS",
2929
+ "USDE",
2930
+ "sUSDE",
2931
+ "sDAI",
2932
+ "FRAX",
2933
+ "LUSD",
2934
+ "GUSD",
2935
+ "PYUSD",
2936
+ "crvUSD",
2937
+ "GHO",
2938
+ "EURC",
2939
+ "EURS",
2940
+ "EURA",
2941
+ "WETH",
2942
+ "WBTC",
2943
+ "wstETH",
2944
+ "cbETH",
2945
+ "rETH"
2946
+ ];
2947
+ function SwapForm({
2948
+ availableFromTokens,
2949
+ availableToTokens,
2950
+ balances,
2951
+ defaultFromToken,
2952
+ defaultToToken,
2953
+ onSwapSuccess,
2954
+ onSwapError
2955
+ }) {
2956
+ const toTokens = Array.from(/* @__PURE__ */ new Set([
2957
+ ...availableFromTokens,
2958
+ ...COMMON_TOKENS,
2959
+ ...availableToTokens || []
2960
+ ]));
2961
+ const [fromToken, setFromToken] = react.useState(defaultFromToken || availableFromTokens[0] || "USDC");
2962
+ const [toToken, setToToken] = react.useState(defaultToToken || toTokens.find((t) => t !== (defaultFromToken || availableFromTokens[0])) || "USDC");
2963
+ const [fromAmount, setFromAmount] = react.useState("");
2964
+ const [isSwapping, setIsSwapping] = react.useState(false);
2965
+ const [swapStatus, setSwapStatus] = react.useState("");
2966
+ const [isFromOpen, setIsFromOpen] = react.useState(false);
2967
+ const [isToOpen, setIsToOpen] = react.useState(false);
2968
+ const { address, isConnected, signTypedData } = useEmbeddableWallet();
2969
+ const { chainId } = useChain();
2970
+ const { quote, isLoading: isQuoteLoading, error: quoteError } = useSwapQuote({
2971
+ fromToken,
2972
+ toToken,
2973
+ amount: fromAmount,
2974
+ enabled: !!fromAmount && parseFloat(fromAmount) > 0
2975
+ });
2976
+ const handleReverse = react.useCallback(() => {
2977
+ const oldFrom = fromToken;
2978
+ const oldTo = toToken;
2979
+ if (availableFromTokens.includes(oldTo)) {
2980
+ setFromToken(oldTo);
2981
+ setToToken(oldFrom);
2982
+ setFromAmount("");
2983
+ }
2984
+ }, [fromToken, toToken, availableFromTokens]);
2985
+ const handleSwap = react.useCallback(async () => {
2986
+ if (!address || !fromAmount || !quote || !signTypedData) return;
2987
+ setIsSwapping(true);
2988
+ setSwapStatus("Preparing swap...");
2989
+ try {
2990
+ const prepareResponse = await fetch("/api/compass/swap/prepare", {
2991
+ method: "POST",
2992
+ headers: { "Content-Type": "application/json" },
2993
+ body: JSON.stringify({
2994
+ owner: address,
2995
+ chain: chainId,
2996
+ tokenIn: fromToken,
2997
+ tokenOut: toToken,
2998
+ amountIn: fromAmount
2999
+ })
3000
+ });
3001
+ if (!prepareResponse.ok) {
3002
+ const error = await prepareResponse.json();
3003
+ throw new Error(error.error || "Failed to prepare swap");
3004
+ }
3005
+ const prepareData = await prepareResponse.json();
3006
+ const { eip712, normalizedTypes } = prepareData;
3007
+ if (!eip712) {
3008
+ throw new Error("No EIP-712 data returned from prepare");
3009
+ }
3010
+ setSwapStatus("Please sign the transaction...");
3011
+ const signature = await signTypedData({
3012
+ domain: eip712.domain,
3013
+ types: normalizedTypes || eip712.types,
3014
+ primaryType: "SafeTx",
3015
+ message: eip712.message
3016
+ });
3017
+ setSwapStatus("Executing swap...");
3018
+ const executeResponse = await fetch("/api/compass/swap/execute", {
3019
+ method: "POST",
3020
+ headers: { "Content-Type": "application/json" },
3021
+ body: JSON.stringify({
3022
+ owner: address,
3023
+ chain: chainId,
3024
+ eip712,
3025
+ signature
3026
+ })
3027
+ });
3028
+ if (!executeResponse.ok) {
3029
+ const error = await executeResponse.json();
3030
+ throw new Error(error.error || "Failed to execute swap");
3031
+ }
3032
+ const executeData = await executeResponse.json();
3033
+ const txHash = executeData.txHash;
3034
+ setSwapStatus("Swap successful!");
3035
+ onSwapSuccess?.(fromToken, toToken, fromAmount, quote.outputAmount, txHash);
3036
+ setFromAmount("");
3037
+ setTimeout(() => setSwapStatus(""), 3e3);
3038
+ } catch (error) {
3039
+ setSwapStatus("");
3040
+ onSwapError?.(error);
3041
+ } finally {
3042
+ setIsSwapping(false);
3043
+ }
3044
+ }, [address, fromAmount, quote, chainId, fromToken, toToken, signTypedData, onSwapSuccess, onSwapError]);
3045
+ const canReverse = availableFromTokens.includes(toToken);
3046
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "calc(var(--compass-spacing-unit) * 0.75)" }, children: [
3047
+ /* @__PURE__ */ jsxRuntime.jsxs(
3048
+ "div",
3049
+ {
3050
+ style: {
3051
+ backgroundColor: "var(--compass-color-surface)",
3052
+ border: "1px solid var(--compass-color-border)",
3053
+ borderRadius: "var(--compass-border-radius-xl)",
3054
+ padding: "calc(var(--compass-spacing-unit) * 0.75)"
3055
+ },
3056
+ children: [
3057
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", style: { marginBottom: "calc(var(--compass-spacing-unit) * 0.25)" }, children: [
3058
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "From" }),
3059
+ balances?.[fromToken] && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: [
3060
+ "Balance: ",
3061
+ parseFloat(balances[fromToken]).toLocaleString(void 0, { maximumFractionDigits: 6 })
3062
+ ] })
3063
+ ] }),
3064
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
3065
+ /* @__PURE__ */ jsxRuntime.jsx(
3066
+ "input",
3067
+ {
3068
+ type: "number",
3069
+ value: fromAmount,
3070
+ onChange: (e) => setFromAmount(e.target.value),
3071
+ placeholder: "0.00",
3072
+ disabled: isSwapping,
3073
+ className: "flex-1 bg-transparent outline-none font-medium min-w-0",
3074
+ style: { color: "var(--compass-color-text)", fontSize: "1.25rem" }
3075
+ }
3076
+ ),
3077
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", style: { flexShrink: 0 }, children: [
3078
+ /* @__PURE__ */ jsxRuntime.jsxs(
3079
+ "button",
3080
+ {
3081
+ onClick: () => {
3082
+ setIsFromOpen(!isFromOpen);
3083
+ setIsToOpen(false);
3084
+ },
3085
+ disabled: isSwapping,
3086
+ className: "flex items-center font-medium",
3087
+ style: {
3088
+ backgroundColor: "var(--compass-color-surface-elevated, var(--compass-color-background))",
3089
+ border: "1px solid var(--compass-color-border)",
3090
+ color: "var(--compass-color-text)",
3091
+ borderRadius: "var(--compass-border-radius-md)",
3092
+ padding: "calc(var(--compass-spacing-unit) * 0.5) calc(var(--compass-spacing-unit) * 0.75)",
3093
+ gap: "calc(var(--compass-spacing-unit) * 0.25)",
3094
+ fontSize: "0.875rem"
3095
+ },
3096
+ children: [
3097
+ fromToken,
3098
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } })
3099
+ ]
3100
+ }
3101
+ ),
3102
+ isFromOpen && /* @__PURE__ */ jsxRuntime.jsx(
3103
+ "div",
3104
+ {
3105
+ className: "absolute right-0 mt-1 z-10",
3106
+ style: {
3107
+ backgroundColor: "var(--compass-color-surface)",
3108
+ border: "1px solid var(--compass-color-border)",
3109
+ borderRadius: "var(--compass-border-radius-lg)",
3110
+ boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
3111
+ minWidth: "120px",
3112
+ maxHeight: "200px",
3113
+ overflowY: "auto",
3114
+ scrollbarWidth: "none"
3115
+ },
3116
+ children: availableFromTokens.filter((t) => t !== toToken).map((token) => /* @__PURE__ */ jsxRuntime.jsx(
3117
+ "button",
3118
+ {
3119
+ onClick: () => {
3120
+ setFromToken(token);
3121
+ setIsFromOpen(false);
3122
+ },
3123
+ className: "w-full text-left font-medium transition-colors",
3124
+ style: {
3125
+ padding: "calc(var(--compass-spacing-unit) * 0.5) calc(var(--compass-spacing-unit) * 0.75)",
3126
+ color: token === fromToken ? "var(--compass-color-primary)" : "var(--compass-color-text)",
3127
+ backgroundColor: token === fromToken ? "var(--compass-color-primary-muted, rgba(99, 102, 241, 0.1))" : "transparent",
3128
+ fontSize: "0.875rem"
3129
+ },
3130
+ children: token
3131
+ },
3132
+ token
3133
+ ))
3134
+ }
3135
+ )
3136
+ ] })
3137
+ ] })
3138
+ ]
3139
+ }
3140
+ ),
3141
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center relative z-10", style: { margin: "calc(var(--compass-spacing-unit) * -0.25) 0" }, children: /* @__PURE__ */ jsxRuntime.jsx(
3142
+ "button",
3143
+ {
3144
+ onClick: handleReverse,
3145
+ disabled: !canReverse || isSwapping,
3146
+ className: "border disabled:opacity-30",
3147
+ style: {
3148
+ backgroundColor: "var(--compass-color-surface)",
3149
+ borderColor: "var(--compass-color-border)",
3150
+ borderRadius: "var(--compass-border-radius-full)",
3151
+ padding: "calc(var(--compass-spacing-unit) * 0.5)",
3152
+ transition: "var(--compass-transition-normal)"
3153
+ },
3154
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownUp, { size: 16, style: { color: "var(--compass-color-text-secondary)" } })
3155
+ }
3156
+ ) }),
3157
+ /* @__PURE__ */ jsxRuntime.jsxs(
3158
+ "div",
3159
+ {
3160
+ style: {
3161
+ backgroundColor: "var(--compass-color-surface)",
3162
+ border: "1px solid var(--compass-color-border)",
3163
+ borderRadius: "var(--compass-border-radius-xl)",
3164
+ padding: "calc(var(--compass-spacing-unit) * 0.75)"
3165
+ },
3166
+ children: [
3167
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between", style: { marginBottom: "calc(var(--compass-spacing-unit) * 0.25)" }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "To" }) }),
3168
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
3169
+ /* @__PURE__ */ jsxRuntime.jsx(
3170
+ "div",
3171
+ {
3172
+ className: "flex-1 font-medium min-w-0",
3173
+ style: {
3174
+ color: isQuoteLoading ? "var(--compass-color-text-tertiary)" : "var(--compass-color-text)",
3175
+ fontSize: "1.25rem"
3176
+ },
3177
+ children: isQuoteLoading ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
3178
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 16, className: "animate-spin" }),
3179
+ "Loading..."
3180
+ ] }) : quote?.outputAmount ? parseFloat(quote.outputAmount).toFixed(8) : "0.00"
3181
+ }
3182
+ ),
3183
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", style: { flexShrink: 0 }, children: [
3184
+ /* @__PURE__ */ jsxRuntime.jsxs(
3185
+ "button",
3186
+ {
3187
+ onClick: () => {
3188
+ setIsToOpen(!isToOpen);
3189
+ setIsFromOpen(false);
3190
+ },
3191
+ disabled: isSwapping,
3192
+ className: "flex items-center font-medium",
3193
+ style: {
3194
+ backgroundColor: "var(--compass-color-surface-elevated, var(--compass-color-background))",
3195
+ border: "1px solid var(--compass-color-border)",
3196
+ color: "var(--compass-color-text)",
3197
+ borderRadius: "var(--compass-border-radius-md)",
3198
+ padding: "calc(var(--compass-spacing-unit) * 0.5) calc(var(--compass-spacing-unit) * 0.75)",
3199
+ gap: "calc(var(--compass-spacing-unit) * 0.25)",
3200
+ fontSize: "0.875rem"
3201
+ },
3202
+ children: [
3203
+ toToken,
3204
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } })
3205
+ ]
3206
+ }
3207
+ ),
3208
+ isToOpen && /* @__PURE__ */ jsxRuntime.jsx(
3209
+ "div",
3210
+ {
3211
+ className: "absolute right-0 mt-1 z-10",
3212
+ style: {
3213
+ backgroundColor: "var(--compass-color-surface)",
3214
+ border: "1px solid var(--compass-color-border)",
3215
+ borderRadius: "var(--compass-border-radius-lg)",
3216
+ boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
3217
+ minWidth: "140px",
3218
+ maxHeight: "280px",
3219
+ overflowY: "auto",
3220
+ scrollbarWidth: "none"
3221
+ },
3222
+ children: toTokens.filter((t) => t !== fromToken).map((token) => /* @__PURE__ */ jsxRuntime.jsx(
3223
+ "button",
3224
+ {
3225
+ onClick: () => {
3226
+ setToToken(token);
3227
+ setIsToOpen(false);
3228
+ },
3229
+ className: "w-full text-left font-medium transition-colors",
3230
+ style: {
3231
+ padding: "calc(var(--compass-spacing-unit) * 0.5) calc(var(--compass-spacing-unit) * 0.75)",
3232
+ color: token === toToken ? "var(--compass-color-primary)" : "var(--compass-color-text)",
3233
+ backgroundColor: token === toToken ? "var(--compass-color-primary-muted, rgba(99, 102, 241, 0.1))" : "transparent",
3234
+ fontSize: "0.875rem"
3235
+ },
3236
+ children: token
3237
+ },
3238
+ token
3239
+ ))
3240
+ }
3241
+ )
3242
+ ] })
3243
+ ] })
3244
+ ]
3245
+ }
3246
+ ),
3247
+ quote && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", style: { color: "var(--compass-color-text-secondary)" }, children: [
3248
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Rate" }),
3249
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono", children: [
3250
+ "1 ",
3251
+ fromToken,
3252
+ " = ",
3253
+ parseFloat(quote.rate).toFixed(6),
3254
+ " ",
3255
+ toToken
3256
+ ] })
3257
+ ] }),
3258
+ quoteError && /* @__PURE__ */ jsxRuntime.jsxs(
3259
+ "div",
3260
+ {
3261
+ className: "flex items-center text-sm",
3262
+ style: {
3263
+ backgroundColor: "var(--compass-color-error-muted)",
3264
+ color: "var(--compass-color-error)",
3265
+ borderRadius: "var(--compass-border-radius-lg)",
3266
+ padding: "calc(var(--compass-spacing-unit) * 0.75)",
3267
+ gap: "calc(var(--compass-spacing-unit) * 0.5)"
3268
+ },
3269
+ children: [
3270
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 16 }),
3271
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: quoteError.message })
3272
+ ]
3273
+ }
3274
+ ),
3275
+ swapStatus && /* @__PURE__ */ jsxRuntime.jsxs(
3276
+ "div",
3277
+ {
3278
+ className: "flex items-center text-sm",
3279
+ style: {
3280
+ backgroundColor: swapStatus.includes("successful") ? "var(--compass-color-success-muted)" : "var(--compass-color-surface)",
3281
+ color: swapStatus.includes("successful") ? "var(--compass-color-success)" : "var(--compass-color-text-secondary)",
3282
+ borderRadius: "var(--compass-border-radius-lg)",
3283
+ padding: "calc(var(--compass-spacing-unit) * 0.75)",
3284
+ gap: "calc(var(--compass-spacing-unit) * 0.5)"
3285
+ },
3286
+ children: [
3287
+ !swapStatus.includes("successful") && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 14, className: "animate-spin" }),
3288
+ swapStatus
3289
+ ]
3290
+ }
3291
+ ),
3292
+ !isConnected ? /* @__PURE__ */ jsxRuntime.jsxs(
3293
+ "div",
3294
+ {
3295
+ className: "flex flex-col items-center",
3296
+ style: {
3297
+ backgroundColor: "var(--compass-color-surface)",
3298
+ border: "1px solid var(--compass-color-border)",
3299
+ borderRadius: "var(--compass-border-radius-lg)",
3300
+ padding: "calc(var(--compass-spacing-unit) * 1) var(--compass-spacing-card)",
3301
+ gap: "calc(var(--compass-spacing-unit) * 0.5)"
3302
+ },
3303
+ children: [
3304
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 20, style: { color: "var(--compass-color-text-tertiary)" } }),
3305
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-center", style: { color: "var(--compass-color-text-secondary)" }, children: "Connect your wallet to swap" })
3306
+ ]
3307
+ }
3308
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
3309
+ "button",
3310
+ {
3311
+ onClick: handleSwap,
3312
+ disabled: isSwapping || !quote || !fromAmount || parseFloat(fromAmount) <= 0,
3313
+ className: "w-full font-semibold flex items-center justify-center disabled:opacity-50 disabled:cursor-not-allowed",
3314
+ style: {
3315
+ backgroundColor: "var(--compass-color-primary)",
3316
+ color: "var(--compass-color-primary-text, white)",
3317
+ borderRadius: "var(--compass-border-radius-lg)",
3318
+ padding: "calc(var(--compass-spacing-unit) * 0.75)",
3319
+ gap: "calc(var(--compass-spacing-unit) * 0.5)",
3320
+ fontSize: "0.875rem",
3321
+ transition: "var(--compass-transition-normal)"
3322
+ },
3323
+ children: [
3324
+ isSwapping && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 16, className: "animate-spin" }),
3325
+ isSwapping ? "Swapping..." : "Swap"
3326
+ ]
3327
+ }
3328
+ )
3329
+ ] });
3330
+ }
2956
3331
  var MARKET_TABS = [
2957
3332
  { value: "variable", label: "VARIABLE" },
2958
3333
  { value: "fixed", label: "FIXED" }
@@ -3785,7 +4160,6 @@ var EVM_CHAIN_IDS = {
3785
4160
  base: 8453,
3786
4161
  arbitrum: 42161
3787
4162
  };
3788
- var SUPPORTED_TOKENS = ["USDC", "USDT", "DAI", "WETH", "SBC", "AUSD"];
3789
4163
  function formatCurrency(amount) {
3790
4164
  if (!amount) return "$0.00";
3791
4165
  const num = typeof amount === "string" ? parseFloat(amount) : amount;
@@ -3837,6 +4211,7 @@ function EarnAccount({
3837
4211
  const [isBalancesModalOpen, setIsBalancesModalOpen] = react.useState(false);
3838
4212
  const [marketTab, setMarketTab] = react.useState(defaultMarketTab);
3839
4213
  const [selectedMarket, setSelectedMarket] = react.useState(null);
4214
+ const [isSwapModalOpen, setIsSwapModalOpen] = react.useState(false);
3840
4215
  const [isEarningsModalOpen, setIsEarningsModalOpen] = react.useState(false);
3841
4216
  react.useEffect(() => {
3842
4217
  setSelectedMarket(null);
@@ -3886,6 +4261,7 @@ function EarnAccount({
3886
4261
  enabled: !!address && isDeployed,
3887
4262
  staleTime: 30 * 1e3
3888
4263
  });
4264
+ const balanceTokens = Object.keys(balancesQuery.data?.balances || {});
3889
4265
  const selectedTokenBalance = balancesQuery.data?.balances?.[selectedToken]?.balance || "0";
3890
4266
  const earnAccountTotalUsd = Object.values(balancesQuery.data?.balances || {}).reduce((sum, b) => sum + parseFloat(b.usdValue || "0"), 0).toString();
3891
4267
  const positionQuery = reactQuery.useQuery({
@@ -4555,39 +4931,59 @@ function EarnAccount({
4555
4931
  ]
4556
4932
  }
4557
4933
  ),
4558
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
4559
- /* @__PURE__ */ jsxRuntime.jsx(
4934
+ /* @__PURE__ */ jsxRuntime.jsx(
4935
+ "button",
4936
+ {
4937
+ onClick: () => setIsBalancesModalOpen(true),
4938
+ className: "transition-opacity hover:opacity-80",
4939
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4940
+ "span",
4941
+ {
4942
+ className: "font-bold",
4943
+ style: {
4944
+ color: "var(--compass-color-text)",
4945
+ fontSize: compact ? "2rem" : "2.5rem",
4946
+ lineHeight: "1"
4947
+ },
4948
+ children: formatCurrency(earnAccountTotal)
4949
+ }
4950
+ )
4951
+ }
4952
+ ),
4953
+ (balanceTokens.length > 0 || showTopUpButton) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "6px", marginTop: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
4954
+ balanceTokens.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
4560
4955
  "button",
4561
4956
  {
4562
- onClick: () => setIsBalancesModalOpen(true),
4563
- className: "transition-opacity hover:opacity-80",
4564
- children: /* @__PURE__ */ jsxRuntime.jsx(
4565
- "span",
4566
- {
4567
- className: "font-bold",
4568
- style: {
4569
- color: "var(--compass-color-text)",
4570
- fontSize: compact ? "2rem" : "2.5rem",
4571
- lineHeight: "1"
4572
- },
4573
- children: formatCurrency(earnAccountTotal)
4574
- }
4575
- )
4957
+ onClick: () => setIsSwapModalOpen(true),
4958
+ className: "flex items-center justify-center font-medium transition-all hover:opacity-80 w-full",
4959
+ style: {
4960
+ backgroundColor: "var(--compass-color-surface-elevated, var(--compass-color-surface))",
4961
+ border: "1px solid var(--compass-color-border)",
4962
+ color: "var(--compass-color-text-secondary)",
4963
+ borderRadius: "var(--compass-border-radius-md)",
4964
+ padding: "8px 10px",
4965
+ gap: "6px",
4966
+ fontSize: "13px"
4967
+ },
4968
+ children: [
4969
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeftRight, { size: 14 }),
4970
+ "Swap"
4971
+ ]
4576
4972
  }
4577
4973
  ),
4578
4974
  showTopUpButton && /* @__PURE__ */ jsxRuntime.jsxs(
4579
4975
  "button",
4580
4976
  {
4581
4977
  onClick: () => setIsFundModalOpen(true),
4582
- className: "flex items-center font-medium transition-all hover:opacity-80",
4978
+ className: "flex items-center justify-center font-medium transition-all hover:opacity-80 w-full",
4583
4979
  style: {
4584
4980
  backgroundColor: "var(--compass-color-surface-elevated, var(--compass-color-surface))",
4585
4981
  border: "1px solid var(--compass-color-border)",
4586
4982
  color: "var(--compass-color-text-secondary)",
4587
4983
  borderRadius: "var(--compass-border-radius-md)",
4588
- padding: "6px 10px",
4589
- gap: "4px",
4590
- fontSize: "12px"
4984
+ padding: "8px 10px",
4985
+ gap: "6px",
4986
+ fontSize: "13px"
4591
4987
  },
4592
4988
  children: [
4593
4989
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { size: 14 }),
@@ -4791,7 +5187,7 @@ function EarnAccount({
4791
5187
  boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
4792
5188
  minWidth: "100px"
4793
5189
  },
4794
- children: SUPPORTED_TOKENS.map((token) => /* @__PURE__ */ jsxRuntime.jsx(
5190
+ children: balanceTokens.map((token) => /* @__PURE__ */ jsxRuntime.jsx(
4795
5191
  "button",
4796
5192
  {
4797
5193
  onClick: () => {
@@ -5103,391 +5499,123 @@ function EarnAccount({
5103
5499
  ] }) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center justify-center gap-2", children: [
5104
5500
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownLeft, { size: 20 }),
5105
5501
  needsFundSwap ? `Swap ${fundToken} & Transfer` : "Transfer to Savings"
5106
- ] })
5107
- }
5108
- ),
5109
- /* @__PURE__ */ jsxRuntime.jsx(
5110
- "p",
5111
- {
5112
- className: "text-xs text-center",
5113
- style: { color: "var(--compass-color-text-tertiary)" },
5114
- children: "Gas fees are sponsored"
5115
- }
5116
- )
5117
- ] })
5118
- }
5119
- ),
5120
- /* @__PURE__ */ jsxRuntime.jsx(
5121
- ActionModal,
5122
- {
5123
- isOpen: isBalancesModalOpen,
5124
- onClose: () => setIsBalancesModalOpen(false),
5125
- title: "Balance Breakdown",
5126
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: balancesQuery.data?.balances && Object.keys(balancesQuery.data.balances).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5127
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
5128
- /* @__PURE__ */ jsxRuntime.jsx(
5129
- "span",
5130
- {
5131
- className: "text-xs font-medium uppercase tracking-wide",
5132
- style: { color: "var(--compass-color-text-tertiary)" },
5133
- children: "Available in Account"
5134
- }
5135
- ),
5136
- Object.entries(balancesQuery.data.balances).map(([symbol, data]) => /* @__PURE__ */ jsxRuntime.jsxs(
5137
- "div",
5138
- {
5139
- className: "flex items-center justify-between p-3 rounded-lg",
5140
- style: {
5141
- backgroundColor: "var(--compass-color-surface)",
5142
- border: "1px solid var(--compass-color-border)"
5143
- },
5144
- children: [
5145
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", style: { color: "var(--compass-color-text)" }, children: symbol }),
5146
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end", children: [
5147
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-text)" }, children: formatAmount2(data.balance) }),
5148
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: formatCurrency(data.usdValue) })
5149
- ] })
5150
- ]
5151
- },
5152
- symbol
5153
- ))
5154
- ] }),
5155
- /* @__PURE__ */ jsxRuntime.jsxs(
5156
- "div",
5157
- {
5158
- className: "flex items-center justify-between pt-3 mt-2",
5159
- style: { borderTop: "2px solid var(--compass-color-border)" },
5160
- children: [
5161
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", style: { color: "var(--compass-color-text)" }, children: "Total" }),
5162
- /* @__PURE__ */ jsxRuntime.jsx(
5163
- "span",
5164
- {
5165
- className: "font-bold text-xl",
5166
- style: { color: "var(--compass-color-text)" },
5167
- children: formatCurrency(earnAccountTotalUsd)
5168
- }
5169
- )
5170
- ]
5171
- }
5172
- )
5173
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(
5174
- "div",
5175
- {
5176
- className: "text-center py-4",
5177
- style: { color: "var(--compass-color-text-tertiary)" },
5178
- children: "No tokens in account"
5179
- }
5180
- ) })
5181
- }
5182
- ),
5183
- /* @__PURE__ */ jsxRuntime.jsx(
5184
- EarningsModal,
5185
- {
5186
- isOpen: isEarningsModalOpen,
5187
- onClose: () => setIsEarningsModalOpen(false),
5188
- positions,
5189
- totalEarned,
5190
- isLoading: positionQuery.isLoading
5191
- }
5192
- )
5193
- ] });
5194
- }
5195
- function useSwapQuote({ fromToken, toToken, amount, enabled = true }) {
5196
- const { chainId } = useChain();
5197
- const { address } = useCompassWallet();
5198
- const query = reactQuery.useQuery({
5199
- queryKey: ["swapQuote", chainId, fromToken, toToken, amount, address],
5200
- queryFn: async () => {
5201
- if (!fromToken || !toToken || !amount || parseFloat(amount) <= 0 || !address) {
5202
- return null;
5203
- }
5204
- try {
5205
- const params = new URLSearchParams({
5206
- owner: address,
5207
- chain: chainId,
5208
- tokenIn: fromToken,
5209
- tokenOut: toToken,
5210
- amountIn: amount
5211
- });
5212
- const response = await fetch(`/api/compass/swap/quote?${params}`);
5213
- if (!response.ok) {
5214
- const errorData = await response.json();
5215
- const errorMessage = errorData.message || errorData.error || "Failed to get swap quote";
5216
- throw new Error(errorMessage);
5217
- }
5218
- const data = await response.json();
5219
- const outputAmount = data.estimatedAmountOut || "0";
5220
- const inputAmountNum = parseFloat(amount);
5221
- const outputAmountNum = parseFloat(outputAmount);
5222
- return {
5223
- inputAmount: amount,
5224
- outputAmount,
5225
- rate: inputAmountNum > 0 ? (outputAmountNum / inputAmountNum).toString() : "0"
5226
- };
5227
- } catch (error) {
5228
- throw error;
5229
- }
5230
- },
5231
- enabled: enabled && !!address && !!fromToken && !!toToken && !!amount && parseFloat(amount) > 0,
5232
- staleTime: 10 * 1e3,
5233
- refetchInterval: 15 * 1e3,
5234
- retry: 1
5235
- });
5236
- return {
5237
- quote: query.data,
5238
- isLoading: query.isLoading,
5239
- isError: query.isError,
5240
- error: query.error,
5241
- refetch: query.refetch
5242
- };
5243
- }
5244
-
5245
- // src/components/SwapWidget/types.ts
5246
- var DEFAULT_SWAP_TOKENS = ["USDC", "ETH", "WETH", "WBTC", "DAI", "USDT", "AUSD", "SBC"];
5247
- function SwapWidget({
5248
- layout = "full",
5249
- defaultFromToken = "ETH",
5250
- defaultToToken = "USDC",
5251
- allowedTokens = [...DEFAULT_SWAP_TOKENS],
5252
- showReverseButton = true,
5253
- showSettings = false,
5254
- onSwapSuccess,
5255
- onSwapError
5256
- }) {
5257
- const [fromToken, setFromToken] = react.useState(defaultFromToken);
5258
- const [toToken, setToToken] = react.useState(defaultToToken);
5259
- const [fromAmount, setFromAmount] = react.useState("");
5260
- const [isSwapping, setIsSwapping] = react.useState(false);
5261
- const [swapStatus, setSwapStatus] = react.useState("");
5262
- const { address, isConnected, signTypedData } = useCompassWallet();
5263
- const { chainId } = useChain();
5264
- const { quote, isLoading: isQuoteLoading, error: quoteError } = useSwapQuote({
5265
- fromToken,
5266
- toToken,
5267
- amount: fromAmount,
5268
- enabled: !!fromAmount && parseFloat(fromAmount) > 0
5269
- });
5270
- const handleReverse = react.useCallback(() => {
5271
- setFromToken(toToken);
5272
- setToToken(fromToken);
5273
- setFromAmount("");
5274
- }, [fromToken, toToken]);
5275
- const handleSwap = react.useCallback(async () => {
5276
- if (!address || !fromAmount || !quote) return;
5277
- setIsSwapping(true);
5278
- setSwapStatus("Preparing swap...");
5279
- try {
5280
- const prepareResponse = await fetch("/api/compass/swap/prepare", {
5281
- method: "POST",
5282
- headers: { "Content-Type": "application/json" },
5283
- body: JSON.stringify({
5284
- owner: address,
5285
- chain: chainId,
5286
- tokenIn: fromToken,
5287
- tokenOut: toToken,
5288
- amountIn: fromAmount
5289
- })
5290
- });
5291
- if (!prepareResponse.ok) {
5292
- const error = await prepareResponse.json();
5293
- throw new Error(error.error || "Failed to prepare swap");
5294
- }
5295
- const prepareData = await prepareResponse.json();
5296
- const { eip712, normalizedTypes } = prepareData;
5297
- if (!eip712) {
5298
- throw new Error("No EIP-712 data returned from prepare");
5299
- }
5300
- setSwapStatus("Please sign the transaction...");
5301
- const signature = await signTypedData({
5302
- domain: eip712.domain,
5303
- types: normalizedTypes || eip712.types,
5304
- primaryType: "SafeTx",
5305
- message: eip712.message
5306
- });
5307
- setSwapStatus("Executing swap...");
5308
- const executeResponse = await fetch("/api/compass/swap/execute", {
5309
- method: "POST",
5310
- headers: { "Content-Type": "application/json" },
5311
- body: JSON.stringify({
5312
- owner: address,
5313
- chain: chainId,
5314
- eip712,
5315
- signature
5316
- })
5317
- });
5318
- if (!executeResponse.ok) {
5319
- const error = await executeResponse.json();
5320
- throw new Error(error.error || "Failed to execute swap");
5502
+ ] })
5503
+ }
5504
+ ),
5505
+ /* @__PURE__ */ jsxRuntime.jsx(
5506
+ "p",
5507
+ {
5508
+ className: "text-xs text-center",
5509
+ style: { color: "var(--compass-color-text-tertiary)" },
5510
+ children: "Gas fees are sponsored"
5511
+ }
5512
+ )
5513
+ ] })
5321
5514
  }
5322
- const executeData = await executeResponse.json();
5323
- const txHash = executeData.txHash;
5324
- setSwapStatus("Swap successful!");
5325
- onSwapSuccess?.(fromToken, toToken, fromAmount, quote.outputAmount, txHash);
5326
- setFromAmount("");
5327
- setTimeout(() => setSwapStatus(""), 3e3);
5328
- } catch (error) {
5329
- setSwapStatus("");
5330
- onSwapError?.(error);
5331
- } finally {
5332
- setIsSwapping(false);
5333
- }
5334
- }, [address, fromAmount, quote, chainId, fromToken, toToken, signTypedData, onSwapSuccess, onSwapError]);
5335
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "var(--compass-spacing-card)" }, children: [
5336
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between flex-wrap", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
5337
- /* @__PURE__ */ jsxRuntime.jsx(ChainSwitcher, {}),
5338
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
5339
- /* @__PURE__ */ jsxRuntime.jsx(EarnAccountBalance, { compact: true }),
5340
- /* @__PURE__ */ jsxRuntime.jsx(WalletStatus, { compact: true })
5341
- ] })
5342
- ] }),
5343
- /* @__PURE__ */ jsxRuntime.jsxs(EarnAccountGuard, { children: [
5344
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
5345
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border relative", style: { backgroundColor: "var(--compass-color-surface)", borderColor: "var(--compass-color-border)", borderRadius: "var(--compass-border-radius-xl)", fontFamily: "var(--compass-font-family)", padding: "var(--compass-spacing-card)" }, children: [
5346
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between", style: { marginBottom: "calc(var(--compass-spacing-unit) * 0.5)" }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "From" }) }),
5347
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.75)" }, children: [
5515
+ ),
5516
+ /* @__PURE__ */ jsxRuntime.jsx(
5517
+ ActionModal,
5518
+ {
5519
+ isOpen: isBalancesModalOpen,
5520
+ onClose: () => setIsBalancesModalOpen(false),
5521
+ title: "Balance Breakdown",
5522
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: balancesQuery.data?.balances && Object.keys(balancesQuery.data.balances).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5523
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
5348
5524
  /* @__PURE__ */ jsxRuntime.jsx(
5349
- "input",
5525
+ "span",
5350
5526
  {
5351
- type: "number",
5352
- value: fromAmount,
5353
- onChange: (e) => setFromAmount(e.target.value),
5354
- placeholder: "0.00",
5355
- className: "flex-1 bg-transparent outline-none text-2xl font-mono min-w-0",
5356
- style: { color: "var(--compass-color-text)" }
5527
+ className: "text-xs font-medium uppercase tracking-wide",
5528
+ style: { color: "var(--compass-color-text-tertiary)" },
5529
+ children: "Available in Account"
5357
5530
  }
5358
5531
  ),
5359
- /* @__PURE__ */ jsxRuntime.jsx(
5360
- "select",
5532
+ Object.entries(balancesQuery.data.balances).map(([symbol, data]) => /* @__PURE__ */ jsxRuntime.jsxs(
5533
+ "div",
5361
5534
  {
5362
- value: fromToken,
5363
- onChange: (e) => setFromToken(e.target.value),
5364
- className: "border text-sm font-medium cursor-pointer flex-shrink-0",
5365
- style: { backgroundColor: "var(--compass-color-background)", borderColor: "var(--compass-color-border)", color: "var(--compass-color-text)", borderRadius: "var(--compass-border-radius-lg)", padding: "var(--compass-spacing-input)" },
5366
- children: allowedTokens.filter((t) => t !== toToken).map((token) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: token, children: token }, token))
5367
- }
5368
- )
5369
- ] })
5370
- ] }),
5371
- showReverseButton && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center relative z-10", style: { margin: "calc(var(--compass-spacing-unit) * -0.25) 0" }, children: /* @__PURE__ */ jsxRuntime.jsx(
5372
- "button",
5535
+ className: "flex items-center justify-between p-3 rounded-lg",
5536
+ style: {
5537
+ backgroundColor: "var(--compass-color-surface)",
5538
+ border: "1px solid var(--compass-color-border)"
5539
+ },
5540
+ children: [
5541
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", style: { color: "var(--compass-color-text)" }, children: symbol }),
5542
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end", children: [
5543
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-text)" }, children: formatAmount2(data.balance) }),
5544
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: formatCurrency(data.usdValue) })
5545
+ ] })
5546
+ ]
5547
+ },
5548
+ symbol
5549
+ ))
5550
+ ] }),
5551
+ /* @__PURE__ */ jsxRuntime.jsxs(
5552
+ "div",
5553
+ {
5554
+ className: "flex items-center justify-between pt-3 mt-2",
5555
+ style: { borderTop: "2px solid var(--compass-color-border)" },
5556
+ children: [
5557
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", style: { color: "var(--compass-color-text)" }, children: "Total" }),
5558
+ /* @__PURE__ */ jsxRuntime.jsx(
5559
+ "span",
5560
+ {
5561
+ className: "font-bold text-xl",
5562
+ style: { color: "var(--compass-color-text)" },
5563
+ children: formatCurrency(earnAccountTotalUsd)
5564
+ }
5565
+ )
5566
+ ]
5567
+ }
5568
+ )
5569
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
5570
+ "div",
5373
5571
  {
5374
- onClick: handleReverse,
5375
- className: "border hover:opacity-80",
5376
- style: { backgroundColor: "var(--compass-color-surface)", borderColor: "var(--compass-color-border)", borderRadius: "var(--compass-border-radius-full)", padding: "calc(var(--compass-spacing-unit) * 0.5)", transition: "var(--compass-transition-normal)" },
5377
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownUp, { size: 16, style: { color: "var(--compass-color-text-secondary)" } })
5572
+ className: "text-center py-4",
5573
+ style: { color: "var(--compass-color-text-tertiary)" },
5574
+ children: "No tokens in account"
5378
5575
  }
5379
- ) }),
5380
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border", style: { backgroundColor: "var(--compass-color-surface)", borderColor: "var(--compass-color-border)", borderRadius: "var(--compass-border-radius-xl)", fontFamily: "var(--compass-font-family)", padding: "var(--compass-spacing-card)" }, children: [
5381
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between", style: { marginBottom: "calc(var(--compass-spacing-unit) * 0.5)" }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "To" }) }),
5382
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.75)" }, children: [
5383
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 text-2xl font-mono", style: { color: isQuoteLoading ? "var(--compass-color-text-tertiary)" : "var(--compass-color-text)" }, children: isQuoteLoading ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
5384
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 16, className: "animate-spin" }),
5385
- "Loading..."
5386
- ] }) : quote?.outputAmount ? parseFloat(quote.outputAmount).toFixed(8) : "0.00000000" }),
5387
- /* @__PURE__ */ jsxRuntime.jsx(
5388
- "select",
5389
- {
5390
- value: toToken,
5391
- onChange: (e) => setToToken(e.target.value),
5392
- className: "border text-sm font-medium cursor-pointer",
5393
- style: { backgroundColor: "var(--compass-color-background)", borderColor: "var(--compass-color-border)", color: "var(--compass-color-text)", borderRadius: "var(--compass-border-radius-lg)", padding: "var(--compass-spacing-input)" },
5394
- children: allowedTokens.filter((t) => t !== fromToken).map((token) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: token, children: token }, token))
5395
- }
5396
- )
5397
- ] })
5398
- ] })
5399
- ] }),
5400
- quote && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", style: { color: "var(--compass-color-text-secondary)" }, children: [
5401
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Rate" }),
5402
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono", children: [
5403
- "1 ",
5404
- fromToken,
5405
- " = ",
5406
- parseFloat(quote.rate).toFixed(6),
5407
- " ",
5408
- toToken
5409
- ] })
5410
- ] }),
5411
- quoteError && /* @__PURE__ */ jsxRuntime.jsxs(
5412
- "div",
5413
- {
5414
- className: "flex items-center text-sm",
5415
- style: {
5416
- backgroundColor: "var(--compass-color-error-muted)",
5417
- color: "var(--compass-color-error)",
5418
- borderRadius: "var(--compass-border-radius-lg)",
5419
- padding: "calc(var(--compass-spacing-unit) * 0.75)",
5420
- gap: "calc(var(--compass-spacing-unit) * 0.5)"
5421
- },
5422
- children: [
5423
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 16 }),
5424
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: quoteError.message })
5425
- ]
5426
- }
5427
- ),
5428
- swapStatus && /* @__PURE__ */ jsxRuntime.jsxs(
5429
- "div",
5430
- {
5431
- className: "flex items-center text-sm",
5432
- style: {
5433
- backgroundColor: swapStatus.includes("successful") ? "var(--compass-color-success-muted)" : "var(--compass-color-surface)",
5434
- color: swapStatus.includes("successful") ? "var(--compass-color-success)" : "var(--compass-color-text-secondary)",
5435
- borderRadius: "var(--compass-border-radius-lg)",
5436
- padding: "calc(var(--compass-spacing-unit) * 0.75)",
5437
- gap: "calc(var(--compass-spacing-unit) * 0.5)"
5438
- },
5439
- children: [
5440
- !swapStatus.includes("successful") && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 14, className: "animate-spin" }),
5441
- swapStatus
5442
- ]
5443
- }
5444
- ),
5445
- !isConnected ? /* @__PURE__ */ jsxRuntime.jsxs(
5446
- "div",
5447
- {
5448
- className: "flex flex-col items-center",
5449
- style: {
5450
- backgroundColor: "var(--compass-color-surface)",
5451
- border: "1px solid var(--compass-color-border)",
5452
- borderRadius: "var(--compass-border-radius-lg)",
5453
- fontFamily: "var(--compass-font-family)",
5454
- padding: "calc(var(--compass-spacing-unit) * 1.5) var(--compass-spacing-card)",
5455
- gap: "calc(var(--compass-spacing-unit) * 0.75)"
5456
- },
5457
- children: [
5458
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 24, style: { color: "var(--compass-color-text-tertiary)" } }),
5459
- /* @__PURE__ */ jsxRuntime.jsx(
5460
- "p",
5461
- {
5462
- className: "text-sm text-center",
5463
- style: { color: "var(--compass-color-text-secondary)" },
5464
- children: "Connect your wallet to swap"
5465
- }
5466
- )
5467
- ]
5468
- }
5469
- ) : /* @__PURE__ */ jsxRuntime.jsxs(
5470
- "button",
5471
- {
5472
- onClick: handleSwap,
5473
- disabled: isSwapping || !quote || !fromAmount || parseFloat(fromAmount) <= 0,
5474
- className: "w-full font-medium flex items-center justify-center disabled:opacity-50 disabled:cursor-not-allowed",
5475
- style: {
5476
- backgroundColor: "var(--compass-color-primary)",
5477
- color: "var(--compass-color-primary-text)",
5478
- borderRadius: "var(--compass-border-radius-lg)",
5479
- fontFamily: "var(--compass-font-family)",
5480
- padding: "calc(var(--compass-spacing-unit) * 0.75)",
5481
- gap: "calc(var(--compass-spacing-unit) * 0.5)",
5482
- transition: "var(--compass-transition-normal)"
5483
- },
5484
- children: [
5485
- isSwapping && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 18, className: "animate-spin" }),
5486
- isSwapping ? "Swapping..." : "Swap"
5487
- ]
5488
- }
5489
- )
5490
- ] })
5576
+ ) })
5577
+ }
5578
+ ),
5579
+ /* @__PURE__ */ jsxRuntime.jsx(
5580
+ ActionModal,
5581
+ {
5582
+ isOpen: isSwapModalOpen,
5583
+ onClose: () => setIsSwapModalOpen(false),
5584
+ title: "Swap Tokens",
5585
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5586
+ SwapForm,
5587
+ {
5588
+ availableFromTokens: balanceTokens,
5589
+ balances: Object.fromEntries(
5590
+ Object.entries(balancesQuery.data?.balances || {}).map(([token, data]) => [token, data.balance])
5591
+ ),
5592
+ onSwapSuccess: () => {
5593
+ setIsSwapModalOpen(false);
5594
+ queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
5595
+ balancesQuery.refetch();
5596
+ setTimeout(() => {
5597
+ queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
5598
+ balancesQuery.refetch();
5599
+ }, 5e3);
5600
+ setTimeout(() => {
5601
+ queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
5602
+ balancesQuery.refetch();
5603
+ }, 15e3);
5604
+ }
5605
+ }
5606
+ )
5607
+ }
5608
+ ),
5609
+ /* @__PURE__ */ jsxRuntime.jsx(
5610
+ EarningsModal,
5611
+ {
5612
+ isOpen: isEarningsModalOpen,
5613
+ onClose: () => setIsEarningsModalOpen(false),
5614
+ positions,
5615
+ totalEarned,
5616
+ isLoading: positionQuery.isLoading
5617
+ }
5618
+ )
5491
5619
  ] });
5492
5620
  }
5493
5621
  function getEarliestDepositTimestamp(deposits) {
@@ -5974,7 +6102,8 @@ function PositionDetailModal({ position, onClose }) {
5974
6102
  className: "relative w-full max-w-md rounded-xl border overflow-hidden max-h-[90vh] overflow-y-auto",
5975
6103
  style: {
5976
6104
  backgroundColor: "var(--compass-color-background)",
5977
- borderColor: "var(--compass-color-border)"
6105
+ borderColor: "var(--compass-color-border)",
6106
+ scrollbarWidth: "none"
5978
6107
  },
5979
6108
  onClick: (e) => e.stopPropagation(),
5980
6109
  children: [
@@ -6477,7 +6606,7 @@ function useRebalancingData(chainOverride) {
6477
6606
  if (usdValue <= 0) continue;
6478
6607
  balances.push({
6479
6608
  token: symbol,
6480
- balance: parseFloat(td.balanceFormatted || td.balance_formatted || "0"),
6609
+ balance: parseFloat(td.balance || "0"),
6481
6610
  usdValue
6482
6611
  });
6483
6612
  }
@@ -6759,11 +6888,13 @@ function PortfolioBalanceCard({
6759
6888
  totalIdleUsd,
6760
6889
  idleBalances,
6761
6890
  earnAccountAddress,
6891
+ walletAddress,
6762
6892
  onViewPositions,
6763
6893
  positionCount,
6764
6894
  totalEarned = 0,
6765
6895
  showTopUp = true,
6766
- onTopUp
6896
+ onTopUp,
6897
+ onSwap
6767
6898
  }) {
6768
6899
  const [showBalancesModal, setShowBalancesModal] = react.useState(false);
6769
6900
  const tokenBalances = idleBalances.map((b) => ({
@@ -6804,39 +6935,59 @@ function PortfolioBalanceCard({
6804
6935
  ]
6805
6936
  }
6806
6937
  ),
6807
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
6808
- /* @__PURE__ */ jsxRuntime.jsx(
6938
+ /* @__PURE__ */ jsxRuntime.jsx(
6939
+ "button",
6940
+ {
6941
+ onClick: () => setShowBalancesModal(true),
6942
+ className: "transition-opacity hover:opacity-80",
6943
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6944
+ "span",
6945
+ {
6946
+ className: "font-bold",
6947
+ style: {
6948
+ color: "var(--compass-color-text)",
6949
+ fontSize: "2rem",
6950
+ lineHeight: "1"
6951
+ },
6952
+ children: formatUSD(totalUsd)
6953
+ }
6954
+ )
6955
+ }
6956
+ ),
6957
+ (onSwap || showTopUp && onTopUp) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "6px", marginTop: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
6958
+ onSwap && /* @__PURE__ */ jsxRuntime.jsxs(
6809
6959
  "button",
6810
6960
  {
6811
- onClick: () => setShowBalancesModal(true),
6812
- className: "transition-opacity hover:opacity-80",
6813
- children: /* @__PURE__ */ jsxRuntime.jsx(
6814
- "span",
6815
- {
6816
- className: "font-bold",
6817
- style: {
6818
- color: "var(--compass-color-text)",
6819
- fontSize: "2rem",
6820
- lineHeight: "1"
6821
- },
6822
- children: formatUSD(totalUsd)
6823
- }
6824
- )
6961
+ onClick: onSwap,
6962
+ className: "flex items-center justify-center font-medium transition-all hover:opacity-80 w-full",
6963
+ style: {
6964
+ backgroundColor: "var(--compass-color-surface-elevated, var(--compass-color-surface))",
6965
+ border: "1px solid var(--compass-color-border)",
6966
+ color: "var(--compass-color-text-secondary)",
6967
+ borderRadius: "var(--compass-border-radius-md)",
6968
+ padding: "8px 10px",
6969
+ gap: "6px",
6970
+ fontSize: "13px"
6971
+ },
6972
+ children: [
6973
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeftRight, { size: 14 }),
6974
+ "Swap"
6975
+ ]
6825
6976
  }
6826
6977
  ),
6827
6978
  showTopUp && onTopUp && /* @__PURE__ */ jsxRuntime.jsxs(
6828
6979
  "button",
6829
6980
  {
6830
6981
  onClick: onTopUp,
6831
- className: "flex items-center font-medium transition-all hover:opacity-80",
6982
+ className: "flex items-center justify-center font-medium transition-all hover:opacity-80 w-full",
6832
6983
  style: {
6833
6984
  backgroundColor: "var(--compass-color-surface-elevated, var(--compass-color-surface))",
6834
6985
  border: "1px solid var(--compass-color-border)",
6835
6986
  color: "var(--compass-color-text-secondary)",
6836
6987
  borderRadius: "var(--compass-border-radius-md)",
6837
- padding: "6px 10px",
6838
- gap: "4px",
6839
- fontSize: "12px"
6988
+ padding: "8px 10px",
6989
+ gap: "6px",
6990
+ fontSize: "13px"
6840
6991
  },
6841
6992
  children: [
6842
6993
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { size: 14 }),
@@ -6909,7 +7060,8 @@ function PortfolioBalanceCard({
6909
7060
  onClose: () => setShowBalancesModal(false),
6910
7061
  balances: tokenBalances,
6911
7062
  totalUsdValue: totalIdleUsd.toString(),
6912
- earnAccountAddress
7063
+ earnAccountAddress,
7064
+ walletAddress
6913
7065
  }
6914
7066
  )
6915
7067
  ] });
@@ -6935,10 +7087,11 @@ function formatPercent(value) {
6935
7087
  function PercentInput({ value, onChange }) {
6936
7088
  const [localValue, setLocalValue] = react.useState(value.toString());
6937
7089
  const [isFocused, setIsFocused] = react.useState(false);
6938
- if (!isFocused && localValue !== value.toString()) {
7090
+ const roundedStr = parseFloat(value.toFixed(2)).toString();
7091
+ if (!isFocused && localValue !== roundedStr) {
6939
7092
  const parsed = parseFloat(localValue);
6940
7093
  if (isNaN(parsed) || Math.abs(parsed - value) > 1e-3) {
6941
- setLocalValue(value.toString());
7094
+ setLocalValue(roundedStr);
6942
7095
  }
6943
7096
  }
6944
7097
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -6949,7 +7102,7 @@ function PercentInput({ value, onChange }) {
6949
7102
  value: isFocused ? localValue : formatPercent(value).replace("%", ""),
6950
7103
  onFocus: () => {
6951
7104
  setIsFocused(true);
6952
- setLocalValue(value.toString());
7105
+ setLocalValue(parseFloat(value.toFixed(2)).toString());
6953
7106
  },
6954
7107
  onChange: (e) => {
6955
7108
  const raw = e.target.value;
@@ -7073,7 +7226,7 @@ function AllocationEditor({
7073
7226
  currentPos && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7074
7227
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-mono", style: { color: "var(--compass-color-text-secondary)", fontSize: "10px" }, children: formatUSD(currentPos.usdValue) }),
7075
7228
  /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: "var(--compass-color-success)", fontSize: "10px" }, children: [
7076
- currentPos.apy.toFixed(1),
7229
+ currentPos.apy.toFixed(2),
7077
7230
  "%"
7078
7231
  ] })
7079
7232
  ] }),
@@ -7177,7 +7330,6 @@ function AllocationEditor({
7177
7330
  ) })
7178
7331
  ] });
7179
7332
  }
7180
- var SUPPORTED_TOKENS2 = ["USDC", "USDT", "DAI", "WETH", "SBC", "AUSD"];
7181
7333
  var EVM_CHAIN_IDS2 = {
7182
7334
  ethereum: 1,
7183
7335
  base: 8453,
@@ -7204,6 +7356,7 @@ function RebalancingWidget({
7204
7356
  const { chainId: contextChainId, setChainId } = useChain();
7205
7357
  const CHAIN_ID = chain || contextChainId;
7206
7358
  const { address, signTypedData, isConnected, login, switchChain, walletChainId } = useEmbeddableWallet();
7359
+ const { earnAccountAddress } = useEarnAccount();
7207
7360
  const queryClient = reactQuery.useQueryClient();
7208
7361
  const { portfolio, earnAccountMarkets, isMarketsLoading, isLoading, isError, error, refetch } = useRebalancingData(chain);
7209
7362
  const allowedVariableMarketIds = react.useMemo(() => {
@@ -7238,7 +7391,12 @@ function RebalancingWidget({
7238
7391
  const [txHash, setTxHash] = react.useState(null);
7239
7392
  const [hasInitializedTargets, setHasInitializedTargets] = react.useState(false);
7240
7393
  const [isEarningsModalOpen, setIsEarningsModalOpen] = react.useState(false);
7394
+ const [isSwapModalOpen, setIsSwapModalOpen] = react.useState(false);
7241
7395
  const [isAddMarketExpanded, setIsAddMarketExpanded] = react.useState(false);
7396
+ const balanceTokens = react.useMemo(() => {
7397
+ if (!portfolio?.idleBalances) return [];
7398
+ return portfolio.idleBalances.map((b) => b.token);
7399
+ }, [portfolio?.idleBalances]);
7242
7400
  const [marketTab, setMarketTab] = react.useState("variable");
7243
7401
  const [selectedMarket, setSelectedMarket] = react.useState(null);
7244
7402
  const [selectedToken, setSelectedToken] = react.useState("USDC");
@@ -7257,25 +7415,26 @@ function RebalancingWidget({
7257
7415
  setTxHash(null);
7258
7416
  setHasInitializedTargets(false);
7259
7417
  setIsAddMarketExpanded(false);
7418
+ setIsSwapModalOpen(false);
7260
7419
  setSelectedMarket(null);
7261
7420
  setDepositAmount("");
7262
7421
  setDepositError(null);
7263
7422
  setDepositStatus("");
7264
7423
  }, [CHAIN_ID]);
7265
7424
  react.useEffect(() => {
7266
- if (portfolio && portfolio.positions.length > 0 && !hasInitializedTargets) {
7425
+ if (portfolio && portfolio.positions.length > 0 && !hasInitializedTargets && !isLoading) {
7267
7426
  setTargets(
7268
7427
  portfolio.positions.map((p) => ({
7269
7428
  venueType: p.venueType,
7270
7429
  venueAddress: p.venueAddress,
7271
7430
  venueName: p.venueName,
7272
7431
  token: p.token,
7273
- targetPercent: p.allocationPercent
7432
+ targetPercent: parseFloat(p.allocationPercent.toFixed(2))
7274
7433
  }))
7275
7434
  );
7276
7435
  setHasInitializedTargets(true);
7277
7436
  }
7278
- }, [portfolio, hasInitializedTargets]);
7437
+ }, [portfolio, hasInitializedTargets, isLoading]);
7279
7438
  const state = react.useMemo(() => {
7280
7439
  if (isLoading) return "loading";
7281
7440
  if (!portfolio || portfolio.positions.length === 0) return "empty";
@@ -7310,7 +7469,7 @@ function RebalancingWidget({
7310
7469
  venueAddress: p.venueAddress,
7311
7470
  venueName: p.venueName,
7312
7471
  token: p.token,
7313
- targetPercent: p.allocationPercent
7472
+ targetPercent: parseFloat(p.allocationPercent.toFixed(2))
7314
7473
  }))
7315
7474
  );
7316
7475
  setPreviewPlan(null);
@@ -7326,7 +7485,8 @@ function RebalancingWidget({
7326
7485
  setTargets((prev) => prev.filter((_, i) => i !== index));
7327
7486
  }, []);
7328
7487
  const handleUpdatePercent = react.useCallback((index, value) => {
7329
- setTargets((prev) => prev.map((t, i) => i === index ? { ...t, targetPercent: Math.max(0, Math.min(100, value)) } : t));
7488
+ const rounded = parseFloat(Math.max(0, Math.min(100, value)).toFixed(2));
7489
+ setTargets((prev) => prev.map((t, i) => i === index ? { ...t, targetPercent: rounded } : t));
7330
7490
  }, []);
7331
7491
  const ensureCorrectChain = react.useCallback(async () => {
7332
7492
  const targetChainId = EVM_CHAIN_IDS2[CHAIN_ID];
@@ -7698,7 +7858,7 @@ function RebalancingWidget({
7698
7858
  ]
7699
7859
  }
7700
7860
  ),
7701
- state === "empty" && /* @__PURE__ */ jsxRuntime.jsxs(
7861
+ state === "empty" && /* @__PURE__ */ jsxRuntime.jsx(
7702
7862
  "div",
7703
7863
  {
7704
7864
  className: "p-8 text-center",
@@ -7706,7 +7866,32 @@ function RebalancingWidget({
7706
7866
  backgroundColor: "var(--compass-color-surface)",
7707
7867
  borderRadius: "var(--compass-border-radius-xl)"
7708
7868
  },
7709
- children: [
7869
+ children: !isConnected ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7870
+ /* @__PURE__ */ jsxRuntime.jsx(
7871
+ "p",
7872
+ {
7873
+ className: "text-lg font-semibold mb-2",
7874
+ style: { color: "var(--compass-color-text)" },
7875
+ children: "Connect your wallet"
7876
+ }
7877
+ ),
7878
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm mb-4", style: { color: "var(--compass-color-text-secondary)" }, children: "Connect your wallet to view and manage your DeFi portfolio." }),
7879
+ login && /* @__PURE__ */ jsxRuntime.jsx(
7880
+ "button",
7881
+ {
7882
+ onClick: login,
7883
+ className: "font-semibold transition-all",
7884
+ style: {
7885
+ backgroundColor: "var(--compass-color-primary)",
7886
+ color: "var(--compass-color-primary-text, white)",
7887
+ borderRadius: "var(--compass-border-radius-lg)",
7888
+ padding: "calc(var(--compass-spacing-unit) * 0.75) calc(var(--compass-spacing-unit) * 1.5)",
7889
+ fontSize: "0.875rem"
7890
+ },
7891
+ children: "Connect Wallet"
7892
+ }
7893
+ )
7894
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7710
7895
  /* @__PURE__ */ jsxRuntime.jsx(
7711
7896
  "p",
7712
7897
  {
@@ -7716,7 +7901,7 @@ function RebalancingWidget({
7716
7901
  }
7717
7902
  ),
7718
7903
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", style: { color: "var(--compass-color-text-secondary)" }, children: "Deposit into a vault, Aave market, or Pendle market to start rebalancing." })
7719
- ]
7904
+ ] })
7720
7905
  }
7721
7906
  ),
7722
7907
  state !== "loading" && state !== "empty" && portfolio && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "calc(var(--compass-spacing-unit) * 0.75)" }, children: [
@@ -7726,11 +7911,14 @@ function RebalancingWidget({
7726
7911
  totalUsd: portfolio.totalUsd,
7727
7912
  totalIdleUsd: portfolio.totalIdleUsd,
7728
7913
  idleBalances: portfolio.idleBalances,
7914
+ earnAccountAddress: earnAccountAddress ?? void 0,
7915
+ walletAddress: address ?? void 0,
7729
7916
  onViewPositions: () => setIsEarningsModalOpen(true),
7730
7917
  positionCount: portfolio.positions.length,
7731
7918
  totalEarned,
7732
7919
  showTopUp,
7733
- onTopUp: () => earnBalanceRef.current?.openTransferModal()
7920
+ onTopUp: () => earnBalanceRef.current?.openTransferModal(),
7921
+ onSwap: balanceTokens.length > 0 ? () => setIsSwapModalOpen(true) : void 0
7734
7922
  }
7735
7923
  ),
7736
7924
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -7850,7 +8038,7 @@ function RebalancingWidget({
7850
8038
  boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
7851
8039
  minWidth: "100px"
7852
8040
  },
7853
- children: SUPPORTED_TOKENS2.map((token) => /* @__PURE__ */ jsxRuntime.jsx(
8041
+ children: balanceTokens.map((token) => /* @__PURE__ */ jsxRuntime.jsx(
7854
8042
  "button",
7855
8043
  {
7856
8044
  onClick: () => {
@@ -8031,7 +8219,25 @@ function RebalancingWidget({
8031
8219
  children: [
8032
8220
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 24, className: "mx-auto mb-2", style: { color: "var(--compass-color-success)" } }),
8033
8221
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold mb-1", style: { color: "var(--compass-color-success)" }, children: "Rebalance Complete" }),
8034
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-mono break-all", style: { color: "var(--compass-color-text-secondary)" }, children: txHash })
8222
+ /* @__PURE__ */ jsxRuntime.jsxs(
8223
+ "button",
8224
+ {
8225
+ onClick: () => navigator.clipboard.writeText(txHash),
8226
+ className: "inline-flex items-center justify-center gap-1.5 text-xs font-mono break-all mx-auto",
8227
+ style: {
8228
+ color: "var(--compass-color-text-secondary)",
8229
+ background: "none",
8230
+ border: "none",
8231
+ cursor: "pointer",
8232
+ padding: 0
8233
+ },
8234
+ title: "Copy transaction hash",
8235
+ children: [
8236
+ txHash,
8237
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { size: 12, className: "flex-shrink-0", style: { color: "var(--compass-color-text-tertiary)" } })
8238
+ ]
8239
+ }
8240
+ )
8035
8241
  ]
8036
8242
  }
8037
8243
  ),
@@ -8190,6 +8396,30 @@ function RebalancingWidget({
8190
8396
  }
8191
8397
  ) }),
8192
8398
  /* @__PURE__ */ jsxRuntime.jsx(EarnAccountBalance, { ref: earnBalanceRef, compact: true, hideVisual: true, onTransferComplete: () => refetch() }),
8399
+ /* @__PURE__ */ jsxRuntime.jsx(
8400
+ ActionModal,
8401
+ {
8402
+ isOpen: isSwapModalOpen,
8403
+ onClose: () => setIsSwapModalOpen(false),
8404
+ title: "Swap Tokens",
8405
+ children: /* @__PURE__ */ jsxRuntime.jsx(
8406
+ SwapForm,
8407
+ {
8408
+ availableFromTokens: balanceTokens,
8409
+ balances: Object.fromEntries(
8410
+ (portfolio?.idleBalances || []).map((b) => [b.token, b.balance.toString()])
8411
+ ),
8412
+ onSwapSuccess: () => {
8413
+ setIsSwapModalOpen(false);
8414
+ refetch();
8415
+ setTimeout(() => refetch(), 5e3);
8416
+ setTimeout(() => refetch(), 15e3);
8417
+ },
8418
+ onSwapError: onError
8419
+ }
8420
+ )
8421
+ }
8422
+ ),
8193
8423
  /* @__PURE__ */ jsxRuntime.jsx(
8194
8424
  EarningsModal,
8195
8425
  {
@@ -8247,7 +8477,6 @@ function ActionList({ actions }) {
8247
8477
 
8248
8478
  // src/components/CompassEarnWidget/presets.ts
8249
8479
  var allTabs = [
8250
- { id: "swap", label: "Swap", enabled: true },
8251
8480
  { id: "rebalance", label: "Rebalance", enabled: true },
8252
8481
  // TODO: Positions tab temporarily disabled - needs more work on API response handling
8253
8482
  { id: "positions", label: "Positions", enabled: false }
@@ -8256,22 +8485,16 @@ function getTabsForPreset(preset) {
8256
8485
  switch (preset) {
8257
8486
  case "full":
8258
8487
  return allTabs;
8259
- case "swap-only":
8260
- return allTabs.map((tab) => ({
8261
- ...tab,
8262
- enabled: tab.id === "swap"
8263
- }));
8264
8488
  default:
8265
8489
  return allTabs;
8266
8490
  }
8267
8491
  }
8268
8492
  function getDefaultTab(tabs) {
8269
8493
  const enabledTab = tabs.find((t) => t.enabled);
8270
- return enabledTab?.id || "swap";
8494
+ return enabledTab?.id || "rebalance";
8271
8495
  }
8272
8496
  function CompassEarnWidget({
8273
8497
  preset = "full",
8274
- enableSwap,
8275
8498
  enablePositions,
8276
8499
  enableRebalance,
8277
8500
  defaultTab,
@@ -8283,12 +8506,11 @@ function CompassEarnWidget({
8283
8506
  const baseTabs = getTabsForPreset(preset);
8284
8507
  return baseTabs.map((tab) => {
8285
8508
  let enabled = tab.enabled;
8286
- if (tab.id === "swap" && enableSwap !== void 0) enabled = enableSwap;
8287
8509
  if (tab.id === "positions" && enablePositions !== void 0) enabled = enablePositions;
8288
8510
  if (tab.id === "rebalance" && enableRebalance !== void 0) enabled = enableRebalance;
8289
8511
  return { ...tab, enabled };
8290
8512
  });
8291
- }, [preset, enableSwap, enablePositions, enableRebalance]);
8513
+ }, [preset, enablePositions, enableRebalance]);
8292
8514
  const enabledTabs = tabs.filter((t) => t.enabled);
8293
8515
  const initialTab = defaultTab && tabs.find((t) => t.id === defaultTab)?.enabled ? defaultTab : getDefaultTab(tabs);
8294
8516
  const [activeTab, setActiveTab] = react.useState(initialTab);
@@ -8329,7 +8551,6 @@ function CompassEarnWidget({
8329
8551
  }
8330
8552
  ),
8331
8553
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
8332
- activeTab === "swap" && /* @__PURE__ */ jsxRuntime.jsx(SwapWidget, {}),
8333
8554
  activeTab === "rebalance" && /* @__PURE__ */ jsxRuntime.jsx(RebalancingWidget, {}),
8334
8555
  activeTab === "positions" && /* @__PURE__ */ jsxRuntime.jsx(
8335
8556
  EarnPositionsList,
@@ -8368,14 +8589,14 @@ exports.CHAINS = CHAINS;
8368
8589
  exports.ChainSwitcher = ChainSwitcher;
8369
8590
  exports.CompassEarnWidget = CompassEarnWidget;
8370
8591
  exports.CompassProvider = CompassProvider;
8371
- exports.DEFAULT_SWAP_TOKENS = DEFAULT_SWAP_TOKENS;
8592
+ exports.CopyableAddress = CopyableAddress;
8372
8593
  exports.DepositWithdrawForm = DepositWithdrawForm;
8373
8594
  exports.EarnAccount = EarnAccount;
8374
8595
  exports.EarnAccountBalance = EarnAccountBalance;
8375
8596
  exports.EarnAccountGuard = EarnAccountGuard;
8376
8597
  exports.PnLSummary = PnLSummary;
8377
8598
  exports.RebalancingWidget = RebalancingWidget;
8378
- exports.SwapWidget = SwapWidget;
8599
+ exports.SwapForm = SwapForm;
8379
8600
  exports.ThemeProvider = ThemeProvider;
8380
8601
  exports.TransactionHistory = TransactionHistory;
8381
8602
  exports.WalletStatus = WalletStatus;