# Tiwiflix Wallet Connector Examples

This directory contains example implementations of the `ConnectButton` component in different scenarios.

## Available Examples

### 1. Quick Start (`connect-button-quick-start.tsx`)
The simplest possible implementation - just 5 lines of code to add wallet connection to your app.

**Best for:** Getting started quickly, understanding the basics

### 2. Basic Usage (`connect-button-react.tsx`)
A straightforward example showing the ConnectButton component with event handlers.

**Best for:** Simple apps, learning the component API

### 3. Complete Example (`connect-button-complete.tsx`)
A comprehensive demo showcasing all features including:
- Balance fetching
- Transaction history
- Custom styling
- Theme variants (light, dark, auto)
- Modal positioning
- Custom button text
- Explorer URLs

**Best for:** Understanding all available features, reference implementation

### 4. Next.js Example (`connect-button-nextjs.tsx`)
Integration example for Next.js applications with:
- Proper SSR setup
- Context provider pattern
- Client-side rendering
- App Router and Pages Router support

**Best for:** Next.js projects

### 5. Vite + React Example (`connect-button-vite.tsx`)
Complete setup for Vite + React applications with:
- Context provider
- Global event listeners
- TypeScript configuration
- Modern React patterns

**Best for:** Vite projects, TypeScript apps

### 6. Simple Connect Button (`SimpleConnectButton.tsx`)
**NEW!** Minimal example showing bare essentials - perfect for learning.

**Best for:** Quick prototyping, understanding the core concepts

### 7. Test Connect Button (`TestConnectButton.tsx`)
**NEW!** Complete test component with all features and best practices to prevent infinite re-renders.

**Best for:** Production-ready implementation, reference for performance optimization

### 8. Redux Integration (`ReduxConnectButton.tsx`)
**NEW!** Example showing Redux integration with authentication flow.

**Best for:** Apps using Redux state management

## How to Use

### Installation

First, install the package:

```bash
npm install tiwiflix-wallet-connector
```

### Peer Dependencies

Install React and any chain-specific dependencies you need:

```bash
# Required for ConnectButton
npm install react react-dom

# Optional: for specific chains
npm install ethers@^6.13.0                    # For EVM chains
npm install @solana/web3.js@^1.95.0           # For Solana
npm install @tonconnect/ui@^2.3.1            # For TON
```

### Basic Setup

```tsx
import React from 'react';
import {
  WalletConnector,
  MetamaskAdapter,
  ConnectButton,
} from 'tiwiflix-wallet-connector';

const connector = new WalletConnector({
  adapters: [new MetamaskAdapter()],
  autoConnect: true,
});

function App() {
  return (
    <div>
      <ConnectButton connector={connector} />
    </div>
  );
}
```

### Advanced Setup with Context

```tsx
import React, { createContext, useContext, useMemo } from 'react';
import {
  WalletConnector,
  MetamaskAdapter,
  PhantomAdapter,
  TonkeeperAdapter,
  ConnectButton,
} from 'tiwiflix-wallet-connector';

const WalletContext = createContext<WalletConnector | null>(null);

export function WalletProvider({ children }) {
  const connector = useMemo(
    () => new WalletConnector({
      adapters: [
        new MetamaskAdapter(),
        new PhantomAdapter(),
        new TonkeeperAdapter(),
      ],
      autoConnect: true,
    }),
    []
  );

  return (
    <WalletContext.Provider value={connector}>
      {children}
    </WalletContext.Provider>
  );
}

function App() {
  return (
    <WalletProvider>
      <ConnectButton connector={useContext(WalletContext)} />
    </WalletProvider>
  );
}
```

## Available Props

The `ConnectButton` component accepts the following props:

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `connector` | `WalletConnector` | ✅ | - | The wallet connector instance |
| `onConnect` | `(account: Account) => void` | ❌ | - | Called when wallet connects |
| `onDisconnect` | `() => void` | ❌ | - | Called when wallet disconnects |
| `onError` | `(error: Error) => void` | ❌ | - | Called on wallet errors |
| `className` | `string` | ❌ | - | Custom CSS class |
| `style` | `React.CSSProperties` | ❌ | - | Inline styles |
| `showBalance` | `boolean` | ❌ | `false` | Show balance in button |
| `modalPosition` | `'top' \| 'bottom' \| 'center'` | ❌ | `'center'` | Modal position |
| `theme` | `'light' \| 'dark' \| 'auto'` | ❌ | `'auto'` | Color theme |
| `buttonText` | `string` | ❌ | `'Connect Wallet'` | Button text |
| `fetchBalance` | `(account: Account) => Promise<...>` | ❌ | - | Custom balance fetcher |
| `fetchTransactions` | `(account: Account) => Promise<...>` | ❌ | - | Custom transaction fetcher |
| `getExplorerUrl` | `(account: Account) => string` | ❌ | - | Block explorer URL |

## Features

### ✨ Auto Theme Detection
Automatically follows system dark/light mode preferences:

```tsx
<ConnectButton theme="auto" connector={connector} />
```

### 🎨 Custom Styling
Style the button to match your app:

```tsx
<ConnectButton
  connector={connector}
  style={{
    backgroundColor: '#FF6B6B',
    padding: '16px 32px',
    fontSize: '18px',
    borderRadius: '12px',
  }}
/>
```

