From 85b52895ec255527401319e628924b64da30f230 Mon Sep 17 00:00:00 2001 From: amnambiar Date: Tue, 25 Apr 2023 19:35:41 +0530 Subject: [PATCH 1/5] PLT-4591 Added support to sign timestamp with connected wallet --- react-web/src/api/onRequest.ts | 4 +- .../ConnectWallet/ConnectWallet.tsx | 44 ++++++++++++++++++- react-web/src/components/Header/Header.tsx | 3 +- react-web/src/store/slices/auth.slice.ts | 1 + 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/react-web/src/api/onRequest.ts b/react-web/src/api/onRequest.ts index b728609a..38f7fbb5 100644 --- a/react-web/src/api/onRequest.ts +++ b/react-web/src/api/onRequest.ts @@ -2,8 +2,8 @@ import { AxiosError, AxiosRequestConfig } from "axios"; // Add a request interceptor export function onRequest(config: AxiosRequestConfig) { - const address: any = localStorage.getItem('address'); - const TokenAuth = address; + const address: any = localStorage.getItem('authToken'); + const TokenAuth = 'Bearer ' + address; if (address) { config.headers = { diff --git a/react-web/src/components/ConnectWallet/ConnectWallet.tsx b/react-web/src/components/ConnectWallet/ConnectWallet.tsx index b9477583..114eeab9 100644 --- a/react-web/src/components/ConnectWallet/ConnectWallet.tsx +++ b/react-web/src/components/ConnectWallet/ConnectWallet.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState, useCallback } from "react"; import { Address } from "@emurgo/cardano-serialization-lib-browser"; import { useAppDispatch } from "store/store"; -import { getProfileDetails, setNetwork } from "store/slices/auth.slice"; +import { getProfileDetails, logout, setNetwork } from "store/slices/auth.slice"; import Modal from "components/Modal/Modal"; import Button from "components/Button/Button"; @@ -9,6 +9,7 @@ import Loader from "components/Loader/Loader"; import Toast from "components/Toast/Toast"; import './ConnectWallet.scss'; +import { fetchData } from "api/api"; const wallets: Array = ['lace', 'nami', 'yoroi'] @@ -42,7 +43,8 @@ const ConnectWallet = () => { setWalletName(walletName) if (enabledWallet) { const response = await enabledWallet.getChangeAddress() - setAddress(Address.from_bytes(Buffer.from(response, "hex")).to_bech32()) + const walletAddr = Address.from_bytes(Buffer.from(response, "hex")).to_bech32() + initiatePrivateWalletSignature(enabledWallet, walletAddr, response) } }) } catch (e) { handleError(e); } @@ -59,6 +61,44 @@ const ConnectWallet = () => { setTimeout(() => { setErrorToast({display: false}) }, 3000) } + const initiatePrivateWalletSignature = (currentWallet: any, walletAddr_bech32: any, walletAddr: string) => { + fetchData.get('/server-timestamp').then(async (res) => { + const timestamp = res.data; + const msgToBeSigned = `Sign this message if you are the owner of the ${walletAddr_bech32} address. \n Timestamp: <<${timestamp}>>`; + try { + const {key, signature} = await currentWallet.signData(walletAddr, Buffer.from(msgToBeSigned, 'utf8').toString('hex')) + console.log(key, signature) + + if (key && signature) { + fetchData.post('/login', { + address: walletAddr_bech32, + key: key, + signature: signature + }).then((response: any) => { + if (response.data) { + localStorage.setItem('authToken', response.data) + setAddress(walletAddr_bech32) + } + }).catch(err => { + handleError(err) + setWalletLoading(false) + dispatch(logout()) + }) + } + + } catch (err) { + handleError(err) + setWalletLoading(false) + setIsOpen(false) + dispatch(logout()) + } + }).catch((err) => { + handleError(err) + setWalletLoading(false) + dispatch(logout()) + }) + } + useEffect(() => { if (address) { (async () => { diff --git a/react-web/src/components/Header/Header.tsx b/react-web/src/components/Header/Header.tsx index d74f7028..208ac081 100644 --- a/react-web/src/components/Header/Header.tsx +++ b/react-web/src/components/Header/Header.tsx @@ -21,7 +21,8 @@ const Header = () => { // check if address, walletName is in localStorage - login user without having to connect to wallet again const addressCache = localStorage.getItem('address') const walletNameCache = localStorage.getItem('walletName') - if (addressCache?.length && walletNameCache?.length) { + const authToken = localStorage.getItem('authToken') + if (addressCache?.length && walletNameCache?.length && authToken?.length) { (async () => { try { const enabledWallet = await window.cardano[walletNameCache].enable() diff --git a/react-web/src/store/slices/auth.slice.ts b/react-web/src/store/slices/auth.slice.ts index 12073e21..92680362 100644 --- a/react-web/src/store/slices/auth.slice.ts +++ b/react-web/src/store/slices/auth.slice.ts @@ -25,6 +25,7 @@ const initialState: AuthState = { const clearLSCache = () => { localStorage.removeItem('address') localStorage.removeItem('walletName') + localStorage.removeItem('authToken') } export const getProfileDetails: any = createAsyncThunk("getProfileDetails", async (data: any, { rejectWithValue }) => { From 783b616146a8b541a542aadf0ce8e35918c395df Mon Sep 17 00:00:00 2001 From: amnambiar Date: Wed, 26 Apr 2023 19:14:25 +0530 Subject: [PATCH 2/5] PLT-4591 Error display fixes --- .../src/components/ConnectWallet/ConnectWallet.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/react-web/src/components/ConnectWallet/ConnectWallet.tsx b/react-web/src/components/ConnectWallet/ConnectWallet.tsx index 114eeab9..7e52d02d 100644 --- a/react-web/src/components/ConnectWallet/ConnectWallet.tsx +++ b/react-web/src/components/ConnectWallet/ConnectWallet.tsx @@ -29,7 +29,11 @@ const ConnectWallet = () => { const [errorToast, setErrorToast] = useState<{display: boolean; statusText?: string; message?: string;}>({display: false}); const [walletLoading, setWalletLoading] = useState(false) - const openConnectWalletModal = useCallback(() => setIsOpen(true),[]) + const openConnectWalletModal = useCallback(() => { + setErrorToast({display: false}) + setWallet(null) + setIsOpen(true) + },[]) const onCloseModal = useCallback(() => setIsOpen(false),[]) @@ -58,17 +62,14 @@ const ConnectWallet = () => { } else { setErrorToast({display: true}) } - setTimeout(() => { setErrorToast({display: false}) }, 3000) } const initiatePrivateWalletSignature = (currentWallet: any, walletAddr_bech32: any, walletAddr: string) => { fetchData.get('/server-timestamp').then(async (res) => { const timestamp = res.data; - const msgToBeSigned = `Sign this message if you are the owner of the ${walletAddr_bech32} address. \n Timestamp: <<${timestamp}>>`; + const msgToBeSigned = `Sign this message if you are the owner of the ${walletAddr_bech32} address. \n Timestamp: <<${timestamp}>> \n Expiry: 60 seconds`; try { const {key, signature} = await currentWallet.signData(walletAddr, Buffer.from(msgToBeSigned, 'utf8').toString('hex')) - console.log(key, signature) - if (key && signature) { fetchData.post('/login', { address: walletAddr_bech32, @@ -89,7 +90,6 @@ const ConnectWallet = () => { } catch (err) { handleError(err) setWalletLoading(false) - setIsOpen(false) dispatch(logout()) } }).catch((err) => { From 0943c00641de7df07fc993bc70810d0a2f6268b9 Mon Sep 17 00:00:00 2001 From: amnambiar Date: Fri, 28 Apr 2023 13:39:22 +0530 Subject: [PATCH 3/5] PLT-4591 Added Retry when Connect wallet failed --- .../ConnectWallet/ConnectWallet.tsx | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/react-web/src/components/ConnectWallet/ConnectWallet.tsx b/react-web/src/components/ConnectWallet/ConnectWallet.tsx index 7e52d02d..93a7bc30 100644 --- a/react-web/src/components/ConnectWallet/ConnectWallet.tsx +++ b/react-web/src/components/ConnectWallet/ConnectWallet.tsx @@ -26,7 +26,7 @@ const ConnectWallet = () => { const [walletName, setWalletName] = useState("") const [address, setAddress] = useState("") const [isOpen, setIsOpen] = useState(false) - const [errorToast, setErrorToast] = useState<{display: boolean; statusText?: string; message?: string;}>({display: false}); + const [errorToast, setErrorToast] = useState<{display: boolean; statusText?: string; message?: string; showRetry?: boolean}>({display: false}); const [walletLoading, setWalletLoading] = useState(false) const openConnectWalletModal = useCallback(() => { @@ -56,9 +56,17 @@ const ConnectWallet = () => { const handleError = (error: any) => { if (error.info) { - setErrorToast({display: true, message: error.info}) + setErrorToast({ + display: true, + message: error.info, + showRetry: error.code === 3}) } else if (error.response) { - setErrorToast({display: true, statusText: error.response.statusText, message: error.response.data || undefined}) + setErrorToast({ + display: true, + statusText: error.response.statusText, + message: error.response.data || undefined, + showRetry: error.status === 403 + }) } else { setErrorToast({display: true}) } @@ -141,7 +149,10 @@ const ConnectWallet = () => { } { walletLoading ? : null} { - (errorToast && errorToast.display) ? ({errorToast.message}): null + (errorToast && errorToast.display) ? (<> + {errorToast.message} + Retry + ): null } From ce351a4f2a2980d6e46ee7553cf8466cc7cd89fa Mon Sep 17 00:00:00 2001 From: amnambiar Date: Fri, 28 Apr 2023 13:43:27 +0530 Subject: [PATCH 4/5] PLT-4591 cleanup --- .../ConnectWallet/ConnectWallet.tsx | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/react-web/src/components/ConnectWallet/ConnectWallet.tsx b/react-web/src/components/ConnectWallet/ConnectWallet.tsx index 93a7bc30..08321178 100644 --- a/react-web/src/components/ConnectWallet/ConnectWallet.tsx +++ b/react-web/src/components/ConnectWallet/ConnectWallet.tsx @@ -72,6 +72,12 @@ const ConnectWallet = () => { } } + const catchError = (err: any) => { + handleError(err) + setWalletLoading(false) + dispatch(logout()) + } + const initiatePrivateWalletSignature = (currentWallet: any, walletAddr_bech32: any, walletAddr: string) => { fetchData.get('/server-timestamp').then(async (res) => { const timestamp = res.data; @@ -89,21 +95,15 @@ const ConnectWallet = () => { setAddress(walletAddr_bech32) } }).catch(err => { - handleError(err) - setWalletLoading(false) - dispatch(logout()) + catchError(err) }) } } catch (err) { - handleError(err) - setWalletLoading(false) - dispatch(logout()) + catchError(err) } }).catch((err) => { - handleError(err) - setWalletLoading(false) - dispatch(logout()) + catchError(err) }) } @@ -156,11 +156,6 @@ const ConnectWallet = () => { } - {/* {(errorToast && errorToast.display) ? ( - ((errorToast.message && errorToast.statusText) ? - : - )) - : null} */} ) } From 50011555176df074348b764b1054a363c1cb4098 Mon Sep 17 00:00:00 2001 From: amnambiar Date: Wed, 24 May 2023 18:26:29 +0530 Subject: [PATCH 5/5] PLT-4591 Review changes --- .../ConnectWallet/ConnectWallet.tsx | 50 ++++++++----------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/react-web/src/components/ConnectWallet/ConnectWallet.tsx b/react-web/src/components/ConnectWallet/ConnectWallet.tsx index 08321178..a7b34631 100644 --- a/react-web/src/components/ConnectWallet/ConnectWallet.tsx +++ b/react-web/src/components/ConnectWallet/ConnectWallet.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useCallback } from "react"; +import { useEffect, useState, useCallback } from "react"; import { Address } from "@emurgo/cardano-serialization-lib-browser"; import { useAppDispatch } from "store/store"; import { getProfileDetails, logout, setNetwork } from "store/slices/auth.slice"; @@ -6,10 +6,10 @@ import { getProfileDetails, logout, setNetwork } from "store/slices/auth.slice"; import Modal from "components/Modal/Modal"; import Button from "components/Button/Button"; import Loader from "components/Loader/Loader"; -import Toast from "components/Toast/Toast"; import './ConnectWallet.scss'; import { fetchData } from "api/api"; +import { AxiosResponse } from "axios"; const wallets: Array = ['lace', 'nami', 'yoroi'] @@ -78,40 +78,32 @@ const ConnectWallet = () => { dispatch(logout()) } - const initiatePrivateWalletSignature = (currentWallet: any, walletAddr_bech32: any, walletAddr: string) => { - fetchData.get('/server-timestamp').then(async (res) => { - const timestamp = res.data; - const msgToBeSigned = `Sign this message if you are the owner of the ${walletAddr_bech32} address. \n Timestamp: <<${timestamp}>> \n Expiry: 60 seconds`; - try { - const {key, signature} = await currentWallet.signData(walletAddr, Buffer.from(msgToBeSigned, 'utf8').toString('hex')) - if (key && signature) { - fetchData.post('/login', { - address: walletAddr_bech32, - key: key, - signature: signature - }).then((response: any) => { - if (response.data) { - localStorage.setItem('authToken', response.data) - setAddress(walletAddr_bech32) - } - }).catch(err => { - catchError(err) - }) - } - - } catch (err) { - catchError(err) + const initiatePrivateWalletSignature = async (currentWallet: any, walletAddr_bech32: any, walletAddr: string) => { + const timestamp = (await fetchData.get,any>('/server-timestamp')).data; + const msgToBeSigned = `Sign this message if you are the owner of the ${walletAddr_bech32} address. \n Timestamp: <<${timestamp}>> \n Expiry: 60 seconds`; + try { + const {key, signature} = await currentWallet.signData(walletAddr, Buffer.from(msgToBeSigned, 'utf8').toString('hex')) + if (key && signature) { + const token = (await fetchData.post,any>('/login', { + address: walletAddr_bech32, + key: key, + signature: signature + })).data; + localStorage.setItem('authToken', token) + setAddress(walletAddr_bech32) + } else { + catchError({ message: "Could not obtain the proper key and signature for the wallet. Please try connecting again." }) } - }).catch((err) => { + } catch (err) { catchError(err) - }) + } } useEffect(() => { if (address) { (async () => { try { - const response: any = await dispatch(getProfileDetails({"address": address, "wallet": wallet, "walletName": walletName})).catch(handleError) + await dispatch(getProfileDetails({"address": address, "wallet": wallet, "walletName": walletName})).catch(handleError) setWalletLoading(false) } catch(error) { setWalletLoading(false) @@ -149,7 +141,7 @@ const ConnectWallet = () => { } { walletLoading ? : null} { - (errorToast && errorToast.display) ? (<> + (errorToast?.display) ? (<> {errorToast.message} Retry ): null