BigBlocks Docs
Components/Wallet

QuickSendButton

A streamlined Bitcoin BSV sending component that provides instant access to send transactions without opening a full wallet interface

A streamlined Bitcoin BSV sending component that provides instant access to send transactions through an elegant modal interface, perfect for quick micropayments, tips, and instant transfers without the complexity of a full wallet interface.

View Component Preview →

Installation

npx bigblocks add quick-send-button

Import

import { QuickSendButton } from 'bigblocks';

Props

PropTypeRequiredDefaultDescription
onSuccess(txid: string, amount: number, address: string) => voidNo-Callback when transaction succeeds
onError(error: string) => voidNo-Callback when transaction fails
defaultAmountnumberNo-Pre-fill amount in satoshis
defaultAddressstringNo-Pre-fill recipient address
buttonTextstringNo'Send BSV'Custom button text
variant'solid' | 'outline' | 'ghost'No'solid'Button style variant
size'small' | 'medium' | 'large'No'medium'Button size
showBalanceHintbooleanNofalseShow current balance hint
maxAmountnumberNo-Maximum send amount in satoshis
disabledbooleanNofalseDisable the button
classNamestringNo-Additional CSS classes

Basic Usage

import { QuickSendButton } from 'bigblocks';

export default function BasicSendExample() {
  return (
    <div className="send-section">
      <h3>Send BSV Instantly</h3>
      
      <QuickSendButton 
        onSuccess={(txid, amount, address) => {
          console.log(`Sent ${amount} satoshis to ${address}. TxID: ${txid}`);
        }}
        onError={(error) => {
          console.error('Send failed:', error);
        }}
      />
    </div>
  );
}

Advanced Usage

Complete Send Interface

import { QuickSendButton } from 'bigblocks';
import { useState } from 'react';

