{{ t.tagline }}
``` ```js [React (src/App.jsx)] const translations = { en: { greeting: 'Hello', tagline: 'Nimiq Pay mini-app starter' }, es: { greeting: 'Hola', tagline: 'Plantilla de mini-app para Nimiq Pay' }, de: { greeting: 'Hallo', tagline: 'Nimiq Pay Mini-App Starter' }, fr: { greeting: 'Bonjour', tagline: 'Starter de mini-app Nimiq Pay' }, pt: { greeting: 'Olá', tagline: 'Modelo de mini-app para Nimiq Pay' }, } const t = translations[window.nimiqPay?.language] ?? translations[navigator.language.split('-')[0]] ?? translations.en export default function App() { return ( <>{t.tagline}
> ) } ``` ```bash [Svelte (src/App.svelte)]{t.tagline}
``` :: ## Using an i18n library For apps with many strings or complex pluralization, pass `window.nimiqPay?.language` as the locale to your i18n library of choice (e.g. [`vue-i18n`](https://vue-i18n.intlify.dev/){rel=""nofollow""}, [`react-i18next`](https://react.i18next.com/){rel=""nofollow""}, [`svelte-i18n`](https://github.com/kaisermann/svelte-i18n){rel=""nofollow""}) and set `'en'` as the fallback locale. # Mini App Ideas A collection of ideas for mini apps that run inside Nimiq Pay. Each idea lists what it does, which providers it needs, and any external APIs that could power it. Pick one, adapt it, or use it as a starting point for something entirely different. ## Payments and Commerce | Idea | What it does | Providers | External APIs | | ------------------ | ------------------------------------------------------------------ | --------- | ----------------------------- | | Tip Jar | Accept NIM tips with a shareable link and a live tip counter | Nimiq | | | Invoice Generator | Create and send NIM payment requests with memo text | Nimiq | | | Pay-per-Use Access | Unlock content or features with a one-time NIM payment | Nimiq | | | Split the Bill | Split a restaurant bill among friends, pay each share in NIM | Nimiq | | | Donation Page | Accept NIM or USDT donations with goal tracking and a progress bar | Both | | | Merchant Checkout | Accept USDT on Polygon for physical or digital goods | Ethereum | | | Freelancer Invoice | Send USDT invoices with a payment link, track paid/unpaid status | Ethereum | | | Gift Cards | Purchase and send digital gift cards paid with NIM or USDT | Both | Gift card API (e.g. Reloadly) | ## Finance and Portfolio | Idea | What it does | Providers | External APIs | | ------------------- | ------------------------------------------------------------------------------------------ | --------- | ------------------- | | Portfolio Tracker | Show NIM balance and ERC-20 token holdings across all supported chains | Both | CoinGecko | | Price Alerts | Notify the user when NIM or a token hits a target price | Ethereum | CoinGecko, Push API | | Savings Goal | Set a NIM savings target and track progress over time | Nimiq | | | Staking Dashboard | Stake NIM, view active stake, switch validators, track rewards | Nimiq | | | Multi-Chain Balance | Display native and token balances across Polygon, Arbitrum, Base, and Optimism in one view | Ethereum | | | Expense Tracker | Log transactions with categories and export monthly reports | Both | | ## Games and Entertainment | Idea | What it does | Providers | External APIs | | ------------------- | ----------------------------------------------------------------- | --------- | --------------------- | | Coin Flip | Two players bet NIM on a coin flip with on-chain randomness | Nimiq | | | Trivia Challenge | Answer trivia questions, bet NIM per round, winner takes the pot | Nimiq | Open Trivia DB | | Prediction Market | Bet USDT on outcomes of events (sports, crypto prices, elections) | Ethereum | Sports API, CoinGecko | | NFT Gallery | Browse and display NFTs from the user's EVM wallet | Ethereum | Alchemy, OpenSea API | | Music Jukebox | Pay a small NIM fee to queue songs in a shared playlist | Nimiq | Spotify API | | Meme Generator | Create memes, tip the best ones with NIM | Nimiq | Imgflip API, Giphy | | Rock Paper Scissors | Play against another user with NIM stakes | Nimiq | | ## Social and Community | Idea | What it does | Providers | External APIs | | ------------------- | ---------------------------------------------------------------------------------- | --------- | ------------- | | Proof of Attendance | Sign a message with your Nimiq or Ethereum identity to prove you attended an event | Both | | | Polls with Stakes | Create polls where voters stake NIM on their answer, majority wins the pool | Nimiq | | | Group Poll | Create polls where participants sign their vote with their Nimiq identity | Nimiq | | | Social Feed | Post short messages signed with your Nimiq identity, tip posts with NIM | Nimiq | | | Group Savings | Pool NIM with friends toward a shared goal, transparent balances | Nimiq | | ## Productivity and Utilities | Idea | What it does | Providers | External APIs | | ----------- | -------------------------------------------------------------------------- | --------- | ----------------- | | AI Chat | Chat with an AI model, pay per message or per session in NIM | Nimiq | OpenAI, Anthropic | | File Locker | Upload files to IPFS, pay for pinning with USDT | Ethereum | Pinata, IPFS | | Weather Bet | Bet NIM on tomorrow's weather in your city | Nimiq | OpenWeatherMap | | QR Pay | Generate QR codes that trigger NIM or USDT payments when scanned | Both | | | Pastebin | Create shareable text snippets, tip the author in NIM | Nimiq | | | Translator | Translate text using an AI model, pay per translation in NIM | Nimiq | DeepL, OpenAI | | Faucet | Distribute free testnet NIM to new users, gated by captcha and rate limits | Nimiq | Captcha API | # Mini Apps Build mini apps that run inside Nimiq Pay, with optional access to Nimiq and Ethereum wallet features. ## What are Mini Apps? Mini apps are web applications that run inside the Nimiq Pay app. They can support a wide range of in-app experiences, from general web tools to apps that interact with Nimiq and Ethereum wallets. Think of it like a specialized web browser embedded within Nimiq Pay. Your mini app loads in the Nimiq Pay app and, when needed, can request wallet operations like listing accounts, signing messages, or sending payments, all while the user stays within the Nimiq Pay app. The wallet handles all the cryptographic operations securely, and users approve every sensitive action through native confirmation dialogs. ## How It Works Mini apps run in a WebView and talk to Nimiq Pay through injected providers. For Nimiq provider access, the recommended pattern is to use the Mini App SDK `init()` helper to wait until the provider is ready: ```javascript import { init } from '@nimiq/mini-app-sdk' const nimiq = await init() const [accounts, consensus, blockNumber] = await Promise.all([ nimiq.listAccounts(), nimiq.isConsensusEstablished(), nimiq.getBlockNumber(), ]) ``` ### Components | Component | Lives in | What it does | | ----------------------------------------------------- | ------------------------------- | --------------------------------------------------------------------------------------------- | | Injected Provider (`window.ethereum`, Nimiq provider) | WebView (injected by Nimiq Pay) | Exposes wallet APIs and sends requests to the host | | Host-side API | Nimiq Pay (native) | Receives requests, validates them, shows approval dialogs, executes actions | | Mini App SDK | WebView (your app or injected) | Waits for the Nimiq provider, adds typed access for TypeScript, and exposes Nimiq-native APIs | Your mini app uses standard Web3 APIs via `window.ethereum` and Nimiq-specific APIs via the Mini App SDK `init()` helper. ### Request lifecycle 1. Your mini app calls a provider method (for example, request accounts or sign a message) 2. The injected provider forwards a message to the Nimiq Pay app 3. The Nimiq Pay app validates the request and shows a native confirmation dialog (when required) 4. If approved, Nimiq Pay executes the wallet operation (keys never leave the wallet) 5. The result is returned to your mini app through the provider ## Supported Networks The framework supports two blockchain ecosystems: **Nimiq** - Native support for NIM payments, message signing, and consensus checks - Direct integration with Nimiq Pay's core wallet features **Ethereum + Layer 2 networks** (EVM-compatible) - Ethereum Mainnet - [Polygon](https://nimiq.com/developers/mini-apps/features/evm-tokens) - Arbitrum One - Optimism - Base - BNB Smart Chain (formerly Binance Smart Chain) - Sepolia (testnet for developers) ERC-20 tokens on any listed chain — including USDT on Polygon — are accessible through `window.ethereum` with no additional setup. See [Using EVM Tokens in Mini Apps](https://nimiq.com/developers/mini-apps/features/evm-tokens) for a worked example. Any EVM-compatible chain supported by our RPC provider can be added; the list above reflects what we currently expose in Nimiq Pay. Additional EVM networks can be added over time via configuration updates. ## User Language Nimiq Pay exposes the user's selected language to mini apps via `window.nimiqPay.language`. The value is a read-only ISO 639-1 two-letter code (e.g. `'en'`, `'de'`, `'es'`) that mirrors the user's Nimiq Pay language setting. It is injected before page scripts run, so it is safe to read during app initialization. The value is static for the lifetime of the session. If the user changes their language in Nimiq Pay, the mini app picks it up the next time it opens. ```javascript const language = window.nimiqPay?.language // e.g. 'en' ``` Use this instead of `navigator.language`, which returns the device locale and may not match the language the user selected in Nimiq Pay. For fallback patterns, translations setup, and framework examples, see [Localization in Mini Apps](https://nimiq.com/developers/mini-apps/features/localization). ## Device Identifier Nimiq Pay can issue a pseudonymous per-device identifier to mini apps that need a stable handle, for example for leaderboards, anti-spam, or save slots. The identifier is a 64-character hex SHA-256 string scoped to your mini app's origin. It identifies the device, not the user: a shared device returns the same value to every user, and the same user on two devices receives two different identifiers. ```ts import { requestDeviceIdentifier } from '@nimiq/mini-app-sdk' const id = await requestDeviceIdentifier({ reason: 'Leaderboard ranking' }) ``` The first call per origin prompts the user with the `reason` you provide; subsequent calls resolve silently. For privacy properties, error handling, and TypeScript types, see [Device Identifier in Mini Apps](https://nimiq.com/developers/mini-apps/features/device-identifier). ## Security and Permissions Every sensitive action requires explicit user approval through native dialogs that mini apps cannot bypass. Your app runs in a secure sandbox with no direct access to private keys. The Nimiq Pay app mediates all wallet operations. Here's how security works: - **User consent is always required**: Viewing accounts, signing messages, and sending NIM payments trigger native confirmation dialogs - **Sandboxed execution**: Mini apps run in an isolated WebView with no access to the wallet's internal state or private keys - **Host app controls everything**: Your app can only *request* actions. The Nimiq Pay app decides whether to fulfill them, always with user approval - **Wallet requests are mediated**: Nimiq Pay handles wallet-related provider requests, while other RPC calls use the configured endpoint or your mini app's own RPC ## Sharing Your Mini App Once your mini app is published, you can share it using a deeplink that opens it directly inside Nimiq Pay. Two link formats are available: **Custom scheme** ```text nimiqpay://miniapp?url=your-app.com ``` When a user taps this link on their phone, Nimiq Pay opens and loads your mini app with full provider access. If the URL is not in the Nimiq Pay mini app list or has never been accessed before, Nimiq Pay displays a warning before proceeding. **HTTPS link** ```text https://nimpay.app/miniapps/open/your-app.com ``` Tapping this link opens the mini app the same way. It works with any domain. # Build a Dual-Chain Mini App with Nimiq Pay In this tutorial, you will build a mini app that uses both injected providers: - the Nimiq provider for Nimiq account and signing flows - the Ethereum provider for EIP-1193 account and signing flows You will implement methods that require user confirmations so you can test real wallet interactions end to end. ## What you'll build The mini app includes two action buttons: | Flow | Methods | User confirmation expected | | -------- | ---------------------------------------- | --------------------------------------- | | Nimiq | `listAccounts()` -> `sign()` | 2 prompts (account sharing, signing) | | Ethereum | `eth_requestAccounts` -> `personal_sign` | 2 prompts (account connection, signing) | ## Prerequisites - **Node.js** (version 22+ required) - **Nimiq Pay** app on a mobile device (or emulator) - Phone and dev machine on the same Wi-Fi network - At least one Ethereum account available in Nimiq Pay for the Ethereum success path ## 1. Create the project Use Vite with Vue + TypeScript for this tutorial: ```bash npm create vite@latest my-mini-app -- --template vue-ts cd my-mini-app npm install ``` ## 2. Configure the dev server Edit `vite.config.ts`: ```ts import vue from '@vitejs/plugin-vue' import { defineConfig } from 'vite' export default defineConfig({ plugins: [vue()], server: { port: 5173, host: true, }, }) ``` ## 3. Install the Nimiq Mini App SDK Install the published Nimiq Mini App SDK before editing `src/App.vue`. ```bash npm install @nimiq/mini-app-sdk ``` ## 4. Add the dual-chain mini app In `src/App.vue`, use separate script, template, and style blocks. ### 4.1 Add the script block ```vue ``` ### 4.2 Add the template block ```vueWaiting for the Nimiq provider to initialize...
Status: {{ status }}
Error: {{ errorMessage }}
Accounts: {{ JSON.stringify(nimiqAccounts, null, 2) }}
Signature: {{ nimiqSignature }}
Accounts: {{ JSON.stringify(ethAccounts, null, 2) }}
Signature: {{ ethSignature }}
Waiting for Nimiq Pay to initialize the provider...
Open this mini app inside Nimiq Pay to connect to the Nimiq provider.
Accounts: {{ accounts }}
Consensus: {{ consensus }}
Block: {{ blockNumber }}
{{ errorMessage }}
Waiting for Nimiq Pay to initialize the provider...
)} {!isConnecting && !isReady && (Open this mini app inside Nimiq Pay to connect to the Nimiq provider.
)} {accounts && (
Accounts:
{JSON.stringify(accounts)}
)}
{consensus !== null && (
Consensus:
{String(consensus)}
)}
{blockNumber !== null && (
Block:
{String(blockNumber)}
)}
{errorMessage && {errorMessage}
}Waiting for Nimiq Pay to initialize the provider...
{:else if !isReady}Open this mini app inside Nimiq Pay to connect to the Nimiq provider.
{/if} {#if accounts}Accounts: {JSON.stringify(accounts)}
{/if}
{#if consensus !== null}
Consensus: {String(consensus)}
{/if}
{#if blockNumber !== null}
Block: {String(blockNumber)}
{/if}
{#if errorMessage}
{errorMessage}
{/if}Connecting to blockchain...
if (error) { return (Error: {error}
) } return (Block Height: {blockHeight.toLocaleString()}
Network: {client?.getNetworkId()}