From 0f10e0f2749ea1513978213c4de7c04dd6152c1d Mon Sep 17 00:00:00 2001 From: Saharsh Khicha <71884962+SaharshKhicha18@users.noreply.github.com> Date: Tue, 17 Sep 2024 16:11:07 +0800 Subject: [PATCH] Add Internet Identity auth --- src/App.tsx | 119 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 87 insertions(+), 32 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index d80bbf8..79afe9c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,7 +6,8 @@ import reactLogo from './assets/bob.png'; import viteLogo from './assets/vite.svg'; import { useQueryCall, useUpdateCall } from '@ic-reactor/react'; import { Principal } from '@dfinity/principal'; -import {Agent, Actor} from '@dfinity/agent'; +import {Agent, Actor, Identity, HttpAgent} from '@dfinity/agent'; +import { AuthClient } from "@dfinity/auth-client"; import { idlFactory as icpFactory} from './declarations/nns-ledger'; import { _SERVICE as icpService } from './declarations/nns-ledger/index.d'; @@ -42,6 +43,8 @@ function App() { const [icpActor, setIcpActor] = useState<icpService | null>(null); const [bobLedgerActor, setBobLedgerActor] = useState<icpService | null>(null); const [yourPrincipal, setYourPrincipal] = useState<string>("null"); + const [II, setII] = useState<Identity>(); + const [IIAuthClient, setIIAuthClient] = useState<AuthClient>(); function bigintToFloatString(bigintValue : bigint, decimals = 8) { const stringValue = bigintValue.toString(); @@ -119,8 +122,8 @@ function App() { }, [isConnected]); const fetchPrincipal = async () => { - if(!(await window.ic.plug.agent)) return; - setYourPrincipal((await window.ic.plug.agent.getPrincipal()).toString()); + if(!isConnected) return; + setYourPrincipal(await window.ic.plug.isConnected() ? (await window.ic.plug.agent.getPrincipal()).toString() : (II?.getPrincipal())?.toString()); }; const fetchStats = async () => { @@ -161,29 +164,54 @@ function App() { console.log("Setting up actors...", icpCanisterID, bobCanisterID, bobLedgerID, pbobCanisterID); - const getICPActor = await window.ic.plug.createActor({ + const getICPActor = await window.ic.plug.isConnected() ? window.ic.plug.createActor({ canisterId: icpCanisterID, interfaceFactory:icpFactory, - }) + }) : + Actor.createActor(icpFactory, { + agent: new HttpAgent({ + identity: II, + }), + canisterId: icpCanisterID, + }); + await setIcpActor(getICPActor); - const getPBOBActor = await window.ic.plug.createActor({ + const getPBOBActor = await window.ic.plug.isConnected() ? await window.ic.plug.createActor({ canisterId: pbobCanisterID, interfaceFactory: pbobFactory, - }) + }) : + Actor.createActor(pbobFactory, { + agent: new HttpAgent({ + identity: II, + }), + canisterId: pbobCanisterID, + }); await setPBobActor(getPBOBActor); - await setBobActor(await window.ic.plug.createActor({ + await setBobActor(await window.ic.plug.isConnected() ? await window.ic.plug.createActor({ canisterId: bobCanisterID, interfaceFactory: bobFactory, + }) : + Actor.createActor(bobFactory, { + agent: new HttpAgent({ + identity: II, + }), + canisterId: bobCanisterID, })); - await setBobLedgerActor(await window.ic.plug.createActor({ + await setBobLedgerActor(await window.ic.plug.isConnected() ? await window.ic.plug.createActor({ canisterId: bobLedgerID, interfaceFactory: icpFactory, + }) : + Actor.createActor(icpFactory, { + agent: new HttpAgent({ + identity: II, + }), + canisterId: bobLedgerID, })); console.log("actors", icpActor, bobLedgerActor, bobActor); @@ -202,7 +230,7 @@ function App() { let icpBalance = await icpActor.icrc1_balance_of({ - owner: await window.ic.plug.agent.getPrincipal(), + owner: await window.ic.plug.isConnected() ? await window.ic.plug.agent.getPrincipal() : II?.getPrincipal(), subaccount: [], }); await setIcpBalance(icpBalance); @@ -210,14 +238,14 @@ function App() { console.log("Fetching balances...", icpBalance); let bobLedgerBalance = await bobLedgerActor.icrc1_balance_of({ - owner: await window.ic.plug.agent.getPrincipal(), + owner: await window.ic.plug.isConnected() ? await window.ic.plug.agent.getPrincipal() : II?.getPrincipal(), subaccount: [], }); console.log("Fetching balances...", bobLedgerBalance); let pbobLedgerBalance = await pbobActor.icrc1_balance_of({ - owner: await window.ic.plug.agent.getPrincipal(), + owner: await window.ic.plug.isConnected() ? await window.ic.plug.agent.getPrincipal() : II?.getPrincipal(), subaccount: [], }); @@ -226,7 +254,7 @@ function App() { console.log("Fetching balances...", pbobLedgerBalance); let share = await pbobActor.get_share_of({ - owner: await window.ic.plug.agent.getPrincipal(), + owner: await window.ic.plug.isConnected() ? await window.ic.plug.agent.getPrincipal() : II?.getPrincipal(), subaccount: [], }); @@ -245,8 +273,14 @@ function App() { const handleLogout = async () => { setLoading(true); try { - await window.ic.plug.disconnect(); - setIsConnected(false); + if (!await window.ic.plug.isConnected()) { + await IIAuthClient?.logout() + setIsConnected(false); + } else { + await window.ic.plug.disconnect(); + setIsConnected(false); + } + } catch (error) { console.error('Logout failed:', error); } finally { @@ -254,26 +288,44 @@ function App() { } }; - const handleLogin = async () => { + const handleLogin = async (auth: string) => { setLoading(true); try { - const connected = await window.ic.plug.isConnected(); - if (!connected) { - let pubkey = await window.ic.plug.requestConnect({ - // whitelist, host, and onConnectionUpdate need to be defined or imported appropriately - whitelist: [bobCanisterID, icpCanisterID, bobLedgerID, pbobCanisterID], - host: "https://ic0.app", - onConnectionUpdate: async () => { - console.log("Connection updated", await window.ic.plug.isConnected()); - await setIsConnected(!!await window.ic.plug.isConnected()); + if (auth == "ii") { + const authClient = await AuthClient.create(); + authClient.login({ + // 7 days in nanoseconds + maxTimeToLive: BigInt(7 * 24 * 60 * 60 * 1000 * 1000 * 1000), + onSuccess: async () => { + setIsConnected(true) }, }); - console.log("Connected with pubkey:", pubkey); - await setIsConnected(true); + setIIAuthClient(authClient); + const identity = authClient.getIdentity(); + setII(identity) + console.log("Hello", authClient.isAuthenticated(), identity) } else { - setIsConnected(true); - //await handleLogin(); - }; + if (auth == 'plug') { + const connected = await window.ic.plug.isConnected(); + if (!connected) { + let pubkey = await window.ic.plug.requestConnect({ + // whitelist, host, and onConnectionUpdate need to be defined or imported appropriately + whitelist: [bobCanisterID, icpCanisterID, bobLedgerID, pbobCanisterID], + host: "https://ic0.app", + onConnectionUpdate: async () => { + console.log("Connection updated", await window.ic.plug.isConnected()); + setIsConnected(!!await window.ic.plug.isConnected()); + }, + }); + console.log("Connected with pubkey:", pubkey); + setIsConnected(true); + } else { + setIsConnected(true); + //await handleLogin(); + }; + } + } + } catch (error) { console.error('Login failed:', error); setIsConnected(false); @@ -412,7 +464,7 @@ function App() { try { // Assuming icpActor and icdvActor are already initialized actors const withdrawResult = await pbobActor.withdraw({ - owner: await window.ic.plug.agent.getPrincipal(), + owner: await window.ic.plug.isConnected() ? await window.ic.plug.agent.getPrincipal() : II?.getPrincipal(), subaccount: [], }); @@ -489,7 +541,10 @@ function App() { <div className="card"> {!isConnected ? ( - <button onClick={handleLogin} disabled={loading}>Login with Plug</button> + <> + <button onClick={() => handleLogin('plug')} disabled={loading}>Login with Plug</button> + <button onClick={() => handleLogin('ii')} disabled={loading}>Login with Internet Identity</button> + </> ) : ( <> <button onClick={handleLogout} disabled={loading}>Logout</button>