@lifi/composer-sdk 0.0.1-alpha

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.
Files changed (160) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +220 -0
  3. package/dist/authoring/FlowBuilderCore.cjs +115 -0
  4. package/dist/authoring/FlowBuilderCore.cjs.map +1 -0
  5. package/dist/authoring/FlowBuilderCore.d.cts +114 -0
  6. package/dist/authoring/FlowBuilderCore.d.ts +114 -0
  7. package/dist/authoring/FlowBuilderCore.js +91 -0
  8. package/dist/authoring/FlowBuilderCore.js.map +1 -0
  9. package/dist/authoring/handles.cjs +43 -0
  10. package/dist/authoring/handles.cjs.map +1 -0
  11. package/dist/authoring/handles.d.cts +61 -0
  12. package/dist/authoring/handles.d.ts +61 -0
  13. package/dist/authoring/handles.js +17 -0
  14. package/dist/authoring/handles.js.map +1 -0
  15. package/dist/authoring/raw.cjs +41 -0
  16. package/dist/authoring/raw.cjs.map +1 -0
  17. package/dist/authoring/raw.d.cts +47 -0
  18. package/dist/authoring/raw.d.ts +47 -0
  19. package/dist/authoring/raw.js +16 -0
  20. package/dist/authoring/raw.js.map +1 -0
  21. package/dist/authoring/signatureArgs.cjs +114 -0
  22. package/dist/authoring/signatureArgs.cjs.map +1 -0
  23. package/dist/authoring/signatureArgs.d.cts +146 -0
  24. package/dist/authoring/signatureArgs.d.ts +146 -0
  25. package/dist/authoring/signatureArgs.js +87 -0
  26. package/dist/authoring/signatureArgs.js.map +1 -0
  27. package/dist/client.cjs +140 -0
  28. package/dist/client.cjs.map +1 -0
  29. package/dist/client.d.cts +67 -0
  30. package/dist/client.d.ts +67 -0
  31. package/dist/client.js +116 -0
  32. package/dist/client.js.map +1 -0
  33. package/dist/discovery.cjs +17 -0
  34. package/dist/discovery.cjs.map +1 -0
  35. package/dist/discovery.d.cts +56 -0
  36. package/dist/discovery.d.ts +56 -0
  37. package/dist/discovery.js +1 -0
  38. package/dist/discovery.js.map +1 -0
  39. package/dist/errors.cjs +91 -0
  40. package/dist/errors.cjs.map +1 -0
  41. package/dist/errors.d.cts +77 -0
  42. package/dist/errors.d.ts +77 -0
  43. package/dist/errors.js +65 -0
  44. package/dist/errors.js.map +1 -0
  45. package/dist/generated/config.generated.cjs +17 -0
  46. package/dist/generated/config.generated.cjs.map +1 -0
  47. package/dist/generated/config.generated.d.cts +144 -0
  48. package/dist/generated/config.generated.d.ts +144 -0
  49. package/dist/generated/config.generated.js +1 -0
  50. package/dist/generated/config.generated.js.map +1 -0
  51. package/dist/generated/guards.generated.cjs +32 -0
  52. package/dist/generated/guards.generated.cjs.map +1 -0
  53. package/dist/generated/guards.generated.d.cts +4 -0
  54. package/dist/generated/guards.generated.d.ts +4 -0
  55. package/dist/generated/guards.generated.js +8 -0
  56. package/dist/generated/guards.generated.js.map +1 -0
  57. package/dist/generated/materialisers.generated.cjs +44 -0
  58. package/dist/generated/materialisers.generated.cjs.map +1 -0
  59. package/dist/generated/materialisers.generated.d.cts +4 -0
  60. package/dist/generated/materialisers.generated.d.ts +4 -0
  61. package/dist/generated/materialisers.generated.js +18 -0
  62. package/dist/generated/materialisers.generated.js.map +1 -0
  63. package/dist/generated/operations.generated.cjs +110 -0
  64. package/dist/generated/operations.generated.cjs.map +1 -0
  65. package/dist/generated/operations.generated.d.cts +337 -0
  66. package/dist/generated/operations.generated.d.ts +337 -0
  67. package/dist/generated/operations.generated.js +89 -0
  68. package/dist/generated/operations.generated.js.map +1 -0
  69. package/dist/generated/preconditions.generated.cjs +44 -0
  70. package/dist/generated/preconditions.generated.cjs.map +1 -0
  71. package/dist/generated/preconditions.generated.d.cts +4 -0
  72. package/dist/generated/preconditions.generated.d.ts +4 -0
  73. package/dist/generated/preconditions.generated.js +18 -0
  74. package/dist/generated/preconditions.generated.js.map +1 -0
  75. package/dist/guards.generated-DKKDKREA.d.ts +14 -0
  76. package/dist/guards.generated-hrQ1KPNv.d.cts +14 -0
  77. package/dist/index.cjs +76 -0
  78. package/dist/index.cjs.map +1 -0
  79. package/dist/index.d.cts +99 -0
  80. package/dist/index.d.ts +99 -0
  81. package/dist/index.js +30 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/materialisers.generated-BsA1uDW8.d.ts +24 -0
  84. package/dist/materialisers.generated-nMxTAaVi.d.cts +24 -0
  85. package/dist/preconditions.generated-DblS13Wq.d.cts +24 -0
  86. package/dist/preconditions.generated-U7YpVh30.d.ts +24 -0
  87. package/dist/raw-Dj_2rBSQ.d.cts +19 -0
  88. package/dist/raw-IxCF_bSS.d.ts +19 -0
  89. package/dist/raw.cjs +34 -0
  90. package/dist/raw.cjs.map +1 -0
  91. package/dist/raw.d.cts +4 -0
  92. package/dist/raw.d.ts +4 -0
  93. package/dist/raw.js +8 -0
  94. package/dist/raw.js.map +1 -0
  95. package/dist/resources-BKlFxjo8.d.cts +56 -0
  96. package/dist/resources-CYis1_DS.d.ts +56 -0
  97. package/dist/resources.cjs +39 -0
  98. package/dist/resources.cjs.map +1 -0
  99. package/dist/resources.d.cts +3 -0
  100. package/dist/resources.d.ts +3 -0
  101. package/dist/resources.js +14 -0
  102. package/dist/resources.js.map +1 -0
  103. package/dist/run/inputs.cjs +51 -0
  104. package/dist/run/inputs.cjs.map +1 -0
  105. package/dist/run/inputs.d.cts +91 -0
  106. package/dist/run/inputs.d.ts +91 -0
  107. package/dist/run/inputs.js +26 -0
  108. package/dist/run/inputs.js.map +1 -0
  109. package/dist/sdk.cjs +60 -0
  110. package/dist/sdk.cjs.map +1 -0
  111. package/dist/sdk.d.cts +112 -0
  112. package/dist/sdk.d.ts +112 -0
  113. package/dist/sdk.js +40 -0
  114. package/dist/sdk.js.map +1 -0
  115. package/dist/types.cjs +17 -0
  116. package/dist/types.cjs.map +1 -0
  117. package/dist/types.d.cts +74 -0
  118. package/dist/types.d.ts +74 -0
  119. package/dist/types.js +1 -0
  120. package/dist/types.js.map +1 -0
  121. package/package.json +81 -0
  122. package/src/authoring/FlowBuilderCore.ts +270 -0
  123. package/src/authoring/handles.ts +81 -0
  124. package/src/authoring/raw.ts +60 -0
  125. package/src/authoring/signatureArgs.ts +249 -0
  126. package/src/client.ts +230 -0
  127. package/src/discovery.ts +51 -0
  128. package/src/errors.ts +150 -0
  129. package/src/examples/approveAndDeposit.ts +84 -0
  130. package/src/examples/callContract.ts +199 -0
  131. package/src/examples/config.ts +9 -0
  132. package/src/examples/consolidateToEth.ts +94 -0
  133. package/src/examples/consolidateToUsdc.ts +95 -0
  134. package/src/examples/depositFromProxy.ts +87 -0
  135. package/src/examples/dustSweep.ts +66 -0
  136. package/src/examples/lifiSwap.ts +56 -0
  137. package/src/examples/lifiZap.ts +60 -0
  138. package/src/examples/rawCallWithArithmetic.ts +78 -0
  139. package/src/examples/readContractState.ts +77 -0
  140. package/src/examples/run.ts +168 -0
  141. package/src/examples/splitAndZap.ts +73 -0
  142. package/src/examples/splitWithArithmetic.ts +93 -0
  143. package/src/examples/swapAndZap.ts +72 -0
  144. package/src/examples/swapToRecipient.ts +109 -0
  145. package/src/examples/swapWithAllowRevert.ts +119 -0
  146. package/src/examples/swapWithBalanceCheck.ts +73 -0
  147. package/src/examples/swapWithOutputValidation.ts +125 -0
  148. package/src/examples/transferTokens.ts +123 -0
  149. package/src/examples/untypedOpWithTypedRef.ts +77 -0
  150. package/src/generated/config.generated.ts +174 -0
  151. package/src/generated/guards.generated.ts +14 -0
  152. package/src/generated/materialisers.generated.ts +44 -0
  153. package/src/generated/operations.generated.ts +568 -0
  154. package/src/generated/preconditions.generated.ts +43 -0
  155. package/src/index.ts +149 -0
  156. package/src/raw.ts +10 -0
  157. package/src/resources.ts +61 -0
  158. package/src/run/inputs.ts +117 -0
  159. package/src/sdk.ts +173 -0
  160. package/src/types.ts +101 -0
