Skip to main content

MiniPay Code Library

Snippets of code that can be used to implement flows inside MiniPay

warning

Make sure you are using Typescript v5 or above and Viem v2 or above.

Get the connected user's address without any Library

// The code must run in a browser environment and not in node environment
if (window && window.ethereum) {
// User has a injected wallet

if (window.ethereum.isMiniPay) {
// User is using Minipay

// Requesting account addresses
let accounts = await window.ethereum.request({
method: "eth_requestAccounts",
params: [],
});

// Injected wallets inject all available addresses,
// to comply with API Minipay injects one address but in the form of array
console.log(accounts[0]);
}

// User is not using MiniPay
}

// User does not have a injected wallet

To use the code snippets below, install the following packages:

yarn add @celo/abis @celo/identity viem@1

Check cUSD Balance of an address

const { getContract, formatEther, createPublicClient, http } = require("viem");
const { celo } = require("viem/chains");
const { stableTokenABI } = require("@celo/abis");

const STABLE_TOKEN_ADDRESS = "0x765DE816845861e75A25fCA122bb6898B8B1282a";

async function checkCUSDBalance(publicClient, address) {
let StableTokenContract = getContract({
abi: stableTokenABI,
address: STABLE_TOKEN_ADDRESS,
publicClient,
});

let balanceInBigNumber = await StableTokenContract.read.balanceOf([
address,
]);

let balanceInWei = balanceInBigNumber.toString();

let balanceInEthers = formatEther(balanceInWei);

return balanceInEthers;
}

const publicClient = createPublicClient({
chain: celo,
transport: http(),
}); // Mainnet

let balance = await checkCUSDBalance(publicClient, address); // In Ether unit

Check If a transaction succeeded

const { createPublicClient, http } = require("viem");
const { celo } = require("viem/chains");

async function checkIfTransactionSucceeded(publicClient, transactionHash) {
let receipt = await publicClient.getTransactionReceipt({
hash: transactionHash,
});

return receipt.status === "success";
}

const publicClient = createPublicClient({
chain: celo,
transport: http(),
}); // Mainnet

let transactionStatus = await checkIfTransactionSucceeded(
publicClient,
transactionHash
);

Estimate Gas for a transaction (in Celo)

const { createPublicClient, http } = require("viem");
const { celo } = require("viem/chains");

async function estimateGas(publicClient, transaction, feeCurrency = "") {
return await publicClient.estimateGas({
...transaction,
feeCurrency: feeCurrency ? feeCurrency : "",
});
}

const publicClient = createPublicClient({
chain: celo,
transport: http(),
});

let gasLimit = await estimateGas(publicClient, {
account: "0x8eb02597d85abc268bc4769e06a0d4cc603ab05f",
to: "0x4f93fa058b03953c851efaa2e4fc5c34afdfab84",
value: "0x1",
data: "0x",
});

Estimate Gas for a transaction (in cUSD)

const { createPublicClient, http } = require("viem");
const { celo } = require("viem/chains");

async function estimateGas(publicClient, transaction, feeCurrency = "") {
return await publicClient.estimateGas({
...transaction,
feeCurrency: feeCurrency ? feeCurrency : "",
});
}

const publicClient = createPublicClient({
chain: celo,
transport: http(),
});

const STABLE_TOKEN_ADDRESS = "0x765DE816845861e75A25fCA122bb6898B8B1282a";

let gasLimit = await estimateGas(
publicClient,
{
account: "0x8eb02597d85abc268bc4769e06a0d4cc603ab05f",
to: "0x4f93fa058b03953c851efaa2e4fc5c34afdfab84",
value: "0x1",
data: "0x",
},
STABLE_TOKEN_ADDRESS
);

Estimate Gas Price for a transaction (in Celo)

const { createPublicClient, http } = require("viem");
const { celo } = require("viem/chains");

async function estimateGasPrice(publicClient, feeCurrency = "") {
return await publicClient.request({
method: "eth_gasPrice",
params: feeCurrency ? [feeCurrency] : [],
});
}

const publicClient = createPublicClient({
chain: celo,
transport: http(),
});

let gasPrice = await estimateGasPrice(publicClient);

Estimate Gas Price for a transaction (in cUSD)

const { createPublicClient, http } = require("viem");
const { celo } = require("viem/chains");

