@tuwaio/nova-connect 1.0.0-fix-test-alpha.61.e356934 → 1.0.0-fix-test-alpha.63.15a38cd

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![NPM Version](https://img.shields.io/npm/v/@tuwaio/nova-connect.svg)](https://www.npmjs.com/package/@tuwaio/nova-connect)
4
4
  [![License](https://img.shields.io/npm/l/@tuwaio/nova-connect.svg)](./LICENSE)
5
- [![Build Status](https://img.shields.io/github/actions/workflow/status/TuwaIO/nova-connect/release.yml?branch=main)](https://github.com/TuwaIO/nova-uikit/actions)
5
+ [![Build Status](https://img.shields.io/github/actions/workflow/status/TuwaIO/nova-uikit/release.yml?branch=main)](https://github.com/TuwaIO/nova-uikit/actions)
6
6
 
7
7
  Feature-rich React components for connecting Web3 wallets with a comprehensive customization system and support for multiple blockchain networks.
8
8
 
@@ -110,10 +110,11 @@ export function Providers({ children }: { children: ReactNode }) {
110
110
 
111
111
  ```tsx
112
112
  import { NovaConnectButton } from '@tuwaio/nova-connect';
113
- import { useSatelliteConnectStore } from '@tuwaio/satellite-react';
113
+ import { SatelliteStoreContext } from '@tuwaio/satellite-react';
114
+ import { useContext } from 'react';
114
115
 
115
116
  function App() {
116
- const store = useSatelliteConnectStore();
117
+ const store = useContext(SatelliteStoreContext);
117
118
 
118
119
  return (
119
120
  <div>
@@ -1,2 +1,2 @@
1
- 'use strict';var novaCore=require('@tuwaio/nova-core'),orbitCore=require('@tuwaio/orbit-core'),react=require('react');function z(w){let{abbreviateSymbols:r=12,maxNameLength:y=30,autoRetry:C=false,retryDelay:u=3e3,store:f}=w,n=f.getState().activeWallet,N=f.getState().getAdapter,a=react.useMemo(()=>n?.address,[n?.address]),l=react.useMemo(()=>n?.walletType,[n?.walletType]),e=react.useMemo(()=>l?N(orbitCore.getAdapterFromWalletType(l??`${orbitCore.OrbitAdapter.EVM}:not-connected`)):null,[N,l]),[t,o]=react.useState(null),[p,m]=react.useState(null),[W,g]=react.useState(false),[b,s]=react.useState(null),c=react.useRef(null),v=react.useRef(null),x=react.useMemo(()=>{if(!e)return {hasNameResolver:false,hasAvatarResolver:false};let d="getName"in e&&typeof e.getName=="function",i="getAvatar"in e&&typeof e.getAvatar=="function";return {hasNameResolver:d,hasAvatarResolver:i}},[e]),A=react.useCallback(()=>{c.current&&(c.current.abort(),c.current=null),v.current!==null&&(clearTimeout(v.current),v.current=null);},[]),h=react.useCallback(async()=>{if(A(),!a||!e||!x.hasNameResolver){o(null),m(null),g(false),s(null);return}c.current=new AbortController;let{signal:d}=c.current;g(true),s(null),o(null),m(null);try{if(d.aborted)return;let i=await e.getName?.(a);if(d.aborted)return;if(i&&(o(i),x.hasAvatarResolver))try{let B=await e.getAvatar?.(i);d.aborted||m(B??null);}catch(B){console.warn("Failed to fetch avatar:",B),d.aborted||m(null);}}catch(i){if(d.aborted)return;let B=i instanceof Error?i.message:"Failed to fetch name service data";console.error("Failed to fetch name service data:",i),s(B),o(null),m(null),C&&(v.current=setTimeout(()=>{h();},u));}finally{d.aborted||g(false);}},[a,e,x,C,u,A]),I=react.useCallback(()=>{s(null),h();},[h]);react.useEffect(()=>(h(),A),[h,A]),react.useEffect(()=>A,[A]);let M=react.useMemo(()=>t?t.length>y?novaCore.textCenterEllipsis(t,r,r):t:a?novaCore.textCenterEllipsis(a,r,r):void 0,[t,a,y,r]);return {ensName:t,ensAvatar:p,isLoading:W,ensNameAbbreviated:M,error:b,retry:I}}function X({store:w}){let[r,y]=react.useState({}),[C,u]=react.useState(false),f=react.useRef(null),n=w.getState().activeWallet,N=w.getState().getAdapter,a=n?.address,l=n?.chainId,e=react.useMemo(()=>a&&l?`${a}-${l}`:null,[a,l]),t=react.useMemo(()=>n?.walletType?N(orbitCore.getAdapterFromWalletType(n.walletType)):null,[N,n?.walletType]),o=react.useMemo(()=>t&&"getBalance"in t&&typeof t.getBalance=="function",[t]),p=react.useCallback(async(g=false)=>{if(!a||!t||!l||!e||!o){u(false);return}let b=`${e}-${Date.now()}`;if(f.current=b,!g&&r[e]){u(false);return}u(true);try{let s=await t.getBalance(a,l);f.current===b&&y(c=>({...c,[e]:s}));}catch(s){console.error(`Failed to fetch native balance for ${e}:`,s),g&&f.current===b&&y(c=>{let v={...c};return delete v[e],v});}finally{f.current===b&&u(false);}},[a,t,l,e,o,r]),m=react.useCallback(()=>{p(true);},[p]);return react.useEffect(()=>{e&&o&&!r[e]?p(false):(!e||!o)&&u(false);},[e,o,r,p]),react.useEffect(()=>()=>{f.current=null;},[]),{balance:react.useMemo(()=>e&&r[e]||null,[e,r]),isLoading:C,refetch:m}}exports.useGetWalletNameAndAvatar=z;exports.useWalletNativeBalance=X;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var novaCore=require('@tuwaio/nova-core'),orbitCore=require('@tuwaio/orbit-core'),react=require('react');function z(m){let{abbreviateSymbols:e=12,maxNameLength:n=30,autoRetry:y=false,retryDelay:B=3e3,store:v}=m,c=v.getState().getAdapter,l=react.useMemo(()=>m.activeWallet?.address,[m.activeWallet?.address]),t=react.useMemo(()=>m.activeWallet?.walletType,[m.activeWallet?.walletType]),a=react.useMemo(()=>t?c(orbitCore.getAdapterFromWalletType(t??`${orbitCore.OrbitAdapter.EVM}:not-connected`)):null,[c,t]),[r,o]=react.useState(null),[T,p]=react.useState(null),[C,i]=react.useState(false),[b,u]=react.useState(null),d=react.useRef(null),R=react.useRef(null),x=react.useMemo(()=>{if(!a)return {hasNameResolver:false,hasAvatarResolver:false};let f="getName"in a&&typeof a.getName=="function",s="getAvatar"in a&&typeof a.getAvatar=="function";return {hasNameResolver:f,hasAvatarResolver:s}},[a]),g=react.useCallback(()=>{d.current&&(d.current.abort(),d.current=null),R.current!==null&&(clearTimeout(R.current),R.current=null);},[]),N=react.useCallback(async()=>{if(g(),!l||!a||!x.hasNameResolver){o(null),p(null),i(false),u(null);return}d.current=new AbortController;let{signal:f}=d.current;i(true),u(null),o(null),p(null);try{if(f.aborted)return;let s=await a.getName?.(l);if(f.aborted)return;if(s&&(o(s),x.hasAvatarResolver))try{let h=await a.getAvatar?.(s);f.aborted||p(h??null);}catch(h){console.warn("Failed to fetch avatar:",h),f.aborted||p(null);}}catch(s){if(f.aborted)return;let h=s instanceof Error?s.message:"Failed to fetch name service data";console.error("Failed to fetch name service data:",s),u(h),o(null),p(null),y&&(R.current=setTimeout(()=>{N();},B));}finally{f.aborted||i(false);}},[l,a,x,y,B,g]),$=react.useCallback(()=>{u(null),N();},[N]);react.useEffect(()=>(N(),g),[N,g]),react.useEffect(()=>g,[g]);let M=react.useMemo(()=>r?r.length>n?novaCore.textCenterEllipsis(r,e,e):r:l?novaCore.textCenterEllipsis(l,e,e):void 0,[r,l,n,e]);return {ensName:r,ensAvatar:T,isLoading:C,ensNameAbbreviated:M,error:b,retry:$}}function W({store:m,activeWallet:e}){let[n,y]=react.useState({}),[B,v]=react.useState(false),c=react.useRef(null),l=m.getState().getAdapter,t=react.useMemo(()=>e?.chainId&&e?.address?`${e.address}-${e.chainId}`:null,[e?.chainId,e?.address]),a=react.useMemo(()=>e?.walletType?l(orbitCore.getAdapterFromWalletType(e.walletType)):null,[l,e?.walletType]),r=react.useMemo(()=>a&&"getBalance"in a&&typeof a.getBalance=="function",[a]),o=react.useCallback(async(C=false)=>{if(!e?.address||!a||!e?.chainId||!t||!r){v(false);return}let i=`${t}-${Date.now()}`;if(c.current=i,!C&&n[t]){v(false);return}v(true);try{let b=await a.getBalance(e.address,e.chainId);c.current===i&&y(u=>({...u,[t]:b}));}catch(b){console.error(`Failed to fetch native balance for ${t}:`,b),C&&c.current===i&&y(u=>{let d={...u};return delete d[t],d});}finally{c.current===i&&v(false);}},[e?.address,a,e?.chainId,t,r,n]),T=react.useCallback(()=>{o(true);},[o]);return react.useEffect(()=>{t&&r&&!n[t]?o(false):(!t||!r)&&v(false);},[t,r,n,o]),react.useEffect(()=>()=>{c.current=null;},[]),{balance:react.useMemo(()=>t&&n[t]||null,[t,n]),isLoading:B,refetch:T}}exports.useGetWalletNameAndAvatar=z;exports.useWalletNativeBalance=W;//# sourceMappingURL=index.cjs.map
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/useGetWalletNameAndAvatar.ts","../../src/hooks/useWalletNativeBalance.ts"],"names":["useGetWalletNameAndAvatar","options","abbreviateSymbols","maxNameLength","autoRetry","retryDelay","store","wallet","getAdapter","walletAddress","useMemo","walletType","foundAdapter","getAdapterFromWalletType","OrbitAdapter","ensName","setEnsName","useState","ensAvatar","setEnsAvatar","isLoading","setIsLoading","error","setError","abortControllerRef","useRef","retryTimeoutRef","adapterCapabilities","hasNameResolver","hasAvatarResolver","cleanup","useCallback","fetchNameData","signal","name","avatar","avatarError","errorMessage","retry","useEffect","ensNameAbbreviated","textCenterEllipsis","useWalletNativeBalance","balanceCache","setBalanceCache","fetchOperationRef","currentChainId","cacheKey","hasBalanceResolver","fetchBalance","forceRefresh","operationId","balanceResult","prevCache","newCache","refetch"],"mappings":"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","file":"index.cjs","sourcesContent":["import { textCenterEllipsis } from '@tuwaio/nova-core';\nimport { getAdapterFromWalletType, OrbitAdapter } from '@tuwaio/orbit-core';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { NovaConnectProviderProps } from './useNovaConnect';\n\nexport interface WalletNameAndAvatarData {\n /** The resolved name from the Name Service (e.g., ENS, like \"alice.eth\"), or null if not found. */\n ensName: string | null;\n /** The URL of the avatar associated with the name, or null if not found. */\n ensAvatar: string | null;\n /** True while the name service data is being fetched. */\n isLoading: boolean;\n /** A truncated version of the name for display, or the abbreviated address if no name. */\n ensNameAbbreviated: string | undefined;\n /** Error message if the name resolution failed. */\n error: string | null;\n /** Function to retry the name resolution manually. */\n retry: () => void;\n}\n\ninterface UseGetWalletNameAndAvatarOptions extends Pick<NovaConnectProviderProps, 'store'> {\n /** Number of characters to show on each side when abbreviating (default: 12) */\n abbreviateSymbols?: number;\n /** Maximum length before abbreviation is applied (default: 30) */\n maxNameLength?: number;\n /** Whether to automatically retry on failure (default: false) */\n autoRetry?: boolean;\n /** Retry delay in milliseconds (default: 3000) */\n retryDelay?: number;\n}\n\n/**\n * A custom hook to fetch the Name Service (e.g., ENS) name and avatar\n * for the currently active wallet.\n *\n * This hook automatically detects the active wallet and its corresponding\n * adapter via the `useSatelliteConnectStore` and attempts to resolve the\n * wallet address to a human-readable name and avatar.\n *\n * @param options Configuration options for the hook\n * @returns An object containing the resolved name, avatar, loading state, and utility functions\n *\n * @example\n * ```typescript\n * import { useGetWalletNameAndAvatar } from './useGetWalletNameAndAvatar';\n *\n * function DisplayWalletInfo() {\n * const { ensName, ensAvatar, isLoading, ensNameAbbreviated, error, retry } = useGetWalletNameAndAvatar({\n * abbreviateSymbols: 8,\n * maxNameLength: 25\n * });\n *\n * if (isLoading) {\n * return <div>Resolving name...</div>;\n * }\n *\n * if (error) {\n * return <div>Error: {error} <button onClick={retry}>Retry</button></div>;\n * }\n *\n * return (\n * <div className=\"wallet-info\">\n * {ensAvatar && <img src={ensAvatar} alt=\"Wallet Avatar\" />}\n * <p title={ensName || ''}>{ensNameAbbreviated || 'No Name Found'}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useGetWalletNameAndAvatar(options: UseGetWalletNameAndAvatarOptions): WalletNameAndAvatarData {\n const { abbreviateSymbols = 12, maxNameLength = 30, autoRetry = false, retryDelay = 3000, store } = options;\n\n // Store state selectors - memoized for performance\n const wallet = store.getState().activeWallet;\n const getAdapter = store.getState().getAdapter;\n\n // Memoize wallet address and adapter for dependency tracking\n const walletAddress = useMemo(() => wallet?.address, [wallet?.address]);\n const walletType = useMemo(() => wallet?.walletType, [wallet?.walletType]);\n\n const foundAdapter = useMemo(() => {\n if (!walletType) return null;\n return getAdapter(getAdapterFromWalletType(walletType ?? `${OrbitAdapter.EVM}:not-connected`));\n }, [getAdapter, walletType]);\n\n // State variables\n const [ensName, setEnsName] = useState<string | null>(null);\n const [ensAvatar, setEnsAvatar] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Refs for cleanup and retry functionality\n const abortControllerRef = useRef<AbortController | null>(null);\n const retryTimeoutRef = useRef<number | null>(null);\n\n // Memoize adapter capabilities\n const adapterCapabilities = useMemo(() => {\n if (!foundAdapter) {\n return { hasNameResolver: false, hasAvatarResolver: false };\n }\n\n const hasNameResolver = 'getName' in foundAdapter && typeof foundAdapter.getName === 'function';\n const hasAvatarResolver = 'getAvatar' in foundAdapter && typeof foundAdapter.getAvatar === 'function';\n\n return { hasNameResolver, hasAvatarResolver };\n }, [foundAdapter]);\n\n // Cleanup function\n const cleanup = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n if (retryTimeoutRef.current !== null) {\n clearTimeout(retryTimeoutRef.current);\n retryTimeoutRef.current = null;\n }\n }, []);\n\n // Main fetch function\n const fetchNameData = useCallback(async () => {\n cleanup();\n\n // Exit conditions\n if (!walletAddress || !foundAdapter || !adapterCapabilities.hasNameResolver) {\n setEnsName(null);\n setEnsAvatar(null);\n setIsLoading(false);\n setError(null);\n return;\n }\n\n // Create new abort controller for this request\n abortControllerRef.current = new AbortController();\n const { signal } = abortControllerRef.current;\n\n // Start loading\n setIsLoading(true);\n setError(null);\n setEnsName(null);\n setEnsAvatar(null);\n\n try {\n // Check if request was aborted\n if (signal.aborted) return;\n\n // Attempt to resolve the name\n const name = await foundAdapter.getName?.(walletAddress);\n\n if (signal.aborted) return;\n\n if (name) {\n setEnsName(name);\n\n // If avatar resolution is supported, fetch the avatar\n if (adapterCapabilities.hasAvatarResolver) {\n try {\n const avatar = await foundAdapter.getAvatar?.(name);\n if (!signal.aborted) {\n // Handle undefined case by converting to null\n setEnsAvatar(avatar ?? null);\n }\n } catch (avatarError) {\n // Avatar fetch failed, but name succeeded - not critical\n console.warn('Failed to fetch avatar:', avatarError);\n if (!signal.aborted) {\n setEnsAvatar(null);\n }\n }\n }\n }\n } catch (error) {\n if (signal.aborted) return;\n\n const errorMessage = error instanceof Error ? error.message : 'Failed to fetch name service data';\n console.error('Failed to fetch name service data:', error);\n\n setError(errorMessage);\n setEnsName(null);\n setEnsAvatar(null);\n\n // Auto retry if enabled\n if (autoRetry) {\n retryTimeoutRef.current = setTimeout(() => {\n fetchNameData();\n }, retryDelay) as unknown as number;\n }\n } finally {\n if (!signal.aborted) {\n setIsLoading(false);\n }\n }\n }, [walletAddress, foundAdapter, adapterCapabilities, autoRetry, retryDelay, cleanup]);\n\n // Manual retry function\n const retry = useCallback(() => {\n setError(null);\n fetchNameData();\n }, [fetchNameData]);\n\n // Effect to fetch data when dependencies change\n useEffect(() => {\n fetchNameData();\n return cleanup;\n }, [fetchNameData, cleanup]);\n\n // Cleanup on unmount\n useEffect(() => {\n return cleanup;\n }, [cleanup]);\n\n // Memoized abbreviated name computation\n const ensNameAbbreviated = useMemo(() => {\n if (ensName) {\n return ensName.length > maxNameLength\n ? textCenterEllipsis(ensName, abbreviateSymbols, abbreviateSymbols)\n : ensName;\n }\n\n return walletAddress ? textCenterEllipsis(walletAddress, abbreviateSymbols, abbreviateSymbols) : undefined;\n }, [ensName, walletAddress, maxNameLength, abbreviateSymbols]);\n\n return {\n ensName,\n ensAvatar,\n isLoading,\n ensNameAbbreviated,\n error,\n retry,\n };\n}\n","import { getAdapterFromWalletType } from '@tuwaio/orbit-core';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { NovaConnectProviderProps } from './useNovaConnect';\n\n/**\n * @interface NativeBalanceResult\n * Represents the native token balance returned by the adapter.\n * The value is already formatted for human readability.\n * @property {string} value The native token balance formatted to standard decimals (e.g., \"1.5\").\n * @property {string} symbol The symbol of the native token (e.g., \"ETH\").\n */\nexport interface NativeBalanceResult {\n value: string;\n symbol: string;\n}\n\n// Type for the balance state within the hook (the fetched data or null).\ntype NativeBalanceState = NativeBalanceResult | null;\n\n// Type for the local cache: \"walletAddress-chainId\" -> { value, symbol }.\ntype BalanceCache = Record<string, NativeBalanceResult>;\n\n/**\n * @interface NativeBalanceData\n * The object returned by the useWalletNativeBalance hook.\n * @property {NativeBalanceState} balance The native token balance and symbol, or null.\n * @property {boolean} isLoading True while the balance is being fetched for the current wallet/chain combination.\n * @property {() => void} refetch Function to manually trigger a balance refresh.\n */\ninterface NativeBalanceData {\n balance: NativeBalanceState;\n isLoading: boolean;\n refetch: () => void;\n}\n\n/**\n * Custom hook to fetch the native token balance for the currently connected wallet\n * on the active chain. It includes a local cache layer to prevent redundant network calls\n * when switching between components or on re-renders for the same wallet/chain.\n *\n * @returns {NativeBalanceData} An object containing the balance data and loading state.\n *\n * @example\n * ```typescript\n * import { useWalletNativeBalance } from './useWalletNativeBalance';\n *\n * function NativeTokenDisplay() {\n * const { balance, isLoading, refetch } = useWalletNativeBalance();\n *\n * if (isLoading) {\n * return <p>Loading balance...</p>;\n * }\n *\n * // Display the formatted balance and symbol\n * return (\n * <div>\n * <p>Balance: {balance ? `${balance.value} ${balance.symbol}` : '0.00'}</p>\n * <button onClick={refetch}>Refresh</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useWalletNativeBalance({ store }: Pick<NovaConnectProviderProps, 'store'>): NativeBalanceData {\n // --- 1. STATE & CACHE SETUP ---\n\n // Local cache storage. Keys combine wallet address and chain ID.\n const [balanceCache, setBalanceCache] = useState<BalanceCache>({});\n\n // Local loading state, managed alongside the cache check.\n const [isLoading, setIsLoading] = useState<boolean>(false);\n\n // Track the current fetch operation to prevent race conditions\n const fetchOperationRef = useRef<string | null>(null);\n\n // Store state selectors - memoized for performance\n const wallet = store.getState().activeWallet;\n const getAdapter = store.getState().getAdapter;\n\n // --- 2. COMPUTED INPUTS ---\n\n const walletAddress = wallet?.address;\n const currentChainId = wallet?.chainId;\n\n // Create the unique key for cache lookups: \"address-chainId\".\n const cacheKey = useMemo(() => {\n return walletAddress && currentChainId ? `${walletAddress}-${currentChainId}` : null;\n }, [walletAddress, currentChainId]);\n\n // Find the actual adapter object from the adapter map.\n const foundAdapter = useMemo(() => {\n if (!wallet?.walletType) return null;\n return getAdapter(getAdapterFromWalletType(wallet.walletType));\n }, [getAdapter, wallet?.walletType]);\n\n // Check if the adapter has balance functionality\n const hasBalanceResolver = useMemo(() => {\n return foundAdapter && 'getBalance' in foundAdapter && typeof foundAdapter.getBalance === 'function';\n }, [foundAdapter]);\n\n // --- 3. BALANCE FETCHING LOGIC ---\n\n const fetchBalance = useCallback(\n async (forceRefresh = false) => {\n // Exit early if essential data is missing (not connected).\n if (!walletAddress || !foundAdapter || !currentChainId || !cacheKey || !hasBalanceResolver) {\n setIsLoading(false);\n return;\n }\n\n // Set the current operation ID to prevent race conditions\n const operationId = `${cacheKey}-${Date.now()}`;\n fetchOperationRef.current = operationId;\n\n // Check cache unless forcing a refresh\n if (!forceRefresh) {\n const cachedBalance = balanceCache[cacheKey];\n if (cachedBalance) {\n setIsLoading(false);\n return;\n }\n }\n\n setIsLoading(true);\n\n try {\n // Call the adapter's getBalance method\n const balanceResult: NativeBalanceResult = await foundAdapter.getBalance(walletAddress, currentChainId);\n\n // Only update if this operation is still the latest one\n if (fetchOperationRef.current === operationId) {\n setBalanceCache((prevCache) => ({\n ...prevCache,\n [cacheKey]: balanceResult,\n }));\n }\n } catch (error) {\n console.error(`Failed to fetch native balance for ${cacheKey}:`, error);\n\n // Optionally clear cache entry on error (if you want to retry on next call)\n if (forceRefresh && fetchOperationRef.current === operationId) {\n setBalanceCache((prevCache) => {\n const newCache = { ...prevCache };\n delete newCache[cacheKey];\n return newCache;\n });\n }\n } finally {\n // Only update loading state if this operation is still current\n if (fetchOperationRef.current === operationId) {\n setIsLoading(false);\n }\n }\n },\n [walletAddress, foundAdapter, currentChainId, cacheKey, hasBalanceResolver, balanceCache],\n );\n\n // Memoized refetch function that forces a refresh\n const refetch = useCallback(() => {\n fetchBalance(true);\n }, [fetchBalance]);\n\n // --- 4. EFFECT FOR INITIAL FETCH ---\n\n useEffect(() => {\n // Only fetch if we have all required data and no cached result\n if (cacheKey && hasBalanceResolver && !balanceCache[cacheKey]) {\n fetchBalance(false);\n } else if (!cacheKey || !hasBalanceResolver) {\n // Reset loading state if we can't fetch\n setIsLoading(false);\n }\n }, [cacheKey, hasBalanceResolver, balanceCache, fetchBalance]);\n\n // --- 5. CLEANUP EFFECT ---\n\n useEffect(() => {\n return () => {\n // Cancel any ongoing operations when component unmounts\n fetchOperationRef.current = null;\n };\n }, []);\n\n // --- 6. RETURNED DATA ---\n\n // The definitive balance is always derived from the cache based on the current key.\n const balance: NativeBalanceState = useMemo(() => {\n return cacheKey ? balanceCache[cacheKey] || null : null;\n }, [cacheKey, balanceCache]);\n\n // Return the fetched balance data and the loading status.\n return {\n balance, // { value: \"1.5\", symbol: \"ETH\" } or null\n isLoading,\n refetch,\n };\n}\n"]}
1
+ {"version":3,"sources":["../../src/hooks/useGetWalletNameAndAvatar.ts","../../src/hooks/useWalletNativeBalance.ts"],"names":["useGetWalletNameAndAvatar","options","abbreviateSymbols","maxNameLength","autoRetry","retryDelay","store","getAdapter","walletAddress","useMemo","walletType","foundAdapter","getAdapterFromWalletType","OrbitAdapter","ensName","setEnsName","useState","ensAvatar","setEnsAvatar","isLoading","setIsLoading","error","setError","abortControllerRef","useRef","retryTimeoutRef","adapterCapabilities","hasNameResolver","hasAvatarResolver","cleanup","useCallback","fetchNameData","signal","name","avatar","avatarError","errorMessage","retry","useEffect","ensNameAbbreviated","textCenterEllipsis","useWalletNativeBalance","activeWallet","balanceCache","setBalanceCache","fetchOperationRef","cacheKey","hasBalanceResolver","fetchBalance","forceRefresh","operationId","balanceResult","prevCache","newCache","refetch"],"mappings":"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","file":"index.cjs","sourcesContent":["import { textCenterEllipsis } from '@tuwaio/nova-core';\nimport { getAdapterFromWalletType, OrbitAdapter } from '@tuwaio/orbit-core';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { NovaConnectProviderProps, NovaConnectProviderType } from './useNovaConnect';\n\nexport interface WalletNameAndAvatarData {\n /** The resolved name from the Name Service (e.g., ENS, like \"alice.eth\"), or null if not found. */\n ensName: string | null;\n /** The URL of the avatar associated with the name, or null if not found. */\n ensAvatar: string | null;\n /** True while the name service data is being fetched. */\n isLoading: boolean;\n /** A truncated version of the name for display, or the abbreviated address if no name. */\n ensNameAbbreviated: string | undefined;\n /** Error message if the name resolution failed. */\n error: string | null;\n /** Function to retry the name resolution manually. */\n retry: () => void;\n}\n\ninterface UseGetWalletNameAndAvatarOptions\n extends Pick<NovaConnectProviderProps, 'store'>,\n Pick<NovaConnectProviderType, 'activeWallet'> {\n /** Number of characters to show on each side when abbreviating (default: 12) */\n abbreviateSymbols?: number;\n /** Maximum length before abbreviation is applied (default: 30) */\n maxNameLength?: number;\n /** Whether to automatically retry on failure (default: false) */\n autoRetry?: boolean;\n /** Retry delay in milliseconds (default: 3000) */\n retryDelay?: number;\n}\n\n/**\n * A custom hook to fetch the Name Service (e.g., ENS) name and avatar\n * for the currently active wallet.\n *\n * This hook automatically detects the active wallet and its corresponding\n * adapter via the `useSatelliteConnectStore` and attempts to resolve the\n * wallet address to a human-readable name and avatar.\n *\n * @param options Configuration options for the hook\n * @returns An object containing the resolved name, avatar, loading state, and utility functions\n *\n * @example\n * ```typescript\n * import { useGetWalletNameAndAvatar } from './useGetWalletNameAndAvatar';\n *\n * function DisplayWalletInfo() {\n * const { ensName, ensAvatar, isLoading, ensNameAbbreviated, error, retry } = useGetWalletNameAndAvatar({\n * abbreviateSymbols: 8,\n * maxNameLength: 25\n * });\n *\n * if (isLoading) {\n * return <div>Resolving name...</div>;\n * }\n *\n * if (error) {\n * return <div>Error: {error} <button onClick={retry}>Retry</button></div>;\n * }\n *\n * return (\n * <div className=\"wallet-info\">\n * {ensAvatar && <img src={ensAvatar} alt=\"Wallet Avatar\" />}\n * <p title={ensName || ''}>{ensNameAbbreviated || 'No Name Found'}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useGetWalletNameAndAvatar(options: UseGetWalletNameAndAvatarOptions): WalletNameAndAvatarData {\n const { abbreviateSymbols = 12, maxNameLength = 30, autoRetry = false, retryDelay = 3000, store } = options;\n\n // Store state selectors - memoized for performance\n const getAdapter = store.getState().getAdapter;\n\n // Memoize wallet address and adapter for dependency tracking\n const walletAddress = useMemo(() => options.activeWallet?.address, [options.activeWallet?.address]);\n const walletType = useMemo(() => options.activeWallet?.walletType, [options.activeWallet?.walletType]);\n\n const foundAdapter = useMemo(() => {\n if (!walletType) return null;\n return getAdapter(getAdapterFromWalletType(walletType ?? `${OrbitAdapter.EVM}:not-connected`));\n }, [getAdapter, walletType]);\n\n // State variables\n const [ensName, setEnsName] = useState<string | null>(null);\n const [ensAvatar, setEnsAvatar] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Refs for cleanup and retry functionality\n const abortControllerRef = useRef<AbortController | null>(null);\n const retryTimeoutRef = useRef<number | null>(null);\n\n // Memoize adapter capabilities\n const adapterCapabilities = useMemo(() => {\n if (!foundAdapter) {\n return { hasNameResolver: false, hasAvatarResolver: false };\n }\n\n const hasNameResolver = 'getName' in foundAdapter && typeof foundAdapter.getName === 'function';\n const hasAvatarResolver = 'getAvatar' in foundAdapter && typeof foundAdapter.getAvatar === 'function';\n\n return { hasNameResolver, hasAvatarResolver };\n }, [foundAdapter]);\n\n // Cleanup function\n const cleanup = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n if (retryTimeoutRef.current !== null) {\n clearTimeout(retryTimeoutRef.current);\n retryTimeoutRef.current = null;\n }\n }, []);\n\n // Main fetch function\n const fetchNameData = useCallback(async () => {\n cleanup();\n\n // Exit conditions\n if (!walletAddress || !foundAdapter || !adapterCapabilities.hasNameResolver) {\n setEnsName(null);\n setEnsAvatar(null);\n setIsLoading(false);\n setError(null);\n return;\n }\n\n // Create new abort controller for this request\n abortControllerRef.current = new AbortController();\n const { signal } = abortControllerRef.current;\n\n // Start loading\n setIsLoading(true);\n setError(null);\n setEnsName(null);\n setEnsAvatar(null);\n\n try {\n // Check if request was aborted\n if (signal.aborted) return;\n\n // Attempt to resolve the name\n const name = await foundAdapter.getName?.(walletAddress);\n\n if (signal.aborted) return;\n\n if (name) {\n setEnsName(name);\n\n // If avatar resolution is supported, fetch the avatar\n if (adapterCapabilities.hasAvatarResolver) {\n try {\n const avatar = await foundAdapter.getAvatar?.(name);\n if (!signal.aborted) {\n // Handle undefined case by converting to null\n setEnsAvatar(avatar ?? null);\n }\n } catch (avatarError) {\n // Avatar fetch failed, but name succeeded - not critical\n console.warn('Failed to fetch avatar:', avatarError);\n if (!signal.aborted) {\n setEnsAvatar(null);\n }\n }\n }\n }\n } catch (error) {\n if (signal.aborted) return;\n\n const errorMessage = error instanceof Error ? error.message : 'Failed to fetch name service data';\n console.error('Failed to fetch name service data:', error);\n\n setError(errorMessage);\n setEnsName(null);\n setEnsAvatar(null);\n\n // Auto retry if enabled\n if (autoRetry) {\n retryTimeoutRef.current = setTimeout(() => {\n fetchNameData();\n }, retryDelay) as unknown as number;\n }\n } finally {\n if (!signal.aborted) {\n setIsLoading(false);\n }\n }\n }, [walletAddress, foundAdapter, adapterCapabilities, autoRetry, retryDelay, cleanup]);\n\n // Manual retry function\n const retry = useCallback(() => {\n setError(null);\n fetchNameData();\n }, [fetchNameData]);\n\n // Effect to fetch data when dependencies change\n useEffect(() => {\n fetchNameData();\n return cleanup;\n }, [fetchNameData, cleanup]);\n\n // Cleanup on unmount\n useEffect(() => {\n return cleanup;\n }, [cleanup]);\n\n // Memoized abbreviated name computation\n const ensNameAbbreviated = useMemo(() => {\n if (ensName) {\n return ensName.length > maxNameLength\n ? textCenterEllipsis(ensName, abbreviateSymbols, abbreviateSymbols)\n : ensName;\n }\n\n return walletAddress ? textCenterEllipsis(walletAddress, abbreviateSymbols, abbreviateSymbols) : undefined;\n }, [ensName, walletAddress, maxNameLength, abbreviateSymbols]);\n\n return {\n ensName,\n ensAvatar,\n isLoading,\n ensNameAbbreviated,\n error,\n retry,\n };\n}\n","import { getAdapterFromWalletType } from '@tuwaio/orbit-core';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { NovaConnectProviderProps, NovaConnectProviderType } from './useNovaConnect';\n\n/**\n * @interface NativeBalanceResult\n * Represents the native token balance returned by the adapter.\n * The value is already formatted for human readability.\n * @property {string} value The native token balance formatted to standard decimals (e.g., \"1.5\").\n * @property {string} symbol The symbol of the native token (e.g., \"ETH\").\n */\nexport interface NativeBalanceResult {\n value: string;\n symbol: string;\n}\n\n// Type for the balance state within the hook (the fetched data or null).\ntype NativeBalanceState = NativeBalanceResult | null;\n\n// Type for the local cache: \"walletAddress-chainId\" -> { value, symbol }.\ntype BalanceCache = Record<string, NativeBalanceResult>;\n\n/**\n * @interface NativeBalanceData\n * The object returned by the useWalletNativeBalance hook.\n * @property {NativeBalanceState} balance The native token balance and symbol, or null.\n * @property {boolean} isLoading True while the balance is being fetched for the current wallet/chain combination.\n * @property {() => void} refetch Function to manually trigger a balance refresh.\n */\ninterface NativeBalanceData {\n balance: NativeBalanceState;\n isLoading: boolean;\n refetch: () => void;\n}\n\n/**\n * Custom hook to fetch the native token balance for the currently connected wallet\n * on the active chain. It includes a local cache layer to prevent redundant network calls\n * when switching between components or on re-renders for the same wallet/chain.\n *\n * @returns {NativeBalanceData} An object containing the balance data and loading state.\n *\n * @example\n * ```typescript\n * import { useWalletNativeBalance } from './useWalletNativeBalance';\n *\n * function NativeTokenDisplay() {\n * const { balance, isLoading, refetch } = useWalletNativeBalance();\n *\n * if (isLoading) {\n * return <p>Loading balance...</p>;\n * }\n *\n * // Display the formatted balance and symbol\n * return (\n * <div>\n * <p>Balance: {balance ? `${balance.value} ${balance.symbol}` : '0.00'}</p>\n * <button onClick={refetch}>Refresh</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useWalletNativeBalance({\n store,\n activeWallet,\n}: Pick<NovaConnectProviderProps, 'store'> & Pick<NovaConnectProviderType, 'activeWallet'>): NativeBalanceData {\n // --- 1. STATE & CACHE SETUP ---\n\n // Local cache storage. Keys combine wallet address and chain ID.\n const [balanceCache, setBalanceCache] = useState<BalanceCache>({});\n\n // Local loading state, managed alongside the cache check.\n const [isLoading, setIsLoading] = useState<boolean>(false);\n\n // Track the current fetch operation to prevent race conditions\n const fetchOperationRef = useRef<string | null>(null);\n\n // Store state selectors - memoized for performance\n const getAdapter = store.getState().getAdapter;\n\n // --- 2. COMPUTED INPUTS ---\n\n // Create the unique key for cache lookups: \"address-chainId\".\n const cacheKey = useMemo(() => {\n return activeWallet?.chainId && activeWallet?.address ? `${activeWallet.address}-${activeWallet.chainId}` : null;\n }, [activeWallet?.chainId, activeWallet?.address]);\n\n // Find the actual adapter object from the adapter map.\n const foundAdapter = useMemo(() => {\n if (!activeWallet?.walletType) return null;\n return getAdapter(getAdapterFromWalletType(activeWallet.walletType));\n }, [getAdapter, activeWallet?.walletType]);\n\n // Check if the adapter has balance functionality\n const hasBalanceResolver = useMemo(() => {\n return foundAdapter && 'getBalance' in foundAdapter && typeof foundAdapter.getBalance === 'function';\n }, [foundAdapter]);\n\n // --- 3. BALANCE FETCHING LOGIC ---\n\n const fetchBalance = useCallback(\n async (forceRefresh = false) => {\n // Exit early if essential data is missing (not connected).\n if (!activeWallet?.address || !foundAdapter || !activeWallet?.chainId || !cacheKey || !hasBalanceResolver) {\n setIsLoading(false);\n return;\n }\n\n // Set the current operation ID to prevent race conditions\n const operationId = `${cacheKey}-${Date.now()}`;\n fetchOperationRef.current = operationId;\n\n // Check cache unless forcing a refresh\n if (!forceRefresh) {\n const cachedBalance = balanceCache[cacheKey];\n if (cachedBalance) {\n setIsLoading(false);\n return;\n }\n }\n\n setIsLoading(true);\n\n try {\n // Call the adapter's getBalance method\n const balanceResult: NativeBalanceResult = await foundAdapter.getBalance(\n activeWallet.address,\n activeWallet.chainId,\n );\n\n // Only update if this operation is still the latest one\n if (fetchOperationRef.current === operationId) {\n setBalanceCache((prevCache) => ({\n ...prevCache,\n [cacheKey]: balanceResult,\n }));\n }\n } catch (error) {\n console.error(`Failed to fetch native balance for ${cacheKey}:`, error);\n\n // Optionally clear cache entry on error (if you want to retry on next call)\n if (forceRefresh && fetchOperationRef.current === operationId) {\n setBalanceCache((prevCache) => {\n const newCache = { ...prevCache };\n delete newCache[cacheKey];\n return newCache;\n });\n }\n } finally {\n // Only update loading state if this operation is still current\n if (fetchOperationRef.current === operationId) {\n setIsLoading(false);\n }\n }\n },\n [activeWallet?.address, foundAdapter, activeWallet?.chainId, cacheKey, hasBalanceResolver, balanceCache],\n );\n\n // Memoized refetch function that forces a refresh\n const refetch = useCallback(() => {\n fetchBalance(true);\n }, [fetchBalance]);\n\n // --- 4. EFFECT FOR INITIAL FETCH ---\n\n useEffect(() => {\n // Only fetch if we have all required data and no cached result\n if (cacheKey && hasBalanceResolver && !balanceCache[cacheKey]) {\n fetchBalance(false);\n } else if (!cacheKey || !hasBalanceResolver) {\n // Reset loading state if we can't fetch\n setIsLoading(false);\n }\n }, [cacheKey, hasBalanceResolver, balanceCache, fetchBalance]);\n\n // --- 5. CLEANUP EFFECT ---\n\n useEffect(() => {\n return () => {\n // Cancel any ongoing operations when component unmounts\n fetchOperationRef.current = null;\n };\n }, []);\n\n // --- 6. RETURNED DATA ---\n\n // The definitive balance is always derived from the cache based on the current key.\n const balance: NativeBalanceState = useMemo(() => {\n return cacheKey ? balanceCache[cacheKey] || null : null;\n }, [cacheKey, balanceCache]);\n\n // Return the fetched balance data and the loading status.\n return {\n balance, // { value: \"1.5\", symbol: \"ETH\" } or null\n isLoading,\n refetch,\n };\n}\n"]}
@@ -1,2 +1,2 @@
1
- import {textCenterEllipsis}from'@tuwaio/nova-core';import {getAdapterFromWalletType,OrbitAdapter}from'@tuwaio/orbit-core';import {useMemo,useState,useRef,useCallback,useEffect}from'react';function z(w){let{abbreviateSymbols:r=12,maxNameLength:y=30,autoRetry:C=false,retryDelay:u=3e3,store:f}=w,n=f.getState().activeWallet,N=f.getState().getAdapter,a=useMemo(()=>n?.address,[n?.address]),l=useMemo(()=>n?.walletType,[n?.walletType]),e=useMemo(()=>l?N(getAdapterFromWalletType(l??`${OrbitAdapter.EVM}:not-connected`)):null,[N,l]),[t,o]=useState(null),[p,m]=useState(null),[W,g]=useState(false),[b,s]=useState(null),c=useRef(null),v=useRef(null),x=useMemo(()=>{if(!e)return {hasNameResolver:false,hasAvatarResolver:false};let d="getName"in e&&typeof e.getName=="function",i="getAvatar"in e&&typeof e.getAvatar=="function";return {hasNameResolver:d,hasAvatarResolver:i}},[e]),A=useCallback(()=>{c.current&&(c.current.abort(),c.current=null),v.current!==null&&(clearTimeout(v.current),v.current=null);},[]),h=useCallback(async()=>{if(A(),!a||!e||!x.hasNameResolver){o(null),m(null),g(false),s(null);return}c.current=new AbortController;let{signal:d}=c.current;g(true),s(null),o(null),m(null);try{if(d.aborted)return;let i=await e.getName?.(a);if(d.aborted)return;if(i&&(o(i),x.hasAvatarResolver))try{let B=await e.getAvatar?.(i);d.aborted||m(B??null);}catch(B){console.warn("Failed to fetch avatar:",B),d.aborted||m(null);}}catch(i){if(d.aborted)return;let B=i instanceof Error?i.message:"Failed to fetch name service data";console.error("Failed to fetch name service data:",i),s(B),o(null),m(null),C&&(v.current=setTimeout(()=>{h();},u));}finally{d.aborted||g(false);}},[a,e,x,C,u,A]),I=useCallback(()=>{s(null),h();},[h]);useEffect(()=>(h(),A),[h,A]),useEffect(()=>A,[A]);let M=useMemo(()=>t?t.length>y?textCenterEllipsis(t,r,r):t:a?textCenterEllipsis(a,r,r):void 0,[t,a,y,r]);return {ensName:t,ensAvatar:p,isLoading:W,ensNameAbbreviated:M,error:b,retry:I}}function X({store:w}){let[r,y]=useState({}),[C,u]=useState(false),f=useRef(null),n=w.getState().activeWallet,N=w.getState().getAdapter,a=n?.address,l=n?.chainId,e=useMemo(()=>a&&l?`${a}-${l}`:null,[a,l]),t=useMemo(()=>n?.walletType?N(getAdapterFromWalletType(n.walletType)):null,[N,n?.walletType]),o=useMemo(()=>t&&"getBalance"in t&&typeof t.getBalance=="function",[t]),p=useCallback(async(g=false)=>{if(!a||!t||!l||!e||!o){u(false);return}let b=`${e}-${Date.now()}`;if(f.current=b,!g&&r[e]){u(false);return}u(true);try{let s=await t.getBalance(a,l);f.current===b&&y(c=>({...c,[e]:s}));}catch(s){console.error(`Failed to fetch native balance for ${e}:`,s),g&&f.current===b&&y(c=>{let v={...c};return delete v[e],v});}finally{f.current===b&&u(false);}},[a,t,l,e,o,r]),m=useCallback(()=>{p(true);},[p]);return useEffect(()=>{e&&o&&!r[e]?p(false):(!e||!o)&&u(false);},[e,o,r,p]),useEffect(()=>()=>{f.current=null;},[]),{balance:useMemo(()=>e&&r[e]||null,[e,r]),isLoading:C,refetch:m}}export{z as useGetWalletNameAndAvatar,X as useWalletNativeBalance};//# sourceMappingURL=index.js.map
1
+ import {textCenterEllipsis}from'@tuwaio/nova-core';import {getAdapterFromWalletType,OrbitAdapter}from'@tuwaio/orbit-core';import {useMemo,useState,useRef,useCallback,useEffect}from'react';function z(m){let{abbreviateSymbols:e=12,maxNameLength:n=30,autoRetry:y=false,retryDelay:B=3e3,store:v}=m,c=v.getState().getAdapter,l=useMemo(()=>m.activeWallet?.address,[m.activeWallet?.address]),t=useMemo(()=>m.activeWallet?.walletType,[m.activeWallet?.walletType]),a=useMemo(()=>t?c(getAdapterFromWalletType(t??`${OrbitAdapter.EVM}:not-connected`)):null,[c,t]),[r,o]=useState(null),[T,p]=useState(null),[C,i]=useState(false),[b,u]=useState(null),d=useRef(null),R=useRef(null),x=useMemo(()=>{if(!a)return {hasNameResolver:false,hasAvatarResolver:false};let f="getName"in a&&typeof a.getName=="function",s="getAvatar"in a&&typeof a.getAvatar=="function";return {hasNameResolver:f,hasAvatarResolver:s}},[a]),g=useCallback(()=>{d.current&&(d.current.abort(),d.current=null),R.current!==null&&(clearTimeout(R.current),R.current=null);},[]),N=useCallback(async()=>{if(g(),!l||!a||!x.hasNameResolver){o(null),p(null),i(false),u(null);return}d.current=new AbortController;let{signal:f}=d.current;i(true),u(null),o(null),p(null);try{if(f.aborted)return;let s=await a.getName?.(l);if(f.aborted)return;if(s&&(o(s),x.hasAvatarResolver))try{let h=await a.getAvatar?.(s);f.aborted||p(h??null);}catch(h){console.warn("Failed to fetch avatar:",h),f.aborted||p(null);}}catch(s){if(f.aborted)return;let h=s instanceof Error?s.message:"Failed to fetch name service data";console.error("Failed to fetch name service data:",s),u(h),o(null),p(null),y&&(R.current=setTimeout(()=>{N();},B));}finally{f.aborted||i(false);}},[l,a,x,y,B,g]),$=useCallback(()=>{u(null),N();},[N]);useEffect(()=>(N(),g),[N,g]),useEffect(()=>g,[g]);let M=useMemo(()=>r?r.length>n?textCenterEllipsis(r,e,e):r:l?textCenterEllipsis(l,e,e):void 0,[r,l,n,e]);return {ensName:r,ensAvatar:T,isLoading:C,ensNameAbbreviated:M,error:b,retry:$}}function W({store:m,activeWallet:e}){let[n,y]=useState({}),[B,v]=useState(false),c=useRef(null),l=m.getState().getAdapter,t=useMemo(()=>e?.chainId&&e?.address?`${e.address}-${e.chainId}`:null,[e?.chainId,e?.address]),a=useMemo(()=>e?.walletType?l(getAdapterFromWalletType(e.walletType)):null,[l,e?.walletType]),r=useMemo(()=>a&&"getBalance"in a&&typeof a.getBalance=="function",[a]),o=useCallback(async(C=false)=>{if(!e?.address||!a||!e?.chainId||!t||!r){v(false);return}let i=`${t}-${Date.now()}`;if(c.current=i,!C&&n[t]){v(false);return}v(true);try{let b=await a.getBalance(e.address,e.chainId);c.current===i&&y(u=>({...u,[t]:b}));}catch(b){console.error(`Failed to fetch native balance for ${t}:`,b),C&&c.current===i&&y(u=>{let d={...u};return delete d[t],d});}finally{c.current===i&&v(false);}},[e?.address,a,e?.chainId,t,r,n]),T=useCallback(()=>{o(true);},[o]);return useEffect(()=>{t&&r&&!n[t]?o(false):(!t||!r)&&v(false);},[t,r,n,o]),useEffect(()=>()=>{c.current=null;},[]),{balance:useMemo(()=>t&&n[t]||null,[t,n]),isLoading:B,refetch:T}}export{z as useGetWalletNameAndAvatar,W as useWalletNativeBalance};//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/useGetWalletNameAndAvatar.ts","../../src/hooks/useWalletNativeBalance.ts"],"names":["useGetWalletNameAndAvatar","options","abbreviateSymbols","maxNameLength","autoRetry","retryDelay","store","wallet","getAdapter","walletAddress","useMemo","walletType","foundAdapter","getAdapterFromWalletType","OrbitAdapter","ensName","setEnsName","useState","ensAvatar","setEnsAvatar","isLoading","setIsLoading","error","setError","abortControllerRef","useRef","retryTimeoutRef","adapterCapabilities","hasNameResolver","hasAvatarResolver","cleanup","useCallback","fetchNameData","signal","name","avatar","avatarError","errorMessage","retry","useEffect","ensNameAbbreviated","textCenterEllipsis","useWalletNativeBalance","balanceCache","setBalanceCache","fetchOperationRef","currentChainId","cacheKey","hasBalanceResolver","fetchBalance","forceRefresh","operationId","balanceResult","prevCache","newCache","refetch"],"mappings":"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","file":"index.js","sourcesContent":["import { textCenterEllipsis } from '@tuwaio/nova-core';\nimport { getAdapterFromWalletType, OrbitAdapter } from '@tuwaio/orbit-core';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { NovaConnectProviderProps } from './useNovaConnect';\n\nexport interface WalletNameAndAvatarData {\n /** The resolved name from the Name Service (e.g., ENS, like \"alice.eth\"), or null if not found. */\n ensName: string | null;\n /** The URL of the avatar associated with the name, or null if not found. */\n ensAvatar: string | null;\n /** True while the name service data is being fetched. */\n isLoading: boolean;\n /** A truncated version of the name for display, or the abbreviated address if no name. */\n ensNameAbbreviated: string | undefined;\n /** Error message if the name resolution failed. */\n error: string | null;\n /** Function to retry the name resolution manually. */\n retry: () => void;\n}\n\ninterface UseGetWalletNameAndAvatarOptions extends Pick<NovaConnectProviderProps, 'store'> {\n /** Number of characters to show on each side when abbreviating (default: 12) */\n abbreviateSymbols?: number;\n /** Maximum length before abbreviation is applied (default: 30) */\n maxNameLength?: number;\n /** Whether to automatically retry on failure (default: false) */\n autoRetry?: boolean;\n /** Retry delay in milliseconds (default: 3000) */\n retryDelay?: number;\n}\n\n/**\n * A custom hook to fetch the Name Service (e.g., ENS) name and avatar\n * for the currently active wallet.\n *\n * This hook automatically detects the active wallet and its corresponding\n * adapter via the `useSatelliteConnectStore` and attempts to resolve the\n * wallet address to a human-readable name and avatar.\n *\n * @param options Configuration options for the hook\n * @returns An object containing the resolved name, avatar, loading state, and utility functions\n *\n * @example\n * ```typescript\n * import { useGetWalletNameAndAvatar } from './useGetWalletNameAndAvatar';\n *\n * function DisplayWalletInfo() {\n * const { ensName, ensAvatar, isLoading, ensNameAbbreviated, error, retry } = useGetWalletNameAndAvatar({\n * abbreviateSymbols: 8,\n * maxNameLength: 25\n * });\n *\n * if (isLoading) {\n * return <div>Resolving name...</div>;\n * }\n *\n * if (error) {\n * return <div>Error: {error} <button onClick={retry}>Retry</button></div>;\n * }\n *\n * return (\n * <div className=\"wallet-info\">\n * {ensAvatar && <img src={ensAvatar} alt=\"Wallet Avatar\" />}\n * <p title={ensName || ''}>{ensNameAbbreviated || 'No Name Found'}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useGetWalletNameAndAvatar(options: UseGetWalletNameAndAvatarOptions): WalletNameAndAvatarData {\n const { abbreviateSymbols = 12, maxNameLength = 30, autoRetry = false, retryDelay = 3000, store } = options;\n\n // Store state selectors - memoized for performance\n const wallet = store.getState().activeWallet;\n const getAdapter = store.getState().getAdapter;\n\n // Memoize wallet address and adapter for dependency tracking\n const walletAddress = useMemo(() => wallet?.address, [wallet?.address]);\n const walletType = useMemo(() => wallet?.walletType, [wallet?.walletType]);\n\n const foundAdapter = useMemo(() => {\n if (!walletType) return null;\n return getAdapter(getAdapterFromWalletType(walletType ?? `${OrbitAdapter.EVM}:not-connected`));\n }, [getAdapter, walletType]);\n\n // State variables\n const [ensName, setEnsName] = useState<string | null>(null);\n const [ensAvatar, setEnsAvatar] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Refs for cleanup and retry functionality\n const abortControllerRef = useRef<AbortController | null>(null);\n const retryTimeoutRef = useRef<number | null>(null);\n\n // Memoize adapter capabilities\n const adapterCapabilities = useMemo(() => {\n if (!foundAdapter) {\n return { hasNameResolver: false, hasAvatarResolver: false };\n }\n\n const hasNameResolver = 'getName' in foundAdapter && typeof foundAdapter.getName === 'function';\n const hasAvatarResolver = 'getAvatar' in foundAdapter && typeof foundAdapter.getAvatar === 'function';\n\n return { hasNameResolver, hasAvatarResolver };\n }, [foundAdapter]);\n\n // Cleanup function\n const cleanup = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n if (retryTimeoutRef.current !== null) {\n clearTimeout(retryTimeoutRef.current);\n retryTimeoutRef.current = null;\n }\n }, []);\n\n // Main fetch function\n const fetchNameData = useCallback(async () => {\n cleanup();\n\n // Exit conditions\n if (!walletAddress || !foundAdapter || !adapterCapabilities.hasNameResolver) {\n setEnsName(null);\n setEnsAvatar(null);\n setIsLoading(false);\n setError(null);\n return;\n }\n\n // Create new abort controller for this request\n abortControllerRef.current = new AbortController();\n const { signal } = abortControllerRef.current;\n\n // Start loading\n setIsLoading(true);\n setError(null);\n setEnsName(null);\n setEnsAvatar(null);\n\n try {\n // Check if request was aborted\n if (signal.aborted) return;\n\n // Attempt to resolve the name\n const name = await foundAdapter.getName?.(walletAddress);\n\n if (signal.aborted) return;\n\n if (name) {\n setEnsName(name);\n\n // If avatar resolution is supported, fetch the avatar\n if (adapterCapabilities.hasAvatarResolver) {\n try {\n const avatar = await foundAdapter.getAvatar?.(name);\n if (!signal.aborted) {\n // Handle undefined case by converting to null\n setEnsAvatar(avatar ?? null);\n }\n } catch (avatarError) {\n // Avatar fetch failed, but name succeeded - not critical\n console.warn('Failed to fetch avatar:', avatarError);\n if (!signal.aborted) {\n setEnsAvatar(null);\n }\n }\n }\n }\n } catch (error) {\n if (signal.aborted) return;\n\n const errorMessage = error instanceof Error ? error.message : 'Failed to fetch name service data';\n console.error('Failed to fetch name service data:', error);\n\n setError(errorMessage);\n setEnsName(null);\n setEnsAvatar(null);\n\n // Auto retry if enabled\n if (autoRetry) {\n retryTimeoutRef.current = setTimeout(() => {\n fetchNameData();\n }, retryDelay) as unknown as number;\n }\n } finally {\n if (!signal.aborted) {\n setIsLoading(false);\n }\n }\n }, [walletAddress, foundAdapter, adapterCapabilities, autoRetry, retryDelay, cleanup]);\n\n // Manual retry function\n const retry = useCallback(() => {\n setError(null);\n fetchNameData();\n }, [fetchNameData]);\n\n // Effect to fetch data when dependencies change\n useEffect(() => {\n fetchNameData();\n return cleanup;\n }, [fetchNameData, cleanup]);\n\n // Cleanup on unmount\n useEffect(() => {\n return cleanup;\n }, [cleanup]);\n\n // Memoized abbreviated name computation\n const ensNameAbbreviated = useMemo(() => {\n if (ensName) {\n return ensName.length > maxNameLength\n ? textCenterEllipsis(ensName, abbreviateSymbols, abbreviateSymbols)\n : ensName;\n }\n\n return walletAddress ? textCenterEllipsis(walletAddress, abbreviateSymbols, abbreviateSymbols) : undefined;\n }, [ensName, walletAddress, maxNameLength, abbreviateSymbols]);\n\n return {\n ensName,\n ensAvatar,\n isLoading,\n ensNameAbbreviated,\n error,\n retry,\n };\n}\n","import { getAdapterFromWalletType } from '@tuwaio/orbit-core';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { NovaConnectProviderProps } from './useNovaConnect';\n\n/**\n * @interface NativeBalanceResult\n * Represents the native token balance returned by the adapter.\n * The value is already formatted for human readability.\n * @property {string} value The native token balance formatted to standard decimals (e.g., \"1.5\").\n * @property {string} symbol The symbol of the native token (e.g., \"ETH\").\n */\nexport interface NativeBalanceResult {\n value: string;\n symbol: string;\n}\n\n// Type for the balance state within the hook (the fetched data or null).\ntype NativeBalanceState = NativeBalanceResult | null;\n\n// Type for the local cache: \"walletAddress-chainId\" -> { value, symbol }.\ntype BalanceCache = Record<string, NativeBalanceResult>;\n\n/**\n * @interface NativeBalanceData\n * The object returned by the useWalletNativeBalance hook.\n * @property {NativeBalanceState} balance The native token balance and symbol, or null.\n * @property {boolean} isLoading True while the balance is being fetched for the current wallet/chain combination.\n * @property {() => void} refetch Function to manually trigger a balance refresh.\n */\ninterface NativeBalanceData {\n balance: NativeBalanceState;\n isLoading: boolean;\n refetch: () => void;\n}\n\n/**\n * Custom hook to fetch the native token balance for the currently connected wallet\n * on the active chain. It includes a local cache layer to prevent redundant network calls\n * when switching between components or on re-renders for the same wallet/chain.\n *\n * @returns {NativeBalanceData} An object containing the balance data and loading state.\n *\n * @example\n * ```typescript\n * import { useWalletNativeBalance } from './useWalletNativeBalance';\n *\n * function NativeTokenDisplay() {\n * const { balance, isLoading, refetch } = useWalletNativeBalance();\n *\n * if (isLoading) {\n * return <p>Loading balance...</p>;\n * }\n *\n * // Display the formatted balance and symbol\n * return (\n * <div>\n * <p>Balance: {balance ? `${balance.value} ${balance.symbol}` : '0.00'}</p>\n * <button onClick={refetch}>Refresh</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useWalletNativeBalance({ store }: Pick<NovaConnectProviderProps, 'store'>): NativeBalanceData {\n // --- 1. STATE & CACHE SETUP ---\n\n // Local cache storage. Keys combine wallet address and chain ID.\n const [balanceCache, setBalanceCache] = useState<BalanceCache>({});\n\n // Local loading state, managed alongside the cache check.\n const [isLoading, setIsLoading] = useState<boolean>(false);\n\n // Track the current fetch operation to prevent race conditions\n const fetchOperationRef = useRef<string | null>(null);\n\n // Store state selectors - memoized for performance\n const wallet = store.getState().activeWallet;\n const getAdapter = store.getState().getAdapter;\n\n // --- 2. COMPUTED INPUTS ---\n\n const walletAddress = wallet?.address;\n const currentChainId = wallet?.chainId;\n\n // Create the unique key for cache lookups: \"address-chainId\".\n const cacheKey = useMemo(() => {\n return walletAddress && currentChainId ? `${walletAddress}-${currentChainId}` : null;\n }, [walletAddress, currentChainId]);\n\n // Find the actual adapter object from the adapter map.\n const foundAdapter = useMemo(() => {\n if (!wallet?.walletType) return null;\n return getAdapter(getAdapterFromWalletType(wallet.walletType));\n }, [getAdapter, wallet?.walletType]);\n\n // Check if the adapter has balance functionality\n const hasBalanceResolver = useMemo(() => {\n return foundAdapter && 'getBalance' in foundAdapter && typeof foundAdapter.getBalance === 'function';\n }, [foundAdapter]);\n\n // --- 3. BALANCE FETCHING LOGIC ---\n\n const fetchBalance = useCallback(\n async (forceRefresh = false) => {\n // Exit early if essential data is missing (not connected).\n if (!walletAddress || !foundAdapter || !currentChainId || !cacheKey || !hasBalanceResolver) {\n setIsLoading(false);\n return;\n }\n\n // Set the current operation ID to prevent race conditions\n const operationId = `${cacheKey}-${Date.now()}`;\n fetchOperationRef.current = operationId;\n\n // Check cache unless forcing a refresh\n if (!forceRefresh) {\n const cachedBalance = balanceCache[cacheKey];\n if (cachedBalance) {\n setIsLoading(false);\n return;\n }\n }\n\n setIsLoading(true);\n\n try {\n // Call the adapter's getBalance method\n const balanceResult: NativeBalanceResult = await foundAdapter.getBalance(walletAddress, currentChainId);\n\n // Only update if this operation is still the latest one\n if (fetchOperationRef.current === operationId) {\n setBalanceCache((prevCache) => ({\n ...prevCache,\n [cacheKey]: balanceResult,\n }));\n }\n } catch (error) {\n console.error(`Failed to fetch native balance for ${cacheKey}:`, error);\n\n // Optionally clear cache entry on error (if you want to retry on next call)\n if (forceRefresh && fetchOperationRef.current === operationId) {\n setBalanceCache((prevCache) => {\n const newCache = { ...prevCache };\n delete newCache[cacheKey];\n return newCache;\n });\n }\n } finally {\n // Only update loading state if this operation is still current\n if (fetchOperationRef.current === operationId) {\n setIsLoading(false);\n }\n }\n },\n [walletAddress, foundAdapter, currentChainId, cacheKey, hasBalanceResolver, balanceCache],\n );\n\n // Memoized refetch function that forces a refresh\n const refetch = useCallback(() => {\n fetchBalance(true);\n }, [fetchBalance]);\n\n // --- 4. EFFECT FOR INITIAL FETCH ---\n\n useEffect(() => {\n // Only fetch if we have all required data and no cached result\n if (cacheKey && hasBalanceResolver && !balanceCache[cacheKey]) {\n fetchBalance(false);\n } else if (!cacheKey || !hasBalanceResolver) {\n // Reset loading state if we can't fetch\n setIsLoading(false);\n }\n }, [cacheKey, hasBalanceResolver, balanceCache, fetchBalance]);\n\n // --- 5. CLEANUP EFFECT ---\n\n useEffect(() => {\n return () => {\n // Cancel any ongoing operations when component unmounts\n fetchOperationRef.current = null;\n };\n }, []);\n\n // --- 6. RETURNED DATA ---\n\n // The definitive balance is always derived from the cache based on the current key.\n const balance: NativeBalanceState = useMemo(() => {\n return cacheKey ? balanceCache[cacheKey] || null : null;\n }, [cacheKey, balanceCache]);\n\n // Return the fetched balance data and the loading status.\n return {\n balance, // { value: \"1.5\", symbol: \"ETH\" } or null\n isLoading,\n refetch,\n };\n}\n"]}
1
+ {"version":3,"sources":["../../src/hooks/useGetWalletNameAndAvatar.ts","../../src/hooks/useWalletNativeBalance.ts"],"names":["useGetWalletNameAndAvatar","options","abbreviateSymbols","maxNameLength","autoRetry","retryDelay","store","getAdapter","walletAddress","useMemo","walletType","foundAdapter","getAdapterFromWalletType","OrbitAdapter","ensName","setEnsName","useState","ensAvatar","setEnsAvatar","isLoading","setIsLoading","error","setError","abortControllerRef","useRef","retryTimeoutRef","adapterCapabilities","hasNameResolver","hasAvatarResolver","cleanup","useCallback","fetchNameData","signal","name","avatar","avatarError","errorMessage","retry","useEffect","ensNameAbbreviated","textCenterEllipsis","useWalletNativeBalance","activeWallet","balanceCache","setBalanceCache","fetchOperationRef","cacheKey","hasBalanceResolver","fetchBalance","forceRefresh","operationId","balanceResult","prevCache","newCache","refetch"],"mappings":"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","file":"index.js","sourcesContent":["import { textCenterEllipsis } from '@tuwaio/nova-core';\nimport { getAdapterFromWalletType, OrbitAdapter } from '@tuwaio/orbit-core';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { NovaConnectProviderProps, NovaConnectProviderType } from './useNovaConnect';\n\nexport interface WalletNameAndAvatarData {\n /** The resolved name from the Name Service (e.g., ENS, like \"alice.eth\"), or null if not found. */\n ensName: string | null;\n /** The URL of the avatar associated with the name, or null if not found. */\n ensAvatar: string | null;\n /** True while the name service data is being fetched. */\n isLoading: boolean;\n /** A truncated version of the name for display, or the abbreviated address if no name. */\n ensNameAbbreviated: string | undefined;\n /** Error message if the name resolution failed. */\n error: string | null;\n /** Function to retry the name resolution manually. */\n retry: () => void;\n}\n\ninterface UseGetWalletNameAndAvatarOptions\n extends Pick<NovaConnectProviderProps, 'store'>,\n Pick<NovaConnectProviderType, 'activeWallet'> {\n /** Number of characters to show on each side when abbreviating (default: 12) */\n abbreviateSymbols?: number;\n /** Maximum length before abbreviation is applied (default: 30) */\n maxNameLength?: number;\n /** Whether to automatically retry on failure (default: false) */\n autoRetry?: boolean;\n /** Retry delay in milliseconds (default: 3000) */\n retryDelay?: number;\n}\n\n/**\n * A custom hook to fetch the Name Service (e.g., ENS) name and avatar\n * for the currently active wallet.\n *\n * This hook automatically detects the active wallet and its corresponding\n * adapter via the `useSatelliteConnectStore` and attempts to resolve the\n * wallet address to a human-readable name and avatar.\n *\n * @param options Configuration options for the hook\n * @returns An object containing the resolved name, avatar, loading state, and utility functions\n *\n * @example\n * ```typescript\n * import { useGetWalletNameAndAvatar } from './useGetWalletNameAndAvatar';\n *\n * function DisplayWalletInfo() {\n * const { ensName, ensAvatar, isLoading, ensNameAbbreviated, error, retry } = useGetWalletNameAndAvatar({\n * abbreviateSymbols: 8,\n * maxNameLength: 25\n * });\n *\n * if (isLoading) {\n * return <div>Resolving name...</div>;\n * }\n *\n * if (error) {\n * return <div>Error: {error} <button onClick={retry}>Retry</button></div>;\n * }\n *\n * return (\n * <div className=\"wallet-info\">\n * {ensAvatar && <img src={ensAvatar} alt=\"Wallet Avatar\" />}\n * <p title={ensName || ''}>{ensNameAbbreviated || 'No Name Found'}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useGetWalletNameAndAvatar(options: UseGetWalletNameAndAvatarOptions): WalletNameAndAvatarData {\n const { abbreviateSymbols = 12, maxNameLength = 30, autoRetry = false, retryDelay = 3000, store } = options;\n\n // Store state selectors - memoized for performance\n const getAdapter = store.getState().getAdapter;\n\n // Memoize wallet address and adapter for dependency tracking\n const walletAddress = useMemo(() => options.activeWallet?.address, [options.activeWallet?.address]);\n const walletType = useMemo(() => options.activeWallet?.walletType, [options.activeWallet?.walletType]);\n\n const foundAdapter = useMemo(() => {\n if (!walletType) return null;\n return getAdapter(getAdapterFromWalletType(walletType ?? `${OrbitAdapter.EVM}:not-connected`));\n }, [getAdapter, walletType]);\n\n // State variables\n const [ensName, setEnsName] = useState<string | null>(null);\n const [ensAvatar, setEnsAvatar] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Refs for cleanup and retry functionality\n const abortControllerRef = useRef<AbortController | null>(null);\n const retryTimeoutRef = useRef<number | null>(null);\n\n // Memoize adapter capabilities\n const adapterCapabilities = useMemo(() => {\n if (!foundAdapter) {\n return { hasNameResolver: false, hasAvatarResolver: false };\n }\n\n const hasNameResolver = 'getName' in foundAdapter && typeof foundAdapter.getName === 'function';\n const hasAvatarResolver = 'getAvatar' in foundAdapter && typeof foundAdapter.getAvatar === 'function';\n\n return { hasNameResolver, hasAvatarResolver };\n }, [foundAdapter]);\n\n // Cleanup function\n const cleanup = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n if (retryTimeoutRef.current !== null) {\n clearTimeout(retryTimeoutRef.current);\n retryTimeoutRef.current = null;\n }\n }, []);\n\n // Main fetch function\n const fetchNameData = useCallback(async () => {\n cleanup();\n\n // Exit conditions\n if (!walletAddress || !foundAdapter || !adapterCapabilities.hasNameResolver) {\n setEnsName(null);\n setEnsAvatar(null);\n setIsLoading(false);\n setError(null);\n return;\n }\n\n // Create new abort controller for this request\n abortControllerRef.current = new AbortController();\n const { signal } = abortControllerRef.current;\n\n // Start loading\n setIsLoading(true);\n setError(null);\n setEnsName(null);\n setEnsAvatar(null);\n\n try {\n // Check if request was aborted\n if (signal.aborted) return;\n\n // Attempt to resolve the name\n const name = await foundAdapter.getName?.(walletAddress);\n\n if (signal.aborted) return;\n\n if (name) {\n setEnsName(name);\n\n // If avatar resolution is supported, fetch the avatar\n if (adapterCapabilities.hasAvatarResolver) {\n try {\n const avatar = await foundAdapter.getAvatar?.(name);\n if (!signal.aborted) {\n // Handle undefined case by converting to null\n setEnsAvatar(avatar ?? null);\n }\n } catch (avatarError) {\n // Avatar fetch failed, but name succeeded - not critical\n console.warn('Failed to fetch avatar:', avatarError);\n if (!signal.aborted) {\n setEnsAvatar(null);\n }\n }\n }\n }\n } catch (error) {\n if (signal.aborted) return;\n\n const errorMessage = error instanceof Error ? error.message : 'Failed to fetch name service data';\n console.error('Failed to fetch name service data:', error);\n\n setError(errorMessage);\n setEnsName(null);\n setEnsAvatar(null);\n\n // Auto retry if enabled\n if (autoRetry) {\n retryTimeoutRef.current = setTimeout(() => {\n fetchNameData();\n }, retryDelay) as unknown as number;\n }\n } finally {\n if (!signal.aborted) {\n setIsLoading(false);\n }\n }\n }, [walletAddress, foundAdapter, adapterCapabilities, autoRetry, retryDelay, cleanup]);\n\n // Manual retry function\n const retry = useCallback(() => {\n setError(null);\n fetchNameData();\n }, [fetchNameData]);\n\n // Effect to fetch data when dependencies change\n useEffect(() => {\n fetchNameData();\n return cleanup;\n }, [fetchNameData, cleanup]);\n\n // Cleanup on unmount\n useEffect(() => {\n return cleanup;\n }, [cleanup]);\n\n // Memoized abbreviated name computation\n const ensNameAbbreviated = useMemo(() => {\n if (ensName) {\n return ensName.length > maxNameLength\n ? textCenterEllipsis(ensName, abbreviateSymbols, abbreviateSymbols)\n : ensName;\n }\n\n return walletAddress ? textCenterEllipsis(walletAddress, abbreviateSymbols, abbreviateSymbols) : undefined;\n }, [ensName, walletAddress, maxNameLength, abbreviateSymbols]);\n\n return {\n ensName,\n ensAvatar,\n isLoading,\n ensNameAbbreviated,\n error,\n retry,\n };\n}\n","import { getAdapterFromWalletType } from '@tuwaio/orbit-core';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { NovaConnectProviderProps, NovaConnectProviderType } from './useNovaConnect';\n\n/**\n * @interface NativeBalanceResult\n * Represents the native token balance returned by the adapter.\n * The value is already formatted for human readability.\n * @property {string} value The native token balance formatted to standard decimals (e.g., \"1.5\").\n * @property {string} symbol The symbol of the native token (e.g., \"ETH\").\n */\nexport interface NativeBalanceResult {\n value: string;\n symbol: string;\n}\n\n// Type for the balance state within the hook (the fetched data or null).\ntype NativeBalanceState = NativeBalanceResult | null;\n\n// Type for the local cache: \"walletAddress-chainId\" -> { value, symbol }.\ntype BalanceCache = Record<string, NativeBalanceResult>;\n\n/**\n * @interface NativeBalanceData\n * The object returned by the useWalletNativeBalance hook.\n * @property {NativeBalanceState} balance The native token balance and symbol, or null.\n * @property {boolean} isLoading True while the balance is being fetched for the current wallet/chain combination.\n * @property {() => void} refetch Function to manually trigger a balance refresh.\n */\ninterface NativeBalanceData {\n balance: NativeBalanceState;\n isLoading: boolean;\n refetch: () => void;\n}\n\n/**\n * Custom hook to fetch the native token balance for the currently connected wallet\n * on the active chain. It includes a local cache layer to prevent redundant network calls\n * when switching between components or on re-renders for the same wallet/chain.\n *\n * @returns {NativeBalanceData} An object containing the balance data and loading state.\n *\n * @example\n * ```typescript\n * import { useWalletNativeBalance } from './useWalletNativeBalance';\n *\n * function NativeTokenDisplay() {\n * const { balance, isLoading, refetch } = useWalletNativeBalance();\n *\n * if (isLoading) {\n * return <p>Loading balance...</p>;\n * }\n *\n * // Display the formatted balance and symbol\n * return (\n * <div>\n * <p>Balance: {balance ? `${balance.value} ${balance.symbol}` : '0.00'}</p>\n * <button onClick={refetch}>Refresh</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useWalletNativeBalance({\n store,\n activeWallet,\n}: Pick<NovaConnectProviderProps, 'store'> & Pick<NovaConnectProviderType, 'activeWallet'>): NativeBalanceData {\n // --- 1. STATE & CACHE SETUP ---\n\n // Local cache storage. Keys combine wallet address and chain ID.\n const [balanceCache, setBalanceCache] = useState<BalanceCache>({});\n\n // Local loading state, managed alongside the cache check.\n const [isLoading, setIsLoading] = useState<boolean>(false);\n\n // Track the current fetch operation to prevent race conditions\n const fetchOperationRef = useRef<string | null>(null);\n\n // Store state selectors - memoized for performance\n const getAdapter = store.getState().getAdapter;\n\n // --- 2. COMPUTED INPUTS ---\n\n // Create the unique key for cache lookups: \"address-chainId\".\n const cacheKey = useMemo(() => {\n return activeWallet?.chainId && activeWallet?.address ? `${activeWallet.address}-${activeWallet.chainId}` : null;\n }, [activeWallet?.chainId, activeWallet?.address]);\n\n // Find the actual adapter object from the adapter map.\n const foundAdapter = useMemo(() => {\n if (!activeWallet?.walletType) return null;\n return getAdapter(getAdapterFromWalletType(activeWallet.walletType));\n }, [getAdapter, activeWallet?.walletType]);\n\n // Check if the adapter has balance functionality\n const hasBalanceResolver = useMemo(() => {\n return foundAdapter && 'getBalance' in foundAdapter && typeof foundAdapter.getBalance === 'function';\n }, [foundAdapter]);\n\n // --- 3. BALANCE FETCHING LOGIC ---\n\n const fetchBalance = useCallback(\n async (forceRefresh = false) => {\n // Exit early if essential data is missing (not connected).\n if (!activeWallet?.address || !foundAdapter || !activeWallet?.chainId || !cacheKey || !hasBalanceResolver) {\n setIsLoading(false);\n return;\n }\n\n // Set the current operation ID to prevent race conditions\n const operationId = `${cacheKey}-${Date.now()}`;\n fetchOperationRef.current = operationId;\n\n // Check cache unless forcing a refresh\n if (!forceRefresh) {\n const cachedBalance = balanceCache[cacheKey];\n if (cachedBalance) {\n setIsLoading(false);\n return;\n }\n }\n\n setIsLoading(true);\n\n try {\n // Call the adapter's getBalance method\n const balanceResult: NativeBalanceResult = await foundAdapter.getBalance(\n activeWallet.address,\n activeWallet.chainId,\n );\n\n // Only update if this operation is still the latest one\n if (fetchOperationRef.current === operationId) {\n setBalanceCache((prevCache) => ({\n ...prevCache,\n [cacheKey]: balanceResult,\n }));\n }\n } catch (error) {\n console.error(`Failed to fetch native balance for ${cacheKey}:`, error);\n\n // Optionally clear cache entry on error (if you want to retry on next call)\n if (forceRefresh && fetchOperationRef.current === operationId) {\n setBalanceCache((prevCache) => {\n const newCache = { ...prevCache };\n delete newCache[cacheKey];\n return newCache;\n });\n }\n } finally {\n // Only update loading state if this operation is still current\n if (fetchOperationRef.current === operationId) {\n setIsLoading(false);\n }\n }\n },\n [activeWallet?.address, foundAdapter, activeWallet?.chainId, cacheKey, hasBalanceResolver, balanceCache],\n );\n\n // Memoized refetch function that forces a refresh\n const refetch = useCallback(() => {\n fetchBalance(true);\n }, [fetchBalance]);\n\n // --- 4. EFFECT FOR INITIAL FETCH ---\n\n useEffect(() => {\n // Only fetch if we have all required data and no cached result\n if (cacheKey && hasBalanceResolver && !balanceCache[cacheKey]) {\n fetchBalance(false);\n } else if (!cacheKey || !hasBalanceResolver) {\n // Reset loading state if we can't fetch\n setIsLoading(false);\n }\n }, [cacheKey, hasBalanceResolver, balanceCache, fetchBalance]);\n\n // --- 5. CLEANUP EFFECT ---\n\n useEffect(() => {\n return () => {\n // Cancel any ongoing operations when component unmounts\n fetchOperationRef.current = null;\n };\n }, []);\n\n // --- 6. RETURNED DATA ---\n\n // The definitive balance is always derived from the cache based on the current key.\n const balance: NativeBalanceState = useMemo(() => {\n return cacheKey ? balanceCache[cacheKey] || null : null;\n }, [cacheKey, balanceCache]);\n\n // Return the fetched balance data and the loading status.\n return {\n balance, // { value: \"1.5\", symbol: \"ETH\" } or null\n isLoading,\n refetch,\n };\n}\n"]}