Skip to content

Commit

Permalink
refactor: account signing and authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
Jennievon committed Nov 29, 2023
1 parent 1891fac commit e30d285
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 63 deletions.
62 changes: 46 additions & 16 deletions tools/walletextension/frontend/src/api/gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,39 @@ import { httpRequest } from ".";
import { pathToUrl } from "../routes/router";
import { getNetworkName } from "../lib/utils";
import {
metamaskPersonalSign,
tenChainIDHex,
tenscanLink,
nativeCurrency,
typedData,
tenChainIDDecimal,
} from "../lib/constants";
import { AuthenticationResponse } from "@/types/interfaces/GatewayInterfaces";

const typedData = {
types: {
EIP712Domain: [
{ name: "name", type: "string" },
{ name: "version", type: "string" },
{ name: "chainId", type: "uint256" },
],
Authentication: [{ name: "Encryption Token", type: "address" }],
},
primaryType: "Authentication",
domain: {
name: "Ten",
version: "1.0",
chainId: tenChainIDDecimal,
},
message: {
"Encryption Token": "0x",
},
};

const { ethereum } = typeof window !== "undefined" ? window : ({} as any);

export async function switchToTenNetwork() {
if (!ethereum) {
return;
}
try {
await (window as any).ethereum.request({
method: requestMethods.switchNetwork,
Expand All @@ -33,34 +58,37 @@ export async function fetchVersion(): Promise<string> {
export async function accountIsAuthenticated(
userID: string,
account: string
): Promise<boolean> {
return await httpRequest<boolean>({
): Promise<AuthenticationResponse> {
return await httpRequest<AuthenticationResponse>({
method: "get",
url: pathToUrl(apiRoutes.queryAccountUserID),
searchParams: {
u: userID,
token: userID,
a: account,
},
});
}

const getSignature = async (account: string, data: any) => {
const { ethereum } = window as any;
const signature = await ethereum.request({
method: metamaskPersonalSign,
if (!ethereum) {
return;
}
return await ethereum.request({
method: requestMethods.signTypedData,
params: [account, JSON.stringify(data)],
});

return signature;
};

export async function authenticateAccountWithTenGatewayEIP712(
userID: string,
account: string
): Promise<any> {
if (!userID) {
return;
}
try {
const isAuthenticated = await accountIsAuthenticated(userID, account);
if (isAuthenticated) {
if (isAuthenticated.status) {
return "Account is already authenticated";
}
const data = {
Expand Down Expand Up @@ -89,23 +117,22 @@ const authenticateUser = async (
address: string;
}
) => {
const authenticateResp = await httpRequest({
return await httpRequest({
method: "post",
url: pathToUrl(apiRoutes.authenticate),
data: authenticateFields,
searchParams: {
u: userID,
token: userID,
},
});
return authenticateResp;
};

export async function revokeAccountsApi(userID: string): Promise<string> {
return await httpRequest<string>({
method: "get",
url: pathToUrl(apiRoutes.revoke),
searchParams: {
u: userID,
token: userID,
},
});
}
Expand All @@ -118,8 +145,11 @@ export async function joinTestnet(): Promise<string> {
}

export async function addNetworkToMetaMask(rpcUrls: string[]) {
if (!ethereum) {
return;
}
try {
await (window as any).ethereum.request({
await ethereum.request({
method: requestMethods.addNetwork,
params: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const Connected = () => {
<TableHeader>
<TableRow>
<TableHead>Account</TableHead>
<TableHead>Connected</TableHead>
<TableHead>Authenticated</TableHead>
<TableHead></TableHead>
</TableRow>
</TableHeader>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { METAMASK_CONNECTION_TIMEOUT } from "../../lib/constants";
import { requestMethods } from "@/routes";
import { ToastType } from "@/types/interfaces";

const { ethereum } = typeof window !== "undefined" ? window : ({} as any);

const WalletConnectionContext =
createContext<WalletConnectionContextType | null>(null);

Expand All @@ -45,8 +47,10 @@ export const WalletConnectionProvider = ({
const [provider, setProvider] = useState({} as ethers.providers.Web3Provider);

useEffect(() => {
const { ethereum } = window as any;
const handleAccountsChanged = async () => {
if (!ethereum) {
return;
}
if (userID && isValidUserIDFormat(userID)) {
await displayCorrectScreenBasedOnMetamaskAndUserID(userID, provider);
}
Expand All @@ -68,7 +72,6 @@ export const WalletConnectionProvider = ({
}, []);

const checkIfMetamaskIsLoaded = async () => {
const { ethereum } = window as any;
if (ethereum) {
await handleEthereum();
} else {
Expand All @@ -81,7 +84,6 @@ export const WalletConnectionProvider = ({
};

const handleEthereum = async () => {
const { ethereum } = window as any;
if (ethereum && ethereum.isMetaMask) {
const provider = new ethers.providers.Web3Provider(ethereum);
setProvider(provider);
Expand Down Expand Up @@ -133,7 +135,7 @@ export const WalletConnectionProvider = ({
setVersion(await fetchVersion());
if (await isTenChain()) {
if (userID) {
await getAccounts(provider);
await getAccounts(provider, userID);
} else {
setWalletConnected(false);
}
Expand All @@ -145,14 +147,30 @@ export const WalletConnectionProvider = ({
};

const connectAccount = async (account: string) => {
if (loading) {
return;
}

if (!userID) {
return;
}
await authenticateAccountWithTenGatewayEIP712(userID, account);
const { status } = await accountIsAuthenticated(userID, account);
if (status) {
showToast(ToastType.SUCCESS, "Account authenticated!");
setAccounts((accounts) => {
if (!accounts) {
return null;
}
return accounts.map((acc) => {
if (acc.name === account) {
return {
...acc,
connected: status,
};
}
return acc;
});
});
} else {
showToast(ToastType.DESTRUCTIVE, "Account authentication failed.");
}
};

const revokeAccounts = async () => {
Expand All @@ -167,7 +185,10 @@ export const WalletConnectionProvider = ({
}
};

const getAccounts = async (provider: ethers.providers.Web3Provider) => {
const getAccounts = async (
provider: ethers.providers.Web3Provider,
id: string
) => {
try {
if (!provider) {
showToast(
Expand All @@ -191,21 +212,22 @@ export const WalletConnectionProvider = ({
return;
}

for (const account of accounts) {
await authenticateAccountWithTenGatewayEIP712(userID, account);
}
let updatedAccounts: Account[] = [];

const updatedAccounts = await Promise.all(
accounts.map(async (account: string) => ({
for (let i = 0; i < accounts.length; i++) {
const account = accounts[i];
authenticateAccountWithTenGatewayEIP712(id, account);
const { status } = await accountIsAuthenticated(id, account);
updatedAccounts.push({
name: account,
connected: await accountIsAuthenticated(userID, account),
}))
);
connected: status,
});
}

setAccounts(updatedAccounts);
setWalletConnected(true);

showToast(ToastType.SUCCESS, "Accounts authenticated successfully!");
showToast(ToastType.SUCCESS, "Accounts authenticated");
} catch (error) {
console.error(error);
showToast(ToastType.DESTRUCTIVE, "An error occurred. Please try again.");
Expand Down
24 changes: 1 addition & 23 deletions tools/walletextension/frontend/src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const tenGatewayAddress = "https://testnet.obscu.ro";
export const tenGatewayAddress = "https://uat-testnet.obscu.ro";
export const tenscanLink = "https://testnet.tenscan.com";

export const socialLinks = {
Expand Down Expand Up @@ -35,8 +35,6 @@ export const userIDHexLength = 40;
export const tenGatewayVersion = "v1";
export const tenChainIDDecimal = 443;

export const metamaskPersonalSign = "personal_sign";

export const tenChainIDHex = "0x" + tenChainIDDecimal.toString(16); // Convert to hexadecimal and prefix with '0x'
export const METAMASK_CONNECTION_TIMEOUT = 3000;

Expand All @@ -45,23 +43,3 @@ export const nativeCurrency = {
symbol: "ETH",
decimals: 18,
};

export const typedData = {
types: {
EIP712Domain: [
{ name: "name", type: "string" },
{ name: "version", type: "string" },
{ name: "chainId", type: "uint256" },
],
Authentication: [{ name: "Encryption Token", type: "address" }],
},
primaryType: "Authentication",
domain: {
name: "Ten",
version: "1.0",
chainId: tenChainIDDecimal,
},
message: {
"Encryption Token": "0x",
},
};
1 change: 1 addition & 0 deletions tools/walletextension/frontend/src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ export const requestMethods = {
switchNetwork: "wallet_switchEthereumChain",
addNetwork: "wallet_addEthereumChain",
getStorageAt: "eth_getStorageAt",
signTypedData: "eth_signTypedData_v4",
};
15 changes: 11 additions & 4 deletions tools/walletextension/frontend/src/services/useGatewayService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ import { SWITCHED_CODE, tenGatewayVersion } from "../lib/constants";
import { getRPCFromUrl, isTenChain, isValidUserIDFormat } from "../lib/utils";
import { requestMethods } from "../routes";

const { ethereum } = typeof window !== "undefined" ? window : ({} as any);

const useGatewayService = () => {
const { provider } = useWalletConnection();
const { userID, setUserID, getAccounts } = useWalletConnection();

const connectAccounts = async () => {
if (!ethereum) {
return null;
}
try {
await (window as any).ethereum.request({
await ethereum.request({
method: requestMethods.connectAccounts,
});
showToast(ToastType.SUCCESS, "Connected to Ten Network");
Expand Down Expand Up @@ -57,7 +62,9 @@ const useGatewayService = () => {
) {
const user = await joinTestnet();
setUserID(user);
const rpcUrls = [`${getRPCFromUrl()}/${tenGatewayVersion}/?u=${user}`];
const rpcUrls = [
`${getRPCFromUrl()}/${tenGatewayVersion}/?token=${user}`,
];
await addNetworkToMetaMask(rpcUrls);
}

Expand All @@ -66,10 +73,10 @@ const useGatewayService = () => {
await connectAccounts();
}

if (!provider) {
if (!provider || !userID) {
return;
}
await getAccounts(provider);
await getAccounts(provider, userID);
} catch (error: any) {
showToast(ToastType.DESTRUCTIVE, `${error.message}`);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type AuthenticationResponse = {
status: boolean;
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ export interface WalletConnectionContextType {
provider: ethers.providers.Web3Provider | null;
version: string | null;
revokeAccounts: () => void;
getAccounts: (provider: ethers.providers.Web3Provider) => Promise<void>;
getAccounts: (
provider: ethers.providers.Web3Provider,
userID: string
) => Promise<void>;
loading: boolean;
}

Expand Down

0 comments on commit e30d285

Please sign in to comment.