Donation Button Example
Accept one-time or recurring donations with custom amounts. Perfect for nonprofits, creators, and causes.
Live Demo
Try out the donation flow below. This is a simulated demo running on Testnet mode.
Implementation
The following code shows how to build the donation component on the left.
"use client"
import { useState } from "react"
import { ZynPayClient, Environment } from '@zyntrialabs/zynpay-sdk'
import { BrowserProvider } from 'ethers'
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
export function DonationButton() {
const [donationType, setDonationType] = useState<"one-time" | "recurring">("one-time")
const [amount, setAmount] = useState("10")
const [loading, setLoading] = useState(false)
const presetAmounts = ["5", "10", "25", "50", "100"]
const handleDonate = async () => {
setLoading(true)
try {
// Connect wallet
const provider = new BrowserProvider(window.ethereum)
const signer = await provider.getSigner()
// Initialize ZynPay
const client = new ZynPayClient({
merchantWallet: '0xYourOrganizationWallet',
environment: Environment.TESTNET,
defaultChain: 'base',
})
// Create payment
const payment = client.createPayment(parseFloat(amount), 'base')
// Process donation
const txHash = await client.pay(payment, signer, true)
console.log('Donation successful!', txHash)
// For recurring donations, you'd set up a subscription here
if (donationType === "recurring") {
// Implement recurring payment logic
}
alert('Thank you for your donation!')
} catch (error) {
console.error('Donation failed:', error)
alert('Donation failed. Please try again.')
} finally {
setLoading(false)
}
}
return (
<div className="space-y-6">
<div>
<h3 className="text-xl font-semibold">Support Our Cause</h3>
<p className="text-muted-foreground">Your donation helps us make a difference</p>
</div>
<RadioGroup value={donationType} onValueChange={(v) => setDonationType(v as any)}>
<div className="flex items-center space-x-2">
<RadioGroupItem value="one-time" id="one-time" />
<label htmlFor="one-time">One-time donation</label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="recurring" id="recurring" />
<label htmlFor="recurring">Monthly recurring</label>
</div>
</RadioGroup>
<div className="grid grid-cols-3 gap-2">
{presetAmounts.map((amt) => (
<Button
key={amt}
variant={amount === amt ? "default" : "outline"}
onClick={() => setAmount(amt)}
>
${amt}
</Button>
))}
</div>
<Input
type="number"
placeholder="Custom amount"
value={amount}
onChange={(e) => setAmount(e.target.value)}
min="0.01"
step="0.01"
/>
<Button
onClick={handleDonate}
disabled={loading || !amount || parseFloat(amount) <= 0}
className="w-full"
>
{loading ? "Processing..." : `Donate ${amount} USDC`}
</Button>
</div>
)
}Features
Accept single donations with preset or custom amounts. Perfect for one-off contributions.
Set up monthly recurring donations. Customers approve once, and payments continue automatically.
Quick-select buttons for common donation amounts. Makes it easy for donors to choose.
Allow donors to enter any amount they want. Flexible for all donation sizes.
Use Cases
Accept donations for your cause. Supporters can donate any amount directly from their wallet.
Let your audience support your work with one-time tips or monthly subscriptions.
Accept contributions from the community. Supporters can sponsor your project monthly.