@lifi/composer-sdk 0.0.1-alpha → 0.2.0-staging.3

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 (66) hide show
  1. package/README.md +37 -1
  2. package/dist/authoring/signatureArgs.cjs +2 -2
  3. package/dist/authoring/signatureArgs.cjs.map +1 -1
  4. package/dist/authoring/signatureArgs.js +2 -2
  5. package/dist/authoring/signatureArgs.js.map +1 -1
  6. package/dist/client.cjs +2 -2
  7. package/dist/client.cjs.map +1 -1
  8. package/dist/client.js +2 -2
  9. package/dist/client.js.map +1 -1
  10. package/dist/generated/config.generated.cjs.map +1 -1
  11. package/dist/generated/config.generated.d.cts +307 -16
  12. package/dist/generated/config.generated.d.ts +307 -16
  13. package/dist/generated/guards.generated.cjs +6 -0
  14. package/dist/generated/guards.generated.cjs.map +1 -1
  15. package/dist/generated/guards.generated.d.cts +1 -1
  16. package/dist/generated/guards.generated.d.ts +1 -1
  17. package/dist/generated/guards.generated.js +5 -0
  18. package/dist/generated/guards.generated.js.map +1 -1
  19. package/dist/generated/materialisers.generated.cjs +8 -2
  20. package/dist/generated/materialisers.generated.cjs.map +1 -1
  21. package/dist/generated/materialisers.generated.d.cts +1 -1
  22. package/dist/generated/materialisers.generated.d.ts +1 -1
  23. package/dist/generated/materialisers.generated.js +6 -1
  24. package/dist/generated/materialisers.generated.js.map +1 -1
  25. package/dist/generated/operations.generated.cjs +84 -14
  26. package/dist/generated/operations.generated.cjs.map +1 -1
  27. package/dist/generated/operations.generated.d.cts +208 -13
  28. package/dist/generated/operations.generated.d.ts +208 -13
  29. package/dist/generated/operations.generated.js +84 -14
  30. package/dist/generated/operations.generated.js.map +1 -1
  31. package/dist/guards.generated-BPLFwe7y.d.ts +19 -0
  32. package/dist/guards.generated-M3VAIevI.d.cts +19 -0
  33. package/dist/index.d.cts +3 -3
  34. package/dist/index.d.ts +3 -3
  35. package/dist/materialisers.generated-BfWJ-g7t.d.ts +29 -0
  36. package/dist/materialisers.generated-DaJRwiRe.d.cts +29 -0
  37. package/dist/run/inputs.cjs +8 -5
  38. package/dist/run/inputs.cjs.map +1 -1
  39. package/dist/run/inputs.d.cts +8 -0
  40. package/dist/run/inputs.d.ts +8 -0
  41. package/dist/run/inputs.js +8 -5
  42. package/dist/run/inputs.js.map +1 -1
  43. package/dist/sdk.cjs +1 -0
  44. package/dist/sdk.cjs.map +1 -1
  45. package/dist/sdk.js +1 -0
  46. package/dist/sdk.js.map +1 -1
  47. package/package.json +16 -7
  48. package/src/authoring/signatureArgs.ts +2 -2
  49. package/src/client.ts +1 -1
  50. package/src/examples/aaveClaimRewards.ts +80 -0
  51. package/src/examples/aaveRepay.ts +69 -0
  52. package/src/examples/aaveRepayWithATokens.ts +81 -0
  53. package/src/examples/aaveSetEMode.ts +68 -0
  54. package/src/examples/run.ts +41 -4
  55. package/src/examples/swapToRecipient.ts +0 -19
  56. package/src/examples/swapWithFee.ts +59 -0
  57. package/src/generated/config.generated.ts +364 -18
  58. package/src/generated/guards.generated.ts +12 -1
  59. package/src/generated/materialisers.generated.ts +24 -12
  60. package/src/generated/operations.generated.ts +373 -13
  61. package/src/run/inputs.ts +16 -5
  62. package/src/sdk.ts +1 -0
  63. package/dist/guards.generated-DKKDKREA.d.ts +0 -14
  64. package/dist/guards.generated-hrQ1KPNv.d.cts +0 -14
  65. package/dist/materialisers.generated-BsA1uDW8.d.ts +0 -24
  66. package/dist/materialisers.generated-nMxTAaVi.d.cts +0 -24
