Skip to content

Commit

Permalink
feat: check signature version (#1429)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsimao authored Jul 10, 2023
1 parent 0c457e9 commit a320deb
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 24 deletions.
4 changes: 4 additions & 0 deletions .env.dev
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ REACT_APP_PARACHAIN_ID="2121"
DOCKER_RELAY_CHAIN_CURRENCY="KSM"
REACT_APP_SQUID_URL="https://api-dev-kintsugi.interlay.io/graphql/graphql"
REACT_APP_MARKET_DATA_URL="https://api.coingecko.com/api/v3/simple/price?vs_currencies=usd"
REACT_APP_TC_VERSION="1.0"

// Interlay testnet

Expand All @@ -41,6 +42,7 @@ REACT_APP_RELAY_CHAIN_NAME="polkadot"
DOCKER_RELAY_CHAIN_CURRENCY="DOT"
REACT_APP_SQUID_URL="https://api-testnet.interlay.io/graphql/graphql"
REACT_APP_MARKET_DATA_URL="https://api.coingecko.com/api/v3/simple/price?vs_currencies=usd"
REACT_APP_TC_VERSION="1.0"

/* PRODUCTION */

Expand All @@ -57,6 +59,7 @@ DOCKER_RELAY_CHAIN_CURRENCY="KSM"
REACT_APP_SQUID_URL="https://api-kusama.interlay.io/graphql/graphql"
REACT_APP_MARKET_DATA_URL="https://api.coingecko.com/api/v3/simple/price?vs_currencies=usd"
REACT_APP_SIGNER_API_URL="https://interbtc-ui-kintsugi-git-api-terms-interlay.vercel.app/terms"
REACT_APP_TC_VERSION="1.0"

// Interlay mainnet

Expand All @@ -71,3 +74,4 @@ DOCKER_RELAY_CHAIN_CURRENCY="DOT"
REACT_APP_SQUID_URL="https://api.interlay.io/graphql/graphql"
REACT_APP_MARKET_DATA_URL="https://api.coingecko.com/api/v3/simple/price?vs_currencies=usd"
REACT_APP_SIGNER_API_URL="https://interbtc-ui-interlay-git-api-terms-interlay.vercel.app/terms"
REACT_APP_TC_VERSION="1.0"
3 changes: 3 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ const VAULT_STATUS_LIQUIDATION = 'Being liquidated';
const BTC_RELAY_DELAY_WARNING = 6;
const BTC_RELAY_DELAY_CRITICAL = 12;

const TC_VERSION = process.env.REACT_APP_TC_VERSION || '';

export {
ANALYTICS_CODE,
BALANCE_MAX_INTEGER_LENGTH,
Expand All @@ -96,6 +98,7 @@ export {
SQUID_URL,
SS58_FORMAT,
STORE_NAME,
TC_VERSION,
VAULT_STATUS_ACTIVE,
VAULT_STATUS_BANNED,
VAULT_STATUS_LIQUIDATED,
Expand Down
4 changes: 1 addition & 3 deletions src/utils/hooks/use-local-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ import { useLocalStorage as useLibLocalStorage } from 'react-use';

enum LocalStorageKey {
TC_SIGNATURES = 'TC_SIGNATURES',
TC_VERSION = 'TC_VERSION',
WALLET_WELCOME_BANNER = 'WALLET_WELCOME_BANNER'
}

type LocalStorageValueTypes = {
[LocalStorageKey.TC_SIGNATURES]: Record<string, boolean>;
[LocalStorageKey.TC_VERSION]: string;
[LocalStorageKey.TC_SIGNATURES]: { [account: string]: { version: string; isSigned: boolean } | boolean };
[LocalStorageKey.WALLET_WELCOME_BANNER]: boolean;
};

Expand Down
39 changes: 18 additions & 21 deletions src/utils/hooks/use-sign-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useDispatch } from 'react-redux';

import { showSignTermsModalAction } from '@/common/actions/general.actions';
import { TERMS_AND_CONDITIONS_LINK } from '@/config/relay-chains';
import { SIGNER_API_URL } from '@/constants';
import { SIGNER_API_URL, TC_VERSION } from '@/constants';
import { KeyringPair, useSubstrateSecureState } from '@/lib/substrate';

import { NotificationToastType, useNotifications } from '../context/Notifications';
Expand All @@ -17,16 +17,14 @@ interface GetSignatureData {
exists: boolean;
}

const TC_VERSION = '1.0';

const postSignature = async (account: KeyringPair) => {
const signerResult = await signMessage(account, TERMS_AND_CONDITIONS_LINK);

if (!signerResult?.signature) {
throw new Error('Failed to sign message');
}

return fetch(`${SIGNER_API_URL}/${account.address}?${new URLSearchParams({version: TC_VERSION})}`, {
return fetch(`${SIGNER_API_URL}/${account.address}?${new URLSearchParams({ version: TC_VERSION })}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
Expand All @@ -52,31 +50,37 @@ type UseSignMessageResult = {
};
};

const shouldCheckSignature = !!TC_VERSION;

const useSignMessage = (): UseSignMessageResult => {
const { t } = useTranslation();
const queryClient = useQueryClient();
const notifications = useNotifications();

const dispatch = useDispatch();
const [signatures, setSignatures] = useLocalStorage(LocalStorageKey.TC_SIGNATURES);
const [tcVersion, setTcVersion] = useLocalStorage(LocalStorageKey.TC_VERSION);

const { selectedAccount } = useSubstrateSecureState();

const setSignature = useCallback(
(address: string, hasSignature: boolean) => setSignatures({ ...signatures, [address]: hasSignature }),
(address: string, hasSignature: boolean) =>
setSignatures({ ...signatures, [address]: { isSigned: hasSignature, version: TC_VERSION } }),
[setSignatures, signatures]
);

const getSignature = useCallback(
async (account: KeyringPair): Promise<boolean> => {
const storedSignature = signatures?.[account.address];
const signatureData = signatures?.[account.address];

// if the stored value is boolean, we will force to fetch, so we can migrate to lastest structure
const hasStoredSignature =
typeof signatureData === 'object' ? signatureData?.version === TC_VERSION && signatureData.isSigned : undefined;

if (storedSignature !== undefined) {
return storedSignature;
if (hasStoredSignature !== undefined) {
return hasStoredSignature;
}

const res = await fetch(`${SIGNER_API_URL}/${account.address}?${new URLSearchParams({version: TC_VERSION})}`, {
const res = await fetch(`${SIGNER_API_URL}/${account.address}?${new URLSearchParams({ version: TC_VERSION })}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
Expand All @@ -99,7 +103,7 @@ const useSignMessage = (): UseSignMessageResult => {
refetchOnWindowFocus: false,
refetchOnMount: false,
refetchOnReconnect: false,
enabled: !!selectedAccount,
enabled: !!selectedAccount && shouldCheckSignature,
queryFn: () => selectedAccount && getSignature(selectedAccount)
});

Expand All @@ -113,7 +117,6 @@ const useSignMessage = (): UseSignMessageResult => {
},
onSuccess: (_, variables) => {
setSignature(variables.address, true);
setTcVersion(TC_VERSION);
dispatch(showSignTermsModalAction(false));
refetchSignatureData();
notifications.show(variables.address, {
Expand All @@ -123,12 +126,6 @@ const useSignMessage = (): UseSignMessageResult => {
}
});

useEffect(() => {
if (tcVersion === TC_VERSION) return;

setSignatures({});
}, [setSignatures, tcVersion]);

// Reset mutation on account change
useEffect(() => {
if (signMessageMutation.isLoading && selectedAccount?.address) {
Expand All @@ -140,13 +137,13 @@ const useSignMessage = (): UseSignMessageResult => {
const handleSignMessage = (account?: KeyringPair) => {
// should not sign message if there is already a stored signature
// or if signer api url is not set
if (!account || !SIGNER_API_URL || hasSignature) return;
if (!account || !SIGNER_API_URL || hasSignature || !shouldCheckSignature) return;

signMessageMutation.mutate(account);
};

const handleOpenSignTermModal = async (account: KeyringPair) => {
if (!SIGNER_API_URL) return;
if (!SIGNER_API_URL || !shouldCheckSignature) return;

// Cancel possible ongoing unwanted account
queryClient.cancelQueries({ queryKey });
Expand All @@ -162,7 +159,7 @@ const useSignMessage = (): UseSignMessageResult => {
};

return {
hasSignature: !!hasSignature,
hasSignature: shouldCheckSignature ? !!hasSignature : true,
modal: {
buttonProps: { onPress: () => handleSignMessage(selectedAccount), loading: signMessageMutation.isLoading }
},
Expand Down

2 comments on commit a320deb

@vercel
Copy link

@vercel vercel bot commented on a320deb Jul 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on a320deb Jul 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.