export default function AdvancedSendInterface() {
  const [transactionHistory, setTransactionHistory] = useState<Array<{
    txid: string;
    amount: number;
    address: string;
    timestamp: number;
  }>>([]);

  const handleSendSuccess = (txid: string, amount: number, address: string) => {
    // Add to transaction history
    const transaction = {
      txid,
      amount,
      address,
      timestamp: Date.now()
    };
    
    setTransactionHistory(prev => [transaction, ...prev]);
    
    // Show success notification
    console.log(`✅ Successfully sent ${amount} satoshis to ${address}`);
    console.log(`Transaction ID: ${txid}`);
    
    // Optional: Track analytics
    fetch('/api/analytics/send', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        amount,
        address,
        txid,
        timestamp: Date.now()
      })
    });
  };

  const handleSendError = (error: string) => {
    console.error('❌ Send failed:', error);
    
    // Show user-friendly error message
    if (error.includes('insufficient')) {
      alert('Insufficient balance. Please check your wallet balance.');
    } else if (error.includes('invalid address')) {
      alert('Invalid recipient address. Please check and try again.');
    } else {
      alert(`Transaction failed: ${error}`);
    }
  };

  return (
    <div className="advanced-send-interface">
      <div className="send-controls">
        <h2>Send Bitcoin SV</h2>
        
        <QuickSendButton 
          onSuccess={handleSendSuccess}
          onError={handleSendError}
          showBalanceHint={true}
          maxAmount={100000000} // 1 BSV maximum
          buttonText="💰 Send BSV"
          variant="solid"
          size="large"
          className="bg-gradient-to-r from-blue-500 to-purple-600 text-white font-bold"
        />
      </div>
      
      {transactionHistory.length > 0 && (
        <div className="transaction-history mt-6">
          <h3>Recent Transactions</h3>
          <div className="space-y-2">
            {transactionHistory.slice(0, 5).map((tx) => (
              <div key={tx.txid} className="flex items-center justify-between p-3 bg-gray-50 rounded">
                <div>
                  <span className="font-mono text-sm">
                    {tx.address.slice(0, 10)}...{tx.address.slice(-6)}
                  </span>
                  <span className="ml-2 text-gray-600">
                    {tx.amount.toLocaleString()} sats
                  </span>
                </div>
                <a 
                  href={`https://whatsonchain.com/tx/${tx.txid}`}
                  target="_blank"
                  rel="noopener noreferrer"
                  className="text-blue-500 hover:underline text-sm"
                >
                  View
                </a>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

Pre-filled Quick Send

import { QuickSendButton } from 'bigblocks';

export default function PrefilledSendExample() {
  return (
    <div className="prefilled-examples">
      <h3>Quick Send Examples</h3>
      
      {/* Pre-filled with amount */}
      <div className="example-item">
        <h4>Tip 1000 satoshis</h4>
        <QuickSendButton 
          defaultAmount={1000}
          buttonText="💡 Send Tip"
          variant="outline"
          onSuccess={(txid) => console.log('Tip sent:', txid)}
        />
      </div>
      
      {/* Pre-filled with address and amount */}
      <div className="example-item">
        <h4>Donate to Developer</h4>
        <QuickSendButton 
          defaultAddress="1DeveloperAddressHere..."
          defaultAmount={5000}
          buttonText="🚀 Support Development"
          variant="solid"
          onSuccess={(txid, amount, address) => {
            console.log(`Donated ${amount} satoshis to developer`);
            // Show thank you message
            alert('Thank you for supporting open source development!');
          }}
        />
      </div>
      
      {/* Custom styling with balance hint */}
      <div className="example-item">
        <h4>Custom Send with Balance</h4>
        <QuickSendButton 
          showBalanceHint={true}
          buttonText="💸 Send Payment"
          size="large"
          className="border-2 border-green-500 hover:bg-green-50"
          onSuccess={(txid, amount, address) => {
            console.log(`Payment sent: ${amount} sats to ${address}`);
          }}
        />
      </div>
    </div>
  );
}

Common Patterns

Tip Button for Content Creators

import { QuickSendButton } from 'bigblocks';

interface TipCreatorProps {
  creatorAddress: string;
  creatorName: string;
  contentId?: string;
}

export default function TipCreator({ creatorAddress, creatorName, contentId }: TipCreatorProps) {
  const tipAmounts = [500, 1000, 5000, 10000]; // Different tip amounts

  const handleTip = (txid: string, amount: number) => {
    console.log(`Tip sent to ${creatorName}: ${amount} satoshis`);
    
    // Track tip for analytics
    fetch('/api/tips/track', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        creatorAddress,
        creatorName,
        amount,
        txid,
        contentId,
        timestamp: Date.now()
      })
    });
    
    // Show thank you message
    alert(`Thank you for tipping ${creatorName}! Transaction: ${txid.slice(0, 8)}...`);
  };

  return (
    <div className="tip-creator-section">
      <div className="creator-info mb-4">
        <h4>Enjoyed this content?</h4>
        <p>Tip {creatorName} to show your appreciation</p>
      </div>
      
      {/* Quick tip amounts */}
      <div className="tip-amounts mb-4">
        <span className="text-sm text-gray-600">Quick tips:</span>
        <div className="flex gap-2 mt-1">
          {tipAmounts.map((amount) => (
            <QuickSendButton 
              key={amount}
              defaultAddress={creatorAddress}
              defaultAmount={amount}
              buttonText={`${amount} sats`}
              size="small"
              variant="outline"
              onSuccess={(txid) => handleTip(txid, amount)}
              className="text-xs"
            />
          ))}
        </div>
      </div>
      
      {/* Custom amount tip */}
      <QuickSendButton 
        defaultAddress={creatorAddress}
        buttonText={`💡 Tip ${creatorName}`}
        variant="solid"
        onSuccess={(txid, amount) => handleTip(txid, amount)}
        className="bg-orange-500 hover:bg-orange-600 text-white"
      />
    </div>
  );
}

Gaming Micropayments

import { QuickSendButton } from 'bigblocks';

interface GameItem {
  id: string;
  name: string;
  price: number; // in satoshis
  description: string;
  icon: string;
}

interface GameShopProps {
  playerId: string;
  gamePaymentAddress: string;
}

export default function GameShop({ playerId, gamePaymentAddress }: GameShopProps) {
  const items: GameItem[] = [
    { id: 'sword', name: 'Magic Sword', price: 2500, description: '+10 Attack', icon: '⚔️' },
    { id: 'shield', name: 'Shield', price: 1500, description: '+8 Defense', icon: '🛡️' },
    { id: 'potion', name: 'Health Potion', price: 500, description: 'Restore 50 HP', icon: '🧪' },
    { id: 'armor', name: 'Dragon Armor', price: 10000, description: '+20 Defense', icon: '🥼' }
  ];

  const handleItemPurchase = async (item: GameItem, txid: string) => {
    try {
      // Award item to player
      const response = await fetch('/api/game/purchase', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          playerId,
          itemId: item.id,
          txid,
          amount: item.price,
          timestamp: Date.now()
        })
      });

      if (response.ok) {
        console.log(`${item.name} purchased for player ${playerId}`);
        alert(`🎮 ${item.name} added to your inventory!`);
      } else {
        throw new Error('Failed to award item');
      }
    } catch (error) {
      console.error('Purchase processing failed:', error);
      alert('Purchase completed but item delivery failed. Contact support.');
    }
  };

  return (
    <div className="game-shop">
      <h2>🏪 Game Shop</h2>
      <p className="text-gray-600 mb-6">Buy items with Bitcoin SV</p>
      
      <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
        {items.map((item) => (
          <div key={item.id} className="shop-item p-4 border rounded-lg bg-white shadow">
            <div className="flex items-center mb-2">
              <span className="text-2xl mr-2">{item.icon}</span>
              <div>
                <h3 className="font-bold">{item.name}</h3>
                <p className="text-sm text-gray-600">{item.description}</p>
              </div>
            </div>
            
            <div className="flex items-center justify-between">
              <span className="font-mono text-lg">
                {item.price.toLocaleString()} sats
              </span>
              
              <QuickSendButton 
                defaultAmount={item.price}
                defaultAddress={gamePaymentAddress}
                buttonText="Buy"
                size="small"
                variant="solid"
                onSuccess={(txid) => handleItemPurchase(item, txid)}
                onError={(error) => {
                  console.error(`Purchase failed for ${item.name}:`, error);
                  alert('Purchase failed. Please try again.');
                }}
                className="bg-green-600 hover:bg-green-700 text-white"
              />
            </div>
          </div>
        ))}
      </div>
      
      <div className="mt-6 p-4 bg-blue-50 border border-blue-200 rounded">
        <p className="text-sm text-blue-800">
          💡 <strong>Pro tip:</strong> Items are delivered instantly upon transaction confirmation. 
          All purchases are recorded on the Bitcoin SV blockchain for permanent ownership proof.
        </p>
      </div>
    </div>
  );
}

