@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,1492 @@
1
+ // The form engine: a draft tree over @meantjs/schema's public API, with
2
+ // no React in it. Ported from the candid-forms lab (engine.ts), with its
3
+ // fixes: own-property reads and writes for keys like "__proto__",
4
+ // inhabitation-aware defaults, a tolerant draftFromValue, and issues on the
5
+ // codec's `$args[i]…` paths.
6
+ //
7
+ // Value model: exactly what validate()/encodeArgs() and ic-reactor accept.
8
+ // bigint (nat, int, nat64, int64) | number (nat8…int32, float32/64)
9
+ // | string (text) | boolean | null | Principal (canonical text)
10
+ // | Uint8Array (blob) | T | null (opt) | { some: T } | null (boxed opt)
11
+ // | T[] (vec) | {} (unit) | object (record) | array (tuple)
12
+ // | { tag } / { tag, value } (variant) | { principal, method } (func)
13
+ // | Principal (service)
14
+ import {
15
+ isBoxedOpt,
16
+ isPrincipal,
17
+ type AnyFieldSchema,
18
+ type AnySchema,
19
+ type ResolvedNode,
20
+ } from "@meantjs/schema"
21
+ import { encodeArgs } from "@meantjs/schema/codec"
22
+ import { validate } from "@meantjs/schema/validate"
23
+ import { toHex } from "../lib/hex.ts"
24
+ import { toVars } from "../lib/reactor.ts"
25
+ import {
26
+ armOf,
27
+ armsOf,
28
+ childPath,
29
+ displayLabel,
30
+ elementsOf,
31
+ fieldsOf,
32
+ getOwn,
33
+ isBytes,
34
+ isTagOnly,
35
+ numericLabelId,
36
+ orderFields,
37
+ resolve,
38
+ setOwn,
39
+ withOwn,
40
+ type RecordNode,
41
+ type TupleNode,
42
+ type VariantNode,
43
+ } from "../lib/schema.ts"
44
+
45
+ // Resolution, typed accessors, own-property access and labels live in
46
+ // lib/schema.ts (the value viewers use them too); the engine re-exports them
47
+ // as part of its surface.
48
+ export {
49
+ armOf,
50
+ armsOf,
51
+ childPath,
52
+ displayLabel,
53
+ elementsOf,
54
+ fieldsOf,
55
+ getOwn,
56
+ isBytes,
57
+ numericLabelId,
58
+ orderFields,
59
+ resolve,
60
+ setOwn,
61
+ withOwn,
62
+ }
63
+
64
+ // ---------------------------------------------------------------------------
65
+ // Paths: validate()'s grammar. `$`, `.ident`, `["quoted key"]`, `[index]`.
66
+ // An unboxed opt's inner shares the opt's path; a boxed opt's inner is
67
+ // `.some`; a variant's payload is `.value` (tag issues at `.tag`); a func
68
+ // reference's parts are `.principal` and `.method`.
69
+ // ---------------------------------------------------------------------------
70
+
71
+ /** Namespaces a per-argument `$…` path the way encodeArgs reports: `$args[i]…`. */
72
+ export function argPath(index: number, path = "$"): string {
73
+ return `$args[${index}]${path.slice(1)}`
74
+ }
75
+
76
+ /**
77
+ * An argument for people: its name in the .did when it has one
78
+ * (`(sequence_number : nat)`), "argument" when it is the only one, else
79
+ * "argument 2" (counted from 1).
80
+ */
81
+ export function argLabel(
82
+ index: number,
83
+ argCount: number,
84
+ names?: readonly (string | undefined)[]
85
+ ): string {
86
+ const name = names?.[index]
87
+ if (name !== undefined && name !== "") return name
88
+ return argCount === 1 ? "argument" : `argument ${index + 1}`
89
+ }
90
+
91
+ /**
92
+ * A path for people, named like the form's labels: `$args[0].to.owner` →
93
+ * "to.owner" for a one-argument method, "argument 2.to.owner" for
94
+ * `$args[1]…` of several, "argument[3]" for an item of a lone vec.
95
+ */
96
+ export function pathLabel(
97
+ path: string,
98
+ argCount: number,
99
+ names?: readonly (string | undefined)[]
100
+ ): string {
101
+ const match = /^\$args\[(\d+)\](.*)$/.exec(path)
102
+ if (match === null) return path === "$" ? "arguments" : path
103
+ const [, index = "0", rest = ""] = match
104
+ const arg = argLabel(Number(index), argCount, names)
105
+ if (argCount === 1 && rest.startsWith(".")) return rest.slice(1)
106
+ return `${arg}${rest}`
107
+ }
108
+
109
+ // ---------------------------------------------------------------------------
110
+ // Controls: which editor a resolved node calls for.
111
+ // ---------------------------------------------------------------------------
112
+
113
+ const FIXED: Readonly<Record<string, readonly [number, number]>> = {
114
+ nat8: [0, 255],
115
+ nat16: [0, 65_535],
116
+ nat32: [0, 4_294_967_295],
117
+ int8: [-128, 127],
118
+ int16: [-32_768, 32_767],
119
+ int32: [-2_147_483_648, 2_147_483_647],
120
+ }
121
+ const BIG: Readonly<Record<string, { min?: bigint; max?: bigint }>> = {
122
+ nat: { min: 0n },
123
+ int: {},
124
+ nat64: { min: 0n, max: 2n ** 64n - 1n },
125
+ int64: { min: -(2n ** 63n), max: 2n ** 63n - 1n },
126
+ }
127
+
128
+ export interface ArmControl {
129
+ readonly tag: string
130
+ readonly tagOnly: boolean
131
+ /** No finite value exists for the payload: the arm cannot be chosen. */
132
+ readonly uninhabited: boolean
133
+ readonly schema: AnyFieldSchema
134
+ }
135
+
136
+ export type Control =
137
+ | { readonly control: "text" }
138
+ | { readonly control: "bool" }
139
+ | {
140
+ readonly control: "bigint"
141
+ readonly primitive: string
142
+ readonly min?: bigint
143
+ readonly max?: bigint
144
+ }
145
+ | {
146
+ readonly control: "integer"
147
+ readonly primitive: string
148
+ readonly min: number
149
+ readonly max: number
150
+ }
151
+ | { readonly control: "float"; readonly bits: 32 | 64 }
152
+ | { readonly control: "principal" }
153
+ | { readonly control: "fixed"; readonly what: "null" | "reserved" | "unit" }
154
+ | { readonly control: "uninhabited" }
155
+ | { readonly control: "bytes" }
156
+ | {
157
+ readonly control: "optional"
158
+ readonly boxed: boolean
159
+ readonly inner: AnyFieldSchema
160
+ }
161
+ | { readonly control: "list"; readonly item: AnyFieldSchema }
162
+ | {
163
+ readonly control: "group"
164
+ readonly fields: readonly (readonly [string, AnyFieldSchema])[]
165
+ }
166
+ | { readonly control: "tuple"; readonly elements: readonly AnyFieldSchema[] }
167
+ | { readonly control: "choice"; readonly arms: readonly ArmControl[] }
168
+ | { readonly control: "funcReference"; readonly mode: string }
169
+ | { readonly control: "serviceReference" }
170
+
171
+ const controls = new WeakMap<ResolvedNode, Control>()
172
+
173
+ export function controlOf(schema: AnyFieldSchema): Control {
174
+ const node = resolve(schema)
175
+ let control = controls.get(node)
176
+ if (control === undefined) {
177
+ control = computeControl(node)
178
+ controls.set(node, control)
179
+ }
180
+ return control
181
+ }
182
+
183
+ function computeControl(node: ResolvedNode): Control {
184
+ switch (node.kind) {
185
+ case "primitive": {
186
+ const p = node.primitive
187
+ const big = BIG[p]
188
+ const fixed = FIXED[p]
189
+ if (p === "text") return { control: "text" }
190
+ if (p === "bool") return { control: "bool" }
191
+ if (big !== undefined) return { control: "bigint", primitive: p, ...big }
192
+ if (fixed !== undefined)
193
+ return {
194
+ control: "integer",
195
+ primitive: p,
196
+ min: fixed[0],
197
+ max: fixed[1],
198
+ }
199
+ if (p === "float32") return { control: "float", bits: 32 }
200
+ if (p === "float64") return { control: "float", bits: 64 }
201
+ if (p === "principal") return { control: "principal" }
202
+ if (p === "null" || p === "reserved") return { control: "fixed", what: p }
203
+ if (p === "empty") return { control: "uninhabited" }
204
+ throw new TypeError(`unknown primitive ${p}`)
205
+ }
206
+ case "opt":
207
+ return { control: "optional", boxed: isBoxedOpt(node), inner: node.inner }
208
+ case "vec":
209
+ return { control: "list", item: node.inner }
210
+ case "blob":
211
+ return { control: "bytes" }
212
+ case "unit":
213
+ return { control: "fixed", what: "unit" }
214
+ case "record":
215
+ return { control: "group", fields: fieldsOf(node) }
216
+ case "tuple":
217
+ return { control: "tuple", elements: elementsOf(node) }
218
+ case "variant":
219
+ return {
220
+ control: "choice",
221
+ arms: armsOf(node).map(([tag, schema]) => ({
222
+ tag,
223
+ tagOnly: isTagOnly(schema),
224
+ uninhabited: isUninhabited(schema),
225
+ schema,
226
+ })),
227
+ }
228
+ case "func":
229
+ return { control: "funcReference", mode: node.mode }
230
+ case "service":
231
+ return { control: "serviceReference" }
232
+ default: {
233
+ const never: never = node
234
+ throw new TypeError(`unknown kind ${(never as { kind: string }).kind}`)
235
+ }
236
+ }
237
+ }
238
+
239
+ /** Whether a field is optional (`opt`), so it may be left out (null). */
240
+ export function isOptional(schema: AnyFieldSchema): boolean {
241
+ return resolve(schema).kind === "opt"
242
+ }
243
+
244
+ /** A short Candid type for labels: "nat", "opt blob", "vec record", "variant". */
245
+ export function typeName(schema: AnyFieldSchema, depth = 0): string {
246
+ const node = resolve(schema)
247
+ switch (node.kind) {
248
+ case "primitive":
249
+ return node.primitive
250
+ case "opt":
251
+ return depth > 1 ? "opt …" : `opt ${typeName(node.inner, depth + 1)}`
252
+ case "vec":
253
+ return depth > 1 ? "vec …" : `vec ${typeName(node.inner, depth + 1)}`
254
+ case "blob":
255
+ return "blob"
256
+ case "unit":
257
+ return "record {}"
258
+ case "record":
259
+ return "record"
260
+ case "tuple":
261
+ return `tuple (${elementsOf(node).length})`
262
+ case "variant":
263
+ return "variant"
264
+ case "func":
265
+ return node.mode === "update" ? "func" : `func ${node.mode}`
266
+ case "service":
267
+ return "service"
268
+ }
269
+ }
270
+
271
+ // ---------------------------------------------------------------------------
272
+ // Default values: the first finite value of each type, inhabitation-aware.
273
+ // opt → null and vec → [] break every legal recursion; a variant takes its
274
+ // first arm (in key order) with a finite value; a cycle on the active path,
275
+ // or `empty`, has none. Principals have no sensible default: "" (fails, so
276
+ // the field says "required") unless options.principal is given.
277
+ // ---------------------------------------------------------------------------
278
+
279
+ export const UNINHABITED: unique symbol = Symbol("uninhabited")
280
+
281
+ export interface DefaultOptions {
282
+ /** Fills principal fields (e.g. the caller); otherwise they start empty. */
283
+ readonly principal?: string
284
+ }
285
+
286
+ export function defaultValue(
287
+ schema: AnyFieldSchema,
288
+ options: DefaultOptions = {}
289
+ ): unknown {
290
+ return defaultAt(schema, options, new Set())
291
+ }
292
+
293
+ const inhabitation = new WeakMap<ResolvedNode, boolean>()
294
+
295
+ /** Whether no finite value of the type exists (`empty`, `record { x : Loop }`). */
296
+ export function isUninhabited(schema: AnyFieldSchema): boolean {
297
+ const node = resolve(schema)
298
+ let empty = inhabitation.get(node)
299
+ if (empty === undefined) {
300
+ // A fresh active set: the answer is then independent of where it is asked.
301
+ empty = defaultAt(schema, {}, new Set()) === UNINHABITED
302
+ inhabitation.set(node, empty)
303
+ }
304
+ return empty
305
+ }
306
+
307
+ function defaultAt(
308
+ schema: AnyFieldSchema,
309
+ options: DefaultOptions,
310
+ active: Set<object>
311
+ ): unknown {
312
+ const node = resolve(schema)
313
+ if (active.has(node)) return UNINHABITED
314
+ active.add(node)
315
+ try {
316
+ switch (node.kind) {
317
+ case "primitive":
318
+ switch (node.primitive) {
319
+ case "null":
320
+ case "reserved":
321
+ return null
322
+ case "bool":
323
+ return false
324
+ case "text":
325
+ return ""
326
+ case "principal":
327
+ return options.principal ?? ""
328
+ case "empty":
329
+ return UNINHABITED
330
+ case "nat":
331
+ case "int":
332
+ case "nat64":
333
+ case "int64":
334
+ return 0n
335
+ default:
336
+ return 0 // nat8…int32, float32, float64
337
+ }
338
+ case "opt":
339
+ return null
340
+ case "vec":
341
+ return []
342
+ case "blob":
343
+ return new Uint8Array(0)
344
+ case "unit":
345
+ return {}
346
+ case "record": {
347
+ const out: Record<string, unknown> = {}
348
+ for (const [key, field] of fieldsOf(node)) {
349
+ const value = defaultAt(field, options, active)
350
+ if (value === UNINHABITED) return UNINHABITED
351
+ setOwn(out, key, value)
352
+ }
353
+ return out
354
+ }
355
+ case "tuple": {
356
+ const out: unknown[] = []
357
+ for (const element of elementsOf(node)) {
358
+ const value = defaultAt(element, options, active)
359
+ if (value === UNINHABITED) return UNINHABITED
360
+ out.push(value)
361
+ }
362
+ return out
363
+ }
364
+ case "variant":
365
+ for (const [tag, arm] of armsOf(node)) {
366
+ if (isTagOnly(arm)) return { tag }
367
+ const value = defaultAt(arm, options, active)
368
+ if (value !== UNINHABITED) return { tag, value }
369
+ }
370
+ return UNINHABITED
371
+ case "func":
372
+ return { principal: options.principal ?? "", method: "" }
373
+ case "service":
374
+ return options.principal ?? ""
375
+ }
376
+ } finally {
377
+ active.delete(node)
378
+ }
379
+ }
380
+
381
+ // ---------------------------------------------------------------------------
382
+ // Draft: the editable state. Leaves hold raw text (so "-", "1_000", "0x" and
383
+ // half-typed principals never break the tree); an opt keeps its inner draft
384
+ // while toggled off; a variant keeps one payload draft per arm visited; vec
385
+ // items carry stable ids for React keys.
386
+ // ---------------------------------------------------------------------------
387
+
388
+ export type BytesFormat = "hex" | "utf8" | "base64"
389
+
390
+ /**
391
+ * The editable state of one value: JSON-serializable, mirrors the schema.
392
+ * Leaves hold raw text; an opt keeps its inner draft while toggled off; a
393
+ * variant keeps one payload draft per arm visited; vec items carry stable ids
394
+ * (React keys). A blob's `format` is absent until someone picks one: the
395
+ * editor then shows its own default (text for a memo, hex otherwise), and a
396
+ * format the user picked holds even while the text is empty.
397
+ */
398
+ export type Draft =
399
+ | { readonly k: "leaf"; readonly text: string }
400
+ | { readonly k: "bool"; readonly value: boolean }
401
+ | { readonly k: "fixed" }
402
+ | {
403
+ readonly k: "bytes"
404
+ readonly text: string
405
+ readonly format?: BytesFormat
406
+ }
407
+ | { readonly k: "opt"; readonly present: boolean; readonly inner?: Draft }
408
+ | {
409
+ readonly k: "vec"
410
+ readonly items: readonly { readonly id: number; readonly draft: Draft }[]
411
+ }
412
+ | { readonly k: "record"; readonly fields: Readonly<Record<string, Draft>> }
413
+ | { readonly k: "tuple"; readonly items: readonly Draft[] }
414
+ | {
415
+ readonly k: "variant"
416
+ readonly tag: string
417
+ readonly payloads: Readonly<Record<string, Draft>>
418
+ }
419
+ | { readonly k: "func"; readonly principal: string; readonly method: string }
420
+ | { readonly k: "uninhabited" }
421
+
422
+ // Vec item ids are React keys only, never rendered into the DOM, so a
423
+ // counter that differs between the server and the browser is harmless.
424
+ let nextItemId = 1
425
+ export const newItemId = (): number => nextItemId++
426
+
427
+ /** A fresh draft for a schema: its default value, as a draft. */
428
+ export function initialDraft(
429
+ schema: AnyFieldSchema,
430
+ opts: DefaultOptions = {}
431
+ ): Draft {
432
+ return fromValue(schema, defaultValue(schema, opts), opts, "$", undefined)
433
+ }
434
+
435
+ const BIG_PRIMITIVES = new Set(["nat", "int", "nat64", "int64"])
436
+
437
+ /** A value `draftFromValue` did not use as given, and what it used instead. */
438
+ export interface DraftNote {
439
+ readonly path: string
440
+ readonly message: string
441
+ }
442
+
443
+ export interface FromValueOptions extends DefaultOptions {
444
+ /**
445
+ * Collects a note wherever the value is not used as given (a misspelled
446
+ * tag, a key the record does not have, a list that is not an array), so a
447
+ * JSON import can say what it replaced rather than stage another call.
448
+ */
449
+ readonly notes?: DraftNote[]
450
+ /** The value's path, for the notes (`$args[0]`); `$` by default. */
451
+ readonly path?: string
452
+ }
453
+
454
+ type Note = ((path: string, message: string) => void) | undefined
455
+
456
+ /**
457
+ * A draft from any value, tolerantly: a domain value (prefill, history,
458
+ * resendOf) or loose JSON: digit strings for bigints, hex strings or
459
+ * `number[]` for blobs, `{ Tag: payload }` variants, agent-js `[]`/`[v]`
460
+ * opts (boxed ones too), `[principal, method]` func references, objects with
461
+ * `toText()` or `__principal__` for principals. Anything unusable at a node
462
+ * falls back to that node's default, with a note when `notes` is given. A
463
+ * type with no values never gets a draft that holds one: an opt of it stays
464
+ * off, a vec of it empty, and a variant leaves such an arm for its default.
465
+ */
466
+ export function draftFromValue(
467
+ schema: AnyFieldSchema,
468
+ value: unknown,
469
+ opts: FromValueOptions = {}
470
+ ): Draft {
471
+ const { notes, path = "$", ...defaults } = opts
472
+ const note: Note =
473
+ notes === undefined
474
+ ? undefined
475
+ : (at, message) => notes.push({ path: at, message })
476
+ return fromValue(schema, value, defaults, path, note)
477
+ }
478
+
479
+ function fromValue(
480
+ schema: AnyFieldSchema,
481
+ value: unknown,
482
+ opts: DefaultOptions,
483
+ path: string,
484
+ note: Note
485
+ ): Draft {
486
+ if (value === UNINHABITED || isUninhabited(schema))
487
+ return { k: "uninhabited" }
488
+ const node = resolve(schema)
489
+ const fallback = (message: string): Draft => {
490
+ note?.(path, message)
491
+ return initialDraft(schema, opts)
492
+ }
493
+ switch (node.kind) {
494
+ case "primitive":
495
+ switch (node.primitive) {
496
+ case "null":
497
+ case "reserved":
498
+ return { k: "fixed" }
499
+ case "bool":
500
+ if (
501
+ typeof value !== "boolean" &&
502
+ value !== "true" &&
503
+ value !== "false"
504
+ )
505
+ note?.(
506
+ path,
507
+ `${missingOr(value, "expected true or false")}; set to false`
508
+ )
509
+ return { k: "bool", value: value === true || value === "true" }
510
+ case "principal":
511
+ return { k: "leaf", text: principalFrom(value, path, note) }
512
+ default:
513
+ return {
514
+ k: "leaf",
515
+ text: leafFrom(node.primitive, value, path, note),
516
+ }
517
+ }
518
+ case "blob":
519
+ if (isBytes(value)) return bytesDraft(toHex(value))
520
+ if (Array.isArray(value) && value.every(isByte))
521
+ return bytesDraft(toHex(Uint8Array.from(value)))
522
+ if (typeof value === "string") return bytesDraft(value)
523
+ note?.(
524
+ path,
525
+ `${missingOr(value, "expected hex text or a byte array")}; left empty`
526
+ )
527
+ return bytesDraft("")
528
+ case "unit":
529
+ return { k: "fixed" }
530
+ case "opt": {
531
+ if (value === null || value === undefined)
532
+ return { k: "opt", present: false }
533
+ const boxed = isBoxedOpt(node)
534
+ let some: unknown = value
535
+ if (boxed && typeof value === "object" && Object.hasOwn(value, "some")) {
536
+ some = (value as { some: unknown }).some
537
+ } else if (Array.isArray(value) && (boxed || !holdsArray(node.inner))) {
538
+ // agent-js writes an opt as [] or [value]: an unboxed one only when
539
+ // its inner type cannot itself be an array, a boxed one (whose own
540
+ // value is { some } or null, never an array) always.
541
+ if (value.length === 0) return { k: "opt", present: false }
542
+ if (value.length > 1)
543
+ note?.(
544
+ path,
545
+ `expected [] or [value]; the first of ${value.length} values is used`
546
+ )
547
+ some = value[0]
548
+ }
549
+ if (isUninhabited(node.inner)) {
550
+ note?.(path, "this type has no values; left out (null)")
551
+ return { k: "opt", present: false }
552
+ }
553
+ return {
554
+ k: "opt",
555
+ present: true,
556
+ inner: fromValue(
557
+ node.inner,
558
+ some,
559
+ opts,
560
+ boxed ? childPath(path, "some") : path,
561
+ note
562
+ ),
563
+ }
564
+ }
565
+ case "vec": {
566
+ if (!Array.isArray(value)) {
567
+ note?.(
568
+ path,
569
+ `${missingOr(value, "expected a list (an array)")}; left empty`
570
+ )
571
+ return { k: "vec", items: [] }
572
+ }
573
+ if (value.length > 0 && isUninhabited(node.inner)) {
574
+ note?.(
575
+ path,
576
+ `the item type has no values; ${value.length} ${value.length === 1 ? "item" : "items"} left out`
577
+ )
578
+ return { k: "vec", items: [] }
579
+ }
580
+ return {
581
+ k: "vec",
582
+ items: value.map((v, i) => ({
583
+ id: newItemId(),
584
+ draft: fromValue(node.inner, v, opts, childPath(path, i), note),
585
+ })),
586
+ }
587
+ }
588
+ case "record": {
589
+ if (typeof value !== "object" || value === null || Array.isArray(value))
590
+ return fallback(
591
+ `${missingOr(value, "expected a record (an object)")}; the default is used`
592
+ )
593
+ const src = value as Record<string, unknown>
594
+ const fields: Record<string, Draft> = {}
595
+ const known = new Set<string>()
596
+ for (const [key, field] of fieldsOf(node)) {
597
+ known.add(key)
598
+ const at = childPath(path, key)
599
+ if (Object.hasOwn(src, key)) {
600
+ setOwn(fields, key, fromValue(field, src[key], opts, at, note))
601
+ } else {
602
+ // A missing opt field is null, as in Candid; anything else is not.
603
+ if (!isOptional(field)) note?.(at, "missing; set to the default")
604
+ setOwn(fields, key, initialDraft(field, opts))
605
+ }
606
+ }
607
+ if (note !== undefined)
608
+ for (const key of Object.keys(src))
609
+ if (!known.has(key))
610
+ note(childPath(path, key), "not a field of this record; ignored")
611
+ return { k: "record", fields }
612
+ }
613
+ case "tuple": {
614
+ if (!Array.isArray(value))
615
+ return fallback(
616
+ `${missingOr(value, "expected a tuple (an array)")}; the default is used`
617
+ )
618
+ const elements = elementsOf(node)
619
+ if (value.length > elements.length)
620
+ note?.(
621
+ path,
622
+ `${value.length - elements.length} extra ${value.length - elements.length === 1 ? "value" : "values"} ignored`
623
+ )
624
+ return {
625
+ k: "tuple",
626
+ items: elements.map((el, i) => {
627
+ const at = childPath(path, i)
628
+ if (i < value.length) return fromValue(el, value[i], opts, at, note)
629
+ if (!isOptional(el)) note?.(at, "missing; set to the default")
630
+ return initialDraft(el, opts)
631
+ }),
632
+ }
633
+ }
634
+ case "variant": {
635
+ const picked = variantOf(node, value)
636
+ if (picked === undefined)
637
+ return fallback(`${variantMiss(value)}; the default arm is used`)
638
+ const [tag, payload, armSchema] = picked
639
+ if (isUninhabited(armSchema))
640
+ return fallback(
641
+ `the arm ${JSON.stringify(tag)} has no values; the default arm is used`
642
+ )
643
+ if (isTagOnly(armSchema)) return { k: "variant", tag, payloads: {} }
644
+ const at = childPath(path, "value")
645
+ if (payload === undefined) note?.(at, "missing; set to the default")
646
+ const payloads: Record<string, Draft> = {}
647
+ setOwn(
648
+ payloads,
649
+ tag,
650
+ payload === undefined
651
+ ? initialDraft(armSchema, opts)
652
+ : fromValue(armSchema, payload, opts, at, note)
653
+ )
654
+ return { k: "variant", tag, payloads }
655
+ }
656
+ case "func": {
657
+ // { principal, method }, or agent-js's [principal, method].
658
+ const parts = Array.isArray(value)
659
+ ? { principal: value[0], method: value[1] }
660
+ : typeof value === "object" && value !== null
661
+ ? (value as { principal?: unknown; method?: unknown })
662
+ : undefined
663
+ if (parts === undefined)
664
+ note?.(
665
+ path,
666
+ `${missingOr(value, "expected { principal, method }")}; left empty`
667
+ )
668
+ else if (typeof parts.method !== "string")
669
+ note?.(
670
+ childPath(path, "method"),
671
+ `${missingOr(parts.method, "expected text")}; left empty`
672
+ )
673
+ return {
674
+ k: "func",
675
+ principal:
676
+ parts === undefined
677
+ ? ""
678
+ : principalFrom(
679
+ parts.principal,
680
+ childPath(path, "principal"),
681
+ note
682
+ ),
683
+ method: typeof parts?.method === "string" ? parts.method : "",
684
+ }
685
+ }
686
+ case "service":
687
+ return { k: "leaf", text: principalFrom(value, path, note) }
688
+ }
689
+ }
690
+
691
+ /** An empty blob has no format yet: the editor shows its default. */
692
+ const bytesDraft = (text: string): Draft =>
693
+ text === "" ? { k: "bytes", text } : { k: "bytes", text, format: "hex" }
694
+
695
+ const missingOr = (value: unknown, expected: string): string =>
696
+ value === null || value === undefined ? "missing" : expected
697
+
698
+ /** The `[tag, payload, armSchema]` of a `{ tag, value }` or `{ Tag: payload }` value. */
699
+ function variantOf(
700
+ node: VariantNode,
701
+ value: unknown
702
+ ): [string, unknown, AnyFieldSchema] | undefined {
703
+ if (typeof value !== "object" || value === null) return undefined
704
+ const v = value as Record<string, unknown>
705
+ if (typeof v.tag === "string") {
706
+ const arm = armOf(node, v.tag)
707
+ if (arm !== undefined) return [v.tag, v.value, arm]
708
+ }
709
+ const keys = Object.keys(v)
710
+ const only = keys.length === 1 ? keys[0] : undefined
711
+ if (only !== undefined) {
712
+ const arm = armOf(node, only)
713
+ if (arm !== undefined) return [only, v[only], arm]
714
+ }
715
+ return undefined
716
+ }
717
+
718
+ /** Why a value picked no arm, for the note. */
719
+ function variantMiss(value: unknown): string {
720
+ if (typeof value !== "object" || value === null || Array.isArray(value))
721
+ return missingOr(value, `expected a variant ({ "Tag": value })`)
722
+ const v = value as Record<string, unknown>
723
+ if (typeof v.tag === "string")
724
+ return `unknown variant tag ${JSON.stringify(v.tag)}`
725
+ const keys = Object.keys(v)
726
+ return keys.length === 1
727
+ ? `unknown variant tag ${JSON.stringify(keys[0])}`
728
+ : `expected one tag, got ${keys.length} keys`
729
+ }
730
+
731
+ const isByte = (b: unknown): b is number =>
732
+ typeof b === "number" && Number.isInteger(b) && b >= 0 && b < 256
733
+
734
+ function holdsArray(schema: AnyFieldSchema): boolean {
735
+ const kind = resolve(schema).kind
736
+ return kind === "vec" || kind === "tuple" || kind === "blob" || kind === "opt"
737
+ }
738
+
739
+ function leafFrom(
740
+ primitive: string,
741
+ value: unknown,
742
+ path: string,
743
+ note: Note
744
+ ): string {
745
+ if (typeof value === "string") return value
746
+ if (typeof value === "bigint") return value.toString()
747
+ if (typeof value === "number") {
748
+ // A JSON number past 2^53 already lost digits: leave the field empty
749
+ // rather than show a different amount.
750
+ if (
751
+ BIG_PRIMITIVES.has(primitive) &&
752
+ Number.isInteger(value) &&
753
+ !Number.isSafeInteger(value)
754
+ ) {
755
+ note?.(
756
+ path,
757
+ "a number past 2^53 has lost digits (write it as a string); left empty"
758
+ )
759
+ return ""
760
+ }
761
+ // String(-0) is "0": a float64 -0.0 is other bytes than 0.0.
762
+ return Object.is(value, -0) ? "-0" : String(value)
763
+ }
764
+ note?.(
765
+ path,
766
+ `${missingOr(value, primitive === "text" ? "expected text" : "expected a number")}; left empty`
767
+ )
768
+ return ""
769
+ }
770
+
771
+ function principalFrom(value: unknown, path: string, note: Note): string {
772
+ if (typeof value === "string") return value
773
+ if (typeof value === "object" && value !== null) {
774
+ if (typeof (value as { toText?: unknown }).toText === "function")
775
+ return String((value as { toText(): unknown }).toText())
776
+ // agent-js writes a Principal to JSON as { "__principal__": text }.
777
+ const text = getOwn(value as Record<string, unknown>, "__principal__")
778
+ if (typeof text === "string") return text
779
+ }
780
+ note?.(path, `${missingOr(value, "expected principal text")}; left empty`)
781
+ return ""
782
+ }
783
+
784
+ /** Switching a variant: keeps the draft of every arm already visited. */
785
+ export function selectArm(
786
+ schema: AnyFieldSchema,
787
+ draft: Draft,
788
+ tag: string,
789
+ opts: DefaultOptions = {}
790
+ ): Draft {
791
+ const node = resolve(schema)
792
+ if (node.kind !== "variant") return draft
793
+ const arm = armOf(node, tag)
794
+ if (arm === undefined) return draft
795
+ const payloads = draft.k === "variant" ? draft.payloads : {}
796
+ if (isTagOnly(arm) || getOwn(payloads, tag) !== undefined)
797
+ return { k: "variant", tag, payloads }
798
+ return {
799
+ k: "variant",
800
+ tag,
801
+ payloads: withOwn(payloads, tag, initialDraft(arm, opts)),
802
+ }
803
+ }
804
+
805
+ // ---------------------------------------------------------------------------
806
+ // Draft → value. A parse failure becomes an issue at the leaf's path (code
807
+ // "parse"); the raw text stays in the value as a placeholder so validate()
808
+ // still sees the slot, and the parse message wins for that path.
809
+ // ---------------------------------------------------------------------------
810
+
811
+ /**
812
+ * An issue at a field. `path` uses the codec's grammar under `$args[i]`
813
+ * (`$args[0].to.owner`), the same paths ic-reactor's `invalid_args` issues
814
+ * carry, so both land on the same field.
815
+ */
816
+ export interface FieldIssue {
817
+ path: string
818
+ code: string
819
+ message: string
820
+ }
821
+
822
+ export function draftToValue(
823
+ schema: AnyFieldSchema,
824
+ draft: Draft,
825
+ path: string,
826
+ issues: FieldIssue[]
827
+ ): unknown {
828
+ // Before anything else: an opt, vec item or arm of a type with no values
829
+ // would otherwise stand in for its missing draft with initialDraft(), which
830
+ // is { k: "uninhabited" } again, and recurse forever.
831
+ if (draft.k === "uninhabited" || isUninhabited(schema)) {
832
+ issues.push({
833
+ path,
834
+ code: "uninhabited_type",
835
+ message: "this type has no values",
836
+ })
837
+ return null
838
+ }
839
+ const node = resolve(schema)
840
+ const parse = (message: string): void => {
841
+ issues.push({ path, code: "parse", message })
842
+ }
843
+ switch (node.kind) {
844
+ case "primitive": {
845
+ const p = node.primitive
846
+ if (p === "null" || p === "reserved") return null
847
+ if (p === "bool") return draft.k === "bool" ? draft.value : false
848
+ const text = draft.k === "leaf" ? draft.text : ""
849
+ if (p === "text") return text
850
+ if (p === "principal") return principalOrIssue(text, parse)
851
+ if (BIG_PRIMITIVES.has(p)) {
852
+ const parsed = parseBigInt(text)
853
+ if (typeof parsed === "string") {
854
+ parse(parsed)
855
+ return text
856
+ }
857
+ return parsed
858
+ }
859
+ if (FIXED[p] !== undefined) {
860
+ const t = integerText(text)
861
+ if (!t.ok || t.text.startsWith("0x")) {
862
+ parse(t.ok ? "enter a whole number" : t.message)
863
+ return text
864
+ }
865
+ return Number(t.text) // the range is validate's out_of_range, with exact bounds
866
+ }
867
+ return parseFloatLeaf(text, p === "float32", parse)
868
+ }
869
+ case "blob": {
870
+ if (draft.k !== "bytes") return new Uint8Array(0)
871
+ const bytes = parseBytes(draft.text, draft.format ?? "hex")
872
+ if (typeof bytes === "string") {
873
+ parse(bytes)
874
+ return draft.text
875
+ }
876
+ return bytes
877
+ }
878
+ case "unit":
879
+ return {}
880
+ case "opt": {
881
+ if (draft.k !== "opt" || !draft.present) return null
882
+ const boxed = isBoxedOpt(node)
883
+ const innerDraft = draft.inner ?? initialDraft(node.inner)
884
+ const inner = draftToValue(
885
+ node.inner,
886
+ innerDraft,
887
+ boxed ? childPath(path, "some") : path,
888
+ issues
889
+ )
890
+ return boxed ? { some: inner } : inner
891
+ }
892
+ case "vec":
893
+ return draft.k === "vec"
894
+ ? draft.items.map((item, i) =>
895
+ draftToValue(node.inner, item.draft, childPath(path, i), issues)
896
+ )
897
+ : []
898
+ case "record": {
899
+ const out: Record<string, unknown> = {}
900
+ for (const [key, field] of fieldsOf(node)) {
901
+ const sub = draft.k === "record" ? getOwn(draft.fields, key) : undefined
902
+ setOwn(
903
+ out,
904
+ key,
905
+ draftToValue(
906
+ field,
907
+ sub ?? initialDraft(field),
908
+ childPath(path, key),
909
+ issues
910
+ )
911
+ )
912
+ }
913
+ return out
914
+ }
915
+ case "tuple":
916
+ return elementsOf(node).map((el, i) => {
917
+ const sub = draft.k === "tuple" ? draft.items[i] : undefined
918
+ return draftToValue(
919
+ el,
920
+ sub ?? initialDraft(el),
921
+ childPath(path, i),
922
+ issues
923
+ )
924
+ })
925
+ case "variant": {
926
+ if (draft.k !== "variant") return null
927
+ const armSchema = armOf(node, draft.tag)
928
+ if (armSchema === undefined) {
929
+ issues.push({
930
+ path: childPath(path, "tag"),
931
+ code: "parse",
932
+ message: `unknown variant tag ${JSON.stringify(draft.tag)}`,
933
+ })
934
+ return { tag: draft.tag }
935
+ }
936
+ if (isTagOnly(armSchema)) return { tag: draft.tag }
937
+ const payload =
938
+ getOwn(draft.payloads, draft.tag) ?? initialDraft(armSchema)
939
+ return {
940
+ tag: draft.tag,
941
+ value: draftToValue(
942
+ armSchema,
943
+ payload,
944
+ childPath(path, "value"),
945
+ issues
946
+ ),
947
+ }
948
+ }
949
+ case "func": {
950
+ const f = draft.k === "func" ? draft : { principal: "", method: "" }
951
+ const principal = principalOrIssue(f.principal, (message) =>
952
+ issues.push({
953
+ path: childPath(path, "principal"),
954
+ code: "parse",
955
+ message,
956
+ })
957
+ )
958
+ const method = f.method.trim()
959
+ if (method === "")
960
+ issues.push({
961
+ path: childPath(path, "method"),
962
+ code: "parse",
963
+ message: "required",
964
+ })
965
+ return { principal, method }
966
+ }
967
+ case "service":
968
+ return principalOrIssue(draft.k === "leaf" ? draft.text : "", parse)
969
+ }
970
+ }
971
+
972
+ function principalOrIssue(
973
+ text: string,
974
+ report: (message: string) => void
975
+ ): string {
976
+ const t = text.trim()
977
+ if (t === "") report("required")
978
+ else if (!isPrincipal(t)) {
979
+ if (isPrincipal(t.toLowerCase())) report("principal text is lower case")
980
+ else report("not a valid principal (wrong grouping or checksum)")
981
+ }
982
+ return t
983
+ }
984
+
985
+ // Decimal notation only: Number() also reads "0x1A", "0b11" and "", which a
986
+ // float field should not take for a decimal.
987
+ const DECIMAL = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i
988
+
989
+ function parseFloatLeaf(
990
+ text: string,
991
+ float32: boolean,
992
+ parse: (message: string) => void
993
+ ): number | string {
994
+ const t = text.trim()
995
+ if (t === "NaN") return NaN
996
+ if (t === "Infinity" || t === "+Infinity") return Infinity
997
+ if (t === "-Infinity") return -Infinity
998
+ if (!DECIMAL.test(t)) {
999
+ parse(t === "" ? "required" : "enter a number")
1000
+ return text
1001
+ }
1002
+ const x = Number(t)
1003
+ if (!Number.isFinite(x)) {
1004
+ // "1e400" overflows to Infinity: say so, never send Infinity for it.
1005
+ parse("too large for a float64 (type Infinity for infinity)")
1006
+ return text
1007
+ }
1008
+ if (float32 && Math.fround(x) !== x) {
1009
+ // encode would refuse it too (unrepresentable_float32): say why, here.
1010
+ parse(`not exactly representable as float32 (nearest is ${Math.fround(x)})`)
1011
+ return x
1012
+ }
1013
+ return x
1014
+ }
1015
+
1016
+ type IntegerText =
1017
+ | { readonly ok: true; readonly text: string }
1018
+ | { readonly ok: false; readonly message: string }
1019
+
1020
+ const GROUP_SPACE = /[ \u00a0\u202f]/g
1021
+
1022
+ /**
1023
+ * Typed integer text as BigInt() reads it, or why not. `_` may sit between
1024
+ * digits (Candid's own `1_000_000`); `,` and spaces only between groups of
1025
+ * three, so a decimal comma ("1,5") is refused rather than read as 15.
1026
+ */
1027
+ function integerText(text: string): IntegerText {
1028
+ const t = text.trim()
1029
+ if (t === "") return { ok: false, message: "required" }
1030
+ if (/^[+-]?\d+(?:_\d+)*$/.test(t))
1031
+ return { ok: true, text: t.replaceAll("_", "") }
1032
+ if (/^[+-]?\d{1,3}(?:,\d{3})+$/.test(t))
1033
+ return { ok: true, text: t.replaceAll(",", "") }
1034
+ if (/^[+-]?\d{1,3}(?:[ \u00a0\u202f]\d{3})+$/.test(t))
1035
+ return { ok: true, text: t.replace(GROUP_SPACE, "") }
1036
+ if (/^0x[0-9a-f]+(?:_[0-9a-f]+)*$/i.test(t))
1037
+ return { ok: true, text: t.replaceAll("_", "") }
1038
+ if (/^[+-]?[\d,_\s\u00a0\u202f]+$/.test(t))
1039
+ return {
1040
+ ok: false,
1041
+ message:
1042
+ 'enter a whole number ("," and spaces only separate groups of 3 digits)',
1043
+ }
1044
+ return { ok: false, message: "enter a whole number" }
1045
+ }
1046
+
1047
+ /**
1048
+ * A bigint from typed text, or why not: decimal digits (with `_` between
1049
+ * them, or `,`/spaces between groups of three) or `0x` hex.
1050
+ */
1051
+ export function parseBigInt(text: string): bigint | string {
1052
+ const t = integerText(text)
1053
+ return t.ok ? BigInt(t.text) : t.message
1054
+ }
1055
+
1056
+ /** Bytes from text in a format, or why not. Hex allows `0x` and separators. */
1057
+ export function parseBytes(
1058
+ text: string,
1059
+ format: BytesFormat
1060
+ ): Uint8Array | string {
1061
+ // A copy, so the bytes are this realm's Uint8Array wherever the encoder
1062
+ // comes from (a test's jsdom window has its own).
1063
+ if (format === "utf8") return Uint8Array.from(new TextEncoder().encode(text))
1064
+ if (format === "base64") {
1065
+ try {
1066
+ const bin = atob(text.trim())
1067
+ return Uint8Array.from(bin, (ch) => ch.charCodeAt(0))
1068
+ } catch {
1069
+ return "not valid base64"
1070
+ }
1071
+ }
1072
+ const t = text
1073
+ .trim()
1074
+ .replace(/^0x/i, "")
1075
+ .replace(/[\s:_-]/g, "")
1076
+ if (!/^[0-9a-f]*$/i.test(t)) return "not valid hex"
1077
+ if (t.length % 2 !== 0) return "hex needs an even number of digits"
1078
+ const out = new Uint8Array(t.length / 2)
1079
+ for (let i = 0; i < out.length; i++)
1080
+ out[i] = Number.parseInt(t.slice(i * 2, i * 2 + 2), 16)
1081
+ return out
1082
+ }
1083
+
1084
+ /**
1085
+ * Bytes as text in a format, or `undefined` when the format cannot hold
1086
+ * them (utf8 for bytes that are not valid UTF-8).
1087
+ */
1088
+ export function formatBytes(
1089
+ bytes: Uint8Array,
1090
+ format: BytesFormat
1091
+ ): string | undefined {
1092
+ if (format === "hex") return toHex(bytes)
1093
+ if (format === "base64") {
1094
+ let bin = ""
1095
+ for (const b of bytes) bin += String.fromCharCode(b)
1096
+ return btoa(bin)
1097
+ }
1098
+ let text: string
1099
+ try {
1100
+ // ignoreBOM: a leading EF BB BF is three of the bytes, not a marker to
1101
+ // drop, or switching to text would send three bytes fewer.
1102
+ text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(
1103
+ bytes
1104
+ )
1105
+ } catch {
1106
+ return undefined
1107
+ }
1108
+ // Only a text that encodes back to the very same bytes may stand for them.
1109
+ const back = new TextEncoder().encode(text)
1110
+ return back.length === bytes.length && back.every((b, i) => b === bytes[i])
1111
+ ? text
1112
+ : undefined
1113
+ }
1114
+
1115
+ // ---------------------------------------------------------------------------
1116
+ // One check for a whole call: parse → validate (per argument) → encodeArgs.
1117
+ // ---------------------------------------------------------------------------
1118
+
1119
+ /** The result of checking a whole call: parse → validate → encodeArgs. */
1120
+ export interface CallCheck {
1121
+ ok: boolean
1122
+ /** One domain value per argument. */
1123
+ values?: unknown[]
1124
+ /** What ic-reactor's builders take: nothing, the one value, or the tuple. */
1125
+ vars?: unknown
1126
+ /** The exact Candid message (DIDL…) when everything passed. */
1127
+ bytes?: Uint8Array
1128
+ issues: FieldIssue[]
1129
+ /** Some argument has no finite value: the method cannot be called. */
1130
+ uninhabited?: boolean
1131
+ }
1132
+
1133
+ /** The values the drafts stand for, parse failures left as their raw text. */
1134
+ export function draftValues(
1135
+ args: readonly AnyFieldSchema[],
1136
+ drafts: readonly (Draft | undefined)[]
1137
+ ): unknown[] {
1138
+ return args.map((schema, i) =>
1139
+ draftToValue(schema, drafts[i] ?? initialDraft(schema), argPath(i), [])
1140
+ )
1141
+ }
1142
+
1143
+ /** Checks a whole call; issues use `$args[i]…` paths. */
1144
+ export function checkCall(
1145
+ args: readonly AnyFieldSchema[],
1146
+ drafts: readonly Draft[]
1147
+ ): CallCheck {
1148
+ const empty = args.findIndex(
1149
+ (schema, i) => drafts[i]?.k === "uninhabited" || isUninhabited(schema)
1150
+ )
1151
+ if (empty !== -1) {
1152
+ return {
1153
+ ok: false,
1154
+ uninhabited: true,
1155
+ issues: [
1156
+ {
1157
+ path: argPath(empty),
1158
+ code: "uninhabited_type",
1159
+ message:
1160
+ "this argument's type has no values (empty, or a type that only contains itself): the method cannot be called",
1161
+ },
1162
+ ],
1163
+ }
1164
+ }
1165
+ const parseIssues: FieldIssue[] = []
1166
+ const values = args.map((schema, i) =>
1167
+ draftToValue(
1168
+ schema,
1169
+ drafts[i] ?? initialDraft(schema),
1170
+ argPath(i),
1171
+ parseIssues
1172
+ )
1173
+ )
1174
+ const parsed = new Set(parseIssues.map((issue) => issue.path))
1175
+ const issues: FieldIssue[] = [...parseIssues]
1176
+ args.forEach((schema, i) => {
1177
+ // AnyFieldSchema includes Schema<never>, which validate()'s Schema<T>
1178
+ // parameter refuses at the type level; the node is the same.
1179
+ const result = validate(schema as AnySchema, values[i], { maxIssues: 50 })
1180
+ if (result.ok) return
1181
+ for (const issue of result.issues) {
1182
+ const path = argPath(i, issue.path)
1183
+ if (!parsed.has(path))
1184
+ issues.push({ path, code: issue.code, message: issue.message })
1185
+ }
1186
+ })
1187
+ const vars = toVars(values)
1188
+ if (issues.length > 0) return { ok: false, values, vars, issues }
1189
+ // encode re-validates (stopping at the first issue) and adds what only it
1190
+ // finds: lone surrogates in text, float32 rounding.
1191
+ const encoded = encodeArgs(args, values)
1192
+ if (!encoded.ok)
1193
+ return {
1194
+ ok: false,
1195
+ values,
1196
+ vars,
1197
+ issues: encoded.issues.map(({ path, code, message }) => ({
1198
+ path,
1199
+ code,
1200
+ message,
1201
+ })),
1202
+ }
1203
+ return { ok: true, values, vars, issues: [], bytes: encoded.bytes }
1204
+ }
1205
+
1206
+ /** Issues grouped by path, for O(1) lookup from each field component. */
1207
+ export function issuesByPath(
1208
+ issues: readonly FieldIssue[]
1209
+ ): Map<string, FieldIssue[]> {
1210
+ const map = new Map<string, FieldIssue[]>()
1211
+ for (const issue of issues) {
1212
+ const list = map.get(issue.path)
1213
+ if (list) list.push(issue)
1214
+ else map.set(issue.path, [issue])
1215
+ }
1216
+ return map
1217
+ }
1218
+
1219
+ /** Whether `path` or anything below it has an issue (for collapsed sections). */
1220
+ export function isAtOrBelow(issuePath: string, path: string): boolean {
1221
+ return (
1222
+ issuePath === path ||
1223
+ issuePath.startsWith(path + ".") ||
1224
+ issuePath.startsWith(path + "[")
1225
+ )
1226
+ }
1227
+
1228
+ /**
1229
+ * Every path the form renders for a value: what a field component registers.
1230
+ * The tests use it to prove each issue lands on a rendered field.
1231
+ */
1232
+ export function renderedPaths(
1233
+ schema: AnyFieldSchema,
1234
+ value: unknown,
1235
+ path: string,
1236
+ out: Set<string> = new Set()
1237
+ ): Set<string> {
1238
+ out.add(path)
1239
+ const node = resolve(schema)
1240
+ switch (node.kind) {
1241
+ case "opt":
1242
+ if (value !== null && value !== undefined) {
1243
+ const boxed = isBoxedOpt(node)
1244
+ renderedPaths(
1245
+ node.inner,
1246
+ boxed ? (value as { some: unknown }).some : value,
1247
+ boxed ? childPath(path, "some") : path,
1248
+ out
1249
+ )
1250
+ }
1251
+ break
1252
+ case "vec":
1253
+ if (Array.isArray(value))
1254
+ value.forEach((v, i) =>
1255
+ renderedPaths(node.inner, v, childPath(path, i), out)
1256
+ )
1257
+ break
1258
+ case "record":
1259
+ for (const [key, field] of fieldsOf(node)) {
1260
+ const v =
1261
+ typeof value === "object" && value !== null
1262
+ ? getOwn(value as Record<string, unknown>, key)
1263
+ : undefined
1264
+ renderedPaths(field, v, childPath(path, key), out)
1265
+ }
1266
+ break
1267
+ case "tuple":
1268
+ elementsOf(node).forEach((el, i) =>
1269
+ renderedPaths(
1270
+ el,
1271
+ Array.isArray(value) ? value[i] : undefined,
1272
+ childPath(path, i),
1273
+ out
1274
+ )
1275
+ )
1276
+ break
1277
+ case "variant": {
1278
+ out.add(childPath(path, "tag"))
1279
+ const v = value as { tag?: unknown; value?: unknown } | null
1280
+ if (v !== null && typeof v === "object" && typeof v.tag === "string") {
1281
+ const arm = armOf(node, v.tag)
1282
+ if (arm !== undefined && "value" in v)
1283
+ renderedPaths(arm, v.value, childPath(path, "value"), out)
1284
+ }
1285
+ break
1286
+ }
1287
+ case "func":
1288
+ out.add(childPath(path, "principal"))
1289
+ out.add(childPath(path, "method"))
1290
+ break
1291
+ default:
1292
+ break
1293
+ }
1294
+ return out
1295
+ }
1296
+
1297
+ // ---------------------------------------------------------------------------
1298
+ // Walking drafts (for "now" defaults): visit every node of the drafts with
1299
+ // its schema, path and record key; a visitor that returns a draft replaces
1300
+ // that node and is not called below it.
1301
+ // ---------------------------------------------------------------------------
1302
+
1303
+ export interface DraftVisit {
1304
+ readonly schema: AnyFieldSchema
1305
+ readonly draft: Draft
1306
+ readonly path: string
1307
+ /** The record key of the field, when the node is one. */
1308
+ readonly key?: string
1309
+ }
1310
+
1311
+ export function mapDrafts(
1312
+ args: readonly AnyFieldSchema[],
1313
+ drafts: readonly Draft[],
1314
+ visit: (at: DraftVisit) => Draft | undefined
1315
+ ): Draft[] {
1316
+ return args.map((schema, i) => {
1317
+ const draft = drafts[i] ?? initialDraft(schema)
1318
+ return mapDraft({ schema, draft, path: argPath(i) }, visit)
1319
+ })
1320
+ }
1321
+
1322
+ function mapDraft(
1323
+ at: DraftVisit,
1324
+ visit: (at: DraftVisit) => Draft | undefined
1325
+ ): Draft {
1326
+ const replaced = visit(at)
1327
+ if (replaced !== undefined) return replaced
1328
+ const { schema, draft, path, key } = at
1329
+ const node = resolve(schema)
1330
+ switch (node.kind) {
1331
+ case "opt": {
1332
+ if (draft.k !== "opt" || !draft.present || draft.inner === undefined)
1333
+ return draft
1334
+ const boxed = isBoxedOpt(node)
1335
+ const inner = mapDraft(
1336
+ {
1337
+ schema: node.inner,
1338
+ draft: draft.inner,
1339
+ path: boxed ? childPath(path, "some") : path,
1340
+ key: boxed ? undefined : key,
1341
+ },
1342
+ visit
1343
+ )
1344
+ return inner === draft.inner ? draft : { ...draft, inner }
1345
+ }
1346
+ case "record": {
1347
+ if (draft.k !== "record") return draft
1348
+ let changed = false
1349
+ const fields: Record<string, Draft> = {}
1350
+ for (const [k, field] of fieldsOf(node)) {
1351
+ const sub = getOwn(draft.fields, k)
1352
+ if (sub === undefined) continue
1353
+ const next = mapDraft(
1354
+ { schema: field, draft: sub, path: childPath(path, k), key: k },
1355
+ visit
1356
+ )
1357
+ if (next !== sub) changed = true
1358
+ setOwn(fields, k, next)
1359
+ }
1360
+ return changed ? { k: "record", fields } : draft
1361
+ }
1362
+ case "tuple": {
1363
+ if (draft.k !== "tuple") return draft
1364
+ const elements = elementsOf(node)
1365
+ const items = draft.items.map((sub, i) => {
1366
+ const el = elements[i]
1367
+ return el === undefined
1368
+ ? sub
1369
+ : mapDraft(
1370
+ { schema: el, draft: sub, path: childPath(path, i) },
1371
+ visit
1372
+ )
1373
+ })
1374
+ return items.every((d, i) => d === draft.items[i])
1375
+ ? draft
1376
+ : { k: "tuple", items }
1377
+ }
1378
+ case "vec": {
1379
+ if (draft.k !== "vec") return draft
1380
+ let changed = false
1381
+ const items = draft.items.map((item, i) => {
1382
+ const next = mapDraft(
1383
+ { schema: node.inner, draft: item.draft, path: childPath(path, i) },
1384
+ visit
1385
+ )
1386
+ if (next === item.draft) return item
1387
+ changed = true
1388
+ // The same id: the item keeps its React identity and its focus.
1389
+ return { id: item.id, draft: next }
1390
+ })
1391
+ return changed ? { k: "vec", items } : draft
1392
+ }
1393
+ case "variant": {
1394
+ if (draft.k !== "variant") return draft
1395
+ const arm = armOf(node, draft.tag)
1396
+ const payload = getOwn(draft.payloads, draft.tag)
1397
+ if (arm === undefined || payload === undefined) return draft
1398
+ const next = mapDraft(
1399
+ { schema: arm, draft: payload, path: childPath(path, "value") },
1400
+ visit
1401
+ )
1402
+ return next === payload
1403
+ ? draft
1404
+ : { ...draft, payloads: withOwn(draft.payloads, draft.tag, next) }
1405
+ }
1406
+ default:
1407
+ return draft
1408
+ }
1409
+ }
1410
+
1411
+ /**
1412
+ * The draft set to a time in nanoseconds: a bigint leaf takes it, an opt is
1413
+ * switched on and filled, a one-field record (the ICP ledger's
1414
+ * `TimeStamp { timestamp_nanos }`) fills its field. Other nodes stay as they are.
1415
+ */
1416
+ export function fillNanos(
1417
+ schema: AnyFieldSchema,
1418
+ draft: Draft,
1419
+ nanos: bigint
1420
+ ): Draft {
1421
+ const node = resolve(schema)
1422
+ switch (node.kind) {
1423
+ case "primitive":
1424
+ return BIG_PRIMITIVES.has(node.primitive)
1425
+ ? { k: "leaf", text: nanos.toString() }
1426
+ : draft
1427
+ case "opt": {
1428
+ const inner =
1429
+ draft.k === "opt" && draft.inner !== undefined
1430
+ ? draft.inner
1431
+ : initialDraft(node.inner)
1432
+ return {
1433
+ k: "opt",
1434
+ present: true,
1435
+ inner: fillNanos(node.inner, inner, nanos),
1436
+ }
1437
+ }
1438
+ case "record": {
1439
+ const fields = fieldsOf(node)
1440
+ const only = fields.length === 1 ? fields[0] : undefined
1441
+ if (only === undefined) return draft
1442
+ const [key, field] = only
1443
+ const current =
1444
+ draft.k === "record" ? getOwn(draft.fields, key) : undefined
1445
+ const out: Record<string, Draft> = {}
1446
+ setOwn(out, key, fillNanos(field, current ?? initialDraft(field), nanos))
1447
+ return { k: "record", fields: out }
1448
+ }
1449
+ default:
1450
+ return draft
1451
+ }
1452
+ }
1453
+
1454
+ /** Whether a draft holds no time yet (an absent opt, an empty or zero leaf). */
1455
+ export function isUnsetTime(draft: Draft): boolean {
1456
+ if (draft.k === "opt") return !draft.present
1457
+ if (draft.k === "leaf") return draft.text.trim() === "" || draft.text === "0"
1458
+ return false
1459
+ }
1460
+
1461
+ // ---------------------------------------------------------------------------
1462
+ // Errors from a call
1463
+ // ---------------------------------------------------------------------------
1464
+
1465
+ interface IssueLike {
1466
+ path: unknown
1467
+ code: unknown
1468
+ message: unknown
1469
+ }
1470
+
1471
+ const isIssue = (issue: unknown): issue is FieldIssue =>
1472
+ typeof issue === "object" &&
1473
+ issue !== null &&
1474
+ typeof (issue as IssueLike).path === "string" &&
1475
+ typeof (issue as IssueLike).code === "string" &&
1476
+ typeof (issue as IssueLike).message === "string"
1477
+
1478
+ /**
1479
+ * An `invalid_args` ReactorError's issues as field issues. ic-reactor takes
1480
+ * them straight from encodeArgs, so their paths are already `$args[i]…`, the
1481
+ * grammar the form's fields use. Any other error gives none. The check is on
1482
+ * the shape, not the brand, so a recorded error (a plain object with `kind`
1483
+ * and `issues`) is read too.
1484
+ */
1485
+ export function issuesFromReactorError(e: unknown): FieldIssue[] {
1486
+ if (typeof e !== "object" || e === null) return []
1487
+ const error = e as { kind?: unknown; issues?: unknown }
1488
+ if (error.kind !== "invalid_args" || !Array.isArray(error.issues)) return []
1489
+ return error.issues
1490
+ .filter(isIssue)
1491
+ .map(({ path, code, message }) => ({ path, code, message }))
1492
+ }