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.
Files changed (393) hide show
  1. intentkit/MANIFEST.in +14 -0
  2. intentkit/README.md +88 -0
  3. intentkit/__init__.py +6 -4
  4. intentkit/abstracts/agent.py +4 -5
  5. intentkit/abstracts/engine.py +5 -5
  6. intentkit/abstracts/graph.py +15 -8
  7. intentkit/abstracts/skill.py +6 -144
  8. intentkit/abstracts/twitter.py +4 -5
  9. intentkit/clients/__init__.py +9 -2
  10. intentkit/clients/cdp.py +129 -153
  11. intentkit/{utils → clients}/s3.py +109 -34
  12. intentkit/clients/twitter.py +83 -62
  13. intentkit/clients/web3.py +4 -7
  14. intentkit/config/config.py +123 -90
  15. intentkit/core/account_checking.py +802 -0
  16. intentkit/core/agent.py +313 -498
  17. intentkit/core/asset.py +267 -0
  18. intentkit/core/chat.py +5 -3
  19. intentkit/core/client.py +1 -1
  20. intentkit/core/credit.py +49 -41
  21. intentkit/core/draft.py +201 -0
  22. intentkit/core/draft_chat.py +118 -0
  23. intentkit/core/engine.py +378 -287
  24. intentkit/core/manager/__init__.py +25 -0
  25. intentkit/core/manager/engine.py +220 -0
  26. intentkit/core/manager/service.py +172 -0
  27. intentkit/core/manager/skills.py +178 -0
  28. intentkit/core/middleware.py +231 -0
  29. intentkit/core/prompt.py +74 -114
  30. intentkit/core/scheduler.py +143 -0
  31. intentkit/core/statistics.py +168 -0
  32. intentkit/models/agent.py +931 -518
  33. intentkit/models/agent_data.py +165 -106
  34. intentkit/models/agent_schema.json +38 -251
  35. intentkit/models/app_setting.py +15 -13
  36. intentkit/models/chat.py +86 -140
  37. intentkit/models/credit.py +182 -162
  38. intentkit/models/db.py +42 -23
  39. intentkit/models/db_mig.py +120 -3
  40. intentkit/models/draft.py +222 -0
  41. intentkit/models/llm.csv +31 -0
  42. intentkit/models/llm.py +262 -370
  43. intentkit/models/redis.py +6 -4
  44. intentkit/models/skill.py +222 -101
  45. intentkit/models/skills.csv +173 -0
  46. intentkit/models/team.py +189 -0
  47. intentkit/models/user.py +103 -31
  48. intentkit/skills/acolyt/__init__.py +2 -9
  49. intentkit/skills/acolyt/ask.py +3 -4
  50. intentkit/skills/acolyt/base.py +4 -9
  51. intentkit/skills/acolyt/schema.json +4 -3
  52. intentkit/skills/aixbt/__init__.py +2 -13
  53. intentkit/skills/aixbt/base.py +1 -7
  54. intentkit/skills/aixbt/projects.py +14 -15
  55. intentkit/skills/aixbt/schema.json +4 -4
  56. intentkit/skills/allora/__init__.py +2 -9
  57. intentkit/skills/allora/base.py +4 -9
  58. intentkit/skills/allora/price.py +3 -4
  59. intentkit/skills/allora/schema.json +3 -2
  60. intentkit/skills/base.py +241 -41
  61. intentkit/skills/basename/__init__.py +51 -0
  62. intentkit/skills/basename/base.py +11 -0
  63. intentkit/skills/basename/basename.svg +11 -0
  64. intentkit/skills/basename/schema.json +58 -0
  65. intentkit/skills/carv/__init__.py +115 -121
  66. intentkit/skills/carv/base.py +184 -185
  67. intentkit/skills/carv/fetch_news.py +3 -3
  68. intentkit/skills/carv/onchain_query.py +4 -4
  69. intentkit/skills/carv/schema.json +134 -137
  70. intentkit/skills/carv/token_info_and_price.py +6 -6
  71. intentkit/skills/casino/__init__.py +4 -15
  72. intentkit/skills/casino/base.py +1 -7
  73. intentkit/skills/casino/deck_draw.py +5 -8
  74. intentkit/skills/casino/deck_shuffle.py +6 -6
  75. intentkit/skills/casino/dice_roll.py +2 -4
  76. intentkit/skills/casino/schema.json +0 -1
  77. intentkit/skills/cdp/__init__.py +22 -84
  78. intentkit/skills/cdp/base.py +1 -7
  79. intentkit/skills/cdp/schema.json +11 -314
  80. intentkit/skills/chainlist/__init__.py +2 -7
  81. intentkit/skills/chainlist/base.py +1 -7
  82. intentkit/skills/chainlist/chain_lookup.py +18 -18
  83. intentkit/skills/chainlist/schema.json +3 -5
  84. intentkit/skills/common/__init__.py +2 -9
  85. intentkit/skills/common/base.py +1 -7
  86. intentkit/skills/common/current_time.py +1 -2
  87. intentkit/skills/common/schema.json +2 -2
  88. intentkit/skills/cookiefun/__init__.py +6 -9
  89. intentkit/skills/cookiefun/base.py +2 -7
  90. intentkit/skills/cookiefun/get_account_details.py +7 -7
  91. intentkit/skills/cookiefun/get_account_feed.py +19 -19
  92. intentkit/skills/cookiefun/get_account_smart_followers.py +7 -7
  93. intentkit/skills/cookiefun/get_sectors.py +3 -3
  94. intentkit/skills/cookiefun/schema.json +1 -3
  95. intentkit/skills/cookiefun/search_accounts.py +9 -9
  96. intentkit/skills/cryptocompare/__init__.py +7 -24
  97. intentkit/skills/cryptocompare/api.py +2 -3
  98. intentkit/skills/cryptocompare/base.py +10 -24
  99. intentkit/skills/cryptocompare/fetch_news.py +4 -5
  100. intentkit/skills/cryptocompare/fetch_price.py +6 -7
  101. intentkit/skills/cryptocompare/fetch_top_exchanges.py +4 -5
  102. intentkit/skills/cryptocompare/fetch_top_market_cap.py +4 -5
  103. intentkit/skills/cryptocompare/fetch_top_volume.py +4 -5
  104. intentkit/skills/cryptocompare/fetch_trading_signals.py +5 -6
  105. intentkit/skills/cryptocompare/schema.json +3 -3
  106. intentkit/skills/cryptopanic/__init__.py +7 -10
  107. intentkit/skills/cryptopanic/base.py +51 -55
  108. intentkit/skills/cryptopanic/fetch_crypto_news.py +4 -8
  109. intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +5 -7
  110. intentkit/skills/cryptopanic/schema.json +105 -103
  111. intentkit/skills/dapplooker/__init__.py +2 -9
  112. intentkit/skills/dapplooker/base.py +4 -9
  113. intentkit/skills/dapplooker/dapplooker_token_data.py +7 -7
  114. intentkit/skills/dapplooker/schema.json +3 -5
  115. intentkit/skills/defillama/__init__.py +24 -74
  116. intentkit/skills/defillama/api.py +6 -9
  117. intentkit/skills/defillama/base.py +8 -19
  118. intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +8 -10
  119. intentkit/skills/defillama/coins/fetch_block.py +6 -8
  120. intentkit/skills/defillama/coins/fetch_current_prices.py +8 -10
  121. intentkit/skills/defillama/coins/fetch_first_price.py +7 -9
  122. intentkit/skills/defillama/coins/fetch_historical_prices.py +9 -11
  123. intentkit/skills/defillama/coins/fetch_price_chart.py +9 -11
  124. intentkit/skills/defillama/coins/fetch_price_percentage.py +7 -9
  125. intentkit/skills/defillama/config/chains.py +1 -3
  126. intentkit/skills/defillama/fees/fetch_fees_overview.py +24 -26
  127. intentkit/skills/defillama/schema.json +5 -1
  128. intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +16 -18
  129. intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +8 -10
  130. intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +5 -7
  131. intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +7 -9
  132. intentkit/skills/defillama/tests/api_integration.test.py +1 -1
  133. intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +4 -6
  134. intentkit/skills/defillama/tvl/fetch_chains.py +9 -11
  135. intentkit/skills/defillama/tvl/fetch_historical_tvl.py +4 -6
  136. intentkit/skills/defillama/tvl/fetch_protocol.py +32 -38
  137. intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +3 -5
  138. intentkit/skills/defillama/tvl/fetch_protocols.py +37 -45
  139. intentkit/skills/defillama/volumes/fetch_dex_overview.py +42 -48
  140. intentkit/skills/defillama/volumes/fetch_dex_summary.py +35 -37
  141. intentkit/skills/defillama/volumes/fetch_options_overview.py +24 -28
  142. intentkit/skills/defillama/yields/fetch_pool_chart.py +10 -12
  143. intentkit/skills/defillama/yields/fetch_pools.py +26 -30
  144. intentkit/skills/dexscreener/__init__.py +97 -102
  145. intentkit/skills/dexscreener/base.py +125 -130
  146. intentkit/skills/dexscreener/get_pair_info.py +4 -5
  147. intentkit/skills/dexscreener/get_token_pairs.py +4 -5
  148. intentkit/skills/dexscreener/get_tokens_info.py +7 -8
  149. intentkit/skills/dexscreener/model/search_token_response.py +80 -82
  150. intentkit/skills/dexscreener/schema.json +91 -93
  151. intentkit/skills/dexscreener/search_token.py +182 -184
  152. intentkit/skills/dexscreener/utils.py +15 -14
  153. intentkit/skills/dune_analytics/__init__.py +7 -9
  154. intentkit/skills/dune_analytics/base.py +48 -52
  155. intentkit/skills/dune_analytics/fetch_kol_buys.py +5 -7
  156. intentkit/skills/dune_analytics/fetch_nation_metrics.py +6 -8
  157. intentkit/skills/dune_analytics/schema.json +104 -99
  158. intentkit/skills/elfa/__init__.py +5 -18
  159. intentkit/skills/elfa/base.py +10 -14
  160. intentkit/skills/elfa/mention.py +19 -21
  161. intentkit/skills/elfa/schema.json +3 -2
  162. intentkit/skills/elfa/stats.py +4 -4
  163. intentkit/skills/elfa/tokens.py +12 -12
  164. intentkit/skills/elfa/utils.py +26 -28
  165. intentkit/skills/enso/__init__.py +11 -31
  166. intentkit/skills/enso/base.py +54 -35
  167. intentkit/skills/enso/best_yield.py +16 -24
  168. intentkit/skills/enso/networks.py +6 -11
  169. intentkit/skills/enso/prices.py +11 -13
  170. intentkit/skills/enso/route.py +34 -38
  171. intentkit/skills/enso/schema.json +3 -2
  172. intentkit/skills/enso/tokens.py +29 -38
  173. intentkit/skills/enso/wallet.py +76 -191
  174. intentkit/skills/erc20/__init__.py +50 -0
  175. intentkit/skills/erc20/base.py +11 -0
  176. intentkit/skills/erc20/erc20.svg +5 -0
  177. intentkit/skills/erc20/schema.json +74 -0
  178. intentkit/skills/erc721/__init__.py +53 -0
  179. intentkit/skills/erc721/base.py +11 -0
  180. intentkit/skills/erc721/erc721.svg +5 -0
  181. intentkit/skills/erc721/schema.json +90 -0
  182. intentkit/skills/firecrawl/__init__.py +5 -18
  183. intentkit/skills/firecrawl/base.py +4 -9
  184. intentkit/skills/firecrawl/clear.py +4 -8
  185. intentkit/skills/firecrawl/crawl.py +19 -19
  186. intentkit/skills/firecrawl/query.py +4 -3
  187. intentkit/skills/firecrawl/schema.json +2 -6
  188. intentkit/skills/firecrawl/scrape.py +17 -22
  189. intentkit/skills/firecrawl/utils.py +50 -42
  190. intentkit/skills/github/__init__.py +2 -7
  191. intentkit/skills/github/base.py +1 -7
  192. intentkit/skills/github/github_search.py +1 -2
  193. intentkit/skills/github/schema.json +3 -4
  194. intentkit/skills/heurist/__init__.py +8 -27
  195. intentkit/skills/heurist/base.py +4 -9
  196. intentkit/skills/heurist/image_generation_animagine_xl.py +13 -15
  197. intentkit/skills/heurist/image_generation_arthemy_comics.py +13 -15
  198. intentkit/skills/heurist/image_generation_arthemy_real.py +13 -15
  199. intentkit/skills/heurist/image_generation_braindance.py +13 -15
  200. intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +13 -15
  201. intentkit/skills/heurist/image_generation_flux_1_dev.py +13 -15
  202. intentkit/skills/heurist/image_generation_sdxl.py +13 -15
  203. intentkit/skills/heurist/schema.json +2 -2
  204. intentkit/skills/http/__init__.py +4 -15
  205. intentkit/skills/http/base.py +1 -7
  206. intentkit/skills/http/get.py +21 -16
  207. intentkit/skills/http/post.py +23 -18
  208. intentkit/skills/http/put.py +23 -18
  209. intentkit/skills/http/schema.json +4 -5
  210. intentkit/skills/lifi/__init__.py +8 -13
  211. intentkit/skills/lifi/base.py +3 -9
  212. intentkit/skills/lifi/schema.json +17 -8
  213. intentkit/skills/lifi/token_execute.py +150 -60
  214. intentkit/skills/lifi/token_quote.py +8 -10
  215. intentkit/skills/lifi/utils.py +104 -51
  216. intentkit/skills/moralis/__init__.py +6 -10
  217. intentkit/skills/moralis/api.py +6 -7
  218. intentkit/skills/moralis/base.py +5 -10
  219. intentkit/skills/moralis/fetch_chain_portfolio.py +10 -11
  220. intentkit/skills/moralis/fetch_nft_portfolio.py +22 -22
  221. intentkit/skills/moralis/fetch_solana_portfolio.py +11 -12
  222. intentkit/skills/moralis/fetch_wallet_portfolio.py +8 -9
  223. intentkit/skills/moralis/schema.json +7 -2
  224. intentkit/skills/morpho/__init__.py +52 -0
  225. intentkit/skills/morpho/base.py +11 -0
  226. intentkit/skills/morpho/morpho.svg +12 -0
  227. intentkit/skills/morpho/schema.json +73 -0
  228. intentkit/skills/nation/__init__.py +4 -9
  229. intentkit/skills/nation/base.py +5 -10
  230. intentkit/skills/nation/nft_check.py +3 -4
  231. intentkit/skills/nation/schema.json +4 -3
  232. intentkit/skills/onchain.py +30 -0
  233. intentkit/skills/openai/__init__.py +17 -18
  234. intentkit/skills/openai/base.py +10 -14
  235. intentkit/skills/openai/dalle_image_generation.py +4 -9
  236. intentkit/skills/openai/gpt_avatar_generator.py +102 -0
  237. intentkit/skills/openai/gpt_image_generation.py +5 -9
  238. intentkit/skills/openai/gpt_image_mini_generator.py +92 -0
  239. intentkit/skills/openai/gpt_image_to_image.py +5 -9
  240. intentkit/skills/openai/image_to_text.py +3 -7
  241. intentkit/skills/openai/schema.json +34 -3
  242. intentkit/skills/portfolio/__init__.py +11 -35
  243. intentkit/skills/portfolio/base.py +33 -19
  244. intentkit/skills/portfolio/schema.json +3 -5
  245. intentkit/skills/portfolio/token_balances.py +21 -21
  246. intentkit/skills/portfolio/wallet_approvals.py +17 -18
  247. intentkit/skills/portfolio/wallet_defi_positions.py +3 -3
  248. intentkit/skills/portfolio/wallet_history.py +31 -31
  249. intentkit/skills/portfolio/wallet_net_worth.py +13 -13
  250. intentkit/skills/portfolio/wallet_nfts.py +19 -19
  251. intentkit/skills/portfolio/wallet_profitability.py +18 -18
  252. intentkit/skills/portfolio/wallet_profitability_summary.py +5 -5
  253. intentkit/skills/portfolio/wallet_stats.py +3 -3
  254. intentkit/skills/portfolio/wallet_swaps.py +19 -19
  255. intentkit/skills/pyth/__init__.py +50 -0
  256. intentkit/skills/pyth/base.py +11 -0
  257. intentkit/skills/pyth/pyth.svg +6 -0
  258. intentkit/skills/pyth/schema.json +75 -0
  259. intentkit/skills/skills.toml +36 -0
  260. intentkit/skills/slack/__init__.py +5 -17
  261. intentkit/skills/slack/base.py +3 -9
  262. intentkit/skills/slack/get_channel.py +8 -8
  263. intentkit/skills/slack/get_message.py +9 -9
  264. intentkit/skills/slack/schedule_message.py +5 -5
  265. intentkit/skills/slack/schema.json +2 -2
  266. intentkit/skills/slack/send_message.py +3 -5
  267. intentkit/skills/supabase/__init__.py +7 -23
  268. intentkit/skills/supabase/base.py +1 -7
  269. intentkit/skills/supabase/delete_data.py +4 -4
  270. intentkit/skills/supabase/fetch_data.py +12 -12
  271. intentkit/skills/supabase/insert_data.py +4 -4
  272. intentkit/skills/supabase/invoke_function.py +6 -6
  273. intentkit/skills/supabase/schema.json +2 -3
  274. intentkit/skills/supabase/update_data.py +6 -6
  275. intentkit/skills/supabase/upsert_data.py +4 -4
  276. intentkit/skills/superfluid/__init__.py +53 -0
  277. intentkit/skills/superfluid/base.py +11 -0
  278. intentkit/skills/superfluid/schema.json +89 -0
  279. intentkit/skills/superfluid/superfluid.svg +6 -0
  280. intentkit/skills/system/__init__.py +7 -24
  281. intentkit/skills/system/add_autonomous_task.py +10 -12
  282. intentkit/skills/system/delete_autonomous_task.py +2 -2
  283. intentkit/skills/system/edit_autonomous_task.py +14 -18
  284. intentkit/skills/system/list_autonomous_tasks.py +3 -5
  285. intentkit/skills/system/read_agent_api_key.py +6 -4
  286. intentkit/skills/system/regenerate_agent_api_key.py +6 -4
  287. intentkit/skills/system/schema.json +6 -8
  288. intentkit/skills/tavily/__init__.py +3 -12
  289. intentkit/skills/tavily/base.py +4 -9
  290. intentkit/skills/tavily/schema.json +3 -5
  291. intentkit/skills/tavily/tavily_extract.py +2 -4
  292. intentkit/skills/tavily/tavily_search.py +4 -6
  293. intentkit/skills/token/__init__.py +5 -10
  294. intentkit/skills/token/base.py +7 -11
  295. intentkit/skills/token/erc20_transfers.py +19 -19
  296. intentkit/skills/token/schema.json +3 -6
  297. intentkit/skills/token/token_analytics.py +3 -3
  298. intentkit/skills/token/token_price.py +13 -13
  299. intentkit/skills/token/token_search.py +9 -9
  300. intentkit/skills/twitter/__init__.py +11 -35
  301. intentkit/skills/twitter/base.py +22 -34
  302. intentkit/skills/twitter/follow_user.py +2 -6
  303. intentkit/skills/twitter/get_mentions.py +5 -12
  304. intentkit/skills/twitter/get_timeline.py +4 -12
  305. intentkit/skills/twitter/get_user_by_username.py +2 -6
  306. intentkit/skills/twitter/get_user_tweets.py +5 -13
  307. intentkit/skills/twitter/like_tweet.py +2 -6
  308. intentkit/skills/twitter/post_tweet.py +6 -9
  309. intentkit/skills/twitter/reply_tweet.py +6 -9
  310. intentkit/skills/twitter/retweet.py +2 -6
  311. intentkit/skills/twitter/schema.json +1 -0
  312. intentkit/skills/twitter/search_tweets.py +4 -12
  313. intentkit/skills/unrealspeech/__init__.py +2 -7
  314. intentkit/skills/unrealspeech/base.py +2 -8
  315. intentkit/skills/unrealspeech/schema.json +2 -5
  316. intentkit/skills/unrealspeech/text_to_speech.py +8 -8
  317. intentkit/skills/venice_audio/__init__.py +98 -106
  318. intentkit/skills/venice_audio/base.py +117 -121
  319. intentkit/skills/venice_audio/input.py +41 -41
  320. intentkit/skills/venice_audio/schema.json +151 -152
  321. intentkit/skills/venice_audio/venice_audio.py +38 -21
  322. intentkit/skills/venice_image/__init__.py +147 -154
  323. intentkit/skills/venice_image/api.py +138 -138
  324. intentkit/skills/venice_image/base.py +185 -192
  325. intentkit/skills/venice_image/config.py +33 -35
  326. intentkit/skills/venice_image/image_enhance/image_enhance.py +2 -3
  327. intentkit/skills/venice_image/image_enhance/image_enhance_base.py +21 -23
  328. intentkit/skills/venice_image/image_enhance/image_enhance_input.py +38 -40
  329. intentkit/skills/venice_image/image_generation/image_generation_base.py +11 -10
  330. intentkit/skills/venice_image/image_generation/image_generation_fluently_xl.py +26 -26
  331. intentkit/skills/venice_image/image_generation/image_generation_flux_dev.py +27 -27
  332. intentkit/skills/venice_image/image_generation/image_generation_flux_dev_uncensored.py +26 -26
  333. intentkit/skills/venice_image/image_generation/image_generation_input.py +158 -158
  334. intentkit/skills/venice_image/image_generation/image_generation_lustify_sdxl.py +26 -26
  335. intentkit/skills/venice_image/image_generation/image_generation_pony_realism.py +26 -26
  336. intentkit/skills/venice_image/image_generation/image_generation_stable_diffusion_3_5.py +28 -28
  337. intentkit/skills/venice_image/image_generation/image_generation_venice_sd35.py +28 -28
  338. intentkit/skills/venice_image/image_upscale/image_upscale.py +3 -3
  339. intentkit/skills/venice_image/image_upscale/image_upscale_base.py +21 -23
  340. intentkit/skills/venice_image/image_upscale/image_upscale_input.py +22 -22
  341. intentkit/skills/venice_image/image_vision/image_vision.py +2 -2
  342. intentkit/skills/venice_image/image_vision/image_vision_base.py +17 -17
  343. intentkit/skills/venice_image/image_vision/image_vision_input.py +9 -9
  344. intentkit/skills/venice_image/schema.json +267 -267
  345. intentkit/skills/venice_image/utils.py +77 -78
  346. intentkit/skills/web_scraper/__init__.py +5 -18
  347. intentkit/skills/web_scraper/base.py +21 -7
  348. intentkit/skills/web_scraper/document_indexer.py +7 -6
  349. intentkit/skills/web_scraper/schema.json +2 -6
  350. intentkit/skills/web_scraper/scrape_and_index.py +15 -15
  351. intentkit/skills/web_scraper/utils.py +62 -63
  352. intentkit/skills/web_scraper/website_indexer.py +17 -19
  353. intentkit/skills/weth/__init__.py +49 -0
  354. intentkit/skills/weth/base.py +11 -0
  355. intentkit/skills/weth/schema.json +58 -0
  356. intentkit/skills/weth/weth.svg +6 -0
  357. intentkit/skills/wow/__init__.py +51 -0
  358. intentkit/skills/wow/base.py +11 -0
  359. intentkit/skills/wow/schema.json +89 -0
  360. intentkit/skills/wow/wow.svg +7 -0
  361. intentkit/skills/x402/__init__.py +58 -0
  362. intentkit/skills/x402/base.py +99 -0
  363. intentkit/skills/x402/http_request.py +117 -0
  364. intentkit/skills/x402/schema.json +40 -0
  365. intentkit/skills/x402/x402.webp +0 -0
  366. intentkit/skills/xmtp/__init__.py +4 -15
  367. intentkit/skills/xmtp/base.py +5 -5
  368. intentkit/skills/xmtp/price.py +7 -6
  369. intentkit/skills/xmtp/schema.json +69 -71
  370. intentkit/skills/xmtp/swap.py +6 -8
  371. intentkit/skills/xmtp/transfer.py +4 -6
  372. intentkit/utils/__init__.py +4 -0
  373. intentkit/utils/chain.py +198 -96
  374. intentkit/utils/ens.py +135 -0
  375. intentkit/utils/error.py +5 -2
  376. intentkit/utils/logging.py +9 -11
  377. intentkit/utils/schema.py +100 -0
  378. intentkit/utils/slack_alert.py +8 -8
  379. intentkit/utils/tx.py +16 -8
  380. intentkit/uv.lock +3377 -0
  381. {intentkit-0.7.5.dev3.dist-info → intentkit-0.8.34.dev7.dist-info}/METADATA +13 -15
  382. intentkit-0.8.34.dev7.dist-info/RECORD +478 -0
  383. intentkit-0.8.34.dev7.dist-info/licenses/LICENSE +21 -0
  384. intentkit/core/node.py +0 -215
  385. intentkit/models/conversation.py +0 -286
  386. intentkit/models/generator.py +0 -347
  387. intentkit/skills/cdp/get_balance.py +0 -110
  388. intentkit/skills/cdp/swap.py +0 -121
  389. intentkit/skills/moralis/tests/__init__.py +0 -0
  390. intentkit/skills/moralis/tests/test_wallet.py +0 -511
  391. intentkit-0.7.5.dev3.dist-info/RECORD +0 -424
  392. {intentkit-0.7.5.dev3.dist-info/licenses → intentkit}/LICENSE +0 -0
  393. {intentkit-0.7.5.dev3.dist-info → intentkit-0.8.34.dev7.dist-info}/WHEEL +0 -0
