Skip to content

Wallet API

Wallet integration.

Connect a Midnight app to 1AM Wallet for accounts, proving, transaction balancing and submission.

Quick Start

The 1AM wallet injects itself at window.midnight['1am']

1. DETECT THE WALLET

TypeScript
1function detectWallet(): Promise<InitialAPI | null> {
2  return new Promise((resolve) => {
3    const wallet = window.midnight?.['1am'];
4    if (wallet) { resolve(wallet); return; }
5
6    let attempts = 0;
7    const interval = setInterval(() => {
8      const w = window.midnight?.['1am'];
9      if (w) { clearInterval(interval); resolve(w); }
10      else if (++attempts > 50) { clearInterval(interval); resolve(null); }
11    }, 100);
12  });
13}

2. CONNECT

TypeScript
1const wallet = await detectWallet();
2if (!wallet) throw new Error('1AM wallet not installed');
3
4const connectedAPI = await wallet.connect('preview');

3. GET ADDRESSES & BALANCES

TypeScript
1const { shieldedAddress } = await connectedAPI.getShieldedAddresses();
2const { unshieldedAddress } = await connectedAPI.getUnshieldedAddress();
3const { dustAddress } = await connectedAPI.getDustAddress();
4
5const shieldedBalances = await connectedAPI.getShieldedBalances();
6const unshieldedBalances = await connectedAPI.getUnshieldedBalances();
7const { balance, cap } = await connectedAPI.getDustBalance();

4. GET NETWORK CONFIG

TypeScript
1const config = await connectedAPI.getConfiguration();
2// {
3//   networkId: 'preview',
4//   indexerUri: 'https://indexer.preview.midnight.network/api/v4/graphql',
5//   indexerWsUri: 'wss://indexer.preview.midnight.network/api/v4/graphql/ws',
6//   proverServerUri: 'https://api-preview.1am.xyz',
7//   substrateNodeUri: 'wss://rpc.preview.midnight.network',
8// }

Build Providers

Your DApp builds providers that delegate proving and transaction balancing to the wallet and its configured services.

INSTALL DEPENDENCIES

TypeScript
1npm install @midnight-ntwrk/compact-js \
2  @midnight-ntwrk/midnight-js-contracts \
3  @midnight-ntwrk/midnight-js-types \
4  @midnight-ntwrk/midnight-js-fetch-zk-config-provider \
5  @midnight-ntwrk/midnight-js-indexer-public-data-provider \
6  @midnight-ntwrk/midnight-js-network-id \
7  @midnight-ntwrk/ledger-v8

BUILD PROVIDERS

TypeScript
1import { setNetworkId } from '@midnight-ntwrk/midnight-js-network-id';
2import { FetchZkConfigProvider } from '@midnight-ntwrk/midnight-js-fetch-zk-config-provider';
3import { indexerPublicDataProvider } from '@midnight-ntwrk/midnight-js-indexer-public-data-provider';
4
5async function buildProviders(connectedAPI) {
6  const config = await connectedAPI.getConfiguration();
7  setNetworkId(config.networkId);
8
9  const zkConfigProvider = new FetchZkConfigProvider(
10    'https://your-app.com/contract/compiled/your-contract',
11    fetch.bind(window),
12  );
13
14  const publicDataProvider = indexerPublicDataProvider(
15    config.indexerUri, config.indexerWsUri,
16  );
17
18  const provingProvider = await connectedAPI.getProvingProvider(zkConfigProvider);
19  const proofProvider = {
20    async proveTx(unprovenTx) {
21      const { CostModel } = await import('@midnight-ntwrk/ledger-v8');
22      return unprovenTx.prove(provingProvider, CostModel.initialCostModel());
23    },
24  };
25
26  const shieldedAddress = await connectedAPI.getShieldedAddresses();
27  const walletProvider = {
28    getCoinPublicKey: () => shieldedAddress.shieldedCoinPublicKey,
29    getEncryptionPublicKey: () => shieldedAddress.shieldedEncryptionPublicKey,
30    async balanceTx(tx) {
31      const serialized = tx.serialize();
32      const hex = Array.from(serialized).map(b => b.toString(16).padStart(2, '0')).join('');
33      const result = await connectedAPI.balanceUnsealedTransaction(hex);
34      const { Transaction } = await import('@midnight-ntwrk/ledger-v8');
35      const bytes = new Uint8Array(result.tx.match(/.{2}/g).map(b => parseInt(b, 16)));
36      return Transaction.deserialize('signature', 'proof', 'binding', bytes);
37    },
38  };
39
40  const midnightProvider = {
41    async submitTx(tx) {
42      const serialized = tx.serialize();
43      const hex = Array.from(serialized).map(b => b.toString(16).padStart(2, '0')).join('');
44      await connectedAPI.submitTransaction(hex);
45      return tx.identifiers()[0];
46    },
47  };
48
49  return { publicDataProvider, zkConfigProvider, proofProvider, walletProvider, midnightProvider };
50}

Deploy & Call Contracts

DEPLOY A CONTRACT

TypeScript
1import { CompiledContract } from '@midnight-ntwrk/compact-js';
2import { deployContract } from '@midnight-ntwrk/midnight-js-contracts';
3import { Contract } from './your-compiled-contract';
4
5const compiledContract = CompiledContract.make('YourContract', Contract).pipe(
6  CompiledContract.withVacantWitnesses,
7  CompiledContract.withCompiledFileAssets('./contract/compiled/your-contract'),
8);
9
10const providers = await buildProviders(connectedAPI);
11const deployed = await deployContract(providers, { compiledContract });
12console.log('Contract address:', deployed.deployTxData.public.contractAddress);

