Integrate wallet connect (#2)

* Configure stack navigation to display header

* Use wallet connect to connect with dApps

* Replace react-native alerts with js alerts

* Add example env file

* Remove unnecessary code

* Make UI changes

* Uncomment required code

* Remove unnecessary dependencies

* Remove any type

* Fix indentation

---------

Co-authored-by: Shreerang Kale <shreerangkale@gmail.com>
Co-authored-by: Nabarun <nabarun@deepstacksoft.com>
This commit is contained in:
Isha Venikar 2024-07-26 10:28:57 +05:30 committed by GitHub
parent 640155aa4a
commit f554c82149
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 1442 additions and 923 deletions

4
.env.example Normal file
View File

@ -0,0 +1,4 @@
REACT_APP_WALLET_CONNECT_PROJECT_ID=
REACT_APP_DEFAULT_GAS_PRICE=0.025
# Reference: https://github.com/cosmos/cosmos-sdk/issues/16020
REACT_APP_GAS_ADJUSTMENT=2

2
.gitignore vendored
View File

@ -21,3 +21,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.env

View File

@ -1,4 +1,5 @@
// TODO: Use Typescript
const webpack = require('webpack')
module.exports = function override(config, env) {
config.module.rules.push({
@ -26,6 +27,12 @@ module.exports = function override(config, env) {
}
});
config.plugins.push(
new webpack.ProvidePlugin({
Buffer: ["buffer", "Buffer"],
})
)
config.module.rules.push({
test: /\.(jpg|png|woff|woff2|eot|ttf|svg)$/,
type: 'asset/resource'
@ -34,6 +41,9 @@ module.exports = function override(config, env) {
config.resolve.fallback = {
crypto: require.resolve("crypto-browserify"),
stream: require.resolve("stream-browserify"),
http: require.resolve('stream-http'),
https: require.resolve('https-browserify'),
url: false
}
config.resolve.alias['react-native$'] = require.resolve('react-native-web');

View File

@ -14,43 +14,31 @@
"@hookform/resolvers": "^3.3.4",
"@json-rpc-tools/utils": "^1.7.6",
"@mui/material": "^5.16.4",
"@react-native-async-storage/async-storage": "^1.22.3",
"@react-native-community/netinfo": "^11.3.1",
"@react-navigation/elements": "^1.3.30",
"@react-navigation/native": "^6.1.10",
"@react-navigation/native-stack": "^6.9.18",
"@react-navigation/stack": "^6.4.1",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^13.0.0",
"@testing-library/user-event": "^13.2.1",
"@types/jest": "^27.0.1",
"@types/node": "^16.7.13",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@walletconnect/web3wallet": "^1.13.0",
"assert": "^2.1.0",
"chain-registry": "^1.41.2",
"cosmjs-types": "^0.9.0",
"ethers": "5.7.2",
"http-browserify": "^1.7.0",
"https-browserify": "^1.0.0",
"lodash": "^4.17.21",
"patch-package": "^8.0.0",
"react": "^18.3.1",
"react-art": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.51.2",
"react-native": "^0.74.3",
"react-native-config": "^1.5.1",
"react-native-get-random-values": "^1.10.0",
"react-native-paper": "^5.12.3",
"react-native-quick-base64": "^2.0.8",
"react-native-quick-crypto": "^0.6.1",
"react-native-safe-area-context": "^4.10.8",
"react-native-screens": "^3.29.0",
"react-native-svg": "^15.1.0",
"react-native-url-polyfill": "^2.0.0",
"react-native-vector-icons": "^10.1.0",
"react-native-web": "^0.19.12",
"react-scripts": "5.0.1",
"stream-http": "^3.2.0",
"text-encoding-polyfill": "^0.6.7",
"typescript": "^4.4.2",
"use-debounce": "^10.0.0",
@ -82,15 +70,12 @@
]
},
"devDependencies": {
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-object-rest-spread": "^7.20.7",
"@babel/preset-env": "^7.24.8",
"@babel/preset-flow": "^7.24.7",
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@types/lodash": "^4.17.7",
"babel-loader": "^9.1.3",
"core-js": "^3.37.1",
"react-app-rewired": "^2.2.1"
"@types/node": "^16.7.13",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"crypto-browserify": "^3.12.0",
"react-app-rewired": "^2.2.1",
"stream-browserify": "^3.0.0"
}
}

View File

@ -1,233 +1,236 @@
import React, { useCallback, useEffect, useState } from 'react';
import { Button, Snackbar, Text } from 'react-native-paper';
// import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
// import { TxBody, AuthInfo } from 'cosmjs-types/cosmos/tx/v1beta1/tx';
import { TxBody, AuthInfo } from 'cosmjs-types/cosmos/tx/v1beta1/tx';
// import { SignClientTypes } from '@walletconnect/types';
import { SignClientTypes } from '@walletconnect/types';
import { useNavigation } from '@react-navigation/native';
import {
NativeStackNavigationProp,
createNativeStackNavigator,
} from '@react-navigation/native-stack';
// import { getSdkError } from '@walletconnect/utils';
// import { Web3WalletTypes } from '@walletconnect/web3wallet';
// import { formatJsonRpcResult } from '@json-rpc-tools/utils';
createStackNavigator,
StackNavigationProp,
} from '@react-navigation/stack';
import { getSdkError } from '@walletconnect/utils';
import { Web3WalletTypes } from '@walletconnect/web3wallet';
import { formatJsonRpcResult } from '@json-rpc-tools/utils';
// import PairingModal from './components/PairingModal';
// import { useWalletConnect } from './context/WalletConnectContext';
import PairingModal from './components/PairingModal';
import { useWalletConnect } from './context/WalletConnectContext';
import { useAccounts } from './context/AccountsContext';
import InvalidPath from './screens/InvalidPath';
import SignMessage from './screens/SignMessage';
import HomeScreen from './screens/HomeScreen';
import SignRequest from './screens/SignRequest';
import AddSession from './screens/AddSession';
// import WalletConnect from './screens/WalletConnect';
import WalletConnect from './screens/WalletConnect';
import ApproveTransaction from './screens/ApproveTransaction';
import { StackParamsList } from './types';
// import { web3wallet } from './utils/wallet-connect/WalletConnectUtils';
// import { EIP155_SIGNING_METHODS } from './utils/wallet-connect/EIP155Data';
// import { getSignParamsMessage } from './utils/wallet-connect/helpers';
import { web3wallet } from './utils/wallet-connect/WalletConnectUtils';
import { EIP155_SIGNING_METHODS } from './utils/wallet-connect/EIP155Data';
import { getSignParamsMessage } from './utils/wallet-connect/helpers';
import ApproveTransfer from './screens/ApproveTransfer';
import AddNetwork from './screens/AddNetwork';
import EditNetwork from './screens/EditNetwork';
// import { COSMOS, EIP155 } from './utils/constants';
import { COSMOS, EIP155 } from './utils/constants';
import { useNetworks } from './context/NetworksContext';
// import { NETWORK_METHODS } from './utils/wallet-connect/common-data';
// import { COSMOS_METHODS } from './utils/wallet-connect/COSMOSData';
import { NETWORK_METHODS } from './utils/wallet-connect/common-data';
import { COSMOS_METHODS } from './utils/wallet-connect/COSMOSData';
const Stack = createNativeStackNavigator<StackParamsList>();
const Stack = createStackNavigator<StackParamsList>();
const App = (): React.JSX.Element => {
const navigation =
useNavigation<NativeStackNavigationProp<StackParamsList>>();
useNavigation<StackNavigationProp<StackParamsList>>();
// const { setActiveSessions } = useWalletConnect();
const { setActiveSessions } = useWalletConnect();
const { accounts, setCurrentIndex } = useAccounts();
const { networksData, selectedNetwork, setSelectedNetwork } = useNetworks();
const [modalVisible, setModalVisible] = useState(false);
const [toastVisible, setToastVisible] = useState(false);
// const [currentProposal, setCurrentProposal] = useState<
// SignClientTypes.EventArguments['session_proposal'] | undefined
// >();
const [currentProposal, setCurrentProposal] = useState<
SignClientTypes.EventArguments['session_proposal'] | undefined
>();
// const onSessionProposal = useCallback(
// async (proposal: SignClientTypes.EventArguments['session_proposal']) => {
// if (!accounts.length || !accounts.length) {
// const { id } = proposal;
// await web3wallet!.rejectSession({
// id,
// reason: getSdkError('UNSUPPORTED_ACCOUNTS'),
// });
// return;
// }
// setModalVisible(true);
// setCurrentProposal(proposal);
// },
// [accounts],
// );
const onSessionProposal = useCallback(
async (proposal: SignClientTypes.EventArguments['session_proposal']) => {
console.log("modal triggered")
debugger
if (!accounts.length || !accounts.length) {
const { id } = proposal;
await web3wallet!.rejectSession({
id,
reason: getSdkError('UNSUPPORTED_ACCOUNTS'),
});
return;
}
setModalVisible(true);
setCurrentProposal(proposal);
},
[accounts],
);
// const onSessionRequest = useCallback(
// async (requestEvent: Web3WalletTypes.SessionRequest) => {
// const { topic, params, id } = requestEvent;
// const { request } = params;
const onSessionRequest = useCallback(
async (requestEvent: Web3WalletTypes.SessionRequest) => {
const { topic, params, id } = requestEvent;
const { request } = params;
// const requestSessionData =
// web3wallet!.engine.signClient.session.get(topic);
// switch (request.method) {
// case NETWORK_METHODS.GET_NETWORKS:
// const currentNetworkId = networksData.find(
// networkData => networkData.networkId === selectedNetwork!.networkId,
// )?.networkId;
const requestSessionData =
web3wallet!.engine.signClient.session.get(topic);
switch (request.method) {
case NETWORK_METHODS.GET_NETWORKS:
const currentNetworkId = networksData.find(
networkData => networkData.networkId === selectedNetwork!.networkId,
)?.networkId;
// const networkNamesData = networksData.map(networkData => {
// return {
// id: networkData.networkId,
// name: networkData.networkName,
// };
// });
const networkNamesData = networksData.map(networkData => {
return {
id: networkData.networkId,
name: networkData.networkName,
};
});
// const formattedResponse = formatJsonRpcResult(id, {
// currentNetworkId,
// networkNamesData,
// });
const formattedResponse = formatJsonRpcResult(id, {
currentNetworkId,
networkNamesData,
});
// await web3wallet!.respondSessionRequest({
// topic,
// response: formattedResponse,
// });
// break;
await web3wallet!.respondSessionRequest({
topic,
response: formattedResponse,
});
break;
// case NETWORK_METHODS.CHANGE_NETWORK:
// const networkNameData = request.params[0];
// const network = networksData.find(
// networkData => networkData.networkId === networkNameData.id,
// );
// setCurrentIndex(0);
// setSelectedNetwork(network);
case NETWORK_METHODS.CHANGE_NETWORK:
const networkNameData = request.params[0];
const network = networksData.find(
networkData => networkData.networkId === networkNameData.id,
);
setCurrentIndex(0);
setSelectedNetwork(network);
// const response = formatJsonRpcResult(id, {
// response: 'true',
// });
const response = formatJsonRpcResult(id, {
response: 'true',
});
// await web3wallet!.respondSessionRequest({
// topic,
// response: response,
// });
// break;
await web3wallet!.respondSessionRequest({
topic,
response: response,
});
break;
// case EIP155_SIGNING_METHODS.ETH_SEND_TRANSACTION:
// navigation.navigate('ApproveTransfer', {
// transaction: request.params[0],
// requestEvent,
// requestSessionData,
// });
// break;
case EIP155_SIGNING_METHODS.ETH_SEND_TRANSACTION:
navigation.navigate('ApproveTransfer', {
transaction: request.params[0],
requestEvent,
requestSessionData,
});
break;
// case EIP155_SIGNING_METHODS.PERSONAL_SIGN:
// navigation.navigate('SignRequest', {
// namespace: EIP155,
// address: request.params[1],
// message: getSignParamsMessage(request.params),
// requestEvent,
// requestSessionData,
// });
// break;
case EIP155_SIGNING_METHODS.PERSONAL_SIGN:
navigation.navigate('SignRequest', {
namespace: EIP155,
address: request.params[1],
message: getSignParamsMessage(request.params),
requestEvent,
requestSessionData,
});
break;
// case COSMOS_METHODS.COSMOS_SIGN_DIRECT:
// const message = {
// txbody: TxBody.toJSON(
// TxBody.decode(
// Uint8Array.from(
// Buffer.from(request.params.signDoc.bodyBytes, 'hex'),
// ),
// ),
// ),
// authInfo: AuthInfo.toJSON(
// AuthInfo.decode(
// Uint8Array.from(
// Buffer.from(request.params.signDoc.authInfoBytes, 'hex'),
// ),
// ),
// ),
// };
// navigation.navigate('SignRequest', {
// namespace: COSMOS,
// address: request.params.signerAddress,
// message: JSON.stringify(message, undefined, 2),
// requestEvent,
// requestSessionData,
// });
// break;
case COSMOS_METHODS.COSMOS_SIGN_DIRECT:
const message = {
txbody: TxBody.toJSON(
TxBody.decode(
Uint8Array.from(
Buffer.from(request.params.signDoc.bodyBytes, 'hex'),
),
),
),
authInfo: AuthInfo.toJSON(
AuthInfo.decode(
Uint8Array.from(
Buffer.from(request.params.signDoc.authInfoBytes, 'hex'),
),
),
),
};
navigation.navigate('SignRequest', {
namespace: COSMOS,
address: request.params.signerAddress,
message: JSON.stringify(message, undefined, 2),
requestEvent,
requestSessionData,
});
break;
// case COSMOS_METHODS.COSMOS_SIGN_AMINO:
// navigation.navigate('SignRequest', {
// namespace: COSMOS,
// address: request.params.signerAddress,
// message: request.params.signDoc.memo,
// requestEvent,
// requestSessionData,
// });
// break;
case COSMOS_METHODS.COSMOS_SIGN_AMINO:
navigation.navigate('SignRequest', {
namespace: COSMOS,
address: request.params.signerAddress,
message: request.params.signDoc.memo,
requestEvent,
requestSessionData,
});
break;
// case COSMOS_METHODS.COSMOS_SEND_TOKENS:
// navigation.navigate('ApproveTransfer', {
// transaction: request.params[0],
// requestEvent,
// requestSessionData,
// });
// break;
case COSMOS_METHODS.COSMOS_SEND_TOKENS:
navigation.navigate('ApproveTransfer', {
transaction: request.params[0],
requestEvent,
requestSessionData,
});
break;
// case COSMOS_METHODS.COSMOS_SEND_TRANSACTION:
// const { transactionMessage, signer } = request.params;
// navigation.navigate('ApproveTransaction', {
// transactionMessage,
// signer,
// requestEvent,
// requestSessionData,
// });
// break;
case COSMOS_METHODS.COSMOS_SEND_TRANSACTION:
const { transactionMessage, signer } = request.params;
navigation.navigate('ApproveTransaction', {
transactionMessage,
signer,
requestEvent,
requestSessionData,
});
break;
// default:
// throw new Error('Invalid method');
// }
// },
// [
// navigation,
// networksData,
// setSelectedNetwork,
// setCurrentIndex,
// selectedNetwork,
// ],
// );
default:
throw new Error('Invalid method');
}
},
[
navigation,
networksData,
setSelectedNetwork,
setCurrentIndex,
selectedNetwork,
],
);
// const onSessionDelete = useCallback(() => {
// const sessions = web3wallet!.getActiveSessions();
// setActiveSessions(sessions);
// }, [setActiveSessions]);
const onSessionDelete = useCallback(() => {
const sessions = web3wallet!.getActiveSessions();
setActiveSessions(sessions);
}, [setActiveSessions]);
// useEffect(() => {
// web3wallet?.on('session_proposal', onSessionProposal);
// web3wallet?.on('session_request', onSessionRequest);
// web3wallet?.on('session_delete', onSessionDelete);
// return () => {
// web3wallet?.off('session_proposal', onSessionProposal);
// web3wallet?.off('session_request', onSessionRequest);
// web3wallet?.off('session_delete', onSessionDelete);
// };
// });
useEffect(() => {
web3wallet?.on('session_proposal', onSessionProposal);
web3wallet?.on('session_request', onSessionRequest);
web3wallet?.on('session_delete', onSessionDelete);
return () => {
web3wallet?.off('session_proposal', onSessionProposal);
web3wallet?.off('session_request', onSessionRequest);
web3wallet?.off('session_delete', onSessionDelete);
};
});
return (
<>
<Stack.Navigator>
<Stack.Navigator
screenOptions={{
headerBackTitleVisible: true,
}}
>
<Stack.Screen
name="Laconic"
component={HomeScreen}
options={{
// eslint-disable-next-line react/no-unstable-nested-components
headerTitle: () => <Text variant="titleLarge">Laconic Wallet</Text>,
headerBackVisible: false,
}}
/>
}} />
<Stack.Screen
name="SignMessage"
component={SignMessage}
@ -236,24 +239,30 @@ const App = (): React.JSX.Element => {
headerTitle: () => <Text variant="titleLarge">Sign Message</Text>,
}}
/>
{/* <Stack.Screen
<Stack.Screen
name="SignRequest"
component={SignRequest}
options={{
// eslint-disable-next-line react/no-unstable-nested-components
headerTitle: () => <Text variant="titleLarge">Sign Request</Text>,
}}
/> */}
/>
<Stack.Screen
name="InvalidPath"
component={InvalidPath}
options={{
// eslint-disable-next-line react/no-unstable-nested-components
headerTitle: () => <Text variant="titleLarge">Bad Request</Text>,
headerBackVisible: false,
}}
/>
{/* <Stack.Screen
<Stack.Screen
name="AddSession"
component={AddSession}
options={{
title: 'New session',
}}
/>
<Stack.Screen
name="WalletConnect"
component={WalletConnect}
options={{
@ -265,27 +274,18 @@ const App = (): React.JSX.Element => {
onPress={() => {
navigation.navigate('AddSession');
}}>
{<Icon name={'qrcode-scan'} size={20} />}
{<Text>PAIR</Text>}
</Button>
),
}}
/> */}
<Stack.Screen
name="AddSession"
component={AddSession}
options={{
title: 'New session',
}}
/>
{/* <Stack.Screen
<Stack.Screen
name="ApproveTransfer"
component={ApproveTransfer}
options={{
title: 'Approve transfer',
}}
/> */}
/>
<Stack.Screen
name="AddNetwork"
component={AddNetwork}
@ -300,21 +300,21 @@ const App = (): React.JSX.Element => {
title: 'Edit Network',
}}
/>
{/* <Stack.Screen
<Stack.Screen
name="ApproveTransaction"
component={ApproveTransaction}
options={{
title: 'Approve Transaction',
}}
/> */}
/>
</Stack.Navigator>
{/* <PairingModal
<PairingModal
visible={modalVisible}
setModalVisible={setModalVisible}
currentProposal={currentProposal}
setCurrentProposal={setCurrentProposal}
setToastVisible={setToastVisible}
/> */}
/>
<Snackbar
visible={toastVisible}
onDismiss={() => setToastVisible(false)}

