@lifi/composer-sdk 0.11.3 → 0.13.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.
Files changed (48) hide show
  1. package/README.md +3 -3
  2. package/dist/authoring/raw.cjs +10 -2
  3. package/dist/authoring/raw.cjs.map +1 -1
  4. package/dist/authoring/raw.d.cts +10 -2
  5. package/dist/authoring/raw.d.ts +10 -2
  6. package/dist/authoring/raw.js +10 -2
  7. package/dist/authoring/raw.js.map +1 -1
  8. package/dist/authoring/signatureArgs.cjs +10 -3
  9. package/dist/authoring/signatureArgs.cjs.map +1 -1
  10. package/dist/authoring/signatureArgs.d.cts +23 -16
  11. package/dist/authoring/signatureArgs.d.ts +23 -16
  12. package/dist/authoring/signatureArgs.js +10 -3
  13. package/dist/authoring/signatureArgs.js.map +1 -1
  14. package/dist/client.cjs +1 -1
  15. package/dist/client.js +1 -1
  16. package/dist/generated/config.generated.d.cts +6 -18
  17. package/dist/generated/config.generated.d.ts +6 -18
  18. package/dist/generated/operations.generated.cjs.map +1 -1
  19. package/dist/generated/operations.generated.d.cts +1 -1
  20. package/dist/generated/operations.generated.d.ts +1 -1
  21. package/dist/generated/operations.generated.js.map +1 -1
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +2 -2
  24. package/dist/index.d.ts +2 -2
  25. package/dist/index.js.map +1 -1
  26. package/dist/run/inputs.cjs +0 -1
  27. package/dist/run/inputs.cjs.map +1 -1
  28. package/dist/run/inputs.d.cts +0 -8
  29. package/dist/run/inputs.d.ts +0 -8
  30. package/dist/run/inputs.js +0 -1
  31. package/dist/run/inputs.js.map +1 -1
  32. package/dist/sdk.cjs +0 -1
  33. package/dist/sdk.cjs.map +1 -1
  34. package/dist/sdk.js +0 -1
  35. package/dist/sdk.js.map +1 -1
  36. package/package.json +2 -2
  37. package/src/authoring/raw.ts +10 -2
  38. package/src/authoring/signatureArgs.ts +53 -23
  39. package/src/examples/continuationBridgeSettle.ts +1 -2
  40. package/src/examples/continuationExactInvoice.ts +341 -0
  41. package/src/examples/continuationSettle.ts +1 -1
  42. package/src/examples/run.ts +27 -0
  43. package/src/generated/config.generated.ts +16 -31
  44. package/src/generated/operations.generated.ts +1 -1
  45. package/src/index.ts +2 -1
  46. package/src/run/inputs.ts +0 -9
  47. package/src/sdk.ts +0 -1
  48. package/src/examples/swapWithFee.ts +0 -59
