@compass-labs/widgets 0.1.38 → 0.1.39

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
@@ -1160,9 +1160,9 @@ function CopyableAddress({
1160
1160
  title: copied ? "Copied!" : `Copy: ${address}`,
1161
1161
  children: [
1162
1162
  label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: label }),
1163
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5", children: [
1163
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
1164
1164
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-mono", style: { color: "var(--compass-color-text)" }, children: displayAddr }),
1165
- copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 12, className: "flex-shrink-0", style: { color: "var(--compass-color-success)" } }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { size: 12, className: "flex-shrink-0", style: { color: "var(--compass-color-text-tertiary)" } })
1165
+ copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 14, className: "flex-shrink-0", style: { color: "var(--compass-color-success)" } }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { size: 14, className: "flex-shrink-0", style: { color: "var(--compass-color-text-secondary)" } })
1166
1166
  ] })
1167
1167
  ]
1168
1168
  }
@@ -2663,7 +2663,7 @@ function AccountBalancesModal({
2663
2663
  ] })
2664
2664
  ] }) });
2665
2665
  }
2666
- var TRANSFER_TOKENS = ["USDC", "SBC"];
2666
+ var TRANSFER_TOKEN = "USDC";
2667
2667
  var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
2668
2668
  compact = false,
2669
2669
  hideVisual = false,
@@ -2671,7 +2671,7 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
2671
2671
  }, ref) {
2672
2672
  const [isModalOpen, setIsModalOpen] = react.useState(false);
2673
2673
  const [activeAction, setActiveAction] = react.useState("deposit");
2674
- const [selectedToken, setSelectedToken] = react.useState(TRANSFER_TOKENS[0]);
2674
+ const selectedToken = TRANSFER_TOKEN;
2675
2675
  const [amount, setAmount] = react.useState("");
2676
2676
  const [transferState, setTransferState] = react.useState("idle");
2677
2677
  const [statusMessage, setStatusMessage] = react.useState("");
@@ -2697,23 +2697,20 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
2697
2697
  staleTime: 30 * 1e3
2698
2698
  });
2699
2699
  const { data: eoaBalances } = reactQuery.useQuery({
2700
- queryKey: ["eoaBalances", chainId, address, TRANSFER_TOKENS.join(",")],
2700
+ queryKey: ["eoaBalances", chainId, address, TRANSFER_TOKEN],
2701
2701
  queryFn: async () => {
2702
2702
  if (!address) return {};
2703
- const balances = {};
2704
- for (const token of TRANSFER_TOKENS) {
2705
- try {
2706
- const response = await fetch(
2707
- `/api/compass/token/balance?chain=${chainId}&token=${token}&address=${address}`
2708
- );
2709
- if (response.ok) {
2710
- const data = await response.json();
2711
- balances[token] = data.balance || "0";
2712
- }
2713
- } catch {
2703
+ try {
2704
+ const response = await fetch(
2705
+ `/api/compass/token/balance?chain=${chainId}&token=${TRANSFER_TOKEN}&address=${address}`
2706
+ );
2707
+ if (response.ok) {
2708
+ const data = await response.json();
2709
+ return { [TRANSFER_TOKEN]: data.balance || "0" };
2714
2710
  }
2711
+ } catch {
2715
2712
  }
2716
- return balances;
2713
+ return {};
2717
2714
  },
2718
2715
  enabled: !!address && activeAction === "deposit",
2719
2716
  staleTime: 30 * 1e3
@@ -2760,11 +2757,6 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
2760
2757
  }
2761
2758
  return earnBalanceAmounts[selectedToken] || "0";
2762
2759
  };
2763
- const handleQuickAmount = (percentage) => {
2764
- const max = parseFloat(getMaxBalance());
2765
- if (isNaN(max)) return;
2766
- setAmount(formatAmount(max * percentage));
2767
- };
2768
2760
  const handleTransfer = react.useCallback(async () => {
2769
2761
  if (!address || !amount || !signTypedData) return;
2770
2762
  setError(null);
@@ -3027,37 +3019,9 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
3027
3019
  {
3028
3020
  className: "text-sm font-medium mb-1 block",
3029
3021
  style: { color: "var(--compass-color-text-secondary)" },
3030
- children: "Token"
3022
+ children: "Amount"
3031
3023
  }
3032
3024
  ),
3033
- /* @__PURE__ */ jsxRuntime.jsx(
3034
- TokenSelector,
3035
- {
3036
- tokens: TRANSFER_TOKENS,
3037
- selectedToken,
3038
- onSelect: setSelectedToken,
3039
- balances: activeAction === "deposit" ? eoaBalances : earnBalanceAmounts,
3040
- disabled: isProcessing
3041
- }
3042
- )
3043
- ] }),
3044
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3045
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-1", children: [
3046
- /* @__PURE__ */ jsxRuntime.jsx(
3047
- "label",
3048
- {
3049
- className: "text-sm font-medium",
3050
- style: { color: "var(--compass-color-text-secondary)" },
3051
- children: "Amount"
3052
- }
3053
- ),
3054
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: [
3055
- "Available: ",
3056
- formatAmount(getMaxBalance()),
3057
- " ",
3058
- selectedToken
3059
- ] })
3060
- ] }),
3061
3025
  /* @__PURE__ */ jsxRuntime.jsxs(
3062
3026
  "div",
3063
3027
  {
@@ -3088,28 +3052,27 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
3088
3052
  {
3089
3053
  className: "text-sm font-medium",
3090
3054
  style: { color: "var(--compass-color-text-secondary)" },
3091
- children: selectedToken
3055
+ children: "USDC"
3092
3056
  }
3093
3057
  )
3094
3058
  ]
3095
3059
  }
3060
+ ),
3061
+ /* @__PURE__ */ jsxRuntime.jsxs(
3062
+ "button",
3063
+ {
3064
+ onClick: () => setAmount(formatAmount(getMaxBalance())),
3065
+ className: "text-xs mt-1",
3066
+ style: { color: "var(--compass-color-primary)", cursor: "pointer", background: "none", border: "none", padding: 0 },
3067
+ children: [
3068
+ "Available: ",
3069
+ formatAmount(getMaxBalance()),
3070
+ " USDC"
3071
+ ]
3072
+ }
3096
3073
  )
3097
3074
  ] }),
3098
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-2", children: [0.25, 0.5, 1].map((pct) => /* @__PURE__ */ jsxRuntime.jsx(
3099
- "button",
3100
- {
3101
- onClick: () => handleQuickAmount(pct),
3102
- disabled: isProcessing,
3103
- className: "flex-1 py-1.5 text-xs font-medium transition-colors",
3104
- style: {
3105
- backgroundColor: "var(--compass-color-secondary)",
3106
- color: "var(--compass-color-text-secondary)",
3107
- borderRadius: "var(--compass-border-radius-md)"
3108
- },
3109
- children: pct === 1 ? "Max" : `${pct * 100}%`
3110
- },
3111
- pct
3112
- )) }),
3075
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: activeAction === "deposit" ? "Approves the token transfer, then transfers USDC from your wallet into your savings account. Requires 2 signatures." : "Withdraws USDC from your savings account back to your wallet. Requires 1 signature." }),
3113
3076
  error && /* @__PURE__ */ jsxRuntime.jsx(
3114
3077
  "div",
3115
3078
  {
@@ -3134,7 +3097,7 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
3134
3097
  children: statusMessage
3135
3098
  }
3136
3099
  ),
3137
- /* @__PURE__ */ jsxRuntime.jsxs(
3100
+ /* @__PURE__ */ jsxRuntime.jsx(
3138
3101
  "button",
3139
3102
  {
3140
3103
  onClick: handleTransfer,
@@ -3146,10 +3109,14 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
3146
3109
  borderRadius: "var(--compass-border-radius-lg)",
3147
3110
  fontFamily: "var(--compass-font-family)"
3148
3111
  },
3149
- children: [
3150
- isProcessing && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 18, className: "animate-spin" }),
3151
- isProcessing ? "Processing..." : activeAction === "deposit" ? "Deposit to Earn Account" : "Withdraw to Wallet"
3152
- ]
3112
+ children: isProcessing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3113
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 18, className: "animate-spin" }),
3114
+ " Processing..."
3115
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3116
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { size: 16 }),
3117
+ " ",
3118
+ activeAction === "deposit" ? "Transfer to Savings Account" : "Withdraw to Wallet"
3119
+ ] })
3153
3120
  }
3154
3121
  ),
3155
3122
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -5672,31 +5639,7 @@ function EarnAccount({
5672
5639
  ]
5673
5640
  }
5674
5641
  )
5675
- ] }),
5676
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex", style: { gap: "6px", marginTop: activeTab === "deposit" && maxAmount >= 10 ? "8px" : "0" }, children: activeTab === "deposit" && maxAmount > 0 && [10, 20, 30].filter((v) => v <= maxAmount).map((val) => /* @__PURE__ */ jsxRuntime.jsxs(
5677
- "button",
5678
- {
5679
- onClick: () => {
5680
- setAmount(val.toString());
5681
- setError(null);
5682
- },
5683
- disabled: isProcessing,
5684
- className: "text-xs font-medium",
5685
- style: {
5686
- padding: "4px 12px",
5687
- backgroundColor: parseFloat(amount) === val ? "transparent" : "var(--compass-color-surface)",
5688
- border: parseFloat(amount) === val ? "1.5px solid var(--compass-color-primary)" : "1.5px solid var(--compass-color-border)",
5689
- color: parseFloat(amount) === val ? "var(--compass-color-primary)" : "var(--compass-color-text-secondary)",
5690
- borderRadius: "var(--compass-border-radius-xl)",
5691
- transition: "all 150ms ease"
5692
- },
5693
- children: [
5694
- "$",
5695
- val
5696
- ]
5697
- },
5698
- val
5699
- )) })
5642
+ ] })
5700
5643
  ]
5701
5644
  }
5702
5645
  ),
@@ -10710,6 +10653,7 @@ function RebalancingWidget({
10710
10653
  const [txHash, setTxHash] = react.useState(null);
10711
10654
  const [txConfirmed, setTxConfirmed] = react.useState(false);
10712
10655
  const [hasInitializedTargets, setHasInitializedTargets] = react.useState(false);
10656
+ const [originalAllocations, setOriginalAllocations] = react.useState({});
10713
10657
  const [isSwapModalOpen, setIsSwapModalOpen] = react.useState(false);
10714
10658
  const [isBalancesModalOpen, setIsBalancesModalOpen] = react.useState(false);
10715
10659
  const [isAddMarketExpanded, setIsAddMarketExpanded] = react.useState(false);
@@ -10728,6 +10672,7 @@ function RebalancingWidget({
10728
10672
  const earnBalanceRef = react.useRef(null);
10729
10673
  react.useEffect(() => {
10730
10674
  setTargets([]);
10675
+ setOriginalAllocations({});
10731
10676
  setPreviewPlan(null);
10732
10677
  setServerPreview(null);
10733
10678
  setWidgetState("editing");
@@ -10744,15 +10689,21 @@ function RebalancingWidget({
10744
10689
  }, [CHAIN_ID]);
10745
10690
  react.useEffect(() => {
10746
10691
  if (portfolio && portfolio.positions.length > 0 && !hasInitializedTargets && !isLoading) {
10692
+ const origAllocs = {};
10747
10693
  setTargets(
10748
- portfolio.positions.map((p) => ({
10749
- venueType: p.venueType,
10750
- venueAddress: p.venueAddress,
10751
- venueName: p.venueName,
10752
- token: p.token,
10753
- targetPercent: parseFloat(p.allocationPercent.toFixed(2))
10754
- }))
10694
+ portfolio.positions.map((p) => {
10695
+ const pct = parseFloat(p.allocationPercent.toFixed(2));
10696
+ origAllocs[`${p.venueType}-${p.venueAddress.toLowerCase()}`] = pct;
10697
+ return {
10698
+ venueType: p.venueType,
10699
+ venueAddress: p.venueAddress,
10700
+ venueName: p.venueName,
10701
+ token: p.token,
10702
+ targetPercent: pct
10703
+ };
10704
+ })
10755
10705
  );
10706
+ setOriginalAllocations(origAllocs);
10756
10707
  setHasInitializedTargets(true);
10757
10708
  }
10758
10709
  }, [portfolio, hasInitializedTargets, isLoading]);
@@ -10784,15 +10735,21 @@ function RebalancingWidget({
10784
10735
  }, [portfolio, targets, hasChanges, defaultSlippage, minRebalanceThresholdUsd]);
10785
10736
  const handleResetToCurrent = react.useCallback(() => {
10786
10737
  if (!portfolio) return;
10738
+ const origAllocs = {};
10787
10739
  setTargets(
10788
- portfolio.positions.map((p) => ({
10789
- venueType: p.venueType,
10790
- venueAddress: p.venueAddress,
10791
- venueName: p.venueName,
10792
- token: p.token,
10793
- targetPercent: parseFloat(p.allocationPercent.toFixed(2))
10794
- }))
10740
+ portfolio.positions.map((p) => {
10741
+ const pct = parseFloat(p.allocationPercent.toFixed(2));
10742
+ origAllocs[`${p.venueType}-${p.venueAddress.toLowerCase()}`] = pct;
10743
+ return {
10744
+ venueType: p.venueType,
10745
+ venueAddress: p.venueAddress,
10746
+ venueName: p.venueName,
10747
+ token: p.token,
10748
+ targetPercent: pct
10749
+ };
10750
+ })
10795
10751
  );
10752
+ setOriginalAllocations(origAllocs);
10796
10753
  setPreviewPlan(null);
10797
10754
  setServerPreview(null);
10798
10755
  setWidgetState("editing");
@@ -10835,7 +10792,8 @@ function RebalancingWidget({
10835
10792
  venueType: t.venueType === "vault" ? "VAULT" : t.venueType === "aave" ? "AAVE" : "PENDLE_PT",
10836
10793
  venueAddress: t.venueAddress,
10837
10794
  targetPercent: t.targetPercent,
10838
- token: t.token
10795
+ token: t.token,
10796
+ originalPercent: originalAllocations[`${t.venueType}-${t.venueAddress.toLowerCase()}`] ?? 0
10839
10797
  })),
10840
10798
  slippage: defaultSlippage
10841
10799
  })
@@ -10853,7 +10811,7 @@ function RebalancingWidget({
10853
10811
  setWidgetState("error");
10854
10812
  onError?.(err instanceof Error ? err : new Error("Preview failed"));
10855
10813
  }
10856
- }, [portfolio, hasChanges, address, CHAIN_ID, targets, defaultSlippage, clientPreview, onError, ensureCorrectChain]);
10814
+ }, [portfolio, hasChanges, address, CHAIN_ID, targets, defaultSlippage, clientPreview, onError, ensureCorrectChain, originalAllocations]);
10857
10815
  const handleExecute = react.useCallback(async () => {
10858
10816
  if (!serverPreview?.eip712 || !address) return;
10859
10817
  setWidgetState("signing");
@@ -11489,11 +11447,7 @@ function RebalancingWidget({
11489
11447
  clientPreview.warnings.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-col gap-1", children: clientPreview.warnings.map((w, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 text-xs", style: { color: "var(--compass-color-warning, #eab308)" }, children: [
11490
11448
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { size: 12, className: "flex-shrink-0 mt-0.5" }),
11491
11449
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: w })
11492
- ] }, i)) }),
11493
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs mt-2", style: { color: "var(--compass-color-text-tertiary)" }, children: [
11494
- "Estimated gas savings: ",
11495
- clientPreview.estimatedGasSavings
11496
- ] })
11450
+ ] }, i)) })
11497
11451
  ]