View File

@ -1,7 +1,6 @@
import React, { useEffect, useState } from 'react';
import { ScrollView, TouchableOpacity, View } from 'react-native';
import { TouchableOpacity, View } from 'react-native';
import { Button, List, Text, useTheme } from 'react-native-paper';
// import { setInternetCredentials } from 'react-native-keychain';
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
@ -17,6 +16,7 @@ import { useNetworks } from '../context/NetworksContext';
import ConfirmDialog from './ConfirmDialog';
import { getNamespaces } from '../utils/wallet-connect/helpers';
import ShowPKDialog from './ShowPKDialog';
import { setInternetCredentials } from '../utils/key-store';
const Accounts = () => {
const navigation =
@ -103,11 +103,11 @@ const Accounts = () => {
networkData => selectedNetwork!.networkId !== networkData.networkId,
);
// await setInternetCredentials(
// 'networks',
// '_',
// JSON.stringify(updatedNetworks),
// );
await setInternetCredentials(
'networks',
'_',
JSON.stringify(updatedNetworks),
);
setSelectedNetwork(updatedNetworks[0]);
setCurrentIndex(0);
@ -116,7 +116,7 @@ const Accounts = () => {
};
return (
<ScrollView>
<View>
<View>
<HDPathDialog
visible={hdDialog}
@ -153,7 +153,7 @@ const Accounts = () => {
</View>
<AccountDetails account={accounts[currentIndex]} />
<View style={styles.linkContainer}>
<View style={styles.signLink}>
<TouchableOpacity
onPress={() => {
@ -219,10 +219,10 @@ const Accounts = () => {
hideDialog={hideDeleteNetworkDialog}
onConfirm={handleRemove}
/>
<ShowPKDialog />
</View>
</ScrollView>
</View>
</View>
);
};

View File

@ -1,10 +1,9 @@
import React, { useEffect, useMemo, useState } from 'react';
import { Image, View, Modal, ScrollView } from 'react-native';
import { Button, Text } from 'react-native-paper';
import { SvgUri } from 'react-native-svg';
import mergeWith from 'lodash/mergeWith';
// import { buildApprovedNamespaces, getSdkError } from '@walletconnect/utils';
import { buildApprovedNamespaces, getSdkError } from '@walletconnect/utils';
import { PairingModalProps } from '../types';
import styles from '../styles/stylesheet';
@ -26,12 +25,9 @@ const PairingModal = ({
const [isLoading, setIsLoading] = useState(false);
const [chainError, setChainError] = useState('');
// const dappName = currentProposal?.params?.proposer?.metadata.name;
// const url = currentProposal?.params?.proposer?.metadata.url;
// const icon = currentProposal?.params.proposer?.metadata.icons[0];
const dappName = undefined;
const url = undefined;
const icon = '.svg';
const dappName = currentProposal?.params?.proposer?.metadata.name;
const url = currentProposal?.params?.proposer?.metadata.url;
const icon = currentProposal?.params.proposer?.metadata.icons[0];
const [walletConnectData, setWalletConnectData] = useState<{
walletConnectMethods: string[];
@ -98,9 +94,7 @@ const PairingModal = ({
return;
}
// const { optionalNamespaces, requiredNamespaces } = currentProposal.params;
const { optionalNamespaces, requiredNamespaces } = currentProposal;
const { optionalNamespaces, requiredNamespaces } = currentProposal.params;
try {
const nameSpaces = await getNamespaces(
optionalNamespaces,
@ -114,11 +108,11 @@ const PairingModal = ({
} catch (err) {
setChainError((err as Error).message);
// const { id } = currentProposal;
// await web3wallet!.rejectSession({
// id,
// reason: getSdkError('UNSUPPORTED_CHAINS'),
// });
const { id } = currentProposal;
await web3wallet!.rejectSession({
id,
reason: getSdkError('UNSUPPORTED_CHAINS'),
});
setCurrentProposal(undefined);
setWalletConnectData({
walletConnectMethods: [],
@ -143,11 +137,11 @@ const PairingModal = ({
return (
currentProposal &&
supportedNamespaces
// &&
// buildApprovedNamespaces({
// proposal: currentProposal.params,
// supportedNamespaces,
// })
&&
buildApprovedNamespaces({
proposal: currentProposal.params,
supportedNamespaces,
})
);
}, [currentProposal, supportedNamespaces]);
@ -188,11 +182,11 @@ const PairingModal = ({
const handleReject = async () => {
if (currentProposal) {
// const { id } = currentProposal;
// await web3wallet!.rejectSession({
// id,
// reason: getSdkError('USER_REJECTED_METHODS'),
// });
const { id } = currentProposal;
await web3wallet!.rejectSession({
id,
reason: getSdkError('USER_REJECTED_METHODS'),
});
setModalVisible(false);
setCurrentProposal(undefined);
@ -214,7 +208,7 @@ const PairingModal = ({
<>
{icon.endsWith('.svg') ? (
<View style={styles.dappLogo}>
<SvgUri height="50" width="50" uri={icon} />
<Text>SvgURI requstIcon</Text>
</View>
) : (
<Image style={styles.dappLogo} source={{ uri: icon }} />
@ -243,7 +237,7 @@ const PairingModal = ({
<>
{icon.endsWith('.svg') ? (
<View style={styles.dappLogo}>
<SvgUri height="50" width="50" uri={icon} />
<Text>SvgURI requstIcon</Text>
</View>
) : (
<Image style={styles.dappLogo} source={{ uri: icon }} />

View File

@ -19,7 +19,7 @@ const useAccounts = () => {
return accountsContext;
};
const AccountsProvider = ({ children }: { children: any }) => {
const AccountsProvider = ({ children }: { children: React.ReactNode }) => {
const [accounts, setAccounts] = useState<Account[]>([]);
const [currentIndex, setCurrentIndex] = useState<number>(0);

View File

@ -27,7 +27,7 @@ const useNetworks = () => {
return networksContext;
};
const NetworksProvider = ({ children }: { children: any }) => {
const NetworksProvider = ({ children }: { children: React.ReactNode }) => {
const [networksData, setNetworksData] = useState<NetworksDataState[]>([]);
const [networkType, setNetworkType] = useState<string>(EIP155);
const [selectedNetwork, setSelectedNetwork] = useState<NetworksDataState>();

View File

@ -1,6 +1,6 @@
import React, { createContext, useContext, useEffect, useState } from 'react';
// import { SessionTypes } from '@walletconnect/types';
import { SessionTypes } from '@walletconnect/types';
import { WalletConnectContextProps } from '../types';
import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils';
@ -25,8 +25,7 @@ const WalletConnectProvider = ({ children }: { children: React.ReactNode }) => {
}, []);
const [activeSessions, setActiveSessions] = useState<
// Record<string, SessionTypes.Struct>
Record<string, any>
Record<string, SessionTypes.Struct>
>({});
return (

View File

@ -3,6 +3,7 @@ import ReactDOM from 'react-dom/client';
import { PaperProvider, MD3LightTheme as DefaultTheme, } from 'react-native-paper';
import { NavigationContainer } from '@react-navigation/native';
import { Platform } from 'react-native';
import { Buffer } from 'buffer';
import './index.css';
import App from './App';
@ -11,26 +12,7 @@ import { NetworksProvider } from './context/NetworksContext';
import reportWebVitals from './reportWebVitals';
import { WalletConnectProvider } from './context/WalletConnectContext';
// // Generate the required CSS
// import iconFont from 'react-native-vector-icons/Fonts/FontAwesome.ttf';
// const iconFontStyles = `@font-face {
// src: url(${iconFont});
// font-family: FontAwesome;
// }`;
// // Create a stylesheet
// const style = document.createElement('style');
// style.type = 'text/css';
// // Append the iconFontStyles to the stylesheet
// if (style.styleSheet) {
// style.styleSheet.cssText = iconFontStyles;
// } else {
// style.appendChild(document.createTextNode(iconFontStyles));
// }
// // Inject the stylesheet into the document head
// document.head.appendChild(style);
globalThis.Buffer = Buffer;
const linking = {
prefixes: ['https://wallet.laconic.com'],

View File

@ -30,6 +30,7 @@ import {
getInternetCredentials,
setInternetCredentials,
} from '../utils/key-store';
import styles from '../styles/stylesheet';
const ethNetworkDataSchema = z.object({
chainId: z.string().nonempty({ message: EMPTY_FIELD_ERROR }),
@ -211,7 +212,7 @@ const AddNetwork = () => {
}, [namespace, reset]);
return (
<View>
<View style={styles.appContainer}>
<SelectNetworkType updateNetworkType={updateNetworkType} />
<Controller

View File

@ -1,13 +1,6 @@
import React, { useEffect, useState } from 'react';
import { AppState, TouchableOpacity, View } from 'react-native';
import React, { useState } from 'react';
import { View } from 'react-native';
import { Button, Text, TextInput } from 'react-native-paper';
// import {
// Camera,
// useCameraDevice,
// useCameraPermission,
// useCodeScanner,
// } from 'react-native-vision-camera';
import { Linking } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
@ -20,30 +13,7 @@ const AddSession = () => {
const navigation =
useNavigation<NativeStackNavigationProp<StackParamsList>>();
// const { hasPermission, requestPermission } = useCameraPermission();
// const device = useCameraDevice('back');
const [currentWCURI, setCurrentWCURI] = useState<string>('');
// const [isActive, setIsActive] = useState(AppState.currentState === 'active');
// const [isScanning, setScanning] = useState(true);
// const codeScanner = useCodeScanner({
// codeTypes: ['qr'],
// onCodeScanned: codes => {
// if (isScanning) {
// codes.forEach(code => {
// if (code.value) {
// setCurrentWCURI(code.value);
// setScanning(false);
// }
// });
// }
// },
// });
const linkToSettings = async () => {
await Linking.openSettings();
};
const pair = async () => {
const pairing = await web3WalletPair({ uri: currentWCURI });
@ -51,50 +21,8 @@ const AddSession = () => {
return pairing;
};
// useEffect(() => {
// const handleAppStateChange = (newState: string) => {
// setIsActive(newState === 'active');
// };
// AppState.addEventListener('change', handleAppStateChange);
// if (!hasPermission) {
// requestPermission();
// }
// }, [hasPermission, requestPermission]);
return (
<View style={styles.appContainer}>
{/* {!hasPermission || !device ? ( */}
{false ? (
<>
{/* <Text>
{!hasPermission
? 'No Camera Permission granted'
: 'No Camera Selected'}
</Text> */}
<TouchableOpacity onPress={linkToSettings}>
<Text variant="titleSmall" style={[styles.hyperlink]}>
Go to settings
</Text>
</TouchableOpacity>
</>
) : (
<>
<View style={styles.cameraContainer}>
{/* {isActive ? (
<Camera
style={styles.camera}
device={device}
isActive={isActive}
codeScanner={codeScanner}
video={false}
/>
) : (
<Text>No Camera Selected!</Text>
)} */}
</View>
<View style={styles.inputContainer}>
<Text variant="titleMedium">Enter WalletConnect URI</Text>
<TextInput
@ -112,8 +40,6 @@ const AddSession = () => {
</Button>
</View>
</View>
</>
)}
</View>
);
};

View File

@ -1,8 +1,6 @@
import React, { useCallback, useEffect, useState } from 'react';
import { Image, ScrollView, View } from 'react-native';
import { Button, Text, TextInput } from 'react-native-paper';
import { SvgUri } from 'react-native-svg';
import Config from 'react-native-config';
import {
NativeStackNavigationProp,
@ -95,7 +93,11 @@ const ApproveTransaction = ({ route }: ApproveTransactionProps) => {
sender,
);
setCosmosStargateClient(client);
} catch (error: any) {
} catch (error) {
if (!(error instanceof Error)) {
throw error;
}
setTxError(error.message);
setIsTxErrorDialogOpen(true);
const response = formatJsonRpcError(requestEventId, error.message);
@ -141,10 +143,14 @@ const ApproveTransaction = ({ route }: ApproveTransactionProps) => {
setCosmosGasLimit(
String(
Math.round(gasEstimation * Number(Config.DEFAULT_GAS_ADJUSTMENT)),
Math.round(gasEstimation * Number(process.env.REACT_APP_GAS_ADJUSTMENT)),
),
);
} catch (error: any) {
} catch (error) {
if (!(error instanceof Error)) {
throw error;
}
setTxError(error.message);
setIsTxErrorDialogOpen(true);
const response = formatJsonRpcError(requestEventId, error.message);
@ -209,7 +215,11 @@ const ApproveTransaction = ({ route }: ApproveTransactionProps) => {
await web3wallet!.respondSessionRequest({ topic, response });
setIsRequestAccepted(false);
navigation.navigate('Laconic');
} catch (error: any) {
} catch (error) {
if (!(error instanceof Error)) {
throw error;
}
setTxError(error.message);
setIsTxErrorDialogOpen(true);
const response = formatJsonRpcError(requestEventId, error.message);
@ -235,7 +245,8 @@ const ApproveTransaction = ({ route }: ApproveTransactionProps) => {
<>
{requestIcon.endsWith('.svg') ? (
<View style={styles.dappLogo}>
<SvgUri height="50" width="50" uri={requestIcon} />
{/* <SvgUri height="50" width="50" uri={requestIcon} /> */}
<Text>SvgURI requstIcon</Text>
</View>
) : (
<Image style={styles.dappLogo} source={{ uri: requestIcon }} />

View File

@ -8,7 +8,6 @@ import {
TextInput,
} from 'react-native-paper';
import { providers, BigNumber } from 'ethers';
import Config from 'react-native-config';
import { Deferrable } from 'ethers/lib/utils';
import { useNavigation } from '@react-navigation/native';
@ -150,7 +149,11 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
);
setCosmosStargateClient(client);
} catch (error: any) {
} catch (error) {
if (!(error instanceof Error)) {
throw error;
}
setTxError(error.message);
setIsTxErrorDialogOpen(true);
}
@ -170,7 +173,11 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
);
return ethProvider;
} catch (error: any) {
} catch (error) {
if (!(error instanceof Error)) {
throw error;
}
setTxError(error.message);
setIsTxErrorDialogOpen(true);
}
@ -330,7 +337,11 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
const { topic } = requestEvent;
await web3wallet!.respondSessionRequest({ topic, response });
navigation.navigate('Laconic');
} catch (error: any) {
} catch (error) {
if (!(error instanceof Error)) {
throw error;
}
setTxError(error.message);
setIsTxErrorDialogOpen(true);
}
@ -368,7 +379,11 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
setBalance(cosmosBalance?.amount!);
}
} catch (error: any) {
} catch (error) {
if (!(error instanceof Error)) {
throw error;
}
setTxError(error.message);
setIsTxErrorDialogOpen(true);
}
@ -431,7 +446,11 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
const gasLimit = await provider.estimateGas(transactionObject);
setEthGasLimit(gasLimit);
}
} catch (error: any) {
} catch (error) {
if (!(error instanceof Error)) {
throw error;
}
setTxError(error.message);
setIsTxErrorDialogOpen(true);
}
@ -457,10 +476,14 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
setCosmosGasLimit(
String(
Math.round(gasEstimation * Number(Config.DEFAULT_GAS_ADJUSTMENT)),
Math.round(gasEstimation * Number(process.env.REACT_APP_GAS_ADJUSTMENT)),
),
);
} catch (error: any) {
} catch (error) {
if (!(error instanceof Error)) {
throw error;
}
setTxError(error.message);
setIsTxErrorDialogOpen(true);
}

View File

@ -96,7 +96,7 @@ const EditNetwork = ({ route }: EditNetworkProps) => {
);
return (
<View>
<View style={styles.appContainer}>
<View>
<Text style={styles.subHeading}>
Edit {networkData?.networkName} details

View File

@ -4,7 +4,7 @@ import { Button, Text } from 'react-native-paper';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { useNavigation } from '@react-navigation/native';
// import { getSdkError } from '@walletconnect/utils';
import { getSdkError } from '@walletconnect/utils';
import { createWallet, resetWallet, retrieveAccounts } from '../utils/accounts';
import { DialogComponent } from '../components/Dialog';
@ -58,7 +58,6 @@ const HomeScreen = () => {
const [isWalletCreating, setIsWalletCreating] = useState<boolean>(false);
const [walletDialog, setWalletDialog] = useState<boolean>(false);
const [resetWalletDialog, setResetWalletDialog] = useState<boolean>(false);
// const [isAccountsFetched, setIsAccountsFetched] = useState<boolean>(false);
const [isAccountsFetched, setIsAccountsFetched] = useState<boolean>(true);
const [phrase, setPhrase] = useState('');
@ -99,14 +98,14 @@ const HomeScreen = () => {
setNetworksData([]);
setSelectedNetwork(undefined);
await resetWallet();
// const sessions = web3wallet!.getActiveSessions();
const sessions = web3wallet!.getActiveSessions();
// Object.keys(sessions).forEach(async sessionId => {
// await web3wallet!.disconnectSession({
// topic: sessionId,
// reason: getSdkError('USER_DISCONNECTED'),
// });
// });
Object.keys(sessions).forEach(async sessionId => {
await web3wallet!.disconnectSession({
topic: sessionId,
reason: getSdkError('USER_DISCONNECTED'),
});
});
setActiveSessions({});
hideResetDialog();

View File

@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { View, Alert } from 'react-native';
import { View } from 'react-native';
import { Button, Text, TextInput } from 'react-native-paper';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
@ -25,7 +25,7 @@ const SignMessage = ({ route }: SignProps) => {
chainId,
accountId: account.index,
});
Alert.alert('Signature', signedMessage);
alert(`Signature ${signedMessage}`);
};
return (

View File

@ -1,7 +1,6 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Alert, Image, ScrollView, View } from 'react-native';
import { Image, ScrollView, View } from 'react-native';
import { ActivityIndicator, Button, Text, Appbar } from 'react-native-paper';
import { SvgUri } from 'react-native-svg';
import { useNavigation } from '@react-navigation/native';
import {
@ -210,7 +209,7 @@ const SignRequest = ({ route }: SignRequestProps) => {
chainId,
accountId: account.index,
});
Alert.alert('Signature', signedMessage);
alert(`Signature ${signedMessage}`);
}
};
@ -279,7 +278,7 @@ const SignRequest = ({ route }: SignRequestProps) => {
<>
{requestIcon.endsWith('.svg') ? (
<View style={styles.dappLogo}>
<SvgUri height="50" width="50" uri={requestIcon} />
<Text>SvgURI requstIcon</Text>
</View>
) : (
<Image

View File

@ -1,9 +1,8 @@
import React, { useEffect } from 'react';
import { Image, TouchableOpacity, View } from 'react-native';
import { List, Text } from 'react-native-paper';
import { SvgUri } from 'react-native-svg';
// import { getSdkError } from '@walletconnect/utils';
import { getSdkError } from '@walletconnect/utils';
import { useWalletConnect } from '../context/WalletConnectContext';
import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils';
@ -13,10 +12,10 @@ export default function WalletConnect() {
const { activeSessions, setActiveSessions } = useWalletConnect();
const disconnect = async (sessionId: string) => {
// await web3wallet!.disconnectSession({
// topic: sessionId,
// reason: getSdkError('USER_DISCONNECTED'),
// });
await web3wallet!.disconnectSession({
topic: sessionId,
reason: getSdkError('USER_DISCONNECTED'),
});
const sessions = web3wallet?.getActiveSessions() || {};
setActiveSessions(sessions);
return;
@ -48,11 +47,7 @@ export default function WalletConnect() {
<>
{session.peer.metadata.icons[0].endsWith('.svg') ? (
<View style={styles.dappLogo}>
<SvgUri
height="50"
width="50"
uri={session.peer.metadata.icons[0]}
/>
<Text>SvgURI peerMetaDataIcon</Text>
</View>
) : (
<Image

View File

@ -218,17 +218,9 @@ const styles = StyleSheet.create({
paddingHorizontal: 10,
marginVertical: 3,
},
cameraContainer: {
justifyContent: 'center',
alignItems: 'center',
},
inputContainer: {
marginTop: 20,
},
camera: {
width: 400,
height: 400,
},
dappDetails: {
display: 'flex',
alignItems: 'center',
@ -282,6 +274,9 @@ const styles = StyleSheet.create({
fontWeight: '700',
padding: 8,
},
linkContainer: {
paddingBottom: 72
}
});
export default styles;

View File

@ -1,7 +1,7 @@
import { PopulatedTransaction } from 'ethers';
// import { SignClientTypes, SessionTypes } from '@walletconnect/types';
// import { Web3WalletTypes } from '@walletconnect/web3wallet';
import { SignClientTypes, SessionTypes } from '@walletconnect/types';
import { Web3WalletTypes } from '@walletconnect/web3wallet';
import { EncodeObject } from '@cosmjs/proto-signing';
export type StackParamsList = {
@ -15,17 +15,13 @@ export type StackParamsList = {
namespace: string;
address: string;
message: string;
// requestEvent?: Web3WalletTypes.SessionRequest;
// requestSessionData?: SessionTypes.Struct;
requestEvent?: any;
requestSessionData?: any;
requestEvent?: Web3WalletTypes.SessionRequest;
requestSessionData?: SessionTypes.Struct;
};
ApproveTransfer: {
transaction: PopulatedTransaction;
// requestEvent: Web3WalletTypes.SessionRequest;
// requestSessionData: SessionTypes.Struct;
requestEvent: any;
requestSessionData: any;
requestEvent: Web3WalletTypes.SessionRequest;
requestSessionData: SessionTypes.Struct;
};
InvalidPath: undefined;
WalletConnect: undefined;
@ -37,10 +33,8 @@ export type StackParamsList = {
ApproveTransaction: {
transactionMessage: EncodeObject;
signer: string;
// requestEvent: Web3WalletTypes.SessionRequest;
// requestSessionData: SessionTypes.Struct;
requestEvent: any;
requestSessionData: any;
requestEvent: Web3WalletTypes.SessionRequest;
requestSessionData: SessionTypes.Struct;
};
};
@ -120,21 +114,19 @@ export interface PairingModalProps {
visible: boolean;
setModalVisible: (arg1: boolean) => void;
currentProposal:
// | SignClientTypes.EventArguments['session_proposal']
| SignClientTypes.EventArguments['session_proposal']
| undefined;
setCurrentProposal: (
arg1:
// | SignClientTypes.EventArguments['session_proposal']
| SignClientTypes.EventArguments['session_proposal']
| undefined,
) => void;
setToastVisible: (arg1: boolean) => void;
}
export interface WalletConnectContextProps {
// activeSessions: Record<string, SessionTypes.Struct>;
activeSessions: Record<string, any>;
activeSessions: Record<string, SessionTypes.Struct>;
setActiveSessions: (
// activeSessions: Record<string, SessionTypes.Struct>,
activeSessions: Record<string, any>,
activeSessions: Record<string, SessionTypes.Struct>,
) => void;
}

View File

@ -119,14 +119,14 @@ const resetKeyServers = async (namespace: string) => {
const networksData: NetworksDataState[] = JSON.parse(networksServer);
const filteredNetworks = networksData.filter(
(network: any) => network.namespace === namespace,
network => network.namespace === namespace,
);
if (filteredNetworks.length === 0) {
throw new Error(`No networks found for namespace ${namespace}.`);
}
filteredNetworks.forEach(async (network: any) => {
filteredNetworks.forEach(async network => {
const { chainId } = network;
const namespaceChainId = `${namespace}:${chainId}`;

View File

@ -1,36 +1,32 @@
import Config from 'react-native-config';
// import '@walletconnect/react-native-compat';
import '@ethersproject/shims';
// import { Core } from '@walletconnect/core';
// import { ICore } from '@walletconnect/types';
// import { Web3Wallet, IWeb3Wallet } from '@walletconnect/web3wallet';
import { Core } from '@walletconnect/core';
import { ICore } from '@walletconnect/types';
import { Web3Wallet, IWeb3Wallet } from '@walletconnect/web3wallet';
export let web3wallet:
// | IWeb3Wallet
| any;
export let core:
// | ICore
| any;
| IWeb3Wallet
| undefined;
export let core: ICore;
export async function createWeb3Wallet() {
// core = new Core({
// projectId: Config.WALLET_CONNECT_PROJECT_ID,
// });
core = new Core({
projectId: process.env.REACT_APP_WALLET_CONNECT_PROJECT_ID,
});
// web3wallet = await Web3Wallet.init({
// core,
// metadata: {
// name: 'Laconic Wallet',
// description: 'Laconic Wallet',
// url: 'https://wallet.laconic.com/',
// icons: ['https://avatars.githubusercontent.com/u/92608123'],
// },
// });
web3wallet = await Web3Wallet.init({
core,
metadata: {
name: 'Laconic Wallet',
description: 'Laconic Wallet',
url: 'https://wallet.laconic.com/',
icons: ['https://avatars.githubusercontent.com/u/92608123'],
},
});
}
export async function web3WalletPair(params: { uri: string }) {
if (web3wallet) {
// return await web3wallet.core.pairing.pair({ uri: params.uri });
return await web3wallet.core.pairing.pair({ uri: params.uri });
}
}

View File

@ -2,7 +2,7 @@
import { utils } from 'ethers';
// import { ProposalTypes } from '@walletconnect/types';
import { ProposalTypes } from '@walletconnect/types';
import { Account, NetworksDataState } from '../../types';
import { EIP155_SIGNING_METHODS } from './EIP155Data';
@ -35,10 +35,8 @@ export function getSignParamsMessage(params: string[]) {
}
export const getNamespaces = async (
// optionalNamespaces: ProposalTypes.OptionalNamespaces,
// requiredNamespaces: ProposalTypes.RequiredNamespaces,
optionalNamespaces: any,
requiredNamespaces: any,
optionalNamespaces: ProposalTypes.OptionalNamespaces,
requiredNamespaces: ProposalTypes.RequiredNamespaces,
networksData: NetworksDataState[],
selectedNetwork: NetworksDataState,
accounts: Account[],

View File

@ -2,8 +2,8 @@
import { BigNumber, Wallet, providers } from 'ethers';
import { formatJsonRpcError, formatJsonRpcResult } from '@json-rpc-tools/utils';
// import { SignClientTypes } from '@walletconnect/types';
// import { getSdkError } from '@walletconnect/utils';
import { SignClientTypes } from '@walletconnect/types';
import { getSdkError } from '@walletconnect/utils';
import {
SigningStargateClient,
StdFee,
@ -11,6 +11,7 @@ import {
} from '@cosmjs/stargate';
import { EncodeObject } from '@cosmjs/proto-signing';
import { LaconicClient } from '@cerc-io/registry-sdk';
import { Buffer } from 'buffer';
import { EIP155_SIGNING_METHODS } from './EIP155Data';
import { signDirectMessage, signEthMessage } from '../sign-message';
@ -67,8 +68,7 @@ export type WalletConnectRequests =
| CosmosSendTransaction;
export async function approveWalletConnectRequest(
// requestEvent: SignClientTypes.EventArguments['session_request'],
requestEvent: any,
requestEvent: SignClientTypes.EventArguments['session_request'],
account: Account,
namespace: string,
chainId: string,
@ -207,15 +207,14 @@ export async function approveWalletConnectRequest(
});
default:
// throw new Error(getSdkError('INVALID_METHOD').message);
throw new Error(getSdkError('INVALID_METHOD').message);
}
}
export function rejectWalletConnectRequest(
// request: SignClientTypes.EventArguments['session_request'],
request: any,
request: SignClientTypes.EventArguments['session_request'],
) {
// const { id } = request;
const { id } = request;
// return formatJsonRpcError(id, getSdkError('USER_REJECTED_METHODS').message);
return formatJsonRpcError(id, getSdkError('USER_REJECTED_METHODS').message);
}

1369
yarn.lock

File diff suppressed because it is too large Load Diff