From 043efa351d0e9961a816e9f88fbf6b6a0a3cef1b Mon Sep 17 00:00:00 2001 From: Kai Peacock Date: Thu, 8 Aug 2024 14:38:25 -0700 Subject: [PATCH] feat: multi-actor config --- docs/CHANGELOG.md | 1 + package-lock.json | 2 +- 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 ++++++++++++++++- 11 files changed, 204 insertions(+), 26 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 d4bb990e..e481de41 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: management canister interface updates for schnorr signatures - feat: ensure that identity-secp256k1 seed phrase must produce a 64 byte seed - docs: documentation and metadata for use-auth-client diff --git a/package-lock.json b/package-lock.json index c59fc595..509e626f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19403,7 +19403,7 @@ "packages/use-auth-client": { "name": "@dfinity/use-auth-client", "version": "2.0.0", - "license": "ISC", + "license": "Apache-2.0", "dependencies": { "@dfinity/agent": "^2.0.0", "@dfinity/auth-client": "^2.0.0", 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'}