diff --git a/tools/walletextension/frontend/src/api/gateway.ts b/tools/walletextension/frontend/src/api/gateway.ts index 47b087d214..35a0610329 100644 --- a/tools/walletextension/frontend/src/api/gateway.ts +++ b/tools/walletextension/frontend/src/api/gateway.ts @@ -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, @@ -33,34 +58,37 @@ export async function fetchVersion(): Promise { export async function accountIsAuthenticated( userID: string, account: string -): Promise { - return await httpRequest({ +): Promise { + return await httpRequest({ 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 { + if (!userID) { + return; + } try { const isAuthenticated = await accountIsAuthenticated(userID, account); - if (isAuthenticated) { + if (isAuthenticated.status) { return "Account is already authenticated"; } const data = { @@ -89,15 +117,14 @@ 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 { @@ -105,7 +132,7 @@ export async function revokeAccountsApi(userID: string): Promise { method: "get", url: pathToUrl(apiRoutes.revoke), searchParams: { - u: userID, + token: userID, }, }); } @@ -118,8 +145,11 @@ export async function joinTestnet(): Promise { } export async function addNetworkToMetaMask(rpcUrls: string[]) { + if (!ethereum) { + return; + } try { - await (window as any).ethereum.request({ + await ethereum.request({ method: requestMethods.addNetwork, params: [ { diff --git a/tools/walletextension/frontend/src/components/modules/home/connected.tsx b/tools/walletextension/frontend/src/components/modules/home/connected.tsx index 65514a6e82..08c6636267 100644 --- a/tools/walletextension/frontend/src/components/modules/home/connected.tsx +++ b/tools/walletextension/frontend/src/components/modules/home/connected.tsx @@ -41,7 +41,7 @@ const Connected = () => { Account - Connected + Authenticated diff --git a/tools/walletextension/frontend/src/components/providers/wallet-provider.tsx b/tools/walletextension/frontend/src/components/providers/wallet-provider.tsx index 3e44036477..f85edca95b 100644 --- a/tools/walletextension/frontend/src/components/providers/wallet-provider.tsx +++ b/tools/walletextension/frontend/src/components/providers/wallet-provider.tsx @@ -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(null); @@ -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); } @@ -68,7 +72,6 @@ export const WalletConnectionProvider = ({ }, []); const checkIfMetamaskIsLoaded = async () => { - const { ethereum } = window as any; if (ethereum) { await handleEthereum(); } else { @@ -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); @@ -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); } @@ -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 () => { @@ -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( @@ -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."); diff --git a/tools/walletextension/frontend/src/lib/constants.ts b/tools/walletextension/frontend/src/lib/constants.ts index 8da38091e6..3f9e6fcb70 100644 --- a/tools/walletextension/frontend/src/lib/constants.ts +++ b/tools/walletextension/frontend/src/lib/constants.ts @@ -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 = { @@ -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; @@ -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", - }, -}; diff --git a/tools/walletextension/frontend/src/routes/index.ts b/tools/walletextension/frontend/src/routes/index.ts index 0fa649e4d5..1b27864791 100644 --- a/tools/walletextension/frontend/src/routes/index.ts +++ b/tools/walletextension/frontend/src/routes/index.ts @@ -16,4 +16,5 @@ export const requestMethods = { switchNetwork: "wallet_switchEthereumChain", addNetwork: "wallet_addEthereumChain", getStorageAt: "eth_getStorageAt", + signTypedData: "eth_signTypedData_v4", }; diff --git a/tools/walletextension/frontend/src/services/useGatewayService.ts b/tools/walletextension/frontend/src/services/useGatewayService.ts index 44d16889e8..a28428d4e4 100644 --- a/tools/walletextension/frontend/src/services/useGatewayService.ts +++ b/tools/walletextension/frontend/src/services/useGatewayService.ts @@ -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"); @@ -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); } @@ -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}`); } diff --git a/tools/walletextension/frontend/src/types/interfaces/GatewayInterfaces.ts b/tools/walletextension/frontend/src/types/interfaces/GatewayInterfaces.ts new file mode 100644 index 0000000000..8e1465a485 --- /dev/null +++ b/tools/walletextension/frontend/src/types/interfaces/GatewayInterfaces.ts @@ -0,0 +1,3 @@ +export type AuthenticationResponse = { + status: boolean; +}; diff --git a/tools/walletextension/frontend/src/types/interfaces/WalletInterfaces.ts b/tools/walletextension/frontend/src/types/interfaces/WalletInterfaces.ts index bcd9450990..b01bc25f08 100644 --- a/tools/walletextension/frontend/src/types/interfaces/WalletInterfaces.ts +++ b/tools/walletextension/frontend/src/types/interfaces/WalletInterfaces.ts @@ -9,7 +9,10 @@ export interface WalletConnectionContextType { provider: ethers.providers.Web3Provider | null; version: string | null; revokeAccounts: () => void; - getAccounts: (provider: ethers.providers.Web3Provider) => Promise; + getAccounts: ( + provider: ethers.providers.Web3Provider, + userID: string + ) => Promise; loading: boolean; }