Skip to content

React Reward Button is a customizable React component that sends Ethereum token rewards on click. It integrates seamlessly with the Reown Wallet Provider, making it ideal for dApps, onboarding flows, or incentivized Web3 actions.

License

Notifications You must be signed in to change notification settings

varungulati/react-reward-button

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

45 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎁 React Reward Button

A React component that provides a reward button with Ethereum token rewards. Built with wagmi, AppKit, and ethers.js for seamless Web3 integration.

Why settle for clicks that do nothing?

React Reward Button is a drop-in, beautifully styled button powered by shadcn/ui and Reown wallet integration β€” but with a twist: every click can reward your users with real tokens.

Unique Selling Points

  1. 🎨 Beautiful by Design
    Built on top of shadcn/ui's Button component β€” fully customizable with variants, sizes, and accessible design patterns out of the box.

  2. πŸ”— Seamless Wallet Integration with Reown
    Handles wallet connection automatically using the Reown React library. Users connect once and are ready to receive rewards instantly.

  3. πŸͺ™ Compatible with Any ERC-20 Token
    Reward users in your own token or any existing ERC-20 token on supported EVM chains (Polygon recommended).

  4. ⚑ One Click = Real Value
    Trigger token rewards instantly when users interact with the button β€” perfect for gamified actions, engagement campaigns, or loyalty flows.

  5. βš™οΈ Flexible Gas Modes
    Choose how rewards are delivered:

    • Developer-funded (gasless for user)
    • Or user-funded (MetaMask/Reown confirmation per claim)
  6. 🧩 Plug-and-Play Integration
    Drop it into any React project like a regular button. Add reward props, and you're done β€” no backend required unless you want one.

Demo

Try the demo here: React Reward Button Demo

Features

  • 🌐 Web3 Integration: Built with wagmi and AppKit for modern Web3 functionality
  • πŸ’° ERC20 Token Rewards: Send any ERC20 token as rewards
  • πŸ”— Wallet Connection: Seamless wallet connection with AppKit
  • βš™οΈ Gas Fee Options: Choose who pays gas fees (sender or receiver)
  • 🎨 Customizable UI: Multiple variants, sizes, and styling options
  • πŸ”’ Type Safe: Full TypeScript support with comprehensive types
  • πŸ“± Mobile Friendly: Works on all devices with responsive design
  • β™Ώ Accessible: Built with accessibility standards in mind
  • πŸš€ Performance: Optimized for production use

βœ… AI-friendly: Works great with ChatGPT/Cursor/GitHub Copilot

Installation

npm install react-reward-button

Peer Dependencies

This library requires the following peer dependencies:

npm install wagmi @tanstack/react-query ethers @reown/appkit @reown/appkit-adapter-wagmi react react-dom

Setup

1. Provider Setup

Wrap your app with the necessary providers:

import { WagmiProvider } from 'wagmi';
import { mainnet, polygon, sepolia } from 'wagmi/chains';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createAppKit } from '@reown/appkit/react';
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi';

const queryClient = new QueryClient();

// Get your project ID from https://cloud.reown.com/
const projectId = 'YOUR_PROJECT_ID';

// Configure networks
const networks = [mainnet, polygon, sepolia];

// Set up the Wagmi adapter
const wagmiAdapter = new WagmiAdapter({
  projectId,
  networks,
});

// Create the AppKit instance
createAppKit({
  adapters: [wagmiAdapter],
  networks,
  projectId,
  metadata: {
    name: 'My App',
    description: 'My App Description',
    url: 'https://myapp.com',
    icons: ['https://myapp.com/icon.png']
  }
});

function App() {
  return (
    <WagmiProvider config={wagmiAdapter.wagmiConfig}>
      <QueryClientProvider client={queryClient}>
        {/* Your app components */}
      </QueryClientProvider>
    </WagmiProvider>
  );
}

2. Basic Usage

import { RewardButton } from 'react-reward-button';

function MyComponent() {
  const handleRewardClaimed = (txHash: string, amount: string) => {
    console.log('Reward claimed!', { txHash, amount });
  };

  const handleRewardFailed = (error: Error) => {
    console.error('Reward failed:', error);
  };

  return (
    <RewardButton
      tokenAddress="0xA0b86a33E6441357C49c74aA8F4b3f0B7C6d6b2c" // Example USDC address
      rewardAmount="1000000" // 1 USDC (6 decimals)
      senderAddress="0x..." // Your wallet address holding the tokens
      senderPrivateKey="0x..." // Your private key (keep secure!)
      onRewardClaimed={handleRewardClaimed}
      onRewardFailed={handleRewardFailed}
      tokenSymbol="USDC"
      showRewardAmount={true}
    >
      Claim 1 USDC Reward
    </RewardButton>
  );
}

API Reference

RewardButton Props

Prop Type Default Description
tokenAddress string undefined The Ethereum address of the reward token contract
rewardAmount string undefined The amount of tokens to reward (in wei or token units)
recipientAddress string undefined The recipient address (falls back to connected wallet)
senderAddress string undefined The sender wallet address that holds the reward tokens
senderPrivateKey string undefined The private key of the sender wallet
rpcUrl string undefined RPC URL for the network
onReward () => void | Promise<void> undefined Callback for non-Web3 mode
onRewardClaimed (txHash: string, amount: string) => void undefined Called when reward is successfully claimed
onRewardFailed (error: Error) => void undefined Called when reward claim fails
onRewardStarted () => void undefined Called when reward claim is initiated
showRewardAmount boolean true Whether to show the reward amount on the button
tokenSymbol string 'TOKEN' Custom token symbol to display
requireConnection boolean true Whether to require wallet connection
loadingText string 'Claiming Reward...' Custom loading text
userPaysGas boolean false Whether user pays gas fees (vs sender)
isLoading boolean false External loading state
children React.ReactNode 'Claim Reward' Button content
variant 'default' | 'secondary' | 'outline' | 'ghost' | 'destructive' 'default' Button variant
size 'default' | 'sm' | 'lg' | 'icon' 'default' Button size
disabled boolean false Whether the button is disabled
className string undefined Additional CSS classes

