@compass-labs/widgets 0.1.38 → 0.1.40
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 +50 -2
- package/dist/index.d.ts +50 -2
- package/dist/index.js +1668 -1134
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1670 -1136
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.js +6 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +6 -0
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ var apiSdk = require('@compass-labs/api-sdk');
|
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
7
|
var chains = require('viem/chains');
|
|
8
8
|
var lucideReact = require('lucide-react');
|
|
9
|
+
var viem = require('viem');
|
|
9
10
|
|
|
10
11
|
// src/provider/CompassProvider.tsx
|
|
11
12
|
var ApiContext = react.createContext(null);
|
|
@@ -92,7 +93,10 @@ var disconnectedWallet = {
|
|
|
92
93
|
},
|
|
93
94
|
switchChain: null,
|
|
94
95
|
login: null,
|
|
95
|
-
logout: null
|
|
96
|
+
logout: null,
|
|
97
|
+
fundWallet: null,
|
|
98
|
+
hasExternalWallet: true,
|
|
99
|
+
sendTransaction: null
|
|
96
100
|
};
|
|
97
101
|
function WalletProvider({ children, wallet }) {
|
|
98
102
|
const value = wallet ? {
|
|
@@ -102,7 +106,10 @@ function WalletProvider({ children, wallet }) {
|
|
|
102
106
|
signTypedData: wallet.signTypedData,
|
|
103
107
|
switchChain: wallet.switchChain ?? null,
|
|
104
108
|
login: wallet.login ?? null,
|
|
105
|
-
logout: wallet.logout ?? null
|
|
109
|
+
logout: wallet.logout ?? null,
|
|
110
|
+
fundWallet: wallet.fundWallet ?? null,
|
|
111
|
+
hasExternalWallet: wallet.hasExternalWallet ?? true,
|
|
112
|
+
sendTransaction: wallet.sendTransaction ?? null
|
|
106
113
|
} : disconnectedWallet;
|
|
107
114
|
return /* @__PURE__ */ jsxRuntime.jsx(WalletContext.Provider, { value, children });
|
|
108
115
|
}
|
|
@@ -1160,9 +1167,9 @@ function CopyableAddress({
|
|
|
1160
1167
|
title: copied ? "Copied!" : `Copy: ${address}`,
|
|
1161
1168
|
children: [
|
|
1162
1169
|
label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: label }),
|
|
1163
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-
|
|
1170
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
|
|
1164
1171
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-mono", style: { color: "var(--compass-color-text)" }, children: displayAddr }),
|
|
1165
|
-
copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size:
|
|
1172
|
+
copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 14, className: "flex-shrink-0", style: { color: "var(--compass-color-success)" } }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { size: 14, className: "flex-shrink-0", style: { color: "var(--compass-color-text-secondary)" } })
|
|
1166
1173
|
] })
|
|
1167
1174
|
]
|
|
1168
1175
|
}
|
|
@@ -1271,25 +1278,29 @@ function WalletStatus({
|
|
|
1271
1278
|
);
|
|
1272
1279
|
}
|
|
1273
1280
|
function ActionModal({ isOpen, onClose, title, children }) {
|
|
1281
|
+
const modalRef = react.useRef(null);
|
|
1274
1282
|
react.useEffect(() => {
|
|
1275
1283
|
const handleEscape = (e) => {
|
|
1276
1284
|
if (e.key === "Escape") onClose();
|
|
1277
1285
|
};
|
|
1278
1286
|
if (isOpen) {
|
|
1279
1287
|
document.addEventListener("keydown", handleEscape);
|
|
1280
|
-
document.body.style.overflow = "hidden";
|
|
1281
1288
|
}
|
|
1282
1289
|
return () => {
|
|
1283
1290
|
document.removeEventListener("keydown", handleEscape);
|
|
1284
|
-
document.body.style.overflow = "";
|
|
1285
1291
|
};
|
|
1286
1292
|
}, [isOpen, onClose]);
|
|
1293
|
+
const handleOverlayWheel = react.useCallback((e) => {
|
|
1294
|
+
if (modalRef.current && !modalRef.current.contains(e.target)) {
|
|
1295
|
+
window.scrollBy(0, e.deltaY);
|
|
1296
|
+
}
|
|
1297
|
+
}, []);
|
|
1287
1298
|
if (!isOpen) return null;
|
|
1288
1299
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1289
1300
|
"div",
|
|
1290
1301
|
{
|
|
1291
1302
|
className: "fixed inset-0 z-50 flex items-center justify-center p-4",
|
|
1292
|
-
|
|
1303
|
+
onWheel: handleOverlayWheel,
|
|
1293
1304
|
children: [
|
|
1294
1305
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1295
1306
|
"div",
|
|
@@ -1302,21 +1313,27 @@ function ActionModal({ isOpen, onClose, title, children }) {
|
|
|
1302
1313
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1303
1314
|
"div",
|
|
1304
1315
|
{
|
|
1316
|
+
ref: modalRef,
|
|
1305
1317
|
className: "relative w-full max-w-md",
|
|
1306
1318
|
style: {
|
|
1307
1319
|
backgroundColor: "var(--compass-color-surface)",
|
|
1308
1320
|
boxShadow: "var(--compass-shadow-lg)",
|
|
1309
1321
|
borderRadius: "var(--compass-border-radius-xl)",
|
|
1310
|
-
fontFamily: "var(--compass-font-family)"
|
|
1322
|
+
fontFamily: "var(--compass-font-family)",
|
|
1323
|
+
maxHeight: "85vh",
|
|
1324
|
+
overflowY: "auto",
|
|
1325
|
+
overscrollBehavior: "contain",
|
|
1326
|
+
scrollbarWidth: "none"
|
|
1311
1327
|
},
|
|
1312
1328
|
children: [
|
|
1313
1329
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1314
1330
|
"div",
|
|
1315
1331
|
{
|
|
1316
|
-
className: "flex items-center justify-between border-b",
|
|
1332
|
+
className: "flex items-center justify-between border-b sticky top-0 z-10",
|
|
1317
1333
|
style: {
|
|
1318
1334
|
borderColor: "var(--compass-color-border)",
|
|
1319
|
-
padding: "calc(var(--compass-spacing-card) * 0.75) var(--compass-spacing-card)"
|
|
1335
|
+
padding: "calc(var(--compass-spacing-card) * 0.75) var(--compass-spacing-card)",
|
|
1336
|
+
backgroundColor: "var(--compass-color-surface)"
|
|
1320
1337
|
},
|
|
1321
1338
|
children: [
|
|
1322
1339
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2573,114 +2590,731 @@ function CreditAccountGuard({
|
|
|
2573
2590
|
}
|
|
2574
2591
|
);
|
|
2575
2592
|
}
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2593
|
+
var EVM_CHAIN_IDS = {
|
|
2594
|
+
ethereum: 1,
|
|
2595
|
+
base: 8453,
|
|
2596
|
+
arbitrum: 42161
|
|
2597
|
+
};
|
|
2598
|
+
function BuyForm({ targetAddress, defaultAsset = "USDC", onComplete }) {
|
|
2599
|
+
const { fundWallet } = useEmbeddableWallet();
|
|
2600
|
+
const { chainId } = useChain();
|
|
2601
|
+
const [amount, setAmount] = react.useState("");
|
|
2602
|
+
const [state, setState] = react.useState("idle");
|
|
2603
|
+
const [error, setError] = react.useState(null);
|
|
2604
|
+
const numericChainId = EVM_CHAIN_IDS[chainId] || 8453;
|
|
2605
|
+
const handleBuy = react.useCallback(async () => {
|
|
2606
|
+
if (!fundWallet || !amount || parseFloat(amount) <= 0) {
|
|
2607
|
+
return;
|
|
2608
|
+
}
|
|
2609
|
+
setState("buying");
|
|
2610
|
+
setError(null);
|
|
2611
|
+
try {
|
|
2612
|
+
await fundWallet({
|
|
2613
|
+
address: targetAddress,
|
|
2614
|
+
chainId: numericChainId,
|
|
2615
|
+
asset: defaultAsset,
|
|
2616
|
+
amount
|
|
2617
|
+
});
|
|
2618
|
+
setState("success");
|
|
2619
|
+
onComplete?.();
|
|
2620
|
+
setTimeout(() => setState("idle"), 3e3);
|
|
2621
|
+
} catch (err) {
|
|
2622
|
+
setState("error");
|
|
2623
|
+
setError(err instanceof Error ? err.message : "Purchase failed. Please try again.");
|
|
2624
|
+
}
|
|
2625
|
+
}, [fundWallet, amount, targetAddress, numericChainId, defaultAsset, onComplete]);
|
|
2626
|
+
const chainName = chainId.charAt(0).toUpperCase() + chainId.slice(1);
|
|
2627
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
2628
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2629
|
+
"p",
|
|
2599
2630
|
{
|
|
2600
|
-
className: "text-
|
|
2601
|
-
style: { color: "var(--compass-color-text-
|
|
2602
|
-
children:
|
|
2631
|
+
className: "text-sm font-medium",
|
|
2632
|
+
style: { color: "var(--compass-color-text)", fontFamily: "var(--compass-font-family)" },
|
|
2633
|
+
children: [
|
|
2634
|
+
"Buy ",
|
|
2635
|
+
defaultAsset,
|
|
2636
|
+
" on ",
|
|
2637
|
+
chainName
|
|
2638
|
+
]
|
|
2603
2639
|
}
|
|
2604
|
-
)
|
|
2605
|
-
|
|
2640
|
+
),
|
|
2641
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2642
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2643
|
+
"label",
|
|
2644
|
+
{
|
|
2645
|
+
className: "block text-sm mb-1.5",
|
|
2646
|
+
style: { color: "var(--compass-color-text-secondary)", fontFamily: "var(--compass-font-family)" },
|
|
2647
|
+
children: "Amount (USD)"
|
|
2648
|
+
}
|
|
2649
|
+
),
|
|
2650
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
2606
2651
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2607
2652
|
"span",
|
|
2608
2653
|
{
|
|
2609
|
-
className: "
|
|
2654
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 text-sm",
|
|
2610
2655
|
style: { color: "var(--compass-color-text-tertiary)" },
|
|
2611
|
-
children: "
|
|
2656
|
+
children: "$"
|
|
2612
2657
|
}
|
|
2613
2658
|
),
|
|
2614
2659
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2615
|
-
"
|
|
2660
|
+
"input",
|
|
2616
2661
|
{
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2662
|
+
type: "number",
|
|
2663
|
+
value: amount,
|
|
2664
|
+
onChange: (e) => {
|
|
2665
|
+
setAmount(e.target.value);
|
|
2666
|
+
if (state === "error") {
|
|
2667
|
+
setState("idle");
|
|
2668
|
+
setError(null);
|
|
2669
|
+
}
|
|
2622
2670
|
},
|
|
2623
|
-
|
|
2624
|
-
|
|
2671
|
+
disabled: state === "buying",
|
|
2672
|
+
placeholder: "0.00",
|
|
2673
|
+
className: "w-full border px-3 py-2.5 pl-7 text-sm focus:outline-none disabled:opacity-50",
|
|
2674
|
+
style: {
|
|
2675
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
2676
|
+
borderColor: "var(--compass-color-border)",
|
|
2677
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
2678
|
+
color: "var(--compass-color-text)",
|
|
2679
|
+
fontFamily: "var(--compass-font-family)"
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
)
|
|
2683
|
+
] })
|
|
2684
|
+
] }),
|
|
2685
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2686
|
+
"p",
|
|
2687
|
+
{
|
|
2688
|
+
className: "text-xs",
|
|
2689
|
+
style: { color: "var(--compass-color-text-tertiary)", fontFamily: "var(--compass-font-family)" },
|
|
2690
|
+
children: "Buy crypto with card or bank transfer. Funds are sent directly to your account."
|
|
2691
|
+
}
|
|
2692
|
+
),
|
|
2693
|
+
state === "success" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2694
|
+
"div",
|
|
2695
|
+
{
|
|
2696
|
+
className: "flex items-center gap-2 p-3 text-sm",
|
|
2697
|
+
style: {
|
|
2698
|
+
backgroundColor: "var(--compass-color-success-muted, rgba(34,197,94,0.1))",
|
|
2699
|
+
color: "var(--compass-color-success)",
|
|
2700
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
2701
|
+
fontFamily: "var(--compass-font-family)"
|
|
2702
|
+
},
|
|
2703
|
+
children: [
|
|
2704
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle, { size: 16 }),
|
|
2705
|
+
"Purchase initiated. Funds may take a few minutes to arrive."
|
|
2706
|
+
]
|
|
2707
|
+
}
|
|
2708
|
+
),
|
|
2709
|
+
state === "error" && error && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2710
|
+
"div",
|
|
2711
|
+
{
|
|
2712
|
+
className: "flex items-center gap-2 p-3 text-sm",
|
|
2713
|
+
style: {
|
|
2714
|
+
backgroundColor: "var(--compass-color-error-muted, rgba(239,68,68,0.1))",
|
|
2715
|
+
color: "var(--compass-color-error)",
|
|
2716
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
2717
|
+
fontFamily: "var(--compass-font-family)"
|
|
2718
|
+
},
|
|
2719
|
+
children: [
|
|
2720
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 16 }),
|
|
2721
|
+
error
|
|
2722
|
+
]
|
|
2723
|
+
}
|
|
2724
|
+
),
|
|
2725
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2726
|
+
"button",
|
|
2727
|
+
{
|
|
2728
|
+
onClick: handleBuy,
|
|
2729
|
+
disabled: state === "buying" || !amount || parseFloat(amount) <= 0,
|
|
2730
|
+
className: "w-full py-3 px-4 text-sm font-medium flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
2731
|
+
style: {
|
|
2732
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
2733
|
+
color: "white",
|
|
2734
|
+
borderRadius: "var(--compass-border-radius-xl)",
|
|
2735
|
+
fontFamily: "var(--compass-font-family)",
|
|
2736
|
+
transition: "var(--compass-transition-normal)"
|
|
2737
|
+
},
|
|
2738
|
+
children: state === "buying" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2739
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
2740
|
+
"Processing..."
|
|
2741
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2742
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "h-4 w-4" }),
|
|
2743
|
+
"Buy with card / bank"
|
|
2744
|
+
] })
|
|
2745
|
+
}
|
|
2746
|
+
)
|
|
2747
|
+
] });
|
|
2748
|
+
}
|
|
2749
|
+
var BLOCK_EXPLORERS = {
|
|
2750
|
+
ethereum: "https://etherscan.io",
|
|
2751
|
+
base: "https://basescan.org",
|
|
2752
|
+
arbitrum: "https://arbiscan.io"
|
|
2753
|
+
};
|
|
2754
|
+
function TxStatus({ state }) {
|
|
2755
|
+
const { chainId } = useChain();
|
|
2756
|
+
if (state.status === "idle") return null;
|
|
2757
|
+
const explorer = BLOCK_EXPLORERS[chainId] || BLOCK_EXPLORERS.ethereum;
|
|
2758
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2759
|
+
"div",
|
|
2760
|
+
{
|
|
2761
|
+
className: "mt-4 p-4 border",
|
|
2762
|
+
style: {
|
|
2763
|
+
borderColor: "var(--compass-color-border)",
|
|
2764
|
+
borderRadius: "var(--compass-border-radius-xl)",
|
|
2765
|
+
fontFamily: "var(--compass-font-family)"
|
|
2766
|
+
},
|
|
2767
|
+
children: [
|
|
2768
|
+
state.status === "preparing" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
2769
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2770
|
+
lucideReact.Loader2,
|
|
2771
|
+
{
|
|
2772
|
+
className: "h-4 w-4 animate-spin",
|
|
2773
|
+
style: { color: "var(--compass-color-primary)" }
|
|
2774
|
+
}
|
|
2775
|
+
),
|
|
2776
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text-secondary)" }, children: "Preparing transaction..." })
|
|
2777
|
+
] }),
|
|
2778
|
+
state.status === "signing" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
2779
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2780
|
+
lucideReact.Loader2,
|
|
2781
|
+
{
|
|
2782
|
+
className: "h-4 w-4 animate-spin",
|
|
2783
|
+
style: { color: "var(--compass-color-warning)" }
|
|
2784
|
+
}
|
|
2785
|
+
),
|
|
2786
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text-secondary)" }, children: "Waiting for signature..." })
|
|
2787
|
+
] }),
|
|
2788
|
+
state.status === "broadcasting" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
2789
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2790
|
+
lucideReact.Loader2,
|
|
2791
|
+
{
|
|
2792
|
+
className: "h-4 w-4 animate-spin",
|
|
2793
|
+
style: { color: "var(--compass-color-primary)" }
|
|
2794
|
+
}
|
|
2795
|
+
),
|
|
2796
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text-secondary)" }, children: "Broadcasting transaction..." })
|
|
2797
|
+
] }),
|
|
2798
|
+
state.status === "submitted" && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2799
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2800
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
2801
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2802
|
+
lucideReact.Loader2,
|
|
2803
|
+
{
|
|
2804
|
+
className: "h-4 w-4 animate-spin",
|
|
2805
|
+
style: { color: "var(--compass-color-primary)" }
|
|
2806
|
+
}
|
|
2807
|
+
),
|
|
2808
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text)" }, children: "Transaction submitted" })
|
|
2809
|
+
] }),
|
|
2810
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2811
|
+
"a",
|
|
2625
2812
|
{
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
},
|
|
2813
|
+
href: `${explorer}/tx/${state.txHash}`,
|
|
2814
|
+
target: "_blank",
|
|
2815
|
+
rel: "noopener noreferrer",
|
|
2816
|
+
className: "flex items-center gap-1.5 text-xs hover:opacity-70 transition-opacity",
|
|
2817
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2632
2818
|
children: [
|
|
2633
|
-
|
|
2634
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2635
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-text)" }, children: formatAmount(token.balance) }),
|
|
2636
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: formatUSD(token.usdValue) })
|
|
2637
|
-
] })
|
|
2819
|
+
"View on explorer",
|
|
2820
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-3 w-3" })
|
|
2638
2821
|
]
|
|
2639
|
-
}
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2822
|
+
}
|
|
2823
|
+
)
|
|
2824
|
+
] }),
|
|
2825
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2826
|
+
"p",
|
|
2827
|
+
{
|
|
2828
|
+
className: "text-xs mt-2",
|
|
2829
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
2830
|
+
children: "Waiting for on-chain confirmation. Balances will update automatically."
|
|
2831
|
+
}
|
|
2832
|
+
)
|
|
2833
|
+
] }),
|
|
2834
|
+
state.status === "confirmed" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2835
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
2652
2836
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2653
|
-
|
|
2837
|
+
lucideReact.CheckCircle,
|
|
2654
2838
|
{
|
|
2655
|
-
className: "
|
|
2656
|
-
style: { color: "var(--compass-color-
|
|
2657
|
-
children: formatUSD(totalUsdValue)
|
|
2839
|
+
className: "h-4 w-4",
|
|
2840
|
+
style: { color: "var(--compass-color-success)" }
|
|
2658
2841
|
}
|
|
2659
|
-
)
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
}
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2842
|
+
),
|
|
2843
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-success)" }, children: "Transaction confirmed" })
|
|
2844
|
+
] }),
|
|
2845
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2846
|
+
"a",
|
|
2847
|
+
{
|
|
2848
|
+
href: `${explorer}/tx/${state.txHash}`,
|
|
2849
|
+
target: "_blank",
|
|
2850
|
+
rel: "noopener noreferrer",
|
|
2851
|
+
className: "flex items-center gap-1.5 text-xs hover:opacity-70 transition-opacity",
|
|
2852
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2853
|
+
children: [
|
|
2854
|
+
"View on explorer",
|
|
2855
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-3 w-3" })
|
|
2856
|
+
]
|
|
2857
|
+
}
|
|
2858
|
+
)
|
|
2859
|
+
] }),
|
|
2860
|
+
state.status === "failed" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 text-sm", children: [
|
|
2861
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2862
|
+
lucideReact.XCircle,
|
|
2863
|
+
{
|
|
2864
|
+
className: "h-4 w-4 mt-0.5 shrink-0",
|
|
2865
|
+
style: { color: "var(--compass-color-error)" }
|
|
2866
|
+
}
|
|
2867
|
+
),
|
|
2868
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2869
|
+
"span",
|
|
2870
|
+
{
|
|
2871
|
+
className: "break-all",
|
|
2872
|
+
style: { color: "var(--compass-color-error)" },
|
|
2873
|
+
children: state.error
|
|
2874
|
+
}
|
|
2875
|
+
)
|
|
2876
|
+
] })
|
|
2877
|
+
]
|
|
2878
|
+
}
|
|
2879
|
+
);
|
|
2880
|
+
}
|
|
2881
|
+
function useTxPolling(options = {}) {
|
|
2882
|
+
const { chainId } = useChain();
|
|
2883
|
+
const queryClient = reactQuery.useQueryClient();
|
|
2884
|
+
const pollIntervalRef = react.useRef(null);
|
|
2885
|
+
const clearPolling = react.useCallback(() => {
|
|
2886
|
+
if (pollIntervalRef.current) {
|
|
2887
|
+
clearInterval(pollIntervalRef.current);
|
|
2888
|
+
pollIntervalRef.current = null;
|
|
2889
|
+
}
|
|
2890
|
+
}, []);
|
|
2891
|
+
react.useEffect(() => {
|
|
2892
|
+
return () => clearPolling();
|
|
2893
|
+
}, [clearPolling]);
|
|
2894
|
+
const startPolling = react.useCallback(
|
|
2895
|
+
(txHash, setTxState) => {
|
|
2896
|
+
clearPolling();
|
|
2897
|
+
let polls = 0;
|
|
2898
|
+
pollIntervalRef.current = setInterval(async () => {
|
|
2899
|
+
polls++;
|
|
2900
|
+
for (const key of options.queryKeysToInvalidate ?? []) {
|
|
2901
|
+
queryClient.invalidateQueries({ queryKey: key });
|
|
2902
|
+
}
|
|
2903
|
+
try {
|
|
2904
|
+
const res = await fetch(
|
|
2905
|
+
`/api/compass/tx/receipt?hash=${txHash}&chain=${chainId}`
|
|
2906
|
+
);
|
|
2907
|
+
const data = await res.json();
|
|
2908
|
+
if (data.status === "success") {
|
|
2909
|
+
clearPolling();
|
|
2910
|
+
setTxState({ status: "confirmed", txHash });
|
|
2911
|
+
return;
|
|
2912
|
+
} else if (data.status === "reverted") {
|
|
2913
|
+
clearPolling();
|
|
2914
|
+
setTxState({ status: "failed", error: "Transaction reverted" });
|
|
2915
|
+
return;
|
|
2916
|
+
}
|
|
2917
|
+
} catch (err) {
|
|
2918
|
+
if (err instanceof TypeError && err.message.includes("fetch")) ; else {
|
|
2919
|
+
console.warn("[useTxPolling] Unexpected error polling tx receipt:", err);
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2922
|
+
if (polls >= 24) {
|
|
2923
|
+
clearPolling();
|
|
2924
|
+
setTxState({ status: "failed", error: "Unable to confirm transaction. Please check a block explorer to verify." });
|
|
2925
|
+
}
|
|
2926
|
+
}, 5e3);
|
|
2927
|
+
},
|
|
2928
|
+
[chainId, clearPolling, queryClient, options.queryKeysToInvalidate]
|
|
2929
|
+
);
|
|
2930
|
+
return { startPolling, clearPolling };
|
|
2931
|
+
}
|
|
2932
|
+
var USDC_ADDRESSES = {
|
|
2933
|
+
ethereum: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
2934
|
+
base: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
2935
|
+
arbitrum: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
|
|
2936
|
+
};
|
|
2937
|
+
var ERC20_TRANSFER_ABI = [
|
|
2938
|
+
{
|
|
2939
|
+
type: "function",
|
|
2940
|
+
name: "transfer",
|
|
2941
|
+
inputs: [
|
|
2942
|
+
{ name: "to", type: "address" },
|
|
2943
|
+
{ name: "amount", type: "uint256" }
|
|
2944
|
+
],
|
|
2945
|
+
outputs: [{ name: "", type: "bool" }],
|
|
2946
|
+
stateMutability: "nonpayable"
|
|
2947
|
+
}
|
|
2948
|
+
];
|
|
2949
|
+
async function waitForReceipt(txHash, chainId) {
|
|
2950
|
+
const maxPolls = 60;
|
|
2951
|
+
for (let i = 0; i < maxPolls; i++) {
|
|
2952
|
+
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
2953
|
+
try {
|
|
2954
|
+
const res = await fetch(`/api/compass/tx/receipt?hash=${txHash}&chain=${chainId}`);
|
|
2955
|
+
const data = await res.json();
|
|
2956
|
+
if (data.status === "success") return;
|
|
2957
|
+
if (data.status === "reverted") throw new Error("Withdrawal transaction reverted");
|
|
2958
|
+
} catch (err) {
|
|
2959
|
+
if (err instanceof Error && err.message.includes("reverted")) throw err;
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
throw new Error("Unable to confirm withdrawal. Please check a block explorer to verify.");
|
|
2963
|
+
}
|
|
2964
|
+
function SendForm({ onComplete, product = "earn", productAccountAddress }) {
|
|
2965
|
+
const { sendTransaction, signTypedData, address } = useEmbeddableWallet();
|
|
2966
|
+
const { chainId } = useChain();
|
|
2967
|
+
const { earnAccountAddress, isDeployed } = useEarnAccount();
|
|
2968
|
+
const [recipient, setRecipient] = react.useState("");
|
|
2675
2969
|
const [amount, setAmount] = react.useState("");
|
|
2676
|
-
const [
|
|
2677
|
-
const
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
const {
|
|
2970
|
+
const [txState, setTxState] = react.useState({ status: "idle" });
|
|
2971
|
+
const { startPolling } = useTxPolling({
|
|
2972
|
+
queryKeysToInvalidate: product === "credit" ? [["creditBalances"], ["creditPositions"], ["eoaBalances"]] : [["earnAccountBalances"], ["eoaBalances"]]
|
|
2973
|
+
});
|
|
2974
|
+
const { data: earnBalanceData } = reactQuery.useQuery({
|
|
2975
|
+
queryKey: ["earnAccountBalances", chainId, address],
|
|
2976
|
+
queryFn: async () => {
|
|
2977
|
+
if (!address) return null;
|
|
2978
|
+
const response = await fetch(
|
|
2979
|
+
`/api/compass/earn-account/balances?owner=${address}&chain=${chainId}`
|
|
2980
|
+
);
|
|
2981
|
+
if (!response.ok) return null;
|
|
2982
|
+
return response.json();
|
|
2983
|
+
},
|
|
2984
|
+
enabled: !!address && isDeployed && product === "earn",
|
|
2985
|
+
staleTime: 30 * 1e3
|
|
2986
|
+
});
|
|
2987
|
+
const { data: creditBalanceData } = reactQuery.useQuery({
|
|
2988
|
+
queryKey: ["creditBalances", productAccountAddress, chainId],
|
|
2989
|
+
queryFn: async () => {
|
|
2990
|
+
if (!productAccountAddress) return null;
|
|
2991
|
+
const response = await fetch(
|
|
2992
|
+
`/api/compass/credit/balances?owner=${productAccountAddress}&chain=${chainId}`
|
|
2993
|
+
);
|
|
2994
|
+
if (!response.ok) return null;
|
|
2995
|
+
return response.json();
|
|
2996
|
+
},
|
|
2997
|
+
enabled: !!productAccountAddress && product === "credit",
|
|
2998
|
+
staleTime: 30 * 1e3
|
|
2999
|
+
});
|
|
3000
|
+
const availableBalance = product === "credit" ? creditBalanceData?.find((b) => b.tokenSymbol === "USDC")?.amount || "0" : earnBalanceData?.balances?.["USDC"]?.balance || "0";
|
|
3001
|
+
const tokenAddress = USDC_ADDRESSES[chainId];
|
|
3002
|
+
const isValidAddress = recipient.length > 0 && viem.isAddress(recipient);
|
|
3003
|
+
const isValidAmount = amount.length > 0 && parseFloat(amount) > 0;
|
|
3004
|
+
const exceedsBalance = isValidAmount && parseFloat(amount) > parseFloat(availableBalance);
|
|
3005
|
+
const isBusy = txState.status !== "idle" && txState.status !== "confirmed" && txState.status !== "failed";
|
|
3006
|
+
const canSend = isValidAddress && isValidAmount && !exceedsBalance && !!sendTransaction && !!signTypedData && !isBusy;
|
|
3007
|
+
const handleSend = react.useCallback(async () => {
|
|
3008
|
+
if (!sendTransaction || !signTypedData || !isValidAddress || !isValidAmount || !tokenAddress) return;
|
|
3009
|
+
try {
|
|
3010
|
+
setTxState({ status: "preparing" });
|
|
3011
|
+
const prepareRes = await fetch("/api/compass/transfer/prepare", {
|
|
3012
|
+
method: "POST",
|
|
3013
|
+
headers: { "Content-Type": "application/json" },
|
|
3014
|
+
body: JSON.stringify({
|
|
3015
|
+
owner: address,
|
|
3016
|
+
chain: chainId,
|
|
3017
|
+
token: "USDC",
|
|
3018
|
+
amount,
|
|
3019
|
+
action: "WITHDRAW",
|
|
3020
|
+
...product === "credit" ? { product: "credit" } : {}
|
|
3021
|
+
})
|
|
3022
|
+
});
|
|
3023
|
+
if (!prepareRes.ok) {
|
|
3024
|
+
const errData = await prepareRes.json();
|
|
3025
|
+
throw new Error(errData.error || "Failed to prepare withdrawal");
|
|
3026
|
+
}
|
|
3027
|
+
const prepareData = await prepareRes.json();
|
|
3028
|
+
setTxState({ status: "signing" });
|
|
3029
|
+
const withdrawSig = await signTypedData({
|
|
3030
|
+
domain: prepareData.domain,
|
|
3031
|
+
types: prepareData.normalizedTypes,
|
|
3032
|
+
primaryType: prepareData.primaryType,
|
|
3033
|
+
message: prepareData.message
|
|
3034
|
+
});
|
|
3035
|
+
setTxState({ status: "broadcasting" });
|
|
3036
|
+
const executeRes = await fetch("/api/compass/transfer/execute", {
|
|
3037
|
+
method: "POST",
|
|
3038
|
+
headers: { "Content-Type": "application/json" },
|
|
3039
|
+
body: JSON.stringify({
|
|
3040
|
+
owner: address,
|
|
3041
|
+
chain: chainId,
|
|
3042
|
+
eip712: prepareData.eip712,
|
|
3043
|
+
signature: withdrawSig,
|
|
3044
|
+
...product === "credit" ? { product: "credit" } : {}
|
|
3045
|
+
})
|
|
3046
|
+
});
|
|
3047
|
+
if (!executeRes.ok) {
|
|
3048
|
+
const errData = await executeRes.json();
|
|
3049
|
+
throw new Error(errData.error || "Withdrawal failed");
|
|
3050
|
+
}
|
|
3051
|
+
const { txHash: withdrawHash } = await executeRes.json();
|
|
3052
|
+
await waitForReceipt(withdrawHash, chainId);
|
|
3053
|
+
setTxState({ status: "signing" });
|
|
3054
|
+
const data = viem.encodeFunctionData({
|
|
3055
|
+
abi: ERC20_TRANSFER_ABI,
|
|
3056
|
+
functionName: "transfer",
|
|
3057
|
+
args: [recipient, viem.parseUnits(amount, 6)]
|
|
3058
|
+
});
|
|
3059
|
+
const sendHash = await sendTransaction({ to: tokenAddress, data });
|
|
3060
|
+
setTxState({ status: "submitted", txHash: sendHash });
|
|
3061
|
+
startPolling(sendHash, setTxState);
|
|
3062
|
+
setAmount("");
|
|
3063
|
+
setRecipient("");
|
|
3064
|
+
onComplete?.();
|
|
3065
|
+
} catch (err) {
|
|
3066
|
+
setTxState({ status: "failed", error: err instanceof Error ? err.message : "Transaction failed" });
|
|
3067
|
+
}
|
|
3068
|
+
}, [sendTransaction, signTypedData, recipient, amount, address, chainId, tokenAddress, isValidAddress, isValidAmount, onComplete, startPolling, product]);
|
|
3069
|
+
const chainName = chainId.charAt(0).toUpperCase() + chainId.slice(1);
|
|
3070
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
3071
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3072
|
+
"p",
|
|
3073
|
+
{
|
|
3074
|
+
className: "text-sm font-medium",
|
|
3075
|
+
style: { color: "var(--compass-color-text)", fontFamily: "var(--compass-font-family)" },
|
|
3076
|
+
children: [
|
|
3077
|
+
"Send USDC on ",
|
|
3078
|
+
chainName
|
|
3079
|
+
]
|
|
3080
|
+
}
|
|
3081
|
+
),
|
|
3082
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3083
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3084
|
+
"label",
|
|
3085
|
+
{
|
|
3086
|
+
className: "block text-sm mb-1.5",
|
|
3087
|
+
style: { color: "var(--compass-color-text-secondary)", fontFamily: "var(--compass-font-family)" },
|
|
3088
|
+
children: "Recipient Address"
|
|
3089
|
+
}
|
|
3090
|
+
),
|
|
3091
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3092
|
+
"input",
|
|
3093
|
+
{
|
|
3094
|
+
type: "text",
|
|
3095
|
+
value: recipient,
|
|
3096
|
+
onChange: (e) => {
|
|
3097
|
+
setRecipient(e.target.value);
|
|
3098
|
+
if (txState.status === "failed") setTxState({ status: "idle" });
|
|
3099
|
+
},
|
|
3100
|
+
disabled: isBusy,
|
|
3101
|
+
placeholder: "0x...",
|
|
3102
|
+
className: "w-full border px-3 py-2.5 text-sm focus:outline-none disabled:opacity-50 font-mono",
|
|
3103
|
+
style: {
|
|
3104
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
3105
|
+
borderColor: recipient && !isValidAddress ? "var(--compass-color-error)" : "var(--compass-color-border)",
|
|
3106
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
3107
|
+
color: "var(--compass-color-text)",
|
|
3108
|
+
fontFamily: "var(--compass-font-family)"
|
|
3109
|
+
}
|
|
3110
|
+
}
|
|
3111
|
+
),
|
|
3112
|
+
recipient && !isValidAddress && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs mt-1", style: { color: "var(--compass-color-error)" }, children: "Invalid Ethereum address" }),
|
|
3113
|
+
isValidAddress && recipient.toLowerCase() === address?.toLowerCase() && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs mt-1", style: { color: "var(--compass-color-warning, #f59e0b)" }, children: "This is your own wallet address" }),
|
|
3114
|
+
isValidAddress && earnAccountAddress && recipient.toLowerCase() === earnAccountAddress.toLowerCase() && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs mt-1", style: { color: "var(--compass-color-warning, #f59e0b)" }, children: "This is your savings account address" })
|
|
3115
|
+
] }),
|
|
3116
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3117
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3118
|
+
"label",
|
|
3119
|
+
{
|
|
3120
|
+
className: "block text-sm mb-1.5",
|
|
3121
|
+
style: { color: "var(--compass-color-text-secondary)", fontFamily: "var(--compass-font-family)" },
|
|
3122
|
+
children: "Amount"
|
|
3123
|
+
}
|
|
3124
|
+
),
|
|
3125
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
3126
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3127
|
+
"input",
|
|
3128
|
+
{
|
|
3129
|
+
type: "number",
|
|
3130
|
+
value: amount,
|
|
3131
|
+
onChange: (e) => {
|
|
3132
|
+
setAmount(e.target.value);
|
|
3133
|
+
if (txState.status === "failed") setTxState({ status: "idle" });
|
|
3134
|
+
},
|
|
3135
|
+
disabled: isBusy,
|
|
3136
|
+
placeholder: "0.00",
|
|
3137
|
+
className: "w-full border px-3 py-2.5 pr-14 text-sm focus:outline-none disabled:opacity-50",
|
|
3138
|
+
style: {
|
|
3139
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
3140
|
+
borderColor: "var(--compass-color-border)",
|
|
3141
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
3142
|
+
color: "var(--compass-color-text)",
|
|
3143
|
+
fontFamily: "var(--compass-font-family)"
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
),
|
|
3147
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3148
|
+
"span",
|
|
3149
|
+
{
|
|
3150
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-xs",
|
|
3151
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
3152
|
+
children: "USDC"
|
|
3153
|
+
}
|
|
3154
|
+
)
|
|
3155
|
+
] }),
|
|
3156
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3157
|
+
"button",
|
|
3158
|
+
{
|
|
3159
|
+
onClick: () => setAmount(availableBalance),
|
|
3160
|
+
className: "text-xs mt-1",
|
|
3161
|
+
style: { color: "var(--compass-color-primary)", cursor: "pointer", background: "none", border: "none", padding: 0 },
|
|
3162
|
+
children: [
|
|
3163
|
+
"Available: ",
|
|
3164
|
+
parseFloat(availableBalance).toFixed(2),
|
|
3165
|
+
" USDC"
|
|
3166
|
+
]
|
|
3167
|
+
}
|
|
3168
|
+
),
|
|
3169
|
+
exceedsBalance && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs mt-1", style: { color: "var(--compass-color-error)" }, children: "Amount exceeds available balance" })
|
|
3170
|
+
] }),
|
|
3171
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3172
|
+
"p",
|
|
3173
|
+
{
|
|
3174
|
+
className: "text-xs",
|
|
3175
|
+
style: { color: "var(--compass-color-text-tertiary)", fontFamily: "var(--compass-font-family)" },
|
|
3176
|
+
children: "Send USDC from your account to any address. Requires 2 signatures. Gas fees are sponsored."
|
|
3177
|
+
}
|
|
3178
|
+
),
|
|
3179
|
+
/* @__PURE__ */ jsxRuntime.jsx(TxStatus, { state: txState }),
|
|
3180
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3181
|
+
"button",
|
|
3182
|
+
{
|
|
3183
|
+
onClick: handleSend,
|
|
3184
|
+
disabled: !canSend,
|
|
3185
|
+
className: "w-full py-3 px-4 text-sm font-medium flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
3186
|
+
style: {
|
|
3187
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
3188
|
+
color: "white",
|
|
3189
|
+
borderRadius: "var(--compass-border-radius-xl)",
|
|
3190
|
+
fontFamily: "var(--compass-font-family)",
|
|
3191
|
+
transition: "var(--compass-transition-normal)"
|
|
3192
|
+
},
|
|
3193
|
+
children: isBusy ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3194
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
3195
|
+
"Sending..."
|
|
3196
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3197
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-4 w-4" }),
|
|
3198
|
+
"Send USDC"
|
|
3199
|
+
] })
|
|
3200
|
+
}
|
|
3201
|
+
)
|
|
3202
|
+
] });
|
|
3203
|
+
}
|
|
3204
|
+
function AccountBalancesModal({
|
|
3205
|
+
isOpen,
|
|
3206
|
+
onClose,
|
|
3207
|
+
balances,
|
|
3208
|
+
totalUsdValue,
|
|
3209
|
+
isLoading = false,
|
|
3210
|
+
earnAccountAddress,
|
|
3211
|
+
walletAddress
|
|
3212
|
+
}) {
|
|
3213
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ActionModal, { isOpen, onClose, title: "Balance Breakdown", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
3214
|
+
(walletAddress || earnAccountAddress) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
3215
|
+
walletAddress && /* @__PURE__ */ jsxRuntime.jsx(CopyableAddress, { address: walletAddress, label: "Wallet" }),
|
|
3216
|
+
earnAccountAddress && /* @__PURE__ */ jsxRuntime.jsx(CopyableAddress, { address: earnAccountAddress, label: "Product Account" })
|
|
3217
|
+
] }),
|
|
3218
|
+
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3219
|
+
lucideReact.Loader2,
|
|
3220
|
+
{
|
|
3221
|
+
size: 24,
|
|
3222
|
+
className: "animate-spin",
|
|
3223
|
+
style: { color: "var(--compass-color-primary)" }
|
|
3224
|
+
}
|
|
3225
|
+
) }) : balances.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3226
|
+
"div",
|
|
3227
|
+
{
|
|
3228
|
+
className: "text-center py-4",
|
|
3229
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
3230
|
+
children: "No tokens in account"
|
|
3231
|
+
}
|
|
3232
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3233
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3234
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3235
|
+
"span",
|
|
3236
|
+
{
|
|
3237
|
+
className: "text-xs font-medium uppercase tracking-wide",
|
|
3238
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
3239
|
+
children: "Available in Account"
|
|
3240
|
+
}
|
|
3241
|
+
),
|
|
3242
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3243
|
+
"div",
|
|
3244
|
+
{
|
|
3245
|
+
className: "flex flex-col gap-2",
|
|
3246
|
+
style: {
|
|
3247
|
+
maxHeight: "50vh",
|
|
3248
|
+
overflowY: "auto",
|
|
3249
|
+
scrollbarWidth: "none"
|
|
3250
|
+
},
|
|
3251
|
+
children: balances.filter((token) => parseFloat(token.balance) >= 5e-3).map((token) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3252
|
+
"div",
|
|
3253
|
+
{
|
|
3254
|
+
className: "flex items-center justify-between p-3 rounded-lg",
|
|
3255
|
+
style: {
|
|
3256
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
3257
|
+
border: "1px solid var(--compass-color-border)",
|
|
3258
|
+
flexShrink: 0
|
|
3259
|
+
},
|
|
3260
|
+
children: [
|
|
3261
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", style: { color: "var(--compass-color-text)" }, children: token.symbol }),
|
|
3262
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end", children: [
|
|
3263
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-text)" }, children: formatAmount(token.balance) }),
|
|
3264
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: formatUSD(token.usdValue) })
|
|
3265
|
+
] })
|
|
3266
|
+
]
|
|
3267
|
+
},
|
|
3268
|
+
token.symbol
|
|
3269
|
+
))
|
|
3270
|
+
}
|
|
3271
|
+
)
|
|
3272
|
+
] }),
|
|
3273
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3274
|
+
"div",
|
|
3275
|
+
{
|
|
3276
|
+
className: "flex items-center justify-between pt-3 mt-2",
|
|
3277
|
+
style: { borderTop: "2px solid var(--compass-color-border)" },
|
|
3278
|
+
children: [
|
|
3279
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", style: { color: "var(--compass-color-text)" }, children: "Total" }),
|
|
3280
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3281
|
+
"span",
|
|
3282
|
+
{
|
|
3283
|
+
className: "font-bold text-xl",
|
|
3284
|
+
style: { color: "var(--compass-color-text)" },
|
|
3285
|
+
children: formatUSD(totalUsdValue)
|
|
3286
|
+
}
|
|
3287
|
+
)
|
|
3288
|
+
]
|
|
3289
|
+
}
|
|
3290
|
+
)
|
|
3291
|
+
] })
|
|
3292
|
+
] }) });
|
|
3293
|
+
}
|
|
3294
|
+
var TRANSFER_TOKEN = "USDC";
|
|
3295
|
+
var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
|
|
3296
|
+
compact = false,
|
|
3297
|
+
hideVisual = false,
|
|
3298
|
+
onTransferComplete
|
|
3299
|
+
}, ref) {
|
|
3300
|
+
const { address, isConnected, signTypedData, switchChain, walletChainId, fundWallet, hasExternalWallet, sendTransaction } = useEmbeddableWallet();
|
|
2681
3301
|
const { chainId, chain } = useChain();
|
|
2682
3302
|
const { earnAccountAddress, isDeployed } = useEarnAccount();
|
|
2683
3303
|
const queryClient = reactQuery.useQueryClient();
|
|
3304
|
+
const showBuyTab = !!fundWallet;
|
|
3305
|
+
const showSendTab = !!sendTransaction && !hasExternalWallet;
|
|
3306
|
+
const buyOnly = !hasExternalWallet && showBuyTab && !sendTransaction;
|
|
3307
|
+
const [isModalOpen, setIsModalOpen] = react.useState(false);
|
|
3308
|
+
const [activeAction, setActiveAction] = react.useState(
|
|
3309
|
+
!hasExternalWallet && fundWallet ? "buy" : "deposit"
|
|
3310
|
+
);
|
|
3311
|
+
const selectedToken = TRANSFER_TOKEN;
|
|
3312
|
+
const [amount, setAmount] = react.useState("");
|
|
3313
|
+
const [txState, setTxState] = react.useState({ status: "idle" });
|
|
3314
|
+
const [isBalancesModalOpen, setIsBalancesModalOpen] = react.useState(false);
|
|
3315
|
+
const { startPolling, clearPolling } = useTxPolling({
|
|
3316
|
+
queryKeysToInvalidate: [["earnAccountBalances"], ["eoaBalances"]]
|
|
3317
|
+
});
|
|
2684
3318
|
const { data: balanceData, isLoading: balancesLoading } = reactQuery.useQuery({
|
|
2685
3319
|
queryKey: ["earnAccountBalances", chainId, address],
|
|
2686
3320
|
queryFn: async () => {
|
|
@@ -2697,25 +3331,22 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
|
|
|
2697
3331
|
staleTime: 30 * 1e3
|
|
2698
3332
|
});
|
|
2699
3333
|
const { data: eoaBalances } = reactQuery.useQuery({
|
|
2700
|
-
queryKey: ["eoaBalances", chainId, address,
|
|
3334
|
+
queryKey: ["eoaBalances", chainId, address, TRANSFER_TOKEN],
|
|
2701
3335
|
queryFn: async () => {
|
|
2702
3336
|
if (!address) return {};
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
);
|
|
2709
|
-
|
|
2710
|
-
const data = await response.json();
|
|
2711
|
-
balances[token] = data.balance || "0";
|
|
2712
|
-
}
|
|
2713
|
-
} catch {
|
|
3337
|
+
try {
|
|
3338
|
+
const response = await fetch(
|
|
3339
|
+
`/api/compass/token/balance?chain=${chainId}&token=${TRANSFER_TOKEN}&address=${address}`
|
|
3340
|
+
);
|
|
3341
|
+
if (response.ok) {
|
|
3342
|
+
const data = await response.json();
|
|
3343
|
+
return { [TRANSFER_TOKEN]: data.balance || "0" };
|
|
2714
3344
|
}
|
|
3345
|
+
} catch {
|
|
2715
3346
|
}
|
|
2716
|
-
return
|
|
3347
|
+
return {};
|
|
2717
3348
|
},
|
|
2718
|
-
enabled: !!address && activeAction === "deposit",
|
|
3349
|
+
enabled: !!address && hasExternalWallet && activeAction === "deposit",
|
|
2719
3350
|
staleTime: 30 * 1e3
|
|
2720
3351
|
});
|
|
2721
3352
|
const earnBalances = balanceData?.balances || {};
|
|
@@ -2734,10 +3365,9 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
|
|
|
2734
3365
|
}
|
|
2735
3366
|
const resetForm = react.useCallback(() => {
|
|
2736
3367
|
setAmount("");
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
}, []);
|
|
3368
|
+
setTxState({ status: "idle" });
|
|
3369
|
+
clearPolling();
|
|
3370
|
+
}, [clearPolling]);
|
|
2741
3371
|
const handleOpenModal = () => {
|
|
2742
3372
|
resetForm();
|
|
2743
3373
|
setIsModalOpen(true);
|
|
@@ -2752,7 +3382,8 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
|
|
|
2752
3382
|
const handleActionChange = (action) => {
|
|
2753
3383
|
setActiveAction(action);
|
|
2754
3384
|
setAmount("");
|
|
2755
|
-
|
|
3385
|
+
setTxState({ status: "idle" });
|
|
3386
|
+
clearPolling();
|
|
2756
3387
|
};
|
|
2757
3388
|
const getMaxBalance = () => {
|
|
2758
3389
|
if (activeAction === "deposit") {
|
|
@@ -2760,37 +3391,28 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
|
|
|
2760
3391
|
}
|
|
2761
3392
|
return earnBalanceAmounts[selectedToken] || "0";
|
|
2762
3393
|
};
|
|
2763
|
-
const handleQuickAmount = (percentage) => {
|
|
2764
|
-
const max = parseFloat(getMaxBalance());
|
|
2765
|
-
if (isNaN(max)) return;
|
|
2766
|
-
setAmount(formatAmount(max * percentage));
|
|
2767
|
-
};
|
|
2768
3394
|
const handleTransfer = react.useCallback(async () => {
|
|
2769
3395
|
if (!address || !amount || !signTypedData) return;
|
|
2770
|
-
|
|
3396
|
+
setTxState({ status: "preparing" });
|
|
2771
3397
|
try {
|
|
2772
3398
|
const targetChainId = chain.viemChain.id;
|
|
2773
3399
|
if (walletChainId !== void 0 && walletChainId !== targetChainId) {
|
|
2774
3400
|
if (!switchChain) {
|
|
2775
3401
|
throw new Error(`Please switch your wallet to ${chain.name} (chain ID ${targetChainId}) to continue. Your wallet is currently on chain ID ${walletChainId}.`);
|
|
2776
3402
|
}
|
|
2777
|
-
setStatusMessage(`Switching network to ${chain.name}...`);
|
|
2778
3403
|
try {
|
|
2779
3404
|
await switchChain(targetChainId);
|
|
2780
|
-
} catch
|
|
3405
|
+
} catch {
|
|
2781
3406
|
throw new Error(`Please switch your wallet to ${chain.name} to continue. Your wallet is on chain ID ${walletChainId}, but ${chain.name} requires chain ID ${targetChainId}.`);
|
|
2782
3407
|
}
|
|
2783
3408
|
} else if (switchChain && walletChainId === void 0) {
|
|
2784
|
-
setStatusMessage("Switching network...");
|
|
2785
3409
|
try {
|
|
2786
3410
|
await switchChain(targetChainId);
|
|
2787
|
-
} catch
|
|
3411
|
+
} catch {
|
|
2788
3412
|
throw new Error(`Please switch your wallet to ${chain.name} to continue`);
|
|
2789
3413
|
}
|
|
2790
3414
|
}
|
|
2791
3415
|
if (activeAction === "deposit") {
|
|
2792
|
-
setTransferState("checking_approval");
|
|
2793
|
-
setStatusMessage("Checking token approval...");
|
|
2794
3416
|
const approveResponse = await fetch("/api/compass/transfer/approve", {
|
|
2795
3417
|
method: "POST",
|
|
2796
3418
|
headers: { "Content-Type": "application/json" },
|
|
@@ -2809,16 +3431,14 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
|
|
|
2809
3431
|
if (approvalData.requiresTransaction) {
|
|
2810
3432
|
throw new Error("This token requires a transaction-based approval. Please approve manually.");
|
|
2811
3433
|
}
|
|
2812
|
-
|
|
2813
|
-
setStatusMessage("Please sign the approval...");
|
|
3434
|
+
setTxState({ status: "signing" });
|
|
2814
3435
|
const approvalSignature = await signTypedData({
|
|
2815
3436
|
domain: approvalData.domain,
|
|
2816
3437
|
types: approvalData.normalizedTypes,
|
|
2817
3438
|
primaryType: "Permit",
|
|
2818
3439
|
message: approvalData.message
|
|
2819
3440
|
});
|
|
2820
|
-
|
|
2821
|
-
setStatusMessage("Executing approval...");
|
|
3441
|
+
setTxState({ status: "broadcasting" });
|
|
2822
3442
|
const executeApprovalResponse = await fetch("/api/compass/transfer/execute", {
|
|
2823
3443
|
method: "POST",
|
|
2824
3444
|
headers: { "Content-Type": "application/json" },
|
|
@@ -2835,8 +3455,7 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
|
|
|
2835
3455
|
}
|
|
2836
3456
|
}
|
|
2837
3457
|
}
|
|
2838
|
-
|
|
2839
|
-
setStatusMessage("Preparing transfer...");
|
|
3458
|
+
setTxState({ status: "signing" });
|
|
2840
3459
|
const prepareResponse = await fetch("/api/compass/transfer/prepare", {
|
|
2841
3460
|
method: "POST",
|
|
2842
3461
|
headers: { "Content-Type": "application/json" },
|
|
@@ -2853,15 +3472,13 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
|
|
|
2853
3472
|
throw new Error(errData.error || "Failed to prepare transfer");
|
|
2854
3473
|
}
|
|
2855
3474
|
const prepareData = await prepareResponse.json();
|
|
2856
|
-
setStatusMessage("Please sign the transfer...");
|
|
2857
3475
|
const transferSignature = await signTypedData({
|
|
2858
3476
|
domain: prepareData.domain,
|
|
2859
3477
|
types: prepareData.normalizedTypes,
|
|
2860
3478
|
primaryType: prepareData.primaryType,
|
|
2861
3479
|
message: prepareData.message
|
|
2862
3480
|
});
|
|
2863
|
-
|
|
2864
|
-
setStatusMessage("Executing transfer...");
|
|
3481
|
+
setTxState({ status: "broadcasting" });
|
|
2865
3482
|
const executeResponse = await fetch("/api/compass/transfer/execute", {
|
|
2866
3483
|
method: "POST",
|
|
2867
3484
|
headers: { "Content-Type": "application/json" },
|
|
@@ -2877,17 +3494,12 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
|
|
|
2877
3494
|
throw new Error(errData.error || "Transfer failed");
|
|
2878
3495
|
}
|
|
2879
3496
|
const { txHash } = await executeResponse.json();
|
|
2880
|
-
|
|
2881
|
-
|
|
3497
|
+
setTxState({ status: "submitted", txHash });
|
|
3498
|
+
startPolling(txHash, setTxState);
|
|
2882
3499
|
onTransferComplete?.(activeAction, selectedToken, amount, txHash);
|
|
2883
|
-
|
|
2884
|
-
queryClient.invalidateQueries({ queryKey: ["eoaBalances"] });
|
|
2885
|
-
setTimeout(() => {
|
|
2886
|
-
resetForm();
|
|
2887
|
-
}, 2e3);
|
|
3500
|
+
setAmount("");
|
|
2888
3501
|
} catch (err) {
|
|
2889
|
-
|
|
2890
|
-
setError(err instanceof Error ? err.message : "Transfer failed");
|
|
3502
|
+
setTxState({ status: "failed", error: err instanceof Error ? err.message : "Transfer failed" });
|
|
2891
3503
|
}
|
|
2892
3504
|
}, [
|
|
2893
3505
|
address,
|
|
@@ -2899,14 +3511,13 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
|
|
|
2899
3511
|
walletChainId,
|
|
2900
3512
|
signTypedData,
|
|
2901
3513
|
switchChain,
|
|
2902
|
-
queryClient,
|
|
2903
3514
|
onTransferComplete,
|
|
2904
|
-
|
|
3515
|
+
startPolling
|
|
2905
3516
|
]);
|
|
2906
3517
|
if (!isConnected) {
|
|
2907
3518
|
return null;
|
|
2908
3519
|
}
|
|
2909
|
-
const isProcessing =
|
|
3520
|
+
const isProcessing = txState.status !== "idle" && txState.status !== "confirmed" && txState.status !== "failed";
|
|
2910
3521
|
if (!isDeployed && !hideVisual) {
|
|
2911
3522
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2912
3523
|
"div",
|
|
@@ -2988,178 +3599,151 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
|
|
|
2988
3599
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2989
3600
|
ActionModal,
|
|
2990
3601
|
{
|
|
2991
|
-
isOpen: isModalOpen,
|
|
2992
|
-
onClose: handleCloseModal,
|
|
2993
|
-
title: "Transfer Funds",
|
|
2994
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2995
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2996
|
-
"div",
|
|
2997
|
-
{
|
|
2998
|
-
className: "flex gap-1 p-1",
|
|
2999
|
-
style: {
|
|
3000
|
-
backgroundColor: "var(--compass-color-background)",
|
|
3001
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
3002
|
-
fontFamily: "var(--compass-font-family)"
|
|
3003
|
-
},
|
|
3004
|
-
children: ["deposit", "withdraw"].map((action) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3005
|
-
"button",
|
|
3006
|
-
{
|
|
3007
|
-
onClick: () => handleActionChange(action),
|
|
3008
|
-
disabled: isProcessing,
|
|
3009
|
-
className: "flex-1 py-2 text-sm font-medium capitalize transition-all flex items-center justify-center gap-2",
|
|
3010
|
-
style: {
|
|
3011
|
-
backgroundColor: activeAction === action ? "var(--compass-color-surface)" : "transparent",
|
|
3012
|
-
color: activeAction === action ? "var(--compass-color-text)" : "var(--compass-color-text-secondary)",
|
|
3013
|
-
borderRadius: "var(--compass-border-radius-md)"
|
|
3014
|
-
},
|
|
3015
|
-
children: [
|
|
3016
|
-
action === "deposit" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownLeft, { size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { size: 14 }),
|
|
3017
|
-
action
|
|
3018
|
-
]
|
|
3019
|
-
},
|
|
3020
|
-
action
|
|
3021
|
-
))
|
|
3022
|
-
}
|
|
3023
|
-
),
|
|
3024
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3025
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3026
|
-
"label",
|
|
3027
|
-
{
|
|
3028
|
-
className: "text-sm font-medium mb-1 block",
|
|
3029
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
3030
|
-
children: "Token"
|
|
3031
|
-
}
|
|
3032
|
-
),
|
|
3033
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3034
|
-
TokenSelector,
|
|
3035
|
-
{
|
|
3036
|
-
tokens: TRANSFER_TOKENS,
|
|
3037
|
-
selectedToken,
|
|
3038
|
-
onSelect: setSelectedToken,
|
|
3039
|
-
balances: activeAction === "deposit" ? eoaBalances : earnBalanceAmounts,
|
|
3040
|
-
disabled: isProcessing
|
|
3041
|
-
}
|
|
3042
|
-
)
|
|
3043
|
-
] }),
|
|
3044
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3045
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-1", children: [
|
|
3046
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3047
|
-
"label",
|
|
3048
|
-
{
|
|
3049
|
-
className: "text-sm font-medium",
|
|
3050
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
3051
|
-
children: "Amount"
|
|
3052
|
-
}
|
|
3053
|
-
),
|
|
3054
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: [
|
|
3055
|
-
"Available: ",
|
|
3056
|
-
formatAmount(getMaxBalance()),
|
|
3057
|
-
" ",
|
|
3058
|
-
selectedToken
|
|
3059
|
-
] })
|
|
3060
|
-
] }),
|
|
3061
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3062
|
-
"div",
|
|
3063
|
-
{
|
|
3064
|
-
className: "flex items-center gap-2 p-3 border",
|
|
3065
|
-
style: {
|
|
3066
|
-
backgroundColor: "var(--compass-color-background)",
|
|
3067
|
-
borderColor: "var(--compass-color-border)",
|
|
3068
|
-
borderRadius: "var(--compass-border-radius-lg)"
|
|
3069
|
-
},
|
|
3070
|
-
children: [
|
|
3071
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3072
|
-
"input",
|
|
3073
|
-
{
|
|
3074
|
-
type: "number",
|
|
3075
|
-
value: amount,
|
|
3076
|
-
onChange: (e) => {
|
|
3077
|
-
setAmount(e.target.value);
|
|
3078
|
-
setError(null);
|
|
3079
|
-
},
|
|
3080
|
-
placeholder: "0.00",
|
|
3081
|
-
disabled: isProcessing,
|
|
3082
|
-
className: "flex-1 bg-transparent outline-none text-lg font-mono",
|
|
3083
|
-
style: { color: "var(--compass-color-text)" }
|
|
3084
|
-
}
|
|
3085
|
-
),
|
|
3086
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3087
|
-
"span",
|
|
3088
|
-
{
|
|
3089
|
-
className: "text-sm font-medium",
|
|
3090
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
3091
|
-
children: selectedToken
|
|
3092
|
-
}
|
|
3093
|
-
)
|
|
3094
|
-
]
|
|
3095
|
-
}
|
|
3096
|
-
)
|
|
3097
|
-
] }),
|
|
3098
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-2", children: [0.25, 0.5, 1].map((pct) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3099
|
-
"button",
|
|
3100
|
-
{
|
|
3101
|
-
onClick: () => handleQuickAmount(pct),
|
|
3102
|
-
disabled: isProcessing,
|
|
3103
|
-
className: "flex-1 py-1.5 text-xs font-medium transition-colors",
|
|
3104
|
-
style: {
|
|
3105
|
-
backgroundColor: "var(--compass-color-secondary)",
|
|
3106
|
-
color: "var(--compass-color-text-secondary)",
|
|
3107
|
-
borderRadius: "var(--compass-border-radius-md)"
|
|
3108
|
-
},
|
|
3109
|
-
children: pct === 1 ? "Max" : `${pct * 100}%`
|
|
3110
|
-
},
|
|
3111
|
-
pct
|
|
3112
|
-
)) }),
|
|
3113
|
-
error && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3114
|
-
"div",
|
|
3115
|
-
{
|
|
3116
|
-
className: "p-3 text-sm",
|
|
3117
|
-
style: {
|
|
3118
|
-
backgroundColor: "var(--compass-color-error-muted)",
|
|
3119
|
-
color: "var(--compass-color-error)",
|
|
3120
|
-
borderRadius: "var(--compass-border-radius-lg)"
|
|
3121
|
-
},
|
|
3122
|
-
children: error
|
|
3123
|
-
}
|
|
3124
|
-
),
|
|
3125
|
-
statusMessage && !error && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3126
|
-
"div",
|
|
3127
|
-
{
|
|
3128
|
-
className: "p-3 text-sm text-center",
|
|
3129
|
-
style: {
|
|
3130
|
-
backgroundColor: transferState === "success" ? "var(--compass-color-success-muted)" : "var(--compass-color-primary-muted)",
|
|
3131
|
-
color: transferState === "success" ? "var(--compass-color-success)" : "var(--compass-color-primary)",
|
|
3132
|
-
borderRadius: "var(--compass-border-radius-lg)"
|
|
3133
|
-
},
|
|
3134
|
-
children: statusMessage
|
|
3135
|
-
}
|
|
3136
|
-
),
|
|
3137
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3138
|
-
"button",
|
|
3602
|
+
isOpen: isModalOpen,
|
|
3603
|
+
onClose: handleCloseModal,
|
|
3604
|
+
title: showSendTab ? "Manage Funds" : buyOnly ? "Add Funds" : "Transfer Funds",
|
|
3605
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
3606
|
+
buyOnly ? null : /* @__PURE__ */ jsxRuntime.jsx(
|
|
3607
|
+
"div",
|
|
3139
3608
|
{
|
|
3140
|
-
|
|
3141
|
-
disabled: isProcessing || !amount || parseFloat(amount) <= 0,
|
|
3142
|
-
className: "w-full py-3 font-medium transition-colors flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
3609
|
+
className: "flex gap-1 p-1",
|
|
3143
3610
|
style: {
|
|
3144
|
-
backgroundColor: "var(--compass-color-
|
|
3145
|
-
color: "var(--compass-color-primary-text)",
|
|
3611
|
+
backgroundColor: "var(--compass-color-background)",
|
|
3146
3612
|
borderRadius: "var(--compass-border-radius-lg)",
|
|
3147
3613
|
fontFamily: "var(--compass-font-family)"
|
|
3148
3614
|
},
|
|
3149
3615
|
children: [
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3616
|
+
...showSendTab ? ["buy", "send"] : ["deposit", "withdraw", ...showBuyTab ? ["buy"] : []]
|
|
3617
|
+
].map((action) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3618
|
+
"button",
|
|
3619
|
+
{
|
|
3620
|
+
onClick: () => handleActionChange(action),
|
|
3621
|
+
disabled: isProcessing,
|
|
3622
|
+
className: "flex-1 py-2 text-sm font-medium capitalize transition-all flex items-center justify-center gap-2",
|
|
3623
|
+
style: {
|
|
3624
|
+
backgroundColor: activeAction === action ? "var(--compass-color-surface)" : "transparent",
|
|
3625
|
+
color: activeAction === action ? "var(--compass-color-text)" : "var(--compass-color-text-secondary)",
|
|
3626
|
+
borderRadius: "var(--compass-border-radius-md)"
|
|
3627
|
+
},
|
|
3628
|
+
children: [
|
|
3629
|
+
action === "deposit" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownLeft, { size: 14 }) : action === "withdraw" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { size: 14 }) : action === "send" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { size: 14 }),
|
|
3630
|
+
action
|
|
3631
|
+
]
|
|
3632
|
+
},
|
|
3633
|
+
action
|
|
3634
|
+
))
|
|
3153
3635
|
}
|
|
3154
3636
|
),
|
|
3155
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3156
|
-
|
|
3637
|
+
activeAction === "send" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3638
|
+
SendForm,
|
|
3157
3639
|
{
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3640
|
+
onComplete: () => {
|
|
3641
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
3642
|
+
queryClient.invalidateQueries({ queryKey: ["eoaBalances"] });
|
|
3643
|
+
}
|
|
3161
3644
|
}
|
|
3162
|
-
)
|
|
3645
|
+
) : activeAction === "buy" || buyOnly ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3646
|
+
BuyForm,
|
|
3647
|
+
{
|
|
3648
|
+
targetAddress: earnAccountAddress || "",
|
|
3649
|
+
onComplete: () => {
|
|
3650
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
3651
|
+
queryClient.invalidateQueries({ queryKey: ["eoaBalances"] });
|
|
3652
|
+
}
|
|
3653
|
+
}
|
|
3654
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3655
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3656
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3657
|
+
"label",
|
|
3658
|
+
{
|
|
3659
|
+
className: "text-sm font-medium mb-1 block",
|
|
3660
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
3661
|
+
children: "Amount"
|
|
3662
|
+
}
|
|
3663
|
+
),
|
|
3664
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3665
|
+
"div",
|
|
3666
|
+
{
|
|
3667
|
+
className: "flex items-center gap-2 p-3 border",
|
|
3668
|
+
style: {
|
|
3669
|
+
backgroundColor: "var(--compass-color-background)",
|
|
3670
|
+
borderColor: "var(--compass-color-border)",
|
|
3671
|
+
borderRadius: "var(--compass-border-radius-lg)"
|
|
3672
|
+
},
|
|
3673
|
+
children: [
|
|
3674
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3675
|
+
"input",
|
|
3676
|
+
{
|
|
3677
|
+
type: "number",
|
|
3678
|
+
value: amount,
|
|
3679
|
+
onChange: (e) => {
|
|
3680
|
+
setAmount(e.target.value);
|
|
3681
|
+
if (txState.status === "failed") setTxState({ status: "idle" });
|
|
3682
|
+
},
|
|
3683
|
+
placeholder: "0.00",
|
|
3684
|
+
disabled: isProcessing,
|
|
3685
|
+
className: "flex-1 bg-transparent outline-none text-lg font-mono",
|
|
3686
|
+
style: { color: "var(--compass-color-text)" }
|
|
3687
|
+
}
|
|
3688
|
+
),
|
|
3689
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3690
|
+
"span",
|
|
3691
|
+
{
|
|
3692
|
+
className: "text-sm font-medium",
|
|
3693
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
3694
|
+
children: "USDC"
|
|
3695
|
+
}
|
|
3696
|
+
)
|
|
3697
|
+
]
|
|
3698
|
+
}
|
|
3699
|
+
),
|
|
3700
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3701
|
+
"button",
|
|
3702
|
+
{
|
|
3703
|
+
onClick: () => setAmount(formatAmount(getMaxBalance())),
|
|
3704
|
+
className: "text-xs mt-1",
|
|
3705
|
+
style: { color: "var(--compass-color-primary)", cursor: "pointer", background: "none", border: "none", padding: 0 },
|
|
3706
|
+
children: [
|
|
3707
|
+
"Available: ",
|
|
3708
|
+
formatAmount(getMaxBalance()),
|
|
3709
|
+
" USDC"
|
|
3710
|
+
]
|
|
3711
|
+
}
|
|
3712
|
+
)
|
|
3713
|
+
] }),
|
|
3714
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: activeAction === "deposit" ? `Approves the token transfer, then transfers USDC from your ${!hasExternalWallet ? "embedded " : ""}wallet into your savings account. Requires 2 signatures.${!hasExternalWallet ? " Note: deposit and withdraw use your embedded wallet, not your bank account." : ""}` : `Moves USDC from your savings account back to your ${!hasExternalWallet ? "embedded " : ""}wallet. Requires 1 signature.${!hasExternalWallet ? " Gas fees are sponsored." : ""}` }),
|
|
3715
|
+
/* @__PURE__ */ jsxRuntime.jsx(TxStatus, { state: txState }),
|
|
3716
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3717
|
+
"button",
|
|
3718
|
+
{
|
|
3719
|
+
onClick: handleTransfer,
|
|
3720
|
+
disabled: isProcessing || !amount || parseFloat(amount) <= 0,
|
|
3721
|
+
className: "w-full py-3 font-medium transition-colors flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
3722
|
+
style: {
|
|
3723
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
3724
|
+
color: "var(--compass-color-primary-text)",
|
|
3725
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
3726
|
+
fontFamily: "var(--compass-font-family)"
|
|
3727
|
+
},
|
|
3728
|
+
children: isProcessing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3729
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 18, className: "animate-spin" }),
|
|
3730
|
+
" Processing..."
|
|
3731
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3732
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { size: 16 }),
|
|
3733
|
+
" ",
|
|
3734
|
+
activeAction === "deposit" ? "Transfer to Savings Account" : "Withdraw to Wallet"
|
|
3735
|
+
] })
|
|
3736
|
+
}
|
|
3737
|
+
),
|
|
3738
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3739
|
+
"p",
|
|
3740
|
+
{
|
|
3741
|
+
className: "text-xs text-center",
|
|
3742
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
3743
|
+
children: "Gas fees are sponsored by Compass"
|
|
3744
|
+
}
|
|
3745
|
+
)
|
|
3746
|
+
] })
|
|
3163
3747
|
] })
|
|
3164
3748
|
}
|
|
3165
3749
|
)
|
|
@@ -3214,7 +3798,7 @@ function truncate(value, decimals) {
|
|
|
3214
3798
|
const factor = Math.pow(10, decimals);
|
|
3215
3799
|
return (Math.floor(value * factor) / factor).toFixed(decimals);
|
|
3216
3800
|
}
|
|
3217
|
-
var
|
|
3801
|
+
var BLOCK_EXPLORERS2 = {
|
|
3218
3802
|
ethereum: "https://etherscan.io",
|
|
3219
3803
|
base: "https://basescan.org",
|
|
3220
3804
|
arbitrum: "https://arbiscan.io"
|
|
@@ -3685,7 +4269,7 @@ function SwapForm({
|
|
|
3685
4269
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3686
4270
|
"a",
|
|
3687
4271
|
{
|
|
3688
|
-
href: `${
|
|
4272
|
+
href: `${BLOCK_EXPLORERS2[chainId] || BLOCK_EXPLORERS2.ethereum}/tx/${lastTxHash}`,
|
|
3689
4273
|
target: "_blank",
|
|
3690
4274
|
rel: "noopener noreferrer",
|
|
3691
4275
|
style: { display: "flex", alignItems: "center", gap: "4px", color: "var(--compass-color-text-secondary)", fontSize: "0.75rem", textDecoration: "none" },
|
|
@@ -3875,8 +4459,7 @@ function MarketSelector({
|
|
|
3875
4459
|
},
|
|
3876
4460
|
children: [
|
|
3877
4461
|
getTypeLabel(selectedMarket.type),
|
|
3878
|
-
" \xB7 "
|
|
3879
|
-
formatTvl(selectedMarket.tvl)
|
|
4462
|
+
selectedMarket.type !== "aave" ? ` \xB7 ${formatTvl(selectedMarket.tvl)}` : ""
|
|
3880
4463
|
]
|
|
3881
4464
|
}
|
|
3882
4465
|
)
|
|
@@ -3982,8 +4565,7 @@ function MarketSelector({
|
|
|
3982
4565
|
},
|
|
3983
4566
|
children: [
|
|
3984
4567
|
getTypeLabel(market.type),
|
|
3985
|
-
" \xB7 "
|
|
3986
|
-
formatTvl(market.tvl)
|
|
4568
|
+
market.type !== "aave" ? ` \xB7 ${formatTvl(market.tvl)}` : ""
|
|
3987
4569
|
]
|
|
3988
4570
|
}
|
|
3989
4571
|
)
|
|
@@ -4012,7 +4594,7 @@ function MarketSelector({
|
|
|
4012
4594
|
)
|
|
4013
4595
|
] });
|
|
4014
4596
|
}
|
|
4015
|
-
var
|
|
4597
|
+
var BLOCK_EXPLORERS3 = {
|
|
4016
4598
|
ethereum: "https://etherscan.io",
|
|
4017
4599
|
base: "https://basescan.org",
|
|
4018
4600
|
arbitrum: "https://arbiscan.io"
|
|
@@ -4174,7 +4756,7 @@ function PositionCard({ position, chainId }) {
|
|
|
4174
4756
|
tx.txHash && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4175
4757
|
"a",
|
|
4176
4758
|
{
|
|
4177
|
-
href: `${
|
|
4759
|
+
href: `${BLOCK_EXPLORERS3[chainId || "ethereum"] || BLOCK_EXPLORERS3.ethereum}/tx/${tx.txHash}`,
|
|
4178
4760
|
target: "_blank",
|
|
4179
4761
|
rel: "noopener noreferrer",
|
|
4180
4762
|
style: { color: "var(--compass-color-text-tertiary)", lineHeight: 0 },
|
|
@@ -4308,161 +4890,29 @@ function EarningsModal({ isOpen, onClose, positions, totalEarned, isLoading, cha
|
|
|
4308
4890
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: {
|
|
4309
4891
|
fontSize: "0.8125rem",
|
|
4310
4892
|
fontWeight: 600,
|
|
4311
|
-
color: totalRealized >= 0 ? "var(--compass-color-success)" : "var(--compass-color-error)"
|
|
4312
|
-
}, children: [
|
|
4313
|
-
totalRealized >= 0 ? "+" : "",
|
|
4314
|
-
formatCurrency(totalRealized)
|
|
4315
|
-
] })
|
|
4316
|
-
] })
|
|
4317
|
-
] })
|
|
4318
|
-
] }),
|
|
4319
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: {
|
|
4320
|
-
flex: 1,
|
|
4321
|
-
overflowY: "auto",
|
|
4322
|
-
scrollbarWidth: "none",
|
|
4323
|
-
padding: "16px",
|
|
4324
|
-
display: "flex",
|
|
4325
|
-
flexDirection: "column",
|
|
4326
|
-
gap: "10px"
|
|
4327
|
-
}, children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", padding: "32px 0", color: "var(--compass-color-text-tertiary)", fontSize: "0.875rem" }, children: "Loading positions..." }) : positions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", padding: "32px 0" }, children: [
|
|
4328
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "var(--compass-color-text-secondary)", fontSize: "0.9375rem", margin: "0 0 4px" }, children: "No active positions yet" }),
|
|
4329
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "var(--compass-color-text-tertiary)", fontSize: "0.8125rem", margin: 0 }, children: "Deposit into a market to start earning" })
|
|
4330
|
-
] }) : positions.map((position) => /* @__PURE__ */ jsxRuntime.jsx(PositionCard, { position, chainId }, position.id)) })
|
|
4331
|
-
]
|
|
4332
|
-
}
|
|
4333
|
-
)
|
|
4334
|
-
}
|
|
4335
|
-
);
|
|
4336
|
-
}
|
|
4337
|
-
var BLOCK_EXPLORERS3 = {
|
|
4338
|
-
ethereum: "https://etherscan.io",
|
|
4339
|
-
base: "https://basescan.org",
|
|
4340
|
-
arbitrum: "https://arbiscan.io"
|
|
4341
|
-
};
|
|
4342
|
-
function TxStatus({ state }) {
|
|
4343
|
-
const { chainId } = useChain();
|
|
4344
|
-
if (state.status === "idle") return null;
|
|
4345
|
-
const explorer = BLOCK_EXPLORERS3[chainId] || BLOCK_EXPLORERS3.ethereum;
|
|
4346
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4347
|
-
"div",
|
|
4348
|
-
{
|
|
4349
|
-
className: "mt-4 p-4 border",
|
|
4350
|
-
style: {
|
|
4351
|
-
borderColor: "var(--compass-color-border)",
|
|
4352
|
-
borderRadius: "var(--compass-border-radius-xl)",
|
|
4353
|
-
fontFamily: "var(--compass-font-family)"
|
|
4354
|
-
},
|
|
4355
|
-
children: [
|
|
4356
|
-
state.status === "preparing" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
4357
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4358
|
-
lucideReact.Loader2,
|
|
4359
|
-
{
|
|
4360
|
-
className: "h-4 w-4 animate-spin",
|
|
4361
|
-
style: { color: "var(--compass-color-primary)" }
|
|
4362
|
-
}
|
|
4363
|
-
),
|
|
4364
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text-secondary)" }, children: "Preparing transaction..." })
|
|
4365
|
-
] }),
|
|
4366
|
-
state.status === "signing" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
4367
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4368
|
-
lucideReact.Loader2,
|
|
4369
|
-
{
|
|
4370
|
-
className: "h-4 w-4 animate-spin",
|
|
4371
|
-
style: { color: "var(--compass-color-warning)" }
|
|
4372
|
-
}
|
|
4373
|
-
),
|
|
4374
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text-secondary)" }, children: "Waiting for signature..." })
|
|
4375
|
-
] }),
|
|
4376
|
-
state.status === "broadcasting" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
4377
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4378
|
-
lucideReact.Loader2,
|
|
4379
|
-
{
|
|
4380
|
-
className: "h-4 w-4 animate-spin",
|
|
4381
|
-
style: { color: "var(--compass-color-primary)" }
|
|
4382
|
-
}
|
|
4383
|
-
),
|
|
4384
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text-secondary)" }, children: "Broadcasting transaction..." })
|
|
4385
|
-
] }),
|
|
4386
|
-
state.status === "submitted" && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4387
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
4388
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
4389
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4390
|
-
lucideReact.Loader2,
|
|
4391
|
-
{
|
|
4392
|
-
className: "h-4 w-4 animate-spin",
|
|
4393
|
-
style: { color: "var(--compass-color-primary)" }
|
|
4394
|
-
}
|
|
4395
|
-
),
|
|
4396
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text)" }, children: "Transaction submitted" })
|
|
4397
|
-
] }),
|
|
4398
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4399
|
-
"a",
|
|
4400
|
-
{
|
|
4401
|
-
href: `${explorer}/tx/${state.txHash}`,
|
|
4402
|
-
target: "_blank",
|
|
4403
|
-
rel: "noopener noreferrer",
|
|
4404
|
-
className: "flex items-center gap-1.5 text-xs hover:opacity-70 transition-opacity",
|
|
4405
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
4406
|
-
children: [
|
|
4407
|
-
"View on explorer",
|
|
4408
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-3 w-3" })
|
|
4409
|
-
]
|
|
4410
|
-
}
|
|
4411
|
-
)
|
|
4412
|
-
] }),
|
|
4413
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4414
|
-
"p",
|
|
4415
|
-
{
|
|
4416
|
-
className: "text-xs mt-2",
|
|
4417
|
-
style: { color: "var(--compass-color-text-tertiary)" },
|
|
4418
|
-
children: "Waiting for on-chain confirmation. Balances will update automatically."
|
|
4419
|
-
}
|
|
4420
|
-
)
|
|
4421
|
-
] }),
|
|
4422
|
-
state.status === "confirmed" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
4423
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
4424
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4425
|
-
lucideReact.CheckCircle,
|
|
4426
|
-
{
|
|
4427
|
-
className: "h-4 w-4",
|
|
4428
|
-
style: { color: "var(--compass-color-success)" }
|
|
4429
|
-
}
|
|
4430
|
-
),
|
|
4431
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-success)" }, children: "Transaction confirmed" })
|
|
4432
|
-
] }),
|
|
4433
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4434
|
-
"a",
|
|
4435
|
-
{
|
|
4436
|
-
href: `${explorer}/tx/${state.txHash}`,
|
|
4437
|
-
target: "_blank",
|
|
4438
|
-
rel: "noopener noreferrer",
|
|
4439
|
-
className: "flex items-center gap-1.5 text-xs hover:opacity-70 transition-opacity",
|
|
4440
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
4441
|
-
children: [
|
|
4442
|
-
"View on explorer",
|
|
4443
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-3 w-3" })
|
|
4444
|
-
]
|
|
4445
|
-
}
|
|
4446
|
-
)
|
|
4447
|
-
] }),
|
|
4448
|
-
state.status === "failed" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 text-sm", children: [
|
|
4449
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4450
|
-
lucideReact.XCircle,
|
|
4451
|
-
{
|
|
4452
|
-
className: "h-4 w-4 mt-0.5 shrink-0",
|
|
4453
|
-
style: { color: "var(--compass-color-error)" }
|
|
4454
|
-
}
|
|
4455
|
-
),
|
|
4456
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4457
|
-
"span",
|
|
4458
|
-
{
|
|
4459
|
-
className: "break-all",
|
|
4460
|
-
style: { color: "var(--compass-color-error)" },
|
|
4461
|
-
children: state.error
|
|
4462
|
-
}
|
|
4463
|
-
)
|
|
4464
|
-
] })
|
|
4465
|
-
]
|
|
4893
|
+
color: totalRealized >= 0 ? "var(--compass-color-success)" : "var(--compass-color-error)"
|
|
4894
|
+
}, children: [
|
|
4895
|
+
totalRealized >= 0 ? "+" : "",
|
|
4896
|
+
formatCurrency(totalRealized)
|
|
4897
|
+
] })
|
|
4898
|
+
] })
|
|
4899
|
+
] })
|
|
4900
|
+
] }),
|
|
4901
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: {
|
|
4902
|
+
flex: 1,
|
|
4903
|
+
overflowY: "auto",
|
|
4904
|
+
scrollbarWidth: "none",
|
|
4905
|
+
padding: "16px",
|
|
4906
|
+
display: "flex",
|
|
4907
|
+
flexDirection: "column",
|
|
4908
|
+
gap: "10px"
|
|
4909
|
+
}, children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", padding: "32px 0", color: "var(--compass-color-text-tertiary)", fontSize: "0.875rem" }, children: "Loading positions..." }) : positions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", padding: "32px 0" }, children: [
|
|
4910
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "var(--compass-color-text-secondary)", fontSize: "0.9375rem", margin: "0 0 4px" }, children: "No active positions yet" }),
|
|
4911
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "var(--compass-color-text-tertiary)", fontSize: "0.8125rem", margin: 0 }, children: "Deposit into a market to start earning" })
|
|
4912
|
+
] }) : positions.map((position) => /* @__PURE__ */ jsxRuntime.jsx(PositionCard, { position, chainId }, position.id)) })
|
|
4913
|
+
]
|
|
4914
|
+
}
|
|
4915
|
+
)
|
|
4466
4916
|
}
|
|
4467
4917
|
);
|
|
4468
4918
|
}
|
|
@@ -4470,7 +4920,7 @@ function truncate2(value, decimals) {
|
|
|
4470
4920
|
const factor = Math.pow(10, decimals);
|
|
4471
4921
|
return (Math.floor(value * factor) / factor).toFixed(decimals);
|
|
4472
4922
|
}
|
|
4473
|
-
var
|
|
4923
|
+
var EVM_CHAIN_IDS2 = {
|
|
4474
4924
|
ethereum: 1,
|
|
4475
4925
|
base: 8453,
|
|
4476
4926
|
arbitrum: 42161
|
|
@@ -4511,8 +4961,8 @@ function EarnAccount({
|
|
|
4511
4961
|
chain: chainProp,
|
|
4512
4962
|
height = "600px"
|
|
4513
4963
|
}) {
|
|
4514
|
-
const { address, isConnected, login, logout, signTypedData, switchChain, walletChainId } = useEmbeddableWallet();
|
|
4515
|
-
const { isDeployed } = useEarnAccount();
|
|
4964
|
+
const { address, isConnected, login, logout, signTypedData, switchChain, walletChainId, fundWallet, hasExternalWallet, sendTransaction } = useEmbeddableWallet();
|
|
4965
|
+
const { isDeployed, earnAccountAddress } = useEarnAccount();
|
|
4516
4966
|
const { chainId: contextChainId } = useChain();
|
|
4517
4967
|
const CHAIN_ID = chainProp || contextChainId;
|
|
4518
4968
|
const queryClient = reactQuery.useQueryClient();
|
|
@@ -4526,10 +4976,15 @@ function EarnAccount({
|
|
|
4526
4976
|
const [isTokenDropdownOpen, setIsTokenDropdownOpen] = react.useState(false);
|
|
4527
4977
|
const [isFundModalOpen, setIsFundModalOpen] = react.useState(false);
|
|
4528
4978
|
const [fundAmount, setFundAmount] = react.useState("");
|
|
4529
|
-
const [fundAction, setFundAction] = react.useState(
|
|
4979
|
+
const [fundAction, setFundAction] = react.useState(
|
|
4980
|
+
!hasExternalWallet && fundWallet ? "buy" : "deposit"
|
|
4981
|
+
);
|
|
4530
4982
|
const [fundStep, setFundStep] = react.useState("idle");
|
|
4531
4983
|
const [fundTxState, setFundTxState] = react.useState({ status: "idle" });
|
|
4532
4984
|
const fundPollRef = react.useRef(null);
|
|
4985
|
+
const showBuyTab = !!fundWallet;
|
|
4986
|
+
const showSendTab = !!sendTransaction && !hasExternalWallet;
|
|
4987
|
+
const fundBuyOnly = !hasExternalWallet && showBuyTab && !sendTransaction;
|
|
4533
4988
|
const actionPollRef = react.useRef(null);
|
|
4534
4989
|
const actionTimeoutRef = react.useRef(null);
|
|
4535
4990
|
const [isBalancesModalOpen, setIsBalancesModalOpen] = react.useState(false);
|
|
@@ -4569,7 +5024,7 @@ function EarnAccount({
|
|
|
4569
5024
|
const fundIsValid = Number(fundAmount) > 0 && !!address && isDeployed;
|
|
4570
5025
|
const fundPhase = getFundPhase(fundStep);
|
|
4571
5026
|
const ensureCorrectChain = react.useCallback(async () => {
|
|
4572
|
-
const targetChainId =
|
|
5027
|
+
const targetChainId = EVM_CHAIN_IDS2[CHAIN_ID];
|
|
4573
5028
|
if (!targetChainId) return;
|
|
4574
5029
|
if (walletChainId !== void 0 && walletChainId !== targetChainId) {
|
|
4575
5030
|
if (!switchChain) {
|
|
@@ -4593,7 +5048,7 @@ function EarnAccount({
|
|
|
4593
5048
|
return null;
|
|
4594
5049
|
}
|
|
4595
5050
|
},
|
|
4596
|
-
enabled: !!address && isFundModalOpen && fundAction === "deposit",
|
|
5051
|
+
enabled: !!address && hasExternalWallet && isFundModalOpen && fundAction === "deposit",
|
|
4597
5052
|
staleTime: 15 * 1e3
|
|
4598
5053
|
});
|
|
4599
5054
|
const walletBalance = walletBalanceQuery.data?.balance || "0";
|
|
@@ -4877,7 +5332,10 @@ function EarnAccount({
|
|
|
4877
5332
|
setFundTxState({ status: "failed", error: "Transaction reverted" });
|
|
4878
5333
|
return;
|
|
4879
5334
|
}
|
|
4880
|
-
} catch {
|
|
5335
|
+
} catch (err) {
|
|
5336
|
+
if (err instanceof TypeError && err.message.includes("fetch")) ; else {
|
|
5337
|
+
console.warn("[EarnAccount] Unexpected error polling tx receipt:", err);
|
|
5338
|
+
}
|
|
4881
5339
|
}
|
|
4882
5340
|
if (polls >= 24) {
|
|
4883
5341
|
clearFundPolling();
|
|
@@ -5672,31 +6130,7 @@ function EarnAccount({
|
|
|
5672
6130
|
]
|
|
5673
6131
|
}
|
|
5674
6132
|
)
|
|
5675
|
-
] })
|
|
5676
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex", style: { gap: "6px", marginTop: activeTab === "deposit" && maxAmount >= 10 ? "8px" : "0" }, children: activeTab === "deposit" && maxAmount > 0 && [10, 20, 30].filter((v) => v <= maxAmount).map((val) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5677
|
-
"button",
|
|
5678
|
-
{
|
|
5679
|
-
onClick: () => {
|
|
5680
|
-
setAmount(val.toString());
|
|
5681
|
-
setError(null);
|
|
5682
|
-
},
|
|
5683
|
-
disabled: isProcessing,
|
|
5684
|
-
className: "text-xs font-medium",
|
|
5685
|
-
style: {
|
|
5686
|
-
padding: "4px 12px",
|
|
5687
|
-
backgroundColor: parseFloat(amount) === val ? "transparent" : "var(--compass-color-surface)",
|
|
5688
|
-
border: parseFloat(amount) === val ? "1.5px solid var(--compass-color-primary)" : "1.5px solid var(--compass-color-border)",
|
|
5689
|
-
color: parseFloat(amount) === val ? "var(--compass-color-primary)" : "var(--compass-color-text-secondary)",
|
|
5690
|
-
borderRadius: "var(--compass-border-radius-xl)",
|
|
5691
|
-
transition: "all 150ms ease"
|
|
5692
|
-
},
|
|
5693
|
-
children: [
|
|
5694
|
-
"$",
|
|
5695
|
-
val
|
|
5696
|
-
]
|
|
5697
|
-
},
|
|
5698
|
-
val
|
|
5699
|
-
)) })
|
|
6133
|
+
] })
|
|
5700
6134
|
]
|
|
5701
6135
|
}
|
|
5702
6136
|
),
|
|
@@ -5792,13 +6226,13 @@ function EarnAccount({
|
|
|
5792
6226
|
onClose: () => {
|
|
5793
6227
|
setIsFundModalOpen(false);
|
|
5794
6228
|
setFundAmount("");
|
|
5795
|
-
setFundAction("deposit");
|
|
6229
|
+
setFundAction(fundBuyOnly ? "buy" : showSendTab ? "buy" : "deposit");
|
|
5796
6230
|
setFundStep("idle");
|
|
5797
6231
|
setFundTxState({ status: "idle" });
|
|
5798
6232
|
},
|
|
5799
|
-
title: "Transfer Funds",
|
|
6233
|
+
title: showSendTab ? "Manage Funds" : fundBuyOnly ? "Add Funds" : "Transfer Funds",
|
|
5800
6234
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
5801
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6235
|
+
fundBuyOnly ? null : /* @__PURE__ */ jsxRuntime.jsx(
|
|
5802
6236
|
"div",
|
|
5803
6237
|
{
|
|
5804
6238
|
className: "flex gap-1 p-1",
|
|
@@ -5807,7 +6241,9 @@ function EarnAccount({
|
|
|
5807
6241
|
borderRadius: "var(--compass-border-radius-lg)",
|
|
5808
6242
|
fontFamily: "var(--compass-font-family)"
|
|
5809
6243
|
},
|
|
5810
|
-
children: [
|
|
6244
|
+
children: [
|
|
6245
|
+
...showSendTab ? ["buy", "send"] : ["deposit", "withdraw", ...showBuyTab ? ["buy"] : []]
|
|
6246
|
+
].map((tab) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5811
6247
|
"button",
|
|
5812
6248
|
{
|
|
5813
6249
|
onClick: () => handleFundActionChange(tab),
|
|
@@ -5820,7 +6256,7 @@ function EarnAccount({
|
|
|
5820
6256
|
border: "none"
|
|
5821
6257
|
},
|
|
5822
6258
|
children: [
|
|
5823
|
-
tab === "deposit" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownLeft, { size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { size: 14 }),
|
|
6259
|
+
tab === "deposit" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownLeft, { size: 14 }) : tab === "withdraw" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { size: 14 }) : tab === "send" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { size: 14 }),
|
|
5824
6260
|
tab
|
|
5825
6261
|
]
|
|
5826
6262
|
},
|
|
@@ -5828,137 +6264,158 @@ function EarnAccount({
|
|
|
5828
6264
|
))
|
|
5829
6265
|
}
|
|
5830
6266
|
),
|
|
5831
|
-
|
|
5832
|
-
|
|
6267
|
+
fundAction === "send" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
6268
|
+
SendForm,
|
|
5833
6269
|
{
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
},
|
|
5840
|
-
children: [
|
|
5841
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5842
|
-
FundStepIndicator,
|
|
5843
|
-
{
|
|
5844
|
-
number: 1,
|
|
5845
|
-
label: "Approve",
|
|
5846
|
-
state: fundPhase > 1 ? "done" : fundPhase === 1 ? "active" : "pending"
|
|
5847
|
-
}
|
|
5848
|
-
),
|
|
5849
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5850
|
-
FundStepIndicator,
|
|
5851
|
-
{
|
|
5852
|
-
number: 2,
|
|
5853
|
-
label: "Transfer",
|
|
5854
|
-
state: fundStep === "confirmed" ? "done" : fundPhase > 1 ? "active" : "pending"
|
|
5855
|
-
}
|
|
5856
|
-
)
|
|
5857
|
-
]
|
|
6270
|
+
onComplete: () => {
|
|
6271
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
6272
|
+
queryClient.invalidateQueries({ queryKey: ["walletBalance"] });
|
|
6273
|
+
queryClient.invalidateQueries({ queryKey: ["walletTokenBalance"] });
|
|
6274
|
+
}
|
|
5858
6275
|
}
|
|
5859
|
-
)
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
"
|
|
6276
|
+
) : fundAction === "buy" || fundBuyOnly ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
6277
|
+
BuyForm,
|
|
6278
|
+
{
|
|
6279
|
+
targetAddress: earnAccountAddress || "",
|
|
6280
|
+
onComplete: () => {
|
|
6281
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
6282
|
+
queryClient.invalidateQueries({ queryKey: ["walletBalance"] });
|
|
6283
|
+
queryClient.invalidateQueries({ queryKey: ["walletTokenBalance"] });
|
|
6284
|
+
}
|
|
6285
|
+
}
|
|
6286
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6287
|
+
(fundIsBusy || fundStep === "confirmed") && fundAction === "deposit" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6288
|
+
"div",
|
|
5863
6289
|
{
|
|
5864
|
-
className: "
|
|
6290
|
+
className: "flex gap-3 p-3 text-xs",
|
|
5865
6291
|
style: {
|
|
5866
|
-
|
|
6292
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
6293
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
5867
6294
|
fontFamily: "var(--compass-font-family)"
|
|
5868
6295
|
},
|
|
5869
|
-
children:
|
|
6296
|
+
children: [
|
|
6297
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6298
|
+
FundStepIndicator,
|
|
6299
|
+
{
|
|
6300
|
+
number: 1,
|
|
6301
|
+
label: "Approve",
|
|
6302
|
+
state: fundPhase > 1 ? "done" : fundPhase === 1 ? "active" : "pending"
|
|
6303
|
+
}
|
|
6304
|
+
),
|
|
6305
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6306
|
+
FundStepIndicator,
|
|
6307
|
+
{
|
|
6308
|
+
number: 2,
|
|
6309
|
+
label: "Transfer",
|
|
6310
|
+
state: fundStep === "confirmed" ? "done" : fundPhase > 1 ? "active" : "pending"
|
|
6311
|
+
}
|
|
6312
|
+
)
|
|
6313
|
+
]
|
|
5870
6314
|
}
|
|
5871
6315
|
),
|
|
5872
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
6316
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5873
6317
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5874
|
-
"
|
|
6318
|
+
"label",
|
|
5875
6319
|
{
|
|
5876
|
-
|
|
5877
|
-
value: fundAmount,
|
|
5878
|
-
onChange: (e) => {
|
|
5879
|
-
setFundAmount(e.target.value);
|
|
5880
|
-
setFundTxState({ status: "idle" });
|
|
5881
|
-
},
|
|
5882
|
-
disabled: fundIsBusy,
|
|
5883
|
-
placeholder: "0.00",
|
|
5884
|
-
className: "w-full border px-3 py-2.5 pr-14 text-sm focus:outline-none disabled:opacity-50",
|
|
6320
|
+
className: "block text-sm mb-1.5",
|
|
5885
6321
|
style: {
|
|
5886
|
-
|
|
5887
|
-
borderColor: "var(--compass-color-border)",
|
|
5888
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
5889
|
-
color: "var(--compass-color-text)",
|
|
6322
|
+
color: "var(--compass-color-text-secondary)",
|
|
5890
6323
|
fontFamily: "var(--compass-font-family)"
|
|
5891
|
-
}
|
|
6324
|
+
},
|
|
6325
|
+
children: "Amount"
|
|
5892
6326
|
}
|
|
5893
6327
|
),
|
|
5894
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5895
|
-
|
|
6328
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
6329
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6330
|
+
"input",
|
|
6331
|
+
{
|
|
6332
|
+
type: "number",
|
|
6333
|
+
value: fundAmount,
|
|
6334
|
+
onChange: (e) => {
|
|
6335
|
+
setFundAmount(e.target.value);
|
|
6336
|
+
setFundTxState({ status: "idle" });
|
|
6337
|
+
},
|
|
6338
|
+
disabled: fundIsBusy,
|
|
6339
|
+
placeholder: "0.00",
|
|
6340
|
+
className: "w-full border px-3 py-2.5 pr-14 text-sm focus:outline-none disabled:opacity-50",
|
|
6341
|
+
style: {
|
|
6342
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
6343
|
+
borderColor: "var(--compass-color-border)",
|
|
6344
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
6345
|
+
color: "var(--compass-color-text)",
|
|
6346
|
+
fontFamily: "var(--compass-font-family)"
|
|
6347
|
+
}
|
|
6348
|
+
}
|
|
6349
|
+
),
|
|
6350
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6351
|
+
"span",
|
|
6352
|
+
{
|
|
6353
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-xs",
|
|
6354
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
6355
|
+
children: "USDC"
|
|
6356
|
+
}
|
|
6357
|
+
)
|
|
6358
|
+
] }),
|
|
6359
|
+
fundMaxBalance !== "0" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6360
|
+
"p",
|
|
5896
6361
|
{
|
|
5897
|
-
className: "
|
|
6362
|
+
className: "text-xs mt-1",
|
|
5898
6363
|
style: { color: "var(--compass-color-text-tertiary)" },
|
|
5899
|
-
children:
|
|
6364
|
+
children: [
|
|
6365
|
+
"Available:",
|
|
6366
|
+
" ",
|
|
6367
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6368
|
+
"button",
|
|
6369
|
+
{
|
|
6370
|
+
onClick: () => setFundAmount(truncate2(parseFloat(fundMaxBalance), 2)),
|
|
6371
|
+
disabled: fundIsBusy,
|
|
6372
|
+
style: { color: "var(--compass-color-primary)", background: "none", border: "none", padding: 0, cursor: "pointer", fontSize: "inherit" },
|
|
6373
|
+
children: [
|
|
6374
|
+
truncate2(parseFloat(fundMaxBalance), 2),
|
|
6375
|
+
" USDC"
|
|
6376
|
+
]
|
|
6377
|
+
}
|
|
6378
|
+
)
|
|
6379
|
+
]
|
|
5900
6380
|
}
|
|
5901
6381
|
)
|
|
5902
6382
|
] }),
|
|
5903
|
-
|
|
6383
|
+
!fundIsBusy && fundStep !== "confirmed" && fundStep !== "failed" && fundTxState.status === "idle" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5904
6384
|
"p",
|
|
5905
6385
|
{
|
|
5906
|
-
className: "text-xs
|
|
5907
|
-
style: {
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
"button",
|
|
5913
|
-
{
|
|
5914
|
-
onClick: () => setFundAmount(truncate2(parseFloat(fundMaxBalance), 2)),
|
|
5915
|
-
disabled: fundIsBusy,
|
|
5916
|
-
style: { color: "var(--compass-color-primary)", background: "none", border: "none", padding: 0, cursor: "pointer", fontSize: "inherit" },
|
|
5917
|
-
children: [
|
|
5918
|
-
truncate2(parseFloat(fundMaxBalance), 2),
|
|
5919
|
-
" USDC"
|
|
5920
|
-
]
|
|
5921
|
-
}
|
|
5922
|
-
)
|
|
5923
|
-
]
|
|
6386
|
+
className: "text-xs",
|
|
6387
|
+
style: {
|
|
6388
|
+
color: "var(--compass-color-text-tertiary)",
|
|
6389
|
+
fontFamily: "var(--compass-font-family)"
|
|
6390
|
+
},
|
|
6391
|
+
children: fundAction === "deposit" ? `Approves the token transfer, then transfers USDC from your ${!hasExternalWallet ? "embedded " : ""}wallet into your savings account. Requires 2 signatures.${!hasExternalWallet ? " Note: deposit and withdraw use your embedded wallet, not your bank account." : ""}` : `Moves USDC from your savings account back to your ${!hasExternalWallet ? "embedded " : ""}wallet. Requires 1 signature.${!hasExternalWallet ? " Gas fees are sponsored." : ""}`
|
|
5924
6392
|
}
|
|
5925
|
-
)
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
},
|
|
5952
|
-
children: fundIsBusy ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5953
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
5954
|
-
fundButtonLabel()
|
|
5955
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5956
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "h-4 w-4" }),
|
|
5957
|
-
fundAction === "deposit" ? "Transfer to Savings Account" : "Withdraw to Wallet"
|
|
5958
|
-
] })
|
|
5959
|
-
}
|
|
5960
|
-
),
|
|
5961
|
-
/* @__PURE__ */ jsxRuntime.jsx(TxStatus, { state: fundTxState })
|
|
6393
|
+
),
|
|
6394
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6395
|
+
"button",
|
|
6396
|
+
{
|
|
6397
|
+
onClick: handleFundTransfer,
|
|
6398
|
+
disabled: !fundIsValid || fundIsBusy,
|
|
6399
|
+
className: "w-full py-3 px-4 text-sm font-medium flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
6400
|
+
style: {
|
|
6401
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
6402
|
+
color: "var(--compass-color-primary-text)",
|
|
6403
|
+
borderRadius: "var(--compass-border-radius-xl)",
|
|
6404
|
+
fontFamily: "var(--compass-font-family)",
|
|
6405
|
+
transition: "all 200ms ease",
|
|
6406
|
+
border: "none"
|
|
6407
|
+
},
|
|
6408
|
+
children: fundIsBusy ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6409
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
6410
|
+
fundButtonLabel()
|
|
6411
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6412
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "h-4 w-4" }),
|
|
6413
|
+
fundAction === "deposit" ? "Transfer to Savings Account" : "Withdraw to Wallet"
|
|
6414
|
+
] })
|
|
6415
|
+
}
|
|
6416
|
+
),
|
|
6417
|
+
/* @__PURE__ */ jsxRuntime.jsx(TxStatus, { state: fundTxState })
|
|
6418
|
+
] })
|
|
5962
6419
|
] })
|
|
5963
6420
|
}
|
|
5964
6421
|
),
|
|
@@ -7765,19 +8222,24 @@ function getPhase(step) {
|
|
|
7765
8222
|
if (step === "approving" || step === "signing-approval") return 1;
|
|
7766
8223
|
return 2;
|
|
7767
8224
|
}
|
|
7768
|
-
var
|
|
8225
|
+
var EVM_CHAIN_IDS3 = {
|
|
7769
8226
|
ethereum: 1,
|
|
7770
8227
|
base: 8453,
|
|
7771
8228
|
arbitrum: 42161
|
|
7772
8229
|
};
|
|
7773
8230
|
function TopUpModal({ isOpen, onClose }) {
|
|
7774
|
-
const { address, signTypedData, switchChain, walletChainId } = useEmbeddableWallet();
|
|
8231
|
+
const { address, signTypedData, switchChain, walletChainId, fundWallet, hasExternalWallet, sendTransaction } = useEmbeddableWallet();
|
|
7775
8232
|
const { chainId } = useChain();
|
|
7776
|
-
const { isDeployed } = useCreditAccount();
|
|
8233
|
+
const { isDeployed, creditAccountAddress } = useCreditAccount();
|
|
7777
8234
|
const queryClient = reactQuery.useQueryClient();
|
|
7778
8235
|
const prices = useTokenPrices();
|
|
7779
8236
|
const token = "USDC";
|
|
7780
|
-
const [action, setAction] = react.useState(
|
|
8237
|
+
const [action, setAction] = react.useState(
|
|
8238
|
+
!hasExternalWallet && fundWallet ? "buy" : "deposit"
|
|
8239
|
+
);
|
|
8240
|
+
const showBuyTab = !!fundWallet;
|
|
8241
|
+
const showSendTab = !!sendTransaction && !hasExternalWallet;
|
|
8242
|
+
const buyOnly = !hasExternalWallet && showBuyTab && !sendTransaction;
|
|
7781
8243
|
const [amount, setAmount] = react.useState("");
|
|
7782
8244
|
const [step, setStep] = react.useState("idle");
|
|
7783
8245
|
const [txState, setTxState] = react.useState({ status: "idle" });
|
|
@@ -7826,7 +8288,7 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
7826
8288
|
const isValid = Number(amount) > 0 && !!address && isDeployed;
|
|
7827
8289
|
const isBusy = step === "approving" || step === "signing-approval" || step === "preparing-transfer" || step === "signing-transfer" || step === "executing";
|
|
7828
8290
|
const ensureCorrectChain = react.useCallback(async () => {
|
|
7829
|
-
const targetChainId =
|
|
8291
|
+
const targetChainId = EVM_CHAIN_IDS3[CHAIN_ID];
|
|
7830
8292
|
if (!targetChainId) return;
|
|
7831
8293
|
if (walletChainId !== void 0 && walletChainId !== targetChainId) {
|
|
7832
8294
|
if (!switchChain) {
|
|
@@ -8028,7 +8490,10 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
8028
8490
|
setTxState({ status: "failed", error: "Transaction reverted" });
|
|
8029
8491
|
return;
|
|
8030
8492
|
}
|
|
8031
|
-
} catch {
|
|
8493
|
+
} catch (err) {
|
|
8494
|
+
if (err instanceof TypeError && err.message.includes("fetch")) ; else {
|
|
8495
|
+
console.warn("[TopUpModal] Unexpected error polling tx receipt:", err);
|
|
8496
|
+
}
|
|
8032
8497
|
}
|
|
8033
8498
|
if (polls >= 24) {
|
|
8034
8499
|
clearPolling();
|
|
@@ -8064,8 +8529,8 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
8064
8529
|
color: "var(--compass-color-text-secondary)",
|
|
8065
8530
|
fontFamily: "var(--compass-font-family)"
|
|
8066
8531
|
};
|
|
8067
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ActionModal, { isOpen, onClose, title: "Transfer Funds", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
8068
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8532
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ActionModal, { isOpen, onClose, title: showSendTab ? "Manage Funds" : buyOnly ? "Add Funds" : "Transfer Funds", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
8533
|
+
!buyOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8069
8534
|
"div",
|
|
8070
8535
|
{
|
|
8071
8536
|
className: "flex gap-1 p-1",
|
|
@@ -8074,7 +8539,9 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
8074
8539
|
borderRadius: "var(--compass-border-radius-lg)",
|
|
8075
8540
|
fontFamily: "var(--compass-font-family)"
|
|
8076
8541
|
},
|
|
8077
|
-
children: [
|
|
8542
|
+
children: [
|
|
8543
|
+
...showSendTab ? ["buy", "send"] : showBuyTab ? ["deposit", "withdraw", "buy"] : ["deposit", "withdraw"]
|
|
8544
|
+
].map((tab) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8078
8545
|
"button",
|
|
8079
8546
|
{
|
|
8080
8547
|
onClick: () => handleActionChange(tab),
|
|
@@ -8086,7 +8553,7 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
8086
8553
|
borderRadius: "var(--compass-border-radius-md)"
|
|
8087
8554
|
},
|
|
8088
8555
|
children: [
|
|
8089
|
-
tab === "deposit" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownLeft, { size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { size: 14 }),
|
|
8556
|
+
tab === "deposit" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownLeft, { size: 14 }) : tab === "withdraw" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { size: 14 }) : tab === "send" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { size: 14 }),
|
|
8090
8557
|
tab
|
|
8091
8558
|
]
|
|
8092
8559
|
},
|
|
@@ -8094,122 +8561,143 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
8094
8561
|
))
|
|
8095
8562
|
}
|
|
8096
8563
|
),
|
|
8097
|
-
|
|
8098
|
-
|
|
8564
|
+
action === "send" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8565
|
+
SendForm,
|
|
8099
8566
|
{
|
|
8100
|
-
|
|
8101
|
-
|
|
8102
|
-
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
}
|
|
8106
|
-
|
|
8567
|
+
product: "credit",
|
|
8568
|
+
productAccountAddress: creditAccountAddress || void 0,
|
|
8569
|
+
onComplete: () => {
|
|
8570
|
+
queryClient.invalidateQueries({ queryKey: ["creditBalances"] });
|
|
8571
|
+
queryClient.invalidateQueries({ queryKey: ["walletTokenBalance"] });
|
|
8572
|
+
}
|
|
8573
|
+
}
|
|
8574
|
+
) : action === "buy" || buyOnly ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8575
|
+
BuyForm,
|
|
8576
|
+
{
|
|
8577
|
+
targetAddress: creditAccountAddress || "",
|
|
8578
|
+
onComplete: () => {
|
|
8579
|
+
queryClient.invalidateQueries({ queryKey: ["creditBalances"] });
|
|
8580
|
+
queryClient.invalidateQueries({ queryKey: ["walletTokenBalance"] });
|
|
8581
|
+
}
|
|
8582
|
+
}
|
|
8583
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8584
|
+
(isBusy || step === "confirmed") && action === "deposit" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8585
|
+
"div",
|
|
8586
|
+
{
|
|
8587
|
+
className: "flex gap-3 p-3 text-xs",
|
|
8588
|
+
style: {
|
|
8589
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
8590
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
8591
|
+
fontFamily: "var(--compass-font-family)"
|
|
8592
|
+
},
|
|
8593
|
+
children: [
|
|
8594
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8595
|
+
StepIndicator,
|
|
8596
|
+
{
|
|
8597
|
+
number: 1,
|
|
8598
|
+
label: "Approve",
|
|
8599
|
+
state: phase > 1 ? "done" : phase === 1 ? "active" : "pending"
|
|
8600
|
+
}
|
|
8601
|
+
),
|
|
8602
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8603
|
+
StepIndicator,
|
|
8604
|
+
{
|
|
8605
|
+
number: 2,
|
|
8606
|
+
label: "Transfer",
|
|
8607
|
+
state: step === "confirmed" ? "done" : phase > 1 ? "active" : "pending"
|
|
8608
|
+
}
|
|
8609
|
+
)
|
|
8610
|
+
]
|
|
8611
|
+
}
|
|
8612
|
+
),
|
|
8613
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
8614
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm mb-1.5", style: labelStyle, children: "Amount" }),
|
|
8615
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
8107
8616
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8108
|
-
|
|
8617
|
+
"input",
|
|
8109
8618
|
{
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8619
|
+
type: "number",
|
|
8620
|
+
value: amount,
|
|
8621
|
+
onChange: (e) => {
|
|
8622
|
+
setAmount(e.target.value);
|
|
8623
|
+
setTxState({ status: "idle" });
|
|
8624
|
+
},
|
|
8625
|
+
disabled: isBusy,
|
|
8626
|
+
placeholder: "0.00",
|
|
8627
|
+
className: "w-full border px-3 py-2.5 pr-14 text-sm focus:outline-none disabled:opacity-50",
|
|
8628
|
+
style: inputStyle
|
|
8113
8629
|
}
|
|
8114
8630
|
),
|
|
8115
8631
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8116
|
-
|
|
8632
|
+
"span",
|
|
8117
8633
|
{
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8634
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-xs",
|
|
8635
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
8636
|
+
children: token
|
|
8121
8637
|
}
|
|
8122
8638
|
)
|
|
8123
|
-
]
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
8127
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm mb-1.5", style: labelStyle, children: "Amount" }),
|
|
8128
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
8129
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8130
|
-
"input",
|
|
8639
|
+
] }),
|
|
8640
|
+
formatUsdEstimate(amount, token, prices) && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8641
|
+
"p",
|
|
8131
8642
|
{
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
placeholder: "0.00",
|
|
8140
|
-
className: "w-full border px-3 py-2.5 pr-14 text-sm focus:outline-none disabled:opacity-50",
|
|
8141
|
-
style: inputStyle
|
|
8643
|
+
className: "text-xs mt-1",
|
|
8644
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
8645
|
+
children: [
|
|
8646
|
+
"\u2248",
|
|
8647
|
+
" ",
|
|
8648
|
+
formatUsdEstimate(amount, token, prices)
|
|
8649
|
+
]
|
|
8142
8650
|
}
|
|
8143
8651
|
),
|
|
8144
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8145
|
-
"
|
|
8652
|
+
maxBalance && maxBalance !== "0" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8653
|
+
"p",
|
|
8146
8654
|
{
|
|
8147
|
-
className: "
|
|
8655
|
+
className: "text-xs mt-1",
|
|
8148
8656
|
style: { color: "var(--compass-color-text-tertiary)" },
|
|
8149
|
-
children:
|
|
8657
|
+
children: [
|
|
8658
|
+
"Available: ",
|
|
8659
|
+
truncate6(parseFloat(maxBalance), 2),
|
|
8660
|
+
" ",
|
|
8661
|
+
token
|
|
8662
|
+
]
|
|
8150
8663
|
}
|
|
8151
8664
|
)
|
|
8152
8665
|
] }),
|
|
8153
|
-
|
|
8666
|
+
!isBusy && step !== "confirmed" && step !== "failed" && txState.status === "idle" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8154
8667
|
"p",
|
|
8155
8668
|
{
|
|
8156
|
-
className: "text-xs
|
|
8157
|
-
style: {
|
|
8158
|
-
|
|
8159
|
-
"
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
]
|
|
8669
|
+
className: "text-xs",
|
|
8670
|
+
style: {
|
|
8671
|
+
color: "var(--compass-color-text-tertiary)",
|
|
8672
|
+
fontFamily: "var(--compass-font-family)"
|
|
8673
|
+
},
|
|
8674
|
+
children: action === "deposit" ? `Approves the token transfer, then transfers tokens from your ${!hasExternalWallet ? "embedded " : ""}wallet into your credit account. Requires 2 signatures.${!hasExternalWallet ? " Note: deposit and withdraw use your embedded wallet, not your bank account." : ""}` : `Moves tokens from your credit account back to your ${!hasExternalWallet ? "embedded " : ""}wallet. Requires 1 signature.${!hasExternalWallet ? " Gas fees are sponsored." : ""}`
|
|
8163
8675
|
}
|
|
8164
8676
|
),
|
|
8165
|
-
|
|
8166
|
-
"
|
|
8677
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8678
|
+
"button",
|
|
8167
8679
|
{
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8175
|
-
|
|
8680
|
+
onClick: handleTransfer,
|
|
8681
|
+
disabled: !isValid || isBusy,
|
|
8682
|
+
className: "w-full py-3 px-4 text-sm font-medium flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
8683
|
+
style: {
|
|
8684
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
8685
|
+
color: "white",
|
|
8686
|
+
borderRadius: "var(--compass-border-radius-xl)",
|
|
8687
|
+
fontFamily: "var(--compass-font-family)",
|
|
8688
|
+
transition: "var(--compass-transition-normal)"
|
|
8689
|
+
},
|
|
8690
|
+
children: isBusy ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8691
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
8692
|
+
buttonLabel()
|
|
8693
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8694
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "h-4 w-4" }),
|
|
8695
|
+
action === "deposit" ? "Transfer to Credit Account" : "Withdraw to Wallet"
|
|
8696
|
+
] })
|
|
8176
8697
|
}
|
|
8177
|
-
)
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
"p",
|
|
8181
|
-
{
|
|
8182
|
-
className: "text-xs",
|
|
8183
|
-
style: {
|
|
8184
|
-
color: "var(--compass-color-text-tertiary)",
|
|
8185
|
-
fontFamily: "var(--compass-font-family)"
|
|
8186
|
-
},
|
|
8187
|
-
children: action === "deposit" ? "Approves the token transfer, then transfers tokens from your wallet into your credit account. Requires 2 signatures." : "Transfers tokens from your credit account back to your wallet. Requires 1 signature."
|
|
8188
|
-
}
|
|
8189
|
-
),
|
|
8190
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8191
|
-
"button",
|
|
8192
|
-
{
|
|
8193
|
-
onClick: handleTransfer,
|
|
8194
|
-
disabled: !isValid || isBusy,
|
|
8195
|
-
className: "w-full py-3 px-4 text-sm font-medium flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
8196
|
-
style: {
|
|
8197
|
-
backgroundColor: "var(--compass-color-primary)",
|
|
8198
|
-
color: "white",
|
|
8199
|
-
borderRadius: "var(--compass-border-radius-xl)",
|
|
8200
|
-
fontFamily: "var(--compass-font-family)",
|
|
8201
|
-
transition: "var(--compass-transition-normal)"
|
|
8202
|
-
},
|
|
8203
|
-
children: isBusy ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8204
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
8205
|
-
buttonLabel()
|
|
8206
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8207
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "h-4 w-4" }),
|
|
8208
|
-
action === "deposit" ? "Transfer to Credit Account" : "Withdraw to Wallet"
|
|
8209
|
-
] })
|
|
8210
|
-
}
|
|
8211
|
-
),
|
|
8212
|
-
/* @__PURE__ */ jsxRuntime.jsx(TxStatus, { state: txState })
|
|
8698
|
+
),
|
|
8699
|
+
/* @__PURE__ */ jsxRuntime.jsx(TxStatus, { state: txState })
|
|
8700
|
+
] })
|
|
8213
8701
|
] }) });
|
|
8214
8702
|
}
|
|
8215
8703
|
function StepIndicator({
|
|
@@ -8237,9 +8725,10 @@ function CreditSwapModal({ isOpen, onClose }) {
|
|
|
8237
8725
|
const prices = useTokenPrices();
|
|
8238
8726
|
const { txState, executeBundle, resetState } = useCreditBundle();
|
|
8239
8727
|
const tokens = CREDIT_TOKENS;
|
|
8240
|
-
const fromToken = "USDC";
|
|
8241
|
-
const [toToken, setToToken] = react.useState(tokens.find((t) => t !==
|
|
8728
|
+
const [fromToken, setFromToken] = react.useState("USDC");
|
|
8729
|
+
const [toToken, setToToken] = react.useState(tokens.find((t) => t !== "USDC") || tokens[0] || "WETH");
|
|
8242
8730
|
const [fromAmount, setFromAmount] = react.useState("");
|
|
8731
|
+
const [isFromOpen, setIsFromOpen] = react.useState(false);
|
|
8243
8732
|
const [isToOpen, setIsToOpen] = react.useState(false);
|
|
8244
8733
|
react.useEffect(() => {
|
|
8245
8734
|
if (isOpen) {
|
|
@@ -8247,6 +8736,12 @@ function CreditSwapModal({ isOpen, onClose }) {
|
|
|
8247
8736
|
resetState();
|
|
8248
8737
|
}
|
|
8249
8738
|
}, [isOpen]);
|
|
8739
|
+
react.useEffect(() => {
|
|
8740
|
+
if (fromToken === toToken) {
|
|
8741
|
+
const alt = tokens.find((t) => t !== fromToken);
|
|
8742
|
+
if (alt) setToToken(alt);
|
|
8743
|
+
}
|
|
8744
|
+
}, [fromToken, toToken, tokens]);
|
|
8250
8745
|
const fromBalance = balances?.find((b) => b.tokenSymbol === fromToken);
|
|
8251
8746
|
const fromBalanceAmount = fromBalance ? parseFloat(fromBalance.amount) : 0;
|
|
8252
8747
|
const estimatedOutput = (() => {
|
|
@@ -8325,24 +8820,76 @@ function CreditSwapModal({ isOpen, onClose }) {
|
|
|
8325
8820
|
}
|
|
8326
8821
|
}
|
|
8327
8822
|
),
|
|
8328
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8329
|
-
|
|
8330
|
-
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
|
|
8334
|
-
|
|
8335
|
-
|
|
8336
|
-
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8823
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", flexShrink: 0 }, children: [
|
|
8824
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8825
|
+
"button",
|
|
8826
|
+
{
|
|
8827
|
+
onClick: () => setIsFromOpen(!isFromOpen),
|
|
8828
|
+
disabled: isBusy,
|
|
8829
|
+
style: {
|
|
8830
|
+
display: "flex",
|
|
8831
|
+
alignItems: "center",
|
|
8832
|
+
fontWeight: 500,
|
|
8833
|
+
backgroundColor: "var(--compass-color-background)",
|
|
8834
|
+
border: "1.5px solid var(--compass-color-border)",
|
|
8835
|
+
color: "var(--compass-color-text)",
|
|
8836
|
+
borderRadius: "var(--compass-border-radius-md)",
|
|
8837
|
+
padding: "4px 8px",
|
|
8838
|
+
gap: "4px",
|
|
8839
|
+
fontSize: "0.8125rem",
|
|
8840
|
+
cursor: isBusy ? "not-allowed" : "pointer"
|
|
8841
|
+
},
|
|
8842
|
+
children: [
|
|
8843
|
+
fromToken,
|
|
8844
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 12, style: { color: "var(--compass-color-text-tertiary)" } })
|
|
8845
|
+
]
|
|
8846
|
+
}
|
|
8847
|
+
),
|
|
8848
|
+
isFromOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8849
|
+
"div",
|
|
8850
|
+
{
|
|
8851
|
+
style: {
|
|
8852
|
+
position: "absolute",
|
|
8853
|
+
right: 0,
|
|
8854
|
+
top: "100%",
|
|
8855
|
+
marginTop: "4px",
|
|
8856
|
+
zIndex: 10,
|
|
8857
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
8858
|
+
border: "1.5px solid var(--compass-color-border)",
|
|
8859
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
8860
|
+
boxShadow: "var(--compass-shadow-md)",
|
|
8861
|
+
minWidth: "120px",
|
|
8862
|
+
maxHeight: "200px",
|
|
8863
|
+
overflowY: "auto",
|
|
8864
|
+
scrollbarWidth: "none"
|
|
8865
|
+
},
|
|
8866
|
+
children: tokens.filter((t) => t !== toToken).map((token) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8867
|
+
"button",
|
|
8868
|
+
{
|
|
8869
|
+
onClick: () => {
|
|
8870
|
+
setFromToken(token);
|
|
8871
|
+
setFromAmount("");
|
|
8872
|
+
setIsFromOpen(false);
|
|
8873
|
+
},
|
|
8874
|
+
style: {
|
|
8875
|
+
display: "block",
|
|
8876
|
+
width: "100%",
|
|
8877
|
+
textAlign: "left",
|
|
8878
|
+
padding: "6px 10px",
|
|
8879
|
+
fontSize: "0.8125rem",
|
|
8880
|
+
fontWeight: 500,
|
|
8881
|
+
color: token === fromToken ? "var(--compass-color-primary)" : "var(--compass-color-text)",
|
|
8882
|
+
backgroundColor: token === fromToken ? "var(--compass-color-primary-muted)" : "transparent",
|
|
8883
|
+
border: "none",
|
|
8884
|
+
cursor: "pointer"
|
|
8885
|
+
},
|
|
8886
|
+
children: token
|
|
8887
|
+
},
|
|
8888
|
+
token
|
|
8889
|
+
))
|
|
8890
|
+
}
|
|
8891
|
+
)
|
|
8892
|
+
] })
|
|
8346
8893
|
] })
|
|
8347
8894
|
]
|
|
8348
8895
|
}
|
|
@@ -8549,7 +9096,7 @@ function CreditAccount({
|
|
|
8549
9096
|
onBorrow: _onBorrow,
|
|
8550
9097
|
onRepay: _onRepay
|
|
8551
9098
|
}) {
|
|
8552
|
-
const { address, isConnected, login, logout } = useEmbeddableWallet();
|
|
9099
|
+
const { address, isConnected, login, logout, hasExternalWallet } = useEmbeddableWallet();
|
|
8553
9100
|
const { isDeployed, creditAccountAddress } = useCreditAccount();
|
|
8554
9101
|
const { chainId } = useChain();
|
|
8555
9102
|
const { data: positions, isLoading: positionsLoading } = useCreditPositions();
|
|
@@ -8575,6 +9122,25 @@ function CreditAccount({
|
|
|
8575
9122
|
return { ...b, usdValue };
|
|
8576
9123
|
}).filter((b) => b.usdValue >= 0.01).sort((a, b) => a.tokenSymbol.localeCompare(b.tokenSymbol));
|
|
8577
9124
|
const totalIdleUsd = balancesWithUsd.reduce((sum, b) => sum + b.usdValue, 0);
|
|
9125
|
+
const { data: walletBalance } = reactQuery.useQuery({
|
|
9126
|
+
queryKey: ["embeddedWalletBalance", chainId, address, "USDC"],
|
|
9127
|
+
queryFn: async () => {
|
|
9128
|
+
if (!address) return "0";
|
|
9129
|
+
try {
|
|
9130
|
+
const response = await fetch(
|
|
9131
|
+
`/api/compass/token/balance?chain=${chainId}&token=USDC&address=${address}`
|
|
9132
|
+
);
|
|
9133
|
+
if (response.ok) {
|
|
9134
|
+
const data = await response.json();
|
|
9135
|
+
return data.balance || "0";
|
|
9136
|
+
}
|
|
9137
|
+
} catch {
|
|
9138
|
+
}
|
|
9139
|
+
return "0";
|
|
9140
|
+
},
|
|
9141
|
+
enabled: !!address && hasExternalWallet,
|
|
9142
|
+
staleTime: 30 * 1e3
|
|
9143
|
+
});
|
|
8578
9144
|
const totalInterestEarnedUsd = (() => {
|
|
8579
9145
|
if (!positions) return 0;
|
|
8580
9146
|
let total = 0;
|
|
@@ -9575,6 +10141,7 @@ function PositionDetailModal({ position, onClose }) {
|
|
|
9575
10141
|
const isPendle = position.venue === "pendle";
|
|
9576
10142
|
const duration = formatDuration(position.entryTimestamp);
|
|
9577
10143
|
const expiryDate = formatExpiryUTC(position.expiry);
|
|
10144
|
+
const modalRef = react.useRef(null);
|
|
9578
10145
|
react.useEffect(() => {
|
|
9579
10146
|
const handleKeyDown = (e) => {
|
|
9580
10147
|
if (e.key === "Escape") onClose();
|
|
@@ -9582,296 +10149,312 @@ function PositionDetailModal({ position, onClose }) {
|
|
|
9582
10149
|
document.addEventListener("keydown", handleKeyDown);
|
|
9583
10150
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
9584
10151
|
}, [onClose]);
|
|
10152
|
+
const handleOverlayWheel = react.useCallback((e) => {
|
|
10153
|
+
if (modalRef.current && !modalRef.current.contains(e.target)) {
|
|
10154
|
+
window.scrollBy(0, e.deltaY);
|
|
10155
|
+
}
|
|
10156
|
+
}, []);
|
|
9585
10157
|
const hasStats = position.apy || isPendle && (duration || expiryDate) || position.pnl;
|
|
9586
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
10158
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9587
10159
|
"div",
|
|
9588
10160
|
{
|
|
9589
10161
|
className: "fixed inset-0 z-50 flex items-center justify-center p-4",
|
|
9590
|
-
|
|
10162
|
+
onWheel: handleOverlayWheel,
|
|
9591
10163
|
onClick: onClose,
|
|
9592
|
-
children:
|
|
9593
|
-
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
backgroundColor: "
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
|
|
9606
|
-
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9613
|
-
|
|
9614
|
-
"h2",
|
|
9615
|
-
{
|
|
9616
|
-
className: "font-semibold text-lg",
|
|
9617
|
-
style: { color: "var(--compass-color-text)" },
|
|
9618
|
-
children: position.name
|
|
9619
|
-
}
|
|
9620
|
-
),
|
|
9621
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9622
|
-
"p",
|
|
9623
|
-
{
|
|
9624
|
-
className: "text-sm",
|
|
9625
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
9626
|
-
children: position.venueName
|
|
9627
|
-
}
|
|
9628
|
-
)
|
|
9629
|
-
] }),
|
|
9630
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9631
|
-
"button",
|
|
9632
|
-
{
|
|
9633
|
-
onClick: onClose,
|
|
9634
|
-
className: "p-2 rounded-lg hover:opacity-80 transition-opacity",
|
|
9635
|
-
style: { backgroundColor: "var(--compass-color-background)" },
|
|
9636
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 20, style: { color: "var(--compass-color-text-secondary)" } })
|
|
9637
|
-
}
|
|
9638
|
-
)
|
|
9639
|
-
]
|
|
9640
|
-
}
|
|
9641
|
-
),
|
|
9642
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 border-b", style: { borderColor: "var(--compass-color-border)" }, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
9643
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9644
|
-
"p",
|
|
9645
|
-
{
|
|
9646
|
-
className: "text-sm mb-1",
|
|
9647
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
9648
|
-
children: "Current Balance"
|
|
9649
|
-
}
|
|
9650
|
-
),
|
|
9651
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9652
|
-
"p",
|
|
9653
|
-
{
|
|
9654
|
-
className: "text-3xl font-bold",
|
|
9655
|
-
style: { color: "var(--compass-color-text)" },
|
|
9656
|
-
children: formatUSD(position.balanceUsd)
|
|
9657
|
-
}
|
|
9658
|
-
),
|
|
9659
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9660
|
-
"p",
|
|
9661
|
-
{
|
|
9662
|
-
className: "text-sm font-mono mt-1",
|
|
9663
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
9664
|
-
children: [
|
|
9665
|
-
formatAmount(position.balance),
|
|
9666
|
-
" ",
|
|
9667
|
-
position.assetSymbol
|
|
9668
|
-
]
|
|
9669
|
-
}
|
|
9670
|
-
)
|
|
9671
|
-
] }) }),
|
|
9672
|
-
hasStats && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3 p-4 border-b", style: { borderColor: "var(--compass-color-border)" }, children: [
|
|
9673
|
-
position.apy && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9674
|
-
"div",
|
|
9675
|
-
{
|
|
9676
|
-
className: "p-3 rounded-lg",
|
|
9677
|
-
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
9678
|
-
children: [
|
|
9679
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
9680
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Percent, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
9681
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "APY" })
|
|
9682
|
-
] }),
|
|
9683
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9684
|
-
"p",
|
|
9685
|
-
{
|
|
9686
|
-
className: "font-semibold",
|
|
9687
|
-
style: { color: "var(--compass-color-success)" },
|
|
9688
|
-
children: [
|
|
9689
|
-
parseFloat(position.apy).toFixed(2),
|
|
9690
|
-
"%"
|
|
9691
|
-
]
|
|
9692
|
-
}
|
|
9693
|
-
)
|
|
9694
|
-
]
|
|
9695
|
-
}
|
|
9696
|
-
),
|
|
9697
|
-
isPendle && duration && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9698
|
-
"div",
|
|
9699
|
-
{
|
|
9700
|
-
className: "p-3 rounded-lg",
|
|
9701
|
-
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
9702
|
-
children: [
|
|
9703
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
9704
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
9705
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "Duration" })
|
|
9706
|
-
] }),
|
|
9707
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9708
|
-
"p",
|
|
9709
|
-
{
|
|
9710
|
-
className: "font-semibold",
|
|
9711
|
-
style: { color: "var(--compass-color-text)" },
|
|
9712
|
-
children: duration
|
|
9713
|
-
}
|
|
9714
|
-
)
|
|
9715
|
-
]
|
|
9716
|
-
}
|
|
9717
|
-
),
|
|
9718
|
-
isPendle && expiryDate && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10164
|
+
children: [
|
|
10165
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10166
|
+
"div",
|
|
10167
|
+
{
|
|
10168
|
+
className: "absolute inset-0",
|
|
10169
|
+
style: { backgroundColor: "rgba(0, 0, 0, 0.7)" }
|
|
10170
|
+
}
|
|
10171
|
+
),
|
|
10172
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10173
|
+
"div",
|
|
10174
|
+
{
|
|
10175
|
+
ref: modalRef,
|
|
10176
|
+
className: "relative w-full max-w-md rounded-xl border max-h-[85vh] overflow-y-auto",
|
|
10177
|
+
style: {
|
|
10178
|
+
backgroundColor: "var(--compass-color-background)",
|
|
10179
|
+
borderColor: "var(--compass-color-border)",
|
|
10180
|
+
scrollbarWidth: "none",
|
|
10181
|
+
overscrollBehavior: "contain"
|
|
10182
|
+
},
|
|
10183
|
+
onClick: (e) => e.stopPropagation(),
|
|
10184
|
+
children: [
|
|
10185
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9719
10186
|
"div",
|
|
9720
10187
|
{
|
|
9721
|
-
className: "p-
|
|
9722
|
-
style: {
|
|
10188
|
+
className: "sticky top-0 flex items-center justify-between p-4 border-b",
|
|
10189
|
+
style: {
|
|
10190
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
10191
|
+
borderColor: "var(--compass-color-border)"
|
|
10192
|
+
},
|
|
9723
10193
|
children: [
|
|
9724
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
9725
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9726
|
-
|
|
10194
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
10195
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10196
|
+
"h2",
|
|
10197
|
+
{
|
|
10198
|
+
className: "font-semibold text-lg",
|
|
10199
|
+
style: { color: "var(--compass-color-text)" },
|
|
10200
|
+
children: position.name
|
|
10201
|
+
}
|
|
10202
|
+
),
|
|
10203
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10204
|
+
"p",
|
|
10205
|
+
{
|
|
10206
|
+
className: "text-sm",
|
|
10207
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
10208
|
+
children: position.venueName
|
|
10209
|
+
}
|
|
10210
|
+
)
|
|
9727
10211
|
] }),
|
|
9728
10212
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9729
|
-
"
|
|
10213
|
+
"button",
|
|
9730
10214
|
{
|
|
9731
|
-
|
|
9732
|
-
|
|
9733
|
-
|
|
10215
|
+
onClick: onClose,
|
|
10216
|
+
className: "p-2 rounded-lg hover:opacity-80 transition-opacity",
|
|
10217
|
+
style: { backgroundColor: "var(--compass-color-background)" },
|
|
10218
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 20, style: { color: "var(--compass-color-text-secondary)" } })
|
|
9734
10219
|
}
|
|
9735
10220
|
)
|
|
9736
10221
|
]
|
|
9737
10222
|
}
|
|
9738
10223
|
),
|
|
9739
|
-
|
|
9740
|
-
|
|
9741
|
-
|
|
9742
|
-
|
|
9743
|
-
|
|
9744
|
-
|
|
9745
|
-
|
|
9746
|
-
|
|
9747
|
-
|
|
9748
|
-
|
|
9749
|
-
|
|
9750
|
-
|
|
10224
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 border-b", style: { borderColor: "var(--compass-color-border)" }, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
10225
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10226
|
+
"p",
|
|
10227
|
+
{
|
|
10228
|
+
className: "text-sm mb-1",
|
|
10229
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
10230
|
+
children: "Current Balance"
|
|
10231
|
+
}
|
|
10232
|
+
),
|
|
10233
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10234
|
+
"p",
|
|
10235
|
+
{
|
|
10236
|
+
className: "text-3xl font-bold",
|
|
10237
|
+
style: { color: "var(--compass-color-text)" },
|
|
10238
|
+
children: formatUSD(position.balanceUsd)
|
|
10239
|
+
}
|
|
10240
|
+
),
|
|
10241
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10242
|
+
"p",
|
|
10243
|
+
{
|
|
10244
|
+
className: "text-sm font-mono mt-1",
|
|
10245
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
10246
|
+
children: [
|
|
10247
|
+
formatAmount(position.balance),
|
|
10248
|
+
" ",
|
|
10249
|
+
position.assetSymbol
|
|
10250
|
+
]
|
|
10251
|
+
}
|
|
10252
|
+
)
|
|
10253
|
+
] }) }),
|
|
10254
|
+
hasStats && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3 p-4 border-b", style: { borderColor: "var(--compass-color-border)" }, children: [
|
|
10255
|
+
position.apy && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10256
|
+
"div",
|
|
10257
|
+
{
|
|
10258
|
+
className: "p-3 rounded-lg",
|
|
10259
|
+
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
10260
|
+
children: [
|
|
10261
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
10262
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Percent, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
10263
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "APY" })
|
|
10264
|
+
] }),
|
|
10265
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10266
|
+
"p",
|
|
10267
|
+
{
|
|
10268
|
+
className: "font-semibold",
|
|
10269
|
+
style: { color: "var(--compass-color-success)" },
|
|
10270
|
+
children: [
|
|
10271
|
+
parseFloat(position.apy).toFixed(2),
|
|
10272
|
+
"%"
|
|
10273
|
+
]
|
|
10274
|
+
}
|
|
10275
|
+
)
|
|
10276
|
+
]
|
|
10277
|
+
}
|
|
10278
|
+
),
|
|
10279
|
+
isPendle && duration && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10280
|
+
"div",
|
|
10281
|
+
{
|
|
10282
|
+
className: "p-3 rounded-lg",
|
|
10283
|
+
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
10284
|
+
children: [
|
|
10285
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
10286
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
10287
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "Duration" })
|
|
10288
|
+
] }),
|
|
10289
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10290
|
+
"p",
|
|
10291
|
+
{
|
|
10292
|
+
className: "font-semibold",
|
|
10293
|
+
style: { color: "var(--compass-color-text)" },
|
|
10294
|
+
children: duration
|
|
10295
|
+
}
|
|
10296
|
+
)
|
|
10297
|
+
]
|
|
10298
|
+
}
|
|
10299
|
+
),
|
|
10300
|
+
isPendle && expiryDate && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10301
|
+
"div",
|
|
10302
|
+
{
|
|
10303
|
+
className: "p-3 rounded-lg",
|
|
10304
|
+
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
10305
|
+
children: [
|
|
10306
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
10307
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
10308
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "Expiry (UTC)" })
|
|
10309
|
+
] }),
|
|
10310
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10311
|
+
"p",
|
|
10312
|
+
{
|
|
10313
|
+
className: "font-semibold",
|
|
10314
|
+
style: { color: "var(--compass-color-text)" },
|
|
10315
|
+
children: expiryDate
|
|
10316
|
+
}
|
|
10317
|
+
)
|
|
10318
|
+
]
|
|
10319
|
+
}
|
|
10320
|
+
),
|
|
10321
|
+
position.pnl && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10322
|
+
"div",
|
|
10323
|
+
{
|
|
10324
|
+
className: "p-3 rounded-lg",
|
|
10325
|
+
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
10326
|
+
children: [
|
|
10327
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
10328
|
+
isPnlPositive ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingUp, { size: 14, style: { color: "var(--compass-color-success)" } }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingDown, { size: 14, style: { color: "var(--compass-color-error)" } }),
|
|
10329
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "Total P&L" })
|
|
10330
|
+
] }),
|
|
10331
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10332
|
+
"p",
|
|
10333
|
+
{
|
|
10334
|
+
className: "font-semibold",
|
|
10335
|
+
style: {
|
|
10336
|
+
color: isPnlPositive ? "var(--compass-color-success)" : "var(--compass-color-error)"
|
|
10337
|
+
},
|
|
10338
|
+
children: [
|
|
10339
|
+
isPnlPositive ? "+" : "",
|
|
10340
|
+
formatUSD(position.pnl.totalPnl)
|
|
10341
|
+
]
|
|
10342
|
+
}
|
|
10343
|
+
)
|
|
10344
|
+
]
|
|
10345
|
+
}
|
|
10346
|
+
)
|
|
10347
|
+
] }),
|
|
10348
|
+
(position.deposits.length > 0 || position.withdrawals.length > 0) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
|
|
10349
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10350
|
+
"h3",
|
|
10351
|
+
{
|
|
10352
|
+
className: "font-semibold mb-3",
|
|
10353
|
+
style: { color: "var(--compass-color-text)" },
|
|
10354
|
+
children: "Transaction History"
|
|
10355
|
+
}
|
|
10356
|
+
),
|
|
10357
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
10358
|
+
position.deposits.map((tx, i) => {
|
|
10359
|
+
const date = formatDate(tx.timestamp);
|
|
10360
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10361
|
+
"div",
|
|
9751
10362
|
{
|
|
9752
|
-
className: "
|
|
9753
|
-
style: {
|
|
9754
|
-
color: isPnlPositive ? "var(--compass-color-success)" : "var(--compass-color-error)"
|
|
9755
|
-
},
|
|
10363
|
+
className: "flex items-center justify-between p-3 rounded-lg",
|
|
10364
|
+
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
9756
10365
|
children: [
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
|
|
9766
|
-
|
|
9767
|
-
|
|
9768
|
-
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
|
|
9774
|
-
|
|
9775
|
-
|
|
9776
|
-
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
|
|
9780
|
-
|
|
9781
|
-
|
|
9782
|
-
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
9783
|
-
children: [
|
|
9784
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
9785
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9786
|
-
"p",
|
|
9787
|
-
{
|
|
9788
|
-
className: "font-medium",
|
|
9789
|
-
style: { color: "var(--compass-color-success)" },
|
|
9790
|
-
children: [
|
|
9791
|
-
"+",
|
|
9792
|
-
formatAmount(tx.amount),
|
|
9793
|
-
" ",
|
|
9794
|
-
position.assetSymbol
|
|
9795
|
-
]
|
|
9796
|
-
}
|
|
9797
|
-
),
|
|
9798
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9799
|
-
"p",
|
|
10366
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
10367
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10368
|
+
"p",
|
|
10369
|
+
{
|
|
10370
|
+
className: "font-medium",
|
|
10371
|
+
style: { color: "var(--compass-color-success)" },
|
|
10372
|
+
children: [
|
|
10373
|
+
"+",
|
|
10374
|
+
formatAmount(tx.amount),
|
|
10375
|
+
" ",
|
|
10376
|
+
position.assetSymbol
|
|
10377
|
+
]
|
|
10378
|
+
}
|
|
10379
|
+
),
|
|
10380
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10381
|
+
"p",
|
|
10382
|
+
{
|
|
10383
|
+
className: "text-xs",
|
|
10384
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
10385
|
+
children: date ? `Deposit - ${date}` : "Deposit"
|
|
10386
|
+
}
|
|
10387
|
+
)
|
|
10388
|
+
] }),
|
|
10389
|
+
tx.txHash && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10390
|
+
"a",
|
|
9800
10391
|
{
|
|
9801
|
-
|
|
9802
|
-
|
|
9803
|
-
|
|
10392
|
+
href: `https://etherscan.io/tx/${tx.txHash}`,
|
|
10393
|
+
target: "_blank",
|
|
10394
|
+
rel: "noopener noreferrer",
|
|
10395
|
+
className: "p-2 rounded-lg hover:opacity-80 transition-opacity",
|
|
10396
|
+
style: { backgroundColor: "var(--compass-color-background)" },
|
|
10397
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } })
|
|
9804
10398
|
}
|
|
9805
10399
|
)
|
|
9806
|
-
]
|
|
9807
|
-
|
|
9808
|
-
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
)
|
|
9818
|
-
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9843
|
-
|
|
9844
|
-
),
|
|
9845
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9846
|
-
"p",
|
|
10400
|
+
]
|
|
10401
|
+
},
|
|
10402
|
+
`deposit-${i}`
|
|
10403
|
+
);
|
|
10404
|
+
}),
|
|
10405
|
+
position.withdrawals.map((tx, i) => {
|
|
10406
|
+
const date = formatDate(tx.timestamp);
|
|
10407
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10408
|
+
"div",
|
|
10409
|
+
{
|
|
10410
|
+
className: "flex items-center justify-between p-3 rounded-lg",
|
|
10411
|
+
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
10412
|
+
children: [
|
|
10413
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
10414
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10415
|
+
"p",
|
|
10416
|
+
{
|
|
10417
|
+
className: "font-medium",
|
|
10418
|
+
style: { color: "var(--compass-color-error)" },
|
|
10419
|
+
children: [
|
|
10420
|
+
"-",
|
|
10421
|
+
formatAmount(tx.amount),
|
|
10422
|
+
" ",
|
|
10423
|
+
position.assetSymbol
|
|
10424
|
+
]
|
|
10425
|
+
}
|
|
10426
|
+
),
|
|
10427
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10428
|
+
"p",
|
|
10429
|
+
{
|
|
10430
|
+
className: "text-xs",
|
|
10431
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
10432
|
+
children: date ? `Withdrawal - ${date}` : "Withdrawal"
|
|
10433
|
+
}
|
|
10434
|
+
)
|
|
10435
|
+
] }),
|
|
10436
|
+
tx.txHash && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10437
|
+
"a",
|
|
9847
10438
|
{
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
10439
|
+
href: `https://etherscan.io/tx/${tx.txHash}`,
|
|
10440
|
+
target: "_blank",
|
|
10441
|
+
rel: "noopener noreferrer",
|
|
10442
|
+
className: "p-2 rounded-lg hover:opacity-80 transition-opacity",
|
|
10443
|
+
style: { backgroundColor: "var(--compass-color-background)" },
|
|
10444
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } })
|
|
9851
10445
|
}
|
|
9852
10446
|
)
|
|
9853
|
-
]
|
|
9854
|
-
|
|
9855
|
-
|
|
9856
|
-
|
|
9857
|
-
|
|
9858
|
-
|
|
9859
|
-
rel: "noopener noreferrer",
|
|
9860
|
-
className: "p-2 rounded-lg hover:opacity-80 transition-opacity",
|
|
9861
|
-
style: { backgroundColor: "var(--compass-color-background)" },
|
|
9862
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } })
|
|
9863
|
-
}
|
|
9864
|
-
)
|
|
9865
|
-
]
|
|
9866
|
-
},
|
|
9867
|
-
`withdraw-${i}`
|
|
9868
|
-
);
|
|
9869
|
-
})
|
|
10447
|
+
]
|
|
10448
|
+
},
|
|
10449
|
+
`withdraw-${i}`
|
|
10450
|
+
);
|
|
10451
|
+
})
|
|
10452
|
+
] })
|
|
9870
10453
|
] })
|
|
9871
|
-
]
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
10454
|
+
]
|
|
10455
|
+
}
|
|
10456
|
+
)
|
|
10457
|
+
]
|
|
9875
10458
|
}
|
|
9876
10459
|
);
|
|
9877
10460
|
}
|
|
@@ -10640,7 +11223,7 @@ function AllocationEditor({
|
|
|
10640
11223
|
) })
|
|
10641
11224
|
] });
|
|
10642
11225
|
}
|
|
10643
|
-
var
|
|
11226
|
+
var EVM_CHAIN_IDS4 = {
|
|
10644
11227
|
ethereum: 1,
|
|
10645
11228
|
base: 8453,
|
|
10646
11229
|
arbitrum: 42161
|
|
@@ -10674,7 +11257,7 @@ function RebalancingWidget({
|
|
|
10674
11257
|
}) {
|
|
10675
11258
|
const { chainId: contextChainId, setChainId } = useChain();
|
|
10676
11259
|
const CHAIN_ID = chain || contextChainId;
|
|
10677
|
-
const { address, signTypedData, isConnected, login, logout, switchChain, walletChainId } = useEmbeddableWallet();
|
|
11260
|
+
const { address, signTypedData, isConnected, login, logout, switchChain, walletChainId, fundWallet, hasExternalWallet } = useEmbeddableWallet();
|
|
10678
11261
|
const { earnAccountAddress } = useEarnAccount();
|
|
10679
11262
|
const queryClient = reactQuery.useQueryClient();
|
|
10680
11263
|
const { portfolio, earnAccountMarkets, isMarketsLoading, isLoading, isError, error, refetch } = useRebalancingData(chain);
|
|
@@ -10710,6 +11293,7 @@ function RebalancingWidget({
|
|
|
10710
11293
|
const [txHash, setTxHash] = react.useState(null);
|
|
10711
11294
|
const [txConfirmed, setTxConfirmed] = react.useState(false);
|
|
10712
11295
|
const [hasInitializedTargets, setHasInitializedTargets] = react.useState(false);
|
|
11296
|
+
const [originalAllocations, setOriginalAllocations] = react.useState({});
|
|
10713
11297
|
const [isSwapModalOpen, setIsSwapModalOpen] = react.useState(false);
|
|
10714
11298
|
const [isBalancesModalOpen, setIsBalancesModalOpen] = react.useState(false);
|
|
10715
11299
|
const [isAddMarketExpanded, setIsAddMarketExpanded] = react.useState(false);
|
|
@@ -10722,12 +11306,14 @@ function RebalancingWidget({
|
|
|
10722
11306
|
const [selectedToken, setSelectedToken] = react.useState("USDC");
|
|
10723
11307
|
const [depositAmount, setDepositAmount] = react.useState("");
|
|
10724
11308
|
const [isTokenDropdownOpen, setIsTokenDropdownOpen] = react.useState(false);
|
|
10725
|
-
const [
|
|
10726
|
-
const [depositError, setDepositError] = react.useState(null);
|
|
10727
|
-
const [depositStatus, setDepositStatus] = react.useState("");
|
|
11309
|
+
const [depositTxState, setDepositTxState] = react.useState({ status: "idle" });
|
|
10728
11310
|
const earnBalanceRef = react.useRef(null);
|
|
11311
|
+
const { startPolling: startDepositPolling, clearPolling: clearDepositPolling } = useTxPolling({
|
|
11312
|
+
queryKeysToInvalidate: [["earnAccountBalances"], ["rebalancing"]]
|
|
11313
|
+
});
|
|
10729
11314
|
react.useEffect(() => {
|
|
10730
11315
|
setTargets([]);
|
|
11316
|
+
setOriginalAllocations({});
|
|
10731
11317
|
setPreviewPlan(null);
|
|
10732
11318
|
setServerPreview(null);
|
|
10733
11319
|
setWidgetState("editing");
|
|
@@ -10739,20 +11325,26 @@ function RebalancingWidget({
|
|
|
10739
11325
|
setIsSwapModalOpen(false);
|
|
10740
11326
|
setSelectedMarket(null);
|
|
10741
11327
|
setDepositAmount("");
|
|
10742
|
-
|
|
10743
|
-
|
|
10744
|
-
}, [CHAIN_ID]);
|
|
11328
|
+
setDepositTxState({ status: "idle" });
|
|
11329
|
+
clearDepositPolling();
|
|
11330
|
+
}, [CHAIN_ID, clearDepositPolling]);
|
|
10745
11331
|
react.useEffect(() => {
|
|
10746
11332
|
if (portfolio && portfolio.positions.length > 0 && !hasInitializedTargets && !isLoading) {
|
|
11333
|
+
const origAllocs = {};
|
|
10747
11334
|
setTargets(
|
|
10748
|
-
portfolio.positions.map((p) =>
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
|
|
10753
|
-
|
|
10754
|
-
|
|
11335
|
+
portfolio.positions.map((p) => {
|
|
11336
|
+
const pct = parseFloat(p.allocationPercent.toFixed(2));
|
|
11337
|
+
origAllocs[`${p.venueType}-${p.venueAddress.toLowerCase()}`] = pct;
|
|
11338
|
+
return {
|
|
11339
|
+
venueType: p.venueType,
|
|
11340
|
+
venueAddress: p.venueAddress,
|
|
11341
|
+
venueName: p.venueName,
|
|
11342
|
+
token: p.token,
|
|
11343
|
+
targetPercent: pct
|
|
11344
|
+
};
|
|
11345
|
+
})
|
|
10755
11346
|
);
|
|
11347
|
+
setOriginalAllocations(origAllocs);
|
|
10756
11348
|
setHasInitializedTargets(true);
|
|
10757
11349
|
}
|
|
10758
11350
|
}, [portfolio, hasInitializedTargets, isLoading]);
|
|
@@ -10784,15 +11376,21 @@ function RebalancingWidget({
|
|
|
10784
11376
|
}, [portfolio, targets, hasChanges, defaultSlippage, minRebalanceThresholdUsd]);
|
|
10785
11377
|
const handleResetToCurrent = react.useCallback(() => {
|
|
10786
11378
|
if (!portfolio) return;
|
|
11379
|
+
const origAllocs = {};
|
|
10787
11380
|
setTargets(
|
|
10788
|
-
portfolio.positions.map((p) =>
|
|
10789
|
-
|
|
10790
|
-
|
|
10791
|
-
|
|
10792
|
-
|
|
10793
|
-
|
|
10794
|
-
|
|
11381
|
+
portfolio.positions.map((p) => {
|
|
11382
|
+
const pct = parseFloat(p.allocationPercent.toFixed(2));
|
|
11383
|
+
origAllocs[`${p.venueType}-${p.venueAddress.toLowerCase()}`] = pct;
|
|
11384
|
+
return {
|
|
11385
|
+
venueType: p.venueType,
|
|
11386
|
+
venueAddress: p.venueAddress,
|
|
11387
|
+
venueName: p.venueName,
|
|
11388
|
+
token: p.token,
|
|
11389
|
+
targetPercent: pct
|
|
11390
|
+
};
|
|
11391
|
+
})
|
|
10795
11392
|
);
|
|
11393
|
+
setOriginalAllocations(origAllocs);
|
|
10796
11394
|
setPreviewPlan(null);
|
|
10797
11395
|
setServerPreview(null);
|
|
10798
11396
|
setWidgetState("editing");
|
|
@@ -10810,7 +11408,7 @@ function RebalancingWidget({
|
|
|
10810
11408
|
setTargets((prev) => prev.map((t, i) => i === index ? { ...t, targetPercent: rounded } : t));
|
|
10811
11409
|
}, []);
|
|
10812
11410
|
const ensureCorrectChain = react.useCallback(async () => {
|
|
10813
|
-
const targetChainId =
|
|
11411
|
+
const targetChainId = EVM_CHAIN_IDS4[CHAIN_ID];
|
|
10814
11412
|
if (!targetChainId) return;
|
|
10815
11413
|
if (walletChainId !== void 0 && walletChainId !== targetChainId) {
|
|
10816
11414
|
if (!switchChain) {
|
|
@@ -10835,7 +11433,8 @@ function RebalancingWidget({
|
|
|
10835
11433
|
venueType: t.venueType === "vault" ? "VAULT" : t.venueType === "aave" ? "AAVE" : "PENDLE_PT",
|
|
10836
11434
|
venueAddress: t.venueAddress,
|
|
10837
11435
|
targetPercent: t.targetPercent,
|
|
10838
|
-
token: t.token
|
|
11436
|
+
token: t.token,
|
|
11437
|
+
originalPercent: originalAllocations[`${t.venueType}-${t.venueAddress.toLowerCase()}`] ?? 0
|
|
10839
11438
|
})),
|
|
10840
11439
|
slippage: defaultSlippage
|
|
10841
11440
|
})
|
|
@@ -10853,7 +11452,7 @@ function RebalancingWidget({
|
|
|
10853
11452
|
setWidgetState("error");
|
|
10854
11453
|
onError?.(err instanceof Error ? err : new Error("Preview failed"));
|
|
10855
11454
|
}
|
|
10856
|
-
}, [portfolio, hasChanges, address, CHAIN_ID, targets, defaultSlippage, clientPreview, onError, ensureCorrectChain]);
|
|
11455
|
+
}, [portfolio, hasChanges, address, CHAIN_ID, targets, defaultSlippage, clientPreview, onError, ensureCorrectChain, originalAllocations]);
|
|
10857
11456
|
const handleExecute = react.useCallback(async () => {
|
|
10858
11457
|
if (!serverPreview?.eip712 || !address) return;
|
|
10859
11458
|
setWidgetState("signing");
|
|
@@ -10941,13 +11540,11 @@ function RebalancingWidget({
|
|
|
10941
11540
|
};
|
|
10942
11541
|
const handleDeposit = react.useCallback(async () => {
|
|
10943
11542
|
if (!selectedMarket || !depositAmount || parseFloat(depositAmount) <= 0 || !address || !signTypedData) return;
|
|
10944
|
-
|
|
10945
|
-
setDepositError(null);
|
|
11543
|
+
setDepositTxState({ status: "preparing" });
|
|
10946
11544
|
const underlyingToken = selectedMarket.underlyingToken;
|
|
10947
11545
|
try {
|
|
10948
11546
|
let resultTxHash;
|
|
10949
11547
|
if (needsSwap) {
|
|
10950
|
-
setDepositStatus("Getting swap quote...");
|
|
10951
11548
|
const quoteResponse = await fetch(
|
|
10952
11549
|
`/api/compass/swap/quote?owner=${address}&chain=${CHAIN_ID}&tokenIn=${selectedToken}&tokenOut=${underlyingToken}&amountIn=${depositAmount}`
|
|
10953
11550
|
);
|
|
@@ -10961,7 +11558,6 @@ function RebalancingWidget({
|
|
|
10961
11558
|
throw new Error("Invalid swap quote - no output amount");
|
|
10962
11559
|
}
|
|
10963
11560
|
const actualDepositAmount = (parseFloat(estimatedOutput) * 0.99999).toString();
|
|
10964
|
-
setDepositStatus("Preparing swap and deposit...");
|
|
10965
11561
|
const bundleActions = [
|
|
10966
11562
|
{
|
|
10967
11563
|
body: {
|
|
@@ -10995,7 +11591,7 @@ function RebalancingWidget({
|
|
|
10995
11591
|
throw new Error(errorData.error || "Failed to prepare bundle");
|
|
10996
11592
|
}
|
|
10997
11593
|
const { eip712, normalizedTypes, domain, message } = await prepareResponse.json();
|
|
10998
|
-
|
|
11594
|
+
setDepositTxState({ status: "signing" });
|
|
10999
11595
|
await ensureCorrectChain();
|
|
11000
11596
|
const signature = await signTypedData({
|
|
11001
11597
|
domain,
|
|
@@ -11003,7 +11599,7 @@ function RebalancingWidget({
|
|
|
11003
11599
|
primaryType: "SafeTx",
|
|
11004
11600
|
message
|
|
11005
11601
|
});
|
|
11006
|
-
|
|
11602
|
+
setDepositTxState({ status: "broadcasting" });
|
|
11007
11603
|
const executeResponse = await fetch("/api/compass/bundle/execute", {
|
|
11008
11604
|
method: "POST",
|
|
11009
11605
|
headers: { "Content-Type": "application/json" },
|
|
@@ -11021,7 +11617,6 @@ function RebalancingWidget({
|
|
|
11021
11617
|
const result = await executeResponse.json();
|
|
11022
11618
|
resultTxHash = result.txHash;
|
|
11023
11619
|
} else {
|
|
11024
|
-
setDepositStatus("Preparing deposit...");
|
|
11025
11620
|
const venueParams = buildVenueParamsFromMarket(selectedMarket);
|
|
11026
11621
|
const prepareResponse = await fetch("/api/compass/deposit/prepare", {
|
|
11027
11622
|
method: "POST",
|
|
@@ -11038,7 +11633,7 @@ function RebalancingWidget({
|
|
|
11038
11633
|
throw new Error(errData.error || "Failed to prepare deposit");
|
|
11039
11634
|
}
|
|
11040
11635
|
const prepareData = await prepareResponse.json();
|
|
11041
|
-
|
|
11636
|
+
setDepositTxState({ status: "signing" });
|
|
11042
11637
|
await ensureCorrectChain();
|
|
11043
11638
|
const signature = await signTypedData({
|
|
11044
11639
|
domain: prepareData.domain,
|
|
@@ -11046,7 +11641,7 @@ function RebalancingWidget({
|
|
|
11046
11641
|
primaryType: "SafeTx",
|
|
11047
11642
|
message: prepareData.message
|
|
11048
11643
|
});
|
|
11049
|
-
|
|
11644
|
+
setDepositTxState({ status: "broadcasting" });
|
|
11050
11645
|
const executeResponse = await fetch("/api/compass/deposit/execute", {
|
|
11051
11646
|
method: "POST",
|
|
11052
11647
|
headers: { "Content-Type": "application/json" },
|
|
@@ -11064,7 +11659,8 @@ function RebalancingWidget({
|
|
|
11064
11659
|
const result = await executeResponse.json();
|
|
11065
11660
|
resultTxHash = result.txHash;
|
|
11066
11661
|
}
|
|
11067
|
-
|
|
11662
|
+
setDepositTxState({ status: "submitted", txHash: resultTxHash });
|
|
11663
|
+
startDepositPolling(resultTxHash, setDepositTxState);
|
|
11068
11664
|
setDepositAmount("");
|
|
11069
11665
|
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
11070
11666
|
queryClient.invalidateQueries({ queryKey: ["rebalancing"] });
|
|
@@ -11076,15 +11672,11 @@ function RebalancingWidget({
|
|
|
11076
11672
|
refetch();
|
|
11077
11673
|
}, delay);
|
|
11078
11674
|
}
|
|
11079
|
-
setTimeout(() => setDepositStatus(""), 3e3);
|
|
11080
11675
|
} catch (err) {
|
|
11081
|
-
|
|
11082
|
-
setDepositStatus("");
|
|
11676
|
+
setDepositTxState({ status: "failed", error: err instanceof Error ? err.message : "Deposit failed" });
|
|
11083
11677
|
onError?.(err instanceof Error ? err : new Error("Deposit failed"));
|
|
11084
|
-
} finally {
|
|
11085
|
-
setIsProcessing(false);
|
|
11086
11678
|
}
|
|
11087
|
-
}, [selectedMarket, depositAmount, address, signTypedData, selectedToken, needsSwap, CHAIN_ID, ensureCorrectChain, queryClient, refetch, onError]);
|
|
11679
|
+
}, [selectedMarket, depositAmount, address, signTypedData, selectedToken, needsSwap, CHAIN_ID, ensureCorrectChain, queryClient, refetch, onError, startDepositPolling]);
|
|
11088
11680
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col w-full", style: { gap: "0", fontFamily: "var(--compass-font-family)", height, overflow: "hidden", borderRadius: "var(--compass-border-radius-xl)" }, children: [
|
|
11089
11681
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minHeight: 0, overflowY: "auto", scrollbarWidth: "none", display: "flex", flexDirection: "column" }, children: [
|
|
11090
11682
|
showChainSwitcher && !chain && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "0 4px", marginBottom: "8px" }, children: /* @__PURE__ */ jsxRuntime.jsx(ChainSwitcher, {}) }),
|
|
@@ -11113,8 +11705,19 @@ function RebalancingWidget({
|
|
|
11113
11705
|
}
|
|
11114
11706
|
)
|
|
11115
11707
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
11116
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-semibold mb-2", style: { color: "var(--compass-color-text)" }, children: "No positions found" }),
|
|
11117
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", style: { color: "var(--compass-color-text-secondary)" }, children: "Deposit into a vault, Aave market, or Pendle market to start rebalancing." })
|
|
11708
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-semibold mb-2", style: { color: "var(--compass-color-text)" }, children: fundWallet && !hasExternalWallet ? "Fund your account to start" : "No positions found" }),
|
|
11709
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm mb-4", style: { color: "var(--compass-color-text-secondary)" }, children: fundWallet && !hasExternalWallet ? "Buy crypto to get started with your DeFi portfolio." : "Deposit into a vault, Aave market, or Pendle market to start rebalancing." }),
|
|
11710
|
+
fundWallet && earnAccountAddress && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "100%", maxWidth: "320px" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11711
|
+
BuyForm,
|
|
11712
|
+
{
|
|
11713
|
+
targetAddress: earnAccountAddress,
|
|
11714
|
+
onComplete: () => {
|
|
11715
|
+
queryClient.invalidateQueries({ queryKey: ["rebalancingPortfolio"] });
|
|
11716
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
11717
|
+
refetch();
|
|
11718
|
+
}
|
|
11719
|
+
}
|
|
11720
|
+
) })
|
|
11118
11721
|
] }) }),
|
|
11119
11722
|
state !== "loading" && state !== "empty" && portfolio && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
11120
11723
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center text-center", style: { padding: "16px 16px 12px" }, children: [
|
|
@@ -11281,7 +11884,7 @@ function RebalancingWidget({
|
|
|
11281
11884
|
selectedMarket,
|
|
11282
11885
|
onMarketSelect: (market) => {
|
|
11283
11886
|
setSelectedMarket(market);
|
|
11284
|
-
|
|
11887
|
+
if (depositTxState.status === "failed") setDepositTxState({ status: "idle" });
|
|
11285
11888
|
},
|
|
11286
11889
|
isLoading: isMarketsLoading
|
|
11287
11890
|
}
|
|
@@ -11304,10 +11907,10 @@ function RebalancingWidget({
|
|
|
11304
11907
|
value: depositAmount,
|
|
11305
11908
|
onChange: (e) => {
|
|
11306
11909
|
setDepositAmount(e.target.value);
|
|
11307
|
-
|
|
11910
|
+
if (depositTxState.status === "failed") setDepositTxState({ status: "idle" });
|
|
11308
11911
|
},
|
|
11309
11912
|
placeholder: "0.00",
|
|
11310
|
-
disabled:
|
|
11913
|
+
disabled: depositTxState.status !== "idle" && depositTxState.status !== "confirmed" && depositTxState.status !== "failed",
|
|
11311
11914
|
className: "flex-1 font-bold bg-transparent outline-none",
|
|
11312
11915
|
style: {
|
|
11313
11916
|
color: "var(--compass-color-text)",
|
|
@@ -11323,7 +11926,7 @@ function RebalancingWidget({
|
|
|
11323
11926
|
"button",
|
|
11324
11927
|
{
|
|
11325
11928
|
onClick: () => setIsTokenDropdownOpen(!isTokenDropdownOpen),
|
|
11326
|
-
disabled:
|
|
11929
|
+
disabled: depositTxState.status !== "idle" && depositTxState.status !== "confirmed" && depositTxState.status !== "failed",
|
|
11327
11930
|
className: "flex items-center font-semibold",
|
|
11328
11931
|
style: {
|
|
11329
11932
|
backgroundColor: "var(--compass-color-surface-hover, var(--compass-color-surface))",
|
|
@@ -11360,7 +11963,7 @@ function RebalancingWidget({
|
|
|
11360
11963
|
onClick: () => {
|
|
11361
11964
|
setSelectedToken(token);
|
|
11362
11965
|
setIsTokenDropdownOpen(false);
|
|
11363
|
-
|
|
11966
|
+
if (depositTxState.status === "failed") setDepositTxState({ status: "idle" });
|
|
11364
11967
|
},
|
|
11365
11968
|
className: "w-full text-left font-medium",
|
|
11366
11969
|
style: {
|
|
@@ -11386,7 +11989,7 @@ function RebalancingWidget({
|
|
|
11386
11989
|
"button",
|
|
11387
11990
|
{
|
|
11388
11991
|
onClick: () => setDepositAmount(earnBalancesQuery.toString()),
|
|
11389
|
-
disabled:
|
|
11992
|
+
disabled: depositTxState.status !== "idle" && depositTxState.status !== "confirmed" && depositTxState.status !== "failed",
|
|
11390
11993
|
className: "font-semibold",
|
|
11391
11994
|
style: { color: "var(--compass-color-primary)", fontSize: "0.8125rem", background: "none", border: "none", padding: 0 },
|
|
11392
11995
|
children: [
|
|
@@ -11423,26 +12026,12 @@ function RebalancingWidget({
|
|
|
11423
12026
|
]
|
|
11424
12027
|
}
|
|
11425
12028
|
),
|
|
11426
|
-
|
|
11427
|
-
"div",
|
|
11428
|
-
{
|
|
11429
|
-
className: "flex items-center",
|
|
11430
|
-
style: {
|
|
11431
|
-
backgroundColor: "var(--compass-color-error-muted)",
|
|
11432
|
-
color: "var(--compass-color-error)",
|
|
11433
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
11434
|
-
padding: "12px 14px",
|
|
11435
|
-
gap: "8px",
|
|
11436
|
-
fontSize: "0.875rem"
|
|
11437
|
-
},
|
|
11438
|
-
children: depositError
|
|
11439
|
-
}
|
|
11440
|
-
),
|
|
12029
|
+
/* @__PURE__ */ jsxRuntime.jsx(TxStatus, { state: depositTxState }),
|
|
11441
12030
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11442
12031
|
"button",
|
|
11443
12032
|
{
|
|
11444
12033
|
onClick: !isConnected && login ? login : handleDeposit,
|
|
11445
|
-
disabled: isConnected && (
|
|
12034
|
+
disabled: isConnected && (depositTxState.status !== "idle" && depositTxState.status !== "confirmed" && depositTxState.status !== "failed" || !selectedMarket || !depositAmount || parseFloat(depositAmount) <= 0 || parseFloat(depositAmount) > earnBalancesQuery),
|
|
11446
12035
|
className: "w-full font-bold",
|
|
11447
12036
|
style: {
|
|
11448
12037
|
backgroundColor: "var(--compass-color-primary)",
|
|
@@ -11453,26 +12042,13 @@ function RebalancingWidget({
|
|
|
11453
12042
|
fontSize: "1rem",
|
|
11454
12043
|
transition: "all 200ms ease",
|
|
11455
12044
|
border: "none",
|
|
11456
|
-
opacity: isConnected && (
|
|
12045
|
+
opacity: isConnected && (depositTxState.status !== "idle" && depositTxState.status !== "confirmed" && depositTxState.status !== "failed" || !selectedMarket || !depositAmount || parseFloat(depositAmount) <= 0 || parseFloat(depositAmount) > earnBalancesQuery) ? 0.4 : 1
|
|
11457
12046
|
},
|
|
11458
|
-
children: !isConnected ? "Connect Wallet" :
|
|
12047
|
+
children: !isConnected ? "Connect Wallet" : depositTxState.status !== "idle" && depositTxState.status !== "confirmed" && depositTxState.status !== "failed" ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center justify-center", style: { gap: "8px" }, children: [
|
|
11459
12048
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 16, className: "animate-spin" }),
|
|
11460
12049
|
"Processing..."
|
|
11461
12050
|
] }) : !selectedMarket ? "Select a market" : needsSwap ? "Swap & Deposit" : "Deposit"
|
|
11462
12051
|
}
|
|
11463
|
-
),
|
|
11464
|
-
depositStatus && !depositError && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11465
|
-
"div",
|
|
11466
|
-
{
|
|
11467
|
-
className: "text-sm text-center",
|
|
11468
|
-
style: {
|
|
11469
|
-
backgroundColor: depositStatus.includes("successful") ? "var(--compass-color-success-muted)" : "var(--compass-color-primary-muted, rgba(99, 102, 241, 0.1))",
|
|
11470
|
-
color: depositStatus.includes("successful") ? "var(--compass-color-success)" : "var(--compass-color-primary)",
|
|
11471
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
11472
|
-
padding: "10px 12px"
|
|
11473
|
-
},
|
|
11474
|
-
children: depositStatus
|
|
11475
|
-
}
|
|
11476
12052
|
)
|
|
11477
12053
|
] }),
|
|
11478
12054
|
clientPreview && clientPreview.actions.length > 0 && state === "editing" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -11489,11 +12065,7 @@ function RebalancingWidget({
|
|
|
11489
12065
|
clientPreview.warnings.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-col gap-1", children: clientPreview.warnings.map((w, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 text-xs", style: { color: "var(--compass-color-warning, #eab308)" }, children: [
|
|
11490
12066
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { size: 12, className: "flex-shrink-0 mt-0.5" }),
|
|
11491
12067
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: w })
|
|
11492
|
-
] }, i)) })
|
|
11493
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs mt-2", style: { color: "var(--compass-color-text-tertiary)" }, children: [
|
|
11494
|
-
"Estimated gas savings: ",
|
|
11495
|
-
clientPreview.estimatedGasSavings
|
|
11496
|
-
] })
|
|
12068
|
+
] }, i)) })
|
|
11497
12069
|
]
|
|
11498
12070
|
}
|
|
11499
12071
|
),
|
|
@@ -11736,46 +12308,8 @@ function RebalancingWidget({
|
|
|
11736
12308
|
onClose: () => setIsBalancesModalOpen(false),
|
|
11737
12309
|
title: "Balance Breakdown",
|
|
11738
12310
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "12px" }, children: [
|
|
11739
|
-
address && /* @__PURE__ */ jsxRuntime.
|
|
11740
|
-
|
|
11741
|
-
{
|
|
11742
|
-
className: "flex items-center justify-between",
|
|
11743
|
-
style: {
|
|
11744
|
-
backgroundColor: "var(--compass-color-surface)",
|
|
11745
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
11746
|
-
padding: "10px 16px",
|
|
11747
|
-
border: "1.5px solid var(--compass-color-border)"
|
|
11748
|
-
},
|
|
11749
|
-
children: [
|
|
11750
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text-tertiary)", fontSize: "0.8125rem" }, children: "Wallet" }),
|
|
11751
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: "var(--compass-color-text)", fontSize: "0.8125rem", fontFamily: "monospace" }, children: [
|
|
11752
|
-
address.slice(0, 6),
|
|
11753
|
-
"...",
|
|
11754
|
-
address.slice(-4)
|
|
11755
|
-
] })
|
|
11756
|
-
]
|
|
11757
|
-
}
|
|
11758
|
-
),
|
|
11759
|
-
earnAccountAddress && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11760
|
-
"div",
|
|
11761
|
-
{
|
|
11762
|
-
className: "flex items-center justify-between",
|
|
11763
|
-
style: {
|
|
11764
|
-
backgroundColor: "var(--compass-color-surface)",
|
|
11765
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
11766
|
-
padding: "10px 16px",
|
|
11767
|
-
border: "1.5px solid var(--compass-color-border)"
|
|
11768
|
-
},
|
|
11769
|
-
children: [
|
|
11770
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text-tertiary)", fontSize: "0.8125rem" }, children: "Product Account" }),
|
|
11771
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: "var(--compass-color-text)", fontSize: "0.8125rem", fontFamily: "monospace" }, children: [
|
|
11772
|
-
earnAccountAddress.slice(0, 6),
|
|
11773
|
-
"...",
|
|
11774
|
-
earnAccountAddress.slice(-4)
|
|
11775
|
-
] })
|
|
11776
|
-
]
|
|
11777
|
-
}
|
|
11778
|
-
),
|
|
12311
|
+
address && /* @__PURE__ */ jsxRuntime.jsx(CopyableAddress, { address, label: "Wallet" }),
|
|
12312
|
+
earnAccountAddress && /* @__PURE__ */ jsxRuntime.jsx(CopyableAddress, { address: earnAccountAddress, label: "Product Account" }),
|
|
11779
12313
|
portfolio && portfolio.idleBalances.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
11780
12314
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11781
12315
|
"span",
|