@compass-labs/widgets 0.1.0 → 0.1.1
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 +20 -17
- package/dist/index.d.ts +20 -17
- package/dist/index.js +786 -175
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +788 -177
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.js +254 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +254 -0
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
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, Search, TrendingUp, Calendar, ArrowDownUp } from 'lucide-react';
|
|
7
7
|
|
|
8
8
|
// src/provider/CompassProvider.tsx
|
|
9
9
|
var ApiContext = createContext(null);
|
|
@@ -1121,7 +1121,7 @@ function PnLSummary({ pnl, tokenSymbol, tokenPrice }) {
|
|
|
1121
1121
|
const prefix = value >= 0 ? "+" : "";
|
|
1122
1122
|
return `${prefix}${value.toFixed(4)}`;
|
|
1123
1123
|
};
|
|
1124
|
-
const
|
|
1124
|
+
const formatUSD2 = (value) => {
|
|
1125
1125
|
const usdValue = value * tokenPrice;
|
|
1126
1126
|
const prefix = usdValue >= 0 ? "+$" : "-$";
|
|
1127
1127
|
return `${prefix}${Math.abs(usdValue).toFixed(2)}`;
|
|
@@ -1198,7 +1198,7 @@ function PnLSummary({ pnl, tokenSymbol, tokenPrice }) {
|
|
|
1198
1198
|
children: formatPnL(unrealizedPnl)
|
|
1199
1199
|
}
|
|
1200
1200
|
),
|
|
1201
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-mono", style: { color: pnlColor(unrealizedPnl) }, children:
|
|
1201
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-mono", style: { color: pnlColor(unrealizedPnl) }, children: formatUSD2(unrealizedPnl) })
|
|
1202
1202
|
] }),
|
|
1203
1203
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
1204
1204
|
/* @__PURE__ */ jsx(
|
|
@@ -1217,7 +1217,7 @@ function PnLSummary({ pnl, tokenSymbol, tokenPrice }) {
|
|
|
1217
1217
|
children: formatPnL(realizedPnl)
|
|
1218
1218
|
}
|
|
1219
1219
|
),
|
|
1220
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-mono", style: { color: pnlColor(realizedPnl) }, children:
|
|
1220
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-mono", style: { color: pnlColor(realizedPnl) }, children: formatUSD2(realizedPnl) })
|
|
1221
1221
|
] })
|
|
1222
1222
|
] }),
|
|
1223
1223
|
/* @__PURE__ */ jsxs(
|
|
@@ -1242,7 +1242,7 @@ function PnLSummary({ pnl, tokenSymbol, tokenPrice }) {
|
|
|
1242
1242
|
] }),
|
|
1243
1243
|
/* @__PURE__ */ jsxs("span", { className: "text-xs font-mono", style: { color: pnlColor(totalPnl) }, children: [
|
|
1244
1244
|
"(",
|
|
1245
|
-
|
|
1245
|
+
formatUSD2(totalPnl),
|
|
1246
1246
|
")"
|
|
1247
1247
|
] })
|
|
1248
1248
|
] })
|
|
@@ -1254,161 +1254,308 @@ function PnLSummary({ pnl, tokenSymbol, tokenPrice }) {
|
|
|
1254
1254
|
)
|
|
1255
1255
|
] });
|
|
1256
1256
|
}
|
|
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
|
-
|
|
1257
|
+
|
|
1258
|
+
// src/utils/format.ts
|
|
1259
|
+
function formatAmount(value) {
|
|
1260
|
+
const num = typeof value === "string" ? parseFloat(value) : value;
|
|
1261
|
+
if (isNaN(num)) return "0";
|
|
1262
|
+
return parseFloat(num.toFixed(6)).toString();
|
|
1263
|
+
}
|
|
1264
|
+
function TokenSelector({
|
|
1265
|
+
tokens,
|
|
1266
|
+
selectedToken,
|
|
1267
|
+
onSelect,
|
|
1268
|
+
balances,
|
|
1269
|
+
showBalances = true,
|
|
1270
|
+
disabled = false
|
|
1271
|
+
}) {
|
|
1272
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
1273
|
+
const dropdownRef = useRef(null);
|
|
1274
|
+
useEffect(() => {
|
|
1275
|
+
function handleClickOutside(event) {
|
|
1276
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
1277
|
+
setIsOpen(false);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1281
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1282
|
+
}, []);
|
|
1283
|
+
const handleSelect = (token) => {
|
|
1284
|
+
onSelect(token);
|
|
1285
|
+
setIsOpen(false);
|
|
1286
|
+
};
|
|
1287
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", ref: dropdownRef, children: [
|
|
1288
|
+
/* @__PURE__ */ jsxs(
|
|
1289
|
+
"button",
|
|
1290
|
+
{
|
|
1291
|
+
type: "button",
|
|
1292
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
1293
|
+
disabled,
|
|
1294
|
+
className: "flex items-center gap-2 px-3 py-2 rounded-lg border transition-colors min-w-[120px]",
|
|
1295
|
+
style: {
|
|
1296
|
+
backgroundColor: "var(--compass-color-background)",
|
|
1297
|
+
borderColor: isOpen ? "var(--compass-color-primary)" : "var(--compass-color-border)",
|
|
1298
|
+
color: "var(--compass-color-text)",
|
|
1299
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
1300
|
+
opacity: disabled ? 0.5 : 1
|
|
1301
|
+
},
|
|
1302
|
+
children: [
|
|
1303
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium flex-1 text-left", children: selectedToken }),
|
|
1304
|
+
/* @__PURE__ */ jsx(
|
|
1305
|
+
ChevronDown,
|
|
1306
|
+
{
|
|
1307
|
+
size: 16,
|
|
1308
|
+
style: {
|
|
1309
|
+
color: "var(--compass-color-text-secondary)",
|
|
1310
|
+
transform: isOpen ? "rotate(180deg)" : "rotate(0deg)",
|
|
1311
|
+
transition: "transform 0.2s"
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
)
|
|
1315
|
+
]
|
|
1316
|
+
}
|
|
1317
|
+
),
|
|
1318
|
+
isOpen && /* @__PURE__ */ jsx(
|
|
1319
|
+
"div",
|
|
1320
|
+
{
|
|
1321
|
+
className: "absolute z-50 mt-1 w-full min-w-[160px] rounded-lg border overflow-y-auto",
|
|
1322
|
+
style: {
|
|
1323
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
1324
|
+
borderColor: "var(--compass-color-border)",
|
|
1325
|
+
boxShadow: "var(--compass-shadow-lg)",
|
|
1326
|
+
maxHeight: "200px"
|
|
1327
|
+
},
|
|
1328
|
+
children: tokens.map((token) => {
|
|
1329
|
+
const balance = balances?.[token];
|
|
1330
|
+
const isSelected = token === selectedToken;
|
|
1331
|
+
return /* @__PURE__ */ jsxs(
|
|
1332
|
+
"button",
|
|
1333
|
+
{
|
|
1334
|
+
type: "button",
|
|
1335
|
+
onClick: () => handleSelect(token),
|
|
1336
|
+
className: "w-full px-3 py-2 flex items-center justify-between transition-colors",
|
|
1337
|
+
style: {
|
|
1338
|
+
backgroundColor: isSelected ? "var(--compass-color-primary-muted)" : "transparent",
|
|
1339
|
+
color: "var(--compass-color-text)"
|
|
1340
|
+
},
|
|
1341
|
+
onMouseEnter: (e) => {
|
|
1342
|
+
if (!isSelected) {
|
|
1343
|
+
e.currentTarget.style.backgroundColor = "var(--compass-color-surface-hover)";
|
|
1344
|
+
}
|
|
1345
|
+
},
|
|
1346
|
+
onMouseLeave: (e) => {
|
|
1347
|
+
if (!isSelected) {
|
|
1348
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
1349
|
+
}
|
|
1350
|
+
},
|
|
1351
|
+
children: [
|
|
1352
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: token }),
|
|
1353
|
+
showBalances && balance && /* @__PURE__ */ jsx(
|
|
1354
|
+
"span",
|
|
1355
|
+
{
|
|
1356
|
+
className: "text-sm font-mono",
|
|
1357
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
1358
|
+
children: formatAmount(balance)
|
|
1359
|
+
}
|
|
1360
|
+
)
|
|
1361
|
+
]
|
|
1362
|
+
},
|
|
1363
|
+
token
|
|
1364
|
+
);
|
|
1365
|
+
})
|
|
1366
|
+
}
|
|
1367
|
+
)
|
|
1368
|
+
] });
|
|
1369
|
+
}
|
|
1286
1370
|
function DepositWithdrawForm({
|
|
1287
1371
|
venueType,
|
|
1288
1372
|
venueAddress,
|
|
1289
|
-
|
|
1290
|
-
|
|
1373
|
+
venueToken,
|
|
1374
|
+
depositTokens = ["SBC", "AUSD", "USDC", "USDT", "WETH", "DAI"],
|
|
1291
1375
|
positionBalance = "0",
|
|
1292
1376
|
onSuccess,
|
|
1293
1377
|
onError
|
|
1294
1378
|
}) {
|
|
1295
1379
|
const [activeTab, setActiveTab] = useState("deposit");
|
|
1380
|
+
const [selectedToken, setSelectedToken] = useState(venueToken);
|
|
1296
1381
|
const [amount, setAmount] = useState("");
|
|
1297
1382
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
1298
1383
|
const [statusMessage, setStatusMessage] = useState("");
|
|
1299
1384
|
const [error, setError] = useState(null);
|
|
1300
|
-
const { address, isConnected, signTypedData
|
|
1301
|
-
const { client } = useEmbeddableApi();
|
|
1385
|
+
const { address, isConnected, signTypedData } = useCompassWallet();
|
|
1302
1386
|
const { chainId } = useChain();
|
|
1303
1387
|
const { earnAccountAddress } = useEarnAccount();
|
|
1304
1388
|
const queryClient = useQueryClient();
|
|
1305
|
-
const
|
|
1306
|
-
const targetChainId = chainConfig?.viemChain?.id;
|
|
1389
|
+
const needsSwap = activeTab === "deposit" && selectedToken !== venueToken;
|
|
1307
1390
|
const { data: tokenBalance } = useQuery({
|
|
1308
|
-
queryKey: ["earnAccountTokenBalance", chainId, earnAccountAddress,
|
|
1391
|
+
queryKey: ["earnAccountTokenBalance", chainId, earnAccountAddress, selectedToken],
|
|
1309
1392
|
queryFn: async () => {
|
|
1310
1393
|
if (!earnAccountAddress) return "0";
|
|
1311
1394
|
try {
|
|
1312
|
-
const response = await
|
|
1313
|
-
chain
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
return
|
|
1318
|
-
} catch
|
|
1319
|
-
console.error("Error fetching earn account token balance:", error2);
|
|
1395
|
+
const response = await fetch(
|
|
1396
|
+
`/api/compass/earn-account/balances?owner=${address}&chain=${chainId}&tokens=${selectedToken}`
|
|
1397
|
+
);
|
|
1398
|
+
if (!response.ok) return "0";
|
|
1399
|
+
const data = await response.json();
|
|
1400
|
+
return data.balances?.[selectedToken] || "0";
|
|
1401
|
+
} catch {
|
|
1320
1402
|
return "0";
|
|
1321
1403
|
}
|
|
1322
1404
|
},
|
|
1323
|
-
enabled: !!earnAccountAddress,
|
|
1405
|
+
enabled: !!earnAccountAddress && !!address,
|
|
1324
1406
|
staleTime: 10 * 1e3
|
|
1325
1407
|
});
|
|
1326
1408
|
const availableBalance = tokenBalance || "0";
|
|
1327
1409
|
const maxBalance = activeTab === "deposit" ? availableBalance : positionBalance;
|
|
1328
|
-
const handleQuickAmount = useCallback(
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1410
|
+
const handleQuickAmount = useCallback(
|
|
1411
|
+
(percentage) => {
|
|
1412
|
+
const max = parseFloat(maxBalance);
|
|
1413
|
+
if (isNaN(max)) return;
|
|
1414
|
+
setAmount(formatAmount(max * percentage));
|
|
1415
|
+
},
|
|
1416
|
+
[maxBalance]
|
|
1417
|
+
);
|
|
1333
1418
|
const handleSubmit = useCallback(async () => {
|
|
1334
1419
|
if (!address || !amount) return;
|
|
1335
1420
|
setIsSubmitting(true);
|
|
1336
1421
|
setStatusMessage("Preparing transaction...");
|
|
1337
1422
|
setError(null);
|
|
1338
1423
|
try {
|
|
1339
|
-
if (switchChain && targetChainId) {
|
|
1340
|
-
setStatusMessage("Checking network...");
|
|
1341
|
-
try {
|
|
1342
|
-
await switchChain(targetChainId);
|
|
1343
|
-
} catch {
|
|
1344
|
-
}
|
|
1345
|
-
}
|
|
1346
1424
|
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
|
-
|
|
1425
|
+
if (isDeposit && needsSwap) {
|
|
1426
|
+
setStatusMessage("Getting swap quote...");
|
|
1427
|
+
const quoteResponse = await fetch(
|
|
1428
|
+
`/api/compass/swap/quote?owner=${address}&chain=${chainId}&tokenIn=${selectedToken}&tokenOut=${venueToken}&amountIn=${amount}`
|
|
1429
|
+
);
|
|
1430
|
+
if (!quoteResponse.ok) {
|
|
1431
|
+
const errorData = await quoteResponse.json();
|
|
1432
|
+
throw new Error(errorData.error || "Failed to get swap quote");
|
|
1433
|
+
}
|
|
1434
|
+
const quoteData = await quoteResponse.json();
|
|
1435
|
+
const estimatedOutput = quoteData.estimatedAmountOut;
|
|
1436
|
+
if (!estimatedOutput || parseFloat(estimatedOutput) <= 0) {
|
|
1437
|
+
throw new Error("Invalid swap quote - no output amount");
|
|
1438
|
+
}
|
|
1439
|
+
const depositAmount = (parseFloat(estimatedOutput) * 0.99).toString();
|
|
1440
|
+
setStatusMessage("Preparing swap and deposit...");
|
|
1441
|
+
const bundleActions = [
|
|
1442
|
+
{
|
|
1443
|
+
body: {
|
|
1444
|
+
actionType: "V2_SWAP",
|
|
1445
|
+
tokenIn: selectedToken,
|
|
1446
|
+
tokenOut: venueToken,
|
|
1447
|
+
amountIn: amount,
|
|
1448
|
+
maxSlippagePercent: 1
|
|
1449
|
+
}
|
|
1450
|
+
},
|
|
1451
|
+
{
|
|
1452
|
+
body: {
|
|
1453
|
+
actionType: "V2_MANAGE",
|
|
1454
|
+
action: "DEPOSIT",
|
|
1455
|
+
venue: venueType === "VAULT" ? { type: "VAULT", vaultAddress: venueAddress } : venueType === "AAVE" ? { type: "AAVE", token: venueToken } : { type: "PENDLE_PT", marketAddress: venueAddress },
|
|
1456
|
+
amount: depositAmount
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
];
|
|
1460
|
+
const prepareResponse = await fetch("/api/compass/bundle/prepare", {
|
|
1461
|
+
method: "POST",
|
|
1462
|
+
headers: { "Content-Type": "application/json" },
|
|
1463
|
+
body: JSON.stringify({
|
|
1464
|
+
owner: address,
|
|
1465
|
+
chain: chainId,
|
|
1466
|
+
actions: bundleActions
|
|
1467
|
+
})
|
|
1468
|
+
});
|
|
1469
|
+
if (!prepareResponse.ok) {
|
|
1470
|
+
const errorData = await prepareResponse.json();
|
|
1471
|
+
throw new Error(errorData.error || "Failed to prepare bundle");
|
|
1472
|
+
}
|
|
1473
|
+
const { eip712, normalizedTypes, domain, message } = await prepareResponse.json();
|
|
1474
|
+
setStatusMessage("Please sign the transaction...");
|
|
1475
|
+
const signature = await signTypedData({
|
|
1476
|
+
domain,
|
|
1477
|
+
types: normalizedTypes,
|
|
1478
|
+
primaryType: "SafeTx",
|
|
1479
|
+
message
|
|
1480
|
+
});
|
|
1481
|
+
setStatusMessage("Executing swap and deposit...");
|
|
1482
|
+
const executeResponse = await fetch("/api/compass/bundle/execute", {
|
|
1483
|
+
method: "POST",
|
|
1484
|
+
headers: { "Content-Type": "application/json" },
|
|
1485
|
+
body: JSON.stringify({
|
|
1486
|
+
owner: address,
|
|
1487
|
+
eip712,
|
|
1488
|
+
signature,
|
|
1489
|
+
chain: chainId
|
|
1490
|
+
})
|
|
1491
|
+
});
|
|
1492
|
+
if (!executeResponse.ok) {
|
|
1493
|
+
const errorData = await executeResponse.json();
|
|
1494
|
+
throw new Error(errorData.error || "Failed to execute bundle");
|
|
1495
|
+
}
|
|
1496
|
+
const { txHash } = await executeResponse.json();
|
|
1497
|
+
setStatusMessage("Transaction successful!");
|
|
1498
|
+
onSuccess?.(activeTab, amount, txHash);
|
|
1499
|
+
setAmount("");
|
|
1500
|
+
} else {
|
|
1501
|
+
const prepareEndpoint = isDeposit ? "/api/compass/deposit/prepare" : "/api/compass/withdraw/prepare";
|
|
1502
|
+
const executeEndpoint = isDeposit ? "/api/compass/deposit/execute" : "/api/compass/withdraw/execute";
|
|
1503
|
+
const prepareBody = {
|
|
1504
|
+
amount,
|
|
1505
|
+
token: venueToken,
|
|
1385
1506
|
owner: address,
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1507
|
+
chain: chainId,
|
|
1508
|
+
venueType
|
|
1509
|
+
};
|
|
1510
|
+
if (venueType === "VAULT") {
|
|
1511
|
+
prepareBody.vaultAddress = venueAddress;
|
|
1512
|
+
} else if (venueType === "PENDLE_PT") {
|
|
1513
|
+
prepareBody.marketAddress = venueAddress;
|
|
1514
|
+
prepareBody.maxSlippagePercent = 1;
|
|
1515
|
+
}
|
|
1516
|
+
setStatusMessage("Getting transaction data...");
|
|
1517
|
+
const prepareResponse = await fetch(prepareEndpoint, {
|
|
1518
|
+
method: "POST",
|
|
1519
|
+
headers: { "Content-Type": "application/json" },
|
|
1520
|
+
body: JSON.stringify(prepareBody)
|
|
1521
|
+
});
|
|
1522
|
+
if (!prepareResponse.ok) {
|
|
1523
|
+
const errorData = await prepareResponse.json();
|
|
1524
|
+
throw new Error(errorData.error || "Failed to prepare transaction");
|
|
1525
|
+
}
|
|
1526
|
+
const { eip712, normalizedTypes, domain, message } = await prepareResponse.json();
|
|
1527
|
+
setStatusMessage("Please sign the transaction...");
|
|
1528
|
+
const signature = await signTypedData({
|
|
1529
|
+
domain,
|
|
1530
|
+
types: normalizedTypes,
|
|
1531
|
+
primaryType: "SafeTx",
|
|
1532
|
+
message
|
|
1533
|
+
});
|
|
1534
|
+
setStatusMessage("Executing transaction...");
|
|
1535
|
+
const executeResponse = await fetch(executeEndpoint, {
|
|
1536
|
+
method: "POST",
|
|
1537
|
+
headers: { "Content-Type": "application/json" },
|
|
1538
|
+
body: JSON.stringify({
|
|
1539
|
+
owner: address,
|
|
1540
|
+
eip712,
|
|
1541
|
+
signature,
|
|
1542
|
+
chain: chainId
|
|
1543
|
+
})
|
|
1544
|
+
});
|
|
1545
|
+
if (!executeResponse.ok) {
|
|
1546
|
+
const errorData = await executeResponse.json();
|
|
1547
|
+
throw new Error(errorData.error || "Failed to execute transaction");
|
|
1548
|
+
}
|
|
1549
|
+
const { txHash } = await executeResponse.json();
|
|
1550
|
+
setStatusMessage("Transaction successful!");
|
|
1551
|
+
onSuccess?.(activeTab, amount, txHash);
|
|
1552
|
+
setAmount("");
|
|
1394
1553
|
}
|
|
1395
|
-
const { txHash } = await executeResponse.json();
|
|
1396
|
-
setStatusMessage("Transaction successful!");
|
|
1397
|
-
onSuccess?.(activeTab, amount, txHash);
|
|
1398
|
-
setAmount("");
|
|
1399
1554
|
queryClient.invalidateQueries({ queryKey: ["earnAccountTokenBalance"] });
|
|
1400
1555
|
queryClient.invalidateQueries({ queryKey: ["vaults"] });
|
|
1401
|
-
queryClient.invalidateQueries({ queryKey: ["vaultPositions"] });
|
|
1402
1556
|
queryClient.invalidateQueries({ queryKey: ["aaveMarkets"] });
|
|
1403
|
-
queryClient.invalidateQueries({ queryKey: ["aavePositions"] });
|
|
1404
1557
|
queryClient.invalidateQueries({ queryKey: ["pendleMarkets"] });
|
|
1405
|
-
queryClient.invalidateQueries({ queryKey: ["pendlePositions"] });
|
|
1406
1558
|
setTimeout(() => setStatusMessage(""), 3e3);
|
|
1407
|
-
setTimeout(() => {
|
|
1408
|
-
queryClient.invalidateQueries({ queryKey: ["earnAccountTokenBalance"] });
|
|
1409
|
-
queryClient.invalidateQueries({ queryKey: ["vaults"] });
|
|
1410
|
-
queryClient.invalidateQueries({ queryKey: ["vaultPositions"] });
|
|
1411
|
-
}, 5e3);
|
|
1412
1559
|
} catch (err) {
|
|
1413
1560
|
console.error("Transaction failed:", err);
|
|
1414
1561
|
const errorMessage = err instanceof Error ? err.message : "Transaction failed";
|
|
@@ -1421,13 +1568,13 @@ function DepositWithdrawForm({
|
|
|
1421
1568
|
address,
|
|
1422
1569
|
amount,
|
|
1423
1570
|
chainId,
|
|
1424
|
-
targetChainId,
|
|
1425
1571
|
activeTab,
|
|
1572
|
+
needsSwap,
|
|
1573
|
+
selectedToken,
|
|
1574
|
+
venueToken,
|
|
1426
1575
|
venueType,
|
|
1427
1576
|
venueAddress,
|
|
1428
|
-
tokenSymbol,
|
|
1429
1577
|
signTypedData,
|
|
1430
|
-
switchChain,
|
|
1431
1578
|
queryClient,
|
|
1432
1579
|
onSuccess,
|
|
1433
1580
|
onError
|
|
@@ -1466,6 +1613,7 @@ function DepositWithdrawForm({
|
|
|
1466
1613
|
{
|
|
1467
1614
|
onClick: () => {
|
|
1468
1615
|
setActiveTab(tab);
|
|
1616
|
+
setSelectedToken(venueToken);
|
|
1469
1617
|
setError(null);
|
|
1470
1618
|
setStatusMessage("");
|
|
1471
1619
|
},
|
|
@@ -1480,6 +1628,45 @@ function DepositWithdrawForm({
|
|
|
1480
1628
|
))
|
|
1481
1629
|
}
|
|
1482
1630
|
),
|
|
1631
|
+
activeTab === "deposit" && /* @__PURE__ */ jsxs("div", { children: [
|
|
1632
|
+
/* @__PURE__ */ jsx(
|
|
1633
|
+
"label",
|
|
1634
|
+
{
|
|
1635
|
+
className: "text-sm font-medium mb-1 block",
|
|
1636
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
1637
|
+
children: "From Token"
|
|
1638
|
+
}
|
|
1639
|
+
),
|
|
1640
|
+
/* @__PURE__ */ jsx(
|
|
1641
|
+
TokenSelector,
|
|
1642
|
+
{
|
|
1643
|
+
tokens: depositTokens,
|
|
1644
|
+
selectedToken,
|
|
1645
|
+
onSelect: setSelectedToken,
|
|
1646
|
+
disabled: isSubmitting
|
|
1647
|
+
}
|
|
1648
|
+
)
|
|
1649
|
+
] }),
|
|
1650
|
+
needsSwap && /* @__PURE__ */ jsxs(
|
|
1651
|
+
"div",
|
|
1652
|
+
{
|
|
1653
|
+
className: "flex items-center gap-2 p-2 rounded-lg text-sm",
|
|
1654
|
+
style: {
|
|
1655
|
+
backgroundColor: "var(--compass-color-primary-muted)",
|
|
1656
|
+
color: "var(--compass-color-primary)"
|
|
1657
|
+
},
|
|
1658
|
+
children: [
|
|
1659
|
+
/* @__PURE__ */ jsx(ArrowRight, { size: 14 }),
|
|
1660
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1661
|
+
"Swaps ",
|
|
1662
|
+
selectedToken,
|
|
1663
|
+
" to ",
|
|
1664
|
+
venueToken,
|
|
1665
|
+
", then deposits"
|
|
1666
|
+
] })
|
|
1667
|
+
]
|
|
1668
|
+
}
|
|
1669
|
+
),
|
|
1483
1670
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
1484
1671
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-1", children: [
|
|
1485
1672
|
/* @__PURE__ */ jsx(
|
|
@@ -1492,9 +1679,9 @@ function DepositWithdrawForm({
|
|
|
1492
1679
|
),
|
|
1493
1680
|
/* @__PURE__ */ jsxs("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: [
|
|
1494
1681
|
"Available: ",
|
|
1495
|
-
|
|
1682
|
+
formatAmount(maxBalance),
|
|
1496
1683
|
" ",
|
|
1497
|
-
|
|
1684
|
+
activeTab === "deposit" ? selectedToken : venueToken
|
|
1498
1685
|
] })
|
|
1499
1686
|
] }),
|
|
1500
1687
|
/* @__PURE__ */ jsxs(
|
|
@@ -1525,7 +1712,7 @@ function DepositWithdrawForm({
|
|
|
1525
1712
|
{
|
|
1526
1713
|
className: "text-sm font-medium",
|
|
1527
1714
|
style: { color: "var(--compass-color-text-secondary)" },
|
|
1528
|
-
children:
|
|
1715
|
+
children: activeTab === "deposit" ? selectedToken : venueToken
|
|
1529
1716
|
}
|
|
1530
1717
|
)
|
|
1531
1718
|
]
|
|
@@ -1550,8 +1737,8 @@ function DepositWithdrawForm({
|
|
|
1550
1737
|
{
|
|
1551
1738
|
className: "p-3 rounded-lg text-sm",
|
|
1552
1739
|
style: {
|
|
1553
|
-
backgroundColor: "var(--compass-color-error-muted
|
|
1554
|
-
color: "var(--compass-color-error
|
|
1740
|
+
backgroundColor: "var(--compass-color-error-muted)",
|
|
1741
|
+
color: "var(--compass-color-error)"
|
|
1555
1742
|
},
|
|
1556
1743
|
children: error
|
|
1557
1744
|
}
|
|
@@ -1561,8 +1748,8 @@ function DepositWithdrawForm({
|
|
|
1561
1748
|
{
|
|
1562
1749
|
className: "p-3 rounded-lg text-sm text-center",
|
|
1563
1750
|
style: {
|
|
1564
|
-
backgroundColor: "var(--compass-color-success-muted
|
|
1565
|
-
color: "var(--compass-color-success
|
|
1751
|
+
backgroundColor: "var(--compass-color-success-muted)",
|
|
1752
|
+
color: "var(--compass-color-success)"
|
|
1566
1753
|
},
|
|
1567
1754
|
children: statusMessage
|
|
1568
1755
|
}
|
|
@@ -1579,7 +1766,7 @@ function DepositWithdrawForm({
|
|
|
1579
1766
|
},
|
|
1580
1767
|
children: [
|
|
1581
1768
|
isSubmitting && /* @__PURE__ */ jsx(Loader2, { size: 18, className: "animate-spin" }),
|
|
1582
|
-
isSubmitting ? "Processing..." : activeTab === "deposit" ? "Deposit" : "Withdraw"
|
|
1769
|
+
isSubmitting ? "Processing..." : needsSwap ? `Swap & ${activeTab === "deposit" ? "Deposit" : "Withdraw"}` : activeTab === "deposit" ? "Deposit" : "Withdraw"
|
|
1583
1770
|
]
|
|
1584
1771
|
}
|
|
1585
1772
|
)
|
|
@@ -1887,6 +2074,434 @@ function EarnAccountGuard({
|
|
|
1887
2074
|
}
|
|
1888
2075
|
);
|
|
1889
2076
|
}
|
|
2077
|
+
var DEFAULT_TOKENS = ["SBC", "AUSD", "USDC", "USDT", "WETH", "DAI"];
|
|
2078
|
+
var APPROVAL_CACHE_KEY = "compass_approved_tokens";
|
|
2079
|
+
function getApprovalCacheKey(chain, owner) {
|
|
2080
|
+
return `${APPROVAL_CACHE_KEY}_${chain}_${owner}`;
|
|
2081
|
+
}
|
|
2082
|
+
function getCachedApprovals(chain, owner) {
|
|
2083
|
+
try {
|
|
2084
|
+
const key = getApprovalCacheKey(chain, owner);
|
|
2085
|
+
const cached = localStorage.getItem(key);
|
|
2086
|
+
return cached ? new Set(JSON.parse(cached)) : /* @__PURE__ */ new Set();
|
|
2087
|
+
} catch {
|
|
2088
|
+
return /* @__PURE__ */ new Set();
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
function cacheApproval(chain, owner, token) {
|
|
2092
|
+
try {
|
|
2093
|
+
const key = getApprovalCacheKey(chain, owner);
|
|
2094
|
+
const approvals = getCachedApprovals(chain, owner);
|
|
2095
|
+
approvals.add(token);
|
|
2096
|
+
localStorage.setItem(key, JSON.stringify([...approvals]));
|
|
2097
|
+
} catch {
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
function EarnAccountBalance({
|
|
2101
|
+
tokens = DEFAULT_TOKENS,
|
|
2102
|
+
compact = false,
|
|
2103
|
+
onTransferComplete
|
|
2104
|
+
}) {
|
|
2105
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
2106
|
+
const [activeAction, setActiveAction] = useState("deposit");
|
|
2107
|
+
const [selectedToken, setSelectedToken] = useState(tokens[0]);
|
|
2108
|
+
const [amount, setAmount] = useState("");
|
|
2109
|
+
const [transferState, setTransferState] = useState("idle");
|
|
2110
|
+
const [statusMessage, setStatusMessage] = useState("");
|
|
2111
|
+
const [error, setError] = useState(null);
|
|
2112
|
+
const { address, isConnected, signTypedData } = useEmbeddableWallet();
|
|
2113
|
+
const { chainId } = useChain();
|
|
2114
|
+
const { earnAccountAddress, isDeployed } = useEarnAccount();
|
|
2115
|
+
const queryClient = useQueryClient();
|
|
2116
|
+
const { data: balanceData, isLoading: balancesLoading } = useQuery({
|
|
2117
|
+
queryKey: ["earnAccountBalances", chainId, address, tokens.join(",")],
|
|
2118
|
+
queryFn: async () => {
|
|
2119
|
+
if (!address) return null;
|
|
2120
|
+
const response = await fetch(
|
|
2121
|
+
`/api/compass/earn-account/balances?owner=${address}&chain=${chainId}&tokens=${tokens.join(",")}`
|
|
2122
|
+
);
|
|
2123
|
+
if (!response.ok) {
|
|
2124
|
+
throw new Error("Failed to fetch balances");
|
|
2125
|
+
}
|
|
2126
|
+
return response.json();
|
|
2127
|
+
},
|
|
2128
|
+
enabled: !!address && isDeployed,
|
|
2129
|
+
staleTime: 30 * 1e3
|
|
2130
|
+
});
|
|
2131
|
+
const { data: eoaBalances } = useQuery({
|
|
2132
|
+
queryKey: ["eoaBalances", chainId, address, tokens.join(",")],
|
|
2133
|
+
queryFn: async () => {
|
|
2134
|
+
if (!address) return {};
|
|
2135
|
+
const balances = {};
|
|
2136
|
+
return balances;
|
|
2137
|
+
},
|
|
2138
|
+
enabled: !!address && activeAction === "deposit",
|
|
2139
|
+
staleTime: 30 * 1e3
|
|
2140
|
+
});
|
|
2141
|
+
const earnBalances = balanceData?.balances || {};
|
|
2142
|
+
Object.values(earnBalances).reduce((sum, bal) => {
|
|
2143
|
+
return sum + parseFloat(bal || "0");
|
|
2144
|
+
}, 0);
|
|
2145
|
+
const resetForm = useCallback(() => {
|
|
2146
|
+
setAmount("");
|
|
2147
|
+
setTransferState("idle");
|
|
2148
|
+
setStatusMessage("");
|
|
2149
|
+
setError(null);
|
|
2150
|
+
}, []);
|
|
2151
|
+
const handleOpenModal = () => {
|
|
2152
|
+
resetForm();
|
|
2153
|
+
setIsModalOpen(true);
|
|
2154
|
+
};
|
|
2155
|
+
const handleCloseModal = () => {
|
|
2156
|
+
setIsModalOpen(false);
|
|
2157
|
+
resetForm();
|
|
2158
|
+
};
|
|
2159
|
+
const handleActionChange = (action) => {
|
|
2160
|
+
setActiveAction(action);
|
|
2161
|
+
setAmount("");
|
|
2162
|
+
setError(null);
|
|
2163
|
+
};
|
|
2164
|
+
const getMaxBalance = () => {
|
|
2165
|
+
if (activeAction === "deposit") {
|
|
2166
|
+
return eoaBalances?.[selectedToken] || "0";
|
|
2167
|
+
}
|
|
2168
|
+
return earnBalances[selectedToken] || "0";
|
|
2169
|
+
};
|
|
2170
|
+
const handleQuickAmount = (percentage) => {
|
|
2171
|
+
const max = parseFloat(getMaxBalance());
|
|
2172
|
+
if (isNaN(max)) return;
|
|
2173
|
+
setAmount(formatAmount(max * percentage));
|
|
2174
|
+
};
|
|
2175
|
+
const handleTransfer = useCallback(async () => {
|
|
2176
|
+
if (!address || !amount || !signTypedData) return;
|
|
2177
|
+
setError(null);
|
|
2178
|
+
try {
|
|
2179
|
+
if (activeAction === "deposit") {
|
|
2180
|
+
const cachedApprovals = getCachedApprovals(chainId, address);
|
|
2181
|
+
if (!cachedApprovals.has(selectedToken)) {
|
|
2182
|
+
setTransferState("checking_approval");
|
|
2183
|
+
setStatusMessage("Checking token approval...");
|
|
2184
|
+
const approveResponse = await fetch("/api/compass/transfer/approve", {
|
|
2185
|
+
method: "POST",
|
|
2186
|
+
headers: { "Content-Type": "application/json" },
|
|
2187
|
+
body: JSON.stringify({
|
|
2188
|
+
owner: address,
|
|
2189
|
+
chain: chainId,
|
|
2190
|
+
token: selectedToken
|
|
2191
|
+
})
|
|
2192
|
+
});
|
|
2193
|
+
if (!approveResponse.ok) {
|
|
2194
|
+
const errData = await approveResponse.json();
|
|
2195
|
+
throw new Error(errData.error || "Failed to check approval");
|
|
2196
|
+
}
|
|
2197
|
+
const approvalData = await approveResponse.json();
|
|
2198
|
+
if (!approvalData.approved) {
|
|
2199
|
+
if (approvalData.requiresTransaction) {
|
|
2200
|
+
throw new Error("This token requires a transaction-based approval. Please approve manually.");
|
|
2201
|
+
}
|
|
2202
|
+
setTransferState("awaiting_approval_signature");
|
|
2203
|
+
setStatusMessage("Please sign the approval...");
|
|
2204
|
+
const approvalSignature = await signTypedData({
|
|
2205
|
+
domain: approvalData.domain,
|
|
2206
|
+
types: approvalData.normalizedTypes,
|
|
2207
|
+
primaryType: "Permit",
|
|
2208
|
+
message: approvalData.message
|
|
2209
|
+
});
|
|
2210
|
+
setTransferState("approving");
|
|
2211
|
+
setStatusMessage("Executing approval...");
|
|
2212
|
+
const executeApprovalResponse = await fetch("/api/compass/transfer/execute", {
|
|
2213
|
+
method: "POST",
|
|
2214
|
+
headers: { "Content-Type": "application/json" },
|
|
2215
|
+
body: JSON.stringify({
|
|
2216
|
+
owner: address,
|
|
2217
|
+
chain: chainId,
|
|
2218
|
+
eip712: approvalData.eip712,
|
|
2219
|
+
signature: approvalSignature
|
|
2220
|
+
})
|
|
2221
|
+
});
|
|
2222
|
+
if (!executeApprovalResponse.ok) {
|
|
2223
|
+
const errData = await executeApprovalResponse.json();
|
|
2224
|
+
throw new Error(errData.error || "Approval failed");
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
cacheApproval(chainId, address, selectedToken);
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
setTransferState("awaiting_transfer_signature");
|
|
2231
|
+
setStatusMessage("Preparing transfer...");
|
|
2232
|
+
const prepareResponse = await fetch("/api/compass/transfer/prepare", {
|
|
2233
|
+
method: "POST",
|
|
2234
|
+
headers: { "Content-Type": "application/json" },
|
|
2235
|
+
body: JSON.stringify({
|
|
2236
|
+
owner: address,
|
|
2237
|
+
chain: chainId,
|
|
2238
|
+
token: selectedToken,
|
|
2239
|
+
amount,
|
|
2240
|
+
action: activeAction.toUpperCase()
|
|
2241
|
+
})
|
|
2242
|
+
});
|
|
2243
|
+
if (!prepareResponse.ok) {
|
|
2244
|
+
const errData = await prepareResponse.json();
|
|
2245
|
+
throw new Error(errData.error || "Failed to prepare transfer");
|
|
2246
|
+
}
|
|
2247
|
+
const prepareData = await prepareResponse.json();
|
|
2248
|
+
setStatusMessage("Please sign the transfer...");
|
|
2249
|
+
const transferSignature = await signTypedData({
|
|
2250
|
+
domain: prepareData.domain,
|
|
2251
|
+
types: prepareData.normalizedTypes,
|
|
2252
|
+
primaryType: prepareData.primaryType,
|
|
2253
|
+
message: prepareData.message
|
|
2254
|
+
});
|
|
2255
|
+
setTransferState("transferring");
|
|
2256
|
+
setStatusMessage("Executing transfer...");
|
|
2257
|
+
const executeResponse = await fetch("/api/compass/transfer/execute", {
|
|
2258
|
+
method: "POST",
|
|
2259
|
+
headers: { "Content-Type": "application/json" },
|
|
2260
|
+
body: JSON.stringify({
|
|
2261
|
+
owner: address,
|
|
2262
|
+
chain: chainId,
|
|
2263
|
+
eip712: prepareData.eip712,
|
|
2264
|
+
signature: transferSignature
|
|
2265
|
+
})
|
|
2266
|
+
});
|
|
2267
|
+
if (!executeResponse.ok) {
|
|
2268
|
+
const errData = await executeResponse.json();
|
|
2269
|
+
throw new Error(errData.error || "Transfer failed");
|
|
2270
|
+
}
|
|
2271
|
+
const { txHash } = await executeResponse.json();
|
|
2272
|
+
setTransferState("success");
|
|
2273
|
+
setStatusMessage("Transfer successful!");
|
|
2274
|
+
onTransferComplete?.(activeAction, selectedToken, amount, txHash);
|
|
2275
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
2276
|
+
queryClient.invalidateQueries({ queryKey: ["eoaBalances"] });
|
|
2277
|
+
setTimeout(() => {
|
|
2278
|
+
resetForm();
|
|
2279
|
+
}, 2e3);
|
|
2280
|
+
} catch (err) {
|
|
2281
|
+
console.error("Transfer failed:", err);
|
|
2282
|
+
setTransferState("error");
|
|
2283
|
+
setError(err instanceof Error ? err.message : "Transfer failed");
|
|
2284
|
+
}
|
|
2285
|
+
}, [
|
|
2286
|
+
address,
|
|
2287
|
+
amount,
|
|
2288
|
+
activeAction,
|
|
2289
|
+
selectedToken,
|
|
2290
|
+
chainId,
|
|
2291
|
+
signTypedData,
|
|
2292
|
+
queryClient,
|
|
2293
|
+
onTransferComplete,
|
|
2294
|
+
resetForm
|
|
2295
|
+
]);
|
|
2296
|
+
if (!isConnected) {
|
|
2297
|
+
return null;
|
|
2298
|
+
}
|
|
2299
|
+
const isProcessing = transferState !== "idle" && transferState !== "success" && transferState !== "error";
|
|
2300
|
+
if (!isDeployed) {
|
|
2301
|
+
return /* @__PURE__ */ jsxs(
|
|
2302
|
+
"div",
|
|
2303
|
+
{
|
|
2304
|
+
className: `flex items-center gap-2 rounded-lg border ${compact ? "px-2 py-1.5" : "px-3 py-2"}`,
|
|
2305
|
+
style: {
|
|
2306
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
2307
|
+
borderColor: "var(--compass-color-border)"
|
|
2308
|
+
},
|
|
2309
|
+
children: [
|
|
2310
|
+
/* @__PURE__ */ jsx(Wallet, { size: compact ? 14 : 16, style: { color: "var(--compass-color-text-secondary)" } }),
|
|
2311
|
+
/* @__PURE__ */ jsx(
|
|
2312
|
+
"span",
|
|
2313
|
+
{
|
|
2314
|
+
className: `${compact ? "text-xs" : "text-sm"}`,
|
|
2315
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2316
|
+
children: "No Earn Account"
|
|
2317
|
+
}
|
|
2318
|
+
)
|
|
2319
|
+
]
|
|
2320
|
+
}
|
|
2321
|
+
);
|
|
2322
|
+
}
|
|
2323
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2324
|
+
/* @__PURE__ */ jsx(
|
|
2325
|
+
"button",
|
|
2326
|
+
{
|
|
2327
|
+
onClick: handleOpenModal,
|
|
2328
|
+
className: `rounded-md font-medium transition-colors ${compact ? "px-2 py-1 text-xs" : "px-3 py-1.5 text-sm"}`,
|
|
2329
|
+
style: {
|
|
2330
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
2331
|
+
color: "var(--compass-color-primary-text)"
|
|
2332
|
+
},
|
|
2333
|
+
children: "Transfer"
|
|
2334
|
+
}
|
|
2335
|
+
),
|
|
2336
|
+
/* @__PURE__ */ jsx(
|
|
2337
|
+
ActionModal,
|
|
2338
|
+
{
|
|
2339
|
+
isOpen: isModalOpen,
|
|
2340
|
+
onClose: handleCloseModal,
|
|
2341
|
+
title: "Transfer Funds",
|
|
2342
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2343
|
+
/* @__PURE__ */ jsx(
|
|
2344
|
+
"div",
|
|
2345
|
+
{
|
|
2346
|
+
className: "flex gap-1 p-1 rounded-lg",
|
|
2347
|
+
style: { backgroundColor: "var(--compass-color-background)" },
|
|
2348
|
+
children: ["deposit", "withdraw"].map((action) => /* @__PURE__ */ jsxs(
|
|
2349
|
+
"button",
|
|
2350
|
+
{
|
|
2351
|
+
onClick: () => handleActionChange(action),
|
|
2352
|
+
disabled: isProcessing,
|
|
2353
|
+
className: "flex-1 py-2 rounded-md text-sm font-medium capitalize transition-all flex items-center justify-center gap-2",
|
|
2354
|
+
style: {
|
|
2355
|
+
backgroundColor: activeAction === action ? "var(--compass-color-surface)" : "transparent",
|
|
2356
|
+
color: activeAction === action ? "var(--compass-color-text)" : "var(--compass-color-text-secondary)"
|
|
2357
|
+
},
|
|
2358
|
+
children: [
|
|
2359
|
+
action === "deposit" ? /* @__PURE__ */ jsx(ArrowDownLeft, { size: 14 }) : /* @__PURE__ */ jsx(ArrowUpRight, { size: 14 }),
|
|
2360
|
+
action
|
|
2361
|
+
]
|
|
2362
|
+
},
|
|
2363
|
+
action
|
|
2364
|
+
))
|
|
2365
|
+
}
|
|
2366
|
+
),
|
|
2367
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2368
|
+
/* @__PURE__ */ jsx(
|
|
2369
|
+
"label",
|
|
2370
|
+
{
|
|
2371
|
+
className: "text-sm font-medium mb-1 block",
|
|
2372
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2373
|
+
children: "Token"
|
|
2374
|
+
}
|
|
2375
|
+
),
|
|
2376
|
+
/* @__PURE__ */ jsx(
|
|
2377
|
+
TokenSelector,
|
|
2378
|
+
{
|
|
2379
|
+
tokens,
|
|
2380
|
+
selectedToken,
|
|
2381
|
+
onSelect: setSelectedToken,
|
|
2382
|
+
balances: activeAction === "deposit" ? eoaBalances : earnBalances,
|
|
2383
|
+
disabled: isProcessing
|
|
2384
|
+
}
|
|
2385
|
+
)
|
|
2386
|
+
] }),
|
|
2387
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2388
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-1", children: [
|
|
2389
|
+
/* @__PURE__ */ jsx(
|
|
2390
|
+
"label",
|
|
2391
|
+
{
|
|
2392
|
+
className: "text-sm font-medium",
|
|
2393
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2394
|
+
children: "Amount"
|
|
2395
|
+
}
|
|
2396
|
+
),
|
|
2397
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: [
|
|
2398
|
+
"Available: ",
|
|
2399
|
+
formatAmount(getMaxBalance()),
|
|
2400
|
+
" ",
|
|
2401
|
+
selectedToken
|
|
2402
|
+
] })
|
|
2403
|
+
] }),
|
|
2404
|
+
/* @__PURE__ */ jsxs(
|
|
2405
|
+
"div",
|
|
2406
|
+
{
|
|
2407
|
+
className: "flex items-center gap-2 p-3 rounded-lg border",
|
|
2408
|
+
style: {
|
|
2409
|
+
backgroundColor: "var(--compass-color-background)",
|
|
2410
|
+
borderColor: "var(--compass-color-border)"
|
|
2411
|
+
},
|
|
2412
|
+
children: [
|
|
2413
|
+
/* @__PURE__ */ jsx(
|
|
2414
|
+
"input",
|
|
2415
|
+
{
|
|
2416
|
+
type: "number",
|
|
2417
|
+
value: amount,
|
|
2418
|
+
onChange: (e) => {
|
|
2419
|
+
setAmount(e.target.value);
|
|
2420
|
+
setError(null);
|
|
2421
|
+
},
|
|
2422
|
+
placeholder: "0.00",
|
|
2423
|
+
disabled: isProcessing,
|
|
2424
|
+
className: "flex-1 bg-transparent outline-none text-lg font-mono",
|
|
2425
|
+
style: { color: "var(--compass-color-text)" }
|
|
2426
|
+
}
|
|
2427
|
+
),
|
|
2428
|
+
/* @__PURE__ */ jsx(
|
|
2429
|
+
"span",
|
|
2430
|
+
{
|
|
2431
|
+
className: "text-sm font-medium",
|
|
2432
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2433
|
+
children: selectedToken
|
|
2434
|
+
}
|
|
2435
|
+
)
|
|
2436
|
+
]
|
|
2437
|
+
}
|
|
2438
|
+
)
|
|
2439
|
+
] }),
|
|
2440
|
+
/* @__PURE__ */ jsx("div", { className: "flex gap-2", children: [0.25, 0.5, 1].map((pct) => /* @__PURE__ */ jsx(
|
|
2441
|
+
"button",
|
|
2442
|
+
{
|
|
2443
|
+
onClick: () => handleQuickAmount(pct),
|
|
2444
|
+
disabled: isProcessing,
|
|
2445
|
+
className: "flex-1 py-1.5 rounded-md text-xs font-medium transition-colors",
|
|
2446
|
+
style: {
|
|
2447
|
+
backgroundColor: "var(--compass-color-secondary)",
|
|
2448
|
+
color: "var(--compass-color-text-secondary)"
|
|
2449
|
+
},
|
|
2450
|
+
children: pct === 1 ? "Max" : `${pct * 100}%`
|
|
2451
|
+
},
|
|
2452
|
+
pct
|
|
2453
|
+
)) }),
|
|
2454
|
+
error && /* @__PURE__ */ jsx(
|
|
2455
|
+
"div",
|
|
2456
|
+
{
|
|
2457
|
+
className: "p-3 rounded-lg text-sm",
|
|
2458
|
+
style: {
|
|
2459
|
+
backgroundColor: "var(--compass-color-error-muted)",
|
|
2460
|
+
color: "var(--compass-color-error)"
|
|
2461
|
+
},
|
|
2462
|
+
children: error
|
|
2463
|
+
}
|
|
2464
|
+
),
|
|
2465
|
+
statusMessage && !error && /* @__PURE__ */ jsx(
|
|
2466
|
+
"div",
|
|
2467
|
+
{
|
|
2468
|
+
className: "p-3 rounded-lg text-sm text-center",
|
|
2469
|
+
style: {
|
|
2470
|
+
backgroundColor: transferState === "success" ? "var(--compass-color-success-muted)" : "var(--compass-color-primary-muted)",
|
|
2471
|
+
color: transferState === "success" ? "var(--compass-color-success)" : "var(--compass-color-primary)"
|
|
2472
|
+
},
|
|
2473
|
+
children: statusMessage
|
|
2474
|
+
}
|
|
2475
|
+
),
|
|
2476
|
+
/* @__PURE__ */ jsxs(
|
|
2477
|
+
"button",
|
|
2478
|
+
{
|
|
2479
|
+
onClick: handleTransfer,
|
|
2480
|
+
disabled: isProcessing || !amount || parseFloat(amount) <= 0,
|
|
2481
|
+
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",
|
|
2482
|
+
style: {
|
|
2483
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
2484
|
+
color: "var(--compass-color-primary-text)"
|
|
2485
|
+
},
|
|
2486
|
+
children: [
|
|
2487
|
+
isProcessing && /* @__PURE__ */ jsx(Loader2, { size: 18, className: "animate-spin" }),
|
|
2488
|
+
isProcessing ? "Processing..." : activeAction === "deposit" ? "Deposit to Earn Account" : "Withdraw to Wallet"
|
|
2489
|
+
]
|
|
2490
|
+
}
|
|
2491
|
+
),
|
|
2492
|
+
/* @__PURE__ */ jsx(
|
|
2493
|
+
"p",
|
|
2494
|
+
{
|
|
2495
|
+
className: "text-xs text-center",
|
|
2496
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
2497
|
+
children: "Gas fees are sponsored by Compass"
|
|
2498
|
+
}
|
|
2499
|
+
)
|
|
2500
|
+
] })
|
|
2501
|
+
}
|
|
2502
|
+
)
|
|
2503
|
+
] });
|
|
2504
|
+
}
|
|
1890
2505
|
function formatTVL(tvl) {
|
|
1891
2506
|
if (!tvl) return "$0";
|
|
1892
2507
|
const num = parseFloat(tvl);
|
|
@@ -2101,15 +2716,6 @@ function useVaultsData(options = {}) {
|
|
|
2101
2716
|
}
|
|
2102
2717
|
};
|
|
2103
2718
|
}
|
|
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
2719
|
function VaultsList({
|
|
2114
2720
|
showApy = true,
|
|
2115
2721
|
apyPeriods = ["7d", "30d", "90d"],
|
|
@@ -2119,7 +2725,6 @@ function VaultsList({
|
|
|
2119
2725
|
showHistory = true,
|
|
2120
2726
|
showSearch = true,
|
|
2121
2727
|
showSort = true,
|
|
2122
|
-
actionMode = "modal",
|
|
2123
2728
|
defaultSort = "apy_7d",
|
|
2124
2729
|
assetFilter,
|
|
2125
2730
|
minApy,
|
|
@@ -2157,7 +2762,10 @@ function VaultsList({
|
|
|
2157
2762
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2158
2763
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
|
|
2159
2764
|
/* @__PURE__ */ jsx(ChainSwitcher, {}),
|
|
2160
|
-
/* @__PURE__ */
|
|
2765
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2766
|
+
/* @__PURE__ */ jsx(EarnAccountBalance, { compact: true }),
|
|
2767
|
+
/* @__PURE__ */ jsx(WalletStatus, { compact: true })
|
|
2768
|
+
] })
|
|
2161
2769
|
] }),
|
|
2162
2770
|
(showSearch || showSort) && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
2163
2771
|
showSearch && /* @__PURE__ */ jsxs(
|
|
@@ -2233,7 +2841,7 @@ function VaultsList({
|
|
|
2233
2841
|
},
|
|
2234
2842
|
vault.vaultAddress
|
|
2235
2843
|
)) }),
|
|
2236
|
-
|
|
2844
|
+
selectedVault && /* @__PURE__ */ jsx(
|
|
2237
2845
|
ActionModal,
|
|
2238
2846
|
{
|
|
2239
2847
|
isOpen: !!selectedVault,
|
|
@@ -2261,8 +2869,7 @@ function VaultsList({
|
|
|
2261
2869
|
{
|
|
2262
2870
|
venueType: "VAULT",
|
|
2263
2871
|
venueAddress: selectedVault.vaultAddress,
|
|
2264
|
-
|
|
2265
|
-
tokenDecimals: TOKEN_DECIMALS2[selectedVault.assetSymbol] || 18,
|
|
2872
|
+
venueToken: selectedVault.assetSymbol,
|
|
2266
2873
|
positionBalance: selectedVault.userPosition?.balance,
|
|
2267
2874
|
onSuccess: handleActionSuccess
|
|
2268
2875
|
}
|
|
@@ -2362,15 +2969,6 @@ function useAaveData(options = {}) {
|
|
|
2362
2969
|
}
|
|
2363
2970
|
};
|
|
2364
2971
|
}
|
|
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
2972
|
function formatAPY2(apy) {
|
|
2375
2973
|
if (!apy) return "0.00%";
|
|
2376
2974
|
const num = parseFloat(apy);
|
|
@@ -2394,7 +2992,6 @@ function AaveMarketsList({
|
|
|
2394
2992
|
showSearch = true,
|
|
2395
2993
|
showSort = false,
|
|
2396
2994
|
// Only one sort option (APY), so hide by default
|
|
2397
|
-
actionMode = "modal",
|
|
2398
2995
|
defaultSort = "supply_apy",
|
|
2399
2996
|
assetFilter,
|
|
2400
2997
|
onMarketSelect,
|
|
@@ -2427,7 +3024,10 @@ function AaveMarketsList({
|
|
|
2427
3024
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2428
3025
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
|
|
2429
3026
|
/* @__PURE__ */ jsx(ChainSwitcher, {}),
|
|
2430
|
-
/* @__PURE__ */
|
|
3027
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3028
|
+
/* @__PURE__ */ jsx(EarnAccountBalance, { compact: true }),
|
|
3029
|
+
/* @__PURE__ */ jsx(WalletStatus, { compact: true })
|
|
3030
|
+
] })
|
|
2431
3031
|
] }),
|
|
2432
3032
|
(showSearch || showSort) && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
2433
3033
|
showSearch && /* @__PURE__ */ jsxs(
|
|
@@ -2579,7 +3179,7 @@ function AaveMarketsList({
|
|
|
2579
3179
|
market.marketAddress
|
|
2580
3180
|
);
|
|
2581
3181
|
}) }),
|
|
2582
|
-
|
|
3182
|
+
selectedMarket && /* @__PURE__ */ jsx(
|
|
2583
3183
|
ActionModal,
|
|
2584
3184
|
{
|
|
2585
3185
|
isOpen: !!selectedMarket,
|
|
@@ -2607,8 +3207,7 @@ function AaveMarketsList({
|
|
|
2607
3207
|
{
|
|
2608
3208
|
venueType: "AAVE",
|
|
2609
3209
|
venueAddress: selectedMarket.marketAddress,
|
|
2610
|
-
|
|
2611
|
-
tokenDecimals: TOKEN_DECIMALS3[selectedMarket.underlyingSymbol] || 18,
|
|
3210
|
+
venueToken: selectedMarket.underlyingSymbol,
|
|
2612
3211
|
positionBalance: selectedMarket.userPosition?.balance,
|
|
2613
3212
|
onSuccess: handleActionSuccess
|
|
2614
3213
|
}
|
|
@@ -2711,15 +3310,6 @@ function usePendleData(options = {}) {
|
|
|
2711
3310
|
}
|
|
2712
3311
|
};
|
|
2713
3312
|
}
|
|
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
3313
|
function formatAPY3(apy) {
|
|
2724
3314
|
if (!apy) return "0.00%";
|
|
2725
3315
|
return `${parseFloat(apy).toFixed(2)}%`;
|
|
@@ -2745,7 +3335,6 @@ function PendleMarketsList({
|
|
|
2745
3335
|
showHistory = true,
|
|
2746
3336
|
showSearch = true,
|
|
2747
3337
|
showSort = true,
|
|
2748
|
-
actionMode = "modal",
|
|
2749
3338
|
defaultSort = "fixed_apy",
|
|
2750
3339
|
assetFilter,
|
|
2751
3340
|
onMarketSelect,
|
|
@@ -2778,7 +3367,10 @@ function PendleMarketsList({
|
|
|
2778
3367
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2779
3368
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
|
|
2780
3369
|
/* @__PURE__ */ jsx(ChainSwitcher, {}),
|
|
2781
|
-
/* @__PURE__ */
|
|
3370
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3371
|
+
/* @__PURE__ */ jsx(EarnAccountBalance, { compact: true }),
|
|
3372
|
+
/* @__PURE__ */ jsx(WalletStatus, { compact: true })
|
|
3373
|
+
] })
|
|
2782
3374
|
] }),
|
|
2783
3375
|
(showSearch || showSort) && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
2784
3376
|
showSearch && /* @__PURE__ */ jsxs(
|
|
@@ -2956,7 +3548,7 @@ function PendleMarketsList({
|
|
|
2956
3548
|
market.marketAddress
|
|
2957
3549
|
);
|
|
2958
3550
|
}) }),
|
|
2959
|
-
|
|
3551
|
+
selectedMarket && /* @__PURE__ */ jsx(
|
|
2960
3552
|
ActionModal,
|
|
2961
3553
|
{
|
|
2962
3554
|
isOpen: !!selectedMarket,
|
|
@@ -2984,8 +3576,7 @@ function PendleMarketsList({
|
|
|
2984
3576
|
{
|
|
2985
3577
|
venueType: "PENDLE_PT",
|
|
2986
3578
|
venueAddress: selectedMarket.marketAddress,
|
|
2987
|
-
|
|
2988
|
-
tokenDecimals: TOKEN_DECIMALS4[selectedMarket.underlyingSymbol] || 18,
|
|
3579
|
+
venueToken: selectedMarket.underlyingSymbol,
|
|
2989
3580
|
positionBalance: selectedMarket.userPosition?.balance,
|
|
2990
3581
|
onSuccess: handleActionSuccess
|
|
2991
3582
|
}
|
|
@@ -3032,12 +3623,12 @@ function useSwapQuote({ fromToken, toToken, amount, enabled = true }) {
|
|
|
3032
3623
|
refetch: query.refetch
|
|
3033
3624
|
};
|
|
3034
3625
|
}
|
|
3035
|
-
var
|
|
3626
|
+
var DEFAULT_TOKENS2 = ["USDC", "ETH", "WETH", "WBTC", "DAI", "USDT"];
|
|
3036
3627
|
function SwapWidget({
|
|
3037
3628
|
layout = "full",
|
|
3038
3629
|
defaultFromToken = "ETH",
|
|
3039
3630
|
defaultToToken = "USDC",
|
|
3040
|
-
allowedTokens =
|
|
3631
|
+
allowedTokens = DEFAULT_TOKENS2,
|
|
3041
3632
|
showReverseButton = true,
|
|
3042
3633
|
showSettings = false,
|
|
3043
3634
|
showPriceImpact = true,
|
|
@@ -3293,7 +3884,27 @@ function CompassEarnWidget({
|
|
|
3293
3884
|
] })
|
|
3294
3885
|
] });
|
|
3295
3886
|
}
|
|
3887
|
+
var CHAINS = {
|
|
3888
|
+
ethereum: {
|
|
3889
|
+
id: "ethereum",
|
|
3890
|
+
name: "Ethereum",
|
|
3891
|
+
viemChain: mainnet,
|
|
3892
|
+
icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png"
|
|
3893
|
+
},
|
|
3894
|
+
base: {
|
|
3895
|
+
id: "base",
|
|
3896
|
+
name: "Base",
|
|
3897
|
+
viemChain: base,
|
|
3898
|
+
icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/base/info/logo.png"
|
|
3899
|
+
},
|
|
3900
|
+
arbitrum: {
|
|
3901
|
+
id: "arbitrum",
|
|
3902
|
+
name: "Arbitrum",
|
|
3903
|
+
viemChain: arbitrum,
|
|
3904
|
+
icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/arbitrum/info/logo.png"
|
|
3905
|
+
}
|
|
3906
|
+
};
|
|
3296
3907
|
|
|
3297
|
-
export { AaveMarketsList, ActionModal, ApiProvider, CHAINS, ChainSwitcher, CompassEarnWidget, CompassProvider, DepositWithdrawForm, EarnAccountGuard, PendleMarketsList, PnLSummary, SwapWidget,
|
|
3908
|
+
export { AaveMarketsList, 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
3909
|
//# sourceMappingURL=index.mjs.map
|
|
3299
3910
|
//# sourceMappingURL=index.mjs.map
|