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