Guide · 60 minutes · Wallet developers
Support Digi-ID in your wallet
Wallets are where Digi-ID lives. If your wallet already holds a BIP39 seed, adding Digi-ID is four steps: parse, confirm, derive and sign, then post the callback.
The examples use digiid-core (packages/digiid-core in this site's repository), the TypeScript module that powers the demo. It's small enough to read in one sitting if you're porting to Kotlin, Swift or Rust.
1. Handle the URI
Register the digiid URL scheme so tapping a link opens your wallet, and accept the same string from your QR scanner.
import { parseUri, callbackUrlFromUri } from 'digiid-core';
const parsed = parseUri(scanned); // null if not a valid digiid:// challenge
if (!parsed) throw new Error('Not a Digi-ID request');
const callbackUrl = callbackUrlFromUri(scanned); // https://host/path (http:// only when u=1)2. Ask the user — show the domain
The confirmation screen is the user's phishing defence. Show the host prominently (for example www.example.com), not a page title the site controls.
- If
u=1is present, warn clearly that the connection is not encrypted and default to “Cancel”. - Require the same unlock you use for sending funds (PIN or biometrics).
- Never sign automatically, and never sign a URI the user didn't just scan or tap.
3. Derive the site key and sign
Each site gets its own key at m/13'/A'/B'/C'/D', derived from the callback URL. It's separate from the user's funds — don't show its address as a receiving address.
import { deriveKey, deriveAddress, signMessage } from 'digiid-core';
const key = deriveKey(seed, scanned); // seed = BIP39 seed bytes, index 0
const address = deriveAddress(key.publicKey!); // D⦠address for this site only
const signature = signMessage(scanned, key.privateKey!); // base64, DigiByte message formatSignatures use the standard DigiByte signed-message format: double SHA-256 of "\x19DigiByte Signed Message:\n" + varint(len) + uri, 65-byte compact recoverable signature with a compressed-key header, base64 encoded.
4. Post the callback
const res = await fetch(callbackUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ address, uri: scanned, signature })
});
showResult(res.ok ? 'Signed in' : `Sign-in failed (${res.status})`);Post the exact URI you signed. Show success or failure based on the HTTP status; services return 2xx on success.
Test against the published vector
With the test seed myth glimpse mystery abstract embark net faint hospital catch hint develop state and URI digiid://digiid.digibyteprojects.com/callback?x=c6140375e5bae71e, your wallet must derive DJDAkjie6nrW6RpFZSTpNUXsZ9JE2x6p1o. Paste your signature into the playground to check it verifies.
Checklist
- Derivation matches the test vector (path and address).
- The host is shown before signing;
u=1triggers a warning. - Signing requires the wallet's normal authentication.
- Restoring the same seed on another device gives the same Digi-ID addresses.
- Network errors and non-2xx responses are shown to the user.
Shipped it? Add your wallet to the ecosystem — wallets are the most-requested listing.