Evolution SDK
Devnet

Configuration

Customize genesis parameters and protocol settings for your devnet

Devnet Configuration

Devnet clusters are fully customizable through genesis configuration. Control initial funding, protocol parameters, block timing, and network behavior to match your testing requirements.

Genesis Configuration Overview

Genesis configuration defines the initial state of your blockchain: funded addresses, protocol parameters, slot timing, and network settings. The devnet package provides sensible defaults while allowing complete customization.

Every devnet cluster accepts an optional shelleyGenesis parameter. When omitted, the cluster uses DEFAULT_SHELLEY_GENESIS from the package. For custom requirements, create a modified genesis object based on the defaults.

Understanding genesis configuration enables testing diverse scenarios: high-value transactions needing large initial funds, protocol parameter edge cases, rapid testing with fast blocks, or mainnet-like conditions with realistic timing.

Custom Genesis with Funded Addresses

The most common customization is funding specific addresses with ADA at genesis. This eliminates faucet dependencies and ensures deterministic test state.

Addresses must be provided in hexadecimal format. Convert Bech32 addresses using the Evolution SDK's address utilities:

import { ,  } from "@evolution-sdk/devnet";
import { , ,  } from "@evolution-sdk/evolution";

// Create a client to generate an address
const  = ({
  : 0, // Network magic 0 for custom devnet
  : {
    : "seed",
    : "your twenty-four word mnemonic phrase here",
    : 0
  }
});

// Get the address
const  = await .();

// Convert to hex for genesis configuration
const  = .();

// Create custom genesis with funded address
const  = {
  ....,
  : 0.1, // 100ms per slot
  : 100, // 100 slots per epoch
  : {
    []: 1_000_000_000_000 // 1 million ADA (in lovelace)
  }
} satisfies .;

// Create cluster with custom genesis
const  = await .({
  : "funded-devnet",
  : { : 3001, : 3002 },
  : 
});

await .();

The address now has 1 million ADA available from block 0. The funds appear as a single UTxO that can be queried and spent immediately.

Amounts are specified in lovelace (1 ADA = 1,000,000 lovelace). Use underscores for readability: 1_000_000_000_000 is 1 million ADA.

Multiple Address Funding

Fund multiple addresses by adding additional entries to initialFunds. Each address gets an independent genesis UTxO:

import { ,  } from "@evolution-sdk/devnet";
import { , ,  } from "@evolution-sdk/evolution";

const  = ({
  : 0,
  : {
    : "seed",
    : "your mnemonic here",
    : 0
  }
});

const  = ({
  : 0,
  : {
    : "seed",
    : "your mnemonic here",
    : 1 // Different account index = different address
  }
});

const  = .(await .());
const  = .(await .());

const  = {
  ....,
  : {
    []: 500_000_000_000, // 500K ADA
    []: 300_000_000_000  // 300K ADA
  }
} satisfies .;

const  = await .({
  : "multi-user-devnet",
  : { : 3001, : 3002 },
  : 
});

await .();

This pattern enables testing multi-party protocols, delegation scenarios, and wallet interaction without complex transaction setup.

Calculating Genesis UTxOs

After creating a genesis configuration, calculate the resulting UTxOs to verify addresses and amounts.

Important: Genesis UTxOs do NOT appear in Kupo's index because Kupo reads chain events starting from block 1, while genesis UTxOs exist in block 0 (the genesis block itself). You must use calculateUtxosFromConfig to derive these UTxOs and provide them to your transaction builder via the availableUtxos parameter. After spending a genesis UTxO, the resulting outputs will be indexed normally by Kupo.

import { ,  } from "@evolution-sdk/devnet";
import { ,  } from "@evolution-sdk/evolution";
declare const : string;

const  = {
  ....,
  : {
    []: 1_000_000_000_000
  }
} satisfies .;

// Calculate UTxOs before starting the cluster
const  = await .();

.("Genesis UTxOs:", .);
.( => {
  .("Address:", .(.));
  .("Amount:", .., "lovelace");
  .("TxHash:", .(.));
  .("OutputIndex:", .);
});

The calculation produces deterministic UTxOs based on the genesis configuration. Transaction hashes derive from genesis block data, ensuring consistency across cluster recreations.

Protocol Parameters

The devnet runs on Conway era and uses three genesis files with distinct parameter sets.

Genesis Type Definitions

