@ic-reactor/mcp 0.0.0-stage → 0.0.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 (1041) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +108 -0
  2. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.yml +77 -0
  4. package/.github/actions/setup-rust-wasm/action.yml +25 -0
  5. package/.github/dependabot.yml +107 -0
  6. package/.github/workflows/auth-latest.yml +67 -0
  7. package/.github/workflows/b3pay-site.yml +49 -0
  8. package/.github/workflows/ci.yml +430 -0
  9. package/.github/workflows/codeql.yml +41 -0
  10. package/.github/workflows/dependency-review.yml +68 -0
  11. package/.github/workflows/docs-check.yml +98 -0
  12. package/.github/workflows/docs.yml +265 -0
  13. package/.github/workflows/e2e.yml +90 -0
  14. package/.github/workflows/examples-published.yml +97 -0
  15. package/.github/workflows/release.yml +326 -0
  16. package/.husky/pre-commit +12 -0
  17. package/.prettierignore +109 -0
  18. package/.prettierrc +6 -0
  19. package/AGENTS.md +103 -0
  20. package/CHANGELOG.md +3268 -0
  21. package/CLAUDE.md +93 -0
  22. package/CNAME +1 -0
  23. package/CODE_OF_CONDUCT.md +7 -0
  24. package/CONTRIBUTING.md +433 -0
  25. package/LICENSE +21 -0
  26. package/README.md +2 -2
  27. package/SECURITY.md +74 -0
  28. package/b3pay-module.json +194 -0
  29. package/docs/.remarkrc.json +10 -0
  30. package/docs/README.md +64 -0
  31. package/docs/astro.config.mjs +205 -0
  32. package/docs/favicon.svg +15 -0
  33. package/docs/package.json +39 -0
  34. package/docs/public/favicon.svg +15 -0
  35. package/docs/public/ic-reactor-social-card.png +0 -0
  36. package/docs/scripts/b3pay-static.mjs +22 -0
  37. package/docs/scripts/check-example-docs.mjs +214 -0
  38. package/docs/scripts/check-links.mjs +212 -0
  39. package/docs/scripts/fix-dist-links.js +125 -0
  40. package/docs/scripts/fix-frontmatter.js +71 -0
  41. package/docs/scripts/remove-redundant-h1.cjs +48 -0
  42. package/docs/scripts/rewrite-typedoc-links.js +110 -0
  43. package/docs/scripts/split-index.js +69 -0
  44. package/docs/src/assets/ic-reactor-hero-dark.svg +23 -0
  45. package/docs/src/assets/ic-reactor-hero-light.svg +23 -0
  46. package/docs/src/assets/ic-reactor-lockup-dark.svg +15 -0
  47. package/docs/src/assets/ic-reactor-lockup-light.svg +15 -0
  48. package/docs/src/assets/ic-reactor-mark-dark.svg +14 -0
  49. package/docs/src/assets/ic-reactor-mark-light.svg +14 -0
  50. package/docs/src/assets/layers/candid-core-layer-icon-dark.svg +4 -0
  51. package/docs/src/assets/layers/candid-core-layer-icon-light.svg +4 -0
  52. package/docs/src/assets/layers/candid-profile-layer-icon-dark.svg +4 -0
  53. package/docs/src/assets/layers/candid-profile-layer-icon-light.svg +4 -0
  54. package/docs/src/assets/layers/ic-reactor-layer-icon-dark.svg +4 -0
  55. package/docs/src/assets/layers/ic-reactor-layer-icon-light.svg +4 -0
  56. package/docs/src/components/LibraryCards.astro +172 -0
  57. package/docs/src/components/LibraryIcon.astro +28 -0
  58. package/docs/src/components/SiteTitle.astro +241 -0
  59. package/docs/src/content/docs/404.mdx +19 -0
  60. package/docs/src/content/docs/build/agent-tools.mdx +593 -0
  61. package/docs/src/content/docs/build/icrc1-wallet.mdx +619 -0
  62. package/docs/src/content/docs/build/ssr-per-user.mdx +552 -0
  63. package/docs/src/content/docs/examples/canister-studio.mdx +95 -0
  64. package/docs/src/content/docs/examples/icrc-ledger.mdx +45 -0
  65. package/docs/src/content/docs/examples/index.mdx +38 -0
  66. package/docs/src/content/docs/examples/next-ssr.mdx +73 -0
  67. package/docs/src/content/docs/examples/node-agent-tool.mdx +80 -0
  68. package/docs/src/content/docs/examples/vite-wallet.mdx +71 -0
  69. package/docs/src/content/docs/guides/auth.mdx +1181 -0
  70. package/docs/src/content/docs/guides/client.mdx +551 -0
  71. package/docs/src/content/docs/guides/deploy.mdx +180 -0
  72. package/docs/src/content/docs/guides/errors.mdx +475 -0
  73. package/docs/src/content/docs/guides/getting-started.mdx +620 -0
  74. package/docs/src/content/docs/guides/reads.mdx +586 -0
  75. package/docs/src/content/docs/guides/ssr.mdx +529 -0
  76. package/docs/src/content/docs/guides/testing.mdx +401 -0
  77. package/docs/src/content/docs/guides/values.mdx +261 -0
  78. package/docs/src/content/docs/guides/vite-plugin.mdx +690 -0
  79. package/docs/src/content/docs/guides/writes.mdx +572 -0
  80. package/docs/src/content/docs/ic-reactor/index.mdx +167 -0
  81. package/docs/src/content/docs/index.mdx +65 -0
  82. package/docs/src/content/docs/migrating-from-3.mdx +535 -0
  83. package/docs/src/content/docs/packages/core.mdx +186 -0
  84. package/docs/src/content/docs/packages/mcp.mdx +163 -0
  85. package/docs/src/content/docs/packages/react.mdx +207 -0
  86. package/docs/src/content/docs/packages/vite-plugin.mdx +73 -0
  87. package/docs/src/content/docs/versioning.mdx +104 -0
  88. package/docs/src/content.config.ts +7 -0
  89. package/docs/src/styles/custom.css +189 -0
  90. package/docs/tsconfig.typedoc.json +26 -0
  91. package/docs/typedoc-entry.ts +17 -0
  92. package/docs/typedoc.json +37 -0
  93. package/e2e/Cargo.lock +646 -0
  94. package/e2e/Cargo.toml +3 -0
  95. package/e2e/README.md +101 -0
  96. package/e2e/frontends/build.mjs +94 -0
  97. package/e2e/frontends/index.html +10 -0
  98. package/e2e/global-setup.ts +65 -0
  99. package/e2e/icp.yaml +38 -0
  100. package/e2e/package.json +40 -0
  101. package/e2e/setup.ts +6 -0
  102. package/e2e/src/actor/Cargo.toml +14 -0
  103. package/e2e/src/actor/hello_actor.did +10 -0
  104. package/e2e/src/actor/src/lib.rs +73 -0
  105. package/e2e/src/calls.test.ts +132 -0
  106. package/e2e/src/declarations/hello_actor.envelope.json +175 -0
  107. package/e2e/src/declarations/hello_actor.ts +15 -0
  108. package/e2e/src/errors.test.ts +107 -0
  109. package/e2e/src/frontend-headers.test.ts +253 -0
  110. package/e2e/src/identity.test.ts +61 -0
  111. package/e2e/src/react.test.tsx +59 -0
  112. package/e2e/src/replica.ts +70 -0
  113. package/e2e/src/vite-env.test.ts +108 -0
  114. package/e2e/test.sh +47 -0
  115. package/e2e/tsconfig.json +20 -0
  116. package/e2e/tsconfig.typecheck.json +9 -0
  117. package/e2e/vitest.config.ts +22 -0
  118. package/eslint.config.mjs +100 -0
  119. package/evals/PREREGISTRATION.md +1346 -0
  120. package/evals/README.md +756 -0
  121. package/evals/conditions/thin/condition.json +8 -0
  122. package/evals/conditions/thin/docs/candid-core-cli.README.md +90 -0
  123. package/evals/conditions/thin/docs/candid-core-schema.README.md +339 -0
  124. package/evals/conditions/thin/package.json +25 -0
  125. package/evals/conditions/thin/starter/src/generated/icrc1.ts +57 -0
  126. package/evals/conditions/thin-guide/condition.json +10 -0
  127. package/evals/conditions/thin-guide/docs/llms.txt +292 -0
  128. package/evals/conditions/v3/condition.json +9 -0
  129. package/evals/conditions/v3/docs/ic-reactor-core.llms.txt +232 -0
  130. package/evals/conditions/v3/docs/ic-reactor-react.llms.txt +280 -0
  131. package/evals/conditions/v3/docs/llms-full.txt +1053 -0
  132. package/evals/conditions/v3/package.json +26 -0
  133. package/evals/conditions/v3/starter/src/declarations/icrc1.did.d.ts +95 -0
  134. package/evals/conditions/v3/starter/src/declarations/icrc1.did.js +140 -0
  135. package/evals/conditions/v4/PORTING.md +384 -0
  136. package/evals/conditions/v4/README.md +106 -0
  137. package/evals/conditions/v4/condition.json +5 -0
  138. package/evals/conditions/v4/docs/llms.txt +323 -0
  139. package/evals/conditions/v4/package.json +27 -0
  140. package/evals/conditions/v4/starter/src/generated/icrc1.ts +78 -0
  141. package/evals/conditions/v4-proto/condition.json +6 -0
  142. package/evals/conditions/v4-proto/docs/llms.txt +291 -0
  143. package/evals/conditions/v4-proto/lib/SHIM-NOTES.md +20 -0
  144. package/evals/conditions/v4-proto/lib/package.json +27 -0
  145. package/evals/conditions/v4-proto/lib/src/client.ts +471 -0
  146. package/evals/conditions/v4-proto/lib/src/errors.ts +214 -0
  147. package/evals/conditions/v4-proto/lib/src/index.ts +36 -0
  148. package/evals/conditions/v4-proto/lib/src/principal.ts +175 -0
  149. package/evals/conditions/v4-proto/lib/src/service.ts +69 -0
  150. package/evals/conditions/v4-proto/lib/src/types.ts +174 -0
  151. package/evals/conditions/v4-proto/lib/test/runtime.test.ts +170 -0
  152. package/evals/conditions/v4-proto/lib/test/tsconfig.json +10 -0
  153. package/evals/conditions/v4-proto/lib/test/types.test-d.ts +145 -0
  154. package/evals/conditions/v4-proto/lib/test/vitest.config.mjs +8 -0
  155. package/evals/conditions/v4-proto/lib/tsconfig.json +17 -0
  156. package/evals/conditions/v4-proto/package.json +26 -0
  157. package/evals/conditions/v4-proto/starter/src/generated/icrc1.service.ts +19 -0
  158. package/evals/conditions/v4-proto/starter/src/generated/icrc1.ts +57 -0
  159. package/evals/drive.mjs +1221 -0
  160. package/evals/gate.mjs +161 -0
  161. package/evals/harness/aggregate.mjs +534 -0
  162. package/evals/harness/aggregate.test.mjs +344 -0
  163. package/evals/harness/assemble.mjs +216 -0
  164. package/evals/harness/assemble.test.mjs +143 -0
  165. package/evals/harness/auth.mjs +91 -0
  166. package/evals/harness/check-docs.mjs +157 -0
  167. package/evals/harness/declarations/icrc1.did.d.ts +95 -0
  168. package/evals/harness/declarations/icrc1.did.js +140 -0
  169. package/evals/harness/drive-auth.test.mjs +584 -0
  170. package/evals/harness/drive.test.mjs +509 -0
  171. package/evals/harness/fake-auth.ts +67 -0
  172. package/evals/harness/fake-ledger.ts +178 -0
  173. package/evals/harness/gate-plan.mjs +104 -0
  174. package/evals/harness/gate-plan.test.mjs +243 -0
  175. package/evals/harness/icrc1.did +88 -0
  176. package/evals/harness/judge.mjs +63 -0
  177. package/evals/harness/judge.test.mjs +81 -0
  178. package/evals/harness/leak-scan.mjs +1373 -0
  179. package/evals/harness/leak-scan.test.mjs +1300 -0
  180. package/evals/harness/probes/amounts.ts +14 -0
  181. package/evals/harness/probes/node-tool.probe.ts +48 -0
  182. package/evals/harness/probes/probe.mjs +149 -0
  183. package/evals/harness/probes/react-wallet.probe.ts +96 -0
  184. package/evals/harness/public/support/auth.ts +38 -0
  185. package/evals/harness/public/support/fake-replica.d.ts +28 -0
  186. package/evals/harness/public/support/fake-replica.js +434 -0
  187. package/evals/harness/public/support/ledger.idl.d.ts +95 -0
  188. package/evals/harness/public/support/ledger.idl.js +140 -0
  189. package/evals/harness/public/support/world.ts +179 -0
  190. package/evals/harness/runs.mjs +139 -0
  191. package/evals/harness/sandbox.mjs +88 -0
  192. package/evals/harness/sandbox.test.mjs +134 -0
  193. package/evals/harness/ship.mjs +264 -0
  194. package/evals/harness/ship.test.mjs +552 -0
  195. package/evals/harness/world.ts +291 -0
  196. package/evals/package.json +26 -0
  197. package/evals/pnpm-lock.yaml +1537 -0
  198. package/evals/pnpm-workspace.yaml +12 -0
  199. package/evals/results/2026-09-30T14-22-05-924Z/pilot.json +384 -0
  200. package/evals/results/2026-09-30T14-22-05-924Z/pilot.rescanned.json +404 -0
  201. package/evals/results/2026-09-30T14-22-05-924Z/pilot.rescanned.rescored.json +404 -0
  202. package/evals/results/2026-09-30T14-22-05-924Z/plan.json +240 -0
  203. package/evals/results/2026-09-30T14-22-05-924Z/summary.json +1800 -0
  204. package/evals/results/2026-09-30T14-22-05-924Z/summary.rescanned.json +1843 -0
  205. package/evals/results/2026-09-30T14-22-05-924Z/summary.rescanned.rescored.json +2100 -0
  206. package/evals/results/2026-09-30T15-48-23-343Z/pilot.json +404 -0
  207. package/evals/results/2026-09-30T15-48-23-343Z/pilot.rescored.json +404 -0
  208. package/evals/results/2026-09-30T15-48-23-343Z/plan.json +242 -0
  209. package/evals/results/2026-09-30T15-48-23-343Z/summary.json +1843 -0
  210. package/evals/results/2026-09-30T15-48-23-343Z/summary.rescored.json +2195 -0
  211. package/evals/results/2026-10-03-beta1-gate/pilot.json +162 -0
  212. package/evals/results/2026-10-03-beta1-gate/plan.json +141 -0
  213. package/evals/results/2026-10-03-beta1-gate/summary.json +983 -0
  214. package/evals/results/2026-10-05-ga-gate/contaminated-run.json +55 -0
  215. package/evals/results/2026-10-05-ga-gate/pilot.json +162 -0
  216. package/evals/results/2026-10-05-ga-gate/plan.json +457 -0
  217. package/evals/results/2026-10-05-ga-gate/summary.json +1037 -0
  218. package/evals/results/2026-10-05-ga-gate/summary.rescanned.json +1037 -0
  219. package/evals/results/README.md +31 -0
  220. package/evals/runs-pilot.log +150 -0
  221. package/evals/runs-pilot2.log +150 -0
  222. package/evals/score.mjs +256 -0
  223. package/evals/setup.mjs +547 -0
  224. package/evals/tasks/node-tool/faulty/thin-accepts-exponent/meta.json +5 -0
  225. package/evals/tasks/node-tool/faulty/thin-accepts-exponent/src/index.ts +121 -0
  226. package/evals/tasks/node-tool/faulty/thin-anonymous-transfer/meta.json +5 -0
  227. package/evals/tasks/node-tool/faulty/thin-anonymous-transfer/src/index.ts +116 -0
  228. package/evals/tasks/node-tool/faulty/thin-every-reject-may-have-executed/meta.json +9 -0
  229. package/evals/tasks/node-tool/faulty/thin-every-reject-may-have-executed/src/index.ts +118 -0
  230. package/evals/tasks/node-tool/faulty/thin-fetches-root-key-off-local/meta.json +5 -0
  231. package/evals/tasks/node-tool/faulty/thin-fetches-root-key-off-local/src/index.ts +118 -0
  232. package/evals/tasks/node-tool/faulty/thin-ignores-root-key/meta.json +5 -0
  233. package/evals/tasks/node-tool/faulty/thin-ignores-root-key/src/index.ts +117 -0
  234. package/evals/tasks/node-tool/faulty/thin-misclassifies-reject-codes/meta.json +9 -0
  235. package/evals/tasks/node-tool/faulty/thin-misclassifies-reject-codes/src/index.ts +119 -0
  236. package/evals/tasks/node-tool/faulty/thin-no-nat64-cap/meta.json +9 -0
  237. package/evals/tasks/node-tool/faulty/thin-no-nat64-cap/src/index.ts +118 -0
  238. package/evals/tasks/node-tool/faulty/thin-number-amount/meta.json +10 -0
  239. package/evals/tasks/node-tool/faulty/thin-number-amount/src/index.ts +117 -0
  240. package/evals/tasks/node-tool/faulty/thin-truncates-fraction-digits/meta.json +5 -0
  241. package/evals/tasks/node-tool/faulty/thin-truncates-fraction-digits/src/index.ts +120 -0
  242. package/evals/tasks/node-tool/faulty/thin-unvalidated-recipient/meta.json +5 -0
  243. package/evals/tasks/node-tool/faulty/thin-unvalidated-recipient/src/index.ts +118 -0
  244. package/evals/tasks/node-tool/faulty/v3-retry-call-errors/meta.json +11 -0
  245. package/evals/tasks/node-tool/faulty/v3-retry-call-errors/src/index.ts +149 -0
  246. package/evals/tasks/node-tool/faulty/v4-anonymous-identity-sent/meta.json +5 -0
  247. package/evals/tasks/node-tool/faulty/v4-anonymous-identity-sent/src/index.ts +71 -0
  248. package/evals/tasks/node-tool/faulty/v4-never-may-have-executed/meta.json +9 -0
  249. package/evals/tasks/node-tool/faulty/v4-never-may-have-executed/src/index.ts +84 -0
  250. package/evals/tasks/node-tool/faulty/v4-proto-never-may-have-executed/meta.json +9 -0
  251. package/evals/tasks/node-tool/faulty/v4-proto-never-may-have-executed/src/index.ts +72 -0
  252. package/evals/tasks/node-tool/faulty/v4-proto-refuses-nat64-max/meta.json +5 -0
  253. package/evals/tasks/node-tool/faulty/v4-proto-refuses-nat64-max/src/index.ts +72 -0
  254. package/evals/tasks/node-tool/faulty/v4-refuses-nat64-max/meta.json +5 -0
  255. package/evals/tasks/node-tool/faulty/v4-refuses-nat64-max/src/index.ts +84 -0
  256. package/evals/tasks/node-tool/hidden/node-tool.test.ts +312 -0
  257. package/evals/tasks/node-tool/prompt.md +55 -0
  258. package/evals/tasks/node-tool/prompt.minimal.md +30 -0
  259. package/evals/tasks/node-tool/solutions/thin/reference/src/index.ts +118 -0
  260. package/evals/tasks/node-tool/solutions/thin/reference-module-scope/src/index.ts +145 -0
  261. package/evals/tasks/node-tool/solutions/thin-guide/reference/src/index.ts +118 -0
  262. package/evals/tasks/node-tool/solutions/thin-guide/reference-module-scope/src/index.ts +145 -0
  263. package/evals/tasks/node-tool/solutions/v3/reference/src/index.ts +140 -0
  264. package/evals/tasks/node-tool/solutions/v3/reference-module-scope/src/index.ts +153 -0
  265. package/evals/tasks/node-tool/solutions/v4/reference/src/index.ts +84 -0
  266. package/evals/tasks/node-tool/solutions/v4/reference-module-scope/src/index.ts +105 -0
  267. package/evals/tasks/node-tool/solutions/v4-proto/reference/src/index.ts +72 -0
  268. package/evals/tasks/node-tool/solutions/v4-proto/reference-module-scope/src/index.ts +87 -0
  269. package/evals/tasks/node-tool/starter/src/contract.ts +31 -0
  270. package/evals/tasks/node-tool/starter/src/index.ts +7 -0
  271. package/evals/tasks/node-tool/starter/test/smoke.test.ts +22 -0
  272. package/evals/tasks/node-tool/starter/tsconfig.json +17 -0
  273. package/evals/tasks/node-tool/task.json +63 -0
  274. package/evals/tasks/react-wallet/faulty/thin-accepts-exponent/meta.json +5 -0
  275. package/evals/tasks/react-wallet/faulty/thin-accepts-exponent/src/Wallet.tsx +216 -0
  276. package/evals/tasks/react-wallet/faulty/thin-anonymous-transfer/meta.json +5 -0
  277. package/evals/tasks/react-wallet/faulty/thin-anonymous-transfer/src/Wallet.tsx +212 -0
  278. package/evals/tasks/react-wallet/faulty/thin-both-auth-buttons/meta.json +5 -0
  279. package/evals/tasks/react-wallet/faulty/thin-both-auth-buttons/src/Wallet.tsx +210 -0
  280. package/evals/tasks/react-wallet/faulty/thin-constant-balance-key/meta.json +8 -0
  281. package/evals/tasks/react-wallet/faulty/thin-constant-balance-key/src/Wallet.tsx +213 -0
  282. package/evals/tasks/react-wallet/faulty/thin-no-nat64-cap/meta.json +9 -0
  283. package/evals/tasks/react-wallet/faulty/thin-no-nat64-cap/src/Wallet.tsx +213 -0
  284. package/evals/tasks/react-wallet/faulty/thin-number-balance/meta.json +5 -0
  285. package/evals/tasks/react-wallet/faulty/thin-number-balance/src/Wallet.tsx +213 -0
  286. package/evals/tasks/react-wallet/faulty/thin-transfer-as-query/meta.json +5 -0
  287. package/evals/tasks/react-wallet/faulty/thin-transfer-as-query/src/Wallet.tsx +254 -0
  288. package/evals/tasks/react-wallet/faulty/thin-truncates-fraction-digits/meta.json +5 -0
  289. package/evals/tasks/react-wallet/faulty/thin-truncates-fraction-digits/src/Wallet.tsx +215 -0
  290. package/evals/tasks/react-wallet/faulty/thin-unguarded-balance-effect/meta.json +5 -0
  291. package/evals/tasks/react-wallet/faulty/thin-unguarded-balance-effect/src/Wallet.tsx +214 -0
  292. package/evals/tasks/react-wallet/faulty/v3-http-4xx-unknown/meta.json +5 -0
  293. package/evals/tasks/react-wallet/faulty/v3-http-4xx-unknown/src/Wallet.tsx +224 -0
  294. package/evals/tasks/react-wallet/faulty/v3-mutation-retry-3/meta.json +12 -0
  295. package/evals/tasks/react-wallet/faulty/v3-mutation-retry-3/src/Wallet.tsx +225 -0
  296. package/evals/tasks/react-wallet/faulty/v3-unknown-as-error/meta.json +11 -0
  297. package/evals/tasks/react-wallet/faulty/v3-unknown-as-error/src/Wallet.tsx +182 -0
  298. package/evals/tasks/react-wallet/faulty/v4-every-reject-unknown/meta.json +5 -0
  299. package/evals/tasks/react-wallet/faulty/v4-every-reject-unknown/src/Wallet.tsx +160 -0
  300. package/evals/tasks/react-wallet/faulty/v4-keep-previous-data/meta.json +5 -0
  301. package/evals/tasks/react-wallet/faulty/v4-keep-previous-data/src/Wallet.tsx +166 -0
  302. package/evals/tasks/react-wallet/faulty/v4-proto-every-reject-unknown/meta.json +5 -0
  303. package/evals/tasks/react-wallet/faulty/v4-proto-every-reject-unknown/src/Wallet.tsx +161 -0
  304. package/evals/tasks/react-wallet/faulty/v4-proto-keep-previous-data/meta.json +5 -0
  305. package/evals/tasks/react-wallet/faulty/v4-proto-keep-previous-data/src/Wallet.tsx +163 -0
  306. package/evals/tasks/react-wallet/faulty/v4-proto-retry-spread/meta.json +12 -0
  307. package/evals/tasks/react-wallet/faulty/v4-proto-retry-spread/src/Wallet.tsx +162 -0
  308. package/evals/tasks/react-wallet/faulty/v4-proto-status-not-idle/meta.json +5 -0
  309. package/evals/tasks/react-wallet/faulty/v4-proto-status-not-idle/src/Wallet.tsx +163 -0
  310. package/evals/tasks/react-wallet/faulty/v4-retry-spread/meta.json +12 -0
  311. package/evals/tasks/react-wallet/faulty/v4-retry-spread/src/Wallet.tsx +163 -0
  312. package/evals/tasks/react-wallet/faulty/v4-status-not-idle/meta.json +5 -0
  313. package/evals/tasks/react-wallet/faulty/v4-status-not-idle/src/Wallet.tsx +162 -0
  314. package/evals/tasks/react-wallet/hidden/react-wallet.test.ts +536 -0
  315. package/evals/tasks/react-wallet/prompt.md +88 -0
  316. package/evals/tasks/react-wallet/prompt.minimal.md +51 -0
  317. package/evals/tasks/react-wallet/solutions/thin/reference/src/Wallet.tsx +213 -0
  318. package/evals/tasks/react-wallet/solutions/thin/reference-module-scope/src/Wallet.tsx +227 -0
  319. package/evals/tasks/react-wallet/solutions/thin-guide/reference/src/Wallet.tsx +213 -0
  320. package/evals/tasks/react-wallet/solutions/thin-guide/reference-module-scope/src/Wallet.tsx +227 -0
  321. package/evals/tasks/react-wallet/solutions/v3/reference/src/Wallet.tsx +224 -0
  322. package/evals/tasks/react-wallet/solutions/v3/reference-module-scope/src/Wallet.tsx +230 -0
  323. package/evals/tasks/react-wallet/solutions/v4/reference/src/Wallet.tsx +160 -0
  324. package/evals/tasks/react-wallet/solutions/v4/reference-module-scope/src/Wallet.tsx +178 -0
  325. package/evals/tasks/react-wallet/solutions/v4-proto/reference/src/Wallet.tsx +161 -0
  326. package/evals/tasks/react-wallet/solutions/v4-proto/reference-module-scope/src/Wallet.tsx +161 -0
  327. package/evals/tasks/react-wallet/starter/src/Wallet.tsx +12 -0
  328. package/evals/tasks/react-wallet/starter/src/auth.ts +16 -0
  329. package/evals/tasks/react-wallet/starter/src/config.ts +14 -0
  330. package/evals/tasks/react-wallet/starter/src/ii-auth.ts +43 -0
  331. package/evals/tasks/react-wallet/starter/src/main.tsx +15 -0
  332. package/evals/tasks/react-wallet/starter/test/smoke.test.ts +34 -0
  333. package/evals/tasks/react-wallet/starter/tsconfig.json +18 -0
  334. package/evals/tasks/react-wallet/task.json +84 -0
  335. package/examples/canister-studio/.stackblitzrc +4 -0
  336. package/examples/canister-studio/README.md +183 -0
  337. package/examples/canister-studio/did/ckbtc_minter.did +806 -0
  338. package/examples/canister-studio/did/icp_ledger.did +586 -0
  339. package/examples/canister-studio/did/icrc1.did +88 -0
  340. package/examples/canister-studio/package.json +45 -0
  341. package/examples/canister-studio/scripts/smoke.ts +188 -0
  342. package/examples/canister-studio/src/calls/CacheKeyPanel.tsx +104 -0
  343. package/examples/canister-studio/src/calls/ConfirmWrite.tsx +265 -0
  344. package/examples/canister-studio/src/calls/ErrorPanel.test.tsx +113 -0
  345. package/examples/canister-studio/src/calls/ErrorPanel.tsx +214 -0
  346. package/examples/canister-studio/src/calls/MethodRunner.test.tsx +354 -0
  347. package/examples/canister-studio/src/calls/MethodRunner.tsx +57 -0
  348. package/examples/canister-studio/src/calls/ReadRunner.tsx +244 -0
  349. package/examples/canister-studio/src/calls/ResendPanel.tsx +165 -0
  350. package/examples/canister-studio/src/calls/ShareLink.tsx +59 -0
  351. package/examples/canister-studio/src/calls/WriteRunner.test.tsx +678 -0
  352. package/examples/canister-studio/src/calls/WriteRunner.tsx +670 -0
  353. package/examples/canister-studio/src/calls/dedupe.ts +189 -0
  354. package/examples/canister-studio/src/calls/error-info.ts +168 -0
  355. package/examples/canister-studio/src/calls/history.test.ts +284 -0
  356. package/examples/canister-studio/src/calls/history.ts +287 -0
  357. package/examples/canister-studio/src/calls/kinds.ts +68 -0
  358. package/examples/canister-studio/src/calls/prepare.ts +32 -0
  359. package/examples/canister-studio/src/calls/query-options.ts +30 -0
  360. package/examples/canister-studio/src/calls/read.ts +47 -0
  361. package/examples/canister-studio/src/calls/readback.ts +100 -0
  362. package/examples/canister-studio/src/calls/record.ts +123 -0
  363. package/examples/canister-studio/src/calls/safe-calls.test.ts +299 -0
  364. package/examples/canister-studio/src/calls/share.ts +46 -0
  365. package/examples/canister-studio/src/calls/testing/doubles.tsx +108 -0
  366. package/examples/canister-studio/src/calls/testing/fixtures.ts +185 -0
  367. package/examples/canister-studio/src/calls/useCanisterHandle.ts +35 -0
  368. package/examples/canister-studio/src/canisters/ckbtc_minter.envelope.json +4228 -0
  369. package/examples/canister-studio/src/canisters/ckbtc_minter.ts +868 -0
  370. package/examples/canister-studio/src/canisters/icp_ledger.envelope.json +3454 -0
  371. package/examples/canister-studio/src/canisters/icp_ledger.ts +584 -0
  372. package/examples/canister-studio/src/canisters/icrc1.envelope.json +840 -0
  373. package/examples/canister-studio/src/canisters/icrc1.ts +78 -0
  374. package/examples/canister-studio/src/components/ActionButton.tsx +32 -0
  375. package/examples/canister-studio/src/components/AppHeader.tsx +83 -0
  376. package/examples/canister-studio/src/components/AppShell.tsx +29 -0
  377. package/examples/canister-studio/src/components/AuthButton.tsx +79 -0
  378. package/examples/canister-studio/src/components/Badge.tsx +79 -0
  379. package/examples/canister-studio/src/components/CanisterHeader.tsx +200 -0
  380. package/examples/canister-studio/src/components/CanisterJump.tsx +130 -0
  381. package/examples/canister-studio/src/components/Card.tsx +64 -0
  382. package/examples/canister-studio/src/components/Code.tsx +101 -0
  383. package/examples/canister-studio/src/components/CopyButton.tsx +126 -0
  384. package/examples/canister-studio/src/components/Disclosure.tsx +34 -0
  385. package/examples/canister-studio/src/components/EmptyState.tsx +34 -0
  386. package/examples/canister-studio/src/components/MethodList.test.tsx +137 -0
  387. package/examples/canister-studio/src/components/MethodList.tsx +244 -0
  388. package/examples/canister-studio/src/components/Notice.tsx +36 -0
  389. package/examples/canister-studio/src/components/ProvenanceBadge.tsx +44 -0
  390. package/examples/canister-studio/src/components/RouteError.tsx +42 -0
  391. package/examples/canister-studio/src/components/SectionBoundary.tsx +76 -0
  392. package/examples/canister-studio/src/components/Spinner.tsx +33 -0
  393. package/examples/canister-studio/src/components/Tabs.tsx +96 -0
  394. package/examples/canister-studio/src/components/canister/CanisterLoadFailure.test.tsx +56 -0
  395. package/examples/canister-studio/src/components/canister/CanisterLoadFailure.tsx +165 -0
  396. package/examples/canister-studio/src/components/canister/CanisterNotFound.tsx +59 -0
  397. package/examples/canister-studio/src/components/canister/CanisterPending.tsx +33 -0
  398. package/examples/canister-studio/src/components/canister/MethodOverview.tsx +93 -0
  399. package/examples/canister-studio/src/components/canister/MethodWorkspace.test.tsx +201 -0
  400. package/examples/canister-studio/src/components/canister/MethodWorkspace.tsx +187 -0
  401. package/examples/canister-studio/src/components/canister/shared-call.test.ts +186 -0
  402. package/examples/canister-studio/src/components/canister/shared-call.ts +133 -0
  403. package/examples/canister-studio/src/components/canister/shared-link-loader.test.ts +116 -0
  404. package/examples/canister-studio/src/components/canister/use-canister-page.ts +44 -0
  405. package/examples/canister-studio/src/components/canister/workspace-key.test.ts +27 -0
  406. package/examples/canister-studio/src/components/canister/workspace-key.ts +36 -0
  407. package/examples/canister-studio/src/components/canister-id-input.ts +69 -0
  408. package/examples/canister-studio/src/components/canister-names.ts +11 -0
  409. package/examples/canister-studio/src/components/download.ts +34 -0
  410. package/examples/canister-studio/src/components/fallbacks.tsx +33 -0
  411. package/examples/canister-studio/src/components/helpers.test.ts +107 -0
  412. package/examples/canister-studio/src/components/history/HistoryList.tsx +284 -0
  413. package/examples/canister-studio/src/components/home/FeaturedLedger.tsx +149 -0
  414. package/examples/canister-studio/src/components/home/OpenCanister.tsx +99 -0
  415. package/examples/canister-studio/src/components/home/featured.test.tsx +92 -0
  416. package/examples/canister-studio/src/components/home/featured.ts +64 -0
  417. package/examples/canister-studio/src/components/interface/CandidTab.tsx +38 -0
  418. package/examples/canister-studio/src/components/interface/CompatReport.tsx +92 -0
  419. package/examples/canister-studio/src/components/interface/CompatibilityTab.tsx +190 -0
  420. package/examples/canister-studio/src/components/interface/ProjectTab.tsx +196 -0
  421. package/examples/canister-studio/src/components/interface/TypeScriptTab.tsx +114 -0
  422. package/examples/canister-studio/src/components/interface/tools.test.tsx +169 -0
  423. package/examples/canister-studio/src/components/modes.ts +31 -0
  424. package/examples/canister-studio/src/components/playground/MethodPicker.tsx +67 -0
  425. package/examples/canister-studio/src/components/playground/PlaygroundForms.tsx +112 -0
  426. package/examples/canister-studio/src/components/playground/PlaygroundTools.tsx +219 -0
  427. package/examples/canister-studio/src/components/playground/sample.ts +43 -0
  428. package/examples/canister-studio/src/components/playground/target.test.tsx +86 -0
  429. package/examples/canister-studio/src/components/primitives.test.tsx +121 -0
  430. package/examples/canister-studio/src/components/provenance.ts +38 -0
  431. package/examples/canister-studio/src/components/route-render.test.tsx +71 -0
  432. package/examples/canister-studio/src/components/use-task.ts +56 -0
  433. package/examples/canister-studio/src/components/wallet/BalancePanel.tsx +110 -0
  434. package/examples/canister-studio/src/components/wallet/LedgerSummary.tsx +63 -0
  435. package/examples/canister-studio/src/components/wallet/MinterPanel.tsx +255 -0
  436. package/examples/canister-studio/src/components/wallet/SendPanel.test.tsx +297 -0
  437. package/examples/canister-studio/src/components/wallet/SendPanel.tsx +446 -0
  438. package/examples/canister-studio/src/components/wallet/ledgers.test.ts +36 -0
  439. package/examples/canister-studio/src/components/wallet/ledgers.ts +111 -0
  440. package/examples/canister-studio/src/forms/JsonPanel.tsx +157 -0
  441. package/examples/canister-studio/src/forms/MethodForm.test.tsx +369 -0
  442. package/examples/canister-studio/src/forms/MethodForm.tsx +368 -0
  443. package/examples/canister-studio/src/forms/TypedForm.tsx +55 -0
  444. package/examples/canister-studio/src/forms/context.ts +62 -0
  445. package/examples/canister-studio/src/forms/convert.ts +131 -0
  446. package/examples/canister-studio/src/forms/edge.test.ts +252 -0
  447. package/examples/canister-studio/src/forms/engine.test.ts +358 -0
  448. package/examples/canister-studio/src/forms/engine.ts +1492 -0
  449. package/examples/canister-studio/src/forms/fields/BytesField.tsx +210 -0
  450. package/examples/canister-studio/src/forms/fields/Field.tsx +106 -0
  451. package/examples/canister-studio/src/forms/fields/FieldShell.tsx +101 -0
  452. package/examples/canister-studio/src/forms/fields/Group.tsx +74 -0
  453. package/examples/canister-studio/src/forms/fields/ListField.tsx +256 -0
  454. package/examples/canister-studio/src/forms/fields/Segmented.tsx +78 -0
  455. package/examples/canister-studio/src/forms/fields/TimestampField.tsx +108 -0
  456. package/examples/canister-studio/src/forms/fields/UnitsField.tsx +119 -0
  457. package/examples/canister-studio/src/forms/fields/composites.tsx +389 -0
  458. package/examples/canister-studio/src/forms/fields/leaves.tsx +350 -0
  459. package/examples/canister-studio/src/forms/fields.test.tsx +396 -0
  460. package/examples/canister-studio/src/forms/helpers.test.ts +225 -0
  461. package/examples/canister-studio/src/forms/hints.ts +128 -0
  462. package/examples/canister-studio/src/forms/json.ts +119 -0
  463. package/examples/canister-studio/src/forms/parsing.test.ts +217 -0
  464. package/examples/canister-studio/src/forms/useMethodForm.ts +251 -0
  465. package/examples/canister-studio/src/interface/browser.test.ts +23 -0
  466. package/examples/canister-studio/src/interface/browser.ts +153 -0
  467. package/examples/canister-studio/src/interface/cache.ts +68 -0
  468. package/examples/canister-studio/src/interface/cli-cache.test.ts +155 -0
  469. package/examples/canister-studio/src/interface/cli-cache.ts +125 -0
  470. package/examples/canister-studio/src/interface/compile.server.test.ts +198 -0
  471. package/examples/canister-studio/src/interface/compile.server.ts +262 -0
  472. package/examples/canister-studio/src/interface/compile.test.ts +108 -0
  473. package/examples/canister-studio/src/interface/compile.ts +305 -0
  474. package/examples/canister-studio/src/interface/docs.test.ts +75 -0
  475. package/examples/canister-studio/src/interface/docs.ts +100 -0
  476. package/examples/canister-studio/src/interface/functions.test.ts +42 -0
  477. package/examples/canister-studio/src/interface/functions.ts +200 -0
  478. package/examples/canister-studio/src/interface/live-candid.server.ts +91 -0
  479. package/examples/canister-studio/src/interface/live-loader.test.ts +515 -0
  480. package/examples/canister-studio/src/interface/live-loader.ts +364 -0
  481. package/examples/canister-studio/src/interface/load.test.ts +328 -0
  482. package/examples/canister-studio/src/interface/load.ts +249 -0
  483. package/examples/canister-studio/src/interface/read-candid.test.ts +185 -0
  484. package/examples/canister-studio/src/interface/read-candid.ts +233 -0
  485. package/examples/canister-studio/src/interface/server-result.ts +42 -0
  486. package/examples/canister-studio/src/interface/typed.ts +68 -0
  487. package/examples/canister-studio/src/interface/types.ts +121 -0
  488. package/examples/canister-studio/src/lib/format.test.ts +107 -0
  489. package/examples/canister-studio/src/lib/format.ts +139 -0
  490. package/examples/canister-studio/src/lib/hex.test.ts +43 -0
  491. package/examples/canister-studio/src/lib/hex.ts +33 -0
  492. package/examples/canister-studio/src/lib/ids.test.ts +70 -0
  493. package/examples/canister-studio/src/lib/ids.ts +93 -0
  494. package/examples/canister-studio/src/lib/reactor.test.ts +55 -0
  495. package/examples/canister-studio/src/lib/reactor.ts +55 -0
  496. package/examples/canister-studio/src/lib/registry.test.ts +74 -0
  497. package/examples/canister-studio/src/lib/registry.ts +238 -0
  498. package/examples/canister-studio/src/lib/schema.ts +148 -0
  499. package/examples/canister-studio/src/routeTree.gen.ts +227 -0
  500. package/examples/canister-studio/src/router.test.ts +290 -0
  501. package/examples/canister-studio/src/router.tsx +127 -0
  502. package/examples/canister-studio/src/routes/__root.tsx +58 -0
  503. package/examples/canister-studio/src/routes/canister.$canisterId.index.tsx +172 -0
  504. package/examples/canister-studio/src/routes/canister.$canisterId.interface.tsx +98 -0
  505. package/examples/canister-studio/src/routes/canister.$canisterId.tsx +91 -0
  506. package/examples/canister-studio/src/routes/history.tsx +55 -0
  507. package/examples/canister-studio/src/routes/index.tsx +169 -0
  508. package/examples/canister-studio/src/routes/playground.tsx +286 -0
  509. package/examples/canister-studio/src/routes/safety.tsx +57 -0
  510. package/examples/canister-studio/src/routes/wallet.tsx +213 -0
  511. package/examples/canister-studio/src/safety/LabTransferForm.tsx +84 -0
  512. package/examples/canister-studio/src/safety/RequestLog.tsx +79 -0
  513. package/examples/canister-studio/src/safety/SafetyLab.test.tsx +89 -0
  514. package/examples/canister-studio/src/safety/SafetyLab.tsx +140 -0
  515. package/examples/canister-studio/src/safety/ScenarioCard.tsx +262 -0
  516. package/examples/canister-studio/src/safety/lab-run.ts +283 -0
  517. package/examples/canister-studio/src/safety/mock-ledger.test.ts +99 -0
  518. package/examples/canister-studio/src/safety/mock-ledger.ts +263 -0
  519. package/examples/canister-studio/src/safety/scenarios.test.ts +157 -0
  520. package/examples/canister-studio/src/safety/scenarios.ts +924 -0
  521. package/examples/canister-studio/src/styles.css +3453 -0
  522. package/examples/canister-studio/src/styles.test.ts +46 -0
  523. package/examples/canister-studio/src/values/CallPreview.test.tsx +86 -0
  524. package/examples/canister-studio/src/values/CallPreview.tsx +148 -0
  525. package/examples/canister-studio/src/values/ErrValueView.tsx +66 -0
  526. package/examples/canister-studio/src/values/Inspector.tsx +133 -0
  527. package/examples/canister-studio/src/values/ReplyView.test.tsx +341 -0
  528. package/examples/canister-studio/src/values/ReplyView.tsx +164 -0
  529. package/examples/canister-studio/src/values/candid-text.test.ts +516 -0
  530. package/examples/canister-studio/src/values/candid-text.ts +479 -0
  531. package/examples/canister-studio/src/values/hints.ts +58 -0
  532. package/examples/canister-studio/src/values/json.test.ts +66 -0
  533. package/examples/canister-studio/src/values/json.ts +31 -0
  534. package/examples/canister-studio/src/values/leaves.tsx +309 -0
  535. package/examples/canister-studio/src/values/schema.test.ts +123 -0
  536. package/examples/canister-studio/src/values/schema.ts +78 -0
  537. package/examples/canister-studio/src/values/test-router.tsx +21 -0
  538. package/examples/canister-studio/src/values/tree.tsx +670 -0
  539. package/examples/canister-studio/src/values/use-sha256.ts +29 -0
  540. package/examples/canister-studio/tsconfig.json +20 -0
  541. package/examples/canister-studio/vite.config.ts +50 -0
  542. package/examples/canister-studio/vitest.config.ts +20 -0
  543. package/examples/icrc-ledger/.stackblitzrc +4 -0
  544. package/examples/icrc-ledger/README.md +100 -0
  545. package/examples/icrc-ledger/ckbtc_minter.did +12 -0
  546. package/examples/icrc-ledger/icp_ledger.did +147 -0
  547. package/examples/icrc-ledger/icrc1.did +88 -0
  548. package/examples/icrc-ledger/index.html +13 -0
  549. package/examples/icrc-ledger/package.json +40 -0
  550. package/examples/icrc-ledger/scripts/smoke.ts +151 -0
  551. package/examples/icrc-ledger/src/App.tsx +71 -0
  552. package/examples/icrc-ledger/src/ErrorPanel.tsx +105 -0
  553. package/examples/icrc-ledger/src/MainnetTab.tsx +450 -0
  554. package/examples/icrc-ledger/src/SandboxTab.test.tsx +379 -0
  555. package/examples/icrc-ledger/src/SandboxTab.tsx +761 -0
  556. package/examples/icrc-ledger/src/blocks.test.ts +247 -0
  557. package/examples/icrc-ledger/src/blocks.ts +140 -0
  558. package/examples/icrc-ledger/src/canisters/ckbtc_minter.envelope.json +96 -0
  559. package/examples/icrc-ledger/src/canisters/ckbtc_minter.ts +16 -0
  560. package/examples/icrc-ledger/src/canisters/icp_ledger.envelope.json +690 -0
  561. package/examples/icrc-ledger/src/canisters/icp_ledger.ts +223 -0
  562. package/examples/icrc-ledger/src/canisters/icrc1.envelope.json +840 -0
  563. package/examples/icrc-ledger/src/canisters/icrc1.ts +78 -0
  564. package/examples/icrc-ledger/src/format.test.ts +41 -0
  565. package/examples/icrc-ledger/src/format.ts +68 -0
  566. package/examples/icrc-ledger/src/ledger.ts +15 -0
  567. package/examples/icrc-ledger/src/main.tsx +10 -0
  568. package/examples/icrc-ledger/src/minter.ts +16 -0
  569. package/examples/icrc-ledger/src/sandbox.test.ts +464 -0
  570. package/examples/icrc-ledger/src/sandbox.ts +281 -0
  571. package/examples/icrc-ledger/src/styles.css +391 -0
  572. package/examples/icrc-ledger/src/transfer-form.test.ts +62 -0
  573. package/examples/icrc-ledger/src/transfer-form.ts +97 -0
  574. package/examples/icrc-ledger/tsconfig.json +19 -0
  575. package/examples/icrc-ledger/vite.config.ts +44 -0
  576. package/examples/icrc-ledger/vitest.config.ts +12 -0
  577. package/examples/next-ssr/.stackblitzrc +4 -0
  578. package/examples/next-ssr/README.md +112 -0
  579. package/examples/next-ssr/icrc1.did +88 -0
  580. package/examples/next-ssr/next.config.ts +10 -0
  581. package/examples/next-ssr/package.json +41 -0
  582. package/examples/next-ssr/scripts/smoke.ts +169 -0
  583. package/examples/next-ssr/src/app/account/CertifiedBalances.tsx +58 -0
  584. package/examples/next-ssr/src/app/account/account.test.tsx +165 -0
  585. package/examples/next-ssr/src/app/account/page.tsx +82 -0
  586. package/examples/next-ssr/src/app/api/balance/[ledger]/[principal]/route.ts +10 -0
  587. package/examples/next-ssr/src/app/globals.css +278 -0
  588. package/examples/next-ssr/src/app/layout.tsx +34 -0
  589. package/examples/next-ssr/src/app/page.tsx +46 -0
  590. package/examples/next-ssr/src/app/providers.browser.test.tsx +127 -0
  591. package/examples/next-ssr/src/app/providers.test.tsx +73 -0
  592. package/examples/next-ssr/src/app/providers.tsx +60 -0
  593. package/examples/next-ssr/src/canisters/icrc1.envelope.json +840 -0
  594. package/examples/next-ssr/src/canisters/icrc1.ts +78 -0
  595. package/examples/next-ssr/src/components/BalanceTable.tsx +43 -0
  596. package/examples/next-ssr/src/components/LedgerCard.test.tsx +96 -0
  597. package/examples/next-ssr/src/components/LedgerCard.tsx +230 -0
  598. package/examples/next-ssr/src/components/LedgerError.tsx +32 -0
  599. package/examples/next-ssr/src/components/LedgerSections.tsx +22 -0
  600. package/examples/next-ssr/src/components/MyBalances.test.tsx +253 -0
  601. package/examples/next-ssr/src/components/MyBalances.tsx +129 -0
  602. package/examples/next-ssr/src/components/SessionBadge.tsx +18 -0
  603. package/examples/next-ssr/src/components/hydration.test.tsx +259 -0
  604. package/examples/next-ssr/src/components/server-data.ts +10 -0
  605. package/examples/next-ssr/src/format.ts +46 -0
  606. package/examples/next-ssr/src/ledgers.ts +38 -0
  607. package/examples/next-ssr/src/server/balance-route.test.ts +151 -0
  608. package/examples/next-ssr/src/server/balance-route.ts +157 -0
  609. package/examples/next-ssr/src/server/error-summary.test.ts +34 -0
  610. package/examples/next-ssr/src/server/error-summary.ts +37 -0
  611. package/examples/next-ssr/src/server/parse-owner.test.ts +39 -0
  612. package/examples/next-ssr/src/server/parse-owner.ts +34 -0
  613. package/examples/next-ssr/src/server/prefetch-ledgers.test.ts +137 -0
  614. package/examples/next-ssr/src/server/prefetch-ledgers.ts +70 -0
  615. package/examples/next-ssr/src/server/read-balances.test.ts +103 -0
  616. package/examples/next-ssr/src/server/read-balances.ts +78 -0
  617. package/examples/next-ssr/src/server/request-client.rsc.test.tsx +110 -0
  618. package/examples/next-ssr/src/server/request-client.ts +24 -0
  619. package/examples/next-ssr/src/testing/mock-ledgers.ts +115 -0
  620. package/examples/next-ssr/src/testing/react-server-dom-turbopack.d.ts +15 -0
  621. package/examples/next-ssr/src/testing/setup.ts +10 -0
  622. package/examples/next-ssr/tsconfig.json +31 -0
  623. package/examples/next-ssr/vitest.config.ts +59 -0
  624. package/examples/node-agent-tool/.stackblitzrc +4 -0
  625. package/examples/node-agent-tool/README.md +165 -0
  626. package/examples/node-agent-tool/icp.yaml +11 -0
  627. package/examples/node-agent-tool/icrc1.did +88 -0
  628. package/examples/node-agent-tool/package.json +32 -0
  629. package/examples/node-agent-tool/src/canisters/icrc1.envelope.json +840 -0
  630. package/examples/node-agent-tool/src/canisters/icrc1.ts +78 -0
  631. package/examples/node-agent-tool/src/cli.test.ts +64 -0
  632. package/examples/node-agent-tool/src/cli.ts +23 -0
  633. package/examples/node-agent-tool/src/command-line.ts +159 -0
  634. package/examples/node-agent-tool/src/commands/balance.ts +73 -0
  635. package/examples/node-agent-tool/src/commands/demo.test.ts +51 -0
  636. package/examples/node-agent-tool/src/commands/demo.ts +359 -0
  637. package/examples/node-agent-tool/src/commands/info.ts +69 -0
  638. package/examples/node-agent-tool/src/commands/reads.test.ts +133 -0
  639. package/examples/node-agent-tool/src/commands/resend.test.ts +363 -0
  640. package/examples/node-agent-tool/src/commands/transfer.test.ts +313 -0
  641. package/examples/node-agent-tool/src/commands/transfer.ts +415 -0
  642. package/examples/node-agent-tool/src/commands/watch.test.ts +159 -0
  643. package/examples/node-agent-tool/src/commands/watch.ts +135 -0
  644. package/examples/node-agent-tool/src/commands/whoami.ts +36 -0
  645. package/examples/node-agent-tool/src/context.ts +20 -0
  646. package/examples/node-agent-tool/src/dispatch.ts +70 -0
  647. package/examples/node-agent-tool/src/failure.test.ts +59 -0
  648. package/examples/node-agent-tool/src/failure.ts +176 -0
  649. package/examples/node-agent-tool/src/identity.test.ts +242 -0
  650. package/examples/node-agent-tool/src/identity.ts +228 -0
  651. package/examples/node-agent-tool/src/input.ts +110 -0
  652. package/examples/node-agent-tool/src/ledgers.test.ts +74 -0
  653. package/examples/node-agent-tool/src/ledgers.ts +62 -0
  654. package/examples/node-agent-tool/src/mock-ledger.ts +211 -0
  655. package/examples/node-agent-tool/src/network.test.ts +128 -0
  656. package/examples/node-agent-tool/src/network.ts +101 -0
  657. package/examples/node-agent-tool/src/output.test.ts +208 -0
  658. package/examples/node-agent-tool/src/output.ts +163 -0
  659. package/examples/node-agent-tool/src/run.ts +73 -0
  660. package/examples/node-agent-tool/src/test-kit.ts +167 -0
  661. package/examples/node-agent-tool/tsconfig.json +18 -0
  662. package/examples/node-agent-tool/vitest.config.ts +8 -0
  663. package/examples/vite-wallet/.stackblitzrc +4 -0
  664. package/examples/vite-wallet/Cargo.lock +646 -0
  665. package/examples/vite-wallet/Cargo.toml +5 -0
  666. package/examples/vite-wallet/README.md +107 -0
  667. package/examples/vite-wallet/backend/Cargo.toml +12 -0
  668. package/examples/vite-wallet/backend/backend.did +37 -0
  669. package/examples/vite-wallet/backend/src/lib.rs +133 -0
  670. package/examples/vite-wallet/icp.yaml +44 -0
  671. package/examples/vite-wallet/index.html +13 -0
  672. package/examples/vite-wallet/ledger.did +54 -0
  673. package/examples/vite-wallet/package.json +46 -0
  674. package/examples/vite-wallet/public/.ic-assets.json5 +26 -0
  675. package/examples/vite-wallet/scripts/faucet-args.test.ts +30 -0
  676. package/examples/vite-wallet/scripts/faucet-args.ts +41 -0
  677. package/examples/vite-wallet/scripts/faucet.ts +41 -0
  678. package/examples/vite-wallet/src/AddressBook.test.tsx +191 -0
  679. package/examples/vite-wallet/src/AddressBook.tsx +147 -0
  680. package/examples/vite-wallet/src/App.tsx +53 -0
  681. package/examples/vite-wallet/src/Balance.test.tsx +57 -0
  682. package/examples/vite-wallet/src/Balance.tsx +58 -0
  683. package/examples/vite-wallet/src/EnvironmentPanel.test.tsx +83 -0
  684. package/examples/vite-wallet/src/EnvironmentPanel.tsx +103 -0
  685. package/examples/vite-wallet/src/ErrorNote.tsx +70 -0
  686. package/examples/vite-wallet/src/Profile.test.tsx +145 -0
  687. package/examples/vite-wallet/src/Profile.tsx +92 -0
  688. package/examples/vite-wallet/src/SendIcp.test.tsx +231 -0
  689. package/examples/vite-wallet/src/SendIcp.tsx +244 -0
  690. package/examples/vite-wallet/src/SendToContact.test.tsx +113 -0
  691. package/examples/vite-wallet/src/SendToContact.tsx +102 -0
  692. package/examples/vite-wallet/src/SignIn.test.tsx +106 -0
  693. package/examples/vite-wallet/src/SignIn.tsx +120 -0
  694. package/examples/vite-wallet/src/Wallet.test.tsx +89 -0
  695. package/examples/vite-wallet/src/account-switch.test.tsx +108 -0
  696. package/examples/vite-wallet/src/auth/dev-accounts.test.ts +113 -0
  697. package/examples/vite-wallet/src/auth/dev-accounts.ts +216 -0
  698. package/examples/vite-wallet/src/auth/local-page.test.ts +28 -0
  699. package/examples/vite-wallet/src/auth/local-page.ts +20 -0
  700. package/examples/vite-wallet/src/auth/wallet-auth.test.ts +159 -0
  701. package/examples/vite-wallet/src/auth/wallet-auth.ts +131 -0
  702. package/examples/vite-wallet/src/canisters/backend.envelope.json +275 -0
  703. package/examples/vite-wallet/src/canisters/backend.ts +58 -0
  704. package/examples/vite-wallet/src/canisters/ledger.envelope.json +451 -0
  705. package/examples/vite-wallet/src/canisters/ledger.ts +56 -0
  706. package/examples/vite-wallet/src/client.ts +45 -0
  707. package/examples/vite-wallet/src/main.tsx +18 -0
  708. package/examples/vite-wallet/src/optimistic-contacts.ts +113 -0
  709. package/examples/vite-wallet/src/refusal.ts +17 -0
  710. package/examples/vite-wallet/src/styles.css +282 -0
  711. package/examples/vite-wallet/src/test/test-wallet.tsx +322 -0
  712. package/examples/vite-wallet/src/token.ts +50 -0
  713. package/examples/vite-wallet/src/transfer.test.ts +178 -0
  714. package/examples/vite-wallet/src/transfer.ts +110 -0
  715. package/examples/vite-wallet/src/use-canisters.ts +49 -0
  716. package/examples/vite-wallet/tsconfig.json +19 -0
  717. package/examples/vite-wallet/vite.config.ts +47 -0
  718. package/examples/vite-wallet/vitest.config.ts +17 -0
  719. package/package.json +9 -4
  720. package/packages/core/.size-limit.js +47 -0
  721. package/packages/core/LICENSE +21 -0
  722. package/packages/core/README.md +84 -0
  723. package/packages/core/llms.txt +610 -0
  724. package/packages/core/package.json +89 -0
  725. package/packages/core/src/call.ts +961 -0
  726. package/packages/core/src/canister.ts +259 -0
  727. package/packages/core/src/client.ts +2061 -0
  728. package/packages/core/src/errors.ts +1079 -0
  729. package/packages/core/src/hydration.ts +239 -0
  730. package/packages/core/src/index.ts +23 -0
  731. package/packages/core/src/keys.ts +108 -0
  732. package/packages/core/src/management.ts +138 -0
  733. package/packages/core/src/network.ts +1020 -0
  734. package/packages/core/src/options.ts +1000 -0
  735. package/packages/core/src/runtime.ts +50 -0
  736. package/packages/core/src/testing/fake-replica.ts +1166 -0
  737. package/packages/core/src/testing/index.ts +16 -0
  738. package/packages/core/src/testing/test-auth.ts +340 -0
  739. package/packages/core/src/testing/test-client.ts +559 -0
  740. package/packages/core/src/types.ts +541 -0
  741. package/packages/core/src/units.ts +299 -0
  742. package/packages/core/src/version.ts +4 -0
  743. package/packages/core/tests/canister-helpers.ts +187 -0
  744. package/packages/core/tests/canister-id.test.ts +158 -0
  745. package/packages/core/tests/canister-unwrap.test.ts +94 -0
  746. package/packages/core/tests/canister.test-d.ts +406 -0
  747. package/packages/core/tests/canister.test.ts +1921 -0
  748. package/packages/core/tests/client-account-change.test.ts +131 -0
  749. package/packages/core/tests/client-agents.test.ts +402 -0
  750. package/packages/core/tests/client-auth-network.test.ts +719 -0
  751. package/packages/core/tests/client-disposed.test.ts +403 -0
  752. package/packages/core/tests/client-helpers.ts +136 -0
  753. package/packages/core/tests/client-hydration.test.ts +166 -0
  754. package/packages/core/tests/client-pinned.test.ts +626 -0
  755. package/packages/core/tests/client-session.test.ts +348 -0
  756. package/packages/core/tests/client.test-d.ts +181 -0
  757. package/packages/core/tests/client.test.ts +1162 -0
  758. package/packages/core/tests/encode.test.ts +171 -0
  759. package/packages/core/tests/env-canister-id.test.ts +666 -0
  760. package/packages/core/tests/env-cookie-copies.test.ts +182 -0
  761. package/packages/core/tests/error-guard.test.ts +222 -0
  762. package/packages/core/tests/errors.test-d.ts +280 -0
  763. package/packages/core/tests/errors.test.ts +1359 -0
  764. package/packages/core/tests/fixtures/README.md +28 -0
  765. package/packages/core/tests/fixtures/accounts.did +21 -0
  766. package/packages/core/tests/fixtures/accounts.envelope.json +367 -0
  767. package/packages/core/tests/fixtures/accounts.ts +26 -0
  768. package/packages/core/tests/fixtures/archive.did +31 -0
  769. package/packages/core/tests/fixtures/archive.envelope.json +259 -0
  770. package/packages/core/tests/fixtures/archive.ts +55 -0
  771. package/packages/core/tests/fixtures/icrc1.did +88 -0
  772. package/packages/core/tests/fixtures/icrc1.envelope.json +840 -0
  773. package/packages/core/tests/fixtures/icrc1.ts +78 -0
  774. package/packages/core/tests/fixtures/management.did +724 -0
  775. package/packages/core/tests/fixtures/management.envelope.json +4455 -0
  776. package/packages/core/tests/fixtures/management.ts +486 -0
  777. package/packages/core/tests/fixtures/shapes.did +33 -0
  778. package/packages/core/tests/fixtures/shapes.envelope.json +440 -0
  779. package/packages/core/tests/fixtures/shapes.ts +56 -0
  780. package/packages/core/tests/fixtures/skippable.did +15 -0
  781. package/packages/core/tests/fixtures/skippable.envelope.json +182 -0
  782. package/packages/core/tests/fixtures/skippable.ts +33 -0
  783. package/packages/core/tests/func.test.ts +154 -0
  784. package/packages/core/tests/identity-attributes.test.ts +214 -0
  785. package/packages/core/tests/keys.test.ts +289 -0
  786. package/packages/core/tests/management.test.ts +206 -0
  787. package/packages/core/tests/network-helpers.ts +121 -0
  788. package/packages/core/tests/network.test-d.ts +78 -0
  789. package/packages/core/tests/network.test.ts +1051 -0
  790. package/packages/core/tests/options.test.ts +1594 -0
  791. package/packages/core/tests/redirect-sign-in.test.ts +393 -0
  792. package/packages/core/tests/resend.test-d.ts +81 -0
  793. package/packages/core/tests/resend.test.ts +723 -0
  794. package/packages/core/tests/skip.test-d.ts +125 -0
  795. package/packages/core/tests/testing-entry.test.ts +73 -0
  796. package/packages/core/tests/testing-fake-replica.test.ts +1242 -0
  797. package/packages/core/tests/testing-test-auth.test-d.ts +84 -0
  798. package/packages/core/tests/testing-test-auth.test.ts +483 -0
  799. package/packages/core/tests/testing-test-client.test-d.ts +184 -0
  800. package/packages/core/tests/testing-test-client.test.ts +1272 -0
  801. package/packages/core/tests/time-realm.test.ts +63 -0
  802. package/packages/core/tests/time.test.ts +238 -0
  803. package/packages/core/tests/traps/README.md +39 -0
  804. package/packages/core/tests/traps/anonymous-write.test.ts +145 -0
  805. package/packages/core/tests/traps/classification-table.test.ts +256 -0
  806. package/packages/core/tests/traps/err-arm.test.ts +144 -0
  807. package/packages/core/tests/traps/fetch-spy.ts +39 -0
  808. package/packages/core/tests/traps/invalidation-after-write.test.ts +178 -0
  809. package/packages/core/tests/traps/ledger.ts +248 -0
  810. package/packages/core/tests/traps/root-key-off-local.test.ts +130 -0
  811. package/packages/core/tests/traps/stale-data-across-users.test.ts +173 -0
  812. package/packages/core/tests/traps/unresolved-name.test.ts +155 -0
  813. package/packages/core/tests/traps/update-as-query.test.ts +244 -0
  814. package/packages/core/tests/traps/update-not-resent.test.ts +126 -0
  815. package/packages/core/tests/traps/update-resent-when-never-delivered.test.ts +159 -0
  816. package/packages/core/tests/traps.test-d.ts +476 -0
  817. package/packages/core/tests/units.test-d.ts +118 -0
  818. package/packages/core/tests/units.test.ts +634 -0
  819. package/packages/core/tsconfig.json +19 -0
  820. package/packages/core/tsconfig.typecheck.json +16 -0
  821. package/packages/core/vitest.config.ts +13 -0
  822. package/packages/mcp/LICENSE +21 -0
  823. package/packages/mcp/README.md +189 -0
  824. package/packages/mcp/package.json +62 -0
  825. package/packages/mcp/src/candid/candid-text.test.ts +455 -0
  826. package/packages/mcp/src/candid/candid-text.ts +501 -0
  827. package/packages/mcp/src/candid/contract.test.ts +398 -0
  828. package/packages/mcp/src/candid/formats.ts +155 -0
  829. package/packages/mcp/src/candid/hex.ts +29 -0
  830. package/packages/mcp/src/candid/json-schema.test.ts +758 -0
  831. package/packages/mcp/src/candid/json-schema.ts +454 -0
  832. package/packages/mcp/src/candid/json.test.ts +1207 -0
  833. package/packages/mcp/src/candid/json.ts +1053 -0
  834. package/packages/mcp/src/candid/schema-walk.ts +189 -0
  835. package/packages/mcp/src/candid/type-text.test.ts +179 -0
  836. package/packages/mcp/src/candid/type-text.ts +238 -0
  837. package/packages/mcp/src/cli.ts +134 -0
  838. package/packages/mcp/src/identity.ts +188 -0
  839. package/packages/mcp/src/interface/cache.test.ts +48 -0
  840. package/packages/mcp/src/interface/cache.ts +68 -0
  841. package/packages/mcp/src/interface/cli-cache.test.ts +150 -0
  842. package/packages/mcp/src/interface/cli-cache.ts +122 -0
  843. package/packages/mcp/src/interface/compile-worker.test.ts +246 -0
  844. package/packages/mcp/src/interface/compile-worker.ts +290 -0
  845. package/packages/mcp/src/interface/compile.test.ts +155 -0
  846. package/packages/mcp/src/interface/compile.ts +281 -0
  847. package/packages/mcp/src/interface/docs.test.ts +105 -0
  848. package/packages/mcp/src/interface/docs.ts +86 -0
  849. package/packages/mcp/src/interface/fixtures/icrc1.did +88 -0
  850. package/packages/mcp/src/interface/hex.ts +8 -0
  851. package/packages/mcp/src/interface/ids.test.ts +71 -0
  852. package/packages/mcp/src/interface/ids.ts +87 -0
  853. package/packages/mcp/src/interface/loader.test.ts +804 -0
  854. package/packages/mcp/src/interface/loader.ts +519 -0
  855. package/packages/mcp/src/interface/read-candid.test.ts +300 -0
  856. package/packages/mcp/src/interface/read-candid.ts +259 -0
  857. package/packages/mcp/src/interface/types.ts +113 -0
  858. package/packages/mcp/src/network.ts +122 -0
  859. package/packages/mcp/src/options.ts +149 -0
  860. package/packages/mcp/src/server/approval.ts +159 -0
  861. package/packages/mcp/src/server/naming.ts +43 -0
  862. package/packages/mcp/src/server/results.ts +102 -0
  863. package/packages/mcp/src/server/server.ts +797 -0
  864. package/packages/mcp/src/server/tools.ts +116 -0
  865. package/packages/mcp/src/usage.ts +40 -0
  866. package/packages/mcp/tests/approval.test.ts +60 -0
  867. package/packages/mcp/tests/identity.test.ts +234 -0
  868. package/packages/mcp/tests/naming.test.ts +62 -0
  869. package/packages/mcp/tests/options.test.ts +140 -0
  870. package/packages/mcp/tests/server.test.ts +997 -0
  871. package/packages/mcp/tsconfig.json +19 -0
  872. package/packages/mcp/tsconfig.typecheck.json +10 -0
  873. package/packages/mcp/vitest.config.ts +10 -0
  874. package/packages/react/LICENSE +21 -0
  875. package/packages/react/README.md +328 -0
  876. package/packages/react/llms.txt +95 -0
  877. package/packages/react/package.json +95 -0
  878. package/packages/react/src/index.tsx +678 -0
  879. package/packages/react/tests/abandoned-render.test.tsx +816 -0
  880. package/packages/react/tests/auth.test.tsx +315 -0
  881. package/packages/react/tests/caller-keys.test.tsx +2334 -0
  882. package/packages/react/tests/client-time.test.ts +40 -0
  883. package/packages/react/tests/entry.test.ts +52 -0
  884. package/packages/react/tests/helpers.tsx +291 -0
  885. package/packages/react/tests/hydration.test.tsx +262 -0
  886. package/packages/react/tests/ownership.test.tsx +260 -0
  887. package/packages/react/tests/provider.server.test.tsx +169 -0
  888. package/packages/react/tests/query-client.test.tsx +107 -0
  889. package/packages/react/tests/strict-mode.test.tsx +288 -0
  890. package/packages/react/tests/suspense.test-d.tsx +357 -0
  891. package/packages/react/tests/two-query-cores.test.tsx +135 -0
  892. package/packages/react/tests/types.test-d.tsx +63 -0
  893. package/packages/react/tsconfig.json +23 -0
  894. package/packages/react/tsconfig.test.json +8 -0
  895. package/packages/react/tsconfig.typecheck.json +16 -0
  896. package/packages/react/vitest.config.ts +39 -0
  897. package/packages/vite-plugin/LICENSE +21 -0
  898. package/packages/vite-plugin/README.md +532 -0
  899. package/packages/vite-plugin/package.json +76 -0
  900. package/packages/vite-plugin/src/describe-value.test.ts +43 -0
  901. package/packages/vite-plugin/src/describe-value.ts +167 -0
  902. package/packages/vite-plugin/src/dev-environment.test.ts +747 -0
  903. package/packages/vite-plugin/src/dev-environment.ts +510 -0
  904. package/packages/vite-plugin/src/env.ts +431 -0
  905. package/packages/vite-plugin/src/fetch.ts +348 -0
  906. package/packages/vite-plugin/src/file-identity.ts +106 -0
  907. package/packages/vite-plugin/src/generate.ts +691 -0
  908. package/packages/vite-plugin/src/index.test.ts +1243 -0
  909. package/packages/vite-plugin/src/index.ts +2565 -0
  910. package/packages/vite-plugin/src/interface.ts +339 -0
  911. package/packages/vite-plugin/src/local-host.ts +34 -0
  912. package/packages/vite-plugin/src/options.ts +641 -0
  913. package/packages/vite-plugin/src/principal-text.test.ts +87 -0
  914. package/packages/vite-plugin/src/principal-text.ts +98 -0
  915. package/packages/vite-plugin/tests/close.test.ts +141 -0
  916. package/packages/vite-plugin/tests/environment-mode.test.ts +136 -0
  917. package/packages/vite-plugin/tests/fake-ic.ts +214 -0
  918. package/packages/vite-plugin/tests/fetch-sdk.test.ts +27 -0
  919. package/packages/vite-plugin/tests/fetch.test.ts +1196 -0
  920. package/packages/vite-plugin/tests/fixtures/fake-cli/bin.js +90 -0
  921. package/packages/vite-plugin/tests/fixtures/fake-cli/package.json +8 -0
  922. package/packages/vite-plugin/tests/fixtures/icrc1.did +88 -0
  923. package/packages/vite-plugin/tests/generation.test.ts +1036 -0
  924. package/packages/vite-plugin/tests/icp-command.test.ts +194 -0
  925. package/packages/vite-plugin/tests/icp-timeout.test.ts +83 -0
  926. package/packages/vite-plugin/tests/no-process-exit.test.ts +83 -0
  927. package/packages/vite-plugin/tests/on-generated.test.ts +323 -0
  928. package/packages/vite-plugin/tests/output-collision.test.ts +329 -0
  929. package/packages/vite-plugin/tests/package.test.ts +62 -0
  930. package/packages/vite-plugin/tests/project.test.ts +2993 -0
  931. package/packages/vite-plugin/tests/support.ts +339 -0
  932. package/packages/vite-plugin/tests/timeout.test.ts +107 -0
  933. package/packages/vite-plugin/tsconfig.json +23 -0
  934. package/packages/vite-plugin/tsconfig.typecheck.json +16 -0
  935. package/packages/vite-plugin/vitest.config.ts +9 -0
  936. package/pnpm-workspace.yaml +23 -0
  937. package/scripts/ai-context-files.js +72 -0
  938. package/scripts/assemble-docs-site.mjs +485 -0
  939. package/scripts/assemble-docs-site.test.mjs +568 -0
  940. package/scripts/build-examples.js +58 -0
  941. package/scripts/check-ai-context.js +963 -0
  942. package/scripts/check-ai-context.test.mjs +811 -0
  943. package/scripts/check-exports.mjs +767 -0
  944. package/scripts/check-exports.test.mjs +1136 -0
  945. package/scripts/check-snippets/ambient.d.ts +428 -0
  946. package/scripts/check-snippets/app/generated/backend.did +7 -0
  947. package/scripts/check-snippets/app/generated/backend.ts +15 -0
  948. package/scripts/check-snippets/app/generated/icrc1.did +88 -0
  949. package/scripts/check-snippets/app/generated/icrc1.ts +78 -0
  950. package/scripts/check-snippets/app/globals.ts +26 -0
  951. package/scripts/check-snippets/docs/guides/App.tsx +21 -0
  952. package/scripts/check-snippets/docs/guides/app/providers.tsx +23 -0
  953. package/scripts/check-snippets/docs/guides/auth-client.ts +47 -0
  954. package/scripts/check-snippets/docs/guides/canisters/backend.ts +3 -0
  955. package/scripts/check-snippets/docs/guides/canisters/icrc1.ts +3 -0
  956. package/scripts/check-snippets/docs/guides/components/LedgerCard.tsx +26 -0
  957. package/scripts/check-snippets/docs/guides/components/shell.tsx +11 -0
  958. package/scripts/check-snippets/docs/guides/components/sign-in-page.tsx +29 -0
  959. package/scripts/check-snippets/docs/guides/components/slow-section.tsx +5 -0
  960. package/scripts/check-snippets/docs/guides/generated/accounts.ts +95 -0
  961. package/scripts/check-snippets/docs/guides/generated/ckbtc_minter.ts +40 -0
  962. package/scripts/check-snippets/docs/guides/generated/icp_ledger.ts +267 -0
  963. package/scripts/check-snippets/docs/guides/ledger.ts +10 -0
  964. package/scripts/check-snippets/docs/guides/server/request-client.ts +8 -0
  965. package/scripts/check-snippets.mjs +993 -0
  966. package/scripts/check-snippets.test.mjs +338 -0
  967. package/scripts/check-stack.mjs +501 -0
  968. package/scripts/check-stack.test.mjs +800 -0
  969. package/scripts/clean-node-modules.js +67 -0
  970. package/scripts/example-projects.js +58 -0
  971. package/scripts/export-budget.mjs +145 -0
  972. package/scripts/faults.json +6749 -0
  973. package/scripts/lib/fault-workspace.mjs +210 -0
  974. package/scripts/lib/io.mjs +29 -0
  975. package/scripts/lib/io.test.mjs +38 -0
  976. package/scripts/lib/markdown-fences.mjs +56 -0
  977. package/scripts/lib/markdown-fences.test.mjs +84 -0
  978. package/scripts/lib/package-exports.mjs +54 -0
  979. package/scripts/lib/package-exports.test.mjs +66 -0
  980. package/scripts/lib/release-pr-steps.mjs +47 -0
  981. package/scripts/release-tag.mjs +95 -0
  982. package/scripts/release-tag.test.mjs +278 -0
  983. package/scripts/release-workflow.test.mjs +98 -0
  984. package/scripts/release.js +167 -0
  985. package/scripts/release.test.mjs +347 -0
  986. package/scripts/removed-v3-names.js +125 -0
  987. package/scripts/size-app/.size-limit.js +90 -0
  988. package/scripts/size-app/core.js +3 -0
  989. package/scripts/size-app/package.json +24 -0
  990. package/scripts/size-app/react.js +4 -0
  991. package/scripts/size-app.test.mjs +73 -0
  992. package/scripts/sync-ai-context-versions.js +102 -0
  993. package/scripts/sync-example-versions.js +151 -0
  994. package/scripts/test-examples-published.mjs +1585 -0
  995. package/scripts/test-examples-published.test.mjs +1586 -0
  996. package/scripts/traps/any-method-vars-not-a-list.json +5 -0
  997. package/scripts/traps/canister-method-unknown.json +5 -0
  998. package/scripts/traps/client-says-who-calls-once.json +5 -0
  999. package/scripts/traps/client-says-who-calls.json +5 -0
  1000. package/scripts/traps/err-only-on-canister-err.json +14 -0
  1001. package/scripts/traps/format-units-refuses-missing-value.json +5 -0
  1002. package/scripts/traps/format-units-refuses-number.json +5 -0
  1003. package/scripts/traps/format-units-unknown-option.json +5 -0
  1004. package/scripts/traps/guard-err-is-the-methods.json +5 -0
  1005. package/scripts/traps/guard-false-keeps-every-kind.json +5 -0
  1006. package/scripts/traps/internals-not-exported.json +9 -0
  1007. package/scripts/traps/network-refuses-unknown-name.json +5 -0
  1008. package/scripts/traps/never-err-has-no-type.json +5 -0
  1009. package/scripts/traps/options-method-unknown.json +5 -0
  1010. package/scripts/traps/options-vars-wrong-type.json +5 -0
  1011. package/scripts/traps/parse-units-refuses-number.json +5 -0
  1012. package/scripts/traps/parse-units-unknown-option.json +5 -0
  1013. package/scripts/traps/principal-is-not-plain-text.json +14 -0
  1014. package/scripts/traps/query-options-refuses-oneway.json +5 -0
  1015. package/scripts/traps/query-options-refuses-update.json +5 -0
  1016. package/scripts/traps/refuse-next-unknown-option.json +5 -0
  1017. package/scripts/traps/resend-key-reads-the-methods-arg.json +5 -0
  1018. package/scripts/traps/resend-states-its-dedupe-key.json +5 -0
  1019. package/scripts/traps/suspense-refuses-argument-skip.json +5 -0
  1020. package/scripts/traps/suspense-refuses-skippable-read.json +5 -0
  1021. package/scripts/traps/suspense-refuses-vars-skip-fits.json +5 -0
  1022. package/scripts/traps/test-handler-method-unknown.json +5 -0
  1023. package/scripts/traps/test-handler-nat-is-bigint.json +5 -0
  1024. package/scripts/traps/test-handler-takes-the-domain-value.json +5 -0
  1025. package/scripts/traps/vars-of-two-arguments-are-the-tuple.json +5 -0
  1026. package/scripts/typecheck-examples.js +122 -0
  1027. package/scripts/verify-faults.mjs +375 -0
  1028. package/scripts/verify-faults.test.mjs +402 -0
  1029. package/scripts/verify-package-artifacts.mjs +590 -0
  1030. package/scripts/verify-peer-floors.js +399 -0
  1031. package/scripts/verify-peer-floors.test.mjs +422 -0
  1032. package/scripts/verify-test-fails-rules.mjs +104 -0
  1033. package/scripts/verify-test-fails-rules.test.mjs +215 -0
  1034. package/scripts/verify-test-fails.js +371 -0
  1035. package/scripts/verify-traps.mjs +505 -0
  1036. package/scripts/verify-traps.test.mjs +521 -0
  1037. package/scripts/verify-typescript-floor.js +239 -0
  1038. package/skill-packages/ic-reactor/SKILL.md +103 -0
  1039. package/stack.json +8 -0
  1040. package/tsconfig.base.json +23 -0
  1041. package/tsconfig.json +8 -0
