@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 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: debtPositions.length > 0 ? "var(--compass-color-error)" : "var(--compass-color-text)" },
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-error)" }, children: formatApy(position.borrowApy) })
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-error)" }, children: [
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" ? "Sign SafeTx..." : "Broadcasting..."
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" ? "Sign SafeTx..." : "Broadcasting..."
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" ? "Sign SafeTx..." : "Broadcasting..."
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.jsx("label", { className: "block text-sm mb-1.5", style: labelStyle, children: "Amount" }),
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
- formatUsdEstimate(amount, token, prices) && /* @__PURE__ */ jsxRuntime.jsxs(
7699
- "p",
7700
- {
7701
- className: "text-xs mt-1",
7702
- style: { color: "var(--compass-color-text-tertiary)" },
7703
- children: [
7704
- "\u2248",
7705
- " ",
7706
- formatUsdEstimate(amount, token, prices)
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" ? "Sign SafeTx..." : "Broadcasting..."
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 === "preparing-permit" || step === "signing-permit") return 1;
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, chain } = useChain();
7745
- const { creditAccountAddress, isDeployed } = useCreditAccount();
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", chainId, address, token],
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=${chainId}&token=${token}`
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 === "preparing-permit" || step === "signing-permit" || step === "preparing-bundle" || step === "signing-bundle" || step === "broadcasting";
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
- if (switchChain && walletChainId !== chain.viemChain.id) {
7800
- await switchChain(chain.viemChain.id);
7801
- }
7851
+ await ensureCorrectChain();
7802
7852
  if (action === "deposit") {
7803
- setStep("preparing-permit");
7853
+ setStep("approving");
7804
7854
  setTxState({ status: "preparing" });
7805
- const transferResponse = await fetch("/api/compass/credit/transfer", {
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: chainId,
7811
- token,
7812
- amount: Number(amount)
7860
+ chain: CHAIN_ID,
7861
+ token
7813
7862
  })
7814
7863
  });
7815
- if (!transferResponse.ok) {
7816
- const errorData = await transferResponse.json();
7817
- throw new Error(errorData.error || "Failed to prepare permit");
7864
+ if (!approveResponse.ok) {
7865
+ const errData = await approveResponse.json();
7866
+ throw new Error(errData.error || "Failed to check approval");
7818
7867
  }
7819
- const transferData = await transferResponse.json();
7820
- const permit2Eip712 = transferData.eip712;
7821
- setStep("signing-permit");
7822
- setTxState({ status: "signing" });
7823
- const permit2Signature = await signTypedData({
7824
- domain: permit2Eip712.domain,
7825
- types: {
7826
- PermitTransferFrom: transferData.normalizedTypes.PermitTransferFrom,
7827
- TokenPermissions: transferData.normalizedTypes.TokenPermissions
7828
- },
7829
- primaryType: "PermitTransferFrom",
7830
- message: permit2Eip712.message
7831
- });
7832
- setStep("preparing-bundle");
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 bundlePrepareResponse = await fetch("/api/compass/credit/bundle/prepare", {
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: chainId,
7840
- actions: [
7841
- {
7842
- actionType: "V2_TRANSFER_FROM_EOA",
7843
- token,
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 (!bundlePrepareResponse.ok) {
7853
- const errorData = await bundlePrepareResponse.json();
7854
- throw new Error(errorData.error || "Failed to prepare bundle");
7927
+ if (!prepareResponse.ok) {
7928
+ const errData = await prepareResponse.json();
7929
+ throw new Error(errData.error || "Failed to prepare transfer");
7855
7930
  }
7856
- const { eip712, normalizedTypes, domain, message } = await bundlePrepareResponse.json();
7857
- setStep("signing-bundle");
7931
+ const prepareData = await prepareResponse.json();
7932
+ setStep("signing-transfer");
7858
7933
  setTxState({ status: "signing" });
7859
- const safeTxSignature = await signTypedData({
7860
- domain,
7861
- types: normalizedTypes,
7862
- primaryType: "SafeTx",
7863
- message
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("broadcasting");
7941
+ setStep("executing");
7866
7942
  setTxState({ status: "broadcasting" });
7867
- const executeResponse = await fetch("/api/compass/credit/bundle/execute", {
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
- eip712,
7873
- signature: safeTxSignature,
7874
- chain: chainId,
7875
- creditAccountAddress
7948
+ chain: CHAIN_ID,
7949
+ eip712: prepareData.eip712,
7950
+ signature,
7951
+ product: "credit"
7876
7952
  })
7877
7953
  });
7878
7954
  if (!executeResponse.ok) {
7879
- const errorData = await executeResponse.json();
7880
- throw new Error(errorData.error || "Failed to execute");
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-bundle");
7961
+ setStep("preparing-transfer");
7886
7962
  setTxState({ status: "preparing" });
7887
- const bundlePrepareResponse = await fetch("/api/compass/credit/bundle/prepare", {
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: chainId,
7893
- actions: [
7894
- {
7895
- actionType: "V2_TRANSFER_TO_EOA",
7896
- token,
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 (!bundlePrepareResponse.ok) {
7903
- const errorData = await bundlePrepareResponse.json();
7904
- throw new Error(errorData.error || "Failed to prepare withdrawal");
7975
+ if (!prepareResponse.ok) {
7976
+ const errData = await prepareResponse.json();
7977
+ throw new Error(errData.error || "Failed to prepare withdrawal");
7905
7978
  }
7906
- const { eip712, normalizedTypes, domain, message } = await bundlePrepareResponse.json();
7907
- setStep("signing-bundle");
7979
+ const prepareData = await prepareResponse.json();
7980
+ setStep("signing-transfer");
7908
7981
  setTxState({ status: "signing" });
7909
- const safeTxSignature = await signTypedData({
7910
- domain,
7911
- types: normalizedTypes,
7912
- primaryType: "SafeTx",
7913
- message
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("broadcasting");
7989
+ setStep("executing");
7916
7990
  setTxState({ status: "broadcasting" });
7917
- const executeResponse = await fetch("/api/compass/credit/bundle/execute", {
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
- eip712,
7923
- signature: safeTxSignature,
7924
- chain: chainId,
7925
- creditAccountAddress
7996
+ chain: CHAIN_ID,
7997
+ eip712: prepareData.eip712,
7998
+ signature,
7999
+ product: "credit"
7926
8000
  })
7927
8001
  });
7928
8002
  if (!executeResponse.ok) {
7929
- const errorData = await executeResponse.json();
7930
- throw new Error(errorData.error || "Failed to execute withdrawal");
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=${chainId}`);
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: "confirmed", txHash });
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 "preparing-permit":
7977
- return "Preparing approval...";
7978
- case "signing-permit":
8051
+ case "approving":
8052
+ return "Checking approval...";
8053
+ case "signing-approval":
7979
8054
  return "Sign Approval (1/2)...";
