Skip to content

Commit

Permalink
chore(suite): refactor to new @suite-common/contacts package + use …
Browse files Browse the repository at this point in the history
…Connect for verify
  • Loading branch information
martykan committed Dec 11, 2024
1 parent 74ee006 commit c7c8023
Show file tree
Hide file tree
Showing 28 changed files with 188 additions and 115 deletions.
1 change: 0 additions & 1 deletion packages/suite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@
"@trezor/type-utils": "workspace:*",
"@trezor/urls": "workspace:*",
"@trezor/utils": "workspace:*",
"bitcoinjs-message": "^2.2.0",
"bs58check": "^4.0.0",
"date-fns": "^2.30.0",
"dropbox": "^10.34.0",
Expand Down
2 changes: 0 additions & 2 deletions packages/suite/src/actions/suite/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import * as METADATA_PASSWORDS from './metadataPasswordsConstants';
import * as DESKTOP_UPDATE from './desktopUpdateConstants';
import * as GUIDE from './guideConstants';
import * as PROTOCOL from './protocolConstants';
import * as CONTACTS from './contactsConstants';

export {
STORAGE,
Expand All @@ -25,5 +24,4 @@ export {
DESKTOP_UPDATE,
GUIDE,
PROTOCOL,
CONTACTS,
};
3 changes: 2 additions & 1 deletion packages/suite/src/actions/suite/storageActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import type { NetworkSymbol } from '@suite-common/wallet-config';
import type { FormState, RatesByTimestamps } from '@suite-common/wallet-types';
import { MetadataState } from '@suite-common/metadata-types';
import { DefinitionType, TokenManagementAction } from '@suite-common/token-definitions';
import { Contact } from '@suite-common/contacts';

import { db } from 'src/storage';
import {
serializeDiscovery,
serializeDevice,
serializeCoinjoinAccount,
} from 'src/utils/suite/storage';
import type { AppState, Contact, Dispatch, GetState, TrezorDevice } from 'src/types/suite';
import type { AppState, Dispatch, GetState, TrezorDevice } from 'src/types/suite';
import type { Account } from 'src/types/wallet';
import type { Trade } from 'src/types/wallet/coinmarketCommonTypes';
import type { PreloadStoreAction } from 'src/support/suite/preloadStore';
Expand Down
3 changes: 2 additions & 1 deletion packages/suite/src/middlewares/wallet/storageMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ import { findAccountDevice } from '@suite-common/wallet-utils';
import { analyticsActions } from '@suite-common/analytics';
import { tokenDefinitionsActions } from '@suite-common/token-definitions/src/tokenDefinitionsActions';
import { TokenManagementAction } from '@suite-common/token-definitions';
import { CONTACTS } from '@suite-common/contacts';

import { db } from 'src/storage';
import { WALLET_SETTINGS } from 'src/actions/settings/constants';
import * as walletSettingsActions from 'src/actions/settings/walletSettingsActions';
import { GRAPH, COINMARKET_COMMON, FORM_DRAFT } from 'src/actions/wallet/constants';
import * as COINJOIN from 'src/actions/wallet/constants/coinjoinConstants';
import * as storageActions from 'src/actions/suite/storageActions';
import { SUITE, METADATA, STORAGE, CONTACTS } from 'src/actions/suite/constants';
import { SUITE, METADATA, STORAGE } from 'src/actions/suite/constants';
import * as metadataActions from 'src/actions/suite/metadataActions';
import { serializeDiscovery } from 'src/utils/suite/storage';
import type { AppState, Action as SuiteAction, Dispatch } from 'src/types/suite';
Expand Down
45 changes: 0 additions & 45 deletions packages/suite/src/reducers/suite/contactsReducer.ts

This file was deleted.

3 changes: 2 additions & 1 deletion packages/suite/src/reducers/suite/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { prepareMessageSystemReducer } from '@suite-common/message-system';
import { notificationsReducer } from '@suite-common/toast-notifications';
import { logsSlice } from '@suite-common/logger';
import { prepareDeviceReducer } from '@suite-common/wallet-core';
import { prepareContactsReducer } from '@suite-common/contacts';

import { extraDependencies } from 'src/support/extraDependencies';

Expand All @@ -16,12 +17,12 @@ import metadata from './metadataReducer';
import desktopUpdate from './desktopUpdateReducer';
import guide from './guideReducer';
import protocol from './protocolReducer';
import contacts from './contactsReducer';

const analytics = prepareAnalyticsReducer(extraDependencies);
// Type annotation as workaround for type-check error "The inferred type of 'default' cannot be named..."
const messageSystem: Reducer = prepareMessageSystemReducer(extraDependencies);
const device = prepareDeviceReducer(extraDependencies);
const contacts = prepareContactsReducer(extraDependencies);

export default {
suite,
Expand Down
2 changes: 1 addition & 1 deletion packages/suite/src/storage/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import { NetworkSymbol } from '@suite-common/wallet-config';
import type { StorageUpdateMessage } from '@trezor/suite-storage';
import { AnalyticsState } from '@suite-common/analytics';
import { SimpleTokenStructure } from '@suite-common/token-definitions';
import { Contact } from '@suite-common/contacts';

import type { CoinjoinAccount, CoinjoinDebugSettings } from 'src/types/wallet/coinjoin';
import type { Account, Discovery, WalletAccountTransaction } from 'src/types/wallet';
import type { Trade } from 'src/types/wallet/coinmarketCommonTypes';
import type { MetadataState } from 'src/types/suite/metadata';
import type { SuiteState } from 'src/reducers/suite/suiteReducer';
import { Contact } from 'src/types/suite';

import { GraphData } from '../types/wallet/graph';

Expand Down
1 change: 1 addition & 0 deletions packages/suite/src/support/extraDependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export const extraDependencies: ExtraDependencies = {
}
},
storageLoadDiscovery: (_, { payload }: StorageLoadAction) => payload.discovery,
storageLoadContacts: (_, { payload }: StorageLoadAction) => payload.contacts,
addButtonRequestFirmware: (
state,
{
Expand Down
9 changes: 1 addition & 8 deletions packages/suite/src/types/suite/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { notificationsActions } from '@suite-common/toast-notifications';
import { messageSystemActions } from '@suite-common/message-system';
import { deviceAuthenticityActions } from '@suite-common/device-authenticity';
import type { Route } from '@suite-common/suite-types';
import { ContactsAction } from '@suite-common/contacts';

import type { RouterAction } from 'src/actions/suite/routerActions';
import type { AppState } from 'src/reducers/store';
Expand All @@ -25,7 +26,6 @@ import type { WalletAction } from 'src/types/wallet';
import type { BackupAction } from 'src/actions/backup/backupActions';
import type { RecoveryAction } from 'src/actions/recovery/recoveryActions';
import type { GuideAction } from 'src/actions/suite/guideActions';
import type { ContactsAction } from 'src/actions/suite/contactsActions';

// reexport
export type { ExtendedMessageDescriptor } from 'src/components/suite/Translation';
Expand Down Expand Up @@ -129,10 +129,3 @@ export enum DisplayMode {
PAGINATED_TEXT,
SINGLE_WRAPPED_TEXT,
}

export type Contact = {
address: string;
label: string;
signature: string;
deviceState: string;
};
3 changes: 1 addition & 2 deletions packages/suite/src/views/contacts/AddNewContactModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { selectDevice } from '@suite-common/wallet-core';
import { spacings } from '@trezor/theme';

import { useSelector } from '../../hooks/suite';
import { getDeviceState } from '../../reducers/suite/contactsReducer';
import { useAddContact } from './useAddContact';

type AddNewContactModalProps = {
Expand All @@ -14,7 +13,7 @@ type AddNewContactModalProps = {

export const AddNewContactModal = ({ onClose }: AddNewContactModalProps) => {
const device = useSelector(selectDevice);
const deviceState = device && getDeviceState(device);
const deviceState = device && !!device.state?.staticSessionId;

const [errorMessage, setErrorMessage] = useState<string | null>(null);
const [label, setLabel] = useState('');
Expand Down
3 changes: 1 addition & 2 deletions packages/suite/src/views/contacts/ContactList.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Contact } from '@suite-common/contacts';
import { Button, Card, Dropdown, Table, Text } from '@trezor/components';
import { spacings } from '@trezor/theme';

import { Contact } from '../../types/suite';

const ContactItem = ({
contact: { address, label, signature },
remove,
Expand Down
25 changes: 10 additions & 15 deletions packages/suite/src/views/contacts/index.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import { useState } from 'react';

import { verify } from 'bitcoinjs-message';

import TrezorConnect from '@trezor/connect';
import { Banner, Button, Row } from '@trezor/components';
import { selectDevice } from '@suite-common/wallet-core';
import { TrezorDevice } from '@suite-common/suite-types';
import { spacings } from '@trezor/theme';
import {
Contact,
contactsActions,
findContact,
selectContactsForDevice,
} from '@suite-common/contacts';

import { useDispatch, useSelector } from 'src/hooks/suite';
import { selectContactsForDevice } from 'src/reducers/suite/contactsReducer';
import * as contactsActions from 'src/actions/suite/contactsActions';
import { Contact } from 'src/types/suite';

import { SettingsLayout } from '../../components/settings';
import { AddNewContactModal } from './AddNewContactModal';
import { ContactList } from './ContactList';

const FindContactButton = ({ contacts }: { contacts: Contact[] }) => {
const findContact = () => {
const handleClick = async () => {
const address = prompt('Address signed by the recipient');
const signature = prompt('Signature from the recipient');

Expand All @@ -28,20 +29,13 @@ const FindContactButton = ({ contacts }: { contacts: Contact[] }) => {
return;
}

const contact = contacts.find(contact => {
try {
return verify(address, contact.address, signature);
} catch {
return false;
}
});

const contact = await findContact(contacts, address, signature);
if (contact) alert(`Address "${address}" was signed by your contact "${contact.label}"`);
else alert('Recipient not in your contacts');
};

return (
<Button variant="tertiary" onClick={findContact} icon="magnifyingGlass">
<Button variant="tertiary" onClick={handleClick} icon="magnifyingGlass">
Find contact
</Button>
);
Expand All @@ -59,6 +53,7 @@ const GetMyPubkeyButton = () => {
coin: 'test',
useEmptyPassphrase: device.useEmptyPassphrase,
showOnTrezor: false,
scriptType: 'SPENDADDRESS',
});
if (response.success) {
alert(`Your identity pubkey: ${response.payload.address}`);
Expand Down
4 changes: 2 additions & 2 deletions packages/suite/src/views/contacts/useAddContact.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import TrezorConnect from '@trezor/connect';
import { selectDevice } from '@suite-common/wallet-core';
import { contactsActions } from '@suite-common/contacts';
import { getDeviceState } from '@suite-common/contacts/src/redux/contactsReducer';

import { useDispatch, useSelector } from '../../hooks/suite';
import { getDeviceState } from '../../reducers/suite/contactsReducer';
import * as contactsActions from '../../actions/suite/contactsActions';

export const useAddContact = (onCloseModal: () => void, label: string, address: string) => {
const dispatch = useDispatch();
Expand Down
17 changes: 17 additions & 0 deletions suite-common/contacts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "@suite-common/contacts",
"version": "1.0.0",
"private": true,
"license": "See LICENSE.md in repo root",
"sideEffects": false,
"main": "src/index",
"scripts": {
"depcheck": "yarn g:depcheck",
"type-check": "yarn g:tsc --build"
},
"dependencies": {
"@reduxjs/toolkit": "1.9.5",
"@suite-common/suite-types": "workspace:*",
"@trezor/connect": "workspace:*"
}
}
2 changes: 2 additions & 0 deletions suite-common/contacts/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const ADD = '@contacts/add';
export const REMOVE = '@contacts/remove';
7 changes: 7 additions & 0 deletions suite-common/contacts/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export * as contactsActions from './redux/contactsActions';
export type { ContactsAction } from './redux/contactsActions';
export { prepareContactsReducer } from './redux/contactsReducer';
export * from './redux/contactsSelectors';
export * as CONTACTS from './constants';
export * from './types';
export * from './utils/findContact';
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { createAction } from '@reduxjs/toolkit';

import { Contact } from 'src/types/suite';

import { CONTACTS } from './constants';
import { Contact } from '../types';
import * as CONTACTS from '../constants';

export const addContact = createAction(CONTACTS.ADD, (payload: Contact) => ({ payload }));

export const removeContact = createAction(CONTACTS.REMOVE, (payload: Contact) => ({ payload }));

export const contactsActions = {
addContact,
removeContact,
};

export type ContactsAction = ReturnType<typeof addContact> | ReturnType<typeof removeContact>;
37 changes: 37 additions & 0 deletions suite-common/contacts/src/redux/contactsReducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { TrezorDevice } from '@suite-common/suite-types';
import { createReducerWithExtraDeps } from '@suite-common/redux-utils';

import { Contact } from '../types';
import { contactsActions } from './contactsActions';

export type ContactsRootState = {
contacts: ContactsState;
};

type ContactsState = Contact[];

const initialState: ContactsState = [];

const isEqual = (c1: Contact, c2: Contact) =>
c1.address === c2.address && c1.deviceState === c2.deviceState;

export const getDeviceState = (device: TrezorDevice) =>
device.state?.staticSessionId?.split('@')?.[0];

export const prepareContactsReducer = createReducerWithExtraDeps(initialState, (builder, extra) => {
builder
.addCase(contactsActions.addContact, (state, { payload: contact }) => {
const index = state.findIndex(c => isEqual(c, contact));
if (index >= 0) state[index] = contact;
else state.push(contact);

return state;
})
.addCase(contactsActions.removeContact, (state, { payload }) => {
return state.filter(c => !isEqual(c, payload));
})
.addMatcher(
action => action.type === extra.actionTypes.storageLoad,
extra.reducers.storageLoadContacts,
);
});
11 changes: 11 additions & 0 deletions suite-common/contacts/src/redux/contactsSelectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { TrezorDevice } from '@suite-common/suite-types';

import { ContactsRootState, getDeviceState } from './contactsReducer';

export const selectContacts = (state: ContactsRootState) => state.contacts;

export const selectContactsForDevice = (device: TrezorDevice) => (state: ContactsRootState) => {
const deviceState = getDeviceState(device);

return deviceState ? state.contacts.filter(c => c.deviceState === deviceState) : [];
};
6 changes: 6 additions & 0 deletions suite-common/contacts/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type Contact = {
address: string;
label: string;
signature: string;
deviceState: string;
};
Loading

0 comments on commit c7c8023

Please sign in to comment.