forked from cerc-io/laconic-wallet
Support SIWE using selected account (#61)
* Sign in using selected address * Use optional namespace * Merge namespaces and use combined namespace * Add todo for lodash merge * Use walletConnect util buildApprovedNamespaces while approving sessions * Lint fixes --------- Co-authored-by: Adw8 <adwait@deepstacksoft.com> Co-authored-by: Nabarun <nabarun@deepstacksoft.com>
This commit is contained in:
parent
3a2087b389
commit
4eecdb7e4c
@ -89,7 +89,7 @@
|
|||||||
|
|
||||||
5. Set up the Android device:
|
5. Set up the Android device:
|
||||||
|
|
||||||
- For a physical device, refer to the [React Native documentation for running on a physical device]("https://reactnative.dev/docs/running-on-device)
|
- For a physical device, refer to the [React Native documentation for running on a physical device](https://reactnative.dev/docs/running-on-device)
|
||||||
|
|
||||||
- For a virtual device, continue with the steps.
|
- For a virtual device, continue with the steps.
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import React from 'react';
|
|||||||
import App from '../src/App';
|
import App from '../src/App';
|
||||||
|
|
||||||
// Note: import explicitly to use the types shipped with jest.
|
// Note: import explicitly to use the types shipped with jest.
|
||||||
import {it} from '@jest/globals';
|
import { it } from '@jest/globals';
|
||||||
|
|
||||||
// Note: test renderer must be required after react-native.
|
// Note: test renderer must be required after react-native.
|
||||||
import renderer from 'react-test-renderer';
|
import renderer from 'react-test-renderer';
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
|
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metro configuration
|
* Metro configuration
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
"cosmjs-types": "^0.9.0",
|
"cosmjs-types": "^0.9.0",
|
||||||
"ethers": "5.7.2",
|
"ethers": "5.7.2",
|
||||||
"fast-text-encoding": "^1.0.6",
|
"fast-text-encoding": "^1.0.6",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
"metro-react-native-babel-preset": "^0.77.0",
|
"metro-react-native-babel-preset": "^0.77.0",
|
||||||
"patch-package": "^8.0.0",
|
"patch-package": "^8.0.0",
|
||||||
"postinstall-postinstall": "^2.1.0",
|
"postinstall-postinstall": "^2.1.0",
|
||||||
@ -51,6 +52,7 @@
|
|||||||
"@react-native/eslint-config": "0.73.2",
|
"@react-native/eslint-config": "0.73.2",
|
||||||
"@react-native/metro-config": "0.73.4",
|
"@react-native/metro-config": "0.73.4",
|
||||||
"@react-native/typescript-config": "0.73.1",
|
"@react-native/typescript-config": "0.73.1",
|
||||||
|
"@types/lodash": "^4.17.0",
|
||||||
"@types/react": "^18.2.6",
|
"@types/react": "^18.2.6",
|
||||||
"@types/react-native-vector-icons": "^6.4.18",
|
"@types/react-native-vector-icons": "^6.4.18",
|
||||||
"@types/react-test-renderer": "^18.0.0",
|
"@types/react-test-renderer": "^18.0.0",
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import AddSession from './screens/AddSession';
|
|||||||
import WalletConnect from './screens/WalletConnect';
|
import WalletConnect from './screens/WalletConnect';
|
||||||
import { StackParamsList } from './types';
|
import { StackParamsList } from './types';
|
||||||
import { web3wallet } from './utils/wallet-connect/WalletConnectUtils';
|
import { web3wallet } from './utils/wallet-connect/WalletConnectUtils';
|
||||||
import { EIP155_SIGNING_METHODS } from './utils/wallet-connect/EIP155Lib';
|
import { EIP155_SIGNING_METHODS } from './utils/wallet-connect/EIP155Data';
|
||||||
import { getSignParamsMessage } from './utils/wallet-connect/Helpers';
|
import { getSignParamsMessage } from './utils/wallet-connect/Helpers';
|
||||||
import ApproveTransaction from './screens/ApproveTransaction';
|
import ApproveTransaction from './screens/ApproveTransaction';
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,17 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { Image, View, Modal, ScrollView } from 'react-native';
|
import { Image, View, Modal, ScrollView } from 'react-native';
|
||||||
import { Button, Text } from 'react-native-paper';
|
import { Button, Text } from 'react-native-paper';
|
||||||
|
import mergeWith from 'lodash/mergeWith';
|
||||||
|
|
||||||
import { SessionTypes } from '@walletconnect/types';
|
import { buildApprovedNamespaces, getSdkError } from '@walletconnect/utils';
|
||||||
import { getSdkError } from '@walletconnect/utils';
|
|
||||||
|
|
||||||
import { PairingModalProps } from '../types';
|
import { AccountsState, PairingModalProps } from '../types';
|
||||||
import styles from '../styles/stylesheet';
|
import styles from '../styles/stylesheet';
|
||||||
import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils';
|
import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils';
|
||||||
import { useAccounts } from '../context/AccountsContext';
|
import { useAccounts } from '../context/AccountsContext';
|
||||||
import { useWalletConnect } from '../context/WalletConnectContext';
|
import { useWalletConnect } from '../context/WalletConnectContext';
|
||||||
|
import { EIP155_CHAINS } from '../utils/wallet-connect/EIP155Data';
|
||||||
|
import { COSMOS_MAINNET_CHAINS } from '../utils/wallet-connect/COSMOSData';
|
||||||
|
|
||||||
const PairingModal = ({
|
const PairingModal = ({
|
||||||
visible,
|
visible,
|
||||||
@ -18,7 +20,7 @@ const PairingModal = ({
|
|||||||
setModalVisible,
|
setModalVisible,
|
||||||
setToastVisible,
|
setToastVisible,
|
||||||
}: PairingModalProps) => {
|
}: PairingModalProps) => {
|
||||||
const { accounts } = useAccounts();
|
const { accounts, currentIndex } = useAccounts();
|
||||||
|
|
||||||
const url = currentProposal?.params?.proposer?.metadata.url;
|
const url = currentProposal?.params?.proposer?.metadata.url;
|
||||||
const icon = currentProposal?.params.proposer?.metadata.icons[0];
|
const icon = currentProposal?.params.proposer?.metadata.icons[0];
|
||||||
@ -38,126 +40,147 @@ const PairingModal = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { params } = currentProposal;
|
const { params } = currentProposal;
|
||||||
const { requiredNamespaces } = params;
|
const { requiredNamespaces, optionalNamespaces } = params;
|
||||||
|
|
||||||
setWalletConnectData({
|
setWalletConnectData({
|
||||||
walletConnectMethods: [],
|
walletConnectMethods: [],
|
||||||
walletConnectEvents: [],
|
walletConnectEvents: [],
|
||||||
walletConnectChains: [],
|
walletConnectChains: [],
|
||||||
});
|
});
|
||||||
Object.keys(requiredNamespaces).forEach(key => {
|
|
||||||
switch (key) {
|
|
||||||
case 'eip155':
|
|
||||||
const {
|
|
||||||
methods: ethMethods,
|
|
||||||
events: ethEvents,
|
|
||||||
chains: ethChains,
|
|
||||||
} = currentProposal?.params?.requiredNamespaces.eip155;
|
|
||||||
|
|
||||||
setWalletConnectData(prevData => {
|
const combinedNamespaces = mergeWith(
|
||||||
return {
|
requiredNamespaces,
|
||||||
walletConnectMethods: [
|
optionalNamespaces,
|
||||||
...prevData.walletConnectMethods,
|
(obj, src) =>
|
||||||
...ethMethods,
|
Array.isArray(obj) && Array.isArray(src) ? [...src, ...obj] : undefined,
|
||||||
],
|
);
|
||||||
walletConnectEvents: [
|
Object.keys(combinedNamespaces).forEach(key => {
|
||||||
...prevData.walletConnectEvents,
|
const { methods, events, chains } = combinedNamespaces[key];
|
||||||
...ethEvents,
|
|
||||||
],
|
|
||||||
walletConnectChains: ethChains
|
|
||||||
? [...prevData.walletConnectChains, ...ethChains]
|
|
||||||
: [...prevData.walletConnectChains],
|
|
||||||
};
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'cosmos':
|
|
||||||
const {
|
|
||||||
methods: cosmosMethods,
|
|
||||||
events: cosmosEvents,
|
|
||||||
chains: cosmosChains,
|
|
||||||
} = currentProposal?.params?.requiredNamespaces.cosmos;
|
|
||||||
|
|
||||||
setWalletConnectData(prevData => {
|
setWalletConnectData(prevData => {
|
||||||
return {
|
return {
|
||||||
walletConnectMethods: [
|
walletConnectMethods: [...prevData.walletConnectMethods, ...methods],
|
||||||
...prevData.walletConnectMethods,
|
walletConnectEvents: [...prevData.walletConnectEvents, ...events],
|
||||||
...cosmosMethods,
|
walletConnectChains: chains
|
||||||
],
|
? [...prevData.walletConnectChains, ...chains]
|
||||||
walletConnectEvents: [
|
: [...prevData.walletConnectChains],
|
||||||
...prevData.walletConnectEvents,
|
};
|
||||||
...cosmosEvents,
|
});
|
||||||
],
|
|
||||||
walletConnectChains: cosmosChains
|
|
||||||
? [...prevData.walletConnectChains, ...cosmosChains]
|
|
||||||
: [...prevData.walletConnectChains],
|
|
||||||
};
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error(`${key} not supported`);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}, [currentProposal]);
|
}, [currentProposal]);
|
||||||
|
|
||||||
const { setActiveSessions } = useWalletConnect();
|
const { setActiveSessions } = useWalletConnect();
|
||||||
|
|
||||||
const handleAccept = async () => {
|
const supportedNamespaces = useMemo(() => {
|
||||||
if (currentProposal) {
|
if (!currentProposal) {
|
||||||
const { id, params } = currentProposal;
|
return;
|
||||||
const { requiredNamespaces, relays } = params;
|
}
|
||||||
const namespaces: SessionTypes.Namespaces = {};
|
|
||||||
|
|
||||||
Object.keys(requiredNamespaces).forEach(key => {
|
// eip155
|
||||||
let currentAddresses: string[];
|
const eip155Chains = Object.keys(EIP155_CHAINS);
|
||||||
|
|
||||||
switch (key) {
|
// cosmos
|
||||||
case 'eip155':
|
const cosmosChains = Object.keys(COSMOS_MAINNET_CHAINS);
|
||||||
if (accounts.ethAccounts.length > 0) {
|
|
||||||
currentAddresses = accounts.ethAccounts.map(
|
// Set selected account as the first account in supported namespaces
|
||||||
account => account.address,
|
const sortedAccounts = Object.entries(accounts).reduce(
|
||||||
);
|
(acc: AccountsState, [key, value]) => {
|
||||||
}
|
let newValue = [...value];
|
||||||
break;
|
|
||||||
case 'cosmos':
|
// TODO: Implement selectedAccount instead of currentIndex in AccountsContext
|
||||||
if (accounts.cosmosAccounts.length > 0) {
|
if (value.length > currentIndex) {
|
||||||
currentAddresses = accounts.cosmosAccounts.map(
|
const currentAccount = newValue[currentIndex];
|
||||||
account => account.address,
|
const remainingAccounts = newValue.filter(
|
||||||
);
|
(_, index) => index !== currentIndex,
|
||||||
}
|
);
|
||||||
break;
|
newValue = [currentAccount, ...remainingAccounts];
|
||||||
default:
|
|
||||||
throw new Error(`${key} not supported`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const namespaceAccounts: string[] = [];
|
acc[key as 'ethAccounts' | 'cosmosAccounts'] = newValue;
|
||||||
requiredNamespaces[key].chains!.map((chain: string) => {
|
return acc;
|
||||||
currentAddresses.map(acc =>
|
},
|
||||||
namespaceAccounts.push(`${chain}:${acc}`),
|
{ ethAccounts: [], cosmosAccounts: [] },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { optionalNamespaces, requiredNamespaces } = currentProposal.params;
|
||||||
|
|
||||||
|
return {
|
||||||
|
eip155: {
|
||||||
|
chains: eip155Chains,
|
||||||
|
// TODO: Debug optional namespace methods and events being required for approval
|
||||||
|
methods: [
|
||||||
|
...(optionalNamespaces.eip155?.methods ?? []),
|
||||||
|
...(requiredNamespaces.eip155?.methods ?? []),
|
||||||
|
],
|
||||||
|
events: [
|
||||||
|
...(optionalNamespaces.eip155?.events ?? []),
|
||||||
|
...(requiredNamespaces.eip155?.events ?? []),
|
||||||
|
],
|
||||||
|
|
||||||
|
accounts: eip155Chains
|
||||||
|
.map(chain =>
|
||||||
|
sortedAccounts.ethAccounts.map(
|
||||||
|
account => `${chain}:${account.address}`,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.flat(),
|
||||||
|
},
|
||||||
|
cosmos: {
|
||||||
|
chains: cosmosChains,
|
||||||
|
methods: [
|
||||||
|
...(optionalNamespaces.cosmos?.methods ?? []),
|
||||||
|
...(requiredNamespaces.cosmos?.methods ?? []),
|
||||||
|
],
|
||||||
|
events: [
|
||||||
|
...(optionalNamespaces.cosmos?.events ?? []),
|
||||||
|
...(requiredNamespaces.cosmos?.events ?? []),
|
||||||
|
],
|
||||||
|
accounts: cosmosChains
|
||||||
|
.map(chain =>
|
||||||
|
sortedAccounts.cosmosAccounts.map(
|
||||||
|
account => `${chain}:${account.address}`,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.flat(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}, [currentIndex, accounts, currentProposal]);
|
||||||
|
|
||||||
|
const namespaces = useMemo(() => {
|
||||||
|
return (
|
||||||
|
currentProposal &&
|
||||||
|
supportedNamespaces &&
|
||||||
|
buildApprovedNamespaces({
|
||||||
|
proposal: currentProposal.params,
|
||||||
|
supportedNamespaces,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}, [currentProposal, supportedNamespaces]);
|
||||||
|
|
||||||
|
const handleAccept = async () => {
|
||||||
|
try {
|
||||||
|
if (currentProposal && namespaces) {
|
||||||
|
const { id } = currentProposal;
|
||||||
|
|
||||||
|
await web3wallet!.approveSession({
|
||||||
|
id,
|
||||||
|
namespaces,
|
||||||
});
|
});
|
||||||
|
|
||||||
namespaces[key] = {
|
const sessions = web3wallet!.getActiveSessions();
|
||||||
accounts: namespaceAccounts,
|
setActiveSessions(sessions);
|
||||||
methods: requiredNamespaces[key].methods,
|
setModalVisible(false);
|
||||||
events: requiredNamespaces[key].events,
|
setToastVisible(true);
|
||||||
};
|
setCurrentProposal(undefined);
|
||||||
});
|
setWalletConnectData({
|
||||||
|
walletConnectMethods: [],
|
||||||
await web3wallet!.approveSession({
|
walletConnectEvents: [],
|
||||||
id,
|
walletConnectChains: [],
|
||||||
relayProtocol: relays[0].protocol,
|
});
|
||||||
namespaces,
|
}
|
||||||
});
|
} catch (error) {
|
||||||
|
console.error('Error in approve session:', error);
|
||||||
const sessions = web3wallet!.getActiveSessions();
|
throw error;
|
||||||
setActiveSessions(sessions);
|
|
||||||
setModalVisible(false);
|
|
||||||
setToastVisible(true);
|
|
||||||
setCurrentProposal(undefined);
|
|
||||||
setWalletConnectData({
|
|
||||||
walletConnectMethods: [],
|
|
||||||
walletConnectEvents: [],
|
|
||||||
walletConnectChains: [],
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -216,11 +239,11 @@ const PairingModal = ({
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={styles.flexRow}>
|
<View style={styles.flexRow}>
|
||||||
<Button mode="contained" onPress={() => handleAccept()}>
|
<Button mode="contained" onPress={handleAccept}>
|
||||||
Accept
|
Accept
|
||||||
</Button>
|
</Button>
|
||||||
<View style={styles.space} />
|
<View style={styles.space} />
|
||||||
<Button mode="outlined" onPress={() => handleReject()}>
|
<Button mode="outlined" onPress={handleReject}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@ -5,9 +5,13 @@ import { AccountsState } from '../types';
|
|||||||
const AccountsContext = createContext<{
|
const AccountsContext = createContext<{
|
||||||
accounts: AccountsState;
|
accounts: AccountsState;
|
||||||
setAccounts: (account: AccountsState) => void;
|
setAccounts: (account: AccountsState) => void;
|
||||||
|
currentIndex: number;
|
||||||
|
setCurrentIndex: (index: number) => void;
|
||||||
}>({
|
}>({
|
||||||
accounts: { ethAccounts: [], cosmosAccounts: [] },
|
accounts: { ethAccounts: [], cosmosAccounts: [] },
|
||||||
setAccounts: () => {},
|
setAccounts: () => {},
|
||||||
|
currentIndex: 0,
|
||||||
|
setCurrentIndex: () => {},
|
||||||
});
|
});
|
||||||
|
|
||||||
const useAccounts = () => {
|
const useAccounts = () => {
|
||||||
@ -20,8 +24,10 @@ const AccountsProvider = ({ children }: { children: any }) => {
|
|||||||
ethAccounts: [],
|
ethAccounts: [],
|
||||||
cosmosAccounts: [],
|
cosmosAccounts: [],
|
||||||
});
|
});
|
||||||
|
const [currentIndex, setCurrentIndex] = useState<number>(0);
|
||||||
return (
|
return (
|
||||||
<AccountsContext.Provider value={{ accounts, setAccounts }}>
|
<AccountsContext.Provider
|
||||||
|
value={{ accounts, setAccounts, currentIndex, setCurrentIndex }}>
|
||||||
{children}
|
{children}
|
||||||
</AccountsContext.Provider>
|
</AccountsContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -9,7 +9,7 @@ export default function useInitialization() {
|
|||||||
await createWeb3Wallet();
|
await createWeb3Wallet();
|
||||||
setInitialized(true);
|
setInitialized(true);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
console.log('Error for initializing', err);
|
console.error('Error for initializing', err);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { Image, ScrollView, View } from 'react-native';
|
import { Image, ScrollView, View } from 'react-native';
|
||||||
import { ActivityIndicator, Button, Text, Appbar } from 'react-native-paper';
|
import { ActivityIndicator, Button, Text, Appbar } from 'react-native-paper';
|
||||||
import { PopulatedTransaction, providers, BigNumber } from 'ethers';
|
import { providers, BigNumber } from 'ethers';
|
||||||
|
|
||||||
import { useNavigation } from '@react-navigation/native';
|
import { useNavigation } from '@react-navigation/native';
|
||||||
import {
|
import {
|
||||||
@ -61,16 +61,22 @@ const ApproveTransaction = ({ route }: SignRequestProps) => {
|
|||||||
const navigation =
|
const navigation =
|
||||||
useNavigation<NativeStackNavigationProp<StackParamsList>>();
|
useNavigation<NativeStackNavigationProp<StackParamsList>>();
|
||||||
|
|
||||||
const retrieveData = async (requestAddress: string) => {
|
const retrieveData = useCallback(
|
||||||
const requestAccount = await retrieveSingleAccount(network, requestAddress);
|
async (requestAddress: string) => {
|
||||||
if (!requestAccount) {
|
const requestAccount = await retrieveSingleAccount(
|
||||||
navigation.navigate('InvalidPath');
|
network,
|
||||||
return;
|
requestAddress,
|
||||||
}
|
);
|
||||||
|
if (!requestAccount) {
|
||||||
|
navigation.navigate('InvalidPath');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setAccount(requestAccount);
|
setAccount(requestAccount);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
},
|
||||||
|
[navigation, network],
|
||||||
|
);
|
||||||
|
|
||||||
const gasFees = useMemo(() => {
|
const gasFees = useMemo(() => {
|
||||||
if (network === 'eth') {
|
if (network === 'eth') {
|
||||||
@ -87,7 +93,7 @@ const ApproveTransaction = ({ route }: SignRequestProps) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
retrieveData(transaction.from!);
|
retrieveData(transaction.from!);
|
||||||
}, [route]);
|
}, [retrieveData, transaction]);
|
||||||
|
|
||||||
const acceptRequestHandler = async () => {
|
const acceptRequestHandler = async () => {
|
||||||
if (!account) {
|
if (!account) {
|
||||||
|
|||||||
@ -28,7 +28,8 @@ const WCLogo = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const HomeScreen = () => {
|
const HomeScreen = () => {
|
||||||
const { accounts, setAccounts } = useAccounts();
|
const { accounts, setAccounts, currentIndex, setCurrentIndex } =
|
||||||
|
useAccounts();
|
||||||
const { setActiveSessions } = useWalletConnect();
|
const { setActiveSessions } = useWalletConnect();
|
||||||
|
|
||||||
const navigation =
|
const navigation =
|
||||||
@ -54,7 +55,6 @@ const HomeScreen = () => {
|
|||||||
const [walletDialog, setWalletDialog] = useState<boolean>(false);
|
const [walletDialog, setWalletDialog] = useState<boolean>(false);
|
||||||
const [resetWalletDialog, setResetWalletDialog] = useState<boolean>(false);
|
const [resetWalletDialog, setResetWalletDialog] = useState<boolean>(false);
|
||||||
const [network, setNetwork] = useState<string>('eth');
|
const [network, setNetwork] = useState<string>('eth');
|
||||||
const [currentIndex, setCurrentIndex] = useState<number>(0);
|
|
||||||
const [isAccountsFetched, setIsAccountsFetched] = useState<boolean>(false);
|
const [isAccountsFetched, setIsAccountsFetched] = useState<boolean>(false);
|
||||||
const [phrase, setPhrase] = useState('');
|
const [phrase, setPhrase] = useState('');
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { Alert, Image, ScrollView, View } from 'react-native';
|
import { Alert, Image, ScrollView, View } from 'react-native';
|
||||||
import { ActivityIndicator, Button, Text, Appbar } from 'react-native-paper';
|
import { ActivityIndicator, Button, Text, Appbar } from 'react-native-paper';
|
||||||
|
|
||||||
@ -60,48 +60,54 @@ const SignRequest = ({ route }: SignRequestProps) => {
|
|||||||
);
|
);
|
||||||
}, [route.params]);
|
}, [route.params]);
|
||||||
|
|
||||||
const retrieveData = async (
|
const retrieveData = useCallback(
|
||||||
requestNetwork: string,
|
async (
|
||||||
requestAddress: string,
|
requestNetwork: string,
|
||||||
requestMessage: string,
|
requestAddress: string,
|
||||||
) => {
|
requestMessage: string,
|
||||||
const requestAccount = await retrieveSingleAccount(
|
) => {
|
||||||
requestNetwork,
|
const requestAccount = await retrieveSingleAccount(
|
||||||
requestAddress,
|
requestNetwork,
|
||||||
);
|
requestAddress,
|
||||||
if (!requestAccount) {
|
);
|
||||||
navigation.navigate('InvalidPath');
|
if (!requestAccount) {
|
||||||
return;
|
navigation.navigate('InvalidPath');
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (requestAccount !== account) {
|
if (requestAccount !== account) {
|
||||||
setAccount(requestAccount);
|
setAccount(requestAccount);
|
||||||
}
|
}
|
||||||
if (requestMessage !== message) {
|
if (requestMessage !== message) {
|
||||||
setMessage(decodeURIComponent(requestMessage));
|
setMessage(decodeURIComponent(requestMessage));
|
||||||
}
|
}
|
||||||
if (requestNetwork !== network) {
|
if (requestNetwork !== network) {
|
||||||
setNetwork(requestNetwork);
|
setNetwork(requestNetwork);
|
||||||
}
|
}
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
},
|
||||||
|
[account, message, navigation, network],
|
||||||
|
);
|
||||||
|
|
||||||
const sanitizePath = (path: string) => {
|
const sanitizePath = useCallback(
|
||||||
const regex = /^\/sign\/(eth|cosmos)\/(.+)\/(.+)$/;
|
(path: string) => {
|
||||||
const match = path.match(regex);
|
const regex = /^\/sign\/(eth|cosmos)\/(.+)\/(.+)$/;
|
||||||
|
const match = path.match(regex);
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
const [network, address, message] = match;
|
const [network, address, message] = match;
|
||||||
return {
|
return {
|
||||||
network,
|
network,
|
||||||
address,
|
address,
|
||||||
message,
|
message,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
navigation.navigate('InvalidPath');
|
navigation.navigate('InvalidPath');
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
},
|
||||||
|
[navigation],
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (route.path) {
|
if (route.path) {
|
||||||
@ -119,7 +125,7 @@ const SignRequest = ({ route }: SignRequestProps) => {
|
|||||||
route.params.address,
|
route.params.address,
|
||||||
route.params.message,
|
route.params.message,
|
||||||
);
|
);
|
||||||
}, [route]);
|
}, [retrieveData, sanitizePath, route]);
|
||||||
|
|
||||||
const handleWalletConnectRequest = async () => {
|
const handleWalletConnectRequest = async () => {
|
||||||
const { requestEvent } = route.params;
|
const { requestEvent } = route.params;
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export default function WalletConnect() {
|
|||||||
const { activeSessions, setActiveSessions } = useWalletConnect();
|
const { activeSessions, setActiveSessions } = useWalletConnect();
|
||||||
|
|
||||||
const disconnect = async (sessionId: string) => {
|
const disconnect = async (sessionId: string) => {
|
||||||
await web3wallet.disconnectSession({
|
await web3wallet!.disconnectSession({
|
||||||
topic: sessionId,
|
topic: sessionId,
|
||||||
reason: getSdkError('USER_DISCONNECTED'),
|
reason: getSdkError('USER_DISCONNECTED'),
|
||||||
});
|
});
|
||||||
@ -22,7 +22,7 @@ export default function WalletConnect() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const sessions = web3wallet.getActiveSessions();
|
const sessions = web3wallet!.getActiveSessions();
|
||||||
setActiveSessions(sessions);
|
setActiveSessions(sessions);
|
||||||
}, [setActiveSessions]);
|
}, [setActiveSessions]);
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
/**
|
/**
|
||||||
* Types
|
* Types
|
||||||
*/
|
*/
|
||||||
export type TCosmosChain = keyof typeof COSMOS_TESTNET_CHAINS;
|
export type TCosmosChain = keyof typeof COSMOS_CHAINS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chains
|
* Chains
|
||||||
@ -27,11 +27,31 @@ export const COSMOS_TESTNET_CHAINS: Record<
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const COSMOS_MAINNET_CHAINS = {
|
||||||
|
'cosmos:cosmoshub-4': {
|
||||||
|
chainId: 'cosmoshub-4',
|
||||||
|
name: 'Cosmos Hub',
|
||||||
|
logo: '/chain-logos/cosmos-cosmoshub-4.png',
|
||||||
|
rgb: '107, 111, 147',
|
||||||
|
rpc: '',
|
||||||
|
namespace: 'cosmos',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const COSMOS_CHAINS = {
|
||||||
|
...COSMOS_MAINNET_CHAINS,
|
||||||
|
...COSMOS_TESTNET_CHAINS,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Methods
|
* Methods
|
||||||
*/
|
*/
|
||||||
export const COSMOS_METHODS = {
|
export const COSMOS_SIGNING_METHODS = {
|
||||||
COSMOS_SIGN_DIRECT: 'cosmos_signDirect',
|
COSMOS_SIGN_DIRECT: 'cosmos_signDirect',
|
||||||
COSMOS_SIGN_AMINO: 'cosmos_signAmino',
|
COSMOS_SIGN_AMINO: 'cosmos_signAmino',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const COSMOS_METHODS = {
|
||||||
|
...COSMOS_SIGNING_METHODS,
|
||||||
COSMOS_SEND_TOKENS: 'cosmos_sendTokens', // Added for pay.laconic.com
|
COSMOS_SEND_TOKENS: 'cosmos_sendTokens', // Added for pay.laconic.com
|
||||||
};
|
};
|
||||||
|
|||||||
@ -64,6 +64,16 @@ export const EIP155_MAINNET_CHAINS: Record<string, EIP155Chain> = {
|
|||||||
rpc: 'https://mainnet.era.zksync.io/',
|
rpc: 'https://mainnet.era.zksync.io/',
|
||||||
namespace: 'eip155',
|
namespace: 'eip155',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Required chain by SIWE
|
||||||
|
'eip155:42161': {
|
||||||
|
chainId: 42161,
|
||||||
|
name: 'Arbitrum One',
|
||||||
|
logo: '',
|
||||||
|
rgb: '242, 242, 242',
|
||||||
|
rpc: 'https://arb1.arbitrum.io/rpc',
|
||||||
|
namespace: 'eip155',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EIP155_TEST_CHAINS: Record<string, EIP155Chain> = {
|
export const EIP155_TEST_CHAINS: Record<string, EIP155Chain> = {
|
||||||
|
|||||||
@ -51,97 +51,3 @@ export default class EIP155Lib {
|
|||||||
return this.wallet.signTransaction(transaction);
|
return this.wallet.signTransaction(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @desc Reference list of eip155 chains
|
|
||||||
* @url https://chainlist.org
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Types
|
|
||||||
*/
|
|
||||||
export type TEIP155Chain = keyof typeof EIP155_CHAINS;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Chains
|
|
||||||
*/
|
|
||||||
export const EIP155_MAINNET_CHAINS = {
|
|
||||||
'eip155:1': {
|
|
||||||
chainId: 1,
|
|
||||||
name: 'Ethereum',
|
|
||||||
logo: '/chain-logos/eip155-1.png',
|
|
||||||
rgb: '99, 125, 234',
|
|
||||||
rpc: 'https://cloudflare-eth.com/',
|
|
||||||
},
|
|
||||||
'eip155:43114': {
|
|
||||||
chainId: 43114,
|
|
||||||
name: 'Avalanche C-Chain',
|
|
||||||
logo: '/chain-logos/eip155-43113.png',
|
|
||||||
rgb: '232, 65, 66',
|
|
||||||
rpc: 'https://api.avax.network/ext/bc/C/rpc',
|
|
||||||
},
|
|
||||||
'eip155:137': {
|
|
||||||
chainId: 137,
|
|
||||||
name: 'Polygon',
|
|
||||||
logo: '/chain-logos/eip155-137.png',
|
|
||||||
rgb: '130, 71, 229',
|
|
||||||
rpc: 'https://polygon-rpc.com/',
|
|
||||||
},
|
|
||||||
'eip155:10': {
|
|
||||||
chainId: 10,
|
|
||||||
name: 'Optimism',
|
|
||||||
logo: '/chain-logos/eip155-10.png',
|
|
||||||
rgb: '235, 0, 25',
|
|
||||||
rpc: 'https://mainnet.optimism.io',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const EIP155_TEST_CHAINS = {
|
|
||||||
'eip155:5': {
|
|
||||||
chainId: 5,
|
|
||||||
name: 'Ethereum Goerli',
|
|
||||||
logo: '/chain-logos/eip155-1.png',
|
|
||||||
rgb: '99, 125, 234',
|
|
||||||
rpc: 'https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161',
|
|
||||||
},
|
|
||||||
'eip155:43113': {
|
|
||||||
chainId: 43113,
|
|
||||||
name: 'Avalanche Fuji',
|
|
||||||
logo: '/chain-logos/eip155-43113.png',
|
|
||||||
rgb: '232, 65, 66',
|
|
||||||
rpc: 'https://api.avax-test.network/ext/bc/C/rpc',
|
|
||||||
},
|
|
||||||
'eip155:80001': {
|
|
||||||
chainId: 80001,
|
|
||||||
name: 'Polygon Mumbai',
|
|
||||||
logo: '/chain-logos/eip155-137.png',
|
|
||||||
rgb: '130, 71, 229',
|
|
||||||
rpc: 'https://matic-mumbai.chainstacklabs.com',
|
|
||||||
},
|
|
||||||
'eip155:420': {
|
|
||||||
chainId: 420,
|
|
||||||
name: 'Optimism Goerli',
|
|
||||||
logo: '/chain-logos/eip155-10.png',
|
|
||||||
rgb: '235, 0, 25',
|
|
||||||
rpc: 'https://goerli.optimism.io',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const EIP155_CHAINS = {
|
|
||||||
...EIP155_MAINNET_CHAINS,
|
|
||||||
...EIP155_TEST_CHAINS,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Methods
|
|
||||||
*/
|
|
||||||
export const EIP155_SIGNING_METHODS = {
|
|
||||||
PERSONAL_SIGN: 'personal_sign',
|
|
||||||
ETH_SIGN: 'eth_sign',
|
|
||||||
ETH_SIGN_TRANSACTION: 'eth_signTransaction',
|
|
||||||
ETH_SIGN_TYPED_DATA: 'eth_signTypedData',
|
|
||||||
ETH_SIGN_TYPED_DATA_V3: 'eth_signTypedData_v3',
|
|
||||||
ETH_SIGN_TYPED_DATA_V4: 'eth_signTypedData_v4',
|
|
||||||
ETH_SEND_RAW_TRANSACTION: 'eth_sendRawTransaction',
|
|
||||||
ETH_SEND_TRANSACTION: 'eth_sendTransaction',
|
|
||||||
};
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import { utils } from 'ethers';
|
import { utils } from 'ethers';
|
||||||
|
|
||||||
import { Account } from '../../types';
|
import { Account } from '../../types';
|
||||||
import { EIP155_CHAINS, TEIP155Chain } from './EIP155Lib';
|
import { EIP155_CHAINS, TEIP155Chain } from './EIP155Data';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Truncates string (in the middle) via given lenght value
|
* Truncates string (in the middle) via given lenght value
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import {
|
|||||||
calculateFee,
|
calculateFee,
|
||||||
} from '@cosmjs/stargate';
|
} from '@cosmjs/stargate';
|
||||||
|
|
||||||
import { EIP155_SIGNING_METHODS } from './EIP155Lib';
|
import { EIP155_SIGNING_METHODS } from './EIP155Data';
|
||||||
import { signDirectMessage, signEthMessage } from '../sign-message';
|
import { signDirectMessage, signEthMessage } from '../sign-message';
|
||||||
import { Account } from '../../types';
|
import { Account } from '../../types';
|
||||||
import { getMnemonic, getPathKey } from '../misc';
|
import { getMnemonic, getPathKey } from '../misc';
|
||||||
@ -60,9 +60,7 @@ export async function approveWalletConnectRequest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ethSignature = await signEthMessage(message, account.counterId);
|
const ethSignature = await signEthMessage(message, account.counterId);
|
||||||
return formatJsonRpcResult(id, {
|
return formatJsonRpcResult(id, ethSignature);
|
||||||
signature: ethSignature,
|
|
||||||
});
|
|
||||||
|
|
||||||
case 'cosmos_signDirect':
|
case 'cosmos_signDirect':
|
||||||
// Reference: https://github.com/confio/cosmjs-types/blob/66e52711914fccd2a9d1a03e392d3628fdf499e2/src/cosmos/tx/v1beta1/tx.ts#L51
|
// Reference: https://github.com/confio/cosmjs-types/blob/66e52711914fccd2a9d1a03e392d3628fdf499e2/src/cosmos/tx/v1beta1/tx.ts#L51
|
||||||
|
|||||||
@ -2814,6 +2814,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a"
|
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a"
|
||||||
integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==
|
integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==
|
||||||
|
|
||||||
|
"@types/lodash@^4.17.0":
|
||||||
|
version "4.17.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.0.tgz#d774355e41f372d5350a4d0714abb48194a489c3"
|
||||||
|
integrity sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/node@*":
|
||||||
version "20.11.16"
|
version "20.11.16"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.16.tgz#4411f79411514eb8e2926f036c86c9f0e4ec6708"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.16.tgz#4411f79411514eb8e2926f036c86c9f0e4ec6708"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user