intentkit 0.5.0__py3-none-any.whl → 0.5.2__py3-none-any.whl
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.
Potentially problematic release.
This version of intentkit might be problematic. Click here for more details.
- intentkit/__init__.py +17 -0
- intentkit/abstracts/__init__.py +0 -0
- intentkit/abstracts/agent.py +60 -0
- intentkit/abstracts/api.py +4 -0
- intentkit/abstracts/engine.py +38 -0
- intentkit/abstracts/exception.py +9 -0
- intentkit/abstracts/graph.py +25 -0
- intentkit/abstracts/skill.py +129 -0
- intentkit/abstracts/twitter.py +54 -0
- intentkit/clients/__init__.py +14 -0
- intentkit/clients/cdp.py +53 -0
- intentkit/clients/twitter.py +445 -0
- intentkit/config/__init__.py +0 -0
- intentkit/config/config.py +164 -0
- intentkit/core/__init__.py +0 -0
- intentkit/core/agent.py +191 -0
- intentkit/core/api.py +40 -0
- intentkit/core/client.py +45 -0
- intentkit/core/credit.py +1767 -0
- intentkit/core/engine.py +1018 -0
- intentkit/core/node.py +223 -0
- intentkit/core/prompt.py +58 -0
- intentkit/core/skill.py +124 -0
- intentkit/models/agent.py +1689 -0
- intentkit/models/agent_data.py +810 -0
- intentkit/models/agent_schema.json +733 -0
- intentkit/models/app_setting.py +156 -0
- intentkit/models/base.py +9 -0
- intentkit/models/chat.py +581 -0
- intentkit/models/conversation.py +286 -0
- intentkit/models/credit.py +1406 -0
- intentkit/models/db.py +120 -0
- intentkit/models/db_mig.py +102 -0
- intentkit/models/generator.py +347 -0
- intentkit/models/llm.py +746 -0
- intentkit/models/redis.py +132 -0
- intentkit/models/skill.py +466 -0
- intentkit/models/user.py +243 -0
- intentkit/skills/__init__.py +12 -0
- intentkit/skills/acolyt/__init__.py +83 -0
- intentkit/skills/acolyt/acolyt.jpg +0 -0
- intentkit/skills/acolyt/ask.py +128 -0
- intentkit/skills/acolyt/base.py +28 -0
- intentkit/skills/acolyt/schema.json +89 -0
- intentkit/skills/aixbt/README.md +71 -0
- intentkit/skills/aixbt/__init__.py +73 -0
- intentkit/skills/aixbt/aixbt.jpg +0 -0
- intentkit/skills/aixbt/base.py +21 -0
- intentkit/skills/aixbt/projects.py +153 -0
- intentkit/skills/aixbt/schema.json +99 -0
- intentkit/skills/allora/__init__.py +83 -0
- intentkit/skills/allora/allora.jpeg +0 -0
- intentkit/skills/allora/base.py +28 -0
- intentkit/skills/allora/price.py +130 -0
- intentkit/skills/allora/schema.json +89 -0
- intentkit/skills/base.py +174 -0
- intentkit/skills/carv/README.md +95 -0
- intentkit/skills/carv/__init__.py +121 -0
- intentkit/skills/carv/base.py +183 -0
- intentkit/skills/carv/carv.webp +0 -0
- intentkit/skills/carv/fetch_news.py +92 -0
- intentkit/skills/carv/onchain_query.py +164 -0
- intentkit/skills/carv/schema.json +137 -0
- intentkit/skills/carv/token_info_and_price.py +110 -0
- intentkit/skills/cdp/__init__.py +137 -0
- intentkit/skills/cdp/base.py +21 -0
- intentkit/skills/cdp/cdp.png +0 -0
- intentkit/skills/cdp/get_balance.py +81 -0
- intentkit/skills/cdp/schema.json +473 -0
- intentkit/skills/chainlist/README.md +38 -0
- intentkit/skills/chainlist/__init__.py +54 -0
- intentkit/skills/chainlist/base.py +21 -0
- intentkit/skills/chainlist/chain_lookup.py +208 -0
- intentkit/skills/chainlist/chainlist.png +0 -0
- intentkit/skills/chainlist/schema.json +47 -0
- intentkit/skills/common/__init__.py +82 -0
- intentkit/skills/common/base.py +21 -0
- intentkit/skills/common/common.jpg +0 -0
- intentkit/skills/common/current_time.py +84 -0
- intentkit/skills/common/schema.json +57 -0
- intentkit/skills/cookiefun/README.md +121 -0
- intentkit/skills/cookiefun/__init__.py +78 -0
- intentkit/skills/cookiefun/base.py +41 -0
- intentkit/skills/cookiefun/constants.py +18 -0
- intentkit/skills/cookiefun/cookiefun.png +0 -0
- intentkit/skills/cookiefun/get_account_details.py +171 -0
- intentkit/skills/cookiefun/get_account_feed.py +282 -0
- intentkit/skills/cookiefun/get_account_smart_followers.py +181 -0
- intentkit/skills/cookiefun/get_sectors.py +128 -0
- intentkit/skills/cookiefun/schema.json +155 -0
- intentkit/skills/cookiefun/search_accounts.py +225 -0
- intentkit/skills/cryptocompare/__init__.py +130 -0
- intentkit/skills/cryptocompare/api.py +159 -0
- intentkit/skills/cryptocompare/base.py +303 -0
- intentkit/skills/cryptocompare/cryptocompare.png +0 -0
- intentkit/skills/cryptocompare/fetch_news.py +96 -0
- intentkit/skills/cryptocompare/fetch_price.py +99 -0
- intentkit/skills/cryptocompare/fetch_top_exchanges.py +113 -0
- intentkit/skills/cryptocompare/fetch_top_market_cap.py +109 -0
- intentkit/skills/cryptocompare/fetch_top_volume.py +108 -0
- intentkit/skills/cryptocompare/fetch_trading_signals.py +107 -0
- intentkit/skills/cryptocompare/schema.json +168 -0
- intentkit/skills/cryptopanic/__init__.py +108 -0
- intentkit/skills/cryptopanic/base.py +51 -0
- intentkit/skills/cryptopanic/cryptopanic.png +0 -0
- intentkit/skills/cryptopanic/fetch_crypto_news.py +153 -0
- intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +136 -0
- intentkit/skills/cryptopanic/schema.json +103 -0
- intentkit/skills/dapplooker/README.md +92 -0
- intentkit/skills/dapplooker/__init__.py +83 -0
- intentkit/skills/dapplooker/base.py +26 -0
- intentkit/skills/dapplooker/dapplooker.jpg +0 -0
- intentkit/skills/dapplooker/dapplooker_token_data.py +476 -0
- intentkit/skills/dapplooker/schema.json +91 -0
- intentkit/skills/defillama/__init__.py +323 -0
- intentkit/skills/defillama/api.py +315 -0
- intentkit/skills/defillama/base.py +135 -0
- intentkit/skills/defillama/coins/__init__.py +0 -0
- intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +116 -0
- intentkit/skills/defillama/coins/fetch_block.py +98 -0
- intentkit/skills/defillama/coins/fetch_current_prices.py +105 -0
- intentkit/skills/defillama/coins/fetch_first_price.py +100 -0
- intentkit/skills/defillama/coins/fetch_historical_prices.py +110 -0
- intentkit/skills/defillama/coins/fetch_price_chart.py +109 -0
- intentkit/skills/defillama/coins/fetch_price_percentage.py +93 -0
- intentkit/skills/defillama/config/__init__.py +0 -0
- intentkit/skills/defillama/config/chains.py +433 -0
- intentkit/skills/defillama/defillama.jpeg +0 -0
- intentkit/skills/defillama/fees/__init__.py +0 -0
- intentkit/skills/defillama/fees/fetch_fees_overview.py +130 -0
- intentkit/skills/defillama/schema.json +383 -0
- intentkit/skills/defillama/stablecoins/__init__.py +0 -0
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +100 -0
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +129 -0
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +83 -0
- intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +126 -0
- intentkit/skills/defillama/tests/__init__.py +0 -0
- intentkit/skills/defillama/tests/api_integration.test.py +192 -0
- intentkit/skills/defillama/tests/api_unit.test.py +583 -0
- intentkit/skills/defillama/tvl/__init__.py +0 -0
- intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +106 -0
- intentkit/skills/defillama/tvl/fetch_chains.py +107 -0
- intentkit/skills/defillama/tvl/fetch_historical_tvl.py +91 -0
- intentkit/skills/defillama/tvl/fetch_protocol.py +207 -0
- intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +93 -0
- intentkit/skills/defillama/tvl/fetch_protocols.py +196 -0
- intentkit/skills/defillama/volumes/__init__.py +0 -0
- intentkit/skills/defillama/volumes/fetch_dex_overview.py +157 -0
- intentkit/skills/defillama/volumes/fetch_dex_summary.py +123 -0
- intentkit/skills/defillama/volumes/fetch_options_overview.py +131 -0
- intentkit/skills/defillama/yields/__init__.py +0 -0
- intentkit/skills/defillama/yields/fetch_pool_chart.py +100 -0
- intentkit/skills/defillama/yields/fetch_pools.py +126 -0
- intentkit/skills/dexscreener/__init__.py +93 -0
- intentkit/skills/dexscreener/base.py +133 -0
- intentkit/skills/dexscreener/dexscreener.png +0 -0
- intentkit/skills/dexscreener/model/__init__.py +0 -0
- intentkit/skills/dexscreener/model/search_token_response.py +82 -0
- intentkit/skills/dexscreener/schema.json +48 -0
- intentkit/skills/dexscreener/search_token.py +321 -0
- intentkit/skills/dune_analytics/__init__.py +103 -0
- intentkit/skills/dune_analytics/base.py +46 -0
- intentkit/skills/dune_analytics/dune.png +0 -0
- intentkit/skills/dune_analytics/fetch_kol_buys.py +128 -0
- intentkit/skills/dune_analytics/fetch_nation_metrics.py +237 -0
- intentkit/skills/dune_analytics/schema.json +99 -0
- intentkit/skills/elfa/README.md +100 -0
- intentkit/skills/elfa/__init__.py +123 -0
- intentkit/skills/elfa/base.py +28 -0
- intentkit/skills/elfa/elfa.jpg +0 -0
- intentkit/skills/elfa/mention.py +504 -0
- intentkit/skills/elfa/schema.json +153 -0
- intentkit/skills/elfa/stats.py +118 -0
- intentkit/skills/elfa/tokens.py +126 -0
- intentkit/skills/enso/README.md +75 -0
- intentkit/skills/enso/__init__.py +114 -0
- intentkit/skills/enso/abi/__init__.py +0 -0
- intentkit/skills/enso/abi/approval.py +279 -0
- intentkit/skills/enso/abi/erc20.py +14 -0
- intentkit/skills/enso/abi/route.py +129 -0
- intentkit/skills/enso/base.py +44 -0
- intentkit/skills/enso/best_yield.py +286 -0
- intentkit/skills/enso/enso.jpg +0 -0
- intentkit/skills/enso/networks.py +105 -0
- intentkit/skills/enso/prices.py +93 -0
- intentkit/skills/enso/route.py +300 -0
- intentkit/skills/enso/schema.json +212 -0
- intentkit/skills/enso/tokens.py +223 -0
- intentkit/skills/enso/wallet.py +381 -0
- intentkit/skills/github/README.md +63 -0
- intentkit/skills/github/__init__.py +54 -0
- intentkit/skills/github/base.py +21 -0
- intentkit/skills/github/github.jpg +0 -0
- intentkit/skills/github/github_search.py +183 -0
- intentkit/skills/github/schema.json +59 -0
- intentkit/skills/heurist/__init__.py +143 -0
- intentkit/skills/heurist/base.py +26 -0
- intentkit/skills/heurist/heurist.png +0 -0
- intentkit/skills/heurist/image_generation_animagine_xl.py +162 -0
- intentkit/skills/heurist/image_generation_arthemy_comics.py +162 -0
- intentkit/skills/heurist/image_generation_arthemy_real.py +162 -0
- intentkit/skills/heurist/image_generation_braindance.py +162 -0
- intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +162 -0
- intentkit/skills/heurist/image_generation_flux_1_dev.py +162 -0
- intentkit/skills/heurist/image_generation_sdxl.py +161 -0
- intentkit/skills/heurist/schema.json +196 -0
- intentkit/skills/lifi/README.md +294 -0
- intentkit/skills/lifi/__init__.py +141 -0
- intentkit/skills/lifi/base.py +21 -0
- intentkit/skills/lifi/lifi.png +0 -0
- intentkit/skills/lifi/schema.json +89 -0
- intentkit/skills/lifi/token_execute.py +472 -0
- intentkit/skills/lifi/token_quote.py +190 -0
- intentkit/skills/lifi/utils.py +656 -0
- intentkit/skills/moralis/README.md +490 -0
- intentkit/skills/moralis/__init__.py +110 -0
- intentkit/skills/moralis/api.py +281 -0
- intentkit/skills/moralis/base.py +55 -0
- intentkit/skills/moralis/fetch_chain_portfolio.py +191 -0
- intentkit/skills/moralis/fetch_nft_portfolio.py +284 -0
- intentkit/skills/moralis/fetch_solana_portfolio.py +331 -0
- intentkit/skills/moralis/fetch_wallet_portfolio.py +301 -0
- intentkit/skills/moralis/moralis.png +0 -0
- intentkit/skills/moralis/schema.json +156 -0
- intentkit/skills/moralis/tests/__init__.py +0 -0
- intentkit/skills/moralis/tests/test_wallet.py +511 -0
- intentkit/skills/nation/__init__.py +62 -0
- intentkit/skills/nation/base.py +31 -0
- intentkit/skills/nation/nation.png +0 -0
- intentkit/skills/nation/nft_check.py +106 -0
- intentkit/skills/nation/schema.json +58 -0
- intentkit/skills/openai/__init__.py +107 -0
- intentkit/skills/openai/base.py +32 -0
- intentkit/skills/openai/dalle_image_generation.py +128 -0
- intentkit/skills/openai/gpt_image_generation.py +152 -0
- intentkit/skills/openai/gpt_image_to_image.py +186 -0
- intentkit/skills/openai/image_to_text.py +126 -0
- intentkit/skills/openai/openai.png +0 -0
- intentkit/skills/openai/schema.json +139 -0
- intentkit/skills/portfolio/README.md +55 -0
- intentkit/skills/portfolio/__init__.py +151 -0
- intentkit/skills/portfolio/base.py +107 -0
- intentkit/skills/portfolio/constants.py +9 -0
- intentkit/skills/portfolio/moralis.png +0 -0
- intentkit/skills/portfolio/schema.json +237 -0
- intentkit/skills/portfolio/token_balances.py +155 -0
- intentkit/skills/portfolio/wallet_approvals.py +102 -0
- intentkit/skills/portfolio/wallet_defi_positions.py +80 -0
- intentkit/skills/portfolio/wallet_history.py +155 -0
- intentkit/skills/portfolio/wallet_net_worth.py +112 -0
- intentkit/skills/portfolio/wallet_nfts.py +139 -0
- intentkit/skills/portfolio/wallet_profitability.py +101 -0
- intentkit/skills/portfolio/wallet_profitability_summary.py +91 -0
- intentkit/skills/portfolio/wallet_stats.py +79 -0
- intentkit/skills/portfolio/wallet_swaps.py +147 -0
- intentkit/skills/skills.toml +103 -0
- intentkit/skills/slack/__init__.py +98 -0
- intentkit/skills/slack/base.py +55 -0
- intentkit/skills/slack/get_channel.py +109 -0
- intentkit/skills/slack/get_message.py +136 -0
- intentkit/skills/slack/schedule_message.py +92 -0
- intentkit/skills/slack/schema.json +135 -0
- intentkit/skills/slack/send_message.py +81 -0
- intentkit/skills/slack/slack.jpg +0 -0
- intentkit/skills/system/__init__.py +90 -0
- intentkit/skills/system/base.py +22 -0
- intentkit/skills/system/read_agent_api_key.py +87 -0
- intentkit/skills/system/regenerate_agent_api_key.py +77 -0
- intentkit/skills/system/schema.json +53 -0
- intentkit/skills/system/system.svg +76 -0
- intentkit/skills/tavily/README.md +86 -0
- intentkit/skills/tavily/__init__.py +91 -0
- intentkit/skills/tavily/base.py +27 -0
- intentkit/skills/tavily/schema.json +119 -0
- intentkit/skills/tavily/tavily.jpg +0 -0
- intentkit/skills/tavily/tavily_extract.py +147 -0
- intentkit/skills/tavily/tavily_search.py +139 -0
- intentkit/skills/token/README.md +89 -0
- intentkit/skills/token/__init__.py +107 -0
- intentkit/skills/token/base.py +154 -0
- intentkit/skills/token/constants.py +9 -0
- intentkit/skills/token/erc20_transfers.py +145 -0
- intentkit/skills/token/moralis.png +0 -0
- intentkit/skills/token/schema.json +141 -0
- intentkit/skills/token/token_analytics.py +81 -0
- intentkit/skills/token/token_price.py +132 -0
- intentkit/skills/token/token_search.py +121 -0
- intentkit/skills/twitter/__init__.py +146 -0
- intentkit/skills/twitter/base.py +68 -0
- intentkit/skills/twitter/follow_user.py +69 -0
- intentkit/skills/twitter/get_mentions.py +124 -0
- intentkit/skills/twitter/get_timeline.py +111 -0
- intentkit/skills/twitter/get_user_by_username.py +84 -0
- intentkit/skills/twitter/get_user_tweets.py +123 -0
- intentkit/skills/twitter/like_tweet.py +65 -0
- intentkit/skills/twitter/post_tweet.py +90 -0
- intentkit/skills/twitter/reply_tweet.py +98 -0
- intentkit/skills/twitter/retweet.py +76 -0
- intentkit/skills/twitter/schema.json +258 -0
- intentkit/skills/twitter/search_tweets.py +115 -0
- intentkit/skills/twitter/twitter.png +0 -0
- intentkit/skills/unrealspeech/__init__.py +55 -0
- intentkit/skills/unrealspeech/base.py +21 -0
- intentkit/skills/unrealspeech/schema.json +100 -0
- intentkit/skills/unrealspeech/text_to_speech.py +177 -0
- intentkit/skills/unrealspeech/unrealspeech.jpg +0 -0
- intentkit/skills/venice_audio/__init__.py +106 -0
- intentkit/skills/venice_audio/base.py +119 -0
- intentkit/skills/venice_audio/input.py +41 -0
- intentkit/skills/venice_audio/schema.json +152 -0
- intentkit/skills/venice_audio/venice_audio.py +240 -0
- intentkit/skills/venice_audio/venice_logo.jpg +0 -0
- intentkit/skills/venice_image/README.md +119 -0
- intentkit/skills/venice_image/__init__.py +154 -0
- intentkit/skills/venice_image/api.py +138 -0
- intentkit/skills/venice_image/base.py +188 -0
- intentkit/skills/venice_image/config.py +35 -0
- intentkit/skills/venice_image/image_enhance/README.md +119 -0
- intentkit/skills/venice_image/image_enhance/__init__.py +0 -0
- intentkit/skills/venice_image/image_enhance/image_enhance.py +80 -0
- intentkit/skills/venice_image/image_enhance/image_enhance_base.py +23 -0
- intentkit/skills/venice_image/image_enhance/image_enhance_input.py +40 -0
- intentkit/skills/venice_image/image_generation/README.md +144 -0
- intentkit/skills/venice_image/image_generation/__init__.py +0 -0
- intentkit/skills/venice_image/image_generation/image_generation_base.py +117 -0
- intentkit/skills/venice_image/image_generation/image_generation_fluently_xl.py +26 -0
- intentkit/skills/venice_image/image_generation/image_generation_flux_dev.py +27 -0
- intentkit/skills/venice_image/image_generation/image_generation_flux_dev_uncensored.py +26 -0
- intentkit/skills/venice_image/image_generation/image_generation_input.py +158 -0
- intentkit/skills/venice_image/image_generation/image_generation_lustify_sdxl.py +26 -0
- intentkit/skills/venice_image/image_generation/image_generation_pony_realism.py +26 -0
- intentkit/skills/venice_image/image_generation/image_generation_stable_diffusion_3_5.py +28 -0
- intentkit/skills/venice_image/image_generation/image_generation_venice_sd35.py +28 -0
- intentkit/skills/venice_image/image_upscale/README.md +111 -0
- intentkit/skills/venice_image/image_upscale/__init__.py +0 -0
- intentkit/skills/venice_image/image_upscale/image_upscale.py +90 -0
- intentkit/skills/venice_image/image_upscale/image_upscale_base.py +23 -0
- intentkit/skills/venice_image/image_upscale/image_upscale_input.py +22 -0
- intentkit/skills/venice_image/image_vision/README.md +112 -0
- intentkit/skills/venice_image/image_vision/__init__.py +0 -0
- intentkit/skills/venice_image/image_vision/image_vision.py +100 -0
- intentkit/skills/venice_image/image_vision/image_vision_base.py +17 -0
- intentkit/skills/venice_image/image_vision/image_vision_input.py +9 -0
- intentkit/skills/venice_image/schema.json +267 -0
- intentkit/skills/venice_image/utils.py +78 -0
- intentkit/skills/venice_image/venice_image.jpg +0 -0
- intentkit/skills/web_scraper/README.md +82 -0
- intentkit/skills/web_scraper/__init__.py +92 -0
- intentkit/skills/web_scraper/base.py +21 -0
- intentkit/skills/web_scraper/langchain.png +0 -0
- intentkit/skills/web_scraper/schema.json +115 -0
- intentkit/skills/web_scraper/scrape_and_index.py +327 -0
- intentkit/utils/__init__.py +1 -0
- intentkit/utils/chain.py +436 -0
- intentkit/utils/error.py +134 -0
- intentkit/utils/logging.py +70 -0
- intentkit/utils/middleware.py +61 -0
- intentkit/utils/random.py +16 -0
- intentkit/utils/s3.py +267 -0
- intentkit/utils/slack_alert.py +79 -0
- intentkit/utils/tx.py +37 -0
- {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/METADATA +1 -1
- intentkit-0.5.2.dist-info/RECORD +365 -0
- intentkit-0.5.0.dist-info/RECORD +0 -4
- {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/WHEEL +0 -0
- {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
from typing import List, Optional, Type
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
from langchain.tools.base import ToolException
|
|
5
|
+
from langchain_core.runnables import RunnableConfig
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
from intentkit.skills.base import SkillContext
|
|
9
|
+
from intentkit.skills.enso.base import (
|
|
10
|
+
EnsoBaseTool,
|
|
11
|
+
base_url,
|
|
12
|
+
)
|
|
13
|
+
from intentkit.utils.chain import NetworkId
|
|
14
|
+
|
|
15
|
+
# Chain ID for Base Mainnet
|
|
16
|
+
BASE_CHAIN_ID = int(NetworkId.BaseMainnet)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class EnsoGetBestYieldInput(BaseModel):
|
|
20
|
+
"""Input for finding the best yield for a token on a specific chain."""
|
|
21
|
+
|
|
22
|
+
token_symbol: str = Field(
|
|
23
|
+
"USDC",
|
|
24
|
+
description="Symbol of the token to find the best yield for (e.g., 'USDC', 'ETH', 'USDT')",
|
|
25
|
+
)
|
|
26
|
+
chain_id: int = Field(
|
|
27
|
+
BASE_CHAIN_ID,
|
|
28
|
+
description="The blockchain chain ID. Default is Base Mainnet (8453)",
|
|
29
|
+
)
|
|
30
|
+
top_n: int = Field(
|
|
31
|
+
5,
|
|
32
|
+
description="Number of top yield options to return",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class YieldOption(BaseModel):
|
|
37
|
+
"""Represents a yield option for a token."""
|
|
38
|
+
|
|
39
|
+
protocol_name: str = Field(
|
|
40
|
+
None, description="Name of the protocol offering the yield"
|
|
41
|
+
)
|
|
42
|
+
protocol_slug: str = Field(None, description="Slug of the protocol")
|
|
43
|
+
token_name: str = Field(None, description="Name of the yield-bearing token")
|
|
44
|
+
token_symbol: str = Field(None, description="Symbol of the yield-bearing token")
|
|
45
|
+
token_address: str = Field(
|
|
46
|
+
None, description="Contract address of the yield-bearing token"
|
|
47
|
+
)
|
|
48
|
+
primary_address: str = Field(
|
|
49
|
+
None, description="Primary contract address for interacting with the protocol"
|
|
50
|
+
)
|
|
51
|
+
apy: float = Field(None, description="Annual Percentage Yield")
|
|
52
|
+
tvl: Optional[float] = Field(None, description="Total Value Locked in the protocol")
|
|
53
|
+
underlying_tokens: List[str] = Field(
|
|
54
|
+
[], description="List of underlying token symbols"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class EnsoGetBestYieldOutput(BaseModel):
|
|
59
|
+
"""Output containing the best yield options."""
|
|
60
|
+
|
|
61
|
+
best_options: List[YieldOption] = Field(
|
|
62
|
+
[], description="List of best yield options sorted by APY (descending)"
|
|
63
|
+
)
|
|
64
|
+
token_symbol: str = Field(None, description="Symbol of the token searched for")
|
|
65
|
+
chain_id: int = Field(None, description="Chain ID searched")
|
|
66
|
+
chain_name: str = Field(None, description="Name of the chain searched")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class EnsoGetBestYield(EnsoBaseTool):
|
|
70
|
+
"""
|
|
71
|
+
Tool for finding the best yield options for a specific token across all protocols on a blockchain network.
|
|
72
|
+
This tool analyzes yield data from various DeFi protocols and returns the top options sorted by APY.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
name: str = "enso_get_best_yield"
|
|
76
|
+
description: str = (
|
|
77
|
+
"Find the best yield options for a specific token (default: USDC) across all protocols "
|
|
78
|
+
"on a blockchain network (default: Base). Results are sorted by APY in descending order."
|
|
79
|
+
)
|
|
80
|
+
args_schema: Type[BaseModel] = EnsoGetBestYieldInput
|
|
81
|
+
|
|
82
|
+
async def _arun(
|
|
83
|
+
self,
|
|
84
|
+
config: RunnableConfig,
|
|
85
|
+
token_symbol: str = "USDC",
|
|
86
|
+
chain_id: int = BASE_CHAIN_ID,
|
|
87
|
+
top_n: int = 5,
|
|
88
|
+
**kwargs,
|
|
89
|
+
) -> EnsoGetBestYieldOutput:
|
|
90
|
+
"""
|
|
91
|
+
Run the tool to find the best yield options.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
token_symbol (str): Symbol of the token to find the best yield for (default: USDC)
|
|
95
|
+
chain_id (int): The chain id of the network (default: Base Mainnet)
|
|
96
|
+
top_n (int): Number of top yield options to return
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
EnsoGetBestYieldOutput: A structured output containing the top yield options.
|
|
100
|
+
|
|
101
|
+
Raises:
|
|
102
|
+
ToolException: If there's an error accessing the Enso API.
|
|
103
|
+
"""
|
|
104
|
+
context: SkillContext = self.context_from_config(config)
|
|
105
|
+
api_token = self.get_api_token(context)
|
|
106
|
+
|
|
107
|
+
if not api_token:
|
|
108
|
+
raise ToolException("No API token found for Enso Finance")
|
|
109
|
+
|
|
110
|
+
# Get the chain name for the given chain ID
|
|
111
|
+
chain_name = await self._get_chain_name(api_token, chain_id)
|
|
112
|
+
|
|
113
|
+
# Get all protocols on the specified chain
|
|
114
|
+
protocols = await self._get_protocols(api_token, chain_id)
|
|
115
|
+
|
|
116
|
+
# Collect all yield options from all protocols
|
|
117
|
+
all_yield_options = []
|
|
118
|
+
|
|
119
|
+
for protocol in protocols:
|
|
120
|
+
protocol_slug = protocol.get("slug")
|
|
121
|
+
protocol_name = protocol.get("name")
|
|
122
|
+
|
|
123
|
+
# Get yield-bearing tokens for this protocol
|
|
124
|
+
tokens = await self._get_protocol_tokens(
|
|
125
|
+
api_token, chain_id, protocol_slug, token_symbol
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Process tokens to extract yield options
|
|
129
|
+
for token in tokens:
|
|
130
|
+
# Skip tokens without APY information
|
|
131
|
+
if token.get("apy") is None:
|
|
132
|
+
continue
|
|
133
|
+
|
|
134
|
+
# Check if the token has USDC as an underlying token
|
|
135
|
+
has_target_token = False
|
|
136
|
+
underlying_token_symbols = []
|
|
137
|
+
|
|
138
|
+
if token.get("underlyingTokens"):
|
|
139
|
+
for underlying in token.get("underlyingTokens", []):
|
|
140
|
+
underlying_symbol = underlying.get("symbol")
|
|
141
|
+
underlying_token_symbols.append(underlying_symbol)
|
|
142
|
+
if (
|
|
143
|
+
underlying_symbol
|
|
144
|
+
and underlying_symbol.upper() == token_symbol.upper()
|
|
145
|
+
):
|
|
146
|
+
has_target_token = True
|
|
147
|
+
|
|
148
|
+
# Skip if the token doesn't have the target token as underlying
|
|
149
|
+
if not has_target_token and token.get("symbol") != token_symbol.upper():
|
|
150
|
+
continue
|
|
151
|
+
|
|
152
|
+
# Create a yield option
|
|
153
|
+
yield_option = YieldOption(
|
|
154
|
+
protocol_name=protocol_name,
|
|
155
|
+
protocol_slug=protocol_slug,
|
|
156
|
+
token_name=token.get("name"),
|
|
157
|
+
token_symbol=token.get("symbol"),
|
|
158
|
+
token_address=token.get("address"),
|
|
159
|
+
primary_address=token.get("primaryAddress"),
|
|
160
|
+
apy=token.get("apy"),
|
|
161
|
+
tvl=token.get("tvl"),
|
|
162
|
+
underlying_tokens=underlying_token_symbols,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
all_yield_options.append(yield_option)
|
|
166
|
+
|
|
167
|
+
# Sort yield options by APY (descending)
|
|
168
|
+
sorted_options = sorted(all_yield_options, key=lambda x: x.apy, reverse=True)
|
|
169
|
+
|
|
170
|
+
# Take the top N options
|
|
171
|
+
top_options = sorted_options[:top_n]
|
|
172
|
+
|
|
173
|
+
return EnsoGetBestYieldOutput(
|
|
174
|
+
best_options=top_options,
|
|
175
|
+
token_symbol=token_symbol,
|
|
176
|
+
chain_id=chain_id,
|
|
177
|
+
chain_name=chain_name,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
async def _get_chain_name(self, api_token: str, chain_id: int) -> str:
|
|
181
|
+
"""
|
|
182
|
+
Get the name of a chain by its ID.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
api_token (str): The Enso API token
|
|
186
|
+
chain_id (int): The chain ID to look up
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
str: The name of the chain, or "Unknown" if not found
|
|
190
|
+
"""
|
|
191
|
+
url = f"{base_url}/api/v1/networks"
|
|
192
|
+
|
|
193
|
+
headers = {
|
|
194
|
+
"accept": "application/json",
|
|
195
|
+
"Authorization": f"Bearer {api_token}",
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async with httpx.AsyncClient() as client:
|
|
199
|
+
try:
|
|
200
|
+
response = await client.get(url, headers=headers)
|
|
201
|
+
response.raise_for_status()
|
|
202
|
+
networks = response.json()
|
|
203
|
+
|
|
204
|
+
for network in networks:
|
|
205
|
+
if network.get("id") == chain_id:
|
|
206
|
+
return network.get("name", "Unknown")
|
|
207
|
+
|
|
208
|
+
return "Unknown"
|
|
209
|
+
except Exception:
|
|
210
|
+
return "Unknown"
|
|
211
|
+
|
|
212
|
+
async def _get_protocols(self, api_token: str, chain_id: int) -> list:
|
|
213
|
+
"""
|
|
214
|
+
Get all protocols available on a specific chain.
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
api_token (str): The Enso API token
|
|
218
|
+
chain_id (int): Chain ID to filter protocols by
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
list: List of protocol data
|
|
222
|
+
"""
|
|
223
|
+
url = f"{base_url}/api/v1/protocols"
|
|
224
|
+
|
|
225
|
+
headers = {
|
|
226
|
+
"accept": "application/json",
|
|
227
|
+
"Authorization": f"Bearer {api_token}",
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
params = {"chainId": chain_id}
|
|
231
|
+
|
|
232
|
+
async with httpx.AsyncClient() as client:
|
|
233
|
+
try:
|
|
234
|
+
response = await client.get(url, headers=headers, params=params)
|
|
235
|
+
response.raise_for_status()
|
|
236
|
+
return response.json()
|
|
237
|
+
except httpx.RequestError as req_err:
|
|
238
|
+
raise ToolException(
|
|
239
|
+
f"Request error from Enso API: {req_err}"
|
|
240
|
+
) from req_err
|
|
241
|
+
except httpx.HTTPStatusError as http_err:
|
|
242
|
+
raise ToolException(
|
|
243
|
+
f"HTTP error from Enso API: {http_err}"
|
|
244
|
+
) from http_err
|
|
245
|
+
except Exception as e:
|
|
246
|
+
raise ToolException(f"Error from Enso API: {e}") from e
|
|
247
|
+
|
|
248
|
+
async def _get_protocol_tokens(
|
|
249
|
+
self, api_token: str, chain_id: int, protocol_slug: str, token_symbol: str
|
|
250
|
+
) -> list:
|
|
251
|
+
"""
|
|
252
|
+
Get tokens for a specific protocol that involve the target token.
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
api_token (str): The Enso API token
|
|
256
|
+
chain_id (int): Chain ID for the tokens
|
|
257
|
+
protocol_slug (str): Protocol slug to filter tokens by
|
|
258
|
+
token_symbol (str): Symbol of the token to search for
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
list: List of token data
|
|
262
|
+
"""
|
|
263
|
+
url = f"{base_url}/api/v1/tokens"
|
|
264
|
+
|
|
265
|
+
headers = {
|
|
266
|
+
"accept": "application/json",
|
|
267
|
+
"Authorization": f"Bearer {api_token}",
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
params = {
|
|
271
|
+
"chainId": chain_id,
|
|
272
|
+
"protocolSlug": protocol_slug,
|
|
273
|
+
"includeMetadata": True,
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
async with httpx.AsyncClient() as client:
|
|
277
|
+
try:
|
|
278
|
+
response = await client.get(url, headers=headers, params=params)
|
|
279
|
+
response.raise_for_status()
|
|
280
|
+
return response.json().get("data", [])
|
|
281
|
+
except httpx.RequestError:
|
|
282
|
+
return []
|
|
283
|
+
except httpx.HTTPStatusError:
|
|
284
|
+
return []
|
|
285
|
+
except Exception:
|
|
286
|
+
return []
|
|
Binary file
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Type
|
|
3
|
+
|
|
4
|
+
import httpx
|
|
5
|
+
from langchain.tools.base import ToolException
|
|
6
|
+
from langchain_core.runnables import RunnableConfig
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from intentkit.skills.base import SkillContext
|
|
10
|
+
|
|
11
|
+
from .base import EnsoBaseTool, base_url
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class EnsoGetNetworksInput(BaseModel):
|
|
17
|
+
"""
|
|
18
|
+
Input model for retrieving networks.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ConnectedNetwork(BaseModel):
|
|
23
|
+
"""
|
|
24
|
+
Represents a single network connection.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
id: int | None = Field(None, description="Unique identifier of the network")
|
|
28
|
+
name: str | None = Field(None, description="Name of the network")
|
|
29
|
+
isConnected: bool | None = Field(
|
|
30
|
+
None, description="Indicates if the network is connected"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class EnsoGetNetworksOutput(BaseModel):
|
|
35
|
+
"""
|
|
36
|
+
Output model for retrieving networks.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
res: list[ConnectedNetwork] | None = Field(
|
|
40
|
+
None, description="Response containing networks and metadata"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class EnsoGetNetworks(EnsoBaseTool):
|
|
45
|
+
"""
|
|
46
|
+
Tool for retrieving networks and their corresponding chainId, the output should be kept.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
name: str = "enso_get_networks"
|
|
50
|
+
description: str = "Retrieve networks supported by the Enso API"
|
|
51
|
+
args_schema: Type[BaseModel] = EnsoGetNetworksInput
|
|
52
|
+
|
|
53
|
+
async def _arun(self, config: RunnableConfig, **kwargs) -> EnsoGetNetworksOutput:
|
|
54
|
+
"""
|
|
55
|
+
Function to request the list of supported networks and their chain id and name.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
EnsoGetNetworksOutput: A structured output containing the network list or an error message.
|
|
59
|
+
"""
|
|
60
|
+
url = f"{base_url}/api/v1/networks"
|
|
61
|
+
|
|
62
|
+
context: SkillContext = self.context_from_config(config)
|
|
63
|
+
api_token = self.get_api_token(context)
|
|
64
|
+
logger.debug(f"api_token: {api_token}")
|
|
65
|
+
headers = {
|
|
66
|
+
"accept": "application/json",
|
|
67
|
+
"Authorization": f"Bearer {api_token}",
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async with httpx.AsyncClient() as client:
|
|
71
|
+
try:
|
|
72
|
+
# Send the GET request
|
|
73
|
+
response = await client.get(url, headers=headers)
|
|
74
|
+
response.raise_for_status()
|
|
75
|
+
|
|
76
|
+
# Parse the response JSON into the NetworkResponse model
|
|
77
|
+
json_dict = response.json()
|
|
78
|
+
|
|
79
|
+
networks = []
|
|
80
|
+
networks_memory = {}
|
|
81
|
+
for item in json_dict:
|
|
82
|
+
network = ConnectedNetwork(**item)
|
|
83
|
+
networks.append(network)
|
|
84
|
+
networks_memory[str(network.id)] = network.model_dump(
|
|
85
|
+
exclude_none=True
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
await self.skill_store.save_agent_skill_data(
|
|
89
|
+
context.agent.id,
|
|
90
|
+
"enso_get_networks",
|
|
91
|
+
"networks",
|
|
92
|
+
networks_memory,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
return EnsoGetNetworksOutput(res=networks)
|
|
96
|
+
except httpx.RequestError as req_err:
|
|
97
|
+
raise ToolException(
|
|
98
|
+
f"request error from Enso API: {req_err}"
|
|
99
|
+
) from req_err
|
|
100
|
+
except httpx.HTTPStatusError as http_err:
|
|
101
|
+
raise ToolException(
|
|
102
|
+
f"http error from Enso API: {http_err}"
|
|
103
|
+
) from http_err
|
|
104
|
+
except Exception as e:
|
|
105
|
+
raise ToolException(f"error from Enso API: {e}") from e
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from typing import Type
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
from langchain.tools.base import ToolException
|
|
5
|
+
from langchain_core.runnables import RunnableConfig
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
from intentkit.skills.base import SkillContext
|
|
9
|
+
|
|
10
|
+
from .base import EnsoBaseTool, base_url, default_chain_id
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class EnsoGetPricesInput(BaseModel):
|
|
14
|
+
chainId: int = Field(
|
|
15
|
+
default_chain_id, description="Blockchain chain ID of the token"
|
|
16
|
+
)
|
|
17
|
+
address: str = Field(
|
|
18
|
+
"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
|
|
19
|
+
description="Contract address of the token",
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class EnsoGetPricesOutput(BaseModel):
|
|
24
|
+
decimals: int | None = Field(None, ge=0, description="Number of decimals")
|
|
25
|
+
price: float | None = Field(None, gt=0, description="Price in the smallest unit")
|
|
26
|
+
address: str | None = Field(None, description="Contract address")
|
|
27
|
+
symbol: str | None = Field(None, description="Token symbol")
|
|
28
|
+
timestamp: int | None = Field(None, ge=0, description="Timestamp in seconds")
|
|
29
|
+
chainId: int | None = Field(None, ge=0, description="Chain ID")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class EnsoGetPrices(EnsoBaseTool):
|
|
33
|
+
"""
|
|
34
|
+
Tool allows fetching the price in USD for a given blockchain's token.
|
|
35
|
+
|
|
36
|
+
Attributes:
|
|
37
|
+
name (str): Name of the tool, specifically "enso_get_prices".
|
|
38
|
+
description (str): Comprehensive description of the tool's purpose and functionality.
|
|
39
|
+
args_schema (Type[BaseModel]): Schema for input arguments, specifying expected parameters.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
name: str = "enso_get_prices"
|
|
43
|
+
description: str = "Retrieve the price of a token by chain ID and contract address"
|
|
44
|
+
args_schema: Type[BaseModel] = EnsoGetPricesInput
|
|
45
|
+
|
|
46
|
+
async def _arun(
|
|
47
|
+
self,
|
|
48
|
+
address: str,
|
|
49
|
+
config: RunnableConfig,
|
|
50
|
+
chainId: int = default_chain_id,
|
|
51
|
+
**kwargs,
|
|
52
|
+
) -> EnsoGetPricesOutput:
|
|
53
|
+
"""
|
|
54
|
+
Asynchronous function to request the token price from the API.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
chainId (int): The blockchain's chain ID.
|
|
58
|
+
address (str): Contract address of the token.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
EnsoGetPricesOutput: Token price response or error message.
|
|
62
|
+
"""
|
|
63
|
+
url = f"{base_url}/api/v1/prices/{str(chainId)}/{address}"
|
|
64
|
+
|
|
65
|
+
context: SkillContext = self.context_from_config(config)
|
|
66
|
+
api_token = self.get_api_token(context)
|
|
67
|
+
|
|
68
|
+
headers = {
|
|
69
|
+
"accept": "application/json",
|
|
70
|
+
"Authorization": f"Bearer {api_token}",
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async with httpx.AsyncClient() as client:
|
|
74
|
+
try:
|
|
75
|
+
response = await client.get(url, headers=headers)
|
|
76
|
+
response.raise_for_status()
|
|
77
|
+
json_dict = response.json()
|
|
78
|
+
|
|
79
|
+
# Parse the response into a `PriceInfo` object
|
|
80
|
+
res = EnsoGetPricesOutput(**json_dict)
|
|
81
|
+
|
|
82
|
+
# Return the parsed response
|
|
83
|
+
return res
|
|
84
|
+
except httpx.RequestError as req_err:
|
|
85
|
+
raise ToolException(
|
|
86
|
+
f"request error from Enso API: {req_err}"
|
|
87
|
+
) from req_err
|
|
88
|
+
except httpx.HTTPStatusError as http_err:
|
|
89
|
+
raise ToolException(
|
|
90
|
+
f"http error from Enso API: {http_err}"
|
|
91
|
+
) from http_err
|
|
92
|
+
except Exception as e:
|
|
93
|
+
raise ToolException(f"error from Enso API: {e}") from e
|