Commit 8e52e6a5 authored by tom goriunov's avatar tom goriunov Committed by GitHub

Auth: Switch the chain before signing the message when the user logs in with their wallet (#2673)

Fixes #2345
parent 0dd6087f
...@@ -3,7 +3,7 @@ import { useQueryClient } from '@tanstack/react-query'; ...@@ -3,7 +3,7 @@ import { useQueryClient } from '@tanstack/react-query';
import { useToggle } from '@uidotdev/usehooks'; import { useToggle } from '@uidotdev/usehooks';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React, { createContext, useContext, useEffect, useMemo, useCallback } from 'react'; import React, { createContext, useContext, useEffect, useMemo, useCallback } from 'react';
import { useSignMessage } from 'wagmi'; import { useSignMessage, useSwitchChain } from 'wagmi';
import type { import type {
RewardsUserBalancesResponse, RewardsUserDailyCheckResponse, RewardsUserBalancesResponse, RewardsUserDailyCheckResponse,
...@@ -118,6 +118,7 @@ export function RewardsContextProvider({ children }: Props) { ...@@ -118,6 +118,7 @@ export function RewardsContextProvider({ children }: Props) {
const apiFetch = useApiFetch(); const apiFetch = useApiFetch();
const { address } = useAccount(); const { address } = useAccount();
const { signMessageAsync } = useSignMessage(); const { signMessageAsync } = useSignMessage();
const { switchChainAsync } = useSwitchChain();
const profileQuery = useProfileQuery(); const profileQuery = useProfileQuery();
const [ isLoginModalOpen, setIsLoginModalOpen ] = useToggle(false); const [ isLoginModalOpen, setIsLoginModalOpen ] = useToggle(false);
...@@ -220,6 +221,7 @@ export function RewardsContextProvider({ children }: Props) { ...@@ -220,6 +221,7 @@ export function RewardsContextProvider({ children }: Props) {
reward: null, reward: null,
}; };
} }
await switchChainAsync({ chainId: Number(config.chain.id) });
const message = getMessageToSign(address, nonceResponse.nonce, checkUserQuery.data?.exists, refCode); const message = getMessageToSign(address, nonceResponse.nonce, checkUserQuery.data?.exists, refCode);
const signature = await signMessageAsync({ message }); const signature = await signMessageAsync({ message });
const loginResponse = await apiFetch('rewards_login', { const loginResponse = await apiFetch('rewards_login', {
...@@ -241,7 +243,7 @@ export function RewardsContextProvider({ children }: Props) { ...@@ -241,7 +243,7 @@ export function RewardsContextProvider({ children }: Props) {
errorToast(_error); errorToast(_error);
throw _error; throw _error;
} }
}, [ apiFetch, address, signMessageAsync, errorToast, saveApiToken, checkUserQuery ]); }, [ address, apiFetch, checkUserQuery.data?.exists, switchChainAsync, signMessageAsync, saveApiToken, errorToast ]);
// Claim daily reward // Claim daily reward
const claim = useCallback(async() => { const claim = useCallback(async() => {
......
...@@ -29,7 +29,7 @@ export default function useCallMethodWalletClient(): (params: Params) => Promise ...@@ -29,7 +29,7 @@ export default function useCallMethodWalletClient(): (params: Params) => Promise
} }
if (chainId && String(chainId) !== config.chain.id) { if (chainId && String(chainId) !== config.chain.id) {
await switchChainAsync?.({ chainId: Number(config.chain.id) }); await switchChainAsync({ chainId: Number(config.chain.id) });
} }
const address = getAddress(addressHash); const address = getAddress(addressHash);
......
...@@ -3,7 +3,7 @@ import { useAppKit } from '@reown/appkit/react'; ...@@ -3,7 +3,7 @@ import { useAppKit } from '@reown/appkit/react';
import React from 'react'; import React from 'react';
import type { SubmitHandler } from 'react-hook-form'; import type { SubmitHandler } from 'react-hook-form';
import { FormProvider, useForm } from 'react-hook-form'; import { FormProvider, useForm } from 'react-hook-form';
import { useSignMessage, useAccount } from 'wagmi'; import { useSignMessage, useAccount, useSwitchChain } from 'wagmi';
import type { import type {
AddressVerificationFormSecondStepFields, AddressVerificationFormSecondStepFields,
...@@ -84,6 +84,7 @@ const AddressVerificationStepSignature = ({ address, signingMessage, contractCre ...@@ -84,6 +84,7 @@ const AddressVerificationStepSignature = ({ address, signingMessage, contractCre
const onSubmit = handleSubmit(onFormSubmit); const onSubmit = handleSubmit(onFormSubmit);
const { signMessage, isPending: isSigning } = useSignMessage(); const { signMessage, isPending: isSigning } = useSignMessage();
const { switchChainAsync } = useSwitchChain();
const handleSignMethodChange = React.useCallback(({ value }: { value: string | null }) => { const handleSignMethodChange = React.useCallback(({ value }: { value: string | null }) => {
if (!value) { if (!value) {
...@@ -99,13 +100,14 @@ const AddressVerificationStepSignature = ({ address, signingMessage, contractCre ...@@ -99,13 +100,14 @@ const AddressVerificationStepSignature = ({ address, signingMessage, contractCre
openWeb3Modal(); openWeb3Modal();
}, [ clearErrors, openWeb3Modal ]); }, [ clearErrors, openWeb3Modal ]);
const handleWeb3SignClick = React.useCallback(() => { const handleWeb3SignClick = React.useCallback(async() => {
clearErrors('root'); clearErrors('root');
if (!isConnected) { if (!isConnected) {
return setError('root', { type: 'manual', message: 'Please connect to your Web3 wallet first' }); return setError('root', { type: 'manual', message: 'Please connect to your Web3 wallet first' });
} }
await switchChainAsync({ chainId: Number(config.chain.id) });
const message = getValues('message'); const message = getValues('message');
signMessage({ message }, { signMessage({ message }, {
onSuccess: (data) => { onSuccess: (data) => {
...@@ -116,7 +118,7 @@ const AddressVerificationStepSignature = ({ address, signingMessage, contractCre ...@@ -116,7 +118,7 @@ const AddressVerificationStepSignature = ({ address, signingMessage, contractCre
return setError('root', { type: 'SIGNING_FAIL', message: (error as Error)?.message || 'Oops! Something went wrong' }); return setError('root', { type: 'SIGNING_FAIL', message: (error as Error)?.message || 'Oops! Something went wrong' });
}, },
}); });
}, [ clearErrors, isConnected, getValues, signMessage, setError, setValue, onSubmit ]); }, [ clearErrors, isConnected, getValues, signMessage, setError, setValue, onSubmit, switchChainAsync ]);
const handleManualSignClick = React.useCallback(() => { const handleManualSignClick = React.useCallback(() => {
clearErrors('root'); clearErrors('root');
......
import React from 'react'; import React from 'react';
import { useSignMessage } from 'wagmi'; import { useSignMessage, useSwitchChain } from 'wagmi';
import type { UserInfo } from 'types/api/account'; import type { UserInfo } from 'types/api/account';
import type { RewardsCheckUserResponse, RewardsConfigResponse, RewardsLoginResponse, RewardsNonceResponse } from 'types/api/rewards'; import type { RewardsCheckUserResponse, RewardsConfigResponse, RewardsLoginResponse, RewardsNonceResponse } from 'types/api/rewards';
...@@ -53,6 +53,7 @@ function useSignInWithWallet({ onSuccess, onError, source = 'Login', isAuth, log ...@@ -53,6 +53,7 @@ function useSignInWithWallet({ onSuccess, onError, source = 'Login', isAuth, log
const apiFetch = useApiFetch(); const apiFetch = useApiFetch();
const web3Wallet = useWeb3Wallet({ source }); const web3Wallet = useWeb3Wallet({ source });
const { signMessageAsync } = useSignMessage(); const { signMessageAsync } = useSignMessage();
const { switchChainAsync } = useSwitchChain();
const getSiweMessage = React.useCallback(async(address: string) => { const getSiweMessage = React.useCallback(async(address: string) => {
try { try {
...@@ -99,6 +100,7 @@ function useSignInWithWallet({ onSuccess, onError, source = 'Login', isAuth, log ...@@ -99,6 +100,7 @@ function useSignInWithWallet({ onSuccess, onError, source = 'Login', isAuth, log
const proceedToAuth = React.useCallback(async(address: string) => { const proceedToAuth = React.useCallback(async(address: string) => {
try { try {
await switchChainAsync({ chainId: Number(config.chain.id) });
const siweMessage = await getSiweMessage(address); const siweMessage = await getSiweMessage(address);
const signature = await signMessageAsync({ message: siweMessage.message }); const signature = await signMessageAsync({ message: siweMessage.message });
const recaptchaToken = await executeRecaptchaAsync(); const recaptchaToken = await executeRecaptchaAsync();
...@@ -143,7 +145,7 @@ function useSignInWithWallet({ onSuccess, onError, source = 'Login', isAuth, log ...@@ -143,7 +145,7 @@ function useSignInWithWallet({ onSuccess, onError, source = 'Login', isAuth, log
} finally { } finally {
setIsPending(false); setIsPending(false);
} }
}, [ getSiweMessage, signMessageAsync, executeRecaptchaAsync, isAuth, apiFetch, onSuccess, onError ]); }, [ getSiweMessage, switchChainAsync, signMessageAsync, executeRecaptchaAsync, isAuth, apiFetch, onSuccess, onError ]);
const start = React.useCallback(() => { const start = React.useCallback(() => {
setIsPending(true); setIsPending(true);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment