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,223 @@
|
|
|
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
|
+
from intentkit.skills.enso.base import (
|
|
10
|
+
EnsoBaseTool,
|
|
11
|
+
base_url,
|
|
12
|
+
default_chain_id,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
# Actual Enso output types
|
|
16
|
+
# class UnderlyingToken(BaseModel):
|
|
17
|
+
# address: str | None = Field(None, description="The address of the token")
|
|
18
|
+
# chainId: int | None = Field(None, description="The blockchain chain ID")
|
|
19
|
+
# type: str | None = Field(None, description="The type of the token (e.g., base token)")
|
|
20
|
+
# decimals: int | None = Field(None, description="The number of decimals for the token")
|
|
21
|
+
# name: str | None = Field(None, description="The name of the token")
|
|
22
|
+
# symbol: str | None = Field(None, description="The symbol of the token")
|
|
23
|
+
# logosUri: list[HttpUrl] | None = Field(None, description="List of URLs to token's logos")
|
|
24
|
+
#
|
|
25
|
+
#
|
|
26
|
+
# class TokenData(BaseModel):
|
|
27
|
+
# chainId: int | None = Field(None, description="The blockchain chain ID")
|
|
28
|
+
# address: str | None = Field(None, description="The address of the token")
|
|
29
|
+
# decimals: int | None = Field(None, description="The number of decimals for the token")
|
|
30
|
+
# name: str | None = Field(None, description="The name of the token")
|
|
31
|
+
# symbol: str | None = Field(None, description="The symbol of the token")
|
|
32
|
+
# logosUri: list[HttpUrl] | None = Field(None, description="List of URLs to token's logos")
|
|
33
|
+
# type: str | None = Field(None, description="The type of the token (e.g., defi, base, etc.)")
|
|
34
|
+
# protocolSlug: str | None = Field(None, description="The protocol slug associated with the token")
|
|
35
|
+
# underlyingTokens: list[UnderlyingToken] | None = Field(None, description="List of underlying tokens")
|
|
36
|
+
# primaryAddress: str | None = Field(None, description="The primary address associated with the token")
|
|
37
|
+
# apy: float | None = Field(None, description="The annual percentage yield (APY) for the token")
|
|
38
|
+
#
|
|
39
|
+
#
|
|
40
|
+
# class MetaData(BaseModel):
|
|
41
|
+
# total: int | None = Field(None, description="Total number of records")
|
|
42
|
+
# lastPage: int | None = Field(None, description="Last page of the data")
|
|
43
|
+
# currentPage: int | None = Field(None, description="Current page of the data")
|
|
44
|
+
# perPage: int | None = Field(None, description="Number of records per page")
|
|
45
|
+
# prev: int | None = Field(None, description="Previous page number, if applicable")
|
|
46
|
+
# next: int | None = Field(None, description="Next page number, if applicable")
|
|
47
|
+
#
|
|
48
|
+
#
|
|
49
|
+
# class TokenResponse(BaseModel):
|
|
50
|
+
# data: list[TokenData] | None = Field(None, description="List of token data")
|
|
51
|
+
# meta: MetaData | None = Field(None, description="Metadata regarding pagination")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class EnsoGetTokensInput(BaseModel):
|
|
55
|
+
chainId: int = Field(
|
|
56
|
+
default_chain_id,
|
|
57
|
+
description="The blockchain chain ID",
|
|
58
|
+
)
|
|
59
|
+
protocolSlug: str | None = Field(
|
|
60
|
+
None,
|
|
61
|
+
description="The protocol slug (e.g., 'aave-v2', 'aave-v3', 'compound-v2')",
|
|
62
|
+
)
|
|
63
|
+
# address: str | None = Field(
|
|
64
|
+
# None,
|
|
65
|
+
# description="Ethereum address of the token",
|
|
66
|
+
# )
|
|
67
|
+
# underlyingTokens: str | list[str] | None = Field(
|
|
68
|
+
# None,
|
|
69
|
+
# description="Underlying tokens (e.g. 0xdAC17F958D2ee523a2206206994597C13D831ec7)",
|
|
70
|
+
# )
|
|
71
|
+
# primaryAddress: str | None = Field(
|
|
72
|
+
# None,
|
|
73
|
+
# description="Ethereum address for contract interaction of defi token",
|
|
74
|
+
# )
|
|
75
|
+
# type: Literal["defi", "base"] | None = Field(
|
|
76
|
+
# None,
|
|
77
|
+
# description="The type of the token (e.g., 'defi', 'base'). Note: Base Network also exists, it should not be confused with type.",
|
|
78
|
+
# )
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class UnderlyingTokenCompact(BaseModel):
|
|
82
|
+
address: str | None = Field(None, description="The address of the token")
|
|
83
|
+
type: str | None = Field(
|
|
84
|
+
None, description="The type of the token (e.g., base token)"
|
|
85
|
+
)
|
|
86
|
+
name: str | None = Field(None, description="The name of the token")
|
|
87
|
+
symbol: str | None = Field(None, description="The symbol of the token")
|
|
88
|
+
decimals: int | None = Field(
|
|
89
|
+
None, description="The number of decimals for the token"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class TokenResponseCompact(BaseModel):
|
|
94
|
+
name: str | None = Field(None, description="The name of the token")
|
|
95
|
+
symbol: str | None = Field(None, description="The symbol of the token")
|
|
96
|
+
address: str | None = Field(None, description="The address of the token")
|
|
97
|
+
primaryAddress: str | None = Field(
|
|
98
|
+
None, description="The primary address associated with the token"
|
|
99
|
+
)
|
|
100
|
+
type: str | None = Field(
|
|
101
|
+
None, description="The type of the token (e.g., defi, base, etc.)"
|
|
102
|
+
)
|
|
103
|
+
apy: float | None = Field(
|
|
104
|
+
None, description="The annual percentage yield (APY) for the token"
|
|
105
|
+
)
|
|
106
|
+
underlyingTokens: list[UnderlyingTokenCompact] | None = Field(
|
|
107
|
+
None, description="List of underlying tokens"
|
|
108
|
+
)
|
|
109
|
+
decimals: int | None = Field(
|
|
110
|
+
None, description="The number of decimals for the token"
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class EnsoGetTokensOutput(BaseModel):
|
|
115
|
+
res: list[TokenResponseCompact] | None
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class EnsoGetTokens(EnsoBaseTool):
|
|
119
|
+
"""
|
|
120
|
+
Tool for interacting with the Enso API to retrieve cryptocurrency token information, including APY, symbol, address,
|
|
121
|
+
protocol slug, token type, and underlying tokens.
|
|
122
|
+
|
|
123
|
+
This class is designed to provide detailed insights into tokens managed by the Enso platform.
|
|
124
|
+
It integrates with the Enso API and offers various options for filtering tokens based on optional inputs such as
|
|
125
|
+
chain ID, protocol slug, token type, and underlying tokens. The main objective is to retrieve APY data
|
|
126
|
+
and relevant information for the specified tokens, delivering structured output for further processing.
|
|
127
|
+
|
|
128
|
+
Attributes:
|
|
129
|
+
name (str): Name of the tool, specifically "enso_get_tokens".
|
|
130
|
+
description (str): Comprehensive description of the tool's purpose and functionality.
|
|
131
|
+
args_schema (Type[BaseModel]): Schema for input arguments, specifying expected parameters.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
name: str = "enso_get_tokens"
|
|
135
|
+
description: str = (
|
|
136
|
+
"Enso Finance Token Information Tool: Retrieves detailed token information from the Enso Finance API, "
|
|
137
|
+
"including APY, symbol, address, protocol slug, token type, and underlying tokens."
|
|
138
|
+
)
|
|
139
|
+
args_schema: Type[BaseModel] = EnsoGetTokensInput
|
|
140
|
+
|
|
141
|
+
async def _arun(
|
|
142
|
+
self,
|
|
143
|
+
config: RunnableConfig,
|
|
144
|
+
chainId: int = default_chain_id,
|
|
145
|
+
protocolSlug: str | None = None,
|
|
146
|
+
**kwargs,
|
|
147
|
+
) -> EnsoGetTokensOutput:
|
|
148
|
+
"""Run the tool to get Tokens and APY.
|
|
149
|
+
Args:
|
|
150
|
+
chainId (int): The chain id of the network.
|
|
151
|
+
protocolSlug (str): The protocol slug (e.g., 'aave-v2', 'aave-v3', 'compound-v2').
|
|
152
|
+
Returns:
|
|
153
|
+
EnsoGetTokensOutput: A structured output containing the tokens APY data.
|
|
154
|
+
|
|
155
|
+
Raises:
|
|
156
|
+
Exception: If there's an error accessing the Enso API.
|
|
157
|
+
"""
|
|
158
|
+
url = f"{base_url}/api/v1/tokens"
|
|
159
|
+
|
|
160
|
+
context: SkillContext = self.context_from_config(config)
|
|
161
|
+
agent_id = context.agent.id
|
|
162
|
+
api_token = self.get_api_token(context)
|
|
163
|
+
main_tokens = self.get_main_tokens(context)
|
|
164
|
+
headers = {
|
|
165
|
+
"accept": "application/json",
|
|
166
|
+
"Authorization": f"Bearer {api_token}",
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
params = EnsoGetTokensInput(
|
|
170
|
+
chainId=chainId,
|
|
171
|
+
protocolSlug=protocolSlug,
|
|
172
|
+
).model_dump(exclude_none=True)
|
|
173
|
+
|
|
174
|
+
params["page"] = 1
|
|
175
|
+
params["includeMetadata"] = "true"
|
|
176
|
+
|
|
177
|
+
async with httpx.AsyncClient() as client:
|
|
178
|
+
try:
|
|
179
|
+
response = await client.get(url, headers=headers, params=params)
|
|
180
|
+
response.raise_for_status()
|
|
181
|
+
json_dict = response.json()
|
|
182
|
+
|
|
183
|
+
token_decimals = await self.skill_store.get_agent_skill_data(
|
|
184
|
+
agent_id,
|
|
185
|
+
"enso_get_tokens",
|
|
186
|
+
"decimals",
|
|
187
|
+
)
|
|
188
|
+
if not token_decimals:
|
|
189
|
+
token_decimals = {}
|
|
190
|
+
|
|
191
|
+
# filter the main tokens from config or the ones that have apy assigned.
|
|
192
|
+
res = EnsoGetTokensOutput(res=list[TokenResponseCompact]())
|
|
193
|
+
for item in json_dict["data"]:
|
|
194
|
+
main_tokens = [item.upper() for item in main_tokens]
|
|
195
|
+
if item.get("apy") or (item.get("symbol").upper() in main_tokens):
|
|
196
|
+
token_response = TokenResponseCompact(**item)
|
|
197
|
+
res.res.append(token_response)
|
|
198
|
+
token_decimals[token_response.address] = token_response.decimals
|
|
199
|
+
if (
|
|
200
|
+
token_response.underlyingTokens
|
|
201
|
+
and len(token_response.underlyingTokens) > 0
|
|
202
|
+
):
|
|
203
|
+
for u_token in token_response.underlyingTokens:
|
|
204
|
+
token_decimals[u_token.address] = u_token.decimals
|
|
205
|
+
|
|
206
|
+
await self.skill_store.save_agent_skill_data(
|
|
207
|
+
agent_id,
|
|
208
|
+
"enso_get_tokens",
|
|
209
|
+
"decimals",
|
|
210
|
+
token_decimals,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
return res
|
|
214
|
+
except httpx.RequestError as req_err:
|
|
215
|
+
raise ToolException(
|
|
216
|
+
f"request error from Enso API: {req_err}"
|
|
217
|
+
) from req_err
|
|
218
|
+
except httpx.HTTPStatusError as http_err:
|
|
219
|
+
raise ToolException(
|
|
220
|
+
f"http error from Enso API: {http_err}"
|
|
221
|
+
) from http_err
|
|
222
|
+
except Exception as e:
|
|
223
|
+
raise ToolException(f"error from Enso API: {e}") from e
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
from typing import Literal, Tuple, 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.utils.tx import EvmContractWrapper
|
|
10
|
+
|
|
11
|
+
from .abi.erc20 import ABI_ERC20
|
|
12
|
+
from .base import EnsoBaseTool, base_url, default_chain_id
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class EnsoGetBalancesInput(BaseModel):
|
|
16
|
+
"""
|
|
17
|
+
Input model for retrieving wallet balances.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
chainId: int = Field(
|
|
21
|
+
default_chain_id, description="Chain ID of the blockchain network"
|
|
22
|
+
)
|
|
23
|
+
# eoaAddress: str = Field(
|
|
24
|
+
# description="Address of the eoa with which to associate the ensoWallet for balances"
|
|
25
|
+
# )
|
|
26
|
+
# useEoa: bool = Field(
|
|
27
|
+
# description="If true returns balances for the provided eoaAddress, instead of the associated ensoWallet"
|
|
28
|
+
# )
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class WalletBalance(BaseModel):
|
|
32
|
+
token: str | None = Field(None, description="The address of the token")
|
|
33
|
+
amount: str | None = Field(None, description="The unformatted balance of the token")
|
|
34
|
+
decimals: int | None = Field(None, ge=0, description="The number of decimals")
|
|
35
|
+
price: float | None = Field(None, description="Price of the token in usd")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class EnsoGetBalancesOutput(BaseModel):
|
|
39
|
+
"""
|
|
40
|
+
Output model for retrieving wallet balances.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
res: list[WalletBalance] | None = Field(
|
|
44
|
+
None, description="The wallet's balances along with token details."
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class EnsoGetWalletBalances(EnsoBaseTool):
|
|
49
|
+
"""
|
|
50
|
+
This tool allows querying for first 20 token balances of a specific wallet
|
|
51
|
+
and blockchain network.
|
|
52
|
+
|
|
53
|
+
Attributes:
|
|
54
|
+
name (str): Name of the tool, specifically "enso_get_wallet_balances".
|
|
55
|
+
description (str): Comprehensive description of the tool's purpose and functionality.
|
|
56
|
+
args_schema (Type[BaseModel]): Schema for input arguments, specifying expected parameters.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
name: str = "enso_get_wallet_balances"
|
|
60
|
+
description: str = (
|
|
61
|
+
"Retrieve token balances of a wallet on a specified blockchain network."
|
|
62
|
+
)
|
|
63
|
+
args_schema: Type[BaseModel] = EnsoGetBalancesInput
|
|
64
|
+
|
|
65
|
+
async def _arun(
|
|
66
|
+
self,
|
|
67
|
+
config: RunnableConfig,
|
|
68
|
+
chainId: int = default_chain_id,
|
|
69
|
+
**kwargs,
|
|
70
|
+
) -> EnsoGetBalancesOutput:
|
|
71
|
+
"""
|
|
72
|
+
Run the tool to get token balances of a wallet.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
chainId (int): Chain ID of the blockchain network.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
EnsoGetBalancesOutput: The list of balances or an error message.
|
|
79
|
+
"""
|
|
80
|
+
url = f"{base_url}/api/v1/wallet/balances"
|
|
81
|
+
|
|
82
|
+
context: SkillContext = self.context_from_config(config)
|
|
83
|
+
api_token = self.get_api_token(context)
|
|
84
|
+
wallet = await self.get_wallet(context)
|
|
85
|
+
headers = {
|
|
86
|
+
"accept": "application/json",
|
|
87
|
+
"Authorization": f"Bearer {api_token}",
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
params = EnsoGetBalancesInput(chainId=chainId).model_dump(exclude_none=True)
|
|
91
|
+
params["eoaAddress"] = wallet.addresses[0].address_id
|
|
92
|
+
params["useEoa"] = True
|
|
93
|
+
|
|
94
|
+
async with httpx.AsyncClient() as client:
|
|
95
|
+
try:
|
|
96
|
+
# Send the GET request
|
|
97
|
+
response = await client.get(url, headers=headers, params=params)
|
|
98
|
+
response.raise_for_status()
|
|
99
|
+
|
|
100
|
+
# Map the response JSON into the WalletBalance model
|
|
101
|
+
json_dict = response.json()[:20]
|
|
102
|
+
res = [WalletBalance(**item) for item in json_dict]
|
|
103
|
+
|
|
104
|
+
# Return the parsed response
|
|
105
|
+
return EnsoGetBalancesOutput(res=res)
|
|
106
|
+
except httpx.RequestError as req_err:
|
|
107
|
+
raise ToolException("request error from Enso API") from req_err
|
|
108
|
+
except httpx.HTTPStatusError as http_err:
|
|
109
|
+
raise ToolException("http error from Enso API") from http_err
|
|
110
|
+
except Exception as e:
|
|
111
|
+
raise ToolException(f"error from Enso API: {e}") from e
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class EnsoGetApprovalsInput(BaseModel):
|
|
115
|
+
"""
|
|
116
|
+
Input model for retrieving wallet approvals.
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
chainId: int = Field(
|
|
120
|
+
default_chain_id, description="Chain ID of the blockchain network"
|
|
121
|
+
)
|
|
122
|
+
fromAddress: str = Field(description="Address of the wallet")
|
|
123
|
+
routingStrategy: Literal["ensowallet", "router", "delegate"] | None = Field(
|
|
124
|
+
None, description="Routing strategy to use"
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class WalletAllowance(BaseModel):
|
|
129
|
+
token: str | None = Field(None, description="The token address")
|
|
130
|
+
allowance: str | None = Field(None, description="The amount of tokens approved")
|
|
131
|
+
spender: str | None = Field(None, description="The spender address")
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class EnsoGetApprovalsOutput(BaseModel):
|
|
135
|
+
"""
|
|
136
|
+
Output model for retrieving wallet approvals.
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
res: list[WalletAllowance] | None = Field(
|
|
140
|
+
None, description="Response containing the list of token approvals."
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class EnsoGetWalletApprovals(EnsoBaseTool):
|
|
145
|
+
"""
|
|
146
|
+
This tool allows querying for first 50 token spend approvals associated with a specific wallet
|
|
147
|
+
and blockchain network.
|
|
148
|
+
|
|
149
|
+
Attributes:
|
|
150
|
+
name (str): Name of the tool, specifically "enso_get_wallet_approvals".
|
|
151
|
+
description (str): Comprehensive description of the tool's purpose and functionality.
|
|
152
|
+
args_schema (Type[BaseModel]): Schema for input arguments, specifying expected parameters.
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
name: str = "enso_get_wallet_approvals"
|
|
156
|
+
description: str = (
|
|
157
|
+
"Retrieve token spend approvals for a wallet on a specified blockchain network."
|
|
158
|
+
)
|
|
159
|
+
args_schema: Type[BaseModel] = EnsoGetApprovalsOutput
|
|
160
|
+
|
|
161
|
+
async def _arun(
|
|
162
|
+
self,
|
|
163
|
+
config: RunnableConfig,
|
|
164
|
+
chainId: int = default_chain_id,
|
|
165
|
+
**kwargs,
|
|
166
|
+
) -> EnsoGetApprovalsOutput:
|
|
167
|
+
"""
|
|
168
|
+
Run the tool to get token approvals for a wallet.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
chainId (int): Chain ID of the blockchain network.
|
|
172
|
+
**kwargs: optional kwargs for the tool with args schema defined in EnsoGetApprovalsInput.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
EnsoGetApprovalsOutput: The list of approvals or an error message.
|
|
176
|
+
"""
|
|
177
|
+
url = f"{base_url}/api/v1/wallet/approvals"
|
|
178
|
+
|
|
179
|
+
context: SkillContext = self.context_from_config(config)
|
|
180
|
+
api_token = self.get_api_token(context)
|
|
181
|
+
wallet = await self.get_wallet(context)
|
|
182
|
+
|
|
183
|
+
headers = {
|
|
184
|
+
"accept": "application/json",
|
|
185
|
+
"Authorization": f"Bearer {api_token}",
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
params = EnsoGetApprovalsInput(
|
|
189
|
+
chainId=chainId,
|
|
190
|
+
fromAddress=wallet.addresses[0].address_id,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
if kwargs.get("routingStrategy"):
|
|
194
|
+
params.routingStrategy = kwargs["routingStrategy"]
|
|
195
|
+
|
|
196
|
+
async with httpx.AsyncClient() as client:
|
|
197
|
+
try:
|
|
198
|
+
# Send the GET request
|
|
199
|
+
response = await client.get(
|
|
200
|
+
url, headers=headers, params=params.model_dump(exclude_none=True)
|
|
201
|
+
)
|
|
202
|
+
response.raise_for_status()
|
|
203
|
+
|
|
204
|
+
# Map the response JSON into the ApprovalsResponse model
|
|
205
|
+
json_dict = response.json()[:50]
|
|
206
|
+
res = [WalletAllowance(**item) for item in json_dict]
|
|
207
|
+
|
|
208
|
+
# Return the parsed response
|
|
209
|
+
return EnsoGetApprovalsOutput(res=res)
|
|
210
|
+
except httpx.RequestError as req_err:
|
|
211
|
+
raise ToolException(
|
|
212
|
+
f"request error from Enso API: {req_err}"
|
|
213
|
+
) from req_err
|
|
214
|
+
except httpx.HTTPStatusError as http_err:
|
|
215
|
+
raise ToolException(
|
|
216
|
+
f"http error from Enso API: {http_err}"
|
|
217
|
+
) from http_err
|
|
218
|
+
except Exception as e:
|
|
219
|
+
raise ToolException(f"error from Enso API: {e}") from e
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class EnsoWalletApproveInput(BaseModel):
|
|
223
|
+
"""
|
|
224
|
+
Input model for approve the wallet.
|
|
225
|
+
"""
|
|
226
|
+
|
|
227
|
+
tokenAddress: str = Field(description="ERC20 token address of the token to approve")
|
|
228
|
+
amount: int = Field(description="Amount of tokens to approve in wei")
|
|
229
|
+
chainId: int = Field(
|
|
230
|
+
default_chain_id, description="Chain ID of the blockchain network"
|
|
231
|
+
)
|
|
232
|
+
routingStrategy: Literal["ensowallet", "router", "delegate"] | None = Field(
|
|
233
|
+
None, description="Routing strategy to use"
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
class EnsoWalletApproveOutput(BaseModel):
|
|
238
|
+
"""
|
|
239
|
+
Output model for approve token for the wallet.
|
|
240
|
+
"""
|
|
241
|
+
|
|
242
|
+
gas: str | None = Field(None, description="The gas estimate for the transaction")
|
|
243
|
+
token: str | None = Field(None, description="The token address to approve")
|
|
244
|
+
amount: str | None = Field(None, description="The amount of tokens to approve")
|
|
245
|
+
spender: str | None = Field(None, description="The spender address to approve")
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
class EnsoWalletApproveArtifact(BaseModel):
|
|
249
|
+
"""
|
|
250
|
+
Output model for approve token for the wallet.
|
|
251
|
+
"""
|
|
252
|
+
|
|
253
|
+
tx: object | None = Field(None, description="The tx object to use in `ethers`")
|
|
254
|
+
txHash: str | None = Field(None, description="The transaction hash")
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
class EnsoWalletApprove(EnsoBaseTool):
|
|
258
|
+
"""
|
|
259
|
+
This tool is used specifically for broadcasting a ERC20 token spending approval transaction to the network.
|
|
260
|
+
It should only be used when the user explicitly requests to broadcast an approval transaction with a specific amount for a certain token.
|
|
261
|
+
|
|
262
|
+
**Example Usage:**
|
|
263
|
+
|
|
264
|
+
"Broadcast an approval transaction for 10 USDC to the wallet."
|
|
265
|
+
|
|
266
|
+
**Important:**
|
|
267
|
+
- This tool should be used with extreme caution.
|
|
268
|
+
- Approving token spending grants another account permission to spend your tokens.
|
|
269
|
+
|
|
270
|
+
Attributes:
|
|
271
|
+
name (str): Name of the tool, specifically "enso_wallet_approve".
|
|
272
|
+
description (str): Comprehensive description of the tool's purpose and functionality.
|
|
273
|
+
args_schema (Type[BaseModel]): Schema for input arguments, specifying expected parameters.
|
|
274
|
+
"""
|
|
275
|
+
|
|
276
|
+
name: str = "enso_wallet_approve"
|
|
277
|
+
description: str = "This tool is used specifically for broadcasting a ERC20 token spending approval transaction to the network. It should only be used when the user explicitly requests to broadcast an approval transaction with a specific amount for a certain token."
|
|
278
|
+
args_schema: Type[BaseModel] = EnsoWalletApproveInput
|
|
279
|
+
response_format: str = "content_and_artifact"
|
|
280
|
+
|
|
281
|
+
# def _run(
|
|
282
|
+
# self,
|
|
283
|
+
# tokenAddress: str,
|
|
284
|
+
# amount: int,
|
|
285
|
+
# chainId: int = default_chain_id,
|
|
286
|
+
# **kwargs,
|
|
287
|
+
# ) -> Tuple[EnsoBroadcastWalletApproveOutput, EnsoBroadcastWalletApproveArtifact]:
|
|
288
|
+
# """Run the tool to approve enso router for a wallet.
|
|
289
|
+
|
|
290
|
+
# Returns:
|
|
291
|
+
# Tuple[EnsoBroadcastWalletApproveOutput, EnsoBroadcastWalletApproveArtifact]: A structured output containing the result of token approval.
|
|
292
|
+
|
|
293
|
+
# Raises:
|
|
294
|
+
# Exception: If there's an error accessing the Enso API.
|
|
295
|
+
# """
|
|
296
|
+
# raise NotImplementedError("Use _arun instead")
|
|
297
|
+
|
|
298
|
+
async def _arun(
|
|
299
|
+
self,
|
|
300
|
+
tokenAddress: str,
|
|
301
|
+
amount: int,
|
|
302
|
+
config: RunnableConfig,
|
|
303
|
+
chainId: int = default_chain_id,
|
|
304
|
+
**kwargs,
|
|
305
|
+
) -> Tuple[EnsoWalletApproveOutput, EnsoWalletApproveArtifact]:
|
|
306
|
+
"""
|
|
307
|
+
Run the tool to approve enso router for a wallet.
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
tokenAddress (str): ERC20 token address of the token to approve.
|
|
311
|
+
amount (int): Amount of tokens to approve in wei.
|
|
312
|
+
chainId (int): Chain ID of the blockchain network.
|
|
313
|
+
**kwargs: optional kwargs for the tool with args schema defined in EnsoGetApproveInput.
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
Tuple[EnsoBroadcastWalletApproveOutput, EnsoBroadcastWalletApproveArtifact]: The list of approve transaction output or an error message.
|
|
317
|
+
"""
|
|
318
|
+
url = f"{base_url}/api/v1/wallet/approve"
|
|
319
|
+
context: SkillContext = self.context_from_config(config)
|
|
320
|
+
api_token = self.get_api_token(context)
|
|
321
|
+
chain_provider = self.get_chain_provider(context)
|
|
322
|
+
wallet = await self.get_wallet(context)
|
|
323
|
+
|
|
324
|
+
headers = {
|
|
325
|
+
"accept": "application/json",
|
|
326
|
+
"Authorization": f"Bearer {api_token}",
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
from_address = wallet.addresses[0].address_id
|
|
330
|
+
|
|
331
|
+
params = EnsoWalletApproveInput(
|
|
332
|
+
tokenAddress=tokenAddress,
|
|
333
|
+
amount=amount,
|
|
334
|
+
chainId=chainId,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
if kwargs.get("routingStrategy"):
|
|
338
|
+
params.routingStrategy = kwargs["routingStrategy"]
|
|
339
|
+
|
|
340
|
+
params = params.model_dump(exclude_none=True)
|
|
341
|
+
|
|
342
|
+
params["fromAddress"] = from_address
|
|
343
|
+
|
|
344
|
+
with httpx.Client() as client:
|
|
345
|
+
try:
|
|
346
|
+
# Send the GET request
|
|
347
|
+
response = client.get(url, headers=headers, params=params)
|
|
348
|
+
response.raise_for_status()
|
|
349
|
+
|
|
350
|
+
# Map the response JSON into the WalletApproveTransaction model
|
|
351
|
+
json_dict = response.json()
|
|
352
|
+
content = EnsoWalletApproveOutput(**json_dict)
|
|
353
|
+
artifact = EnsoWalletApproveArtifact(**json_dict)
|
|
354
|
+
|
|
355
|
+
rpc_url = chain_provider.get_chain_config_by_id(chainId).rpc_url
|
|
356
|
+
contract = EvmContractWrapper(rpc_url, ABI_ERC20, artifact.tx)
|
|
357
|
+
|
|
358
|
+
fn, fn_args = contract.fn_and_args
|
|
359
|
+
fn_args["value"] = str(fn_args["value"])
|
|
360
|
+
|
|
361
|
+
invocation = wallet.invoke_contract(
|
|
362
|
+
contract_address=contract.dst_addr,
|
|
363
|
+
method=fn.fn_name,
|
|
364
|
+
abi=ABI_ERC20,
|
|
365
|
+
args=fn_args,
|
|
366
|
+
).wait()
|
|
367
|
+
|
|
368
|
+
artifact.txHash = invocation.transaction.transaction_hash
|
|
369
|
+
|
|
370
|
+
# Return the parsed response
|
|
371
|
+
return (content, artifact)
|
|
372
|
+
except httpx.RequestError as req_err:
|
|
373
|
+
raise ToolException(
|
|
374
|
+
f"request error from Enso API: {req_err}"
|
|
375
|
+
) from req_err
|
|
376
|
+
except httpx.HTTPStatusError as http_err:
|
|
377
|
+
raise ToolException(
|
|
378
|
+
f"http error from Enso API: {http_err}"
|
|
379
|
+
) from http_err
|
|
380
|
+
except Exception as e:
|
|
381
|
+
raise ToolException(f"error from Enso API: {e}") from e
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# GitHub Skill
|
|
2
|
+
|
|
3
|
+
This skill enables agents to search GitHub for repositories, users, and code using GitHub's public API endpoints.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Search GitHub repositories by name, description, or topics
|
|
8
|
+
- Search GitHub users by username or real name
|
|
9
|
+
- Search code snippets across GitHub repositories
|
|
10
|
+
- No authentication required (uses public API endpoints)
|
|
11
|
+
- Rate limit aware (respects GitHub's public API limits)
|
|
12
|
+
|
|
13
|
+
## Configuration
|
|
14
|
+
|
|
15
|
+
Add the GitHub skill to your agent's configuration:
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
skills:
|
|
19
|
+
github:
|
|
20
|
+
states:
|
|
21
|
+
github_search: public # or private if you want to restrict access
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage Examples
|
|
25
|
+
|
|
26
|
+
The agent can use the GitHub skill to answer questions like:
|
|
27
|
+
|
|
28
|
+
- "Find repositories about blockchain development"
|
|
29
|
+
- "Search for users who work on web3 projects"
|
|
30
|
+
- "Find code examples of smart contracts in Solidity"
|
|
31
|
+
- "Show me popular Python machine learning repositories"
|
|
32
|
+
- "Find developers who contribute to Ethereum"
|
|
33
|
+
|
|
34
|
+
## Rate Limits
|
|
35
|
+
|
|
36
|
+
The skill uses GitHub's public API which has the following rate limits:
|
|
37
|
+
- 60 requests per hour per IP address
|
|
38
|
+
- No authentication required
|
|
39
|
+
- Results are limited to public repositories and users
|
|
40
|
+
|
|
41
|
+
## Implementation Details
|
|
42
|
+
|
|
43
|
+
The skill uses the following GitHub API endpoints:
|
|
44
|
+
- `/search/repositories` - For searching repositories
|
|
45
|
+
- `/search/users` - For searching users
|
|
46
|
+
- `/search/code` - For searching code
|
|
47
|
+
|
|
48
|
+
Each search result includes:
|
|
49
|
+
- For repositories: name, description, language, stars count, and URL
|
|
50
|
+
- For users: username, name, bio, and profile URL
|
|
51
|
+
- For code: repository name, file path, and URL
|
|
52
|
+
|
|
53
|
+
## Error Handling
|
|
54
|
+
|
|
55
|
+
The skill handles various error cases:
|
|
56
|
+
- API rate limits
|
|
57
|
+
- Network errors
|
|
58
|
+
- Invalid queries
|
|
59
|
+
- No results found
|
|
60
|
+
|
|
61
|
+
## Logging
|
|
62
|
+
|
|
63
|
+
All operations are logged with the prefix `github_search.py:` for easy debugging and monitoring.
|