Skip to content

Commit

Permalink
Add call to fetch user's canister (#239)
Browse files Browse the repository at this point in the history
* Update User template declaration in canister

* Update declarations with types in frontend

* Ignore declarations folders

* Add dummy Ids of declared canisters

* Add example env variable

* Ignore implicit any errors from ts

* Add userCanister to user store

* Update canisterId if logged in

* Update backend util to cache actor & use identity

* Add userCanisterPrincipal to auth and authHelper
  • Loading branch information
harsh-mn-yral authored Aug 27, 2022
1 parent 150b543 commit 08ea8c2
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 16 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ package
pnpm-lock.yaml
package-lock.json
yarn.lock
declarations
6 changes: 6 additions & 0 deletions canister_ids.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
{
"webclient": {
"ic": "vyatz-hqaaa-aaaam-qauea-cai"
},
"individual_user_template": {
"local": "rwlgt-iiaaa-aaaaa-aaaaa-cai"
},
"user_index": {
"local": "ryjl3-tyaaa-aaaaa-aaaba-cai"
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
type PostDetailsFromFrontend = record {
hashtags : vec text;
description : text;
video_url : text;
};
service : {
create_post : (text, vec text, text) -> (nat64);
create_post : (PostDetailsFromFrontend) -> (nat64);
mark_post_as_ready_to_view : (nat64) -> ();
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import type { Principal } from '@dfinity/principal';
import type { ActorMethod } from '@dfinity/agent';

export interface PostDetailsFromFrontend {
'hashtags' : Array<string>,
'description' : string,
'video_url' : string,
}
export interface _SERVICE {
'create_post' : ActorMethod<[string, Array<string>, string], bigint>,
'create_post' : ActorMethod<[PostDetailsFromFrontend], bigint>,
'mark_post_as_ready_to_view' : ActorMethod<[bigint], undefined>,
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
export const idlFactory = ({ IDL }) => {
const PostDetailsFromFrontend = IDL.Record({
'hashtags' : IDL.Vec(IDL.Text),
'description' : IDL.Text,
'video_url' : IDL.Text,
});
return IDL.Service({
'create_post' : IDL.Func(
[IDL.Text, IDL.Vec(IDL.Text), IDL.Text],
[IDL.Nat64],
[],
),
'create_post' : IDL.Func([PostDetailsFromFrontend], [IDL.Nat64], []),
'mark_post_as_ready_to_view' : IDL.Func([IDL.Nat64], [], []),
});
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Actor, HttpAgent } from "@dfinity/agent";

// Imports and re-exports candid interface
import { idlFactory } from './user_index.did.js';
export { idlFactory } from './user_index.did.js';
// CANISTER_ID is replaced by webpack based on node environment
export const canisterId = process.env.USER_INDEX_CANISTER_ID;

/**
*
* @param {string | import("@dfinity/principal").Principal} canisterId Canister ID of Agent
* @param {{agentOptions?: import("@dfinity/agent").HttpAgentOptions; actorOptions?: import("@dfinity/agent").ActorConfig}} [options]
* @return {import("@dfinity/agent").ActorSubclass<import("./user_index.did.js")._SERVICE>}
*/
export const createActor = (canisterId, options) => {
const agent = new HttpAgent(options ? { ...options.agentOptions } : {});

// Fetch root key for certificate validation during development
if (process.env.NODE_ENV !== "production") {
agent.fetchRootKey().catch(err => {
console.warn("Unable to fetch root key. Check to ensure that your local replica is running");
console.error(err);
});
}

// Creates an actor with using the candid interface and the HttpAgent
return Actor.createActor(idlFactory, {
agent,
canisterId,
...(options ? options.actorOptions : {}),
});
};

/**
* A ready-to-use agent for the user_index canister
* @type {import("@dfinity/agent").ActorSubclass<import("./user_index.did.js")._SERVICE>}
*/
export const user_index = createActor(canisterId);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { Principal } from '@dfinity/principal';
import type { ActorMethod } from '@dfinity/agent';

export interface _SERVICE {
'__comment_this_reset_user_canisters' : ActorMethod<[], undefined>,
'get_users_canister' : ActorMethod<[], Principal>,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const idlFactory = ({ IDL }) => {
return IDL.Service({
'__comment_this_reset_user_canisters' : IDL.Func([], [], []),
'get_users_canister' : IDL.Func([], [IDL.Principal], []),
});
};
export const init = ({ IDL }) => { return []; };
9 changes: 7 additions & 2 deletions packages/web-client/src/lib/authHelper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AuthClient } from '@dfinity/auth-client';
import { get } from 'svelte/store';
import { auth } from '../stores/auth';
import { userIndex } from './backend';

export async function initializeAuthClient(): Promise<void> {
let authStore = get(auth);
Expand All @@ -13,20 +14,24 @@ export async function initializeAuthClient(): Promise<void> {
}
const identity = authStore.client?.getIdentity();
const principal = await identity?.getPrincipal();
const userCanisterPrincipal = await userIndex().get_users_canister();

if (await authStore.client?.isAuthenticated()) {
auth.set({
client: authStore.client,
isLoggedIn: true,
identity,
principal,
showLogin: false
showLogin: false,
userCanisterPrincipal
});
} else {
auth.set({
client: authStore.client,
isLoggedIn: false,
principal,
showLogin: authStore.showLogin
showLogin: authStore.showLogin,
userCanisterPrincipal
});
}
}
54 changes: 48 additions & 6 deletions packages/web-client/src/lib/backend.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,52 @@
import { createActor, canisterId } from '../../declarations/backend';
import {
createActor as createUserIndexActor,
canisterId as userIndexCanisterId
} from '$canisters/user_index';
import { createActor as createIndividualUserActor } from '$canisters/individual_user_template';
import type { _SERVICE as _USER_INDEX_SERVICE } from '$canisters/user_index/user_index.did';
import type { _SERVICE as _INDIVIDUAL_USER_SERVICE } from '$canisters/individual_user_template/individual_user_template.did';
import { auth } from '$stores/auth';
import type { ActorSubclass } from '@dfinity/agent';
import { get } from 'svelte/store';

export const host =
process.env.NODE_ENV === 'development' ? 'http://localhost:8000' : 'https://ic0.app';

export const backend = createActor(canisterId ?? '', {
agentOptions: {
host
}
});
export type UserIndexActor = ActorSubclass<_USER_INDEX_SERVICE>;
export type IndividualUserCanister = ActorSubclass<_INDIVIDUAL_USER_SERVICE>;

const userIndexCanister: {
actor?: UserIndexActor;
loginState: boolean;
} = {
loginState: false
};

const individualUserCanister: {
actor?: IndividualUserCanister;
loginState: boolean;
} = {
loginState: false
};

export function userIndex(): UserIndexActor {
const authStore = get(auth);
if (!userIndexCanister.actor || userIndexCanister.loginState != authStore.isLoggedIn) {
userIndexCanister.actor = createUserIndexActor(userIndexCanisterId as string, {
agentOptions: { identity: authStore?.identity, host }
}) as UserIndexActor;
userIndexCanister.loginState = authStore.isLoggedIn;
return userIndexCanister.actor;
} else return userIndexCanister.actor;
}

export function individualUser(individualUserCanisterId: string): IndividualUserCanister {
const authStore = get(auth);
if (!individualUserCanister.actor || individualUserCanister.loginState != authStore.isLoggedIn) {
individualUserCanister.actor = createIndividualUserActor(individualUserCanisterId as string, {
agentOptions: { identity: authStore?.identity, host }
}) as IndividualUserCanister;
individualUserCanister.loginState = authStore.isLoggedIn;
return individualUserCanister.actor;
} else return individualUserCanister.actor;
}
1 change: 1 addition & 0 deletions packages/web-client/src/stores/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const auth = writable<{
identity?: Identity;
principal?: Principal;
showLogin: boolean;
userCanisterPrincipal?: Principal;
}>({
client: undefined,
isLoggedIn: false,
Expand Down
1 change: 1 addition & 0 deletions packages/web-client/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"composite": true,
"noImplicitAny": false,
"paths": {
"$lib": ["src/lib"],
"$lib/*": ["src/lib/*"],
Expand Down
3 changes: 2 additions & 1 deletion packages/web-client/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ export default ({ mode }) => {
// Here we can define global constants
// This is required for now because the code generated by dfx relies on process.env being set
...canisterDefinitions,
'process.env.NODE_ENV': JSON.stringify(isDev ? 'development' : 'production')
'process.env.NODE_ENV': JSON.stringify(isDev ? 'development' : 'production'),
'import.meta.env.IS_DEV': isDev
},
server: {
fs: {
Expand Down

0 comments on commit 08ea8c2

Please sign in to comment.