Mini Apps

Provider runtime

Wait for the Nimiq mini-app provider and handle unavailable host state.

Use @onmax/nimiq-mini-app-kit when your app needs the Nimiq Pay window.nimiq provider. The helpers give you one typed entry point for the real host, the Nuxt simulator, and tests with custom sources.

Do not use these helpers for generic Nimiq RPC access. Use @onmax/unimiq when the app is not running as a Nimiq Pay mini app.

Choose the provider path

Use initMiniAppProvider() when an action cannot continue without the provider.

Use getMiniAppProvider() when you only need to render an available, loading, or unavailable state.

Use source or target only in tests, embedded shells, or non-window runtimes.

Wait before a wallet action

Put confirmation-requiring calls behind a user action. listAccounts(), sign(), and transaction methods can open host approval UI.

app/nimiq-pay.ts
import {
  initMiniAppProvider,
  isMiniAppProviderError,
} from '@onmax/nimiq-mini-app-kit'

export async function signCheckout(orderId: string) {
  const provider = await initMiniAppProvider({ timeout: 10_000 })
  const result = await provider.sign(`Confirm checkout ${orderId}`)

  if (isMiniAppProviderError(result))
    throw new Error(result.error.message)

  return {
    publicKey: result.publicKey,
    signature: result.signature,
  }
}

Expected behavior:

  • Inside Nimiq Pay or the simulator, the host asks the user to approve the signature.
  • Outside the host, the promise rejects after the timeout with guidance to open the app inside Nimiq Pay.

Render provider state without prompting

Reading the provider synchronously does not ask for account access. Use it for UI state before the user clicks a wallet action.

app/provider-state.ts
import {
  getMiniAppProvider,
  hasMiniAppProvider,
} from '@onmax/nimiq-mini-app-kit'

export function readMiniAppRuntimeState() {
  const provider = getMiniAppProvider()

  return {
    available: hasMiniAppProvider(),
    canSign: Boolean(provider),
  }
}

Expected result outside Nimiq Pay:

output
{
  "available": false,
  "canSign": false
}

Send a Nimiq payment with order data

Use Nimiq payment methods when the receiver expects Luna amounts. 1 NIM = 100000 Luna.

app/pay-with-nim.ts
import {
  initMiniAppProvider,
  isMiniAppProviderError,
} from '@onmax/nimiq-mini-app-kit'

interface PayOrderInput {
  orderId: string
  recipient: string
  amountLuna: number
  feeLuna?: number
}

export async function payOrder(input: PayOrderInput) {
  const provider = await initMiniAppProvider({ timeout: 10_000 })
  const txHash = await provider.sendBasicTransactionWithData({
    recipient: input.recipient,
    value: input.amountLuna,
    fee: input.feeLuna ?? 0,
    data: `order:${input.orderId}`,
  })

  if (isMiniAppProviderError(txHash))
    throw new Error(txHash.error.message)

  return txHash
}

Expected behavior:

  • The host previews the recipient, amount, fee, and attached data.
  • The function resolves to a transaction hash when the user approves.
  • The function throws a normal Error when the provider returns an error envelope.

Check read-only capabilities

Use capability checks for optional status UI. Do not block checkout only because status methods are missing.

app/network-status.ts
import {
  hasBlockNumberCapability,
  hasConsensusCapability,
  initMiniAppProvider,
} from '@onmax/nimiq-mini-app-kit'

export async function readNimiqStatus() {
  const provider = await initMiniAppProvider({ timeout: 10_000 })

  return {
    consensusEstablished: hasConsensusCapability(provider)
      ? await provider.isConsensusEstablished()
      : null,
    blockNumber: hasBlockNumberCapability(provider)
      ? await provider.getBlockNumber()
      : null,
  }
}

Use custom sources in tests

Use source when your test controls when the provider appears.

test/wait-for-provider.test.ts
import { expect, it } from 'vitest'
import { waitForMiniAppProvider } from '@onmax/nimiq-mini-app-kit'
import { createStubNimiqProvider } from '@onmax/nimiq-mini-app-kit/dev'

it('waits for delayed mini-app injection', async () => {
  let provider = null as ReturnType<typeof createStubNimiqProvider> | null

  setTimeout(() => {
    provider = createStubNimiqProvider()
  }, 10)

  await expect(waitForMiniAppProvider({
    source: () => provider,
    timeout: 100,
    intervalMs: 5,
  })).resolves.toBe(provider)
})

Runtime rules

  • Use initMiniAppProvider() for user actions that require the provider.
  • Use getMiniAppProvider() for synchronous rendering decisions.
  • Use isMiniAppProviderError() before treating provider results as successful signatures or transaction hashes.
  • Do not trigger confirmation-requiring methods during page load.
  • Do not access private keys. The host owns the wallet.
Copyright © 2026