Skip to content

Wallet API

Sign Message API.

Sign arbitrary messages for authentication, identity verification, and wallet ownership proofs. Works without wallet sync — no gas, no dust, no on-chain state needed.

Quick Start

TypeScript
1// 1. Detect wallet
2const wallet = window.midnight?.['1am'];
3
4// 2. Connect
5const api = await wallet.connect('preview');
6
7// 3. Sign a message
8const result = await api.signData('Sign in to MyApp: 1234567890', {
9  encoding: 'text',
10  keyType: 'unshielded',
11});
12
13console.log(result);
14// {
15//   data: "Sign in to MyApp: 1234567890",
16//   signature: "a1b2c3d4...",      // hex-encoded Ed25519 signature
17//   verifyingKey: "e5f6a7b8..."    // hex-encoded public key
18// }

API Reference

api.signData(data, options)— Signs arbitrary data with the wallet's unshielded key.

PARAMETERS

ParamTypeDescription
datastringThe message to sign
options.encoding'text' | 'hex' | 'base64'How data is encoded
options.keyType'unshielded'Key to sign with

RETURNS

TypeScript
1{
2  data: string;          // Original message
3  signature: string;     // Hex-encoded Ed25519 signature
4  verifyingKey: string;  // Hex-encoded public key
5}

ENCODING OPTIONS

EncodingUse CaseExample
textAuth challenges, human-readable"Sign in: abc123"
hexBinary data as hex"48656c6c6f"
base64Binary data as base64"SGVsbG8="

Authentication Flow

1

Challenge

Backend generates a random nonce

2

Sign

DApp calls api.signData(nonce, { encoding: 'text', keyType: 'unshielded' })

3

Approve

User sees wallet popup and approves the signature

4

Verify

DApp sends { signature, verifyingKey } to backend

5

Validate

Backend verifies Ed25519 signature against verifyingKey

6

Auth

User is authenticated — no gas, no sync, no seed phrase

Frontend — Prove Wallet Ownership

TypeScript
1async function authenticate(challenge: string) {
2  const wallet = window.midnight?.['1am'];
3  if (!wallet) throw new Error('1AM wallet not installed');
4
5  const api = await wallet.connect('preview');
6  const { signature, verifyingKey } = await api.signData(challenge, {
7    encoding: 'text',
8    keyType: 'unshielded',
9  });
10
11  // Send to your backend for verification
12  const response = await fetch('/api/auth/verify', {
13    method: 'POST',
14    headers: { 'Content-Type': 'application/json' },
15    body: JSON.stringify({ challenge, signature, verifyingKey }),
16  });
17
18  return response.json();
19}

Backend Verification (Node.js)

TypeScript
1import { ed25519 } from '@noble/curves/ed25519';
2
3function verifySignature(
4  challenge: string,
5  signature: string,
6  verifyingKey: string
7): boolean {
8  const messageBytes = new TextEncoder().encode(challenge);
9  const sigBytes = Buffer.from(signature, 'hex');
10  const pubKeyBytes = Buffer.from(verifyingKey, 'hex');
11
12  return ed25519.verify(sigBytes, messageBytes, pubKeyBytes);
13}

Install: npm install @noble/curves

Key Details

Algorithm

Ed25519 (same as Midnight unshielded key)

No sync required

Works immediately after wallet creation

No gas/dust

Signing is local — no transaction needed

User approval

Wallet shows signing prompt — user must approve