@@ -0,0 +1,81 @@
1
+ import type { ComposeCompileRequest, Flow } from '@lifi/compose-spec';
2
+
3
+ import {
4
+ createComposeSdk,
5
+ materialisers,
6
+ preconditions,
7
+ resources,
8
+ } from '../index.js';
9
+ import type { Address } from '../types.js';
10
+
11
+ import { BASE_URL } from './config.js';
12
+
13
+ // Aave v3 contracts on Ethereum mainnet.
14
+ const AAVE_V3_POOL = '0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2';
15
+ const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
16
+ const A_ETH_USDC = '0x98C23E9d8f34FEFb1B7BD6a91B7FF122F4e16F5c';
17
+
18
+ export interface AaveRepayWithATokensInput {
19
+ readonly owner: Address;
20
+ readonly proxyAddress: Address;
21
+ readonly expectedATokenBalance: `${bigint}`;
22
+ }
23
+
24
+ /**
25
+ * Repay an Aave v3 variable-rate USDC debt by burning aToken collateral
26
+ * already held by the proxy (no fresh asset transfer required).
27
+ *
28
+ * The aTokens are sourced from the proxy's existing balance via the
29
+ * `balanceOf` materialiser. The `erc20Balance` precondition fails fast
30
+ * if the expected aTokens haven't landed on the proxy yet.
31
+ *
32
+ * Demonstrates:
33
+ * - `aave.repayWithATokens` with the aToken as the resource input.
34
+ * - `balanceOf` materialiser to consume proxy-held aTokens directly.
35
+ * - `erc20Balance` precondition to guard against silent zero-value repays.
36
+ * - The `residual` port returns any aTokens not burned (when debt < input).
37
+ */
38
+ export const buildAaveRepayWithATokens = ({
39
+ owner,
40
+ proxyAddress,
41
+ expectedATokenBalance,
42
+ }: AaveRepayWithATokensInput): {
43
+ flow: Flow;
44
+ request: ComposeCompileRequest;
45
+ } => {
46
+ const sdk = createComposeSdk({ baseUrl: BASE_URL });
47
+
48
+ const builder = sdk.flow(1, {
49
+ name: 'aave-repay-with-atokens',
50
+ inputs: {
51
+ aTokenIn: resources.erc20(A_ETH_USDC, 1),
52
+ },
53
+ });
54
+
55
+ builder.aave.repayWithATokens('repay-atokens', {
56
+ bind: { aTokenIn: builder.inputs.aTokenIn },
57
+ config: {
58
+ pool: AAVE_V3_POOL,
59
+ asset: USDC,
60
+ },
61
+ });
62
+
63
+ const flow = builder.build();
64
+
65
+ const request = sdk.request(flow, {
66
+ signer: owner,
67
+ inputs: {
68
+ aTokenIn: materialisers.balanceOf({ owner: proxyAddress }),
69
+ },
70
+ preconditions: [
71
+ preconditions.erc20Balance({
72
+ wallet: proxyAddress,
73
+ token: A_ETH_USDC,
74
+ balance: expectedATokenBalance,
75
+ }),
76
+ ],
77
+ sweepTo: builder.context.sender,
78
+ });
79
+
80
+ return { flow, request };
81
+ };
@@ -0,0 +1,68 @@
1
+ import type { ComposeCompileRequest, Flow } from '@lifi/compose-spec';
2
+
3
+ import { createComposeSdk } from '../index.js';
4
+ import type { Address } from '../types.js';
5
+
6
+ import { BASE_URL } from './config.js';
7
+
8
+ // Aave v3 contracts on Ethereum mainnet.
9
+ const AAVE_V3_POOL = '0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2';
10
+
11
+ // Mainnet ETH-correlated eMode category. Categories are per-pool; check
12
+ // `Pool.getEModeCategoryData(id)` on the target chain before reusing this id.
13
+ const ETH_CORRELATED_CATEGORY = 1;
14
+
15
+ export interface AaveSetEModeInput {
16
+ readonly owner: Address;
17
+ }
18
+
19
+ /**
20
+ * Switch the executionAddress's Aave v3 eMode category.
21
+ *
22
+ * eMode is a per-user setting on the pool that allows higher LTV when both
23
+ * collateral and debt are correlated assets (e.g. ETH-LSTs, stablecoins).
24
+ * The setting persists across transactions until changed again.
25
+ *
26
+ * Demonstrates:
27
+ * - `aave.setEMode` as a side-effecting op with no resource inputs or outputs.
28
+ * - The op's category is validated at request-validation time against the
29
+ * protocol's uint8 range. Per-pool category existence (Ethereum has 40+
30
+ * categories, Base has 15+, Arbitrum 10+; new ones are added by governance)
31
+ * is verified at simulation time, not in the schema.
32
+ *
33
+ * Real flows typically combine this op with `aave.supply` + `aave.borrow` of
34
+ * correlated assets. The reset call (`category: 0`) is intentionally omitted —
35
+ * leaving eMode on persists the leveraged position past the tx, and resetting
36
+ * to 0 after a high-LTV borrow would revert with a sub-1 health factor.
37
+ */
38
+ export const buildAaveSetEMode = ({
39
+ owner,
40
+ }: AaveSetEModeInput): {
41
+ flow: Flow;
42
+ request: ComposeCompileRequest;
43
+ } => {
44
+ const sdk = createComposeSdk({ baseUrl: BASE_URL });
45
+
46
+ const builder = sdk.flow(1, {
47
+ name: 'aave-set-emode',
48
+ inputs: {},
49
+ });
50
+
51
+ builder.aave.setEMode('enter-eth-emode', {
52
+ bind: {},
53
+ config: {
54
+ pool: AAVE_V3_POOL,
55
+ category: ETH_CORRELATED_CATEGORY,
56
+ },
57
+ });
58
+
59
+ const flow = builder.build();
60
+
61
+ const request = sdk.request(flow, {
62
+ signer: owner,
63
+ inputs: {},
64
+ sweepTo: builder.context.sender,
65
+ });
66
+
67
+ return { flow, request };
68
+ };
@@ -8,12 +8,16 @@
8
8
  * LIFI_API_KEY=your-key COMPOSER_BASE_URL=https://composer.li.quest yarn example <name>
