@lifi/composer-sdk
Version:
Public Composer SDK for building and submitting flows
115 lines (112 loc) • 5.06 kB
TypeScript
import { Resource, SolType, Ref, AppliedGuard, Flow } from '@lifi/compose-spec';
import { TypedRef, InputSchema, InputDecl, TypedGuard, OutputKind } from '../types.js';
import { InputHandle, OutputHandle, ResourceInputHandle } from './handles.js';
/**
* Arguments for calling an operation node in a flow.
*/
interface CallArgs {
/** Maps parameter names to input/output handles or raw `$ref` pointers. */
readonly bind: Record<string, AnyBindable>;
/** Optional operation-specific configuration. */
readonly config?: object;
/** Optional guards (e.g. slippage checks) applied to this operation's outputs. */
readonly guards?: readonly TypedGuard[];
}
/**
* Any value that can be bound to an operation parameter: an input handle,
* an output handle from a previous operation, or a typed `$ref` pointer.
*
* Use `raw.ref<T>()` to create a typed ref from a raw path string.
*/
type AnyBindable = InputHandle | OutputHandle | TypedRef;
/**
* Provides references to runtime context values available inside a flow.
* Access via `builder.context`.
*/
interface ContextAccessor {
/** A `$ref` pointing to the transaction sender (signer) address. */
readonly sender: TypedRef<'address'>;
/** A `$ref` pointing to the on-chain execution (proxy) address. */
readonly executionAddress: TypedRef<'address'>;
}
type InputHandleOf<D extends InputDecl> = D extends Resource ? ResourceInputHandle : D extends SolType ? InputHandle<D> : InputHandle;
/**
* A mapped type that converts an input schema into typed handles.
* Resource inputs produce {@link ResourceInputHandle}; scalar inputs produce {@link InputHandle}.
*
* @typeParam T - The flow's input schema.
*/
type InputHandles<T extends InputSchema> = {
readonly [K in keyof T]: InputHandleOf<T[K]>;
};
/**
* Options for creating a new flow builder.
*
* @typeParam T - The flow's input schema.
*/
interface FlowOptions<T extends InputSchema> {
/** Optional human-readable name for the flow. Defaults to a random UUID. */
readonly name?: string;
/** Input declarations mapping names to resource or scalar types. */
readonly inputs: T;
}
/**
* A Flow document branded with its input schema for type-safe request building.
*
* The `__inputs` field is a phantom type — it exists only at compile time for
* TypeScript inference and is never present at runtime.
*/
type TypedFlow<T extends InputSchema = InputSchema> = Flow & {
readonly __inputs?: T;
};
/**
* Core flow builder interface providing low-level access to flow construction.
*
* For most use cases, prefer the {@link FlowBuilder} type returned by `sdk.flow()`
* which adds generated operation methods and a `compile` method.
*
* @typeParam T - The flow's input schema.
*/
interface FlowBuilderCore<T extends InputSchema = InputSchema> {
/** Runtime context references (sender address, execution address). */
readonly context: ContextAccessor;
/** Typed handles for each declared flow input, used to bind inputs to operations. */
readonly inputs: InputHandles<T>;
/**
* Appends an untyped operation node to the flow. This is an escape hatch
* for operations not yet covered by the generated methods.
*
* Use `raw.ref<T>()` to reference this node's outputs in subsequent typed
* operations.
*
* @param id - Unique node identifier within the flow.
* @param op - The operation name (e.g. `"custom.vaultQuery"`).
* @param args - Bind map, config, and optional guards for the node.
* @throws Error if a node with the same `id` already exists in the flow.
*/
readonly untypedOp: (id: string, op: string, args: {
readonly bind: Record<string, Ref>;
readonly config: Record<string, unknown>;
readonly guards?: readonly AppliedGuard[];
}) => void;
/** Serialises the builder state into a {@link TypedFlow} document. */
readonly build: () => TypedFlow<T>;
}
/** Maps output port names to their output kind for compile-time and runtime validation. */
type OutputSpec = Record<string, OutputKind>;
/** Internal interface exposed to bindGeneratedOps — not part of the public API. */
interface FlowBuilderInternal<T extends InputSchema = InputSchema> extends FlowBuilderCore<T> {
readonly call: <O extends OutputSpec>(nodeId: string, op: string, args: CallArgs, outputs: O) => {
readonly [K in keyof O & string]: OutputHandle<O[K]>;
};
}
/**
* Creates a new flow builder targeting the given chain.
*
* @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).
* @param options - Flow configuration including input declarations.
* @returns A {@link FlowBuilderInternal} instance.
* @internal
*/
declare const createFlowBuilderCore: <T extends InputSchema>(chainId: number, options: FlowOptions<T>) => FlowBuilderInternal<T>;
export { type AnyBindable, type CallArgs, type ContextAccessor, type FlowBuilderCore, type FlowBuilderInternal, type FlowOptions, type InputHandles, type OutputSpec, type TypedFlow, createFlowBuilderCore };