diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index a5398e220..f36d509e4 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -11,9 +11,6 @@ const BASE_DOCS_PATH = '/core'; const docsVersion = process.env.DOCS_VERSION ?? 'local'; const packagesDir = '../packages'; -const UPGRADE_BANNER_CONTENT = - 'Still using @dfinity/agent? Migrate to @icp-sdk/core!'; - // https://astro.build/config export default defineConfig({ site: 'https://js.icp.build/', @@ -37,16 +34,33 @@ export default defineConfig({ exclude: [ `${packagesDir}/core`, `${packagesDir}/migrate`, + `${packagesDir}/assets`, + `${packagesDir}/auth-client`, + `${packagesDir}/use-auth-client`, ], }, frontmatter: { editUrl: false, next: true, prev: true, - banner: { - content: UPGRADE_BANNER_CONTENT, - }, }, + prependSidebar: [ + { + label: 'Getting Started', + items: [ + { label: 'Overview', link: '/' }, + { label: 'Installation', link: '/installation' }, + { label: 'Quick Start', link: '/quick-start' }, + { label: 'Typescript', link: '/typescript' }, + ], + }, + ], + appendSidebar: [ + { + label: 'Upgrading', + autogenerate: { directory: 'upgrading', collapsed: true }, + }, + ], }), additionalFilesPlugin({ additionalFiles: [ @@ -58,9 +72,6 @@ export default defineConfig({ editUrl: false, next: false, prev: false, - banner: { - content: UPGRADE_BANNER_CONTENT, - }, }, }, ], @@ -69,12 +80,6 @@ export default defineConfig({ versionsJsonPath: `${BASE_DOCS_PATH}/versions.json`, }), ], - sidebar: [ - { - label: 'Upgrading', - autogenerate: { directory: 'upgrading', collapsed: true }, - }, - ], }), ], }); diff --git a/docs/plugins/src/libs.ts b/docs/plugins/src/libs.ts index 00ede3c0a..bafdd8163 100644 --- a/docs/plugins/src/libs.ts +++ b/docs/plugins/src/libs.ts @@ -1,18 +1,13 @@ -import fs from "node:fs/promises"; -import path from "node:path"; -import { - Application, - ProjectReflection, - ReflectionKind, - type TypeDocOptions, -} from "typedoc"; -import type { StarlightPlugin } from "@astrojs/starlight/types"; -import { type PluginOptions as TypeDocMarkdownOptions } from "typedoc-plugin-markdown"; - -import { DOCS_DIR, TMP_DIR } from "./utils/constants.ts"; -import { type Frontmatter } from "./utils/types.ts"; -import { titleFromFilename, titleFromIdCapitalized } from "./utils/string.ts"; -import { processMarkdown } from "./utils/markdown.ts"; +import fs from 'node:fs/promises'; +import path from 'node:path'; +import { Application, ProjectReflection, ReflectionKind, type TypeDocOptions } from 'typedoc'; +import type { StarlightPlugin } from '@astrojs/starlight/types'; +import { type PluginOptions as TypeDocMarkdownOptions } from 'typedoc-plugin-markdown'; + +import { DOCS_DIR, TMP_DIR } from './utils/constants.ts'; +import type { Frontmatter, Sidebar } from './utils/types.ts'; +import { titleFromFilename, titleFromIdCapitalized } from './utils/string.ts'; +import { processMarkdown } from './utils/markdown.ts'; async function generateApiDocs({ baseDir, @@ -20,16 +15,16 @@ async function generateApiDocs({ }: LibsLoaderOptions): Promise { const defaultTypeDocOptions: LibsLoaderTypeDocOptions = { entryPoints: [`${baseDir}/*`], - entryPointStrategy: "packages", + entryPointStrategy: 'packages', packageOptions: { - entryPoints: ["src/index.ts"], - tsconfig: "./tsconfig.json", - readme: "none", + entryPoints: ['src/index.ts'], + tsconfig: './tsconfig.json', + readme: 'none', }, - plugin: ["typedoc-plugin-markdown", "typedoc-plugin-frontmatter"], - tsconfig: "./tsconfig.typedoc.json", - outputs: [{ name: "markdown", path: TMP_DIR }], - readme: "none", + plugin: ['typedoc-plugin-markdown', 'typedoc-plugin-frontmatter'], + tsconfig: './tsconfig.typedoc.json', + outputs: [{ name: 'markdown', path: TMP_DIR }], + readme: 'none', hidePageTitle: true, hideBreadcrumbs: true, hidePageHeader: true, @@ -42,7 +37,7 @@ async function generateApiDocs({ const project = await app.convert(); if (!project) { - throw new Error("Failed to convert project with TypeDoc"); + throw new Error('Failed to convert project with TypeDoc'); } await app.generateOutputs(project); @@ -84,25 +79,32 @@ export interface LibsLoaderOptions { * Frontmatter applied to every markdown file generated by TypeDoc. */ frontmatter?: Frontmatter; + + /** + * Sidebar items to add before the generated sidebar items. + */ + prependSidebar?: Sidebar; + + /** + * Sidebar items to add after the generated sidebar items. + */ + appendSidebar?: Sidebar; } export type LibsLoaderTypeDocOptions = TypeDocMarkdownOptions & TypeDocOptions; export function libsPlugin(opts: LibsLoaderOptions): StarlightPlugin { return { - name: "@dfinity/starlight/libs", + name: '@dfinity/starlight/libs', hooks: { - async "config:setup"(ctx) { + async 'config:setup'(ctx) { const site = ctx.astroConfig.site; const baseDir = path.resolve(opts.baseDir.toString()); - const outDir = path.resolve( - DOCS_DIR, - opts.outDir?.toString() ?? "libs", - ); + const outDir = path.resolve(DOCS_DIR, opts.outDir?.toString() ?? 'libs'); const clean = opts.clean ?? true; if (!site) { - throw new Error("Site URL is not defined in Astro config"); + throw new Error('Site URL is not defined in Astro config'); } if (clean) { @@ -115,13 +117,13 @@ export function libsPlugin(opts: LibsLoaderOptions): StarlightPlugin { const librarySidebarItems = []; const modules = project.getChildrenByKind(ReflectionKind.Module); for (const { name } of modules) { - const id = name.startsWith("@") ? name.split("/")[1]! : name; + const id = name.startsWith('@') ? name.split('/')[1]! : name; const outputRootDir = path.resolve(outDir, id); - const outputApiDir = path.resolve(outputRootDir, "api"); + const outputApiDir = path.resolve(outputRootDir, 'api'); const title = titleFromIdCapitalized(id); await processMarkdown({ - inputPath: path.resolve(baseDir, id, "README.md"), + inputPath: path.resolve(baseDir, id, 'README.md'), outputPath: path.resolve(outputRootDir, `index.md`), frontmatter: { title, @@ -135,14 +137,12 @@ export function libsPlugin(opts: LibsLoaderOptions): StarlightPlugin { recursive: true, }); for (const file of files) { - if (file.isFile() && file.name.endsWith(".md")) { + if (file.isFile() && file.name.endsWith('.md')) { const prefix = path.relative(apiSrcDir, file.parentPath); const inputFileName = file.name; - const isReadme = inputFileName.endsWith("README.md"); - const outputFileName = isReadme ? "index.md" : inputFileName; - const title = isReadme - ? "Overview" - : titleFromFilename(file.name); + const isReadme = inputFileName.endsWith('README.md'); + const outputFileName = isReadme ? 'index.md' : inputFileName; + const title = isReadme ? 'Overview' : titleFromFilename(file.name); await processMarkdown({ inputPath: path.resolve(apiSrcDir, prefix, inputFileName), @@ -160,11 +160,11 @@ export function libsPlugin(opts: LibsLoaderOptions): StarlightPlugin { collapsed: true, items: [ { - label: "Overview", + label: 'Overview', link: `/libs/${id}`, }, { - label: "API Reference", + label: 'API Reference', collapsed: true, autogenerate: { collapsed: true, @@ -177,8 +177,12 @@ export function libsPlugin(opts: LibsLoaderOptions): StarlightPlugin { ctx.updateConfig({ sidebar: [ - { label: "Overview", link: "/" }, - { label: "Libraries", items: librarySidebarItems }, + ...(opts.prependSidebar || []), + { + label: 'Modules', + items: librarySidebarItems, + }, + ...(opts.appendSidebar || []), ...(ctx.config.sidebar || []), ], }); diff --git a/docs/plugins/src/markdown-urls.ts b/docs/plugins/src/markdown-urls.ts index 569edf61d..27f6d15fc 100644 --- a/docs/plugins/src/markdown-urls.ts +++ b/docs/plugins/src/markdown-urls.ts @@ -1,90 +1,86 @@ -import { type AstroIntegrationLogger, type RemarkPlugins } from "astro"; -import { visit } from "unist-util-visit"; -import path from "node:path"; -import { type StarlightPlugin } from "@astrojs/starlight/types"; -import { DOCS_DIR } from "./utils/constants.ts"; -import { readdirSync } from "node:fs"; +import { type AstroIntegrationLogger, type RemarkPlugins } from 'astro'; +import { visit } from 'unist-util-visit'; +import path from 'node:path'; +import { type StarlightPlugin } from '@astrojs/starlight/types'; +import { DOCS_DIR } from './utils/constants.ts'; +import { readdirSync } from 'node:fs'; type RemarkPlugin = RemarkPlugins[number]; -const markdownUrlsRemarkPlugin: RemarkPlugin = ( - [logger, docsDir, site, baseUrl, crossPackageUrlRegex]: [ +const markdownUrlsRemarkPlugin: RemarkPlugin = + ([logger, docsDir, site, baseUrl, crossPackageUrlRegex]: [ AstroIntegrationLogger, string, string, string, RegExp, - ], -) => -(tree, file) => { - const currentFileDir = path.dirname(file.path); + ]) => + (tree, file) => { + const currentFileDir = path.dirname(file.path); - visit(tree, "link", (node) => { - const url = node.url; + visit(tree, 'link', node => { + const url = node.url; - // take full URLs to the current site and make them relative - if (url.startsWith(site)) { - node.url = new URL(url).pathname; - return; - } + // take full URLs to the current site and make them relative + if (url.startsWith(site)) { + node.url = new URL(url).pathname; + return; + } - // skip any other full URLs - if ( - url.startsWith("https://") || - url.startsWith("/") || - url.startsWith("http://") || - url.startsWith("mailto:") || - url.startsWith("#") - ) { - logger.debug(`Skipping URL: ${url}`); - return; - } + // skip any other full URLs + if ( + url.startsWith('https://') || + url.startsWith('/') || + url.startsWith('http://') || + url.startsWith('mailto:') || + url.startsWith('#') + ) { + logger.debug(`Skipping URL: ${url}`); + return; + } - // if the url is a cross-package link, go back one level and add the api directory - const normalizedUrl = url.replace(crossPackageUrlRegex, '../../$1/api'); - const absoluteLinkedFilePath = path.resolve(currentFileDir, normalizedUrl); + // if the url is a cross-package link, go back one level and add the api directory + const normalizedUrl = url.replace(crossPackageUrlRegex, '../../$1/api'); + const absoluteLinkedFilePath = path.resolve(currentFileDir, normalizedUrl); - // normalize all other relative URLs to the docs directory - const relativeToDocs = path.relative(docsDir, absoluteLinkedFilePath); - const nodeUrl = `${baseUrl}${ - relativeToDocs.replace(/(index)?\.mdx?(#.*)?$/, "$2").toLowerCase() - }`; - logger.debug(`Normalizing URL: ${url} -> ${nodeUrl}`); + // normalize all other relative URLs to the docs directory + const relativeToDocs = path.relative(docsDir, absoluteLinkedFilePath); + const nodeUrl = `${baseUrl}${relativeToDocs + .replace(/(index)?\.mdx?(#.*)?$/, '$2') + .toLowerCase()}`; + logger.debug(`Normalizing URL: ${url} -> ${nodeUrl}`); - node.url = nodeUrl; - }); -}; + node.url = nodeUrl; + }); + }; -interface MarkdownUrlsPluginOptions { +interface MarkdownUrlsPluginOptions { packagesDir: string; } export function markdownUrlsPlugin({ packagesDir }: MarkdownUrlsPluginOptions): StarlightPlugin { return { - name: "@dfinity/starlight/markdown-urls", + name: '@dfinity/starlight/markdown-urls', hooks: { - "config:setup": (ctx) => { + 'config:setup': ctx => { const site = ctx.astroConfig.site; // get all the packages in the packagesDir const packages = readdirSync(packagesDir); - const crossPackageUrlRegex = new RegExp(`\\.\\.\\/(${packages.join('|')})`); + const crossPackageUrlRegex = new RegExp(`\\.\\.\\/(${packages.join('|')})/`); ctx.addIntegration({ - name: "libs-astro-plugin", + name: 'libs-astro-plugin', hooks: { - "astro:config:setup": ({ updateConfig, config, logger }) => { + 'astro:config:setup': ({ updateConfig, config, logger }) => { updateConfig({ markdown: { remarkPlugins: [ ...config.markdown.remarkPlugins, - [markdownUrlsRemarkPlugin, [ - logger, - DOCS_DIR, - site, - ctx.astroConfig.base, - crossPackageUrlRegex, - ]], + [ + markdownUrlsRemarkPlugin, + [logger, DOCS_DIR, site, ctx.astroConfig.base, crossPackageUrlRegex], + ], ], }, }); diff --git a/docs/plugins/src/utils/types.ts b/docs/plugins/src/utils/types.ts index 8087788cc..959ebf6d9 100644 --- a/docs/plugins/src/utils/types.ts +++ b/docs/plugins/src/utils/types.ts @@ -1,6 +1,7 @@ -import { docsSchema } from "@astrojs/starlight/schema"; -import type { z } from "astro/zod"; +import { docsSchema } from '@astrojs/starlight/schema'; +import { type StarlightUserConfig } from '@astrojs/starlight/types'; +import type { z } from 'astro/zod'; -export type Frontmatter = Partial< - z.infer>> ->; +export type Frontmatter = Partial>>>; + +export type Sidebar = StarlightUserConfig['sidebar']; diff --git a/docs/src/content/docs/installation.mdx b/docs/src/content/docs/installation.mdx new file mode 100644 index 000000000..34e2f7a96 --- /dev/null +++ b/docs/src/content/docs/installation.mdx @@ -0,0 +1,29 @@ +--- +title: Installation +description: How to install the @icp-sdk/core package. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +The `@icp-sdk/core` is a single, unified package that contains all the modules you need to interact with the Internet Computer. + + + + ```shell npm install @icp-sdk/core ``` + + + ```shell pnpm add @icp-sdk/core ``` + + + ```shell bun add @icp-sdk/core ``` + + + ```shell yarn add @icp-sdk/core ``` + + + +## CDN + +We do not recommend using the CDN distribution of the `@icp-sdk/core` package for **production** applications. + +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). diff --git a/docs/src/content/docs/quick-start.mdx b/docs/src/content/docs/quick-start.mdx new file mode 100644 index 000000000..7c8f4361d --- /dev/null +++ b/docs/src/content/docs/quick-start.mdx @@ -0,0 +1,92 @@ +--- +title: Quick Start +description: A quick start guide to using the @icp-sdk/core package. +next: + label: Agent Module +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +This guide offers a simple example of how to use the `@icp-sdk/core` package to interact with Internet Computer canisters. + +## Using an Actor + +This is the most common way to use the `@icp-sdk/core` package to interact with Internet Computer canisters. + + + + ```ts + import { Actor, HttpAgent, type ActorSubclass } from "@icp-sdk/core/agent"; + import { Ed25519KeyIdentity } from "@icp-sdk/core/identity"; + import { Principal } from "@icp-sdk/core/principal"; + import { idlFactory, type _SERVICE } from "./declarations"; + + const canisterId = Principal.fromText('uqqxf-5h777-77774-qaaaa-cai'); + const identity = Ed25519KeyIdentity.generate(); + + const agent = await HttpAgent.create({ + host: 'https://icp-api.io', + identity, + }); + + const actor = Actor.createActor(idlFactory, { + canisterId, + agent, + }) as ActorSubclass<_SERVICE>; + + const response = await actor.greet('world'); + + console.log(response); + ``` + + + + ```ts + // This file is typically auto-generated by the ICP CLI. + + import type { ActorMethod } from '@icp-sdk/core/agent'; + import type { IDL } from '@icp-sdk/core/candid'; + + export interface _SERVICE { 'greet' : ActorMethod<[string], string> } + + export const idlFactory: IDL.InterfaceFactory = ({ IDL }) => { + return IDL.Service({ 'greet' : IDL.Func([IDL.Text], [IDL.Text], []) }); + }; + ``` + + + + +## Using the HttpAgent + +You can also use the `HttpAgent` class to interact with canisters directly. + +```ts +// Importing the HttpAgent from the agent module +import { HttpAgent } from '@icp-sdk/core/agent'; +import { Ed25519KeyIdentity } from '@icp-sdk/core/identity'; +import { IDL } from '@icp-sdk/core/candid'; +import { Principal } from '@icp-sdk/core/principal'; + +const identity = Ed25519KeyIdentity.generate(); +const canisterId = Principal.fromText('uqqxf-5h777-77774-qaaaa-cai'); + +const agent = await HttpAgent.create({ + host: 'https://icp-api.io', + identity, +}); + +// Send an update call to the canister +await agent.call(canisterId, { + methodName: 'greet', + arg: IDL.encode([IDL.Text], ['world']), +}); +``` + +## Usage in a TypeScript project + +If you are using TypeScript, have a look at the [TypeScript guide](./typescript.mdx). + +## Next Steps + +Have a look at the [Examples repo](https://github.com/dfinity/examples) to see how to use the `@icp-sdk/core` package in a real-world application. diff --git a/docs/src/content/docs/typescript.mdx b/docs/src/content/docs/typescript.mdx new file mode 100644 index 000000000..29d3247cf --- /dev/null +++ b/docs/src/content/docs/typescript.mdx @@ -0,0 +1,22 @@ +--- +title: Typescript +description: Typescript guide for the @icp-sdk/core package. +next: + label: Agent Module +--- + +This guide covers the basics of using TypeScript with the `@icp-sdk/core` package. + +## Configure the `moduleResolution` + +You must configure your TypeScript compiler to use the a modern [`moduleResolution`](https://www.typescriptlang.org/tsconfig#moduleResolution) strategy. + +In your `tsconfig.json` file, set the `moduleResolution` to either `node16`, `nodenext`, or `bundler`: + +```json +{ + "compilerOptions": { + "moduleResolution": "node16" + } +} +``` diff --git a/docs/src/content/docs/upgrading/v4.md b/docs/src/content/docs/upgrading/v4.md new file mode 100644 index 000000000..8c98c01cd --- /dev/null +++ b/docs/src/content/docs/upgrading/v4.md @@ -0,0 +1,117 @@ +--- +title: Upgrading to @icp-sdk/core +description: Upgrading guide for the new @icp-sdk/core package +sidebar: + label: v4 + order: 1 +next: + label: Overview + link: /core/latest/ +--- + +The new `@icp-sdk/core` package is made up of multiple submodules, each of which contains the functionality of the respective old `@dfinity/...` package. + +## Automatic + +We provide a CLI tool to automatically upgrade your code to use the new package. + +Simply run the following command in the root of your project: + +```shell +npx @icp-sdk/core-migrate@latest +``` + +For more migration options, run `npx @icp-sdk/core-migrate@latest --help`. + +## Manual + +Everything previously exported from the individual `@dfinity/*` packages is now +exported from a `@icp-sdk/core/*` submodule. + +1. Remove the following packages, if present: + - `@dfinity/agent` + - `@dfinity/candid` + - `@dfinity/identity` + - `@dfinity/identity-secp256k1` + - `@dfinity/principal` + + E.g. + + ```shell + npm remove @dfinity/{agent,candid,identity,identity-secp256k1,principal} + ``` + +2. Install the new `@icp-sdk/core` package: + + ```shell + npm i @icp-sdk/core + ``` + +3. Replace old imports with new imports, if present: + + | Old Import | New Import | + | ----------------------------- | ---------------------------------- | + | `@dfinity/agent` | `@icp-sdk/core/agent` | + | `@dfinity/candid` | `@icp-sdk/core/candid` | + | `@dfinity/identity` | `@icp-sdk/core/identity` | + | `@dfinity/identity-secp256k1` | `@icp-sdk/core/identity/secp256k1` | + | `@dfinity/principal` | `@icp-sdk/core/principal` | + + E.g. + + ```ts + - import { HttpAgent } from '@dfinity/agent'; + + import { HttpAgent } from '@icp-sdk/core/agent'; + ``` + +## FAQ + +### TypeScript `moduleResolution` + +If you're using TypeScript, you need to set the [`moduleResolution`](https://www.typescriptlang.org/tsconfig/#moduleResolution) to either `node16`, `nodenext` or `bundler` in your `tsconfig.json` file. + +```json +{ + "compilerOptions": { + "moduleResolution": "node16" + } +} +``` + +### Using agent-js v2 + +If you're using agent-js v2, you need to upgrade to v3 before upgrading to `@icp-sdk/core`. You can find the release notes [here](https://js.icp.build/core/release-notes/v300/). + +### Workspaces + +If you're using a workspace, you must run the migration tool for each package in the workspace that has any `@dfinity/*` dependencies. You may need to first uninstall the `@dfinity/*` packages manually from all the packages in the workspace before running the migration tool, to avoid version conflicts. + +A similar approach can be used for monorepos. + +### Tree-shaking + +Tree-shaking is supported, so you can import only the submodules you need and your bundler will automatically remove the unused code. + +### Using `@dfinity/*` packages in other places than imports + +The `@icp-sdk/core-migrate` CLI tool only replaces the `@dfinity/*` occurrences in imports. If you are using `@dfinity/*` packages somewhere else in your code, e.g. in tests mocks, you will need to find and replace the occurrences **manually**. + +E.g. + +```diff +- vi.mock('@dfinity/agent', () => ({ ++ vi.mock('@icp-sdk/core/agent', () => ({ + ... +})); +``` + +### `@dfinity/assets` and `@dfinity/auth-client` + +The `@dfinity/assets` and `@dfinity/auth-client` packages are not included in `@icp-sdk/core`. They will be included in other `@icp-sdk/*` packages in the near future. For now, you can still use them. + +### `@dfinity/use-auth-client` + +The `@dfinity/use-auth-client` package is not included in `@icp-sdk/core` and **will be deprecated soon**. Please consider using other libraries instead. Recommended alternatives: + +- [ic-use-internet-identity](https://www.npmjs.com/package/ic-use-internet-identity) +- [@ic-reactor/react](https://www.npmjs.com/package/@ic-reactor/react) diff --git a/docs/src/pages/index.astro b/docs/src/pages/index.astro index 91f2dfda7..eb46073f1 100644 --- a/docs/src/pages/index.astro +++ b/docs/src/pages/index.astro @@ -8,9 +8,6 @@ import icpSvg from '@dfinity/starlight/assets/icp.svg'; @dfinity/agent? Migrate to @icp-sdk/core!`, - }, next: false, prev: false, tableOfContents: false, @@ -36,92 +33,97 @@ import icpSvg from '@dfinity/starlight/assets/icp.svg'; }} >
-

Libraries

+

Get Started

- - Build applications that interact with the Internet Computer from browsers, Node.js, and - other JavaScript runtimes. - - - See @dfinity/agent docs + + + Install the @icp-sdk/core package - - Manage assets on an Internet Computer assets canister. - - - See @dfinity/assets docs + + + Get started with the @icp-sdk/core package + +
- - Simple interface to get your web application authenticated with the Internet Identity Service. +
+

Modules

- - See @dfinity/auth-client docs + + + Build applications that interact with the Internet Computer from browsers, Node.js, and + other JavaScript runtimes. + + + See @icp-sdk/core/agent docs - JavaScript and TypeScript library to work with Candid interfaces. + JavaScript and TypeScript module to work with Candid interfaces. - - See @dfinity/candid docs + + See @icp-sdk/core/candid docs - JavaScript and TypeScript library to manage Identities and enable simple Web Authentication flows. + JavaScript and TypeScript module to manage Identities and enable simple Web Authentication flows. - - See @dfinity/identity docs - - - - - The `Secp256k1KeyIdentity` package provides an implementation of the `SignIdentity` interface for the `secp256k1` elliptic curve. - - - See @dfinity/identity-secp256k1 docs + + See @icp-sdk/core/identity docs - JavaScript and TypeScript library to work with Internet Computer Principals. + JavaScript and TypeScript module to work with Internet Computer Principals. - See @dfinity/principal docs + See @icp-sdk/core/principal docs - - A package for Internet Computer React developers, making it easier to integrate the auth-client with your React application. - - - See @dfinity/use-auth-client docs - -

Upgrading

- + + +

+ If you're using @dfinity/agent version 3.x, you can migrate to + @icp-sdk/core with the help of our automated migration tools or manual migration + guide. +

+ + + Migrate to @icp-sdk/core + +
+ +

If you're still using @dfinity/agent version 2.x, you can migrate to 3.x with the help of our migration guide.

Still using `@dfinity/agent`? Migrate to [`@icp-sdk/core`](https://js.icp.build/core/latest/upgrading/v4)! +JavaScript and TypeScript module to interact with the [Internet Computer](https://internetcomputer.org/) for Node.js and browser applications. -JavaScript and TypeScript library to interact with the [Internet Computer](https://dfinity.org/) for Node.js and browser applications. - -Do you want to know more about developing on the Internet Computer? Visit the [Developer Docs](https://internetcomputer.org/docs/home). - -Additional API Documentation can be found [here](https://js.icp.build/core/v3.2/libs/agent/api). - ---- - -## Installation - -Using agent: - -```shell -npm i --save @dfinity/agent -``` - -### In the browser: - -```ts -import * as agent from '@dfinity/agent'; -``` - -or using individual exports: - -```ts -import { Actor, HttpAgent } from '@dfinity/agent'; -``` - -### In Node.js +## Usage ```ts -const DfinityAgent = require('@dfinity/agent'); -``` +import { HttpAgent } from '@icp-sdk/core/agent'; -or using individual exports: +const agent = await HttpAgent.create({ + host: 'https://icp-api.io', +}); -```ts -const { Actor, HttpAgent } = require('@dfinity/agent'); +agent.call(..) // Send an update call to the canister +agent.query(..) // Send a query call to the canister +agent.readState(..) // Read the state of the canister ``` -## Using an Agent +### Using an Agent The agent is a low-level interface that the Actor uses to encode and decode messages to the Internet Computer. It provides `call`, `query` and `readState` methods to the Actor, as well as a few additional utilities. For the most part, calls through the agent are intended to be structured through an Actor, configured with a canister interface that can be automatically generated from a [Candid](https://github.com/dfinity/candid) interface. -## Initializing an Actor +### Initializing an Actor The most common use for the agent is to create an actor. This is done by calling the `Actor.createActor` constructor: @@ -72,7 +46,7 @@ const defaultAgent = Actor.agentOf(defaultActor); This is useful if you need to replace or invalidate the identity used by an actor's agent. -For example, if you want to replace the identity of an actor's agent with a newly authenticated identity from [Internet Identity](https://identity.ic0.app), you can do so by calling the `Actor.replaceAgent` method: +For example, if you want to replace the identity of an actor's agent with a newly authenticated identity from [Internet Identity](https://identity.internetcomputer.org), you can do so by calling the `Actor.replaceAgent` method: ```ts defaultAgent.replaceIdentity(await authClient.getIdentity()); @@ -86,7 +60,7 @@ For example, ```ts import fetch from 'isomorphic-fetch'; -import { HttpAgent } from '@dfinity/agent'; +import { HttpAgent } from '@icp-sdk/core/agent'; const host = process.env.DFX_NETWORK === 'local' ? 'http://127.0.0.1:4943' : 'https://icp-api.io'; @@ -99,7 +73,7 @@ For example, ```ts import fetch from 'isomorphic-fetch'; -import { HttpAgent } from '@dfinity/agent'; +import { HttpAgent } from '@icp-sdk/core/agent'; const host = process.env.DFX_NETWORK === 'local' ? 'http://127.0.0.1:4943' : 'https://ic0.app'; @@ -114,3 +88,7 @@ const fetchOptions = { const agent = new HttpAgent({ fetch, host, fetchOptions }); ``` + +## API Reference + +Additional API Documentation can be found [here](https://js.icp.build/core/latest/libs/agent/api). diff --git a/packages/candid/README.md b/packages/candid/README.md index 2aec5a9e4..557b69c89 100644 --- a/packages/candid/README.md +++ b/packages/candid/README.md @@ -1,25 +1,13 @@ -# @dfinity/candid +# @icp-sdk/core/candid -> Still using `@dfinity/candid`? Migrate to [`@icp-sdk/core`](https://js.icp.build/core/latest/upgrading/v4)! +JavaScript and TypeScript module to work with Candid interfaces -JavaScript and TypeScript library to work with Candid interfaces +## Usage -Do you want to know more about developing on the Internet Computer? Visit the [Developer Docs](https://internetcomputer.org/docs/home). - -Additional API Documentation can be found [here](https://js.icp.build/core/v3.2/libs/candid/api). - ---- - -## Installation - -Using Candid: - -```shell -npm i --save @dfinity/candid +```ts +import { IDL } from '@icp-sdk/core/candid'; ``` -### In the browser: +## API Reference -```ts -import { Candid } from '@dfinity/candid'; -``` +Additional API Documentation can be found [here](https://js.icp.build/core/latest/libs/candid/api). diff --git a/packages/core/README.md b/packages/core/README.md index a98f3452c..7aa0ef4b7 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -4,9 +4,7 @@ The `@icp-sdk/core` package is a JavaScript and TypeScript library designed to i Do you want to know more about developing on the Internet Computer? Visit the [Developer Docs](https://internetcomputer.org/docs/home). -Additional API Documentation can be found [here](https://js.icp.build/core/libs/core/api). - -**Note:** This package requires the `node16` (or later) module resolution strategy to function correctly. +> Still using `@dfinity/agent`? Migrate to [`@icp-sdk/core`](https://js.icp.build/core/latest/upgrading/v4)! --- @@ -32,16 +30,6 @@ yarn add @icp-sdk/core pnpm add @icp-sdk/core ``` -## Package Structure - -The `@icp-sdk/core` package re-exports modules from the following `@dfinity` packages: - -- [`@dfinity/agent`](../agent/README.md): Provides tools to interact with the Internet Computer, including creating actors and making calls. -- [`@dfinity/candid`](../candid/README.md): Tools for working with Candid, the Internet Computer's interface definition language. -- [`@dfinity/identity`](../identity/README.md): Identity management for signing and authentication. -- [`@dfinity/identity-secp256k1`](../identity-secp256k1/README.md): Identity management using secp256k1 cryptography. -- [`@dfinity/principal`](../principal/README.md): Utilities for working with principals on the Internet Computer. - ## Import Paths The package provides the following import paths for accessing the re-exported modules: @@ -60,26 +48,39 @@ Here is an example of how to use the `@icp-sdk/core` package: // Importing the HttpAgent from the agent module import { HttpAgent } from '@icp-sdk/core/agent'; +// Importing the Identity utility +import { Ed25519KeyIdentity } from '@icp-sdk/core/identity'; + +// Importing the Candid utility +import { IDL } from '@icp-sdk/core/candid'; + // Importing the Principal utility import { Principal } from '@icp-sdk/core/principal'; -// Create an HttpAgent instance -const agent = new HttpAgent({ host: 'https://ic0.app' }); +// Create a new identity +const identity = Ed25519KeyIdentity.generate(); // Create a Principal from a string -const principal = Principal.fromText('aaaaa-aa'); +const canisterId = Principal.fromText('uqqxf-5h777-77774-qaaaa-cai'); -// Log the Principal -console.log(principal.toText()); +// Create an HttpAgent instance +const agent = await HttpAgent.create({ + host: 'https://icp-api.io', + identity, +}); + +// Call a canister +const response = await agent.call(canisterId, { + methodName: 'greet', + arg: IDL.encode([IDL.Text], ['world']), +}); + +console.log(response); ``` -For detailed usage and API documentation, refer to the respective documentation of the re-exported packages: +**Note:** If you are using TypeScript, this package requires the `node16` (or later) [`moduleResolution`](https://www.typescriptlang.org/tsconfig#moduleResolution) strategy to function correctly. -- [@dfinity/agent Documentation](../agent/README.md) -- [@dfinity/candid Documentation](../candid/README.md) -- [@dfinity/identity Documentation](../identity/README.md) -- [@dfinity/identity-secp256k1 Documentation](../identity-secp256k1/README.md) -- [@dfinity/principal Documentation](../principal/README.md) +Additional API Documentation can be found [here](https://js.icp.build/core/latest/). ## Contributing diff --git a/packages/core/package.json b/packages/core/package.json index f324925c9..e6ebd902c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -5,7 +5,7 @@ "author": "DFINITY Stiftung ", "license": "Apache-2.0", "description": "JavaScript and TypeScript library to interact with the Internet Computer", - "homepage": "https://js.icp.build/core/libs/core", + "homepage": "https://js.icp.build/core/", "repository": { "type": "git", "url": "https://github.com/dfinity/agent-js.git", diff --git a/packages/identity-secp256k1/README.md b/packages/identity-secp256k1/README.md index 39ead4599..3b79a44a2 100644 --- a/packages/identity-secp256k1/README.md +++ b/packages/identity-secp256k1/README.md @@ -1,20 +1,13 @@ -# @dfinity/identity-secp256k1 +# @icp-sdk/core/identity-secp256k1 -> Still using `@dfinity/identity-secp256k1`? Migrate to [`@icp-sdk/core`](https://js.icp.build/core/latest/upgrading/v4)! +The `@icp-sdk/core/identity-secp256k1` module provides an implementation of the [`SignIdentity`](https://js.icp.build/core/latest/libs/agent/api/classes/signidentity/) interface for the secp256k1 elliptic curve. It allows you to create and manage key pairs for signing and verification of messages. -The Secp256k1KeyIdentity package provides an implementation of the SignIdentity interface for the secp256k1 elliptic curve. It allows you to create and manage key pairs for signing and verification of messages. +## Usage -Do you want to know more about developing on the Internet Computer? Visit the [Developer Docs](https://internetcomputer.org/docs/home). - -Additional API Documentation can be found [here](https://js.icp.build/core/v3.2/libs/identity-secp256k1/api). - ---- - -Example -Here's an example of how to use the Secp256k1KeyIdentity class to generate a new key pair and sign and verify a message: +Here's an example of how to use the `Secp256k1KeyIdentity` class to generate a new key pair and sign and verify a message: ```ts -import { Secp256k1KeyIdentity } from '@dfinity/identity-secp256k1'; +import { Secp256k1KeyIdentity } from '@icp-sdk/core/identity/secp256k1'; // Generate a new key pair const identity = Secp256k1KeyIdentity.generate(); @@ -32,7 +25,7 @@ console.log(`Signature is ${isValid ? 'valid' : 'invalid'}`); You can also use a seed to generate deterministic key pairs: ```ts -import { Secp256k1KeyIdentity } from '@dfinity/identity-secp256k1'; +import { Secp256k1KeyIdentity } from '@icp-sdk/core/identity/secp256k1'; const seed = Buffer.from('my-secret-seed', 'utf8'); const identity = Secp256k1KeyIdentity.generate(seed); @@ -41,7 +34,7 @@ const identity = Secp256k1KeyIdentity.generate(seed); The Secp256k1KeyIdentity class also provides methods for converting the key pair to and from JSON-serializable objects: ```ts -import { Secp256k1KeyIdentity } from '@dfinity/agent'; +import { Secp256k1KeyIdentity } from '@icp-sdk/core/identity/secp256k1'; // Generate a new key pair const identity = Secp256k1KeyIdentity.generate(); @@ -53,5 +46,6 @@ const json = identity.toJson(); const restoredIdentity = Secp256k1KeyIdentity.fromJson(json); ``` -References -The Secp256k1KeyIdentity class extends the SignIdentity interface from the @dfinity/agent package. For more information about the SignIdentity interface and how to use it, see the [@dfinity/agent documentation](https://js.icp.build/core/v3.2/libs/agent/api/classes/signidentity). +## API Reference + +Additional API Documentation can be found [here](https://js.icp.build/core/latest/libs/identity-secp256k1/api/). diff --git a/packages/identity/README.md b/packages/identity/README.md index e205ea86d..127da3807 100644 --- a/packages/identity/README.md +++ b/packages/identity/README.md @@ -1,49 +1,33 @@ -# @dfinity/identity +# @icp-sdk/core/identity -> Still using `@dfinity/identity`? Migrate to [`@icp-sdk/core`](https://js.icp.build/core/latest/upgrading/v4)! +JavaScript and TypeScript module to manage Identities and enable simple Web Authentication flows for applications on the [Internet Computer](https://internetcomputer.org/) -JavaScript and TypeScript library to manage Identities and enable simple Web Authentication flows for applications on the [Internet Computer](https://dfinity.org/) - -Do you want to know more about developing on the Internet Computer? Visit the [Developer Docs](https://internetcomputer.org/docs/home). - -Additional API Documentation can be found [here](https://js.icp.build/core/v3.2/libs/identity/api). - ---- - -## Installation - -Using authentication: - -```shell -npm i --save @dfinity/identity -``` - -### In the browser: +## Usage ```ts -import * as identity from '@dfinity/identity'; -``` +import { ECDSAKeyIdentity, Ed25519KeyIdentity, WebAuthnIdentity } from '@icp-sdk/core/identity'; -or using individual exports: - -```ts -import { ECDSAKeyIdentity, DelegationIdentity } from '@dfinity/identity'; +const ecdsaIdentity = await ECDSAKeyIdentity.generate(); +const ed25519Identity = Ed25519KeyIdentity.generate(); +const webAuthnIdentity = await WebAuthnIdentity.create(); ``` -### ECDSAKeyIdentity +### DelegationIdentity -Using an `ECDSAKeyIdentity`, you can now use the native Web Crypto API to manage your keys in `agent-js`. `ECDSAKeyIdentity` uses the crypto.subtle interface under the hood, and wraps the conventions for managing identities in the same way as other identities in this package. +The `DelegationIdentity` is typically generated using the [@dfinity/auth-client](https://npmjs.com/package/@dfinity/auth-client) package. -Importantly, there is no importing from a private key or from JSON for this library. This should be used only in secure contexts, and you should only in rare circumstances interact directly with the KeyPair or CryptoKeys involved. Importantly, your CryptoKeys can be used in IndexedDb and can be created as `extractable` or `non-extractable` for enhanced security properties. +### PartialIdentity -### Secp256k1KeyIdentity +The `PartialIdentity` is not typically used directly, but is used by the `DelegationIdentity` and `WebAuthnIdentity` classes. -This identity can be generated using the bip39 curve from a seed phrase, to produce a consistent identity across `dfx` and `agent-js`. In this package, import `Secp256k1KeyIdentity` and call `fromSeed`, passing in your seed. You can import the same seed in `dfx` by writing it to a file, and running `dfx identity import --seed-file `. +### Secp256k1KeyIdentity -Depending on the security of what this identity controls, this should not be used carelessly. Even copy/pasting a phrase can be a risk, and you should make your best efforts to discourage your users from storing seed phrases digitally or using them in browser contexts that may be at risk of cross-site scripting. +See [@icp-sdk/core/identity/secp256k1](https://js.icp.build/core/latest/libs/identity-secp256k1/api/) for more information. -#### In Node.js +## In Node.js Depending on your version, you may need to use a polyfill and set `global.crypto` in a setup file. If you prefer, you can also pass in a `subtleCrypto` implementation in methods that call for it, either as a direct argument, or in a `cryptoOptions` object. -Note: depends on [@dfinity/agent](https://www.npmjs.com/package/@dfinity/agent) +## API Reference + +Additional API Documentation can be found [here](https://js.icp.build/core/latest/libs/identity/api/). diff --git a/packages/identity/seed.txt b/packages/identity/seed.txt deleted file mode 100644 index c891ac088..000000000 --- a/packages/identity/seed.txt +++ /dev/null @@ -1,2 +0,0 @@ -early cinnamon crucial teach mobile just toast real rebel around card priority spike aerobic result account marble hero action -intact inside elbow wrestle oval diff --git a/packages/principal/README.md b/packages/principal/README.md index 9ec1da2d6..d0290f257 100644 --- a/packages/principal/README.md +++ b/packages/principal/README.md @@ -1,25 +1,16 @@ -# @dfinity/principal +# @icp-sdk/core/principal -> Still using `@dfinity/principal`? Migrate to [`@icp-sdk/core`](https://js.icp.build/core/latest/upgrading/v4)! +JavaScript and TypeScript module to work with Internet Computer Principals. -JavaScript and TypeScript library to work with Internet Computer Principals +## Usage -Do you want to know more about developing on the Internet Computer? Visit the [Developer Docs](https://internetcomputer.org/docs/home). - -Additional API Documentation can be found [here](https://js.icp.build/core/v3.2/libs/principal/api). - ---- - -## Installation - -Using Principal: +```ts +import { Principal } from '@icp-sdk/core/principal'; -```shell -npm i --save @dfinity/principal +const canisterId = Principal.fromText('uqqxf-5h777-77774-qaaaa-cai'); +const anonymousPrincipal = Principal.anonymous(); ``` -### In the browser: +## API Reference -```ts -import { Principal } from '@dfinity/principal'; -``` +Additional API Documentation can be found [here](https://js.icp.build/core/latest/libs/principal/api/).