@lifi/composer-sdk 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -3
- package/dist/authoring/FlowBuilderCore.cjs.map +1 -1
- package/dist/authoring/FlowBuilderCore.d.cts +11 -4
- package/dist/authoring/FlowBuilderCore.d.ts +11 -4
- package/dist/authoring/FlowBuilderCore.js.map +1 -1
- package/dist/authoring/handles.cjs.map +1 -1
- package/dist/authoring/handles.d.cts +2 -2
- package/dist/authoring/handles.d.ts +2 -2
- package/dist/authoring/handles.js.map +1 -1
- package/dist/authoring/raw.cjs +5 -3
- package/dist/authoring/raw.cjs.map +1 -1
- package/dist/authoring/raw.js +5 -3
- package/dist/authoring/raw.js.map +1 -1
- package/dist/client.cjs +94 -60
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +12 -4
- package/dist/client.d.ts +12 -4
- package/dist/client.js +98 -60
- package/dist/client.js.map +1 -1
- package/dist/errors.cjs +42 -3
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +67 -4
- package/dist/errors.d.ts +67 -4
- package/dist/errors.js +29 -2
- package/dist/errors.js.map +1 -1
- package/dist/generated/config.generated.cjs.map +1 -1
- package/dist/generated/config.generated.d.cts +46 -5
- package/dist/generated/config.generated.d.ts +46 -5
- package/dist/generated/operations.generated.cjs +4 -0
- package/dist/generated/operations.generated.cjs.map +1 -1
- package/dist/generated/operations.generated.d.cts +16 -2
- package/dist/generated/operations.generated.d.ts +16 -2
- package/dist/generated/operations.generated.js +4 -0
- package/dist/generated/operations.generated.js.map +1 -1
- package/dist/index.cjs +8 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/outputs.cjs +33 -0
- package/dist/outputs.cjs.map +1 -0
- package/dist/outputs.d.cts +10 -0
- package/dist/outputs.d.ts +10 -0
- package/dist/outputs.js +9 -0
- package/dist/outputs.js.map +1 -0
- package/dist/responseSchemas.cjs +3 -0
- package/dist/responseSchemas.cjs.map +1 -1
- package/dist/responseSchemas.d.cts +7 -4
- package/dist/responseSchemas.d.ts +7 -4
- package/dist/responseSchemas.js +3 -0
- package/dist/responseSchemas.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +16 -5
- package/dist/types.d.ts +16 -5
- package/package.json +4 -3
- package/src/authoring/FlowBuilderCore.ts +12 -3
- package/src/authoring/handles.ts +2 -1
- package/src/authoring/raw.ts +4 -3
- package/src/client.ts +177 -79
- package/src/errors.ts +116 -3
- package/src/examples/flySwap.ts +3 -3
- package/src/examples/lifiZapAsync.ts +8 -7
- package/src/examples/run.ts +6 -9
- package/src/examples/swapAndZap.ts +7 -0
- package/src/examples/swapWithAllowRevert.ts +13 -3
- package/src/generated/config.generated.ts +49 -4
- package/src/generated/operations.generated.ts +25 -0
- package/src/index.ts +21 -3
- package/src/outputs.ts +16 -0
- package/src/responseSchemas.ts +10 -4
- package/src/types.ts +16 -4
package/README.md
CHANGED
|
@@ -98,6 +98,14 @@ const result = await sdk.client.compile(request);
|
|
|
98
98
|
if (result.status === 'success') {
|
|
99
99
|
// Full success — transactionRequest includes gasLimit.
|
|
100
100
|
console.log(result.transactionRequest);
|
|
101
|
+
|
|
102
|
+
// What the flow produced, one entry per output port. The zap's output is
|
|
103
|
+
// terminal (nothing downstream spends it), so it carries the owner it is
|
|
104
|
+
// delivered to; the swap's output is `role: 'consumed'` by the zap.
|
|
105
|
+
const position = result.outputs['zap.amountOut'];
|
|
106
|
+
if (position?.role === 'terminal') {
|
|
107
|
+
console.log(position.owner, position.amount.estimate?.value);
|
|
108
|
+
}
|
|
101
109
|
} else {
|
|
102
110
|
// result.status === 'partial' — simulation reverted.
|
|
103
111
|
// Transaction is still available but without gasLimit.
|
|
@@ -119,6 +127,8 @@ if (result.status === 'success') {
|
|
|
119
127
|
|
|
120
128
|
**Guards** — Protect against slippage and other runtime conditions. Applied per-operation via the `guards` field.
|
|
121
129
|
|
|
130
|
+
**Outputs** — A compile result carries `outputs`, a record keyed `'<nodeId>.<portName>'` holding every resource output the flow produces. Each entry is `role: 'terminal'` (delivered to `owner`, with `delivery.when` telling you whether it lands with this transaction) or `role: 'consumed'` (spent by the node named in `consumedBy`), so narrow on `role` before reading either field. `amount.estimate` and `amount.minimum` are both optional: an estimate is absent when nothing measured or quoted the port, and a minimum is absent when no floor is enforced. `terminalOutputs(result.outputs)` narrows the record to the terminal entries. Full field reference: [docs/sdk-interface.md](./docs/sdk-interface.md#outputs).
|
|
131
|
+
|
|
122
132
|
## API surface
|
|
123
133
|
|
|
124
134
|
**SDK factory**
|
|
@@ -138,7 +148,7 @@ if (result.status === 'success') {
|
|
|
138
148
|
- `sdk.client.compile(request)` — sends the flow to the backend and returns a `ComposeCompileResult` (discriminated union: `status: 'success'` or `status: 'partial'`)
|
|
139
149
|
- `sdk.client.getManifest()` — fetches the operation manifest
|
|
140
150
|
- `sdk.client.getChains()` / `sdk.getSupportedChains()` — fetches the chains this deployment supports as `readonly ChainSummary[]` (`{ chainId, name }`), ascending by `chainId`. A chain is listed once the VM contract is confirmed deployed on it, which is the same condition `compile`, `route` and `simulate` validate against — so a chain missing from this list is rejected by those methods. The converse does not hold: a listed chain can still have no routing edge for a given pair, reported by `route` as `no_route_error`. `name` is a display label maintained by the deployment, so render it but key on `chainId`; a chain with no configured label reports `Chain <id>`. The list tracks the backend's chain registry, which refreshes periodically, and is not cached by the SDK.
|
|
141
|
-
- `sdk.client.getZapPacks(options?)` — fetches the available routing edges grouped by protocol, returning `ZapPackOverview[]`. The catalog is dynamic and is not cached by the SDK. Filter through `GetZapPacksOptions`. An edge with `recipient: 'required'` requires the zap's `recipient` binding, delivers the output externally, and produces an output that cannot be chained or swept. An edge with `availability: 'future'` produces an output that settles only after the initiating transaction; `route` compiles it for you, and on the authoring path it needs `lifi.zapAsync` with a bound `recipient`.
|
|
151
|
+
- `sdk.client.getZapPacks(options?)` — fetches the available routing edges grouped by protocol, returning `ZapPackOverview[]`. The catalog is dynamic and is not cached by the SDK. Filter through `GetZapPacksOptions`. An edge with `recipient: 'required'` requires the zap's `recipient` binding, delivers the output externally, and produces an output that cannot be chained or swept. An edge with `availability: 'future'` produces an output that settles only after the initiating transaction; `route` compiles it for you, and on the authoring path it needs `lifi.zapAsync` with a bound `recipient`. Delivery timing governs custody only — a future output still reports an `amount.estimate` (`basis: 'simulated'`, an in-transaction estimate; the delivered amount arrives after settlement), with an `amount.minimum` present only when a minimum source applied. The catalog publishes no settlement duration: a deferred output's ETA rides on the compile result as each future terminal output's `delivery.etaSeconds` in `outputs` (expected seconds until the proceeds land, present only on a `delivery.when: 'future'` output and only when the protocol publishes an estimate; absence means unknown, not zero).
|
|
142
152
|
- `sdk.client.simulate(request)` / `sdk.simulate(request)` — simulates a raw, pre-encoded transaction and returns a `SimulateResult` (discriminated union: `status: 'ok' | 'revert' | 'error'`). See [Simulating a raw transaction](#simulating-a-raw-transaction).
|
|
143
153
|
- `sdk.client.route(request)` / `sdk.route(request)` — compiles a single from/to token pair on one chain via `POST /compose/route`, returning the same `ComposeCompileResult` as `compile()`. See [Routing a token pair](#routing-a-token-pair).
|
|
144
154
|
|
|
@@ -198,7 +208,7 @@ for (const pack of packs) {
|
|
|
198
208
|
Every edge is one routable pair: `edge.in` and `edge.out` are the `fromToken` and `toToken` of a `route` call on `edge.in.chainId`, and `inAmountMin` / `inAmountMax` bound the amount when the protocol constrains it. Two edge fields change how you call `route`:
|
|
199
209
|
|
|
200
210
|
- **`recipient: 'required'`** — the protocol mints to a named receiver, so set `sweepTo` when the output should not land with the signer.
|
|
201
|
-
- **`availability: 'future'`** — the output only exists once the transaction settles. `route` skips these unless you pass `allowAsyncRoutes: true`, so by default a pair reachable only this way is a `no_route_error` and every
|
|
211
|
+
- **`availability: 'future'`** — the output only exists once the transaction settles. `route` skips these unless you pass `allowAsyncRoutes: true`, so by default a pair reachable only this way is a `no_route_error` and every terminal output delivers now (`delivery.when: 'now'`). Opt in and `sweepTo` names the future output's owner, no slippage floor is applied, and you must track settlement rather than treat the transaction as completing the job. A synchronous edge still wins whenever the pair has one, so read each terminal output's `delivery.when` in `result.outputs` to know which representation you got.
|
|
202
212
|
|
|
203
213
|
### Amounts
|
|
204
214
|
|
|
@@ -221,7 +231,7 @@ Both accept a `bigint` or a decimal string. `bigint` values are serialised for y
|
|
|
221
231
|
- **`checkOnChainAllowances`** — when `true`, the server reads current allowances and omits approvals that are already sufficient. Defaults to `false`.
|
|
222
232
|
- **`simulationPolicy`** — `'strict'` (default) or `'allow-revert'`, exactly as on the authoring path. See [Simulation policy and partial results](#simulation-policy-and-partial-results).
|
|
223
233
|
- **`simulateUserProgram`** — when `true`, additionally simulates the final user-facing transaction after the structured simulation succeeds. Defaults to `false`.
|
|
224
|
-
- **`allowAsyncRoutes`** — when `true`, accept a route whose output arrives only after the initiating transaction settles. Defaults to `false`, which leaves such a pair a `no_route_error` and guarantees every
|
|
234
|
+
- **`allowAsyncRoutes`** — when `true`, accept a route whose output arrives only after the initiating transaction settles. Defaults to `false`, which leaves such a pair a `no_route_error` and guarantees every terminal output delivers now (`delivery.when: 'now'`). Set it only if you track settlement and can live without a slippage floor.
|
|
225
235
|
|
|
226
236
|
### When to author a flow instead
|
|
227
237
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/authoring/FlowBuilderCore.ts"],"sourcesContent":["import type {\n AppliedGuard,\n BindValue,\n Call,\n Flow,\n FlowInput,\n Resource,\n SolType,\n} from '@lifi/compose-spec';\n\nimport type {\n InputDecl,\n InputSchema,\n OutputKind,\n TypedGuard,\n TypedLiteral,\n TypedRef,\n} from '../types.js';\n\nimport type {\n InputHandle,\n OutputHandle,\n ResourceInputHandle,\n} from './handles.js';\nimport { toBindValue } from './handles.js';\nimport { ref } from './raw.js';\n\n/**\n * Arguments for calling an operation node in a flow.\n */\nexport interface CallArgs {\n /** Maps parameter names to input/output handles or raw `$ref` pointers. */\n readonly bind: Record<string, AnyBindable>;\n /** Optional operation-specific configuration. */\n readonly config?: object;\n /** Optional guards (e.g. slippage checks) applied to this operation's outputs. */\n readonly guards?: readonly TypedGuard[];\n}\n\n/**\n * Any value that can be bound to an operation parameter: an input handle, an\n * output handle from a previous operation, a typed `$ref` pointer, or a typed\n * literal.\n *\n * Use `raw.ref<T>()` to create a typed ref from a raw path string, and\n * `raw.literal<T>()` to bake in a constant.\n */\nexport type AnyBindable = InputHandle | OutputHandle | TypedRef | TypedLiteral;\n\n/**\n * Provides references to runtime context values available inside a flow.\n * Access via `builder.context`.\n */\nexport interface ContextAccessor {\n /** A `$ref` pointing to the transaction sender (signer) address. */\n readonly sender: TypedRef<'address'>;\n /** A `$ref` pointing to the on-chain execution (proxy) address. */\n readonly executionAddress: TypedRef<'address'>;\n}\n\ntype InputHandleOf<D extends InputDecl> = D extends Resource\n ? ResourceInputHandle\n : D extends SolType\n ? InputHandle<D>\n : InputHandle;\n\n/**\n * A mapped type that converts an input schema into typed handles.\n * Resource inputs produce {@link ResourceInputHandle}; scalar inputs produce {@link InputHandle}.\n *\n * @typeParam T - The flow's input schema.\n */\nexport type InputHandles<T extends InputSchema> = {\n readonly [K in keyof T]: InputHandleOf<T[K]>;\n};\n\n/**\n * Options for creating a new flow builder.\n *\n * @typeParam T - The flow's input schema.\n */\nexport interface FlowOptions<T extends InputSchema> {\n /** Optional human-readable name for the flow. Defaults to a random UUID. */\n readonly name?: string;\n /** Input declarations mapping names to resource or scalar types. */\n readonly inputs: T;\n}\n\n/**\n * A Flow document branded with its input schema for type-safe request building.\n *\n * The `__inputs` field is a phantom type — it exists only at compile time for\n * TypeScript inference and is never present at runtime.\n */\nexport type TypedFlow<T extends InputSchema = InputSchema> = Flow & {\n readonly __inputs?: T;\n};\n\n/**\n * Core flow builder interface providing low-level access to flow construction.\n *\n * For most use cases, prefer the {@link FlowBuilder} type returned by `sdk.flow()`\n * which adds generated operation methods and a `compile` method.\n *\n * @typeParam T - The flow's input schema.\n */\nexport interface FlowBuilderCore<T extends InputSchema = InputSchema> {\n /** Runtime context references (sender address, execution address). */\n readonly context: ContextAccessor;\n /** Typed handles for each declared flow input, used to bind inputs to operations. */\n readonly inputs: InputHandles<T>;\n /**\n * Appends an untyped operation node to the flow. This is an escape hatch\n * for operations not yet covered by the generated methods.\n *\n * Use `raw.ref<T>()` to reference this node's outputs in subsequent typed\n * operations.\n *\n * @param id - Unique node identifier within the flow.\n * @param op - The operation name (e.g. `\"custom.vaultQuery\"`).\n * @param args - Bind map, config, and optional guards for the node.\n * @throws Error if a node with the same `id` already exists in the flow.\n */\n readonly untypedOp: (\n id: string,\n op: string,\n args: {\n readonly bind: Record<string, BindValue>;\n readonly config: Record<string, unknown>;\n readonly guards?: readonly AppliedGuard[];\n },\n ) => void;\n /** Serialises the builder state into a {@link TypedFlow} document. */\n readonly build: () => TypedFlow<T>;\n}\n\n/** Maps output port names to their output kind for compile-time and runtime validation. */\nexport type OutputSpec = Record<string, OutputKind>;\n\n/** Internal interface exposed to bindGeneratedOps — not part of the public API. */\nexport interface FlowBuilderInternal<\n T extends InputSchema = InputSchema,\n> extends FlowBuilderCore<T> {\n readonly call: <O extends OutputSpec>(\n nodeId: string,\n op: string,\n args: CallArgs,\n outputs: O,\n ) => { readonly [K in keyof O & string]: OutputHandle<O[K]> };\n}\n\nconst isResource = (decl: InputDecl): decl is Resource =>\n typeof decl === 'object' && decl !== null && 'kind' in decl;\n\n/**\n * Creates a new flow builder targeting the given chain.\n *\n * @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).\n * @param options - Flow configuration including input declarations.\n * @returns A {@link FlowBuilderInternal} instance.\n * @internal\n */\nexport const createFlowBuilderCore = <T extends InputSchema>(\n chainId: number,\n options: FlowOptions<T>,\n): FlowBuilderInternal<T> => {\n const id = options.name ?? crypto.randomUUID();\n const flowInputs: FlowInput[] = [];\n const nodes: Call[] = [];\n const nodeIds = new Set<string>();\n\n const inputHandles = {} as Record<string, InputHandle | ResourceInputHandle>;\n for (const [name, decl] of Object.entries(options.inputs)) {\n if (isResource(decl)) {\n if (decl.chainId !== chainId) {\n throw new Error(\n `Input \"${name}\" has chainId ${decl.chainId} but flow targets chain ${chainId}`,\n );\n }\n flowInputs.push({ name, resource: decl });\n inputHandles[name] = { _tag: 'input', inputName: name, resource: decl };\n } else {\n flowInputs.push({ name, type: decl });\n inputHandles[name] = { _tag: 'input', inputName: name };\n }\n }\n\n const call = <O extends OutputSpec>(\n nodeId: string,\n op: string,\n args: CallArgs,\n outputs: O,\n ): { readonly [K in keyof O & string]: OutputHandle<O[K]> } => {\n if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: \"${nodeId}\"`);\n nodeIds.add(nodeId);\n\n const bind: Record<string, BindValue> = {};\n for (const [key, val] of Object.entries(args.bind)) {\n bind[key] = toBindValue(val);\n }\n\n const node: Call = {\n id: nodeId,\n op,\n bind,\n config: (args.config ?? {}) as Record<string, unknown>,\n ...(args.guards && args.guards.length > 0 && { guards: args.guards }),\n };\n nodes.push(node);\n\n type Result = { readonly [K in keyof O & string]: OutputHandle<O[K]> };\n return new Proxy({} as Result, {\n get: (_target, prop): OutputHandle | undefined => {\n if (typeof prop !== 'string' || prop === 'then') return undefined;\n if (!(prop in outputs)) {\n throw new Error(\n `Op \"${op}\" has no output port \"${prop}\". Valid ports: ${Object.keys(\n outputs,\n ).join(', ')}`,\n );\n }\n return { _tag: 'output', nodeId, portName: prop };\n },\n });\n };\n\n const untypedOp = (\n nodeId: string,\n op: string,\n args: {\n readonly bind: Record<string, BindValue>;\n readonly config: Record<string, unknown>;\n readonly guards?: readonly AppliedGuard[];\n },\n ): void => {\n if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: \"${nodeId}\"`);\n nodeIds.add(nodeId);\n const node: Call = {\n id: nodeId,\n op,\n bind: args.bind,\n config: args.config,\n ...(args.guards && args.guards.length > 0 && { guards: args.guards }),\n };\n nodes.push(node);\n };\n\n const build = (): TypedFlow<T> => ({\n version: 1,\n id,\n chainId,\n inputs: [...flowInputs],\n nodes: [...nodes],\n });\n\n const context: ContextAccessor = {\n sender: ref<'address'>('context.sender'),\n executionAddress: ref<'address'>('context.executionAddress'),\n };\n\n return {\n context,\n inputs: inputHandles as InputHandles<T>,\n call,\n untypedOp,\n build,\n };\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/authoring/FlowBuilderCore.ts"],"sourcesContent":["import type {\n AppliedGuard,\n BindValue,\n Call,\n Flow,\n FlowInput,\n Ref,\n Resource,\n SolType,\n} from '@lifi/compose-spec';\n\nimport type {\n InputDecl,\n InputSchema,\n OutputKind,\n TypedGuard,\n TypedLiteral,\n TypedRef,\n} from '../types.js';\n\nimport type {\n InputHandle,\n OutputHandle,\n ResourceInputHandle,\n} from './handles.js';\nimport { toBindValue } from './handles.js';\nimport { ref } from './raw.js';\n\n/**\n * Arguments for calling an operation node in a flow.\n */\nexport interface CallArgs {\n /** Maps parameter names to input/output handles or raw `$ref` pointers. */\n readonly bind: Record<string, AnyBindable>;\n /** Optional operation-specific configuration. */\n readonly config?: object;\n /** Optional guards (e.g. slippage checks) applied to this operation's outputs. */\n readonly guards?: readonly TypedGuard[];\n}\n\n/**\n * Any value that can be bound to an operation parameter: an input handle, an\n * output handle from a previous operation, a typed `$ref` pointer, a typed\n * literal, or a bare `{ $ref }` pointer.\n *\n * This is the bind type of {@link FlowBuilderInternal.call}, the entry point\n * every generated operation lowers into — not a public authoring surface. A\n * bare `Ref` belongs here because a generated op resolves its own typed binds\n * to wire refs (`toBindRef` in `./signatureArgs.js`) before calling it. Typed\n * operation slots use `Bindable<T>`, which rejects a bare `Ref`; see\n * `RefBindable` in `./handles.js`.\n *\n * Use `raw.ref<T>()` to create a typed ref from a raw path string, and\n * `raw.literal<T>()` to bake in a constant.\n */\nexport type AnyBindable =\n InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref;\n\n/**\n * Provides references to runtime context values available inside a flow.\n * Access via `builder.context`.\n */\nexport interface ContextAccessor {\n /** A `$ref` pointing to the transaction sender (signer) address. */\n readonly sender: TypedRef<'address'>;\n /** A `$ref` pointing to the on-chain execution (proxy) address. */\n readonly executionAddress: TypedRef<'address'>;\n}\n\ntype InputHandleOf<D extends InputDecl> = D extends Resource\n ? ResourceInputHandle\n : D extends SolType\n ? InputHandle<D>\n : InputHandle;\n\n/**\n * A mapped type that converts an input schema into typed handles.\n * Resource inputs produce {@link ResourceInputHandle}; scalar inputs produce {@link InputHandle}.\n *\n * @typeParam T - The flow's input schema.\n */\nexport type InputHandles<T extends InputSchema> = {\n readonly [K in keyof T]: InputHandleOf<T[K]>;\n};\n\n/**\n * Options for creating a new flow builder.\n *\n * @typeParam T - The flow's input schema.\n */\nexport interface FlowOptions<T extends InputSchema> {\n /** Optional human-readable name for the flow. Defaults to a random UUID. */\n readonly name?: string;\n /** Input declarations mapping names to resource or scalar types. */\n readonly inputs: T;\n}\n\n/**\n * A Flow document branded with its input schema for type-safe request building.\n *\n * The `__inputs` field is a phantom type — it exists only at compile time for\n * TypeScript inference and is never present at runtime.\n */\nexport type TypedFlow<T extends InputSchema = InputSchema> = Flow & {\n readonly __inputs?: T;\n};\n\n/**\n * Core flow builder interface providing low-level access to flow construction.\n *\n * For most use cases, prefer the {@link FlowBuilder} type returned by `sdk.flow()`\n * which adds generated operation methods and a `compile` method.\n *\n * @typeParam T - The flow's input schema.\n */\nexport interface FlowBuilderCore<T extends InputSchema = InputSchema> {\n /** Runtime context references (sender address, execution address). */\n readonly context: ContextAccessor;\n /** Typed handles for each declared flow input, used to bind inputs to operations. */\n readonly inputs: InputHandles<T>;\n /**\n * Appends an untyped operation node to the flow. This is an escape hatch\n * for operations not yet covered by the generated methods.\n *\n * Use `raw.ref<T>()` to reference this node's outputs in subsequent typed\n * operations.\n *\n * @param id - Unique node identifier within the flow.\n * @param op - The operation name (e.g. `\"custom.vaultQuery\"`).\n * @param args - Bind map, config, and optional guards for the node.\n * @throws Error if a node with the same `id` already exists in the flow.\n */\n readonly untypedOp: (\n id: string,\n op: string,\n args: {\n readonly bind: Record<string, BindValue>;\n readonly config: Record<string, unknown>;\n readonly guards?: readonly AppliedGuard[];\n },\n ) => void;\n /** Serialises the builder state into a {@link TypedFlow} document. */\n readonly build: () => TypedFlow<T>;\n}\n\n/** Maps output port names to their output kind for compile-time and runtime validation. */\nexport type OutputSpec = Record<string, OutputKind>;\n\n/** Internal interface exposed to bindGeneratedOps — not part of the public API. */\nexport interface FlowBuilderInternal<\n T extends InputSchema = InputSchema,\n> extends FlowBuilderCore<T> {\n readonly call: <O extends OutputSpec>(\n nodeId: string,\n op: string,\n args: CallArgs,\n outputs: O,\n ) => { readonly [K in keyof O & string]: OutputHandle<O[K]> };\n}\n\nconst isResource = (decl: InputDecl): decl is Resource =>\n typeof decl === 'object' && decl !== null && 'kind' in decl;\n\n/**\n * Creates a new flow builder targeting the given chain.\n *\n * @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).\n * @param options - Flow configuration including input declarations.\n * @returns A {@link FlowBuilderInternal} instance.\n * @internal\n */\nexport const createFlowBuilderCore = <T extends InputSchema>(\n chainId: number,\n options: FlowOptions<T>,\n): FlowBuilderInternal<T> => {\n const id = options.name ?? crypto.randomUUID();\n const flowInputs: FlowInput[] = [];\n const nodes: Call[] = [];\n const nodeIds = new Set<string>();\n\n const inputHandles = {} as Record<string, InputHandle | ResourceInputHandle>;\n for (const [name, decl] of Object.entries(options.inputs)) {\n if (isResource(decl)) {\n if (decl.chainId !== chainId) {\n throw new Error(\n `Input \"${name}\" has chainId ${decl.chainId} but flow targets chain ${chainId}`,\n );\n }\n flowInputs.push({ name, resource: decl });\n inputHandles[name] = { _tag: 'input', inputName: name, resource: decl };\n } else {\n flowInputs.push({ name, type: decl });\n inputHandles[name] = { _tag: 'input', inputName: name };\n }\n }\n\n const call = <O extends OutputSpec>(\n nodeId: string,\n op: string,\n args: CallArgs,\n outputs: O,\n ): { readonly [K in keyof O & string]: OutputHandle<O[K]> } => {\n if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: \"${nodeId}\"`);\n nodeIds.add(nodeId);\n\n const bind: Record<string, BindValue> = {};\n for (const [key, val] of Object.entries(args.bind)) {\n bind[key] = toBindValue(val);\n }\n\n const node: Call = {\n id: nodeId,\n op,\n bind,\n config: (args.config ?? {}) as Record<string, unknown>,\n ...(args.guards && args.guards.length > 0 && { guards: args.guards }),\n };\n nodes.push(node);\n\n type Result = { readonly [K in keyof O & string]: OutputHandle<O[K]> };\n return new Proxy({} as Result, {\n get: (_target, prop): OutputHandle | undefined => {\n if (typeof prop !== 'string' || prop === 'then') return undefined;\n if (!(prop in outputs)) {\n throw new Error(\n `Op \"${op}\" has no output port \"${prop}\". Valid ports: ${Object.keys(\n outputs,\n ).join(', ')}`,\n );\n }\n return { _tag: 'output', nodeId, portName: prop };\n },\n });\n };\n\n const untypedOp = (\n nodeId: string,\n op: string,\n args: {\n readonly bind: Record<string, BindValue>;\n readonly config: Record<string, unknown>;\n readonly guards?: readonly AppliedGuard[];\n },\n ): void => {\n if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: \"${nodeId}\"`);\n nodeIds.add(nodeId);\n const node: Call = {\n id: nodeId,\n op,\n bind: args.bind,\n config: args.config,\n ...(args.guards && args.guards.length > 0 && { guards: args.guards }),\n };\n nodes.push(node);\n };\n\n const build = (): TypedFlow<T> => ({\n version: 1,\n id,\n chainId,\n inputs: [...flowInputs],\n nodes: [...nodes],\n });\n\n const context: ContextAccessor = {\n sender: ref<'address'>('context.sender'),\n executionAddress: ref<'address'>('context.executionAddress'),\n };\n\n return {\n context,\n inputs: inputHandles as InputHandles<T>,\n call,\n untypedOp,\n build,\n };\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Resource, SolType, BindValue, AppliedGuard, Flow } from '@lifi/compose-spec';
|
|
1
|
+
import { Ref, Resource, SolType, BindValue, AppliedGuard, Flow } from '@lifi/compose-spec';
|
|
2
2
|
import { TypedRef, TypedLiteral, InputSchema, InputDecl, TypedGuard, OutputKind } from '../types.cjs';
|
|
3
3
|
import { InputHandle, OutputHandle, ResourceInputHandle } from './handles.cjs';
|
|
4
4
|
|
|
@@ -15,13 +15,20 @@ interface CallArgs {
|
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* Any value that can be bound to an operation parameter: an input handle, an
|
|
18
|
-
* output handle from a previous operation, a typed `$ref` pointer,
|
|
19
|
-
* literal.
|
|
18
|
+
* output handle from a previous operation, a typed `$ref` pointer, a typed
|
|
19
|
+
* literal, or a bare `{ $ref }` pointer.
|
|
20
|
+
*
|
|
21
|
+
* This is the bind type of {@link FlowBuilderInternal.call}, the entry point
|
|
22
|
+
* every generated operation lowers into — not a public authoring surface. A
|
|
23
|
+
* bare `Ref` belongs here because a generated op resolves its own typed binds
|
|
24
|
+
* to wire refs (`toBindRef` in `./signatureArgs.js`) before calling it. Typed
|
|
25
|
+
* operation slots use `Bindable<T>`, which rejects a bare `Ref`; see
|
|
26
|
+
* `RefBindable` in `./handles.js`.
|
|
20
27
|
*
|
|
21
28
|
* Use `raw.ref<T>()` to create a typed ref from a raw path string, and
|
|
22
29
|
* `raw.literal<T>()` to bake in a constant.
|
|
23
30
|
*/
|
|
24
|
-
type AnyBindable = InputHandle | OutputHandle | TypedRef | TypedLiteral;
|
|
31
|
+
type AnyBindable = InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref;
|
|
25
32
|
/**
|
|
26
33
|
* Provides references to runtime context values available inside a flow.
|
|
27
34
|
* Access via `builder.context`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Resource, SolType, BindValue, AppliedGuard, Flow } from '@lifi/compose-spec';
|
|
1
|
+
import { Ref, Resource, SolType, BindValue, AppliedGuard, Flow } from '@lifi/compose-spec';
|
|
2
2
|
import { TypedRef, TypedLiteral, InputSchema, InputDecl, TypedGuard, OutputKind } from '../types.js';
|
|
3
3
|
import { InputHandle, OutputHandle, ResourceInputHandle } from './handles.js';
|
|
4
4
|
|
|
@@ -15,13 +15,20 @@ interface CallArgs {
|
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* Any value that can be bound to an operation parameter: an input handle, an
|
|
18
|
-
* output handle from a previous operation, a typed `$ref` pointer,
|
|
19
|
-
* literal.
|
|
18
|
+
* output handle from a previous operation, a typed `$ref` pointer, a typed
|
|
19
|
+
* literal, or a bare `{ $ref }` pointer.
|
|
20
|
+
*
|
|
21
|
+
* This is the bind type of {@link FlowBuilderInternal.call}, the entry point
|
|
22
|
+
* every generated operation lowers into — not a public authoring surface. A
|
|
23
|
+
* bare `Ref` belongs here because a generated op resolves its own typed binds
|
|
24
|
+
* to wire refs (`toBindRef` in `./signatureArgs.js`) before calling it. Typed
|
|
25
|
+
* operation slots use `Bindable<T>`, which rejects a bare `Ref`; see
|
|
26
|
+
* `RefBindable` in `./handles.js`.
|
|
20
27
|
*
|
|
21
28
|
* Use `raw.ref<T>()` to create a typed ref from a raw path string, and
|
|
22
29
|
* `raw.literal<T>()` to bake in a constant.
|
|
23
30
|
*/
|
|
24
|
-
type AnyBindable = InputHandle | OutputHandle | TypedRef | TypedLiteral;
|
|
31
|
+
type AnyBindable = InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref;
|
|
25
32
|
/**
|
|
26
33
|
* Provides references to runtime context values available inside a flow.
|
|
27
34
|
* Access via `builder.context`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/authoring/FlowBuilderCore.ts"],"sourcesContent":["import type {\n AppliedGuard,\n BindValue,\n Call,\n Flow,\n FlowInput,\n Resource,\n SolType,\n} from '@lifi/compose-spec';\n\nimport type {\n InputDecl,\n InputSchema,\n OutputKind,\n TypedGuard,\n TypedLiteral,\n TypedRef,\n} from '../types.js';\n\nimport type {\n InputHandle,\n OutputHandle,\n ResourceInputHandle,\n} from './handles.js';\nimport { toBindValue } from './handles.js';\nimport { ref } from './raw.js';\n\n/**\n * Arguments for calling an operation node in a flow.\n */\nexport interface CallArgs {\n /** Maps parameter names to input/output handles or raw `$ref` pointers. */\n readonly bind: Record<string, AnyBindable>;\n /** Optional operation-specific configuration. */\n readonly config?: object;\n /** Optional guards (e.g. slippage checks) applied to this operation's outputs. */\n readonly guards?: readonly TypedGuard[];\n}\n\n/**\n * Any value that can be bound to an operation parameter: an input handle, an\n * output handle from a previous operation, a typed `$ref` pointer, or a typed\n * literal.\n *\n * Use `raw.ref<T>()` to create a typed ref from a raw path string, and\n * `raw.literal<T>()` to bake in a constant.\n */\nexport type AnyBindable = InputHandle | OutputHandle | TypedRef | TypedLiteral;\n\n/**\n * Provides references to runtime context values available inside a flow.\n * Access via `builder.context`.\n */\nexport interface ContextAccessor {\n /** A `$ref` pointing to the transaction sender (signer) address. */\n readonly sender: TypedRef<'address'>;\n /** A `$ref` pointing to the on-chain execution (proxy) address. */\n readonly executionAddress: TypedRef<'address'>;\n}\n\ntype InputHandleOf<D extends InputDecl> = D extends Resource\n ? ResourceInputHandle\n : D extends SolType\n ? InputHandle<D>\n : InputHandle;\n\n/**\n * A mapped type that converts an input schema into typed handles.\n * Resource inputs produce {@link ResourceInputHandle}; scalar inputs produce {@link InputHandle}.\n *\n * @typeParam T - The flow's input schema.\n */\nexport type InputHandles<T extends InputSchema> = {\n readonly [K in keyof T]: InputHandleOf<T[K]>;\n};\n\n/**\n * Options for creating a new flow builder.\n *\n * @typeParam T - The flow's input schema.\n */\nexport interface FlowOptions<T extends InputSchema> {\n /** Optional human-readable name for the flow. Defaults to a random UUID. */\n readonly name?: string;\n /** Input declarations mapping names to resource or scalar types. */\n readonly inputs: T;\n}\n\n/**\n * A Flow document branded with its input schema for type-safe request building.\n *\n * The `__inputs` field is a phantom type — it exists only at compile time for\n * TypeScript inference and is never present at runtime.\n */\nexport type TypedFlow<T extends InputSchema = InputSchema> = Flow & {\n readonly __inputs?: T;\n};\n\n/**\n * Core flow builder interface providing low-level access to flow construction.\n *\n * For most use cases, prefer the {@link FlowBuilder} type returned by `sdk.flow()`\n * which adds generated operation methods and a `compile` method.\n *\n * @typeParam T - The flow's input schema.\n */\nexport interface FlowBuilderCore<T extends InputSchema = InputSchema> {\n /** Runtime context references (sender address, execution address). */\n readonly context: ContextAccessor;\n /** Typed handles for each declared flow input, used to bind inputs to operations. */\n readonly inputs: InputHandles<T>;\n /**\n * Appends an untyped operation node to the flow. This is an escape hatch\n * for operations not yet covered by the generated methods.\n *\n * Use `raw.ref<T>()` to reference this node's outputs in subsequent typed\n * operations.\n *\n * @param id - Unique node identifier within the flow.\n * @param op - The operation name (e.g. `\"custom.vaultQuery\"`).\n * @param args - Bind map, config, and optional guards for the node.\n * @throws Error if a node with the same `id` already exists in the flow.\n */\n readonly untypedOp: (\n id: string,\n op: string,\n args: {\n readonly bind: Record<string, BindValue>;\n readonly config: Record<string, unknown>;\n readonly guards?: readonly AppliedGuard[];\n },\n ) => void;\n /** Serialises the builder state into a {@link TypedFlow} document. */\n readonly build: () => TypedFlow<T>;\n}\n\n/** Maps output port names to their output kind for compile-time and runtime validation. */\nexport type OutputSpec = Record<string, OutputKind>;\n\n/** Internal interface exposed to bindGeneratedOps — not part of the public API. */\nexport interface FlowBuilderInternal<\n T extends InputSchema = InputSchema,\n> extends FlowBuilderCore<T> {\n readonly call: <O extends OutputSpec>(\n nodeId: string,\n op: string,\n args: CallArgs,\n outputs: O,\n ) => { readonly [K in keyof O & string]: OutputHandle<O[K]> };\n}\n\nconst isResource = (decl: InputDecl): decl is Resource =>\n typeof decl === 'object' && decl !== null && 'kind' in decl;\n\n/**\n * Creates a new flow builder targeting the given chain.\n *\n * @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).\n * @param options - Flow configuration including input declarations.\n * @returns A {@link FlowBuilderInternal} instance.\n * @internal\n */\nexport const createFlowBuilderCore = <T extends InputSchema>(\n chainId: number,\n options: FlowOptions<T>,\n): FlowBuilderInternal<T> => {\n const id = options.name ?? crypto.randomUUID();\n const flowInputs: FlowInput[] = [];\n const nodes: Call[] = [];\n const nodeIds = new Set<string>();\n\n const inputHandles = {} as Record<string, InputHandle | ResourceInputHandle>;\n for (const [name, decl] of Object.entries(options.inputs)) {\n if (isResource(decl)) {\n if (decl.chainId !== chainId) {\n throw new Error(\n `Input \"${name}\" has chainId ${decl.chainId} but flow targets chain ${chainId}`,\n );\n }\n flowInputs.push({ name, resource: decl });\n inputHandles[name] = { _tag: 'input', inputName: name, resource: decl };\n } else {\n flowInputs.push({ name, type: decl });\n inputHandles[name] = { _tag: 'input', inputName: name };\n }\n }\n\n const call = <O extends OutputSpec>(\n nodeId: string,\n op: string,\n args: CallArgs,\n outputs: O,\n ): { readonly [K in keyof O & string]: OutputHandle<O[K]> } => {\n if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: \"${nodeId}\"`);\n nodeIds.add(nodeId);\n\n const bind: Record<string, BindValue> = {};\n for (const [key, val] of Object.entries(args.bind)) {\n bind[key] = toBindValue(val);\n }\n\n const node: Call = {\n id: nodeId,\n op,\n bind,\n config: (args.config ?? {}) as Record<string, unknown>,\n ...(args.guards && args.guards.length > 0 && { guards: args.guards }),\n };\n nodes.push(node);\n\n type Result = { readonly [K in keyof O & string]: OutputHandle<O[K]> };\n return new Proxy({} as Result, {\n get: (_target, prop): OutputHandle | undefined => {\n if (typeof prop !== 'string' || prop === 'then') return undefined;\n if (!(prop in outputs)) {\n throw new Error(\n `Op \"${op}\" has no output port \"${prop}\". Valid ports: ${Object.keys(\n outputs,\n ).join(', ')}`,\n );\n }\n return { _tag: 'output', nodeId, portName: prop };\n },\n });\n };\n\n const untypedOp = (\n nodeId: string,\n op: string,\n args: {\n readonly bind: Record<string, BindValue>;\n readonly config: Record<string, unknown>;\n readonly guards?: readonly AppliedGuard[];\n },\n ): void => {\n if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: \"${nodeId}\"`);\n nodeIds.add(nodeId);\n const node: Call = {\n id: nodeId,\n op,\n bind: args.bind,\n config: args.config,\n ...(args.guards && args.guards.length > 0 && { guards: args.guards }),\n };\n nodes.push(node);\n };\n\n const build = (): TypedFlow<T> => ({\n version: 1,\n id,\n chainId,\n inputs: [...flowInputs],\n nodes: [...nodes],\n });\n\n const context: ContextAccessor = {\n sender: ref<'address'>('context.sender'),\n executionAddress: ref<'address'>('context.executionAddress'),\n };\n\n return {\n context,\n inputs: inputHandles as InputHandles<T>,\n call,\n untypedOp,\n build,\n };\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/authoring/FlowBuilderCore.ts"],"sourcesContent":["import type {\n AppliedGuard,\n BindValue,\n Call,\n Flow,\n FlowInput,\n Ref,\n Resource,\n SolType,\n} from '@lifi/compose-spec';\n\nimport type {\n InputDecl,\n InputSchema,\n OutputKind,\n TypedGuard,\n TypedLiteral,\n TypedRef,\n} from '../types.js';\n\nimport type {\n InputHandle,\n OutputHandle,\n ResourceInputHandle,\n} from './handles.js';\nimport { toBindValue } from './handles.js';\nimport { ref } from './raw.js';\n\n/**\n * Arguments for calling an operation node in a flow.\n */\nexport interface CallArgs {\n /** Maps parameter names to input/output handles or raw `$ref` pointers. */\n readonly bind: Record<string, AnyBindable>;\n /** Optional operation-specific configuration. */\n readonly config?: object;\n /** Optional guards (e.g. slippage checks) applied to this operation's outputs. */\n readonly guards?: readonly TypedGuard[];\n}\n\n/**\n * Any value that can be bound to an operation parameter: an input handle, an\n * output handle from a previous operation, a typed `$ref` pointer, a typed\n * literal, or a bare `{ $ref }` pointer.\n *\n * This is the bind type of {@link FlowBuilderInternal.call}, the entry point\n * every generated operation lowers into — not a public authoring surface. A\n * bare `Ref` belongs here because a generated op resolves its own typed binds\n * to wire refs (`toBindRef` in `./signatureArgs.js`) before calling it. Typed\n * operation slots use `Bindable<T>`, which rejects a bare `Ref`; see\n * `RefBindable` in `./handles.js`.\n *\n * Use `raw.ref<T>()` to create a typed ref from a raw path string, and\n * `raw.literal<T>()` to bake in a constant.\n */\nexport type AnyBindable =\n InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref;\n\n/**\n * Provides references to runtime context values available inside a flow.\n * Access via `builder.context`.\n */\nexport interface ContextAccessor {\n /** A `$ref` pointing to the transaction sender (signer) address. */\n readonly sender: TypedRef<'address'>;\n /** A `$ref` pointing to the on-chain execution (proxy) address. */\n readonly executionAddress: TypedRef<'address'>;\n}\n\ntype InputHandleOf<D extends InputDecl> = D extends Resource\n ? ResourceInputHandle\n : D extends SolType\n ? InputHandle<D>\n : InputHandle;\n\n/**\n * A mapped type that converts an input schema into typed handles.\n * Resource inputs produce {@link ResourceInputHandle}; scalar inputs produce {@link InputHandle}.\n *\n * @typeParam T - The flow's input schema.\n */\nexport type InputHandles<T extends InputSchema> = {\n readonly [K in keyof T]: InputHandleOf<T[K]>;\n};\n\n/**\n * Options for creating a new flow builder.\n *\n * @typeParam T - The flow's input schema.\n */\nexport interface FlowOptions<T extends InputSchema> {\n /** Optional human-readable name for the flow. Defaults to a random UUID. */\n readonly name?: string;\n /** Input declarations mapping names to resource or scalar types. */\n readonly inputs: T;\n}\n\n/**\n * A Flow document branded with its input schema for type-safe request building.\n *\n * The `__inputs` field is a phantom type — it exists only at compile time for\n * TypeScript inference and is never present at runtime.\n */\nexport type TypedFlow<T extends InputSchema = InputSchema> = Flow & {\n readonly __inputs?: T;\n};\n\n/**\n * Core flow builder interface providing low-level access to flow construction.\n *\n * For most use cases, prefer the {@link FlowBuilder} type returned by `sdk.flow()`\n * which adds generated operation methods and a `compile` method.\n *\n * @typeParam T - The flow's input schema.\n */\nexport interface FlowBuilderCore<T extends InputSchema = InputSchema> {\n /** Runtime context references (sender address, execution address). */\n readonly context: ContextAccessor;\n /** Typed handles for each declared flow input, used to bind inputs to operations. */\n readonly inputs: InputHandles<T>;\n /**\n * Appends an untyped operation node to the flow. This is an escape hatch\n * for operations not yet covered by the generated methods.\n *\n * Use `raw.ref<T>()` to reference this node's outputs in subsequent typed\n * operations.\n *\n * @param id - Unique node identifier within the flow.\n * @param op - The operation name (e.g. `\"custom.vaultQuery\"`).\n * @param args - Bind map, config, and optional guards for the node.\n * @throws Error if a node with the same `id` already exists in the flow.\n */\n readonly untypedOp: (\n id: string,\n op: string,\n args: {\n readonly bind: Record<string, BindValue>;\n readonly config: Record<string, unknown>;\n readonly guards?: readonly AppliedGuard[];\n },\n ) => void;\n /** Serialises the builder state into a {@link TypedFlow} document. */\n readonly build: () => TypedFlow<T>;\n}\n\n/** Maps output port names to their output kind for compile-time and runtime validation. */\nexport type OutputSpec = Record<string, OutputKind>;\n\n/** Internal interface exposed to bindGeneratedOps — not part of the public API. */\nexport interface FlowBuilderInternal<\n T extends InputSchema = InputSchema,\n> extends FlowBuilderCore<T> {\n readonly call: <O extends OutputSpec>(\n nodeId: string,\n op: string,\n args: CallArgs,\n outputs: O,\n ) => { readonly [K in keyof O & string]: OutputHandle<O[K]> };\n}\n\nconst isResource = (decl: InputDecl): decl is Resource =>\n typeof decl === 'object' && decl !== null && 'kind' in decl;\n\n/**\n * Creates a new flow builder targeting the given chain.\n *\n * @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).\n * @param options - Flow configuration including input declarations.\n * @returns A {@link FlowBuilderInternal} instance.\n * @internal\n */\nexport const createFlowBuilderCore = <T extends InputSchema>(\n chainId: number,\n options: FlowOptions<T>,\n): FlowBuilderInternal<T> => {\n const id = options.name ?? crypto.randomUUID();\n const flowInputs: FlowInput[] = [];\n const nodes: Call[] = [];\n const nodeIds = new Set<string>();\n\n const inputHandles = {} as Record<string, InputHandle | ResourceInputHandle>;\n for (const [name, decl] of Object.entries(options.inputs)) {\n if (isResource(decl)) {\n if (decl.chainId !== chainId) {\n throw new Error(\n `Input \"${name}\" has chainId ${decl.chainId} but flow targets chain ${chainId}`,\n );\n }\n flowInputs.push({ name, resource: decl });\n inputHandles[name] = { _tag: 'input', inputName: name, resource: decl };\n } else {\n flowInputs.push({ name, type: decl });\n inputHandles[name] = { _tag: 'input', inputName: name };\n }\n }\n\n const call = <O extends OutputSpec>(\n nodeId: string,\n op: string,\n args: CallArgs,\n outputs: O,\n ): { readonly [K in keyof O & string]: OutputHandle<O[K]> } => {\n if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: \"${nodeId}\"`);\n nodeIds.add(nodeId);\n\n const bind: Record<string, BindValue> = {};\n for (const [key, val] of Object.entries(args.bind)) {\n bind[key] = toBindValue(val);\n }\n\n const node: Call = {\n id: nodeId,\n op,\n bind,\n config: (args.config ?? {}) as Record<string, unknown>,\n ...(args.guards && args.guards.length > 0 && { guards: args.guards }),\n };\n nodes.push(node);\n\n type Result = { readonly [K in keyof O & string]: OutputHandle<O[K]> };\n return new Proxy({} as Result, {\n get: (_target, prop): OutputHandle | undefined => {\n if (typeof prop !== 'string' || prop === 'then') return undefined;\n if (!(prop in outputs)) {\n throw new Error(\n `Op \"${op}\" has no output port \"${prop}\". Valid ports: ${Object.keys(\n outputs,\n ).join(', ')}`,\n );\n }\n return { _tag: 'output', nodeId, portName: prop };\n },\n });\n };\n\n const untypedOp = (\n nodeId: string,\n op: string,\n args: {\n readonly bind: Record<string, BindValue>;\n readonly config: Record<string, unknown>;\n readonly guards?: readonly AppliedGuard[];\n },\n ): void => {\n if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: \"${nodeId}\"`);\n nodeIds.add(nodeId);\n const node: Call = {\n id: nodeId,\n op,\n bind: args.bind,\n config: args.config,\n ...(args.guards && args.guards.length > 0 && { guards: args.guards }),\n };\n nodes.push(node);\n };\n\n const build = (): TypedFlow<T> => ({\n version: 1,\n id,\n chainId,\n inputs: [...flowInputs],\n nodes: [...nodes],\n });\n\n const context: ContextAccessor = {\n sender: ref<'address'>('context.sender'),\n executionAddress: ref<'address'>('context.executionAddress'),\n };\n\n return {\n context,\n inputs: inputHandles as InputHandles<T>,\n call,\n untypedOp,\n build,\n };\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/authoring/handles.ts"],"sourcesContent":["import type {\n BindValue,\n Resource,\n SolType,\n StaticSolType,\n} from '@lifi/compose-spec';\n\nimport type { OutputKind, TypedLiteral, TypedRef } from '../types.js';\n\n/**\n * A handle referencing a flow input declared in the flow's input schema.\n * The phantom `__outputKind` field carries the type parameter through\n * TypeScript's structural type system without affecting runtime shape.\n */\nexport interface InputHandle<T extends OutputKind = OutputKind> {\n readonly _tag: 'input';\n readonly inputName: string;\n readonly __outputKind?: T;\n}\n\n/**\n * An input handle for a resource (token) input, carrying the resource\n * declaration alongside the reference.\n */\nexport interface ResourceInputHandle extends InputHandle<'resource'> {\n readonly resource: Resource;\n}\n\n/**\n * A handle referencing an output port of a previously declared operation node.\n * The phantom `__outputKind` field carries the type parameter through\n * TypeScript's structural type system without affecting runtime shape.\n */\nexport interface OutputHandle<T extends OutputKind = OutputKind> {\n readonly _tag: 'output';\n readonly nodeId: string;\n readonly portName: string;\n readonly __outputKind?: T;\n}\n\n/** Discriminated union of all handle types that can be bound to operation arguments. */\nexport type AnyHandle = InputHandle | OutputHandle;\n\n/** Type guard that narrows an {@link AnyHandle} to an {@link InputHandle}. */\nexport const isInputHandle = (h: AnyHandle): h is InputHandle =>\n h._tag === 'input';\n\n/** Type guard that narrows an {@link AnyHandle} to an {@link OutputHandle}. */\nexport const isOutputHandle = (h: AnyHandle): h is OutputHandle =>\n h._tag === 'output';\n\n/**\n * Converts a handle to a JSON `$ref` pointer used in the flow document.\n * Input handles become `\"input.<name>\"`; output handles become `\"<nodeId>.<port>\"`.\n */\nexport const handleToRef = (h: AnyHandle): { $ref: string } => {\n if (h._tag === 'input') {\n if (!h.inputName) throw new Error('InputHandle has empty inputName');\n return { $ref: `input.${h.inputName}` };\n }\n if (!h.nodeId) throw new Error('OutputHandle has empty nodeId');\n if (!h.portName) throw new Error('OutputHandle has empty portName');\n return { $ref: `${h.nodeId}.${h.portName}` };\n};\n\n/**\n * For a bind slot expecting type T, widen the set of accepted handle types:\n * - `'bytes32'` is the raw 32-byte word type: accept any static-32-byte handle\n * (`uint256`/`uintN`/`address`/`bool`/`bytes32`) plus `'resource'` (a uint256\n * amount). At the IR1 boundary every value is a type-erased word, so any\n * static-32-byte handle is a sound bind for a `bytes32` payload port.\n * - `'uint256'` keeps its existing widening to also accept `'resource'`-tagged\n * handles (resources are uint256 amounts).\n * - every other type keeps exact-SolType matching.\n */\ntype SlotAssignable<T extends OutputKind> = T extends 'bytes32'\n ? StaticSolType | 'resource'\n : T extends 'uint256'\n ? T | 'resource'\n : T;\n\n/**\n * The values accepted by a typed slot that must resolve to a `$ref`:\n * - `OutputHandle<T>` / `InputHandle<T>` (same type)\n * - For `'uint256'` slots, also `'resource'`-tagged handles\n * - For `'bytes32'` slots, any static-32-byte handle (and `'resource'`)\n * - `TypedRef<T>` (typed context refs, subject to `SlotAssignable`)\n *\n * Plain `{ $ref: '...' }` objects are **not** accepted - use `raw.ref<T>()`\n * to create a typed ref when you need to reference a raw path.\n */\nexport type RefBindable<T extends OutputKind> =\n | OutputHandle<SlotAssignable<T>>\n | InputHandle<SlotAssignable<T>>\n | TypedRef<SlotAssignable<T>>;\n\n/**\n * Any ref-resolving bindable, with no per-slot type constraint.\n */\nexport type AnyRefBindable = InputHandle | OutputHandle | TypedRef;\n\n/**\n * The set of values accepted by a typed operation bind slot: everything\n * {@link RefBindable} accepts, plus a {@link TypedLiteral} constant baked\n * into the flow document. A `'resource'` slot rejects a literal: a token\n * resource is not a scalar constant.\n *\n * Use `raw.literal<T>()` to create one.\n */\nexport type Bindable<T extends OutputKind> =\n RefBindable<T> | LiteralBindable<SlotAssignable<T>>;\n\n// Distributes over the slot's assignable kinds and keeps the scalar ones: a\n// `'resource'` slot has no scalar arm, so its literal arm collapses to\n// `never` and a literal is rejected outright.\ntype LiteralBindable<K extends OutputKind> = K extends SolType\n ? TypedLiteral<K>\n : never;\n\n/**\n * Converts a bindable to the wire `bind` value it denotes: handles become\n * `$ref` pointers, refs and literals pass through as-is.\n */\nexport const toBindValue = (\n bindable: InputHandle | OutputHandle | TypedRef | TypedLiteral,\n): BindValue => ('_tag' in bindable ? handleToRef(bindable) : bindable);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
1
|
+
{"version":3,"sources":["../../src/authoring/handles.ts"],"sourcesContent":["import type {\n BindValue,\n Ref,\n Resource,\n SolType,\n StaticSolType,\n} from '@lifi/compose-spec';\n\nimport type { OutputKind, TypedLiteral, TypedRef } from '../types.js';\n\n/**\n * A handle referencing a flow input declared in the flow's input schema.\n * The phantom `__outputKind` field carries the type parameter through\n * TypeScript's structural type system without affecting runtime shape.\n */\nexport interface InputHandle<T extends OutputKind = OutputKind> {\n readonly _tag: 'input';\n readonly inputName: string;\n readonly __outputKind?: T;\n}\n\n/**\n * An input handle for a resource (token) input, carrying the resource\n * declaration alongside the reference.\n */\nexport interface ResourceInputHandle extends InputHandle<'resource'> {\n readonly resource: Resource;\n}\n\n/**\n * A handle referencing an output port of a previously declared operation node.\n * The phantom `__outputKind` field carries the type parameter through\n * TypeScript's structural type system without affecting runtime shape.\n */\nexport interface OutputHandle<T extends OutputKind = OutputKind> {\n readonly _tag: 'output';\n readonly nodeId: string;\n readonly portName: string;\n readonly __outputKind?: T;\n}\n\n/** Discriminated union of all handle types that can be bound to operation arguments. */\nexport type AnyHandle = InputHandle | OutputHandle;\n\n/** Type guard that narrows an {@link AnyHandle} to an {@link InputHandle}. */\nexport const isInputHandle = (h: AnyHandle): h is InputHandle =>\n h._tag === 'input';\n\n/** Type guard that narrows an {@link AnyHandle} to an {@link OutputHandle}. */\nexport const isOutputHandle = (h: AnyHandle): h is OutputHandle =>\n h._tag === 'output';\n\n/**\n * Converts a handle to a JSON `$ref` pointer used in the flow document.\n * Input handles become `\"input.<name>\"`; output handles become `\"<nodeId>.<port>\"`.\n */\nexport const handleToRef = (h: AnyHandle): { $ref: string } => {\n if (h._tag === 'input') {\n if (!h.inputName) throw new Error('InputHandle has empty inputName');\n return { $ref: `input.${h.inputName}` };\n }\n if (!h.nodeId) throw new Error('OutputHandle has empty nodeId');\n if (!h.portName) throw new Error('OutputHandle has empty portName');\n return { $ref: `${h.nodeId}.${h.portName}` };\n};\n\n/**\n * For a bind slot expecting type T, widen the set of accepted handle types:\n * - `'bytes32'` is the raw 32-byte word type: accept any static-32-byte handle\n * (`uint256`/`uintN`/`address`/`bool`/`bytes32`) plus `'resource'` (a uint256\n * amount). At the IR1 boundary every value is a type-erased word, so any\n * static-32-byte handle is a sound bind for a `bytes32` payload port.\n * - `'uint256'` keeps its existing widening to also accept `'resource'`-tagged\n * handles (resources are uint256 amounts).\n * - every other type keeps exact-SolType matching.\n */\ntype SlotAssignable<T extends OutputKind> = T extends 'bytes32'\n ? StaticSolType | 'resource'\n : T extends 'uint256'\n ? T | 'resource'\n : T;\n\n/**\n * The values accepted by a typed slot that must resolve to a `$ref`:\n * - `OutputHandle<T>` / `InputHandle<T>` (same type)\n * - For `'uint256'` slots, also `'resource'`-tagged handles\n * - For `'bytes32'` slots, any static-32-byte handle (and `'resource'`)\n * - `TypedRef<T>` (typed context refs, subject to `SlotAssignable`)\n *\n * Plain `{ $ref: '...' }` objects are **not** accepted - use `raw.ref<T>()`\n * to create a typed ref when you need to reference a raw path.\n */\nexport type RefBindable<T extends OutputKind> =\n | OutputHandle<SlotAssignable<T>>\n | InputHandle<SlotAssignable<T>>\n | TypedRef<SlotAssignable<T>>;\n\n/**\n * Any ref-resolving bindable, with no per-slot type constraint.\n */\nexport type AnyRefBindable = InputHandle | OutputHandle | TypedRef;\n\n/**\n * The set of values accepted by a typed operation bind slot: everything\n * {@link RefBindable} accepts, plus a {@link TypedLiteral} constant baked\n * into the flow document. A `'resource'` slot rejects a literal: a token\n * resource is not a scalar constant.\n *\n * Use `raw.literal<T>()` to create one.\n */\nexport type Bindable<T extends OutputKind> =\n RefBindable<T> | LiteralBindable<SlotAssignable<T>>;\n\n// Distributes over the slot's assignable kinds and keeps the scalar ones: a\n// `'resource'` slot has no scalar arm, so its literal arm collapses to\n// `never` and a literal is rejected outright.\ntype LiteralBindable<K extends OutputKind> = K extends SolType\n ? TypedLiteral<K>\n : never;\n\n/**\n * Converts a bindable to the wire `bind` value it denotes: handles become\n * `$ref` pointers, refs and literals pass through as-is.\n */\nexport const toBindValue = (\n bindable: InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref,\n): BindValue => ('_tag' in bindable ? handleToRef(bindable) : bindable);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6CO,MAAM,gBAAgB,CAAC,MAC5B,EAAE,SAAS;AAGN,MAAM,iBAAiB,CAAC,MAC7B,EAAE,SAAS;AAMN,MAAM,cAAc,CAAC,MAAmC;AAC7D,MAAI,EAAE,SAAS,SAAS;AACtB,QAAI,CAAC,EAAE,UAAW,OAAM,IAAI,MAAM,iCAAiC;AACnE,WAAO,EAAE,MAAM,SAAS,EAAE,SAAS,GAAG;AAAA,EACxC;AACA,MAAI,CAAC,EAAE,OAAQ,OAAM,IAAI,MAAM,+BAA+B;AAC9D,MAAI,CAAC,EAAE,SAAU,OAAM,IAAI,MAAM,iCAAiC;AAClE,SAAO,EAAE,MAAM,GAAG,EAAE,MAAM,IAAI,EAAE,QAAQ,GAAG;AAC7C;AA4DO,MAAM,cAAc,CACzB,aACe,UAAU,WAAW,YAAY,QAAQ,IAAI;","names":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StaticSolType, SolType, Resource, BindValue } from '@lifi/compose-spec';
|
|
1
|
+
import { StaticSolType, SolType, Resource, Ref, BindValue } from '@lifi/compose-spec';
|
|
2
2
|
import { OutputKind, TypedRef, TypedLiteral } from '../types.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -82,6 +82,6 @@ type LiteralBindable<K extends OutputKind> = K extends SolType ? TypedLiteral<K>
|
|
|
82
82
|
* Converts a bindable to the wire `bind` value it denotes: handles become
|
|
83
83
|
* `$ref` pointers, refs and literals pass through as-is.
|
|
84
84
|
*/
|
|
85
|
-
declare const toBindValue: (bindable: InputHandle | OutputHandle | TypedRef | TypedLiteral) => BindValue;
|
|
85
|
+
declare const toBindValue: (bindable: InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref) => BindValue;
|
|
86
86
|
|
|
87
87
|
export { type AnyHandle, type AnyRefBindable, type Bindable, type InputHandle, type OutputHandle, type RefBindable, type ResourceInputHandle, handleToRef, isInputHandle, isOutputHandle, toBindValue };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StaticSolType, SolType, Resource, BindValue } from '@lifi/compose-spec';
|
|
1
|
+
import { StaticSolType, SolType, Resource, Ref, BindValue } from '@lifi/compose-spec';
|
|
2
2
|
import { OutputKind, TypedRef, TypedLiteral } from '../types.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -82,6 +82,6 @@ type LiteralBindable<K extends OutputKind> = K extends SolType ? TypedLiteral<K>
|
|
|
82
82
|
* Converts a bindable to the wire `bind` value it denotes: handles become
|
|
83
83
|
* `$ref` pointers, refs and literals pass through as-is.
|
|
84
84
|
*/
|
|
85
|
-
declare const toBindValue: (bindable: InputHandle | OutputHandle | TypedRef | TypedLiteral) => BindValue;
|
|
85
|
+
declare const toBindValue: (bindable: InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref) => BindValue;
|
|
86
86
|
|
|
87
87
|
export { type AnyHandle, type AnyRefBindable, type Bindable, type InputHandle, type OutputHandle, type RefBindable, type ResourceInputHandle, handleToRef, isInputHandle, isOutputHandle, toBindValue };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/authoring/handles.ts"],"sourcesContent":["import type {\n BindValue,\n Resource,\n SolType,\n StaticSolType,\n} from '@lifi/compose-spec';\n\nimport type { OutputKind, TypedLiteral, TypedRef } from '../types.js';\n\n/**\n * A handle referencing a flow input declared in the flow's input schema.\n * The phantom `__outputKind` field carries the type parameter through\n * TypeScript's structural type system without affecting runtime shape.\n */\nexport interface InputHandle<T extends OutputKind = OutputKind> {\n readonly _tag: 'input';\n readonly inputName: string;\n readonly __outputKind?: T;\n}\n\n/**\n * An input handle for a resource (token) input, carrying the resource\n * declaration alongside the reference.\n */\nexport interface ResourceInputHandle extends InputHandle<'resource'> {\n readonly resource: Resource;\n}\n\n/**\n * A handle referencing an output port of a previously declared operation node.\n * The phantom `__outputKind` field carries the type parameter through\n * TypeScript's structural type system without affecting runtime shape.\n */\nexport interface OutputHandle<T extends OutputKind = OutputKind> {\n readonly _tag: 'output';\n readonly nodeId: string;\n readonly portName: string;\n readonly __outputKind?: T;\n}\n\n/** Discriminated union of all handle types that can be bound to operation arguments. */\nexport type AnyHandle = InputHandle | OutputHandle;\n\n/** Type guard that narrows an {@link AnyHandle} to an {@link InputHandle}. */\nexport const isInputHandle = (h: AnyHandle): h is InputHandle =>\n h._tag === 'input';\n\n/** Type guard that narrows an {@link AnyHandle} to an {@link OutputHandle}. */\nexport const isOutputHandle = (h: AnyHandle): h is OutputHandle =>\n h._tag === 'output';\n\n/**\n * Converts a handle to a JSON `$ref` pointer used in the flow document.\n * Input handles become `\"input.<name>\"`; output handles become `\"<nodeId>.<port>\"`.\n */\nexport const handleToRef = (h: AnyHandle): { $ref: string } => {\n if (h._tag === 'input') {\n if (!h.inputName) throw new Error('InputHandle has empty inputName');\n return { $ref: `input.${h.inputName}` };\n }\n if (!h.nodeId) throw new Error('OutputHandle has empty nodeId');\n if (!h.portName) throw new Error('OutputHandle has empty portName');\n return { $ref: `${h.nodeId}.${h.portName}` };\n};\n\n/**\n * For a bind slot expecting type T, widen the set of accepted handle types:\n * - `'bytes32'` is the raw 32-byte word type: accept any static-32-byte handle\n * (`uint256`/`uintN`/`address`/`bool`/`bytes32`) plus `'resource'` (a uint256\n * amount). At the IR1 boundary every value is a type-erased word, so any\n * static-32-byte handle is a sound bind for a `bytes32` payload port.\n * - `'uint256'` keeps its existing widening to also accept `'resource'`-tagged\n * handles (resources are uint256 amounts).\n * - every other type keeps exact-SolType matching.\n */\ntype SlotAssignable<T extends OutputKind> = T extends 'bytes32'\n ? StaticSolType | 'resource'\n : T extends 'uint256'\n ? T | 'resource'\n : T;\n\n/**\n * The values accepted by a typed slot that must resolve to a `$ref`:\n * - `OutputHandle<T>` / `InputHandle<T>` (same type)\n * - For `'uint256'` slots, also `'resource'`-tagged handles\n * - For `'bytes32'` slots, any static-32-byte handle (and `'resource'`)\n * - `TypedRef<T>` (typed context refs, subject to `SlotAssignable`)\n *\n * Plain `{ $ref: '...' }` objects are **not** accepted - use `raw.ref<T>()`\n * to create a typed ref when you need to reference a raw path.\n */\nexport type RefBindable<T extends OutputKind> =\n | OutputHandle<SlotAssignable<T>>\n | InputHandle<SlotAssignable<T>>\n | TypedRef<SlotAssignable<T>>;\n\n/**\n * Any ref-resolving bindable, with no per-slot type constraint.\n */\nexport type AnyRefBindable = InputHandle | OutputHandle | TypedRef;\n\n/**\n * The set of values accepted by a typed operation bind slot: everything\n * {@link RefBindable} accepts, plus a {@link TypedLiteral} constant baked\n * into the flow document. A `'resource'` slot rejects a literal: a token\n * resource is not a scalar constant.\n *\n * Use `raw.literal<T>()` to create one.\n */\nexport type Bindable<T extends OutputKind> =\n RefBindable<T> | LiteralBindable<SlotAssignable<T>>;\n\n// Distributes over the slot's assignable kinds and keeps the scalar ones: a\n// `'resource'` slot has no scalar arm, so its literal arm collapses to\n// `never` and a literal is rejected outright.\ntype LiteralBindable<K extends OutputKind> = K extends SolType\n ? TypedLiteral<K>\n : never;\n\n/**\n * Converts a bindable to the wire `bind` value it denotes: handles become\n * `$ref` pointers, refs and literals pass through as-is.\n */\nexport const toBindValue = (\n bindable: InputHandle | OutputHandle | TypedRef | TypedLiteral,\n): BindValue => ('_tag' in bindable ? handleToRef(bindable) : bindable);\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/authoring/handles.ts"],"sourcesContent":["import type {\n BindValue,\n Ref,\n Resource,\n SolType,\n StaticSolType,\n} from '@lifi/compose-spec';\n\nimport type { OutputKind, TypedLiteral, TypedRef } from '../types.js';\n\n/**\n * A handle referencing a flow input declared in the flow's input schema.\n * The phantom `__outputKind` field carries the type parameter through\n * TypeScript's structural type system without affecting runtime shape.\n */\nexport interface InputHandle<T extends OutputKind = OutputKind> {\n readonly _tag: 'input';\n readonly inputName: string;\n readonly __outputKind?: T;\n}\n\n/**\n * An input handle for a resource (token) input, carrying the resource\n * declaration alongside the reference.\n */\nexport interface ResourceInputHandle extends InputHandle<'resource'> {\n readonly resource: Resource;\n}\n\n/**\n * A handle referencing an output port of a previously declared operation node.\n * The phantom `__outputKind` field carries the type parameter through\n * TypeScript's structural type system without affecting runtime shape.\n */\nexport interface OutputHandle<T extends OutputKind = OutputKind> {\n readonly _tag: 'output';\n readonly nodeId: string;\n readonly portName: string;\n readonly __outputKind?: T;\n}\n\n/** Discriminated union of all handle types that can be bound to operation arguments. */\nexport type AnyHandle = InputHandle | OutputHandle;\n\n/** Type guard that narrows an {@link AnyHandle} to an {@link InputHandle}. */\nexport const isInputHandle = (h: AnyHandle): h is InputHandle =>\n h._tag === 'input';\n\n/** Type guard that narrows an {@link AnyHandle} to an {@link OutputHandle}. */\nexport const isOutputHandle = (h: AnyHandle): h is OutputHandle =>\n h._tag === 'output';\n\n/**\n * Converts a handle to a JSON `$ref` pointer used in the flow document.\n * Input handles become `\"input.<name>\"`; output handles become `\"<nodeId>.<port>\"`.\n */\nexport const handleToRef = (h: AnyHandle): { $ref: string } => {\n if (h._tag === 'input') {\n if (!h.inputName) throw new Error('InputHandle has empty inputName');\n return { $ref: `input.${h.inputName}` };\n }\n if (!h.nodeId) throw new Error('OutputHandle has empty nodeId');\n if (!h.portName) throw new Error('OutputHandle has empty portName');\n return { $ref: `${h.nodeId}.${h.portName}` };\n};\n\n/**\n * For a bind slot expecting type T, widen the set of accepted handle types:\n * - `'bytes32'` is the raw 32-byte word type: accept any static-32-byte handle\n * (`uint256`/`uintN`/`address`/`bool`/`bytes32`) plus `'resource'` (a uint256\n * amount). At the IR1 boundary every value is a type-erased word, so any\n * static-32-byte handle is a sound bind for a `bytes32` payload port.\n * - `'uint256'` keeps its existing widening to also accept `'resource'`-tagged\n * handles (resources are uint256 amounts).\n * - every other type keeps exact-SolType matching.\n */\ntype SlotAssignable<T extends OutputKind> = T extends 'bytes32'\n ? StaticSolType | 'resource'\n : T extends 'uint256'\n ? T | 'resource'\n : T;\n\n/**\n * The values accepted by a typed slot that must resolve to a `$ref`:\n * - `OutputHandle<T>` / `InputHandle<T>` (same type)\n * - For `'uint256'` slots, also `'resource'`-tagged handles\n * - For `'bytes32'` slots, any static-32-byte handle (and `'resource'`)\n * - `TypedRef<T>` (typed context refs, subject to `SlotAssignable`)\n *\n * Plain `{ $ref: '...' }` objects are **not** accepted - use `raw.ref<T>()`\n * to create a typed ref when you need to reference a raw path.\n */\nexport type RefBindable<T extends OutputKind> =\n | OutputHandle<SlotAssignable<T>>\n | InputHandle<SlotAssignable<T>>\n | TypedRef<SlotAssignable<T>>;\n\n/**\n * Any ref-resolving bindable, with no per-slot type constraint.\n */\nexport type AnyRefBindable = InputHandle | OutputHandle | TypedRef;\n\n/**\n * The set of values accepted by a typed operation bind slot: everything\n * {@link RefBindable} accepts, plus a {@link TypedLiteral} constant baked\n * into the flow document. A `'resource'` slot rejects a literal: a token\n * resource is not a scalar constant.\n *\n * Use `raw.literal<T>()` to create one.\n */\nexport type Bindable<T extends OutputKind> =\n RefBindable<T> | LiteralBindable<SlotAssignable<T>>;\n\n// Distributes over the slot's assignable kinds and keeps the scalar ones: a\n// `'resource'` slot has no scalar arm, so its literal arm collapses to\n// `never` and a literal is rejected outright.\ntype LiteralBindable<K extends OutputKind> = K extends SolType\n ? TypedLiteral<K>\n : never;\n\n/**\n * Converts a bindable to the wire `bind` value it denotes: handles become\n * `$ref` pointers, refs and literals pass through as-is.\n */\nexport const toBindValue = (\n bindable: InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref,\n): BindValue => ('_tag' in bindable ? handleToRef(bindable) : bindable);\n"],"mappings":"AA6CO,MAAM,gBAAgB,CAAC,MAC5B,EAAE,SAAS;AAGN,MAAM,iBAAiB,CAAC,MAC7B,EAAE,SAAS;AAMN,MAAM,cAAc,CAAC,MAAmC;AAC7D,MAAI,EAAE,SAAS,SAAS;AACtB,QAAI,CAAC,EAAE,UAAW,OAAM,IAAI,MAAM,iCAAiC;AACnE,WAAO,EAAE,MAAM,SAAS,EAAE,SAAS,GAAG;AAAA,EACxC;AACA,MAAI,CAAC,EAAE,OAAQ,OAAM,IAAI,MAAM,+BAA+B;AAC9D,MAAI,CAAC,EAAE,SAAU,OAAM,IAAI,MAAM,iCAAiC;AAClE,SAAO,EAAE,MAAM,GAAG,EAAE,MAAM,IAAI,EAAE,QAAQ,GAAG;AAC7C;AA4DO,MAAM,cAAc,CACzB,aACe,UAAU,WAAW,YAAY,QAAQ,IAAI;","names":[]}
|
package/dist/authoring/raw.cjs
CHANGED
|
@@ -23,9 +23,11 @@ __export(raw_exports, {
|
|
|
23
23
|
ref: () => ref
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(raw_exports);
|
|
26
|
-
const ref = (path) => (
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
const ref = (path) => (
|
|
27
|
+
// The brand is phantom, so the runtime value is the bare wire ref. This is
|
|
28
|
+
// the only place a `TypedRef` is minted; the cast is what the brand buys.
|
|
29
|
+
{ $ref: path }
|
|
30
|
+
);
|
|
29
31
|
const literal = (kind, value) => ({ kind, value });
|
|
30
32
|
const rawGuard = (kind, config = {}) => {
|
|
31
33
|
if ("kind" in config) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/authoring/raw.ts"],"sourcesContent":["import type { AppliedGuard, SolType } from '@lifi/compose-spec';\n\nimport type { OutputKind, TypedLiteral, TypedRef } from '../types.js';\n\n/**\n * Creates a typed `$ref` pointer for use in bind slots.\n *\n * This is an **escape hatch** for referencing values that the typed builder\n * API doesn't cover — for example, outputs of an `untypedOp` node or custom\n * context paths. The caller is responsible for choosing the correct type\n * parameter; no runtime validation occurs.\n *\n * Prefer typed handles (`OutputHandle`, `InputHandle`) and `builder.context`\n * whenever possible. Use `ref` only when you need to construct a `$ref` path\n * manually and want it accepted by a `Bindable<T>` slot.\n *\n * @typeParam T - The output kind this ref represents (e.g. `'address'`, `'uint256'`, `'resource'`).\n * @param path - The `$ref` path (e.g. `\"context.sender\"`, `\"myNode.result\"`).\n * @returns A {@link TypedRef} accepted by `Bindable<T>` slots matching `T`.\n *\n * @example\n * ```ts\n * import { raw } from '@lifi/composer-sdk';\n *\n * // Reference an untypedOp output in a typed operation:\n * builder.untypedOp('custom', 'some.op', {\n * bind: { x: { $ref: 'input.token' } },\n * config: {},\n * });\n * builder.core.add('sum', {\n * bind: {\n * a: raw.ref<'uint256'>('custom.result'),\n * b: someTypedHandle,\n * },\n * });\n * ```\n */\nexport const ref = <T extends OutputKind>(path: string): TypedRef<T>
|
|
1
|
+
{"version":3,"sources":["../../src/authoring/raw.ts"],"sourcesContent":["import type { AppliedGuard, SolType } from '@lifi/compose-spec';\n\nimport type { OutputKind, TypedLiteral, TypedRef } from '../types.js';\n\n/**\n * Creates a typed `$ref` pointer for use in bind slots.\n *\n * This is an **escape hatch** for referencing values that the typed builder\n * API doesn't cover — for example, outputs of an `untypedOp` node or custom\n * context paths. The caller is responsible for choosing the correct type\n * parameter; no runtime validation occurs.\n *\n * Prefer typed handles (`OutputHandle`, `InputHandle`) and `builder.context`\n * whenever possible. Use `ref` only when you need to construct a `$ref` path\n * manually and want it accepted by a `Bindable<T>` slot.\n *\n * @typeParam T - The output kind this ref represents (e.g. `'address'`, `'uint256'`, `'resource'`).\n * @param path - The `$ref` path (e.g. `\"context.sender\"`, `\"myNode.result\"`).\n * @returns A {@link TypedRef} accepted by `Bindable<T>` slots matching `T`.\n *\n * @example\n * ```ts\n * import { raw } from '@lifi/composer-sdk';\n *\n * // Reference an untypedOp output in a typed operation:\n * builder.untypedOp('custom', 'some.op', {\n * bind: { x: { $ref: 'input.token' } },\n * config: {},\n * });\n * builder.core.add('sum', {\n * bind: {\n * a: raw.ref<'uint256'>('custom.result'),\n * b: someTypedHandle,\n * },\n * });\n * ```\n */\nexport const ref = <T extends OutputKind>(path: string): TypedRef<T> =>\n // The brand is phantom, so the runtime value is the bare wire ref. This is\n // the only place a `TypedRef` is minted; the cast is what the brand buys.\n ({ $ref: path }) as TypedRef<T>;\n\n/**\n * Creates a typed literal for use in bind slots: a constant baked into the\n * flow document rather than supplied at run time.\n *\n * Prefer a declared flow input and `builder.inputs.<name>` — a value the\n * caller supplies per run stays out of the document. Use a literal when the\n * flow has no run of its own to take the value from: the `continuationFlow`\n * of a `continuation.settle` node is stored by the settlement backend and\n * re-run later against the deferred proceeds, so its delivery address has to\n * be part of the committed document.\n *\n * @typeParam T - The Solidity type of the literal (e.g. `'address'`).\n * @param kind - The literal's Solidity type.\n * @param value - The literal value, as the wire format carries it: a string.\n * @returns A {@link TypedLiteral} accepted by `Bindable<T>` slots matching `T`.\n *\n * @example\n * ```ts\n * import { raw } from '@lifi/composer-sdk';\n *\n * builder.core.transfer('deliver', {\n * bind: {\n * amount: zap.amountOut,\n * recipient: raw.literal('address', '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'),\n * },\n * config: {},\n * });\n * ```\n */\nexport const literal = <T extends SolType>(\n kind: T,\n value: string,\n): TypedLiteral<T> => ({ kind, value });\n\n/**\n * Creates a raw guard object for use in the `guards` array of an operation call.\n *\n * @param kind - The guard type (e.g. `\"slippage\"`).\n * @param config - Guard-specific configuration (e.g. `{ toleranceBps: 300 }`).\n * @returns An {@link AppliedGuard} object.\n */\nexport const rawGuard = (\n kind: string,\n config: Record<string, unknown> = {},\n): AppliedGuard => {\n if ('kind' in config) {\n throw new Error(\n `rawGuard: 'kind' must not appear in config (got \"${String(\n config.kind,\n )}\"). Pass it as the first argument instead.`,\n );\n }\n return { ...config, kind };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqCO,MAAM,MAAM,CAAuB;AAAA;AAAA;AAAA,EAGvC,EAAE,MAAM,KAAK;AAAA;AA+BT,MAAM,UAAU,CACrB,MACA,WACqB,EAAE,MAAM,MAAM;AAS9B,MAAM,WAAW,CACtB,MACA,SAAkC,CAAC,MAClB;AACjB,MAAI,UAAU,QAAQ;AACpB,UAAM,IAAI;AAAA,MACR,oDAAoD;AAAA,QAClD,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO,EAAE,GAAG,QAAQ,KAAK;AAC3B;","names":[]}
|
package/dist/authoring/raw.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
const ref = (path) => (
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const ref = (path) => (
|
|
2
|
+
// The brand is phantom, so the runtime value is the bare wire ref. This is
|
|
3
|
+
// the only place a `TypedRef` is minted; the cast is what the brand buys.
|
|
4
|
+
{ $ref: path }
|
|
5
|
+
);
|
|
4
6
|
const literal = (kind, value) => ({ kind, value });
|
|
5
7
|
const rawGuard = (kind, config = {}) => {
|
|
6
8
|
if ("kind" in config) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/authoring/raw.ts"],"sourcesContent":["import type { AppliedGuard, SolType } from '@lifi/compose-spec';\n\nimport type { OutputKind, TypedLiteral, TypedRef } from '../types.js';\n\n/**\n * Creates a typed `$ref` pointer for use in bind slots.\n *\n * This is an **escape hatch** for referencing values that the typed builder\n * API doesn't cover — for example, outputs of an `untypedOp` node or custom\n * context paths. The caller is responsible for choosing the correct type\n * parameter; no runtime validation occurs.\n *\n * Prefer typed handles (`OutputHandle`, `InputHandle`) and `builder.context`\n * whenever possible. Use `ref` only when you need to construct a `$ref` path\n * manually and want it accepted by a `Bindable<T>` slot.\n *\n * @typeParam T - The output kind this ref represents (e.g. `'address'`, `'uint256'`, `'resource'`).\n * @param path - The `$ref` path (e.g. `\"context.sender\"`, `\"myNode.result\"`).\n * @returns A {@link TypedRef} accepted by `Bindable<T>` slots matching `T`.\n *\n * @example\n * ```ts\n * import { raw } from '@lifi/composer-sdk';\n *\n * // Reference an untypedOp output in a typed operation:\n * builder.untypedOp('custom', 'some.op', {\n * bind: { x: { $ref: 'input.token' } },\n * config: {},\n * });\n * builder.core.add('sum', {\n * bind: {\n * a: raw.ref<'uint256'>('custom.result'),\n * b: someTypedHandle,\n * },\n * });\n * ```\n */\nexport const ref = <T extends OutputKind>(path: string): TypedRef<T>
|
|
1
|
+
{"version":3,"sources":["../../src/authoring/raw.ts"],"sourcesContent":["import type { AppliedGuard, SolType } from '@lifi/compose-spec';\n\nimport type { OutputKind, TypedLiteral, TypedRef } from '../types.js';\n\n/**\n * Creates a typed `$ref` pointer for use in bind slots.\n *\n * This is an **escape hatch** for referencing values that the typed builder\n * API doesn't cover — for example, outputs of an `untypedOp` node or custom\n * context paths. The caller is responsible for choosing the correct type\n * parameter; no runtime validation occurs.\n *\n * Prefer typed handles (`OutputHandle`, `InputHandle`) and `builder.context`\n * whenever possible. Use `ref` only when you need to construct a `$ref` path\n * manually and want it accepted by a `Bindable<T>` slot.\n *\n * @typeParam T - The output kind this ref represents (e.g. `'address'`, `'uint256'`, `'resource'`).\n * @param path - The `$ref` path (e.g. `\"context.sender\"`, `\"myNode.result\"`).\n * @returns A {@link TypedRef} accepted by `Bindable<T>` slots matching `T`.\n *\n * @example\n * ```ts\n * import { raw } from '@lifi/composer-sdk';\n *\n * // Reference an untypedOp output in a typed operation:\n * builder.untypedOp('custom', 'some.op', {\n * bind: { x: { $ref: 'input.token' } },\n * config: {},\n * });\n * builder.core.add('sum', {\n * bind: {\n * a: raw.ref<'uint256'>('custom.result'),\n * b: someTypedHandle,\n * },\n * });\n * ```\n */\nexport const ref = <T extends OutputKind>(path: string): TypedRef<T> =>\n // The brand is phantom, so the runtime value is the bare wire ref. This is\n // the only place a `TypedRef` is minted; the cast is what the brand buys.\n ({ $ref: path }) as TypedRef<T>;\n\n/**\n * Creates a typed literal for use in bind slots: a constant baked into the\n * flow document rather than supplied at run time.\n *\n * Prefer a declared flow input and `builder.inputs.<name>` — a value the\n * caller supplies per run stays out of the document. Use a literal when the\n * flow has no run of its own to take the value from: the `continuationFlow`\n * of a `continuation.settle` node is stored by the settlement backend and\n * re-run later against the deferred proceeds, so its delivery address has to\n * be part of the committed document.\n *\n * @typeParam T - The Solidity type of the literal (e.g. `'address'`).\n * @param kind - The literal's Solidity type.\n * @param value - The literal value, as the wire format carries it: a string.\n * @returns A {@link TypedLiteral} accepted by `Bindable<T>` slots matching `T`.\n *\n * @example\n * ```ts\n * import { raw } from '@lifi/composer-sdk';\n *\n * builder.core.transfer('deliver', {\n * bind: {\n * amount: zap.amountOut,\n * recipient: raw.literal('address', '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'),\n * },\n * config: {},\n * });\n * ```\n */\nexport const literal = <T extends SolType>(\n kind: T,\n value: string,\n): TypedLiteral<T> => ({ kind, value });\n\n/**\n * Creates a raw guard object for use in the `guards` array of an operation call.\n *\n * @param kind - The guard type (e.g. `\"slippage\"`).\n * @param config - Guard-specific configuration (e.g. `{ toleranceBps: 300 }`).\n * @returns An {@link AppliedGuard} object.\n */\nexport const rawGuard = (\n kind: string,\n config: Record<string, unknown> = {},\n): AppliedGuard => {\n if ('kind' in config) {\n throw new Error(\n `rawGuard: 'kind' must not appear in config (got \"${String(\n config.kind,\n )}\"). Pass it as the first argument instead.`,\n );\n }\n return { ...config, kind };\n};\n"],"mappings":"AAqCO,MAAM,MAAM,CAAuB;AAAA;AAAA;AAAA,EAGvC,EAAE,MAAM,KAAK;AAAA;AA+BT,MAAM,UAAU,CACrB,MACA,WACqB,EAAE,MAAM,MAAM;AAS9B,MAAM,WAAW,CACtB,MACA,SAAkC,CAAC,MAClB;AACjB,MAAI,UAAU,QAAQ;AACpB,UAAM,IAAI;AAAA,MACR,oDAAoD;AAAA,QAClD,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO,EAAE,GAAG,QAAQ,KAAK;AAC3B;","names":[]}
|