Skip to content

Commit

Permalink
Merge pull request #1374 from gabrielbazan7/ref/walletconnect
Browse files Browse the repository at this point in the history
[REF] WC: display decoded transaction parameters in detail view
  • Loading branch information
JohnathanWhite authored Oct 29, 2024
2 parents 3728f18 + 68b0e25 commit 750a689
Show file tree
Hide file tree
Showing 28 changed files with 3,042 additions and 444 deletions.
7 changes: 6 additions & 1 deletion .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@ GOOGLE_MAPS_API_KEY=
MIXPANEL_PROJECT_TOKEN=
MORALIS_API_KEY=
WALLET_CONNECT_V2_PROJECT_ID=
ZENLEDGER_CLIENT_ID=
ZENLEDGER_CLIENT_ID=
ETHERSCAN_API_KEY=
POLYGONSCAN_API_KEY=
ARBISCAN_API_KEY=
OPSCAN_API_KEY=
BASESCAN_API_KEY=
5 changes: 5 additions & 0 deletions declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@ declare module '@env' {
export const ZENLEDGER_CLIENT_SECRET: string;
export const APPSFLYER_API_KEY: string;
export const APPSFLYER_APP_ID: string;
export const ETHERSCAN_API_KEY: string;
export const POLYGONSCAN_API_KEY: string;
export const ARBISCAN_API_KEY: string;
export const OPSCAN_API_KEY: string;
export const BASESCAN_API_KEY: string;
}
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@
"@walletconnect/jsonrpc-types": "1.0.2",
"@walletconnect/legacy-utils": "2.0.0-rc.0",
"@walletconnect/react-native-compat": "2.14.0",
"@walletconnect/sign-client": "2.10.4",
"@walletconnect/types": "2.10.4",
"@walletconnect/utils": "2.10.4",
"@walletconnect/web3wallet": "1.8.8",
"@walletconnect/sign-client": "2.11.3",
"@walletconnect/types": "2.11.3",
"@walletconnect/utils": "2.11.3",
"@walletconnect/web3wallet": "1.11.2",
"asyncstorage-down": "4.2.0",
"axios": "0.21.1",
"babel-plugin-module-resolver": "4.1.0",
Expand Down Expand Up @@ -178,6 +178,7 @@
"reselect": "4.1.5",
"rn-nodeify": "10.3.0",
"rn-swipe-button": "1.3.8",
"safe-json-utils": "1.1.1",
"stream-browserify": "1.0.0",
"styled-components": "5.3.3",
"url": "0.10.3",
Expand Down
1 change: 1 addition & 0 deletions scripts/allowed-url-prefixes.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const allowedUrlPrefixes = [
'https://goerli-rollup.arbitrum.io/rpc',
'https://goerli.base.org',
'https://verify.walletconnect.com/',
'https://api.etherscan.io/v2/api',
].concat(developmentOnlyAllowedUrlPrefixes);

const allowedUrlPrefixString = allowedUrlPrefixes.join(',');
Expand Down
1 change: 1 addition & 0 deletions src/api/etherscan/etherscan.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const ETHERSCAN_API_URL = 'https://api.etherscan.io/v2/api';
Empty file.
54 changes: 54 additions & 0 deletions src/api/etherscan/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import axios from 'axios';
import {ETHERSCAN_API_URL} from './etherscan.constants';
import {ETHERSCAN_API_KEY} from '@env';
import {Effect} from '../../store';
import {updateContractAbi} from '../../store/wallet-connect-v2/wallet-connect-v2.actions';

const getContractAbi =
(chainId: string, contractAddress: string): Effect<Promise<string>> =>
async (dispatch, getState) => {
const {WALLET_CONNECT_V2} = getState();
const ABI = WALLET_CONNECT_V2.contractAbi[contractAddress];
if (ABI) {
return ABI;
}
const url = `${ETHERSCAN_API_URL}?chainid=${chainId}&module=contract&action=getabi&address=${contractAddress}&apikey=${ETHERSCAN_API_KEY}`;
const headers = {
'Content-Type': 'application/json',
};
try {
const {data} = await axios.get(url, {headers});
const {result} = data;
if (result) {
dispatch(updateContractAbi(result, contractAddress));
}
return result;
} catch (error: any) {
throw error.message;
}
};