Split Payment Interface

import { QuickSendButton } from 'bigblocks';
import { useState } from 'react';

interface Recipient {
  name: string;
  address: string;
  percentage?: number;
}

interface SplitPaymentProps {
  recipients: Recipient[];
  totalAmount: number;
}

export default function SplitPayment({ recipients, totalAmount }: SplitPaymentProps) {
  const [selectedRecipients, setSelectedRecipients] = useState<Recipient[]>([]);
  
  const splitAmount = selectedRecipients.length > 0 
    ? Math.floor(totalAmount / selectedRecipients.length)
    : 0;

  const handleRecipientToggle = (recipient: Recipient, checked: boolean) => {
    if (checked) {
      setSelectedRecipients(prev => [...prev, recipient]);
    } else {
      setSelectedRecipients(prev => prev.filter(r => r.address !== recipient.address));
    }
  };

  const handleSplitPayment = async (txid: string) => {
    console.log(`Split payment initiated. Master TxID: ${txid}`);
    
    try {
      // Process individual payments to each recipient
      const payments = await Promise.all(
        selectedRecipients.map(async (recipient) => {
          const response = await fetch('/api/wallet/send', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
              recipientAddress: recipient.address,
              amount: splitAmount,
              metadata: {
                type: 'split_payment',
                masterTxid: txid,
                recipientName: recipient.name
              }
            })
          });
          
          return response.json();
        })
      );
      
      const successfulPayments = payments.filter(p => p.success);
      
      console.log(`Split payment completed: ${successfulPayments.length}/${selectedRecipients.length} successful`);
      alert(`💰 Split payment completed! ${successfulPayments.length} payments sent successfully.`);
      
    } catch (error) {
      console.error('Split payment processing failed:', error);
      alert('Split payment processing failed. Please check individual transactions.');
    }
  };

  return (
    <div className="split-payment">
      <h3>Split Payment: {totalAmount.toLocaleString()} sats</h3>
      
      <div className="recipient-selection mb-4">
        <h4 className="mb-2">Select Recipients:</h4>
        {recipients.map((recipient) => (
          <label key={recipient.address} className="flex items-center mb-2">
            <input 
              type="checkbox"
              checked={selectedRecipients.some(r => r.address === recipient.address)}
              onChange={(e) => handleRecipientToggle(recipient, e.target.checked)}
              className="mr-2"
            />
            <span className="flex-1">
              {recipient.name}
            </span>
            <span className="text-sm text-gray-500 font-mono">
              {recipient.address.slice(0, 10)}...{recipient.address.slice(-6)}
            </span>
          </label>
        ))}
      </div>
      
      {selectedRecipients.length > 0 && (
        <div className="split-summary mb-4 p-3 bg-gray-50 rounded">
          <p><strong>Recipients:</strong> {selectedRecipients.length}</p>
          <p><strong>Amount per recipient:</strong> {splitAmount.toLocaleString()} sats</p>
          <p><strong>Total:</strong> {(splitAmount * selectedRecipients.length).toLocaleString()} sats</p>
        </div>
      )}
      
      <QuickSendButton 
        buttonText={selectedRecipients.length > 0 
          ? `Send to ${selectedRecipients.length} recipients`
          : 'Select recipients first'
        }
        disabled={selectedRecipients.length === 0}
        onSuccess={handleSplitPayment}
        onError={(error) => {
          console.error('Split payment failed:', error);
          alert('Split payment initiation failed. Please try again.');
        }}
        className="w-full bg-purple-600 hover:bg-purple-700 text-white font-semibold"
      />
    </div>
  );
}

