@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,62 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest"
|
|
2
|
+
import { SEED_2 } from "./sandbox.ts"
|
|
3
|
+
import { readTransferForm, type TransferForm } from "./transfer-form.ts"
|
|
4
|
+
|
|
5
|
+
const form = (overrides: Partial<TransferForm> = {}): TransferForm => ({
|
|
6
|
+
to: SEED_2,
|
|
7
|
+
amount: "1.5",
|
|
8
|
+
fee: "",
|
|
9
|
+
...overrides,
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
describe("reading the transfer form", () => {
|
|
13
|
+
it("makes the exact argument: base units, the ledger's fee, the memo, created_at_time in ns", () => {
|
|
14
|
+
const memo = new Uint8Array(16).fill(7)
|
|
15
|
+
expect(
|
|
16
|
+
readTransferForm(form({ to: ` ${SEED_2} ` }), 8, 1_700_000_000_000, memo)
|
|
17
|
+
).toEqual({
|
|
18
|
+
ok: true,
|
|
19
|
+
arg: {
|
|
20
|
+
to: { owner: SEED_2, subaccount: null },
|
|
21
|
+
amount: 150_000_000n,
|
|
22
|
+
fee: null,
|
|
23
|
+
memo,
|
|
24
|
+
from_subaccount: null,
|
|
25
|
+
created_at_time: 1_700_000_000_000_000_000n,
|
|
26
|
+
},
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it("gives each transfer its own 16-byte memo, even in the same millisecond", () => {
|
|
31
|
+
const first = readTransferForm(form(), 8, 1_700_000_000_000)
|
|
32
|
+
const second = readTransferForm(form(), 8, 1_700_000_000_000)
|
|
33
|
+
if (!first.ok || !second.ok) throw new Error("refused")
|
|
34
|
+
expect(first.arg.memo).toHaveLength(16)
|
|
35
|
+
expect(second.arg.memo).toHaveLength(16)
|
|
36
|
+
expect(second.arg.memo).not.toEqual(first.arg.memo)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it("keeps a typed fee, also exactly", () => {
|
|
40
|
+
const read = readTransferForm(form({ amount: "0.29", fee: "0.0001" }), 8)
|
|
41
|
+
expect(read.ok && [read.arg.amount, read.arg.fee]).toEqual([
|
|
42
|
+
29_000_000n,
|
|
43
|
+
10_000n,
|
|
44
|
+
])
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it.each([
|
|
48
|
+
["to", form({ to: "not a principal" })],
|
|
49
|
+
["to", form({ to: SEED_2.toUpperCase() })],
|
|
50
|
+
["amount", form({ amount: "" })],
|
|
51
|
+
["amount", form({ amount: "1e3" })],
|
|
52
|
+
["amount", form({ amount: "1,5" })],
|
|
53
|
+
["amount", form({ amount: "-1" })],
|
|
54
|
+
["amount", form({ amount: "3.141592653" })],
|
|
55
|
+
["amount", form({ amount: "0" })],
|
|
56
|
+
["fee", form({ fee: "ten" })],
|
|
57
|
+
] as const)("refuses the %s field of %j", (field, typed) => {
|
|
58
|
+
const read = readTransferForm(typed, 8)
|
|
59
|
+
expect(read.ok).toBe(false)
|
|
60
|
+
expect(!read.ok && read.field).toBe(field)
|
|
61
|
+
})
|
|
62
|
+
})
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// Turns what a person typed into an ICRC-1 transfer, or refuses it. Nothing
|
|
2
|
+
// here guesses: a principal must be canonical text, and an amount must be a
|
|
3
|
+
// plain decimal the token's decimals can hold exactly.
|
|
4
|
+
import { isPrincipal, principal } from "@meantjs/schema"
|
|
5
|
+
import { parseUnits } from "@ic-reactor/core"
|
|
6
|
+
import type { TransferArg } from "./canisters/icrc1.ts"
|
|
7
|
+
|
|
8
|
+
export interface TransferForm {
|
|
9
|
+
/** The recipient's principal. */
|
|
10
|
+
readonly to: string
|
|
11
|
+
/** The amount, in tokens: "1.5". */
|
|
12
|
+
readonly amount: string
|
|
13
|
+
/** An explicit fee in tokens, or "" to let the ledger charge its own. */
|
|
14
|
+
readonly fee: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type ReadTransfer =
|
|
18
|
+
| { readonly ok: true; readonly arg: TransferArg }
|
|
19
|
+
| {
|
|
20
|
+
readonly ok: false
|
|
21
|
+
readonly field: keyof TransferForm
|
|
22
|
+
readonly reason: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** The amount `text` stands for, in base units, or why it is refused. */
|
|
26
|
+
function readAmount(
|
|
27
|
+
text: string,
|
|
28
|
+
decimals: number
|
|
29
|
+
): { ok: true; units: bigint } | { ok: false; reason: string } {
|
|
30
|
+
try {
|
|
31
|
+
return { ok: true, units: parseUnits(text, decimals) }
|
|
32
|
+
} catch (error) {
|
|
33
|
+
if (error instanceof RangeError) {
|
|
34
|
+
return {
|
|
35
|
+
ok: false,
|
|
36
|
+
reason: text.trim().startsWith("-")
|
|
37
|
+
? "An amount cannot be negative."
|
|
38
|
+
: `At most ${decimals} decimals.`,
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
ok: false,
|
|
43
|
+
reason:
|
|
44
|
+
'Write plain digits with at most one "." (no exponent, grouping or sign).',
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The `icrc1_transfer` argument for `form`, or the first field that is
|
|
51
|
+
* refused. `nowMs` becomes `created_at_time`, so that sending the same
|
|
52
|
+
* argument twice is answered `Duplicate` instead of moving the funds twice.
|
|
53
|
+
*
|
|
54
|
+
* `memo` is this transfer's own, 16 random bytes: the ledger takes two
|
|
55
|
+
* arguments for one only when every field matches, so two different transfers
|
|
56
|
+
* of the same amount to the same account made in the same millisecond are not
|
|
57
|
+
* taken for each other's `Duplicate`. Read the form once per transfer, and
|
|
58
|
+
* send the argument it gave again, memo included, to re-send that transfer.
|
|
59
|
+
*/
|
|
60
|
+
export function readTransferForm(
|
|
61
|
+
form: TransferForm,
|
|
62
|
+
decimals: number,
|
|
63
|
+
nowMs: number = Date.now(),
|
|
64
|
+
memo: Uint8Array = newMemo()
|
|
65
|
+
): ReadTransfer {
|
|
66
|
+
const to = form.to.trim()
|
|
67
|
+
if (!isPrincipal(to)) {
|
|
68
|
+
return { ok: false, field: "to", reason: "Not a principal." }
|
|
69
|
+
}
|
|
70
|
+
const amount = readAmount(form.amount, decimals)
|
|
71
|
+
if (!amount.ok) return { ok: false, field: "amount", reason: amount.reason }
|
|
72
|
+
if (amount.units === 0n) {
|
|
73
|
+
return { ok: false, field: "amount", reason: "Send more than zero." }
|
|
74
|
+
}
|
|
75
|
+
let fee: bigint | null = null
|
|
76
|
+
if (form.fee.trim() !== "") {
|
|
77
|
+
const read = readAmount(form.fee, decimals)
|
|
78
|
+
if (!read.ok) return { ok: false, field: "fee", reason: read.reason }
|
|
79
|
+
fee = read.units
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
ok: true,
|
|
83
|
+
arg: {
|
|
84
|
+
to: { owner: principal(to), subaccount: null },
|
|
85
|
+
amount: amount.units,
|
|
86
|
+
fee,
|
|
87
|
+
memo,
|
|
88
|
+
from_subaccount: null,
|
|
89
|
+
created_at_time: BigInt(nowMs) * 1_000_000n,
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** A memo of its own for one transfer: 16 bytes from `crypto.getRandomValues`. */
|
|
95
|
+
export function newMemo(): Uint8Array {
|
|
96
|
+
return crypto.getRandomValues(new Uint8Array(16))
|
|
97
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"noUncheckedIndexedAccess": true,
|
|
10
|
+
"noEmit": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"isolatedModules": true,
|
|
13
|
+
"verbatimModuleSyntax": true,
|
|
14
|
+
"erasableSyntaxOnly": true,
|
|
15
|
+
"allowImportingTsExtensions": true,
|
|
16
|
+
"types": ["vite/client", "node"]
|
|
17
|
+
},
|
|
18
|
+
"include": ["src", "scripts", "vite.config.ts", "vitest.config.ts"]
|
|
19
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { icReactor } from "@ic-reactor/vite-plugin"
|
|
2
|
+
import react from "@vitejs/plugin-react"
|
|
3
|
+
import { defineConfig } from "vite"
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [
|
|
7
|
+
react(),
|
|
8
|
+
// Writes src/canisters/<name>.ts (and its envelope) from each .did when
|
|
9
|
+
// `vite dev` or `vite build` starts, and again when a .did changes. The
|
|
10
|
+
// files are committed too, so `pnpm gen:check` can fail a stale copy.
|
|
11
|
+
icReactor({
|
|
12
|
+
canisters: {
|
|
13
|
+
// Any ICRC-1 ledger: the ICP ledger, ckBTC, a pasted id.
|
|
14
|
+
icrc1: { didFile: "icrc1.did", outDir: "src/canisters" },
|
|
15
|
+
// The next two are projections of mainnet canisters' interfaces to
|
|
16
|
+
// the methods the app calls, and every type they reach. They are
|
|
17
|
+
// committed, so the plugin reads them and fetches nothing: builds
|
|
18
|
+
// work offline. `IC_REACTOR_FETCH=<name>` fetches and projects one
|
|
19
|
+
// again, and `IC_REACTOR_VERIFY=1` checks both against the live
|
|
20
|
+
// canisters.
|
|
21
|
+
// The ICP ledger's own block reads, with their archive callbacks.
|
|
22
|
+
icp_ledger: {
|
|
23
|
+
didFile: "icp_ledger.did",
|
|
24
|
+
outDir: "src/canisters",
|
|
25
|
+
canisterId: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
26
|
+
methods: ["query_blocks"],
|
|
27
|
+
},
|
|
28
|
+
// The ckBTC minter's get_btc_address, an update read as a query.
|
|
29
|
+
ckbtc_minter: {
|
|
30
|
+
didFile: "ckbtc_minter.did",
|
|
31
|
+
outDir: "src/canisters",
|
|
32
|
+
canisterId: "mqygn-kiaaa-aaaar-qaadq-cai",
|
|
33
|
+
methods: ["get_btc_address"],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
// Both tabs talk to a replica of their own (mainnet, or the fake one in
|
|
37
|
+
// the page), so there is no local network to ask `icp` about.
|
|
38
|
+
injectEnvironment: false,
|
|
39
|
+
}),
|
|
40
|
+
],
|
|
41
|
+
server: { port: 5173 },
|
|
42
|
+
// The IC agent, with its BLS certificate check, is most of the main chunk.
|
|
43
|
+
build: { chunkSizeWarningLimit: 600 },
|
|
44
|
+
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from "vitest/config"
|
|
2
|
+
|
|
3
|
+
// The tests run over the committed generated module (`pnpm gen:check` keeps it
|
|
4
|
+
// current), so they need neither the React plugin nor the generator. The
|
|
5
|
+
// sandbox's own tests run in Node; a `.test.tsx` renders the page in jsdom.
|
|
6
|
+
//
|
|
7
|
+
// package.json pins jsdom to 30.0.1: jsdom 30.1 subclasses the global
|
|
8
|
+
// `Iterator`, which StackBlitz's WebContainer does not define, so there a jsdom
|
|
9
|
+
// test fails to start with "ReferenceError: Iterator is not defined".
|
|
10
|
+
export default defineConfig({
|
|
11
|
+
test: { environment: "node", include: ["src/**/*.test.{ts,tsx}"] },
|
|
12
|
+
})
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Next.js SSR on ic-reactor 4
|
|
2
|
+
|
|
3
|
+
A Next.js App Router app (Next 16, React 19) that reads three mainnet ICRC-1
|
|
4
|
+
ledgers (ICP, ckBTC and ckETH) on the server with `@ic-reactor/core`, hands
|
|
5
|
+
its cache to the browser, and reads again in the browser as whoever signs in
|
|
6
|
+
with Internet Identity there. One generated module,
|
|
7
|
+
`src/canisters/icrc1.ts`, serves every ledger.
|
|
8
|
+
|
|
9
|
+
## Scenarios
|
|
10
|
+
|
|
11
|
+
Each scenario lives in its own small file, whose header comment names the
|
|
12
|
+
rule it shows. Every one is tested (`pnpm test`), and every one shows on a
|
|
13
|
+
running server.
|
|
14
|
+
|
|
15
|
+
| # | Scenario | Files | How to see it |
|
|
16
|
+
| --- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- |
|
|
17
|
+
| 1 | One client per request on the server; prefetch by `{ id }`; `dehydrate` | `src/server/request-client.ts`, `src/server/prefetch-ledgers.ts`, `src/app/page.tsx` | `/`: each card says when the server read it |
|
|
18
|
+
| 2 | `ReactorProvider` factory in a `'use client'` module; nothing refetched | `src/app/providers.tsx`, `src/components/server-data.ts` | `/` with the network panel open: no request to `icp-api.io` until you ask for one |
|
|
19
|
+
| 3 | Lossless hydration of `bigint`, principals and `Uint8Array` | `src/components/LedgerCard.tsx` | the run-time type after each value; mainnet returns no blob here, the tests' mocks do |
|
|
20
|
+
| 4 | Renders with JavaScript disabled | `scripts/smoke.ts` | turn JavaScript off and reload `/` |
|
|
21
|
+
| 5 | Streaming with Suspense: certified balances arrive after the page | `src/app/account/CertifiedBalances.tsx` | `/account?owner=rkp4c-7iaaa-aaaaa-aaaca-cai` |
|
|
22
|
+
| 6 | Progressive enhancement: a GET form, validated on the server | `src/app/account/page.tsx`, `src/server/parse-owner.ts` | look up with JavaScript on and off; `/account?owner=not-a-principal` |
|
|
23
|
+
| 7 | Route Handler: a client per request, amounts as text, kind as HTTP status | `src/app/api/balance/[ledger]/[principal]/route.ts`, `src/server/balance-route.ts` | `/api/balance/ckBTC/rkp4c-7iaaa-aaaaa-aaaca-cai`; a bad principal is a 400 |
|
|
24
|
+
| 8 | Errors on the server: one section fails with its `kind`, not the page | `src/components/LedgerError.tsx`, `src/server/error-summary.ts` | `/`: the "NNS governance (not a ledger)" section |
|
|
25
|
+
| 9 | Sign in after hydration: the new caller's keys, nothing anonymous reused | `src/components/MyBalances.tsx`, `src/components/LedgerCard.tsx` | sign in with Internet Identity: "My balances" loads, each card reads again as you |
|
|
26
|
+
| 10 | A reload while signed in: hydrated from the server's data, then read as you | `src/app/providers.tsx`, `src/components/LedgerCard.tsx` | sign in, then reload `/`: no hydration error, then each card reads again as you |
|
|
27
|
+
|
|
28
|
+
## Run it
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
pnpm install && pnpm build # once, at the repository root: the workspace packages
|
|
32
|
+
cd examples/next-ssr
|
|
33
|
+
pnpm dev # http://localhost:3001
|
|
34
|
+
pnpm build && pnpm start # http://localhost:3011
|
|
35
|
+
pnpm smoke # checks the running start server against mainnet; Node 22.18+
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
To see scenario 4, turn JavaScript off (Chrome DevTools: the command menu,
|
|
39
|
+
"Disable JavaScript") and reload `/` or `/account?owner=...`: every value is
|
|
40
|
+
there, and the certified section shows its fallback, which says why.
|
|
41
|
+
|
|
42
|
+
The route of scenario 7 answers a failure with a status that says whether
|
|
43
|
+
asking again can help. A canister id that names no canister,
|
|
44
|
+
`/api/balance/2y4s5-zaaaa-aaad7-7777q-cai/rkp4c-7iaaa-aaaaa-aaaca-cai`, is a
|
|
45
|
+
502 with `kind: "not_delivered"`, `httpStatus: 400` and
|
|
46
|
+
`code: "canister_not_found"`: the IC refused it for good. A rate limit or a
|
|
47
|
+
5xx from the IC is a 503.
|
|
48
|
+
|
|
49
|
+
The pages read mainnet when a request comes in, never during `next build`
|
|
50
|
+
(`/` calls `connection()`; `/account` and the route read their parameters), so
|
|
51
|
+
a build needs no network.
|
|
52
|
+
|
|
53
|
+
## Test it
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
pnpm test # vitest; no test reaches mainnet
|
|
57
|
+
pnpm typecheck
|
|
58
|
+
pnpm gen:check # fails if src/canisters/ is stale
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The tests run the real client on `createTestClient()` from
|
|
62
|
+
`@ic-reactor/core/testing`, over in-memory replicas that mock the ledgers at
|
|
63
|
+
their mainnet ids (`src/testing/mock-ledgers.ts`). A test builds one client
|
|
64
|
+
for the server's request, one for the server render of the client components
|
|
65
|
+
and one for the browser tab, as the app has, and reads each replica's request
|
|
66
|
+
log to tell which side sent what:
|
|
67
|
+
|
|
68
|
+
- `src/server/*.test.ts`: the prefetch, its JSON round trip, the account
|
|
69
|
+
reads, the owner parameter and the route handler.
|
|
70
|
+
- `src/server/request-client.rsc.test.tsx`: `/account` rendered by React's
|
|
71
|
+
Flight server with the `react-server` condition, as Next renders Server
|
|
72
|
+
Components, so React's `cache()` memoizes as in a request: one client
|
|
73
|
+
serves the page and its streamed section, and the next request gets a new
|
|
74
|
+
one. It runs in vitest's `react-server` project (`vitest.config.ts`).
|
|
75
|
+
- `src/components/hydration.test.tsx`: the home page rendered to HTML, read
|
|
76
|
+
with no script run, hydrated without a mismatch or a request, then signed
|
|
77
|
+
in; and hydrated in a tab that is still signed in, without a mismatch, then
|
|
78
|
+
read as the user.
|
|
79
|
+
- `src/components/MyBalances.test.tsx`: sign-in, a switch of account,
|
|
80
|
+
sign-out, and a ledger whose decimals or symbol read fails.
|
|
81
|
+
- `src/components/LedgerCard.test.tsx`: a card whose reads fail in the tab.
|
|
82
|
+
- `src/app/providers*.test.tsx`: the real `<Providers>` on a server and in a
|
|
83
|
+
browser.
|
|
84
|
+
- `src/app/account/account.test.tsx`: `/account` streamed by React's server
|
|
85
|
+
renderer, the certified section held until the first part is read.
|
|
86
|
+
|
|
87
|
+
`src/canisters/` is generated from `icrc1.did` by `pnpm gen`
|
|
88
|
+
(`meant gen`), committed, and never edited.
|
|
89
|
+
|
|
90
|
+
## A tab that is still signed in
|
|
91
|
+
|
|
92
|
+
Query keys carry the caller, and an `AuthClient` reads a stored session
|
|
93
|
+
synchronously, so a tab that is still signed in from an earlier visit knows
|
|
94
|
+
the user before its first render, while the server prefetched as the
|
|
95
|
+
anonymous principal. The keys `useClient()` builds follow the caller React
|
|
96
|
+
renders with, the one `useAuth()` returns: anonymous on the server and while
|
|
97
|
+
the page hydrates. So the hydrating render finds the server's data under the
|
|
98
|
+
anonymous keys, matches the server's HTML and sends nothing; then React
|
|
99
|
+
renders each component that calls `useClient()` or `useAuth()` again with the
|
|
100
|
+
session, and every card reads its own keys once, as the user (scenario 10).
|
|
101
|
+
`src/components/hydration.test.tsx` checks it: no recoverable error, no
|
|
102
|
+
console error, the server's nodes kept, no anonymous read sent, and each card
|
|
103
|
+
read once as the user.
|
|
104
|
+
|
|
105
|
+
That move has one cost, which this app does not pay: a Suspense boundary that
|
|
106
|
+
has not hydrated yet (its streamed HTML, or its lazy code, still on the way)
|
|
107
|
+
below a component that calls `useClient()` or `useAuth()` is rendered on the
|
|
108
|
+
client when that component moves on, showing its fallback instead of the
|
|
109
|
+
server's HTML. The streamed section of `/account` sits in a Server Component,
|
|
110
|
+
and no client component above it renders with the caller, so it streams in as
|
|
111
|
+
the server sent it. In your own app, keep such a boundary out from under a
|
|
112
|
+
component that renders with the caller, or pass it in as `children`.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
type BlockIndex = nat;
|
|
2
|
+
type Subaccount = blob;
|
|
3
|
+
// Number of nanoseconds since the UNIX epoch in UTC timezone.
|
|
4
|
+
type Timestamp = nat64;
|
|
5
|
+
// Number of nanoseconds between two [Timestamp]s.
|
|
6
|
+
type Duration = nat64;
|
|
7
|
+
type Tokens = nat;
|
|
8
|
+
|
|
9
|
+
type Account = record {
|
|
10
|
+
owner : principal;
|
|
11
|
+
subaccount : opt Subaccount;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type TransferArg = record {
|
|
15
|
+
from_subaccount : opt Subaccount;
|
|
16
|
+
to : Account;
|
|
17
|
+
amount : Tokens;
|
|
18
|
+
fee : opt Tokens;
|
|
19
|
+
memo : opt blob;
|
|
20
|
+
created_at_time: opt Timestamp;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type TransferError = variant {
|
|
24
|
+
BadFee : record { expected_fee : Tokens };
|
|
25
|
+
BadBurn : record { min_burn_amount : Tokens };
|
|
26
|
+
InsufficientFunds : record { balance : Tokens };
|
|
27
|
+
TooOld;
|
|
28
|
+
CreatedInFuture : record { ledger_time : nat64 };
|
|
29
|
+
TemporarilyUnavailable;
|
|
30
|
+
Duplicate : record { duplicate_of : BlockIndex };
|
|
31
|
+
GenericError : record { error_code : nat; message : text };
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type TransferResult = variant {
|
|
35
|
+
Ok : BlockIndex;
|
|
36
|
+
Err : TransferError;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// The value returned from the [icrc1_metadata] endpoint.
|
|
40
|
+
type Value = variant {
|
|
41
|
+
Nat : nat;
|
|
42
|
+
Int : int;
|
|
43
|
+
Text : text;
|
|
44
|
+
Blob : blob;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// The initialization parameters of the Ledger
|
|
48
|
+
type InitArgs = record {
|
|
49
|
+
minting_account : Account;
|
|
50
|
+
transfer_fee : nat64;
|
|
51
|
+
token_symbol : text;
|
|
52
|
+
token_name : text;
|
|
53
|
+
metadata : vec record { text; Value };
|
|
54
|
+
initial_balances : vec record { Account; nat64 };
|
|
55
|
+
archive_options : record {
|
|
56
|
+
num_blocks_to_archive : nat64;
|
|
57
|
+
trigger_threshold : nat64;
|
|
58
|
+
max_message_size_bytes : opt nat64;
|
|
59
|
+
cycles_for_archive_creation : opt nat64;
|
|
60
|
+
node_max_memory_size_bytes : opt nat64;
|
|
61
|
+
controller_id : principal;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
type UpgradeArgs = record {
|
|
66
|
+
metadata : opt vec record { text; Value };
|
|
67
|
+
token_symbol : opt text;
|
|
68
|
+
token_name : opt text;
|
|
69
|
+
transfer_fee : opt nat64;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
type LedgerArg = variant {
|
|
73
|
+
Init: InitArgs;
|
|
74
|
+
Upgrade: opt UpgradeArgs;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
service : (ledger_arg : LedgerArg) -> {
|
|
78
|
+
icrc1_name : () -> (text) query;
|
|
79
|
+
icrc1_symbol : () -> (text) query;
|
|
80
|
+
icrc1_decimals : () -> (nat8) query;
|
|
81
|
+
icrc1_metadata : () -> (vec record { text; Value }) query;
|
|
82
|
+
icrc1_total_supply : () -> (Tokens) query;
|
|
83
|
+
icrc1_fee : () -> (Tokens) query;
|
|
84
|
+
icrc1_minting_account : () -> (opt Account) query;
|
|
85
|
+
icrc1_balance_of : (Account) -> (Tokens) query;
|
|
86
|
+
icrc1_transfer : (TransferArg) -> (TransferResult);
|
|
87
|
+
icrc1_supported_standards : () -> (vec record { name : text; url : text }) query;
|
|
88
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { NextConfig } from "next"
|
|
2
|
+
|
|
3
|
+
const nextConfig: NextConfig = {
|
|
4
|
+
reactStrictMode: true,
|
|
5
|
+
// `next dev` would otherwise write an AGENTS.md and a CLAUDE.md into this
|
|
6
|
+
// folder when it detects a coding agent; the repository keeps its own.
|
|
7
|
+
agentRules: false,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default nextConfig
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "next-ssr",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "next dev -p 3001",
|
|
8
|
+
"build": "next build",
|
|
9
|
+
"start": "next start -p 3011",
|
|
10
|
+
"typecheck": "tsc --noEmit",
|
|
11
|
+
"test": "vitest run",
|
|
12
|
+
"gen": "meant gen icrc1.did -o src/canisters",
|
|
13
|
+
"gen:check": "meant gen icrc1.did -o src/canisters --check",
|
|
14
|
+
"smoke": "node scripts/smoke.ts"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@meantjs/schema": "0.6.0",
|
|
18
|
+
"@ic-reactor/core": "^4.1.1",
|
|
19
|
+
"@ic-reactor/react": "^4.1.1",
|
|
20
|
+
"@icp-sdk/auth": "^10.0.1",
|
|
21
|
+
"@icp-sdk/core": "^6.1.0",
|
|
22
|
+
"@tanstack/react-query": "^5.102.8",
|
|
23
|
+
"next": "^16.4.2",
|
|
24
|
+
"react": "^19.3.0",
|
|
25
|
+
"react-dom": "^19.3.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@meantjs/cli": "0.5.1",
|
|
29
|
+
"@noble/curves": "^2.2.0",
|
|
30
|
+
"@testing-library/dom": "^10.4.1",
|
|
31
|
+
"@testing-library/react": "^16.3.3",
|
|
32
|
+
"@types/jsdom": "^30.0.0",
|
|
33
|
+
"@types/node": "^26.5.1",
|
|
34
|
+
"@types/react": "^19.3.0",
|
|
35
|
+
"@types/react-dom": "^19.3.0",
|
|
36
|
+
"jsdom": "30.0.1",
|
|
37
|
+
"react-server-dom-turbopack": "^19.3.0",
|
|
38
|
+
"typescript": "^6.0.3",
|
|
39
|
+
"vitest": "^5.0.0"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// Scenario 4: the pages render with JavaScript disabled. Checks a running
|
|
2
|
+
// production server (`pnpm build && pnpm start`) against mainnet, reading each
|
|
3
|
+
// page the way a browser with JavaScript off sees it: the HTML as it arrives,
|
|
4
|
+
// no script run, nothing that a script would reveal. Also checks the account
|
|
5
|
+
// lookup and its streamed section (scenarios 5 and 6), the error section
|
|
6
|
+
// (scenario 8) and the JSON route (scenario 7).
|
|
7
|
+
//
|
|
8
|
+
// pnpm smoke # http://localhost:3011
|
|
9
|
+
// pnpm smoke http://localhost:3001 # another server, such as `pnpm dev`
|
|
10
|
+
//
|
|
11
|
+
// Node strips the types itself (22.18 or newer). It calls mainnet, so it is
|
|
12
|
+
// not part of `pnpm test`.
|
|
13
|
+
import assert from "node:assert/strict"
|
|
14
|
+
import { createClient, formatUnits } from "@ic-reactor/core"
|
|
15
|
+
import { JSDOM } from "jsdom"
|
|
16
|
+
import { actor, type Actor } from "../src/canisters/icrc1.ts"
|
|
17
|
+
import {
|
|
18
|
+
LEDGERS,
|
|
19
|
+
NO_CANISTER,
|
|
20
|
+
NOT_A_LEDGER,
|
|
21
|
+
SAMPLE_OWNER,
|
|
22
|
+
} from "../src/ledgers.ts"
|
|
23
|
+
|
|
24
|
+
const base = process.argv[2] ?? "http://localhost:3011"
|
|
25
|
+
const mainnet = createClient({ network: "ic", identity: "anonymous" })
|
|
26
|
+
|
|
27
|
+
/** The page at `path` as a browser without JavaScript shows it. */
|
|
28
|
+
async function withoutJavaScript(path: string) {
|
|
29
|
+
const response = await fetch(new URL(path, base))
|
|
30
|
+
assert.equal(response.status, 200, `GET ${path}`)
|
|
31
|
+
const { document } = new JSDOM(await response.text()).window
|
|
32
|
+
for (const node of document.querySelectorAll("script, template, [hidden]")) {
|
|
33
|
+
node.remove()
|
|
34
|
+
}
|
|
35
|
+
return document
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// The home page: every ledger's values are in the HTML, and they are
|
|
39
|
+
// mainnet's, read again here directly.
|
|
40
|
+
const home = await withoutJavaScript("/")
|
|
41
|
+
for (const ref of LEDGERS) {
|
|
42
|
+
const ledger = mainnet.canister<Actor>(actor, { id: ref.id })
|
|
43
|
+
const [name, symbol, decimals, fee, minter] = await Promise.all([
|
|
44
|
+
ledger.icrc1_name(),
|
|
45
|
+
ledger.icrc1_symbol(),
|
|
46
|
+
ledger.icrc1_decimals(),
|
|
47
|
+
ledger.icrc1_fee(),
|
|
48
|
+
ledger.icrc1_minting_account(),
|
|
49
|
+
])
|
|
50
|
+
const card = home.querySelector(`[data-ledger="${ref.id}"]`)
|
|
51
|
+
const read = (method: string) =>
|
|
52
|
+
card?.querySelector(`[data-read="${method}"]`)?.textContent ?? ""
|
|
53
|
+
assert.equal(read("icrc1_name"), `${name} string`)
|
|
54
|
+
assert.equal(read("icrc1_symbol"), `${symbol} string`)
|
|
55
|
+
assert.equal(read("icrc1_decimals"), `${decimals} number`)
|
|
56
|
+
assert.equal(
|
|
57
|
+
read("icrc1_fee"),
|
|
58
|
+
`${formatUnits(fee, decimals)} ${symbol} bigint`
|
|
59
|
+
)
|
|
60
|
+
assert.match(
|
|
61
|
+
read("icrc1_total_supply"),
|
|
62
|
+
new RegExp(`^\\d+(\\.\\d+)? ${symbol} bigint$`)
|
|
63
|
+
)
|
|
64
|
+
assert.ok(
|
|
65
|
+
read("icrc1_minting_account").startsWith(`${minter?.owner} principal text`)
|
|
66
|
+
)
|
|
67
|
+
const origin = card?.querySelector("[data-origin]")
|
|
68
|
+
assert.equal(origin?.getAttribute("data-origin"), "server")
|
|
69
|
+
console.log(
|
|
70
|
+
`${ref.label.padEnd(6)} ${read("icrc1_total_supply").replace(/ bigint$/, "")}, fee ${read("icrc1_fee").replace(/ bigint$/, "")}, ${origin?.textContent?.replace(/ Read again in this tab$/, "")}`
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
const failed = home.querySelector(
|
|
74
|
+
`[data-ledger="${NOT_A_LEDGER.id}"] [data-kind]`
|
|
75
|
+
)
|
|
76
|
+
assert.equal(failed?.textContent, "rejected")
|
|
77
|
+
console.log(
|
|
78
|
+
`${NOT_A_LEDGER.label}: ${failed?.textContent}, rendered by the server`
|
|
79
|
+
)
|
|
80
|
+
assert.equal(home.querySelector(".pill")?.textContent, "anonymous")
|
|
81
|
+
|
|
82
|
+
// The account page: the plain balances are in the first part of the
|
|
83
|
+
// response; the certified ones arrive later in the same response.
|
|
84
|
+
const started = Date.now()
|
|
85
|
+
const response = await fetch(new URL(`/account?owner=${SAMPLE_OWNER}`, base))
|
|
86
|
+
assert.equal(response.status, 200)
|
|
87
|
+
let html = ""
|
|
88
|
+
const arrivals: Record<string, number> = {}
|
|
89
|
+
const decoder = new TextDecoder()
|
|
90
|
+
for await (const chunk of response.body ?? []) {
|
|
91
|
+
html += decoder.decode(chunk, { stream: true })
|
|
92
|
+
for (const marker of ["balances", "certified-fallback", "certified"]) {
|
|
93
|
+
if (
|
|
94
|
+
arrivals[marker] === undefined &&
|
|
95
|
+
html.includes(`data-section="${marker}"`)
|
|
96
|
+
) {
|
|
97
|
+
arrivals[marker] = Date.now() - started
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
assert.ok(arrivals.balances !== undefined && arrivals.certified !== undefined)
|
|
102
|
+
assert.ok(
|
|
103
|
+
arrivals.certified > arrivals.balances,
|
|
104
|
+
"the certified balances stream in after the plain ones"
|
|
105
|
+
)
|
|
106
|
+
console.log(
|
|
107
|
+
`/account: balances at ${arrivals.balances} ms, certified balances streamed in at ${arrivals.certified} ms`
|
|
108
|
+
)
|
|
109
|
+
const account = new JSDOM(html).window.document
|
|
110
|
+
const visible = (section: string) => {
|
|
111
|
+
const table = account.querySelector(`[data-section="${section}"]`)
|
|
112
|
+
return table !== null && table.closest("[hidden]") === null
|
|
113
|
+
}
|
|
114
|
+
assert.ok(visible("balances"), "the plain balances show without JavaScript")
|
|
115
|
+
assert.ok(
|
|
116
|
+
!visible("certified"),
|
|
117
|
+
"the streamed section needs JavaScript to show"
|
|
118
|
+
)
|
|
119
|
+
const icp = account.querySelector(
|
|
120
|
+
`[data-section="balances"] [data-ledger="${LEDGERS[0]?.id}"] [data-field="balance"]`
|
|
121
|
+
)?.textContent
|
|
122
|
+
assert.match(icp ?? "", /^\d+(\.\d+)? ICP$/)
|
|
123
|
+
console.log(`/account: ${SAMPLE_OWNER} holds ${icp}`)
|
|
124
|
+
|
|
125
|
+
// A typo in the search parameter is a message in the page.
|
|
126
|
+
const typo = await withoutJavaScript("/account?owner=not-a-principal")
|
|
127
|
+
const problem = typo.querySelector('[data-problem="owner"]')?.textContent ?? ""
|
|
128
|
+
assert.match(problem, /"not-a-principal" is not a principal/)
|
|
129
|
+
assert.equal(typo.querySelector("table"), null)
|
|
130
|
+
console.log(`/account?owner=not-a-principal: ${problem.slice(0, 40)}…`)
|
|
131
|
+
|
|
132
|
+
// The route handler.
|
|
133
|
+
const api = async (path: string) => {
|
|
134
|
+
const reply = await fetch(new URL(path, base))
|
|
135
|
+
return {
|
|
136
|
+
status: reply.status,
|
|
137
|
+
body: (await reply.json()) as Record<string, unknown>,
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const ok = await api(`/api/balance/ckBTC/${SAMPLE_OWNER}`)
|
|
141
|
+
assert.equal(ok.status, 200)
|
|
142
|
+
assert.equal(
|
|
143
|
+
ok.body.balance,
|
|
144
|
+
formatUnits(BigInt(String(ok.body.baseUnits)), Number(ok.body.decimals))
|
|
145
|
+
)
|
|
146
|
+
console.log(
|
|
147
|
+
`/api/balance/ckBTC/${SAMPLE_OWNER}: ${ok.status} ${JSON.stringify(ok.body)}`
|
|
148
|
+
)
|
|
149
|
+
const bad = await api("/api/balance/ICP/not-a-principal")
|
|
150
|
+
assert.equal(bad.status, 400)
|
|
151
|
+
console.log(
|
|
152
|
+
`/api/balance/ICP/not-a-principal: ${bad.status} ${JSON.stringify(bad.body)}`
|
|
153
|
+
)
|
|
154
|
+
const notALedger = await api(`/api/balance/${NOT_A_LEDGER.id}/${SAMPLE_OWNER}`)
|
|
155
|
+
assert.equal(notALedger.status, 502)
|
|
156
|
+
console.log(
|
|
157
|
+
`/api/balance/${NOT_A_LEDGER.id}/…: ${notALedger.status} kind ${JSON.stringify((notALedger.body.error as { kind?: string }).kind)}`
|
|
158
|
+
)
|
|
159
|
+
// A canister that does not exist: refused for good, so a 502 and not a 503.
|
|
160
|
+
const missing = await api(`/api/balance/${NO_CANISTER}/${SAMPLE_OWNER}`)
|
|
161
|
+
const refusal = missing.body.error as { kind?: string; httpStatus?: number }
|
|
162
|
+
assert.equal(missing.status, 502)
|
|
163
|
+
assert.equal(refusal.kind, "not_delivered")
|
|
164
|
+
assert.equal(refusal.httpStatus, 400)
|
|
165
|
+
console.log(
|
|
166
|
+
`/api/balance/${NO_CANISTER}/…: ${missing.status} kind "${refusal.kind}", HTTP ${refusal.httpStatus} from the IC`
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
console.log("smoke: every check passed")
|