intentkit 0.7.5.dev3__py3-none-any.whl → 0.8.34.dev7__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.
- intentkit/MANIFEST.in +14 -0
- intentkit/README.md +88 -0
- intentkit/__init__.py +6 -4
- intentkit/abstracts/agent.py +4 -5
- intentkit/abstracts/engine.py +5 -5
- intentkit/abstracts/graph.py +15 -8
- intentkit/abstracts/skill.py +6 -144
- intentkit/abstracts/twitter.py +4 -5
- intentkit/clients/__init__.py +9 -2
- intentkit/clients/cdp.py +129 -153
- intentkit/{utils → clients}/s3.py +109 -34
- intentkit/clients/twitter.py +83 -62
- intentkit/clients/web3.py +4 -7
- intentkit/config/config.py +123 -90
- intentkit/core/account_checking.py +802 -0
- intentkit/core/agent.py +313 -498
- intentkit/core/asset.py +267 -0
- intentkit/core/chat.py +5 -3
- intentkit/core/client.py +1 -1
- intentkit/core/credit.py +49 -41
- intentkit/core/draft.py +201 -0
- intentkit/core/draft_chat.py +118 -0
- intentkit/core/engine.py +378 -287
- intentkit/core/manager/__init__.py +25 -0
- intentkit/core/manager/engine.py +220 -0
- intentkit/core/manager/service.py +172 -0
- intentkit/core/manager/skills.py +178 -0
- intentkit/core/middleware.py +231 -0
- intentkit/core/prompt.py +74 -114
- intentkit/core/scheduler.py +143 -0
- intentkit/core/statistics.py +168 -0
- intentkit/models/agent.py +931 -518
- intentkit/models/agent_data.py +165 -106
- intentkit/models/agent_schema.json +38 -251
- intentkit/models/app_setting.py +15 -13
- intentkit/models/chat.py +86 -140
- intentkit/models/credit.py +182 -162
- intentkit/models/db.py +42 -23
- intentkit/models/db_mig.py +120 -3
- intentkit/models/draft.py +222 -0
- intentkit/models/llm.csv +31 -0
- intentkit/models/llm.py +262 -370
- intentkit/models/redis.py +6 -4
- intentkit/models/skill.py +222 -101
- intentkit/models/skills.csv +173 -0
- intentkit/models/team.py +189 -0
- intentkit/models/user.py +103 -31
- 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 +241 -41
- 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 +6 -6
- intentkit/skills/casino/__init__.py +4 -15
- intentkit/skills/casino/base.py +1 -7
- intentkit/skills/casino/deck_draw.py +5 -8
- intentkit/skills/casino/deck_shuffle.py +6 -6
- intentkit/skills/casino/dice_roll.py +2 -4
- intentkit/skills/casino/schema.json +0 -1
- 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 +10 -24
- 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 +8 -19
- 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/__init__.py +97 -102
- intentkit/skills/dexscreener/base.py +125 -130
- intentkit/skills/dexscreener/get_pair_info.py +4 -5
- intentkit/skills/dexscreener/get_token_pairs.py +4 -5
- intentkit/skills/dexscreener/get_tokens_info.py +7 -8
- intentkit/skills/dexscreener/model/search_token_response.py +80 -82
- intentkit/skills/dexscreener/schema.json +91 -93
- intentkit/skills/dexscreener/search_token.py +182 -184
- intentkit/skills/dexscreener/utils.py +15 -14
- 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 +54 -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/__init__.py +5 -18
- intentkit/skills/firecrawl/base.py +4 -9
- 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 +2 -6
- intentkit/skills/firecrawl/scrape.py +17 -22
- 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 +13 -15
- intentkit/skills/heurist/image_generation_arthemy_comics.py +13 -15
- intentkit/skills/heurist/image_generation_arthemy_real.py +13 -15
- intentkit/skills/heurist/image_generation_braindance.py +13 -15
- intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +13 -15
- intentkit/skills/heurist/image_generation_flux_1_dev.py +13 -15
- intentkit/skills/heurist/image_generation_sdxl.py +13 -15
- 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 +3 -9
- intentkit/skills/lifi/schema.json +17 -8
- intentkit/skills/lifi/token_execute.py +150 -60
- 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 +30 -0
- intentkit/skills/openai/__init__.py +17 -18
- intentkit/skills/openai/base.py +10 -14
- intentkit/skills/openai/dalle_image_generation.py +4 -9
- intentkit/skills/openai/gpt_avatar_generator.py +102 -0
- intentkit/skills/openai/gpt_image_generation.py +5 -9
- intentkit/skills/openai/gpt_image_mini_generator.py +92 -0
- intentkit/skills/openai/gpt_image_to_image.py +5 -9
- 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 +36 -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 +1 -7
- intentkit/skills/supabase/delete_data.py +4 -4
- intentkit/skills/supabase/fetch_data.py +12 -12
- intentkit/skills/supabase/insert_data.py +4 -4
- intentkit/skills/supabase/invoke_function.py +6 -6
- intentkit/skills/supabase/schema.json +2 -3
- intentkit/skills/supabase/update_data.py +6 -6
- intentkit/skills/supabase/upsert_data.py +4 -4
- 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 +22 -34
- intentkit/skills/twitter/follow_user.py +2 -6
- intentkit/skills/twitter/get_mentions.py +5 -12
- intentkit/skills/twitter/get_timeline.py +4 -12
- intentkit/skills/twitter/get_user_by_username.py +2 -6
- intentkit/skills/twitter/get_user_tweets.py +5 -13
- intentkit/skills/twitter/like_tweet.py +2 -6
- intentkit/skills/twitter/post_tweet.py +6 -9
- intentkit/skills/twitter/reply_tweet.py +6 -9
- intentkit/skills/twitter/retweet.py +2 -6
- intentkit/skills/twitter/schema.json +1 -0
- intentkit/skills/twitter/search_tweets.py +4 -12
- 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 +11 -10
- 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 +58 -0
- intentkit/skills/x402/base.py +99 -0
- intentkit/skills/x402/http_request.py +117 -0
- intentkit/skills/x402/schema.json +40 -0
- intentkit/skills/x402/x402.webp +0 -0
- intentkit/skills/xmtp/__init__.py +4 -15
- intentkit/skills/xmtp/base.py +5 -5
- intentkit/skills/xmtp/price.py +7 -6
- intentkit/skills/xmtp/schema.json +69 -71
- intentkit/skills/xmtp/swap.py +6 -8
- intentkit/skills/xmtp/transfer.py +4 -6
- intentkit/utils/__init__.py +4 -0
- intentkit/utils/chain.py +198 -96
- intentkit/utils/ens.py +135 -0
- intentkit/utils/error.py +5 -2
- intentkit/utils/logging.py +9 -11
- intentkit/utils/schema.py +100 -0
- intentkit/utils/slack_alert.py +8 -8
- intentkit/utils/tx.py +16 -8
- intentkit/uv.lock +3377 -0
- {intentkit-0.7.5.dev3.dist-info → intentkit-0.8.34.dev7.dist-info}/METADATA +13 -15
- intentkit-0.8.34.dev7.dist-info/RECORD +478 -0
- intentkit-0.8.34.dev7.dist-info/licenses/LICENSE +21 -0
- intentkit/core/node.py +0 -215
- intentkit/models/conversation.py +0 -286
- 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.7.5.dev3.dist-info/RECORD +0 -424
- {intentkit-0.7.5.dev3.dist-info/licenses → intentkit}/LICENSE +0 -0
- {intentkit-0.7.5.dev3.dist-info → intentkit-0.8.34.dev7.dist-info}/WHEEL +0 -0
|
@@ -1,75 +1,73 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"title": "XMTP",
|
|
5
|
+
"description": "Use this skill only if you want make an XMTP Agent. XMTP protocol skills for creating blockchain transaction requests that can be sent to users for signing",
|
|
6
|
+
"x-icon": "https://ai.service.crestal.dev/skills/xmtp/xmtp.png",
|
|
7
|
+
"x-tags": [
|
|
8
|
+
"Communication",
|
|
9
|
+
"Crypto",
|
|
10
|
+
"DeFi"
|
|
11
|
+
],
|
|
12
|
+
"properties": {
|
|
13
|
+
"enabled": {
|
|
14
|
+
"type": "boolean",
|
|
15
|
+
"title": "Enabled",
|
|
16
|
+
"description": "Whether this skill is enabled",
|
|
17
|
+
"default": false
|
|
18
|
+
},
|
|
19
|
+
"states": {
|
|
20
|
+
"type": "object",
|
|
21
|
+
"properties": {
|
|
22
|
+
"xmtp_transfer": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"title": "XMTP Transfer",
|
|
25
|
+
"enum": [
|
|
26
|
+
"disabled",
|
|
27
|
+
"public",
|
|
28
|
+
"private"
|
|
29
|
+
],
|
|
30
|
+
"x-enum-title": [
|
|
31
|
+
"Disabled",
|
|
32
|
+
"Agent Owner + All Users",
|
|
33
|
+
"Agent Owner Only"
|
|
34
|
+
],
|
|
35
|
+
"description": "Create XMTP transaction requests for transferring ETH or ERC20 tokens on Base mainnet. Supports both native ETH transfers and ERC20 token transfers. Generates wallet_sendCalls transaction data that users can sign.",
|
|
36
|
+
"default": "disabled"
|
|
20
37
|
},
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
],
|
|
53
|
-
"description": "Create XMTP transaction requests for swapping tokens on Base using CDP swap quote. Returns a wallet_sendCalls payload that can include an optional approval call and the swap call. Only supports base-mainnet and base-sepolia.",
|
|
54
|
-
"default": "disabled"
|
|
55
|
-
},
|
|
56
|
-
"xmtp_get_swap_price": {
|
|
57
|
-
"type": "string",
|
|
58
|
-
"title": "XMTP Get Swap Price",
|
|
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": "Get an indicative swap price/quote for token pair and amount on Base networks using CDP. Provides estimated output amounts for token swaps without creating transactions.",
|
|
70
|
-
"default": "disabled"
|
|
71
|
-
}
|
|
72
|
-
}
|
|
38
|
+
"xmtp_swap": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"title": "XMTP Swap",
|
|
41
|
+
"enum": [
|
|
42
|
+
"disabled",
|
|
43
|
+
"public",
|
|
44
|
+
"private"
|
|
45
|
+
],
|
|
46
|
+
"x-enum-title": [
|
|
47
|
+
"Disabled",
|
|
48
|
+
"Agent Owner + All Users",
|
|
49
|
+
"Agent Owner Only"
|
|
50
|
+
],
|
|
51
|
+
"description": "Create XMTP transaction requests for swapping tokens on Base using CDP swap quote. Returns a wallet_sendCalls payload that can include an optional approval call and the swap call. Only supports base-mainnet and base-sepolia.",
|
|
52
|
+
"default": "disabled"
|
|
53
|
+
},
|
|
54
|
+
"xmtp_get_swap_price": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"title": "XMTP Get Swap Price",
|
|
57
|
+
"enum": [
|
|
58
|
+
"disabled",
|
|
59
|
+
"public",
|
|
60
|
+
"private"
|
|
61
|
+
],
|
|
62
|
+
"x-enum-title": [
|
|
63
|
+
"Disabled",
|
|
64
|
+
"Agent Owner + All Users",
|
|
65
|
+
"Agent Owner Only"
|
|
66
|
+
],
|
|
67
|
+
"description": "Get an indicative swap price/quote for token pair and amount on Base networks using CDP. Provides estimated output amounts for token swaps without creating transactions.",
|
|
68
|
+
"default": "disabled"
|
|
73
69
|
}
|
|
70
|
+
}
|
|
74
71
|
}
|
|
75
|
-
}
|
|
72
|
+
}
|
|
73
|
+
}
|
intentkit/skills/xmtp/swap.py
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
from typing import List, Tuple, Type
|
|
2
|
-
|
|
3
1
|
from pydantic import BaseModel, Field
|
|
4
2
|
|
|
5
|
-
from intentkit.clients.cdp import
|
|
3
|
+
from intentkit.clients.cdp import get_cdp_client
|
|
6
4
|
from intentkit.models.chat import ChatMessageAttachment, ChatMessageAttachmentType
|
|
7
5
|
from intentkit.skills.xmtp.base import XmtpBaseTool
|
|
8
6
|
|
|
@@ -42,7 +40,7 @@ class XmtpSwap(XmtpBaseTool):
|
|
|
42
40
|
"Returns a wallet_sendCalls payload that can include an optional approval call and the swap call. "
|
|
43
41
|
"Supports Ethereum, Base, Arbitrum, and Optimism mainnet networks."
|
|
44
42
|
)
|
|
45
|
-
args_schema:
|
|
43
|
+
args_schema: type[BaseModel] = SwapInput
|
|
46
44
|
|
|
47
45
|
async def _arun(
|
|
48
46
|
self,
|
|
@@ -51,7 +49,7 @@ class XmtpSwap(XmtpBaseTool):
|
|
|
51
49
|
to_token: str,
|
|
52
50
|
from_amount: str,
|
|
53
51
|
slippage_bps: int = 100,
|
|
54
|
-
) ->
|
|
52
|
+
) -> tuple[str, list[ChatMessageAttachment]]:
|
|
55
53
|
# Input validation
|
|
56
54
|
if (
|
|
57
55
|
not from_address
|
|
@@ -107,15 +105,15 @@ class XmtpSwap(XmtpBaseTool):
|
|
|
107
105
|
# https://github.com/coinbase/cdp-sdk/blob/main/examples/python/evm/swaps/create_swap_quote.py
|
|
108
106
|
network_for_cdp = self.get_cdp_network(agent.network_id)
|
|
109
107
|
|
|
110
|
-
# Get CDP client from global
|
|
111
|
-
cdp_client =
|
|
108
|
+
# Get CDP client from the global helper (server-side credentials)
|
|
109
|
+
cdp_client = get_cdp_client()
|
|
112
110
|
|
|
113
111
|
# Call CDP to create swap quote and extract call datas
|
|
114
112
|
# Be permissive with response shape across SDK versions
|
|
115
113
|
try:
|
|
116
114
|
# Attempt the canonical method per CDP SDK examples
|
|
117
115
|
# create_swap_quote(from_token, to_token, from_amount, network, taker, slippage_bps, signer_address)
|
|
118
|
-
# Note: Don't use async with context manager as
|
|
116
|
+
# Note: Don't use async with context manager as get_cdp_client returns a managed global client
|
|
119
117
|
quote = await cdp_client.evm.create_swap_quote(
|
|
120
118
|
from_token=from_token,
|
|
121
119
|
to_token=to_token,
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import List, Optional, Tuple, Type
|
|
2
|
-
|
|
3
1
|
from pydantic import BaseModel, Field
|
|
4
2
|
from web3.exceptions import ContractLogicError
|
|
5
3
|
|
|
@@ -16,7 +14,7 @@ class TransferInput(BaseModel):
|
|
|
16
14
|
description="The amount to transfer in human-readable format (e.g., '1.5' for 1.5 ETH, '100' for 100 USDC). Do NOT multiply by token decimals."
|
|
17
15
|
)
|
|
18
16
|
currency: str = Field(description="Currency symbol (e.g., 'ETH', 'USDC', 'NATION')")
|
|
19
|
-
token_contract_address:
|
|
17
|
+
token_contract_address: str | None = Field(
|
|
20
18
|
default=None,
|
|
21
19
|
description="Token contract address for ERC20 transfers. Leave empty for ETH transfers.",
|
|
22
20
|
)
|
|
@@ -31,7 +29,7 @@ class XmtpTransfer(XmtpBaseTool):
|
|
|
31
29
|
that can be sent to users for signing.
|
|
32
30
|
Supports Ethereum, Polygon, Base, Arbitrum, and Optimism networks (both mainnet and testnet).
|
|
33
31
|
"""
|
|
34
|
-
args_schema:
|
|
32
|
+
args_schema: type[BaseModel] = TransferInput
|
|
35
33
|
|
|
36
34
|
async def _arun(
|
|
37
35
|
self,
|
|
@@ -39,8 +37,8 @@ class XmtpTransfer(XmtpBaseTool):
|
|
|
39
37
|
to_address: str,
|
|
40
38
|
amount: str,
|
|
41
39
|
currency: str,
|
|
42
|
-
token_contract_address:
|
|
43
|
-
) ->
|
|
40
|
+
token_contract_address: str | None,
|
|
41
|
+
) -> tuple[str, list[ChatMessageAttachment]]:
|
|
44
42
|
"""Create an XMTP transfer transaction request.
|
|
45
43
|
|
|
46
44
|
Args:
|
intentkit/utils/__init__.py
CHANGED
intentkit/utils/chain.py
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from abc import ABC, abstractmethod
|
|
2
3
|
from enum import IntEnum, StrEnum
|
|
3
4
|
|
|
4
5
|
import httpx
|
|
5
6
|
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
6
9
|
|
|
7
10
|
class Chain(StrEnum):
|
|
8
11
|
"""
|
|
@@ -54,7 +57,7 @@ class Chain(StrEnum):
|
|
|
54
57
|
Frontera = "frontera"
|
|
55
58
|
|
|
56
59
|
|
|
57
|
-
class
|
|
60
|
+
class QuickNodeNetwork(StrEnum):
|
|
58
61
|
"""
|
|
59
62
|
Enum of well-known blockchain network names, based on QuickNode API.
|
|
60
63
|
|
|
@@ -65,9 +68,9 @@ class Network(StrEnum):
|
|
|
65
68
|
"""
|
|
66
69
|
|
|
67
70
|
# Ethereum Mainnet and Testnets
|
|
68
|
-
EthereumMainnet = "
|
|
69
|
-
EthereumGoerli = "
|
|
70
|
-
EthereumSepolia = "
|
|
71
|
+
EthereumMainnet = "mainnet"
|
|
72
|
+
EthereumGoerli = "goerli" # Goerli Testnet (deprecated, Sepolia preferred)
|
|
73
|
+
EthereumSepolia = "sepolia"
|
|
71
74
|
|
|
72
75
|
# Layer 2s on Ethereum
|
|
73
76
|
ArbitrumMainnet = "arbitrum-mainnet"
|
|
@@ -150,51 +153,123 @@ class NetworkId(IntEnum):
|
|
|
150
153
|
BeraMainnet = 80094
|
|
151
154
|
|
|
152
155
|
|
|
153
|
-
# Mapping of
|
|
156
|
+
# Mapping of QuickNodeNetwork enum members to their corresponding NetworkId enum members.
|
|
154
157
|
# This dictionary facilitates efficient lookup of network IDs given a network name.
|
|
155
158
|
# Note: SolanaMainnet is intentionally excluded as it does not have a numeric chain ID.
|
|
156
159
|
# Always refer to the official documentation for the most up-to-date mappings.
|
|
157
|
-
network_to_id: dict[
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
160
|
+
network_to_id: dict[QuickNodeNetwork, NetworkId] = {
|
|
161
|
+
QuickNodeNetwork.ArbitrumMainnet: NetworkId.ArbitrumMainnet,
|
|
162
|
+
QuickNodeNetwork.AvalancheMainnet: NetworkId.AvalancheMainnet,
|
|
163
|
+
QuickNodeNetwork.BaseMainnet: NetworkId.BaseMainnet,
|
|
164
|
+
QuickNodeNetwork.BaseSepolia: NetworkId.BaseSepolia,
|
|
165
|
+
QuickNodeNetwork.BeraMainnet: NetworkId.BeraMainnet,
|
|
166
|
+
QuickNodeNetwork.BinanceMainnet: NetworkId.BinanceMainnet,
|
|
167
|
+
QuickNodeNetwork.EthereumMainnet: NetworkId.EthereumMainnet,
|
|
168
|
+
QuickNodeNetwork.EthereumSepolia: NetworkId.EthereumSepolia,
|
|
169
|
+
QuickNodeNetwork.GnosisMainnet: NetworkId.GnosisMainnet,
|
|
170
|
+
QuickNodeNetwork.LineaMainnet: NetworkId.LineaMainnet,
|
|
171
|
+
QuickNodeNetwork.OptimismMainnet: NetworkId.OptimismMainnet,
|
|
172
|
+
QuickNodeNetwork.PolygonMainnet: NetworkId.PolygonMainnet,
|
|
173
|
+
QuickNodeNetwork.SonicMainnet: NetworkId.SonicMainnet,
|
|
174
|
+
QuickNodeNetwork.ZkSyncMainnet: NetworkId.ZkSyncMainnet,
|
|
172
175
|
}
|
|
173
176
|
|
|
174
177
|
# Mapping of NetworkId enum members (chain IDs) to their corresponding
|
|
175
|
-
#
|
|
178
|
+
# QuickNodeNetwork enum members (network names). This dictionary allows for reverse
|
|
176
179
|
# lookup, enabling retrieval of the network name given a chain ID.
|
|
177
180
|
# Note: Solana is not included here as it does not use a standard numeric
|
|
178
181
|
# chain ID. Always consult official documentation for the most
|
|
179
182
|
# up-to-date mappings.
|
|
180
|
-
id_to_network: dict[NetworkId,
|
|
181
|
-
NetworkId.ArbitrumMainnet:
|
|
182
|
-
NetworkId.AvalancheMainnet:
|
|
183
|
-
NetworkId.BaseMainnet:
|
|
184
|
-
NetworkId.BaseSepolia:
|
|
185
|
-
NetworkId.BeraMainnet:
|
|
186
|
-
NetworkId.BinanceMainnet:
|
|
187
|
-
NetworkId.EthereumMainnet:
|
|
188
|
-
NetworkId.EthereumSepolia:
|
|
189
|
-
NetworkId.GnosisMainnet:
|
|
190
|
-
NetworkId.LineaMainnet:
|
|
191
|
-
NetworkId.OptimismMainnet:
|
|
192
|
-
NetworkId.PolygonMainnet:
|
|
193
|
-
NetworkId.SonicMainnet:
|
|
194
|
-
NetworkId.ZkSyncMainnet:
|
|
183
|
+
id_to_network: dict[NetworkId, QuickNodeNetwork] = {
|
|
184
|
+
NetworkId.ArbitrumMainnet: QuickNodeNetwork.ArbitrumMainnet,
|
|
185
|
+
NetworkId.AvalancheMainnet: QuickNodeNetwork.AvalancheMainnet,
|
|
186
|
+
NetworkId.BaseMainnet: QuickNodeNetwork.BaseMainnet,
|
|
187
|
+
NetworkId.BaseSepolia: QuickNodeNetwork.BaseSepolia,
|
|
188
|
+
NetworkId.BeraMainnet: QuickNodeNetwork.BeraMainnet,
|
|
189
|
+
NetworkId.BinanceMainnet: QuickNodeNetwork.BinanceMainnet,
|
|
190
|
+
NetworkId.EthereumMainnet: QuickNodeNetwork.EthereumMainnet,
|
|
191
|
+
NetworkId.EthereumSepolia: QuickNodeNetwork.EthereumSepolia,
|
|
192
|
+
NetworkId.GnosisMainnet: QuickNodeNetwork.GnosisMainnet,
|
|
193
|
+
NetworkId.LineaMainnet: QuickNodeNetwork.LineaMainnet,
|
|
194
|
+
NetworkId.OptimismMainnet: QuickNodeNetwork.OptimismMainnet,
|
|
195
|
+
NetworkId.PolygonMainnet: QuickNodeNetwork.PolygonMainnet,
|
|
196
|
+
NetworkId.SonicMainnet: QuickNodeNetwork.SonicMainnet,
|
|
197
|
+
NetworkId.ZkSyncMainnet: QuickNodeNetwork.ZkSyncMainnet,
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
# Mapping of agent-level network identifiers to QuickNode network names.
|
|
201
|
+
# Agent configuration often uses human-friendly identifiers such as
|
|
202
|
+
# "ethereum-mainnet" or "solana" while QuickNode expects the canonical
|
|
203
|
+
# network strings defined in `QuickNodeNetwork`. This mapping bridges the two.
|
|
204
|
+
AGENT_NETWORK_TO_QUICKNODE_NETWORK: dict[str, QuickNodeNetwork] = {
|
|
205
|
+
"arbitrum-mainnet": QuickNodeNetwork.ArbitrumMainnet,
|
|
206
|
+
"avalanche-mainnet": QuickNodeNetwork.AvalancheMainnet,
|
|
207
|
+
"aurora-mainnet": QuickNodeNetwork.AuroraMainnet,
|
|
208
|
+
"axelar-mainnet": QuickNodeNetwork.AxelarMainnet,
|
|
209
|
+
"base-mainnet": QuickNodeNetwork.BaseMainnet,
|
|
210
|
+
"base-sepolia": QuickNodeNetwork.BaseSepolia,
|
|
211
|
+
"bera-mainnet": QuickNodeNetwork.BeraMainnet,
|
|
212
|
+
"binance-mainnet": QuickNodeNetwork.BinanceMainnet,
|
|
213
|
+
"bsc-mainnet": QuickNodeNetwork.BinanceMainnet,
|
|
214
|
+
"celo-mainnet": QuickNodeNetwork.CeloMainnet,
|
|
215
|
+
"ethereum": QuickNodeNetwork.EthereumMainnet,
|
|
216
|
+
"ethereum-mainnet": QuickNodeNetwork.EthereumMainnet,
|
|
217
|
+
"ethereum-sepolia": QuickNodeNetwork.EthereumSepolia,
|
|
218
|
+
"evmos-mainnet": QuickNodeNetwork.EvmosMainnet,
|
|
219
|
+
"fantom-mainnet": QuickNodeNetwork.FantomMainnet,
|
|
220
|
+
"frontera-mainnet": QuickNodeNetwork.FronteraMainnet,
|
|
221
|
+
"gnosis": QuickNodeNetwork.GnosisMainnet,
|
|
222
|
+
"gnosis-mainnet": QuickNodeNetwork.GnosisMainnet,
|
|
223
|
+
"goerli": QuickNodeNetwork.EthereumGoerli,
|
|
224
|
+
"kava-mainnet": QuickNodeNetwork.KavaMainnet,
|
|
225
|
+
"linea-mainnet": QuickNodeNetwork.LineaMainnet,
|
|
226
|
+
"matic": QuickNodeNetwork.PolygonMainnet,
|
|
227
|
+
"matic-mainnet": QuickNodeNetwork.PolygonMainnet,
|
|
228
|
+
"moonbeam-mainnet": QuickNodeNetwork.MoonbeamMainnet,
|
|
229
|
+
"near-mainnet": QuickNodeNetwork.NearMainnet,
|
|
230
|
+
"optimism-mainnet": QuickNodeNetwork.OptimismMainnet,
|
|
231
|
+
"persistence-mainnet": QuickNodeNetwork.PersistenceMainnet,
|
|
232
|
+
"polygon": QuickNodeNetwork.PolygonMainnet,
|
|
233
|
+
"polygon-mainnet": QuickNodeNetwork.PolygonMainnet,
|
|
234
|
+
"secret-mainnet": QuickNodeNetwork.SecretMainnet,
|
|
235
|
+
"sepolia": QuickNodeNetwork.EthereumSepolia,
|
|
236
|
+
"solana": QuickNodeNetwork.SolanaMainnet,
|
|
237
|
+
"solana-mainnet": QuickNodeNetwork.SolanaMainnet,
|
|
238
|
+
"sonic-mainnet": QuickNodeNetwork.SonicMainnet,
|
|
239
|
+
"stargaze-mainnet": QuickNodeNetwork.StargazeMainnet,
|
|
240
|
+
"terra-mainnet": QuickNodeNetwork.TerraMainnet,
|
|
241
|
+
"xdai": QuickNodeNetwork.GnosisMainnet,
|
|
242
|
+
"zksync-mainnet": QuickNodeNetwork.ZkSyncMainnet,
|
|
195
243
|
}
|
|
196
244
|
|
|
197
245
|
|
|
246
|
+
def resolve_quicknode_network(agent_network_id: str) -> QuickNodeNetwork:
|
|
247
|
+
"""Resolve an agent-level network identifier to a QuickNode network.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
agent_network_id: Network identifier stored on the agent model.
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
The corresponding `QuickNodeNetwork` enum value.
|
|
254
|
+
|
|
255
|
+
Raises:
|
|
256
|
+
ValueError: If the agent network identifier is empty or unmapped.
|
|
257
|
+
"""
|
|
258
|
+
|
|
259
|
+
normalized = (agent_network_id or "").strip().lower()
|
|
260
|
+
if not normalized:
|
|
261
|
+
raise ValueError("agent network_id must be provided")
|
|
262
|
+
|
|
263
|
+
mapped_network = AGENT_NETWORK_TO_QUICKNODE_NETWORK.get(normalized)
|
|
264
|
+
if mapped_network:
|
|
265
|
+
return mapped_network
|
|
266
|
+
|
|
267
|
+
try:
|
|
268
|
+
return QuickNodeNetwork(normalized)
|
|
269
|
+
except ValueError as exc: # pragma: no cover - defensive guard
|
|
270
|
+
raise ValueError(f"unsupported agent network_id: {agent_network_id}") from exc
|
|
271
|
+
|
|
272
|
+
|
|
198
273
|
class ChainConfig:
|
|
199
274
|
"""
|
|
200
275
|
Configuration class for a specific blockchain chain.
|
|
@@ -206,7 +281,7 @@ class ChainConfig:
|
|
|
206
281
|
def __init__(
|
|
207
282
|
self,
|
|
208
283
|
chain: Chain,
|
|
209
|
-
network:
|
|
284
|
+
network: QuickNodeNetwork,
|
|
210
285
|
rpc_url: str,
|
|
211
286
|
ens_url: str,
|
|
212
287
|
wss_url: str,
|
|
@@ -216,7 +291,7 @@ class ChainConfig:
|
|
|
216
291
|
|
|
217
292
|
Args:
|
|
218
293
|
chain: The Chain enum member representing the blockchain type (e.g., Ethereum, Solana).
|
|
219
|
-
network: The
|
|
294
|
+
network: The QuickNodeNetwork enum member representing the specific network (e.g., EthereumMainnet).
|
|
220
295
|
rpc_url: The URL for the RPC endpoint of the blockchain.
|
|
221
296
|
ens_url: The URL for the ENS (Ethereum Name Service) endpoint (can be None if not applicable).
|
|
222
297
|
wss_url: The URL for the WebSocket endpoint of the blockchain (can be None if not applicable).
|
|
@@ -236,9 +311,9 @@ class ChainConfig:
|
|
|
236
311
|
return self._chain
|
|
237
312
|
|
|
238
313
|
@property
|
|
239
|
-
def network(self) ->
|
|
314
|
+
def network(self) -> QuickNodeNetwork:
|
|
240
315
|
"""
|
|
241
|
-
Returns the
|
|
316
|
+
Returns the QuickNodeNetwork enum member.
|
|
242
317
|
"""
|
|
243
318
|
return self._network
|
|
244
319
|
|
|
@@ -287,14 +362,14 @@ class ChainProvider(ABC):
|
|
|
287
362
|
|
|
288
363
|
Sets up an empty dictionary `chain_configs` to store the configurations.
|
|
289
364
|
"""
|
|
290
|
-
self.chain_configs: dict[
|
|
365
|
+
self.chain_configs: dict[QuickNodeNetwork, ChainConfig] = {}
|
|
291
366
|
|
|
292
|
-
def get_chain_config(self,
|
|
367
|
+
def get_chain_config(self, network_id: str) -> ChainConfig:
|
|
293
368
|
"""
|
|
294
|
-
Retrieves the chain configuration for a specific network.
|
|
369
|
+
Retrieves the chain configuration for a specific agent network identifier.
|
|
295
370
|
|
|
296
371
|
Args:
|
|
297
|
-
|
|
372
|
+
network_id: The agent-level network identifier (e.g., "base-mainnet").
|
|
298
373
|
|
|
299
374
|
Returns:
|
|
300
375
|
The `ChainConfig` object associated with the given network.
|
|
@@ -302,17 +377,27 @@ class ChainProvider(ABC):
|
|
|
302
377
|
Raises:
|
|
303
378
|
Exception: If no chain configuration is found for the specified network.
|
|
304
379
|
"""
|
|
305
|
-
|
|
380
|
+
try:
|
|
381
|
+
quicknode_network = resolve_quicknode_network(network_id)
|
|
382
|
+
except ValueError as exc:
|
|
383
|
+
raise Exception(f"unsupported network_id: {network_id}") from exc
|
|
384
|
+
|
|
385
|
+
return self._get_chain_config_by_quicknode_network(quicknode_network)
|
|
386
|
+
|
|
387
|
+
def _get_chain_config_by_quicknode_network(
|
|
388
|
+
self, quicknode_network: QuickNodeNetwork
|
|
389
|
+
) -> ChainConfig:
|
|
390
|
+
chain_config = self.chain_configs.get(quicknode_network)
|
|
306
391
|
if not chain_config:
|
|
307
|
-
raise Exception(f"chain config for network {
|
|
392
|
+
raise Exception(f"chain config for network {quicknode_network} not found")
|
|
308
393
|
return chain_config
|
|
309
394
|
|
|
310
395
|
def get_chain_config_by_id(self, network_id: NetworkId) -> ChainConfig:
|
|
311
396
|
"""
|
|
312
397
|
Retrieves the chain configuration by network ID.
|
|
313
398
|
|
|
314
|
-
This method first looks up the `
|
|
315
|
-
provided `NetworkId` and then
|
|
399
|
+
This method first looks up the `QuickNodeNetwork` enum member associated
|
|
400
|
+
with the provided `NetworkId` and then retrieves the corresponding
|
|
316
401
|
configuration.
|
|
317
402
|
|
|
318
403
|
Args:
|
|
@@ -328,10 +413,10 @@ class ChainProvider(ABC):
|
|
|
328
413
|
network = id_to_network.get(network_id)
|
|
329
414
|
if not network:
|
|
330
415
|
raise Exception(f"network with id {network_id} not found")
|
|
331
|
-
return self.
|
|
416
|
+
return self._get_chain_config_by_quicknode_network(network)
|
|
332
417
|
|
|
333
418
|
@abstractmethod
|
|
334
|
-
def init_chain_configs(self,
|
|
419
|
+
def init_chain_configs(self, *_, **__) -> None:
|
|
335
420
|
"""
|
|
336
421
|
Initializes the chain configurations.
|
|
337
422
|
|
|
@@ -340,11 +425,8 @@ class ChainProvider(ABC):
|
|
|
340
425
|
`ChainConfig` objects, typically using the provided `api_key` to fetch
|
|
341
426
|
or generate the necessary configuration data.
|
|
342
427
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
Returns:
|
|
347
|
-
A dictionary mapping `Network` enum members to `ChainConfig` objects.
|
|
428
|
+
The method must mutate `self.chain_configs` in-place and does not need
|
|
429
|
+
to return anything.
|
|
348
430
|
"""
|
|
349
431
|
raise NotImplementedError
|
|
350
432
|
|
|
@@ -367,27 +449,18 @@ class QuicknodeChainProvider(ChainProvider):
|
|
|
367
449
|
super().__init__()
|
|
368
450
|
self.api_key = api_key
|
|
369
451
|
|
|
370
|
-
def init_chain_configs(
|
|
371
|
-
self, limit: int = 100, offset: int = 0
|
|
372
|
-
) -> dict[Network, ChainConfig]:
|
|
452
|
+
def init_chain_configs(self, limit: int = 100, offset: int = 0) -> None:
|
|
373
453
|
"""
|
|
374
454
|
Initializes chain configurations by fetching data from the QuickNode API.
|
|
375
455
|
|
|
376
456
|
This method retrieves a list of QuickNode endpoints using the provided
|
|
377
457
|
API key and populates the `chain_configs` dictionary with `ChainConfig`
|
|
378
|
-
objects.
|
|
458
|
+
objects. Errors are logged and do not raise exceptions so that any
|
|
459
|
+
successful configurations remain available.
|
|
379
460
|
|
|
380
461
|
Args:
|
|
381
462
|
limit: The maximum number of endpoints to retrieve (default: 100).
|
|
382
463
|
offset: The number of endpoints to skip (default: 0).
|
|
383
|
-
|
|
384
|
-
Returns:
|
|
385
|
-
A dictionary mapping `Network` enum members to `ChainConfig` objects.
|
|
386
|
-
|
|
387
|
-
Raises:
|
|
388
|
-
Exception: If an error occurs during the API request or processing
|
|
389
|
-
the response. More specific exception types are used
|
|
390
|
-
for HTTP errors and request errors.
|
|
391
464
|
"""
|
|
392
465
|
url = "https://api.quicknode.com/v0/endpoints"
|
|
393
466
|
headers = {
|
|
@@ -399,38 +472,67 @@ class QuicknodeChainProvider(ChainProvider):
|
|
|
399
472
|
"offset": offset,
|
|
400
473
|
}
|
|
401
474
|
|
|
402
|
-
with httpx.Client(timeout=30) as client:
|
|
475
|
+
with httpx.Client(timeout=30) as client:
|
|
403
476
|
try:
|
|
404
477
|
response = client.get(url, timeout=30, headers=headers, params=params)
|
|
405
|
-
response.raise_for_status()
|
|
478
|
+
response.raise_for_status()
|
|
406
479
|
json_dict = response.json()
|
|
407
|
-
|
|
408
|
-
for item in json_dict["data"]:
|
|
409
|
-
# Assuming 'item' contains 'chain', 'network', 'http_url', 'wss_url'
|
|
410
|
-
# and that these values can be used to construct the ChainConfig object
|
|
411
|
-
chain = Chain(item["chain"])
|
|
412
|
-
network = Network(item["network"])
|
|
413
|
-
|
|
414
|
-
self.chain_configs[item["network"]] = ChainConfig(
|
|
415
|
-
chain,
|
|
416
|
-
network,
|
|
417
|
-
item["http_url"],
|
|
418
|
-
item[
|
|
419
|
-
"http_url"
|
|
420
|
-
], # ens_url is the same as http_url in this case.
|
|
421
|
-
item["wss_url"],
|
|
422
|
-
)
|
|
423
|
-
|
|
424
480
|
except httpx.HTTPStatusError as http_err:
|
|
425
|
-
|
|
481
|
+
logger.error(
|
|
482
|
+
"QuickNode API HTTP error while initializing chain configs: %s",
|
|
483
|
+
http_err,
|
|
484
|
+
)
|
|
485
|
+
return
|
|
426
486
|
except httpx.RequestError as req_err:
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
487
|
+
logger.error(
|
|
488
|
+
"QuickNode API request error while initializing chain configs: %s",
|
|
489
|
+
req_err,
|
|
490
|
+
)
|
|
491
|
+
return
|
|
492
|
+
except Exception as exc:
|
|
493
|
+
logger.exception(
|
|
494
|
+
"Unexpected error while fetching QuickNode chain configs: %s", exc
|
|
495
|
+
)
|
|
496
|
+
return
|
|
497
|
+
|
|
498
|
+
data = json_dict.get("data", [])
|
|
499
|
+
if not isinstance(data, list):
|
|
500
|
+
logger.error(
|
|
501
|
+
"QuickNode chain configs response 'data' is not a list: %s", data
|
|
502
|
+
)
|
|
503
|
+
return
|
|
504
|
+
|
|
505
|
+
for item in data:
|
|
506
|
+
if not isinstance(item, dict):
|
|
507
|
+
logger.error("Skipping malformed QuickNode chain entry: %s", item)
|
|
508
|
+
continue
|
|
509
|
+
|
|
510
|
+
try:
|
|
511
|
+
chain_value = item["chain"]
|
|
512
|
+
network_value = item["network"]
|
|
513
|
+
rpc_url = item["http_url"]
|
|
514
|
+
chain = Chain(chain_value)
|
|
515
|
+
network = QuickNodeNetwork(network_value)
|
|
516
|
+
ens_url = item.get("ens_url", rpc_url)
|
|
517
|
+
wss_url = item.get("wss_url")
|
|
518
|
+
except ValueError as exc:
|
|
519
|
+
logger.debug("Skipping unsupported QuickNode entry %s: %s", item, exc)
|
|
520
|
+
continue
|
|
521
|
+
except KeyError as exc:
|
|
522
|
+
logger.error(
|
|
523
|
+
"Missing field %s in QuickNode chain config item %s", exc, item
|
|
524
|
+
)
|
|
525
|
+
continue
|
|
526
|
+
except Exception as exc:
|
|
527
|
+
logger.error(
|
|
528
|
+
"Failed processing QuickNode chain config item %s: %s", item, exc
|
|
434
529
|
)
|
|
435
|
-
|
|
436
|
-
|
|
530
|
+
continue
|
|
531
|
+
|
|
532
|
+
self.chain_configs[network] = ChainConfig(
|
|
533
|
+
chain,
|
|
534
|
+
network,
|
|
535
|
+
rpc_url,
|
|
536
|
+
ens_url,
|
|
537
|
+
wss_url,
|
|
538
|
+
)
|