example-hello-world
Skill18 starsChanged 16 days agoMITView on GitHub
Generate a complete Midnight Network hello-world DApp from scratch — Compact smart contract, headless Node.js tests with vitest, wallet setup using testkit-js FluentWalletBuilder, DUST generation, deploy and call transactions, and all supporting config. Use when a user wants to build a full Midnight DApp, bootstrap a new project, understand the end-to-end lifecycle, or needs working boilerplate for wallet + contract + tests. This skill produces all files needed to run on local devnet (Docker stack) using the official midnightntwrk/example-hello-world reference implementation.
- Reads credentials
1 other project uses a version of this, 1 of them edited.
Adopted by
Most recently taken up by
- tusharpamnani/Midnight-Skillsedited, first seen May 2, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 1
- tusharpamnani/Midnight-Skills★ 198% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository36 other files it gives its agents.
- AGENTS.mdAGENTS.md
- 1am-walletSkill
- android-example-votingSkill
- ankr-midnightSkill
- compactSkill
- dynamic-midnight-walletSkill
- example-counterSkill
- example-leaderboard-dappSkill
- example-locker-dappSkill
- example-passport-dappSkill
- example-payment-dappSkill
- example-private-party-dappSkill
- example-private-reserve-auction-dappSkill
- example-zk-loan-applicationSkill
- gsap-coreSkill
- gsap-utilsSkill
- indexerSkill
- midnight-consensusSkill
- midnight-cryptographySkill
- midnight-environment-setupSkill
- midnight-jsSkill
- midnight-onchain-logicSkill
- midnight-p2p-networkingSkill
- midnight-passportSkill
- midnight-rpcSkill
- midnightskillSkill
- midnight-storageSkill
- midnight-transactionsSkill
- multinetworkSkill
- nftSkill
- react-wallet-connectorSkill
- midnight-securitySkill
- testingSkill
- token-transfersSkill
- why-midnightSkill
- zk-vs-fhe-vs-mpcSkill
The file
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 0 are distinctive, and 9 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
9
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 24
Test uses static seed (ALICE_SEED) for reproducible testing
- Very specific: line 184
Create this file manually — the compiler output in managed/ is generated from it.
- Very specific: line 216
Create this file manually — it imports from the compiled contract output.
- Very specific: line 737
Update zkConfigPath to managed/your-contract
- Very specific: line 738
Update CompiledContract.make() name and Contract reference
- Very specific: line 740
Update HelloWorldCircuits type to your circuit names
- Very specific: line 741
Update privateStateStoreName prefix to avoid LevelDB collisions
- Very specific: line 745
Update ALICE_PRIVATE_STATE_ID and initialPrivateState shape
- Very specific: line 746
Update src/config.ts if targeting non-local networks
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Example Hello World DApp Skill
This skill generates a complete, runnable Midnight DApp. It covers every file in the project: the Compact contract, TypeScript utilities, test script, Docker configs, and package setup. All code matches the official midnightntwrk/example-hello-world reference implementation.
Primary references:
github.com/midnightntwrk/example-hello-world— official reference repodocs.midnight.network/getting-started/hello-world— official hello-world guidedocs.midnight.network/relnotes/support-matrix— authoritative version compatibility matrix
Package versions below are a dated snapshot (May 2026). Resolve the current tested set from the support matrix before pinning — see references/volatile.md. Never install @latest.
Key architecture notes:
- Uses
@midnight-ntwrk/testkit-jsFluentWalletBuilderfor wallet creation - Uses
@midnight-ntwrk/midnight-js-contractsdeployContractandsubmitCallTx - Compact pragma is
>= 0.23 - Indexer API paths use
/api/v4/graphqlfor local devnet MidnightWalletProviderclass wrapsWalletFacadeto implementMidnightProviderandWalletProviderinterfacessyncWalletfunction provides detailed progress logging during wallet sync- Test uses static seed (
ALICE_SEED) for reproducible testing privateStateStoreNameusesDate.now()for test isolationNODE_OPTIONS='--experimental-vm-modules'required for vitest with ESM
1) Project Structure
hello-world-local/
├── contracts/
│ ├── hello-world.compact # Compact smart contract (you create this)
│ ├── index.ts # Barrel file for compiled contract exports (create manually)
│ └── managed/
│ └── hello-world/ # Compiler output (auto-generated, do not edit)
│ ├── compiler/
│ ├── contract/
│ ├── keys/
│ └── zkir/
├── src/
│ ├── config.ts # Network configuration
│ ├── wallet.ts # MidnightWalletProvider + syncWallet
│ ├── providers.ts # HelloWorldProviders builder
│ └── test/
│ └── hw.test.ts # vitest tests (deploy + storeMessage)
├── compose.yml # Docker: full local stack
├── package.json
├── tsconfig.json
└── vitest.config.tsThe contracts/managed/ directory is created by the Compact compiler — do not create or edit files inside it manually.
2) Prerequisites
# Node.js 22+ required
node --version
# Docker required (local stack)
docker --version
# Install Compact compiler
curl --proto '=https' --tlsv1.2 -sSf \
https://github.com/midnightntwrk/compact/releases/latest/download/compact-installer.sh | sh
source $HOME/.local/bin/env
compact --version3) package.json
{
"name": "hello-world-local",
"version": "0.1.0",
"private": true,
"type": "module",
"engines": {
"node": ">=22.0.0"
},
"scripts": {
"compile": "compact compile contracts/hello-world.compact managed/hello-world",
"test": "NODE_OPTIONS='--experimental-vm-modules' vitest run",
"test:local": "MIDNIGHT_NETWORK=local yarn test",
"env:up": "docker compose up -d --wait",
"env:down": "docker compose down",
"validate": "yarn env:up && yarn test:local; yarn env:down"
},
"dependencies": {
"@midnight-ntwrk/compact-runtime": "0.16.0",
"@midnight-ntwrk/ledger-v8": "8.0.3",
"@midnight-ntwrk/midnight-js-contracts": "4.0.4",
"@midnight-ntwrk/midnight-js-http-client-proof-provider": "4.0.4",
"@midnight-ntwrk/midnight-js-indexer-public-data-provider": "4.0.4",
"@midnight-ntwrk/midnight-js-level-private-state-provider": "4.0.4",
"@midnight-ntwrk/midnight-js-network-id": "4.0.4",
"@midnight-ntwrk/midnight-js-node-zk-config-provider": "4.0.4",
"@midnight-ntwrk/midnight-js-types": "4.0.4",
"@midnight-ntwrk/midnight-js-utils": "4.0.4",
"@midnight-ntwrk/testkit-js": "4.0.4",
"@midnight-ntwrk/wallet-sdk-facade": "3.0.0",
"axios": "^1.15.0",
"pino": "^9.0.0",
"pino-pretty": "^13.0.0",
"rxjs": "^7.8.2",
"testcontainers": "^11.13.0",
"ws": "^8.14.2"
},
"devDependencies": {
"@midnight-ntwrk/midnight-js-compact": "4.0.4",
"@types/node": "^22.0.0",
"@types/ws": "^8.5.9",
"typescript": "^5.7.0",
"vitest": "^3.0.0"
},
"resolutions": {
"@midnight-ntwrk/ledger-v8": "8.0.3",
"@midnight-ntwrk/midnight-js-network-id": "4.0.4",
"@midnight-ntwrk/compact-runtime": "0.16.0"
},
"packageManager": "yarn@1.22.22"
}4) tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "bundler",
"lib": ["ES2022"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"noEmit": true,
"outDir": "dist",
"rootDir": "."
},
"include": ["src/**/*.ts", "contract/**/*.ts"]
}⚠️
"contract/**/*.ts"is singular — this matches the repo exactly and covers the compiler output path. Using"contracts/**/*.ts"(plural) will silently break TypeScript resolution of the compiled contract types.
5) vitest.config.ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'node',
globals: true,
testTimeout: 10 * 60_000,
hookTimeout: 15 * 60_000,
include: ['src/**/*.test.ts'],
reporters: ['default'],
sequence: { concurrent: false },
},
});6) contracts/hello-world.compact
Create this file manually — the compiler output in managed/ is generated from it.
pragma language_version >= 0.23;
export ledger message: Opaque<"string">;
export circuit storeMessage(newMessage: Opaque<"string">): [] {
message = disclose(newMessage);
}Compile from the contracts/ directory:
cd contracts
compact compile hello-world.compact managed/hello-world
cd ..Expected output:
Compiling 1 circuits:
circuit "storeMessage" (k=6, rows=26)This generates contracts/managed/hello-world/contract/index.js (and keys, zkir, compiler dirs). Always compile before running tests.
7) contracts/index.ts (barrel file — create manually)
Create this file manually — it imports from the compiled contract output. The compiled contract module must exist (from running compact compile) for the imports to resolve.
import { CompiledContract } from '@midnight-ntwrk/compact-runtime';
import { fileURLToPath } from 'node:url';
import path from 'node:path';
export {
Contract,
ledger,
pureCircuits,
type Ledger,
type ImpureCircuits,
type PureCircuits,
} from './managed/hello-world/contract/index.js';
import { Contract } from './managed/hello-world/contract/index.js';
const currentDir = path.dirname(fileURLToPath(import.meta.url));
export const zkConfigPath = path.resolve(currentDir, 'managed', 'hello-world');
export const CompiledHelloWorldContract = CompiledContract.make(
'HelloWorldContract',
Contract,
).pipe(
CompiledContract.withVacantWitnesses,
CompiledContract.withCompiledFileAssets(zkConfigPath),
);8) src/config.ts
export type NetworkConfig = {
networkId: string;
indexer: string;
indexerWS: string;
node: string;
nodeWS: string;
proofServer: string;
faucet: string;
};
export const LOCAL_CONFIG: NetworkConfig = {
networkId: 'undeployed',
indexer: 'http://127.0.0.1:8088/api/v4/graphql',
indexerWS: 'ws://127.0.0.1:8088/api/v4/graphql/ws',
node: 'http://127.0.0.1:9944',
nodeWS: 'ws://127.0.0.1:9944',
proofServer: 'http://127.0.0.1:6300',
faucet: '',
};
export function getConfig(): NetworkConfig {
const network = process.env['MIDNIGHT_NETWORK'] ?? 'local';
if (network !== 'local') {
throw new Error(
`Unknown network: ${network}. This harness only supports 'local'.`,
);
}
return LOCAL_CONFIG;
}9) src/wallet.ts
import {
type CoinPublicKey,
DustSecretKey,
type EncPublicKey,
type FinalizedTransaction,
LedgerParameters,
ZswapSecretKeys,
} from '@midnight-ntwrk/ledger-v8';
import {
type MidnightProvider,
type UnboundTransaction,
type WalletProvider,
} from '@midnight-ntwrk/midnight-js-types';
import { ttlOneHour } from '@midnight-ntwrk/midnight-js-utils';
import { type WalletFacade, type FacadeState } from '@midnight-ntwrk/wallet-sdk-facade';
import {
type DustWalletOptions,
type EnvironmentConfiguration,
FluentWalletBuilder,
} from '@midnight-ntwrk/testkit-js';
import * as Rx from 'rxjs';
import type { Logger } from 'pino';
export class MidnightWalletProvider implements MidnightProvider, WalletProvider {
readonly wallet: WalletFacade;
private constructor(
private readonly logger: Logger,
wallet: WalletFacade,
private readonly zswapSecretKeys: ZswapSecretKeys,
private readonly dustSecretKey: DustSecretKey,
) {
this.wallet = wallet;
}
getCoinPublicKey(): CoinPublicKey {
return this.zswapSecretKeys.coinPublicKey;
}
getEncryptionPublicKey(): EncPublicKey {
return this.zswapSecretKeys.encryptionPublicKey;
}
async balanceTx(
tx: UnboundTransaction,
ttl: Date = ttlOneHour(),
): Promise<FinalizedTransaction> {
const recipe = await this.wallet.balanceUnboundTransaction(
tx,
{
shieldedSecretKeys: this.zswapSecretKeys,
dustSecretKey: this.dustSecretKey,
},
{ ttl },
);
return await this.wallet.finalizeRecipe(recipe);
}
submitTx(tx: FinalizedTransaction): Promise<string> {
return this.wallet.submitTransaction(tx);
}
async start(): Promise<void> {
this.logger.info('Starting wallet...');
await this.wallet.start(this.zswapSecretKeys, this.dustSecretKey);
}
async stop(): Promise<void> {
return this.wallet.stop();
}
static async build(
logger: Logger,
env: EnvironmentConfiguration,
seed: string,
): Promise<MidnightWalletProvider> {
const dustOptions: DustWalletOptions = {
ledgerParams: LedgerParameters.initialParameters(),
additionalFeeOverhead: 1_000n,
feeBlocksMargin: 5,
};
const builder = FluentWalletBuilder.forEnvironment(env)
.withDustOptions(dustOptions);
// buildWithoutStarting() returns { wallet, seeds } — seeds contains
// the derived key material. The cast reflects the documented testkit-js
// pattern; verify against your installed version if you see type errors.
const buildResult = await builder.withSeed(seed).buildWithoutStarting();
const { wallet, seeds } = buildResult as {
wallet: WalletFacade;
seeds: {
masterSeed: string;
shielded: Uint8Array;
dust: Uint8Array;
};
};
logger.info(`Wallet built from seed: ${seeds.masterSeed.slice(0, 8)}...`);
return new MidnightWalletProvider(
logger,
wallet,
ZswapSecretKeys.fromSeed(seeds.shielded),
DustSecretKey.fromSeed(seeds.dust),
);
}
}
function isProgressStrictlyComplete(progress: unknown): boolean {
if (!progress || typeof progress !== 'object') {
return false;
}
const candidate = progress as { isStrictlyComplete?: unknown };
if (typeof candidate.isStrictlyComplete !== 'function') {
return false;
}
return (candidate.isStrictlyComplete as () => boolean)();
}
export async function syncWallet(
logger: Logger,
wallet: WalletFacade,
timeout = 300_000,
): Promise<FacadeState> {
logger.info('Syncing wallet...');
let emissionCount = 0;
return Rx.firstValueFrom(
wallet.state().pipe(
Rx.tap((state: FacadeState) => {
emissionCount++;
const shielded = isProgressStrictlyComplete(state.shielded.state.progress);
const unshielded = isProgressStrictlyComplete(state.unshielded.progress);
const dust = isProgressStrictlyComplete(state.dust.state.progress);
logger.info(
`Wallet sync [${emissionCount}]: shielded=${shielded}, unshielded=${unshielded}, dust=${dust}`,
);
}),
Rx.filter(
(state: FacadeState) =>
isProgressStrictlyComplete(state.shielded.state.progress) &&
isProgressStrictlyComplete(state.dust.state.progress) &&
isProgressStrictlyComplete(state.unshielded.progress),
),
Rx.tap(() => logger.info(`Wallet sync complete after ${emissionCount} emissions`)),
Rx.timeout({
each: timeout,
with: () =>
Rx.throwError(
() => new Error(`Wallet sync timeout after ${timeout}ms (${emissionCount} emissions received)`),
),
}),
Rx.catchError((err) => {
logger.error(`Wallet sync error: ${err}`);
return Rx.throwError(() => err);
}),
),
);
}10) src/providers.ts
import { type MidnightProviders } from '@midnight-ntwrk/midnight-js-types';
import { indexerPublicDataProvider } from '@midnight-ntwrk/midnight-js-indexer-public-data-provider';
import { httpClientProofProvider } from '@midnight-ntwrk/midnight-js-http-client-proof-provider';
import { NodeZkConfigProvider } from '@midnight-ntwrk/midnight-js-node-zk-config-provider';
import { levelPrivateStateProvider } from '@midnight-ntwrk/midnight-js-level-private-state-provider';
import { type MidnightWalletProvider } from './wallet.js';
import { type NetworkConfig } from './config.js';
export type HelloWorldCircuits = 'storeMessage';
export type HelloWorldProviders = MidnightProviders<any>;
export function buildProviders(
wallet: MidnightWalletProvider,
zkConfigPath: string,
config: NetworkConfig,
): HelloWorldProviders {
const zkConfigProvider = new NodeZkConfigProvider<HelloWorldCircuits>(zkConfigPath);
return {
privateStateProvider: levelPrivateStateProvider({
privateStateStoreName: `hello-world-${Date.now()}`,
walletProvider: wallet,
privateStoragePasswordProvider: () => 'xK9#mQ2$pL8@nR5!vW3*',
accountId: `test-account-${Date.now()}`,
}),
publicDataProvider: indexerPublicDataProvider(
config.indexer,
config.indexerWS,
),
zkConfigProvider,
proofProvider: httpClientProofProvider(
config.proofServer,
zkConfigProvider,
),
walletProvider: wallet,
midnightProvider: wallet,
};
}11) src/test/hw.test.ts
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { WebSocket } from 'ws';
import { setNetworkId } from '@midnight-ntwrk/midnight-js-network-id';
import {
deployContract,
submitCallTx,
} from '@midnight-ntwrk/midnight-js-contracts';
import type { ContractAddress } from '@midnight-ntwrk/compact-runtime';
import pino from 'pino';
import { getConfig } from '../config.js';
import { MidnightWalletProvider, syncWallet } from '../wallet.js';
import { buildProviders, type HelloWorldProviders } from '../providers.js';
import {
CompiledHelloWorldContract,
ledger,
zkConfigPath,
} from '../../contracts/index.js';
import type { EnvironmentConfiguration } from '@midnight-ntwrk/testkit-js';
// Required for GraphQL subscriptions in Node.js
// @ts-expect-error WebSocket global assignment for apollo
globalThis.WebSocket = WebSocket;
process.on('unhandledRejection', (reason, promise) => {
console.error('UNHANDLED REJECTION:', reason);
console.error('Promise:', promise);
});
process.on('uncaughtException', (err) => {
console.error('UNCAUGHT EXCEPTION:', err);
});
const ALICE_SEED =
'0000000000000000000000000000000000000000000000000000000000000001';
const ALICE_PRIVATE_STATE_ID = 'AlicePrivateHWState';
const logger = pino({
level: process.env['LOG_LEVEL'] ?? 'info',
transport: { target: 'pino-pretty' },
});
describe('Hello World Contract', () => {
let aliceWallet: MidnightWalletProvider;
let aliceProviders: HelloWorldProviders;
let contractAddress: ContractAddress;
const config = getConfig();
async function queryLedger(providers: HelloWorldProviders) {
const state =
await providers.publicDataProvider.queryContractState(contractAddress);
expect(state).not.toBeNull();
return ledger(state!.data);
}
beforeAll(async () => {
setNetworkId(config.networkId);
const envConfig: EnvironmentConfiguration = {
walletNetworkId: config.networkId,
networkId: config.networkId,
indexer: config.indexer,
indexerWS: config.indexerWS,
node: config.node,
nodeWS: config.nodeWS,
faucet: config.faucet,
proofServer: config.proofServer,
};
aliceWallet = await MidnightWalletProvider.build(logger, envConfig, ALICE_SEED);
await aliceWallet.start();
await syncWallet(logger, aliceWallet.wallet, 600_000);
aliceProviders = buildProviders(aliceWallet, zkConfigPath, config);
logger.info('Providers initialized. Ready to test!');
});
afterAll(async () => {
if (aliceWallet) {
logger.info('Stopping Alice wallet...');
await aliceWallet.stop();
}
});
it('Deploys the contract', async () => {
logger.info('Creating private state...');
const deployed: any = await (deployContract as any)(aliceProviders, {
compiledContract: CompiledHelloWorldContract,
privateStateId: ALICE_PRIVATE_STATE_ID,
initialPrivateState: {},
args: [],
});
logger.info('Setting the contract address...');
contractAddress = deployed.deployTxData.public.contractAddress;
logger.info(`Contract deployed at: ${contractAddress}`);
expect(contractAddress).toBeDefined();
expect(contractAddress.length).toBeGreaterThan(0);
const state = await queryLedger(aliceProviders);
expect(state.message).toEqual('');
});
it('Stores Hello World!', async () => {
const message = 'Hello World!';
await (submitCallTx as any)(aliceProviders, {
compiledContract: CompiledHelloWorldContract,
contractAddress,
privateStateId: ALICE_PRIVATE_STATE_ID,
circuitId: 'storeMessage',
args: [message],
});
const state = await queryLedger(aliceProviders);
expect(state.message).toEqual(message);
});
});12) compose.yml
services:
proof-server:
image: 'midnightntwrk/proof-server:8.0.3'
command: ['midnight-proof-server', '-v']
ports:
- '127.0.0.1:6300:6300'
environment:
RUST_BACKTRACE: 'full'
healthcheck:
test: ['CMD-SHELL', 'echo > /dev/tcp/127.0.0.1/6300']
interval: 10s
timeout: 5s
retries: 20
start_period: 10s
indexer:
image: 'midnightntwrk/indexer-standalone:4.0.0'
ports:
- '127.0.0.1:8088:8088'
environment:
RUST_LOG: 'indexer=info,chain_indexer=info,indexer_api=info,wallet_indexer=info,indexer_common=info,fastrace_opentelemetry=off,info'
APP__INFRA__NODE__URL: 'ws://node:9944'
APP__APPLICATION__NETWORK_ID: 'undeployed'
APP__INFRA__STORAGE__PASSWORD: 'indexer'
APP__INFRA__PUB_SUB__PASSWORD: 'indexer'
APP__INFRA__LEDGER_STATE_STORAGE__PASSWORD: 'indexer'
APP__INFRA__SECRET: '303132333435363738393031323334353637383930313233343536373839303132'
healthcheck:
test: ['CMD-SHELL', 'cat /var/run/indexer-standalone/running']
interval: 10s
timeout: 5s
retries: 20
start_period: 10s
depends_on:
node:
condition: service_healthy
node:
image: 'midnightntwrk/midnight-node:0.22.3'
ports:
- '127.0.0.1:9944:9944'
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:9944/health']
interval: 2s
timeout: 5s
retries: 20
start_period: 5s
environment:
CFG_PRESET: 'dev'
SIDECHAIN_BLOCK_BENEFICIARY: '04bcf7ad3be7a5c790460be82a713af570f22e0f801f6659ab8e84a52be6969e'13) First Run — Local Devnet
# 1. Install deps
yarn install
# 2. Compile contract (must run from contracts/ directory)
cd contracts
compact compile hello-world.compact managed/hello-world
cd ..
# 3. Start local stack
yarn env:up
# wait ~30 seconds for all services to become healthy
# 4. Run tests (new terminal)
yarn test:localExpected output:
[12:46:12.694] INFO (22064): Wallet sync complete after 23 emissions
[12:46:12.703] INFO (22064): Providers initialized. Ready to test
[12:46:12.707] INFO (22064): Creating private state...
[12:46:32.347] INFO (22064): Setting the contract address...
[12:46:32.347] INFO (22064): Contract deployed at: bba6579743ae23b44301d4a9f8df30dbd5244d63a59d8fbc2c9fc7ea521a04f8
✓ src/test/hw.test.ts (2 tests) 39112ms
✓ Hello World Contract > Deploys the contract 19649ms
✓ Hello World Contract > Stores Hello World! 18184ms14) Troubleshooting
| Error | Cause | Fix |
compact: command not found | PATH not set | source $HOME/.local/bin/env |
Cannot find module '../../contracts/...' | Contract not compiled yet | Run compact compile from contracts/ first |
ETARGET No matching version found | Version not in the tested set | Resolve current versions from the support matrix — see references/volatile.md. Do not install @latest. |
ECONNREFUSED 127.0.0.1:6300 | Proof server not running | yarn env:up |
NODE_OPTIONS error in test | Missing experimental flag | Ensure NODE_OPTIONS='--experimental-vm-modules' in test script |
Wallet sync timeout | Docker services not healthy | Verify yarn env:up finished — all 3 containers must be healthy |
v4/graphql 404 | Old indexer URL | Local devnet uses /api/v4/graphql — correct in config.ts |
FluentWalletBuilder is not a function | Wrong testkit-js import | Import from @midnight-ntwrk/testkit-js |
levelPrivateStateProvider options error | Missing required fields | Must pass privateStateStoreName, walletProvider, privateStoragePasswordProvider (strong password, min 16 chars, no sequential patterns), and accountId |
TS: Cannot find module for contracts | Wrong tsconfig.json include | Must be "contract/**/*.ts" (singular), not "contracts/**/*.ts" |
submitCallTx not found | Wrong import | Import from @midnight-ntwrk/midnight-js-contracts |
| Old contract address fails after recompile | Verifier key changed | Redeploy — compiled keys change when contract source changes |
15) Adapting This Template
- Replace
contracts/hello-world.compactwith your contract - Compile:
cd contracts && compact compile your-contract.compact managed/your-contract - Update
contracts/index.ts:- Change import paths to
./managed/your-contract/contract/index.js - Update
zkConfigPathtomanaged/your-contract - Update
CompiledContract.make()name andContractreference
- Change import paths to
- In
src/providers.ts:- Update
HelloWorldCircuitstype to your circuit names - Update
privateStateStoreNameprefix to avoid LevelDB collisions
- Update
- In
src/test/hw.test.ts:- Replace
submitCallTxargs with your circuit calls - Replace
ledger()with your contract'sledger()function - Update
ALICE_PRIVATE_STATE_IDandinitialPrivateStateshape
- Replace
- Update
src/config.tsif targeting non-local networks
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

