@compass-labs/widgets 0.1.35 → 0.1.37
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.js +291 -163
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +291 -163
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.js +138 -82
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +138 -82
- package/dist/server/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -6746,7 +6746,7 @@ function PositionsView({ allowedCollateralTokens, allowedDebtTokens, onBorrow, o
|
|
|
6746
6746
|
"span",
|
|
6747
6747
|
{
|
|
6748
6748
|
className: "text-lg font-semibold tabular-nums",
|
|
6749
|
-
style: { color:
|
|
6749
|
+
style: { color: "var(--compass-color-text)" },
|
|
6750
6750
|
children: totalDebtUsd
|
|
6751
6751
|
}
|
|
6752
6752
|
),
|
|
@@ -7121,11 +7121,11 @@ function DebtPositionCard({
|
|
|
7121
7121
|
] }),
|
|
7122
7122
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
7123
7123
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text-tertiary)" }, children: "Borrow APY" }),
|
|
7124
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-
|
|
7124
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-warning, #f59e0b)" }, children: formatApy(position.borrowApy) })
|
|
7125
7125
|
] }),
|
|
7126
7126
|
position.interestPaid !== null && position.interestPaid !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
7127
7127
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text-tertiary)" }, children: "Interest paid" }),
|
|
7128
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: "var(--compass-color-
|
|
7128
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: "var(--compass-color-text)" }, children: [
|
|
7129
7129
|
formatNumber(position.interestPaid),
|
|
7130
7130
|
" ",
|
|
7131
7131
|
position.symbol
|
|
@@ -7287,7 +7287,7 @@ function BorrowModal({ isOpen, onClose, initialToken, allowedTokens }) {
|
|
|
7287
7287
|
},
|
|
7288
7288
|
children: isBusy ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7289
7289
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
7290
|
-
txState.status === "preparing" ? "Preparing..." : txState.status === "signing" ? "
|
|
7290
|
+
txState.status === "preparing" ? "Preparing..." : txState.status === "signing" ? "Signing Borrow..." : "Broadcasting..."
|
|
7291
7291
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7292
7292
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingUp, { className: "h-4 w-4" }),
|
|
7293
7293
|
"Borrow"
|
|
@@ -7443,7 +7443,7 @@ function RepayModal({ isOpen, onClose, initialToken, allowedTokens }) {
|
|
|
7443
7443
|
},
|
|
7444
7444
|
children: isBusy ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7445
7445
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
7446
|
-
txState.status === "preparing" ? "Preparing..." : txState.status === "signing" ? "
|
|
7446
|
+
txState.status === "preparing" ? "Preparing..." : txState.status === "signing" ? "Signing Repay..." : "Broadcasting..."
|
|
7447
7447
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7448
7448
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownLeft, { className: "h-4 w-4" }),
|
|
7449
7449
|
"Repay"
|
|
@@ -7599,7 +7599,7 @@ function SupplyModal({ isOpen, onClose, initialToken, allowedTokens }) {
|
|
|
7599
7599
|
},
|
|
7600
7600
|
children: isBusy ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7601
7601
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
7602
|
-
txState.status === "preparing" ? "Preparing..." : txState.status === "signing" ? "
|
|
7602
|
+
txState.status === "preparing" ? "Preparing..." : txState.status === "signing" ? "Signing Supply..." : "Broadcasting..."
|
|
7603
7603
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7604
7604
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpCircle, { className: "h-4 w-4" }),
|
|
7605
7605
|
"Supply"
|
|
@@ -7613,12 +7613,20 @@ function WithdrawModal({ isOpen, onClose, initialToken, allowedTokens }) {
|
|
|
7613
7613
|
const { address } = useEmbeddableWallet();
|
|
7614
7614
|
const { isDeployed } = useCreditAccount();
|
|
7615
7615
|
const { txState, executeBundle, resetState } = useCreditBundle();
|
|
7616
|
+
const { data: positionsData } = useCreditPositions();
|
|
7616
7617
|
const prices = useTokenPrices();
|
|
7617
7618
|
const [token, setToken] = react.useState(initialToken || "USDC");
|
|
7618
7619
|
const [amount, setAmount] = react.useState("");
|
|
7619
7620
|
react.useEffect(() => {
|
|
7620
7621
|
if (initialToken) setToken(initialToken);
|
|
7621
7622
|
}, [initialToken]);
|
|
7623
|
+
const suppliedAmount = (() => {
|
|
7624
|
+
if (!positionsData) return null;
|
|
7625
|
+
const pos = positionsData.collateralPositions.find((p) => p.symbol === token);
|
|
7626
|
+
if (!pos || !pos.amountSupplied) return null;
|
|
7627
|
+
const amt = parseFloat(pos.amountSupplied);
|
|
7628
|
+
return amt > 0 ? amt : null;
|
|
7629
|
+
})();
|
|
7622
7630
|
const isValid = Number(amount) > 0 && !!address && isDeployed;
|
|
7623
7631
|
const isBusy = txState.status === "preparing" || txState.status === "signing" || txState.status === "broadcasting";
|
|
7624
7632
|
react.useEffect(() => {
|
|
@@ -7673,7 +7681,19 @@ function WithdrawModal({ isOpen, onClose, initialToken, allowedTokens }) {
|
|
|
7673
7681
|
)
|
|
7674
7682
|
] }),
|
|
7675
7683
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
7676
|
-
/* @__PURE__ */ jsxRuntime.
|
|
7684
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-1.5", children: [
|
|
7685
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm", style: labelStyle, children: "Amount" }),
|
|
7686
|
+
suppliedAmount !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7687
|
+
"button",
|
|
7688
|
+
{
|
|
7689
|
+
type: "button",
|
|
7690
|
+
onClick: () => setAmount(suppliedAmount.toFixed(6).replace(/\.?0+$/, "")),
|
|
7691
|
+
className: "text-xs font-medium transition-opacity hover:opacity-80",
|
|
7692
|
+
style: { color: "var(--compass-color-primary)" },
|
|
7693
|
+
children: "MAX"
|
|
7694
|
+
}
|
|
7695
|
+
)
|
|
7696
|
+
] }),
|
|
7677
7697
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
7678
7698
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7679
7699
|
"input",
|
|
@@ -7695,18 +7715,33 @@ function WithdrawModal({ isOpen, onClose, initialToken, allowedTokens }) {
|
|
|
7695
7715
|
}
|
|
7696
7716
|
)
|
|
7697
7717
|
] }),
|
|
7698
|
-
|
|
7699
|
-
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
|
|
7708
|
-
|
|
7709
|
-
|
|
7718
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mt-1", children: [
|
|
7719
|
+
formatUsdEstimate(amount, token, prices) ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7720
|
+
"span",
|
|
7721
|
+
{
|
|
7722
|
+
className: "text-xs",
|
|
7723
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
7724
|
+
children: [
|
|
7725
|
+
"\u2248",
|
|
7726
|
+
" ",
|
|
7727
|
+
formatUsdEstimate(amount, token, prices)
|
|
7728
|
+
]
|
|
7729
|
+
}
|
|
7730
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
|
|
7731
|
+
suppliedAmount !== null && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7732
|
+
"span",
|
|
7733
|
+
{
|
|
7734
|
+
className: "text-xs",
|
|
7735
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
7736
|
+
children: [
|
|
7737
|
+
"Supplied: ",
|
|
7738
|
+
suppliedAmount.toLocaleString(void 0, { maximumFractionDigits: 4 }),
|
|
7739
|
+
" ",
|
|
7740
|
+
token
|
|
7741
|
+
]
|
|
7742
|
+
}
|
|
7743
|
+
)
|
|
7744
|
+
] })
|
|
7710
7745
|
] })
|
|
7711
7746
|
] }),
|
|
7712
7747
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -7724,7 +7759,7 @@ function WithdrawModal({ isOpen, onClose, initialToken, allowedTokens }) {
|
|
|
7724
7759
|
},
|
|
7725
7760
|
children: isBusy ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7726
7761
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
7727
|
-
txState.status === "preparing" ? "Preparing..." : txState.status === "signing" ? "
|
|
7762
|
+
txState.status === "preparing" ? "Preparing..." : txState.status === "signing" ? "Signing Withdraw..." : "Broadcasting..."
|
|
7728
7763
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7729
7764
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownCircle, { className: "h-4 w-4" }),
|
|
7730
7765
|
"Withdraw"
|
|
@@ -7736,13 +7771,18 @@ function WithdrawModal({ isOpen, onClose, initialToken, allowedTokens }) {
|
|
|
7736
7771
|
}
|
|
7737
7772
|
function getPhase2(step) {
|
|
7738
7773
|
if (step === "idle" || step === "failed") return 0;
|
|
7739
|
-
if (step === "
|
|
7774
|
+
if (step === "approving" || step === "signing-approval") return 1;
|
|
7740
7775
|
return 2;
|
|
7741
7776
|
}
|
|
7777
|
+
var EVM_CHAIN_IDS3 = {
|
|
7778
|
+
ethereum: 1,
|
|
7779
|
+
base: 8453,
|
|
7780
|
+
arbitrum: 42161
|
|
7781
|
+
};
|
|
7742
7782
|
function TopUpModal({ isOpen, onClose }) {
|
|
7743
7783
|
const { address, signTypedData, switchChain, walletChainId } = useEmbeddableWallet();
|
|
7744
|
-
const { chainId
|
|
7745
|
-
const {
|
|
7784
|
+
const { chainId } = useChain();
|
|
7785
|
+
const { isDeployed } = useCreditAccount();
|
|
7746
7786
|
const queryClient = reactQuery.useQueryClient();
|
|
7747
7787
|
const prices = useTokenPrices();
|
|
7748
7788
|
const token = "USDC";
|
|
@@ -7760,13 +7800,14 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
7760
7800
|
react.useEffect(() => {
|
|
7761
7801
|
return () => clearPolling();
|
|
7762
7802
|
}, [clearPolling]);
|
|
7803
|
+
const CHAIN_ID = chainId;
|
|
7763
7804
|
const { data: walletBalance } = reactQuery.useQuery({
|
|
7764
|
-
queryKey: ["walletTokenBalance",
|
|
7805
|
+
queryKey: ["walletTokenBalance", CHAIN_ID, address, token],
|
|
7765
7806
|
queryFn: async () => {
|
|
7766
7807
|
if (!address) return "0";
|
|
7767
7808
|
try {
|
|
7768
7809
|
const res = await fetch(
|
|
7769
|
-
`/api/compass/token/balance?address=${address}&chain=${
|
|
7810
|
+
`/api/compass/token/balance?address=${address}&chain=${CHAIN_ID}&token=${token}`
|
|
7770
7811
|
);
|
|
7771
7812
|
if (!res.ok) return "0";
|
|
7772
7813
|
const data = await res.json();
|
|
@@ -7792,142 +7833,175 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
7792
7833
|
setTxState({ status: "idle" });
|
|
7793
7834
|
};
|
|
7794
7835
|
const isValid = Number(amount) > 0 && !!address && isDeployed;
|
|
7795
|
-
const isBusy = step === "
|
|
7836
|
+
const isBusy = step === "approving" || step === "signing-approval" || step === "preparing-transfer" || step === "signing-transfer" || step === "executing";
|
|
7837
|
+
const ensureCorrectChain = react.useCallback(async () => {
|
|
7838
|
+
const targetChainId = EVM_CHAIN_IDS3[CHAIN_ID];
|
|
7839
|
+
if (!targetChainId) return;
|
|
7840
|
+
if (walletChainId !== void 0 && walletChainId !== targetChainId) {
|
|
7841
|
+
if (!switchChain) {
|
|
7842
|
+
throw new Error(`Please switch your wallet to ${CHAIN_ID} (chain ${targetChainId})`);
|
|
7843
|
+
}
|
|
7844
|
+
await switchChain(targetChainId);
|
|
7845
|
+
}
|
|
7846
|
+
}, [walletChainId, switchChain, CHAIN_ID]);
|
|
7796
7847
|
const handleTransfer = async () => {
|
|
7797
|
-
if (!isValid) return;
|
|
7848
|
+
if (!isValid || !signTypedData) return;
|
|
7849
|
+
setTxState({ status: "idle" });
|
|
7798
7850
|
try {
|
|
7799
|
-
|
|
7800
|
-
await switchChain(chain.viemChain.id);
|
|
7801
|
-
}
|
|
7851
|
+
await ensureCorrectChain();
|
|
7802
7852
|
if (action === "deposit") {
|
|
7803
|
-
setStep("
|
|
7853
|
+
setStep("approving");
|
|
7804
7854
|
setTxState({ status: "preparing" });
|
|
7805
|
-
const
|
|
7855
|
+
const approveResponse = await fetch("/api/compass/transfer/approve", {
|
|
7806
7856
|
method: "POST",
|
|
7807
7857
|
headers: { "Content-Type": "application/json" },
|
|
7808
7858
|
body: JSON.stringify({
|
|
7809
7859
|
owner: address,
|
|
7810
|
-
chain:
|
|
7811
|
-
token
|
|
7812
|
-
amount: Number(amount)
|
|
7860
|
+
chain: CHAIN_ID,
|
|
7861
|
+
token
|
|
7813
7862
|
})
|
|
7814
7863
|
});
|
|
7815
|
-
if (!
|
|
7816
|
-
const
|
|
7817
|
-
throw new Error(
|
|
7864
|
+
if (!approveResponse.ok) {
|
|
7865
|
+
const errData = await approveResponse.json();
|
|
7866
|
+
throw new Error(errData.error || "Failed to check approval");
|
|
7818
7867
|
}
|
|
7819
|
-
const
|
|
7820
|
-
|
|
7821
|
-
|
|
7822
|
-
|
|
7823
|
-
|
|
7824
|
-
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7868
|
+
const approvalData = await approveResponse.json();
|
|
7869
|
+
if (!approvalData.approved) {
|
|
7870
|
+
if (approvalData.requiresTransaction && approvalData.transaction) {
|
|
7871
|
+
setTxState({ status: "broadcasting" });
|
|
7872
|
+
const executeApprovalResponse = await fetch("/api/compass/approval/execute", {
|
|
7873
|
+
method: "POST",
|
|
7874
|
+
headers: { "Content-Type": "application/json" },
|
|
7875
|
+
body: JSON.stringify({
|
|
7876
|
+
owner: address,
|
|
7877
|
+
chain: CHAIN_ID,
|
|
7878
|
+
transaction: approvalData.transaction
|
|
7879
|
+
})
|
|
7880
|
+
});
|
|
7881
|
+
if (!executeApprovalResponse.ok) {
|
|
7882
|
+
const errData = await executeApprovalResponse.json();
|
|
7883
|
+
throw new Error(errData.error || "Approval transaction failed");
|
|
7884
|
+
}
|
|
7885
|
+
} else if (approvalData.eip712) {
|
|
7886
|
+
setStep("signing-approval");
|
|
7887
|
+
setTxState({ status: "signing" });
|
|
7888
|
+
const approvalSignature = await signTypedData({
|
|
7889
|
+
domain: approvalData.domain,
|
|
7890
|
+
types: approvalData.normalizedTypes,
|
|
7891
|
+
primaryType: "Permit",
|
|
7892
|
+
message: approvalData.message
|
|
7893
|
+
});
|
|
7894
|
+
setTxState({ status: "broadcasting" });
|
|
7895
|
+
const executeApprovalResponse = await fetch("/api/compass/transfer/execute", {
|
|
7896
|
+
method: "POST",
|
|
7897
|
+
headers: { "Content-Type": "application/json" },
|
|
7898
|
+
body: JSON.stringify({
|
|
7899
|
+
owner: address,
|
|
7900
|
+
chain: CHAIN_ID,
|
|
7901
|
+
eip712: approvalData.eip712,
|
|
7902
|
+
signature: approvalSignature
|
|
7903
|
+
})
|
|
7904
|
+
});
|
|
7905
|
+
if (!executeApprovalResponse.ok) {
|
|
7906
|
+
const errData = await executeApprovalResponse.json();
|
|
7907
|
+
throw new Error(errData.error || "Approval failed");
|
|
7908
|
+
}
|
|
7909
|
+
} else {
|
|
7910
|
+
throw new Error("Unable to approve token for transfers");
|
|
7911
|
+
}
|
|
7912
|
+
}
|
|
7913
|
+
setStep("preparing-transfer");
|
|
7833
7914
|
setTxState({ status: "preparing" });
|
|
7834
|
-
const
|
|
7915
|
+
const prepareResponse = await fetch("/api/compass/transfer/prepare", {
|
|
7835
7916
|
method: "POST",
|
|
7836
7917
|
headers: { "Content-Type": "application/json" },
|
|
7837
7918
|
body: JSON.stringify({
|
|
7838
7919
|
owner: address,
|
|
7839
|
-
chain:
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
amount: Number(amount),
|
|
7845
|
-
permit2Signature,
|
|
7846
|
-
permit2Nonce: permit2Eip712.message.nonce,
|
|
7847
|
-
permit2Deadline: permit2Eip712.message.deadline
|
|
7848
|
-
}
|
|
7849
|
-
]
|
|
7920
|
+
chain: CHAIN_ID,
|
|
7921
|
+
token,
|
|
7922
|
+
amount,
|
|
7923
|
+
action: "DEPOSIT",
|
|
7924
|
+
product: "credit"
|
|
7850
7925
|
})
|
|
7851
7926
|
});
|
|
7852
|
-
if (!
|
|
7853
|
-
const
|
|
7854
|
-
throw new Error(
|
|
7927
|
+
if (!prepareResponse.ok) {
|
|
7928
|
+
const errData = await prepareResponse.json();
|
|
7929
|
+
throw new Error(errData.error || "Failed to prepare transfer");
|
|
7855
7930
|
}
|
|
7856
|
-
const
|
|
7857
|
-
setStep("signing-
|
|
7931
|
+
const prepareData = await prepareResponse.json();
|
|
7932
|
+
setStep("signing-transfer");
|
|
7858
7933
|
setTxState({ status: "signing" });
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7934
|
+
await ensureCorrectChain();
|
|
7935
|
+
const signature = await signTypedData({
|
|
7936
|
+
domain: prepareData.domain,
|
|
7937
|
+
types: prepareData.normalizedTypes,
|
|
7938
|
+
primaryType: prepareData.primaryType,
|
|
7939
|
+
message: prepareData.message
|
|
7864
7940
|
});
|
|
7865
|
-
setStep("
|
|
7941
|
+
setStep("executing");
|
|
7866
7942
|
setTxState({ status: "broadcasting" });
|
|
7867
|
-
const executeResponse = await fetch("/api/compass/
|
|
7943
|
+
const executeResponse = await fetch("/api/compass/transfer/execute", {
|
|
7868
7944
|
method: "POST",
|
|
7869
7945
|
headers: { "Content-Type": "application/json" },
|
|
7870
7946
|
body: JSON.stringify({
|
|
7871
7947
|
owner: address,
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
|
|
7875
|
-
|
|
7948
|
+
chain: CHAIN_ID,
|
|
7949
|
+
eip712: prepareData.eip712,
|
|
7950
|
+
signature,
|
|
7951
|
+
product: "credit"
|
|
7876
7952
|
})
|
|
7877
7953
|
});
|
|
7878
7954
|
if (!executeResponse.ok) {
|
|
7879
|
-
const
|
|
7880
|
-
throw new Error(
|
|
7955
|
+
const errData = await executeResponse.json();
|
|
7956
|
+
throw new Error(errData.error || "Transfer failed");
|
|
7881
7957
|
}
|
|
7882
7958
|
const { txHash } = await executeResponse.json();
|
|
7883
7959
|
handleSuccess(txHash);
|
|
7884
7960
|
} else {
|
|
7885
|
-
setStep("preparing-
|
|
7961
|
+
setStep("preparing-transfer");
|
|
7886
7962
|
setTxState({ status: "preparing" });
|
|
7887
|
-
const
|
|
7963
|
+
const prepareResponse = await fetch("/api/compass/transfer/prepare", {
|
|
7888
7964
|
method: "POST",
|
|
7889
7965
|
headers: { "Content-Type": "application/json" },
|
|
7890
7966
|
body: JSON.stringify({
|
|
7891
7967
|
owner: address,
|
|
7892
|
-
chain:
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
|
|
7896
|
-
|
|
7897
|
-
amount: Number(amount)
|
|
7898
|
-
}
|
|
7899
|
-
]
|
|
7968
|
+
chain: CHAIN_ID,
|
|
7969
|
+
token,
|
|
7970
|
+
amount,
|
|
7971
|
+
action: "WITHDRAW",
|
|
7972
|
+
product: "credit"
|
|
7900
7973
|
})
|
|
7901
7974
|
});
|
|
7902
|
-
if (!
|
|
7903
|
-
const
|
|
7904
|
-
throw new Error(
|
|
7975
|
+
if (!prepareResponse.ok) {
|
|
7976
|
+
const errData = await prepareResponse.json();
|
|
7977
|
+
throw new Error(errData.error || "Failed to prepare withdrawal");
|
|
7905
7978
|
}
|
|
7906
|
-
const
|
|
7907
|
-
setStep("signing-
|
|
7979
|
+
const prepareData = await prepareResponse.json();
|
|
7980
|
+
setStep("signing-transfer");
|
|
7908
7981
|
setTxState({ status: "signing" });
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
7982
|
+
await ensureCorrectChain();
|
|
7983
|
+
const signature = await signTypedData({
|
|
7984
|
+
domain: prepareData.domain,
|
|
7985
|
+
types: prepareData.normalizedTypes,
|
|
7986
|
+
primaryType: prepareData.primaryType,
|
|
7987
|
+
message: prepareData.message
|
|
7914
7988
|
});
|
|
7915
|
-
setStep("
|
|
7989
|
+
setStep("executing");
|
|
7916
7990
|
setTxState({ status: "broadcasting" });
|
|
7917
|
-
const executeResponse = await fetch("/api/compass/
|
|
7991
|
+
const executeResponse = await fetch("/api/compass/transfer/execute", {
|
|
7918
7992
|
method: "POST",
|
|
7919
7993
|
headers: { "Content-Type": "application/json" },
|
|
7920
7994
|
body: JSON.stringify({
|
|
7921
7995
|
owner: address,
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
|
|
7996
|
+
chain: CHAIN_ID,
|
|
7997
|
+
eip712: prepareData.eip712,
|
|
7998
|
+
signature,
|
|
7999
|
+
product: "credit"
|
|
7926
8000
|
})
|
|
7927
8001
|
});
|
|
7928
8002
|
if (!executeResponse.ok) {
|
|
7929
|
-
const
|
|
7930
|
-
throw new Error(
|
|
8003
|
+
const errData = await executeResponse.json();
|
|
8004
|
+
throw new Error(errData.error || "Withdrawal failed");
|
|
7931
8005
|
}
|
|
7932
8006
|
const { txHash } = await executeResponse.json();
|
|
7933
8007
|
handleSuccess(txHash);
|
|
@@ -7950,8 +8024,9 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
7950
8024
|
polls++;
|
|
7951
8025
|
queryClient.invalidateQueries({ queryKey: ["creditBalances"] });
|
|
7952
8026
|
queryClient.invalidateQueries({ queryKey: ["creditPositions"] });
|
|
8027
|
+
queryClient.invalidateQueries({ queryKey: ["walletTokenBalance"] });
|
|
7953
8028
|
try {
|
|
7954
|
-
const res = await fetch(`/api/compass/tx/receipt?hash=${txHash}&chain=${
|
|
8029
|
+
const res = await fetch(`/api/compass/tx/receipt?hash=${txHash}&chain=${CHAIN_ID}`);
|
|
7955
8030
|
const data = await res.json();
|
|
7956
8031
|
if (data.status === "success") {
|
|
7957
8032
|
clearPolling();
|
|
@@ -7966,23 +8041,23 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
7966
8041
|
}
|
|
7967
8042
|
if (polls >= 24) {
|
|
7968
8043
|
clearPolling();
|
|
7969
|
-
setTxState({ status: "
|
|
8044
|
+
setTxState({ status: "failed", error: "Unable to confirm transaction. Please check your wallet for status." });
|
|
7970
8045
|
}
|
|
7971
8046
|
}, 5e3);
|
|
7972
8047
|
};
|
|
7973
8048
|
const phase = getPhase2(step);
|
|
7974
8049
|
const buttonLabel = () => {
|
|
7975
8050
|
switch (step) {
|
|
7976
|
-
case "
|
|
7977
|
-
return "
|
|
7978
|
-
case "signing-
|
|
8051
|
+
case "approving":
|
|
8052
|
+
return "Checking approval...";
|
|
8053
|
+
case "signing-approval":
|
|
7979
8054
|
return "Sign Approval (1/2)...";
|
|
7980
|
-
case "preparing-
|
|
8055
|
+
case "preparing-transfer":
|
|
7981
8056
|
return action === "deposit" ? "Preparing transfer..." : "Preparing withdrawal...";
|
|
7982
|
-
case "signing-
|
|
8057
|
+
case "signing-transfer":
|
|
7983
8058
|
return action === "deposit" ? "Sign Transfer (2/2)..." : "Sign Withdrawal...";
|
|
7984
|
-
case "
|
|
7985
|
-
return "
|
|
8059
|
+
case "executing":
|
|
8060
|
+
return "Executing...";
|
|
7986
8061
|
default:
|
|
7987
8062
|
return null;
|
|
7988
8063
|
}
|
|
@@ -8065,7 +8140,10 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
8065
8140
|
{
|
|
8066
8141
|
type: "number",
|
|
8067
8142
|
value: amount,
|
|
8068
|
-
onChange: (e) =>
|
|
8143
|
+
onChange: (e) => {
|
|
8144
|
+
setAmount(e.target.value);
|
|
8145
|
+
setTxState({ status: "idle" });
|
|
8146
|
+
},
|
|
8069
8147
|
disabled: isBusy,
|
|
8070
8148
|
placeholder: "0.00",
|
|
8071
8149
|
className: "w-full border px-3 py-2.5 pr-14 text-sm focus:outline-none disabled:opacity-50",
|
|
@@ -8107,7 +8185,7 @@ function TopUpModal({ isOpen, onClose }) {
|
|
|
8107
8185
|
}
|
|
8108
8186
|
)
|
|
8109
8187
|
] }),
|
|
8110
|
-
!isBusy && step !== "confirmed" && step !== "failed" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8188
|
+
!isBusy && step !== "confirmed" && step !== "failed" && txState.status === "idle" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8111
8189
|
"p",
|
|
8112
8190
|
{
|
|
8113
8191
|
className: "text-xs",
|
|
@@ -8396,7 +8474,7 @@ function CreditSwapModal({ isOpen, onClose }) {
|
|
|
8396
8474
|
},
|
|
8397
8475
|
children: isBusy ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8398
8476
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 16, className: "animate-spin" }),
|
|
8399
|
-
txState.status === "preparing" ? "Preparing..." : txState.status === "signing" ? "
|
|
8477
|
+
txState.status === "preparing" ? "Preparing..." : txState.status === "signing" ? "Signing Swap..." : "Broadcasting..."
|
|
8400
8478
|
] }) : "Swap"
|
|
8401
8479
|
}
|
|
8402
8480
|
),
|
|
@@ -8450,8 +8528,28 @@ function CreditAccount({
|
|
|
8450
8528
|
const price = tokenPrices[b.tokenSymbol];
|
|
8451
8529
|
const usdValue = amount > 0 && price != null ? amount * price : 0;
|
|
8452
8530
|
return { ...b, usdValue };
|
|
8453
|
-
}).filter((b) => b.usdValue >= 0.01);
|
|
8531
|
+
}).filter((b) => b.usdValue >= 0.01).sort((a, b) => a.tokenSymbol.localeCompare(b.tokenSymbol));
|
|
8454
8532
|
const totalIdleUsd = balancesWithUsd.reduce((sum, b) => sum + b.usdValue, 0);
|
|
8533
|
+
const totalInterestEarnedUsd = (() => {
|
|
8534
|
+
if (!positions) return 0;
|
|
8535
|
+
let total = 0;
|
|
8536
|
+
for (const pos of positions.collateralPositions) {
|
|
8537
|
+
const interest = parseFloat(pos.interestEarned ?? "0");
|
|
8538
|
+
const price = tokenPrices[pos.symbol] ?? 0;
|
|
8539
|
+
if (interest > 0 && price > 0) total += interest * price;
|
|
8540
|
+
}
|
|
8541
|
+
return total;
|
|
8542
|
+
})();
|
|
8543
|
+
const totalInterestPaidUsd = (() => {
|
|
8544
|
+
if (!positions) return 0;
|
|
8545
|
+
let total = 0;
|
|
8546
|
+
for (const pos of positions.debtPositions) {
|
|
8547
|
+
const interest = parseFloat(pos.interestPaid ?? "0");
|
|
8548
|
+
const price = tokenPrices[pos.symbol] ?? 0;
|
|
8549
|
+
if (interest > 0 && price > 0) total += interest * price;
|
|
8550
|
+
}
|
|
8551
|
+
return total;
|
|
8552
|
+
})();
|
|
8455
8553
|
const netPositionUsd = totalCollateral - totalDebt;
|
|
8456
8554
|
const totalBalance = netPositionUsd + totalIdleUsd;
|
|
8457
8555
|
const netInterestUsdPerYear = (() => {
|
|
@@ -8688,15 +8786,28 @@ function CreditAccount({
|
|
|
8688
8786
|
/* @__PURE__ */ jsxRuntime.jsx(CopyableAddress, { address: creditAccountAddress, label: "Credit Account" })
|
|
8689
8787
|
] }),
|
|
8690
8788
|
positions && positions.collateralPositions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
8691
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
8698
|
-
|
|
8699
|
-
|
|
8789
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8790
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8791
|
+
"span",
|
|
8792
|
+
{
|
|
8793
|
+
className: "text-xs font-medium uppercase tracking-wide",
|
|
8794
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
8795
|
+
children: "Collateral"
|
|
8796
|
+
}
|
|
8797
|
+
),
|
|
8798
|
+
totalInterestEarnedUsd > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8799
|
+
"span",
|
|
8800
|
+
{
|
|
8801
|
+
className: "text-xs font-medium",
|
|
8802
|
+
style: { color: "var(--compass-color-success)" },
|
|
8803
|
+
children: [
|
|
8804
|
+
"Interest: +",
|
|
8805
|
+
formatUsd2(totalInterestEarnedUsd)
|
|
8806
|
+
]
|
|
8807
|
+
}
|
|
8808
|
+
)
|
|
8809
|
+
] }),
|
|
8810
|
+
[...positions.collateralPositions].filter((p) => parseFloat(p.usdValue ?? "0") >= 0.01).sort((a, b) => a.symbol.localeCompare(b.symbol)).map((p) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8700
8811
|
"div",
|
|
8701
8812
|
{
|
|
8702
8813
|
className: "flex items-center justify-between p-3 rounded-lg",
|
|
@@ -8719,15 +8830,28 @@ function CreditAccount({
|
|
|
8719
8830
|
))
|
|
8720
8831
|
] }),
|
|
8721
8832
|
positions && positions.debtPositions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
8722
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8723
|
-
|
|
8724
|
-
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8833
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8834
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8835
|
+
"span",
|
|
8836
|
+
{
|
|
8837
|
+
className: "text-xs font-medium uppercase tracking-wide",
|
|
8838
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
8839
|
+
children: "Debt"
|
|
8840
|
+
}
|
|
8841
|
+
),
|
|
8842
|
+
totalInterestPaidUsd > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8843
|
+
"span",
|
|
8844
|
+
{
|
|
8845
|
+
className: "text-xs font-medium",
|
|
8846
|
+
style: { color: "var(--compass-color-error, #ef4444)" },
|
|
8847
|
+
children: [
|
|
8848
|
+
"Interest: -",
|
|
8849
|
+
formatUsd2(totalInterestPaidUsd)
|
|
8850
|
+
]
|
|
8851
|
+
}
|
|
8852
|
+
)
|
|
8853
|
+
] }),
|
|
8854
|
+
[...positions.debtPositions].filter((p) => parseFloat(p.usdValue ?? "0") >= 0.01).sort((a, b) => a.symbol.localeCompare(b.symbol)).map((p) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8731
8855
|
"div",
|
|
8732
8856
|
{
|
|
8733
8857
|
className: "flex items-center justify-between p-3 rounded-lg",
|
|
@@ -8736,19 +8860,13 @@ function CreditAccount({
|
|
|
8736
8860
|
border: "1px solid var(--compass-color-border)"
|
|
8737
8861
|
},
|
|
8738
8862
|
children: [
|
|
8739
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", style: { color: "var(--compass-color-
|
|
8863
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", style: { color: "var(--compass-color-text)" }, children: p.symbol }),
|
|
8740
8864
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end", children: [
|
|
8741
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8742
|
-
|
|
8743
|
-
|
|
8744
|
-
|
|
8745
|
-
|
|
8746
|
-
})
|
|
8747
|
-
] }),
|
|
8748
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: [
|
|
8749
|
-
"-$",
|
|
8750
|
-
parseFloat(p.usdValue ?? "0").toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
|
8751
|
-
] })
|
|
8865
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-text)" }, children: parseFloat(p.amountBorrowed ?? "0").toLocaleString(void 0, {
|
|
8866
|
+
minimumFractionDigits: 2,
|
|
8867
|
+
maximumFractionDigits: 4
|
|
8868
|
+
}) }),
|
|
8869
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: formatUsd2(p.usdValue) })
|
|
8752
8870
|
] })
|
|
8753
8871
|
]
|
|
8754
8872
|
},
|
|
@@ -8756,14 +8874,24 @@ function CreditAccount({
|
|
|
8756
8874
|
))
|
|
8757
8875
|
] }),
|
|
8758
8876
|
balancesWithUsd.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
8759
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8760
|
-
|
|
8761
|
-
|
|
8762
|
-
|
|
8763
|
-
|
|
8764
|
-
|
|
8765
|
-
|
|
8766
|
-
|
|
8877
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8878
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8879
|
+
"span",
|
|
8880
|
+
{
|
|
8881
|
+
className: "text-xs font-medium uppercase tracking-wide",
|
|
8882
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
8883
|
+
children: "Available in Account"
|
|
8884
|
+
}
|
|
8885
|
+
),
|
|
8886
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8887
|
+
"span",
|
|
8888
|
+
{
|
|
8889
|
+
className: "text-sm font-semibold",
|
|
8890
|
+
style: { color: "var(--compass-color-text)" },
|
|
8891
|
+
children: formatUsd2(totalIdleUsd)
|
|
8892
|
+
}
|
|
8893
|
+
)
|
|
8894
|
+
] }),
|
|
8767
8895
|
balancesWithUsd.map((b) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8768
8896
|
"div",
|
|
8769
8897
|
{
|
|
@@ -10686,7 +10814,7 @@ function AllocationEditor({
|
|
|
10686
10814
|
) })
|
|
10687
10815
|
] });
|
|
10688
10816
|
}
|
|
10689
|
-
var
|
|
10817
|
+
var EVM_CHAIN_IDS4 = {
|
|
10690
10818
|
ethereum: 1,
|
|
10691
10819
|
base: 8453,
|
|
10692
10820
|
arbitrum: 42161
|
|
@@ -10865,7 +10993,7 @@ function RebalancingWidget({
|
|
|
10865
10993
|
setTargets((prev) => prev.map((t, i) => i === index ? { ...t, targetPercent: rounded } : t));
|
|
10866
10994
|
}, []);
|
|
10867
10995
|
const ensureCorrectChain = react.useCallback(async () => {
|
|
10868
|
-
const targetChainId =
|
|
10996
|
+
const targetChainId = EVM_CHAIN_IDS4[CHAIN_ID];
|
|
10869
10997
|
if (!targetChainId) return;
|
|
10870
10998
|
if (walletChainId !== void 0 && walletChainId !== targetChainId) {
|
|
10871
10999
|
if (!switchChain) {
|