CALL A CIRCUIT

TypeScript
1import { submitCallTx } from '@midnight-ntwrk/midnight-js-contracts';
2
3const result = await submitCallTx(providers, {
4  compiledContract,
5  contractAddress: '09dbe05f...',
6  circuitId: 'register',
7  args: [nameHash, 1n],
8});
9
10console.log('Tx hash:', result.public.txHash);

Transaction Flow

1

Build

DApp builds unproven tx (SDK + compiled contract)

2

Prove

DApp calls proveTx() → wallet → proof server → ZK proof generated

3

Balance

DApp calls balanceTx() → wallet → balance service, with DUST sponsorship where available

4

Submit

DApp calls submitTx() → wallet → broadcasts to Midnight chain

ProofStation can sponsor DUST on supported networks. Availability and limits depend on the service configuration.

DApp Connector API Reference

window.midnight['1am'] — InitialAPI

MethodReturnsDescription
connect(networkId)ConnectedAPIConnect to wallet
namestring'1AM'
apiVersionstringReported connector API version

ConnectedAPI

MethodReturnsDescription
getShieldedBalances()Record<string, bigint>Shielded token balances
getUnshieldedBalances()Record<string, bigint>Unshielded token balances
getDustBalance(){ cap, balance }Dust balance
getShieldedAddresses(){ shieldedAddress, ... }Shielded keys
getUnshieldedAddress(){ unshieldedAddress }Unshielded address
getDustAddress(){ dustAddress }Dust address
getConfiguration()ConfigurationNetwork URLs, proof server
balanceUnsealedTransaction(hex){ tx }Balance a proved transaction
submitTransaction(hex)voidSubmit to chain
getProvingProvider(keyProvider)ProvingProviderGet ZK proving provider
signData(data, options)SignatureSign arbitrary data
makeTransfer(outputs){ tx }Create a token transfer

Hosting ZK Keys

Your compiled contract produces prover keys, verifier keys, and ZKIR files. These must be served via HTTP with CORS enabled.

TypeScript
1your-cdn.com/contract/compiled/your-contract/
2  keys/
3    circuitName.prover      (2-10 MB each)
4    circuitName.verifier    (2 KB each)
5  zkir/
6    circuitName.bzkir       (1-3 KB each)

The FetchZkConfigProvider fetches these on demand. Host on any CDN with Access-Control-Allow-Origin: *.

Networks

NetworkIndexerRPC
previewindexer.preview.midnight.networkrpc.preview.midnight.network
preprodindexer.preprod.midnight.networkrpc.preprod.midnight.network
mainnetindexer.mainnet.midnight.networkrpc.mainnet.midnight.network

Start development on preview. Read the connected wallet's getConfiguration() for the configured endpoints, and check service availability before submitting transactions.

DUST sponsorship

Sponsored transaction fees.

ProofStation can add DUST from a funded sponsorship wallet. Availability depends on the network, service configuration and applicable limits.

TypeScript
1Your DApp → 1AM Wallet → ProofStation
2                            ↓
3                  1. Proves ZK circuits
4                  2. Adds DUST when sponsorship is available
5                  3. Returns finalized transaction
6                            ↓
7          1AM Wallet submits to Midnight chain
8
9Sponsorship depends on network and service availability.

The walletProvider.balanceTx() provider routes the transaction to ProofStation's /balance-only endpoint, where an available sponsorship wallet can add DUST.

ProofStation API

ProofStation is the proving + balancing infrastructure behind 1AM Wallet — ZK proof generation, dust sponsorship, and Cardano queries.

EndpointMethodDescription
/healthGETServer health + upstream status
/provePOSTGenerate ZK proof (native binary)
/verifyPOSTVerify a ZK proof
/prove-and-balancePOSTProve + balance an unproved TX
/balance-onlyPOSTBalance a pre-proven TX
/wallet-statusGETSponsorship wallet dust balance

Auth: X-API-Key: pk_live_xxx · 3 networks: api.1am.xyz · api-preprod.1am.xyz · api-preview.1am.xyz

List Your DApp

Submit your DApp to the 1AM app registry to appear in the wallet's Apps tab.

TypeScript
1{
2  "name": "Your DApp",
3  "description": "Short description",
4  "logo": "https://your-app.com/logo.svg",
5  "link": "https://your-app.com",
6  "chains": ["midnight"],
7  "categories": ["defi", "games", "collectibles", "social", "other"]
8}

Submit via the 1AM App Registry on GitHub or DM @oneamxyz

AI Skill for Claude Code

Install Midnight Agent Skills for guidance on wallet integration, Compact contracts and deployment workflows.

Shell
1npx skills add UvRoxx/midnight-agent-skills

What the skill teaches your AI:

Wallet Detection

Detect and connect the 1AM extension

Provider Setup

Build all 5 providers for contract ops

DUST sponsorship

Use sponsorship where available

Contract Deployment

Deploy and call Compact circuits

ZK Key Hosting

Serve prover keys from CDN

App Registry

Get listed in the 1AM wallet

Demo

Working Example

See the working example at ZKMint: a DApp that compiles a Compact contract, deploys it and calls circuits through 1AM Wallet.

View ZKMint

Support