@compass-labs/widgets 0.1.33 → 0.1.34

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
@@ -3,7 +3,7 @@ import { useQueryClient, useQuery, QueryClient, QueryClientProvider } from '@tan
3
3
  import { CompassApiSDK } from '@compass-labs/api-sdk';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
5
  import { arbitrum, base, mainnet } from 'viem/chains';
6
- import { Wallet, Loader2, ArrowDownLeft, ArrowUpRight, X, ChevronDown, LogOut, AlertCircle, ArrowRight, ExternalLink, ArrowDownUp, ArrowLeftRight, Plus, ChevronRight, Minus, Shield, CheckCircle, AlertTriangle, Check, RotateCcw, Equal, ChevronUp, Inbox, Percent, Clock, Calendar, TrendingUp, TrendingDown } from 'lucide-react';
6
+ import { Wallet, Loader2, ArrowDownLeft, ArrowUpRight, X, ChevronDown, Check, Copy, LogOut, AlertCircle, ArrowRight, ExternalLink, ArrowDownUp, ArrowLeftRight, Plus, ChevronRight, Minus, Shield, CheckCircle, AlertTriangle, RotateCcw, Equal, ChevronUp, Inbox, Percent, Clock, Calendar, TrendingUp, TrendingDown } from 'lucide-react';
7
7
 
8
8
  // src/provider/CompassProvider.tsx
9
9
  var ApiContext = createContext(null);
@@ -990,9 +990,52 @@ function ChainSwitcher() {
990
990
  }
991
991
  );
992
992
  }
