Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/components/docs/DocsAsideLeftBody.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const miniAppsNavigationOrder = [
'ideas',
'evm-tokens',
'localization',
'device-identifier',
'api-reference',
] as const

Expand Down
53 changes: 53 additions & 0 deletions content/mini-apps/device-identifier.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
title: Device Identifier in Mini Apps
description: Request a pseudonymous per-device handle from Nimiq Pay using requestDeviceIdentifier
icon: i-tabler:fingerprint
navigation:
title: Device Identifier
order: 9
---

# Device Identifier in Mini Apps

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.

## Requesting the identifier

Call `requestDeviceIdentifier()` with a `reason` string. The reason is shown verbatim to the user in a consent prompt the first time your origin requests it. Subsequent calls from the same origin resolve silently.

```ts
import { requestDeviceIdentifier } from '@nimiq/mini-app-sdk'

try {
const id = await requestDeviceIdentifier({ reason: 'Leaderboard ranking' })
// id: 64-char hex SHA-256, stable for this mini app on this device
}
catch (error) {
// user denied, reason was empty, or not running inside Nimiq Pay
}
```

## How the value behaves

| Property | Behaviour |
| --- | --- |
| Format | 64-character hex string (SHA-256 digest) |
| Scope | One value per (device, origin). Different mini apps on the same device receive different identifiers |
| Stability | Stable across Nimiq Pay reinstalls and across different user accounts on the same device |
| Prompts | First call per origin shows a consent prompt with your `reason`. Later calls resolve without a prompt |

The host derives the value by hashing a host-side device ID with your origin, so two mini apps cannot recognise the same device by comparing identifiers.

## What you should not use it for

The identifier is for device-scoped state, not user identity. Do not use it for authentication or as a user ID: a shared device returns the same value to every user, and the same user on two devices receives two different identifiers.

If you need a user identity, use the Nimiq provider to request the user's account address through [`listAccounts`](/mini-apps/api-reference/nimiq-provider#listaccounts).

## Error handling

`requestDeviceIdentifier()` rejects in three cases:

- **User denied the consent prompt.**
- **`reason` is empty.**
- **Not running inside Nimiq Pay.** The host API is unavailable outside the Nimiq Pay app.
12 changes: 12 additions & 0 deletions content/mini-apps/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ 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](/mini-apps/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](/mini-apps/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.
Expand Down
18 changes: 0 additions & 18 deletions content/mini-apps/localization.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,6 @@ function getLanguage() {

`navigator.language` returns a BCP 47 tag like `en-US`. The `.split('-')[0]` extracts the two-letter language code. The final fallback to `'en'` covers the case where both are unavailable.

## TypeScript type declaration

TypeScript does not know about `window.nimiqPay` by default. Add a declaration file to your project to avoid type errors:

```ts
// nimiq-pay.d.ts
declare global {
interface Window {
nimiqPay?: {
readonly language?: string
}
}
}
export {}
```

Place this file anywhere in your project's source directory. TypeScript picks it up automatically. No import needed.

## Translations without a library

For most mini apps, a plain object map is enough. No i18n library is needed.
Expand Down
Loading