@compass-labs/widgets 0.1.20 → 0.1.22

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.d.mts CHANGED
@@ -566,6 +566,8 @@ declare function useAaveData(options?: UseAaveDataOptions): {
566
566
  };
567
567
 
568
568
  type MarketType = 'aave' | 'pendle' | 'vaults';
569
+ /** UI tab type for the market selector */
570
+ type UIMarketTab = 'variable' | 'fixed';
569
571
  interface MarketOption {
570
572
  id: string;
571
573
  name: string;
@@ -605,16 +607,32 @@ interface EarnAccountProps {
605
607
  onDeposit?: (market: MarketOption, amount: number, txHash: string) => void;
606
608
  /** Callback after successful withdraw */
607
609
  onWithdraw?: (market: MarketOption, amount: number, txHash: string) => void;
608
- /** Default market type to show @default 'aave' */
609
- defaultMarketType?: MarketType;
610
- /** Default minimum TVL filter @default 0 */
611
- defaultMinTvl?: number;
610
+ /** Default market tab to show @default 'variable' */
611
+ defaultMarketTab?: UIMarketTab;
612
+ /**
613
+ * List of market IDs to show in Variable tab.
614
+ * If undefined, all variable markets are shown.
615
+ * Pass an empty array to hide all variable markets.
616
+ */
617
+ allowedVariableMarkets?: string[];
618
+ /**
619
+ * List of market IDs to show in Fixed tab.
620
+ * If undefined, all fixed markets are shown.
621
+ * Pass an empty array to hide all fixed markets.
622
+ */
623
+ allowedFixedMarkets?: string[];
624
+ /**
625
+ * Lock the widget to a specific chain.
626
+ * When provided, the chain selector is hidden and the widget uses this chain.
627
+ * Valid values: 'ethereum', 'base', 'arbitrum'
628
+ */
629
+ chain?: string;
612
630
  }
613
631
 
614
632
  /**
615
633
  * EarnAccount widget - A beautiful banking-style USDC savings account.
616
634
  */
617
- declare function EarnAccount({ showHeader, showInterestRate, showTopUpButton, showTrustBadge, compact, title, onDeposit, onWithdraw, defaultMarketType, defaultMinTvl, }: EarnAccountProps): react_jsx_runtime.JSX.Element;
635
+ declare function EarnAccount({ showHeader, showInterestRate, showTopUpButton, showTrustBadge, compact, title, onDeposit, onWithdraw, defaultMarketTab, allowedVariableMarkets, allowedFixedMarkets, chain: chainProp, }: EarnAccountProps): react_jsx_runtime.JSX.Element;
618
636
 
619
637
  type SortOption = 'fixed_apy' | 'tvl' | 'expiry';
620
638
  interface PendleMarketData {
package/dist/index.d.ts CHANGED
@@ -566,6 +566,8 @@ declare function useAaveData(options?: UseAaveDataOptions): {
566
566
  };
567
567
 
568
568
  type MarketType = 'aave' | 'pendle' | 'vaults';
569
+ /** UI tab type for the market selector */
570
+ type UIMarketTab = 'variable' | 'fixed';
569
571
  interface MarketOption {
570
572
  id: string;
571
573
  name: string;
@@ -605,16 +607,32 @@ interface EarnAccountProps {
605
607
  onDeposit?: (market: MarketOption, amount: number, txHash: string) => void;
606
608
  /** Callback after successful withdraw */
607
609
  onWithdraw?: (market: MarketOption, amount: number, txHash: string) => void;
608
- /** Default market type to show @default 'aave' */
609
- defaultMarketType?: MarketType;
610
- /** Default minimum TVL filter @default 0 */
611
- defaultMinTvl?: number;
610
+ /** Default market tab to show @default 'variable' */
611
+ defaultMarketTab?: UIMarketTab;
612
+ /**
613
+ * List of market IDs to show in Variable tab.
614
+ * If undefined, all variable markets are shown.
615
+ * Pass an empty array to hide all variable markets.
616
+ */
617
+ allowedVariableMarkets?: string[];
618
+ /**
619
+ * List of market IDs to show in Fixed tab.
620
+ * If undefined, all fixed markets are shown.
621
+ * Pass an empty array to hide all fixed markets.
622
+ */
623
+ allowedFixedMarkets?: string[];
624
+ /**
625
+ * Lock the widget to a specific chain.
626
+ * When provided, the chain selector is hidden and the widget uses this chain.
627
+ * Valid values: 'ethereum', 'base', 'arbitrum'
628
+ */
629
+ chain?: string;
612
630
  }
613
631
 
614
632
  /**
615
633
  * EarnAccount widget - A beautiful banking-style USDC savings account.
616
634
  */
617
- declare function EarnAccount({ showHeader, showInterestRate, showTopUpButton, showTrustBadge, compact, title, onDeposit, onWithdraw, defaultMarketType, defaultMinTvl, }: EarnAccountProps): react_jsx_runtime.JSX.Element;
635
+ declare function EarnAccount({ showHeader, showInterestRate, showTopUpButton, showTrustBadge, compact, title, onDeposit, onWithdraw, defaultMarketTab, allowedVariableMarkets, allowedFixedMarkets, chain: chainProp, }: EarnAccountProps): react_jsx_runtime.JSX.Element;
618
636
 
619
637
  type SortOption = 'fixed_apy' | 'tvl' | 'expiry';
620
638
  interface PendleMarketData {
package/dist/index.js CHANGED
@@ -3781,31 +3781,45 @@ function AaveMarketsList({
3781
3781
  )
3782
3782
  ] });
3783
3783
  }
3784
- var MARKET_TYPES = [
3785
- { value: "aave", label: "SAFE" },
3786
- { value: "vaults", label: "MODERATE" },
3787
- { value: "pendle", label: "FIXED" }
3784
+ var MARKET_TABS = [
3785
+ { value: "variable", label: "VARIABLE" },
3786
+ { value: "fixed", label: "FIXED" }
3788
3787
  ];
3788
+ var TAB_TO_MARKET_TYPES = {
3789
+ variable: ["aave", "vaults"],
3790
+ fixed: ["pendle"]
3791
+ };
3789
3792
  function MarketSelector({
3790
3793
  markets,
3791
3794
  selectedMarket,
3792
3795
  onMarketSelect,
3793
- marketType,
3794
- onMarketTypeChange,
3795
- minTvl,
3796
- onMinTvlChange,
3797
- isLoading
3796
+ marketTab,
3797
+ onMarketTabChange,
3798
+ isLoading,
3799
+ allowedMarketIds
3798
3800
  }) {
3799
3801
  const [isDropdownOpen, setIsDropdownOpen] = react.useState(false);
3800
- const showTvl = marketType !== "aave";
3802
+ const dropdownRef = react.useRef(null);
3803
+ react.useEffect(() => {
3804
+ function handleClickOutside(e) {
3805
+ if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
3806
+ setIsDropdownOpen(false);
3807
+ }
3808
+ }
3809
+ document.addEventListener("mousedown", handleClickOutside);
3810
+ return () => document.removeEventListener("mousedown", handleClickOutside);
3811
+ }, []);
3812
+ const allowedTypes = TAB_TO_MARKET_TYPES[marketTab];
3813
+ const showTvl = marketTab === "variable";
3801
3814
  const filteredMarkets = react.useMemo(() => {
3802
- return markets.filter((m) => m.type === marketType && (showTvl ? m.tvl >= minTvl : true));
3803
- }, [markets, marketType, minTvl, showTvl]);
3804
- const maxTvl = react.useMemo(() => {
3805
- const typeMarkets = markets.filter((m) => m.type === marketType);
3806
- if (typeMarkets.length === 0) return 0;
3807
- return Math.max(...typeMarkets.map((m) => m.tvl));
3808
- }, [markets, marketType]);
3815
+ return markets.filter((m) => {
3816
+ if (!allowedTypes.includes(m.type)) return false;
3817
+ if (allowedMarketIds !== void 0) {
3818
+ return allowedMarketIds.includes(m.id);
3819
+ }
3820
+ return true;
3821
+ }).sort((a, b) => b.apy - a.apy);
3822
+ }, [markets, allowedTypes, allowedMarketIds]);
3809
3823
  const hasMarkets = filteredMarkets.length > 0;
