Skip to main content
midgard-ts is the TypeScript types and binary codec package for the Sundial L2 data model. It gives you precise TypeScript interfaces for every on-chain structure — blocks, transactions, deposit events, withdrawal events — along with encode/decode functions that round-trip those structures through Sundial’s custom static/dynamic binary format. It also ships Phase A (stateless) and Phase B (stateful) validation pipelines, the same ones the Sundial node’s mempool processor uses. Version 0.1.0 lives in the demo/midgard-ts folder of the sundial-monorepo workspace and is published as the workspace package midgard-ts.

Installation

midgard-ts is a workspace package — add it as a local dependency from inside the sundial-monorepo workspace:
Build the package before first use:

Type Modules

types/block — Block and Header

A Sundial L2 Block comprises a 28-byte header hash, a Header with Merkle roots for each dataset, and a BlockBody containing four maps: UTxOs, transactions, deposits, and withdrawals.

types/transaction — Transactions

Each L2 Transaction carries a full TransactionBody (inputs, outputs, fee, and optional fields controlled by a bitmask) and a TransactionWitnessSet. A TransactionCompact replaces the full body and witness set with their hashes — used inside block headers and fraud proofs.

types/events — Deposit and Withdrawal Events

DepositInfo and WithdrawalInfo are the payload types for L2 user events. Both have full representations (raw bytes) and compact representations (hashed) used in block headers.

Validation Modules

Phase A — Stateless Validation

Phase A validates each transaction independently against its own structure. No UTxO state is required. All checks are synchronous and safe to run in parallel. It enforces the following rules:
| Rule | Description | |---|---| | R2 | Transaction hash integrity — computed body hash must match declared txId | | R3 | Unsupported fields absent — no redeemers, plutus_v3_scripts, or script_data_hash | | R4 | At least one spend input | | R5 | No duplicate inputs within a single transaction | | R6 | Output structure valid — non-negative coin, no overflow | | R9 | Validity interval well-formed — validity_interval_start ≤ ttl | | R11 | Minimum fee — measured against the CBOR-encoded transaction size | | R13 | Required signers have corresponding vkey witnesses | | R14 | vkey witness signatures verify against the transaction body hash | | R15 | Native scripts present and valid against the validity interval | | R19 | is_valid must be true | | R20 | No auxiliary data hash | | R23 | No minting | | R24 | network_id matches the configured network when present |

Phase B — Stateful Validation

Phase B validates Phase-A-accepted candidates against the current UTxO set. It builds a dependency graph, detects cycles, and processes transactions in topological waves with conflict-bucket parallelism. It enforces:
| Rule | Description | |---|---| | R7 | Every spend input exists in the UTxO state or is produced by an earlier accepted tx in the same batch | | R8 | No double-spend across accepted transactions | | R8b | Every reference input exists in UTxO state and is not spent by the same transaction | | R10 | Validity interval is compatible with the current slot | | R12 | Value preservation: Σ(inputs) − fee = Σ(outputs) | | R16 | Input-witness consistency: pubkey inputs need vkey witnesses; script inputs need native script witnesses | | R17 | No dependency cycles between transactions in the batch | | R18 | Cascade-reject all descendants of any rejected transaction |
Use runPhaseBValidationWithPatch when building a block-commitment pipeline. The returned statePatch tells you exactly which UTxOs were spent and which were produced, so you can advance your ledger state in one pass.

Block Inspection Utilities

The inspect module provides a high-level validation helper for individual transactions supplied as CBOR hex. It decodes the CBOR, converts to the Midgard wire format, runs Phase A, and returns structural metadata alongside the validation result.

Binary Codec

midgard-ts uses a custom static/dynamic binary format for all on-chain structures. Each type exposes matching encode* and decode* functions.
The midgard-ts binary format uses an 8-byte-aligned static/dynamic split — every field’s fixed-size portion is written first, followed by variable-length data. This is distinct from standard CBOR encoding and is intentionally larger. Phase A’s minimum-fee check uses the CBOR size, not the Midgard binary size, to match L1 protocol parameters correctly.

Aiken Alignment

midgard-ts types mirror the Sundial on-chain Aiken smart contract data structures. When building off-chain tooling that constructs fraud proofs or state-queue operations, use midgard-ts to produce correctly shaped datums and redeemers that match the Plutus V3 validators.
Use midgard-ts for building off-chain tooling that needs to validate L2 transactions before submission — for example, a custom Watcher node that checks blocks for double-spends before the challenge window closes.

Midgard SDK

The full transaction-building SDK for Sundial L2 — deposits, withdrawals, transaction orders, and fraud proofs on the L1 settlement layer.

REST API Overview

Submit transactions and query L2 state via the Sundial node’s HTTP RPC API without the SDK.