Skip to content

API Overview

JAM Forge provides a comprehensive set of APIs for working with the JAM protocol. All APIs are organized into modular packages with clear dependencies.

Foundation module providing core protocol types and serialization.

Package: io.forge.jam.core

Key APIs:

  • Types: Block, Header, Extrinsic, WorkPackage, WorkReport
  • Codec: Binary serialization using scodec
  • Configuration: Chain configuration and constants

Example:

import io.forge.jam.core.types.*
import io.forge.jam.core.codec.given
// Decode a block from bytes
val block: Either[Error, Block] = Block.codec.decode(bytes)
// Encode a header
val encoded: BitVector = header.codec.encode(header)

Cryptographic operations for the JAM protocol.

Package: io.forge.jam.crypto

Key APIs:

  • Bandersnatch VRF: Ring VRF signatures
  • Ed25519: Signature operations
  • Erasure Coding: Reed-Solomon encoding
  • Hashing: Blake2b, Keccak

Example:

import io.forge.jam.crypto.*
// Verify Ed25519 signature
val valid: Boolean = Ed25519.verify(publicKey, message, signature)
// Generate erasure coding chunks
val chunks: Vector[Chunk] = ErasureCoding.encode(data, numChunks)

PolkaVM virtual machine for work package execution.

Package: io.forge.jam.pvm

Key APIs:

  • VM: Virtual machine instance
  • Program: Bytecode representation
  • Memory: Page-based memory model
  • Gas: Resource metering

Example:

import io.forge.jam.pvm.*
// Load and execute a program
val program = Program.load(bytecode)
val vm = VM.create(program)
val result = vm.execute(gasLimit)

State transition functions and block import pipeline.

Package: io.forge.jam.protocol

Key APIs:

  • State Transitions: All nine STFs (Safrole, Assurances, etc.)
  • Block Import: End-to-end block validation
  • State Management: JAM state representation

Example:

import io.forge.jam.protocol.*
import io.forge.jam.protocol.safrole.*
// Apply block to state
val newState = BlockImport.importBlock(currentState, block, config)
// Run specific STF
val updated = SafroleTransition.transition(state, block, config)

All APIs use Either[Error, Result] for operations that can fail:

// Decode with error handling
Block.codec.decode(bytes) match
case Right(block) => processBlock(block)
case Left(error) => handleError(error)
// Monadic composition
for
block <- decodeBlock(bytes)
validated <- validateBlock(block)
newState <- importBlock(state, validated)
yield newState

JAM Forge uses type classes for extensible functionality:

// Codec type class
trait Codec[A]:
def encode(value: A): Attempt[BitVector]
def decode(bits: BitVector): Attempt[DecodeResult[A]]
// Automatic derivation
given Codec[MyType] = deriveCodec

Domain primitives use opaque types for safety:

opaque type Hash = Array[Byte]
opaque type Balance = UInt
opaque type ServiceId = UInt
// Type-safe construction
val hash: Hash = Hash.fromBytes(bytes)
val balance: Balance = Balance(1000)
import io.forge.jam.core.types.*
import io.forge.jam.protocol.*
// Deserialize block
val block: Block = Block.codec.decode(blockBytes).toOption.get
// Validate and import
val result: Either[PipelineError, State] =
BlockImport.importBlock(currentState, block, config)
result match
case Right(newState) =>
println(s"Block imported successfully")
println(s"New state root: ${newState.stateRoot}")
case Left(error) =>
println(s"Import failed: $error")
import io.forge.jam.pvm.*
import io.forge.jam.core.types.*
// Load work package
val workPackage: WorkPackage = // ... from block extrinsic
// Create VM and execute
val program = Program.load(workPackage.code)
val vm = VM.create(program)
val result = vm.execute(gasLimit = 1_000_000)
result match
case Success(output) =>
println(s"Execution successful: $output")
case Failure(error) =>
println(s"Execution failed: $error")
import io.forge.jam.crypto.*
// Ed25519 signing
val keyPair = Ed25519.generateKeyPair()
val signature = Ed25519.sign(keyPair.secret, message)
val valid = Ed25519.verify(keyPair.public, message, signature)
// Bandersnatch VRF
val vrfOutput = BandersnatchVrf.sign(secret, input)
val verified = BandersnatchVrf.verify(public, input, vrfOutput)
// Erasure coding
val chunks = ErasureCoding.encode(data, numChunks = 341)
val recovered = ErasureCoding.decode(chunks.take(171))

Detailed API documentation is available for each module:

JAM Forge requires Scala 3.3.7 or later. Key Scala 3 features used:

  • GADTs: For type-safe instruction encoding
  • Opaque Types: For zero-cost domain types
  • Given/Using: For type class instances
  • Extension Methods: For ergonomic APIs
  • Inline: For performance-critical code