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