Host runtime
Use @onmax/nimiq-mini-app-kit/host-runtime when you build a custom local host shell and own both sides of the simulated Nimiq Pay bridge.
Do not use this subpath inside a normal mini app that only needs window.nimiq or window.ethereum. Use the root package or the Nuxt module instead.
Choose host-runtime over dev helpers
Use host-runtime when the host window needs to:
- create launch payloads for a mini-app window,
- validate mini-app-to-host messages,
- fulfill Nimiq and Ethereum approval requests,
- track wallet balance and transaction history,
- send provider responses back to the mini-app window.
Use @onmax/nimiq-mini-app-kit/dev when you only need to install simulated providers in the current app window.
Open a mini app with launch state
The launch payload is serialized into window.name. The mini app consumes it during bootstrap.
import {
createSimulatedHostRuntime,
serializeSimulatedHostLaunchPayload,
} from '@onmax/nimiq-mini-app-kit/host-runtime'
const runtime = createSimulatedHostRuntime({
provider: {
privateKeyHex: '4f4e9c6d93fab8a1716dd2136bfdcf8bc6bfcb7e5fcb868f1f8f1eb8bbf4d2f0',
},
wallet: {
balanceLuna: 20_000,
},
ethereum: {
account: '0xf5d7f7c63cb8F6d9Db7D2674bfaB3F5D2aED2fcb',
chainId: '0x89',
},
})
export function openMiniApp(appUrl: string) {
const payload = runtime.createLaunchPayload({
hostOrigin: window.location.origin,
})
return window.open(appUrl, 'nimiq-pay-mini-app', serializeSimulatedHostLaunchPayload(payload))
}
Expected behavior:
- The opened window receives the host origin and initial wallet state.
bootstrapMiniAppProvider()can create bridge providers from that launch payload.- The payload is not a production transport. It is simulator state.
Consume a launch payload in a custom app bootstrap
Use this only when you are not using bootstrapMiniAppProvider() or the Nuxt module.
import { consumeSimulatedHostLaunchPayload } from '@onmax/nimiq-mini-app-kit/host-runtime'
export function readSimulatorLaunch() {
const launch = consumeSimulatedHostLaunchPayload()
if (!launch)
return null
return {
hostOrigin: launch.hostOrigin,
balanceLuna: launch.state.wallet.balanceLuna,
ethereumChainId: launch.state.ethereum.providerConfig.chainId,
}
}
Expected behavior:
- The first call returns the parsed launch payload.
- The helper clears
window.nameafter consuming the payload. - Later calls return
nullunless a new payload is provided.
Fulfill Nimiq approval requests
Use runtime fulfillment when your host shell receives a provider-request message and the user approves it.
import {
createSimulatedHostRuntime,
createSimulatedProviderResponseMessage,
} from '@onmax/nimiq-mini-app-kit/host-runtime'
import type { SimulatedProviderRequest } from '@onmax/nimiq-mini-app-kit/dev'
const runtime = createSimulatedHostRuntime({
provider: {
privateKeyHex: '4f4e9c6d93fab8a1716dd2136bfdcf8bc6bfcb7e5fcb868f1f8f1eb8bbf4d2f0',
},
wallet: {
balanceLuna: 20_000,
},
})
export async function approveNimiqRequest(request: SimulatedProviderRequest) {
const response = await runtime.fulfillProviderRequest(request)
return {
message: createSimulatedProviderResponseMessage(response),
wallet: runtime.getState().wallet,
}
}
Expected behavior after approving a send-basic-transaction-with-data request for 5000 Luna with a 100 Luna fee:
{
"balanceLuna": 14900,
"transactions": [
{
"kind": "wallet-transaction",
"method": "send-basic-transaction-with-data",
"amountLuna": 5000,
"balanceDeltaLuna": -5100,
"feeLuna": 100,
"status": "approved"
}
]
}
Fulfill Ethereum approval requests
Use Ethereum fulfillment for account, sign, chain, and transaction approvals.
import {
createSimulatedEthereumProviderResponseMessage,
createSimulatedHostRuntime,
} from '@onmax/nimiq-mini-app-kit/host-runtime'
import type { SimulatedEthereumProviderRequest } from '@onmax/nimiq-mini-app-kit/dev'
const runtime = createSimulatedHostRuntime({
ethereum: {
account: '0xf5d7f7c63cb8F6d9Db7D2674bfaB3F5D2aED2fcb',
chainId: '0x89',
},
})
export async function approveEthereumRequest(request: SimulatedEthereumProviderRequest) {
const response = await runtime.fulfillEthereumProviderRequest(request)
return createSimulatedEthereumProviderResponseMessage(response)
}
Expected behavior:
eth_requestAccountsreturns the configured account.wallet_addEthereumChainrecords the added chain.wallet_switchEthereumChainupdatesruntime.getState().ethereum.providerConfig.chainId.- Rejected Ethereum requests should be returned as Ethereum-shaped errors with an optional
code.
Validate bridge messages
Use the guards before trusting postMessage data from a mini-app window.
import {
isSimulatedHostToMiniAppMessage,
isSimulatedMiniAppToHostMessage,
} from '@onmax/nimiq-mini-app-kit/host-runtime'
export function classifyMessage(data: unknown) {
if (isSimulatedMiniAppToHostMessage(data))
return `mini-app:${data.type}`
if (isSimulatedHostToMiniAppMessage(data))
return `host:${data.type}`
return 'unknown'
}
Expected examples:
mini-app:provider-request
mini-app:ethereum-provider-request
host:provider-response
unknown
Runtime rules
- Use exact
event.originchecks aroundpostMessage. - Use runtime fulfillment after your host UI records an approval decision.
- Use
createSimulatedProviderResponseMessage()andcreateSimulatedEthereumProviderResponseMessage()to send successful responses. - Use the exported error response factories when the host rejects a request.
- Do not use host-runtime as a production wallet protocol.