Skip to content

Upgrading to v3

While functionally intact, we made changes to the third version of @icp-sdk/canisters to improve consistency and readability, with the ultimate goal of making it more maintainable for both the library and your projects.

The following breaking changes will need to be resolved when upgrading. Most can be addressed with a simple search-and-replace approach.

A long time ago in a galaxy far, far away, this library was originally created to extract logic from NNS dapp with the intent of easing community access to the same services used in the application, and with the expectation that the number of services would grow. This indeed happened, and since then, all services (ckBTC, SNS, etc.) have been shared through these packages.

The project started with existing code that entirely obfuscated the types for canister declarations generated to describe Internet Computer interfaces (Candid). The original approach was to follow this pattern. However, we quickly realized this wasn’t sustainable as it added maintenance overhead and, while perhaps slightly more developer-friendly initially, wasn’t always practical for developers who needed to access the original declarations in their projects.

That’s why we shifted to a hybrid approach that mixes custom types with IC-related types—an approach that’s also common in the applications we’re developing and likely used by many developers in the ecosystem.

More recently, however, we started experimenting with a new pattern: not importing Internet Computer interfaces (Candid) “directly” (exposed at the root of modules), but instead enforcing their usage through namespaces. While admittedly more verbose, we’ve noticed many advantages to this pattern. First, it makes code more readable since you can easily understand the context of a type — which is particularly useful in this case because nullish types in Candid are treated differently than in JavaScript (undefined vs [] | [Something]). Additionally, it helps avoid name clashes. For example, many types are similar across ICP and ICRC ledgers, and more generally, this pattern helps maintain large codebases.

That’s why, as of version 3 of @icp-sdk/canisters, the types for canister declarations generated to describe Internet Computer interfaces (Candid) are now re-exported through namespaces.

For example, the Tokens type of the IcrcLedgerCanister is available within the related namespace IcrcLedgerDid.

import {
type IcrcLedgerDid,
IcrcLedgerCanister,
} from "@icp-sdk/canisters/ledger/icrc";
const { balance } = IcrcLedgerCanister.create({
agent,
canisterId,
});
const data: IcrcLedgerDid.Tokens = await balance({ owner });

Each entry of the library exposes its own related namespaces:

EntryNamespaces
@icp-sdk/canisters/ckbtcCkBtcMinterDid
BitcoinDid
@icp-sdk/canisters/ckethCkEthMinterDid
CkEthOrchestratorDid
@icp-sdk/canisters/cmcCmcDid
@icp-sdk/canisters/ic-managementIcManagementDid
@icp-sdk/canisters/ledger/icpIcpLedgerDid
IcpIndexDid
@icp-sdk/canisters/ledger/icrcIcrcLedgerDid
IcrcIndexDid
IcrcNftLedgerDid
@icp-sdk/canisters/nnsNnsGovernanceDid
NnsGenesisTokenDid
NnsGovernanceTestDid
SnsWasmDid
@icp-sdk/canisters/snsSnsGovernanceDid
SnsGovernanceTestDid
SnsRootDid
SnsSwapDid
SnsWasmDid

We noticed inconsistency in the naming of the canisters. Some used uppercase for names, others used camel case. In addition, the ledger and index canisters for ICP were exposed without a prefix, which made their names somewhat generic.

That’s why the following canisters have been renamed for consistency and readability:

OldNew 🆕
CkBTCMinterCanisterCkBtcMinterCanister
CkETHMinterCanisterCkEthMinterCanister
CkETHOrchestratorCanisterCkEthOrchestratorCanister
CMCCanisterCmcCanister
ICManagementCanisterIcManagementCanister
LedgerCanisterIcpLedgerCanister
IndexCanisterIcpIndexCanister
GenesisTokenCanisterNnsGenesisTokenCanister
GovernanceCanisterNnsGovernanceCanister
GovernanceTestCanisterNnsGovernanceTestCanister

The Index canister was developed iteratively with forks. At some point, there were close to five different implementations. Among those, there was the original “Index canister” and a new implementation (that supported queries for getting transactions and balances) called “Index Ng Canister” — “Ng” as in “new generation”.

Given that dapps often needed to support both “old” and “new”, the library exposed both implementations with a similar naming pattern, even though arguably the latter made no particular sense for new developers: IcrcIndexCanister and IcrcIndexNgCanister.

Fortunately, time has passed and code has been improved. To our knowledge, there are no known Index canisters still using the “old” implementation. For example, all SNSes were migrated to the new implementation — “ng” — about a year ago. Likewise, the source code of the “old” index canister has even been removed from the IC repo.

That’s why, with this release, the deprecated implementation of the ICRC Index canister has been deleted, and its common implementation becomes the new standard.

In other words, IcrcIndexNgCanister becomes IcrcIndexCanister.

OldNew 🆕
IcrcIndexCanister---
IcrcIndexNgCanisterIcrcIndexCanister

For more details, have a look at the Changelog.