@tuwaio/nova-connect 1.0.0-fix-test-modals-alpha.2.e4ae89d → 1.0.0-fix-styles-alpha.1.f2958e5

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.
Files changed (33) hide show
  1. package/README.md +40 -45
  2. package/dist/{ToastError-Dgx4fCxI.d.ts → ToastError-BLFMIzVb.d.ts} +4 -4
  3. package/dist/{ToastError-B5-z1_uC.d.cts → ToastError-CaoiEVOK.d.cts} +4 -4
  4. package/dist/{chunk-MVAF36Z4.cjs → chunk-7FTV55DQ.cjs} +2 -2
  5. package/dist/{chunk-MVAF36Z4.cjs.map → chunk-7FTV55DQ.cjs.map} +1 -1
  6. package/dist/chunk-JVVOBSVI.js +6 -0
  7. package/dist/chunk-JVVOBSVI.js.map +1 -0
  8. package/dist/{chunk-AGY44ZDF.js → chunk-S5WT3DLF.js} +2 -2
  9. package/dist/{chunk-AGY44ZDF.js.map → chunk-S5WT3DLF.js.map} +1 -1
  10. package/dist/chunk-Y3SFEPYJ.cjs +6 -0
  11. package/dist/chunk-Y3SFEPYJ.cjs.map +1 -0
  12. package/dist/components/index.cjs +1 -1
  13. package/dist/components/index.d.cts +2 -2
  14. package/dist/components/index.d.ts +2 -2
  15. package/dist/components/index.js +1 -1
  16. package/dist/hooks/index.cjs +1 -1
  17. package/dist/hooks/index.d.cts +1 -1
  18. package/dist/hooks/index.d.ts +1 -1
  19. package/dist/hooks/index.js +1 -1
  20. package/dist/index.cjs +1 -1
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.css +69 -4
  23. package/dist/index.d.cts +4 -4
  24. package/dist/index.d.ts +4 -4
  25. package/dist/index.js +1 -1
  26. package/dist/index.js.map +1 -1
  27. package/dist/{useWalletNativeBalance-DCdB3_v2.d.ts → useWalletNativeBalance-CEASeZ6Z.d.ts} +1 -1
  28. package/dist/{useWalletNativeBalance-DKa97yY5.d.cts → useWalletNativeBalance-DSt1VUWC.d.cts} +1 -1
  29. package/package.json +19 -19
  30. package/dist/chunk-52HU3266.js +0 -6
  31. package/dist/chunk-52HU3266.js.map +0 -1
  32. package/dist/chunk-ITJU3AYW.cjs +0 -6
  33. package/dist/chunk-ITJU3AYW.cjs.map +0 -1
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Nova Connect
1
+ # TUWA Nova Connect
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)
@@ -26,7 +26,6 @@ Built on top of the Satellite Connect ecosystem, Nova Connect offers a unified i
26
26
  - **♿ Accessibility**: Full ARIA and keyboard navigation support.
27
27
  - **🎭 Internationalization**: Support for multiple languages.
28
28
  - **🔄 State Management**: Zustand-based store for efficient state management.
29
- - **📱 Responsiveness**: Mobile-first design.
30
29
 
31
30
  ---
32
31
 
@@ -34,7 +33,7 @@ Built on top of the Satellite Connect ecosystem, Nova Connect offers a unified i
34
33
 
35
34
  ### Requirements
36
35
  - React 19+
37
- - Node.js 24+
36
+ - Node.js 20+
38
37
  - TypeScript 5.9+
39
38
 
40
39
  ```bash
@@ -56,55 +55,66 @@ yarn add @tuwaio/nova-connect @tuwaio/satellite-core @tuwaio/orbit-core @tuwaio/
56
55
 
57
56
  ```tsx
58
57
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
59
- import { satelliteEVMAdapter } from '@tuwaio/satellite-evm';
60
- import { SatelliteConnectProvider, NovaConnectProvider } from '@tuwaio/nova-connect';
58
+ import { satelliteEVMAdapter, createDefaultTransports, initAllConnectors } from '@tuwaio/satellite-evm';
59
+ import { NovaConnectProvider } from '@tuwaio/nova-connect';
60
+ import { SatelliteConnectProvider } from '@tuwaio/nova-connect/satellite';
61
61
  import { EVMWalletsWatcher } from '@tuwaio/nova-connect/evm';
62
62
  import { SolanaWalletsWatcher } from '@tuwaio/nova-connect/solana';
63
- import { initializeSolanaMobileConnectors, satelliteSolanaAdapter } from '@tuwaio/satellite-solana';
64
- import { createDefaultTransports, initAllConnectors } from '@tuwaio/satellite-evm';
65
- import { createConfig } from '@wagmi/core';
66
- import { ReactNode } from 'react';
63
+ import { satelliteSolanaAdapter } from '@tuwaio/satellite-solana';
67
64
  import { WagmiProvider } from 'wagmi';
68
- import { Chain, mainnet, polygon, arbitrum } from 'viem/chains';
65
+ import { ReactNode } from 'react';
66
+ import { createConfig, http } from '@wagmi/core';
67
+ import { mainnet, sepolia } from 'viem/chains';
68
+ import type { Chain } from 'viem/chains';
69
69
 
70
70
  export const appConfig = {
71
- appName: 'My Nova Connect App',
72
- };
73
-
74
- export const solanaRPCUrls = {
75
- mainnet: 'https://api.mainnet-beta.solana.com',
71
+ appName: 'Satellite EVM Test App',
72
+ // Ensure you have WalletConnect Project ID in your environment variables
73
+ projectId: process.env.NEXT_PUBLIC_WALLET_PROJECT_ID ?? 'YOUR_OWN_PROJECT_ID',
76
74
  };
77
75
 
78
- export const appEVMChains = [mainnet, polygon, arbitrum] as readonly [Chain, ...Chain[]];
76
+ export const appEVMChains = [
77
+ mainnet,
78
+ sepolia,
79
+ ] as readonly [Chain, ...Chain[]];
79
80
 
80
81
  export const wagmiConfig = createConfig({
81
82
  connectors: initAllConnectors({
82
83
  ...appConfig,
84
+ // Optional: Add app details for WalletConnect modal
85
+ description: 'My awesome dApp',
86
+ appUrl: '[https://my-dapp.com](https://my-dapp.com)',
87
+ appIcons: ['[https://my-dapp.com/icon.png](https://my-dapp.com/icon.png)'],
83
88
  }),
84
- transports: createDefaultTransports(appEVMChains),
89
+ transports: createDefaultTransports(appEVMChains), // Automatically creates http transports
85
90
  chains: appEVMChains,
86
- ssr: true,
87
- syncConnectedChain: true,
91
+ ssr: true, // Enable SSR support if needed (e.g., in Next.js)
88
92
  });
89
93
 
90
- const queryClient = new QueryClient();
94
+ export const solanaRPCUrls = {
95
+ devnet: 'https://api.devnet.solana.com',
96
+ };
91
97
 
92
- initializeSolanaMobileConnectors({
93
- rpcUrls: solanaRPCUrls,
94
- ...appConfig,
95
- });
98
+
99
+ const queryClient = new QueryClient();
96
100
 
