|
| 1 | +# Euler Swap API |
| 2 | + |
| 3 | +API for fetching swap quotes and payloads from multiple DEX aggregators for use with Euler V2. |
| 4 | + |
1 | 5 | # Instalation
|
2 | 6 |
|
3 | 7 | Install npm packages
|
@@ -31,12 +35,115 @@ pnpm run lint # check
|
31 | 35 | pnpm run lint:fix # fix
|
32 | 36 | ```
|
33 | 37 |
|
34 |
| -DOC |
35 |
| -- install/run |
36 |
| -- config |
| 38 | +# Swagger API docs |
| 39 | + |
| 40 | +Swagger UI is served at the root. Request and response schemas are also available [here](./src/api/routes/swap/swapModel.ts) |
| 41 | + |
| 42 | +# Fetching quotes and executing trades |
| 43 | + |
| 44 | +The `/swap` endpoint fetches token trade quotes which can be used with the swapping peripheries in the Euler Vault Kit [periphery contracts](https://github.com/euler-xyz/evk-periphery/tree/master/src/Swaps). See [periphery docs](https://github.com/euler-xyz/evk-periphery/blob/master/docs/swaps.md) for detailed description of the swapping architecture in Euler V2. The API response includes both encoded payloads as well as raw data for calls to the `Swapper` (`swap` field of the response) and `SwapVerifier` (`verify` field) contracts. These payloads can be used directly in EVC batches. |
| 45 | + |
| 46 | +Example of fetching a swap and repay quote to use e.g. in liquidation: |
| 47 | + |
| 48 | +```js |
| 49 | +const collateralVault = EUSDC_ADDRESS |
| 50 | +const liabilityVault = EWETH_ADDRESS |
| 51 | + |
| 52 | +const currentDebtAmount = parseUnits('100', 6).toString() |
| 53 | + |
| 54 | +// Fetch a quote to repay WETH liability by selling USDC from the collateral vault. |
| 55 | +// Use target debt mode, which will attempt to buy exactly enough of the liability asset |
| 56 | +// to repay the debt down to `targetDebt` amount. The target here is 0, meaning all |
| 57 | +// of the debt should be repaid. |
| 58 | + |
| 59 | +const queryParams = { |
| 60 | + chainId: "1", |
| 61 | + tokenIn: USDC_ADDRESS, |
| 62 | + tokenOut: WETH_ADDRESS, |
| 63 | + amount: currentDebtAmount, |
| 64 | + targetDebt: "0", |
| 65 | + currentDebt: currentDebtAmount, |
| 66 | + receiver: liabilityVault, |
| 67 | + vaultIn: collateralVault, |
| 68 | + origin: connectedAccount, |
| 69 | + accountIn: connectedAccount, |
| 70 | + accountOut: connectedAccount, |
| 71 | + slippage: "0.1", // 0.1% |
| 72 | + deadline: String(Date.now() / 1000 + 10 * 60), // 10 minutes from now |
| 73 | + swapperMode: "2", // target debt mode |
| 74 | + isRepay: "true", |
| 75 | +} |
37 | 76 |
|
38 |
| -- quoters |
39 |
| -- strategies |
40 |
| -- pipeline |
41 |
| -- routing override |
| 77 | +const { data: response } = await axios.get( |
| 78 | + `${SWAP_API_URL}/swap`, |
| 79 | + { |
| 80 | + params: requstParams, |
| 81 | + }, |
| 82 | +) |
42 | 83 |
|
| 84 | +// Encode EVC batch |
| 85 | +const batchItems = |
| 86 | + // Withdraw collateral to the Swapper contract |
| 87 | + { |
| 88 | + targetContract: collateralVault, |
| 89 | + onBehalfOfAccount: connectedAccount, |
| 90 | + value: 0, |
| 91 | + data: encodeFunctionData({ |
| 92 | + abi: EVAULT_ABI, |
| 93 | + functionName: "withdraw" |
| 94 | + args: [response.data.amountInMax, response.data.swap.swapperAddress, connectedAccount] |
| 95 | + } |
| 96 | + }, |
| 97 | + // execute Swapper payload from the API response |
| 98 | + { |
| 99 | + targetContract: response.data.swap.swapperAddress, |
| 100 | + onBehalfOfAccount: connectedAccount, |
| 101 | + value: 0, |
| 102 | + data: response.data.swap.swapperData |
| 103 | + }, |
| 104 | + // execut SwapVerifier payload from the API response |
| 105 | + { |
| 106 | + targetContract: response.data.verify.verifierAddress, |
| 107 | + onBehalfOfAccount: connectedAccount, |
| 108 | + value: 0, |
| 109 | + data: response.data.verify.verifierData |
| 110 | + }, |
| 111 | +)) |
| 112 | + |
| 113 | +const evcBatch = encodeFunctionData({ |
| 114 | + abi: EVC_ABI, |
| 115 | + functionName: "batch", |
| 116 | + args: [batchItems] |
| 117 | +}) |
| 118 | + |
| 119 | +// send tx |
| 120 | + |
| 121 | +``` |
| 122 | +
|
| 123 | +# Configuration |
| 124 | +
|
| 125 | +To handle an incoming swap request, the API processes the query through a series of strategies until one of them provides a valid response. The strategy pipelines are defined per chain in `/swapService/config` folder. The strategies can handle requests in multiple ways. The basic one is the balmy SDK strategy, which queries multiple DEXes and aggregators for a swap quote and picks the best one. Strategies can themselves run the pipelines recursively. ERC4626 wrapper can be configured for assets which are vault shares and are not supported by aggregators. The strategy will deposit or redeem vault shares and run the pipeline again, this time using the underlying asset of the vault. For a list of available strategies see `swapService/strategies` folder. |
| 126 | +
|
| 127 | +The pipeline definition consits of an array of objects, selecting a strategy with it's configuration, and optional matching logic. In the following example, the pipeline is configured to query Pendle and LI.FI for swap of the Pendle PT tokens, and 1Inch and LI.FI for all other tokens. |
| 128 | +
|
| 129 | +```js |
| 130 | +const pipeline = [ |
| 131 | + { |
| 132 | + strategy: StrategyBalmySDK.name(), |
| 133 | + config: { |
| 134 | + sourcesFilter: { |
| 135 | + includeSources: ["pendle", "li-fi"], |
| 136 | + }, |
| 137 | + }, |
| 138 | + match: { isPendlePT: true }, |
| 139 | + }, |
| 140 | + { |
| 141 | + strategy: StrategyBalmySDK.name(), |
| 142 | + config: { |
| 143 | + sourcesFilter: { |
| 144 | + includeSources: ["1inch", "li-fi"], |
| 145 | + }, |
| 146 | + }, |
| 147 | + }, |
| 148 | +] |
| 149 | +``` |
0 commit comments