@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.
- package/.github/ISSUE_TEMPLATE/bug_report.yml +108 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +77 -0
- package/.github/actions/setup-rust-wasm/action.yml +25 -0
- package/.github/dependabot.yml +107 -0
- package/.github/workflows/auth-latest.yml +67 -0
- package/.github/workflows/b3pay-site.yml +49 -0
- package/.github/workflows/ci.yml +430 -0
- package/.github/workflows/codeql.yml +41 -0
- package/.github/workflows/dependency-review.yml +68 -0
- package/.github/workflows/docs-check.yml +98 -0
- package/.github/workflows/docs.yml +265 -0
- package/.github/workflows/e2e.yml +90 -0
- package/.github/workflows/examples-published.yml +97 -0
- package/.github/workflows/release.yml +326 -0
- package/.husky/pre-commit +12 -0
- package/.prettierignore +109 -0
- package/.prettierrc +6 -0
- package/AGENTS.md +103 -0
- package/CHANGELOG.md +3268 -0
- package/CLAUDE.md +93 -0
- package/CNAME +1 -0
- package/CODE_OF_CONDUCT.md +7 -0
- package/CONTRIBUTING.md +433 -0
- package/LICENSE +21 -0
- package/README.md +2 -2
- package/SECURITY.md +74 -0
- package/b3pay-module.json +194 -0
- package/docs/.remarkrc.json +10 -0
- package/docs/README.md +64 -0
- package/docs/astro.config.mjs +205 -0
- package/docs/favicon.svg +15 -0
- package/docs/package.json +39 -0
- package/docs/public/favicon.svg +15 -0
- package/docs/public/ic-reactor-social-card.png +0 -0
- package/docs/scripts/b3pay-static.mjs +22 -0
- package/docs/scripts/check-example-docs.mjs +214 -0
- package/docs/scripts/check-links.mjs +212 -0
- package/docs/scripts/fix-dist-links.js +125 -0
- package/docs/scripts/fix-frontmatter.js +71 -0
- package/docs/scripts/remove-redundant-h1.cjs +48 -0
- package/docs/scripts/rewrite-typedoc-links.js +110 -0
- package/docs/scripts/split-index.js +69 -0
- package/docs/src/assets/ic-reactor-hero-dark.svg +23 -0
- package/docs/src/assets/ic-reactor-hero-light.svg +23 -0
- package/docs/src/assets/ic-reactor-lockup-dark.svg +15 -0
- package/docs/src/assets/ic-reactor-lockup-light.svg +15 -0
- package/docs/src/assets/ic-reactor-mark-dark.svg +14 -0
- package/docs/src/assets/ic-reactor-mark-light.svg +14 -0
- package/docs/src/assets/layers/candid-core-layer-icon-dark.svg +4 -0
- package/docs/src/assets/layers/candid-core-layer-icon-light.svg +4 -0
- package/docs/src/assets/layers/candid-profile-layer-icon-dark.svg +4 -0
- package/docs/src/assets/layers/candid-profile-layer-icon-light.svg +4 -0
- package/docs/src/assets/layers/ic-reactor-layer-icon-dark.svg +4 -0
- package/docs/src/assets/layers/ic-reactor-layer-icon-light.svg +4 -0
- package/docs/src/components/LibraryCards.astro +172 -0
- package/docs/src/components/LibraryIcon.astro +28 -0
- package/docs/src/components/SiteTitle.astro +241 -0
- package/docs/src/content/docs/404.mdx +19 -0
- package/docs/src/content/docs/build/agent-tools.mdx +593 -0
- package/docs/src/content/docs/build/icrc1-wallet.mdx +619 -0
- package/docs/src/content/docs/build/ssr-per-user.mdx +552 -0
- package/docs/src/content/docs/examples/canister-studio.mdx +95 -0
- package/docs/src/content/docs/examples/icrc-ledger.mdx +45 -0
- package/docs/src/content/docs/examples/index.mdx +38 -0
- package/docs/src/content/docs/examples/next-ssr.mdx +73 -0
- package/docs/src/content/docs/examples/node-agent-tool.mdx +80 -0
- package/docs/src/content/docs/examples/vite-wallet.mdx +71 -0
- package/docs/src/content/docs/guides/auth.mdx +1181 -0
- package/docs/src/content/docs/guides/client.mdx +551 -0
- package/docs/src/content/docs/guides/deploy.mdx +180 -0
- package/docs/src/content/docs/guides/errors.mdx +475 -0
- package/docs/src/content/docs/guides/getting-started.mdx +620 -0
- package/docs/src/content/docs/guides/reads.mdx +586 -0
- package/docs/src/content/docs/guides/ssr.mdx +529 -0
- package/docs/src/content/docs/guides/testing.mdx +401 -0
- package/docs/src/content/docs/guides/values.mdx +261 -0
- package/docs/src/content/docs/guides/vite-plugin.mdx +690 -0
- package/docs/src/content/docs/guides/writes.mdx +572 -0
- package/docs/src/content/docs/ic-reactor/index.mdx +167 -0
- package/docs/src/content/docs/index.mdx +65 -0
- package/docs/src/content/docs/migrating-from-3.mdx +535 -0
- package/docs/src/content/docs/packages/core.mdx +186 -0
- package/docs/src/content/docs/packages/mcp.mdx +163 -0
- package/docs/src/content/docs/packages/react.mdx +207 -0
- package/docs/src/content/docs/packages/vite-plugin.mdx +73 -0
- package/docs/src/content/docs/versioning.mdx +104 -0
- package/docs/src/content.config.ts +7 -0
- package/docs/src/styles/custom.css +189 -0
- package/docs/tsconfig.typedoc.json +26 -0
- package/docs/typedoc-entry.ts +17 -0
- package/docs/typedoc.json +37 -0
- package/e2e/Cargo.lock +646 -0
- package/e2e/Cargo.toml +3 -0
- package/e2e/README.md +101 -0
- package/e2e/frontends/build.mjs +94 -0
- package/e2e/frontends/index.html +10 -0
- package/e2e/global-setup.ts +65 -0
- package/e2e/icp.yaml +38 -0
- package/e2e/package.json +40 -0
- package/e2e/setup.ts +6 -0
- package/e2e/src/actor/Cargo.toml +14 -0
- package/e2e/src/actor/hello_actor.did +10 -0
- package/e2e/src/actor/src/lib.rs +73 -0
- package/e2e/src/calls.test.ts +132 -0
- package/e2e/src/declarations/hello_actor.envelope.json +175 -0
- package/e2e/src/declarations/hello_actor.ts +15 -0
- package/e2e/src/errors.test.ts +107 -0
- package/e2e/src/frontend-headers.test.ts +253 -0
- package/e2e/src/identity.test.ts +61 -0
- package/e2e/src/react.test.tsx +59 -0
- package/e2e/src/replica.ts +70 -0
- package/e2e/src/vite-env.test.ts +108 -0
- package/e2e/test.sh +47 -0
- package/e2e/tsconfig.json +20 -0
- package/e2e/tsconfig.typecheck.json +9 -0
- package/e2e/vitest.config.ts +22 -0
- package/eslint.config.mjs +100 -0
- package/evals/PREREGISTRATION.md +1346 -0
- package/evals/README.md +756 -0
- package/evals/conditions/thin/condition.json +8 -0
- package/evals/conditions/thin/docs/candid-core-cli.README.md +90 -0
- package/evals/conditions/thin/docs/candid-core-schema.README.md +339 -0
- package/evals/conditions/thin/package.json +25 -0
- package/evals/conditions/thin/starter/src/generated/icrc1.ts +57 -0
- package/evals/conditions/thin-guide/condition.json +10 -0
- package/evals/conditions/thin-guide/docs/llms.txt +292 -0
- package/evals/conditions/v3/condition.json +9 -0
- package/evals/conditions/v3/docs/ic-reactor-core.llms.txt +232 -0
- package/evals/conditions/v3/docs/ic-reactor-react.llms.txt +280 -0
- package/evals/conditions/v3/docs/llms-full.txt +1053 -0
- package/evals/conditions/v3/package.json +26 -0
- package/evals/conditions/v3/starter/src/declarations/icrc1.did.d.ts +95 -0
- package/evals/conditions/v3/starter/src/declarations/icrc1.did.js +140 -0
- package/evals/conditions/v4/PORTING.md +384 -0
- package/evals/conditions/v4/README.md +106 -0
- package/evals/conditions/v4/condition.json +5 -0
- package/evals/conditions/v4/docs/llms.txt +323 -0
- package/evals/conditions/v4/package.json +27 -0
- package/evals/conditions/v4/starter/src/generated/icrc1.ts +78 -0
- package/evals/conditions/v4-proto/condition.json +6 -0
- package/evals/conditions/v4-proto/docs/llms.txt +291 -0
- package/evals/conditions/v4-proto/lib/SHIM-NOTES.md +20 -0
- package/evals/conditions/v4-proto/lib/package.json +27 -0
- package/evals/conditions/v4-proto/lib/src/client.ts +471 -0
- package/evals/conditions/v4-proto/lib/src/errors.ts +214 -0
- package/evals/conditions/v4-proto/lib/src/index.ts +36 -0
- package/evals/conditions/v4-proto/lib/src/principal.ts +175 -0
- package/evals/conditions/v4-proto/lib/src/service.ts +69 -0
- package/evals/conditions/v4-proto/lib/src/types.ts +174 -0
- package/evals/conditions/v4-proto/lib/test/runtime.test.ts +170 -0
- package/evals/conditions/v4-proto/lib/test/tsconfig.json +10 -0
- package/evals/conditions/v4-proto/lib/test/types.test-d.ts +145 -0
- package/evals/conditions/v4-proto/lib/test/vitest.config.mjs +8 -0
- package/evals/conditions/v4-proto/lib/tsconfig.json +17 -0
- package/evals/conditions/v4-proto/package.json +26 -0
- package/evals/conditions/v4-proto/starter/src/generated/icrc1.service.ts +19 -0
- package/evals/conditions/v4-proto/starter/src/generated/icrc1.ts +57 -0
- package/evals/drive.mjs +1221 -0
- package/evals/gate.mjs +161 -0
- package/evals/harness/aggregate.mjs +534 -0
- package/evals/harness/aggregate.test.mjs +344 -0
- package/evals/harness/assemble.mjs +216 -0
- package/evals/harness/assemble.test.mjs +143 -0
- package/evals/harness/auth.mjs +91 -0
- package/evals/harness/check-docs.mjs +157 -0
- package/evals/harness/declarations/icrc1.did.d.ts +95 -0
- package/evals/harness/declarations/icrc1.did.js +140 -0
- package/evals/harness/drive-auth.test.mjs +584 -0
- package/evals/harness/drive.test.mjs +509 -0
- package/evals/harness/fake-auth.ts +67 -0
- package/evals/harness/fake-ledger.ts +178 -0
- package/evals/harness/gate-plan.mjs +104 -0
- package/evals/harness/gate-plan.test.mjs +243 -0
- package/evals/harness/icrc1.did +88 -0
- package/evals/harness/judge.mjs +63 -0
- package/evals/harness/judge.test.mjs +81 -0
- package/evals/harness/leak-scan.mjs +1373 -0
- package/evals/harness/leak-scan.test.mjs +1300 -0
- package/evals/harness/probes/amounts.ts +14 -0
- package/evals/harness/probes/node-tool.probe.ts +48 -0
- package/evals/harness/probes/probe.mjs +149 -0
- package/evals/harness/probes/react-wallet.probe.ts +96 -0
- package/evals/harness/public/support/auth.ts +38 -0
- package/evals/harness/public/support/fake-replica.d.ts +28 -0
- package/evals/harness/public/support/fake-replica.js +434 -0
- package/evals/harness/public/support/ledger.idl.d.ts +95 -0
- package/evals/harness/public/support/ledger.idl.js +140 -0
- package/evals/harness/public/support/world.ts +179 -0
- package/evals/harness/runs.mjs +139 -0
- package/evals/harness/sandbox.mjs +88 -0
- package/evals/harness/sandbox.test.mjs +134 -0
- package/evals/harness/ship.mjs +264 -0
- package/evals/harness/ship.test.mjs +552 -0
- package/evals/harness/world.ts +291 -0
- package/evals/package.json +26 -0
- package/evals/pnpm-lock.yaml +1537 -0
- package/evals/pnpm-workspace.yaml +12 -0
- package/evals/results/2026-09-30T14-22-05-924Z/pilot.json +384 -0
- package/evals/results/2026-09-30T14-22-05-924Z/pilot.rescanned.json +404 -0
- package/evals/results/2026-09-30T14-22-05-924Z/pilot.rescanned.rescored.json +404 -0
- package/evals/results/2026-09-30T14-22-05-924Z/plan.json +240 -0
- package/evals/results/2026-09-30T14-22-05-924Z/summary.json +1800 -0
- package/evals/results/2026-09-30T14-22-05-924Z/summary.rescanned.json +1843 -0
- package/evals/results/2026-09-30T14-22-05-924Z/summary.rescanned.rescored.json +2100 -0
- package/evals/results/2026-09-30T15-48-23-343Z/pilot.json +404 -0
- package/evals/results/2026-09-30T15-48-23-343Z/pilot.rescored.json +404 -0
- package/evals/results/2026-09-30T15-48-23-343Z/plan.json +242 -0
- package/evals/results/2026-09-30T15-48-23-343Z/summary.json +1843 -0
- package/evals/results/2026-09-30T15-48-23-343Z/summary.rescored.json +2195 -0
- package/evals/results/2026-10-03-beta1-gate/pilot.json +162 -0
- package/evals/results/2026-10-03-beta1-gate/plan.json +141 -0
- package/evals/results/2026-10-03-beta1-gate/summary.json +983 -0
- package/evals/results/2026-10-05-ga-gate/contaminated-run.json +55 -0
- package/evals/results/2026-10-05-ga-gate/pilot.json +162 -0
- package/evals/results/2026-10-05-ga-gate/plan.json +457 -0
- package/evals/results/2026-10-05-ga-gate/summary.json +1037 -0
- package/evals/results/2026-10-05-ga-gate/summary.rescanned.json +1037 -0
- package/evals/results/README.md +31 -0
- package/evals/runs-pilot.log +150 -0
- package/evals/runs-pilot2.log +150 -0
- package/evals/score.mjs +256 -0
- package/evals/setup.mjs +547 -0
- package/evals/tasks/node-tool/faulty/thin-accepts-exponent/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/thin-accepts-exponent/src/index.ts +121 -0
- package/evals/tasks/node-tool/faulty/thin-anonymous-transfer/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/thin-anonymous-transfer/src/index.ts +116 -0
- package/evals/tasks/node-tool/faulty/thin-every-reject-may-have-executed/meta.json +9 -0
- package/evals/tasks/node-tool/faulty/thin-every-reject-may-have-executed/src/index.ts +118 -0
- package/evals/tasks/node-tool/faulty/thin-fetches-root-key-off-local/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/thin-fetches-root-key-off-local/src/index.ts +118 -0
- package/evals/tasks/node-tool/faulty/thin-ignores-root-key/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/thin-ignores-root-key/src/index.ts +117 -0
- package/evals/tasks/node-tool/faulty/thin-misclassifies-reject-codes/meta.json +9 -0
- package/evals/tasks/node-tool/faulty/thin-misclassifies-reject-codes/src/index.ts +119 -0
- package/evals/tasks/node-tool/faulty/thin-no-nat64-cap/meta.json +9 -0
- package/evals/tasks/node-tool/faulty/thin-no-nat64-cap/src/index.ts +118 -0
- package/evals/tasks/node-tool/faulty/thin-number-amount/meta.json +10 -0
- package/evals/tasks/node-tool/faulty/thin-number-amount/src/index.ts +117 -0
- package/evals/tasks/node-tool/faulty/thin-truncates-fraction-digits/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/thin-truncates-fraction-digits/src/index.ts +120 -0
- package/evals/tasks/node-tool/faulty/thin-unvalidated-recipient/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/thin-unvalidated-recipient/src/index.ts +118 -0
- package/evals/tasks/node-tool/faulty/v3-retry-call-errors/meta.json +11 -0
- package/evals/tasks/node-tool/faulty/v3-retry-call-errors/src/index.ts +149 -0
- package/evals/tasks/node-tool/faulty/v4-anonymous-identity-sent/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/v4-anonymous-identity-sent/src/index.ts +71 -0
- package/evals/tasks/node-tool/faulty/v4-never-may-have-executed/meta.json +9 -0
- package/evals/tasks/node-tool/faulty/v4-never-may-have-executed/src/index.ts +84 -0
- package/evals/tasks/node-tool/faulty/v4-proto-never-may-have-executed/meta.json +9 -0
- package/evals/tasks/node-tool/faulty/v4-proto-never-may-have-executed/src/index.ts +72 -0
- package/evals/tasks/node-tool/faulty/v4-proto-refuses-nat64-max/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/v4-proto-refuses-nat64-max/src/index.ts +72 -0
- package/evals/tasks/node-tool/faulty/v4-refuses-nat64-max/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/v4-refuses-nat64-max/src/index.ts +84 -0
- package/evals/tasks/node-tool/hidden/node-tool.test.ts +312 -0
- package/evals/tasks/node-tool/prompt.md +55 -0
- package/evals/tasks/node-tool/prompt.minimal.md +30 -0
- package/evals/tasks/node-tool/solutions/thin/reference/src/index.ts +118 -0
- package/evals/tasks/node-tool/solutions/thin/reference-module-scope/src/index.ts +145 -0
- package/evals/tasks/node-tool/solutions/thin-guide/reference/src/index.ts +118 -0
- package/evals/tasks/node-tool/solutions/thin-guide/reference-module-scope/src/index.ts +145 -0
- package/evals/tasks/node-tool/solutions/v3/reference/src/index.ts +140 -0
- package/evals/tasks/node-tool/solutions/v3/reference-module-scope/src/index.ts +153 -0
- package/evals/tasks/node-tool/solutions/v4/reference/src/index.ts +84 -0
- package/evals/tasks/node-tool/solutions/v4/reference-module-scope/src/index.ts +105 -0
- package/evals/tasks/node-tool/solutions/v4-proto/reference/src/index.ts +72 -0
- package/evals/tasks/node-tool/solutions/v4-proto/reference-module-scope/src/index.ts +87 -0
- package/evals/tasks/node-tool/starter/src/contract.ts +31 -0
- package/evals/tasks/node-tool/starter/src/index.ts +7 -0
- package/evals/tasks/node-tool/starter/test/smoke.test.ts +22 -0
- package/evals/tasks/node-tool/starter/tsconfig.json +17 -0
- package/evals/tasks/node-tool/task.json +63 -0
- package/evals/tasks/react-wallet/faulty/thin-accepts-exponent/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-accepts-exponent/src/Wallet.tsx +216 -0
- package/evals/tasks/react-wallet/faulty/thin-anonymous-transfer/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-anonymous-transfer/src/Wallet.tsx +212 -0
- package/evals/tasks/react-wallet/faulty/thin-both-auth-buttons/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-both-auth-buttons/src/Wallet.tsx +210 -0
- package/evals/tasks/react-wallet/faulty/thin-constant-balance-key/meta.json +8 -0
- package/evals/tasks/react-wallet/faulty/thin-constant-balance-key/src/Wallet.tsx +213 -0
- package/evals/tasks/react-wallet/faulty/thin-no-nat64-cap/meta.json +9 -0
- package/evals/tasks/react-wallet/faulty/thin-no-nat64-cap/src/Wallet.tsx +213 -0
- package/evals/tasks/react-wallet/faulty/thin-number-balance/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-number-balance/src/Wallet.tsx +213 -0
- package/evals/tasks/react-wallet/faulty/thin-transfer-as-query/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-transfer-as-query/src/Wallet.tsx +254 -0
- package/evals/tasks/react-wallet/faulty/thin-truncates-fraction-digits/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-truncates-fraction-digits/src/Wallet.tsx +215 -0
- package/evals/tasks/react-wallet/faulty/thin-unguarded-balance-effect/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-unguarded-balance-effect/src/Wallet.tsx +214 -0
- package/evals/tasks/react-wallet/faulty/v3-http-4xx-unknown/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v3-http-4xx-unknown/src/Wallet.tsx +224 -0
- package/evals/tasks/react-wallet/faulty/v3-mutation-retry-3/meta.json +12 -0
- package/evals/tasks/react-wallet/faulty/v3-mutation-retry-3/src/Wallet.tsx +225 -0
- package/evals/tasks/react-wallet/faulty/v3-unknown-as-error/meta.json +11 -0
- package/evals/tasks/react-wallet/faulty/v3-unknown-as-error/src/Wallet.tsx +182 -0
- package/evals/tasks/react-wallet/faulty/v4-every-reject-unknown/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v4-every-reject-unknown/src/Wallet.tsx +160 -0
- package/evals/tasks/react-wallet/faulty/v4-keep-previous-data/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v4-keep-previous-data/src/Wallet.tsx +166 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-every-reject-unknown/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-every-reject-unknown/src/Wallet.tsx +161 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-keep-previous-data/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-keep-previous-data/src/Wallet.tsx +163 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-retry-spread/meta.json +12 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-retry-spread/src/Wallet.tsx +162 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-status-not-idle/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-status-not-idle/src/Wallet.tsx +163 -0
- package/evals/tasks/react-wallet/faulty/v4-retry-spread/meta.json +12 -0
- package/evals/tasks/react-wallet/faulty/v4-retry-spread/src/Wallet.tsx +163 -0
- package/evals/tasks/react-wallet/faulty/v4-status-not-idle/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v4-status-not-idle/src/Wallet.tsx +162 -0
- package/evals/tasks/react-wallet/hidden/react-wallet.test.ts +536 -0
- package/evals/tasks/react-wallet/prompt.md +88 -0
- package/evals/tasks/react-wallet/prompt.minimal.md +51 -0
- package/evals/tasks/react-wallet/solutions/thin/reference/src/Wallet.tsx +213 -0
- package/evals/tasks/react-wallet/solutions/thin/reference-module-scope/src/Wallet.tsx +227 -0
- package/evals/tasks/react-wallet/solutions/thin-guide/reference/src/Wallet.tsx +213 -0
- package/evals/tasks/react-wallet/solutions/thin-guide/reference-module-scope/src/Wallet.tsx +227 -0
- package/evals/tasks/react-wallet/solutions/v3/reference/src/Wallet.tsx +224 -0
- package/evals/tasks/react-wallet/solutions/v3/reference-module-scope/src/Wallet.tsx +230 -0
- package/evals/tasks/react-wallet/solutions/v4/reference/src/Wallet.tsx +160 -0
- package/evals/tasks/react-wallet/solutions/v4/reference-module-scope/src/Wallet.tsx +178 -0
- package/evals/tasks/react-wallet/solutions/v4-proto/reference/src/Wallet.tsx +161 -0
- package/evals/tasks/react-wallet/solutions/v4-proto/reference-module-scope/src/Wallet.tsx +161 -0
- package/evals/tasks/react-wallet/starter/src/Wallet.tsx +12 -0
- package/evals/tasks/react-wallet/starter/src/auth.ts +16 -0
- package/evals/tasks/react-wallet/starter/src/config.ts +14 -0
- package/evals/tasks/react-wallet/starter/src/ii-auth.ts +43 -0
- package/evals/tasks/react-wallet/starter/src/main.tsx +15 -0
- package/evals/tasks/react-wallet/starter/test/smoke.test.ts +34 -0
- package/evals/tasks/react-wallet/starter/tsconfig.json +18 -0
- package/evals/tasks/react-wallet/task.json +84 -0
- package/examples/canister-studio/.stackblitzrc +4 -0
- package/examples/canister-studio/README.md +183 -0
- package/examples/canister-studio/did/ckbtc_minter.did +806 -0
- package/examples/canister-studio/did/icp_ledger.did +586 -0
- package/examples/canister-studio/did/icrc1.did +88 -0
- package/examples/canister-studio/package.json +45 -0
- package/examples/canister-studio/scripts/smoke.ts +188 -0
- package/examples/canister-studio/src/calls/CacheKeyPanel.tsx +104 -0
- package/examples/canister-studio/src/calls/ConfirmWrite.tsx +265 -0
- package/examples/canister-studio/src/calls/ErrorPanel.test.tsx +113 -0
- package/examples/canister-studio/src/calls/ErrorPanel.tsx +214 -0
- package/examples/canister-studio/src/calls/MethodRunner.test.tsx +354 -0
- package/examples/canister-studio/src/calls/MethodRunner.tsx +57 -0
- package/examples/canister-studio/src/calls/ReadRunner.tsx +244 -0
- package/examples/canister-studio/src/calls/ResendPanel.tsx +165 -0
- package/examples/canister-studio/src/calls/ShareLink.tsx +59 -0
- package/examples/canister-studio/src/calls/WriteRunner.test.tsx +678 -0
- package/examples/canister-studio/src/calls/WriteRunner.tsx +670 -0
- package/examples/canister-studio/src/calls/dedupe.ts +189 -0
- package/examples/canister-studio/src/calls/error-info.ts +168 -0
- package/examples/canister-studio/src/calls/history.test.ts +284 -0
- package/examples/canister-studio/src/calls/history.ts +287 -0
- package/examples/canister-studio/src/calls/kinds.ts +68 -0
- package/examples/canister-studio/src/calls/prepare.ts +32 -0
- package/examples/canister-studio/src/calls/query-options.ts +30 -0
- package/examples/canister-studio/src/calls/read.ts +47 -0
- package/examples/canister-studio/src/calls/readback.ts +100 -0
- package/examples/canister-studio/src/calls/record.ts +123 -0
- package/examples/canister-studio/src/calls/safe-calls.test.ts +299 -0
- package/examples/canister-studio/src/calls/share.ts +46 -0
- package/examples/canister-studio/src/calls/testing/doubles.tsx +108 -0
- package/examples/canister-studio/src/calls/testing/fixtures.ts +185 -0
- package/examples/canister-studio/src/calls/useCanisterHandle.ts +35 -0
- package/examples/canister-studio/src/canisters/ckbtc_minter.envelope.json +4228 -0
- package/examples/canister-studio/src/canisters/ckbtc_minter.ts +868 -0
- package/examples/canister-studio/src/canisters/icp_ledger.envelope.json +3454 -0
- package/examples/canister-studio/src/canisters/icp_ledger.ts +584 -0
- package/examples/canister-studio/src/canisters/icrc1.envelope.json +840 -0
- package/examples/canister-studio/src/canisters/icrc1.ts +78 -0
- package/examples/canister-studio/src/components/ActionButton.tsx +32 -0
- package/examples/canister-studio/src/components/AppHeader.tsx +83 -0
- package/examples/canister-studio/src/components/AppShell.tsx +29 -0
- package/examples/canister-studio/src/components/AuthButton.tsx +79 -0
- package/examples/canister-studio/src/components/Badge.tsx +79 -0
- package/examples/canister-studio/src/components/CanisterHeader.tsx +200 -0
- package/examples/canister-studio/src/components/CanisterJump.tsx +130 -0
- package/examples/canister-studio/src/components/Card.tsx +64 -0
- package/examples/canister-studio/src/components/Code.tsx +101 -0
- package/examples/canister-studio/src/components/CopyButton.tsx +126 -0
- package/examples/canister-studio/src/components/Disclosure.tsx +34 -0
- package/examples/canister-studio/src/components/EmptyState.tsx +34 -0
- package/examples/canister-studio/src/components/MethodList.test.tsx +137 -0
- package/examples/canister-studio/src/components/MethodList.tsx +244 -0
- package/examples/canister-studio/src/components/Notice.tsx +36 -0
- package/examples/canister-studio/src/components/ProvenanceBadge.tsx +44 -0
- package/examples/canister-studio/src/components/RouteError.tsx +42 -0
- package/examples/canister-studio/src/components/SectionBoundary.tsx +76 -0
- package/examples/canister-studio/src/components/Spinner.tsx +33 -0
- package/examples/canister-studio/src/components/Tabs.tsx +96 -0
- package/examples/canister-studio/src/components/canister/CanisterLoadFailure.test.tsx +56 -0
- package/examples/canister-studio/src/components/canister/CanisterLoadFailure.tsx +165 -0
- package/examples/canister-studio/src/components/canister/CanisterNotFound.tsx +59 -0
- package/examples/canister-studio/src/components/canister/CanisterPending.tsx +33 -0
- package/examples/canister-studio/src/components/canister/MethodOverview.tsx +93 -0
- package/examples/canister-studio/src/components/canister/MethodWorkspace.test.tsx +201 -0
- package/examples/canister-studio/src/components/canister/MethodWorkspace.tsx +187 -0
- package/examples/canister-studio/src/components/canister/shared-call.test.ts +186 -0
- package/examples/canister-studio/src/components/canister/shared-call.ts +133 -0
- package/examples/canister-studio/src/components/canister/shared-link-loader.test.ts +116 -0
- package/examples/canister-studio/src/components/canister/use-canister-page.ts +44 -0
- package/examples/canister-studio/src/components/canister/workspace-key.test.ts +27 -0
- package/examples/canister-studio/src/components/canister/workspace-key.ts +36 -0
- package/examples/canister-studio/src/components/canister-id-input.ts +69 -0
- package/examples/canister-studio/src/components/canister-names.ts +11 -0
- package/examples/canister-studio/src/components/download.ts +34 -0
- package/examples/canister-studio/src/components/fallbacks.tsx +33 -0
- package/examples/canister-studio/src/components/helpers.test.ts +107 -0
- package/examples/canister-studio/src/components/history/HistoryList.tsx +284 -0
- package/examples/canister-studio/src/components/home/FeaturedLedger.tsx +149 -0
- package/examples/canister-studio/src/components/home/OpenCanister.tsx +99 -0
- package/examples/canister-studio/src/components/home/featured.test.tsx +92 -0
- package/examples/canister-studio/src/components/home/featured.ts +64 -0
- package/examples/canister-studio/src/components/interface/CandidTab.tsx +38 -0
- package/examples/canister-studio/src/components/interface/CompatReport.tsx +92 -0
- package/examples/canister-studio/src/components/interface/CompatibilityTab.tsx +190 -0
- package/examples/canister-studio/src/components/interface/ProjectTab.tsx +196 -0
- package/examples/canister-studio/src/components/interface/TypeScriptTab.tsx +114 -0
- package/examples/canister-studio/src/components/interface/tools.test.tsx +169 -0
- package/examples/canister-studio/src/components/modes.ts +31 -0
- package/examples/canister-studio/src/components/playground/MethodPicker.tsx +67 -0
- package/examples/canister-studio/src/components/playground/PlaygroundForms.tsx +112 -0
- package/examples/canister-studio/src/components/playground/PlaygroundTools.tsx +219 -0
- package/examples/canister-studio/src/components/playground/sample.ts +43 -0
- package/examples/canister-studio/src/components/playground/target.test.tsx +86 -0
- package/examples/canister-studio/src/components/primitives.test.tsx +121 -0
- package/examples/canister-studio/src/components/provenance.ts +38 -0
- package/examples/canister-studio/src/components/route-render.test.tsx +71 -0
- package/examples/canister-studio/src/components/use-task.ts +56 -0
- package/examples/canister-studio/src/components/wallet/BalancePanel.tsx +110 -0
- package/examples/canister-studio/src/components/wallet/LedgerSummary.tsx +63 -0
- package/examples/canister-studio/src/components/wallet/MinterPanel.tsx +255 -0
- package/examples/canister-studio/src/components/wallet/SendPanel.test.tsx +297 -0
- package/examples/canister-studio/src/components/wallet/SendPanel.tsx +446 -0
- package/examples/canister-studio/src/components/wallet/ledgers.test.ts +36 -0
- package/examples/canister-studio/src/components/wallet/ledgers.ts +111 -0
- package/examples/canister-studio/src/forms/JsonPanel.tsx +157 -0
- package/examples/canister-studio/src/forms/MethodForm.test.tsx +369 -0
- package/examples/canister-studio/src/forms/MethodForm.tsx +368 -0
- package/examples/canister-studio/src/forms/TypedForm.tsx +55 -0
- package/examples/canister-studio/src/forms/context.ts +62 -0
- package/examples/canister-studio/src/forms/convert.ts +131 -0
- package/examples/canister-studio/src/forms/edge.test.ts +252 -0
- package/examples/canister-studio/src/forms/engine.test.ts +358 -0
- package/examples/canister-studio/src/forms/engine.ts +1492 -0
- package/examples/canister-studio/src/forms/fields/BytesField.tsx +210 -0
- package/examples/canister-studio/src/forms/fields/Field.tsx +106 -0
- package/examples/canister-studio/src/forms/fields/FieldShell.tsx +101 -0
- package/examples/canister-studio/src/forms/fields/Group.tsx +74 -0
- package/examples/canister-studio/src/forms/fields/ListField.tsx +256 -0
- package/examples/canister-studio/src/forms/fields/Segmented.tsx +78 -0
- package/examples/canister-studio/src/forms/fields/TimestampField.tsx +108 -0
- package/examples/canister-studio/src/forms/fields/UnitsField.tsx +119 -0
- package/examples/canister-studio/src/forms/fields/composites.tsx +389 -0
- package/examples/canister-studio/src/forms/fields/leaves.tsx +350 -0
- package/examples/canister-studio/src/forms/fields.test.tsx +396 -0
- package/examples/canister-studio/src/forms/helpers.test.ts +225 -0
- package/examples/canister-studio/src/forms/hints.ts +128 -0
- package/examples/canister-studio/src/forms/json.ts +119 -0
- package/examples/canister-studio/src/forms/parsing.test.ts +217 -0
- package/examples/canister-studio/src/forms/useMethodForm.ts +251 -0
- package/examples/canister-studio/src/interface/browser.test.ts +23 -0
- package/examples/canister-studio/src/interface/browser.ts +153 -0
- package/examples/canister-studio/src/interface/cache.ts +68 -0
- package/examples/canister-studio/src/interface/cli-cache.test.ts +155 -0
- package/examples/canister-studio/src/interface/cli-cache.ts +125 -0
- package/examples/canister-studio/src/interface/compile.server.test.ts +198 -0
- package/examples/canister-studio/src/interface/compile.server.ts +262 -0
- package/examples/canister-studio/src/interface/compile.test.ts +108 -0
- package/examples/canister-studio/src/interface/compile.ts +305 -0
- package/examples/canister-studio/src/interface/docs.test.ts +75 -0
- package/examples/canister-studio/src/interface/docs.ts +100 -0
- package/examples/canister-studio/src/interface/functions.test.ts +42 -0
- package/examples/canister-studio/src/interface/functions.ts +200 -0
- package/examples/canister-studio/src/interface/live-candid.server.ts +91 -0
- package/examples/canister-studio/src/interface/live-loader.test.ts +515 -0
- package/examples/canister-studio/src/interface/live-loader.ts +364 -0
- package/examples/canister-studio/src/interface/load.test.ts +328 -0
- package/examples/canister-studio/src/interface/load.ts +249 -0
- package/examples/canister-studio/src/interface/read-candid.test.ts +185 -0
- package/examples/canister-studio/src/interface/read-candid.ts +233 -0
- package/examples/canister-studio/src/interface/server-result.ts +42 -0
- package/examples/canister-studio/src/interface/typed.ts +68 -0
- package/examples/canister-studio/src/interface/types.ts +121 -0
- package/examples/canister-studio/src/lib/format.test.ts +107 -0
- package/examples/canister-studio/src/lib/format.ts +139 -0
- package/examples/canister-studio/src/lib/hex.test.ts +43 -0
- package/examples/canister-studio/src/lib/hex.ts +33 -0
- package/examples/canister-studio/src/lib/ids.test.ts +70 -0
- package/examples/canister-studio/src/lib/ids.ts +93 -0
- package/examples/canister-studio/src/lib/reactor.test.ts +55 -0
- package/examples/canister-studio/src/lib/reactor.ts +55 -0
- package/examples/canister-studio/src/lib/registry.test.ts +74 -0
- package/examples/canister-studio/src/lib/registry.ts +238 -0
- package/examples/canister-studio/src/lib/schema.ts +148 -0
- package/examples/canister-studio/src/routeTree.gen.ts +227 -0
- package/examples/canister-studio/src/router.test.ts +290 -0
- package/examples/canister-studio/src/router.tsx +127 -0
- package/examples/canister-studio/src/routes/__root.tsx +58 -0
- package/examples/canister-studio/src/routes/canister.$canisterId.index.tsx +172 -0
- package/examples/canister-studio/src/routes/canister.$canisterId.interface.tsx +98 -0
- package/examples/canister-studio/src/routes/canister.$canisterId.tsx +91 -0
- package/examples/canister-studio/src/routes/history.tsx +55 -0
- package/examples/canister-studio/src/routes/index.tsx +169 -0
- package/examples/canister-studio/src/routes/playground.tsx +286 -0
- package/examples/canister-studio/src/routes/safety.tsx +57 -0
- package/examples/canister-studio/src/routes/wallet.tsx +213 -0
- package/examples/canister-studio/src/safety/LabTransferForm.tsx +84 -0
- package/examples/canister-studio/src/safety/RequestLog.tsx +79 -0
- package/examples/canister-studio/src/safety/SafetyLab.test.tsx +89 -0
- package/examples/canister-studio/src/safety/SafetyLab.tsx +140 -0
- package/examples/canister-studio/src/safety/ScenarioCard.tsx +262 -0
- package/examples/canister-studio/src/safety/lab-run.ts +283 -0
- package/examples/canister-studio/src/safety/mock-ledger.test.ts +99 -0
- package/examples/canister-studio/src/safety/mock-ledger.ts +263 -0
- package/examples/canister-studio/src/safety/scenarios.test.ts +157 -0
- package/examples/canister-studio/src/safety/scenarios.ts +924 -0
- package/examples/canister-studio/src/styles.css +3453 -0
- package/examples/canister-studio/src/styles.test.ts +46 -0
- package/examples/canister-studio/src/values/CallPreview.test.tsx +86 -0
- package/examples/canister-studio/src/values/CallPreview.tsx +148 -0
- package/examples/canister-studio/src/values/ErrValueView.tsx +66 -0
- package/examples/canister-studio/src/values/Inspector.tsx +133 -0
- package/examples/canister-studio/src/values/ReplyView.test.tsx +341 -0
- package/examples/canister-studio/src/values/ReplyView.tsx +164 -0
- package/examples/canister-studio/src/values/candid-text.test.ts +516 -0
- package/examples/canister-studio/src/values/candid-text.ts +479 -0
- package/examples/canister-studio/src/values/hints.ts +58 -0
- package/examples/canister-studio/src/values/json.test.ts +66 -0
- package/examples/canister-studio/src/values/json.ts +31 -0
- package/examples/canister-studio/src/values/leaves.tsx +309 -0
- package/examples/canister-studio/src/values/schema.test.ts +123 -0
- package/examples/canister-studio/src/values/schema.ts +78 -0
- package/examples/canister-studio/src/values/test-router.tsx +21 -0
- package/examples/canister-studio/src/values/tree.tsx +670 -0
- package/examples/canister-studio/src/values/use-sha256.ts +29 -0
- package/examples/canister-studio/tsconfig.json +20 -0
- package/examples/canister-studio/vite.config.ts +50 -0
- package/examples/canister-studio/vitest.config.ts +20 -0
- package/examples/icrc-ledger/.stackblitzrc +4 -0
- package/examples/icrc-ledger/README.md +100 -0
- package/examples/icrc-ledger/ckbtc_minter.did +12 -0
- package/examples/icrc-ledger/icp_ledger.did +147 -0
- package/examples/icrc-ledger/icrc1.did +88 -0
- package/examples/icrc-ledger/index.html +13 -0
- package/examples/icrc-ledger/package.json +40 -0
- package/examples/icrc-ledger/scripts/smoke.ts +151 -0
- package/examples/icrc-ledger/src/App.tsx +71 -0
- package/examples/icrc-ledger/src/ErrorPanel.tsx +105 -0
- package/examples/icrc-ledger/src/MainnetTab.tsx +450 -0
- package/examples/icrc-ledger/src/SandboxTab.test.tsx +379 -0
- package/examples/icrc-ledger/src/SandboxTab.tsx +761 -0
- package/examples/icrc-ledger/src/blocks.test.ts +247 -0
- package/examples/icrc-ledger/src/blocks.ts +140 -0
- package/examples/icrc-ledger/src/canisters/ckbtc_minter.envelope.json +96 -0
- package/examples/icrc-ledger/src/canisters/ckbtc_minter.ts +16 -0
- package/examples/icrc-ledger/src/canisters/icp_ledger.envelope.json +690 -0
- package/examples/icrc-ledger/src/canisters/icp_ledger.ts +223 -0
- package/examples/icrc-ledger/src/canisters/icrc1.envelope.json +840 -0
- package/examples/icrc-ledger/src/canisters/icrc1.ts +78 -0
- package/examples/icrc-ledger/src/format.test.ts +41 -0
- package/examples/icrc-ledger/src/format.ts +68 -0
- package/examples/icrc-ledger/src/ledger.ts +15 -0
- package/examples/icrc-ledger/src/main.tsx +10 -0
- package/examples/icrc-ledger/src/minter.ts +16 -0
- package/examples/icrc-ledger/src/sandbox.test.ts +464 -0
- package/examples/icrc-ledger/src/sandbox.ts +281 -0
- package/examples/icrc-ledger/src/styles.css +391 -0
- package/examples/icrc-ledger/src/transfer-form.test.ts +62 -0
- package/examples/icrc-ledger/src/transfer-form.ts +97 -0
- package/examples/icrc-ledger/tsconfig.json +19 -0
- package/examples/icrc-ledger/vite.config.ts +44 -0
- package/examples/icrc-ledger/vitest.config.ts +12 -0
- package/examples/next-ssr/.stackblitzrc +4 -0
- package/examples/next-ssr/README.md +112 -0
- package/examples/next-ssr/icrc1.did +88 -0
- package/examples/next-ssr/next.config.ts +10 -0
- package/examples/next-ssr/package.json +41 -0
- package/examples/next-ssr/scripts/smoke.ts +169 -0
- package/examples/next-ssr/src/app/account/CertifiedBalances.tsx +58 -0
- package/examples/next-ssr/src/app/account/account.test.tsx +165 -0
- package/examples/next-ssr/src/app/account/page.tsx +82 -0
- package/examples/next-ssr/src/app/api/balance/[ledger]/[principal]/route.ts +10 -0
- package/examples/next-ssr/src/app/globals.css +278 -0
- package/examples/next-ssr/src/app/layout.tsx +34 -0
- package/examples/next-ssr/src/app/page.tsx +46 -0
- package/examples/next-ssr/src/app/providers.browser.test.tsx +127 -0
- package/examples/next-ssr/src/app/providers.test.tsx +73 -0
- package/examples/next-ssr/src/app/providers.tsx +60 -0
- package/examples/next-ssr/src/canisters/icrc1.envelope.json +840 -0
- package/examples/next-ssr/src/canisters/icrc1.ts +78 -0
- package/examples/next-ssr/src/components/BalanceTable.tsx +43 -0
- package/examples/next-ssr/src/components/LedgerCard.test.tsx +96 -0
- package/examples/next-ssr/src/components/LedgerCard.tsx +230 -0
- package/examples/next-ssr/src/components/LedgerError.tsx +32 -0
- package/examples/next-ssr/src/components/LedgerSections.tsx +22 -0
- package/examples/next-ssr/src/components/MyBalances.test.tsx +253 -0
- package/examples/next-ssr/src/components/MyBalances.tsx +129 -0
- package/examples/next-ssr/src/components/SessionBadge.tsx +18 -0
- package/examples/next-ssr/src/components/hydration.test.tsx +259 -0
- package/examples/next-ssr/src/components/server-data.ts +10 -0
- package/examples/next-ssr/src/format.ts +46 -0
- package/examples/next-ssr/src/ledgers.ts +38 -0
- package/examples/next-ssr/src/server/balance-route.test.ts +151 -0
- package/examples/next-ssr/src/server/balance-route.ts +157 -0
- package/examples/next-ssr/src/server/error-summary.test.ts +34 -0
- package/examples/next-ssr/src/server/error-summary.ts +37 -0
- package/examples/next-ssr/src/server/parse-owner.test.ts +39 -0
- package/examples/next-ssr/src/server/parse-owner.ts +34 -0
- package/examples/next-ssr/src/server/prefetch-ledgers.test.ts +137 -0
- package/examples/next-ssr/src/server/prefetch-ledgers.ts +70 -0
- package/examples/next-ssr/src/server/read-balances.test.ts +103 -0
- package/examples/next-ssr/src/server/read-balances.ts +78 -0
- package/examples/next-ssr/src/server/request-client.rsc.test.tsx +110 -0
- package/examples/next-ssr/src/server/request-client.ts +24 -0
- package/examples/next-ssr/src/testing/mock-ledgers.ts +115 -0
- package/examples/next-ssr/src/testing/react-server-dom-turbopack.d.ts +15 -0
- package/examples/next-ssr/src/testing/setup.ts +10 -0
- package/examples/next-ssr/tsconfig.json +31 -0
- package/examples/next-ssr/vitest.config.ts +59 -0
- package/examples/node-agent-tool/.stackblitzrc +4 -0
- package/examples/node-agent-tool/README.md +165 -0
- package/examples/node-agent-tool/icp.yaml +11 -0
- package/examples/node-agent-tool/icrc1.did +88 -0
- package/examples/node-agent-tool/package.json +32 -0
- package/examples/node-agent-tool/src/canisters/icrc1.envelope.json +840 -0
- package/examples/node-agent-tool/src/canisters/icrc1.ts +78 -0
- package/examples/node-agent-tool/src/cli.test.ts +64 -0
- package/examples/node-agent-tool/src/cli.ts +23 -0
- package/examples/node-agent-tool/src/command-line.ts +159 -0
- package/examples/node-agent-tool/src/commands/balance.ts +73 -0
- package/examples/node-agent-tool/src/commands/demo.test.ts +51 -0
- package/examples/node-agent-tool/src/commands/demo.ts +359 -0
- package/examples/node-agent-tool/src/commands/info.ts +69 -0
- package/examples/node-agent-tool/src/commands/reads.test.ts +133 -0
- package/examples/node-agent-tool/src/commands/resend.test.ts +363 -0
- package/examples/node-agent-tool/src/commands/transfer.test.ts +313 -0
- package/examples/node-agent-tool/src/commands/transfer.ts +415 -0
- package/examples/node-agent-tool/src/commands/watch.test.ts +159 -0
- package/examples/node-agent-tool/src/commands/watch.ts +135 -0
- package/examples/node-agent-tool/src/commands/whoami.ts +36 -0
- package/examples/node-agent-tool/src/context.ts +20 -0
- package/examples/node-agent-tool/src/dispatch.ts +70 -0
- package/examples/node-agent-tool/src/failure.test.ts +59 -0
- package/examples/node-agent-tool/src/failure.ts +176 -0
- package/examples/node-agent-tool/src/identity.test.ts +242 -0
- package/examples/node-agent-tool/src/identity.ts +228 -0
- package/examples/node-agent-tool/src/input.ts +110 -0
- package/examples/node-agent-tool/src/ledgers.test.ts +74 -0
- package/examples/node-agent-tool/src/ledgers.ts +62 -0
- package/examples/node-agent-tool/src/mock-ledger.ts +211 -0
- package/examples/node-agent-tool/src/network.test.ts +128 -0
- package/examples/node-agent-tool/src/network.ts +101 -0
- package/examples/node-agent-tool/src/output.test.ts +208 -0
- package/examples/node-agent-tool/src/output.ts +163 -0
- package/examples/node-agent-tool/src/run.ts +73 -0
- package/examples/node-agent-tool/src/test-kit.ts +167 -0
- package/examples/node-agent-tool/tsconfig.json +18 -0
- package/examples/node-agent-tool/vitest.config.ts +8 -0
- package/examples/vite-wallet/.stackblitzrc +4 -0
- package/examples/vite-wallet/Cargo.lock +646 -0
- package/examples/vite-wallet/Cargo.toml +5 -0
- package/examples/vite-wallet/README.md +107 -0
- package/examples/vite-wallet/backend/Cargo.toml +12 -0
- package/examples/vite-wallet/backend/backend.did +37 -0
- package/examples/vite-wallet/backend/src/lib.rs +133 -0
- package/examples/vite-wallet/icp.yaml +44 -0
- package/examples/vite-wallet/index.html +13 -0
- package/examples/vite-wallet/ledger.did +54 -0
- package/examples/vite-wallet/package.json +46 -0
- package/examples/vite-wallet/public/.ic-assets.json5 +26 -0
- package/examples/vite-wallet/scripts/faucet-args.test.ts +30 -0
- package/examples/vite-wallet/scripts/faucet-args.ts +41 -0
- package/examples/vite-wallet/scripts/faucet.ts +41 -0
- package/examples/vite-wallet/src/AddressBook.test.tsx +191 -0
- package/examples/vite-wallet/src/AddressBook.tsx +147 -0
- package/examples/vite-wallet/src/App.tsx +53 -0
- package/examples/vite-wallet/src/Balance.test.tsx +57 -0
- package/examples/vite-wallet/src/Balance.tsx +58 -0
- package/examples/vite-wallet/src/EnvironmentPanel.test.tsx +83 -0
- package/examples/vite-wallet/src/EnvironmentPanel.tsx +103 -0
- package/examples/vite-wallet/src/ErrorNote.tsx +70 -0
- package/examples/vite-wallet/src/Profile.test.tsx +145 -0
- package/examples/vite-wallet/src/Profile.tsx +92 -0
- package/examples/vite-wallet/src/SendIcp.test.tsx +231 -0
- package/examples/vite-wallet/src/SendIcp.tsx +244 -0
- package/examples/vite-wallet/src/SendToContact.test.tsx +113 -0
- package/examples/vite-wallet/src/SendToContact.tsx +102 -0
- package/examples/vite-wallet/src/SignIn.test.tsx +106 -0
- package/examples/vite-wallet/src/SignIn.tsx +120 -0
- package/examples/vite-wallet/src/Wallet.test.tsx +89 -0
- package/examples/vite-wallet/src/account-switch.test.tsx +108 -0
- package/examples/vite-wallet/src/auth/dev-accounts.test.ts +113 -0
- package/examples/vite-wallet/src/auth/dev-accounts.ts +216 -0
- package/examples/vite-wallet/src/auth/local-page.test.ts +28 -0
- package/examples/vite-wallet/src/auth/local-page.ts +20 -0
- package/examples/vite-wallet/src/auth/wallet-auth.test.ts +159 -0
- package/examples/vite-wallet/src/auth/wallet-auth.ts +131 -0
- package/examples/vite-wallet/src/canisters/backend.envelope.json +275 -0
- package/examples/vite-wallet/src/canisters/backend.ts +58 -0
- package/examples/vite-wallet/src/canisters/ledger.envelope.json +451 -0
- package/examples/vite-wallet/src/canisters/ledger.ts +56 -0
- package/examples/vite-wallet/src/client.ts +45 -0
- package/examples/vite-wallet/src/main.tsx +18 -0
- package/examples/vite-wallet/src/optimistic-contacts.ts +113 -0
- package/examples/vite-wallet/src/refusal.ts +17 -0
- package/examples/vite-wallet/src/styles.css +282 -0
- package/examples/vite-wallet/src/test/test-wallet.tsx +322 -0
- package/examples/vite-wallet/src/token.ts +50 -0
- package/examples/vite-wallet/src/transfer.test.ts +178 -0
- package/examples/vite-wallet/src/transfer.ts +110 -0
- package/examples/vite-wallet/src/use-canisters.ts +49 -0
- package/examples/vite-wallet/tsconfig.json +19 -0
- package/examples/vite-wallet/vite.config.ts +47 -0
- package/examples/vite-wallet/vitest.config.ts +17 -0
- package/package.json +9 -4
- package/packages/core/.size-limit.js +47 -0
- package/packages/core/LICENSE +21 -0
- package/packages/core/README.md +84 -0
- package/packages/core/llms.txt +610 -0
- package/packages/core/package.json +89 -0
- package/packages/core/src/call.ts +961 -0
- package/packages/core/src/canister.ts +259 -0
- package/packages/core/src/client.ts +2061 -0
- package/packages/core/src/errors.ts +1079 -0
- package/packages/core/src/hydration.ts +239 -0
- package/packages/core/src/index.ts +23 -0
- package/packages/core/src/keys.ts +108 -0
- package/packages/core/src/management.ts +138 -0
- package/packages/core/src/network.ts +1020 -0
- package/packages/core/src/options.ts +1000 -0
- package/packages/core/src/runtime.ts +50 -0
- package/packages/core/src/testing/fake-replica.ts +1166 -0
- package/packages/core/src/testing/index.ts +16 -0
- package/packages/core/src/testing/test-auth.ts +340 -0
- package/packages/core/src/testing/test-client.ts +559 -0
- package/packages/core/src/types.ts +541 -0
- package/packages/core/src/units.ts +299 -0
- package/packages/core/src/version.ts +4 -0
- package/packages/core/tests/canister-helpers.ts +187 -0
- package/packages/core/tests/canister-id.test.ts +158 -0
- package/packages/core/tests/canister-unwrap.test.ts +94 -0
- package/packages/core/tests/canister.test-d.ts +406 -0
- package/packages/core/tests/canister.test.ts +1921 -0
- package/packages/core/tests/client-account-change.test.ts +131 -0
- package/packages/core/tests/client-agents.test.ts +402 -0
- package/packages/core/tests/client-auth-network.test.ts +719 -0
- package/packages/core/tests/client-disposed.test.ts +403 -0
- package/packages/core/tests/client-helpers.ts +136 -0
- package/packages/core/tests/client-hydration.test.ts +166 -0
- package/packages/core/tests/client-pinned.test.ts +626 -0
- package/packages/core/tests/client-session.test.ts +348 -0
- package/packages/core/tests/client.test-d.ts +181 -0
- package/packages/core/tests/client.test.ts +1162 -0
- package/packages/core/tests/encode.test.ts +171 -0
- package/packages/core/tests/env-canister-id.test.ts +666 -0
- package/packages/core/tests/env-cookie-copies.test.ts +182 -0
- package/packages/core/tests/error-guard.test.ts +222 -0
- package/packages/core/tests/errors.test-d.ts +280 -0
- package/packages/core/tests/errors.test.ts +1359 -0
- package/packages/core/tests/fixtures/README.md +28 -0
- package/packages/core/tests/fixtures/accounts.did +21 -0
- package/packages/core/tests/fixtures/accounts.envelope.json +367 -0
- package/packages/core/tests/fixtures/accounts.ts +26 -0
- package/packages/core/tests/fixtures/archive.did +31 -0
- package/packages/core/tests/fixtures/archive.envelope.json +259 -0
- package/packages/core/tests/fixtures/archive.ts +55 -0
- package/packages/core/tests/fixtures/icrc1.did +88 -0
- package/packages/core/tests/fixtures/icrc1.envelope.json +840 -0
- package/packages/core/tests/fixtures/icrc1.ts +78 -0
- package/packages/core/tests/fixtures/management.did +724 -0
- package/packages/core/tests/fixtures/management.envelope.json +4455 -0
- package/packages/core/tests/fixtures/management.ts +486 -0
- package/packages/core/tests/fixtures/shapes.did +33 -0
- package/packages/core/tests/fixtures/shapes.envelope.json +440 -0
- package/packages/core/tests/fixtures/shapes.ts +56 -0
- package/packages/core/tests/fixtures/skippable.did +15 -0
- package/packages/core/tests/fixtures/skippable.envelope.json +182 -0
- package/packages/core/tests/fixtures/skippable.ts +33 -0
- package/packages/core/tests/func.test.ts +154 -0
- package/packages/core/tests/identity-attributes.test.ts +214 -0
- package/packages/core/tests/keys.test.ts +289 -0
- package/packages/core/tests/management.test.ts +206 -0
- package/packages/core/tests/network-helpers.ts +121 -0
- package/packages/core/tests/network.test-d.ts +78 -0
- package/packages/core/tests/network.test.ts +1051 -0
- package/packages/core/tests/options.test.ts +1594 -0
- package/packages/core/tests/redirect-sign-in.test.ts +393 -0
- package/packages/core/tests/resend.test-d.ts +81 -0
- package/packages/core/tests/resend.test.ts +723 -0
- package/packages/core/tests/skip.test-d.ts +125 -0
- package/packages/core/tests/testing-entry.test.ts +73 -0
- package/packages/core/tests/testing-fake-replica.test.ts +1242 -0
- package/packages/core/tests/testing-test-auth.test-d.ts +84 -0
- package/packages/core/tests/testing-test-auth.test.ts +483 -0
- package/packages/core/tests/testing-test-client.test-d.ts +184 -0
- package/packages/core/tests/testing-test-client.test.ts +1272 -0
- package/packages/core/tests/time-realm.test.ts +63 -0
- package/packages/core/tests/time.test.ts +238 -0
- package/packages/core/tests/traps/README.md +39 -0
- package/packages/core/tests/traps/anonymous-write.test.ts +145 -0
- package/packages/core/tests/traps/classification-table.test.ts +256 -0
- package/packages/core/tests/traps/err-arm.test.ts +144 -0
- package/packages/core/tests/traps/fetch-spy.ts +39 -0
- package/packages/core/tests/traps/invalidation-after-write.test.ts +178 -0
- package/packages/core/tests/traps/ledger.ts +248 -0
- package/packages/core/tests/traps/root-key-off-local.test.ts +130 -0
- package/packages/core/tests/traps/stale-data-across-users.test.ts +173 -0
- package/packages/core/tests/traps/unresolved-name.test.ts +155 -0
- package/packages/core/tests/traps/update-as-query.test.ts +244 -0
- package/packages/core/tests/traps/update-not-resent.test.ts +126 -0
- package/packages/core/tests/traps/update-resent-when-never-delivered.test.ts +159 -0
- package/packages/core/tests/traps.test-d.ts +476 -0
- package/packages/core/tests/units.test-d.ts +118 -0
- package/packages/core/tests/units.test.ts +634 -0
- package/packages/core/tsconfig.json +19 -0
- package/packages/core/tsconfig.typecheck.json +16 -0
- package/packages/core/vitest.config.ts +13 -0
- package/packages/mcp/LICENSE +21 -0
- package/packages/mcp/README.md +189 -0
- package/packages/mcp/package.json +62 -0
- package/packages/mcp/src/candid/candid-text.test.ts +455 -0
- package/packages/mcp/src/candid/candid-text.ts +501 -0
- package/packages/mcp/src/candid/contract.test.ts +398 -0
- package/packages/mcp/src/candid/formats.ts +155 -0
- package/packages/mcp/src/candid/hex.ts +29 -0
- package/packages/mcp/src/candid/json-schema.test.ts +758 -0
- package/packages/mcp/src/candid/json-schema.ts +454 -0
- package/packages/mcp/src/candid/json.test.ts +1207 -0
- package/packages/mcp/src/candid/json.ts +1053 -0
- package/packages/mcp/src/candid/schema-walk.ts +189 -0
- package/packages/mcp/src/candid/type-text.test.ts +179 -0
- package/packages/mcp/src/candid/type-text.ts +238 -0
- package/packages/mcp/src/cli.ts +134 -0
- package/packages/mcp/src/identity.ts +188 -0
- package/packages/mcp/src/interface/cache.test.ts +48 -0
- package/packages/mcp/src/interface/cache.ts +68 -0
- package/packages/mcp/src/interface/cli-cache.test.ts +150 -0
- package/packages/mcp/src/interface/cli-cache.ts +122 -0
- package/packages/mcp/src/interface/compile-worker.test.ts +246 -0
- package/packages/mcp/src/interface/compile-worker.ts +290 -0
- package/packages/mcp/src/interface/compile.test.ts +155 -0
- package/packages/mcp/src/interface/compile.ts +281 -0
- package/packages/mcp/src/interface/docs.test.ts +105 -0
- package/packages/mcp/src/interface/docs.ts +86 -0
- package/packages/mcp/src/interface/fixtures/icrc1.did +88 -0
- package/packages/mcp/src/interface/hex.ts +8 -0
- package/packages/mcp/src/interface/ids.test.ts +71 -0
- package/packages/mcp/src/interface/ids.ts +87 -0
- package/packages/mcp/src/interface/loader.test.ts +804 -0
- package/packages/mcp/src/interface/loader.ts +519 -0
- package/packages/mcp/src/interface/read-candid.test.ts +300 -0
- package/packages/mcp/src/interface/read-candid.ts +259 -0
- package/packages/mcp/src/interface/types.ts +113 -0
- package/packages/mcp/src/network.ts +122 -0
- package/packages/mcp/src/options.ts +149 -0
- package/packages/mcp/src/server/approval.ts +159 -0
- package/packages/mcp/src/server/naming.ts +43 -0
- package/packages/mcp/src/server/results.ts +102 -0
- package/packages/mcp/src/server/server.ts +797 -0
- package/packages/mcp/src/server/tools.ts +116 -0
- package/packages/mcp/src/usage.ts +40 -0
- package/packages/mcp/tests/approval.test.ts +60 -0
- package/packages/mcp/tests/identity.test.ts +234 -0
- package/packages/mcp/tests/naming.test.ts +62 -0
- package/packages/mcp/tests/options.test.ts +140 -0
- package/packages/mcp/tests/server.test.ts +997 -0
- package/packages/mcp/tsconfig.json +19 -0
- package/packages/mcp/tsconfig.typecheck.json +10 -0
- package/packages/mcp/vitest.config.ts +10 -0
- package/packages/react/LICENSE +21 -0
- package/packages/react/README.md +328 -0
- package/packages/react/llms.txt +95 -0
- package/packages/react/package.json +95 -0
- package/packages/react/src/index.tsx +678 -0
- package/packages/react/tests/abandoned-render.test.tsx +816 -0
- package/packages/react/tests/auth.test.tsx +315 -0
- package/packages/react/tests/caller-keys.test.tsx +2334 -0
- package/packages/react/tests/client-time.test.ts +40 -0
- package/packages/react/tests/entry.test.ts +52 -0
- package/packages/react/tests/helpers.tsx +291 -0
- package/packages/react/tests/hydration.test.tsx +262 -0
- package/packages/react/tests/ownership.test.tsx +260 -0
- package/packages/react/tests/provider.server.test.tsx +169 -0
- package/packages/react/tests/query-client.test.tsx +107 -0
- package/packages/react/tests/strict-mode.test.tsx +288 -0
- package/packages/react/tests/suspense.test-d.tsx +357 -0
- package/packages/react/tests/two-query-cores.test.tsx +135 -0
- package/packages/react/tests/types.test-d.tsx +63 -0
- package/packages/react/tsconfig.json +23 -0
- package/packages/react/tsconfig.test.json +8 -0
- package/packages/react/tsconfig.typecheck.json +16 -0
- package/packages/react/vitest.config.ts +39 -0
- package/packages/vite-plugin/LICENSE +21 -0
- package/packages/vite-plugin/README.md +532 -0
- package/packages/vite-plugin/package.json +76 -0
- package/packages/vite-plugin/src/describe-value.test.ts +43 -0
- package/packages/vite-plugin/src/describe-value.ts +167 -0
- package/packages/vite-plugin/src/dev-environment.test.ts +747 -0
- package/packages/vite-plugin/src/dev-environment.ts +510 -0
- package/packages/vite-plugin/src/env.ts +431 -0
- package/packages/vite-plugin/src/fetch.ts +348 -0
- package/packages/vite-plugin/src/file-identity.ts +106 -0
- package/packages/vite-plugin/src/generate.ts +691 -0
- package/packages/vite-plugin/src/index.test.ts +1243 -0
- package/packages/vite-plugin/src/index.ts +2565 -0
- package/packages/vite-plugin/src/interface.ts +339 -0
- package/packages/vite-plugin/src/local-host.ts +34 -0
- package/packages/vite-plugin/src/options.ts +641 -0
- package/packages/vite-plugin/src/principal-text.test.ts +87 -0
- package/packages/vite-plugin/src/principal-text.ts +98 -0
- package/packages/vite-plugin/tests/close.test.ts +141 -0
- package/packages/vite-plugin/tests/environment-mode.test.ts +136 -0
- package/packages/vite-plugin/tests/fake-ic.ts +214 -0
- package/packages/vite-plugin/tests/fetch-sdk.test.ts +27 -0
- package/packages/vite-plugin/tests/fetch.test.ts +1196 -0
- package/packages/vite-plugin/tests/fixtures/fake-cli/bin.js +90 -0
- package/packages/vite-plugin/tests/fixtures/fake-cli/package.json +8 -0
- package/packages/vite-plugin/tests/fixtures/icrc1.did +88 -0
- package/packages/vite-plugin/tests/generation.test.ts +1036 -0
- package/packages/vite-plugin/tests/icp-command.test.ts +194 -0
- package/packages/vite-plugin/tests/icp-timeout.test.ts +83 -0
- package/packages/vite-plugin/tests/no-process-exit.test.ts +83 -0
- package/packages/vite-plugin/tests/on-generated.test.ts +323 -0
- package/packages/vite-plugin/tests/output-collision.test.ts +329 -0
- package/packages/vite-plugin/tests/package.test.ts +62 -0
- package/packages/vite-plugin/tests/project.test.ts +2993 -0
- package/packages/vite-plugin/tests/support.ts +339 -0
- package/packages/vite-plugin/tests/timeout.test.ts +107 -0
- package/packages/vite-plugin/tsconfig.json +23 -0
- package/packages/vite-plugin/tsconfig.typecheck.json +16 -0
- package/packages/vite-plugin/vitest.config.ts +9 -0
- package/pnpm-workspace.yaml +23 -0
- package/scripts/ai-context-files.js +72 -0
- package/scripts/assemble-docs-site.mjs +485 -0
- package/scripts/assemble-docs-site.test.mjs +568 -0
- package/scripts/build-examples.js +58 -0
- package/scripts/check-ai-context.js +963 -0
- package/scripts/check-ai-context.test.mjs +811 -0
- package/scripts/check-exports.mjs +767 -0
- package/scripts/check-exports.test.mjs +1136 -0
- package/scripts/check-snippets/ambient.d.ts +428 -0
- package/scripts/check-snippets/app/generated/backend.did +7 -0
- package/scripts/check-snippets/app/generated/backend.ts +15 -0
- package/scripts/check-snippets/app/generated/icrc1.did +88 -0
- package/scripts/check-snippets/app/generated/icrc1.ts +78 -0
- package/scripts/check-snippets/app/globals.ts +26 -0
- package/scripts/check-snippets/docs/guides/App.tsx +21 -0
- package/scripts/check-snippets/docs/guides/app/providers.tsx +23 -0
- package/scripts/check-snippets/docs/guides/auth-client.ts +47 -0
- package/scripts/check-snippets/docs/guides/canisters/backend.ts +3 -0
- package/scripts/check-snippets/docs/guides/canisters/icrc1.ts +3 -0
- package/scripts/check-snippets/docs/guides/components/LedgerCard.tsx +26 -0
- package/scripts/check-snippets/docs/guides/components/shell.tsx +11 -0
- package/scripts/check-snippets/docs/guides/components/sign-in-page.tsx +29 -0
- package/scripts/check-snippets/docs/guides/components/slow-section.tsx +5 -0
- package/scripts/check-snippets/docs/guides/generated/accounts.ts +95 -0
- package/scripts/check-snippets/docs/guides/generated/ckbtc_minter.ts +40 -0
- package/scripts/check-snippets/docs/guides/generated/icp_ledger.ts +267 -0
- package/scripts/check-snippets/docs/guides/ledger.ts +10 -0
- package/scripts/check-snippets/docs/guides/server/request-client.ts +8 -0
- package/scripts/check-snippets.mjs +993 -0
- package/scripts/check-snippets.test.mjs +338 -0
- package/scripts/check-stack.mjs +501 -0
- package/scripts/check-stack.test.mjs +800 -0
- package/scripts/clean-node-modules.js +67 -0
- package/scripts/example-projects.js +58 -0
- package/scripts/export-budget.mjs +145 -0
- package/scripts/faults.json +6749 -0
- package/scripts/lib/fault-workspace.mjs +210 -0
- package/scripts/lib/io.mjs +29 -0
- package/scripts/lib/io.test.mjs +38 -0
- package/scripts/lib/markdown-fences.mjs +56 -0
- package/scripts/lib/markdown-fences.test.mjs +84 -0
- package/scripts/lib/package-exports.mjs +54 -0
- package/scripts/lib/package-exports.test.mjs +66 -0
- package/scripts/lib/release-pr-steps.mjs +47 -0
- package/scripts/release-tag.mjs +95 -0
- package/scripts/release-tag.test.mjs +278 -0
- package/scripts/release-workflow.test.mjs +98 -0
- package/scripts/release.js +167 -0
- package/scripts/release.test.mjs +347 -0
- package/scripts/removed-v3-names.js +125 -0
- package/scripts/size-app/.size-limit.js +90 -0
- package/scripts/size-app/core.js +3 -0
- package/scripts/size-app/package.json +24 -0
- package/scripts/size-app/react.js +4 -0
- package/scripts/size-app.test.mjs +73 -0
- package/scripts/sync-ai-context-versions.js +102 -0
- package/scripts/sync-example-versions.js +151 -0
- package/scripts/test-examples-published.mjs +1585 -0
- package/scripts/test-examples-published.test.mjs +1586 -0
- package/scripts/traps/any-method-vars-not-a-list.json +5 -0
- package/scripts/traps/canister-method-unknown.json +5 -0
- package/scripts/traps/client-says-who-calls-once.json +5 -0
- package/scripts/traps/client-says-who-calls.json +5 -0
- package/scripts/traps/err-only-on-canister-err.json +14 -0
- package/scripts/traps/format-units-refuses-missing-value.json +5 -0
- package/scripts/traps/format-units-refuses-number.json +5 -0
- package/scripts/traps/format-units-unknown-option.json +5 -0
- package/scripts/traps/guard-err-is-the-methods.json +5 -0
- package/scripts/traps/guard-false-keeps-every-kind.json +5 -0
- package/scripts/traps/internals-not-exported.json +9 -0
- package/scripts/traps/network-refuses-unknown-name.json +5 -0
- package/scripts/traps/never-err-has-no-type.json +5 -0
- package/scripts/traps/options-method-unknown.json +5 -0
- package/scripts/traps/options-vars-wrong-type.json +5 -0
- package/scripts/traps/parse-units-refuses-number.json +5 -0
- package/scripts/traps/parse-units-unknown-option.json +5 -0
- package/scripts/traps/principal-is-not-plain-text.json +14 -0
- package/scripts/traps/query-options-refuses-oneway.json +5 -0
- package/scripts/traps/query-options-refuses-update.json +5 -0
- package/scripts/traps/refuse-next-unknown-option.json +5 -0
- package/scripts/traps/resend-key-reads-the-methods-arg.json +5 -0
- package/scripts/traps/resend-states-its-dedupe-key.json +5 -0
- package/scripts/traps/suspense-refuses-argument-skip.json +5 -0
- package/scripts/traps/suspense-refuses-skippable-read.json +5 -0
- package/scripts/traps/suspense-refuses-vars-skip-fits.json +5 -0
- package/scripts/traps/test-handler-method-unknown.json +5 -0
- package/scripts/traps/test-handler-nat-is-bigint.json +5 -0
- package/scripts/traps/test-handler-takes-the-domain-value.json +5 -0
- package/scripts/traps/vars-of-two-arguments-are-the-tuple.json +5 -0
- package/scripts/typecheck-examples.js +122 -0
- package/scripts/verify-faults.mjs +375 -0
- package/scripts/verify-faults.test.mjs +402 -0
- package/scripts/verify-package-artifacts.mjs +590 -0
- package/scripts/verify-peer-floors.js +399 -0
- package/scripts/verify-peer-floors.test.mjs +422 -0
- package/scripts/verify-test-fails-rules.mjs +104 -0
- package/scripts/verify-test-fails-rules.test.mjs +215 -0
- package/scripts/verify-test-fails.js +371 -0
- package/scripts/verify-traps.mjs +505 -0
- package/scripts/verify-traps.test.mjs +521 -0
- package/scripts/verify-typescript-floor.js +239 -0
- package/skill-packages/ic-reactor/SKILL.md +103 -0
- package/stack.json +8 -0
- package/tsconfig.base.json +23 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Testing"
|
|
3
|
+
description: "createTestClient from @ic-reactor/core/testing: a real client over an in-memory replica, mocked canisters, injected failures and a sign-in a test controls"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`createTestClient` gives you a real client for a test. Nothing in it is a stub
|
|
7
|
+
of the client. Calls are signed by the principal that is signed in, sent
|
|
8
|
+
through an `HttpAgent` to an in-memory replica that checks the signature and
|
|
9
|
+
certifies the reply, and the client verifies the certificate. Only the canister
|
|
10
|
+
is replaced, by plain functions you write. So a test sees what an app would
|
|
11
|
+
see: a refused write, a lost reply, a re-send after HTTP 429, a read that
|
|
12
|
+
moves to another caller's key.
|
|
13
|
+
|
|
14
|
+
Nothing global is replaced. `globalThis.fetch` is untouched, and two test
|
|
15
|
+
clients run side by side, each with its own replica and sign-in.
|
|
16
|
+
|
|
17
|
+
## Import
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { createTestClient, type TestHandlers } from "@ic-reactor/core/testing"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
That subpath exports `createTestClient` and the type `TestHandlers`, and
|
|
24
|
+
nothing else. The fake replica signs with `@noble/curves`, an optional peer of
|
|
25
|
+
`@ic-reactor/core` that `@icp-sdk/core` already installs. If your package
|
|
26
|
+
manager does not let core resolve it, add it to `devDependencies`.
|
|
27
|
+
|
|
28
|
+
## A first test
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { principal } from "@meantjs/schema"
|
|
32
|
+
import { createTestClient } from "@ic-reactor/core/testing"
|
|
33
|
+
import { afterEach, beforeEach, expect, it } from "vitest"
|
|
34
|
+
import { actor, type Actor } from "./generated/icrc1"
|
|
35
|
+
|
|
36
|
+
const LEDGER = "ryjl3-tyaaa-aaaaa-aaaba-cai"
|
|
37
|
+
|
|
38
|
+
let test: ReturnType<typeof createTestClient>
|
|
39
|
+
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
test = createTestClient() // signed in as the identity of seed 1
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
afterEach(() => {
|
|
45
|
+
test.client.dispose()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it("reads the balance of the caller", async () => {
|
|
49
|
+
const { client, auth, mock } = test
|
|
50
|
+
mock<Actor>(actor, LEDGER, {
|
|
51
|
+
icrc1_balance_of: ({ owner }, { caller }) => (owner === caller ? 7n : 0n),
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
const ledger = client.canister<Actor>(actor, { id: LEDGER })
|
|
55
|
+
const me = principal(auth.getPrincipal()!.toText())
|
|
56
|
+
|
|
57
|
+
expect(await ledger.icrc1_balance_of({ owner: me, subaccount: null })).toBe(
|
|
58
|
+
7n
|
|
59
|
+
)
|
|
60
|
+
})
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`mock<Actor>(actor, id, handlers)` runs a canister at `id`, replacing any
|
|
64
|
+
canister already there. `actor` is the service schema of the generated module
|
|
65
|
+
and `Actor` its type, as for `client.canister<Actor>(actor, { id })`.
|
|
66
|
+
|
|
67
|
+
## What it returns and what it takes
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { createTestClient } from "@ic-reactor/core/testing"
|
|
71
|
+
|
|
72
|
+
const { client, auth, mock, reject, dropNextReply, refuseNext, requests } =
|
|
73
|
+
createTestClient({
|
|
74
|
+
identity: 1,
|
|
75
|
+
signedIn: true,
|
|
76
|
+
})
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
| Returned | What it is |
|
|
80
|
+
| --------------- | ------------------------------------------------------------------------------------------- |
|
|
81
|
+
| `client` | a real client from `createClient`, whose auth is `auth`. Dispose it at the end of each test |
|
|
82
|
+
| `auth` | the sign-in the client calls as (see [Sign-in](#sign-in)) |
|
|
83
|
+
| `mock` | runs a canister at an id, answering with handlers |
|
|
84
|
+
| `reject` | rejects the call being handled with a reject code, from inside a handler |
|
|
85
|
+
| `dropNextReply` | loses the reply to the next call request, or to the next ones it names |
|
|
86
|
+
| `refuseNext` | answers the next canister requests with an HTTP error status |
|
|
87
|
+
| `requests` | every request the replica received, in order |
|
|
88
|
+
|
|
89
|
+
| Option | Meaning |
|
|
90
|
+
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
91
|
+
| `identity` | who is signed in at first: a real signing identity such as `Ed25519KeyIdentity`, or a number that stands for one. The same number is the same principal in every run. Default: seed `1` |
|
|
92
|
+
| `signedIn` | `true` by default. With `false` the client starts anonymous, every update is refused, and `auth.signIn()` signs in as `identity` |
|
|
93
|
+
| `network` | the network the client believes it is on, for the key segment and the host. Give the host with a scheme. The root key is always the fake's |
|
|
94
|
+
| `allowEnvConfig` | as for `createClient`. Only a test that resolves `{ name }` canisters from an `ic_env` cookie needs it, and a `{ name }` resolves only on a page (jsdom or happy-dom), never in Node |
|
|
95
|
+
| `maxDepth` | how deep a decoded value may nest, for the client and the mocks. Default 256 |
|
|
96
|
+
| `maxElements` | how many values a decoded value may hold beyond one per byte, for the client and the mocks. Default 1,000,000 |
|
|
97
|
+
|
|
98
|
+
`createTestClient` throws a `TypeError` for an option that does not exist or
|
|
99
|
+
cannot be used.
|
|
100
|
+
|
|
101
|
+
## Writing handlers
|
|
102
|
+
|
|
103
|
+
A handler is a function of domain values, the same shapes the generated
|
|
104
|
+
`Actor` uses (see [Values and units](/v4/guides/values/)). It takes the
|
|
105
|
+
method's arguments, then a context `{ caller }`: the principal that sent the
|
|
106
|
+
call, as checked principal text, after the replica verified the signature.
|
|
107
|
+
`TestHandlers<Actor>` types every method, and a handler that returns a
|
|
108
|
+
`number` for a `nat` does not compile.
|
|
109
|
+
|
|
110
|
+
- **Ok and Err.** For a method whose one result is `variant { Ok : T; Err : E }`,
|
|
111
|
+
return `{ tag: "Ok", value }` or `{ tag: "Err", value }`. The client unwraps
|
|
112
|
+
it as in production: the call resolves with the `Ok` value, or rejects as
|
|
113
|
+
`canister_err` with the `Err` value in `err`.
|
|
114
|
+
- **No handler.** A call to a method with no handler traps, with a message that
|
|
115
|
+
names the method.
|
|
116
|
+
- **Throwing.** A handler that throws traps the call, as a canister does: reject
|
|
117
|
+
code 5 with the error's message. So does a call whose arguments do not decode,
|
|
118
|
+
and a handler that returns something the method's result cannot encode.
|
|
119
|
+
- **Query or update.** A method answers by its mode: a `query` on the query
|
|
120
|
+
path, an `update` on the call path. A `query` method also answers a
|
|
121
|
+
replicated call, which is how a `certified: true` canister reads it.
|
|
122
|
+
- **The management canister.** `mock` takes `"aaaaa-aa"` as an id.
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import { principal } from "@meantjs/schema"
|
|
126
|
+
import { createTestClient, type TestHandlers } from "@ic-reactor/core/testing"
|
|
127
|
+
import { expect, it } from "vitest"
|
|
128
|
+
import { actor, type Actor } from "./generated/icrc1"
|
|
129
|
+
|
|
130
|
+
const LEDGER = "ryjl3-tyaaa-aaaaa-aaaba-cai"
|
|
131
|
+
|
|
132
|
+
it("turns an Err into canister_err", async () => {
|
|
133
|
+
const { client, mock } = createTestClient()
|
|
134
|
+
const handlers: TestHandlers<Actor> = {
|
|
135
|
+
icrc1_transfer: () => ({
|
|
136
|
+
tag: "Err",
|
|
137
|
+
value: { tag: "InsufficientFunds", value: { balance: 0n } },
|
|
138
|
+
}),
|
|
139
|
+
}
|
|
140
|
+
mock<Actor>(actor, LEDGER, handlers)
|
|
141
|
+
|
|
142
|
+
const ledger = client.canister<Actor>(actor, { id: LEDGER })
|
|
143
|
+
const arg = {
|
|
144
|
+
to: { owner: principal("aaaaa-aa"), subaccount: null },
|
|
145
|
+
amount: 1n,
|
|
146
|
+
fee: null,
|
|
147
|
+
memo: null,
|
|
148
|
+
from_subaccount: null,
|
|
149
|
+
created_at_time: null,
|
|
150
|
+
}
|
|
151
|
+
await expect(ledger.icrc1_transfer(arg)).rejects.toMatchObject({
|
|
152
|
+
kind: "canister_err",
|
|
153
|
+
mayHaveExecuted: false,
|
|
154
|
+
err: { tag: "InsufficientFunds", value: { balance: 0n } },
|
|
155
|
+
})
|
|
156
|
+
client.dispose()
|
|
157
|
+
})
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Injecting failures
|
|
161
|
+
|
|
162
|
+
Each of these makes the client meet a failure it classifies, so a test can
|
|
163
|
+
check what the app does with it. See [Errors](/v4/guides/errors/) for the
|
|
164
|
+
kinds.
|
|
165
|
+
|
|
166
|
+
| Call | What the client meets | Result |
|
|
167
|
+
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
168
|
+
| `reject(code, msg)` | inside a handler: the call is rejected with reject code 1 to 6 | the kind of that code, see the classification table |
|
|
169
|
+
| `dropNextReply()` | the next call request runs, and its reply is lost: an update, or a certified read or an update read, which go out as calls | an update: `outcome_unknown`, `mayHaveExecuted: true`; never run twice. A read: the client sends it again as a new request, which can be answered, so its handler runs again |
|
|
170
|
+
| `dropNextReply({ method, canister, times })` | the same, aimed: only the call requests that name `method` and are addressed to `canister` (each when given) lose their reply; every other request goes through | `dropNextReply({ method: "icrc1_transfer" })`: the transfer's reply is lost, the reads before it are answered |
|
|
171
|
+
| `refuseNext(status, times = 1)` | the next `times` canister requests (queries or calls) get HTTP `status` (400 to 599) before any canister sees them | `refuseNext(429)`: one re-send; `refuseNext(429, 3)`: `not_delivered` |
|
|
172
|
+
| `refuseNext(status, { method, canister, times })` | the same, aimed: only the queries and calls that name `method` and are addressed to `canister` (each when given) are refused; every other request goes through | `refuseNext(429, { method: "icrc1_transfer" })`: the transfer is throttled, the reads around it are answered |
|
|
173
|
+
|
|
174
|
+
The aimed form of `refuseNext` matches a query and a replicated call of the
|
|
175
|
+
same method alike. `canister` is the canister a request names (`aaaaa-aa` for a
|
|
176
|
+
call to the management canister), and need not be mocked: a gateway refuses a
|
|
177
|
+
request for a canister that does not exist. `times` (default 1) counts matching
|
|
178
|
+
requests, each re-send included. The status and `read_state` requests an agent
|
|
179
|
+
makes on its own never match, and a request that several refusals match is
|
|
180
|
+
refused by the one armed first.
|
|
181
|
+
|
|
182
|
+
The aimed form of `dropNextReply` matches call requests by the same rules,
|
|
183
|
+
and an armed drop is used up in the order drops were armed. The bare form
|
|
184
|
+
loses the reply of whatever call request comes next, so a certified read made
|
|
185
|
+
before the write takes it: aim it at the write when reads go first.
|
|
186
|
+
|
|
187
|
+
`dropNextReply` keeps its reply lost whenever the same request is asked again,
|
|
188
|
+
so a test cannot run the update twice by accident. The client does not re-send
|
|
189
|
+
after it: it cannot know that is safe.
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
import { principal } from "@meantjs/schema"
|
|
193
|
+
import { createTestClient } from "@ic-reactor/core/testing"
|
|
194
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest"
|
|
195
|
+
import { actor, type Actor, type TransferArg } from "./generated/icrc1"
|
|
196
|
+
|
|
197
|
+
const LEDGER = "ryjl3-tyaaa-aaaaa-aaaba-cai"
|
|
198
|
+
const arg: TransferArg = {
|
|
199
|
+
to: { owner: principal("aaaaa-aa"), subaccount: null },
|
|
200
|
+
amount: 100n,
|
|
201
|
+
fee: null,
|
|
202
|
+
memo: null,
|
|
203
|
+
from_subaccount: null,
|
|
204
|
+
created_at_time: null,
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
describe("a transfer under failure", () => {
|
|
208
|
+
let test: ReturnType<typeof createTestClient>
|
|
209
|
+
|
|
210
|
+
beforeEach(() => {
|
|
211
|
+
test = createTestClient()
|
|
212
|
+
test.mock<Actor>(actor, LEDGER, {
|
|
213
|
+
icrc1_transfer: (_arg, { caller }) =>
|
|
214
|
+
caller === principal("aaaaa-aa")
|
|
215
|
+
? test.reject(4, "no funds")
|
|
216
|
+
: { tag: "Ok", value: 1n },
|
|
217
|
+
})
|
|
218
|
+
})
|
|
219
|
+
afterEach(() => test.client.dispose())
|
|
220
|
+
|
|
221
|
+
const sends = () =>
|
|
222
|
+
test.requests.filter(
|
|
223
|
+
(r) => r.endpoint === "call" && r.methodName === "icrc1_transfer"
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
it("loses a reply: the outcome is unknown", async () => {
|
|
227
|
+
const ledger = test.client.canister<Actor>(actor, { id: LEDGER })
|
|
228
|
+
test.dropNextReply()
|
|
229
|
+
|
|
230
|
+
await expect(ledger.icrc1_transfer(arg)).rejects.toMatchObject({
|
|
231
|
+
kind: "outcome_unknown",
|
|
232
|
+
mayHaveExecuted: true,
|
|
233
|
+
})
|
|
234
|
+
expect(sends()).toHaveLength(1) // the client never sent it again
|
|
235
|
+
expect(sends()[0]?.dropped).toBe(true)
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
it("sends again once after a 429, and it goes through", async () => {
|
|
239
|
+
const ledger = test.client.canister<Actor>(actor, { id: LEDGER })
|
|
240
|
+
test.refuseNext(429)
|
|
241
|
+
|
|
242
|
+
expect(await ledger.icrc1_transfer(arg)).toBe(1n)
|
|
243
|
+
expect(sends()).toHaveLength(2)
|
|
244
|
+
expect(sends()[0]?.refused).toContain("429")
|
|
245
|
+
expect(sends()[1]?.refused).toBeUndefined()
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
it("gives up after three 429s: not delivered, certainly not run", async () => {
|
|
249
|
+
const ledger = test.client.canister<Actor>(actor, { id: LEDGER })
|
|
250
|
+
test.refuseNext(429, 3)
|
|
251
|
+
|
|
252
|
+
await expect(ledger.icrc1_transfer(arg)).rejects.toMatchObject({
|
|
253
|
+
kind: "not_delivered",
|
|
254
|
+
httpStatus: 429,
|
|
255
|
+
mayHaveExecuted: false,
|
|
256
|
+
})
|
|
257
|
+
expect(sends()).toHaveLength(3) // the first send and the two re-sends the client allows itself
|
|
258
|
+
})
|
|
259
|
+
})
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
The client waits 300 ms and then 600 ms before the re-sends, so the last two
|
|
263
|
+
tests take about a second.
|
|
264
|
+
|
|
265
|
+
## Sign-in
|
|
266
|
+
|
|
267
|
+
`auth` is the sign-in the client calls as. It has the surface of an
|
|
268
|
+
`@icp-sdk/auth` 10 `AuthClient`, driven by calls instead of an identity
|
|
269
|
+
provider, plus the controls a test needs to play out what a user does. Every
|
|
270
|
+
change is synchronous and reaches the client's listeners once, so a test
|
|
271
|
+
reads the result without waiting.
|
|
272
|
+
|
|
273
|
+
| Call | Effect |
|
|
274
|
+
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
275
|
+
| `auth.signOut()` | nobody is signed in. A later `signIn()` returns to the same identity |
|
|
276
|
+
| `auth.signIn(identityOrSeed?)` | signs in as that identity, or as the one it last signed in as |
|
|
277
|
+
| `auth.switchTo(identityOrSeed)` | signs in as another identity in one step, with no signed-out state in between: a user picking another account |
|
|
278
|
+
| `auth.expire()` | the session of the last identity ends: status `expired`. A session also ends by the clock, eight hours after its sign-in (advance fake timers to get there) |
|
|
279
|
+
| `auth.elsewhere()` | that identity is signed in on this domain but not held by this origin: status `signed-in-elsewhere` |
|
|
280
|
+
|
|
281
|
+
`getPrincipal()`, `getStatus()` and `getIdentity()` read the current state.
|
|
282
|
+
The client owns the auth once anything has asked it who the caller is, and
|
|
283
|
+
disposes it with itself.
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
import { createTestClient } from "@ic-reactor/core/testing"
|
|
287
|
+
import { expect, it } from "vitest"
|
|
288
|
+
|
|
289
|
+
it("follows the sign-in", () => {
|
|
290
|
+
const { client, auth } = createTestClient({ identity: 1 })
|
|
291
|
+
const alice = client.caller()
|
|
292
|
+
expect(client.authState().status).toBe("signed-in")
|
|
293
|
+
|
|
294
|
+
auth.switchTo(2)
|
|
295
|
+
expect(client.caller()).not.toBe(alice)
|
|
296
|
+
|
|
297
|
+
auth.expire() // an expired session calls as the anonymous principal
|
|
298
|
+
expect(client.authState().status).toBe("expired")
|
|
299
|
+
expect(client.caller()).toBe("2vxsx-fae")
|
|
300
|
+
|
|
301
|
+
auth.signOut()
|
|
302
|
+
expect(client.authState().status).toBe("anonymous")
|
|
303
|
+
client.dispose()
|
|
304
|
+
})
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Asserting on requests
|
|
308
|
+
|
|
309
|
+
`requests` is the log of what the replica received, in order. The same array
|
|
310
|
+
grows, so copy it (`[...requests]`) to keep one moment of it. An entry has:
|
|
311
|
+
|
|
312
|
+
| Field | Meaning |
|
|
313
|
+
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
314
|
+
| `endpoint` | `"status"`, `"query"`, `"call"` or `"read_state"` |
|
|
315
|
+
| `canisterId` | the canister the request was addressed to |
|
|
316
|
+
| `effectiveCanisterId` | the canister it was routed by: differs for a call to `aaaaa-aa` |
|
|
317
|
+
| `methodName` | the method a `query` or `call` named |
|
|
318
|
+
| `caller` | the principal the request came from, after the replica checked its signature |
|
|
319
|
+
| `refused` | why the replica answered before any canister saw the request: a bad signature, delegation or target, or a `refuseNext` status |
|
|
320
|
+
| `dropped` | `true` when `dropNextReply()` lost the reply |
|
|
321
|
+
|
|
322
|
+
Use it to count sends (an update must not run twice), to check that a write was
|
|
323
|
+
refused before sending (no `"call"` entry), and to check who signed.
|
|
324
|
+
|
|
325
|
+
## Testing React
|
|
326
|
+
|
|
327
|
+
Give the provider the test client as a borrowed one, `client={() => test.client}`,
|
|
328
|
+
and dispose it yourself after the test. See
|
|
329
|
+
[`@ic-reactor/react`](/v4/packages/react/) for what the provider owns.
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
// @vitest-environment jsdom
|
|
333
|
+
import { principal } from "@meantjs/schema"
|
|
334
|
+
import { createTestClient } from "@ic-reactor/core/testing"
|
|
335
|
+
import { ReactorProvider, useAuth, useClient } from "@ic-reactor/react"
|
|
336
|
+
import { useQuery } from "@tanstack/react-query"
|
|
337
|
+
import { act, cleanup, render, screen } from "@testing-library/react"
|
|
338
|
+
import { afterEach, expect, it } from "vitest"
|
|
339
|
+
import { actor, type Actor } from "./generated/icrc1"
|
|
340
|
+
|
|
341
|
+
const LEDGER = "ryjl3-tyaaa-aaaaa-aaaba-cai"
|
|
342
|
+
|
|
343
|
+
function MyBalance() {
|
|
344
|
+
const client = useClient()
|
|
345
|
+
const { principal: caller } = useAuth()
|
|
346
|
+
const ledger = client.canister<Actor>(actor, { id: LEDGER })
|
|
347
|
+
const balance = useQuery(
|
|
348
|
+
client.queryOptions(ledger, "icrc1_balance_of", {
|
|
349
|
+
owner: principal(caller),
|
|
350
|
+
subaccount: null,
|
|
351
|
+
})
|
|
352
|
+
)
|
|
353
|
+
return (
|
|
354
|
+
<p>{balance.data === undefined ? "loading" : `balance ${balance.data}`}</p>
|
|
355
|
+
)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
afterEach(cleanup)
|
|
359
|
+
|
|
360
|
+
it("shows each caller's own balance", async () => {
|
|
361
|
+
const test = createTestClient({ identity: 1 })
|
|
362
|
+
const alice = principal(test.auth.getPrincipal()!.toText())
|
|
363
|
+
test.mock<Actor>(actor, LEDGER, {
|
|
364
|
+
icrc1_balance_of: ({ owner }) => (owner === alice ? 7n : 0n),
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
render(
|
|
368
|
+
<ReactorProvider client={() => test.client}>
|
|
369
|
+
<MyBalance />
|
|
370
|
+
</ReactorProvider>
|
|
371
|
+
)
|
|
372
|
+
await screen.findByText("balance 7")
|
|
373
|
+
|
|
374
|
+
await act(async () => {
|
|
375
|
+
test.auth.switchTo(2) // another account: the keys move, never another's data
|
|
376
|
+
})
|
|
377
|
+
await screen.findByText("balance 0")
|
|
378
|
+
|
|
379
|
+
test.client.dispose()
|
|
380
|
+
})
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
After the switch the component reads the new caller's key, which is empty until
|
|
384
|
+
it loads, so the test never sees the first caller's `7` under the second.
|
|
385
|
+
|
|
386
|
+
## Examples
|
|
387
|
+
|
|
388
|
+
The examples ship their test kits. Read them for larger setups.
|
|
389
|
+
|
|
390
|
+
- [ICRC-1 ledger](/v4/examples/icrc-ledger/):
|
|
391
|
+
[`src/sandbox.ts`](https://github.com/b3pay/ic-reactor/blob/main/examples/icrc-ledger/src/sandbox.ts)
|
|
392
|
+
arms each failure above, and
|
|
393
|
+
[`sandbox.test.ts`](https://github.com/b3pay/ic-reactor/blob/main/examples/icrc-ledger/src/sandbox.test.ts)
|
|
394
|
+
asserts the re-sends and the unknown outcome.
|
|
395
|
+
- [Vite wallet](/v4/examples/vite-wallet/):
|
|
396
|
+
[`src/test/test-wallet.tsx`](https://github.com/b3pay/ic-reactor/blob/main/examples/vite-wallet/src/test/test-wallet.tsx)
|
|
397
|
+
renders components in a provider over a test client with `network: "env"`
|
|
398
|
+
and an `ic_env` cookie written as the Vite plugin writes it.
|
|
399
|
+
- [Node agent tool](/v4/examples/node-agent-tool/):
|
|
400
|
+
[`src/test-kit.ts`](https://github.com/b3pay/ic-reactor/blob/main/examples/node-agent-tool/src/test-kit.ts)
|
|
401
|
+
runs a command-line tool against the in-memory replica.
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Values and units"
|
|
3
|
+
description: "How Candid values look in TypeScript, how to make principals, and how to convert token amounts with parseUnits and formatUnits"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
A module that `meant gen` writes types every Candid value as plain
|
|
7
|
+
TypeScript. There are no wrapper classes. This page lists the shapes, shows
|
|
8
|
+
how to make arguments, and shows how to convert token amounts exactly.
|
|
9
|
+
|
|
10
|
+
## Candid to TypeScript
|
|
11
|
+
|
|
12
|
+
| Candid | TypeScript |
|
|
13
|
+
| ---------------------------------------- | ------------------------------------------------------- |
|
|
14
|
+
| `nat`, `int`, `nat64`, `int64` | `bigint` (never `number`) |
|
|
15
|
+
| `nat8`..`nat32`, `int8`..`int32`, floats | `number` |
|
|
16
|
+
| `text`, `bool` | `string`, `boolean` |
|
|
17
|
+
| `principal` | `Principal`: branded principal text |
|
|
18
|
+
| `blob`, `vec nat8` | `Uint8Array` |
|
|
19
|
+
| `opt T` | `T \| null` (the property is always present) |
|
|
20
|
+
| `opt opt T`, `opt null` | `{ some: T \| null } \| null`, `{ some: null } \| null` |
|
|
21
|
+
| `vec T` | `T[]` |
|
|
22
|
+
| `record { a : T }` | `{ a: T }`, every field present |
|
|
23
|
+
| `variant { A : T; B }` | `{ tag: "A"; value: T } \| { tag: "B" }` |
|
|
24
|
+
|
|
25
|
+
Three consequences:
|
|
26
|
+
|
|
27
|
+
- **`bigint` for amounts.** A `nat` is a `bigint`, so a ledger's balance is
|
|
28
|
+
`bigint` too. `icrc1_decimals` is a `nat8`, so it is a `number`.
|
|
29
|
+
- **`null` for an empty `opt`.** The property is always there. A record with an
|
|
30
|
+
optional field is written with `null`, not by leaving the field out.
|
|
31
|
+
- **Variants are `{ tag, value }`.** A variant arm with no payload has no
|
|
32
|
+
`value`.
|
|
33
|
+
|
|
34
|
+
An ICRC-1 transfer shows all three:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { principal } from "@meantjs/schema"
|
|
38
|
+
import type { Account, TransferArg, TransferError } from "./generated/icrc1"
|
|
39
|
+
|
|
40
|
+
const to: Account = {
|
|
41
|
+
owner: principal("aaaaa-aa"),
|
|
42
|
+
subaccount: null, // opt blob
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const arg: TransferArg = {
|
|
46
|
+
to,
|
|
47
|
+
amount: 150_000_000n, // nat
|
|
48
|
+
fee: null,
|
|
49
|
+
memo: null,
|
|
50
|
+
from_subaccount: null,
|
|
51
|
+
created_at_time: null,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function describe(error: TransferError): string {
|
|
55
|
+
switch (error.tag) {
|
|
56
|
+
case "InsufficientFunds":
|
|
57
|
+
return `the balance is ${error.value.balance}`
|
|
58
|
+
case "BadFee":
|
|
59
|
+
return `the fee is ${error.value.expected_fee}`
|
|
60
|
+
case "TooOld":
|
|
61
|
+
return "created_at_time is too old" // no value on this arm
|
|
62
|
+
default:
|
|
63
|
+
return error.tag
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Principals
|
|
69
|
+
|
|
70
|
+
A `Principal` is principal text with a brand, so a plain `string` does not
|
|
71
|
+
pass for one. Make one with `principal(text)` from `@meantjs/schema`. It
|
|
72
|
+
accepts only canonical text and throws a `TypeError` for anything else, so
|
|
73
|
+
catch it where the text comes from a user:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import { isPrincipal, principal, type Principal } from "@meantjs/schema"
|
|
77
|
+
|
|
78
|
+
export function parseOwner(text: string): Principal | undefined {
|
|
79
|
+
try {
|
|
80
|
+
return principal(text.trim())
|
|
81
|
+
} catch {
|
|
82
|
+
return undefined // refuse the input
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function isOwner(text: string): boolean {
|
|
87
|
+
return isPrincipal(text) // in render: no throw
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`principal` also takes an `@icp-sdk/core` `Principal`, or any object with a
|
|
92
|
+
`toText()` method. `isPrincipal(value)` is the same check without the throw: use
|
|
93
|
+
it first in render, for example to pass `skipToken` until a typed owner is
|
|
94
|
+
valid. Never cast text to `Principal`. A cast skips the check, and the value is
|
|
95
|
+
refused later, when it is encoded.
|
|
96
|
+
|
|
97
|
+
`principal` and `isPrincipal` come from `@meantjs/schema` only.
|
|
98
|
+
`@ic-reactor/core` and `@ic-reactor/react` do not re-export them.
|
|
99
|
+
|
|
100
|
+
## Arguments
|
|
101
|
+
|
|
102
|
+
- A **direct call** takes the parameters as `type Actor` lists them:
|
|
103
|
+
`ledger.icrc1_balance_of(account)`, `backend.set_name(owner, "Ada")`.
|
|
104
|
+
- The **builders**, `client.queryOptions` and `client.mutationOptions`, take
|
|
105
|
+
the variables as one value: nothing for a method with no arguments, the value
|
|
106
|
+
for one argument, and a tuple `[a, b]` for several.
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { principal } from "@meantjs/schema"
|
|
110
|
+
import { client } from "./ledger"
|
|
111
|
+
import { actor, type Actor } from "./generated/backend"
|
|
112
|
+
|
|
113
|
+
const backend = client.canister<Actor>(actor, {
|
|
114
|
+
id: "rrkah-fqaaa-aaaaa-aaaaq-cai",
|
|
115
|
+
})
|
|
116
|
+
const me = principal("aaaaa-aa")
|
|
117
|
+
|
|
118
|
+
// Direct: the parameters, as Actor lists them.
|
|
119
|
+
await backend.get_profile(me)
|
|
120
|
+
|
|
121
|
+
// Builders: one value for one argument. A method with no arguments takes
|
|
122
|
+
// nothing, as in client.queryOptions(ledger, "icrc1_fee").
|
|
123
|
+
const getProfile = client.queryOptions(backend, "get_profile", me)
|
|
124
|
+
|
|
125
|
+
// set_name has two parameters, so its variables are a tuple:
|
|
126
|
+
const setName = client.mutationOptions(backend, "set_name")
|
|
127
|
+
// useMutation(setName).mutate([me, "Ada"])
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Results
|
|
131
|
+
|
|
132
|
+
A method whose single result is `variant { Ok : T; Err : E }` resolves with the
|
|
133
|
+
`Ok` value. The `Err` value rejects as a `ReactorError` of kind
|
|
134
|
+
`"canister_err"`, with the value in `err`, typed on a query's or mutation's
|
|
135
|
+
`error`. See [Errors and mayHaveExecuted](/v4/guides/errors/).
|
|
136
|
+
|
|
137
|
+
## Token amounts
|
|
138
|
+
|
|
139
|
+
A ledger counts in base units: e8s for ICP, satoshis for ckBTC, wei for ckETH.
|
|
140
|
+
`parseUnits` and `formatUnits` convert between those and the decimal text a
|
|
141
|
+
person reads and types. Neither goes through `Number`, so every amount a ledger
|
|
142
|
+
can hold converts exactly in both directions.
|
|
143
|
+
|
|
144
|
+
### Why not `Number`
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
const lost = Math.floor(Number("0.29") * 10 ** 8)
|
|
148
|
+
console.log(lost) // 28999999: a transfer of 0.29 would send 0.28999999
|
|
149
|
+
|
|
150
|
+
const wei = BigInt(Math.floor(Number("1.1") * 1e18))
|
|
151
|
+
console.log(wei) // 1100000000000000128n: not 1.1 tokens at 18 decimals
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The helpers work on the digits, not on a `Number`.
|
|
155
|
+
|
|
156
|
+
### `parseUnits`
|
|
157
|
+
|
|
158
|
+
`parseUnits(text, decimals, options?)` reads text a person typed and returns
|
|
159
|
+
base units as a `bigint`:
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
import { parseUnits } from "@ic-reactor/core"
|
|
163
|
+
|
|
164
|
+
parseUnits("1.5", 8) // 150000000n
|
|
165
|
+
parseUnits("0.29", 8) // 29000000n
|
|
166
|
+
parseUnits("1.1", 18) // 1100000000000000000n
|
|
167
|
+
parseUnits(" 5. ", 8) // 500000000n: whitespace around the number, and "5.", are fine
|
|
168
|
+
parseUnits(".5", 8) // 50000000n
|
|
169
|
+
parseUnits("1.000000000", 8) // 100000000n: the extra zeros change nothing
|
|
170
|
+
parseUnits("-1", 8, { signed: true }) // -100000000n, for an int amount
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
It refuses anything it would have to guess at:
|
|
174
|
+
|
|
175
|
+
| Input | Result |
|
|
176
|
+
| ------------------------------------------------------ | ------------ |
|
|
177
|
+
| not text, blank, letters | `TypeError` |
|
|
178
|
+
| grouping (`"1,5"`), exponents (`"1e3"`), a leading `+` | `TypeError` |
|
|
179
|
+
| a lone `.`, whitespace inside the number | `TypeError` |
|
|
180
|
+
| `decimals` that is not a whole number | `TypeError` |
|
|
181
|
+
| an option other than `signed`, a `signed` not boolean | `TypeError` |
|
|
182
|
+
| more significant fraction digits than `decimals` | `RangeError` |
|
|
183
|
+
| a negative amount without `signed: true` | `RangeError` |
|
|
184
|
+
| `decimals` outside 0 to 255 | `RangeError` |
|
|
185
|
+
|
|
186
|
+
`"0.123456789"` at 8 decimals is no amount of e8s, and rounding it would send
|
|
187
|
+
something other than what was typed, so it is refused. Fraction digits past
|
|
188
|
+
`decimals` that are all zeros are not significant, so `"1.000000000"` at 8
|
|
189
|
+
decimals is `100000000n`; `"5."`, `".5"` and whitespace around the number are
|
|
190
|
+
accepted too. Validate the field with `parseUnits` itself, so that the form
|
|
191
|
+
and the amount sent never disagree. In a form, catch both
|
|
192
|
+
errors, show the message, and send nothing:
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
import { parseUnits } from "@ic-reactor/core"
|
|
196
|
+
|
|
197
|
+
export function readAmount(input: string, decimals: number): bigint | string {
|
|
198
|
+
try {
|
|
199
|
+
return parseUnits(input, decimals)
|
|
200
|
+
} catch (error) {
|
|
201
|
+
return (error as Error).message
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
There is no upper bound on the result. The limit belongs to the Candid type: a
|
|
207
|
+
`nat64` field refuses 2^64 when the call is encoded, as `invalid_args`, before
|
|
208
|
+
anything is sent, and an ICRC-1 `amount` is a `nat`, which has no limit.
|
|
209
|
+
|
|
210
|
+
### `formatUnits`
|
|
211
|
+
|
|
212
|
+
`formatUnits(value, decimals, options?)` shows base units as plain decimal text.
|
|
213
|
+
The text is only `-`, the digits and `.`, the same on a server and in every
|
|
214
|
+
browser, and the form `parseUnits` reads back.
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
import { formatUnits } from "@ic-reactor/core"
|
|
218
|
+
|
|
219
|
+
formatUnits(150_000_000n, 8) // "1.5": trailing zeros are dropped
|
|
220
|
+
formatUnits(100_000_000n, 8) // "1"
|
|
221
|
+
formatUnits(123_456_789n, 8, { maxFractionDigits: 2 }) // "1.23"
|
|
222
|
+
formatUnits(99_999_999n, 8, { maxFractionDigits: 2 }) // "0.99", never "1"
|
|
223
|
+
formatUnits(100_000_000n, 8, { minFractionDigits: 2 }) // "1.00"
|
|
224
|
+
formatUnits(-1n, 8) // "-0.00000001"
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
- `maxFractionDigits` cuts the digits past it toward zero and never rounds up.
|
|
228
|
+
A display never shows more than is held.
|
|
229
|
+
- `minFractionDigits` pads the fraction with zeros instead of trimming them.
|
|
230
|
+
- There is no `"-0"`: a negative amount whose shown digits are all zero is
|
|
231
|
+
written without the sign.
|
|
232
|
+
- `formatUnits` throws a `TypeError` when `value` is not a `bigint` or an
|
|
233
|
+
option is not one of these two (Intl's `maximumFractionDigits` included), and
|
|
234
|
+
a `RangeError` for digit options outside 0 to 255 or a `minFractionDigits` above
|
|
235
|
+
`maxFractionDigits`.
|
|
236
|
+
|
|
237
|
+
### Locale display
|
|
238
|
+
|
|
239
|
+
For a locale's separators, format the text yourself with `Intl.NumberFormat`.
|
|
240
|
+
It reads a decimal string exactly, but it rounds to 3 fraction digits unless you
|
|
241
|
+
say otherwise, so give it a `maximumFractionDigits` as large as the digits the
|
|
242
|
+
text has:
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
/// <reference lib="es2023.intl" />
|
|
246
|
+
import { formatUnits } from "@ic-reactor/core"
|
|
247
|
+
|
|
248
|
+
const text = formatUnits(123_456_789_000n, 8) // "1234.56789"
|
|
249
|
+
const shown = new Intl.NumberFormat("de-DE", {
|
|
250
|
+
maximumFractionDigits: 8,
|
|
251
|
+
}).format(
|
|
252
|
+
text as Intl.StringNumericLiteral // the cast needs lib ES2023
|
|
253
|
+
)
|
|
254
|
+
console.log(shown) // "1.234,56789"
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Before lib ES2023, the `Intl` types accept only a `number` or a `bigint`, and a
|
|
258
|
+
`number` loses digits. That is why the cast, and the reference line, are there.
|
|
259
|
+
|
|
260
|
+
Next: [Reads](/v4/guides/reads/) and [Writes](/v4/guides/writes/) use these
|
|
261
|
+
values.
|