Utilities

Universal Nimiq facade

Use @onmax/unimiq across browser, Nuxt, Vite, Node.js, Workers, and tests.

Use @onmax/unimiq when you want one Nimiq API surface for account reads, balances, network summaries, local wallets, and basic sends across app runtimes.

Do not use it when you need a full wallet UI, fiat checkout policy, token registries, or consensus-client control in Node.js. Node.js and Cloudflare Workers require an RPC URL.

Choose the runtime path

Use createNimiq() directly in shared TypeScript. In browsers it uses the web-client driver. In Node.js and Workers it uses the RPC driver and fails unless rpc.url is set.

app/nimiq.ts
import { createNimiq } from '@onmax/unimiq'

export const nimiq = createNimiq({
  network: 'test',
  rpc: {
    url: 'https://history1.pos.nimiq-testnet.com:8648',
  },
})

await nimiq.ready()

const network = await nimiq.network()

console.log(network.driver, network.headHeight)

Expected behavior:

output
rpc 1234567

The exact height changes. The driver should be rpc in Node.js and Workers, and web-client in a browser without a custom driver.

Send with a local wallet

Use the facade wallet helpers for local test wallets, server-side signing jobs, or scripts where the private key stays inside your process.

scripts/send-nim.ts
import { createNimiq } from '@onmax/unimiq'

const nimiq = createNimiq({
  network: 'test',
  rpc: { url: process.env.NIMIQ_RPC_URL! },
})

const sender = await nimiq.wallet.importPrivateKey(process.env.NIMIQ_PRIVATE_KEY_HEX!)
const recipient = 'NQ51 PF64 3FPJ 86JE RCTP 5R7F 0BR5 U41V ELP6'
const network = await nimiq.network()

const transaction = await nimiq.send({
  from: sender,
  to: recipient,
  value: 1_000_000n,
  fee: 0n,
  validityStartHeight: network.headHeight ?? 0,
})

console.log(transaction.hash)
await nimiq.destroy()

Expected behavior:

output
<transaction hash>

Use bigint for Luna values. 1_000_000n is 10 NIM.

Test without the network

Use @onmax/unimiq/mock when unit tests should verify app behavior without RPC, consensus, or browser APIs.

test/nimiq-payment.test.ts
import { describe, expect, it } from 'vitest'
import { createNimiq } from '@onmax/unimiq'
import { createMockNimiqDriver } from '@onmax/unimiq/mock'

describe('payment flow', () => {
  it('moves mock balances and stores the transaction', async () => {
    const nimiq = createNimiq({
      driver: createMockNimiqDriver({
        headHeight: 42,
        accounts: {
          sender: { balance: 5_000_000n },
        },
      }),
    })

    const transaction = await nimiq.send({
      from: {
        kind: 'local',
        address: 'sender',
        privateKeyHex: '00',
        publicKeyHex: '11',
      },
      to: 'recipient',
      value: 1_000_000n,
    })

    expect(transaction).toMatchObject({
      hash: 'mock-43',
      sender: 'sender',
      recipient: 'recipient',
      value: 1_000_000n,
    })
    expect(await nimiq.balance('sender')).toBe(4_000_000n)
    expect(await nimiq.balance('recipient')).toBe(1_000_000n)
    expect(await nimiq.transaction(transaction.hash)).toMatchObject({ hash: 'mock-43' })
  })
})

Use mock-driver tests for business logic. Do not use them to prove RPC compatibility, browser bundling, or wallet-host behavior.

Configure Vite

Use the Vite plugin when a Vite app imports @onmax/unimiq directly. The plugin configures wasm and top-level await handling around @nimiq/core.

vite.config.ts
import { defineConfig } from 'vite'
import Unimiq from '@onmax/unimiq/vite'

export default defineConfig({
  plugins: [Unimiq()],
})

Configure Nuxt

Use the Nuxt module when a Nuxt app should inject one facade and auto-import useNimiq() and useNimiqNetwork().

nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@onmax/unimiq/nuxt'],
  unimiq: {
    network: 'test',
    rpcUrl: process.env.NIMIQ_RPC_URL,
    autoConnect: false,
  },
})
app/components/Balance.vue
<script setup lang="ts">
const nimiq = useNimiq()
const network = useNimiqNetwork({ refreshIntervalMs: 15_000 })
const address = 'NQ51 PF64 3FPJ 86JE RCTP 5R7F 0BR5 U41V ELP6'
const balance = await nimiq.balance(address)
</script>

<template>
  <NimiqAddressPill :address="address" format="full" />
  <output>{{ balance }}</output>
</template>

Use @onmax/nimiq-mini-app-kit/nuxt separately when the app also needs local mini-app simulator behavior.

Render Vue account UI

Use the Vue subpath for small address and identicon components. These components are display helpers; they do not fetch balances or connect wallets.

components/AccountBadge.vue
<script setup lang="ts">
import { NimiqAccount, NimiqAddress, NimiqIdenticon } from '@onmax/unimiq/vue'

const address = 'NQ51 PF64 3FPJ 86JE RCTP 5R7F 0BR5 U41V ELP6'
</script>

<template>
  <NimiqAccount :address="address" display="identicon" />
  <NimiqIdenticon :address="address" />
  <NimiqAddress :address="address" />
</template>

Use focused crypto helpers

Use the root crypto exports when you need deterministic Nimiq message signing, address derivation, or transaction hex construction outside the facade.

scripts/sign-message.ts
import {
  deriveAddressFromPrivateKeyHex,
  signNimiqMessage,
  verifyNimiqSignedMessage,
} from '@onmax/unimiq'

const privateKeyHex = process.env.NIMIQ_PRIVATE_KEY_HEX!
const message = 'Authorize payout batch 42'
const signed = signNimiqMessage({ message, privateKeyHex })

console.log(deriveAddressFromPrivateKeyHex(privateKeyHex))
console.log(verifyNimiqSignedMessage({
  message,
  publicKeyHex: signed.publicKeyHex,
  signatureHex: signed.signatureHex,
}))

Expected behavior:

output
NQ...
true
Copyright © 2026