intentkit 0.6.13.dev2__py3-none-any.whl → 0.8.17__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of intentkit might be problematic. Click here for more details.

Files changed (385) hide show
  1. intentkit/__init__.py +1 -1
  2. intentkit/abstracts/agent.py +4 -5
  3. intentkit/abstracts/engine.py +5 -5
  4. intentkit/abstracts/graph.py +14 -7
  5. intentkit/abstracts/skill.py +6 -144
  6. intentkit/abstracts/twitter.py +4 -5
  7. intentkit/clients/__init__.py +5 -2
  8. intentkit/clients/cdp.py +101 -141
  9. intentkit/clients/twitter.py +83 -62
  10. intentkit/clients/web3.py +29 -0
  11. intentkit/config/config.py +8 -5
  12. intentkit/core/agent.py +472 -195
  13. intentkit/core/asset.py +253 -0
  14. intentkit/core/chat.py +51 -0
  15. intentkit/core/client.py +1 -1
  16. intentkit/core/credit.py +460 -130
  17. intentkit/core/engine.py +262 -233
  18. intentkit/core/node.py +15 -16
  19. intentkit/core/prompt.py +62 -28
  20. intentkit/core/scheduler.py +92 -0
  21. intentkit/core/statistics.py +168 -0
  22. intentkit/models/agent.py +1096 -949
  23. intentkit/models/agent_data.py +68 -38
  24. intentkit/models/agent_public.json +98 -0
  25. intentkit/models/agent_schema.json +54 -439
  26. intentkit/models/app_setting.py +96 -33
  27. intentkit/models/chat.py +74 -27
  28. intentkit/models/conversation.py +8 -8
  29. intentkit/models/credit.py +362 -74
  30. intentkit/models/db.py +26 -8
  31. intentkit/models/db_mig.py +2 -2
  32. intentkit/models/llm.csv +28 -0
  33. intentkit/models/llm.py +185 -350
  34. intentkit/models/redis.py +6 -4
  35. intentkit/models/skill.py +186 -72
  36. intentkit/models/skills.csv +174 -0
  37. intentkit/models/user.py +82 -24
  38. intentkit/skills/acolyt/__init__.py +2 -9
  39. intentkit/skills/acolyt/ask.py +3 -4
  40. intentkit/skills/acolyt/base.py +4 -9
  41. intentkit/skills/acolyt/schema.json +4 -3
  42. intentkit/skills/aixbt/__init__.py +2 -13
  43. intentkit/skills/aixbt/base.py +1 -7
  44. intentkit/skills/aixbt/projects.py +14 -15
  45. intentkit/skills/aixbt/schema.json +4 -4
  46. intentkit/skills/allora/__init__.py +2 -9
  47. intentkit/skills/allora/base.py +4 -9
  48. intentkit/skills/allora/price.py +3 -4
  49. intentkit/skills/allora/schema.json +3 -2
  50. intentkit/skills/base.py +248 -85
  51. intentkit/skills/basename/__init__.py +51 -0
  52. intentkit/skills/basename/base.py +11 -0
  53. intentkit/skills/basename/basename.svg +11 -0
  54. intentkit/skills/basename/schema.json +58 -0
  55. intentkit/skills/carv/__init__.py +115 -121
  56. intentkit/skills/carv/base.py +184 -185
  57. intentkit/skills/carv/fetch_news.py +3 -3
  58. intentkit/skills/carv/onchain_query.py +4 -4
  59. intentkit/skills/carv/schema.json +134 -137
  60. intentkit/skills/carv/token_info_and_price.py +5 -5
  61. intentkit/skills/casino/README.md +254 -0
  62. intentkit/skills/casino/__init__.py +86 -0
  63. intentkit/skills/casino/base.py +17 -0
  64. intentkit/skills/casino/casino.png +0 -0
  65. intentkit/skills/casino/deck_draw.py +127 -0
  66. intentkit/skills/casino/deck_shuffle.py +118 -0
  67. intentkit/skills/casino/dice_roll.py +100 -0
  68. intentkit/skills/casino/schema.json +77 -0
  69. intentkit/skills/casino/utils.py +107 -0
  70. intentkit/skills/cdp/__init__.py +22 -84
  71. intentkit/skills/cdp/base.py +1 -7
  72. intentkit/skills/cdp/schema.json +11 -314
  73. intentkit/skills/chainlist/__init__.py +2 -7
  74. intentkit/skills/chainlist/base.py +1 -7
  75. intentkit/skills/chainlist/chain_lookup.py +18 -18
  76. intentkit/skills/chainlist/schema.json +3 -5
  77. intentkit/skills/common/__init__.py +2 -9
  78. intentkit/skills/common/base.py +1 -7
  79. intentkit/skills/common/current_time.py +1 -2
  80. intentkit/skills/common/schema.json +2 -2
  81. intentkit/skills/cookiefun/__init__.py +6 -9
  82. intentkit/skills/cookiefun/base.py +2 -7
  83. intentkit/skills/cookiefun/get_account_details.py +7 -7
  84. intentkit/skills/cookiefun/get_account_feed.py +19 -19
  85. intentkit/skills/cookiefun/get_account_smart_followers.py +7 -7
  86. intentkit/skills/cookiefun/get_sectors.py +3 -3
  87. intentkit/skills/cookiefun/schema.json +1 -3
  88. intentkit/skills/cookiefun/search_accounts.py +9 -9
  89. intentkit/skills/cryptocompare/__init__.py +7 -24
  90. intentkit/skills/cryptocompare/api.py +2 -3
  91. intentkit/skills/cryptocompare/base.py +11 -25
  92. intentkit/skills/cryptocompare/fetch_news.py +4 -5
  93. intentkit/skills/cryptocompare/fetch_price.py +6 -7
  94. intentkit/skills/cryptocompare/fetch_top_exchanges.py +4 -5
  95. intentkit/skills/cryptocompare/fetch_top_market_cap.py +4 -5
  96. intentkit/skills/cryptocompare/fetch_top_volume.py +4 -5
  97. intentkit/skills/cryptocompare/fetch_trading_signals.py +5 -6
  98. intentkit/skills/cryptocompare/schema.json +3 -3
  99. intentkit/skills/cryptopanic/__init__.py +7 -10
  100. intentkit/skills/cryptopanic/base.py +51 -55
  101. intentkit/skills/cryptopanic/fetch_crypto_news.py +4 -8
  102. intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +5 -7
  103. intentkit/skills/cryptopanic/schema.json +105 -103
  104. intentkit/skills/dapplooker/__init__.py +2 -9
  105. intentkit/skills/dapplooker/base.py +4 -9
  106. intentkit/skills/dapplooker/dapplooker_token_data.py +7 -7
  107. intentkit/skills/dapplooker/schema.json +3 -5
  108. intentkit/skills/defillama/__init__.py +24 -74
  109. intentkit/skills/defillama/api.py +6 -9
  110. intentkit/skills/defillama/base.py +11 -21
  111. intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +8 -10
  112. intentkit/skills/defillama/coins/fetch_block.py +6 -8
  113. intentkit/skills/defillama/coins/fetch_current_prices.py +8 -10
  114. intentkit/skills/defillama/coins/fetch_first_price.py +7 -9
  115. intentkit/skills/defillama/coins/fetch_historical_prices.py +9 -11
  116. intentkit/skills/defillama/coins/fetch_price_chart.py +9 -11
  117. intentkit/skills/defillama/coins/fetch_price_percentage.py +7 -9
  118. intentkit/skills/defillama/config/chains.py +1 -3
  119. intentkit/skills/defillama/fees/fetch_fees_overview.py +24 -26
  120. intentkit/skills/defillama/schema.json +5 -1
  121. intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +16 -18
  122. intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +8 -10
  123. intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +5 -7
  124. intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +7 -9
  125. intentkit/skills/defillama/tests/api_integration.test.py +1 -1
  126. intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +4 -6
  127. intentkit/skills/defillama/tvl/fetch_chains.py +9 -11
  128. intentkit/skills/defillama/tvl/fetch_historical_tvl.py +4 -6
  129. intentkit/skills/defillama/tvl/fetch_protocol.py +32 -38
  130. intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +3 -5
  131. intentkit/skills/defillama/tvl/fetch_protocols.py +37 -45
  132. intentkit/skills/defillama/volumes/fetch_dex_overview.py +42 -48
  133. intentkit/skills/defillama/volumes/fetch_dex_summary.py +35 -37
  134. intentkit/skills/defillama/volumes/fetch_options_overview.py +24 -28
  135. intentkit/skills/defillama/yields/fetch_pool_chart.py +10 -12
  136. intentkit/skills/defillama/yields/fetch_pools.py +26 -30
  137. intentkit/skills/dexscreener/README.md +154 -0
  138. intentkit/skills/dexscreener/__init__.py +97 -93
  139. intentkit/skills/dexscreener/base.py +125 -133
  140. intentkit/skills/dexscreener/get_pair_info.py +158 -0
  141. intentkit/skills/dexscreener/get_token_pairs.py +165 -0
  142. intentkit/skills/dexscreener/get_tokens_info.py +212 -0
  143. intentkit/skills/dexscreener/model/search_token_response.py +80 -82
  144. intentkit/skills/dexscreener/schema.json +91 -48
  145. intentkit/skills/dexscreener/search_token.py +182 -321
  146. intentkit/skills/dexscreener/utils.py +420 -0
  147. intentkit/skills/dune_analytics/__init__.py +7 -9
  148. intentkit/skills/dune_analytics/base.py +48 -52
  149. intentkit/skills/dune_analytics/fetch_kol_buys.py +5 -7
  150. intentkit/skills/dune_analytics/fetch_nation_metrics.py +6 -8
  151. intentkit/skills/dune_analytics/schema.json +104 -99
  152. intentkit/skills/elfa/__init__.py +5 -18
  153. intentkit/skills/elfa/base.py +10 -14
  154. intentkit/skills/elfa/mention.py +19 -21
  155. intentkit/skills/elfa/schema.json +3 -2
  156. intentkit/skills/elfa/stats.py +4 -4
  157. intentkit/skills/elfa/tokens.py +12 -12
  158. intentkit/skills/elfa/utils.py +26 -28
  159. intentkit/skills/enso/__init__.py +11 -31
  160. intentkit/skills/enso/base.py +50 -35
  161. intentkit/skills/enso/best_yield.py +16 -24
  162. intentkit/skills/enso/networks.py +6 -11
  163. intentkit/skills/enso/prices.py +11 -13
  164. intentkit/skills/enso/route.py +34 -38
  165. intentkit/skills/enso/schema.json +3 -2
  166. intentkit/skills/enso/tokens.py +29 -38
  167. intentkit/skills/enso/wallet.py +76 -191
  168. intentkit/skills/erc20/__init__.py +50 -0
  169. intentkit/skills/erc20/base.py +11 -0
  170. intentkit/skills/erc20/erc20.svg +5 -0
  171. intentkit/skills/erc20/schema.json +74 -0
  172. intentkit/skills/erc721/__init__.py +53 -0
  173. intentkit/skills/erc721/base.py +11 -0
  174. intentkit/skills/erc721/erc721.svg +5 -0
  175. intentkit/skills/erc721/schema.json +90 -0
  176. intentkit/skills/firecrawl/README.md +11 -5
  177. intentkit/skills/firecrawl/__init__.py +5 -18
  178. intentkit/skills/firecrawl/base.py +4 -11
  179. intentkit/skills/firecrawl/clear.py +4 -8
  180. intentkit/skills/firecrawl/crawl.py +19 -19
  181. intentkit/skills/firecrawl/query.py +4 -3
  182. intentkit/skills/firecrawl/schema.json +6 -8
  183. intentkit/skills/firecrawl/scrape.py +150 -40
  184. intentkit/skills/firecrawl/utils.py +50 -42
  185. intentkit/skills/github/__init__.py +2 -7
  186. intentkit/skills/github/base.py +1 -7
  187. intentkit/skills/github/github_search.py +1 -2
  188. intentkit/skills/github/schema.json +3 -4
  189. intentkit/skills/heurist/__init__.py +8 -27
  190. intentkit/skills/heurist/base.py +4 -9
  191. intentkit/skills/heurist/image_generation_animagine_xl.py +12 -13
  192. intentkit/skills/heurist/image_generation_arthemy_comics.py +12 -13
  193. intentkit/skills/heurist/image_generation_arthemy_real.py +12 -13
  194. intentkit/skills/heurist/image_generation_braindance.py +12 -13
  195. intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +12 -13
  196. intentkit/skills/heurist/image_generation_flux_1_dev.py +12 -13
  197. intentkit/skills/heurist/image_generation_sdxl.py +12 -13
  198. intentkit/skills/heurist/schema.json +2 -2
  199. intentkit/skills/http/__init__.py +4 -15
  200. intentkit/skills/http/base.py +1 -7
  201. intentkit/skills/http/get.py +21 -16
  202. intentkit/skills/http/post.py +23 -18
  203. intentkit/skills/http/put.py +23 -18
  204. intentkit/skills/http/schema.json +4 -5
  205. intentkit/skills/lifi/__init__.py +8 -13
  206. intentkit/skills/lifi/base.py +1 -7
  207. intentkit/skills/lifi/schema.json +17 -8
  208. intentkit/skills/lifi/token_execute.py +36 -30
  209. intentkit/skills/lifi/token_quote.py +8 -10
  210. intentkit/skills/lifi/utils.py +104 -51
  211. intentkit/skills/moralis/__init__.py +6 -10
  212. intentkit/skills/moralis/api.py +6 -7
  213. intentkit/skills/moralis/base.py +5 -10
  214. intentkit/skills/moralis/fetch_chain_portfolio.py +10 -11
  215. intentkit/skills/moralis/fetch_nft_portfolio.py +22 -22
  216. intentkit/skills/moralis/fetch_solana_portfolio.py +11 -12
  217. intentkit/skills/moralis/fetch_wallet_portfolio.py +8 -9
  218. intentkit/skills/moralis/schema.json +7 -2
  219. intentkit/skills/morpho/__init__.py +52 -0
  220. intentkit/skills/morpho/base.py +11 -0
  221. intentkit/skills/morpho/morpho.svg +12 -0
  222. intentkit/skills/morpho/schema.json +73 -0
  223. intentkit/skills/nation/__init__.py +4 -9
  224. intentkit/skills/nation/base.py +5 -10
  225. intentkit/skills/nation/nft_check.py +3 -4
  226. intentkit/skills/nation/schema.json +4 -3
  227. intentkit/skills/onchain.py +23 -0
  228. intentkit/skills/openai/__init__.py +17 -18
  229. intentkit/skills/openai/base.py +10 -14
  230. intentkit/skills/openai/dalle_image_generation.py +3 -8
  231. intentkit/skills/openai/gpt_avatar_generator.py +102 -0
  232. intentkit/skills/openai/gpt_image_generation.py +4 -8
  233. intentkit/skills/openai/gpt_image_mini_generator.py +91 -0
  234. intentkit/skills/openai/gpt_image_to_image.py +4 -8
  235. intentkit/skills/openai/image_to_text.py +3 -7
  236. intentkit/skills/openai/schema.json +34 -3
  237. intentkit/skills/portfolio/__init__.py +11 -35
  238. intentkit/skills/portfolio/base.py +33 -19
  239. intentkit/skills/portfolio/schema.json +3 -5
  240. intentkit/skills/portfolio/token_balances.py +21 -21
  241. intentkit/skills/portfolio/wallet_approvals.py +17 -18
  242. intentkit/skills/portfolio/wallet_defi_positions.py +3 -3
  243. intentkit/skills/portfolio/wallet_history.py +31 -31
  244. intentkit/skills/portfolio/wallet_net_worth.py +13 -13
  245. intentkit/skills/portfolio/wallet_nfts.py +19 -19
  246. intentkit/skills/portfolio/wallet_profitability.py +18 -18
  247. intentkit/skills/portfolio/wallet_profitability_summary.py +5 -5
  248. intentkit/skills/portfolio/wallet_stats.py +3 -3
  249. intentkit/skills/portfolio/wallet_swaps.py +19 -19
  250. intentkit/skills/pyth/__init__.py +50 -0
  251. intentkit/skills/pyth/base.py +11 -0
  252. intentkit/skills/pyth/pyth.svg +6 -0
  253. intentkit/skills/pyth/schema.json +75 -0
  254. intentkit/skills/skills.toml +40 -0
  255. intentkit/skills/slack/__init__.py +5 -17
  256. intentkit/skills/slack/base.py +3 -9
  257. intentkit/skills/slack/get_channel.py +8 -8
  258. intentkit/skills/slack/get_message.py +9 -9
  259. intentkit/skills/slack/schedule_message.py +5 -5
  260. intentkit/skills/slack/schema.json +2 -2
  261. intentkit/skills/slack/send_message.py +3 -5
  262. intentkit/skills/supabase/__init__.py +7 -23
  263. intentkit/skills/supabase/base.py +9 -13
  264. intentkit/skills/supabase/delete_data.py +5 -6
  265. intentkit/skills/supabase/fetch_data.py +13 -14
  266. intentkit/skills/supabase/insert_data.py +5 -6
  267. intentkit/skills/supabase/invoke_function.py +7 -8
  268. intentkit/skills/supabase/schema.json +2 -3
  269. intentkit/skills/supabase/update_data.py +7 -8
  270. intentkit/skills/supabase/upsert_data.py +5 -6
  271. intentkit/skills/superfluid/__init__.py +53 -0
  272. intentkit/skills/superfluid/base.py +11 -0
  273. intentkit/skills/superfluid/schema.json +89 -0
  274. intentkit/skills/superfluid/superfluid.svg +6 -0
  275. intentkit/skills/system/__init__.py +7 -24
  276. intentkit/skills/system/add_autonomous_task.py +10 -12
  277. intentkit/skills/system/delete_autonomous_task.py +2 -2
  278. intentkit/skills/system/edit_autonomous_task.py +14 -18
  279. intentkit/skills/system/list_autonomous_tasks.py +3 -5
  280. intentkit/skills/system/read_agent_api_key.py +6 -4
  281. intentkit/skills/system/regenerate_agent_api_key.py +6 -4
  282. intentkit/skills/system/schema.json +6 -8
  283. intentkit/skills/tavily/__init__.py +3 -12
  284. intentkit/skills/tavily/base.py +4 -9
  285. intentkit/skills/tavily/schema.json +3 -5
  286. intentkit/skills/tavily/tavily_extract.py +2 -4
  287. intentkit/skills/tavily/tavily_search.py +4 -6
  288. intentkit/skills/token/__init__.py +5 -10
  289. intentkit/skills/token/base.py +7 -11
  290. intentkit/skills/token/erc20_transfers.py +19 -19
  291. intentkit/skills/token/schema.json +3 -6
  292. intentkit/skills/token/token_analytics.py +3 -3
  293. intentkit/skills/token/token_price.py +13 -13
  294. intentkit/skills/token/token_search.py +9 -9
  295. intentkit/skills/twitter/__init__.py +11 -35
  296. intentkit/skills/twitter/base.py +23 -35
  297. intentkit/skills/twitter/follow_user.py +3 -7
  298. intentkit/skills/twitter/get_mentions.py +6 -13
  299. intentkit/skills/twitter/get_timeline.py +5 -13
  300. intentkit/skills/twitter/get_user_by_username.py +3 -7
  301. intentkit/skills/twitter/get_user_tweets.py +6 -14
  302. intentkit/skills/twitter/like_tweet.py +3 -7
  303. intentkit/skills/twitter/post_tweet.py +23 -12
  304. intentkit/skills/twitter/reply_tweet.py +21 -12
  305. intentkit/skills/twitter/retweet.py +3 -7
  306. intentkit/skills/twitter/schema.json +1 -0
  307. intentkit/skills/twitter/search_tweets.py +5 -13
  308. intentkit/skills/unrealspeech/__init__.py +2 -7
  309. intentkit/skills/unrealspeech/base.py +2 -8
  310. intentkit/skills/unrealspeech/schema.json +2 -5
  311. intentkit/skills/unrealspeech/text_to_speech.py +8 -8
  312. intentkit/skills/venice_audio/__init__.py +98 -106
  313. intentkit/skills/venice_audio/base.py +117 -121
  314. intentkit/skills/venice_audio/input.py +41 -41
  315. intentkit/skills/venice_audio/schema.json +151 -152
  316. intentkit/skills/venice_audio/venice_audio.py +38 -21
  317. intentkit/skills/venice_image/__init__.py +147 -154
  318. intentkit/skills/venice_image/api.py +138 -138
  319. intentkit/skills/venice_image/base.py +185 -192
  320. intentkit/skills/venice_image/config.py +33 -35
  321. intentkit/skills/venice_image/image_enhance/image_enhance.py +2 -3
  322. intentkit/skills/venice_image/image_enhance/image_enhance_base.py +21 -23
  323. intentkit/skills/venice_image/image_enhance/image_enhance_input.py +38 -40
  324. intentkit/skills/venice_image/image_generation/image_generation_base.py +9 -9
  325. intentkit/skills/venice_image/image_generation/image_generation_fluently_xl.py +26 -26
  326. intentkit/skills/venice_image/image_generation/image_generation_flux_dev.py +27 -27
  327. intentkit/skills/venice_image/image_generation/image_generation_flux_dev_uncensored.py +26 -26
  328. intentkit/skills/venice_image/image_generation/image_generation_input.py +158 -158
  329. intentkit/skills/venice_image/image_generation/image_generation_lustify_sdxl.py +26 -26
  330. intentkit/skills/venice_image/image_generation/image_generation_pony_realism.py +26 -26
  331. intentkit/skills/venice_image/image_generation/image_generation_stable_diffusion_3_5.py +28 -28
  332. intentkit/skills/venice_image/image_generation/image_generation_venice_sd35.py +28 -28
  333. intentkit/skills/venice_image/image_upscale/image_upscale.py +3 -3
  334. intentkit/skills/venice_image/image_upscale/image_upscale_base.py +21 -23
  335. intentkit/skills/venice_image/image_upscale/image_upscale_input.py +22 -22
  336. intentkit/skills/venice_image/image_vision/image_vision.py +2 -2
  337. intentkit/skills/venice_image/image_vision/image_vision_base.py +17 -17
  338. intentkit/skills/venice_image/image_vision/image_vision_input.py +9 -9
  339. intentkit/skills/venice_image/schema.json +267 -267
  340. intentkit/skills/venice_image/utils.py +77 -78
  341. intentkit/skills/web_scraper/__init__.py +5 -18
  342. intentkit/skills/web_scraper/base.py +21 -7
  343. intentkit/skills/web_scraper/document_indexer.py +7 -6
  344. intentkit/skills/web_scraper/schema.json +2 -6
  345. intentkit/skills/web_scraper/scrape_and_index.py +15 -15
  346. intentkit/skills/web_scraper/utils.py +62 -63
  347. intentkit/skills/web_scraper/website_indexer.py +17 -19
  348. intentkit/skills/weth/__init__.py +49 -0
  349. intentkit/skills/weth/base.py +11 -0
  350. intentkit/skills/weth/schema.json +58 -0
  351. intentkit/skills/weth/weth.svg +6 -0
  352. intentkit/skills/wow/__init__.py +51 -0
  353. intentkit/skills/wow/base.py +11 -0
  354. intentkit/skills/wow/schema.json +89 -0
  355. intentkit/skills/wow/wow.svg +7 -0
  356. intentkit/skills/x402/__init__.py +61 -0
  357. intentkit/skills/x402/ask_agent.py +98 -0
  358. intentkit/skills/x402/base.py +99 -0
  359. intentkit/skills/x402/http_request.py +117 -0
  360. intentkit/skills/x402/schema.json +45 -0
  361. intentkit/skills/x402/x402.webp +0 -0
  362. intentkit/skills/xmtp/__init__.py +4 -15
  363. intentkit/skills/xmtp/base.py +61 -2
  364. intentkit/skills/xmtp/price.py +18 -13
  365. intentkit/skills/xmtp/schema.json +69 -71
  366. intentkit/skills/xmtp/swap.py +22 -25
  367. intentkit/skills/xmtp/transfer.py +71 -32
  368. intentkit/utils/chain.py +3 -3
  369. intentkit/utils/error.py +14 -1
  370. intentkit/utils/logging.py +2 -4
  371. intentkit/utils/s3.py +59 -7
  372. intentkit/utils/schema.py +100 -0
  373. intentkit/utils/slack_alert.py +7 -8
  374. {intentkit-0.6.13.dev2.dist-info → intentkit-0.8.17.dist-info}/METADATA +14 -16
  375. intentkit-0.8.17.dist-info/RECORD +466 -0
  376. intentkit/abstracts/exception.py +0 -9
  377. intentkit/core/skill.py +0 -200
  378. intentkit/models/generator.py +0 -347
  379. intentkit/skills/cdp/get_balance.py +0 -110
  380. intentkit/skills/cdp/swap.py +0 -121
  381. intentkit/skills/moralis/tests/__init__.py +0 -0
  382. intentkit/skills/moralis/tests/test_wallet.py +0 -511
  383. intentkit-0.6.13.dev2.dist-info/RECORD +0 -409
  384. {intentkit-0.6.13.dev2.dist-info → intentkit-0.8.17.dist-info}/WHEEL +0 -0
  385. {intentkit-0.6.13.dev2.dist-info → intentkit-0.8.17.dist-info}/licenses/LICENSE +0 -0
