@compass-labs/widgets 0.1.36 → 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.mjs CHANGED
@@ -7769,13 +7769,18 @@ function WithdrawModal({ isOpen, onClose, initialToken, allowedTokens }) {
7769
7769
  }
7770
7770
  function getPhase2(step) {
7771
7771
  if (step === "idle" || step === "failed") return 0;
7772
- if (step === "preparing-permit" || step === "signing-permit") return 1;
7772
+ if (step === "approving" || step === "signing-approval") return 1;
7773
7773
  return 2;
7774
7774
  }
7775
+ var EVM_CHAIN_IDS3 = {
7776
+ ethereum: 1,
7777
+ base: 8453,
7778
+ arbitrum: 42161
7779
+ };
7775
7780
  function TopUpModal({ isOpen, onClose }) {
7776
7781
  const { address, signTypedData, switchChain, walletChainId } = useEmbeddableWallet();
7777
- const { chainId, chain } = useChain();
7778
- const { creditAccountAddress, isDeployed } = useCreditAccount();
7782
+ const { chainId } = useChain();
7783
+ const { isDeployed } = useCreditAccount();
7779
7784
  const queryClient = useQueryClient();
7780
7785
  const prices = useTokenPrices();
7781
7786
  const token = "USDC";
@@ -7793,13 +7798,14 @@ function TopUpModal({ isOpen, onClose }) {
7793
7798
  useEffect(() => {
7794
7799
  return () => clearPolling();
7795
7800
  }, [clearPolling]);
7801
+ const CHAIN_ID = chainId;
7796
7802
  const { data: walletBalance } = useQuery({
7797
- queryKey: ["walletTokenBalance", chainId, address, token],
7803
+ queryKey: ["walletTokenBalance", CHAIN_ID, address, token],
7798
7804
  queryFn: async () => {
7799
7805
  if (!address) return "0";
7800
7806
  try {
7801
7807
  const res = await fetch(
7802
- `/api/compass/token/balance?address=${address}&chain=${chainId}&token=${token}`
7808
+ `/api/compass/token/balance?address=${address}&chain=${CHAIN_ID}&token=${token}`
7803
7809
  );
7804
7810
  if (!res.ok) return "0";
7805
7811
  const data = await res.json();
@@ -7825,142 +7831,175 @@ function TopUpModal({ isOpen, onClose }) {
7825
7831
  setTxState({ status: "idle" });
7826
7832
  };
7827
7833
  const isValid = Number(amount) > 0 && !!address && isDeployed;
7828
- const isBusy = step === "preparing-permit" || step === "signing-permit" || step === "preparing-bundle" || step === "signing-bundle" || step === "broadcasting";
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]);
7829
7845
  const handleTransfer = async () => {
7830
- if (!isValid) return;
7846
+ if (!isValid || !signTypedData) return;
7847
+ setTxState({ status: "idle" });
7831
7848
  try {
7832
- if (switchChain && walletChainId !== chain.viemChain.id) {
7833
- await switchChain(chain.viemChain.id);
7834
- }
7849
+ await ensureCorrectChain();
7835
7850
  if (action === "deposit") {
7836
- setStep("preparing-permit");
7851
+ setStep("approving");
7837
7852
  setTxState({ status: "preparing" });
7838
- const transferResponse = await fetch("/api/compass/credit/transfer", {
7853
+ const approveResponse = await fetch("/api/compass/transfer/approve", {
7839
7854
  method: "POST",
7840
7855
  headers: { "Content-Type": "application/json" },
7841
7856
  body: JSON.stringify({
7842
7857
  owner: address,
7843
- chain: chainId,
7844
- token,
7845
- amount: Number(amount)
7858
+ chain: CHAIN_ID,
7859
+ token
7846
7860
  })
7847
7861
  });
7848
- if (!transferResponse.ok) {
7849
- const errorData = await transferResponse.json();
7850
- throw new Error(errorData.error || "Failed to prepare permit");
7862
+ if (!approveResponse.ok) {
7863
+ const errData = await approveResponse.json();
7864
+ throw new Error(errData.error || "Failed to check approval");
7851
7865
  }
7852
- const transferData = await transferResponse.json();
7853
- const permit2Eip712 = transferData.eip712;
7854
- setStep("signing-permit");
7855
- setTxState({ status: "signing" });
7856
- const permit2Signature = await signTypedData({
7857
- domain: permit2Eip712.domain,
7858
- types: {
7859
- PermitTransferFrom: transferData.normalizedTypes.PermitTransferFrom,
7860
- TokenPermissions: transferData.normalizedTypes.TokenPermissions
7861
- },
7862
- primaryType: "PermitTransferFrom",
7863
- message: permit2Eip712.message
7864
- });
7865
- setStep("preparing-bundle");
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");
7866
7912
  setTxState({ status: "preparing" });
7867
- const bundlePrepareResponse = await fetch("/api/compass/credit/bundle/prepare", {
7913
+ const prepareResponse = await fetch("/api/compass/transfer/prepare", {
7868
7914
  method: "POST",
7869
7915
  headers: { "Content-Type": "application/json" },
7870
7916
  body: JSON.stringify({
7871
7917
  owner: address,
7872
- chain: chainId,
7873
- actions: [
7874
- {
7875
- actionType: "V2_TRANSFER_FROM_EOA",
7876
- token,
7877
- amount: Number(amount),
7878
- permit2Signature,
7879
- permit2Nonce: permit2Eip712.message.nonce,
7880
- permit2Deadline: permit2Eip712.message.deadline
7881
- }
7882
- ]
7918
+ chain: CHAIN_ID,
7919
+ token,
7920
+ amount,
7921
+ action: "DEPOSIT",
7922
+ product: "credit"
7883
7923
  })
7884
7924
  });
7885
- if (!bundlePrepareResponse.ok) {
7886
- const errorData = await bundlePrepareResponse.json();
7887
- throw new Error(errorData.error || "Failed to prepare bundle");
7925
+ if (!prepareResponse.ok) {
7926
+ const errData = await prepareResponse.json();
7927
+ throw new Error(errData.error || "Failed to prepare transfer");
7888
7928
  }
7889
- const { eip712, normalizedTypes, domain, message } = await bundlePrepareResponse.json();
7890
- setStep("signing-bundle");
7929
+ const prepareData = await prepareResponse.json();
7930
+ setStep("signing-transfer");
7891
7931
  setTxState({ status: "signing" });
7892
- const safeTxSignature = await signTypedData({
7893
- domain,
7894
- types: normalizedTypes,
7895
- primaryType: "SafeTx",
7896
- message
7932
+ await ensureCorrectChain();
7933
+ const signature = await signTypedData({
7934
+ domain: prepareData.domain,
7935
+ types: prepareData.normalizedTypes,
7936
+ primaryType: prepareData.primaryType,
7937
+ message: prepareData.message
7897
7938
  });
7898
- setStep("broadcasting");
7939
+ setStep("executing");
7899
7940
  setTxState({ status: "broadcasting" });
7900
- const executeResponse = await fetch("/api/compass/credit/bundle/execute", {
7941
+ const executeResponse = await fetch("/api/compass/transfer/execute", {
7901
7942
  method: "POST",
7902
7943
  headers: { "Content-Type": "application/json" },
7903
7944
  body: JSON.stringify({
7904
7945
  owner: address,
7905
- eip712,
7906
- signature: safeTxSignature,
7907
- chain: chainId,
7908
- creditAccountAddress
7946
+ chain: CHAIN_ID,
7947
+ eip712: prepareData.eip712,
7948
+ signature,
7949
+ product: "credit"
7909
7950
  })
7910
7951
  });
7911
7952
  if (!executeResponse.ok) {
7912
- const errorData = await executeResponse.json();
7913
- throw new Error(errorData.error || "Failed to execute");
7953
+ const errData = await executeResponse.json();
7954
+ throw new Error(errData.error || "Transfer failed");
7914
7955
  }
7915
7956
  const { txHash } = await executeResponse.json();
7916
7957
  handleSuccess(txHash);
7917
7958
  } else {
7918
- setStep("preparing-bundle");
7959
+ setStep("preparing-transfer");
7919
7960
  setTxState({ status: "preparing" });
7920
- const bundlePrepareResponse = await fetch("/api/compass/credit/bundle/prepare", {
7961
+ const prepareResponse = await fetch("/api/compass/transfer/prepare", {
7921
7962
  method: "POST",
7922
7963
  headers: { "Content-Type": "application/json" },
7923
7964
  body: JSON.stringify({
7924
7965
  owner: address,
7925
- chain: chainId,
7926
- actions: [
7927
- {
7928
- actionType: "V2_TRANSFER_TO_EOA",
7929
- token,
7930
- amount: Number(amount)
7931
- }
7932
- ]
7966
+ chain: CHAIN_ID,
7967
+ token,
7968
+ amount,
7969
+ action: "WITHDRAW",
7970
+ product: "credit"
7933
7971
  })
7934
7972
  });
7935
- if (!bundlePrepareResponse.ok) {
7936
- const errorData = await bundlePrepareResponse.json();
7937
- throw new Error(errorData.error || "Failed to prepare withdrawal");
7973
+ if (!prepareResponse.ok) {
7974
+ const errData = await prepareResponse.json();
7975
+ throw new Error(errData.error || "Failed to prepare withdrawal");
7938
7976
  }
7939
- const { eip712, normalizedTypes, domain, message } = await bundlePrepareResponse.json();
7940
- setStep("signing-bundle");
7977
+ const prepareData = await prepareResponse.json();
7978
+ setStep("signing-transfer");
7941
7979
  setTxState({ status: "signing" });
7942
- const safeTxSignature = await signTypedData({
7943
- domain,
7944
- types: normalizedTypes,
7945
- primaryType: "SafeTx",
7946
- message
7980
+ await ensureCorrectChain();
7981
+ const signature = await signTypedData({
7982
+ domain: prepareData.domain,
7983
+ types: prepareData.normalizedTypes,
7984
+ primaryType: prepareData.primaryType,
7985
+ message: prepareData.message
7947
7986
  });
7948
- setStep("broadcasting");
7987
+ setStep("executing");
7949
7988
  setTxState({ status: "broadcasting" });
7950
- const executeResponse = await fetch("/api/compass/credit/bundle/execute", {
7989
+ const executeResponse = await fetch("/api/compass/transfer/execute", {
7951
7990
  method: "POST",
7952
7991
  headers: { "Content-Type": "application/json" },
7953
7992
  body: JSON.stringify({
7954
7993
  owner: address,
7955
- eip712,
7956
- signature: safeTxSignature,
7957
- chain: chainId,
7958
- creditAccountAddress
7994
+ chain: CHAIN_ID,
7995
+ eip712: prepareData.eip712,
7996
+ signature,
7997
+ product: "credit"
7959
7998
  })
7960
7999
  });
7961
8000
  if (!executeResponse.ok) {
7962
- const errorData = await executeResponse.json();
7963
- throw new Error(errorData.error || "Failed to execute withdrawal");
8001
+ const errData = await executeResponse.json();
8002
+ throw new Error(errData.error || "Withdrawal failed");
7964
8003
  }
7965
8004
  const { txHash } = await executeResponse.json();
7966
8005
  handleSuccess(txHash);
@@ -7983,8 +8022,9 @@ function TopUpModal({ isOpen, onClose }) {
7983
8022
  polls++;
7984
8023
  queryClient.invalidateQueries({ queryKey: ["creditBalances"] });
7985
8024
  queryClient.invalidateQueries({ queryKey: ["creditPositions"] });
8025
+ queryClient.invalidateQueries({ queryKey: ["walletTokenBalance"] });
7986
8026
  try {
7987
- const res = await fetch(`/api/compass/tx/receipt?hash=${txHash}&chain=${chainId}`);
8027
+ const res = await fetch(`/api/compass/tx/receipt?hash=${txHash}&chain=${CHAIN_ID}`);
7988
8028
  const data = await res.json();
7989
8029
  if (data.status === "success") {
7990
8030
  clearPolling();
@@ -7999,23 +8039,23 @@ function TopUpModal({ isOpen, onClose }) {
7999
8039
  }
8000
8040
  if (polls >= 24) {
8001
8041
  clearPolling();
8002
- setTxState({ status: "confirmed", txHash });
8042
+ setTxState({ status: "failed", error: "Unable to confirm transaction. Please check your wallet for status." });
8003
8043
  }
8004
8044
  }, 5e3);
8005
8045
  };
8006
8046
  const phase = getPhase2(step);
8007
8047
  const buttonLabel = () => {
8008
8048
  switch (step) {
8009
- case "preparing-permit":
8010
- return "Preparing approval...";
8011
- case "signing-permit":
8049
+ case "approving":
8050
+ return "Checking approval...";
8051
+ case "signing-approval":
8012
8052
  return "Sign Approval (1/2)...";
8013
- case "preparing-bundle":
8053
+ case "preparing-transfer":
8014
8054
  return action === "deposit" ? "Preparing transfer..." : "Preparing withdrawal...";
8015
- case "signing-bundle":
8055
+ case "signing-transfer":
8016
8056
  return action === "deposit" ? "Sign Transfer (2/2)..." : "Sign Withdrawal...";
8017
- case "broadcasting":
8018
- return "Broadcasting...";
8057
+ case "executing":
8058
+ return "Executing...";
8019
8059
  default:
8020
8060
  return null;
8021
8061
  }
@@ -8098,7 +8138,10 @@ function TopUpModal({ isOpen, onClose }) {
8098
8138
  {
8099
8139
  type: "number",
8100
8140
  value: amount,
8101
- onChange: (e) => setAmount(e.target.value),
8141
+ onChange: (e) => {
8142
+ setAmount(e.target.value);
8143
+ setTxState({ status: "idle" });
8144
+ },
8102
8145
  disabled: isBusy,
8103
8146
  placeholder: "0.00",
8104
8147
  className: "w-full border px-3 py-2.5 pr-14 text-sm focus:outline-none disabled:opacity-50",
@@ -8140,7 +8183,7 @@ function TopUpModal({ isOpen, onClose }) {
8140
8183
  }
8141
8184
  )
8142
8185
  ] }),
8143
- !isBusy && step !== "confirmed" && step !== "failed" && /* @__PURE__ */ jsx(
8186
+ !isBusy && step !== "confirmed" && step !== "failed" && txState.status === "idle" && /* @__PURE__ */ jsx(
8144
8187
  "p",
8145
8188
  {
8146
8189
  className: "text-xs",
@@ -10769,7 +10812,7 @@ function AllocationEditor({
10769
10812
  ) })
10770
10813
  ] });
10771
10814
  }
10772
- var EVM_CHAIN_IDS3 = {
10815
+ var EVM_CHAIN_IDS4 = {
10773
10816
  ethereum: 1,
10774
10817
  base: 8453,
10775
10818
  arbitrum: 42161
@@ -10948,7 +10991,7 @@ function RebalancingWidget({
10948
10991
  setTargets((prev) => prev.map((t, i) => i === index ? { ...t, targetPercent: rounded } : t));
10949
10992
  }, []);
10950
10993
  const ensureCorrectChain = useCallback(async () => {
10951
- const targetChainId = EVM_CHAIN_IDS3[CHAIN_ID];
10994
+ const targetChainId = EVM_CHAIN_IDS4[CHAIN_ID];
10952
10995
  if (!targetChainId) return;
10953
10996
  if (walletChainId !== void 0 && walletChainId !== targetChainId) {
10954
10997
  if (!switchChain) {