Evolution SDK
ModulesSdkBuildersPhases

sdk/builders/phases/ChangeCreation.ts

ChangeCreation overview

Change Creation Phase - Change Output Generation

Creates change outputs from leftover assets using a cascading retry strategy. Handles both unfrack (N outputs) and single output approaches with fallback options.

Added in v2.0.0


Table of contents


utils

executeChangeCreation

Change Creation Phase

Creates change outputs from leftover assets using a cascading retry strategy. Both unfrack (N outputs) and single output follow the same retry pattern: try with available funds → if insufficient, reselect (up to MAX_ATTEMPTS) → fallback.

Symmetric Retry Flow (Unfrack vs Single Output):

UNFRACK (N outputs)                    SINGLE OUTPUT (1 output)
─────────────────────────────────────────────────────────────────

Try: Create N outputs                  Try: Create 1 output
↓                                      ↓
Check: leftover >= (minUTxO × N)?      Check: leftover >= minUTxO?
↓                                      ↓
If NO (not affordable):                If NO (insufficient):
  ├─ attempt < MAX? → Reselect           ├─ attempt < MAX? → Reselect
  └─ attempt >= MAX? → Fallback          └─ attempt >= MAX? → Fallback

Fallback:                              Fallback:
  └─ Single output                       ├─ drainTo (merge into output)
      ├─ (retry/fallback)                ├─ burn (leftover → fee)
      └─ ...                             └─ error

Detailed Flow:

1. Calculate tentative leftover (inputs - outputs - contextFee)

2. If unfrack enabled and canUnfrack=true:
   → Try createUnfrackedChangeOutputs() (N outputs)
   → Success: store N outputs, goto FeeCalculation
   → Not affordable:
      ├─ If attempt < MAX_ATTEMPTS: reselect (add more UTxOs)
      └─ If attempt >= MAX_ATTEMPTS: canUnfrack=false, goto step 3

3. Single output approach:
   → Create 1 change output with leftover
   → Success: store 1 output, goto FeeCalculation
   → Not affordable:
      ├─ If attempt < MAX_ATTEMPTS: reselect (add more UTxOs)
      └─ If attempt >= MAX_ATTEMPTS: goto step 4

4. Insufficient change fallbacks (single-output only):
   a. If drainTo specified: merge into existing output
   b. If onInsufficientChange="burn": leftover becomes fee
   c. If onInsufficientChange="error": throw error

Key Principles:

  • Unfrack and single output use SAME retry mechanism (reselection up to MAX_ATTEMPTS)
  • Phase loop handles fee convergence (leftover recalculated each iteration)
  • Last subdivision output absorbs remainder for exact balance
  • canUnfrack flag prevents retry loops (once false, stays false)
  • drainTo and burn are terminal fallbacks (single-output only)
  • Unfrack outputs bypass drainTo/burn (they're already valid)

Signature

export declare const executeChangeCreation: () => Effect.Effect<
  PhaseResult,
  TransactionBuilderError,
  PhaseContextTag | TxContext | ChangeAddressTag | BuildOptionsTag | ProtocolParametersTag | AvailableUtxosTag
>