@@ -1,9 +1,8 @@
1
1
  """Enso skills."""
2
2
 
3
3
  import logging
4
- from typing import List, NotRequired, TypedDict
4
+ from typing import NotRequired, TypedDict
5
5
 
6
- from intentkit.abstracts.skill import SkillStoreABC
7
6
  from intentkit.skills.base import SkillConfig, SkillState
8
7
  from intentkit.skills.enso.base import EnsoBaseTool
9
8
  from intentkit.skills.enso.best_yield import EnsoGetBestYield
@@ -36,13 +35,12 @@ class Config(SkillConfig):
36
35
 
37
36
  states: SkillStates
38
37
  api_token: NotRequired[str]
39
- main_tokens: List[str]
38
+ main_tokens: NotRequired[list[str]]
40
39
 
41
40
 
42
41
  async def get_skills(
43
42
  config: Config,
44
43
  is_private: bool,
45
- store: SkillStoreABC,
46
44
  **_,
47
45
  ) -> list[EnsoBaseTool]:
48
46
  """Get all Enso skills."""
@@ -58,7 +56,7 @@ async def get_skills(
58
56
  # Get each skill using the cached getter
59
57
  result = []
60
58
  for name in available_skills:
61
- skill = get_enso_skill(name, store)
59
+ skill = get_enso_skill(name)
62
60
  if skill:
63
61
  result.append(skill)
64
62
  return result
@@ -66,49 +64,31 @@ async def get_skills(
66
64
 
67
65
  def get_enso_skill(
68
66
  name: str,
69
- skill_store: SkillStoreABC,
70
67
  ) -> EnsoBaseTool:
71
68
  """Get an Enso skill by name.
72
69
 
73
70
  Args:
74
71
  name: The name of the skill to get
75
- skill_store: The skill store for persisting data
76
72
 
77
73
  Returns:
78
74
  The requested Enso skill
79
75
  """
80
76
  if name == "get_networks":
81
- return EnsoGetNetworks(
82
- skill_store=skill_store,
83
- )
77
+ return EnsoGetNetworks()
84
78
  if name == "get_tokens":
85
- return EnsoGetTokens(
86
- skill_store=skill_store,
87
- )
79
+ return EnsoGetTokens()
88
80
  if name == "get_prices":
89
- return EnsoGetPrices(
90
- skill_store=skill_store,
91
- )
81
+ return EnsoGetPrices()
92
82
  if name == "get_wallet_approvals":
93
- return EnsoGetWalletApprovals(
94
- skill_store=skill_store,
95
- )
83
+ return EnsoGetWalletApprovals()
96
84
  if name == "get_wallet_balances":
97
- return EnsoGetWalletBalances(
98
- skill_store=skill_store,
99
- )
85
+ return EnsoGetWalletBalances()
100
86
  if name == "wallet_approve":
101
- return EnsoWalletApprove(
102
- skill_store=skill_store,
103
- )
87
+ return EnsoWalletApprove()
104
88
  if name == "route_shortcut":
105
- return EnsoRouteShortcut(
106
- skill_store=skill_store,
107
- )
89
+ return EnsoRouteShortcut()
108
90
  if name == "get_best_yield":
109
- return EnsoGetBestYield(
110
- skill_store=skill_store,
111
- )
91
+ return EnsoGetBestYield()
112
92
  else:
113
93
  logger.warning(f"Unknown Enso skill: {name}")
114
94
  return None
@@ -1,18 +1,16 @@
1
- from typing import Optional, Type
1
+ from decimal import Decimal
2
2
 
3
- from cdp import EvmServerAccount
4
- from coinbase_agentkit import CdpEvmServerWalletProvider
5
- from langchain.tools.base import ToolException
3
+ from coinbase_agentkit import CdpEvmWalletProvider
4
+ from langchain_core.tools.base import ToolException
6
5
  from pydantic import BaseModel, Field
7
6
 
8
7
  from intentkit.abstracts.graph import AgentContext
9
- from intentkit.abstracts.skill import SkillStoreABC
10
- from intentkit.clients import CdpClient, get_cdp_client
8
+ from intentkit.clients import get_wallet_provider as get_agent_wallet_provider
9
+ from intentkit.config.config import config
11
10
  from intentkit.skills.base import IntentKitSkill
12
- from intentkit.utils.chain import ChainProvider, NetworkId
11
+ from intentkit.utils.chain import ChainProvider, Network, network_to_id
13
12
 
14
13
  base_url = "https://api.enso.finance"
15
- default_chain_id = int(NetworkId.BaseMainnet)
16
14
 
17
15
 
18
16
  class EnsoBaseTool(IntentKitSkill):
@@ -20,39 +18,25 @@ class EnsoBaseTool(IntentKitSkill):
20
18
 
21
19
  name: str = Field(description="The name of the tool")
22
20
  description: str = Field(description="A description of what the tool does")
23
- args_schema: Type[BaseModel]
24
- skill_store: SkillStoreABC = Field(
25
- description="The skill store for persisting data"
26
- )
21
+ args_schema: type[BaseModel]
27
22
 
28
- async def get_account(self, context: AgentContext) -> Optional[EvmServerAccount]:
29
- """Get the account object from the CDP client.
30
-
31
- Args:
32
- context: The skill context containing agent information.
33
-
34
- Returns:
35
- Optional[EvmServerAccount]: The account object if available.
36
- """
37
- client: CdpClient = await get_cdp_client(context.agent.id, self.skill_store)
38
- return await client.get_account()
39
-
40
- async def get_wallet_provider(
41
- self, context: AgentContext
42
- ) -> Optional[CdpEvmServerWalletProvider]:
23
+ async def get_wallet_provider(self, context: AgentContext) -> CdpEvmWalletProvider:
43
24
  """Get the wallet provider from the CDP client.
44
25
 
45
26
  Args:
46
27
  context: The skill context containing agent information.
47
28
 
48
29
  Returns:
49
- Optional[CdpEvmServerWalletProvider]: The wallet provider if available.
30
+ CdpEvmWalletProvider | None: The wallet provider if available.
50
31
  """
51
- client: CdpClient = await get_cdp_client(context.agent.id, self.skill_store)
52
- return await client.get_wallet_provider()
32
+ return await get_agent_wallet_provider(context.agent)
53
33
 
54
- def get_chain_provider(self, context: AgentContext) -> Optional[ChainProvider]:
55
- return self.skill_store.get_system_config("chain_provider")
34
+ async def get_wallet_address(self, context: AgentContext) -> str:
35
+ provider: CdpEvmWalletProvider = await self.get_wallet_provider(context)
36
+ return provider.get_address()
37
+
38
+ def get_chain_provider(self, context: AgentContext) -> ChainProvider | None:
39
+ return config.chain_provider
56
40
 
57
41
  def get_main_tokens(self, context: AgentContext) -> list[str]:
58
42
  skill_config = context.agent.skill_config(self.category)
@@ -60,12 +44,11 @@ class EnsoBaseTool(IntentKitSkill):
60
44
  return skill_config["main_tokens"]
61
45
  return []
62
46
 
63
- def get_api_key(self) -> str:
64
- context = self.get_context()
47
+ def get_api_token(self, context: AgentContext) -> str:
65
48
  skill_config = context.agent.skill_config(self.category)
66
49
  api_key_provider = skill_config.get("api_key_provider")
67
50
  if api_key_provider == "platform":
68
- return self.skill_store.get_system_config("enso_api_token")
51
+ return config.enso_api_token
69
52
  # for backward compatibility, may only have api_token in skill_config
70
53
  elif skill_config.get("api_token"):
71
54
  return skill_config.get("api_token")
@@ -74,6 +57,38 @@ class EnsoBaseTool(IntentKitSkill):
74
57
  f"Invalid API key provider: {api_key_provider}, or no api_token in config"
75
58
  )
76
59
 
60
+ def resolve_chain_id(
61
+ self, context: AgentContext, chain_id: int | None = None
62
+ ) -> int:
63
+ if chain_id:
64
+ return chain_id
65
+
66
+ agent = context.agent
67
+ try:
68
+ network = Network(agent.network_id)
69
+ except ValueError as exc: # pragma: no cover - defensive
70
+ raise ToolException(
71
+ f"Unsupported network configured for agent: {agent.network_id}"
72
+ ) from exc
73
+
74
+ network_id = network_to_id.get(network)
75
+ if network_id is None:
76
+ raise ToolException(
77
+ f"Unable to determine chain id for network: {agent.network_id}"
78
+ )
79
+ return int(network_id)
80
+
77
81
  @property
78
82
  def category(self) -> str:
79
83
  return "enso"
84
+
85
+
86
+ def format_amount_with_decimals(amount: object, decimals: int | None) -> str | None:
87
+ if amount is None or decimals is None:
88
+ return None
89
+
90
+ try:
91
+ value = Decimal(str(amount)) / (Decimal(10) ** decimals)
92
+ return format(value, "f")
93
+ except Exception: # pragma: no cover - defensive
94
+ return None
@@ -1,17 +1,8 @@
1
- from typing import List, Optional, Type
2
-
3
1
  import httpx
4
- from langchain.tools.base import ToolException
2
+ from langchain_core.tools.base import ToolException
5
3
  from pydantic import BaseModel, Field
6
4
 
7
- from intentkit.skills.enso.base import (
8
- EnsoBaseTool,
9
- base_url,
10
- )
11
- from intentkit.utils.chain import NetworkId
12
-
13
- # Chain ID for Base Mainnet
14
- BASE_CHAIN_ID = int(NetworkId.BaseMainnet)
5
+ from intentkit.skills.enso.base import EnsoBaseTool, base_url
15
6
 
16
7
 
17
8
  class EnsoGetBestYieldInput(BaseModel):
@@ -21,9 +12,9 @@ class EnsoGetBestYieldInput(BaseModel):
21
12
  "USDC",
22
13
  description="Symbol of the token to find the best yield for (e.g., 'USDC', 'ETH', 'USDT')",
23
14
  )