3810
3824
  const formatTvl = (value) => {
3811
3825
  if (value >= 1e9) return `$${(value / 1e9).toFixed(1)}B`;
@@ -3844,15 +3858,15 @@ function MarketSelector({
3844
3858
  border: "1px solid var(--compass-color-border, rgba(255, 255, 255, 0.1))",
3845
3859
  overflow: "hidden"
3846
3860
  },
3847
- children: MARKET_TYPES.map((type) => /* @__PURE__ */ jsxRuntime.jsx(
3861
+ children: MARKET_TABS.map((tab) => /* @__PURE__ */ jsxRuntime.jsx(
3848
3862
  "button",
3849
3863
  {
3850
- onClick: () => onMarketTypeChange(type.value),
3864
+ onClick: () => onMarketTabChange(tab.value),
3851
3865
  style: {
3852
3866
  flex: 1,
3853
3867
  padding: "6px 8px",
3854
- backgroundColor: marketType === type.value ? "var(--compass-color-primary, #6366f1)" : "var(--compass-color-surface, #12121a)",
3855
- color: marketType === type.value ? "var(--compass-color-primary-text, white)" : "var(--compass-color-text, #e4e4e7)",
3868
+ backgroundColor: marketTab === tab.value ? "var(--compass-color-primary, #6366f1)" : "var(--compass-color-surface, #12121a)",
3869
+ color: marketTab === tab.value ? "var(--compass-color-primary-text, white)" : "var(--compass-color-text, #e4e4e7)",
3856
3870
  border: "none",
3857
3871
  cursor: "pointer",
3858
3872
  fontSize: "12px",
@@ -3860,9 +3874,9 @@ function MarketSelector({
3860
3874
  fontFamily: "var(--compass-font-family)",
3861
3875
  transition: "var(--compass-transition-normal, all 0.2s ease)"
3862
3876
  },
3863
- children: type.label
3877
+ children: tab.label
3864
3878
  },
3865
- type.value
3879
+ tab.value
3866
3880
  ))
3867
3881
  }
3868
3882
  )
@@ -3880,7 +3894,7 @@ function MarketSelector({
3880
3894
  children: "Select Market"
3881
3895
  }
3882
3896
  ),
3883
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [
3897
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: dropdownRef, style: { position: "relative" }, children: [
3884
3898
  /* @__PURE__ */ jsxRuntime.jsxs(
3885
3899
  "button",
3886
3900
  {
@@ -3907,7 +3921,7 @@ function MarketSelector({
3907
3921
  style: {
3908
3922
  color: selectedMarket ? "var(--compass-color-text)" : "var(--compass-color-text-secondary)"
3909
3923
  },
3910
- children: isLoading ? "Loading markets..." : !hasMarkets ? `No markets above ${formatTvl(minTvl)}` : selectedMarket ? selectedMarket.name : "Select a market"
3924
+ children: isLoading ? "Loading markets..." : !hasMarkets ? "No markets available" : selectedMarket ? selectedMarket.name : "Select a market"
3911
3925
  }
3912
3926
  ),
3913
3927
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "var(--compass-spacing-unit)" }, children: [
@@ -4000,7 +4014,7 @@ function MarketSelector({
4000
4014
  ]
4001
4015
  }
4002
4016
  ),
4003
- (showTvl || market.expiry) && /* @__PURE__ */ jsxRuntime.jsxs(
4017
+ (showTvl && market.tvl > 0 || market.expiry) && /* @__PURE__ */ jsxRuntime.jsxs(
4004
4018
  "div",
4005
4019
  {
4006
4020
  style: {
@@ -4009,8 +4023,8 @@ function MarketSelector({
4009
4023
  marginTop: "calc(var(--compass-spacing-unit) * 0.5)"
4010
4024
  },
4011
4025
  children: [
4012
- showTvl && `TVL: ${formatTvl(market.tvl)}`,
4013
- showTvl && market.expiry && " \xB7 ",
4026
+ showTvl && market.tvl > 0 && `TVL: ${formatTvl(market.tvl)}`,
4027
+ showTvl && market.tvl > 0 && market.expiry && " \xB7 ",
4014
4028
  market.expiry && `Expires: ${market.expiry}`
4015
4029
  ]
4016
4030
  }
@@ -4022,56 +4036,6 @@ function MarketSelector({
4022
4036
  }
4023
4037
  )
4024
4038
  ] })
4025
- ] }),
4026
- showTvl && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4027
- /* @__PURE__ */ jsxRuntime.jsxs(
4028
- "div",
4029
- {
4030
- style: {
4031
- display: "flex",
4032
- justifyContent: "space-between",
4033
- alignItems: "center",
4034
- marginBottom: "var(--compass-spacing-unit)"
4035
- },
4036
- children: [
4037
- /* @__PURE__ */ jsxRuntime.jsx(
4038
- "label",
4039
- {
4040
- style: {
4041
- fontSize: "var(--compass-font-size-sm)",
4042
- color: "var(--compass-color-text-secondary)"
4043
- },
4044
- children: "Min TVL"
4045
- }
4046
- ),
4047
- /* @__PURE__ */ jsxRuntime.jsx(
4048
- "span",
4049
- {
4050
- style: {
4051
- fontSize: "var(--compass-font-size-sm)",
4052
- color: "var(--compass-color-text)"
4053
- },
4054
- children: formatTvl(minTvl)
4055
- }
4056
- )
4057
- ]
4058
- }
4059
- ),
4060
- /* @__PURE__ */ jsxRuntime.jsx(
4061
- "input",
4062
- {
4063
- type: "range",
4064
- min: 0,
4065
- max: maxTvl,
4066
- step: 1e5,
4067
- value: minTvl,
4068
- onChange: (e) => onMinTvlChange(Number(e.target.value)),
4069
- style: {
4070
- width: "100%",
4071
- accentColor: "var(--compass-color-primary)"
4072
- }
4073
- }
4074
- )
4075
4039
  ] })
4076
4040
  ]
4077
4041
  }
