add keystore read logic

This commit is contained in:
Sasha 2023-10-27 15:52:28 +02:00
parent eecd6a29b9
commit 4183b2b13f
No known key found for this signature in database
4 changed files with 129 additions and 71 deletions

View File

@ -3,11 +3,15 @@ import { Block, BlockTypes } from "@/components/Block";
import { Button } from "@/components/Button";
import { Subtitle } from "@/components/Subtitle";
import { useStore, useWallet } from "@/hooks";
import { useKeystore } from "@/hooks/useKeystore";
export const Keystore: React.FunctionComponent<{}> = () => {
const { keystorePassword, setKeystorePassword, keystoreCredentials } =
useStore();
const { onGenerateCredentials, onRegisterCredentials } = useWallet();
const { keystoreCredentials } = useStore();
const { onGenerateCredentials } = useWallet();
const { onReadCredentials, onRegisterCredentials } = useKeystore();
const { password, onPasswordChanged } = usePassword();
const { selectedKeystore, onKeystoreChanged } = useSelectedKeystore();
const credentialsNodes = React.useMemo(
() =>
@ -19,13 +23,6 @@ export const Keystore: React.FunctionComponent<{}> = () => {
[keystoreCredentials]
);
const onPasswordChanged = React.useCallback(
(event: React.FormEvent<HTMLInputElement>) => {
setKeystorePassword(event.currentTarget.value);
},
[setKeystorePassword]
);
return (
<Block className="mt-10">
<Block type={BlockTypes.FlexHorizontal}>
@ -45,8 +42,8 @@ export const Keystore: React.FunctionComponent<{}> = () => {
</label>
<input
type="text"
value={password}
id="keystore-input"
value={keystorePassword || ""}
onChange={onPasswordChanged}
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm w-full rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
/>
@ -57,7 +54,10 @@ export const Keystore: React.FunctionComponent<{}> = () => {
<Button onClick={onGenerateCredentials}>
Generate new credentials
</Button>
<Button className="ml-5" onClick={onRegisterCredentials}>
<Button
className="ml-5"
onClick={() => onRegisterCredentials(password)}
>
Register credentials
</Button>
</Block>
@ -65,12 +65,43 @@ export const Keystore: React.FunctionComponent<{}> = () => {
<Block className="mt-4">
<p className="text-s">Read from Keystore</p>
<Block type={BlockTypes.FlexHorizontal}>
<select className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-3/4 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
<select
value={selectedKeystore}
onChange={onKeystoreChanged}
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-3/4 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
>
{credentialsNodes}
</select>
<Button>Read credentials</Button>
<Button onClick={() => onReadCredentials(selectedKeystore, password)}>
Read credentials
</Button>
</Block>
</Block>
</Block>
);
};
function usePassword() {
const [password, setPassword] = React.useState<string>("");
const onPasswordChanged = (event: React.FormEvent<HTMLInputElement>) => {
setPassword(event.currentTarget.value);
};
return {
password,
onPasswordChanged,
};
}
function useSelectedKeystore() {
const [selectedKeystore, setKeystore] = React.useState<string>("");
const onKeystoreChanged = (event: React.FormEvent<HTMLSelectElement>) => {
setKeystore(event.currentTarget.value || "");
};
return {
selectedKeystore,
onKeystoreChanged,
};
}

View File

@ -0,0 +1,83 @@
import React from "react";
import { useStore } from "./useStore";
import { useRLN } from "./useRLN";
import { SEPOLIA_CONTRACT } from "@waku/rln";
import { StatusEventPayload } from "@/services/rln";
type UseKeystoreResult = {
onReadCredentials: (hash: string, password: string) => void;
onRegisterCredentials: (password: string) => void;
};
export const useKeystore = (): UseKeystoreResult => {
const { rln } = useRLN();
const {
credentials,
setActiveCredential,
setActiveMembershipID,
setAppStatus,
setCredentials,
} = useStore();
const onRegisterCredentials = React.useCallback(
async (password: string) => {
if (!credentials || !rln?.rlnContract || !password) {
return;
}
try {
setAppStatus(StatusEventPayload.CREDENTIALS_REGISTERING);
const membershipInfo = await rln.rlnContract.registerWithKey(
credentials
);
const membershipID = membershipInfo!.index.toNumber();
const keystoreHash = await rln.keystore.addCredential(
{
membership: {
treeIndex: membershipID,
chainId: SEPOLIA_CONTRACT.chainId,
address: SEPOLIA_CONTRACT.address,
},
identity: credentials,
},
password
);
setActiveCredential(keystoreHash);
setActiveMembershipID(membershipID);
rln.saveKeystore();
setAppStatus(StatusEventPayload.CREDENTIALS_REGISTERED);
} catch (error) {
setAppStatus(StatusEventPayload.CREDENTIALS_FAILURE);
console.error("Failed to register to RLN Contract: ", error);
return;
}
},
[credentials, rln, setActiveCredential, setActiveMembershipID, setAppStatus]
);
const onReadCredentials = React.useCallback(
async (hash: string, password: string) => {
if (!rln || !hash || !password) {
return;
}
try {
const record = await rln.keystore.readCredential(hash, password);
if (record) {
setCredentials(record.identity);
setActiveCredential(hash);
setActiveMembershipID(record.membership.treeIndex);
}
} catch (error) {
console.error("Failed to read credentials from Keystore.");
return;
}
},
[rln, setActiveCredential, setActiveMembershipID, setCredentials]
);
return {
onRegisterCredentials,
onReadCredentials,
};
};

View File

@ -13,8 +13,6 @@ type StoreResult = {
credentials: undefined | IdentityCredential;
setCredentials: (v: undefined | IdentityCredential) => void;
keystorePassword: undefined | string;
setKeystorePassword: (v: string) => void;
activeCredential: string;
keystoreCredentials: string[];
setKeystoreCredentials: (v: string[]) => void;
@ -52,9 +50,6 @@ export const useStore = create<StoreResult>((set) => {
};
const keystoreModule = {
keystorePassword: undefined,
setKeystorePassword: (v: string) =>
set((state) => ({ ...state, keystorePassword: v })),
activeCredential: DEFAULT_VALUE,
setActiveCredential: (v: string) =>
set((state) => ({ ...state, activeCredential: v })),

View File

@ -3,27 +3,15 @@ import { useStore } from "./useStore";
import { isEthereumEvenEmitterValid } from "@/utils/ethereum";
import { useRLN } from "./useRLN";
import { SIGNATURE_MESSAGE } from "@/constants";
import { SEPOLIA_CONTRACT } from "@waku/rln";
import { StatusEventPayload } from "@/services/rln";
type UseWalletResult = {
onConnectWallet: () => void;
onGenerateCredentials: () => void;
onRegisterCredentials: () => void;
};
export const useWallet = (): UseWalletResult => {
const { rln } = useRLN();
const {
keystorePassword,
credentials,
setEthAccount,
setChainID,
setCredentials,
setActiveCredential,
setActiveMembershipID,
setAppStatus,
} = useStore();
const { setEthAccount, setChainID, setCredentials } = useStore();
React.useEffect(() => {
const ethereum = window.ethereum;
@ -81,48 +69,9 @@ export const useWallet = (): UseWalletResult => {
setCredentials(credentials);
}, [rln, setCredentials]);
const onRegisterCredentials = React.useCallback(async () => {
if (!credentials || !rln?.rlnContract || !keystorePassword) {
return;
}
try {
setAppStatus(StatusEventPayload.CREDENTIALS_REGISTERING);
const membershipInfo = await rln.rlnContract.registerWithKey(credentials);
const membershipID = membershipInfo!.index.toNumber();
const keystoreHash = await rln.keystore.addCredential(
{
membership: {
treeIndex: membershipID,
chainId: SEPOLIA_CONTRACT.chainId,
address: SEPOLIA_CONTRACT.address,
},
identity: credentials,
},
keystorePassword
);
setActiveCredential(keystoreHash);
setActiveMembershipID(membershipID);
rln.saveKeystore();
setAppStatus(StatusEventPayload.CREDENTIALS_REGISTERED);
} catch (error) {
setAppStatus(StatusEventPayload.CREDENTIALS_FAILURE);
console.error("Failed to register to RLN Contract: ", error);
return;
}
}, [
credentials,
rln,
keystorePassword,
setActiveCredential,
setActiveMembershipID,
setAppStatus,
]);
return {
onConnectWallet,
onGenerateCredentials,
onRegisterCredentials,
};
};