├── .npmrc ├── .github ├── CODEOWNERS ├── repo_policies │ └── BOT_APPROVED_FILES ├── actions │ └── prepare │ │ └── action.yml ├── pull_request_template.md └── workflows │ ├── tests-integration.yml │ └── pr-checks.yml ├── .prettierrc.json ├── packages ├── utils │ ├── tsconfig.json │ ├── src │ │ ├── constants │ │ │ └── constants.ts │ │ ├── enums │ │ │ └── token.enums.ts │ │ ├── types │ │ │ ├── query.params.ts │ │ │ ├── agent.utils.ts │ │ │ ├── actor-type.utils.ts │ │ │ ├── did.utils.ts │ │ │ ├── canister.options.ts │ │ │ └── query-and-update.params.ts │ │ ├── services │ │ │ └── canister.ts │ │ ├── utils │ │ │ ├── crc.utils.spec.ts │ │ │ ├── principal.utils.ts │ │ │ ├── base64.utils.ts │ │ │ ├── principal.utils.spec.ts │ │ │ ├── base32.utils.spec.ts │ │ │ ├── debounce.utils.ts │ │ │ ├── crypto.utils.ts │ │ │ ├── nullish.utils.spec.ts │ │ │ ├── debounce.utils.spec.ts │ │ │ ├── actor.utils.ts │ │ │ ├── nullish.utils.ts │ │ │ └── asserts.utils.ts │ │ ├── mocks │ │ │ ├── identity.mock.ts │ │ │ └── agent.mock.ts │ │ └── index.ts │ ├── esbuild.mjs │ ├── vitest.config.ts │ └── package.json ├── zod-schemas │ ├── tsconfig.json │ ├── src │ │ ├── index.ts │ │ └── principal.ts │ ├── esbuild.mjs │ ├── vitest.config.ts │ └── package.json ├── canisters │ ├── src │ │ ├── ledger │ │ │ ├── icp │ │ │ │ ├── errors │ │ │ │ │ └── index.errors.ts │ │ │ │ ├── types │ │ │ │ │ ├── common.ts │ │ │ │ │ ├── ledger.options.ts │ │ │ │ │ ├── index.params.ts │ │ │ │ │ └── ledger.params.ts │ │ │ │ ├── constants │ │ │ │ │ ├── canister_ids.ts │ │ │ │ │ └── constants.ts │ │ │ │ ├── mocks │ │ │ │ │ ├── ledger.request.mock.ts │ │ │ │ │ └── ledger.mock.ts │ │ │ │ ├── utils │ │ │ │ │ └── params.utils.ts │ │ │ │ └── index.ts │ │ │ └── icrc │ │ │ │ ├── errors │ │ │ │ └── index.errors.ts │ │ │ │ ├── types │ │ │ │ ├── canister.types.ts │ │ │ │ ├── canister.options.ts │ │ │ │ ├── index-ng.params.ts │ │ │ │ └── ledger.responses.ts │ │ │ │ ├── index.ts │ │ │ │ ├── converters │ │ │ │ ├── index.converters.ts │ │ │ │ ├── converters.ts │ │ │ │ └── converters.spec.ts │ │ │ │ ├── canister.ts │ │ │ │ ├── mocks │ │ │ │ └── ledger.mock.ts │ │ │ │ ├── nft-ledger.canister.ts │ │ │ │ ├── nft-ledger.canister.spec.ts │ │ │ │ └── utils │ │ │ │ └── payment.utils.ts │ │ ├── sns │ │ │ ├── errors │ │ │ │ ├── governance.errors.ts │ │ │ │ ├── common.errors.ts │ │ │ │ └── swap.errors.ts │ │ │ ├── types │ │ │ │ ├── common.ts │ │ │ │ ├── swap.params.ts │ │ │ │ ├── governance_test.params.ts │ │ │ │ └── canister.options.ts │ │ │ ├── constants │ │ │ │ └── governance.constants.ts │ │ │ ├── converters │ │ │ │ └── swap.converters.ts │ │ │ ├── mocks │ │ │ │ ├── ledger.mock.ts │ │ │ │ ├── sns.mock.ts │ │ │ │ └── governance.mock.ts │ │ │ ├── root.canister.spec.ts │ │ │ ├── utils │ │ │ │ ├── governance.utils.spec.ts │ │ │ │ ├── error.utils.ts │ │ │ │ ├── governance.utils.ts │ │ │ │ └── error.utils.spec.ts │ │ │ ├── index.ts │ │ │ ├── sns.spec.ts │ │ │ ├── root.canister.ts │ │ │ └── enums │ │ │ │ └── swap.enums.ts │ │ ├── declarations │ │ │ ├── index.ts │ │ │ ├── cmc │ │ │ │ ├── cmc.idl.d.ts │ │ │ │ └── cmc.certified.idl.d.ts │ │ │ ├── sns │ │ │ │ ├── root.idl.d.ts │ │ │ │ ├── swap.idl.d.ts │ │ │ │ ├── governance.idl.d.ts │ │ │ │ ├── governance_test.idl.d.ts │ │ │ │ ├── root.certified.idl.d.ts │ │ │ │ ├── swap.certified.idl.d.ts │ │ │ │ ├── governance.certified.idl.d.ts │ │ │ │ └── governance_test.certified.idl.d.ts │ │ │ ├── ckbtc │ │ │ │ ├── bitcoin.idl.d.ts │ │ │ │ ├── minter.idl.d.ts │ │ │ │ ├── bitcoin.certified.idl.d.ts │ │ │ │ └── minter.certified.idl.d.ts │ │ │ ├── cketh │ │ │ │ ├── minter.idl.d.ts │ │ │ │ ├── orchestrator.idl.d.ts │ │ │ │ ├── minter.certified.idl.d.ts │ │ │ │ └── orchestrator.certified.idl.d.ts │ │ │ ├── nns │ │ │ │ ├── governance.idl.d.ts │ │ │ │ ├── sns_wasm.idl.d.ts │ │ │ │ ├── genesis_token.idl.d.ts │ │ │ │ ├── governance_test.idl.d.ts │ │ │ │ ├── governance.certified.idl.d.ts │ │ │ │ ├── sns_wasm.certified.idl.d.ts │ │ │ │ ├── genesis_token.certified.idl.d.ts │ │ │ │ ├── governance_test.certified.idl.d.ts │ │ │ │ ├── old_list_neurons_service.certified.idl.d.ts │ │ │ │ └── genesis_token.did │ │ │ ├── ledger-icp │ │ │ │ ├── index.idl.d.ts │ │ │ │ ├── ledger.idl.d.ts │ │ │ │ ├── index.certified.idl.d.ts │ │ │ │ └── ledger.certified.idl.d.ts │ │ │ ├── ledger-icrc │ │ │ │ ├── icrc_icrc-1.idl.d.ts │ │ │ │ ├── icrc_icrc-10.idl.d.ts │ │ │ │ ├── icrc_index.idl.d.ts │ │ │ │ ├── icrc_ledger.idl.d.ts │ │ │ │ ├── icrc_nft-ledger.idl.d.ts │ │ │ │ ├── icrc_icrc-1.certified.idl.d.ts │ │ │ │ ├── icrc_icrc-10.certified.idl.d.ts │ │ │ │ ├── icrc_index.certified.idl.d.ts │ │ │ │ ├── icrc_ledger.certified.idl.d.ts │ │ │ │ ├── icrc_nft-ledger.certified.idl.d.ts │ │ │ │ ├── icrc_icrc-10.did │ │ │ │ ├── icrc_icrc-10.certified.idl.js │ │ │ │ ├── icrc_icrc-10.idl.js │ │ │ │ ├── icrc_icrc-10.d.ts │ │ │ │ └── icrc_icrc-1.did │ │ │ ├── assets │ │ │ │ ├── assets_assetstorage.idl.d.ts │ │ │ │ └── assets_assetstorage.certified.idl.d.ts │ │ │ ├── ic-management │ │ │ │ ├── ic-management.idl.d.ts │ │ │ │ └── ic-management.certified.idl.d.ts │ │ │ └── _types.ts │ │ ├── index.ts │ │ ├── nns │ │ │ ├── constants │ │ │ │ ├── constants.ts │ │ │ │ └── canister_ids.ts │ │ │ ├── types │ │ │ │ ├── sns_wasm.options.ts │ │ │ │ ├── common.ts │ │ │ │ └── governance.options.ts │ │ │ ├── sns_wasm.canister.spec.ts │ │ │ ├── errors │ │ │ │ └── governance.errors.ts │ │ │ ├── index.ts │ │ │ ├── mocks │ │ │ │ └── sns_wasm.mock.ts │ │ │ ├── sns_wasm.canister.ts │ │ │ ├── genesis_token.canister.ts │ │ │ ├── genesis_token.canister.spec.ts │ │ │ ├── canisters │ │ │ │ └── governance │ │ │ │ │ └── services.ts │ │ │ └── utils │ │ │ │ └── account_identifier.utils.ts │ │ ├── cmc │ │ │ ├── index.ts │ │ │ ├── cmc.options.ts │ │ │ ├── cmc.mock.ts │ │ │ └── cmc.errors.ts │ │ ├── ic-management │ │ │ ├── types │ │ │ │ ├── canister.options.ts │ │ │ │ └── ic-management.responses.ts │ │ │ ├── index.ts │ │ │ ├── ic-management.mock.ts │ │ │ └── utils │ │ │ │ └── ic-management.utils.spec.ts │ │ ├── ckbtc │ │ │ ├── types │ │ │ │ ├── btc.ts │ │ │ │ ├── canister.options.ts │ │ │ │ ├── minter.responses.ts │ │ │ │ ├── minter.params.ts │ │ │ │ └── bitcoin.params.ts │ │ │ ├── mocks │ │ │ │ └── minter.mock.ts │ │ │ ├── enums │ │ │ │ └── btc.enums.ts │ │ │ ├── index.ts │ │ │ └── errors │ │ │ │ └── btc.errors.ts │ │ ├── index.spec.ts │ │ ├── cketh │ │ │ ├── types │ │ │ │ ├── canister.options.ts │ │ │ │ └── minter.params.ts │ │ │ ├── index.ts │ │ │ └── mocks │ │ │ │ └── minter.mock.ts │ │ └── assets │ │ │ ├── assets.canister.ts │ │ │ ├── utils │ │ │ ├── path-polyfill.ts │ │ │ ├── fs-polyfill.ts │ │ │ ├── assets.ts │ │ │ └── limit.ts │ │ │ └── readable │ │ │ ├── readable-blob.spec.ts │ │ │ ├── readable-path.spec.ts │ │ │ ├── readable-file.ts │ │ │ ├── readable-blob.ts │ │ │ ├── readable-bytes.ts │ │ │ ├── readable-file.spec.ts │ │ │ ├── readable.ts │ │ │ └── readable-bytes.spec.ts │ ├── tsconfig.json │ ├── esbuild.mjs │ ├── .gitignore │ ├── .npmignore │ └── vitest.config.ts ├── cmc │ ├── tsconfig.json │ ├── esbuild.mjs │ ├── src │ │ ├── index.spec.ts │ │ └── index.ts │ ├── vitest.config.ts │ ├── package.json │ └── README.md ├── nns │ ├── tsconfig.json │ ├── esbuild.mjs │ ├── vitest.config.ts │ ├── src │ │ ├── index.spec.ts │ │ └── index.ts │ └── package.json ├── sns │ ├── tsconfig.json │ ├── esbuild.mjs │ ├── vitest.config.ts │ ├── src │ │ └── index.spec.ts │ └── package.json ├── ckbtc │ ├── tsconfig.json │ ├── esbuild.mjs │ ├── vitest.config.ts │ ├── src │ │ ├── index.spec.ts │ │ └── index.ts │ └── package.json ├── cketh │ ├── tsconfig.json │ ├── esbuild.mjs │ ├── vitest.config.ts │ ├── src │ │ ├── index.spec.ts │ │ └── index.ts │ └── package.json ├── ic-management │ ├── tsconfig.json │ ├── esbuild.mjs │ ├── src │ │ ├── index.spec.ts │ │ └── index.ts │ ├── vitest.config.ts │ └── package.json ├── ledger-icp │ ├── tsconfig.json │ ├── esbuild.mjs │ ├── vitest.config.ts │ ├── src │ │ ├── index.spec.ts │ │ └── index.ts │ └── package.json ├── ledger-icrc │ ├── tsconfig.json │ ├── esbuild.mjs │ ├── vitest.config.ts │ ├── src │ │ ├── index.spec.ts │ │ └── index.ts │ └── package.json ├── nns-proto │ ├── tsconfig.json │ ├── esbuild.mjs │ ├── README.md │ ├── proto │ │ ├── nns_common.proto │ │ ├── base_types.proto │ │ ├── base_types_pb.d.ts │ │ ├── nervous_system.proto │ │ └── nns_common_pb.d.ts │ ├── src │ │ └── index.ts │ └── package.json └── ledger │ └── README.md ├── docs ├── .gitignore ├── tsconfig.json ├── package.json ├── src │ └── content │ │ └── docs │ │ ├── upgrading │ │ └── v2.md │ │ ├── quick-start.md │ │ └── installation.mdx └── typedoc.json ├── scripts ├── finish-integration-tests ├── build-docs ├── rmdir.mjs ├── fmt-sh ├── prepare-integration-tests ├── update_payloads_idl_declarations.sh ├── copy-declarations ├── docs.js ├── update-agent ├── build.utils.mjs ├── build-next ├── publish-npm.sh ├── refreshNeuron.mjs └── update_proto.sh ├── eslint-local-rules.cjs ├── tests └── integration │ ├── canisters │ └── assets │ │ └── .ic-assets.json5 │ ├── tsconfig.json │ ├── src │ └── utils │ │ ├── env.ts │ │ └── identity.ts │ ├── dfx.json │ ├── package.json │ └── vitest.config.ts ├── tsconfig.eslint.json ├── tsconfig.spec.json ├── vitest.config.ts ├── .prettierignore ├── tsconfig.json └── eslint.config.mjs /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | ignore-scripts=true -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @dfinity/oisy @dfinity/governance-team 2 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["prettier-plugin-organize-imports"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /packages/zod-schemas/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /packages/utils/src/constants/constants.ts: -------------------------------------------------------------------------------- 1 | export const E8S_PER_TOKEN = BigInt(100000000); 2 | -------------------------------------------------------------------------------- /packages/zod-schemas/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./principal"; 2 | export * from "./url"; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icp/errors/index.errors.ts: -------------------------------------------------------------------------------- 1 | export class IndexError extends Error {} 2 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/errors/index.errors.ts: -------------------------------------------------------------------------------- 1 | export class IndexError extends Error {} 2 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | src/content/tmp/ 3 | src/content/docs/api/ 4 | src/content/docs/changelog.md 5 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/errors/governance.errors.ts: -------------------------------------------------------------------------------- 1 | export class SnsGovernanceError extends Error {} 2 | -------------------------------------------------------------------------------- /packages/cmc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/nns/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/sns/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./_factory"; 2 | export type * from "./_types"; 3 | -------------------------------------------------------------------------------- /packages/ckbtc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/cketh/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /scripts/finish-integration-tests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ueo pipefail 3 | 4 | dfx stop 5 | dfx killall 6 | -------------------------------------------------------------------------------- /packages/canisters/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/ic-management/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/ledger-icp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/ledger-icrc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "include": ["../packages/canisters/src/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/types/common.ts: -------------------------------------------------------------------------------- 1 | export type E8s = bigint; 2 | 3 | export type Option = T | undefined; 4 | -------------------------------------------------------------------------------- /packages/ckbtc/esbuild.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { build } from "../../scripts/esbuild.mjs"; 4 | 5 | build(); 6 | -------------------------------------------------------------------------------- /packages/cketh/esbuild.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { build } from "../../scripts/esbuild.mjs"; 4 | 5 | build(); 6 | -------------------------------------------------------------------------------- /packages/cmc/esbuild.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { build } from "../../scripts/esbuild.mjs"; 4 | 5 | build(); 6 | -------------------------------------------------------------------------------- /packages/nns-proto/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*", "proto/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/nns/esbuild.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { build } from "../../scripts/esbuild.mjs"; 4 | 5 | build(); 6 | -------------------------------------------------------------------------------- /packages/sns/esbuild.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { build } from "../../scripts/esbuild.mjs"; 4 | 5 | build(); 6 | -------------------------------------------------------------------------------- /packages/utils/esbuild.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { build } from "../../scripts/esbuild.mjs"; 4 | 5 | build(); 6 | -------------------------------------------------------------------------------- /eslint-local-rules.cjs: -------------------------------------------------------------------------------- 1 | // @ts-expect-error 2 | module.exports = require("@dfinity/eslint-config-oisy-wallet/eslint-local-rules"); 3 | -------------------------------------------------------------------------------- /packages/ledger-icp/esbuild.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { build } from "../../scripts/esbuild.mjs"; 4 | 5 | build(); 6 | -------------------------------------------------------------------------------- /packages/ic-management/esbuild.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { build } from "../../scripts/esbuild.mjs"; 4 | 5 | build(); 6 | -------------------------------------------------------------------------------- /packages/ledger-icrc/esbuild.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { build } from "../../scripts/esbuild.mjs"; 4 | 5 | build(); 6 | -------------------------------------------------------------------------------- /packages/zod-schemas/esbuild.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { build } from "../../scripts/esbuild.mjs"; 4 | 5 | build(); 6 | -------------------------------------------------------------------------------- /packages/canisters/src/index.ts: -------------------------------------------------------------------------------- 1 | throw new Error( 2 | "This package has no default entry point. Please import from a subpath.", 3 | ); 4 | -------------------------------------------------------------------------------- /tests/integration/canisters/assets/.ic-assets.json5: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | match: "**/*", 4 | security_policy: "standard", 5 | }, 6 | ] 7 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true 5 | }, 6 | "exclude": [] 7 | } 8 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/cmc/cmc.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/sns/root.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/sns/swap.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ckbtc/bitcoin.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ckbtc/minter.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/cketh/minter.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/nns/governance.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/nns/sns_wasm.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/sns/governance.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /tests/integration/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.spec.json", 3 | "include": ["src/**/*"], 4 | "exclude": ["node_modules", ".dfx"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/canisters/esbuild.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { build } from "../../scripts/esbuild.mjs"; 4 | 5 | build({ nodeFormat: "esm", multi: true }); 6 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/cketh/orchestrator.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/cmc/cmc.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icp/index.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icp/ledger.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/nns/genesis_token.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/nns/governance_test.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/sns/governance_test.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/sns/root.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/sns/swap.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icp/types/common.ts: -------------------------------------------------------------------------------- 1 | export type AccountIdentifierHex = string; 2 | export type BlockHeight = bigint; 3 | export type E8s = bigint; 4 | -------------------------------------------------------------------------------- /packages/nns-proto/esbuild.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { build } from "../../scripts/esbuild.mjs"; 4 | 5 | build({ multi: false, nodeFormat: "cjs" }); 6 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ckbtc/bitcoin.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ckbtc/minter.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/cketh/minter.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_icrc-1.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_icrc-10.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_index.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_ledger.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/nns/governance.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/nns/sns_wasm.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/sns/governance.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/ledger/README.md: -------------------------------------------------------------------------------- 1 | # ledger-js 2 | 3 | ⚠️ The library `@dfinity/ledger` has been deprecated, renamed, and replaced by [@dfinity/ledger-icrc](../ledger-icrc). 4 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/assets/assets_assetstorage.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/cketh/orchestrator.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ic-management/ic-management.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icp/index.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icp/ledger.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_nft-ledger.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/nns/genesis_token.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/nns/governance_test.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/sns/governance_test.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/utils/src/enums/token.enums.ts: -------------------------------------------------------------------------------- 1 | export enum FromStringToTokenError { 2 | FractionalMoreThan8Decimals, 3 | InvalidFormat, 4 | FractionalTooManyDecimals, 5 | } 6 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_icrc-1.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_icrc-10.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_index.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_ledger.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/nns/old_list_neurons_service.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@dfinity/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/assets/assets_assetstorage.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ic-management/ic-management.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_nft-ledger.certified.idl.d.ts: -------------------------------------------------------------------------------- 1 | import type { IDL } from "@icp-sdk/core/candid"; 2 | export const idlFactory: IDL.InterfaceFactory; 3 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/types/canister.types.ts: -------------------------------------------------------------------------------- 1 | import type { IcrcIcrc1Service } from "../../../declarations"; 2 | 3 | export type IcrcCanisterService = Pick; 4 | -------------------------------------------------------------------------------- /packages/canisters/src/nns/constants/constants.ts: -------------------------------------------------------------------------------- 1 | // Note: Canister IDs are not constant, so are not provided here. 2 | // The same applies to HOST. 3 | export const E8S_PER_TOKEN = BigInt(100000000); 4 | -------------------------------------------------------------------------------- /.github/repo_policies/BOT_APPROVED_FILES: -------------------------------------------------------------------------------- 1 | packages/*/candid/*.did 2 | packages/*/candid/*.idl.js 3 | packages/*/candid/*.d.ts 4 | packages/*/declarations/*.did 5 | packages/*/declarations/*.idl.js 6 | packages/*/declarations/*.d.ts -------------------------------------------------------------------------------- /packages/canisters/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything 2 | * 3 | 4 | # Except 5 | !.npmignore 6 | !src/ 7 | !esbuild.mjs 8 | !LICENSE 9 | !package.json 10 | !README.md 11 | !tsconfig.json 12 | !vitest.config.ts 13 | 14 | !src/** -------------------------------------------------------------------------------- /packages/cmc/src/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { CMCCanister } from "./index"; 2 | 3 | describe("@dfinity/cmc", () => { 4 | it("should re-export CMCCanister", () => { 5 | expect(CMCCanister).not.toBeUndefined(); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/canisters/.npmignore: -------------------------------------------------------------------------------- 1 | # Git and config files 2 | .gitignore 3 | tsconfig.json 4 | vitest.config.ts 5 | 6 | # Build and publish scripts 7 | esbuild.mjs 8 | 9 | # Temporary files 10 | package.json.backup 11 | 12 | # Sources 13 | src/ -------------------------------------------------------------------------------- /packages/canisters/src/nns/types/sns_wasm.options.ts: -------------------------------------------------------------------------------- 1 | import type { CanisterOptions } from "@dfinity/utils"; 2 | import type { SnsWasmService } from "../../declarations"; 3 | 4 | export type SnsWasmCanisterOptions = CanisterOptions; 5 | -------------------------------------------------------------------------------- /packages/utils/src/types/query.params.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The common parameters to query features 3 | */ 4 | export interface QueryParams { 5 | /** Perform update calls (certified) or query calls (not certified). */ 6 | certified?: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /packages/canisters/src/cmc/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module api/cmc 3 | */ 4 | 5 | export type { CmcDid } from "../declarations"; 6 | export { CmcCanister } from "./cmc.canister"; 7 | export * from "./cmc.errors"; 8 | export type * from "./cmc.options"; 9 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icp/types/ledger.options.ts: -------------------------------------------------------------------------------- 1 | import type { CanisterOptions } from "@dfinity/utils"; 2 | import type { IcpLedgerService } from "../../../declarations"; 3 | 4 | export type IcpLedgerCanisterOptions = CanisterOptions; 5 | -------------------------------------------------------------------------------- /packages/canisters/src/nns/types/common.ts: -------------------------------------------------------------------------------- 1 | export type CanisterIdString = string; 2 | export type NeuronId = bigint; 3 | export type E8s = bigint; 4 | export type Memo = bigint; 5 | export type PrincipalString = string; 6 | 7 | export type Option = T | undefined; 8 | -------------------------------------------------------------------------------- /scripts/build-docs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | docs_version=${DOCS_VERSION:-local} 4 | 5 | rm -rf ./dist/$docs_version/ && mkdir -p ./dist/$docs_version/ 6 | 7 | typedoc --options ./typedoc.json 8 | 9 | cp -r ./src/content/docs/* ./dist/$docs_version/ 10 | -------------------------------------------------------------------------------- /packages/ic-management/src/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { ICManagementCanister } from "./index"; 2 | 3 | describe("@dfinity/ic-management", () => { 4 | it("should re-export IcManagementCanister", () => { 5 | expect(ICManagementCanister).not.toBeUndefined(); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/types/swap.params.ts: -------------------------------------------------------------------------------- 1 | import type { E8s } from "./common"; 2 | 3 | /** 4 | * The parameters to create a sale ticket (payment flow) 5 | */ 6 | export interface NewSaleTicketParams { 7 | subaccount?: Uint8Array; 8 | amount_icp_e8s: E8s; 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "composite": true, 5 | "types": ["vitest/globals", "node"] 6 | }, 7 | "exclude": [], 8 | "include": ["./packages/**/*.js", "./packages/**/*.ts", "./vitest.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/cmc/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { baseConfig } from "../../vitest.config"; 3 | 4 | export default defineConfig({ 5 | ...baseConfig, 6 | test: { 7 | ...baseConfig.test, 8 | exclude: ["./dist"], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /packages/nns/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { baseConfig } from "../../vitest.config"; 3 | 4 | export default defineConfig({ 5 | ...baseConfig, 6 | test: { 7 | ...baseConfig.test, 8 | exclude: ["./dist"], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /packages/sns/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { baseConfig } from "../../vitest.config"; 3 | 4 | export default defineConfig({ 5 | ...baseConfig, 6 | test: { 7 | ...baseConfig.test, 8 | exclude: ["./dist"], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /packages/canisters/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { baseConfig } from "../../vitest.config"; 3 | 4 | export default defineConfig({ 5 | ...baseConfig, 6 | test: { 7 | ...baseConfig.test, 8 | exclude: ["./dist"], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /packages/ckbtc/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { baseConfig } from "../../vitest.config"; 3 | 4 | export default defineConfig({ 5 | ...baseConfig, 6 | test: { 7 | ...baseConfig.test, 8 | exclude: ["./dist"], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /packages/cketh/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { baseConfig } from "../../vitest.config"; 3 | 4 | export default defineConfig({ 5 | ...baseConfig, 6 | test: { 7 | ...baseConfig.test, 8 | exclude: ["./dist"], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /packages/utils/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { baseConfig } from "../../vitest.config"; 3 | 4 | export default defineConfig({ 5 | ...baseConfig, 6 | test: { 7 | ...baseConfig.test, 8 | exclude: ["./dist"], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /packages/ic-management/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { baseConfig } from "../../vitest.config"; 3 | 4 | export default defineConfig({ 5 | ...baseConfig, 6 | test: { 7 | ...baseConfig.test, 8 | exclude: ["./dist"], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /packages/ledger-icp/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { baseConfig } from "../../vitest.config"; 3 | 4 | export default defineConfig({ 5 | ...baseConfig, 6 | test: { 7 | ...baseConfig.test, 8 | exclude: ["./dist"], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /packages/ledger-icrc/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { baseConfig } from "../../vitest.config"; 3 | 4 | export default defineConfig({ 5 | ...baseConfig, 6 | test: { 7 | ...baseConfig.test, 8 | exclude: ["./dist"], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /packages/zod-schemas/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { baseConfig } from "../../vitest.config"; 3 | 4 | export default defineConfig({ 5 | ...baseConfig, 6 | test: { 7 | ...baseConfig.test, 8 | exclude: ["./dist"], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/errors/common.errors.ts: -------------------------------------------------------------------------------- 1 | // This is possible specially in SNS projects/ 2 | // Because they share the same canisters but in different versions. 3 | export class UnsupportedMethodError extends Error { 4 | constructor(public readonly methodName: string) { 5 | super(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/integration/src/utils/env.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | import { execSync } from "child_process"; 3 | 4 | export const getCanisterId = (canisterName: string): Principal => 5 | Principal.fromText( 6 | execSync(`dfx canister id ${canisterName}`).toString().trim(), 7 | ); 8 | -------------------------------------------------------------------------------- /packages/utils/src/types/agent.utils.ts: -------------------------------------------------------------------------------- 1 | import type { HttpAgentOptions, Identity } from "@icp-sdk/core/agent"; 2 | 3 | export type CreateAgentParams = Pick< 4 | HttpAgentOptions, 5 | "host" | "retryTimes" | "verifyQuerySignatures" 6 | > & { 7 | identity: Identity; 8 | fetchRootKey?: boolean; 9 | }; 10 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icp/types/index.params.ts: -------------------------------------------------------------------------------- 1 | import type { QueryParams } from "@dfinity/utils"; 2 | import type { AccountIdentifierParam } from "./ledger.params"; 3 | 4 | export type GetTransactionsParams = { 5 | maxResults: bigint; 6 | start?: bigint; 7 | accountIdentifier: AccountIdentifierParam; 8 | } & QueryParams; 9 | -------------------------------------------------------------------------------- /scripts/rmdir.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { existsSync, rmSync } from "fs"; 4 | import { join } from "path"; 5 | 6 | const rmDir = () => { 7 | const dir = join(process.cwd(), "dist"); 8 | 9 | if (!existsSync(dir)) { 10 | return; 11 | } 12 | 13 | rmSync(dir, { recursive: true }); 14 | }; 15 | 16 | rmDir(); 17 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/types/governance_test.params.ts: -------------------------------------------------------------------------------- 1 | import type { QueryParams } from "@dfinity/utils"; 2 | import type { SnsGovernanceDid } from "../../declarations"; 3 | import type { E8s } from "./common"; 4 | 5 | export interface SnsAddMaturityParams extends QueryParams { 6 | id: SnsGovernanceDid.NeuronId; 7 | amountE8s: E8s; 8 | } 9 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icp/constants/canister_ids.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | 3 | export const MAINNET_LEDGER_CANISTER_ID = Principal.fromText( 4 | "ryjl3-tyaaa-aaaaa-aaaba-cai", 5 | ); 6 | 7 | export const MAINNET_INDEX_CANISTER_ID = Principal.fromText( 8 | "qhbym-qaaaa-aaaaa-aaafq-cai", 9 | ); 10 | -------------------------------------------------------------------------------- /packages/utils/src/types/actor-type.utils.ts: -------------------------------------------------------------------------------- 1 | import type { ActorMethod } from "@icp-sdk/core/agent"; 2 | 3 | export type ServiceParam = 4 | S[K] extends ActorMethod ? A : never; 5 | 6 | export type ServiceResponse = 7 | S[K] extends ActorMethod ? Awaited : never; 8 | -------------------------------------------------------------------------------- /packages/canisters/src/ic-management/types/canister.options.ts: -------------------------------------------------------------------------------- 1 | import type { CanisterOptions } from "@dfinity/utils"; 2 | import type { IcManagementService } from "../../declarations"; 3 | 4 | export type IcManagementCanisterOptions = Pick< 5 | CanisterOptions, 6 | "agent" | "serviceOverride" | "certifiedServiceOverride" 7 | >; 8 | -------------------------------------------------------------------------------- /packages/canisters/src/ckbtc/types/btc.ts: -------------------------------------------------------------------------------- 1 | import type { BtcAddressType, BtcNetwork } from "../enums/btc.enums"; 2 | 3 | export interface BtcAddress { 4 | address: string; 5 | network?: BtcNetwork; 6 | } 7 | 8 | export interface BtcAddressInfo extends Required { 9 | parser: "bip-173" | "base58"; 10 | type: BtcAddressType; 11 | } 12 | -------------------------------------------------------------------------------- /tests/integration/dfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "canisters": { 3 | "assets": { 4 | "type": "assets", 5 | "source": ["canisters/assets"], 6 | "build": "" 7 | } 8 | }, 9 | "defaults": { 10 | "build": { 11 | "packtool": "", 12 | "args": "" 13 | } 14 | }, 15 | "output_env_file": ".env", 16 | "version": 1 17 | } 18 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/constants/governance.constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A default length for the queried list of neurons 3 | * 4 | * Source: https://github.com/dfinity/ic/blob/master/rs/sns/governance/src/neuron.rs 5 | */ 6 | export const MAX_LIST_NEURONS_RESULTS = 100; 7 | export const MAX_NEURONS_SUBACCOUNTS = 2 ** 16; 8 | export const DEFAULT_PROPOSALS_LIMIT = 10; 9 | -------------------------------------------------------------------------------- /packages/canisters/src/cmc/cmc.options.ts: -------------------------------------------------------------------------------- 1 | import type { CanisterOptions } from "@dfinity/utils"; 2 | import type { Principal } from "@icp-sdk/core/principal"; 3 | import type { CmcService } from "../declarations"; 4 | 5 | export interface CmcCanisterOptions extends Omit< 6 | CanisterOptions, 7 | "canisterId" 8 | > { 9 | canisterId: Principal; 10 | } 11 | -------------------------------------------------------------------------------- /tests/integration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dfinity/icp-js-canisters-tests-integration", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "pretest": "bash ../../scripts/prepare-integration-tests", 7 | "test": "npm run pretest && vitest && npm run posttest", 8 | "posttest": "bash ../../scripts/finish-integration-tests" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.github/actions/prepare/action.yml: -------------------------------------------------------------------------------- 1 | name: Prepare 2 | 3 | description: Checkout and install dependencies 4 | 5 | runs: 6 | using: composite 7 | steps: 8 | - uses: actions/setup-node@v4 9 | with: 10 | node-version: 24 11 | registry-url: 'https://registry.npmjs.org' 12 | - name: Install dependencies 13 | shell: bash 14 | run: npm ci 15 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, type ViteUserConfig } from "vitest/config"; 2 | 3 | export const baseConfig: ViteUserConfig = { 4 | test: { 5 | environment: "node", 6 | globals: true, 7 | watch: false, 8 | exclude: ["tests/integration/**", "node_modules/**"], 9 | }, 10 | }; 11 | 12 | export default defineConfig({ 13 | ...baseConfig, 14 | }); 15 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Motivation 2 | 3 | 4 | 5 | # Changes 6 | 7 | 8 | 9 | # Tests 10 | 11 | 12 | 13 | # Todos 14 | 15 | - [ ] Add entry to changelog (if necessary). 16 | -------------------------------------------------------------------------------- /packages/ledger-icp/src/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { IndexCanister, LedgerCanister } from "./index"; 2 | 3 | describe("@dfinity/ledger-icp", () => { 4 | it("should re-export LedgerCanister", () => { 5 | expect(LedgerCanister).not.toBeUndefined(); 6 | }); 7 | 8 | it("should re-export IndexCanister", () => { 9 | expect(IndexCanister).not.toBeUndefined(); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/types/canister.options.ts: -------------------------------------------------------------------------------- 1 | import type { CanisterOptions } from "@dfinity/utils"; 2 | import type { Principal } from "@icp-sdk/core/principal"; 3 | 4 | export interface SnsCanisterOptions extends Omit< 5 | CanisterOptions, 6 | "canisterId" 7 | > { 8 | // The canister's ID is mandatory in Sns canister classes. 9 | canisterId: Principal; 10 | } 11 | -------------------------------------------------------------------------------- /packages/ckbtc/src/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { BitcoinCanister, CkBTCMinterCanister } from "./index"; 2 | 3 | describe("@dfinity/ckbtc", () => { 4 | it("should re-export CkBTCMinterCanister", () => { 5 | expect(CkBTCMinterCanister).not.toBeUndefined(); 6 | }); 7 | 8 | it("should re-export BitcoinCanister", () => { 9 | expect(BitcoinCanister).not.toBeUndefined(); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dfinity/icp-js-canisters-docs", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "docs": "../scripts/build-docs" 7 | }, 8 | "devDependencies": { 9 | "@dfinity/typedoc-plugin-icp-docs": "^0.0.3", 10 | "typedoc": "^0.28.14", 11 | "typedoc-plugin-frontmatter": "^1.3.0", 12 | "typedoc-plugin-markdown": "^4.9.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/canisters/src/ckbtc/types/canister.options.ts: -------------------------------------------------------------------------------- 1 | import type { CanisterOptions } from "@dfinity/utils"; 2 | import type { Principal } from "@icp-sdk/core/principal"; 3 | 4 | export interface CkBtcCanisterOptions extends Omit< 5 | CanisterOptions, 6 | "canisterId" 7 | > { 8 | // The canister's ID is mandatory to instantiate a ckBTC related canister. 9 | canisterId: Principal; 10 | } 11 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_icrc-10.did: -------------------------------------------------------------------------------- 1 | // Generated from dfinity/ICRC commit 1df0c6af6ecca4f4eb1956c67b29c0d13279f1cd for file 'ICRCs/ICRC-10/ICRC-10.did' 2 | 3 | type SupportedStandard = record { name : text; url : text; }; 4 | type SupportedStandardsResponse = vec SupportedStandard; 5 | 6 | service : { 7 | icrc10_supported_standards : () -> (SupportedStandardsResponse) query; 8 | } 9 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/types/canister.options.ts: -------------------------------------------------------------------------------- 1 | import type { CanisterOptions } from "@dfinity/utils"; 2 | import type { Principal } from "@icp-sdk/core/principal"; 3 | 4 | export interface IcrcLedgerCanisterOptions extends Omit< 5 | CanisterOptions, 6 | "canisterId" 7 | > { 8 | // The canister's ID is mandatory to instantiate an ICRC-1 ledger. 9 | canisterId: Principal; 10 | } 11 | -------------------------------------------------------------------------------- /packages/canisters/src/index.spec.ts: -------------------------------------------------------------------------------- 1 | describe("@icp-sdk/canisters", () => { 2 | it("should throw loading error", async () => { 3 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 4 | // @ts-expect-error 5 | await expect(import("@icp-sdk/canisters")).rejects.toThrowError( 6 | "This package has no default entry point. Please import from a subpath.", 7 | ); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /scripts/fmt-sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | cd "$(dirname "$(realpath "$0")")/.." || exit 3 | 4 | list_files() { 5 | git ls-files | while read -r line; do if [[ "$line" = *.sh ]] || file "$line" | grep -qw Bourne; then echo "$line"; fi; done 6 | } 7 | 8 | case "${1:-}" in 9 | --list) list_files ;; 10 | --check) list_files | xargs -I{} shfmt -i 2 -d "{}" ;; 11 | *) list_files | xargs -I{} shfmt -i 2 -l -w "{}" ;; 12 | esac 13 | -------------------------------------------------------------------------------- /tests/integration/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { baseConfig } from "../../vitest.config"; 3 | 4 | export default defineConfig({ 5 | ...baseConfig, 6 | test: { 7 | ...baseConfig.test, 8 | exclude: ["node_modules/**"], 9 | testTimeout: 100_000, 10 | typecheck: { 11 | enabled: true, 12 | tsconfig: "./tsconfig.json", 13 | }, 14 | }, 15 | }); 16 | -------------------------------------------------------------------------------- /packages/cketh/src/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { CkETHMinterCanister, CkETHOrchestratorCanister } from "./index"; 2 | 3 | describe("@dfinity/cketh", () => { 4 | it("should re-export CkETHMinterCanister", () => { 5 | expect(CkETHMinterCanister).not.toBeUndefined(); 6 | }); 7 | 8 | it("should re-export CkETHOrchestratorCanister", () => { 9 | expect(CkETHOrchestratorCanister).not.toBeUndefined(); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /scripts/prepare-integration-tests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ueo pipefail 3 | 4 | # Stop any running dfx processes 5 | dfx killall 6 | 7 | dfx start --host 127.0.0.1:4943 --background --clean 8 | dfx deploy 9 | 10 | # The principal obtained from the "seed" in the tests/integration/src/utils/identity.ts file 11 | dfx canister call assets authorize '(principal "n7obp-cx27z-e4ytc-ipt7n-urffz-txqa5-el2vn-7vpqc-jjoh3-wrob6-bqe")' 12 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icp/types/ledger.params.ts: -------------------------------------------------------------------------------- 1 | import type { QueryParams } from "@dfinity/utils"; 2 | import type { AccountIdentifier } from "../account_identifier"; 3 | import type { AccountIdentifierHex } from "./common"; 4 | 5 | export type AccountIdentifierParam = AccountIdentifier | AccountIdentifierHex; 6 | 7 | export type AccountBalanceParams = { 8 | accountIdentifier: AccountIdentifierParam; 9 | } & QueryParams; 10 | -------------------------------------------------------------------------------- /packages/canisters/src/ckbtc/mocks/minter.mock.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | 3 | export const minterCanisterIdMock: Principal = Principal.fromText( 4 | "q3fc5-haaaa-aaaaa-aaahq-cai", 5 | ); 6 | 7 | export const bitcoinCanisterIdMock: Principal = Principal.fromText( 8 | "ghsi2-tqaaa-aaaan-aaaca-cai", 9 | ); 10 | 11 | export const bitcoinAddressMock = 12 | "bcrt1qu2aqme90t6hpac50x0xw8ljwqs250vn6tzlmsv"; 13 | -------------------------------------------------------------------------------- /packages/canisters/src/ic-management/types/ic-management.responses.ts: -------------------------------------------------------------------------------- 1 | import type { ServiceResponse } from "@dfinity/utils"; 2 | import type { IcManagementService } from "../../declarations"; 3 | 4 | export type CanisterStatusResponse = ServiceResponse< 5 | IcManagementService, 6 | "canister_status" 7 | >; 8 | 9 | export type FetchCanisterLogsResponse = ServiceResponse< 10 | IcManagementService, 11 | "fetch_canister_logs" 12 | >; 13 | -------------------------------------------------------------------------------- /packages/nns-proto/README.md: -------------------------------------------------------------------------------- 1 | # nns-proto-js 2 | 3 | The protobuf source used by the [NNS Governance canister](https://dashboard.internetcomputer.org/canister/rrkah-fqaaa-aaaaa-aaaaq-cai). 4 | 5 | [![npm version](https://img.shields.io/npm/v/@dfinity/nns-proto.svg?logo=npm)](https://www.npmjs.com/package/@dfinity/nns-proto) [![GitHub license](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 6 | -------------------------------------------------------------------------------- /tests/integration/src/utils/identity.ts: -------------------------------------------------------------------------------- 1 | import { Ed25519KeyIdentity } from "@icp-sdk/core/identity"; 2 | import { utf8ToBytes } from "@noble/hashes/utils"; 3 | 4 | // yields n7obp-cx27z-e4ytc-ipt7n-urffz-txqa5-el2vn-7vpqc-jjoh3-wrob6-bqe 5 | const assetsSeed = new Uint8Array(32); 6 | utf8ToBytes("test").forEach((byte, i) => { 7 | assetsSeed[i] = byte; 8 | }); 9 | 10 | export const assetsIdentity = Ed25519KeyIdentity.generate(assetsSeed); 11 | -------------------------------------------------------------------------------- /packages/canisters/src/cmc/cmc.mock.ts: -------------------------------------------------------------------------------- 1 | import type { Identity } from "@icp-sdk/core/agent"; 2 | import { Principal } from "@icp-sdk/core/principal"; 3 | 4 | export const mockPrincipalText = 5 | "xlmdg-vkosz-ceopx-7wtgu-g3xmd-koiyc-awqaq-7modz-zf6r6-364rh-oqe"; 6 | 7 | export const mockPrincipal = Principal.fromText(mockPrincipalText); 8 | 9 | export const mockIdentity = { 10 | getPrincipal: () => mockPrincipal, 11 | } as unknown as Identity; 12 | -------------------------------------------------------------------------------- /scripts/update_payloads_idl_declarations.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | JS_FILE="candid/payloads.idl.js" 4 | TMP_FILE="candid/payloads.idl.tmp" 5 | D_TS_FILE="candid/payloads.idl.d.ts" 6 | 7 | cat $JS_FILE | grep "^export const " | sed -E "s/(export const .*) =.*/\1: IDL.RecordClass;/" >$TMP_FILE 8 | echo "import type { IDL } from \"@icp-sdk/core/candid\";" >$D_TS_FILE 9 | echo "" >>$D_TS_FILE 10 | cat $TMP_FILE >>$D_TS_FILE 11 | 12 | rm $TMP_FILE 13 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icp/constants/constants.ts: -------------------------------------------------------------------------------- 1 | export const SUB_ACCOUNT_BYTE_LENGTH = 32; 2 | export const CREATE_CANISTER_MEMO = BigInt(0x41455243); // CREA, 3 | export const TOP_UP_CANISTER_MEMO = BigInt(0x50555054); // TPUP 4 | 5 | export const TRANSACTION_FEE = BigInt(10_000); 6 | 7 | // Note: Canister IDs are not constant, so are not provided here. 8 | // The same applies to HOST. 9 | export const E8S_PER_TOKEN = BigInt(100000000); 10 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icp/mocks/ledger.request.mock.ts: -------------------------------------------------------------------------------- 1 | import type { Icrc21ConsentMessageRequest } from "../types/ledger_converters"; 2 | 3 | export const mockConsentMessageRequest: Icrc21ConsentMessageRequest = { 4 | method: "icrc1_transfer", 5 | arg: new Uint8Array([1, 2, 3]), 6 | userPreferences: { 7 | metadata: { 8 | language: "en-US", 9 | }, 10 | deriveSpec: { 11 | GenericDisplay: null, 12 | }, 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /packages/canisters/src/ckbtc/enums/btc.enums.ts: -------------------------------------------------------------------------------- 1 | // As defined on Bitcoin network. 2 | // e.g. https://developer.bitcoin.org/examples/testing.html 3 | export enum BtcNetwork { 4 | Mainnet, 5 | Regtest, 6 | Testnet, 7 | } 8 | 9 | // See https://github.com/dfinity/ic/blob/a8da3aa23dc6f8f4708cb0cb8edce84c5bd8f225/rs/bitcoin/ckbtc/minter/src/address.rs#L18 10 | export enum BtcAddressType { 11 | P2wpkhV0, 12 | P2pkh, 13 | P2sh, 14 | P2wsh, 15 | P2tr, 16 | } 17 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | **/*.did.js 3 | **/proto/* 4 | .github/* 5 | 6 | packages/**/*.js 7 | packages/**/*.mjs 8 | packages/**/*.d.ts 9 | !packages/**/candid/**/*.js 10 | !packages/**/candid/**/*.mjs 11 | !packages/**/candid/**/*.d.ts 12 | !packages/**/declarations/**/*.js 13 | !packages/**/declarations/**/*.mjs 14 | !packages/**/declarations/**/*.d.ts 15 | !packages/**/esbuild.mjs 16 | 17 | docs/src/content/tmp/ 18 | docs/src/content/docs/api/ 19 | docs/src/content/docs/changelog.md 20 | -------------------------------------------------------------------------------- /packages/canisters/src/cketh/types/canister.options.ts: -------------------------------------------------------------------------------- 1 | import type { CanisterOptions } from "@dfinity/utils"; 2 | import type { Principal } from "@icp-sdk/core/principal"; 3 | 4 | export interface CkEthMinterCanisterOptions extends Omit< 5 | CanisterOptions, 6 | "canisterId" 7 | > { 8 | // The canister's ID is mandatory to instantiate an ckETH minter. 9 | canisterId: Principal; 10 | } 11 | 12 | export type CkEthOrchestratorCanisterOptions = CkEthMinterCanisterOptions; 13 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/converters/swap.converters.ts: -------------------------------------------------------------------------------- 1 | import type { SnsSwapDid } from "../../declarations"; 2 | import type { NewSaleTicketParams } from "../types/swap.params"; 3 | 4 | // Helper for building `NewSaleTicketRequest` structure 5 | export const toNewSaleTicketRequest = ({ 6 | subaccount, 7 | amount_icp_e8s, 8 | }: NewSaleTicketParams): SnsSwapDid.NewSaleTicketRequest => ({ 9 | subaccount: subaccount === undefined ? [] : [subaccount], 10 | amount_icp_e8s, 11 | }); 12 | -------------------------------------------------------------------------------- /packages/utils/src/types/did.utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A Candid-style variant representation of an optional value. 3 | * It is an empty array for `null` and `undefined`, or an array with the value. 4 | */ 5 | export type Nullable = [] | [T]; 6 | 7 | /** 8 | * An optional Candid-style variant representation of an optional value. 9 | * It is an empty array for `null` and `undefined`, or an array with the value, or `undefined`. 10 | */ 11 | export type NullishNullable = Nullable | undefined; 12 | -------------------------------------------------------------------------------- /packages/canisters/src/cketh/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module api/cketh 3 | */ 4 | 5 | export type { CkEthMinterDid, CkEthOrchestratorDid } from "../declarations"; 6 | export * from "./errors/minter.errors"; 7 | export { CkEthMinterCanister } from "./minter.canister"; 8 | export { CkEthOrchestratorCanister } from "./orchestrator.canister"; 9 | export type * from "./types/canister.options"; 10 | export type { Eip1559TransactionPriceParams } from "./types/minter.params"; 11 | export * from "./utils/minter.utils"; 12 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icp/mocks/ledger.mock.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | import { AccountIdentifier } from "../account_identifier"; 3 | 4 | export const mockAccountIdentifier = AccountIdentifier.fromHex( 5 | "d3e13d4777e22367532053190b6c6ccf57444a61337e996242b1abfb52cf92c8", 6 | ); 7 | 8 | export const mockPrincipalText = 9 | "xlmdg-vkosz-ceopx-7wtgu-g3xmd-koiyc-awqaq-7modz-zf6r6-364rh-oqe"; 10 | 11 | export const mockPrincipal = Principal.fromText(mockPrincipalText); 12 | -------------------------------------------------------------------------------- /packages/canisters/src/ic-management/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module api/ic-management 3 | */ 4 | 5 | export type { IcManagementDid } from "../declarations"; 6 | export { IcManagementCanister } from "./ic-management.canister"; 7 | export type * from "./types/canister.options"; 8 | export * from "./types/ic-management.params"; 9 | export * from "./types/ic-management.responses"; 10 | export * from "./types/snapshot.params"; 11 | export * from "./types/snapshot.responses"; 12 | export * from "./utils/ic-management.utils"; 13 | -------------------------------------------------------------------------------- /packages/canisters/src/assets/assets.canister.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Actor, 3 | type ActorConfig, 4 | type ActorSubclass, 5 | } from "@icp-sdk/core/agent"; 6 | import { type AssetsService, idlFactoryAssets } from "../declarations"; 7 | 8 | /** 9 | * Create an assets canister actor 10 | * @param config Configuration to make calls to the Replica. 11 | */ 12 | export const getAssetsCanister = ( 13 | config: ActorConfig, 14 | ): ActorSubclass => 15 | Actor.createActor(idlFactoryAssets, config); 16 | -------------------------------------------------------------------------------- /packages/canisters/src/cketh/mocks/minter.mock.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | 3 | export const minterCanisterIdMock: Principal = Principal.fromText( 4 | "sv3dd-oaaaa-aaaar-qacoa-cai", 5 | ); 6 | 7 | export const ledgerCanisterIdMock: Principal = Principal.fromText( 8 | "apia6-jaaaa-aaaar-qabma-cai", 9 | ); 10 | 11 | export const ckETHSmartContractAddressMock = 12 | "0x7574eB42cA208A4f6960ECCAfDF186D627dCC175"; 13 | 14 | export const ethAddressMock = "0x6D1b7ceAd24FBaf153a3a18f09395Fd2f9C64912"; 15 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/types/index-ng.params.ts: -------------------------------------------------------------------------------- 1 | import type { QueryParams } from "@dfinity/utils"; 2 | import type { IcrcIndexDid, IcrcLedgerDid } from "../../../declarations"; 3 | import type { IcrcAccount } from "./ledger.responses"; 4 | 5 | export type GetIndexAccountTransactionsParams = { 6 | max_results: bigint; 7 | start?: IcrcIndexDid.BlockIndex; 8 | account: IcrcAccount; 9 | } & QueryParams; 10 | 11 | export type ListSubaccountsParams = { 12 | start?: IcrcLedgerDid.Subaccount; 13 | } & Pick & 14 | QueryParams; 15 | -------------------------------------------------------------------------------- /packages/canisters/src/nns/types/governance.options.ts: -------------------------------------------------------------------------------- 1 | import type { CanisterOptions } from "@dfinity/utils"; 2 | import type { ActorSubclass } from "@icp-sdk/core/agent"; 3 | import type { NnsGovernanceService } from "../../declarations"; 4 | 5 | export interface NnsGovernanceCanisterOptions extends CanisterOptions { 6 | // Ledger IC App needs requests built with Protobuf. 7 | // This flag ensures that the methods use Protobuf. 8 | hardwareWallet?: boolean; 9 | oldListNeuronsServiceOverride?: ActorSubclass; 10 | } 11 | -------------------------------------------------------------------------------- /packages/nns-proto/proto/nns_common.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ic_nns_common.pb.v1; 4 | 5 | import "base_types.proto"; 6 | 7 | // A container for a NeuronId blob, which uniquely identifies 8 | // a Neuron. 9 | message NeuronId { 10 | option (ic_base_types.pb.v1.tui_signed_message) = true; 11 | // bytes serialized_id = 1; 12 | reserved 1; 13 | reserved 'serialized_id'; 14 | uint64 id = 2 [(ic_base_types.pb.v1.tui_signed_display_q2_2021) = true]; 15 | } 16 | 17 | // The id of a specific proposal. 18 | message ProposalId { 19 | uint64 id = 1; 20 | } 21 | -------------------------------------------------------------------------------- /packages/utils/src/services/canister.ts: -------------------------------------------------------------------------------- 1 | import type { Principal } from "@icp-sdk/core/principal"; 2 | import type { QueryParams } from "../types/query.params"; 3 | 4 | export abstract class Canister { 5 | protected constructor( 6 | private readonly id: Principal, 7 | protected readonly service: T, 8 | protected readonly certifiedService: T, 9 | ) {} 10 | 11 | get canisterId(): Principal { 12 | return this.id; 13 | } 14 | 15 | protected caller = ({ certified = true }: QueryParams): T => 16 | certified ? this.certifiedService : this.service; 17 | } 18 | -------------------------------------------------------------------------------- /packages/ledger-icrc/src/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | IcrcIndexCanister, 3 | IcrcLedgerCanister, 4 | IcrcNftLedgerCanister, 5 | } from "./index"; 6 | 7 | describe("@dfinity/ledger-icrc", () => { 8 | it("should re-export IcrcIndexNgCanister", () => { 9 | expect(IcrcIndexCanister).not.toBeUndefined(); 10 | }); 11 | 12 | it("should re-export IcrcLedgerCanister", () => { 13 | expect(IcrcLedgerCanister).not.toBeUndefined(); 14 | }); 15 | 16 | it("should re-export IcrcNftLedgerCanister", () => { 17 | expect(IcrcNftLedgerCanister).not.toBeUndefined(); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/utils/src/utils/crc.utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { bigEndianCrc32 } from "./crc.utils"; 2 | 3 | describe("crc-utils", () => { 4 | it("should convert array to big endian crc32", () => { 5 | expect(bigEndianCrc32(new Uint8Array([]))).toEqual( 6 | Uint8Array.from([0, 0, 0, 0]), 7 | ); 8 | expect(bigEndianCrc32(new Uint8Array([1, 2, 3]))).toEqual( 9 | Uint8Array.from([0x55, 0xbc, 0x80, 0x1d]), 10 | ); 11 | expect(bigEndianCrc32(new Uint8Array([100, 99, 98, 1, 2, 3]))).toEqual( 12 | Uint8Array.from([0xc7, 0xe7, 0x87, 0xf5]), 13 | ); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "target": "esnext", 5 | "lib": ["esnext", "dom"], 6 | "strict": true, 7 | "noImplicitAny": false, 8 | "esModuleInterop": true, 9 | "moduleResolution": "bundler", 10 | "module": "esnext", 11 | "skipLibCheck": true, 12 | "outDir": "./dist" 13 | }, 14 | "exclude": [ 15 | "**/src/**/*.test.ts", 16 | "**/src/**/*.spec.ts", 17 | "**/src/**/*.mock.ts", 18 | "**/vitest.config.ts", 19 | "**/vitest.setup.ts" 20 | ], 21 | "references": [{ "path": "./tsconfig.spec.json" }] 22 | } 23 | -------------------------------------------------------------------------------- /scripts/copy-declarations: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIR="$(pwd)/declarations" 4 | 5 | if [ ! -d "$DIR" ]; then 6 | mkdir "$DIR" 7 | fi 8 | 9 | # While technically we could copy only the .d.ts declaration files, 10 | # we also copy the .did and .js files for convenience. According to our experience, 11 | # those files can be useful for developers. For example, for accessing the DID 12 | # file without the need to search for their effective source, or to create scripts 13 | # that load non-exposed functions with an actor. 14 | cp -r "$(pwd)/src/declarations/"* "$DIR/" 15 | 16 | echo "📦 Bundle declarations copied" 17 | -------------------------------------------------------------------------------- /packages/canisters/src/assets/utils/path-polyfill.ts: -------------------------------------------------------------------------------- 1 | import type * as path from "path"; 2 | 3 | // Check if we're in a Node.js environment 4 | // Not really reliable, we must find a better way to do it 5 | const isNode = typeof window === "undefined"; 6 | 7 | // Browser-safe no-op implementation using actual path function types 8 | // @ts-expect-error - path is not defined in the browser 9 | const browserPath: typeof path = {}; 10 | 11 | const pathPolyfill: typeof path = isNode 12 | ? // eslint-disable-next-line @typescript-eslint/no-require-imports 13 | require("path") 14 | : browserPath; 15 | 16 | export default pathPolyfill; 17 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icp/utils/params.utils.ts: -------------------------------------------------------------------------------- 1 | import { AccountIdentifier } from "../account_identifier"; 2 | import type { AccountIdentifierHex } from "../types/common"; 3 | import type { AccountIdentifierParam } from "../types/ledger.params"; 4 | 5 | export const paramToAccountIdentifier = ( 6 | param: AccountIdentifierParam, 7 | ): AccountIdentifier => 8 | param instanceof AccountIdentifier ? param : AccountIdentifier.fromHex(param); 9 | 10 | export const paramToAccountIdentifierHex = ( 11 | param: AccountIdentifierParam, 12 | ): AccountIdentifierHex => 13 | param instanceof AccountIdentifier ? param.toHex() : param; 14 | -------------------------------------------------------------------------------- /packages/utils/src/utils/principal.utils.ts: -------------------------------------------------------------------------------- 1 | import type { Principal } from "@icp-sdk/core/principal"; 2 | 3 | /** 4 | * Convert a principal to a Uint8Array 32 length. 5 | * e.g. Useful to convert a canister ID when topping up cycles with the Cmc canister 6 | * @param principal The principal that needs to be converted to Subaccount 7 | */ 8 | export const principalToSubAccount = (principal: Principal): Uint8Array => { 9 | const bytes: Uint8Array = principal.toUint8Array(); 10 | const subAccount: Uint8Array = new Uint8Array(32); 11 | subAccount[0] = bytes.length; 12 | subAccount.set(bytes, 1); 13 | return subAccount; 14 | }; 15 | -------------------------------------------------------------------------------- /packages/canisters/src/nns/constants/canister_ids.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | 3 | export const GOVERNANCE_CANISTER_ID = Principal.fromText( 4 | "rrkah-fqaaa-aaaaa-aaaaq-cai", 5 | ); 6 | 7 | export const MAINNET_GOVERNANCE_CANISTER_ID = Principal.fromText( 8 | "rrkah-fqaaa-aaaaa-aaaaq-cai", 9 | ); 10 | 11 | export const MAINNET_GENESIS_TOKEN_CANISTER_ID = Principal.fromText( 12 | "renrk-eyaaa-aaaaa-aaada-cai", 13 | ); 14 | 15 | // TODO(L2-828): Sns-wasm canister is not yet deployed on mainnet 16 | export const MAINNET_SNS_WASM_CANISTER_ID = Principal.fromText( 17 | "r7inp-6aaaa-aaaaa-aaabq-cai", 18 | ); 19 | -------------------------------------------------------------------------------- /packages/canisters/src/ckbtc/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module api/ckbtc 3 | */ 4 | 5 | export type { BitcoinDid, CkBtcMinterDid } from "../declarations"; 6 | export { BitcoinCanister } from "./bitcoin.canister"; 7 | export * from "./enums/btc.enums"; 8 | export * from "./errors/btc.errors"; 9 | export * from "./errors/minter.errors"; 10 | export { CkBtcMinterCanister } from "./minter.canister"; 11 | export * from "./types/bitcoin.params"; 12 | export * from "./types/btc"; 13 | export type * from "./types/canister.options"; 14 | export * from "./types/minter.params"; 15 | export * from "./types/minter.responses"; 16 | export * from "./utils/btc.utils"; 17 | -------------------------------------------------------------------------------- /packages/canisters/src/cketh/types/minter.params.ts: -------------------------------------------------------------------------------- 1 | import { isNullish, toNullable, type QueryParams } from "@dfinity/utils"; 2 | import type { Principal } from "@icp-sdk/core/principal"; 3 | import type { CkEthMinterDid } from "../../declarations"; 4 | 5 | export type Eip1559TransactionPriceParams = { 6 | ckErc20LedgerId?: Principal; 7 | } & QueryParams; 8 | 9 | export const toEip1559TransactionPriceParams = ({ 10 | ckErc20LedgerId: ckerc20_ledger_id, 11 | }: Eip1559TransactionPriceParams): 12 | | [] 13 | | [CkEthMinterDid.Eip1559TransactionPriceArg] => 14 | toNullable(isNullish(ckerc20_ledger_id) ? undefined : { ckerc20_ledger_id }); 15 | -------------------------------------------------------------------------------- /packages/utils/src/types/canister.options.ts: -------------------------------------------------------------------------------- 1 | import type { ActorSubclass, Agent } from "@icp-sdk/core/agent"; 2 | import type { Principal } from "@icp-sdk/core/principal"; 3 | 4 | export interface CanisterOptions { 5 | // The agent to use when communicating with the canister. 6 | agent?: Agent; 7 | // The canister's ID. 8 | canisterId?: Principal; 9 | // The service to use when calling into the IC. Primarily overridden 10 | // in test for mocking. 11 | serviceOverride?: ActorSubclass; 12 | // The service to use when calling into the IC. Primarily overridden 13 | // in test for mocking. 14 | certifiedServiceOverride?: ActorSubclass; 15 | } 16 | -------------------------------------------------------------------------------- /packages/canisters/src/assets/utils/fs-polyfill.ts: -------------------------------------------------------------------------------- 1 | import type * as fs from "fs"; 2 | 3 | // Check if we're in a Node.js environment 4 | // Not really reliable, we must find a better way to do it 5 | const isNode = typeof window === "undefined"; 6 | 7 | // Browser-safe no-op implementation using actual fs function types 8 | // @ts-expect-error - fs is not defined in the browser 9 | const browserFs: typeof fs = {}; 10 | 11 | // Export either the real fs module or the polyfill 12 | const fsPolyfill: typeof fs = isNode 13 | ? // eslint-disable-next-line @typescript-eslint/no-require-imports 14 | require("fs") 15 | : browserFs; 16 | 17 | export default fsPolyfill; 18 | -------------------------------------------------------------------------------- /packages/nns-proto/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "../proto/base_types_pb"; 2 | export { 3 | BallotInfo, 4 | Governance, 5 | ListNeurons, 6 | ListNeuronsResponse, 7 | ManageNeuron, 8 | ManageNeuronResponse, 9 | NetworkEconomics, 10 | Neuron, 11 | NeuronInfo, 12 | NeuronsFundEconomics, 13 | NeuronsFundMatchedFundingCurveCoefficients, 14 | XdrConversionRate, 15 | } from "../proto/governance_pb"; 16 | export { 17 | AccountBalanceRequest, 18 | AccountIdentifier, 19 | Memo, 20 | Payment, 21 | SendRequest, 22 | Subaccount, 23 | TimeStamp, 24 | } from "../proto/ledger_pb"; 25 | export * from "../proto/nervous_system_pb"; 26 | export * from "../proto/nns_common_pb"; 27 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icp/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module api/ledger/icp 3 | */ 4 | 5 | export type { IcpIndexDid, IcpLedgerDid } from "../../declarations"; 6 | export { AccountIdentifier, SubAccount } from "./account_identifier"; 7 | export * from "./canisters/ledger/ledger.request.converts"; 8 | export * from "./errors/ledger.errors"; 9 | export { IcpIndexCanister } from "./index.canister"; 10 | export { IcpLedgerCanister } from "./ledger.canister"; 11 | export type * from "./types/common"; 12 | export * from "./types/ledger.options"; 13 | export type { 14 | Icrc1TransferRequest, 15 | Icrc2ApproveRequest, 16 | TransferRequest, 17 | } from "./types/ledger_converters"; 18 | export * from "./utils/accounts.utils"; 19 | -------------------------------------------------------------------------------- /packages/canisters/src/assets/utils/assets.ts: -------------------------------------------------------------------------------- 1 | import type { AssetsService } from "../../declarations"; 2 | 3 | export type AssetDetails = Awaited>[number]; 4 | 5 | /** 6 | * Compare two arrays of asset entries by their keys. 7 | * @param a First array of asset entries. 8 | * @param b Second array of asset entries. 9 | * @returns True if the arrays have the same length and the same keys, false otherwise. 10 | */ 11 | export const entriesEqual = ({ 12 | a, 13 | b, 14 | }: { 15 | a: AssetDetails[]; 16 | b: AssetDetails[]; 17 | }): boolean => { 18 | if (a.length !== b.length) { 19 | return false; 20 | } 21 | return a.every((entry, index) => entry.key === b[index].key); 22 | }; 23 | -------------------------------------------------------------------------------- /packages/nns/src/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | GenesisTokenCanister, 3 | GovernanceCanister, 4 | GovernanceTestCanister, 5 | SnsWasmCanister, 6 | } from "./index"; 7 | 8 | describe("@dfinity/nns", () => { 9 | it("should re-export GovernanceCanister", () => { 10 | expect(GovernanceCanister).not.toBeUndefined(); 11 | }); 12 | 13 | it("should re-export GovernanceTestCanister", () => { 14 | expect(GovernanceTestCanister).not.toBeUndefined(); 15 | }); 16 | 17 | it("should re-export SnsWasmCanister", () => { 18 | expect(SnsWasmCanister).not.toBeUndefined(); 19 | }); 20 | 21 | it("should re-export GenesisTokenCanister", () => { 22 | expect(GenesisTokenCanister).not.toBeUndefined(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /packages/canisters/src/assets/readable/readable-blob.spec.ts: -------------------------------------------------------------------------------- 1 | import { ReadableBlob } from "./readable-blob"; 2 | 3 | describe("ReadableBlob", () => { 4 | test("ReadableBlob from Blob", async () => { 5 | const blob = new Blob(["Hello world!"]); 6 | const fileName = "hello.txt"; 7 | const readable = new ReadableBlob(fileName, blob); 8 | 9 | expect(readable.fileName).toEqual(fileName); 10 | expect(readable.contentType).toEqual("text/plain"); 11 | expect(readable).toHaveLength(blob.size); 12 | 13 | await readable.open(); 14 | 15 | await expect(readable.slice(1, 4)).resolves.toEqual( 16 | new Uint8Array(await blob.slice(1, 4).arrayBuffer()), 17 | ); 18 | 19 | await readable.close(); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/utils/src/mocks/identity.mock.ts: -------------------------------------------------------------------------------- 1 | import type { Identity } from "@icp-sdk/core/agent"; 2 | import { Principal } from "@icp-sdk/core/principal"; 3 | 4 | export const mockPrincipalText = 5 | "xlmdg-vkosz-ceopx-7wtgu-g3xmd-koiyc-awqaq-7modz-zf6r6-364rh-oqe"; 6 | 7 | export const mockPrincipal = Principal.fromText(mockPrincipalText); 8 | 9 | export const mockIdentity = { 10 | getPrincipal: () => mockPrincipal, 11 | } as unknown as Identity; 12 | 13 | export const mockPrincipalText2 = 14 | "5uuwe-ggtgm-fonrs-rblmx-cfc23-pb3dg-iyfk2-dle5w-j5uev-ggmep-6ae"; 15 | 16 | export const mockPrincipal2 = Principal.fromText(mockPrincipalText2); 17 | 18 | export const mockIdentity2 = { 19 | getPrincipal: () => mockPrincipal2, 20 | } as unknown as Identity; 21 | -------------------------------------------------------------------------------- /packages/cmc/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { CmcDid } from "@icp-sdk/canisters/cmc"; 2 | 3 | export type Cycles = CmcDid.Cycles; 4 | export type NotifyCreateCanisterArg = CmcDid.NotifyCreateCanisterArg; 5 | export type NotifyTopUpArg = CmcDid.NotifyTopUpArg; 6 | export type SubnetTypesToSubnetsResponse = CmcDid.SubnetTypesToSubnetsResponse; 7 | 8 | /** 9 | * @deprecated Use "@icp-sdk/canisters/cmc" directly instead 10 | */ 11 | export * from "@icp-sdk/canisters/cmc"; 12 | 13 | /** 14 | * Legacy re-export for backward compatibility. 15 | * @deprecated Use "@icp-sdk/canisters/cmc" directly instead 16 | */ 17 | export { 18 | CmcCanister as CMCCanister, 19 | CmcError as CMCError, 20 | type CmcCanisterOptions as CMCCanisterOptions, 21 | } from "@icp-sdk/canisters/cmc"; 22 | -------------------------------------------------------------------------------- /packages/nns/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { NnsGovernanceDid, SnsWasmDid } from "@icp-sdk/canisters/nns"; 2 | 3 | export type RewardEvent = NnsGovernanceDid.RewardEvent; 4 | export type DeployedSns = SnsWasmDid.DeployedSns; 5 | 6 | /** 7 | * @deprecated Use "@icp-sdk/canisters/nns" directly instead 8 | */ 9 | export * from "@icp-sdk/canisters/nns"; 10 | 11 | /** 12 | * Legacy re-export for backward compatibility. 13 | * @deprecated Use "@icp-sdk/canisters/nns" directly instead 14 | */ 15 | export { 16 | NnsGenesisTokenCanister as GenesisTokenCanister, 17 | NnsGovernanceCanister as GovernanceCanister, 18 | NnsGovernanceTestCanister as GovernanceTestCanister, 19 | type NnsGovernanceCanisterOptions as GovernanceCanisterOptions, 20 | } from "@icp-sdk/canisters/nns"; 21 | -------------------------------------------------------------------------------- /packages/canisters/src/ckbtc/errors/btc.errors.ts: -------------------------------------------------------------------------------- 1 | export class ParseBtcAddressError extends Error {} 2 | export class ParseBtcAddressInvalidError extends ParseBtcAddressError {} 3 | export class ParseBtcAddressNoDataError extends ParseBtcAddressError {} 4 | export class ParseBtcAddressUnsupportedAddressTypeError extends ParseBtcAddressError {} 5 | export class ParseBtcAddressBadWitnessLengthError extends ParseBtcAddressError {} 6 | export class ParseBtcAddressUnsupportedWitnessVersionError extends ParseBtcAddressError {} 7 | export class ParseBtcAddressUnexpectedHumanReadablePartError extends ParseBtcAddressError {} 8 | export class ParseBtcAddressMalformedAddressError extends ParseBtcAddressError {} 9 | export class ParseBtcAddressWrongNetworkError extends ParseBtcAddressError {} 10 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/mocks/ledger.mock.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | import { 3 | IcrcMetadataResponseEntries, 4 | type IcrcLedgerDid, 5 | } from "../../ledger/icrc"; 6 | 7 | export const tokenMetadataResponseMock: [ 8 | string | IcrcMetadataResponseEntries, 9 | IcrcLedgerDid.Value, 10 | ][] = [ 11 | [IcrcMetadataResponseEntries.DECIMALS, { Nat: BigInt(8) }], 12 | [IcrcMetadataResponseEntries.NAME, { Text: "Beta Test" }], 13 | [IcrcMetadataResponseEntries.SYMBOL, { Text: "BTA" }], 14 | [IcrcMetadataResponseEntries.FEE, { Nat: BigInt(1000) }], 15 | ]; 16 | 17 | export const mockPrincipalText = 18 | "xlmdg-vkosz-ceopx-7wtgu-g3xmd-koiyc-awqaq-7modz-zf6r6-364rh-oqe"; 19 | 20 | export const mockPrincipal = Principal.fromText(mockPrincipalText); 21 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module api/ledger/icrc 3 | */ 4 | 5 | export type { 6 | IcrcIndexDid, 7 | IcrcLedgerDid, 8 | IcrcNftLedgerDid, 9 | } from "../../declarations"; 10 | export * from "./converters/converters"; 11 | export * from "./converters/ledger.converters"; 12 | export * from "./errors/index.errors"; 13 | export * from "./errors/ledger.errors"; 14 | export { IcrcIndexCanister } from "./index.canister"; 15 | export { IcrcLedgerCanister } from "./ledger.canister"; 16 | export { IcrcNftLedgerCanister } from "./nft-ledger.canister"; 17 | export type * from "./types/index-ng.params"; 18 | export * from "./types/ledger.params"; 19 | export * from "./types/ledger.responses"; 20 | export * from "./utils/ledger.utils"; 21 | export * from "./utils/payment.utils"; 22 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_icrc-10.certified.idl.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // @ts-nocheck 4 | 5 | // This file was automatically generated by @icp-sdk/bindgen@0.2.1. 6 | // You should NOT make any changes in this file as it will be overwritten. 7 | // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. 8 | 9 | export const idlFactory = ({ IDL }) => { 10 | const SupportedStandard = IDL.Record({ url: IDL.Text, name: IDL.Text }); 11 | const SupportedStandardsResponse = IDL.Vec(SupportedStandard); 12 | 13 | return IDL.Service({ 14 | icrc10_supported_standards: IDL.Func([], [SupportedStandardsResponse], []), 15 | }); 16 | }; 17 | 18 | export const init = ({ IDL }) => { 19 | return []; 20 | }; 21 | -------------------------------------------------------------------------------- /docs/src/content/docs/upgrading/v2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Upgrading to v2 3 | description: Upgrading guide for the v2 of @icp-sdk/canisters package 4 | sidebar: 5 | label: v2 6 | order: 2 7 | prev: false 8 | next: 9 | label: Overview 10 | link: /canisters/latest/ 11 | --- 12 | 13 | ## Breaking Changes 14 | 15 | - Various Candid-inherited types are no longer expressed as unions and resolves to a single type. For example: `Uint8Array` instead of `Uint8Array | number[]`. 16 | - The `canisterStatus` function interface was modified to introduce support for query calls. 17 | 18 | ## Upgrading from `@dfinity/*` libraries 19 | 20 | If you are upgrading from `@dfinity/*` libraries, have a look at the [Upgrading to v1](./v1.md) guide. 21 | 22 | --- 23 | 24 | For more details, have a look at the [Changelog](../changelog.md). 25 | -------------------------------------------------------------------------------- /packages/canisters/src/nns/sns_wasm.canister.spec.ts: -------------------------------------------------------------------------------- 1 | import type { ActorSubclass } from "@icp-sdk/core/agent"; 2 | import { mock } from "vitest-mock-extended"; 3 | import type { SnsWasmService } from "../declarations"; 4 | import { deployedSnsMock } from "./mocks/sns_wasm.mock"; 5 | import { SnsWasmCanister } from "./sns_wasm.canister"; 6 | 7 | describe("Sns-wasm", () => { 8 | it("should return the list of sns", async () => { 9 | const service = mock>(); 10 | service.list_deployed_snses.mockResolvedValue({ 11 | instances: deployedSnsMock, 12 | }); 13 | 14 | const canister = SnsWasmCanister.create({ 15 | certifiedServiceOverride: service, 16 | }); 17 | const res = await canister.listSnses({}); 18 | 19 | expect(res).toEqual(deployedSnsMock); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/canisters/src/assets/readable/readable-path.spec.ts: -------------------------------------------------------------------------------- 1 | import { readFileSync, statSync } from "fs"; 2 | import { basename, resolve } from "path"; 3 | import { ReadablePath } from "./readable-path"; 4 | 5 | describe("ReadablePath", () => { 6 | test("ReadablePath from path", async () => { 7 | const path = resolve(__dirname, "../../../package.json"); 8 | const readable = await ReadablePath.create(path); 9 | 10 | expect(readable.fileName).toEqual(basename(path)); 11 | expect(readable.contentType).toEqual("application/json"); 12 | expect(readable).toHaveLength(statSync(path).size); 13 | 14 | await readable.open(); 15 | 16 | await expect(readable.slice(16, 24)).resolves.toEqual( 17 | new Uint8Array(readFileSync(path).subarray(16, 24)), 18 | ); 19 | 20 | await readable.close(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/root.canister.spec.ts: -------------------------------------------------------------------------------- 1 | import type { ActorSubclass } from "@icp-sdk/core/agent"; 2 | import { mock } from "vitest-mock-extended"; 3 | import type { SnsRootService } from "../declarations"; 4 | import { rootCanisterIdMock, snsMock } from "./mocks/sns.mock"; 5 | import { SnsRootCanister } from "./root.canister"; 6 | 7 | describe("Root canister", () => { 8 | it("should return the list of canister of the sns", async () => { 9 | const service = mock>(); 10 | service.list_sns_canisters.mockResolvedValue(snsMock); 11 | 12 | const canister = SnsRootCanister.create({ 13 | canisterId: rootCanisterIdMock, 14 | certifiedServiceOverride: service, 15 | }); 16 | const res = await canister.listSnsCanisters({}); 17 | 18 | expect(res).toEqual(snsMock); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_icrc-10.idl.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // @ts-nocheck 4 | 5 | // This file was automatically generated by @icp-sdk/bindgen@0.2.1. 6 | // You should NOT make any changes in this file as it will be overwritten. 7 | // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. 8 | 9 | export const idlFactory = ({ IDL }) => { 10 | const SupportedStandard = IDL.Record({ url: IDL.Text, name: IDL.Text }); 11 | const SupportedStandardsResponse = IDL.Vec(SupportedStandard); 12 | 13 | return IDL.Service({ 14 | icrc10_supported_standards: IDL.Func( 15 | [], 16 | [SupportedStandardsResponse], 17 | ["query"], 18 | ), 19 | }); 20 | }; 21 | 22 | export const init = ({ IDL }) => { 23 | return []; 24 | }; 25 | -------------------------------------------------------------------------------- /packages/utils/src/utils/base64.utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Converts a Uint8Array (binary data) to a base64 encoded string. 3 | * 4 | * @param {Uint8Array} uint8Array - The Uint8Array containing binary data to be encoded. 5 | * @returns {string} - The base64 encoded string representation of the binary data. 6 | */ 7 | export const uint8ArrayToBase64 = (uint8Array: Uint8Array): string => 8 | btoa(String.fromCharCode(...new Uint8Array(uint8Array))); 9 | 10 | /** 11 | * Converts a base64 encoded string to a Uint8Array (binary data). 12 | * 13 | * @param {string} base64String - The base64 encoded string to be decoded. 14 | * @returns {Uint8Array} - The Uint8Array representation of the decoded binary data. 15 | */ 16 | export const base64ToUint8Array = (base64String: string): Uint8Array => 17 | Uint8Array.from(atob(base64String), (c) => c.charCodeAt(0)); 18 | -------------------------------------------------------------------------------- /scripts/docs.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { generateDocumentation } = require("tsdoc-markdown"); 4 | 5 | const utilsInputFiles = ["./packages/utils/src/index.ts"]; 6 | 7 | const zodSchemasInputFiles = ["./packages/zod-schemas/src/index.ts"]; 8 | 9 | const buildOptions = { 10 | repo: { url: "https://github.com/dfinity/icp-js-canisters" }, 11 | }; 12 | 13 | const markdownOptions = { 14 | headingLevel: "###", 15 | }; 16 | 17 | generateDocumentation({ 18 | inputFiles: utilsInputFiles, 19 | outputFile: "./packages/utils/README.md", 20 | markdownOptions, 21 | buildOptions: { ...buildOptions, explore: true }, 22 | }); 23 | 24 | generateDocumentation({ 25 | inputFiles: zodSchemasInputFiles, 26 | outputFile: "./packages/zod-schemas/README.md", 27 | markdownOptions, 28 | buildOptions: { ...buildOptions, explore: true }, 29 | }); 30 | -------------------------------------------------------------------------------- /packages/canisters/src/ckbtc/types/minter.responses.ts: -------------------------------------------------------------------------------- 1 | import type { CkBtcMinterDid } from "../../declarations"; 2 | 3 | export type UpdateBalanceOk = CkBtcMinterDid.UtxoStatus[]; 4 | 5 | export type UpdateBalanceResponse = 6 | | { Ok: UpdateBalanceOk } 7 | | { Err: CkBtcMinterDid.UpdateBalanceError }; 8 | 9 | export type RetrieveBtcResponse = 10 | | { Ok: CkBtcMinterDid.RetrieveBtcOk } 11 | | { Err: CkBtcMinterDid.RetrieveBtcError }; 12 | 13 | export type RetrieveBtcWithApprovalResponse = 14 | | { Ok: CkBtcMinterDid.RetrieveBtcOk } 15 | | { Err: CkBtcMinterDid.RetrieveBtcWithApprovalError }; 16 | 17 | export interface EstimateWithdrawalFee { 18 | minter_fee: bigint; 19 | bitcoin_fee: bigint; 20 | } 21 | 22 | export interface RetrieveBtcStatusV2WithId { 23 | id: bigint; 24 | status: CkBtcMinterDid.RetrieveBtcStatusV2 | undefined; 25 | } 26 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/types/ledger.responses.ts: -------------------------------------------------------------------------------- 1 | import type { Principal } from "@icp-sdk/core/principal"; 2 | import type { IcrcLedgerDid } from "../../../declarations"; 3 | 4 | // Source: https://github.com/dfinity/icrc-1#standard-metadata-entries 5 | export enum IcrcMetadataResponseEntries { 6 | SYMBOL = "icrc1:symbol", 7 | NAME = "icrc1:name", 8 | DECIMALS = "icrc1:decimals", 9 | FEE = "icrc1:fee", 10 | LOGO = "icrc1:logo", 11 | } 12 | 13 | export type IcrcTokenMetadataResponse = [ 14 | string | IcrcMetadataResponseEntries, 15 | IcrcLedgerDid.Value, 16 | ][]; 17 | 18 | export interface IcrcAccount { 19 | owner: Principal; 20 | subaccount?: IcrcLedgerDid.Subaccount; 21 | } 22 | 23 | export interface IcrcTokenMetadata { 24 | name: string; 25 | symbol: string; 26 | fee: bigint; 27 | decimals: number; 28 | icon?: string; 29 | } 30 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/utils/governance.utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { mockPrincipal } from "../mocks/ledger.mock"; 2 | import { neuronSubaccount } from "./governance.utils"; 3 | 4 | describe("governance utils", () => { 5 | describe("neuronSubaccount", () => { 6 | // Test it to make sure that if there are changes, the test will fail. 7 | it("calculates the neuron subaccount based on controller and index", () => { 8 | const subaccount = neuronSubaccount({ 9 | controller: mockPrincipal, 10 | index: 4, 11 | }); 12 | const expected = new Uint8Array([ 13 | 198, 112, 210, 99, 31, 205, 63, 124, 217, 206, 133, 104, 105, 140, 83, 14 | 167, 139, 60, 94, 58, 107, 169, 215, 12, 177, 219, 237, 24, 75, 149, 15 | 241, 128, 16 | ]); 17 | 18 | expect(subaccount).toEqual(expected); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/nns-proto/proto/base_types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ic_base_types.pb.v1; 4 | 5 | import "google/protobuf/descriptor.proto"; 6 | 7 | // The annotated message is supported by hardware wallet signing. 8 | // The numbering was chosen as the range 19000-19999 is anyway reserved in protobuf. 9 | extend google.protobuf.MessageOptions { 10 | bool tui_signed_message = 20000; 11 | } 12 | 13 | // The annotated field is displayed on the hardware wallet in the specification 14 | // used by launch of the Internet Computer. 15 | extend google.protobuf.FieldOptions { 16 | bool tui_signed_display_q2_2021 = 20001; 17 | } 18 | 19 | // A PB container for a PrincipalId, which uniquely identifies 20 | // a principal. 21 | message PrincipalId { 22 | option (tui_signed_message) = true; 23 | bytes serialized_id = 1 [(tui_signed_display_q2_2021) = true]; 24 | } 25 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/converters/index.converters.ts: -------------------------------------------------------------------------------- 1 | import { toNullable } from "@dfinity/utils"; 2 | import type { IcrcIndexDid } from "../../../declarations"; 3 | import type { 4 | GetIndexAccountTransactionsParams, 5 | ListSubaccountsParams, 6 | } from "../types/index-ng.params"; 7 | import { toCandidAccount } from "./converters"; 8 | 9 | export const toGetTransactionsArgs = ({ 10 | account, 11 | max_results, 12 | start, 13 | }: Omit< 14 | GetIndexAccountTransactionsParams, 15 | "certified" 16 | >): IcrcIndexDid.GetAccountTransactionsArgs => ({ 17 | account: toCandidAccount(account), 18 | max_results, 19 | start: toNullable(start), 20 | }); 21 | 22 | export const toListSubaccountsParams = ({ 23 | owner, 24 | start, 25 | }: ListSubaccountsParams): IcrcIndexDid.ListSubaccountsArgs => ({ 26 | owner, 27 | start: toNullable(start), 28 | }); 29 | -------------------------------------------------------------------------------- /packages/canisters/src/nns/errors/governance.errors.ts: -------------------------------------------------------------------------------- 1 | import type { NnsGovernanceDid } from "../../declarations"; 2 | 3 | export abstract class StakeNeuronError extends Error {} 4 | 5 | export class CouldNotClaimNeuronError extends StakeNeuronError {} 6 | 7 | export class InsufficientAmountError extends StakeNeuronError { 8 | constructor(public readonly minimumAmount: bigint) { 9 | super(); 10 | } 11 | } 12 | 13 | export class UnrecognizedTypeError extends Error {} 14 | export class GovernanceError extends Error { 15 | constructor(public readonly detail: NnsGovernanceDid.GovernanceError) { 16 | super(); 17 | } 18 | } 19 | 20 | /** 21 | * An error used to ensure at compile-time that it's never reached. 22 | */ 23 | export class UnsupportedValueError extends Error { 24 | constructor(value: never) { 25 | super(`Unsupported value: ${value}`); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/canisters/src/nns/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module api/nns 3 | */ 4 | 5 | export type { 6 | NnsGenesisTokenDid, 7 | NnsGovernanceDid, 8 | NnsGovernanceTestDid, 9 | SnsWasmDid, 10 | } from "../declarations"; 11 | export * from "./enums/governance.enums"; 12 | export * from "./errors/governance.errors"; 13 | export { NnsGenesisTokenCanister } from "./genesis_token.canister"; 14 | export { NnsGovernanceCanister } from "./governance.canister"; 15 | export { NnsGovernanceTestCanister } from "./governance_test.canister"; 16 | export { SnsWasmCanister } from "./sns_wasm.canister"; 17 | export * from "./types/common"; 18 | export * from "./types/governance.options"; 19 | export * from "./types/governance_converters"; 20 | export type { SnsWasmCanisterOptions } from "./types/sns_wasm.options"; 21 | export * from "./utils/account_identifier.utils"; 22 | export * from "./utils/neurons.utils"; 23 | -------------------------------------------------------------------------------- /scripts/update-agent: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function rm_agent() { 4 | local package=$1 5 | 6 | npm rm @icp-sdk/core --workspace=packages/"$package" 7 | 8 | # Just in case, make sure the dependencies re-exported by `@icp-sdk/core` are properly removed 9 | npm rm @dfinity/agent @dfinity/candid @dfinity/principal @dfinity/identity @dfinity/identity-secp256k1 --workspace=packages/"$package" 10 | } 11 | 12 | function install_agent() { 13 | local package=$1 14 | 15 | npm i @icp-sdk/core@latest --workspace=packages/"$package" --save-peer 16 | } 17 | 18 | PACKAGES=utils,zod-schemas,canisters 19 | 20 | # Remove agent-js libraries from all packages first to avoid resolve conflicts between those 21 | for package in $(echo $PACKAGES | sed "s/,/ /g"); do 22 | rm_agent "$package" 23 | done 24 | 25 | for package in $(echo $PACKAGES | sed "s/,/ /g"); do 26 | install_agent "$package" 27 | done 28 | -------------------------------------------------------------------------------- /.github/workflows/tests-integration.yml: -------------------------------------------------------------------------------- 1 | name: Integration Tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - 'packages/canisters/src/assets/**' 9 | - 'tests/integration/**' 10 | pull_request: 11 | paths: 12 | - 'packages/canisters/src/assets/**' 13 | - 'tests/integration/**' 14 | 15 | jobs: 16 | test-assets-integration: 17 | runs-on: ubuntu-24.04 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | - uses: dfinity/setup-dfx@main 22 | - name: Prepare 23 | uses: ./.github/actions/prepare 24 | - name: Build 25 | run: npm run build 26 | - name: Test integration 27 | run: npm run test:integration 28 | 29 | may-merge: 30 | needs: ["test-assets-integration"] 31 | runs-on: ubuntu-24.04 32 | steps: 33 | - name: Cleared for merging 34 | run: echo OK -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_icrc-10.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // @ts-nocheck 4 | 5 | // This file was automatically generated by @icp-sdk/bindgen@0.2.1. 6 | // You should NOT make any changes in this file as it will be overwritten. 7 | // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. 8 | 9 | import type { ActorMethod } from "@icp-sdk/core/agent"; 10 | import type { IDL } from "@icp-sdk/core/candid"; 11 | 12 | export interface SupportedStandard { 13 | url: string; 14 | name: string; 15 | } 16 | export type SupportedStandardsResponse = Array; 17 | export interface _SERVICE { 18 | icrc10_supported_standards: ActorMethod<[], SupportedStandardsResponse>; 19 | } 20 | export declare const idlFactory: IDL.InterfaceFactory; 21 | export declare const init: (args: { IDL: typeof IDL }) => IDL.Type[]; 22 | -------------------------------------------------------------------------------- /packages/canisters/src/assets/readable/readable-file.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable local-rules/prefer-object-params */ 2 | 3 | import type { Readable } from "./readable"; 4 | 5 | export class ReadableFile implements Readable { 6 | private readonly _file: File; 7 | 8 | constructor(file: File) { 9 | this._file = file; 10 | } 11 | 12 | public get fileName(): string { 13 | return this._file.name; 14 | } 15 | 16 | public get contentType(): string { 17 | return this._file.type; 18 | } 19 | 20 | public get length(): number { 21 | return this._file.size; 22 | } 23 | 24 | public open(): Promise { 25 | return Promise.resolve(); 26 | } 27 | 28 | public close(): Promise { 29 | return Promise.resolve(); 30 | } 31 | 32 | public async slice(start: number, end: number): Promise { 33 | return new Uint8Array(await this._file.slice(start, end).arrayBuffer()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/canister.ts: -------------------------------------------------------------------------------- 1 | import { Canister, toNullable } from "@dfinity/utils"; 2 | import type { IcrcLedgerDid } from "../../declarations"; 3 | import type { IcrcCanisterService } from "./types/canister.types"; 4 | import type { BalanceParams } from "./types/ledger.params"; 5 | 6 | export abstract class IcrcCanister< 7 | T extends IcrcCanisterService, 8 | > extends Canister { 9 | /** 10 | * Returns the balance for a given account provided as owner and with optional subaccount. 11 | * 12 | * @param {BalanceParams} params The parameters to get the balance of an account. 13 | * @returns {Promise} The balance of the given account. 14 | */ 15 | balance = (params: BalanceParams): Promise => 16 | this.caller({ certified: params.certified }).icrc1_balance_of({ 17 | owner: params.owner, 18 | subaccount: toNullable(params.subaccount), 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /packages/zod-schemas/src/principal.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | import * as z from "zod"; 3 | 4 | /** 5 | * Zod schema to validate a string as a valid textual representation of a Principal. 6 | * 7 | * This schema checks if the provided string can be converted into a `Principal` instance. 8 | * If the conversion fails, validation will return an error message. 9 | * 10 | * @example 11 | * ```typescript 12 | * const result = PrincipalTextSchema.safeParse('aaaaa-aa'); 13 | * console.log(result.success); // true or false 14 | * ``` 15 | */ 16 | export const PrincipalTextSchema = z.string().refine( 17 | (principal) => { 18 | try { 19 | Principal.fromText(principal); 20 | return true; 21 | } catch (_err: unknown) { 22 | return false; 23 | } 24 | }, 25 | { 26 | error: "Invalid textual representation of a Principal.", 27 | }, 28 | ); 29 | 30 | export type PrincipalText = z.infer; 31 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/utils/error.utils.ts: -------------------------------------------------------------------------------- 1 | import { nonNullish } from "@dfinity/utils"; 2 | 3 | /** 4 | * Identifies errors of method not being present in the canister. 5 | * 6 | * This is useful because SNS projects have different versions of SNS canisters. 7 | * Therefore, what works in the latest version might not work in the previous one. 8 | * 9 | * Error message example: "Call was rejected: 10 | * Request ID: 3a6ef904b35fd19721c95c3df2b0b00b8abefba7f0ad188f5c472809b772c914 11 | * Reject code: 3 12 | * Reject text: Canister 75ffu-oaaaa-aaaaa-aabbq-cai has no update method 'get_auto_finalization_status'" 13 | */ 14 | export const isMethodNotSupportedError = (err: unknown): boolean => { 15 | if (typeof err === "object" && nonNullish(err) && "message" in err) { 16 | const message = err.message as string; 17 | return ( 18 | message.includes("has no update method") || 19 | message.includes("has no query method") 20 | ); 21 | } 22 | return false; 23 | }; 24 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module api/sns 3 | */ 4 | 5 | export type { 6 | SnsGovernanceDid, 7 | SnsGovernanceTestDid, 8 | SnsRootDid, 9 | SnsSwapDid, 10 | SnsWasmDid, 11 | } from "../declarations"; 12 | export { fromCandidAction } from "./converters/governance.converters"; 13 | export * from "./enums/governance.enums"; 14 | export * from "./enums/swap.enums"; 15 | export * from "./errors/common.errors"; 16 | export * from "./errors/governance.errors"; 17 | export * from "./errors/swap.errors"; 18 | export { SnsGovernanceCanister } from "./governance.canister"; 19 | export { SnsGovernanceTestCanister } from "./governance_test.canister"; 20 | export { SnsRootCanister } from "./root.canister"; 21 | export * from "./sns"; 22 | export * from "./sns.wrapper"; 23 | export { SnsSwapCanister } from "./swap.canister"; 24 | export type { SnsCanisterOptions } from "./types/canister.options"; 25 | export * from "./types/governance.params"; 26 | export * from "./utils/governance.utils"; 27 | -------------------------------------------------------------------------------- /packages/sns/src/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | initSnsWrapper, 3 | SnsGovernanceCanister, 4 | SnsGovernanceTestCanister, 5 | SnsRootCanister, 6 | SnsSwapCanister, 7 | SnsWrapper, 8 | } from "./index"; 9 | 10 | describe("@dfinity/sns", () => { 11 | it("should re-export SnsRootCanister", () => { 12 | expect(SnsRootCanister).not.toBeUndefined(); 13 | }); 14 | 15 | it("should re-export SnsGovernanceCanister", () => { 16 | expect(SnsGovernanceCanister).not.toBeUndefined(); 17 | }); 18 | 19 | it("should re-export SnsSwapCanister", () => { 20 | expect(SnsSwapCanister).not.toBeUndefined(); 21 | }); 22 | 23 | it("should re-export SnsGovernanceTestCanister", () => { 24 | expect(SnsGovernanceTestCanister).not.toBeUndefined(); 25 | }); 26 | 27 | it("should re-export initSnsWrapper", () => { 28 | expect(initSnsWrapper).not.toBeUndefined(); 29 | }); 30 | 31 | it("should re-export SnsWrapper", () => { 32 | expect(SnsWrapper).not.toBeUndefined(); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/errors/swap.errors.ts: -------------------------------------------------------------------------------- 1 | import type { SnsSwapDid } from "../../declarations"; 2 | import type { 3 | GetOpenTicketErrorType, 4 | NewSaleTicketResponseErrorType, 5 | } from "../enums/swap.enums"; 6 | 7 | export class SnsSwapNewTicketError extends Error { 8 | public errorType: NewSaleTicketResponseErrorType; 9 | public invalidUserAmount?: SnsSwapDid.InvalidUserAmount; 10 | public existingTicket?: SnsSwapDid.Ticket; 11 | 12 | constructor({ 13 | errorType, 14 | invalidUserAmount, 15 | existingTicket, 16 | }: { 17 | errorType: NewSaleTicketResponseErrorType; 18 | invalidUserAmount?: SnsSwapDid.InvalidUserAmount; 19 | existingTicket?: SnsSwapDid.Ticket; 20 | }) { 21 | super(); 22 | this.errorType = errorType; 23 | this.invalidUserAmount = invalidUserAmount; 24 | this.existingTicket = existingTicket; 25 | } 26 | } 27 | 28 | export class SnsSwapGetOpenTicketError extends Error { 29 | constructor(public errorType: GetOpenTicketErrorType) { 30 | super(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /scripts/build.utils.mjs: -------------------------------------------------------------------------------- 1 | import { readFileSync } from "node:fs"; 2 | import { dirname, join } from "node:path"; 3 | import { fileURLToPath } from "node:url"; 4 | 5 | const __filename = fileURLToPath(import.meta.url); 6 | const __dirname = dirname(__filename); 7 | 8 | export const SCRIPTS_PATH = __dirname; 9 | 10 | /** 11 | * Read the peer dependencies and exports of the package.json of the package (library) to build. 12 | */ 13 | export const readPackageJsonPeerAndExports = (packageJson) => { 14 | const json = readFileSync(packageJson, "utf8"); 15 | const { peerDependencies, exports } = JSON.parse(json); 16 | return { peerDependencies: peerDependencies ?? {}, exports: exports ?? {} }; 17 | }; 18 | 19 | /** 20 | * Root peerDependencies are common external dependencies for all libraries of the mono-repo. 21 | */ 22 | export const rootPeerDependencies = () => { 23 | const packageJson = join(SCRIPTS_PATH, "../package.json"); 24 | const { peerDependencies } = readPackageJsonPeerAndExports(packageJson); 25 | return peerDependencies; 26 | }; 27 | -------------------------------------------------------------------------------- /packages/canisters/src/assets/readable/readable-blob.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable local-rules/prefer-object-params */ 2 | 3 | import mime from "mime/lite.js"; 4 | import type { Readable } from "./readable"; 5 | 6 | export class ReadableBlob implements Readable { 7 | public readonly fileName: string; 8 | private readonly _blob: Blob; 9 | 10 | constructor(fileName: string, blob: Blob) { 11 | this.fileName = fileName; 12 | this._blob = blob; 13 | } 14 | 15 | public get contentType(): string { 16 | return ( 17 | this._blob.type || 18 | (mime.getType(this.fileName) ?? "application/octet-stream") 19 | ); 20 | } 21 | 22 | public get length(): number { 23 | return this._blob.size; 24 | } 25 | 26 | open(): Promise { 27 | return Promise.resolve(); 28 | } 29 | 30 | close(): Promise { 31 | return Promise.resolve(); 32 | } 33 | 34 | async slice(start: number, end: number): Promise { 35 | return new Uint8Array(await this._blob.slice(start, end).arrayBuffer()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/canisters/src/assets/utils/limit.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Minimal promise executor with concurrency limit implementation 3 | * @param concurrency Maximum number of promises executed concurrently 4 | */ 5 | export const limit = (concurrency: number) => { 6 | const queue: Array<{ 7 | fn: () => Promise; 8 | resolve: (value: unknown | PromiseLike) => void; 9 | reject: (reason: unknown) => void; 10 | }> = []; 11 | let active = 0; 12 | const next = () => { 13 | if (active < concurrency && queue.length > 0) { 14 | active++; 15 | const { fn, resolve, reject } = queue.shift() ?? {}; 16 | fn?.() 17 | .then(resolve) 18 | .catch(reject) 19 | .then(() => { 20 | active--; 21 | next(); 22 | }); 23 | } 24 | }; 25 | return (fn: () => Promise) => 26 | new Promise((resolve, reject) => { 27 | queue.push({ fn, resolve, reject }); 28 | next(); 29 | }) as Promise; 30 | }; 31 | 32 | export type LimitFn = ReturnType; 33 | -------------------------------------------------------------------------------- /packages/canisters/src/nns/mocks/sns_wasm.mock.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | import type { SnsWasmDid } from "../../declarations"; 3 | 4 | export const deployedSnsMock: SnsWasmDid.DeployedSns[] = [ 5 | { 6 | root_canister_id: [Principal.fromText("pin7y-wyaaa-aaaaa-aacpa-cai")], 7 | governance_canister_id: [Principal.fromText("pin7y-wyaaa-aaaaa-aacpa-cai")], 8 | index_canister_id: [Principal.fromText("pin7y-wyaaa-aaaaa-aacpa-cai")], 9 | swap_canister_id: [Principal.fromText("pin7y-wyaaa-aaaaa-aacpa-cai")], 10 | ledger_canister_id: [Principal.fromText("pin7y-wyaaa-aaaaa-aacpa-cai")], 11 | }, 12 | { 13 | root_canister_id: [Principal.fromText("zdlco-vyaaa-aaaaa-aabva-cai")], 14 | governance_canister_id: [Principal.fromText("zdlco-vyaaa-aaaaa-aabva-cai")], 15 | index_canister_id: [Principal.fromText("zdlco-vyaaa-aaaaa-aabva-cai")], 16 | swap_canister_id: [Principal.fromText("zdlco-vyaaa-aaaaa-aabva-cai")], 17 | ledger_canister_id: [Principal.fromText("zdlco-vyaaa-aaaaa-aabva-cai")], 18 | }, 19 | ]; 20 | -------------------------------------------------------------------------------- /packages/canisters/src/assets/readable/readable-bytes.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable local-rules/prefer-object-params */ 2 | 3 | import mime from "mime/lite.js"; 4 | import type { Readable } from "./readable"; 5 | 6 | export class ReadableBytes implements Readable { 7 | public readonly fileName: string; 8 | private readonly _bytes: Uint8Array; 9 | 10 | constructor(fileName: string, bytes: Uint8Array | ArrayBuffer | number[]) { 11 | this.fileName = fileName; 12 | this._bytes = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes); 13 | } 14 | 15 | public get contentType(): string { 16 | return mime.getType(this.fileName) ?? "application/octet-stream"; 17 | } 18 | 19 | public get length(): number { 20 | return this._bytes.byteLength; 21 | } 22 | 23 | public open(): Promise { 24 | return Promise.resolve(); 25 | } 26 | 27 | public close(): Promise { 28 | return Promise.resolve(); 29 | } 30 | 31 | public slice(start: number, end: number): Promise { 32 | return Promise.resolve(this._bytes.slice(start, end)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/canisters/src/assets/readable/readable-file.spec.ts: -------------------------------------------------------------------------------- 1 | import { ReadableFile } from "./readable-file"; 2 | 3 | describe("ReadableFile", () => { 4 | test("ReadableFile from File", async () => { 5 | const file = new File(["Hello world!"], "hello.txt"); 6 | const readable = new ReadableFile(file); 7 | 8 | expect(readable.fileName).toEqual(file.name); 9 | expect(readable.contentType).toEqual(""); 10 | expect(readable).toHaveLength(file.size); 11 | 12 | await readable.open(); 13 | 14 | await expect(readable.slice(1, 4)).resolves.toEqual( 15 | new Uint8Array(await file.slice(1, 4).arrayBuffer()), 16 | ); 17 | 18 | await readable.close(); 19 | }); 20 | 21 | test("ReadableFile from File with mime type", () => { 22 | const file = new File(["Hello world!"], "hello.txt", { 23 | type: "text/plain", 24 | }); 25 | const readable = new ReadableFile(file); 26 | 27 | expect(readable.fileName).toEqual(file.name); 28 | expect(readable.contentType).toEqual("text/plain"); 29 | expect(readable).toHaveLength(file.size); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /packages/canisters/src/ic-management/ic-management.mock.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | import { 3 | toCanisterSettings, 4 | type CanisterSettings, 5 | } from "./types/ic-management.params"; 6 | 7 | export const mockPrincipalText = 8 | "xlmdg-vkosz-ceopx-7wtgu-g3xmd-koiyc-awqaq-7modz-zf6r6-364rh-oqe"; 9 | 10 | export const mockPrincipal = Principal.fromText(mockPrincipalText); 11 | 12 | export const mockCanisterId = Principal.fromText("ryjl3-tyaaa-aaaaa-aaaba-cai"); 13 | 14 | export const mockCanisterSettings: CanisterSettings = { 15 | freezingThreshold: BigInt(2), 16 | controllers: [mockPrincipalText], 17 | memoryAllocation: BigInt(4), 18 | computeAllocation: BigInt(10), 19 | }; 20 | 21 | export const mappedMockCanisterSettings = 22 | toCanisterSettings(mockCanisterSettings); 23 | 24 | const mockLocalSubnetId = [0, 0, 0, 0, 0, 0, 0, 1]; 25 | 26 | export const mockSnapshotId = Uint8Array.from([ 27 | ...mockCanisterId.toUint8Array(), 28 | ...mockLocalSubnetId, 29 | ]); 30 | 31 | export const mockSnapshotIdHex = "000000000000000201010000000000000001"; 32 | -------------------------------------------------------------------------------- /packages/canisters/src/assets/readable/readable.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable local-rules/prefer-object-params */ 2 | 3 | export interface Readable { 4 | fileName: string; 5 | contentType: string; 6 | length: number; 7 | open: () => Promise; 8 | close: () => Promise; 9 | slice: (start: number, end: number) => Promise; 10 | } 11 | 12 | const isObjWithKeys = ( 13 | obj: unknown, 14 | ...keys: Array 15 | ): obj is Record => 16 | obj !== null && 17 | typeof obj === "object" && 18 | keys.every((key) => key !== null && key !== undefined && key in obj); 19 | 20 | export const isReadable = (value: unknown): value is Readable => 21 | isObjWithKeys( 22 | value, 23 | "fileName", 24 | "contentType", 25 | "length", 26 | "open", 27 | "close", 28 | "slice", 29 | ) && 30 | typeof value.fileName === "string" && 31 | typeof value.contentType === "string" && 32 | typeof value.length === "number" && 33 | typeof value.open === "function" && 34 | typeof value.close === "function" && 35 | typeof value.slice === "function"; 36 | -------------------------------------------------------------------------------- /packages/utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./enums/token.enums"; 2 | export * from "./parser/token"; 3 | export * from "./services/canister"; 4 | export * from "./services/query"; 5 | export * from "./types/actor-type.utils"; 6 | export type { CreateAgentParams } from "./types/agent.utils"; 7 | export type { CanisterOptions } from "./types/canister.options"; 8 | export * from "./types/did.utils"; 9 | export * from "./types/query-and-update.params"; 10 | export type { QueryParams } from "./types/query.params"; 11 | export * from "./utils/actor.utils"; 12 | export * from "./utils/agent.utils"; 13 | export * from "./utils/arrays.utils"; 14 | export * from "./utils/asserts.utils"; 15 | export * from "./utils/base32.utils"; 16 | export * from "./utils/base64.utils"; 17 | export * from "./utils/crc.utils"; 18 | export * from "./utils/crypto.utils"; 19 | export * from "./utils/date.utils"; 20 | export * from "./utils/debounce.utils"; 21 | export * from "./utils/did.utils"; 22 | export * from "./utils/json.utils"; 23 | export * from "./utils/nullish.utils"; 24 | export * from "./utils/principal.utils"; 25 | export * from "./utils/version.utils"; 26 | -------------------------------------------------------------------------------- /packages/utils/src/utils/principal.utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | import { principalToSubAccount } from "./principal.utils"; 3 | 4 | describe("Cycles Minting Canister utils", () => { 5 | describe("principalToSubAccount", () => { 6 | it("converts successfully principals to subaccounts", () => { 7 | const principalEmtpy = Principal.fromText("aaaaa-aa"); 8 | const expectedEmpty = new Uint8Array([ 9 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 | 0, 0, 0, 0, 0, 0, 0, 0, 11 | ]); 12 | const somePrincipal = Principal.fromText( 13 | "xlmdg-vkosz-ceopx-7wtgu-g3xmd-koiyc-awqaq-7modz-zf6r6-364rh-oqe", 14 | ); 15 | const someExpected = new Uint8Array([ 16 | 29, 78, 150, 68, 71, 62, 255, 180, 205, 67, 110, 236, 26, 156, 140, 8, 17 | 22, 128, 33, 246, 56, 121, 201, 125, 31, 111, 220, 137, 221, 2, 0, 0, 18 | ]); 19 | 20 | expect(principalToSubAccount(principalEmtpy)).toEqual(expectedEmpty); 21 | expect(principalToSubAccount(somePrincipal)).toEqual(someExpected); 22 | }); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/utils/governance.utils.ts: -------------------------------------------------------------------------------- 1 | import { 2 | arrayOfNumberToUint8Array, 3 | asciiStringToByteArray, 4 | numberToUint8Array, 5 | } from "@dfinity/utils"; 6 | import type { Principal } from "@icp-sdk/core/principal"; 7 | import { sha256 } from "@noble/hashes/sha2"; 8 | import type { IcrcLedgerDid } from "../../ledger/icrc"; 9 | 10 | /** 11 | * Neuron subaccount is calculated as "sha256(0x0c . “neuron-stake” . controller . i)" 12 | * 13 | * @param params 14 | * @param {Principal} params.newController 15 | * @param {number} params.index 16 | * @returns 17 | */ 18 | export const neuronSubaccount = ({ 19 | index, 20 | controller, 21 | }: { 22 | index: number; 23 | controller: Principal; 24 | }): IcrcLedgerDid.Subaccount => { 25 | const padding = asciiStringToByteArray("neuron-stake"); 26 | const data = [ 27 | 0x0c, 28 | ...padding, 29 | ...controller.toUint8Array(), 30 | ...numberToUint8Array(index), 31 | ]; 32 | // TODO(#238): Implement without library and make it compatible with NodeJS and browser 33 | const shaObj = sha256.create(); 34 | shaObj.update(arrayOfNumberToUint8Array(data)); 35 | return shaObj.digest(); 36 | }; 37 | -------------------------------------------------------------------------------- /scripts/build-next: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eux 3 | 4 | : Optional tag argument 5 | TAG= 6 | 7 | while [[ $# -gt 0 ]]; do 8 | case "$1" in 9 | --tag=*) 10 | TAG="${1#*=}" 11 | shift 12 | ;; 13 | *) 14 | echo "Unknown argument: $1" 15 | echo "Usage: ./scripts/build-next [--tag=TAG_NAME]" 16 | exit 1 17 | ;; 18 | esac 19 | done 20 | 21 | : Update the package.json version before build and publish 22 | node ./scripts/update-version.mjs utils dfinity $TAG 23 | node ./scripts/update-version.mjs zod-schemas dfinity $TAG 24 | node ./scripts/update-version.mjs nns-proto dfinity $TAG 25 | node ./scripts/update-version.mjs canisters icp-sdk $TAG 26 | node ./scripts/update-version.mjs ckbtc dfinity $TAG 27 | node ./scripts/update-version.mjs cketh dfinity $TAG 28 | node ./scripts/update-version.mjs cmc dfinity $TAG 29 | node ./scripts/update-version.mjs ic-management dfinity $TAG 30 | node ./scripts/update-version.mjs ledger-icp dfinity $TAG 31 | node ./scripts/update-version.mjs ledger-icrc dfinity $TAG 32 | node ./scripts/update-version.mjs nns dfinity $TAG 33 | node ./scripts/update-version.mjs sns dfinity $TAG 34 | 35 | : Now we can build 36 | npm run build 37 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/mocks/ledger.mock.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | import type { IcrcLedgerDid } from "../../../declarations"; 3 | import { IcrcMetadataResponseEntries } from "../types/ledger.responses"; 4 | 5 | export const tokenMetadataResponseMock: [ 6 | string | IcrcMetadataResponseEntries, 7 | IcrcLedgerDid.MetadataValue, 8 | ][] = [ 9 | [IcrcMetadataResponseEntries.DECIMALS, { Nat: BigInt(8) }], 10 | [IcrcMetadataResponseEntries.NAME, { Text: "Beta Test" }], 11 | [IcrcMetadataResponseEntries.SYMBOL, { Text: "BTA" }], 12 | [IcrcMetadataResponseEntries.FEE, { Nat: BigInt(1000) }], 13 | [ 14 | IcrcMetadataResponseEntries.LOGO, 15 | { Text: "data:image/svg+xml;base64,PHN2ZyB3aW..." }, 16 | ], 17 | ]; 18 | 19 | export const mockPrincipalText = 20 | "xlmdg-vkosz-ceopx-7wtgu-g3xmd-koiyc-awqaq-7modz-zf6r6-364rh-oqe"; 21 | 22 | export const mockPrincipal = Principal.fromText(mockPrincipalText); 23 | 24 | export const ledgerCanisterIdMock: Principal = Principal.fromText( 25 | "ktxdj-qiaaa-aaaaa-aacqa-cai", 26 | ); 27 | 28 | export const indexCanisterIdMock: Principal = Principal.fromText( 29 | "qjdve-lqaaa-aaaaa-aaaeq-cai", 30 | ); 31 | -------------------------------------------------------------------------------- /packages/utils/src/utils/base32.utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | import { decodeBase32, encodeBase32 } from "./base32.utils"; 3 | import { bigEndianCrc32 } from "./crc.utils"; 4 | 5 | describe("base32-utils", () => { 6 | const checksum = "dfxgiyy"; 7 | 8 | it("should encode base32", () => { 9 | const owner = Principal.fromText( 10 | "k2t6j-2nvnp-4zjm3-25dtz-6xhaa-c7boj-5gayf-oj3xs-i43lp-teztq-6ae", 11 | ); 12 | const subaccount = Uint8Array.from([...Array(32)].map((_, i) => i + 1)); 13 | 14 | const crc = bigEndianCrc32( 15 | Uint8Array.from([...owner.toUint8Array(), ...subaccount]), 16 | ); 17 | 18 | expect(encodeBase32(crc)).toEqual(checksum); 19 | }); 20 | 21 | // Same logic as in @icp-sdk/core/principal.fromText 22 | it("should decode base32", () => { 23 | const canisterIdNoDash = "rrkah-fqaaa-aaaaa-aaaaq-cai" 24 | .toLowerCase() 25 | .replace(/-/g, ""); 26 | 27 | let arr = decodeBase32(canisterIdNoDash); 28 | arr = arr.slice(4, arr.length); 29 | 30 | const principal = Principal.fromUint8Array(arr); 31 | 32 | expect(principal.toText()).toEqual("rrkah-fqaaa-aaaaa-aaaaq-cai"); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/sns.spec.ts: -------------------------------------------------------------------------------- 1 | import type { ActorSubclass } from "@icp-sdk/core/agent"; 2 | import { mock } from "vitest-mock-extended"; 3 | import type { SnsRootService } from "../declarations"; 4 | import { 5 | governanceCanisterIdMock, 6 | indexCanisterIdMock, 7 | ledgerCanisterIdMock, 8 | rootCanisterIdMock, 9 | snsMock, 10 | swapCanisterIdMock, 11 | } from "./mocks/sns.mock"; 12 | import { initSnsWrapper } from "./sns"; 13 | 14 | describe("Sns", () => { 15 | it("should init a wrapper", async () => { 16 | const service = mock>(); 17 | service.list_sns_canisters.mockResolvedValue(snsMock); 18 | 19 | const { canisterIds } = await initSnsWrapper({ 20 | rootOptions: { 21 | canisterId: rootCanisterIdMock, 22 | certifiedServiceOverride: service, 23 | }, 24 | }); 25 | 26 | expect(canisterIds).not.toBeNull(); 27 | 28 | expect(canisterIds).toEqual({ 29 | rootCanisterId: rootCanisterIdMock, 30 | ledgerCanisterId: ledgerCanisterIdMock, 31 | governanceCanisterId: governanceCanisterIdMock, 32 | swapCanisterId: swapCanisterIdMock, 33 | indexCanisterId: indexCanisterIdMock, 34 | }); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /.github/workflows/pr-checks.yml: -------------------------------------------------------------------------------- 1 | name: 'PR Checks' 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - opened 7 | - edited 8 | - reopened 9 | - synchronize 10 | - labeled 11 | merge_group: 12 | 13 | permissions: {} 14 | 15 | jobs: 16 | check-pr-title: 17 | runs-on: ubuntu-latest 18 | permissions: 19 | pull-requests: read 20 | env: 21 | TITLE: ${{ github.event.pull_request.title }} 22 | steps: 23 | - name: 'Check PR Title' 24 | run: | 25 | if [[ "$TITLE" =~ ^(feat|fix|chore|build|ci|docs|style|refactor|perf|test)(\([-a-zA-Z0-9,]+\))\!?\: ]]; then 26 | echo "PR Title passes" 27 | else 28 | echo "PR Title does not match conventions:" 29 | echo " verb(scope): description" 30 | echo "or for a breaking change:" 31 | echo " verb(scope)!: description" 32 | echo "For scope, please use the affected library name(s) or 'ci' for infrastructure changes." 33 | exit 1 34 | fi 35 | 36 | may-merge: 37 | needs: ['check-pr-title'] 38 | runs-on: ubuntu-latest 39 | steps: 40 | - name: Cleared for merging 41 | run: echo OK 42 | -------------------------------------------------------------------------------- /packages/utils/src/mocks/agent.mock.ts: -------------------------------------------------------------------------------- 1 | import type { HttpAgent } from "@icp-sdk/core/agent"; 2 | import type { AgentManagerConfig } from "../utils/agent.utils"; 3 | 4 | export const mockHttpAgent = { 5 | call: vi.fn().mockResolvedValue({ 6 | ok: true, 7 | status: 200, 8 | statusText: "OK", 9 | json: () => ({ data: "mocked call result" }), 10 | }), 11 | query: vi.fn().mockResolvedValue({ 12 | ok: true, 13 | status: 200, 14 | statusText: "OK", 15 | json: () => ({ data: "mocked query result" }), 16 | }), 17 | fetchRootKey: vi.fn().mockResolvedValue(undefined), 18 | } as unknown as HttpAgent; 19 | 20 | export const mockHttpAgent2 = { 21 | call: vi.fn().mockResolvedValue({ 22 | ok: true, 23 | status: 200, 24 | statusText: "OK", 25 | json: () => ({ data: "mocked call result" }), 26 | }), 27 | query: vi.fn().mockResolvedValue({ 28 | ok: true, 29 | status: 200, 30 | statusText: "OK", 31 | json: () => ({ data: "mocked query result" }), 32 | }), 33 | fetchRootKey: vi.fn().mockResolvedValue(undefined), 34 | } as unknown as HttpAgent; 35 | 36 | export const mockAgentManagerConfig: AgentManagerConfig = { 37 | fetchRootKey: false, 38 | host: "https://icp-api.io", 39 | }; 40 | -------------------------------------------------------------------------------- /packages/canisters/src/cmc/cmc.errors.ts: -------------------------------------------------------------------------------- 1 | import { assertNever, jsonReplacer } from "@dfinity/utils"; 2 | import type { CmcDid } from "../declarations"; 3 | 4 | export class RefundedError extends Error {} 5 | export class InvalidaTransactionError extends Error {} 6 | export class CmcError extends Error {} 7 | export class ProcessingError extends Error {} 8 | export class TransactionTooOldError extends Error {} 9 | 10 | // Throws one of the errors above 11 | export const throwNotifyError = ({ 12 | Err: error, 13 | }: { 14 | Err: CmcDid.NotifyError; 15 | }): void => { 16 | if ("Refunded" in error) { 17 | throw new RefundedError(error.Refunded.reason); 18 | } 19 | if ("InvalidTransaction" in error) { 20 | throw new InvalidaTransactionError(error.InvalidTransaction); 21 | } 22 | if ("Processing" in error) { 23 | throw new ProcessingError(); 24 | } 25 | if ("TransactionTooOld" in error) { 26 | throw new TransactionTooOldError(); 27 | } 28 | if ("Other" in error) { 29 | throw new CmcError( 30 | `Error in CMC with code ${error.Other.error_code}: ${error.Other.error_message}`, 31 | ); 32 | } 33 | 34 | assertNever( 35 | error, 36 | `Unsupported error type ${JSON.stringify(error, jsonReplacer)}`, 37 | ); 38 | }; 39 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/converters/converters.ts: -------------------------------------------------------------------------------- 1 | import { fromNullable, nonNullish, toNullable } from "@dfinity/utils"; 2 | import type { IcrcLedgerDid } from "../../../declarations"; 3 | import type { IcrcAccount } from "../types/ledger.responses"; 4 | 5 | /** 6 | * Converts a Candid Account object to an IcrcAccount, effectively transforming nullable properties into nullish ones. 7 | * 8 | * @param {Account} - The Candid Account object to convert. 9 | * @return {IcrcAccount} - The converted IcrcAccount object. 10 | */ 11 | export const fromCandidAccount = ({ 12 | owner, 13 | subaccount: nullableSubaccount, 14 | }: IcrcLedgerDid.Account): IcrcAccount => { 15 | const subaccount = fromNullable(nullableSubaccount); 16 | 17 | return { 18 | owner, 19 | ...(nonNullish(subaccount) ? { subaccount } : {}), 20 | }; 21 | }; 22 | 23 | /** 24 | * Converts an IcrcAccount to a Candid Account object, effectively transforming nullish properties into nullable ones. 25 | * 26 | * @param {IcrcAccount} - The IcrcAccount object to convert. 27 | * @return {Account} - The converted Candid Account object. 28 | */ 29 | export const toCandidAccount = ({ 30 | owner, 31 | subaccount, 32 | }: IcrcAccount): IcrcLedgerDid.Account => ({ 33 | owner, 34 | subaccount: toNullable(subaccount), 35 | }); 36 | -------------------------------------------------------------------------------- /packages/canisters/src/nns/sns_wasm.canister.ts: -------------------------------------------------------------------------------- 1 | import { createServices, type CanisterOptions } from "@dfinity/utils"; 2 | import { 3 | idlFactoryCertifiedSnsWasm, 4 | idlFactorySnsWasm, 5 | type SnsWasmDid, 6 | type SnsWasmService, 7 | } from "../declarations"; 8 | import { MAINNET_SNS_WASM_CANISTER_ID } from "./constants/canister_ids"; 9 | 10 | export class SnsWasmCanister { 11 | private constructor( 12 | private readonly service: SnsWasmService, 13 | private readonly certifiedService: SnsWasmService, 14 | ) {} 15 | 16 | public static create(options: CanisterOptions = {}) { 17 | const { service, certifiedService } = createServices({ 18 | options: { 19 | ...options, 20 | canisterId: options.canisterId ?? MAINNET_SNS_WASM_CANISTER_ID, 21 | }, 22 | idlFactory: idlFactorySnsWasm, 23 | certifiedIdlFactory: idlFactoryCertifiedSnsWasm, 24 | }); 25 | 26 | return new SnsWasmCanister(service, certifiedService); 27 | } 28 | 29 | public listSnses = async ({ 30 | certified = true, 31 | }: { 32 | certified?: boolean; 33 | }): Promise => { 34 | const service = certified ? this.certifiedService : this.service; 35 | 36 | const { instances } = await service.list_deployed_snses({}); 37 | return instances; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /packages/canisters/src/ckbtc/types/minter.params.ts: -------------------------------------------------------------------------------- 1 | import type { QueryParams } from "@dfinity/utils"; 2 | import type { Principal } from "@icp-sdk/core/principal"; 3 | import type { CkBtcMinterDid } from "../../declarations"; 4 | 5 | export interface MinterAccount { 6 | owner: Principal; 7 | subaccount?: Uint8Array; 8 | } 9 | 10 | export type MinterParams = Omit & 11 | Partial; 12 | 13 | /** 14 | * Params to get a BTC address. 15 | */ 16 | export type GetBTCAddressParams = MinterParams; 17 | 18 | /** 19 | * Params to update ckBTC balance after a bitcoin transfer. 20 | */ 21 | export type UpdateBalanceParams = MinterParams; 22 | 23 | /** 24 | * Params to convert ckBTC to Bitcoin. 25 | */ 26 | export type RetrieveBtcParams = CkBtcMinterDid.RetrieveBtcArgs & 27 | Omit; 28 | 29 | /** 30 | * Params to estimate the fee of the Bitcoin network. 31 | */ 32 | export type EstimateWithdrawalFeeParams = QueryParams & { 33 | amount: bigint | undefined; 34 | }; 35 | 36 | /** 37 | * Params to retrieve the status of all BTC withdrawals for an account. 38 | */ 39 | export type RetrieveBtcStatusV2ByAccountParams = QueryParams & { 40 | account?: MinterAccount; 41 | }; 42 | 43 | /** 44 | * Params to get the known utxos. 45 | */ 46 | export type GetKnownUtxosParams = QueryParams & MinterParams; 47 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/mocks/sns.mock.ts: -------------------------------------------------------------------------------- 1 | import { Principal } from "@icp-sdk/core/principal"; 2 | import type { SnsRootDid, SnsSwapDid } from "../../declarations"; 3 | 4 | export const rootCanisterIdMock: Principal = Principal.fromText( 5 | "pin7y-wyaaa-aaaaa-aacpa-cai", 6 | ); 7 | 8 | export const ledgerCanisterIdMock: Principal = Principal.fromText( 9 | "ktxdj-qiaaa-aaaaa-aacqa-cai", 10 | ); 11 | 12 | export const governanceCanisterIdMock: Principal = Principal.fromText( 13 | "ppmzm-3aaaa-aaaaa-aacpq-cai", 14 | ); 15 | 16 | export const swapCanisterIdMock: Principal = Principal.fromText( 17 | "kuwf5-5qaaa-aaaaa-aacqq-cai", 18 | ); 19 | 20 | export const indexCanisterIdMock: Principal = Principal.fromText( 21 | "qjdve-lqaaa-aaaaa-aaaeq-cai", 22 | ); 23 | 24 | export const snsMock: SnsRootDid.ListSnsCanistersResponse = { 25 | root: [rootCanisterIdMock], 26 | ledger: [ledgerCanisterIdMock], 27 | governance: [governanceCanisterIdMock], 28 | swap: [swapCanisterIdMock], 29 | index: [indexCanisterIdMock], 30 | dapps: [], 31 | archives: [], 32 | extensions: [], 33 | }; 34 | 35 | export const saleTicketMock: SnsSwapDid.Ticket = { 36 | creation_time: 1n, 37 | ticket_id: 2n, 38 | account: [ 39 | { 40 | owner: [Principal.fromText("aaaaa-aa")], 41 | subaccount: [], 42 | }, 43 | ], 44 | amount_icp_e8s: 3n, 45 | }; 46 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/mocks/governance.mock.ts: -------------------------------------------------------------------------------- 1 | import { arrayOfNumberToUint8Array } from "@dfinity/utils"; 2 | import type { SnsGovernanceDid } from "../../declarations"; 3 | 4 | export const neuronIdMock: SnsGovernanceDid.NeuronId = { 5 | id: arrayOfNumberToUint8Array([1]), 6 | }; 7 | 8 | export const neuronMock = { 9 | id: [neuronIdMock], 10 | } as SnsGovernanceDid.Neuron; 11 | 12 | export const neuronsMock: SnsGovernanceDid.Neuron[] = [neuronMock]; 13 | 14 | export const metadataMock: SnsGovernanceDid.GetMetadataResponse = { 15 | url: ["https://my.url/"], 16 | logo: [], 17 | name: ["My project"], 18 | description: ["Web3 for the win"], 19 | }; 20 | 21 | export const proposalIdMock = { id: BigInt(12) }; 22 | 23 | export const proposalMock = { 24 | id: [proposalIdMock], 25 | } as SnsGovernanceDid.ProposalData; 26 | 27 | export const proposalsMock: SnsGovernanceDid.ProposalData[] = [proposalMock]; 28 | 29 | export const topicMock: SnsGovernanceDid.Topic = { 30 | ApplicationBusinessLogic: null, 31 | }; 32 | 33 | export const topicInfoMock: SnsGovernanceDid.TopicInfo = { 34 | custom_functions: [], 35 | description: ["Description"], 36 | is_critical: [false], 37 | name: ["Name"], 38 | native_functions: [], 39 | topic: [topicMock], 40 | extension_operations: [], 41 | }; 42 | 43 | export const topicsMock: SnsGovernanceDid.TopicInfo[] = [topicInfoMock]; 44 | -------------------------------------------------------------------------------- /packages/utils/src/utils/debounce.utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates a debounced version of the provided function. 3 | * 4 | * The debounced function postpones its execution until after a certain amount of time 5 | * has elapsed since the last time it was invoked. This is useful for limiting the rate 6 | * at which a function is called (e.g. in response to user input or events). 7 | * 8 | * @param {Function} func - The function to debounce. It will only be called after no new calls happen within the specified timeout. 9 | * @param {number} [timeout=300] - The debounce delay in milliseconds. Defaults to 300ms if not provided or invalid. 10 | * @returns {(args: unknown[]) => void} A debounced version of the original function. 11 | */ 12 | // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type, local-rules/prefer-object-params 13 | export const debounce = (func: Function, timeout?: number) => { 14 | let timer: NodeJS.Timer | undefined; 15 | 16 | return (...args: unknown[]) => { 17 | const next = () => func(...args); 18 | 19 | if (timer) { 20 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 21 | // @ts-ignore TypeScript global and window confusion even if we are using @types/node 22 | clearTimeout(timer); 23 | } 24 | 25 | timer = setTimeout( 26 | next, 27 | timeout !== undefined && timeout > 0 ? timeout : 300, 28 | ); 29 | }; 30 | }; 31 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/nns/genesis_token.did: -------------------------------------------------------------------------------- 1 | // Generated from IC repo commit d2a13f0 (2025-12-03 tags: release-2025-12-04_03-28-base) 'rs/nns/gtc/canister/gtc.did' by import-candid 2 | 3 | type AccountState = record { 4 | authenticated_principal_id : opt principal; 5 | successfully_transferred_neurons : vec TransferredNeuron; 6 | is_whitelisted_for_forwarding : bool; 7 | has_donated : bool; 8 | failed_transferred_neurons : vec TransferredNeuron; 9 | neuron_ids : vec NeuronId; 10 | has_claimed : bool; 11 | has_forwarded : bool; 12 | icpts : nat32; 13 | }; 14 | 15 | type NeuronId = record { 16 | id : nat64 17 | }; 18 | 19 | type Result = variant { 20 | Ok : vec NeuronId; 21 | Err : text 22 | }; 23 | 24 | type Result_1 = variant { 25 | Ok; 26 | Err : text 27 | }; 28 | 29 | type Result_2 = variant { 30 | Ok : AccountState; 31 | Err : text 32 | }; 33 | 34 | type TransferredNeuron = record { 35 | error : opt text; 36 | timestamp_seconds : nat64; 37 | neuron_id : opt NeuronId; 38 | }; 39 | 40 | service : { 41 | balance : (text) -> (nat32) query; 42 | claim_neurons : (text) -> (Result); 43 | donate_account : (text) -> (Result_1); 44 | forward_whitelisted_unclaimed_accounts : (null) -> (Result_1); 45 | get_account : (text) -> (Result_2) query; 46 | get_build_metadata : () -> (text) query; 47 | len : () -> (nat16) query; 48 | total : () -> (nat32) query; 49 | } 50 | -------------------------------------------------------------------------------- /packages/nns-proto/proto/base_types_pb.d.ts: -------------------------------------------------------------------------------- 1 | // package: ic_base_types.pb.v1 2 | // file: proto/base_types.proto 3 | 4 | import * as jspb from "google-protobuf"; 5 | import * as google_protobuf_descriptor_pb from "google-protobuf/google/protobuf/descriptor_pb"; 6 | 7 | export class PrincipalId extends jspb.Message { 8 | getSerializedId(): Uint8Array | string; 9 | getSerializedId_asU8(): Uint8Array; 10 | getSerializedId_asB64(): string; 11 | setSerializedId(value: Uint8Array | string): void; 12 | 13 | serializeBinary(): Uint8Array; 14 | toObject(includeInstance?: boolean): PrincipalId.AsObject; 15 | static toObject(includeInstance: boolean, msg: PrincipalId): PrincipalId.AsObject; 16 | static extensions: {[key: number]: jspb.ExtensionFieldInfo}; 17 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; 18 | static serializeBinaryToWriter(message: PrincipalId, writer: jspb.BinaryWriter): void; 19 | static deserializeBinary(bytes: Uint8Array): PrincipalId; 20 | static deserializeBinaryFromReader(message: PrincipalId, reader: jspb.BinaryReader): PrincipalId; 21 | } 22 | 23 | export namespace PrincipalId { 24 | export type AsObject = { 25 | serializedId: Uint8Array | string, 26 | } 27 | } 28 | 29 | export const tuiSignedMessage: jspb.ExtensionFieldInfo; 30 | 31 | export const tuiSignedDisplayQ22021: jspb.ExtensionFieldInfo; 32 | 33 | -------------------------------------------------------------------------------- /packages/canisters/src/ic-management/utils/ic-management.utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { mockSnapshotId, mockSnapshotIdHex } from "../ic-management.mock"; 2 | import { 3 | decodeSnapshotId, 4 | encodeSnapshotId, 5 | mapSnapshotId, 6 | } from "./ic-management.utils"; 7 | 8 | describe("ic-management.utils", () => { 9 | it("should correctly encode a snapshot ID with encodeSnapshotId", () => { 10 | const encoded = encodeSnapshotId(mockSnapshotId); 11 | 12 | expect(encoded).toBe(mockSnapshotIdHex); 13 | }); 14 | 15 | it("should correctly decode a snapshot ID with decodeSnapshotId", () => { 16 | const decoded = decodeSnapshotId(mockSnapshotIdHex); 17 | 18 | expect(decoded).toEqual(mockSnapshotId); 19 | }); 20 | 21 | it("should encodeSnapshotId and decodeSnapshotId", () => { 22 | const encoded = encodeSnapshotId(mockSnapshotId); 23 | const decoded = decodeSnapshotId(encoded); 24 | 25 | expect(decoded).toEqual(mockSnapshotId); 26 | }); 27 | 28 | describe("mapSnapshotId", () => { 29 | it("should map a Uint8Array snapshot ID without changes", () => { 30 | const result = mapSnapshotId(mockSnapshotId); 31 | 32 | expect(result).toEqual(mockSnapshotId); 33 | }); 34 | 35 | it("should map a string snapshot ID by decoding it", () => { 36 | const result = mapSnapshotId(mockSnapshotIdHex); 37 | 38 | expect(result).toEqual(mockSnapshotId); 39 | }); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/root.canister.ts: -------------------------------------------------------------------------------- 1 | import { Canister, createServices } from "@dfinity/utils"; 2 | import { 3 | type SnsRootDid, 4 | type SnsRootService, 5 | idlFactoryCertifiedSnsRoot, 6 | idlFactorySnsRoot, 7 | } from "../declarations"; 8 | import type { SnsCanisterOptions } from "./types/canister.options"; 9 | 10 | export class SnsRootCanister extends Canister { 11 | static create(options: SnsCanisterOptions) { 12 | const { service, certifiedService, canisterId } = 13 | createServices({ 14 | options, 15 | idlFactory: idlFactorySnsRoot, 16 | certifiedIdlFactory: idlFactoryCertifiedSnsRoot, 17 | }); 18 | 19 | return new SnsRootCanister(canisterId, service, certifiedService); 20 | } 21 | 22 | /** 23 | * List the canisters that are part of the Sns. 24 | * 25 | * Source code: https://github.com/dfinity/ic/blob/master/rs/sns/root/src/lib.rs 26 | * 27 | * @param {Object} params 28 | * @param {boolean} [params.certified=true] - Query or update calls 29 | * 30 | * @returns {ListSnsCanistersResponse} - A list of canisters ('root' | 'governance' | 'ledger' | 'dapps' | 'swap' | 'archives') 31 | */ 32 | listSnsCanisters = ({ 33 | certified = true, 34 | }: { 35 | certified?: boolean; 36 | }): Promise => 37 | this.caller({ certified }).list_sns_canisters({}); 38 | } 39 | -------------------------------------------------------------------------------- /scripts/publish-npm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Reference: NPM RRFC --if-needed https://github.com/npm/rfcs/issues/466 4 | 5 | function publish_npm() { 6 | local lib=$1 7 | local org=$2 8 | 9 | LOCAL_SHASUM=$(npm --silent pack -w packages/"$lib" --json | jq '.[] | .shasum' | sed -r 's/^"|"$//g') 10 | 11 | NPM_TARBALL=$(npm show "@$org/$lib" dist.tarball 2>/dev/null || true) 12 | 13 | if [ -z "$NPM_TARBALL" ]; then 14 | echo "@"$org"/$lib not found on NPM. Publishing new package..." 15 | npm publish --workspace="packages/$lib" --provenance --access public 16 | else 17 | NPM_SHASUM=$(curl -s "$NPM_TARBALL" 2>&1 | shasum | cut -f1 -d' ') 18 | 19 | if [ "$LOCAL_SHASUM" == "$NPM_SHASUM" ]; then 20 | echo "No changes in @$org/$lib need to be published to NPM." 21 | else 22 | npm publish --workspace=packages/"$lib" --provenance --access public 23 | fi 24 | fi 25 | } 26 | 27 | # Tips: libs use by other libs first 28 | DFINITY_LIBS=utils,zod-schemas,nns-proto 29 | 30 | for lib in $(echo $DFINITY_LIBS | sed "s/,/ /g"); do 31 | publish_npm "$lib" "dfinity" 32 | done 33 | 34 | ICP_SDK=canisters 35 | 36 | for lib in $(echo $ICP_SDK | sed "s/,/ /g"); do 37 | publish_npm "$lib" "icp-sdk" 38 | done 39 | 40 | DFINITY_LEGACY_LIBS=cmc,ic-management,ckbtc,cketh,ledger-icrc,ledger-icp,nns,sns 41 | 42 | for lib in $(echo $DFINITY_LEGACY_LIBS | sed "s/,/ /g"); do 43 | publish_npm "$lib" "dfinity" 44 | done 45 | -------------------------------------------------------------------------------- /packages/nns-proto/proto/nervous_system.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ic_nervous_system.pb.v1; 4 | 5 | import "base_types.proto"; 6 | 7 | message Duration { 8 | optional uint64 seconds = 1; 9 | } 10 | 11 | message GlobalTimeOfDay { 12 | optional uint64 seconds_after_utc_midnight = 1; 13 | } 14 | 15 | message Tokens { 16 | optional uint64 e8s = 1; 17 | } 18 | 19 | message Image { 20 | // A data URI of a png. E.g. 21 | // data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAD0lEQVQIHQEEAPv/AAD/DwIRAQ8HgT3GAAAAAElFTkSuQmCC 22 | // ^ 1 pixel containing the color #00FF0F. 23 | optional string base64_encoding = 1; 24 | } 25 | 26 | message Percentage { 27 | optional uint64 basis_points = 1; 28 | } 29 | 30 | // A Canister that will be transferred to an SNS. 31 | message Canister { 32 | // The id of the canister. 33 | optional ic_base_types.pb.v1.PrincipalId id = 1; 34 | } 35 | 36 | // Represents a set of countries. To be used in country-specific configurations, 37 | // e.g., to restrict the geography of an SNS swap. 38 | message Countries { 39 | // ISO 3166-1 alpha-2 codes 40 | repeated string iso_codes = 1; 41 | } 42 | 43 | // Features: 44 | // 1. Sign ('+' is optional). 45 | // 2. Smallest positive value: 10^-28. 46 | // 3. 96 bits of significand. 47 | // 4. Decimal point character: '.' (dot/period). 48 | message Decimal { 49 | // E.g. "3.14". 50 | optional string human_readable = 1; 51 | } 52 | -------------------------------------------------------------------------------- /docs/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://typedoc-plugin-markdown.org/schema.json", 3 | "entryPoints": [ 4 | "../packages/canisters/src/assets/index.ts", 5 | "../packages/canisters/src/ckbtc/index.ts", 6 | "../packages/canisters/src/cketh/index.ts", 7 | "../packages/canisters/src/cmc/index.ts", 8 | "../packages/canisters/src/ic-management/index.ts", 9 | "../packages/canisters/src/ledger/icp/index.ts", 10 | "../packages/canisters/src/ledger/icrc/index.ts", 11 | "../packages/canisters/src/nns/index.ts", 12 | "../packages/canisters/src/sns/index.ts" 13 | ], 14 | "tsconfig": "./tsconfig.json", 15 | "readme": "none", 16 | "out": "src/content/tmp", 17 | "plugin": [ 18 | "typedoc-plugin-markdown", 19 | "typedoc-plugin-frontmatter", 20 | "@dfinity/typedoc-plugin-icp-docs" 21 | ], 22 | "outputs": [ 23 | { "name": "markdown", "path": "src/content/tmp" }, 24 | { "name": "icp-docs", "path": "src/content/docs" } 25 | ], 26 | "projectDocuments": ["../CHANGELOG.md"], 27 | "entryFileName": "index", 28 | "hidePageTitle": true, 29 | "hideBreadcrumbs": true, 30 | "hidePageHeader": true, 31 | "frontmatterGlobals": { 32 | "editUrl": false, 33 | "next": true, 34 | "prev": true 35 | }, 36 | "readmeFrontmatter": { 37 | "editUrl": false, 38 | "next": true, 39 | "prev": true 40 | }, 41 | "indexFrontmatter": {}, 42 | "frontmatterNamingConvention": "camelCase" 43 | } 44 | -------------------------------------------------------------------------------- /packages/utils/src/utils/crypto.utils.ts: -------------------------------------------------------------------------------- 1 | import { uint8ArrayToHexString } from "./arrays.utils"; 2 | import { jsonReplacer } from "./json.utils"; 3 | 4 | /** 5 | * Generates a SHA-256 hash from the given object. 6 | * 7 | * The object is first stringified using a custom `jsonReplacer`, then 8 | * hashed using the SubtleCrypto API. The resulting hash is returned as a hex string. 9 | * 10 | * @template T - The type of the input object. 11 | * @param {T} params - The object to hash. 12 | * @returns {Promise} A promise that resolves to the hex string of the SHA-256 hash. 13 | */ 14 | export const hashObject = async ( 15 | params: T, 16 | ): Promise => { 17 | const jsonString = JSON.stringify(params, jsonReplacer); 18 | 19 | return await hashText(jsonString); 20 | }; 21 | 22 | /** 23 | * Generates a SHA-256 hash from a plain text string. 24 | * 25 | * The string is UTF-8 encoded and hashed using the SubtleCrypto API. 26 | * The resulting hash is returned as a hexadecimal string. 27 | * 28 | * @param {string} text - The text to hash. 29 | * @returns {Promise} A promise that resolves to the hex string of the SHA-256 hash. 30 | */ 31 | export const hashText = async (text: string): Promise => { 32 | const dataBuffer = new TextEncoder().encode(text); 33 | const hashBuffer = await crypto.subtle.digest("SHA-256", dataBuffer); 34 | 35 | return uint8ArrayToHexString(new Uint8Array(hashBuffer)); 36 | }; 37 | -------------------------------------------------------------------------------- /scripts/refreshNeuron.mjs: -------------------------------------------------------------------------------- 1 | import { HttpAgent } from "@icp-sdk/core/agent"; 2 | import { Principal } from "@icp-sdk/core/principal"; 3 | import pkg from "../packages/nns/dist/index.cjs.js"; 4 | const { GovernanceCanister } = pkg; 5 | 6 | const refreshNeuron = async (neuronId, shouldFetchRootKey) => { 7 | try { 8 | const agent = await HttpAgent.create({ 9 | fetch, 10 | host: "https://ic0.app", 11 | // host: "https://nnsdapp.dfinity.network", 12 | shouldFetchRootKey, 13 | }); 14 | const canister = GovernanceCanister.create({ 15 | agent, 16 | canisterId: Principal.fromText("rrkah-fqaaa-aaaaa-aaaaq-cai"), 17 | }); 18 | await canister.claimOrRefreshNeuron({ 19 | neuronId: BigInt(neuronId), 20 | by: { NeuronIdOrSubaccount: {} }, 21 | }); 22 | console.log("neuron refreshed"); 23 | } catch (e) { 24 | console.error(e); 25 | } 26 | }; 27 | 28 | // Neuron from User with problems 29 | refreshNeuron("7966791617963362468"); 30 | const a = { 31 | command: [ 32 | { 33 | Error: { 34 | error_message: 35 | "Account does not have enough funds to refresh a neuron. Please make sure that account has at least 100000000 e8s (was 6299993 e8s)", 36 | error_type: 14, 37 | }, 38 | }, 39 | ], 40 | }; 41 | // Mainnet neuron 42 | // refreshNeuron("13291324902841494691"); 43 | // Testnet neuron less than 1ICP stake 44 | // refreshNeuron("4766351651311749354", true); 45 | -------------------------------------------------------------------------------- /packages/canisters/src/nns/genesis_token.canister.ts: -------------------------------------------------------------------------------- 1 | import { createServices, type CanisterOptions } from "@dfinity/utils"; 2 | import type { ActorSubclass } from "@icp-sdk/core/agent"; 3 | import { 4 | idlFactoryCertifiedNnsGenesisToken, 5 | idlFactoryNnsGenesisToken, 6 | type NnsGenesisTokenService, 7 | } from "../declarations"; 8 | import { MAINNET_GENESIS_TOKEN_CANISTER_ID } from "./constants/canister_ids"; 9 | import type { NeuronId } from "./types/common"; 10 | 11 | export class NnsGenesisTokenCanister { 12 | private constructor( 13 | private readonly service: ActorSubclass, 14 | ) {} 15 | 16 | public static create(options: CanisterOptions = {}) { 17 | const { service } = createServices({ 18 | options: { 19 | ...options, 20 | canisterId: options.canisterId ?? MAINNET_GENESIS_TOKEN_CANISTER_ID, 21 | }, 22 | idlFactory: idlFactoryNnsGenesisToken, 23 | certifiedIdlFactory: idlFactoryCertifiedNnsGenesisToken, 24 | }); 25 | 26 | return new NnsGenesisTokenCanister(service); 27 | } 28 | 29 | public claimNeurons = async ({ 30 | hexPubKey, 31 | }: { 32 | hexPubKey: string; 33 | }): Promise => { 34 | const response = await this.service.claim_neurons(hexPubKey); 35 | if ("Ok" in response) { 36 | return response.Ok.map((neuronId) => neuronId.id); 37 | } 38 | 39 | throw new Error(response.Err); 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /packages/nns-proto/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dfinity/nns-proto", 3 | "version": "2.0.4", 4 | "description": "The protobuf source used by nns-js to support hardware wallets.", 5 | "license": "Apache-2.0", 6 | "main": "dist/cjs/index.cjs.js", 7 | "module": "dist/index.js", 8 | "types": "dist/index.d.ts", 9 | "files": [ 10 | "dist", 11 | "README.md", 12 | "LICENSE" 13 | ], 14 | "scripts": { 15 | "rmdir": "node ../../scripts/rmdir.mjs", 16 | "ts-declaration": "tsc --emitDeclarationOnly --outDir dist", 17 | "build": "npm run rmdir && mkdir -p dist && cp -R proto dist && node esbuild.mjs && npm run ts-declaration", 18 | "prepack": "npm run build", 19 | "test": "" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "git+https://github.com/dfinity/icp-js-canisters.git", 24 | "directory": "packages/nns-proto" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/dfinity/icp-js-canisters" 28 | }, 29 | "keywords": [ 30 | "internet computer", 31 | "internet-computer", 32 | "ic", 33 | "dfinity", 34 | "dfx", 35 | "canister", 36 | "candid", 37 | "motoko", 38 | "javascript", 39 | "typescript", 40 | "blockchain", 41 | "crypto", 42 | "nns", 43 | "network nervous system", 44 | "network-nervous-system" 45 | ], 46 | "dependencies": { 47 | "google-protobuf": "^3.21.2" 48 | }, 49 | "devDependencies": { 50 | "@types/google-protobuf": "^3.15.6" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/nft-ledger.canister.ts: -------------------------------------------------------------------------------- 1 | import { Canister, createServices, type QueryParams } from "@dfinity/utils"; 2 | import { 3 | idlFactoryCertifiedIcrcNftLedger, 4 | idlFactoryIcrcNftLedger, 5 | type IcrcNftLedgerService, 6 | } from "../../declarations"; 7 | import type { IcrcLedgerCanisterOptions } from "./types/canister.options"; 8 | import type { IcrcTokenMetadataResponse } from "./types/ledger.responses"; 9 | 10 | export class IcrcNftLedgerCanister extends Canister { 11 | static create(options: IcrcLedgerCanisterOptions) { 12 | const { service, certifiedService, canisterId } = 13 | createServices({ 14 | options, 15 | idlFactory: idlFactoryIcrcNftLedger, 16 | certifiedIdlFactory: idlFactoryCertifiedIcrcNftLedger, 17 | }); 18 | 19 | return new IcrcNftLedgerCanister(canisterId, service, certifiedService); 20 | } 21 | 22 | /** 23 | * The collection metadata. 24 | * 25 | * @link https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-7/ICRC-7.md#icrc7_collection_metadata 26 | * 27 | * @param {QueryParams} params The parameters to get the metadata of the collection. 28 | * @returns {Promise} The metadata as a list of metadata type and its value. 29 | */ 30 | collectionMetadata = ( 31 | params: QueryParams, 32 | ): Promise => 33 | this.caller(params).icrc7_collection_metadata(); 34 | } 35 | -------------------------------------------------------------------------------- /packages/canisters/src/nns/genesis_token.canister.spec.ts: -------------------------------------------------------------------------------- 1 | import type { ActorSubclass } from "@icp-sdk/core/agent"; 2 | import { mock } from "vitest-mock-extended"; 3 | import type { NnsGenesisTokenService } from "../declarations"; 4 | import { NnsGenesisTokenCanister } from "./genesis_token.canister"; 5 | 6 | describe("GenesisTokenCanister", () => { 7 | it("claimNeurons returns a list of neuron ids", async () => { 8 | const response = { 9 | Ok: [ 10 | { 11 | id: BigInt(1), 12 | }, 13 | { 14 | id: BigInt(2), 15 | }, 16 | ], 17 | }; 18 | const service = mock>(); 19 | service.claim_neurons.mockResolvedValue(response); 20 | 21 | const gtc = NnsGenesisTokenCanister.create({ serviceOverride: service }); 22 | const res = await gtc.claimNeurons({ 23 | hexPubKey: "", 24 | }); 25 | 26 | expect(res).toEqual([BigInt(1), BigInt(2)]); 27 | }); 28 | 29 | it("claimNeurons throws errors", async () => { 30 | const response = { 31 | Err: "An error occurred.", 32 | }; 33 | const service = mock>(); 34 | service.claim_neurons.mockResolvedValue(response); 35 | 36 | const gtc = NnsGenesisTokenCanister.create({ serviceOverride: service }); 37 | const call = async () => { 38 | await gtc.claimNeurons({ hexPubKey: "" }); 39 | }; 40 | 41 | await expect(call).rejects.toThrowError("An error occurred."); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /packages/ledger-icrc/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | IcrcIndexDid, 3 | IcrcLedgerDid, 4 | } from "@icp-sdk/canisters/ledger/icrc"; 5 | 6 | export type Icrc3Value = IcrcLedgerDid.ICRC3Value; 7 | export type IcrcAllowance = IcrcLedgerDid.Allowance; 8 | export type IcrcApproveError = IcrcLedgerDid.ApproveError; 9 | export type IcrcBlockIndex = IcrcLedgerDid.BlockIndex; 10 | export type IcrcCandidAccount = IcrcLedgerDid.Account; 11 | export type IcrcGetBlocksArgs = IcrcLedgerDid.GetBlocksArgs; 12 | export type IcrcGetBlocksResult = IcrcLedgerDid.GetBlocksResult; 13 | export type IcrcStandardRecord = IcrcLedgerDid.StandardRecord; 14 | export type IcrcSubaccount = IcrcLedgerDid.Subaccount; 15 | export type IcrcTimestamp = IcrcLedgerDid.Timestamp; 16 | export type IcrcTokens = IcrcLedgerDid.Tokens; 17 | export type IcrcTransferArg = IcrcLedgerDid.TransferArg; 18 | export type IcrcTransferFromError = IcrcLedgerDid.TransferFromError; 19 | export type IcrcTransferVariantError = IcrcLedgerDid.TransferError; 20 | export type IcrcValue = IcrcLedgerDid.Value; 21 | 22 | export type IcrcIndexNgGetTransactions = IcrcIndexDid.GetTransactions; 23 | export type IcrcIndexNgTransaction = IcrcIndexDid.Transaction; 24 | export type IcrcIndexNgTransactionWithId = IcrcIndexDid.TransactionWithId; 25 | export type IcrcNgStatus = IcrcIndexDid.Status; 26 | export type IcrcNgTxId = IcrcIndexDid.BlockIndex; 27 | 28 | /** 29 | * @deprecated Use "@icp-sdk/canisters/ledger/icrc" directly instead 30 | */ 31 | export * from "@icp-sdk/canisters/ledger/icrc"; 32 | -------------------------------------------------------------------------------- /packages/ckbtc/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { BitcoinDid, CkBtcMinterDid } from "@icp-sdk/canisters/ckbtc"; 2 | 3 | export type block_hash = BitcoinDid.block_hash; 4 | export type block_height = BitcoinDid.block_height; 5 | export type get_utxos_response = BitcoinDid.get_utxos_response; 6 | export type outpoint = BitcoinDid.outpoint; 7 | export type satoshi = BitcoinDid.satoshi; 8 | export type utxo = BitcoinDid.utxo; 9 | 10 | export type Account = CkBtcMinterDid.Account; 11 | export type MinterInfo = CkBtcMinterDid.MinterInfo; 12 | export type PendingUtxo = CkBtcMinterDid.PendingUtxo; 13 | export type ReimbursedDeposit = CkBtcMinterDid.ReimbursedDeposit; 14 | export type ReimbursementRequest = CkBtcMinterDid.ReimbursementRequest; 15 | export type RetrieveBtcOk = CkBtcMinterDid.RetrieveBtcOk; 16 | export type RetrieveBtcStatus = CkBtcMinterDid.RetrieveBtcStatus; 17 | export type RetrieveBtcStatusV2 = CkBtcMinterDid.RetrieveBtcStatusV2; 18 | export type Utxo = CkBtcMinterDid.Utxo; 19 | export type UtxoStatus = CkBtcMinterDid.UtxoStatus; 20 | export type WithdrawalAccount = CkBtcMinterDid.Account; 21 | 22 | /** 23 | * @deprecated Use "@icp-sdk/canisters/ckbtc" directly instead 24 | */ 25 | export * from "@icp-sdk/canisters/ckbtc"; 26 | 27 | /** 28 | * Legacy re-export for backward compatibility. 29 | * @deprecated Use "@icp-sdk/canisters/ckbtc" directly instead 30 | */ 31 | export { 32 | CkBtcMinterCanister as CkBTCMinterCanister, 33 | type CkBtcCanisterOptions as CkBTCCanisterOptions, 34 | } from "@icp-sdk/canisters/ckbtc"; 35 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/utils/error.utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { isMethodNotSupportedError } from "./error.utils"; 2 | 3 | describe("error utils", () => { 4 | describe("isMethodNotSupportedError", () => { 5 | it("returns true for method is not supported for update", () => { 6 | const errorMessage = `"Call was rejected: 7 | Request ID: 3a6ef904b35fd19721c95c3df2b0b00b8abefba7f0ad188f5c472809b772c914 8 | Reject code: 3 9 | Reject text: Canister 75ffu-oaaaa-aaaaa-aabbq-cai has no update method 'get_auto_finalization_status'"`; 10 | const err = new Error(errorMessage); 11 | 12 | expect(isMethodNotSupportedError(err)).toBeTruthy(); 13 | }); 14 | 15 | it("returns true for method is not supported for query", () => { 16 | const errorMessage = `Call failed: 17 | Canister: s55qq-oqaaa-aaaaa-aaakq-cai 18 | Method: get_auto_finalization_status (query) 19 | "Status": "rejected" 20 | "Code": "DestinationInvalid" 21 | "Message": "IC0302: Canister s55qq-oqaaa-aaaaa-aaakq-cai has no query method 'get_auto_finalization_status'"`; 22 | const err = new Error(errorMessage); 23 | 24 | expect(isMethodNotSupportedError(err)).toBeTruthy(); 25 | }); 26 | 27 | it("returns false for other errors and non errors", () => { 28 | expect(isMethodNotSupportedError(new Error("another error"))).toBeFalsy(); 29 | expect(isMethodNotSupportedError(undefined)).toBeFalsy(); 30 | expect(isMethodNotSupportedError({})).toBeFalsy(); 31 | }); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /packages/sns/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dfinity/sns", 3 | "version": "7.0.0", 4 | "description": "A library for interfacing with a Service Nervous System (SNS) project.", 5 | "license": "Apache-2.0", 6 | "type": "module", 7 | "main": "./dist/index.mjs", 8 | "module": "./dist/index.js", 9 | "types": "./dist/index.d.ts", 10 | "exports": { 11 | ".": { 12 | "import": { 13 | "types": "./dist/index.d.ts", 14 | "default": "./dist/index.js" 15 | }, 16 | "require": { 17 | "types": "./dist/index.d.ts", 18 | "default": "./dist/index.mjs" 19 | } 20 | } 21 | }, 22 | "files": [ 23 | "dist", 24 | "README.md", 25 | "LICENSE" 26 | ], 27 | "scripts": { 28 | "rmdir": "node ../../scripts/rmdir.mjs", 29 | "ts-declaration": "tsc --emitDeclarationOnly --outDir dist", 30 | "build": "npm run rmdir && mkdir -p dist && node esbuild.mjs && npm run ts-declaration", 31 | "prepack": "npm run build", 32 | "test": "vitest" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/dfinity/icp-js-canisters.git", 37 | "directory": "packages/sns" 38 | }, 39 | "bugs": { 40 | "url": "https://github.com/dfinity/icp-js-canisters" 41 | }, 42 | "keywords": [ 43 | "internet computer", 44 | "internet-computer", 45 | "ic", 46 | "dfinity", 47 | "service nervous system", 48 | "service-nervous-system", 49 | "sns" 50 | ], 51 | "peerDependencies": { 52 | "@icp-sdk/canisters": "^3" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /packages/ic-management/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dfinity/ic-management", 3 | "version": "10.0.0", 4 | "description": "A library for interfacing with the IC management canister.", 5 | "license": "Apache-2.0", 6 | "type": "module", 7 | "main": "./dist/index.mjs", 8 | "module": "./dist/index.js", 9 | "types": "./dist/index.d.ts", 10 | "exports": { 11 | ".": { 12 | "import": { 13 | "types": "./dist/index.d.ts", 14 | "default": "./dist/index.js" 15 | }, 16 | "require": { 17 | "types": "./dist/index.d.ts", 18 | "default": "./dist/index.mjs" 19 | } 20 | } 21 | }, 22 | "files": [ 23 | "dist", 24 | "README.md", 25 | "LICENSE" 26 | ], 27 | "scripts": { 28 | "rmdir": "node ../../scripts/rmdir.mjs", 29 | "ts-declaration": "tsc --emitDeclarationOnly --outDir dist", 30 | "build": "npm run rmdir && mkdir -p dist && node esbuild.mjs && npm run ts-declaration", 31 | "prepack": "npm run build", 32 | "test": "vitest" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/dfinity/icp-js-canisters.git", 37 | "directory": "packages/ic-management" 38 | }, 39 | "bugs": { 40 | "url": "https://github.com/dfinity/icp-js-canisters" 41 | }, 42 | "keywords": [ 43 | "internet computer", 44 | "internet-computer", 45 | "ic", 46 | "dfinity" 47 | ], 48 | "homepage": "https://github.com/dfinity/icp-js-canisters#readme", 49 | "peerDependencies": { 50 | "@icp-sdk/canisters": "^3" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/cmc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dfinity/cmc", 3 | "version": "9.0.0", 4 | "description": "A library for interfacing with the cycle minting canister.", 5 | "license": "Apache-2.0", 6 | "type": "module", 7 | "main": "./dist/index.mjs", 8 | "module": "./dist/index.js", 9 | "types": "./dist/index.d.ts", 10 | "exports": { 11 | ".": { 12 | "import": { 13 | "types": "./dist/index.d.ts", 14 | "default": "./dist/index.js" 15 | }, 16 | "require": { 17 | "types": "./dist/index.d.ts", 18 | "default": "./dist/index.mjs" 19 | } 20 | } 21 | }, 22 | "files": [ 23 | "dist", 24 | "README.md", 25 | "LICENSE" 26 | ], 27 | "scripts": { 28 | "rmdir": "node ../../scripts/rmdir.mjs", 29 | "ts-declaration": "tsc --emitDeclarationOnly --outDir dist", 30 | "build": "npm run rmdir && mkdir -p dist && node esbuild.mjs && npm run ts-declaration", 31 | "prepack": "npm run build", 32 | "test": "vitest" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/dfinity/icp-js-canisters.git", 37 | "directory": "packages/cmc" 38 | }, 39 | "bugs": { 40 | "url": "https://github.com/dfinity/icp-js-canisters" 41 | }, 42 | "keywords": [ 43 | "internet computer", 44 | "internet-computer", 45 | "ic", 46 | "dfinity", 47 | "cmc", 48 | "cycle minting canister" 49 | ], 50 | "homepage": "https://github.com/dfinity/icp-js-canisters#readme", 51 | "peerDependencies": { 52 | "@icp-sdk/canisters": "^3" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /packages/utils/src/types/query-and-update.params.ts: -------------------------------------------------------------------------------- 1 | import type { Identity } from "@icp-sdk/core/agent"; 2 | 3 | export type QueryAndUpdateIdentity = Identity | undefined | null; 4 | 5 | export interface QueryAndUpdateRequestParams { 6 | certified: boolean; 7 | identity: QueryAndUpdateIdentity; 8 | } 9 | 10 | export type QueryAndUpdateRequest = ( 11 | options: QueryAndUpdateRequestParams, 12 | ) => Promise; 13 | 14 | export type QueryAndUpdateOnResponse = (options: { 15 | certified: boolean; 16 | response: R; 17 | }) => void; 18 | 19 | export interface QueryAndUpdateOnErrorOptions { 20 | error: E; 21 | // The identity used for the request 22 | identity: QueryAndUpdateIdentity; 23 | } 24 | 25 | type QueryAndUpdateOnError = ( 26 | options: QueryAndUpdateOnErrorOptions, 27 | ) => void; 28 | 29 | export type QueryAndUpdateOnQueryError = QueryAndUpdateOnError; 30 | 31 | export type QueryAndUpdateOnUpdateError = QueryAndUpdateOnError; 32 | 33 | export type QueryAndUpdateStrategy = "query_and_update" | "query" | "update"; 34 | 35 | export type QueryAndUpdatePromiseResolution = "all_settled" | "race"; 36 | 37 | export interface QueryAndUpdateParams { 38 | request: QueryAndUpdateRequest; 39 | onLoad: QueryAndUpdateOnResponse; 40 | onQueryError?: QueryAndUpdateOnQueryError; 41 | onUpdateError?: QueryAndUpdateOnUpdateError; 42 | strategy?: QueryAndUpdateStrategy; 43 | identity: QueryAndUpdateIdentity; 44 | resolution?: QueryAndUpdatePromiseResolution; 45 | } 46 | -------------------------------------------------------------------------------- /packages/ckbtc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dfinity/ckbtc", 3 | "version": "7.0.0", 4 | "description": "A library for interfacing with ckBTC.", 5 | "license": "Apache-2.0", 6 | "type": "module", 7 | "main": "./dist/index.mjs", 8 | "module": "./dist/index.js", 9 | "types": "./dist/index.d.ts", 10 | "exports": { 11 | ".": { 12 | "import": { 13 | "types": "./dist/index.d.ts", 14 | "default": "./dist/index.js" 15 | }, 16 | "require": { 17 | "types": "./dist/index.d.ts", 18 | "default": "./dist/index.mjs" 19 | } 20 | } 21 | }, 22 | "files": [ 23 | "dist", 24 | "README.md", 25 | "LICENSE" 26 | ], 27 | "scripts": { 28 | "rmdir": "node ../../scripts/rmdir.mjs", 29 | "ts-declaration": "tsc --emitDeclarationOnly --outDir dist", 30 | "build": "npm run rmdir && mkdir -p dist && node esbuild.mjs && npm run ts-declaration", 31 | "prepack": "npm run build", 32 | "test": "vitest" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/dfinity/icp-js-canisters.git", 37 | "directory": "packages/ckbtc" 38 | }, 39 | "bugs": { 40 | "url": "https://github.com/dfinity/icp-js-canisters" 41 | }, 42 | "keywords": [ 43 | "internet computer", 44 | "internet-computer", 45 | "ic", 46 | "dfinity", 47 | "ckbtc", 48 | "bitcoin", 49 | "minter", 50 | "token" 51 | ], 52 | "homepage": "https://github.com/dfinity/icp-js-canisters#readme", 53 | "peerDependencies": { 54 | "@icp-sdk/canisters": "^3" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/cketh/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dfinity/cketh", 3 | "version": "7.0.0", 4 | "description": "A library for interfacing with ckETH.", 5 | "license": "Apache-2.0", 6 | "type": "module", 7 | "main": "./dist/index.mjs", 8 | "module": "./dist/index.js", 9 | "types": "./dist/index.d.ts", 10 | "exports": { 11 | ".": { 12 | "import": { 13 | "types": "./dist/index.d.ts", 14 | "default": "./dist/index.js" 15 | }, 16 | "require": { 17 | "types": "./dist/index.d.ts", 18 | "default": "./dist/index.mjs" 19 | } 20 | } 21 | }, 22 | "files": [ 23 | "dist", 24 | "README.md", 25 | "LICENSE" 26 | ], 27 | "scripts": { 28 | "rmdir": "node ../../scripts/rmdir.mjs", 29 | "ts-declaration": "tsc --emitDeclarationOnly --outDir dist", 30 | "build": "npm run rmdir && mkdir -p dist && node esbuild.mjs && npm run ts-declaration", 31 | "prepack": "npm run build", 32 | "test": "vitest" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/dfinity/icp-js-canisters.git", 37 | "directory": "packages/cketh" 38 | }, 39 | "bugs": { 40 | "url": "https://github.com/dfinity/icp-js-canisters" 41 | }, 42 | "keywords": [ 43 | "internet computer", 44 | "internet-computer", 45 | "ic", 46 | "dfinity", 47 | "ckETH", 48 | "Ethereum", 49 | "minter", 50 | "token" 51 | ], 52 | "homepage": "https://github.com/dfinity/icp-js-canisters#readme", 53 | "peerDependencies": { 54 | "@icp-sdk/canisters": "^3" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/canisters/src/sns/enums/swap.enums.ts: -------------------------------------------------------------------------------- 1 | // Source: https://github.com/dfinity/ic/blob/master/rs/sns/swap/gen/ic_sns_swap.pb.v1.rs - Lifecycle 2 | export enum SnsSwapLifecycle { 3 | Unspecified = 0, 4 | Pending = 1, 5 | Open = 2, 6 | Committed = 3, 7 | Aborted = 4, 8 | Adopted = 5, 9 | } 10 | 11 | // Source: https://gitlab.com/dfinity-lab/public/ic/-/blob/5936d73770dbd16dab9b23379367a8bd5513fb88/rs/sns/swap/proto/ic_sns_swap/pb/v1/swap.proto#L887 12 | export enum GetOpenTicketErrorType { 13 | TYPE_UNSPECIFIED = 0, 14 | TYPE_SALE_NOT_OPEN = 1, 15 | TYPE_SALE_CLOSED = 2, 16 | } 17 | 18 | // Source: https://gitlab.com/dfinity-lab/public/ic/-/blob/5936d73770dbd16dab9b23379367a8bd5513fb88/rs/sns/swap/proto/ic_sns_swap/pb/v1/swap.proto#L928 19 | export enum NewSaleTicketResponseErrorType { 20 | TYPE_UNSPECIFIED = 0, 21 | TYPE_SALE_NOT_OPEN = 1, 22 | TYPE_SALE_CLOSED = 2, 23 | // There is already an open ticket associated with the caller. 24 | // 25 | // When this is the `error_type`, then the field existing_ticket 26 | // is set and contains the ticket itself. 27 | TYPE_TICKET_EXISTS = 3, 28 | // The amount sent by the user is not within the Sale parameters. 29 | // 30 | // When this is the `error_type`, then the field invalid_user_amount 31 | // is set and describes minimum and maximum amounts. 32 | TYPE_INVALID_USER_AMOUNT = 4, 33 | // The specified subaccount is not a valid subaccount (length != 32 bytes). 34 | TYPE_INVALID_SUBACCOUNT = 5, 35 | // The specified principal is forbidden from creating tickets. 36 | TYPE_INVALID_PRINCIPAL = 6, 37 | } 38 | -------------------------------------------------------------------------------- /packages/canisters/src/assets/readable/readable-bytes.spec.ts: -------------------------------------------------------------------------------- 1 | import { ReadableBytes } from "./readable-bytes"; 2 | 3 | const transparentPixelGif = [ 4 | 71, 73, 70, 56, 57, 97, 1, 0, 1, 0, 0, 0, 0, 33, 249, 4, 1, 0, 0, 0, 0, 44, 0, 5 | 0, 0, 0, 1, 0, 1, 0, 0, 2, 1, 0, 0, 6 | ]; 7 | 8 | describe("ReadableBytes", () => { 9 | test("ReadableBytes from Uint8Array", async () => { 10 | const uint8Array = Uint8Array.from(transparentPixelGif); 11 | const fileName = "transparent_pixel.gif"; 12 | const readable = new ReadableBytes( 13 | fileName, 14 | Uint8Array.from(transparentPixelGif), 15 | ); 16 | 17 | expect(readable.fileName).toEqual(fileName); 18 | expect(readable.contentType).toEqual("image/gif"); 19 | expect(readable).toHaveLength(uint8Array.length); 20 | 21 | await readable.open(); 22 | 23 | await expect(readable.slice(16, 24)).resolves.toEqual( 24 | uint8Array.slice(16, 24), 25 | ); 26 | 27 | await readable.close(); 28 | }); 29 | 30 | test("ReadableBytes from number[]", async () => { 31 | const fileName = "transparent_pixel.gif"; 32 | const readable = new ReadableBytes(fileName, transparentPixelGif); 33 | 34 | expect(readable.fileName).toEqual(fileName); 35 | expect(readable.contentType).toEqual("image/gif"); 36 | expect(readable).toHaveLength(transparentPixelGif.length); 37 | 38 | await readable.open(); 39 | 40 | await expect(readable.slice(16, 24)).resolves.toEqual( 41 | Uint8Array.from(transparentPixelGif.slice(16, 24)), 42 | ); 43 | 44 | await readable.close(); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /packages/ledger-icrc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dfinity/ledger-icrc", 3 | "version": "7.0.0", 4 | "description": "A library for interfacing with ICRC ledgers on the Internet Computer.", 5 | "license": "Apache-2.0", 6 | "type": "module", 7 | "main": "./dist/index.mjs", 8 | "module": "./dist/index.js", 9 | "types": "./dist/index.d.ts", 10 | "exports": { 11 | ".": { 12 | "import": { 13 | "types": "./dist/index.d.ts", 14 | "default": "./dist/index.js" 15 | }, 16 | "require": { 17 | "types": "./dist/index.d.ts", 18 | "default": "./dist/index.mjs" 19 | } 20 | } 21 | }, 22 | "files": [ 23 | "dist", 24 | "README.md", 25 | "LICENSE" 26 | ], 27 | "scripts": { 28 | "rmdir": "node ../../scripts/rmdir.mjs", 29 | "ts-declaration": "tsc --emitDeclarationOnly --outDir dist", 30 | "build": "npm run rmdir && mkdir -p dist && node esbuild.mjs && npm run ts-declaration", 31 | "prepack": "npm run build", 32 | "test": "vitest" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/dfinity/icp-js-canisters.git", 37 | "directory": "packages/ledger-icrc" 38 | }, 39 | "bugs": { 40 | "url": "https://github.com/dfinity/icp-js-canisters" 41 | }, 42 | "keywords": [ 43 | "internet computer", 44 | "internet-computer", 45 | "ic", 46 | "dfinity", 47 | "Ledger", 48 | "ICRC-1 ledger", 49 | "token" 50 | ], 51 | "homepage": "https://github.com/dfinity/icp-js-canisters#readme", 52 | "peerDependencies": { 53 | "@icp-sdk/canisters": "^3" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/ledger-icp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dfinity/ledger-icp", 3 | "version": "9.0.0", 4 | "description": "A library for interfacing with the ICP ledger on the Internet Computer.", 5 | "license": "Apache-2.0", 6 | "type": "module", 7 | "main": "./dist/index.mjs", 8 | "module": "./dist/index.js", 9 | "types": "./dist/index.d.ts", 10 | "exports": { 11 | ".": { 12 | "import": { 13 | "types": "./dist/index.d.ts", 14 | "default": "./dist/index.js" 15 | }, 16 | "require": { 17 | "types": "./dist/index.d.ts", 18 | "default": "./dist/index.mjs" 19 | } 20 | } 21 | }, 22 | "files": [ 23 | "dist", 24 | "README.md", 25 | "LICENSE" 26 | ], 27 | "scripts": { 28 | "rmdir": "node ../../scripts/rmdir.mjs", 29 | "ts-declaration": "tsc --emitDeclarationOnly --outDir dist", 30 | "build": "npm run rmdir && mkdir -p dist && node esbuild.mjs && npm run ts-declaration", 31 | "prepack": "npm run build", 32 | "test": "vitest" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/dfinity/icp-js-canisters.git", 37 | "directory": "packages/ledger-icp" 38 | }, 39 | "bugs": { 40 | "url": "https://github.com/dfinity/icp-js-canisters" 41 | }, 42 | "keywords": [ 43 | "internet computer", 44 | "internet-computer", 45 | "ic", 46 | "dfinity", 47 | "Ledger", 48 | "ICP ledger", 49 | "token", 50 | "icp" 51 | ], 52 | "homepage": "https://github.com/dfinity/icp-js-canisters#readme", 53 | "peerDependencies": { 54 | "@icp-sdk/canisters": "^3" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /docs/src/content/docs/quick-start.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Quick Start 3 | description: A quick start guide to using the @icp-sdk/canisters package. 4 | next: 5 | label: ckBTC Module 6 | --- 7 | 8 | This guide offers simple examples of how to use the `@icp-sdk/canisters` package. 9 | 10 | ### ckETH 11 | 12 | Here's an example on how to use the ckETH module through its sub-entry: 13 | 14 | ```typescript 15 | import { CkEthMinterCanister } from "@icp-sdk/canisters/cketh"; 16 | import { createAgent } from "@dfinity/utils"; 17 | 18 | const agent = await createAgent({ 19 | identity, 20 | host: HOST, 21 | }); 22 | 23 | const { getSmartContractAddress } = CkEthMinterCanister.create({ 24 | agent, 25 | canisterId: MY_CKETH_MINTER_CANISTER_ID, 26 | }); 27 | 28 | const address = await getSmartContractAddress({}); 29 | ``` 30 | 31 | ### ICP and ICRC Ledgers 32 | 33 | Similarly, the ICP and ICRC ledgers can be used as follows, with the slight difference that their imports are nested under a common parent. 34 | 35 | ```typescript 36 | import { IcrcLedgerCanister } from "@icp-sdk/canisters/ledger/icrc"; 37 | import { createAgent } from "@dfinity/utils"; 38 | 39 | const agent = await createAgent({ 40 | identity, 41 | host: HOST, 42 | }); 43 | 44 | const { metadata } = IcrcLedgerCanister.create({ 45 | agent, 46 | canisterId: MY_LEDGER_CANISTER_ID, 47 | }); 48 | 49 | const data = await metadata({}); 50 | ``` 51 | 52 | ## Next Steps 53 | 54 | In the sidebar, navigate the **Modules** section to find the documentation for each module that the `@icp-sdk/canisters` package provides. Use the search bar to find specific items across all modules. 55 | -------------------------------------------------------------------------------- /packages/cketh/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | CkEthMinterDid, 3 | CkEthOrchestratorDid, 4 | } from "@icp-sdk/canisters/cketh"; 5 | 6 | export type Eip1559TransactionPrice = CkEthMinterDid.Eip1559TransactionPrice; 7 | export type EthTransaction = CkEthMinterDid.EthTransaction; 8 | export type MinterInfo = CkEthMinterDid.MinterInfo; 9 | export type RetrieveErc20Request = CkEthMinterDid.RetrieveErc20Request; 10 | export type RetrieveEthRequest = CkEthMinterDid.RetrieveEthRequest; 11 | export type RetrieveEthStatus = CkEthMinterDid.RetrieveEthStatus; 12 | export type Subaccount = CkEthMinterDid.Subaccount; 13 | export type TxFinalizedStatus = CkEthMinterDid.TxFinalizedStatus; 14 | 15 | export type CyclesManagement = CkEthOrchestratorDid.CyclesManagement; 16 | export type Erc20Contract = CkEthOrchestratorDid.Erc20Contract; 17 | export type ManagedCanisterStatus = CkEthOrchestratorDid.ManagedCanisterStatus; 18 | export type ManagedCanisters = CkEthOrchestratorDid.ManagedCanisters; 19 | export type OrchestratorInfo = CkEthOrchestratorDid.OrchestratorInfo; 20 | 21 | /** 22 | * @deprecated Use "@icp-sdk/canisters/cketh" directly instead 23 | */ 24 | export * from "@icp-sdk/canisters/cketh"; 25 | 26 | /** 27 | * Legacy re-export for backward compatibility. 28 | * @deprecated Use "@icp-sdk/canisters/cketh" directly instead 29 | */ 30 | export { 31 | CkEthMinterCanister as CkETHMinterCanister, 32 | CkEthOrchestratorCanister as CkETHOrchestratorCanister, 33 | type CkEthMinterCanisterOptions as CkETHMinterCanisterOptions, 34 | type CkEthOrchestratorCanisterOptions as CkETHOrchestratorCanisterOptions, 35 | } from "@icp-sdk/canisters/cketh"; 36 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/converters/converters.spec.ts: -------------------------------------------------------------------------------- 1 | import { toNullable } from "@dfinity/utils"; 2 | import { mockPrincipal } from "../mocks/ledger.mock"; 3 | import { fromCandidAccount, toCandidAccount } from "./converters"; 4 | 5 | describe("converters", () => { 6 | const owner = mockPrincipal; 7 | const subaccount = new Uint8Array([1, 2, 3]); 8 | 9 | describe("fromCandidAccount", () => { 10 | it("should transform a Candid Account to IcrcAccount correctly", () => { 11 | expect( 12 | fromCandidAccount({ 13 | owner, 14 | subaccount: toNullable(subaccount), 15 | }), 16 | ).toStrictEqual({ 17 | owner, 18 | subaccount, 19 | }); 20 | }); 21 | 22 | it("should handle nullish subaccount", () => { 23 | expect( 24 | fromCandidAccount({ 25 | owner, 26 | subaccount: toNullable(), 27 | }), 28 | ).toStrictEqual({ 29 | owner, 30 | }); 31 | }); 32 | }); 33 | 34 | describe("toCandidAccount", () => { 35 | it("should transform an IcrcAccount to a Candid Account correctly", () => { 36 | expect( 37 | toCandidAccount({ 38 | owner, 39 | subaccount, 40 | }), 41 | ).toStrictEqual({ 42 | owner, 43 | subaccount: toNullable(subaccount), 44 | }); 45 | }); 46 | 47 | it("should handle nullish subaccount", () => { 48 | expect( 49 | toCandidAccount({ 50 | owner, 51 | }), 52 | ).toStrictEqual({ 53 | owner, 54 | subaccount: toNullable(), 55 | }); 56 | }); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /packages/utils/src/utils/nullish.utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | isEmptyString, 3 | isNullish, 4 | nonNullish, 5 | notEmptyString, 6 | } from "./nullish.utils"; 7 | 8 | describe("nullish-utils", () => { 9 | describe("isNullish", () => { 10 | it("should determine nullable", () => { 11 | expect(isNullish(null)).toBeTruthy(); 12 | expect(isNullish(undefined)).toBeTruthy(); 13 | expect(isNullish(0)).toBeFalsy(); 14 | expect(isNullish(1)).toBeFalsy(); 15 | expect(isNullish("")).toBeFalsy(); 16 | expect(isNullish([])).toBeFalsy(); 17 | }); 18 | }); 19 | 20 | describe("nonNullish", () => { 21 | it("should determine not nullable", () => { 22 | expect(nonNullish(null)).toBeFalsy(); 23 | expect(nonNullish(undefined)).toBeFalsy(); 24 | expect(nonNullish(0)).toBeTruthy(); 25 | expect(nonNullish(1)).toBeTruthy(); 26 | expect(nonNullish("")).toBeTruthy(); 27 | expect(nonNullish([])).toBeTruthy(); 28 | }); 29 | }); 30 | 31 | describe("notEmptyString", () => { 32 | it("should determine not empty", () => { 33 | expect(notEmptyString(null)).toBeFalsy(); 34 | expect(notEmptyString(undefined)).toBeFalsy(); 35 | expect(notEmptyString("")).toBeFalsy(); 36 | expect(notEmptyString("test")).toBeTruthy(); 37 | }); 38 | }); 39 | 40 | describe("isEmptyString", () => { 41 | it("should determine empty", () => { 42 | expect(isEmptyString(null)).toBeTruthy(); 43 | expect(isEmptyString(undefined)).toBeTruthy(); 44 | expect(isEmptyString("")).toBeTruthy(); 45 | expect(isEmptyString("test")).toBeFalsy(); 46 | }); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/nft-ledger.canister.spec.ts: -------------------------------------------------------------------------------- 1 | import type { ActorSubclass } from "@icp-sdk/core/agent"; 2 | import { mock } from "vitest-mock-extended"; 3 | import type { IcrcNftLedgerService } from "../../declarations"; 4 | import { 5 | ledgerCanisterIdMock, 6 | tokenMetadataResponseMock, 7 | } from "./mocks/ledger.mock"; 8 | import { IcrcNftLedgerCanister } from "./nft-ledger.canister"; 9 | 10 | describe("NFT Ledger canister", () => { 11 | describe("collectionMetadata", () => { 12 | it("should return the collection metadata", async () => { 13 | const service = mock>(); 14 | service.icrc7_collection_metadata.mockResolvedValue( 15 | tokenMetadataResponseMock, 16 | ); 17 | 18 | const canister = IcrcNftLedgerCanister.create({ 19 | canisterId: ledgerCanisterIdMock, 20 | certifiedServiceOverride: service, 21 | }); 22 | 23 | const res = await canister.collectionMetadata({}); 24 | 25 | expect(res).toEqual(tokenMetadataResponseMock); 26 | }); 27 | 28 | it("should fail when the canister call fails", async () => { 29 | const mockError = new Error("Canister call failed"); 30 | const service = mock>(); 31 | service.icrc7_collection_metadata.mockRejectedValue(mockError); 32 | 33 | const canister = IcrcNftLedgerCanister.create({ 34 | canisterId: ledgerCanisterIdMock, 35 | certifiedServiceOverride: service, 36 | }); 37 | 38 | await expect(canister.collectionMetadata({})).rejects.toThrowError( 39 | mockError, 40 | ); 41 | }); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { default as config } from "@dfinity/eslint-config-oisy-wallet"; 2 | import { default as vitestConfig } from "@dfinity/eslint-config-oisy-wallet/vitest"; 3 | 4 | export default [ 5 | ...config, 6 | ...vitestConfig, 7 | { 8 | rules: { 9 | // This rule is disabled because the candid declarations folder is referenced by the canisters and indexes 10 | // using relative parent paths. Resolving this would require either restructuring the folder 11 | // (which impacts the build pipeline) or setting up path aliases (which requires configuration). 12 | // Since neither is a current priority, the rule remains off. 13 | "import/no-relative-parent-imports": "off", 14 | 15 | // We use no-restricted-imports in apps to prevent imports from the legacy @dfinity/... libraries 16 | // which are developed in this repo. 17 | "no-restricted-imports": "off", 18 | }, 19 | }, 20 | { 21 | ignores: [ 22 | "**/dist/", 23 | "**/candid/", 24 | "*.did.js", 25 | "*_pb.d.ts", 26 | "scripts", 27 | "**/vitest.config.ts", 28 | "**/esbuild.mjs", 29 | "packages/nns-proto/proto", 30 | "eslint-local-rules.cjs", 31 | ], 32 | }, 33 | { 34 | ignores: [ 35 | "packages/**/*.js", 36 | "packages/**/*.mjs", 37 | "packages/**/*.d.ts", 38 | 39 | "packages/index.js", 40 | "packages/index.mjs", 41 | "packages/index.d.ts", 42 | 43 | "!packages/*.js", 44 | "!packages/*.mjs", 45 | "!packages/*.d.ts", 46 | 47 | "!packages/**/src/**/*.js", 48 | "!packages/**/src/**/*.mjs", 49 | "!packages/**/src/**/*.d.ts", 50 | ], 51 | }, 52 | ]; 53 | -------------------------------------------------------------------------------- /packages/canisters/src/ckbtc/types/bitcoin.params.ts: -------------------------------------------------------------------------------- 1 | import { nonNullish, toNullable, type QueryParams } from "@dfinity/utils"; 2 | import type { BitcoinDid } from "../../declarations"; 3 | 4 | export type BitcoinNetwork = "testnet" | "mainnet" | "regtest"; 5 | 6 | const mapBitcoinNetwork: Record = { 7 | mainnet: { mainnet: null }, 8 | testnet: { testnet: null }, 9 | regtest: { regtest: null }, 10 | }; 11 | 12 | export type GetUtxosParams = Omit< 13 | BitcoinDid.get_utxos_request, 14 | "network" | "filter" 15 | > & { 16 | network: BitcoinNetwork; 17 | filter?: { page: Uint8Array } | { minConfirmations: number }; 18 | } & Omit; 19 | 20 | export const toGetUtxosParams = ({ 21 | network, 22 | filter, 23 | ...rest 24 | }: GetUtxosParams): BitcoinDid.get_utxos_request => ({ 25 | filter: nonNullish(filter) 26 | ? toNullable( 27 | "minConfirmations" in filter 28 | ? { min_confirmations: filter.minConfirmations } 29 | : { page: filter.page }, 30 | ) 31 | : toNullable(), 32 | network: network === "testnet" ? { testnet: null } : { mainnet: null }, 33 | ...rest, 34 | }); 35 | 36 | export type GetBalanceParams = Omit< 37 | BitcoinDid.get_balance_request, 38 | "network" | "min_confirmations" 39 | > & { 40 | network: BitcoinNetwork; 41 | minConfirmations?: number; 42 | } & Omit; 43 | 44 | export const toGetBalanceParams = ({ 45 | network, 46 | minConfirmations, 47 | ...rest 48 | }: GetBalanceParams): BitcoinDid.get_balance_request => ({ 49 | min_confirmations: toNullable(minConfirmations), 50 | network: mapBitcoinNetwork[network], 51 | ...rest, 52 | }); 53 | -------------------------------------------------------------------------------- /packages/nns/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dfinity/nns", 3 | "version": "12.0.0", 4 | "description": "A library for interfacing with the Internet Computer's Network Nervous System.", 5 | "license": "Apache-2.0", 6 | "type": "module", 7 | "main": "./dist/index.mjs", 8 | "module": "./dist/index.js", 9 | "types": "./dist/index.d.ts", 10 | "exports": { 11 | ".": { 12 | "import": { 13 | "types": "./dist/index.d.ts", 14 | "default": "./dist/index.js" 15 | }, 16 | "require": { 17 | "types": "./dist/index.d.ts", 18 | "default": "./dist/index.mjs" 19 | } 20 | } 21 | }, 22 | "files": [ 23 | "dist", 24 | "README.md", 25 | "LICENSE" 26 | ], 27 | "scripts": { 28 | "rmdir": "node ../../scripts/rmdir.mjs", 29 | "ts-declaration": "tsc --emitDeclarationOnly --outDir dist", 30 | "build": "npm run rmdir && mkdir -p dist && node esbuild.mjs && npm run ts-declaration", 31 | "prepack": "npm run build", 32 | "test": "vitest" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/dfinity/icp-js-canisters.git", 37 | "directory": "packages/nns" 38 | }, 39 | "bugs": { 40 | "url": "https://github.com/dfinity/icp-js-canisters" 41 | }, 42 | "keywords": [ 43 | "internet computer", 44 | "internet-computer", 45 | "ic", 46 | "dfinity", 47 | "dfx", 48 | "canister", 49 | "candid", 50 | "motoko", 51 | "javascript", 52 | "typescript", 53 | "blockchain", 54 | "crypto", 55 | "nns", 56 | "network nervous system", 57 | "network-nervous-system" 58 | ], 59 | "peerDependencies": { 60 | "@icp-sdk/canisters": "^3" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/utils/src/utils/debounce.utils.spec.ts: -------------------------------------------------------------------------------- 1 | import type { MockedFunction } from "vitest"; 2 | import { debounce } from "./debounce.utils"; 3 | 4 | describe("debounce-utils", () => { 5 | let callback: MockedFunction<() => void>; 6 | 7 | beforeAll(() => 8 | vi.spyOn(console, "error").mockImplementation(() => undefined), 9 | ); 10 | 11 | beforeEach(() => { 12 | vi.useFakeTimers(); 13 | vi.spyOn(global, "setTimeout"); 14 | callback = vi.fn(); 15 | }); 16 | 17 | afterEach(() => vi.useRealTimers()); 18 | 19 | afterAll(() => vi.resetAllMocks()); 20 | 21 | it("should debounce function with timeout", () => { 22 | const testDebounce = debounce(callback, 100); 23 | 24 | testDebounce(); 25 | testDebounce(); 26 | testDebounce(); 27 | 28 | expect(setTimeout).toHaveBeenCalledTimes(3); 29 | expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 100); 30 | expect(callback).not.toHaveBeenCalled(); 31 | 32 | vi.runAllTimers(); 33 | 34 | expect(callback).toHaveBeenCalledOnce(); 35 | }); 36 | 37 | it("should debounce one function call", () => { 38 | debounce(callback)(); 39 | 40 | expect(callback).not.toHaveBeenCalled(); 41 | 42 | vi.runAllTimers(); 43 | 44 | expect(callback).toHaveBeenCalled(); 45 | expect(callback).toHaveBeenCalledOnce(); 46 | }); 47 | 48 | it("should debounce multiple functions call", () => { 49 | const anotherCallback = vi.fn(); 50 | 51 | const test = debounce(anotherCallback); 52 | 53 | test(); 54 | 55 | test(); 56 | 57 | test(); 58 | 59 | vi.runAllTimers(); 60 | 61 | expect(anotherCallback).toHaveBeenCalled(); 62 | expect(anotherCallback).toHaveBeenCalledOnce(); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /docs/src/content/docs/installation.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installation 3 | description: How to install the @icp-sdk/canisters package. 4 | --- 5 | 6 | import { Code, Tabs, TabItem } from "@astrojs/starlight/components"; 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | You might need to install the peer dependencies of `@icp-sdk/canisters` manually: 16 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | You might need to install the peer dependencies of `@icp-sdk/canisters` manually: 29 | 33 | 34 | 35 | 36 | 37 | ## CDN 38 | 39 | We do not recommend using the CDN distribution of the `@icp-sdk/canisters` package for **production** applications. 40 | 41 | It can constitute a security risk, because the CDN can potentially serve a different IC mainnet [root key](https://internetcomputer.org/docs/references/ic-interface-spec/#root-of-trust). 42 | -------------------------------------------------------------------------------- /packages/cmc/README.md: -------------------------------------------------------------------------------- 1 | # cmc-js 2 | 3 | A library for interfacing with the cycle minting canister. 4 | 5 | [![npm version](https://img.shields.io/npm/v/@dfinity/cmc.svg?logo=npm)](https://www.npmjs.com/package/@dfinity/cmc) [![GitHub license](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 6 | 7 | > [!TIP] 8 | > Still using `@dfinity/cmc`? Upgrade to [`@icp-sdk/canisters/cmc`](https://js.icp.build/canisters/latest/upgrading/v1/)! 9 | 10 | ## Table of contents 11 | 12 | - [Installation](#installation) 13 | - [Usage](#usage) 14 | - [Features](#features) 15 | 16 | ## Installation 17 | 18 | You can use `cmc-js` by installing it in your project. 19 | 20 | ```bash 21 | npm i @dfinity/cmc 22 | ``` 23 | 24 | The bundle needs peer dependencies, be sure that following resources are available in your project as well. 25 | 26 | ```bash 27 | npm i @icp-sdk/core @dfinity/utils 28 | ``` 29 | 30 | ## Usage 31 | 32 | The features are available through the class `CmcCanister`. It has to be instantiated with the canister ID of the cycles minting canister. On `mainnet`, its ID is `rkp4c-7iaaa-aaaaa-aaaca-cai`. 33 | 34 | e.g. querying the current Icp to cycles conversion rate. 35 | 36 | ```ts 37 | import { CmcCanister } from "@dfinity/cmc"; 38 | import { createAgent } from "@dfinity/utils"; 39 | 40 | const agent = await createAgent({ 41 | identity, 42 | host: HOST, 43 | }); 44 | 45 | const { getIcpToCyclesConversionRate } = CmcCanister.create({ 46 | agent, 47 | canisterId: CYCLES_MINTING_CANISTER_ID, 48 | }); 49 | 50 | const rate = await getIcpToCyclesConversionRate(); 51 | ``` 52 | 53 | ## Documentation 54 | 55 | You can find the API docs [here](https://js.icp.build/canisters/latest/api/cmc/). 56 | -------------------------------------------------------------------------------- /packages/ledger-icp/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { IcpIndexDid, IcpLedgerDid } from "@icp-sdk/canisters/ledger/icp"; 2 | 3 | export type Icrc1Account = IcpLedgerDid.Account; 4 | export type Icrc1ApproveError = IcpLedgerDid.ApproveError; 5 | export type Icrc1BlockIndex = IcpLedgerDid.Icrc1BlockIndex; 6 | export type Icrc1SubAccount = IcpLedgerDid.SubAccount; 7 | export type Icrc1Timestamp = IcpLedgerDid.Icrc1Timestamp; 8 | export type Icrc1Tokens = IcpLedgerDid.Icrc1Tokens; 9 | export type Icrc1TransferError = IcpLedgerDid.Icrc1TransferError; 10 | export type Icrc1TransferResult = IcpLedgerDid.Icrc1TransferResult; 11 | export type Icrc2ApproveResult = IcpLedgerDid.ApproveResult; 12 | export type Icrc2TransferFromError = IcpLedgerDid.TransferFromError; 13 | export type Icrc2TransferFromResult = IcpLedgerDid.TransferFromResult; 14 | export type Value = IcpLedgerDid.Value; 15 | 16 | export type GetAccountIdentifierTransactionsResponse = 17 | IcpIndexDid.GetAccountIdentifierTransactionsResponse; 18 | export type TransactionWithId = IcpIndexDid.TransactionWithId; 19 | export type Transaction = IcpIndexDid.Transaction; 20 | export type Operation = IcpIndexDid.Operation; 21 | export type Tokens = IcpIndexDid.Tokens; 22 | export type TimeStamp = IcpIndexDid.TimeStamp; 23 | 24 | /** 25 | * @deprecated Use "@icp-sdk/canisters/ledger/icp" directly instead 26 | */ 27 | export * from "@icp-sdk/canisters/ledger/icp"; 28 | 29 | /** 30 | * Legacy re-export for backward compatibility. 31 | * @deprecated Use "@icp-sdk/canisters/ledger/icp" directly instead 32 | */ 33 | export { 34 | IcpIndexCanister as IndexCanister, 35 | IcpLedgerCanister as LedgerCanister, 36 | type IcpLedgerCanisterOptions as LedgerCanisterOptions, 37 | } from "@icp-sdk/canisters/ledger/icp"; 38 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/_types.ts: -------------------------------------------------------------------------------- 1 | import type * as AssetsDid from "./assets/assets_assetstorage"; 2 | import type * as BitcoinDid from "./ckbtc/bitcoin"; 3 | import type * as CkBtcMinterDid from "./ckbtc/minter"; 4 | import type * as CkEthMinterDid from "./cketh/minter"; 5 | import type * as CkEthOrchestratorDid from "./cketh/orchestrator"; 6 | import type * as CmcDid from "./cmc/cmc"; 7 | import type * as IcManagementDid from "./ic-management/ic-management"; 8 | import type * as IcpIndexDid from "./ledger-icp/index"; 9 | import type * as IcpLedgerDid from "./ledger-icp/ledger"; 10 | import type * as IcrcIndexDid from "./ledger-icrc/icrc_index"; 11 | import type * as IcrcLedgerDid from "./ledger-icrc/icrc_ledger"; 12 | import type * as IcrcNftLedgerDid from "./ledger-icrc/icrc_nft-ledger"; 13 | import type * as NnsGenesisTokenDid from "./nns/genesis_token"; 14 | import type * as NnsGovernanceDid from "./nns/governance"; 15 | import type * as NnsGovernanceTestDid from "./nns/governance_test"; 16 | import type * as SnsWasmDid from "./nns/sns_wasm"; 17 | import type * as SnsGovernanceDid from "./sns/governance"; 18 | import type * as SnsGovernanceTestDid from "./sns/governance_test"; 19 | import type * as SnsRootDid from "./sns/root"; 20 | import type * as SnsSwapDid from "./sns/swap"; 21 | 22 | export type { 23 | AssetsDid, 24 | BitcoinDid, 25 | CkBtcMinterDid, 26 | CkEthMinterDid, 27 | CkEthOrchestratorDid, 28 | CmcDid, 29 | IcManagementDid, 30 | IcpIndexDid, 31 | IcpLedgerDid, 32 | IcrcIndexDid, 33 | IcrcLedgerDid, 34 | IcrcNftLedgerDid, 35 | NnsGenesisTokenDid, 36 | NnsGovernanceDid, 37 | NnsGovernanceTestDid, 38 | SnsGovernanceDid, 39 | SnsGovernanceTestDid, 40 | SnsRootDid, 41 | SnsSwapDid, 42 | SnsWasmDid, 43 | }; 44 | -------------------------------------------------------------------------------- /packages/utils/src/utils/actor.utils.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Actor, 3 | type ActorConfig, 4 | type ActorSubclass, 5 | type Agent, 6 | } from "@icp-sdk/core/agent"; 7 | import type { IDL } from "@icp-sdk/core/candid"; 8 | import type { Principal } from "@icp-sdk/core/principal"; 9 | import type { CanisterOptions } from "../types/canister.options"; 10 | import { defaultAgent } from "./agent.utils"; 11 | 12 | type RequiredCanisterOptions = Required< 13 | Pick, "canisterId"> 14 | > & 15 | Omit, "canisterId">; 16 | 17 | export const createServices = ({ 18 | options: { 19 | canisterId, 20 | serviceOverride, 21 | certifiedServiceOverride, 22 | agent: agentOption, 23 | callTransform, 24 | queryTransform, 25 | }, 26 | idlFactory, 27 | certifiedIdlFactory, 28 | }: { 29 | options: RequiredCanisterOptions & 30 | Pick; 31 | idlFactory: IDL.InterfaceFactory; 32 | certifiedIdlFactory: IDL.InterfaceFactory; 33 | }): { 34 | service: ActorSubclass; 35 | certifiedService: ActorSubclass; 36 | agent: Agent; 37 | canisterId: Principal; 38 | } => { 39 | const agent: Agent = agentOption ?? defaultAgent(); 40 | 41 | const service: ActorSubclass = 42 | serviceOverride ?? 43 | Actor.createActor(idlFactory, { 44 | agent, 45 | canisterId, 46 | callTransform, 47 | queryTransform, 48 | }); 49 | 50 | const certifiedService: ActorSubclass = 51 | certifiedServiceOverride ?? 52 | Actor.createActor(certifiedIdlFactory, { 53 | agent, 54 | canisterId, 55 | callTransform, 56 | queryTransform, 57 | }); 58 | 59 | return { service, certifiedService, agent, canisterId }; 60 | }; 61 | -------------------------------------------------------------------------------- /packages/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dfinity/utils", 3 | "version": "4.0.2", 4 | "description": "A collection of utilities and constants for NNS/SNS projects.", 5 | "license": "Apache-2.0", 6 | "type": "module", 7 | "main": "./dist/index.mjs", 8 | "module": "./dist/index.js", 9 | "types": "./dist/index.d.ts", 10 | "exports": { 11 | ".": { 12 | "import": { 13 | "types": "./dist/index.d.ts", 14 | "default": "./dist/index.js" 15 | }, 16 | "require": { 17 | "types": "./dist/index.d.ts", 18 | "default": "./dist/index.mjs" 19 | } 20 | } 21 | }, 22 | "files": [ 23 | "dist", 24 | "README.md", 25 | "LICENSE" 26 | ], 27 | "scripts": { 28 | "rmdir": "node ../../scripts/rmdir.mjs", 29 | "ts-declaration": "tsc --emitDeclarationOnly --outDir dist", 30 | "build": "npm run rmdir && mkdir -p dist && node esbuild.mjs && npm run ts-declaration", 31 | "prepack": "npm run build", 32 | "test": "vitest" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/dfinity/icp-js-canisters.git", 37 | "directory": "packages/utils" 38 | }, 39 | "bugs": { 40 | "url": "https://github.com/dfinity/icp-js-canisters" 41 | }, 42 | "keywords": [ 43 | "internet computer", 44 | "internet-computer", 45 | "ic", 46 | "dfinity", 47 | "dfx", 48 | "canister", 49 | "candid", 50 | "motoko", 51 | "javascript", 52 | "typescript", 53 | "blockchain", 54 | "crypto", 55 | "nns", 56 | "network nervous system", 57 | "network-nervous-system", 58 | "sns", 59 | "service nervous system", 60 | "service-nervous-system" 61 | ], 62 | "peerDependencies": { 63 | "@icp-sdk/core": "^4" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /packages/canisters/src/nns/canisters/governance/services.ts: -------------------------------------------------------------------------------- 1 | import { isNullish } from "@dfinity/utils"; 2 | import type { 3 | NnsGovernanceDid, 4 | NnsGovernanceService, 5 | } from "../../../declarations"; 6 | import { GovernanceError } from "../../errors/governance.errors"; 7 | 8 | /** 9 | * Checks a Manage Neuron Response for error and returns successful response data. 10 | * 11 | * @throws {@link GovernanceError} 12 | */ 13 | export const getSuccessfulCommandFromResponse = ( 14 | response: NnsGovernanceDid.ManageNeuronResponse, 15 | ): NnsGovernanceDid.Command_1 => { 16 | const { command } = response; 17 | const [data] = command; 18 | if (isNullish(data)) { 19 | throw new GovernanceError({ 20 | error_message: "Error updating neuron", 21 | error_type: 0, 22 | }); 23 | } 24 | 25 | if ("Error" in data) { 26 | throw new GovernanceError(data.Error); 27 | } 28 | return data; 29 | }; 30 | 31 | /** 32 | * @throws {@link GovernanceError} 33 | */ 34 | export const manageNeuron = async ({ 35 | request, 36 | service, 37 | }: { 38 | request: NnsGovernanceDid.ManageNeuronRequest; 39 | service: NnsGovernanceService; 40 | }): Promise => { 41 | const response = await service.manage_neuron(request); 42 | // We use it only to assert that there are no errors 43 | return getSuccessfulCommandFromResponse(response); 44 | }; 45 | 46 | /** 47 | * @throws {@link GovernanceError} 48 | */ 49 | export const simulateManageNeuron = async ({ 50 | request, 51 | service, 52 | }: { 53 | request: NnsGovernanceDid.ManageNeuronRequest; 54 | service: NnsGovernanceService; 55 | }): Promise => { 56 | const response = await service.simulate_manage_neuron(request); 57 | return getSuccessfulCommandFromResponse(response); 58 | }; 59 | -------------------------------------------------------------------------------- /packages/canisters/src/nns/utils/account_identifier.utils.ts: -------------------------------------------------------------------------------- 1 | import { 2 | arrayOfNumberToUint8Array, 3 | asciiStringToByteArray, 4 | bigEndianCrc32, 5 | hexStringToUint8Array, 6 | uint8ArrayToHexString, 7 | } from "@dfinity/utils"; 8 | import type { Principal } from "@icp-sdk/core/principal"; 9 | import { sha224 } from "@noble/hashes/sha2"; 10 | import type { AccountIdentifierHex } from "../../ledger/icp"; 11 | 12 | // The following functions were originally made available in @dfinity/ledger-icp for domain alignment reasons. 13 | // Since they are only used by @dfinity/nns and potentially the NNS dapp, they have been moved to this package instead. 14 | 15 | export const accountIdentifierToBytes = ( 16 | accountIdentifier: AccountIdentifierHex, 17 | ): Uint8Array => hexStringToUint8Array(accountIdentifier).subarray(4); 18 | 19 | export const accountIdentifierFromBytes = ( 20 | accountIdentifier: Uint8Array, 21 | ): AccountIdentifierHex => uint8ArrayToHexString(accountIdentifier); 22 | 23 | // eslint-disable-next-line local-rules/prefer-object-params 24 | export const principalToAccountIdentifier = ( 25 | principal: Principal, 26 | subAccount?: Uint8Array, 27 | ): string => { 28 | // Hash (sha224) the principal, the subAccount and some padding 29 | const padding = asciiStringToByteArray("\x0Aaccount-id"); 30 | 31 | const shaObj = sha224.create(); 32 | shaObj.update( 33 | arrayOfNumberToUint8Array([ 34 | ...padding, 35 | ...principal.toUint8Array(), 36 | ...(subAccount ?? Array(32).fill(0)), 37 | ]), 38 | ); 39 | const hash = shaObj.digest(); 40 | 41 | // Prepend the checksum of the hash and convert to a hex string 42 | const checksum = bigEndianCrc32(hash); 43 | const bytes = new Uint8Array([...checksum, ...hash]); 44 | return uint8ArrayToHexString(bytes); 45 | }; 46 | -------------------------------------------------------------------------------- /packages/utils/src/utils/nullish.utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if a given argument is null or undefined. 3 | * 4 | * @template T - The type of the argument. 5 | * @param {T | undefined | null} argument - The argument to check. 6 | * @returns {argument is undefined | null} `true` if the argument is null or undefined; otherwise, `false`. 7 | */ 8 | export const isNullish = ( 9 | argument: T | undefined | null, 10 | ): argument is undefined | null => argument === null || argument === undefined; 11 | 12 | /** 13 | * Checks if a given argument is neither null nor undefined. 14 | * 15 | * @template T - The type of the argument. 16 | * @param {T | undefined | null} argument - The argument to check. 17 | * @returns {argument is NonNullable} `true` if the argument is not null or undefined; otherwise, `false`. 18 | */ 19 | export const nonNullish = ( 20 | argument: T | undefined | null, 21 | ): argument is NonNullable => !isNullish(argument); 22 | 23 | /** 24 | * Checks if a given value is not null, not undefined, and not an empty string. 25 | * 26 | * @param {string | undefined | null} value - The value to check. 27 | * @returns {boolean} `true` if the value is not null, not undefined, and not an empty string; otherwise, `false`. 28 | */ 29 | export const notEmptyString = ( 30 | value: string | undefined | null, 31 | ): value is string => nonNullish(value) && value !== ""; 32 | 33 | /** 34 | * Checks if a given value is null, undefined, or an empty string. 35 | * 36 | * @param {string | undefined | null} value - The value to check. 37 | * @returns {value is undefined | null | ""} Type predicate indicating if the value is null, undefined, or an empty string. 38 | */ 39 | export const isEmptyString = ( 40 | value: string | undefined | null, 41 | ): value is undefined | null | "" => !notEmptyString(value); 42 | -------------------------------------------------------------------------------- /packages/zod-schemas/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dfinity/zod-schemas", 3 | "version": "3.0.2", 4 | "description": "A collection of reusable Zod schemas and validators for common data patterns in ICP applications", 5 | "license": "Apache-2.0", 6 | "type": "module", 7 | "main": "./dist/index.mjs", 8 | "module": "./dist/index.js", 9 | "types": "./dist/index.d.ts", 10 | "exports": { 11 | ".": { 12 | "import": { 13 | "types": "./dist/index.d.ts", 14 | "default": "./dist/index.js" 15 | }, 16 | "require": { 17 | "types": "./dist/index.d.ts", 18 | "default": "./dist/index.mjs" 19 | } 20 | } 21 | }, 22 | "files": [ 23 | "dist", 24 | "README.md", 25 | "LICENSE" 26 | ], 27 | "scripts": { 28 | "rmdir": "node ../../scripts/rmdir.mjs", 29 | "ts-declaration": "tsc --emitDeclarationOnly --outDir dist", 30 | "build": "npm run rmdir && mkdir -p dist && node esbuild.mjs && npm run ts-declaration", 31 | "prepack": "npm run build", 32 | "test": "vitest" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/dfinity/icp-js-canisters.git", 37 | "directory": "packages/zod-schemas" 38 | }, 39 | "bugs": { 40 | "url": "https://github.com/dfinity/icp-js-canisters" 41 | }, 42 | "keywords": [ 43 | "internet computer", 44 | "internet-computer", 45 | "ic", 46 | "dfinity", 47 | "dfx", 48 | "canister", 49 | "candid", 50 | "motoko", 51 | "javascript", 52 | "typescript", 53 | "blockchain", 54 | "crypto", 55 | "nns", 56 | "network nervous system", 57 | "network-nervous-system", 58 | "sns", 59 | "service nervous system", 60 | "service-nervous-system" 61 | ], 62 | "peerDependencies": { 63 | "@icp-sdk/core": "*", 64 | "zod": "^4" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /packages/utils/src/utils/asserts.utils.ts: -------------------------------------------------------------------------------- 1 | export class InvalidPercentageError extends Error {} 2 | export class NullishError extends Error {} 3 | 4 | export const assertNonNullish: ( 5 | value: T, 6 | message?: string, 7 | // eslint-disable-next-line local-rules/prefer-object-params 8 | ) => asserts value is NonNullable = ( 9 | value: T, 10 | message?: string, 11 | ): void => { 12 | if (value === null || value === undefined) { 13 | throw new NullishError(message); 14 | } 15 | }; 16 | 17 | // eslint-disable-next-line local-rules/prefer-object-params 18 | export const asNonNullish = (value: T, message?: string): NonNullable => { 19 | assertNonNullish(value, message); 20 | return value; 21 | }; 22 | 23 | export const assertPercentageNumber = (percentage: number) => { 24 | if (percentage < 0 || percentage > 100) { 25 | throw new InvalidPercentageError( 26 | `${percentage} is not a valid percentage number.`, 27 | ); 28 | } 29 | }; 30 | 31 | /** 32 | * Utility to enforce exhaustiveness checks in TypeScript. 33 | * 34 | * This function should only be called in branches of a `switch` or conditional 35 | * that should be unreachable if the union type has been fully handled. 36 | * 37 | * By typing the parameter as `never`, the compiler will emit an error if 38 | * a new variant is added to the union but not covered in the logic. 39 | * 40 | * @param _ - A value that should be of type `never`. If this is not the case, 41 | * the TypeScript compiler will flag a type error. 42 | * @param message - Optional custom error message to include in the thrown error. 43 | * @throws {Error} Always throws when invoked at runtime. 44 | * 45 | */ 46 | // eslint-disable-next-line local-rules/prefer-object-params 47 | export const assertNever = (_: never, message?: string): never => { 48 | throw new Error(message); 49 | }; 50 | -------------------------------------------------------------------------------- /packages/canisters/src/declarations/ledger-icrc/icrc_icrc-1.did: -------------------------------------------------------------------------------- 1 | // Generated from dfinity/ICRC-1 commit f8c39bec71b1ac7f6cdb1a6c9844726efc58be38 for file 'standards/ICRC-1/ICRC-1.did' 2 | 3 | // Number of nanoseconds since the UNIX epoch in UTC timezone. 4 | type Timestamp = nat64; 5 | 6 | // Number of nanoseconds between two [Timestamp]s. 7 | type Duration = nat64; 8 | 9 | type Subaccount = blob; 10 | 11 | type Account = record { 12 | owner : principal; 13 | subaccount : opt Subaccount; 14 | }; 15 | 16 | type TransferArgs = record { 17 | from_subaccount : opt Subaccount; 18 | to : Account; 19 | amount : nat; 20 | fee : opt nat; 21 | memo : opt blob; 22 | created_at_time : opt Timestamp; 23 | }; 24 | 25 | type TransferError = variant { 26 | BadFee : record { expected_fee : nat }; 27 | BadBurn : record { min_burn_amount : nat }; 28 | InsufficientFunds : record { balance : nat }; 29 | TooOld; 30 | CreatedInFuture: record { ledger_time : Timestamp }; 31 | Duplicate : record { duplicate_of : nat }; 32 | TemporarilyUnavailable; 33 | GenericError : record { error_code : nat; message : text }; 34 | }; 35 | 36 | type Value = variant { 37 | Nat : nat; 38 | Int : int; 39 | Text : text; 40 | Blob : blob; 41 | }; 42 | 43 | service : { 44 | icrc1_metadata : () -> (vec record { text; Value; }) query; 45 | icrc1_name : () -> (text) query; 46 | icrc1_symbol : () -> (text) query; 47 | icrc1_decimals : () -> (nat8) query; 48 | icrc1_fee : () -> (nat) query; 49 | icrc1_total_supply : () -> (nat) query; 50 | icrc1_minting_account : () -> (opt Account) query; 51 | icrc1_balance_of : (Account) -> (nat) query; 52 | icrc1_transfer : (TransferArgs) -> (variant { Ok : nat; Err : TransferError }); 53 | icrc1_supported_standards : () -> (vec record { name : text; url : text }) query; 54 | } 55 | -------------------------------------------------------------------------------- /packages/ic-management/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { IcManagementDid } from "@icp-sdk/canisters/ic-management"; 2 | 3 | export type canister_install_mode = IcManagementDid.canister_install_mode; 4 | export type canister_log_record = IcManagementDid.canister_log_record; 5 | export type canister_status_result = IcManagementDid.canister_status_result; 6 | export type chunk_hash = IcManagementDid.chunk_hash; 7 | export type definite_canister_settings = 8 | IcManagementDid.definite_canister_settings; 9 | export type environment_variable = IcManagementDid.environment_variable; 10 | export type fetch_canister_logs_result = 11 | IcManagementDid.fetch_canister_logs_result; 12 | export type list_canister_snapshots_result = 13 | IcManagementDid.list_canister_snapshots_result; 14 | export type log_visibility = IcManagementDid.log_visibility; 15 | export type read_canister_snapshot_data_response = 16 | IcManagementDid.read_canister_snapshot_data_response; 17 | export type read_canister_snapshot_metadata_response = 18 | IcManagementDid.read_canister_snapshot_metadata_response; 19 | export type snapshot = IcManagementDid.snapshot; 20 | export type snapshot_id = IcManagementDid.snapshot_id; 21 | export type take_canister_snapshot_result = 22 | IcManagementDid.take_canister_snapshot_result; 23 | export type upload_canister_snapshot_metadata_response = 24 | IcManagementDid.upload_canister_snapshot_metadata_response; 25 | 26 | /** 27 | * @deprecated Use "@icp-sdk/canisters/ic-management" directly instead 28 | */ 29 | export * from "@icp-sdk/canisters/ic-management"; 30 | 31 | /** 32 | * Legacy re-export for backward compatibility. 33 | * @deprecated Use "@icp-sdk/canisters/ic-management" directly instead 34 | */ 35 | export { 36 | IcManagementCanister as ICManagementCanister, 37 | type IcManagementCanisterOptions as ICManagementCanisterOptions, 38 | } from "@icp-sdk/canisters/ic-management"; 39 | -------------------------------------------------------------------------------- /packages/nns-proto/proto/nns_common_pb.d.ts: -------------------------------------------------------------------------------- 1 | // package: ic_nns_common.pb.v1 2 | // file: nns_common.proto 3 | 4 | import * as jspb from "google-protobuf"; 5 | import * as base_types_pb from "./base_types_pb"; 6 | 7 | export class NeuronId extends jspb.Message { 8 | getId(): number; 9 | setId(value: number): void; 10 | 11 | serializeBinary(): Uint8Array; 12 | toObject(includeInstance?: boolean): NeuronId.AsObject; 13 | static toObject(includeInstance: boolean, msg: NeuronId): NeuronId.AsObject; 14 | static extensions: {[key: number]: jspb.ExtensionFieldInfo}; 15 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; 16 | static serializeBinaryToWriter(message: NeuronId, writer: jspb.BinaryWriter): void; 17 | static deserializeBinary(bytes: Uint8Array): NeuronId; 18 | static deserializeBinaryFromReader(message: NeuronId, reader: jspb.BinaryReader): NeuronId; 19 | } 20 | 21 | export namespace NeuronId { 22 | export type AsObject = { 23 | id: number, 24 | } 25 | } 26 | 27 | export class ProposalId extends jspb.Message { 28 | getId(): number; 29 | setId(value: number): void; 30 | 31 | serializeBinary(): Uint8Array; 32 | toObject(includeInstance?: boolean): ProposalId.AsObject; 33 | static toObject(includeInstance: boolean, msg: ProposalId): ProposalId.AsObject; 34 | static extensions: {[key: number]: jspb.ExtensionFieldInfo}; 35 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; 36 | static serializeBinaryToWriter(message: ProposalId, writer: jspb.BinaryWriter): void; 37 | static deserializeBinary(bytes: Uint8Array): ProposalId; 38 | static deserializeBinaryFromReader(message: ProposalId, reader: jspb.BinaryReader): ProposalId; 39 | } 40 | 41 | export namespace ProposalId { 42 | export type AsObject = { 43 | id: number, 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /scripts/update_proto.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # A script for generating the JS of proto files. 3 | protoc \ 4 | --plugin="protoc-gen-ts=./node_modules/.bin/protoc-gen-ts" \ 5 | --ts_out="./packages/nns-proto/" \ 6 | --js_out="import_style=commonjs,binary:./packages/nns-proto/" \ 7 | --proto_path="./packages/nns-proto/" \ 8 | ./packages/nns-proto/proto/base_types.proto 9 | 10 | protoc \ 11 | --plugin="protoc-gen-ts=./node_modules/.bin/protoc-gen-ts" \ 12 | --ts_out="./packages/nns-proto/proto/" \ 13 | --js_out="import_style=commonjs,binary:./packages/nns-proto/proto/" \ 14 | --proto_path="./packages/nns-proto/proto" \ 15 | ./packages/nns-proto/proto/nervous_system.proto 16 | 17 | protoc \ 18 | --plugin="protoc-gen-ts=./node_modules/.bin/protoc-gen-ts" \ 19 | --ts_out="./packages/nns-proto/proto/" \ 20 | --js_out="import_style=commonjs,binary:./packages/nns-proto/proto/" \ 21 | --proto_path="./packages/nns-proto/proto" \ 22 | ./packages/nns-proto/proto/nns_common.proto 23 | 24 | protoc \ 25 | --plugin="protoc-gen-ts=./node_modules/.bin/protoc-gen-ts" \ 26 | --ts_out="./packages/nns-proto/proto/" \ 27 | --js_out="import_style=commonjs,binary:./packages/nns-proto/proto/" \ 28 | --proto_path="./packages/nns-proto/proto" \ 29 | ./packages/nns-proto/proto/swap.proto 30 | 31 | protoc \ 32 | --plugin="protoc-gen-ts=./node_modules/.bin/protoc-gen-ts" \ 33 | --ts_out="./packages/nns-proto/proto/" \ 34 | --js_out="import_style=commonjs,binary:./packages/nns-proto/proto/" \ 35 | --proto_path="./packages/nns-proto/proto" \ 36 | ./packages/nns-proto/proto/ledger.proto 37 | 38 | protoc \ 39 | --plugin="protoc-gen-ts=./node_modules/.bin/protoc-gen-ts" \ 40 | --ts_out="./packages/nns-proto/proto/" \ 41 | --js_out="import_style=commonjs,binary:./packages/nns-proto/proto/" \ 42 | --proto_path="./packages/nns-proto/proto" \ 43 | ./packages/nns-proto/proto/governance.proto 44 | -------------------------------------------------------------------------------- /packages/canisters/src/ledger/icrc/utils/payment.utils.ts: -------------------------------------------------------------------------------- 1 | import { isNullish, nonNullish } from "@dfinity/utils"; 2 | 3 | /** 4 | * 👀 This feature is currently in draft. You can find more information about it at https://github.com/dfinity/ICRC/issues/22. 5 | * 6 | * A naive implementation of a payment parser. Given a code, the function attempts to extract a token name, account identifier (textual representation), and an optional amount. 7 | * 8 | * If the code doesn't match the expected pattern, `undefined` is returned for simplicity. 9 | * Similarly, if an optional amount is provided but it's not a valid number, the parser will not throw an exception and returns `undefined`. 10 | * 11 | * Please note that this function doesn't perform any validity checks on the extracted information. 12 | * It does not verify if the token is known or if the identifier is a valid address. 13 | * 14 | * ``` 15 | * urn = token ":" address [ "?" params] 16 | * token = [ ckbtc / icp / chat / bitcoin / ethereum ... ] 17 | * address = STRING 18 | * params = param [ "&" params ] 19 | * param = [ amountparam ] 20 | * amountparam = "amount=" *digit [ "." *digit ] 21 | * ``` 22 | * 23 | * @param code string 24 | * @returns { token: string; identifier: string; amount?: number } | undefined 25 | */ 26 | export const decodePayment = ( 27 | code: string, 28 | ): { token: string; identifier: string; amount?: number } | undefined => { 29 | const regex = 30 | /^([a-zA-Z]+):([A-Za-z0-9:\-.]+).*?(?:[?&](?:amount|value)=(\d+(?:\.\d+)?))?$/; 31 | 32 | const match = code.match(regex); 33 | if (isNullish(match)) { 34 | return undefined; 35 | } 36 | 37 | const [_, token, identifier, amount] = match; 38 | 39 | return { 40 | token, 41 | identifier, 42 | ...(nonNullish(amount) && 43 | !isNaN(parseFloat(amount)) && { amount: parseFloat(amount) }), 44 | }; 45 | }; 46 | --------------------------------------------------------------------------------