11498
11452
  }
11499
11453
  ),
@@ -11736,46 +11690,8 @@ function RebalancingWidget({
11736
11690
  onClose: () => setIsBalancesModalOpen(false),
11737
11691
  title: "Balance Breakdown",
11738
11692
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "12px" }, children: [
11739
- address && /* @__PURE__ */ jsxRuntime.jsxs(
11740
- "div",
11741
- {
11742
- className: "flex items-center justify-between",
11743
- style: {
11744
- backgroundColor: "var(--compass-color-surface)",
11745
- borderRadius: "var(--compass-border-radius-lg)",
11746
- padding: "10px 16px",
11747
- border: "1.5px solid var(--compass-color-border)"
11748
- },
11749
- children: [
11750
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text-tertiary)", fontSize: "0.8125rem" }, children: "Wallet" }),
11751
- /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: "var(--compass-color-text)", fontSize: "0.8125rem", fontFamily: "monospace" }, children: [
11752
- address.slice(0, 6),
11753
- "...",
11754
- address.slice(-4)
11755
- ] })
11756
- ]
11757
- }
11758
- ),
11759
- earnAccountAddress && /* @__PURE__ */ jsxRuntime.jsxs(
11760
- "div",
11761
- {
11762
- className: "flex items-center justify-between",
11763
- style: {
11764
- backgroundColor: "var(--compass-color-surface)",
11765
- borderRadius: "var(--compass-border-radius-lg)",
11766
- padding: "10px 16px",
11767
- border: "1.5px solid var(--compass-color-border)"
11768
- },
11769
- children: [
11770
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--compass-color-text-tertiary)", fontSize: "0.8125rem" }, children: "Product Account" }),
11771
- /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: "var(--compass-color-text)", fontSize: "0.8125rem", fontFamily: "monospace" }, children: [
11772
- earnAccountAddress.slice(0, 6),
11773
- "...",
11774
- earnAccountAddress.slice(-4)
11775
- ] })
11776
- ]
11777
- }
11778
- ),
11693
+ address && /* @__PURE__ */ jsxRuntime.jsx(CopyableAddress, { address, label: "Wallet" }),
11694
+ earnAccountAddress && /* @__PURE__ */ jsxRuntime.jsx(CopyableAddress, { address: earnAccountAddress, label: "Product Account" }),
11779
11695
  portfolio && portfolio.idleBalances.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
11780
11696
  /* @__PURE__ */ jsxRuntime.jsx(
11781
11697
  "span",