Best Practices & Quick Start
This section provides a step-by-step integration flow and summarizes key best practices for developers building on the Blockhead Recurring Payments Protocol.
Quick Start Example
A typical subscription flow has three steps:
1. User Approves Token Spend
Customers must grant the contract an allowance. Always request a large or infinite approval so recurring charges do not fail over time.
import { ethers } from "ethers";
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const USDC = "0xTokenAddress";
const CONTRACT_ADDRESS = "0xRecurringPaymentsContract";
const ERC20_ABI = ["function approve(address spender, uint256 value) external returns (bool)"];
const token = new ethers.Contract(USDC, ERC20_ABI, signer);
// Approve max allowance
await token.approve(CONTRACT_ADDRESS, ethers.MaxUint256);
2. Merchant Creates Subscription
Call createRecurringPayment with parameters for recipient, amount, token, interval, interface wallet, metadata, and optional free trial.
const CONTRACT_ABI = [ /* ...RecurringPayments ABI... */ ];
const contract = new ethers.Contract(CONTRACT_ADDRESS, CONTRACT_ABI, signer);
const recipient = "0xMerchantWallet";
const uiInterfaceWallet = "0xUIWallet";
// 10 USDC per month, 7-day free trial
const amount = ethers.parseUnits("10", 6); // USDC uses 6 decimals
const ONE_MONTH = 2_592_000; // 30 days in seconds
const FREE_TRIAL_7_DAYS = 7 * 86_400;
const tx = await contract.createRecurringPayment(
recipient,
amount,
USDC,
ONE_MONTH,
uiInterfaceWallet,
["customer123", "plan_gold"], // optional metadata
FREE_TRIAL_7_DAYS
);
await tx.wait();
3. Display Subscription Status
Frontends can query subscription state using recurringPayments, getPaymentDue, isSubscriptionValid, and related functions.
const id = 0n; // example account ID
const sub = await contract.recurringPayments(id);
console.log("Next payment due:", new Date(Number(sub[8]) * 1000));
const valid = await contract.isSubscriptionValid(id);
console.log("Subscription active?", valid);
Best Practices
- Approvals: Request large/infinite allowances. Recurring charges will fail once allowance runs out.
- Token Units: Always express
_amountin the token’s base unit. Respect the token’sdecimals(). - Time: All intervals and due dates are in seconds. Convert to days/weeks/months in UI.
- Free Trials: Pass trial length in seconds (e.g., 7 days =
604800). - Metadata: Keep
additionalInformationconcise to minimize gas fees. Store heavier data off-chain and link it via an ID. - Grace Period: Subscriptions remain valid for an extra 24 hours to handle chain delays. Do not revoke access immediately after a missed charge.
- Events: Subscribe to
RecurringPaymentCreated,RecurringPaymentCancelled, andPaymentTransferredto update your system in real time. - Networks: Verify the correct contract address for your target chain (see Networks).
By following this flow and best practices, merchants and gateways can quickly enable recurring payments with minimal on-chain complexity.