Skip to content

Commit

Permalink
feat: upgrade to WalletConnectV2
Browse files Browse the repository at this point in the history
  • Loading branch information
therealharpaljadeja committed Jun 19, 2023
1 parent 8902931 commit 29ace10
Show file tree
Hide file tree
Showing 33 changed files with 2,190 additions and 2,782 deletions.
49 changes: 21 additions & 28 deletions packages/react-native-app-without-expo/App.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
// @ts-expect-error - `@env` is a virtualised module via Babel config.
import {ENV_PROJECT_ID} from '@env';

import React from 'react';
import {Platform, StatusBar, StyleSheet} from 'react-native';
import {StatusBar, StyleSheet} from 'react-native';
import {SafeAreaProvider} from 'react-native-safe-area-context';
import {useEffect} from 'react';
import {LogBox} from 'react-native';
import useColorScheme from './hooks/useColorScheme';
import Navigation from './navigation';
import {ThemeProvider} from './context/ThemeProvider';
import WalletConnectProvider from '@walletconnect/react-native-dapp';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {Web3Modal} from '@web3modal/react-native';
import {providerMetadata, sessionParams} from './constants/Config';

console.log(ENV_PROJECT_ID);

const App = () => {
const colorScheme = useColorScheme();
Expand All @@ -18,31 +23,19 @@ const App = () => {
}, []);

return (
<WalletConnectProvider
bridge="https://bridge.walletconnect.org"
clientMeta={{
name: 'Celo Composer React Native without expo',
description: 'React Native Starter Project to build on Celo',
url: 'https://celo.org',
icons: ['https://walletconnect.org/walletconnect-logo.png'],
}}
redirectUrl={
Platform.OS === 'web'
? window.location.origin
: `rnWithoutExpoCeloComposer://`
}
storageOptions={{
asyncStorage: AsyncStorage,
}}>
<ThemeProvider>
<SafeAreaProvider>
<Navigation colorScheme={colorScheme} />
<StatusBar
barStyle={colorScheme == 'dark' ? 'light-content' : 'dark-content'}
/>
</SafeAreaProvider>
</ThemeProvider>
</WalletConnectProvider>
<ThemeProvider>
<SafeAreaProvider>
<Navigation colorScheme={colorScheme} />
<StatusBar
barStyle={colorScheme == 'dark' ? 'light-content' : 'dark-content'}
/>
<Web3Modal
projectId={ENV_PROJECT_ID}
providerMetadata={providerMetadata}
sessionParams={sessionParams}
/>
</SafeAreaProvider>
</ThemeProvider>
);
};

Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {useContext} from 'react';
import {ThemeContext} from '../context/ThemeProvider';
import {Text} from './Themed';
import {useWeb3Modal} from '@web3modal/react-native';

const AccountAddress = () => {
const {styles} = useContext(ThemeContext);
const {address} = useWeb3Modal();

return <Text style={styles.externalLink}>{address}</Text>;
};

export default AccountAddress;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {Text, View} from './Themed';
import {useWeb3Modal} from '@web3modal/react-native';
import {useEffect, useState} from 'react';

const AccountBalance = () => {
const [balances, setBalances] = useState<any>(null);
const {address} = useWeb3Modal();

return (
<View>
{balances
? Object.keys(balances).map(key => (
<Text>{`${key}: ${balances[key]}`}</Text>
))
: null}
</View>
);
};

export default AccountBalance;
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
import {useWeb3Modal, Web3Button} from '@web3modal/react-native';
import {ethers} from 'ethers';
import {useMemo, useState} from 'react';
import {FlatList, StyleSheet, Text, TouchableOpacity} from 'react-native';

import type {
AccountAction,
FormattedRpcError,
FormattedRpcResponse,
RpcRequestParams,
} from '../types';
import {getFilterChanges, readContract} from '../utils/ContractUtil';
import {
ethSign,
sendTransaction,
signMessage,
signTransaction,
signTypedData,
} from '../utils/MethodUtil';
import {RequestModal} from './RequestModal';
import Button from './Button';