The devnet package exports these types from Config:

import type {  } from "@evolution-sdk/devnet";

// Use the exported types
type  = .;
type  = .;
type  = .;

// ShelleyGenesis.protocolParams contains:
// - minFeeA, minFeeB: Transaction fees
// - maxTxSize, maxBlockBodySize: Size limits
// - keyDeposit, poolDeposit: Stake deposits
// - minUTxOValue: Legacy parameter (unused in Conway)

// AlonzoGenesis contains:
// - lovelacePerUTxOWord: UTxO cost (Conway converts to coinsPerUtxoByte ÷8)
// - executionPrices: Plutus script execution costs
// - maxTxExUnits, maxBlockExUnits: Script execution limits
// - collateralPercentage, maxCollateralInputs: Collateral settings
// - costModels: PlutusV1 and PlutusV2 cost models

// ConwayGenesis contains:
// - poolVotingThresholds, dRepVotingThresholds: Governance voting
// - govActionDeposit, dRepDeposit: Governance deposits
// - minFeeRefScriptCostPerByte: Reference script fees
// - plutusV3CostModel: PlutusV3 cost model

Modifying Parameters

Customize protocol parameters by modifying the appropriate genesis configuration:

import { ,  } from "@evolution-sdk/devnet";
declare const : string;

// Shelley genesis: fees and transaction limits
const : <.> = {
  ....,
  : {
    .....,
    : 50,        // Transaction fee coefficient (default: 44)
    : 200000,    // Minimum fee constant (default: 155381)
    : 32768    // Maximum transaction size in bytes (default: 16384)
  },
  : {
    []: 100_000_000_000
  }
};

// Alonzo genesis: UTxO costs (Conway runtime uses this)
const : <.> = {
  ....,
  : 34482  // Conway converts to coinsPerUtxoByte (÷8 = 4310.25)
};

const  = await .({
  : "custom-protocol-devnet",
  : { : 3001, : 3002 },
  : ,
  : 
});

await .();

Common protocol parameter customizations:

ShelleyGenesis.protocolParams:

  • minFeeA / minFeeB: Transaction fee coefficient and constant
  • maxTxSize: Maximum transaction size in bytes
  • maxBlockBodySize: Maximum block size in bytes
  • keyDeposit / poolDeposit: Stake credential and pool deposits

AlonzoGenesis:

  • lovelacePerUTxOWord: UTxO cost. Conway runtime converts this to coinsPerUtxoByte (÷8). Default 34482 ≈ 4310 lovelace/byte
  • collateralPercentage: Collateral % for script transactions (default: 150)
  • maxCollateralInputs: Max collateral inputs (default: 3)