@@ -4669,12 +4633,15 @@ function EarnAccount({
4669
4633
  title = "Savings Account",
4670
4634
  onDeposit,
4671
4635
  onWithdraw,
4672
- defaultMarketType = "aave",
4673
- defaultMinTvl = 0
4636
+ defaultMarketTab = "variable",
4637
+ allowedVariableMarkets,
4638
+ allowedFixedMarkets,
4639
+ chain: chainProp
4674
4640
  }) {
4675
4641
  const { address, isConnected, login, signTypedData, switchChain, walletChainId } = useEmbeddableWallet();
4676
4642
  const { isDeployed } = useEarnAccount();
4677
- const { chainId: CHAIN_ID } = useChain();
4643
+ const { chainId: contextChainId } = useChain();
4644
+ const CHAIN_ID = chainProp || contextChainId;
4678
4645
  const queryClient = reactQuery.useQueryClient();
4679
4646
  const [activeTab, setActiveTab] = react.useState("deposit");
4680
4647
  const [selectedToken, setSelectedToken] = react.useState("USDC");
@@ -4690,9 +4657,8 @@ function EarnAccount({
4690
4657
  const [fundError, setFundError] = react.useState(null);
4691
4658
  const [fundStatus, setFundStatus] = react.useState("");
4692
4659
  const [isBalancesModalOpen, setIsBalancesModalOpen] = react.useState(false);
4693
- const [marketType, setMarketType] = react.useState(defaultMarketType);
4660
+ const [marketTab, setMarketTab] = react.useState(defaultMarketTab);
4694
4661
  const [selectedMarket, setSelectedMarket] = react.useState(null);
4695
- const [minTvl, setMinTvl] = react.useState(defaultMinTvl);
4696
4662
  const [isEarningsModalOpen, setIsEarningsModalOpen] = react.useState(false);
4697
4663
  react.useEffect(() => {
4698
4664
  setSelectedMarket(null);
@@ -4758,7 +4724,7 @@ function EarnAccount({
4758
4724
  });
4759
4725
  const allPositionData = positionQuery.data || [];
4760
4726
  const totalDepositedBalance = allPositionData.reduce((sum, p) => sum + parseFloat(p.balanceUsd || "0"), 0);
4761
- const earnAccountTotal = parseFloat(earnAccountTotalUsd);
4727
+ const earnAccountTotal = parseFloat(earnAccountTotalUsd) + totalDepositedBalance;
4762
4728
  const aaveMarketsQuery = reactQuery.useQuery({
4763
4729
  queryKey: ["allAaveMarkets", CHAIN_ID],
4764
4730
  queryFn: async () => {
@@ -5161,7 +5127,7 @@ function EarnAccount({
5161
5127
  if (!estimatedOutput || parseFloat(estimatedOutput) <= 0) {
5162
5128
  throw new Error("Invalid swap quote - no output amount");
5163
5129
  }
5164
- const depositAmount = (parseFloat(estimatedOutput) * 0.99).toString();
5130
+ const depositAmount = (parseFloat(estimatedOutput) * 0.99999).toString();
5165
5131
  setStatusMessage(`Preparing swap and deposit...`);
5166
5132
  const bundleActions = [
5167
5133
  {
@@ -5375,7 +5341,7 @@ function EarnAccount({
5375
5341
  ) }),
5376
5342
  /* @__PURE__ */ jsxRuntime.jsx(WalletStatus, { compact: true })
5377
5343
  ] }),
5378
- /* @__PURE__ */ jsxRuntime.jsx(ChainSwitcher, {}),
5344
+ !chainProp && /* @__PURE__ */ jsxRuntime.jsx(ChainSwitcher, {}),
5379
5345
  /* @__PURE__ */ jsxRuntime.jsxs(EarnAccountGuard, { children: [
5380
5346
  /* @__PURE__ */ jsxRuntime.jsxs(
5381
5347
  "div",
@@ -5387,14 +5353,14 @@ function EarnAccount({
5387
5353
  padding: compact ? "var(--compass-spacing-card)" : "calc(var(--compass-spacing-card) * 1.25)"
5388
5354
  },
5389
5355
  children: [
5390
- /* @__PURE__ */ jsxRuntime.jsxs(
5391
- "button",
5392
- {
5393
- onClick: () => setIsBalancesModalOpen(true),
5394
- className: "flex flex-col text-left w-full transition-opacity hover:opacity-80",
5395
- style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" },
5396
- children: [
5397
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
5356
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
5357
+ /* @__PURE__ */ jsxRuntime.jsxs(
5358
+ "button",
5359
+ {
5360
+ onClick: () => setIsBalancesModalOpen(true),
5361
+ className: "flex items-center text-left transition-opacity hover:opacity-80",
5362
+ style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" },
5363
+ children: [
5398
5364
  /* @__PURE__ */ jsxRuntime.jsx(
5399
5365
  "span",
5400
5366
  {
@@ -5404,22 +5370,51 @@ function EarnAccount({
5404
5370
  }
5405
5371
  ),
5406
5372
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 12, style: { color: "var(--compass-color-text-tertiary)" } })
5407
- ] }),
5408
- /* @__PURE__ */ jsxRuntime.jsx(
5409
- "span",
5410
- {
5411
- className: "font-bold",
5412
- style: {
5413
- color: "var(--compass-color-text)",
5414
- fontSize: compact ? "2rem" : "2.5rem",
5415
- lineHeight: "1"
5416
- },
5417
- children: formatCurrency(earnAccountTotal)
5418
- }
5419
- )
5420
- ]
5421
- }
5422
- ),
5373
+ ]
5374
+ }
5375
+ ),
5376
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
5377
+ /* @__PURE__ */ jsxRuntime.jsx(
5378
+ "button",
5379
+ {
5380
+ onClick: () => setIsBalancesModalOpen(true),
5381
+ className: "transition-opacity hover:opacity-80",
5382
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5383
+ "span",
5384
+ {
5385
+ className: "font-bold",
5386
+ style: {
5387
+ color: "var(--compass-color-text)",
5388
+ fontSize: compact ? "2rem" : "2.5rem",
5389
+ lineHeight: "1"
5390
+ },
5391
+ children: formatCurrency(earnAccountTotal)
5392
+ }
5393
+ )
5394
+ }
5395
+ ),
5396
+ showTopUpButton && /* @__PURE__ */ jsxRuntime.jsxs(
5397
+ "button",
5398
+ {
5399
+ onClick: () => setIsFundModalOpen(true),
5400
+ className: "flex items-center font-medium transition-all hover:opacity-80",
5401
+ style: {
5402
+ backgroundColor: "var(--compass-color-surface-elevated, var(--compass-color-surface))",
5403
+ border: "1px solid var(--compass-color-border)",
5404
+ color: "var(--compass-color-text-secondary)",
5405
+ borderRadius: "var(--compass-border-radius-md)",
5406
+ padding: "6px 10px",
5407
+ gap: "4px",
5408
+ fontSize: "12px"
5409
+ },
5410
+ children: [
5411
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { size: 14 }),
5412
+ "Top Up"
5413
+ ]
5414
+ }
5415
+ )
5416
+ ] })
5417
+ ] }),
5423
5418
  /* @__PURE__ */ jsxRuntime.jsx(
5424
5419
  "div",
5425
5420
  {
@@ -5482,14 +5477,13 @@ function EarnAccount({
5482
5477
  markets: allMarkets,
5483
5478
  selectedMarket,
5484
5479
  onMarketSelect: setSelectedMarket,
5485
- marketType,
5486
- onMarketTypeChange: (type) => {
5487
- setMarketType(type);
5480
+ marketTab,
5481
+ onMarketTabChange: (tab) => {
5482
+ setMarketTab(tab);
5488
5483
  setSelectedMarket(null);
5489
5484
  },
5490
- minTvl,
5491
- onMinTvlChange: setMinTvl,
5492
- isLoading: isMarketsLoading
5485
+ isLoading: isMarketsLoading,
5486
+ allowedMarketIds: marketTab === "variable" ? allowedVariableMarkets : allowedFixedMarkets
5493
5487
  }
5494
5488
  ),
5495
5489
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -5749,26 +5743,6 @@ function EarnAccount({
5749
5743
  ] })
5750
5744
  ]
5751
5745
  }
5752
- ),
5753
- showTopUpButton && /* @__PURE__ */ jsxRuntime.jsxs(
5754
- "button",
5755
- {
5756
- onClick: () => setIsFundModalOpen(true),
5757
- className: "w-full font-medium flex items-center justify-center transition-all",
5758
- style: {
5759
- backgroundColor: "var(--compass-color-surface)",
5760
- border: "1px solid var(--compass-color-border)",
5761
- color: "var(--compass-color-text)",
5762
- borderRadius: "var(--compass-border-radius-lg)",
5763
- padding: compact ? "calc(var(--compass-spacing-unit) * 0.75)" : "var(--compass-spacing-card)",
5764
- gap: "calc(var(--compass-spacing-unit) * 0.5)",
5765
- transition: "var(--compass-transition-normal)"
5766
- },
5767
- children: [
5768
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { size: compact ? 16 : 18 }),
5769
- "Top Up"
5770
- ]
5771
- }
5772
5746
  )
5773
5747
  ] }),
5774
5748
  /* @__PURE__ */ jsxRuntime.jsx(