From 7e992e3142ac02ce242f58192af54f5a207a6577 Mon Sep 17 00:00:00 2001 From: Kai Peacock Date: Mon, 9 Sep 2024 10:39:47 -0700 Subject: [PATCH 1/3] feat: exports polling utilities from `@dfinity/agent` (#921) --- docs/CHANGELOG.md | 3 +++ packages/agent/src/certificate.ts | 2 +- packages/agent/src/index.ts | 1 + packages/agent/src/polling/index.ts | 3 ++- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3c5b5338..af214b85 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -14,6 +14,9 @@ - docs: documentation and metadata for use-auth-client - feat: adds optional `rootKey` to `HttpAgentOptions` to allow for a custom root key to be used for verifying signatures from other networks - chore: npm audit bumping micromatch +- feat: exports polling utilities from `@dfinity/agent` for use in other packages + - `pollForResponse` now uses the default strategy by default + - Updated the `bls-verify` jsdoc comment to accurately reflect that the default strategy now uses @noble/curves - docs: clarifies meaning of `effectiveCanisterId` in `CallOptions` ### Changed diff --git a/packages/agent/src/certificate.ts b/packages/agent/src/certificate.ts index a8cdf551..4e7c5eac 100644 --- a/packages/agent/src/certificate.ts +++ b/packages/agent/src/certificate.ts @@ -135,7 +135,7 @@ export interface CreateCertificateOptions { */ canisterId: Principal; /** - * BLS Verification strategy. Default strategy uses wasm for performance, but that may not be available in all contexts. + * BLS Verification strategy. Default strategy uses bls12_381 from @noble/curves */ blsVerify?: VerifyFunc; diff --git a/packages/agent/src/index.ts b/packages/agent/src/index.ts index 98608f63..cf911b7f 100644 --- a/packages/agent/src/index.ts +++ b/packages/agent/src/index.ts @@ -29,6 +29,7 @@ import { Agent, HttpAgent } from './agent'; import { IDL } from '@dfinity/candid'; export * as Cbor from './cbor'; +export * from './polling'; export interface GlobalInternetComputer { ic: { diff --git a/packages/agent/src/polling/index.ts b/packages/agent/src/polling/index.ts index 2a18bc26..ccd399eb 100644 --- a/packages/agent/src/polling/index.ts +++ b/packages/agent/src/polling/index.ts @@ -5,6 +5,7 @@ import { RequestId } from '../request_id'; import { toHex } from '../utils/buffer'; export * as strategy from './strategy'; +import { defaultStrategy } from './strategy'; export { defaultStrategy } from './strategy'; export type PollStrategy = ( canisterId: Principal, @@ -27,7 +28,7 @@ export async function pollForResponse( agent: Agent, canisterId: Principal, requestId: RequestId, - strategy: PollStrategy, + strategy: PollStrategy = defaultStrategy(), // eslint-disable-next-line request?: any, blsVerify?: CreateCertificateOptions['blsVerify'], From 19e2f8f856edb4fb5f4dee652d3996df282b1feb Mon Sep 17 00:00:00 2001 From: Kai Peacock Date: Tue, 10 Sep 2024 01:27:11 -0700 Subject: [PATCH 2/3] feat: multi-actor config (#916) --- docs/CHANGELOG.md | 1 + packages/use-auth-client/README.md | 22 +++++++ .../candid/ivcos-eqaaa-aaaab-qablq-cai.did | 3 + .../examples/auth-demo/deps/init.json | 8 +++ .../examples/auth-demo/deps/pulled.json | 13 ++++ .../examples/auth-demo/dfx.json | 6 +- .../src/{App.jsx => App.tsx} | 51 +++++++++++---- .../src/auth-demo-frontend/tsconfig.json | 2 +- .../use-auth-client/src/use-auth-client.ts | 63 ++++++++++++++++--- .../test/use-auth-client.test.tsx | 59 ++++++++++++++++- 10 files changed, 203 insertions(+), 25 deletions(-) create mode 100644 packages/use-auth-client/examples/auth-demo/deps/candid/ivcos-eqaaa-aaaab-qablq-cai.did create mode 100644 packages/use-auth-client/examples/auth-demo/deps/init.json create mode 100644 packages/use-auth-client/examples/auth-demo/deps/pulled.json rename packages/use-auth-client/examples/auth-demo/src/auth-demo-frontend/src/{App.jsx => App.tsx} (54%) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index af214b85..35bd9235 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added +- feat: allow creation of multiple Actors in `useAuthClient` by passing a record to `actorOptions` with the actor name as the key, and `CreateActorOptions` as the value - feat: sync_call support in HttpAgent and Actor - Skips polling if the sync call succeeds and provides a certificate - Falls back to v2 api if the v3 endpoint 404's diff --git a/packages/use-auth-client/README.md b/packages/use-auth-client/README.md index 09533833..cec8432c 100644 --- a/packages/use-auth-client/README.md +++ b/packages/use-auth-client/README.md @@ -36,6 +36,28 @@ const App = () => { } ``` +## Multiple Actors + +If you have multiple actors, you can pass a record of `actorOptions` to the `useAuthClient` hook. The keys of the record will be the names of the actors, and the values will be the `actorOptions` for that actor. It will look something like this: + +```ts +const { isAuthenticated, login, logout, actors } = useAuthClient({ + actors: { + actor1: { + canisterId: canisterId1, + idlFactory: idlFactory1, + }, + actor2: { + canisterId: canisterId2, + idlFactory: idlFactory2, + }, + }, +}); + +const { actor1, actor2 } = actors; + +``` + There is a live demo at https://5ibdo-haaaa-aaaab-qajia-cai.icp0.io/ Additional generated documentaion is available at https://agent-js.icp.xyz/use-auth-client/index.html diff --git a/packages/use-auth-client/examples/auth-demo/deps/candid/ivcos-eqaaa-aaaab-qablq-cai.did b/packages/use-auth-client/examples/auth-demo/deps/candid/ivcos-eqaaa-aaaab-qablq-cai.did new file mode 100644 index 00000000..b2a2e50c --- /dev/null +++ b/packages/use-auth-client/examples/auth-demo/deps/candid/ivcos-eqaaa-aaaab-qablq-cai.did @@ -0,0 +1,3 @@ +service : { + whoami: () -> (principal) query; +} diff --git a/packages/use-auth-client/examples/auth-demo/deps/init.json b/packages/use-auth-client/examples/auth-demo/deps/init.json new file mode 100644 index 00000000..0ecb8de6 --- /dev/null +++ b/packages/use-auth-client/examples/auth-demo/deps/init.json @@ -0,0 +1,8 @@ +{ + "canisters": { + "ivcos-eqaaa-aaaab-qablq-cai": { + "arg_str": null, + "arg_raw": null + } + } +} \ No newline at end of file diff --git a/packages/use-auth-client/examples/auth-demo/deps/pulled.json b/packages/use-auth-client/examples/auth-demo/deps/pulled.json new file mode 100644 index 00000000..4043b79c --- /dev/null +++ b/packages/use-auth-client/examples/auth-demo/deps/pulled.json @@ -0,0 +1,13 @@ +{ + "canisters": { + "ivcos-eqaaa-aaaab-qablq-cai": { + "name": "whoami", + "wasm_hash": "a5af74d01aec228c5a717dfb43f773917e1a9138e512431aafcd225ad0001a8b", + "wasm_hash_download": "88f0162fa446ad32e08e7ee513a85a82f145d16a9ebb6d2adfa9bc5ff5605f74", + "init_guide": "null", + "init_arg": null, + "candid_args": "()", + "gzip": false + } + } +} \ No newline at end of file diff --git a/packages/use-auth-client/examples/auth-demo/dfx.json b/packages/use-auth-client/examples/auth-demo/dfx.json index d7c7b4e5..fa4991c6 100644 --- a/packages/use-auth-client/examples/auth-demo/dfx.json +++ b/packages/use-auth-client/examples/auth-demo/dfx.json @@ -14,6 +14,10 @@ "type": "assets", "workspace": "auth-demo-frontend" }, + "whoami": { + "type": "pull", + "id": "ivcos-eqaaa-aaaab-qablq-cai" + }, "internet_identity": { "candid": "https://github.com/dfinity/internet-identity/releases/latest/download/internet_identity.did", "frontend": {}, @@ -34,4 +38,4 @@ }, "output_env_file": ".env", "version": 1 -} \ No newline at end of file +} diff --git a/packages/use-auth-client/examples/auth-demo/src/auth-demo-frontend/src/App.jsx b/packages/use-auth-client/examples/auth-demo/src/auth-demo-frontend/src/App.tsx similarity index 54% rename from packages/use-auth-client/examples/auth-demo/src/auth-demo-frontend/src/App.jsx rename to packages/use-auth-client/examples/auth-demo/src/auth-demo-frontend/src/App.tsx index d51322af..0b716f7f 100644 --- a/packages/use-auth-client/examples/auth-demo/src/auth-demo-frontend/src/App.jsx +++ b/packages/use-auth-client/examples/auth-demo/src/auth-demo-frontend/src/App.tsx @@ -1,10 +1,28 @@ -import { useState } from 'react'; -import { idlFactory, canisterId } from 'declarations/auth-demo-backend'; +import { FormEvent, useState } from 'react'; +import { + idlFactory as helloFactory, + canisterId as helloId, +} from '../../declarations/auth-demo-backend'; +import { _SERVICE as HELLO_SERVICE } from '../../declarations/auth-demo-backend/auth-demo-backend.did'; +import { + idlFactory as whoamiFactory, + canisterId as whoamiId, +} from '../../declarations/auth-demo-backend'; +import { _SERVICE as WHOAMI_SERVICE } from '../../declarations/auth-demo-backend/auth-demo-backend.did'; import { useAuthClient } from '../../../../../src/index'; +import type { ActorSubclass } from '@dfinity/agent'; import IILogo from './IILogo.svg'; +export interface ProcessEnv { + [key: string]: string | undefined; +} + +declare var process: { + env: ProcessEnv; +}; + /** - * + * * @returns app */ function App() { @@ -15,23 +33,34 @@ function App() { `http://${process.env.CANISTER_ID_INTERNET_IDENTITY}.localhost:4943` : 'https://identity.ic0.app'; - const { isAuthenticated, login, logout, actor } = useAuthClient({ + const { isAuthenticated, login, logout, actors } = useAuthClient({ loginOptions: { identityProvider, }, actorOptions: { - canisterId, - idlFactory, + whoami_canister: { + canisterId: whoamiId, + idlFactory: whoamiFactory, + }, + greet_canister: { + canisterId: helloId, + idlFactory: helloFactory, + }, }, }); + const { whoami_canister, greet_canister } = actors as unknown as { + whoami_canister: ActorSubclass; + greet_canister: ActorSubclass; + }; + const [greeting, setGreeting] = useState(''); const [whoamiText, setWhoamiText] = useState(''); - function handleSubmit(event) { + function handleSubmit(event: FormEvent) { event.preventDefault(); - const name = event.target.elements.name.value; - actor.greet(name).then(greeting => { + const name = (event.target as HTMLFormElement).querySelector('input')?.value || ''; + greet_canister.greet(name).then(greeting => { setGreeting(greeting); }); return false; @@ -61,8 +90,8 @@ function App() {

{isAuthenticated ? 'You are logged in' : 'You are not logged in'}