const getStorageAt = async (
chainId: string,
proxyAddress: string,
implementationSlot: string,
): Promise<string> => {
const url = `${ETHERSCAN_API_URL}?chainid=${chainId}&module=proxy&action=eth_getStorageAt&address=${proxyAddress}&position=${implementationSlot}&tag=latest&apikey=${ETHERSCAN_API_KEY}`;
const headers = {
'Content-Type': 'application/json',
};
try {
const {data} = await axios.get(url, {headers});
const {result} = data;
return result;
} catch (error: any) {
throw error.message;
}
};

const EtherscanAPI = {
getContractAbi,
getStorageAt,
};

export default EtherscanAPI;
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import haptic from '../../haptic-feedback/haptic';
import CloseModal from '../../../../assets/img/close-modal-icon.svg';
import {WIDTH} from '../../styled/Containers';
import {useNavigation} from '@react-navigation/native';
import {getWalletByRequest} from '../../../store/wallet-connect-v2/wallet-connect-v2.effects';
import {getGasWalletByRequest} from '../../../store/wallet-connect-v2/wallet-connect-v2.effects';
import {sleep} from '../../../utils/helper-methods';

export type InAppNotificationMessages = 'NEW_PENDING_REQUEST';
Expand Down Expand Up @@ -84,14 +84,15 @@ const InAppNotification: React.FC = () => {

await sleep(0);

const wallet = request && dispatch(getWalletByRequest(request));
const wallet = request && dispatch(getGasWalletByRequest(request));
if (!wallet || !wallet.receiveAddress) {
return;
}

navigation.navigate('WalletConnectHome', {
topic: request?.topic,
selectedAccountAddress: wallet.receiveAddress,
notificationRequestId: request.id,
keyId: wallet.keyId,
context: 'notification',
});
Expand Down
22 changes: 11 additions & 11 deletions src/components/modal/wallet-connect/VerifyModalContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
UriContainerTouchable,
} from '../../../components/modal/wallet-connect/WalletConnectStartModal';
import ExternalLinkSvg from '../../../../assets/img/external-link-small.svg';
import {Caution, NotificationPrimary} from '../../../styles/colors';
import {sleep} from '../../../utils/helper-methods';
import {useTranslation} from 'react-i18next';
import {
Expand All @@ -26,6 +25,7 @@ import TrustedDomainSvg from '../../../../assets/img/trusted-domain.svg';
import InvalidDomainSvg from '../../../../assets/img/invalid-domain.svg';
import DefaultImage from '../../../../assets/img/wallet-connect/default-icon.svg';
import {View} from 'react-native';
import {BottomNotificationCta} from '../bottom-notification/BottomNotification';

const CloseModalButton = styled.TouchableOpacity`
height: 40px;
Expand Down Expand Up @@ -168,21 +168,21 @@ const VerifyContextModal = ({
icon={VerifyIcon}
/>
<RowContainer style={{paddingTop: 16}}>
<StyledTouchableOpacity onPress={closeModal}>
<H6 medium style={{color: NotificationPrimary}}>
{t('I UNDERSTAND')}
</H6>
</StyledTouchableOpacity>
<StyledTouchableOpacity
<BottomNotificationCta
onPress={closeModal}
suppressHighlighting={true}
primary={true}>
{t('I UNDERSTAND')}
</BottomNotificationCta>
<BottomNotificationCta
suppressHighlighting={true}
onPress={async () => {
closeModal();
await sleep(1000);
onRemovePress();
}}>
<H6 medium style={{color: Caution}}>
{t('REMOVE')}
</H6>
</StyledTouchableOpacity>
{t('REMOVE')}
</BottomNotificationCta>
</RowContainer>
</ContentContainer>
</WalletSelectMenuContainer>
Expand Down
95 changes: 55 additions & 40 deletions src/components/modal/wallet-connect/WalletConnectStartModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
CHAIN_NAME_MAPPING,
EIP155_SIGNING_METHODS,
WALLET_CONNECT_SUPPORTED_CHAINS,
WC_EVENTS,
} from '../../../constants/WalletConnectV2';
import {Web3WalletTypes} from '@walletconnect/web3wallet';
import FastImage from 'react-native-fast-image';
Expand Down Expand Up @@ -114,7 +115,10 @@ const ValidationText = styled(BaseText)<{textColor: string}>`
color: ${({textColor}) => textColor};
font-size: 12px;
`;
const TitleContainer = styled.View``;

const TitleContainer = styled.View`
padding-bottom: 20px;
`;

const DescriptionContainer = styled.View`
margin-bottom: 16px;
Expand Down Expand Up @@ -149,6 +153,14 @@ const AccountSettingsContainer = styled.TouchableOpacity`
gap: 8px;
`;

const AccountSettingsArrowContainer = styled.View`
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
gap: 8px;
`;

const styles = StyleSheet.create({
icon: {
height: 80,
Expand Down Expand Up @@ -212,6 +224,9 @@ export const WalletConnectStartModal = () => {
const NETWORK_ERROR_PREFIX =
"Non conforming namespaces. approve() namespaces chains don't satisfy required namespaces.";

const EVENTS_ERROR_PREFIX =
"Non conforming namespaces. approve() namespaces events don't satisfy namespace events for eip155:1";

if (error.includes(NETWORK_ERROR_PREFIX)) {
// Replace chain codes with corresponding chain names
error = error.replace(/eip155:\d+/g, match => {
Expand All @@ -223,6 +238,11 @@ export const WalletConnectStartModal = () => {
let approvedPart = parts[1].replace(/,/g, ', ');
const transformedMessage = `Network compatibility issue. The supported networks do not meet the requirements.\n\nRequired Networks:\n${requiredPart}\n\nSupported Networks:\n${approvedPart}`;
return transformedMessage;
}
if (error.includes(EVENTS_ERROR_PREFIX)) {
const transformedMessage =
'Events compatibility issue. The current supported events are insufficient to fulfill the requirements of the DApp.';
return transformedMessage;
} else {
return error;
}
Expand All @@ -246,9 +266,9 @@ export const WalletConnectStartModal = () => {
proposal: proposal.params,
supportedNamespaces: {
eip155: {
chains,
chains: uniqueChains,
methods: Object.values(EIP155_SIGNING_METHODS),
events: ['chainChanged', 'accountsChanged'],
events: WC_EVENTS,
accounts,
},
},
Expand Down Expand Up @@ -597,47 +617,42 @@ export const WalletConnectStartModal = () => {
<H7
medium={true}
style={{color: theme.dark ? White : SlateDark}}>
{t('Accounts')}
{t('Account')}
</H7>
<DescriptionItemContainer>
{allKeys && allKeys[0]?.accounts[0] && checkedAccount ? (
<>
<AccountSettingsContainer
activeOpacity={ActiveOpacity}
onPress={() => {
setShowAccountWCV2SelectionBottomModal(true);
}}>
<CurrencyImageContainer
style={{height: 30, width: 30}}>
<Blockie
size={30}
seed={checkedAccount.receiveAddress}
/>
</CurrencyImageContainer>
<Row>
<H6
medium={true}
ellipsizeMode="tail"
numberOfLines={1}>
{checkedAccount.accountName}
{allKeys[0]?.accounts.length > 1 ? (
<BaseText
style={{
color: theme.dark ? White : SlateDark,
}}>
{' '}
(+{allKeys[0]?.accounts.length - 1})
</BaseText>
) : (
''
)}
</H6>
</Row>
</AccountSettingsContainer>
{allKeys[0]?.accounts.length > 0 ? (
<SelectorArrowRight />
<AccountSettingsContainer
activeOpacity={ActiveOpacity}
onPress={() => {
setShowAccountWCV2SelectionBottomModal(true);
}}>
<CurrencyImageContainer style={{height: 30, width: 30}}>
<Blockie
size={30}
seed={checkedAccount.receiveAddress}
/>
</CurrencyImageContainer>
<Row>
<H6
medium={true}
ellipsizeMode="tail"
numberOfLines={1}>
{checkedAccount.accountName}
</H6>
</Row>
{allKeys[0]?.accounts.length > 1 ? (
<AccountSettingsArrowContainer>
<BaseText
style={{
fontSize: 16,
color: theme.dark ? White : SlateDark,
}}>
(+{allKeys[0]?.accounts.length - 1})
</BaseText>
<SelectorArrowRight />
</AccountSettingsArrowContainer>
) : null}
</>
</AccountSettingsContainer>
) : (
<DescriptionItemContainer>
<WarningBrownSvg />
Expand Down
8 changes: 8 additions & 0 deletions src/constants/WalletConnectV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ export const WALLETCONNECT_V2_METADATA = {
icons: ['https://bitpay.com/resources/content/images/2019/10/bitpay.png'],
};

export const WC_EVENTS = [
'chainChanged',
'accountsChanged',
'message',
'disconnect',
'connect',
];

export const CHAIN_NAME_MAPPING: {[key: string]: string} = {
// ETHEREUM
'1': 'Ethereum Mainnet',
Expand Down
Loading

0 comments on commit 750a689

Please sign in to comment.