7980
- case "preparing-bundle":
8055
+ case "preparing-transfer":
7981
8056
  return action === "deposit" ? "Preparing transfer..." : "Preparing withdrawal...";
7982
- case "signing-bundle":
8057
+ case "signing-transfer":
7983
8058
  return action === "deposit" ? "Sign Transfer (2/2)..." : "Sign Withdrawal...";
7984
- case "broadcasting":
7985
- return "Broadcasting...";
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) => setAmount(e.target.value),
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" ? "Sign SafeTx..." : "Broadcasting..."
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.jsx(
8692
- "span",
8693
- {
8694
- className: "text-xs font-medium uppercase tracking-wide",
8695
- style: { color: "var(--compass-color-text-tertiary)" },
8696
- children: "Collateral"
8697
- }
8698
- ),
8699
- positions.collateralPositions.filter((p) => parseFloat(p.usdValue ?? "0") >= 0.01).map((p) => /* @__PURE__ */ jsxRuntime.jsxs(
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.jsx(
8723
- "span",
8724
- {
8725
- className: "text-xs font-medium uppercase tracking-wide",
8726
- style: { color: "var(--compass-color-text-tertiary)" },
8727
- children: "Debt"
8728
- }
8729
- ),
8730
- positions.debtPositions.filter((p) => parseFloat(p.usdValue ?? "0") >= 0.01).map((p) => /* @__PURE__ */ jsxRuntime.jsxs(
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-error, #ef4444)" }, children: p.symbol }),
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.jsxs("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-error, #ef4444)" }, children: [
8742
- "-",
8743
- parseFloat(p.amountBorrowed ?? "0").toLocaleString(void 0, {
8744
- minimumFractionDigits: 2,
8745
- maximumFractionDigits: 4
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.jsx(
8760
- "span",
8761
- {
8762
- className: "text-xs font-medium uppercase tracking-wide",
8763
- style: { color: "var(--compass-color-text-tertiary)" },
8764
- children: "Available in Account"
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 EVM_CHAIN_IDS3 = {
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 = EVM_CHAIN_IDS3[CHAIN_ID];
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) {