| name | midnight-verify:verify-by-devnet |
| description | Verification by running E2E scripts against a local Midnight devnet. Writes SDK test scripts (raw or using testkit-js) that exercise the full transaction pipeline: deploy, call circuits, observe state. Checks devnet health before proceeding. Loaded by the sdk-tester agent. Loads the `midnight-tooling:devnet` skill for infrastructure management. |
| version | 0.3.0 |
Verify by Devnet Execution
You are verifying an SDK behavioral claim by running a test script against a live local devnet. Follow these steps in order.
Critical Rule
Do NOT attempt E2E testing without first confirming devnet is healthy. If devnet is unreachable, report Inconclusive immediately. Do not guess at behavior.
Step 1: Check Devnet Health
Load the midnight-tooling:devnet skill for endpoint URLs and health check patterns. Check that all three services are reachable:
- Node — health endpoint
- Indexer — health endpoint
- Proof server — health endpoint
If ANY service is unreachable:
- Report Inconclusive (devnet unavailable)
- Message: "Devnet not available. Load the
midnight-tooling:devnet skill for instructions on starting the devnet, then retry."
- Stop. Do not proceed to Step 2.
Step 2: Set Up the Workspace
Uses the same workspace as the type-checker: ~/.midnight-expert/verify/sdk-workspace/.
If it doesn't exist, follow the same initialization as verify-by-type-check (create workspace, install packages, create tsconfig).
Create a job directory:
JOB_ID=$(uuidgen | tr '[:upper:]' '[:lower:]')
mkdir -p "$HOME/.midnight-expert/verify/sdk-workspace/jobs/$JOB_ID"
Step 3: Choose Your Approach
You have two approaches. Choose based on the claim:
Approach A: Raw SDK Script
Write a self-contained .mjs script that imports SDK packages directly. Best for:
- Testing a specific SDK function's behavior in isolation
- Verifying a particular API call's return value or side effects
- Claims about a single SDK feature
- Claims that are ABOUT SDK behavior (not testkit behavior)
- Claims about provider wiring
Pros: No extra dependencies. Transparent — mirrors what a DApp developer would write. Easy to debug.
Cons: More boilerplate (provider setup, wallet init, waiting for sync).
Example structure for a raw SDK script:
import { deployContract } from '@midnight-ntwrk/midnight-js-contracts';
import { setNetworkId } from '@midnight-ntwrk/midnight-js-network-id';
import { httpClientProofProvider } from '@midnight-ntwrk/midnight-js-http-client-proof-provider';
import { indexerPublicDataProvider } from '@midnight-ntwrk/midnight-js-indexer-public-data-provider';
import { NodeZkConfigProvider } from '@midnight-ntwrk/midnight-js-node-zk-config-provider';
import { levelPrivateStateProvider } from '@midnight-ntwrk/midnight-js-level-private-state-provider';
setNetworkId('devnet');
const providers = {
privateStateProvider: levelPrivateStateProvider({ ... }),
publicDataProvider: indexerPublicDataProvider({ ... }),
zkConfigProvider: new NodeZkConfigProvider({ ... }),
proofProvider: httpClientProofProvider({ ... }),
walletProvider: ...,
midnightProvider: ...,
};
console.log(JSON.stringify({ result: ... }));
Approach B: testkit-js
Use @midnight-ntwrk/testkit-js for TestEnvironment and wallet management. Best for:
- Multi-step lifecycle tests (deploy -> call -> observe -> reconnect)
- Claims involving multiple users or contract interactions
- Claims about state observation patterns (observables, subscriptions)
- Complex provider wiring scenarios
Pros: Handles provider wiring, wallet management, health checks automatically. Less boilerplate for complex scenarios.
Cons: Additional abstraction layer. Don't use when the claim is about SDK primitives that testkit wraps.
Example structure for a testkit-js script:
import { createTestEnvironment } from '@midnight-ntwrk/testkit-js';
const env = await createTestEnvironment('undeployed');
Decision Guide
| Scenario | Use |
|---|
| "Does function X return Y?" | Raw SDK script |
| "Does deploy work?" | Raw SDK script |
| "Full lifecycle (deploy -> call -> observe -> reconnect)" | testkit-js |
| "Multi-user interaction" | testkit-js |
| "State observation / subscriptions" | testkit-js |
| "Claim is ABOUT testkit behavior" | Raw SDK script |
| "Claim is about provider wiring" | Raw SDK script |
Step 4: Handle Compact Contract Dependencies
Most E2E tests need a compiled Compact contract. Options:
- Check for pre-compiled test contracts in the workspace (e.g., a counter contract)
- Write and compile a minimal contract using
compact compile --skip-zk — load the midnight-tooling:compact-cli skill for compilation details
- Use a stock counter contract — this is the simplest possible Midnight contract:
import CompactStandardLibrary;
export ledger round: Counter;
export circuit increment(): [] {
round.increment(1);
}
Compile it and place the output in the job directory.
Step 5: Write and Run the Script
Write the chosen script to the job directory:
cat > "$HOME/.midnight-expert/verify/sdk-workspace/jobs/$JOB_ID/test-claim.mjs" << 'SCRIPT_EOF'
<script content>
SCRIPT_EOF
Run it:
cd "$HOME/.midnight-expert/verify/sdk-workspace/jobs/$JOB_ID"
node test-claim.mjs
Capture stdout and stderr. The script should output structured JSON for programmatic interpretation.
If the script throws: Capture the error. Determine if it's a claim issue (the SDK genuinely doesn't behave as claimed) or a test issue (your script has a bug). If it's a test issue, fix and retry once.
Step 6: Interpret and Report
Report format:
### Devnet Execution Report
**Claim:** [verbatim]
**Approach:** [Raw SDK script / testkit-js]
**Test script:**
\`\`\`javascript
[full source]
\`\`\`
**Output:**
\`\`\`
[stdout/stderr]
\`\`\`
**Interpretation:** [Confirmed / Refuted / Inconclusive] — [explanation]
Step 7: Clean Up
rm -rf "$HOME/.midnight-expert/verify/sdk-workspace/jobs/$JOB_ID"
Wallet SDK Devnet Mode
This mode is used ONLY as a fallback for wallet SDK claims when source investigation returned Inconclusive. You will only reach this section if the orchestrator explicitly dispatches you with domain: 'wallet-sdk'.
Health Check Differences
The wallet SDK requires Docker containers instead of a standalone devnet:
- midnight-node — check with
docker ps | grep midnight-node or query the substrate RPC endpoint
- midnight-indexer — check GraphQL health endpoint (typically
http://localhost:8088/api/v4/graphql)
- proof-server — check health endpoint (typically
http://localhost:6300/health)
If ANY container is unreachable:
- Report Inconclusive (source insufficient, devnet unavailable)
- Message: "Source investigation was inconclusive and wallet devnet infrastructure is not available. Start the required Docker containers and retry."
- Stop. Do not proceed.
Workspace
Reuse the wallet-sdk-workspace at ~/.midnight-expert/verify/wallet-sdk-workspace/. It already has all wallet SDK packages installed.
Script Approach
Write test scripts using the wallet SDK packages directly. The packages/docs-snippets/ in the wallet repo provide reference patterns for common operations (initialization, transfers, swaps, balancing). Use these as hints for script structure but verify behavior through execution.
The rest of the devnet verification flow (choose approach, write script, run, interpret, report, clean up) follows the same pattern as the standard SDK devnet mode.