@lifi/composer-sdk
Version:
Public Composer SDK for building and submitting flows
133 lines (120 loc) • 4.55 kB
text/typescript
import type { LiteralBinding, Ref } from '@lifi/compose-spec';
import {
InputSpec,
MaterialiserInput,
Resource,
SolType,
} from '@lifi/compose-spec';
/**
* A string that represents a non-negative integer (e.g. "1000000000").
* Uses a template literal type so that only numeric-looking strings
* are assignable at compile time.
*/
export type IntegerString = `${bigint}`;
/**
* Accepted input for integer-string config fields.
* Callers may pass either a numeric string ("1000000000") or a native bigint
* (1000000000n). Bigint values are stringified automatically during JSON
* serialization via the SDK's `bigintReplacer`.
*/
export type IntegerStringInput = IntegerString | bigint;
/**
* A `0x`-prefixed hex string representing an Ethereum address.
* Template literal type catches obviously wrong values at compile time.
*/
export type Address = `0x${string}`;
/** The universe of output port kinds: Solidity scalar types plus `'resource'`. */
export type OutputKind = SolType | 'resource';
/**
* Maps an ABI parameter type string (from abitype's `ParseAbiItem`) to the
* closest `OutputKind`. When the ABI type is one of the supported `SolType`
* scalars, the mapping is exact; for all other Solidity types (e.g. tuples,
* fixed-point decimals) it falls back to `SolType` — accepting any scalar
* handle but not `'resource'` handles.
*
* The fallback excludes `'resource'` because every Solidity type is a scalar;
* resource handles carry token-amount semantics that should only flow into
* slots explicitly declared as resources.
*
* Extending `SolType` with new members automatically widens the exact-match
* branch — no changes needed here.
*/
export type AbiTypeToOutputKind<T extends string> = T extends SolType
? T
: SolType;
/**
* Phantom brand key for {@link TypedRef}.
*
* Declared, never assigned: it exists only so the type checker can tell a
* typed ref from an arbitrary `{ $ref }` object. Keying it on a `unique
* symbol` means no caller can produce one by writing an object literal.
*/
export declare const typedRefKind: unique symbol;
/**
* A typed `$ref` pointer carrying a phantom type parameter.
*
* On the wire, and at run time, this is exactly `{ $ref: string }` — the
* brand is erased. The brand is *required* in the type so a plain `Ref` does
* not satisfy `TypedRef` structurally, which is the contract `RefBindable`
* advertises: an untyped `{ $ref }` never enters a typed bind slot. Build one
* with `raw.ref<T>()`.
*/
export interface TypedRef<T extends OutputKind = OutputKind> extends Ref {
readonly [typedRefKind]: T;
}
/**
* A literal bind value carrying a phantom type parameter.
*
* The wire format accepts a constant in a bind slot as
* `{ kind: <solType>, value: <string> }`, alongside `$ref` pointers. Use it
* for a value that must be baked into the flow document rather than supplied
* at run time — the destination of a flow the backend stores and re-runs
* later (a `continuation.settle` node's `continuationFlow`) has no run to
* take an input from.
*
* @typeParam T - The Solidity type of the literal (e.g. `'address'`).
*/
export interface TypedLiteral<
T extends SolType = SolType,
> extends LiteralBinding {
readonly kind: T;
readonly __outputKind?: T;
}
/**
* An input declaration in a flow schema.
* `Resource` values become resource inputs (token amounts);
* `SolType` strings become handle inputs (scalars like addresses).
*/
export type InputDecl = Resource | SolType;
/**
* A record mapping input names to their declarations.
* Used as the type parameter for generic flow builders and requests.
*/
export type InputSchema = Record<string, InputDecl>;
/**
* Maps an input declaration to the allowed runtime value type.
* Resource inputs accept materialisers or literal amounts.
* Handle inputs accept the scalar type matching their SolType.
*/
export type InputSpecOf<D> = D extends Resource
? MaterialiserInput | IntegerStringInput
: D extends 'address'
? Address
: D extends 'bool'
? boolean
: D extends `${'u' | ''}int${string}`
? IntegerStringInput
: D extends `bytes${string}`
? `0x${string}`
: D extends 'string'
? string
: InputSpec;
/**
* A guard applied to an operation, with the `port` field constrained
* to a specific set of output port names.
*/
export interface TypedGuard<Port extends string = string> {
readonly kind: string;
readonly port: Port;
readonly [key: string]: unknown;
}