@lifi/composer-sdk 0.9.0 → 0.11.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.
- package/README.md +37 -3
- package/dist/authoring/raw.cjs +12 -7
- package/dist/authoring/raw.cjs.map +1 -1
- package/dist/authoring/raw.d.cts +12 -7
- package/dist/authoring/raw.d.ts +12 -7
- package/dist/authoring/raw.js +12 -7
- package/dist/authoring/raw.js.map +1 -1
- package/dist/client.cjs +11 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.js +11 -1
- package/dist/client.js.map +1 -1
- package/dist/errors.cjs +35 -13
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +19 -1
- package/dist/errors.d.ts +19 -1
- package/dist/errors.js +35 -14
- package/dist/errors.js.map +1 -1
- package/dist/generated/config.generated.d.cts +96 -1
- package/dist/generated/config.generated.d.ts +96 -1
- package/dist/generated/operations.generated.cjs +10 -0
- package/dist/generated/operations.generated.cjs.map +1 -1
- package/dist/generated/operations.generated.d.cts +56 -1
- package/dist/generated/operations.generated.d.ts +56 -1
- package/dist/generated/operations.generated.js +10 -0
- package/dist/generated/operations.generated.js.map +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/outputs.cjs +3 -2
- package/dist/outputs.cjs.map +1 -1
- package/dist/outputs.d.cts +3 -2
- package/dist/outputs.d.ts +3 -2
- package/dist/outputs.js +3 -2
- package/dist/outputs.js.map +1 -1
- package/dist/responseSchemas.cjs.map +1 -1
- package/dist/responseSchemas.d.cts +2 -2
- package/dist/responseSchemas.d.ts +2 -2
- package/dist/responseSchemas.js.map +1 -1
- package/dist/run/inputs.cjs.map +1 -1
- package/dist/run/inputs.d.cts +3 -3
- package/dist/run/inputs.d.ts +3 -3
- package/dist/run/inputs.js.map +1 -1
- package/package.json +3 -3
- package/src/authoring/raw.ts +12 -7
- package/src/client.ts +24 -1
- package/src/errors.ts +48 -17
- package/src/examples/continuationBridgeSettle.ts +100 -0
- package/src/examples/continuationSettle.ts +113 -0
- package/src/examples/run.ts +8 -0
- package/src/generated/config.generated.ts +109 -1
- package/src/generated/operations.generated.ts +98 -0
- package/src/index.ts +5 -1
- package/src/outputs.ts +3 -2
- package/src/responseSchemas.ts +9 -5
- package/src/run/inputs.ts +3 -3
|
@@ -0,0 +1,100 @@
|
|
|
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
|
+
const ARBITRUM = 42161;
|
|
14
|
+
const BASE = 8453;
|
|
15
|
+
const ARB_USDC = '0xaf88d065e77c8cC2239327C5EDb3A432268e5831';
|
|
16
|
+
const BASE_USDC = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
|
|
17
|
+
// Aave V3 aToken for USDC on Base.
|
|
18
|
+
const A_BAS_USDC = '0x4e65fE4DbA92790696d040ac24Aa414708F5c0AB';
|
|
19
|
+
const VALIDITY_WINDOW_MS = 3_600_000;
|
|
20
|
+
|
|
21
|
+
export interface ContinuationBridgeSettleInput {
|
|
22
|
+
readonly owner: Address;
|
|
23
|
+
// Receives the aBasUSDC position on Base; defaults to `owner`.
|
|
24
|
+
readonly recipient?: Address;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Bridge USDC from Arbitrum to Base, and escrow the bridged USDC on Base for a
|
|
29
|
+
* deferred settlement that supplies it to Aave and delivers the aBasUSDC
|
|
30
|
+
* position to the recipient.
|
|
31
|
+
*
|
|
32
|
+
* Demonstrates:
|
|
33
|
+
* - `lifi.bridge` with no `destination`: its `amountOut` funds the settle's
|
|
34
|
+
* escrow on Base instead of landing at an address
|
|
35
|
+
* - `continuation.settle` bound to `bridge.amountOut` (delivered funding): the
|
|
36
|
+
* bridge delivers straight into the escrow, so the user signs one
|
|
37
|
+
* transaction on Arbitrum, and the settle must omit `funding` and
|
|
38
|
+
* `perpetual`
|
|
39
|
+
* - `validity.expiresAtMs` at least `max(3 × the bridge ETA, 30 minutes)` away
|
|
40
|
+
* - A leg on the escrow chain (Base) that does the work the user could not do
|
|
41
|
+
* from Arbitrum: `lifi.zap` supplies the landed USDC to Aave. The aBasUSDC
|
|
42
|
+
* stays in the leg's proxy; the settlement epilogue the composer appends at
|
|
43
|
+
* commit forwards it to the recipient
|
|
44
|
+
* - An outcome in a token the leg produces (aBasUSDC), not the funding token:
|
|
45
|
+
* the zap's slippage guard proves the floor, so `minAmount` is omitted
|
|
46
|
+
*/
|
|
47
|
+
export const buildContinuationBridgeSettleExample = ({
|
|
48
|
+
owner,
|
|
49
|
+
recipient = owner,
|
|
50
|
+
}: ContinuationBridgeSettleInput): {
|
|
51
|
+
flow: Flow;
|
|
52
|
+
request: ComposeCompileRequest;
|
|
53
|
+
} => {
|
|
54
|
+
const sdk = createComposeSdk({ baseUrl: BASE_URL, apiKey: API_KEY });
|
|
55
|
+
|
|
56
|
+
// The leg: runs from the escrow on Base once the bridged USDC has landed.
|
|
57
|
+
// The zap supplies the USDC to Aave; the aBasUSDC it mints lands in the
|
|
58
|
+
// leg's proxy, where the settlement epilogue picks it up. The slippage guard
|
|
59
|
+
// on `amountOut` is the enforced floor the compiler commits.
|
|
60
|
+
const leg = sdk.flow(BASE, {
|
|
61
|
+
name: 'bridge-settle-leg',
|
|
62
|
+
inputs: { funding: resources.erc20(BASE_USDC, BASE) },
|
|
63
|
+
});
|
|
64
|
+
leg.lifi.zap('supply', {
|
|
65
|
+
bind: { amountIn: leg.inputs.funding },
|
|
66
|
+
config: { resourceOut: resources.erc20(A_BAS_USDC, BASE) },
|
|
67
|
+
guards: [guards.slippage({ port: 'amountOut', bps: 50 })],
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// The main flow on Arbitrum: bridge to Base, then escrow the delivery.
|
|
71
|
+
const builder = sdk.flow(ARBITRUM, {
|
|
72
|
+
name: 'bridge-and-settle',
|
|
73
|
+
inputs: { amountIn: resources.erc20(ARB_USDC, ARBITRUM) },
|
|
74
|
+
});
|
|
75
|
+
const bridge = builder.lifi.bridge('bridge', {
|
|
76
|
+
bind: { amountIn: builder.inputs.amountIn },
|
|
77
|
+
config: { resourceOut: resources.erc20(BASE_USDC, BASE) },
|
|
78
|
+
});
|
|
79
|
+
builder.continuation.settle('settle', {
|
|
80
|
+
bind: { input: bridge.amountOut },
|
|
81
|
+
config: {
|
|
82
|
+
outcomes: [{ token: A_BAS_USDC, destination: recipient, chainId: BASE }],
|
|
83
|
+
validity: { expiresAtMs: Date.now() + VALIDITY_WINDOW_MS },
|
|
84
|
+
provider: 'intent-factory',
|
|
85
|
+
refund: owner,
|
|
86
|
+
continuationFlow: leg.build(),
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const flow = builder.build();
|
|
91
|
+
|
|
92
|
+
const request = sdk.request(flow, {
|
|
93
|
+
signer: owner,
|
|
94
|
+
inputs: {
|
|
95
|
+
amountIn: materialisers.directDeposit({ amount: '1000000000' }),
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return { flow, request };
|
|
100
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
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
|
+
const BASE = 8453;
|
|
14
|
+
const USDC = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
|
|
15
|
+
const WETH = '0x4200000000000000000000000000000000000006';
|
|
16
|
+
// Aave V3 aToken for WETH on Base.
|
|
17
|
+
const A_BAS_WETH = '0xD4a0e0b9149BCee3C920d2E00b5dE09138fd8bb7';
|
|
18
|
+
const VALIDITY_WINDOW_MS = 3_600_000;
|
|
19
|
+
|
|
20
|
+
export interface ContinuationSettleInput {
|
|
21
|
+
readonly owner: Address;
|
|
22
|
+
// Receives the aBasWETH position; defaults to `owner`.
|
|
23
|
+
readonly recipient?: Address;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Swap USDC to WETH on Base, then escrow the WETH for a deferred settlement
|
|
28
|
+
* whose leg supplies it to Aave and delivers the aBasWETH position to the
|
|
29
|
+
* recipient.
|
|
30
|
+
*
|
|
31
|
+
* Demonstrates:
|
|
32
|
+
* - `continuation.settle` funded by an upstream output (`swap.amountOut`)
|
|
33
|
+
* - The leg (`continuationFlow`) as an ordinary flow built with `sdk.flow`
|
|
34
|
+
* and assigned with `leg.build()`: here one `lifi.zap` that supplies the
|
|
35
|
+
* escrowed WETH to Aave
|
|
36
|
+
* - An outcome in the token the leg produces (aBasWETH): the zap's slippage
|
|
37
|
+
* guard proves the floor, so `minAmount` is omitted
|
|
38
|
+
* - `refund` naming the address that receives the escrow balance on expiry
|
|
39
|
+
* and the leg's residual (optional; defaults to the signer)
|
|
40
|
+
*
|
|
41
|
+
* The leg contract:
|
|
42
|
+
* - Exactly one input: a resource input in the funding token on the escrow
|
|
43
|
+
* chain. The solver binds the escrow balance to it.
|
|
44
|
+
* - Produce each outcome into the leg's own proxy and end there. A zap or a
|
|
45
|
+
* deposit mints into the proxy by default; a node that needs a receiver
|
|
46
|
+
* binds `leg.context.executionAddress`. A funding input no node consumes
|
|
47
|
+
* stays in the proxy as the terminal `input.<name>`. Never
|
|
48
|
+
* pay a recipient: not `destination`, not the provider's settlement
|
|
49
|
+
* recipient, and never `context.sender` (inside the leg that is the
|
|
50
|
+
* settlement account, not the user). Never set the leg's own epilogue. At
|
|
51
|
+
* commit the composer appends the settlement epilogue, which forwards each
|
|
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
|
|
54
|
+
* `amountOut` (see `continuationBridgeSettle.ts`).
|
|
55
|
+
* - `minAmount` is optional: a guard or an op floor on the outcome token
|
|
56
|
+
* proves it, and an unconsumed funding input proves the full funding floor.
|
|
57
|
+
*/
|
|
58
|
+
export const buildContinuationSettleExample = ({
|
|
59
|
+
owner,
|
|
60
|
+
recipient = owner,
|
|
61
|
+
}: ContinuationSettleInput): {
|
|
62
|
+
flow: Flow;
|
|
63
|
+
request: ComposeCompileRequest;
|
|
64
|
+
} => {
|
|
65
|
+
const sdk = createComposeSdk({ baseUrl: BASE_URL, apiKey: API_KEY });
|
|
66
|
+
|
|
67
|
+
// The leg: runs from the escrow on Base once the WETH has landed there. The
|
|
68
|
+
// zap supplies the WETH to Aave; the aBasWETH it mints lands in the leg's
|
|
69
|
+
// proxy, where the settlement epilogue picks it up. The slippage guard on
|
|
70
|
+
// `amountOut` is the enforced floor the compiler commits.
|
|
71
|
+
const leg = sdk.flow(BASE, {
|
|
72
|
+
name: 'settle-leg',
|
|
73
|
+
inputs: { funding: resources.erc20(WETH, BASE) },
|
|
74
|
+
});
|
|
75
|
+
leg.lifi.zap('supply', {
|
|
76
|
+
bind: { amountIn: leg.inputs.funding },
|
|
77
|
+
config: { resourceOut: resources.erc20(A_BAS_WETH, BASE) },
|
|
78
|
+
guards: [guards.slippage({ port: 'amountOut', bps: 50 })],
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// The main flow: swap USDC to WETH, then escrow the WETH for the leg.
|
|
82
|
+
const builder = sdk.flow(BASE, {
|
|
83
|
+
name: 'swap-and-settle',
|
|
84
|
+
inputs: { amountIn: resources.erc20(USDC, BASE) },
|
|
85
|
+
});
|
|
86
|
+
const swap = builder.lifi.swap('swap', {
|
|
87
|
+
bind: { amountIn: builder.inputs.amountIn },
|
|
88
|
+
config: { resourceOut: resources.erc20(WETH, BASE) },
|
|
89
|
+
});
|
|
90
|
+
builder.continuation.settle('settle', {
|
|
91
|
+
bind: { input: swap.amountOut },
|
|
92
|
+
config: {
|
|
93
|
+
outcomes: [{ token: A_BAS_WETH, destination: recipient, chainId: BASE }],
|
|
94
|
+
validity: { expiresAtMs: Date.now() + VALIDITY_WINDOW_MS },
|
|
95
|
+
provider: 'intent-factory',
|
|
96
|
+
refund: owner,
|
|
97
|
+
continuationFlow: leg.build(),
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const flow = builder.build();
|
|
102
|
+
|
|
103
|
+
// No `sweepTo`: the swap output funds the escrow and the settle output is
|
|
104
|
+
// delivered by the settlement, never landing in the VM.
|
|
105
|
+
const request = sdk.request(flow, {
|
|
106
|
+
signer: owner,
|
|
107
|
+
inputs: {
|
|
108
|
+
amountIn: materialisers.directDeposit({ amount: '1000000000' }),
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return { flow, request };
|
|
113
|
+
};
|
package/src/examples/run.ts
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
* approve-deposit — approve vault allowance then deposit USDC
|
|
17
17
|
* consolidate — consolidate ERC-20 balances to USDC
|
|
18
18
|
* consolidate-eth — consolidate ERC-20 balances to native ETH
|
|
19
|
+
* continuation-settle — swap USDC to WETH on Base, escrow it for a deferred settlement
|
|
20
|
+
* continuation-bridge-settle — bridge Arbitrum USDC into a Base settlement escrow
|
|
19
21
|
* deposit-proxy — deposit tokens already on the proxy into Aave
|
|
20
22
|
* dust-sweep — split USDC 80/20 and sweep leftover dust
|
|
21
23
|
* swap — swap WETH to USDC via LI.FI
|
|
@@ -62,6 +64,8 @@ import { buildRedeemFromVault, buildWrapEth } from './callContract.js';
|
|
|
62
64
|
import { API_KEY, BASE_URL, OWNER, PROXY, RECIPIENT } from './config.js';
|
|
63
65
|
import { buildConsolidateToEth } from './consolidateToEth.js';
|
|
64
66
|
import { buildConsolidateStablesToUsdc } from './consolidateToUsdc.js';
|
|
67
|
+
import { buildContinuationBridgeSettleExample } from './continuationBridgeSettle.js';
|
|
68
|
+
import { buildContinuationSettleExample } from './continuationSettle.js';
|
|
65
69
|
import { buildDepositFromProxy } from './depositFromProxy.js';
|
|
66
70
|
import { buildDustSweepExample } from './dustSweep.js';
|
|
67
71
|
import { buildFlySwapExample } from './flySwap.js';
|
|
@@ -134,6 +138,10 @@ const EXAMPLES: Record<string, () => ComposeCompileRequest> = {
|
|
|
134
138
|
usdtAmount: '1000000000',
|
|
135
139
|
daiAmount: '1000000000000000000000',
|
|
136
140
|
}).request,
|
|
141
|
+
'continuation-settle': () =>
|
|
142
|
+
buildContinuationSettleExample({ owner: OWNER }).request,
|
|
143
|
+
'continuation-bridge-settle': () =>
|
|
144
|
+
buildContinuationBridgeSettleExample({ owner: OWNER }).request,
|
|
137
145
|
'deposit-proxy': () =>
|
|
138
146
|
buildDepositFromProxy({
|
|
139
147
|
owner: OWNER,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// AUTO-GENERATED from manifest.json — do not edit by hand.
|
|
2
2
|
// Regenerate with: yarn workspace @lifi/composer-sdk generate
|
|
3
3
|
|
|
4
|
+
import type { Flow } from '@lifi/compose-spec';
|
|
5
|
+
|
|
4
6
|
import type { Address, IntegerStringInput } from '../types.js';
|
|
5
7
|
|
|
6
8
|
/**
|
|
@@ -253,7 +255,7 @@ export interface LifiBridgeConfig {
|
|
|
253
255
|
token: Address;
|
|
254
256
|
chainId: Positive;
|
|
255
257
|
};
|
|
256
|
-
destination
|
|
258
|
+
destination?: StartsWith0X;
|
|
257
259
|
slippage?: Between01;
|
|
258
260
|
timing?: {
|
|
259
261
|
swapStepTimingStrategies?: {
|
|
@@ -1278,6 +1280,54 @@ export interface FlySwapConfig {
|
|
|
1278
1280
|
maxSlippageBps?: Between05000;
|
|
1279
1281
|
}
|
|
1280
1282
|
|
|
1283
|
+
/**
|
|
1284
|
+
* a number between -8640000000000000 and 8640000000000000
|
|
1285
|
+
*/
|
|
1286
|
+
export type Between86400000000000008640000000000000 = number;
|
|
1287
|
+
|
|
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
|
+
];
|
|
1318
|
+
continuationFlow?: Flow;
|
|
1319
|
+
validity: {
|
|
1320
|
+
expiresAtMs: Between86400000000000008640000000000000;
|
|
1321
|
+
};
|
|
1322
|
+
perpetual?: boolean;
|
|
1323
|
+
provider?: string;
|
|
1324
|
+
funding?: 'inline' | 'external';
|
|
1325
|
+
/**
|
|
1326
|
+
* EVM address: 0x followed by 40 hex characters
|
|
1327
|
+
*/
|
|
1328
|
+
refund?: Address;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1281
1331
|
export interface UniswapV2AddLiquidityConfig {
|
|
1282
1332
|
/**
|
|
1283
1333
|
* EVM address: 0x followed by 40 hex characters
|
|
@@ -1355,6 +1405,64 @@ export interface UniswapV3IncreaseLiquidityConfig {
|
|
|
1355
1405
|
tokenId: string;
|
|
1356
1406
|
}
|
|
1357
1407
|
|
|
1408
|
+
/**
|
|
1409
|
+
* a number less than 1
|
|
1410
|
+
*/
|
|
1411
|
+
export type LessThan1 = number;
|
|
1412
|
+
/**
|
|
1413
|
+
* a number between 1 and 300
|
|
1414
|
+
*/
|
|
1415
|
+
export type Between1300 = number;
|
|
1416
|
+
/**
|
|
1417
|
+
* a number between 0 and 120
|
|
1418
|
+
*/
|
|
1419
|
+
export type Between0120 = number;
|
|
1420
|
+
|
|
1421
|
+
export interface LifiIntentsOrderConfig {
|
|
1422
|
+
resourceOut:
|
|
1423
|
+
| {
|
|
1424
|
+
kind: 'native';
|
|
1425
|
+
chainId: Positive;
|
|
1426
|
+
}
|
|
1427
|
+
| {
|
|
1428
|
+
kind: 'erc20';
|
|
1429
|
+
/**
|
|
1430
|
+
* EVM address: 0x followed by 40 hex characters
|
|
1431
|
+
*/
|
|
1432
|
+
token: Address;
|
|
1433
|
+
chainId: Positive;
|
|
1434
|
+
};
|
|
1435
|
+
destination?: StartsWith0X;
|
|
1436
|
+
slippage?: LessThan1;
|
|
1437
|
+
validitySeconds?: Between1300;
|
|
1438
|
+
exclusiveSeconds?: Between0120;
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
export interface LifiIntentsRefundConfig {
|
|
1442
|
+
/**
|
|
1443
|
+
* The order id: lifiIntents.order's delivery.trackingId, or topic1 of the escrow's Open log
|
|
1444
|
+
*/
|
|
1445
|
+
orderId: string;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
export interface LifiIntentsAttestNonFillConfig {
|
|
1449
|
+
/**
|
|
1450
|
+
* The order id: lifiIntents.order's delivery.trackingId, or topic1 of the escrow's Open log
|
|
1451
|
+
*/
|
|
1452
|
+
orderId: string;
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
export interface LifiIntentsRefundOnNonFillConfig {
|
|
1456
|
+
/**
|
|
1457
|
+
* The order id: lifiIntents.order's delivery.trackingId, or topic1 of the escrow's Open log
|
|
1458
|
+
*/
|
|
1459
|
+
orderId: string;
|
|
1460
|
+
/**
|
|
1461
|
+
* The output-chain transaction of lifiIntents.attestNonFill
|
|
1462
|
+
*/
|
|
1463
|
+
attestationTxHash: string;
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1358
1466
|
export interface SlippageGuardConfig {
|
|
1359
1467
|
port: string;
|
|
1360
1468
|
bps: Between010000;
|
|
@@ -27,6 +27,7 @@ import type {
|
|
|
27
27
|
AaveRepayConfig,
|
|
28
28
|
AaveRepayWithATokensConfig,
|
|
29
29
|
AaveSetEModeConfig,
|
|
30
|
+
ContinuationSettleConfig,
|
|
30
31
|
CoreApproveConfig,
|
|
31
32
|
CoreAsResourceConfig,
|
|
32
33
|
CoreBalanceOfConfig,
|
|
@@ -54,6 +55,10 @@ import type {
|
|
|
54
55
|
InvariantNumericConfig,
|
|
55
56
|
InvariantNumericInRangeConfig,
|
|
56
57
|
LifiBridgeConfig,
|
|
58
|
+
LifiIntentsAttestNonFillConfig,
|
|
59
|
+
LifiIntentsOrderConfig,
|
|
60
|
+
LifiIntentsRefundConfig,
|
|
61
|
+
LifiIntentsRefundOnNonFillConfig,
|
|
57
62
|
LifiSwapConfig,
|
|
58
63
|
LifiZapAsyncConfig,
|
|
59
64
|
LifiZapConfig,
|
|
@@ -668,6 +673,15 @@ export interface FlySwapArgs {
|
|
|
668
673
|
readonly guards?: readonly TypedGuard<'unspentIn'>[];
|
|
669
674
|
}
|
|
670
675
|
|
|
676
|
+
/** Fund a deferred settlement and commit to a future outcome */
|
|
677
|
+
export interface ContinuationSettleArgs {
|
|
678
|
+
readonly bind: {
|
|
679
|
+
readonly input: Bindable<'resource'>;
|
|
680
|
+
};
|
|
681
|
+
readonly config: ContinuationSettleConfig;
|
|
682
|
+
readonly guards?: readonly TypedGuard<never>[];
|
|
683
|
+
}
|
|
684
|
+
|
|
671
685
|
/** 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. */
|
|
672
686
|
export interface UniswapV2AddLiquidityArgs {
|
|
673
687
|
readonly bind: {
|
|
@@ -715,6 +729,36 @@ export interface UniswapV3IncreaseLiquidityArgs {
|
|
|
715
729
|
>[];
|
|
716
730
|
}
|
|
717
731
|
|
|
732
|
+
/** Swap or bridge tokens through a LI.FI Intents order a solver fills */
|
|
733
|
+
export interface LifiIntentsOrderArgs {
|
|
734
|
+
readonly bind: {
|
|
735
|
+
readonly amountIn: Bindable<'resource'>;
|
|
736
|
+
};
|
|
737
|
+
readonly config: LifiIntentsOrderConfig;
|
|
738
|
+
readonly guards?: readonly TypedGuard<'unspentIn'>[];
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/** Refund a LI.FI Intents escrow order after its expiry. Anyone may call; the escrow pays the order's user. Only an order the order server reports before delivery (status Open or Signed) is refunded. */
|
|
742
|
+
export interface LifiIntentsRefundArgs {
|
|
743
|
+
readonly bind: Record<string, never>;
|
|
744
|
+
readonly config: LifiIntentsRefundConfig;
|
|
745
|
+
readonly guards?: readonly TypedGuard<never>[];
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/** Step 1 of the early refund of a cross-chain LI.FI Intents order: on the order's output chain, after its fill deadline, record that the output was not filled. Keep the transaction hash for lifiIntents.refundOnNonFill. */
|
|
749
|
+
export interface LifiIntentsAttestNonFillArgs {
|
|
750
|
+
readonly bind: Record<string, never>;
|
|
751
|
+
readonly config: LifiIntentsAttestNonFillConfig;
|
|
752
|
+
readonly guards?: readonly TypedGuard<never>[];
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/** Step 2 of the early refund of a cross-chain LI.FI Intents order: on the order's input chain, prove the non-fill attestation through Polymer and refund the order's user. A resolution_error means the proof is not ready yet; retry. */
|
|
756
|
+
export interface LifiIntentsRefundOnNonFillArgs {
|
|
757
|
+
readonly bind: Record<string, never>;
|
|
758
|
+
readonly config: LifiIntentsRefundOnNonFillConfig;
|
|
759
|
+
readonly guards?: readonly TypedGuard<never>[];
|
|
760
|
+
}
|
|
761
|
+
|
|
718
762
|
export interface CoreSplitOutputs {
|
|
719
763
|
readonly a: OutputHandle<'resource'>;
|
|
720
764
|
readonly b: OutputHandle<'resource'>;
|
|
@@ -872,6 +916,10 @@ export interface FlySwapOutputs {
|
|
|
872
916
|
readonly unspentIn: OutputHandle<'resource'>;
|
|
873
917
|
}
|
|
874
918
|
|
|
919
|
+
export interface ContinuationSettleOutputs {
|
|
920
|
+
readonly output: OutputHandle<'resource'>;
|
|
921
|
+
}
|
|
922
|
+
|
|
875
923
|
export interface UniswapV2AddLiquidityOutputs {
|
|
876
924
|
readonly liquidity: OutputHandle<'resource'>;
|
|
877
925
|
readonly residualA: OutputHandle<'resource'>;
|
|
@@ -899,6 +947,11 @@ export interface UniswapV3IncreaseLiquidityOutputs {
|
|
|
899
947
|
readonly residualB: OutputHandle<'resource'>;
|
|
900
948
|
}
|
|
901
949
|
|
|
950
|
+
export interface LifiIntentsOrderOutputs {
|
|
951
|
+
readonly amountOut: OutputHandle<'resource'>;
|
|
952
|
+
readonly unspentIn: OutputHandle<'resource'>;
|
|
953
|
+
}
|
|
954
|
+
|
|
902
955
|
export type GeneratedOps = {
|
|
903
956
|
readonly core: {
|
|
904
957
|
/** 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" */
|
|
@@ -1149,6 +1202,13 @@ export type GeneratedOps = {
|
|
|
1149
1202
|
args: MorphoBlueGetPositionArgs,
|
|
1150
1203
|
) => MorphoBlueGetPositionOutputs;
|
|
1151
1204
|
};
|
|
1205
|
+
readonly continuation: {
|
|
1206
|
+
/** Fund a deferred settlement and commit to a future outcome — original id: "continuation.settle" */
|
|
1207
|
+
readonly settle: (
|
|
1208
|
+
nodeId: string,
|
|
1209
|
+
args: ContinuationSettleArgs,
|
|
1210
|
+
) => ContinuationSettleOutputs;
|
|
1211
|
+
};
|
|
1152
1212
|
readonly paraswap: {
|
|
1153
1213
|
/** Exact-output (BUY) swap via the Paraswap/Velora Market API: produce exactly `exactAmountOut` of the destination token, pulling only the source needed and exposing the genuinely-unspent source as `unspentIn`. — original id: "paraswap.buy" */
|
|
1154
1214
|
readonly buy: (nodeId: string, args: ParaswapBuyArgs) => ParaswapBuyOutputs;
|
|
@@ -1181,6 +1241,25 @@ export type GeneratedOps = {
|
|
|
1181
1241
|
args: UniswapV3IncreaseLiquidityArgs,
|
|
1182
1242
|
) => UniswapV3IncreaseLiquidityOutputs;
|
|
1183
1243
|
};
|
|
1244
|
+
readonly lifiIntents: {
|
|
1245
|
+
/** Swap or bridge tokens through a LI.FI Intents order a solver fills — original id: "lifiIntents.order" */
|
|
1246
|
+
readonly order: (
|
|
1247
|
+
nodeId: string,
|
|
1248
|
+
args: LifiIntentsOrderArgs,
|
|
1249
|
+
) => LifiIntentsOrderOutputs;
|
|
1250
|
+
/** Refund a LI.FI Intents escrow order after its expiry. Anyone may call; the escrow pays the order's user. Only an order the order server reports before delivery (status Open or Signed) is refunded. — original id: "lifiIntents.refund" */
|
|
1251
|
+
readonly refund: (nodeId: string, args: LifiIntentsRefundArgs) => void;
|
|
1252
|
+
/** Step 1 of the early refund of a cross-chain LI.FI Intents order: on the order's output chain, after its fill deadline, record that the output was not filled. Keep the transaction hash for lifiIntents.refundOnNonFill. — original id: "lifiIntents.attestNonFill" */
|
|
1253
|
+
readonly attestNonFill: (
|
|
1254
|
+
nodeId: string,
|
|
1255
|
+
args: LifiIntentsAttestNonFillArgs,
|
|
1256
|
+
) => void;
|
|
1257
|
+
/** Step 2 of the early refund of a cross-chain LI.FI Intents order: on the order's input chain, prove the non-fill attestation through Polymer and refund the order's user. A resolution_error means the proof is not ready yet; retry. — original id: "lifiIntents.refundOnNonFill" */
|
|
1258
|
+
readonly refundOnNonFill: (
|
|
1259
|
+
nodeId: string,
|
|
1260
|
+
args: LifiIntentsRefundOnNonFillArgs,
|
|
1261
|
+
) => void;
|
|
1262
|
+
};
|
|
1184
1263
|
};
|
|
1185
1264
|
|
|
1186
1265
|
export const bindGeneratedOps = (
|
|
@@ -1470,6 +1549,12 @@ export const bindGeneratedOps = (
|
|
|
1470
1549
|
collateral: 'uint128',
|
|
1471
1550
|
} as const),
|
|
1472
1551
|
},
|
|
1552
|
+
continuation: {
|
|
1553
|
+
settle: (nodeId: string, args: ContinuationSettleArgs) =>
|
|
1554
|
+
builder.call(nodeId, 'continuation.settle', args, {
|
|
1555
|
+
output: 'resource',
|
|
1556
|
+
} as const),
|
|
1557
|
+
},
|
|
1473
1558
|
paraswap: {
|
|
1474
1559
|
buy: (nodeId: string, args: ParaswapBuyArgs) =>
|
|
1475
1560
|
builder.call(nodeId, 'paraswap.buy', args, {
|
|
@@ -1515,4 +1600,17 @@ export const bindGeneratedOps = (
|
|
|
1515
1600
|
residualB: 'resource',
|
|
1516
1601
|
} as const),
|
|
1517
1602
|
},
|
|
1603
|
+
lifiIntents: {
|
|
1604
|
+
order: (nodeId: string, args: LifiIntentsOrderArgs) =>
|
|
1605
|
+
builder.call(nodeId, 'lifiIntents.order', args, {
|
|
1606
|
+
amountOut: 'resource',
|
|
1607
|
+
unspentIn: 'resource',
|
|
1608
|
+
} as const),
|
|
1609
|
+
refund: (nodeId: string, args: LifiIntentsRefundArgs) =>
|
|
1610
|
+
builder.call(nodeId, 'lifiIntents.refund', args, {}),
|
|
1611
|
+
attestNonFill: (nodeId: string, args: LifiIntentsAttestNonFillArgs) =>
|
|
1612
|
+
builder.call(nodeId, 'lifiIntents.attestNonFill', args, {}),
|
|
1613
|
+
refundOnNonFill: (nodeId: string, args: LifiIntentsRefundOnNonFillArgs) =>
|
|
1614
|
+
builder.call(nodeId, 'lifiIntents.refundOnNonFill', args, {}),
|
|
1615
|
+
},
|
|
1518
1616
|
});
|
package/src/index.ts
CHANGED
|
@@ -51,6 +51,7 @@ export type {
|
|
|
51
51
|
ComposeFill,
|
|
52
52
|
ComposeFee,
|
|
53
53
|
ComposeUserProgramSimulation,
|
|
54
|
+
ComposeWarning,
|
|
54
55
|
ComposeCompileRequest,
|
|
55
56
|
ComposeCompileResult,
|
|
56
57
|
ComposeCompileSuccessData,
|
|
@@ -83,8 +84,10 @@ export type {
|
|
|
83
84
|
RouteAmountExact,
|
|
84
85
|
SimulationPolicy,
|
|
85
86
|
SimulationRevert,
|
|
87
|
+
DeliveryErrorDetails,
|
|
88
|
+
DeliveryErrorReason,
|
|
86
89
|
SolType,
|
|
87
|
-
|
|
90
|
+
ForwardTo,
|
|
88
91
|
SimulateRequest,
|
|
89
92
|
SimulateResult,
|
|
90
93
|
SimulateOkResult,
|
|
@@ -107,6 +110,7 @@ export {
|
|
|
107
110
|
SIMULATE_MAX_REQUIREMENTS,
|
|
108
111
|
} from '@lifi/compose-spec';
|
|
109
112
|
export {
|
|
113
|
+
isComposeDeliveryError,
|
|
110
114
|
isComposeError,
|
|
111
115
|
isComposePreparationError,
|
|
112
116
|
isComposeSdkOutdatedError,
|
package/src/outputs.ts
CHANGED
|
@@ -2,8 +2,9 @@ import type { Outputs, TerminalOutput } from '@lifi/compose-spec';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The entries of `outputs` the caller actually receives: every port no later
|
|
5
|
-
* node spends, keyed `<nodeId>.<portName>` as on the wire
|
|
6
|
-
*
|
|
5
|
+
* node spends, keyed `<nodeId>.<portName>` as on the wire, and every resource
|
|
6
|
+
* input no node spends, keyed `input.<name>`. Consumed ports (intermediate
|
|
7
|
+
* amounts a later op takes as input) are dropped.
|
|
7
8
|
*/
|
|
8
9
|
export const terminalOutputs = (
|
|
9
10
|
outputs: Outputs,
|
package/src/responseSchemas.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
DeliveryErrorDetails,
|
|
3
|
+
SimulateResult,
|
|
4
|
+
SimulationRevert,
|
|
5
|
+
} from '@lifi/compose-spec';
|
|
2
6
|
import z from 'zod';
|
|
3
7
|
|
|
4
8
|
/**
|
|
@@ -138,7 +142,7 @@ export interface ServerErrorBody {
|
|
|
138
142
|
readonly sdkVersion?: string;
|
|
139
143
|
readonly serverVersion?: string;
|
|
140
144
|
readonly minimumSdkVersion?: string;
|
|
141
|
-
readonly details?: SimulationRevert;
|
|
145
|
+
readonly details?: SimulationRevert | DeliveryErrorDetails;
|
|
142
146
|
readonly failedOps?: readonly ServerFailedPreparedOp[];
|
|
143
147
|
readonly succeededOps?: readonly string[];
|
|
144
148
|
};
|
|
@@ -155,8 +159,8 @@ const failedPreparedOpSchema = z.object({
|
|
|
155
159
|
});
|
|
156
160
|
|
|
157
161
|
// `details` is passed through (`z.custom`) rather than parsed: the SDK does not
|
|
158
|
-
// own the `SimulationRevert`
|
|
159
|
-
// `ComposeError`.
|
|
162
|
+
// own the `SimulationRevert` or `DeliveryErrorDetails` schemas and forwards
|
|
163
|
+
// the field verbatim onto `ComposeError`.
|
|
160
164
|
//
|
|
161
165
|
// `failedOps`/`succeededOps` are optional here because every error kind shares
|
|
162
166
|
// this envelope; they are only populated for `preparation_error` (422). Zod
|
|
@@ -174,7 +178,7 @@ const serverErrorBodySchema = z.object({
|
|
|
174
178
|
sdkVersion: z.string().optional(),
|
|
175
179
|
serverVersion: z.string().optional(),
|
|
176
180
|
minimumSdkVersion: z.string().optional(),
|
|
177
|
-
details: z.custom<SimulationRevert>().optional(),
|
|
181
|
+
details: z.custom<SimulationRevert | DeliveryErrorDetails>().optional(),
|
|
178
182
|
failedOps: z.array(failedPreparedOpSchema).readonly().optional(),
|
|
179
183
|
succeededOps: z.array(z.string()).readonly().optional(),
|
|
180
184
|
})
|
package/src/run/inputs.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
ComposeRun,
|
|
3
|
+
ForwardTo,
|
|
3
4
|
InputSpec,
|
|
4
5
|
MaterialiserInput,
|
|
5
6
|
Precondition,
|
|
6
7
|
SimulationPolicy,
|
|
7
|
-
SweepTo,
|
|
8
8
|
} from '@lifi/compose-spec';
|
|
9
9
|
|
|
10
10
|
import type { Address, InputSchema, InputSpecOf } from '../types.js';
|
|
@@ -47,7 +47,7 @@ export interface ComposeRunInput<T extends InputSchema = InputSchema> {
|
|
|
47
47
|
* Pass a literal `0x`-prefixed address or `{ $ref: "context.sender" }` to
|
|
48
48
|
* send remaining tokens to the signer.
|
|
49
49
|
*/
|
|
50
|
-
readonly sweepTo?:
|
|
50
|
+
readonly sweepTo?: ForwardTo;
|
|
51
51
|
/**
|
|
52
52
|
* Controls behavior when simulation detects a revert.
|
|
53
53
|
* `'strict'` (default) returns an error; `'allow-revert'` returns a partial
|
|
@@ -125,7 +125,7 @@ export const buildRun = (run: {
|
|
|
125
125
|
referrer?: string;
|
|
126
126
|
integratorFeeBps?: number;
|
|
127
127
|
maxPriceImpactBps?: number;
|
|
128
|
-
sweepTo?:
|
|
128
|
+
sweepTo?: ForwardTo;
|
|
129
129
|
simulationPolicy?: SimulationPolicy;
|
|
130
130
|
simulateUserProgram?: boolean;
|
|
131
131
|
checkOnChainAllowances?: boolean;
|