Skip to content

Commit

Permalink
feat(wallet): Add main badge to accounts with the 0/0/0 derivation …
Browse files Browse the repository at this point in the history
…path (#2664)

* feat(explorer): bip path main label.

Signed-off-by: Eugene Panteleymonchuk <[email protected]>

* feat(explorer): add badge "main" to manage accounts.

Signed-off-by: Eugene Panteleymonchuk <[email protected]>

* feat(explorer): update badgeConfig variable;

Signed-off-by: Eugene Panteleymonchuk <[email protected]>

---------

Signed-off-by: Eugene Panteleymonchuk <[email protected]>
Co-authored-by: Bran <[email protected]>
Co-authored-by: Begoña Álvarez de la Cruz <[email protected]>
  • Loading branch information
3 people authored Sep 19, 2024
1 parent 0220d2b commit 7321872
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 2 deletions.
20 changes: 20 additions & 0 deletions apps/wallet/src/background/account-sources/bip44Path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,23 @@ export function makeDerivationPath({
// currently returns only Ed25519 path
return `m/44'/${bip44CoinType}'/${accountIndex}'/${changeIndex}'/${addressIndex}'`;
}

/**
* Parses a derivation path string and returns its components.
*
* @param path - The derivation path string (e.g., "m/44'/4218'/0'/0'/0'")
* @returns An object containing bip44CoinType, accountIndex, changeIndex, and addressIndex
*/
export function parseDerivationPath(path: string): MakeDerivationOptions {
const parts = path
.split("'/")
.slice(1)
.map((part) => parseInt(part, 10));

return {
bip44CoinType: parts[0],
accountIndex: parts[1],
changeIndex: parts[2],
addressIndex: parts[3],
};
}
28 changes: 28 additions & 0 deletions apps/wallet/src/background/accounts/isMainAccount.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { isLedgerAccountSerializedUI } from '_src/background/accounts/LedgerAccount';
import { isMnemonicSerializedUiAccount } from '_src/background/accounts/MnemonicAccount';
import { isSeedSerializedUiAccount } from '_src/background/accounts/SeedAccount';
import { parseDerivationPath } from '_src/background/account-sources/bip44Path';
import type { SerializedUIAccount } from '_src/background/accounts/Account';

export function isMainAccount(account: SerializedUIAccount | null) {
{
if (!account) {
return false;
}

if (
isLedgerAccountSerializedUI(account) ||
isMnemonicSerializedUiAccount(account) ||
isSeedSerializedUiAccount(account)
) {
const { addressIndex, changeIndex, accountIndex } = parseDerivationPath(
account.derivationPath,
);

return addressIndex === 0 && changeIndex === 0 && accountIndex === 0;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import { useNavigate } from 'react-router-dom';
import { useAccounts } from '_app/hooks/useAccounts';
import { useExplorerLink } from '_app/hooks/useExplorerLink';
import toast from 'react-hot-toast';
import { Account, Dropdown, ListItem } from '@iota/apps-ui-kit';
import { Account, BadgeType, Dropdown, ListItem } from '@iota/apps-ui-kit';
import { OutsideClickHandler } from '_components/OutsideClickHandler';
import { IotaLogoMark, Ledger } from '@iota/ui-icons';
import { RemoveDialog } from './RemoveDialog';
import { useBackgroundClient } from '_app/hooks/useBackgroundClient';
import { isMainAccount } from '_src/background/accounts/isMainAccount';

interface AccountGroupItemProps {
account: SerializedUIAccount;
Expand Down Expand Up @@ -83,6 +84,18 @@ export function AccountGroupItem({ account, isLast }: AccountGroupItemProps) {
setDropdownOpen(true);
}

const isMain = isMainAccount(account);

const badgeConfig = isMain
? {
type: BadgeType.PrimarySoft,
text: 'Main',
}
: {
type: undefined,
text: undefined,
};

return (
<div className="relative overflow-visible [&_span]:whitespace-nowrap">
<div onClick={handleSelectAccount}>
Expand All @@ -94,6 +107,8 @@ export function AccountGroupItem({ account, isLast }: AccountGroupItemProps) {
onOpen={handleOpen}
avatarContent={() => <AccountAvatar account={account} />}
title={accountName}
badgeType={badgeConfig.type}
badgeText={badgeConfig.text}
subtitle={formatAddress(account.address)}
onCopy={handleCopySuccess}
onOptionsClick={handleOptionsClick}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

import { ErrorBoundary, MenuContent, Navigation, WalletSettingsButton } from '_components';
import cn from 'clsx';
import { createContext, useState, type ReactNode } from 'react';
import { BadgeType, Badge } from '@iota/apps-ui-kit';
import { createContext, type ReactNode, useState } from 'react';
import { useAppSelector } from '../../hooks';
import { AppType } from '../../redux/slices/app/AppType';
import DappStatus from '../dapp-status';
Expand All @@ -16,6 +17,7 @@ import { Link } from 'react-router-dom';
import { formatAddress } from '@iota/iota-sdk/utils';
import { isLedgerAccountSerializedUI } from '_src/background/accounts/LedgerAccount';
import { type SerializedUIAccount } from '_src/background/accounts/Account';
import { isMainAccount } from '_src/background/accounts/isMainAccount';

export const PageMainLayoutContext = createContext<HTMLDivElement | null>(null);

Expand Down Expand Up @@ -93,6 +95,8 @@ function LeftContent({
isLedgerAccount: boolean | null;
isLocked?: boolean;
}) {
const isMain = isMainAccount(account);

const accountName = account?.nickname ?? formatAddress(account?.address || '');
const backgroundColor = isLocked ? 'bg-neutral-90' : 'bg-primary-30';
return (
Expand All @@ -109,6 +113,7 @@ function LeftContent({
{isLedgerAccount ? <Ledger /> : <IotaLogoMark />}
</div>
<span className="text-title-sm text-neutral-10">{accountName}</span>
{isMain && <Badge type={BadgeType.PrimarySoft} label="Main" />}
</Link>
);
}

0 comments on commit 7321872

Please sign in to comment.