Skip to main content

Local Development

LocalBlockchain provides a local testing environment for ZkApp development. Unlike live networks, LocalBlockchain runs entirely in-memory with pre-funded test accounts and configurable settings for rapid development and testing.

LocalBlockchain is essential for unit testing, integration testing, and development workflows. It provides instant transaction finality, deterministic behavior, and the ability to control proof generation for different testing scenarios.

Basic Setup

Configure LocalBlockchain for your development environment:

async () => {
// Development mode - fast execution, no proofs
let Local = await Mina.LocalBlockchain({ proofsEnabled: false });
Mina.setActiveInstance(Local);

// Access pre-funded test accounts
let [feePayer, user1, user2] = Local.testAccounts;

Configuration Options

LocalBlockchain accepts configuration parameters to control its behavior:

// Production-like testing with proofs
let LocalWithProofs = await Mina.LocalBlockchain({
proofsEnabled: true, // Generate real proofs (slower)
enforceTransactionLimits: true, // Enforce network transaction limits
});

// Development testing without constraints
let LocalFast = await Mina.LocalBlockchain({
proofsEnabled: false, // Skip proof generation (faster)
enforceTransactionLimits: false, // Allow complex transactions
});

Test Accounts

LocalBlockchain provides 10 pre-funded test accounts:

let LocalAccounts = await Mina.LocalBlockchain();
let [feePayer, user1, user2, user3] = LocalAccounts.testAccounts;

console.log(`Fee Payer: ${feePayer.toBase58()}`);

Deploying and Testing ZkApps

Here's a complete example showing how to define, deploy, and test a ZkApp on LocalBlockchain:

// Define a smart contract with state
class CounterContract extends SmartContract {
@state(Field) counter = State<Field>();

init() {
super.init();
this.counter.set(Field(0));
}

@method async add(value: Field) {
let currentCounter = this.counter.getAndRequireEquals();
this.counter.set(currentCounter.add(value));
}
}

// Set up LocalBlockchain
let Local = await Mina.LocalBlockchain({ proofsEnabled: false });
Mina.setActiveInstance(Local);

let [feePayer] = Local.testAccounts;
let contractAccount = Mina.TestPublicKey.random();
let contract = new CounterContract(contractAccount);

// Compile contract (or analyze for faster development)
await CounterContract.analyzeMethods();

// Deploy contract
let deployTx = await Mina.transaction(feePayer, async () => {
AccountUpdate.fundNewAccount(feePayer);
await contract.deploy();
});
await deployTx.prove();
await deployTx.sign([feePayer.key, contractAccount.key]).send();

console.log("Initial state:", contract.counter.get().toString());

// Call the add method
let addTx = await Mina.transaction(feePayer, async () => {
await contract.add(Field(5));
});
await addTx.prove();
await addTx.sign([feePayer.key]).send();

console.log("State after adding 5:", contract.counter.get().toString());

// Call add method again
let addTx2 = await Mina.transaction(feePayer, async () => {
await contract.add(Field(3));
});
await addTx2.prove();
await addTx2.sign([feePayer.key]).send();

console.log("State after adding 3:", contract.counter.get().toString());
// Expected output: "8"

This example demonstrates the typical LocalBlockchain development workflow: define contracts, deploy to local environment, execute methods, and verify state changes.

API Reference

For detailed LocalBlockchain information, see: