Skip to content

Commit

Permalink
Merge pull request #199 from celo-org/therealharpaljadeja/react-nativ…
Browse files Browse the repository at this point in the history
…e-walletconnect-v2

Add WalletConnect v2 support for React Native Expo example
  • Loading branch information
viral-sangani authored Jul 11, 2023
2 parents 7278b19 + 58e2ac3 commit ff90b5d
Show file tree
Hide file tree
Showing 30 changed files with 11,250 additions and 344 deletions.
2 changes: 2 additions & 0 deletions packages/react-native-app/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ENV_PROJECT_ID=
ENV_RELAY_URL=
10 changes: 10 additions & 0 deletions packages/react-native-app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import useCachedResources from "./hooks/useCachedResources";
import useColorScheme from "./hooks/useColorScheme";
import Navigation from "./navigation";
import { ThemeProvider } from "./context/ThemeProvider";
import { Web3Modal } from "@web3modal/react-native";
import { providerMetadata, sessionParams } from "./constants/Config";

// @ts-expect-error - `@env` is a virtualised module via Babel config.
import { ENV_PROJECT_ID } from "@env";

export default function App() {
const isLoadingComplete = useCachedResources();
Expand All @@ -25,6 +30,11 @@ export default function App() {
<SafeAreaProvider>
<Navigation colorScheme={colorScheme} />
<StatusBar />
<Web3Modal
projectId={ENV_PROJECT_ID}
providerMetadata={providerMetadata}
sessionParams={sessionParams}
/>
</SafeAreaProvider>
</ThemeProvider>
);
Expand Down
3 changes: 1 addition & 2 deletions packages/react-native-app/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
"userInterfaceStyle": "automatic",
"splash": {
"image": "./assets/images/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
"resizeMode": "cover"
},
"updates": {
"fallbackToCacheTimeout": 0
Expand Down
Binary file modified packages/react-native-app/assets/images/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/react-native-app/assets/images/splash.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 20 additions & 5 deletions packages/react-native-app/babel.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo']
};
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: [
[
"module:react-native-dotenv",
{
envName: "APP_ENV",
moduleName: "@env",
path: ".env",
blocklist: null,
allowlist: null,
safe: false,
allowUndefined: true,
verbose: false,
},
],
],
};
};
6 changes: 3 additions & 3 deletions packages/react-native-app/components/AccountAddress.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useWalletConnect } from "@walletconnect/react-native-dapp";
import { useContext } from "react";
import { ThemeContext } from "../context/ThemeProvider";
import { Text } from "./Themed";
import { useWeb3Modal } from "@web3modal/react-native";

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

return <Text style={styles.externalLink}>{connector.accounts[0]}</Text>;
return <Text style={styles.externalLink}>{address}</Text>;
};

export default AccountAddress;
17 changes: 2 additions & 15 deletions packages/react-native-app/components/AccountBalance.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,10 @@
import { Text, View } from "./Themed";
import { newKit } from "@celo/contractkit";
import { useWeb3Modal } from "@web3modal/react-native";
import { useEffect, useState } from "react";
import { useWalletConnect } from "@walletconnect/react-native-dapp";

const AccountBalance = () => {
let connector = useWalletConnect();
const [balances, setBalances] = useState<any>(null);

useEffect(() => {
(async () => {
let kit = newKit("https://alfajores-forno.celo-testnet.org");
let balances = await kit.getTotalBalance(connector.accounts[0]);
console.log(balances.CELO);
Object.keys(balances).map((balance) =>
console.log(balance, balances[balance].toString())
);
setBalances(balances);
})();
}, [connector]);
const { address } = useWeb3Modal();

return (
<View>
Expand Down
203 changes: 203 additions & 0 deletions packages/react-native-app/components/BlockchainActions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
import React from "react";
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,
},
});
6 changes: 1 addition & 5 deletions packages/react-native-app/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { TouchableOpacity } from "react-native";
import { useThemeColor } from "./Themed";

type ThemeProps = {
lightColor?: string;
Expand All @@ -10,10 +9,7 @@ export type TouchableOpacityProps = ThemeProps & TouchableOpacity["props"];

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

return (
<TouchableOpacity
style={[
Expand Down
Loading

0 comments on commit ff90b5d

Please sign in to comment.