Skip to content

Commit

Permalink
fix: account discovery last used account index calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
peronczyk committed Oct 4, 2023
1 parent 9e04f7a commit 02665a8
Show file tree
Hide file tree
Showing 16 changed files with 51 additions and 48 deletions.
18 changes: 7 additions & 11 deletions src/composables/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
}
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/popup/components/AccountCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<AccountInfo
:account="account"
avatar-borderless
with-protocol-icon
show-protocol-icon
/>
</template>

Expand Down
2 changes: 1 addition & 1 deletion src/popup/components/AccountCardMultisig.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
:account="convertMultisigAccountToAccount(account)"
is-multisig
avatar-borderless
with-protocol-icon
show-protocol-icon
/>
</template>

Expand Down
2 changes: 1 addition & 1 deletion src/popup/components/AccountDetailsBase.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
v-else
:account="activeAccount"
can-copy-address
with-protocol-icon
show-protocol-icon
/>
<BtnClose
class="close-button"
Expand Down
13 changes: 4 additions & 9 deletions src/popup/components/AccountInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@
v-if="account.address?.length"
class="account-address"
>
<IconWrapper
v-if="withProtocolIcon"
:protocol-icon="account.protocol"
class="protocol-icon"
/>
<CopyText
data-cy="copy"
:value="account.address"
Expand All @@ -48,6 +43,7 @@
<AddressTruncated
:address="account.address"
:protocol="account.protocol"
:show-protocol-icon="showProtocolIcon"
class="ae-address"
/>
</CopyText>
Expand All @@ -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,
Expand All @@ -88,7 +82,7 @@ export default defineComponent({
isMultisig: Boolean,
avatarBorderless: Boolean,
isListName: Boolean,
withProtocolIcon: Boolean,
showProtocolIcon: Boolean,
},
setup(props) {
const store = useStore();
Expand Down Expand Up @@ -155,7 +149,6 @@ export default defineComponent({
.ae-address {
color: rgba(variables.$color-white, 0.85);
opacity: 0.85;
user-select: none;
.icon {
Expand All @@ -178,6 +171,8 @@ export default defineComponent({
&.can-copy-address {
.ae-address {
opacity: 0.85;
&:hover {
opacity: 1;
}
Expand Down
1 change: 0 additions & 1 deletion src/popup/components/AccountItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
v-else
class="address"
:address="address"
:protocol="protocol"
/>

<template #icon>
Expand Down
21 changes: 15 additions & 6 deletions src/popup/components/AccountSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
:avatar="avatarOnly"
:model-value="modelValue"
:options="options || accountsSelectOptions"
unstyled
:hide-arrow="avatarOnly"
:default-text="$t('modals.createMultisigAccount.selectAccount')"
account-select
unstyled
@update:modelValue="$emit('update:modelValue', $event)"
>
<template #current-text="{ text }">
Expand All @@ -41,16 +41,16 @@
<AddressTruncated
v-if="!avatarOnly"
show-explorer-link
show-protocol-icon
:address="modelValue.toString()"
:protocol="selectedAccount?.protocol"
class="address-truncated"
/>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue';
import { computed, defineComponent, PropType } from 'vue';
import type { IFormSelectOption } from '@/types';
import { useAccounts } from '@/composables';
Expand All @@ -77,10 +77,19 @@ export default defineComponent({
avatarOnly: Boolean,
},
emits: ['update:modelValue'],
setup() {
const { accountsSelectOptions } = useAccounts();
setup(props) {
const { accountsSelectOptions, getAccountByAddress } = useAccounts();
return { accountsSelectOptions };
const selectedAccount = computed(
() => (props.modelValue)
// TODO remove any after changing the address type to string
? getAccountByAddress(props.modelValue as any)
: undefined,
);
return {
accountsSelectOptions,
selectedAccount,
};
},
});
</script>
Expand Down
2 changes: 1 addition & 1 deletion src/popup/components/Modals/MultisigVaultCreate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
v-model.trim="signer.address"
:default-text="$t('modals.createMultisigAccount.signerInputPlaceholder')"
:label="getSignerLabel(index)"
item-title="address"
:options="aeAccountsSelectOptions"
item-title="value"
account-select
/>
<Field
Expand Down
2 changes: 1 addition & 1 deletion src/popup/pages/AccountDetailsMultisig.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<AccountInfo
:account="convertMultisigAccountToAccount(activeMultisigAccount)"
is-multisig
with-protocol-icon
show-protocol-icon
can-copy-address
/>
</template>
Expand Down
2 changes: 1 addition & 1 deletion src/popup/pages/Invite.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<AccountInfo
:account="activeAccount"
can-copy-address
with-protocol-icon
show-protocol-icon
/>
<BalanceInfo
:balance="balance.toNumber()"
Expand Down
7 changes: 5 additions & 2 deletions src/popup/pages/SeedPhraseVerifySettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ import { useStore } from 'vuex';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { IonPage, IonContent } from '@ionic/vue';
import { ROUTE_ACCOUNT } from '../router/routeNames';
import { useAccounts } from '@/composables';
import { ROUTE_ACCOUNT } from '@/popup/router/routeNames';
import BtnMain from '../components/buttons/BtnMain.vue';
import FixedScreenFooter from '../components/FixedScreenFooter.vue';
import SeedPhraseNotification from '../components/SeedPhraseNotification.vue';
Expand All @@ -101,12 +103,13 @@ export default defineComponent({
const router = useRouter();
const { t } = useI18n();
const { mnemonic } = useAccounts();
const selectedWordIds = ref<number[]>([]);
const showNotification = ref<boolean>(false);
const hasError = ref<boolean>(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() {
Expand Down
4 changes: 2 additions & 2 deletions src/protocols/BaseProtocolAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<number>;
abstract discoverLastUsedAccountIndex(seed: Uint8Array): Promise<number>;

abstract constructAndSignTx(
amount: number,
Expand Down
10 changes: 5 additions & 5 deletions src/protocols/aeternity/libs/AeternityAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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<number> {
const accountNumber = await defaultAccountDiscovery(
override async discoverLastUsedAccountIndex(seed: Uint8Array): Promise<number> {
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() {
Expand Down
6 changes: 3 additions & 3 deletions src/protocols/bitcoin/libs/BitcoinAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import {
BTC_SYMBOL,
} from '@/protocols/bitcoin/config';
import {
defaultAccountDiscovery,
getLastNotEmptyAccountIndex,
fetchJson,
} from '@/utils';
import { normalizeTransactionStructure } from '@/protocols/bitcoin/helpers';
Expand Down Expand Up @@ -153,8 +153,8 @@ export class BitcoinAdapter extends BaseProtocolAdapter {
};
}

override async discoverAccounts(seed: Uint8Array): Promise<number> {
return defaultAccountDiscovery(
override async discoverLastUsedAccountIndex(seed: Uint8Array): Promise<number> {
return getLastNotEmptyAccountIndex(
this.isAccountUsed,
this.getHdWalletAccountFromMnemonicSeed.bind(this),
seed,
Expand Down
5 changes: 4 additions & 1 deletion src/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,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<boolean>,
getHdWalletAccountFromMnemonicSeed: (
seed: Uint8Array,
Expand Down
2 changes: 0 additions & 2 deletions tests/unit/import-account.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import AccountImport from '../../src/popup/components/Modals/AccountImport.vue';

jest.mock('vuex', () => ({
useStore: jest.fn(() => ({
state: {},
getters: {},
commit: jest.fn(),
})),
}));
Expand Down

0 comments on commit 02665a8

Please sign in to comment.