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,301 @@
|
|
|
1
|
+
"""fetching a complete wallet portfolio (EVM + Solana)."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Dict, List, Optional, Type
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
from intentkit.skills.moralis.api import (
|
|
9
|
+
fetch_net_worth,
|
|
10
|
+
fetch_wallet_balances,
|
|
11
|
+
get_solana_balance,
|
|
12
|
+
get_solana_portfolio,
|
|
13
|
+
get_solana_spl_tokens,
|
|
14
|
+
get_token_price,
|
|
15
|
+
)
|
|
16
|
+
from intentkit.skills.moralis.base import CHAIN_MAPPING, WalletBaseTool
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class FetchWalletPortfolioInput(BaseModel):
|
|
22
|
+
"""Input for FetchWalletPortfolio tool."""
|
|
23
|
+
|
|
24
|
+
address: str = Field(
|
|
25
|
+
..., description="Wallet address to analyze (Ethereum or Solana)"
|
|
26
|
+
)
|
|
27
|
+
chains: Optional[List[int]] = Field(
|
|
28
|
+
default=None,
|
|
29
|
+
description="List of EVM chain IDs to check (default: all supported)",
|
|
30
|
+
)
|
|
31
|
+
include_solana: bool = Field(
|
|
32
|
+
default=True, description="Whether to include Solana in the analysis"
|
|
33
|
+
)
|
|
34
|
+
solana_network: str = Field(
|
|
35
|
+
default="mainnet", description="Solana network to use (mainnet or devnet)"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class TokenBalance(BaseModel):
|
|
40
|
+
"""Model for token balance."""
|
|
41
|
+
|
|
42
|
+
symbol: str
|
|
43
|
+
name: str
|
|
44
|
+
balance: float
|
|
45
|
+
usd_value: float
|
|
46
|
+
chain: str
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class PortfolioOutput(BaseModel):
|
|
50
|
+
"""Output for FetchWalletPortfolio tool."""
|
|
51
|
+
|
|
52
|
+
address: str
|
|
53
|
+
total_net_worth: float
|
|
54
|
+
chains: Dict[str, float]
|
|
55
|
+
tokens: List[TokenBalance]
|
|
56
|
+
error: Optional[str] = None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class FetchWalletPortfolio(WalletBaseTool):
|
|
60
|
+
"""Tool for fetching a complete wallet portfolio across all chains (EVM + Solana).
|
|
61
|
+
|
|
62
|
+
This tool retrieves detailed information about a wallet's holdings across
|
|
63
|
+
multiple blockchains, including token balances, USD values, and a summary
|
|
64
|
+
of the total portfolio value.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
name: str = "moralis_fetch_wallet_portfolio"
|
|
68
|
+
description: str = (
|
|
69
|
+
"Get comprehensive portfolio data for a wallet including:\n"
|
|
70
|
+
"- Token balances and prices across multiple chains (EVM and Solana)\n"
|
|
71
|
+
"- Total net worth estimation\n"
|
|
72
|
+
"- Chain distribution of assets\n"
|
|
73
|
+
"Use this tool whenever the user asks about their crypto holdings, portfolio value, "
|
|
74
|
+
"or wallet contents across multiple blockchains."
|
|
75
|
+
)
|
|
76
|
+
args_schema: Type[BaseModel] = FetchWalletPortfolioInput
|
|
77
|
+
|
|
78
|
+
async def _arun(
|
|
79
|
+
self,
|
|
80
|
+
address: str,
|
|
81
|
+
chains: Optional[List[int]] = None,
|
|
82
|
+
include_solana: bool = True,
|
|
83
|
+
solana_network: str = "mainnet",
|
|
84
|
+
**kwargs,
|
|
85
|
+
) -> PortfolioOutput:
|
|
86
|
+
"""Fetch wallet portfolio data across multiple chains.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
address: Wallet address to fetch portfolio for
|
|
90
|
+
chains: List of EVM chain IDs to check (if None, checks all supported chains)
|
|
91
|
+
include_solana: Whether to include Solana in the analysis
|
|
92
|
+
solana_network: Solana network to use (mainnet or devnet)
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
PortfolioOutput containing the wallet's portfolio data
|
|
96
|
+
"""
|
|
97
|
+
try:
|
|
98
|
+
# Initialize portfolio data
|
|
99
|
+
portfolio = {"tokens": [], "chains": {}, "total_net_worth": 0}
|
|
100
|
+
|
|
101
|
+
# Get EVM chain portfolio
|
|
102
|
+
await self._fetch_evm_portfolio(address, chains, portfolio)
|
|
103
|
+
|
|
104
|
+
# Get Solana portfolio if requested
|
|
105
|
+
if include_solana:
|
|
106
|
+
await self._fetch_solana_portfolio(address, solana_network, portfolio)
|
|
107
|
+
|
|
108
|
+
return PortfolioOutput(
|
|
109
|
+
address=address,
|
|
110
|
+
total_net_worth=portfolio["total_net_worth"],
|
|
111
|
+
chains=portfolio["chains"],
|
|
112
|
+
tokens=portfolio["tokens"],
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
except Exception as e:
|
|
116
|
+
logger.error(f"Error fetching wallet portfolio: {str(e)}")
|
|
117
|
+
return PortfolioOutput(
|
|
118
|
+
address=address, total_net_worth=0, chains={}, tokens=[], error=str(e)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
async def _fetch_evm_portfolio(
|
|
122
|
+
self, address: str, chains: Optional[List[int]], portfolio: Dict
|
|
123
|
+
) -> None:
|
|
124
|
+
"""Fetch portfolio data for EVM chains.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
address: Wallet address to fetch portfolio for
|
|
128
|
+
chains: List of EVM chain IDs to check (if None, checks all supported chains)
|
|
129
|
+
portfolio: Portfolio data to update
|
|
130
|
+
"""
|
|
131
|
+
# Get chain IDs to query (use all supported chains if not specified)
|
|
132
|
+
chain_ids = chains or list(CHAIN_MAPPING.keys())
|
|
133
|
+
|
|
134
|
+
# Get balances for each chain
|
|
135
|
+
for chain_id in chain_ids:
|
|
136
|
+
balance_data = await fetch_wallet_balances(self.api_key, address, chain_id)
|
|
137
|
+
|
|
138
|
+
if "error" in balance_data:
|
|
139
|
+
continue
|
|
140
|
+
|
|
141
|
+
chain_name = self._get_chain_name(chain_id)
|
|
142
|
+
chain_total = 0
|
|
143
|
+
|
|
144
|
+
for token in balance_data.get("result", []):
|
|
145
|
+
if token.get("usd_value"):
|
|
146
|
+
portfolio["tokens"].append(
|
|
147
|
+
TokenBalance(
|
|
148
|
+
symbol=token.get("symbol", "UNKNOWN"),
|
|
149
|
+
name=token.get("name", "Unknown Token"),
|
|
150
|
+
balance=float(token.get("balance_formatted", 0)),
|
|
151
|
+
usd_value=token["usd_value"],
|
|
152
|
+
chain=chain_name,
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
chain_total += token["usd_value"]
|
|
156
|
+
|
|
157
|
+
portfolio["chains"][chain_name] = chain_total
|
|
158
|
+
portfolio["total_net_worth"] += chain_total
|
|
159
|
+
|
|
160
|
+
# Add net worth data if available
|
|
161
|
+
net_worth = await fetch_net_worth(self.api_key, address)
|
|
162
|
+
if "result" in net_worth:
|
|
163
|
+
portfolio["total_net_worth"] = net_worth["result"].get(
|
|
164
|
+
"total_networth_usd", portfolio["total_net_worth"]
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
async def _fetch_solana_portfolio(
|
|
168
|
+
self, address: str, network: str, portfolio: Dict
|
|
169
|
+
) -> None:
|
|
170
|
+
"""Fetch portfolio data for Solana.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
address: Wallet address to fetch portfolio for
|
|
174
|
+
network: Solana network to use (mainnet or devnet)
|
|
175
|
+
portfolio: Portfolio data to update
|
|
176
|
+
"""
|
|
177
|
+
chain_name = "solana"
|
|
178
|
+
chain_total = 0
|
|
179
|
+
|
|
180
|
+
# Try to get complete portfolio
|
|
181
|
+
sol_portfolio = await get_solana_portfolio(self.api_key, address, network)
|
|
182
|
+
|
|
183
|
+
if "error" not in sol_portfolio:
|
|
184
|
+
# Process native SOL balance
|
|
185
|
+
if "nativeBalance" in sol_portfolio:
|
|
186
|
+
sol_balance = float(sol_portfolio["nativeBalance"].get("solana", 0))
|
|
187
|
+
|
|
188
|
+
# Get SOL price
|
|
189
|
+
sol_price_result = await get_token_price(
|
|
190
|
+
self.api_key,
|
|
191
|
+
"So11111111111111111111111111111111111111112", # SOL mint address
|
|
192
|
+
network,
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
sol_price_usd = 0
|
|
196
|
+
if "error" not in sol_price_result:
|
|
197
|
+
sol_price_usd = float(sol_price_result.get("usdPrice", 0))
|
|
198
|
+
|
|
199
|
+
sol_value_usd = sol_balance * sol_price_usd
|
|
200
|
+
chain_total += sol_value_usd
|
|
201
|
+
|
|
202
|
+
# Add SOL to tokens
|
|
203
|
+
portfolio["tokens"].append(
|
|
204
|
+
TokenBalance(
|
|
205
|
+
symbol="SOL",
|
|
206
|
+
name="Solana",
|
|
207
|
+
balance=sol_balance,
|
|
208
|
+
usd_value=sol_value_usd,
|
|
209
|
+
chain=chain_name,
|
|
210
|
+
)
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
# Process SPL tokens
|
|
214
|
+
for token in sol_portfolio.get("tokens", []):
|
|
215
|
+
token_balance = {
|
|
216
|
+
"symbol": token.get("symbol", "UNKNOWN"),
|
|
217
|
+
"name": token.get("name", "Unknown Token"),
|
|
218
|
+
"balance": float(token.get("amount", 0)),
|
|
219
|
+
"usd_value": 0, # Will update if price is available
|
|
220
|
+
"chain": chain_name,
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
# Try to get token price
|
|
224
|
+
if token.get("mint"):
|
|
225
|
+
price_result = await get_token_price(
|
|
226
|
+
self.api_key, token["mint"], network
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
if "error" not in price_result:
|
|
230
|
+
token_price_usd = float(price_result.get("usdPrice", 0))
|
|
231
|
+
token_balance["usd_value"] = (
|
|
232
|
+
token_balance["balance"] * token_price_usd
|
|
233
|
+
)
|
|
234
|
+
chain_total += token_balance["usd_value"]
|
|
235
|
+
|
|
236
|
+
portfolio["tokens"].append(TokenBalance(**token_balance))
|
|
237
|
+
else:
|
|
238
|
+
# If portfolio endpoint fails, try to fetch balance and tokens separately
|
|
239
|
+
sol_balance_result = await get_solana_balance(
|
|
240
|
+
self.api_key, address, network
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
if "error" not in sol_balance_result:
|
|
244
|
+
sol_balance = float(sol_balance_result.get("solana", 0))
|
|
245
|
+
|
|
246
|
+
# Get SOL price
|
|
247
|
+
sol_price_result = await get_token_price(
|
|
248
|
+
self.api_key,
|
|
249
|
+
"So11111111111111111111111111111111111111112", # SOL mint address
|
|
250
|
+
network,
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
sol_price_usd = 0
|
|
254
|
+
if "error" not in sol_price_result:
|
|
255
|
+
sol_price_usd = float(sol_price_result.get("usdPrice", 0))
|
|
256
|
+
|
|
257
|
+
sol_value_usd = sol_balance * sol_price_usd
|
|
258
|
+
chain_total += sol_value_usd
|
|
259
|
+
|
|
260
|
+
# Add SOL to tokens
|
|
261
|
+
portfolio["tokens"].append(
|
|
262
|
+
TokenBalance(
|
|
263
|
+
symbol="SOL",
|
|
264
|
+
name="Solana",
|
|
265
|
+
balance=sol_balance,
|
|
266
|
+
usd_value=sol_value_usd,
|
|
267
|
+
chain=chain_name,
|
|
268
|
+
)
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
# Get SPL tokens
|
|
272
|
+
tokens_result = await get_solana_spl_tokens(self.api_key, address, network)
|
|
273
|
+
|
|
274
|
+
if "error" not in tokens_result and isinstance(tokens_result, list):
|
|
275
|
+
for token in tokens_result:
|
|
276
|
+
token_balance = {
|
|
277
|
+
"symbol": token.get("symbol", "UNKNOWN"),
|
|
278
|
+
"name": token.get("name", "Unknown Token"),
|
|
279
|
+
"balance": float(token.get("amount", 0)),
|
|
280
|
+
"usd_value": 0, # Will update if price is available
|
|
281
|
+
"chain": chain_name,
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
# Try to get token price
|
|
285
|
+
if token.get("mint"):
|
|
286
|
+
price_result = await get_token_price(
|
|
287
|
+
self.api_key, token["mint"], network
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
if "error" not in price_result:
|
|
291
|
+
token_price_usd = float(price_result.get("usdPrice", 0))
|
|
292
|
+
token_balance["usd_value"] = (
|
|
293
|
+
token_balance["balance"] * token_price_usd
|
|
294
|
+
)
|
|
295
|
+
chain_total += token_balance["usd_value"]
|
|
296
|
+
|
|
297
|
+
portfolio["tokens"].append(TokenBalance(**token_balance))
|
|
298
|
+
|
|
299
|
+
# Update chain total and net worth
|
|
300
|
+
portfolio["chains"][chain_name] = chain_total
|
|
301
|
+
portfolio["total_net_worth"] += chain_total
|
|
Binary file
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"title": "Moralis",
|
|
5
|
+
"x-icon": "https://ai.service.crestal.dev/skills/moralis/moralis.png",
|
|
6
|
+
"description": "Comprehensive blockchain data access via Moralis API providing wallet portfolio information, NFT data, and transaction details across multiple EVM chains and Solana networks",
|
|
7
|
+
"properties": {
|
|
8
|
+
"enabled": {
|
|
9
|
+
"type": "boolean",
|
|
10
|
+
"title": "Enabled",
|
|
11
|
+
"description": "Whether this skill is enabled",
|
|
12
|
+
"default": false
|
|
13
|
+
},
|
|
14
|
+
"states": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"title": "Skill States",
|
|
17
|
+
"description": "States for each skill (disabled, public, or private)",
|
|
18
|
+
"properties": {
|
|
19
|
+
"fetch_wallet_portfolio": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"title": "Fetch Wallet Portfolio",
|
|
22
|
+
"enum": [
|
|
23
|
+
"disabled",
|
|
24
|
+
"public",
|
|
25
|
+
"private"
|
|
26
|
+
],
|
|
27
|
+
"x-enum-title": [
|
|
28
|
+
"Disabled",
|
|
29
|
+
"Agent Owner + All Users",
|
|
30
|
+
"Agent Owner Only"
|
|
31
|
+
],
|
|
32
|
+
"description": "Fetches a complete wallet portfolio across all chains (EVM + Solana), retrieving detailed information about a wallet's holdings, token balances, USD values, and total portfolio value."
|
|
33
|
+
},
|
|
34
|
+
"fetch_chain_portfolio": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"title": "Fetch Chain Portfolio",
|
|
37
|
+
"enum": [
|
|
38
|
+
"disabled",
|
|
39
|
+
"public",
|
|
40
|
+
"private"
|
|
41
|
+
],
|
|
42
|
+
"x-enum-title": [
|
|
43
|
+
"Disabled",
|
|
44
|
+
"Agent Owner + All Users",
|
|
45
|
+
"Agent Owner Only"
|
|
46
|
+
],
|
|
47
|
+
"description": "Fetches wallet portfolio for a specific blockchain, retrieving detailed information about a wallet's holdings, token balances, USD values, and optionally token approvals."
|
|
48
|
+
},
|
|
49
|
+
"fetch_nft_portfolio": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"title": "Fetch NFT Portfolio",
|
|
52
|
+
"enum": [
|
|
53
|
+
"disabled",
|
|
54
|
+
"public",
|
|
55
|
+
"private"
|
|
56
|
+
],
|
|
57
|
+
"x-enum-title": [
|
|
58
|
+
"Disabled",
|
|
59
|
+
"Agent Owner + All Users",
|
|
60
|
+
"Agent Owner Only"
|
|
61
|
+
],
|
|
62
|
+
"description": "Fetches NFT portfolio for a wallet, retrieving detailed information about NFTs owned by a wallet address, including metadata, media URLs, and floor prices when available."
|
|
63
|
+
},
|
|
64
|
+
"fetch_solana_portfolio": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"title": "Fetch Solana Portfolio",
|
|
67
|
+
"enum": [
|
|
68
|
+
"disabled",
|
|
69
|
+
"public",
|
|
70
|
+
"private"
|
|
71
|
+
],
|
|
72
|
+
"x-enum-title": [
|
|
73
|
+
"Disabled",
|
|
74
|
+
"Agent Owner + All Users",
|
|
75
|
+
"Agent Owner Only"
|
|
76
|
+
],
|
|
77
|
+
"description": "Fetches Solana wallet portfolio, retrieving detailed information about a Solana wallet's holdings, including native SOL, SPL tokens, and optionally NFTs."
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"required": [
|
|
81
|
+
"fetch_wallet_portfolio",
|
|
82
|
+
"fetch_chain_portfolio",
|
|
83
|
+
"fetch_nft_portfolio",
|
|
84
|
+
"fetch_solana_portfolio"
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
"supported_chains": {
|
|
88
|
+
"type": "object",
|
|
89
|
+
"title": "Supported Blockchain Networks",
|
|
90
|
+
"description": "Configure which blockchain networks are supported",
|
|
91
|
+
"properties": {
|
|
92
|
+
"evm": {
|
|
93
|
+
"type": "boolean",
|
|
94
|
+
"title": "EVM Chains",
|
|
95
|
+
"description": "Whether to support EVM-compatible chains (Ethereum, Binance Smart Chain, etc.)",
|
|
96
|
+
"default": true
|
|
97
|
+
},
|
|
98
|
+
"solana": {
|
|
99
|
+
"type": "boolean",
|
|
100
|
+
"title": "Solana",
|
|
101
|
+
"description": "Whether to support Solana blockchain",
|
|
102
|
+
"default": true
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"api_key_provider": {
|
|
107
|
+
"type": "string",
|
|
108
|
+
"title": "API Key Provider",
|
|
109
|
+
"description": "Provider of the API key",
|
|
110
|
+
"enum": [
|
|
111
|
+
"platform",
|
|
112
|
+
"agent_owner"
|
|
113
|
+
],
|
|
114
|
+
"x-enum-title": [
|
|
115
|
+
"Nation Hosted",
|
|
116
|
+
"Owner Provided"
|
|
117
|
+
],
|
|
118
|
+
"default": "platform"
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"required": [
|
|
122
|
+
"states",
|
|
123
|
+
"enabled"
|
|
124
|
+
],
|
|
125
|
+
"if": {
|
|
126
|
+
"properties": {
|
|
127
|
+
"api_key_provider": {
|
|
128
|
+
"const": "agent_owner"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"then": {
|
|
133
|
+
"properties": {
|
|
134
|
+
"api_key": {
|
|
135
|
+
"type": "string",
|
|
136
|
+
"title": "API Key",
|
|
137
|
+
"x-link": "[Get your API key](https://developers.moralis.com/)",
|
|
138
|
+
"x-sensitive": true,
|
|
139
|
+
"description": "Moralis API key for blockchain data access"
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"if": {
|
|
143
|
+
"properties": {
|
|
144
|
+
"enabled": {
|
|
145
|
+
"const": true
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"then": {
|
|
150
|
+
"required": [
|
|
151
|
+
"api_key"
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"additionalProperties": true
|
|
156
|
+
}
|
|
File without changes
|