@@ -0,0 +1,341 @@
1
+ import type { ComposeCompileRequest, Flow } from '@lifi/compose-spec';
2
+
3
+ import {
4
+ type ComposeSdk,
5
+ type ContinuationSettleConfig,
6
+ createComposeSdk,
7
+ materialisers,
8
+ raw,
9
+ resources,
10
+ } from '../index.js';
11
+ import type { Address } from '../types.js';
12
+
13
+ import { API_KEY, BASE_URL, RECIPIENT } from './config.js';
14
+
15
+ const ARBITRUM = 42161;
16
+ const BASE = 8453;
17
+ const ARB_USDC = '0xaf88d065e77c8cC2239327C5EDb3A432268e5831';
18
+ const USDC = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
19
+ const WETH = '0x4200000000000000000000000000000000000006';
20
+ // Request Network's ERC20FeeProxy on Base. It moves `amount` to `to` and
21
+ // `feeAmount` to `feeAddress` from the caller with `transferFrom`, and emits
22
+ // `TransferWithReferenceAndFee` with the payment reference: the event that
23
+ // marks the invoice paid.
24
+ const ERC20_FEE_PROXY = '0x1892196E80C4c17ea5100Da765Ab48c1fE2Fb814';
25
+ const VALIDITY_WINDOW_MS = 3_600_000;
26
+
27
+ /** A Request Network invoice payable in USDC on Base. */
28
+ export interface UsdcInvoice {
29
+ readonly payee: Address;
30
+ // USDC base units (6 decimals) paid to `payee`.
31
+ readonly amount: bigint;
32
+ // USDC base units paid to `feeAddress`; may be 0.
33
+ readonly fee: bigint;
34
+ readonly feeAddress: Address;
35
+ // The invoice's payment reference (8 bytes for Request Network).
36
+ readonly paymentReference: `0x${string}`;
37
+ }
38
+
39
+ // A sample invoice for the examples: 990 USDC to the payee plus a 10 USDC fee.
40
+ export const SAMPLE_INVOICE: UsdcInvoice = {
41
+ payee: RECIPIENT,
42
+ amount: 990_000_000n,
43
+ fee: 10_000_000n,
44
+ feeAddress: '0x2222222222222222222222222222222222222222',
45
+ paymentReference: '0x8c6f1d3b4a5e7c21',
46
+ };
47
+
48
+ export interface ContinuationExactInvoiceInput {
49
+ readonly owner: Address;
50
+ readonly invoice: UsdcInvoice;
51
+ // USDC base units the escrow is funded with. Must exceed
52
+ // `invoice.amount + invoice.fee`: the surplus, the settle's only outcome,
53
+ // returns to `owner`, and an outcome must commit a positive floor.
54
+ readonly usdcAmount: `${bigint}`;
55
+ }
56
+
57
+ export interface ContinuationExactSwapInvoiceInput {
58
+ readonly owner: Address;
59
+ readonly invoice: UsdcInvoice;
60
+ // WETH base units (18 decimals) swapped to USDC. The swap's guaranteed
61
+ // minimum output must exceed `invoice.amount + invoice.fee`, for the same
62
+ // reason as `usdcAmount` above.
63
+ readonly wethAmount: `${bigint}`;
64
+ }
65
+
66
+ export interface ContinuationExactIntentInvoiceInput {
67
+ readonly owner: Address;
68
+ readonly invoice: UsdcInvoice;
69
+ // Native ETH base units (18 decimals) on Arbitrum, swapped to Arbitrum
70
+ // USDC. The swap's guaranteed minimum output must cover the input the
71
+ // solver asks for the invoice total plus one unit; the rest returns to
72
+ // `owner`.
73
+ readonly ethAmount: `${bigint}`;
74
+ }
75
+
76
+ /**
77
+ * The leg every example settles: split the invoice total off the escrowed
78
+ * USDC, pay it through `ERC20FeeProxy`, and leave the surplus in the leg's
79
+ * proxy as the settle's outcome, if the settle commits one.
80
+ *
81
+ * `core.call` declares no settlement verification, so only an exact settle
82
+ * may run it. The invoice terms are constants of the leg document, so each
83
+ * argument is a `raw.literal` of the parameter's Solidity type. The leg names
84
+ * no funding amount: at fill the executor's proxy sweeps the escrowed USDC
85
+ * into `input.funding`.
86
+ */
87
+ const buildInvoiceLeg = (sdk: ComposeSdk, invoice: UsdcInvoice): Flow => {
88
+ const leg = sdk.flow(BASE, {
89
+ name: 'pay-invoice-leg',
90
+ inputs: { funding: resources.erc20(USDC, BASE) },
91
+ });
92
+ // `head` is the invoice total; `tail`, the surplus, stays in the proxy.
93
+ const { head } = leg.core.splitAt('invoice', {
94
+ bind: { source: leg.inputs.funding },
95
+ config: { amount: `${invoice.amount + invoice.fee}` },
96
+ });
97
+ leg.core.call('pay', {
98
+ resource: head,
99
+ bind: {
100
+ tokenAddress: raw.literal('address', USDC),
101
+ to: raw.literal('address', invoice.payee),
102
+ amount: raw.literal('uint256', `${invoice.amount}`),
103
+ paymentReference: raw.literal('bytes', invoice.paymentReference),
104
+ feeAmount: raw.literal('uint256', `${invoice.fee}`),
105
+ feeAddress: raw.literal('address', invoice.feeAddress),
106
+ },
107
+ config: {
108
+ target: ERC20_FEE_PROXY,
109
+ functionSignature:
110
+ 'function transferFromWithReferenceAndFee(address tokenAddress, address to, uint256 amount, bytes paymentReference, uint256 feeAmount, address feeAddress)',
111
+ // The fee proxy pulls the USDC with `transferFrom`.
112
+ approvals: [{ spender: ERC20_FEE_PROXY }],
113
+ },
114
+ });
115
+ return leg.build();
116
+ };
117
+
118
+ /**
119
+ * The exact settle config every example shares: the leg's leftover USDC
120
+ * returns to `owner` on Base, and so does the escrow if it expires unfilled.
121
+ */
122
+ const invoiceSettleConfig = (
123
+ sdk: ComposeSdk,
124
+ owner: Address,
125
+ invoice: UsdcInvoice,
126
+ ): ContinuationSettleConfig => ({
127
+ exact: true,
128
+ outcomes: [{ token: USDC, destination: owner, chainId: BASE }],
129
+ validity: { expiresAtMs: Date.now() + VALIDITY_WINDOW_MS },
130
+ provider: 'intent-factory',
131
+ refund: owner,
132
+ continuationFlow: buildInvoiceLeg(sdk, invoice),
133
+ });
134
+
135
+ /**
136
+ * Escrow USDC on Base for an exact continuation leg that pays a Request
137
+ * Network invoice, and return the surplus to the owner.
138
+ *
139
+ * Demonstrates:
140
+ * - `exact: true` on `continuation.settle`: the escrow is bound to the leg's
141
+ * compiled calldata, so the solver runs exactly those bytes and chooses
142
+ * nothing. A committed (non-exact) leg rejects `core.call`, because a
143
+ * balance cannot prove that an invoice was paid; an exact leg admits it.
144
+ * - A leg that pays a third party (`invoice.payee`), which only an exact leg
145
+ * may do: its bytes are fixed at compile time.
146
+ * - The surplus (`usdcAmount` minus the invoice total) as the outcome. The
147
+ * compile proves its floor at the escrow's funding floor, so `minAmount` is
148
+ * omitted. A surplus of 0 proves no floor, and the compile rejects it.
149
+ * - Funding from a declared input, transferred into the escrow inline by the
150
+ * user's transaction.
151
+ *
152
+ * Reading the response:
153
+ * - `settlements.settle.escrow` holds the registered escrow. `binding` holds
154
+ * what the escrow is bound to: the solver's executor (`executionTarget`),
155
+ * the compiled leg (`calldata`), its `approvals`, and the `payload` the
156
+ * settlement service hashes into `payloadHash`.
157
+ * - Inline funding means the user's `execute` transaction funds the escrow.
158
+ * Before submitting it, check that `payloadHash` is the hash of `payload`,
159
+ * for example with viem:
160
+ * `keccak256(binding.payload) === binding.payloadHash.toLowerCase()`.
161
+ * On a mismatch, do not submit.
162
+ *
163
+ * The exact-leg rules:
164
+ * - No leg node may quote off-chain or declare an expiring route:
165
+ * `lifi.swap`, `paraswap.buy`, `core.peek` and any prepared op fail
166
+ * `validation_error` at the leg node, because the bound bytes cannot be
167
+ * re-quoted at fill.
168
+ * - The settle's funding must be an ERC-20 from a declared input, an upstream
169
+ * output, or a `lifi.bridge` or `lifiIntents.order` delivery into the
170
+ * escrow: native funding fails `validation_error`.
171
+ * - The deployment must serve exact legs (an intent-factory provider
172
+ * configured with the solver's executor); elsewhere the settle fails
173
+ * `validation_error` before any registration.
174
+ */
175
+ export const buildContinuationExactInvoiceExample = ({
176
+ owner,
177
+ invoice,
178
+ usdcAmount,
179
+ }: ContinuationExactInvoiceInput): {
180
+ flow: Flow;
181
+ request: ComposeCompileRequest;
182
+ } => {
183
+ const sdk = createComposeSdk({ baseUrl: BASE_URL, apiKey: API_KEY });
184
+
185
+ const builder = sdk.flow(BASE, {
186
+ name: 'pay-invoice',
187
+ inputs: { usdc: resources.erc20(USDC, BASE) },
188
+ });
189
+ builder.continuation.settle('settle', {
190
+ bind: { input: builder.inputs.usdc },
191
+ config: invoiceSettleConfig(sdk, owner, invoice),
192
+ });
193
+
194
+ const flow = builder.build();
195
+
196
+ // No `sweepTo`: the funding moves into the escrow, and the surplus reaches
197
+ // the owner through the settlement, never through the user's proxy.
198
+ const request = sdk.request(flow, {
199
+ signer: owner,
200
+ inputs: {
201
+ usdc: materialisers.directDeposit({ amount: usdcAmount }),
202
+ },
203
+ // The price-impact check compares the flow's input value with its output
204
+ // value. The invoice payment leaves the flow, so the check would count it
205
+ // as lost value (1,050 USDC in, a 50 USDC surplus out: 95% impact) and
206
+ // reject the compile. `0` disables the check.
207
+ maxPriceImpactBps: 0,
208
+ });
209
+
210
+ return { flow, request };
211
+ };
212
+
213
+ /**
214
+ * Pay the same USDC invoice from WETH: the user's transaction swaps WETH to
215
+ * USDC and escrows the swap output for the exact leg.
216
+ *
217
+ * Demonstrates:
218
+ * - An exact settle funded by an upstream output (`swap.amountOut`). The
219
+ * escrow's funding floor is the swap's guaranteed minimum output, and the
220
+ * leg is proven at that floor, so the minimum must exceed the invoice total.
221
+ * - The quote rule applies to the leg only. The main flow runs inside the
222
+ * user's transaction, so its `lifi.swap` may quote; the leg, bound to fixed
223
+ * bytes until the fill, may not.
224
+ */
225
+ export const buildContinuationExactSwapInvoiceExample = ({
226
+ owner,
227
+ invoice,
228
+ wethAmount,
229
+ }: ContinuationExactSwapInvoiceInput): {
230
+ flow: Flow;
231
+ request: ComposeCompileRequest;
232
+ } => {
233
+ const sdk = createComposeSdk({ baseUrl: BASE_URL, apiKey: API_KEY });
234
+
235
+ const builder = sdk.flow(BASE, {
236
+ name: 'swap-and-pay-invoice',
237
+ inputs: { weth: resources.erc20(WETH, BASE) },
238
+ });
239
+ const swap = builder.lifi.swap('swap', {
240
+ bind: { amountIn: builder.inputs.weth },
241
+ config: { resourceOut: resources.erc20(USDC, BASE) },
242
+ });
243
+ builder.continuation.settle('settle', {
244
+ bind: { input: swap.amountOut },
245
+ config: invoiceSettleConfig(sdk, owner, invoice),
246
+ });
247
+
248
+ const flow = builder.build();
249
+
250
+ const request = sdk.request(flow, {
251
+ signer: owner,
252
+ inputs: {
253
+ weth: materialisers.directDeposit({ amount: wethAmount }),
254
+ },
255
+ // The invoice payment leaves the flow, so the price-impact check would
256
+ // count it as lost value. `0` disables the check, and with it the only
257
+ // bound on the swap's price against the market. The swap's minimum output
258
+ // bounds only slippage against its own quote. Before signing, compare
259
+ // that minimum (`settlements.settle.escrow.floor` in the response) with
260
+ // an independent WETH price.
261
+ maxPriceImpactBps: 0,
262
+ });
263
+
264
+ return { flow, request };
265
+ };
266
+
267
+ /**
268
+ * Pay the same USDC invoice on Base from ETH on Arbitrum: the user's
269
+ * transaction swaps ETH to Arbitrum USDC and opens an exact-output LI.FI
270
+ * Intents order whose solver delivers Base USDC into the escrow.
271
+ *
272
+ * Demonstrates:
273
+ * - An exact settle funded by a `lifiIntents.order` delivery: the order omits
274
+ * `destination`, the solver delivers into the escrow on Base, and the user
275
+ * signs one transaction on Arbitrum.
276
+ * - `exactAmountOut` `T`, the invoice total, and `outcomes: []`. The leg pays
277
+ * all of `T`, so nothing is left on Base and the settle commits no outcome.
278
+ * An outcome would need a positive floor, so it would cost an extra unit of
279
+ * funding that only lands on Base as dust.
280
+ * - The escrow registers at `T` itself, with no drift margin: an exact-output
281
+ * order delivers exactly `T` on both of the compile's quotes, so the leg
282
+ * compiles at `T`.
283
+ *
284
+ * Sizing the deposit:
285
+ * - The solver quotes the Arbitrum USDC input `X` it needs for exactly `T`,
286
+ * and the order pulls exactly `X`. The swap's minimum output must cover
287
+ * `X`, or the compile fails with a 422 `preparation_error` whose failed op
288
+ * is a `validation_error` naming both amounts. Deposit enough ETH for the
289
+ * swap's minimum to clear `X` with room to spare.
290
+ * - The rest of the swap output (`order.unspentIn`) returns to `owner` as
291
+ * Arbitrum USDC through `sweepTo`, in the same transaction. All slack
292
+ * (swap slippage, the solver's price, the sizing buffer) lands there, not
293
+ * on Base.
294
+ */
295
+ export const buildContinuationExactIntentInvoiceExample = ({
296
+ owner,
297
+ invoice,
298
+ ethAmount,
299
+ }: ContinuationExactIntentInvoiceInput): {
300
+ flow: Flow;
301
+ request: ComposeCompileRequest;
302
+ } => {
303
+ const sdk = createComposeSdk({ baseUrl: BASE_URL, apiKey: API_KEY });
304
+
305
+ const builder = sdk.flow(ARBITRUM, {
306
+ name: 'intent-and-pay-invoice',
307
+ inputs: { eth: resources.native(ARBITRUM) },
308
+ });
309
+ const swap = builder.lifi.swap('swap', {
310
+ bind: { amountIn: builder.inputs.eth },
311
+ config: { resourceOut: resources.erc20(ARB_USDC, ARBITRUM) },
312
+ });
313
+ const order = builder.lifiIntents.order('order', {
314
+ bind: { amountIn: swap.amountOut },
315
+ config: {
316
+ resourceOut: resources.erc20(USDC, BASE),
317
+ exactAmountOut: `${invoice.amount + invoice.fee}`,
318
+ },
319
+ });
320
+ builder.continuation.settle('settle', {
321
+ bind: { input: order.amountOut },
322
+ config: { ...invoiceSettleConfig(sdk, owner, invoice), outcomes: [] },
323
+ });
324
+
325
+ const flow = builder.build();
326
+
327
+ const request = sdk.request(flow, {
328
+ signer: owner,
329
+ inputs: {
330
+ eth: materialisers.directDeposit({ amount: ethAmount }),
331
+ },
332
+ // Returns the order's unspent Arbitrum USDC to the owner.
333
+ sweepTo: owner,
334
+ // The invoice payment leaves the flow, so the price-impact check would
335
+ // count it as lost value. `0` disables the check; the swap is then bounded
336
+ // only by its slippage against its own quote.
337
+ maxPriceImpactBps: 0,
338
+ });
339
+
340
+ return { flow, request };
341
+ };
@@ -50,7 +50,7 @@ export interface ContinuationSettleInput {
50
50
  * settlement account, not the user). Never set the leg's own epilogue. At
