Evolution SDK
Advanced

Architecture

How the transaction builder works internally

Architecture

Evolution SDK's transaction builder uses a deferred execution pattern. Operations like payToAddress, collectFrom, and mintAssets don't execute immediately — they accumulate as a list of programs that run together when you call .build().

Build Phases

When .build() is called, the transaction goes through a state machine of phases. The exact order depends on whether scripts are involved:

Simple transactions (no scripts): Selection → Change Creation → Fee Calculation → Balance → Complete

Script transactions: Selection → Collateral → Change Creation → Fee Calculation → Balance → Evaluation → (re-balance if needed) → Complete

PhasePurpose
SelectionChoose UTxOs from the wallet to cover outputs + fees
CollateralSelect collateral UTxOs (script transactions only)
Change CreationCompute change outputs for leftover value
Fee CalculationCalculate transaction fees based on size and script costs
BalanceVerify inputs equal outputs + fees
EvaluationExecute Plutus scripts and compute execution units
FallbackHandle edge cases (insufficient change, etc.)
CompleteAssemble the final transaction

Deferred Execution

// These don't execute immediately — they record operations
const builder = client.newTx()
  .payToAddress({ ... })    // Records a "pay" program
  .collectFrom({ ... })     // Records a "collect" program
  .mintAssets({ ... })       // Records a "mint" program

// This executes all programs and runs the build phases
const tx = await builder.build()

This design enables:

  • Composition — Combine builders with .compose()
  • Redeemer indexing — Compute correct indices after coin selection
  • Optimization — The builder sees all operations before making decisions

Three Build Methods

MethodReturnsUse Case
.build()Promise<SignBuilder>Standard async/await
.buildEffect()Effect<SignBuilder, Error>Effect-based composition
.buildEither()Promise<Either<Error, SignBuilder>>Explicit error handling

Build Options

Customize the build process:

.build({
  coinSelection: "largest-first",  // or custom function
  changeAddress: customAddress,     // Override change address
  availableUtxos: utxos,           // Override available UTxOs
  evaluator: customEvaluator,      // Custom script evaluator
  debug: true,                     // Enable debug logging
  setCollateral: 5_000_000n,       // Collateral amount
  slotConfig: { ... },             // Custom time configuration
})

Next Steps