@bze/bze-ui-kit 0.4.1 → 0.4.3

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
@@ -1394,19 +1394,34 @@ var EXCLUDED_MARKETS = {
1394
1394
  // src/constants/ecosystem.ts
1395
1395
  import { LuGlobe, LuCoins, LuChartColumn, LuFlame, LuFactory } from "react-icons/lu";
1396
1396
  var ECOSYSTEM_MENU_LABEL = "Other";
1397
- var ALL_APPS = [
1398
- { name: "Website", href: "https://getbze.com", disabled: false, icon: LuGlobe },
1399
- { name: "Staking", href: "https://staking.getbze.com", disabled: false, icon: LuCoins },
1400
- { name: "DEX", href: "https://dex.getbze.com", disabled: false, icon: LuChartColumn },
1401
- { name: "Burner", href: "https://burner.getbze.com", disabled: false, icon: LuFlame },
1402
- { name: "Factory", href: "#", disabled: true, icon: LuFactory }
1397
+ var DEFAULT_APPS = [
1398
+ { key: "website", name: "Website", href: "https://getbze.com", disabled: false, icon: LuGlobe },
1399
+ { key: "staking", name: "Staking", href: "https://staking.getbze.com", disabled: false, icon: LuCoins },
1400
+ { key: "dex", name: "DEX", href: "https://dex.getbze.com", disabled: false, icon: LuChartColumn },
1401
+ { key: "burner", name: "Burner", href: "https://burner.getbze.com", disabled: false, icon: LuFlame },
1402
+ { key: "factory", name: "Factory", href: "#", disabled: true, icon: LuFactory }
1403
1403
  ];
1404
- var getEcosystemApps = () => {
1405
- const currentHost = process.env.NEXT_PUBLIC_SITE_URL || "";
1406
- if (!currentHost) {
1407
- return ALL_APPS;
1404
+ var getExcludedKeys = () => {
1405
+ const raw = process.env.NEXT_PUBLIC_ECOSYSTEM_EXCLUDED || "";
1406
+ if (!raw.trim()) {
1407
+ return /* @__PURE__ */ new Set();
1408
1408
  }
1409
- return ALL_APPS.filter((app) => app.href !== currentHost);
1409
+ return new Set(raw.split(",").map((k) => k.trim().toLowerCase()).filter(Boolean));
1410
+ };
1411
+ var getEcosystemApps = () => {
1412
+ const excluded = getExcludedKeys();
1413
+ return DEFAULT_APPS.filter((app) => !excluded.has(app.key)).map((app) => {
1414
+ const envKey = app.key.toUpperCase();
1415
+ const linkOverride = process.env[`NEXT_PUBLIC_ECOSYSTEM_LINK_${envKey}`];
1416
+ const labelOverride = process.env[`NEXT_PUBLIC_ECOSYSTEM_LABEL_${envKey}`];
1417
+ return {
1418
+ key: app.key,
1419
+ name: labelOverride || app.name,
1420
+ href: linkOverride || app.href,
1421
+ disabled: linkOverride ? false : app.disabled,
1422
+ icon: app.icon
1423
+ };
1424
+ });
1410
1425
  };
1411
1426
 
1412
1427
  // src/constants/keplr.ts
@@ -3913,9 +3928,104 @@ var useTx = (chainName, isCosmos, isIBC) => {
3913
3928
  };
3914
3929
  };
3915
3930
 
3931
+ // src/hooks/useValidatorLogos.ts
3932
+ import { useCallback as useCallback12, useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
3933
+ var KEYBASE_API_URL = "https://keybase.io/_/api/1.0/user/lookup.json";
3934
+ var LOGOS_STORAGE_KEY = "validator_logos";
3935
+ var LOGOS_TTL = 24 * 60 * 60 * 1e3;
3936
+ var useValidatorLogos = (validators) => {
3937
+ const [logos, setLogos] = useState4({});
3938
+ const [isLoading, setIsLoading] = useState4(false);
3939
+ const fetchedRef = useRef2(false);
3940
+ const validatorCountRef = useRef2(0);
3941
+ const fetchLogos = useCallback12(async (identities) => {
3942
+ if (identities.length === 0) return {};
3943
+ let cached = null;
3944
+ try {
3945
+ const raw = typeof window !== "undefined" ? localStorage.getItem(LOGOS_STORAGE_KEY) : null;
3946
+ if (raw) {
3947
+ const parsed = JSON.parse(raw);
3948
+ if (parsed && typeof parsed === "object" && parsed.data && (!parsed.expiry || Date.now() < parsed.expiry)) {
3949
+ cached = parsed.data;
3950
+ }
3951
+ }
3952
+ } catch (e) {
3953
+ }
3954
+ if (cached) {
3955
+ const allCached = identities.every(
3956
+ (v) => v.operatorAddress in cached
3957
+ );
3958
+ if (allCached) {
3959
+ return cached;
3960
+ }
3961
+ }
3962
+ const result = cached != null ? cached : {};
3963
+ const toFetch = identities.filter((v) => !(v.operatorAddress in result));
3964
+ if (toFetch.length === 0) return result;
3965
+ const chunkSize = 20;
3966
+ for (let i = 0; i < toFetch.length; i += chunkSize) {
3967
+ const chunk = toFetch.slice(i, i + chunkSize);
3968
+ const chunkResults = await Promise.all(
3969
+ chunk.map(async ({ operatorAddress, identity }) => {
3970
+ var _a2, _b2, _c, _d, _e;
3971
+ if (!identity) {
3972
+ return { operatorAddress, url: "" };
3973
+ }
3974
+ try {
3975
+ const resp = await fetch(
3976
+ `${KEYBASE_API_URL}?key_suffix=${encodeURIComponent(identity)}&fields=pictures`
3977
+ );
3978
+ const data = await resp.json();
3979
+ const url = (_e = (_d = (_c = (_b2 = (_a2 = data == null ? void 0 : data.them) == null ? void 0 : _a2[0]) == null ? void 0 : _b2.pictures) == null ? void 0 : _c.primary) == null ? void 0 : _d.url) != null ? _e : "";
3980
+ return { operatorAddress, url };
3981
+ } catch (e) {
3982
+ return { operatorAddress, url: "" };
3983
+ }
3984
+ })
3985
+ );
3986
+ for (const { operatorAddress, url } of chunkResults) {
3987
+ result[operatorAddress] = url;
3988
+ }
3989
+ if (i + chunkSize < toFetch.length) {
3990
+ await new Promise((resolve) => setTimeout(resolve, 500));
3991
+ }
3992
+ }
3993
+ try {
3994
+ if (typeof window !== "undefined") {
3995
+ localStorage.setItem(LOGOS_STORAGE_KEY, JSON.stringify({
3996
+ data: result,
3997
+ expiry: Date.now() + LOGOS_TTL
3998
+ }));
3999
+ }
4000
+ } catch (e) {
4001
+ }
4002
+ return result;
4003
+ }, []);
4004
+ useEffect3(() => {
4005
+ if (!validators || validators.length === 0) return;
4006
+ if (fetchedRef.current && validatorCountRef.current === validators.length) return;
4007
+ const identities = validators.map((v) => {
4008
+ var _a2, _b2;
4009
+ return {
4010
+ operatorAddress: v.operator_address,
4011
+ identity: (_b2 = (_a2 = v.description) == null ? void 0 : _a2.identity) != null ? _b2 : ""
4012
+ };
4013
+ });
4014
+ setIsLoading(true);
4015
+ fetchedRef.current = true;
4016
+ validatorCountRef.current = validators.length;
4017
+ fetchLogos(identities).then((result) => {
4018
+ setLogos(result);
4019
+ }).catch(console.error).finally(() => {
4020
+ setIsLoading(false);
4021
+ });
4022
+ }, [validators, fetchLogos]);
4023
+ return { logos, isLoading };
4024
+ };
4025
+
3916
4026
  // src/components/highlight.tsx
3917
4027
  import { Text } from "@chakra-ui/react";
3918
- import { useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
4028
+ import { useEffect as useEffect4, useRef as useRef3, useState as useState5 } from "react";
3919
4029
  import { jsx as jsx2 } from "react/jsx-runtime";
3920
4030
  var HighlightText = (_a2) => {
3921
4031
  var _b2 = _a2, {
@@ -3931,14 +4041,14 @@ var HighlightText = (_a2) => {
3931
4041
  "highlightIntensity",
3932
4042
  "children"
3933
4043
  ]);
3934
- const [isHighlighted, setIsHighlighted] = useState4(false);
3935
- const isMountedRef = useRef2(false);
3936
- const timeoutRef = useRef2(void 0);
4044
+ const [isHighlighted, setIsHighlighted] = useState5(false);
4045
+ const isMountedRef = useRef3(false);
4046
+ const timeoutRef = useRef3(void 0);
3937
4047
  const childrenString = String(children);
3938
- const previousValueRef = useRef2(childrenString);
4048
+ const previousValueRef = useRef3(childrenString);
3939
4049
  const highlightOpacity = highlightIntensity === "subtle" ? "15" : "50";
3940
4050
  const boxShadowStrength = highlightIntensity === "subtle" ? "10" : "25";
3941
- useEffect3(() => {
4051
+ useEffect4(() => {
3942
4052
  if (!isMountedRef.current) {
3943
4053
  isMountedRef.current = true;
3944
4054
  if (highlightOnMount) {
@@ -3984,10 +4094,10 @@ var HighlightText = (_a2) => {
3984
4094
  // src/components/sidebar/sidebar.tsx
3985
4095
  import { Icon, IconButton, Portal as Portal2 } from "@chakra-ui/react";
3986
4096
  import { LuX } from "react-icons/lu";
3987
- import { useState as useState5 } from "react";
4097
+ import { useState as useState6 } from "react";
3988
4098
  import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
3989
4099
  var Sidebar = ({ children, trigger, ariaLabel }) => {
3990
- const [isOpen, setIsOpen] = useState5(false);
4100
+ const [isOpen, setIsOpen] = useState6(false);
3991
4101
  const handleTriggerClick = () => {
3992
4102
  setIsOpen(true);
3993
4103
  };
@@ -4111,7 +4221,7 @@ import {
4111
4221
  } from "@chakra-ui/react";
4112
4222
  import { Select, Portal as Portal3 } from "@chakra-ui/react";
4113
4223
  import { useTheme } from "next-themes";
4114
- import { useState as useState6, useEffect as useEffect4, useMemo as useMemo13, useCallback as useCallback12 } from "react";
4224
+ import { useState as useState7, useEffect as useEffect5, useMemo as useMemo13, useCallback as useCallback13 } from "react";
4115
4225
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
4116
4226
  var SettingsSidebarContent = ({ accentColor = "blue" }) => {
4117
4227
  const { setTheme, resolvedTheme } = useTheme();
@@ -4119,19 +4229,19 @@ var SettingsSidebarContent = ({ accentColor = "blue" }) => {
4119
4229
  const { settings, isLoaded, updateEndpoints, updatePreferredFeeDenom, defaultSettings } = useSettings();
4120
4230
  const { connectionType } = useConnectionType();
4121
4231
  const { feeTokens, isLoading: feeTokensLoading } = useFeeTokens();
4122
- const [restEndpoint, setRestEndpoint] = useState6("");
4123
- const [rpcEndpoint, setRpcEndpoint] = useState6("");
4124
- const [isValidating, setIsValidating] = useState6(false);
4125
- const [validationResults, setValidationResults] = useState6({});
4126
- const [preferredFeeDenom, setPreferredFeeDenom] = useState6(void 0);
4127
- useEffect4(() => {
4232
+ const [restEndpoint, setRestEndpoint] = useState7("");
4233
+ const [rpcEndpoint, setRpcEndpoint] = useState7("");
4234
+ const [isValidating, setIsValidating] = useState7(false);
4235
+ const [validationResults, setValidationResults] = useState7({});
4236
+ const [preferredFeeDenom, setPreferredFeeDenom] = useState7(void 0);
4237
+ useEffect5(() => {
4128
4238
  if (isLoaded) {
4129
4239
  setRestEndpoint(settings.endpoints.restEndpoint);
4130
4240
  setRpcEndpoint(settings.endpoints.rpcEndpoint);
4131
4241
  setPreferredFeeDenom(settings.preferredFeeDenom || getChainNativeAssetDenom());
4132
4242
  }
4133
4243
  }, [isLoaded, settings]);
4134
- const handleValidateEndpoints = useCallback12(async (rest, rpc) => {
4244
+ const handleValidateEndpoints = useCallback13(async (rest, rpc) => {
4135
4245
  setIsValidating(true);
4136
4246
  setValidationResults({});
4137
4247
  try {
@@ -4151,7 +4261,7 @@ var SettingsSidebarContent = ({ accentColor = "blue" }) => {
4151
4261
  setTimeout(() => setValidationResults({}), 1e4);
4152
4262
  }
4153
4263
  }, []);
4154
- const handleSaveSettings = useCallback12(async (rest, rpc, feeDenom) => {
4264
+ const handleSaveSettings = useCallback13(async (rest, rpc, feeDenom) => {
4155
4265
  setValidationResults({});
4156
4266
  const results = await validateEndpoints(rest, rpc);
4157
4267
  if (!results.isValid) {
@@ -4171,7 +4281,7 @@ var SettingsSidebarContent = ({ accentColor = "blue" }) => {
4171
4281
  toast.success("Success!", "Settings have been saved.");
4172
4282
  }
4173
4283
  }, []);
4174
- const handleResetToDefaults = useCallback12(() => {
4284
+ const handleResetToDefaults = useCallback13(() => {
4175
4285
  setRestEndpoint(defaultSettings.endpoints.restEndpoint);
4176
4286
  setRpcEndpoint(defaultSettings.endpoints.rpcEndpoint);
4177
4287
  setPreferredFeeDenom(defaultSettings.preferredFeeDenom);
@@ -4204,7 +4314,7 @@ var SettingsSidebarContent = ({ accentColor = "blue" }) => {
4204
4314
  name: token.ticker || token.name
4205
4315
  }))
4206
4316
  }), [feeTokens]);
4207
- const handleFeeTokenChange = useCallback12((denom) => {
4317
+ const handleFeeTokenChange = useCallback13((denom) => {
4208
4318
  setPreferredFeeDenom(denom || void 0);
4209
4319
  }, []);
4210
4320
  const hasUnsavedChanges = restEndpoint !== settings.endpoints.restEndpoint || rpcEndpoint !== settings.endpoints.rpcEndpoint || preferredFeeDenom !== settings.preferredFeeDenom;
@@ -4380,7 +4490,7 @@ import {
4380
4490
  VStack as VStack2
4381
4491
  } from "@chakra-ui/react";
4382
4492
  import { LuCopy, LuExternalLink, LuX as LuX2 } from "react-icons/lu";
4383
- import { useCallback as useCallback13, useEffect as useEffect5, useMemo as useMemo14, useRef as useRef3, useState as useState7 } from "react";
4493
+ import { useCallback as useCallback14, useEffect as useEffect6, useMemo as useMemo14, useRef as useRef4, useState as useState8 } from "react";
4384
4494
  import { WalletState } from "@interchain-kit/core";
4385
4495
  import BigNumber14 from "bignumber.js";
4386
4496
  import { cosmos } from "@bze/bzejs";
@@ -4401,7 +4511,7 @@ var validateAmount = (amount, coin, onError) => {
4401
4511
  }
4402
4512
  };
4403
4513
  var BalanceItem = ({ asset, onClick, accentColor }) => {
4404
- const [showSendButton, setShowSendButton] = useState7(false);
4514
+ const [showSendButton, setShowSendButton] = useState8(false);
4405
4515
  const formattedBalanceAmount = useMemo14(() => {
4406
4516
  var _a2;
4407
4517
  return prettyAmount(uAmountToBigNumberAmount(asset.amount, (_a2 = asset.decimals) != null ? _a2 : 0));
@@ -4458,14 +4568,14 @@ var BalanceItem = ({ asset, onClick, accentColor }) => {
4458
4568
  );
4459
4569
  };
4460
4570
  var SendForm = ({ balances, onClose, selectedTicker, accentColor }) => {
4461
- const [isLoading, setIsLoading] = useState7(false);
4462
- const [selectedCoin, setSelectedCoin] = useState7();
4463
- const [sendAmount, setSendAmount] = useState7("");
4464
- const [sendAmountError, setSendAmountError] = useState7("");
4465
- const [recipient, setRecipient] = useState7("");
4466
- const [recipientError, setRecipientError] = useState7("");
4467
- const [memo, setMemo] = useState7("");
4468
- const [memoError, setMemoError] = useState7("");
4571
+ const [isLoading, setIsLoading] = useState8(false);
4572
+ const [selectedCoin, setSelectedCoin] = useState8();
4573
+ const [sendAmount, setSendAmount] = useState8("");
4574
+ const [sendAmountError, setSendAmountError] = useState8("");
4575
+ const [recipient, setRecipient] = useState8("");
4576
+ const [recipientError, setRecipientError] = useState8("");
4577
+ const [memo, setMemo] = useState8("");
4578
+ const [memoError, setMemoError] = useState8("");
4469
4579
  const { toast } = useToast();
4470
4580
  const { status, address } = useChain3(getChainName());
4471
4581
  const { tx } = useSDKTx(getChainName());
@@ -4482,13 +4592,13 @@ var SendForm = ({ balances, onClose, selectedTicker, accentColor }) => {
4482
4592
  const isValidForm = useMemo14(() => {
4483
4593
  return selectedCoin && memoError === "" && recipientError === "" && sendAmountError === "" && sendAmount !== "" && recipient !== "";
4484
4594
  }, [selectedCoin, memoError, recipientError, sendAmountError, sendAmount, recipient]);
4485
- const resetSendForm = useCallback13(() => {
4595
+ const resetSendForm = useCallback14(() => {
4486
4596
  setSelectedCoin(void 0);
4487
4597
  setSendAmount("");
4488
4598
  setRecipient("");
4489
4599
  setMemo("");
4490
4600
  }, []);
4491
- const handleSend = useCallback13(async () => {
4601
+ const handleSend = useCallback14(async () => {
4492
4602
  var _a2, _b2;
4493
4603
  if (!isValidForm) {
4494
4604
  toast.error("Can not send coins!", "Please check the input data.");
@@ -4513,11 +4623,11 @@ var SendForm = ({ balances, onClose, selectedTicker, accentColor }) => {
4513
4623
  setIsLoading(false);
4514
4624
  onClose();
4515
4625
  }, [address, memo, onClose, recipient, selectedCoin, sendAmount, status]);
4516
- const handleCancel = useCallback13(() => {
4626
+ const handleCancel = useCallback14(() => {
4517
4627
  resetSendForm();
4518
4628
  onClose();
4519
4629
  }, [onClose, resetSendForm]);
4520
- const onRecipientChange = useCallback13((recipient2) => {
4630
+ const onRecipientChange = useCallback14((recipient2) => {
4521
4631
  setRecipient(recipient2);
4522
4632
  if (recipient2.length === 0) {
4523
4633
  setRecipientError("");
@@ -4530,11 +4640,11 @@ var SendForm = ({ balances, onClose, selectedTicker, accentColor }) => {
4530
4640
  setRecipientError(validate.message);
4531
4641
  }
4532
4642
  }, []);
4533
- const onAmountChange = useCallback13((amount) => {
4643
+ const onAmountChange = useCallback14((amount) => {
4534
4644
  setSendAmount(sanitizeNumberInput(amount));
4535
4645
  setSendAmountError("");
4536
4646
  }, []);
4537
- const onCoinSelectChange = useCallback13((ticker) => {
4647
+ const onCoinSelectChange = useCallback14((ticker) => {
4538
4648
  if (ticker === "") return;
4539
4649
  const selectedCoin2 = balances.find((item) => item.ticker === ticker);
4540
4650
  if (selectedCoin2) {
@@ -4542,13 +4652,13 @@ var SendForm = ({ balances, onClose, selectedTicker, accentColor }) => {
4542
4652
  validateAmount(sendAmount, selectedCoin2, setSendAmountError);
4543
4653
  }
4544
4654
  }, [sendAmount, balances]);
4545
- const setMaxAmount = useCallback13(() => {
4655
+ const setMaxAmount = useCallback14(() => {
4546
4656
  if (!selectedCoin) return;
4547
4657
  const maxAmount = uAmountToBigNumberAmount(selectedCoin.amount, selectedCoin.decimals);
4548
4658
  onAmountChange(maxAmount.toString());
4549
4659
  validateAmount(maxAmount.toString(), selectedCoin, setSendAmountError);
4550
4660
  }, [selectedCoin, onAmountChange]);
4551
- const onMemoChange = useCallback13((memo2) => {
4661
+ const onMemoChange = useCallback14((memo2) => {
4552
4662
  setMemo(memo2);
4553
4663
  if (memo2.length > 256) {
4554
4664
  setMemoError("Memo must be less than or equal to 256 characters");
@@ -4556,7 +4666,7 @@ var SendForm = ({ balances, onClose, selectedTicker, accentColor }) => {
4556
4666
  setMemoError("");
4557
4667
  }
4558
4668
  }, []);
4559
- useEffect5(() => {
4669
+ useEffect6(() => {
4560
4670
  if (selectedTicker !== "") {
4561
4671
  onCoinSelectChange(selectedTicker);
4562
4672
  }
@@ -4719,11 +4829,11 @@ var SendForm = ({ balances, onClose, selectedTicker, accentColor }) => {
4719
4829
  ] });
4720
4830
  };
4721
4831
  var WalletSidebarContent = ({ accentColor = "blue" }) => {
4722
- const [viewState, setViewState] = useState7("balances");
4723
- const [isDisconnecting, setIsDisconnecting] = useState7(false);
4724
- const [showCopiedTooltip, setShowCopiedTooltip] = useState7(false);
4725
- const [clickedBalance, setClickedBalance] = useState7("");
4726
- const copyButtonRef = useRef3(null);
4832
+ const [viewState, setViewState] = useState8("balances");
4833
+ const [isDisconnecting, setIsDisconnecting] = useState8(false);
4834
+ const [showCopiedTooltip, setShowCopiedTooltip] = useState8(false);
4835
+ const [clickedBalance, setClickedBalance] = useState8("");
4836
+ const copyButtonRef = useRef4(null);
4727
4837
  const {
4728
4838
  status,
4729
4839
  username,
@@ -4759,15 +4869,15 @@ var WalletSidebarContent = ({ accentColor = "blue" }) => {
4759
4869
  setShowCopiedTooltip(true);
4760
4870
  setTimeout(() => setShowCopiedTooltip(false), 2e3);
4761
4871
  };
4762
- const handleCancel = useCallback13(() => {
4872
+ const handleCancel = useCallback14(() => {
4763
4873
  setViewState("balances");
4764
4874
  setClickedBalance("");
4765
4875
  }, []);
4766
- const onBalanceClick = useCallback13((ticker) => {
4876
+ const onBalanceClick = useCallback14((ticker) => {
4767
4877
  setClickedBalance(ticker);
4768
4878
  setViewState("send");
4769
4879
  }, []);
4770
- const handleDisconnectAll = useCallback13(async () => {
4880
+ const handleDisconnectAll = useCallback14(async () => {
4771
4881
  setIsDisconnecting(true);
4772
4882
  try {
4773
4883
  console.log("Disconnected from all chains");
@@ -5219,6 +5329,7 @@ export {
5219
5329
  useSettings,
5220
5330
  useSigningClient,
5221
5331
  useToast,
5332
+ useValidatorLogos,
5222
5333
  validateBZEBech32Address,
5223
5334
  validateBech32Address,
5224
5335
  validateEndpoints,