Subscription Payment

import { QuickSendButton } from 'bigblocks';
import { useState } from 'react';

interface SubscriptionPlan {
  id: string;
  name: string;
  price: number; // monthly price in satoshis
  features: string[];
}

export default function SubscriptionPayment() {
  const [selectedPlan, setSelectedPlan] = useState<SubscriptionPlan | null>(null);
  
  const plans: SubscriptionPlan[] = [
    {
      id: 'basic',
      name: 'Basic Plan',
      price: 50000, // 50k satoshis/month
      features: ['Feature A', 'Feature B', 'Email Support']
    },
    {
      id: 'pro',
      name: 'Pro Plan', 
      price: 100000, // 100k satoshis/month
      features: ['Everything in Basic', 'Feature C', 'Feature D', 'Priority Support']
    },
    {
      id: 'enterprise',
      name: 'Enterprise Plan',
      price: 250000, // 250k satoshis/month  
      features: ['Everything in Pro', 'Custom Features', 'Dedicated Support']
    }
  ];

  const handleSubscription = async (txid: string, amount: number) => {
    if (!selectedPlan) return;
    
    try {
      // Create subscription
      const response = await fetch('/api/subscriptions/create', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          planId: selectedPlan.id,
          paymentTxid: txid,
          amount,
          startDate: Date.now()
        })
      });
      
      if (response.ok) {
        const subscription = await response.json();
        console.log('Subscription created:', subscription);
        alert(`🎉 Welcome to ${selectedPlan.name}! Your subscription is now active.`);
        
        // Redirect to dashboard
        window.location.href = '/dashboard';
      } else {
        throw new Error('Subscription creation failed');
      }
    } catch (error) {
      console.error('Subscription setup failed:', error);
      alert('Payment received but subscription setup failed. Please contact support.');
    }
  };

  return (
    <div className="subscription-payment">
      <h2>Choose Your Plan</h2>
      
      <div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
        {plans.map((plan) => (
          <div 
            key={plan.id}
            className={`plan-card p-6 border-2 rounded-lg cursor-pointer transition-all ${
              selectedPlan?.id === plan.id 
                ? 'border-blue-500 bg-blue-50' 
                : 'border-gray-200 hover:border-gray-300'
            }`}
            onClick={() => setSelectedPlan(plan)}
          >
            <h3 className="font-bold text-xl mb-2">{plan.name}</h3>
            <p className="text-2xl font-mono mb-4">
              {plan.price.toLocaleString()} sats/mo
            </p>
            
            <ul className="text-sm space-y-1">
              {plan.features.map((feature, index) => (
                <li key={index} className="flex items-center">
                  <span className="text-green-500 mr-2">✓</span>
                  {feature}
                </li>
              ))}
            </ul>
          </div>
        ))}
      </div>
      
      {selectedPlan && (
        <div className="selected-plan p-4 bg-blue-50 border border-blue-200 rounded mb-4">
          <h4>Selected: {selectedPlan.name}</h4>
          <p>Monthly payment: {selectedPlan.price.toLocaleString()} satoshis</p>
        </div>
      )}
      
      <QuickSendButton 
        defaultAmount={selectedPlan?.price}
        buttonText={selectedPlan 
          ? `Subscribe to ${selectedPlan.name}` 
          : 'Select a plan first'
        }
        disabled={!selectedPlan}
        onSuccess={(txid, amount) => handleSubscription(txid, amount)}
        onError={(error) => {
          console.error('Subscription payment failed:', error);
          alert('Payment failed. Please try again.');
        }}
        className="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3"
      />
      
      {selectedPlan && (
        <p className="text-sm text-gray-600 mt-2 text-center">
          By subscribing, you agree to monthly payments of {selectedPlan.price.toLocaleString()} satoshis. 
          Cancel anytime in your account settings.
        </p>
      )}
    </div>
  );
}

