@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,572 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Writes"
|
|
3
|
+
description: "client.mutationOptions with TanStack Query: invalidation after a write, and when an update is sent again"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
A write is a TanStack Query mutation. `client.mutationOptions` builds its
|
|
7
|
+
options and `useMutation` runs them. The client takes care of the rules that
|
|
8
|
+
are easy to get wrong: who signs the call, which reads to refresh afterwards,
|
|
9
|
+
and, above all, when an update may be sent again.
|
|
10
|
+
|
|
11
|
+
## A first write
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { useClient } from "@ic-reactor/react"
|
|
15
|
+
import { useMutation } from "@tanstack/react-query"
|
|
16
|
+
import { actor, type Actor, type TransferArg } from "./generated/icrc1"
|
|
17
|
+
|
|
18
|
+
export function Send({ arg }: { arg: TransferArg }) {
|
|
19
|
+
const client = useClient()
|
|
20
|
+
const ledger = client.canister<Actor>(actor, {
|
|
21
|
+
id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
22
|
+
})
|
|
23
|
+
const transfer = useMutation(client.mutationOptions(ledger, "icrc1_transfer"))
|
|
24
|
+
return (
|
|
25
|
+
<button disabled={transfer.isPending} onClick={() => transfer.mutate(arg)}>
|
|
26
|
+
Send
|
|
27
|
+
</button>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`mutate(variables)` follows the same rule as a read: nothing for a method
|
|
33
|
+
without arguments, the value for one, a tuple `[a, b]` for two or more. Here
|
|
34
|
+
`mutate(arg)` sends the one argument. On success, `data` is the method's
|
|
35
|
+
result: for a result `variant { Ok : T; Err : E }`, the `Ok` value. An `Err`
|
|
36
|
+
rejects as kind `canister_err`.
|
|
37
|
+
|
|
38
|
+
`mutationOptions` throws a `TypeError` for a method the service does not have.
|
|
39
|
+
Its `mutationKey` is `["ic-reactor", network, canisterId, method]`. Built from
|
|
40
|
+
the client `useClient()` returns, it ends with the caller the render shows as
|
|
41
|
+
well, `["ic-reactor", network, canisterId, method, caller]`, so a filter on
|
|
42
|
+
the shorter key still finds it.
|
|
43
|
+
|
|
44
|
+
## Who signs
|
|
45
|
+
|
|
46
|
+
A write calls as the caller current **when `mutate()` was called**, or not at
|
|
47
|
+
all; not the one current when the options were built. TanStack Query can run a
|
|
48
|
+
write later: paused while the browser is offline, queued behind another
|
|
49
|
+
mutation of its `scope`, or retried by a `retry` of the app's. If someone else
|
|
50
|
+
is current by the time it is sent, the client refuses it: kind `cancelled`,
|
|
51
|
+
code `caller_changed`, `mayHaveExecuted: false`, and nothing is sent. A
|
|
52
|
+
mutation restored from a persister is refused the same way whoever is signed
|
|
53
|
+
in, since TanStack runs no `onMutate` for it and who started it is not known:
|
|
54
|
+
call `mutate()` again. A write run on a `QueryClient` other than
|
|
55
|
+
`client.queryClient` keeps the rule only through the client's `onMutate` (see
|
|
56
|
+
`onMutate` below).
|
|
57
|
+
|
|
58
|
+
A write needs a signed-in caller. If nobody is signed in, or the client was
|
|
59
|
+
built with `identity: "anonymous"`, the client refuses it before sending
|
|
60
|
+
anything: kind `unauthenticated`, code `anonymous_write`,
|
|
61
|
+
`mayHaveExecuted: false`.
|
|
62
|
+
|
|
63
|
+
Built from the `useClient()` of a render, the options send only as the caller
|
|
64
|
+
that render shows. A press handled before an account switch reached the
|
|
65
|
+
render (the switch and the click in one batch) is refused: kind `cancelled`,
|
|
66
|
+
code `caller_changed`, `mayHaveExecuted: false`, and nothing is sent. The
|
|
67
|
+
refusal reaches the callbacks of the options the press used (an `onError`
|
|
68
|
+
given to `useMutation`); the mutation that the render for the new caller shows
|
|
69
|
+
starts over, idle, since the key holds the caller. That is true of any
|
|
70
|
+
outcome, a write whose outcome is unknown included: an app that must keep
|
|
71
|
+
showing it across a switch (to read the sender's balance back, say) keeps it
|
|
72
|
+
in its own state, from the promise `mutateAsync` returns. The handler needs no check
|
|
73
|
+
of its own; disable the button for a caller who is not signed in:
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
import { useAuth, useClient } from "@ic-reactor/react"
|
|
77
|
+
import { useMutation } from "@tanstack/react-query"
|
|
78
|
+
import { actor, type Actor, type TransferArg } from "./generated/icrc1"
|
|
79
|
+
|
|
80
|
+
export function SendAsShown({ arg }: { arg: TransferArg }) {
|
|
81
|
+
const client = useClient()
|
|
82
|
+
const { status, principal: shown } = useAuth()
|
|
83
|
+
const ledger = client.canister<Actor>(actor, {
|
|
84
|
+
id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
85
|
+
})
|
|
86
|
+
const transfer = useMutation(client.mutationOptions(ledger, "icrc1_transfer"))
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<button
|
|
90
|
+
disabled={status !== "signed-in" || transfer.isPending}
|
|
91
|
+
onClick={() => transfer.mutate(arg)}
|
|
92
|
+
>
|
|
93
|
+
Send as {shown}
|
|
94
|
+
</button>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
A handler that signs in and then writes (`await client.signIn()`, then
|
|
100
|
+
`transfer.mutate(arg)`) presses with the options of the last render React
|
|
101
|
+
committed. The render for the user normally commits before the handler goes
|
|
102
|
+
on, and the write goes out as the user; while that render cannot commit, such
|
|
103
|
+
as when it suspends on the user's data, the press has the previous caller's
|
|
104
|
+
options and is refused. Let the render that shows the user press, or make a
|
|
105
|
+
direct call.
|
|
106
|
+
|
|
107
|
+
A direct call on a canister (`await ledger.icrc1_transfer(arg)`) is not held
|
|
108
|
+
to a render: it signs as whoever is signed in when it runs. In a component,
|
|
109
|
+
send writes through `mutationOptions`.
|
|
110
|
+
|
|
111
|
+
See [Auth](/v4/guides/auth/) for sign-in and caller changes.
|
|
112
|
+
|
|
113
|
+
## What a write refreshes
|
|
114
|
+
|
|
115
|
+
After a write settles, the client invalidates the reads it may have changed.
|
|
116
|
+
The rule:
|
|
117
|
+
|
|
118
|
+
- **Which reads.** Every read of the canister written to, for every caller,
|
|
119
|
+
certified or not. An update read made with `{ update: "idempotent" }` is
|
|
120
|
+
included, and it runs once more as a replicated call.
|
|
121
|
+
- **When.** After a success, after a `canister_err`, and after any failure with
|
|
122
|
+
`mayHaveExecuted: true`. A canister may change state before it returns an
|
|
123
|
+
`Err`, and after a lost reply the re-read shows whether the write happened,
|
|
124
|
+
so nothing else is needed after an unknown outcome.
|
|
125
|
+
- **When not.** Not after a failure that proves nothing ran: `invalid_args`,
|
|
126
|
+
`unauthenticated`, `not_delivered`, a reject with code 1 or 3, and a
|
|
127
|
+
`cancelled` before sending.
|
|
128
|
+
- **Waiting.** The invalidation is awaited: the mutation stays pending until
|
|
129
|
+
the active reads have been fetched again, so `isPending` covers the refresh.
|
|
130
|
+
|
|
131
|
+
To choose the reads yourself, pass `invalidates` as the third argument. The
|
|
132
|
+
list replaces the default, so name the written canister too if its reads
|
|
133
|
+
change. Each item is a canister (all its reads) or a `[canister, method]` pair
|
|
134
|
+
(one method's reads), for every caller. An empty list invalidates nothing.
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
import { useClient } from "@ic-reactor/react"
|
|
138
|
+
import { useMutation } from "@tanstack/react-query"
|
|
139
|
+
import { actor, type Actor, type TransferArg } from "./generated/icrc1"
|
|
140
|
+
|
|
141
|
+
export function SendQuietly({
|
|
142
|
+
arg,
|
|
143
|
+
otherId,
|
|
144
|
+
}: {
|
|
145
|
+
arg: TransferArg
|
|
146
|
+
otherId: string
|
|
147
|
+
}) {
|
|
148
|
+
const client = useClient()
|
|
149
|
+
const ledger = client.canister<Actor>(actor, {
|
|
150
|
+
id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
151
|
+
})
|
|
152
|
+
const other = client.canister<Actor>(actor, { id: otherId })
|
|
153
|
+
|
|
154
|
+
// Only the balances of this ledger, and everything of another canister.
|
|
155
|
+
const refreshBalances = client.mutationOptions(ledger, "icrc1_transfer", {
|
|
156
|
+
invalidates: [[ledger, "icrc1_balance_of"], other],
|
|
157
|
+
})
|
|
158
|
+
// Nothing: the page refreshes by itself, or the read must stay cached.
|
|
159
|
+
const refreshNothing = client.mutationOptions(ledger, "icrc1_transfer", {
|
|
160
|
+
invalidates: [],
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
const transfer = useMutation(refreshBalances)
|
|
164
|
+
const quiet = useMutation(refreshNothing)
|
|
165
|
+
return (
|
|
166
|
+
<>
|
|
167
|
+
<button onClick={() => transfer.mutate(arg)}>Send</button>
|
|
168
|
+
<button onClick={() => quiet.mutate(arg)}>Send, refresh nothing</button>
|
|
169
|
+
</>
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`invalidates` takes canisters of the same client. A canister of another client
|
|
175
|
+
throws a `TypeError`. The reads of a canister are found by their key, which
|
|
176
|
+
starts with `"ic-reactor"`; see [Reads](/v4/guides/reads/#finding-a-key-clientquerykey).
|
|
177
|
+
|
|
178
|
+
## When an update is sent again
|
|
179
|
+
|
|
180
|
+
An update has no safe retry in general. Every attempt at an update is a new
|
|
181
|
+
request on the Internet Computer, so a second attempt after an unknown outcome
|
|
182
|
+
can run the write twice. Two rules follow.
|
|
183
|
+
|
|
184
|
+
- **Never add `retry` to a write.** `retry` is `false` in the client's
|
|
185
|
+
options, and it must stay `false`. Spreading the options and setting
|
|
186
|
+
`retry: 3` compiles, and it makes TanStack Query send the update again
|
|
187
|
+
after failures that do not prove it never got in: a lost reply, a timeout, a
|
|
188
|
+
5xx. The write then runs twice.
|
|
189
|
+
- **Never call an update from `useQuery`.** TanStack Query may run a query
|
|
190
|
+
function again whenever it refetches. Call update methods from `useMutation`
|
|
191
|
+
or directly. `queryOptions` does not compile for an update of a generated
|
|
192
|
+
`Actor`, and throws for one at run time, to stop you; see
|
|
193
|
+
[Reads](/v4/guides/reads/#update-methods) for the one exception.
|
|
194
|
+
|
|
195
|
+
The client itself sends an update again in exactly two cases, because only
|
|
196
|
+
these two prove the first attempt was never accepted:
|
|
197
|
+
|
|
198
|
+
| Failure | Re-send |
|
|
199
|
+
| ----------------------------------------- | ------------------------------------- |
|
|
200
|
+
| reject code 2 (`SYS_TRANSIENT`) | after 300 ms, then after 600 ms |
|
|
201
|
+
| HTTP 429, before the request got in | after 300 ms, then after 600 ms |
|
|
202
|
+
| anything else, a network failure included | never: the call fails with that error |
|
|
203
|
+
|
|
204
|
+
Neither applies to the management canister, `aaaaa-aa`: the client never
|
|
205
|
+
re-sends an update there.
|
|
206
|
+
|
|
207
|
+
That is at most two re-sends. If they all fail, the call fails with the last
|
|
208
|
+
error, kind `not_delivered`, `mayHaveExecuted: false`. The agents the client
|
|
209
|
+
builds never retry on their own (`retryTimes` is 0), so these two rules are the
|
|
210
|
+
only re-sending.
|
|
211
|
+
|
|
212
|
+
What to do after `mayHaveExecuted: true` is yours to decide. Read the state
|
|
213
|
+
back, then decide whether to send again. The [Errors page](/v4/guides/errors/)
|
|
214
|
+
has the recipe, and the next section the one case where sending the same
|
|
215
|
+
write again is safe.
|
|
216
|
+
|
|
217
|
+
## Sending the same write again
|
|
218
|
+
|
|
219
|
+
Sending the same argument again after `mayHaveExecuted: true` is safe only
|
|
220
|
+
when the canister deduplicates it: it runs the same argument from the same
|
|
221
|
+
sender at most once. The ICRC-1 ledger does, for a transfer with
|
|
222
|
+
`created_at_time` set: the second one is answered `Duplicate`, which means the
|
|
223
|
+
first went through. Stamp `created_at_time` with `await client.time(ledger)`:
|
|
224
|
+
the IC's time in nanoseconds, from a certificate verified against the
|
|
225
|
+
network's root key, rather than the host's clock. Its request is signed with
|
|
226
|
+
an ingress expiry taken from the host's clock, as every request is: a host
|
|
227
|
+
clock so far off that the IC refuses its requests cannot read the time
|
|
228
|
+
either, and no call works until that clock is fixed. That time moves about once a second, so
|
|
229
|
+
two transfers stamped in the same second need their own `memo` each, or the
|
|
230
|
+
second is answered `Duplicate` without running. Most methods do not
|
|
231
|
+
deduplicate. For them a second send
|
|
232
|
+
can run the write twice, so read the state back instead.
|
|
233
|
+
|
|
234
|
+
`client.resendOf(error, canister, method, { dedupedBy })` offers that re-send.
|
|
235
|
+
`dedupedBy` states what the canister deduplicates on, read from the
|
|
236
|
+
argument. The client cannot check it: name only a field the canister really
|
|
237
|
+
deduplicates on. The call returns `undefined`, so nothing is offered, unless
|
|
238
|
+
all of these hold:
|
|
239
|
+
|
|
240
|
+
- `error` is one a write of that method on that canister rejected with (the
|
|
241
|
+
mutation's `error`, or what a direct call threw), and its
|
|
242
|
+
`mayHaveExecuted` is `true`. Any other failure proves what happened.
|
|
243
|
+
- The argument is an object (a record, a variant, or the tuple of several
|
|
244
|
+
arguments), and `dedupedBy` finds a key in it: neither `undefined` nor
|
|
245
|
+
`null`. A transfer without `created_at_time` is not deduplicated by the
|
|
246
|
+
ledger, so it is not offered.
|
|
247
|
+
- The argument is still what was sent: it encodes to the same bytes. If the
|
|
248
|
+
app changed that object since, it is not offered.
|
|
249
|
+
- The canister object still resolves to the canister the write went to. A
|
|
250
|
+
`{ name }` that the `ic_env` cookie maps to another canister since (a local
|
|
251
|
+
redeploy) is not offered: that canister has never seen the transfer, and
|
|
252
|
+
would run it.
|
|
253
|
+
- Whoever sent it is the caller now. After a sign-out, or a sign-in as
|
|
254
|
+
another account, nothing is offered: the same argument from another sender
|
|
255
|
+
is a new transfer, paid in full. Signing back in as the sender offers it
|
|
256
|
+
again. `useClient()` returns a view pinned to the caller its render shows;
|
|
257
|
+
the offer still follows the live caller, whom the write goes out as.
|
|
258
|
+
|
|
259
|
+
The offer's `arg` is the attempt's own argument, the object `mutate` was
|
|
260
|
+
given, and `from` is its sender. Send it with `mutate(again.arg)` on the same
|
|
261
|
+
mutation, which keeps its pending state and invalidation, or with
|
|
262
|
+
`again.send()`. Either one goes out only as the same write, and otherwise
|
|
263
|
+
sends nothing:
|
|
264
|
+
|
|
265
|
+
- only as `from`: if someone else is the caller by then, it is refused (code
|
|
266
|
+
`caller_changed`);
|
|
267
|
+
- only to the method and canister the write went to: `again.send()` always
|
|
268
|
+
goes there, and a mutation whose canister now resolves elsewhere is refused
|
|
269
|
+
(code `target_changed`);
|
|
270
|
+
- only with the bytes the write sent: `again.send()` sends those bytes, and
|
|
271
|
+
`mutate(again.arg)` is refused (code `arg_changed`) if the object was
|
|
272
|
+
changed since.
|
|
273
|
+
|
|
274
|
+
A re-send that did not run is not the end of the write, whether it was
|
|
275
|
+
refused or turned away when sent (an HTTP 429 or another 4xx, reject code 1
|
|
276
|
+
to 3). The first attempt may have run all the same, so it rejects
|
|
277
|
+
`outcome_unknown` with `mayHaveExecuted: true`, its `code`, `httpStatus` or
|
|
278
|
+
`rejectCode` and its `cause` say why the re-send did not run, and
|
|
279
|
+
`client.resendOf(transfer.error)` offers the write again while its sender is
|
|
280
|
+
the caller. Read the state back before anything else (see
|
|
281
|
+
[Errors](/v4/guides/errors/#what-to-do-for-each-kind)).
|
|
282
|
+
|
|
283
|
+
Once offered, that object stays held to that write on every mutation of the
|
|
284
|
+
client, for good: another account that sends the same object is cancelled
|
|
285
|
+
too. Build a new argument object for each new transfer, and for another
|
|
286
|
+
account, and never change one you sent.
|
|
287
|
+
|
|
288
|
+
```tsx
|
|
289
|
+
import { useAuth, useClient } from "@ic-reactor/react"
|
|
290
|
+
import { useMutation } from "@tanstack/react-query"
|
|
291
|
+
import { actor, type Actor, type TransferArg } from "./generated/icrc1"
|
|
292
|
+
|
|
293
|
+
// `arg` has `created_at_time` set and a `memo` of its own: build a new one for
|
|
294
|
+
// each new transfer (and when the account changes), and send that same one again.
|
|
295
|
+
export function SendOnce({ arg }: { arg: TransferArg }) {
|
|
296
|
+
const client = useClient()
|
|
297
|
+
// Re-renders when the caller changes, and the offer follows.
|
|
298
|
+
useAuth()
|
|
299
|
+
const ledger = client.canister<Actor>(actor, {
|
|
300
|
+
id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
301
|
+
})
|
|
302
|
+
const transfer = useMutation(client.mutationOptions(ledger, "icrc1_transfer"))
|
|
303
|
+
const again = client.resendOf(transfer.error, ledger, "icrc1_transfer", {
|
|
304
|
+
dedupedBy: (sent) => sent.created_at_time,
|
|
305
|
+
})
|
|
306
|
+
return (
|
|
307
|
+
<>
|
|
308
|
+
<button
|
|
309
|
+
disabled={transfer.isPending}
|
|
310
|
+
onClick={() => transfer.mutate(arg)}
|
|
311
|
+
>
|
|
312
|
+
Send
|
|
313
|
+
</button>
|
|
314
|
+
{again && (
|
|
315
|
+
<button
|
|
316
|
+
disabled={transfer.isPending}
|
|
317
|
+
onClick={() => transfer.mutate(again.arg)}
|
|
318
|
+
>
|
|
319
|
+
Send the same transfer again
|
|
320
|
+
</button>
|
|
321
|
+
)}
|
|
322
|
+
</>
|
|
323
|
+
)
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
`again.bytes` is the Candid bytes the attempt sent, the ones `send()` sends
|
|
328
|
+
again: a copy on every read, for an audit log or a consent screen.
|
|
329
|
+
|
|
330
|
+
A `canister_err` is a known outcome, so `resendOf` offers nothing after it.
|
|
331
|
+
When the canister says the failure is temporary (an ICRC-1
|
|
332
|
+
`TemporarilyUnavailable`), send the same argument object again with
|
|
333
|
+
`transfer.mutate(arg)`. Encoding is deterministic, so a deduplicating method
|
|
334
|
+
sees the same bytes and the same key, and answers `Duplicate` if an earlier
|
|
335
|
+
attempt ran.
|
|
336
|
+
|
|
337
|
+
`Resend` is not exported. To keep an offer in state, type it from the method:
|
|
338
|
+
|
|
339
|
+
```ts
|
|
340
|
+
import { createClient } from "@ic-reactor/core"
|
|
341
|
+
import type { Actor } from "./generated/icrc1"
|
|
342
|
+
|
|
343
|
+
const client = createClient({ network: "ic", identity: "anonymous" })
|
|
344
|
+
type TransferResend = NonNullable<
|
|
345
|
+
ReturnType<typeof client.resendOf<Actor, "icrc1_transfer">>
|
|
346
|
+
>
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## The bytes a write sends
|
|
350
|
+
|
|
351
|
+
`client.encode(canister, method, vars)` returns the Candid bytes a call of
|
|
352
|
+
`method` with `vars` sends, as a `Uint8Array`. It uses the call path's own
|
|
353
|
+
encoder and variables rule, so the bytes are the ones that go out, not a
|
|
354
|
+
second encoding of the same value. Pass them where the exact argument is
|
|
355
|
+
wanted, such as the `arg` of an ICRC-21 consent request:
|
|
356
|
+
|
|
357
|
+
```ts
|
|
358
|
+
import { client, ledger } from "./ledger"
|
|
359
|
+
import type { TransferArg } from "./generated/icrc1"
|
|
360
|
+
|
|
361
|
+
export function consentArg(transfer: TransferArg): Uint8Array {
|
|
362
|
+
return client.encode(ledger, "icrc1_transfer", transfer)
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
It sends nothing and needs no canister id, so it works for a `{ name }` the
|
|
367
|
+
`ic_env` cookie does not resolve yet. It checks only the variables, not the
|
|
368
|
+
caller or the canister id. Variables that do not encode throw `invalid_args`
|
|
369
|
+
with the `issues` a call of them rejects with.
|
|
370
|
+
|
|
371
|
+
## Typed errors
|
|
372
|
+
|
|
373
|
+
The mutation's `error` is `ReactorError<E> | null`, where `E` is the method's
|
|
374
|
+
`Err` type. Narrow on `kind` to read a typed `err`, and look at
|
|
375
|
+
`mayHaveExecuted` for the rest:
|
|
376
|
+
|
|
377
|
+
```tsx
|
|
378
|
+
import { useClient } from "@ic-reactor/react"
|
|
379
|
+
import { useMutation } from "@tanstack/react-query"
|
|
380
|
+
import { actor, type Actor, type TransferArg } from "./generated/icrc1"
|
|
381
|
+
|
|
382
|
+
export function SendWithMessage({ arg }: { arg: TransferArg }) {
|
|
383
|
+
const client = useClient()
|
|
384
|
+
const ledger = client.canister<Actor>(actor, {
|
|
385
|
+
id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
386
|
+
})
|
|
387
|
+
const transfer = useMutation(client.mutationOptions(ledger, "icrc1_transfer"))
|
|
388
|
+
const error = transfer.error
|
|
389
|
+
|
|
390
|
+
let message: string | undefined
|
|
391
|
+
if (error?.kind === "canister_err") {
|
|
392
|
+
// The ledger ran the call and refused it. error.err is a TransferError.
|
|
393
|
+
message =
|
|
394
|
+
error.err.tag === "InsufficientFunds"
|
|
395
|
+
? `Balance is only ${error.err.value.balance}`
|
|
396
|
+
: `The ledger refused: ${error.err.tag}`
|
|
397
|
+
} else if (error?.mayHaveExecuted) {
|
|
398
|
+
message = "Unknown outcome: check the balance before sending again."
|
|
399
|
+
} else if (error) {
|
|
400
|
+
message = error.message
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return (
|
|
404
|
+
<>
|
|
405
|
+
<button
|
|
406
|
+
disabled={transfer.isPending}
|
|
407
|
+
onClick={() => transfer.mutate(arg)}
|
|
408
|
+
>
|
|
409
|
+
Send
|
|
410
|
+
</button>
|
|
411
|
+
{message && <p role="alert">{message}</p>}
|
|
412
|
+
</>
|
|
413
|
+
)
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## Adding your own callbacks
|
|
418
|
+
|
|
419
|
+
The options have an `onMutate` and an `onSettled` of their own. Together they
|
|
420
|
+
resolve the canister a run writes to and invalidate its reads, so replacing
|
|
421
|
+
either one drops the invalidation. Call the client's from yours.
|
|
422
|
+
|
|
423
|
+
**`onSettled`:** call the client's with every argument you get, and return its
|
|
424
|
+
promise so the mutation settles once the reads are fetched again.
|
|
425
|
+
|
|
426
|
+
```tsx
|
|
427
|
+
import type { ReactorError } from "@ic-reactor/core"
|
|
428
|
+
import { useClient } from "@ic-reactor/react"
|
|
429
|
+
import { useMutation } from "@tanstack/react-query"
|
|
430
|
+
import {
|
|
431
|
+
actor,
|
|
432
|
+
type Actor,
|
|
433
|
+
type TransferArg,
|
|
434
|
+
type TransferError,
|
|
435
|
+
} from "./generated/icrc1"
|
|
436
|
+
|
|
437
|
+
export function SendThenToast({ arg }: { arg: TransferArg }) {
|
|
438
|
+
const client = useClient()
|
|
439
|
+
const ledger = client.canister<Actor>(actor, {
|
|
440
|
+
id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
|
|
441
|
+
})
|
|
442
|
+
const options = client.mutationOptions(ledger, "icrc1_transfer")
|
|
443
|
+
const transfer = useMutation({
|
|
444
|
+
...options,
|
|
445
|
+
// Typed, because a callback of yours leaves TanStack nothing else to
|
|
446
|
+
// infer the error type from.
|
|
447
|
+
onSettled: async (
|
|
448
|
+
data,
|
|
449
|
+
error: ReactorError<TransferError> | null,
|
|
450
|
+
variables,
|
|
451
|
+
onMutateResult,
|
|
452
|
+
context
|
|
453
|
+
) => {
|
|
454
|
+
await options.onSettled(data, error, variables, onMutateResult, context)
|
|
455
|
+
if (!error) toast.success("Sent")
|
|
456
|
+
},
|
|
457
|
+
})
|
|
458
|
+
return <button onClick={() => transfer.mutate(arg)}>Send</button>
|
|
459
|
+
}
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
**`onMutate`:** for an optimistic update, call the client's `onMutate` with
|
|
463
|
+
both arguments and spread its result into yours:
|
|
464
|
+
`{ ...options.onMutate(variables, context), previous }`. TanStack Query hands
|
|
465
|
+
the result to `onSettled`, which is how the client finds the reads to
|
|
466
|
+
invalidate. An `onMutate` that replaces the client's, as TanStack's own
|
|
467
|
+
optimistic recipe is written, keeps the write and its invalidation together
|
|
468
|
+
only from TanStack Query 5.89 on (`@ic-reactor/react` needs 5.90.2 or newer).
|
|
469
|
+
The spread form works everywhere. Either form keeps the caller on the client's
|
|
470
|
+
own `queryClient`: its `MutationCache` reads who started each run. On another
|
|
471
|
+
`QueryClient`, only the client's `onMutate` reads it, so from 5.89 on a write
|
|
472
|
+
whose `onMutate` replaced it there is refused (`caller_changed`). Before 5.89,
|
|
473
|
+
which passes no run context, TanStack must call the client's `onMutate` itself
|
|
474
|
+
there, as a method of the run's options: one of yours that calls it leaves
|
|
475
|
+
the write refused, and one that replaces it, sent as the caller current when
|
|
476
|
+
it is sent.
|
|
477
|
+
|
|
478
|
+
This example shows a new name at once and puts the old one back on failure.
|
|
479
|
+
The client's `onSettled` then re-reads the profile, so the page ends with what
|
|
480
|
+
the canister holds.
|
|
481
|
+
|
|
482
|
+
```tsx
|
|
483
|
+
import { principal } from "@meantjs/schema"
|
|
484
|
+
import type { ReactorError } from "@ic-reactor/core"
|
|
485
|
+
import { useAuth, useClient } from "@ic-reactor/react"
|
|
486
|
+
import { useMutation } from "@tanstack/react-query"
|
|
487
|
+
import { actor, type Actor, type Profile } from "./generated/backend"
|
|
488
|
+
|
|
489
|
+
export function Rename({ name }: { name: string }) {
|
|
490
|
+
const client = useClient()
|
|
491
|
+
const { principal: caller } = useAuth()
|
|
492
|
+
const backend = client.canister<Actor>(actor, {
|
|
493
|
+
id: "rrkah-fqaaa-aaaaa-aaaaq-cai",
|
|
494
|
+
})
|
|
495
|
+
const options = client.mutationOptions(backend, "set_name")
|
|
496
|
+
|
|
497
|
+
const rename = useMutation({
|
|
498
|
+
...options,
|
|
499
|
+
onMutate: async (variables, context) => {
|
|
500
|
+
const targets = options.onMutate(variables, context)
|
|
501
|
+
const [who, next] = variables
|
|
502
|
+
const key = client.queryKey(backend, "get_profile", who)
|
|
503
|
+
// A read in flight would land after this and overwrite the change.
|
|
504
|
+
await client.queryClient.cancelQueries({ queryKey: key })
|
|
505
|
+
const previous = client.queryClient.getQueryData<Profile>(key)
|
|
506
|
+
client.queryClient.setQueryData<Profile>(key, { name: next })
|
|
507
|
+
return { ...targets, key, previous }
|
|
508
|
+
},
|
|
509
|
+
// Typed, as in the previous example.
|
|
510
|
+
onError: (_error: ReactorError, _variables, result) => {
|
|
511
|
+
if (result?.previous)
|
|
512
|
+
client.queryClient.setQueryData(result.key, result.previous)
|
|
513
|
+
},
|
|
514
|
+
onSettled: (data, error: ReactorError | null, variables, result, context) =>
|
|
515
|
+
options.onSettled(data, error, variables, result, context),
|
|
516
|
+
})
|
|
517
|
+
|
|
518
|
+
return (
|
|
519
|
+
<button onClick={() => rename.mutate([principal(caller), name])}>
|
|
520
|
+
Rename
|
|
521
|
+
</button>
|
|
522
|
+
)
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
The key comes from `client.queryKey(backend, "get_profile", who)`, built for
|
|
527
|
+
the caller now. A key written by hand would match nothing. The
|
|
528
|
+
[Vite wallet example](/v4/examples/vite-wallet/) has a longer version for an
|
|
529
|
+
address book, in `src/optimistic-contacts.ts`.
|
|
530
|
+
|
|
531
|
+
## Outside React
|
|
532
|
+
|
|
533
|
+
A direct call on a canister is a write when the method is an update. It touches
|
|
534
|
+
no cache, so nothing is invalidated: refresh what you need yourself.
|
|
535
|
+
|
|
536
|
+
```ts
|
|
537
|
+
import { principal } from "@meantjs/schema"
|
|
538
|
+
import { isReactorError, parseUnits } from "@ic-reactor/core"
|
|
539
|
+
import { client, ledger } from "./ledger"
|
|
540
|
+
|
|
541
|
+
try {
|
|
542
|
+
// `client` here is anonymous, so this is refused. Build the client with an
|
|
543
|
+
// Identity, or with an auth that is signed in, to send.
|
|
544
|
+
const block = await ledger.icrc1_transfer({
|
|
545
|
+
to: { owner: principal("aaaaa-aa"), subaccount: null },
|
|
546
|
+
amount: parseUnits("1.5", 8),
|
|
547
|
+
fee: null,
|
|
548
|
+
memo: null,
|
|
549
|
+
from_subaccount: null,
|
|
550
|
+
created_at_time: null,
|
|
551
|
+
})
|
|
552
|
+
console.log("block", block)
|
|
553
|
+
await client.queryClient.invalidateQueries({
|
|
554
|
+
queryKey: client.queryKey(ledger),
|
|
555
|
+
})
|
|
556
|
+
} catch (error) {
|
|
557
|
+
if (!isReactorError(error, ledger, "icrc1_transfer")) throw error
|
|
558
|
+
if (error.kind === "canister_err") {
|
|
559
|
+
console.error("refused:", error.err.tag) // error.err is a TransferError
|
|
560
|
+
} else if (error.mayHaveExecuted) {
|
|
561
|
+
console.error("unknown outcome: read the balance before sending again")
|
|
562
|
+
} else {
|
|
563
|
+
console.error(error.kind, error.message)
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
`isReactorError(error, ledger, "icrc1_transfer")` narrows to the
|
|
569
|
+
`ReactorError` of that method, so `err` is its `TransferError`; it is `false`
|
|
570
|
+
for an error of any other call (see
|
|
571
|
+
[Errors](/v4/guides/errors/#testing-for-a-reactorerror)). A direct update is re-sent by the client under the
|
|
572
|
+
same two rules as above, and under no others.
|