Skip to content

Commit

Permalink
feat: CP-9309 account and wallet renaming (#71)
Browse files Browse the repository at this point in the history
  • Loading branch information
vvava authored Oct 28, 2024
1 parent 68a849c commit 996cdd0
Show file tree
Hide file tree
Showing 29 changed files with 898 additions and 227 deletions.
1 change: 1 addition & 0 deletions src/background/connections/dAppConnection/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export enum DAppProviderRequest {
AVALANCHE_SIGN_TRANSACTION = 'avalanche_signTransaction',
AVALANCHE_SIGN_MESSAGE = 'avalanche_signMessage',
BITCOIN_SEND_TRANSACTION = 'bitcoin_sendTransaction',
WALLET_RENAME = 'avalanche_renameWallet',
}

export enum Web3Event {
Expand Down
2 changes: 2 additions & 0 deletions src/background/connections/dAppConnection/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { AvalancheGetAddressesInRangeHandler } from '@src/background/services/ac
import { AvalancheSignTransactionHandler } from '@src/background/services/wallet/handlers/avalanche_signTransaction';
import { AvalancheSignMessageHandler } from '@src/background/services/messages/handlers/avalanche_signMessage';
import { AvalancheRenameAccountHandler } from '@src/background/services/accounts/handlers/avalanche_renameAccount';
import { AvalancheRenameWalletHandler } from '@src/background/services/secrets/handlers/avalanche_renameWallet';

/**
* TODO: GENERATE THIS FILE AS PART OF THE BUILD PROCESS
Expand Down Expand Up @@ -70,6 +71,7 @@ import { AvalancheRenameAccountHandler } from '@src/background/services/accounts
{ token: 'DAppRequestHandler', useToken: WalletWatchAssetHandler },
{ token: 'DAppRequestHandler', useToken: ConnectRequestHandler },
{ token: 'DAppRequestHandler', useToken: AvalancheGetProviderState },
{ token: 'DAppRequestHandler', useToken: AvalancheRenameWalletHandler },
{
token: 'DAppRequestHandler',
useToken: AvalancheSendDomainMetadataHandler,
Expand Down
2 changes: 1 addition & 1 deletion src/background/connections/extensionConnection/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ import { KeystoneRequestEvents } from '@src/background/services/keystone/events/
import { SubmitKeystoneSignature } from '@src/background/services/keystone/handlers/keystoneSubmitSignature';
import { StoreBtcWalletPolicyDetails } from '@src/background/services/wallet/handlers/storeBtcWalletPolicyDetails';
import { GetBtcWalletPolicyDetails } from '@src/background/services/wallet/handlers/getBtcWalletPolicyDetails';
import { WalletUpdatedEvents } from '@src/background/services/wallet/events/WalletUpdatedEvent';
import { WalletUpdatedEvents } from '@src/background/services/secrets/events/WalletUpdatedEvent';
import { GetDefiPortfolioHandler } from '@src/background/services/defi/handlers/getDefiPortfolio';
import { CurrencyRatesUpdatedEvents } from '@src/background/services/currency/events/currencyRatesUpdatedEvent';
import { GetCurrencyExchangeRatesHandler } from '@src/background/services/currency/handlers/getCurrencyExchangeRates';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ const CORE_METHODS = Object.freeze([
DAppProviderRequest.AVALANCHE_GET_ACCOUNT_PUB_KEY,
DAppProviderRequest.BITCOIN_SEND_TRANSACTION,
DAppProviderRequest.WALLET_GET_CHAIN,
DAppProviderRequest.WALLET_RENAME,
]);

export function PermissionMiddleware(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { AccountType } from '../models';
import { AvalancheGetAccountsHandler } from './avalanche_getAccounts';
import { SecretType } from '../../secrets/models';
import { buildRpcCall } from '@src/tests/test-utils';
import { SecretsService } from '../../secrets/SecretsService';

const walletName = 'Wallet-Name-001';
describe('background/services/accounts/handlers/avalanche_getAccounts.ts', () => {
Expand Down Expand Up @@ -36,28 +37,26 @@ describe('background/services/accounts/handlers/avalanche_getAccounts.ts', () =>
activeAccount: accounts[0],
} as any;

const walletServiceMock = {
wallets: [
{
type: SecretType.Mnemonic,
name: walletName,
},
],
} as any;

const secretsService = new SecretsService({} as any);
const request = {
id: '123',
method: DAppProviderRequest.AVALANCHE_GET_ACCOUNTS,
} as const;

beforeEach(() => {
jest.resetAllMocks();
secretsService.getPrimaryWalletsDetails = jest.fn().mockResolvedValue([
{
type: SecretType.Mnemonic,
name: walletName,
},
]);
});

it('handleAuthenticated', async () => {
const handler = new AvalancheGetAccountsHandler(
accountServiceMock,
walletServiceMock
secretsService
);
const result = await handler.handleAuthenticated(buildRpcCall(request));

Expand Down Expand Up @@ -101,7 +100,7 @@ describe('background/services/accounts/handlers/avalanche_getAccounts.ts', () =>
it('handleUnauthenticated', async () => {
const handler = new AvalancheGetAccountsHandler(
accountServiceMock,
walletServiceMock
secretsService
);
const result = await handler.handleUnauthenticated(buildRpcCall(request));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,27 @@ import { DAppProviderRequest } from '@src/background/connections/dAppConnection/
import { injectable } from 'tsyringe';
import { AccountsService } from '../AccountsService';
import { Account, AccountType } from '../models';
import { WalletService } from '../../wallet/WalletService';
import { SecretsService } from '../../secrets/SecretsService';

@injectable()
export class AvalancheGetAccountsHandler extends DAppRequestHandler {
methods = [DAppProviderRequest.AVALANCHE_GET_ACCOUNTS];

constructor(
private accountsService: AccountsService,
private walletService: WalletService
private secretsService: SecretsService
) {
super();
}

handleAuthenticated = async ({ request }) => {
const accounts = this.accountsService.getAccountList();
const activeAccount = this.accountsService.activeAccount;
const wallets = await this.secretsService.getPrimaryWalletsDetails();

const getWalletData = (acc: Account) => {
if (acc.type === AccountType.PRIMARY) {
const walletData = this.walletService.wallets.find((wallet) => {
const walletData = wallets.find((wallet) => {
return wallet.id === acc.walletId;
});
return {
Expand Down
41 changes: 30 additions & 11 deletions src/background/services/messages/handlers/signMessage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ describe('src/background/services/messages/handlers/signMessage.ts', () => {
let networkServiceMock;

let blockaidServiceMock;
let secretsServiceMock;

beforeEach(() => {
jest.resetAllMocks();
Expand All @@ -55,6 +56,14 @@ describe('src/background/services/messages/handlers/signMessage.ts', () => {
getNetwork: () => activeNetworkMock,
} as any;

secretsServiceMock = {
getPrimaryWalletsDetails: jest.fn().mockResolvedValue([
{
type: SecretType.Mnemonic,
},
]),
};

jest.mocked(openApprovalWindow).mockResolvedValue({} as any);
(paramsToMessageParams as jest.Mock).mockReturnValue(displayDataMock);
});
Expand All @@ -63,7 +72,8 @@ describe('src/background/services/messages/handlers/signMessage.ts', () => {
const handler = new PersonalSignHandler(
walletServiceMock,
networkServiceMock,
blockaidServiceMock
blockaidServiceMock,
secretsServiceMock
);

const request = {
Expand All @@ -85,7 +95,8 @@ describe('src/background/services/messages/handlers/signMessage.ts', () => {
const handler = new PersonalSignHandler(
walletServiceMock,
networkServiceMock,
blockaidServiceMock
blockaidServiceMock,
secretsServiceMock
);

expect(handler.methods).toStrictEqual([
Expand All @@ -100,11 +111,12 @@ describe('src/background/services/messages/handlers/signMessage.ts', () => {

describe('handleAuthenticated', () => {
it('throws if walletType is undefined', async () => {
walletServiceMock.wallets = [];
secretsServiceMock.getPrimaryWalletsDetails.mockResolvedValueOnce([]);
const handler = new PersonalSignHandler(
walletServiceMock,
networkServiceMock,
blockaidServiceMock
blockaidServiceMock,
secretsServiceMock
);

const request = {
Expand All @@ -128,7 +140,8 @@ describe('src/background/services/messages/handlers/signMessage.ts', () => {
const handler = new PersonalSignHandler(
walletServiceMock,
networkServiceMock,
blockaidServiceMock
blockaidServiceMock,
secretsServiceMock
);

const request = {
Expand All @@ -154,7 +167,8 @@ describe('src/background/services/messages/handlers/signMessage.ts', () => {
const handler = new PersonalSignHandler(
walletServiceMock,
networkServiceMock,
blockaidServiceMock
blockaidServiceMock,
secretsServiceMock
);

const request = {
Expand Down Expand Up @@ -190,7 +204,8 @@ describe('src/background/services/messages/handlers/signMessage.ts', () => {
const handler = new PersonalSignHandler(
walletServiceMock,
networkServiceMock,
blockaidServiceMock
blockaidServiceMock,
secretsServiceMock
);

const methodsWithoutTypeCheck = [
Expand Down Expand Up @@ -245,7 +260,8 @@ describe('src/background/services/messages/handlers/signMessage.ts', () => {
const handler = new PersonalSignHandler(
walletServiceMock,
networkServiceMock,
blockaidServiceMock
blockaidServiceMock,
secretsServiceMock
);

const messageParamsMock: MessageParams = {
Expand Down Expand Up @@ -325,7 +341,8 @@ describe('src/background/services/messages/handlers/signMessage.ts', () => {
const handler = new PersonalSignHandler(
walletServiceMock,
networkServiceMock,
blockaidServiceMock
blockaidServiceMock,
secretsServiceMock
);

const request = {
Expand Down Expand Up @@ -379,7 +396,8 @@ describe('src/background/services/messages/handlers/signMessage.ts', () => {
const handler = new PersonalSignHandler(
walletServiceMock,
networkServiceMock,
blockaidServiceMock
blockaidServiceMock,
secretsServiceMock
);

(walletServiceMock.signMessage as jest.Mock).mockResolvedValueOnce(
Expand All @@ -406,7 +424,8 @@ describe('src/background/services/messages/handlers/signMessage.ts', () => {
const handler = new PersonalSignHandler(
walletServiceMock,
networkServiceMock,
blockaidServiceMock
blockaidServiceMock,
secretsServiceMock
);

(walletServiceMock.signMessage as jest.Mock).mockRejectedValueOnce(error);
Expand Down
7 changes: 5 additions & 2 deletions src/background/services/messages/handlers/signMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { TypedDataEncoder } from 'ethers';
import { openApprovalWindow } from '@src/background/runtime/openApprovalWindow';
import { BlockaidService } from '../../blockaid/BlockaidService';
import { getValidationResultType } from '../../blockaid/utils';
import { SecretsService } from '../../secrets/SecretsService';

@injectable()
export class PersonalSignHandler extends DAppRequestHandler {
Expand All @@ -28,7 +29,8 @@ export class PersonalSignHandler extends DAppRequestHandler {
constructor(
private walletService: WalletService,
private networkService: NetworkService,
private blockaidService: BlockaidService
private blockaidService: BlockaidService,
private secretsService: SecretsService
) {
super();
}
Expand All @@ -41,7 +43,8 @@ export class PersonalSignHandler extends DAppRequestHandler {
};

handleAuthenticated = async ({ request, scope }) => {
if (this.walletService.wallets.length === 0) {
const wallets = await this.secretsService.getPrimaryWalletsDetails();
if (wallets.length === 0) {
return {
...request,
error: 'wallet undefined',
Expand Down
49 changes: 46 additions & 3 deletions src/background/services/secrets/SecretsService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
} from '../accounts/models';
import { NetworkService } from '../network/NetworkService';
import { StorageService } from '../storage/StorageService';
import { PubKeyType, WALLET_STORAGE_KEY } from '../wallet/models';
import { PubKeyType, WALLET_STORAGE_KEY, WalletEvents } from '../wallet/models';
import { SecretType } from './models';
import { SecretsService } from './SecretsService';
import { WalletConnectService } from '../walletConnect/WalletConnectService';
Expand Down Expand Up @@ -253,6 +253,35 @@ describe('src/background/services/secrets/SecretsService.ts', () => {
return data;
};

describe('onUnlock', () => {
it('should emit the `WALLET_STATE_UPDATE` event with an empty array', async () => {
const eventListener = jest.fn();
secretsService.addListener(
WalletEvents.WALLET_STATE_UPDATE,
eventListener
);
await secretsService.onUnlock();
expect(eventListener).toHaveBeenCalledWith([]);
});
it('should emit the `WALLET_STATE_UPDATE` event with the correct data', async () => {
mockMnemonicWallet();
const eventListener = jest.fn();
secretsService.addListener(
WalletEvents.WALLET_STATE_UPDATE,
eventListener
);
await secretsService.onUnlock();
expect(eventListener).toHaveBeenCalledWith([
{
derivationPath: DerivationPath.BIP44,
id: ACTIVE_WALLET_ID,
name: undefined,
type: SecretType.Mnemonic,
},
]);
});
});

describe('getPrimaryAccountSecrets', () => {
it('returns null if no secrets are saved', async () => {
storageService.load.mockResolvedValue(null);
Expand Down Expand Up @@ -293,7 +322,13 @@ describe('src/background/services/secrets/SecretsService.ts', () => {
});

describe('addSecrets()', () => {
it('should save a new wallet to the `wallets` array', async () => {
it('should save a new wallet to the `wallets` array and emits the `WALLET_STATE_UPDATE` event', async () => {
const eventListener = jest.fn();
secretsService.addListener(
WalletEvents.WALLET_STATE_UPDATE,
eventListener
);

const uuid = 'uuid';
(crypto.randomUUID as jest.Mock).mockReturnValueOnce(uuid);
const existingWallets = [
Expand Down Expand Up @@ -329,6 +364,7 @@ describe('src/background/services/secrets/SecretsService.ts', () => {
},
],
});
expect(eventListener).toHaveBeenCalled();
});

it('should save a new wallet to the `wallets` array with default name when name is missing', async () => {
Expand Down Expand Up @@ -405,7 +441,12 @@ describe('src/background/services/secrets/SecretsService.ts', () => {
});

describe('updateSecrets', () => {
it('does not implicitly remove existing secrets in storage', async () => {
it('does not implicitly remove existing secrets in storage and emit `WALLET_STATE_UPDATE` event', async () => {
const eventListener = jest.fn();
secretsService.addListener(
WalletEvents.WALLET_STATE_UPDATE,
eventListener
);
const existingSecrets = {
xpub: 'xpub',
wallets: [
Expand All @@ -425,6 +466,8 @@ describe('src/background/services/secrets/SecretsService.ts', () => {
...existingSecrets,
wallets: [{ ...existingSecrets.wallets[0], xpubXP: 'xpubXP' }],
});

expect(eventListener).toHaveBeenCalled();
});
});

Expand Down
Loading

0 comments on commit 996cdd0

Please sign in to comment.