From c7c8023b5ef193e22e8e5184263105b5bd45879d Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Wed, 11 Dec 2024 18:02:07 +0100 Subject: [PATCH] chore(suite): refactor to new `@suite-common/contacts` package + use Connect for verify --- packages/suite/package.json | 1 - .../src/actions/suite/constants/index.ts | 2 - .../suite/src/actions/suite/storageActions.ts | 3 +- .../middlewares/wallet/storageMiddleware.ts | 3 +- .../src/reducers/suite/contactsReducer.ts | 45 ------------- packages/suite/src/reducers/suite/index.ts | 3 +- packages/suite/src/storage/definitions.ts | 2 +- .../suite/src/support/extraDependencies.ts | 1 + packages/suite/src/types/suite/index.ts | 9 +-- .../src/views/contacts/AddNewContactModal.tsx | 3 +- .../suite/src/views/contacts/ContactList.tsx | 3 +- packages/suite/src/views/contacts/index.tsx | 25 +++----- .../src/views/contacts/useAddContact.tsx | 4 +- suite-common/contacts/package.json | 17 +++++ suite-common/contacts/src/constants.ts | 2 + suite-common/contacts/src/index.ts | 7 ++ .../contacts/src/redux}/contactsActions.ts | 10 ++- .../contacts/src/redux/contactsReducer.ts | 37 +++++++++++ .../contacts/src/redux/contactsSelectors.ts | 11 ++++ suite-common/contacts/src/types.ts | 6 ++ .../contacts/src/utils/findContact.ts | 23 +++++++ suite-common/contacts/tsconfig.json | 7 ++ .../redux-utils/src/extraDependenciesType.ts | 1 + .../test-utils/src/extraDependenciesMock.ts | 1 + suite-common/wallet-core/package.json | 1 + .../src/send/sendFormBitcoinThunks.ts | 64 ++++++++++--------- suite-common/wallet-core/tsconfig.json | 1 + yarn.lock | 11 ++++ 28 files changed, 188 insertions(+), 115 deletions(-) delete mode 100644 packages/suite/src/reducers/suite/contactsReducer.ts create mode 100644 suite-common/contacts/package.json create mode 100644 suite-common/contacts/src/constants.ts create mode 100644 suite-common/contacts/src/index.ts rename {packages/suite/src/actions/suite => suite-common/contacts/src/redux}/contactsActions.ts (69%) create mode 100644 suite-common/contacts/src/redux/contactsReducer.ts create mode 100644 suite-common/contacts/src/redux/contactsSelectors.ts create mode 100644 suite-common/contacts/src/types.ts create mode 100644 suite-common/contacts/src/utils/findContact.ts create mode 100644 suite-common/contacts/tsconfig.json diff --git a/packages/suite/package.json b/packages/suite/package.json index 2d3515bde6f..4d98b750653 100644 --- a/packages/suite/package.json +++ b/packages/suite/package.json @@ -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", diff --git a/packages/suite/src/actions/suite/constants/index.ts b/packages/suite/src/actions/suite/constants/index.ts index e1a0c108463..f4c3de04671 100644 --- a/packages/suite/src/actions/suite/constants/index.ts +++ b/packages/suite/src/actions/suite/constants/index.ts @@ -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, @@ -25,5 +24,4 @@ export { DESKTOP_UPDATE, GUIDE, PROTOCOL, - CONTACTS, }; diff --git a/packages/suite/src/actions/suite/storageActions.ts b/packages/suite/src/actions/suite/storageActions.ts index 380f21571d5..d3c2efff94a 100644 --- a/packages/suite/src/actions/suite/storageActions.ts +++ b/packages/suite/src/actions/suite/storageActions.ts @@ -11,6 +11,7 @@ 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 { @@ -18,7 +19,7 @@ import { 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'; diff --git a/packages/suite/src/middlewares/wallet/storageMiddleware.ts b/packages/suite/src/middlewares/wallet/storageMiddleware.ts index b201013b327..924d8a5a091 100644 --- a/packages/suite/src/middlewares/wallet/storageMiddleware.ts +++ b/packages/suite/src/middlewares/wallet/storageMiddleware.ts @@ -23,6 +23,7 @@ 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'; @@ -30,7 +31,7 @@ import * as walletSettingsActions from 'src/actions/settings/walletSettingsActio 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'; diff --git a/packages/suite/src/reducers/suite/contactsReducer.ts b/packages/suite/src/reducers/suite/contactsReducer.ts deleted file mode 100644 index 83f16d34e53..00000000000 --- a/packages/suite/src/reducers/suite/contactsReducer.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { CONTACTS, STORAGE } from 'src/actions/suite/constants'; -import type { Action, Contact, TrezorDevice } from 'src/types/suite'; - -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]; - -const contactsReducer = (state: ContactsState = initialState, action: Action): ContactsState => { - switch (action.type) { - case STORAGE.LOAD: { - return action.payload.contacts; - } - case CONTACTS.ADD: { - const contact = action.payload; - const index = state.findIndex(c => isEqual(c, contact)); - if (index >= 0) state[index] = contact; - else state.push(contact); - - return state.slice(); - } - case CONTACTS.REMOVE: { - return state.filter(c => !isEqual(c, action.payload)); - } - default: - return state; - } -}; - -export const selectContactsForDevice = (device: TrezorDevice) => (state: ContactsRootState) => { - const deviceState = getDeviceState(device); - - return deviceState ? state.contacts.filter(c => c.deviceState === deviceState) : []; -}; - -export default contactsReducer; diff --git a/packages/suite/src/reducers/suite/index.ts b/packages/suite/src/reducers/suite/index.ts index b8059e473e1..1709fa9b7dd 100644 --- a/packages/suite/src/reducers/suite/index.ts +++ b/packages/suite/src/reducers/suite/index.ts @@ -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'; @@ -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, diff --git a/packages/suite/src/storage/definitions.ts b/packages/suite/src/storage/definitions.ts index c598e4a4968..6124eca504a 100644 --- a/packages/suite/src/storage/definitions.ts +++ b/packages/suite/src/storage/definitions.ts @@ -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'; diff --git a/packages/suite/src/support/extraDependencies.ts b/packages/suite/src/support/extraDependencies.ts index 3f30bddb60f..c8263ca5001 100644 --- a/packages/suite/src/support/extraDependencies.ts +++ b/packages/suite/src/support/extraDependencies.ts @@ -159,6 +159,7 @@ export const extraDependencies: ExtraDependencies = { } }, storageLoadDiscovery: (_, { payload }: StorageLoadAction) => payload.discovery, + storageLoadContacts: (_, { payload }: StorageLoadAction) => payload.contacts, addButtonRequestFirmware: ( state, { diff --git a/packages/suite/src/types/suite/index.ts b/packages/suite/src/types/suite/index.ts index be2d500575f..d4a3d6dc8fe 100644 --- a/packages/suite/src/types/suite/index.ts +++ b/packages/suite/src/types/suite/index.ts @@ -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'; @@ -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'; @@ -129,10 +129,3 @@ export enum DisplayMode { PAGINATED_TEXT, SINGLE_WRAPPED_TEXT, } - -export type Contact = { - address: string; - label: string; - signature: string; - deviceState: string; -}; diff --git a/packages/suite/src/views/contacts/AddNewContactModal.tsx b/packages/suite/src/views/contacts/AddNewContactModal.tsx index a3f594de0bf..e14246cca6c 100644 --- a/packages/suite/src/views/contacts/AddNewContactModal.tsx +++ b/packages/suite/src/views/contacts/AddNewContactModal.tsx @@ -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 = { @@ -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(null); const [label, setLabel] = useState(''); diff --git a/packages/suite/src/views/contacts/ContactList.tsx b/packages/suite/src/views/contacts/ContactList.tsx index 40d5c0b8c00..03688830e44 100644 --- a/packages/suite/src/views/contacts/ContactList.tsx +++ b/packages/suite/src/views/contacts/ContactList.tsx @@ -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, diff --git a/packages/suite/src/views/contacts/index.tsx b/packages/suite/src/views/contacts/index.tsx index c888e439d4e..057b2f7dc17 100644 --- a/packages/suite/src/views/contacts/index.tsx +++ b/packages/suite/src/views/contacts/index.tsx @@ -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'); @@ -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 ( - ); @@ -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}`); diff --git a/packages/suite/src/views/contacts/useAddContact.tsx b/packages/suite/src/views/contacts/useAddContact.tsx index 09b9309c9a3..5aab2cb03d2 100644 --- a/packages/suite/src/views/contacts/useAddContact.tsx +++ b/packages/suite/src/views/contacts/useAddContact.tsx @@ -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(); diff --git a/suite-common/contacts/package.json b/suite-common/contacts/package.json new file mode 100644 index 00000000000..fe1757384c5 --- /dev/null +++ b/suite-common/contacts/package.json @@ -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:*" + } +} diff --git a/suite-common/contacts/src/constants.ts b/suite-common/contacts/src/constants.ts new file mode 100644 index 00000000000..8ad36ee631e --- /dev/null +++ b/suite-common/contacts/src/constants.ts @@ -0,0 +1,2 @@ +export const ADD = '@contacts/add'; +export const REMOVE = '@contacts/remove'; diff --git a/suite-common/contacts/src/index.ts b/suite-common/contacts/src/index.ts new file mode 100644 index 00000000000..f504cd23809 --- /dev/null +++ b/suite-common/contacts/src/index.ts @@ -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'; diff --git a/packages/suite/src/actions/suite/contactsActions.ts b/suite-common/contacts/src/redux/contactsActions.ts similarity index 69% rename from packages/suite/src/actions/suite/contactsActions.ts rename to suite-common/contacts/src/redux/contactsActions.ts index 4d39d4a086e..9eb55385126 100644 --- a/packages/suite/src/actions/suite/contactsActions.ts +++ b/suite-common/contacts/src/redux/contactsActions.ts @@ -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 | ReturnType; diff --git a/suite-common/contacts/src/redux/contactsReducer.ts b/suite-common/contacts/src/redux/contactsReducer.ts new file mode 100644 index 00000000000..89445bd0656 --- /dev/null +++ b/suite-common/contacts/src/redux/contactsReducer.ts @@ -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, + ); +}); diff --git a/suite-common/contacts/src/redux/contactsSelectors.ts b/suite-common/contacts/src/redux/contactsSelectors.ts new file mode 100644 index 00000000000..8c49798faf1 --- /dev/null +++ b/suite-common/contacts/src/redux/contactsSelectors.ts @@ -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) : []; +}; diff --git a/suite-common/contacts/src/types.ts b/suite-common/contacts/src/types.ts new file mode 100644 index 00000000000..5d9eec0924e --- /dev/null +++ b/suite-common/contacts/src/types.ts @@ -0,0 +1,6 @@ +export type Contact = { + address: string; + label: string; + signature: string; + deviceState: string; +}; diff --git a/suite-common/contacts/src/utils/findContact.ts b/suite-common/contacts/src/utils/findContact.ts new file mode 100644 index 00000000000..3f515f0fed9 --- /dev/null +++ b/suite-common/contacts/src/utils/findContact.ts @@ -0,0 +1,23 @@ +import TrezorConnect from '@trezor/connect'; + +import { Contact } from '../types'; + +export const findContact = async (contacts: Contact[], address: string, signature: string) => { + for (const contact of contacts) { + try { + // I thought this would work better but it still doesn't... + const response = await TrezorConnect.verifyMessage({ + address: contact.address, + message: address, + signature: Buffer.from(signature, 'hex').toString('base64'), + coin: 'test', + }); + + if (response.success) { + return contact; + } + } catch { + continue; + } + } +}; diff --git a/suite-common/contacts/tsconfig.json b/suite-common/contacts/tsconfig.json new file mode 100644 index 00000000000..de3ee596b86 --- /dev/null +++ b/suite-common/contacts/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { "outDir": "libDev" }, + "references": [ + { "path": "../../packages/connect" } + ] +} diff --git a/suite-common/redux-utils/src/extraDependenciesType.ts b/suite-common/redux-utils/src/extraDependenciesType.ts index b388c6362ff..b8bb40c2bd0 100644 --- a/suite-common/redux-utils/src/extraDependenciesType.ts +++ b/suite-common/redux-utils/src/extraDependenciesType.ts @@ -128,6 +128,7 @@ export type ExtraDependencies = { storageLoadHistoricRates: StorageLoadReducer; storageLoadFirmware: StorageLoadReducer; storageLoadDiscovery: StorageLoadReducer; + storageLoadContacts: StorageLoadReducer; addButtonRequestFirmware: AddButtonRequestReducer; setDeviceMetadataReducer: BaseReducer; setDeviceMetadataPasswordsReducer: BaseReducer; diff --git a/suite-common/test-utils/src/extraDependenciesMock.ts b/suite-common/test-utils/src/extraDependenciesMock.ts index e140e87bba6..523b0c8020a 100644 --- a/suite-common/test-utils/src/extraDependenciesMock.ts +++ b/suite-common/test-utils/src/extraDependenciesMock.ts @@ -127,6 +127,7 @@ export const extraDependenciesMock: ExtraDependencies = { storageLoadHistoricRates: mockReducer('storageLoadHistoricRates'), storageLoadFirmware: mockReducer('storageLoadFirmware'), storageLoadDiscovery: mockReducer('storageLoadDiscovery'), + storageLoadContacts: mockReducer('storageLoadContacts'), addButtonRequestFirmware: mockReducer('addButtonRequestFirmware'), setDeviceMetadataReducer: mockReducer('setDeviceMetadataReducer'), setDeviceMetadataPasswordsReducer: mockReducer('setDeviceMetadataPasswordsReducer'), diff --git a/suite-common/wallet-core/package.json b/suite-common/wallet-core/package.json index 573037e0e22..9151f193818 100644 --- a/suite-common/wallet-core/package.json +++ b/suite-common/wallet-core/package.json @@ -13,6 +13,7 @@ "dependencies": { "@mobily/ts-belt": "^3.13.1", "@reduxjs/toolkit": "1.9.5", + "@suite-common/contacts": "workspace:*", "@suite-common/device-authenticity": "workspace:*", "@suite-common/fiat-services": "workspace:*", "@suite-common/redux-utils": "workspace:*", diff --git a/suite-common/wallet-core/src/send/sendFormBitcoinThunks.ts b/suite-common/wallet-core/src/send/sendFormBitcoinThunks.ts index 6cc1fc7744c..cb0b2fa94ad 100644 --- a/suite-common/wallet-core/src/send/sendFormBitcoinThunks.ts +++ b/suite-common/wallet-core/src/send/sendFormBitcoinThunks.ts @@ -1,5 +1,3 @@ -import { verify } from 'bitcoinjs-message'; - import { BigNumber } from '@trezor/utils/src/bigNumber'; import TrezorConnect, { FeeLevel, @@ -27,6 +25,7 @@ import { PrecomposedTransaction, } from '@suite-common/wallet-types'; import { createThunk } from '@suite-common/redux-utils'; +import { findContact, selectContactsForDevice } from '@suite-common/contacts'; import { selectTransactions } from '../transactions/transactionsReducer'; import { selectDevice } from '../device/deviceReducer'; @@ -346,48 +345,51 @@ export const signBitcoinSendFormTransactionThunk = createThunk< ...signEnhancement, }; - const deviceState = device.state?.staticSessionId?.split('@')?.[0]; - const contacts: { address: string; label: string; signature: string }[] = deviceState - ? getState().contacts.filter((c: any) => c.deviceState === deviceState) - : []; - - signPayload.outputs = signPayload.outputs.map(output => { - if (output.address) { - const contactSignature = formState.contactSignatures[output.address]; - if (contactSignature) { - const contact = contacts.find(c => { - try { - return verify(output.address, c.address, contactSignature); - } catch { - return false; + const contacts = selectContactsForDevice(device)(getState()); + + signPayload.outputs = await Promise.all( + signPayload.outputs.map(async output => { + if (output.address) { + const contactSignature = formState.contactSignatures?.[output.address]; + if (contactSignature) { + //console.log('contactSignature', contactSignature); + const contact = await findContact( + contacts, + output.address, + contactSignature, + ); + //console.log('contact', contact); + if (contact) { + return { + ...output, + label: contact.label, + label_sig: Buffer.from(contact.signature, 'base64').toString('hex'), + label_pk: contact.address, + address_pk_sig: contactSignature, + }; } - }); + } + + const contact = contacts.find(c => c.address === output.address); + //console.log('direct contact', contact); if (contact) { return { ...output, label: contact.label, label_sig: Buffer.from(contact.signature, 'base64').toString('hex'), - label_pk: contact.address, - address_pk_sig: contactSignature, }; } } - const contact = contacts.find(c => c.address === output.address); - if (contact) { - return { - ...output, - label: contact.label, - label_sig: Buffer.from(contact.signature, 'base64').toString('hex'), - }; - } - } - - return output; - }); + return output; + }), + ); + //console.log('signPayload', signPayload); const response = await TrezorConnect.signTransaction(signPayload); if (!response.success) { + console.error('sign-transaction-failed', response.payload); + return rejectWithValue({ error: 'sign-transaction-failed', errorCode: response.payload.code, diff --git a/suite-common/wallet-core/tsconfig.json b/suite-common/wallet-core/tsconfig.json index 748ceceb982..3f22527b50b 100644 --- a/suite-common/wallet-core/tsconfig.json +++ b/suite-common/wallet-core/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "libDev" }, "references": [ + { "path": "../contacts" }, { "path": "../device-authenticity" }, { "path": "../fiat-services" }, { "path": "../redux-utils" }, diff --git a/yarn.lock b/yarn.lock index 36ed32ce7b6..65b6be46e7f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9424,6 +9424,16 @@ __metadata: languageName: unknown linkType: soft +"@suite-common/contacts@workspace:*, @suite-common/contacts@workspace:suite-common/contacts": + version: 0.0.0-use.local + resolution: "@suite-common/contacts@workspace:suite-common/contacts" + dependencies: + "@reduxjs/toolkit": "npm:1.9.5" + "@suite-common/suite-types": "workspace:*" + "@trezor/connect": "workspace:*" + languageName: unknown + linkType: soft + "@suite-common/device-authenticity@workspace:*, @suite-common/device-authenticity@workspace:suite-common/device-authenticity": version: 0.0.0-use.local resolution: "@suite-common/device-authenticity@workspace:suite-common/device-authenticity" @@ -9750,6 +9760,7 @@ __metadata: dependencies: "@mobily/ts-belt": "npm:^3.13.1" "@reduxjs/toolkit": "npm:1.9.5" + "@suite-common/contacts": "workspace:*" "@suite-common/device-authenticity": "workspace:*" "@suite-common/fiat-services": "workspace:*" "@suite-common/redux-utils": "workspace:*"