diff --git a/packages/react-native-app/.env.example b/packages/react-native-app/.env.example new file mode 100644 index 00000000..3d2d6084 --- /dev/null +++ b/packages/react-native-app/.env.example @@ -0,0 +1,2 @@ +ENV_PROJECT_ID= +ENV_RELAY_URL= diff --git a/packages/react-native-app/App.tsx b/packages/react-native-app/App.tsx index ead70de5..79757500 100644 --- a/packages/react-native-app/App.tsx +++ b/packages/react-native-app/App.tsx @@ -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(); @@ -25,6 +30,11 @@ export default function App() { + ); diff --git a/packages/react-native-app/app.json b/packages/react-native-app/app.json index 64ac7e2e..043692d7 100644 --- a/packages/react-native-app/app.json +++ b/packages/react-native-app/app.json @@ -9,8 +9,7 @@ "userInterfaceStyle": "automatic", "splash": { "image": "./assets/images/splash.png", - "resizeMode": "contain", - "backgroundColor": "#ffffff" + "resizeMode": "cover" }, "updates": { "fallbackToCacheTimeout": 0 diff --git a/packages/react-native-app/assets/images/icon.png b/packages/react-native-app/assets/images/icon.png index a0b1526f..67633525 100644 Binary files a/packages/react-native-app/assets/images/icon.png and b/packages/react-native-app/assets/images/icon.png differ diff --git a/packages/react-native-app/assets/images/splash.png b/packages/react-native-app/assets/images/splash.png index 0e89705a..390b8b38 100644 Binary files a/packages/react-native-app/assets/images/splash.png and b/packages/react-native-app/assets/images/splash.png differ diff --git a/packages/react-native-app/babel.config.js b/packages/react-native-app/babel.config.js index baac9e50..587d1c7c 100644 --- a/packages/react-native-app/babel.config.js +++ b/packages/react-native-app/babel.config.js @@ -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, + }, + ], + ], + }; }; diff --git a/packages/react-native-app/components/AccountAddress.tsx b/packages/react-native-app/components/AccountAddress.tsx index ed8da2a8..9c63928d 100644 --- a/packages/react-native-app/components/AccountAddress.tsx +++ b/packages/react-native-app/components/AccountAddress.tsx @@ -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 {connector.accounts[0]}; + return {address}; }; export default AccountAddress; diff --git a/packages/react-native-app/components/AccountBalance.tsx b/packages/react-native-app/components/AccountBalance.tsx index 303562a7..23c0c8b9 100644 --- a/packages/react-native-app/components/AccountBalance.tsx +++ b/packages/react-native-app/components/AccountBalance.tsx @@ -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(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 ( diff --git a/packages/react-native-app/components/BlockchainActions.tsx b/packages/react-native-app/components/BlockchainActions.tsx new file mode 100644 index 00000000..34cdfbf4 --- /dev/null +++ b/packages/react-native-app/components/BlockchainActions.tsx @@ -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(); + const [rpcError, setRpcError] = useState(); + 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 + ) => + 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 ( + <> + + } + contentContainerStyle={styles.listContent} + renderItem={({ item }) => ( + + )} + /> + + + ); +} + +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, + }, +}); diff --git a/packages/react-native-app/components/Button.tsx b/packages/react-native-app/components/Button.tsx index 102303b6..5bbf9114 100644 --- a/packages/react-native-app/components/Button.tsx +++ b/packages/react-native-app/components/Button.tsx @@ -1,5 +1,4 @@ import { TouchableOpacity } from "react-native"; -import { useThemeColor } from "./Themed"; type ThemeProps = { lightColor?: string; @@ -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 ( void; + isLoading?: boolean; + rpcResponse?: FormattedRpcResponse; + rpcError?: FormattedRpcError; +} + +export function RequestModal({ + isVisible, + onClose, + isLoading, + rpcResponse, + rpcError, +}: Props) { + return ( + + + + + + {isLoading && ( + <> + Pending Request + + + Approve or reject request using your wallet if + needed + + + )} + {rpcResponse && ( + <> + + Request Response + + {Object.keys(rpcResponse).map((key) => ( + + {key}:{" "} + + {rpcResponse[ + key as keyof FormattedRpcResponse + ]?.toString()} + + + ))} + + )} + {rpcError && ( + <> + + Request Failure + + + Method:{" "} + + {rpcError.method} + + + + Error:{" "} + + {rpcError.error} + + + + )} + + + ); +} + +const styles = StyleSheet.create({ + closeButton: { + alignSelf: "flex-end", + backgroundColor: "white", + height: 30, + width: 30, + alignItems: "center", + justifyContent: "center", + borderRadius: 100, + margin: 8, + }, + innerContainer: { + padding: 16, + backgroundColor: "white", + borderRadius: 8, + borderTopLeftRadius: 30, + borderTopRightRadius: 30, + borderBottomLeftRadius: 30, + borderBottomRightRadius: 30, + }, + loader: { + marginVertical: 24, + }, + title: { + fontWeight: "600", + fontSize: 16, + textAlign: "center", + marginBottom: 8, + }, + successText: { + color: Colors.brand.light.text, + }, + failureText: { + color: "#F05142", + }, + subtitle: { + fontWeight: "bold", + marginVertical: 4, + }, + center: { + textAlign: "center", + }, + responseText: { + fontWeight: "300", + }, +}); diff --git a/packages/react-native-app/components/Themed.tsx b/packages/react-native-app/components/Themed.tsx index 19d3d754..4430b4a8 100644 --- a/packages/react-native-app/components/Themed.tsx +++ b/packages/react-native-app/components/Themed.tsx @@ -3,50 +3,27 @@ * https://docs.expo.io/guides/color-schemes/ */ -import { - Text as DefaultText, - View as DefaultView, - TouchableOpacity as DefaultTouchableOpacity, -} from "react-native"; - +import { Text as DefaultText, View as DefaultView } from "react-native"; import Colors from "../constants/Colors"; -import useColorScheme from "../hooks/useColorScheme"; - -export function useThemeColor( - props: { light?: string; dark?: string }, - colorName: keyof typeof Colors.brand.light & keyof typeof Colors.brand.dark -) { - const theme = useColorScheme(); - const colorFromProps = props[theme]; - - if (colorFromProps) { - return colorFromProps; - } else { - return Colors.brand[theme][colorName]; - } -} - -type ThemeProps = { - lightColor?: string; - darkColor?: string; -}; -export type TextProps = ThemeProps & DefaultText["props"]; -export type ViewProps = ThemeProps & DefaultView["props"]; +export type TextProps = DefaultText["props"]; +export type ViewProps = DefaultView["props"]; export function Text(props: TextProps) { - const { style, lightColor, darkColor, ...otherProps } = props; - const color = useThemeColor({ light: lightColor, dark: darkColor }, "text"); + const { style, ...otherProps } = props; - return ; + return ; } export function View(props: ViewProps) { - const { style, lightColor, darkColor, ...otherProps } = props; - const backgroundColor = useThemeColor( - { light: lightColor, dark: darkColor }, - 200 + const { style, ...otherProps } = props; + + return ( + ); - - return ; } diff --git a/packages/react-native-app/constants/Config.ts b/packages/react-native-app/constants/Config.ts new file mode 100644 index 00000000..12a6aef1 --- /dev/null +++ b/packages/react-native-app/constants/Config.ts @@ -0,0 +1,23 @@ +export const providerMetadata = { + name: "Celo Composer", + description: "Celo Composer build on Celo", + url: "https://celo.org/", + icons: ["https://avatars.githubusercontent.com/u/37784886"], +}; + +export const sessionParams = { + namespaces: { + eip155: { + methods: [ + "eth_sendTransaction", + "eth_signTransaction", + "eth_sign", + "personal_sign", + "eth_signTypedData", + ], + chains: ["eip155:44787"], + events: ["chainChanged", "accountsChanged"], + rpcMap: {}, + }, + }, +}; diff --git a/packages/react-native-app/constants/Contract.ts b/packages/react-native-app/constants/Contract.ts new file mode 100644 index 00000000..32bc8e01 --- /dev/null +++ b/packages/react-native-app/constants/Contract.ts @@ -0,0 +1,80 @@ +// Tether (USDT) +const contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7"; + +// vitalik.eth +const balanceAddress = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; + +const readContractAbi = [ + { + constant: true, + inputs: [], + name: "name", + outputs: [ + { + name: "", + type: "string", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "symbol", + outputs: [ + { + name: "", + type: "string", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "totalSupply", + outputs: [ + { + name: "", + type: "uint256", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [ + { + name: "_owner", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + name: "balance", + type: "uint256", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, +]; + +const getFilterChangesAbi = [ + "event Transfer(address indexed from, address indexed to, uint amount)", +]; + +export default { + contractAddress, + balanceAddress, + readContractAbi, + getFilterChangesAbi, +}; diff --git a/packages/react-native-app/constants/eip712.ts b/packages/react-native-app/constants/eip712.ts new file mode 100644 index 00000000..32175388 --- /dev/null +++ b/packages/react-native-app/constants/eip712.ts @@ -0,0 +1,38 @@ +// From spec: https://eips.ethereum.org/EIPS/eip-712 +export const getTypedDataExample = (chainId?: number) => ({ + types: { + EIP712Domain: [ + { name: "name", type: "string" }, + { name: "version", type: "string" }, + { name: "chainId", type: "uint256" }, + { name: "verifyingContract", type: "address" }, + ], + Person: [ + { name: "name", type: "string" }, + { name: "wallet", type: "address" }, + ], + Mail: [ + { name: "from", type: "Person" }, + { name: "to", type: "Person" }, + { name: "contents", type: "string" }, + ], + }, + primaryType: "Mail", + domain: { + name: "Ether Mail", + version: "1", + chainId: chainId || 1, + verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", + }, + message: { + from: { + name: "Alice", + wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", + }, + to: { + name: "Bob", + wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB", + }, + contents: "Hello, Bob!", + }, +}); diff --git a/packages/react-native-app/context/ThemeProvider.tsx b/packages/react-native-app/context/ThemeProvider.tsx index dbfc9373..3d8b497b 100644 --- a/packages/react-native-app/context/ThemeProvider.tsx +++ b/packages/react-native-app/context/ThemeProvider.tsx @@ -12,9 +12,11 @@ export const ThemeProvider = ({ children }: ThemeProviderProps) => { const styles = StyleSheet.create({ container: { flex: 1, + display: "flex", alignItems: "center", justifyContent: "center", padding: 20, + backgroundColor: Colors.brand.light.background, }, innerContainer: { width: "100%", @@ -22,7 +24,7 @@ export const ThemeProvider = ({ children }: ThemeProviderProps) => { }, title: { fontSize: 20, - fontWeight: "bold", + fontWeight: "500", color: Colors["brand"].light.text, }, separator: { @@ -37,6 +39,7 @@ export const ThemeProvider = ({ children }: ThemeProviderProps) => { textDecorationColor: "white", textDecorationLine: "underline", backgroundColor: "transparent", + fontSize: 12, }, textInput: { borderColor: Colors["brand"].light.text, @@ -66,6 +69,7 @@ export const ThemeProvider = ({ children }: ThemeProviderProps) => { h4: { color: Colors["brand"].light.text, fontSize: 24, + fontWeight: "400", }, h5: { color: Colors["brand"].light.text, diff --git a/packages/react-native-app/global.ts b/packages/react-native-app/global.ts deleted file mode 100644 index 2198cf02..00000000 --- a/packages/react-native-app/global.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Platform, LogBox } from "react-native"; - -export interface Global { - btoa: any - atob: any - self: any - Buffer: any - process: any - location: any -} - -declare var global: Global -if (typeof global.self === 'undefined') { - global.self = global -} - -if (Platform.OS !== "web") { - require("react-native-get-random-values"); - LogBox.ignoreLogs([ - "Warning: The provided value 'ms-stream' is not a valid 'responseType'.", - "Warning: The provided value 'moz-chunked-arraybuffer' is not a valid 'responseType'.", - ]); - } - -global.btoa = global.btoa || require('base-64').encode; -global.atob = global.atob || require('base-64').decode; - -global.Buffer = require('buffer').Buffer - -global.process = require('process') -global.process.env.NODE_ENV = __DEV__ ? 'development' : 'production'; -global.process.version = 'v9.40'; - -global.location = { - protocol: 'https', -} \ No newline at end of file diff --git a/packages/react-native-app/index.js b/packages/react-native-app/index.js index afd5ff79..78934219 100644 --- a/packages/react-native-app/index.js +++ b/packages/react-native-app/index.js @@ -1,25 +1,9 @@ -import "./global"; +import "./shim"; import App from "./App"; -import { registerRootComponent, scheme } from "expo"; -const { - default: AsyncStorage, -} = require("@react-native-async-storage/async-storage"); -const { withWalletConnect } = require("@walletconnect/react-native-dapp"); +import { registerRootComponent } from "expo"; +import "@walletconnect/react-native-compat"; // registerRootComponent calls AppRegistry.registerComponent('main', () => App); // It also ensures that whether you load the app in Expo Go or in a native build, // the environment is set up appropriately -registerRootComponent( - withWalletConnect(App, { - clientMeta: { - // Change App name here to see it in other wallets. - name: "Celo Composer React Native", - description: "React Native Starter Project to build on Celo", - }, - redirectUrl: - Platform.OS === "web" ? window.location.origin : `${scheme}://`, - storageOptions: { - asyncStorage: AsyncStorage, - }, - }) -); +registerRootComponent(App); diff --git a/packages/react-native-app/metro.config.js b/packages/react-native-app/metro.config.js deleted file mode 100644 index b80f2279..00000000 --- a/packages/react-native-app/metro.config.js +++ /dev/null @@ -1,37 +0,0 @@ -// Learn more https://docs.expo.io/guides/customizing-metro -const { getDefaultConfig } = require("expo/metro-config"); -const path = require("path"); -const crypto = require.resolve("crypto-browserify"); -const url = require.resolve("url/"); - -// Find the workspace root, this can be replaced with `find-yarn-workspace-root` -const workspaceRoot = path.resolve(__dirname, "../.."); -const projectRoot = __dirname; - -const config = getDefaultConfig(projectRoot); - -// 1. Watch all files within the monorepo -config.watchFolders = [workspaceRoot]; -// 2. Let Metro know where to resolve packages, and in what order -config.resolver.nodeModulesPaths = [ - path.resolve(projectRoot, "node_modules"), - path.resolve(workspaceRoot, "node_modules"), -]; - -module.exports = { - ...config, - resolver: { - extraNodeModules: { - crypto, - url, - fs: require.resolve("expo-file-system"), - http: require.resolve("stream-http"), - https: require.resolve("https-browserify"), - // net: require.resolve("react-native-tcp"), - os: require.resolve("os-browserify/browser.js"), - path: require.resolve("path-browserify"), - stream: require.resolve("readable-stream"), - vm: require.resolve("vm-browserify"), - }, - }, -}; diff --git a/packages/react-native-app/navigation/index.tsx b/packages/react-native-app/navigation/index.tsx index 445b92e7..23761f7d 100644 --- a/packages/react-native-app/navigation/index.tsx +++ b/packages/react-native-app/navigation/index.tsx @@ -12,8 +12,7 @@ import { } from "@react-navigation/native"; import { createNativeStackNavigator } from "@react-navigation/native-stack"; import * as React from "react"; -import { ColorSchemeName, Button } from "react-native"; -import { useWalletConnect } from "@walletconnect/react-native-dapp"; +import { ColorSchemeName } from "react-native"; import Colors from "../constants/Colors"; import useColorScheme from "../hooks/useColorScheme"; import ModalScreen from "../screens/ModalScreen"; @@ -21,9 +20,9 @@ import NotFoundScreen from "../screens/NotFoundScreen"; import { RootStackParamList, RootTabParamList } from "../types"; import LinkingConfiguration from "./LinkingConfiguration"; import LoginScreen from "../screens/LoginScreen"; -// import deployedContracts from "@celo-composer/hardhat/deployments/hardhat_contracts.json"; import Account from "../screens/Account"; import Docs from "../screens/Docs"; +import { useWeb3Modal } from "@web3modal/react-native"; export default function Navigation({ colorScheme, @@ -47,10 +46,10 @@ export default function Navigation({ const Stack = createNativeStackNavigator(); function RootNavigator() { - const connector = useWalletConnect(); + const { isConnected } = useWeb3Modal(); return ( - {connector.connected ? ( + {isConnected ? ( (); function BottomTabNavigator() { const theme = useColorScheme(); - // const contracts = deployedContracts["44787"]?.["alfajores"]?.contracts; - return ( - {/* ( - - )} + ({ - title: "Greeter Contract", - headerShown: false, - // render icons if any - tabBarIcon: ({ - focused: boolean, - color: string, - size: number, - }) => { + tabBarIcon: () => { return <>; }, tabBarLabelPosition: "beside-icon", })} + component={Docs} /> - ( - - )} - options={{ - title: "Storage Contract", - headerShown: false, - tabBarIcon: ({ - focused: boolean, - color: string, - size: number, - }) => { - return <>; - }, - tabBarLabelPosition: "beside-icon", - }} - /> */} - ({ title: "Account", headerShown: false, - tabBarIcon: ({ - focused: boolean, - color: string, - size: number, - }) => { + tabBarIcon: () => { return <>; }, tabBarLabelPosition: "beside-icon", diff --git a/packages/react-native-app/package.json b/packages/react-native-app/package.json index bfae9123..5fdc3518 100644 --- a/packages/react-native-app/package.json +++ b/packages/react-native-app/package.json @@ -19,8 +19,11 @@ "@react-navigation/bottom-tabs": "^6.0.5", "@react-navigation/native": "^6.0.2", "@react-navigation/native-stack": "^6.1.0", - "@walletconnect/react-native-dapp": "^1.7.7", + "@walletconnect/encoding": "^1.0.2", + "@walletconnect/react-native-compat": "^2.7.7", + "@web3modal/react-native": "^1.0.0-alpha.5", "base-64": "^1.0.0", + "big-integer": "^1.6.51", "crypto-browserify": "^3.12.0", "expo": "^47.0.0", "expo-asset": "~8.6.2", @@ -30,22 +33,16 @@ "expo-splash-screen": "~0.17.5", "expo-status-bar": "~1.4.2", "expo-web-browser": "~12.0.0", - "https-browserify": "^1.0.0", - "node-libs-react-native": "^1.2.1", - "os-browserify": "^0.3.0", - "path-browserify": "^1.0.1", "react": "18.1.0", "react-dom": "18.1.0", - "react-native": "0.70.5", - "react-native-get-random-values": "^1.7.2", + "react-native": "0.70.8", + "react-native-dotenv": "^3.4.8", + "react-native-get-random-values": "~1.8.0", + "react-native-modal": "^13.0.1", "react-native-safe-area-context": "4.4.1", "react-native-screens": "~3.18.1", - "react-native-web": "0.18.9", - "stream-http": "^3.2.0", - "vm-browserify": "^1.1.2", - "web3": "^1.8.0", - "@celo/contractkit": "^3.1.0", - "stream-browserify": "^3.0.0" + "react-native-svg": "13.4.0", + "react-native-web": "0.18.9" }, "devDependencies": { "@babel/core": "^7.12.9", diff --git a/packages/react-native-app/screens/Account.tsx b/packages/react-native-app/screens/Account.tsx index da50bdd3..f27d6229 100644 --- a/packages/react-native-app/screens/Account.tsx +++ b/packages/react-native-app/screens/Account.tsx @@ -1,22 +1,21 @@ import { useState, useEffect, useContext } from "react"; -import { StyleSheet, ActivityIndicator, TextInput } from "react-native"; -import { useWalletConnect } from "@walletconnect/react-native-dapp"; import { Text, View } from "../components/Themed"; import Button from "../components/Button"; import * as WebBrowser from "expo-web-browser"; -import Web3 from "web3"; import { ThemeContext } from "../context/ThemeProvider"; import AccountAddress from "../components/AccountAddress"; import AccountBalance from "../components/AccountBalance"; import Colors from "../constants/Colors"; +import { useWeb3Modal } from "@web3modal/react-native"; +import { BlockchainActions } from "../components/BlockchainActions"; export default function Account() { - const connector = useWalletConnect(); + const { address, provider } = useWeb3Modal(); const { styles } = useContext(ThemeContext); const [accountLink, setAccountLink] = useState(); useEffect(() => { - setAccountLink(`https://celoscan.io/address/${connector.accounts[0]}`); - }, [connector]); + setAccountLink(`https://celoscan.io/address/${address}`); + }, [address]); function handlePress() { WebBrowser.openBrowserAsync(accountLink); @@ -25,14 +24,14 @@ export default function Account() { return ( - Account Info + Connected As: + - -