### 💰 Balance Display
Show balance in the button:

```tsx
<ConnectButton
  connector={connector}
  fetchBalance={async (account) => {
    // Your balance fetching logic
    return { amount: '1.234', symbol: 'BNB', usdValue: 234.56 };
  }}
/>
```

### 📊 Transaction History
Display recent transactions:

```tsx
<ConnectButton
  connector={connector}
  fetchTransactions={async (account) => {
    // Your transaction fetching logic
    return [
      {
        hash: '0x...',
        amount: '0.1',
        symbol: 'BNB',
        status: 'success',
        url: 'https://bscscan.com/tx/0x...'
      }
    ];
  }}
/>
```

## Troubleshooting

### TypeScript Errors
If you see TypeScript errors about missing exports, make sure you have the latest types installed:

```bash
npm install --save-dev @types/react @types/react-dom
```

### React Not Found
Make sure React is installed as a peer dependency:

```bash
npm install react@^18.0.0 react-dom@^18.0.0
```

### Build Errors
Check that all required peer dependencies are installed for the chains you're using.

## Next Steps

- Read the [Full Documentation](../README.md)
- Check out the [React Setup Guide](../REACT_SETUP.md)
- See [Component Usage Examples](../COMPONENT_USAGE.md)
- Review the [Advanced Features](../ADVANCED_FEATURES.md)

## Support

For issues, questions, or contributions, please visit our [GitHub repository](https://github.com/tiwiflix/wallet-connector).

---

## 🎯 Performance Best Practices (Preventing Infinite Re-renders)

**IMPORTANT:** Follow these patterns to prevent "Maximum update depth exceeded" errors:

### 1. Create Connector Outside Component
```tsx
// ✅ GOOD: Create once
const connector = new WalletConnector({
  adapters: [new MetamaskAdapter()],
});

function App() {
  return <ConnectButton connector={connector} />;
}

// ❌ BAD: Creates new instance on every render
function App() {
  const connector = new WalletConnector({ /* ... */ });
  return <ConnectButton connector={connector} />;
}
```

### 2. Use `memo()` for Your Component
```tsx
import { memo } from 'react';

const MyButton = memo(function MyButton() {
  return <ConnectButton connector={connector} />;
});
```

### 3. Use `useCallback()` for Event Handlers
```tsx
const handleConnect = useCallback((account: Account) => {
  console.log('Connected:', account);
}, []); // Empty deps = stable reference

const handleDisconnect = useCallback(() => {
  console.log('Disconnected');
}, []);
```

### 4. Use `useMemo()` for the Connector
```tsx
const memoizedConnector = useMemo(() => connector, []);

<ConnectButton connector={memoizedConnector} />
```

### 5. Use Refs to Prevent Duplicate Calls
```tsx
const processingRef = useRef(false);
const lastAddressRef = useRef<string | null>(null);

const handleConnect = useCallback((account: Account) => {
  // Prevent duplicate calls
  if (processingRef.current) return;
  if (account?.address === lastAddressRef.current) return;
  
  processingRef.current = true;
  lastAddressRef.current = account.address;
  
  // Your logic here
  
  setTimeout(() => {
    processingRef.current = false;
  }, 1000);
}, []);
```

### 6. Track Component Mount State
```tsx
const mountedRef = useRef(false);

useEffect(() => {
  mountedRef.current = true;
  return () => {
    mountedRef.current = false;
  };
}, []);

const handleConnect = useCallback((account: Account) => {
  if (!mountedRef.current) return; // Prevent updates after unmount
  // Your logic here
}, []);
```

### Complete Example
```tsx
import { memo, useCallback, useRef, useEffect, useMemo } from 'react';
import { ConnectButton, WalletConnector, MetamaskAdapter } from 'tiwiflix-wallet-connector';

// Create outside component
const connector = new WalletConnector({
  adapters: [new MetamaskAdapter()],
});

const App = memo(function App() {
  const processingRef = useRef(false);
  const lastAddressRef = useRef<string | null>(null);
  const mountedRef = useRef(false);

  useEffect(() => {
    mountedRef.current = true;
    return () => {
      mountedRef.current = false;
    };
  }, []);

  const handleConnect = useCallback((account) => {
    if (!mountedRef.current) return;
    if (processingRef.current) return;
    if (account?.address === lastAddressRef.current) return;

    processingRef.current = true;
    lastAddressRef.current = account.address;

    setTimeout(() => {
      if (!mountedRef.current) {
        processingRef.current = false;
        return;
      }

      console.log('Connected:', account);
      
      setTimeout(() => {
        processingRef.current = false;
      }, 1000);
    }, 100);
  }, []);

  const handleDisconnect = useCallback(() => {
    lastAddressRef.current = null;
    processingRef.current = false;
    console.log('Disconnected');
  }, []);

  const memoizedConnector = useMemo(() => connector, []);

  return (
    <ConnectButton
      connector={memoizedConnector}
      onConnect={handleConnect}
      onDisconnect={handleDisconnect}
    />
  );
});

export default App;
```

See `TestConnectButton.tsx` and `ReduxConnectButton.tsx` for complete implementations!