Important: The devnet runs Conway era. At runtime, the node uses coinsPerUtxoByte (from Alonzo's lovelacePerUTxOWord), not Shelley's legacy minUTxOValue.

See the exported types Config.ShelleyGenesis, Config.AlonzoGenesis, and Config.ConwayGenesis for complete definitions.

Block Timing and Network Behavior

Control block production speed to match testing requirements. Fast blocks accelerate test suites, while realistic timing simulates production conditions.

Adjust slot timing through genesis parameters:

import { ,  } from "@evolution-sdk/devnet";
declare const : string;

const  = {
  ....,
  : 0.02,        // 20ms per slot (very fast!)
  : 50,          // 50 slots per epoch
  : 1.0,    // Every slot produces a block
  : {
    []: 100_000_000_000
  }
} satisfies .;

const  = await .({
  : "fast-devnet",
  : { : 3001, : 3002 },
  : 
});

await .();

Timing parameters explained:

  • slotLength: Seconds per slot. Default 1 second matches mainnet. Use 0.02-0.1 for fast testing, 1.0 for realistic behavior.
  • epochLength: Slots per epoch. Default 432000 (5 days on mainnet). Use 50-100 for rapid epoch transitions in tests.
  • activeSlotsCoeff: Probability a slot produces a block. Use 1.0 for guaranteed blocks (testing), 0.05 for mainnet-like sparsity.

Fast block production (20ms slots, coefficient 1.0) provides near-instant transaction confirmation ideal for integration tests. Realistic timing (1 second slots, coefficient 0.05) validates behavior under production conditions.

Security Parameters

Security parameters affect chain stability and rollback protection:

import {  } from "@evolution-sdk/devnet";
declare const : string;

const  = {
  ....,
  : 10,        // k parameter: rollback limit
  : 120,    // KES key evolution limit
  : 7200,  // Slots before KES evolution
  : {
    []: 100_000_000_000
  }
} satisfies .;
  • securityParam (k): Blocks before finality. Lower values (10) allow faster testing of chain reorganizations. Default 2160 matches mainnet.
  • maxKESEvolutions: Operational certificate validity. Lower for faster key rotation testing.
  • slotsPerKESPeriod: KES evolution frequency. Affects stake pool testing scenarios.

Most applications can ignore these parameters and use defaults. Adjust only when testing specific consensus or staking behaviors.

Complete Configuration Example

Combining all customization options for a comprehensive devnet:

import { , ,  } from "@evolution-sdk/devnet";
import { , ,  } from "@evolution-sdk/evolution";

// Generate funded addresses
const  = ({
  : 0,
  : {
    : "seed",
    : "test wallet one mnemonic here",
    : 0
  }
});

const  = ({
  : 0,
  : {
    : "seed",
    : "test wallet two mnemonic here",
    : 0
  }
});

const  = .(await .());
const  = .(await .());

// Custom genesis configuration
const  = {
  ....,
  
  // Fast block production
  : 0.05,      // 50ms slots
  : 200,      // 200 slots (10 seconds) per epoch
  : 1.0, // Every slot produces a block
  
  // Fund multiple addresses
  : {
    []: 5_000_000_000_000,  // 5M ADA for primary testing
    []: 1_000_000_000_000   // 1M ADA for secondary scenarios
  },
  
  // Custom protocol parameters
  : {
    .....,
    : 40,           // Lower fees for testing
    : 150000,
    : 32768,      // Larger transactions allowed
    : 131072 // Larger blocks for throughput
  },
  
  // Faster key evolution for staking tests
  : 60,
  : 3600
} satisfies .;

// Create cluster with full services
const  = await .({
  : "comprehensive-devnet",
  : { : 3001, : 3002 },
  : ,
  : {
    : true,
    : 1442,
    : "Info"
  },
  : {
    : true,
    : 1337,
    : "info"
  }
});

// Start the devnet
await .();

.("Comprehensive devnet ready:");
.("- Two funded addresses");
.("- 50ms block time");
.("- Custom protocol parameters");
.("- Kupo and Ogmios enabled");

// Calculate and verify genesis UTxOs
const  = await .();
.(`\nGenesis UTxOs: ${.}`);
.((, ) => {
  .(`  Address ${ + 1}: ${..} lovelace`);
});

This configuration provides a fast, well-funded environment suitable for comprehensive integration testing.

Configuration Presets

Common configuration patterns for different testing scenarios:

Rapid Testing (instant confirmations):

{
  slotLength: 0.02,
  epochLength: 50,
  activeSlotsCoeff: 1.0
}

Mainnet Simulation (realistic timing):

{
  slotLength: 1.0,
  epochLength: 21600, // 6 hours per epoch
  activeSlotsCoeff: 0.05
}

High-Value Testing (large initial funds):

{
  initialFunds: {
    [addressHex]: 45_000_000_000_000_000 // 45B ADA (total supply)
  }
}

Fee Testing (extreme fee conditions):

{
  protocolParams: {
    ...defaults,
    minFeeA: 1000,    // Very high fees
    minFeeB: 10000000
  }
}

Size Limit Testing (constrained transactions):

{
  protocolParams: {
    ...defaults,
    maxTxSize: 8192,  // Half normal size
    maxBlockBodySize: 32768
  }
}

Next Steps

With custom genesis configuration, you can now:

  • Integration: Build complete workflows using the Evolution SDK client with your funded devnet addresses

Troubleshooting

Address format errors: Ensure addresses are in hexadecimal format, not Bech32. Use Address.toHex(address) to convert from an Address object.

Genesis UTxO not found: Wait 3-5 seconds after cluster start for full initialization. Query timing matters for fast block configurations.

Protocol parameter validation: Some parameter combinations are invalid (e.g., lovelacePerUTxOWord too low in Alonzo genesis). Check cardano-node logs if startup fails.

Client network parameter: Always use network: 0 for devnet clients to create testnet-format addresses (addr_test...).

Excessive funds: While genesis supports arbitrary amounts, extremely large values may cause numeric overflow in some calculations. Stay under 45B ADA (total supply) per address.