Guidelines

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/