Authentication Requirements

The QuickSendButton requires Bitcoin authentication context for wallet operations:

import { 
  BitcoinAuthProvider, 
  BitcoinQueryProvider, 
  QuickSendButton 
} from 'bigblocks';

function App() {
  return (
    <BitcoinQueryProvider>
      <BitcoinAuthProvider config={{ 
        apiUrl: '/api',
        walletMode: 'integrated' // Enables wallet features
      }}>
        <QuickSendButton 
          buttonText="Send BSV"
          showBalanceHint={true}
        />
      </BitcoinAuthProvider>
    </BitcoinQueryProvider>
  );
}

Features

  • Inline Modal Interface: Quick popup form without full page navigation
  • Balance Validation: Automatically checks sufficient funds before enabling send
  • Address Validation: Validates Bitcoin addresses in real-time
  • Amount Formatting: Smart satoshi/BSV conversion display
  • Transaction Status: Real-time transaction broadcast status and confirmation
  • Error Handling: User-friendly error messages with retry options
  • Keyboard Shortcuts: ESC to close modal, Enter to send
  • Responsive Design: Optimized for both mobile and desktop
  • Security: Amount limits and address validation prevent errors

Best Practices

  1. Clear Intent: Use descriptive button text that explains what the payment is for
  2. Amount Validation: Set reasonable max amounts to prevent accidental large sends
  3. Address Verification: Always validate recipient addresses before enabling send
  4. Transaction Feedback: Provide clear success/error feedback with transaction IDs
  5. Balance Awareness: Show current balance to help users understand affordability
  6. Confirmation Steps: For larger amounts, consider additional confirmation prompts

Error Handling

Comprehensive Error Management

import { QuickSendButton } from 'bigblocks';

export default function RobustSendHandler() {
  const handleSendError = (error: string) => {
    console.error('Send failed:', error);
    
    if (error.includes('insufficient funds')) {
      // Show balance and suggest smaller amount
      alert('Insufficient balance. Please check your wallet balance and try a smaller amount.');
    } else if (error.includes('invalid address')) {
      // Address format error
      alert('Invalid recipient address. Please check the address format and try again.');
    } else if (error.includes('amount too small')) {
      // Below dust limit
      alert('Amount too small. Minimum send amount is 546 satoshis.');
    } else if (error.includes('network')) {
      // Network connectivity issues
      alert('Network error. Please check your connection and try again.');
    } else if (error.includes('rate limit')) {
      // Too many requests
      alert('Too many transactions. Please wait a moment and try again.');
    } else {
      // Generic error
      alert(`Transaction failed: ${error}`);
    }
  };

  return (
    <QuickSendButton 
      onError={handleSendError}
      onSuccess={(txid, amount, address) => {
        console.log(`✅ Sent ${amount} satoshis to ${address}`);
        console.log(`Transaction: https://whatsonchain.com/tx/${txid}`);
        alert('Transaction sent successfully!');
      }}
      maxAmount={10000000} // 0.1 BSV maximum
      showBalanceHint={true}
    />
  );
}

Security Considerations

Amount Limits and Validation

import { QuickSendButton } from 'bigblocks';

