dapp-sdd:implement
Use when executing implementation tasks with commits after each task and reviews after each phase.
Use when calling deployed Midnight contracts from Node.js backends, querying contract state, executing state-changing transactions, building API endpoints that interact with contracts, or automating contract interactions.
Full skill instructions
Interact with deployed Midnight contracts from Node.js backends, including read-only queries and state-changing transactions with proof generation.
| Type | Proof Required | State Change | Gas Cost | Use Case |
|---|---|---|---|---|
| Read-only query | No | No | None | Fetching current state |
| State change | Yes | Yes | Variable | Updating ledger state |
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Your Code │────▶│ Contract │────▶│ Prover │
│ │ │ Client │ │ Service │
└─────────────┘ └──────────────┘ └─────────────┘
│
▼
┌──────────────┐ ┌─────────────┐
│ Indexer │────▶│ Midnight │
│ Client │ │ Network │
└──────────────┘ └─────────────┘
Compact contracts define circuits that can be invoked:
// Read-only circuit - no proof needed
circuit get_balance(address: Address): Uint {
return ledger.balances[address];
}
// State-changing circuit - requires proof
circuit transfer(to: Address, amount: Uint): Void {
// Generates proof, updates ledger
ledger.balances[sender] -= amount;
ledger.balances[to] += amount;
}
| Document | Description |
|---|---|
| api-client-setup.md | SDK initialization and wallet connection |
| error-handling.md | Error types, retries, and timeout handling |
| Example | Description |
|---|---|
| read-query/ | Query contract state without proofs |
| state-change/ | Execute state-changing transactions |
import { connectContract } from '@midnight-ntwrk/midnight-js-contracts';
import { createWallet } from '@midnight-ntwrk/midnight-js-wallet';
import { Contract } from './build/contract.cjs';
const wallet = await createWallet({ seed: process.env.WALLET_SEED! });
const contract = await connectContract({
address: '0x1234...', // Deployed contract address
artifact: Contract,
wallet,
config: {
indexer: 'https://indexer.testnet.midnight.network',
indexerWs: 'wss://indexer.testnet.midnight.network/ws',
prover: 'https://prover.testnet.midnight.network',
},
});
// Call read-only circuit (no proof generation)
const balance = await contract.query.get_balance({
address: '0xabc...',
});
console.log('Balance:', balance);
// Call state-changing circuit (generates proof)
const result = await contract.call.transfer({
to: '0xdef...',
amount: 100n,
});
// Wait for confirmation
const confirmed = await result.waitForConfirmation();
console.log('Transfer confirmed:', confirmed.txHash);
import { connectContract } from '@midnight-ntwrk/midnight-js-contracts';
import type { ContractMethods, ContractState } from './build/contract.d.cts';
class TokenClient {
private contract: ConnectedContract<ContractState, ContractMethods>;
static async connect(
address: string,
wallet: Wallet,
config: NetworkConfig
): Promise<TokenClient> {
const client = new TokenClient();
client.contract = await connectContract({
address,
artifact: Contract,
wallet,
config,
});
return client;
}
async getBalance(address: string): Promise<bigint> {
return this.contract.query.get_balance({ address });
}
async transfer(to: string, amount: bigint): Promise<TransactionResult> {
const result = await this.contract.call.transfer({ to, amount });
return result.waitForConfirmation();
}
}
async function batchGetBalances(
contract: ConnectedContract,
addresses: string[]
): Promise<Map<string, bigint>> {
const results = new Map<string, bigint>();
// Run queries in parallel
const balances = await Promise.all(
addresses.map((addr) =>
contract.query.get_balance({ address: addr })
.then((balance) => ({ addr, balance }))
)
);
for (const { addr, balance } of balances) {
results.set(addr, balance);
}
return results;
}
interface TransactionOptions {
timeout?: number;
confirmations?: number;
onProofProgress?: (progress: number) => void;
}
async function executeTransaction<T>(
callFn: () => Promise<PendingTransaction<T>>,
options: TransactionOptions = {}
): Promise<ConfirmedTransaction<T>> {
const { timeout = 120000, confirmations = 1, onProofProgress } = options;
const pending = await callFn();
// Monitor proof generation progress
if (onProofProgress) {
pending.onProgress(onProofProgress);
}
const result = await pending.waitForConfirmation({
timeout,
confirmations,
});
if (result.status !== 'confirmed') {
throw new Error(`Transaction failed: ${result.error || 'timeout'}`);
}
return result;
}
// Usage
const result = await executeTransaction(
() => contract.call.transfer({ to: recipient, amount: 100n }),
{
timeout: 180000,
onProofProgress: (p) => console.log(`Proof: ${(p * 100).toFixed(0)}%`),
}
);
// For circuits with private witness data
const result = await contract.call.private_transfer({
to: recipient,
amount: 100n,
// Private inputs are handled by the SDK
// They never leave your backend
});
Common errors when calling contracts:
| Error | Cause | Solution |
|---|---|---|
Contract not found | Invalid address | Verify contract address |
Proof generation failed | Invalid witness | Check circuit inputs |
Insufficient balance | Low DUST | Fund wallet |
Circuit execution failed | Assertion violated | Review circuit logic |
Timeout | Slow network/prover | Increase timeout |
See error-handling.md for detailed error recovery strategies.
contract-deployment - Deploying contracts before callinglifecycle-management - Managing contract statemidnight-proofs plugin - Server-side proof optimization/midnight:check - Verify environment is configuredUse when executing implementation tasks with commits after each task and reviews after each phase.
Use when starting a new Midnight project, cloning example contracts (counter, tokens, NFTs, DEX), scaffolding from OpenZeppelin templates, or bootstrapping a Compact contract development environment with working starter code.
Use when caching ZK proofs for performance, implementing proof cache invalidation, storing verification results, caching intermediate proof components, or building distributed proof caches with Redis.
Use when setting up CI/CD for Midnight projects, configuring GitHub Actions for Compact contract compilation, running TypeScript tests in CI, validating version consistency, or automating contract builds.
Use when building witness data for ZK proofs, showing proof generation progress to users, implementing disclosure consent flows, handling proof timeouts and retries, or explaining privacy guarantees.
Use when implementing any Midnight example dApp to ensure compliance with quality standards and project conventions.
Use when implementing witness functions in TypeScript, mapping Compact types to TypeScript (Field→bigint, Bytes→Uint8Array), deploying contracts, calling circuits from TypeScript, reading ledger state, or building Midnight DApps with the JavaScript SDK.
Use when reading public ledger state, implementing reactive UI that updates with chain state, caching state for performance, or understanding public vs private state in Midnight DApps.
Use when optimizing prover performance, reducing proof generation memory usage, configuring prover infrastructure in Docker or Kubernetes, implementing parallel proof generation, or diagnosing prover bottlenecks.
Use when creating a phased implementation plan from a specification, with review gates after each phase.
Use when expanding a README-based dApp description into a full specification with user stories and acceptance criteria.
Use when reviewing Compact contracts for idiomatic patterns, learning recommended practices, or identifying common mistakes to avoid in Midnight smart contract development.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience