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,656 @@
1
+ """
2
+ LiFi Skills Utilities
3
+
4
+ Common utilities and helper functions for LiFi token transfer skills.
5
+ """
6
+
7
+ from typing import Any, Dict, List, Optional, Tuple
8
+
9
+ import httpx
10
+ from web3 import Web3
11
+
12
+ # Constants
13
+ LIFI_API_URL = "https://li.quest/v1"
14
+ DUMMY_ADDRESS = "0x552008c0f6870c2f77e5cC1d2eb9bdff03e30Ea0" # For quotes
15
+
16
+ # Chain ID to name mapping (includes mainnet and testnet)
17
+ CHAIN_NAMES = {
18
+ # Mainnet chains
19
+ 1: "Ethereum",
20
+ 10: "Optimism",
21
+ 56: "BNB Chain",
22
+ 100: "Gnosis Chain",
23
+ 137: "Polygon",
24
+ 250: "Fantom",
25
+ 8453: "Base",
26
+ 42161: "Arbitrum One",
27
+ 43114: "Avalanche",
28
+ 59144: "Linea",
29
+ 324: "zkSync Era",
30
+ 1101: "Polygon zkEVM",
31
+ 534352: "Scroll",
32
+ # Testnet chains
33
+ 11155111: "Ethereum Sepolia",
34
+ 84532: "Base Sepolia",
35
+ 421614: "Arbitrum Sepolia",
36
+ 11155420: "Optimism Sepolia",
37
+ 80001: "Polygon Mumbai",
38
+ 5: "Ethereum Goerli", # Legacy testnet
39
+ 420: "Optimism Goerli", # Legacy testnet
40
+ }
41
+
42
+ # Standard ERC20 ABI for allowance and approve functions
43
+ ERC20_ABI = [
44
+ {
45
+ "constant": True,
46
+ "inputs": [
47
+ {"name": "_owner", "type": "address"},
48
+ {"name": "_spender", "type": "address"},
49
+ ],
50
+ "name": "allowance",
51
+ "outputs": [{"name": "", "type": "uint256"}],
52
+ "type": "function",
53
+ },
54
+ {
55
+ "constant": False,
56
+ "inputs": [
57
+ {"name": "_spender", "type": "address"},
58
+ {"name": "_value", "type": "uint256"},
59
+ ],
60
+ "name": "approve",
61
+ "outputs": [{"name": "", "type": "bool"}],
62
+ "type": "function",
63
+ },
64
+ ]
65
+
66
+
67
+ def validate_inputs(
68
+ from_chain: str,
69
+ to_chain: str,
70
+ from_token: str,
71
+ to_token: str,
72
+ from_amount: str,
73
+ slippage: float,
74
+ allowed_chains: Optional[List[str]] = None,
75
+ ) -> Optional[str]:
76
+ """
77
+ Validate all input parameters for LiFi operations.
78
+
79
+ Returns:
80
+ None if valid, error message string if invalid
81
+ """
82
+ # Validate slippage
83
+ if slippage < 0.001 or slippage > 0.5:
84
+ return "Invalid slippage: must be between 0.001 (0.1%) and 0.5 (50%)"
85
+
86
+ # Validate chain identifiers can be converted to chain IDs
87
+ try:
88
+ convert_chain_to_id(from_chain)
89
+ except ValueError as e:
90
+ return f"Invalid source chain: {str(e)}"
91
+
92
+ try:
93
+ convert_chain_to_id(to_chain)
94
+ except ValueError as e:
95
+ return f"Invalid destination chain: {str(e)}"
96
+
97
+ # Validate chains if restricted (use original chain names for restriction check)
98
+ if allowed_chains:
99
+ if from_chain not in allowed_chains:
100
+ return f"Source chain '{from_chain}' is not allowed. Allowed chains: {', '.join(allowed_chains)}"
101
+ if to_chain not in allowed_chains:
102
+ return f"Destination chain '{to_chain}' is not allowed. Allowed chains: {', '.join(allowed_chains)}"
103
+
104
+ # Validate amount is numeric and positive
105
+ try:
106
+ amount_float = float(from_amount)
107
+ if amount_float <= 0:
108
+ return "Amount must be greater than 0"
109
+ except ValueError:
110
+ return f"Invalid amount format: {from_amount}. Must be a numeric value."
111
+
112
+ return None
113
+
114
+
115
+ def format_amount(amount: str, decimals: int) -> str:
116
+ """
117
+ Format amount from wei/smallest unit to human readable.
118
+
119
+ Args:
120
+ amount: Amount in smallest unit (wei/satoshi/etc)
121
+ decimals: Number of decimal places for the token
122
+
123
+ Returns:
124
+ Formatted amount string
125
+ """
126
+ try:
127
+ amount_int = int(amount)
128
+ amount_float = amount_int / (10**decimals)
129
+
130
+ # Format with appropriate precision
131
+ if amount_float >= 1000:
132
+ return f"{amount_float:,.2f}"
133
+ elif amount_float >= 1:
134
+ return f"{amount_float:.4f}"
135
+ elif amount_float >= 0.01:
136
+ return f"{amount_float:.6f}"
137
+ else:
138
+ return f"{amount_float:.8f}"
139
+ except (ValueError, TypeError):
140
+ return str(amount)
141
+
142
+
143
+ def get_chain_name(chain_id: int) -> str:
144
+ """
145
+ Get human readable chain name from chain ID.
146
+
147
+ Args:
148
+ chain_id: Blockchain chain ID
149
+
150
+ Returns:
151
+ Human readable chain name
152
+ """
153
+ return CHAIN_NAMES.get(chain_id, f"Chain {chain_id}")
154
+
155
+
156
+ def format_duration(duration: int) -> str:
157
+ """
158
+ Format duration in seconds to human readable format.
159
+
160
+ Args:
161
+ duration: Duration in seconds
162
+
163
+ Returns:
164
+ Formatted duration string
165
+ """
166
+ if duration < 60:
167
+ return f"{duration} seconds"
168
+ elif duration < 3600:
169
+ return f"{duration // 60} minutes {duration % 60} seconds"
170
+ else:
171
+ hours = duration // 3600
172
+ minutes = (duration % 3600) // 60
173
+ return f"{hours} hours {minutes} minutes"
174
+
175
+
176
+ def handle_api_response(
177
+ response: httpx.Response,
178
+ from_token: str,
179
+ from_chain: str,
180
+ to_token: str,
181
+ to_chain: str,
182
+ ) -> Tuple[Optional[Dict], Optional[str]]:
183
+ """
184
+ Handle LiFi API response and return data or error message.
185
+
186
+ Args:
187
+ response: HTTP response from LiFi API
188
+ from_token, from_chain, to_token, to_chain: Transfer parameters for error messages
189
+
190
+ Returns:
191
+ Tuple of (data, error_message). One will be None.
192
+ """
193
+ if response.status_code == 400:
194
+ try:
195
+ error_data = response.json()
196
+ error_message = error_data.get("message", response.text)
197
+ return None, f"Invalid request: {error_message}"
198
+ except (ValueError, TypeError, AttributeError):
199
+ return None, f"Invalid request: {response.text}"
200
+ elif response.status_code == 404:
201
+ return (
202
+ None,
203
+ f"No route found for transfer from {from_token} on {from_chain} to {to_token} on {to_chain}. Try different tokens or chains.",
204
+ )
205
+ elif response.status_code != 200:
206
+ return None, f"LiFi API error ({response.status_code}): {response.text}"
207
+
208
+ try:
209
+ data = response.json()
210
+ if not isinstance(data, dict):
211
+ return None, "Invalid response format from LiFi API."
212
+ return data, None
213
+ except Exception:
214
+ return None, "Invalid response from LiFi API. Please try again."
215
+
216
+
217
+ def convert_chain_to_id(chain: str) -> int:
218
+ """
219
+ Convert chain identifier to numeric chain ID.
220
+
221
+ Args:
222
+ chain: Chain identifier (can be name, key, or numeric ID as string)
223
+
224
+ Returns:
225
+ Numeric chain ID
226
+
227
+ Raises:
228
+ ValueError: If chain identifier is not recognized
229
+ """
230
+ # If it's already a number, return it
231
+ if chain.isdigit():
232
+ return int(chain)
233
+
234
+ # Chain name/key to ID mapping
235
+ chain_mapping = {
236
+ # Mainnet chains
237
+ "ethereum": 1,
238
+ "eth": 1,
239
+ "1": 1,
240
+ "optimism": 10,
241
+ "opt": 10,
242
+ "10": 10,
243
+ "binance": 56,
244
+ "bsc": 56,
245
+ "bnb": 56,
246
+ "56": 56,
247
+ "gnosis": 100,
248
+ "100": 100,
249
+ "polygon": 137,
250
+ "pol": 137,
251
+ "matic": 137,
252
+ "137": 137,
253
+ "fantom": 250,
254
+ "ftm": 250,
255
+ "250": 250,
256
+ "base": 8453,
257
+ "base-mainnet": 8453,
258
+ "8453": 8453,
259
+ "arbitrum": 42161,
260
+ "arb": 42161,
261
+ "42161": 42161,
262
+ "avalanche": 43114,
263
+ "avax": 43114,
264
+ "43114": 43114,
265
+ "linea": 59144,
266
+ "59144": 59144,
267
+ "zksync": 324,
268
+ "324": 324,
269
+ "polygon-zkevm": 1101,
270
+ "1101": 1101,
271
+ "scroll": 534352,
272
+ "534352": 534352,
273
+ # Testnet chains
274
+ "ethereum-sepolia": 11155111,
275
+ "sepolia": 11155111,
276
+ "11155111": 11155111,
277
+ "base-sepolia": 84532,
278
+ "84532": 84532,
279
+ "arbitrum-sepolia": 421614,
280
+ "421614": 421614,
281
+ "optimism-sepolia": 11155420,
282
+ "11155420": 11155420,
283
+ "polygon-mumbai": 80001,
284
+ "mumbai": 80001,
285
+ "80001": 80001,
286
+ }
287
+
288
+ chain_lower = chain.lower()
289
+ if chain_lower in chain_mapping:
290
+ return chain_mapping[chain_lower]
291
+
292
+ raise ValueError(f"Unsupported chain identifier: {chain}")
293
+
294
+
295
+ def convert_amount_to_wei(amount: str, token_symbol: str = "ETH") -> str:
296
+ """
297
+ Convert human-readable amount to wei format for LiFi API.
298
+
299
+ Args:
300
+ amount: Amount in human readable format (e.g., "0.0015")
301
+ token_symbol: Token symbol to determine decimals
302
+
303
+ Returns:
304
+ Amount in wei format as string
305
+ """
306
+ # Default decimals for common tokens
307
+ token_decimals = {
308
+ "ETH": 18,
309
+ "USDC": 6,
310
+ "USDT": 6,
311
+ "DAI": 18,
312
+ "WETH": 18,
313
+ "MATIC": 18,
314
+ "BNB": 18,
315
+ "AVAX": 18,
316
+ }
317
+
318
+ decimals = token_decimals.get(token_symbol.upper(), 18)
319
+
320
+ try:
321
+ # Convert string to float, then to wei
322
+ amount_float = float(amount)
323
+ amount_wei = int(amount_float * (10**decimals))
324
+ return str(amount_wei)
325
+ except (ValueError, TypeError):
326
+ # If conversion fails, return original amount
327
+ return amount
328
+
329
+
330
+ def build_quote_params(
331
+ from_chain: str,
332
+ to_chain: str,
333
+ from_token: str,
334
+ to_token: str,
335
+ from_amount: str,
336
+ slippage: float,
337
+ from_address: Optional[str] = None,
338
+ ) -> Dict[str, Any]:
339
+ """
340
+ Build parameters for LiFi quote API request.
341
+
342
+ Args:
343
+ from_chain, to_chain, from_token, to_token, from_amount: Transfer parameters
344
+ slippage: Slippage tolerance
345
+ from_address: Wallet address (uses dummy if None)
346
+
347
+ Returns:
348
+ Dictionary of API parameters
349
+
350
+ Raises:
351
+ ValueError: If chain identifiers are not recognized
352
+ """
353
+ # Convert amount to wei format for API
354
+ wei_amount = convert_amount_to_wei(from_amount, from_token)
355
+
356
+ return {
357
+ "fromChain": convert_chain_to_id(from_chain),
358
+ "toChain": convert_chain_to_id(to_chain),
359
+ "fromToken": from_token,
360
+ "toToken": to_token,
361
+ "fromAmount": wei_amount,
362
+ "fromAddress": from_address or DUMMY_ADDRESS,
363
+ "slippage": slippage,
364
+ }
365
+
366
+
367
+ def is_native_token(token_address: str) -> bool:
368
+ """
369
+ Check if token address represents a native token (ETH, MATIC, etc).
370
+
371
+ Args:
372
+ token_address: Token contract address
373
+
374
+ Returns:
375
+ True if native token, False if ERC20
376
+ """
377
+ return (
378
+ token_address == "0x0000000000000000000000000000000000000000"
379
+ or token_address == ""
380
+ or token_address.lower() == "0x0"
381
+ )
382
+
383
+
384
+ def prepare_transaction_params(transaction_request: Dict[str, Any]) -> Dict[str, Any]:
385
+ """
386
+ Prepare transaction parameters for CDP wallet provider.
387
+
388
+ Args:
389
+ transaction_request: Transaction request from LiFi API
390
+
391
+ Returns:
392
+ Formatted transaction parameters
393
+
394
+ Raises:
395
+ Exception: If required parameters are missing
396
+ """
397
+ to_address = transaction_request.get("to")
398
+ value = transaction_request.get("value", "0")
399
+ data = transaction_request.get("data", "0x")
400
+
401
+ if not to_address:
402
+ raise Exception("No destination address in transaction request")
403
+
404
+ # Convert value to integer if it's a string
405
+ if isinstance(value, str):
406
+ value = int(value, 16) if value.startswith("0x") else int(value)
407
+
408
+ return {
409
+ "to": Web3.to_checksum_address(to_address),
410
+ "value": value,
411
+ "data": data,
412
+ }
413
+
414
+
415
+ def format_quote_basic_info(data: Dict[str, Any]) -> Dict[str, Any]:
416
+ """
417
+ Extract and format basic quote information.
418
+
419
+ Args:
420
+ data: Quote response from LiFi API
421
+
422
+ Returns:
423
+ Dictionary with formatted basic info
424
+ """
425
+ action = data.get("action", {})
426
+ estimate = data.get("estimate", {})
427
+
428
+ from_token_info = action.get("fromToken", {})
429
+ to_token_info = action.get("toToken", {})
430
+
431
+ from_amount = action.get("fromAmount", "0")
432
+ to_amount = estimate.get("toAmount", "0")
433
+ to_amount_min = estimate.get("toAmountMin", "0")
434
+
435
+ from_token_decimals = from_token_info.get("decimals", 18)
436
+ to_token_decimals = to_token_info.get("decimals", 18)
437
+
438
+ return {
439
+ "from_token": from_token_info.get("symbol", "Unknown"),
440
+ "to_token": to_token_info.get("symbol", "Unknown"),
441
+ "from_chain": get_chain_name(action.get("fromChainId")),
442
+ "to_chain": get_chain_name(action.get("toChainId")),
443
+ "from_amount": format_amount(from_amount, from_token_decimals),
444
+ "to_amount": format_amount(to_amount, to_token_decimals),
445
+ "to_amount_min": format_amount(to_amount_min, to_token_decimals),
446
+ "tool": data.get("tool", "Unknown"),
447
+ "from_amount_usd": estimate.get("fromAmountUSD"),
448
+ "to_amount_usd": estimate.get("toAmountUSD"),
449
+ "execution_duration": estimate.get("executionDuration"),
450
+ }
451
+
452
+
453
+ def format_fees_and_gas(data: Dict[str, Any]) -> Tuple[str, str]:
454
+ """
455
+ Format fee and gas cost information from quote data.
456
+
457
+ Args:
458
+ data: Quote response from LiFi API
459
+
460
+ Returns:
461
+ Tuple of (fees_text, gas_text)
462
+ """
463
+ estimate = data.get("estimate", {})
464
+
465
+ # Extract gas and fee costs
466
+ gas_costs = estimate.get("gasCosts", [])
467
+ fee_costs = []
468
+
469
+ # Collect fee information from included steps
470
+ for step in data.get("includedSteps", []):
471
+ step_fees = step.get("estimate", {}).get("feeCosts", [])
472
+ if step_fees:
473
+ fee_costs.extend(step_fees)
474
+
475
+ # Format fees
476
+ fees_text = ""
477
+ if fee_costs:
478
+ fees_text = "**Fees:**\n"
479
+ total_fee_usd = 0
480
+ for fee in fee_costs:
481
+ fee_name = fee.get("name", "Unknown fee")
482
+ fee_amount = fee.get("amount", "0")
483
+ fee_token = fee.get("token", {}).get("symbol", "")
484
+ fee_decimals = fee.get("token", {}).get("decimals", 18)
485
+ fee_percentage = fee.get("percentage", "0")
486
+ fee_usd = fee.get("amountUSD", "0")
487
+
488
+ fee_amount_formatted = format_amount(fee_amount, fee_decimals)
489
+ percentage_str = (
490
+ f" ({float(fee_percentage) * 100:.3f}%)"
491
+ if fee_percentage != "0"
492
+ else ""
493
+ )
494
+ fees_text += (
495
+ f"- {fee_name}: {fee_amount_formatted} {fee_token}{percentage_str}"
496
+ )
497
+
498
+ if fee_usd and float(fee_usd) > 0:
499
+ fees_text += f" (${fee_usd})"
500
+ total_fee_usd += float(fee_usd)
501
+
502
+ fees_text += "\n"
503
+
504
+ if total_fee_usd > 0:
505
+ fees_text += f"- **Total Fees:** ~${total_fee_usd:.4f}\n"
506
+
507
+ # Format gas costs
508
+ gas_text = ""
509
+ if gas_costs:
510
+ gas_text = "**Gas Cost:**\n"
511
+ total_gas_usd = 0
512
+ for gas in gas_costs:
513
+ gas_amount = gas.get("amount", "0")
514
+ gas_token = gas.get("token", {}).get("symbol", "ETH")
515
+ gas_decimals = gas.get("token", {}).get("decimals", 18)
516
+ gas_usd = gas.get("amountUSD", "0")
517
+ gas_type = gas.get("type", "SEND")
518
+
519
+ gas_amount_formatted = format_amount(gas_amount, gas_decimals)
520
+ gas_text += f"- {gas_type}: {gas_amount_formatted} {gas_token}"
521
+
522
+ if gas_usd and float(gas_usd) > 0:
523
+ gas_text += f" (${gas_usd})"
524
+ total_gas_usd += float(gas_usd)
525
+
526
+ gas_text += "\n"
527
+
528
+ if total_gas_usd > 0:
529
+ gas_text += f"- **Total Gas:** ~${total_gas_usd:.4f}\n"
530
+
531
+ return fees_text, gas_text
532
+
533
+
534
+ def format_route_info(data: Dict[str, Any]) -> str:
535
+ """
536
+ Format routing information from quote data.
537
+
538
+ Args:
539
+ data: Quote response from LiFi API
540
+
541
+ Returns:
542
+ Formatted route information text
543
+ """
544
+ included_steps = data.get("includedSteps", [])
545
+ if len(included_steps) <= 1:
546
+ return ""
547
+
548
+ route_text = "**Route:**\n"
549
+ for i, step in enumerate(included_steps, 1):
550
+ step_tool = step.get("tool", "Unknown")
551
+ step_type = step.get("type", "unknown")
552
+ route_text += f"{i}. {step_tool} ({step_type})\n"
553
+
554
+ return route_text
555
+
556
+
557
+ def create_erc20_approve_data(spender_address: str, amount: str) -> str:
558
+ """
559
+ Create encoded data for ERC20 approve function call.
560
+
561
+ Args:
562
+ spender_address: Address to approve
563
+ amount: Amount to approve
564
+
565
+ Returns:
566
+ Encoded function call data
567
+ """
568
+ contract = Web3().eth.contract(
569
+ address=Web3.to_checksum_address("0x0000000000000000000000000000000000000000"),
570
+ abi=ERC20_ABI,
571
+ )
572
+ return contract.encode_abi("approve", [spender_address, int(amount)])
573
+
574
+
575
+ def get_api_error_message(response: httpx.Response) -> str:
576
+ """
577
+ Extract error message from API response.
578
+
579
+ Args:
580
+ response: HTTP response
581
+
582
+ Returns:
583
+ Formatted error message
584
+ """
585
+ try:
586
+ error_data = response.json()
587
+ return error_data.get("message", response.text)
588
+ except (ValueError, TypeError, AttributeError):
589
+ return response.text
590
+
591
+
592
+ def get_explorer_url(chain_id: int, tx_hash: str) -> str:
593
+ """
594
+ Generate blockchain explorer URL for a transaction.
595
+
596
+ Args:
597
+ chain_id: Blockchain chain ID
598
+ tx_hash: Transaction hash
599
+
600
+ Returns:
601
+ Explorer URL for the transaction
602
+ """
603
+ # Explorer URLs for different chains
604
+ explorers = {
605
+ 1: "https://etherscan.io/tx/", # Ethereum
606
+ 10: "https://optimistic.etherscan.io/tx/", # Optimism
607
+ 56: "https://bscscan.com/tx/", # BSC
608
+ 100: "https://gnosisscan.io/tx/", # Gnosis
609
+ 137: "https://polygonscan.com/tx/", # Polygon
610
+ 250: "https://ftmscan.com/tx/", # Fantom
611
+ 8453: "https://basescan.org/tx/", # Base
612
+ 42161: "https://arbiscan.io/tx/", # Arbitrum
613
+ 43114: "https://snowtrace.io/tx/", # Avalanche
614
+ 59144: "https://lineascan.build/tx/", # Linea
615
+ 324: "https://explorer.zksync.io/tx/", # zkSync Era
616
+ 1101: "https://zkevm.polygonscan.com/tx/", # Polygon zkEVM
617
+ 534352: "https://scrollscan.com/tx/", # Scroll
618
+ # Testnet explorers
619
+ 11155111: "https://sepolia.etherscan.io/tx/", # Ethereum Sepolia
620
+ 84532: "https://sepolia.basescan.org/tx/", # Base Sepolia
621
+ 421614: "https://sepolia.arbiscan.io/tx/", # Arbitrum Sepolia
622
+ 11155420: "https://sepolia-optimism.etherscan.io/tx/", # Optimism Sepolia
623
+ 80001: "https://mumbai.polygonscan.com/tx/", # Polygon Mumbai
624
+ }
625
+
626
+ base_url = explorers.get(chain_id, "https://etherscan.io/tx/")
627
+ return f"{base_url}{tx_hash}"
628
+
629
+
630
+ def format_transaction_result(
631
+ tx_hash: str, chain_id: int, token_info: dict = None
632
+ ) -> str:
633
+ """
634
+ Format transaction result with explorer link.
635
+
636
+ Args:
637
+ tx_hash: Transaction hash
638
+ chain_id: Chain ID where transaction was executed
639
+ token_info: Optional token information for context
640
+
641
+ Returns:
642
+ Formatted transaction result message
643
+ """
644
+ explorer_url = get_explorer_url(chain_id, tx_hash)
645
+ chain_name = get_chain_name(chain_id)
646
+
647
+ result = "Transaction successful!\n"
648
+ result += f"Transaction Hash: {tx_hash}\n"
649
+ result += f"Network: {chain_name}\n"
650
+ result += f"Explorer: {explorer_url}\n"
651
+
652
+ if token_info:
653
+ result += f"Token: {token_info.get('symbol', 'Unknown')}\n"
654
+ result += f"Amount: {token_info.get('amount', 'Unknown')}\n"
655
+
656
+ return result