Skip to content

Instantly share code, notes, and snippets.

@solanoepalacio
Created April 22, 2025 22:26
Show Gist options
  • Select an option

  • Save solanoepalacio/3b02cee4eb5c7ce376747665286287f6 to your computer and use it in GitHub Desktop.

Select an option

Save solanoepalacio/3b02cee4eb5c7ce376747665286287f6 to your computer and use it in GitHub Desktop.

Revisions

  1. solanoepalacio created this gist Apr 22, 2025.
    86 changes: 86 additions & 0 deletions example-state-machine-iterator.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,86 @@
    type StepId = string;

    interface StateMachineOptions {
    steps: Step[];
    }

    interface MachineIteratorInterface {
    step: Step;
    state: Record<StepId, StepState>;
    }

    interface StepState {
    executed: boolean;
    error?: string; // ?
    result?: string; // this would be tied to the ExecutionStep.type
    }

    // this would be ExecutionStep that already exists on the sdk.
    interface Step {
    id: StepId;
    tx: string; // this will be a very complex type depending on the platform and so on... but just using "string" just for the poc example.
    }

    export class AsyncStateMachine implements AsyncIterable<MachineIteratorInterface> {
    private currentIndex = 0;
    private steps: Step[];
    private state: Record<StepId, StepState>;

    constructor(private options: StateMachineOptions) {
    this.steps = options.steps;
    this.state = Object.fromEntries(options.steps.map(s => [s.id, { executed: false }]));
    }

    completeStep(step: Step, result: string) {
    this.state = {
    ...this.state,
    [step.id]: {
    executed: true,
    result,
    }
    }
    };

    async next(): Promise<IteratorResult<MachineIteratorInterface>> {
    if (this.currentIndex >= this.steps.length) {
    return { value: undefined, done: true };
    }

    const step = this.steps[this.currentIndex];

    this.currentIndex++;

    return {
    value: {
    state: this.state,
    step
    },
    done: false
    };
    }

    [Symbol.asyncIterator](): AsyncIterator<MachineIteratorInterface> {
    return this;
    }
    }

    (async function run () {
    const steps = [
    { id: "1", tx: "transaction-1" },
    { id: "2", tx: "transaction-2" },
    { id: "3", tx: "transaction-3" },
    ];

    const workflow = new AsyncStateMachine({ steps });

    for await (const { state, step } of workflow) {
    console.log(`Executing step ${step.id} transaction: ${step.tx}`);

    if (step.id === "2") {
    console.log("Because I'm in step 2 I'll require the result of step 2");
    console.log("Which is: ", state["1"].result);
    }

    workflow.completeStep(step, `TX ${step.id} executed successfully`);
    }
    })();