intentkit 0.6.13.dev2__py3-none-any.whl → 0.8.17__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 +1 -1
- intentkit/abstracts/agent.py +4 -5
- intentkit/abstracts/engine.py +5 -5
- intentkit/abstracts/graph.py +14 -7
- intentkit/abstracts/skill.py +6 -144
- intentkit/abstracts/twitter.py +4 -5
- intentkit/clients/__init__.py +5 -2
- intentkit/clients/cdp.py +101 -141
- intentkit/clients/twitter.py +83 -62
- intentkit/clients/web3.py +29 -0
- intentkit/config/config.py +8 -5
- intentkit/core/agent.py +472 -195
- intentkit/core/asset.py +253 -0
- intentkit/core/chat.py +51 -0
- intentkit/core/client.py +1 -1
- intentkit/core/credit.py +460 -130
- intentkit/core/engine.py +262 -233
- intentkit/core/node.py +15 -16
- intentkit/core/prompt.py +62 -28
- intentkit/core/scheduler.py +92 -0
- intentkit/core/statistics.py +168 -0
- intentkit/models/agent.py +1096 -949
- intentkit/models/agent_data.py +68 -38
- intentkit/models/agent_public.json +98 -0
- intentkit/models/agent_schema.json +54 -439
- intentkit/models/app_setting.py +96 -33
- intentkit/models/chat.py +74 -27
- intentkit/models/conversation.py +8 -8
- intentkit/models/credit.py +362 -74
- intentkit/models/db.py +26 -8
- intentkit/models/db_mig.py +2 -2
- intentkit/models/llm.csv +28 -0
- intentkit/models/llm.py +185 -350
- intentkit/models/redis.py +6 -4
- intentkit/models/skill.py +186 -72
- intentkit/models/skills.csv +174 -0
- intentkit/models/user.py +82 -24
- intentkit/skills/acolyt/__init__.py +2 -9
- intentkit/skills/acolyt/ask.py +3 -4
- intentkit/skills/acolyt/base.py +4 -9
- intentkit/skills/acolyt/schema.json +4 -3
- intentkit/skills/aixbt/__init__.py +2 -13
- intentkit/skills/aixbt/base.py +1 -7
- intentkit/skills/aixbt/projects.py +14 -15
- intentkit/skills/aixbt/schema.json +4 -4
- intentkit/skills/allora/__init__.py +2 -9
- intentkit/skills/allora/base.py +4 -9
- intentkit/skills/allora/price.py +3 -4
- intentkit/skills/allora/schema.json +3 -2
- intentkit/skills/base.py +248 -85
- intentkit/skills/basename/__init__.py +51 -0
- intentkit/skills/basename/base.py +11 -0
- intentkit/skills/basename/basename.svg +11 -0
- intentkit/skills/basename/schema.json +58 -0
- intentkit/skills/carv/__init__.py +115 -121
- intentkit/skills/carv/base.py +184 -185
- intentkit/skills/carv/fetch_news.py +3 -3
- intentkit/skills/carv/onchain_query.py +4 -4
- intentkit/skills/carv/schema.json +134 -137
- intentkit/skills/carv/token_info_and_price.py +5 -5
- intentkit/skills/casino/README.md +254 -0
- intentkit/skills/casino/__init__.py +86 -0
- intentkit/skills/casino/base.py +17 -0
- intentkit/skills/casino/casino.png +0 -0
- intentkit/skills/casino/deck_draw.py +127 -0
- intentkit/skills/casino/deck_shuffle.py +118 -0
- intentkit/skills/casino/dice_roll.py +100 -0
- intentkit/skills/casino/schema.json +77 -0
- intentkit/skills/casino/utils.py +107 -0
- intentkit/skills/cdp/__init__.py +22 -84
- intentkit/skills/cdp/base.py +1 -7
- intentkit/skills/cdp/schema.json +11 -314
- intentkit/skills/chainlist/__init__.py +2 -7
- intentkit/skills/chainlist/base.py +1 -7
- intentkit/skills/chainlist/chain_lookup.py +18 -18
- intentkit/skills/chainlist/schema.json +3 -5
- intentkit/skills/common/__init__.py +2 -9
- intentkit/skills/common/base.py +1 -7
- intentkit/skills/common/current_time.py +1 -2
- intentkit/skills/common/schema.json +2 -2
- intentkit/skills/cookiefun/__init__.py +6 -9
- intentkit/skills/cookiefun/base.py +2 -7
- intentkit/skills/cookiefun/get_account_details.py +7 -7
- intentkit/skills/cookiefun/get_account_feed.py +19 -19
- intentkit/skills/cookiefun/get_account_smart_followers.py +7 -7
- intentkit/skills/cookiefun/get_sectors.py +3 -3
- intentkit/skills/cookiefun/schema.json +1 -3
- intentkit/skills/cookiefun/search_accounts.py +9 -9
- intentkit/skills/cryptocompare/__init__.py +7 -24
- intentkit/skills/cryptocompare/api.py +2 -3
- intentkit/skills/cryptocompare/base.py +11 -25
- intentkit/skills/cryptocompare/fetch_news.py +4 -5
- intentkit/skills/cryptocompare/fetch_price.py +6 -7
- intentkit/skills/cryptocompare/fetch_top_exchanges.py +4 -5
- intentkit/skills/cryptocompare/fetch_top_market_cap.py +4 -5
- intentkit/skills/cryptocompare/fetch_top_volume.py +4 -5
- intentkit/skills/cryptocompare/fetch_trading_signals.py +5 -6
- intentkit/skills/cryptocompare/schema.json +3 -3
- intentkit/skills/cryptopanic/__init__.py +7 -10
- intentkit/skills/cryptopanic/base.py +51 -55
- intentkit/skills/cryptopanic/fetch_crypto_news.py +4 -8
- intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +5 -7
- intentkit/skills/cryptopanic/schema.json +105 -103
- intentkit/skills/dapplooker/__init__.py +2 -9
- intentkit/skills/dapplooker/base.py +4 -9
- intentkit/skills/dapplooker/dapplooker_token_data.py +7 -7
- intentkit/skills/dapplooker/schema.json +3 -5
- intentkit/skills/defillama/__init__.py +24 -74
- intentkit/skills/defillama/api.py +6 -9
- intentkit/skills/defillama/base.py +11 -21
- intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +8 -10
- intentkit/skills/defillama/coins/fetch_block.py +6 -8
- intentkit/skills/defillama/coins/fetch_current_prices.py +8 -10
- intentkit/skills/defillama/coins/fetch_first_price.py +7 -9
- intentkit/skills/defillama/coins/fetch_historical_prices.py +9 -11
- intentkit/skills/defillama/coins/fetch_price_chart.py +9 -11
- intentkit/skills/defillama/coins/fetch_price_percentage.py +7 -9
- intentkit/skills/defillama/config/chains.py +1 -3
- intentkit/skills/defillama/fees/fetch_fees_overview.py +24 -26
- intentkit/skills/defillama/schema.json +5 -1
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +16 -18
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +8 -10
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +5 -7
- intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +7 -9
- intentkit/skills/defillama/tests/api_integration.test.py +1 -1
- intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +4 -6
- intentkit/skills/defillama/tvl/fetch_chains.py +9 -11
- intentkit/skills/defillama/tvl/fetch_historical_tvl.py +4 -6
- intentkit/skills/defillama/tvl/fetch_protocol.py +32 -38
- intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +3 -5
- intentkit/skills/defillama/tvl/fetch_protocols.py +37 -45
- intentkit/skills/defillama/volumes/fetch_dex_overview.py +42 -48
- intentkit/skills/defillama/volumes/fetch_dex_summary.py +35 -37
- intentkit/skills/defillama/volumes/fetch_options_overview.py +24 -28
- intentkit/skills/defillama/yields/fetch_pool_chart.py +10 -12
- intentkit/skills/defillama/yields/fetch_pools.py +26 -30
- intentkit/skills/dexscreener/README.md +154 -0
- intentkit/skills/dexscreener/__init__.py +97 -93
- intentkit/skills/dexscreener/base.py +125 -133
- intentkit/skills/dexscreener/get_pair_info.py +158 -0
- intentkit/skills/dexscreener/get_token_pairs.py +165 -0
- intentkit/skills/dexscreener/get_tokens_info.py +212 -0
- intentkit/skills/dexscreener/model/search_token_response.py +80 -82
- intentkit/skills/dexscreener/schema.json +91 -48
- intentkit/skills/dexscreener/search_token.py +182 -321
- intentkit/skills/dexscreener/utils.py +420 -0
- intentkit/skills/dune_analytics/__init__.py +7 -9
- intentkit/skills/dune_analytics/base.py +48 -52
- intentkit/skills/dune_analytics/fetch_kol_buys.py +5 -7
- intentkit/skills/dune_analytics/fetch_nation_metrics.py +6 -8
- intentkit/skills/dune_analytics/schema.json +104 -99
- intentkit/skills/elfa/__init__.py +5 -18
- intentkit/skills/elfa/base.py +10 -14
- intentkit/skills/elfa/mention.py +19 -21
- intentkit/skills/elfa/schema.json +3 -2
- intentkit/skills/elfa/stats.py +4 -4
- intentkit/skills/elfa/tokens.py +12 -12
- intentkit/skills/elfa/utils.py +26 -28
- intentkit/skills/enso/__init__.py +11 -31
- intentkit/skills/enso/base.py +50 -35
- intentkit/skills/enso/best_yield.py +16 -24
- intentkit/skills/enso/networks.py +6 -11
- intentkit/skills/enso/prices.py +11 -13
- intentkit/skills/enso/route.py +34 -38
- intentkit/skills/enso/schema.json +3 -2
- intentkit/skills/enso/tokens.py +29 -38
- intentkit/skills/enso/wallet.py +76 -191
- intentkit/skills/erc20/__init__.py +50 -0
- intentkit/skills/erc20/base.py +11 -0
- intentkit/skills/erc20/erc20.svg +5 -0
- intentkit/skills/erc20/schema.json +74 -0
- intentkit/skills/erc721/__init__.py +53 -0
- intentkit/skills/erc721/base.py +11 -0
- intentkit/skills/erc721/erc721.svg +5 -0
- intentkit/skills/erc721/schema.json +90 -0
- intentkit/skills/firecrawl/README.md +11 -5
- intentkit/skills/firecrawl/__init__.py +5 -18
- intentkit/skills/firecrawl/base.py +4 -11
- intentkit/skills/firecrawl/clear.py +4 -8
- intentkit/skills/firecrawl/crawl.py +19 -19
- intentkit/skills/firecrawl/query.py +4 -3
- intentkit/skills/firecrawl/schema.json +6 -8
- intentkit/skills/firecrawl/scrape.py +150 -40
- intentkit/skills/firecrawl/utils.py +50 -42
- intentkit/skills/github/__init__.py +2 -7
- intentkit/skills/github/base.py +1 -7
- intentkit/skills/github/github_search.py +1 -2
- intentkit/skills/github/schema.json +3 -4
- intentkit/skills/heurist/__init__.py +8 -27
- intentkit/skills/heurist/base.py +4 -9
- intentkit/skills/heurist/image_generation_animagine_xl.py +12 -13
- intentkit/skills/heurist/image_generation_arthemy_comics.py +12 -13
- intentkit/skills/heurist/image_generation_arthemy_real.py +12 -13
- intentkit/skills/heurist/image_generation_braindance.py +12 -13
- intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +12 -13
- intentkit/skills/heurist/image_generation_flux_1_dev.py +12 -13
- intentkit/skills/heurist/image_generation_sdxl.py +12 -13
- intentkit/skills/heurist/schema.json +2 -2
- intentkit/skills/http/__init__.py +4 -15
- intentkit/skills/http/base.py +1 -7
- intentkit/skills/http/get.py +21 -16
- intentkit/skills/http/post.py +23 -18
- intentkit/skills/http/put.py +23 -18
- intentkit/skills/http/schema.json +4 -5
- intentkit/skills/lifi/__init__.py +8 -13
- intentkit/skills/lifi/base.py +1 -7
- intentkit/skills/lifi/schema.json +17 -8
- intentkit/skills/lifi/token_execute.py +36 -30
- intentkit/skills/lifi/token_quote.py +8 -10
- intentkit/skills/lifi/utils.py +104 -51
- intentkit/skills/moralis/__init__.py +6 -10
- intentkit/skills/moralis/api.py +6 -7
- intentkit/skills/moralis/base.py +5 -10
- intentkit/skills/moralis/fetch_chain_portfolio.py +10 -11
- intentkit/skills/moralis/fetch_nft_portfolio.py +22 -22
- intentkit/skills/moralis/fetch_solana_portfolio.py +11 -12
- intentkit/skills/moralis/fetch_wallet_portfolio.py +8 -9
- intentkit/skills/moralis/schema.json +7 -2
- intentkit/skills/morpho/__init__.py +52 -0
- intentkit/skills/morpho/base.py +11 -0
- intentkit/skills/morpho/morpho.svg +12 -0
- intentkit/skills/morpho/schema.json +73 -0
- intentkit/skills/nation/__init__.py +4 -9
- intentkit/skills/nation/base.py +5 -10
- intentkit/skills/nation/nft_check.py +3 -4
- intentkit/skills/nation/schema.json +4 -3
- intentkit/skills/onchain.py +23 -0
- intentkit/skills/openai/__init__.py +17 -18
- intentkit/skills/openai/base.py +10 -14
- intentkit/skills/openai/dalle_image_generation.py +3 -8
- intentkit/skills/openai/gpt_avatar_generator.py +102 -0
- intentkit/skills/openai/gpt_image_generation.py +4 -8
- intentkit/skills/openai/gpt_image_mini_generator.py +91 -0
- intentkit/skills/openai/gpt_image_to_image.py +4 -8
- intentkit/skills/openai/image_to_text.py +3 -7
- intentkit/skills/openai/schema.json +34 -3
- intentkit/skills/portfolio/__init__.py +11 -35
- intentkit/skills/portfolio/base.py +33 -19
- intentkit/skills/portfolio/schema.json +3 -5
- intentkit/skills/portfolio/token_balances.py +21 -21
- intentkit/skills/portfolio/wallet_approvals.py +17 -18
- intentkit/skills/portfolio/wallet_defi_positions.py +3 -3
- intentkit/skills/portfolio/wallet_history.py +31 -31
- intentkit/skills/portfolio/wallet_net_worth.py +13 -13
- intentkit/skills/portfolio/wallet_nfts.py +19 -19
- intentkit/skills/portfolio/wallet_profitability.py +18 -18
- intentkit/skills/portfolio/wallet_profitability_summary.py +5 -5
- intentkit/skills/portfolio/wallet_stats.py +3 -3
- intentkit/skills/portfolio/wallet_swaps.py +19 -19
- intentkit/skills/pyth/__init__.py +50 -0
- intentkit/skills/pyth/base.py +11 -0
- intentkit/skills/pyth/pyth.svg +6 -0
- intentkit/skills/pyth/schema.json +75 -0
- intentkit/skills/skills.toml +40 -0
- intentkit/skills/slack/__init__.py +5 -17
- intentkit/skills/slack/base.py +3 -9
- intentkit/skills/slack/get_channel.py +8 -8
- intentkit/skills/slack/get_message.py +9 -9
- intentkit/skills/slack/schedule_message.py +5 -5
- intentkit/skills/slack/schema.json +2 -2
- intentkit/skills/slack/send_message.py +3 -5
- intentkit/skills/supabase/__init__.py +7 -23
- intentkit/skills/supabase/base.py +9 -13
- intentkit/skills/supabase/delete_data.py +5 -6
- intentkit/skills/supabase/fetch_data.py +13 -14
- intentkit/skills/supabase/insert_data.py +5 -6
- intentkit/skills/supabase/invoke_function.py +7 -8
- intentkit/skills/supabase/schema.json +2 -3
- intentkit/skills/supabase/update_data.py +7 -8
- intentkit/skills/supabase/upsert_data.py +5 -6
- intentkit/skills/superfluid/__init__.py +53 -0
- intentkit/skills/superfluid/base.py +11 -0
- intentkit/skills/superfluid/schema.json +89 -0
- intentkit/skills/superfluid/superfluid.svg +6 -0
- intentkit/skills/system/__init__.py +7 -24
- intentkit/skills/system/add_autonomous_task.py +10 -12
- intentkit/skills/system/delete_autonomous_task.py +2 -2
- intentkit/skills/system/edit_autonomous_task.py +14 -18
- intentkit/skills/system/list_autonomous_tasks.py +3 -5
- intentkit/skills/system/read_agent_api_key.py +6 -4
- intentkit/skills/system/regenerate_agent_api_key.py +6 -4
- intentkit/skills/system/schema.json +6 -8
- intentkit/skills/tavily/__init__.py +3 -12
- intentkit/skills/tavily/base.py +4 -9
- intentkit/skills/tavily/schema.json +3 -5
- intentkit/skills/tavily/tavily_extract.py +2 -4
- intentkit/skills/tavily/tavily_search.py +4 -6
- intentkit/skills/token/__init__.py +5 -10
- intentkit/skills/token/base.py +7 -11
- intentkit/skills/token/erc20_transfers.py +19 -19
- intentkit/skills/token/schema.json +3 -6
- intentkit/skills/token/token_analytics.py +3 -3
- intentkit/skills/token/token_price.py +13 -13
- intentkit/skills/token/token_search.py +9 -9
- intentkit/skills/twitter/__init__.py +11 -35
- intentkit/skills/twitter/base.py +23 -35
- intentkit/skills/twitter/follow_user.py +3 -7
- intentkit/skills/twitter/get_mentions.py +6 -13
- intentkit/skills/twitter/get_timeline.py +5 -13
- intentkit/skills/twitter/get_user_by_username.py +3 -7
- intentkit/skills/twitter/get_user_tweets.py +6 -14
- intentkit/skills/twitter/like_tweet.py +3 -7
- intentkit/skills/twitter/post_tweet.py +23 -12
- intentkit/skills/twitter/reply_tweet.py +21 -12
- intentkit/skills/twitter/retweet.py +3 -7
- intentkit/skills/twitter/schema.json +1 -0
- intentkit/skills/twitter/search_tweets.py +5 -13
- intentkit/skills/unrealspeech/__init__.py +2 -7
- intentkit/skills/unrealspeech/base.py +2 -8
- intentkit/skills/unrealspeech/schema.json +2 -5
- intentkit/skills/unrealspeech/text_to_speech.py +8 -8
- intentkit/skills/venice_audio/__init__.py +98 -106
- intentkit/skills/venice_audio/base.py +117 -121
- intentkit/skills/venice_audio/input.py +41 -41
- intentkit/skills/venice_audio/schema.json +151 -152
- intentkit/skills/venice_audio/venice_audio.py +38 -21
- intentkit/skills/venice_image/__init__.py +147 -154
- intentkit/skills/venice_image/api.py +138 -138
- intentkit/skills/venice_image/base.py +185 -192
- intentkit/skills/venice_image/config.py +33 -35
- intentkit/skills/venice_image/image_enhance/image_enhance.py +2 -3
- intentkit/skills/venice_image/image_enhance/image_enhance_base.py +21 -23
- intentkit/skills/venice_image/image_enhance/image_enhance_input.py +38 -40
- intentkit/skills/venice_image/image_generation/image_generation_base.py +9 -9
- intentkit/skills/venice_image/image_generation/image_generation_fluently_xl.py +26 -26
- intentkit/skills/venice_image/image_generation/image_generation_flux_dev.py +27 -27
- intentkit/skills/venice_image/image_generation/image_generation_flux_dev_uncensored.py +26 -26
- intentkit/skills/venice_image/image_generation/image_generation_input.py +158 -158
- intentkit/skills/venice_image/image_generation/image_generation_lustify_sdxl.py +26 -26
- intentkit/skills/venice_image/image_generation/image_generation_pony_realism.py +26 -26
- intentkit/skills/venice_image/image_generation/image_generation_stable_diffusion_3_5.py +28 -28
- intentkit/skills/venice_image/image_generation/image_generation_venice_sd35.py +28 -28
- intentkit/skills/venice_image/image_upscale/image_upscale.py +3 -3
- intentkit/skills/venice_image/image_upscale/image_upscale_base.py +21 -23
- intentkit/skills/venice_image/image_upscale/image_upscale_input.py +22 -22
- intentkit/skills/venice_image/image_vision/image_vision.py +2 -2
- intentkit/skills/venice_image/image_vision/image_vision_base.py +17 -17
- intentkit/skills/venice_image/image_vision/image_vision_input.py +9 -9
- intentkit/skills/venice_image/schema.json +267 -267
- intentkit/skills/venice_image/utils.py +77 -78
- intentkit/skills/web_scraper/__init__.py +5 -18
- intentkit/skills/web_scraper/base.py +21 -7
- intentkit/skills/web_scraper/document_indexer.py +7 -6
- intentkit/skills/web_scraper/schema.json +2 -6
- intentkit/skills/web_scraper/scrape_and_index.py +15 -15
- intentkit/skills/web_scraper/utils.py +62 -63
- intentkit/skills/web_scraper/website_indexer.py +17 -19
- intentkit/skills/weth/__init__.py +49 -0
- intentkit/skills/weth/base.py +11 -0
- intentkit/skills/weth/schema.json +58 -0
- intentkit/skills/weth/weth.svg +6 -0
- intentkit/skills/wow/__init__.py +51 -0
- intentkit/skills/wow/base.py +11 -0
- intentkit/skills/wow/schema.json +89 -0
- intentkit/skills/wow/wow.svg +7 -0
- intentkit/skills/x402/__init__.py +61 -0
- intentkit/skills/x402/ask_agent.py +98 -0
- intentkit/skills/x402/base.py +99 -0
- intentkit/skills/x402/http_request.py +117 -0
- intentkit/skills/x402/schema.json +45 -0
- intentkit/skills/x402/x402.webp +0 -0
- intentkit/skills/xmtp/__init__.py +4 -15
- intentkit/skills/xmtp/base.py +61 -2
- intentkit/skills/xmtp/price.py +18 -13
- intentkit/skills/xmtp/schema.json +69 -71
- intentkit/skills/xmtp/swap.py +22 -25
- intentkit/skills/xmtp/transfer.py +71 -32
- intentkit/utils/chain.py +3 -3
- intentkit/utils/error.py +14 -1
- intentkit/utils/logging.py +2 -4
- intentkit/utils/s3.py +59 -7
- intentkit/utils/schema.py +100 -0
- intentkit/utils/slack_alert.py +7 -8
- {intentkit-0.6.13.dev2.dist-info → intentkit-0.8.17.dist-info}/METADATA +14 -16
- intentkit-0.8.17.dist-info/RECORD +466 -0
- intentkit/abstracts/exception.py +0 -9
- intentkit/core/skill.py +0 -200
- intentkit/models/generator.py +0 -347
- intentkit/skills/cdp/get_balance.py +0 -110
- intentkit/skills/cdp/swap.py +0 -121
- intentkit/skills/moralis/tests/__init__.py +0 -0
- intentkit/skills/moralis/tests/test_wallet.py +0 -511
- intentkit-0.6.13.dev2.dist-info/RECORD +0 -409
- {intentkit-0.6.13.dev2.dist-info → intentkit-0.8.17.dist-info}/WHEEL +0 -0
- {intentkit-0.6.13.dev2.dist-info → intentkit-0.8.17.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
from typing import Any
|
|
2
|
+
from typing import Any
|
|
3
3
|
|
|
4
4
|
import httpx
|
|
5
|
+
from coinbase_agentkit import CdpEvmWalletProvider
|
|
5
6
|
from pydantic import BaseModel, Field
|
|
6
7
|
from web3 import Web3
|
|
7
8
|
|
|
8
|
-
from intentkit.
|
|
9
|
-
from intentkit.
|
|
9
|
+
from intentkit.clients import get_wallet_provider as get_agent_wallet_provider
|
|
10
|
+
from intentkit.models.agent import Agent
|
|
10
11
|
from intentkit.skills.lifi.base import LiFiBaseTool
|
|
11
12
|
from intentkit.skills.lifi.token_quote import TokenQuote
|
|
12
13
|
from intentkit.skills.lifi.utils import (
|
|
@@ -62,37 +63,37 @@ class TokenExecute(LiFiBaseTool):
|
|
|
62
63
|
"Use token_quote first to check rates and fees before executing.\n"
|
|
63
64
|
"Supports all major chains like Ethereum, Polygon, Arbitrum, Optimism, Base, and more."
|
|
64
65
|
)
|
|
65
|
-
args_schema:
|
|
66
|
+
args_schema: type[BaseModel] = TokenExecuteInput
|
|
66
67
|
api_url: str = LIFI_API_URL
|
|
67
68
|
|
|
68
69
|
# Configuration options
|
|
69
70
|
default_slippage: float = 0.03
|
|
70
|
-
allowed_chains:
|
|
71
|
+
allowed_chains: list[str] | None = None
|
|
71
72
|
max_execution_time: int = 300
|
|
72
|
-
quote_tool: TokenQuote = Field(default=None, exclude=True)
|
|
73
|
+
quote_tool: TokenQuote | None = Field(default=None, exclude=True)
|
|
73
74
|
|
|
74
75
|
def __init__(
|
|
75
76
|
self,
|
|
76
|
-
skill_store: SkillStoreABC,
|
|
77
77
|
default_slippage: float = 0.03,
|
|
78
|
-
allowed_chains:
|
|
78
|
+
allowed_chains: list[str] | None = None,
|
|
79
79
|
max_execution_time: int = 300,
|
|
80
|
-
):
|
|
80
|
+
) -> None:
|
|
81
81
|
"""Initialize the TokenExecute skill with configuration options."""
|
|
82
|
-
super().__init__(
|
|
82
|
+
super().__init__()
|
|
83
83
|
self.default_slippage = default_slippage
|
|
84
84
|
self.allowed_chains = allowed_chains
|
|
85
85
|
self.max_execution_time = max_execution_time
|
|
86
86
|
# Initialize quote tool if not set
|
|
87
87
|
if not self.quote_tool:
|
|
88
88
|
self.quote_tool = TokenQuote(
|
|
89
|
-
skill_store=skill_store,
|
|
90
89
|
default_slippage=default_slippage,
|
|
91
90
|
allowed_chains=allowed_chains,
|
|
92
91
|
)
|
|
93
92
|
|
|
94
|
-
def _format_quote_result(self, data:
|
|
93
|
+
def _format_quote_result(self, data: dict[str, Any]) -> str:
|
|
95
94
|
"""Format the quote result in a readable format."""
|
|
95
|
+
if self.quote_tool is None:
|
|
96
|
+
raise RuntimeError("Quote tool is not initialized")
|
|
96
97
|
# Use the same formatting as token_quote
|
|
97
98
|
return self.quote_tool._format_quote_result(data)
|
|
98
99
|
|
|
@@ -103,7 +104,7 @@ class TokenExecute(LiFiBaseTool):
|
|
|
103
104
|
from_token: str,
|
|
104
105
|
to_token: str,
|
|
105
106
|
from_amount: str,
|
|
106
|
-
slippage: float = None,
|
|
107
|
+
slippage: float | None = None,
|
|
107
108
|
**kwargs,
|
|
108
109
|
) -> str:
|
|
109
110
|
"""Execute a token transfer."""
|
|
@@ -127,14 +128,14 @@ class TokenExecute(LiFiBaseTool):
|
|
|
127
128
|
|
|
128
129
|
# Get agent context for CDP wallet
|
|
129
130
|
context = self.get_context()
|
|
130
|
-
|
|
131
|
+
agent = context.agent
|
|
131
132
|
|
|
132
133
|
self.logger.info(
|
|
133
134
|
f"Executing LiFi transfer: {from_amount} {from_token} on {from_chain} -> {to_token} on {to_chain}"
|
|
134
135
|
)
|
|
135
136
|
|
|
136
137
|
# Get CDP wallet provider
|
|
137
|
-
cdp_wallet_provider = await self._get_cdp_wallet_provider(
|
|
138
|
+
cdp_wallet_provider = await self._get_cdp_wallet_provider(agent)
|
|
138
139
|
if isinstance(cdp_wallet_provider, str): # Error message
|
|
139
140
|
return cdp_wallet_provider
|
|
140
141
|
|
|
@@ -168,7 +169,9 @@ class TokenExecute(LiFiBaseTool):
|
|
|
168
169
|
|
|
169
170
|
# Step 3: Execute transaction
|
|
170
171
|
tx_hash = await self._execute_transfer_transaction(
|
|
171
|
-
cdp_wallet_provider,
|
|
172
|
+
cdp_wallet_provider,
|
|
173
|
+
quote_data,
|
|
174
|
+
from_address,
|
|
172
175
|
)
|
|
173
176
|
|
|
174
177
|
# Step 4: Monitor status and return result
|
|
@@ -180,14 +183,12 @@ class TokenExecute(LiFiBaseTool):
|
|
|
180
183
|
self.logger.error("LiFi_Error: %s", str(e))
|
|
181
184
|
return f"An unexpected error occurred: {str(e)}"
|
|
182
185
|
|
|
183
|
-
async def _get_cdp_wallet_provider(
|
|
186
|
+
async def _get_cdp_wallet_provider(
|
|
187
|
+
self, agent: Agent
|
|
188
|
+
) -> CdpEvmWalletProvider | str:
|
|
184
189
|
"""Get CDP wallet provider with error handling."""
|
|
185
190
|
try:
|
|
186
|
-
|
|
187
|
-
if not cdp_client:
|
|
188
|
-
return "CDP client not available. Please ensure your agent has CDP wallet configuration."
|
|
189
|
-
|
|
190
|
-
cdp_wallet_provider = await cdp_client.get_wallet_provider()
|
|
191
|
+
cdp_wallet_provider = await get_agent_wallet_provider(agent)
|
|
191
192
|
if not cdp_wallet_provider:
|
|
192
193
|
return "CDP wallet provider not configured. Please set up your agent's CDP wallet first."
|
|
193
194
|
|
|
@@ -207,7 +208,7 @@ class TokenExecute(LiFiBaseTool):
|
|
|
207
208
|
from_amount: str,
|
|
208
209
|
slippage: float,
|
|
209
210
|
from_address: str,
|
|
210
|
-
) ->
|
|
211
|
+
) -> dict[str, Any] | str:
|
|
211
212
|
"""Get quote from LiFi API."""
|
|
212
213
|
api_params = build_quote_params(
|
|
213
214
|
from_chain,
|
|
@@ -249,8 +250,8 @@ class TokenExecute(LiFiBaseTool):
|
|
|
249
250
|
return data
|
|
250
251
|
|
|
251
252
|
async def _handle_token_approval(
|
|
252
|
-
self, wallet_provider, quote_data:
|
|
253
|
-
) ->
|
|
253
|
+
self, wallet_provider: CdpEvmWalletProvider, quote_data: dict[str, Any]
|
|
254
|
+
) -> str | None:
|
|
254
255
|
"""Handle ERC20 token approval if needed."""
|
|
255
256
|
estimate = quote_data.get("estimate", {})
|
|
256
257
|
approval_address = estimate.get("approvalAddress")
|
|
@@ -273,13 +274,18 @@ class TokenExecute(LiFiBaseTool):
|
|
|
273
274
|
raise Exception(f"Failed to approve token: {str(e)}")
|
|
274
275
|
|
|
275
276
|
async def _execute_transfer_transaction(
|
|
276
|
-
self,
|
|
277
|
+
self,
|
|
278
|
+
wallet_provider: CdpEvmWalletProvider,
|
|
279
|
+
quote_data: dict[str, Any],
|
|
280
|
+
from_address: str,
|
|
277
281
|
) -> str:
|
|
278
282
|
"""Execute the main transfer transaction."""
|
|
279
283
|
transaction_request = quote_data.get("transactionRequest")
|
|
280
284
|
|
|
281
285
|
try:
|
|
282
|
-
tx_params = prepare_transaction_params(
|
|
286
|
+
tx_params = prepare_transaction_params(
|
|
287
|
+
transaction_request, wallet_address=from_address
|
|
288
|
+
)
|
|
283
289
|
self.logger.info(
|
|
284
290
|
f"Sending transaction to {tx_params['to']} with value {tx_params['value']}"
|
|
285
291
|
)
|
|
@@ -304,7 +310,7 @@ class TokenExecute(LiFiBaseTool):
|
|
|
304
310
|
tx_hash: str,
|
|
305
311
|
from_chain: str,
|
|
306
312
|
to_chain: str,
|
|
307
|
-
quote_data:
|
|
313
|
+
quote_data: dict[str, Any],
|
|
308
314
|
) -> str:
|
|
309
315
|
"""Finalize transfer and return formatted result."""
|
|
310
316
|
self.logger.info(f"Transaction sent: {tx_hash}")
|
|
@@ -407,11 +413,11 @@ class TokenExecute(LiFiBaseTool):
|
|
|
407
413
|
|
|
408
414
|
async def _check_and_set_allowance(
|
|
409
415
|
self,
|
|
410
|
-
wallet_provider,
|
|
416
|
+
wallet_provider: CdpEvmWalletProvider,
|
|
411
417
|
token_address: str,
|
|
412
418
|
approval_address: str,
|
|
413
419
|
amount: str,
|
|
414
|
-
) ->
|
|
420
|
+
) -> str | None:
|
|
415
421
|
"""Check if token allowance is sufficient and set approval if needed."""
|
|
416
422
|
try:
|
|
417
423
|
# Normalize addresses
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
from typing import Any
|
|
1
|
+
from typing import Any
|
|
2
2
|
|
|
3
3
|
import httpx
|
|
4
4
|
from pydantic import BaseModel, Field
|
|
5
5
|
|
|
6
|
-
from intentkit.abstracts.skill import SkillStoreABC
|
|
7
6
|
from intentkit.skills.lifi.base import LiFiBaseTool
|
|
8
7
|
from intentkit.skills.lifi.utils import (
|
|
9
8
|
LIFI_API_URL,
|
|
@@ -53,21 +52,20 @@ class TokenQuote(LiFiBaseTool):
|
|
|
53
52
|
"Use this tool to check rates, fees, and estimated time for token transfers without executing them.\n"
|
|
54
53
|
"Supports all major chains like Ethereum, Polygon, Arbitrum, Optimism, Base, and more."
|
|
55
54
|
)
|
|
56
|
-
args_schema:
|
|
55
|
+
args_schema: type[BaseModel] = TokenQuoteInput
|
|
57
56
|
api_url: str = LIFI_API_URL
|
|
58
57
|
|
|
59
58
|
# Configuration options
|
|
60
59
|
default_slippage: float = 0.03
|
|
61
|
-
allowed_chains:
|
|
60
|
+
allowed_chains: list[str] | None = None
|
|
62
61
|
|
|
63
62
|
def __init__(
|
|
64
63
|
self,
|
|
65
|
-
skill_store: SkillStoreABC,
|
|
66
64
|
default_slippage: float = 0.03,
|
|
67
|
-
allowed_chains:
|
|
68
|
-
):
|
|
65
|
+
allowed_chains: list[str] | None = None,
|
|
66
|
+
) -> None:
|
|
69
67
|
"""Initialize the TokenQuote skill with configuration options."""
|
|
70
|
-
super().__init__(
|
|
68
|
+
super().__init__()
|
|
71
69
|
self.default_slippage = default_slippage
|
|
72
70
|
self.allowed_chains = allowed_chains
|
|
73
71
|
|
|
@@ -78,7 +76,7 @@ class TokenQuote(LiFiBaseTool):
|
|
|
78
76
|
from_token: str,
|
|
79
77
|
to_token: str,
|
|
80
78
|
from_amount: str,
|
|
81
|
-
slippage: float = None,
|
|
79
|
+
slippage: float | None = None,
|
|
82
80
|
**kwargs,
|
|
83
81
|
) -> str:
|
|
84
82
|
"""Get a quote for token transfer."""
|
|
@@ -140,7 +138,7 @@ class TokenQuote(LiFiBaseTool):
|
|
|
140
138
|
self.logger.error("LiFi_Error: %s", str(e))
|
|
141
139
|
return f"An unexpected error occurred: {str(e)}"
|
|
142
140
|
|
|
143
|
-
def _format_quote_result(self, data:
|
|
141
|
+
def _format_quote_result(self, data: dict[str, Any]) -> str:
|
|
144
142
|
"""Format quote result into human-readable text."""
|
|
145
143
|
try:
|
|
146
144
|
# Get basic info
|
intentkit/skills/lifi/utils.py
CHANGED
|
@@ -4,7 +4,8 @@ LiFi Skills Utilities
|
|
|
4
4
|
Common utilities and helper functions for LiFi token transfer skills.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from decimal import ROUND_DOWN, Decimal, InvalidOperation
|
|
8
|
+
from typing import Any
|
|
8
9
|
|
|
9
10
|
import httpx
|
|
10
11
|
from web3 import Web3
|
|
@@ -71,8 +72,8 @@ def validate_inputs(
|
|
|
71
72
|
to_token: str,
|
|
72
73
|
from_amount: str,
|
|
73
74
|
slippage: float,
|
|
74
|
-
allowed_chains:
|
|
75
|
-
) ->
|
|
75
|
+
allowed_chains: list[str] | None = None,
|
|
76
|
+
) -> str | None:
|
|
76
77
|
"""
|
|
77
78
|
Validate all input parameters for LiFi operations.
|
|
78
79
|
|
|
@@ -179,7 +180,7 @@ def handle_api_response(
|
|
|
179
180
|
from_chain: str,
|
|
180
181
|
to_token: str,
|
|
181
182
|
to_chain: str,
|
|
182
|
-
) ->
|
|
183
|
+
) -> tuple[dict[str, Any] | None, str | None]:
|
|
183
184
|
"""
|
|
184
185
|
Handle LiFi API response and return data or error message.
|
|
185
186
|
|
|
@@ -293,17 +294,20 @@ def convert_chain_to_id(chain: str) -> int:
|
|
|
293
294
|
|
|
294
295
|
|
|
295
296
|
def convert_amount_to_wei(amount: str, token_symbol: str = "ETH") -> str:
|
|
296
|
-
"""
|
|
297
|
-
Convert human-readable amount to wei format for LiFi API.
|
|
297
|
+
"""Convert a token amount into the smallest denomination expected by LiFi."""
|
|
298
298
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
299
|
+
if amount is None:
|
|
300
|
+
raise ValueError("Amount is required")
|
|
301
|
+
|
|
302
|
+
normalized_amount = amount.strip()
|
|
303
|
+
if not normalized_amount:
|
|
304
|
+
raise ValueError("Amount cannot be empty")
|
|
305
|
+
|
|
306
|
+
# If the user already provided an integer amount without a decimal point,
|
|
307
|
+
# assume it is already in the token's smallest denomination.
|
|
308
|
+
if normalized_amount.isdigit():
|
|
309
|
+
return normalized_amount
|
|
302
310
|
|
|
303
|
-
Returns:
|
|
304
|
-
Amount in wei format as string
|
|
305
|
-
"""
|
|
306
|
-
# Default decimals for common tokens
|
|
307
311
|
token_decimals = {
|
|
308
312
|
"ETH": 18,
|
|
309
313
|
"USDC": 6,
|
|
@@ -318,13 +322,16 @@ def convert_amount_to_wei(amount: str, token_symbol: str = "ETH") -> str:
|
|
|
318
322
|
decimals = token_decimals.get(token_symbol.upper(), 18)
|
|
319
323
|
|
|
320
324
|
try:
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
325
|
+
decimal_amount = Decimal(normalized_amount)
|
|
326
|
+
scaled_amount = (decimal_amount * (Decimal(10) ** decimals)).quantize(
|
|
327
|
+
Decimal("1"),
|
|
328
|
+
rounding=ROUND_DOWN,
|
|
329
|
+
)
|
|
330
|
+
return str(int(scaled_amount))
|
|
331
|
+
except (InvalidOperation, ValueError, TypeError):
|
|
332
|
+
# If conversion fails, fall back to the original value to avoid
|
|
333
|
+
# accidentally submitting an incorrect amount.
|
|
334
|
+
return normalized_amount
|
|
328
335
|
|
|
329
336
|
|
|
330
337
|
def build_quote_params(
|
|
@@ -334,8 +341,8 @@ def build_quote_params(
|
|
|
334
341
|
to_token: str,
|
|
335
342
|
from_amount: str,
|
|
336
343
|
slippage: float,
|
|
337
|
-
from_address:
|
|
338
|
-
) ->
|
|
344
|
+
from_address: str | None = None,
|
|
345
|
+
) -> dict[str, Any]:
|
|
339
346
|
"""
|
|
340
347
|
Build parameters for LiFi quote API request.
|
|
341
348
|
|
|
@@ -350,15 +357,12 @@ def build_quote_params(
|
|
|
350
357
|
Raises:
|
|
351
358
|
ValueError: If chain identifiers are not recognized
|
|
352
359
|
"""
|
|
353
|
-
# Convert amount to wei format for API
|
|
354
|
-
wei_amount = convert_amount_to_wei(from_amount, from_token)
|
|
355
|
-
|
|
356
360
|
return {
|
|
357
361
|
"fromChain": convert_chain_to_id(from_chain),
|
|
358
362
|
"toChain": convert_chain_to_id(to_chain),
|
|
359
363
|
"fromToken": from_token,
|
|
360
364
|
"toToken": to_token,
|
|
361
|
-
"fromAmount":
|
|
365
|
+
"fromAmount": convert_amount_to_wei(from_amount, from_token),
|
|
362
366
|
"fromAddress": from_address or DUMMY_ADDRESS,
|
|
363
367
|
"slippage": slippage,
|
|
364
368
|
}
|
|
@@ -381,38 +385,87 @@ def is_native_token(token_address: str) -> bool:
|
|
|
381
385
|
)
|
|
382
386
|
|
|
383
387
|
|
|
384
|
-
def
|
|
385
|
-
"""
|
|
386
|
-
Prepare transaction parameters for CDP wallet provider.
|
|
388
|
+
def _convert_hex_or_decimal(value: Any) -> int | None:
|
|
389
|
+
"""Convert LiFi transaction numeric values into integers."""
|
|
387
390
|
|
|
388
|
-
|
|
389
|
-
|
|
391
|
+
if value is None:
|
|
392
|
+
return None
|
|
390
393
|
|
|
391
|
-
|
|
392
|
-
|
|
394
|
+
if isinstance(value, int):
|
|
395
|
+
return value
|
|
396
|
+
|
|
397
|
+
if isinstance(value, str):
|
|
398
|
+
stripped = value.strip()
|
|
399
|
+
if not stripped:
|
|
400
|
+
return None
|
|
401
|
+
if stripped.startswith("0x"):
|
|
402
|
+
return int(stripped, 16)
|
|
403
|
+
try:
|
|
404
|
+
return int(Decimal(stripped))
|
|
405
|
+
except (InvalidOperation, ValueError):
|
|
406
|
+
return None
|
|
407
|
+
|
|
408
|
+
return None
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def prepare_transaction_params(
|
|
412
|
+
transaction_request: dict[str, Any],
|
|
413
|
+
wallet_address: str | None = None,
|
|
414
|
+
) -> dict[str, Any]:
|
|
415
|
+
"""Prepare transaction parameters for the CDP wallet provider."""
|
|
393
416
|
|
|
394
|
-
Raises:
|
|
395
|
-
Exception: If required parameters are missing
|
|
396
|
-
"""
|
|
397
417
|
to_address = transaction_request.get("to")
|
|
398
|
-
value = transaction_request.get("value", "
|
|
418
|
+
value = transaction_request.get("value", "0x0")
|
|
399
419
|
data = transaction_request.get("data", "0x")
|
|
400
420
|
|
|
401
421
|
if not to_address:
|
|
402
|
-
raise Exception("
|
|
403
|
-
|
|
404
|
-
# Convert value to integer if it's a string
|
|
405
|
-
if isinstance(value, str):
|
|
406
|
-
value = int(value, 16) if value.startswith("0x") else int(value)
|
|
422
|
+
raise Exception("Transaction request is missing destination address")
|
|
407
423
|
|
|
408
|
-
|
|
424
|
+
tx_params: dict[str, Any] = {
|
|
409
425
|
"to": Web3.to_checksum_address(to_address),
|
|
410
|
-
"value": value,
|
|
411
426
|
"data": data,
|
|
412
427
|
}
|
|
413
428
|
|
|
429
|
+
int_value = _convert_hex_or_decimal(value)
|
|
430
|
+
if int_value is not None:
|
|
431
|
+
tx_params["value"] = int_value
|
|
432
|
+
|
|
433
|
+
chain_id = _convert_hex_or_decimal(transaction_request.get("chainId"))
|
|
434
|
+
if chain_id is not None:
|
|
435
|
+
tx_params["chainId"] = chain_id
|
|
436
|
+
|
|
437
|
+
gas_limit = _convert_hex_or_decimal(
|
|
438
|
+
transaction_request.get("gasLimit") or transaction_request.get("gas")
|
|
439
|
+
)
|
|
440
|
+
if gas_limit is not None:
|
|
441
|
+
tx_params["gas"] = gas_limit
|
|
442
|
+
|
|
443
|
+
gas_price = _convert_hex_or_decimal(transaction_request.get("gasPrice"))
|
|
444
|
+
if gas_price is not None:
|
|
445
|
+
tx_params["gasPrice"] = gas_price
|
|
446
|
+
|
|
447
|
+
max_fee_per_gas = _convert_hex_or_decimal(transaction_request.get("maxFeePerGas"))
|
|
448
|
+
if max_fee_per_gas is not None:
|
|
449
|
+
tx_params["maxFeePerGas"] = max_fee_per_gas
|
|
450
|
+
|
|
451
|
+
max_priority_fee_per_gas = _convert_hex_or_decimal(
|
|
452
|
+
transaction_request.get("maxPriorityFeePerGas")
|
|
453
|
+
)
|
|
454
|
+
if max_priority_fee_per_gas is not None:
|
|
455
|
+
tx_params["maxPriorityFeePerGas"] = max_priority_fee_per_gas
|
|
456
|
+
|
|
457
|
+
nonce = _convert_hex_or_decimal(transaction_request.get("nonce"))
|
|
458
|
+
if nonce is not None:
|
|
459
|
+
tx_params["nonce"] = nonce
|
|
460
|
+
|
|
461
|
+
from_address = transaction_request.get("from") or wallet_address
|
|
462
|
+
if from_address:
|
|
463
|
+
tx_params["from"] = Web3.to_checksum_address(from_address)
|
|
464
|
+
|
|
465
|
+
return tx_params
|
|
466
|
+
|
|
414
467
|
|
|
415
|
-
def format_quote_basic_info(data:
|
|
468
|
+
def format_quote_basic_info(data: dict[str, Any]) -> dict[str, Any]:
|
|
416
469
|
"""
|
|
417
470
|
Extract and format basic quote information.
|
|
418
471
|
|
|
@@ -450,7 +503,7 @@ def format_quote_basic_info(data: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
450
503
|
}
|
|
451
504
|
|
|
452
505
|
|
|
453
|
-
def format_fees_and_gas(data:
|
|
506
|
+
def format_fees_and_gas(data: dict[str, Any]) -> tuple[str, str]:
|
|
454
507
|
"""
|
|
455
508
|
Format fee and gas cost information from quote data.
|
|
456
509
|
|
|
@@ -464,7 +517,7 @@ def format_fees_and_gas(data: Dict[str, Any]) -> Tuple[str, str]:
|
|
|
464
517
|
|
|
465
518
|
# Extract gas and fee costs
|
|
466
519
|
gas_costs = estimate.get("gasCosts", [])
|
|
467
|
-
fee_costs = []
|
|
520
|
+
fee_costs: list[dict[str, Any]] = []
|
|
468
521
|
|
|
469
522
|
# Collect fee information from included steps
|
|
470
523
|
for step in data.get("includedSteps", []):
|
|
@@ -476,7 +529,7 @@ def format_fees_and_gas(data: Dict[str, Any]) -> Tuple[str, str]:
|
|
|
476
529
|
fees_text = ""
|
|
477
530
|
if fee_costs:
|
|
478
531
|
fees_text = "**Fees:**\n"
|
|
479
|
-
total_fee_usd = 0
|
|
532
|
+
total_fee_usd = 0.0
|
|
480
533
|
for fee in fee_costs:
|
|
481
534
|
fee_name = fee.get("name", "Unknown fee")
|
|
482
535
|
fee_amount = fee.get("amount", "0")
|
|
@@ -508,7 +561,7 @@ def format_fees_and_gas(data: Dict[str, Any]) -> Tuple[str, str]:
|
|
|
508
561
|
gas_text = ""
|
|
509
562
|
if gas_costs:
|
|
510
563
|
gas_text = "**Gas Cost:**\n"
|
|
511
|
-
total_gas_usd = 0
|
|
564
|
+
total_gas_usd = 0.0
|
|
512
565
|
for gas in gas_costs:
|
|
513
566
|
gas_amount = gas.get("amount", "0")
|
|
514
567
|
gas_token = gas.get("token", {}).get("symbol", "ETH")
|
|
@@ -531,7 +584,7 @@ def format_fees_and_gas(data: Dict[str, Any]) -> Tuple[str, str]:
|
|
|
531
584
|
return fees_text, gas_text
|
|
532
585
|
|
|
533
586
|
|
|
534
|
-
def format_route_info(data:
|
|
587
|
+
def format_route_info(data: dict[str, Any]) -> str:
|
|
535
588
|
"""
|
|
536
589
|
Format routing information from quote data.
|
|
537
590
|
|
|
@@ -628,7 +681,7 @@ def get_explorer_url(chain_id: int, tx_hash: str) -> str:
|
|
|
628
681
|
|
|
629
682
|
|
|
630
683
|
def format_transaction_result(
|
|
631
|
-
tx_hash: str, chain_id: int, token_info: dict = None
|
|
684
|
+
tx_hash: str, chain_id: int, token_info: dict[str, str] | None = None
|
|
632
685
|
) -> str:
|
|
633
686
|
"""
|
|
634
687
|
Format transaction result with explorer link.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"""Wallet Portfolio Skills for IntentKit."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import NotRequired, TypedDict
|
|
5
5
|
|
|
6
|
-
from intentkit.
|
|
6
|
+
from intentkit.config.config import config as system_config
|
|
7
7
|
from intentkit.skills.base import SkillConfig, SkillState
|
|
8
8
|
from intentkit.skills.moralis.base import WalletBaseTool
|
|
9
9
|
from intentkit.skills.moralis.fetch_chain_portfolio import FetchChainPortfolio
|
|
@@ -28,21 +28,19 @@ class Config(SkillConfig):
|
|
|
28
28
|
|
|
29
29
|
api_key: str
|
|
30
30
|
states: SkillStates
|
|
31
|
-
supported_chains: NotRequired[
|
|
31
|
+
supported_chains: NotRequired[dict[str, bool]] = {"evm": True, "solana": True}
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
async def get_skills(
|
|
35
35
|
config: "Config",
|
|
36
36
|
is_private: bool,
|
|
37
|
-
store: SkillStoreABC,
|
|
38
37
|
**_,
|
|
39
|
-
) ->
|
|
38
|
+
) -> list[WalletBaseTool]:
|
|
40
39
|
"""Get all Wallet Portfolio skills.
|
|
41
40
|
|
|
42
41
|
Args:
|
|
43
42
|
config: Skill configuration
|
|
44
43
|
is_private: Whether the request is from an authenticated user
|
|
45
|
-
store: Skill store for persistence
|
|
46
44
|
chain_provider: Optional chain provider for blockchain interactions
|
|
47
45
|
**_: Additional arguments
|
|
48
46
|
|
|
@@ -67,12 +65,12 @@ async def get_skills(
|
|
|
67
65
|
if config.get("api_key_provider") == "agent_owner":
|
|
68
66
|
api_key = config.get("api_key")
|
|
69
67
|
else:
|
|
70
|
-
api_key =
|
|
68
|
+
api_key = system_config.moralis_api_key
|
|
71
69
|
|
|
72
70
|
# Get each skill using the getter
|
|
73
71
|
result = []
|
|
74
72
|
for name in available_skills:
|
|
75
|
-
skill = get_wallet_skill(name, api_key
|
|
73
|
+
skill = get_wallet_skill(name, api_key)
|
|
76
74
|
if skill:
|
|
77
75
|
result.append(skill)
|
|
78
76
|
return result
|
|
@@ -81,7 +79,6 @@ async def get_skills(
|
|
|
81
79
|
def get_wallet_skill(
|
|
82
80
|
name: str,
|
|
83
81
|
api_key: str,
|
|
84
|
-
store: SkillStoreABC,
|
|
85
82
|
) -> WalletBaseTool:
|
|
86
83
|
"""Get a specific Wallet Portfolio skill by name.
|
|
87
84
|
|
|
@@ -106,5 +103,4 @@ def get_wallet_skill(
|
|
|
106
103
|
|
|
107
104
|
return skill_classes[name](
|
|
108
105
|
api_key=api_key,
|
|
109
|
-
skill_store=store,
|
|
110
106
|
)
|
intentkit/skills/moralis/api.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""API interface for wallet data providers (EVM chains and Solana)."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from typing import Dict
|
|
5
4
|
|
|
6
5
|
import httpx
|
|
7
6
|
|
|
@@ -163,7 +162,7 @@ async def fetch_net_worth(api_key: str, address: str) -> dict:
|
|
|
163
162
|
#############################################
|
|
164
163
|
|
|
165
164
|
|
|
166
|
-
async def fetch_solana_api(api_key: str, endpoint: str, params:
|
|
165
|
+
async def fetch_solana_api(api_key: str, endpoint: str, params: dict = None) -> dict:
|
|
167
166
|
"""Base function for Solana API calls using Moralis.
|
|
168
167
|
|
|
169
168
|
Args:
|
|
@@ -200,7 +199,7 @@ async def fetch_solana_api(api_key: str, endpoint: str, params: Dict = None) ->
|
|
|
200
199
|
|
|
201
200
|
async def get_solana_portfolio(
|
|
202
201
|
api_key: str, address: str, network: str = "mainnet"
|
|
203
|
-
) ->
|
|
202
|
+
) -> dict:
|
|
204
203
|
"""Get complete portfolio for a Solana wallet.
|
|
205
204
|
|
|
206
205
|
Args:
|
|
@@ -217,7 +216,7 @@ async def get_solana_portfolio(
|
|
|
217
216
|
|
|
218
217
|
async def get_solana_balance(
|
|
219
218
|
api_key: str, address: str, network: str = "mainnet"
|
|
220
|
-
) ->
|
|
219
|
+
) -> dict:
|
|
221
220
|
"""Get native SOL balance.
|
|
222
221
|
|
|
223
222
|
Args:
|
|
@@ -234,7 +233,7 @@ async def get_solana_balance(
|
|
|
234
233
|
|
|
235
234
|
async def get_solana_spl_tokens(
|
|
236
235
|
api_key: str, address: str, network: str = "mainnet"
|
|
237
|
-
) ->
|
|
236
|
+
) -> dict:
|
|
238
237
|
"""Get SPL token balances.
|
|
239
238
|
|
|
240
239
|
Args:
|
|
@@ -249,7 +248,7 @@ async def get_solana_spl_tokens(
|
|
|
249
248
|
return await fetch_solana_api(api_key, endpoint)
|
|
250
249
|
|
|
251
250
|
|
|
252
|
-
async def get_solana_nfts(api_key: str, address: str, network: str = "mainnet") ->
|
|
251
|
+
async def get_solana_nfts(api_key: str, address: str, network: str = "mainnet") -> dict:
|
|
253
252
|
"""Get NFTs owned by a Solana wallet.
|
|
254
253
|
|
|
255
254
|
Args:
|
|
@@ -266,7 +265,7 @@ async def get_solana_nfts(api_key: str, address: str, network: str = "mainnet")
|
|
|
266
265
|
|
|
267
266
|
async def get_token_price(
|
|
268
267
|
api_key: str, token_address: str, network: str = "mainnet"
|
|
269
|
-
) ->
|
|
268
|
+
) -> dict:
|
|
270
269
|
"""Get token price by mint address.
|
|
271
270
|
|
|
272
271
|
Args:
|
intentkit/skills/moralis/base.py
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
"""Base class for Wallet Portfolio tools."""
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
|
|
5
|
-
from langchain.tools.base import ToolException
|
|
3
|
+
from langchain_core.tools.base import ToolException
|
|
6
4
|
from pydantic import BaseModel, Field
|
|
7
5
|
|
|
8
|
-
from intentkit.
|
|
6
|
+
from intentkit.config.config import config
|
|
9
7
|
from intentkit.skills.base import IntentKitSkill
|
|
10
8
|
|
|
11
9
|
# Chain ID to chain name mapping for EVM chains
|
|
@@ -29,13 +27,10 @@ class WalletBaseTool(IntentKitSkill):
|
|
|
29
27
|
|
|
30
28
|
name: str = Field(description="The name of the tool")
|
|
31
29
|
description: str = Field(description="A description of what the tool does")
|
|
32
|
-
args_schema:
|
|
33
|
-
skill_store: SkillStoreABC = Field(
|
|
34
|
-
description="The skill store for persisting data"
|
|
35
|
-
)
|
|
30
|
+
args_schema: type[BaseModel]
|
|
36
31
|
|
|
37
32
|
# Optional fields for blockchain providers
|
|
38
|
-
solana_networks:
|
|
33
|
+
solana_networks: list[str] | None = Field(
|
|
39
34
|
default=SOLANA_NETWORKS, description="Supported Solana networks"
|
|
40
35
|
)
|
|
41
36
|
|
|
@@ -44,7 +39,7 @@ class WalletBaseTool(IntentKitSkill):
|
|
|
44
39
|
skill_config = context.agent.skill_config(self.category)
|
|
45
40
|
api_key_provider = skill_config.get("api_key_provider")
|
|
46
41
|
if api_key_provider == "platform":
|
|
47
|
-
return
|
|
42
|
+
return config.moralis_api_key
|
|
48
43
|
# for backward compatibility, may only have api_key in skill_config
|
|
49
44
|
elif skill_config.get("api_key"):
|
|
50
45
|
return skill_config.get("api_key")
|