{Object.values(accountTypeAccounts)
- .filter((account) => account.xpub !== '')
+ .filter((account) => account.address.startsWith('0x'))
.map((account, index) => (
{
+ onClick={async () => {
if (
(account.isTrezorWallet &&
account?.originNetwork?.isBitcoinBased) ||
@@ -228,7 +274,7 @@ const RenderAccountsListByBitcoinBased = (
) {
return;
}
- setActiveAccount(
+ await setActiveAccount(
account.id,
keyringAccountType as KeyringAccountType
);
@@ -245,27 +291,29 @@ const RenderAccountsListByBitcoinBased = (
className="w-full flex items-center justify-start whitespace-nowrap overflow-hidden"
>
{account.isImported ? (
-
+
) : account.isTrezorWallet ? (
+ />
) : account.isLedgerWallet ? (
+ />
) : (
-
+
)}{' '}
{account.label}{' '}
{!(
@@ -328,8 +376,6 @@ export const AccountMenu: React.FC = () => {
await controllerEmitter(['wallet', 'setAccount'], [Number(id), type]);
};
- const cursorType = isBitcoinBased ? 'cursor-not-allowed' : 'cursor-pointer';
-
return (
@@ -394,27 +440,13 @@ export const AccountMenu: React.FC = () => {
{
- isBitcoinBased ? null : navigate('/settings/account/import');
- }}
- className={`py-1.5 ${cursorType} px-6 w-full backface-visibility-hidden flex items-center justify-start gap-3 text-white text-sm font-medium active:bg-opacity-40 focus:outline-none`}
+ onClick={() => navigate('/settings/account/import')}
+ className={`py-1.5 cursor-pointer px-6 w-full backface-visibility-hidden flex items-center justify-start gap-3 text-white text-sm font-medium active:bg-opacity-40 focus:outline-none`}
>
-
-
-
- {t('accountMenu.importAccount')}
-
+
+
+ {t('accountMenu.importAccount')}
- {isBitcoinBased && (
-
- {t('accountMenu.importAccMessage')}
-
- )}
diff --git a/source/components/Header/Menus/NetworkMenu.tsx b/source/components/Header/Menus/NetworkMenu.tsx
index ef009acd0..4467cec5d 100644
--- a/source/components/Header/Menus/NetworkMenu.tsx
+++ b/source/components/Header/Menus/NetworkMenu.tsx
@@ -193,7 +193,7 @@ export const NetworkMenu: React.FC = (
- {!activeAccount.isImported ? (
+ {isBitcoinBased || !activeAccount.isImported ? (
<>
@@ -272,71 +272,77 @@ export const NetworkMenu: React.FC = (
) : null}
-
-
- {({ open }) => (
- <>
-
-
-
-
- {t('networkMenu.evmNetworks')}
-
-
-
-
-
-
- {Object.values(networks.ethereum)
- .sort(customSort)
-
- .map((currentNetwork: any, index: number, arr) => (
-
- handleChangeNetwork(
- currentNetwork,
- 'ethereum'
- )
- }
- >
-
- {currentNetwork.label}
-
-
- {!isBitcoinBased &&
- activeNetworkValidator(currentNetwork) && (
-
- )}
-
-
- ))}
-
- >
- )}
-
-
+ {activeAccount.isImported && isBitcoinBased ? null : (
+
+
+ {({ open }) => (
+ <>
+
+
+
+
+ {t('networkMenu.evmNetworks')}
+
+
+
+
+
+
+ {Object.values(networks.ethereum)
+ .sort(customSort)
+
+ .map(
+ (currentNetwork: any, index: number, arr) => (
+
+ handleChangeNetwork(
+ currentNetwork,
+ 'ethereum'
+ )
+ }
+ >
+
+ {currentNetwork.label}
+
+
+ {!isBitcoinBased &&
+ activeNetworkValidator(
+ currentNetwork
+ ) && (
+
+ )}
+
+
+ )
+ )}
+
+ >
+ )}
+
+
+ )}
{t('networkMenu.networkSettings')}
diff --git a/source/pages/Connections/ChangeConnectedAccount.tsx b/source/pages/Connections/ChangeConnectedAccount.tsx
index 298c1640d..8550d79f5 100644
--- a/source/pages/Connections/ChangeConnectedAccount.tsx
+++ b/source/pages/Connections/ChangeConnectedAccount.tsx
@@ -19,8 +19,8 @@ export const ChangeConnectedAccount = () => {
//TODO: validate this
const { host, eventName, connectedAccount, accountType } = useQueryData();
- const handleConnectedAccount = () => {
- controllerEmitter(
+ const handleConnectedAccount = async () => {
+ await controllerEmitter(
['wallet', 'setAccount'],
[connectedAccount.id, accountType]
);
@@ -30,8 +30,8 @@ export const ChangeConnectedAccount = () => {
window.close();
};
- const handleActiveAccount = () => {
- controllerEmitter(
+ const handleActiveAccount = async () => {
+ await controllerEmitter(
['dapp', 'changeAccount'],
[host, activeAccount.id, activeAccount.type]
);
diff --git a/source/pages/Send/Confirm.tsx b/source/pages/Send/Confirm.tsx
index f0bbfcbc4..ee3ee7b5b 100755
--- a/source/pages/Send/Confirm.tsx
+++ b/source/pages/Send/Confirm.tsx
@@ -209,7 +209,6 @@ export const SendConfirm = () => {
'chainId',
'maxFeePerGas',
'maxPriorityFeePerGas',
- ,
]) as ITxState;
const value = ethers.utils.parseUnits(
diff --git a/source/pages/Settings/ImportAccount.tsx b/source/pages/Settings/ImportAccount.tsx
index 2fcc2c441..b64439ac1 100644
--- a/source/pages/Settings/ImportAccount.tsx
+++ b/source/pages/Settings/ImportAccount.tsx
@@ -15,14 +15,17 @@ const ImportAccountView = () => {
const { controllerEmitter } = useController();
const { navigate, alert } = useUtils();
const [form] = useForm();
+ const [validPrivateKey, setValidPrivateKey] = useState(false);
//* States
const [isAccountImported, setIsAccountImported] = useState(false);
const [isImporting, setIsImporting] = useState(false);
- const { accounts, activeAccount: activeAccountMeta } = useSelector(
- (state: RootState) => state.vault
- );
+ const {
+ accounts,
+ activeAccount: activeAccountMeta,
+ isBitcoinBased,
+ } = useSelector((state: RootState) => state.vault);
const activeAccount = accounts[activeAccountMeta.type][activeAccountMeta.id];
@@ -96,15 +99,14 @@ const ImportAccountView = () => {
className="md:w-full"
hasFeedback
rules={[
- {
- required: true,
- message: '',
- },
+ { required: true, message: '' },
() => ({
async validator(_, value) {
- if (validatePrivateKeyValue(value)) {
+ if (validatePrivateKeyValue(value, isBitcoinBased)) {
+ setValidPrivateKey(true);
return Promise.resolve();
}
+ setValidPrivateKey(false);
return Promise.reject();
},
}),
@@ -124,6 +126,7 @@ const ImportAccountView = () => {
loading={isImporting}
onClick={handleImportAccount}
fullWidth={true}
+ disabled={!validPrivateKey}
>
{t('buttons.import')}
diff --git a/source/scripts/Background/controllers/MainController.ts b/source/scripts/Background/controllers/MainController.ts
index acb77de0a..e53966a34 100644
--- a/source/scripts/Background/controllers/MainController.ts
+++ b/source/scripts/Background/controllers/MainController.ts
@@ -89,6 +89,12 @@ import {
import { validateAndManageUserTransactions } from './transactions/utils';
class MainController extends KeyringManager {
+ public account: {
+ eth: IEthAccountController;
+ sys: ISysAccountController;
+ };
+ public assets: IAssetsManager;
+ public transactions: ITransactionsManager;
private utilsController: IControllerUtils;
private assetsManager: IAssetsManager;
private nftsController: INftController;
@@ -96,13 +102,6 @@ class MainController extends KeyringManager {
private transactionsManager: ITransactionsManager;
private balancesManager: IBalancesManager;
private cancellablePromises: CancellablePromises;
- public account: {
- eth: IEthAccountController;
- sys: ISysAccountController;
- };
- public assets: IAssetsManager;
- public transactions: ITransactionsManager;
-
private currentPromise: {
cancel: () => void;
promise: Promise<{ chainId: string; networkVersion: number }>;
@@ -169,7 +168,23 @@ class MainController extends KeyringManager {
})
.catch((error) => console.error('Unlock', error));
+ const accounts = JSON.parse(
+ JSON.stringify(store.getState().vault.accounts)
+ );
+
+ // update xprv every time the wallet is unlocked
+ for (const type in accounts) {
+ for (const id in accounts[type]) {
+ accounts[type][id] = {
+ ...accounts[type][id],
+ xprv: this.wallet.accounts[type][id].xprv,
+ };
+ }
+ }
+
+ store.dispatch(setAccounts(accounts));
store.dispatch(setLastLogin());
+
return canLogin;
}
@@ -340,8 +355,9 @@ class MainController extends KeyringManager {
}
}
- this.setActiveAccount(id, type);
- store.dispatch(setActiveAccount({ id, type }));
+ this.setActiveAccount(id, type).then(() => {
+ store.dispatch(setActiveAccount({ id, type }));
+ });
}
public async setActiveNetwork(
@@ -662,8 +678,10 @@ class MainController extends KeyringManager {
}
public async importAccountFromPrivateKey(privKey: string, label?: string) {
- const { accounts } = store.getState().vault;
+ const { accounts, isBitcoinBased, activeAccount, activeNetwork } =
+ store.getState().vault;
const importedAccount = await this.importAccount(privKey, label);
+
const paliImp: IPaliAccount = {
...importedAccount,
assets: {
@@ -675,6 +693,7 @@ class MainController extends KeyringManager {
ethereum: {},
},
} as IPaliAccount;
+
store.dispatch(
setAccounts({
...accounts,
@@ -684,10 +703,25 @@ class MainController extends KeyringManager {
},
})
);
+
+ await this.setActiveAccount(paliImp.id, KeyringAccountType.Imported);
+
store.dispatch(
setActiveAccount({ id: paliImp.id, type: KeyringAccountType.Imported })
);
+ this.updateUserTransactionsState({
+ isPolling: false,
+ isBitcoinBased,
+ activeAccount,
+ activeNetwork,
+ });
+ this.updateAssetsFromCurrentAccount({
+ activeAccount,
+ activeNetwork,
+ isBitcoinBased,
+ });
+
return importedAccount;
}
@@ -718,6 +752,7 @@ class MainController extends KeyringManager {
ethereum: {},
},
} as IPaliAccount;
+
store.dispatch(
setAccounts({
...accounts,
@@ -727,7 +762,7 @@ class MainController extends KeyringManager {
},
})
);
- this.setActiveAccount(paliImp.id, KeyringAccountType.Trezor);
+ await this.setActiveAccount(paliImp.id, KeyringAccountType.Trezor);
store.dispatch(
setActiveAccount({ id: paliImp.id, type: KeyringAccountType.Trezor })
);
diff --git a/source/utils/validatePrivateKey.ts b/source/utils/validatePrivateKey.ts
index d626f77b3..c97d993b8 100644
--- a/source/utils/validatePrivateKey.ts
+++ b/source/utils/validatePrivateKey.ts
@@ -1,25 +1,27 @@
import { ethers } from 'ethers';
-export const validatePrivateKeyValue = (privKey: string) => {
- //Get 2 first characters to validate if starts with 0x or not
- const initialValue = privKey.slice(0, 2);
+import { getController } from 'scripts/Background';
- switch (initialValue) {
- case '0x':
- try {
- new ethers.Wallet(`${privKey}`);
- } catch (error) {
- return false;
- }
- return true;
-
- default:
- try {
- new ethers.Wallet(`0x${privKey}`);
- } catch (error) {
- return false;
- }
+export const validatePrivateKeyValue = (
+ privKey: string,
+ isBitcoinBased: boolean
+) => {
+ const mainController = getController();
+ const initialValue = privKey.match(/^(0x|zprv)/)?.[0];
+ if ([undefined, '0x'].includes(initialValue) && !isBitcoinBased) {
+ try {
+ new ethers.Wallet(initialValue === undefined ? `0x${privKey}` : privKey);
return true;
+ } catch (error) {
+ return false;
+ }
}
+
+ if (initialValue === 'zprv' && isBitcoinBased) {
+ const { isValid } = mainController.wallet.validateZprv(privKey);
+ return isValid;
+ }
+
+ return false;
};
diff --git a/yarn.lock b/yarn.lock
index aca32d21f..bbc055cdd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2379,10 +2379,10 @@
resolved "https://registry.yarnpkg.com/@pollum-io/sysweb3-core/-/sysweb3-core-1.0.27.tgz#2ecbf38c3b5f6821ec2bcc95472eed0a2f11cd10"
integrity sha512-HHW2ozdXCac2Xo0oUQgRk/sczBIGQCBvsqYBIwondipA3Rx4/jGC6Y9U/M4wpTi5wQ+ZD18DyEbKAVMXElGcbQ==
-"@pollum-io/sysweb3-keyring@^1.0.487":
- version "1.0.487"
- resolved "https://registry.yarnpkg.com/@pollum-io/sysweb3-keyring/-/sysweb3-keyring-1.0.487.tgz#832ec8809ede161db883930ee9c54eb9aace392f"
- integrity sha512-oBrRnJPWYwv0IcRRLheYk1+rvNIl8lCKkoW2Z+Nw7UadFOPwXsSsrzbByjc7rHKkVKM39a+iD63mZt1f/pSUQg==
+"@pollum-io/sysweb3-keyring@^1.0.488":
+ version "1.0.488"
+ resolved "https://registry.yarnpkg.com/@pollum-io/sysweb3-keyring/-/sysweb3-keyring-1.0.488.tgz#db90e2dff05128d7d01350ed64ad6bb747e656a9"
+ integrity sha512-7nc7fkuzbhDqn17LQiNkCZ3GCFDQ5asAhPOr5EiBLBCW6HlmPmln8Hy3EaxyvMKYoognSeZ3t9QdNLy4Uq6puw==
dependencies:
"@bitcoinerlab/descriptors" "^2.0.1"
"@bitcoinerlab/secp256k1" "^1.0.5"
@@ -2391,7 +2391,7 @@
"@ledgerhq/logs" "^6.10.1"
"@pollum-io/sysweb3-core" "^1.0.27"
"@pollum-io/sysweb3-network" "^1.0.95"
- "@pollum-io/sysweb3-utils" "^1.1.235"
+ "@pollum-io/sysweb3-utils" "^1.1.236"
"@trezor/connect-web" "^9.1.5"
"@trezor/connect-webextension" "^9.3.0"
"@trezor/utxo-lib" "^1.0.12"
@@ -2429,10 +2429,10 @@
ethers "^5.6.9"
web3 "^1.7.1"
-"@pollum-io/sysweb3-utils@^1.1.235":
- version "1.1.235"
- resolved "https://registry.yarnpkg.com/@pollum-io/sysweb3-utils/-/sysweb3-utils-1.1.235.tgz#9ae08757631b40a4e2e4fe3da13b14457137f9f4"
- integrity sha512-El0fvuZg1AQ/a/fb8dwEfLQwDuVPR8Xj12uVWC2hPal5HjAVH9fNDXyHwUWeblH9oUUUyR5bXjbbf5slVW3KgA==
+"@pollum-io/sysweb3-utils@^1.1.236":
+ version "1.1.236"
+ resolved "https://registry.yarnpkg.com/@pollum-io/sysweb3-utils/-/sysweb3-utils-1.1.236.tgz#512a8d34257e881a32e92ad5d24ed6f8b635a9a5"
+ integrity sha512-tqZdMdp1ffriQZ5HPwWI71489UZNAdLOACGcXbIbRRvvbX64HKlQFdav/+k9BzuKR7d12zFWmoUvOwHNkSW5OA==
dependencies:
"@ethersproject/contracts" "^5.6.2"
axios "^0.26.1"
@@ -13422,7 +13422,16 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0":
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -13500,7 +13509,7 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -13514,6 +13523,13 @@ strip-ansi@^3.0.0:
dependencies:
ansi-regex "^2.0.0"
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
strip-ansi@^7.0.1:
version "7.1.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
@@ -15030,7 +15046,7 @@ workerpool@6.2.1:
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343"
integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -15048,6 +15064,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"