@@ -0,0 +1,1053 @@
1
+ # IC Reactor: full guide for AI coding agents
2
+
3
+ > How to write correct IC Reactor code in an app: install, choose a setup, call
4
+ > canisters from React and from plain code, cache and invalidate, sign in,
5
+ > render on a server, handle errors, generate code, test, and the mistakes to
6
+ > avoid.
7
+
8
+ This guide is for code that uses the published packages. The short index of
9
+ the documentation is https://ic-reactor.b3pay.net/llms.txt. Both are published
10
+ from the main branch, so they can describe changes that no release carries
11
+ yet; the Unreleased section of
12
+ https://github.com/B3Pay/ic-reactor/blob/main/CHANGELOG.md lists those, with
13
+ migration hints for behaviour changes. Each installed package also carries a
14
+ guide for its own API at `node_modules/@ic-reactor/<package>/llms.txt`,
15
+ written for the version installed.
16
+
17
+ The rules below also ship as the `ic-reactor` Agent Skill. In Claude Code:
18
+ `/plugin marketplace add B3Pay/ic-reactor`, then
19
+ `/plugin install ic-reactor@ic-reactor`. For other agents:
20
+ `npx skills add B3Pay/ic-reactor --skill ic-reactor`.
21
+
22
+ Package versions this guide describes:
23
+
24
+ - `@ic-reactor/core`: `3.13.0`
25
+ - `@ic-reactor/react`: `3.13.0`
26
+ - `@ic-reactor/candid`: `3.13.0`
27
+ - `@ic-reactor/codegen`: `0.15.1`
28
+ - `@ic-reactor/cli`: `0.15.1`
29
+ - `@ic-reactor/vite-plugin`: `0.15.1`
30
+ - `@ic-reactor/parser`: `0.6.0`
31
+
32
+ ## What IC Reactor Is
33
+
34
+ IC Reactor calls Internet Computer canisters with end-to-end TypeScript types
35
+ taken from the canister's Candid service type (`_SERVICE` in generated
36
+ declarations). It caches query results in TanStack Query, gives React hooks
37
+ and reusable query/mutation objects, unwraps Candid `Result` values into data
38
+ or a typed error, signs users in with Internet Identity, and can generate all
39
+ of this from `.did` files.
40
+
41
+ | Package | Use it for |
42
+ | ------------------------- | ------------------------------------------------------------------------------------------- |
43
+ | `@ic-reactor/core` | `ClientManager`, `Reactor`, `DisplayReactor`, errors, token helpers. No React. |
44
+ | `@ic-reactor/react` | Hooks, query/mutation factories, `defineReactor`, auth. Re-exports all of core. |
45
+ | `@ic-reactor/candid` | Reactors for canisters whose Candid is only known at run time; forms from Candid metadata. |
46
+ | `@ic-reactor/parser` | WASM Candid parser: `didToJs`, `didToTs`, `parseDid`, `validateIDL`. |
47
+ | `@ic-reactor/vite-plugin` | Generates declarations and hooks from `.did` files in a Vite app; local canister ids. |
48
+ | `@ic-reactor/cli` | The `ic-reactor` command: the same generation for non-Vite projects and CI. |
49
+ | `@ic-reactor/codegen` | The generation pipeline behind the CLI and the Vite plugin; apps rarely import it directly. |
50
+
51
+ ## Install
52
+
53
+ React apps:
54
+
55
+ ```bash
56
+ pnpm add @ic-reactor/react @icp-sdk/core @tanstack/react-query
57
+ ```
58
+
59
+ `@ic-reactor/react` needs `@tanstack/react-query` 5.90.2 or later and React 18
60
+ or later. IC Reactor needs TypeScript 5.7 or later: its declarations, and those
61
+ of `@icp-sdk/core`, use generic typed arrays such as `Uint8Array<ArrayBuffer>`,
62
+ which TypeScript 5.7 introduced. Import the runtime (`ClientManager`,
63
+ `Reactor`, ...) from `@ic-reactor/react` too: with the install above,
64
+ `@ic-reactor/core` is not a direct dependency, and pnpm does not let the app
65
+ import it.
66
+
67
+ Non-React apps:
68
+
69
+ ```bash
70
+ pnpm add @ic-reactor/core @icp-sdk/core @tanstack/query-core
71
+ ```
72
+
73
+ Internet Identity sign-in (optional; the auth classes ship in
74
+ `@ic-reactor/react`):
75
+
76
+ ```bash
77
+ pnpm add @icp-sdk/auth@^10
78
+ ```
79
+
80
+ The `@icp-sdk/auth` peer is `^8.0.0 || ^10.0.0`. Install v10: it is the first
81
+ release to peer `@icp-sdk/core@^6`, so a strict `npm install` resolves the set
82
+ with no `overrides`. v7 and v9 are not supported; v9 still peers
83
+ `@icp-sdk/core@^5`. On v8, a strict `npm install` fails with `ERESOLVE`
84
+ (stale metadata, not an actual incompatibility). For npm on v8, add to
85
+ `package.json`:
86
+
87
+ ```json
88
+ { "overrides": { "@icp-sdk/auth": { "@icp-sdk/core": "$@icp-sdk/core" } } }
89
+ ```
90
+
91
+ On v10, four constructor options are dropped with a warning because v10 has
92
+ no equivalent: `storage`, `keyType`, `idleOptions`, `identity`. `targets` on
93
+ `login()` is ignored by v10, so the delegation is NOT restricted to those
94
+ canisters; pin `^8` if you depend on canister-scoped delegations.
95
+ `maxTimeToIdle` on `login()` and `disableBrowserActivity` exist only on v10.
96
+ On v10 a custom `identityProvider` also needs `internetIdentityId`.
97
+
98
+ Dynamic Candid:
99
+
100
+ ```bash
101
+ pnpm add @ic-reactor/candid @ic-reactor/core @icp-sdk/core @tanstack/query-core
102
+ ```
103
+
104
+ Code generation: `pnpm add -D @ic-reactor/vite-plugin` (Vite) or
105
+ `pnpm add -D @ic-reactor/cli` (anything else; Node.js 22.12 or later).
106
+
107
+ The snippets below import `canisterId`, `idlFactory` and the `_SERVICE` type
108
+ from `./declarations/backend`, which stands for your canister's declarations.
109
+ `idlFactory` comes from the generated `.js` file and `_SERVICE` from the
110
+ `.d.ts`. With the CLI or the Vite plugin those are
111
+ `src/declarations/<name>/declarations/<did>.js` and `.d.ts`, named after the
112
+ `.did` file; the folder's own `index.ts` exports the generated reactor and
113
+ hooks, not `idlFactory`.
114
+ `canisterId` is the canister's id as text: a constant, or a value from your
115
+ build's environment.
116
+
117
+ ## Choose a Setup
118
+
119
+ | Your app | Use |
120
+ | ----------------------------------------------------------- | --------------------------------------------------------------------------------- |
121
+ | React SPA, a few canisters | `defineReactor(...)` or `defineDisplayReactor(...)` at module scope |
122
+ | React SPA, many canisters or a `.did` that changes often | `@ic-reactor/vite-plugin` (Vite) or `@ic-reactor/cli`, with `factories: true` |
123
+ | Server-rendered React (Next.js, any SSR) | `createReactorProvider(() => defineReactor(...))` in a `"use client"` module |
124
+ | React Server Component, server action, route handler | `ClientManager` + `Reactor` built inside the request; `fetchQuery` / `callMethod` |
125
+ | Construction order or dependency injection must be explicit | `ClientManager` + `Reactor` or `DisplayReactor` + `createActorHooks(reactor)` |
126
+ | No React (Node scripts, other frameworks, workers) | `@ic-reactor/core`: `ClientManager` + `Reactor`, imperative API |
127
+ | Several canisters with one interface (ICRC ledgers) | one reactor, plus `reactor.forCanister(canisterId)` for each other canister |
128
+ | Canister interface known only at run time | `@ic-reactor/candid` |
129
+
130
+ `Reactor` returns raw Candid values; `DisplayReactor` returns values a UI can
131
+ show and a form can send:
132
+
133
+ | Candid | `Reactor` | `DisplayReactor` |
134
+ | -------------------------------- | ----------------------------------- | ---------------------- |
135
+ | `nat`, `int`, `nat64`, `int64` | `bigint` | `string` |
136
+ | `nat8`..`nat32`, `int8`..`int32` | `number` | `number` |
137
+ | `principal` | `Principal` | `string` |
138
+ | `blob` | `Uint8Array` | hex `string`, no `0x` |
139
+ | `opt T` | `[] \| [T]` | `T \| undefined` |
140
+ | `variant { A: T }` | `{ A: T }` | `{ _type: "A", A: T }` |
141
+ | `variant { A }` (no value) | `{ A: null }` | `{ _type: "A" }` |
142
+ | `vec record { text; T }` | `[string, T][]` | `{ [key: string]: T }` |
143
+ | `Result` (`Ok`/`Err`) | Ok value, or throws `CanisterError` | same |
144
+
145
+ `DisplayReactor` adds zod (about 24 kB gzipped). Until the next major,
146
+ `defineReactor` includes it too because of its deprecated `display` flag; the
147
+ smallest setup is `createActorHooks(new Reactor(...))`.
148
+
149
+ ## One-Call Setup
150
+
151
+ `defineReactor` creates the `QueryClient` (with `reactorRetry` as its query
152
+ retry), the `ClientManager`, the reactor and its hooks in one call.
153
+ `defineDisplayReactor` takes the same options and builds a `DisplayReactor`.
154
+ `defineReactor({ display: true })` is deprecated; never write it. Plain
155
+ `defineReactor` is not deprecated, although typescript-eslint's
156
+ `no-deprecated` also flags references such as `typeof defineReactor`: do not
157
+ switch a raw-value setup to `defineDisplayReactor` to silence it.
158
+
159
+ ```ts
160
+ // src/reactor.ts
161
+ import { defineDisplayReactor } from "@ic-reactor/react"
162
+ import { canisterId, idlFactory, type _SERVICE } from "./declarations/backend"
163
+
164
+ export const backendApp = defineDisplayReactor<_SERVICE>({
165
+ name: "backend",
166
+ idlFactory,
167
+ // Required unless the Vite plugin injects it on a local replica.
168
+ canisterId,
169
+ })
170
+
171
+ export const {
172
+ reactor: backend,
173
+ useActorQuery,
174
+ useActorMutation,
175
+ useAuth,
176
+ } = backendApp
177
+ ```
178
+
179
+ The result holds the six hooks of `createActorHooks` (`useActorQuery`,
180
+ `useActorSuspenseQuery`, `useActorInfiniteQuery`,
181
+ `useActorSuspenseInfiniteQuery`, `useActorMutation`, `useActorMethod`),
182
+ `useAuth`, `useAgentState`, `useUserPrincipal`, `useIdentityAttributes`, and
183
+ `reactor`, `clientManager`, `queryClient`, `authentication` and
184
+ `identityAttributes`. `authentication` and `identityAttributes` are lazy
185
+ getters, so the optional `@icp-sdk/auth` peer loads only once auth is used.
186
+ Without the peer the app still builds; webpack-family bundlers print one
187
+ `Module not found` warning for it, silenced with
188
+ `ignoreWarnings: [{ module: /@ic-reactor\/react/, message: /@icp-sdk\/auth/ }]`.
189
+
190
+ Without `canisterId`, the reactor reads `PUBLIC_CANISTER_ID:<name>` from the
191
+ `ic_env` cookie, which `ClientManager` trusts only on a local replica
192
+ (loopback and `localhost` hosts) unless `allowEnvConfig: true` is passed. On a
193
+ server or a deployed origin the constructor then throws
194
+ `canisterId is required for "backend"`.
195
+
196
+ A second canister shares the agent and the Internet Identity session when it
197
+ gets the first result's `authentication`:
198
+
199
+ ```ts
200
+ // src/ledger.ts
201
+ import { defineReactor } from "@ic-reactor/react"
202
+ import {
203
+ canisterId as ledgerId,
204
+ idlFactory as ledgerIdl,
205
+ type _SERVICE as Ledger,
206
+ } from "./declarations/ledger"
207
+ import { backendApp } from "./reactor"
208
+
209
+ export const ledgerApp = defineReactor<Ledger>({
210
+ name: "ledger",
211
+ idlFactory: ledgerIdl,
212
+ canisterId: ledgerId,
213
+ authentication: backendApp.authentication,
214
+ })
215
+ export const ledger = ledgerApp.reactor
216
+ ```
217
+
218
+ Passing `authentication` alone is enough; its `clientManager` is adopted.
219
+ Passing a different `clientManager` alongside it throws, because sign-in would
220
+ update one agent while the reactor calls through another. Do not build a
221
+ second `AuthenticationManager` for the same app.
222
+
223
+ ## Manual Setup
224
+
225
+ Use this when construction order must be explicit:
226
+
227
+ ```ts
228
+ // src/manual.ts
229
+ import {
230
+ ClientManager,
231
+ DisplayReactor,
232
+ createActorHooks,
233
+ reactorRetry,
234
+ } from "@ic-reactor/react"
235
+ import { QueryClient } from "@tanstack/react-query"
236
+ import { canisterId, idlFactory, type _SERVICE } from "./declarations/backend"
237
+
238
+ export const queryClient = new QueryClient({
239
+ defaultOptions: { queries: { retry: reactorRetry } },
240
+ })
241
+ export const clientManager = new ClientManager({ queryClient })
242
+
243
+ export const backend = new DisplayReactor<_SERVICE>({
244
+ clientManager,
245
+ idlFactory,
246
+ name: "backend",
247
+ canisterId,
248
+ })
249
+
250
+ export const { useActorQuery, useActorMutation } = createActorHooks(backend)
251
+ ```
252
+
253
+ Keep the `<_SERVICE>` type argument: without it every argument and result is
254
+ `unknown` (`any` on an untyped `Reactor`). A `QueryClient` you create keeps
255
+ TanStack's defaults unless you set `retry: reactorRetry` as above. The hooks
256
+ bind to the reactor's own `QueryClient`; a `QueryClientProvider` is optional.
257
+
258
+ ## Queries and Mutations in Components
259
+
260
+ ```tsx
261
+ import { skipToken } from "@ic-reactor/react"
262
+ import { useActorMutation, useActorQuery } from "./reactor"
263
+
264
+ export function ProfileCard({ userId }: { userId?: string }) {
265
+ const { data, isPending, error } = useActorQuery({
266
+ functionName: "get_profile",
267
+ // No call until the id exists; never `[userId!]`
268
+ args: userId ? [userId] : skipToken,
269
+ })
270
+ const rename = useActorMutation({
271
+ functionName: "update_profile",
272
+ // Refetch every get_profile query of this canister once it succeeds
273
+ invalidateQueries: [{ functionName: "get_profile" }],
274
+ // The canister returned Err: err.code is the variant name
275
+ onCanisterError: (err) => alert(`Not saved: ${err.code}`),
276
+ })
277
+
278
+ if (!userId) return <p>Sign in first</p>
279
+ if (isPending) return <p>Loading…</p>
280
+ if (error) return <p>{error.message}</p>
281
+ return (
282
+ <button
283
+ disabled={rename.isPending}
284
+ onClick={() => rename.mutate([{ name: "Ada" }])}
285
+ >
286
+ {data.name}: {data.likes} likes
287
+ </button>
288
+ )
289
+ }
290
+ ```
291
+
292
+ - `args` is always the method's argument tuple (`[userId]`, `[]` or omitted
293
+ for no arguments), in the reactor's form (display strings above).
294
+ - `data` is the `Ok` payload of a `Result`: an `Err` becomes a `CanisterError`
295
+ in `error`, so never write `"Ok" in data`.
296
+ - A query hook takes TanStack's options too (`select`, `staleTime`,
297
+ `refetchInterval`, `enabled`, ...) and `callConfig` (`canisterId`, `agent`,
298
+ `effectiveCanisterId`) for one call.
299
+ - `skipToken` works in `useActorQuery`, `useActorInfiniteQuery` (as
300
+ `getArgs: owner ? (page) => [...] : skipToken`) and `createQueryFactory`.
301
+ The suspense hooks, `createQuery` and `createSuspenseQuery` do not take it.
302
+ Keep `enabled` for conditions that are not about missing args. Never call
303
+ `refetch()` on a skipped query.
304
+ - Call state-changing update methods only through `useActorMutation`,
305
+ `useActorMethod` or `createMutation`. A query hook or factory runs its method
306
+ again on every refetch (mount, window focus, reconnect, invalidation), and
307
+ each run of an update executes on the canister. A query of an update method
308
+ is fine only when repeating it is safe (a certified read).
309
+ - `useActorMethod` handles a query or an update method with one hook and an
310
+ imperative `call()`; use it only when that unified shape helps.
311
+
312
+ ## Reusable Query and Mutation Objects
313
+
314
+ Define query and mutation objects once and use them in components, loaders,
315
+ actions and tests. In a client-only app they live at module scope; in a
316
+ server-rendered app build them inside the `createReactorProvider` factory.
317
+
318
+ ```ts
319
+ // src/queries.ts
320
+ import {
321
+ createMutation,
322
+ createQuery,
323
+ createQueryFactory,
324
+ } from "@ic-reactor/react"
325
+ import { backend } from "./reactor"
326
+
327
+ export const postsQuery = createQuery(backend, { functionName: "get_posts" })
328
+ export const getPost = createQueryFactory(backend, { functionName: "get_post" })
329
+
330
+ export const createPost = createMutation(backend, {
331
+ functionName: "create_post",
332
+ invalidateQueries: [postsQuery, { functionName: "get_posts_count" }],
333
+ })
334
+ export const likePost = createMutation(backend, { functionName: "like_post" })
335
+ ```
336
+
337
+ | Need | Use |
338
+ | ------------------------------ | ---------------------------------------------------------------------------- |
339
+ | A query method without args | `createQuery` (or `createSuspenseQuery`) |
340
+ | A query method whose args vary | `createQueryFactory` (or `createSuspenseQueryFactory`), called with the args |
341
+ | Paginated reads | `createInfiniteQuery`, `createSuspenseInfiniteQuery` (and their factories) |
342
+ | An update method | `createMutation` |
343
+
344
+ Inside React: `postsQuery.useQuery()`, `getPost([id]).useQuery()`,
345
+ `createPost.useMutation(options)`; `.useSuspenseQuery()`,
346
+ `.useInfiniteQuery()` and `.useSuspenseInfiniteQuery()` on the other kinds.
347
+
348
+ Outside React:
349
+
350
+ ```ts
351
+ import { createPost, getPost, postsQuery } from "./queries"
352
+
353
+ export function postLoader(postId: string) {
354
+ // Cached and deduplicated; refetches as the new principal after a sign-in
355
+ return getPost([postId]).fetch()
356
+ }
357
+
358
+ export function createPostAction(title: string) {
359
+ // Resolves with the Ok payload after the factory's invalidateQueries ran;
360
+ // an Err rejects with a CanisterError
361
+ return createPost.execute([title])
362
+ }
363
+
364
+ export function refreshPosts() {
365
+ return postsQuery.invalidate() // resolves once mounted queries refetched
366
+ }
367
+ ```
368
+
369
+ A query object also has `.prefetch()`, `.getCacheData()`, `.setData()`,
370
+ `.getQueryKey()`, `.cancel()`, `.reset()` and `.optimisticUpdate()`
371
+ (`.prefetch()` and `.setData()` are not on infinite query objects). A query
372
+ factory function has `getQueryKey()` (the prefix of all its queries) and
373
+ `invalidate()`. `createQuery`, `createSuspenseQuery` and the query factories
374
+ take `callConfig` as the hooks do:
375
+ `createQuery(ledger, { functionName: "icrc1_symbol", callConfig: { canisterId: ckbtcId } })`.
376
+
377
+ Paginated reads take TanStack's `initialPageParam` and `getNextPageParam`,
378
+ plus `getArgs`, which turns a page param into the method's argument tuple:
379
+
380
+ ```ts
381
+ import { createInfiniteQuery } from "@ic-reactor/react"
382
+ import { backend } from "./reactor"
383
+
384
+ // list_posts : (record { offset : nat; limit : nat })
385
+ // -> (record { posts : vec Post; next : opt nat }) query
386
+ export const postPages = createInfiniteQuery(backend, {
387
+ functionName: "list_posts",
388
+ initialPageParam: "0", // a DisplayReactor takes a nat as text
389
+ getArgs: (offset) => [{ offset, limit: "20" }] as const,
390
+ getNextPageParam: (lastPage) => lastPage.next, // undefined: no next page
391
+ })
392
+
393
+ // In a component:
394
+ // const { data, fetchNextPage, hasNextPage } = postPages.useInfiniteQuery()
395
+ // const posts = data?.pages.flatMap((page) => page.posts) ?? []
396
+ // In a loader: await postPages.fetch()
397
+ ```
398
+
399
+ Keep `as const` on what `getArgs` returns: without it the args are inferred
400
+ as an array rather than a tuple, and `createInfiniteQuery` rejects them.
401
+ `useActorInfiniteQuery` takes the same fields.
402
+
403
+ ## Cache Invalidation and Optimistic Updates
404
+
405
+ A mutation's `invalidateQueries` (on `createMutation`, `.useMutation()`,
406
+ `useActorMutation` and `useActorMethod`) takes, per entry:
407
+
408
+ - a query object: `[postsQuery]`;
409
+ - a query factory, covering every args instance: `[getPost]`;
410
+ - a method of the mutation's own reactor, type-checked:
411
+ `{ functionName: "get_post" }` for every query of the method, or
412
+ `{ functionName: "get_post", args: [id] }` for one. It is keyed at the
413
+ canister the mutation was sent to.
414
+
415
+ The invalidation is awaited before `onSuccess`, so `onSuccess` reads fresh
416
+ data. Never hand-write a key such as `["get_posts"]`: every key starts with
417
+ the canister id, so it matches nothing. A key is the canister id and the
418
+ method name, then segments for a non-default transform (a `DisplayReactor`),
419
+ another agent or effective target given in `callConfig`, and the args. Build
420
+ one with `reactor.generateQueryKey(...)` or `query.getQueryKey()` if you need
421
+ it, and never add the canister id to a `queryKey` yourself.
422
+
423
+ `query.invalidate()`, a factory's `invalidate()` and
424
+ `reactor.invalidateQueries(...)` return a `Promise` that resolves once the
425
+ active matches have refetched (a failed refetch does not reject it). Prefix a
426
+ call you do not wait for with `void`.
427
+
428
+ For optimistic UI, return the query's `optimisticUpdate(updater)` from
429
+ `onMutate`, roll back in `onError`, and invalidate in `onSettled`:
430
+
431
+ ```tsx
432
+ import { getPost, likePost } from "./queries"
433
+
434
+ export function LikeButton({ postId }: { postId: string }) {
435
+ const { data: post } = getPost([postId]).useQuery()
436
+ const like = likePost.useMutation({
437
+ // Show the new count at once; undo it if the call fails
438
+ onMutate: ([id]) =>
439
+ getPost([id]).optimisticUpdate((cached) => ({
440
+ ...cached,
441
+ likes: (BigInt(cached.likes) + 1n).toString(),
442
+ })),
443
+ onError: (_error, _args, update) => update?.rollback(),
444
+ onSettled: (_data, _error, [id]) => getPost([id]).invalidate(),
445
+ })
446
+ return (
447
+ <button onClick={() => like.mutate([postId])}>
448
+ {post?.title}: {post?.likes}
449
+ </button>
450
+ )
451
+ }
452
+ ```
453
+
454
+ The updater gets the cached raw (pre-`select`) value and is skipped when
455
+ nothing is cached. `rollback()` does nothing after a sign-in or sign-out,
456
+ since the snapshot was the previous principal's. Do not hand-roll
457
+ `cancelQueries` / `setQueryData` snapshots. When you need the `QueryClient`
458
+ itself, use `reactor.queryClient`; `useQueryClient()` throws without a
459
+ `QueryClientProvider`.
460
+
461
+ ## Inside React vs Outside React
462
+
463
+ Only call hooks inside React components or custom hooks: `useActorQuery`,
464
+ `useActorMutation`, `useActorMethod`, `useAuth`, `.useQuery()`,
465
+ `.useMutation()`, `.useSuspenseQuery()`, `.useInfiniteQuery()`. Loaders,
466
+ actions, services, scripts and non-hook tests use:
467
+
468
+ - query objects: `.fetch()`, `.prefetch()`, `.invalidate()`,
469
+ `.getCacheData()`, `.setData()`, `.cancel()`, `.reset()`,
470
+ `.optimisticUpdate()`
471
+ - mutation objects: `.execute(args)`
472
+ - reactors: `.fetchQuery()`, `.getQueryData()`, `.invalidateQueries()`,
473
+ `.callMethod()`
474
+
475
+ `query.fetch()` and `reactor.fetchQuery()` fetch again, at most three times,
476
+ when a sign-in or sign-out switches the principal mid-fetch (after that they
477
+ reject with a `CallError`). Wrap a fetch you write against the `QueryClient`
478
+ yourself (`queryClient.fetchQuery`, `fetchInfiniteQuery`, `ensureQueryData`) in
479
+ `clientManager.fetchAcrossIdentitySwitch(() => ...)`: unwrapped, a switch can
480
+ resolve it with the previous principal's cached data. A query object's
481
+ `.prefetch()` fetches again the same way and never rejects, and a query
482
+ method's `call()` and `refetch()` from `useActorMethod` resolve with the new
483
+ principal's answer (`undefined` if that fetch fails). Loaders and services
484
+ still use `query.fetch()` or `reactor.fetchQuery()`: hooks belong in
485
+ components.
486
+
487
+ ## Several Canisters of One Interface
488
+
489
+ For a multi-token wallet, build one reactor and derive the others:
490
+ `reactor.forCanister(canisterId)` returns a memoized sibling of the same class
491
+ on the same `ClientManager`, with the same interface and validators, whose
492
+ calls and query keys use its own canister. The same id always gives the same
493
+ object, so it is safe in render and in `useMemo` dependencies. A single query
494
+ can instead take `callConfig: { canisterId }`.
495
+
496
+ ```tsx
497
+ import { useMemo } from "react"
498
+ import {
499
+ createActorHooks,
500
+ formatTokenAmount,
501
+ type ReactorArgsOf,
502
+ } from "@ic-reactor/react"
503
+ import { ledger } from "./ledger"
504
+
505
+ type Account = ReactorArgsOf<typeof ledger, "icrc1_balance_of">[0]
506
+
507
+ export function Balance({
508
+ tokenId,
509
+ account,
510
+ }: {
511
+ tokenId: string
512
+ account: Account
513
+ }) {
514
+ const token = useMemo(
515
+ () => createActorHooks(ledger.forCanister(tokenId)),
516
+ [tokenId]
517
+ )
518
+ const { data: balance } = token.useActorQuery({
519
+ functionName: "icrc1_balance_of",
520
+ args: [account],
521
+ })
522
+ const { data: decimals } = token.useActorQuery({
523
+ functionName: "icrc1_decimals",
524
+ })
525
+ if (balance === undefined || decimals === undefined) return null
526
+ return (
527
+ <span>
528
+ {formatTokenAmount(balance, decimals, { maxFractionDigits: 4 })}
529
+ </span>
530
+ )
531
+ }
532
+ ```
533
+
534
+ Do not retarget a shared reactor with `setCanisterId`, and do not build one
535
+ reactor per canister by hand.
536
+
537
+ ## Types From a Reactor
538
+
539
+ Read types off the reactor instead of copying shapes:
540
+
541
+ - `ReactorArgsOf<typeof ledger, "icrc1_transfer">[0]`: the first argument in
542
+ the reactor's form (raw or display)
543
+ - `ReactorDataOf<typeof ledger, "icrc1_transfer">`: what `callMethod`, a
544
+ mutation and `execute()` resolve with
545
+ - `ReactorErrorOf<typeof ledger, "icrc1_transfer">`: a hook's `error` type
546
+ - `ServiceOf<typeof ledger>`, `TransformOf<typeof ledger>`
547
+
548
+ They take a reactor instance's type (any `Reactor`, `DisplayReactor` or
549
+ subclass), not a query or mutation object.
550
+
551
+ ## Token Amounts and Principals
552
+
553
+ Ledger amounts are base units (e8s for ICP): a `bigint` from a `Reactor`,
554
+ integer text from a `DisplayReactor`. Never convert them with `Number`,
555
+ `parseFloat`, `Math.pow` or `toFixed`: `Math.floor(Number("0.29") * 10 ** 8)`
556
+ is 28999999.
557
+
558
+ ```ts
559
+ import { isPrincipalText, parseTokenAmount } from "@ic-reactor/react"
560
+ import { Principal } from "@icp-sdk/core/principal"
561
+ import { ledger } from "./ledger"
562
+
563
+ export async function send(to: string, text: string, decimals: number) {
564
+ if (!isPrincipalText(to.trim())) throw new Error("Not a principal")
565
+ const amount = parseTokenAmount(text, decimals) // "0.29", 8 -> 29000000n
566
+ return ledger.callMethod({
567
+ functionName: "icrc1_transfer",
568
+ args: [
569
+ {
570
+ to: { owner: Principal.fromText(to.trim()), subaccount: [] },
571
+ amount,
572
+ fee: [],
573
+ memo: [],
574
+ from_subaccount: [],
575
+ created_at_time: [],
576
+ },
577
+ ],
578
+ })
579
+ }
580
+ ```
581
+
582
+ - `formatTokenAmount(value, decimals, options?)` takes the value and
583
+ `icrc1_decimals` as a query returns them. Options: `maxFractionDigits`,
584
+ `minFractionDigits`, `trimTrailingZeros`, `roundingMode`, `locale`,
585
+ `useGrouping`. It truncates past `maxFractionDigits` unless
586
+ `roundingMode: "halfExpand"`, and writes plain text (`"1234.5"`) unless given
587
+ a `locale`.
588
+ - `parseTokenAmount(text, decimals)` returns a `bigint`. It throws a
589
+ `TypeError` for text that is not digits with at most one `.` and a
590
+ `RangeError` for more fraction digits than the token has or a negative
591
+ amount (`{ allowNegative: true }` for an `int`). Send `amount.toString()` to
592
+ a `DisplayReactor`.
593
+ - `isPrincipalText(text.trim())` validates typed principal text; do not wrap
594
+ `Principal.fromText` in a `try`. A `DisplayReactor` takes the text, a
595
+ `Reactor` takes `Principal.fromText(text)`.
596
+ - `jsonToString(value)` prints a raw result, with bigints as digits,
597
+ principals as text and blobs as hex.
598
+
599
+ All four are plain functions in core, re-exported by `@ic-reactor/react` and by
600
+ its `react-server` entry.
601
+
602
+ ## Server Rendering (SSR and RSC)
603
+
604
+ A reactor owns its `QueryClient`, and query keys carry no caller principal. A
605
+ reactor at module scope on a server is therefore one cache shared by every
606
+ request, and a caller-scoped result (`get_my_profile`, a balance of self) is
607
+ served to the next visitor. `AuthenticationManager` signs in on its
608
+ `ClientManager`'s agent, so it belongs in the same request as that manager.
609
+ Build the reactor, `ClientManager`, `AuthenticationManager` and any query or
610
+ mutation objects inside the request. A bare `defineReactor(...)` in a module
611
+ body is still module scope.
612
+
613
+ Client components in a server-rendered app use `createReactorProvider`:
614
+
615
+ ```tsx
616
+ "use client"
617
+ import {
618
+ createReactorProvider,
619
+ defineReactor,
620
+ skipToken,
621
+ } from "@ic-reactor/react"
622
+ import { canisterId, idlFactory, type _SERVICE } from "../declarations/backend"
623
+
624
+ // The factory runs once per mounted provider: once per request on a server
625
+ export const { ReactorProvider, useReactor } = createReactorProvider(() =>
626
+ defineReactor<_SERVICE>({ name: "backend", idlFactory, canisterId })
627
+ )
628
+
629
+ // app/layout.tsx (a Server Component) wraps the app:
630
+ // <ReactorProvider>{children}</ReactorProvider>
631
+
632
+ export function MyProfile() {
633
+ const { useActorQuery, useAuth } = useReactor()
634
+ const { isAuthenticated, isAuthenticating, login } = useAuth()
635
+ const { data } = useActorQuery({
636
+ functionName: "get_my_profile",
637
+ args: isAuthenticated ? [] : skipToken,
638
+ })
639
+ // true until the stored session has been checked, and in every server render
640
+ if (isAuthenticating) return <p>Checking session…</p>
641
+ if (!isAuthenticated)
642
+ return <button onClick={() => void login()}>Sign in</button>
643
+ return <h1>{data?.name}</h1>
644
+ }
645
+ ```
646
+
647
+ - `ReactorProvider` and `useReactor` are what the app destructures, not
648
+ package exports. Call `createReactorProvider` at module scope, never inside a
649
+ component, and take hooks from `useReactor()` rather than calling
650
+ `createActorHooks` or `createAuthHooks` in a component.
651
+ - The factory may return a record (`{ backend, ledger, posts }`, with query
652
+ objects built inside it), read with `useReactor("ledger")`. `useReactor()` is
653
+ typed as the factory's return: never write `as any` hook forwarders.
654
+ - The factory receives the provider's props other than `children`, read once
655
+ per mount; give the provider a new `key` to build again.
656
+ - On unmount the provider disposes the `AuthenticationManager`s built for its
657
+ value and leaves managers built elsewhere alone. When the value holds
658
+ exactly one `QueryClient` (every reactor in it built on one
659
+ `ClientManager`, as passing `authentication` on does), it renders a
660
+ `QueryClientProvider` for it, so `useQueryClient()` and `HydrationBoundary`
661
+ below it use the cache the hooks fill; pass `{ queryClientProvider: false }`
662
+ to keep your own.
663
+ - A provider mounted by a transition (router navigation, `startTransition`)
664
+ needs a `<Suspense>` boundary inside it around suspending components.
665
+
666
+ A React Server Component, server action or route handler imports the core
667
+ runtime from `@ic-reactor/react`: its `react-server` export condition resolves
668
+ to an entry that loads no React.
669
+
670
+ ```tsx
671
+ // app/Supply.tsx: a React Server Component
672
+ import { ClientManager, Reactor, formatTokenAmount } from "@ic-reactor/react"
673
+ import { QueryClient } from "@tanstack/react-query"
674
+ import { canisterId, idlFactory, type _SERVICE } from "../declarations/ledger"
675
+
676
+ export default async function Supply() {
677
+ // Built inside the request: a module-scope reactor would share its cache
678
+ // with every visitor
679
+ const clientManager = new ClientManager({
680
+ queryClient: new QueryClient(),
681
+ agentOptions: { host: "https://ic0.app" },
682
+ })
683
+ const ledger = new Reactor<_SERVICE>({
684
+ name: "ledger",
685
+ clientManager,
686
+ idlFactory,
687
+ canisterId,
688
+ })
689
+ const [supply, decimals] = await Promise.all([
690
+ ledger.fetchQuery({ functionName: "icrc1_total_supply" }),
691
+ ledger.fetchQuery({ functionName: "icrc1_decimals" }),
692
+ ])
693
+ return <p>{formatTokenAmount(supply, decimals, { maxFractionDigits: 0 })}</p>
694
+ }
695
+ ```
696
+
697
+ Hooks, `defineReactor`, `defineDisplayReactor`, `createReactorProvider`,
698
+ `createActorHooks`, the query/mutation factories, `skipToken`, the auth classes
699
+ and the identity-attribute helpers are missing exports in the `react-server`
700
+ graph (`next build`: "Export X doesn't exist in target module"). When the RSC
701
+ bundler ignores the `react-server` condition, add `@ic-reactor/core` as a
702
+ dependency and import the runtime from it instead. Generated canister modules
703
+ (hooks and `factories: true` objects) import hooks, so a server component must
704
+ not import them.
705
+
706
+ Module scope stays correct in client-only apps.
707
+
708
+ ## Authentication
709
+
710
+ `defineReactor` already returns `useAuth`, `useAgentState`,
711
+ `useUserPrincipal`, `useIdentityAttributes`, `authentication` and
712
+ `identityAttributes`. With a manual setup:
713
+
714
+ ```ts
715
+ import {
716
+ AuthenticationManager,
717
+ IdentityAttributesManager,
718
+ createAuthHooks,
719
+ createIdentityAttributeHooks,
720
+ hexToUint8Array,
721
+ } from "@ic-reactor/react"
722
+ import { backend, clientManager } from "./manual"
723
+
724
+ export const authentication = new AuthenticationManager({ clientManager })
725
+ export const { useAuth, useAgentState, useUserPrincipal } =
726
+ createAuthHooks(authentication)
727
+
728
+ export const identityAttributes = new IdentityAttributesManager(authentication)
729
+ export const { useIdentityAttributes } =
730
+ createIdentityAttributeHooks(identityAttributes)
731
+
732
+ // In a click handler: pass the nonce as a callback so the popup opens within
733
+ // the user gesture. A DisplayReactor returns a blob as hex.
734
+ export const requestEmail = () =>
735
+ identityAttributes.request({
736
+ keys: ["email"],
737
+ nonce: async () =>
738
+ hexToUint8Array(
739
+ await backend.callMethod({ functionName: "register_begin" })
740
+ ),
741
+ })
742
+ ```
743
+
744
+ - `createAuthHooks` takes an `AuthenticationManager`, never a `ClientManager`,
745
+ and returns exactly `useAuth`, `useAgentState` and `useUserPrincipal`.
746
+ `useIdentityAttributes` comes only from `createIdentityAttributeHooks`.
747
+ - `useAuth()` returns `login`, `logout`, `authenticate`, `isAuthenticated`,
748
+ `isAuthenticating`, `principal`, `identity` and `error`. Read the principal
749
+ from it (or `useUserPrincipal()`), not from `identity.getPrincipal()` in
750
+ your own state.
751
+ - `useAuth()` reports `isAuthenticating: true` from the first render, and in
752
+ every server render, until the first session restore settles (a failed
753
+ restore counts as settled). Guard a protected route with
754
+ `if (isAuthenticating)` before `if (!isAuthenticated)`.
755
+ - Awaiting a nonce before `request()` ends the user gesture, and the browser
756
+ blocks the Internet Identity window; pass the nonce as a callback. With a raw
757
+ `Reactor`, the blob is already a `Uint8Array`:
758
+ `nonce: () => backend.callMethod({ ... })`.
759
+ - `authentication.dispose()` releases the auth client the manager built. It
760
+ does not sign out, and a later `login()` builds a new client, so it is safe
761
+ in a StrictMode effect cleanup. `createReactorProvider` calls it for you.
762
+ - On `@icp-sdk/auth` v10 a manager follows sign-outs and account switches made
763
+ in other tabs.
764
+ - A sign-in, sign-out or account switch cancels the fetches in flight of
765
+ every canister the `ClientManager` has a reactor for, removes their inactive
766
+ cache entries and refetches mounted queries as the new principal. A renewed
767
+ delegation for the same principal keeps the cache.
768
+
769
+ Local Internet Identity:
770
+ `localInternetIdentityProvider(port, canisterId?, authorizePath?)` builds
771
+ `http://<canisterId>.localhost:<port>/authorize`, and
772
+ `authentication.prepareClient()` probes the canister for `/authorize` or the
773
+ legacy `/#authorize`. Only Internet Identity builds up to `release-2026-03-16`
774
+ serve a local frontend; a login that hangs on the gateway's "Response
775
+ Verification Error" page is an unsupported build.
776
+
777
+ ## Errors and Retries
778
+
779
+ | Error | Source | Handle with |
780
+ | ----------------- | ----------------------------------------------------------- | ---------------------------------------------------------------- |
781
+ | `CanisterError` | the canister returned `Err` | `onCanisterError` on mutations, `isCanisterError(e)` elsewhere |
782
+ | `CallError` | network, agent, certificate, a trap, a validator that threw | `onError`, `isCallError(e)` |
783
+ | `ValidationError` | a `DisplayReactor` validator refused the arguments | `isValidationError(e)`, `mapValidationErrors(e)` for form fields |
784
+
785
+ ```ts
786
+ import {
787
+ isCallError,
788
+ isCanisterError,
789
+ isValidationError,
790
+ } from "@ic-reactor/react"
791
+ import { backend } from "./reactor"
792
+
793
+ export async function rename(name: string) {
794
+ try {
795
+ return await backend.callMethod({
796
+ functionName: "update_profile",
797
+ args: [{ name }],
798
+ })
799
+ } catch (error) {
800
+ if (isCanisterError(error)) {
801
+ // The canister's Err value: error.err, variant name: error.code
802
+ return `Refused: ${error.code}`
803
+ }
804
+ if (isValidationError(error)) return `Invalid: ${error.message}`
805
+ if (isCallError(error)) return `Network or agent failure: ${error.message}`
806
+ throw error
807
+ }
808
+ }
809
+ ```
810
+
811
+ `CanisterError` carries the canister's error value on `.err`, not `.detail`,
812
+ `.data` or `.message`. `.code` is the variant key, or the `code` field when the
813
+ payload has the API shape (`code`, `message`, `details`). `.details` is that
814
+ payload's `details` field as decoded, never a `Map`. The guards also recognise
815
+ errors from another copy of the package; prefer them to `instanceof`.
816
+
817
+ Retries:
818
+
819
+ - `reactorRetry` (predicate `isRetryableReactorError`) is the query retry of
820
+ the `QueryClient` that `defineReactor` and `defineDisplayReactor` create. In
821
+ a browser it retries transport, certificate, HTTP 5xx/408/429 and
822
+ `SysTransient`/`SysUnknown` failures up to 3 times, and never a
823
+ `CanisterError`, a `ValidationError`, an encode/decode failure or another
824
+ HTTP 4xx (an expired delegation's 400, a 403).
825
+ - A query of an update method with no `retry` of its own retries only a
826
+ `SysTransient` rejection, within the `QueryClient`'s retry default.
827
+ - Mutations retry nothing unless `retry` is set on them or as the
828
+ `QueryClient`'s `mutations.retry` default, which also reaches
829
+ `createMutation().execute()` and `useActorMethod` update calls. Each retry
830
+ of an update is a new call the canister runs, so use
831
+ `retry: reactorUpdateRetry` (predicate `isRetryableUpdateError`), which
832
+ retries only `SysTransient`, never a number.
833
+ - `reactorRetry` and `reactorUpdateRetry` return `false` wherever there is no
834
+ `window` (Node scripts, server rendering, web workers), as TanStack Query
835
+ retries nothing on a server by default; the agent still resends a failed
836
+ HTTP request itself (3 times by default). For query retries in a Node
837
+ script, pass the predicate:
838
+ `retry: (count, error) => count < 3 && isRetryableReactorError(error)`.
839
+
840
+ ## Code Generation
841
+
842
+ Use generated code when there are many canisters, `.did` files change often,
843
+ or you want consistent typed exports.
844
+
845
+ | Tool | Use when |
846
+ | ------------------------- | --------------------------------------------------------------------- |
847
+ | `@ic-reactor/vite-plugin` | Vite app: generates on start and on `.did` changes, injects local ids |
848
+ | `@ic-reactor/cli` | Any other project, CI, or explicit `ic-reactor generate` runs |
849
+ | `@ic-reactor/codegen` | Custom tooling only (`runCanisterPipeline`) |
850
+
851
+ ```ts
852
+ // vite.config.ts
853
+ import { defineConfig, loadEnv } from "vite"
854
+ import { icReactor } from "@ic-reactor/vite-plugin"
855
+
856
+ export default defineConfig(({ mode }) => {
857
+ const env = loadEnv(mode, process.cwd(), "")
858
+ return {
859
+ plugins: [
860
+ icReactor({
861
+ canisters: [
862
+ {
863
+ name: "backend",
864
+ didFile: "./backend/backend.did",
865
+ factories: true,
866
+ // Written into the generated reactor, and used under `vite dev`
867
+ // too in place of the local id: set it per environment
868
+ canisterId: env.CANISTER_ID_BACKEND,
869
+ },
870
+ ],
871
+ }),
872
+ ],
873
+ }
874
+ })
875
+ ```
876
+
877
+ The CLI reads the same per-canister fields from `ic-reactor.json`
878
+ (`pnpm exec ic-reactor init`, then `pnpm exec ic-reactor generate`). Each
879
+ canister's output directory holds:
880
+
881
+ - `declarations/`: the IDL factory and `_SERVICE` types;
882
+ - `index.generated.ts` (managed, rewritten on every run): the reactor
883
+ (`backendReactor`, a `DisplayReactor` unless `mode` names another class) and
884
+ six bound hooks named after the canister (`useBackendQuery`,
885
+ `useBackendMutation`, ...);
886
+ - `index.factories.generated.ts` (managed, only with `factories: true` and
887
+ `target: "react"`): a `<method>Query` per query method (`createQuery`, or
888
+ `createQueryFactory` when it takes args) and a `<method>Mutation`
889
+ (`createMutation`) per update or oneway method, each `/* @__PURE__ */` so
890
+ unused ones are tree-shaken;
891
+ - `index.ts` (created once, yours to edit): re-exports `index.generated.ts`,
892
+ and the factories file with `factories: true`. Put custom factories,
893
+ invalidation wiring and helpers here; an export with the same name replaces
894
+ the generated one.
895
+
896
+ Never edit the managed files. Prefer `factories: true` over hand-written
897
+ per-method factory modules. The generated modules are module scope, so they
898
+ are client-only; on a server build the reactor per request. Without
899
+ `canisterId`, the generated reactor reads its id from the `ic_env` cookie,
900
+ which works only on a local replica (or with `allowEnvConfig: true`), so
901
+ importing it throws `canisterId is required` in Node, during SSR and on a
902
+ deployed origin.
903
+
904
+ ## Dynamic Candid and the Parser
905
+
906
+ Use `@ic-reactor/candid` for explorers, dev tools and forms over canisters
907
+ whose interface is known only at run time: `CandidAdapter` fetches and parses
908
+ Candid, `CandidReactor` / `CandidDisplayReactor` call it dynamically, and
909
+ `MetadataReactor` / `MetadataDisplayReactor` produce form and result metadata.
910
+ `forCanister` works on all four. `@ic-reactor/parser` is a dependency of
911
+ candid and loads on first parse. To parse Candid yourself, import it from its
912
+ single entrypoint:
913
+
914
+ ```ts
915
+ import init, { didToJs, parseDid, validateIDL } from "@ic-reactor/parser"
916
+
917
+ await init() // required on the web build (browsers, bundlers); a no-op on Node
918
+ const schema = parseDid("service : { greet : (text) -> (text) query }")
919
+ console.log(schema.service?.methods) // [{ name: "greet", mode: "query", ... }]
920
+ ```
921
+
922
+ There are no `/web`, `/nodejs` or `/bundler` subpaths; conditional exports pick
923
+ the browser or Node build. Do not deep-import `dist/`. `validateIDL` throws the
924
+ parser's message for invalid Candid instead of returning `false`, and
925
+ `didToJs` / `didToTs` return source strings.
926
+
927
+ ## Testing
928
+
929
+ Run the real reactor and hooks against the fake replica from
930
+ `@ic-reactor/react/testing` (`@ic-reactor/core/testing` without React). Do not
931
+ stub a reactor with `as unknown as Reactor`, and do not hard-code query keys in
932
+ tests.
933
+
934
+ ```ts
935
+ import { afterEach, beforeEach, expect, it } from "vitest"
936
+ import { QueryClient } from "@tanstack/react-query"
937
+ import { ClientManager, Reactor, isCanisterError } from "@ic-reactor/react"
938
+ import {
939
+ createTestCanister,
940
+ installFakeReplica,
941
+ type FakeReplica,
942
+ } from "@ic-reactor/react/testing"
943
+ import { canisterId, idlFactory, type _SERVICE } from "./declarations/backend"
944
+
945
+ let replica: FakeReplica
946
+ let backend: Reactor<_SERVICE>
947
+
948
+ beforeEach(() => {
949
+ // Install the fake before any ClientManager or agent is built
950
+ replica = installFakeReplica({
951
+ canisters: {
952
+ [canisterId]: createTestCanister<_SERVICE>(idlFactory, {
953
+ // Handlers get the decoded args and { caller } and return raw Candid
954
+ greet: ([name]) => `Hello, ${name}!`,
955
+ update_profile: () => ({ Err: { NotFound: null } }),
956
+ }),
957
+ },
958
+ })
959
+ backend = new Reactor<_SERVICE>({
960
+ clientManager: new ClientManager({
961
+ queryClient: new QueryClient(),
962
+ agentOptions: { host: replica.host },
963
+ }),
964
+ name: "backend",
965
+ canisterId,
966
+ idlFactory,
967
+ })
968
+ })
969
+ afterEach(() => replica.restore())
970
+
971
+ it("greets", async () => {
972
+ await expect(
973
+ backend.fetchQuery({ functionName: "greet", args: ["Ada"] })
974
+ ).resolves.toBe("Hello, Ada!")
975
+ })
976
+
977
+ it("turns an Err into a CanisterError", async () => {
978
+ const error = await backend
979
+ .callMethod({ functionName: "update_profile", args: [{ name: "" }] })
980
+ .catch((e: unknown) => e)
981
+ expect(isCanisterError(error) && error.code).toBe("NotFound")
982
+ })
983
+ ```
984
+
985
+ - A handler returns `{ Err: ... }` for a `CanisterError`, and throws for the
986
+ `CallError` of a trap.
987
+ - For a module-scope `defineReactor(...)`, install the fake at the top of the
988
+ test file (or in a setup file) and `await import(...)` the components after
989
+ it. With no `host` on either side, both use the page origin in jsdom or
990
+ happy-dom. Reset a shared reactor between tests with `queryClient.clear()`.
991
+ - Generated code is module scope too: its entry imports your `clientManager`.
992
+ Import `idlFactory` and `_SERVICE` from the canister's `declarations/`
993
+ folder (it builds nothing), key the fake by the `canisterId` the generator
994
+ wrote into `index.generated.ts`, and `await import(...)` the entry and the
995
+ components after the fake. Vitest runs `vite.config.ts` (unless a
996
+ `vitest.config.ts` replaces it), so the Vite plugin generates again in mode
997
+ `test`: set the variable a `loadEnv` `canisterId` comes from in
998
+ `.env.test`, or importing the regenerated entry throws
999
+ `canisterId is required`.
1000
+ - Test a signed-in user with `clientManager.updateAgent(identity)`, for
1001
+ example `Ed25519KeyIdentity.generate()`; the kit does not simulate Internet
1002
+ Identity.
1003
+ - The kit signs with `@noble/curves`, an optional peer that `@icp-sdk/core`
1004
+ already installs; add it as a devDependency under a strict install.
1005
+
1006
+ ## Do Not
1007
+
1008
+ - Call hooks in loaders, actions, services or scripts.
1009
+ - Create hooks (`createActorHooks`, `createAuthHooks`) on every render: build
1010
+ them at module scope, in a `useMemo` keyed by what they depend on, or take
1011
+ them from `useReactor()`.
1012
+ - Put a state-changing update method in a query hook or query factory
1013
+ (`useActorQuery`, `createQuery`, `createQueryFactory`, the infinite and
1014
+ suspense variants); use a mutation.
1015
+ - Give an update mutation, `useActorMethod` or a `mutations.retry` default a
1016
+ numeric `retry`; use `retry: reactorUpdateRetry`.
1017
+ - Hand-write query keys (`["get_posts"]`) or add the canister id to a
1018
+ `queryKey`; pass query objects, query factories or
1019
+ `{ functionName, args? }` to `invalidateQueries`.
1020
+ - Write `args: [userId!]`, placeholder args, or `as any` plus `enabled` for
1021
+ args not known yet; pass `skipToken`.
1022
+ - Check `"Ok" in data`: a `Result` is already unwrapped, and an `Err` throws.
1023
+ - Do token math with `Number(x) / 10 ** decimals`, `parseFloat`, `Math.pow` or
1024
+ `toFixed`; use `formatTokenAmount` / `parseTokenAmount`.
1025
+ - Retarget a shared reactor with `setCanisterId`; use
1026
+ `reactor.forCanister(canisterId)`.
1027
+ - Write `defineReactor({ display: true })`; use `defineDisplayReactor`.
1028
+ - Build a reactor, `ClientManager` or `AuthenticationManager` at module scope
1029
+ in a server-rendered app, or import hooks into a server component.
1030
+ - Pass a `ClientManager` to `createAuthHooks`, or build a second
1031
+ `AuthenticationManager` instead of passing `authentication` on.
1032
+ - Use `useQueryClient()` for cache writes, or hand-roll `setQueryData`
1033
+ snapshots for optimistic UI; use `reactor.queryClient` and
1034
+ `optimisticUpdate`.
1035
+ - Stub a `Reactor` with `as unknown as Reactor` in tests.
1036
+ - Edit `index.generated.ts` or `index.factories.generated.ts`, or repeat
1037
+ per-method factories that `factories: true` generates.
1038
+ - Leave out the `<_SERVICE>` type argument, or cast hooks to `any`.
1039
+
1040
+ ## Links
1041
+
1042
+ - Documentation: https://ic-reactor.b3pay.net/v3/
1043
+ - Index for agents: https://ic-reactor.b3pay.net/llms.txt
1044
+ - Changelog: https://github.com/B3Pay/ic-reactor/blob/main/CHANGELOG.md
1045
+ - Agent skill: https://github.com/B3Pay/ic-reactor/tree/main/skill-packages/ic-reactor
1046
+ - React setup: https://ic-reactor.b3pay.net/v3/framework/react-setup.md
1047
+ - Queries: https://ic-reactor.b3pay.net/v3/framework/queries.md
1048
+ - Mutations: https://ic-reactor.b3pay.net/v3/framework/mutations.md
1049
+ - Authentication: https://ic-reactor.b3pay.net/v3/guides/authentication.md
1050
+ - Error handling: https://ic-reactor.b3pay.net/v3/guides/error-handling.md
1051
+ - Testing: https://ic-reactor.b3pay.net/v3/guides/testing.md
1052
+ - createReactorProvider: https://ic-reactor.b3pay.net/v3/reference/createReactorProvider.md
1053
+ - Next.js App Router example: https://ic-reactor.b3pay.net/v3/examples/nextjs-app-router.md