A Cardano blockchain emulator for offchain testing, part of the HarmonicLabs/plu-ts ecosystem.
Pluts Emulator simulates a Cardano blockchain environment locally, enabling developers to test smart contracts and transactions without connecting to a real network. It implements the UTxO model with basic transaction processing and Plutus script execution.
Current Version: v0.0.1-dev10 (Early Development)
- UTxO ledger state management with efficient lookups
- Address-to-UTxO mapping
- UTxO resolution by reference and address
- Blockfrost-compatible API
- Transaction mempool (FIFO queue)
- Two-phase validation:
- Phase 1: Structural validation (inputs exist, no duplicates, size limits)
- Phase 2: Plutus script execution (via TxBuilder)
- Collateral handling with slashing on phase-2 failures
- Transaction size and block size limits
- Block height tracking
- Slot number tracking
- POSIX time tracking
- Genesis info integration (system start time, slot length)
awaitBlock()- advance by N blocksawaitSlot()- advance by N slots
- Transaction well-formedness check
- Input existence validation
- At least one input required
- No duplicate inputs
- Transaction size limit enforcement
- Collateral validation for script transactions
- Collateral percentage calculation
- Datum management and resolution
- Protocol parameters from mainnet defaults
- Debug logging with verbosity levels
- Pretty printing for UTxOs, mempool, and ledger state
- Provider pattern implementation (ITxRunnerProvider, IResolveUTxOs, etc.)
npm install @harmoniclabs/pluts-emulatorimport { Emulator } from "@harmoniclabs/pluts-emulator";
// Create emulator instance with optional genesis info and protocol params
const emulator = new Emulator();
// Initialize with UTxOs
emulator.addUtxo([
{
utxoRef: myUtxoRef,
resolved: {
address: myAddress,
value: Value.lovelaces(10_000_000),
datum: undefined,
refScript: undefined
}
}
]);
// Submit a transaction
await emulator.submitTx(myTx);
// Advance blockchain state
await emulator.awaitBlock(1); // Advance by 1 block
// Query UTxOs
const utxos = await emulator.resolveUtxos([myAddress]);
// Pretty print current state
emulator.prettyPrintUtxos();submitTx(tx: Tx): Promise<string>- Submit transaction to mempool
awaitBlock(blocks?: number): Promise<void>- Advance by N blocks (default: 1)awaitSlot(slots?: number): Promise<void>- Advance by N slots (default: 1)
addUtxo(utxos: UTxO[]): void- Add UTxOs to ledgerresolveUtxos(addresses: Address[]): Promise<UTxO[]>- Get UTxOs by addressgetUtxo(utxoRef: TxOutRef): UTxO | undefined- Get specific UTxO
prettyPrintUtxo(utxo: UTxO): void- Print single UTxOprettyPrintUtxos(): void- Print all UTxOsprettyPrintMempool(): void- Print pending transactions
Implements standard Cardano provider interfaces:
IGetGenesisInfosIGetProtocolParametersIResolveUTxOsISubmitTxITxRunnerProvider
src/
├── Emulator.ts # Main emulator class
├── queue.ts # FIFO queue for mempool
├── types/
│ ├── EmulatorBlockInfos.ts # Block metadata
│ └── StakeAddressInfos.ts # Staking data structures
├── utils/
│ └── helper.ts # Test utilities
└── index.ts # Public exports
- Provider Pattern: Drop-in replacement for blockchain providers
- Immutability: UTxO cloning for safe state management
- State Machine: Clear separation between mempool and ledger
- Delegation: Phase 2 validation delegated to TxBuilder
This emulator is designed for basic offchain testing and has significant limitations:
- ✗ Value preservation check (inputs = outputs + fees)
- ✗ Minimum Ada per UTxO validation
- ✗ Validity interval checks (transaction timeouts)
- ✗ Token minting/burning validation
- ✗ Signature verification
- ✗ Native scripts (multisig, timelock)
- ✗ Reference inputs/scripts (partial support)
- ✗ Metadata support
- ✗ Execution unit limits enforcement
- ✗ Staking & delegation (stake pools, rewards, certificates)
- ✗ Governance (CIP-1694, voting, treasury)
- ✗ Multi-era support (no hard fork simulation)
- ✗ Network simulation (no peers, forks, or rollbacks)
- ✗ Block production (fake slot leader only)
- ✗ No state persistence (memory only)
- ✗ No concurrency control (not thread-safe)
- ✗ No transaction rollback on partial failures
- ✗ Unbounded memory growth (no pruning)
- ✗ Single-threaded processing
Good for:
- Testing simple UTxO transactions locally
- Basic Plutus script validation
- Quick iteration during development
- Unit testing smart contract logic
- Educational purposes
NOT suitable for:
- Production validation
- Complex multi-contract interactions
- Staking/delegation testing
- Performance testing
- Governance testing
- Accurate fee estimation for mainnet
npm install
npm run buildnpm testStatus: All tests passing ✅ (37/37 tests pass, 4/4 test suites pass)
Set debug verbosity in emulator constructor:
const emulator = new Emulator(
genesisInfos,
protocolParams,
2 // debug level: 0=errors, 1=warnings, 2=info
);Contributions welcome! See TODO.md for priority improvements needed.
- Phase 1: Fix broken tests
- Phase 2: Implement core ledger rules (value preservation, fees)
- Phase 3: Add documentation and examples
- Phase 4: Advanced validation (minting, certificates, native scripts)
- Phase 5: Staking and governance
- Phase 6: Production hardening (persistence, optimization)
- plu-ts - Plutus TypeScript SDK
- @harmoniclabs/buildooor - Transaction builder
- @harmoniclabs/uplc - Untyped Plutus Core
See LICENSE file.
- GitHub Issues: Report bugs or request features
- HarmonicLabs Discord: Community support