package/src/index.ts ADDED
@@ -0,0 +1,149 @@
1
+ /**
2
+ * `@lifi/composer-sdk` — TypeScript SDK for building and compiling
3
+ * Compose flows into executable EVM calldata.
4
+ *
5
+ * Start by creating an SDK instance with {@link createComposeSdk}, then use
6
+ * {@link ComposeSdk.flow} to build flows and compile them.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+
11
+ export type {
12
+ AbiTypeToOutputKind,
13
+ Address,
14
+ InputDecl,
15
+ InputSchema,
16
+ InputSpecOf,
17
+ IntegerString,
18
+ IntegerStringInput,
19
+ OutputKind,
20
+ TypedGuard,
21
+ TypedRef,
22
+ } from './types.js';
23
+
24
+ export type {
25
+ GetZapPacksOptions,
26
+ ZapPackEdge,
27
+ ZapPackOverview,
28
+ } from './discovery.js';
29
+ export type { ComposeError, ComposeErrorCode } from './errors.js';
30
+ export type {
31
+ AppliedGuard,
32
+ ApprovalEntry,
33
+ Call,
34
+ ComposeCompilePartialData,
35
+ ComposeCompileRequest,
36
+ ComposeCompileResult,
37
+ ComposeCompileSuccessData,
38
+ ComposeContinuation,
39
+ ComposeErrorKind,
40
+ ComposeTransactionRequest,
41
+ Flow,
42
+ InputSpec,
43
+ MaterialiserConfigOf,
44
+ MaterialiserInput,
45
+ Precondition,
46
+ PreconditionConfigOf,
47
+ PriceImpact,
48
+ Ref,
49
+ Resource,
50
+ SimulationPolicy,
51
+ SimulationRevert,
52
+ SolType,
53
+ SweepTo,
54
+ } from '@lifi/compose-spec';
55
+ export { isComposeError } from './errors.js';
56
+
57
+ export type {
58
+ Bindable,
59
+ InputHandle,
60
+ ResourceInputHandle,
61
+ OutputHandle,
62
+ AnyHandle,
63
+ } from './authoring/handles.js';
64
+ export { isInputHandle, isOutputHandle } from './authoring/handles.js';
65
+ export { ref } from './authoring/raw.js';
66
+
67
+ export type { AnyBindable } from './authoring/FlowBuilderCore.js';
68
+ export type { TypedFlow, FlowOptions } from './authoring/FlowBuilderCore.js';
69
+
70
+ export type { ComposeRunInput } from './run/inputs.js';
71
+ export { materialiser } from './run/inputs.js';
72
+
73
+ export { createComposeSdk } from './sdk.js';
74
+ export type { ComposeSdk, ComposeSdkOptions, FlowBuilder } from './sdk.js';
75
+
76
+ import * as guardsMod from './generated/guards.generated.js';
77
+ import * as materialisersMod from './generated/materialisers.generated.js';
78
+ import * as preconditionsMod from './generated/preconditions.generated.js';
79
+ import * as rawMod from './raw.js';
80
+ import * as resourcesMod from './resources.js';
81
+
82
+ /**
83
+ * Guard factories for protecting operation outputs (e.g. slippage tolerance).
84
+ * Pass guards to an operation's `guards` array.
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * builder.lifi.swap('swap1', {
89
+ * bind: { amountIn: builder.inputs.token },
90
+ * config: { resourceOut: resources.native(1) },
91
+ * guards: [guards.slippage({ port: 'amountOut', bps: 300 })],
92
+ * });
93
+ * ```
94
+ */
95
+ export const guards: typeof guardsMod = guardsMod;
96
+ /**
97
+ * Materialiser factories that tell the runtime how to resolve token input
98
+ * amounts on-chain (e.g. read a wallet balance, accept a direct deposit).
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * await builder.compile({
103
+ * inputs: { token: materialisers.balanceOf({}) },
104
+ * signer: '0x...',
105
+ * });
106
+ * ```
107
+ */
108
+ export const materialisers: typeof materialisersMod = materialisersMod;
109
+ /**
110
+ * Precondition factories for asserting on-chain state before a flow executes
111
+ * (e.g. minimum token balances, ERC-20 allowances).
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * await builder.compile({
116
+ * inputs: { token: materialisers.balanceOf({}) },
117
+ * preconditions: [
118
+ * preconditions.erc20Balance({ wallet: '0x...', token: '0x...', balance: 1000n }),
119
+ * ],
120
+ * signer: '0x...',
121
+ * });
122
+ * ```
123
+ */
124
+ export const preconditions: typeof preconditionsMod = preconditionsMod;
125
+ /**
126
+ * Resource declaration helpers for defining token inputs in a flow schema.
127
+ * Use {@link resources.erc20} for ERC-20 tokens and {@link resources.native}
128
+ * for the chain's native coin (ETH, MATIC, etc.).
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * const builder = sdk.flow(1, {
133
+ * inputs: {
134
+ * usdc: resources.erc20('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 1),
135
+ * eth: resources.native(1),
136
+ * },
137
+ * });
138
+ * ```
139
+ */
140
+ export const resources: typeof resourcesMod = resourcesMod;
141
+ export * from './generated/config.generated.js';
142
+
143
+ /**
144
+ * Low-level escape hatch for constructing flow nodes, guards, and materialiser
145
+ * inputs without the typed builder API. Prefer the generated operation methods
146
+ * on {@link FlowBuilder} and the typed `guards`/`materialisers` namespaces
147
+ * for most use cases.
148
+ */
149
+ export const raw: typeof rawMod = rawMod;
package/src/raw.ts ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Low-level escape hatch for constructing flow nodes and guards without the
3
+ * typed builder API. Use these when working with operation kinds not covered
4
+ * by the generated methods, or when you need full control over the JSON shape.
5
+ *
6
+ * For most use cases, prefer the generated operation methods on {@link FlowBuilder}
7
+ * (e.g. `builder.lifi.swap(...)`) and the typed guard/materialiser helpers.
8
+ */
9
+ export { rawGuard as guard, ref } from './authoring/raw.js';
10
+ export { materialiser } from './run/inputs.js';
@@ -0,0 +1,61 @@
1
+ import type { Address } from './types.js';
2
+
3
+ // These resource types are SDK-local declarations that mirror the shape of
4
+ // `Resource` from `@lifi/compose-spec`. They exist so the SDK can be used
5
+ // without directly depending on `@lifi/compose-spec` at the call site.
6
+ // The types are structurally compatible, so they are assignable to each other.
7
+
8
+ /** A resource declaration representing the chain's native token (e.g. ETH, MATIC). */
9
+ export interface NativeResource {
10
+ readonly kind: 'native';
11
+ readonly chainId: number;
12
+ }
13
+
14
+ /** A resource declaration representing an ERC-20 token at a specific address. */
15
+ export interface Erc20Resource {
16
+ readonly kind: 'erc20';
17
+ readonly token: Address;
18
+ readonly chainId: number;
19
+ }
20
+
21
+ /** A token resource — either the chain's native token or an ERC-20. */
22
+ export type Resource = NativeResource | Erc20Resource;
23
+
24
+ /**
25
+ * Creates a native token resource declaration.
26
+ *
27
+ * @param chainId - The EVM chain ID the native token belongs to.
28
+ * @returns A {@link NativeResource} for use in flow input schemas.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const builder = sdk.flow(1, {
33
+ * inputs: { eth: native(1) },
34
+ * });
35
+ * ```
36
+ */
37
+ export const native = (chainId: number): NativeResource => ({
38
+ kind: 'native',
39
+ chainId,
40
+ });
41
+
42
+ /**
43
+ * Creates an ERC-20 token resource declaration.
44
+ *
45
+ * @param token - The `0x`-prefixed contract address of the ERC-20 token.
46
+ * @param chainId - The EVM chain ID the token is deployed on.
47
+ * @returns An {@link Erc20Resource} for use in flow input schemas.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
52
+ * const builder = sdk.flow(1, {
53
+ * inputs: { usdc: erc20(USDC, 1) },
54
+ * });
55
+ * ```
56
+ */
57
+ export const erc20 = (token: Address, chainId: number): Erc20Resource => ({
58
+ kind: 'erc20',
59
+ token,
60
+ chainId,
61
+ });
@@ -0,0 +1,117 @@
1
+ import type {
2
+ ComposeRun,
3
+ InputSpec,
4
+ MaterialiserInput,
5
+ Precondition,
6
+ SimulationPolicy,
7
+ SweepTo,
8
+ } from '@lifi/compose-spec';
9
+
10
+ import type { Address, InputSchema, InputSpecOf } from '../types.js';
11
+
12
+ /**
13
+ * Runtime inputs for compiling a flow. Passed to `builder.compile()` or `sdk.request()`.
14
+ *
15
+ * @typeParam T - The flow's input schema, used to type-check `inputs` and `assumptions`.
16
+ */
17
+ export interface ComposeRunInput<T extends InputSchema = InputSchema> {
18
+ /**
19
+ * Concrete values for each declared flow input. Resource inputs accept a
20
+ * materialiser or a literal integer amount; scalar inputs accept the matching type.
21
+ */
22
+ readonly inputs: { readonly [K in keyof T]: InputSpecOf<T[K]> };
23
+ /** Optional preconditions that must hold before the flow executes (e.g. minimum balances). */
24
+ readonly preconditions?: readonly Precondition[];
25
+ /** The `0x`-prefixed address of the transaction signer. */
26
+ readonly signer: Address;
27
+ /**
28
+ * Optional assumed token amounts for resource inputs, keyed by input name.
29
+ * When a materialiser resolves amounts at execution time rather than upfront,
30
+ * assumptions let the compiler plan routes using estimated values. The keys
31
+ * must match the input names declared in the flow schema.
32
+ */
33
+ readonly assumptions?: { readonly [K in keyof T]?: bigint };
34
+ /** Optional integrator referrer identifier. */
35
+ readonly referrer?: string;
36
+ /** Maximum acceptable price impact in basis points (e.g. `300` = 3%). */
37
+ readonly maxPriceImpactBps?: number;
38
+ /**
39
+ * Destination for sweeping all proxy-held terminal resources after execution.
40
+ * Pass a literal `0x`-prefixed address or `{ $ref: "context.sender" }` to
41
+ * send remaining tokens to the signer.
42
+ */
43
+ readonly sweepTo?: SweepTo;
44
+ /**
45
+ * Controls behavior when simulation detects a revert.
46
+ * `'strict'` (default) returns an error; `'allow-revert'` returns a partial
47
+ * result with the transaction and revert diagnostics.
48
+ */
49
+ readonly simulationPolicy?: SimulationPolicy;
50
+ /**
51
+ * When `true`, the server checks on-chain ERC-20 allowances and omits
52
+ * approvals that are already sufficient. Defaults to `false`.
53
+ */
54
+ readonly checkOnChainAllowances?: boolean;
55
+ }
56
+
57
+ /**
58
+ * Creates an untyped materialiser input spec. This is a low-level escape hatch
59
+ * for materialiser kinds not yet covered by the generated helpers.
60
+ *
61
+ * Prefer the typed helpers in the `materialisers` namespace (e.g.
62
+ * `materialisers.balanceOf()`, `materialisers.directDeposit()`) which provide
63
+ * compile-time config validation.
64
+ *
65
+ * @param kind - The materialiser type (e.g. `"balanceOf"`, `"directDeposit"`).
66
+ * @param config - Optional materialiser-specific configuration.
67
+ * @returns A {@link MaterialiserInput} for use in {@link ComposeRunInput.inputs}.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * const run = {
72
+ * inputs: { token: materialiser('customKind', { myParam: '0x...' }) },
73
+ * signer: '0x...',
74
+ * };
75
+ * ```
76
+ */
77
+ export const materialiser = (
78
+ kind: string,
79
+ config: Record<string, unknown> = {},
80
+ ): MaterialiserInput => ({
81
+ kind,
82
+ ...config,
83
+ });
84
+
85
+ /**
86
+ * Assembles a {@link ComposeRun} object from individual parameters.
87
+ * Used internally by the SDK; prefer {@link ComposeRunInput} for external use.
88
+ *
89
+ * @internal
90
+ */
91
+ export const buildRun = (run: {
92
+ inputs: Record<string, InputSpec>;
93
+ preconditions?: readonly Precondition[];
94
+ signer: string;
95
+ assumptions?: Record<string, bigint>;
96
+ referrer?: string;
97
+ maxPriceImpactBps?: number;
98
+ sweepTo?: SweepTo;
99
+ simulationPolicy?: SimulationPolicy;
100
+ checkOnChainAllowances?: boolean;
101
+ }): ComposeRun => ({
102
+ inputs: run.inputs,
103
+ ...(run.preconditions?.length && { preconditions: run.preconditions }),
104
+ signer: run.signer,
105
+ ...(run.assumptions && { assumptions: run.assumptions }),
106
+ ...(run.referrer != null && { referrer: run.referrer }),
107
+ ...(run.maxPriceImpactBps != null && {
108
+ maxPriceImpactBps: run.maxPriceImpactBps,
109
+ }),
110
+ ...(run.sweepTo != null && { sweepTo: run.sweepTo }),
111
+ ...(run.simulationPolicy != null && {
112
+ simulationPolicy: run.simulationPolicy,
113
+ }),
114
+ ...(run.checkOnChainAllowances != null && {
115
+ checkOnChainAllowances: run.checkOnChainAllowances,
116
+ }),
117
+ });
package/src/sdk.ts ADDED
@@ -0,0 +1,173 @@
1
+ import type {
2
+ ComposeCompileRequest,
3
+ ComposeCompileResult,
4
+ InputSpec,
5
+ } from '@lifi/compose-spec';
6
+
7
+ import {
8
+ createFlowBuilderCore,
9
+ type FlowBuilderCore,
10
+ type FlowOptions,
11
+ type TypedFlow,
12
+ } from './authoring/FlowBuilderCore.js';
13
+ import { type ComposeClient, createComposeClient } from './client.js';
14
+ import {
15
+ bindGeneratedOps,
16
+ type GeneratedOps,
17
+ } from './generated/operations.generated.js';
18
+ import { buildRun, type ComposeRunInput } from './run/inputs.js';
19
+ import type { InputSchema } from './types.js';
20
+
21
+ export type { ComposeRunInput };
22
+
23
+ /**
24
+ * A flow builder augmented with generated operation methods and a `compile` method
25
+ * that submits the flow to the Compose backend for compilation.
26
+ *
27
+ * Created via {@link ComposeSdk.flow}.
28
+ *
29
+ * @typeParam T - The input schema describing the flow's required inputs.
30
+ */
31
+ export type FlowBuilder<T extends InputSchema = InputSchema> =
32
+ FlowBuilderCore<T> &
33
+ GeneratedOps & {
34
+ /**
35
+ * Builds the flow document from the current builder state and submits it
36
+ * to the Compose API for compilation.
37
+ *
38
+ * @param run - Runtime inputs, preconditions, and signer address.
39
+ * @returns The compiled transaction calldata and metadata.
40
+ * @throws {@link ComposeError} on network, validation, or server errors.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * const result = await builder.compile({
45
+ * inputs: { token: materialisers.balanceOf({}) },
46
+ * signer: '0xYourAddress...',
47
+ * });
48
+ * console.log(result.calldata);
49
+ * ```
50
+ */
51
+ readonly compile: (
52
+ run: ComposeRunInput<T>,
53
+ ) => Promise<ComposeCompileResult>;
54
+ };
55
+
56
+ /**
57
+ * Configuration for creating a Compose SDK instance.
58
+ */
59
+ export interface ComposeSdkOptions {
60
+ /** Base URL of the Compose API (e.g. `"https://li.quest"`). */
61
+ readonly baseUrl: string;
62
+ /** Optional custom `fetch` implementation. Defaults to `globalThis.fetch`. */
63
+ readonly fetch?: typeof globalThis.fetch;
64
+ /** Optional LI.FI API key for authenticated access. Sent as the `x-lifi-api-key` header on every request. */
65
+ readonly apiKey?: string;
66
+ }
67
+
68
+ /**
69
+ * The top-level Compose SDK interface.
70
+ *
71
+ * Provides methods to build flows, compile them into executable calldata, and
72
+ * interact with the Compose API directly.
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * import { createComposeSdk, resources, materialisers } from '@lifi/composer-sdk';
77
+ *
78
+ * const sdk = createComposeSdk({ baseUrl: 'https://li.quest' });
79
+ *
80
+ * const builder = sdk.flow(1, {
81
+ * inputs: { usdc: resources.erc20('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 1) },
82
+ * });
83
+ *
84
+ * builder.lifi.swap('swap1', {
85
+ * bind: { amountIn: builder.inputs.usdc },
86
+ * config: { resourceOut: resources.native(1) },
87
+ * });
88
+ *
89
+ * const result = await builder.compile({
90
+ * inputs: { usdc: materialisers.balanceOf({}) },
91
+ * signer: '0xYourAddress...',
92
+ * });
93
+ * ```
94
+ */
95
+ export interface ComposeSdk {
96
+ /** Low-level HTTP client for the Compose API. */
97
+ readonly client: ComposeClient;
98
+ /**
99
+ * Creates a new flow builder targeting the given chain.
100
+ * @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).
101
+ * @param options - Flow configuration including input declarations.
102
+ * @returns A {@link FlowBuilder} with generated operation methods and a `compile` method.
103
+ * @throws Error if any resource input's `chainId` doesn't match the flow's `chainId`.
104
+ */
105
+ readonly flow: <T extends InputSchema>(
106
+ chainId: number,
107
+ options: FlowOptions<T>,
108
+ ) => FlowBuilder<T>;
109
+ /**
110
+ * Builds a raw compile request without sending it. Useful for inspecting the
111
+ * request payload or submitting it through a custom transport.
112
+ * @param flow - A built flow document (from `builder.build()`).
113
+ * @param run - Runtime inputs, preconditions, and signer address.
114
+ * @returns A {@link ComposeCompileRequest} ready to send to the Compose API.
115
+ */
116
+ readonly request: <T extends InputSchema>(
117
+ flow: TypedFlow<T>,
118
+ run: ComposeRunInput<T>,
119
+ ) => ComposeCompileRequest;
120
+ }
121
+
122
+ /**
123
+ * Creates a new Compose SDK instance.
124
+ *
125
+ * @param options - SDK configuration including the API base URL and optional fetch implementation.
126
+ * @returns A {@link ComposeSdk} instance.
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * const sdk = createComposeSdk({ baseUrl: 'https://li.quest' });
131
+ * ```
132
+ */
133
+ export const createComposeSdk = (options: ComposeSdkOptions): ComposeSdk => {
134
+ const composeClient = createComposeClient(options);
135
+
136
+ const request = <T extends InputSchema>(
137
+ flowDoc: TypedFlow<T>,
138
+ run: ComposeRunInput<T>,
139
+ ): ComposeCompileRequest => ({
140
+ flow: flowDoc,
141
+ run: buildRun({
142
+ inputs: run.inputs as Record<string, InputSpec>,
143
+ preconditions: run.preconditions,
144
+ signer: run.signer,
145
+ assumptions: run.assumptions as Record<string, bigint> | undefined,
146
+ referrer: run.referrer,
147
+ maxPriceImpactBps: run.maxPriceImpactBps,
148
+ sweepTo: run.sweepTo,
149
+ simulationPolicy: run.simulationPolicy,
150
+ checkOnChainAllowances: run.checkOnChainAllowances,
151
+ }),
152
+ });
153
+
154
+ const flow = <T extends InputSchema>(
155
+ chainId: number,
156
+ opts: FlowOptions<T>,
157
+ ): FlowBuilder<T> => {
158
+ const core = createFlowBuilderCore(chainId, opts);
159
+ const builder = Object.assign(core, bindGeneratedOps(core));
160
+
161
+ const compile = async (
162
+ run: ComposeRunInput<T>,
163
+ ): Promise<ComposeCompileResult> => {
164
+ const flowDoc = builder.build();
165
+ const req = request(flowDoc, run);
166
+ return composeClient.compile(req);
167
+ };
168
+
169
+ return Object.assign(builder, { compile });
170
+ };
171
+
172
+ return { client: composeClient, flow, request };
173
+ };
package/src/types.ts ADDED
@@ -0,0 +1,101 @@
1
+ import type { Ref } from '@lifi/compose-spec';
2
+ import {
3
+ InputSpec,
4
+ MaterialiserInput,
5
+ Resource,
6
+ SolType,
7
+ } from '@lifi/compose-spec';
8
+
9
+ /**
10
+ * A string that represents a non-negative integer (e.g. "1000000000").
11
+ * Uses a template literal type so that only numeric-looking strings
12
+ * are assignable at compile time.
13
+ */
14
+ export type IntegerString = `${bigint}`;
15
+
16
+ /**
17
+ * Accepted input for integer-string config fields.
18
+ * Callers may pass either a numeric string ("1000000000") or a native bigint
19
+ * (1000000000n). Bigint values are stringified automatically during JSON
20
+ * serialization via the SDK's `bigintReplacer`.
21
+ */
22
+ export type IntegerStringInput = IntegerString | bigint;
23
+
24
+ /**
25
+ * A `0x`-prefixed hex string representing an Ethereum address.
26
+ * Template literal type catches obviously wrong values at compile time.
27
+ */
28
+ export type Address = `0x${string}`;
29
+
30
+ /** The universe of output port kinds: Solidity scalar types plus `'resource'`. */
31
+ export type OutputKind = SolType | 'resource';
32
+
33
+ /**
34
+ * Maps an ABI parameter type string (from abitype's `ParseAbiItem`) to the
35
+ * closest `OutputKind`. When the ABI type is one of the supported `SolType`
36
+ * scalars, the mapping is exact; for all other Solidity types (e.g. tuples,
37
+ * fixed-point decimals) it falls back to `SolType` — accepting any scalar
38
+ * handle but not `'resource'` handles.
39
+ *
40
+ * The fallback excludes `'resource'` because every Solidity type is a scalar;
41
+ * resource handles carry token-amount semantics that should only flow into
42
+ * slots explicitly declared as resources.
43
+ *
44
+ * Extending `SolType` with new members automatically widens the exact-match
45
+ * branch — no changes needed here.
46
+ */
47
+ export type AbiTypeToOutputKind<T extends string> = T extends SolType
48
+ ? T
49
+ : SolType;
50
+
51
+ /**
52
+ * A typed `$ref` pointer carrying a phantom type parameter.
53
+ * Extends `Ref` so it is accepted anywhere a plain `Ref` is.
54
+ * The `__outputKind` field is never set at runtime — it exists only
55
+ * for TypeScript's structural type checker to distinguish typed refs.
56
+ */
57
+ export interface TypedRef<T extends OutputKind = OutputKind> extends Ref {
58
+ readonly __outputKind?: T;
59
+ }
60
+
61
+ /**
62
+ * An input declaration in a flow schema.
63
+ * `Resource` values become resource inputs (token amounts);
64
+ * `SolType` strings become handle inputs (scalars like addresses).
65
+ */
66
+ export type InputDecl = Resource | SolType;
67
+
68
+ /**
69
+ * A record mapping input names to their declarations.
70
+ * Used as the type parameter for generic flow builders and requests.
71
+ */
72
+ export type InputSchema = Record<string, InputDecl>;
73
+
74
+ /**
75
+ * Maps an input declaration to the allowed runtime value type.
76
+ * Resource inputs accept materialisers or literal amounts.
77
+ * Handle inputs accept the scalar type matching their SolType.
78
+ */
79
+ export type InputSpecOf<D> = D extends Resource
80
+ ? MaterialiserInput | IntegerStringInput
81
+ : D extends 'address'
82
+ ? Address
83
+ : D extends 'bool'
84
+ ? boolean
85
+ : D extends `${'u' | ''}int${string}`
86
+ ? IntegerStringInput
87
+ : D extends `bytes${string}`
88
+ ? `0x${string}`
89
+ : D extends 'string'
90
+ ? string
91
+ : InputSpec;
92
+
93
+ /**
94
+ * A guard applied to an operation, with the `port` field constrained
95
+ * to a specific set of output port names.
96
+ */
97
+ export interface TypedGuard<Port extends string = string> {
98
+ readonly kind: string;
99
+ readonly port: Port;
100
+ readonly [key: string]: unknown;
101
+ }