@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,586 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Reads"
|
|
3
|
+
description: "client.queryOptions with TanStack Query: keys that carry the caller, skipToken, retries, certified reads, suspense and infinite queries"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
A read is a TanStack Query query. `client.queryOptions` builds its options, and
|
|
7
|
+
you hand them to `useQuery`, `useSuspenseQuery`, `fetchQuery` or any other
|
|
8
|
+
TanStack API. The client does the parts that are easy to get wrong: the key
|
|
9
|
+
carries the caller, the query function calls as that caller, and `retry` only
|
|
10
|
+
re-sends what can be re-sent.
|
|
11
|
+
|
|
12
|
+
This page assumes the setup of [Getting started](/v4/guides/getting-started/)
|
|
13
|
+
and [The client](/v4/guides/client/).
|
|
14
|
+
|
|
15
|
+
## A first read
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import type { Principal } from "@meantjs/schema"
|
|
19
|
+
import { formatUnits } from "@ic-reactor/core"
|
|
20
|
+
import { useClient } from "@ic-reactor/react"
|
|
21
|
+
import { skipToken, useQuery } from "@tanstack/react-query"
|
|
22
|
+
import { actor, type Actor } from "./generated/icrc1"
|
|
23
|
+
|
|
24
|
+
export function Balance({ owner }: { owner: Principal | undefined }) {
|
|
25
|
+
const client = useClient()
|
|
26
|
+
const ledger = client.canister<Actor>(actor, {
|
|
27
|
+
id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
28
|
+
})
|
|
29
|
+
const balance = useQuery(
|
|
30
|
+
client.queryOptions(
|
|
31
|
+
ledger,
|
|
32
|
+
"icrc1_balance_of",
|
|
33
|
+
owner ? { owner, subaccount: null } : skipToken
|
|
34
|
+
)
|
|
35
|
+
)
|
|
36
|
+
return (
|
|
37
|
+
<p>{balance.data === undefined ? "…" : formatUnits(balance.data, 8)}</p>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Three rules sit in those few lines.
|
|
43
|
+
|
|
44
|
+
- **Build the options in render, from that render's `useClient()`.** Do not
|
|
45
|
+
build them once at module scope and do not keep `useClient()`'s result past
|
|
46
|
+
its render. The caller can change between renders, and so must the key. The
|
|
47
|
+
[SSR page](/v4/guides/ssr/) explains why this matters while a page hydrates.
|
|
48
|
+
- **The variables are one value.** Nothing for a method without arguments, the
|
|
49
|
+
value for one argument, a tuple `[a, b]` for two or more. A direct call
|
|
50
|
+
(`ledger.icrc1_balance_of(account)`) takes the parameters as the generated
|
|
51
|
+
`Actor` lists them. See [Values and units](/v4/guides/values/).
|
|
52
|
+
- **`client.canister()` is safe in render.** It returns the same object for the
|
|
53
|
+
same service and target every time.
|
|
54
|
+
|
|
55
|
+
`queryOptions` throws a `TypeError` for a method the service does not have, so
|
|
56
|
+
a wrong method name fails at once, not on the first fetch.
|
|
57
|
+
|
|
58
|
+
## Keys carry the caller
|
|
59
|
+
|
|
60
|
+
The key of a read is:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
["ic-reactor", network, caller, canisterId, method, args]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
| Segment | Value |
|
|
67
|
+
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
68
|
+
| `network` | `"ic"`, `"local"`, a custom network's `name` (or its host), or the resolved host for `"env"` |
|
|
69
|
+
| `caller` | the principal text calls go out as now: `"2vxsx-fae"` unless someone is signed in |
|
|
70
|
+
| `canisterId` | the canister, as text (`"$unresolved:<name>"` for a `{ name }` the `ic_env` cookie cannot resolve) |
|
|
71
|
+
| `method` | the Candid method |
|
|
72
|
+
| `args` | the hex of the Candid encoding of the variables; `"$skip"` for `skipToken`; `"$invalid"` and a text of the value for variables that do not encode |
|
|
73
|
+
|
|
74
|
+
A read through a canister made with `certified: true` has one more segment at
|
|
75
|
+
the end, `"certified"` (see [Certified reads](#certified-reads)).
|
|
76
|
+
|
|
77
|
+
The caller is in the key so that one principal's answer is never served to
|
|
78
|
+
another. Reads often depend on who asks: a balance, a profile, an inbox. After
|
|
79
|
+
a sign-in, a sign-out or an account switch, a component that calls
|
|
80
|
+
`useClient()` renders again, builds the new caller's key and finds it empty:
|
|
81
|
+
`data` is `undefined` until the read loads. The old caller's read, if still in
|
|
82
|
+
flight, never lands under the new key (see [The caller changes](#the-caller-changes)).
|
|
83
|
+
|
|
84
|
+
Because of this, add nothing that carries data across keys:
|
|
85
|
+
|
|
86
|
+
- no `placeholderData: keepPreviousData`: it would show the previous caller's
|
|
87
|
+
data while the new caller's loads;
|
|
88
|
+
- no `initialData` taken from another key.
|
|
89
|
+
|
|
90
|
+
## Finding a key: `client.queryKey`
|
|
91
|
+
|
|
92
|
+
Never write a key by hand. A key typed out as an array is a plain `QueryKey`:
|
|
93
|
+
it leaves the caller out and matches nothing the client caches or invalidates.
|
|
94
|
+
Ask the client:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { principal } from "@meantjs/schema"
|
|
98
|
+
import { client, ledger } from "./ledger"
|
|
99
|
+
|
|
100
|
+
const account = { owner: principal("aaaaa-aa"), subaccount: null }
|
|
101
|
+
|
|
102
|
+
// A prefix: every read of the ledger by the current caller.
|
|
103
|
+
await client.queryClient.invalidateQueries({
|
|
104
|
+
queryKey: client.queryKey(ledger),
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
// A prefix: every icrc1_balance_of read of the current caller, whatever the account.
|
|
108
|
+
await client.queryClient.invalidateQueries({
|
|
109
|
+
queryKey: client.queryKey(ledger, "icrc1_balance_of"),
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
// The exact key of one read. getQueryData and setQueryData need an exact key.
|
|
113
|
+
const balance = client.queryClient.getQueryData<bigint>(
|
|
114
|
+
client.queryKey(ledger, "icrc1_balance_of", account)
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
// A method without arguments has one read, so its method key is its exact key.
|
|
118
|
+
const fee = client.queryClient.getQueryData<bigint>(
|
|
119
|
+
client.queryKey(ledger, "icrc1_fee")
|
|
120
|
+
)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
- `queryKey(canister)`: every read of the canister by the current caller.
|
|
124
|
+
- `queryKey(canister, method)`: every read of that method by the current
|
|
125
|
+
caller. For a method without arguments this is the read's exact key.
|
|
126
|
+
- `queryKey(canister, method, variables)`: the exact key `queryOptions` gives
|
|
127
|
+
for those variables.
|
|
128
|
+
|
|
129
|
+
`invalidateQueries` takes a prefix. `getQueryData` and `setQueryData` match a
|
|
130
|
+
key exactly, so give them a whole key and never a prefix.
|
|
131
|
+
|
|
132
|
+
`queryKey` never throws for variables that do not encode: the key then holds
|
|
133
|
+
`"$invalid"`. It throws a `TypeError` for a canister of another client or a
|
|
134
|
+
method the service does not have.
|
|
135
|
+
|
|
136
|
+
A key for the current caller is not a key for every caller. A write
|
|
137
|
+
invalidates the written canister's reads for every caller, see
|
|
138
|
+
[Writes](/v4/guides/writes/).
|
|
139
|
+
|
|
140
|
+
## `skipToken` and arguments that do not encode
|
|
141
|
+
|
|
142
|
+
While the variables are not known yet, pass `skipToken` in their place. Import
|
|
143
|
+
it from `@tanstack/react-query`: `@ic-reactor/react` does not re-export it.
|
|
144
|
+
The query then does not run, and its key ends in `"$skip"`.
|
|
145
|
+
|
|
146
|
+
Variables that do not encode (a typed-in string that is not a principal, a
|
|
147
|
+
number where a `nat` is asked) do not throw while rendering. The key is tagged
|
|
148
|
+
`"$invalid"`, and the read rejects with kind `invalid_args` and the codec's
|
|
149
|
+
`issues`. Nothing is sent.
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
import { isPrincipal, principal } from "@meantjs/schema"
|
|
153
|
+
import { useClient } from "@ic-reactor/react"
|
|
154
|
+
import { skipToken, useQuery } from "@tanstack/react-query"
|
|
155
|
+
import { actor, type Actor } from "./generated/icrc1"
|
|
156
|
+
|
|
157
|
+
export function BalanceOf({ text }: { text: string }) {
|
|
158
|
+
const client = useClient()
|
|
159
|
+
const ledger = client.canister<Actor>(actor, {
|
|
160
|
+
id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
161
|
+
})
|
|
162
|
+
// Wait until the text is a principal, then read.
|
|
163
|
+
const owner = isPrincipal(text) ? principal(text) : undefined
|
|
164
|
+
const balance = useQuery(
|
|
165
|
+
client.queryOptions(
|
|
166
|
+
ledger,
|
|
167
|
+
"icrc1_balance_of",
|
|
168
|
+
owner ? { owner, subaccount: null } : skipToken
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
if (balance.error?.kind === "invalid_args") {
|
|
172
|
+
return <p>{balance.error.issues?.[0]?.message ?? balance.error.message}</p>
|
|
173
|
+
}
|
|
174
|
+
return <p>{balance.data?.toString() ?? "…"}</p>
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Retries
|
|
179
|
+
|
|
180
|
+
`queryOptions` sets `retry`. A read is retried at most 3 times, and only after
|
|
181
|
+
a failure the client classifies as retryable: a `not_delivered` that another
|
|
182
|
+
attempt can change (an HTTP 429, a reject with code 2, a network failure, a
|
|
183
|
+
timeout). Every other kind fails at once: retrying `invalid_args`, `rejected`,
|
|
184
|
+
`invalid_reply` or `canister_err` would only repeat the answer. A read through
|
|
185
|
+
`queryOptions` is never retried on a server, and the client's own
|
|
186
|
+
`QueryClient` has the same default for a `ReactorError` (any other error, from
|
|
187
|
+
an app's own query on it, is retried as TanStack Query retries it). A direct call still re-sends a retryable
|
|
188
|
+
read up to twice (see [Outside React](#outside-react)).
|
|
189
|
+
|
|
190
|
+
The [classification table](/v4/guides/errors/) lists which failures are
|
|
191
|
+
retryable. A read cannot have executed, so a retry is always safe. Writes are
|
|
192
|
+
different, see [Writes](/v4/guides/writes/).
|
|
193
|
+
|
|
194
|
+
## Adding options
|
|
195
|
+
|
|
196
|
+
The options are plain TanStack Query options. Spread them to add your own:
|
|
197
|
+
|
|
198
|
+
```tsx
|
|
199
|
+
import { formatUnits } from "@ic-reactor/core"
|
|
200
|
+
import { useClient } from "@ic-reactor/react"
|
|
201
|
+
import { useQuery } from "@tanstack/react-query"
|
|
202
|
+
import { actor, type Actor } from "./generated/icrc1"
|
|
203
|
+
|
|
204
|
+
export function Fee() {
|
|
205
|
+
const client = useClient()
|
|
206
|
+
const ledger = client.canister<Actor>(actor, {
|
|
207
|
+
id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
208
|
+
})
|
|
209
|
+
const fee = useQuery({
|
|
210
|
+
...client.queryOptions(ledger, "icrc1_fee"),
|
|
211
|
+
staleTime: 60_000,
|
|
212
|
+
select: (value) => formatUnits(value, 8),
|
|
213
|
+
})
|
|
214
|
+
return <span>{fee.data ?? "…"}</span>
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Keep `queryKey`, `queryFn` and `retry` as the client set them.
|
|
219
|
+
|
|
220
|
+
## The caller changes
|
|
221
|
+
|
|
222
|
+
The query function calls as the caller that was current when the options were
|
|
223
|
+
built, which is the caller in the key. If someone else is signed in by the time
|
|
224
|
+
it runs, it refuses: the read fails with kind `cancelled`, code
|
|
225
|
+
`caller_changed`, `mayHaveExecuted: false`, and nothing is sent. It never
|
|
226
|
+
lands under the new caller's key, and the component, which renders again with
|
|
227
|
+
the new caller, reads its own key.
|
|
228
|
+
|
|
229
|
+
You will not see this error in a component: it renders under the new key. It
|
|
230
|
+
can show up in a global error handler, such as a listener on
|
|
231
|
+
`client.queryClient.getQueryCache()`. Ignore kind `"cancelled"` there. The
|
|
232
|
+
[SSR page](/v4/guides/ssr/#a-read-the-hydrating-render-built-may-be-cancelled-once)
|
|
233
|
+
shows such a listener, and the one case where a read built by a hydrating
|
|
234
|
+
render is cancelled once.
|
|
235
|
+
|
|
236
|
+
## Update methods
|
|
237
|
+
|
|
238
|
+
An update method is not a read: a query refetches on mount, on focus and on
|
|
239
|
+
reconnect, and every refetch would run the update again. Use `useMutation`
|
|
240
|
+
with `client.mutationOptions`, see [Writes](/v4/guides/writes/). A oneway
|
|
241
|
+
method is not a read either: it has no reply to cache.
|
|
242
|
+
|
|
243
|
+
The generated `Actor` says each method's mode, so `queryOptions` with an
|
|
244
|
+
update or a oneway method does not compile:
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
import { useClient } from "@ic-reactor/react"
|
|
248
|
+
import { useMutation } from "@tanstack/react-query"
|
|
249
|
+
import { actor, type Actor, type TransferArg } from "./generated/icrc1"
|
|
250
|
+
|
|
251
|
+
export function Send({ arg }: { arg: TransferArg }) {
|
|
252
|
+
const client = useClient()
|
|
253
|
+
const ledger = client.canister<Actor>(actor, {
|
|
254
|
+
id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
255
|
+
})
|
|
256
|
+
// @ts-expect-error No overload matches this call: Argument of type
|
|
257
|
+
// '"icrc1_transfer"' is not assignable to parameter of type 'ReadMethod<Actor>'.
|
|
258
|
+
client.queryOptions(ledger, "icrc1_transfer", arg)
|
|
259
|
+
// A write is a mutation.
|
|
260
|
+
const transfer = useMutation(client.mutationOptions(ledger, "icrc1_transfer"))
|
|
261
|
+
return <button onClick={() => transfer.mutate(arg)}>Send</button>
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
`ReadMethod<Actor>` is the methods a read may be built from: the `query` and
|
|
266
|
+
`composite_query` methods. An `Actor` you write by hand says no mode, so every
|
|
267
|
+
one of its methods compiles here; `queryOptions` then checks the mode when it
|
|
268
|
+
builds the read, and throws a `TypeError` for an update or a oneway. A method
|
|
269
|
+
that returns nothing is refused the same way (`TypeError`), whatever its mode:
|
|
270
|
+
there is nothing to cache, so call it directly.
|
|
271
|
+
|
|
272
|
+
A method whose type is not one name the `Actor` marks as a read does not
|
|
273
|
+
compile either, even when every value of it names a query: a type parameter
|
|
274
|
+
`M extends keyof A & string`, a union that may name an update (a method picker
|
|
275
|
+
typed `keyof Actor & string`), or any method of a canister whose `Actor` type
|
|
276
|
+
is itself generic (`Canister<A>` in a function generic over `A`). TypeScript
|
|
277
|
+
cannot tell that such a method is a `ReadMethod<A>`. Give the type arguments yourself,
|
|
278
|
+
`client.queryOptions<A, any>(canister, method, vars)`: the call compiles, the
|
|
279
|
+
mode is checked at run time as for an `Actor` written by hand, and the data of
|
|
280
|
+
the options is `unknown`, for your function to state. The variables keep the
|
|
281
|
+
rule of every other read, and are checked against the method's schemas at run
|
|
282
|
+
time: the value itself for a method with one argument, a tuple for several,
|
|
283
|
+
and `undefined` or `[]` for none. `[arg]` for a one-argument method compiles,
|
|
284
|
+
since an array is a value too, and is refused `invalid_args`. `mutationOptions`,
|
|
285
|
+
`queryKey` and `resendOf` take `<A, any>` the same way; inside a function
|
|
286
|
+
generic over `A`, only `queryOptions` widens the variables, so cast them for the
|
|
287
|
+
other three. The same goes for an
|
|
288
|
+
`{ update: "idempotent" }` that may be `undefined`: for an update, pass a value
|
|
289
|
+
whose type says it is the opt-in.
|
|
290
|
+
|
|
291
|
+
One case is different. Some update methods give the same answer however often
|
|
292
|
+
they run. The ckBTC minter's `get_btc_address` is one: it is an update call,
|
|
293
|
+
it needs a signed-in caller, and it returns the same deposit address for an
|
|
294
|
+
account every time. Read it as a query with a fourth argument:
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
import { useAuth, useClient } from "@ic-reactor/react"
|
|
298
|
+
import { skipToken, useQuery } from "@tanstack/react-query"
|
|
299
|
+
import { actor, type Actor } from "./generated/ckbtc_minter"
|
|
300
|
+
|
|
301
|
+
export function DepositAddress() {
|
|
302
|
+
const client = useClient()
|
|
303
|
+
const { status } = useAuth()
|
|
304
|
+
const minter = client.canister<Actor>(actor, {
|
|
305
|
+
id: "mqygn-kiaaa-aaaar-qaadq-cai",
|
|
306
|
+
})
|
|
307
|
+
const address = useQuery(
|
|
308
|
+
client.queryOptions(
|
|
309
|
+
minter,
|
|
310
|
+
"get_btc_address",
|
|
311
|
+
status === "signed-in" ? { owner: null, subaccount: null } : skipToken,
|
|
312
|
+
{ update: "idempotent" }
|
|
313
|
+
)
|
|
314
|
+
)
|
|
315
|
+
return <p>{address.data ?? "…"}</p>
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
`{ update: "idempotent" }` is a promise that you make. The read is fetched once
|
|
320
|
+
per key and caller: `staleTime` is `Infinity`, and it does not refetch on
|
|
321
|
+
mount, window focus or reconnect. It is retried only after a failure that
|
|
322
|
+
proves it never got in. A write to the same canister through
|
|
323
|
+
`mutationOptions` invalidates it like any other read of that canister, so it
|
|
324
|
+
runs once more, as a replicated call. That is safe for an idempotent method but
|
|
325
|
+
it is a cost. To keep the read cached across writes, list the reads a write
|
|
326
|
+
changes in `invalidates`, see [Writes](/v4/guides/writes/).
|
|
327
|
+
|
|
328
|
+
It is still an update, so a signed-out or `"anonymous"` client refuses it as
|
|
329
|
+
`unauthenticated` (code `anonymous_write`) and sends nothing, as it refuses a
|
|
330
|
+
write. Read an ICRC-21 consent message (`icrc21_canister_call_consent_message`)
|
|
331
|
+
as the caller who will send the write: the message can depend on the caller,
|
|
332
|
+
and the DFINITY ICRC-1 ledger names the sender as `From`.
|
|
333
|
+
|
|
334
|
+
Do not use `{ update: "idempotent" }` for a method that changes state. The
|
|
335
|
+
option opts in an update only: a oneway method does not compile even with it,
|
|
336
|
+
and the variables come before it, `undefined` for a method without
|
|
337
|
+
arguments.
|
|
338
|
+
|
|
339
|
+
## Certified reads
|
|
340
|
+
|
|
341
|
+
A plain query is answered by one replica and is not certified. For a reply you
|
|
342
|
+
can verify, build the canister with `certified: true`:
|
|
343
|
+
|
|
344
|
+
```tsx
|
|
345
|
+
import { useClient } from "@ic-reactor/react"
|
|
346
|
+
import { useQuery } from "@tanstack/react-query"
|
|
347
|
+
import { actor, type Actor } from "./generated/icrc1"
|
|
348
|
+
|
|
349
|
+
export function CertifiedSupply() {
|
|
350
|
+
const client = useClient()
|
|
351
|
+
const ledger = client.canister<Actor>(actor, {
|
|
352
|
+
id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
353
|
+
certified: true,
|
|
354
|
+
})
|
|
355
|
+
const supply = useQuery(client.queryOptions(ledger, "icrc1_total_supply"))
|
|
356
|
+
return <p>{supply.data?.toString() ?? "…"}</p>
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
The `query` methods of that canister object are sent as replicated calls, and
|
|
361
|
+
the client verifies the certificate of the reply. Its keys end in
|
|
362
|
+
`"certified"`, so a certified read and a plain read of the same method are two
|
|
363
|
+
different reads in the cache. There is no composite query on a certified
|
|
364
|
+
canister: a `composite_query` method has no certified path. Calling it
|
|
365
|
+
directly rejects `invalid_args` with code `no_certified_path`, and
|
|
366
|
+
`queryOptions` throws a `TypeError`. That one is checked only when the code
|
|
367
|
+
runs: the type of a canister object does not say whether it is certified.
|
|
368
|
+
|
|
369
|
+
### What to certify
|
|
370
|
+
|
|
371
|
+
A plain query is answered by one replica, and the client accepts a reply that
|
|
372
|
+
replica signed, so a faulty or malicious replica can answer with a value of
|
|
373
|
+
its own. A certified read is checked against the subnet's certificate.
|
|
374
|
+
|
|
375
|
+
Certify a read whose value decides where value goes or what a person
|
|
376
|
+
approves: a recipient, a deposit address, an allowance, the details of a
|
|
377
|
+
transfer or an approval that someone confirms. Read the rest plainly: a list
|
|
378
|
+
a person browses, a name, a price shown for information.
|
|
379
|
+
|
|
380
|
+
A certified read costs what an update call costs. It takes as long, because
|
|
381
|
+
it goes through consensus, and the canister pays cycles for it, where a plain
|
|
382
|
+
query is free. So certify only the reads that decide something. Two canister
|
|
383
|
+
objects of one canister keep the two apart, and a write through either
|
|
384
|
+
invalidates the reads of both:
|
|
385
|
+
|
|
386
|
+
```ts
|
|
387
|
+
import { createClient } from "@ic-reactor/core"
|
|
388
|
+
import { actor, type Actor } from "./generated/backend"
|
|
389
|
+
|
|
390
|
+
const client = createClient({ network: "ic", identity: "anonymous" })
|
|
391
|
+
const id = "bkyz2-fmaaa-aaaaa-qaaaq-cai"
|
|
392
|
+
// Profiles and lists, read plainly.
|
|
393
|
+
export const backend = client.canister<Actor>(actor, { id })
|
|
394
|
+
// Payees and deposit addresses, read certified.
|
|
395
|
+
export const certifiedBackend = client.canister<Actor>(actor, {
|
|
396
|
+
id,
|
|
397
|
+
certified: true,
|
|
398
|
+
})
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
The [Vite wallet](/v4/examples/vite-wallet/) reads its address book this
|
|
402
|
+
way: a contact is who a payment goes to.
|
|
403
|
+
|
|
404
|
+
## Outside React
|
|
405
|
+
|
|
406
|
+
The same options work with the client's `QueryClient`. A direct call on the
|
|
407
|
+
canister touches no cache:
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
import { client, ledger } from "./ledger"
|
|
411
|
+
|
|
412
|
+
const fee = await client.queryClient.fetchQuery(
|
|
413
|
+
client.queryOptions(ledger, "icrc1_fee")
|
|
414
|
+
)
|
|
415
|
+
await client.queryClient.invalidateQueries({
|
|
416
|
+
queryKey: client.queryKey(ledger),
|
|
417
|
+
})
|
|
418
|
+
const fresh = await ledger.icrc1_fee() // not cached
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
A direct read re-sends after a retryable failure, at most twice.
|
|
422
|
+
|
|
423
|
+
## Suspense
|
|
424
|
+
|
|
425
|
+
`useSuspenseQuery` suspends until the data is there and never returns
|
|
426
|
+
`undefined`. Two things to know.
|
|
427
|
+
|
|
428
|
+
First, `useSuspenseQuery` and `useSuspenseQueries` take the options of
|
|
429
|
+
`client.queryOptions(...)` as they are when the variables cannot be
|
|
430
|
+
`skipToken`. Options built with variables typed `V | SkipToken`, or with
|
|
431
|
+
`skipToken` itself, keep `skipToken` in the type of `queryFn`, and the suspense
|
|
432
|
+
hooks refuse them: a suspense read cannot wait for its variables. Read the
|
|
433
|
+
variables first, or use `useQuery`. The same holds for every read of a method
|
|
434
|
+
whose variables' type `skipToken` is assignable to, such as one whose one
|
|
435
|
+
argument is Candid `reserved` (typed `unknown`): the type cannot tell a value
|
|
436
|
+
from `skipToken`. Read such a method with `useQuery`, or, for a suspense read
|
|
437
|
+
of a value that is never `skipToken`, cast the options:
|
|
438
|
+
`options as typeof options & { queryFn: Exclude<typeof options.queryFn, SkipToken> }`.
|
|
439
|
+
|
|
440
|
+
Second, a component that suspends needs a `Suspense` boundary above it. This
|
|
441
|
+
holds on React 18 and 19, and matters most on a page that hydrates: see
|
|
442
|
+
[SSR and hydration](/v4/guides/ssr/).
|
|
443
|
+
|
|
444
|
+
```tsx
|
|
445
|
+
import { formatUnits } from "@ic-reactor/core"
|
|
446
|
+
import { useClient } from "@ic-reactor/react"
|
|
447
|
+
import { useSuspenseQuery } from "@tanstack/react-query"
|
|
448
|
+
import { Suspense } from "react"
|
|
449
|
+
import { actor, type Actor } from "./generated/icrc1"
|
|
450
|
+
|
|
451
|
+
function Fee() {
|
|
452
|
+
const client = useClient()
|
|
453
|
+
const ledger = client.canister<Actor>(actor, {
|
|
454
|
+
id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
455
|
+
})
|
|
456
|
+
const fee = useSuspenseQuery(client.queryOptions(ledger, "icrc1_fee"))
|
|
457
|
+
return <span>{formatUnits(fee.data, 8)}</span>
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
export function FeeWithFallback() {
|
|
461
|
+
return (
|
|
462
|
+
<Suspense fallback={<span>…</span>}>
|
|
463
|
+
<Fee />
|
|
464
|
+
</Suspense>
|
|
465
|
+
)
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## Infinite queries
|
|
470
|
+
|
|
471
|
+
There is no helper for `useInfiniteQuery`: the pieces are the same as for any
|
|
472
|
+
read, and the recipe is short. Four rules keep it correct.
|
|
473
|
+
|
|
474
|
+
- **Extend a client key, never write one.** Use
|
|
475
|
+
`[...client.queryKey(canister, method), "pages"]`. It keeps the caller in the
|
|
476
|
+
key and it keeps the read under its canister. A mutation invalidates it by
|
|
477
|
+
default, because the default invalidation matches the network, the canister
|
|
478
|
+
and the method of every read of the canister it wrote to, for every caller.
|
|
479
|
+
- **Fetch through the client's read options, not a direct call.** A direct
|
|
480
|
+
call (`ledger.query_blocks(...)`, or a function from `client.func`) signs as
|
|
481
|
+
the caller current when it runs, whatever caller the key names. While a page
|
|
482
|
+
hydrates in a browser that holds a session, the key names the anonymous
|
|
483
|
+
caller the server rendered for, and a direct call goes out as the signed-in
|
|
484
|
+
user (see [SSR and hydration](/v4/guides/ssr/)). Fetch each ledger page with
|
|
485
|
+
`client.queryClient.fetchQuery` and `client.queryOptions(...)`: that read is
|
|
486
|
+
refused (`cancelled`, code `caller_changed`) unless the key's caller is the
|
|
487
|
+
one calls go out as. Give it `staleTime: 0`, so that it is asked, and
|
|
488
|
+
checked, every time.
|
|
489
|
+
- **Throw if the caller changes while a page loads.** The archive reads that
|
|
490
|
+
follow the ledger page are direct calls. Listen with `client.subscribe` for
|
|
491
|
+
as long as `queryFn` runs, and throw if the caller changed.
|
|
492
|
+
- **Put everything the pages depend on in the key.** A `bigint` cannot be in a
|
|
493
|
+
key: write it with `toString()`.
|
|
494
|
+
|
|
495
|
+
This example walks the ICP ledger's blocks backwards. The ledger answers
|
|
496
|
+
`query_blocks` with the blocks it still holds and, for older ones, a list of
|
|
497
|
+
archived ranges; each carries a function reference that `client.func` turns
|
|
498
|
+
into a call to the archive canister. See
|
|
499
|
+
[`blocks.ts`](https://github.com/b3pay/ic-reactor/blob/main/examples/icrc-ledger/src/blocks.ts)
|
|
500
|
+
of the ICRC-1 ledger example for how it reads archived ranges, each as a
|
|
501
|
+
cached read of its own.
|
|
502
|
+
|
|
503
|
+
```tsx
|
|
504
|
+
import { useClient } from "@ic-reactor/react"
|
|
505
|
+
import { useInfiniteQuery, useQuery } from "@tanstack/react-query"
|
|
506
|
+
import {
|
|
507
|
+
actor,
|
|
508
|
+
QueryArchiveFn,
|
|
509
|
+
type Actor,
|
|
510
|
+
type ArchivedBlocksRange,
|
|
511
|
+
type Block,
|
|
512
|
+
type BlockRange,
|
|
513
|
+
type GetBlocksArgs,
|
|
514
|
+
} from "./generated/icp_ledger"
|
|
515
|
+
|
|
516
|
+
const PAGE = 10n
|
|
517
|
+
|
|
518
|
+
// The signature the `.did` gives the archive callback: a generated func type
|
|
519
|
+
// carries none. The Ok payload is the result; Err rejects as canister_err.
|
|
520
|
+
type ReadArchive = (arg: GetBlocksArgs) => Promise<BlockRange>
|
|
521
|
+
|
|
522
|
+
export function RecentBlocks() {
|
|
523
|
+
const client = useClient()
|
|
524
|
+
const ledger = client.canister<Actor>(actor, {
|
|
525
|
+
id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
526
|
+
})
|
|
527
|
+
|
|
528
|
+
// An empty range asks only for the length of the chain.
|
|
529
|
+
const tip = useQuery(
|
|
530
|
+
client.queryOptions(ledger, "query_blocks", { start: 0n, length: 0n })
|
|
531
|
+
)
|
|
532
|
+
const chain = tip.data?.chain_length
|
|
533
|
+
|
|
534
|
+
const pages = useInfiniteQuery({
|
|
535
|
+
queryKey: [
|
|
536
|
+
...client.queryKey(ledger, "query_blocks"),
|
|
537
|
+
"pages",
|
|
538
|
+
chain?.toString(),
|
|
539
|
+
],
|
|
540
|
+
enabled: chain !== undefined,
|
|
541
|
+
initialPageParam: chain ?? 0n, // the end, exclusive, of the first page
|
|
542
|
+
queryFn: async ({ pageParam }): Promise<Block[]> => {
|
|
543
|
+
let changed = false
|
|
544
|
+
const stop = client.subscribe(() => {
|
|
545
|
+
changed = true
|
|
546
|
+
})
|
|
547
|
+
try {
|
|
548
|
+
const start = pageParam > PAGE ? pageParam - PAGE : 0n
|
|
549
|
+
const args = { start, length: pageParam - start }
|
|
550
|
+
// Refused (caller_changed) unless the key's caller is the live one.
|
|
551
|
+
const reply = await client.queryClient.fetchQuery({
|
|
552
|
+
...client.queryOptions(ledger, "query_blocks", args),
|
|
553
|
+
staleTime: 0,
|
|
554
|
+
})
|
|
555
|
+
const archived = await Promise.all(
|
|
556
|
+
reply.archived_blocks.map((range: ArchivedBlocksRange) => {
|
|
557
|
+
const read = client.func<ReadArchive>(
|
|
558
|
+
QueryArchiveFn,
|
|
559
|
+
range.callback
|
|
560
|
+
)
|
|
561
|
+
return read({ start: range.start, length: range.length })
|
|
562
|
+
})
|
|
563
|
+
)
|
|
564
|
+
if (changed) throw new Error("The caller changed: refresh")
|
|
565
|
+
return [...archived.flatMap((range) => range.blocks), ...reply.blocks]
|
|
566
|
+
} finally {
|
|
567
|
+
stop()
|
|
568
|
+
}
|
|
569
|
+
},
|
|
570
|
+
getNextPageParam: (_last, _all, lastParam) =>
|
|
571
|
+
lastParam > PAGE ? lastParam - PAGE : undefined,
|
|
572
|
+
})
|
|
573
|
+
|
|
574
|
+
return (
|
|
575
|
+
<>
|
|
576
|
+
<p>{pages.data?.pages.flat().length ?? 0} blocks</p>
|
|
577
|
+
<button
|
|
578
|
+
disabled={!pages.hasNextPage || pages.isFetchingNextPage}
|
|
579
|
+
onClick={() => void pages.fetchNextPage()}
|
|
580
|
+
>
|
|
581
|
+
Older
|
|
582
|
+
</button>
|
|
583
|
+
</>
|
|
584
|
+
)
|
|
585
|
+
}
|
|
586
|
+
```
|