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,107 @@
|
|
|
1
|
+
"""Base classes for portfolio skills."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
from abc import ABC
|
|
6
|
+
from typing import Any, Dict, Type
|
|
7
|
+
|
|
8
|
+
import aiohttp
|
|
9
|
+
from pydantic import BaseModel, Field
|
|
10
|
+
|
|
11
|
+
from intentkit.abstracts.skill import SkillStoreABC
|
|
12
|
+
from intentkit.skills.base import IntentKitSkill, SkillContext
|
|
13
|
+
from intentkit.skills.portfolio.constants import MORALIS_API_BASE_URL
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class PortfolioBaseTool(IntentKitSkill, ABC):
|
|
19
|
+
"""Base class for portfolio analysis skills."""
|
|
20
|
+
|
|
21
|
+
name: str = Field(description="The name of the tool")
|
|
22
|
+
description: str = Field(description="A description of what the tool does")
|
|
23
|
+
args_schema: Type[BaseModel]
|
|
24
|
+
skill_store: SkillStoreABC = Field(
|
|
25
|
+
description="The skill store for persisting data"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
def get_api_key(self, context: SkillContext) -> str:
|
|
29
|
+
skill_config = context.config
|
|
30
|
+
if skill_config.get("api_key_provider") == "agent_owner":
|
|
31
|
+
return skill_config.get("api_key")
|
|
32
|
+
return self.skill_store.get_system_config("moralis_api_key")
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def category(self) -> str:
|
|
36
|
+
return "portfolio"
|
|
37
|
+
|
|
38
|
+
def _prepare_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
|
39
|
+
"""Convert boolean values to lowercase strings for API compatibility.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
params: Dictionary with query parameters that may contain boolean values
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Dictionary with boolean values converted to lowercase strings
|
|
46
|
+
"""
|
|
47
|
+
if not params:
|
|
48
|
+
return params
|
|
49
|
+
|
|
50
|
+
result = {}
|
|
51
|
+
for key, value in params.items():
|
|
52
|
+
if isinstance(value, bool):
|
|
53
|
+
result[key] = str(value).lower()
|
|
54
|
+
else:
|
|
55
|
+
result[key] = value
|
|
56
|
+
return result
|
|
57
|
+
|
|
58
|
+
async def _make_request(
|
|
59
|
+
self,
|
|
60
|
+
method: str,
|
|
61
|
+
endpoint: str,
|
|
62
|
+
api_key: str,
|
|
63
|
+
params: Dict[str, Any] = None,
|
|
64
|
+
data: Dict[str, Any] = None,
|
|
65
|
+
) -> Dict[str, Any]:
|
|
66
|
+
"""Make a request to the Moralis API.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
method: HTTP method (GET, POST, etc.)
|
|
70
|
+
endpoint: API endpoint (without base URL)
|
|
71
|
+
api_key: Moralis API key
|
|
72
|
+
params: Query parameters
|
|
73
|
+
data: Request body data for POST requests
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Response data as dictionary
|
|
77
|
+
"""
|
|
78
|
+
url = f"{MORALIS_API_BASE_URL}{endpoint}"
|
|
79
|
+
|
|
80
|
+
headers = {"accept": "application/json", "X-API-Key": api_key}
|
|
81
|
+
|
|
82
|
+
# Convert boolean params to strings
|
|
83
|
+
processed_params = self._prepare_params(params) if params else None
|
|
84
|
+
|
|
85
|
+
logger.debug(f"portfolio/base.py: Making request to {url}")
|
|
86
|
+
|
|
87
|
+
async with aiohttp.ClientSession() as session:
|
|
88
|
+
async with session.request(
|
|
89
|
+
method=method,
|
|
90
|
+
url=url,
|
|
91
|
+
headers=headers,
|
|
92
|
+
params=processed_params,
|
|
93
|
+
json=data,
|
|
94
|
+
) as response:
|
|
95
|
+
if response.status >= 400:
|
|
96
|
+
error_text = await response.text()
|
|
97
|
+
logger.error(f"portfolio/base.py: API error: {error_text}")
|
|
98
|
+
return {
|
|
99
|
+
"error": f"API error: {response.status}",
|
|
100
|
+
"details": error_text,
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return await response.json()
|
|
104
|
+
|
|
105
|
+
def _run(self, *args: Any, **kwargs: Any) -> Any:
|
|
106
|
+
"""Execute the tool synchronously by running the async version in a loop."""
|
|
107
|
+
return asyncio.run(self._arun(*args, **kwargs))
|
|
Binary file
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"title": "Portfolio Analysis",
|
|
5
|
+
"description": "Access blockchain wallet data and analytics through Moralis APIs for portfolio tracking, token balances, and investment performance",
|
|
6
|
+
"x-icon": "https://ai.service.crestal.dev/skills/portfolio/moralis.png",
|
|
7
|
+
"x-tags": [
|
|
8
|
+
"Blockchain",
|
|
9
|
+
"Web3",
|
|
10
|
+
"Crypto",
|
|
11
|
+
"Portfolio",
|
|
12
|
+
"Wallet"
|
|
13
|
+
],
|
|
14
|
+
"properties": {
|
|
15
|
+
"enabled": {
|
|
16
|
+
"type": "boolean",
|
|
17
|
+
"title": "Enabled",
|
|
18
|
+
"description": "Whether this skill is enabled",
|
|
19
|
+
"default": true
|
|
20
|
+
},
|
|
21
|
+
"states": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"properties": {
|
|
24
|
+
"wallet_history": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"title": "Wallet Transaction History",
|
|
27
|
+
"enum": [
|
|
28
|
+
"disabled",
|
|
29
|
+
"public",
|
|
30
|
+
"private"
|
|
31
|
+
],
|
|
32
|
+
"x-enum-title": [
|
|
33
|
+
"Disabled",
|
|
34
|
+
"Agent Owner + All Users",
|
|
35
|
+
"Agent Owner Only"
|
|
36
|
+
],
|
|
37
|
+
"description": "Retrieve the full transaction history of a specified wallet address",
|
|
38
|
+
"default": "private"
|
|
39
|
+
},
|
|
40
|
+
"token_balances": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"title": "Token Balances",
|
|
43
|
+
"enum": [
|
|
44
|
+
"disabled",
|
|
45
|
+
"public",
|
|
46
|
+
"private"
|
|
47
|
+
],
|
|
48
|
+
"x-enum-title": [
|
|
49
|
+
"Disabled",
|
|
50
|
+
"Agent Owner + All Users",
|
|
51
|
+
"Agent Owner Only"
|
|
52
|
+
],
|
|
53
|
+
"description": "Get token balances for a specific wallet address and their token prices in USD",
|
|
54
|
+
"default": "private"
|
|
55
|
+
},
|
|
56
|
+
"wallet_approvals": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"title": "Wallet Approvals",
|
|
59
|
+
"enum": [
|
|
60
|
+
"disabled",
|
|
61
|
+
"public",
|
|
62
|
+
"private"
|
|
63
|
+
],
|
|
64
|
+
"x-enum-title": [
|
|
65
|
+
"Disabled",
|
|
66
|
+
"Agent Owner + All Users",
|
|
67
|
+
"Agent Owner Only"
|
|
68
|
+
],
|
|
69
|
+
"description": "Retrieve active ERC20 token approvals for a specified wallet address",
|
|
70
|
+
"default": "disabled"
|
|
71
|
+
},
|
|
72
|
+
"wallet_swaps": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"title": "Wallet Swaps",
|
|
75
|
+
"enum": [
|
|
76
|
+
"disabled",
|
|
77
|
+
"public",
|
|
78
|
+
"private"
|
|
79
|
+
],
|
|
80
|
+
"x-enum-title": [
|
|
81
|
+
"Disabled",
|
|
82
|
+
"Agent Owner + All Users",
|
|
83
|
+
"Agent Owner Only"
|
|
84
|
+
],
|
|
85
|
+
"description": "Get all swap-related transactions (buy, sell) for a wallet address",
|
|
86
|
+
"default": "disabled"
|
|
87
|
+
},
|
|
88
|
+
"wallet_net_worth": {
|
|
89
|
+
"type": "string",
|
|
90
|
+
"title": "Wallet Net Worth",
|
|
91
|
+
"enum": [
|
|
92
|
+
"disabled",
|
|
93
|
+
"public",
|
|
94
|
+
"private"
|
|
95
|
+
],
|
|
96
|
+
"x-enum-title": [
|
|
97
|
+
"Disabled",
|
|
98
|
+
"Agent Owner + All Users",
|
|
99
|
+
"Agent Owner Only"
|
|
100
|
+
],
|
|
101
|
+
"description": "Get the net worth of a wallet in USD across multiple chains",
|
|
102
|
+
"default": "private"
|
|
103
|
+
},
|
|
104
|
+
"wallet_profitability_summary": {
|
|
105
|
+
"type": "string",
|
|
106
|
+
"title": "Wallet Profitability Summary",
|
|
107
|
+
"enum": [
|
|
108
|
+
"disabled",
|
|
109
|
+
"public",
|
|
110
|
+
"private"
|
|
111
|
+
],
|
|
112
|
+
"x-enum-title": [
|
|
113
|
+
"Disabled",
|
|
114
|
+
"Agent Owner + All Users",
|
|
115
|
+
"Agent Owner Only"
|
|
116
|
+
],
|
|
117
|
+
"description": "Retrieve a summary of wallet profitability",
|
|
118
|
+
"default": "private"
|
|
119
|
+
},
|
|
120
|
+
"wallet_profitability": {
|
|
121
|
+
"type": "string",
|
|
122
|
+
"title": "Wallet Profitability Breakdown",
|
|
123
|
+
"enum": [
|
|
124
|
+
"disabled",
|
|
125
|
+
"public",
|
|
126
|
+
"private"
|
|
127
|
+
],
|
|
128
|
+
"x-enum-title": [
|
|
129
|
+
"Disabled",
|
|
130
|
+
"Agent Owner + All Users",
|
|
131
|
+
"Agent Owner Only"
|
|
132
|
+
],
|
|
133
|
+
"description": "Retrieve detailed profitability breakdown for a wallet",
|
|
134
|
+
"default": "private"
|
|
135
|
+
},
|
|
136
|
+
"wallet_stats": {
|
|
137
|
+
"type": "string",
|
|
138
|
+
"title": "Wallet Stats",
|
|
139
|
+
"enum": [
|
|
140
|
+
"disabled",
|
|
141
|
+
"public",
|
|
142
|
+
"private"
|
|
143
|
+
],
|
|
144
|
+
"x-enum-title": [
|
|
145
|
+
"Disabled",
|
|
146
|
+
"Agent Owner + All Users",
|
|
147
|
+
"Agent Owner Only"
|
|
148
|
+
],
|
|
149
|
+
"description": "Get statistical information about a wallet",
|
|
150
|
+
"default": "disabled"
|
|
151
|
+
},
|
|
152
|
+
"wallet_defi_positions": {
|
|
153
|
+
"type": "string",
|
|
154
|
+
"title": "Wallet DeFi Positions",
|
|
155
|
+
"enum": [
|
|
156
|
+
"disabled",
|
|
157
|
+
"public",
|
|
158
|
+
"private"
|
|
159
|
+
],
|
|
160
|
+
"x-enum-title": [
|
|
161
|
+
"Disabled",
|
|
162
|
+
"Agent Owner + All Users",
|
|
163
|
+
"Agent Owner Only"
|
|
164
|
+
],
|
|
165
|
+
"description": "Get the positions summary of a wallet address",
|
|
166
|
+
"default": "disabled"
|
|
167
|
+
},
|
|
168
|
+
"wallet_nfts": {
|
|
169
|
+
"type": "string",
|
|
170
|
+
"title": "Wallet NFTs",
|
|
171
|
+
"enum": [
|
|
172
|
+
"disabled",
|
|
173
|
+
"public",
|
|
174
|
+
"private"
|
|
175
|
+
],
|
|
176
|
+
"x-enum-title": [
|
|
177
|
+
"Disabled",
|
|
178
|
+
"Agent Owner + All Users",
|
|
179
|
+
"Agent Owner Only"
|
|
180
|
+
],
|
|
181
|
+
"description": "Get NFTs owned by a given wallet address",
|
|
182
|
+
"default": "disabled"
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"description": "States for each portfolio blockchain analysis skill (disabled, public, or private)"
|
|
186
|
+
},
|
|
187
|
+
"api_key_provider": {
|
|
188
|
+
"type": "string",
|
|
189
|
+
"title": "API Key Provider",
|
|
190
|
+
"description": "Provider of the API key",
|
|
191
|
+
"enum": [
|
|
192
|
+
"platform",
|
|
193
|
+
"agent_owner"
|
|
194
|
+
],
|
|
195
|
+
"x-enum-title": [
|
|
196
|
+
"Nation Hosted",
|
|
197
|
+
"Owner Provided"
|
|
198
|
+
],
|
|
199
|
+
"default": "platform"
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
"required": [
|
|
203
|
+
"states",
|
|
204
|
+
"enabled"
|
|
205
|
+
],
|
|
206
|
+
"if": {
|
|
207
|
+
"properties": {
|
|
208
|
+
"api_key_provider": {
|
|
209
|
+
"const": "agent_owner"
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
"then": {
|
|
214
|
+
"properties": {
|
|
215
|
+
"api_key": {
|
|
216
|
+
"type": "string",
|
|
217
|
+
"title": "Moralis API Key",
|
|
218
|
+
"description": "API key for Moralis API service",
|
|
219
|
+
"x-link": "[Get your API key](https://moralis.io/)",
|
|
220
|
+
"x-sensitive": true
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
"if": {
|
|
224
|
+
"properties": {
|
|
225
|
+
"enabled": {
|
|
226
|
+
"const": true
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
"then": {
|
|
231
|
+
"required": [
|
|
232
|
+
"api_key"
|
|
233
|
+
]
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
"additionalProperties": true
|
|
237
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any, Dict, List, Optional, Type
|
|
3
|
+
|
|
4
|
+
from langchain_core.runnables import RunnableConfig
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
from intentkit.skills.portfolio.base import PortfolioBaseTool
|
|
8
|
+
from intentkit.skills.portfolio.constants import (
|
|
9
|
+
DEFAULT_CHAIN,
|
|
10
|
+
DEFAULT_LIMIT,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TokenBalancesInput(BaseModel):
|
|
17
|
+
"""Input for token balances tool."""
|
|
18
|
+
|
|
19
|
+
address: str = Field(description="The wallet address to check token balances for.")
|
|
20
|
+
chain: str = Field(
|
|
21
|
+
description="The chain to query (e.g., 'eth', 'bsc', 'polygon').",
|
|
22
|
+
default=DEFAULT_CHAIN,
|
|
23
|
+
)
|
|
24
|
+
to_block: Optional[int] = Field(
|
|
25
|
+
description="The block number up to which the balances will be checked.",
|
|
26
|
+
default=None,
|
|
27
|
+
)
|
|
28
|
+
token_addresses: Optional[List[str]] = Field(
|
|
29
|
+
description="The specific token addresses to get balances for.",
|
|
30
|
+
default=None,
|
|
31
|
+
)
|
|
32
|
+
exclude_spam: Optional[bool] = Field(
|
|
33
|
+
description="Exclude spam tokens from the result.",
|
|
34
|
+
default=True,
|
|
35
|
+
)
|
|
36
|
+
exclude_unverified_contracts: Optional[bool] = Field(
|
|
37
|
+
description="Exclude unverified contracts from the result.",
|
|
38
|
+
default=True,
|
|
39
|
+
)
|
|
40
|
+
cursor: Optional[str] = Field(
|
|
41
|
+
description="The cursor for pagination.",
|
|
42
|
+
default=None,
|
|
43
|
+
)
|
|
44
|
+
limit: Optional[int] = Field(
|
|
45
|
+
description="The number of results per page.",
|
|
46
|
+
default=DEFAULT_LIMIT,
|
|
47
|
+
)
|
|
48
|
+
exclude_native: Optional[bool] = Field(
|
|
49
|
+
description="Exclude native balance from the result.",
|
|
50
|
+
default=None,
|
|
51
|
+
)
|
|
52
|
+
max_token_inactivity: Optional[int] = Field(
|
|
53
|
+
description="Exclude tokens inactive for more than the given amount of days.",
|
|
54
|
+
default=None,
|
|
55
|
+
)
|
|
56
|
+
min_pair_side_liquidity_usd: Optional[float] = Field(
|
|
57
|
+
description="Exclude tokens with liquidity less than the specified amount in USD.",
|
|
58
|
+
default=None,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class TokenBalances(PortfolioBaseTool):
|
|
63
|
+
"""Tool for retrieving native and ERC20 token balances using Moralis.
|
|
64
|
+
|
|
65
|
+
This tool uses Moralis' API to fetch token balances for a specific wallet address
|
|
66
|
+
and their token prices in USD.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
name: str = "portfolio_token_balances"
|
|
70
|
+
description: str = (
|
|
71
|
+
"Get token balances for a specific wallet address and their token prices in USD. "
|
|
72
|
+
"Includes options to exclude spam and unverified contracts."
|
|
73
|
+
)
|
|
74
|
+
args_schema: Type[BaseModel] = TokenBalancesInput
|
|
75
|
+
|
|
76
|
+
async def _arun(
|
|
77
|
+
self,
|
|
78
|
+
address: str,
|
|
79
|
+
chain: str = DEFAULT_CHAIN,
|
|
80
|
+
to_block: Optional[int] = None,
|
|
81
|
+
token_addresses: Optional[List[str]] = None,
|
|
82
|
+
exclude_spam: Optional[bool] = True,
|
|
83
|
+
exclude_unverified_contracts: Optional[bool] = True,
|
|
84
|
+
cursor: Optional[str] = None,
|
|
85
|
+
limit: Optional[int] = DEFAULT_LIMIT,
|
|
86
|
+
exclude_native: Optional[bool] = None,
|
|
87
|
+
max_token_inactivity: Optional[int] = None,
|
|
88
|
+
min_pair_side_liquidity_usd: Optional[float] = None,
|
|
89
|
+
config: RunnableConfig = None,
|
|
90
|
+
**kwargs,
|
|
91
|
+
) -> Dict[str, Any]:
|
|
92
|
+
"""Fetch token balances from Moralis.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
address: The wallet address to get balances for
|
|
96
|
+
chain: The blockchain to query
|
|
97
|
+
to_block: Block number up to which balances will be checked
|
|
98
|
+
token_addresses: Specific token addresses to get balances for
|
|
99
|
+
exclude_spam: Whether to exclude spam tokens
|
|
100
|
+
exclude_unverified_contracts: Whether to exclude unverified contracts
|
|
101
|
+
cursor: Pagination cursor
|
|
102
|
+
limit: Number of results per page
|
|
103
|
+
exclude_native: Whether to exclude native balance
|
|
104
|
+
max_token_inactivity: Exclude tokens inactive for more than the given days
|
|
105
|
+
min_pair_side_liquidity_usd: Exclude tokens with liquidity less than specified
|
|
106
|
+
config: The configuration for the tool call
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Dict containing token balances data
|
|
110
|
+
"""
|
|
111
|
+
context = self.context_from_config(config)
|
|
112
|
+
logger.debug(
|
|
113
|
+
f"token_balances.py: Fetching token balances with context {context}"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Get the API key from the agent's configuration
|
|
117
|
+
api_key = self.get_api_key(context)
|
|
118
|
+
if not api_key:
|
|
119
|
+
return {"error": "No Moralis API key provided in the configuration."}
|
|
120
|
+
|
|
121
|
+
# Build query parameters
|
|
122
|
+
params = {
|
|
123
|
+
"chain": chain,
|
|
124
|
+
"limit": limit,
|
|
125
|
+
"exclude_spam": exclude_spam,
|
|
126
|
+
"exclude_unverified_contracts": exclude_unverified_contracts,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
# Add optional parameters if they exist
|
|
130
|
+
if to_block:
|
|
131
|
+
params["to_block"] = to_block
|
|
132
|
+
if token_addresses:
|
|
133
|
+
params["token_addresses"] = token_addresses
|
|
134
|
+
if cursor:
|
|
135
|
+
params["cursor"] = cursor
|
|
136
|
+
if exclude_native is not None:
|
|
137
|
+
params["exclude_native"] = exclude_native
|
|
138
|
+
if max_token_inactivity:
|
|
139
|
+
params["max_token_inactivity"] = max_token_inactivity
|
|
140
|
+
if min_pair_side_liquidity_usd:
|
|
141
|
+
params["min_pair_side_liquidity_usd"] = min_pair_side_liquidity_usd
|
|
142
|
+
|
|
143
|
+
# Call Moralis API
|
|
144
|
+
try:
|
|
145
|
+
endpoint = f"/wallets/{address}/tokens"
|
|
146
|
+
return await self._make_request(
|
|
147
|
+
method="GET", endpoint=endpoint, api_key=api_key, params=params
|
|
148
|
+
)
|
|
149
|
+
except Exception as e:
|
|
150
|
+
logger.error(
|
|
151
|
+
f"token_balances.py: Error fetching token balances: {e}", exc_info=True
|
|
152
|
+
)
|
|
153
|
+
return {
|
|
154
|
+
"error": "An error occurred while fetching token balances. Please try again later."
|
|
155
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any, Dict, Optional, Type
|
|
3
|
+
|
|
4
|
+
from langchain_core.runnables import RunnableConfig
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
from intentkit.skills.portfolio.base import PortfolioBaseTool
|
|
8
|
+
from intentkit.skills.portfolio.constants import (
|
|
9
|
+
DEFAULT_CHAIN,
|
|
10
|
+
DEFAULT_LIMIT,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class WalletApprovalsInput(BaseModel):
|
|
17
|
+
"""Input for wallet token approvals tool."""
|
|
18
|
+
|
|
19
|
+
address: str = Field(description="The wallet address to check token approvals for.")
|
|
20
|
+
chain: str = Field(
|
|
21
|
+
description="The chain to query (e.g., 'eth', 'bsc', 'polygon').",
|
|
22
|
+
default=DEFAULT_CHAIN,
|
|
23
|
+
)
|
|
24
|
+
cursor: Optional[str] = Field(
|
|
25
|
+
description="The cursor for pagination.",
|
|
26
|
+
default=None,
|
|
27
|
+
)
|
|
28
|
+
limit: Optional[int] = Field(
|
|
29
|
+
description="The number of results per page.",
|
|
30
|
+
default=DEFAULT_LIMIT,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class WalletApprovals(PortfolioBaseTool):
|
|
35
|
+
"""Tool for retrieving token approvals for a wallet using Moralis.
|
|
36
|
+
|
|
37
|
+
This tool uses Moralis' API to fetch active ERC20 token approvals for the
|
|
38
|
+
specified wallet address.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
name: str = "portfolio_wallet_approvals"
|
|
42
|
+
description: str = (
|
|
43
|
+
"Retrieve active ERC20 token approvals for the specified wallet address. "
|
|
44
|
+
"This helps identify which contracts have permission to spend tokens."
|
|
45
|
+
)
|
|
46
|
+
args_schema: Type[BaseModel] = WalletApprovalsInput
|
|
47
|
+
|
|
48
|
+
async def _arun(
|
|
49
|
+
self,
|
|
50
|
+
address: str,
|
|
51
|
+
chain: str = DEFAULT_CHAIN,
|
|
52
|
+
cursor: Optional[str] = None,
|
|
53
|
+
limit: Optional[int] = DEFAULT_LIMIT,
|
|
54
|
+
config: RunnableConfig = None,
|
|
55
|
+
**kwargs,
|
|
56
|
+
) -> Dict[str, Any]:
|
|
57
|
+
"""Fetch wallet token approvals from Moralis.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
address: The wallet address to get approvals for
|
|
61
|
+
chain: The blockchain to query
|
|
62
|
+
cursor: Pagination cursor
|
|
63
|
+
limit: Number of results per page
|
|
64
|
+
config: The configuration for the tool call
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Dict containing wallet approvals data
|
|
68
|
+
"""
|
|
69
|
+
context = self.context_from_config(config)
|
|
70
|
+
logger.debug(
|
|
71
|
+
f"wallet_approvals.py: Fetching wallet approvals with context {context}"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Get the API key from the agent's configuration
|
|
75
|
+
api_key = self.get_api_key(context)
|
|
76
|
+
if not api_key:
|
|
77
|
+
return {"error": "No Moralis API key provided in the configuration."}
|
|
78
|
+
|
|
79
|
+
# Build query parameters
|
|
80
|
+
params = {
|
|
81
|
+
"chain": chain,
|
|
82
|
+
"limit": limit,
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# Add optional parameters if they exist
|
|
86
|
+
if cursor:
|
|
87
|
+
params["cursor"] = cursor
|
|
88
|
+
|
|
89
|
+
# Call Moralis API
|
|
90
|
+
try:
|
|
91
|
+
endpoint = f"/wallets/{address}/approvals"
|
|
92
|
+
return await self._make_request(
|
|
93
|
+
method="GET", endpoint=endpoint, api_key=api_key, params=params
|
|
94
|
+
)
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logger.error(
|
|
97
|
+
f"wallet_approvals.py: Error fetching wallet approvals: {e}",
|
|
98
|
+
exc_info=True,
|
|
99
|
+
)
|
|
100
|
+
return {
|
|
101
|
+
"error": "An error occurred while fetching wallet approvals. Please try again later."
|
|
102
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any, Dict, Type
|
|
3
|
+
|
|
4
|
+
from langchain_core.runnables import RunnableConfig
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
from intentkit.skills.portfolio.base import PortfolioBaseTool
|
|
8
|
+
from intentkit.skills.portfolio.constants import DEFAULT_CHAIN
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class WalletDefiPositionsInput(BaseModel):
|
|
14
|
+
"""Input for wallet DeFi positions tool."""
|
|
15
|
+
|
|
16
|
+
address: str = Field(description="The wallet address to get DeFi positions for.")
|
|
17
|
+
chain: str = Field(
|
|
18
|
+
description="The chain to query (e.g., 'eth', 'bsc', 'polygon').",
|
|
19
|
+
default=DEFAULT_CHAIN,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class WalletDefiPositions(PortfolioBaseTool):
|
|
24
|
+
"""Tool for retrieving DeFi positions by wallet using Moralis.
|
|
25
|
+
|
|
26
|
+
This tool uses Moralis' API to fetch the positions summary of a wallet address,
|
|
27
|
+
including liquidity positions, staking, lending, and other DeFi activities.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
name: str = "portfolio_wallet_defi_positions"
|
|
31
|
+
description: str = (
|
|
32
|
+
"Get the DeFi positions summary of a wallet address. "
|
|
33
|
+
"Returns information about liquidity positions, staking, lending, and other DeFi activities."
|
|
34
|
+
)
|
|
35
|
+
args_schema: Type[BaseModel] = WalletDefiPositionsInput
|
|
36
|
+
|
|
37
|
+
async def _arun(
|
|
38
|
+
self,
|
|
39
|
+
address: str,
|
|
40
|
+
chain: str = DEFAULT_CHAIN,
|
|
41
|
+
config: RunnableConfig = None,
|
|
42
|
+
**kwargs,
|
|
43
|
+
) -> Dict[str, Any]:
|
|
44
|
+
"""Fetch wallet DeFi positions from Moralis.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
address: The wallet address
|
|
48
|
+
chain: The blockchain to query
|
|
49
|
+
config: The configuration for the tool call
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Dict containing DeFi positions data
|
|
53
|
+
"""
|
|
54
|
+
context = self.context_from_config(config)
|
|
55
|
+
logger.debug(
|
|
56
|
+
f"wallet_defi_positions.py: Fetching wallet DeFi positions with context {context}"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Get the API key from the agent's configuration
|
|
60
|
+
api_key = context.config.get("api_key")
|
|
61
|
+
if not api_key:
|
|
62
|
+
return {"error": "No Moralis API key provided in the configuration."}
|
|
63
|
+
|
|
64
|
+
# Build query parameters
|
|
65
|
+
params = {"chain": chain}
|
|
66
|
+
|
|
67
|
+
# Call Moralis API
|
|
68
|
+
try:
|
|
69
|
+
endpoint = f"/wallets/{address}/defi/positions"
|
|
70
|
+
return await self._make_request(
|
|
71
|
+
method="GET", endpoint=endpoint, api_key=api_key, params=params
|
|
72
|
+
)
|
|
73
|
+
except Exception as e:
|
|
74
|
+
logger.error(
|
|
75
|
+
f"wallet_defi_positions.py: Error fetching wallet DeFi positions: {e}",
|
|
76
|
+
exc_info=True,
|
|
77
|
+
)
|
|
78
|
+
return {
|
|
79
|
+
"error": "An error occurred while fetching wallet DeFi positions. Please try again later."
|
|
80
|
+
}
|