@compass-labs/widgets 0.1.27 → 0.1.28

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
@@ -6759,9 +6759,9 @@ function PortfolioBalanceCard({
6759
6759
  totalIdleUsd,
6760
6760
  idleBalances,
6761
6761
  earnAccountAddress,
6762
- isPositionsExpanded,
6763
- onTogglePositions,
6762
+ onViewPositions,
6764
6763
  positionCount,
6764
+ totalEarned = 0,
6765
6765
  showTopUp = true,
6766
6766
  onTopUp
6767
6767
  }) {
@@ -6859,27 +6859,43 @@ function PortfolioBalanceCard({
6859
6859
  /* @__PURE__ */ jsxRuntime.jsx(
6860
6860
  "button",
6861
6861
  {
6862
- onClick: onTogglePositions,
6863
- className: "flex items-center justify-between w-full text-left transition-opacity hover:opacity-80",
6862
+ onClick: onViewPositions,
6863
+ disabled: positionCount === 0,
6864
+ className: "flex items-center justify-between w-full text-left transition-opacity hover:opacity-80 disabled:hover:opacity-100 disabled:cursor-default",
6864
6865
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "calc(var(--compass-spacing-unit) * 0.25)" }, children: [
6865
6866
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
6866
6867
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm", style: { color: "var(--compass-color-text-tertiary)" }, children: [
6867
6868
  "Earning interest",
6868
- positionCount > 0 ? ` \xB7 ${positionCount} ${positionCount === 1 ? "position" : "positions"}` : ""
6869
+ positionCount > 1 ? ` \xB7 ${positionCount} positions` : ""
6869
6870
  ] }),
6870
- positionCount > 0 && (isPositionsExpanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } }))
6871
+ positionCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } })
6871
6872
  ] }),
6872
- /* @__PURE__ */ jsxRuntime.jsx(
6873
- "span",
6874
- {
6875
- className: "font-semibold",
6876
- style: {
6877
- color: "var(--compass-color-text)",
6878
- fontSize: "1rem"
6879
- },
6880
- children: formatUSD(earningInterestUsd)
6881
- }
6882
- )
6873
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.75)" }, children: [
6874
+ /* @__PURE__ */ jsxRuntime.jsx(
6875
+ "span",
6876
+ {
6877
+ className: "font-semibold",
6878
+ style: {
6879
+ color: "var(--compass-color-text)",
6880
+ fontSize: "1rem"
6881
+ },
6882
+ children: formatUSD(earningInterestUsd)
6883
+ }
6884
+ ),
6885
+ positionCount > 0 && totalEarned !== 0 && /* @__PURE__ */ jsxRuntime.jsxs(
6886
+ "span",
6887
+ {
6888
+ className: "text-sm font-medium",
6889
+ style: {
6890
+ color: totalEarned >= 0 ? "var(--compass-color-success)" : "var(--compass-color-error)"
6891
+ },
6892
+ children: [
6893
+ totalEarned >= 0 ? "+" : "",
6894
+ formatUSD(totalEarned)
6895
+ ]
6896
+ }
6897
+ )
6898
+ ] })
6883
6899
  ] })
6884
6900
  }
6885
6901
  )
