Skip to content

Commit

Permalink
feat(connect): dispatch call in progress event - needed for immediate…
Browse files Browse the repository at this point in the history
… feedback in suite when called from outside
  • Loading branch information
mroz22 committed Oct 21, 2024
1 parent f6caf4c commit 2f90c34
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 57 deletions.
14 changes: 11 additions & 3 deletions packages/connect/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,6 @@ const onCall = async (context: CoreContext, message: IFrameCallMessage) => {
'onCall: message.id or message.payload is missing',
);
}

const {
uiPromises,
callMethods,
Expand Down Expand Up @@ -526,7 +525,17 @@ const onCall = async (context: CoreContext, message: IFrameCallMessage) => {
return Promise.resolve();
}

return await onCallDevice(context, message, method);
if (method.useDevice) {
sendCoreMessage(createUiMessage(UI.CALL_IN_PROGRESS, { value: true }));
}

try {
return await onCallDevice(context, message, method);
} finally {
if (method.useDevice) {
sendCoreMessage(createUiMessage(UI.CALL_IN_PROGRESS, { value: true }));
}
}
};

const onCallDevice = async (
Expand Down Expand Up @@ -578,7 +587,6 @@ const onCallDevice = async (
const device = tempDevice;

method.setDevice(device);

// find pending calls to this device
const previousCall = callMethods.filter(
call => call && call !== method && call.devicePath === method.devicePath,
Expand Down
11 changes: 10 additions & 1 deletion packages/connect/src/events/ui-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const UI_REQUEST = {
FIRMWARE_NOT_COMPATIBLE: 'ui-device_firmware_not_compatible',
FIRMWARE_NOT_INSTALLED: 'ui-device_firmware_not_installed',
FIRMWARE_PROGRESS: 'ui-firmware-progress',
CALL_IN_PROGRESS: 'ui-call_in_progress',

/** connect is waiting for device to be automatically reconnected */
FIRMWARE_RECONNECT: 'ui-firmware_reconnect',
Expand Down Expand Up @@ -157,6 +158,13 @@ export interface UiRequestSetOperation {
payload: string;
}

export interface UiRequestCallInProgress {
type: typeof UI_REQUEST.CALL_IN_PROGRESS;
payload: {
value: boolean; // is in progress?
};
}

export interface UiRequestPermission {
type: typeof UI_REQUEST.REQUEST_PERMISSION;
payload: {
Expand Down Expand Up @@ -292,7 +300,8 @@ export type UiEvent =
| FirmwareException
| FirmwareReconnect
| UiRequestAddressValidation
| UiRequestSetOperation;
| UiRequestSetOperation
| UiRequestCallInProgress;

export type UiEventMessage = UiEvent & { event: typeof UI_EVENT };

Expand Down
44 changes: 40 additions & 4 deletions packages/suite/src/actions/backup/__tests__/backupActions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { mergeDeepObject } from '@trezor/utils';
import { connectInitThunk } from '@suite-common/connect-init';
import { testMocks } from '@suite-common/test-utils';
import { notificationsActions } from '@suite-common/toast-notifications';
import { CommonParams, DeviceModelInternal } from '@trezor/connect';
import { CommonParams, DeviceModelInternal, UI, UI_EVENT } from '@trezor/connect';

import { configureStore } from 'src/support/tests/configureStore';
import { SUITE } from 'src/actions/suite/constants';
import { BACKUP } from 'src/actions/backup/constants';
import * as backupActions from 'src/actions/backup/backupActions';
import { value } from '@trezor/utxo-lib/src/payments/lazy';

export const getInitialState = (override: any) => {
const defaults = {
Expand Down Expand Up @@ -51,17 +52,26 @@ describe('Backup Actions', () => {
});

it('backup success', async () => {
const { emitTestEvent } = testMocks.getTrezorConnectMock();
testMocks.setTrezorConnectFixtures({ success: true });

const state = getInitialState({});
const store = mockStore(state);
await store.dispatch(connectInitThunk());

await store.dispatch(
const p = store.dispatch(
backupActions.backupDevice({
device: store.getState().device.selectedDevice as CommonParams['device'],
}),
);
emitTestEvent(UI_EVENT, {
type: UI.CALL_IN_PROGRESS,
payload: { value: true },
});
emitTestEvent(UI_EVENT, {
type: UI.CALL_IN_PROGRESS,
payload: { value: false },
});
await p;

expect(store.getActions().shift()).toMatchObject({
type: connectInitThunk.pending.type,
Expand All @@ -76,14 +86,23 @@ describe('Backup Actions', () => {
payload: 'in-progress',
});
expect(store.getActions().shift()).toEqual({ type: SUITE.LOCK_DEVICE, payload: true });
expect(store.getActions().shift()).toEqual({
type: UI.CALL_IN_PROGRESS,
payload: { value: true },
});
expect(store.getActions().shift()).toEqual({ type: SUITE.LOCK_DEVICE, payload: false });
expect(store.getActions().shift()).toEqual({
type: UI.CALL_IN_PROGRESS,
payload: { value: false },
});
expect(store.getActions().shift()).toMatchObject({
type: notificationsActions.addToast.type,
payload: { type: 'backup-success' },
});
});

it('backup error', async () => {
const { emitTestEvent } = testMocks.getTrezorConnectMock();
testMocks.setTrezorConnectFixtures({
success: false,
payload: { error: 'avadakedavra' },
Expand All @@ -93,11 +112,20 @@ describe('Backup Actions', () => {
const store = mockStore(state);
await store.dispatch(connectInitThunk());

await store.dispatch(
const p = store.dispatch(
backupActions.backupDevice({
device: store.getState().device.selectedDevice as CommonParams['device'],
}),
);
emitTestEvent(UI_EVENT, {
type: UI.CALL_IN_PROGRESS,
payload: { value: true },
});
emitTestEvent(UI_EVENT, {
type: UI.CALL_IN_PROGRESS,
payload: { value: false },
});
await p;

expect(store.getActions().shift()).toMatchObject({
type: connectInitThunk.pending.type,
Expand All @@ -112,7 +140,15 @@ describe('Backup Actions', () => {
payload: 'in-progress',
});
expect(store.getActions().shift()).toEqual({ type: SUITE.LOCK_DEVICE, payload: true });
expect(store.getActions().shift()).toEqual({
type: UI.CALL_IN_PROGRESS,
payload: { value: true },
});
expect(store.getActions().shift()).toEqual({ type: SUITE.LOCK_DEVICE, payload: false });
expect(store.getActions().shift()).toEqual({
type: UI.CALL_IN_PROGRESS,
payload: { value: false },
});
expect(store.getActions().shift()).toMatchObject({
type: notificationsActions.addToast.type,
payload: { type: 'backup-failed' },
Expand Down
17 changes: 0 additions & 17 deletions packages/suite/src/actions/suite/__fixtures__/suiteActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -734,23 +734,6 @@ const observeSelectedDevice = [
];

const acquireDevice = [
{
description: `success`,
state: {
device: {
selectedDevice: SUITE_DEVICE,
},
},
result: SUITE.LOCK_DEVICE,
},
{
description: `success with requestedDevice param`,
state: {
device: {},
},
requestedDevice: SUITE_DEVICE,
result: SUITE.LOCK_DEVICE,
},
{
description: `with TrezorConnect error`,
state: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DEVICE_EVENT, UI_EVENT, TRANSPORT_EVENT, BLOCKCHAIN_EVENT } from '@trezor/connect';
import { DEVICE_EVENT, UI_EVENT, TRANSPORT_EVENT, BLOCKCHAIN_EVENT, UI } from '@trezor/connect';
import { connectInitThunk } from '@suite-common/connect-init';
import { testMocks } from '@suite-common/test-utils';
import { prepareDeviceReducer } from '@suite-common/wallet-core';
Expand Down Expand Up @@ -113,13 +113,27 @@ describe('TrezorConnect Actions', () => {
const state = getInitialState();
const store = initStore(state);
await store.dispatch(connectInitThunk());
await testMocks.getTrezorConnectMock().getFeatures();
const p = testMocks.getTrezorConnectMock().getFeatures();

const { emitTestEvent } = testMocks.getTrezorConnectMock();
emitTestEvent(UI_EVENT, { type: UI.CALL_IN_PROGRESS, payload: { value: true } });
emitTestEvent(UI_EVENT, { type: UI.CALL_IN_PROGRESS, payload: { value: false } });

await p;
const actions = store.getActions();
// check actions in reversed order
expect(actions.pop()).toEqual({
type: UI.CALL_IN_PROGRESS,
payload: { value: false },
});
expect(actions.pop()).toEqual({
type: SUITE.LOCK_DEVICE,
payload: false,
});
expect(actions.pop()).toEqual({
type: UI.CALL_IN_PROGRESS,
payload: { value: true },
});
expect(actions.pop()).toEqual({
type: SUITE.LOCK_DEVICE,
payload: true,
Expand Down
10 changes: 0 additions & 10 deletions packages/suite/src/actions/wallet/__fixtures__/publicKeyActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import { MODAL } from 'src/actions/suite/constants';

const { getSuiteDevice } = testMocks;

const LOCK_DEVICE = '@mocked/extraDependency/action/notImplemented/lockDevice';

export default [
{
description: 'Show unverified public key',
Expand All @@ -33,8 +31,6 @@ export default [
{ type: connectInitThunk.pending.type, payload: undefined },
{ type: connectInitThunk.fulfilled.type, payload: undefined },
{ type: MODAL.PRESERVE },
{ type: LOCK_DEVICE },
{ type: LOCK_DEVICE },
{ type: MODAL.OPEN_USER_CONTEXT },
],
},
Expand All @@ -51,8 +47,6 @@ export default [
{ type: connectInitThunk.pending.type, payload: undefined },
{ type: connectInitThunk.fulfilled.type, payload: undefined },
{ type: MODAL.PRESERVE },
{ type: LOCK_DEVICE },
{ type: LOCK_DEVICE },
{ type: MODAL.OPEN_USER_CONTEXT },
],
},
Expand Down Expand Up @@ -127,8 +121,6 @@ export default [
{ type: connectInitThunk.pending.type, payload: undefined },
{ type: connectInitThunk.fulfilled.type, payload: undefined },
{ type: MODAL.PRESERVE },
{ type: LOCK_DEVICE },
{ type: LOCK_DEVICE },
{ type: MODAL.CLOSE },
{
type: notificationsActions.addToast.type,
Expand All @@ -152,8 +144,6 @@ export default [
{ type: connectInitThunk.pending.type, payload: undefined },
{ type: connectInitThunk.fulfilled.type, payload: undefined },
{ type: MODAL.PRESERVE },
{ type: LOCK_DEVICE },
{ type: LOCK_DEVICE },
{ type: MODAL.CLOSE },
],
},
Expand Down
10 changes: 0 additions & 10 deletions packages/suite/src/actions/wallet/__fixtures__/receiveActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ export default [
{ type: connectInitThunk.fulfilled.type, payload: undefined },
{ type: MODAL.PRESERVE },
{ type: confirmAddressOnDeviceThunk.pending.type, payload: undefined },
{ type: SUITE.LOCK_DEVICE, payload: true },
{ type: SUITE.LOCK_DEVICE, payload: false },
{ type: confirmAddressOnDeviceThunk.fulfilled.type, payload: { success: true } },
{ type: MODAL.OPEN_USER_CONTEXT },
{ type: RECEIVE.SHOW_ADDRESS, path: PATH, address: ADDRESS },
Expand Down Expand Up @@ -72,8 +70,6 @@ export default [
{ type: connectInitThunk.fulfilled.type, payload: undefined },
{ type: MODAL.PRESERVE },
{ type: confirmAddressOnDeviceThunk.pending.type, payload: undefined },
{ type: SUITE.LOCK_DEVICE, payload: true },
{ type: SUITE.LOCK_DEVICE, payload: false },
{ type: confirmAddressOnDeviceThunk.fulfilled.type, payload: { success: true } },
{ type: MODAL.OPEN_USER_CONTEXT },
{ type: RECEIVE.SHOW_ADDRESS, path: PATH, address: ADDRESS },
Expand Down Expand Up @@ -104,8 +100,6 @@ export default [
{ type: connectInitThunk.fulfilled.type, payload: undefined },
{ type: MODAL.PRESERVE },
{ type: confirmAddressOnDeviceThunk.pending.type, payload: undefined },
{ type: SUITE.LOCK_DEVICE, payload: true },
{ type: SUITE.LOCK_DEVICE, payload: false },
{ type: confirmAddressOnDeviceThunk.fulfilled.type, payload: { success: true } },
{ type: MODAL.OPEN_USER_CONTEXT },
{ type: RECEIVE.SHOW_ADDRESS, path: PATH, address: ADDRESS },
Expand Down Expand Up @@ -182,8 +176,6 @@ export default [
{ type: connectInitThunk.fulfilled.type, payload: undefined },
{ type: MODAL.PRESERVE },
{ type: confirmAddressOnDeviceThunk.pending.type, payload: undefined },
{ type: SUITE.LOCK_DEVICE, payload: true },
{ type: SUITE.LOCK_DEVICE, payload: false },
{ type: confirmAddressOnDeviceThunk.fulfilled.type, payload: { success: false } },
{ type: MODAL.CLOSE },
{
Expand All @@ -209,8 +201,6 @@ export default [
{ type: connectInitThunk.fulfilled.type, payload: undefined },
{ type: MODAL.PRESERVE },
{ type: confirmAddressOnDeviceThunk.pending.type, payload: undefined },
{ type: SUITE.LOCK_DEVICE, payload: true },
{ type: SUITE.LOCK_DEVICE, payload: false },
{ type: confirmAddressOnDeviceThunk.fulfilled.type, payload: { success: false } },
{ type: MODAL.CLOSE },
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ describe('ReceiveActions', () => {
const store = initStore(state);
await store.dispatch(connectInitThunk());
await store.dispatch(f.action());

if (f.result && f.result.actions) {
expect(store.getActions()).toMatchObject(f.result.actions);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ describe('buttonRequest middleware', () => {

// fake few ui events, just like when user is changing PIN
await Promise.resolve();
emitTestEvent(UI_EVENT, {
type: UI.CALL_IN_PROGRESS,
payload: { value: true },
});
emitTestEvent(UI_EVENT, {
type: UI.REQUEST_BUTTON,
payload: { code: 'ButtonRequest_ProtectCall' },
Expand All @@ -58,6 +62,10 @@ describe('buttonRequest middleware', () => {
type: UI.REQUEST_PIN,
payload: { type: 'PinMatrixRequestType_NewFirst', device },
});
emitTestEvent(UI_EVENT, {
type: UI.CALL_IN_PROGRESS,
payload: { value: false },
});

await call;

Expand All @@ -67,6 +75,7 @@ describe('buttonRequest middleware', () => {
{ type: connectInitThunk.pending.type, payload: undefined },
{ type: connectInitThunk.fulfilled.type, payload: undefined },
{ type: SUITE.LOCK_DEVICE, payload: true },
{ type: UI.CALL_IN_PROGRESS, payload: { value: true } },
{ type: UI.REQUEST_BUTTON, payload: { code: 'ButtonRequest_ProtectCall' } },
{
type: deviceActions.addButtonRequest.type,
Expand All @@ -79,6 +88,7 @@ describe('buttonRequest middleware', () => {
},
{ type: SUITE.LOCK_DEVICE, payload: false },
{ type: deviceActions.removeButtonRequests.type, payload: { device } },
{ type: UI.CALL_IN_PROGRESS, payload: { value: false } },
]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,13 @@ describe('TrezorConnect Actions', () => {
it('Wrapped method', async () => {
testMocks.setTrezorConnectFixtures();
await store.dispatch(connectInitThunk());
await testMocks.getTrezorConnectMock().getFeatures();
const { getFeatures, emitTestEvent } = testMocks.getTrezorConnectMock();
await getFeatures();
emitTestEvent(UI_EVENT, { type: 'ui-call_in_progress', payload: { value: true } });

const actions = store.getActions();
// check actions in reversed order
expect(actions.pop()).toEqual({
type: extraDependenciesMock.actions.lockDevice.type,
payload: false,
});
expect(actions.pop()).toEqual({ type: 'ui-call_in_progress', payload: { value: true } });
expect(actions.pop()).toEqual({
type: extraDependenciesMock.actions.lockDevice.type,
payload: true,
Expand Down
Loading

0 comments on commit 2f90c34

Please sign in to comment.