993
- function truncateAddress(address) {
993
+ function truncateAddr(address) {
994
994
  return `${address.slice(0, 6)}...${address.slice(-4)}`;
995
995
  }
996
+ function CopyableAddress({
997
+ address,
998
+ label,
999
+ truncate = true,
1000
+ textSize = "text-xs"
1001
+ }) {
1002
+ const [copied, setCopied] = useState(false);
1003
+ const handleCopy = useCallback(() => {
1004
+ navigator.clipboard.writeText(address);
1005
+ setCopied(true);
1006
+ setTimeout(() => setCopied(false), 1500);
1007
+ }, [address]);
1008
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", style: { gap: "2px" }, children: [
1009
+ label && /* @__PURE__ */ jsx(
1010
+ "span",
1011
+ {
1012
+ className: "text-xs",
1013
+ style: { color: "var(--compass-color-text-tertiary)", fontSize: "10px" },
1014
+ children: label
1015
+ }
1016
+ ),
1017
+ /* @__PURE__ */ jsxs(
1018
+ "button",
1019
+ {
1020
+ onClick: handleCopy,
1021
+ className: `inline-flex items-center font-mono ${textSize}`,
1022
+ style: {
1023
+ color: "var(--compass-color-text-secondary)",
1024
+ background: "none",
1025
+ border: "none",
1026
+ cursor: "pointer",
1027
+ padding: 0,
1028
+ gap: "4px"
1029
+ },
1030
+ title: copied ? "Copied!" : `Copy: ${address}`,
1031
+ children: [
1032
+ /* @__PURE__ */ jsx("span", { children: truncate ? truncateAddr(address) : address }),
1033
+ copied ? /* @__PURE__ */ jsx(Check, { size: 10, className: "flex-shrink-0", style: { color: "var(--compass-color-success)" } }) : /* @__PURE__ */ jsx(Copy, { size: 10, className: "flex-shrink-0", style: { color: "var(--compass-color-text-tertiary)" } })
1034
+ ]
1035
+ }
1036
+ )
1037
+ ] });
1038
+ }
996
1039
  function WalletStatus({
997
1040
  showFullAddress = false,
998
1041
  showLogout = true,
@@ -1069,11 +1112,11 @@ function WalletStatus({
1069
1112
  }
1070
1113
  ),
1071
1114
  /* @__PURE__ */ jsx(
1072
- "span",
1115
+ CopyableAddress,
1073
1116
  {
1074
- className: `font-mono whitespace-nowrap ${compact ? "text-xs" : "text-sm"}`,
1075
- style: { color: "var(--compass-color-text)" },
1076
- children: showFullAddress ? address : truncateAddress(address)
1117
+ address,
1118
+ truncate: !showFullAddress,
1119
+ textSize: compact ? "text-xs" : "text-sm"
1077
1120
  }
1078
1121
  ),
1079
1122
  showLogout && disconnectFn !== null && /* @__PURE__ */ jsx(
@@ -2237,82 +2280,97 @@ function AccountBalancesModal({
2237
2280
  onClose,
2238
2281
  balances,
2239
2282
  totalUsdValue,
2240
- isLoading = false
2283
+ isLoading = false,
2284
+ earnAccountAddress,
2285
+ walletAddress
2241
2286
  }) {
2242
- return /* @__PURE__ */ jsx(ActionModal, { isOpen, onClose, title: "Balance Breakdown", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-3", children: isLoading ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ jsx(
2243
- Loader2,
2244
- {
2245
- size: 24,
2246
- className: "animate-spin",
2247
- style: { color: "var(--compass-color-primary)" }
2248
- }
2249
- ) }) : balances.length === 0 ? /* @__PURE__ */ jsx(
2250
- "div",
2251
- {
2252
- className: "text-center py-4",
2253
- style: { color: "var(--compass-color-text-tertiary)" },
2254
- children: "No tokens in account"
2255
- }
2256
- ) : /* @__PURE__ */ jsxs(Fragment, { children: [
2257
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
2258
- /* @__PURE__ */ jsx(
2259
- "span",
2260
- {
2261
- className: "text-xs font-medium uppercase tracking-wide",
2262
- style: { color: "var(--compass-color-text-tertiary)" },
2263
- children: "Available in Account"
2264
- }
2265
- ),
2266
- /* @__PURE__ */ jsx(
2267
- "div",
2268
- {
2269
- className: "flex flex-col gap-2",
2270
- style: {
2271
- maxHeight: "50vh",
2272
- overflowY: "auto",
2273
- scrollbarWidth: "none"
2274
- },
2275
- children: balances.map((token) => /* @__PURE__ */ jsxs(
2276
- "div",
2277
- {
2278
- className: "flex items-center justify-between p-3 rounded-lg",
2279
- style: {
2280
- backgroundColor: "var(--compass-color-surface)",
2281
- border: "1px solid var(--compass-color-border)",
2282
- flexShrink: 0
2283
- },
2284
- children: [
2285
- /* @__PURE__ */ jsx("span", { className: "font-medium", style: { color: "var(--compass-color-text)" }, children: token.symbol }),
2286
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-end", children: [
2287
- /* @__PURE__ */ jsx("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-text)" }, children: formatAmount(token.balance) }),
2288
- /* @__PURE__ */ jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: formatUSD(token.usdValue) })
2289
- ] })
2290
- ]
2291
- },
2292
- token.symbol
2293
- ))
2294
- }
2295
- )
2296
- ] }),
2297
- /* @__PURE__ */ jsxs(
2287
+ return /* @__PURE__ */ jsx(ActionModal, { isOpen, onClose, title: "Balance Breakdown", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
2288
+ (walletAddress || earnAccountAddress) && /* @__PURE__ */ jsxs(
2298
2289
  "div",
2299
2290
  {
2300
- className: "flex items-center justify-between pt-3 mt-2",
2301
- style: { borderTop: "2px solid var(--compass-color-border)" },
2291
+ className: "flex flex-col gap-2 pb-3",
2292
+ style: { borderBottom: "1px solid var(--compass-color-border)" },
2302
2293
  children: [
2303
- /* @__PURE__ */ jsx("span", { className: "font-semibold", style: { color: "var(--compass-color-text)" }, children: "Total" }),
2304
- /* @__PURE__ */ jsx(
2305
- "span",
2306
- {
2307
- className: "font-bold text-xl",
2308
- style: { color: "var(--compass-color-text)" },
2309
- children: formatUSD(totalUsdValue)
2310
- }
2311
- )
2294
+ walletAddress && /* @__PURE__ */ jsx(CopyableAddress, { address: walletAddress, label: "Wallet" }),
2295
+ earnAccountAddress && /* @__PURE__ */ jsx(CopyableAddress, { address: earnAccountAddress, label: "Product Account" })
2312
2296
  ]
2313
2297
  }
2314
- )
2315
- ] }) }) });
2298
+ ),
2299
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ jsx(
2300
+ Loader2,
2301
+ {
2302
+ size: 24,
2303
+ className: "animate-spin",
2304
+ style: { color: "var(--compass-color-primary)" }
2305
+ }
2306
+ ) }) : balances.length === 0 ? /* @__PURE__ */ jsx(
2307
+ "div",
2308
+ {
2309
+ className: "text-center py-4",
2310
+ style: { color: "var(--compass-color-text-tertiary)" },
2311
+ children: "No tokens in account"
2312
+ }
2313
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
2314
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
2315
+ /* @__PURE__ */ jsx(
2316
+ "span",
2317
+ {
2318
+ className: "text-xs font-medium uppercase tracking-wide",
2319
+ style: { color: "var(--compass-color-text-tertiary)" },
2320
+ children: "Available in Account"
2321
+ }
2322
+ ),
2323
+ /* @__PURE__ */ jsx(
2324
+ "div",
2325
+ {
2326
+ className: "flex flex-col gap-2",
2327
+ style: {
2328
+ maxHeight: "50vh",
2329
+ overflowY: "auto",
2330
+ scrollbarWidth: "none"
2331
+ },
2332
+ children: balances.map((token) => /* @__PURE__ */ jsxs(
2333
+ "div",
2334
+ {
2335
+ className: "flex items-center justify-between p-3 rounded-lg",
2336
+ style: {
2337
+ backgroundColor: "var(--compass-color-surface)",
2338
+ border: "1px solid var(--compass-color-border)",
2339
+ flexShrink: 0
2340
+ },
2341
+ children: [
2342
+ /* @__PURE__ */ jsx("span", { className: "font-medium", style: { color: "var(--compass-color-text)" }, children: token.symbol }),
2343
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-end", children: [
2344
+ /* @__PURE__ */ jsx("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-text)" }, children: formatAmount(token.balance) }),
2345
+ /* @__PURE__ */ jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: formatUSD(token.usdValue) })
2346
+ ] })
2347
+ ]
2348
+ },
2349
+ token.symbol
2350
+ ))
2351
+ }
2352
+ )
2353
+ ] }),
2354
+ /* @__PURE__ */ jsxs(
2355
+ "div",
2356
+ {
2357
+ className: "flex items-center justify-between pt-3 mt-2",
2358
+ style: { borderTop: "2px solid var(--compass-color-border)" },
2359
+ children: [
2360
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", style: { color: "var(--compass-color-text)" }, children: "Total" }),
2361
+ /* @__PURE__ */ jsx(
2362
+ "span",
2363
+ {
2364
+ className: "font-bold text-xl",
2365
+ style: { color: "var(--compass-color-text)" },
2366
+ children: formatUSD(totalUsdValue)
2367
+ }
2368
+ )
2369
+ ]
2370
+ }
2371
+ )
2372
+ ] })
2373
+ ] }) });
2316
2374
  }
2317
2375
  var TRANSFER_TOKENS = ["USDC", "SBC"];
2318
2376
  var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
@@ -2632,7 +2690,8 @@ var EarnAccountBalance = forwardRef(function EarnAccountBalance2({
2632
2690
  balances: tokenBalances,
2633
2691
  totalUsdValue: totalUsdValue.toString(),
2634
2692
  isLoading: balancesLoading,
2635
- earnAccountAddress: earnAccountAddress ?? void 0
2693
+ earnAccountAddress: earnAccountAddress ?? void 0,
2694
+ walletAddress: address ?? void 0
2636
2695
  }
2637
2696
  ),
2638
2697
  /* @__PURE__ */ jsx(
@@ -6827,6 +6886,7 @@ function PortfolioBalanceCard({
6827
6886
  totalIdleUsd,
6828
6887
  idleBalances,
6829
6888
  earnAccountAddress,
6889
+ walletAddress,
6830
6890
  onViewPositions,
6831
6891
  positionCount,
6832
6892
  totalEarned = 0,
@@ -6998,7 +7058,8 @@ function PortfolioBalanceCard({
6998
7058
  onClose: () => setShowBalancesModal(false),
6999
7059
  balances: tokenBalances,
7000
7060
  totalUsdValue: totalIdleUsd.toString(),
7001
- earnAccountAddress
7061
+ earnAccountAddress,
7062
+ walletAddress
7002
7063
  }
7003
7064
  )
7004
7065
  ] });
@@ -7024,10 +7085,11 @@ function formatPercent(value) {
7024
7085
  function PercentInput({ value, onChange }) {
7025
7086
  const [localValue, setLocalValue] = useState(value.toString());
7026
7087
  const [isFocused, setIsFocused] = useState(false);
7027
- if (!isFocused && localValue !== value.toString()) {
7088
+ const roundedStr = parseFloat(value.toFixed(2)).toString();
7089
+ if (!isFocused && localValue !== roundedStr) {
7028
7090
  const parsed = parseFloat(localValue);
7029
7091
  if (isNaN(parsed) || Math.abs(parsed - value) > 1e-3) {
7030
- setLocalValue(value.toString());
7092
+ setLocalValue(roundedStr);
7031
7093
  }
7032
7094
  }
7033
7095
  return /* @__PURE__ */ jsx(
@@ -7038,7 +7100,7 @@ function PercentInput({ value, onChange }) {
7038
7100
  value: isFocused ? localValue : formatPercent(value).replace("%", ""),
7039
7101
  onFocus: () => {
7040
7102
  setIsFocused(true);
7041
- setLocalValue(value.toString());
7103
+ setLocalValue(parseFloat(value.toFixed(2)).toString());
7042
7104
  },
7043
7105
  onChange: (e) => {
7044
7106
  const raw = e.target.value;
@@ -7162,7 +7224,7 @@ function AllocationEditor({
7162
7224
  currentPos && /* @__PURE__ */ jsxs(Fragment, { children: [
7163
7225
  /* @__PURE__ */ jsx("span", { className: "text-xs font-mono", style: { color: "var(--compass-color-text-secondary)", fontSize: "10px" }, children: formatUSD(currentPos.usdValue) }),
7164
7226
  /* @__PURE__ */ jsxs("span", { style: { color: "var(--compass-color-success)", fontSize: "10px" }, children: [
7165
- currentPos.apy.toFixed(1),
7227
+ currentPos.apy.toFixed(2),
7166
7228
  "%"
7167
7229
  ] })
7168
7230
  ] }),
@@ -7292,6 +7354,7 @@ function RebalancingWidget({
7292
7354
  const { chainId: contextChainId, setChainId } = useChain();
7293
7355
  const CHAIN_ID = chain || contextChainId;
7294
7356
  const { address, signTypedData, isConnected, login, switchChain, walletChainId } = useEmbeddableWallet();
7357
+ const { earnAccountAddress } = useEarnAccount();
7295
7358
  const queryClient = useQueryClient();
7296
7359
  const { portfolio, earnAccountMarkets, isMarketsLoading, isLoading, isError, error, refetch } = useRebalancingData(chain);
7297
7360
  const allowedVariableMarketIds = useMemo(() => {
@@ -7364,7 +7427,7 @@ function RebalancingWidget({
7364
7427
  venueAddress: p.venueAddress,
7365
7428
  venueName: p.venueName,
7366
7429
  token: p.token,
7367
- targetPercent: p.allocationPercent
7430
+ targetPercent: parseFloat(p.allocationPercent.toFixed(2))
7368
7431
  }))
7369
7432
  );
7370
7433
  setHasInitializedTargets(true);
@@ -7404,7 +7467,7 @@ function RebalancingWidget({
7404
7467
  venueAddress: p.venueAddress,
7405
7468
  venueName: p.venueName,
7406
7469
  token: p.token,
7407
- targetPercent: p.allocationPercent
7470
+ targetPercent: parseFloat(p.allocationPercent.toFixed(2))
7408
7471
  }))
7409
7472
  );
7410
7473
  setPreviewPlan(null);
@@ -7420,7 +7483,8 @@ function RebalancingWidget({
7420
7483
  setTargets((prev) => prev.filter((_, i) => i !== index));
7421
7484
  }, []);
7422
7485
  const handleUpdatePercent = useCallback((index, value) => {
7423
- setTargets((prev) => prev.map((t, i) => i === index ? { ...t, targetPercent: Math.max(0, Math.min(100, value)) } : t));
7486
+ const rounded = parseFloat(Math.max(0, Math.min(100, value)).toFixed(2));
7487
+ setTargets((prev) => prev.map((t, i) => i === index ? { ...t, targetPercent: rounded } : t));
7424
7488
  }, []);
7425
7489
  const ensureCorrectChain = useCallback(async () => {
7426
7490
  const targetChainId = EVM_CHAIN_IDS2[CHAIN_ID];
@@ -7845,6 +7909,8 @@ function RebalancingWidget({
7845
7909
  totalUsd: portfolio.totalUsd,
7846
7910
  totalIdleUsd: portfolio.totalIdleUsd,
7847
7911
  idleBalances: portfolio.idleBalances,
7912
+ earnAccountAddress: earnAccountAddress ?? void 0,
7913
+ walletAddress: address ?? void 0,
7848
7914
  onViewPositions: () => setIsEarningsModalOpen(true),
7849
7915
  positionCount: portfolio.positions.length,
7850
7916
  totalEarned,
@@ -8151,7 +8217,25 @@ function RebalancingWidget({
8151
8217
  children: [
8152
8218
  /* @__PURE__ */ jsx(Check, { size: 24, className: "mx-auto mb-2", style: { color: "var(--compass-color-success)" } }),
8153
8219
  /* @__PURE__ */ jsx("p", { className: "font-semibold mb-1", style: { color: "var(--compass-color-success)" }, children: "Rebalance Complete" }),
8154
- /* @__PURE__ */ jsx("p", { className: "text-xs font-mono break-all", style: { color: "var(--compass-color-text-secondary)" }, children: txHash })
8220
+ /* @__PURE__ */ jsxs(
8221
+ "button",
8222
+ {
8223
+ onClick: () => navigator.clipboard.writeText(txHash),
8224
+ className: "inline-flex items-center justify-center gap-1.5 text-xs font-mono break-all mx-auto",
8225
+ style: {
8226
+ color: "var(--compass-color-text-secondary)",
8227
+ background: "none",
8228
+ border: "none",
8229
+ cursor: "pointer",
8230
+ padding: 0
8231
+ },
8232
+ title: "Copy transaction hash",
8233
+ children: [
8234
+ txHash,
8235
+ /* @__PURE__ */ jsx(Copy, { size: 12, className: "flex-shrink-0", style: { color: "var(--compass-color-text-tertiary)" } })
8236
+ ]
8237
+ }
8238
+ )
8155
8239
  ]
8156
8240
  }
8157
8241
  ),
@@ -8496,6 +8580,6 @@ var CHAINS = {
8496
8580
  }
8497
8581
  };
8498
8582
 
8499
- export { AccountBalancesModal, ActionModal, ApiProvider, CHAINS, ChainSwitcher, CompassEarnWidget, CompassProvider, DepositWithdrawForm, EarnAccount, EarnAccountBalance, EarnAccountGuard, PnLSummary, RebalancingWidget, SwapForm, ThemeProvider, TransactionHistory, WalletStatus, themePresets, useChain, useCompassApi, useCompassChain, useCompassWallet, useEarnAccount, useEmbeddableApi, useEmbeddableWallet, useRebalancingData, useSwapQuote, useTheme };
8583
+ export { AccountBalancesModal, ActionModal, ApiProvider, CHAINS, ChainSwitcher, CompassEarnWidget, CompassProvider, CopyableAddress, DepositWithdrawForm, EarnAccount, EarnAccountBalance, EarnAccountGuard, PnLSummary, RebalancingWidget, SwapForm, ThemeProvider, TransactionHistory, WalletStatus, themePresets, useChain, useCompassApi, useCompassChain, useCompassWallet, useEarnAccount, useEmbeddableApi, useEmbeddableWallet, useRebalancingData, useSwapQuote, useTheme };
8500
8584
  //# sourceMappingURL=index.mjs.map
8501
8585
  //# sourceMappingURL=index.mjs.map