@lifi/composer-sdk 0.7.1 → 0.8.1

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 (32) hide show
  1. package/README.md +2 -0
  2. package/dist/client.cjs +1 -1
  3. package/dist/client.js +1 -1
  4. package/dist/generated/config.generated.cjs.map +1 -1
  5. package/dist/generated/config.generated.d.cts +77 -35
  6. package/dist/generated/config.generated.d.ts +77 -35
  7. package/dist/generated/guards.generated.cjs +6 -0
  8. package/dist/generated/guards.generated.cjs.map +1 -1
  9. package/dist/generated/guards.generated.d.cts +1 -1
  10. package/dist/generated/guards.generated.d.ts +1 -1
  11. package/dist/generated/guards.generated.js +5 -0
  12. package/dist/generated/guards.generated.js.map +1 -1
  13. package/dist/generated/operations.generated.cjs +27 -0
  14. package/dist/generated/operations.generated.cjs.map +1 -1
  15. package/dist/generated/operations.generated.d.cts +74 -2
  16. package/dist/generated/operations.generated.d.ts +74 -2
  17. package/dist/generated/operations.generated.js +27 -0
  18. package/dist/generated/operations.generated.js.map +1 -1
  19. package/dist/{guards.generated-M3VAIevI.d.cts → guards.generated-CDCgYGZo.d.cts} +8 -3
  20. package/dist/{guards.generated-BPLFwe7y.d.ts → guards.generated-CdYcs4h0.d.ts} +8 -3
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +3 -3
  23. package/dist/index.d.ts +3 -3
  24. package/dist/index.js.map +1 -1
  25. package/package.json +2 -2
  26. package/src/examples/run.ts +13 -0
  27. package/src/examples/uniswapV2AddLiquidity.ts +106 -0
  28. package/src/examples/uniswapV3Mint.ts +95 -0
  29. package/src/generated/config.generated.ts +82 -38
  30. package/src/generated/guards.generated.ts +9 -0
  31. package/src/generated/operations.generated.ts +133 -0
  32. package/src/index.ts +0 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifi/composer-sdk",
3
- "version": "0.7.1",
3
+ "version": "0.8.1",
4
4
  "description": "Public Composer SDK for building and submitting flows",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -47,7 +47,7 @@
47
47
  "example:staged": "tsx src/examples/run.ts --staged"
48
48
  },
49
49
  "peerDependencies": {
50
- "@lifi/compose-spec": "0.7.1"
50
+ "@lifi/compose-spec": "0.8.1"
51
51
  },
52
52
  "dependencies": {
53
53
  "abitype": "^1.2.3",
@@ -38,6 +38,8 @@
38
38
  * transfer — transfer full token balance to a recipient
39
39
  * partial-transfer — transfer a specific amount, keeping the remainder
40
40
  * untyped-ref — mix untypedOp with typed handles via raw.ref
41
+ * uniswap-v2-add — split USDC, swap half to WETH, add both to the Uniswap V2 pair
42
+ * uniswap-v3-mint — open a full-range Uniswap V3 USDC/WETH position
41
43
  * route-exact — wrap 0.1 native ETH into WETH via /compose/route
42
44
  * route-all — unwrap the whole WETH balance to ETH via /compose/route
43
45
  * supported-chains — list the chains this deployment supports, and guard on them
@@ -83,6 +85,8 @@ import { buildSwapWithAllowRevertExample } from './swapWithAllowRevert.js';
83
85
  import { buildSwapWithBalanceCheck } from './swapWithBalanceCheck.js';
84
86
  import { buildSwapWithOutputValidation } from './swapWithOutputValidation.js';
85
87
  import { buildPartialTransfer, buildTransferTokens } from './transferTokens.js';
88
+ import { buildUniswapV2AddLiquidity } from './uniswapV2AddLiquidity.js';
89
+ import { buildUniswapV3Mint } from './uniswapV3Mint.js';
86
90
  import { buildUntypedOpWithTypedRef } from './untypedOpWithTypedRef.js';
87
91
 
88
92
  const stringifyJson = (value: unknown) =>
@@ -196,6 +200,15 @@ const EXAMPLES: Record<string, () => ComposeCompileRequest> = {
196
200
  amount: '1000000000',
197
201
  }).request,
198
202
  'untyped-ref': () => buildUntypedOpWithTypedRef({ owner: OWNER }).request,
203
+ 'uniswap-v2-add': () =>
204
+ buildUniswapV2AddLiquidity({ owner: OWNER, usdcAmount: '1000000000' })
205
+ .request,
206
+ 'uniswap-v3-mint': () =>
207
+ buildUniswapV3Mint({
208
+ owner: OWNER,
209
+ usdcAmount: '1000000000',
210
+ wethAmount: '400000000000000000',
211
+ }).request,
199
212
  };
200
213
 
201
214
  // `/compose/route` examples build a `ComposeRouteRequest` and go to
@@ -0,0 +1,106 @@
1
+ import type { ComposeCompileRequest, Flow } from '@lifi/compose-spec';
2
+
3
+ import {
4
+ createComposeSdk,
5
+ guards,
6
+ materialisers,
7
+ resources,
8
+ } from '../index.js';
9
+ import type { Address } from '../types.js';
10
+
11
+ import { API_KEY, BASE_URL } from './config.js';
12
+
13
+ // Ethereum mainnet (chainId 1).
14
+ const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
15
+ const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
16
+ const UNISWAP_V2_ROUTER = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D';
17
+ const UNISWAP_V2_FACTORY = '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f';
18
+ const USDC_WETH_PAIR = '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc';
19
+
20
+ // Tolerance of the swap leg: the aggregator's `toAmountMin` lets the swap
21
+ // deliver up to 3% less WETH than quoted.
22
+ const SWAP_SLIPPAGE = 0.03;
23
+
24
+ export interface UniswapV2AddLiquidityInput {
25
+ readonly owner: Address;
26
+ readonly usdcAmount: `${bigint}`;
27
+ }
28
+
29
+ /**
30
+ * Deposit USDC alone into the Uniswap V2 USDC/WETH pair.
31
+ *
32
+ * - `core.split` halves the USDC input.
33
+ * - `lifi.swap` turns one half into WETH.
34
+ * - `uniswapV2.addLiquidity` deposits the other USDC half and the swapped
35
+ * WETH, minting the UNI-V2 LP token. Unused input comes back as residuals.
36
+ * - The request sweeps the LP token and the residuals to the signer.
37
+ */
38
+ export const buildUniswapV2AddLiquidity = ({
39
+ owner,
40
+ usdcAmount,
41
+ }: UniswapV2AddLiquidityInput): {
42
+ flow: Flow;
43
+ request: ComposeCompileRequest;
44
+ } => {
45
+ const sdk = createComposeSdk({ baseUrl: BASE_URL, apiKey: API_KEY });
46
+
47
+ const builder = sdk.flow(1, {
48
+ name: 'uniswap-v2-add-liquidity-usdc-weth',
49
+ inputs: {
50
+ usdcIn: resources.erc20(USDC, 1),
51
+ },
52
+ });
53
+
54
+ const { a: usdcHalf, b: usdcToSwap } = builder.core.split('split', {
55
+ bind: { source: builder.inputs.usdcIn },
56
+ config: { bps: 5000 },
57
+ });
58
+
59
+ const swap = builder.lifi.swap('swap', {
60
+ bind: { amountIn: usdcToSwap },
61
+ config: {
62
+ resourceOut: resources.erc20(WETH, 1),
63
+ slippage: SWAP_SLIPPAGE,
64
+ },
65
+ });
66
+
67
+ builder.uniswapV2.addLiquidity('add-liquidity', {
68
+ bind: {
69
+ tokenA: usdcHalf,
70
+ tokenB: swap.amountOut,
71
+ },
72
+ config: {
73
+ router: UNISWAP_V2_ROUTER,
74
+ factory: UNISWAP_V2_FACTORY,
75
+ pair: USDC_WETH_PAIR,
76
+ },
77
+ guards: [
78
+ // The router is called with zero minimums, so this band is the sandwich
79
+ // protection: it reverts unless the pool price read before the deposit
80
+ // stays within ±50 bps of the simulated price. It does not depend on the
81
+ // swap leg.
82
+ guards.band({ port: 'poolPrice', bps: 50 }),
83
+ // A swap that fills at its 3% minimum delivers less WETH, so the add
84
+ // mints less LP. The floor must cover that tolerance (300 bps) plus the
85
+ // 50 bps band, or a valid swap fill reverts the transaction.
86
+ guards.slippage({ port: 'liquidity', bps: 350 }),
87
+ ],
88
+ });
89
+
90
+ const flow = builder.build();
91
+
92
+ const request = sdk.request(flow, {
93
+ signer: owner,
94
+ inputs: {
95
+ usdcIn: materialisers.directDeposit({ amount: usdcAmount }),
96
+ },
97
+ // Sweep the LP token and the unused USDC/WETH back to the signer.
98
+ sweepTo: builder.context.sender,
99
+ // The UNI-V2 LP token is unpriced, so the default 500 bps price-impact
100
+ // check reads the deposit as a 100% loss. 0 skips the check; the `band`
101
+ // and `slippage` guards above are the protection.
102
+ maxPriceImpactBps: 0,
103
+ });
104
+
105
+ return { flow, request };
106
+ };
@@ -0,0 +1,95 @@
1
+ import type { ComposeCompileRequest, Flow } from '@lifi/compose-spec';
2
+
3
+ import {
4
+ createComposeSdk,
5
+ guards,
6
+ materialisers,
7
+ resources,
8
+ } from '../index.js';
9
+ import type { Address } from '../types.js';
10
+
11
+ import { API_KEY, BASE_URL } from './config.js';
12
+
13
+ // Uniswap V3 USDC/WETH 0.05% pool on Ethereum mainnet (chainId 1).
14
+ const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
15
+ const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
16
+ const POSITION_MANAGER = '0xC36442b4a4522E871399CD717aBDD847Ab11FE88';
17
+ const FACTORY = '0x1F98431c8aD98523631AE4a59f267346ea31F984';
18
+ const USDC_WETH_500_POOL = '0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640';
19
+ // Full range: the widest ticks that are multiples of the pool's tick spacing (10).
20
+ const TICK_LOWER = -887270;
21
+ const TICK_UPPER = 887270;
22
+
23
+ export interface UniswapV3MintInput {
24
+ readonly owner: Address;
25
+ readonly usdcAmount: `${bigint}`;
26
+ readonly wethAmount: `${bigint}`;
27
+ }
28
+
29
+ /**
30
+ * Open a full-range Uniswap V3 USDC/WETH position on Ethereum mainnet.
31
+ *
32
+ * - `uniswapV3.mint` deposits the proxy's USDC and WETH and mints the
33
+ * position NFT straight to the signer.
34
+ * - Unused USDC or WETH comes back as residuals, swept to the signer.
35
+ */
36
+ export const buildUniswapV3Mint = ({
37
+ owner,
38
+ usdcAmount,
39
+ wethAmount,
40
+ }: UniswapV3MintInput): {
41
+ flow: Flow;
42
+ request: ComposeCompileRequest;
43
+ } => {
44
+ const sdk = createComposeSdk({ baseUrl: BASE_URL, apiKey: API_KEY });
45
+
46
+ const builder = sdk.flow(1, {
47
+ name: 'uniswap-v3-mint-usdc-weth',
48
+ inputs: {
49
+ usdc: resources.erc20(USDC, 1),
50
+ weth: resources.erc20(WETH, 1),
51
+ },
52
+ });
53
+
54
+ builder.uniswapV3.mint('mint', {
55
+ bind: {
56
+ tokenA: builder.inputs.usdc,
57
+ tokenB: builder.inputs.weth,
58
+ recipient: builder.context.sender,
59
+ },
60
+ config: {
61
+ positionManager: POSITION_MANAGER,
62
+ factory: FACTORY,
63
+ pool: USDC_WETH_500_POOL,
64
+ fee: 500,
65
+ tickLower: TICK_LOWER,
66
+ tickUpper: TICK_UPPER,
67
+ },
68
+ guards: [
69
+ // Bound the pool price before the deposit; N bps on the sqrt price
70
+ // allows about 2N bps of price movement, so this caps it near 50 bps.
71
+ guards.band({ port: 'sqrtPriceX96', bps: 25 }),
72
+ // Floor the minted liquidity. Liquidity is a handle, not a resource,
73
+ // so no minimum appears in the response.
74
+ guards.slippage({ port: 'liquidity', bps: 50 }),
75
+ ],
76
+ });
77
+
78
+ const flow = builder.build();
79
+
80
+ const request = sdk.request(flow, {
81
+ signer: owner,
82
+ inputs: {
83
+ usdc: materialisers.directDeposit({ amount: usdcAmount }),
84
+ weth: materialisers.directDeposit({ amount: wethAmount }),
85
+ },
86
+ // Return unused USDC or WETH to the signer.
87
+ sweepTo: builder.context.sender,
88
+ // The position NFT is not a resource, so only the residuals count as
89
+ // output and the default price-impact check would read a full loss.
90
+ // 0 skips the check; the band and slippage guards protect the deposit.
91
+ maxPriceImpactBps: 0,
92
+ });
93
+
94
+ return { flow, request };
95
+ };
@@ -1170,44 +1170,6 @@ export interface LifiFlashloanRepayConfig {
1170
1170
  fee?: string;
1171
1171
  }