51
51
  * commit the composer appends the settlement epilogue, which forwards each
52
52
  * outcome to the provider's recipient and the residual to `refund`.
53
- * - Omit `funding` and `perpetual` when the settle input is a bridge's
53
+ * - Omit `funding` when the settle input is a bridge's
54
54
  * `amountOut` (see `continuationBridgeSettle.ts`).
55
55
  * - `minAmount` is optional: a guard or an op floor on the outcome token
56
56
  * proves it, and an unconsumed funding input proves the full funding floor.
@@ -18,6 +18,9 @@
18
18
  * consolidate-eth — consolidate ERC-20 balances to native ETH
19
19
  * continuation-settle — swap USDC to WETH on Base, escrow it for a deferred settlement
20
20
  * continuation-bridge-settle — bridge Arbitrum USDC into a Base settlement escrow
21
+ * continuation-exact-invoice — escrow USDC on Base for an exact leg that pays a Request Network invoice
22
+ * continuation-exact-swap-invoice — swap WETH to USDC on Base, escrow it for the same exact invoice leg
23
+ * continuation-exact-intent-invoice — swap Arbitrum ETH to USDC, order exactly the invoice total on Base for the same exact leg, with no outcome
21
24
  * deposit-proxy — deposit tokens already on the proxy into Aave
