-
Notifications
You must be signed in to change notification settings - Fork 70
Enso integration #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Brenzee
wants to merge
19
commits into
RealWagmi:main
Choose a base branch
from
EnsoBuild:feature/enso
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Enso integration #41
Changes from 9 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
bd56d6b
create Enso project, add getProtocols and getTokens functions
Brenzee 425302e
remove script lines
Brenzee 58b5eec
feature: implement route function
Brenzee 80a60dd
route - changes to props
Brenzee dd58f42
add getToken and getProtocol, improve parameter validaton in route
Brenzee 8c5ddc8
Update README
Brenzee 074c340
Add links to Enso documentation, update common tasks
Brenzee 5be6ab7
add Enso SDK, replace API calls with SDK
Brenzee 30207eb
update Basic Operations
Brenzee 5b2423c
update common tasks/operation examples
Brenzee 2041ff7
update basic operations
Brenzee 9f000af
use NATIVE_ADDRESS for ETH
Brenzee ed9efc8
remove required parameter checks
Brenzee 6b20d2e
parse amountIn and amountOut from decimal values to wei
Brenzee 8fa8d57
update slippage, tokenIn, tokenOut descriptions
Brenzee 8fec7ed
more descriptive function names
Brenzee 723c8e5
route - improve notify and toResult messages
Brenzee 9db8e85
Merge branch 'RealWagmi:main' into feature/enso
Brenzee ae4a3bd
Add quote and getTokenOut functions, bump Enso SDK version
Brenzee File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| node_modules |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "singleQuote": true, | ||
| "trailingComma": "all", | ||
| "tabWidth": 4, | ||
| "printWidth": 180 | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| # Enso | ||
|
|
||
| Enso | ||
|
|
||
| ## Supported Networks | ||
|
|
||
| - ETHEREUM | ||
| - OPTIMISM | ||
| - BSC | ||
| - GNOSIS | ||
| - POLYGON | ||
| - ZKSYNC | ||
| - BASE | ||
| - ARBITRUM | ||
| - AVALANCHE | ||
| - SEPOLIA | ||
|
|
||
| ## Common Tasks | ||
|
|
||
| 1. Basic Operations | ||
|
|
||
| - "Swap 15000 USDT to WETH on @enso on Optimism network" | ||
| - "Redeem 0.01 WETH-USDT UNI-V2 LP token for WBTC on @enso on Ethereum network" | ||
| - "Deposit 10 ETH into a Curve pool on @enso" | ||
| - "Withdraw aEthWBTC from Aave V3 for USDC on @enso" | ||
|
|
||
| 2. Information Queries | ||
|
|
||
| - "Show me supported tokens on @enso" | ||
| - "Is USDC supported on @enso on Base network" | ||
| - "Show me supported protocols on @enso on Etheruem network" | ||
| - "Is Uniswap supported on @enso on Ethereum network" | ||
|
|
||
| ## Available Functions | ||
|
|
||
| ### Actions | ||
|
|
||
| - route | ||
|
|
||
| ### Getters | ||
|
|
||
| - getProtocol | ||
| - getProtocols | ||
| - getToken | ||
| - getTokens | ||
|
|
||
| ## Documentation | ||
|
|
||
| - [Router API reference](https://api-docs.enso.build/router-api/introduction) | ||
| - [Tokens API reference](https://api-docs.enso.build/metadata-api/api-reference/tokens) | ||
| - [Protocols API reference](https://api-docs.enso.build/metadata-api/api-reference/protocols) | ||
|
|
||
| ## Installation | ||
|
|
||
| ```bash | ||
| yarn add @heyanon/enso | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| Example usage will be added here. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import { ChainId } from '@heyanon/sdk'; | ||
|
|
||
| export const supportedChains = [ | ||
| ChainId.ETHEREUM, | ||
| ChainId.OPTIMISM, | ||
| ChainId.BSC, | ||
| ChainId.GNOSIS, | ||
| ChainId.POLYGON, | ||
| ChainId.ZKSYNC, | ||
| ChainId.BASE, | ||
| ChainId.ARBITRUM, | ||
| ChainId.AVALANCHE, | ||
| ChainId.SEPOLIA, | ||
| ]; | ||
|
|
||
| export const ENSO_API = 'https://api.enso.finance/api/v1' as const; | ||
| export const ENSO_API_TOKEN = '1e02632d-6feb-4a75-a157-documentation' as const; | ||
|
|
||
| export const ENSO_ETH = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' as const; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| import { FunctionReturn, toResult, getChainFromName } from '@heyanon/sdk'; | ||
| import { ENSO_API_TOKEN, supportedChains } from '../constants'; | ||
| import axios from 'axios'; | ||
| import { EnsoApiProtocol } from './getProtocols'; | ||
| import { EnsoClient } from '@ensofinance/sdk'; | ||
|
|
||
| interface Props { | ||
| chainName: string; | ||
| protocol: string; | ||
| } | ||
|
|
||
| /** | ||
| * Search for a protocol by its slug on specified chain | ||
| * @param props - The function parameters | ||
| * @returns Protocol | ||
| */ | ||
| export async function getProtocol({ chainName, protocol }: Props): Promise<FunctionReturn> { | ||
| const chainId = getChainFromName(chainName); | ||
| if (!chainId) return toResult(`Unsupported chain name: ${chainName}`, true); | ||
| if (!protocol) return toResult(`No protocol provided`, true); | ||
| if (!supportedChains.includes(chainId)) return toResult(`Enso is not supported on ${chainName}`, true); | ||
|
|
||
| try { | ||
| const ensoClient = new EnsoClient({ | ||
| apiKey: ENSO_API_TOKEN, | ||
| }); | ||
| const protocolData = await ensoClient.getProtocolData({ slug: protocol }); | ||
|
|
||
| if (protocolData.length == 0) { | ||
| return toResult(`Protocol ${protocol} not found`, true); | ||
| } | ||
|
|
||
| const isChainSupported = protocolData[0].chains.some((chain) => chain.id === chainId); | ||
| if (!isChainSupported) return toResult(`Protocol ${protocol} is not supported on ${chainName}`, true); | ||
|
|
||
| delete (protocolData[0] as Partial<EnsoApiProtocol>).chains; | ||
| return toResult(JSON.stringify(protocolData)); | ||
| } catch (e) { | ||
| if (axios.isAxiosError(e)) { | ||
| return toResult(`API error: ${e.message}`, true); | ||
| } | ||
| return toResult(`Unknown error when fetching protocol from Enso API`, true); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| import { FunctionReturn, toResult, getChainFromName } from '@heyanon/sdk'; | ||
| import { ENSO_API_TOKEN, supportedChains } from '../constants'; | ||
| import axios from 'axios'; | ||
| import { EnsoClient } from '@ensofinance/sdk'; | ||
|
|
||
| interface Props { | ||
| chainName: string; | ||
| } | ||
|
|
||
| export interface EnsoApiProtocol { | ||
| chains: { name: string; id: number }[]; | ||
| name: string | null; | ||
| description: string | null; | ||
| slug: string; | ||
| url: string; | ||
| logosUri: string[]; | ||
| } | ||
|
|
||
| /** | ||
| * Get protocols that are supported by Enso on specified chain | ||
| * @param props - The function parameters | ||
| * @returns List of protocol slugs | ||
| */ | ||
| export async function getProtocols({ chainName }: Props): Promise<FunctionReturn> { | ||
| const chainId = getChainFromName(chainName); | ||
| if (!chainId) return toResult(`Unsupported chain name: ${chainName}`, true); | ||
| if (!supportedChains.includes(chainId)) return toResult(`Enso is not supported on ${chainName}`, true); | ||
|
|
||
| try { | ||
| const ensoClient = new EnsoClient({ apiKey: ENSO_API_TOKEN }); | ||
| const protocolData = await ensoClient.getProtocolData(); | ||
|
|
||
| const protocols: string[] = []; | ||
| for (const protocol of protocolData) { | ||
| const hasChain = protocol.chains.some((chain) => chain.id === chainId); | ||
| if (hasChain) { | ||
| protocols.push(protocol.slug); | ||
| } | ||
| } | ||
|
|
||
| return toResult(JSON.stringify(protocols)); | ||
| } catch (e) { | ||
| if (axios.isAxiosError(e)) { | ||
| return toResult(`API error: ${e.message}`, true); | ||
| } | ||
| return toResult(`Unknown error when fetching protocols from Enso API`, true); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| import { FunctionReturn, toResult, getChainFromName } from '@heyanon/sdk'; | ||
| import { ENSO_API_TOKEN, supportedChains } from '../constants'; | ||
| import axios from 'axios'; | ||
| import { Address } from 'viem'; | ||
| import { EnsoClient } from '@ensofinance/sdk'; | ||
|
|
||
| interface Props { | ||
| chainName: string; | ||
| address: Address; | ||
| } | ||
|
|
||
| /** | ||
| * Search for a token by its address | ||
| * @param props - The function parameters | ||
| * @returns Token | ||
| */ | ||
| export async function getToken({ chainName, address }: Props): Promise<FunctionReturn> { | ||
Brenzee marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const chainId = getChainFromName(chainName); | ||
| if (!chainId) return toResult(`Unsupported chain name: ${chainName}`, true); | ||
| if (!address) return toResult('Token address not provided', true); | ||
| if (!supportedChains.includes(chainId)) return toResult(`Enso is not supported on ${chainName}`, true); | ||
|
|
||
| try { | ||
| const ensoClient = new EnsoClient({ apiKey: ENSO_API_TOKEN }); | ||
| const tokenData = await ensoClient.getTokenData({ chainId, address }); | ||
|
|
||
| if (tokenData.data.length === 0) { | ||
| return toResult('Token not found', true); | ||
| } | ||
|
|
||
| return toResult(JSON.stringify(tokenData.data[0])); | ||
| } catch (e) { | ||
| if (axios.isAxiosError(e)) { | ||
| return toResult(`API error: ${e.message}`, true); | ||
| } | ||
| return toResult(`Unknown error when fetching token from Enso API`, true); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import { FunctionReturn, toResult, getChainFromName } from '@heyanon/sdk'; | ||
| import { ENSO_API, ENSO_API_TOKEN, supportedChains } from '../constants'; | ||
| import axios from 'axios'; | ||
|
|
||
| interface Props { | ||
| chainName: string; | ||
| } | ||
|
|
||
| export interface EnsoApiToken { | ||
| chainId: number; | ||
| address: string; | ||
| decimals: number; | ||
| type: string; | ||
| } | ||
|
|
||
| // NOTE: Not sure if this should be kept or getToken is enough | ||
| // This method in Enso SDK is not supported | ||
| /** | ||
| * Get tokens that are supported by Enso on specified chain | ||
| * @param props - The function parameters | ||
| * @returns List of protocols | ||
| */ | ||
| export async function getTokens({ chainName }: Props): Promise<FunctionReturn> { | ||
| const chainId = getChainFromName(chainName); | ||
| if (!chainId) return toResult(`Unsupported chain name: ${chainName}`, true); | ||
| if (!supportedChains.includes(chainId)) return toResult(`Enso is not supported on ${chainName}`, true); | ||
|
|
||
| try { | ||
| const url = `${ENSO_API}/tokens?chainId=${chainId}&page=1`; | ||
| const res = await axios.get<{ data: EnsoApiToken[] }>(url, { headers: { Authorization: `Bearer ${ENSO_API_TOKEN}` } }); | ||
|
|
||
| // NOTE: Not sure if only address should be returned or address+symbol/address+name | ||
| // as well. Maybe it is benefitial for the LLM to have name/symbol as well | ||
| const tokens = res.data.data.map((token) => { | ||
| return token.address; | ||
| }); | ||
|
|
||
| return toResult(JSON.stringify(tokens)); | ||
| } catch (e) { | ||
| if (axios.isAxiosError(e)) { | ||
| return toResult(`API error: ${e.message}`, true); | ||
| } | ||
| return toResult(`Unknown error when fetching tokens from Enso API`, true); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| export { getProtocols } from './getProtocols'; | ||
| export { getProtocol } from './getProtocol'; | ||
| export { getTokens } from './getTokens'; | ||
| export { getToken } from './getToken'; | ||
| export { route } from './route'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| import { FunctionReturn, toResult, getChainFromName, FunctionOptions, TransactionParams, checkToApprove } from '@heyanon/sdk'; | ||
| import { ENSO_API_TOKEN, ENSO_ETH, supportedChains } from '../constants'; | ||
| import axios from 'axios'; | ||
| import { Address, Hex, isAddress } from 'viem'; | ||
| import { EnsoClient, RouteParams } from '@ensofinance/sdk'; | ||
|
|
||
| interface Props { | ||
| chainName: string; | ||
| account: Address; | ||
| tokenIn: Address; | ||
| tokenOut: Address; | ||
| amountIn: string; | ||
| amountOut?: string; | ||
| receiver?: Address; | ||
| spender?: Address; | ||
| slippage?: number; | ||
| fee?: number; | ||
| feeReceiver?: Address; | ||
| } | ||
|
|
||
| /** | ||
| * Best route from a token to a token | ||
| * @param props - The function parameters | ||
| */ | ||
| export async function route( | ||
| { chainName, tokenIn, tokenOut, amountIn, spender, receiver, slippage, amountOut, account, fee, feeReceiver }: Props, | ||
| { sendTransactions, notify, getProvider }: FunctionOptions, | ||
| ): Promise<FunctionReturn> { | ||
| if (!account) return toResult('No account provided', true); | ||
| if (!tokenIn) return toResult('No tokenIn provided', true); | ||
| if (!tokenOut) return toResult('No tokenOut provided', true); | ||
| if (!amountIn) return toResult('No amountIn provided', true); | ||
Brenzee marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| const chainId = getChainFromName(chainName); | ||
| if (!chainId) return toResult(`Unsupported chain name: ${chainName}`, true); | ||
| if (!supportedChains.includes(chainId)) return toResult(`Enso is not supported on ${chainName}`, true); | ||
|
|
||
| const params: RouteParams = { | ||
| chainId, | ||
| tokenIn, | ||
| tokenOut, | ||
| amountIn, | ||
| fromAddress: account, | ||
| receiver: receiver || account, | ||
| spender: spender || account, | ||
| }; | ||
|
|
||
| if (!isAddress(params.receiver)) { | ||
| return toResult('Receiver is not an address', true); | ||
| } | ||
| if (!isAddress(params.spender)) { | ||
| return toResult('Spender is not an address', true); | ||
| } | ||
|
|
||
| if (amountOut) { | ||
| params.minAmountOut = amountOut; | ||
| } | ||
| if (slippage) { | ||
| if (slippage > 10_000 || slippage < 0) { | ||
| return toResult('Slippage is outside of 0-10000 range', true); | ||
| } | ||
| params.slippage = slippage; | ||
| } | ||
| if (fee) { | ||
| if (fee > 100 || fee < 0) { | ||
| return toResult('Fee is outside of 0-100 range', true); | ||
| } | ||
| params.fee = fee; | ||
| } | ||
| if (feeReceiver) { | ||
| if (!isAddress(feeReceiver)) { | ||
| return toResult('Fee receiver is not an address', true); | ||
| } | ||
| params.feeReceiver = feeReceiver; | ||
| } | ||
|
|
||
| try { | ||
| const ensoClient = new EnsoClient({ apiKey: ENSO_API_TOKEN }); | ||
| await notify('Fetching the best route from Enso API'); | ||
| const routeData = await ensoClient.getRouterData(params); | ||
|
|
||
| const provider = getProvider(chainId); | ||
| const transactions: TransactionParams[] = []; | ||
|
|
||
| if (tokenIn !== ENSO_ETH) { | ||
| await checkToApprove({ | ||
| args: { | ||
| account, | ||
| target: tokenIn, | ||
| spender: routeData.tx.to, | ||
| amount: BigInt(amountIn), | ||
| }, | ||
Brenzee marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| provider, | ||
| transactions, | ||
| }); | ||
| } | ||
|
|
||
| const tx: TransactionParams = { target: routeData.tx.to, data: routeData.tx.data as Hex, value: BigInt(routeData.tx.value) }; | ||
| transactions.push(tx); | ||
|
|
||
| const result = await sendTransactions({ chainId, account, transactions }); | ||
| const depositMessage = result.data[result.data.length - 1]; | ||
|
|
||
| return toResult(result.isMultisig ? depositMessage.message : `Successfully executed route. ${depositMessage.message}`); | ||
| } catch (e) { | ||
Brenzee marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (axios.isAxiosError(e)) { | ||
| return toResult(`API error: ${e.message}`, true); | ||
| } | ||
| return toResult(`Unknown error when fetching route from Enso API`, true); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| import { AdapterExport } from '@heyanon/sdk'; | ||
| import { tools } from './tools'; | ||
| import * as functions from './functions'; | ||
|
|
||
| export default { | ||
| tools, | ||
| functions, | ||
| description: 'Enso', | ||
| } satisfies AdapterExport; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.