Components/Wallet
DonateButton
Accept Bitcoin donations with customizable preset amounts, QR codes, and a beautiful donation interface
Accept Bitcoin donations with customizable preset amounts and a beautiful UI. The DonateButton component provides a complete donation interface with preset amounts, custom amount input, QR code generation, and seamless Bitcoin transaction handling.
Installation
npx bigblocks add donate-buttonImport
import { DonateButton } from 'bigblocks';
// or
import { DonateButton, QuickDonateButton } from 'bigblocks';Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| donationAddress | string | No | '1BitcoinAuthUi1111111111111111112345' | Bitcoin address to receive donations |
| defaultAmounts | number[] | No | [1000000, 5000000, 10000000, 50000000, 100000000] | Preset donation amounts in satoshis |
| customAmountEnabled | boolean | No | true | Allow users to enter custom amounts |
| variant | 'solid' | 'soft' | 'outline' | 'ghost' | No | 'solid' | Button visual style |
| size | '1' | '2' | '3' | '4' | No | '2' | Button size |
| buttonText | string | No | 'Donate' | Text displayed on the button |
| dialogTitle | string | No | 'Make a Donation' | Title shown in the donation dialog |
| description | string | No | - | Optional description text |
| onDonate | (amount: number, txid: string) => void | No | - | Callback when donation succeeds |
| onError | (error: Error) => void | No | - | Callback when donation fails |
| showQR | boolean | No | true | Show QR code for mobile wallets |
| showCopyAddress | boolean | No | true | Show copy address button |
| disabled | boolean | No | false | Disable the donation button |
Basic Usage
import { DonateButton } from 'bigblocks';
export default function SupportSection() {
return (
<DonateButton
donationAddress="1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
onDonate={(amount, txid) => {
console.log(`Received ${amount} satoshis! TX: ${txid}`);
}}
/>
);
}Advanced Usage
Custom Amounts and Configuration
import { DonateButton } from 'bigblocks';
export default function CustomDonations() {
return (
<DonateButton
donationAddress="1YourAddress..."
defaultAmounts={[500000, 1000000, 5000000, 10000000]} // 0.005, 0.01, 0.05, 0.1 BSV
customAmountEnabled={true}
buttonText="Support This Project"
dialogTitle="Support Development"
description="Your donations help fund ongoing development and server costs."
variant="solid"
size="3"
onDonate={(amount, txid) => {
// Track donation analytics
analytics.track('donation_completed', {
amount_satoshis: amount,
amount_bsv: amount / 100000000,
txid
});
// Show success message
toast.success(`Thank you for donating ${amount / 100000000} BSV!`);
}}
onError={(error) => {
console.error('Donation failed:', error);
toast.error('Donation failed. Please try again.');
}}
/>
);
}Support Page Example
import { DonateButton } from 'bigblocks';
export default function SupportPage() {
const projectAddress = "1YourProjectAddress...";
return (
<div className="max-w-2xl mx-auto p-8 space-y-6">
<div className="text-center">
<h1 className="text-3xl font-bold mb-4">Support Our Work</h1>
<p className="text-lg text-gray-600 mb-6">
Your donations help keep this project running and support ongoing development.
</p>
</div>
<div className="bg-gray-50 rounded-lg p-6">
<h2 className="text-xl font-semibold mb-4">Make a Donation</h2>
<DonateButton
donationAddress={projectAddress}
defaultAmounts={[1000000, 5000000, 10000000, 50000000]} // 0.01, 0.05, 0.1, 0.5 BSV
customAmountEnabled={true}
buttonText="Donate Bitcoin"
dialogTitle="Support Development"
description="All donations go directly to development costs and server infrastructure."
showQR={true}
showCopyAddress={true}
onDonate={(amount, txid) => {
// Log donation
console.log('Donation received:', {
amount_satoshis: amount,
amount_bsv: amount / 100000000,
txid,
timestamp: Date.now()
});
// Show gratitude
toast.success('Thank you for your generous support!');
// Optional: redirect to thank you page
setTimeout(() => {
router.push('/thank-you');
}, 2000);
}}
/>
</div>
<div className="text-sm text-gray-500 text-center">
<p>All donations are processed on the Bitcoin SV blockchain.</p>
<p>Transaction fees are minimal (~$0.001 USD).</p>
</div>
</div>
);
}QuickDonateButton
For simpler use cases, use the QuickDonateButton component with a preset amount:
import { QuickDonateButton } from 'bigblocks';
export default function ArticleDonation() {
return (
<div className="flex items-center space-x-4">
<p>Enjoyed this article?</p>
<QuickDonateButton
donationAddress="1AuthorAddress..."
amount={1000000} // 0.01 BSV
buttonText="Tip 0.01 BSV"
size="1"
variant="outline"
onDonate={(amount, txid) => {
toast.success('Thanks for the tip!');
}}
/>
</div>
);
}Common Patterns
Donation Goals and Progress
import { DonateButton } from 'bigblocks';
import { useState, useEffect } from 'react';
export default function DonationGoal() {
const [raised, setRaised] = useState(0);
const goal = 100000000; // 1 BSV goal
const progress = (raised / goal) * 100;
return (
<div className="space-y-4">
<div>
<div className="flex justify-between text-sm mb-2">
<span>Progress</span>
<span>{(raised / 100000000).toFixed(4)} BSV / {(goal / 100000000)} BSV</span>
</div>
<div className="w-full bg-gray-200 rounded-full h-2">
<div
className="bg-orange-500 h-2 rounded-full transition-all duration-300"
style={{ width: `${Math.min(progress, 100)}%` }}
/>
</div>
<p className="text-xs text-gray-500 mt-1">{progress.toFixed(1)}% funded</p>
</div>
<DonateButton
donationAddress="1FundraisingAddress..."
onDonate={(amount, txid) => {
// Update progress
setRaised(prev => prev + amount);
// Check if goal reached
if (raised + amount >= goal) {
toast.success('🎉 Fundraising goal reached! Thank you!');
} else {
toast.success('Thank you for your donation!');
}
}}
/>
</div>
);
}Multiple Donation Categories
import { DonateButton } from 'bigblocks';
export default function DonationCategories() {
const categories = [
{
id: 'development',
title: 'Development',
description: 'Support ongoing development and new features',
address: '1DevAddress...',
color: 'blue'
},
{
id: 'infrastructure',
title: 'Infrastructure',
description: 'Help cover server and hosting costs',
address: '1InfraAddress...',
color: 'green'
},
{
id: 'community',
title: 'Community',
description: 'Support community events and outreach',
address: '1CommunityAddress...',
color: 'purple'
}
];
return (
<div className="grid md:grid-cols-3 gap-6">
{categories.map(category => (
<div key={category.id} className="border rounded-lg p-6">
<h3 className="text-lg font-semibold mb-2">{category.title}</h3>
<p className="text-gray-600 mb-4">{category.description}</p>
<DonateButton
donationAddress={category.address}
buttonText={`Support ${category.title}`}
dialogTitle={`Support ${category.title}`}
description={category.description}
size="2"
onDonate={(amount, txid) => {
analytics.track('category_donation', {
category: category.id,
amount,
txid
});
toast.success(`Thank you for supporting ${category.title}!`);
}}
/>
</div>
))}
</div>
);
}Styling Variants
import { DonateButton } from 'bigblocks';
export default function StylingExamples() {
return (
<div className="space-y-4">
{/* Solid (default) */}
<DonateButton variant="solid" size="2" buttonText="Solid Donate" />
{/* Soft */}
<DonateButton variant="soft" size="2" buttonText="Soft Donate" />
{/* Outline */}
<DonateButton variant="outline" size="2" buttonText="Outline Donate" />
{/* Ghost */}
<DonateButton variant="ghost" size="2" buttonText="Ghost Donate" />
{/* Different sizes */}
<div className="flex items-center space-x-2">
<DonateButton size="1" buttonText="Small" />
<DonateButton size="2" buttonText="Medium" />
<DonateButton size="3" buttonText="Large" />
<DonateButton size="4" buttonText="Extra Large" />
</div>
</div>
);
}Authentication Requirements
The DonateButton component requires Bitcoin authentication to function. Wrap your app with the required providers:
import { BitcoinAuthProvider, BitcoinQueryProvider } from 'bigblocks';
function App() {
return (
<BitcoinQueryProvider>
<BitcoinAuthProvider config={{ apiUrl: '/api' }}>
<YourAppWithDonateButtons />
</BitcoinAuthProvider>
</BitcoinQueryProvider>
);
}Backend Integration
API Requirements
The component uses the useSendBSV hook which requires these API endpoints:
// POST /api/wallet/send
{
"recipientAddress": "1RecipientAddress...",
"amount": 1000000, // satoshis
"message": "Donation" // optional
}
// Response:
{
"success": true,
"txid": "abc123...",
"fee": 500 // transaction fee in satoshis
}Donation Tracking
// Optional: Track donations in your database
CREATE TABLE donations (
id UUID PRIMARY KEY,
txid VARCHAR(64) UNIQUE NOT NULL,
donor_address VARCHAR(64) NOT NULL,
recipient_address VARCHAR(64) NOT NULL,
amount BIGINT NOT NULL,
message TEXT,
category VARCHAR(50),
timestamp TIMESTAMP DEFAULT NOW(),
confirmed BOOLEAN DEFAULT FALSE
);Troubleshooting
Common Issues
"Insufficient funds" error
- Ensure the user has enough BSV balance
- Check for minimum transaction amount requirements
- Verify fee calculation includes transaction costs
QR code not displaying
- Ensure
showQRprop is set totrue - Check that the donation address is valid
- Verify mobile wallet compatibility
Transaction fails to broadcast
- Check API endpoint authentication
- Verify the recipient address is valid
- Ensure the transaction is properly signed
Error Handling
<DonateButton
donationAddress="1YourAddress..."
onError={(error) => {
switch (error.message) {
case 'INSUFFICIENT_FUNDS':
toast.error('Insufficient BSV balance for this donation');
break;
case 'INVALID_ADDRESS':
toast.error('Invalid donation address');
break;
case 'NETWORK_ERROR':
toast.error('Network error. Please try again.');
break;
default:
toast.error('Donation failed. Please try again.');
}
}}
/>Security Considerations
- Address Validation: Always validate donation addresses
- Amount Limits: Consider setting maximum donation amounts
- Rate Limiting: Implement rate limiting on donation endpoints
- Audit Trail: Log all donation attempts for security review
Related Components
- QuickDonateButton - Simplified one-click donations
- SendBSVButton - General BSV sending interface
- WalletOverview - Display wallet balance and info
- TokenBalance - Show token balances
API Reference
Default Amounts
The default preset amounts are:
- 0.01 BSV (1,000,000 satoshis)
- 0.05 BSV (5,000,000 satoshis)
- 0.1 BSV (10,000,000 satoshis)
- 0.5 BSV (50,000,000 satoshis)
- 1 BSV (100,000,000 satoshis)
QR Code Format
The QR code includes:
bitcoin:{address}?amount={amount_in_bsv}&message={message}Dependencies
useBitcoinAuth- Authentication hookuseSendBSV- Transaction sending hookQRCodeRenderer- QR code display- Radix UI components for dialogs and buttons