Best Practices
Learn how to build robust and maintainable Bitcoin applications with LaserEyes best practices and patterns.
Wallet Integration
Proper Provider Setup
Always wrap your app with LaserEyesProvider at the root level and configure network settings appropriately.
// _app.tsx or layout.tsx
export default function RootLayout({ children }) {
return (
<LaserEyesProvider
config={{
network: MAINNET,
enforceNetwork: true,
autoConnect: true
}}
>
{children}
</LaserEyesProvider>
)
}
Connection Management
Handle wallet connections gracefully with proper error handling and user feedback.
const { connect, disconnect } = useLaserEyes()
try {
await connect(UNISAT)
showSuccessToast('Wallet connected!')
} catch (error) {
showErrorToast(error.message)
// Log error for debugging
console.error('Connection failed:', error)
}
State Management
State Updates
Keep wallet state fresh by implementing proper update strategies and handling state changes.
// Subscribe to state changes
useEffect(() => {
const unsubscribe = subscribeToWalletEvents(
(event) => {
if (event.type === 'networkChanged') {
refreshBalance()
}
}
)
return () => unsubscribe()
}, [])
Data Persistence
Implement proper caching and persistence strategies for better performance and UX.
// Cache frequently accessed data
const { getCachedBalance, refreshBalance } = useLaserEyes()
// Use cached data first
const cached = getCachedBalance()
if (cached) {
setBalance(cached)
}
// Then fetch fresh data
const fresh = await refreshBalance()
setBalance(fresh)
Performance
Optimization
Optimize your application's performance with proper data fetching and rendering strategies.
// Use React.memo for expensive components
const WalletInfo = React.memo(({ address }) => (
<div>
<AddressDisplay address={address} />
<BalanceDisplay address={address} />
</div>
))
// Implement proper loading states
const { data, isLoading } = useInscriptions()
if (isLoading) return <LoadingSpinner />
Efficient Updates
Implement efficient update patterns to minimize unnecessary re-renders and API calls.
// Use callbacks for event handlers
const handleTransfer = useCallback(async () => {
setLoading(true)
try {
await transfer(...)
await refreshBalance()
} finally {
setLoading(false)
}
}, [transfer, refreshBalance])
Security
Transaction Safety
Implement proper transaction validation and confirmation handling for secure operations.
// Validate transactions before sending
const { validateTransaction } = useLaserEyes()
try {
await validateTransaction({
recipient,
amount,
feeRate
})
// Proceed with transaction
} catch (error) {
// Handle validation error
}
Error Handling
Implement comprehensive error handling and recovery strategies.
try {
await sendTransaction(...)
} catch (error) {
if (error.code === 'INSUFFICIENT_FUNDS') {
notifyUser('Insufficient funds')
} else if (error.code === 'NETWORK_ERROR') {
await retryWithBackoff(sendTransaction)
} else {
reportError(error)
}
}
Code Organization
Component Structure
Organize your wallet-related components and hooks in a maintainable way.
// src/features/wallet/hooks/useWalletConnection.ts
export function useWalletConnection() {
const laser = useLaserEyes()
// Custom connection logic
return {
connect: async () => {...},
disconnect: async () => {...}
}
}
// src/features/wallet/components/WalletButton.tsx
export function WalletButton() {
const { connect } = useWalletConnection()
// Button implementation
}
Feature Organization
Structure your Bitcoin features in a modular and scalable way.
src/features/
├── wallet/
│ ├── components/
│ ├── hooks/
│ └── utils/
├── inscriptions/
│ ├── components/
│ ├── hooks/
│ └── utils/
└── transactions/
├── components/
├── hooks/
└── utils/