97
101
  export function Providers({ children }: { children: ReactNode }) {
98
102
  return (
99
103
  <WagmiProvider config={wagmiConfig}>
100
104
  <QueryClientProvider client={queryClient}>
101
105
  <SatelliteConnectProvider
102
- adapters={[satelliteEVMAdapter({ wagmiConfig }), satelliteSolanaAdapter({ rpcUrls: solanaRPCUrls })]}
103
- appName={appConfig.appName}
106
+ adapter={[satelliteEVMAdapter(wagmiConfig), satelliteSolanaAdapter({ rpcUrls: solanaRPCUrls })]}
107
+ autoConnect={true}
104
108
  >
105
- <EVMWalletsWatcher />
109
+ <EVMWalletsWatcher wagmiConfig={wagmiConfig} />
106
110
  <SolanaWalletsWatcher />
107
- <NovaConnectProvider>
111
+ <NovaConnectProvider
112
+ appChains={appEVMChains}
113
+ solanaRPCUrls={solanaRPCUrls}
114
+ withImpersonated
115
+ withBalance
116
+ withChain
117
+ >
108
118
  {children}
109
119
  </NovaConnectProvider>
110
120
  </SatelliteConnectProvider>
@@ -117,18 +127,12 @@ export function Providers({ children }: { children: ReactNode }) {
117
127
  ### Using ConnectButton
118
128
 
119
129
  ```tsx
120
- import { ConnectButton } from '@tuwaio/nova-connect';
130
+ import { ConnectButton } from '@tuwaio/nova-connect/components';
121
131
 
122
132
  function App() {
123
133
  return (
124
134
  <div>
125
- <ConnectButton
126
- appChains={appEVMChains}
127
- solanaRPCUrls={solanaRPCUrls}
128
- withImpersonated
129
- withBalance
130
- withChain
131
- />
135
+ <ConnectButton />
132
136
  </div>
133
137
  );
134
138
  }
@@ -141,7 +145,6 @@ function App() {
141
145
  ### 1. **ConnectButton**
142
146
 
143
147
  - Main component for wallet connection.
144
- - Built-in support for balance display and network selector.
145
148
  - Full customization system.
146
149
 
147
150
  ### 2. **NovaConnectProvider**
@@ -150,10 +153,6 @@ function App() {
150
153
  - Customizable error handling.
151
154
  - Flexible internationalization system.
152
155
 
153
- ### 3. **Hooks**
154
-
155
- - `useWalletBalance`: Get the wallet balance.
156
-
157
156
  -----
158
157
 
159
158
  ## 🌍 Internationalization
@@ -198,7 +197,3 @@ If you find this library useful, please consider supporting its development. Eve
198
197
  ## 📄 License
199
198
 
200
199
  This project is licensed under the **Apache-2.0 License** - see the [LICENSE](./LICENSE) file for details.
201
-
202
- ## 👥 Contributors
203
-
204
- - **Oleksandr Tkach** - [GitHub](https://github.com/Argeare5)
@@ -2,11 +2,11 @@ import { Dialog, DialogContent, StarsBackground } from '@tuwaio/nova-core';
2
2
  import { TargetAndTransition, VariantLabels, LegacyAnimationControls, Transition, AnyResolvedKeyframe, HTMLMotionProps, Variants, Easing, motion } from 'framer-motion';
3
3
  import * as React$1 from 'react';
4
4
  import React__default, { ComponentType, ReactNode, ComponentPropsWithoutRef } from 'react';
5
- import { B as ButtonTxStatus, b as NovaConnectProviderProps, h as useNovaConnectLabels, p as NativeBalanceResult, C as ConnectContentType } from './useWalletNativeBalance-DCdB3_v2.js';
5
+ import { B as ButtonTxStatus, b as NovaConnectProviderProps, h as useNovaConnectLabels, p as NativeBalanceResult, C as ConnectContentType } from './useWalletNativeBalance-CEASeZ6Z.js';
6
6
  import { BaseWallet } from '@tuwaio/satellite-core';
7
- import { I as InitialChains } from './types-DGsiEwne.js';
8
7
  import * as react_jsx_runtime from 'react/jsx-runtime';
9
8
  import * as Select from '@radix-ui/react-select';
9
+ import { I as InitialChains } from './types-DGsiEwne.js';
10
10
  import { Transaction } from '@tuwaio/pulsar-core';
11
11
  import { OrbitAdapter, WalletType } from '@tuwaio/orbit-core';
12
12
  import { Connector } from '@tuwaio/satellite-react';
@@ -1561,7 +1561,7 @@ type ConnectButtonCustomization = {
1561
1561
  /**
1562
1562
  * Base props for ConnectButton component
1563
1563
  */
1564
- type ConnectButtonProps = InitialChains & {
1564
+ type ConnectButtonProps = Pick<NovaConnectProviderProps, 'transactionPool'> & {
1565
1565
  /** CSS classes to apply to the button */
1566
1566
  className?: string;
1567
1567
  /** Customization options */
@@ -3220,7 +3220,7 @@ type ConnectedModalCustomization = {
3220
3220
  /**
3221
3221
  * Props for the ConnectedModal component
3222
3222
  */
3223
- interface ConnectedModalProps extends Omit<ConnectButtonProps, 'className' | 'customization'>, Pick<NovaConnectProviderProps, 'transactionPool' | 'pulsarAdapter'> {
3223
+ interface ConnectedModalProps extends Omit<ConnectButtonProps, 'className' | 'customization'>, Pick<NovaConnectProviderProps, 'transactionPool' | 'pulsarAdapter' | 'appChains' | 'solanaRPCUrls'> {
3224
3224
  /** Additional CSS classes for the modal */
3225
3225
  className?: string;
3226
3226
  /** Customization options */
@@ -2,11 +2,11 @@ import { Dialog, DialogContent, StarsBackground } from '@tuwaio/nova-core';
2
2
  import { TargetAndTransition, VariantLabels, LegacyAnimationControls, Transition, AnyResolvedKeyframe, HTMLMotionProps, Variants, Easing, motion } from 'framer-motion';
3
3
  import * as React$1 from 'react';
4
4
  import React__default, { ComponentType, ReactNode, ComponentPropsWithoutRef } from 'react';
5
- import { B as ButtonTxStatus, b as NovaConnectProviderProps, h as useNovaConnectLabels, p as NativeBalanceResult, C as ConnectContentType } from './useWalletNativeBalance-DKa97yY5.cjs';
5
+ import { B as ButtonTxStatus, b as NovaConnectProviderProps, h as useNovaConnectLabels, p as NativeBalanceResult, C as ConnectContentType } from './useWalletNativeBalance-DSt1VUWC.cjs';
6
6
  import { BaseWallet } from '@tuwaio/satellite-core';
7
- import { I as InitialChains } from './types-DGsiEwne.cjs';
8
7
  import * as react_jsx_runtime from 'react/jsx-runtime';
9
8
  import * as Select from '@radix-ui/react-select';
9
+ import { I as InitialChains } from './types-DGsiEwne.cjs';
10
10
  import { Transaction } from '@tuwaio/pulsar-core';
11
11
  import { OrbitAdapter, WalletType } from '@tuwaio/orbit-core';
12
12
  import { Connector } from '@tuwaio/satellite-react';
@@ -1561,7 +1561,7 @@ type ConnectButtonCustomization = {
1561
1561
  /**
1562
1562
  * Base props for ConnectButton component
1563
1563
  */
1564
- type ConnectButtonProps = InitialChains & {
1564
+ type ConnectButtonProps = Pick<NovaConnectProviderProps, 'transactionPool'> & {
1565
1565
  /** CSS classes to apply to the button */
1566
1566
  className?: string;
1567
1567
  /** Customization options */
@@ -3220,7 +3220,7 @@ type ConnectedModalCustomization = {
3220
3220
  /**
3221
3221
  * Props for the ConnectedModal component
3222
3222
  */
3223
- interface ConnectedModalProps extends Omit<ConnectButtonProps, 'className' | 'customization'>, Pick<NovaConnectProviderProps, 'transactionPool' | 'pulsarAdapter'> {
3223
+ interface ConnectedModalProps extends Omit<ConnectButtonProps, 'className' | 'customization'>, Pick<NovaConnectProviderProps, 'transactionPool' | 'pulsarAdapter' | 'appChains' | 'solanaRPCUrls'> {
3224
3224
  /** Additional CSS classes for the modal */
3225
3225
  className?: string;
3226
3226
  /** Customization options */
@@ -1,2 +1,2 @@
1
- 'use strict';var chunkQERPNHKX_cjs=require('./chunk-QERPNHKX.cjs'),chunkOA6MB7CZ_cjs=require('./chunk-OA6MB7CZ.cjs'),novaCore=require('@tuwaio/nova-core'),orbitCore=require('@tuwaio/orbit-core'),react=require('react');function ne(e){let{abbreviateSymbols:t=12,maxNameLength:s=30,autoRetry:o=false,retryDelay:i=3e3}=e,n=chunkOA6MB7CZ_cjs.h(c=>c.activeWallet),N=chunkOA6MB7CZ_cjs.h(c=>c.getAdapter),a=react.useMemo(()=>n?.address,[n?.address]),u=react.useMemo(()=>n?.walletType,[n?.walletType]),r=react.useMemo(()=>u?N(orbitCore.getAdapterFromWalletType(u??`${orbitCore.OrbitAdapter.EVM}:not-connected`)):null,[N,u]),[d,b]=react.useState(null),[O,l]=react.useState(null),[C,f]=react.useState(false),[g,v]=react.useState(null),x=react.useRef(null),T=react.useRef(null),R=react.useMemo(()=>{if(!r)return {hasNameResolver:false,hasAvatarResolver:false};let c="getName"in r&&typeof r.getName=="function",p="getAvatar"in r&&typeof r.getAvatar=="function";return {hasNameResolver:c,hasAvatarResolver:p}},[r]),y=react.useCallback(()=>{x.current&&(x.current.abort(),x.current=null),T.current!==null&&(clearTimeout(T.current),T.current=null);},[]),L=react.useCallback(async()=>{if(y(),!a||!r||!R.hasNameResolver){b(null),l(null),f(false),v(null);return}x.current=new AbortController;let{signal:c}=x.current;f(true),v(null),b(null),l(null);try{if(c.aborted)return;let p=await r.getName?.(a);if(c.aborted)return;if(p&&(b(p),R.hasAvatarResolver))try{let h=await r.getAvatar?.(p);c.aborted||l(h??null);}catch(h){console.warn("Failed to fetch avatar:",h),c.aborted||l(null);}}catch(p){if(c.aborted)return;let h=p instanceof Error?p.message:"Failed to fetch name service data";console.error("Failed to fetch name service data:",p),v(h),b(null),l(null),o&&(T.current=setTimeout(()=>{L();},i));}finally{c.aborted||f(false);}},[a,r,R,o,i,y]),U=react.useCallback(()=>{v(null),L();},[L]);react.useEffect(()=>(L(),y),[L,y]),react.useEffect(()=>y,[y]);let H=react.useMemo(()=>d?d.length>s?novaCore.textCenterEllipsis(d,t,t):d:a?novaCore.textCenterEllipsis(a,t,t):void 0,[d,a,s,t]);return {ensName:d,ensAvatar:O,isLoading:C,ensNameAbbreviated:H,error:g,retry:U}}var P=class extends Error{constructor(t="useNovaConnect must be used within NovaConnectProvider"){super(t),this.name="NovaConnectProviderError";}},I=react.createContext(void 0),re=()=>{let e=react.useContext(I);if(!e)throw new P;return e},se=()=>react.useContext(I)!==void 0,le=()=>react.useContext(I)??null;var Q=react.createContext(chunkQERPNHKX_cjs.a),M=()=>react.useContext(Q),pe=e=>M()[e],fe=e=>{let t=M(),s={};for(let o of e)s[o]=t[o];return s},ve=(e,t)=>!!e[t]?.trim(),be=e=>{let t=M(),o={actions:["connectWallet","disconnect","connecting","connected","tryAgain","back","connect","close"],states:["success","error","replaced","loading","idle"],accessibility:["chainSelector","closeModal","selectChain","walletControls","openWalletModal"],transactions:["transactionLoading","transactionSuccess","transactionError","transactionReplaced","recent"]}[e],i={};for(let n of o)i[n]=t[n];return i},Ce=e=>e===chunkQERPNHKX_cjs.a,ye=(e,t,s)=>{let o=e[t];return o&&o.trim()?o:s||chunkQERPNHKX_cjs.a[t]||t.toString()},me=(e,t)=>{let s={};for(let o of t)s[o]=e[o];return s};function he(){let[e,t]=react.useState({}),[s,o]=react.useState(false),i=react.useRef(null),n=chunkOA6MB7CZ_cjs.h(l=>l.activeWallet),N=chunkOA6MB7CZ_cjs.h(l=>l.getAdapter),a=react.useMemo(()=>n?.chainId&&n?.address?`${n.address}-${n.chainId}`:null,[n?.chainId,n?.address]),u=react.useMemo(()=>n?.walletType?N(orbitCore.getAdapterFromWalletType(n.walletType)):null,[N,n?.walletType]),r=react.useMemo(()=>u&&"getBalance"in u&&typeof u.getBalance=="function",[u]),d=react.useCallback(async(l=false)=>{if(!n?.address||!u||!n?.chainId||!a||!r){o(false);return}let C=`${a}-${Date.now()}`;if(i.current=C,!l&&e[a]){o(false);return}o(true);try{let f=await u.getBalance(n.address,n.chainId);i.current===C&&t(g=>({...g,[a]:f}));}catch(f){console.error(`Failed to fetch native balance for ${a}:`,f),l&&i.current===C&&t(g=>{let v={...g};return delete v[a],v});}finally{i.current===C&&o(false);}},[n?.address,u,n?.chainId,a,r,e]),b=react.useCallback(()=>{d(true);},[d]);return react.useEffect(()=>{a&&r&&!e[a]?d(false):(!a||!r)&&o(false);},[a,r,e,d]),react.useEffect(()=>()=>{i.current=null;},[]),{balance:react.useMemo(()=>a&&e[a]||null,[a,e]),isLoading:s,refetch:b}}exports.a=ne;exports.b=P;exports.c=I;exports.d=re;exports.e=se;exports.f=le;exports.g=Q;exports.h=M;exports.i=pe;exports.j=fe;exports.k=ve;exports.l=be;exports.m=Ce;exports.n=ye;exports.o=me;exports.p=he;//# sourceMappingURL=chunk-MVAF36Z4.cjs.map
2
- //# sourceMappingURL=chunk-MVAF36Z4.cjs.map
1
+ 'use strict';var chunkQERPNHKX_cjs=require('./chunk-QERPNHKX.cjs'),chunkOA6MB7CZ_cjs=require('./chunk-OA6MB7CZ.cjs'),novaCore=require('@tuwaio/nova-core'),orbitCore=require('@tuwaio/orbit-core'),react=require('react');function ne(e){let{abbreviateSymbols:t=12,maxNameLength:s=30,autoRetry:o=false,retryDelay:i=3e3}=e,n=chunkOA6MB7CZ_cjs.h(c=>c.activeWallet),N=chunkOA6MB7CZ_cjs.h(c=>c.getAdapter),a=react.useMemo(()=>n?.address,[n?.address]),u=react.useMemo(()=>n?.walletType,[n?.walletType]),r=react.useMemo(()=>u?N(orbitCore.getAdapterFromWalletType(u??`${orbitCore.OrbitAdapter.EVM}:not-connected`)):null,[N,u]),[d,b]=react.useState(null),[O,l]=react.useState(null),[C,f]=react.useState(false),[g,v]=react.useState(null),x=react.useRef(null),T=react.useRef(null),R=react.useMemo(()=>{if(!r)return {hasNameResolver:false,hasAvatarResolver:false};let c="getName"in r&&typeof r.getName=="function",p="getAvatar"in r&&typeof r.getAvatar=="function";return {hasNameResolver:c,hasAvatarResolver:p}},[r]),y=react.useCallback(()=>{x.current&&(x.current.abort(),x.current=null),T.current!==null&&(clearTimeout(T.current),T.current=null);},[]),L=react.useCallback(async()=>{if(y(),!a||!r||!R.hasNameResolver){b(null),l(null),f(false),v(null);return}x.current=new AbortController;let{signal:c}=x.current;f(true),v(null),b(null),l(null);try{if(c.aborted)return;let p=await r.getName?.(a);if(c.aborted)return;if(p&&(b(p),R.hasAvatarResolver))try{let h=await r.getAvatar?.(p);c.aborted||l(h??null);}catch(h){console.warn("Failed to fetch avatar:",h),c.aborted||l(null);}}catch(p){if(c.aborted)return;let h=p instanceof Error?p.message:"Failed to fetch name service data";console.error("Failed to fetch name service data:",p),v(h),b(null),l(null),o&&(T.current=setTimeout(()=>{L();},i));}finally{c.aborted||f(false);}},[a,r,R,o,i,y]),U=react.useCallback(()=>{v(null),L();},[L]);react.useEffect(()=>(L(),y),[L,y]),react.useEffect(()=>y,[y]);let H=react.useMemo(()=>d?d.length>s?novaCore.textCenterEllipsis(d,t,t):d:a?novaCore.textCenterEllipsis(a,t,t):void 0,[d,a,s,t]);return {ensName:d,ensAvatar:O,isLoading:C,ensNameAbbreviated:H,error:g,retry:U}}var P=class extends Error{constructor(t="useNovaConnect must be used within NovaConnectProvider"){super(t),this.name="NovaConnectProviderError";}},I=react.createContext(void 0),re=()=>{let e=react.useContext(I);if(!e)throw new P;return e},se=()=>react.useContext(I)!==void 0,le=()=>react.useContext(I)??null;var Q=react.createContext(chunkQERPNHKX_cjs.a),M=()=>react.useContext(Q),pe=e=>M()[e],fe=e=>{let t=M(),s={};for(let o of e)s[o]=t[o];return s},ve=(e,t)=>!!e[t]?.trim(),be=e=>{let t=M(),o={actions:["connectWallet","disconnect","connecting","connected","tryAgain","back","connect","close"],states:["success","error","replaced","loading","idle"],accessibility:["chainSelector","closeModal","selectChain","walletControls","openWalletModal"],transactions:["transactionLoading","transactionSuccess","transactionError","transactionReplaced","recent"]}[e],i={};for(let n of o)i[n]=t[n];return i},Ce=e=>e===chunkQERPNHKX_cjs.a,ye=(e,t,s)=>{let o=e[t];return o&&o.trim()?o:s||chunkQERPNHKX_cjs.a[t]||t.toString()},me=(e,t)=>{let s={};for(let o of t)s[o]=e[o];return s};function he(){let[e,t]=react.useState({}),[s,o]=react.useState(false),i=react.useRef(null),n=chunkOA6MB7CZ_cjs.h(l=>l.activeWallet),N=chunkOA6MB7CZ_cjs.h(l=>l.getAdapter),a=react.useMemo(()=>n?.chainId&&n?.address?`${n.address}-${n.chainId}`:null,[n?.chainId,n?.address]),u=react.useMemo(()=>n?.walletType?N(orbitCore.getAdapterFromWalletType(n.walletType)):null,[N,n?.walletType]),r=react.useMemo(()=>u&&"getBalance"in u&&typeof u.getBalance=="function",[u]),d=react.useCallback(async(l=false)=>{if(!n?.address||!u||!n?.chainId||!a||!r){o(false);return}let C=`${a}-${Date.now()}`;if(i.current=C,!l&&e[a]){o(false);return}o(true);try{let f=await u.getBalance(n.address,n.chainId);i.current===C&&t(g=>({...g,[a]:f}));}catch(f){console.error(`Failed to fetch native balance for ${a}:`,f),l&&i.current===C&&t(g=>{let v={...g};return delete v[a],v});}finally{i.current===C&&o(false);}},[n?.address,u,n?.chainId,a,r,e]),b=react.useCallback(()=>{d(true);},[d]);return react.useEffect(()=>{a&&r&&!e[a]?d(false):(!a||!r)&&o(false);},[a,r,e,d]),react.useEffect(()=>()=>{i.current=null;},[]),{balance:react.useMemo(()=>a&&e[a]||null,[a,e]),isLoading:s,refetch:b}}exports.a=ne;exports.b=P;exports.c=I;exports.d=re;exports.e=se;exports.f=le;exports.g=Q;exports.h=M;exports.i=pe;exports.j=fe;exports.k=ve;exports.l=be;exports.m=Ce;exports.n=ye;exports.o=me;exports.p=he;//# sourceMappingURL=chunk-7FTV55DQ.cjs.map
2
+ //# sourceMappingURL=chunk-7FTV55DQ.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hooks/useGetWalletNameAndAvatar.ts","../src/hooks/useNovaConnect.ts","../src/hooks/useNovaConnectLabels.ts","../src/hooks/useWalletNativeBalance.ts"],"names":["useGetWalletNameAndAvatar","options","abbreviateSymbols","maxNameLength","autoRetry","retryDelay","activeWallet","useSatelliteConnectStore","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","NovaConnectProviderError","message","NovaConnectProviderContext","createContext","useNovaConnect","context","useContext","useHasNovaConnectContext","useNovaConnectOptional","NovaConnectLabelsContext","defaultLabels","useNovaConnectLabels","useNovaConnectLabel","key","useNovaConnectLabelsSubset","keys","allLabels","subset","hasLabel","labels","useLabelsByCategory","category","categoryLabels","isDefaultLabels","getLabelWithFallback","fallback","value","createLabelsSubset","useWalletNativeBalance","balanceCache","setBalanceCache","fetchOperationRef","cacheKey","hasBalanceResolver","fetchBalance","forceRefresh","operationId","balanceResult","prevCache","newCache","refetch"],"mappings":"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","file":"chunk-MVAF36Z4.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 { useSatelliteConnectStore } from '../satellite';\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 /** 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 } = options;\n\n // Store state selectors - memoized for performance\n const activeWallet = useSatelliteConnectStore((store) => store.activeWallet);\n const getAdapter = useSatelliteConnectStore((store) => store.getAdapter);\n\n // Memoize wallet address and adapter for dependency tracking\n const walletAddress = useMemo(() => activeWallet?.address, [activeWallet?.address]);\n const walletType = useMemo(() => activeWallet?.walletType, [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 { OrbitAdapter } from '@tuwaio/orbit-core';\nimport { Transaction, TransactionPool, TxAdapter } from '@tuwaio/pulsar-core';\nimport { createContext, useContext } from 'react';\n\nimport { NovaConnectLabels } from '../i18n';\nimport { InitialChains } from '../types';\n\nexport type ButtonTxStatus = 'idle' | 'loading' | 'succeed' | 'failed' | 'replaced';\nexport type ConnectContentType = 'network' | 'connectors' | 'about' | 'getWallet' | 'connecting' | 'impersonate';\nexport type ConnectedContentType = 'main' | 'transactions' | 'chains';\n\n// Provider props interface\nexport interface NovaConnectProviderProps extends InitialChains {\n /** Transaction pool for pending transactions display */\n transactionPool?: TransactionPool<Transaction>;\n /** Pulsar adapter(s) for transaction handling */\n pulsarAdapter?: TxAdapter<Transaction> | TxAdapter<Transaction>[];\n /** Whether balance should be shown */\n withBalance?: boolean;\n /** Whether chain selector should be shown */\n withChain?: boolean;\n /** Whether impersonated wallets are enabled */\n withImpersonated?: boolean;\n children: React.ReactNode;\n labels?: Partial<NovaConnectLabels>;\n}\n\n// Balance type for better type safety\nexport interface WalletBalance {\n value: string;\n symbol: string;\n}\n\n// Provider context type with better organization\nexport interface NovaConnectProviderType\n extends Omit<NovaConnectProviderProps, 'pulsarAdapter' | 'children' | 'labels'> {\n // Modal states\n isConnectModalOpen: boolean;\n setIsConnectModalOpen: (value: boolean) => void;\n isConnectedModalOpen: boolean;\n setIsConnectedModalOpen: (value: boolean) => void;\n\n // Chain selection states\n isChainsListOpen: boolean;\n setIsChainsListOpen: (value: boolean) => void;\n isChainsListOpenMobile: boolean;\n setIsChainsListOpenMobile: (value: boolean) => void;\n\n // Connection states\n connectedButtonStatus: ButtonTxStatus;\n setConnectedButtonStatus: (value: ButtonTxStatus) => void;\n isConnected: boolean;\n setIsConnected: (value: boolean) => void;\n\n // Modal content types\n connectedModalContentType: ConnectedContentType;\n setConnectedModalContentType: (value: ConnectedContentType) => void;\n connectModalContentType: ConnectContentType;\n setConnectModalContentType: (value: ConnectContentType) => void;\n\n // Adapter and connector states\n selectedAdapter: OrbitAdapter | undefined;\n setSelectedAdapter: (value: OrbitAdapter | undefined) => void;\n activeConnector: string | undefined;\n setActiveConnector: (value: string | undefined) => void;\n\n // Impersonation\n impersonatedAddress: string;\n setImpersonatedAddress: (value: string) => void;\n}\n\n// Custom error for hook usage outside provider\nexport class NovaConnectProviderError extends Error {\n constructor(message = 'useNovaConnect must be used within NovaConnectProvider') {\n super(message);\n this.name = 'NovaConnectProviderError';\n }\n}\n\n// Create context with undefined default to enforce provider usage\nexport const NovaConnectProviderContext = createContext<NovaConnectProviderType | undefined>(undefined);\n\n/**\n * Hook to access NovaConnect context\n *\n * @throws {NovaConnectProviderError} When used outside of NovaConnectProvider\n * @returns {NovaConnectProviderType} The NovaConnect context value\n *\n * @example\n * ```typescript\n * function MyComponent() {\n * const { isConnected, handleConnectButtonClick } = useNovaConnect();\n *\n * return (\n * <button onClick={handleConnectButtonClick}>\n * {isConnected ? 'Connected' : 'Connect Wallet'}\n * </button>\n * );\n * }\n * ```\n */\nexport const useNovaConnect = (): NovaConnectProviderType => {\n const context = useContext(NovaConnectProviderContext);\n\n if (!context) {\n throw new NovaConnectProviderError();\n }\n\n return context;\n};\n\n/**\n * Hook to check if NovaConnect context is available\n *\n * @returns {boolean} True if context is available, false otherwise\n *\n * @example\n * ```typescript\n * function ConditionalComponent() {\n * const hasContext = useHasNovaConnectContext();\n *\n * if (!hasContext) {\n * return <div>NovaConnect provider not found</div>;\n * }\n *\n * return <ConnectedComponent />;\n * }\n * ```\n */\nexport const useHasNovaConnectContext = (): boolean => {\n const context = useContext(NovaConnectProviderContext);\n return context !== undefined;\n};\n\n/**\n * Optional hook that returns null if provider is not available\n *\n * @returns {NovaConnectProviderType | null} Context value or null if not available\n *\n * @example\n * ```typescript\n * function OptionalComponent() {\n * const context = useNovaConnectOptional();\n *\n * if (!context) {\n * return <div>No wallet provider available</div>;\n * }\n *\n * return <div>Connected: {context.isConnected}</div>;\n * }\n * ```\n */\nexport const useNovaConnectOptional = (): NovaConnectProviderType | null => {\n const context = useContext(NovaConnectProviderContext);\n return context ?? null;\n};\n","import { createContext, useContext } from 'react';\n\nimport { defaultLabels, NovaConnectLabels } from '../i18n';\n\n/**\n * React Context for storing and providing the UI labels.\n * It is initialized with the default English labels, ensuring that components\n * work even without an explicit provider.\n */\nexport const NovaConnectLabelsContext = createContext<NovaConnectLabels>(defaultLabels);\n\n/**\n * A custom hook to easily access the i18n labels from any component\n * within the `NovaConnectLabelsProvider` tree.\n *\n * This hook provides type-safe access to all UI labels and automatically\n * falls back to default English labels if no provider is found.\n *\n * @returns {NovaConnectLabels} The complete object of UI labels for the current locale.\n *\n * @example\n * ```typescript\n * import { useNovaConnectLabels } from './hooks/useNovaConnectLabels';\n *\n * function MyComponent() {\n * const labels = useNovaConnectLabels();\n *\n * return (\n * <div>\n * <h1>{labels.connectWallet}</h1>\n * <button>{labels.connect}</button>\n * <p aria-label={labels.walletBalance}>{formattedBalance}</p>\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Destructuring specific labels for better performance\n * function ConnectButton() {\n * const { connectWallet, connecting, connected } = useNovaConnectLabels();\n *\n * return (\n * <button>\n * {isConnecting ? connecting : isConnected ? connected : connectWallet}\n * </button>\n * );\n * }\n * ```\n */\nexport const useNovaConnectLabels = (): NovaConnectLabels => {\n return useContext(NovaConnectLabelsContext);\n};\n\n/**\n * Hook to get a specific label by key path with type safety\n *\n * @param key The label key to retrieve\n * @returns The specific label value\n *\n * @example\n * ```typescript\n * function MyComponent() {\n * const connectLabel = useNovaConnectLabel('connectWallet');\n * const errorLabel = useNovaConnectLabel('connectionError');\n *\n * return <button>{connectLabel}</button>;\n * }\n * ```\n */\nexport const useNovaConnectLabel = <K extends keyof NovaConnectLabels>(key: K): NovaConnectLabels[K] => {\n const labels = useNovaConnectLabels();\n return labels[key];\n};\n\n/**\n * Hook to get multiple specific labels for better performance\n *\n * @param keys Array of label keys to retrieve\n * @returns Object with only the requested labels\n *\n * @example\n * ```typescript\n * function ConnectModal() {\n * const { connectWallet, connecting, disconnect } = useNovaConnectLabelsSubset(['connectWallet', 'connecting', 'disconnect']);\n *\n * return (\n * <div>\n * <h2>{connectWallet}</h2>\n * <span>{connecting}</span>\n * <button>{disconnect}</button>\n * </div>\n * );\n * }\n * ```\n */\nexport const useNovaConnectLabelsSubset = <K extends keyof NovaConnectLabels>(\n keys: K[],\n): Pick<NovaConnectLabels, K> => {\n const allLabels = useNovaConnectLabels();\n\n const subset = {} as Pick<NovaConnectLabels, K>;\n for (const key of keys) {\n subset[key] = allLabels[key];\n }\n\n return subset;\n};\n\n/**\n * Type-safe helper to check if a label exists\n *\n * @param labels The labels object\n * @param key The key to check\n * @returns Whether the key exists and has a non-empty value\n */\nexport const hasLabel = (labels: NovaConnectLabels, key: keyof NovaConnectLabels): boolean => {\n return Boolean(labels[key]?.trim());\n};\n\n/**\n * Utility type for extracting label keys by category\n */\nexport type LabelCategory = {\n actions: Extract<\n keyof NovaConnectLabels,\n 'connectWallet' | 'disconnect' | 'connecting' | 'connected' | 'tryAgain' | 'back' | 'connect' | 'close'\n >;\n states: Extract<keyof NovaConnectLabels, 'success' | 'error' | 'replaced' | 'loading' | 'idle'>;\n accessibility: Extract<\n keyof NovaConnectLabels,\n 'chainSelector' | 'closeModal' | 'selectChain' | 'walletControls' | 'openWalletModal'\n >;\n transactions: Extract<\n keyof NovaConnectLabels,\n 'transactionLoading' | 'transactionSuccess' | 'transactionError' | 'transactionReplaced' | 'recent'\n >;\n};\n\n/**\n * Hook to get labels by category for better organization\n *\n * @param category The category of labels to retrieve\n * @returns Object with labels from the specified category\n */\nexport const useLabelsByCategory = <T extends keyof LabelCategory>(\n category: T,\n): Pick<NovaConnectLabels, LabelCategory[T]> => {\n const allLabels = useNovaConnectLabels();\n\n const categoryKeys: Record<keyof LabelCategory, (keyof NovaConnectLabels)[]> = {\n actions: ['connectWallet', 'disconnect', 'connecting', 'connected', 'tryAgain', 'back', 'connect', 'close'],\n states: ['success', 'error', 'replaced', 'loading', 'idle'],\n accessibility: ['chainSelector', 'closeModal', 'selectChain', 'walletControls', 'openWalletModal'],\n transactions: ['transactionLoading', 'transactionSuccess', 'transactionError', 'transactionReplaced', 'recent'],\n };\n\n const keys = categoryKeys[category] as LabelCategory[T][];\n const categoryLabels = {} as Pick<NovaConnectLabels, LabelCategory[T]>;\n\n for (const key of keys) {\n // eslint-disable-next-line\n (categoryLabels as any)[key] = allLabels[key as keyof NovaConnectLabels];\n }\n\n return categoryLabels;\n};\n\n/**\n * Utility function to check if labels are default ones (for external use)\n * This is a regular function, not a hook, so it can be used anywhere\n *\n * @param labels The labels to check\n * @returns Whether the labels are the default English labels\n *\n * @example\n * ```typescript\n * function SomeUtilityFunction(labels: NovaConnectLabels) {\n * if (isDefaultLabels(labels)) {\n * console.log('Using default English labels');\n * }\n * }\n * ```\n */\nexport const isDefaultLabels = (labels: NovaConnectLabels): boolean => {\n return labels === defaultLabels;\n};\n\n/**\n * Utility function to get a formatted label with fallback\n *\n * @param labels The labels object\n * @param key The label key\n * @param fallback Optional fallback text\n * @returns The label value or fallback\n *\n * @example\n * ```typescript\n * const buttonText = getLabelWithFallback(labels, 'connectWallet', 'Connect');\n * ```\n */\nexport const getLabelWithFallback = (\n labels: NovaConnectLabels,\n key: keyof NovaConnectLabels,\n fallback?: string,\n): string => {\n const value = labels[key];\n if (value && value.trim()) {\n return value;\n }\n return fallback || defaultLabels[key] || key.toString();\n};\n\n/**\n * Utility function to create a labels subset (for use outside of React components)\n *\n * @param labels The source labels object\n * @param keys Array of keys to extract\n * @returns Object with only the requested labels\n *\n * @example\n * ```typescript\n * const actionLabels = createLabelsSubset(labels, ['connect', 'disconnect', 'tryAgain']);\n * ```\n */\nexport const createLabelsSubset = <K extends keyof NovaConnectLabels>(\n labels: NovaConnectLabels,\n keys: K[],\n): Pick<NovaConnectLabels, K> => {\n const subset = {} as Pick<NovaConnectLabels, K>;\n for (const key of keys) {\n subset[key] = labels[key];\n }\n return subset;\n};\n","import { getAdapterFromWalletType } from '@tuwaio/orbit-core';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { useSatelliteConnectStore } from '../satellite';\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(): 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 activeWallet = useSatelliteConnectStore((store) => store.activeWallet);\n const getAdapter = useSatelliteConnectStore((store) => store.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
+ {"version":3,"sources":["../src/hooks/useGetWalletNameAndAvatar.ts","../src/hooks/useNovaConnect.ts","../src/hooks/useNovaConnectLabels.ts","../src/hooks/useWalletNativeBalance.ts"],"names":["useGetWalletNameAndAvatar","options","abbreviateSymbols","maxNameLength","autoRetry","retryDelay","activeWallet","useSatelliteConnectStore","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","NovaConnectProviderError","message","NovaConnectProviderContext","createContext","useNovaConnect","context","useContext","useHasNovaConnectContext","useNovaConnectOptional","NovaConnectLabelsContext","defaultLabels","useNovaConnectLabels","useNovaConnectLabel","key","useNovaConnectLabelsSubset","keys","allLabels","subset","hasLabel","labels","useLabelsByCategory","category","categoryLabels","isDefaultLabels","getLabelWithFallback","fallback","value","createLabelsSubset","useWalletNativeBalance","balanceCache","setBalanceCache","fetchOperationRef","cacheKey","hasBalanceResolver","fetchBalance","forceRefresh","operationId","balanceResult","prevCache","newCache","refetch"],"mappings":"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","file":"chunk-7FTV55DQ.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 { useSatelliteConnectStore } from '../satellite';\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 /** 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 } = options;\n\n // Store state selectors - memoized for performance\n const activeWallet = useSatelliteConnectStore((store) => store.activeWallet);\n const getAdapter = useSatelliteConnectStore((store) => store.getAdapter);\n\n // Memoize wallet address and adapter for dependency tracking\n const walletAddress = useMemo(() => activeWallet?.address, [activeWallet?.address]);\n const walletType = useMemo(() => activeWallet?.walletType, [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 { OrbitAdapter } from '@tuwaio/orbit-core';\nimport { Transaction, TransactionPool, TxAdapter } from '@tuwaio/pulsar-core';\nimport { createContext, useContext } from 'react';\n\nimport { NovaConnectLabels } from '../i18n';\nimport { InitialChains } from '../types';\n\nexport type ButtonTxStatus = 'idle' | 'loading' | 'succeed' | 'failed' | 'replaced';\nexport type ConnectContentType = 'network' | 'connectors' | 'about' | 'getWallet' | 'connecting' | 'impersonate';\nexport type ConnectedContentType = 'main' | 'transactions' | 'chains';\n\n// Provider props interface\nexport interface NovaConnectProviderProps extends InitialChains {\n /** Transaction pool for pending transactions display */\n transactionPool?: TransactionPool<Transaction>;\n /** Pulsar adapter(s) for transaction handling */\n pulsarAdapter?: TxAdapter<Transaction> | TxAdapter<Transaction>[];\n /** Whether balance should be shown */\n withBalance?: boolean;\n /** Whether chain selector should be shown */\n withChain?: boolean;\n /** Whether impersonated wallets are enabled */\n withImpersonated?: boolean;\n children: React.ReactNode;\n labels?: Partial<NovaConnectLabels>;\n}\n\n// Balance type for better type safety\nexport interface WalletBalance {\n value: string;\n symbol: string;\n}\n\n// Provider context type with better organization\nexport interface NovaConnectProviderType\n extends Omit<NovaConnectProviderProps, 'pulsarAdapter' | 'children' | 'labels' | 'transactionPool'> {\n // Modal states\n isConnectModalOpen: boolean;\n setIsConnectModalOpen: (value: boolean) => void;\n isConnectedModalOpen: boolean;\n setIsConnectedModalOpen: (value: boolean) => void;\n\n // Chain selection states\n isChainsListOpen: boolean;\n setIsChainsListOpen: (value: boolean) => void;\n isChainsListOpenMobile: boolean;\n setIsChainsListOpenMobile: (value: boolean) => void;\n\n // Connection states\n connectedButtonStatus: ButtonTxStatus;\n setConnectedButtonStatus: (value: ButtonTxStatus) => void;\n isConnected: boolean;\n setIsConnected: (value: boolean) => void;\n\n // Modal content types\n connectedModalContentType: ConnectedContentType;\n setConnectedModalContentType: (value: ConnectedContentType) => void;\n connectModalContentType: ConnectContentType;\n setConnectModalContentType: (value: ConnectContentType) => void;\n\n // Adapter and connector states\n selectedAdapter: OrbitAdapter | undefined;\n setSelectedAdapter: (value: OrbitAdapter | undefined) => void;\n activeConnector: string | undefined;\n setActiveConnector: (value: string | undefined) => void;\n\n // Impersonation\n impersonatedAddress: string;\n setImpersonatedAddress: (value: string) => void;\n}\n\n// Custom error for hook usage outside provider\nexport class NovaConnectProviderError extends Error {\n constructor(message = 'useNovaConnect must be used within NovaConnectProvider') {\n super(message);\n this.name = 'NovaConnectProviderError';\n }\n}\n\n// Create context with undefined default to enforce provider usage\nexport const NovaConnectProviderContext = createContext<NovaConnectProviderType | undefined>(undefined);\n\n/**\n * Hook to access NovaConnect context\n *\n * @throws {NovaConnectProviderError} When used outside of NovaConnectProvider\n * @returns {NovaConnectProviderType} The NovaConnect context value\n *\n * @example\n * ```typescript\n * function MyComponent() {\n * const { isConnected, handleConnectButtonClick } = useNovaConnect();\n *\n * return (\n * <button onClick={handleConnectButtonClick}>\n * {isConnected ? 'Connected' : 'Connect Wallet'}\n * </button>\n * );\n * }\n * ```\n */\nexport const useNovaConnect = (): NovaConnectProviderType => {\n const context = useContext(NovaConnectProviderContext);\n\n if (!context) {\n throw new NovaConnectProviderError();\n }\n\n return context;\n};\n\n/**\n * Hook to check if NovaConnect context is available\n *\n * @returns {boolean} True if context is available, false otherwise\n *\n * @example\n * ```typescript\n * function ConditionalComponent() {\n * const hasContext = useHasNovaConnectContext();\n *\n * if (!hasContext) {\n * return <div>NovaConnect provider not found</div>;\n * }\n *\n * return <ConnectedComponent />;\n * }\n * ```\n */\nexport const useHasNovaConnectContext = (): boolean => {\n const context = useContext(NovaConnectProviderContext);\n return context !== undefined;\n};\n\n/**\n * Optional hook that returns null if provider is not available\n *\n * @returns {NovaConnectProviderType | null} Context value or null if not available\n *\n * @example\n * ```typescript\n * function OptionalComponent() {\n * const context = useNovaConnectOptional();\n *\n * if (!context) {\n * return <div>No wallet provider available</div>;\n * }\n *\n * return <div>Connected: {context.isConnected}</div>;\n * }\n * ```\n */\nexport const useNovaConnectOptional = (): NovaConnectProviderType | null => {\n const context = useContext(NovaConnectProviderContext);\n return context ?? null;\n};\n","import { createContext, useContext } from 'react';\n\nimport { defaultLabels, NovaConnectLabels } from '../i18n';\n\n/**\n * React Context for storing and providing the UI labels.\n * It is initialized with the default English labels, ensuring that components\n * work even without an explicit provider.\n */\nexport const NovaConnectLabelsContext = createContext<NovaConnectLabels>(defaultLabels);\n\n/**\n * A custom hook to easily access the i18n labels from any component\n * within the `NovaConnectLabelsProvider` tree.\n *\n * This hook provides type-safe access to all UI labels and automatically\n * falls back to default English labels if no provider is found.\n *\n * @returns {NovaConnectLabels} The complete object of UI labels for the current locale.\n *\n * @example\n * ```typescript\n * import { useNovaConnectLabels } from './hooks/useNovaConnectLabels';\n *\n * function MyComponent() {\n * const labels = useNovaConnectLabels();\n *\n * return (\n * <div>\n * <h1>{labels.connectWallet}</h1>\n * <button>{labels.connect}</button>\n * <p aria-label={labels.walletBalance}>{formattedBalance}</p>\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Destructuring specific labels for better performance\n * function ConnectButton() {\n * const { connectWallet, connecting, connected } = useNovaConnectLabels();\n *\n * return (\n * <button>\n * {isConnecting ? connecting : isConnected ? connected : connectWallet}\n * </button>\n * );\n * }\n * ```\n */\nexport const useNovaConnectLabels = (): NovaConnectLabels => {\n return useContext(NovaConnectLabelsContext);\n};\n\n/**\n * Hook to get a specific label by key path with type safety\n *\n * @param key The label key to retrieve\n * @returns The specific label value\n *\n * @example\n * ```typescript\n * function MyComponent() {\n * const connectLabel = useNovaConnectLabel('connectWallet');\n * const errorLabel = useNovaConnectLabel('connectionError');\n *\n * return <button>{connectLabel}</button>;\n * }\n * ```\n */\nexport const useNovaConnectLabel = <K extends keyof NovaConnectLabels>(key: K): NovaConnectLabels[K] => {\n const labels = useNovaConnectLabels();\n return labels[key];\n};\n\n/**\n * Hook to get multiple specific labels for better performance\n *\n * @param keys Array of label keys to retrieve\n * @returns Object with only the requested labels\n *\n * @example\n * ```typescript\n * function ConnectModal() {\n * const { connectWallet, connecting, disconnect } = useNovaConnectLabelsSubset(['connectWallet', 'connecting', 'disconnect']);\n *\n * return (\n * <div>\n * <h2>{connectWallet}</h2>\n * <span>{connecting}</span>\n * <button>{disconnect}</button>\n * </div>\n * );\n * }\n * ```\n */\nexport const useNovaConnectLabelsSubset = <K extends keyof NovaConnectLabels>(\n keys: K[],\n): Pick<NovaConnectLabels, K> => {\n const allLabels = useNovaConnectLabels();\n\n const subset = {} as Pick<NovaConnectLabels, K>;\n for (const key of keys) {\n subset[key] = allLabels[key];\n }\n\n return subset;\n};\n\n/**\n * Type-safe helper to check if a label exists\n *\n * @param labels The labels object\n * @param key The key to check\n * @returns Whether the key exists and has a non-empty value\n */\nexport const hasLabel = (labels: NovaConnectLabels, key: keyof NovaConnectLabels): boolean => {\n return Boolean(labels[key]?.trim());\n};\n\n/**\n * Utility type for extracting label keys by category\n */\nexport type LabelCategory = {\n actions: Extract<\n keyof NovaConnectLabels,\n 'connectWallet' | 'disconnect' | 'connecting' | 'connected' | 'tryAgain' | 'back' | 'connect' | 'close'\n >;\n states: Extract<keyof NovaConnectLabels, 'success' | 'error' | 'replaced' | 'loading' | 'idle'>;\n accessibility: Extract<\n keyof NovaConnectLabels,\n 'chainSelector' | 'closeModal' | 'selectChain' | 'walletControls' | 'openWalletModal'\n >;\n transactions: Extract<\n keyof NovaConnectLabels,\n 'transactionLoading' | 'transactionSuccess' | 'transactionError' | 'transactionReplaced' | 'recent'\n >;\n};\n\n/**\n * Hook to get labels by category for better organization\n *\n * @param category The category of labels to retrieve\n * @returns Object with labels from the specified category\n */\nexport const useLabelsByCategory = <T extends keyof LabelCategory>(\n category: T,\n): Pick<NovaConnectLabels, LabelCategory[T]> => {\n const allLabels = useNovaConnectLabels();\n\n const categoryKeys: Record<keyof LabelCategory, (keyof NovaConnectLabels)[]> = {\n actions: ['connectWallet', 'disconnect', 'connecting', 'connected', 'tryAgain', 'back', 'connect', 'close'],\n states: ['success', 'error', 'replaced', 'loading', 'idle'],\n accessibility: ['chainSelector', 'closeModal', 'selectChain', 'walletControls', 'openWalletModal'],\n transactions: ['transactionLoading', 'transactionSuccess', 'transactionError', 'transactionReplaced', 'recent'],\n };\n\n const keys = categoryKeys[category] as LabelCategory[T][];\n const categoryLabels = {} as Pick<NovaConnectLabels, LabelCategory[T]>;\n\n for (const key of keys) {\n // eslint-disable-next-line\n (categoryLabels as any)[key] = allLabels[key as keyof NovaConnectLabels];\n }\n\n return categoryLabels;\n};\n\n/**\n * Utility function to check if labels are default ones (for external use)\n * This is a regular function, not a hook, so it can be used anywhere\n *\n * @param labels The labels to check\n * @returns Whether the labels are the default English labels\n *\n * @example\n * ```typescript\n * function SomeUtilityFunction(labels: NovaConnectLabels) {\n * if (isDefaultLabels(labels)) {\n * console.log('Using default English labels');\n * }\n * }\n * ```\n */\nexport const isDefaultLabels = (labels: NovaConnectLabels): boolean => {\n return labels === defaultLabels;\n};\n\n/**\n * Utility function to get a formatted label with fallback\n *\n * @param labels The labels object\n * @param key The label key\n * @param fallback Optional fallback text\n * @returns The label value or fallback\n *\n * @example\n * ```typescript\n * const buttonText = getLabelWithFallback(labels, 'connectWallet', 'Connect');\n * ```\n */\nexport const getLabelWithFallback = (\n labels: NovaConnectLabels,\n key: keyof NovaConnectLabels,\n fallback?: string,\n): string => {\n const value = labels[key];\n if (value && value.trim()) {\n return value;\n }\n return fallback || defaultLabels[key] || key.toString();\n};\n\n/**\n * Utility function to create a labels subset (for use outside of React components)\n *\n * @param labels The source labels object\n * @param keys Array of keys to extract\n * @returns Object with only the requested labels\n *\n * @example\n * ```typescript\n * const actionLabels = createLabelsSubset(labels, ['connect', 'disconnect', 'tryAgain']);\n * ```\n */\nexport const createLabelsSubset = <K extends keyof NovaConnectLabels>(\n labels: NovaConnectLabels,\n keys: K[],\n): Pick<NovaConnectLabels, K> => {\n const subset = {} as Pick<NovaConnectLabels, K>;\n for (const key of keys) {\n subset[key] = labels[key];\n }\n return subset;\n};\n","import { getAdapterFromWalletType } from '@tuwaio/orbit-core';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { useSatelliteConnectStore } from '../satellite';\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(): 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 activeWallet = useSatelliteConnectStore((store) => store.activeWallet);\n const getAdapter = useSatelliteConnectStore((store) => store.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"]}