export default function SecureSendButton() {
  return (
    <div className="secure-send">
      <div className="security-notice mb-4 p-3 bg-yellow-50 border border-yellow-200 rounded">
        <p className="text-sm text-yellow-800">
          🔒 All transactions are signed with your private key and broadcast securely. 
          Maximum single transaction: 0.1 BSV.
        </p>
      </div>
      
      <QuickSendButton 
        maxAmount={10000000} // 0.1 BSV limit
        buttonText="🔐 Secure Send"
        onSuccess={(txid, amount, address) => {
          // Log transaction for audit trail
          fetch('/api/audit/transaction', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
              txid,
              amount,
              address,
              timestamp: Date.now(),
              userAgent: navigator.userAgent
            })
          });
          
          console.log('Secure transaction completed:', txid);
        }}
        onError={(error) => {
          // Log security-related errors
          if (error.includes('amount exceeds')) {
            console.warn('User attempted to exceed maximum amount');
          }
          console.error('Secure send failed:', error);
        }}
      />
    </div>
  );
}

Troubleshooting

Common Issues

Button appears disabled/unresponsive

  • Ensure BitcoinAuthProvider is properly configured with wallet access
  • Check that user has authenticated and unlocked their wallet
  • Verify sufficient balance for minimum transaction (546 satoshis + fees)

Modal doesn't open when clicked

  • Check for JavaScript errors in browser console
  • Ensure required Bitcoin context providers are wrapped around the component
  • Verify the component is not disabled via props

Transactions fail with "insufficient funds"

  • User needs more BSV in their wallet
  • Account for transaction fees (typically ~0.0001 BSV)
  • Check if user has UTXOs available for spending

Address validation errors

  • Ensure addresses are valid Bitcoin SV format
  • Check for correct network (mainnet vs testnet)
  • Verify addresses haven't been copy-pasted incorrectly

Debug Mode

import { QuickSendButton } from 'bigblocks';

export default function DebugSendButton() {
  const debugSend = (txid: string, amount: number, address: string) => {
    console.log('🐛 Debug send success:', {
      txid,
      amount,
      address,
      timestamp: new Date().toISOString(),
      userAgent: navigator.userAgent
    });
  };

  const debugError = (error: string) => {
    console.error('🐛 Debug send error:', {
      error,
      timestamp: new Date().toISOString(),
      userAgent: navigator.userAgent
    });
  };

  return (
    <div className="debug-send">
      <h3>Debug Mode Send</h3>
      <QuickSendButton 
        onSuccess={debugSend}
        onError={debugError}
        buttonText="🐛 Debug Send"
        showBalanceHint={true}
        className="border-2 border-gray-300"
      />
    </div>
  );
}

API Reference

QuickSendButton Component

interface QuickSendButtonProps {
  onSuccess?: (txid: string, amount: number, address: string) => void;
  onError?: (error: string) => void;
  defaultAmount?: number;
  defaultAddress?: string;
  buttonText?: string;
  variant?: 'solid' | 'outline' | 'ghost';
  size?: 'small' | 'medium' | 'large';
  showBalanceHint?: boolean;
  maxAmount?: number;
  disabled?: boolean;
  className?: string;
}

Usage with React Query

import { useQuery, useMutation } from '@tanstack/react-query';
import { QuickSendButton } from 'bigblocks';

function QuickSendWithQuery() {
  // Query for wallet balance
  const { data: balance } = useQuery({
    queryKey: ['wallet-balance'],
    queryFn: () => fetch('/api/wallet/balance').then(res => res.json()),
    refetchInterval: 30000 // Refresh every 30 seconds
  });

  // Mutation for sending transactions
  const sendMutation = useMutation({
    mutationFn: (sendData: { address: string; amount: number }) =>
      fetch('/api/wallet/send', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(sendData)
      }).then(res => res.json()),
    onSuccess: (data) => {
      console.log('Transaction sent:', data.txid);
    },
    onError: (error) => {
      console.error('Send failed:', error);
    }
  });

  const maxSafeAmount = balance ? Math.floor(balance.satoshis * 0.9) : undefined;

  return (
    <QuickSendButton 
      maxAmount={maxSafeAmount}
      showBalanceHint={true}
      onSuccess={(txid, amount, address) => {
        console.log('Success:', { txid, amount, address });
      }}
      onError={(error) => {
        console.error('Error:', error);
      }}
    />
  );
}