Examples

Basic ERC20 Token Reward

import { RewardButton } from 'react-reward-button';

function BasicReward() {
  return (
    <RewardButton
      tokenAddress="0xA0b86a33E6441357C49c74aA8F4b3f0B7C6d6b2c"
      rewardAmount="1000000" // 1 USDC (6 decimals)
      senderAddress="0x742d35Cc6634C0532925a3b8D372C468F8c9d5b7"
      senderPrivateKey="0x..." // Keep this secure!
      tokenSymbol="USDC"
      onRewardClaimed={(txHash, amount) => {
        console.log(`Reward claimed! Amount: ${amount}, TX: ${txHash}`);
      }}
    >
      Claim 1 USDC
    </RewardButton>
  );
}

Different Token Examples

// ETH-based reward
<RewardButton
  tokenAddress="0x..." // WETH address
  rewardAmount={ethers.parseEther("0.01")} // 0.01 ETH
  senderAddress="0x..."
  senderPrivateKey="0x..."
  tokenSymbol="WETH"
>
  Claim 0.01 WETH
</RewardButton>

// Custom ERC20 token
<RewardButton
  tokenAddress="0x..." // Your token address
  rewardAmount="100000000000000000000" // 100 tokens (18 decimals)
  senderAddress="0x..."
  senderPrivateKey="0x..."
  tokenSymbol="MYTOKEN"
  showRewardAmount={true}
>
  Claim Daily Reward
</RewardButton>

Gas Fee Options

// Sender pays gas fees (default)
<RewardButton
  tokenAddress="0x..."
  rewardAmount="1000000"
  senderAddress="0x..."
  senderPrivateKey="0x..."
  userPaysGas={false} // Sender pays gas
>
  Free Reward (No Gas Required)
</RewardButton>

// User pays gas fees
<RewardButton
  tokenAddress="0x..."
  rewardAmount="1000000"
  senderAddress="0x..."
  senderPrivateKey="0x..."
  userPaysGas={true} // User pays gas
>
  Claim Reward (You Pay Gas)
</RewardButton>

Custom Styling

<RewardButton
  tokenAddress="0x..."
  rewardAmount="1000000"
  senderAddress="0x..."
  senderPrivateKey="0x..."
  variant="outline"
  size="lg"
  className="my-custom-styles"
  style={{
    backgroundColor: '#ff6b6b',
    borderRadius: '12px',
    padding: '16px 32px'
  }}
>
  🎁 Special Reward
</RewardButton>

Error Handling

import { useState } from 'react';
import { RewardButton } from 'react-reward-button';

function RewardWithErrorHandling() {
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState(false);

  return (
    <div>
      <RewardButton
        tokenAddress="0x..."
        rewardAmount="1000000"
        senderAddress="0x..."
        senderPrivateKey="0x..."
        onRewardClaimed={(txHash, amount) => {
          setSuccess(true);
          setError(null);
          console.log('Success!', { txHash, amount });
        }}
        onRewardFailed={(error) => {
          setError(error.message);
          setSuccess(false);
        }}
        onRewardStarted={() => {
          setError(null);
          setSuccess(false);
        }}
      >
        Claim Reward
      </RewardButton>
      
      {error && <p style={{ color: 'red' }}>Error: {error}</p>}
      {success && <p style={{ color: 'green' }}>Reward claimed successfully!</p>}
    </div>
  );
}

Using as Regular Button

If you don't provide tokenAddress and rewardAmount, it works as a regular button:

import { RewardButton } from 'react-reward-button';

function RegularButton() {
  return (
    <RewardButton
      onReward={() => {
        console.log('Regular button clicked!');
      }}
      variant="secondary"
    >
      Regular Button
    </RewardButton>
  );
}

Configuration

Environment Variables

For development, you can use environment variables:

# .env
VITE_REOWN_PROJECT_ID=your_project_id
VITE_NETWORK=mainnet
VITE_RPC_URL=https://mainnet.infura.io/v3/your_key

Network Configuration

import { mainnet, polygon, sepolia, arbitrum } from 'wagmi/chains';

const networks = [
  mainnet,    // Ethereum Mainnet
  polygon,    // Polygon
  sepolia,    // Ethereum Sepolia Testnet
  arbitrum,   // Arbitrum One
];

Security Considerations

⚠️ Important Security Notes:

  1. Never expose private keys in client-side code - The senderPrivateKey should only be used in secure environments
  2. Use environment variables for sensitive data
  3. Consider using a backend service for production applications
  4. Validate all inputs and amounts before processing
  5. Test thoroughly on testnets before mainnet deployment

Supported Networks

  • Ethereum Mainnet
  • Polygon
  • Arbitrum
  • Optimism
  • Sepolia Testnet
  • Polygon Mumbai Testnet
  • Any EVM-compatible network

Browser Support

  • Chrome 90+
  • Firefox 88+
  • Safari 14+
  • Edge 90+
  • Mobile browsers with Web3 wallet support

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

MIT License - see the LICENSE file for details.

Support


Made with ❀️ for the Web3 community

About

React Reward Button is a customizable React component that sends Ethereum token rewards on click. It integrates seamlessly with the Reown Wallet Provider, making it ideal for dApps, onboarding flows, or incentivized Web3 actions.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published