Skip to content

Commit

Permalink
[REF] ensure that each evm account has all supported wallets attached
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielbazan7 committed Oct 1, 2024
1 parent 9602c7c commit f5b3fd3
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 38 deletions.
62 changes: 61 additions & 1 deletion src/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,12 @@ import DebugScreen, {
import CardActivationGroup, {
CardActivationGroupParamList,
} from './navigation/card-activation/CardActivationGroup';
import {fixWalletAddresses, sleep} from './utils/helper-methods';
import {
createWalletsForAccounts,
fixWalletAddresses,
getEvmGasWallets,
sleep,
} from './utils/helper-methods';
import {Analytics} from './store/analytics/analytics.effects';
import {
handleBwsEvent,
Expand Down Expand Up @@ -133,6 +138,11 @@ import SettingsGroup, {
} from './navigation/tabs/settings/SettingsGroup';
import {ImportLedgerWalletModal} from './components/modal/import-ledger-wallet/ImportLedgerWalletModal';
import {WalletConnectStartModal} from './components/modal/wallet-connect/WalletConnectStartModal';
import {KeyMethods} from './store/wallet/wallet.models';
import {
setAccountEVMCreationMigrationComplete,
successAddWallet,
} from './store/wallet/wallet.actions';

// ROOT NAVIGATION CONFIG
export type RootStackParamList = {
Expand Down Expand Up @@ -266,6 +276,9 @@ export default () => {
);
const inAppMessageData = useAppSelector(({APP}) => APP.inAppMessageData);
const keys = useAppSelector(({WALLET}) => WALLET.keys);
const accountEvmCreationMigrationComplete = useAppSelector(
({WALLET}) => WALLET.accountEvmCreationMigrationComplete,
);

const blurScreenList: string[] = [
OnboardingScreens.IMPORT,
Expand Down Expand Up @@ -553,6 +566,50 @@ export default () => {
}
};

// we need to ensure that each evm account has all supported wallets attached.
const runCompleteEvmWalletsAccountFix = async () => {
try {
dispatch(startOnGoingProcessModal('GENERAL_AWAITING'));
await sleep(1000); // give the modal time to show
await Promise.all(
Object.values(keys).map(async key => {
const evmWallets = getEvmGasWallets(key.wallets);
const accountsArray = [
...new Set(
evmWallets.map(wallet => wallet.credentials.account),
),
];
const wallets = await createWalletsForAccounts(
dispatch,
accountsArray,
key.methods as KeyMethods,
);
key.wallets.push(...wallets);
dispatch(successAddWallet({key}));
}),
);
dispatch(
LogActions.info(
'success [runCompleteEvmWalletsAccountFix]',
),
);
dispatch(setAccountEVMCreationMigrationComplete());
dispatch(dismissOnGoingProcessModal());
} catch (error) {
const errMsg =
error instanceof Error
? error.message
: JSON.stringify(error);
dispatch(
LogActions.error(
`Error in [runCompleteEvmWalletsAccountFix]: ${errMsg}`,
),
);
dispatch(setAccountEVMCreationMigrationComplete());
dispatch(dismissOnGoingProcessModal());
}
};

if (pinLockActive || biometricLockActive) {
const subscriptionToPinModalDismissed =
DeviceEventEmitter.addListener(
Expand All @@ -565,6 +622,9 @@ export default () => {
);
} else {
await runAddressFix();
if (!accountEvmCreationMigrationComplete) {
await runCompleteEvmWalletsAccountFix();
}
urlHandler();
}

Expand Down
65 changes: 37 additions & 28 deletions src/store/wallet/effects/create/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,35 +368,44 @@ export const createMultipleWallets =
const tokens = currencies.filter(({isToken}) => isToken);
const coins = currencies.filter(({isToken}) => !isToken);
for (const coin of coins) {
const wallet = (await dispatch(
createWallet({
key,
coin: coin.currencyAbbreviation,
chain: coin.chain as SupportedChains,
options: {
...options,
useNativeSegwit: IsSegwitCoin(coin.currencyAbbreviation),
},
}),
)) as Wallet;
const receiveAddress = (await dispatch<any>(
createWalletAddress({wallet, newAddress: true}),
)) as string;
dispatch(LogActions.info(`new address generated: ${receiveAddress}`));
wallet.receiveAddress = receiveAddress;
wallets.push(wallet);
for (const token of tokens) {
if (token.chain === coin.chain) {
const tokenWallet = await dispatch(
createTokenWallet(
wallet,
token.currencyAbbreviation.toLowerCase(),
token.tokenAddress!,
tokenOpts,
),
);
wallets.push(tokenWallet);
try {
const wallet = (await dispatch(
createWallet({
key,
coin: coin.currencyAbbreviation,
chain: coin.chain as SupportedChains,
options: {
...options,
useNativeSegwit: IsSegwitCoin(coin.currencyAbbreviation),
},
}),
)) as Wallet;
const receiveAddress = (await dispatch<any>(
createWalletAddress({wallet, newAddress: true}),
)) as string;
dispatch(LogActions.info(`new address generated: ${receiveAddress}`));
wallet.receiveAddress = receiveAddress;
wallets.push(wallet);
for (const token of tokens) {
if (token.chain === coin.chain) {
const tokenWallet = await dispatch(
createTokenWallet(
wallet,
token.currencyAbbreviation.toLowerCase(),
token.tokenAddress!,
tokenOpts,
),
);
wallets.push(tokenWallet);
}
}
} catch (err) {
const errMsg = err instanceof Error ? err.message : JSON.stringify(err);
dispatch(
LogActions.debug(
`Error creating wallet - continue anyway: ${errMsg}`,
),
);
}
}

Expand Down
22 changes: 18 additions & 4 deletions src/store/wallet/effects/import/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ import {
deleteKey,
failedImport,
setCustomizeNonce,
setEnableReplaceByFee,
setUseUnconfirmedFunds,
setWalletTermsAccepted,
successImport,
updateCacheFeeLevel,
updatePortfolioBalance,
} from '../../wallet.actions';
import {
BitpaySupportedEthereumTokenOptsByAddress,
Expand Down Expand Up @@ -95,14 +93,17 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
import RNRestart from 'react-native-restart';
import uniqBy from 'lodash.uniqby';
import {credentialsFromExtendedPublicKey} from '../../../../utils/wallet-hardware';
import {sleep} from '../../../../utils/helper-methods';
import {BitpaySupportedCoins} from '../../../../constants/currencies';
import {
GetName,
IsSegwitCoin,
isSingleAddressChain,
} from '../../utils/currency';
import {BASE_BWS_URL} from '../../../../constants/config';
import {
createWalletsForAccounts,
getEvmGasWallets,
} from '../../../../utils/helper-methods';

const BWC = BwcProvider.getInstance();
const BwcConstants = BWC.getConstants();
Expand Down Expand Up @@ -849,7 +850,19 @@ export const startImportMnemonic =
opts.xPrivKey = xPrivKey;

const data = await serverAssistedImport(opts);

// we need to ensure that each evm account has all supported wallets attached.
const evmWallets = getEvmGasWallets(data.wallets);
const accountsArray = [
...new Set(evmWallets.map(wallet => wallet.credentials.account)),
];
const _wallets = await createWalletsForAccounts(
dispatch,
accountsArray,
data.key as KeyMethods,
);
if (_wallets.length > 0) {
data.wallets.push(..._wallets);
}
// To Avoid Duplicate wallet import
const {
key: _key,
Expand Down Expand Up @@ -1548,6 +1561,7 @@ export const serverAssistedImport = async (
}
});
};

const linkTokenToWallet = (tokens: Wallet[], wallets: Wallet[]) => {
tokens.forEach(token => {
// find the associated wallet to add tokens too
Expand Down
2 changes: 0 additions & 2 deletions src/store/wallet/utils/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ import {
AssetsByChainData,
AssetsByChainListProps,
} from '../../../navigation/wallet/screens/AccountDetails';
import {DeviceEventEmitter} from 'react-native';
import {DeviceEmitterEvents} from '../../../constants/device-emitter-events';

export const mapAbbreviationAndName =
(
Expand Down
4 changes: 4 additions & 0 deletions src/store/wallet/wallet.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,7 @@ export const setCustomTokensMigrationComplete = (): WalletActionType => ({
export const setPolygonMigrationComplete = (): WalletActionType => ({
type: WalletActionTypes.SET_POLYGON_MIGRATION_COMPLETE,
});

export const setAccountEVMCreationMigrationComplete = (): WalletActionType => ({
type: WalletActionTypes.SET_ACCOUNT_EVM_CREATION_MIGRATION_COMPLETE,
});
8 changes: 8 additions & 0 deletions src/store/wallet/wallet.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface WalletState {
initLogs: AddLog[];
customTokensMigrationComplete: boolean;
polygonMigrationComplete: boolean;
accountEvmCreationMigrationComplete: boolean;
}

export const initialState: WalletState = {
Expand Down Expand Up @@ -71,6 +72,7 @@ export const initialState: WalletState = {
initLogs: [], // keep init logs at the end (order is important)
customTokensMigrationComplete: false,
polygonMigrationComplete: false,
accountEvmCreationMigrationComplete: false,
};

export const walletReducer = (
Expand Down Expand Up @@ -606,6 +608,12 @@ export const walletReducer = (
polygonMigrationComplete: true,
};

case WalletActionTypes.SET_ACCOUNT_EVM_CREATION_MIGRATION_COMPLETE:
return {
...state,
accountEvmCreationMigrationComplete: true,
};

default:
return state;
}
Expand Down
8 changes: 7 additions & 1 deletion src/store/wallet/wallet.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export enum WalletActionTypes {
CLEAR_DEFERRED_IMPORT = 'WALLET/CLEAR_DEFERRED_IMPORT',
SET_CUSTOM_TOKENS_MIGRATION_COMPLETE = 'APP/SET_CUSTOM_TOKENS_MIGRATION_COMPLETE',
SET_POLYGON_MIGRATION_COMPLETE = 'APP/SET_POLYGON_MIGRATION_COMPLETE',
SET_ACCOUNT_EVM_CREATION_MIGRATION_COMPLETE = 'APP/SET_ACCOUNT_EVM_CREATION_MIGRATION_COMPLETE',
}

interface successWalletStoreInit {
Expand Down Expand Up @@ -330,6 +331,10 @@ interface setPolygonMigrationComplete {
type: typeof WalletActionTypes.SET_POLYGON_MIGRATION_COMPLETE;
}

interface setAccountEVMCreationMigrationComplete {
type: typeof WalletActionTypes.SET_ACCOUNT_EVM_CREATION_MIGRATION_COMPLETE;
}

export type WalletActionType =
| successWalletStoreInit
| failedWalletStoreInit
Expand Down Expand Up @@ -372,4 +377,5 @@ export type WalletActionType =
| toggleHideAccount
| updateCacheFeeLevel
| SetCustomTokensMigrationComplete
| setPolygonMigrationComplete;
| setPolygonMigrationComplete
| setAccountEVMCreationMigrationComplete;
49 changes: 47 additions & 2 deletions src/utils/helper-methods.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {Key, Wallet} from '../store/wallet/wallet.models';
import {Key, KeyMethods, Wallet} from '../store/wallet/wallet.models';
import {ContactRowProps} from '../components/list/ContactRow';
import {Network} from '../constants';
import {CurrencyListIcons} from '../constants/SupportedCurrencyOptions';
import {ReactElement} from 'react';
import {IsERCToken} from '../store/wallet/utils/currency';
import {IsERCToken, IsEVMChain} from '../store/wallet/utils/currency';
import {Rate, Rates} from '../store/rate/rate.models';
import {PROTOCOL_NAME} from '../constants/config';
import _ from 'lodash';
Expand All @@ -12,6 +12,7 @@ import {AppDispatch} from './hooks';
import {createWalletAddress} from '../store/wallet/effects/address/address';
import {SUPPORTED_EVM_COINS} from '../constants/currencies';
import {LogActions} from '../store/log';
import {createMultipleWallets} from '../store/wallet/effects';

export const suffixChainMap: {[suffix: string]: string} = {
eth: 'e',
Expand Down Expand Up @@ -581,3 +582,47 @@ export const fixWalletAddresses = async ({
}),
);
};

export const createWalletsForAccounts = async (
dispatch: any,
accountsArray: number[],
key: KeyMethods,
) => {
return (
await Promise.all(
accountsArray.flatMap(async account => {
try {
const newWallets = (await dispatch(
createMultipleWallets({
key: key as KeyMethods,
currencies: [],
options: {
account,
customAccount: true,
},
}),
)) as Wallet[];
return newWallets;
} catch (err) {
const errMsg =
err instanceof Error ? err.message : JSON.stringify(err);
dispatch(
LogActions.debug(
`Error creating wallet - continue anyway: ${errMsg}`,
),
);
}
}),
)
)
.flat()
.filter(Boolean) as Wallet[];
};

export const getEvmGasWallets = (wallets: Wallet[]) => {
return wallets.filter(
wallet =>
IsEVMChain(wallet.credentials.chain) &&
!IsERCToken(wallet.credentials.coin, wallet.credentials.chain),
);
};

0 comments on commit f5b3fd3

Please sign in to comment.