1172
1172
 
1173
- export type ContinuationAssertReadyConfig =
1174
- | {
1175
- kind: 'erc20BalanceGte';
1176
- chainId: Positive;
1177
- /**
1178
- * EVM address: 0x followed by 40 hex characters
1179
- */
1180
- token: Address;
1181
- /**
1182
- * EVM address: 0x followed by 40 hex characters
1183
- */
1184
- owner: Address;
1185
- minAmount: string;
1186
- }
1187
- | {
1188
- kind: 'nativeBalanceGte';
1189
- chainId: Positive;
1190
- /**
1191
- * EVM address: 0x followed by 40 hex characters
1192
- */
1193
- owner: Address;
1194
- minAmount: string;
1195
- }
1196
- | {
1197
- kind: 'call';
1198
- chainId: Positive;
1199
- /**
1200
- * EVM address: 0x followed by 40 hex characters
1201
- */
1202
- to: string;
1203
- /**
1204
- * Hex bytes: 0x followed by an even number of hex characters
1205
- */
1206
- calldata: string;
1207
- comparator: 'gte' | 'eq' | 'lte';
1208
- value: string;
1209
- };
1210
-
1211
1173
  export interface LifiZapConfig {
1212
1174
  resourceOut:
1213
1175
  | {
@@ -1305,6 +1267,83 @@ export interface FlySwapConfig {
1305
1267
  maxSlippageBps?: Between05000;
1306
1268
  }
1307
1269
 
1270
+ export interface UniswapV2AddLiquidityConfig {
1271
+ /**
1272
+ * EVM address: 0x followed by 40 hex characters
1273
+ */
1274
+ router: string;
1275
+ /**
1276
+ * EVM address: 0x followed by 40 hex characters
1277
+ */
1278
+ factory: string;
1279
+ /**
1280
+ * EVM address: 0x followed by 40 hex characters
1281
+ */
1282
+ pair: string;
1283
+ }
1284
+
1285
+ export interface UniswapV2RemoveLiquidityConfig {
1286
+ /**
1287
+ * EVM address: 0x followed by 40 hex characters
1288
+ */
1289
+ router: string;
1290
+ /**
1291
+ * EVM address: 0x followed by 40 hex characters
1292
+ */
1293
+ factory: string;
1294
+ /**
1295
+ * EVM address: 0x followed by 40 hex characters
1296
+ */
1297
+ tokenA: string;
1298
+ /**
1299
+ * EVM address: 0x followed by 40 hex characters
1300
+ */
1301
+ tokenB: string;
1302
+ }
1303
+
1304
+ /**
1305
+ * a number between 0 and 999999
1306
+ */
1307
+ export type Between0999999 = number;
1308
+ /**
1309
+ * a number between -887272 and 887272
1310
+ */
1311
+ export type Between887272887272 = number;
1312
+
1313
+ export interface UniswapV3MintConfig {
1314
+ /**
1315
+ * EVM address: 0x followed by 40 hex characters
1316
+ */
1317
+ positionManager: string;
1318
+ /**
1319
+ * EVM address: 0x followed by 40 hex characters
1320
+ */
1321
+ factory: string;
1322
+ /**
1323
+ * EVM address: 0x followed by 40 hex characters
1324
+ */
1325
+ pool: string;
1326
+ fee: Between0999999;
1327
+ tickLower: Between887272887272;
1328
+ tickUpper: Between887272887272;
1329
+ }
1330
+
1331
+ export interface UniswapV3IncreaseLiquidityConfig {
1332
+ /**
1333
+ * EVM address: 0x followed by 40 hex characters
1334
+ */
1335
+ positionManager: string;
1336
+ /**
1337
+ * EVM address: 0x followed by 40 hex characters
1338
+ */
1339
+ factory: string;
1340
+ /**
1341
+ * EVM address: 0x followed by 40 hex characters
1342
+ */
1343
+ pool: string;
1344
+ tokenId: string;
1345
+ }
1346
+
1308
1347
  export interface SlippageGuardConfig {
1309
1348
  port: string;
1310
1349
  bps: Between010000;
@@ -1316,6 +1355,11 @@ export interface CoreNumericInvariantGuardConfig {
1316
1355
  threshold: IntegerStringInput;
1317
1356
  }
1318
1357
 
1358
+ export interface BandGuardConfig {
1359
+ port: string;
1360
+ bps: Between010000;
1361
+ }
1362
+
1319
1363
  export interface BalanceOfMaterialiserConfig {
1320
1364
  /**
1321
1365
  * EVM address: 0x followed by 40 hex characters
@@ -4,6 +4,7 @@
4
4
  import type { TypedGuard } from '../types.js';
5
5
 
6
6
  import type {
7
+ BandGuardConfig,
7
8
  CoreNumericInvariantGuardConfig,
8
9
  SlippageGuardConfig,
9
10
  } from './config.generated.js';
@@ -23,3 +24,11 @@ export const coreNumericInvariant = <P extends string>(
23
24
  kind: 'core.numericInvariant',
24
25
  ...config,
25
26
  });
27
+
28
+ /** Assert that an output stays within a tolerance in basis points of its simulated value, in both directions */
29
+ export const band = <P extends string>(
30
+ config: Omit<BandGuardConfig, 'port'> & { port: P },
31
+ ): TypedGuard<P> => ({
32
+ kind: 'band',
33
+ ...config,
34
+ });
@@ -64,6 +64,10 @@ import type {
64
64
  MorphoBlueWithdrawCollateralConfig,
65
65
  MorphoBlueWithdrawConfig,
66
66
  ParaswapBuyConfig,
67
+ UniswapV2AddLiquidityConfig,
68
+ UniswapV2RemoveLiquidityConfig,
69
+ UniswapV3IncreaseLiquidityConfig,
70
+ UniswapV3MintConfig,
67
71
  } from './config.generated.js';
68
72
 
69
73
  /** Split a resource into two outputs by basis-point ratio. Output `a` receives `bps` of the source, rounded up, and `b` takes the remainder. */
@@ -654,6 +658,53 @@ export interface FlySwapArgs {
654
658
  readonly guards?: readonly TypedGuard<'unspentIn'>[];
655
659
  }
656
660
 
661
+ /** Deposit two ERC-20 tokens into an existing Uniswap V2 pair (or an ABI-identical fork such as SushiSwap V2) through its Router02 and receive the pair's LP token; unused input returns as residuals. Asserts on chain that the router's factory is `factory`, that the factory's pair for the two tokens is `pair`, and that the pair holds non-zero reserves. Exposes the pool price read before the deposit as `poolPrice`. The deposit is protected only with a `band` guard on `poolPrice` and a `slippage` guard on `liquidity`. Fee-on-transfer tokens are unsupported. */
662
+ export interface UniswapV2AddLiquidityArgs {
663
+ readonly bind: {
664
+ readonly tokenA: Bindable<'resource'>;
665
+ readonly tokenB: Bindable<'resource'>;
666
+ };
667
+ readonly config: UniswapV2AddLiquidityConfig;
668
+ readonly guards?: readonly TypedGuard<
669
+ 'liquidity' | 'residualA' | 'residualB' | 'poolPrice'
670
+ >[];
671
+ }
672
+
673
+ /** Burn a Uniswap V2 LP token (or one of an ABI-identical fork such as SushiSwap V2) through its Router02 and receive both underlying tokens. Asserts on chain that the router's factory is `factory` and that the factory's pair for `tokenA`/`tokenB` is the input LP token. The withdrawal is protected only with a `slippage` guard on each of `tokenA` and `tokenB`. Fee-on-transfer tokens are unsupported: the outputs are the amounts the router reports, which would overstate what such a token delivers. */
674
+ export interface UniswapV2RemoveLiquidityArgs {
675
+ readonly bind: {
676
+ readonly liquidity: Bindable<'resource'>;
677
+ };
678
+ readonly config: UniswapV2RemoveLiquidityConfig;
679
+ readonly guards?: readonly TypedGuard<'tokenA' | 'tokenB'>[];
680
+ }
681
+
682
+ /** Open a Uniswap V3 concentrated-liquidity position (or one on an ABI-identical fork) for a tick range, minting the position NFT straight to `recipient`, which must not be the execution address. Exposes the new `tokenId`; unused input comes back as residuals. The deposit is protected only with a `band` guard on `sqrtPriceX96` (read before the deposit) and a `slippage` guard on `liquidity`; a band of N bps on `sqrtPriceX96` allows about 2N bps of price movement. Fee-on-transfer tokens are unsupported. */
683
+ export interface UniswapV3MintArgs {
684
+ readonly bind: {
685
+ readonly tokenA: Bindable<'resource'>;
686
+ readonly tokenB: Bindable<'resource'>;
687
+ readonly recipient: Bindable<'address'>;
688
+ };
689
+ readonly config: UniswapV3MintConfig;
690
+ readonly guards?: readonly TypedGuard<
691
+ 'tokenId' | 'liquidity' | 'sqrtPriceX96' | 'residualA' | 'residualB'
692
+ >[];
693
+ }
694
+
695
+ /** Add two tokens to an existing Uniswap V3 position (or one on an ABI-identical fork). `owner` must own `tokenId`, and the position must hold the two input tokens; both are asserted on chain, since the position manager checks neither. Unused input comes back as residuals. The deposit is protected only with a `band` guard on `sqrtPriceX96` (read before the deposit) and a `slippage` guard on `liquidity`; a band of N bps on `sqrtPriceX96` allows about 2N bps of price movement. Fee-on-transfer tokens are unsupported. */
696
+ export interface UniswapV3IncreaseLiquidityArgs {
697
+ readonly bind: {
698
+ readonly tokenA: Bindable<'resource'>;
699
+ readonly tokenB: Bindable<'resource'>;
700
+ readonly owner: Bindable<'address'>;
701
+ };
702
+ readonly config: UniswapV3IncreaseLiquidityConfig;
703
+ readonly guards?: readonly TypedGuard<
704
+ 'liquidity' | 'sqrtPriceX96' | 'residualA' | 'residualB'
705
+ >[];
706
+ }
707
+
657
708
  export interface CoreSplitOutputs {
658
709
  readonly a: OutputHandle<'resource'>;
659
710
  readonly b: OutputHandle<'resource'>;
@@ -807,6 +858,33 @@ export interface FlySwapOutputs {
807
858
  readonly unspentIn: OutputHandle<'resource'>;
808
859
  }
809
860
 
861
+ export interface UniswapV2AddLiquidityOutputs {
862
+ readonly liquidity: OutputHandle<'resource'>;
863
+ readonly residualA: OutputHandle<'resource'>;
864
+ readonly residualB: OutputHandle<'resource'>;
865
+ readonly poolPrice: OutputHandle<'uint256'>;
866
+ }
867
+
868
+ export interface UniswapV2RemoveLiquidityOutputs {
869
+ readonly tokenA: OutputHandle<'resource'>;
870
+ readonly tokenB: OutputHandle<'resource'>;
871
+ }
872
+
873
+ export interface UniswapV3MintOutputs {
874
+ readonly tokenId: OutputHandle<'uint256'>;
875
+ readonly liquidity: OutputHandle<'uint256'>;
876
+ readonly sqrtPriceX96: OutputHandle<'uint256'>;
877
+ readonly residualA: OutputHandle<'resource'>;
878
+ readonly residualB: OutputHandle<'resource'>;
879
+ }
880
+
881
+ export interface UniswapV3IncreaseLiquidityOutputs {
882
+ readonly liquidity: OutputHandle<'uint256'>;
883
+ readonly sqrtPriceX96: OutputHandle<'uint256'>;
884
+ readonly residualA: OutputHandle<'resource'>;
885
+ readonly residualB: OutputHandle<'resource'>;
886
+ }
887
+
810
888
  export type GeneratedOps = {
811
889
  readonly core: {
812
890
  /** Split a resource into two outputs by basis-point ratio. Output `a` receives `bps` of the source, rounded up, and `b` takes the remainder. — original id: "core.split" */
@@ -1060,6 +1138,30 @@ export type GeneratedOps = {
1060
1138
  /** Swap via Fly's DexAggregator, sized at runtime: the router calldata leaves `amountIn` unset, so an upstream op's output can feed the swap without being known at plan time. Either leg may be the chain-native coin. — original id: "fly.swap" */
1061
1139
  readonly swap: (nodeId: string, args: FlySwapArgs) => FlySwapOutputs;
1062
1140
  };
1141
+ readonly uniswapV2: {
1142
+ /** Deposit two ERC-20 tokens into an existing Uniswap V2 pair (or an ABI-identical fork such as SushiSwap V2) through its Router02 and receive the pair's LP token; unused input returns as residuals. Asserts on chain that the router's factory is `factory`, that the factory's pair for the two tokens is `pair`, and that the pair holds non-zero reserves. Exposes the pool price read before the deposit as `poolPrice`. The deposit is protected only with a `band` guard on `poolPrice` and a `slippage` guard on `liquidity`. Fee-on-transfer tokens are unsupported. — original id: "uniswapV2.addLiquidity" */
1143
+ readonly addLiquidity: (
1144
+ nodeId: string,
1145
+ args: UniswapV2AddLiquidityArgs,
1146
+ ) => UniswapV2AddLiquidityOutputs;
1147
+ /** Burn a Uniswap V2 LP token (or one of an ABI-identical fork such as SushiSwap V2) through its Router02 and receive both underlying tokens. Asserts on chain that the router's factory is `factory` and that the factory's pair for `tokenA`/`tokenB` is the input LP token. The withdrawal is protected only with a `slippage` guard on each of `tokenA` and `tokenB`. Fee-on-transfer tokens are unsupported: the outputs are the amounts the router reports, which would overstate what such a token delivers. — original id: "uniswapV2.removeLiquidity" */
1148
+ readonly removeLiquidity: (
1149
+ nodeId: string,
1150
+ args: UniswapV2RemoveLiquidityArgs,
1151
+ ) => UniswapV2RemoveLiquidityOutputs;
1152
+ };
1153
+ readonly uniswapV3: {
1154
+ /** Open a Uniswap V3 concentrated-liquidity position (or one on an ABI-identical fork) for a tick range, minting the position NFT straight to `recipient`, which must not be the execution address. Exposes the new `tokenId`; unused input comes back as residuals. The deposit is protected only with a `band` guard on `sqrtPriceX96` (read before the deposit) and a `slippage` guard on `liquidity`; a band of N bps on `sqrtPriceX96` allows about 2N bps of price movement. Fee-on-transfer tokens are unsupported. — original id: "uniswapV3.mint" */
1155
+ readonly mint: (
1156
+ nodeId: string,
1157
+ args: UniswapV3MintArgs,
1158
+ ) => UniswapV3MintOutputs;
1159
+ /** Add two tokens to an existing Uniswap V3 position (or one on an ABI-identical fork). `owner` must own `tokenId`, and the position must hold the two input tokens; both are asserted on chain, since the position manager checks neither. Unused input comes back as residuals. The deposit is protected only with a `band` guard on `sqrtPriceX96` (read before the deposit) and a `slippage` guard on `liquidity`; a band of N bps on `sqrtPriceX96` allows about 2N bps of price movement. Fee-on-transfer tokens are unsupported. — original id: "uniswapV3.increaseLiquidity" */
1160
+ readonly increaseLiquidity: (
1161
+ nodeId: string,
1162
+ args: UniswapV3IncreaseLiquidityArgs,
1163
+ ) => UniswapV3IncreaseLiquidityOutputs;
1164
+ };
1063
1165
  };
1064
1166
 
1065
1167
  export const bindGeneratedOps = (
@@ -1359,4 +1461,35 @@ export const bindGeneratedOps = (
1359
1461
  unspentIn: 'resource',
1360
1462
  } as const),
1361
1463
  },
1464
+ uniswapV2: {
1465
+ addLiquidity: (nodeId: string, args: UniswapV2AddLiquidityArgs) =>
1466
+ builder.call(nodeId, 'uniswapV2.addLiquidity', args, {
1467
+ liquidity: 'resource',
1468
+ residualA: 'resource',
1469
+ residualB: 'resource',
1470
+ poolPrice: 'uint256',
1471
+ } as const),
1472
+ removeLiquidity: (nodeId: string, args: UniswapV2RemoveLiquidityArgs) =>
1473
+ builder.call(nodeId, 'uniswapV2.removeLiquidity', args, {
1474
+ tokenA: 'resource',
1475
+ tokenB: 'resource',
1476
+ } as const),
1477
+ },
1478
+ uniswapV3: {
1479
+ mint: (nodeId: string, args: UniswapV3MintArgs) =>
1480
+ builder.call(nodeId, 'uniswapV3.mint', args, {
1481
+ tokenId: 'uint256',
1482
+ liquidity: 'uint256',
1483
+ sqrtPriceX96: 'uint256',
1484
+ residualA: 'resource',
1485
+ residualB: 'resource',
1486
+ } as const),
1487
+ increaseLiquidity: (nodeId: string, args: UniswapV3IncreaseLiquidityArgs) =>
1488
+ builder.call(nodeId, 'uniswapV3.increaseLiquidity', args, {
1489
+ liquidity: 'uint256',
1490
+ sqrtPriceX96: 'uint256',
1491
+ residualA: 'resource',
1492
+ residualB: 'resource',
1493
+ } as const),
1494
+ },
1362
1495
  });
package/src/index.ts CHANGED
@@ -99,11 +99,8 @@ export type {
99
99
  Erc20AllowanceRequirement,
100
100
  ContinuationIntent,
101
101
  ContinuationOutcome,
102
- Check,
103
- CheckComparator,
104
102
  SettlementWire,
105
103
  SettlementEscrowWire,
106
- ContinuationPlanWire,
107
104
  } from '@lifi/compose-spec';
108
105
  export {
109
106
  SIMULATE_MAX_TRACKED_BALANCES,