@hyperweb/telescope 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (382) hide show
  1. package/README.md +1529 -0
  2. package/main/build.js +183 -0
  3. package/main/builder.js +229 -0
  4. package/main/bundle.js +162 -0
  5. package/main/bundler.js +100 -0
  6. package/main/cli.js +71 -0
  7. package/main/cmds.js +28 -0
  8. package/main/commands/download.js +122 -0
  9. package/main/commands/generate.js +151 -0
  10. package/main/commands/install.js +143 -0
  11. package/main/commands/transpile.js +197 -0
  12. package/main/contracts/generate.js +31 -0
  13. package/main/contracts/install.js +107 -0
  14. package/main/contracts/message-composer.js +31 -0
  15. package/main/contracts/react-query.js +31 -0
  16. package/main/contracts/recoil.js +31 -0
  17. package/main/file.js +20 -0
  18. package/main/generators/create-aggregated-lcd-client.js +87 -0
  19. package/main/generators/create-all-stargate-clients.js +96 -0
  20. package/main/generators/create-amino-converters.js +43 -0
  21. package/main/generators/create-bundle.js +83 -0
  22. package/main/generators/create-cosmwasm-bundle.js +15 -0
  23. package/main/generators/create-custom-stargate-clients.js +100 -0
  24. package/main/generators/create-helpers.js +119 -0
  25. package/main/generators/create-index.js +75 -0
  26. package/main/generators/create-lcd-client-all.js +116 -0
  27. package/main/generators/create-lcd-client-scoped.js +89 -0
  28. package/main/generators/create-lcd-clients.js +78 -0
  29. package/main/generators/create-mcp-server.js +1853 -0
  30. package/main/generators/create-mobx-bundle.js +52 -0
  31. package/main/generators/create-msg-funcs.js +132 -0
  32. package/main/generators/create-pinia-store-bundle.js +50 -0
  33. package/main/generators/create-pinia-store.js +90 -0
  34. package/main/generators/create-query-funcs.js +133 -0
  35. package/main/generators/create-react-query-bundle.js +103 -0
  36. package/main/generators/create-registries.js +49 -0
  37. package/main/generators/create-root-readme.js +259 -0
  38. package/main/generators/create-rpc-msg-client-all.js +135 -0
  39. package/main/generators/create-rpc-msg-client-scoped.js +114 -0
  40. package/main/generators/create-rpc-msg-clients.js +116 -0
  41. package/main/generators/create-rpc-ops-bundle.js +119 -0
  42. package/main/generators/create-rpc-query-client-all.js +137 -0
  43. package/main/generators/create-rpc-query-client-scoped.js +110 -0
  44. package/main/generators/create-rpc-query-clients.js +198 -0
  45. package/main/generators/create-sdk-module-stargate-clients.js +95 -0
  46. package/main/generators/create-stargate-clients.js +96 -0
  47. package/main/generators/create-types.js +164 -0
  48. package/main/generators/customize-utils.js +50 -0
  49. package/main/helpers/__test__/internalTimestamp.js +49 -0
  50. package/main/helpers/__test__/internalTimestampBigint.js +45 -0
  51. package/main/helpers/binary-coder.js +535 -0
  52. package/main/helpers/decimals.js +111 -0
  53. package/main/helpers/external-comet.js +52 -0
  54. package/main/helpers/external-icjs.js +36 -0
  55. package/main/helpers/external.js +31 -0
  56. package/main/helpers/grpc-gateway.js +348 -0
  57. package/main/helpers/grpc-web.js +14 -0
  58. package/main/helpers/helper-func-types-interface.js +106 -0
  59. package/main/helpers/helper-func-types.js +93 -0
  60. package/main/helpers/index.js +38 -0
  61. package/main/helpers/internal-for-bigint.js +259 -0
  62. package/main/helpers/internal.js +240 -0
  63. package/main/helpers/json-safe.js +12 -0
  64. package/main/helpers/mobx.js +80 -0
  65. package/main/helpers/pinia-endpoint.js +20 -0
  66. package/main/helpers/react-query-hooks-icjs.js +223 -0
  67. package/main/helpers/react-query-hooks.js +258 -0
  68. package/main/helpers/react-query.js +93 -0
  69. package/main/helpers/registry-helper.js +229 -0
  70. package/main/helpers/types-helper.js +165 -0
  71. package/main/helpers/utf8-helper.js +146 -0
  72. package/main/helpers/varint.js +486 -0
  73. package/main/helpers/vue-query-hooks.js +226 -0
  74. package/main/imports.js +416 -0
  75. package/main/index.js +24 -0
  76. package/main/parse.js +194 -0
  77. package/main/prompt.js +64 -0
  78. package/main/protod/bufbuild.js +87 -0
  79. package/main/protod/config.js +30 -0
  80. package/main/protod/git-repo.js +58 -0
  81. package/main/protod/index.js +17 -0
  82. package/main/protod/recursive.js +134 -0
  83. package/main/protod/types.js +2 -0
  84. package/main/protod/utils.js +91 -0
  85. package/main/telescope.js +10 -0
  86. package/main/types.js +2 -0
  87. package/main/utils/common-create-bundle.js +29 -0
  88. package/main/utils/contracts.js +39 -0
  89. package/main/utils/files.js +138 -0
  90. package/main/utils/index.js +163 -0
  91. package/main/utils/unused.js +73 -0
  92. package/module/build.js +176 -0
  93. package/module/builder.js +222 -0
  94. package/module/bundle.js +128 -0
  95. package/module/bundler.js +96 -0
  96. package/module/cli.js +44 -0
  97. package/module/cmds.js +22 -0
  98. package/module/commands/download.js +94 -0
  99. package/module/commands/generate.js +123 -0
  100. package/module/commands/install.js +141 -0
  101. package/module/commands/transpile.js +169 -0
  102. package/module/contracts/generate.js +29 -0
  103. package/module/contracts/install.js +105 -0
  104. package/module/contracts/message-composer.js +29 -0
  105. package/module/contracts/react-query.js +29 -0
  106. package/module/contracts/recoil.js +29 -0
  107. package/module/file.js +18 -0
  108. package/module/generators/create-aggregated-lcd-client.js +83 -0
  109. package/module/generators/create-all-stargate-clients.js +92 -0
  110. package/module/generators/create-amino-converters.js +39 -0
  111. package/module/generators/create-bundle.js +79 -0
  112. package/module/generators/create-cosmwasm-bundle.js +11 -0
  113. package/module/generators/create-custom-stargate-clients.js +96 -0
  114. package/module/generators/create-helpers.js +112 -0
  115. package/module/generators/create-index.js +45 -0
  116. package/module/generators/create-lcd-client-all.js +89 -0
  117. package/module/generators/create-lcd-client-scoped.js +62 -0
  118. package/module/generators/create-lcd-clients.js +74 -0
  119. package/module/generators/create-mcp-server.js +1849 -0
  120. package/module/generators/create-mobx-bundle.js +25 -0
  121. package/module/generators/create-msg-funcs.js +128 -0
  122. package/module/generators/create-pinia-store-bundle.js +23 -0
  123. package/module/generators/create-pinia-store.js +86 -0
  124. package/module/generators/create-query-funcs.js +129 -0
  125. package/module/generators/create-react-query-bundle.js +76 -0
  126. package/module/generators/create-registries.js +45 -0
  127. package/module/generators/create-root-readme.js +255 -0
  128. package/module/generators/create-rpc-msg-client-all.js +108 -0
  129. package/module/generators/create-rpc-msg-client-scoped.js +87 -0
  130. package/module/generators/create-rpc-msg-clients.js +112 -0
  131. package/module/generators/create-rpc-ops-bundle.js +92 -0
  132. package/module/generators/create-rpc-query-client-all.js +110 -0
  133. package/module/generators/create-rpc-query-client-scoped.js +83 -0
  134. package/module/generators/create-rpc-query-clients.js +198 -0
  135. package/module/generators/create-sdk-module-stargate-clients.js +91 -0
  136. package/module/generators/create-stargate-clients.js +92 -0
  137. package/module/generators/create-types.js +137 -0
  138. package/module/generators/customize-utils.js +46 -0
  139. package/module/helpers/__test__/internalTimestamp.js +39 -0
  140. package/module/helpers/__test__/internalTimestampBigint.js +38 -0
  141. package/module/helpers/binary-coder.js +531 -0
  142. package/module/helpers/decimals.js +108 -0
  143. package/module/helpers/external-comet.js +49 -0
  144. package/module/helpers/external-icjs.js +33 -0
  145. package/module/helpers/external.js +28 -0
  146. package/module/helpers/grpc-gateway.js +345 -0
  147. package/module/helpers/grpc-web.js +11 -0
  148. package/module/helpers/helper-func-types-interface.js +102 -0
  149. package/module/helpers/helper-func-types.js +89 -0
  150. package/module/helpers/index.js +22 -0
  151. package/module/helpers/internal-for-bigint.js +255 -0
  152. package/module/helpers/internal.js +236 -0
  153. package/module/helpers/json-safe.js +9 -0
  154. package/module/helpers/mobx.js +77 -0
  155. package/module/helpers/pinia-endpoint.js +17 -0
  156. package/module/helpers/react-query-hooks-icjs.js +219 -0
  157. package/module/helpers/react-query-hooks.js +254 -0
  158. package/module/helpers/react-query.js +89 -0
  159. package/module/helpers/registry-helper.js +225 -0
  160. package/module/helpers/types-helper.js +161 -0
  161. package/module/helpers/utf8-helper.js +143 -0
  162. package/module/helpers/varint.js +483 -0
  163. package/module/helpers/vue-query-hooks.js +222 -0
  164. package/module/imports.js +382 -0
  165. package/module/index.js +8 -0
  166. package/module/parse.js +185 -0
  167. package/module/prompt.js +58 -0
  168. package/module/protod/bufbuild.js +76 -0
  169. package/module/protod/config.js +27 -0
  170. package/module/protod/git-repo.js +54 -0
  171. package/module/protod/index.js +1 -0
  172. package/module/protod/recursive.js +125 -0
  173. package/module/protod/types.js +1 -0
  174. package/module/protod/utils.js +77 -0
  175. package/module/telescope.js +8 -0
  176. package/module/types.js +1 -0
  177. package/module/utils/common-create-bundle.js +25 -0
  178. package/module/utils/contracts.js +33 -0
  179. package/module/utils/files.js +106 -0
  180. package/module/utils/index.js +143 -0
  181. package/module/utils/unused.js +47 -0
  182. package/package.json +115 -0
  183. package/src/build.ts +255 -0
  184. package/src/builder.ts +302 -0
  185. package/src/bundle.ts +160 -0
  186. package/src/bundler.ts +153 -0
  187. package/src/cli.js +51 -0
  188. package/src/cmds.js +25 -0
  189. package/src/commands/download.ts +120 -0
  190. package/src/commands/generate.ts +156 -0
  191. package/src/commands/install.ts +154 -0
  192. package/src/commands/transpile.ts +198 -0
  193. package/src/contracts/generate.ts +33 -0
  194. package/src/contracts/install.ts +118 -0
  195. package/src/contracts/message-composer.ts +34 -0
  196. package/src/contracts/react-query.ts +33 -0
  197. package/src/contracts/recoil.ts +32 -0
  198. package/src/file.js +20 -0
  199. package/src/generators/create-aggregated-lcd-client.ts +133 -0
  200. package/src/generators/create-all-stargate-clients.ts +121 -0
  201. package/src/generators/create-amino-converters.ts +62 -0
  202. package/src/generators/create-bundle.ts +97 -0
  203. package/src/generators/create-cosmwasm-bundle.ts +17 -0
  204. package/src/generators/create-custom-stargate-clients.ts +128 -0
  205. package/src/generators/create-helpers.ts +196 -0
  206. package/src/generators/create-index.ts +72 -0
  207. package/src/generators/create-lcd-client-all.ts +139 -0
  208. package/src/generators/create-lcd-client-scoped.ts +109 -0
  209. package/src/generators/create-lcd-clients.ts +108 -0
  210. package/src/generators/create-mcp-server.ts +1902 -0
  211. package/src/generators/create-mobx-bundle.ts +31 -0
  212. package/src/generators/create-msg-funcs.ts +219 -0
  213. package/src/generators/create-pinia-store-bundle.ts +35 -0
  214. package/src/generators/create-pinia-store.ts +121 -0
  215. package/src/generators/create-query-funcs.ts +224 -0
  216. package/src/generators/create-react-query-bundle.ts +111 -0
  217. package/src/generators/create-registries.ts +70 -0
  218. package/src/generators/create-root-readme.ts +316 -0
  219. package/src/generators/create-rpc-msg-client-all.ts +167 -0
  220. package/src/generators/create-rpc-msg-client-scoped.ts +147 -0
  221. package/src/generators/create-rpc-msg-clients.ts +165 -0
  222. package/src/generators/create-rpc-ops-bundle.ts +155 -0
  223. package/src/generators/create-rpc-query-client-all.ts +173 -0
  224. package/src/generators/create-rpc-query-client-scoped.ts +142 -0
  225. package/src/generators/create-rpc-query-clients.ts +304 -0
  226. package/src/generators/create-sdk-module-stargate-clients.ts +120 -0
  227. package/src/generators/create-stargate-clients.ts +123 -0
  228. package/src/generators/create-types.ts +236 -0
  229. package/src/generators/customize-utils.ts +54 -0
  230. package/src/helpers/__test__/internalTimestamp.test.ts +79 -0
  231. package/src/helpers/__test__/internalTimestamp.ts +58 -0
  232. package/src/helpers/__test__/internalTimestampBigint.test.ts +78 -0
  233. package/src/helpers/__test__/internalTimestampBigint.ts +58 -0
  234. package/src/helpers/binary-coder.ts +533 -0
  235. package/src/helpers/decimals.ts +108 -0
  236. package/src/helpers/external-comet.ts +49 -0
  237. package/src/helpers/external-icjs.ts +33 -0
  238. package/src/helpers/external.ts +28 -0
  239. package/src/helpers/grpc-gateway.ts +345 -0
  240. package/src/helpers/grpc-web.ts +11 -0
  241. package/src/helpers/helper-func-types-interface.ts +104 -0
  242. package/src/helpers/helper-func-types.ts +91 -0
  243. package/src/helpers/index.ts +22 -0
  244. package/src/helpers/internal-for-bigint.ts +257 -0
  245. package/src/helpers/internal.ts +238 -0
  246. package/src/helpers/json-safe.ts +11 -0
  247. package/src/helpers/mobx.ts +77 -0
  248. package/src/helpers/pinia-endpoint.ts +17 -0
  249. package/src/helpers/react-query-hooks-icjs.ts +223 -0
  250. package/src/helpers/react-query-hooks.ts +266 -0
  251. package/src/helpers/react-query.ts +101 -0
  252. package/src/helpers/registry-helper.ts +227 -0
  253. package/src/helpers/types-helper.ts +169 -0
  254. package/src/helpers/utf8-helper.ts +143 -0
  255. package/src/helpers/varint.ts +483 -0
  256. package/src/helpers/vue-query-hooks.ts +224 -0
  257. package/src/imports.ts +499 -0
  258. package/src/index.ts +12 -0
  259. package/src/parse.ts +243 -0
  260. package/src/prompt.js +65 -0
  261. package/src/protod/bufbuild.spec.ts +80 -0
  262. package/src/protod/bufbuild.ts +95 -0
  263. package/src/protod/config.ts +30 -0
  264. package/src/protod/git-repo.ts +74 -0
  265. package/src/protod/index.ts +1 -0
  266. package/src/protod/recursive.spec.ts +164 -0
  267. package/src/protod/recursive.ts +180 -0
  268. package/src/protod/test-data/.protod.config.json +42 -0
  269. package/src/protod/test-data/buf.lock +23 -0
  270. package/src/protod/test-data/buf.yaml +25 -0
  271. package/src/protod/test-data/buf2.yaml +20 -0
  272. package/src/protod/test-data/cosmos/buf.lock +23 -0
  273. package/src/protod/test-data/cosmos/crypto/secp256k1/keys.proto +38 -0
  274. package/src/protod/test-data/model.proto +101 -0
  275. package/src/protod/types.ts +55 -0
  276. package/src/protod/utils.spec.ts +68 -0
  277. package/src/protod/utils.ts +90 -0
  278. package/src/telescope.js +9 -0
  279. package/src/types.ts +46 -0
  280. package/src/utils/common-create-bundle.ts +62 -0
  281. package/src/utils/contracts.ts +37 -0
  282. package/src/utils/files.ts +145 -0
  283. package/src/utils/index.ts +150 -0
  284. package/src/utils/unused.ts +52 -0
  285. package/types/build.d.ts +41 -0
  286. package/types/builder.d.ts +50 -0
  287. package/types/bundle.d.ts +30 -0
  288. package/types/bundler.d.ts +31 -0
  289. package/types/cli.d.ts +1 -0
  290. package/types/cmds.d.ts +11 -0
  291. package/types/commands/download.d.ts +5 -0
  292. package/types/commands/generate.d.ts +2 -0
  293. package/types/commands/install.d.ts +2 -0
  294. package/types/commands/transpile.d.ts +4 -0
  295. package/types/contracts/generate.d.ts +2 -0
  296. package/types/contracts/install.d.ts +2 -0
  297. package/types/contracts/message-composer.d.ts +2 -0
  298. package/types/contracts/react-query.d.ts +2 -0
  299. package/types/contracts/recoil.d.ts +2 -0
  300. package/types/file.d.ts +2 -0
  301. package/types/generators/create-aggregated-lcd-client.d.ts +2 -0
  302. package/types/generators/create-all-stargate-clients.d.ts +3 -0
  303. package/types/generators/create-amino-converters.d.ts +3 -0
  304. package/types/generators/create-bundle.d.ts +3 -0
  305. package/types/generators/create-combined-stargate-clients.d.ts +3 -0
  306. package/types/generators/create-cosmwasm-bundle.d.ts +2 -0
  307. package/types/generators/create-custom-stargate-clients.d.ts +3 -0
  308. package/types/generators/create-helpers.d.ts +2 -0
  309. package/types/generators/create-index.d.ts +2 -0
  310. package/types/generators/create-lcd-client-all.d.ts +3 -0
  311. package/types/generators/create-lcd-client-scoped.d.ts +3 -0
  312. package/types/generators/create-lcd-clients.d.ts +3 -0
  313. package/types/generators/create-mcp-server.d.ts +3 -0
  314. package/types/generators/create-mobx-bundle.d.ts +2 -0
  315. package/types/generators/create-msg-funcs.d.ts +3 -0
  316. package/types/generators/create-pinia-store-bundle.d.ts +2 -0
  317. package/types/generators/create-pinia-store.d.ts +3 -0
  318. package/types/generators/create-query-funcs.d.ts +3 -0
  319. package/types/generators/create-react-query-bundle.d.ts +2 -0
  320. package/types/generators/create-registries.d.ts +3 -0
  321. package/types/generators/create-root-readme.d.ts +2 -0
  322. package/types/generators/create-rpc-msg-client-all.d.ts +3 -0
  323. package/types/generators/create-rpc-msg-client-scoped.d.ts +3 -0
  324. package/types/generators/create-rpc-msg-clients.d.ts +3 -0
  325. package/types/generators/create-rpc-ops-bundle.d.ts +2 -0
  326. package/types/generators/create-rpc-query-client-all.d.ts +3 -0
  327. package/types/generators/create-rpc-query-client-scoped.d.ts +3 -0
  328. package/types/generators/create-rpc-query-clients.d.ts +3 -0
  329. package/types/generators/create-scoped-stargate-clients.d.ts +3 -0
  330. package/types/generators/create-sdk-module-stargate-clients.d.ts +3 -0
  331. package/types/generators/create-stargate-clients.d.ts +3 -0
  332. package/types/generators/create-types.d.ts +3 -0
  333. package/types/generators/create-unified-stargate-clients.d.ts +3 -0
  334. package/types/generators/customize-utils.d.ts +2 -0
  335. package/types/helpers/__test__/internalTimestamp.d.ts +21 -0
  336. package/types/helpers/__test__/internalTimestampBigint.d.ts +20 -0
  337. package/types/helpers/binary-coder.d.ts +2 -0
  338. package/types/helpers/decimals.d.ts +1 -0
  339. package/types/helpers/external-comet.d.ts +1 -0
  340. package/types/helpers/external-icjs.d.ts +1 -0
  341. package/types/helpers/external.d.ts +1 -0
  342. package/types/helpers/generated-type.d.ts +1 -0
  343. package/types/helpers/grpc-gateway.d.ts +1 -0
  344. package/types/helpers/grpc-web.d.ts +1 -0
  345. package/types/helpers/helper-func-types-interface.d.ts +2 -0
  346. package/types/helpers/helper-func-types.d.ts +2 -0
  347. package/types/helpers/index.d.ts +22 -0
  348. package/types/helpers/internal-for-bigint.d.ts +2 -0
  349. package/types/helpers/internal.d.ts +2 -0
  350. package/types/helpers/internalForBigInt.d.ts +1 -0
  351. package/types/helpers/json-safe.d.ts +1 -0
  352. package/types/helpers/mobx.d.ts +1 -0
  353. package/types/helpers/pinia-endpoint.d.ts +1 -0
  354. package/types/helpers/react-query-hooks-icjs.d.ts +2 -0
  355. package/types/helpers/react-query-hooks.d.ts +2 -0
  356. package/types/helpers/react-query.d.ts +2 -0
  357. package/types/helpers/registry-helper.d.ts +2 -0
  358. package/types/helpers/types-helper.d.ts +2 -0
  359. package/types/helpers/types.d.ts +1 -0
  360. package/types/helpers/utf8-helper.d.ts +1 -0
  361. package/types/helpers/varint.d.ts +1 -0
  362. package/types/helpers/vue-query-hooks.d.ts +2 -0
  363. package/types/helpers/vue-query.d.ts +2 -0
  364. package/types/imports.d.ts +17 -0
  365. package/types/index.d.ts +6 -0
  366. package/types/parse.d.ts +15 -0
  367. package/types/prompt.d.ts +3 -0
  368. package/types/protod/bufbuild.d.ts +6 -0
  369. package/types/protod/config.d.ts +7 -0
  370. package/types/protod/git-repo.d.ts +11 -0
  371. package/types/protod/index.d.ts +1 -0
  372. package/types/protod/proto-download.d.ts +2 -0
  373. package/types/protod/recursive.d.ts +4 -0
  374. package/types/protod/types.d.ts +49 -0
  375. package/types/protod/utils.d.ts +11 -0
  376. package/types/telescope.d.ts +2 -0
  377. package/types/types.d.ts +43 -0
  378. package/types/utils/common-create-bundle.d.ts +18 -0
  379. package/types/utils/contracts.d.ts +6 -0
  380. package/types/utils/files.d.ts +5 -0
  381. package/types/utils/index.d.ts +16 -0
  382. package/types/utils/unused.d.ts +5 -0
@@ -0,0 +1,1853 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.plugin = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const plugin = (builder, bundler) => {
7
+ // Early return if MCP server is not enabled
8
+ if (!builder.options.mcpServer?.enabled) {
9
+ return;
10
+ }
11
+ // Use the output directory name instead of bundle base
12
+ const outputDirName = (0, path_1.basename)(builder.outPath);
13
+ const packageName = outputDirName || bundler.bundle.base;
14
+ const parentDir = (0, path_1.dirname)(builder.outPath);
15
+ const mcpServerPath = (0, path_1.join)(parentDir, `${packageName}-mcp`);
16
+ // Ensure MCP server directory exists
17
+ (0, fs_1.mkdirSync)(mcpServerPath, { recursive: true });
18
+ (0, fs_1.mkdirSync)((0, path_1.join)(mcpServerPath, 'src'), { recursive: true });
19
+ (0, fs_1.mkdirSync)((0, path_1.join)(mcpServerPath, 'src', 'prompts'), { recursive: true });
20
+ (0, fs_1.mkdirSync)((0, path_1.join)(mcpServerPath, 'src', 'telescope-examples'), { recursive: true });
21
+ // Generate package.json for MCP server
22
+ const packageJson = generateMcpPackageJson(packageName);
23
+ (0, fs_1.writeFileSync)((0, path_1.join)(mcpServerPath, 'package.json'), JSON.stringify(packageJson, null, 2));
24
+ // Generate main MCP server file
25
+ const indexContent = `#!/usr/bin/env node
26
+
27
+ import { readFileSync } from 'node:fs';
28
+ import { dirname, resolve } from 'node:path';
29
+ import { fileURLToPath } from 'node:url';
30
+
31
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
32
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
33
+ import { z } from 'zod';
34
+
35
+ // Get package.json version
36
+ const __filename = fileURLToPath(import.meta.url);
37
+ const __dirname = dirname(__filename);
38
+ const packageJson = JSON.parse(readFileSync(resolve(__dirname, '../package.json'), 'utf8'));
39
+ const VERSION = packageJson.version;
40
+
41
+ async function main() {
42
+ const server = new McpServer({
43
+ name: '${packageName} MCP Server',
44
+ version: VERSION,
45
+ });
46
+
47
+ // Add prompts for AI agents
48
+ server.prompt(
49
+ 'codegen-usage',
50
+ 'Guide for using telescope generated code',
51
+ async () => {
52
+ const promptPath = resolve(__dirname, 'prompts/codegen-usage.md');
53
+ const content = readFileSync(promptPath, 'utf-8');
54
+ return {
55
+ messages: [{
56
+ role: 'user',
57
+ content: {
58
+ type: 'text',
59
+ text: content
60
+ }
61
+ }]
62
+ };
63
+ }
64
+ );
65
+
66
+ server.prompt(
67
+ 'agent-guidelines',
68
+ 'Guidelines for MCP agents using ${packageName}',
69
+ async () => {
70
+ const promptPath = resolve(__dirname, 'prompts/agent-guidelines.md');
71
+ const content = readFileSync(promptPath, 'utf-8');
72
+ return {
73
+ messages: [{
74
+ role: 'user',
75
+ content: {
76
+ type: 'text',
77
+ text: content
78
+ }
79
+ }]
80
+ };
81
+ }
82
+ );
83
+
84
+ // Register blockchain function generator tool
85
+ server.tool(
86
+ 'create-blockchain-function',
87
+ 'Create custom blockchain functions by referencing telescope examples and generated code',
88
+ {
89
+ task: z.string().describe('The blockchain task to implement (e.g., "get balance", "check staking rewards", "query validators")').optional(),
90
+ chainName: z.string().describe('The blockchain name (e.g., cosmos, osmosis, injective)').optional(),
91
+ functionType: z.enum(['query', 'transaction', 'react-hook', 'utility']).describe('Type of function to create').optional(),
92
+ customRequirements: z.string().describe('Any specific requirements or modifications needed').optional()
93
+ },
94
+ async (args) => {
95
+ try {
96
+ const { task = 'get account balance', chainName = 'cosmos', functionType = 'query', customRequirements } = args;
97
+
98
+ // Read available examples
99
+ const examplesPath = resolve(__dirname, 'telescope-examples');
100
+ let availableExamples: string[] = [];
101
+
102
+ try {
103
+ const fs = await import('fs');
104
+ availableExamples = fs.readdirSync(examplesPath)
105
+ .filter(file => file.endsWith('.ts'))
106
+ .map(file => file.replace('.ts', ''));
107
+ } catch (error) {
108
+ // If examples directory doesn't exist, provide default list
109
+ availableExamples = [
110
+ 'config-example', 'useBalance', 'useBalanceFunc', 'getBalance',
111
+ 'useAssets', 'useStakingData', 'useValidators', 'useVoting',
112
+ 'useVotingData', 'useContractInfo', 'useQueryContract',
113
+ 'useCodeDetails', 'useMyContracts', 'useGrants', 'useSendData',
114
+ 'useTotalAssets', 'useBalanceReact'
115
+ ];
116
+ }
117
+
118
+ const examplesList = availableExamples.map(example => \`- **\${example}.ts**: Reference implementation\`).join('\\n');
119
+
120
+ const relevantExamples = getRelevantExamples(task, availableExamples)
121
+ .map(example => \`- **\${example}**: \${getExampleDescription(example)}\`)
122
+ .join('\\n');
123
+
124
+ const codeBlockStart = '\`\`\`';
125
+ const codeBlockEnd = '\`\`\`';
126
+
127
+ const response = [
128
+ '# Blockchain Function Generator',
129
+ '',
130
+ \`## Task: \${task}\`,
131
+ \`## Chain: \${chainName}\`,
132
+ \`## Function Type: \${functionType}\`,
133
+ customRequirements ? \`## Custom Requirements: \${customRequirements}\` : '',
134
+ '',
135
+ '## Instructions for Implementation',
136
+ '',
137
+ '### Step 1: Review Available Examples',
138
+ 'The following example files are available in \`src/telescope-examples/\`:',
139
+ '',
140
+ examplesList,
141
+ '',
142
+ '### Step 2: Identify Relevant Examples',
143
+ \`Based on your task "\${task}", you should primarily reference:\`,
144
+ '',
145
+ relevantExamples,
146
+ '',
147
+ '### Step 3: Implementation Pattern',
148
+ '',
149
+ \`**For Query Functions (\${functionType === 'query' ? 'SELECTED' : 'Available'}):**\`,
150
+ \`\${codeBlockStart}typescript\`,
151
+ "import { getBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.func';",
152
+ '',
153
+ 'export const customQueryFunction = async (params: QueryParams) => {',
154
+ \` const rpcEndpoint = 'https://\${chainName}-rpc.quickapi.com:443';\`,
155
+ ' ',
156
+ ' try {',
157
+ ' const result = await getBalance(rpcEndpoint, params);',
158
+ ' return {',
159
+ ' success: true,',
160
+ ' data: result,',
161
+ ' };',
162
+ ' } catch (error) {',
163
+ ' return {',
164
+ ' success: false,',
165
+ ' error: (error as Error).message,',
166
+ ' };',
167
+ ' }',
168
+ '};',
169
+ codeBlockEnd,
170
+ '',
171
+ \`**For React Hooks (\${functionType === 'react-hook' ? 'SELECTED' : 'Available'}):**\`,
172
+ \`\${codeBlockStart}typescript\`,
173
+ "import { useGetBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';",
174
+ "import { defaultContext } from '@tanstack/react-query';",
175
+ '',
176
+ 'export const useCustomHook = (params: HookParams) => {',
177
+ \` const rpcEndpoint = 'https://\${chainName}-rpc.quickapi.com:443';\`,
178
+ ' ',
179
+ ' return useGetBalance({',
180
+ ' request: params,',
181
+ ' options: {',
182
+ ' enabled: !!params.address,',
183
+ ' context: defaultContext,',
184
+ ' },',
185
+ ' clientResolver: rpcEndpoint,',
186
+ ' });',
187
+ '};',
188
+ codeBlockEnd,
189
+ '',
190
+ '### Step 4: Configuration Setup',
191
+ 'Always include proper chain configuration. Reference \`config-example.ts\`:',
192
+ '',
193
+ \`\${codeBlockStart}typescript\`,
194
+ 'import { assetLists, chains } from "@chain-registry/v2";',
195
+ '',
196
+ \`export const targetChainName = '\${chainName}';\`,
197
+ \`export const rpcEndpoint = 'https://\${chainName}-rpc.quickapi.com:443';\`,
198
+ 'export const chain = chains.find((chain) => chain.chainName === targetChainName);',
199
+ 'export const assetList = assetLists.find((assetList) => assetList.chainName === targetChainName);',
200
+ codeBlockEnd,
201
+ '',
202
+ '### Step 5: Error Handling & Best Practices',
203
+ '- Always wrap async calls in try-catch blocks',
204
+ '- Validate input parameters before making requests',
205
+ '- Handle network timeouts and connection errors',
206
+ '- Convert base units to human-readable amounts (uatom → ATOM)',
207
+ '- Include proper TypeScript types',
208
+ '',
209
+ '### Step 6: Testing Your Function',
210
+ \`\${codeBlockStart}typescript\`,
211
+ '// Example usage',
212
+ 'const result = await customQueryFunction({',
213
+ " address: 'cosmos1...',",
214
+ " denom: 'uatom'",
215
+ '});',
216
+ '',
217
+ 'if (result.success) {',
218
+ " console.log('Result:', result.data);",
219
+ '} else {',
220
+ " console.error('Error:', result.error);",
221
+ '}',
222
+ codeBlockEnd,
223
+ '',
224
+ '## Additional Resources',
225
+ '',
226
+ '- **Full codebase reference**: \`src/telescope/\` directory contains all generated types and functions',
227
+ '- **Configuration examples**: \`src/telescope-examples/config-example.ts\`',
228
+ '- **Chain registry data**: \`src/prompts/chains.json\`',
229
+ '- **Usage guidelines**: Use the \`codegen-usage\` and \`agent-guidelines\` prompts for detailed instructions',
230
+ '',
231
+ '## Next Steps',
232
+ '',
233
+ '1. Review the suggested example files above',
234
+ '2. Copy and modify the relevant pattern for your use case',
235
+ '3. Test your implementation with proper error handling',
236
+ '4. Ensure proper TypeScript types are used',
237
+ '',
238
+ 'The examples in \`telescope-examples/\` are production-ready patterns that you can adapt for any blockchain task.'
239
+ ].filter(line => line !== '').join('\\n');
240
+
241
+ return {
242
+ content: [{
243
+ type: "text",
244
+ text: response
245
+ }]
246
+ };
247
+
248
+ } catch (error) {
249
+ return {
250
+ content: [{
251
+ type: "text",
252
+ text: \`Error generating blockchain function guidance: \${(error as Error).message}\`
253
+ }]
254
+ };
255
+ }
256
+ }
257
+ );
258
+
259
+ const transport = new StdioServerTransport();
260
+ await server.connect(transport);
261
+ console.log('${packageName} MCP server started on stdio');
262
+ }
263
+
264
+ // Helper functions for example recommendations
265
+ function getRelevantExamples(task: string, availableExamples: string[]): string[] {
266
+ const taskLower = task.toLowerCase();
267
+ const relevantExamples: string[] = [];
268
+
269
+ // Balance-related tasks
270
+ if (taskLower.includes('balance')) {
271
+ relevantExamples.push('useBalance', 'useBalanceFunc', 'getBalance');
272
+ if (taskLower.includes('react')) {
273
+ relevantExamples.push('useBalanceReact');
274
+ }
275
+ }
276
+
277
+ // Staking-related tasks
278
+ if (taskLower.includes('staking') || taskLower.includes('delegate') || taskLower.includes('validator')) {
279
+ relevantExamples.push('useStakingData', 'useValidators');
280
+ }
281
+
282
+ // Governance/voting tasks
283
+ if (taskLower.includes('voting') || taskLower.includes('proposal') || taskLower.includes('governance')) {
284
+ relevantExamples.push('useVoting', 'useVotingData');
285
+ }
286
+
287
+ // Assets/portfolio tasks
288
+ if (taskLower.includes('asset') || taskLower.includes('portfolio') || taskLower.includes('total')) {
289
+ relevantExamples.push('useAssets', 'useTotalAssets');
290
+ }
291
+
292
+ // Contract-related tasks
293
+ if (taskLower.includes('contract') || taskLower.includes('cosmwasm')) {
294
+ relevantExamples.push('useContractInfo', 'useQueryContract', 'useCodeDetails', 'useMyContracts');
295
+ }
296
+
297
+ // Transaction/sending tasks
298
+ if (taskLower.includes('send') || taskLower.includes('transaction') || taskLower.includes('transfer')) {
299
+ relevantExamples.push('useSendData', 'getBalance');
300
+ }
301
+
302
+ // Authorization tasks
303
+ if (taskLower.includes('grant') || taskLower.includes('authorization') || taskLower.includes('authz')) {
304
+ relevantExamples.push('useGrants');
305
+ }
306
+
307
+ // Always include config as it's fundamental
308
+ relevantExamples.unshift('config-example');
309
+
310
+ // Remove duplicates and ensure examples exist
311
+ return [...new Set(relevantExamples)].filter(example =>
312
+ availableExamples.includes(example)
313
+ );
314
+ }
315
+
316
+ function getExampleDescription(example: string): string {
317
+ const descriptions: Record<string, string> = {
318
+ 'config-example': 'Chain configuration and RPC endpoints setup',
319
+ 'useBalance': 'React hook for querying account balance',
320
+ 'useBalanceFunc': 'Direct function for balance queries',
321
+ 'useBalanceReact': 'React hook with BigNumber for balance queries',
322
+ 'getBalance': 'Basic balance query with transaction examples',
323
+ 'useAssets': 'Query all token balances for an account',
324
+ 'useStakingData': 'Comprehensive staking information (delegations, rewards, validators)',
325
+ 'useValidators': 'Query active validators with sorting',
326
+ 'useVoting': 'Active governance proposals in voting period',
327
+ 'useVotingData': 'All governance proposals with categorization',
328
+ 'useContractInfo': 'Smart contract information queries',
329
+ 'useQueryContract': 'Execute smart contract queries',
330
+ 'useCodeDetails': 'Contract code information and metadata',
331
+ 'useMyContracts': 'Contracts created by specific address',
332
+ 'useGrants': 'Authorization grants (granter/grantee)',
333
+ 'useSendData': 'Prepare transaction data for token transfers',
334
+ 'useTotalAssets': 'Portfolio summary with total asset calculations'
335
+ };
336
+
337
+ return descriptions[example] || 'Blockchain utility function';
338
+ }
339
+
340
+ main().catch((error) => {
341
+ console.error('Fatal error in main()', error);
342
+ process.exit(1);
343
+ });
344
+ `;
345
+ (0, fs_1.writeFileSync)((0, path_1.join)(mcpServerPath, 'src', 'index.ts'), indexContent);
346
+ // Generate telescope loader utility
347
+ const telescopeLoaderCode = generateTelescopeLoader(packageName);
348
+ (0, fs_1.writeFileSync)((0, path_1.join)(mcpServerPath, 'src', 'telescope-loader.ts'), telescopeLoaderCode);
349
+ // Generate TypeScript configuration
350
+ const tsConfig = generateTsConfig();
351
+ (0, fs_1.writeFileSync)((0, path_1.join)(mcpServerPath, 'tsconfig.json'), JSON.stringify(tsConfig, null, 2));
352
+ // Generate README
353
+ const readme = generateReadme(packageName);
354
+ (0, fs_1.writeFileSync)((0, path_1.join)(mcpServerPath, 'README.md'), readme);
355
+ // Generate comprehensive prompts and guidelines
356
+ generateComprehensivePrompts(mcpServerPath, packageName);
357
+ // Generate telescope examples
358
+ generateTelescopeExamples(mcpServerPath, packageName);
359
+ // Copy entire telescope generated codebase for AI reference (excluded from build)
360
+ copyTelescopeCodebase(builder, mcpServerPath, packageName);
361
+ };
362
+ exports.plugin = plugin;
363
+ function generateMcpPackageJson(packageName) {
364
+ return {
365
+ name: `@${packageName}/mcp-server`,
366
+ version: "0.1.0",
367
+ description: `MCP server for ${packageName} blockchain interactions`,
368
+ main: "dist/index.js",
369
+ type: "module",
370
+ bin: {
371
+ [`@${packageName}/mcp-server`]: "./dist/index.js"
372
+ },
373
+ scripts: {
374
+ build: "rimraf dist && tsc",
375
+ clean: "rimraf dist",
376
+ test: "vitest",
377
+ inspector: "npm run build && npm exec @modelcontextprotocol/inspector node dist/index.js",
378
+ format: "biome check --write",
379
+ lint: "biome check"
380
+ },
381
+ dependencies: {
382
+ "@modelcontextprotocol/sdk": "^1.7.0",
383
+ "zod": "^3.24.2"
384
+ },
385
+ devDependencies: {
386
+ "@biomejs/biome": "1.9.4",
387
+ "@types/node": "^22.13.10",
388
+ "rimraf": "^6.0.1",
389
+ "typescript": "^5.8.2",
390
+ "vitest": "^3.1.1"
391
+ },
392
+ files: ["dist"],
393
+ publishConfig: {
394
+ access: "public"
395
+ }
396
+ };
397
+ }
398
+ function generateMcpServerCode(builder, bundler) {
399
+ const outputDirName = (0, path_1.basename)(builder.outPath);
400
+ const packageName = outputDirName || bundler.bundle.base;
401
+ return `#!/usr/bin/env node
402
+
403
+ import { readFileSync } from 'node:fs';
404
+ import { dirname, resolve } from 'node:path';
405
+ import { fileURLToPath } from 'node:url';
406
+
407
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
408
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
409
+ import { z } from 'zod';
410
+
411
+ // NOTE: Tool imports are commented out since they are excluded from build
412
+ // Uncomment and modify these imports if you want to include tools in your build
413
+ /*
414
+ import { getBalanceTool } from './tools/getBalance.js';
415
+ import { getBalanceReactTool } from './tools/useBalance.js';
416
+ */
417
+
418
+ // Get package.json version
419
+ const __filename = fileURLToPath(import.meta.url);
420
+ const __dirname = dirname(__filename);
421
+ const packageJson = JSON.parse(readFileSync(resolve(__dirname, '../package.json'), 'utf8'));
422
+ const VERSION = packageJson.version;
423
+
424
+ async function main() {
425
+ const server = new McpServer({
426
+ name: '${packageName} MCP Server',
427
+ version: VERSION,
428
+ });
429
+
430
+ // Add prompts for AI agents
431
+ server.prompt(
432
+ 'codegen-usage',
433
+ 'Guide for using telescope generated code',
434
+ async () => {
435
+ const promptPath = resolve(__dirname, 'prompts/codegen-usage.md');
436
+ const content = readFileSync(promptPath, 'utf-8');
437
+ return {
438
+ messages: [{
439
+ role: 'user',
440
+ content: {
441
+ type: 'text',
442
+ text: content
443
+ }
444
+ }]
445
+ };
446
+ }
447
+ );
448
+
449
+ server.prompt(
450
+ 'agent-guidelines',
451
+ 'Guidelines for MCP agents using ${packageName}',
452
+ async () => {
453
+ const promptPath = resolve(__dirname, 'prompts/agent-guidelines.md');
454
+ const content = readFileSync(promptPath, 'utf-8');
455
+ return {
456
+ messages: [{
457
+ role: 'user',
458
+ content: {
459
+ type: 'text',
460
+ text: content
461
+ }
462
+ }]
463
+ };
464
+ }
465
+ );
466
+
467
+ // NOTE: Tool registrations are commented out since tool functions are not imported
468
+ // Uncomment and modify these registrations if you want to include tools in your build
469
+ /*
470
+ // Register tools
471
+ server.tool('get-balance', 'Get account balance for a specific token', {
472
+ address: z.string().describe('The account address'),
473
+ chainName: z.string().describe('The blockchain name (e.g., cosmos, osmosis)').optional(),
474
+ denom: z.string().describe('The token denomination (e.g., uatom, uosmo)').optional()
475
+ }, getBalanceTool);
476
+
477
+ server.tool('get-balance-react', 'Get balance using React hook pattern', {
478
+ address: z.string().describe('The account address'),
479
+ chainName: z.string().describe('The blockchain name').optional(),
480
+ displayDenom: z.string().describe('The display denomination').optional()
481
+ }, getBalanceReactTool);
482
+ */
483
+
484
+ const transport = new StdioServerTransport();
485
+ await server.connect(transport);
486
+ console.log('${packageName} MCP server started on stdio');
487
+ }
488
+
489
+ main().catch((error) => {
490
+ console.error('Fatal error in main()', error);
491
+ process.exit(1);
492
+ });
493
+ `;
494
+ }
495
+ function generateTsConfig() {
496
+ return {
497
+ compilerOptions: {
498
+ target: "ES2022",
499
+ module: "ESNext",
500
+ moduleResolution: "node",
501
+ outDir: "./dist",
502
+ rootDir: "./src",
503
+ strict: true,
504
+ esModuleInterop: true,
505
+ skipLibCheck: true,
506
+ forceConsistentCasingInFileNames: true,
507
+ declaration: true,
508
+ declarationMap: true,
509
+ sourceMap: true,
510
+ allowSyntheticDefaultImports: true,
511
+ resolveJsonModule: true
512
+ },
513
+ include: ["src/**/*"],
514
+ exclude: ["node_modules", "dist", "src/telescope/**/*", "src/telescope-examples/**/*"]
515
+ };
516
+ }
517
+ function generateReadme(packageName) {
518
+ return `# ${packageName.charAt(0).toUpperCase() + packageName.slice(1)} MCP Server
519
+
520
+ This MCP server provides AI agents with tools to interact with blockchain through generated TypeScript clients.
521
+
522
+ **Note**: This MCP server contains a complete copy of the telescope generated codebase in \`src/telescope/\` for AI agents to reference, but uses mock implementations for demonstration. The telescope code is excluded from the build process.
523
+
524
+ ## Installation
525
+
526
+ \`\`\`bash
527
+ cd ${packageName}-mcp
528
+ npm install
529
+ npm run build
530
+ \`\`\`
531
+
532
+ ## Usage with AI Agents
533
+
534
+ Add this configuration to your AI agent's MCP settings:
535
+
536
+ \`\`\`json
537
+ {
538
+ "mcpServers": {
539
+ "${packageName}-mcp-server": {
540
+ "command": "node",
541
+ "args": ["/path/to/${packageName}-mcp/dist/index.js"]
542
+ }
543
+ }
544
+ }
545
+ \`\`\`
546
+
547
+ ## Available Features
548
+
549
+ This MCP server provides:
550
+
551
+ - **Comprehensive Examples**: Reference implementations in \`src/telescope-examples/\`
552
+ - **Function Generator Tool**: AI-powered tool that creates custom blockchain functions based on user requirements
553
+ - **AI Guidance**: Prompt files to help AI agents understand blockchain development
554
+ - **Complete Codebase**: Full telescope-generated code in \`src/telescope/\` for reference
555
+
556
+ **Note**: The MCP server uses a meta-tool approach - instead of predefined tools, it instructs agents to create custom functions by referencing the comprehensive examples.
557
+
558
+ ## Development
559
+
560
+ \`\`\`bash
561
+ npm run build # Build the server
562
+ npm run inspector # Run MCP inspector for testing
563
+ npm run clean # Clean dist directory
564
+ \`\`\`
565
+
566
+ ## Directory Structure
567
+
568
+ \`\`\`
569
+ ${packageName}-mcp/
570
+ ├── src/
571
+ │ ├── telescope/ # 📚 Telescope generated code (reference only, excluded from build)
572
+ │ │ ├── cosmos/ # Full cosmos SDK modules
573
+ │ │ │ ├── bank/ # Balance queries, transfers
574
+ │ │ │ ├── staking/ # Validator operations
575
+ │ │ │ └── ... # Other cosmos modules
576
+ │ │ ├── osmosis/ # Osmosis DEX functionality
577
+ │ │ ├── ibc/ # Inter-blockchain communication
578
+ │ │ └── index.ts # Main exports
579
+ │ ├── telescope-examples/ # 📖 Usage examples and patterns (excluded from build)
580
+ │ │ ├── config-example.ts # Chain configuration setup
581
+ │ │ ├── useBalance.ts # Balance query React hooks
582
+ │ │ ├── useBalanceFunc.ts # Direct balance functions
583
+ │ │ ├── getBalance.ts # Balance queries with examples
584
+ │ │ ├── useAssets.ts # Multi-token balance queries
585
+ │ │ ├── useStakingData.ts # Staking and delegation info
586
+ │ │ ├── useValidators.ts # Validator queries
587
+ │ │ ├── useVoting.ts # Governance proposals
588
+ │ │ ├── useContractInfo.ts # Smart contract queries
589
+ │ │ ├── useMyContracts.ts # User's contract list
590
+ │ │ ├── useGrants.ts # Authorization grants
591
+ │ │ └── useSendData.ts # Transaction preparation
592
+ │ ├── prompts/ # 🤖 Agent instruction files
593
+ │ │ ├── codegen-usage.md # Telescope usage guide
594
+ │ │ ├── agent-guidelines.md # Best practices for agents
595
+ │ │ └── chains.json # Chain registry data
596
+ │ ├── index.ts # MCP server with function generator tool
597
+ │ └── telescope-loader.ts # Utility for dynamic code loading
598
+ ├── dist/ # Compiled JavaScript (excludes telescope/ and telescope-examples/)
599
+ └── package.json
600
+ \`\`\`
601
+
602
+ The \`src/telescope/\` and \`src/telescope-examples/\` directories contain reference code for AI agents but are excluded from the TypeScript build process.
603
+
604
+ Generated by [Telescope](https://github.com/hyperweb-io/telescope) 🔭
605
+ `;
606
+ }
607
+ function copyTelescopeCodebase(builder, mcpServerPath, packageName) {
608
+ const sourcePath = builder.outPath;
609
+ const destPath = (0, path_1.join)(mcpServerPath, 'src', 'telescope');
610
+ // Copy the entire telescope generated directory
611
+ if ((0, fs_1.existsSync)(sourcePath)) {
612
+ // Skip copy if destination already exists (avoids Windows file permission issues)
613
+ if ((0, fs_1.existsSync)(destPath)) {
614
+ console.log(`Telescope codebase already exists at ${destPath}, skipping copy to avoid Windows file permission issues`);
615
+ return;
616
+ }
617
+ console.log(`Copying telescope codebase from ${sourcePath} to ${destPath}`);
618
+ // Ensure parent directory exists
619
+ (0, fs_1.mkdirSync)((0, path_1.dirname)(destPath), { recursive: true });
620
+ // Copy without removing destination first
621
+ try {
622
+ (0, fs_1.cpSync)(sourcePath, destPath, { recursive: true, force: true });
623
+ }
624
+ catch (error) {
625
+ console.warn(`Warning: Could not copy telescope codebase: ${error}`);
626
+ console.log('MCP server will still function, but AI agents will have limited code references');
627
+ // Don't throw error - let MCP server generation continue
628
+ }
629
+ }
630
+ else {
631
+ console.warn(`Source path ${sourcePath} does not exist, skipping telescope codebase copy`);
632
+ }
633
+ }
634
+ // Removed retry logic - no longer needed since we skip copy if destination exists
635
+ function generateTelescopeLoader(packageName) {
636
+ return `import { readFileSync } from 'node:fs';
637
+ import { resolve, dirname } from 'node:path';
638
+ import { fileURLToPath } from 'node:url';
639
+
640
+ const __filename = fileURLToPath(import.meta.url);
641
+ const __dirname = dirname(__filename);
642
+
643
+ /**
644
+ * Load telescope generated modules dynamically
645
+ * This utility helps MCP tools access the telescope codebase
646
+ */
647
+ export class TelescopeLoader {
648
+ private basePath: string;
649
+
650
+ constructor() {
651
+ this.basePath = resolve(__dirname, 'telescope');
652
+ }
653
+
654
+ /**
655
+ * Get available modules in the telescope codebase
656
+ */
657
+ getAvailableModules(): string[] {
658
+ // This would typically read the directory structure
659
+ // For now, return common cosmos modules
660
+ return [
661
+ 'cosmos/bank/v1beta1',
662
+ 'cosmos/staking/v1beta1',
663
+ 'cosmos/gov/v1beta1',
664
+ 'cosmos/distribution/v1beta1',
665
+ 'cosmwasm/wasm/v1',
666
+ 'ibc/core/client/v1',
667
+ 'osmosis/gamm/v1beta1'
668
+ ];
669
+ }
670
+
671
+ /**
672
+ * Load module documentation/examples
673
+ */
674
+ loadModuleInfo(modulePath: string) {
675
+ try {
676
+ const infoPath = resolve(this.basePath, modulePath, 'README.md');
677
+ return readFileSync(infoPath, 'utf-8');
678
+ } catch (error) {
679
+ return \`Module documentation not found for \${modulePath}\`;
680
+ }
681
+ }
682
+
683
+ /**
684
+ * Get module schema information
685
+ */
686
+ getModuleSchema(modulePath: string) {
687
+ // Return basic schema info for the module
688
+ return {
689
+ module: modulePath,
690
+ package: '${packageName}',
691
+ queries: ['getBalance', 'getAllBalances'],
692
+ mutations: ['send', 'delegate'],
693
+ types: ['Coin', 'MsgSend', 'MsgDelegate']
694
+ };
695
+ }
696
+ }
697
+
698
+ export const telescopeLoader = new TelescopeLoader();
699
+ `;
700
+ }
701
+ function generateComprehensivePrompts(mcpServerPath, packageName) {
702
+ // Generate codegen-usage.md
703
+ const codegenUsageContent = `# Codegen Usage Guide
704
+
705
+ ## Overview
706
+ This guide provides instructions for MCP agents on how to use the telescope generated code in the ${packageName} package.
707
+
708
+ ## Category of Functions
709
+
710
+ ### 1. **.rpc.func** - Direct Function Calls
711
+ These are direct async functions that make RPC calls to blockchain nodes. Use these for:
712
+ - Server-side operations
713
+ - Node.js scripts
714
+ - Direct blockchain queries outside React
715
+
716
+ **Import Pattern**:
717
+ \`\`\`typescript
718
+ import { getBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.func';
719
+ import { send } from '${packageName}/cosmos/bank/v1beta1/tx.rpc.func';
720
+ \`\`\`
721
+
722
+ **Usage Examples**:
723
+
724
+ **Query Balance**:
725
+ \`\`\`typescript
726
+ import { getBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.func';
727
+
728
+ // Basic balance query
729
+ const { balance } = await getBalance(rpcEndpoint, {
730
+ address: "cosmos1...",
731
+ denom: "uatom"
732
+ });
733
+
734
+ // With error handling
735
+ try {
736
+ const { balance } = await getBalance(rpcEndpoint, { address, denom });
737
+ const atomAmount = Number(balance?.amount || 0) / Math.pow(10, 6); // Convert uatom to ATOM
738
+ return atomAmount;
739
+ } catch (error) {
740
+ console.error('Error fetching balance:', error);
741
+ return null;
742
+ }
743
+ \`\`\`
744
+
745
+ ### 2. **.rpc.react** - React Hooks
746
+ These are React hooks for frontend applications. They provide:
747
+ - Automatic caching and refetching
748
+ - Loading states
749
+ - Error handling
750
+ - Integration with React Query
751
+
752
+ **Import Pattern**:
753
+ \`\`\`typescript
754
+ import { useGetBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
755
+ import { useSend } from '${packageName}/cosmos/bank/v1beta1/tx.rpc.react';
756
+ \`\`\`
757
+
758
+ ## Chain Configuration Setup
759
+
760
+ ### Import Chain Registry Data
761
+ \`\`\`typescript
762
+ import { assetLists, chains } from "@chain-registry/v2";
763
+ \`\`\`
764
+
765
+ ### Basic Configuration
766
+ \`\`\`typescript
767
+ // Define your target chain
768
+ export const defaultChainName = 'cosmos'; // or 'osmosis', 'injective', etc.
769
+
770
+ // Find chain info from registry
771
+ export const defaultChain = chains.find((chain) => chain.chainName === defaultChainName);
772
+
773
+ // Get RPC endpoint
774
+ export const defaultRpcEndpoint = defaultChain?.apis?.rpc?.[0]?.address || 'http://localhost:26657';
775
+ \`\`\`
776
+
777
+ ## Detailed Examples Reference
778
+
779
+ ### Using src/telescope-examples Directory
780
+ When you need more specific implementation details or complex use cases, reference the example files in \`src/telescope-examples/\`. These are real-world examples for production usage.
781
+
782
+ ### Using src/tools Directory
783
+ The \`src/tools/\` directory contains MCP tool implementations that demonstrate how to use the telescope-examples in MCP tools. These tools show patterns for:
784
+ - Importing functions from telescope-examples
785
+ - Handling errors and returning proper MCP responses
786
+ - Working with blockchain data in MCP context
787
+
788
+ Each tool in \`src/tools/\` corresponds to functionality in \`src/telescope-examples/\` and shows how to bridge the gap between React hooks/utility functions and MCP tool implementations.
789
+
790
+ ## Important Notes
791
+
792
+ ### Function Categories Usage
793
+ - **Use .rpc.func** for: Server-side scripts, CLI tools, backend services
794
+ - **Use .rpc.react** for: React applications, frontend components with state management
795
+
796
+ ### Error Handling Patterns
797
+ \`\`\`typescript
798
+ // For .rpc.func
799
+ try {
800
+ const result = await getBalance(rpcEndpoint, { address, denom });
801
+ return result;
802
+ } catch (error) {
803
+ if (error.message.includes('not found')) {
804
+ return null; // Handle account not found
805
+ }
806
+ throw error; // Re-throw other errors
807
+ }
808
+ \`\`\`
809
+ `;
810
+ (0, fs_1.writeFileSync)((0, path_1.join)(mcpServerPath, 'src', 'prompts', 'codegen-usage.md'), codegenUsageContent);
811
+ // Generate agent-guidelines.md
812
+ const agentGuidelinesContent = `# MCP Agent Guidelines
813
+
814
+ ## Overview
815
+ These guidelines help MCP agents provide helpful, accurate, and safe blockchain interactions using the ${packageName} library.
816
+
817
+ ## General Principles
818
+
819
+ ### 1. Safety First
820
+ - **Never expose private keys or mnemonics**
821
+ - **Always validate addresses before operations**
822
+ - **Warn users about irreversible operations**
823
+ - **Explain risks (slashing, unbonding periods, etc.)**
824
+
825
+ ### 2. User-Friendly Communication
826
+ - **Convert base units to human-readable amounts** (uatom → ATOM)
827
+ - **Use clear, non-technical language when possible**
828
+ - **Provide context for blockchain-specific concepts**
829
+ - **Show approximate USD values when helpful**
830
+
831
+ ### 3. Accuracy and Reliability
832
+ - **Always handle errors gracefully**
833
+ - **Provide accurate information about fees and timing**
834
+ - **Double-check calculations and conversions**
835
+ - **Verify data freshness and warn about stale data**
836
+
837
+ ## Response Patterns
838
+
839
+ ### When User Asks About Balances
840
+ \`\`\`
841
+ ✅ Good Response:
842
+ "You have 12.5 ATOM (12,500,000 uatom) in your wallet. This is worth approximately $150 USD at current prices. You also have 0.05 ATOM available to pay for transaction fees."
843
+
844
+ ❌ Poor Response:
845
+ "Balance: 12500000"
846
+ \`\`\`
847
+
848
+ ## Data Formatting Guidelines
849
+
850
+ ### Amounts
851
+ Always convert from base units:
852
+ \`\`\`typescript
853
+ // Good
854
+ const atomAmount = parseInt(balance.amount) / 1_000_000;
855
+ return \`$\{atomAmount} ATOM\`;
856
+
857
+ // Bad
858
+ return \`$\{balance.amount} uatom\`;
859
+ \`\`\`
860
+
861
+ ### Addresses
862
+ Abbreviate long addresses for readability:
863
+ \`\`\`typescript
864
+ const formatAddress = (addr: string) => {
865
+ return \`$\{addr.slice(0, 10)}...$\{addr.slice(-4)}\`;
866
+ };
867
+ // cosmos1abc123...xyz9
868
+ \`\`\`
869
+
870
+ ## Security Guidelines
871
+
872
+ ### Address Validation
873
+ \`\`\`typescript
874
+ const validateCosmosAddress = (address: string): boolean => {
875
+ return address.startsWith('cosmos1') && address.length === 45;
876
+ };
877
+ \`\`\`
878
+
879
+ ### Amount Validation
880
+ \`\`\`typescript
881
+ const validateAmount = (amount: string): boolean => {
882
+ const num = parseFloat(amount);
883
+ return !isNaN(num) && num > 0 && num < 1e15; // Reasonable limits
884
+ };
885
+ \`\`\`
886
+ `;
887
+ (0, fs_1.writeFileSync)((0, path_1.join)(mcpServerPath, 'src', 'prompts', 'agent-guidelines.md'), agentGuidelinesContent);
888
+ // Copy chains.json from chain-registry (this is a large static file)
889
+ const chainsJsonContent = `[
890
+ {
891
+ "$schema": "../chain.schema.json",
892
+ "chainName": "cosmos",
893
+ "status": "live",
894
+ "networkType": "mainnet",
895
+ "prettyName": "Cosmos Hub",
896
+ "chainId": "cosmoshub-4",
897
+ "bech32Prefix": "cosmos",
898
+ "daemonName": "gaiad",
899
+ "nodeHome": "$HOME/.gaia",
900
+ "slip44": 118,
901
+ "apis": {
902
+ "rpc": [
903
+ {
904
+ "address": "https://cosmos-rpc.quickapi.com:443"
905
+ }
906
+ ],
907
+ "rest": [
908
+ {
909
+ "address": "https://cosmos-rest.quickapi.com:443"
910
+ }
911
+ ]
912
+ }
913
+ },
914
+ {
915
+ "chainName": "osmosis",
916
+ "status": "live",
917
+ "networkType": "mainnet",
918
+ "prettyName": "Osmosis",
919
+ "chainId": "osmosis-1",
920
+ "bech32Prefix": "osmo",
921
+ "daemonName": "osmosisd",
922
+ "nodeHome": "$HOME/.osmosisd",
923
+ "slip44": 118,
924
+ "apis": {
925
+ "rpc": [
926
+ {
927
+ "address": "https://osmosis-rpc.quickapi.com:443"
928
+ }
929
+ ],
930
+ "rest": [
931
+ {
932
+ "address": "https://osmosis-rest.quickapi.com:443"
933
+ }
934
+ ]
935
+ }
936
+ },
937
+ {
938
+ "chainName": "injective",
939
+ "status": "live",
940
+ "networkType": "mainnet",
941
+ "prettyName": "Injective",
942
+ "chainId": "injective-1",
943
+ "bech32Prefix": "inj",
944
+ "daemonName": "injectived",
945
+ "nodeHome": "$HOME/.injectived",
946
+ "slip44": 60,
947
+ "apis": {
948
+ "rpc": [
949
+ {
950
+ "address": "https://injective-rpc.quickapi.com:443"
951
+ }
952
+ ],
953
+ "rest": [
954
+ {
955
+ "address": "https://injective-rest.quickapi.com:443"
956
+ }
957
+ ]
958
+ }
959
+ }
960
+ ]`;
961
+ (0, fs_1.writeFileSync)((0, path_1.join)(mcpServerPath, 'src', 'prompts', 'chains.json'), chainsJsonContent);
962
+ }
963
+ function generateTelescopeExamples(mcpServerPath, packageName) {
964
+ const exampleFiles = [
965
+ {
966
+ name: 'config-example.ts',
967
+ content: `import { assetLists, chains } from "@chain-registry/v2";
968
+
969
+ /**
970
+ * mainnet: 'cosmos'
971
+ * testnet: 'cosmoshub-testnet'
972
+ * mainnet rpc: 'https://cosmos-rpc.quickapi.com:443'
973
+ * testnet rpc: 'https://rpc.testnet.cosmos.network:443'
974
+ */
975
+ export const defaultChainName = 'cosmos'
976
+ export const defaultRpcEndpoint = 'https://cosmos-rpc.quickapi.com:443'
977
+
978
+ export const defaultChain = chains.find((chain) => chain.chainName === defaultChainName)
979
+
980
+ export const defaultAssetList = assetLists.find((assetList) => assetList.chainName === defaultChainName)
981
+ `
982
+ },
983
+ {
984
+ name: 'useBalance.ts',
985
+ content: `import { useChain } from '@interchain-kit/react';
986
+ import { defaultContext } from '@tanstack/react-query';
987
+ import { useGetBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
988
+
989
+ export const useBalance = (
990
+ chainName: string,
991
+ enabled: boolean = true,
992
+ displayDenom?: string
993
+ ) => {
994
+ const { address, assetList } = useChain(chainName);
995
+
996
+ let denom = assetList?.assets[0].base!;
997
+ for (const asset of assetList?.assets || []) {
998
+ if (asset.display.toLowerCase() === displayDenom?.toLowerCase()) {
999
+ denom = asset.base;
1000
+ break;
1001
+ }
1002
+ }
1003
+
1004
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443'; // Use dynamic endpoint
1005
+
1006
+ const isReady = !!address && !!rpcEndpoint;
1007
+
1008
+ const balanceQuery = useGetBalance({
1009
+ request: {
1010
+ denom,
1011
+ address: address || '',
1012
+ },
1013
+ options: {
1014
+ enabled: isReady && enabled,
1015
+ select: ({ balance }) => balance,
1016
+ context: defaultContext,
1017
+ },
1018
+ clientResolver: rpcEndpoint,
1019
+ customizedQueryKey: ['balance', address, denom],
1020
+ });
1021
+
1022
+ return {
1023
+ balance: balanceQuery.data,
1024
+ isLoading: balanceQuery.isFetching,
1025
+ };
1026
+ };
1027
+ `
1028
+ },
1029
+ {
1030
+ name: 'useBalanceReact.ts',
1031
+ content: `import { useGetBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
1032
+ import { defaultRpcEndpoint as rpcEndpoint } from '@/config';
1033
+ import BigNumber from 'bignumber.js';
1034
+ import { defaultAssetList } from '@/config';
1035
+ import { defaultContext } from '@tanstack/react-query';
1036
+
1037
+ export default function useBalance({ address }: { address: string }) {
1038
+ const coin = defaultAssetList?.assets[0];
1039
+
1040
+ const denom = coin!.base!;
1041
+
1042
+ const COIN_DISPLAY_EXPONENT = coin!.denomUnits.find(
1043
+ (unit) => unit.denom === coin!.display
1044
+ )?.exponent as number;
1045
+
1046
+ const {
1047
+ data: balance,
1048
+ isSuccess: isBalanceLoaded,
1049
+ isLoading: isFetchingBalance,
1050
+ refetch: refetchBalance,
1051
+ } = useGetBalance({
1052
+ request: {
1053
+ address: address || '',
1054
+ denom,
1055
+ },
1056
+ options: {
1057
+ context: defaultContext,
1058
+ enabled: !!address,
1059
+ select: ({ balance }) =>
1060
+ new BigNumber(balance?.amount ?? 0).multipliedBy(
1061
+ 10 ** -COIN_DISPLAY_EXPONENT
1062
+ ),
1063
+ staleTime: 0,
1064
+ },
1065
+ clientResolver: rpcEndpoint,
1066
+ });
1067
+
1068
+ return {
1069
+ balance,
1070
+ isBalanceLoaded,
1071
+ isFetchingBalance,
1072
+ refetchBalance,
1073
+ };
1074
+ }
1075
+ `
1076
+ },
1077
+ {
1078
+ name: 'useBalanceFunc.ts',
1079
+ content: `import { getBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.func';
1080
+ import { defaultRpcEndpoint } from '@/config';
1081
+
1082
+ export const useBalanceFunc = async (address: string, denom: string) => {
1083
+ try {
1084
+ const { balance } = await getBalance(defaultRpcEndpoint, {
1085
+ address,
1086
+ denom,
1087
+ });
1088
+
1089
+ return {
1090
+ balance: balance?.amount || '0',
1091
+ denom: balance?.denom || denom,
1092
+ };
1093
+ } catch (error) {
1094
+ console.error('Error fetching balance:', error);
1095
+ return {
1096
+ balance: '0',
1097
+ denom,
1098
+ };
1099
+ }
1100
+ };
1101
+ `
1102
+ },
1103
+ {
1104
+ name: 'getBalance.ts',
1105
+ content: `import { getBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.func';
1106
+ import { send } from '${packageName}/cosmos/bank/v1beta1/tx.rpc.func';
1107
+ import { MsgSend } from '${packageName}/cosmos/bank/v1beta1/tx';
1108
+
1109
+ const main = async () => {
1110
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1111
+ const denom = 'uatom';
1112
+ const address = 'cosmos1...'; // Your address here
1113
+
1114
+ // Query balance
1115
+ const { balance } = await getBalance(rpcEndpoint, {
1116
+ address,
1117
+ denom,
1118
+ });
1119
+
1120
+ console.log(\`Balance: \${balance?.amount} \${denom}\`);
1121
+
1122
+ // Example: Send transaction (requires signer setup)
1123
+ /*
1124
+ const fee = {
1125
+ amount: [{ denom, amount: '5000' }],
1126
+ gas: '200000',
1127
+ };
1128
+
1129
+ const token = {
1130
+ amount: '1000000',
1131
+ denom,
1132
+ };
1133
+
1134
+ const msg = MsgSend.fromPartial({
1135
+ fromAddress: address,
1136
+ toAddress: 'cosmos1recipient...',
1137
+ amount: [token],
1138
+ });
1139
+
1140
+ // const tx = await send(signer, address, msg, fee, 'Payment');
1141
+ */
1142
+ };
1143
+
1144
+ main().catch(console.error);
1145
+ `
1146
+ },
1147
+ {
1148
+ name: 'useAssets.ts',
1149
+ content: `import { useMemo } from 'react';
1150
+ import { useChain } from '@interchain-kit/react';
1151
+ import { defaultContext } from '@tanstack/react-query';
1152
+ import BigNumber from 'bignumber.js';
1153
+ import { useGetAllBalances } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
1154
+ import { Coin } from '${packageName}/types';
1155
+
1156
+ export const useAssets = (chainName: string) => {
1157
+ const { address } = useChain(chainName);
1158
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1159
+
1160
+ const isReady = !!address && !!rpcEndpoint;
1161
+
1162
+ const allBalancesQuery = useGetAllBalances({
1163
+ request: {
1164
+ address: address || '',
1165
+ pagination: {
1166
+ key: new Uint8Array(),
1167
+ offset: 0n,
1168
+ limit: 100n,
1169
+ countTotal: true,
1170
+ reverse: false,
1171
+ },
1172
+ resolveDenom: false,
1173
+ },
1174
+ options: {
1175
+ enabled: isReady,
1176
+ select: ({ balances }) => balances || [],
1177
+ context: defaultContext,
1178
+ },
1179
+ clientResolver: rpcEndpoint,
1180
+ customizedQueryKey: ['allBalances', address],
1181
+ });
1182
+
1183
+ const data = useMemo(() => {
1184
+ if (!allBalancesQuery.data) return;
1185
+
1186
+ const assets = allBalancesQuery.data.map(({ amount, denom }) => ({
1187
+ symbol: denom.toUpperCase(),
1188
+ displayAmount: new BigNumber(amount).dividedBy(1e6).toString(),
1189
+ amount,
1190
+ denom,
1191
+ }));
1192
+
1193
+ return { assets };
1194
+ }, [allBalancesQuery.data]);
1195
+
1196
+ return {
1197
+ data,
1198
+ isLoading: allBalancesQuery.isLoading,
1199
+ refetch: allBalancesQuery.refetch
1200
+ };
1201
+ };
1202
+ `
1203
+ },
1204
+ {
1205
+ name: 'useStakingData.ts',
1206
+ content: `import { useMemo } from 'react';
1207
+ import { useChain } from '@interchain-kit/react';
1208
+ import BigNumber from 'bignumber.js';
1209
+ import {
1210
+ BondStatus,
1211
+ bondStatusToJSON,
1212
+ } from '${packageName}/cosmos/staking/v1beta1/staking';
1213
+ import { useGetBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
1214
+ import {
1215
+ useGetDelegatorValidators,
1216
+ useGetDelegatorDelegations,
1217
+ useGetValidators,
1218
+ useGetParams as useStakingParams,
1219
+ useGetPool,
1220
+ } from '${packageName}/cosmos/staking/v1beta1/query.rpc.react';
1221
+ import {
1222
+ useGetDelegationTotalRewards,
1223
+ useGetParams as useDistributionParams,
1224
+ } from '${packageName}/cosmos/distribution/v1beta1/query.rpc.react';
1225
+ import { useGetAnnualProvisions } from '${packageName}/cosmos/mint/v1beta1/query.rpc.react';
1226
+ import { defaultContext } from '@tanstack/react-query';
1227
+
1228
+ export const useStakingData = (chainName: string) => {
1229
+ const { address, assetList } = useChain(chainName);
1230
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1231
+
1232
+ const coin = assetList?.assets[0];
1233
+ const denom = coin?.base || 'uatom';
1234
+
1235
+ const isDataQueryEnabled = !!address && !!rpcEndpoint;
1236
+
1237
+ const balanceQuery = useGetBalance({
1238
+ request: {
1239
+ address: address || '',
1240
+ denom,
1241
+ },
1242
+ options: {
1243
+ context: defaultContext,
1244
+ enabled: isDataQueryEnabled,
1245
+ select: ({ balance }) => balance?.amount || '0',
1246
+ refetchOnMount: 'always',
1247
+ },
1248
+ clientResolver: rpcEndpoint,
1249
+ });
1250
+
1251
+ const validatorsQuery = useGetValidators({
1252
+ request: {
1253
+ status: bondStatusToJSON(BondStatus.BOND_STATUS_BONDED),
1254
+ pagination: {
1255
+ key: new Uint8Array(),
1256
+ offset: 0n,
1257
+ limit: 200n,
1258
+ countTotal: true,
1259
+ reverse: false,
1260
+ },
1261
+ },
1262
+ options: {
1263
+ context: defaultContext,
1264
+ enabled: isDataQueryEnabled,
1265
+ select: ({ validators }) => {
1266
+ return validators.sort((a, b) =>
1267
+ new BigNumber(b.tokens).minus(a.tokens).toNumber(),
1268
+ );
1269
+ },
1270
+ },
1271
+ clientResolver: rpcEndpoint,
1272
+ customizedQueryKey: ['validators', chainName],
1273
+ });
1274
+
1275
+ const delegationsQuery = useGetDelegatorDelegations({
1276
+ request: {
1277
+ delegatorAddr: address || '',
1278
+ pagination: {
1279
+ key: new Uint8Array(),
1280
+ offset: 0n,
1281
+ limit: 100n,
1282
+ countTotal: true,
1283
+ reverse: false,
1284
+ },
1285
+ },
1286
+ options: {
1287
+ context: defaultContext,
1288
+ enabled: isDataQueryEnabled,
1289
+ select: ({ delegationResponses }) => delegationResponses,
1290
+ },
1291
+ clientResolver: rpcEndpoint,
1292
+ });
1293
+
1294
+ const rewardsQuery = useGetDelegationTotalRewards({
1295
+ request: {
1296
+ delegatorAddress: address || '',
1297
+ },
1298
+ options: {
1299
+ context: defaultContext,
1300
+ enabled: isDataQueryEnabled,
1301
+ select: (data) => data,
1302
+ },
1303
+ clientResolver: rpcEndpoint,
1304
+ });
1305
+
1306
+ const allQueries = {
1307
+ balance: balanceQuery,
1308
+ validators: validatorsQuery,
1309
+ delegations: delegationsQuery,
1310
+ rewards: rewardsQuery,
1311
+ };
1312
+
1313
+ const isLoading = Object.values(allQueries).some(
1314
+ ({ isLoading }) => isLoading,
1315
+ );
1316
+
1317
+ const data = useMemo(() => {
1318
+ if (isLoading) return;
1319
+
1320
+ return {
1321
+ balance: balanceQuery.data,
1322
+ validators: validatorsQuery.data,
1323
+ delegations: delegationsQuery.data,
1324
+ rewards: rewardsQuery.data,
1325
+ };
1326
+ }, [isLoading, balanceQuery.data, validatorsQuery.data, delegationsQuery.data, rewardsQuery.data]);
1327
+
1328
+ const refetch = () => {
1329
+ Object.values(allQueries).forEach((query) => query.refetch());
1330
+ };
1331
+
1332
+ return { data, isLoading, refetch };
1333
+ };
1334
+ `
1335
+ },
1336
+ {
1337
+ name: 'useValidators.ts',
1338
+ content: `import { useMemo } from 'react';
1339
+ import { BondStatus, bondStatusToJSON } from '${packageName}/cosmos/staking/v1beta1/staking';
1340
+ import { useGetValidators } from '${packageName}/cosmos/staking/v1beta1/query.rpc.react';
1341
+ import { defaultContext } from '@tanstack/react-query';
1342
+ import BigNumber from 'bignumber.js';
1343
+
1344
+ export const useValidators = (chainName: string) => {
1345
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1346
+
1347
+ const validatorsQuery = useGetValidators({
1348
+ request: {
1349
+ status: bondStatusToJSON(BondStatus.BOND_STATUS_BONDED),
1350
+ pagination: {
1351
+ key: new Uint8Array(),
1352
+ offset: 0n,
1353
+ limit: 200n,
1354
+ countTotal: true,
1355
+ reverse: false,
1356
+ },
1357
+ },
1358
+ options: {
1359
+ context: defaultContext,
1360
+ enabled: !!rpcEndpoint,
1361
+ select: ({ validators }) => {
1362
+ return validators
1363
+ .sort((a, b) => new BigNumber(b.tokens).minus(a.tokens).toNumber())
1364
+ .map((validator) => ({
1365
+ operatorAddress: validator.operatorAddress,
1366
+ moniker: validator.description?.moniker || '',
1367
+ tokens: validator.tokens,
1368
+ delegatorShares: validator.delegatorShares,
1369
+ commission: validator.commission?.commissionRates?.rate || '0',
1370
+ status: validator.status,
1371
+ jailed: validator.jailed,
1372
+ }));
1373
+ },
1374
+ },
1375
+ clientResolver: rpcEndpoint,
1376
+ customizedQueryKey: ['validators', chainName],
1377
+ });
1378
+
1379
+ return {
1380
+ data: validatorsQuery.data,
1381
+ isLoading: validatorsQuery.isLoading,
1382
+ refetch: validatorsQuery.refetch,
1383
+ };
1384
+ };
1385
+ `
1386
+ },
1387
+ {
1388
+ name: 'useVoting.ts',
1389
+ content: `import { useMemo } from 'react';
1390
+ import { useGetProposals } from '${packageName}/cosmos/gov/v1beta1/query.rpc.react';
1391
+ import { ProposalStatus, proposalStatusToJSON } from '${packageName}/cosmos/gov/v1beta1/gov';
1392
+ import { defaultContext } from '@tanstack/react-query';
1393
+
1394
+ export const useVoting = (chainName: string) => {
1395
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1396
+
1397
+ const proposalsQuery = useGetProposals({
1398
+ request: {
1399
+ proposalStatus: proposalStatusToJSON(ProposalStatus.PROPOSAL_STATUS_VOTING_PERIOD),
1400
+ voter: '',
1401
+ depositor: '',
1402
+ pagination: {
1403
+ key: new Uint8Array(),
1404
+ offset: 0n,
1405
+ limit: 50n,
1406
+ countTotal: true,
1407
+ reverse: true,
1408
+ },
1409
+ },
1410
+ options: {
1411
+ context: defaultContext,
1412
+ enabled: !!rpcEndpoint,
1413
+ select: ({ proposals }) => proposals,
1414
+ },
1415
+ clientResolver: rpcEndpoint,
1416
+ customizedQueryKey: ['proposals', chainName],
1417
+ });
1418
+
1419
+ const data = useMemo(() => {
1420
+ if (!proposalsQuery.data) return;
1421
+
1422
+ return {
1423
+ proposals: proposalsQuery.data.map((proposal) => ({
1424
+ proposalId: proposal.proposalId.toString(),
1425
+ title: proposal.content?.title || '',
1426
+ description: proposal.content?.description || '',
1427
+ status: proposal.status,
1428
+ submitTime: proposal.submitTime,
1429
+ votingStartTime: proposal.votingStartTime,
1430
+ votingEndTime: proposal.votingEndTime,
1431
+ })),
1432
+ };
1433
+ }, [proposalsQuery.data]);
1434
+
1435
+ return {
1436
+ data,
1437
+ isLoading: proposalsQuery.isLoading,
1438
+ refetch: proposalsQuery.refetch,
1439
+ };
1440
+ };
1441
+ `
1442
+ },
1443
+ {
1444
+ name: 'useVotingData.ts',
1445
+ content: `import { useMemo } from 'react';
1446
+ import { useChain } from '@interchain-kit/react';
1447
+ import {
1448
+ useGetProposals,
1449
+ useGetVote,
1450
+ useGetTallyResult,
1451
+ } from '${packageName}/cosmos/gov/v1beta1/query.rpc.react';
1452
+ import { ProposalStatus, proposalStatusToJSON } from '${packageName}/cosmos/gov/v1beta1/gov';
1453
+ import { defaultContext } from '@tanstack/react-query';
1454
+
1455
+ export const useVotingData = (chainName: string) => {
1456
+ const { address } = useChain(chainName);
1457
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1458
+
1459
+ const isEnabled = !!rpcEndpoint;
1460
+
1461
+ const proposalsQuery = useGetProposals({
1462
+ request: {
1463
+ proposalStatus: proposalStatusToJSON(ProposalStatus.PROPOSAL_STATUS_UNSPECIFIED),
1464
+ voter: '',
1465
+ depositor: '',
1466
+ pagination: {
1467
+ key: new Uint8Array(),
1468
+ offset: 0n,
1469
+ limit: 100n,
1470
+ countTotal: true,
1471
+ reverse: true,
1472
+ },
1473
+ },
1474
+ options: {
1475
+ context: defaultContext,
1476
+ enabled: isEnabled,
1477
+ select: ({ proposals }) => proposals,
1478
+ },
1479
+ clientResolver: rpcEndpoint,
1480
+ customizedQueryKey: ['allProposals', chainName],
1481
+ });
1482
+
1483
+ const activeProposals = useMemo(() => {
1484
+ return proposalsQuery.data?.filter(
1485
+ (proposal) => proposal.status === ProposalStatus.PROPOSAL_STATUS_VOTING_PERIOD
1486
+ ) || [];
1487
+ }, [proposalsQuery.data]);
1488
+
1489
+ const data = useMemo(() => {
1490
+ if (!proposalsQuery.data) return;
1491
+
1492
+ const categorized = {
1493
+ active: activeProposals,
1494
+ passed: proposalsQuery.data.filter(
1495
+ (p) => p.status === ProposalStatus.PROPOSAL_STATUS_PASSED
1496
+ ),
1497
+ rejected: proposalsQuery.data.filter(
1498
+ (p) => p.status === ProposalStatus.PROPOSAL_STATUS_REJECTED
1499
+ ),
1500
+ failed: proposalsQuery.data.filter(
1501
+ (p) => p.status === ProposalStatus.PROPOSAL_STATUS_FAILED
1502
+ ),
1503
+ };
1504
+
1505
+ return {
1506
+ proposals: proposalsQuery.data,
1507
+ categorized,
1508
+ activeCount: categorized.active.length,
1509
+ };
1510
+ }, [proposalsQuery.data, activeProposals]);
1511
+
1512
+ return {
1513
+ data,
1514
+ isLoading: proposalsQuery.isLoading,
1515
+ refetch: proposalsQuery.refetch,
1516
+ };
1517
+ };
1518
+ `
1519
+ },
1520
+ {
1521
+ name: 'useContractInfo.ts',
1522
+ content: `import { defaultContext } from '@tanstack/react-query';
1523
+ import { useGetContractInfo } from '${packageName}/cosmwasm/wasm/v1/query.rpc.react';
1524
+
1525
+ export const useContractInfo = ({
1526
+ contractAddress,
1527
+ enabled = true,
1528
+ }: {
1529
+ contractAddress: string;
1530
+ enabled?: boolean;
1531
+ }) => {
1532
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1533
+
1534
+ return useGetContractInfo({
1535
+ request: {
1536
+ address: contractAddress,
1537
+ },
1538
+ options: {
1539
+ enabled: !!contractAddress && !!rpcEndpoint && enabled,
1540
+ context: defaultContext,
1541
+ },
1542
+ clientResolver: rpcEndpoint,
1543
+ });
1544
+ };
1545
+ `
1546
+ },
1547
+ {
1548
+ name: 'useQueryContract.ts',
1549
+ content: `import { defaultContext } from '@tanstack/react-query';
1550
+ import { useGetSmartContractState } from '${packageName}/cosmwasm/wasm/v1/query.rpc.react';
1551
+
1552
+ export const useQueryContract = ({
1553
+ contractAddress,
1554
+ queryMsg,
1555
+ enabled = true,
1556
+ }: {
1557
+ contractAddress: string;
1558
+ queryMsg: object;
1559
+ enabled?: boolean;
1560
+ }) => {
1561
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1562
+
1563
+ return useGetSmartContractState({
1564
+ request: {
1565
+ address: contractAddress,
1566
+ queryData: new TextEncoder().encode(JSON.stringify(queryMsg)),
1567
+ },
1568
+ options: {
1569
+ enabled: !!contractAddress && !!queryMsg && !!rpcEndpoint && enabled,
1570
+ context: defaultContext,
1571
+ select: ({ data }) => {
1572
+ if (data) {
1573
+ return JSON.parse(new TextDecoder().decode(data));
1574
+ }
1575
+ return null;
1576
+ },
1577
+ },
1578
+ clientResolver: rpcEndpoint,
1579
+ });
1580
+ };
1581
+ `
1582
+ },
1583
+ {
1584
+ name: 'useCodeDetails.ts',
1585
+ content: `import { defaultContext } from '@tanstack/react-query';
1586
+ import { useGetCode } from '${packageName}/cosmwasm/wasm/v1/query.rpc.react';
1587
+
1588
+ export const useCodeDetails = ({
1589
+ codeId,
1590
+ enabled = true,
1591
+ }: {
1592
+ codeId: string | number;
1593
+ enabled?: boolean;
1594
+ }) => {
1595
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1596
+
1597
+ return useGetCode({
1598
+ request: {
1599
+ codeId: BigInt(codeId),
1600
+ },
1601
+ options: {
1602
+ enabled: !!codeId && !!rpcEndpoint && enabled,
1603
+ context: defaultContext,
1604
+ },
1605
+ clientResolver: rpcEndpoint,
1606
+ });
1607
+ };
1608
+ `
1609
+ },
1610
+ {
1611
+ name: 'useMyContracts.ts',
1612
+ content: `import { useMemo } from 'react';
1613
+ import { useChain } from '@interchain-kit/react';
1614
+ import { useGetContractsByCreator } from '${packageName}/cosmwasm/wasm/v1/query.rpc.react';
1615
+ import { defaultContext } from '@tanstack/react-query';
1616
+
1617
+ export const useMyContracts = (chainName: string) => {
1618
+ const { address } = useChain(chainName);
1619
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1620
+
1621
+ const contractsQuery = useGetContractsByCreator({
1622
+ request: {
1623
+ creatorAddress: address || '',
1624
+ pagination: {
1625
+ key: new Uint8Array(),
1626
+ offset: 0n,
1627
+ limit: 100n,
1628
+ countTotal: true,
1629
+ reverse: false,
1630
+ },
1631
+ },
1632
+ options: {
1633
+ enabled: !!address && !!rpcEndpoint,
1634
+ context: defaultContext,
1635
+ select: ({ contractAddresses }) => contractAddresses,
1636
+ },
1637
+ clientResolver: rpcEndpoint,
1638
+ });
1639
+
1640
+ const data = useMemo(() => {
1641
+ if (!contractsQuery.data) return;
1642
+
1643
+ return {
1644
+ contracts: contractsQuery.data.map((address) => ({
1645
+ address,
1646
+ label: \`Contract \${address.slice(0, 8)}...\`,
1647
+ })),
1648
+ count: contractsQuery.data.length,
1649
+ };
1650
+ }, [contractsQuery.data]);
1651
+
1652
+ return {
1653
+ data,
1654
+ isLoading: contractsQuery.isLoading,
1655
+ refetch: contractsQuery.refetch,
1656
+ };
1657
+ };
1658
+ `
1659
+ },
1660
+ {
1661
+ name: 'useGrants.ts',
1662
+ content: `import { useMemo } from 'react';
1663
+ import { useChain } from '@interchain-kit/react';
1664
+ import { useGetGranterGrants, useGetGranteeGrants } from '${packageName}/cosmos/authz/v1beta1/query.rpc.react';
1665
+ import { defaultContext } from '@tanstack/react-query';
1666
+
1667
+ export const useGrants = (chainName: string) => {
1668
+ const { address } = useChain(chainName);
1669
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1670
+
1671
+ const granterQuery = useGetGranterGrants({
1672
+ request: {
1673
+ granter: address || '',
1674
+ pagination: {
1675
+ key: new Uint8Array(),
1676
+ offset: 0n,
1677
+ limit: 100n,
1678
+ countTotal: true,
1679
+ reverse: false,
1680
+ },
1681
+ },
1682
+ options: {
1683
+ enabled: !!address && !!rpcEndpoint,
1684
+ context: defaultContext,
1685
+ select: ({ grants }) => grants,
1686
+ },
1687
+ clientResolver: rpcEndpoint,
1688
+ });
1689
+
1690
+ const granteeQuery = useGetGranteeGrants({
1691
+ request: {
1692
+ grantee: address || '',
1693
+ pagination: {
1694
+ key: new Uint8Array(),
1695
+ offset: 0n,
1696
+ limit: 100n,
1697
+ countTotal: true,
1698
+ reverse: false,
1699
+ },
1700
+ },
1701
+ options: {
1702
+ enabled: !!address && !!rpcEndpoint,
1703
+ context: defaultContext,
1704
+ select: ({ grants }) => grants,
1705
+ },
1706
+ clientResolver: rpcEndpoint,
1707
+ });
1708
+
1709
+ const data = useMemo(() => {
1710
+ return {
1711
+ granterGrants: granterQuery.data || [],
1712
+ granteeGrants: granteeQuery.data || [],
1713
+ };
1714
+ }, [granterQuery.data, granteeQuery.data]);
1715
+
1716
+ const isLoading = granterQuery.isLoading || granteeQuery.isLoading;
1717
+
1718
+ return {
1719
+ data,
1720
+ isLoading,
1721
+ refetch: () => {
1722
+ granterQuery.refetch();
1723
+ granteeQuery.refetch();
1724
+ },
1725
+ };
1726
+ };
1727
+ `
1728
+ },
1729
+ {
1730
+ name: 'useSendData.ts',
1731
+ content: `import { useMemo } from 'react';
1732
+ import { useChain } from '@interchain-kit/react';
1733
+ import { useGetBalance } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
1734
+ import { defaultContext } from '@tanstack/react-query';
1735
+ import BigNumber from 'bignumber.js';
1736
+
1737
+ export const useSendData = (chainName: string) => {
1738
+ const { address, assetList } = useChain(chainName);
1739
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1740
+
1741
+ const coin = assetList?.assets[0];
1742
+ const denom = coin?.base || 'uatom';
1743
+ const exponent = coin?.denomUnits?.find(unit => unit.denom === coin.display)?.exponent || 6;
1744
+
1745
+ const balanceQuery = useGetBalance({
1746
+ request: {
1747
+ address: address || '',
1748
+ denom,
1749
+ },
1750
+ options: {
1751
+ enabled: !!address && !!rpcEndpoint,
1752
+ context: defaultContext,
1753
+ select: ({ balance }) => {
1754
+ const amount = balance?.amount || '0';
1755
+ const displayAmount = new BigNumber(amount).dividedBy(Math.pow(10, exponent));
1756
+ return {
1757
+ amount,
1758
+ displayAmount: displayAmount.toString(),
1759
+ denom: balance?.denom || denom,
1760
+ };
1761
+ },
1762
+ },
1763
+ clientResolver: rpcEndpoint,
1764
+ });
1765
+
1766
+ const data = useMemo(() => {
1767
+ if (!balanceQuery.data) return;
1768
+
1769
+ return {
1770
+ balance: balanceQuery.data,
1771
+ canSend: new BigNumber(balanceQuery.data.amount).isGreaterThan(0),
1772
+ fee: {
1773
+ amount: '5000',
1774
+ displayAmount: new BigNumber('5000').dividedBy(Math.pow(10, exponent)).toString(),
1775
+ denom,
1776
+ },
1777
+ };
1778
+ }, [balanceQuery.data, denom, exponent]);
1779
+
1780
+ return {
1781
+ data,
1782
+ isLoading: balanceQuery.isLoading,
1783
+ refetch: balanceQuery.refetch,
1784
+ };
1785
+ };
1786
+ `
1787
+ },
1788
+ {
1789
+ name: 'useTotalAssets.ts',
1790
+ content: `import { useMemo } from 'react';
1791
+ import { useChain } from '@interchain-kit/react';
1792
+ import { useGetAllBalances } from '${packageName}/cosmos/bank/v1beta1/query.rpc.react';
1793
+ import { defaultContext } from '@tanstack/react-query';
1794
+ import BigNumber from 'bignumber.js';
1795
+
1796
+ export const getPagination = (limit: bigint) => ({
1797
+ key: new Uint8Array(),
1798
+ offset: 0n,
1799
+ limit,
1800
+ countTotal: true,
1801
+ reverse: false,
1802
+ });
1803
+
1804
+ export const useTotalAssets = (chainName: string) => {
1805
+ const { address, assetList } = useChain(chainName);
1806
+ const rpcEndpoint = 'https://cosmos-rpc.quickapi.com:443';
1807
+
1808
+ const allBalancesQuery = useGetAllBalances({
1809
+ request: {
1810
+ address: address || '',
1811
+ pagination: getPagination(100n),
1812
+ resolveDenom: false,
1813
+ },
1814
+ options: {
1815
+ enabled: !!address && !!rpcEndpoint,
1816
+ select: ({ balances }) => balances || [],
1817
+ context: defaultContext,
1818
+ },
1819
+ clientResolver: rpcEndpoint,
1820
+ customizedQueryKey: ['totalAssets', address],
1821
+ });
1822
+
1823
+ const data = useMemo(() => {
1824
+ if (!allBalancesQuery.data) return;
1825
+
1826
+ const totalValue = allBalancesQuery.data.reduce((sum, balance) => {
1827
+ return sum.plus(balance.amount);
1828
+ }, new BigNumber(0));
1829
+
1830
+ return {
1831
+ balances: allBalancesQuery.data,
1832
+ totalCount: allBalancesQuery.data.length,
1833
+ totalValue: totalValue.toString(),
1834
+ nonZeroBalances: allBalancesQuery.data.filter(
1835
+ balance => new BigNumber(balance.amount).isGreaterThan(0)
1836
+ ),
1837
+ };
1838
+ }, [allBalancesQuery.data]);
1839
+
1840
+ return {
1841
+ data,
1842
+ isLoading: allBalancesQuery.isLoading,
1843
+ refetch: allBalancesQuery.refetch,
1844
+ };
1845
+ };
1846
+ `
1847
+ }
1848
+ ];
1849
+ // Write all example files
1850
+ exampleFiles.forEach(({ name, content }) => {
1851
+ (0, fs_1.writeFileSync)((0, path_1.join)(mcpServerPath, 'src', 'telescope-examples', name), content);
1852
+ });
1853
+ }