@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.
- package/LICENSE +201 -0
- package/README.md +220 -0
- package/dist/authoring/FlowBuilderCore.cjs +115 -0
- package/dist/authoring/FlowBuilderCore.cjs.map +1 -0
- package/dist/authoring/FlowBuilderCore.d.cts +114 -0
- package/dist/authoring/FlowBuilderCore.d.ts +114 -0
- package/dist/authoring/FlowBuilderCore.js +91 -0
- package/dist/authoring/FlowBuilderCore.js.map +1 -0
- package/dist/authoring/handles.cjs +43 -0
- package/dist/authoring/handles.cjs.map +1 -0
- package/dist/authoring/handles.d.cts +61 -0
- package/dist/authoring/handles.d.ts +61 -0
- package/dist/authoring/handles.js +17 -0
- package/dist/authoring/handles.js.map +1 -0
- package/dist/authoring/raw.cjs +41 -0
- package/dist/authoring/raw.cjs.map +1 -0
- package/dist/authoring/raw.d.cts +47 -0
- package/dist/authoring/raw.d.ts +47 -0
- package/dist/authoring/raw.js +16 -0
- package/dist/authoring/raw.js.map +1 -0
- package/dist/authoring/signatureArgs.cjs +114 -0
- package/dist/authoring/signatureArgs.cjs.map +1 -0
- package/dist/authoring/signatureArgs.d.cts +146 -0
- package/dist/authoring/signatureArgs.d.ts +146 -0
- package/dist/authoring/signatureArgs.js +87 -0
- package/dist/authoring/signatureArgs.js.map +1 -0
- package/dist/client.cjs +140 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +67 -0
- package/dist/client.d.ts +67 -0
- package/dist/client.js +116 -0
- package/dist/client.js.map +1 -0
- package/dist/discovery.cjs +17 -0
- package/dist/discovery.cjs.map +1 -0
- package/dist/discovery.d.cts +56 -0
- package/dist/discovery.d.ts +56 -0
- package/dist/discovery.js +1 -0
- package/dist/discovery.js.map +1 -0
- package/dist/errors.cjs +91 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.cts +77 -0
- package/dist/errors.d.ts +77 -0
- package/dist/errors.js +65 -0
- package/dist/errors.js.map +1 -0
- package/dist/generated/config.generated.cjs +17 -0
- package/dist/generated/config.generated.cjs.map +1 -0
- package/dist/generated/config.generated.d.cts +144 -0
- package/dist/generated/config.generated.d.ts +144 -0
- package/dist/generated/config.generated.js +1 -0
- package/dist/generated/config.generated.js.map +1 -0
- package/dist/generated/guards.generated.cjs +32 -0
- package/dist/generated/guards.generated.cjs.map +1 -0
- package/dist/generated/guards.generated.d.cts +4 -0
- package/dist/generated/guards.generated.d.ts +4 -0
- package/dist/generated/guards.generated.js +8 -0
- package/dist/generated/guards.generated.js.map +1 -0
- package/dist/generated/materialisers.generated.cjs +44 -0
- package/dist/generated/materialisers.generated.cjs.map +1 -0
- package/dist/generated/materialisers.generated.d.cts +4 -0
- package/dist/generated/materialisers.generated.d.ts +4 -0
- package/dist/generated/materialisers.generated.js +18 -0
- package/dist/generated/materialisers.generated.js.map +1 -0
- package/dist/generated/operations.generated.cjs +110 -0
- package/dist/generated/operations.generated.cjs.map +1 -0
- package/dist/generated/operations.generated.d.cts +337 -0
- package/dist/generated/operations.generated.d.ts +337 -0
- package/dist/generated/operations.generated.js +89 -0
- package/dist/generated/operations.generated.js.map +1 -0
- package/dist/generated/preconditions.generated.cjs +44 -0
- package/dist/generated/preconditions.generated.cjs.map +1 -0
- package/dist/generated/preconditions.generated.d.cts +4 -0
- package/dist/generated/preconditions.generated.d.ts +4 -0
- package/dist/generated/preconditions.generated.js +18 -0
- package/dist/generated/preconditions.generated.js.map +1 -0
- package/dist/guards.generated-DKKDKREA.d.ts +14 -0
- package/dist/guards.generated-hrQ1KPNv.d.cts +14 -0
- package/dist/index.cjs +76 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +99 -0
- package/dist/index.d.ts +99 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/materialisers.generated-BsA1uDW8.d.ts +24 -0
- package/dist/materialisers.generated-nMxTAaVi.d.cts +24 -0
- package/dist/preconditions.generated-DblS13Wq.d.cts +24 -0
- package/dist/preconditions.generated-U7YpVh30.d.ts +24 -0
- package/dist/raw-Dj_2rBSQ.d.cts +19 -0
- package/dist/raw-IxCF_bSS.d.ts +19 -0
- package/dist/raw.cjs +34 -0
- package/dist/raw.cjs.map +1 -0
- package/dist/raw.d.cts +4 -0
- package/dist/raw.d.ts +4 -0
- package/dist/raw.js +8 -0
- package/dist/raw.js.map +1 -0
- package/dist/resources-BKlFxjo8.d.cts +56 -0
- package/dist/resources-CYis1_DS.d.ts +56 -0
- package/dist/resources.cjs +39 -0
- package/dist/resources.cjs.map +1 -0
- package/dist/resources.d.cts +3 -0
- package/dist/resources.d.ts +3 -0
- package/dist/resources.js +14 -0
- package/dist/resources.js.map +1 -0
- package/dist/run/inputs.cjs +51 -0
- package/dist/run/inputs.cjs.map +1 -0
- package/dist/run/inputs.d.cts +91 -0
- package/dist/run/inputs.d.ts +91 -0
- package/dist/run/inputs.js +26 -0
- package/dist/run/inputs.js.map +1 -0
- package/dist/sdk.cjs +60 -0
- package/dist/sdk.cjs.map +1 -0
- package/dist/sdk.d.cts +112 -0
- package/dist/sdk.d.ts +112 -0
- package/dist/sdk.js +40 -0
- package/dist/sdk.js.map +1 -0
- package/dist/types.cjs +17 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +74 -0
- package/dist/types.d.ts +74 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/package.json +81 -0
- package/src/authoring/FlowBuilderCore.ts +270 -0
- package/src/authoring/handles.ts +81 -0
- package/src/authoring/raw.ts +60 -0
- package/src/authoring/signatureArgs.ts +249 -0
- package/src/client.ts +230 -0
- package/src/discovery.ts +51 -0
- package/src/errors.ts +150 -0
- package/src/examples/approveAndDeposit.ts +84 -0
- package/src/examples/callContract.ts +199 -0
- package/src/examples/config.ts +9 -0
- package/src/examples/consolidateToEth.ts +94 -0
- package/src/examples/consolidateToUsdc.ts +95 -0
- package/src/examples/depositFromProxy.ts +87 -0
- package/src/examples/dustSweep.ts +66 -0
- package/src/examples/lifiSwap.ts +56 -0
- package/src/examples/lifiZap.ts +60 -0
- package/src/examples/rawCallWithArithmetic.ts +78 -0
- package/src/examples/readContractState.ts +77 -0
- package/src/examples/run.ts +168 -0
- package/src/examples/splitAndZap.ts +73 -0
- package/src/examples/splitWithArithmetic.ts +93 -0
- package/src/examples/swapAndZap.ts +72 -0
- package/src/examples/swapToRecipient.ts +109 -0
- package/src/examples/swapWithAllowRevert.ts +119 -0
- package/src/examples/swapWithBalanceCheck.ts +73 -0
- package/src/examples/swapWithOutputValidation.ts +125 -0
- package/src/examples/transferTokens.ts +123 -0
- package/src/examples/untypedOpWithTypedRef.ts +77 -0
- package/src/generated/config.generated.ts +174 -0
- package/src/generated/guards.generated.ts +14 -0
- package/src/generated/materialisers.generated.ts +44 -0
- package/src/generated/operations.generated.ts +568 -0
- package/src/generated/preconditions.generated.ts +43 -0
- package/src/index.ts +149 -0
- package/src/raw.ts +10 -0
- package/src/resources.ts +61 -0
- package/src/run/inputs.ts +117 -0
- package/src/sdk.ts +173 -0
- package/src/types.ts +101 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import type { ComposeCompileRequest, Flow } from '@lifi/compose-spec';
|
|
2
|
+
|
|
3
|
+
import { createComposeSdk, materialisers, resources } from '../index.js';
|
|
4
|
+
import type { Address } from '../types.js';
|
|
5
|
+
|
|
6
|
+
import { BASE_URL } from './config.js';
|
|
7
|
+
|
|
8
|
+
// Example ERC-4626 vault address (Steakhouse USDC on Ethereum mainnet)
|
|
9
|
+
const VAULT = '0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB';
|
|
10
|
+
const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
|
|
11
|
+
const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
|
|
12
|
+
|
|
13
|
+
export interface CallContractInput {
|
|
14
|
+
readonly owner: Address;
|
|
15
|
+
readonly amount: `${bigint}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Redeem shares from an ERC-4626 vault back to the underlying token.
|
|
20
|
+
*
|
|
21
|
+
* Demonstrates:
|
|
22
|
+
* - core.call with a human-readable function signature and typed args
|
|
23
|
+
* - Inline approvals via the `approvals` config (alternative to a separate core.approve)
|
|
24
|
+
* - `$handle` and `$context` argument references
|
|
25
|
+
* - Threading the `result` output into core.asResource for downstream use
|
|
26
|
+
*/
|
|
27
|
+
export const buildRedeemFromVault = ({
|
|
28
|
+
owner,
|
|
29
|
+
amount,
|
|
30
|
+
}: CallContractInput): {
|
|
31
|
+
flow: Flow;
|
|
32
|
+
request: ComposeCompileRequest;
|
|
33
|
+
} => {
|
|
34
|
+
const sdk = createComposeSdk({ baseUrl: BASE_URL });
|
|
35
|
+
|
|
36
|
+
const builder = sdk.flow(1, {
|
|
37
|
+
name: 'redeem-from-vault',
|
|
38
|
+
inputs: {
|
|
39
|
+
shares: resources.erc20(VAULT, 1),
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Redeem vault shares for the underlying USDC.
|
|
44
|
+
// - `input` binds the vault shares resource (consumed by the call)
|
|
45
|
+
// - `approvals` grants the vault allowance inline (no separate approve node needed)
|
|
46
|
+
// - `args` maps function parameters:
|
|
47
|
+
// $handle references a bound input by name
|
|
48
|
+
// $context references a runtime context value (e.g. the execution proxy address)
|
|
49
|
+
// - `returns (uint256)` in the signature gives typed access to `.result`
|
|
50
|
+
const redeemResult = builder.core.call('redeem', {
|
|
51
|
+
resource: builder.inputs.shares,
|
|
52
|
+
bind: {
|
|
53
|
+
shares: builder.inputs.shares,
|
|
54
|
+
receiver: builder.context.executionAddress,
|
|
55
|
+
owner: builder.context.executionAddress,
|
|
56
|
+
},
|
|
57
|
+
config: {
|
|
58
|
+
target: VAULT,
|
|
59
|
+
functionSignature:
|
|
60
|
+
'function redeem(uint256 shares, address receiver, address owner) returns (uint256)',
|
|
61
|
+
approvals: [{ spender: VAULT }],
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Graduate the raw uint256 return value to a tracked USDC resource
|
|
66
|
+
// so downstream nodes can consume it with linearity and slippage tracking.
|
|
67
|
+
builder.core.asResource('underlying', {
|
|
68
|
+
bind: { handle: redeemResult.result },
|
|
69
|
+
config: {
|
|
70
|
+
resource: resources.erc20(USDC, 1),
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const flow = builder.build();
|
|
75
|
+
|
|
76
|
+
const request = sdk.request(flow, {
|
|
77
|
+
signer: owner,
|
|
78
|
+
inputs: {
|
|
79
|
+
shares: materialisers.directDeposit({ amount }),
|
|
80
|
+
},
|
|
81
|
+
sweepTo: builder.context.sender,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return { flow, request };
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Claim rewards from a contract that does not consume a token resource.
|
|
89
|
+
*
|
|
90
|
+
* Demonstrates:
|
|
91
|
+
* - Resource-free core.call (no `resource` field) — routes to `core.invoke` internally
|
|
92
|
+
* - `returns (uint256)` makes `.result` available for downstream use
|
|
93
|
+
* - Graduating the raw result to a tracked resource via core.asResource
|
|
94
|
+
*/
|
|
95
|
+
export const buildClaimRewards = ({
|
|
96
|
+
owner,
|
|
97
|
+
}: {
|
|
98
|
+
readonly owner: Address;
|
|
99
|
+
}): {
|
|
100
|
+
flow: Flow;
|
|
101
|
+
request: ComposeCompileRequest;
|
|
102
|
+
} => {
|
|
103
|
+
const REWARDS_CONTRACT = '0x1111111111111111111111111111111111111111';
|
|
104
|
+
const REWARD_TOKEN = '0x2222222222222222222222222222222222222222';
|
|
105
|
+
|
|
106
|
+
const sdk = createComposeSdk({ baseUrl: BASE_URL });
|
|
107
|
+
|
|
108
|
+
const builder = sdk.flow(1, {
|
|
109
|
+
name: 'claim-rewards',
|
|
110
|
+
inputs: {},
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Claim rewards — no token consumed, no resource needed.
|
|
114
|
+
// The `returns (uint256)` clause enables typed access to `.result`.
|
|
115
|
+
const claimResult = builder.core.call('claim', {
|
|
116
|
+
bind: {},
|
|
117
|
+
config: {
|
|
118
|
+
target: REWARDS_CONTRACT,
|
|
119
|
+
functionSignature: 'function claim() returns (uint256)',
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Graduate the raw uint256 result to a tracked resource.
|
|
124
|
+
builder.core.asResource('reward-token', {
|
|
125
|
+
bind: { handle: claimResult.result },
|
|
126
|
+
config: {
|
|
127
|
+
resource: resources.erc20(REWARD_TOKEN, 1),
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const flow = builder.build();
|
|
132
|
+
|
|
133
|
+
const request = sdk.request(flow, {
|
|
134
|
+
signer: owner,
|
|
135
|
+
inputs: {},
|
|
136
|
+
sweepTo: builder.context.sender,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
return { flow, request };
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Wrap native ETH into WETH using a ValueCall.
|
|
144
|
+
*
|
|
145
|
+
* Demonstrates:
|
|
146
|
+
* - `callType: 'ValueCall'` to send native ETH value along with the call
|
|
147
|
+
* - Calling a void payable function (no return value — `.result` is `undefined`)
|
|
148
|
+
* - Using `core.balanceOf` to discover the minted WETH after a void call
|
|
149
|
+
*/
|
|
150
|
+
export const buildWrapEth = ({
|
|
151
|
+
owner,
|
|
152
|
+
amount,
|
|
153
|
+
}: CallContractInput): {
|
|
154
|
+
flow: Flow;
|
|
155
|
+
request: ComposeCompileRequest;
|
|
156
|
+
} => {
|
|
157
|
+
const sdk = createComposeSdk({ baseUrl: BASE_URL });
|
|
158
|
+
|
|
159
|
+
const builder = sdk.flow(1, {
|
|
160
|
+
name: 'wrap-eth',
|
|
161
|
+
inputs: {
|
|
162
|
+
ethIn: resources.native(1),
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// WETH.deposit() is payable with no arguments — the ETH value sent
|
|
167
|
+
// becomes the minted WETH amount. `callType: 'ValueCall'` forwards
|
|
168
|
+
// the bound resource's value as msg.value.
|
|
169
|
+
// deposit() returns void, so .result is undefined.
|
|
170
|
+
builder.core.call('wrap', {
|
|
171
|
+
resource: builder.inputs.ethIn,
|
|
172
|
+
bind: {},
|
|
173
|
+
config: {
|
|
174
|
+
target: WETH,
|
|
175
|
+
functionSignature: 'function deposit()',
|
|
176
|
+
callType: 'ValueCall',
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// deposit() is void — read the minted WETH balance to get a tracked resource.
|
|
181
|
+
builder.core.balanceOf('weth', {
|
|
182
|
+
bind: {},
|
|
183
|
+
config: {
|
|
184
|
+
token: WETH,
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const flow = builder.build();
|
|
189
|
+
|
|
190
|
+
const request = sdk.request(flow, {
|
|
191
|
+
signer: owner,
|
|
192
|
+
inputs: {
|
|
193
|
+
ethIn: materialisers.directDeposit({ amount }),
|
|
194
|
+
},
|
|
195
|
+
sweepTo: builder.context.sender,
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
return { flow, request };
|
|
199
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// COMPOSER_BASE_URL rather than BASE_URL to avoid collision with Vite's
|
|
2
|
+
// built-in process.env.BASE_URL (set to "/" from the `base` config option).
|
|
3
|
+
export const BASE_URL: string =
|
|
4
|
+
process.env['COMPOSER_BASE_URL'] ?? 'https://composer.li.quest';
|
|
5
|
+
export const API_KEY: string | undefined = process.env['LIFI_API_KEY'];
|
|
6
|
+
|
|
7
|
+
export const OWNER = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045';
|
|
8
|
+
export const RECIPIENT = '0x1234567890abcdef1234567890abcdef12345678';
|
|
9
|
+
export const PROXY = '0x2222222222222222222222222222222222222222';
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { ComposeCompileRequest, Flow } from '@lifi/compose-spec';
|
|
2
|
+
|
|
3
|
+
import { createComposeSdk, materialisers, resources } from '../index.js';
|
|
4
|
+
import type { Address } from '../types.js';
|
|
5
|
+
|
|
6
|
+
import { BASE_URL } from './config.js';
|
|
7
|
+
|
|
8
|
+
export interface ConsolidateToEthInput {
|
|
9
|
+
readonly owner: Address;
|
|
10
|
+
readonly wethAmount: `${bigint}`;
|
|
11
|
+
readonly usdcAmount: `${bigint}`;
|
|
12
|
+
readonly usdtAmount: `${bigint}`;
|
|
13
|
+
readonly daiAmount: `${bigint}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const CHAIN_ID = 1;
|
|
17
|
+
|
|
18
|
+
const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
|
|
19
|
+
const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
|
|
20
|
+
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7';
|
|
21
|
+
const DAI = '0x6B175474E89094C44Da98b954EedeAC495271d0F';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Consolidate ERC-20 token balances into native ETH on Ethereum mainnet.
|
|
25
|
+
*
|
|
26
|
+
* Demonstrates:
|
|
27
|
+
* - Multiple resource inputs swapped to native ETH (not an ERC-20 target)
|
|
28
|
+
* - resources.native() for the swap target
|
|
29
|
+
* - directDeposit materialisers with fixed amounts (no on-chain balance read)
|
|
30
|
+
*/
|
|
31
|
+
export const buildConsolidateToEth = ({
|
|
32
|
+
owner,
|
|
33
|
+
wethAmount,
|
|
34
|
+
usdcAmount,
|
|
35
|
+
usdtAmount,
|
|
36
|
+
daiAmount,
|
|
37
|
+
}: ConsolidateToEthInput): {
|
|
38
|
+
flow: Flow;
|
|
39
|
+
request: ComposeCompileRequest;
|
|
40
|
+
} => {
|
|
41
|
+
const sdk = createComposeSdk({ baseUrl: BASE_URL });
|
|
42
|
+
const erc20 = (token: Address) => resources.erc20(token, CHAIN_ID);
|
|
43
|
+
|
|
44
|
+
// Declare the flow with one input per ERC-20 token on Ethereum mainnet.
|
|
45
|
+
const builder = sdk.flow(CHAIN_ID, {
|
|
46
|
+
name: 'consolidate-to-eth',
|
|
47
|
+
inputs: {
|
|
48
|
+
token_weth: erc20(WETH),
|
|
49
|
+
token_usdc: erc20(USDC),
|
|
50
|
+
token_usdt: erc20(USDT),
|
|
51
|
+
token_dai: erc20(DAI),
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Swap each token → native ETH via LI.FI with shared config.
|
|
56
|
+
const swapConfig = {
|
|
57
|
+
resourceOut: resources.native(CHAIN_ID),
|
|
58
|
+
slippage: 0.03,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
builder.lifi.swap('swap_token_weth', {
|
|
62
|
+
bind: { amountIn: builder.inputs.token_weth },
|
|
63
|
+
config: swapConfig,
|
|
64
|
+
});
|
|
65
|
+
builder.lifi.swap('swap_token_usdc', {
|
|
66
|
+
bind: { amountIn: builder.inputs.token_usdc },
|
|
67
|
+
config: swapConfig,
|
|
68
|
+
});
|
|
69
|
+
builder.lifi.swap('swap_token_usdt', {
|
|
70
|
+
bind: { amountIn: builder.inputs.token_usdt },
|
|
71
|
+
config: swapConfig,
|
|
72
|
+
});
|
|
73
|
+
builder.lifi.swap('swap_token_dai', {
|
|
74
|
+
bind: { amountIn: builder.inputs.token_dai },
|
|
75
|
+
config: swapConfig,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const flow = builder.build();
|
|
79
|
+
|
|
80
|
+
// Build the compile request.
|
|
81
|
+
// directDeposit materialisers transfer fixed amounts into the VM.
|
|
82
|
+
const request = sdk.request(flow, {
|
|
83
|
+
signer: owner,
|
|
84
|
+
inputs: {
|
|
85
|
+
token_weth: materialisers.directDeposit({ amount: wethAmount }),
|
|
86
|
+
token_usdc: materialisers.directDeposit({ amount: usdcAmount }),
|
|
87
|
+
token_usdt: materialisers.directDeposit({ amount: usdtAmount }),
|
|
88
|
+
token_dai: materialisers.directDeposit({ amount: daiAmount }),
|
|
89
|
+
},
|
|
90
|
+
sweepTo: builder.context.sender,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return { flow, request };
|
|
94
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { ComposeCompileRequest, Flow } from '@lifi/compose-spec';
|
|
2
|
+
|
|
3
|
+
import { createComposeSdk, materialisers, resources } from '../index.js';
|
|
4
|
+
import type { Address } from '../types.js';
|
|
5
|
+
|
|
6
|
+
import { BASE_URL } from './config.js';
|
|
7
|
+
|
|
8
|
+
export interface ConsolidateStablesToUsdcInput {
|
|
9
|
+
readonly owner: Address;
|
|
10
|
+
readonly usdtAmount: `${bigint}`;
|
|
11
|
+
readonly daiAmount: `${bigint}`;
|
|
12
|
+
readonly fraxAmount: `${bigint}`;
|
|
13
|
+
readonly lusdAmount: `${bigint}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const CHAIN_ID = 1;
|
|
17
|
+
const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
|
|
18
|
+
|
|
19
|
+
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7';
|
|
20
|
+
const DAI = '0x6B175474E89094C44Da98b954EedeAC495271d0F';
|
|
21
|
+
const FRAX = '0x853d955aCEf822Db058eb8505911ED77F175b99e';
|
|
22
|
+
const LUSD = '0x5f98805A4E8be255a32880FDeC7F6728C6568bA0';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Consolidate blue-chip stablecoin balances into USDC on Ethereum mainnet.
|
|
26
|
+
*
|
|
27
|
+
* Demonstrates:
|
|
28
|
+
* - Multiple resource inputs (four stablecoins)
|
|
29
|
+
* - Shared swap config reused across all nodes
|
|
30
|
+
* - directDeposit materialisers with fixed amounts (no on-chain balance read)
|
|
31
|
+
*/
|
|
32
|
+
export const buildConsolidateStablesToUsdc = ({
|
|
33
|
+
owner,
|
|
34
|
+
usdtAmount,
|
|
35
|
+
daiAmount,
|
|
36
|
+
fraxAmount,
|
|
37
|
+
lusdAmount,
|
|
38
|
+
}: ConsolidateStablesToUsdcInput): {
|
|
39
|
+
flow: Flow;
|
|
40
|
+
request: ComposeCompileRequest;
|
|
41
|
+
} => {
|
|
42
|
+
const sdk = createComposeSdk({ baseUrl: BASE_URL });
|
|
43
|
+
const erc20 = (token: Address) => resources.erc20(token, CHAIN_ID);
|
|
44
|
+
|
|
45
|
+
// Declare the flow with one input per stablecoin on Ethereum mainnet.
|
|
46
|
+
const builder = sdk.flow(CHAIN_ID, {
|
|
47
|
+
name: 'consolidate-stables-to-usdc',
|
|
48
|
+
inputs: {
|
|
49
|
+
stable_usdt: erc20(USDT),
|
|
50
|
+
stable_dai: erc20(DAI),
|
|
51
|
+
stable_frax: erc20(FRAX),
|
|
52
|
+
stable_lusd: erc20(LUSD),
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Swap each stablecoin → USDC via LI.FI with shared config.
|
|
57
|
+
const swapConfig = {
|
|
58
|
+
resourceOut: resources.erc20(USDC, CHAIN_ID),
|
|
59
|
+
slippage: 0.03,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
builder.lifi.swap('swap_stable_usdt', {
|
|
63
|
+
bind: { amountIn: builder.inputs.stable_usdt },
|
|
64
|
+
config: swapConfig,
|
|
65
|
+
});
|
|
66
|
+
builder.lifi.swap('swap_stable_dai', {
|
|
67
|
+
bind: { amountIn: builder.inputs.stable_dai },
|
|
68
|
+
config: swapConfig,
|
|
69
|
+
});
|
|
70
|
+
builder.lifi.swap('swap_stable_frax', {
|
|
71
|
+
bind: { amountIn: builder.inputs.stable_frax },
|
|
72
|
+
config: swapConfig,
|
|
73
|
+
});
|
|
74
|
+
builder.lifi.swap('swap_stable_lusd', {
|
|
75
|
+
bind: { amountIn: builder.inputs.stable_lusd },
|
|
76
|
+
config: swapConfig,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const flow = builder.build();
|
|
80
|
+
|
|
81
|
+
// Build the compile request.
|
|
82
|
+
// directDeposit materialisers transfer fixed amounts into the VM.
|
|
83
|
+
const request = sdk.request(flow, {
|
|
84
|
+
signer: owner,
|
|
85
|
+
inputs: {
|
|
86
|
+
stable_usdt: materialisers.directDeposit({ amount: usdtAmount }),
|
|
87
|
+
stable_dai: materialisers.directDeposit({ amount: daiAmount }),
|
|
88
|
+
stable_frax: materialisers.directDeposit({ amount: fraxAmount }),
|
|
89
|
+
stable_lusd: materialisers.directDeposit({ amount: lusdAmount }),
|
|
90
|
+
},
|
|
91
|
+
sweepTo: builder.context.sender,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return { flow, request };
|
|
95
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { ComposeCompileRequest, Flow } from '@lifi/compose-spec';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
createComposeSdk,
|
|
5
|
+
guards,
|
|
6
|
+
materialisers,
|
|
7
|
+
preconditions,
|
|
8
|
+
resources,
|
|
9
|
+
} from '../index.js';
|
|
10
|
+
import type { Address } from '../types.js';
|
|
11
|
+
|
|
12
|
+
import { BASE_URL } from './config.js';
|
|
13
|
+
|
|
14
|
+
const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
|
|
15
|
+
// Aave v3 aEthUSDC receipt token on Ethereum mainnet
|
|
16
|
+
const A_ETH_USDC = '0x98C23E9d8f34FEFb1B7BD6a91B7FF122F4e16F5c';
|
|
17
|
+
|
|
18
|
+
export interface DepositFromProxyInput {
|
|
19
|
+
readonly owner: Address;
|
|
20
|
+
readonly proxyAddress: Address;
|
|
21
|
+
readonly expectedAmount: `${bigint}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Read tokens already on the proxy and deposit them into Aave.
|
|
26
|
+
*
|
|
27
|
+
* Demonstrates:
|
|
28
|
+
* - `balanceOf` materialiser to source input from the proxy's existing
|
|
29
|
+
* token balance rather than transferring tokens in.
|
|
30
|
+
* - `erc20Balance` precondition to assert the expected amount is present.
|
|
31
|
+
*
|
|
32
|
+
* Why the precondition matters:
|
|
33
|
+
* `balanceOf` reads whatever balance happens to be on the proxy at
|
|
34
|
+
* execution time. Without a precondition, the flow would silently
|
|
35
|
+
* succeed with zero tokens if the expected funds never arrived (e.g.
|
|
36
|
+
* a bridge transfer that hasn't landed yet). The precondition makes
|
|
37
|
+
* the flow fail-fast with a clear error instead of executing a
|
|
38
|
+
* worthless deposit.
|
|
39
|
+
*/
|
|
40
|
+
export const buildDepositFromProxy = ({
|
|
41
|
+
owner,
|
|
42
|
+
proxyAddress,
|
|
43
|
+
expectedAmount,
|
|
44
|
+
}: DepositFromProxyInput): {
|
|
45
|
+
flow: Flow;
|
|
46
|
+
request: ComposeCompileRequest;
|
|
47
|
+
} => {
|
|
48
|
+
const sdk = createComposeSdk({ baseUrl: BASE_URL });
|
|
49
|
+
|
|
50
|
+
const builder = sdk.flow(1, {
|
|
51
|
+
name: 'deposit-from-proxy',
|
|
52
|
+
inputs: {
|
|
53
|
+
amountIn: resources.erc20(USDC, 1),
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Zap the USDC into Aave's aEthUSDC position.
|
|
58
|
+
builder.lifi.zap('deposit', {
|
|
59
|
+
bind: { amountIn: builder.inputs.amountIn },
|
|
60
|
+
config: {
|
|
61
|
+
resourceOut: resources.erc20(A_ETH_USDC, 1),
|
|
62
|
+
},
|
|
63
|
+
guards: [guards.slippage({ port: 'amountOut', bps: 100 })],
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const flow = builder.build();
|
|
67
|
+
|
|
68
|
+
// balanceOf reads the proxy's current USDC balance as the input.
|
|
69
|
+
// The precondition guarantees at least `expectedAmount` is present —
|
|
70
|
+
// without it, a delayed bridge would cause a silent zero-value deposit.
|
|
71
|
+
const request = sdk.request(flow, {
|
|
72
|
+
signer: owner,
|
|
73
|
+
inputs: {
|
|
74
|
+
amountIn: materialisers.balanceOf({ owner: proxyAddress }),
|
|
75
|
+
},
|
|
76
|
+
preconditions: [
|
|
77
|
+
preconditions.erc20Balance({
|
|
78
|
+
wallet: proxyAddress,
|
|
79
|
+
token: USDC,
|
|
80
|
+
balance: expectedAmount,
|
|
81
|
+
}),
|
|
82
|
+
],
|
|
83
|
+
sweepTo: builder.context.sender,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return { flow, request };
|
|
87
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
|
|
7
|
+
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Split USDC 80/20, swap only the 80% portion to USDT, and sweep the
|
|
11
|
+
* remaining 20% back to the sender as dust.
|
|
12
|
+
*
|
|
13
|
+
* Demonstrates:
|
|
14
|
+
* - Dust recovery via `sweepTo`. When a flow produces leftover tokens
|
|
15
|
+
* that are not consumed by any downstream operation, those tokens
|
|
16
|
+
* remain on the proxy contract. `sweepTo` tells the backend to
|
|
17
|
+
* transfer all residual token balances to the specified address
|
|
18
|
+
* at the end of execution.
|
|
19
|
+
* - In this example the 20% USDC from the split is intentionally
|
|
20
|
+
* unused — it becomes dust that `sweepTo` returns to the sender.
|
|
21
|
+
*/
|
|
22
|
+
export const buildDustSweepExample = (): {
|
|
23
|
+
flow: Flow;
|
|
24
|
+
request: ComposeCompileRequest;
|
|
25
|
+
} => {
|
|
26
|
+
const sdk = createComposeSdk({ baseUrl: BASE_URL });
|
|
27
|
+
|
|
28
|
+
const builder = sdk.flow(1, {
|
|
29
|
+
name: 'dust-sweep',
|
|
30
|
+
inputs: {
|
|
31
|
+
amountIn: resources.erc20(USDC, 1),
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Split USDC 80/20.
|
|
36
|
+
// Only the 80% portion (`a`) is consumed by the swap.
|
|
37
|
+
// The 20% portion (`b`) is intentionally left unbound — it stays on
|
|
38
|
+
// the proxy as dust and gets swept back to the sender.
|
|
39
|
+
const { a } = builder.core.split('split', {
|
|
40
|
+
bind: { source: builder.inputs.amountIn },
|
|
41
|
+
config: { bps: 8000 },
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Swap only the 80% portion to USDT.
|
|
45
|
+
builder.lifi.swap('swap', {
|
|
46
|
+
bind: { amountIn: a },
|
|
47
|
+
config: {
|
|
48
|
+
resourceOut: resources.erc20(USDT, 1),
|
|
49
|
+
slippage: 0.03,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const flow = builder.build();
|
|
54
|
+
|
|
55
|
+
// `sweepTo` ensures the unused 20% USDC is transferred back to the
|
|
56
|
+
// sender rather than being left stranded on the proxy contract.
|
|
57
|
+
const request = sdk.request(flow, {
|
|
58
|
+
signer: OWNER,
|
|
59
|
+
inputs: {
|
|
60
|
+
amountIn: materialisers.directDeposit({ amount: '10000000' }),
|
|
61
|
+
},
|
|
62
|
+
sweepTo: builder.context.sender,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return { flow, request };
|
|
66
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
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 on Ethereum mainnet via LI.FI.
|
|
12
|
+
*
|
|
13
|
+
* Demonstrates:
|
|
14
|
+
* - Simplest possible single-swap flow
|
|
15
|
+
* - directDeposit materialiser with a fixed amount
|
|
16
|
+
* - No slippage guard needed — lifi.swap's amountOut already providesMinimum
|
|
17
|
+
*/
|
|
18
|
+
export const buildLifiSwapExample = (): {
|
|
19
|
+
flow: Flow;
|
|
20
|
+
request: ComposeCompileRequest;
|
|
21
|
+
} => {
|
|
22
|
+
const sdk = createComposeSdk({ baseUrl: BASE_URL });
|
|
23
|
+
|
|
24
|
+
// Declare the flow with a single WETH input on Ethereum mainnet.
|
|
25
|
+
const builder = sdk.flow(1, {
|
|
26
|
+
name: 'swap-weth-to-usdc',
|
|
27
|
+
inputs: {
|
|
28
|
+
amountIn: resources.erc20(WETH, 1),
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Swap WETH → USDC via LI.FI.
|
|
33
|
+
builder.lifi.swap('swap', {
|
|
34
|
+
bind: { amountIn: builder.inputs.amountIn },
|
|
35
|
+
config: {
|
|
36
|
+
resourceOut: resources.erc20(USDC, 1),
|
|
37
|
+
slippage: 0.03,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const flow = builder.build();
|
|
42
|
+
|
|
43
|
+
// Build the compile request.
|
|
44
|
+
// directDeposit transfers a fixed amount of WETH into the VM.
|
|
45
|
+
const request = sdk.request(flow, {
|
|
46
|
+
signer: OWNER,
|
|
47
|
+
inputs: {
|
|
48
|
+
amountIn: materialisers.directDeposit({
|
|
49
|
+
amount: '1000000000000000000',
|
|
50
|
+
}),
|
|
51
|
+
},
|
|
52
|
+
sweepTo: builder.context.sender,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return { flow, request };
|
|
56
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
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
|
+
|
|
10
|
+
import { BASE_URL, OWNER } from './config.js';
|
|
11
|
+
const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
|
|
12
|
+
// Aave aEthUSDC receipt token on Ethereum mainnet
|
|
13
|
+
const A_ETH_USDC = '0x98C23E9d8f34FEFb1B7BD6a91B7FF122F4e16F5c';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Zap USDC into an Aave lending position on Ethereum mainnet via LI.FI.
|
|
17
|
+
*
|
|
18
|
+
* Demonstrates:
|
|
19
|
+
* - Simplest possible single-zap flow
|
|
20
|
+
* - Slippage guard on the zap output (allowed because amountOut does not providesMinimum)
|
|
21
|
+
* - directDeposit materialiser with a fixed amount
|
|
22
|
+
*/
|
|
23
|
+
export const buildLifiZapExample = (): {
|
|
24
|
+
flow: Flow;
|
|
25
|
+
request: ComposeCompileRequest;
|
|
26
|
+
} => {
|
|
27
|
+
const sdk = createComposeSdk({ baseUrl: BASE_URL });
|
|
28
|
+
|
|
29
|
+
// Declare the flow with a single USDC input on Ethereum mainnet.
|
|
30
|
+
const builder = sdk.flow(1, {
|
|
31
|
+
name: 'zap-usdc-to-aave',
|
|
32
|
+
inputs: {
|
|
33
|
+
amountIn: resources.erc20(USDC, 1),
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Zap USDC into Aave's aEthUSDC position via LI.FI.
|
|
38
|
+
// Slippage guard asserts the output is within 1% (100 bps) of the expected amount.
|
|
39
|
+
builder.lifi.zap('zap', {
|
|
40
|
+
bind: { amountIn: builder.inputs.amountIn },
|
|
41
|
+
config: {
|
|
42
|
+
resourceOut: resources.erc20(A_ETH_USDC, 1),
|
|
43
|
+
},
|
|
44
|
+
guards: [guards.slippage({ port: 'amountOut', bps: 100 })],
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const flow = builder.build();
|
|
48
|
+
|
|
49
|
+
// Build the compile request.
|
|
50
|
+
// directDeposit transfers a fixed amount of USDC into the VM.
|
|
51
|
+
const request = sdk.request(flow, {
|
|
52
|
+
signer: OWNER,
|
|
53
|
+
inputs: {
|
|
54
|
+
amountIn: materialisers.directDeposit({ amount: '1000000000' }),
|
|
55
|
+
},
|
|
56
|
+
sweepTo: builder.context.sender,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return { flow, request };
|
|
60
|
+
};
|