9
9
  *
10
10
  * Available examples:
11
+ * aave-repay — repay an Aave v3 WETH debt by supplying WETH
12
+ * aave-repay-atoken — repay an Aave v3 USDC debt by burning proxy aTokens
13
+ * aave-claim — claim AAVE rewards and forward to a recipient
11
14
  * approve-deposit — approve vault allowance then deposit USDC
12
15
  * consolidate — consolidate ERC-20 balances to USDC
13
16
  * consolidate-eth — consolidate ERC-20 balances to native ETH
14
17
  * deposit-proxy — deposit tokens already on the proxy into Aave
15
18
  * dust-sweep — split USDC 80/20 and sweep leftover dust
16
19
  * swap — swap WETH to USDC via LI.FI
20
+ * swap-fee — swap WETH to USDC with a 50 bps integrator fee
17
21
  * split-zap — split USDC 60/40 and zap into Aave + Morpho vaults
18
22
  * split-arithmetic — split USDC 70/30 with arithmetic assertions
19
23
  * zap — zap USDC into Aave lending position
@@ -35,6 +39,9 @@ import type { ComposeCompileRequest } from '@lifi/compose-spec';
35
39
 
36
40
  import { createComposeSdk } from '../sdk.js';
37
41
 
42
+ import { buildAaveClaimRewards } from './aaveClaimRewards.js';
43
+ import { buildAaveRepay } from './aaveRepay.js';
44
+ import { buildAaveRepayWithATokens } from './aaveRepayWithATokens.js';
38
45
  import { buildApproveAndDeposit } from './approveAndDeposit.js';
