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,284 @@
1
+ """fetching NFT portfolio for a wallet."""
2
+
3
+ import json
4
+ import logging
5
+ from typing import Any, Dict, List, Optional, Type
6
+
7
+ from pydantic import BaseModel, Field
8
+
9
+ from intentkit.skills.moralis.api import fetch_nft_data, get_solana_nfts
10
+ from intentkit.skills.moralis.base import WalletBaseTool
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class FetchNftPortfolioInput(BaseModel):
16
+ """Input for FetchNftPortfolio tool."""
17
+
18
+ address: str = Field(..., description="Wallet address")
19
+ chain_id: Optional[int] = Field(
20
+ None,
21
+ description="Chain ID (if not specified, fetches from all supported chains)",
22
+ )
23
+ include_solana: bool = Field(
24
+ default=False, description="Whether to include Solana NFTs"
25
+ )
26
+ solana_network: str = Field(
27
+ default="mainnet", description="Solana network to use (mainnet or devnet)"
28
+ )
29
+ limit: Optional[int] = Field(100, description="Maximum number of NFTs to return")
30
+ normalize_metadata: bool = Field(
31
+ True, description="Whether to normalize metadata across different standards"
32
+ )
33
+
34
+
35
+ class NftMetadata(BaseModel):
36
+ """Model for NFT metadata."""
37
+
38
+ name: Optional[str] = Field(None, description="NFT name")
39
+ description: Optional[str] = Field(None, description="NFT description")
40
+ image: Optional[str] = Field(None, description="NFT image URL")
41
+ animation_url: Optional[str] = Field(None, description="NFT animation URL")
42
+ attributes: Optional[List[Dict]] = Field(None, description="NFT attributes/traits")
43
+ external_url: Optional[str] = Field(None, description="External URL")
44
+
45
+
46
+ class NftItem(BaseModel):
47
+ """Model for an NFT item."""
48
+
49
+ token_id: str = Field(..., description="NFT token ID")
50
+ token_address: str = Field(..., description="NFT contract address")
51
+ contract_type: Optional[str] = Field(
52
+ None, description="NFT contract type (ERC721, ERC1155, etc.)"
53
+ )
54
+ name: Optional[str] = Field(None, description="NFT name")
55
+ symbol: Optional[str] = Field(None, description="NFT symbol")
56
+ owner_of: str = Field(..., description="Owner address")
57
+ metadata: Optional[NftMetadata] = Field(None, description="NFT metadata")
58
+ floor_price: Optional[float] = Field(None, description="Floor price if available")
59
+ chain: str = Field("eth", description="Blockchain network")
60
+
61
+
62
+ class NftPortfolioOutput(BaseModel):
63
+ """Output for FetchNftPortfolio tool."""
64
+
65
+ address: str = Field(..., description="Wallet address")
66
+ nfts: List[NftItem] = Field(default_factory=list, description="List of NFT items")
67
+ total_count: int = Field(0, description="Total count of NFTs")
68
+ chains: List[str] = Field(
69
+ default_factory=list, description="Chains included in the response"
70
+ )
71
+ cursor: Optional[str] = Field(None, description="Cursor for pagination")
72
+ error: Optional[str] = Field(None, description="Error message if any")
73
+
74
+
75
+ class FetchNftPortfolio(WalletBaseTool):
76
+ """Tool for fetching NFT portfolio for a wallet.
77
+
78
+ This tool retrieves detailed information about NFTs owned by a wallet address,
79
+ including metadata, media URLs, and floor prices when available.
80
+ """
81
+
82
+ name: str = "moralis_fetch_nft_portfolio"
83
+ description: str = (
84
+ "This tool fetches NFT holdings for a wallet address.\n"
85
+ "Provide a wallet address and optionally a chain ID to get detailed information about NFTs.\n"
86
+ "Returns:\n"
87
+ "- NFT collection data\n"
88
+ "- NFT metadata and attributes\n"
89
+ "- Media URLs if available\n"
90
+ "- Floor prices if available\n"
91
+ "Use this tool whenever a user asks about their NFTs or digital collectibles."
92
+ )
93
+ args_schema: Type[BaseModel] = FetchNftPortfolioInput
94
+
95
+ async def _arun(
96
+ self,
97
+ address: str,
98
+ chain_id: Optional[int] = None,
99
+ include_solana: bool = False,
100
+ solana_network: str = "mainnet",
101
+ limit: int = 100,
102
+ normalize_metadata: bool = True,
103
+ **kwargs,
104
+ ) -> NftPortfolioOutput:
105
+ """Fetch NFT portfolio for a wallet.
106
+
107
+ Args:
108
+ address: Wallet address to fetch NFTs for
109
+ chain_id: Chain ID to fetch NFTs for (if None, fetches from all supported chains)
110
+ include_solana: Whether to include Solana NFTs
111
+ solana_network: Solana network to use (mainnet or devnet)
112
+ limit: Maximum number of NFTs to return
113
+ normalize_metadata: Whether to normalize metadata across different standards
114
+
115
+ Returns:
116
+ NftPortfolioOutput containing NFT portfolio data
117
+ """
118
+ try:
119
+ # Initialize result
120
+ result = {"address": address, "nfts": [], "total_count": 0, "chains": []}
121
+
122
+ # Fetch EVM NFTs
123
+ if chain_id is not None:
124
+ # Fetch from specific chain
125
+ await self._fetch_evm_nfts(
126
+ address, chain_id, limit, normalize_metadata, result
127
+ )
128
+ else:
129
+ # Fetch from all supported chains
130
+ from intentkit.skills.moralis.base import CHAIN_MAPPING
131
+
132
+ for chain_id in CHAIN_MAPPING.keys():
133
+ await self._fetch_evm_nfts(
134
+ address,
135
+ chain_id,
136
+ limit // len(CHAIN_MAPPING),
137
+ normalize_metadata,
138
+ result,
139
+ )
140
+
141
+ # Fetch Solana NFTs if requested
142
+ if include_solana:
143
+ await self._fetch_solana_nfts(address, solana_network, limit, result)
144
+
145
+ return NftPortfolioOutput(**result)
146
+
147
+ except Exception as e:
148
+ logger.error(f"Error fetching NFT portfolio: {str(e)}")
149
+ return NftPortfolioOutput(
150
+ address=address, nfts=[], total_count=0, chains=[], error=str(e)
151
+ )
152
+
153
+ async def _fetch_evm_nfts(
154
+ self,
155
+ address: str,
156
+ chain_id: int,
157
+ limit: int,
158
+ normalize_metadata: bool,
159
+ result: Dict[str, Any],
160
+ ) -> None:
161
+ """Fetch NFTs from an EVM chain.
162
+
163
+ Args:
164
+ address: Wallet address
165
+ chain_id: Chain ID
166
+ limit: Maximum number of NFTs to return
167
+ normalize_metadata: Whether to normalize metadata
168
+ result: Result dictionary to update
169
+ """
170
+ params = {"limit": limit, "normalizeMetadata": normalize_metadata}
171
+
172
+ nft_data = await fetch_nft_data(self.api_key, address, chain_id, params)
173
+
174
+ if "error" in nft_data:
175
+ return
176
+
177
+ chain_name = self._get_chain_name(chain_id)
178
+ if chain_name not in result["chains"]:
179
+ result["chains"].append(chain_name)
180
+
181
+ result["total_count"] += nft_data.get("total", 0)
182
+
183
+ if "cursor" in nft_data:
184
+ result["cursor"] = nft_data["cursor"]
185
+
186
+ for nft in nft_data.get("result", []):
187
+ # Extract metadata
188
+ metadata = None
189
+ if "metadata" in nft and nft["metadata"]:
190
+ try:
191
+ if isinstance(nft["metadata"], str):
192
+ metadata_dict = json.loads(nft["metadata"])
193
+ else:
194
+ metadata_dict = nft["metadata"]
195
+
196
+ metadata = NftMetadata(
197
+ name=metadata_dict.get("name"),
198
+ description=metadata_dict.get("description"),
199
+ image=metadata_dict.get("image"),
200
+ animation_url=metadata_dict.get("animation_url"),
201
+ attributes=metadata_dict.get("attributes"),
202
+ external_url=metadata_dict.get("external_url"),
203
+ )
204
+ except Exception as e:
205
+ logger.warning(f"Error parsing NFT metadata: {str(e)}")
206
+ # If metadata parsing fails, continue without it
207
+ pass
208
+
209
+ # Create NFT item
210
+ nft_item = NftItem(
211
+ token_id=nft.get("token_id", ""),
212
+ token_address=nft.get("token_address", ""),
213
+ contract_type=nft.get("contract_type"),
214
+ name=nft.get("name"),
215
+ symbol=nft.get("symbol"),
216
+ owner_of=nft.get("owner_of", address),
217
+ metadata=metadata,
218
+ floor_price=nft.get("floor_price"),
219
+ chain=chain_name,
220
+ )
221
+
222
+ result["nfts"].append(nft_item)
223
+
224
+ async def _fetch_solana_nfts(
225
+ self, address: str, network: str, limit: int, result: Dict[str, Any]
226
+ ) -> None:
227
+ """Fetch NFTs from Solana.
228
+
229
+ Args:
230
+ address: Wallet address
231
+ network: Solana network
232
+ limit: Maximum number of NFTs to return
233
+ result: Result dictionary to update
234
+ """
235
+ chain_name = "solana"
236
+ if chain_name not in result["chains"]:
237
+ result["chains"].append(chain_name)
238
+
239
+ nfts_result = await get_solana_nfts(self.api_key, address, network)
240
+
241
+ if "error" in nfts_result:
242
+ return
243
+
244
+ if not isinstance(nfts_result, list):
245
+ return
246
+
247
+ count = min(limit, len(nfts_result))
248
+ result["total_count"] += count
249
+
250
+ for i, nft in enumerate(nfts_result):
251
+ if i >= limit:
252
+ break
253
+
254
+ # Create NFT item
255
+ metadata = None
256
+ if "metadata" in nft and nft["metadata"]:
257
+ try:
258
+ metadata_dict = nft["metadata"]
259
+ if isinstance(metadata_dict, str):
260
+ metadata_dict = json.loads(metadata_dict)
261
+
262
+ metadata = NftMetadata(
263
+ name=metadata_dict.get("name"),
264
+ description=metadata_dict.get("description"),
265
+ image=metadata_dict.get("image"),
266
+ animation_url=metadata_dict.get("animation_url"),
267
+ attributes=metadata_dict.get("attributes"),
268
+ external_url=metadata_dict.get("external_url"),
269
+ )
270
+ except Exception as e:
271
+ logger.warning(f"Error parsing Solana NFT metadata: {str(e)}")
272
+ pass
273
+
274
+ nft_item = NftItem(
275
+ token_id=nft.get("mint", ""), # Use mint address as token ID
276
+ token_address=nft.get("mint", ""), # Use mint address as token address
277
+ name=nft.get("name"),
278
+ symbol=nft.get("symbol"),
279
+ owner_of=address,
280
+ metadata=metadata,
281
+ chain=chain_name,
282
+ )
283
+
284
+ result["nfts"].append(nft_item)
@@ -0,0 +1,331 @@
1
+ """fetching Solana wallet portfolio."""
2
+
3
+ import logging
4
+ from typing import Dict, List, Optional, Type
5
+
6
+ from pydantic import BaseModel, Field
7
+
8
+ from intentkit.skills.moralis.api import (
9
+ get_solana_balance,
10
+ get_solana_nfts,
11
+ get_solana_portfolio,
12
+ get_solana_spl_tokens,
13
+ get_token_price,
14
+ )
15
+ from intentkit.skills.moralis.base import WalletBaseTool
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class SolanaPortfolioInput(BaseModel):
21
+ """Input for FetchSolanaPortfolio tool."""
22
+
23
+ address: str = Field(..., description="Solana wallet address")
24
+ network: str = Field(
25
+ default="mainnet", description="Solana network to use (mainnet or devnet)"
26
+ )
27
+ include_nfts: bool = Field(
28
+ default=False, description="Whether to include NFTs in the response"
29
+ )
30
+ include_price_data: bool = Field(
31
+ default=True, description="Whether to include price data for tokens"
32
+ )
33
+
34
+
35
+ class SolanaTokenInfo(BaseModel):
36
+ """Model for Solana token information."""
37
+
38
+ symbol: str
39
+ name: str
40
+ decimals: int
41
+ mint: str
42
+ associated_token_address: str
43
+
44
+
45
+ class SolanaTokenBalance(BaseModel):
46
+ """Model for Solana token balance."""
47
+
48
+ token_info: SolanaTokenInfo
49
+ amount: float
50
+ amount_raw: str
51
+ usd_value: Optional[float] = 0.0
52
+
53
+
54
+ class SolanaNftInfo(BaseModel):
55
+ """Model for Solana NFT information."""
56
+
57
+ mint: str
58
+ name: Optional[str] = None
59
+ symbol: Optional[str] = None
60
+ associated_token_address: str
61
+ metadata: Optional[Dict] = None
62
+
63
+
64
+ class SolanaPortfolioOutput(BaseModel):
65
+ """Output for FetchSolanaPortfolio tool."""
66
+
67
+ address: str
68
+ sol_balance: float
69
+ sol_balance_lamports: int
70
+ sol_price_usd: Optional[float] = None
71
+ sol_value_usd: Optional[float] = None
72
+ tokens: List[SolanaTokenBalance] = []
73
+ nfts: List[SolanaNftInfo] = []
74
+ total_value_usd: float = 0.0
75
+ error: Optional[str] = None
76
+
77
+
78
+ class FetchSolanaPortfolio(WalletBaseTool):
79
+ """Tool for fetching Solana wallet portfolio.
80
+
81
+ This tool retrieves detailed information about a Solana wallet's holdings,
82
+ including native SOL, SPL tokens, and optionally NFTs.
83
+ """
84
+
85
+ name: str = "moralis_fetch_solana_portfolio"
86
+ description: str = (
87
+ "Get comprehensive portfolio data for a Solana wallet including:\n"
88
+ "- Native SOL balance\n"
89
+ "- SPL token balances\n"
90
+ "- NFT holdings (optional)\n"
91
+ "- USD values of assets\n"
92
+ "Use this tool whenever the user asks specifically about Solana holdings."
93
+ )
94
+ args_schema: Type[BaseModel] = SolanaPortfolioInput
95
+
96
+ async def _arun(
97
+ self,
98
+ address: str,
99
+ network: str = "mainnet",
100
+ include_nfts: bool = False,
101
+ include_price_data: bool = True,
102
+ **kwargs,
103
+ ) -> SolanaPortfolioOutput:
104
+ """Fetch Solana wallet portfolio data.
105
+
106
+ Args:
107
+ address: Solana wallet address
108
+ network: Solana network to use (mainnet or devnet)
109
+ include_nfts: Whether to include NFTs in the response
110
+ include_price_data: Whether to include price data for tokens
111
+
112
+ Returns:
113
+ SolanaPortfolioOutput containing the Solana wallet's portfolio data
114
+ """
115
+ try:
116
+ # Try to get complete portfolio
117
+ sol_portfolio = await get_solana_portfolio(self.api_key, address, network)
118
+
119
+ if "error" not in sol_portfolio:
120
+ return await self._process_portfolio_data(
121
+ address, network, sol_portfolio, include_nfts, include_price_data
122
+ )
123
+ else:
124
+ # If portfolio endpoint fails, try to fetch data separately
125
+ return await self._fetch_separate_portfolio_data(
126
+ address, network, include_nfts, include_price_data
127
+ )
128
+
129
+ except Exception as e:
130
+ logger.error(f"Error fetching Solana portfolio: {str(e)}")
131
+ return SolanaPortfolioOutput(
132
+ address=address, sol_balance=0, sol_balance_lamports=0, error=str(e)
133
+ )
134
+
135
+ async def _process_portfolio_data(
136
+ self,
137
+ address: str,
138
+ network: str,
139
+ sol_portfolio: Dict,
140
+ include_nfts: bool,
141
+ include_price_data: bool,
142
+ ) -> SolanaPortfolioOutput:
143
+ """Process portfolio data from the API.
144
+
145
+ Args:
146
+ address: Solana wallet address
147
+ network: Solana network
148
+ sol_portfolio: Portfolio data from the API
149
+ include_nfts: Whether to include NFTs
150
+ include_price_data: Whether to include price data
151
+
152
+ Returns:
153
+ SolanaPortfolioOutput with processed data
154
+ """
155
+ result = SolanaPortfolioOutput(
156
+ address=address,
157
+ sol_balance=float(sol_portfolio.get("nativeBalance", {}).get("solana", 0)),
158
+ sol_balance_lamports=int(
159
+ sol_portfolio.get("nativeBalance", {}).get("lamports", 0)
160
+ ),
161
+ )
162
+
163
+ # Process tokens
164
+ tokens = []
165
+ for token in sol_portfolio.get("tokens", []):
166
+ token_info = SolanaTokenInfo(
167
+ symbol=token.get("symbol", ""),
168
+ name=token.get("name", ""),
169
+ decimals=int(token.get("decimals", 0)),
170
+ mint=token.get("mint", ""),
171
+ associated_token_address=token.get("associatedTokenAddress", ""),
172
+ )
173
+
174
+ token_balance = SolanaTokenBalance(
175
+ token_info=token_info,
176
+ amount=float(token.get("amount", 0)),
177
+ amount_raw=token.get("amountRaw", "0"),
178
+ )
179
+
180
+ tokens.append(token_balance)
181
+
182
+ result.tokens = tokens
183
+
184
+ # Fetch NFTs if requested
185
+ if include_nfts:
186
+ nfts_result = await get_solana_nfts(self.api_key, address, network)
187
+
188
+ if "error" not in nfts_result and isinstance(nfts_result, list):
189
+ nfts = []
190
+ for nft in nfts_result:
191
+ nft_info = SolanaNftInfo(
192
+ mint=nft.get("mint", ""),
193
+ name=nft.get("name"),
194
+ symbol=nft.get("symbol"),
195
+ associated_token_address=nft.get("associatedTokenAddress", ""),
196
+ metadata=nft.get("metadata"),
197
+ )
198
+ nfts.append(nft_info)
199
+
200
+ result.nfts = nfts
201
+
202
+ # Fetch price data if requested
203
+ if include_price_data:
204
+ # Fetch SOL price
205
+ sol_price_result = await get_token_price(
206
+ self.api_key,
207
+ "So11111111111111111111111111111111111111112", # SOL mint address
208
+ network,
209
+ )
210
+
211
+ if "error" not in sol_price_result:
212
+ sol_price_usd = float(sol_price_result.get("usdPrice", 0))
213
+ result.sol_price_usd = sol_price_usd
214
+ result.sol_value_usd = sol_price_usd * result.sol_balance
215
+ result.total_value_usd += result.sol_value_usd or 0
216
+
217
+ # Fetch token prices
218
+ for token in result.tokens:
219
+ if token.token_info.mint:
220
+ price_result = await get_token_price(
221
+ self.api_key, token.token_info.mint, network
222
+ )
223
+
224
+ if "error" not in price_result:
225
+ token_price_usd = float(price_result.get("usdPrice", 0))
226
+ token.usd_value = token_price_usd * token.amount
227
+ result.total_value_usd += token.usd_value
228
+
229
+ return result
230
+
231
+ async def _fetch_separate_portfolio_data(
232
+ self, address: str, network: str, include_nfts: bool, include_price_data: bool
233
+ ) -> SolanaPortfolioOutput:
234
+ """Fetch portfolio data using separate API calls.
235
+
236
+ Args:
237
+ address: Solana wallet address
238
+ network: Solana network
239
+ include_nfts: Whether to include NFTs
240
+ include_price_data: Whether to include price data
241
+
242
+ Returns:
243
+ SolanaPortfolioOutput with processed data
244
+ """
245
+ # Get SOL balance
246
+ balance_result = await get_solana_balance(self.api_key, address, network)
247
+
248
+ if "error" in balance_result:
249
+ return SolanaPortfolioOutput(
250
+ address=address,
251
+ sol_balance=0,
252
+ sol_balance_lamports=0,
253
+ error=balance_result["error"],
254
+ )
255
+
256
+ result = SolanaPortfolioOutput(
257
+ address=address,
258
+ sol_balance=float(balance_result.get("solana", 0)),
259
+ sol_balance_lamports=int(balance_result.get("lamports", 0)),
260
+ )
261
+
262
+ # Get SPL tokens
263
+ tokens_result = await get_solana_spl_tokens(self.api_key, address, network)
264
+
265
+ if "error" not in tokens_result and isinstance(tokens_result, list):
266
+ tokens = []
267
+ for token in tokens_result:
268
+ token_info = SolanaTokenInfo(
269
+ symbol=token.get("symbol", ""),
270
+ name=token.get("name", ""),
271
+ decimals=int(token.get("decimals", 0)),
272
+ mint=token.get("mint", ""),
273
+ associated_token_address=token.get("associatedTokenAddress", ""),
274
+ )
275
+
276
+ token_balance = SolanaTokenBalance(
277
+ token_info=token_info,
278
+ amount=float(token.get("amount", 0)),
279
+ amount_raw=token.get("amountRaw", "0"),
280
+ )
281
+
282
+ tokens.append(token_balance)
283
+
284
+ result.tokens = tokens
285
+
286
+ # Fetch NFTs if requested
287
+ if include_nfts:
288
+ nfts_result = await get_solana_nfts(self.api_key, address, network)
289
+
290
+ if "error" not in nfts_result and isinstance(nfts_result, list):
291
+ nfts = []
292
+ for nft in nfts_result:
293
+ nft_info = SolanaNftInfo(
294
+ mint=nft.get("mint", ""),
295
+ name=nft.get("name"),
296
+ symbol=nft.get("symbol"),
297
+ associated_token_address=nft.get("associatedTokenAddress", ""),
298
+ metadata=nft.get("metadata"),
299
+ )
300
+ nfts.append(nft_info)
301
+
302
+ result.nfts = nfts
303
+
304
+ # Fetch price data if requested
305
+ if include_price_data:
306
+ # Fetch SOL price
307
+ sol_price_result = await get_token_price(
308
+ self.api_key,
309
+ "So11111111111111111111111111111111111111112", # SOL mint address
310
+ network,
311
+ )
312
+
313
+ if "error" not in sol_price_result:
314
+ sol_price_usd = float(sol_price_result.get("usdPrice", 0))
315
+ result.sol_price_usd = sol_price_usd
316
+ result.sol_value_usd = sol_price_usd * result.sol_balance
317
+ result.total_value_usd += result.sol_value_usd or 0
318
+
319
+ # Fetch token prices
320
+ for token in result.tokens:
321
+ if token.token_info.mint:
322
+ price_result = await get_token_price(
323
+ self.api_key, token.token_info.mint, network
324
+ )
325
+
326
+ if "error" not in price_result:
327
+ token_price_usd = float(price_result.get("usdPrice", 0))
328
+ token.usd_value = token_price_usd * token.amount
329
+ result.total_value_usd += token.usd_value
330
+
331
+ return result