minipay-integration
MiniPay Integration
This skill covers building Mini Apps for MiniPay, the fastest growing non-custodial wallet in the Global South with 10M+ activations.
When to Use
- Building Mini Apps for MiniPay
- Detecting MiniPay wallet in your dApp
- Creating mobile-first payment applications
- Integrating with MiniPay's discovery page
What is MiniPay?
MiniPay is a stablecoin wallet with a built-in Mini App discovery page. It's available as:
- Built into Opera Mini browser (Android)
- Standalone app (Android and iOS)
Key features:
- Phone number mapping to wallet addresses
- Sub-cent transaction fees
- 2MB lightweight footprint
- Supports USDm (cUSD), USDC, and USDT
Quick Start
Create a MiniPay App
npx @celo/celo-composer@latest create -t minipay
This scaffolds a Next.js app pre-configured for MiniPay.
Detecting MiniPay
Check if the user is using MiniPay:
function isMiniPay(): boolean {
return typeof window !== "undefined" &&
window.ethereum?.isMiniPay === true;
}
Important: This code must run in a browser environment, not Node.js.
Connecting Wallet
MiniPay automatically injects the wallet. Request account access:
async function connectWallet(): Promise<string | null> {
if (typeof window === "undefined" || !window.ethereum) {
return null;
}
const accounts = await window.ethereum.request({
method: "eth_requestAccounts",
params: [],
});
return accounts[0] || null;
}
Important: Hide the "Connect Wallet" button when inside MiniPay - the connection is implicit.
const [address, setAddress] = useState<string | null>(null);
const inMiniPay = isMiniPay();
useEffect(() => {
if (inMiniPay) {
connectWallet().then(setAddress);
}
}, [inMiniPay]);
return (
<div>
{!inMiniPay && (
<button onClick={() => connectWallet().then(setAddress)}>
Connect Wallet
</button>
)}
{address && <p>Connected: {address}</p>}
</div>
);
Reading Balances
import { createPublicClient, http, formatUnits } from "viem";
import { celo } from "viem/chains";
const publicClient = createPublicClient({
chain: celo,
transport: http(),
});
const USDM_ADDRESS = "0x765de816845861e75a25fca122bb6898b8b1282a";
const ERC20_ABI = [
{
name: "balanceOf",
type: "function",
stateMutability: "view",
inputs: [{ name: "account", type: "address" }],
outputs: [{ type: "uint256" }],
},
] as const;
async function getUSDmBalance(address: string): Promise<string> {
const balance = await publicClient.readContract({
address: USDM_ADDRESS,
abi: ERC20_ABI,
functionName: "balanceOf",
args: [address as `0x${string}`],
});
return formatUnits(balance, 18);
}
Sending Transactions
Use viem or wagmi for transactions. MiniPay does not support ethers.js.
import { createWalletClient, custom, parseUnits, encodeFunctionData } from "viem";
import { celo } from "viem/chains";
const USDM_ADDRESS = "0x765de816845861e75a25fca122bb6898b8b1282a";
const ERC20_ABI = [
{
name: "transfer",
type: "function",
stateMutability: "nonpayable",
inputs: [
{ name: "to", type: "address" },
{ name: "amount", type: "uint256" },
],
outputs: [{ type: "bool" }],
},
] as const;
async function sendUSDm(to: string, amount: string): Promise<string> {
const walletClient = createWalletClient({
chain: celo,
transport: custom(window.ethereum),
});
const [address] = await walletClient.getAddresses();
const hash = await walletClient.sendTransaction({
account: address,
to: USDM_ADDRESS,
data: encodeFunctionData({
abi: ERC20_ABI,
functionName: "transfer",
args: [to as `0x${string}`, parseUnits(amount, 18)],
}),
});
return hash;
}
Testing Your Mini App
1. Set Up ngrok
MiniPay cannot access localhost. Use ngrok to create a tunnel:
ngrok http 3000
2. Enable Developer Mode in MiniPay
- Open MiniPay > Settings > About
- Tap Version number repeatedly until Developer Mode is enabled
- Go to Settings > Developer Settings
- Enable "Use Testnet" for Celo Sepolia
3. Load Your App
- Open MiniPay > Tap compass icon
- Select "Test Page"
- Enter your ngrok HTTPS URL
- Tap "Go"
Requirements and Limitations
Supported
- Celo Mainnet and Celo Sepolia Testnet only
- viem v2+ and wagmi libraries
- TypeScript v5+, Node.js v20+
- USDm (cUSD), USDC, and USDT stablecoins
Not Supported
- ethers.js (use viem instead)
- EIP-1559 transactions (legacy only)
- Message signing
- Android/iOS emulators (use real device)
- Other blockchain networks
Dependencies
{
"dependencies": {
"viem": "^2.0.0",
"@celo/abis": "^11.0.0"
},
"devDependencies": {
"typescript": "^5.0.0"
}
}
Additional Resources
- testing-guide.md - Detailed testing instructions
- troubleshooting.md - Common issues and solutions
- code-examples.md - Gas estimation, fee currency, React hooks
More from celo-org/agent-skills
evm-hardhat
Hardhat development for EVM chains including Celo. Use when setting up Hardhat projects, writing Solidity contracts, compiling, testing, deploying, or verifying contracts with Hardhat.
7evm-foundry
Foundry development for EVM chains including Celo. Use when working with forge, cast, anvil, writing Solidity contracts, testing, deploying, or verifying contracts with Foundry.
5x402
x402 HTTP-native payment protocol for AI agents on Celo. Use when implementing pay-per-use APIs, agent micropayments, or HTTP 402 Payment Required flows with stablecoins.
3viem
Use viem for Celo development. Includes fee currency support, transaction signing, and Celo-specific configurations.
3wagmi
Use wagmi React hooks for Celo dApps. Includes wallet connection, transaction hooks, and React integration patterns.
3evm-wallet-integration
Integrate wallets into Celo dApps. Covers RainbowKit, Dynamic, and wallet connection patterns.
3