39
46
  import {
40
47
  buildClaimRewards,
@@ -56,11 +63,22 @@ import { buildSwapAndZapExample } from './swapAndZap.js';
56
63
  import { buildSwapToRecipient } from './swapToRecipient.js';
57
64
  import { buildSwapWithAllowRevertExample } from './swapWithAllowRevert.js';
58
65
  import { buildSwapWithBalanceCheck } from './swapWithBalanceCheck.js';
66
+ import { buildSwapWithFeeExample } from './swapWithFee.js';
59
67
  import { buildSwapWithOutputValidation } from './swapWithOutputValidation.js';
60
68
  import { buildPartialTransfer, buildTransferTokens } from './transferTokens.js';
61
69
  import { buildUntypedOpWithTypedRef } from './untypedOpWithTypedRef.js';
62
70
 
63
71
  const EXAMPLES: Record<string, () => ComposeCompileRequest> = {
72
+ 'aave-repay': () =>
73
+ buildAaveRepay({ owner: OWNER, amount: '500000000000000000' }).request,
74
+ 'aave-repay-atoken': () =>
75
+ buildAaveRepayWithATokens({
76
+ owner: OWNER,
77
+ proxyAddress: PROXY,
78
+ expectedATokenBalance: '1000000000',
79
+ }).request,
80
+ 'aave-claim': () =>
81
+ buildAaveClaimRewards({ owner: OWNER, recipient: RECIPIENT }).request,
64
82
  'approve-deposit': () =>
65
83
  buildApproveAndDeposit({ owner: OWNER, amount: '1000000000' }).request,
66
84
  consolidate: () =>
@@ -87,6 +105,7 @@ const EXAMPLES: Record<string, () => ComposeCompileRequest> = {
87
105
  }).request,
88
106
  'dust-sweep': () => buildDustSweepExample().request,
89
107
  swap: () => buildLifiSwapExample().request,
108
+ 'swap-fee': () => buildSwapWithFeeExample().request,
90
109
  'split-zap': () => buildSplitAndZapExample().request,
91
110
  'split-arithmetic': () =>
92
111
  buildSplitWithArithmetic({ owner: OWNER, amount: '1000000000' }).request,
@@ -133,17 +152,35 @@ const EXAMPLES: Record<string, () => ComposeCompileRequest> = {
133
152
  };
134
153
 
135
154
  const run = async () => {
136
- const name = process.argv[2];
137
- const builder = name ? EXAMPLES[name] : undefined;
155
+ const args = process.argv.slice(2);
156
+ const useStaged = args.includes('--staged');
157
+ const name = args.find((arg) => arg !== '--staged');
158
+
159
+ // Staged examples live under examples/staged/ and reference not-yet-prod
160
+ // definitions, so they are deliberately excluded from this production file's
161
+ // type-check. With --staged, pull their registry in via a NON-LITERAL dynamic
162
+ // import (kept `any` to tsc, so the staged files are not dragged into the
163
+ // production program). Requires the SDK to have been regenerated with
164
+ // `yarn generate --staged` first, so the staged ops/materialisers exist at
165
+ // runtime; run `yarn generate` afterwards to restore the production surface.
166
+ let examples: Record<string, () => ComposeCompileRequest> = EXAMPLES;
167
+ if (useStaged) {
168
+ const stagedModule = (await import(
169
+ `${import.meta.dirname}/staged/registry.js`
170
+ )) as { STAGED_EXAMPLES: Record<string, () => ComposeCompileRequest> };
171
+ examples = { ...EXAMPLES, ...stagedModule.STAGED_EXAMPLES };
172
+ }
173
+
174
+ const builder = name ? examples[name] : undefined;
138
175
 
139
176
  if (!builder) {
140
- const valid = Object.keys(EXAMPLES).join(', ');
177
+ const valid = Object.keys(examples).join(', ');
141
178
  console.error(
142
179
  `Error: ${
143
180
  name ? `unknown example "${name}"` : 'no example specified'
144
181
  }\n` +
145
182
  `Valid examples: ${valid}\n` +
146
- `Usage: COMPOSER_BASE_URL=https://composer.li.quest yarn example <name>`,
183
+ `Usage: COMPOSER_BASE_URL=https://composer.li.quest yarn example [--staged] <name>`,
147
184
  );
148
185
  process.exit(1);
149
186
  }
@@ -17,32 +17,13 @@ export interface SwapToRecipientInput {
17
17
  }
18
18
 
19
19
  /**
20
- <<<<<<< HEAD
21
- <<<<<<< HEAD
22
- * Swap WETH and DAI into USDC, merge the outputs, transfer to a recipient,
23
- =======
24
- * Swap WETH and DAI into USDC, merge the outputs, transfer to the recipient,
25
- >>>>>>> a2c178fd (chore: fix examples)
26
- * and verify the recipient holds the combined balance.
27
- =======
28
20
  * Swap WETH and DAI into USDC, merge the outputs, and deliver to a recipient.
29
- >>>>>>> 4c49ff9b (fix: support resource bindings for handle ports)
30
21
  *
31
22
  * Demonstrates:
32
23
  * - Multiple resource inputs (two ERC-20 tokens)
33
24
  * - A handle input (recipient address as a scalar value)
34
25
  * - Chaining two swaps through a merge node
35
- <<<<<<< HEAD
36
- <<<<<<< HEAD
37
- * - Explicit core.transfer to send merged tokens to the recipient
38
- * - Copy-mode resource input on invariant.balanceAtLeast (reads without consuming)
39
- =======
40
- * - core.transfer to send merged tokens to the recipient
41
- * - Using invariant.balanceAtLeast with a handle input for the account
42
- >>>>>>> a2c178fd (chore: fix examples)
43
- =======
44
26
  * - Using `sweepTo` with a handle input to deliver tokens to the recipient
45
- >>>>>>> 4c49ff9b (fix: support resource bindings for handle ports)
46
27
  * - Typed request inputs inferred from the flow schema
47
28
  */
48
29
  export const buildSwapToRecipient = ({
@@ -0,0 +1,59 @@
1
+ import type { ComposeCompileRequest, Flow } from '@lifi/compose-spec';
2
+
3
+ import { createComposeSdk, materialisers, resources } from '../index.js';
4
+
5
+ import { 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 });
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
+ };