UNPKG

@lifi/compose-spec

Version:

Public wire-format types and schemas for Compose flows

205 lines (187 loc) 8.45 kB
import type { VerificationDescriptor } from './descriptor.js'; import type { InputSpec, Precondition } from './flow.js'; import type { Flow } from './flowSchema.js'; import type { Outputs } from './output.js'; import type { ContinuationPlanWire, Phase1ArtifactWire } from './zodSchemas.js'; export type SimulationPolicy = 'strict' | 'allow-revert'; /** * Destination for sweeping proxy-held terminal resources after execution. * Either a literal EVM address or a `{ $ref }` context reference * (e.g. `{ $ref: "context.sender" }`). */ export type SweepTo = string | { readonly $ref: string }; export interface ComposeRun { readonly inputs: Record<string, InputSpec>; readonly preconditions?: readonly Precondition[]; readonly signer: string; readonly assumptions?: Record<string, bigint>; readonly referrer?: string; readonly integratorFeeBps?: number; readonly maxPriceImpactBps?: number; readonly sweepTo?: SweepTo; readonly simulationPolicy?: SimulationPolicy; /** * Also simulate the final user-facing transaction. Defaults to `false`; * reverts honour `simulationPolicy` and a success is echoed back as * `userProgramSimulation`. */ readonly simulateUserProgram?: boolean; readonly checkOnChainAllowances?: boolean; } export interface ComposeCompileRequest { readonly flow: Flow; readonly run: ComposeRun; } export interface PriceImpact { readonly inputValueUsd: number; readonly outputValueUsd: number; readonly impactBps: number; readonly unpricedInputs: readonly string[]; readonly unpricedOutputs: readonly string[]; } export interface ApprovalEntry { readonly token: string; readonly spender: string; readonly amount: string; readonly transactionRequest: { readonly to: string; readonly data: string; readonly value: '0'; }; } export interface SimulationRevert { readonly code: number; readonly rawErrorBytes: string; readonly decodeResult?: { readonly errorCandidates?: readonly { readonly decodedErrorSignature: string; readonly decodedParams: readonly string[]; }[]; readonly error?: string; }; } export interface ComposeTransactionRequest { readonly to: string; readonly chainId: number; readonly data: string; readonly value: string; readonly gasLimit?: string; } // Hand-mirrored from `ComposeActionSchema`, the OpenAPI source of truth in // `@lifi/api-schemas`. export interface ComposeAction { readonly kind: 'transaction'; readonly purpose: 'approval' | 'execute' | 'fundEscrow'; readonly submitter: 'signer' | 'anyone'; readonly transactionRequest: ComposeTransactionRequest; readonly nodeId?: string; } // Continuation fields shared by the success and partial-error responses, so the // two shapes cannot drift. `phase1ByNode` / `continuationPlans` reuse the // Zod-inferred wire types from `zodSchemas.ts`, pinning these SDK-facing types // to the server contract rather than hand-transcribing them. interface ComposeContinuationData { // Phase-1 action to sign/fund now, keyed by settle node. Absent for an atomic flow. readonly phase1ByNode?: Record<string, Phase1ArtifactWire>; // Self-serve second leg to re-submit later, keyed by settle node. Present only // for providers that hand the next leg back to the caller (manual-relay). readonly continuationPlans?: Record<string, ContinuationPlanWire>; } // One funding leg the compiled fill consumes: the resource input's name, its // token (native → zero address) and chain, and the statically resolved amount // as a decimal string (verified continuations, plan GD-8, seam C5). `nodeId` // names the `continuation.settle` node this input funds (the `phase1ByNode` / // `actions` key); absent when the input funds no settle leg (e.g. a plain // swap's input). export interface SpendEntry { readonly input: string; readonly token: string; readonly chainId: number; readonly amount: string; readonly nodeId?: string; } // One fee row per (input, recipient), as the compiled fill charges it. // Hand-mirrored from api-schemas' `ComposeFeeSchema` (the OpenAPI source of // truth; this package cannot depend on it). `recipient` names WHO is charged // — never an address; the address is the sibling `recipientAddress`. `amount` // is absent when the gross is only known on-chain at execution time (a // balance-materialiser input). export interface ComposeFee { readonly input: string; // Zero address for native, otherwise the ERC-20 contract. readonly token: string; readonly recipient: 'lifi' | 'integrator'; readonly recipientAddress: string; readonly bps: number; readonly amount?: string; } // The optional user-program simulation result, present only when the request // opted in via `run.simulateUserProgram` and the simulation succeeded. // Hand-mirrored from api-schemas' `ComposeUserProgramSimulationOkSchema`. export interface ComposeUserProgramSimulation { readonly status: 'ok'; readonly returnData: string; } // The solver-extractable fill (verified continuations, GD-8/GD-6, seam C5), // present on every compiled success. Hand-mirrored to api-schemas' `fill` // object (the OpenAPI source of truth; this package cannot depend on it). // `spends` is what the fill consumes per funding input; `validUntilMs` is the // fill freshness bound (earliest prepared-node expiry) — ABSENT = no expiry. // The fill is transaction-scoped; the leg-scoped C4 verification echo lives in // the sibling `verificationByNode` record. export interface ComposeFill { readonly spends: readonly SpendEntry[]; readonly validUntilMs?: number; } export interface ComposeCompileSuccessData extends ComposeContinuationData { // Every linear resource output port, consumed or terminal, keyed // `<nodeId>.<portName>`. See `Output` for the per-entry rules. Hand-mirrored // from api-schemas' `OutputSchema` (the OpenAPI source of truth; this // package cannot depend on it); the SDK decodes the wire strings to `bigint`. readonly outputs: Outputs; // The OpenAPI source of truth documents the optionality and funding modes. readonly transactionRequest?: ComposeTransactionRequest; readonly actions?: readonly ComposeAction[]; readonly userProxy: string; readonly priceImpact?: PriceImpact; readonly approvals?: readonly ApprovalEntry[]; // The per-(input, recipient) fee rows the compiled fill charges. Absent when // no fee applies. readonly fees?: readonly ComposeFee[]; // The optional user-program simulation echo, present only when the request // opted in via `run.simulateUserProgram` and the simulation succeeded. readonly userProgramSimulation?: ComposeUserProgramSimulation; // GD-8 settlement-fill surface (seam C5): the solver-extractable `fill`, // present on every success response — the funding legs it consumes and the // freshness bound (absent = no expiry). readonly fill?: ComposeFill; // The C4 verification echo, keyed by the flow node that carried the // commitment (the `continuation.commitment` node on a settlement // re-submission, the `continuation.settle` node on authoring-time provider // verification). Present only when the compile committed a validation // program; today at most one entry (the compiler rejects multi-node // committed verification). readonly verificationByNode?: Record<string, VerificationDescriptor>; } export interface ComposeCompilePartialData extends ComposeContinuationData { // Mirrors `ComposeCompileSuccessData.outputs`. A revert measured nothing, so // estimates are quotes and minimums are op-sourced. readonly outputs: Outputs; readonly transactionRequest: ComposeTransactionRequest; readonly userProxy: string; readonly simulationRevert: SimulationRevert; readonly approvals?: readonly ApprovalEntry[]; readonly actions?: readonly ComposeAction[]; // The per-(input, recipient) fee rows the compiled fill charges. Absent when // no fee applies. readonly fees?: readonly ComposeFee[]; // The optional user-program simulation echo, present only when the request // opted in via `run.simulateUserProgram` and the simulation succeeded. readonly userProgramSimulation?: ComposeUserProgramSimulation; } export type ComposeCompileResult = | (ComposeCompileSuccessData & { readonly status: 'success' }) | (ComposeCompilePartialData & { readonly status: 'partial'; readonly error: { readonly kind: string; readonly message: string }; });