Skip to content
midnight-tooling:contract-calling logo

midnight-tooling:contract-calling

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.

SKILL.md

Full skill instructions

Contract Calling

Interact with deployed Midnight contracts from Node.js backends, including read-only queries and state-changing transactions with proof generation.

When to Use

  • Querying contract state from a backend service
  • Executing state-changing transactions
  • Building API endpoints that interact with contracts
  • Automating contract interactions in scripts
  • Testing contract behavior programmatically

Key Concepts

Call Types

TypeProof RequiredState ChangeGas CostUse Case
Read-only queryNoNoNoneFetching current state
State changeYesYesVariableUpdating ledger state

Contract Client Architecture

┌─────────────┐     ┌──────────────┐     ┌─────────────┐
│  Your Code  │────▶│   Contract   │────▶│   Prover    │
│             │     │    Client    │     │   Service   │
└─────────────┘     └──────────────┘     └─────────────┘
                           │
                           ▼
                    ┌──────────────┐     ┌─────────────┐
                    │   Indexer    │────▶│  Midnight   │
                    │    Client    │     │   Network   │
                    └──────────────┘     └─────────────┘

Circuit Types in Compact

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;
}

References

DocumentDescription
api-client-setup.mdSDK initialization and wallet connection
error-handling.mdError types, retries, and timeout handling

Examples

ExampleDescription
read-query/Query contract state without proofs
state-change/Execute state-changing transactions

Quick Start

1. Connect to Deployed Contract

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',
  },
});

2. Read-Only Query

// Call read-only circuit (no proof generation)
const balance = await contract.query.get_balance({
  address: '0xabc...',
});

console.log('Balance:', balance);

3. State-Changing Transaction

// 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);

Common Patterns

Building a Contract API Client

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();
  }
}

Batch Queries

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;
}

Transaction with Confirmation

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)}%`),
  }
);

Handling Private Inputs

// 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
});

Error Handling

Common errors when calling contracts:

ErrorCauseSolution
Contract not foundInvalid addressVerify contract address
Proof generation failedInvalid witnessCheck circuit inputs
Insufficient balanceLow DUSTFund wallet
Circuit execution failedAssertion violatedReview circuit logic
TimeoutSlow network/​proverIncrease timeout

See error-handling.md for detailed error recovery strategies.

Related Skills

  • contract-deployment - Deploying contracts before calling
  • lifecycle-management - Managing contract state
  • midnight-proofs plugin - Server-side proof optimization

Related Commands

  • /​midnight:check - Verify environment is configured

More skills from aaronbassett

dapp-sdd:implement logo
aaronbassett/midnight-knowledgebase

dapp-sdd:implement

Use when executing implementation tasks with commits after each task and reviews after each phase.

0 0
View
compact-core:clone-examples logo
aaronbassett/midnight-knowledgebase

compact-core:clone-examples

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.

0 0
View
midnight-proofs:proof-caching logo
aaronbassett/midnight-knowledgebase

midnight-proofs:proof-caching

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.

0 0
View
midnight-tooling:midnight-ci logo
aaronbassett/midnight-knowledgebase

midnight-tooling:midnight-ci

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.

0 0
View
midnight-dapp:proof-handling logo
aaronbassett/midnight-knowledgebase

midnight-dapp:proof-handling

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.

0 0
View
dapp-sdd:constitution logo
aaronbassett/midnight-knowledgebase

dapp-sdd:constitution

Use when implementing any Midnight example dApp to ensure compliance with quality standards and project conventions.

0 0
View
compact-core:typescript-integration logo
aaronbassett/midnight-knowledgebase

compact-core:typescript-integration

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.

0 0
View
midnight-dapp:state-management logo
aaronbassett/midnight-knowledgebase

midnight-dapp:state-management

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.

0 0
View
midnight-proofs:prover-optimization logo
aaronbassett/midnight-knowledgebase

midnight-proofs:prover-optimization

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.

0 0
View
dapp-sdd:plan logo
aaronbassett/midnight-knowledgebase

dapp-sdd:plan

Use when creating a phased implementation plan from a specification, with review gates after each phase.

0 0
View
dapp-sdd:specify logo
aaronbassett/midnight-knowledgebase

dapp-sdd:specify

Use when expanding a README-based dApp description into a full specification with user stories and acceptance criteria.

0 0
View
compact-reviewer:best-practices logo
aaronbassett/midnight-knowledgebase

compact-reviewer:best-practices

Use when reviewing Compact contracts for idiomatic patterns, learning recommended practices, or identifying common mistakes to avoid in Midnight smart contract development.

0 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View