import { getSdkError } from '@walletconnect/utils'
import { Web3WalletTypes } from '@walletconnect/web3wallet'
import React, { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet } from 'react-native'
import InLineNotification, { NotificationVariant } from 'src/components/InLineNotification'
import { useDispatch, useSelector } from 'src/redux/hooks'
import { NETWORK_NAMES } from 'src/shared/conts'
import { Spacing } from 'src/styles/styles'
import Logger from 'src/utils/Logger'
import { SerializableTransactionRequest } from 'src/viem/preparedTransactionSerialization'
import { acceptRequest, denyRequest } from 'src/walletConnect/actions'
import {
SupportedActions,
chainAgnosticActions,
getDisplayTextFromAction,
} from 'src/walletConnect/constants'
import ActionRequestPayload from 'src/walletConnect/screens/ActionRequestPayload'
import DappsDisclaimer from 'src/walletConnect/screens/DappsDisclaimer'
import EstimatedNetworkFee from 'src/walletConnect/screens/EstimatedNetworkFee'
import RequestContent, { useDappMetadata } from 'src/walletConnect/screens/RequestContent'
import { useIsDappListed } from 'src/walletConnect/screens/useIsDappListed'
import { sessionsSelector } from 'src/walletConnect/selectors'
import { walletConnectChainIdToNetworkId } from 'src/web3/networkConfig'
export interface ActionRequestProps {
version: 2
pendingAction: Web3WalletTypes.EventArguments['session_request']
supportedChains: string[]
hasInsufficientGasFunds: boolean
feeCurrenciesSymbols: string[]
preparedTransaction?: SerializableTransactionRequest
prepareTransactionErrorMessage?: string
}
function ActionRequest({
pendingAction,
supportedChains,
hasInsufficientGasFunds,
feeCurrenciesSymbols,
preparedTransaction,
prepareTransactionErrorMessage,
}: ActionRequestProps) {
const { t } = useTranslation()
const dispatch = useDispatch()
const sessions = useSelector(sessionsSelector)
const activeSession = useMemo(() => {
return sessions.find((s) => s.topic === pendingAction.topic)
}, [sessions])
const { url, dappName, dappImageUrl } = useDappMetadata(activeSession?.peer.metadata)
const isDappListed = useIsDappListed(url)
if (!activeSession) {
// should never happen
Logger.error(
'WalletConnectRequest/ActionRequestV2',
'No active WallectConnect session could be found'
)
return null
}
const chainId = pendingAction.params.chainId
const networkId = walletConnectChainIdToNetworkId[chainId]
const networkName = NETWORK_NAMES[networkId]
const method = pendingAction.params.request.method
const { description, title, action } = getDisplayTextFromAction(
t,
method as SupportedActions,
dappName,
networkName
)
// Reject and warn if the chain is not supported
// Note: we still allow off-chain actions like personal_sign on unsupported
// chains (Cred Protocol does this) as this does not depend on the chainId
if (!supportedChains.includes(chainId) && !chainAgnosticActions.includes(method)) {
const supportedNetworkNames = supportedChains
.map((chain) => NETWORK_NAMES[walletConnectChainIdToNetworkId[chain]])
.join(`, `)
return (
dispatch(denyRequest(pendingAction, getSdkError('UNSUPPORTED_CHAINS')))}
dappName={dappName}
dappImageUrl={dappImageUrl}
title={title}
description={description}
testId="WalletConnectActionRequest"
>
)
}
if (hasInsufficientGasFunds) {
return (
dispatch(denyRequest(pendingAction, getSdkError('USER_REJECTED')))}
dappName={dappName}
dappImageUrl={dappImageUrl}
title={title}
description={description}
testId="WalletConnectActionRequest"
>
)
}
if (
!preparedTransaction &&
(method === SupportedActions.eth_signTransaction ||
method === SupportedActions.eth_sendTransaction)
) {
return (
dispatch(denyRequest(pendingAction, getSdkError('USER_REJECTED')))}
dappName={dappName}
dappImageUrl={dappImageUrl}
title={title}
description={description}
testId="WalletConnectActionRequest"
>
)
}
return (
dispatch(acceptRequest(pendingAction, preparedTransaction))}
onDeny={() => {
dispatch(denyRequest(pendingAction, getSdkError('USER_REJECTED')))
}}
dappName={dappName}
dappImageUrl={dappImageUrl}
title={title}
description={description}
testId="WalletConnectActionRequest"
>
{preparedTransaction && (
)}
)
}
const styles = StyleSheet.create({
warning: {
marginBottom: Spacing.Thick24,
},
})
export default ActionRequest