Build DApps on Midnight Network with dust-free execution using the 1AM Wallet and ProofStation. Use when: (1) building Midnight DApps that need wallet integration, (2) deploying or calling Compact smart contracts, (3) implementing dust-free/gasless transaction sponsorship, (4) working with @midnight-ntwrk SDK packages, (5) setting up ZK proving infrastructure, (6) connecting to the 1AM browser extension via DApp Connector API. Covers wallet detection, provider setup, ZK proving, dust sponsorship, contract deployment, and DApp listing.
Build Midnight Network DApps where users pay zero gas fees.
DApp → 1AM Wallet Extension → ProofStation (Hetzner ARM64)
├── /prove, /check → Native binary (ZK proofs)
└── /balance-only → Balance service (adds dust)
npm install @midnight-ntwrk/compact-js \
@midnight-ntwrk/midnight-js-contracts \
@midnight-ntwrk/midnight-js-types \
@midnight-ntwrk/midnight-js-fetch-zk-config-provider \
@midnight-ntwrk/midnight-js-indexer-public-data-provider \
@midnight-ntwrk/midnight-js-network-id \
@midnight-ntwrk/ledger-v8
// Detect 1AM wallet (registers at window.midnight['1am'])
const wallet = window.midnight?.['1am'];
if (!wallet) throw new Error('Install 1AM wallet extension');
// Connect to preview network
const api = await wallet.connect('preview');
// Get network config
const config = await api.getConfiguration();
// Returns: { networkId, indexerUri, indexerWsUri, proverServerUri, substrateNodeUri }
import { setNetworkId } from '@midnight-ntwrk/midnight-js-network-id';
import { FetchZkConfigProvider } from '@midnight-ntwrk/midnight-js-fetch-zk-config-provider';
import { indexerPublicDataProvider } from '@midnight-ntwrk/midnight-js-indexer-public-data-provider';
setNetworkId(config.networkId);
// ZK keys from your CDN
const zkConfigProvider = new FetchZkConfigProvider(
'https://your-cdn.com/contract/compiled/your-contract',
fetch.bind(window),
);
// On-chain state
const publicDataProvider = indexerPublicDataProvider(config.indexerUri, config.indexerWsUri);
// Proof provider — wallet routes to ProofStation native binary
const provingProvider = await api.getProvingProvider(zkConfigProvider);
const proofProvider = {
async proveTx(unprovenTx) {
const { CostModel } = await import('@midnight-ntwrk/ledger-v8');
return unprovenTx.prove(provingProvider, CostModel.initialCostModel());
},
};
// Wallet provider — ProofStation sponsors dust fees (user pays nothing)
const shieldedAddr = await api.getShieldedAddresses();
const walletProvider = {
getCoinPublicKey: () => shieldedAddr.shieldedCoinPublicKey,
getEncryptionPublicKey: () => shieldedAddr.shieldedEncryptionPublicKey,
async balanceTx(tx) {
const hex = toHex(tx.serialize());
const result = await api.balanceUnsealedTransaction(hex);
const { Transaction } = await import('@midnight-ntwrk/ledger-v8');
return Transaction.deserialize('signature', 'proof', 'binding', fromHex(result.tx));
},
};
// Submit provider
const midnightProvider = {
async submitTx(tx) {
await api.submitTransaction(toHex(tx.serialize()));
return tx.identifiers()[0];
},
};
import { deployContract, submitCallTx } from '@midnight-ntwrk/midnight-js-contracts';
import { CompiledContract } from '@midnight-ntwrk/compact-js';
const compiled = CompiledContract.make('MyContract', ContractClass).pipe(
CompiledContract.withVacantWitnesses,
CompiledContract.withCompiledFileAssets('./contract/compiled/my-contract'),
);
// Deploy — user pays nothing
const deployed = await deployContract(providers, { compiledContract: compiled });
const address = deployed.deployTxData.public.contractAddress;
// Call circuit — user pays nothing
const result = await submitCallTx(providers, {
compiledContract: compiled,
contractAddress: address,
circuitId: 'myCircuit',
args: [arg1, arg2],
});
proofProvider.proveTx() → wallet → ProofStation /check + /prove → ZK proof (~2-5s)walletProvider.balanceTx() → wallet → ProofStation /balance-only → server adds dustmidnightProvider.submitTx() → wallet broadcasts to chain → tx hash returnedfunction toHex(bytes: Uint8Array): string {
return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
}
function fromHex(hex: string): Uint8Array {
return new Uint8Array(hex.match(/.{2}/g)!.map(b => parseInt(b, 16)));
}
| Network | Status | Proof Server |
|---|---|---|
| preview | Live | https://api-preview.1am.xyz |
| preprod | Live | https://api-preprod.1am.xyz |
ZKMint Night-ID at zkmint.1am.xyz — full dust-free minting. Source: midnight-launchpad/lib/midnight/night-id-contract.ts