24
- chain_id: int = Field(
25
- BASE_CHAIN_ID,
26
- description="The blockchain chain ID. Default is Base Mainnet (8453)",
15
+ chain_id: int | None = Field(
16
+ None,
17
+ description="The blockchain chain ID. Defaults to the agent's configured network.",
27
18
  )
28
19
  top_n: int = Field(
29
20
  5,
@@ -47,8 +38,8 @@ class YieldOption(BaseModel):
47
38
  None, description="Primary contract address for interacting with the protocol"
48
39
  )
49
40
  apy: float = Field(None, description="Annual Percentage Yield")
50
- tvl: Optional[float] = Field(None, description="Total Value Locked in the protocol")
51
- underlying_tokens: List[str] = Field(
41
+ tvl: float | None = Field(None, description="Total Value Locked in the protocol")
42
+ underlying_tokens: list[str] = Field(
52
43
  [], description="List of underlying token symbols"
53
44
  )
54
45
 
@@ -56,7 +47,7 @@ class YieldOption(BaseModel):
56
47
  class EnsoGetBestYieldOutput(BaseModel):
57
48
  """Output containing the best yield options."""
58
49
 
59
- best_options: List[YieldOption] = Field(
50
+ best_options: list[YieldOption] = Field(
60
51
  [], description="List of best yield options sorted by APY (descending)"
61
52
  )
62
53
  token_symbol: str = Field(None, description="Symbol of the token searched for")
@@ -75,12 +66,12 @@ class EnsoGetBestYield(EnsoBaseTool):
75
66
  "Find the best yield options for a specific token (default: USDC) across all protocols "
76
67
  "on a blockchain network (default: Base). Results are sorted by APY in descending order."
77
68
  )
78
- args_schema: Type[BaseModel] = EnsoGetBestYieldInput
69
+ args_schema: type[BaseModel] = EnsoGetBestYieldInput
79
70
 
80
71
  async def _arun(
81
72
  self,
82
73
  token_symbol: str = "USDC",
83
- chain_id: int = BASE_CHAIN_ID,
74
+ chain_id: int | None = None,
84
75
  top_n: int = 5,
85
76
  **kwargs,
86
77
  ) -> EnsoGetBestYieldOutput:
@@ -89,7 +80,7 @@ class EnsoGetBestYield(EnsoBaseTool):
89
80
 
90
81
  Args:
91
82
  token_symbol (str): Symbol of the token to find the best yield for (default: USDC)
92
- chain_id (int): The chain id of the network (default: Base Mainnet)
83
+ chain_id (int | None): The chain id of the network. Defaults to the agent's configured network.
93
84
  top_n (int): Number of top yield options to return
94
85
 
95
86
  Returns:
@@ -99,16 +90,17 @@ class EnsoGetBestYield(EnsoBaseTool):
99
90
  ToolException: If there's an error accessing the Enso API.
100
91
  """
101
92
  context = self.get_context()
93
+ resolved_chain_id = self.resolve_chain_id(context, chain_id)
102
94
  api_token = self.get_api_token(context)
103
95
 
104
96
  if not api_token:
105
97
  raise ToolException("No API token found for Enso Finance")
106
98
 
107
99
  # Get the chain name for the given chain ID
108
- chain_name = await self._get_chain_name(api_token, chain_id)
100
+ chain_name = await self._get_chain_name(api_token, resolved_chain_id)
109
101
 
110
102
  # Get all protocols on the specified chain
111
- protocols = await self._get_protocols(api_token, chain_id)
103
+ protocols = await self._get_protocols(api_token, resolved_chain_id)
112
104
 
113
105
  # Collect all yield options from all protocols
114
106
  all_yield_options = []
@@ -119,7 +111,7 @@ class EnsoGetBestYield(EnsoBaseTool):
119
111
 
120
112
  # Get yield-bearing tokens for this protocol
121
113
  tokens = await self._get_protocol_tokens(
122
- api_token, chain_id, protocol_slug, token_symbol
114
+ api_token, resolved_chain_id, protocol_slug, token_symbol
123
115
  )
124
116
 
125
117
  # Process tokens to extract yield options
@@ -170,7 +162,7 @@ class EnsoGetBestYield(EnsoBaseTool):
170
162
  return EnsoGetBestYieldOutput(
171
163
  best_options=top_options,
172
164
  token_symbol=token_symbol,
173
- chain_id=chain_id,
165
+ chain_id=resolved_chain_id,
174
166
  chain_name=chain_name,
175
167
  )
176
168
 
@@ -1,14 +1,11 @@
1
1
  import logging
2
- from typing import Type
3
2
 
4
3
  import httpx
5
- from langchain.tools.base import ToolException
4
+ from langchain_core.tools.base import ToolException
6
5
  from pydantic import BaseModel, Field
7
6
 
8
7
  from .base import EnsoBaseTool, base_url
9
8
 
10
- logger = logging.getLogger(__name__)
11
-
12
9
 
13
10
  class EnsoGetNetworksInput(BaseModel):
14
11
  """
@@ -38,6 +35,9 @@ class EnsoGetNetworksOutput(BaseModel):
38
35
  )
39
36
 
40
37
 
38
+ logger = logging.getLogger(__name__)
39
+
40
+
41
41
  class EnsoGetNetworks(EnsoBaseTool):
42
42
  """
43
43
  Tool for retrieving networks and their corresponding chainId, the output should be kept.
@@ -45,7 +45,7 @@ class EnsoGetNetworks(EnsoBaseTool):
45
45
 
46
46
  name: str = "enso_get_networks"
47
47
  description: str = "Retrieve networks supported by the Enso API"
48
- args_schema: Type[BaseModel] = EnsoGetNetworksInput
48
+ args_schema: type[BaseModel] = EnsoGetNetworksInput
49
49
 
50
50
  async def _arun(self, **kwargs) -> EnsoGetNetworksOutput:
51
51
  """
@@ -82,12 +82,7 @@ class EnsoGetNetworks(EnsoBaseTool):
82
82
  exclude_none=True
83
83
  )