export function BlockchainActions() {
const [rpcResponse, setRpcResponse] = useState<FormattedRpcResponse>();
const [rpcError, setRpcError] = useState<FormattedRpcError>();
const {provider} = useWeb3Modal();

const web3Provider = useMemo(
() => (provider ? new ethers.providers.Web3Provider(provider) : undefined),
[provider],
);

const [loading, setLoading] = useState(false);
const [modalVisible, setModalVisible] = useState(false);

const onModalClose = () => {
setModalVisible(false);
setLoading(false);
setRpcResponse(undefined);
setRpcError(undefined);
};

const getEthereumActions = () => {
const wrapRpcRequest =
(
method: string,
rpcRequest: ({
web3Provider,
method,
}: RpcRequestParams) => Promise<FormattedRpcResponse>,
) =>
async () => {
if (!web3Provider) {
return;
}

setRpcResponse(undefined);
setRpcError(undefined);
setModalVisible(true);
try {
setLoading(true);
const result = await rpcRequest({web3Provider, method});
setRpcResponse(result);
setRpcError(undefined);
} catch (error: any) {
console.error('RPC request failed:', error);
setRpcResponse(undefined);
setRpcError({method, error: error?.message});
} finally {
setLoading(false);
}
};

const actions: AccountAction[] = [
{
method: 'eth_sendTransaction',
callback: wrapRpcRequest('eth_sendTransaction', sendTransaction),
},
{
method: 'eth_signTransaction',
callback: wrapRpcRequest('eth_signTransaction', signTransaction),
},
{
method: 'personal_sign',
callback: wrapRpcRequest('personal_sign', signMessage),
},
{
method: 'eth_sign (standard)',
callback: wrapRpcRequest('eth_sign (standard)', ethSign),
},
{
method: 'eth_signTypedData',
callback: wrapRpcRequest('eth_signTypedData', signTypedData),
},
{
method: 'read contract (mainnet)',
callback: wrapRpcRequest('read contract', readContract),
},
{
method: 'filter contract (mainnet)',
callback: wrapRpcRequest('filter contract', getFilterChanges),
},
];
return actions;
};

return (
<>
<FlatList
data={getEthereumActions()}
ListHeaderComponent={
<Web3Button
style={[
{backgroundColor: 'black'},
{
paddingHorizontal: 15,
paddingVertical: 7,
marginTop: 10,
borderRadius: 5,
},
]}
/>
}
contentContainerStyle={styles.listContent}
renderItem={({item}) => (
<Button
style={[
{backgroundColor: 'black'},
{
paddingHorizontal: 15,
paddingVertical: 7,
marginTop: 10,
borderRadius: 5,
},
]}
key={item.method}
onPress={() => item.callback(web3Provider)}>
<Text style={styles.buttonText}>{item.method}</Text>
</Button>
)}
/>
<RequestModal
rpcResponse={rpcResponse}
rpcError={rpcError}
isLoading={loading}
isVisible={modalVisible}
onClose={onModalClose}
/>
</>
);
}

const styles = StyleSheet.create({
button: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#3396FF',
borderRadius: 20,
width: 200,
height: 50,
borderWidth: 1,
borderColor: 'rgba(0, 0, 0, 0.1)',
marginTop: 4,
},
buttonText: {
color: 'white',
fontWeight: '700',
},
modalContainer: {
padding: 16,
backgroundColor: 'white',
borderRadius: 8,
},
title: {
fontWeight: '600',
fontSize: 16,
textAlign: 'center',
marginBottom: 8,
},
subtitle: {
fontWeight: 'bold',
marginVertical: 4,
},
responseText: {
fontWeight: '300',
},
listContent: {
alignItems: 'center',
},
web3Button: {
width: 200,
},
});
29 changes: 29 additions & 0 deletions packages/react-native-app-without-expo/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {TouchableOpacity} from 'react-native';

type ThemeProps = {
lightColor?: string;
darkColor?: string;
};

export type TouchableOpacityProps = ThemeProps & TouchableOpacity['props'];

export default function Button(props: TouchableOpacityProps) {
const {style, lightColor, darkColor, children, ...otherProps} = props;

return (
<TouchableOpacity
style={[
{backgroundColor: 'black'},
style,
{
paddingHorizontal: 15,
paddingVertical: 7,
marginTop: 10,
borderRadius: 5,
},
]}
{...otherProps}>
{children}
</TouchableOpacity>
);
}
25 changes: 25 additions & 0 deletions packages/react-native-app-without-expo/components/Container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {ReactNode} from 'react';
import {View, ViewStyle} from 'react-native';
import Colors from '../constants/Colors';

type ContainerProps = {
children: ReactNode;
style: ViewStyle;
};

const Container = ({children, style}: ContainerProps) => {
return (
<View
style={{
backgroundColor: Colors.brand.yellow[75],
borderRadius: 5,
padding: 10,
width: '100%',
...style,
}}>
{children}
</View>
);
};

export default Container;
Loading

0 comments on commit 29ace10

Please sign in to comment.