MOI Wallet
MOI Wallet is the official self-custodial wallet for the MOI Protocol. It is available as a mobile app (iOS and Android) and a browser extension (Chrome). Keys and seed phrases are generated and encrypted on the user's device and never leave it.
Download & Install
| Platform | Link |
|---|---|
| iOS (iPhone & iPad) | App Store |
| Android (Phone & Tablet) | Google Play |
| Chrome Browser Extension | Chrome Web Store |
Full documentation for the wallet is available at docs.wallet.moi.technology.
Mobile App
The mobile wallet supports iOS 16+ and Android 8.0+. Key capabilities:
- Create a new wallet or import from a seed phrase
- Biometric unlock (Face ID, Touch ID, fingerprint) — handled entirely by the device
- Multi-account and sub-account management
- Send and receive MOI assets with a full review flow
- WalletConnect v2 — connect to any MOI dApp by scanning a QR code
- Switch between Mainnet and Testnet
- Real-time push notifications for transactions and session requests
Browser Extension
The Chrome extension injects a window.moi transport into every page. The recommended way to interact with it is through the BrowserProvider class from js-moi-sdk, which wraps the injected transport and exposes a typed API for requesting accounts, sending interactions, and listening to wallet events.
Installation
npm install js-moi-sdk
Detecting the Wallet
import { BrowserProvider } from "js-moi-sdk";
if (globalThis?.moi?.__isMOIWallet === true) {
const provider = new BrowserProvider(globalThis.moi);
}
Requesting Account Access
requestPermissions prompts the user to grant your dApp access to their accounts. Once approved, getWalletAccounts returns the list of addresses — the first element is the currently active account.
import { BrowserProvider } from "js-moi-sdk";
const provider = new BrowserProvider(globalThis.moi);
// Prompt the user to approve account access
await provider.requestPermissions("wallet.Accounts", {});
// Retrieve the list of account addresses
const accounts = await provider.getWalletAccounts();
// returns Hex[] — first element is the active account
Sending an Interaction
import { BrowserProvider } from "js-moi-sdk";
const provider = new BrowserProvider(globalThis.moi);
const response = await provider.sendInteraction({
type: 3,
fuel_price: 1,
fuel_limit: 200,
});
// Wait for the interaction to be confirmed
const receipt = await response.wait();
console.log(response.hash);
The wallet surfaces a full review screen to the user before signing. sendInteraction rejects with an error if the user cancels.
Listening for Account and Network Changes
import { BrowserProvider } from "js-moi-sdk";
const provider = new BrowserProvider(globalThis.moi);
provider.on("accountChange", (identifier) => {
// user switched to a different account
console.log("active account:", identifier);
});
provider.on("networkChange", (network) => {
// user switched network or RPC endpoint
console.log("network:", network.name, network.jsonRpcHost);
});
Reading the Active Network
import { BrowserProvider } from "js-moi-sdk";
const provider = new BrowserProvider(globalThis.moi);
const network = await provider.getNetwork();
// { id, name, jsonRpcHost, blockExplorer? }
console.log(network?.name);
BrowserProvider API Reference
| Method | Description |
|---|---|
requestPermissions(key, permission) | Prompts the user to grant access (e.g. "wallet.Accounts") |
getPermissions() | Returns the dApp's currently granted permissions |
revokePermissions(key, permission) | Revokes a previously granted permission |
getWalletAccounts() | Returns all account addresses; first element is the active account |
getWalletAccount(id?) | Returns a single WalletParticipant by identifier, or the master account |
sendInteraction(interaction) | Submits an interaction for user review and signing |
getNetwork() | Returns the active NetworkConfiguration |
getWalletVersion() | Returns the installed wallet version string |
on(event, listener) | Subscribes to "accountChange" or "networkChange" events |
For the full API reference, see the Developer Reference in the wallet docs.
Security Model
- Keys and seed phrases are generated locally and protected with AES-256-GCM encryption and scrypt key derivation
- Biometric data is handled entirely by the OS (Secure Enclave / Android Keystore) — the wallet never sees it
- The extension codebase is open-source on GitHub
- Non-custodial architecture — Sarva Labs has no access to user funds or keys
Resources
- MOI Wallet Website
- Developer Documentation
- GitHub — Sarva Labs
- JS MOI SDK — for building dApps that submit interactions programmatically