@compass-labs/widgets 0.1.0 → 0.1.2
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 +56 -35
- package/dist/index.d.ts +56 -35
- package/dist/index.js +1386 -333
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1387 -335
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.js +439 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +439 -0
- package/dist/server/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createContext, useMemo, useContext, useState, useEffect, useCallback } from 'react';
|
|
1
|
+
import { createContext, useMemo, useContext, useState, useEffect, useCallback, useRef } from 'react';
|
|
2
2
|
import { QueryClient, QueryClientProvider, useQueryClient, useQuery } from '@tanstack/react-query';
|
|
3
3
|
import { CompassApiSDK } from '@compass-labs/api-sdk';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { arbitrum, base, mainnet } from 'viem/chains';
|
|
6
|
-
import { Wallet, LogOut, X, ChevronDown, AlertCircle, Loader2, ArrowDownLeft, ArrowUpRight, ExternalLink, Search, TrendingUp, Calendar, ArrowDownUp } from 'lucide-react';
|
|
6
|
+
import { Wallet, LogOut, X, ChevronDown, AlertCircle, ArrowRight, Loader2, ArrowDownLeft, ArrowUpRight, ExternalLink, Coins, Search, SlidersHorizontal, TrendingUp, Calendar, ArrowDownUp } from 'lucide-react';
|
|
7
7
|
|
|
8
8
|
// src/provider/CompassProvider.tsx
|
|
9
9
|
var ApiContext = createContext(null);
|
|
@@ -79,6 +79,7 @@ var WalletContext = createContext(null);
|
|
|
79
79
|
var disconnectedWallet = {
|
|
80
80
|
address: null,
|
|
81
81
|
isConnected: false,
|
|
82
|
+
walletChainId: void 0,
|
|
82
83
|
signTypedData: async () => {
|
|
83
84
|
throw new Error("No wallet connected. Please connect a wallet first.");
|
|
84
85
|
},
|
|
@@ -90,6 +91,7 @@ function WalletProvider({ children, wallet }) {
|
|
|
90
91
|
const value = wallet ? {
|
|
91
92
|
address: wallet.address,
|
|
92
93
|
isConnected: wallet.address !== null,
|
|
94
|
+
walletChainId: wallet.chainId,
|
|
93
95
|
signTypedData: wallet.signTypedData,
|
|
94
96
|
switchChain: wallet.switchChain ?? null,
|
|
95
97
|
login: wallet.login ?? null,
|
|
@@ -1121,7 +1123,7 @@ function PnLSummary({ pnl, tokenSymbol, tokenPrice }) {
|
|
|
1121
1123
|
const prefix = value >= 0 ? "+" : "";
|
|
1122
1124
|
return `${prefix}${value.toFixed(4)}`;
|
|
1123
1125
|
};
|
|
1124
|
-
const
|
|
1126
|
+
const formatUSD2 = (value) => {
|
|
1125
1127
|
const usdValue = value * tokenPrice;
|
|
1126
1128
|
const prefix = usdValue >= 0 ? "+$" : "-$";
|
|
1127
1129
|
return `${prefix}${Math.abs(usdValue).toFixed(2)}`;
|
|
@@ -1198,7 +1200,7 @@ function PnLSummary({ pnl, tokenSymbol, tokenPrice }) {
|
|
|
1198
1200
|
children: formatPnL(unrealizedPnl)
|
|
1199
1201
|
}
|
|
1200
1202
|
),
|
|
1201
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-mono", style: { color: pnlColor(unrealizedPnl) }, children:
|
|
1203
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-mono", style: { color: pnlColor(unrealizedPnl) }, children: formatUSD2(unrealizedPnl) })
|
|
1202
1204
|
] }),
|
|
1203
1205
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
1204
1206
|
/* @__PURE__ */ jsx(
|
|
@@ -1217,7 +1219,7 @@ function PnLSummary({ pnl, tokenSymbol, tokenPrice }) {
|
|
|
1217
1219
|
children: formatPnL(realizedPnl)
|
|
1218
1220
|
}
|
|
1219
1221
|
),
|
|
1220
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-mono", style: { color: pnlColor(realizedPnl) }, children:
|
|
1222
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-mono", style: { color: pnlColor(realizedPnl) }, children: formatUSD2(realizedPnl) })
|
|
1221
1223
|
] })
|
|
1222
1224
|
] }),
|
|
1223
1225
|
/* @__PURE__ */ jsxs(
|
|
@@ -1242,7 +1244,7 @@ function PnLSummary({ pnl, tokenSymbol, tokenPrice }) {
|
|
|
1242
1244
|
] }),
|
|
1243
1245
|
/* @__PURE__ */ jsxs("span", { className: "text-xs font-mono", style: { color: pnlColor(totalPnl) }, children: [
|
|
1244
1246
|
"(",
|
|
1245
|
-
|
|
1247
|
+
formatUSD2(totalPnl),
|
|
1246
1248
|
")"
|
|
1247
1249
|
] })
|
|
1248
1250
|
] })
|
|
@@ -1254,161 +1256,327 @@ function PnLSummary({ pnl, tokenSymbol, tokenPrice }) {
|
|
|
1254
1256
|
)
|
|
1255
1257
|
] });
|
|
1256
1258
|
}
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1259
|
+
|
|
1260
|
+
// src/utils/format.ts
|
|
1261
|
+
function formatAmount(value) {
|
|
1262
|
+
const num = typeof value === "string" ? parseFloat(value) : value;
|
|
1263
|
+
if (isNaN(num)) return "0";
|
|
1264
|
+
return parseFloat(num.toFixed(6)).toString();
|
|
1265
|
+
}
|
|
1266
|
+
function formatUSD(value) {
|
|
1267
|
+
const num = typeof value === "string" ? parseFloat(value) : value;
|
|
1268
|
+
if (isNaN(num)) return "$0.00";
|
|
1269
|
+
return new Intl.NumberFormat("en-US", {
|
|
1270
|
+
style: "currency",
|
|
1271
|
+
currency: "USD",
|
|
1272
|
+
minimumFractionDigits: 2,
|
|
1273
|
+
maximumFractionDigits: 2
|
|
1274
|
+
}).format(num);
|
|
1275
|
+
}
|
|
1276
|
+
function TokenSelector({
|
|
1277
|
+
tokens,
|
|
1278
|
+
selectedToken,
|
|
1279
|
+
onSelect,
|
|
1280
|
+
balances,
|
|
1281
|
+
showBalances = true,
|
|
1282
|
+
disabled = false
|
|
1283
|
+
}) {
|
|
1284
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
1285
|
+
const dropdownRef = useRef(null);
|
|
1286
|
+
useEffect(() => {
|
|
1287
|
+
function handleClickOutside(event) {
|
|
1288
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
1289
|
+
setIsOpen(false);
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1293
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1294
|
+
}, []);
|
|
1295
|
+
const handleSelect = (token) => {
|
|
1296
|
+
onSelect(token);
|
|
1297
|
+
setIsOpen(false);
|
|
1298
|
+
};
|
|
1299
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", ref: dropdownRef, children: [
|
|
1300
|
+
/* @__PURE__ */ jsxs(
|
|
1301
|
+
"button",
|
|
1302
|
+
{
|
|
1303
|
+
type: "button",
|
|
1304
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
1305
|
+
disabled,
|
|
1306
|
+
className: "flex items-center gap-2 px-3 py-2 rounded-lg border transition-colors min-w-[120px]",
|
|
1307
|
+
style: {
|
|
1308
|
+
backgroundColor: "var(--compass-color-background)",
|
|
1309
|
+
borderColor: isOpen ? "var(--compass-color-primary)" : "var(--compass-color-border)",
|
|
1310
|
+
color: "var(--compass-color-text)",
|
|
1311
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
1312
|
+
opacity: disabled ? 0.5 : 1
|
|
1313
|
+
},
|
|
1314
|
+
children: [
|
|
1315
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium flex-1 text-left", children: selectedToken }),
|
|
1316
|
+
/* @__PURE__ */ jsx(
|
|
1317
|
+
ChevronDown,
|
|
1318
|
+
{
|
|
1319
|
+
size: 16,
|
|
1320
|
+
style: {
|
|
1321
|
+
color: "var(--compass-color-text-secondary)",
|
|
1322
|
+
transform: isOpen ? "rotate(180deg)" : "rotate(0deg)",
|
|
1323
|
+
transition: "transform 0.2s"
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
)
|
|
1327
|
+
]
|
|
1328
|
+
}
|
|
1329
|
+
),
|
|
1330
|
+
isOpen && /* @__PURE__ */ jsx(
|
|
1331
|
+
"div",
|
|
1332
|
+
{
|
|
1333
|
+
className: "absolute z-50 mt-1 w-full min-w-[160px] rounded-lg border overflow-y-auto",
|
|
1334
|
+
style: {
|
|
1335
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
1336
|
+
borderColor: "var(--compass-color-border)",
|
|
1337
|
+
boxShadow: "var(--compass-shadow-lg)",
|
|
1338
|
+
maxHeight: "200px"
|
|
1339
|
+
},
|
|
1340
|
+
children: tokens.map((token) => {
|
|
1341
|
+
const balance = balances?.[token];
|
|
1342
|
+
const isSelected = token === selectedToken;
|
|
1343
|
+
return /* @__PURE__ */ jsxs(
|
|
1344
|
+
"button",
|
|
1345
|
+
{
|
|
1346
|
+
type: "button",
|
|
1347
|
+
onClick: () => handleSelect(token),
|
|
1348
|
+
className: "w-full px-3 py-2 flex items-center justify-between transition-colors",
|
|
1349
|
+
style: {
|
|
1350
|
+
backgroundColor: isSelected ? "var(--compass-color-primary-muted)" : "transparent",
|
|
1351
|
+
color: "var(--compass-color-text)"
|
|
1352
|
+
},
|
|
1353
|
+
onMouseEnter: (e) => {
|
|
1354
|
+
if (!isSelected) {
|
|
1355
|
+
e.currentTarget.style.backgroundColor = "var(--compass-color-surface-hover)";
|
|
1356
|
+
}
|
|
1357
|
+
},
|
|
1358
|
+
onMouseLeave: (e) => {
|
|
1359
|
+
if (!isSelected) {
|
|
1360
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
1361
|
+
}
|
|
1362
|
+
},
|
|
1363
|
+
children: [
|
|
1364
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: token }),
|
|
1365
|
+
showBalances && balance && /* @__PURE__ */ jsx(
|
|
1366
|
+
"span",
|
|
1367
|
+
{
|
|
1368
|
+
className: "text-sm font-mono",
|
|
1369
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
1370
|
+
children: formatAmount(balance)
|
|
1371
|
+
}
|
|
1372
|
+
)
|
|
1373
|
+
]
|
|
1374
|
+
},
|
|
1375
|
+
token
|
|
1376
|
+
);
|
|
1377
|
+
})
|
|
1378
|
+
}
|
|
1379
|
+
)
|
|
1380
|
+
] });
|
|
1381
|
+
}
|
|
1286
1382
|
function DepositWithdrawForm({
|
|
1287
1383
|
venueType,
|
|
1288
1384
|
venueAddress,
|
|
1289
|
-
|
|
1290
|
-
|
|
1385
|
+
venueToken,
|
|
1386
|
+
depositTokens = ["SBC", "AUSD", "USDC", "USDT", "WETH", "DAI"],
|
|
1291
1387
|
positionBalance = "0",
|
|
1292
1388
|
onSuccess,
|
|
1293
1389
|
onError
|
|
1294
1390
|
}) {
|
|
1295
1391
|
const [activeTab, setActiveTab] = useState("deposit");
|
|
1392
|
+
const [selectedToken, setSelectedToken] = useState(venueToken);
|
|
1296
1393
|
const [amount, setAmount] = useState("");
|
|
1297
1394
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
1298
1395
|
const [statusMessage, setStatusMessage] = useState("");
|
|
1299
1396
|
const [error, setError] = useState(null);
|
|
1300
1397
|
const { address, isConnected, signTypedData, switchChain } = useCompassWallet();
|
|
1301
|
-
const {
|
|
1302
|
-
const { chainId } = useChain();
|
|
1398
|
+
const { chainId, chain } = useChain();
|
|
1303
1399
|
const { earnAccountAddress } = useEarnAccount();
|
|
1304
1400
|
const queryClient = useQueryClient();
|
|
1305
|
-
const
|
|
1306
|
-
const targetChainId = chainConfig?.viemChain?.id;
|
|
1401
|
+
const needsSwap = activeTab === "deposit" && selectedToken !== venueToken;
|
|
1307
1402
|
const { data: tokenBalance } = useQuery({
|
|
1308
|
-
queryKey: ["earnAccountTokenBalance", chainId, earnAccountAddress,
|
|
1403
|
+
queryKey: ["earnAccountTokenBalance", chainId, earnAccountAddress, selectedToken],
|
|
1309
1404
|
queryFn: async () => {
|
|
1310
1405
|
if (!earnAccountAddress) return "0";
|
|
1311
1406
|
try {
|
|
1312
|
-
const response = await
|
|
1313
|
-
chain
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
return
|
|
1318
|
-
} catch
|
|
1319
|
-
console.error("Error fetching earn account token balance:", error2);
|
|
1407
|
+
const response = await fetch(
|
|
1408
|
+
`/api/compass/earn-account/balances?owner=${address}&chain=${chainId}&tokens=${selectedToken}`
|
|
1409
|
+
);
|
|
1410
|
+
if (!response.ok) return "0";
|
|
1411
|
+
const data = await response.json();
|
|
1412
|
+
return data.balances?.[selectedToken]?.balance || "0";
|
|
1413
|
+
} catch {
|
|
1320
1414
|
return "0";
|
|
1321
1415
|
}
|
|
1322
1416
|
},
|
|
1323
|
-
enabled: !!earnAccountAddress,
|
|
1417
|
+
enabled: !!earnAccountAddress && !!address,
|
|
1324
1418
|
staleTime: 10 * 1e3
|
|
1325
1419
|
});
|
|
1326
1420
|
const availableBalance = tokenBalance || "0";
|
|
1327
1421
|
const maxBalance = activeTab === "deposit" ? availableBalance : positionBalance;
|
|
1328
|
-
const handleQuickAmount = useCallback(
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1422
|
+
const handleQuickAmount = useCallback(
|
|
1423
|
+
(percentage) => {
|
|
1424
|
+
const max = parseFloat(maxBalance);
|
|
1425
|
+
if (isNaN(max)) return;
|
|
1426
|
+
setAmount(formatAmount(max * percentage));
|
|
1427
|
+
},
|
|
1428
|
+
[maxBalance]
|
|
1429
|
+
);
|
|
1333
1430
|
const handleSubmit = useCallback(async () => {
|
|
1334
1431
|
if (!address || !amount) return;
|
|
1335
1432
|
setIsSubmitting(true);
|
|
1336
1433
|
setStatusMessage("Preparing transaction...");
|
|
1337
1434
|
setError(null);
|
|
1338
1435
|
try {
|
|
1339
|
-
|
|
1340
|
-
|
|
1436
|
+
const targetChainId = chain.viemChain.id;
|
|
1437
|
+
if (switchChain) {
|
|
1438
|
+
setStatusMessage("Switching network...");
|
|
1341
1439
|
try {
|
|
1342
1440
|
await switchChain(targetChainId);
|
|
1343
1441
|
} catch {
|
|
1442
|
+
throw new Error(`Please switch your wallet to ${chain.name} to continue`);
|
|
1344
1443
|
}
|
|
1345
1444
|
}
|
|
1346
1445
|
const isDeposit = activeTab === "deposit";
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1446
|
+
if (isDeposit && needsSwap) {
|
|
1447
|
+
setStatusMessage("Getting swap quote...");
|
|
1448
|
+
const quoteResponse = await fetch(
|
|
1449
|
+
`/api/compass/swap/quote?owner=${address}&chain=${chainId}&tokenIn=${selectedToken}&tokenOut=${venueToken}&amountIn=${amount}`
|
|
1450
|
+
);
|
|
1451
|
+
if (!quoteResponse.ok) {
|
|
1452
|
+
const errorData = await quoteResponse.json();
|
|
1453
|
+
throw new Error(errorData.error || "Failed to get swap quote");
|
|
1454
|
+
}
|
|
1455
|
+
const quoteData = await quoteResponse.json();
|
|
1456
|
+
const estimatedOutput = quoteData.estimatedAmountOut;
|
|
1457
|
+
if (!estimatedOutput || parseFloat(estimatedOutput) <= 0) {
|
|
1458
|
+
throw new Error("Invalid swap quote - no output amount");
|
|
1459
|
+
}
|
|
1460
|
+
const depositAmount = (parseFloat(estimatedOutput) * 0.99).toString();
|
|
1461
|
+
setStatusMessage("Preparing swap and deposit...");
|
|
1462
|
+
const bundleActions = [
|
|
1463
|
+
{
|
|
1464
|
+
body: {
|
|
1465
|
+
actionType: "V2_SWAP",
|
|
1466
|
+
tokenIn: selectedToken,
|
|
1467
|
+
tokenOut: venueToken,
|
|
1468
|
+
amountIn: amount,
|
|
1469
|
+
maxSlippagePercent: 1
|
|
1470
|
+
}
|
|
1471
|
+
},
|
|
1472
|
+
{
|
|
1473
|
+
body: {
|
|
1474
|
+
actionType: "V2_MANAGE",
|
|
1475
|
+
action: "DEPOSIT",
|
|
1476
|
+
venue: venueType === "VAULT" ? { type: "VAULT", vaultAddress: venueAddress } : venueType === "AAVE" ? { type: "AAVE", token: venueToken } : { type: "PENDLE_PT", marketAddress: venueAddress },
|
|
1477
|
+
amount: depositAmount
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
];
|
|
1481
|
+
const prepareResponse = await fetch("/api/compass/bundle/prepare", {
|
|
1482
|
+
method: "POST",
|
|
1483
|
+
headers: { "Content-Type": "application/json" },
|
|
1484
|
+
body: JSON.stringify({
|
|
1485
|
+
owner: address,
|
|
1486
|
+
chain: chainId,
|
|
1487
|
+
actions: bundleActions
|
|
1488
|
+
})
|
|
1489
|
+
});
|
|
1490
|
+
if (!prepareResponse.ok) {
|
|
1491
|
+
const errorData = await prepareResponse.json();
|
|
1492
|
+
throw new Error(errorData.error || "Failed to prepare bundle");
|
|
1493
|
+
}
|
|
1494
|
+
const { eip712, normalizedTypes, domain, message } = await prepareResponse.json();
|
|
1495
|
+
setStatusMessage("Please sign the transaction...");
|
|
1496
|
+
const signature = await signTypedData({
|
|
1497
|
+
domain,
|
|
1498
|
+
types: normalizedTypes,
|
|
1499
|
+
primaryType: "SafeTx",
|
|
1500
|
+
message
|
|
1501
|
+
});
|
|
1502
|
+
setStatusMessage("Executing swap and deposit...");
|
|
1503
|
+
const executeResponse = await fetch("/api/compass/bundle/execute", {
|
|
1504
|
+
method: "POST",
|
|
1505
|
+
headers: { "Content-Type": "application/json" },
|
|
1506
|
+
body: JSON.stringify({
|
|
1507
|
+
owner: address,
|
|
1508
|
+
eip712,
|
|
1509
|
+
signature,
|
|
1510
|
+
chain: chainId
|
|
1511
|
+
})
|
|
1512
|
+
});
|
|
1513
|
+
if (!executeResponse.ok) {
|
|
1514
|
+
const errorData = await executeResponse.json();
|
|
1515
|
+
throw new Error(errorData.error || "Failed to execute bundle");
|
|
1516
|
+
}
|
|
1517
|
+
const { txHash } = await executeResponse.json();
|
|
1518
|
+
setStatusMessage("Transaction successful!");
|
|
1519
|
+
onSuccess?.(activeTab, amount, txHash);
|
|
1520
|
+
setAmount("");
|
|
1521
|
+
} else {
|
|
1522
|
+
const prepareEndpoint = isDeposit ? "/api/compass/deposit/prepare" : "/api/compass/withdraw/prepare";
|
|
1523
|
+
const executeEndpoint = isDeposit ? "/api/compass/deposit/execute" : "/api/compass/withdraw/execute";
|
|
1524
|
+
const prepareBody = {
|
|
1525
|
+
amount,
|
|
1526
|
+
token: venueToken,
|
|
1385
1527
|
owner: address,
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1528
|
+
chain: chainId,
|
|
1529
|
+
venueType
|
|
1530
|
+
};
|
|
1531
|
+
if (venueType === "VAULT") {
|
|
1532
|
+
prepareBody.vaultAddress = venueAddress;
|
|
1533
|
+
} else if (venueType === "PENDLE_PT") {
|
|
1534
|
+
prepareBody.marketAddress = venueAddress;
|
|
1535
|
+
prepareBody.maxSlippagePercent = 1;
|
|
1536
|
+
}
|
|
1537
|
+
setStatusMessage("Getting transaction data...");
|
|
1538
|
+
const prepareResponse = await fetch(prepareEndpoint, {
|
|
1539
|
+
method: "POST",
|
|
1540
|
+
headers: { "Content-Type": "application/json" },
|
|
1541
|
+
body: JSON.stringify(prepareBody)
|
|
1542
|
+
});
|
|
1543
|
+
if (!prepareResponse.ok) {
|
|
1544
|
+
const errorData = await prepareResponse.json();
|
|
1545
|
+
throw new Error(errorData.error || "Failed to prepare transaction");
|
|
1546
|
+
}
|
|
1547
|
+
const { eip712, normalizedTypes, domain, message } = await prepareResponse.json();
|
|
1548
|
+
setStatusMessage("Please sign the transaction...");
|
|
1549
|
+
const signature = await signTypedData({
|
|
1550
|
+
domain,
|
|
1551
|
+
types: normalizedTypes,
|
|
1552
|
+
primaryType: "SafeTx",
|
|
1553
|
+
message
|
|
1554
|
+
});
|
|
1555
|
+
setStatusMessage("Executing transaction...");
|
|
1556
|
+
const executeResponse = await fetch(executeEndpoint, {
|
|
1557
|
+
method: "POST",
|
|
1558
|
+
headers: { "Content-Type": "application/json" },
|
|
1559
|
+
body: JSON.stringify({
|
|
1560
|
+
owner: address,
|
|
1561
|
+
eip712,
|
|
1562
|
+
signature,
|
|
1563
|
+
chain: chainId
|
|
1564
|
+
})
|
|
1565
|
+
});
|
|
1566
|
+
if (!executeResponse.ok) {
|
|
1567
|
+
const errorData = await executeResponse.json();
|
|
1568
|
+
throw new Error(errorData.error || "Failed to execute transaction");
|
|
1569
|
+
}
|
|
1570
|
+
const { txHash } = await executeResponse.json();
|
|
1571
|
+
setStatusMessage("Transaction successful!");
|
|
1572
|
+
onSuccess?.(activeTab, amount, txHash);
|
|
1573
|
+
setAmount("");
|
|
1394
1574
|
}
|
|
1395
|
-
const { txHash } = await executeResponse.json();
|
|
1396
|
-
setStatusMessage("Transaction successful!");
|
|
1397
|
-
onSuccess?.(activeTab, amount, txHash);
|
|
1398
|
-
setAmount("");
|
|
1399
1575
|
queryClient.invalidateQueries({ queryKey: ["earnAccountTokenBalance"] });
|
|
1400
1576
|
queryClient.invalidateQueries({ queryKey: ["vaults"] });
|
|
1401
|
-
queryClient.invalidateQueries({ queryKey: ["vaultPositions"] });
|
|
1402
1577
|
queryClient.invalidateQueries({ queryKey: ["aaveMarkets"] });
|
|
1403
|
-
queryClient.invalidateQueries({ queryKey: ["aavePositions"] });
|
|
1404
1578
|
queryClient.invalidateQueries({ queryKey: ["pendleMarkets"] });
|
|
1405
|
-
queryClient.invalidateQueries({ queryKey: ["pendlePositions"] });
|
|
1406
1579
|
setTimeout(() => setStatusMessage(""), 3e3);
|
|
1407
|
-
setTimeout(() => {
|
|
1408
|
-
queryClient.invalidateQueries({ queryKey: ["earnAccountTokenBalance"] });
|
|
1409
|
-
queryClient.invalidateQueries({ queryKey: ["vaults"] });
|
|
1410
|
-
queryClient.invalidateQueries({ queryKey: ["vaultPositions"] });
|
|
1411
|
-
}, 5e3);
|
|
1412
1580
|
} catch (err) {
|
|
1413
1581
|
console.error("Transaction failed:", err);
|
|
1414
1582
|
const errorMessage = err instanceof Error ? err.message : "Transaction failed";
|
|
@@ -1421,11 +1589,13 @@ function DepositWithdrawForm({
|
|
|
1421
1589
|
address,
|
|
1422
1590
|
amount,
|
|
1423
1591
|
chainId,
|
|
1424
|
-
|
|
1592
|
+
chain,
|
|
1425
1593
|
activeTab,
|
|
1594
|
+
needsSwap,
|
|
1595
|
+
selectedToken,
|
|
1596
|
+
venueToken,
|
|
1426
1597
|
venueType,
|
|
1427
1598
|
venueAddress,
|
|
1428
|
-
tokenSymbol,
|
|
1429
1599
|
signTypedData,
|
|
1430
1600
|
switchChain,
|
|
1431
1601
|
queryClient,
|
|
@@ -1466,6 +1636,7 @@ function DepositWithdrawForm({
|
|
|
1466
1636
|
{
|
|
1467
1637
|
onClick: () => {
|
|
1468
1638
|
setActiveTab(tab);
|
|
1639
|
+
setSelectedToken(venueToken);
|
|
1469
1640
|
setError(null);
|
|
1470
1641
|
setStatusMessage("");
|
|
1471
1642
|
},
|
|
@@ -1480,6 +1651,45 @@ function DepositWithdrawForm({
|
|
|
1480
1651
|
))
|
|
1481
1652
|
}
|
|
1482
1653
|
),
|
|
1654
|
+
activeTab === "deposit" && /* @__PURE__ */ jsxs("div", { children: [
|
|
1655
|
+
/* @__PURE__ */ jsx(
|
|
1656
|
+
"label",
|
|
1657
|
+
{
|
|
1658
|
+
className: "text-sm font-medium mb-1 block",
|
|
1659
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
1660
|
+
children: "From Token"
|
|
1661
|
+
}
|
|
1662
|
+
),
|
|
1663
|
+
/* @__PURE__ */ jsx(
|
|
1664
|
+
TokenSelector,
|
|
1665
|
+
{
|
|
1666
|
+
tokens: depositTokens,
|
|
1667
|
+
selectedToken,
|
|
1668
|
+
onSelect: setSelectedToken,
|
|
1669
|
+
disabled: isSubmitting
|
|
1670
|
+
}
|
|
1671
|
+
)
|
|
1672
|
+
] }),
|
|
1673
|
+
needsSwap && /* @__PURE__ */ jsxs(
|
|
1674
|
+
"div",
|
|
1675
|
+
{
|
|
1676
|
+
className: "flex items-center gap-2 p-2 rounded-lg text-sm",
|
|
1677
|
+
style: {
|
|
1678
|
+
backgroundColor: "var(--compass-color-primary-muted)",
|
|
1679
|
+
color: "var(--compass-color-primary)"
|
|
1680
|
+
},
|
|
1681
|
+
children: [
|
|
1682
|
+
/* @__PURE__ */ jsx(ArrowRight, { size: 14 }),
|
|
1683
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1684
|
+
"Swaps ",
|
|
1685
|
+
selectedToken,
|
|
1686
|
+
" to ",
|
|
1687
|
+
venueToken,
|
|
1688
|
+
", then deposits"
|
|
1689
|
+
] })
|
|
1690
|
+
]
|
|
1691
|
+
}
|
|
1692
|
+
),
|
|
1483
1693
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
1484
1694
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-1", children: [
|
|
1485
1695
|
/* @__PURE__ */ jsx(
|
|
@@ -1492,9 +1702,9 @@ function DepositWithdrawForm({
|
|
|
1492
1702
|
),
|
|
1493
1703
|
/* @__PURE__ */ jsxs("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: [
|
|
1494
1704
|
"Available: ",
|
|
1495
|
-
|
|
1705
|
+
formatAmount(maxBalance),
|
|
1496
1706
|
" ",
|
|
1497
|
-
|
|
1707
|
+
activeTab === "deposit" ? selectedToken : venueToken
|
|
1498
1708
|
] })
|
|
1499
1709
|
] }),
|
|
1500
1710
|
/* @__PURE__ */ jsxs(
|
|
@@ -1525,7 +1735,7 @@ function DepositWithdrawForm({
|
|
|
1525
1735
|
{
|
|
1526
1736
|
className: "text-sm font-medium",
|
|
1527
1737
|
style: { color: "var(--compass-color-text-secondary)" },
|
|
1528
|
-
children:
|
|
1738
|
+
children: activeTab === "deposit" ? selectedToken : venueToken
|
|
1529
1739
|
}
|
|
1530
1740
|
)
|
|
1531
1741
|
]
|
|
@@ -1550,8 +1760,8 @@ function DepositWithdrawForm({
|
|
|
1550
1760
|
{
|
|
1551
1761
|
className: "p-3 rounded-lg text-sm",
|
|
1552
1762
|
style: {
|
|
1553
|
-
backgroundColor: "var(--compass-color-error-muted
|
|
1554
|
-
color: "var(--compass-color-error
|
|
1763
|
+
backgroundColor: "var(--compass-color-error-muted)",
|
|
1764
|
+
color: "var(--compass-color-error)"
|
|
1555
1765
|
},
|
|
1556
1766
|
children: error
|
|
1557
1767
|
}
|
|
@@ -1561,8 +1771,8 @@ function DepositWithdrawForm({
|
|
|
1561
1771
|
{
|
|
1562
1772
|
className: "p-3 rounded-lg text-sm text-center",
|
|
1563
1773
|
style: {
|
|
1564
|
-
backgroundColor: "var(--compass-color-success-muted
|
|
1565
|
-
color: "var(--compass-color-success
|
|
1774
|
+
backgroundColor: "var(--compass-color-success-muted)",
|
|
1775
|
+
color: "var(--compass-color-success)"
|
|
1566
1776
|
},
|
|
1567
1777
|
children: statusMessage
|
|
1568
1778
|
}
|
|
@@ -1579,7 +1789,7 @@ function DepositWithdrawForm({
|
|
|
1579
1789
|
},
|
|
1580
1790
|
children: [
|
|
1581
1791
|
isSubmitting && /* @__PURE__ */ jsx(Loader2, { size: 18, className: "animate-spin" }),
|
|
1582
|
-
isSubmitting ? "Processing..." : activeTab === "deposit" ? "Deposit" : "Withdraw"
|
|
1792
|
+
isSubmitting ? "Processing..." : needsSwap ? `Swap & ${activeTab === "deposit" ? "Deposit" : "Withdraw"}` : activeTab === "deposit" ? "Deposit" : "Withdraw"
|
|
1583
1793
|
]
|
|
1584
1794
|
}
|
|
1585
1795
|
)
|
|
@@ -1887,6 +2097,678 @@ function EarnAccountGuard({
|
|
|
1887
2097
|
}
|
|
1888
2098
|
);
|
|
1889
2099
|
}
|
|
2100
|
+
function AccountBalancesModal({
|
|
2101
|
+
isOpen,
|
|
2102
|
+
onClose,
|
|
2103
|
+
balances,
|
|
2104
|
+
totalUsdValue,
|
|
2105
|
+
isLoading = false,
|
|
2106
|
+
earnAccountAddress
|
|
2107
|
+
}) {
|
|
2108
|
+
useEffect(() => {
|
|
2109
|
+
const handleEscape = (e) => {
|
|
2110
|
+
if (e.key === "Escape") onClose();
|
|
2111
|
+
};
|
|
2112
|
+
if (isOpen) {
|
|
2113
|
+
document.addEventListener("keydown", handleEscape);
|
|
2114
|
+
document.body.style.overflow = "hidden";
|
|
2115
|
+
}
|
|
2116
|
+
return () => {
|
|
2117
|
+
document.removeEventListener("keydown", handleEscape);
|
|
2118
|
+
document.body.style.overflow = "";
|
|
2119
|
+
};
|
|
2120
|
+
}, [isOpen, onClose]);
|
|
2121
|
+
if (!isOpen) return null;
|
|
2122
|
+
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [
|
|
2123
|
+
/* @__PURE__ */ jsx(
|
|
2124
|
+
"div",
|
|
2125
|
+
{
|
|
2126
|
+
className: "absolute inset-0",
|
|
2127
|
+
style: { backgroundColor: "var(--compass-color-overlay)" },
|
|
2128
|
+
onClick: onClose
|
|
2129
|
+
}
|
|
2130
|
+
),
|
|
2131
|
+
/* @__PURE__ */ jsxs(
|
|
2132
|
+
"div",
|
|
2133
|
+
{
|
|
2134
|
+
className: "relative w-full max-w-md mx-4 rounded-xl overflow-hidden",
|
|
2135
|
+
style: {
|
|
2136
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
2137
|
+
boxShadow: "var(--compass-shadow-lg)"
|
|
2138
|
+
},
|
|
2139
|
+
children: [
|
|
2140
|
+
/* @__PURE__ */ jsxs(
|
|
2141
|
+
"div",
|
|
2142
|
+
{
|
|
2143
|
+
className: "flex items-center justify-between px-4 py-3 border-b",
|
|
2144
|
+
style: { borderColor: "var(--compass-color-border)" },
|
|
2145
|
+
children: [
|
|
2146
|
+
/* @__PURE__ */ jsxs(
|
|
2147
|
+
"h2",
|
|
2148
|
+
{
|
|
2149
|
+
className: "font-semibold flex items-center gap-2",
|
|
2150
|
+
style: {
|
|
2151
|
+
fontSize: "var(--compass-font-size-subheading)",
|
|
2152
|
+
color: "var(--compass-color-text)"
|
|
2153
|
+
},
|
|
2154
|
+
children: [
|
|
2155
|
+
/* @__PURE__ */ jsx(Coins, { size: 20 }),
|
|
2156
|
+
"Account Balances"
|
|
2157
|
+
]
|
|
2158
|
+
}
|
|
2159
|
+
),
|
|
2160
|
+
/* @__PURE__ */ jsx(
|
|
2161
|
+
"button",
|
|
2162
|
+
{
|
|
2163
|
+
onClick: onClose,
|
|
2164
|
+
className: "p-1 rounded-md transition-colors hover:opacity-70",
|
|
2165
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2166
|
+
children: /* @__PURE__ */ jsx(X, { size: 20 })
|
|
2167
|
+
}
|
|
2168
|
+
)
|
|
2169
|
+
]
|
|
2170
|
+
}
|
|
2171
|
+
),
|
|
2172
|
+
/* @__PURE__ */ jsxs("div", { className: "p-4", children: [
|
|
2173
|
+
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx(
|
|
2174
|
+
Loader2,
|
|
2175
|
+
{
|
|
2176
|
+
size: 24,
|
|
2177
|
+
className: "animate-spin",
|
|
2178
|
+
style: { color: "var(--compass-color-primary)" }
|
|
2179
|
+
}
|
|
2180
|
+
) }) : balances.length === 0 ? /* @__PURE__ */ jsx(
|
|
2181
|
+
"div",
|
|
2182
|
+
{
|
|
2183
|
+
className: "text-center py-8",
|
|
2184
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2185
|
+
children: "No token balances found"
|
|
2186
|
+
}
|
|
2187
|
+
) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
2188
|
+
balances.map((token) => /* @__PURE__ */ jsxs(
|
|
2189
|
+
"div",
|
|
2190
|
+
{
|
|
2191
|
+
className: "flex items-center justify-between p-3 rounded-lg",
|
|
2192
|
+
style: { backgroundColor: "var(--compass-color-background)" },
|
|
2193
|
+
children: [
|
|
2194
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
2195
|
+
/* @__PURE__ */ jsx(
|
|
2196
|
+
"div",
|
|
2197
|
+
{
|
|
2198
|
+
className: "w-8 h-8 rounded-full flex items-center justify-center text-xs font-bold",
|
|
2199
|
+
style: {
|
|
2200
|
+
backgroundColor: "var(--compass-color-primary-muted)",
|
|
2201
|
+
color: "var(--compass-color-primary)"
|
|
2202
|
+
},
|
|
2203
|
+
children: token.symbol.slice(0, 2)
|
|
2204
|
+
}
|
|
2205
|
+
),
|
|
2206
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2207
|
+
/* @__PURE__ */ jsx(
|
|
2208
|
+
"div",
|
|
2209
|
+
{
|
|
2210
|
+
className: "font-medium",
|
|
2211
|
+
style: { color: "var(--compass-color-text)" },
|
|
2212
|
+
children: token.symbol
|
|
2213
|
+
}
|
|
2214
|
+
),
|
|
2215
|
+
/* @__PURE__ */ jsx(
|
|
2216
|
+
"div",
|
|
2217
|
+
{
|
|
2218
|
+
className: "text-sm font-mono",
|
|
2219
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2220
|
+
children: formatAmount(token.balance)
|
|
2221
|
+
}
|
|
2222
|
+
)
|
|
2223
|
+
] })
|
|
2224
|
+
] }),
|
|
2225
|
+
/* @__PURE__ */ jsx(
|
|
2226
|
+
"div",
|
|
2227
|
+
{
|
|
2228
|
+
className: "font-medium",
|
|
2229
|
+
style: { color: "var(--compass-color-text)" },
|
|
2230
|
+
children: formatUSD(token.usdValue)
|
|
2231
|
+
}
|
|
2232
|
+
)
|
|
2233
|
+
]
|
|
2234
|
+
},
|
|
2235
|
+
token.symbol
|
|
2236
|
+
)),
|
|
2237
|
+
/* @__PURE__ */ jsxs(
|
|
2238
|
+
"div",
|
|
2239
|
+
{
|
|
2240
|
+
className: "flex items-center justify-between p-3 mt-2 rounded-lg border",
|
|
2241
|
+
style: {
|
|
2242
|
+
borderColor: "var(--compass-color-border)",
|
|
2243
|
+
backgroundColor: "var(--compass-color-surface)"
|
|
2244
|
+
},
|
|
2245
|
+
children: [
|
|
2246
|
+
/* @__PURE__ */ jsx(
|
|
2247
|
+
"span",
|
|
2248
|
+
{
|
|
2249
|
+
className: "font-medium",
|
|
2250
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2251
|
+
children: "Total Balance"
|
|
2252
|
+
}
|
|
2253
|
+
),
|
|
2254
|
+
/* @__PURE__ */ jsx(
|
|
2255
|
+
"span",
|
|
2256
|
+
{
|
|
2257
|
+
className: "font-bold text-lg",
|
|
2258
|
+
style: { color: "var(--compass-color-text)" },
|
|
2259
|
+
children: formatUSD(totalUsdValue)
|
|
2260
|
+
}
|
|
2261
|
+
)
|
|
2262
|
+
]
|
|
2263
|
+
}
|
|
2264
|
+
)
|
|
2265
|
+
] }),
|
|
2266
|
+
earnAccountAddress && /* @__PURE__ */ jsx(
|
|
2267
|
+
"div",
|
|
2268
|
+
{
|
|
2269
|
+
className: "mt-4 pt-4 border-t text-center",
|
|
2270
|
+
style: { borderColor: "var(--compass-color-border)" },
|
|
2271
|
+
children: /* @__PURE__ */ jsxs(
|
|
2272
|
+
"span",
|
|
2273
|
+
{
|
|
2274
|
+
className: "text-xs",
|
|
2275
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
2276
|
+
children: [
|
|
2277
|
+
"Earn Account: ",
|
|
2278
|
+
earnAccountAddress.slice(0, 6),
|
|
2279
|
+
"...",
|
|
2280
|
+
earnAccountAddress.slice(-4)
|
|
2281
|
+
]
|
|
2282
|
+
}
|
|
2283
|
+
)
|
|
2284
|
+
}
|
|
2285
|
+
)
|
|
2286
|
+
] })
|
|
2287
|
+
]
|
|
2288
|
+
}
|
|
2289
|
+
)
|
|
2290
|
+
] });
|
|
2291
|
+
}
|
|
2292
|
+
var TRANSFER_TOKENS = ["USDC"];
|
|
2293
|
+
function EarnAccountBalance({
|
|
2294
|
+
compact = false,
|
|
2295
|
+
onTransferComplete
|
|
2296
|
+
}) {
|
|
2297
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
2298
|
+
const [activeAction, setActiveAction] = useState("deposit");
|
|
2299
|
+
const [selectedToken, setSelectedToken] = useState(TRANSFER_TOKENS[0]);
|
|
2300
|
+
const [amount, setAmount] = useState("");
|
|
2301
|
+
const [transferState, setTransferState] = useState("idle");
|
|
2302
|
+
const [statusMessage, setStatusMessage] = useState("");
|
|
2303
|
+
const [error, setError] = useState(null);
|
|
2304
|
+
const [isBalancesModalOpen, setIsBalancesModalOpen] = useState(false);
|
|
2305
|
+
const { address, isConnected, signTypedData, switchChain, walletChainId } = useEmbeddableWallet();
|
|
2306
|
+
const { chainId, chain } = useChain();
|
|
2307
|
+
const { earnAccountAddress, isDeployed } = useEarnAccount();
|
|
2308
|
+
const queryClient = useQueryClient();
|
|
2309
|
+
const { data: balanceData, isLoading: balancesLoading } = useQuery({
|
|
2310
|
+
queryKey: ["earnAccountBalances", chainId, address],
|
|
2311
|
+
queryFn: async () => {
|
|
2312
|
+
if (!address) return null;
|
|
2313
|
+
const response = await fetch(
|
|
2314
|
+
`/api/compass/earn-account/balances?owner=${address}&chain=${chainId}`
|
|
2315
|
+
);
|
|
2316
|
+
if (!response.ok) {
|
|
2317
|
+
throw new Error("Failed to fetch balances");
|
|
2318
|
+
}
|
|
2319
|
+
return response.json();
|
|
2320
|
+
},
|
|
2321
|
+
enabled: !!address && isDeployed,
|
|
2322
|
+
staleTime: 30 * 1e3
|
|
2323
|
+
});
|
|
2324
|
+
const { data: eoaBalances } = useQuery({
|
|
2325
|
+
queryKey: ["eoaBalances", chainId, address, TRANSFER_TOKENS.join(",")],
|
|
2326
|
+
queryFn: async () => {
|
|
2327
|
+
if (!address) return {};
|
|
2328
|
+
const balances = {};
|
|
2329
|
+
for (const token of TRANSFER_TOKENS) {
|
|
2330
|
+
try {
|
|
2331
|
+
const response = await fetch(
|
|
2332
|
+
`/api/compass/token/balance?chain=${chainId}&token=${token}&address=${address}`
|
|
2333
|
+
);
|
|
2334
|
+
if (response.ok) {
|
|
2335
|
+
const data = await response.json();
|
|
2336
|
+
balances[token] = data.balance || "0";
|
|
2337
|
+
}
|
|
2338
|
+
} catch {
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
return balances;
|
|
2342
|
+
},
|
|
2343
|
+
enabled: !!address && activeAction === "deposit",
|
|
2344
|
+
staleTime: 30 * 1e3
|
|
2345
|
+
});
|
|
2346
|
+
const earnBalances = balanceData?.balances || {};
|
|
2347
|
+
const totalUsdValue = parseFloat(balanceData?.totalUsdValue || "0");
|
|
2348
|
+
const tokenBalances = Object.entries(earnBalances).filter(([, data]) => {
|
|
2349
|
+
const usdVal = parseFloat(data.usdValue || "0");
|
|
2350
|
+
return usdVal > 0;
|
|
2351
|
+
}).map(([symbol, data]) => ({
|
|
2352
|
+
symbol,
|
|
2353
|
+
balance: data.balance || "0",
|
|
2354
|
+
usdValue: data.usdValue || "0"
|
|
2355
|
+
}));
|
|
2356
|
+
const earnBalanceAmounts = {};
|
|
2357
|
+
for (const [symbol, data] of Object.entries(earnBalances)) {
|
|
2358
|
+
earnBalanceAmounts[symbol] = data.balance;
|
|
2359
|
+
}
|
|
2360
|
+
const resetForm = useCallback(() => {
|
|
2361
|
+
setAmount("");
|
|
2362
|
+
setTransferState("idle");
|
|
2363
|
+
setStatusMessage("");
|
|
2364
|
+
setError(null);
|
|
2365
|
+
}, []);
|
|
2366
|
+
const handleOpenModal = () => {
|
|
2367
|
+
resetForm();
|
|
2368
|
+
setIsModalOpen(true);
|
|
2369
|
+
};
|
|
2370
|
+
const handleCloseModal = () => {
|
|
2371
|
+
setIsModalOpen(false);
|
|
2372
|
+
resetForm();
|
|
2373
|
+
};
|
|
2374
|
+
const handleActionChange = (action) => {
|
|
2375
|
+
setActiveAction(action);
|
|
2376
|
+
setAmount("");
|
|
2377
|
+
setError(null);
|
|
2378
|
+
};
|
|
2379
|
+
const getMaxBalance = () => {
|
|
2380
|
+
if (activeAction === "deposit") {
|
|
2381
|
+
return eoaBalances?.[selectedToken] || "0";
|
|
2382
|
+
}
|
|
2383
|
+
return earnBalanceAmounts[selectedToken] || "0";
|
|
2384
|
+
};
|
|
2385
|
+
const handleQuickAmount = (percentage) => {
|
|
2386
|
+
const max = parseFloat(getMaxBalance());
|
|
2387
|
+
if (isNaN(max)) return;
|
|
2388
|
+
setAmount(formatAmount(max * percentage));
|
|
2389
|
+
};
|
|
2390
|
+
const handleTransfer = useCallback(async () => {
|
|
2391
|
+
if (!address || !amount || !signTypedData) return;
|
|
2392
|
+
setError(null);
|
|
2393
|
+
try {
|
|
2394
|
+
const targetChainId = chain.viemChain.id;
|
|
2395
|
+
if (walletChainId !== void 0 && walletChainId !== targetChainId) {
|
|
2396
|
+
if (!switchChain) {
|
|
2397
|
+
throw new Error(`Please switch your wallet to ${chain.name} (chain ID ${targetChainId}) to continue. Your wallet is currently on chain ID ${walletChainId}.`);
|
|
2398
|
+
}
|
|
2399
|
+
setStatusMessage(`Switching network to ${chain.name}...`);
|
|
2400
|
+
try {
|
|
2401
|
+
await switchChain(targetChainId);
|
|
2402
|
+
} catch (switchError) {
|
|
2403
|
+
throw new Error(`Please switch your wallet to ${chain.name} to continue. Your wallet is on chain ID ${walletChainId}, but ${chain.name} requires chain ID ${targetChainId}.`);
|
|
2404
|
+
}
|
|
2405
|
+
} else if (switchChain && walletChainId === void 0) {
|
|
2406
|
+
setStatusMessage("Switching network...");
|
|
2407
|
+
try {
|
|
2408
|
+
await switchChain(targetChainId);
|
|
2409
|
+
} catch (switchError) {
|
|
2410
|
+
throw new Error(`Please switch your wallet to ${chain.name} to continue`);
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
if (activeAction === "deposit") {
|
|
2414
|
+
setTransferState("checking_approval");
|
|
2415
|
+
setStatusMessage("Checking token approval...");
|
|
2416
|
+
const approveResponse = await fetch("/api/compass/transfer/approve", {
|
|
2417
|
+
method: "POST",
|
|
2418
|
+
headers: { "Content-Type": "application/json" },
|
|
2419
|
+
body: JSON.stringify({
|
|
2420
|
+
owner: address,
|
|
2421
|
+
chain: chainId,
|
|
2422
|
+
token: selectedToken
|
|
2423
|
+
})
|
|
2424
|
+
});
|
|
2425
|
+
if (!approveResponse.ok) {
|
|
2426
|
+
const errData = await approveResponse.json();
|
|
2427
|
+
throw new Error(errData.error || "Failed to check approval");
|
|
2428
|
+
}
|
|
2429
|
+
const approvalData = await approveResponse.json();
|
|
2430
|
+
if (!approvalData.approved) {
|
|
2431
|
+
if (approvalData.requiresTransaction) {
|
|
2432
|
+
throw new Error("This token requires a transaction-based approval. Please approve manually.");
|
|
2433
|
+
}
|
|
2434
|
+
setTransferState("awaiting_approval_signature");
|
|
2435
|
+
setStatusMessage("Please sign the approval...");
|
|
2436
|
+
const approvalSignature = await signTypedData({
|
|
2437
|
+
domain: approvalData.domain,
|
|
2438
|
+
types: approvalData.normalizedTypes,
|
|
2439
|
+
primaryType: "Permit",
|
|
2440
|
+
message: approvalData.message
|
|
2441
|
+
});
|
|
2442
|
+
setTransferState("approving");
|
|
2443
|
+
setStatusMessage("Executing approval...");
|
|
2444
|
+
const executeApprovalResponse = await fetch("/api/compass/transfer/execute", {
|
|
2445
|
+
method: "POST",
|
|
2446
|
+
headers: { "Content-Type": "application/json" },
|
|
2447
|
+
body: JSON.stringify({
|
|
2448
|
+
owner: address,
|
|
2449
|
+
chain: chainId,
|
|
2450
|
+
eip712: approvalData.eip712,
|
|
2451
|
+
signature: approvalSignature
|
|
2452
|
+
})
|
|
2453
|
+
});
|
|
2454
|
+
if (!executeApprovalResponse.ok) {
|
|
2455
|
+
const errData = await executeApprovalResponse.json();
|
|
2456
|
+
throw new Error(errData.error || "Approval failed");
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
setTransferState("awaiting_transfer_signature");
|
|
2461
|
+
setStatusMessage("Preparing transfer...");
|
|
2462
|
+
const prepareResponse = await fetch("/api/compass/transfer/prepare", {
|
|
2463
|
+
method: "POST",
|
|
2464
|
+
headers: { "Content-Type": "application/json" },
|
|
2465
|
+
body: JSON.stringify({
|
|
2466
|
+
owner: address,
|
|
2467
|
+
chain: chainId,
|
|
2468
|
+
token: selectedToken,
|
|
2469
|
+
amount,
|
|
2470
|
+
action: activeAction.toUpperCase()
|
|
2471
|
+
})
|
|
2472
|
+
});
|
|
2473
|
+
if (!prepareResponse.ok) {
|
|
2474
|
+
const errData = await prepareResponse.json();
|
|
2475
|
+
throw new Error(errData.error || "Failed to prepare transfer");
|
|
2476
|
+
}
|
|
2477
|
+
const prepareData = await prepareResponse.json();
|
|
2478
|
+
setStatusMessage("Please sign the transfer...");
|
|
2479
|
+
const transferSignature = await signTypedData({
|
|
2480
|
+
domain: prepareData.domain,
|
|
2481
|
+
types: prepareData.normalizedTypes,
|
|
2482
|
+
primaryType: prepareData.primaryType,
|
|
2483
|
+
message: prepareData.message
|
|
2484
|
+
});
|
|
2485
|
+
setTransferState("transferring");
|
|
2486
|
+
setStatusMessage("Executing transfer...");
|
|
2487
|
+
const executeResponse = await fetch("/api/compass/transfer/execute", {
|
|
2488
|
+
method: "POST",
|
|
2489
|
+
headers: { "Content-Type": "application/json" },
|
|
2490
|
+
body: JSON.stringify({
|
|
2491
|
+
owner: address,
|
|
2492
|
+
chain: chainId,
|
|
2493
|
+
eip712: prepareData.eip712,
|
|
2494
|
+
signature: transferSignature
|
|
2495
|
+
})
|
|
2496
|
+
});
|
|
2497
|
+
if (!executeResponse.ok) {
|
|
2498
|
+
const errData = await executeResponse.json();
|
|
2499
|
+
throw new Error(errData.error || "Transfer failed");
|
|
2500
|
+
}
|
|
2501
|
+
const { txHash } = await executeResponse.json();
|
|
2502
|
+
setTransferState("success");
|
|
2503
|
+
setStatusMessage("Transfer successful!");
|
|
2504
|
+
onTransferComplete?.(activeAction, selectedToken, amount, txHash);
|
|
2505
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
2506
|
+
queryClient.invalidateQueries({ queryKey: ["eoaBalances"] });
|
|
2507
|
+
setTimeout(() => {
|
|
2508
|
+
resetForm();
|
|
2509
|
+
}, 2e3);
|
|
2510
|
+
} catch (err) {
|
|
2511
|
+
console.error("Transfer failed:", err);
|
|
2512
|
+
setTransferState("error");
|
|
2513
|
+
setError(err instanceof Error ? err.message : "Transfer failed");
|
|
2514
|
+
}
|
|
2515
|
+
}, [
|
|
2516
|
+
address,
|
|
2517
|
+
amount,
|
|
2518
|
+
activeAction,
|
|
2519
|
+
selectedToken,
|
|
2520
|
+
chainId,
|
|
2521
|
+
chain,
|
|
2522
|
+
walletChainId,
|
|
2523
|
+
signTypedData,
|
|
2524
|
+
switchChain,
|
|
2525
|
+
queryClient,
|
|
2526
|
+
onTransferComplete,
|
|
2527
|
+
resetForm
|
|
2528
|
+
]);
|
|
2529
|
+
if (!isConnected) {
|
|
2530
|
+
return null;
|
|
2531
|
+
}
|
|
2532
|
+
const isProcessing = transferState !== "idle" && transferState !== "success" && transferState !== "error";
|
|
2533
|
+
if (!isDeployed) {
|
|
2534
|
+
return /* @__PURE__ */ jsxs(
|
|
2535
|
+
"div",
|
|
2536
|
+
{
|
|
2537
|
+
className: `flex items-center gap-2 rounded-lg border ${compact ? "px-2 py-1.5" : "px-3 py-2"}`,
|
|
2538
|
+
style: {
|
|
2539
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
2540
|
+
borderColor: "var(--compass-color-border)"
|
|
2541
|
+
},
|
|
2542
|
+
children: [
|
|
2543
|
+
/* @__PURE__ */ jsx(Wallet, { size: compact ? 14 : 16, style: { color: "var(--compass-color-text-secondary)" } }),
|
|
2544
|
+
/* @__PURE__ */ jsx(
|
|
2545
|
+
"span",
|
|
2546
|
+
{
|
|
2547
|
+
className: `${compact ? "text-xs" : "text-sm"}`,
|
|
2548
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2549
|
+
children: "No Earn Account"
|
|
2550
|
+
}
|
|
2551
|
+
)
|
|
2552
|
+
]
|
|
2553
|
+
}
|
|
2554
|
+
);
|
|
2555
|
+
}
|
|
2556
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2557
|
+
/* @__PURE__ */ jsxs(
|
|
2558
|
+
"button",
|
|
2559
|
+
{
|
|
2560
|
+
onClick: () => setIsBalancesModalOpen(true),
|
|
2561
|
+
className: `flex items-center gap-2 rounded-lg border transition-colors hover:border-[var(--compass-color-primary)] ${compact ? "px-2 py-1.5" : "px-3 py-2"}`,
|
|
2562
|
+
style: {
|
|
2563
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
2564
|
+
borderColor: "var(--compass-color-border)",
|
|
2565
|
+
cursor: "pointer"
|
|
2566
|
+
},
|
|
2567
|
+
children: [
|
|
2568
|
+
/* @__PURE__ */ jsx(Wallet, { size: compact ? 14 : 16, style: { color: "var(--compass-color-primary)" } }),
|
|
2569
|
+
balancesLoading ? /* @__PURE__ */ jsx(Loader2, { size: compact ? 12 : 14, className: "animate-spin", style: { color: "var(--compass-color-text-secondary)" } }) : /* @__PURE__ */ jsx(
|
|
2570
|
+
"span",
|
|
2571
|
+
{
|
|
2572
|
+
className: `font-medium ${compact ? "text-xs" : "text-sm"}`,
|
|
2573
|
+
style: { color: "var(--compass-color-text)" },
|
|
2574
|
+
children: formatUSD(totalUsdValue)
|
|
2575
|
+
}
|
|
2576
|
+
)
|
|
2577
|
+
]
|
|
2578
|
+
}
|
|
2579
|
+
),
|
|
2580
|
+
/* @__PURE__ */ jsx(
|
|
2581
|
+
"button",
|
|
2582
|
+
{
|
|
2583
|
+
onClick: handleOpenModal,
|
|
2584
|
+
className: `rounded-md font-medium transition-colors ${compact ? "px-2 py-1 text-xs" : "px-3 py-1.5 text-sm"}`,
|
|
2585
|
+
style: {
|
|
2586
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
2587
|
+
color: "var(--compass-color-primary-text)"
|
|
2588
|
+
},
|
|
2589
|
+
children: "Fund"
|
|
2590
|
+
}
|
|
2591
|
+
),
|
|
2592
|
+
/* @__PURE__ */ jsx(
|
|
2593
|
+
AccountBalancesModal,
|
|
2594
|
+
{
|
|
2595
|
+
isOpen: isBalancesModalOpen,
|
|
2596
|
+
onClose: () => setIsBalancesModalOpen(false),
|
|
2597
|
+
balances: tokenBalances,
|
|
2598
|
+
totalUsdValue: totalUsdValue.toString(),
|
|
2599
|
+
isLoading: balancesLoading,
|
|
2600
|
+
earnAccountAddress: earnAccountAddress ?? void 0
|
|
2601
|
+
}
|
|
2602
|
+
),
|
|
2603
|
+
/* @__PURE__ */ jsx(
|
|
2604
|
+
ActionModal,
|
|
2605
|
+
{
|
|
2606
|
+
isOpen: isModalOpen,
|
|
2607
|
+
onClose: handleCloseModal,
|
|
2608
|
+
title: "Transfer Funds",
|
|
2609
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2610
|
+
/* @__PURE__ */ jsx(
|
|
2611
|
+
"div",
|
|
2612
|
+
{
|
|
2613
|
+
className: "flex gap-1 p-1 rounded-lg",
|
|
2614
|
+
style: { backgroundColor: "var(--compass-color-background)" },
|
|
2615
|
+
children: ["deposit", "withdraw"].map((action) => /* @__PURE__ */ jsxs(
|
|
2616
|
+
"button",
|
|
2617
|
+
{
|
|
2618
|
+
onClick: () => handleActionChange(action),
|
|
2619
|
+
disabled: isProcessing,
|
|
2620
|
+
className: "flex-1 py-2 rounded-md text-sm font-medium capitalize transition-all flex items-center justify-center gap-2",
|
|
2621
|
+
style: {
|
|
2622
|
+
backgroundColor: activeAction === action ? "var(--compass-color-surface)" : "transparent",
|
|
2623
|
+
color: activeAction === action ? "var(--compass-color-text)" : "var(--compass-color-text-secondary)"
|
|
2624
|
+
},
|
|
2625
|
+
children: [
|
|
2626
|
+
action === "deposit" ? /* @__PURE__ */ jsx(ArrowDownLeft, { size: 14 }) : /* @__PURE__ */ jsx(ArrowUpRight, { size: 14 }),
|
|
2627
|
+
action
|
|
2628
|
+
]
|
|
2629
|
+
},
|
|
2630
|
+
action
|
|
2631
|
+
))
|
|
2632
|
+
}
|
|
2633
|
+
),
|
|
2634
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2635
|
+
/* @__PURE__ */ jsx(
|
|
2636
|
+
"label",
|
|
2637
|
+
{
|
|
2638
|
+
className: "text-sm font-medium mb-1 block",
|
|
2639
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2640
|
+
children: "Token"
|
|
2641
|
+
}
|
|
2642
|
+
),
|
|
2643
|
+
/* @__PURE__ */ jsx(
|
|
2644
|
+
TokenSelector,
|
|
2645
|
+
{
|
|
2646
|
+
tokens: TRANSFER_TOKENS,
|
|
2647
|
+
selectedToken,
|
|
2648
|
+
onSelect: setSelectedToken,
|
|
2649
|
+
balances: activeAction === "deposit" ? eoaBalances : earnBalanceAmounts,
|
|
2650
|
+
disabled: isProcessing
|
|
2651
|
+
}
|
|
2652
|
+
)
|
|
2653
|
+
] }),
|
|
2654
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2655
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-1", children: [
|
|
2656
|
+
/* @__PURE__ */ jsx(
|
|
2657
|
+
"label",
|
|
2658
|
+
{
|
|
2659
|
+
className: "text-sm font-medium",
|
|
2660
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2661
|
+
children: "Amount"
|
|
2662
|
+
}
|
|
2663
|
+
),
|
|
2664
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: [
|
|
2665
|
+
"Available: ",
|
|
2666
|
+
formatAmount(getMaxBalance()),
|
|
2667
|
+
" ",
|
|
2668
|
+
selectedToken
|
|
2669
|
+
] })
|
|
2670
|
+
] }),
|
|
2671
|
+
/* @__PURE__ */ jsxs(
|
|
2672
|
+
"div",
|
|
2673
|
+
{
|
|
2674
|
+
className: "flex items-center gap-2 p-3 rounded-lg border",
|
|
2675
|
+
style: {
|
|
2676
|
+
backgroundColor: "var(--compass-color-background)",
|
|
2677
|
+
borderColor: "var(--compass-color-border)"
|
|
2678
|
+
},
|
|
2679
|
+
children: [
|
|
2680
|
+
/* @__PURE__ */ jsx(
|
|
2681
|
+
"input",
|
|
2682
|
+
{
|
|
2683
|
+
type: "number",
|
|
2684
|
+
value: amount,
|
|
2685
|
+
onChange: (e) => {
|
|
2686
|
+
setAmount(e.target.value);
|
|
2687
|
+
setError(null);
|
|
2688
|
+
},
|
|
2689
|
+
placeholder: "0.00",
|
|
2690
|
+
disabled: isProcessing,
|
|
2691
|
+
className: "flex-1 bg-transparent outline-none text-lg font-mono",
|
|
2692
|
+
style: { color: "var(--compass-color-text)" }
|
|
2693
|
+
}
|
|
2694
|
+
),
|
|
2695
|
+
/* @__PURE__ */ jsx(
|
|
2696
|
+
"span",
|
|
2697
|
+
{
|
|
2698
|
+
className: "text-sm font-medium",
|
|
2699
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2700
|
+
children: selectedToken
|
|
2701
|
+
}
|
|
2702
|
+
)
|
|
2703
|
+
]
|
|
2704
|
+
}
|
|
2705
|
+
)
|
|
2706
|
+
] }),
|
|
2707
|
+
/* @__PURE__ */ jsx("div", { className: "flex gap-2", children: [0.25, 0.5, 1].map((pct) => /* @__PURE__ */ jsx(
|
|
2708
|
+
"button",
|
|
2709
|
+
{
|
|
2710
|
+
onClick: () => handleQuickAmount(pct),
|
|
2711
|
+
disabled: isProcessing,
|
|
2712
|
+
className: "flex-1 py-1.5 rounded-md text-xs font-medium transition-colors",
|
|
2713
|
+
style: {
|
|
2714
|
+
backgroundColor: "var(--compass-color-secondary)",
|
|
2715
|
+
color: "var(--compass-color-text-secondary)"
|
|
2716
|
+
},
|
|
2717
|
+
children: pct === 1 ? "Max" : `${pct * 100}%`
|
|
2718
|
+
},
|
|
2719
|
+
pct
|
|
2720
|
+
)) }),
|
|
2721
|
+
error && /* @__PURE__ */ jsx(
|
|
2722
|
+
"div",
|
|
2723
|
+
{
|
|
2724
|
+
className: "p-3 rounded-lg text-sm",
|
|
2725
|
+
style: {
|
|
2726
|
+
backgroundColor: "var(--compass-color-error-muted)",
|
|
2727
|
+
color: "var(--compass-color-error)"
|
|
2728
|
+
},
|
|
2729
|
+
children: error
|
|
2730
|
+
}
|
|
2731
|
+
),
|
|
2732
|
+
statusMessage && !error && /* @__PURE__ */ jsx(
|
|
2733
|
+
"div",
|
|
2734
|
+
{
|
|
2735
|
+
className: "p-3 rounded-lg text-sm text-center",
|
|
2736
|
+
style: {
|
|
2737
|
+
backgroundColor: transferState === "success" ? "var(--compass-color-success-muted)" : "var(--compass-color-primary-muted)",
|
|
2738
|
+
color: transferState === "success" ? "var(--compass-color-success)" : "var(--compass-color-primary)"
|
|
2739
|
+
},
|
|
2740
|
+
children: statusMessage
|
|
2741
|
+
}
|
|
2742
|
+
),
|
|
2743
|
+
/* @__PURE__ */ jsxs(
|
|
2744
|
+
"button",
|
|
2745
|
+
{
|
|
2746
|
+
onClick: handleTransfer,
|
|
2747
|
+
disabled: isProcessing || !amount || parseFloat(amount) <= 0,
|
|
2748
|
+
className: "w-full py-3 rounded-lg font-medium transition-colors flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
2749
|
+
style: {
|
|
2750
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
2751
|
+
color: "var(--compass-color-primary-text)"
|
|
2752
|
+
},
|
|
2753
|
+
children: [
|
|
2754
|
+
isProcessing && /* @__PURE__ */ jsx(Loader2, { size: 18, className: "animate-spin" }),
|
|
2755
|
+
isProcessing ? "Processing..." : activeAction === "deposit" ? "Deposit to Earn Account" : "Withdraw to Wallet"
|
|
2756
|
+
]
|
|
2757
|
+
}
|
|
2758
|
+
),
|
|
2759
|
+
/* @__PURE__ */ jsx(
|
|
2760
|
+
"p",
|
|
2761
|
+
{
|
|
2762
|
+
className: "text-xs text-center",
|
|
2763
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
2764
|
+
children: "Gas fees are sponsored by Compass"
|
|
2765
|
+
}
|
|
2766
|
+
)
|
|
2767
|
+
] })
|
|
2768
|
+
}
|
|
2769
|
+
)
|
|
2770
|
+
] });
|
|
2771
|
+
}
|
|
1890
2772
|
function formatTVL(tvl) {
|
|
1891
2773
|
if (!tvl) return "$0";
|
|
1892
2774
|
const num = parseFloat(tvl);
|
|
@@ -2016,9 +2898,9 @@ function useVaultsData(options = {}) {
|
|
|
2016
2898
|
const { client } = useEmbeddableApi();
|
|
2017
2899
|
const { address } = useEmbeddableWallet();
|
|
2018
2900
|
const { chainId } = useChain();
|
|
2019
|
-
const { sortBy = "apy_7d", assetFilter, minApy } = options;
|
|
2901
|
+
const { sortBy = "apy_7d", assetFilter, minApy, minTvl } = options;
|
|
2020
2902
|
const vaultsQuery = useQuery({
|
|
2021
|
-
queryKey: ["vaults", chainId, sortBy, assetFilter, minApy],
|
|
2903
|
+
queryKey: ["vaults", chainId, sortBy, assetFilter, minApy, minTvl],
|
|
2022
2904
|
queryFn: async () => {
|
|
2023
2905
|
const assetSymbol = assetFilter && assetFilter.length === 1 ? assetFilter[0] : void 0;
|
|
2024
2906
|
const response = await client.earn.earnVaults({
|
|
@@ -2048,6 +2930,12 @@ function useVaultsData(options = {}) {
|
|
|
2048
2930
|
return apy >= minApy;
|
|
2049
2931
|
});
|
|
2050
2932
|
}
|
|
2933
|
+
if (minTvl !== void 0 && minTvl > 0) {
|
|
2934
|
+
vaults = vaults.filter((v) => {
|
|
2935
|
+
const tvl = parseFloat(v.tvlUsd || "0");
|
|
2936
|
+
return tvl >= minTvl;
|
|
2937
|
+
});
|
|
2938
|
+
}
|
|
2051
2939
|
return vaults;
|
|
2052
2940
|
},
|
|
2053
2941
|
staleTime: 30 * 1e3
|
|
@@ -2101,15 +2989,6 @@ function useVaultsData(options = {}) {
|
|
|
2101
2989
|
}
|
|
2102
2990
|
};
|
|
2103
2991
|
}
|
|
2104
|
-
var TOKEN_DECIMALS2 = {
|
|
2105
|
-
USDC: 6,
|
|
2106
|
-
USDT: 6,
|
|
2107
|
-
DAI: 18,
|
|
2108
|
-
ETH: 18,
|
|
2109
|
-
WETH: 18,
|
|
2110
|
-
WBTC: 8,
|
|
2111
|
-
cbBTC: 8
|
|
2112
|
-
};
|
|
2113
2992
|
function VaultsList({
|
|
2114
2993
|
showApy = true,
|
|
2115
2994
|
apyPeriods = ["7d", "30d", "90d"],
|
|
@@ -2119,10 +2998,11 @@ function VaultsList({
|
|
|
2119
2998
|
showHistory = true,
|
|
2120
2999
|
showSearch = true,
|
|
2121
3000
|
showSort = true,
|
|
2122
|
-
actionMode = "modal",
|
|
2123
3001
|
defaultSort = "apy_7d",
|
|
2124
3002
|
assetFilter,
|
|
2125
3003
|
minApy,
|
|
3004
|
+
minTvl: initialMinTvl,
|
|
3005
|
+
showTvlFilter = true,
|
|
2126
3006
|
onVaultSelect,
|
|
2127
3007
|
onDeposit,
|
|
2128
3008
|
onWithdraw
|
|
@@ -2130,11 +3010,18 @@ function VaultsList({
|
|
|
2130
3010
|
const [searchQuery, setSearchQuery] = useState("");
|
|
2131
3011
|
const [sortBy, setSortBy] = useState(defaultSort);
|
|
2132
3012
|
const [selectedVault, setSelectedVault] = useState(null);
|
|
3013
|
+
const [minTvlFilter, setMinTvlFilter] = useState(initialMinTvl);
|
|
3014
|
+
const [showFilterPanel, setShowFilterPanel] = useState(false);
|
|
2133
3015
|
const { vaults, isLoading, isError, refetch } = useVaultsData({
|
|
2134
3016
|
sortBy,
|
|
2135
3017
|
assetFilter,
|
|
2136
|
-
minApy
|
|
3018
|
+
minApy,
|
|
3019
|
+
minTvl: minTvlFilter
|
|
2137
3020
|
});
|
|
3021
|
+
const handleMinTvlChange = useCallback((value) => {
|
|
3022
|
+
const num = parseFloat(value);
|
|
3023
|
+
setMinTvlFilter(isNaN(num) || num <= 0 ? void 0 : num);
|
|
3024
|
+
}, []);
|
|
2138
3025
|
const filteredVaults = useMemo(() => {
|
|
2139
3026
|
if (!searchQuery) return vaults;
|
|
2140
3027
|
const query = searchQuery.toLowerCase();
|
|
@@ -2157,51 +3044,121 @@ function VaultsList({
|
|
|
2157
3044
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2158
3045
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
|
|
2159
3046
|
/* @__PURE__ */ jsx(ChainSwitcher, {}),
|
|
2160
|
-
/* @__PURE__ */
|
|
3047
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3048
|
+
/* @__PURE__ */ jsx(EarnAccountBalance, { compact: true }),
|
|
3049
|
+
/* @__PURE__ */ jsx(WalletStatus, { compact: true })
|
|
3050
|
+
] })
|
|
2161
3051
|
] }),
|
|
2162
|
-
(showSearch || showSort) && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
2163
|
-
|
|
3052
|
+
(showSearch || showSort || showTvlFilter) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3053
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
3054
|
+
showSearch && /* @__PURE__ */ jsxs(
|
|
3055
|
+
"div",
|
|
3056
|
+
{
|
|
3057
|
+
className: "flex-1 flex items-center gap-2 px-3 py-2 rounded-lg border",
|
|
3058
|
+
style: {
|
|
3059
|
+
backgroundColor: "var(--compass-color-background)",
|
|
3060
|
+
borderColor: "var(--compass-color-border)"
|
|
3061
|
+
},
|
|
3062
|
+
children: [
|
|
3063
|
+
/* @__PURE__ */ jsx(Search, { size: 16, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
3064
|
+
/* @__PURE__ */ jsx(
|
|
3065
|
+
"input",
|
|
3066
|
+
{
|
|
3067
|
+
type: "text",
|
|
3068
|
+
placeholder: "Search vaults...",
|
|
3069
|
+
value: searchQuery,
|
|
3070
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
3071
|
+
className: "flex-1 bg-transparent outline-none text-sm",
|
|
3072
|
+
style: { color: "var(--compass-color-text)" }
|
|
3073
|
+
}
|
|
3074
|
+
)
|
|
3075
|
+
]
|
|
3076
|
+
}
|
|
3077
|
+
),
|
|
3078
|
+
showSort && /* @__PURE__ */ jsxs(
|
|
3079
|
+
"select",
|
|
3080
|
+
{
|
|
3081
|
+
value: sortBy,
|
|
3082
|
+
onChange: (e) => setSortBy(e.target.value),
|
|
3083
|
+
className: "px-3 py-2 rounded-lg border text-sm cursor-pointer",
|
|
3084
|
+
style: {
|
|
3085
|
+
backgroundColor: "var(--compass-color-background)",
|
|
3086
|
+
borderColor: "var(--compass-color-border)",
|
|
3087
|
+
color: "var(--compass-color-text)"
|
|
3088
|
+
},
|
|
3089
|
+
children: [
|
|
3090
|
+
/* @__PURE__ */ jsx("option", { value: "apy_7d", children: "APY (7D)" }),
|
|
3091
|
+
/* @__PURE__ */ jsx("option", { value: "apy_30d", children: "APY (30D)" }),
|
|
3092
|
+
/* @__PURE__ */ jsx("option", { value: "apy_90d", children: "APY (90D)" }),
|
|
3093
|
+
/* @__PURE__ */ jsx("option", { value: "tvl", children: "TVL" })
|
|
3094
|
+
]
|
|
3095
|
+
}
|
|
3096
|
+
),
|
|
3097
|
+
showTvlFilter && /* @__PURE__ */ jsxs(
|
|
3098
|
+
"button",
|
|
3099
|
+
{
|
|
3100
|
+
onClick: () => setShowFilterPanel(!showFilterPanel),
|
|
3101
|
+
className: "px-3 py-2 rounded-lg border text-sm flex items-center gap-2",
|
|
3102
|
+
style: {
|
|
3103
|
+
backgroundColor: showFilterPanel || minTvlFilter ? "var(--compass-color-primary-muted)" : "var(--compass-color-background)",
|
|
3104
|
+
borderColor: showFilterPanel || minTvlFilter ? "var(--compass-color-primary)" : "var(--compass-color-border)",
|
|
3105
|
+
color: showFilterPanel || minTvlFilter ? "var(--compass-color-primary)" : "var(--compass-color-text)"
|
|
3106
|
+
},
|
|
3107
|
+
children: [
|
|
3108
|
+
/* @__PURE__ */ jsx(SlidersHorizontal, { size: 14 }),
|
|
3109
|
+
"Filter"
|
|
3110
|
+
]
|
|
3111
|
+
}
|
|
3112
|
+
)
|
|
3113
|
+
] }),
|
|
3114
|
+
showTvlFilter && showFilterPanel && /* @__PURE__ */ jsxs(
|
|
2164
3115
|
"div",
|
|
2165
3116
|
{
|
|
2166
|
-
className: "flex
|
|
3117
|
+
className: "flex items-center gap-3 p-3 rounded-lg border",
|
|
2167
3118
|
style: {
|
|
2168
|
-
backgroundColor: "var(--compass-color-
|
|
3119
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
2169
3120
|
borderColor: "var(--compass-color-border)"
|
|
2170
3121
|
},
|
|
2171
3122
|
children: [
|
|
2172
|
-
/* @__PURE__ */ jsx(Search, { size: 16, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
2173
3123
|
/* @__PURE__ */ jsx(
|
|
2174
|
-
"
|
|
3124
|
+
"label",
|
|
2175
3125
|
{
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
3126
|
+
className: "text-sm font-medium whitespace-nowrap",
|
|
3127
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
3128
|
+
children: "Min TVL:"
|
|
3129
|
+
}
|
|
3130
|
+
),
|
|
3131
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3132
|
+
/* @__PURE__ */ jsx("span", { style: { color: "var(--compass-color-text-tertiary)" }, children: "$" }),
|
|
3133
|
+
/* @__PURE__ */ jsx(
|
|
3134
|
+
"input",
|
|
3135
|
+
{
|
|
3136
|
+
type: "number",
|
|
3137
|
+
placeholder: "0",
|
|
3138
|
+
value: minTvlFilter || "",
|
|
3139
|
+
onChange: (e) => handleMinTvlChange(e.target.value),
|
|
3140
|
+
className: "w-24 px-2 py-1 rounded border text-sm bg-transparent",
|
|
3141
|
+
style: {
|
|
3142
|
+
borderColor: "var(--compass-color-border)",
|
|
3143
|
+
color: "var(--compass-color-text)"
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
)
|
|
3147
|
+
] }),
|
|
3148
|
+
minTvlFilter && /* @__PURE__ */ jsx(
|
|
3149
|
+
"button",
|
|
3150
|
+
{
|
|
3151
|
+
onClick: () => setMinTvlFilter(void 0),
|
|
3152
|
+
className: "text-xs px-2 py-1 rounded",
|
|
3153
|
+
style: {
|
|
3154
|
+
backgroundColor: "var(--compass-color-error-muted)",
|
|
3155
|
+
color: "var(--compass-color-error)"
|
|
3156
|
+
},
|
|
3157
|
+
children: "Clear"
|
|
2182
3158
|
}
|
|
2183
3159
|
)
|
|
2184
3160
|
]
|
|
2185
3161
|
}
|
|
2186
|
-
),
|
|
2187
|
-
showSort && /* @__PURE__ */ jsxs(
|
|
2188
|
-
"select",
|
|
2189
|
-
{
|
|
2190
|
-
value: sortBy,
|
|
2191
|
-
onChange: (e) => setSortBy(e.target.value),
|
|
2192
|
-
className: "px-3 py-2 rounded-lg border text-sm cursor-pointer",
|
|
2193
|
-
style: {
|
|
2194
|
-
backgroundColor: "var(--compass-color-background)",
|
|
2195
|
-
borderColor: "var(--compass-color-border)",
|
|
2196
|
-
color: "var(--compass-color-text)"
|
|
2197
|
-
},
|
|
2198
|
-
children: [
|
|
2199
|
-
/* @__PURE__ */ jsx("option", { value: "apy_7d", children: "APY (7D)" }),
|
|
2200
|
-
/* @__PURE__ */ jsx("option", { value: "apy_30d", children: "APY (30D)" }),
|
|
2201
|
-
/* @__PURE__ */ jsx("option", { value: "apy_90d", children: "APY (90D)" }),
|
|
2202
|
-
/* @__PURE__ */ jsx("option", { value: "tvl", children: "TVL" })
|
|
2203
|
-
]
|
|
2204
|
-
}
|
|
2205
3162
|
)
|
|
2206
3163
|
] }),
|
|
2207
3164
|
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx(Loader2, { size: 24, className: "animate-spin", style: { color: "var(--compass-color-primary)" } }) }) : isError ? /* @__PURE__ */ jsx(
|
|
@@ -2233,7 +3190,7 @@ function VaultsList({
|
|
|
2233
3190
|
},
|
|
2234
3191
|
vault.vaultAddress
|
|
2235
3192
|
)) }),
|
|
2236
|
-
|
|
3193
|
+
selectedVault && /* @__PURE__ */ jsx(
|
|
2237
3194
|
ActionModal,
|
|
2238
3195
|
{
|
|
2239
3196
|
isOpen: !!selectedVault,
|
|
@@ -2261,8 +3218,7 @@ function VaultsList({
|
|
|
2261
3218
|
{
|
|
2262
3219
|
venueType: "VAULT",
|
|
2263
3220
|
venueAddress: selectedVault.vaultAddress,
|
|
2264
|
-
|
|
2265
|
-
tokenDecimals: TOKEN_DECIMALS2[selectedVault.assetSymbol] || 18,
|
|
3221
|
+
venueToken: selectedVault.assetSymbol,
|
|
2266
3222
|
positionBalance: selectedVault.userPosition?.balance,
|
|
2267
3223
|
onSuccess: handleActionSuccess
|
|
2268
3224
|
}
|
|
@@ -2362,15 +3318,6 @@ function useAaveData(options = {}) {
|
|
|
2362
3318
|
}
|
|
2363
3319
|
};
|
|
2364
3320
|
}
|
|
2365
|
-
var TOKEN_DECIMALS3 = {
|
|
2366
|
-
USDC: 6,
|
|
2367
|
-
USDT: 6,
|
|
2368
|
-
DAI: 18,
|
|
2369
|
-
ETH: 18,
|
|
2370
|
-
WETH: 18,
|
|
2371
|
-
WBTC: 8,
|
|
2372
|
-
cbBTC: 8
|
|
2373
|
-
};
|
|
2374
3321
|
function formatAPY2(apy) {
|
|
2375
3322
|
if (!apy) return "0.00%";
|
|
2376
3323
|
const num = parseFloat(apy);
|
|
@@ -2394,7 +3341,6 @@ function AaveMarketsList({
|
|
|
2394
3341
|
showSearch = true,
|
|
2395
3342
|
showSort = false,
|
|
2396
3343
|
// Only one sort option (APY), so hide by default
|
|
2397
|
-
actionMode = "modal",
|
|
2398
3344
|
defaultSort = "supply_apy",
|
|
2399
3345
|
assetFilter,
|
|
2400
3346
|
onMarketSelect,
|
|
@@ -2427,7 +3373,10 @@ function AaveMarketsList({
|
|
|
2427
3373
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2428
3374
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
|
|
2429
3375
|
/* @__PURE__ */ jsx(ChainSwitcher, {}),
|
|
2430
|
-
/* @__PURE__ */
|
|
3376
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3377
|
+
/* @__PURE__ */ jsx(EarnAccountBalance, { compact: true }),
|
|
3378
|
+
/* @__PURE__ */ jsx(WalletStatus, { compact: true })
|
|
3379
|
+
] })
|
|
2431
3380
|
] }),
|
|
2432
3381
|
(showSearch || showSort) && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
2433
3382
|
showSearch && /* @__PURE__ */ jsxs(
|
|
@@ -2579,7 +3528,7 @@ function AaveMarketsList({
|
|
|
2579
3528
|
market.marketAddress
|
|
2580
3529
|
);
|
|
2581
3530
|
}) }),
|
|
2582
|
-
|
|
3531
|
+
selectedMarket && /* @__PURE__ */ jsx(
|
|
2583
3532
|
ActionModal,
|
|
2584
3533
|
{
|
|
2585
3534
|
isOpen: !!selectedMarket,
|
|
@@ -2607,8 +3556,7 @@ function AaveMarketsList({
|
|
|
2607
3556
|
{
|
|
2608
3557
|
venueType: "AAVE",
|
|
2609
3558
|
venueAddress: selectedMarket.marketAddress,
|
|
2610
|
-
|
|
2611
|
-
tokenDecimals: TOKEN_DECIMALS3[selectedMarket.underlyingSymbol] || 18,
|
|
3559
|
+
venueToken: selectedMarket.underlyingSymbol,
|
|
2612
3560
|
positionBalance: selectedMarket.userPosition?.balance,
|
|
2613
3561
|
onSuccess: handleActionSuccess
|
|
2614
3562
|
}
|
|
@@ -2622,9 +3570,9 @@ function usePendleData(options = {}) {
|
|
|
2622
3570
|
const { client } = useEmbeddableApi();
|
|
2623
3571
|
const { address } = useEmbeddableWallet();
|
|
2624
3572
|
const { chainId } = useChain();
|
|
2625
|
-
const { sortBy = "fixed_apy", assetFilter } = options;
|
|
3573
|
+
const { sortBy = "fixed_apy", assetFilter, minTvl } = options;
|
|
2626
3574
|
const marketsQuery = useQuery({
|
|
2627
|
-
queryKey: ["pendleMarkets", chainId, sortBy, assetFilter],
|
|
3575
|
+
queryKey: ["pendleMarkets", chainId, sortBy, assetFilter, minTvl],
|
|
2628
3576
|
queryFn: async () => {
|
|
2629
3577
|
const underlyingSymbol = assetFilter && assetFilter.length === 1 ? assetFilter[0] : void 0;
|
|
2630
3578
|
const orderBy = sortBy === "tvl" ? "tvl_usd" : "implied_apy";
|
|
@@ -2653,6 +3601,12 @@ function usePendleData(options = {}) {
|
|
|
2653
3601
|
(m) => assetFilter.includes(m.underlyingSymbol.toUpperCase())
|
|
2654
3602
|
);
|
|
2655
3603
|
}
|
|
3604
|
+
if (minTvl !== void 0 && minTvl > 0) {
|
|
3605
|
+
markets = markets.filter((m) => {
|
|
3606
|
+
const tvl = parseFloat(m.tvlUsd || "0");
|
|
3607
|
+
return tvl >= minTvl;
|
|
3608
|
+
});
|
|
3609
|
+
}
|
|
2656
3610
|
if (sortBy === "expiry") {
|
|
2657
3611
|
markets.sort((a, b) => {
|
|
2658
3612
|
return new Date(a.expiry).getTime() - new Date(b.expiry).getTime();
|
|
@@ -2711,15 +3665,6 @@ function usePendleData(options = {}) {
|
|
|
2711
3665
|
}
|
|
2712
3666
|
};
|
|
2713
3667
|
}
|
|
2714
|
-
var TOKEN_DECIMALS4 = {
|
|
2715
|
-
USDC: 6,
|
|
2716
|
-
USDT: 6,
|
|
2717
|
-
DAI: 18,
|
|
2718
|
-
ETH: 18,
|
|
2719
|
-
WETH: 18,
|
|
2720
|
-
WBTC: 8,
|
|
2721
|
-
cbBTC: 8
|
|
2722
|
-
};
|
|
2723
3668
|
function formatAPY3(apy) {
|
|
2724
3669
|
if (!apy) return "0.00%";
|
|
2725
3670
|
return `${parseFloat(apy).toFixed(2)}%`;
|
|
@@ -2745,9 +3690,10 @@ function PendleMarketsList({
|
|
|
2745
3690
|
showHistory = true,
|
|
2746
3691
|
showSearch = true,
|
|
2747
3692
|
showSort = true,
|
|
2748
|
-
actionMode = "modal",
|
|
2749
3693
|
defaultSort = "fixed_apy",
|
|
2750
3694
|
assetFilter,
|
|
3695
|
+
minTvl: initialMinTvl,
|
|
3696
|
+
showTvlFilter = true,
|
|
2751
3697
|
onMarketSelect,
|
|
2752
3698
|
onDeposit,
|
|
2753
3699
|
onWithdraw
|
|
@@ -2755,7 +3701,13 @@ function PendleMarketsList({
|
|
|
2755
3701
|
const [searchQuery, setSearchQuery] = useState("");
|
|
2756
3702
|
const [sortBy, setSortBy] = useState(defaultSort);
|
|
2757
3703
|
const [selectedMarket, setSelectedMarket] = useState(null);
|
|
2758
|
-
const
|
|
3704
|
+
const [minTvlFilter, setMinTvlFilter] = useState(initialMinTvl);
|
|
3705
|
+
const [showFilterPanel, setShowFilterPanel] = useState(false);
|
|
3706
|
+
const { markets, isLoading, isError, refetch } = usePendleData({ sortBy, assetFilter, minTvl: minTvlFilter });
|
|
3707
|
+
const handleMinTvlChange = useCallback((value) => {
|
|
3708
|
+
const num = parseFloat(value);
|
|
3709
|
+
setMinTvlFilter(isNaN(num) || num <= 0 ? void 0 : num);
|
|
3710
|
+
}, []);
|
|
2759
3711
|
const filteredMarkets = useMemo(() => {
|
|
2760
3712
|
if (!searchQuery) return markets;
|
|
2761
3713
|
const query = searchQuery.toLowerCase();
|
|
@@ -2778,50 +3730,120 @@ function PendleMarketsList({
|
|
|
2778
3730
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2779
3731
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
|
|
2780
3732
|
/* @__PURE__ */ jsx(ChainSwitcher, {}),
|
|
2781
|
-
/* @__PURE__ */
|
|
3733
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3734
|
+
/* @__PURE__ */ jsx(EarnAccountBalance, { compact: true }),
|
|
3735
|
+
/* @__PURE__ */ jsx(WalletStatus, { compact: true })
|
|
3736
|
+
] })
|
|
2782
3737
|
] }),
|
|
2783
|
-
(showSearch || showSort) && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
2784
|
-
|
|
3738
|
+
(showSearch || showSort || showTvlFilter) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3739
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
3740
|
+
showSearch && /* @__PURE__ */ jsxs(
|
|
3741
|
+
"div",
|
|
3742
|
+
{
|
|
3743
|
+
className: "flex-1 flex items-center gap-2 px-3 py-2 rounded-lg border",
|
|
3744
|
+
style: {
|
|
3745
|
+
backgroundColor: "var(--compass-color-background)",
|
|
3746
|
+
borderColor: "var(--compass-color-border)"
|
|
3747
|
+
},
|
|
3748
|
+
children: [
|
|
3749
|
+
/* @__PURE__ */ jsx(Search, { size: 16, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
3750
|
+
/* @__PURE__ */ jsx(
|
|
3751
|
+
"input",
|
|
3752
|
+
{
|
|
3753
|
+
type: "text",
|
|
3754
|
+
placeholder: "Search markets...",
|
|
3755
|
+
value: searchQuery,
|
|
3756
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
3757
|
+
className: "flex-1 bg-transparent outline-none text-sm",
|
|
3758
|
+
style: { color: "var(--compass-color-text)" }
|
|
3759
|
+
}
|
|
3760
|
+
)
|
|
3761
|
+
]
|
|
3762
|
+
}
|
|
3763
|
+
),
|
|
3764
|
+
showSort && /* @__PURE__ */ jsxs(
|
|
3765
|
+
"select",
|
|
3766
|
+
{
|
|
3767
|
+
value: sortBy,
|
|
3768
|
+
onChange: (e) => setSortBy(e.target.value),
|
|
3769
|
+
className: "px-3 py-2 rounded-lg border text-sm cursor-pointer",
|
|
3770
|
+
style: {
|
|
3771
|
+
backgroundColor: "var(--compass-color-background)",
|
|
3772
|
+
borderColor: "var(--compass-color-border)",
|
|
3773
|
+
color: "var(--compass-color-text)"
|
|
3774
|
+
},
|
|
3775
|
+
children: [
|
|
3776
|
+
/* @__PURE__ */ jsx("option", { value: "fixed_apy", children: "Fixed APY" }),
|
|
3777
|
+
/* @__PURE__ */ jsx("option", { value: "tvl", children: "TVL" }),
|
|
3778
|
+
/* @__PURE__ */ jsx("option", { value: "expiry", children: "Expiry" })
|
|
3779
|
+
]
|
|
3780
|
+
}
|
|
3781
|
+
),
|
|
3782
|
+
showTvlFilter && /* @__PURE__ */ jsxs(
|
|
3783
|
+
"button",
|
|
3784
|
+
{
|
|
3785
|
+
onClick: () => setShowFilterPanel(!showFilterPanel),
|
|
3786
|
+
className: "px-3 py-2 rounded-lg border text-sm flex items-center gap-2",
|
|
3787
|
+
style: {
|
|
3788
|
+
backgroundColor: showFilterPanel || minTvlFilter ? "var(--compass-color-primary-muted)" : "var(--compass-color-background)",
|
|
3789
|
+
borderColor: showFilterPanel || minTvlFilter ? "var(--compass-color-primary)" : "var(--compass-color-border)",
|
|
3790
|
+
color: showFilterPanel || minTvlFilter ? "var(--compass-color-primary)" : "var(--compass-color-text)"
|
|
3791
|
+
},
|
|
3792
|
+
children: [
|
|
3793
|
+
/* @__PURE__ */ jsx(SlidersHorizontal, { size: 14 }),
|
|
3794
|
+
"Filter"
|
|
3795
|
+
]
|
|
3796
|
+
}
|
|
3797
|
+
)
|
|
3798
|
+
] }),
|
|
3799
|
+
showTvlFilter && showFilterPanel && /* @__PURE__ */ jsxs(
|
|
2785
3800
|
"div",
|
|
2786
3801
|
{
|
|
2787
|
-
className: "flex
|
|
3802
|
+
className: "flex items-center gap-3 p-3 rounded-lg border",
|
|
2788
3803
|
style: {
|
|
2789
|
-
backgroundColor: "var(--compass-color-
|
|
3804
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
2790
3805
|
borderColor: "var(--compass-color-border)"
|
|
2791
3806
|
},
|
|
2792
3807
|
children: [
|
|
2793
|
-
/* @__PURE__ */ jsx(Search, { size: 16, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
2794
3808
|
/* @__PURE__ */ jsx(
|
|
2795
|
-
"
|
|
3809
|
+
"label",
|
|
2796
3810
|
{
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
3811
|
+
className: "text-sm font-medium whitespace-nowrap",
|
|
3812
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
3813
|
+
children: "Min TVL:"
|
|
3814
|
+
}
|
|
3815
|
+
),
|
|
3816
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3817
|
+
/* @__PURE__ */ jsx("span", { style: { color: "var(--compass-color-text-tertiary)" }, children: "$" }),
|
|
3818
|
+
/* @__PURE__ */ jsx(
|
|
3819
|
+
"input",
|
|
3820
|
+
{
|
|
3821
|
+
type: "number",
|
|
3822
|
+
placeholder: "0",
|
|
3823
|
+
value: minTvlFilter || "",
|
|
3824
|
+
onChange: (e) => handleMinTvlChange(e.target.value),
|
|
3825
|
+
className: "w-24 px-2 py-1 rounded border text-sm bg-transparent",
|
|
3826
|
+
style: {
|
|
3827
|
+
borderColor: "var(--compass-color-border)",
|
|
3828
|
+
color: "var(--compass-color-text)"
|
|
3829
|
+
}
|
|
3830
|
+
}
|
|
3831
|
+
)
|
|
3832
|
+
] }),
|
|
3833
|
+
minTvlFilter && /* @__PURE__ */ jsx(
|
|
3834
|
+
"button",
|
|
3835
|
+
{
|
|
3836
|
+
onClick: () => setMinTvlFilter(void 0),
|
|
3837
|
+
className: "text-xs px-2 py-1 rounded",
|
|
3838
|
+
style: {
|
|
3839
|
+
backgroundColor: "var(--compass-color-error-muted)",
|
|
3840
|
+
color: "var(--compass-color-error)"
|
|
3841
|
+
},
|
|
3842
|
+
children: "Clear"
|
|
2803
3843
|
}
|
|
2804
3844
|
)
|
|
2805
3845
|
]
|
|
2806
3846
|
}
|
|
2807
|
-
),
|
|
2808
|
-
showSort && /* @__PURE__ */ jsxs(
|
|
2809
|
-
"select",
|
|
2810
|
-
{
|
|
2811
|
-
value: sortBy,
|
|
2812
|
-
onChange: (e) => setSortBy(e.target.value),
|
|
2813
|
-
className: "px-3 py-2 rounded-lg border text-sm cursor-pointer",
|
|
2814
|
-
style: {
|
|
2815
|
-
backgroundColor: "var(--compass-color-background)",
|
|
2816
|
-
borderColor: "var(--compass-color-border)",
|
|
2817
|
-
color: "var(--compass-color-text)"
|
|
2818
|
-
},
|
|
2819
|
-
children: [
|
|
2820
|
-
/* @__PURE__ */ jsx("option", { value: "fixed_apy", children: "Fixed APY" }),
|
|
2821
|
-
/* @__PURE__ */ jsx("option", { value: "tvl", children: "TVL" }),
|
|
2822
|
-
/* @__PURE__ */ jsx("option", { value: "expiry", children: "Expiry" })
|
|
2823
|
-
]
|
|
2824
|
-
}
|
|
2825
3847
|
)
|
|
2826
3848
|
] }),
|
|
2827
3849
|
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx(Loader2, { size: 24, className: "animate-spin", style: { color: "var(--compass-color-primary)" } }) }) : isError ? /* @__PURE__ */ jsx(
|
|
@@ -2956,7 +3978,7 @@ function PendleMarketsList({
|
|
|
2956
3978
|
market.marketAddress
|
|
2957
3979
|
);
|
|
2958
3980
|
}) }),
|
|
2959
|
-
|
|
3981
|
+
selectedMarket && /* @__PURE__ */ jsx(
|
|
2960
3982
|
ActionModal,
|
|
2961
3983
|
{
|
|
2962
3984
|
isOpen: !!selectedMarket,
|
|
@@ -2984,8 +4006,7 @@ function PendleMarketsList({
|
|
|
2984
4006
|
{
|
|
2985
4007
|
venueType: "PENDLE_PT",
|
|
2986
4008
|
venueAddress: selectedMarket.marketAddress,
|
|
2987
|
-
|
|
2988
|
-
tokenDecimals: TOKEN_DECIMALS4[selectedMarket.underlyingSymbol] || 18,
|
|
4009
|
+
venueToken: selectedMarket.underlyingSymbol,
|
|
2989
4010
|
positionBalance: selectedMarket.userPosition?.balance,
|
|
2990
4011
|
onSuccess: handleActionSuccess
|
|
2991
4012
|
}
|
|
@@ -2996,43 +4017,55 @@ function PendleMarketsList({
|
|
|
2996
4017
|
] });
|
|
2997
4018
|
}
|
|
2998
4019
|
function useSwapQuote({ fromToken, toToken, amount, enabled = true }) {
|
|
2999
|
-
const { client } = useEmbeddableApi();
|
|
3000
4020
|
const { chainId } = useChain();
|
|
4021
|
+
const { address } = useCompassWallet();
|
|
3001
4022
|
const query = useQuery({
|
|
3002
|
-
queryKey: ["swapQuote", chainId, fromToken, toToken, amount],
|
|
4023
|
+
queryKey: ["swapQuote", chainId, fromToken, toToken, amount, address],
|
|
3003
4024
|
queryFn: async () => {
|
|
3004
|
-
if (!fromToken || !toToken || !amount || parseFloat(amount) <= 0) {
|
|
4025
|
+
if (!fromToken || !toToken || !amount || parseFloat(amount) <= 0 || !address) {
|
|
3005
4026
|
return null;
|
|
3006
4027
|
}
|
|
3007
4028
|
try {
|
|
3008
|
-
const
|
|
3009
|
-
|
|
4029
|
+
const params = new URLSearchParams({
|
|
4030
|
+
owner: address,
|
|
4031
|
+
chain: chainId,
|
|
4032
|
+
tokenIn: fromToken,
|
|
4033
|
+
tokenOut: toToken,
|
|
4034
|
+
amountIn: amount
|
|
4035
|
+
});
|
|
4036
|
+
const response = await fetch(`/api/compass/swap/quote?${params}`);
|
|
4037
|
+
if (!response.ok) {
|
|
4038
|
+
const error = await response.json();
|
|
4039
|
+
throw new Error(error.error || "Failed to get swap quote");
|
|
4040
|
+
}
|
|
4041
|
+
const data = await response.json();
|
|
4042
|
+
const outputAmount = data.estimatedAmountOut || "0";
|
|
4043
|
+
const inputAmountNum = parseFloat(amount);
|
|
4044
|
+
const outputAmountNum = parseFloat(outputAmount);
|
|
3010
4045
|
return {
|
|
3011
4046
|
inputAmount: amount,
|
|
3012
4047
|
outputAmount,
|
|
3013
|
-
rate:
|
|
3014
|
-
priceImpact: "0",
|
|
3015
|
-
fee: "0"
|
|
4048
|
+
rate: inputAmountNum > 0 ? (outputAmountNum / inputAmountNum).toString() : "0"
|
|
3016
4049
|
};
|
|
3017
4050
|
} catch (error) {
|
|
3018
4051
|
console.error("Failed to get swap quote:", error);
|
|
3019
|
-
|
|
4052
|
+
throw error;
|
|
3020
4053
|
}
|
|
3021
4054
|
},
|
|
3022
|
-
enabled: enabled && !!fromToken && !!toToken && !!amount && parseFloat(amount) > 0,
|
|
4055
|
+
enabled: enabled && !!address && !!fromToken && !!toToken && !!amount && parseFloat(amount) > 0,
|
|
3023
4056
|
staleTime: 10 * 1e3,
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
// Refresh every 15 seconds
|
|
4057
|
+
refetchInterval: 15 * 1e3,
|
|
4058
|
+
retry: 1
|
|
3027
4059
|
});
|
|
3028
4060
|
return {
|
|
3029
4061
|
quote: query.data,
|
|
3030
4062
|
isLoading: query.isLoading,
|
|
3031
4063
|
isError: query.isError,
|
|
4064
|
+
error: query.error,
|
|
3032
4065
|
refetch: query.refetch
|
|
3033
4066
|
};
|
|
3034
4067
|
}
|
|
3035
|
-
var DEFAULT_TOKENS = ["USDC", "ETH", "WETH", "WBTC", "DAI", "USDT"];
|
|
4068
|
+
var DEFAULT_TOKENS = ["USDC", "ETH", "WETH", "WBTC", "DAI", "USDT", "AUSD", "SBC"];
|
|
3036
4069
|
function SwapWidget({
|
|
3037
4070
|
layout = "full",
|
|
3038
4071
|
defaultFromToken = "ETH",
|
|
@@ -3040,7 +4073,6 @@ function SwapWidget({
|
|
|
3040
4073
|
allowedTokens = DEFAULT_TOKENS,
|
|
3041
4074
|
showReverseButton = true,
|
|
3042
4075
|
showSettings = false,
|
|
3043
|
-
showPriceImpact = true,
|
|
3044
4076
|
onSwapSuccess,
|
|
3045
4077
|
onSwapError
|
|
3046
4078
|
}) {
|
|
@@ -3048,8 +4080,8 @@ function SwapWidget({
|
|
|
3048
4080
|
const [toToken, setToToken] = useState(defaultToToken);
|
|
3049
4081
|
const [fromAmount, setFromAmount] = useState("");
|
|
3050
4082
|
const [isSwapping, setIsSwapping] = useState(false);
|
|
3051
|
-
const
|
|
3052
|
-
const {
|
|
4083
|
+
const [swapStatus, setSwapStatus] = useState("");
|
|
4084
|
+
const { address, isConnected, signTypedData } = useCompassWallet();
|
|
3053
4085
|
const { chainId } = useChain();
|
|
3054
4086
|
const { quote, isLoading: isQuoteLoading } = useSwapQuote({
|
|
3055
4087
|
fromToken,
|
|
@@ -3065,32 +4097,75 @@ function SwapWidget({
|
|
|
3065
4097
|
const handleSwap = useCallback(async () => {
|
|
3066
4098
|
if (!address || !fromAmount || !quote) return;
|
|
3067
4099
|
setIsSwapping(true);
|
|
4100
|
+
setSwapStatus("Preparing swap...");
|
|
3068
4101
|
try {
|
|
3069
|
-
const
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
4102
|
+
const prepareResponse = await fetch("/api/compass/swap/prepare", {
|
|
4103
|
+
method: "POST",
|
|
4104
|
+
headers: { "Content-Type": "application/json" },
|
|
4105
|
+
body: JSON.stringify({
|
|
4106
|
+
owner: address,
|
|
4107
|
+
chain: chainId,
|
|
4108
|
+
tokenIn: fromToken,
|
|
4109
|
+
tokenOut: toToken,
|
|
4110
|
+
amountIn: fromAmount
|
|
4111
|
+
})
|
|
4112
|
+
});
|
|
4113
|
+
if (!prepareResponse.ok) {
|
|
4114
|
+
const error = await prepareResponse.json();
|
|
4115
|
+
throw new Error(error.error || "Failed to prepare swap");
|
|
4116
|
+
}
|
|
4117
|
+
const prepareData = await prepareResponse.json();
|
|
4118
|
+
const { eip712, normalizedTypes } = prepareData;
|
|
4119
|
+
if (!eip712) {
|
|
4120
|
+
throw new Error("No EIP-712 data returned from prepare");
|
|
4121
|
+
}
|
|
4122
|
+
setSwapStatus("Please sign the transaction...");
|
|
4123
|
+
const signature = await signTypedData({
|
|
4124
|
+
domain: eip712.domain,
|
|
4125
|
+
types: normalizedTypes || eip712.types,
|
|
4126
|
+
primaryType: "SafeTx",
|
|
4127
|
+
message: eip712.message
|
|
4128
|
+
});
|
|
4129
|
+
setSwapStatus("Executing swap...");
|
|
4130
|
+
const executeResponse = await fetch("/api/compass/swap/execute", {
|
|
4131
|
+
method: "POST",
|
|
4132
|
+
headers: { "Content-Type": "application/json" },
|
|
4133
|
+
body: JSON.stringify({
|
|
4134
|
+
owner: address,
|
|
4135
|
+
chain: chainId,
|
|
4136
|
+
eip712,
|
|
4137
|
+
signature
|
|
4138
|
+
})
|
|
3075
4139
|
});
|
|
3076
|
-
|
|
3077
|
-
|
|
4140
|
+
if (!executeResponse.ok) {
|
|
4141
|
+
const error = await executeResponse.json();
|
|
4142
|
+
throw new Error(error.error || "Failed to execute swap");
|
|
4143
|
+
}
|
|
4144
|
+
const executeData = await executeResponse.json();
|
|
4145
|
+
const txHash = executeData.txHash;
|
|
4146
|
+
setSwapStatus("Swap successful!");
|
|
4147
|
+
onSwapSuccess?.(fromToken, toToken, fromAmount, quote.outputAmount, txHash);
|
|
3078
4148
|
setFromAmount("");
|
|
4149
|
+
setTimeout(() => setSwapStatus(""), 3e3);
|
|
3079
4150
|
} catch (error) {
|
|
3080
4151
|
console.error("Swap failed:", error);
|
|
4152
|
+
setSwapStatus("");
|
|
3081
4153
|
onSwapError?.(error);
|
|
3082
4154
|
} finally {
|
|
3083
4155
|
setIsSwapping(false);
|
|
3084
4156
|
}
|
|
3085
|
-
}, [address, fromAmount, quote,
|
|
4157
|
+
}, [address, fromAmount, quote, chainId, fromToken, toToken, signTypedData, onSwapSuccess, onSwapError]);
|
|
3086
4158
|
const isCompact = layout === "compact";
|
|
3087
4159
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
3088
4160
|
!isCompact && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
|
|
3089
4161
|
/* @__PURE__ */ jsx(ChainSwitcher, {}),
|
|
3090
|
-
/* @__PURE__ */
|
|
4162
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4163
|
+
/* @__PURE__ */ jsx(EarnAccountBalance, { compact: true }),
|
|
4164
|
+
/* @__PURE__ */ jsx(WalletStatus, { compact: true })
|
|
4165
|
+
] })
|
|
3091
4166
|
] }),
|
|
3092
4167
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3093
|
-
/* @__PURE__ */ jsxs("div", { className: "p-4 rounded-xl border", style: { backgroundColor: "var(--compass-color-surface)", borderColor: "var(--compass-color-border)" }, children: [
|
|
4168
|
+
/* @__PURE__ */ jsxs("div", { className: "p-4 rounded-xl border relative", style: { backgroundColor: "var(--compass-color-surface)", borderColor: "var(--compass-color-border)" }, children: [
|
|
3094
4169
|
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "From" }) }),
|
|
3095
4170
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
3096
4171
|
/* @__PURE__ */ jsx(
|
|
@@ -3100,7 +4175,7 @@ function SwapWidget({
|
|
|
3100
4175
|
value: fromAmount,
|
|
3101
4176
|
onChange: (e) => setFromAmount(e.target.value),
|
|
3102
4177
|
placeholder: "0.00",
|
|
3103
|
-
className: "flex-1 bg-transparent outline-none text-2xl font-mono",
|
|
4178
|
+
className: "flex-1 bg-transparent outline-none text-2xl font-mono min-w-0",
|
|
3104
4179
|
style: { color: "var(--compass-color-text)" }
|
|
3105
4180
|
}
|
|
3106
4181
|
),
|
|
@@ -3109,9 +4184,9 @@ function SwapWidget({
|
|
|
3109
4184
|
{
|
|
3110
4185
|
value: fromToken,
|
|
3111
4186
|
onChange: (e) => setFromToken(e.target.value),
|
|
3112
|
-
className: "px-3 py-2 rounded-lg border text-sm font-medium cursor-pointer",
|
|
4187
|
+
className: "px-3 py-2 rounded-lg border text-sm font-medium cursor-pointer flex-shrink-0",
|
|
3113
4188
|
style: { backgroundColor: "var(--compass-color-background)", borderColor: "var(--compass-color-border)", color: "var(--compass-color-text)" },
|
|
3114
|
-
children: allowedTokens.map((token) => /* @__PURE__ */ jsx("option", { value: token, children: token }, token))
|
|
4189
|
+
children: allowedTokens.filter((t) => t !== toToken).map((token) => /* @__PURE__ */ jsx("option", { value: token, children: token }, token))
|
|
3115
4190
|
}
|
|
3116
4191
|
)
|
|
3117
4192
|
] })
|
|
@@ -3131,7 +4206,7 @@ function SwapWidget({
|
|
|
3131
4206
|
/* @__PURE__ */ jsx("div", { className: "flex-1 text-2xl font-mono", style: { color: isQuoteLoading ? "var(--compass-color-text-tertiary)" : "var(--compass-color-text)" }, children: isQuoteLoading ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
3132
4207
|
/* @__PURE__ */ jsx(Loader2, { size: 16, className: "animate-spin" }),
|
|
3133
4208
|
"Loading..."
|
|
3134
|
-
] }) : quote?.outputAmount ? parseFloat(quote.outputAmount).toFixed(
|
|
4209
|
+
] }) : quote?.outputAmount ? parseFloat(quote.outputAmount).toFixed(8) : "0.00000000" }),
|
|
3135
4210
|
/* @__PURE__ */ jsx(
|
|
3136
4211
|
"select",
|
|
3137
4212
|
{
|
|
@@ -3145,14 +4220,6 @@ function SwapWidget({
|
|
|
3145
4220
|
] })
|
|
3146
4221
|
] })
|
|
3147
4222
|
] }),
|
|
3148
|
-
showPriceImpact && quote && parseFloat(quote.priceImpact) > 0.01 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 p-3 rounded-lg", style: { backgroundColor: "var(--compass-color-warning-muted)" }, children: [
|
|
3149
|
-
/* @__PURE__ */ jsx(AlertCircle, { size: 16, style: { color: "var(--compass-color-warning)" } }),
|
|
3150
|
-
/* @__PURE__ */ jsxs("span", { className: "text-sm", style: { color: "var(--compass-color-warning)" }, children: [
|
|
3151
|
-
"Price impact: ",
|
|
3152
|
-
(parseFloat(quote.priceImpact) * 100).toFixed(2),
|
|
3153
|
-
"%"
|
|
3154
|
-
] })
|
|
3155
|
-
] }),
|
|
3156
4223
|
quote && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", style: { color: "var(--compass-color-text-secondary)" }, children: [
|
|
3157
4224
|
/* @__PURE__ */ jsx("span", { children: "Rate" }),
|
|
3158
4225
|
/* @__PURE__ */ jsxs("span", { className: "font-mono", children: [
|
|
@@ -3164,6 +4231,20 @@ function SwapWidget({
|
|
|
3164
4231
|
toToken
|
|
3165
4232
|
] })
|
|
3166
4233
|
] }),
|
|
4234
|
+
swapStatus && /* @__PURE__ */ jsxs(
|
|
4235
|
+
"div",
|
|
4236
|
+
{
|
|
4237
|
+
className: "flex items-center gap-2 p-3 rounded-lg text-sm",
|
|
4238
|
+
style: {
|
|
4239
|
+
backgroundColor: swapStatus.includes("successful") ? "var(--compass-color-success-muted)" : "var(--compass-color-surface)",
|
|
4240
|
+
color: swapStatus.includes("successful") ? "var(--compass-color-success)" : "var(--compass-color-text-secondary)"
|
|
4241
|
+
},
|
|
4242
|
+
children: [
|
|
4243
|
+
!swapStatus.includes("successful") && /* @__PURE__ */ jsx(Loader2, { size: 14, className: "animate-spin" }),
|
|
4244
|
+
swapStatus
|
|
4245
|
+
]
|
|
4246
|
+
}
|
|
4247
|
+
),
|
|
3167
4248
|
!isConnected ? /* @__PURE__ */ jsxs(
|
|
3168
4249
|
"div",
|
|
3169
4250
|
{
|
|
@@ -3199,78 +4280,29 @@ function SwapWidget({
|
|
|
3199
4280
|
)
|
|
3200
4281
|
] });
|
|
3201
4282
|
}
|
|
3202
|
-
|
|
3203
|
-
// src/components/CompassEarnWidget/presets.ts
|
|
3204
|
-
var allTabs = [
|
|
4283
|
+
var tabs = [
|
|
3205
4284
|
{ id: "vaults", label: "Vaults", enabled: true },
|
|
3206
4285
|
{ id: "aave", label: "Aave", enabled: true },
|
|
3207
4286
|
{ id: "pendle", label: "Pendle", enabled: true },
|
|
3208
4287
|
{ id: "swap", label: "Swap", enabled: true }
|
|
3209
4288
|
];
|
|
3210
|
-
function getTabsForPreset(preset) {
|
|
3211
|
-
switch (preset) {
|
|
3212
|
-
case "full":
|
|
3213
|
-
return allTabs;
|
|
3214
|
-
case "earn-only":
|
|
3215
|
-
return allTabs.map((tab) => ({
|
|
3216
|
-
...tab,
|
|
3217
|
-
enabled: tab.id !== "swap"
|
|
3218
|
-
}));
|
|
3219
|
-
case "swap-only":
|
|
3220
|
-
return allTabs.map((tab) => ({
|
|
3221
|
-
...tab,
|
|
3222
|
-
enabled: tab.id === "swap"
|
|
3223
|
-
}));
|
|
3224
|
-
case "vaults-only":
|
|
3225
|
-
return allTabs.map((tab) => ({
|
|
3226
|
-
...tab,
|
|
3227
|
-
enabled: tab.id === "vaults"
|
|
3228
|
-
}));
|
|
3229
|
-
default:
|
|
3230
|
-
return allTabs;
|
|
3231
|
-
}
|
|
3232
|
-
}
|
|
3233
|
-
function getDefaultTab(tabs) {
|
|
3234
|
-
const enabledTab = tabs.find((t) => t.enabled);
|
|
3235
|
-
return enabledTab?.id || "vaults";
|
|
3236
|
-
}
|
|
3237
4289
|
function CompassEarnWidget({
|
|
3238
|
-
|
|
3239
|
-
enableVaults,
|
|
3240
|
-
enableAave,
|
|
3241
|
-
enablePendle,
|
|
3242
|
-
enableSwap,
|
|
3243
|
-
defaultTab,
|
|
3244
|
-
showHeader = true,
|
|
4290
|
+
defaultTab = "vaults",
|
|
3245
4291
|
onTabChange
|
|
3246
4292
|
}) {
|
|
3247
|
-
const
|
|
3248
|
-
const baseTabs = getTabsForPreset(preset);
|
|
3249
|
-
return baseTabs.map((tab) => {
|
|
3250
|
-
let enabled = tab.enabled;
|
|
3251
|
-
if (tab.id === "vaults" && enableVaults !== void 0) enabled = enableVaults;
|
|
3252
|
-
if (tab.id === "aave" && enableAave !== void 0) enabled = enableAave;
|
|
3253
|
-
if (tab.id === "pendle" && enablePendle !== void 0) enabled = enablePendle;
|
|
3254
|
-
if (tab.id === "swap" && enableSwap !== void 0) enabled = enableSwap;
|
|
3255
|
-
return { ...tab, enabled };
|
|
3256
|
-
});
|
|
3257
|
-
}, [preset, enableVaults, enableAave, enablePendle, enableSwap]);
|
|
3258
|
-
const enabledTabs = tabs.filter((t) => t.enabled);
|
|
3259
|
-
const initialTab = defaultTab && tabs.find((t) => t.id === defaultTab)?.enabled ? defaultTab : getDefaultTab(tabs);
|
|
3260
|
-
const [activeTab, setActiveTab] = useState(initialTab);
|
|
4293
|
+
const [activeTab, setActiveTab] = useState(defaultTab);
|
|
3261
4294
|
const handleTabChange = (tab) => {
|
|
3262
4295
|
setActiveTab(tab);
|
|
3263
4296
|
onTabChange?.(tab);
|
|
3264
4297
|
};
|
|
3265
|
-
const showTabs = enabledTabs.length > 1;
|
|
3266
4298
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
3267
|
-
|
|
3268
|
-
|
|
4299
|
+
/* @__PURE__ */ jsx("h1", { className: "font-bold text-xl", style: { color: "var(--compass-color-text)" }, children: "Compass Earn" }),
|
|
4300
|
+
/* @__PURE__ */ jsx(
|
|
3269
4301
|
"div",
|
|
3270
4302
|
{
|
|
3271
4303
|
className: "flex gap-1 p-1 rounded-lg",
|
|
3272
4304
|
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
3273
|
-
children:
|
|
4305
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsx(
|
|
3274
4306
|
"button",
|
|
3275
4307
|
{
|
|
3276
4308
|
onClick: () => handleTabChange(tab.id),
|
|
@@ -3286,14 +4318,34 @@ function CompassEarnWidget({
|
|
|
3286
4318
|
}
|
|
3287
4319
|
),
|
|
3288
4320
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
3289
|
-
activeTab === "vaults" &&
|
|
3290
|
-
activeTab === "aave" &&
|
|
3291
|
-
activeTab === "pendle" &&
|
|
3292
|
-
activeTab === "swap" &&
|
|
4321
|
+
activeTab === "vaults" && /* @__PURE__ */ jsx(VaultsList, {}),
|
|
4322
|
+
activeTab === "aave" && /* @__PURE__ */ jsx(AaveMarketsList, {}),
|
|
4323
|
+
activeTab === "pendle" && /* @__PURE__ */ jsx(PendleMarketsList, {}),
|
|
4324
|
+
activeTab === "swap" && /* @__PURE__ */ jsx(SwapWidget, {})
|
|
3293
4325
|
] })
|
|
3294
4326
|
] });
|
|
3295
4327
|
}
|
|
4328
|
+
var CHAINS = {
|
|
4329
|
+
ethereum: {
|
|
4330
|
+
id: "ethereum",
|
|
4331
|
+
name: "Ethereum",
|
|
4332
|
+
viemChain: mainnet,
|
|
4333
|
+
icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png"
|
|
4334
|
+
},
|
|
4335
|
+
base: {
|
|
4336
|
+
id: "base",
|
|
4337
|
+
name: "Base",
|
|
4338
|
+
viemChain: base,
|
|
4339
|
+
icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/base/info/logo.png"
|
|
4340
|
+
},
|
|
4341
|
+
arbitrum: {
|
|
4342
|
+
id: "arbitrum",
|
|
4343
|
+
name: "Arbitrum",
|
|
4344
|
+
viemChain: arbitrum,
|
|
4345
|
+
icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/arbitrum/info/logo.png"
|
|
4346
|
+
}
|
|
4347
|
+
};
|
|
3296
4348
|
|
|
3297
|
-
export { AaveMarketsList, ActionModal, ApiProvider, CHAINS, ChainSwitcher, CompassEarnWidget, CompassProvider, DepositWithdrawForm, EarnAccountGuard, PendleMarketsList, PnLSummary, SwapWidget,
|
|
4349
|
+
export { AaveMarketsList, AccountBalancesModal, ActionModal, ApiProvider, CHAINS, ChainSwitcher, CompassEarnWidget, CompassProvider, DepositWithdrawForm, EarnAccountBalance, EarnAccountGuard, PendleMarketsList, PnLSummary, SwapWidget, ThemeProvider, TransactionHistory, VaultsList, WalletStatus, themePresets, useAaveData, useChain, useCompassApi, useCompassChain, useCompassWallet, useEarnAccount, useEmbeddableApi, useEmbeddableWallet, usePendleData, useSwapQuote, useTheme, useVaultsData };
|
|
3298
4350
|
//# sourceMappingURL=index.mjs.map
|
|
3299
4351
|
//# sourceMappingURL=index.mjs.map
|