Internet Computer (ICP) JavaScript SDK Core

repository·main·Indexed 41 days ago

https://github.com/dfinity/icp-js-core

The official JavaScript SDK (@icp-sdk/core) for building applications on the Internet Computer. It provides core modules for interacting with the network, including Agent, Candid, Identity, and Principal utilities. Version 5.0.0 includes tools for canister environment configuration and a migration CLI to transition from legacy @dfinity packages.

Tokens
25.6K
Snippets
94
Records
134
Agent score
51%

What's inside ICP JS SDK

  1. What is the `ic_env` cookie?

    main

    The ic_env cookie is a URI-encoded string served by the asset canister alongside HTML assets to provide environment variables to the frontend synchronously.

    It contains:

    • ic_root_key: The root of trust for the Internet Computer network where the asset canister is deployed (always present).
    • Custom Variables: Any canister environment variable prefixed with PUBLIC_ (e.g., PUBLIC_CANISTER_ID:backend).
  2. Core Modules in @icp-sdk/core

    main

    The SDK is composed of several specialized modules for interacting with the Internet Computer:

    • Agent (@icp-sdk/core/agent): Provides the foundation for interacting with the Internet Computer from browsers, Node.js, and other JavaScript runtimes.
    • Candid (@icp-sdk/core/candid): A module for working with Candid interfaces.
    • Identity (@icp-sdk/core/identity): Manages Identities and enables Web Authentication (WebAuthn) flows.
    • Principal (@icp-sdk/core/principal): A module for working with Internet Computer Principals.
  3. How the Canister Environment flow works

    main

    The Canister Environment allows a frontend application to be configured at runtime without rebuilding or redeploying. This is achieved by the asset canister serving environment variables via a cookie.

    The Workflow:

    1. Developer Setup: The developer deploys a backend canister and sets environment variables (e.g., PUBLIC_CANISTER_ID:backend) on the asset canister using the management canister.
    2. Asset Request: When a user's browser requests HTML assets, the asset canister responds with an ic_env cookie.
    3. Cookie Decoding: The browser decodes the ic_env cookie (which is a URI-encoded string) to retrieve variables like ic_root_key and any variables prefixed with PUBLIC_.
    4. Actor Configuration: The frontend application uses these values to configure the canister actor (e.g., setting the rootKey and the specific canisterId) and then makes calls to the backend.
  4. Remove usage of defaultAgent and ProxyAgent

    main

    The global defaultAgent concept, the getDefaultAgent function, and the ProxyAgent class have been removed from @dfinity/agent.

    • To create an agent, use the HttpAgent constructor via HttpAgent.create() or HttpAgent.createSync().
    • To implement proxy logic, you must now create your own proxy agent using the HttpAgent class.
    import { HttpAgent } from '@dfinity/agent';
    
    // Instead of getDefaultAgent()
    const agent = await HttpAgent.create();
  5. Install @icp-sdk/core

    main

    Install the @icp-sdk/core package using your preferred package manager. This package acts as a meta-package that re-exports functionality from several @dfinity packages for interacting with the Internet Computer.

    # Using npm
    npm install @icp-sdk/core
    
    # Using yarn
    yarn add @icp-sdk/core
    
    # Using pnpm
    pnpm add @icp-sdk/core
  6. Interact with canisters using an Actor

    main

    The most common way to interact with Internet Computer canisters is by using an Actor. This typically involves using @icp-sdk/bindgen to generate type-safe bindings for your canister interface. You create an HttpAgent with a specific identity and host, then pass that agent into the generated createActor function along with the canister's Principal ID.

    import { HttpAgent } from "@icp-sdk/core/agent";
    import { Ed25519KeyIdentity } from "@icp-sdk/core/identity";
    import { Principal } from "@icp-sdk/core/principal";
    import { createActor } from "./api/hello-world";
    
    // Define the canister ID
    const canisterId = Principal.fromText('uqqxf-5h777-77774-qaaaa-cai');
    const identity = Ed25519KeyIdentity.generate();
    
    // Create the agent
    const agent = await HttpAgent.create({
      host: 'https://icp-api.io',
      identity,
    });
    
    // Create the actor using generated bindings
    const actor = createActor(canisterId, {
      agent,
    });
    
    // Call a method on the actor
    const response = await actor.greet('world');
    console.log(response);
  7. Configure Rollup/Vite for @icp-sdk/core submodules

    main

    When building a library that depends on @icp-sdk/core, you must specify each submodule you use as an external dependency in your Rollup (or Vite) configuration to ensure they are not bundled into your library.

    rollupOptions: {
      external: [
        '@icp-sdk/core/agent',
        '@icp-sdk/core/candid',
        '@icp-sdk/core/identity',
        '@icp-sdk/core/identity/secp256k1',
        '@icp-sdk/core/principal',
      ],
      output: {
        globals: {
          '@icp-sdk/core/agent': 'icp-sdk-core-agent',
          '@icp-sdk/core/candid': 'icp-sdk-core-candid',
          '@icp-sdk/core/identity': 'icp-sdk-core-identity',
          '@icp-sdk/core/identity/secp256k1': 'icp-sdk-core-identity-secp256k1',
          '@icp-sdk/core/principal': 'icp-sdk-core-principal',
        },
      },
    }