22
25
  * dust-sweep — split USDC 80/20 and sweep leftover dust
23
26
  * swap — swap WETH to USDC via LI.FI
@@ -65,6 +68,12 @@ import { API_KEY, BASE_URL, OWNER, PROXY, RECIPIENT } from './config.js';
65
68
  import { buildConsolidateToEth } from './consolidateToEth.js';
66
69
  import { buildConsolidateStablesToUsdc } from './consolidateToUsdc.js';
67
70
  import { buildContinuationBridgeSettleExample } from './continuationBridgeSettle.js';
71
+ import {
72
+ buildContinuationExactIntentInvoiceExample,
73
+ buildContinuationExactInvoiceExample,
74
+ buildContinuationExactSwapInvoiceExample,
75
+ SAMPLE_INVOICE,
76
+ } from './continuationExactInvoice.js';
68
77
  import { buildContinuationSettleExample } from './continuationSettle.js';
69
78
  import { buildDepositFromProxy } from './depositFromProxy.js';
70
79
  import { buildDustSweepExample } from './dustSweep.js';
@@ -142,6 +151,24 @@ const EXAMPLES: Record<string, () => ComposeCompileRequest> = {
142
151
  buildContinuationSettleExample({ owner: OWNER }).request,
143
152
  'continuation-bridge-settle': () =>
144
153
  buildContinuationBridgeSettleExample({ owner: OWNER }).request,
154
+ 'continuation-exact-invoice': () =>
155
+ buildContinuationExactInvoiceExample({
156
+ owner: OWNER,
157
+ invoice: SAMPLE_INVOICE,
158
+ usdcAmount: '1050000000',
159
+ }).request,
160
+ 'continuation-exact-swap-invoice': () =>
161
+ buildContinuationExactSwapInvoiceExample({
162
+ owner: OWNER,
163
+ invoice: SAMPLE_INVOICE,
164
+ wethAmount: '1000000000000000000',
165
+ }).request,
166
+ 'continuation-exact-intent-invoice': () =>
167
+ buildContinuationExactIntentInvoiceExample({
168
+ owner: OWNER,
169
+ invoice: SAMPLE_INVOICE,
170
+ ethAmount: '500000000000000000',
171
+ }).request,
145
172
  'deposit-proxy': () =>
146
173
  buildDepositFromProxy({
147
174
  owner: OWNER,
@@ -1230,7 +1230,7 @@ export interface ParaswapBuyConfig {
1230
1230
  */
1231
1231
  partnerAddress?: string;
1232
1232
  /**
1233
- * Integrator fee in basis points; non-negative integer string capped at 9000.
1233
+ * Paraswap partner fee in basis points; non-negative integer string capped at 9000.
1234
1234
  */
1235
1235
  partnerFeeBps?: string;
1236
1236
  }
@@ -1286,46 +1286,29 @@ export interface FlySwapConfig {
1286
1286
  export type Between86400000000000008640000000000000 = number;
1287
1287
 
1288
1288
  export interface ContinuationSettleConfig {
1289
- /**
1290
- * @minItems 1
1291
- */
1292
- outcomes: [
1293
- {
1294
- /**
1295
- * EVM address: 0x followed by 40 hex characters
1296
- */
1297
- token: Address;
1298
- minAmount?: IntegerStringInput;
1299
- /**
1300
- * EVM address: 0x followed by 40 hex characters
1301
- */
1302
- destination: Address;
1303
- chainId: Positive;
1304
- },
1305
- ...{
1306
- /**
1307
- * EVM address: 0x followed by 40 hex characters
1308
- */
1309
- token: Address;
1310
- minAmount?: IntegerStringInput;
1311
- /**
1312
- * EVM address: 0x followed by 40 hex characters
1313
- */
1314
- destination: Address;
1315
- chainId: Positive;
1316
- }[],
1317
- ];
1289
+ outcomes: {
1290
+ /**
1291
+ * EVM address: 0x followed by 40 hex characters
1292
+ */
1293
+ token: Address;
1294
+ minAmount?: IntegerStringInput;
1295
+ /**
1296
+ * EVM address: 0x followed by 40 hex characters
1297
+ */
1298
+ destination: Address;
1299
+ chainId: Positive;
1300
+ }[];
1318
1301
  continuationFlow?: Flow;
1319
1302
  validity: {
1320
1303
  expiresAtMs: Between86400000000000008640000000000000;
1321
1304
  };
1322
- perpetual?: boolean;
1323
1305
  provider?: string;
1324
1306
  funding?: 'inline' | 'external';
1325
1307
  /**
1326
1308
  * EVM address: 0x followed by 40 hex characters
1327
1309
  */
1328
1310
  refund?: Address;
1311
+ exact?: boolean;
1329
1312
  }
1330
1313
 
1331
1314
  export interface UniswapV2AddLiquidityConfig {
@@ -1436,6 +1419,7 @@ export interface LifiIntentsOrderConfig {
1436
1419
  slippage?: LessThan1;
1437
1420
  validitySeconds?: Between1300;
1438
1421
  exclusiveSeconds?: Between0120;
1422
+ exactAmountOut?: string;
1439
1423
  }
1440
1424
 
1441
1425
  export interface LifiIntentsRefundConfig {
@@ -1498,6 +1482,7 @@ export type DirectDepositMaterialiserConfig =
1498
1482
  | {
1499
1483
  allowNonExact: true;
1500
1484
  simAmount?: string;
1485
+ minAmount?: IntegerStringInput;
1501
1486
  };
1502
1487
 
1503
1488
  export interface CallMaterialiserConfig {
@@ -436,7 +436,7 @@ export interface CoreTransferArgs {
436
436
  readonly amount: Bindable<'resource'>;
437
437
  readonly recipient: Bindable<'address'>;
438
438
  };
439
- readonly config: CoreTransferConfig;
439
+ readonly config?: CoreTransferConfig;
440
440
  readonly guards?: readonly TypedGuard<'transferred'>[];
441
441
  }
442
442
 
package/src/index.ts CHANGED
@@ -49,7 +49,6 @@ export type {
49
49
  ComposeCompilePartialData,
50
50
  ComposeAction,
51
51
  ComposeFill,
52
- ComposeFee,
53
52
  ComposeUserProgramSimulation,
54
53
  ComposeWarning,
55
54
  ComposeCompileRequest,
@@ -100,10 +99,12 @@ export type {
100
99
  Erc20BalanceRequirement,
101
100
  NativeBalanceRequirement,
102
101
  Erc20AllowanceRequirement,
102
+ Permit2AllowanceRequirement,
103
103
  ContinuationIntent,
104
104
  ContinuationOutcome,
105
105
  SettlementWire,
106
106
  SettlementEscrowWire,
107
+ SettlementBindingWire,
107
108
  } from '@lifi/compose-spec';
108
109
  export {
109
110
  SIMULATE_MAX_TRACKED_BALANCES,
package/src/run/inputs.ts CHANGED
@@ -33,13 +33,6 @@ export interface ComposeRunInput<T extends InputSchema = InputSchema> {
33
33
  readonly assumptions?: { readonly [K in keyof T]?: bigint };
34
34
  /** Optional integrator referrer identifier. */
35
35
  readonly referrer?: string;
36
- /**
37
- * Optional integrator fee in basis points (1bp = 0.01%, max `9000` = 90%).
38
- * A non-zero value requires the request to be authenticated with an
39
- * integration-scoped API key — the integration is derived from the key, not
40
- * this field. Defaults to `0` (no fee) when omitted.
41
- */
42
- readonly integratorFeeBps?: number;
43
36
  /** Maximum acceptable price impact in basis points (e.g. `300` = 3%). */
44
37
  readonly maxPriceImpactBps?: number;
45
38
  /**
@@ -123,7 +116,6 @@ export const buildRun = (run: {
123
116
  signer: string;
124
117
  assumptions?: Record<string, bigint>;
125
118
  referrer?: string;
126
- integratorFeeBps?: number;
127
119
  maxPriceImpactBps?: number;
128
120
  sweepTo?: ForwardTo;
129
121
  simulationPolicy?: SimulationPolicy;
@@ -137,7 +129,6 @@ export const buildRun = (run: {
137
129
  preconditions: run.preconditions?.length ? run.preconditions : undefined,
138
130
  assumptions: run.assumptions,
139
131
  referrer: run.referrer,
140
- integratorFeeBps: run.integratorFeeBps,
141
132
  maxPriceImpactBps: run.maxPriceImpactBps,
142
133
  sweepTo: run.sweepTo,
143
134
  simulationPolicy: run.simulationPolicy,
package/src/sdk.ts CHANGED
@@ -201,7 +201,6 @@ export const createComposeSdk = (options: ComposeSdkOptions): ComposeSdk => {
201
201
  signer: run.signer,
202
202
  assumptions: run.assumptions as Record<string, bigint> | undefined,
203
203
  referrer: run.referrer,
204
- integratorFeeBps: run.integratorFeeBps,
205
204
  maxPriceImpactBps: run.maxPriceImpactBps,
206
205
  sweepTo: run.sweepTo,
207
206
  simulationPolicy: run.simulationPolicy,
@@ -1,59 +0,0 @@
1
- import type { ComposeCompileRequest, Flow } from '@lifi/compose-spec';
2
-
3
- import { createComposeSdk, materialisers, resources } from '../index.js';
4
-
5
- import { API_KEY, BASE_URL, OWNER } from './config.js';
6
-
7
- const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
8
- const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
9
-
10
- /**
11
- * Swap WETH to USDC via LI.FI while collecting an integrator fee.
12
- *
13
- * Demonstrates:
14
- * - Setting `integratorFeeBps` on the compile request (50 bps = 0.5%)
15
- * - The fee is taken on the input token; the backend injects the fee transfer
16
- *
17
- * A non-zero `integratorFeeBps` requires the SDK to be configured with an
18
- * integration-scoped API key (`apiKey`); the integration is derived from the
19
- * key, not the request body.
20
- */
21
- export const buildSwapWithFeeExample = (): {
22
- flow: Flow;
23
- request: ComposeCompileRequest;
24
- } => {
25
- const sdk = createComposeSdk({ baseUrl: BASE_URL, apiKey: API_KEY });
26
-
27
- // Declare the flow with a single WETH input on Ethereum mainnet.
28
- const builder = sdk.flow(1, {
29
- name: 'swap-with-fee',
30
- inputs: {
31
- amountIn: resources.erc20(WETH, 1),
32
- },
33
- });
34
-
35
- // Swap WETH → USDC via LI.FI.
36
- builder.lifi.swap('swap', {
37
- bind: { amountIn: builder.inputs.amountIn },
38
- config: {
39
- resourceOut: resources.erc20(USDC, 1),
40
- slippage: 0.03,
41
- },
42
- });
43
-
44
- const flow = builder.build();
45
-
46
- // Build the compile request with a 50 bps (0.5%) integrator fee.
47
- const request = sdk.request(flow, {
48
- signer: OWNER,
49
- inputs: {
50
- amountIn: materialisers.directDeposit({
51
- amount: '1000000000000000000',
52
- }),
53
- },
54
- integratorFeeBps: 50,
55
- sweepTo: builder.context.sender,
56
- });
57
-
58
- return { flow, request };
59
- };