diff --git a/react-web/src/api/onRequest.ts b/react-web/src/api/onRequest.ts index 27107f65..82c54ec5 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..a7b34631 100644 --- a/react-web/src/components/ConnectWallet/ConnectWallet.tsx +++ b/react-web/src/components/ConnectWallet/ConnectWallet.tsx @@ -1,14 +1,15 @@ -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, 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"; 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'] @@ -25,10 +26,14 @@ 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(() => setIsOpen(true),[]) + const openConnectWalletModal = useCallback(() => { + setErrorToast({display: false}) + setWallet(null) + setIsOpen(true) + },[]) const onCloseModal = useCallback(() => setIsOpen(false),[]) @@ -42,7 +47,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); } @@ -50,20 +56,54 @@ 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}) } - setTimeout(() => { setErrorToast({display: false}) }, 3000) + } + + const catchError = (err: any) => { + handleError(err) + setWalletLoading(false) + dispatch(logout()) + } + + 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) { + 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) @@ -101,15 +141,13 @@ const ConnectWallet = () => { } { walletLoading ? : null} { - (errorToast && errorToast.display) ? ({errorToast.message}): null + (errorToast?.display) ? (<> + {errorToast.message} + Retry + ): null } - {/* {(errorToast && errorToast.display) ? ( - ((errorToast.message && errorToast.statusText) ? - : - )) - : null} */} ) } diff --git a/react-web/src/components/Header/Header.tsx b/react-web/src/components/Header/Header.tsx index 5734460e..d5e7f312 100644 --- a/react-web/src/components/Header/Header.tsx +++ b/react-web/src/components/Header/Header.tsx @@ -22,7 +22,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()