@compass-labs/widgets 0.1.39 → 0.1.41
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 +1650 -1032
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1652 -1034
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.js +0 -3
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +0 -3
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { createContext, forwardRef, useState, useCallback, useImperativeHandle, useContext, useEffect, useMemo
|
|
1
|
+
import { createContext, forwardRef, useState, useCallback, useImperativeHandle, useContext, useRef, useEffect, useMemo } from 'react';
|
|
2
2
|
import { useQueryClient, useQuery, QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
3
3
|
import { CompassApiSDK } from '@compass-labs/api-sdk';
|
|
4
4
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { arbitrum, base, mainnet } from 'viem/chains';
|
|
6
|
-
import { Wallet, Loader2, ArrowDownLeft, ArrowUpRight, X,
|
|
6
|
+
import { Wallet, Loader2, ArrowDownLeft, ArrowUpRight, Send, ArrowRight, X, CheckCircle, AlertCircle, CreditCard, ExternalLink, XCircle, Check, Copy, LogOut, ChevronDown, ArrowDownUp, ArrowLeftRight, TrendingUp, Plus, Minus, Circle, AlertTriangle, TrendingDown, ChevronRight, ArrowUpCircle, ArrowDownCircle, RotateCcw, Equal, ChevronUp, Inbox, Percent, Clock, Calendar } from 'lucide-react';
|
|
7
|
+
import { isAddress, encodeFunctionData, parseUnits } from 'viem';
|
|
7
8
|
|
|
8
9
|
// src/provider/CompassProvider.tsx
|
|
9
10
|
var ApiContext = createContext(null);
|
|
@@ -90,7 +91,10 @@ var disconnectedWallet = {
|
|
|
90
91
|
},
|
|
91
92
|
switchChain: null,
|
|
92
93
|
login: null,
|
|
93
|
-
logout: null
|
|
94
|
+
logout: null,
|
|
95
|
+
fundWallet: null,
|
|
96
|
+
hasExternalWallet: true,
|
|
97
|
+
sendTransaction: null
|
|
94
98
|
};
|
|
95
99
|
function WalletProvider({ children, wallet }) {
|
|
96
100
|
const value = wallet ? {
|
|
@@ -100,7 +104,10 @@ function WalletProvider({ children, wallet }) {
|
|
|
100
104
|
signTypedData: wallet.signTypedData,
|
|
101
105
|
switchChain: wallet.switchChain ?? null,
|
|
102
106
|
login: wallet.login ?? null,
|
|
103
|
-
logout: wallet.logout ?? null
|
|
107
|
+
logout: wallet.logout ?? null,
|
|
108
|
+
fundWallet: wallet.fundWallet ?? null,
|
|
109
|
+
hasExternalWallet: wallet.hasExternalWallet ?? true,
|
|
110
|
+
sendTransaction: wallet.sendTransaction ?? null
|
|
104
111
|
} : disconnectedWallet;
|
|
105
112
|
return /* @__PURE__ */ jsx(WalletContext.Provider, { value, children });
|
|
106
113
|
}
|
|
@@ -1269,25 +1276,29 @@ function WalletStatus({
|
|
|
1269
1276
|
);
|
|
1270
1277
|
}
|
|
1271
1278
|
function ActionModal({ isOpen, onClose, title, children }) {
|
|
1279
|
+
const modalRef = useRef(null);
|
|
1272
1280
|
useEffect(() => {
|
|
1273
1281
|
const handleEscape = (e) => {
|
|
1274
1282
|
if (e.key === "Escape") onClose();
|
|
1275
1283
|
};
|
|
1276
1284
|
if (isOpen) {
|
|
1277
1285
|
document.addEventListener("keydown", handleEscape);
|
|
1278
|
-
document.body.style.overflow = "hidden";
|
|
1279
1286
|
}
|
|
1280
1287
|
return () => {
|
|
1281
1288
|
document.removeEventListener("keydown", handleEscape);
|
|
1282
|
-
document.body.style.overflow = "";
|
|
1283
1289
|
};
|
|
1284
1290
|
}, [isOpen, onClose]);
|
|
1291
|
+
const handleOverlayWheel = useCallback((e) => {
|
|
1292
|
+
if (modalRef.current && !modalRef.current.contains(e.target)) {
|
|
1293
|
+
window.scrollBy(0, e.deltaY);
|
|
1294
|
+
}
|
|
1295
|
+
}, []);
|
|
1285
1296
|
if (!isOpen) return null;
|
|
1286
1297
|
return /* @__PURE__ */ jsxs(
|
|
1287
1298
|
"div",
|
|
1288
1299
|
{
|
|
1289
1300
|
className: "fixed inset-0 z-50 flex items-center justify-center p-4",
|
|
1290
|
-
|
|
1301
|
+
onWheel: handleOverlayWheel,
|
|
1291
1302
|
children: [
|
|
1292
1303
|
/* @__PURE__ */ jsx(
|
|
1293
1304
|
"div",
|
|
@@ -1300,21 +1311,27 @@ function ActionModal({ isOpen, onClose, title, children }) {
|
|
|
1300
1311
|
/* @__PURE__ */ jsxs(
|
|
1301
1312
|
"div",
|
|
1302
1313
|
{
|
|
1314
|
+
ref: modalRef,
|
|
1303
1315
|
className: "relative w-full max-w-md",
|
|
1304
1316
|
style: {
|
|
1305
1317
|
backgroundColor: "var(--compass-color-surface)",
|
|
1306
1318
|
boxShadow: "var(--compass-shadow-lg)",
|
|
1307
1319
|
borderRadius: "var(--compass-border-radius-xl)",
|
|
1308
|
-
fontFamily: "var(--compass-font-family)"
|
|
1320
|
+
fontFamily: "var(--compass-font-family)",
|
|
1321
|
+
maxHeight: "85vh",
|
|
1322
|
+
overflowY: "auto",
|
|
1323
|
+
overscrollBehavior: "contain",
|
|
1324
|
+
scrollbarWidth: "none"
|
|
1309
1325
|
},
|
|
1310
1326
|
children: [
|
|
1311
1327
|
/* @__PURE__ */ jsxs(
|
|
1312
1328
|
"div",
|
|
1313
1329
|
{
|
|
1314
|
-
className: "flex items-center justify-between border-b",
|
|
1330
|
+
className: "flex items-center justify-between border-b sticky top-0 z-10",
|
|
1315
1331
|
style: {
|
|
1316
1332
|
borderColor: "var(--compass-color-border)",
|
|
1317
|
-
padding: "calc(var(--compass-spacing-card) * 0.75) var(--compass-spacing-card)"
|
|
1333
|
+
padding: "calc(var(--compass-spacing-card) * 0.75) var(--compass-spacing-card)",
|
|
1334
|
+
backgroundColor: "var(--compass-color-surface)"
|
|
1318
1335
|
},
|
|
1319
1336
|
children: [
|
|
1320
1337
|
/* @__PURE__ */ jsx(
|
|
@@ -2571,114 +2588,731 @@ function CreditAccountGuard({
|
|
|
2571
2588
|
}
|
|
2572
2589
|
);
|
|
2573
2590
|
}
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2591
|
+
var EVM_CHAIN_IDS = {
|
|
2592
|
+
ethereum: 1,
|
|
2593
|
+
base: 8453,
|
|
2594
|
+
arbitrum: 42161
|
|
2595
|
+
};
|
|
2596
|
+
function BuyForm({ targetAddress, defaultAsset = "USDC", onComplete }) {
|
|
2597
|
+
const { fundWallet } = useEmbeddableWallet();
|
|
2598
|
+
const { chainId } = useChain();
|
|
2599
|
+
const [amount, setAmount] = useState("");
|
|
2600
|
+
const [state, setState] = useState("idle");
|
|
2601
|
+
const [error, setError] = useState(null);
|
|
2602
|
+
const numericChainId = EVM_CHAIN_IDS[chainId] || 8453;
|
|
2603
|
+
const handleBuy = useCallback(async () => {
|
|
2604
|
+
if (!fundWallet || !amount || parseFloat(amount) <= 0) {
|
|
2605
|
+
return;
|
|
2606
|
+
}
|
|
2607
|
+
setState("buying");
|
|
2608
|
+
setError(null);
|
|
2609
|
+
try {
|
|
2610
|
+
await fundWallet({
|
|
2611
|
+
address: targetAddress,
|
|
2612
|
+
chainId: numericChainId,
|
|
2613
|
+
asset: defaultAsset,
|
|
2614
|
+
amount
|
|
2615
|
+
});
|
|
2616
|
+
setState("success");
|
|
2617
|
+
onComplete?.();
|
|
2618
|
+
setTimeout(() => setState("idle"), 3e3);
|
|
2619
|
+
} catch (err) {
|
|
2620
|
+
setState("error");
|
|
2621
|
+
setError(err instanceof Error ? err.message : "Purchase failed. Please try again.");
|
|
2622
|
+
}
|
|
2623
|
+
}, [fundWallet, amount, targetAddress, numericChainId, defaultAsset, onComplete]);
|
|
2624
|
+
const chainName = chainId.charAt(0).toUpperCase() + chainId.slice(1);
|
|
2625
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
2626
|
+
/* @__PURE__ */ jsxs(
|
|
2627
|
+
"p",
|
|
2597
2628
|
{
|
|
2598
|
-
className: "text-
|
|
2599
|
-
style: { color: "var(--compass-color-text-
|
|
2600
|
-
children:
|
|
2629
|
+
className: "text-sm font-medium",
|
|
2630
|
+
style: { color: "var(--compass-color-text)", fontFamily: "var(--compass-font-family)" },
|
|
2631
|
+
children: [
|
|
2632
|
+
"Buy ",
|
|
2633
|
+
defaultAsset,
|
|
2634
|
+
" on ",
|
|
2635
|
+
chainName
|
|
2636
|
+
]
|
|
2601
2637
|
}
|
|
2602
|
-
)
|
|
2603
|
-
|
|
2638
|
+
),
|
|
2639
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2640
|
+
/* @__PURE__ */ jsx(
|
|
2641
|
+
"label",
|
|
2642
|
+
{
|
|
2643
|
+
className: "block text-sm mb-1.5",
|
|
2644
|
+
style: { color: "var(--compass-color-text-secondary)", fontFamily: "var(--compass-font-family)" },
|
|
2645
|
+
children: "Amount (USD)"
|
|
2646
|
+
}
|
|
2647
|
+
),
|
|
2648
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
2604
2649
|
/* @__PURE__ */ jsx(
|
|
2605
2650
|
"span",
|
|
2606
2651
|
{
|
|
2607
|
-
className: "
|
|
2652
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 text-sm",
|
|
2608
2653
|
style: { color: "var(--compass-color-text-tertiary)" },
|
|
2609
|
-
children: "
|
|
2654
|
+
children: "$"
|
|
2610
2655
|
}
|
|
2611
2656
|
),
|
|
2612
2657
|
/* @__PURE__ */ jsx(
|
|
2613
|
-
"
|
|
2658
|
+
"input",
|
|
2614
2659
|
{
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2660
|
+
type: "number",
|
|
2661
|
+
value: amount,
|
|
2662
|
+
onChange: (e) => {
|
|
2663
|
+
setAmount(e.target.value);
|
|
2664
|
+
if (state === "error") {
|
|
2665
|
+
setState("idle");
|
|
2666
|
+
setError(null);
|
|
2667
|
+
}
|
|
2620
2668
|
},
|
|
2621
|
-
|
|
2622
|
-
|
|
2669
|
+
disabled: state === "buying",
|
|
2670
|
+
placeholder: "0.00",
|
|
2671
|
+
className: "w-full border px-3 py-2.5 pl-7 text-sm focus:outline-none disabled:opacity-50",
|
|
2672
|
+
style: {
|
|
2673
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
2674
|
+
borderColor: "var(--compass-color-border)",
|
|
2675
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
2676
|
+
color: "var(--compass-color-text)",
|
|
2677
|
+
fontFamily: "var(--compass-font-family)"
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
)
|
|
2681
|
+
] })
|
|
2682
|
+
] }),
|
|
2683
|
+
/* @__PURE__ */ jsx(
|
|
2684
|
+
"p",
|
|
2685
|
+
{
|
|
2686
|
+
className: "text-xs",
|
|
2687
|
+
style: { color: "var(--compass-color-text-tertiary)", fontFamily: "var(--compass-font-family)" },
|
|
2688
|
+
children: "Buy crypto with card or bank transfer. Funds are sent directly to your account."
|
|
2689
|
+
}
|
|
2690
|
+
),
|
|
2691
|
+
state === "success" && /* @__PURE__ */ jsxs(
|
|
2692
|
+
"div",
|
|
2693
|
+
{
|
|
2694
|
+
className: "flex items-center gap-2 p-3 text-sm",
|
|
2695
|
+
style: {
|
|
2696
|
+
backgroundColor: "var(--compass-color-success-muted, rgba(34,197,94,0.1))",
|
|
2697
|
+
color: "var(--compass-color-success)",
|
|
2698
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
2699
|
+
fontFamily: "var(--compass-font-family)"
|
|
2700
|
+
},
|
|
2701
|
+
children: [
|
|
2702
|
+
/* @__PURE__ */ jsx(CheckCircle, { size: 16 }),
|
|
2703
|
+
"Purchase initiated. Funds may take a few minutes to arrive."
|
|
2704
|
+
]
|
|
2705
|
+
}
|
|
2706
|
+
),
|
|
2707
|
+
state === "error" && error && /* @__PURE__ */ jsxs(
|
|
2708
|
+
"div",
|
|
2709
|
+
{
|
|
2710
|
+
className: "flex items-center gap-2 p-3 text-sm",
|
|
2711
|
+
style: {
|
|
2712
|
+
backgroundColor: "var(--compass-color-error-muted, rgba(239,68,68,0.1))",
|
|
2713
|
+
color: "var(--compass-color-error)",
|
|
2714
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
2715
|
+
fontFamily: "var(--compass-font-family)"
|
|
2716
|
+
},
|
|
2717
|
+
children: [
|
|
2718
|
+
/* @__PURE__ */ jsx(AlertCircle, { size: 16 }),
|
|
2719
|
+
error
|
|
2720
|
+
]
|
|
2721
|
+
}
|
|
2722
|
+
),
|
|
2723
|
+
/* @__PURE__ */ jsx(
|
|
2724
|
+
"button",
|
|
2725
|
+
{
|
|
2726
|
+
onClick: handleBuy,
|
|
2727
|
+
disabled: state === "buying" || !amount || parseFloat(amount) <= 0,
|
|
2728
|
+
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",
|
|
2729
|
+
style: {
|
|
2730
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
2731
|
+
color: "white",
|
|
2732
|
+
borderRadius: "var(--compass-border-radius-xl)",
|
|
2733
|
+
fontFamily: "var(--compass-font-family)",
|
|
2734
|
+
transition: "var(--compass-transition-normal)"
|
|
2735
|
+
},
|
|
2736
|
+
children: state === "buying" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2737
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
2738
|
+
"Processing..."
|
|
2739
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2740
|
+
/* @__PURE__ */ jsx(CreditCard, { className: "h-4 w-4" }),
|
|
2741
|
+
"Buy with card / bank"
|
|
2742
|
+
] })
|
|
2743
|
+
}
|
|
2744
|
+
)
|
|
2745
|
+
] });
|
|
2746
|
+
}
|
|
2747
|
+
var BLOCK_EXPLORERS = {
|
|
2748
|
+
ethereum: "https://etherscan.io",
|
|
2749
|
+
base: "https://basescan.org",
|
|
2750
|
+
arbitrum: "https://arbiscan.io"
|
|
2751
|
+
};
|
|
2752
|
+
function TxStatus({ state }) {
|
|
2753
|
+
const { chainId } = useChain();
|
|
2754
|
+
if (state.status === "idle") return null;
|
|
2755
|
+
const explorer = BLOCK_EXPLORERS[chainId] || BLOCK_EXPLORERS.ethereum;
|
|
2756
|
+
return /* @__PURE__ */ jsxs(
|
|
2757
|
+
"div",
|
|
2758
|
+
{
|
|
2759
|
+
className: "mt-4 p-4 border",
|
|
2760
|
+
style: {
|
|
2761
|
+
borderColor: "var(--compass-color-border)",
|
|
2762
|
+
borderRadius: "var(--compass-border-radius-xl)",
|
|
2763
|
+
fontFamily: "var(--compass-font-family)"
|
|
2764
|
+
},
|
|
2765
|
+
children: [
|
|
2766
|
+
state.status === "preparing" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
2767
|
+
/* @__PURE__ */ jsx(
|
|
2768
|
+
Loader2,
|
|
2769
|
+
{
|
|
2770
|
+
className: "h-4 w-4 animate-spin",
|
|
2771
|
+
style: { color: "var(--compass-color-primary)" }
|
|
2772
|
+
}
|
|
2773
|
+
),
|
|
2774
|
+
/* @__PURE__ */ jsx("span", { style: { color: "var(--compass-color-text-secondary)" }, children: "Preparing transaction..." })
|
|
2775
|
+
] }),
|
|
2776
|
+
state.status === "signing" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
2777
|
+
/* @__PURE__ */ jsx(
|
|
2778
|
+
Loader2,
|
|
2779
|
+
{
|
|
2780
|
+
className: "h-4 w-4 animate-spin",
|
|
2781
|
+
style: { color: "var(--compass-color-warning)" }
|
|
2782
|
+
}
|
|
2783
|
+
),
|
|
2784
|
+
/* @__PURE__ */ jsx("span", { style: { color: "var(--compass-color-text-secondary)" }, children: "Waiting for signature..." })
|
|
2785
|
+
] }),
|
|
2786
|
+
state.status === "broadcasting" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
2787
|
+
/* @__PURE__ */ jsx(
|
|
2788
|
+
Loader2,
|
|
2789
|
+
{
|
|
2790
|
+
className: "h-4 w-4 animate-spin",
|
|
2791
|
+
style: { color: "var(--compass-color-primary)" }
|
|
2792
|
+
}
|
|
2793
|
+
),
|
|
2794
|
+
/* @__PURE__ */ jsx("span", { style: { color: "var(--compass-color-text-secondary)" }, children: "Broadcasting transaction..." })
|
|
2795
|
+
] }),
|
|
2796
|
+
state.status === "submitted" && /* @__PURE__ */ jsxs("div", { children: [
|
|
2797
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2798
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
2799
|
+
/* @__PURE__ */ jsx(
|
|
2800
|
+
Loader2,
|
|
2801
|
+
{
|
|
2802
|
+
className: "h-4 w-4 animate-spin",
|
|
2803
|
+
style: { color: "var(--compass-color-primary)" }
|
|
2804
|
+
}
|
|
2805
|
+
),
|
|
2806
|
+
/* @__PURE__ */ jsx("span", { style: { color: "var(--compass-color-text)" }, children: "Transaction submitted" })
|
|
2807
|
+
] }),
|
|
2808
|
+
/* @__PURE__ */ jsxs(
|
|
2809
|
+
"a",
|
|
2623
2810
|
{
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
},
|
|
2811
|
+
href: `${explorer}/tx/${state.txHash}`,
|
|
2812
|
+
target: "_blank",
|
|
2813
|
+
rel: "noopener noreferrer",
|
|
2814
|
+
className: "flex items-center gap-1.5 text-xs hover:opacity-70 transition-opacity",
|
|
2815
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2630
2816
|
children: [
|
|
2631
|
-
|
|
2632
|
-
/* @__PURE__ */
|
|
2633
|
-
/* @__PURE__ */ jsx("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-text)" }, children: formatAmount(token.balance) }),
|
|
2634
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: formatUSD(token.usdValue) })
|
|
2635
|
-
] })
|
|
2817
|
+
"View on explorer",
|
|
2818
|
+
/* @__PURE__ */ jsx(ExternalLink, { className: "h-3 w-3" })
|
|
2636
2819
|
]
|
|
2637
|
-
}
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2820
|
+
}
|
|
2821
|
+
)
|
|
2822
|
+
] }),
|
|
2823
|
+
/* @__PURE__ */ jsx(
|
|
2824
|
+
"p",
|
|
2825
|
+
{
|
|
2826
|
+
className: "text-xs mt-2",
|
|
2827
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
2828
|
+
children: "Waiting for on-chain confirmation. Balances will update automatically."
|
|
2829
|
+
}
|
|
2830
|
+
)
|
|
2831
|
+
] }),
|
|
2832
|
+
state.status === "confirmed" && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2833
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
2650
2834
|
/* @__PURE__ */ jsx(
|
|
2651
|
-
|
|
2835
|
+
CheckCircle,
|
|
2652
2836
|
{
|
|
2653
|
-
className: "
|
|
2654
|
-
style: { color: "var(--compass-color-
|
|
2655
|
-
children: formatUSD(totalUsdValue)
|
|
2837
|
+
className: "h-4 w-4",
|
|
2838
|
+
style: { color: "var(--compass-color-success)" }
|
|
2656
2839
|
}
|
|
2657
|
-
)
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
}
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2840
|
+
),
|
|
2841
|
+
/* @__PURE__ */ jsx("span", { style: { color: "var(--compass-color-success)" }, children: "Transaction confirmed" })
|
|
2842
|
+
] }),
|
|
2843
|
+
/* @__PURE__ */ jsxs(
|
|
2844
|
+
"a",
|
|
2845
|
+
{
|
|
2846
|
+
href: `${explorer}/tx/${state.txHash}`,
|
|
2847
|
+
target: "_blank",
|
|
2848
|
+
rel: "noopener noreferrer",
|
|
2849
|
+
className: "flex items-center gap-1.5 text-xs hover:opacity-70 transition-opacity",
|
|
2850
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
2851
|
+
children: [
|
|
2852
|
+
"View on explorer",
|
|
2853
|
+
/* @__PURE__ */ jsx(ExternalLink, { className: "h-3 w-3" })
|
|
2854
|
+
]
|
|
2855
|
+
}
|
|
2856
|
+
)
|
|
2857
|
+
] }),
|
|
2858
|
+
state.status === "failed" && /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 text-sm", children: [
|
|
2859
|
+
/* @__PURE__ */ jsx(
|
|
2860
|
+
XCircle,
|
|
2861
|
+
{
|
|
2862
|
+
className: "h-4 w-4 mt-0.5 shrink-0",
|
|
2863
|
+
style: { color: "var(--compass-color-error)" }
|
|
2864
|
+
}
|
|
2865
|
+
),
|
|
2866
|
+
/* @__PURE__ */ jsx(
|
|
2867
|
+
"span",
|
|
2868
|
+
{
|
|
2869
|
+
className: "break-all",
|
|
2870
|
+
style: { color: "var(--compass-color-error)" },
|
|
2871
|
+
children: state.error
|
|
2872
|
+
}
|
|
2873
|
+
)
|
|
2874
|
+
] })
|
|
2875
|
+
]
|
|
2876
|
+
}
|
|
2877
|
+
);
|
|
2878
|
+
}
|
|
2879
|
+
function useTxPolling(options = {}) {
|
|
2880
|
+
const { chainId } = useChain();
|
|
2881
|
+
const queryClient = useQueryClient();
|
|
2882
|
+
const pollIntervalRef = useRef(null);
|
|
2883
|
+
const clearPolling = useCallback(() => {
|
|
2884
|
+
if (pollIntervalRef.current) {
|
|
2885
|
+
clearInterval(pollIntervalRef.current);
|
|
2886
|
+
pollIntervalRef.current = null;
|
|
2887
|
+
}
|
|
2888
|
+
}, []);
|
|
2889
|
+
useEffect(() => {
|
|
2890
|
+
return () => clearPolling();
|
|
2891
|
+
}, [clearPolling]);
|
|
2892
|
+
const startPolling = useCallback(
|
|
2893
|
+
(txHash, setTxState) => {
|
|
2894
|
+
clearPolling();
|
|
2895
|
+
let polls = 0;
|
|
2896
|
+
pollIntervalRef.current = setInterval(async () => {
|
|
2897
|
+
polls++;
|
|
2898
|
+
for (const key of options.queryKeysToInvalidate ?? []) {
|
|
2899
|
+
queryClient.invalidateQueries({ queryKey: key });
|
|
2900
|
+
}
|
|
2901
|
+
try {
|
|
2902
|
+
const res = await fetch(
|
|
2903
|
+
`/api/compass/tx/receipt?hash=${txHash}&chain=${chainId}`
|
|
2904
|
+
);
|
|
2905
|
+
const data = await res.json();
|
|
2906
|
+
if (data.status === "success") {
|
|
2907
|
+
clearPolling();
|
|
2908
|
+
setTxState({ status: "confirmed", txHash });
|
|
2909
|
+
return;
|
|
2910
|
+
} else if (data.status === "reverted") {
|
|
2911
|
+
clearPolling();
|
|
2912
|
+
setTxState({ status: "failed", error: "Transaction reverted" });
|
|
2913
|
+
return;
|
|
2914
|
+
}
|
|
2915
|
+
} catch (err) {
|
|
2916
|
+
if (err instanceof TypeError && err.message.includes("fetch")) ; else {
|
|
2917
|
+
console.warn("[useTxPolling] Unexpected error polling tx receipt:", err);
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
if (polls >= 24) {
|
|
2921
|
+
clearPolling();
|
|
2922
|
+
setTxState({ status: "failed", error: "Unable to confirm transaction. Please check a block explorer to verify." });
|
|
2923
|
+
}
|
|
2924
|
+
}, 5e3);
|
|
2925
|
+
},
|
|
2926
|
+
[chainId, clearPolling, queryClient, options.queryKeysToInvalidate]
|
|
2927
|
+
);
|
|
2928
|
+
return { startPolling, clearPolling };
|
|
2929
|
+
}
|
|
2930
|
+
var USDC_ADDRESSES = {
|
|
2931
|
+
ethereum: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
2932
|
+
base: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
2933
|
+
arbitrum: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
|
|
2934
|
+
};
|
|
2935
|
+
var ERC20_TRANSFER_ABI = [
|
|
2936
|
+
{
|
|
2937
|
+
type: "function",
|
|
2938
|
+
name: "transfer",
|
|
2939
|
+
inputs: [
|
|
2940
|
+
{ name: "to", type: "address" },
|
|
2941
|
+
{ name: "amount", type: "uint256" }
|
|
2942
|
+
],
|
|
2943
|
+
outputs: [{ name: "", type: "bool" }],
|
|
2944
|
+
stateMutability: "nonpayable"
|
|
2945
|
+
}
|
|
2946
|
+
];
|
|
2947
|
+
async function waitForReceipt(txHash, chainId) {
|
|
2948
|
+
const maxPolls = 60;
|
|
2949
|
+
for (let i = 0; i < maxPolls; i++) {
|
|
2950
|
+
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
2951
|
+
try {
|
|
2952
|
+
const res = await fetch(`/api/compass/tx/receipt?hash=${txHash}&chain=${chainId}`);
|
|
2953
|
+
const data = await res.json();
|
|
2954
|
+
if (data.status === "success") return;
|
|
2955
|
+
if (data.status === "reverted") throw new Error("Withdrawal transaction reverted");
|
|
2956
|
+
} catch (err) {
|
|
2957
|
+
if (err instanceof Error && err.message.includes("reverted")) throw err;
|
|
2958
|
+
}
|
|
2959
|
+
}
|
|
2960
|
+
throw new Error("Unable to confirm withdrawal. Please check a block explorer to verify.");
|
|
2961
|
+
}
|
|
2962
|
+
function SendForm({ onComplete, product = "earn", productAccountAddress }) {
|
|
2963
|
+
const { sendTransaction, signTypedData, address } = useEmbeddableWallet();
|
|
2964
|
+
const { chainId } = useChain();
|
|
2965
|
+
const { earnAccountAddress, isDeployed } = useEarnAccount();
|
|
2966
|
+
const [recipient, setRecipient] = useState("");
|
|
2967
|
+
const [amount, setAmount] = useState("");
|
|
2968
|
+
const [txState, setTxState] = useState({ status: "idle" });
|
|
2969
|
+
const { startPolling } = useTxPolling({
|
|
2970
|
+
queryKeysToInvalidate: product === "credit" ? [["creditBalances"], ["creditPositions"], ["eoaBalances"]] : [["earnAccountBalances"], ["eoaBalances"]]
|
|
2971
|
+
});
|
|
2972
|
+
const { data: earnBalanceData } = useQuery({
|
|
2973
|
+
queryKey: ["earnAccountBalances", chainId, address],
|
|
2974
|
+
queryFn: async () => {
|
|
2975
|
+
if (!address) return null;
|
|
2976
|
+
const response = await fetch(
|
|
2977
|
+
`/api/compass/earn-account/balances?owner=${address}&chain=${chainId}`
|
|
2978
|
+
);
|
|
2979
|
+
if (!response.ok) return null;
|
|
2980
|
+
return response.json();
|
|
2981
|
+
},
|
|
2982
|
+
enabled: !!address && isDeployed && product === "earn",
|
|
2983
|
+
staleTime: 30 * 1e3
|
|
2984
|
+
});
|
|
2985
|
+
const { data: creditBalanceData } = useQuery({
|
|
2986
|
+
queryKey: ["creditBalances", productAccountAddress, chainId],
|
|
2987
|
+
queryFn: async () => {
|
|
2988
|
+
if (!productAccountAddress) return null;
|
|
2989
|
+
const response = await fetch(
|
|
2990
|
+
`/api/compass/credit/balances?owner=${productAccountAddress}&chain=${chainId}`
|
|
2991
|
+
);
|
|
2992
|
+
if (!response.ok) return null;
|
|
2993
|
+
return response.json();
|
|
2994
|
+
},
|
|
2995
|
+
enabled: !!productAccountAddress && product === "credit",
|
|
2996
|
+
staleTime: 30 * 1e3
|
|
2997
|
+
});
|
|
2998
|
+
const availableBalance = product === "credit" ? creditBalanceData?.find((b) => b.tokenSymbol === "USDC")?.amount || "0" : earnBalanceData?.balances?.["USDC"]?.balance || "0";
|
|
2999
|
+
const tokenAddress = USDC_ADDRESSES[chainId];
|
|
3000
|
+
const isValidAddress = recipient.length > 0 && isAddress(recipient);
|
|
3001
|
+
const isValidAmount = amount.length > 0 && parseFloat(amount) > 0;
|
|
3002
|
+
const exceedsBalance = isValidAmount && parseFloat(amount) > parseFloat(availableBalance);
|
|
3003
|
+
const isBusy = txState.status !== "idle" && txState.status !== "confirmed" && txState.status !== "failed";
|
|
3004
|
+
const canSend = isValidAddress && isValidAmount && !exceedsBalance && !!sendTransaction && !!signTypedData && !isBusy;
|
|
3005
|
+
const handleSend = useCallback(async () => {
|
|
3006
|
+
if (!sendTransaction || !signTypedData || !isValidAddress || !isValidAmount || !tokenAddress) return;
|
|
3007
|
+
try {
|
|
3008
|
+
setTxState({ status: "preparing" });
|
|
3009
|
+
const prepareRes = await fetch("/api/compass/transfer/prepare", {
|
|
3010
|
+
method: "POST",
|
|
3011
|
+
headers: { "Content-Type": "application/json" },
|
|
3012
|
+
body: JSON.stringify({
|
|
3013
|
+
owner: address,
|
|
3014
|
+
chain: chainId,
|
|
3015
|
+
token: "USDC",
|
|
3016
|
+
amount,
|
|
3017
|
+
action: "WITHDRAW",
|
|
3018
|
+
...product === "credit" ? { product: "credit" } : {}
|
|
3019
|
+
})
|
|
3020
|
+
});
|
|
3021
|
+
if (!prepareRes.ok) {
|
|
3022
|
+
const errData = await prepareRes.json();
|
|
3023
|
+
throw new Error(errData.error || "Failed to prepare withdrawal");
|
|
3024
|
+
}
|
|
3025
|
+
const prepareData = await prepareRes.json();
|
|
3026
|
+
setTxState({ status: "signing" });
|
|
3027
|
+
const withdrawSig = await signTypedData({
|
|
3028
|
+
domain: prepareData.domain,
|
|
3029
|
+
types: prepareData.normalizedTypes,
|
|
3030
|
+
primaryType: prepareData.primaryType,
|
|
3031
|
+
message: prepareData.message
|
|
3032
|
+
});
|
|
3033
|
+
setTxState({ status: "broadcasting" });
|
|
3034
|
+
const executeRes = await fetch("/api/compass/transfer/execute", {
|
|
3035
|
+
method: "POST",
|
|
3036
|
+
headers: { "Content-Type": "application/json" },
|
|
3037
|
+
body: JSON.stringify({
|
|
3038
|
+
owner: address,
|
|
3039
|
+
chain: chainId,
|
|
3040
|
+
eip712: prepareData.eip712,
|
|
3041
|
+
signature: withdrawSig,
|
|
3042
|
+
...product === "credit" ? { product: "credit" } : {}
|
|
3043
|
+
})
|
|
3044
|
+
});
|
|
3045
|
+
if (!executeRes.ok) {
|
|
3046
|
+
const errData = await executeRes.json();
|
|
3047
|
+
throw new Error(errData.error || "Withdrawal failed");
|
|
3048
|
+
}
|
|
3049
|
+
const { txHash: withdrawHash } = await executeRes.json();
|
|
3050
|
+
await waitForReceipt(withdrawHash, chainId);
|
|
3051
|
+
setTxState({ status: "signing" });
|
|
3052
|
+
const data = encodeFunctionData({
|
|
3053
|
+
abi: ERC20_TRANSFER_ABI,
|
|
3054
|
+
functionName: "transfer",
|
|
3055
|
+
args: [recipient, parseUnits(amount, 6)]
|
|
3056
|
+
});
|
|
3057
|
+
const sendHash = await sendTransaction({ to: tokenAddress, data });
|
|
3058
|
+
setTxState({ status: "submitted", txHash: sendHash });
|
|
3059
|
+
startPolling(sendHash, setTxState);
|
|
3060
|
+
setAmount("");
|
|
3061
|
+
setRecipient("");
|
|
3062
|
+
onComplete?.();
|
|
3063
|
+
} catch (err) {
|
|
3064
|
+
setTxState({ status: "failed", error: err instanceof Error ? err.message : "Transaction failed" });
|
|
3065
|
+
}
|
|
3066
|
+
}, [sendTransaction, signTypedData, recipient, amount, address, chainId, tokenAddress, isValidAddress, isValidAmount, onComplete, startPolling, product]);
|
|
3067
|
+
const chainName = chainId.charAt(0).toUpperCase() + chainId.slice(1);
|
|
3068
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
3069
|
+
/* @__PURE__ */ jsxs(
|
|
3070
|
+
"p",
|
|
3071
|
+
{
|
|
3072
|
+
className: "text-sm font-medium",
|
|
3073
|
+
style: { color: "var(--compass-color-text)", fontFamily: "var(--compass-font-family)" },
|
|
3074
|
+
children: [
|
|
3075
|
+
"Send USDC on ",
|
|
3076
|
+
chainName
|
|
3077
|
+
]
|
|
3078
|
+
}
|
|
3079
|
+
),
|
|
3080
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
3081
|
+
/* @__PURE__ */ jsx(
|
|
3082
|
+
"label",
|
|
3083
|
+
{
|
|
3084
|
+
className: "block text-sm mb-1.5",
|
|
3085
|
+
style: { color: "var(--compass-color-text-secondary)", fontFamily: "var(--compass-font-family)" },
|
|
3086
|
+
children: "Recipient Address"
|
|
3087
|
+
}
|
|
3088
|
+
),
|
|
3089
|
+
/* @__PURE__ */ jsx(
|
|
3090
|
+
"input",
|
|
3091
|
+
{
|
|
3092
|
+
type: "text",
|
|
3093
|
+
value: recipient,
|
|
3094
|
+
onChange: (e) => {
|
|
3095
|
+
setRecipient(e.target.value);
|
|
3096
|
+
if (txState.status === "failed") setTxState({ status: "idle" });
|
|
3097
|
+
},
|
|
3098
|
+
disabled: isBusy,
|
|
3099
|
+
placeholder: "0x...",
|
|
3100
|
+
className: "w-full border px-3 py-2.5 text-sm focus:outline-none disabled:opacity-50 font-mono",
|
|
3101
|
+
style: {
|
|
3102
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
3103
|
+
borderColor: recipient && !isValidAddress ? "var(--compass-color-error)" : "var(--compass-color-border)",
|
|
3104
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
3105
|
+
color: "var(--compass-color-text)",
|
|
3106
|
+
fontFamily: "var(--compass-font-family)"
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
),
|
|
3110
|
+
recipient && !isValidAddress && /* @__PURE__ */ jsx("p", { className: "text-xs mt-1", style: { color: "var(--compass-color-error)" }, children: "Invalid Ethereum address" }),
|
|
3111
|
+
isValidAddress && recipient.toLowerCase() === address?.toLowerCase() && /* @__PURE__ */ jsx("p", { className: "text-xs mt-1", style: { color: "var(--compass-color-warning, #f59e0b)" }, children: "This is your own wallet address" }),
|
|
3112
|
+
isValidAddress && earnAccountAddress && recipient.toLowerCase() === earnAccountAddress.toLowerCase() && /* @__PURE__ */ jsx("p", { className: "text-xs mt-1", style: { color: "var(--compass-color-warning, #f59e0b)" }, children: "This is your savings account address" })
|
|
3113
|
+
] }),
|
|
3114
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
3115
|
+
/* @__PURE__ */ jsx(
|
|
3116
|
+
"label",
|
|
3117
|
+
{
|
|
3118
|
+
className: "block text-sm mb-1.5",
|
|
3119
|
+
style: { color: "var(--compass-color-text-secondary)", fontFamily: "var(--compass-font-family)" },
|
|
3120
|
+
children: "Amount"
|
|
3121
|
+
}
|
|
3122
|
+
),
|
|
3123
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
3124
|
+
/* @__PURE__ */ jsx(
|
|
3125
|
+
"input",
|
|
3126
|
+
{
|
|
3127
|
+
type: "number",
|
|
3128
|
+
value: amount,
|
|
3129
|
+
onChange: (e) => {
|
|
3130
|
+
setAmount(e.target.value);
|
|
3131
|
+
if (txState.status === "failed") setTxState({ status: "idle" });
|
|
3132
|
+
},
|
|
3133
|
+
disabled: isBusy,
|
|
3134
|
+
placeholder: "0.00",
|
|
3135
|
+
className: "w-full border px-3 py-2.5 pr-14 text-sm focus:outline-none disabled:opacity-50",
|
|
3136
|
+
style: {
|
|
3137
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
3138
|
+
borderColor: "var(--compass-color-border)",
|
|
3139
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
3140
|
+
color: "var(--compass-color-text)",
|
|
3141
|
+
fontFamily: "var(--compass-font-family)"
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
),
|
|
3145
|
+
/* @__PURE__ */ jsx(
|
|
3146
|
+
"span",
|
|
3147
|
+
{
|
|
3148
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-xs",
|
|
3149
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
3150
|
+
children: "USDC"
|
|
3151
|
+
}
|
|
3152
|
+
)
|
|
3153
|
+
] }),
|
|
3154
|
+
/* @__PURE__ */ jsxs(
|
|
3155
|
+
"button",
|
|
3156
|
+
{
|
|
3157
|
+
onClick: () => setAmount(availableBalance),
|
|
3158
|
+
className: "text-xs mt-1",
|
|
3159
|
+
style: { color: "var(--compass-color-primary)", cursor: "pointer", background: "none", border: "none", padding: 0 },
|
|
3160
|
+
children: [
|
|
3161
|
+
"Available: ",
|
|
3162
|
+
parseFloat(availableBalance).toFixed(2),
|
|
3163
|
+
" USDC"
|
|
3164
|
+
]
|
|
3165
|
+
}
|
|
3166
|
+
),
|
|
3167
|
+
exceedsBalance && /* @__PURE__ */ jsx("p", { className: "text-xs mt-1", style: { color: "var(--compass-color-error)" }, children: "Amount exceeds available balance" })
|
|
3168
|
+
] }),
|
|
3169
|
+
/* @__PURE__ */ jsx(
|
|
3170
|
+
"p",
|
|
3171
|
+
{
|
|
3172
|
+
className: "text-xs",
|
|
3173
|
+
style: { color: "var(--compass-color-text-tertiary)", fontFamily: "var(--compass-font-family)" },
|
|
3174
|
+
children: "Send USDC from your account to any address. Requires 2 signatures. Gas fees are sponsored."
|
|
3175
|
+
}
|
|
3176
|
+
),
|
|
3177
|
+
/* @__PURE__ */ jsx(TxStatus, { state: txState }),
|
|
3178
|
+
/* @__PURE__ */ jsx(
|
|
3179
|
+
"button",
|
|
3180
|
+
{
|
|
3181
|
+
onClick: handleSend,
|
|
3182
|
+
disabled: !canSend,
|
|
3183
|
+
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",
|
|
3184
|
+
style: {
|
|
3185
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
3186
|
+
color: "white",
|
|
3187
|
+
borderRadius: "var(--compass-border-radius-xl)",
|
|
3188
|
+
fontFamily: "var(--compass-font-family)",
|
|
3189
|
+
transition: "var(--compass-transition-normal)"
|
|
3190
|
+
},
|
|
3191
|
+
children: isBusy ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3192
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
3193
|
+
"Sending..."
|
|
3194
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3195
|
+
/* @__PURE__ */ jsx(Send, { className: "h-4 w-4" }),
|
|
3196
|
+
"Send USDC"
|
|
3197
|
+
] })
|
|
3198
|
+
}
|
|
3199
|
+
)
|
|
3200
|
+
] });
|
|
3201
|
+
}
|
|
3202
|
+
function AccountBalancesModal({
|
|
3203
|
+
isOpen,
|
|
3204
|
+
onClose,
|
|
3205
|
+
balances,
|
|
3206
|
+
totalUsdValue,
|
|
3207
|
+
isLoading = false,
|
|
3208
|
+
earnAccountAddress,
|
|
3209
|
+
walletAddress
|
|
3210
|
+
}) {
|
|
3211
|
+
return /* @__PURE__ */ jsx(ActionModal, { isOpen, onClose, title: "Balance Breakdown", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
3212
|
+
(walletAddress || earnAccountAddress) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
3213
|
+
walletAddress && /* @__PURE__ */ jsx(CopyableAddress, { address: walletAddress, label: "Wallet" }),
|
|
3214
|
+
earnAccountAddress && /* @__PURE__ */ jsx(CopyableAddress, { address: earnAccountAddress, label: "Product Account" })
|
|
3215
|
+
] }),
|
|
3216
|
+
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ jsx(
|
|
3217
|
+
Loader2,
|
|
3218
|
+
{
|
|
3219
|
+
size: 24,
|
|
3220
|
+
className: "animate-spin",
|
|
3221
|
+
style: { color: "var(--compass-color-primary)" }
|
|
3222
|
+
}
|
|
3223
|
+
) }) : balances.length === 0 ? /* @__PURE__ */ jsx(
|
|
3224
|
+
"div",
|
|
3225
|
+
{
|
|
3226
|
+
className: "text-center py-4",
|
|
3227
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
3228
|
+
children: "No tokens in account"
|
|
3229
|
+
}
|
|
3230
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3231
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3232
|
+
/* @__PURE__ */ jsx(
|
|
3233
|
+
"span",
|
|
3234
|
+
{
|
|
3235
|
+
className: "text-xs font-medium uppercase tracking-wide",
|
|
3236
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
3237
|
+
children: "Available in Account"
|
|
3238
|
+
}
|
|
3239
|
+
),
|
|
3240
|
+
/* @__PURE__ */ jsx(
|
|
3241
|
+
"div",
|
|
3242
|
+
{
|
|
3243
|
+
className: "flex flex-col gap-2",
|
|
3244
|
+
style: {
|
|
3245
|
+
maxHeight: "50vh",
|
|
3246
|
+
overflowY: "auto",
|
|
3247
|
+
scrollbarWidth: "none"
|
|
3248
|
+
},
|
|
3249
|
+
children: balances.filter((token) => parseFloat(token.balance) >= 5e-3).map((token) => /* @__PURE__ */ jsxs(
|
|
3250
|
+
"div",
|
|
3251
|
+
{
|
|
3252
|
+
className: "flex items-center justify-between p-3 rounded-lg",
|
|
3253
|
+
style: {
|
|
3254
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
3255
|
+
border: "1px solid var(--compass-color-border)",
|
|
3256
|
+
flexShrink: 0
|
|
3257
|
+
},
|
|
3258
|
+
children: [
|
|
3259
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", style: { color: "var(--compass-color-text)" }, children: token.symbol }),
|
|
3260
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-end", children: [
|
|
3261
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-text)" }, children: formatAmount(token.balance) }),
|
|
3262
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: formatUSD(token.usdValue) })
|
|
3263
|
+
] })
|
|
3264
|
+
]
|
|
3265
|
+
},
|
|
3266
|
+
token.symbol
|
|
3267
|
+
))
|
|
3268
|
+
}
|
|
3269
|
+
)
|
|
3270
|
+
] }),
|
|
3271
|
+
/* @__PURE__ */ jsxs(
|
|
3272
|
+
"div",
|
|
3273
|
+
{
|
|
3274
|
+
className: "flex items-center justify-between pt-3 mt-2",
|
|
3275
|
+
style: { borderTop: "2px solid var(--compass-color-border)" },
|
|
3276
|
+
children: [
|
|
3277
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold", style: { color: "var(--compass-color-text)" }, children: "Total" }),
|
|
3278
|
+
/* @__PURE__ */ jsx(
|
|
3279
|
+
"span",
|
|
3280
|
+
{
|
|
3281
|
+
className: "font-bold text-xl",
|
|
3282
|
+
style: { color: "var(--compass-color-text)" },
|
|
3283
|
+
children: formatUSD(totalUsdValue)
|
|
3284
|
+
}
|
|
3285
|
+
)
|
|
3286
|
+
]
|
|
3287
|
+
}
|
|
3288
|
+
)
|
|
3289
|
+
] })
|
|
3290
|
+
] }) });
|
|
3291
|
+
}
|
|
3292
|
+
var TRANSFER_TOKEN = "USDC";
|
|
3293
|
+
var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
3294
|
+
compact = false,
|
|
3295
|
+
hideVisual = false,
|
|
2668
3296
|
onTransferComplete
|
|
2669
3297
|
}, ref) {
|
|
3298
|
+
const { address, isConnected, signTypedData, switchChain, walletChainId, fundWallet, hasExternalWallet, sendTransaction } = useEmbeddableWallet();
|
|
3299
|
+
const { chainId, chain } = useChain();
|
|
3300
|
+
const { earnAccountAddress, isDeployed } = useEarnAccount();
|
|
3301
|
+
const queryClient = useQueryClient();
|
|
3302
|
+
const showBuyTab = !!fundWallet;
|
|
3303
|
+
const showSendTab = !!sendTransaction && !hasExternalWallet;
|
|
3304
|
+
const buyOnly = !hasExternalWallet && showBuyTab && !sendTransaction;
|
|
2670
3305
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
2671
|
-
const [activeAction, setActiveAction] = useState(
|
|
3306
|
+
const [activeAction, setActiveAction] = useState(
|
|
3307
|
+
!hasExternalWallet && fundWallet ? "buy" : "deposit"
|
|
3308
|
+
);
|
|
2672
3309
|
const selectedToken = TRANSFER_TOKEN;
|
|
2673
3310
|
const [amount, setAmount] = useState("");
|
|
2674
|
-
const [
|
|
2675
|
-
const [statusMessage, setStatusMessage] = useState("");
|
|
2676
|
-
const [error, setError] = useState(null);
|
|
3311
|
+
const [txState, setTxState] = useState({ status: "idle" });
|
|
2677
3312
|
const [isBalancesModalOpen, setIsBalancesModalOpen] = useState(false);
|
|
2678
|
-
const {
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
const queryClient = useQueryClient();
|
|
3313
|
+
const { startPolling, clearPolling } = useTxPolling({
|
|
3314
|
+
queryKeysToInvalidate: [["earnAccountBalances"], ["eoaBalances"]]
|
|
3315
|
+
});
|
|
2682
3316
|
const { data: balanceData, isLoading: balancesLoading } = useQuery({
|
|
2683
3317
|
queryKey: ["earnAccountBalances", chainId, address],
|
|
2684
3318
|
queryFn: async () => {
|
|
@@ -2710,7 +3344,7 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
|
2710
3344
|
}
|
|
2711
3345
|
return {};
|
|
2712
3346
|
},
|
|
2713
|
-
enabled: !!address && activeAction === "deposit",
|
|
3347
|
+
enabled: !!address && hasExternalWallet && activeAction === "deposit",
|
|
2714
3348
|
staleTime: 30 * 1e3
|
|
2715
3349
|
});
|
|
2716
3350
|
const earnBalances = balanceData?.balances || {};
|
|
@@ -2729,10 +3363,9 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
|
2729
3363
|
}
|
|
2730
3364
|
const resetForm = useCallback(() => {
|
|
2731
3365
|
setAmount("");
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
}, []);
|
|
3366
|
+
setTxState({ status: "idle" });
|
|
3367
|
+
clearPolling();
|
|
3368
|
+
}, [clearPolling]);
|
|
2736
3369
|
const handleOpenModal = () => {
|
|
2737
3370
|
resetForm();
|
|
2738
3371
|
setIsModalOpen(true);
|
|
@@ -2747,7 +3380,8 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
|
2747
3380
|
const handleActionChange = (action) => {
|
|
2748
3381
|
setActiveAction(action);
|
|
2749
3382
|
setAmount("");
|
|
2750
|
-
|
|
3383
|
+
setTxState({ status: "idle" });
|
|
3384
|
+
clearPolling();
|
|
2751
3385
|
};
|
|
2752
3386
|
const getMaxBalance = () => {
|
|
2753
3387
|
if (activeAction === "deposit") {
|
|
@@ -2757,30 +3391,26 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
|
2757
3391
|
};
|
|
2758
3392
|
const handleTransfer = useCallback(async () => {
|
|
2759
3393
|
if (!address || !amount || !signTypedData) return;
|
|
2760
|
-
|
|
3394
|
+
setTxState({ status: "preparing" });
|
|
2761
3395
|
try {
|
|
2762
3396
|
const targetChainId = chain.viemChain.id;
|
|
2763
3397
|
if (walletChainId !== void 0 && walletChainId !== targetChainId) {
|
|
2764
3398
|
if (!switchChain) {
|
|
2765
3399
|
throw new Error(`Please switch your wallet to ${chain.name} (chain ID ${targetChainId}) to continue. Your wallet is currently on chain ID ${walletChainId}.`);
|
|
2766
3400
|
}
|
|
2767
|
-
setStatusMessage(`Switching network to ${chain.name}...`);
|
|
2768
3401
|
try {
|
|
2769
3402
|
await switchChain(targetChainId);
|
|
2770
|
-
} catch
|
|
3403
|
+
} catch {
|
|
2771
3404
|
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}.`);
|
|
2772
3405
|
}
|
|
2773
3406
|
} else if (switchChain && walletChainId === void 0) {
|
|
2774
|
-
setStatusMessage("Switching network...");
|
|
2775
3407
|
try {
|
|
2776
3408
|
await switchChain(targetChainId);
|
|
2777
|
-
} catch
|
|
3409
|
+
} catch {
|
|
2778
3410
|
throw new Error(`Please switch your wallet to ${chain.name} to continue`);
|
|
2779
3411
|
}
|
|
2780
3412
|
}
|
|
2781
3413
|
if (activeAction === "deposit") {
|
|
2782
|
-
setTransferState("checking_approval");
|
|
2783
|
-
setStatusMessage("Checking token approval...");
|
|
2784
3414
|
const approveResponse = await fetch("/api/compass/transfer/approve", {
|
|
2785
3415
|
method: "POST",
|
|
2786
3416
|
headers: { "Content-Type": "application/json" },
|
|
@@ -2799,16 +3429,14 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
|
2799
3429
|
if (approvalData.requiresTransaction) {
|
|
2800
3430
|
throw new Error("This token requires a transaction-based approval. Please approve manually.");
|
|
2801
3431
|
}
|
|
2802
|
-
|
|
2803
|
-
setStatusMessage("Please sign the approval...");
|
|
3432
|
+
setTxState({ status: "signing" });
|
|
2804
3433
|
const approvalSignature = await signTypedData({
|
|
2805
3434
|
domain: approvalData.domain,
|
|
2806
3435
|
types: approvalData.normalizedTypes,
|
|
2807
3436
|
primaryType: "Permit",
|
|
2808
3437
|
message: approvalData.message
|
|
2809
3438
|
});
|
|
2810
|
-
|
|
2811
|
-
setStatusMessage("Executing approval...");
|
|
3439
|
+
setTxState({ status: "broadcasting" });
|
|
2812
3440
|
const executeApprovalResponse = await fetch("/api/compass/transfer/execute", {
|
|
2813
3441
|
method: "POST",
|
|
2814
3442
|
headers: { "Content-Type": "application/json" },
|
|
@@ -2825,8 +3453,7 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
|
2825
3453
|
}
|
|
2826
3454
|
}
|
|
2827
3455
|
}
|
|
2828
|
-
|
|
2829
|
-
setStatusMessage("Preparing transfer...");
|
|
3456
|
+
setTxState({ status: "signing" });
|
|
2830
3457
|
const prepareResponse = await fetch("/api/compass/transfer/prepare", {
|
|
2831
3458
|
method: "POST",
|
|
2832
3459
|
headers: { "Content-Type": "application/json" },
|
|
@@ -2843,15 +3470,13 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
|
2843
3470
|
throw new Error(errData.error || "Failed to prepare transfer");
|
|
2844
3471
|
}
|
|
2845
3472
|
const prepareData = await prepareResponse.json();
|
|
2846
|
-
setStatusMessage("Please sign the transfer...");
|
|
2847
3473
|
const transferSignature = await signTypedData({
|
|
2848
3474
|
domain: prepareData.domain,
|
|
2849
3475
|
types: prepareData.normalizedTypes,
|
|
2850
3476
|
primaryType: prepareData.primaryType,
|
|
2851
3477
|
message: prepareData.message
|
|
2852
3478
|
});
|
|
2853
|
-
|
|
2854
|
-
setStatusMessage("Executing transfer...");
|
|
3479
|
+
setTxState({ status: "broadcasting" });
|
|
2855
3480
|
const executeResponse = await fetch("/api/compass/transfer/execute", {
|
|
2856
3481
|
method: "POST",
|
|
2857
3482
|
headers: { "Content-Type": "application/json" },
|
|
@@ -2867,17 +3492,12 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
|
2867
3492
|
throw new Error(errData.error || "Transfer failed");
|
|
2868
3493
|
}
|
|
2869
3494
|
const { txHash } = await executeResponse.json();
|
|
2870
|
-
|
|
2871
|
-
|
|
3495
|
+
setTxState({ status: "submitted", txHash });
|
|
3496
|
+
startPolling(txHash, setTxState);
|
|
2872
3497
|
onTransferComplete?.(activeAction, selectedToken, amount, txHash);
|
|
2873
|
-
|
|
2874
|
-
queryClient.invalidateQueries({ queryKey: ["eoaBalances"] });
|
|
2875
|
-
setTimeout(() => {
|
|
2876
|
-
resetForm();
|
|
2877
|
-
}, 2e3);
|
|
3498
|
+
setAmount("");
|
|
2878
3499
|
} catch (err) {
|
|
2879
|
-
|
|
2880
|
-
setError(err instanceof Error ? err.message : "Transfer failed");
|
|
3500
|
+
setTxState({ status: "failed", error: err instanceof Error ? err.message : "Transfer failed" });
|
|
2881
3501
|
}
|
|
2882
3502
|
}, [
|
|
2883
3503
|
address,
|
|
@@ -2889,14 +3509,13 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
|
2889
3509
|
walletChainId,
|
|
2890
3510
|
signTypedData,
|
|
2891
3511
|
switchChain,
|
|
2892
|
-
queryClient,
|
|
2893
3512
|
onTransferComplete,
|
|
2894
|
-
|
|
3513
|
+
startPolling
|
|
2895
3514
|
]);
|
|
2896
3515
|
if (!isConnected) {
|
|
2897
3516
|
return null;
|
|
2898
3517
|
}
|
|
2899
|
-
const isProcessing =
|
|
3518
|
+
const isProcessing = txState.status !== "idle" && txState.status !== "confirmed" && txState.status !== "failed";
|
|
2900
3519
|
if (!isDeployed && !hideVisual) {
|
|
2901
3520
|
return /* @__PURE__ */ jsxs(
|
|
2902
3521
|
"div",
|
|
@@ -2980,9 +3599,9 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
|
2980
3599
|
{
|
|
2981
3600
|
isOpen: isModalOpen,
|
|
2982
3601
|
onClose: handleCloseModal,
|
|
2983
|
-
title: "Transfer Funds",
|
|
3602
|
+
title: showSendTab ? "Manage Funds" : buyOnly ? "Add Funds" : "Transfer Funds",
|
|
2984
3603
|
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2985
|
-
/* @__PURE__ */ jsx(
|
|
3604
|
+
buyOnly ? null : /* @__PURE__ */ jsx(
|
|
2986
3605
|
"div",
|
|
2987
3606
|
{
|
|
2988
3607
|
className: "flex gap-1 p-1",
|
|
@@ -2991,7 +3610,9 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
|
2991
3610
|
borderRadius: "var(--compass-border-radius-lg)",
|
|
2992
3611
|
fontFamily: "var(--compass-font-family)"
|
|
2993
3612
|
},
|
|
2994
|
-
children: [
|
|
3613
|
+
children: [
|
|
3614
|
+
...showSendTab ? ["buy", "send"] : ["deposit", "withdraw", ...showBuyTab ? ["buy"] : []]
|
|
3615
|
+
].map((action) => /* @__PURE__ */ jsxs(
|
|
2995
3616
|
"button",
|
|
2996
3617
|
{
|
|
2997
3618
|
onClick: () => handleActionChange(action),
|
|
@@ -3003,7 +3624,7 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
|
3003
3624
|
borderRadius: "var(--compass-border-radius-md)"
|
|
3004
3625
|
},
|
|
3005
3626
|
children: [
|
|
3006
|
-
action === "deposit" ? /* @__PURE__ */ jsx(ArrowDownLeft, { size: 14 }) : /* @__PURE__ */ jsx(ArrowUpRight, { size: 14 }),
|
|
3627
|
+
action === "deposit" ? /* @__PURE__ */ jsx(ArrowDownLeft, { size: 14 }) : action === "withdraw" ? /* @__PURE__ */ jsx(ArrowUpRight, { size: 14 }) : action === "send" ? /* @__PURE__ */ jsx(Send, { size: 14 }) : /* @__PURE__ */ jsx(ArrowRight, { size: 14 }),
|
|
3007
3628
|
action
|
|
3008
3629
|
]
|
|
3009
3630
|
},
|
|
@@ -3011,120 +3632,116 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
|
|
|
3011
3632
|
))
|
|
3012
3633
|
}
|
|
3013
3634
|
),
|
|
3014
|
-
/* @__PURE__ */
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
{
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
children: "Amount"
|
|
3635
|
+
activeAction === "send" ? /* @__PURE__ */ jsx(
|
|
3636
|
+
SendForm,
|
|
3637
|
+
{
|
|
3638
|
+
onComplete: () => {
|
|
3639
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
3640
|
+
queryClient.invalidateQueries({ queryKey: ["eoaBalances"] });
|
|
3021
3641
|
}
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3642
|
+
}
|
|
3643
|
+
) : activeAction === "buy" || buyOnly ? /* @__PURE__ */ jsx(
|
|
3644
|
+
BuyForm,
|
|
3645
|
+
{
|
|
3646
|
+
targetAddress: earnAccountAddress || "",
|
|
3647
|
+
onComplete: () => {
|
|
3648
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
3649
|
+
queryClient.invalidateQueries({ queryKey: ["eoaBalances"] });
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3653
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
3654
|
+
/* @__PURE__ */ jsx(
|
|
3655
|
+
"label",
|
|
3656
|
+
{
|
|
3657
|
+
className: "text-sm font-medium mb-1 block",
|
|
3658
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
3659
|
+
children: "Amount"
|
|
3660
|
+
}
|
|
3661
|
+
),
|
|
3662
|
+
/* @__PURE__ */ jsxs(
|
|
3663
|
+
"div",
|
|
3664
|
+
{
|
|
3665
|
+
className: "flex items-center gap-2 p-3 border",
|
|
3666
|
+
style: {
|
|
3667
|
+
backgroundColor: "var(--compass-color-background)",
|
|
3668
|
+
borderColor: "var(--compass-color-border)",
|
|
3669
|
+
borderRadius: "var(--compass-border-radius-lg)"
|
|
3670
|
+
},
|
|
3671
|
+
children: [
|
|
3672
|
+
/* @__PURE__ */ jsx(
|
|
3673
|
+
"input",
|
|
3674
|
+
{
|
|
3675
|
+
type: "number",
|
|
3676
|
+
value: amount,
|
|
3677
|
+
onChange: (e) => {
|
|
3678
|
+
setAmount(e.target.value);
|
|
3679
|
+
if (txState.status === "failed") setTxState({ status: "idle" });
|
|
3680
|
+
},
|
|
3681
|
+
placeholder: "0.00",
|
|
3682
|
+
disabled: isProcessing,
|
|
3683
|
+
className: "flex-1 bg-transparent outline-none text-lg font-mono",
|
|
3684
|
+
style: { color: "var(--compass-color-text)" }
|
|
3685
|
+
}
|
|
3686
|
+
),
|
|
3687
|
+
/* @__PURE__ */ jsx(
|
|
3688
|
+
"span",
|
|
3689
|
+
{
|
|
3690
|
+
className: "text-sm font-medium",
|
|
3691
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
3692
|
+
children: "USDC"
|
|
3693
|
+
}
|
|
3694
|
+
)
|
|
3695
|
+
]
|
|
3696
|
+
}
|
|
3697
|
+
),
|
|
3698
|
+
/* @__PURE__ */ jsxs(
|
|
3699
|
+
"button",
|
|
3700
|
+
{
|
|
3701
|
+
onClick: () => setAmount(formatAmount(getMaxBalance())),
|
|
3702
|
+
className: "text-xs mt-1",
|
|
3703
|
+
style: { color: "var(--compass-color-primary)", cursor: "pointer", background: "none", border: "none", padding: 0 },
|
|
3704
|
+
children: [
|
|
3705
|
+
"Available: ",
|
|
3706
|
+
formatAmount(getMaxBalance()),
|
|
3707
|
+
" USDC"
|
|
3708
|
+
]
|
|
3709
|
+
}
|
|
3710
|
+
)
|
|
3711
|
+
] }),
|
|
3712
|
+
/* @__PURE__ */ 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." : ""}` }),
|
|
3713
|
+
/* @__PURE__ */ jsx(TxStatus, { state: txState }),
|
|
3714
|
+
/* @__PURE__ */ jsx(
|
|
3715
|
+
"button",
|
|
3025
3716
|
{
|
|
3026
|
-
|
|
3717
|
+
onClick: handleTransfer,
|
|
3718
|
+
disabled: isProcessing || !amount || parseFloat(amount) <= 0,
|
|
3719
|
+
className: "w-full py-3 font-medium transition-colors flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
3027
3720
|
style: {
|
|
3028
|
-
backgroundColor: "var(--compass-color-
|
|
3029
|
-
|
|
3030
|
-
borderRadius: "var(--compass-border-radius-lg)"
|
|
3721
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
3722
|
+
color: "var(--compass-color-primary-text)",
|
|
3723
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
3724
|
+
fontFamily: "var(--compass-font-family)"
|
|
3031
3725
|
},
|
|
3032
|
-
children: [
|
|
3033
|
-
/* @__PURE__ */ jsx(
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
setError(null);
|
|
3041
|
-
},
|
|
3042
|
-
placeholder: "0.00",
|
|
3043
|
-
disabled: isProcessing,
|
|
3044
|
-
className: "flex-1 bg-transparent outline-none text-lg font-mono",
|
|
3045
|
-
style: { color: "var(--compass-color-text)" }
|
|
3046
|
-
}
|
|
3047
|
-
),
|
|
3048
|
-
/* @__PURE__ */ jsx(
|
|
3049
|
-
"span",
|
|
3050
|
-
{
|
|
3051
|
-
className: "text-sm font-medium",
|
|
3052
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
3053
|
-
children: "USDC"
|
|
3054
|
-
}
|
|
3055
|
-
)
|
|
3056
|
-
]
|
|
3726
|
+
children: isProcessing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3727
|
+
/* @__PURE__ */ jsx(Loader2, { size: 18, className: "animate-spin" }),
|
|
3728
|
+
" Processing..."
|
|
3729
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3730
|
+
/* @__PURE__ */ jsx(ArrowUpRight, { size: 16 }),
|
|
3731
|
+
" ",
|
|
3732
|
+
activeAction === "deposit" ? "Transfer to Savings Account" : "Withdraw to Wallet"
|
|
3733
|
+
] })
|
|
3057
3734
|
}
|
|
3058
|
-
),
|
|
3059
|
-
/* @__PURE__ */
|
|
3060
|
-
"
|
|
3735
|
+
),
|
|
3736
|
+
/* @__PURE__ */ jsx(
|
|
3737
|
+
"p",
|
|
3061
3738
|
{
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
children: [
|
|
3066
|
-
"Available: ",
|
|
3067
|
-
formatAmount(getMaxBalance()),
|
|
3068
|
-
" USDC"
|
|
3069
|
-
]
|
|
3739
|
+
className: "text-xs text-center",
|
|
3740
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
3741
|
+
children: "Gas fees are sponsored by Compass"
|
|
3070
3742
|
}
|
|
3071
3743
|
)
|
|
3072
|
-
] })
|
|
3073
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: activeAction === "deposit" ? "Approves the token transfer, then transfers USDC from your wallet into your savings account. Requires 2 signatures." : "Withdraws USDC from your savings account back to your wallet. Requires 1 signature." }),
|
|
3074
|
-
error && /* @__PURE__ */ jsx(
|
|
3075
|
-
"div",
|
|
3076
|
-
{
|
|
3077
|
-
className: "p-3 text-sm",
|
|
3078
|
-
style: {
|
|
3079
|
-
backgroundColor: "var(--compass-color-error-muted)",
|
|
3080
|
-
color: "var(--compass-color-error)",
|
|
3081
|
-
borderRadius: "var(--compass-border-radius-lg)"
|
|
3082
|
-
},
|
|
3083
|
-
children: error
|
|
3084
|
-
}
|
|
3085
|
-
),
|
|
3086
|
-
statusMessage && !error && /* @__PURE__ */ jsx(
|
|
3087
|
-
"div",
|
|
3088
|
-
{
|
|
3089
|
-
className: "p-3 text-sm text-center",
|
|
3090
|
-
style: {
|
|
3091
|
-
backgroundColor: transferState === "success" ? "var(--compass-color-success-muted)" : "var(--compass-color-primary-muted)",
|
|
3092
|
-
color: transferState === "success" ? "var(--compass-color-success)" : "var(--compass-color-primary)",
|
|
3093
|
-
borderRadius: "var(--compass-border-radius-lg)"
|
|
3094
|
-
},
|
|
3095
|
-
children: statusMessage
|
|
3096
|
-
}
|
|
3097
|
-
),
|
|
3098
|
-
/* @__PURE__ */ jsx(
|
|
3099
|
-
"button",
|
|
3100
|
-
{
|
|
3101
|
-
onClick: handleTransfer,
|
|
3102
|
-
disabled: isProcessing || !amount || parseFloat(amount) <= 0,
|
|
3103
|
-
className: "w-full py-3 font-medium transition-colors flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
3104
|
-
style: {
|
|
3105
|
-
backgroundColor: "var(--compass-color-primary)",
|
|
3106
|
-
color: "var(--compass-color-primary-text)",
|
|
3107
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
3108
|
-
fontFamily: "var(--compass-font-family)"
|
|
3109
|
-
},
|
|
3110
|
-
children: isProcessing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3111
|
-
/* @__PURE__ */ jsx(Loader2, { size: 18, className: "animate-spin" }),
|
|
3112
|
-
" Processing..."
|
|
3113
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3114
|
-
/* @__PURE__ */ jsx(ArrowUpRight, { size: 16 }),
|
|
3115
|
-
" ",
|
|
3116
|
-
activeAction === "deposit" ? "Transfer to Savings Account" : "Withdraw to Wallet"
|
|
3117
|
-
] })
|
|
3118
|
-
}
|
|
3119
|
-
),
|
|
3120
|
-
/* @__PURE__ */ jsx(
|
|
3121
|
-
"p",
|
|
3122
|
-
{
|
|
3123
|
-
className: "text-xs text-center",
|
|
3124
|
-
style: { color: "var(--compass-color-text-tertiary)" },
|
|
3125
|
-
children: "Gas fees are sponsored by Compass"
|
|
3126
|
-
}
|
|
3127
|
-
)
|
|
3744
|
+
] })
|
|
3128
3745
|
] })
|
|
3129
3746
|
}
|
|
3130
3747
|
)
|
|
@@ -3179,7 +3796,7 @@ function truncate(value, decimals) {
|
|
|
3179
3796
|
const factor = Math.pow(10, decimals);
|
|
3180
3797
|
return (Math.floor(value * factor) / factor).toFixed(decimals);
|
|
3181
3798
|
}
|
|
3182
|
-
var
|
|
3799
|
+
var BLOCK_EXPLORERS2 = {
|
|
3183
3800
|
ethereum: "https://etherscan.io",
|
|
3184
3801
|
base: "https://basescan.org",
|
|
3185
3802
|
arbitrum: "https://arbiscan.io"
|
|
@@ -3650,7 +4267,7 @@ function SwapForm({
|
|
|
3650
4267
|
/* @__PURE__ */ jsxs(
|
|
3651
4268
|
"a",
|
|
3652
4269
|
{
|
|
3653
|
-
href: `${
|
|
4270
|
+
href: `${BLOCK_EXPLORERS2[chainId] || BLOCK_EXPLORERS2.ethereum}/tx/${lastTxHash}`,
|
|
3654
4271
|
target: "_blank",
|
|
3655
4272
|
rel: "noopener noreferrer",
|
|
3656
4273
|
style: { display: "flex", alignItems: "center", gap: "4px", color: "var(--compass-color-text-secondary)", fontSize: "0.75rem", textDecoration: "none" },
|
|
@@ -3840,8 +4457,7 @@ function MarketSelector({
|
|
|
3840
4457
|
},
|
|
3841
4458
|
children: [
|
|
3842
4459
|
getTypeLabel(selectedMarket.type),
|
|
3843
|
-
" \xB7 "
|
|
3844
|
-
formatTvl(selectedMarket.tvl)
|
|
4460
|
+
selectedMarket.type !== "aave" ? ` \xB7 ${formatTvl(selectedMarket.tvl)}` : ""
|
|
3845
4461
|
]
|
|
3846
4462
|
}
|
|
3847
4463
|
)
|
|
@@ -3947,8 +4563,7 @@ function MarketSelector({
|
|
|
3947
4563
|
},
|
|
3948
4564
|
children: [
|
|
3949
4565
|
getTypeLabel(market.type),
|
|
3950
|
-
" \xB7 "
|
|
3951
|
-
formatTvl(market.tvl)
|
|
4566
|
+
market.type !== "aave" ? ` \xB7 ${formatTvl(market.tvl)}` : ""
|
|
3952
4567
|
]
|
|
3953
4568
|
}
|
|
3954
4569
|
)
|
|
@@ -3977,7 +4592,7 @@ function MarketSelector({
|
|
|
3977
4592
|
)
|
|
3978
4593
|
] });
|
|
3979
4594
|
}
|
|
3980
|
-
var
|
|
4595
|
+
var BLOCK_EXPLORERS3 = {
|
|
3981
4596
|
ethereum: "https://etherscan.io",
|
|
3982
4597
|
base: "https://basescan.org",
|
|
3983
4598
|
arbitrum: "https://arbiscan.io"
|
|
@@ -4139,7 +4754,7 @@ function PositionCard({ position, chainId }) {
|
|
|
4139
4754
|
tx.txHash && /* @__PURE__ */ jsx(
|
|
4140
4755
|
"a",
|
|
4141
4756
|
{
|
|
4142
|
-
href: `${
|
|
4757
|
+
href: `${BLOCK_EXPLORERS3[chainId || "ethereum"] || BLOCK_EXPLORERS3.ethereum}/tx/${tx.txHash}`,
|
|
4143
4758
|
target: "_blank",
|
|
4144
4759
|
rel: "noopener noreferrer",
|
|
4145
4760
|
style: { color: "var(--compass-color-text-tertiary)", lineHeight: 0 },
|
|
@@ -4214,220 +4829,88 @@ function EarningsModal({ isOpen, onClose, positions, totalEarned, isLoading, cha
|
|
|
4214
4829
|
padding: "6px",
|
|
4215
4830
|
color: "var(--compass-color-text-secondary)",
|
|
4216
4831
|
borderRadius: "8px",
|
|
4217
|
-
display: "flex",
|
|
4218
|
-
alignItems: "center",
|
|
4219
|
-
justifyContent: "center"
|
|
4220
|
-
},
|
|
4221
|
-
children: /* @__PURE__ */ jsx(X, { size: 16 })
|
|
4222
|
-
}
|
|
4223
|
-
)
|
|
4224
|
-
] }),
|
|
4225
|
-
/* @__PURE__ */ jsxs("div", { style: {
|
|
4226
|
-
padding: "16px 20px",
|
|
4227
|
-
margin: "0 16px",
|
|
4228
|
-
backgroundColor: "var(--compass-color-surface)",
|
|
4229
|
-
borderRadius: "14px"
|
|
4230
|
-
}, children: [
|
|
4231
|
-
/* @__PURE__ */ jsxs("div", { style: {
|
|
4232
|
-
display: "flex",
|
|
4233
|
-
alignItems: "center",
|
|
4234
|
-
gap: "8px",
|
|
4235
|
-
marginBottom: "8px"
|
|
4236
|
-
}, children: [
|
|
4237
|
-
/* @__PURE__ */ jsx("div", { style: {
|
|
4238
|
-
width: "28px",
|
|
4239
|
-
height: "28px",
|
|
4240
|
-
borderRadius: "50%",
|
|
4241
|
-
backgroundColor: totalEarned >= 0 ? "var(--compass-color-success-muted)" : "var(--compass-color-error-muted)",
|
|
4242
|
-
display: "flex",
|
|
4243
|
-
alignItems: "center",
|
|
4244
|
-
justifyContent: "center"
|
|
4245
|
-
}, children: totalEarned >= 0 ? /* @__PURE__ */ jsx(TrendingUp, { size: 14, style: { color: "var(--compass-color-success)" } }) : /* @__PURE__ */ jsx(TrendingDown, { size: 14, style: { color: "var(--compass-color-error)" } }) }),
|
|
4246
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
4247
|
-
/* @__PURE__ */ jsx("div", { style: { fontSize: "0.6875rem", color: "var(--compass-color-text-tertiary)" }, children: "Total P&L" }),
|
|
4248
|
-
/* @__PURE__ */ jsxs("div", { style: {
|
|
4249
|
-
fontSize: "1.25rem",
|
|
4250
|
-
fontWeight: 700,
|
|
4251
|
-
color: totalEarned >= 0 ? "var(--compass-color-success)" : "var(--compass-color-error)",
|
|
4252
|
-
letterSpacing: "-0.02em"
|
|
4253
|
-
}, children: [
|
|
4254
|
-
totalEarned >= 0 ? "+" : "",
|
|
4255
|
-
formatCurrency(totalEarned)
|
|
4256
|
-
] })
|
|
4257
|
-
] })
|
|
4258
|
-
] }),
|
|
4259
|
-
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "16px" }, children: [
|
|
4260
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
4261
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: "0.6875rem", color: "var(--compass-color-text-tertiary)" }, children: "Unrealised " }),
|
|
4262
|
-
/* @__PURE__ */ jsxs("span", { style: {
|
|
4263
|
-
fontSize: "0.8125rem",
|
|
4264
|
-
fontWeight: 600,
|
|
4265
|
-
color: totalUnrealized >= 0 ? "var(--compass-color-success)" : "var(--compass-color-error)"
|
|
4266
|
-
}, children: [
|
|
4267
|
-
totalUnrealized >= 0 ? "+" : "",
|
|
4268
|
-
formatCurrency(totalUnrealized)
|
|
4269
|
-
] })
|
|
4270
|
-
] }),
|
|
4271
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
4272
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: "0.6875rem", color: "var(--compass-color-text-tertiary)" }, children: "Realised " }),
|
|
4273
|
-
/* @__PURE__ */ jsxs("span", { style: {
|
|
4274
|
-
fontSize: "0.8125rem",
|
|
4275
|
-
fontWeight: 600,
|
|
4276
|
-
color: totalRealized >= 0 ? "var(--compass-color-success)" : "var(--compass-color-error)"
|
|
4277
|
-
}, children: [
|
|
4278
|
-
totalRealized >= 0 ? "+" : "",
|
|
4279
|
-
formatCurrency(totalRealized)
|
|
4280
|
-
] })
|
|
4281
|
-
] })
|
|
4282
|
-
] })
|
|
4283
|
-
] }),
|
|
4284
|
-
/* @__PURE__ */ jsx("div", { style: {
|
|
4285
|
-
flex: 1,
|
|
4286
|
-
overflowY: "auto",
|
|
4287
|
-
scrollbarWidth: "none",
|
|
4288
|
-
padding: "16px",
|
|
4289
|
-
display: "flex",
|
|
4290
|
-
flexDirection: "column",
|
|
4291
|
-
gap: "10px"
|
|
4292
|
-
}, children: isLoading ? /* @__PURE__ */ jsx("div", { style: { textAlign: "center", padding: "32px 0", color: "var(--compass-color-text-tertiary)", fontSize: "0.875rem" }, children: "Loading positions..." }) : positions.length === 0 ? /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "32px 0" }, children: [
|
|
4293
|
-
/* @__PURE__ */ jsx("p", { style: { color: "var(--compass-color-text-secondary)", fontSize: "0.9375rem", margin: "0 0 4px" }, children: "No active positions yet" }),
|
|
4294
|
-
/* @__PURE__ */ jsx("p", { style: { color: "var(--compass-color-text-tertiary)", fontSize: "0.8125rem", margin: 0 }, children: "Deposit into a market to start earning" })
|
|
4295
|
-
] }) : positions.map((position) => /* @__PURE__ */ jsx(PositionCard, { position, chainId }, position.id)) })
|
|
4296
|
-
]
|
|
4297
|
-
}
|
|
4298
|
-
)
|
|
4299
|
-
}
|
|
4300
|
-
);
|
|
4301
|
-
}
|
|
4302
|
-
var BLOCK_EXPLORERS3 = {
|
|
4303
|
-
ethereum: "https://etherscan.io",
|
|
4304
|
-
base: "https://basescan.org",
|
|
4305
|
-
arbitrum: "https://arbiscan.io"
|
|
4306
|
-
};
|
|
4307
|
-
function TxStatus({ state }) {
|
|
4308
|
-
const { chainId } = useChain();
|
|
4309
|
-
if (state.status === "idle") return null;
|
|
4310
|
-
const explorer = BLOCK_EXPLORERS3[chainId] || BLOCK_EXPLORERS3.ethereum;
|
|
4311
|
-
return /* @__PURE__ */ jsxs(
|
|
4312
|
-
"div",
|
|
4313
|
-
{
|
|
4314
|
-
className: "mt-4 p-4 border",
|
|
4315
|
-
style: {
|
|
4316
|
-
borderColor: "var(--compass-color-border)",
|
|
4317
|
-
borderRadius: "var(--compass-border-radius-xl)",
|
|
4318
|
-
fontFamily: "var(--compass-font-family)"
|
|
4319
|
-
},
|
|
4320
|
-
children: [
|
|
4321
|
-
state.status === "preparing" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
4322
|
-
/* @__PURE__ */ jsx(
|
|
4323
|
-
Loader2,
|
|
4324
|
-
{
|
|
4325
|
-
className: "h-4 w-4 animate-spin",
|
|
4326
|
-
style: { color: "var(--compass-color-primary)" }
|
|
4327
|
-
}
|
|
4328
|
-
),
|
|
4329
|
-
/* @__PURE__ */ jsx("span", { style: { color: "var(--compass-color-text-secondary)" }, children: "Preparing transaction..." })
|
|
4330
|
-
] }),
|
|
4331
|
-
state.status === "signing" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
4332
|
-
/* @__PURE__ */ jsx(
|
|
4333
|
-
Loader2,
|
|
4334
|
-
{
|
|
4335
|
-
className: "h-4 w-4 animate-spin",
|
|
4336
|
-
style: { color: "var(--compass-color-warning)" }
|
|
4337
|
-
}
|
|
4338
|
-
),
|
|
4339
|
-
/* @__PURE__ */ jsx("span", { style: { color: "var(--compass-color-text-secondary)" }, children: "Waiting for signature..." })
|
|
4340
|
-
] }),
|
|
4341
|
-
state.status === "broadcasting" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
4342
|
-
/* @__PURE__ */ jsx(
|
|
4343
|
-
Loader2,
|
|
4344
|
-
{
|
|
4345
|
-
className: "h-4 w-4 animate-spin",
|
|
4346
|
-
style: { color: "var(--compass-color-primary)" }
|
|
4347
|
-
}
|
|
4348
|
-
),
|
|
4349
|
-
/* @__PURE__ */ jsx("span", { style: { color: "var(--compass-color-text-secondary)" }, children: "Broadcasting transaction..." })
|
|
4350
|
-
] }),
|
|
4351
|
-
state.status === "submitted" && /* @__PURE__ */ jsxs("div", { children: [
|
|
4352
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
4353
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
4354
|
-
/* @__PURE__ */ jsx(
|
|
4355
|
-
Loader2,
|
|
4356
|
-
{
|
|
4357
|
-
className: "h-4 w-4 animate-spin",
|
|
4358
|
-
style: { color: "var(--compass-color-primary)" }
|
|
4359
|
-
}
|
|
4360
|
-
),
|
|
4361
|
-
/* @__PURE__ */ jsx("span", { style: { color: "var(--compass-color-text)" }, children: "Transaction submitted" })
|
|
4362
|
-
] }),
|
|
4363
|
-
/* @__PURE__ */ jsxs(
|
|
4364
|
-
"a",
|
|
4365
|
-
{
|
|
4366
|
-
href: `${explorer}/tx/${state.txHash}`,
|
|
4367
|
-
target: "_blank",
|
|
4368
|
-
rel: "noopener noreferrer",
|
|
4369
|
-
className: "flex items-center gap-1.5 text-xs hover:opacity-70 transition-opacity",
|
|
4370
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
4371
|
-
children: [
|
|
4372
|
-
"View on explorer",
|
|
4373
|
-
/* @__PURE__ */ jsx(ExternalLink, { className: "h-3 w-3" })
|
|
4374
|
-
]
|
|
4375
|
-
}
|
|
4376
|
-
)
|
|
4377
|
-
] }),
|
|
4378
|
-
/* @__PURE__ */ jsx(
|
|
4379
|
-
"p",
|
|
4380
|
-
{
|
|
4381
|
-
className: "text-xs mt-2",
|
|
4382
|
-
style: { color: "var(--compass-color-text-tertiary)" },
|
|
4383
|
-
children: "Waiting for on-chain confirmation. Balances will update automatically."
|
|
4384
|
-
}
|
|
4385
|
-
)
|
|
4386
|
-
] }),
|
|
4387
|
-
state.status === "confirmed" && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
4388
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
4389
|
-
/* @__PURE__ */ jsx(
|
|
4390
|
-
CheckCircle,
|
|
4391
|
-
{
|
|
4392
|
-
className: "h-4 w-4",
|
|
4393
|
-
style: { color: "var(--compass-color-success)" }
|
|
4394
|
-
}
|
|
4395
|
-
),
|
|
4396
|
-
/* @__PURE__ */ jsx("span", { style: { color: "var(--compass-color-success)" }, children: "Transaction confirmed" })
|
|
4397
|
-
] }),
|
|
4398
|
-
/* @__PURE__ */ 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__ */ jsx(ExternalLink, { className: "h-3 w-3" })
|
|
4409
|
-
]
|
|
4410
|
-
}
|
|
4411
|
-
)
|
|
4412
|
-
] }),
|
|
4413
|
-
state.status === "failed" && /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 text-sm", children: [
|
|
4414
|
-
/* @__PURE__ */ jsx(
|
|
4415
|
-
XCircle,
|
|
4416
|
-
{
|
|
4417
|
-
className: "h-4 w-4 mt-0.5 shrink-0",
|
|
4418
|
-
style: { color: "var(--compass-color-error)" }
|
|
4419
|
-
}
|
|
4420
|
-
),
|
|
4421
|
-
/* @__PURE__ */ jsx(
|
|
4422
|
-
"span",
|
|
4423
|
-
{
|
|
4424
|
-
className: "break-all",
|
|
4425
|
-
style: { color: "var(--compass-color-error)" },
|
|
4426
|
-
children: state.error
|
|
4427
|
-
}
|
|
4428
|
-
)
|
|
4429
|
-
] })
|
|
4430
|
-
]
|
|
4832
|
+
display: "flex",
|
|
4833
|
+
alignItems: "center",
|
|
4834
|
+
justifyContent: "center"
|
|
4835
|
+
},
|
|
4836
|
+
children: /* @__PURE__ */ jsx(X, { size: 16 })
|
|
4837
|
+
}
|
|
4838
|
+
)
|
|
4839
|
+
] }),
|
|
4840
|
+
/* @__PURE__ */ jsxs("div", { style: {
|
|
4841
|
+
padding: "16px 20px",
|
|
4842
|
+
margin: "0 16px",
|
|
4843
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
4844
|
+
borderRadius: "14px"
|
|
4845
|
+
}, children: [
|
|
4846
|
+
/* @__PURE__ */ jsxs("div", { style: {
|
|
4847
|
+
display: "flex",
|
|
4848
|
+
alignItems: "center",
|
|
4849
|
+
gap: "8px",
|
|
4850
|
+
marginBottom: "8px"
|
|
4851
|
+
}, children: [
|
|
4852
|
+
/* @__PURE__ */ jsx("div", { style: {
|
|
4853
|
+
width: "28px",
|
|
4854
|
+
height: "28px",
|
|
4855
|
+
borderRadius: "50%",
|
|
4856
|
+
backgroundColor: totalEarned >= 0 ? "var(--compass-color-success-muted)" : "var(--compass-color-error-muted)",
|
|
4857
|
+
display: "flex",
|
|
4858
|
+
alignItems: "center",
|
|
4859
|
+
justifyContent: "center"
|
|
4860
|
+
}, children: totalEarned >= 0 ? /* @__PURE__ */ jsx(TrendingUp, { size: 14, style: { color: "var(--compass-color-success)" } }) : /* @__PURE__ */ jsx(TrendingDown, { size: 14, style: { color: "var(--compass-color-error)" } }) }),
|
|
4861
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4862
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: "0.6875rem", color: "var(--compass-color-text-tertiary)" }, children: "Total P&L" }),
|
|
4863
|
+
/* @__PURE__ */ jsxs("div", { style: {
|
|
4864
|
+
fontSize: "1.25rem",
|
|
4865
|
+
fontWeight: 700,
|
|
4866
|
+
color: totalEarned >= 0 ? "var(--compass-color-success)" : "var(--compass-color-error)",
|
|
4867
|
+
letterSpacing: "-0.02em"
|
|
4868
|
+
}, children: [
|
|
4869
|
+
totalEarned >= 0 ? "+" : "",
|
|
4870
|
+
formatCurrency(totalEarned)
|
|
4871
|
+
] })
|
|
4872
|
+
] })
|
|
4873
|
+
] }),
|
|
4874
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "16px" }, children: [
|
|
4875
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4876
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: "0.6875rem", color: "var(--compass-color-text-tertiary)" }, children: "Unrealised " }),
|
|
4877
|
+
/* @__PURE__ */ jsxs("span", { style: {
|
|
4878
|
+
fontSize: "0.8125rem",
|
|
4879
|
+
fontWeight: 600,
|
|
4880
|
+
color: totalUnrealized >= 0 ? "var(--compass-color-success)" : "var(--compass-color-error)"
|
|
4881
|
+
}, children: [
|
|
4882
|
+
totalUnrealized >= 0 ? "+" : "",
|
|
4883
|
+
formatCurrency(totalUnrealized)
|
|
4884
|
+
] })
|
|
4885
|
+
] }),
|
|
4886
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4887
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: "0.6875rem", color: "var(--compass-color-text-tertiary)" }, children: "Realised " }),
|
|
4888
|
+
/* @__PURE__ */ jsxs("span", { style: {
|
|
4889
|
+
fontSize: "0.8125rem",
|
|
4890
|
+
fontWeight: 600,
|
|
4891
|
+
color: totalRealized >= 0 ? "var(--compass-color-success)" : "var(--compass-color-error)"
|
|
4892
|
+
}, children: [
|
|
4893
|
+
totalRealized >= 0 ? "+" : "",
|
|
4894
|
+
formatCurrency(totalRealized)
|
|
4895
|
+
] })
|
|
4896
|
+
] })
|
|
4897
|
+
] })
|
|
4898
|
+
] }),
|
|
4899
|
+
/* @__PURE__ */ jsx("div", { style: {
|
|
4900
|
+
flex: 1,
|
|
4901
|
+
overflowY: "auto",
|
|
4902
|
+
scrollbarWidth: "none",
|
|
4903
|
+
padding: "16px",
|
|
4904
|
+
display: "flex",
|
|
4905
|
+
flexDirection: "column",
|
|
4906
|
+
gap: "10px"
|
|
4907
|
+
}, children: isLoading ? /* @__PURE__ */ jsx("div", { style: { textAlign: "center", padding: "32px 0", color: "var(--compass-color-text-tertiary)", fontSize: "0.875rem" }, children: "Loading positions..." }) : positions.length === 0 ? /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "32px 0" }, children: [
|
|
4908
|
+
/* @__PURE__ */ jsx("p", { style: { color: "var(--compass-color-text-secondary)", fontSize: "0.9375rem", margin: "0 0 4px" }, children: "No active positions yet" }),
|
|
4909
|
+
/* @__PURE__ */ jsx("p", { style: { color: "var(--compass-color-text-tertiary)", fontSize: "0.8125rem", margin: 0 }, children: "Deposit into a market to start earning" })
|
|
4910
|
+
] }) : positions.map((position) => /* @__PURE__ */ jsx(PositionCard, { position, chainId }, position.id)) })
|
|
4911
|
+
]
|
|
4912
|
+
}
|
|
4913
|
+
)
|
|
4431
4914
|
}
|
|
4432
4915
|
);
|
|
4433
4916
|
}
|
|
@@ -4435,7 +4918,7 @@ function truncate2(value, decimals) {
|
|
|
4435
4918
|
const factor = Math.pow(10, decimals);
|
|
4436
4919
|
return (Math.floor(value * factor) / factor).toFixed(decimals);
|
|
4437
4920
|
}
|
|
4438
|
-
var
|
|
4921
|
+
var EVM_CHAIN_IDS2 = {
|
|
4439
4922
|
ethereum: 1,
|
|
4440
4923
|
base: 8453,
|
|
4441
4924
|
arbitrum: 42161
|
|
@@ -4476,8 +4959,8 @@ function EarnAccount({
|
|
|
4476
4959
|
chain: chainProp,
|
|
4477
4960
|
height = "600px"
|
|
4478
4961
|
}) {
|
|
4479
|
-
const { address, isConnected, login, logout, signTypedData, switchChain, walletChainId } = useEmbeddableWallet();
|
|
4480
|
-
const { isDeployed } = useEarnAccount();
|
|
4962
|
+
const { address, isConnected, login, logout, signTypedData, switchChain, walletChainId, fundWallet, hasExternalWallet, sendTransaction } = useEmbeddableWallet();
|
|
4963
|
+
const { isDeployed, earnAccountAddress } = useEarnAccount();
|
|
4481
4964
|
const { chainId: contextChainId } = useChain();
|
|
4482
4965
|
const CHAIN_ID = chainProp || contextChainId;
|
|
4483
4966
|
const queryClient = useQueryClient();
|
|
@@ -4491,10 +4974,15 @@ function EarnAccount({
|
|
|
4491
4974
|
const [isTokenDropdownOpen, setIsTokenDropdownOpen] = useState(false);
|
|
4492
4975
|
const [isFundModalOpen, setIsFundModalOpen] = useState(false);
|
|
4493
4976
|
const [fundAmount, setFundAmount] = useState("");
|
|
4494
|
-
const [fundAction, setFundAction] = useState(
|
|
4977
|
+
const [fundAction, setFundAction] = useState(
|
|
4978
|
+
!hasExternalWallet && fundWallet ? "buy" : "deposit"
|
|
4979
|
+
);
|
|
4495
4980
|
const [fundStep, setFundStep] = useState("idle");
|
|
4496
4981
|
const [fundTxState, setFundTxState] = useState({ status: "idle" });
|
|
4497
4982
|
const fundPollRef = useRef(null);
|
|
4983
|
+
const showBuyTab = !!fundWallet;
|
|
4984
|
+
const showSendTab = !!sendTransaction && !hasExternalWallet;
|
|
4985
|
+
const fundBuyOnly = !hasExternalWallet && showBuyTab && !sendTransaction;
|
|
4498
4986
|
const actionPollRef = useRef(null);
|
|
4499
4987
|
const actionTimeoutRef = useRef(null);
|
|
4500
4988
|
const [isBalancesModalOpen, setIsBalancesModalOpen] = useState(false);
|
|
@@ -4534,7 +5022,7 @@ function EarnAccount({
|
|
|
4534
5022
|
const fundIsValid = Number(fundAmount) > 0 && !!address && isDeployed;
|
|
4535
5023
|
const fundPhase = getFundPhase(fundStep);
|
|
4536
5024
|
const ensureCorrectChain = useCallback(async () => {
|
|
4537
|
-
const targetChainId =
|
|
5025
|
+
const targetChainId = EVM_CHAIN_IDS2[CHAIN_ID];
|
|
4538
5026
|
if (!targetChainId) return;
|
|
4539
5027
|
if (walletChainId !== void 0 && walletChainId !== targetChainId) {
|
|
4540
5028
|
if (!switchChain) {
|
|
@@ -4558,7 +5046,7 @@ function EarnAccount({
|
|
|
4558
5046
|
return null;
|
|
4559
5047
|
}
|
|
4560
5048
|
},
|
|
4561
|
-
enabled: !!address && isFundModalOpen && fundAction === "deposit",
|
|
5049
|
+
enabled: !!address && hasExternalWallet && isFundModalOpen && fundAction === "deposit",
|
|
4562
5050
|
staleTime: 15 * 1e3
|
|
4563
5051
|
});
|
|
4564
5052
|
const walletBalance = walletBalanceQuery.data?.balance || "0";
|
|
@@ -4842,7 +5330,10 @@ function EarnAccount({
|
|
|
4842
5330
|
setFundTxState({ status: "failed", error: "Transaction reverted" });
|
|
4843
5331
|
return;
|
|
4844
5332
|
}
|
|
4845
|
-
} catch {
|
|
5333
|
+
} catch (err) {
|
|
5334
|
+
if (err instanceof TypeError && err.message.includes("fetch")) ; else {
|
|
5335
|
+
console.warn("[EarnAccount] Unexpected error polling tx receipt:", err);
|
|
5336
|
+
}
|
|
4846
5337
|
}
|
|
4847
5338
|
if (polls >= 24) {
|
|
4848
5339
|
clearFundPolling();
|
|
@@ -5733,13 +6224,13 @@ function EarnAccount({
|
|
|
5733
6224
|
onClose: () => {
|
|
5734
6225
|
setIsFundModalOpen(false);
|
|
5735
6226
|
setFundAmount("");
|
|
5736
|
-
setFundAction("deposit");
|
|
6227
|
+
setFundAction(fundBuyOnly ? "buy" : showSendTab ? "buy" : "deposit");
|
|
5737
6228
|
setFundStep("idle");
|
|
5738
6229
|
setFundTxState({ status: "idle" });
|
|
5739
6230
|
},
|
|
5740
|
-
title: "Transfer Funds",
|
|
6231
|
+
title: showSendTab ? "Manage Funds" : fundBuyOnly ? "Add Funds" : "Transfer Funds",
|
|
5741
6232
|
children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
5742
|
-
/* @__PURE__ */ jsx(
|
|
6233
|
+
fundBuyOnly ? null : /* @__PURE__ */ jsx(
|
|
5743
6234
|
"div",
|
|
5744
6235
|
{
|
|
5745
6236
|
className: "flex gap-1 p-1",
|
|
@@ -5748,7 +6239,9 @@ function EarnAccount({
|
|
|
5748
6239
|
borderRadius: "var(--compass-border-radius-lg)",
|
|
5749
6240
|
fontFamily: "var(--compass-font-family)"
|
|
5750
6241
|
},
|
|
5751
|
-
children: [
|
|
6242
|
+
children: [
|
|
6243
|
+
...showSendTab ? ["buy", "send"] : ["deposit", "withdraw", ...showBuyTab ? ["buy"] : []]
|
|
6244
|
+
].map((tab) => /* @__PURE__ */ jsxs(
|
|
5752
6245
|
"button",
|
|
5753
6246
|
{
|
|
5754
6247
|
onClick: () => handleFundActionChange(tab),
|
|
@@ -5761,7 +6254,7 @@ function EarnAccount({
|
|
|
5761
6254
|
border: "none"
|
|
5762
6255
|
},
|
|
5763
6256
|
children: [
|
|
5764
|
-
tab === "deposit" ? /* @__PURE__ */ jsx(ArrowDownLeft, { size: 14 }) : /* @__PURE__ */ jsx(ArrowUpRight, { size: 14 }),
|
|
6257
|
+
tab === "deposit" ? /* @__PURE__ */ jsx(ArrowDownLeft, { size: 14 }) : tab === "withdraw" ? /* @__PURE__ */ jsx(ArrowUpRight, { size: 14 }) : tab === "send" ? /* @__PURE__ */ jsx(Send, { size: 14 }) : /* @__PURE__ */ jsx(ArrowRight, { size: 14 }),
|
|
5765
6258
|
tab
|
|
5766
6259
|
]
|
|
5767
6260
|
},
|
|
@@ -5769,137 +6262,158 @@ function EarnAccount({
|
|
|
5769
6262
|
))
|
|
5770
6263
|
}
|
|
5771
6264
|
),
|
|
5772
|
-
|
|
5773
|
-
|
|
6265
|
+
fundAction === "send" ? /* @__PURE__ */ jsx(
|
|
6266
|
+
SendForm,
|
|
5774
6267
|
{
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
},
|
|
5781
|
-
children: [
|
|
5782
|
-
/* @__PURE__ */ jsx(
|
|
5783
|
-
FundStepIndicator,
|
|
5784
|
-
{
|
|
5785
|
-
number: 1,
|
|
5786
|
-
label: "Approve",
|
|
5787
|
-
state: fundPhase > 1 ? "done" : fundPhase === 1 ? "active" : "pending"
|
|
5788
|
-
}
|
|
5789
|
-
),
|
|
5790
|
-
/* @__PURE__ */ jsx(
|
|
5791
|
-
FundStepIndicator,
|
|
5792
|
-
{
|
|
5793
|
-
number: 2,
|
|
5794
|
-
label: "Transfer",
|
|
5795
|
-
state: fundStep === "confirmed" ? "done" : fundPhase > 1 ? "active" : "pending"
|
|
5796
|
-
}
|
|
5797
|
-
)
|
|
5798
|
-
]
|
|
6268
|
+
onComplete: () => {
|
|
6269
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
6270
|
+
queryClient.invalidateQueries({ queryKey: ["walletBalance"] });
|
|
6271
|
+
queryClient.invalidateQueries({ queryKey: ["walletTokenBalance"] });
|
|
6272
|
+
}
|
|
5799
6273
|
}
|
|
5800
|
-
)
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
"
|
|
6274
|
+
) : fundAction === "buy" || fundBuyOnly ? /* @__PURE__ */ jsx(
|
|
6275
|
+
BuyForm,
|
|
6276
|
+
{
|
|
6277
|
+
targetAddress: earnAccountAddress || "",
|
|
6278
|
+
onComplete: () => {
|
|
6279
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
6280
|
+
queryClient.invalidateQueries({ queryKey: ["walletBalance"] });
|
|
6281
|
+
queryClient.invalidateQueries({ queryKey: ["walletTokenBalance"] });
|
|
6282
|
+
}
|
|
6283
|
+
}
|
|
6284
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6285
|
+
(fundIsBusy || fundStep === "confirmed") && fundAction === "deposit" && /* @__PURE__ */ jsxs(
|
|
6286
|
+
"div",
|
|
5804
6287
|
{
|
|
5805
|
-
className: "
|
|
6288
|
+
className: "flex gap-3 p-3 text-xs",
|
|
5806
6289
|
style: {
|
|
5807
|
-
|
|
6290
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
6291
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
5808
6292
|
fontFamily: "var(--compass-font-family)"
|
|
5809
6293
|
},
|
|
5810
|
-
children:
|
|
6294
|
+
children: [
|
|
6295
|
+
/* @__PURE__ */ jsx(
|
|
6296
|
+
FundStepIndicator,
|
|
6297
|
+
{
|
|
6298
|
+
number: 1,
|
|
6299
|
+
label: "Approve",
|
|
6300
|
+
state: fundPhase > 1 ? "done" : fundPhase === 1 ? "active" : "pending"
|
|
6301
|
+
}
|
|
6302
|
+
),
|
|
6303
|
+
/* @__PURE__ */ jsx(
|
|
6304
|
+
FundStepIndicator,
|
|
6305
|
+
{
|
|
6306
|
+
number: 2,
|
|
6307
|
+
label: "Transfer",
|
|
6308
|
+
state: fundStep === "confirmed" ? "done" : fundPhase > 1 ? "active" : "pending"
|
|
6309
|
+
}
|
|
6310
|
+
)
|
|
6311
|
+
]
|
|
5811
6312
|
}
|
|
5812
6313
|
),
|
|
5813
|
-
/* @__PURE__ */ jsxs("div", {
|
|
6314
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
5814
6315
|
/* @__PURE__ */ jsx(
|
|
5815
|
-
"
|
|
6316
|
+
"label",
|
|
5816
6317
|
{
|
|
5817
|
-
|
|
5818
|
-
value: fundAmount,
|
|
5819
|
-
onChange: (e) => {
|
|
5820
|
-
setFundAmount(e.target.value);
|
|
5821
|
-
setFundTxState({ status: "idle" });
|
|
5822
|
-
},
|
|
5823
|
-
disabled: fundIsBusy,
|
|
5824
|
-
placeholder: "0.00",
|
|
5825
|
-
className: "w-full border px-3 py-2.5 pr-14 text-sm focus:outline-none disabled:opacity-50",
|
|
6318
|
+
className: "block text-sm mb-1.5",
|
|
5826
6319
|
style: {
|
|
5827
|
-
|
|
5828
|
-
borderColor: "var(--compass-color-border)",
|
|
5829
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
5830
|
-
color: "var(--compass-color-text)",
|
|
6320
|
+
color: "var(--compass-color-text-secondary)",
|
|
5831
6321
|
fontFamily: "var(--compass-font-family)"
|
|
5832
|
-
}
|
|
6322
|
+
},
|
|
6323
|
+
children: "Amount"
|
|
5833
6324
|
}
|
|
5834
6325
|
),
|
|
5835
|
-
/* @__PURE__ */
|
|
5836
|
-
|
|
6326
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
6327
|
+
/* @__PURE__ */ jsx(
|
|
6328
|
+
"input",
|
|
6329
|
+
{
|
|
6330
|
+
type: "number",
|
|
6331
|
+
value: fundAmount,
|
|
6332
|
+
onChange: (e) => {
|
|
6333
|
+
setFundAmount(e.target.value);
|
|
6334
|
+
setFundTxState({ status: "idle" });
|
|
6335
|
+
},
|
|
6336
|
+
disabled: fundIsBusy,
|
|
6337
|
+
placeholder: "0.00",
|
|
6338
|
+
className: "w-full border px-3 py-2.5 pr-14 text-sm focus:outline-none disabled:opacity-50",
|
|
6339
|
+
style: {
|
|
6340
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
6341
|
+
borderColor: "var(--compass-color-border)",
|
|
6342
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
6343
|
+
color: "var(--compass-color-text)",
|
|
6344
|
+
fontFamily: "var(--compass-font-family)"
|
|
6345
|
+
}
|
|
6346
|
+
}
|
|
6347
|
+
),
|
|
6348
|
+
/* @__PURE__ */ jsx(
|
|
6349
|
+
"span",
|
|
6350
|
+
{
|
|
6351
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-xs",
|
|
6352
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
6353
|
+
children: "USDC"
|
|
6354
|
+
}
|
|
6355
|
+
)
|
|
6356
|
+
] }),
|
|
6357
|
+
fundMaxBalance !== "0" && /* @__PURE__ */ jsxs(
|
|
6358
|
+
"p",
|
|
5837
6359
|
{
|
|
5838
|
-
className: "
|
|
6360
|
+
className: "text-xs mt-1",
|
|
5839
6361
|
style: { color: "var(--compass-color-text-tertiary)" },
|
|
5840
|
-
children:
|
|
6362
|
+
children: [
|
|
6363
|
+
"Available:",
|
|
6364
|
+
" ",
|
|
6365
|
+
/* @__PURE__ */ jsxs(
|
|
6366
|
+
"button",
|
|
6367
|
+
{
|
|
6368
|
+
onClick: () => setFundAmount(truncate2(parseFloat(fundMaxBalance), 2)),
|
|
6369
|
+
disabled: fundIsBusy,
|
|
6370
|
+
style: { color: "var(--compass-color-primary)", background: "none", border: "none", padding: 0, cursor: "pointer", fontSize: "inherit" },
|
|
6371
|
+
children: [
|
|
6372
|
+
truncate2(parseFloat(fundMaxBalance), 2),
|
|
6373
|
+
" USDC"
|
|
6374
|
+
]
|
|
6375
|
+
}
|
|
6376
|
+
)
|
|
6377
|
+
]
|
|
5841
6378
|
}
|
|
5842
6379
|
)
|
|
5843
6380
|
] }),
|
|
5844
|
-
|
|
6381
|
+
!fundIsBusy && fundStep !== "confirmed" && fundStep !== "failed" && fundTxState.status === "idle" && /* @__PURE__ */ jsx(
|
|
5845
6382
|
"p",
|
|
5846
6383
|
{
|
|
5847
|
-
className: "text-xs
|
|
5848
|
-
style: {
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
"button",
|
|
5854
|
-
{
|
|
5855
|
-
onClick: () => setFundAmount(truncate2(parseFloat(fundMaxBalance), 2)),
|
|
5856
|
-
disabled: fundIsBusy,
|
|
5857
|
-
style: { color: "var(--compass-color-primary)", background: "none", border: "none", padding: 0, cursor: "pointer", fontSize: "inherit" },
|
|
5858
|
-
children: [
|
|
5859
|
-
truncate2(parseFloat(fundMaxBalance), 2),
|
|
5860
|
-
" USDC"
|
|
5861
|
-
]
|
|
5862
|
-
}
|
|
5863
|
-
)
|
|
5864
|
-
]
|
|
6384
|
+
className: "text-xs",
|
|
6385
|
+
style: {
|
|
6386
|
+
color: "var(--compass-color-text-tertiary)",
|
|
6387
|
+
fontFamily: "var(--compass-font-family)"
|
|
6388
|
+
},
|
|
6389
|
+
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." : ""}`
|
|
5865
6390
|
}
|
|
5866
|
-
)
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
},
|
|
5893
|
-
children: fundIsBusy ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5894
|
-
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
5895
|
-
fundButtonLabel()
|
|
5896
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5897
|
-
/* @__PURE__ */ jsx(ArrowRight, { className: "h-4 w-4" }),
|
|
5898
|
-
fundAction === "deposit" ? "Transfer to Savings Account" : "Withdraw to Wallet"
|
|
5899
|
-
] })
|
|
5900
|
-
}
|
|
5901
|
-
),
|
|
5902
|
-
/* @__PURE__ */ jsx(TxStatus, { state: fundTxState })
|
|
6391
|
+
),
|
|
6392
|
+
/* @__PURE__ */ jsx(
|
|
6393
|
+
"button",
|
|
6394
|
+
{
|
|
6395
|
+
onClick: handleFundTransfer,
|
|
6396
|
+
disabled: !fundIsValid || fundIsBusy,
|
|
6397
|
+
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",
|
|
6398
|
+
style: {
|
|
6399
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
6400
|
+
color: "var(--compass-color-primary-text)",
|
|
6401
|
+
borderRadius: "var(--compass-border-radius-xl)",
|
|
6402
|
+
fontFamily: "var(--compass-font-family)",
|
|
6403
|
+
transition: "all 200ms ease",
|
|
6404
|
+
border: "none"
|
|
6405
|
+
},
|
|
6406
|
+
children: fundIsBusy ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6407
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
6408
|
+
fundButtonLabel()
|
|
6409
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6410
|
+
/* @__PURE__ */ jsx(ArrowRight, { className: "h-4 w-4" }),
|
|
6411
|
+
fundAction === "deposit" ? "Transfer to Savings Account" : "Withdraw to Wallet"
|
|
6412
|
+
] })
|
|
6413
|
+
}
|
|
6414
|
+
),
|
|
6415
|
+
/* @__PURE__ */ jsx(TxStatus, { state: fundTxState })
|
|
6416
|
+
] })
|
|
5903
6417
|
] })
|
|
5904
6418
|
}
|
|
5905
6419
|
),
|
|
@@ -7706,19 +8220,24 @@ function getPhase(step) {
|
|
|
7706
8220
|
if (step === "approving" || step === "signing-approval") return 1;
|
|
7707
8221
|
return 2;
|
|
7708
8222
|
}
|
|
7709
|
-
var
|
|
8223
|
+
var EVM_CHAIN_IDS3 = {
|
|
7710
8224
|
ethereum: 1,
|
|
7711
8225
|
base: 8453,
|
|
7712
8226
|
arbitrum: 42161
|
|
7713
8227
|
};
|
|
7714
8228
|
function TopUpModal({ isOpen, onClose }) {
|
|
7715
|
-
const { address, signTypedData, switchChain, walletChainId } = useEmbeddableWallet();
|
|
8229
|
+
const { address, signTypedData, switchChain, walletChainId, fundWallet, hasExternalWallet, sendTransaction } = useEmbeddableWallet();
|
|
7716
8230
|
const { chainId } = useChain();
|
|
7717
|
-
const { isDeployed } = useCreditAccount();
|
|
8231
|
+
const { isDeployed, creditAccountAddress } = useCreditAccount();
|
|
7718
8232
|
const queryClient = useQueryClient();
|
|
7719
8233
|
const prices = useTokenPrices();
|
|
7720
8234
|
const token = "USDC";
|
|
7721
|
-
const [action, setAction] = useState(
|
|
8235
|
+
const [action, setAction] = useState(
|
|
8236
|
+
!hasExternalWallet && fundWallet ? "buy" : "deposit"
|
|
8237
|
+
);
|
|
8238
|
+
const showBuyTab = !!fundWallet;
|
|
8239
|
+
const showSendTab = !!sendTransaction && !hasExternalWallet;
|
|
8240
|
+
const buyOnly = !hasExternalWallet && showBuyTab && !sendTransaction;
|
|
7722
8241
|
const [amount, setAmount] = useState("");
|
|
7723
8242
|
const [step, setStep] = useState("idle");
|
|
7724
8243
|
const [txState, setTxState] = useState({ status: "idle" });
|
|
@@ -7767,7 +8286,7 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
7767
8286
|
const isValid = Number(amount) > 0 && !!address && isDeployed;
|
|
7768
8287
|
const isBusy = step === "approving" || step === "signing-approval" || step === "preparing-transfer" || step === "signing-transfer" || step === "executing";
|
|
7769
8288
|
const ensureCorrectChain = useCallback(async () => {
|
|
7770
|
-
const targetChainId =
|
|
8289
|
+
const targetChainId = EVM_CHAIN_IDS3[CHAIN_ID];
|
|
7771
8290
|
if (!targetChainId) return;
|
|
7772
8291
|
if (walletChainId !== void 0 && walletChainId !== targetChainId) {
|
|
7773
8292
|
if (!switchChain) {
|
|
@@ -7969,7 +8488,10 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
7969
8488
|
setTxState({ status: "failed", error: "Transaction reverted" });
|
|
7970
8489
|
return;
|
|
7971
8490
|
}
|
|
7972
|
-
} catch {
|
|
8491
|
+
} catch (err) {
|
|
8492
|
+
if (err instanceof TypeError && err.message.includes("fetch")) ; else {
|
|
8493
|
+
console.warn("[TopUpModal] Unexpected error polling tx receipt:", err);
|
|
8494
|
+
}
|
|
7973
8495
|
}
|
|
7974
8496
|
if (polls >= 24) {
|
|
7975
8497
|
clearPolling();
|
|
@@ -8005,8 +8527,8 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
8005
8527
|
color: "var(--compass-color-text-secondary)",
|
|
8006
8528
|
fontFamily: "var(--compass-font-family)"
|
|
8007
8529
|
};
|
|
8008
|
-
return /* @__PURE__ */ jsx(ActionModal, { isOpen, onClose, title: "Transfer Funds", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
8009
|
-
/* @__PURE__ */ jsx(
|
|
8530
|
+
return /* @__PURE__ */ jsx(ActionModal, { isOpen, onClose, title: showSendTab ? "Manage Funds" : buyOnly ? "Add Funds" : "Transfer Funds", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
8531
|
+
!buyOnly && /* @__PURE__ */ jsx(
|
|
8010
8532
|
"div",
|
|
8011
8533
|
{
|
|
8012
8534
|
className: "flex gap-1 p-1",
|
|
@@ -8015,7 +8537,9 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
8015
8537
|
borderRadius: "var(--compass-border-radius-lg)",
|
|
8016
8538
|
fontFamily: "var(--compass-font-family)"
|
|
8017
8539
|
},
|
|
8018
|
-
children: [
|
|
8540
|
+
children: [
|
|
8541
|
+
...showSendTab ? ["buy", "send"] : showBuyTab ? ["deposit", "withdraw", "buy"] : ["deposit", "withdraw"]
|
|
8542
|
+
].map((tab) => /* @__PURE__ */ jsxs(
|
|
8019
8543
|
"button",
|
|
8020
8544
|
{
|
|
8021
8545
|
onClick: () => handleActionChange(tab),
|
|
@@ -8027,7 +8551,7 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
8027
8551
|
borderRadius: "var(--compass-border-radius-md)"
|
|
8028
8552
|
},
|
|
8029
8553
|
children: [
|
|
8030
|
-
tab === "deposit" ? /* @__PURE__ */ jsx(ArrowDownLeft, { size: 14 }) : /* @__PURE__ */ jsx(ArrowUpRight, { size: 14 }),
|
|
8554
|
+
tab === "deposit" ? /* @__PURE__ */ jsx(ArrowDownLeft, { size: 14 }) : tab === "withdraw" ? /* @__PURE__ */ jsx(ArrowUpRight, { size: 14 }) : tab === "send" ? /* @__PURE__ */ jsx(Send, { size: 14 }) : /* @__PURE__ */ jsx(ArrowRight, { size: 14 }),
|
|
8031
8555
|
tab
|
|
8032
8556
|
]
|
|
8033
8557
|
},
|
|
@@ -8035,122 +8559,143 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
8035
8559
|
))
|
|
8036
8560
|
}
|
|
8037
8561
|
),
|
|
8038
|
-
|
|
8039
|
-
|
|
8562
|
+
action === "send" ? /* @__PURE__ */ jsx(
|
|
8563
|
+
SendForm,
|
|
8040
8564
|
{
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
}
|
|
8047
|
-
|
|
8565
|
+
product: "credit",
|
|
8566
|
+
productAccountAddress: creditAccountAddress || void 0,
|
|
8567
|
+
onComplete: () => {
|
|
8568
|
+
queryClient.invalidateQueries({ queryKey: ["creditBalances"] });
|
|
8569
|
+
queryClient.invalidateQueries({ queryKey: ["walletTokenBalance"] });
|
|
8570
|
+
}
|
|
8571
|
+
}
|
|
8572
|
+
) : action === "buy" || buyOnly ? /* @__PURE__ */ jsx(
|
|
8573
|
+
BuyForm,
|
|
8574
|
+
{
|
|
8575
|
+
targetAddress: creditAccountAddress || "",
|
|
8576
|
+
onComplete: () => {
|
|
8577
|
+
queryClient.invalidateQueries({ queryKey: ["creditBalances"] });
|
|
8578
|
+
queryClient.invalidateQueries({ queryKey: ["walletTokenBalance"] });
|
|
8579
|
+
}
|
|
8580
|
+
}
|
|
8581
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8582
|
+
(isBusy || step === "confirmed") && action === "deposit" && /* @__PURE__ */ jsxs(
|
|
8583
|
+
"div",
|
|
8584
|
+
{
|
|
8585
|
+
className: "flex gap-3 p-3 text-xs",
|
|
8586
|
+
style: {
|
|
8587
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
8588
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
8589
|
+
fontFamily: "var(--compass-font-family)"
|
|
8590
|
+
},
|
|
8591
|
+
children: [
|
|
8592
|
+
/* @__PURE__ */ jsx(
|
|
8593
|
+
StepIndicator,
|
|
8594
|
+
{
|
|
8595
|
+
number: 1,
|
|
8596
|
+
label: "Approve",
|
|
8597
|
+
state: phase > 1 ? "done" : phase === 1 ? "active" : "pending"
|
|
8598
|
+
}
|
|
8599
|
+
),
|
|
8600
|
+
/* @__PURE__ */ jsx(
|
|
8601
|
+
StepIndicator,
|
|
8602
|
+
{
|
|
8603
|
+
number: 2,
|
|
8604
|
+
label: "Transfer",
|
|
8605
|
+
state: step === "confirmed" ? "done" : phase > 1 ? "active" : "pending"
|
|
8606
|
+
}
|
|
8607
|
+
)
|
|
8608
|
+
]
|
|
8609
|
+
}
|
|
8610
|
+
),
|
|
8611
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
8612
|
+
/* @__PURE__ */ jsx("label", { className: "block text-sm mb-1.5", style: labelStyle, children: "Amount" }),
|
|
8613
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
8048
8614
|
/* @__PURE__ */ jsx(
|
|
8049
|
-
|
|
8615
|
+
"input",
|
|
8050
8616
|
{
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
|
|
8617
|
+
type: "number",
|
|
8618
|
+
value: amount,
|
|
8619
|
+
onChange: (e) => {
|
|
8620
|
+
setAmount(e.target.value);
|
|
8621
|
+
setTxState({ status: "idle" });
|
|
8622
|
+
},
|
|
8623
|
+
disabled: isBusy,
|
|
8624
|
+
placeholder: "0.00",
|
|
8625
|
+
className: "w-full border px-3 py-2.5 pr-14 text-sm focus:outline-none disabled:opacity-50",
|
|
8626
|
+
style: inputStyle
|
|
8054
8627
|
}
|
|
8055
8628
|
),
|
|
8056
8629
|
/* @__PURE__ */ jsx(
|
|
8057
|
-
|
|
8630
|
+
"span",
|
|
8058
8631
|
{
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
|
|
8632
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-xs",
|
|
8633
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
8634
|
+
children: token
|
|
8062
8635
|
}
|
|
8063
8636
|
)
|
|
8064
|
-
]
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
8068
|
-
/* @__PURE__ */ jsx("label", { className: "block text-sm mb-1.5", style: labelStyle, children: "Amount" }),
|
|
8069
|
-
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
8070
|
-
/* @__PURE__ */ jsx(
|
|
8071
|
-
"input",
|
|
8637
|
+
] }),
|
|
8638
|
+
formatUsdEstimate(amount, token, prices) && /* @__PURE__ */ jsxs(
|
|
8639
|
+
"p",
|
|
8072
8640
|
{
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
|
|
8078
|
-
|
|
8079
|
-
|
|
8080
|
-
placeholder: "0.00",
|
|
8081
|
-
className: "w-full border px-3 py-2.5 pr-14 text-sm focus:outline-none disabled:opacity-50",
|
|
8082
|
-
style: inputStyle
|
|
8641
|
+
className: "text-xs mt-1",
|
|
8642
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
8643
|
+
children: [
|
|
8644
|
+
"\u2248",
|
|
8645
|
+
" ",
|
|
8646
|
+
formatUsdEstimate(amount, token, prices)
|
|
8647
|
+
]
|
|
8083
8648
|
}
|
|
8084
8649
|
),
|
|
8085
|
-
/* @__PURE__ */
|
|
8086
|
-
"
|
|
8650
|
+
maxBalance && maxBalance !== "0" && /* @__PURE__ */ jsxs(
|
|
8651
|
+
"p",
|
|
8087
8652
|
{
|
|
8088
|
-
className: "
|
|
8653
|
+
className: "text-xs mt-1",
|
|
8089
8654
|
style: { color: "var(--compass-color-text-tertiary)" },
|
|
8090
|
-
children:
|
|
8655
|
+
children: [
|
|
8656
|
+
"Available: ",
|
|
8657
|
+
truncate6(parseFloat(maxBalance), 2),
|
|
8658
|
+
" ",
|
|
8659
|
+
token
|
|
8660
|
+
]
|
|
8091
8661
|
}
|
|
8092
8662
|
)
|
|
8093
8663
|
] }),
|
|
8094
|
-
|
|
8664
|
+
!isBusy && step !== "confirmed" && step !== "failed" && txState.status === "idle" && /* @__PURE__ */ jsx(
|
|
8095
8665
|
"p",
|
|
8096
8666
|
{
|
|
8097
|
-
className: "text-xs
|
|
8098
|
-
style: {
|
|
8099
|
-
|
|
8100
|
-
"
|
|
8101
|
-
|
|
8102
|
-
|
|
8103
|
-
]
|
|
8667
|
+
className: "text-xs",
|
|
8668
|
+
style: {
|
|
8669
|
+
color: "var(--compass-color-text-tertiary)",
|
|
8670
|
+
fontFamily: "var(--compass-font-family)"
|
|
8671
|
+
},
|
|
8672
|
+
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." : ""}`
|
|
8104
8673
|
}
|
|
8105
8674
|
),
|
|
8106
|
-
|
|
8107
|
-
"
|
|
8675
|
+
/* @__PURE__ */ jsx(
|
|
8676
|
+
"button",
|
|
8108
8677
|
{
|
|
8109
|
-
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8678
|
+
onClick: handleTransfer,
|
|
8679
|
+
disabled: !isValid || isBusy,
|
|
8680
|
+
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",
|
|
8681
|
+
style: {
|
|
8682
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
8683
|
+
color: "white",
|
|
8684
|
+
borderRadius: "var(--compass-border-radius-xl)",
|
|
8685
|
+
fontFamily: "var(--compass-font-family)",
|
|
8686
|
+
transition: "var(--compass-transition-normal)"
|
|
8687
|
+
},
|
|
8688
|
+
children: isBusy ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8689
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
8690
|
+
buttonLabel()
|
|
8691
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8692
|
+
/* @__PURE__ */ jsx(ArrowRight, { className: "h-4 w-4" }),
|
|
8693
|
+
action === "deposit" ? "Transfer to Credit Account" : "Withdraw to Wallet"
|
|
8694
|
+
] })
|
|
8117
8695
|
}
|
|
8118
|
-
)
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
"p",
|
|
8122
|
-
{
|
|
8123
|
-
className: "text-xs",
|
|
8124
|
-
style: {
|
|
8125
|
-
color: "var(--compass-color-text-tertiary)",
|
|
8126
|
-
fontFamily: "var(--compass-font-family)"
|
|
8127
|
-
},
|
|
8128
|
-
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."
|
|
8129
|
-
}
|
|
8130
|
-
),
|
|
8131
|
-
/* @__PURE__ */ jsx(
|
|
8132
|
-
"button",
|
|
8133
|
-
{
|
|
8134
|
-
onClick: handleTransfer,
|
|
8135
|
-
disabled: !isValid || isBusy,
|
|
8136
|
-
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",
|
|
8137
|
-
style: {
|
|
8138
|
-
backgroundColor: "var(--compass-color-primary)",
|
|
8139
|
-
color: "white",
|
|
8140
|
-
borderRadius: "var(--compass-border-radius-xl)",
|
|
8141
|
-
fontFamily: "var(--compass-font-family)",
|
|
8142
|
-
transition: "var(--compass-transition-normal)"
|
|
8143
|
-
},
|
|
8144
|
-
children: isBusy ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8145
|
-
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
8146
|
-
buttonLabel()
|
|
8147
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8148
|
-
/* @__PURE__ */ jsx(ArrowRight, { className: "h-4 w-4" }),
|
|
8149
|
-
action === "deposit" ? "Transfer to Credit Account" : "Withdraw to Wallet"
|
|
8150
|
-
] })
|
|
8151
|
-
}
|
|
8152
|
-
),
|
|
8153
|
-
/* @__PURE__ */ jsx(TxStatus, { state: txState })
|
|
8696
|
+
),
|
|
8697
|
+
/* @__PURE__ */ jsx(TxStatus, { state: txState })
|
|
8698
|
+
] })
|
|
8154
8699
|
] }) });
|
|
8155
8700
|
}
|
|
8156
8701
|
function StepIndicator({
|
|
@@ -8178,9 +8723,10 @@ function CreditSwapModal({ isOpen, onClose }) {
|
|
|
8178
8723
|
const prices = useTokenPrices();
|
|
8179
8724
|
const { txState, executeBundle, resetState } = useCreditBundle();
|
|
8180
8725
|
const tokens = CREDIT_TOKENS;
|
|
8181
|
-
const fromToken = "USDC";
|
|
8182
|
-
const [toToken, setToToken] = useState(tokens.find((t) => t !==
|
|
8726
|
+
const [fromToken, setFromToken] = useState("USDC");
|
|
8727
|
+
const [toToken, setToToken] = useState(tokens.find((t) => t !== "USDC") || tokens[0] || "WETH");
|
|
8183
8728
|
const [fromAmount, setFromAmount] = useState("");
|
|
8729
|
+
const [isFromOpen, setIsFromOpen] = useState(false);
|
|
8184
8730
|
const [isToOpen, setIsToOpen] = useState(false);
|
|
8185
8731
|
useEffect(() => {
|
|
8186
8732
|
if (isOpen) {
|
|
@@ -8188,6 +8734,12 @@ function CreditSwapModal({ isOpen, onClose }) {
|
|
|
8188
8734
|
resetState();
|
|
8189
8735
|
}
|
|
8190
8736
|
}, [isOpen]);
|
|
8737
|
+
useEffect(() => {
|
|
8738
|
+
if (fromToken === toToken) {
|
|
8739
|
+
const alt = tokens.find((t) => t !== fromToken);
|
|
8740
|
+
if (alt) setToToken(alt);
|
|
8741
|
+
}
|
|
8742
|
+
}, [fromToken, toToken, tokens]);
|
|
8191
8743
|
const fromBalance = balances?.find((b) => b.tokenSymbol === fromToken);
|
|
8192
8744
|
const fromBalanceAmount = fromBalance ? parseFloat(fromBalance.amount) : 0;
|
|
8193
8745
|
const estimatedOutput = (() => {
|
|
@@ -8266,24 +8818,76 @@ function CreditSwapModal({ isOpen, onClose }) {
|
|
|
8266
8818
|
}
|
|
8267
8819
|
}
|
|
8268
8820
|
),
|
|
8269
|
-
/* @__PURE__ */
|
|
8270
|
-
|
|
8271
|
-
|
|
8272
|
-
|
|
8273
|
-
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8821
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative", flexShrink: 0 }, children: [
|
|
8822
|
+
/* @__PURE__ */ jsxs(
|
|
8823
|
+
"button",
|
|
8824
|
+
{
|
|
8825
|
+
onClick: () => setIsFromOpen(!isFromOpen),
|
|
8826
|
+
disabled: isBusy,
|
|
8827
|
+
style: {
|
|
8828
|
+
display: "flex",
|
|
8829
|
+
alignItems: "center",
|
|
8830
|
+
fontWeight: 500,
|
|
8831
|
+
backgroundColor: "var(--compass-color-background)",
|
|
8832
|
+
border: "1.5px solid var(--compass-color-border)",
|
|
8833
|
+
color: "var(--compass-color-text)",
|
|
8834
|
+
borderRadius: "var(--compass-border-radius-md)",
|
|
8835
|
+
padding: "4px 8px",
|
|
8836
|
+
gap: "4px",
|
|
8837
|
+
fontSize: "0.8125rem",
|
|
8838
|
+
cursor: isBusy ? "not-allowed" : "pointer"
|
|
8839
|
+
},
|
|
8840
|
+
children: [
|
|
8841
|
+
fromToken,
|
|
8842
|
+
/* @__PURE__ */ jsx(ChevronDown, { size: 12, style: { color: "var(--compass-color-text-tertiary)" } })
|
|
8843
|
+
]
|
|
8844
|
+
}
|
|
8845
|
+
),
|
|
8846
|
+
isFromOpen && /* @__PURE__ */ jsx(
|
|
8847
|
+
"div",
|
|
8848
|
+
{
|
|
8849
|
+
style: {
|
|
8850
|
+
position: "absolute",
|
|
8851
|
+
right: 0,
|
|
8852
|
+
top: "100%",
|
|
8853
|
+
marginTop: "4px",
|
|
8854
|
+
zIndex: 10,
|
|
8855
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
8856
|
+
border: "1.5px solid var(--compass-color-border)",
|
|
8857
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
8858
|
+
boxShadow: "var(--compass-shadow-md)",
|
|
8859
|
+
minWidth: "120px",
|
|
8860
|
+
maxHeight: "200px",
|
|
8861
|
+
overflowY: "auto",
|
|
8862
|
+
scrollbarWidth: "none"
|
|
8863
|
+
},
|
|
8864
|
+
children: tokens.filter((t) => t !== toToken).map((token) => /* @__PURE__ */ jsx(
|
|
8865
|
+
"button",
|
|
8866
|
+
{
|
|
8867
|
+
onClick: () => {
|
|
8868
|
+
setFromToken(token);
|
|
8869
|
+
setFromAmount("");
|
|
8870
|
+
setIsFromOpen(false);
|
|
8871
|
+
},
|
|
8872
|
+
style: {
|
|
8873
|
+
display: "block",
|
|
8874
|
+
width: "100%",
|
|
8875
|
+
textAlign: "left",
|
|
8876
|
+
padding: "6px 10px",
|
|
8877
|
+
fontSize: "0.8125rem",
|
|
8878
|
+
fontWeight: 500,
|
|
8879
|
+
color: token === fromToken ? "var(--compass-color-primary)" : "var(--compass-color-text)",
|
|
8880
|
+
backgroundColor: token === fromToken ? "var(--compass-color-primary-muted)" : "transparent",
|
|
8881
|
+
border: "none",
|
|
8882
|
+
cursor: "pointer"
|
|
8883
|
+
},
|
|
8884
|
+
children: token
|
|
8885
|
+
},
|
|
8886
|
+
token
|
|
8887
|
+
))
|
|
8888
|
+
}
|
|
8889
|
+
)
|
|
8890
|
+
] })
|
|
8287
8891
|
] })
|
|
8288
8892
|
]
|
|
8289
8893
|
}
|
|
@@ -8490,7 +9094,7 @@ function CreditAccount({
|
|
|
8490
9094
|
onBorrow: _onBorrow,
|
|
8491
9095
|
onRepay: _onRepay
|
|
8492
9096
|
}) {
|
|
8493
|
-
const { address, isConnected, login, logout } = useEmbeddableWallet();
|
|
9097
|
+
const { address, isConnected, login, logout, hasExternalWallet } = useEmbeddableWallet();
|
|
8494
9098
|
const { isDeployed, creditAccountAddress } = useCreditAccount();
|
|
8495
9099
|
const { chainId } = useChain();
|
|
8496
9100
|
const { data: positions, isLoading: positionsLoading } = useCreditPositions();
|
|
@@ -8516,6 +9120,25 @@ function CreditAccount({
|
|
|
8516
9120
|
return { ...b, usdValue };
|
|
8517
9121
|
}).filter((b) => b.usdValue >= 0.01).sort((a, b) => a.tokenSymbol.localeCompare(b.tokenSymbol));
|
|
8518
9122
|
const totalIdleUsd = balancesWithUsd.reduce((sum, b) => sum + b.usdValue, 0);
|
|
9123
|
+
const { data: walletBalance } = useQuery({
|
|
9124
|
+
queryKey: ["embeddedWalletBalance", chainId, address, "USDC"],
|
|
9125
|
+
queryFn: async () => {
|
|
9126
|
+
if (!address) return "0";
|
|
9127
|
+
try {
|
|
9128
|
+
const response = await fetch(
|
|
9129
|
+
`/api/compass/token/balance?chain=${chainId}&token=USDC&address=${address}`
|
|
9130
|
+
);
|
|
9131
|
+
if (response.ok) {
|
|
9132
|
+
const data = await response.json();
|
|
9133
|
+
return data.balance || "0";
|
|
9134
|
+
}
|
|
9135
|
+
} catch {
|
|
9136
|
+
}
|
|
9137
|
+
return "0";
|
|
9138
|
+
},
|
|
9139
|
+
enabled: !!address && hasExternalWallet,
|
|
9140
|
+
staleTime: 30 * 1e3
|
|
9141
|
+
});
|
|
8519
9142
|
const totalInterestEarnedUsd = (() => {
|
|
8520
9143
|
if (!positions) return 0;
|
|
8521
9144
|
let total = 0;
|
|
@@ -9516,6 +10139,7 @@ function PositionDetailModal({ position, onClose }) {
|
|
|
9516
10139
|
const isPendle = position.venue === "pendle";
|
|
9517
10140
|
const duration = formatDuration(position.entryTimestamp);
|
|
9518
10141
|
const expiryDate = formatExpiryUTC(position.expiry);
|
|
10142
|
+
const modalRef = useRef(null);
|
|
9519
10143
|
useEffect(() => {
|
|
9520
10144
|
const handleKeyDown = (e) => {
|
|
9521
10145
|
if (e.key === "Escape") onClose();
|
|
@@ -9523,296 +10147,312 @@ function PositionDetailModal({ position, onClose }) {
|
|
|
9523
10147
|
document.addEventListener("keydown", handleKeyDown);
|
|
9524
10148
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
9525
10149
|
}, [onClose]);
|
|
10150
|
+
const handleOverlayWheel = useCallback((e) => {
|
|
10151
|
+
if (modalRef.current && !modalRef.current.contains(e.target)) {
|
|
10152
|
+
window.scrollBy(0, e.deltaY);
|
|
10153
|
+
}
|
|
10154
|
+
}, []);
|
|
9526
10155
|
const hasStats = position.apy || isPendle && (duration || expiryDate) || position.pnl;
|
|
9527
|
-
return /* @__PURE__ */
|
|
10156
|
+
return /* @__PURE__ */ jsxs(
|
|
9528
10157
|
"div",
|
|
9529
10158
|
{
|
|
9530
10159
|
className: "fixed inset-0 z-50 flex items-center justify-center p-4",
|
|
9531
|
-
|
|
10160
|
+
onWheel: handleOverlayWheel,
|
|
9532
10161
|
onClick: onClose,
|
|
9533
|
-
children:
|
|
9534
|
-
|
|
9535
|
-
|
|
9536
|
-
|
|
9537
|
-
|
|
9538
|
-
backgroundColor: "
|
|
9539
|
-
|
|
9540
|
-
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
/* @__PURE__ */ jsx(
|
|
9555
|
-
"h2",
|
|
9556
|
-
{
|
|
9557
|
-
className: "font-semibold text-lg",
|
|
9558
|
-
style: { color: "var(--compass-color-text)" },
|
|
9559
|
-
children: position.name
|
|
9560
|
-
}
|
|
9561
|
-
),
|
|
9562
|
-
/* @__PURE__ */ jsx(
|
|
9563
|
-
"p",
|
|
9564
|
-
{
|
|
9565
|
-
className: "text-sm",
|
|
9566
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
9567
|
-
children: position.venueName
|
|
9568
|
-
}
|
|
9569
|
-
)
|
|
9570
|
-
] }),
|
|
9571
|
-
/* @__PURE__ */ jsx(
|
|
9572
|
-
"button",
|
|
9573
|
-
{
|
|
9574
|
-
onClick: onClose,
|
|
9575
|
-
className: "p-2 rounded-lg hover:opacity-80 transition-opacity",
|
|
9576
|
-
style: { backgroundColor: "var(--compass-color-background)" },
|
|
9577
|
-
children: /* @__PURE__ */ jsx(X, { size: 20, style: { color: "var(--compass-color-text-secondary)" } })
|
|
9578
|
-
}
|
|
9579
|
-
)
|
|
9580
|
-
]
|
|
9581
|
-
}
|
|
9582
|
-
),
|
|
9583
|
-
/* @__PURE__ */ jsx("div", { className: "p-4 border-b", style: { borderColor: "var(--compass-color-border)" }, children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
9584
|
-
/* @__PURE__ */ jsx(
|
|
9585
|
-
"p",
|
|
9586
|
-
{
|
|
9587
|
-
className: "text-sm mb-1",
|
|
9588
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
9589
|
-
children: "Current Balance"
|
|
9590
|
-
}
|
|
9591
|
-
),
|
|
9592
|
-
/* @__PURE__ */ jsx(
|
|
9593
|
-
"p",
|
|
9594
|
-
{
|
|
9595
|
-
className: "text-3xl font-bold",
|
|
9596
|
-
style: { color: "var(--compass-color-text)" },
|
|
9597
|
-
children: formatUSD(position.balanceUsd)
|
|
9598
|
-
}
|
|
9599
|
-
),
|
|
10162
|
+
children: [
|
|
10163
|
+
/* @__PURE__ */ jsx(
|
|
10164
|
+
"div",
|
|
10165
|
+
{
|
|
10166
|
+
className: "absolute inset-0",
|
|
10167
|
+
style: { backgroundColor: "rgba(0, 0, 0, 0.7)" }
|
|
10168
|
+
}
|
|
10169
|
+
),
|
|
10170
|
+
/* @__PURE__ */ jsxs(
|
|
10171
|
+
"div",
|
|
10172
|
+
{
|
|
10173
|
+
ref: modalRef,
|
|
10174
|
+
className: "relative w-full max-w-md rounded-xl border max-h-[85vh] overflow-y-auto",
|
|
10175
|
+
style: {
|
|
10176
|
+
backgroundColor: "var(--compass-color-background)",
|
|
10177
|
+
borderColor: "var(--compass-color-border)",
|
|
10178
|
+
scrollbarWidth: "none",
|
|
10179
|
+
overscrollBehavior: "contain"
|
|
10180
|
+
},
|
|
10181
|
+
onClick: (e) => e.stopPropagation(),
|
|
10182
|
+
children: [
|
|
9600
10183
|
/* @__PURE__ */ jsxs(
|
|
9601
|
-
"p",
|
|
9602
|
-
{
|
|
9603
|
-
className: "text-sm font-mono mt-1",
|
|
9604
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
9605
|
-
children: [
|
|
9606
|
-
formatAmount(position.balance),
|
|
9607
|
-
" ",
|
|
9608
|
-
position.assetSymbol
|
|
9609
|
-
]
|
|
9610
|
-
}
|
|
9611
|
-
)
|
|
9612
|
-
] }) }),
|
|
9613
|
-
hasStats && /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3 p-4 border-b", style: { borderColor: "var(--compass-color-border)" }, children: [
|
|
9614
|
-
position.apy && /* @__PURE__ */ jsxs(
|
|
9615
|
-
"div",
|
|
9616
|
-
{
|
|
9617
|
-
className: "p-3 rounded-lg",
|
|
9618
|
-
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
9619
|
-
children: [
|
|
9620
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
9621
|
-
/* @__PURE__ */ jsx(Percent, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
9622
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "APY" })
|
|
9623
|
-
] }),
|
|
9624
|
-
/* @__PURE__ */ jsxs(
|
|
9625
|
-
"p",
|
|
9626
|
-
{
|
|
9627
|
-
className: "font-semibold",
|
|
9628
|
-
style: { color: "var(--compass-color-success)" },
|
|
9629
|
-
children: [
|
|
9630
|
-
parseFloat(position.apy).toFixed(2),
|
|
9631
|
-
"%"
|
|
9632
|
-
]
|
|
9633
|
-
}
|
|
9634
|
-
)
|
|
9635
|
-
]
|
|
9636
|
-
}
|
|
9637
|
-
),
|
|
9638
|
-
isPendle && duration && /* @__PURE__ */ jsxs(
|
|
9639
|
-
"div",
|
|
9640
|
-
{
|
|
9641
|
-
className: "p-3 rounded-lg",
|
|
9642
|
-
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
9643
|
-
children: [
|
|
9644
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
9645
|
-
/* @__PURE__ */ jsx(Clock, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
9646
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "Duration" })
|
|
9647
|
-
] }),
|
|
9648
|
-
/* @__PURE__ */ jsx(
|
|
9649
|
-
"p",
|
|
9650
|
-
{
|
|
9651
|
-
className: "font-semibold",
|
|
9652
|
-
style: { color: "var(--compass-color-text)" },
|
|
9653
|
-
children: duration
|
|
9654
|
-
}
|
|
9655
|
-
)
|
|
9656
|
-
]
|
|
9657
|
-
}
|
|
9658
|
-
),
|
|
9659
|
-
isPendle && expiryDate && /* @__PURE__ */ jsxs(
|
|
9660
10184
|
"div",
|
|
9661
10185
|
{
|
|
9662
|
-
className: "p-
|
|
9663
|
-
style: {
|
|
10186
|
+
className: "sticky top-0 flex items-center justify-between p-4 border-b",
|
|
10187
|
+
style: {
|
|
10188
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
10189
|
+
borderColor: "var(--compass-color-border)"
|
|
10190
|
+
},
|
|
9664
10191
|
children: [
|
|
9665
|
-
/* @__PURE__ */ jsxs("div", {
|
|
9666
|
-
/* @__PURE__ */ jsx(
|
|
9667
|
-
|
|
10192
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
10193
|
+
/* @__PURE__ */ jsx(
|
|
10194
|
+
"h2",
|
|
10195
|
+
{
|
|
10196
|
+
className: "font-semibold text-lg",
|
|
10197
|
+
style: { color: "var(--compass-color-text)" },
|
|
10198
|
+
children: position.name
|
|
10199
|
+
}
|
|
10200
|
+
),
|
|
10201
|
+
/* @__PURE__ */ jsx(
|
|
10202
|
+
"p",
|
|
10203
|
+
{
|
|
10204
|
+
className: "text-sm",
|
|
10205
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
10206
|
+
children: position.venueName
|
|
10207
|
+
}
|
|
10208
|
+
)
|
|
9668
10209
|
] }),
|
|
9669
10210
|
/* @__PURE__ */ jsx(
|
|
9670
|
-
"
|
|
10211
|
+
"button",
|
|
9671
10212
|
{
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
10213
|
+
onClick: onClose,
|
|
10214
|
+
className: "p-2 rounded-lg hover:opacity-80 transition-opacity",
|
|
10215
|
+
style: { backgroundColor: "var(--compass-color-background)" },
|
|
10216
|
+
children: /* @__PURE__ */ jsx(X, { size: 20, style: { color: "var(--compass-color-text-secondary)" } })
|
|
9675
10217
|
}
|
|
9676
10218
|
)
|
|
9677
10219
|
]
|
|
9678
10220
|
}
|
|
9679
10221
|
),
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
|
|
10222
|
+
/* @__PURE__ */ jsx("div", { className: "p-4 border-b", style: { borderColor: "var(--compass-color-border)" }, children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
10223
|
+
/* @__PURE__ */ jsx(
|
|
10224
|
+
"p",
|
|
10225
|
+
{
|
|
10226
|
+
className: "text-sm mb-1",
|
|
10227
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
10228
|
+
children: "Current Balance"
|
|
10229
|
+
}
|
|
10230
|
+
),
|
|
10231
|
+
/* @__PURE__ */ jsx(
|
|
10232
|
+
"p",
|
|
10233
|
+
{
|
|
10234
|
+
className: "text-3xl font-bold",
|
|
10235
|
+
style: { color: "var(--compass-color-text)" },
|
|
10236
|
+
children: formatUSD(position.balanceUsd)
|
|
10237
|
+
}
|
|
10238
|
+
),
|
|
10239
|
+
/* @__PURE__ */ jsxs(
|
|
10240
|
+
"p",
|
|
10241
|
+
{
|
|
10242
|
+
className: "text-sm font-mono mt-1",
|
|
10243
|
+
style: { color: "var(--compass-color-text-secondary)" },
|
|
10244
|
+
children: [
|
|
10245
|
+
formatAmount(position.balance),
|
|
10246
|
+
" ",
|
|
10247
|
+
position.assetSymbol
|
|
10248
|
+
]
|
|
10249
|
+
}
|
|
10250
|
+
)
|
|
10251
|
+
] }) }),
|
|
10252
|
+
hasStats && /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3 p-4 border-b", style: { borderColor: "var(--compass-color-border)" }, children: [
|
|
10253
|
+
position.apy && /* @__PURE__ */ jsxs(
|
|
10254
|
+
"div",
|
|
10255
|
+
{
|
|
10256
|
+
className: "p-3 rounded-lg",
|
|
10257
|
+
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
10258
|
+
children: [
|
|
10259
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
10260
|
+
/* @__PURE__ */ jsx(Percent, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
10261
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "APY" })
|
|
10262
|
+
] }),
|
|
10263
|
+
/* @__PURE__ */ jsxs(
|
|
10264
|
+
"p",
|
|
10265
|
+
{
|
|
10266
|
+
className: "font-semibold",
|
|
10267
|
+
style: { color: "var(--compass-color-success)" },
|
|
10268
|
+
children: [
|
|
10269
|
+
parseFloat(position.apy).toFixed(2),
|
|
10270
|
+
"%"
|
|
10271
|
+
]
|
|
10272
|
+
}
|
|
10273
|
+
)
|
|
10274
|
+
]
|
|
10275
|
+
}
|
|
10276
|
+
),
|
|
10277
|
+
isPendle && duration && /* @__PURE__ */ jsxs(
|
|
10278
|
+
"div",
|
|
10279
|
+
{
|
|
10280
|
+
className: "p-3 rounded-lg",
|
|
10281
|
+
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
10282
|
+
children: [
|
|
10283
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
10284
|
+
/* @__PURE__ */ jsx(Clock, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
10285
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "Duration" })
|
|
10286
|
+
] }),
|
|
10287
|
+
/* @__PURE__ */ jsx(
|
|
10288
|
+
"p",
|
|
10289
|
+
{
|
|
10290
|
+
className: "font-semibold",
|
|
10291
|
+
style: { color: "var(--compass-color-text)" },
|
|
10292
|
+
children: duration
|
|
10293
|
+
}
|
|
10294
|
+
)
|
|
10295
|
+
]
|
|
10296
|
+
}
|
|
10297
|
+
),
|
|
10298
|
+
isPendle && expiryDate && /* @__PURE__ */ jsxs(
|
|
10299
|
+
"div",
|
|
10300
|
+
{
|
|
10301
|
+
className: "p-3 rounded-lg",
|
|
10302
|
+
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
10303
|
+
children: [
|
|
10304
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
10305
|
+
/* @__PURE__ */ jsx(Calendar, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
10306
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "Expiry (UTC)" })
|
|
10307
|
+
] }),
|
|
10308
|
+
/* @__PURE__ */ jsx(
|
|
10309
|
+
"p",
|
|
10310
|
+
{
|
|
10311
|
+
className: "font-semibold",
|
|
10312
|
+
style: { color: "var(--compass-color-text)" },
|
|
10313
|
+
children: expiryDate
|
|
10314
|
+
}
|
|
10315
|
+
)
|
|
10316
|
+
]
|
|
10317
|
+
}
|
|
10318
|
+
),
|
|
10319
|
+
position.pnl && /* @__PURE__ */ jsxs(
|
|
10320
|
+
"div",
|
|
10321
|
+
{
|
|
10322
|
+
className: "p-3 rounded-lg",
|
|
10323
|
+
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
10324
|
+
children: [
|
|
10325
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
10326
|
+
isPnlPositive ? /* @__PURE__ */ jsx(TrendingUp, { size: 14, style: { color: "var(--compass-color-success)" } }) : /* @__PURE__ */ jsx(TrendingDown, { size: 14, style: { color: "var(--compass-color-error)" } }),
|
|
10327
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "Total P&L" })
|
|
10328
|
+
] }),
|
|
10329
|
+
/* @__PURE__ */ jsxs(
|
|
10330
|
+
"p",
|
|
10331
|
+
{
|
|
10332
|
+
className: "font-semibold",
|
|
10333
|
+
style: {
|
|
10334
|
+
color: isPnlPositive ? "var(--compass-color-success)" : "var(--compass-color-error)"
|
|
10335
|
+
},
|
|
10336
|
+
children: [
|
|
10337
|
+
isPnlPositive ? "+" : "",
|
|
10338
|
+
formatUSD(position.pnl.totalPnl)
|
|
10339
|
+
]
|
|
10340
|
+
}
|
|
10341
|
+
)
|
|
10342
|
+
]
|
|
10343
|
+
}
|
|
10344
|
+
)
|
|
10345
|
+
] }),
|
|
10346
|
+
(position.deposits.length > 0 || position.withdrawals.length > 0) && /* @__PURE__ */ jsxs("div", { className: "p-4", children: [
|
|
10347
|
+
/* @__PURE__ */ jsx(
|
|
10348
|
+
"h3",
|
|
10349
|
+
{
|
|
10350
|
+
className: "font-semibold mb-3",
|
|
10351
|
+
style: { color: "var(--compass-color-text)" },
|
|
10352
|
+
children: "Transaction History"
|
|
10353
|
+
}
|
|
10354
|
+
),
|
|
10355
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
10356
|
+
position.deposits.map((tx, i) => {
|
|
10357
|
+
const date = formatDate(tx.timestamp);
|
|
10358
|
+
return /* @__PURE__ */ jsxs(
|
|
10359
|
+
"div",
|
|
9692
10360
|
{
|
|
9693
|
-
className: "
|
|
9694
|
-
style: {
|
|
9695
|
-
color: isPnlPositive ? "var(--compass-color-success)" : "var(--compass-color-error)"
|
|
9696
|
-
},
|
|
10361
|
+
className: "flex items-center justify-between p-3 rounded-lg",
|
|
10362
|
+
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
9697
10363
|
children: [
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
|
|
9703
|
-
|
|
9704
|
-
|
|
9705
|
-
|
|
9706
|
-
|
|
9707
|
-
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
9719
|
-
|
|
9720
|
-
|
|
9721
|
-
|
|
9722
|
-
|
|
9723
|
-
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
9724
|
-
children: [
|
|
9725
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
9726
|
-
/* @__PURE__ */ jsxs(
|
|
9727
|
-
"p",
|
|
9728
|
-
{
|
|
9729
|
-
className: "font-medium",
|
|
9730
|
-
style: { color: "var(--compass-color-success)" },
|
|
9731
|
-
children: [
|
|
9732
|
-
"+",
|
|
9733
|
-
formatAmount(tx.amount),
|
|
9734
|
-
" ",
|
|
9735
|
-
position.assetSymbol
|
|
9736
|
-
]
|
|
9737
|
-
}
|
|
9738
|
-
),
|
|
9739
|
-
/* @__PURE__ */ jsx(
|
|
9740
|
-
"p",
|
|
10364
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
10365
|
+
/* @__PURE__ */ jsxs(
|
|
10366
|
+
"p",
|
|
10367
|
+
{
|
|
10368
|
+
className: "font-medium",
|
|
10369
|
+
style: { color: "var(--compass-color-success)" },
|
|
10370
|
+
children: [
|
|
10371
|
+
"+",
|
|
10372
|
+
formatAmount(tx.amount),
|
|
10373
|
+
" ",
|
|
10374
|
+
position.assetSymbol
|
|
10375
|
+
]
|
|
10376
|
+
}
|
|
10377
|
+
),
|
|
10378
|
+
/* @__PURE__ */ jsx(
|
|
10379
|
+
"p",
|
|
10380
|
+
{
|
|
10381
|
+
className: "text-xs",
|
|
10382
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
10383
|
+
children: date ? `Deposit - ${date}` : "Deposit"
|
|
10384
|
+
}
|
|
10385
|
+
)
|
|
10386
|
+
] }),
|
|
10387
|
+
tx.txHash && /* @__PURE__ */ jsx(
|
|
10388
|
+
"a",
|
|
9741
10389
|
{
|
|
9742
|
-
|
|
9743
|
-
|
|
9744
|
-
|
|
10390
|
+
href: `https://etherscan.io/tx/${tx.txHash}`,
|
|
10391
|
+
target: "_blank",
|
|
10392
|
+
rel: "noopener noreferrer",
|
|
10393
|
+
className: "p-2 rounded-lg hover:opacity-80 transition-opacity",
|
|
10394
|
+
style: { backgroundColor: "var(--compass-color-background)" },
|
|
10395
|
+
children: /* @__PURE__ */ jsx(ExternalLink, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } })
|
|
9745
10396
|
}
|
|
9746
10397
|
)
|
|
9747
|
-
]
|
|
9748
|
-
|
|
9749
|
-
|
|
9750
|
-
|
|
9751
|
-
|
|
9752
|
-
|
|
9753
|
-
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
|
|
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
|
-
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
),
|
|
9786
|
-
/* @__PURE__ */ jsx(
|
|
9787
|
-
"p",
|
|
10398
|
+
]
|
|
10399
|
+
},
|
|
10400
|
+
`deposit-${i}`
|
|
10401
|
+
);
|
|
10402
|
+
}),
|
|
10403
|
+
position.withdrawals.map((tx, i) => {
|
|
10404
|
+
const date = formatDate(tx.timestamp);
|
|
10405
|
+
return /* @__PURE__ */ jsxs(
|
|
10406
|
+
"div",
|
|
10407
|
+
{
|
|
10408
|
+
className: "flex items-center justify-between p-3 rounded-lg",
|
|
10409
|
+
style: { backgroundColor: "var(--compass-color-surface)" },
|
|
10410
|
+
children: [
|
|
10411
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
10412
|
+
/* @__PURE__ */ jsxs(
|
|
10413
|
+
"p",
|
|
10414
|
+
{
|
|
10415
|
+
className: "font-medium",
|
|
10416
|
+
style: { color: "var(--compass-color-error)" },
|
|
10417
|
+
children: [
|
|
10418
|
+
"-",
|
|
10419
|
+
formatAmount(tx.amount),
|
|
10420
|
+
" ",
|
|
10421
|
+
position.assetSymbol
|
|
10422
|
+
]
|
|
10423
|
+
}
|
|
10424
|
+
),
|
|
10425
|
+
/* @__PURE__ */ jsx(
|
|
10426
|
+
"p",
|
|
10427
|
+
{
|
|
10428
|
+
className: "text-xs",
|
|
10429
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
10430
|
+
children: date ? `Withdrawal - ${date}` : "Withdrawal"
|
|
10431
|
+
}
|
|
10432
|
+
)
|
|
10433
|
+
] }),
|
|
10434
|
+
tx.txHash && /* @__PURE__ */ jsx(
|
|
10435
|
+
"a",
|
|
9788
10436
|
{
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
10437
|
+
href: `https://etherscan.io/tx/${tx.txHash}`,
|
|
10438
|
+
target: "_blank",
|
|
10439
|
+
rel: "noopener noreferrer",
|
|
10440
|
+
className: "p-2 rounded-lg hover:opacity-80 transition-opacity",
|
|
10441
|
+
style: { backgroundColor: "var(--compass-color-background)" },
|
|
10442
|
+
children: /* @__PURE__ */ jsx(ExternalLink, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } })
|
|
9792
10443
|
}
|
|
9793
10444
|
)
|
|
9794
|
-
]
|
|
9795
|
-
|
|
9796
|
-
|
|
9797
|
-
|
|
9798
|
-
|
|
9799
|
-
|
|
9800
|
-
rel: "noopener noreferrer",
|
|
9801
|
-
className: "p-2 rounded-lg hover:opacity-80 transition-opacity",
|
|
9802
|
-
style: { backgroundColor: "var(--compass-color-background)" },
|
|
9803
|
-
children: /* @__PURE__ */ jsx(ExternalLink, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } })
|
|
9804
|
-
}
|
|
9805
|
-
)
|
|
9806
|
-
]
|
|
9807
|
-
},
|
|
9808
|
-
`withdraw-${i}`
|
|
9809
|
-
);
|
|
9810
|
-
})
|
|
10445
|
+
]
|
|
10446
|
+
},
|
|
10447
|
+
`withdraw-${i}`
|
|
10448
|
+
);
|
|
10449
|
+
})
|
|
10450
|
+
] })
|
|
9811
10451
|
] })
|
|
9812
|
-
]
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
10452
|
+
]
|
|
10453
|
+
}
|
|
10454
|
+
)
|
|
10455
|
+
]
|
|
9816
10456
|
}
|
|
9817
10457
|
);
|
|
9818
10458
|
}
|
|
@@ -10581,7 +11221,7 @@ function AllocationEditor({
|
|
|
10581
11221
|
) })
|
|
10582
11222
|
] });
|
|
10583
11223
|
}
|
|
10584
|
-
var
|
|
11224
|
+
var EVM_CHAIN_IDS4 = {
|
|
10585
11225
|
ethereum: 1,
|
|
10586
11226
|
base: 8453,
|
|
10587
11227
|
arbitrum: 42161
|
|
@@ -10615,7 +11255,7 @@ function RebalancingWidget({
|
|
|
10615
11255
|
}) {
|
|
10616
11256
|
const { chainId: contextChainId, setChainId } = useChain();
|
|
10617
11257
|
const CHAIN_ID = chain || contextChainId;
|
|
10618
|
-
const { address, signTypedData, isConnected, login, logout, switchChain, walletChainId } = useEmbeddableWallet();
|
|
11258
|
+
const { address, signTypedData, isConnected, login, logout, switchChain, walletChainId, fundWallet, hasExternalWallet } = useEmbeddableWallet();
|
|
10619
11259
|
const { earnAccountAddress } = useEarnAccount();
|
|
10620
11260
|
const queryClient = useQueryClient();
|
|
10621
11261
|
const { portfolio, earnAccountMarkets, isMarketsLoading, isLoading, isError, error, refetch } = useRebalancingData(chain);
|
|
@@ -10664,10 +11304,11 @@ function RebalancingWidget({
|
|
|
10664
11304
|
const [selectedToken, setSelectedToken] = useState("USDC");
|
|
10665
11305
|
const [depositAmount, setDepositAmount] = useState("");
|
|
10666
11306
|
const [isTokenDropdownOpen, setIsTokenDropdownOpen] = useState(false);
|
|
10667
|
-
const [
|
|
10668
|
-
const [depositError, setDepositError] = useState(null);
|
|
10669
|
-
const [depositStatus, setDepositStatus] = useState("");
|
|
11307
|
+
const [depositTxState, setDepositTxState] = useState({ status: "idle" });
|
|
10670
11308
|
const earnBalanceRef = useRef(null);
|
|
11309
|
+
const { startPolling: startDepositPolling, clearPolling: clearDepositPolling } = useTxPolling({
|
|
11310
|
+
queryKeysToInvalidate: [["earnAccountBalances"], ["rebalancing"]]
|
|
11311
|
+
});
|
|
10671
11312
|
useEffect(() => {
|
|
10672
11313
|
setTargets([]);
|
|
10673
11314
|
setOriginalAllocations({});
|
|
@@ -10682,9 +11323,9 @@ function RebalancingWidget({
|
|
|
10682
11323
|
setIsSwapModalOpen(false);
|
|
10683
11324
|
setSelectedMarket(null);
|
|
10684
11325
|
setDepositAmount("");
|
|
10685
|
-
|
|
10686
|
-
|
|
10687
|
-
}, [CHAIN_ID]);
|
|
11326
|
+
setDepositTxState({ status: "idle" });
|
|
11327
|
+
clearDepositPolling();
|
|
11328
|
+
}, [CHAIN_ID, clearDepositPolling]);
|
|
10688
11329
|
useEffect(() => {
|
|
10689
11330
|
if (portfolio && portfolio.positions.length > 0 && !hasInitializedTargets && !isLoading) {
|
|
10690
11331
|
const origAllocs = {};
|
|
@@ -10765,7 +11406,7 @@ function RebalancingWidget({
|
|
|
10765
11406
|
setTargets((prev) => prev.map((t, i) => i === index ? { ...t, targetPercent: rounded } : t));
|
|
10766
11407
|
}, []);
|
|
10767
11408
|
const ensureCorrectChain = useCallback(async () => {
|
|
10768
|
-
const targetChainId =
|
|
11409
|
+
const targetChainId = EVM_CHAIN_IDS4[CHAIN_ID];
|
|
10769
11410
|
if (!targetChainId) return;
|
|
10770
11411
|
if (walletChainId !== void 0 && walletChainId !== targetChainId) {
|
|
10771
11412
|
if (!switchChain) {
|
|
@@ -10897,13 +11538,11 @@ function RebalancingWidget({
|
|
|
10897
11538
|
};
|
|
10898
11539
|
const handleDeposit = useCallback(async () => {
|
|
10899
11540
|
if (!selectedMarket || !depositAmount || parseFloat(depositAmount) <= 0 || !address || !signTypedData) return;
|
|
10900
|
-
|
|
10901
|
-
setDepositError(null);
|
|
11541
|
+
setDepositTxState({ status: "preparing" });
|
|
10902
11542
|
const underlyingToken = selectedMarket.underlyingToken;
|
|
10903
11543
|
try {
|
|
10904
11544
|
let resultTxHash;
|
|
10905
11545
|
if (needsSwap) {
|
|
10906
|
-
setDepositStatus("Getting swap quote...");
|
|
10907
11546
|
const quoteResponse = await fetch(
|
|
10908
11547
|
`/api/compass/swap/quote?owner=${address}&chain=${CHAIN_ID}&tokenIn=${selectedToken}&tokenOut=${underlyingToken}&amountIn=${depositAmount}`
|
|
10909
11548
|
);
|
|
@@ -10917,7 +11556,6 @@ function RebalancingWidget({
|
|
|
10917
11556
|
throw new Error("Invalid swap quote - no output amount");
|
|
10918
11557
|
}
|
|
10919
11558
|
const actualDepositAmount = (parseFloat(estimatedOutput) * 0.99999).toString();
|
|
10920
|
-
setDepositStatus("Preparing swap and deposit...");
|
|
10921
11559
|
const bundleActions = [
|
|
10922
11560
|
{
|
|
10923
11561
|
body: {
|
|
@@ -10951,7 +11589,7 @@ function RebalancingWidget({
|
|
|
10951
11589
|
throw new Error(errorData.error || "Failed to prepare bundle");
|
|
10952
11590
|
}
|
|
10953
11591
|
const { eip712, normalizedTypes, domain, message } = await prepareResponse.json();
|
|
10954
|
-
|
|
11592
|
+
setDepositTxState({ status: "signing" });
|
|
10955
11593
|
await ensureCorrectChain();
|
|
10956
11594
|
const signature = await signTypedData({
|
|
10957
11595
|
domain,
|
|
@@ -10959,7 +11597,7 @@ function RebalancingWidget({
|
|
|
10959
11597
|
primaryType: "SafeTx",
|
|
10960
11598
|
message
|
|
10961
11599
|
});
|
|
10962
|
-
|
|
11600
|
+
setDepositTxState({ status: "broadcasting" });
|
|
10963
11601
|
const executeResponse = await fetch("/api/compass/bundle/execute", {
|
|
10964
11602
|
method: "POST",
|
|
10965
11603
|
headers: { "Content-Type": "application/json" },
|
|
@@ -10977,7 +11615,6 @@ function RebalancingWidget({
|
|
|
10977
11615
|
const result = await executeResponse.json();
|
|
10978
11616
|
resultTxHash = result.txHash;
|
|
10979
11617
|
} else {
|
|
10980
|
-
setDepositStatus("Preparing deposit...");
|
|
10981
11618
|
const venueParams = buildVenueParamsFromMarket(selectedMarket);
|
|
10982
11619
|
const prepareResponse = await fetch("/api/compass/deposit/prepare", {
|
|
10983
11620
|
method: "POST",
|
|
@@ -10994,7 +11631,7 @@ function RebalancingWidget({
|
|
|
10994
11631
|
throw new Error(errData.error || "Failed to prepare deposit");
|
|
10995
11632
|
}
|
|
10996
11633
|
const prepareData = await prepareResponse.json();
|
|
10997
|
-
|
|
11634
|
+
setDepositTxState({ status: "signing" });
|
|
10998
11635
|
await ensureCorrectChain();
|
|
10999
11636
|
const signature = await signTypedData({
|
|
11000
11637
|
domain: prepareData.domain,
|
|
@@ -11002,7 +11639,7 @@ function RebalancingWidget({
|
|
|
11002
11639
|
primaryType: "SafeTx",
|
|
11003
11640
|
message: prepareData.message
|
|
11004
11641
|
});
|
|
11005
|
-
|
|
11642
|
+
setDepositTxState({ status: "broadcasting" });
|
|
11006
11643
|
const executeResponse = await fetch("/api/compass/deposit/execute", {
|
|
11007
11644
|
method: "POST",
|
|
11008
11645
|
headers: { "Content-Type": "application/json" },
|
|
@@ -11020,7 +11657,8 @@ function RebalancingWidget({
|
|
|
11020
11657
|
const result = await executeResponse.json();
|
|
11021
11658
|
resultTxHash = result.txHash;
|
|
11022
11659
|
}
|
|
11023
|
-
|
|
11660
|
+
setDepositTxState({ status: "submitted", txHash: resultTxHash });
|
|
11661
|
+
startDepositPolling(resultTxHash, setDepositTxState);
|
|
11024
11662
|
setDepositAmount("");
|
|
11025
11663
|
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
11026
11664
|
queryClient.invalidateQueries({ queryKey: ["rebalancing"] });
|
|
@@ -11032,15 +11670,11 @@ function RebalancingWidget({
|
|
|
11032
11670
|
refetch();
|
|
11033
11671
|
}, delay);
|
|
11034
11672
|
}
|
|
11035
|
-
setTimeout(() => setDepositStatus(""), 3e3);
|
|
11036
11673
|
} catch (err) {
|
|
11037
|
-
|
|
11038
|
-
setDepositStatus("");
|
|
11674
|
+
setDepositTxState({ status: "failed", error: err instanceof Error ? err.message : "Deposit failed" });
|
|
11039
11675
|
onError?.(err instanceof Error ? err : new Error("Deposit failed"));
|
|
11040
|
-
} finally {
|
|
11041
|
-
setIsProcessing(false);
|
|
11042
11676
|
}
|
|
11043
|
-
}, [selectedMarket, depositAmount, address, signTypedData, selectedToken, needsSwap, CHAIN_ID, ensureCorrectChain, queryClient, refetch, onError]);
|
|
11677
|
+
}, [selectedMarket, depositAmount, address, signTypedData, selectedToken, needsSwap, CHAIN_ID, ensureCorrectChain, queryClient, refetch, onError, startDepositPolling]);
|
|
11044
11678
|
return /* @__PURE__ */ 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: [
|
|
11045
11679
|
/* @__PURE__ */ jsxs("div", { style: { flex: 1, minHeight: 0, overflowY: "auto", scrollbarWidth: "none", display: "flex", flexDirection: "column" }, children: [
|
|
11046
11680
|
showChainSwitcher && !chain && /* @__PURE__ */ jsx("div", { style: { padding: "0 4px", marginBottom: "8px" }, children: /* @__PURE__ */ jsx(ChainSwitcher, {}) }),
|
|
@@ -11069,8 +11703,19 @@ function RebalancingWidget({
|
|
|
11069
11703
|
}
|
|
11070
11704
|
)
|
|
11071
11705
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
11072
|
-
/* @__PURE__ */ jsx("p", { className: "text-lg font-semibold mb-2", style: { color: "var(--compass-color-text)" }, children: "No positions found" }),
|
|
11073
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm", style: { color: "var(--compass-color-text-secondary)" }, children: "Deposit into a vault, Aave market, or Pendle market to start rebalancing." })
|
|
11706
|
+
/* @__PURE__ */ 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" }),
|
|
11707
|
+
/* @__PURE__ */ 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." }),
|
|
11708
|
+
fundWallet && earnAccountAddress && /* @__PURE__ */ jsx("div", { style: { width: "100%", maxWidth: "320px" }, children: /* @__PURE__ */ jsx(
|
|
11709
|
+
BuyForm,
|
|
11710
|
+
{
|
|
11711
|
+
targetAddress: earnAccountAddress,
|
|
11712
|
+
onComplete: () => {
|
|
11713
|
+
queryClient.invalidateQueries({ queryKey: ["rebalancingPortfolio"] });
|
|
11714
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
11715
|
+
refetch();
|
|
11716
|
+
}
|
|
11717
|
+
}
|
|
11718
|
+
) })
|
|
11074
11719
|
] }) }),
|
|
11075
11720
|
state !== "loading" && state !== "empty" && portfolio && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
11076
11721
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center text-center", style: { padding: "16px 16px 12px" }, children: [
|
|
@@ -11237,7 +11882,7 @@ function RebalancingWidget({
|
|
|
11237
11882
|
selectedMarket,
|
|
11238
11883
|
onMarketSelect: (market) => {
|
|
11239
11884
|
setSelectedMarket(market);
|
|
11240
|
-
|
|
11885
|
+
if (depositTxState.status === "failed") setDepositTxState({ status: "idle" });
|
|
11241
11886
|
},
|
|
11242
11887
|
isLoading: isMarketsLoading
|
|
11243
11888
|
}
|
|
@@ -11260,10 +11905,10 @@ function RebalancingWidget({
|
|
|
11260
11905
|
value: depositAmount,
|
|
11261
11906
|
onChange: (e) => {
|
|
11262
11907
|
setDepositAmount(e.target.value);
|
|
11263
|
-
|
|
11908
|
+
if (depositTxState.status === "failed") setDepositTxState({ status: "idle" });
|
|
11264
11909
|
},
|
|
11265
11910
|
placeholder: "0.00",
|
|
11266
|
-
disabled:
|
|
11911
|
+
disabled: depositTxState.status !== "idle" && depositTxState.status !== "confirmed" && depositTxState.status !== "failed",
|
|
11267
11912
|
className: "flex-1 font-bold bg-transparent outline-none",
|
|
11268
11913
|
style: {
|
|
11269
11914
|
color: "var(--compass-color-text)",
|
|
@@ -11279,7 +11924,7 @@ function RebalancingWidget({
|
|
|
11279
11924
|
"button",
|
|
11280
11925
|
{
|
|
11281
11926
|
onClick: () => setIsTokenDropdownOpen(!isTokenDropdownOpen),
|
|
11282
|
-
disabled:
|
|
11927
|
+
disabled: depositTxState.status !== "idle" && depositTxState.status !== "confirmed" && depositTxState.status !== "failed",
|
|
11283
11928
|
className: "flex items-center font-semibold",
|
|
11284
11929
|
style: {
|
|
11285
11930
|
backgroundColor: "var(--compass-color-surface-hover, var(--compass-color-surface))",
|
|
@@ -11316,7 +11961,7 @@ function RebalancingWidget({
|
|
|
11316
11961
|
onClick: () => {
|
|
11317
11962
|
setSelectedToken(token);
|
|
11318
11963
|
setIsTokenDropdownOpen(false);
|
|
11319
|
-
|
|
11964
|
+
if (depositTxState.status === "failed") setDepositTxState({ status: "idle" });
|
|
11320
11965
|
},
|
|
11321
11966
|
className: "w-full text-left font-medium",
|
|
11322
11967
|
style: {
|
|
@@ -11342,7 +11987,7 @@ function RebalancingWidget({
|
|
|
11342
11987
|
"button",
|
|
11343
11988
|
{
|
|
11344
11989
|
onClick: () => setDepositAmount(earnBalancesQuery.toString()),
|
|
11345
|
-
disabled:
|
|
11990
|
+
disabled: depositTxState.status !== "idle" && depositTxState.status !== "confirmed" && depositTxState.status !== "failed",
|
|
11346
11991
|
className: "font-semibold",
|
|
11347
11992
|
style: { color: "var(--compass-color-primary)", fontSize: "0.8125rem", background: "none", border: "none", padding: 0 },
|
|
11348
11993
|
children: [
|
|
@@ -11379,26 +12024,12 @@ function RebalancingWidget({
|
|
|
11379
12024
|
]
|
|
11380
12025
|
}
|
|
11381
12026
|
),
|
|
11382
|
-
|
|
11383
|
-
"div",
|
|
11384
|
-
{
|
|
11385
|
-
className: "flex items-center",
|
|
11386
|
-
style: {
|
|
11387
|
-
backgroundColor: "var(--compass-color-error-muted)",
|
|
11388
|
-
color: "var(--compass-color-error)",
|
|
11389
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
11390
|
-
padding: "12px 14px",
|
|
11391
|
-
gap: "8px",
|
|
11392
|
-
fontSize: "0.875rem"
|
|
11393
|
-
},
|
|
11394
|
-
children: depositError
|
|
11395
|
-
}
|
|
11396
|
-
),
|
|
12027
|
+
/* @__PURE__ */ jsx(TxStatus, { state: depositTxState }),
|
|
11397
12028
|
/* @__PURE__ */ jsx(
|
|
11398
12029
|
"button",
|
|
11399
12030
|
{
|
|
11400
12031
|
onClick: !isConnected && login ? login : handleDeposit,
|
|
11401
|
-
disabled: isConnected && (
|
|
12032
|
+
disabled: isConnected && (depositTxState.status !== "idle" && depositTxState.status !== "confirmed" && depositTxState.status !== "failed" || !selectedMarket || !depositAmount || parseFloat(depositAmount) <= 0 || parseFloat(depositAmount) > earnBalancesQuery),
|
|
11402
12033
|
className: "w-full font-bold",
|
|
11403
12034
|
style: {
|
|
11404
12035
|
backgroundColor: "var(--compass-color-primary)",
|
|
@@ -11409,26 +12040,13 @@ function RebalancingWidget({
|
|
|
11409
12040
|
fontSize: "1rem",
|
|
11410
12041
|
transition: "all 200ms ease",
|
|
11411
12042
|
border: "none",
|
|
11412
|
-
opacity: isConnected && (
|
|
12043
|
+
opacity: isConnected && (depositTxState.status !== "idle" && depositTxState.status !== "confirmed" && depositTxState.status !== "failed" || !selectedMarket || !depositAmount || parseFloat(depositAmount) <= 0 || parseFloat(depositAmount) > earnBalancesQuery) ? 0.4 : 1
|
|
11413
12044
|
},
|
|
11414
|
-
children: !isConnected ? "Connect Wallet" :
|
|
12045
|
+
children: !isConnected ? "Connect Wallet" : depositTxState.status !== "idle" && depositTxState.status !== "confirmed" && depositTxState.status !== "failed" ? /* @__PURE__ */ jsxs("span", { className: "flex items-center justify-center", style: { gap: "8px" }, children: [
|
|
11415
12046
|
/* @__PURE__ */ jsx(Loader2, { size: 16, className: "animate-spin" }),
|
|
11416
12047
|
"Processing..."
|
|
11417
12048
|
] }) : !selectedMarket ? "Select a market" : needsSwap ? "Swap & Deposit" : "Deposit"
|
|
11418
12049
|
}
|
|
11419
|
-
),
|
|
11420
|
-
depositStatus && !depositError && /* @__PURE__ */ jsx(
|
|
11421
|
-
"div",
|
|
11422
|
-
{
|
|
11423
|
-
className: "text-sm text-center",
|
|
11424
|
-
style: {
|
|
11425
|
-
backgroundColor: depositStatus.includes("successful") ? "var(--compass-color-success-muted)" : "var(--compass-color-primary-muted, rgba(99, 102, 241, 0.1))",
|
|
11426
|
-
color: depositStatus.includes("successful") ? "var(--compass-color-success)" : "var(--compass-color-primary)",
|
|
11427
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
11428
|
-
padding: "10px 12px"
|
|
11429
|
-
},
|
|
11430
|
-
children: depositStatus
|
|
11431
|
-
}
|
|
11432
12050
|
)
|
|
11433
12051
|
] }),
|
|
11434
12052
|
clientPreview && clientPreview.actions.length > 0 && state === "editing" && /* @__PURE__ */ jsxs(
|