> ## Documentation Index
> Fetch the complete documentation index at: https://docs.celo.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Build for MiniPay

> What is Celo-specific about building a MiniPay Mini App — stablecoins, gas paid in stablecoins, detecting MiniPay, phone-number lookup — plus the index of the MiniPay developer docs for everything else

This page is for developers building a Mini App for [MiniPay](https://www.opera.com/products/minipay), the stablecoin wallet from Opera. It covers only what is specific to Celo. The build, test and submit lifecycle is documented by the MiniPay team at [docs.minipay.xyz](https://docs.minipay.xyz/); the index at the end of this page lists every page there so you — or your coding agent — can see what is available without leaving this site.

MiniPay runs only on Celo (mainnet) and Celo Sepolia (testnet). It has more than 10M activations, a built-in Mini App discovery page, and ships inside the Opera Mini Android browser and as a standalone app for [Android](https://play.google.com/store/apps/details?id=com.opera.minipay) and [iOS](https://apps.apple.com/de/app/minipay-easy-global-wallet/id6504087257?l=en-GB). Balances are shown in the user's local currency, the wallet is 2 MB, and phone numbers can stand in for addresses.

## Prerequisites

* A web app (any framework) reachable over HTTPS; for local development use `ngrok http 3000` to expose `localhost`
* [viem](/build/tools/libraries-sdks/viem/index) or [wagmi](https://wagmi.sh/) — both support Celo's fee-currency transactions natively
* Testnet funds: CELO from the [Celo Sepolia faucet](https://faucet.celo.org/celo-sepolia), swapped to a stablecoin in the [Mento app](https://app.mento.org/)
* To scaffold: `npx @celo/celo-composer@latest create -t minipay` (the [MiniPay template](https://github.com/celo-org/minipay-template)), or follow the [MiniPay quick start](https://docs.minipay.xyz/getting-started/quick-start.html)

## What is Celo-specific

### Stablecoins are the only assets

MiniPay holds USDm, USDC and USDT — no CELO balance is shown to the user. Price and settle in one of these.

| Token | Celo mainnet (42220) | Decimals |
| - | - | - |
| USDm | [`0x765DE816845861e75A25fCA122bb6898B8B1282a`](https://celoscan.io/address/0x765DE816845861e75A25fCA122bb6898B8B1282a) | 18 |
| USDC | [`0xcebA9300f2b948710d2653dD7B07f33A8B32118C`](https://celoscan.io/address/0xcebA9300f2b948710d2653dD7B07f33A8B32118C) | 6 |
| USDT | [`0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e`](https://celoscan.io/address/0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e) | 6 |

<Warning>
  USDC and USDT use **6 decimals**; USDm uses 18. `parseUnits(amount, 18)` on a USDC transfer sends 10¹² times the intended amount. Pass the token's decimals explicitly.
</Warning>

```ts theme={null}
import { erc20Abi, parseUnits, encodeFunctionData } from "viem";

// USDC on Celo mainnet (42220): 6 decimals
const USDC = "0xcebA9300f2b948710d2653dD7B07f33A8B32118C";
const hash = await walletClient.sendTransaction({
  to: USDC,
  data: encodeFunctionData({
    abi: erc20Abi,
    functionName: "transfer",
    args: [receiver, parseUnits("1.50", 6)], // 1.50 USDC
  }),
});
```

Testnet addresses are on [Fee currency contracts](/build/tools/contracts/fee-currencies).

### Gas is paid in stablecoins

MiniPay uses [fee abstraction](/build/fee-abstraction/overview): the user never holds CELO, and the wallet pays gas in the stablecoin the user holds the most of. You may set `feeCurrency` on `eth_sendTransaction`, but MiniPay can override it. Do not build flows that assume a CELO balance, and do not show a "buy CELO for gas" step.

To show a fee estimate in the user's currency, estimate gas and gas price in that token. The JSON-RPC methods accept the fee currency directly:

```ts theme={null}
// Celo mainnet (42220); USDm has 18 decimals. For USDC/USDT use the *adapter* address, see fee abstraction.
const USDM = "0x765DE816845861e75A25fCA122bb6898B8B1282a";

const gasLimit = await publicClient.request({
  method: "eth_estimateGas",
  params: [{ from: account, to, value: "0x0", data: "0x", feeCurrency: USDM }],
});
const gasPrice = await publicClient.request({
  method: "eth_gasPrice",
  params: [USDM],
});
const feeInUsdm = formatUnits(BigInt(gasLimit) * BigInt(gasPrice), 18);
```

In the UI, label this "network fee", not "gas" — see the MiniPay [design standards](https://docs.minipay.xyz/design-standards/).

### Detect MiniPay and skip the connect button

Inside MiniPay the wallet is already connected through the injected provider, and `window.ethereum.isMiniPay` is `true`. Hide your connect-wallet UI and connect the injected connector on load:

```tsx theme={null}
import { useEffect, useState } from "react";
import { useConnect } from "wagmi";
import { injected } from "wagmi/connectors";

export function useMiniPay() {
  const [isMiniPay, setIsMiniPay] = useState(false);
  const { connect } = useConnect();

  useEffect(() => {
    if (window.ethereum?.isMiniPay) {
      setIsMiniPay(true);
      connect({ connector: injected({ target: "metaMask" }) });
    }
  }, [connect]);

  return isMiniPay; // render <ConnectButton /> only when false
}
```

Check for `window.ethereum` before initialising any web3 library; the provider is injected by the host. Wallet-connection details and error handling: [Wallet connection](https://docs.minipay.xyz/getting-started/wallet-connection.html).

### Resolve MiniPay phone numbers to addresses

MiniPay maps phone numbers to addresses through [SocialConnect](/build/build-on-socialconnect) and ODIS. To look a number up you act as an *issuer*: an account that has verified the user owns the number (for example by SMS), has a [data encryption key (DEK)](https://github.com/celo-org/social-connect) registered on the Accounts contract, and holds ODIS quota.

```bash theme={null}
npm install @celo/identity @celo/abis viem
```

```ts theme={null}
import { createPublicClient, http } from "viem";
import { celo } from "viem/chains";
import { federatedAttestationsABI } from "@celo/abis";
import { OdisUtils } from "@celo/identity";
import type { AuthSigner } from "@celo/identity/lib/odis/query";

// Celo mainnet (42220). @celo/identity ships ODIS contexts for mainnet only — no Celo Sepolia.
const FEDERATED_ATTESTATIONS = "0x0aD5b1d0C25ecF6266Dd951403723B2687d6aff2";
const issuerAddress = "0xYourIssuerAddress";

// 1. Authenticate with ODIS using the issuer's DEK private key
const authSigner: AuthSigner = {
  authenticationMethod: OdisUtils.Query.AuthenticationMethod.ENCRYPTION_KEY,
  rawKey: process.env.ISSUER_DEK_PRIVATE_KEY!,
};
const serviceContext = OdisUtils.Query.getServiceContext(OdisUtils.Query.OdisContextName.MAINNET);

// 2. Check quota; top up by paying OdisPayments (0xAE6B29f31B96e61DdDc792f45fDa4e4F0356D0CB) if it is 0
const { remainingQuota } = await OdisUtils.Quota.getPnpQuotaStatus(issuerAddress, authSigner, serviceContext);

// 3. Derive the obfuscated identifier for the phone number (one quota unit per call)
const { obfuscatedIdentifier } = await OdisUtils.Identifier.getObfuscatedIdentifier(
  "+12345678910",
  OdisUtils.Identifier.IdentifierPrefix.PHONE_NUMBER,
  issuerAddress,
  authSigner,
  serviceContext,
);

// 4. Read the accounts attested for it by the issuers you trust
const publicClient = createPublicClient({ chain: celo, transport: http() });
const [, accounts] = await publicClient.readContract({
  address: FEDERATED_ATTESTATIONS,
  abi: federatedAttestationsABI,
  functionName: "lookupAttestations",
  args: [obfuscatedIdentifier as `0x${string}`, [issuerAddress]],
});
console.log(accounts);
```

Contract addresses are from the on-chain registry (`FederatedAttestations`, `OdisPayments`) and listed on [Core contracts](/build/tools/contracts/core-contracts). The MiniPay reference for this is [Phone number lookup](https://docs.minipay.xyz/technical-references/phone-number-lookup.html).

### Deeplinks

Deeplinks open a MiniPay screen from your Mini App or from outside (WhatsApp, a web page). The host is `link.minipay.xyz`; users without the app get an install prompt.

| Action | Deeplink |
| - | - |
| Add cash, optionally scoped to tokens | `https://link.minipay.xyz/add_cash?tokens=USDM,USDT,USDC` |
| Open an approved Mini App | `https://link.minipay.xyz/browse?url=https://your-app.example` |
| Discovery page | `https://link.minipay.xyz/discover` |
| Transaction receipt (append `&celebrate` for an animation) | `https://link.minipay.xyz/receipt?tx=0x…` |
| User's QR code | `https://link.minipay.xyz/qr` |
| Invite friends | `https://link.minipay.xyz/invite_friends` |
| Balance (pockets) | `https://link.minipay.xyz/balance` |

Reference: [Deeplinks](https://docs.minipay.xyz/technical-references/deeplinks.html).

## Test inside MiniPay

You cannot test in an Android emulator; use a phone.

1. In the MiniPay app open **Settings → About** and tap the **Version** number until developer mode is confirmed.
2. Back in **Settings → Developer Settings**, enable **Developer Mode** and, for Celo Sepolia, **Use Testnet**.
3. Tap **Load Test Page**, enter your app's HTTPS URL (the `ngrok` URL for local development), and tap **Go**.

Step-by-step with screenshots: [Test your Mini App inside MiniPay](https://docs.minipay.xyz/getting-started/test-in-minipay.html).

## The MiniPay developer docs

Everything below lives at docs.minipay.xyz and is maintained by the MiniPay team.

**Getting started**

* [What are Mini Apps?](https://docs.minipay.xyz/getting-started/overview.html)
* [Quick start](https://docs.minipay.xyz/getting-started/quick-start.html) — scaffold a Mini App with the Celo agent skills
* [Test your Mini App inside MiniPay](https://docs.minipay.xyz/getting-started/test-in-minipay.html)
* [Project setup](https://docs.minipay.xyz/getting-started/project-setup.html) and [Setting up a React app](https://docs.minipay.xyz/getting-started/setup-react.html)
* [FAQ](https://docs.minipay.xyz/faq.html)

**Guides**

* [Wallet connection](https://docs.minipay.xyz/getting-started/wallet-connection.html) — injected provider, auto-connect, connection state, errors
* [UI and container integration](https://docs.minipay.xyz/getting-started/ui-and-container.html)
* [Interacting with smart contracts](https://docs.minipay.xyz/getting-started/smart-contracts.html)
* [Best practices](https://docs.minipay.xyz/getting-started/best-practices.html)
* [Deployment](https://docs.minipay.xyz/getting-started/deployment.html)
* [Submit your Mini App](https://docs.minipay.xyz/getting-started/submit-your-miniapp.html) to the discovery page
* [Building for MiniPay](https://docs.minipay.xyz/getting-started/why-minipay.html) and [Availability](https://docs.minipay.xyz/getting-started/availability.html)
* [Design standards](https://docs.minipay.xyz/design-standards/) — including user-facing terminology
* [Examples](https://docs.minipay.xyz/getting-started/examples.html)

**Technical reference**

* [Retrieve balance](https://docs.minipay.xyz/technical-references/retrieve-balance.html)
* [Send a transaction](https://docs.minipay.xyz/technical-references/send-transaction.html) — USDC, USDT, USDm with wagmi
* [Gas estimation](https://docs.minipay.xyz/technical-references/gas-estimation.html)
* [Transaction status](https://docs.minipay.xyz/technical-references/transaction-status.html)
* [Phone number lookup](https://docs.minipay.xyz/technical-references/phone-number-lookup.html)
* [Chain switching](https://docs.minipay.xyz/technical-references/chain-switching.html)
* [Deeplinks](https://docs.minipay.xyz/technical-references/deeplinks.html)
* Custom methods: [overview](https://docs.minipay.xyz/technical-references/custom-methods/custom-methods.html), [getExchangeRate](https://docs.minipay.xyz/technical-references/custom-methods/get-exchange-rate.html), [scanQrCode](https://docs.minipay.xyz/technical-references/custom-methods/scan-qr-code.html), [requestContact](https://docs.minipay.xyz/technical-references/custom-methods/request-contact.html)

## Funding and programs

* Raising? Send a deck or product demo to [team@verda.ventures](mailto:team@verda.ventures).
* Grants and accelerators: [Fund your project](/build/fund-your-project).

## Related

* [Fee abstraction](/build/fee-abstraction/overview) - How gas in stablecoins works and the adapter addresses for USDC and USDT
* [Fee currency contracts](/build/tools/contracts/fee-currencies) - Token and adapter addresses per network
* [Build with local stablecoins](/build/build-with-local-stablecoin) - Mento stablecoins beyond USDm
* [SocialConnect](/build/build-on-socialconnect) - Phone-number to address mapping
* [Celo Composer](/build/quickstart) - Scaffold a MiniPay-ready app


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.