Getting Started
Learn how to get started with the Tap Ants Voucher System.
Prerequisites
Before you begin working with the Tap Ants Voucher System, ensure you have the following:
- Ethereum Development Environment: Familiarity with Ethereum development tools and concepts.
- Wallet: An Ethereum wallet like MetaMask for interacting with the contracts.
- Testnet ETH: Some Sepolia testnet ETH for testing (available from faucets).
- Development Tools: Node.js, npm/yarn, and a code editor.
Installation
Foundry is the recommended development environment for working with the Tap Ants Voucher System.
Install Foundry
Terminal# Install Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup
# Clone the repository
git clone https://github.com/tapants-com/tapants-voucher.git
cd tapants-voucher
# Install dependencies
forge install
# Build the contracts
forge build
Quick Start Guides
For Developers
1. Connect to Existing Contracts
Connect to the existing contracts on Sepolia testnet to start experimenting.
import { createConfig, http } from 'wagmi'
import { sepolia } from 'wagmi/chains'
import { useReadContract, useWriteContract } from 'wagmi'
// Contract addresses on Sepolia testnet
const VOUCHER_ADDRESS = "0x4223f47b1EB3bDB97d0117Ae50e2cC65309c22AE";
const REDEEM_ADDRESS = "0x6cD3B9C6a28851377FCf305D3C269C328797Cc5E";
const TOKEN_ADDRESS = "0x8f71a7503284c69eb200605b5ab11fabc555c865";
// Create wagmi config
const config = createConfig({
chains: [sepolia],
transports: {
[sepolia.id]: http(),
},
})
// Example: Reading voucher balance
function VoucherBalance({ address }) {
const { data: balance } = useReadContract({
address: VOUCHER_ADDRESS,
abi: voucherAbi,
functionName: 'balanceOf',
args: [address],
})
return <div>Balance: {balance ? formatUnits(balance, 18) : '0'}</div>
}
2. Deploy Your Own Contracts
Deploy your own instances of the contracts for a custom implementation.
// Using Foundry
// Create a deployment script in the script directory
// Example script.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Script.sol";
import "../src/TapAntsVoucher.sol";
import "../src/VoucherRedeemContract.sol";
import "../src/RedemptionToken.sol";
contract DeployScript is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
// Deploy the contracts
RedemptionToken token = new RedemptionToken("Redemption Token", "RTK", msg.sender);
TapAntsVoucher voucher = new TapAntsVoucher("Tap Ants Voucher", "TAV", 1, msg.sender);
VoucherRedeemContract redeem = new VoucherRedeemContract(msg.sender);
// Configure the contracts
voucher.setRedeemContract(address(redeem));
redeem.addSupportedVoucher(address(voucher), address(token), 1);
vm.stopBroadcast();
}
}
For Administrators
1. Mint and Distribute Vouchers
As the contract owner, mint vouchers and distribute them to users.
import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
import { parseUnits } from 'viem'
function MintVouchers() {
const { data: hash, writeContract } = useWriteContract()
const { isLoading, isSuccess } = useWaitForTransactionReceipt({
hash,
})
async function mintVouchers() {
const userAddress = "0x..."; // User's address
const amount = parseUnits("100", 18); // 100 vouchers
writeContract({
address: VOUCHER_ADDRESS,
abi: voucherAbi,
functionName: 'mint',
args: [userAddress, amount],
})
}
return (
<button onClick={mintVouchers} disabled={isLoading}>
{isLoading ? 'Minting...' : 'Mint Vouchers'}
</button>
)
}
2. Configure Redemption Rules
Set up the redemption rules for vouchers.
import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
function ConfigureRedemption() {
const { data: hash, writeContract } = useWriteContract()
const { isLoading, isSuccess } = useWaitForTransactionReceipt({
hash,
})
async function addSupportedVoucher() {
const voucherAddress = "0x..."; // Voucher contract address
const tokenAddress = "0x..."; // Redemption token address
const conversionRate = 1; // 1:1 conversion rate
writeContract({
address: REDEEM_ADDRESS,
abi: redeemAbi,
functionName: 'addSupportedVoucher',
args: [voucherAddress, tokenAddress, conversionRate],
})
}
return (
<button onClick={addSupportedVoucher} disabled={isLoading}>
{isLoading ? 'Adding...' : 'Add Supported Voucher'}
</button>
)
}
For End Users
1. Check Voucher Balance
Check your voucher balance.
import { useAccount, useReadContract } from 'wagmi'
import { formatUnits } from 'viem'
function VoucherBalanceChecker() {
const { address } = useAccount()
const { data: balance } = useReadContract({
address: VOUCHER_ADDRESS,
abi: voucherAbi,
functionName: 'balanceOf',
args: [address],
})
return (
<div>
<h2>Your Voucher Balance</h2>
<p>{balance ? formatUnits(balance, 18) : '0'} TAV</p>
</div>
)
}
2. Redeem Vouchers
Redeem your vouchers for tokens.
import { useAccount, useReadContract, useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
import { parseUnits } from 'viem'
function RedeemVouchers() {
const { address } = useAccount()
// Check allowance
const { data: allowance } = useReadContract({
address: VOUCHER_ADDRESS,
abi: voucherAbi,
functionName: 'allowance',
args: [address, REDEEM_ADDRESS],
})
// Approve vouchers
const { data: approveHash, writeContract: approve } = useWriteContract()
// Wait for approval transaction
const { isLoading: isApproving, isSuccess: isApproved } = useWaitForTransactionReceipt({
hash: approveHash,
})
// Redeem vouchers
const { data: redeemHash, writeContract: redeem } = useWriteContract()
// Wait for redeem transaction
const { isLoading: isRedeeming, isSuccess: isRedeemed } = useWaitForTransactionReceipt({
hash: redeemHash,
})
async function handleRedeem() {
const amount = parseUnits("10", 18); // 10 vouchers
// Check if we need to approve first
if (!allowance || allowance < amount) {
await approve({
address: VOUCHER_ADDRESS,
abi: voucherAbi,
functionName: 'approve',
args: [REDEEM_ADDRESS, amount],
})
}
// Then redeem the vouchers
await redeem({
address: REDEEM_ADDRESS,
abi: redeemAbi,
functionName: 'redeem',
args: [VOUCHER_ADDRESS, amount, "0x"],
})
}
return (
<button
onClick={handleRedeem}
disabled={isApproving || isRedeeming}
>
{isApproving ? 'Approving...' : isRedeeming ? 'Redeeming...' : 'Redeem Vouchers'}
</button>
)
}