async function estimateGasPrice(publicClient, feeCurrency = "") {
return await publicClient.request({
method: "eth_gasPrice",
params: feeCurrency ? [feeCurrency] : [],
});
}

const publicClient = createPublicClient({
chain: celo,
transport: http(),
});

const STABLE_TOKEN_ADDRESS = "0x765DE816845861e75A25fCA122bb6898B8B1282a";

let gasPrice = await estimateGasPrice(publicClient, STABLE_TOKEN_ADDRESS);

Calculate cUSD to be spent for transaction fees

const { createPublicClient, http, formatEther } = require("viem");
const { celo } = require("viem/chains");

const publicClient = createPublicClient({
chain: celo,
transport: http(),
});

const STABLE_TOKEN_ADDRESS = "0x765DE816845861e75A25fCA122bb6898B8B1282a";

// `estimateGas` implemented above
let gasLimit = await estimateGas(
publicClient,
{
account: "0x8eb02597d85abc268bc4769e06a0d4cc603ab05f",
to: "0x4f93fa058b03953c851efaa2e4fc5c34afdfab84",
value: "0x1",
data: "0x",
},
STABLE_TOKEN_ADDRESS
);

// `estimateGasPrice` implemented above
let gasPrice = await estimateGasPrice(publicClient, STABLE_TOKEN_ADDRESS);

let transactionFeesInCUSD = formatEther(gasLimit * hexToBigInt(gasPrice));

Resolve Minipay phone numbers to Addresses

const { createPublicClient, http } = require("viem");
const { celo } = require("viem/chains");
const { privateKeyToAccount } = require("viem/accounts");
const { SocialConnectIssuer } = require("./SocialConnect.js");

let account = privateKeyToAccount(process.env.ISSUER_PRIVATE_KEY);

let walletClient = createWalletClient({
account,
transport: http(),
chain,
});

const issuer = new SocialConnectIssuer(walletClient, {
authenticationMethod: AuthenticationMethod.ENCRYPTION_KEY,
rawKey: process.env.DEK_PRIVATE_KEY,
});

await issuer.initialize();

const identifierType = IdentifierPrefix.PHONE_NUMBER;

/**
* Any phone number you want to lookup
*
* The below phone number is registered on the testnet issuer mentioned below.
*/
const identifier = "+911234567890";

/**
* You can lookup under multiple issuers in one request.
*
* Below is the MiniPay issuer address on Mainnet.
*
* Note: Remember to make your environment variable ENVIRONMENT=MAINNET
*/
let issuerAddresses = ["0x7888612486844Bb9BE598668081c59A9f7367FBc"];

// A testnet issuer we setup for you to lookup on testnet.
// let issuerAddresses = ["0xDF7d8B197EB130cF68809730b0D41999A830c4d7"];

let results = await issuer.lookup(identifier, identifierType, issuerAddresses);

Request an ERC20 token transfer

import { createWalletClient, custom } from 'viem'
// import { celo } from 'viem/chains'
import { celoAlfajores } from 'viem/chains'

const client = createWalletClient({
chain: celoAlfajores,
// chain: celo,
transport: custom(window.ethereum!)
})

const publicClient = createPublicClient({
chain: celoAlfajores,
// chain: celo,
transport: http()
})

async function requestTransfer(tokenAddress, transferValue, tokenDecimals) {

let hash = await client.sendTransaction({
to: tokenAddress,
// to: '0x765DE816845861e75A25fCA122bb6898B8B1282a' // cUSD (Mainnet)
// to: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C' // USDC (Mainnet)
// to: '0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e' // USDT (Mainnet)
data: encodeFunctionData({
abi: stableTokenAbi, // Token ABI can be fetched from Explorer.
functionName: "transfer",
args: [
receiverAddress,
// Different tokens can have different decimals, cUSD (18), USDC (6)
parseUnits(`${Number(transferValue)}`, tokenDecimals),
],
}),
// If the wallet is connected to a different network then you get an error.
chain: celoAlfajores,
// chain: celo,
});

const transaction = await publicClient.waitForTransactionReceipt({
hash, // Transaction hash that can be used to search transaction on the explorer.
});

if (transaction.status === "success") {
// Do something after transaction is successful.
} else {
// Do something after transaction has failed.
}
}