@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,552 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Render a server page for one user"
|
|
3
|
+
description: "A Next.js App Router page for the account a URL names: its ICP balance read on the server and handed to the browser exact, a certified balance streamed in, and the owner told apart once they sign in"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
import { Aside, FileTree } from "@astrojs/starlight/components"
|
|
7
|
+
|
|
8
|
+
This guide builds one page of a Next.js App Router app:
|
|
9
|
+
`/accounts/<principal>`, the ICP balance of the account the URL names. The
|
|
10
|
+
server reads the balance and sends it with the page. The browser takes over
|
|
11
|
+
the server's cache and sends nothing on load. A certified balance, read
|
|
12
|
+
through consensus, streams in after it.
|
|
13
|
+
|
|
14
|
+
The user is the account in the URL, not the visitor. A server holds no
|
|
15
|
+
session: it reads as the anonymous principal, and any account's balance can be
|
|
16
|
+
read that way. Once the visitor signs in, the browser knows who they are, and
|
|
17
|
+
the page says whether the account is theirs.
|
|
18
|
+
|
|
19
|
+
The page takes care of five things:
|
|
20
|
+
|
|
21
|
+
- **One client per request.** Two visitors never share a cache.
|
|
22
|
+
- **The same keys on both sides.** One function builds the page's reads for
|
|
23
|
+
the server and for the browser, so the browser finds what the server read.
|
|
24
|
+
- **Exact amounts.** A balance crosses from the server to the browser as a
|
|
25
|
+
`bigint`, never as a rounded number.
|
|
26
|
+
- **A bad URL.** Text that is not a principal gets the not-found page, and
|
|
27
|
+
nothing is sent to the ledger.
|
|
28
|
+
- **Failures.** A ledger that does not answer is shown with the error's kind,
|
|
29
|
+
rendered on the server.
|
|
30
|
+
|
|
31
|
+
When it is done, the project holds these files beside the ones
|
|
32
|
+
`create-next-app` wrote:
|
|
33
|
+
|
|
34
|
+
<FileTree>
|
|
35
|
+
|
|
36
|
+
- icrc1.did the ledger's interface
|
|
37
|
+
- vitest.config.ts
|
|
38
|
+
- src/
|
|
39
|
+
- generated/
|
|
40
|
+
- icrc1.ts written by `meant gen`
|
|
41
|
+
- account.ts the page's reads, for the server and the browser
|
|
42
|
+
- account.test.ts
|
|
43
|
+
- server/
|
|
44
|
+
- request-client.ts
|
|
45
|
+
- app/
|
|
46
|
+
- layout.tsx
|
|
47
|
+
- providers.tsx
|
|
48
|
+
- accounts/
|
|
49
|
+
- \[owner\]/
|
|
50
|
+
- page.tsx
|
|
51
|
+
- components/
|
|
52
|
+
- Balance.tsx
|
|
53
|
+
- YourAccount.tsx
|
|
54
|
+
- CertifiedBalance.tsx
|
|
55
|
+
|
|
56
|
+
</FileTree>
|
|
57
|
+
|
|
58
|
+
## Before you start
|
|
59
|
+
|
|
60
|
+
Create the app. These flags give it a `src/` directory and the `@/*` alias
|
|
61
|
+
this guide imports with:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
npx create-next-app@latest my-app --ts --app --src-dir --import-alias "@/*" --yes
|
|
65
|
+
cd my-app
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`create-next-app` turns on Cache Components (`cacheComponents: true` in
|
|
69
|
+
`next.config.ts`). This guide is written for them.
|
|
70
|
+
|
|
71
|
+
1. Install the packages of
|
|
72
|
+
[Getting started, step 1](/v4/guides/getting-started/#1-install): the
|
|
73
|
+
core, React and Internet Identity packages, and the generator.
|
|
74
|
+
2. Install Vitest for the test in step 8. `create-next-app` pins
|
|
75
|
+
`@types/node` to version 20, which Vitest 5 does not accept, so update it
|
|
76
|
+
in the same command:
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
npm install --save-dev vitest @types/node@22
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
3. In `tsconfig.json`, set `"target"` to `"ES2022"`. `create-next-app` writes
|
|
83
|
+
`"ES2017"`, and TypeScript refuses a bigint literal such as `1n` below
|
|
84
|
+
ES2020.
|
|
85
|
+
4. Copy `icrc1.did` from the repository's
|
|
86
|
+
[`examples/icrc-ledger`](https://github.com/B3Pay/ic-reactor/tree/main/examples/icrc-ledger)
|
|
87
|
+
directory to the project's root, and generate its module:
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
npx @meantjs/cli gen icrc1.did -o src/generated
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## 1. One client per request
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
// src/server/request-client.ts
|
|
97
|
+
import { createClient, type Client } from "@ic-reactor/core"
|
|
98
|
+
import { cache } from "react"
|
|
99
|
+
|
|
100
|
+
/** This request's client: every Server Component of one request gets it. */
|
|
101
|
+
export const requestClient = cache((): Client =>
|
|
102
|
+
createClient({ network: "ic", identity: "anonymous" })
|
|
103
|
+
)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
React's `cache()` keeps a value for the length of one server request. Every
|
|
107
|
+
Server Component of a request gets the same client, and the next request gets
|
|
108
|
+
a new one. Never build a client at module scope on a server: every request
|
|
109
|
+
would share it, and its cache with it.
|
|
110
|
+
|
|
111
|
+
The client is anonymous, because a server holds no session, and an anonymous
|
|
112
|
+
client refuses every update before sending it. There is nothing to dispose:
|
|
113
|
+
it built no sign-in, and a server's `QueryClient` sets no timers. See
|
|
114
|
+
[SSR and hydration](/v4/guides/ssr/#one-client-per-request).
|
|
115
|
+
|
|
116
|
+
## 2. The provider
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
// src/app/providers.tsx
|
|
120
|
+
"use client"
|
|
121
|
+
|
|
122
|
+
import { createClient } from "@ic-reactor/core"
|
|
123
|
+
import { ReactorProvider } from "@ic-reactor/react"
|
|
124
|
+
import { AuthClient } from "@icp-sdk/auth/client"
|
|
125
|
+
import type { ReactNode } from "react"
|
|
126
|
+
|
|
127
|
+
export function Providers({ children }: { children: ReactNode }) {
|
|
128
|
+
return (
|
|
129
|
+
<ReactorProvider
|
|
130
|
+
client={() =>
|
|
131
|
+
createClient({
|
|
132
|
+
network: "ic",
|
|
133
|
+
auth: (network) => new AuthClient(network),
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
>
|
|
137
|
+
{children}
|
|
138
|
+
</ReactorProvider>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Replace the `src/app/layout.tsx` that `create-next-app` wrote:
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
// src/app/layout.tsx
|
|
147
|
+
import type { ReactNode } from "react"
|
|
148
|
+
import { Providers } from "@/app/providers"
|
|
149
|
+
|
|
150
|
+
export default function RootLayout({ children }: { children: ReactNode }) {
|
|
151
|
+
return (
|
|
152
|
+
<html lang="en">
|
|
153
|
+
<body>
|
|
154
|
+
<Providers>{children}</Providers>
|
|
155
|
+
</body>
|
|
156
|
+
</html>
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The layout is a Server Component, and a function cannot cross from a Server
|
|
162
|
+
Component into a client one, so the `client` factory lives in a module marked
|
|
163
|
+
`"use client"`. The provider calls the factory once for each request's server
|
|
164
|
+
render, and once in the browser tab. The `auth` factory runs only in the
|
|
165
|
+
browser.
|
|
166
|
+
|
|
167
|
+
## 3. The page's reads
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
// src/account.ts
|
|
171
|
+
import type { Principal } from "@meantjs/schema"
|
|
172
|
+
import type { Client } from "@ic-reactor/core"
|
|
173
|
+
import { actor, type Actor } from "@/generated/icrc1"
|
|
174
|
+
|
|
175
|
+
/** The ICP ledger on mainnet. */
|
|
176
|
+
export const LEDGER_ID = "ryjl3-tyaaa-aaaaa-aaaba-cai"
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* The reads of an account page. The server and the browser both build them
|
|
180
|
+
* here, so the browser asks for the very keys the server filled.
|
|
181
|
+
*/
|
|
182
|
+
export function accountReads(client: Client, owner: Principal) {
|
|
183
|
+
const ledger = client.canister<Actor>(actor, { id: LEDGER_ID })
|
|
184
|
+
return {
|
|
185
|
+
symbol: client.queryOptions(ledger, "icrc1_symbol"),
|
|
186
|
+
decimals: client.queryOptions(ledger, "icrc1_decimals"),
|
|
187
|
+
balance: client.queryOptions(ledger, "icrc1_balance_of", {
|
|
188
|
+
owner,
|
|
189
|
+
subaccount: null,
|
|
190
|
+
}),
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Reads an account into the client's cache. prefetchQuery never throws: a
|
|
196
|
+
* read that fails stays in the cache with its error.
|
|
197
|
+
*/
|
|
198
|
+
export async function prefetchAccount(client: Client, owner: Principal) {
|
|
199
|
+
const reads = accountReads(client, owner)
|
|
200
|
+
await Promise.all([
|
|
201
|
+
client.queryClient.prefetchQuery(reads.symbol),
|
|
202
|
+
client.queryClient.prefetchQuery(reads.decimals),
|
|
203
|
+
client.queryClient.prefetchQuery(reads.balance),
|
|
204
|
+
])
|
|
205
|
+
return reads
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
- The server builds the page's reads with `accountReads`, and so does the
|
|
210
|
+
component that shows them in the browser. The keys come from the client,
|
|
211
|
+
never from a string you wrote, so both sides ask for the same keys.
|
|
212
|
+
- Those keys hold the caller. The server reads as the anonymous principal, and
|
|
213
|
+
the browser's hydrating render is anonymous too, whoever is signed in, so the
|
|
214
|
+
browser finds the server's data.
|
|
215
|
+
- `prefetchAccount` reads the three into the client's cache.
|
|
216
|
+
`prefetchQuery` never throws, so a failed read stays in the cache with its
|
|
217
|
+
error, to be read back with `getQueryState`.
|
|
218
|
+
|
|
219
|
+
## 4. The page
|
|
220
|
+
|
|
221
|
+
```tsx
|
|
222
|
+
// src/app/accounts/[owner]/page.tsx
|
|
223
|
+
import { isPrincipal, principal } from "@meantjs/schema"
|
|
224
|
+
import { isReactorError } from "@ic-reactor/core"
|
|
225
|
+
import { dehydrate, HydrationBoundary } from "@tanstack/react-query"
|
|
226
|
+
import { notFound } from "next/navigation"
|
|
227
|
+
import { connection } from "next/server"
|
|
228
|
+
import { Suspense } from "react"
|
|
229
|
+
import { prefetchAccount } from "@/account"
|
|
230
|
+
import { Balance } from "@/components/Balance"
|
|
231
|
+
import { CertifiedBalance } from "@/components/CertifiedBalance"
|
|
232
|
+
import { YourAccount } from "@/components/YourAccount"
|
|
233
|
+
import { requestClient } from "@/server/request-client"
|
|
234
|
+
|
|
235
|
+
type Params = Promise<{ owner: string }>
|
|
236
|
+
|
|
237
|
+
export default function AccountPage({ params }: { params: Params }) {
|
|
238
|
+
return (
|
|
239
|
+
<main>
|
|
240
|
+
<h1>Account</h1>
|
|
241
|
+
<Suspense fallback={<p>Reading the account…</p>}>
|
|
242
|
+
<Account params={params} />
|
|
243
|
+
</Suspense>
|
|
244
|
+
</main>
|
|
245
|
+
)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async function Account({ params }: { params: Params }) {
|
|
249
|
+
// Read the ledger for each request: never once, kept for every visitor.
|
|
250
|
+
await connection()
|
|
251
|
+
// Anything can arrive in a URL: only principal text names an account.
|
|
252
|
+
const { owner: text } = await params
|
|
253
|
+
if (!isPrincipal(text)) notFound()
|
|
254
|
+
const owner = principal(text)
|
|
255
|
+
|
|
256
|
+
const client = requestClient()
|
|
257
|
+
const reads = await prefetchAccount(client, owner)
|
|
258
|
+
const failed = client.queryClient.getQueryState(reads.balance.queryKey)?.error
|
|
259
|
+
|
|
260
|
+
return (
|
|
261
|
+
<>
|
|
262
|
+
<p>
|
|
263
|
+
<code>{owner}</code>
|
|
264
|
+
</p>
|
|
265
|
+
<YourAccount owner={owner} />
|
|
266
|
+
{failed == null ? (
|
|
267
|
+
<HydrationBoundary state={dehydrate(client.queryClient)}>
|
|
268
|
+
<Balance owner={owner} />
|
|
269
|
+
</HydrationBoundary>
|
|
270
|
+
) : (
|
|
271
|
+
<p role="alert">
|
|
272
|
+
The ledger did not answer (
|
|
273
|
+
{isReactorError(failed) ? failed.kind : "failed"}).
|
|
274
|
+
</p>
|
|
275
|
+
)}
|
|
276
|
+
<Suspense fallback={<p>Certified balance: reading through consensus…</p>}>
|
|
277
|
+
<CertifiedBalance owner={owner} />
|
|
278
|
+
</Suspense>
|
|
279
|
+
</>
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
- **A shell, then the account.** Cache Components prerender the heading and
|
|
285
|
+
the fallback once, at build time. The account section renders for each
|
|
286
|
+
request and streams into the same response. Reading `params` outside a
|
|
287
|
+
`<Suspense>` fails the build ("prevents the route from being
|
|
288
|
+
prerendered").
|
|
289
|
+
- **`connection()`** says the section is rendered when a request comes in.
|
|
290
|
+
Without it, Next tries to prerender the section, and logs an error when the
|
|
291
|
+
agent reads the clock ("encountered the unstable value `Date.now()`").
|
|
292
|
+
- **A bad URL.** `isPrincipal` turns away anything that is not principal text,
|
|
293
|
+
before a call is made. The response is under way by then, so its status
|
|
294
|
+
stays 200. Next marks the not-found page `noindex`.
|
|
295
|
+
- **The hand-over.** `dehydrate(client.queryClient)` is plain JSON. The
|
|
296
|
+
client's `QueryClient` writes a `bigint` into it as tagged text and reads it
|
|
297
|
+
back exact in the browser.
|
|
298
|
+
- **A failure** stays on the server. TanStack Query dehydrates successful
|
|
299
|
+
reads only, so the page renders the error's kind itself, where
|
|
300
|
+
`isReactorError` can read it.
|
|
301
|
+
|
|
302
|
+
<Aside>
|
|
303
|
+
The account section is in the first response, but React's inline script is
|
|
304
|
+
what puts it on the screen. Without JavaScript, the fallback stays. For a page
|
|
305
|
+
that shows its data without JavaScript, or answers a bad principal with a 404,
|
|
306
|
+
turn Cache Components off and await the account in the page itself, as
|
|
307
|
+
[SSR and hydration](/v4/guides/ssr/#prefetch-and-hand-over) does.
|
|
308
|
+
</Aside>
|
|
309
|
+
|
|
310
|
+
## 5. The balance in the browser
|
|
311
|
+
|
|
312
|
+
```tsx
|
|
313
|
+
// src/components/Balance.tsx
|
|
314
|
+
"use client"
|
|
315
|
+
|
|
316
|
+
import type { Principal } from "@meantjs/schema"
|
|
317
|
+
import { formatUnits } from "@ic-reactor/core"
|
|
318
|
+
import { useClient } from "@ic-reactor/react"
|
|
319
|
+
import { useQuery } from "@tanstack/react-query"
|
|
320
|
+
import { accountReads } from "@/account"
|
|
321
|
+
|
|
322
|
+
export function Balance({ owner }: { owner: Principal }) {
|
|
323
|
+
const client = useClient()
|
|
324
|
+
const reads = accountReads(client, owner)
|
|
325
|
+
// The server has just read these: no read again on mount. A token's symbol
|
|
326
|
+
// and decimals never change; the balance is read again after a minute.
|
|
327
|
+
const symbol = useQuery({ ...reads.symbol, staleTime: Infinity })
|
|
328
|
+
const decimals = useQuery({ ...reads.decimals, staleTime: Infinity })
|
|
329
|
+
const balance = useQuery({ ...reads.balance, staleTime: 60_000 })
|
|
330
|
+
|
|
331
|
+
if (balance.isError) return <p role="alert">{balance.error.message}</p>
|
|
332
|
+
if (
|
|
333
|
+
symbol.data === undefined ||
|
|
334
|
+
decimals.data === undefined ||
|
|
335
|
+
balance.data === undefined
|
|
336
|
+
) {
|
|
337
|
+
return <p>Balance: …</p>
|
|
338
|
+
}
|
|
339
|
+
return (
|
|
340
|
+
<p>
|
|
341
|
+
Balance: {formatUnits(balance.data, decimals.data)} {symbol.data}
|
|
342
|
+
</p>
|
|
343
|
+
)
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
- TanStack Query's default `staleTime` is 0. Without one, each read the server
|
|
348
|
+
handed over would be stale on arrival, and read again as soon as the
|
|
349
|
+
component mounts. With these, the browser sends nothing on load. A minute
|
|
350
|
+
after the server's read, a remount or a refocused window reads the balance
|
|
351
|
+
again.
|
|
352
|
+
- After the visitor signs in, `useClient()` renders the component again for
|
|
353
|
+
the new caller, whose keys are empty. The balance shows `…` until it is read
|
|
354
|
+
as them. Nothing read anonymously is reused for a signed-in visitor.
|
|
355
|
+
- `formatUnits` shows base units as decimal text, never through `Number`. See
|
|
356
|
+
[Values and units](/v4/guides/values/#token-amounts).
|
|
357
|
+
|
|
358
|
+
## 6. Whose account it is
|
|
359
|
+
|
|
360
|
+
```tsx
|
|
361
|
+
// src/components/YourAccount.tsx
|
|
362
|
+
"use client"
|
|
363
|
+
|
|
364
|
+
import type { Principal } from "@meantjs/schema"
|
|
365
|
+
import { useAuth } from "@ic-reactor/react"
|
|
366
|
+
|
|
367
|
+
export function YourAccount({ owner }: { owner: Principal }) {
|
|
368
|
+
const { status, principal, signIn } = useAuth()
|
|
369
|
+
if (status === "signed-in") {
|
|
370
|
+
return principal === owner ? (
|
|
371
|
+
<p>This is your account.</p>
|
|
372
|
+
) : (
|
|
373
|
+
<p>
|
|
374
|
+
You are signed in as <code>{principal}</code>, another account.
|
|
375
|
+
</p>
|
|
376
|
+
)
|
|
377
|
+
}
|
|
378
|
+
return (
|
|
379
|
+
<button onClick={() => signIn().catch(console.error)}>
|
|
380
|
+
Sign in to see if this is you
|
|
381
|
+
</button>
|
|
382
|
+
)
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
`useAuth()` is `"anonymous"` on the server and in the browser's hydrating
|
|
387
|
+
render, whatever session the browser holds, so the HTML matches. Right after
|
|
388
|
+
hydration, the component renders again with the session, and the page says
|
|
389
|
+
whether the account is the visitor's. See
|
|
390
|
+
[The hydrating render](/v4/guides/ssr/#the-hydrating-render).
|
|
391
|
+
|
|
392
|
+
## 7. A certified balance, streamed
|
|
393
|
+
|
|
394
|
+
```tsx
|
|
395
|
+
// src/components/CertifiedBalance.tsx
|
|
396
|
+
import type { Principal } from "@meantjs/schema"
|
|
397
|
+
import { formatUnits, isReactorError } from "@ic-reactor/core"
|
|
398
|
+
import { LEDGER_ID } from "@/account"
|
|
399
|
+
import { actor, type Actor } from "@/generated/icrc1"
|
|
400
|
+
import { requestClient } from "@/server/request-client"
|
|
401
|
+
|
|
402
|
+
/** The balance read through consensus: a second or two on mainnet. */
|
|
403
|
+
export async function CertifiedBalance({ owner }: { owner: Principal }) {
|
|
404
|
+
const client = requestClient()
|
|
405
|
+
const { queryClient } = client
|
|
406
|
+
const ledger = client.canister<Actor>(actor, {
|
|
407
|
+
id: LEDGER_ID,
|
|
408
|
+
certified: true,
|
|
409
|
+
})
|
|
410
|
+
try {
|
|
411
|
+
const [balance, decimals, symbol] = await Promise.all([
|
|
412
|
+
queryClient.fetchQuery(
|
|
413
|
+
client.queryOptions(ledger, "icrc1_balance_of", {
|
|
414
|
+
owner,
|
|
415
|
+
subaccount: null,
|
|
416
|
+
})
|
|
417
|
+
),
|
|
418
|
+
queryClient.fetchQuery(client.queryOptions(ledger, "icrc1_decimals")),
|
|
419
|
+
queryClient.fetchQuery(client.queryOptions(ledger, "icrc1_symbol")),
|
|
420
|
+
])
|
|
421
|
+
return (
|
|
422
|
+
<p>
|
|
423
|
+
Certified balance: {formatUnits(balance, decimals)} {symbol}
|
|
424
|
+
</p>
|
|
425
|
+
)
|
|
426
|
+
} catch (error) {
|
|
427
|
+
return (
|
|
428
|
+
<p role="alert">
|
|
429
|
+
Certified balance: not read (
|
|
430
|
+
{isReactorError(error) ? error.kind : "failed"}).
|
|
431
|
+
</p>
|
|
432
|
+
)
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
- `certified: true` makes each read a replicated call, which goes through
|
|
438
|
+
consensus: a second or two on mainnet. Its keys are its own, ending in
|
|
439
|
+
`"certified"`, so an uncertified answer is never served for it.
|
|
440
|
+
- The page renders it inside its own `<Suspense>`, so the rest of the account
|
|
441
|
+
does not wait for it.
|
|
442
|
+
- `requestClient()` returns the client the page used, because it is the same
|
|
443
|
+
request.
|
|
444
|
+
- It is an awaited Server Component, so a failure is rendered with its kind
|
|
445
|
+
here, on the server.
|
|
446
|
+
|
|
447
|
+
## 8. Test the hand-over
|
|
448
|
+
|
|
449
|
+
Vitest needs the `@/` alias that Next.js resolves:
|
|
450
|
+
|
|
451
|
+
```ts
|
|
452
|
+
// vitest.config.ts
|
|
453
|
+
import { fileURLToPath } from "node:url"
|
|
454
|
+
import { defineConfig } from "vitest/config"
|
|
455
|
+
|
|
456
|
+
export default defineConfig({
|
|
457
|
+
// The same `@/` that Next.js resolves to src/.
|
|
458
|
+
resolve: { alias: { "@": fileURLToPath(new URL("./src", import.meta.url)) } },
|
|
459
|
+
})
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
```ts
|
|
463
|
+
// src/account.test.ts
|
|
464
|
+
import { principal } from "@meantjs/schema"
|
|
465
|
+
import { createTestClient } from "@ic-reactor/core/testing"
|
|
466
|
+
import { dehydrate, hydrate } from "@tanstack/react-query"
|
|
467
|
+
import { afterEach, expect, it } from "vitest"
|
|
468
|
+
import { accountReads, LEDGER_ID, prefetchAccount } from "@/account"
|
|
469
|
+
import { actor, type Actor } from "@/generated/icrc1"
|
|
470
|
+
|
|
471
|
+
const owner = principal("rkp4c-7iaaa-aaaaa-aaaca-cai")
|
|
472
|
+
const balance = 2n ** 70n // more than a Number holds exactly
|
|
473
|
+
|
|
474
|
+
// A client over an in-memory replica, with the ledger mocked: one for the
|
|
475
|
+
// server's request and one for the browser tab, as the app has.
|
|
476
|
+
const clients: ReturnType<typeof createTestClient>[] = []
|
|
477
|
+
function side(signedIn: boolean) {
|
|
478
|
+
const test = createTestClient({ signedIn })
|
|
479
|
+
test.mock<Actor>(actor, LEDGER_ID, {
|
|
480
|
+
icrc1_symbol: () => "ICP",
|
|
481
|
+
icrc1_decimals: () => 8,
|
|
482
|
+
icrc1_balance_of: () => balance,
|
|
483
|
+
})
|
|
484
|
+
clients.push(test)
|
|
485
|
+
return test
|
|
486
|
+
}
|
|
487
|
+
afterEach(() => {
|
|
488
|
+
for (const test of clients.splice(0)) test.client.dispose()
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
/** What the page sends the browser: the server's cache, as JSON. */
|
|
492
|
+
async function serverRender() {
|
|
493
|
+
const server = side(false)
|
|
494
|
+
await prefetchAccount(server.client, owner)
|
|
495
|
+
return JSON.parse(JSON.stringify(dehydrate(server.client.queryClient)))
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
it("hands the balance to the browser exactly, and the browser reads nothing", async () => {
|
|
499
|
+
const state = await serverRender()
|
|
500
|
+
const browser = side(false)
|
|
501
|
+
hydrate(browser.client.queryClient, state)
|
|
502
|
+
|
|
503
|
+
const reads = accountReads(browser.client, owner)
|
|
504
|
+
expect(browser.client.queryClient.getQueryData(reads.balance.queryKey)).toBe(
|
|
505
|
+
balance
|
|
506
|
+
)
|
|
507
|
+
expect(browser.requests).toHaveLength(0)
|
|
508
|
+
})
|
|
509
|
+
|
|
510
|
+
it("reads again as a signed-in visitor: nothing read anonymously is reused", async () => {
|
|
511
|
+
const state = await serverRender()
|
|
512
|
+
const browser = side(true)
|
|
513
|
+
hydrate(browser.client.queryClient, state)
|
|
514
|
+
|
|
515
|
+
const reads = accountReads(browser.client, owner)
|
|
516
|
+
const { queryClient } = browser.client
|
|
517
|
+
expect(queryClient.getQueryData(reads.balance.queryKey)).toBeUndefined()
|
|
518
|
+
expect(await queryClient.fetchQuery(reads.balance)).toBe(balance)
|
|
519
|
+
})
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
```sh
|
|
523
|
+
npx vitest run
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
- Each side is a real client over an in-memory replica, with the ledger
|
|
527
|
+
mocked. The server's state goes through `JSON.stringify` and `JSON.parse`,
|
|
528
|
+
as it does on its way to the browser.
|
|
529
|
+
- `2n ** 70n` is more than a `Number` holds exactly, and it arrives exact.
|
|
530
|
+
- An anonymous browser sends nothing. A signed-in one finds no data under its
|
|
531
|
+
own keys, and reads the balance again.
|
|
532
|
+
|
|
533
|
+
## 9. Run it
|
|
534
|
+
|
|
535
|
+
```sh
|
|
536
|
+
npm run dev
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
Open `http://localhost:3000/accounts/rkp4c-7iaaa-aaaaa-aaaca-cai`, the
|
|
540
|
+
account of the cycles minting canister. The balance shows first, and the
|
|
541
|
+
certified balance a second or two later. In the network panel, the browser
|
|
542
|
+
sends no request to the IC for the page. Then try
|
|
543
|
+
`http://localhost:3000/accounts/not-a-principal`.
|
|
544
|
+
|
|
545
|
+
## Next
|
|
546
|
+
|
|
547
|
+
- [Next.js SSR example](/v4/examples/next-ssr/): three ledgers, a lookup
|
|
548
|
+
form, a Route Handler, and tests of the hydration itself.
|
|
549
|
+
- [SSR and hydration](/v4/guides/ssr/): every rule this page follows, and what
|
|
550
|
+
a signed-in reload costs.
|
|
551
|
+
- [Build an ICRC-1 wallet](/v4/build/icrc1-wallet/): sign in and send a
|
|
552
|
+
transfer that is never paid twice.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Canister Studio"
|
|
3
|
+
description: Automatic forms and safe calls for any mainnet canister, server-rendered with TanStack Start, on ic-reactor 4 and Meant
|
|
4
|
+
editUrl: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
import { CardGrid, LinkCard } from "@astrojs/starlight/components"
|
|
8
|
+
|
|
9
|
+
A TanStack Start app, rendered on the server, built on `@ic-reactor/core`,
|
|
10
|
+
`@ic-reactor/react` and `@ic-reactor/vite-plugin` with TanStack Query's own
|
|
11
|
+
hooks. It gives every method of any canister on mainnet a form built from its
|
|
12
|
+
Candid, and calls it with every rule of ic-reactor 4 in view:
|
|
13
|
+
|
|
14
|
+
- **Typed canisters.** The ICP ledger, the ckBTC and ckETH ledgers and the ckBTC
|
|
15
|
+
minter come from three modules that the Vite plugin generates from committed
|
|
16
|
+
`.did` files with `meant gen`. The wallet page calls them through the
|
|
17
|
+
generated types, with no cast.
|
|
18
|
+
- **Any canister, read live.** Open any mainnet canister id: a server function
|
|
19
|
+
reads its `candid:service` metadata and module hash in one certified
|
|
20
|
+
`read_state`, compiles the interface with `@meantjs/cli` in a worker
|
|
21
|
+
thread with a deadline, and caches it by module hash. The browser rebuilds
|
|
22
|
+
the actor from the compiled envelope with `schemaFromContract`. An
|
|
23
|
+
interface read from the uncertified `__get_candid_interface_tmp_hack` query
|
|
24
|
+
is labelled so, and a certificate that fails to verify, or leaves the
|
|
25
|
+
metadata unproven, is never followed by a fallback.
|
|
26
|
+
- **Automatic forms.** A field per Candid type: amounts in token units read
|
|
27
|
+
with `parseUnits`, principals checked as you type, blobs as hex, text or
|
|
28
|
+
base64, and variants, options, vectors and records, with `created_at_time`
|
|
29
|
+
set to now for ICRC deduplication. The submit button names what is wrong,
|
|
30
|
+
and the issues of an `invalid_args` refusal land on their fields.
|
|
31
|
+
- **Server rendering.** One client per request on the server and one per tab,
|
|
32
|
+
made by the router. Loaders prefetch mainnet reads and never throw, the
|
|
33
|
+
browser hydrates them without reading again, and a failed read is never
|
|
34
|
+
sent to the browser, which reads it itself and gets the full
|
|
35
|
+
`ReactorError`. A shared query link, a method and its arguments as hex
|
|
36
|
+
Candid, renders its result in the server's HTML.
|
|
37
|
+
- **Safe writes.** Signed out, a write is disabled and says why. Signed in, a
|
|
38
|
+
confirm step shows the sender, the target, the method, the Candid text and
|
|
39
|
+
the sha256 of the exact argument bytes. A write is sent once and never
|
|
40
|
+
retried. A failure shows its `kind`, its code and whether it may have
|
|
41
|
+
executed, and after an unknown outcome `client.resendOf` offers the same
|
|
42
|
+
call again, deduplicated by `created_at_time`.
|
|
43
|
+
- **Reads.** Certified reads under keys of their own, the live query key with
|
|
44
|
+
its caller segment, and the ckBTC minter's `get_btc_address`, an update,
|
|
45
|
+
read once per caller through `{ update: "idempotent" }`.
|
|
46
|
+
- **The Safety lab.** Ten scenarios that `createTestClient()` runs in the
|
|
47
|
+
browser against a mocked ICRC-1 ledger: an anonymous write refused before
|
|
48
|
+
sending, arguments that do not encode, a lost reply and its deduplicated
|
|
49
|
+
re-send, an HTTP 429 the client sends again by itself, canister rejects, a
|
|
50
|
+
typed `Err`, a caller that changes, cache isolation and certified reads.
|
|
51
|
+
Each shows its request log and the error's fields.
|
|
52
|
+
- **The playground and the interface tools.** Paste a `.did` and compile it
|
|
53
|
+
in the browser with the compiler's lazily loaded WASM; for any canister, get
|
|
54
|
+
its Candid, its TypeScript module, a projection to the methods you choose,
|
|
55
|
+
and a check of a written `.did` against the live one.
|
|
56
|
+
|
|
57
|
+
The guides it shows at work: [The client](/v4/guides/client/) and
|
|
58
|
+
[SSR and hydration](/v4/guides/ssr/) (a client per request, prefetch and
|
|
59
|
+
hydration), [Reads](/v4/guides/reads/), [Writes](/v4/guides/writes/) and
|
|
60
|
+
[Errors and mayHaveExecuted](/v4/guides/errors/) (every call),
|
|
61
|
+
[Values and units](/v4/guides/values/) (the forms and the replies),
|
|
62
|
+
[Auth](/v4/guides/auth/) (Internet Identity), [Testing](/v4/guides/testing/)
|
|
63
|
+
(the Safety lab and the tests) and [The Vite plugin](/v4/guides/vite-plugin/)
|
|
64
|
+
(the typed modules).
|
|
65
|
+
|
|
66
|
+
The tests run the real client on `createTestClient()` from
|
|
67
|
+
`@ic-reactor/core/testing`, with each canister mocked at its mainnet id and
|
|
68
|
+
the interface loader given a fetcher of the test's own, and never reach
|
|
69
|
+
mainnet. The app itself calls mainnet: sign-in is mainnet's Internet
|
|
70
|
+
Identity, and a transfer you confirm moves real tokens.
|
|
71
|
+
|
|
72
|
+
StackBlitz installs the example from npm and starts its dev server
|
|
73
|
+
(`npm run dev`). The home page renders there on the server with its mainnet
|
|
74
|
+
reads, because its loader calls no server function. TanStack Start's server
|
|
75
|
+
functions do not run there: they keep each request in Node's
|
|
76
|
+
`AsyncLocalStorage`, which StackBlitz does not implement. The typed canisters
|
|
77
|
+
need none to load and to call. Any other canister opened from inside the app
|
|
78
|
+
is read and compiled in the browser instead, with the compiler's lazily
|
|
79
|
+
loaded WASM, and so is the live side of a pasted `.did` check. A projection,
|
|
80
|
+
the TypeScript module of a canister read live and the check of a typed
|
|
81
|
+
canister's committed `.did` run on the studio's server only, and say so
|
|
82
|
+
there. Clone the repository to run the server path.
|
|
83
|
+
|
|
84
|
+
<CardGrid>
|
|
85
|
+
<LinkCard
|
|
86
|
+
title="Open in StackBlitz"
|
|
87
|
+
description="Edit and run in your browser"
|
|
88
|
+
href="https://stackblitz.com/github/b3pay/ic-reactor/tree/main/examples/canister-studio?file=src/routes/index.tsx"
|
|
89
|
+
/>
|
|
90
|
+
<LinkCard
|
|
91
|
+
title="View on GitHub"
|
|
92
|
+
description="Browse the source code"
|
|
93
|
+
href="https://github.com/b3pay/ic-reactor/tree/main/examples/canister-studio"
|
|
94
|
+
/>
|
|
95
|
+
</CardGrid>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "ICRC-1 ledger"
|
|
3
|
+
description: Mainnet ICP ledger reads and a fault-injection transfer sandbox on ic-reactor 4
|
|
4
|
+
editUrl: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
import { CardGrid, LinkCard } from "@astrojs/starlight/components"
|
|
8
|
+
|
|
9
|
+
An explorer for an ICRC-1 ledger, built on `@ic-reactor/core`,
|
|
10
|
+
`@ic-reactor/react` and `@ic-reactor/vite-plugin` with TanStack Query's own
|
|
11
|
+
hooks.
|
|
12
|
+
|
|
13
|
+
- **Mainnet:** a client built with `createClient({ network: "ic", identity: "anonymous" })`
|
|
14
|
+
reads the ICP ledger: name, symbol, decimals, fee, total supply, metadata,
|
|
15
|
+
the minting account and the balance of a principal you type. It also reads
|
|
16
|
+
the block log, following the archive callbacks the ledger's reply carries
|
|
17
|
+
with `client.func`. Certified reads can be switched on.
|
|
18
|
+
- **Sandbox:** `createTestClient()` from `@ic-reactor/core/testing` runs a real
|
|
19
|
+
client against an in-memory replica with a mocked ledger. Sign in, switch
|
|
20
|
+
accounts, and send transfers with a fault armed (a canister reject, a lost
|
|
21
|
+
reply, HTTP 429) to see what the client reports: whether the transfer may
|
|
22
|
+
have executed, the re-read of the balance, and the single re-send after a
|
|
23
|
+
failure that proves the transfer never arrived.
|
|
24
|
+
|
|
25
|
+
The generated modules come from the ledger's `.did` files through the Vite
|
|
26
|
+
plugin, which runs `meant gen`.
|
|
27
|
+
|
|
28
|
+
The guides this example shows at work: [Reads](/v4/guides/reads/) (the
|
|
29
|
+
balance, certified reads), [The client](/v4/guides/client/) (`client.func` for
|
|
30
|
+
archive callbacks), [Writes](/v4/guides/writes/) and
|
|
31
|
+
[Errors and mayHaveExecuted](/v4/guides/errors/) (the transfer and its
|
|
32
|
+
faults), and [Testing](/v4/guides/testing/) (the sandbox).
|
|
33
|
+
|
|
34
|
+
<CardGrid>
|
|
35
|
+
<LinkCard
|
|
36
|
+
title="Open in StackBlitz"
|
|
37
|
+
description="Edit and run in your browser"
|
|
38
|
+
href="https://stackblitz.com/github/b3pay/ic-reactor/tree/main/examples/icrc-ledger?file=src/App.tsx"
|
|
39
|
+
/>
|
|
40
|
+
<LinkCard
|
|
41
|
+
title="View on GitHub"
|
|
42
|
+
description="Browse the source code"
|
|
43
|
+
href="https://github.com/b3pay/ic-reactor/tree/main/examples/icrc-ledger"
|
|
44
|
+
/>
|
|
45
|
+
</CardGrid>
|