@@ -7183,7 +7199,8 @@ function RebalancingWidget({
7183
7199
  const [errorMessage, setErrorMessage] = react.useState(null);
7184
7200
  const [txHash, setTxHash] = react.useState(null);
7185
7201
  const [hasInitializedTargets, setHasInitializedTargets] = react.useState(false);
7186
- const [isPositionsExpanded, setIsPositionsExpanded] = react.useState(false);
7202
+ const [isEarningsModalOpen, setIsEarningsModalOpen] = react.useState(false);
7203
+ const [isAddMarketExpanded, setIsAddMarketExpanded] = react.useState(false);
7187
7204
  const [marketTab, setMarketTab] = react.useState("variable");
7188
7205
  const [selectedMarket, setSelectedMarket] = react.useState(null);
7189
7206
  const [selectedToken, setSelectedToken] = react.useState("USDC");
@@ -7201,7 +7218,7 @@ function RebalancingWidget({
7201
7218
  setErrorMessage(null);
7202
7219
  setTxHash(null);
7203
7220
  setHasInitializedTargets(false);
7204
- setIsPositionsExpanded(false);
7221
+ setIsAddMarketExpanded(false);
7205
7222
  setSelectedMarket(null);
7206
7223
  setDepositAmount("");
7207
7224
  setDepositError(null);
@@ -7363,6 +7380,59 @@ function RebalancingWidget({
7363
7380
  await switchChain(targetChainId);
7364
7381
  }
7365
7382
  }, [walletChainId, switchChain, CHAIN_ID]);
7383
+ const rawPositionsQuery = reactQuery.useQuery({
7384
+ queryKey: ["rebalancingRawPositions", CHAIN_ID, address],
7385
+ queryFn: async () => {
7386
+ if (!address) return [];
7387
+ const response = await fetch(`/api/compass/positions?chain=${CHAIN_ID}&owner=${address}`);
7388
+ if (!response.ok) return [];
7389
+ const data = await response.json();
7390
+ return data.positions || [];
7391
+ },
7392
+ enabled: !!address,
7393
+ staleTime: 3e4
7394
+ });
7395
+ const earningsPositions = react.useMemo(() => {
7396
+ return (rawPositionsQuery.data || []).map((pos, index) => ({
7397
+ id: `pos-${index}`,
7398
+ marketType: pos.protocol,
7399
+ marketName: pos.name,
7400
+ marketId: `${pos.protocol}-${index}`,
7401
+ amount: parseFloat(pos.balance || "0"),
7402
+ token: pos.symbol,
7403
+ apy: pos.apy || 0,
7404
+ performance: parseFloat(pos.pnl?.totalPnl || "0"),
7405
+ pnl: pos.pnl ? {
7406
+ unrealizedPnl: parseFloat(pos.pnl.unrealizedPnl || "0"),
7407
+ realizedPnl: parseFloat(pos.pnl.realizedPnl || "0"),
7408
+ totalPnl: parseFloat(pos.pnl.totalPnl || "0")
7409
+ } : void 0,
7410
+ transactions: [
7411
+ ...(pos.deposits || []).map((d, i) => ({
7412
+ id: `dep-${index}-${i}`,
7413
+ type: "deposit",
7414
+ amount: parseFloat(d.amount || "0"),
7415
+ token: pos.symbol,
7416
+ txHash: d.txHash || "",
7417
+ timestamp: d.timestamp || void 0
7418
+ })),
7419
+ ...(pos.withdrawals || []).map((w, i) => ({
7420
+ id: `wit-${index}-${i}`,
7421
+ type: "withdraw",
7422
+ amount: parseFloat(w.amount || "0"),
7423
+ token: pos.symbol,
7424
+ txHash: w.txHash || "",
7425
+ timestamp: w.timestamp || void 0
7426
+ }))
7427
+ ].sort((a, b) => {
7428
+ if (a.timestamp && b.timestamp) return new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime();
7429
+ if (a.timestamp) return -1;
7430
+ if (b.timestamp) return 1;
7431
+ return 0;
7432
+ })
7433
+ }));
7434
+ }, [rawPositionsQuery.data]);
7435
+ const totalEarned = react.useMemo(() => earningsPositions.reduce((sum, p) => sum + p.performance, 0), [earningsPositions]);
7366
7436
  const buildVenueParamsFromMarket = (market) => {
7367
7437
  switch (market.type) {
7368
7438
  case "aave":
@@ -7617,14 +7687,14 @@ function RebalancingWidget({
7617
7687
  totalUsd: portfolio.totalUsd,
7618
7688
  totalIdleUsd: portfolio.totalIdleUsd,
7619
7689
  idleBalances: portfolio.idleBalances,
7620
- isPositionsExpanded,
7621
- onTogglePositions: () => setIsPositionsExpanded((prev) => !prev),
7690
+ onViewPositions: () => setIsEarningsModalOpen(true),
7622
7691
  positionCount: portfolio.positions.length,
7692
+ totalEarned,
7623
7693
  showTopUp,
7624
7694
  onTopUp: () => earnBalanceRef.current?.openTransferModal()
7625
7695
  }
7626
7696
  ),
7627
- isPositionsExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
7697
+ /* @__PURE__ */ jsxRuntime.jsx(
7628
7698
  AllocationEditor,
7629
7699
  {
7630
7700
  portfolio,
@@ -7637,8 +7707,30 @@ function RebalancingWidget({
7637
7707
  onResetToCurrent: handleResetToCurrent,
7638
7708
  onEqualSplit: handleEqualSplit
7639
7709
  }
7640
- ) }),
7641
- !isPositionsExpanded && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7710
+ ),
7711
+ /* @__PURE__ */ jsxRuntime.jsxs(
7712
+ "button",
7713
+ {
7714
+ onClick: () => setIsAddMarketExpanded((prev) => !prev),
7715
+ className: "flex items-center font-medium transition-all hover:opacity-80",
7716
+ style: {
7717
+ backgroundColor: "var(--compass-color-surface)",
7718
+ border: "1px solid var(--compass-color-border)",
7719
+ color: "var(--compass-color-text-secondary)",
7720
+ borderRadius: "var(--compass-border-radius-lg)",
7721
+ padding: "calc(var(--compass-spacing-unit) * 0.75) calc(var(--compass-spacing-unit) * 1)",
7722
+ gap: "calc(var(--compass-spacing-unit) * 0.5)",
7723
+ fontSize: "0.8125rem",
7724
+ width: "100%",
7725
+ justifyContent: "center"
7726
+ },
7727
+ children: [
7728
+ isAddMarketExpanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { size: 14 }),
7729
+ isAddMarketExpanded ? "Hide" : "Add new market"
7730
+ ]
7731
+ }
7732
+ ),
7733
+ isAddMarketExpanded && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7642
7734
  /* @__PURE__ */ jsxRuntime.jsx(
7643
7735
  MarketSelector,
7644
7736
  {
@@ -8058,7 +8150,17 @@ function RebalancingWidget({
8058
8150
  ]
8059
8151
  }
8060
8152
  ) }),
8061
- /* @__PURE__ */ jsxRuntime.jsx(EarnAccountBalance, { ref: earnBalanceRef, compact: true, hideVisual: true, onTransferComplete: () => refetch() })
8153
+ /* @__PURE__ */ jsxRuntime.jsx(EarnAccountBalance, { ref: earnBalanceRef, compact: true, hideVisual: true, onTransferComplete: () => refetch() }),
8154
+ /* @__PURE__ */ jsxRuntime.jsx(
8155
+ EarningsModal,
8156
+ {
8157
+ isOpen: isEarningsModalOpen,
8158
+ onClose: () => setIsEarningsModalOpen(false),
8159
+ positions: earningsPositions,
8160
+ totalEarned,
8161
+ isLoading: rawPositionsQuery.isLoading
8162
+ }
8163
+ )
8062
8164
  ]
8063
8165
  }
8064
8166
  );