84
84
 
85
- await self.skill_store.save_agent_skill_data(
86
- context.agent_id,
87
- "enso_get_networks",
88
- "networks",
89
- networks_memory,
90
- )
85
+ await self.save_agent_skill_data("networks", networks_memory)
91
86
 
92
87
  return EnsoGetNetworksOutput(res=networks)
93
88
  except httpx.RequestError as req_err:
@@ -1,16 +1,12 @@
1
- from typing import Type
2
-
3
1
  import httpx
4
- from langchain.tools.base import ToolException
2
+ from langchain_core.tools.base import ToolException
5
3
  from pydantic import BaseModel, Field
6
4
 
7
- from .base import EnsoBaseTool, base_url, default_chain_id
5
+ from .base import EnsoBaseTool, base_url
8
6
 
9
7
 
10
8
  class EnsoGetPricesInput(BaseModel):
11
- chainId: int = Field(
12
- default_chain_id, description="Blockchain chain ID of the token"
13
- )
9
+ chainId: int | None = Field(None, description="Blockchain chain ID of the token")
14
10
  address: str = Field(
15
11
  "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
16
12
  description="Contract address of the token",
@@ -38,27 +34,26 @@ class EnsoGetPrices(EnsoBaseTool):
38
34
 
39
35
  name: str = "enso_get_prices"
40
36
  description: str = "Retrieve the price of a token by chain ID and contract address"
41
- args_schema: Type[BaseModel] = EnsoGetPricesInput
37
+ args_schema: type[BaseModel] = EnsoGetPricesInput
42
38
 
43
39
  async def _arun(
44
40
  self,
45
41
  address: str,
46
- chainId: int = default_chain_id,
42
+ chainId: int | None = None,
47
43
  **kwargs,
48
44
  ) -> EnsoGetPricesOutput:
49
45
  """
50
46
  Asynchronous function to request the token price from the API.
51
47
 
52
48
  Args:
53
- chainId (int): The blockchain's chain ID.
49
+ chainId (int | None): The blockchain's chain ID. Defaults to the agent's configured network.
54
50
  address (str): Contract address of the token.
55
51
 
56
52
  Returns:
57
53
  EnsoGetPricesOutput: Token price response or error message.
58
54
  """
59
- url = f"{base_url}/api/v1/prices/{str(chainId)}/{address}"
60
-
61
55
  context = self.get_context()
56
+ resolved_chain_id = self.resolve_chain_id(context, chainId)
62
57
  api_token = self.get_api_token(context)
63
58
 
64
59
  headers = {
@@ -68,7 +63,10 @@ class EnsoGetPrices(EnsoBaseTool):
68
63
 
69
64
  async with httpx.AsyncClient() as client:
70
65
  try:
71
- response = await client.get(url, headers=headers)
66
+ response = await client.get(
67
+ f"{base_url}/api/v1/prices/{str(resolved_chain_id)}/{address}",
68
+ headers=headers,
69
+ )
72
70
  response.raise_for_status()
73
71
  json_dict = response.json()
74
72
 
@@ -1,12 +1,10 @@
1
- from typing import Type
2
-
3
1
  import httpx
4
- from langchain.tools.base import ToolException
2
+ from langchain_core.tools.base import ToolException
5
3
  from pydantic import BaseModel, Field
6
4
 
7
5
  from intentkit.skills.enso.networks import EnsoGetNetworks
8
6
 
9
- from .base import EnsoBaseTool, base_url, default_chain_id
7
+ from .base import EnsoBaseTool, base_url, format_amount_with_decimals
10
8
 
11
9
 
12
10
  class EnsoRouteShortcutInput(BaseModel):
@@ -18,9 +16,9 @@ class EnsoRouteShortcutInput(BaseModel):
18
16
  False,
19
17
  description="Whether to broadcast the transaction or not, this is false by default.",
20
18
  )
21
- chainId: int = Field(
22
- default_chain_id,
23
- description="(Optional) Chain ID of the network to execute the transaction on. the default value is the chain_id extracted from networks according to tokenIn and tokenOut",
19
+ chainId: int | None = Field(
20
+ None,
21
+ description="(Optional) Chain ID of the network to execute the transaction on. Defaults to the agent's configured network.",
24
22
  )
25
23
  amountIn: list[int] = Field(
26
24
  description="Amount of tokenIn to swap in wei, you should multiply user's requested value by token decimals."
@@ -155,14 +153,14 @@ class EnsoRouteShortcut(EnsoBaseTool):
155
153
 
156
154
  name: str = "enso_route_shortcut"
157
155
  description: str = "This tool is used specifically for broadcasting a route transaction calldata to the network. It should only be used when the user explicitly requests to broadcast a route transaction with routeId."
158
- args_schema: Type[BaseModel] = EnsoRouteShortcutInput
156
+ args_schema: type[BaseModel] = EnsoRouteShortcutInput
159
157
 
160
158
  async def _arun(
161
159
  self,
162
160
  amountIn: list[int],
163
161
  tokenIn: list[str],
164
162
  tokenOut: list[str],
165
- chainId: int = default_chain_id,
163
+ chainId: int | None = None,
166
164
  broadcast_requested: bool = False,
167
165
  **kwargs,
168
166
  ) -> EnsoRouteShortcutOutput:
@@ -173,7 +171,7 @@ class EnsoRouteShortcut(EnsoBaseTool):
173
171
  amountIn (list[int]): Amount of tokenIn to swap in wei, you should multiply user's requested value by token decimals.
174
172
  tokenIn (list[str]): Ethereum address of the token to swap or enter into a position from (For ETH, use 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee).
175
173
  tokenOut (list[str]): Ethereum address of the token to swap or enter into a position to (For ETH, use 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee).
176
- chainId (int): The chain id of the network to be used for swap, deposit and routing.
174
+ chainId (int | None): The chain id of the network to be used for swap, deposit and routing. Defaults to the agent's configured network.
177
175
  broadcast_requested (bool): User should ask for broadcasting the transaction explicitly, otherwise it is always false.
178
176
 
179
177
  Returns:
@@ -181,35 +179,36 @@ class EnsoRouteShortcut(EnsoBaseTool):
181
179
  """
182
180
 
183
181
  context = self.get_context()
184
- agent_id = context.agent_id
182
+ resolved_chain_id = self.resolve_chain_id(context, chainId)
185
183
  api_token = self.get_api_token(context)
186
- account = await self.get_account(context)
184
+ # Use the wallet provider to send the transaction
185
+ wallet_provider = await self.get_wallet_provider(context)
186
+ wallet_address = wallet_provider.get_address()
187
187
 
188
188
  async with httpx.AsyncClient() as client:
189
189
  try:
190
190
  network_name = None
191
- networks = await self.skill_store.get_agent_skill_data(
192
- agent_id, "enso_get_networks", "networks"
191
+ networks = await self.get_agent_skill_data_raw(
192
+ "enso_get_networks", "networks"
193
193
  )
194
194
 
195
195
  if networks:
196
+ resolved_key = str(resolved_chain_id)
196
197
  network_name = (
197
- networks.get(str(chainId)).get("name")
198
- if networks.get(str(chainId))
198
+ networks.get(resolved_key).get("name")
199
+ if networks.get(resolved_key)
199
200
  else None
200
201
  )
201
202
  if network_name is None:
202
- networks = await EnsoGetNetworks(
203
- skill_store=self.skill_store,
204
- ).arun()
203
+ networks = await EnsoGetNetworks().arun()
205
204
 
206
205
  for network in networks.res:
207
- if network.id == chainId:
206
+ if network.id == resolved_chain_id:
208
207
  network_name = network.name
209
208
 
210
209
  if not network_name:
211
210
  raise ToolException(
212
- f"network name not found for chainId: {chainId}"
211
+ f"network name not found for chainId: {resolved_chain_id}"
213
212
  )
214
213
 
215
214
  headers = {
@@ -217,8 +216,7 @@ class EnsoRouteShortcut(EnsoBaseTool):
217
216
  "Authorization": f"Bearer {api_token}",
218
217
  }
219
218
 
220
- token_decimals = await self.skill_store.get_agent_skill_data(
221
- agent_id,
219
+ token_decimals = await self.get_agent_skill_data_raw(
222
220
  "enso_get_tokens",
223
221
  "decimals",
224
222
  )
@@ -242,13 +240,13 @@ class EnsoRouteShortcut(EnsoBaseTool):
242
240
 
243
241
  # Prepare query parameters
244
242
  params = EnsoRouteShortcutInput(
245
- chainId=chainId,
243
+ chainId=resolved_chain_id,
246
244
  amountIn=amountIn,
247
245
  tokenIn=tokenIn,
248
246
  tokenOut=tokenOut,
249
247
  ).model_dump(exclude_none=True)
250
248
 
251
- params["fromAddress"] = account.address
249
+ params["fromAddress"] = wallet_address
252
250
 
253
251
  response = await client.get(url, headers=headers, params=params)
254
252
  response.raise_for_status() # Raise HTTPError for non-2xx responses
@@ -256,26 +254,24 @@ class EnsoRouteShortcut(EnsoBaseTool):
256
254
 
257
255
  res = EnsoRouteShortcutOutput(**json_dict)
258
256
  res.network = network_name
259
-
260
- res.amountOut = str(
261
- float(res.amountOut) / 10 ** token_decimals[tokenOut[0]]
257
+ decimals = token_decimals.get(tokenOut[0])
258
+ amount_out = format_amount_with_decimals(
259
+ json_dict.get("amountOut"), decimals
262
260
  )
261
+ if amount_out is not None:
262
+ res.amountOut = amount_out
263
263
 
264
264
  if broadcast_requested:
265
- # Use the wallet provider to send the transaction
266
- wallet_provider = await self.get_wallet_provider(context)
267
-
268
265
  # Extract transaction data from the Enso API response
269
266
  tx_data = json_dict.get("tx", {})
270
267
  if tx_data:
271
268
  # Send the transaction using the wallet provider
272
- tx_hash = wallet_provider.send_transaction(
273
- {
274
- "to": tx_data.get("to"),
275
- "data": tx_data.get("data", "0x"),
276
- "value": tx_data.get("value", 0),
277
- }
278
- )
269
+ tx_params = {
270
+ "to": tx_data.get("to"),
271
+ "data": tx_data.get("data", "0x"),
272
+ "value": tx_data.get("value", 0),
273
+ }
274
+ tx_hash = wallet_provider.send_transaction(tx_params)
279
275
 
280
276
  # Wait for transaction confirmation
281
277
  wallet_provider.wait_for_transaction_receipt(tx_hash)
@@ -5,7 +5,8 @@
5
5
  "description": "Integration with Enso Finance API providing DeFi trading and portfolio management capabilities across multiple blockchain networks",
6
6
  "x-icon": "https://ai.service.crestal.dev/skills/enso/enso.jpg",
7
7
  "x-tags": [
8
- "Blockchain"
8
+ "Analytics",
9
+ "DeFi"
9
10
  ],
10
11
  "properties": {
11
12
  "enabled": {
@@ -209,4 +210,4 @@
209
210
  }
210
211
  },
211
212
  "additionalProperties": true
212
- }
213
+ }