Install
$ agentstack add skill-mzf11125-midnight-agent-skills-midnight-dapp-dev ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Midnight DApp Development
Overview
Midnight DApp frontend development involves building web applications that interact with the Midnight Network blockchain using TypeScript and React. This guide covers the complete workflow from project scaffolding to production deployment. The Midnight ecosystem provides several TypeScript packages that enable wallet connections, contract interactions, state management, and ZK proof generation all from within a browser or Node.js application.
The core development pattern follows a provider based architecture where each concern such as wallet connectivity, proof generation, or state management is handled by a dedicated provider. These providers are composed together using the MidnightProviders abstraction which serves as the backbone of any Midnight DApp.
Developers typically use either Vite with React 19 for single page applications or Next.js with the App Router for server rendered applications. Both approaches support the full Midnight DApp Connector API for wallet integration.
Project Scaffolding Patterns
Vite Plus React 19 Plus shadcn/ui
The recommended Vite scaffolding pattern combines React 19 with TypeScript and shadcn/ui for building Midnight DApps. Start by creating a Vite project with React and TypeScript support.
npm create vite@latest my-midnight-dapp -- --template react-ts
cd my-midnight-dapp
npm install
Add the Midnight dependencies needed for a standard DApp frontend. The core packages include the DApp Connector for wallet integration and the various providers for state management and contract interaction.
npm install @midnight-ntwrk/dapp-connector-api
npm install @midnight-ntwrk/onchain-rpc-provider
npm install @midnight-ntwrk/midnight-js-types
npm install @midnight-ntwrk/midnight-js-contracts
npm install @midnight-ntwrk/midnight-js-level-private-state-provider
npm install @midnight-ntwrk/midnight-js-network-id
npm install @midnight-ntwrk/midnight-js-fetch-zk-config-provider
npm install @midnight-ntwrk/midnight-js-http-client-proof-provider
Install shadcn/ui following the standard CLI initialization. This requires tailwindcss and its associated configuration.
npx shadcn@latest init
npx shadcn@latest add button card input toast dialog
The project structure for a Midnight DApp should organize concerns clearly. Create directories for components, hooks, providers, contracts, and utilities.
src/
components/
wallet/
ConnectButton.tsx
WalletStatus.tsx
BalanceDisplay.tsx
contract/
ContractForm.tsx
TransactionResult.tsx
layout/
AppLayout.tsx
Header.tsx
hooks/
useWallet.ts
useContract.ts
useMidnightProviders.ts
providers/
MidnightProviders.tsx
wallet.ts
proof.ts
state.ts
contracts/
types.ts
interaction.ts
lib/
midnight.ts
utils.ts
App.tsx
main.tsx
Next.js Wallet Connector
Next.js projects use the App Router pattern for Midnight DApp development. Create a Next.js application with TypeScript and the App Router enabled.
npx create-next-app@latest my-midnight-dapp --typescript --tailwind --app
cd my-midnight-dapp
Install the Midnight dependencies alongside the standard Next.js packages.
npm install @midnight-ntwrk/dapp-connector-api
npm install @midnight-ntwrk/midnight-js-types
npm install @midnight-ntwrk/midnight-js-contracts
npm install @midnight-ntwrk/midnight-js-level-private-state-provider
npm install @midnight-ntwrk/midnight-js-network-id
npm install @midnight-ntwrk/midnight-js-fetch-zk-config-provider
npm install @midnight-ntwrk/midnight-js-http-client-proof-provider
The App Router pattern for Midnight DApps requires careful handling of client side only components. The wallet connector and all blockchain interactions must run in the browser since they depend on the window.midnight API. Use the 'use client' directive at the top of any file that interacts with the Midnight provider stack.
For the layout pattern create a root layout with metadata and a client side provider wrapper. The providers must be initialized in a client component and wrap the application at the layout level.
src/
app/
layout.tsx
page.tsx
providers.tsx
components/
wallet/
ConnectButton.tsx
WalletStatus.tsx
contract/
ContractForm.tsx
TransactionResult.tsx
ui/
Button.tsx
Card.tsx
Input.tsx
hooks/
useWallet.ts
useContract.ts
lib/
midnight.ts
providers.ts
React Wallet Connector With Vite
For projects that do not need Next.js features a simpler Vite plus React setup provides a lightweight alternative. This is suitable for single page DApps that do not require server side rendering.
npm create vite@latest my-midnight-dapp -- --template react-ts
cd my-midnight-dapp
npm install
npm install @midnight-ntwrk/dapp-connector-api @midnight-ntwrk/midnight-js-types
Wallet connection in a Vite React app follows the same DApp Connector API patterns. The initialization code checks for the window.midnight object and uses the connector API to establish a connection.
import { useEffect, useState } from 'react';
import {
type ConnectedAPI,
type ConnectionStatus,
DAppConnectorAPI
} from '@midnight-ntwrk/dapp-connector-api';
function useMidnightWallet() {
const [api, setApi] = useState(null);
const [status, setStatus] = useState('disconnected');
useEffect(() => {
const midnight = window.midnight;
if (!midnight) {
setStatus('unavailable');
return;
}
const connector = new DAppConnectorAPI(midnight);
connector.connect().then((connectedApi) => {
setApi(connectedApi);
setStatus('connected');
});
return () => {
connector.disconnect();
};
}, []);
return { api, status };
}
Provider Architecture
MidnightProviders
The MidnightProviders abstraction is the central composition point for all provider services in a Midnight DApp. It combines the wallet provider, proof provider, public data provider, private state provider, and ZK config provider into a single interface that contracts consume.
The MidnightProviders type is generic over three parameters. The first parameter is the public state type which varies per contract. The second parameter is the wallet provider type. The third parameter is the private state type which can be void if the contract has no private state.
type MidnightProviders = {
readonly publicDataProvider: PublicDataProvider;
readonly privateStateProvider: PrivateStateProvider;
readonly walletProvider: W;
readonly zkConfigProvider: ZKConfigProvider;
};
Building a MidnightProviders instance involves initializing each provider component and composing them together. The wallet provider comes from the DApp Connector connection. The public data provider wraps the indexer GraphQL endpoint. The private state provider manages encrypted local storage. The ZK config provider fetches circuit configuration from the network.
async function buildProviders(walletAPI: ConnectedAPI): Promise> {
const walletProvider = new WalletProviderAdapter(walletAPI);
const publicDataProvider = new IndexerPublicDataProvider(indexerUri);
const privateStateProvider = await LevelPrivateStateProvider.create({
privateStateStoreName: 'my-dapp-state'
});
const zkConfigProvider = new FetchZkConfigProvider(
walletAPI.zkConfigUri,
fetch
);
return {
publicDataProvider,
privateStateProvider,
walletProvider,
zkConfigProvider
};
}
Proof Provider
The proof provider handles zero knowledge proof generation for contract calls. There are two primary proof provider implementations available to DApp developers.
The DApp Connector Proof Provider relies on the browser wallet extension to generate proofs client side. This is the standard approach for end user applications where the wallet handles proving transparently.
const proofProvider = new DAppConnectorProofProvider(connectedAPI);
The HTTP Client Proof Provider sends proving requests to a remote proof server. This is useful for server side proving or when the wallet does not support a particular proving scheme.
const proofProvider = new HttpClientProofProvider(
'https://proof-server.example.com',
fetch
);
Public Data Provider
The public data provider serves as the read interface to the Midnight blockchain. It wraps the GraphQL indexer API and provides typed access to contract state, transactions, and block data. All public state queries flow through this provider.
const publicDataProvider = new IndexerPublicDataProvider(
'https://indexer.preview.midnight.network/api/v1/graphql',
{ contractAddress }
);
Private State Provider
The private state provider uses level based encrypted local storage to persist sensitive contract state that must remain hidden from the public ledger. It supports password rotation for key updates and multiple crypto backends for flexibility.
const privateStateProvider = await LevelPrivateStateProvider.create({
privateStateStoreName: 'my-app-private-state'
});
Wallet Provider
The wallet provider wraps the DApp Connector connection and exposes wallet operations such as token transfers, balance queries, and key material access. It serves as the bridge between the DApp and the user's wallet.
ZK Config Provider
The ZK config provider fetches zero knowledge circuit configuration from the network. This configuration includes circuit parameters, proof types, and verification keys needed for proof generation and verification.
const zkConfigProvider = new FetchZkConfigProvider(
zkConfigUri,
fetch
);
Wallet Integration
DApp Connector API v4.0.1
The DApp Connector API is the standard interface for DApps to interact with Midnight wallets. It is accessed through the window.midnight global object which is injected by wallet browser extensions such as 1AM and Lace.
The DApp Connector API provides methods for connecting to a wallet, disconnecting, requesting authorization, and accessing the connected wallet interface. The connected wallet interface exposes methods for contract deployment, contract calls, token operations, and key material access.
const midnight = window.midnight;
if (!midnight) {
throw new Error('No Midnight wallet extension detected');
}
const initialApi = await midnight.connect();
const connectedApi = await initialApi.requestAuthorization({
networkId: NetworkId.Preprod
});
The connection status can be one of several states including 'disconnected', 'connecting', 'connected', or 'unavailable'. DApps should monitor the connection status and update their UI accordingly.
Connect and Disconnect
Connecting to a wallet is an asynchronous operation that may require user approval. The connect method returns an initial API object that has not yet been authorized for network access.
async function connectWallet(): Promise {
const midnight = window.midnight;
const initialApi = await midnight.connect();
const connectedApi = await initialApi.requestAuthorization();
return connectedApi;
}
Disconnecting releases the wallet connection and clears any stored state on the DApp side. The wallet remains available for reconnection.
async function disconnectWallet(api: ConnectedAPI): Promise {
await api.disconnect();
}
Request Authorization
The request authorization step is where the DApp asks the user to approve network access. This step may present a wallet dialog to the user showing the requested network and permissions.
const connectedApi = await initialApi.requestAuthorization({
networkId: NetworkId.Preprod
});
DApp Connector Types
Configuration
The Configuration type defines the settings for a DApp Connector instance. It includes the network identifier and optional proving server configuration.
type Configuration = {
readonly networkId: NetworkId;
};
ConnectionStatus
The ConnectionStatus type tracks the current state of the wallet connection. It is a union of string literal types representing each possible connection state.
type ConnectionStatus =
| 'disconnected'
| 'connecting'
| 'connected'
| 'disconnecting'
| 'unavailable';
ConnectedAPI
The ConnectedAPI interface represents a fully authorized wallet connection. It exposes all methods needed for contract deployment, contract calls, token operations, and provider access.
interface ConnectedAPI {
readonly deployContract: (args: DeployArgs) => Promise;
readonly submitCallTx: (args: CallTxArgs) => Promise;
readonly getBalances: () => Promise;
readonly getUtxos: () => Promise;
readonly disconnect: () => Promise;
readonly networkId: NetworkId;
readonly walletAddress: string;
readonly proveTransaction: (tx: UnprovenTransaction) => Promise;
readonly waitForTxFinalization: (txHash: string) => Promise;
}
InitialAPI
The InitialAPI is returned from the connect call before authorization. It provides a limited interface for requesting authorization and checking connection state.
interface InitialAPI {
readonly requestAuthorization: (config?: Configuration) => Promise;
readonly connectionStatus: ConnectionStatus;
}
WalletConnectedAPI
The WalletConnectedAPI extends ConnectedAPI with wallet specific operations such as key material access and signing.
interface WalletConnectedAPI extends ConnectedAPI {
readonly keyMaterialProvider: KeyMaterialProvider;
readonly provingProvider: ProvingProvider;
}
KeyMaterialProvider
The KeyMaterialProvider gives DApps access to the wallet key material without exposing raw private keys. It provides derived keys for specific purposes such as encryption or signing.
interface KeyMaterialProvider {
readonly getEncryptionPublicKey: () => Promise;
readonly getSigningPublicKey: () => Promise;
readonly signData: (data: Uint8Array) => Promise;
}
ProvingProvider
The ProvingProvider handles zero knowledge proof generation using the wallet key material. It takes an unproven transaction and returns a proven transaction ready for submission.
interface ProvingProvider {
readonly proveTransaction: (
tx: UnprovenTransaction,
zkConfig: ZkConfig
) => Promise;
}
Transaction Flow
Creating an Unproven Transaction
An unproven transaction contains all the public inputs and circuit context needed for a contract call but lacks the zero knowledge proof. It is created using the contract type definitions and the provider stack.
const unprovenTx = await contractInterface.createUnprovenCallTx(
providers,
'increment'
);
Proving the Transaction
Proving generates the zero knowledge proof that attests to the validity of the transaction without revealing private inputs. The proof provider handles this step using either the browser wallet or a remote proof server.
const provenTx = await contractInterface.proveCallTx(
providers,
unprovenTx
);
Submitting the Transaction
Submission sends the proven transaction to the Midnight network. The transaction is broadcast to the mempool and included in a forthcoming block.
const txHash = await contractInterface.submitCallTx(
providers,
provenTx
);
Waiting for Finalization
After submission the DApp should wait for the transaction to be finalized. Finalization means the transaction has been included in a block and is considered irreversible.
const result = await contractInterface.waitForCallTxFinalization(
providers,
txHash
);
Handling Transaction Results
Transaction re
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mzf11125
- Source: mzf11125/midnightagent_skills
- License: MIT
- Homepage: https://github.com/mzf11125/midnightagentskills#readme
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.