From 65688cd83532d244f17a274574f084076b166e15 Mon Sep 17 00:00:00 2001 From: Izumi Hoshino Date: Fri, 1 Nov 2024 02:02:26 +0900 Subject: [PATCH] Checkpoint --- ...ConnectRequestPermissionsConfirmDialog.tsx | 91 +++++++++++++------ .../src/constants/WalletConnectCommands.tsx | 2 +- .../gui/src/hooks/useWalletConnectCommand.tsx | 17 ++-- 3 files changed, 72 insertions(+), 38 deletions(-) diff --git a/packages/gui/src/components/walletConnect/WalletConnectRequestPermissionsConfirmDialog.tsx b/packages/gui/src/components/walletConnect/WalletConnectRequestPermissionsConfirmDialog.tsx index 9d66892a98..6f6f5113ef 100644 --- a/packages/gui/src/components/walletConnect/WalletConnectRequestPermissionsConfirmDialog.tsx +++ b/packages/gui/src/components/walletConnect/WalletConnectRequestPermissionsConfirmDialog.tsx @@ -1,8 +1,8 @@ import { useGetKeysQuery } from '@chia-network/api-react'; import { ConfirmDialog, Flex, LoadingOverlay } from '@chia-network/core'; import { Trans } from '@lingui/macro'; -import { Typography, Divider } from '@mui/material'; -import React, { useState, useMemo } from 'react'; +import { Alert, Typography, Divider } from '@mui/material'; +import React from 'react'; import type WalletConnectCommandParam from '../../@types/WalletConnectCommandParam'; import walletConnectCommands from '../../constants/WalletConnectCommands'; @@ -35,47 +35,84 @@ export default function WalletConnectRequestPermissionsConfirmDialog( onChange, } = props; - const [values, setValues] = useState(defaultValues); + const [values, setValues] = React.useState(defaultValues); const { getPairBySession, bypassCommands } = useWalletConnectPairs(); - const { data: keys, isLoading: isLoadingPublicKeys } = useGetKeysQuery(); + const { data: keys, isLoading: isLoadingPublicKeys } = useGetKeysQuery({}); const key = keys?.find((item) => item.fingerprint === fingerprint); - const pair = useMemo(() => getPairBySession(topic), [topic, getPairBySession]); - - function handleClose(confirmed: boolean) { - if (confirmed) { - params.forEach((element) => { - if (element.name === 'commands') { - // filter out commands that don't allow bypassing confirmation - const cmds = values[element.name].filter((cmd: string) => { - const cmdDescription = walletConnectCommands.find((item) => item.command === cmd); - return cmdDescription?.bypassConfirm; - }); - bypassCommands(topic, cmds, true); - } - }); + const pair = React.useMemo(() => getPairBySession(topic), [topic, getPairBySession]); + + const targetCommands = React.useMemo(() => { + for (let i = 0; i < params.length; i++) { + const p = params[i]; + if (p.name === 'commands') { + return (values.commands as string[]).map((cmd) => { + const cmdDescription = walletConnectCommands.find((item) => `chia_${item.command}` === cmd); + return { + command: cmdDescription?.command ?? cmd.replace('chia_', ''), + bypassConfirm: Boolean(cmdDescription?.bypassConfirm), + }; + }); + } } + return []; + }, [params, values]); + + const disableApprove = React.useMemo(() => targetCommands.some((cmd) => !cmd.bypassConfirm), [targetCommands]); + + const handleClose = React.useCallback( + (confirmed: boolean) => { + if (confirmed) { + // filter out commands that don't allow bypassing confirmation + const bypassingCommands = targetCommands.filter((cmd) => cmd.bypassConfirm).map((cmd) => cmd.command); + bypassCommands(topic, bypassingCommands, true); + } + + onClose?.(confirmed); + }, + [onClose, topic, bypassCommands, targetCommands], + ); - onClose?.(confirmed); - } - - function handleChangeValues(newValues: Record) { - setValues(newValues); - onChange?.(newValues); - } + const handleChangeValues = React.useCallback( + (newValues: Record) => { + setValues(newValues); + onChange?.(newValues); + }, + [setValues, onChange], + ); return ( Requesting Permissions} confirmColor="primary" - confirmTitle={Confirm} + confirmTitle={Approve} cancelTitle={Reject} onClose={handleClose} open={open} + disableConfirmButton={disableApprove} > - An app has requested permission to execute the following commands. + + An app has requested permission to execute the following commands. + + + + After you approve, the connected app can execute these commands on your behalf without confirmation. + + + + {disableApprove && ( + + The following commands are not allowed to bypass confirmation. + + {targetCommands + .filter((cmd) => !cmd.bypassConfirm) + .map((cmd) => cmd.command) + .join(', ')} + + + )} {params.length > 0 && ( diff --git a/packages/gui/src/constants/WalletConnectCommands.tsx b/packages/gui/src/constants/WalletConnectCommands.tsx index acb482e7b5..a86973a58d 100644 --- a/packages/gui/src/constants/WalletConnectCommands.tsx +++ b/packages/gui/src/constants/WalletConnectCommands.tsx @@ -16,7 +16,7 @@ const walletConnectCommands: WalletConnectCommand[] = [ label: Request Permissions, description: App is requesting permission to execute these commands, service: 'EXECUTE', - execute: {}, + execute: (values) => ({ values }), params: [ { name: WalletConnectCommandParamName.COMMANDS, diff --git a/packages/gui/src/hooks/useWalletConnectCommand.tsx b/packages/gui/src/hooks/useWalletConnectCommand.tsx index aa925512ad..c5e4acc0ff 100644 --- a/packages/gui/src/hooks/useWalletConnectCommand.tsx +++ b/packages/gui/src/hooks/useWalletConnectCommand.tsx @@ -114,14 +114,11 @@ export default function useWalletConnectCommand(options: UseWalletConnectCommand return pair.bypassCommands[command]; } if (command === 'requestPermissions') { - let hasPermissions = true; - if (values.commands) { - values.commands.forEach((cmd: string) => { - if (!pair.bypassCommands || !pair.bypassCommands[cmd]) { - hasPermissions = false; - } - }); + if (!values.commands || values.commands.some((cmd: string) => cmd === 'requestPermissions')) { + return false; } + const { bypassCommands } = pair; + const hasPermissions = !!bypassCommands && values.commands.every((cmd: string) => bypassCommands[cmd]); if (hasPermissions) { return true; } @@ -243,9 +240,9 @@ export default function useWalletConnectCommand(options: UseWalletConnectCommand } // validate current fingerprint again - const currentLoggedInFingerptintPromise = store.dispatch(api.endpoints.getLoggedInFingerprint.initiate()); - const { data: currentFingerprintAfterWait } = await currentLoggedInFingerptintPromise; - currentLoggedInFingerptintPromise.unsubscribe(); + const currentLoggedInFingerprintPromise = store.dispatch(api.endpoints.getLoggedInFingerprint.initiate()); + const { data: currentFingerprintAfterWait } = await currentLoggedInFingerprintPromise; + currentLoggedInFingerprintPromise.unsubscribe(); if (currentFingerprintAfterWait !== fingerprint) { throw new Error(`Fingerprint changed during execution`);