@@ -1,75 +1,73 @@
1
1
  {
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
- "XMTP",
9
- "Blockchain",
10
- "Transactions",
11
- "Web3",
12
- "Base"
13
- ],
14
- "properties": {
15
- "enabled": {
16
- "type": "boolean",
17
- "title": "Enabled",
18
- "description": "Whether this skill is enabled",
19
- "default": false
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
- "states": {
22
- "type": "object",
23
- "properties": {
24
- "xmtp_transfer": {
25
- "type": "string",
26
- "title": "XMTP Transfer",
27
- "enum": [
28
- "disabled",
29
- "public",
30
- "private"
31
- ],
32
- "x-enum-title": [
33
- "Disabled",
34
- "Agent Owner + All Users",
35
- "Agent Owner Only"
36
- ],
37
- "description": "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.",
38
- "default": "disabled"
39
- },
40
- "xmtp_swap": {
41
- "type": "string",
42
- "title": "XMTP Swap",
43
- "enum": [
44
- "disabled",
45
- "public",
46
- "private"
47
- ],
48
- "x-enum-title": [
49
- "Disabled",
50
- "Agent Owner + All Users",
51
- "Agent Owner Only"
52
- ],
53
- "description": "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
+ }
@@ -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 get_origin_cdp_client
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: Type[BaseModel] = SwapInput
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
- ) -> Tuple[str, List[ChatMessageAttachment]]:
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 origin helper (server-side credentials)
111
- cdp_client = get_origin_cdp_client(self.skill_store)
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 get_origin_cdp_client returns a managed global client
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: Optional[str] = Field(
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: Type[BaseModel] = TransferInput
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: Optional[str],
43
- ) -> Tuple[str, List[ChatMessageAttachment]]:
40
+ token_contract_address: str | None,
41
+ ) -> tuple[str, list[ChatMessageAttachment]]:
44
42
  """Create an XMTP transfer transaction request.
45
43
 
46
44
  Args:
@@ -1 +1,5 @@
1
+ """Utility exports for IntentKit."""
1
2
 
3
+ from intentkit.utils.ens import resolve_ens_to_address
4
+
5
+ __all__ = ["resolve_ens_to_address"]
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 Network(StrEnum):
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 = "ethereum-mainnet"
69
- EthereumGoerli = "ethereum-goerli" # Goerli Testnet (deprecated, Sepolia preferred)
70
- EthereumSepolia = "ethereum-sepolia"
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 Network enum members to their corresponding NetworkId enum members.
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[Network, NetworkId] = {
158
- Network.ArbitrumMainnet: NetworkId.ArbitrumMainnet,
159
- Network.AvalancheMainnet: NetworkId.AvalancheMainnet,
160
- Network.BaseMainnet: NetworkId.BaseMainnet,
161
- Network.BaseSepolia: NetworkId.BaseSepolia,
162
- Network.BeraMainnet: NetworkId.BeraMainnet,
163
- Network.BinanceMainnet: NetworkId.BinanceMainnet,
164
- Network.EthereumMainnet: NetworkId.EthereumMainnet,
165
- Network.EthereumSepolia: NetworkId.EthereumSepolia,
166
- Network.GnosisMainnet: NetworkId.GnosisMainnet,
167
- Network.LineaMainnet: NetworkId.LineaMainnet,
168
- Network.OptimismMainnet: NetworkId.OptimismMainnet,
169
- Network.PolygonMainnet: NetworkId.PolygonMainnet,
170
- Network.SonicMainnet: NetworkId.SonicMainnet,
171
- Network.ZkSyncMainnet: NetworkId.ZkSyncMainnet,
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
- # Network enum members (network names). This dictionary allows for reverse
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, Network] = {
181
- NetworkId.ArbitrumMainnet: Network.ArbitrumMainnet,
182
- NetworkId.AvalancheMainnet: Network.AvalancheMainnet,
183
- NetworkId.BaseMainnet: Network.BaseMainnet,
184
- NetworkId.BaseSepolia: Network.BaseSepolia,
185
- NetworkId.BeraMainnet: Network.BeraMainnet,
186
- NetworkId.BinanceMainnet: Network.BinanceMainnet,
187
- NetworkId.EthereumMainnet: Network.EthereumMainnet,
188
- NetworkId.EthereumSepolia: Network.EthereumSepolia,
189
- NetworkId.GnosisMainnet: Network.GnosisMainnet,
190
- NetworkId.LineaMainnet: Network.LineaMainnet,
191
- NetworkId.OptimismMainnet: Network.OptimismMainnet,
192
- NetworkId.PolygonMainnet: Network.PolygonMainnet,
193
- NetworkId.SonicMainnet: Network.SonicMainnet,
194
- NetworkId.ZkSyncMainnet: Network.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: 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 Network enum member representing the specific network (e.g., EthereumMainnet).
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) -> Network:
314
+ def network(self) -> QuickNodeNetwork:
240
315
  """
241
- Returns the Network enum member.
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[Network, ChainConfig] = {}
365
+ self.chain_configs: dict[QuickNodeNetwork, ChainConfig] = {}
291
366
 
292
- def get_chain_config(self, network: Network) -> ChainConfig:
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
- network: The `Network` enum member representing the desired network.
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
- chain_config = self.chain_configs.get(network)
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 {network} not found")
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 `Network` enum member associated with the
315
- provided `NetworkId` and then uses `get_chain_config` to retrieve the
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.get_chain_config(network)
416
+ return self._get_chain_config_by_quicknode_network(network)
332
417
 
333
418
  @abstractmethod
334
- def init_chain_configs(self, api_key: str) -> dict[Network, ChainConfig]:
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
- Args:
344
- api_key: The API key used for initializing chain configurations.
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: # Set a timeout for the request
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() # Raise HTTPError for bad responses (4xx or 5xx)
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
- raise Exception(f"Quicknode API HTTP Error: {http_err}")
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
- raise Exception(f"Quicknode API Request Error: {req_err}")
428
- except (
429
- KeyError,
430
- TypeError,
431
- ) as e: # Handle potential data issues in the API response
432
- raise Exception(
433
- f"Error processing QuickNode API response: {e}. Check the API response format."
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
- except Exception as e:
436
- raise Exception(f"Quicknode API An unexpected error occurred: {e}")
530
+ continue
531
+
532
+ self.chain_configs[network] = ChainConfig(
533
+ chain,
534
+ network,
535
+ rpc_url,
536
+ ens_url,
537
+ wss_url,
538
+ )