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