@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,1020 @@
1
+ /**
2
+ * Network resolution: which replica a client talks to, whose root key its
3
+ * certificates are checked against, and where a canister id may come from.
4
+ *
5
+ * Only {@link Network} is public. The rest is internal, for the client and
6
+ * the canister builders, and is not exported from the package entry.
7
+ *
8
+ * Everything here decides who is believed, so each rule is a positive
9
+ * allowlist that fails closed:
10
+ *
11
+ * - **A root key is fetched from a replica only when asked for in writing or
12
+ * when the host is local.** A given key is used and never fetched.
13
+ * Anything else is checked against the mainnet key the agent ships with, so
14
+ * a host that is not a local replica can never hand over a key of its own
15
+ * choosing.
16
+ * - **The `ic_env` cookie is believed only where it is as trustworthy as the
17
+ * replica it describes.** Cookies are not origin-isolated: any sibling
18
+ * subdomain of the page's registrable domain can write one. (Not so on
19
+ * `<id>.icp0.io` and `<id>.raw.icp0.io`: `icp0.io` and `*.raw.icp0.io` are
20
+ * on the Public Suffix List, so a browser refuses a cookie a sibling
21
+ * canister sets for them, and the cookie such a page receives is its own
22
+ * asset canister's.) It carries the
23
+ * root key certificates are verified against and the canister ids calls are
24
+ * routed to, and certificate verification cannot notice a substituted id
25
+ * (the attacker names a real canister, whose replies verify against the real
26
+ * root key). So the cookie is read only in a browser, and only when both the
27
+ * agent host and the page are a local replica, or the caller wrote
28
+ * `allowEnvConfig: true`. On a canister's own `icp0.io` page with a mainnet
29
+ * agent host, its canister ids are believed by default. Its root key is
30
+ * never taken for a mainnet host, which has one key, the agent's own; its
31
+ * Internet Identity URL is taken over `http:` only on a local page; and the
32
+ * opt-in itself is refused on a page under a shared parent that is not a
33
+ * public suffix (`ic0.app`, `github.dev`, `gitpod.io`, `loca.lt`,
34
+ * `devtunnels.ms`), where any stranger's page can write the cookie.
35
+ *
36
+ * @module
37
+ */
38
+
39
+ import { IC_ROOT_KEY } from "@icp-sdk/core/agent"
40
+ import { safeGetCanisterEnv } from "@icp-sdk/core/agent/canister-env"
41
+ import { Principal } from "@icp-sdk/core/principal"
42
+ import { isServer } from "./runtime.js"
43
+
44
+ /**
45
+ * Where the canisters are.
46
+ *
47
+ * - `"ic"`: mainnet, through `https://icp-api.io`, checked against the
48
+ * mainnet root key the agent ships with. Nothing is fetched.
49
+ * - `"local"`: icp-cli's local network, `http://127.0.0.1:8000`. Its root key
50
+ * is fetched from the replica before the first call. A dfx replica (port
51
+ * 4943) is an object: `{ host: "http://127.0.0.1:4943" }`.
52
+ * - `"env"`: the network of the page this code runs in, as an asset canister
53
+ * or a dev server describes it. In a browser, a page on a local replica or
54
+ * on a mainnet boundary domain routes through its own origin, and so does
55
+ * a page that forwards a dev server: Codespaces, Gitpod, a LAN address
56
+ * (RFC 1918, link-local, IPv6 ULA), a Tailscale address or name
57
+ * (100.64/10, `*.ts.net`), a LAN name with no dot such as `devbox`, a
58
+ * `*.local`, `*.test` or `*.internal` name such as `host.docker.internal`,
59
+ * or a tunnel (ngrok, `trycloudflare.com`, `loca.lt`, VS Code's
60
+ * `devtunnels.ms`). `"env"` is for localhost pages: those
61
+ * others never reach mainnet, but none is local. The root key
62
+ * comes from the `ic_env` cookie, but only where that cookie is trusted:
63
+ * when both the page and the replica are local, or the client was built
64
+ * with `allowEnvConfig: true`. On a canister's own `<id>.icp0.io` page the
65
+ * cookie's canister ids are believed by default, never its root key. A
66
+ * local replica with no key from the cookie has its root key fetched. A
67
+ * forwarding page is routed but is not local, so there the key is neither
68
+ * taken from the cookie nor fetched,
69
+ * and the agent checks the forwarded replica's certificates against
70
+ * mainnet's key, so every certified call fails verification. Name the
71
+ * replica with an object that has a `rootKey` (or `fetchRootKey: true`)
72
+ * and the canisters with `{ id }`: on a dev container or a localtunnel,
73
+ * `allowEnvConfig: true` is refused, because every workspace or tunnel is
74
+ * a sibling of every stranger's. On a
75
+ * mainnet host the cookie's root key is never taken, even with
76
+ * `allowEnvConfig: true`: the agent keeps mainnet's own. On a server there
77
+ * is no page and no cookie: the host is `ICP_HOST` or `IC_HOST` when
78
+ * `ICP_NETWORK` is `"local"` (`http://127.0.0.1:8000` if neither is set),
79
+ * and mainnet otherwise. With no `ICP_NETWORK`, dfx's `DFX_NETWORK=local`
80
+ * counts too, and its default is dfx's `http://127.0.0.1:4943`.
81
+ * - An object: any other replica. `rootKey` is used as given and never
82
+ * fetched. Without one the root key is fetched only when `host` is local
83
+ * (`localhost`, `*.localhost` or any loopback address), unless `fetchRootKey`
84
+ * says otherwise. A replica behind a Codespaces, Gitpod or custom domain is
85
+ * not local: pass its `rootKey`, or write `fetchRootKey: true` to trust the
86
+ * key it reports. `name` is the network's segment in query keys and defaults
87
+ * to `host`.
88
+ */
89
+ export type Network =
90
+ | "ic"
91
+ | "local"
92
+ | "env"
93
+ | {
94
+ /**
95
+ * The replica's URL, over `http:` or `https:`. A host with no scheme is
96
+ * read against the page's protocol, as `HttpAgent` reads it, and is
97
+ * refused where there is no page. `createClient` throws a `TypeError`
98
+ * for any other host, such as `localhost:4943`, which reads as the
99
+ * scheme `localhost:`.
100
+ */
101
+ readonly host: string
102
+ /**
103
+ * The root key certificates are verified against. Used as given and
104
+ * never fetched, even where `fetchRootKey` is `true`.
105
+ */
106
+ readonly rootKey?: Uint8Array
107
+ /** This network's segment in query keys. Defaults to `host`. */
108
+ readonly name?: string
109
+ /**
110
+ * Whether to fetch the root key from the replica when `rootKey` is
111
+ * absent. Defaults to whether `host` is local. Writing `true` for a host
112
+ * that is not local trusts whatever key that host reports, which is why it
113
+ * is never the default.
114
+ */
115
+ readonly fetchRootKey?: boolean
116
+ }
117
+
118
+ /** What the caller can decide about trusting the `ic_env` cookie. */
119
+ export interface NetworkOptions {
120
+ /**
121
+ * `true` trusts the cookie (root key and canister ids) wherever the code
122
+ * runs in a browser, `false` never reads it, and absent trusts it only when
123
+ * both the agent host and the page are a local replica, or (canister ids
124
+ * only) when the page is a canister's own `<id>.icp0.io` or
125
+ * `<id>.raw.icp0.io` page and the agent host is mainnet's. Set it to `true`
126
+ * only when every subdomain of the page's domain is trusted to write
127
+ * cookies. Even with `true`, the root key is never taken for a mainnet host
128
+ * and an `http:` Internet Identity URL only on a local page.
129
+ *
130
+ * @throws TypeError, when `true`, on a page under `ic0.app`, `github.dev`
131
+ * (Codespaces), `gitpod.io`, `loca.lt` (localtunnel) or `devtunnels.ms`
132
+ * (VS Code dev tunnels): none of them is a public suffix, so any other site
133
+ * under it can write the cookie this page reads.
134
+ */
135
+ readonly allowEnvConfig?: boolean
136
+ }
137
+
138
+ /** A {@link Network} with every decision made. */
139
+ export interface ResolvedNetwork {
140
+ /** The network's segment in query keys: `"ic"`, `"local"`, `name ?? host` for a custom network, the resolved host for `"env"`. */
141
+ readonly keySegment: string
142
+ /** The URL the agent connects to. */
143
+ readonly host: string
144
+ /** The root key to verify with. Absent means the agent's own: mainnet's, or the one it fetches when {@link fetchRootKey} is set. */
145
+ readonly rootKey?: Uint8Array
146
+ /** Whether the agent fetches the root key from `host`. Never `true` while {@link rootKey} is set. */
147
+ readonly fetchRootKey: boolean
148
+ /** Whether the `ic_env` cookie is believed. Always `false` outside a browser page. */
149
+ readonly trustsEnv: boolean
150
+ /**
151
+ * Present when the cookie is believed for canister ids only, as on a
152
+ * canister's own `icp0.io` page by default: its root key is never taken,
153
+ * nor its sign-in entries (`INTERNET_IDENTITY_PROVIDER` and
154
+ * `PUBLIC_CANISTER_ID:internet_identity` as the canister that mints
155
+ * delegations), so sign-in keeps `AuthClient`'s defaults.
156
+ */
157
+ readonly envIdsOnly?: true
158
+ }
159
+
160
+ /** The part of `HttpAgentOptions` a resolved network decides. */
161
+ export interface AgentNetworkOptions {
162
+ readonly host: string
163
+ readonly rootKey?: Uint8Array
164
+ readonly shouldFetchRootKey: boolean
165
+ }
166
+
167
+ /** A canister to call: by its id, or by the name the `ic_env` cookie gives it. */
168
+ export type CanisterIdTarget =
169
+ { readonly id: string } | { readonly name: string }
170
+
171
+ /** Why a `{ name }` target could not be resolved. */
172
+ export type CanisterIdFailure = "no_browser" | "untrusted_host" | "absent"
173
+
174
+ /** The result of {@link resolveCanisterId}. */
175
+ export type CanisterIdResolution =
176
+ | { readonly ok: true; readonly id: string }
177
+ | {
178
+ readonly ok: false
179
+ readonly reason: CanisterIdFailure
180
+ readonly message: string
181
+ }
182
+
183
+ /** A value for an error message, without throwing on a value `JSON.stringify` rejects. */
184
+ const describe = (value: unknown): string => {
185
+ try {
186
+ return JSON.stringify(value) ?? String(value)
187
+ } catch {
188
+ return String(value)
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Throws a `TypeError` for a key of `options` that `names` does not list, so a
194
+ * misspelt option fails instead of being ignored. Internal.
195
+ */
196
+ export const checkKeys = (
197
+ options: object,
198
+ names: readonly string[],
199
+ what: string
200
+ ): void => {
201
+ const unknown = Object.keys(options).filter((key) => !names.includes(key))
202
+ if (unknown.length > 0) {
203
+ throw new TypeError(
204
+ `[ic-reactor] ${what} has no option ${unknown.join(", ")}. Its options: ${names.join(", ")}.`
205
+ )
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Throws a `TypeError` unless `value` is `true`, `false` or absent: the text
211
+ * `"false"` an environment variable gives is truthy, and would trust what
212
+ * `false` refuses. Internal.
213
+ */
214
+ export const checkBoolean = (value: unknown, name: string): void => {
215
+ if (value !== undefined && typeof value !== "boolean") {
216
+ throw new TypeError(
217
+ `[ic-reactor] ${name} is true or false, got ${describe(value)}.`
218
+ )
219
+ }
220
+ }
221
+
222
+ /** The keys a network object may have. */
223
+ const NETWORK_KEYS = ["host", "rootKey", "name", "fetchRootKey"]
224
+
225
+ /** The length of a DER-encoded BLS root key. */
226
+ const ROOT_KEY_LENGTH = 133
227
+
228
+ const badTarget = (target: unknown): TypeError =>
229
+ new TypeError(
230
+ `[ic-reactor] a canister target is { id: string } or { name: string }, got ${describe(target)}.`
231
+ )
232
+
233
+ /** Validates principal text, and returns the reason it is not one. */
234
+ const principalProblem = (text: string): string | undefined => {
235
+ try {
236
+ // `fromText` also accepts the JSON form `{"__principal__":"..."}`, which is
237
+ // not an id: only the text it prints back is.
238
+ return Principal.fromText(text).toText() === text
239
+ ? undefined
240
+ : "it is not in canonical text form"
241
+ } catch (error) {
242
+ return error instanceof Error ? error.message : String(error)
243
+ }
244
+ }
245
+
246
+ const IC_HOST = "https://icp-api.io"
247
+ /** icp-cli's local network: its gateway's default port is 8000. */
248
+ const LOCAL_HOST = "http://127.0.0.1:8000"
249
+ /** dfx's local replica, the default only when `DFX_NETWORK` is the signal. */
250
+ const DFX_LOCAL_HOST = "http://127.0.0.1:4943"
251
+
252
+ /** The domains whose pages route agent traffic through their own origin. */
253
+ const MAINNET_DOMAINS = ["ic0.app", "icp0.io", "icp-api.io"]
254
+
255
+ /** Whether `hostname` is `domain` or one of its subdomains. */
256
+ const isUnder = (hostname: string, domain: string): boolean =>
257
+ hostname === domain || hostname.endsWith(`.${domain}`)
258
+
259
+ /**
260
+ * Whether `hostname` is mainnet's: a boundary domain or the API host `"ic"`
261
+ * and the fallback use. Mainnet has one root key, the one the agent ships
262
+ * with, so no cookie's key is ever taken for it.
263
+ */
264
+ const isMainnetHostname = (hostname: string | undefined): boolean =>
265
+ hostname !== undefined &&
266
+ MAINNET_DOMAINS.some((domain) => isUnder(hostname, domain))
267
+
268
+ /**
269
+ * Parents whose subdomains are strangers' sites and which are not on the
270
+ * Public Suffix List, so a page on any one of them can set a cookie for the
271
+ * whole parent, and every other page under it reads that cookie. `ic0.app`
272
+ * serves every canister's frontend, `github.dev` every codespace
273
+ * (`*.app.github.dev`), `gitpod.io` every Gitpod workspace, `loca.lt` every
274
+ * localtunnel and `devtunnels.ms` every VS Code dev tunnel. `icp0.io` and
275
+ * `*.raw.icp0.io` are public suffixes, so they are not here: a browser
276
+ * refuses a cookie a sibling canister sets for them. So are the other tunnel
277
+ * parents {@link REMOTE_DEV_SUFFIXES} names.
278
+ */
279
+ const SHARED_PARENTS = [
280
+ "ic0.app",
281
+ "github.dev",
282
+ "gitpod.io",
283
+ "loca.lt",
284
+ "devtunnels.ms",
285
+ ]
286
+
287
+ /**
288
+ * A canister's own page on `icp0.io`: `<id>.icp0.io` or `<id>.raw.icp0.io`,
289
+ * `<id>` being principal text. Both parents are on the Public Suffix List
290
+ * (`icp0.io` and `*.raw.icp0.io`), so no other site can set a cookie this
291
+ * page receives. `ic0.app` is not on it, nor is a custom domain known to be.
292
+ */
293
+ const ICP0_CANISTER_PAGE = /^([a-z0-9-]+)\.(?:raw\.)?icp0\.io$/
294
+
295
+ /**
296
+ * Names that forward a dev server and its replica to the browser from
297
+ * elsewhere: dev containers (Codespaces, Gitpod), the special-use and
298
+ * internal names a LAN, mDNS or Docker gives a dev machine (`*.local`,
299
+ * `*.test`, `*.internal`, which covers `host.docker.internal`), the names
300
+ * Tailscale gives the machines of a tailnet (`*.ts.net`), and the tunnels
301
+ * people open to show a dev app on a phone. Their pages route through
302
+ * their own origin, but they are never local: on a dev container every
303
+ * workspace is a sibling of every stranger's, and the rest are not this
304
+ * machine. A production app on such a name falls back to nothing it did not
305
+ * ask for: it reaches its own origin, never mainnet.
306
+ */
307
+ const REMOTE_DEV_SUFFIXES = [
308
+ ".github.dev",
309
+ ".gitpod.io",
310
+ ".local",
311
+ ".test",
312
+ ".internal",
313
+ ".ngrok-free.app",
314
+ ".ngrok-free.dev",
315
+ ".ngrok.app",
316
+ ".ngrok.io",
317
+ ".trycloudflare.com",
318
+ ".loca.lt",
319
+ ".devtunnels.ms",
320
+ ".ts.net",
321
+ ]
322
+
323
+ /**
324
+ * Private and link-local addresses, which a LAN or a VM gives a dev machine
325
+ * (`vite --host` prints one): 10/8, 172.16/12, 192.168/16 and 169.254/16,
326
+ * the shared 100.64/10 that Tailscale gives each machine of a tailnet, and
327
+ * IPv6's unique local fc00::/7 (Tailscale's IPv6 addresses among them) and
328
+ * link-local fe80::/10, with the brackets a URL's `hostname` keeps around
329
+ * them.
330
+ */
331
+ const PRIVATE_ADDRESS =
332
+ /^(?:10\.\d{1,3}|172\.(?:1[6-9]|2\d|3[01])|192\.168|169\.254|100\.(?:6[4-9]|[7-9]\d|1[01]\d|12[0-7]))\.\d{1,3}\.\d{1,3}$|^\[(?:f[cd][0-9a-f]{2}|fe[89ab][0-9a-f]):[0-9a-f:.]*\]$/i
333
+
334
+ /** An `http:` or `https:` origin: a page a web server serves. */
335
+ const WEB_ORIGIN = /^https?:\/\//i
336
+
337
+ /**
338
+ * Whether the page at `origin`, whose hostname is `hostname`, forwards a dev
339
+ * server from elsewhere: a {@link REMOTE_DEV_SUFFIXES} name, a
340
+ * {@link PRIVATE_ADDRESS}, or a web page whose name has no dot, which only a
341
+ * LAN, a hosts file or a VPN's DNS resolves (`http://devbox:5173`). An IPv6
342
+ * address has no dot either, so one in brackets is not such a name. Neither
343
+ * is the id a browser extension's or a desktop app's own scheme puts there
344
+ * (`chrome-extension://<id>`, `app://name`): no dev server is behind it.
345
+ */
346
+ const isRemoteDevPage = (origin: string, hostname: string): boolean =>
347
+ PRIVATE_ADDRESS.test(hostname) ||
348
+ REMOTE_DEV_SUFFIXES.some((suffix) => hostname.endsWith(suffix)) ||
349
+ (WEB_ORIGIN.test(origin) &&
350
+ !hostname.includes(".") &&
351
+ !hostname.startsWith("["))
352
+
353
+ /** 127.0.0.0/8: the entire IPv4 loopback range, not just 127.0.0.1. */
354
+ const IPV4_LOOPBACK = /^127\.(?:\d{1,3}\.){2}\d{1,3}$/
355
+
356
+ /**
357
+ * Whether `hostname` is a local replica: `localhost` and its subdomains, all
358
+ * of 127.0.0.0/8, and the IPv6 `::1` with or without the brackets a URL's
359
+ * `hostname` keeps around it.
360
+ *
361
+ * This is a positive allowlist, and deliberately not "anything that is not
362
+ * mainnet": a production dapp on a custom domain, a Codespaces host and a
363
+ * Gitpod host are all outside it. The names are matched whole or as a
364
+ * `.localhost` subdomain, so `notlocalhost` and `localhost.example.com` are
365
+ * not local.
366
+ */
367
+ const isLocalHostname = (hostname: string | undefined): boolean => {
368
+ if (!hostname) return false
369
+ return (
370
+ hostname === "localhost" ||
371
+ hostname.endsWith(".localhost") ||
372
+ IPV4_LOOPBACK.test(hostname) ||
373
+ hostname === "::1" ||
374
+ hostname === "[::1]"
375
+ )
376
+ }
377
+
378
+ /**
379
+ * The URL `HttpAgent` connects to for `host`, found the way the agent
380
+ * finds it (`determineHost` in `@icp-sdk/core`): on a page, a host that does
381
+ * not start with a scheme, such as `127.0.0.1:4943` or a bare Codespaces
382
+ * domain, is read against the page's protocol. The agent's scheme test is
383
+ * copied as is, so `localhost:4943`, which it reads as the scheme `localhost:`,
384
+ * has no hostname here either, and neither has a scheme-less host where there
385
+ * is no page. A host the agent cannot read is not local. Internal: also read
386
+ * by `createClient`'s host check, and not exported from the package entry.
387
+ */
388
+ export const agentUrlOf = (host: string): URL | undefined => {
389
+ try {
390
+ return !/^[a-z]+:/.test(host) && typeof window !== "undefined"
391
+ ? new URL(`${window.location.protocol}//${host}`)
392
+ : new URL(host)
393
+ } catch {
394
+ return undefined
395
+ }
396
+ }
397
+
398
+ /**
399
+ * A hostname without the one trailing dot a fully qualified name may end
400
+ * with. The URL parser keeps it, so `victim.ic0.app.` would otherwise not be
401
+ * under `ic0.app`, and every rule here that names a domain would miss it
402
+ * (all but {@link pageIsIcp0Canister}'s, which keeps it on purpose).
403
+ */
404
+ const withoutRootDot = (hostname: string): string =>
405
+ hostname.endsWith(".") ? hostname.slice(0, -1) : hostname
406
+
407
+ /** The hostname of {@link agentUrlOf}, without its trailing dot. */
408
+ const agentHostnameOf = (host: string): string | undefined => {
409
+ const hostname = agentUrlOf(host)?.hostname
410
+ return hostname === undefined ? undefined : withoutRootDot(hostname)
411
+ }
412
+
413
+ /**
414
+ * The hostname of a page origin as the URL parser reads it, trailing dot
415
+ * included, or `undefined` when it is not a URL (an opaque origin reads as
416
+ * `"null"`).
417
+ */
418
+ const parsedHostnameOf = (origin: string | undefined): string | undefined => {
419
+ if (!origin) return undefined
420
+ try {
421
+ return new URL(origin).hostname || undefined
422
+ } catch {
423
+ return undefined
424
+ }
425
+ }
426
+
427
+ /** The hostname of a page origin without its trailing dot (see {@link parsedHostnameOf}). */
428
+ const pageHostnameOf = (origin: string | undefined): string | undefined => {
429
+ const hostname = parsedHostnameOf(origin)
430
+ return hostname === undefined
431
+ ? undefined
432
+ : withoutRootDot(hostname) || undefined
433
+ }
434
+
435
+ /**
436
+ * The origin of the page this code runs for. A web worker has no `window`,
437
+ * but its global scope has a `location` (the worker script's URL), whose
438
+ * origin is that of the page that started it. Node has neither. Deno 2 has no
439
+ * `window`, and reading its `location` throws unless it was started with
440
+ * `--location`. React Native defines `window` with no `location` at all.
441
+ */
442
+ const pageOrigin = (): string | undefined => {
443
+ try {
444
+ const location =
445
+ typeof window !== "undefined"
446
+ ? window.location
447
+ : (globalThis as { location?: { origin?: string } }).location
448
+ return location?.origin
449
+ } catch {
450
+ return undefined
451
+ }
452
+ }
453
+
454
+ /** Whether the page this code runs in is a local replica's page. A worker has no cookie to protect, so it is never one. */
455
+ const pageIsLocal = (): boolean =>
456
+ typeof window !== "undefined" && isLocalHostname(pageHostnameOf(pageOrigin()))
457
+
458
+ /**
459
+ * The page's own origin when agent traffic can route through it: a local page
460
+ * (a dev server or a locally deployed asset canister proxies `/api`), a
461
+ * mainnet boundary domain, or a page that forwards a dev server from
462
+ * elsewhere ({@link isRemoteDevPage}). An ordinary web host (Vercel,
463
+ * Cloudflare, a custom domain) cannot, so it is left to the fallback; so is a
464
+ * page with no usable origin.
465
+ *
466
+ * A Codespaces page used to fall back to mainnet, and a dev app in a codespace
467
+ * sent its local canister ids to mainnet, where whatever canister had that id
468
+ * answered. So did a dev page opened from a phone by its LAN address, a
469
+ * Docker host name or a tunnel: a wallet whose ledger has the same id locally
470
+ * and on mainnet showed, and after a mainnet sign-in sent, real ICP.
471
+ */
472
+ const routableOrigin = (): string | undefined => {
473
+ const origin = pageOrigin()
474
+ const hostname = pageHostnameOf(origin)
475
+ if (origin === undefined || hostname === undefined) return undefined
476
+ const routable =
477
+ isLocalHostname(hostname) ||
478
+ isMainnetHostname(hostname) ||
479
+ isRemoteDevPage(origin, hostname)
480
+ return routable ? origin : undefined
481
+ }
482
+
483
+ /** `process.env`, or `undefined` where there is no `process`. */
484
+ const processEnv = (): Record<string, string | undefined> | undefined => {
485
+ try {
486
+ return typeof process !== "undefined" ? process.env : undefined
487
+ } catch {
488
+ return undefined
489
+ }
490
+ }
491
+
492
+ /**
493
+ * The host `"env"` falls back to when no page routes the agent. With
494
+ * `ICP_NETWORK` set to `"local"` that is `ICP_HOST` or `IC_HOST`, else
495
+ * icp-cli's local network, `"local"`'s `http://127.0.0.1:8000`. The older
496
+ * `DFX_NETWORK` counts only when `ICP_NETWORK` is not set (which overrides
497
+ * it): with `DFX_NETWORK=local` it is `ICP_HOST` or `IC_HOST`, else dfx's own
498
+ * replica, `http://127.0.0.1:4943`, because that variable says the project
499
+ * runs dfx. Any other value, or none, is mainnet. v3 fell back to
500
+ * `https://ic0.app` here; this is the same mainnet host `"ic"` uses.
501
+ */
502
+ const fallbackHost = (): string => {
503
+ const env = processEnv()
504
+ const fromIcp = env?.ICP_NETWORK !== undefined
505
+ const network = fromIcp ? env?.ICP_NETWORK : env?.DFX_NETWORK
506
+ if (network !== "local") return IC_HOST
507
+ return (
508
+ env?.ICP_HOST || env?.IC_HOST || (fromIcp ? LOCAL_HOST : DFX_LOCAL_HOST)
509
+ )
510
+ }
511
+
512
+ /**
513
+ * Whether the `ic_env` cookie is believed for an agent on `host`.
514
+ *
515
+ * Both sides must be a local replica, because the page decides who can write
516
+ * the cookie: a document on `app.example.com` pointed at a loopback replica
517
+ * shares its cookie jar with every sibling of `example.com`, and the agent host
518
+ * says nothing about that. `allowEnvConfig` overrides the pair either way,
519
+ * except that outside a browser page there is no cookie to believe at all.
520
+ */
521
+ const trustsEnvFor = (
522
+ host: string,
523
+ allowEnvConfig: boolean | undefined
524
+ ): boolean => {
525
+ if (isServer()) return false
526
+ return (
527
+ allowEnvConfig ?? (isLocalHostname(agentHostnameOf(host)) && pageIsLocal())
528
+ )
529
+ }
530
+
531
+ /**
532
+ * Whether the page is a canister's own {@link ICP0_CANISTER_PAGE}. A worker
533
+ * has no cookie, so it is never one. The name is matched as the URL parser
534
+ * reads it: `<id>.icp0.io.`, with the trailing dot, believes nothing by
535
+ * default, because the Public Suffix List's protection of a name written
536
+ * that way has not been checked.
537
+ */
538
+ const pageIsIcp0Canister = (): boolean => {
539
+ if (typeof window === "undefined") return false
540
+ const match = ICP0_CANISTER_PAGE.exec(parsedHostnameOf(pageOrigin()) ?? "")
541
+ return match !== null && principalProblem(match[1]!) === undefined
542
+ }
543
+
544
+ /**
545
+ * How far the `ic_env` cookie is believed for an agent on `host`: the
546
+ * {@link ResolvedNetwork} fields `trustsEnv` and `envIdsOnly`. With no
547
+ * `allowEnvConfig`, a canister's own `icp0.io` page talking to mainnet has
548
+ * its cookie believed for canister ids: icp-cli's asset canister serves it,
549
+ * and no sibling can write it.
550
+ */
551
+ const envTrustFor = (
552
+ host: string,
553
+ allowEnvConfig: boolean | undefined
554
+ ): Pick<ResolvedNetwork, "trustsEnv" | "envIdsOnly"> => {
555
+ if (trustsEnvFor(host, allowEnvConfig)) return { trustsEnv: true }
556
+ return allowEnvConfig === undefined &&
557
+ !isServer() &&
558
+ isMainnetHostname(agentHostnameOf(host)) &&
559
+ pageIsIcp0Canister()
560
+ ? { trustsEnv: true, envIdsOnly: true }
561
+ : { trustsEnv: false }
562
+ }
563
+
564
+ /**
565
+ * Refuses `allowEnvConfig` on a browser page under a {@link SHARED_PARENTS}
566
+ * domain, where it would believe a cookie any stranger's page can set.
567
+ */
568
+ const refuseSharedParent = (allowEnvConfig: boolean | undefined): void => {
569
+ if (!allowEnvConfig || isServer()) return
570
+ const origin = pageOrigin()
571
+ const hostname = pageHostnameOf(origin)
572
+ const parent =
573
+ hostname === undefined
574
+ ? undefined
575
+ : SHARED_PARENTS.find((domain) => isUnder(hostname, domain))
576
+ if (parent === undefined) return
577
+ throw new TypeError(
578
+ `[ic-reactor] allowEnvConfig: true is refused on ${origin}: ${parent} is not a public suffix, ` +
579
+ `so any other site under it can set the ic_env cookie this page reads, with canister ids of its choosing. ` +
580
+ `Name the canisters with { id } (bake the ids in at build time), and a replica that is not mainnet ` +
581
+ `with { host, rootKey }.`
582
+ )
583
+ }
584
+
585
+ /**
586
+ * Entry `key` of the `ic_env` cookie, as `@icp-sdk/core` reads it, or `null`
587
+ * when a page that is not local receives more than one `ic_env` cookie and
588
+ * they differ. A browser keeps one for each path or domain a cookie was set
589
+ * for, and `@icp-sdk/core` reads the first it lists, which need not be the
590
+ * one the frontend's canister set last, so differing copies are believed for
591
+ * nothing. A local page reads the first, as before: a redeploy there often
592
+ * leaves an older copy at another path, and only the machine itself can set
593
+ * one. Only ever called for a trusted page.
594
+ */
595
+ const cookieEntry = (key: string): unknown => {
596
+ try {
597
+ return !pageIsLocal() &&
598
+ new Set(
599
+ document.cookie
600
+ .split(";")
601
+ .map((cookie) => cookie.trim())
602
+ .filter((cookie) => cookie.startsWith("ic_env="))
603
+ ).size > 1
604
+ ? null
605
+ : safeGetCanisterEnv()?.[key]
606
+ } catch {
607
+ return undefined
608
+ }
609
+ }
610
+
611
+ /** The root key the cookie carries, or `undefined` when it carries none. */
612
+ const cookieRootKey = (): Uint8Array | undefined => {
613
+ const rootKey = cookieEntry("IC_ROOT_KEY")
614
+ return rootKey instanceof Uint8Array ? rootKey : undefined
615
+ }
616
+
617
+ /** Builds a {@link ResolvedNetwork}, leaving `rootKey` out rather than `undefined`. */
618
+ const resolved = (
619
+ parts: Omit<ResolvedNetwork, "rootKey"> & { rootKey?: Uint8Array }
620
+ ): ResolvedNetwork => {
621
+ const { rootKey, ...rest } = parts
622
+ return rootKey === undefined ? rest : { ...rest, rootKey }
623
+ }
624
+
625
+ /**
626
+ * Decides everything about a network that the client needs before it builds an
627
+ * agent: the host, the root key (given, taken from a trusted cookie, or to be
628
+ * fetched), the key segment, and whether the `ic_env` cookie is believed.
629
+ *
630
+ * Reads the page it runs in, so it is called once, when the client is built.
631
+ * The legacy v3 option `allowEnvRootKey` is not carried over: `allowEnvConfig`
632
+ * is the only opt-in, and it covers the whole cookie.
633
+ *
634
+ * @throws TypeError for a network that is not one of the allowed shapes (a
635
+ * network object with a key it does not have, a `fetchRootKey` that is not a
636
+ * boolean, or a `rootKey` that is not 133 bytes in a `Uint8Array`), an
637
+ * `allowEnvConfig` that is not a boolean, or `allowEnvConfig: true` on a page
638
+ * under a shared parent that is not a public suffix: a programmer error at
639
+ * build time.
640
+ */
641
+ export const resolveNetwork = (
642
+ network: Network,
643
+ options: NetworkOptions = {}
644
+ ): ResolvedNetwork => {
645
+ const { allowEnvConfig } = options
646
+ checkBoolean(allowEnvConfig, "allowEnvConfig")
647
+ refuseSharedParent(allowEnvConfig)
648
+
649
+ if (network === "ic") {
650
+ return resolved({
651
+ keySegment: "ic",
652
+ host: IC_HOST,
653
+ fetchRootKey: false,
654
+ ...envTrustFor(IC_HOST, allowEnvConfig),
655
+ })
656
+ }
657
+
658
+ if (network === "local") {
659
+ return resolved({
660
+ keySegment: "local",
661
+ host: LOCAL_HOST,
662
+ fetchRootKey: true,
663
+ ...envTrustFor(LOCAL_HOST, allowEnvConfig),
664
+ })
665
+ }
666
+
667
+ if (network === "env") {
668
+ const host = routableOrigin() ?? fallbackHost()
669
+ const trust = envTrustFor(host, allowEnvConfig)
670
+ // The key is the replica's, so it is taken only from a cookie that is as
671
+ // trustworthy as the replica, and never for mainnet, whose key the agent
672
+ // already holds (a cookie believed for ids only is always a mainnet
673
+ // host's). Without one, a local replica is asked.
674
+ const rootKey =
675
+ trust.trustsEnv && !isMainnetHostname(agentHostnameOf(host))
676
+ ? cookieRootKey()
677
+ : undefined
678
+ return resolved({
679
+ keySegment: host,
680
+ host,
681
+ rootKey,
682
+ fetchRootKey:
683
+ rootKey === undefined && isLocalHostname(agentHostnameOf(host)),
684
+ ...trust,
685
+ })
686
+ }
687
+
688
+ if (
689
+ typeof network !== "object" ||
690
+ network === null ||
691
+ typeof network.host !== "string"
692
+ ) {
693
+ throw new TypeError(
694
+ `[ic-reactor] unknown network ${describe(network)}: expected "ic", "local", "env", or { host: string, rootKey?, name?, fetchRootKey? }.`
695
+ )
696
+ }
697
+
698
+ checkKeys(network, NETWORK_KEYS, "a network object")
699
+ const { host, name, rootKey, fetchRootKey } = network
700
+ checkBoolean(fetchRootKey, "fetchRootKey")
701
+ if (
702
+ rootKey !== undefined &&
703
+ !(rootKey instanceof Uint8Array && rootKey.length === ROOT_KEY_LENGTH)
704
+ ) {
705
+ throw new TypeError(
706
+ `[ic-reactor] rootKey is a Uint8Array of ${ROOT_KEY_LENGTH} bytes (decode hex first), got ${
707
+ rootKey instanceof Uint8Array
708
+ ? `${rootKey.length} bytes`
709
+ : describe(rootKey)
710
+ }.`
711
+ )
712
+ }
713
+ return resolved({
714
+ keySegment: name ?? host,
715
+ host,
716
+ rootKey,
717
+ // A key the caller gave is the one to verify with, so nothing is fetched to
718
+ // replace it. Otherwise a replica is asked only when it is local, or when
719
+ // the caller wrote it out.
720
+ fetchRootKey:
721
+ rootKey === undefined &&
722
+ (fetchRootKey ?? isLocalHostname(agentHostnameOf(host))),
723
+ ...envTrustFor(host, allowEnvConfig),
724
+ })
725
+ }
726
+
727
+ /**
728
+ * The agent options a resolved network decides, so that every `HttpAgent` is
729
+ * built from one place. A given or cookie-supplied `rootKey` is passed and
730
+ * `shouldFetchRootKey` is `false`: the agent holds that key from the start and
731
+ * never requests `/api/v2/status`. With neither, the agent holds mainnet's, or
732
+ * (when `shouldFetchRootKey` is `true`) asks the replica on its first request.
733
+ */
734
+ export const agentOptionsFor = (net: ResolvedNetwork): AgentNetworkOptions => ({
735
+ host: net.host,
736
+ ...(net.rootKey === undefined ? {} : { rootKey: net.rootKey }),
737
+ shouldFetchRootKey: net.fetchRootKey,
738
+ })
739
+
740
+ /**
741
+ * The canister a target names.
742
+ *
743
+ * `{ id }` is validated now, and an id that is not principal text throws a
744
+ * `TypeError` that names it: a programmer error at build time, never something
745
+ * a deployed app hits at run time.
746
+ *
747
+ * `{ name }` is read from the `PUBLIC_CANISTER_ID:<name>` entry of the
748
+ * `ic_env` cookie, and only when the network trusts the cookie. It never
749
+ * throws and sends nothing: where the id cannot be had it says why, in one of
750
+ * three ways that need three different fixes, so a refused cookie is not
751
+ * reported as an absent one, and a server render is not blamed on the host
752
+ * for having no cookie jar:
753
+ *
754
+ * - `no_browser`: there is no page, so no cookie jar to read.
755
+ * - `untrusted_host`: the cookie is there to read but not trusted for this
756
+ * network, so it was not read; or a page that is not local holds more
757
+ * than one `ic_env` cookie and they differ, so none is believed.
758
+ * - `absent`: the cookie was read and has no usable entry under that name.
759
+ * An entry that is not principal text counts as absent.
760
+ */
761
+ export const resolveCanisterId = (
762
+ target: CanisterIdTarget,
763
+ net: ResolvedNetwork
764
+ ): CanisterIdResolution => {
765
+ if (typeof target !== "object" || target === null) throw badTarget(target)
766
+
767
+ if ("id" in target) {
768
+ const problem = principalProblem(target.id)
769
+ if (problem !== undefined) {
770
+ throw new TypeError(
771
+ `[ic-reactor] ${describe(target.id)} is not a valid canister id: ${problem}`
772
+ )
773
+ }
774
+ return { ok: true, id: target.id }
775
+ }
776
+
777
+ if (typeof target.name !== "string") throw badTarget(target)
778
+
779
+ const key = `PUBLIC_CANISTER_ID:${target.name}`
780
+ const what = `the canister id for { name: ${describe(target.name)} }`
781
+ const fail = (
782
+ reason: CanisterIdFailure,
783
+ message: string
784
+ ): CanisterIdResolution => ({
785
+ ok: false,
786
+ reason,
787
+ message: `[ic-reactor] cannot resolve ${what}: ${message}`,
788
+ })
789
+
790
+ if (isServer()) {
791
+ return fail(
792
+ "no_browser",
793
+ `there is no ic_env cookie to read outside a browser page (a server render, or a web worker). ` +
794
+ `Use { id } for a canister you call from there.`
795
+ )
796
+ }
797
+
798
+ // A cookie that is not trusted is not read; one that is, but disagrees with
799
+ // another `ic_env` cookie of the page, is refused the same way.
800
+ const value = net.trustsEnv ? cookieEntry(key) : null
801
+ if (value === null) {
802
+ const origin = pageOrigin()
803
+ return fail(
804
+ "untrusted_host",
805
+ net.trustsEnv
806
+ ? `the page's ic_env cookies differ. Use { id } (bake the id in at build time).`
807
+ : `the ic_env cookie is not trusted for this network (agent host ${net.host}` +
808
+ // The agent host is often the library's mainnet fallback rather
809
+ // than anywhere the reader recognises, so name the page too.
810
+ `${origin ? `, page ${origin}` : ""}), so it was not read. ` +
811
+ `It is trusted only when both the agent host and the page are a local replica ` +
812
+ `(localhost, *.localhost or a loopback address), or, for canister ids, on a canister's own ` +
813
+ `<id>.icp0.io page with a mainnet host, because elsewhere a sibling subdomain can write it. ` +
814
+ `Use { id } (bake the id in at build time) or, only if you trust every subdomain of this domain, ` +
815
+ `set allowEnvConfig: true, which trusts the cookie's canister ids, and its root key for a replica that is not mainnet.`
816
+ )
817
+ }
818
+ if (typeof value !== "string" || value === "") {
819
+ return fail(
820
+ "absent",
821
+ `the ic_env cookie has no "${key}" entry. Check the name against the canister's name in the project config, or use { id }.`
822
+ )
823
+ }
824
+ // The cookie is trusted, not validated: a value that is not a principal must
825
+ // not become a canister id.
826
+ if (principalProblem(value) !== undefined) {
827
+ return fail(
828
+ "absent",
829
+ `the "${key}" entry of the ic_env cookie is not principal text. Use { id }.`
830
+ )
831
+ }
832
+ return { ok: true, id: value }
833
+ }
834
+
835
+ // ---------------------------------------------------------------------------
836
+ // What the auth factory is told about the network
837
+ // ---------------------------------------------------------------------------
838
+
839
+ /**
840
+ * Internet Identity's canister: its id on mainnet, and the id icp-cli installs
841
+ * its built-in Internet Identity at on every local network it starts.
842
+ */
843
+ const INTERNET_IDENTITY = "rdmx6-jaaaa-aaaaa-aaadq-cai"
844
+
845
+ /** Where a sign-in ceremony runs and which canister mints its delegations: `@icp-sdk/auth` 10's `identityProvider`. */
846
+ export interface IdentityProvider {
847
+ readonly authorizeUrl: string
848
+ readonly canisterId: string
849
+ }
850
+
851
+ /**
852
+ * What the client hands its `auth` factory, under `@icp-sdk/auth` 10's own
853
+ * option names, so that `(network) => new AuthClient(network)` signs in on
854
+ * the client's network.
855
+ */
856
+ export interface AuthNetwork {
857
+ readonly agentOptions: AgentNetworkOptions
858
+ readonly identityProvider?: IdentityProvider
859
+ }
860
+
861
+ /** The result of {@link authNetworkFor}. */
862
+ export interface AuthNetworkResolution {
863
+ readonly network: AuthNetwork
864
+ /**
865
+ * Set when the network is not mainnet's and no identity provider could be
866
+ * named for it: why, as a clause for a warning. An auth built without one
867
+ * signs in with mainnet's Internet Identity, whose delegations a replica
868
+ * with another root key rejects.
869
+ */
870
+ readonly gap?: string
871
+ }
872
+
873
+ const hexOf = (bytes: Uint8Array): string =>
874
+ Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("")
875
+
876
+ /**
877
+ * Whether the agent verifies against mainnet's root key: it fetches none, and
878
+ * holds either none of its own (the agent's default is mainnet's) or one equal
879
+ * to mainnet's (a mainnet asset canister's cookie carries it).
880
+ */
881
+ const verifiesAsMainnet = (net: ResolvedNetwork): boolean =>
882
+ !net.fetchRootKey &&
883
+ (net.rootKey === undefined || hexOf(net.rootKey) === IC_ROOT_KEY)
884
+
885
+ /**
886
+ * The cookie's `INTERNET_IDENTITY_PROVIDER`, when it is an `https:` URL, or an
887
+ * `http:` one on a local page. Over plain `http:` from a page that is not
888
+ * local, anyone on the path could stand in for the sign-in page.
889
+ */
890
+ const cookieAuthorizeUrl = (): string | undefined => {
891
+ const value = cookieEntry("INTERNET_IDENTITY_PROVIDER")
892
+ if (typeof value !== "string" || value === "") return undefined
893
+ try {
894
+ const { protocol } = new URL(value)
895
+ return protocol === "https:" || (protocol === "http:" && pageIsLocal())
896
+ ? value
897
+ : undefined
898
+ } catch {
899
+ return undefined
900
+ }
901
+ }
902
+
903
+ /** The cookie's `PUBLIC_CANISTER_ID:internet_identity`, when it is principal text. */
904
+ const cookieInternetIdentity = (): string | undefined => {
905
+ const value = cookieEntry("PUBLIC_CANISTER_ID:internet_identity")
906
+ return typeof value === "string" &&
907
+ value !== "" &&
908
+ principalProblem(value) === undefined
909
+ ? value
910
+ : undefined
911
+ }
912
+
913
+ /**
914
+ * icp-cli's built-in Internet Identity for a gateway at `host`:
915
+ * `id.ai.localhost` on the gateway's scheme and port. The same rule as the
916
+ * Vite plugin's `localInternetIdentityProvider`, which puts this URL in the
917
+ * `ic_env` cookie.
918
+ */
919
+ const builtInAuthorizeUrl = (host: string): string | undefined => {
920
+ const url = agentUrlOf(host)
921
+ if (url === undefined) return undefined
922
+ return `${url.protocol}//id.ai.localhost${url.port ? `:${url.port}` : ""}/authorize`
923
+ }
924
+
925
+ /**
926
+ * What the client tells its `auth` factory: the agent options of its own
927
+ * agents, and the identity provider to sign in with, by these rules in order.
928
+ *
929
+ * 1. An `ic_env` cookie believed in full (never one believed for canister ids
930
+ * only, as on a canister's `icp0.io` page by default) that names
931
+ * `INTERNET_IDENTITY_PROVIDER` over `https:` (or `http:` on a local page):
932
+ * that URL, with the cookie's `PUBLIC_CANISTER_ID:internet_identity`, or
933
+ * Internet Identity's own id when it names none.
934
+ * 2. A cookie believed in full that names an `internet_identity` canister but
935
+ * no URL (the project deploys its own): none, and a gap unless the network
936
+ * is mainnet's. Its URL cannot be derived from its id.
937
+ * 3. `"local"`, or a network object whose host is local: icp-cli's built-in
938
+ * Internet Identity on that host's port.
939
+ * 4. `"env"` on a local page: none, and a gap. The agent's host is the
940
+ * page's (a dev server, or a gateway serving an asset canister), which
941
+ * does not say where icp-cli's built-in Internet Identity is.
942
+ * 5. Any other network that does not verify against mainnet's root key: none,
943
+ * and a gap.
944
+ * 6. Mainnet: none. `AuthClient`'s defaults are mainnet's.
945
+ *
946
+ * Reads the cookie, so it is called when the factory is, in a browser.
947
+ */
948
+ export const authNetworkFor = (
949
+ network: Network,
950
+ net: ResolvedNetwork
951
+ ): AuthNetworkResolution => {
952
+ const agentOptions = agentOptionsFor(net)
953
+ // Who signs a person in is not a canister id, so a cookie believed for ids
954
+ // only does not choose it.
955
+ const full = net.trustsEnv && !net.envIdsOnly
956
+ const authorizeUrl = full ? cookieAuthorizeUrl() : undefined
957
+ const projectCanister = full ? cookieInternetIdentity() : undefined
958
+
959
+ if (authorizeUrl !== undefined) {
960
+ return {
961
+ network: {
962
+ agentOptions,
963
+ identityProvider: {
964
+ authorizeUrl,
965
+ canisterId: projectCanister ?? INTERNET_IDENTITY,
966
+ },
967
+ },
968
+ }
969
+ }
970
+
971
+ const mainnet = verifiesAsMainnet(net)
972
+ if (projectCanister !== undefined) {
973
+ return mainnet
974
+ ? { network: { agentOptions } }
975
+ : {
976
+ network: { agentOptions },
977
+ gap:
978
+ `the ic_env cookie names an internet_identity canister (${projectCanister}) ` +
979
+ `but no INTERNET_IDENTITY_PROVIDER, and its sign-in URL cannot be derived from its id`,
980
+ }
981
+ }
982
+
983
+ const localHost =
984
+ network === "local" ||
985
+ (typeof network === "object" &&
986
+ isLocalHostname(agentHostnameOf(network.host)))
987
+ const builtIn = localHost ? builtInAuthorizeUrl(net.host) : undefined
988
+ if (builtIn !== undefined) {
989
+ return {
990
+ network: {
991
+ agentOptions,
992
+ identityProvider: {
993
+ authorizeUrl: builtIn,
994
+ canisterId: INTERNET_IDENTITY,
995
+ },
996
+ },
997
+ }
998
+ }
999
+
1000
+ if (network === "env" && pageIsLocal()) {
1001
+ const why = net.trustsEnv
1002
+ ? `whose ic_env cookie names no INTERNET_IDENTITY_PROVIDER`
1003
+ : `with allowEnvConfig: false, so no INTERNET_IDENTITY_PROVIDER is read from the ic_env cookie`
1004
+ return {
1005
+ network: { agentOptions },
1006
+ gap:
1007
+ `network "env" on a local page ${why}: ` +
1008
+ `the agent's host (${net.host}) does not say where icp-cli's built-in Internet Identity is`,
1009
+ }
1010
+ }
1011
+
1012
+ if (!mainnet) {
1013
+ return {
1014
+ network: { agentOptions },
1015
+ gap: `its root key is not mainnet's, and nothing names an identity provider for it`,
1016
+ }
1017
+ }
1018
+
1019
+ return { network: { agentOptions } }
1020
+ }