@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,924 @@
1
+ import { principal, type Principal } from "@meantjs/schema"
2
+ import { isReactorError } from "@ic-reactor/core"
3
+ import { MutationObserver, type QueryKey } from "@tanstack/react-query"
4
+ import {
5
+ actor as icrc1Actor,
6
+ type Actor as Icrc1Actor,
7
+ type TransferArg,
8
+ type TransferError,
9
+ } from "../canisters/icrc1.ts"
10
+ import { nowNanos } from "../forms/convert.ts"
11
+ import type { DynActor } from "../lib/reactor.ts"
12
+ import {
13
+ callUntyped,
14
+ clip,
15
+ describeFailure,
16
+ failureOf,
17
+ fieldsOf,
18
+ issuePaths,
19
+ logged,
20
+ present,
21
+ runInLab,
22
+ sent,
23
+ settle,
24
+ show,
25
+ valueOf,
26
+ type LoggedRequest,
27
+ type Recorder,
28
+ type Scenario,
29
+ type ScenarioReply,
30
+ } from "./lab-run.ts"
31
+ import {
32
+ createLab,
33
+ LAB_FEE,
34
+ LAB_INDEX_ID,
35
+ LAB_LEDGER_ID,
36
+ labIndexActor,
37
+ type Lab,
38
+ type LabIndexActor,
39
+ } from "./mock-ledger.ts"
40
+
41
+ export type {
42
+ LabeledError,
43
+ LoggedRequest,
44
+ Scenario,
45
+ ScenarioReply,
46
+ ScenarioResult,
47
+ ScenarioStep,
48
+ ScenarioVerdict,
49
+ } from "./lab-run.ts"
50
+
51
+ // The ten scenarios of the Safety lab. Each runs against a fresh
52
+ // createTestClient() (mock-ledger.ts) and states, as checks, what ic-reactor
53
+ // must do; lab-run.ts turns any check that does not hold into a failed
54
+ // verdict.
55
+
56
+ /** The setup every scenario starts from (shown once, above the cards). */
57
+ export const LAB_SETUP = `import { createTestClient } from "@ic-reactor/core/testing"
58
+ import { MutationObserver } from "@tanstack/react-query"
59
+ import { actor, type Actor, type TransferArg } from "./canisters/icrc1"
60
+
61
+ // LEDGER: the ckBTC ledger's id, "mxzaz-hqaaa-aaaar-qaada-cai" (mocked here).
62
+ // seed1, seed2: the principals of the test identities of seeds 1 and 2.
63
+ const { client, auth, mock, reject, dropNextReply, refuseNext, requests } =
64
+ createTestClient({ network: "ic" }) // signed in as the identity of seed 1
65
+ // Balances (seed 1 holds 1 ckBTC), fee 10, created_at_time deduplication:
66
+ mock<Actor>(actor, LEDGER, ledgerHandlers)
67
+ const ledger = client.canister<Actor>(actor, { id: LEDGER })
68
+ // What useMutation runs, without React:
69
+ const transfer = new MutationObserver(
70
+ client.queryClient,
71
+ client.mutationOptions(ledger, "icrc1_transfer"),
72
+ )
73
+ const arg = { to: { owner: seed2, subaccount: null }, amount: 25_000n,
74
+ fee: null, memo: null, from_subaccount: null,
75
+ created_at_time: BigInt(Date.now()) * 1_000_000n }
76
+ const dedupe = { dedupedBy: (a: TransferArg) => a.created_at_time }`
77
+
78
+ /** What the identity of seed 1 holds when a scenario starts: 1 ckBTC. */
79
+ export const START_BALANCE = 100_000_000n
80
+
81
+ /** Who the transfers pay: the identity of seed 2. */
82
+ const SEED2 = principal(
83
+ "xledz-fktfc-4ywwn-gai5u-ieqce-5x4qc-7lpel-o4ubn-ucngz-7lrzo-5ae"
84
+ )
85
+ const ANONYMOUS = "2vxsx-fae"
86
+
87
+ /** The typed Err payload of a transfer's `canister_err`. */
88
+ function transferErr(lab: Lab, error: unknown): TransferError | undefined {
89
+ return isReactorError(error, lab.ledger, "icrc1_transfer") &&
90
+ error.kind === "canister_err"
91
+ ? error.err
92
+ : undefined
93
+ }
94
+
95
+ const transferArg = (overrides: Partial<TransferArg> = {}): TransferArg => ({
96
+ to: { owner: SEED2, subaccount: null },
97
+ amount: 25_000n,
98
+ fee: null,
99
+ memo: null,
100
+ from_subaccount: null,
101
+ created_at_time: nowNanos(),
102
+ ...overrides,
103
+ })
104
+
105
+ const accountOf = (owner: Principal) => ({ owner, subaccount: null })
106
+
107
+ /** The caller as a checked principal (the test auth's text is always principal text). */
108
+ const callerOf = (lab: Lab): Principal => principal(lab.client.caller())
109
+
110
+ /** What `useMutation(client.mutationOptions(ledger, "icrc1_transfer"))` runs, without React. */
111
+ function transferObserver(lab: Lab) {
112
+ return new MutationObserver(
113
+ lab.client.queryClient,
114
+ lab.client.mutationOptions(lab.ledger, "icrc1_transfer")
115
+ )
116
+ }
117
+
118
+ const dedupedBy = { dedupedBy: (arg: TransferArg) => arg.created_at_time }
119
+
120
+ /** The caller's balance, read back as a direct query. */
121
+ async function readBack(
122
+ lab: Lab,
123
+ r: Recorder,
124
+ expected: bigint
125
+ ): Promise<ScenarioReply | undefined> {
126
+ const balance = valueOf(
127
+ r,
128
+ "Read the balance back (icrc1_balance_of)",
129
+ await settle(() => lab.ledger.icrc1_balance_of(accountOf(callerOf(lab))))
130
+ )
131
+ if (balance === undefined) return undefined
132
+ r.same("The balance is what one execution leaves", balance, expected)
133
+ return { method: "icrc1_balance_of", value: balance, tokens: true }
134
+ }
135
+
136
+ // ---------------------------------------------------------------------------
137
+ // The scenarios
138
+ // ---------------------------------------------------------------------------
139
+
140
+ const anonymousWrite: Scenario = {
141
+ id: "anonymous-write",
142
+ title: "An anonymous write is refused before it is sent",
143
+ rule: "A write is sent as whoever is signed in when it runs. If nobody is, the client refuses it (unauthenticated) before calling anything.",
144
+ narrative:
145
+ "Nobody is signed in, and the page runs a transfer through the same mutation options useMutation takes. The client looks up the caller when the mutation runs, finds the anonymous principal and refuses: nothing is signed, nothing reaches the replica, and the error says for certain that nothing ran.",
146
+ expected:
147
+ "unauthenticated / anonymous_write, mayHaveExecuted false, 0 requests.",
148
+ code: `createTestClient({ network: "ic", signedIn: false })
149
+ client.caller() // "2vxsx-fae"
150
+
151
+ await transfer.mutate(arg)
152
+ // ReactorError: kind "unauthenticated", code "anonymous_write",
153
+ // mayHaveExecuted false
154
+ requests.length // 0`,
155
+ run: () =>
156
+ runInLab({ signedIn: false }, async (lab, r) => {
157
+ r.same("Nobody is signed in", lab.client.caller(), ANONYMOUS)
158
+ const error = failureOf(
159
+ r,
160
+ "transfer.mutate(arg) is refused",
161
+ await settle(() => transferObserver(lab).mutate(transferArg()))
162
+ )
163
+ r.same("kind", fieldsOf(error)?.kind, "unauthenticated")
164
+ r.same("code", fieldsOf(error)?.code, "anonymous_write")
165
+ r.same("mayHaveExecuted", fieldsOf(error)?.mayHaveExecuted, false)
166
+ r.same("Requests the replica received", lab.kit.requests.length, 0)
167
+ r.same("Transfers the ledger ran", lab.mock.executed, 0)
168
+ return { error }
169
+ }),
170
+ }
171
+
172
+ /** A transfer argument that does not encode: a principal that is not one, a negative nat. */
173
+ const BAD_TRANSFER: Readonly<Record<string, unknown>> = {
174
+ to: { owner: "alice", subaccount: null },
175
+ amount: -5n,
176
+ fee: null,
177
+ memo: null,
178
+ from_subaccount: null,
179
+ created_at_time: null,
180
+ }
181
+
182
+ const invalidArgs: Scenario = {
183
+ id: "invalid-args",
184
+ title: "Arguments that do not encode never leave the page",
185
+ rule: "Arguments that do not encode make the call reject invalid_args, with the codec's issues; a render never throws on half-typed input.",
186
+ narrative:
187
+ "A transfer whose owner is not principal text and whose amount is a negative nat is sent through an untyped view of the ledger, which is what a form over a runtime interface holds. The codec refuses it before anything is signed. Its issue names the field, rooted at $args[0] (the codec stops at the first field that fails, so fixing the owner moves the issue to the amount), and the form below puts each issue on its field with the same paths. A read with the same mistake gets a $invalid key instead of throwing during render.",
188
+ expected:
189
+ "invalid_args at $args[0].to.owner, then at $args[0].amount once the owner is fixed; 0 requests.",
190
+ code: `const untyped = client.canister<DynActor>(actor, { id: LEDGER })
191
+ await untyped.icrc1_transfer({
192
+ to: { owner: "alice", subaccount: null }, // not principal text
193
+ amount: -5n, // a nat is never negative
194
+ fee: null, memo: null, from_subaccount: null, created_at_time: null,
195
+ })
196
+ // ReactorError: kind "invalid_args", issues: [{ path: "$args[0].to.owner", … }]
197
+ // with the owner fixed, the issue moves to "$args[0].amount"
198
+
199
+ client.queryKey(untyped, "icrc1_balance_of", { owner: "alice", subaccount: null })
200
+ // [..., "$invalid", …]: the read rejects invalid_args when it runs`,
201
+ run: () =>
202
+ runInLab({ fund: START_BALANCE }, async (lab, r) => {
203
+ // The same canister object, typed for values that are not checked yet.
204
+ const untyped = lab.client.canister<DynActor>(icrc1Actor, {
205
+ id: LAB_LEDGER_ID,
206
+ })
207
+ r.same(
208
+ "The untyped view is the same canister object",
209
+ Object.is(untyped, lab.ledger),
210
+ true
211
+ )
212
+ const error = failureOf(
213
+ r,
214
+ "icrc1_transfer(bad argument) is refused",
215
+ await settle(() => callUntyped(untyped, "icrc1_transfer", BAD_TRANSFER))
216
+ )
217
+ r.same("kind", fieldsOf(error)?.kind, "invalid_args")
218
+ r.same("mayHaveExecuted", fieldsOf(error)?.mayHaveExecuted, false)
219
+ const paths = issuePaths(error)
220
+ r.check(
221
+ "Its issues are rooted at $args[0]",
222
+ paths.length > 0 && paths.every((p) => p.startsWith("$args[0]")),
223
+ show(paths)
224
+ )
225
+ r.check(
226
+ "The issue is on $args[0].to.owner, the first field that fails",
227
+ paths.includes("$args[0].to.owner"),
228
+ show(paths)
229
+ )
230
+
231
+ // The codec stops at the first field that fails: fix it and the next
232
+ // one is named.
233
+ const ownerFixed = {
234
+ ...BAD_TRANSFER,
235
+ to: { owner: SEED2, subaccount: null },
236
+ }
237
+ const next = failureOf(
238
+ r,
239
+ "With the owner fixed, it is refused again",
240
+ await settle(() => callUntyped(untyped, "icrc1_transfer", ownerFixed))
241
+ )
242
+ r.check(
243
+ "Now the issue is on $args[0].amount",
244
+ issuePaths(next).includes("$args[0].amount"),
245
+ show(issuePaths(next))
246
+ )
247
+
248
+ const badAccount = { owner: "alice", subaccount: null }
249
+ const key = await settle(() =>
250
+ lab.client.queryKey(untyped, "icrc1_balance_of", badAccount)
251
+ )
252
+ r.check(
253
+ "A read of the same mistake builds a $invalid key without throwing",
254
+ key.ok && key.value.includes("$invalid"),
255
+ key.ok ? show(key.value.slice(4)) : describeFailure(key.error)
256
+ )
257
+ const read = await settle(() =>
258
+ lab.client.queryClient.fetchQuery(
259
+ lab.client.queryOptions(untyped, "icrc1_balance_of", badAccount)
260
+ )
261
+ )
262
+ const readError = failureOf(r, "Running that read is refused", read)
263
+ r.same("The read's kind", fieldsOf(readError)?.kind, "invalid_args")
264
+ r.same("Requests the replica received", lab.kit.requests.length, 0)
265
+ return {
266
+ error,
267
+ form: { method: "icrc1_transfer", values: [BAD_TRANSFER] },
268
+ }
269
+ }),
270
+ }
271
+
272
+ const lostReply: Scenario = {
273
+ id: "lost-reply",
274
+ title: "A lost reply: re-send safely, and it runs once",
275
+ rule: "Send the same write again after mayHaveExecuted: true only to a method that deduplicates, such as an ICRC-1 transfer with created_at_time set, and only through resendOf.",
276
+ narrative:
277
+ "The ledger runs the transfer, but its reply is lost on the way back. The client cannot know whether it ran, so it says outcome_unknown and mayHaveExecuted: true, and retries nothing. Because the argument carries created_at_time, resendOf offers to send the very same bytes again, as the same sender. The ledger recognises the transaction and answers Duplicate: it executed exactly once, and the balance read back agrees.",
278
+ expected:
279
+ "outcome_unknown (mayHaveExecuted true), resendOf offered, send() → canister_err Duplicate, 1 execution.",
280
+ code: `dropNextReply()
281
+ await transfer.mutate(arg)
282
+ // ReactorError: kind "outcome_unknown", mayHaveExecuted true
283
+
284
+ const error = transfer.getCurrentResult().error
285
+ const again = client.resendOf(error, ledger, "icrc1_transfer", dedupe)
286
+ again.arg === arg // the very object that was sent
287
+ await again.send()
288
+ // ReactorError: kind "canister_err", err { tag: "Duplicate", … }`,
289
+ run: () =>
290
+ runInLab({ fund: START_BALANCE }, async (lab, r) => {
291
+ const arg = transferArg()
292
+ const observer = transferObserver(lab)
293
+ lab.kit.dropNextReply()
294
+ r.note("dropNextReply(): the ledger will run, its reply will be lost")
295
+ const error = failureOf(
296
+ r,
297
+ "transfer.mutate(arg) fails",
298
+ await settle(() => observer.mutate(arg))
299
+ )
300
+ r.check(
301
+ "The mutation keeps that error",
302
+ observer.getCurrentResult().error === error
303
+ )
304
+ r.same("kind", fieldsOf(error)?.kind, "outcome_unknown")
305
+ r.same("mayHaveExecuted", fieldsOf(error)?.mayHaveExecuted, true)
306
+ r.same("The ledger did run it", lab.mock.executed, 1)
307
+ r.same(
308
+ "The client sent it once (no blind retry)",
309
+ sent(lab, "icrc1_transfer").length,
310
+ 1
311
+ )
312
+
313
+ const again = lab.client.resendOf(
314
+ error,
315
+ lab.ledger,
316
+ "icrc1_transfer",
317
+ dedupedBy
318
+ )
319
+ if (!present(r, "resendOf offers a re-send", again)) {
320
+ return { error }
321
+ }
322
+ r.check("It offers the very object that was sent", again.arg === arg)
323
+ r.same(
324
+ "It re-sends as the original sender",
325
+ again.from,
326
+ lab.client.caller()
327
+ )
328
+
329
+ const duplicate = failureOf(
330
+ r,
331
+ "again.send() is answered with an Err",
332
+ await settle(() => again.send())
333
+ )
334
+ r.same("kind", fieldsOf(duplicate)?.kind, "canister_err")
335
+ const err = transferErr(lab, duplicate)
336
+ r.same("The Err is Duplicate", err?.tag, "Duplicate")
337
+ if (err?.tag === "Duplicate") {
338
+ r.same("duplicate_of the first block", err.value.duplicate_of, 0n)
339
+ }
340
+ r.same("The ledger ran it exactly once", lab.mock.executed, 1)
341
+ r.same(
342
+ "The re-send reached the replica",
343
+ sent(lab, "icrc1_transfer").length,
344
+ 2
345
+ )
346
+ const reply = await readBack(lab, r, START_BALANCE - arg.amount - LAB_FEE)
347
+ return {
348
+ error,
349
+ moreErrors: [{ label: "The re-send: Duplicate", error: duplicate }],
350
+ ...(reply === undefined ? {} : { reply }),
351
+ }
352
+ }),
353
+ }
354
+
355
+ const throttled: Scenario = {
356
+ id: "http-429",
357
+ title: "HTTP 429: the client re-sends once, by itself",
358
+ rule: "The client itself re-sends an update, at most twice, only after a failure proving the canister never got it (reject code 2, status 429); any other failure is final.",
359
+ narrative:
360
+ "The boundary node throttles the first transfer with HTTP 429 before any canister sees it. That status proves the update never got in, so the client waits briefly and sends the same request again on its own: the mutation still has retry: false, and the caller sees one success. The log shows two calls, the first refused.",
361
+ expected:
362
+ "Ok (block index) after 2 icrc1_transfer calls, the first refused 429.",
363
+ code: `refuseNext(429, { method: "icrc1_transfer" })
364
+ await transfer.mutate({ ...arg, created_at_time: null }) // 0n: the block index
365
+ requests.filter((q) => q.methodName === "icrc1_transfer")
366
+ // [{ refused: "refuseNext(429) answered …" }, { caller: "psith-…" }]`,
367
+ run: () =>
368
+ runInLab({ fund: START_BALANCE }, async (lab, r) => {
369
+ lab.kit.refuseNext(429, { method: "icrc1_transfer" })
370
+ r.note('refuseNext(429, { method: "icrc1_transfer" })')
371
+ const options = lab.client.mutationOptions(lab.ledger, "icrc1_transfer")
372
+ r.same("The mutation options never retry", options.retry, false)
373
+ const block = valueOf(
374
+ r,
375
+ "transfer.mutate(arg) succeeds",
376
+ await settle(() =>
377
+ new MutationObserver(lab.client.queryClient, options).mutate(
378
+ transferArg({ created_at_time: null })
379
+ )
380
+ )
381
+ )
382
+ const calls = sent(lab, "icrc1_transfer")
383
+ r.same("icrc1_transfer calls the replica received", calls.length, 2)
384
+ r.check(
385
+ "The first was refused with 429",
386
+ calls[0]?.refused?.includes("429") === true,
387
+ calls[0]?.refused
388
+ )
389
+ r.same("The second went through", calls[1]?.refused, undefined)
390
+ r.same("The ledger ran it once", lab.mock.executed, 1)
391
+ return block === undefined
392
+ ? {}
393
+ : { reply: { method: "icrc1_transfer", value: block, tokens: false } }
394
+ }),
395
+ }
396
+
397
+ const trapped: Scenario = {
398
+ id: "reject-5",
399
+ title: "A trap (reject 5) may have executed: no blind retry",
400
+ rule: "Read mayHaveExecuted on every failed write. A method with no deduplication key has no safe re-send: read the state back.",
401
+ narrative:
402
+ "The ledger traps while handling the transfer. A canister can commit work before it traps (an inter-canister call made earlier commits its side), so ic-reactor cannot promise nothing happened: kind rejected, reject code 5, mayHaveExecuted true. It sends nothing again by itself, and since this argument has no created_at_time, resendOf offers nothing either: the right move is to read the state back. Here the trap rolled the transfer back, so the balance is unchanged.",
403
+ expected:
404
+ "rejected, rejectCode 5, mayHaveExecuted true, 1 call, resendOf undefined.",
405
+ code: `mock<Actor>(actor, LEDGER, {
406
+ ...ledgerHandlers,
407
+ icrc1_transfer: () => { throw new Error("assertion failed: …") }, // a trap
408
+ })
409
+ await transfer.mutate({ ...arg, created_at_time: null })
410
+ // ReactorError: kind "rejected", rejectCode 5, mayHaveExecuted true
411
+
412
+ client.resendOf(error, ledger, "icrc1_transfer", dedupe)
413
+ // undefined: nothing to deduplicate on, so read the state back:
414
+ await ledger.icrc1_balance_of({ owner: seed1, subaccount: null })`,
415
+ run: () =>
416
+ runInLab({ fund: START_BALANCE }, async (lab, r) => {
417
+ lab.mock.failNextTransfer({
418
+ kind: "trap",
419
+ message: "assertion failed: the memo is longer than 32 bytes",
420
+ })
421
+ r.note("The ledger's next transfer traps")
422
+ const error = failureOf(
423
+ r,
424
+ "transfer.mutate(arg) fails",
425
+ await settle(() =>
426
+ transferObserver(lab).mutate(transferArg({ created_at_time: null }))
427
+ )
428
+ )
429
+ r.same("kind", fieldsOf(error)?.kind, "rejected")
430
+ r.same("rejectCode", fieldsOf(error)?.rejectCode, 5)
431
+ r.same("mayHaveExecuted", fieldsOf(error)?.mayHaveExecuted, true)
432
+ r.same(
433
+ "It was sent once (no blind retry)",
434
+ sent(lab, "icrc1_transfer").length,
435
+ 1
436
+ )
437
+ r.same(
438
+ "resendOf offers nothing without a created_at_time",
439
+ lab.client.resendOf(error, lab.ledger, "icrc1_transfer", dedupedBy),
440
+ undefined
441
+ )
442
+ const reply = await readBack(lab, r, START_BALANCE)
443
+ return { error, ...(reply === undefined ? {} : { reply }) }
444
+ }),
445
+ }
446
+
447
+ const destinationInvalid: Scenario = {
448
+ id: "reject-3",
449
+ title: "Reject 3: certainly not executed",
450
+ rule: "A reject 1 or 3 proves nothing ran: mayHaveExecuted is false, nothing is invalidated, and no re-send is offered.",
451
+ narrative:
452
+ "The replica rejects the transfer with code 3 (destination invalid), the reject a call gets when the canister cannot take it at all. That proves the canister never ran it, so mayHaveExecuted is false. Even though the argument carries created_at_time, resendOf offers nothing: there is no unknown outcome to resolve, and a fresh attempt is simply a new write.",
453
+ expected:
454
+ "rejected, rejectCode 3, mayHaveExecuted false, resendOf undefined, balance unchanged.",
455
+ code: `mock<Actor>(actor, LEDGER, {
456
+ ...ledgerHandlers,
457
+ icrc1_transfer: () => reject(3, "Requested canister has no wasm module"),
458
+ })
459
+ await transfer.mutate(arg) // arg has created_at_time
460
+ // ReactorError: kind "rejected", rejectCode 3, mayHaveExecuted false
461
+ client.resendOf(error, ledger, "icrc1_transfer", dedupe)
462
+ // undefined: the outcome is known, nothing to resolve`,
463
+ run: () =>
464
+ runInLab({ fund: START_BALANCE }, async (lab, r) => {
465
+ lab.mock.failNextTransfer({
466
+ kind: "reject",
467
+ code: 3,
468
+ message: "Requested canister has no wasm module",
469
+ })
470
+ r.note("The ledger's next transfer is rejected with code 3")
471
+ const error = failureOf(
472
+ r,
473
+ "transfer.mutate(arg) fails",
474
+ await settle(() => transferObserver(lab).mutate(transferArg()))
475
+ )
476
+ r.same("kind", fieldsOf(error)?.kind, "rejected")
477
+ r.same("rejectCode", fieldsOf(error)?.rejectCode, 3)
478
+ r.same("mayHaveExecuted", fieldsOf(error)?.mayHaveExecuted, false)
479
+ r.same(
480
+ "resendOf offers nothing: the outcome is known",
481
+ lab.client.resendOf(error, lab.ledger, "icrc1_transfer", dedupedBy),
482
+ undefined
483
+ )
484
+ r.same("It was sent once", sent(lab, "icrc1_transfer").length, 1)
485
+ r.same("Transfers the ledger ran", lab.mock.executed, 0)
486
+ const reply = await readBack(lab, r, START_BALANCE)
487
+ return { error, ...(reply === undefined ? {} : { reply }) }
488
+ }),
489
+ }
490
+
491
+ const canisterErr: Scenario = {
492
+ id: "canister-err",
493
+ title: "An Err result is a typed canister_err",
494
+ rule: "A method whose result is variant { Ok; Err } resolves with the Ok value; Err rejects as kind canister_err, with the Err value in err.",
495
+ narrative:
496
+ 'The transfer asks for more than the account holds. The ledger answers Err InsufficientFunds, a reply, not a failure of the call: ic-reactor rejects with kind canister_err, mayHaveExecuted false, and the Err payload in err. Narrowed with isReactorError(error, ledger, "icrc1_transfer"), err is typed as the ledger\'s TransferError, so the balance in it is a bigint with no cast.',
497
+ expected:
498
+ 'canister_err, mayHaveExecuted false, err { tag: "InsufficientFunds", value: { balance } }.',
499
+ code: `try {
500
+ await ledger.icrc1_transfer({ ...arg, amount: 2_000_000_000n })
501
+ } catch (error) {
502
+ if (isReactorError(error, ledger, "icrc1_transfer") &&
503
+ error.kind === "canister_err" &&
504
+ error.err.tag === "InsufficientFunds") {
505
+ error.err.value.balance // bigint, typed from the .did
506
+ }
507
+ }`,
508
+ run: () =>
509
+ runInLab({ fund: START_BALANCE }, async (lab, r) => {
510
+ const error = failureOf(
511
+ r,
512
+ "icrc1_transfer(20 ckBTC) fails",
513
+ await settle(() =>
514
+ lab.ledger.icrc1_transfer(transferArg({ amount: 2_000_000_000n }))
515
+ )
516
+ )
517
+ if (isReactorError(error, lab.ledger, "icrc1_transfer")) {
518
+ r.same("kind", error.kind, "canister_err")
519
+ r.same("mayHaveExecuted", error.mayHaveExecuted, false)
520
+ const err = error.kind === "canister_err" ? error.err : undefined
521
+ r.same("The Err is InsufficientFunds", err?.tag, "InsufficientFunds")
522
+ if (err?.tag === "InsufficientFunds") {
523
+ r.same(
524
+ "Its balance is the account's",
525
+ err.value.balance,
526
+ START_BALANCE
527
+ )
528
+ }
529
+ } else {
530
+ r.check(
531
+ 'isReactorError(error, ledger, "icrc1_transfer") narrows it',
532
+ false,
533
+ describeFailure(error)
534
+ )
535
+ }
536
+ r.same("Transfers the ledger ran", lab.mock.executed, 0)
537
+ return { error }
538
+ }),
539
+ }
540
+
541
+ const callerChanged: Scenario = {
542
+ id: "caller-changed",
543
+ title: "The caller changes: reads and re-sends refuse",
544
+ rule: "A read is made as the caller current when its options are built, and a re-send goes out only as its sender; for anyone else nothing is sent (caller_changed). The read is cancelled; the re-send stays outcome_unknown, since the write it re-sends may have run.",
545
+ narrative:
546
+ "Options for a balance read are built while seed 1 is signed in, then the user switches to seed 2 before the read runs: the query function refuses to send seed 1's read as seed 2. Then a transfer by seed 1 loses its reply. After a switch to seed 2, resendOf offers nothing, and the offer already in hand refuses to go out as the wrong sender. Back as seed 1, the offer returns and the re-send answers Duplicate.",
547
+ expected:
548
+ "cancelled / caller_changed for the read, outcome_unknown / caller_changed for send() as seed 2, 0 extra requests; offer restored for seed 1.",
549
+ code: `const account = { owner: seed2, subaccount: null }
550
+ const read = client.queryOptions(ledger, "icrc1_balance_of", account) // as seed 1
551
+ auth.switchTo(2)
552
+ await client.queryClient.fetchQuery(read)
553
+ // ReactorError: kind "cancelled", code "caller_changed"
554
+
555
+ auth.switchTo(1); dropNextReply(); await transfer.mutate(arg) // outcome_unknown
556
+ const again = client.resendOf(error, ledger, "icrc1_transfer", dedupe)
557
+ auth.switchTo(2)
558
+ client.resendOf(error, ledger, "icrc1_transfer", dedupe) // undefined
559
+ await again.send() // outcome_unknown / caller_changed, nothing sent
560
+ auth.switchTo(1)
561
+ await again.send() // canister_err Duplicate: it ran once`,
562
+ run: () =>
563
+ runInLab({ fund: START_BALANCE }, async (lab, r) => {
564
+ const { auth } = lab.kit
565
+ const seed1 = lab.client.caller()
566
+ const read = lab.client.queryOptions(
567
+ lab.ledger,
568
+ "icrc1_balance_of",
569
+ accountOf(SEED2)
570
+ )
571
+ r.same("The read's key holds seed 1", read.queryKey[2], seed1)
572
+ auth.switchTo(2)
573
+ r.note("auth.switchTo(2) before the read runs", lab.client.caller())
574
+ const before = lab.kit.requests.length
575
+ const readError = failureOf(
576
+ r,
577
+ "Running seed 1's read as seed 2 is refused",
578
+ await settle(() => lab.client.queryClient.fetchQuery(read))
579
+ )
580
+ r.same("kind", fieldsOf(readError)?.kind, "cancelled")
581
+ r.same("code", fieldsOf(readError)?.code, "caller_changed")
582
+ r.same("Nothing was sent", lab.kit.requests.length, before)
583
+
584
+ auth.switchTo(1)
585
+ r.note("auth.switchTo(1); dropNextReply(); transfer.mutate(arg)")
586
+ const arg = transferArg()
587
+ lab.kit.dropNextReply()
588
+ const lost = failureOf(
589
+ r,
590
+ "The transfer's reply is lost",
591
+ await settle(() => transferObserver(lab).mutate(arg))
592
+ )
593
+ const again = lab.client.resendOf(
594
+ lost,
595
+ lab.ledger,
596
+ "icrc1_transfer",
597
+ dedupedBy
598
+ )
599
+ if (!present(r, "resendOf offers a re-send to seed 1", again)) {
600
+ return { error: readError }
601
+ }
602
+ auth.switchTo(2)
603
+ r.note("auth.switchTo(2)")
604
+ r.same(
605
+ "resendOf offers nothing to seed 2",
606
+ lab.client.resendOf(lost, lab.ledger, "icrc1_transfer", dedupedBy),
607
+ undefined
608
+ )
609
+ const calls = sent(lab, "icrc1_transfer").length
610
+ const refused = failureOf(
611
+ r,
612
+ "again.send() as seed 2 is refused",
613
+ await settle(() => again.send())
614
+ )
615
+ // The write it re-sends may have run: its outcome stays unknown.
616
+ r.same("kind", fieldsOf(refused)?.kind, "outcome_unknown")
617
+ r.same("mayHaveExecuted", fieldsOf(refused)?.mayHaveExecuted, true)
618
+ r.same("code", fieldsOf(refused)?.code, "caller_changed")
619
+ r.same("Nothing was sent", sent(lab, "icrc1_transfer").length, calls)
620
+
621
+ auth.switchTo(1)
622
+ r.note("auth.switchTo(1)")
623
+ r.check(
624
+ "The offer is back for its sender",
625
+ lab.client.resendOf(lost, lab.ledger, "icrc1_transfer", dedupedBy) !==
626
+ undefined
627
+ )
628
+ const duplicate = failureOf(
629
+ r,
630
+ "again.send() as seed 1 is answered",
631
+ await settle(() => again.send())
632
+ )
633
+ r.same(
634
+ "The answer is Duplicate",
635
+ transferErr(lab, duplicate)?.tag,
636
+ "Duplicate"
637
+ )
638
+ r.same("The ledger ran it exactly once", lab.mock.executed, 1)
639
+ return {
640
+ error: readError,
641
+ moreErrors: [
642
+ { label: "The re-send as seed 2", error: refused, afterResend: true },
643
+ ],
644
+ }
645
+ }),
646
+ }
647
+
648
+ /** The key segments after the caller's: what two callers' keys of one read share. */
649
+ const afterCaller = (key: QueryKey): string => JSON.stringify(key.slice(3))
650
+
651
+ const cacheIsolation: Scenario = {
652
+ id: "cache-isolation",
653
+ title: "One read, two principals, two keys",
654
+ rule: "Keys are [\"ic-reactor\", network, caller, canisterId, method, args]: one principal's cached answer is never served to another; after a sign-in, sign-out or switch, the new caller's key is empty until it loads.",
655
+ narrative:
656
+ "The same balance read, with the same argument, is made by seed 1 and then by seed 2. Their keys differ only in the caller segment, so each principal gets its own cache entry, and seed 2 starts with nothing, whatever the cache holds for seed 1. After a sign-out the anonymous key is empty too: nothing cached for a principal is shown to anyone else.",
657
+ expected:
658
+ "Two keys that differ only at the caller; seed 2's and the anonymous key start empty.",
659
+ code: `const account = { owner: seed2, subaccount: null }
660
+ await client.queryClient.fetchQuery(
661
+ client.queryOptions(ledger, "icrc1_balance_of", account)) // as seed 1
662
+ auth.switchTo(2)
663
+ client.queryClient.getQueryData(
664
+ client.queryKey(ledger, "icrc1_balance_of", account)) // undefined
665
+ await client.queryClient.fetchQuery(
666
+ client.queryOptions(ledger, "icrc1_balance_of", account)) // as seed 2
667
+ await auth.signOut()
668
+ client.queryClient.getQueryData(
669
+ client.queryKey(ledger, "icrc1_balance_of", account)) // undefined`,
670
+ run: () =>
671
+ runInLab({ fund: START_BALANCE }, async (lab, r) => {
672
+ const { auth } = lab.kit
673
+ const { queryClient } = lab.client
674
+ lab.mock.fund(SEED2, 5_000n)
675
+ const account = accountOf(SEED2)
676
+ const keyNow = (): QueryKey =>
677
+ lab.client.queryKey(lab.ledger, "icrc1_balance_of", account)
678
+
679
+ const first = lab.client.queryOptions(
680
+ lab.ledger,
681
+ "icrc1_balance_of",
682
+ account
683
+ )
684
+ const value1 = valueOf(
685
+ r,
686
+ "Seed 1 reads the balance",
687
+ await settle(() => queryClient.fetchQuery(first))
688
+ )
689
+ const key1 = first.queryKey
690
+ r.same("Its key holds seed 1", key1[2], lab.client.caller())
691
+
692
+ auth.switchTo(2)
693
+ r.note("auth.switchTo(2)", lab.client.caller())
694
+ r.same(
695
+ "Seed 2's key starts empty",
696
+ queryClient.getQueryData(keyNow()),
697
+ undefined
698
+ )
699
+ const second = lab.client.queryOptions(
700
+ lab.ledger,
701
+ "icrc1_balance_of",
702
+ account
703
+ )
704
+ const value2 = valueOf(
705
+ r,
706
+ "Seed 2 reads the same balance",
707
+ await settle(() => queryClient.fetchQuery(second))
708
+ )
709
+ const key2 = second.queryKey
710
+ r.same("Same answer for both", value2, value1)
711
+ r.check(
712
+ "The keys differ",
713
+ JSON.stringify(key1) !== JSON.stringify(key2),
714
+ `${show(key1[2])} vs ${show(key2[2])}`
715
+ )
716
+ r.check(
717
+ "Only in the caller segment",
718
+ JSON.stringify(key1.slice(0, 2)) === JSON.stringify(key2.slice(0, 2)) &&
719
+ afterCaller(key1) === afterCaller(key2)
720
+ )
721
+
722
+ await auth.signOut()
723
+ r.note("auth.signOut()", lab.client.caller())
724
+ r.same(
725
+ "The anonymous key is empty",
726
+ queryClient.getQueryData(keyNow()),
727
+ undefined
728
+ )
729
+ r.same(
730
+ "Reads cached for the anonymous principal",
731
+ queryClient.getQueryCache().findAll({
732
+ queryKey: lab.client.queryKey(lab.ledger),
733
+ }).length,
734
+ 0
735
+ )
736
+ return value1 === undefined
737
+ ? {}
738
+ : { reply: { method: "icrc1_balance_of", value: value1, tokens: true } }
739
+ }),
740
+ }
741
+
742
+ const certifiedTwin: Scenario = {
743
+ id: "certified-twin",
744
+ title: "The certified twin: its own keys, no composite queries",
745
+ rule: 'The target { id, certified: true } certifies query replies; it is a separate canister object with keys ending in "certified", and a composite query on it is refused.',
746
+ narrative:
747
+ 'The certified twin of the ledger is a different canister object. Its balance read goes out as a replicated call whose certificate the client verifies, and it caches under a key that ends in "certified", so a certified answer and an uncertified one never mix. A composite query cannot be certified: building its read options on the certified twin of the index throws a TypeError at once, while the plain index answers it.',
748
+ expected:
749
+ 'Separate keys ("certified" last), query vs call in the log, TypeError for the certified composite query.',
750
+ code: `const account = { owner: seed1, subaccount: null }
751
+ const certified = client.canister<Actor>(actor, { id: LEDGER, certified: true })
752
+ client.queryKey(certified, "icrc1_balance_of", account).at(-1) // "certified"
753
+ await client.queryClient.fetchQuery(
754
+ client.queryOptions(certified, "icrc1_balance_of", account)) // a replicated call
755
+
756
+ // An index canister whose balance_via_ledger is a composite query:
757
+ const index = client.canister<Index>(indexActor, { id: INDEX, certified: true })
758
+ client.queryOptions(index, "balance_via_ledger", account)
759
+ // TypeError: a composite query cannot be certified`,
760
+ run: () =>
761
+ runInLab({ fund: START_BALANCE }, async (lab, r) => {
762
+ const { queryClient } = lab.client
763
+ const account = accountOf(callerOf(lab))
764
+ const certified = lab.client.canister<Icrc1Actor>(icrc1Actor, {
765
+ id: LAB_LEDGER_ID,
766
+ certified: true,
767
+ })
768
+ r.check(
769
+ "The certified twin is another canister object",
770
+ certified !== lab.ledger
771
+ )
772
+ const plainKey = lab.client.queryKey(
773
+ lab.ledger,
774
+ "icrc1_balance_of",
775
+ account
776
+ )
777
+ const certifiedKey = lab.client.queryKey(
778
+ certified,
779
+ "icrc1_balance_of",
780
+ account
781
+ )
782
+ r.same(
783
+ 'The certified key ends in "certified"',
784
+ certifiedKey.at(-1),
785
+ "certified"
786
+ )
787
+ r.check(
788
+ "The plain key ends in the argument bytes",
789
+ plainKey.at(-1) !== "certified",
790
+ clip(String(plainKey.at(-1)))
791
+ )
792
+ r.check(
793
+ "The keys differ",
794
+ JSON.stringify(plainKey) !== JSON.stringify(certifiedKey)
795
+ )
796
+
797
+ const plain = valueOf(
798
+ r,
799
+ "The plain read",
800
+ await settle(() =>
801
+ queryClient.fetchQuery(
802
+ lab.client.queryOptions(lab.ledger, "icrc1_balance_of", account)
803
+ )
804
+ )
805
+ )
806
+ const cert = valueOf(
807
+ r,
808
+ "The certified read",
809
+ await settle(() =>
810
+ queryClient.fetchQuery(
811
+ lab.client.queryOptions(certified, "icrc1_balance_of", account)
812
+ )
813
+ )
814
+ )
815
+ r.same("Both read the same balance", cert, plain)
816
+ const balanceRequests = sent(lab, "icrc1_balance_of").map(
817
+ (q) => q.endpoint
818
+ )
819
+ r.same(
820
+ "The plain read went out as a query, the certified one as a call",
821
+ balanceRequests.join(" then "),
822
+ "query then call"
823
+ )
824
+ const cache = queryClient.getQueryCache()
825
+ const plainEntry = cache.find({ queryKey: plainKey, exact: true })
826
+ const certifiedEntry = cache.find({ queryKey: certifiedKey, exact: true })
827
+ r.check(
828
+ "Each twin has its own cache entry",
829
+ plainEntry !== undefined &&
830
+ certifiedEntry !== undefined &&
831
+ plainEntry !== certifiedEntry
832
+ )
833
+ // Keys are prefixes of each other: the canister's prefix matches the
834
+ // certified key too, which is how a write invalidates both twins.
835
+ r.same(
836
+ "The canister's key prefix matches both, so a write invalidates both",
837
+ cache.findAll({ queryKey: lab.client.queryKey(lab.ledger) }).length,
838
+ 2
839
+ )
840
+
841
+ const certifiedIndex = lab.client.canister<LabIndexActor>(labIndexActor, {
842
+ id: LAB_INDEX_ID,
843
+ certified: true,
844
+ })
845
+ const refused = await settle(() =>
846
+ lab.client.queryOptions(certifiedIndex, "balance_via_ledger", account)
847
+ )
848
+ r.check(
849
+ "A composite query on the certified twin throws a TypeError",
850
+ !refused.ok && refused.error instanceof TypeError,
851
+ refused.ok ? "it built options" : describeFailure(refused.error)
852
+ )
853
+ valueOf(
854
+ r,
855
+ "The plain index answers the composite query",
856
+ await settle(() =>
857
+ queryClient.fetchQuery(
858
+ lab.client.queryOptions(lab.index, "balance_via_ledger", account)
859
+ )
860
+ )
861
+ )
862
+ return plain === undefined
863
+ ? {}
864
+ : { reply: { method: "icrc1_balance_of", value: plain, tokens: true } }
865
+ }),
866
+ }
867
+
868
+ export const SCENARIOS: readonly Scenario[] = [
869
+ anonymousWrite,
870
+ invalidArgs,
871
+ lostReply,
872
+ throttled,
873
+ trapped,
874
+ destinationInvalid,
875
+ canisterErr,
876
+ callerChanged,
877
+ cacheIsolation,
878
+ certifiedTwin,
879
+ ]
880
+
881
+ /** What a transfer sent from the lab's form did. */
882
+ export type LabSend =
883
+ | {
884
+ readonly ok: true
885
+ readonly block: bigint
886
+ readonly requests: readonly LoggedRequest[]
887
+ }
888
+ | {
889
+ readonly ok: false
890
+ readonly error: unknown
891
+ readonly requests: readonly LoggedRequest[]
892
+ }
893
+
894
+ /**
895
+ * Sends `vars` (the form's corrected transfer) as seed 1 to a fresh lab, so
896
+ * the invalid-arguments card can show the fixed call going through. Never
897
+ * rejects: a failure, the lab's own included, is the outcome.
898
+ */
899
+ export async function sendTransferInLab(vars: unknown): Promise<LabSend> {
900
+ let lab: Lab | undefined
901
+ try {
902
+ lab = await createLab({ fund: START_BALANCE })
903
+ const untyped = lab.client.canister<DynActor>(icrc1Actor, {
904
+ id: LAB_LEDGER_ID,
905
+ })
906
+ const block = await callUntyped(untyped, "icrc1_transfer", vars)
907
+ const requests = lab.kit.requests.map(logged)
908
+ return typeof block === "bigint"
909
+ ? { ok: true, block, requests }
910
+ : {
911
+ ok: false,
912
+ error: new TypeError("the reply is not a block index"),
913
+ requests,
914
+ }
915
+ } catch (error) {
916
+ return {
917
+ ok: false,
918
+ error,
919
+ requests: lab === undefined ? [] : lab.kit.requests.map(logged),
920
+ }
921
+ } finally {
922
+ lab?.client.dispose()
923
+ }
924
+ }