@lifi/compose-spec
Version:
Public wire-format types and schemas for Compose flows
155 lines (126 loc) • 4.54 kB
text/typescript
import type { SimulationRevert } from './compile.js';
import type { FlowInput, ResourceInput, SolType } from './flowSchema.js';
import type { Availability, Resource } from './resource.js';
import type {
HandlePort,
OpInputPort,
OpOutputPort,
ResourceOutputPort,
ResourcePort,
} from './zodSchemas.js';
export type {
HandlePort,
OpInputPort,
OpOutputPort,
ResourceOutputPort,
ResourcePort,
} from './zodSchemas.js';
export interface Port {
readonly name: string;
readonly type: SolType;
readonly mode: 'linear' | 'copy';
readonly availability?: Availability;
readonly resource?: Resource;
}
export const isResourceInput = (input: FlowInput): input is ResourceInput =>
'resource' in input;
export const flowInputType = (input: FlowInput): SolType =>
isResourceInput(input) ? 'uint256' : input.type;
export const flowInputMode = (input: FlowInput): 'linear' | 'copy' =>
isResourceInput(input) ? 'linear' : 'copy';
export const flowInputResource = (input: FlowInput): Resource | undefined =>
isResourceInput(input) ? input.resource : undefined;
export const isResourcePort = (port: OpInputPort): port is ResourcePort =>
port.kind === 'resource';
export const isHandlePort = (
port: OpInputPort | OpOutputPort,
): port is HandlePort => port.kind === 'handle';
export const isResourceOutputPort = (
port: OpInputPort | OpOutputPort,
): port is ResourceOutputPort => port.kind === 'resource_output';
// A resource output whose value becomes available only after the initiating
// transaction settles. Absence of `availability` means `'now'`, so the check is
// a direct comparison against the one non-default mode. Every site that asks
// "is this port's value delivered later?" goes through here, so a rename of the
// property or a new availability mode lands in one place.
export const isFutureResourceOutput = (
port: OpInputPort | OpOutputPort,
): boolean => isResourceOutputPort(port) && port.availability === 'future';
export type ComposeErrorKind =
| 'decode_error'
| 'validation_error'
| 'linearity_error'
| 'resolve_error'
| 'preparation_error'
| 'provider_error'
| 'no_route_error'
| 'resolution_error'
| 'resolution_rejected'
| 'lowering_error'
| 'empty_program'
| 'simulation_error'
| 'simulation_setup_error'
| 'simulation_insufficient_funds'
| 'simulation_gas_limit'
| 'simulation_rpc_error'
| 'simulation_revert'
| 'subgraph_simulation_revert'
| 'guard_error'
| 'continuation_error'
| 'compilation_error'
| 'verification_error'
| 'price_impact_exceeded'
| 'fee_resolution_error'
| 'fee_resolution_unavailable'
| 'flashloan_unauthorized'
// The request exceeded its wall-clock budget and was cancelled mid-flight.
| 'deadline_exceeded';
export type GenericComposeErrorKind = Exclude<
ComposeErrorKind,
'preparation_error' | 'simulation_revert'
>;
export interface FailedPreparedOp {
readonly callId: string;
readonly op: string;
readonly kind: GenericComposeErrorKind;
readonly message: string;
readonly path?: string;
}
interface ComposeErrorBase {
readonly message: string;
readonly path?: string;
}
export interface PreparationComposeError extends ComposeErrorBase {
readonly kind: 'preparation_error';
readonly failedOps: readonly FailedPreparedOp[];
readonly succeededOps: readonly string[];
}
export interface SimulationRevertComposeError extends ComposeErrorBase {
readonly kind: 'simulation_revert';
readonly details?: SimulationRevert;
}
export interface GenericComposeError extends ComposeErrorBase {
readonly kind: GenericComposeErrorKind;
readonly [key: string]: unknown;
}
export type ComposeError =
PreparationComposeError | SimulationRevertComposeError | GenericComposeError;
export interface MaterialiserInputBase {
readonly kind: string;
}
export type MaterialiserInput = MaterialiserInputBase & Record<string, unknown>;
export type MaterialiserInputOf<C extends object> = MaterialiserInputBase & C;
export type MaterialiserConfigOf<C extends object> = C;
export const isMaterialiserInput = (s: InputSpec): s is MaterialiserInput =>
typeof s === 'object' && s !== null && 'kind' in s;
export type InputSpec = bigint | string | MaterialiserInput;
export interface PreconditionBase {
readonly type: string;
}
export type Precondition = PreconditionBase & Record<string, unknown>;
export type PreconditionOf<C extends object> = PreconditionBase & C;
export type PreconditionConfigOf<C extends object> = Omit<
PreconditionBase,
'type'
> &
C;