diff --git a/src/composables/accounts.ts b/src/composables/accounts.ts index 42a23546c2..86ae963483 100644 --- a/src/composables/accounts.ts +++ b/src/composables/accounts.ts @@ -201,29 +201,25 @@ export function useAccounts() { isRestored, type: ACCOUNT_HD_WALLET, }); - const lastProtocolAccount = getLastProtocolAccount(protocol); - const idx: number = (lastProtocolAccount) ? lastProtocolAccount.idx : 0; - return idx; + return getLastProtocolAccount(protocol)?.idx || 0; } /** - * Establish how many accounts are present under the actual seed phrase in each of the protocols - * and collect the raw versions so they can be stored in the browser storage. + * Establish the last used account index under the actual seed phrase for each of the protocols + * and collect the raw accounts so they can be stored in the browser storage. */ async function discoverAccounts() { - const accountsToRecover: number[] = await Promise.all( + const lastUsedAccountIndexRegistry: number[] = await Promise.all( PROTOCOLS.map( (protocol) => ProtocolAdapterFactory .getAdapter(protocol) - .discoverAccounts(mnemonicSeed.value), + .discoverLastUsedAccountIndex(mnemonicSeed.value), ), ); PROTOCOLS.forEach((protocol, index) => { - if (accountsToRecover[index] > 0) { - for (let i = 0; i < accountsToRecover[index]; i += 1) { - addRawAccount({ isRestored: true, protocol }); - } + for (let i = 0; i <= lastUsedAccountIndexRegistry[index]; i += 1) { + addRawAccount({ isRestored: true, protocol }); } }); } diff --git a/src/popup/components/AccountCard.vue b/src/popup/components/AccountCard.vue index 84530fd8ea..0922a8fbfa 100644 --- a/src/popup/components/AccountCard.vue +++ b/src/popup/components/AccountCard.vue @@ -7,7 +7,7 @@ diff --git a/src/popup/components/AccountCardMultisig.vue b/src/popup/components/AccountCardMultisig.vue index c413a9a4cc..841f0bbdb4 100644 --- a/src/popup/components/AccountCardMultisig.vue +++ b/src/popup/components/AccountCardMultisig.vue @@ -5,7 +5,7 @@ :account="convertMultisigAccountToAccount(account)" is-multisig avatar-borderless - with-protocol-icon + show-protocol-icon /> diff --git a/src/popup/components/AccountDetailsBase.vue b/src/popup/components/AccountDetailsBase.vue index 3d9c405831..741008fae6 100644 --- a/src/popup/components/AccountDetailsBase.vue +++ b/src/popup/components/AccountDetailsBase.vue @@ -12,7 +12,7 @@ v-else :account="activeAccount" can-copy-address - with-protocol-icon + show-protocol-icon /> - @@ -71,11 +67,9 @@ import Avatar from './Avatar.vue'; import CopyText from './CopyText.vue'; import Truncate from './Truncate.vue'; import AddressTruncated from './AddressTruncated.vue'; -import IconWrapper from './IconWrapper.vue'; export default defineComponent({ components: { - IconWrapper, AddressTruncated, Avatar, Truncate, @@ -88,7 +82,7 @@ export default defineComponent({ isMultisig: Boolean, avatarBorderless: Boolean, isListName: Boolean, - withProtocolIcon: Boolean, + showProtocolIcon: Boolean, }, setup(props) { const store = useStore(); @@ -155,7 +149,6 @@ export default defineComponent({ .ae-address { color: rgba(variables.$color-white, 0.85); - opacity: 0.85; user-select: none; .icon { @@ -178,6 +171,8 @@ export default defineComponent({ &.can-copy-address { .ae-address { + opacity: 0.85; + &:hover { opacity: 1; } diff --git a/src/popup/components/AccountItem.vue b/src/popup/components/AccountItem.vue index 1497f52b38..c50f2c70cc 100644 --- a/src/popup/components/AccountItem.vue +++ b/src/popup/components/AccountItem.vue @@ -34,7 +34,6 @@ v-else class="address" :address="address" - :protocol="protocol" /> diff --git a/src/popup/pages/Invite.vue b/src/popup/pages/Invite.vue index 8daa5f3ff6..9a7bc47036 100644 --- a/src/popup/pages/Invite.vue +++ b/src/popup/pages/Invite.vue @@ -3,7 +3,7 @@ ([]); const showNotification = ref(false); const hasError = ref(false); const examplePhrase = ref([t('pages.seedPhrase.first'), t('pages.seedPhrase.second'), '...']); - const mnemonic = computed((): string => store.state.mnemonic); const mnemonicShuffled = computed((): string[] => shuffle(mnemonic.value.split(' '))); function verifyLastStep() { diff --git a/src/protocols/BaseProtocolAdapter.ts b/src/protocols/BaseProtocolAdapter.ts index c81d8990f9..d464427144 100644 --- a/src/protocols/BaseProtocolAdapter.ts +++ b/src/protocols/BaseProtocolAdapter.ts @@ -63,9 +63,9 @@ export abstract class BaseProtocolAdapter { /** * Discover accounts that have been used in the past * @param seed 12 word seed array buffer - * @returns total number of used accounts + * @returns index of the last account that has any history records (-1 means no accounts found) */ - abstract discoverAccounts(seed: Uint8Array): Promise; + abstract discoverLastUsedAccountIndex(seed: Uint8Array): Promise; abstract constructAndSignTx( amount: number, diff --git a/src/protocols/aeternity/libs/AeternityAdapter.ts b/src/protocols/aeternity/libs/AeternityAdapter.ts index c95bc3cd78..78947cc417 100644 --- a/src/protocols/aeternity/libs/AeternityAdapter.ts +++ b/src/protocols/aeternity/libs/AeternityAdapter.ts @@ -18,7 +18,7 @@ import { PROTOCOL_AETERNITY } from '@/constants'; import { useAeSdk } from '@/composables/aeSdk'; import { BaseProtocolAdapter } from '@/protocols/BaseProtocolAdapter'; import { tg } from '@/store/plugins/languages'; -import { defaultAccountDiscovery } from '@/utils'; +import { getLastNotEmptyAccountIndex } from '@/utils'; import type { AeNetworkProtocolSettings } from '@/protocols/aeternity/types'; import { @@ -159,15 +159,15 @@ export class AeternityAdapter extends BaseProtocolAdapter { } /** - * As the Aeternity protocol is the primary one we always return at least 1. + * As the Aeternity protocol is the primary one we always return at least index 0 (one account). */ - override async discoverAccounts(seed: Uint8Array): Promise { - const accountNumber = await defaultAccountDiscovery( + override async discoverLastUsedAccountIndex(seed: Uint8Array): Promise { + const index = await getLastNotEmptyAccountIndex( this.isAccountUsed.bind(this), this.getHdWalletAccountFromMnemonicSeed.bind(this), seed, ); - return (accountNumber > 0) ? accountNumber : 1; + return (index > -1) ? index : 0; } override async constructAndSignTx() { diff --git a/src/protocols/bitcoin/libs/BitcoinAdapter.ts b/src/protocols/bitcoin/libs/BitcoinAdapter.ts index 3acaf7787c..0cd8f88e15 100644 --- a/src/protocols/bitcoin/libs/BitcoinAdapter.ts +++ b/src/protocols/bitcoin/libs/BitcoinAdapter.ts @@ -34,7 +34,7 @@ import { BTC_SYMBOL, } from '@/protocols/bitcoin/config'; import { - defaultAccountDiscovery, + getLastNotEmptyAccountIndex, fetchJson, } from '@/utils'; import { normalizeTransactionStructure } from '@/protocols/bitcoin/helpers'; @@ -153,8 +153,8 @@ export class BitcoinAdapter extends BaseProtocolAdapter { }; } - override async discoverAccounts(seed: Uint8Array): Promise { - return defaultAccountDiscovery( + override async discoverLastUsedAccountIndex(seed: Uint8Array): Promise { + return getLastNotEmptyAccountIndex( this.isAccountUsed, this.getHdWalletAccountFromMnemonicSeed.bind(this), seed, diff --git a/src/utils/common.ts b/src/utils/common.ts index 4655f98438..c8279d264f 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -374,7 +374,10 @@ export function detectProtocolByOwner(network: string, address?: string) { return null; } -export async function defaultAccountDiscovery( +/** + * @returns {number} between -1 and n where -1 means there are no accounts found. + */ +export async function getLastNotEmptyAccountIndex( isAccountUsed: (address: string) => Promise, getHdWalletAccountFromMnemonicSeed: ( seed: Uint8Array, diff --git a/tests/unit/import-account.spec.js b/tests/unit/import-account.spec.js index 5afaa73438..3bb6b66bfa 100644 --- a/tests/unit/import-account.spec.js +++ b/tests/unit/import-account.spec.js @@ -4,8 +4,6 @@ import AccountImport from '../../src/popup/components/Modals/AccountImport.vue'; jest.mock('vuex', () => ({ useStore: jest.fn(() => ({ - state: {}, - getters: {}, commit: jest.fn(), })), }));