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:
Adwait Gharpure 2024-03-28 11:10:55 +05:30 committed by GitHub
parent 3a2087b389
commit 4eecdb7e4c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 255 additions and 273 deletions

View File

@ -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.

View File

@ -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';

View File

@ -1,4 +1,4 @@
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
/** /**
* Metro configuration * Metro configuration

View File

@ -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",

View File

@ -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';

View File

@ -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>

View File

@ -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>
); );

View File

@ -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);
} }
}, []); }, []);

View File

@ -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) {

View File

@ -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('');

View File

@ -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;

View File

@ -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]);

View File

@ -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
}; };

View File

@ -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> = {

View File

@ -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',
};

View File

@ -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

View File

@ -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

View File

@ -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"