intentkit 0.5.0__py3-none-any.whl → 0.5.2__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (366) hide show
  1. intentkit/__init__.py +17 -0
  2. intentkit/abstracts/__init__.py +0 -0
  3. intentkit/abstracts/agent.py +60 -0
  4. intentkit/abstracts/api.py +4 -0
  5. intentkit/abstracts/engine.py +38 -0
  6. intentkit/abstracts/exception.py +9 -0
  7. intentkit/abstracts/graph.py +25 -0
  8. intentkit/abstracts/skill.py +129 -0
  9. intentkit/abstracts/twitter.py +54 -0
  10. intentkit/clients/__init__.py +14 -0
  11. intentkit/clients/cdp.py +53 -0
  12. intentkit/clients/twitter.py +445 -0
  13. intentkit/config/__init__.py +0 -0
  14. intentkit/config/config.py +164 -0
  15. intentkit/core/__init__.py +0 -0
  16. intentkit/core/agent.py +191 -0
  17. intentkit/core/api.py +40 -0
  18. intentkit/core/client.py +45 -0
  19. intentkit/core/credit.py +1767 -0
  20. intentkit/core/engine.py +1018 -0
  21. intentkit/core/node.py +223 -0
  22. intentkit/core/prompt.py +58 -0
  23. intentkit/core/skill.py +124 -0
  24. intentkit/models/agent.py +1689 -0
  25. intentkit/models/agent_data.py +810 -0
  26. intentkit/models/agent_schema.json +733 -0
  27. intentkit/models/app_setting.py +156 -0
  28. intentkit/models/base.py +9 -0
  29. intentkit/models/chat.py +581 -0
  30. intentkit/models/conversation.py +286 -0
  31. intentkit/models/credit.py +1406 -0
  32. intentkit/models/db.py +120 -0
  33. intentkit/models/db_mig.py +102 -0
  34. intentkit/models/generator.py +347 -0
  35. intentkit/models/llm.py +746 -0
  36. intentkit/models/redis.py +132 -0
  37. intentkit/models/skill.py +466 -0
  38. intentkit/models/user.py +243 -0
  39. intentkit/skills/__init__.py +12 -0
  40. intentkit/skills/acolyt/__init__.py +83 -0
  41. intentkit/skills/acolyt/acolyt.jpg +0 -0
  42. intentkit/skills/acolyt/ask.py +128 -0
  43. intentkit/skills/acolyt/base.py +28 -0
  44. intentkit/skills/acolyt/schema.json +89 -0
  45. intentkit/skills/aixbt/README.md +71 -0
  46. intentkit/skills/aixbt/__init__.py +73 -0
  47. intentkit/skills/aixbt/aixbt.jpg +0 -0
  48. intentkit/skills/aixbt/base.py +21 -0
  49. intentkit/skills/aixbt/projects.py +153 -0
  50. intentkit/skills/aixbt/schema.json +99 -0
  51. intentkit/skills/allora/__init__.py +83 -0
  52. intentkit/skills/allora/allora.jpeg +0 -0
  53. intentkit/skills/allora/base.py +28 -0
  54. intentkit/skills/allora/price.py +130 -0
  55. intentkit/skills/allora/schema.json +89 -0
  56. intentkit/skills/base.py +174 -0
  57. intentkit/skills/carv/README.md +95 -0
  58. intentkit/skills/carv/__init__.py +121 -0
  59. intentkit/skills/carv/base.py +183 -0
  60. intentkit/skills/carv/carv.webp +0 -0
  61. intentkit/skills/carv/fetch_news.py +92 -0
  62. intentkit/skills/carv/onchain_query.py +164 -0
  63. intentkit/skills/carv/schema.json +137 -0
  64. intentkit/skills/carv/token_info_and_price.py +110 -0
  65. intentkit/skills/cdp/__init__.py +137 -0
  66. intentkit/skills/cdp/base.py +21 -0
  67. intentkit/skills/cdp/cdp.png +0 -0
  68. intentkit/skills/cdp/get_balance.py +81 -0
  69. intentkit/skills/cdp/schema.json +473 -0
  70. intentkit/skills/chainlist/README.md +38 -0
  71. intentkit/skills/chainlist/__init__.py +54 -0
  72. intentkit/skills/chainlist/base.py +21 -0
  73. intentkit/skills/chainlist/chain_lookup.py +208 -0
  74. intentkit/skills/chainlist/chainlist.png +0 -0
  75. intentkit/skills/chainlist/schema.json +47 -0
  76. intentkit/skills/common/__init__.py +82 -0
  77. intentkit/skills/common/base.py +21 -0
  78. intentkit/skills/common/common.jpg +0 -0
  79. intentkit/skills/common/current_time.py +84 -0
  80. intentkit/skills/common/schema.json +57 -0
  81. intentkit/skills/cookiefun/README.md +121 -0
  82. intentkit/skills/cookiefun/__init__.py +78 -0
  83. intentkit/skills/cookiefun/base.py +41 -0
  84. intentkit/skills/cookiefun/constants.py +18 -0
  85. intentkit/skills/cookiefun/cookiefun.png +0 -0
  86. intentkit/skills/cookiefun/get_account_details.py +171 -0
  87. intentkit/skills/cookiefun/get_account_feed.py +282 -0
  88. intentkit/skills/cookiefun/get_account_smart_followers.py +181 -0
  89. intentkit/skills/cookiefun/get_sectors.py +128 -0
  90. intentkit/skills/cookiefun/schema.json +155 -0
  91. intentkit/skills/cookiefun/search_accounts.py +225 -0
  92. intentkit/skills/cryptocompare/__init__.py +130 -0
  93. intentkit/skills/cryptocompare/api.py +159 -0
  94. intentkit/skills/cryptocompare/base.py +303 -0
  95. intentkit/skills/cryptocompare/cryptocompare.png +0 -0
  96. intentkit/skills/cryptocompare/fetch_news.py +96 -0
  97. intentkit/skills/cryptocompare/fetch_price.py +99 -0
  98. intentkit/skills/cryptocompare/fetch_top_exchanges.py +113 -0
  99. intentkit/skills/cryptocompare/fetch_top_market_cap.py +109 -0
  100. intentkit/skills/cryptocompare/fetch_top_volume.py +108 -0
  101. intentkit/skills/cryptocompare/fetch_trading_signals.py +107 -0
  102. intentkit/skills/cryptocompare/schema.json +168 -0
  103. intentkit/skills/cryptopanic/__init__.py +108 -0
  104. intentkit/skills/cryptopanic/base.py +51 -0
  105. intentkit/skills/cryptopanic/cryptopanic.png +0 -0
  106. intentkit/skills/cryptopanic/fetch_crypto_news.py +153 -0
  107. intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +136 -0
  108. intentkit/skills/cryptopanic/schema.json +103 -0
  109. intentkit/skills/dapplooker/README.md +92 -0
  110. intentkit/skills/dapplooker/__init__.py +83 -0
  111. intentkit/skills/dapplooker/base.py +26 -0
  112. intentkit/skills/dapplooker/dapplooker.jpg +0 -0
  113. intentkit/skills/dapplooker/dapplooker_token_data.py +476 -0
  114. intentkit/skills/dapplooker/schema.json +91 -0
  115. intentkit/skills/defillama/__init__.py +323 -0
  116. intentkit/skills/defillama/api.py +315 -0
  117. intentkit/skills/defillama/base.py +135 -0
  118. intentkit/skills/defillama/coins/__init__.py +0 -0
  119. intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +116 -0
  120. intentkit/skills/defillama/coins/fetch_block.py +98 -0
  121. intentkit/skills/defillama/coins/fetch_current_prices.py +105 -0
  122. intentkit/skills/defillama/coins/fetch_first_price.py +100 -0
  123. intentkit/skills/defillama/coins/fetch_historical_prices.py +110 -0
  124. intentkit/skills/defillama/coins/fetch_price_chart.py +109 -0
  125. intentkit/skills/defillama/coins/fetch_price_percentage.py +93 -0
  126. intentkit/skills/defillama/config/__init__.py +0 -0
  127. intentkit/skills/defillama/config/chains.py +433 -0
  128. intentkit/skills/defillama/defillama.jpeg +0 -0
  129. intentkit/skills/defillama/fees/__init__.py +0 -0
  130. intentkit/skills/defillama/fees/fetch_fees_overview.py +130 -0
  131. intentkit/skills/defillama/schema.json +383 -0
  132. intentkit/skills/defillama/stablecoins/__init__.py +0 -0
  133. intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +100 -0
  134. intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +129 -0
  135. intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +83 -0
  136. intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +126 -0
  137. intentkit/skills/defillama/tests/__init__.py +0 -0
  138. intentkit/skills/defillama/tests/api_integration.test.py +192 -0
  139. intentkit/skills/defillama/tests/api_unit.test.py +583 -0
  140. intentkit/skills/defillama/tvl/__init__.py +0 -0
  141. intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +106 -0
  142. intentkit/skills/defillama/tvl/fetch_chains.py +107 -0
  143. intentkit/skills/defillama/tvl/fetch_historical_tvl.py +91 -0
  144. intentkit/skills/defillama/tvl/fetch_protocol.py +207 -0
  145. intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +93 -0
  146. intentkit/skills/defillama/tvl/fetch_protocols.py +196 -0
  147. intentkit/skills/defillama/volumes/__init__.py +0 -0
  148. intentkit/skills/defillama/volumes/fetch_dex_overview.py +157 -0
  149. intentkit/skills/defillama/volumes/fetch_dex_summary.py +123 -0
  150. intentkit/skills/defillama/volumes/fetch_options_overview.py +131 -0
  151. intentkit/skills/defillama/yields/__init__.py +0 -0
  152. intentkit/skills/defillama/yields/fetch_pool_chart.py +100 -0
  153. intentkit/skills/defillama/yields/fetch_pools.py +126 -0
  154. intentkit/skills/dexscreener/__init__.py +93 -0
  155. intentkit/skills/dexscreener/base.py +133 -0
  156. intentkit/skills/dexscreener/dexscreener.png +0 -0
  157. intentkit/skills/dexscreener/model/__init__.py +0 -0
  158. intentkit/skills/dexscreener/model/search_token_response.py +82 -0
  159. intentkit/skills/dexscreener/schema.json +48 -0
  160. intentkit/skills/dexscreener/search_token.py +321 -0
  161. intentkit/skills/dune_analytics/__init__.py +103 -0
  162. intentkit/skills/dune_analytics/base.py +46 -0
  163. intentkit/skills/dune_analytics/dune.png +0 -0
  164. intentkit/skills/dune_analytics/fetch_kol_buys.py +128 -0
  165. intentkit/skills/dune_analytics/fetch_nation_metrics.py +237 -0
  166. intentkit/skills/dune_analytics/schema.json +99 -0
  167. intentkit/skills/elfa/README.md +100 -0
  168. intentkit/skills/elfa/__init__.py +123 -0
  169. intentkit/skills/elfa/base.py +28 -0
  170. intentkit/skills/elfa/elfa.jpg +0 -0
  171. intentkit/skills/elfa/mention.py +504 -0
  172. intentkit/skills/elfa/schema.json +153 -0
  173. intentkit/skills/elfa/stats.py +118 -0
  174. intentkit/skills/elfa/tokens.py +126 -0
  175. intentkit/skills/enso/README.md +75 -0
  176. intentkit/skills/enso/__init__.py +114 -0
  177. intentkit/skills/enso/abi/__init__.py +0 -0
  178. intentkit/skills/enso/abi/approval.py +279 -0
  179. intentkit/skills/enso/abi/erc20.py +14 -0
  180. intentkit/skills/enso/abi/route.py +129 -0
  181. intentkit/skills/enso/base.py +44 -0
  182. intentkit/skills/enso/best_yield.py +286 -0
  183. intentkit/skills/enso/enso.jpg +0 -0
  184. intentkit/skills/enso/networks.py +105 -0
  185. intentkit/skills/enso/prices.py +93 -0
  186. intentkit/skills/enso/route.py +300 -0
  187. intentkit/skills/enso/schema.json +212 -0
  188. intentkit/skills/enso/tokens.py +223 -0
  189. intentkit/skills/enso/wallet.py +381 -0
  190. intentkit/skills/github/README.md +63 -0
  191. intentkit/skills/github/__init__.py +54 -0
  192. intentkit/skills/github/base.py +21 -0
  193. intentkit/skills/github/github.jpg +0 -0
  194. intentkit/skills/github/github_search.py +183 -0
  195. intentkit/skills/github/schema.json +59 -0
  196. intentkit/skills/heurist/__init__.py +143 -0
  197. intentkit/skills/heurist/base.py +26 -0
  198. intentkit/skills/heurist/heurist.png +0 -0
  199. intentkit/skills/heurist/image_generation_animagine_xl.py +162 -0
  200. intentkit/skills/heurist/image_generation_arthemy_comics.py +162 -0
  201. intentkit/skills/heurist/image_generation_arthemy_real.py +162 -0
  202. intentkit/skills/heurist/image_generation_braindance.py +162 -0
  203. intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +162 -0
  204. intentkit/skills/heurist/image_generation_flux_1_dev.py +162 -0
  205. intentkit/skills/heurist/image_generation_sdxl.py +161 -0
  206. intentkit/skills/heurist/schema.json +196 -0
  207. intentkit/skills/lifi/README.md +294 -0
  208. intentkit/skills/lifi/__init__.py +141 -0
  209. intentkit/skills/lifi/base.py +21 -0
  210. intentkit/skills/lifi/lifi.png +0 -0
  211. intentkit/skills/lifi/schema.json +89 -0
  212. intentkit/skills/lifi/token_execute.py +472 -0
  213. intentkit/skills/lifi/token_quote.py +190 -0
  214. intentkit/skills/lifi/utils.py +656 -0
  215. intentkit/skills/moralis/README.md +490 -0
  216. intentkit/skills/moralis/__init__.py +110 -0
  217. intentkit/skills/moralis/api.py +281 -0
  218. intentkit/skills/moralis/base.py +55 -0
  219. intentkit/skills/moralis/fetch_chain_portfolio.py +191 -0
  220. intentkit/skills/moralis/fetch_nft_portfolio.py +284 -0
  221. intentkit/skills/moralis/fetch_solana_portfolio.py +331 -0
  222. intentkit/skills/moralis/fetch_wallet_portfolio.py +301 -0
  223. intentkit/skills/moralis/moralis.png +0 -0
  224. intentkit/skills/moralis/schema.json +156 -0
  225. intentkit/skills/moralis/tests/__init__.py +0 -0
  226. intentkit/skills/moralis/tests/test_wallet.py +511 -0
  227. intentkit/skills/nation/__init__.py +62 -0
  228. intentkit/skills/nation/base.py +31 -0
  229. intentkit/skills/nation/nation.png +0 -0
  230. intentkit/skills/nation/nft_check.py +106 -0
  231. intentkit/skills/nation/schema.json +58 -0
  232. intentkit/skills/openai/__init__.py +107 -0
  233. intentkit/skills/openai/base.py +32 -0
  234. intentkit/skills/openai/dalle_image_generation.py +128 -0
  235. intentkit/skills/openai/gpt_image_generation.py +152 -0
  236. intentkit/skills/openai/gpt_image_to_image.py +186 -0
  237. intentkit/skills/openai/image_to_text.py +126 -0
  238. intentkit/skills/openai/openai.png +0 -0
  239. intentkit/skills/openai/schema.json +139 -0
  240. intentkit/skills/portfolio/README.md +55 -0
  241. intentkit/skills/portfolio/__init__.py +151 -0
  242. intentkit/skills/portfolio/base.py +107 -0
  243. intentkit/skills/portfolio/constants.py +9 -0
  244. intentkit/skills/portfolio/moralis.png +0 -0
  245. intentkit/skills/portfolio/schema.json +237 -0
  246. intentkit/skills/portfolio/token_balances.py +155 -0
  247. intentkit/skills/portfolio/wallet_approvals.py +102 -0
  248. intentkit/skills/portfolio/wallet_defi_positions.py +80 -0
  249. intentkit/skills/portfolio/wallet_history.py +155 -0
  250. intentkit/skills/portfolio/wallet_net_worth.py +112 -0
  251. intentkit/skills/portfolio/wallet_nfts.py +139 -0
  252. intentkit/skills/portfolio/wallet_profitability.py +101 -0
  253. intentkit/skills/portfolio/wallet_profitability_summary.py +91 -0
  254. intentkit/skills/portfolio/wallet_stats.py +79 -0
  255. intentkit/skills/portfolio/wallet_swaps.py +147 -0
  256. intentkit/skills/skills.toml +103 -0
  257. intentkit/skills/slack/__init__.py +98 -0
  258. intentkit/skills/slack/base.py +55 -0
  259. intentkit/skills/slack/get_channel.py +109 -0
  260. intentkit/skills/slack/get_message.py +136 -0
  261. intentkit/skills/slack/schedule_message.py +92 -0
  262. intentkit/skills/slack/schema.json +135 -0
  263. intentkit/skills/slack/send_message.py +81 -0
  264. intentkit/skills/slack/slack.jpg +0 -0
  265. intentkit/skills/system/__init__.py +90 -0
  266. intentkit/skills/system/base.py +22 -0
  267. intentkit/skills/system/read_agent_api_key.py +87 -0
  268. intentkit/skills/system/regenerate_agent_api_key.py +77 -0
  269. intentkit/skills/system/schema.json +53 -0
  270. intentkit/skills/system/system.svg +76 -0
  271. intentkit/skills/tavily/README.md +86 -0
  272. intentkit/skills/tavily/__init__.py +91 -0
  273. intentkit/skills/tavily/base.py +27 -0
  274. intentkit/skills/tavily/schema.json +119 -0
  275. intentkit/skills/tavily/tavily.jpg +0 -0
  276. intentkit/skills/tavily/tavily_extract.py +147 -0
  277. intentkit/skills/tavily/tavily_search.py +139 -0
  278. intentkit/skills/token/README.md +89 -0
  279. intentkit/skills/token/__init__.py +107 -0
  280. intentkit/skills/token/base.py +154 -0
  281. intentkit/skills/token/constants.py +9 -0
  282. intentkit/skills/token/erc20_transfers.py +145 -0
  283. intentkit/skills/token/moralis.png +0 -0
  284. intentkit/skills/token/schema.json +141 -0
  285. intentkit/skills/token/token_analytics.py +81 -0
  286. intentkit/skills/token/token_price.py +132 -0
  287. intentkit/skills/token/token_search.py +121 -0
  288. intentkit/skills/twitter/__init__.py +146 -0
  289. intentkit/skills/twitter/base.py +68 -0
  290. intentkit/skills/twitter/follow_user.py +69 -0
  291. intentkit/skills/twitter/get_mentions.py +124 -0
  292. intentkit/skills/twitter/get_timeline.py +111 -0
  293. intentkit/skills/twitter/get_user_by_username.py +84 -0
  294. intentkit/skills/twitter/get_user_tweets.py +123 -0
  295. intentkit/skills/twitter/like_tweet.py +65 -0
  296. intentkit/skills/twitter/post_tweet.py +90 -0
  297. intentkit/skills/twitter/reply_tweet.py +98 -0
  298. intentkit/skills/twitter/retweet.py +76 -0
  299. intentkit/skills/twitter/schema.json +258 -0
  300. intentkit/skills/twitter/search_tweets.py +115 -0
  301. intentkit/skills/twitter/twitter.png +0 -0
  302. intentkit/skills/unrealspeech/__init__.py +55 -0
  303. intentkit/skills/unrealspeech/base.py +21 -0
  304. intentkit/skills/unrealspeech/schema.json +100 -0
  305. intentkit/skills/unrealspeech/text_to_speech.py +177 -0
  306. intentkit/skills/unrealspeech/unrealspeech.jpg +0 -0
  307. intentkit/skills/venice_audio/__init__.py +106 -0
  308. intentkit/skills/venice_audio/base.py +119 -0
  309. intentkit/skills/venice_audio/input.py +41 -0
  310. intentkit/skills/venice_audio/schema.json +152 -0
  311. intentkit/skills/venice_audio/venice_audio.py +240 -0
  312. intentkit/skills/venice_audio/venice_logo.jpg +0 -0
  313. intentkit/skills/venice_image/README.md +119 -0
  314. intentkit/skills/venice_image/__init__.py +154 -0
  315. intentkit/skills/venice_image/api.py +138 -0
  316. intentkit/skills/venice_image/base.py +188 -0
  317. intentkit/skills/venice_image/config.py +35 -0
  318. intentkit/skills/venice_image/image_enhance/README.md +119 -0
  319. intentkit/skills/venice_image/image_enhance/__init__.py +0 -0
  320. intentkit/skills/venice_image/image_enhance/image_enhance.py +80 -0
  321. intentkit/skills/venice_image/image_enhance/image_enhance_base.py +23 -0
  322. intentkit/skills/venice_image/image_enhance/image_enhance_input.py +40 -0
  323. intentkit/skills/venice_image/image_generation/README.md +144 -0
  324. intentkit/skills/venice_image/image_generation/__init__.py +0 -0
  325. intentkit/skills/venice_image/image_generation/image_generation_base.py +117 -0
  326. intentkit/skills/venice_image/image_generation/image_generation_fluently_xl.py +26 -0
  327. intentkit/skills/venice_image/image_generation/image_generation_flux_dev.py +27 -0
  328. intentkit/skills/venice_image/image_generation/image_generation_flux_dev_uncensored.py +26 -0
  329. intentkit/skills/venice_image/image_generation/image_generation_input.py +158 -0
  330. intentkit/skills/venice_image/image_generation/image_generation_lustify_sdxl.py +26 -0
  331. intentkit/skills/venice_image/image_generation/image_generation_pony_realism.py +26 -0
  332. intentkit/skills/venice_image/image_generation/image_generation_stable_diffusion_3_5.py +28 -0
  333. intentkit/skills/venice_image/image_generation/image_generation_venice_sd35.py +28 -0
  334. intentkit/skills/venice_image/image_upscale/README.md +111 -0
  335. intentkit/skills/venice_image/image_upscale/__init__.py +0 -0
  336. intentkit/skills/venice_image/image_upscale/image_upscale.py +90 -0
  337. intentkit/skills/venice_image/image_upscale/image_upscale_base.py +23 -0
  338. intentkit/skills/venice_image/image_upscale/image_upscale_input.py +22 -0
  339. intentkit/skills/venice_image/image_vision/README.md +112 -0
  340. intentkit/skills/venice_image/image_vision/__init__.py +0 -0
  341. intentkit/skills/venice_image/image_vision/image_vision.py +100 -0
  342. intentkit/skills/venice_image/image_vision/image_vision_base.py +17 -0
  343. intentkit/skills/venice_image/image_vision/image_vision_input.py +9 -0
  344. intentkit/skills/venice_image/schema.json +267 -0
  345. intentkit/skills/venice_image/utils.py +78 -0
  346. intentkit/skills/venice_image/venice_image.jpg +0 -0
  347. intentkit/skills/web_scraper/README.md +82 -0
  348. intentkit/skills/web_scraper/__init__.py +92 -0
  349. intentkit/skills/web_scraper/base.py +21 -0
  350. intentkit/skills/web_scraper/langchain.png +0 -0
  351. intentkit/skills/web_scraper/schema.json +115 -0
  352. intentkit/skills/web_scraper/scrape_and_index.py +327 -0
  353. intentkit/utils/__init__.py +1 -0
  354. intentkit/utils/chain.py +436 -0
  355. intentkit/utils/error.py +134 -0
  356. intentkit/utils/logging.py +70 -0
  357. intentkit/utils/middleware.py +61 -0
  358. intentkit/utils/random.py +16 -0
  359. intentkit/utils/s3.py +267 -0
  360. intentkit/utils/slack_alert.py +79 -0
  361. intentkit/utils/tx.py +37 -0
  362. {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/METADATA +1 -1
  363. intentkit-0.5.2.dist-info/RECORD +365 -0
  364. intentkit-0.5.0.dist-info/RECORD +0 -4
  365. {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/WHEEL +0 -0
  366. {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,511 @@
1
+ """Tests for the Moralis Wallet Portfolio skills."""
2
+
3
+ import asyncio
4
+ import json
5
+ import unittest
6
+ from unittest.mock import AsyncMock, MagicMock, patch
7
+
8
+ from intentkit.skills.moralis import (
9
+ FetchChainPortfolio,
10
+ FetchSolanaPortfolio,
11
+ FetchWalletPortfolio,
12
+ get_skills,
13
+ )
14
+ from intentkit.skills.moralis.api import (
15
+ fetch_moralis_data,
16
+ fetch_wallet_balances,
17
+ get_solana_portfolio,
18
+ )
19
+ from intentkit.skills.moralis.base import WalletBaseTool
20
+
21
+
22
+ class DummyResponse:
23
+ """Mock HTTP response for testing."""
24
+
25
+ def __init__(self, status_code, json_data):
26
+ self.status_code = status_code
27
+ self._json_data = json_data
28
+ self.text = json.dumps(json_data) if json_data else ""
29
+
30
+ def json(self):
31
+ return self._json_data
32
+
33
+ async def raise_for_status(self):
34
+ if self.status_code >= 400:
35
+ raise Exception(f"HTTP Error: {self.status_code}")
36
+
37
+
38
+ class TestWalletBaseClass(unittest.TestCase):
39
+ """Test the base wallet portfolio tool class."""
40
+
41
+ def setUp(self):
42
+ self.loop = asyncio.new_event_loop()
43
+ asyncio.set_event_loop(self.loop)
44
+
45
+ self.mock_skill_store = MagicMock()
46
+
47
+ def tearDown(self):
48
+ self.loop.close()
49
+
50
+ def test_base_class_init(self):
51
+ """Test base class initialization."""
52
+
53
+ # Create a concrete subclass for testing
54
+ class TestTool(WalletBaseTool):
55
+ async def _arun(self, *args, **kwargs):
56
+ return "test"
57
+
58
+ tool = TestTool(
59
+ name="test_tool",
60
+ description="Test tool",
61
+ args_schema=MagicMock(),
62
+ api_key="test_key",
63
+ skill_store=self.mock_skill_store,
64
+ agent_id="test_agent",
65
+ )
66
+
67
+ self.assertEqual(tool.api_key, "test_key")
68
+ self.assertEqual(tool.agent_id, "test_agent")
69
+ self.assertEqual(tool.skill_store, self.mock_skill_store)
70
+ self.assertEqual(tool.category, "moralis")
71
+
72
+ def test_get_chain_name(self):
73
+ """Test chain name conversion."""
74
+
75
+ class TestTool(WalletBaseTool):
76
+ async def _arun(self, *args, **kwargs):
77
+ return "test"
78
+
79
+ tool = TestTool(
80
+ name="test_tool",
81
+ description="Test tool",
82
+ args_schema=MagicMock(),
83
+ api_key="test_key",
84
+ skill_store=self.mock_skill_store,
85
+ agent_id="test_agent",
86
+ )
87
+
88
+ # Test with known chain IDs
89
+ self.assertEqual(tool._get_chain_name(1), "eth")
90
+ self.assertEqual(tool._get_chain_name(56), "bsc")
91
+ self.assertEqual(tool._get_chain_name(137), "polygon")
92
+
93
+ # Test with unknown chain ID
94
+ self.assertEqual(tool._get_chain_name(999999), "eth")
95
+
96
+
97
+ class TestAPIFunctions(unittest.IsolatedAsyncioTestCase):
98
+ """Test the API interaction functions."""
99
+
100
+ async def test_fetch_moralis_data(self):
101
+ """Test the base Moralis API function."""
102
+ with patch("httpx.AsyncClient") as MockClient:
103
+ client_instance = AsyncMock()
104
+ client_instance.get.return_value = DummyResponse(
105
+ 200, {"success": True, "data": "test_data"}
106
+ )
107
+ MockClient.return_value.__aenter__.return_value = client_instance
108
+
109
+ result = await fetch_moralis_data(
110
+ "test_api_key", "test_endpoint", "0xAddress", 1
111
+ )
112
+
113
+ self.assertEqual(result, {"success": True, "data": "test_data"})
114
+
115
+ # Test error handling
116
+ client_instance.get.return_value = DummyResponse(404, None)
117
+ client_instance.get.return_value.raise_for_status = AsyncMock(
118
+ side_effect=Exception("HTTP error 404")
119
+ )
120
+
121
+ result = await fetch_moralis_data(
122
+ "test_api_key", "test_endpoint", "0xAddress", 1
123
+ )
124
+ self.assertIn("error", result)
125
+
126
+ async def test_fetch_wallet_balances(self):
127
+ """Test fetching wallet balances."""
128
+ with patch("skills.moralis.api.fetch_moralis_data") as mock_fetch:
129
+ mock_fetch.return_value = {
130
+ "result": [
131
+ {
132
+ "token_address": "0x123",
133
+ "symbol": "TEST",
134
+ "balance": "1000000",
135
+ "usd_value": 100,
136
+ }
137
+ ]
138
+ }
139
+
140
+ result = await fetch_wallet_balances("test_api_key", "0xAddress", 1)
141
+
142
+ self.assertEqual(result["result"][0]["symbol"], "TEST")
143
+ mock_fetch.assert_called_once_with(
144
+ "test_api_key", "wallets/{address}/tokens", "0xAddress", 1, None
145
+ )
146
+
147
+ async def test_get_solana_portfolio(self):
148
+ """Test getting Solana portfolio."""
149
+ with patch("skills.moralis.api.fetch_solana_api") as mock_fetch:
150
+ mock_fetch.return_value = {
151
+ "nativeBalance": {"solana": 1.5, "lamports": 1500000000},
152
+ "tokens": [
153
+ {
154
+ "symbol": "TEST",
155
+ "name": "Test Token",
156
+ "mint": "TokenMintAddress",
157
+ "associatedTokenAddress": "AssocTokenAddress",
158
+ "amount": 10,
159
+ "decimals": 9,
160
+ "amountRaw": "10000000000",
161
+ }
162
+ ],
163
+ }
164
+
165
+ result = await get_solana_portfolio("test_api_key", "SolAddress", "mainnet")
166
+
167
+ mock_fetch.assert_called_once_with(
168
+ "test_api_key", "/account/mainnet/SolAddress/portfolio"
169
+ )
170
+ self.assertEqual(result["nativeBalance"]["solana"], 1.5)
171
+ self.assertEqual(len(result["tokens"]), 1)
172
+ self.assertEqual(result["tokens"][0]["symbol"], "TEST")
173
+
174
+
175
+ class TestFetchWalletPortfolio(unittest.IsolatedAsyncioTestCase):
176
+ """Test the FetchWalletPortfolio skill."""
177
+
178
+ async def test_wallet_portfolio_success(self):
179
+ """Test successful wallet portfolio fetch."""
180
+ mock_skill_store = MagicMock()
181
+
182
+ with (
183
+ patch(
184
+ "skills.moralis.moralis_fetch_wallet_portfolio.fetch_wallet_balances"
185
+ ) as mock_balances,
186
+ patch(
187
+ "skills.moralis.moralis_fetch_wallet_portfolio.fetch_net_worth"
188
+ ) as mock_net_worth,
189
+ ):
190
+ # Mock successful responses
191
+ mock_balances.return_value = {
192
+ "result": [
193
+ {
194
+ "token_address": "0x123",
195
+ "symbol": "TEST",
196
+ "name": "Test Token",
197
+ "balance": "1000000000000000000",
198
+ "balance_formatted": "1.0",
199
+ "usd_value": 100,
200
+ }
201
+ ]
202
+ }
203
+ mock_net_worth.return_value = {"result": {"total_networth_usd": 1000}}
204
+
205
+ tool = FetchWalletPortfolio(
206
+ name="fetch_wallet_portfolio",
207
+ description="Test description",
208
+ args_schema=MagicMock(),
209
+ api_key="test_key",
210
+ skill_store=mock_skill_store,
211
+ agent_id="test_agent",
212
+ )
213
+
214
+ result = await tool._arun(address="0xAddress")
215
+
216
+ self.assertEqual(result.address, "0xAddress")
217
+ self.assertEqual(result.total_net_worth, 1000)
218
+ self.assertEqual(len(result.tokens), 1)
219
+ self.assertEqual(result.tokens[0].symbol, "TEST")
220
+
221
+ async def test_wallet_portfolio_with_solana(self):
222
+ """Test wallet portfolio with Solana support."""
223
+ mock_skill_store = MagicMock()
224
+
225
+ with (
226
+ patch(
227
+ "skills.moralis.moralis_fetch_wallet_portfolio.fetch_wallet_balances"
228
+ ) as mock_evm_balances,
229
+ patch(
230
+ "skills.moralis.moralis_fetch_wallet_portfolio.fetch_net_worth"
231
+ ) as mock_net_worth,
232
+ patch(
233
+ "skills.moralis.moralis_fetch_wallet_portfolio.get_solana_portfolio"
234
+ ) as mock_sol_portfolio,
235
+ patch(
236
+ "skills.moralis.moralis_fetch_wallet_portfolio.get_token_price"
237
+ ) as mock_token_price,
238
+ ):
239
+ # Mock EVM responses
240
+ mock_evm_balances.return_value = {
241
+ "result": [
242
+ {
243
+ "token_address": "0x123",
244
+ "symbol": "ETH",
245
+ "name": "Ethereum",
246
+ "balance": "1000000000000000000",
247
+ "balance_formatted": "1.0",
248
+ "usd_value": 2000,
249
+ }
250
+ ]
251
+ }
252
+ mock_net_worth.return_value = {"result": {"total_networth_usd": 3000}}
253
+
254
+ # Mock Solana responses
255
+ mock_sol_portfolio.return_value = {
256
+ "nativeBalance": {"solana": 2.0, "lamports": 2000000000},
257
+ "tokens": [
258
+ {
259
+ "symbol": "SOL",
260
+ "name": "Solana",
261
+ "mint": "So11111111111111111111111111111111111111112",
262
+ "associatedTokenAddress": "AssocTokenAddress",
263
+ "amount": 2.0,
264
+ "decimals": 9,
265
+ "amountRaw": "2000000000",
266
+ }
267
+ ],
268
+ }
269
+
270
+ mock_token_price.return_value = {"usdPrice": 500}
271
+
272
+ tool = FetchWalletPortfolio(
273
+ name="fetch_wallet_portfolio",
274
+ description="Test description",
275
+ args_schema=MagicMock(),
276
+ api_key="test_key",
277
+ skill_store=mock_skill_store,
278
+ agent_id="test_agent",
279
+ )
280
+
281
+ result = await tool._arun(address="0xAddress", include_solana=True)
282
+
283
+ self.assertEqual(result.address, "0xAddress")
284
+ self.assertEqual(
285
+ result.total_net_worth, 3000
286
+ ) # Using the net worth from mock
287
+ self.assertIn("eth", result.chains)
288
+ self.assertIn("solana", result.chains)
289
+
290
+ # Check that we have both EVM and Solana tokens
291
+ token_symbols = [token.symbol for token in result.tokens]
292
+ self.assertIn("ETH", token_symbols)
293
+ self.assertIn("SOL", token_symbols)
294
+
295
+
296
+ class TestFetchSolanaPortfolio(unittest.IsolatedAsyncioTestCase):
297
+ """Test the FetchSolanaPortfolio skill."""
298
+
299
+ async def test_solana_portfolio_success(self):
300
+ """Test successful Solana portfolio fetch."""
301
+ mock_skill_store = MagicMock()
302
+
303
+ with (
304
+ patch(
305
+ "skills.moralis.moralis_fetch_solana_portfolio.get_solana_portfolio"
306
+ ) as mock_portfolio,
307
+ patch(
308
+ "skills.moralis.moralis_fetch_solana_portfolio.get_solana_nfts"
309
+ ) as mock_nfts,
310
+ patch(
311
+ "skills.moralis.moralis_fetch_solana_portfolio.get_token_price"
312
+ ) as mock_token_price,
313
+ ):
314
+ # Mock successful responses
315
+ mock_portfolio.return_value = {
316
+ "nativeBalance": {"solana": 1.5, "lamports": 1500000000},
317
+ "tokens": [
318
+ {
319
+ "symbol": "TEST",
320
+ "name": "Test Token",
321
+ "mint": "TokenMintAddress",
322
+ "associatedTokenAddress": "AssocTokenAddress",
323
+ "amount": 10,
324
+ "decimals": 9,
325
+ "amountRaw": "10000000000",
326
+ }
327
+ ],
328
+ }
329
+
330
+ mock_nfts.return_value = [
331
+ {
332
+ "mint": "NFTMintAddress",
333
+ "name": "Test NFT",
334
+ "symbol": "TNFT",
335
+ "associatedTokenAddress": "AssocTokenAddress",
336
+ "metadata": {"name": "Test NFT", "image": "image.png"},
337
+ }
338
+ ]
339
+
340
+ mock_token_price.return_value = {"usdPrice": 25}
341
+
342
+ tool = FetchSolanaPortfolio(
343
+ name="fetch_solana_portfolio",
344
+ description="Test description",
345
+ args_schema=MagicMock(),
346
+ api_key="test_key",
347
+ skill_store=mock_skill_store,
348
+ agent_id="test_agent",
349
+ )
350
+
351
+ result = await tool._arun(address="SolanaAddress", include_nfts=True)
352
+
353
+ self.assertEqual(result.address, "SolanaAddress")
354
+ self.assertEqual(result.sol_balance, 1.5)
355
+ self.assertEqual(len(result.tokens), 1)
356
+ self.assertEqual(result.tokens[0].token_info.symbol, "TEST")
357
+ self.assertEqual(len(result.nfts), 1)
358
+ self.assertEqual(result.nfts[0].name, "Test NFT")
359
+ self.assertEqual(result.sol_price_usd, 25)
360
+ self.assertEqual(result.sol_value_usd, 37.5) # 1.5 SOL * $25
361
+
362
+
363
+ class TestFetchChainPortfolio(unittest.IsolatedAsyncioTestCase):
364
+ """Test the FetchChainPortfolio skill."""
365
+
366
+ async def test_chain_portfolio_success(self):
367
+ """Test successful chain portfolio fetch."""
368
+ mock_skill_store = MagicMock()
369
+
370
+ with patch(
371
+ "skills.moralis.moralis_fetch_chain_portfolio.fetch_wallet_balances"
372
+ ) as mock_balances:
373
+ # Mock successful responses
374
+ mock_balances.return_value = {
375
+ "result": [
376
+ {
377
+ "token_address": "0x123",
378
+ "symbol": "ETH",
379
+ "name": "Ethereum",
380
+ "logo": "logo.png",
381
+ "decimals": 18,
382
+ "balance": "1000000000000000000",
383
+ "balance_formatted": "1.0",
384
+ "usd_value": 2000,
385
+ "native_token": True,
386
+ },
387
+ {
388
+ "token_address": "0x456",
389
+ "symbol": "TOKEN",
390
+ "name": "Test Token",
391
+ "logo": "logo2.png",
392
+ "decimals": 18,
393
+ "balance": "2000000000000000000",
394
+ "balance_formatted": "2.0",
395
+ "usd_value": 200,
396
+ "native_token": False,
397
+ },
398
+ ]
399
+ }
400
+
401
+ tool = FetchChainPortfolio(
402
+ name="fetch_chain_portfolio",
403
+ description="Test description",
404
+ args_schema=MagicMock(),
405
+ api_key="test_key",
406
+ skill_store=mock_skill_store,
407
+ agent_id="test_agent",
408
+ )
409
+
410
+ result = await tool._arun(address="0xAddress", chain_id=1)
411
+
412
+ self.assertEqual(result.address, "0xAddress")
413
+ self.assertEqual(result.chain_id, 1)
414
+ self.assertEqual(result.chain_name, "eth")
415
+ self.assertEqual(result.total_usd_value, 2200) # 2000 + 200
416
+ self.assertEqual(len(result.tokens), 1) # Regular tokens, not native
417
+ self.assertIsNotNone(result.native_token)
418
+ self.assertEqual(result.native_token.symbol, "ETH")
419
+ self.assertEqual(result.tokens[0].symbol, "TOKEN")
420
+
421
+
422
+ class TestSkillInitialization(unittest.TestCase):
423
+ """Test skill initialization and configuration."""
424
+
425
+ def setUp(self):
426
+ self.mock_skill_store = MagicMock()
427
+
428
+ def test_get_skills(self):
429
+ """Test getting multiple skills from config."""
430
+ config = {
431
+ "api_key": "test_api_key",
432
+ "states": {
433
+ "fetch_wallet_portfolio": "public",
434
+ "fetch_chain_portfolio": "public",
435
+ "fetch_nft_portfolio": "private",
436
+ "fetch_transaction_history": "private",
437
+ "fetch_solana_portfolio": "public",
438
+ },
439
+ "supported_chains": {"evm": True, "solana": True},
440
+ }
441
+
442
+ # Test with mock implementation
443
+ with patch("skills.moralis.base.WalletBaseTool") as mock_tool:
444
+ mock_tool.return_value = MagicMock()
445
+
446
+ # This is just a test structure - actual implementation would create the skills
447
+ skills = get_skills(
448
+ config,
449
+ is_private=False, # Only get public skills
450
+ skill_store=self.mock_skill_store,
451
+ agent_id="test_agent",
452
+ )
453
+
454
+ # In a real implementation, we'd test that the correct skills were returned
455
+ # For now, we just verify the function exists
456
+ self.assertIsNotNone(skills)
457
+
458
+
459
+ class TestIntegration(unittest.TestCase):
460
+ """Integration tests for wallet skills."""
461
+
462
+ def test_wallet_skill_configuration(self):
463
+ """Test wallet skill configuration in agent config."""
464
+ # Example agent configuration
465
+ agent_config = {
466
+ "id": "crypto-agent",
467
+ "skills": {
468
+ "moralis": {
469
+ "api_key": "test_api_key",
470
+ "states": {
471
+ "fetch_wallet_portfolio": "public",
472
+ "fetch_chain_portfolio": "public",
473
+ "fetch_nft_portfolio": "private",
474
+ "fetch_transaction_history": "private",
475
+ "fetch_solana_portfolio": "public",
476
+ },
477
+ "supported_chains": {"evm": True, "solana": True},
478
+ }
479
+ },
480
+ }
481
+
482
+ # Verify the configuration structure is valid
483
+ moralis_config = agent_config["skills"]["moralis"]
484
+ self.assertIn("api_key", moralis_config)
485
+ self.assertIn("states", moralis_config)
486
+ self.assertIn("supported_chains", moralis_config)
487
+
488
+ # Check that all required skills are configured
489
+ states = moralis_config["states"]
490
+ required_skills = [
491
+ "fetch_wallet_portfolio",
492
+ "fetch_chain_portfolio",
493
+ "fetch_nft_portfolio",
494
+ "fetch_transaction_history",
495
+ "fetch_solana_portfolio",
496
+ ]
497
+
498
+ for skill in required_skills:
499
+ self.assertIn(skill, states)
500
+ self.assertIn(states[skill], ["public", "private", "disabled"])
501
+
502
+ # Check chain configuration
503
+ chains = moralis_config["supported_chains"]
504
+ self.assertIn("evm", chains)
505
+ self.assertIn("solana", chains)
506
+ self.assertTrue(isinstance(chains["evm"], bool))
507
+ self.assertTrue(isinstance(chains["solana"], bool))
508
+
509
+
510
+ if __name__ == "__main__":
511
+ unittest.main()
@@ -0,0 +1,62 @@
1
+ import logging
2
+ from typing import Optional, TypedDict
3
+
4
+ from intentkit.abstracts.skill import SkillStoreABC
5
+ from intentkit.skills.base import SkillConfig, SkillState
6
+ from intentkit.skills.nation.base import NationBaseTool
7
+ from intentkit.skills.nation.nft_check import NftCheck
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ # Cache skills at the system level, because they are stateless
12
+ _cache: dict[str, NationBaseTool] = {}
13
+
14
+
15
+ class SkillStates(TypedDict):
16
+ nft_check: SkillState
17
+
18
+
19
+ class Config(SkillConfig):
20
+ """Configuration for nation skills."""
21
+
22
+ states: SkillStates
23
+
24
+
25
+ async def get_skills(
26
+ config: "Config",
27
+ is_private: bool,
28
+ store: SkillStoreABC,
29
+ **_,
30
+ ) -> list[NationBaseTool]:
31
+ """Get all nation skills."""
32
+ available_skills = []
33
+
34
+ # Include skills based on their state
35
+ for skill_name, state in config["states"].items():
36
+ if state == "disabled":
37
+ continue
38
+ elif state == "public" or (state == "private" and is_private):
39
+ available_skills.append(skill_name)
40
+
41
+ # Get each skill using the cached getter
42
+ return [
43
+ skill
44
+ for name in available_skills
45
+ if (skill := get_nation_skill(name, store)) is not None
46
+ ]
47
+
48
+
49
+ def get_nation_skill(
50
+ name: str,
51
+ store: SkillStoreABC,
52
+ ) -> Optional[NationBaseTool]:
53
+ """Get a nation skill by name."""
54
+ if name == "nft_check":
55
+ if name not in _cache:
56
+ _cache[name] = NftCheck(
57
+ skill_store=store,
58
+ )
59
+ return _cache[name]
60
+ else:
61
+ logger.error(f"Unknown Nation skill: {name}")
62
+ return None
@@ -0,0 +1,31 @@
1
+ from typing import Type
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+ from intentkit.abstracts.skill import SkillStoreABC
6
+ from intentkit.skills.base import IntentKitSkill
7
+
8
+ default_nation_api_url = "http://backend-api"
9
+
10
+
11
+ class NationBaseTool(IntentKitSkill):
12
+ """Base class for GitHub tools."""
13
+
14
+ name: str = Field(description="The name of the tool")
15
+ description: str = Field(description="A description of what the tool does")
16
+ args_schema: Type[BaseModel]
17
+ skill_store: SkillStoreABC = Field(
18
+ description="The skill store for persisting data"
19
+ )
20
+
21
+ def get_api_key(self) -> str:
22
+ return self.skill_store.get_system_config("nation_api_key")
23
+
24
+ def get_base_url(self) -> str:
25
+ if self.skill_store.get_system_config("nation_api_url"):
26
+ return self.skill_store.get_system_config("nation_api_url")
27
+ return default_nation_api_url
28
+
29
+ @property
30
+ def category(self) -> str:
31
+ return "nation"
Binary file