feat(connect): send analytics data from connect core

This commit is contained in:
tomasklim
2022-10-31 14:37:01 +01:00
committed by Tomáš Klíma
parent cccc502813
commit f7b5e27ce7
18 changed files with 110 additions and 18 deletions

View File

@@ -1,4 +1,5 @@
export enum EventType {
AppReady = 'app/ready',
SettingsTracking = 'settings/tracking',
}

View File

@@ -1,8 +1,28 @@
import { EventType } from '../constants';
export type ConnectAnalyticsEvent = {
type: EventType.SettingsTracking;
export type EventTypeDeviceSelected = {
type: EventType.DeviceSelected;
payload: {
value: boolean;
mode: 'normal' | 'bootloader' | 'initialize' | 'seedless';
pinProtection: boolean | '';
passphraseProtection: boolean | '';
backupType: string;
language: string;
model: string;
vendor: string;
firmware: string;
firmwareRevision: string;
firmwareType: string;
bootloaderHash: string;
bootloaderVersion: string;
};
};
export type ConnectAnalyticsEvent =
| EventTypeDeviceSelected
| {
type: EventType.SettingsTracking;
payload: {
value: boolean;
};
};

View File

@@ -13,6 +13,7 @@
"dependencies": {
"@trezor/components": "*",
"@trezor/connect": "9.0.4",
"@trezor/connect-analytics": "*",
"@trezor/connect-ui": "*",
"@trezor/crypto-utils": "*",
"@trezor/urls": "*"

View File

@@ -10,6 +10,7 @@ import {
PopupHandshake,
} from '@trezor/connect';
import { reactEventBus } from '@trezor/connect-ui/src/utils/eventBus';
import { analytics, EventType } from '@trezor/connect-analytics';
import * as view from './view';
import {
@@ -75,6 +76,15 @@ const handleMessage = (event: MessageEvent<PopupEvent | UiEvent>) => {
const message = parseMessage(data);
if (
message?.payload &&
typeof message.payload === 'object' &&
'analytics' in message.payload &&
message.payload.analytics
) {
analytics.report(message.payload.analytics);
}
console.log('message.type', message.type);
console.log('message', message);
switch (message.type) {

View File

@@ -8,6 +8,7 @@
"references": [
{ "path": "../components" },
{ "path": "../connect" },
{ "path": "../connect-analytics" },
{ "path": "../connect-ui" },
{ "path": "../crypto-utils" },
{ "path": "../urls" },

View File

@@ -42,5 +42,6 @@ export const initAnalytics = () => {
onEnable,
onDisable,
},
useQueue: true,
});
};

View File

@@ -1,3 +1,7 @@
# 9.0.5 - UNRELEASED
- introduction of connect analytics
# 9.0.4
- @trezor/blockchain-link 2.1.5

View File

@@ -47,7 +47,9 @@
},
"dependencies": {
"@trezor/blockchain-link": "^2.1.5",
"@trezor/connect-analytics": "*",
"@trezor/connect-common": "0.0.10",
"@trezor/device-utils": "*",
"@trezor/transport": "^1.1.5",
"@trezor/utils": "^9.0.3",
"@trezor/utxo-lib": "^1.0.1",

View File

@@ -2,6 +2,7 @@
import EventEmitter from 'events';
import { DataManager } from '../data/DataManager';
import { DeviceList } from '../device/DeviceList';
import { enhancePostMessageWithAnalytics } from '../data/analyticsInfo';
import { ERRORS } from '../constants';
@@ -361,6 +362,9 @@ export const onCall = async (message: CoreMessage) => {
throw error;
}
method.postMessage = (message: CoreMessage) =>
enhancePostMessageWithAnalytics(postMessage, message, { device });
method.setDevice(device);
// find pending calls to this device

View File

@@ -0,0 +1,52 @@
/* eslint-disable no-case-declarations */
import { EventType } from '@trezor/connect-analytics';
import {
getBootloaderHash,
getBootloaderVersion,
getDeviceMode,
getDeviceModel,
getFirmwareRevision,
getFirmwareType,
getFirmwareVersion,
} from '@trezor/device-utils';
import { CoreMessage, UI_REQUEST } from '../events';
import type { Device } from '../device/Device';
export const enhancePostMessageWithAnalytics = (
callback: (message: CoreMessage) => void,
message: CoreMessage,
data: { device?: Device },
) => {
switch (message.type) {
case UI_REQUEST.REQUEST_CONFIRMATION:
const { device } = data;
callback({
...message,
payload: {
...message.payload,
analytics: {
type: EventType.DeviceSelected,
payload: {
mode: getDeviceMode(device),
pinProtection: device?.features.pin_protection || '',
passphraseProtection: device?.features.passphrase_protection || '',
backupType: device?.features.backup_type || 'Bip39',
language: device?.features.language || '',
model: getDeviceModel(device),
vendor: device?.features.vendor || '',
firmware: getFirmwareVersion(device),
firmwareRevision: getFirmwareRevision(device),
firmwareType: getFirmwareType(device),
bootloaderHash: getBootloaderHash(device),
bootloaderVersion: getBootloaderVersion(device),
},
},
},
});
break;
default:
callback(message);
}
};

View File

@@ -1,6 +1,7 @@
/*
* messages to UI emitted as UI_EVENT
*/
import type { EventTypeDeviceSelected } from '@trezor/connect-analytics';
import type { PROTO } from '../constants';
import type { TransportDisableWebUSB } from './transport';
@@ -172,6 +173,7 @@ export interface UiRequestConfirmation {
className: string;
label: string;
};
analytics?: EventTypeDeviceSelected;
};
}

View File

@@ -4,7 +4,9 @@
"include": ["../../submodules/trezor-common"],
"references": [
{ "path": "../blockchain-link" },
{ "path": "../connect-analytics" },
{ "path": "../connect-common" },
{ "path": "../device-utils" },
{ "path": "../transport" },
{ "path": "../utils" },
{ "path": "../utxo-lib" },

View File

@@ -1,6 +1,3 @@
import { PartialDevice } from './types';
export const getDeviceModel = (device: PartialDevice): 'T' | '1' => {
const { features } = device;
return typeof features?.major_version === 'number' && features?.major_version > 1 ? 'T' : '1';
};
export const getDeviceModel = (device?: PartialDevice) => device?.features?.model || '';

View File

@@ -13,6 +13,7 @@ export type PartialDevice = Partial<{
fw_patch: number | null;
initialized: boolean | null;
no_backup: boolean | null;
model: string | null;
};
firmwareType: string | null;
}>;

View File

@@ -79,7 +79,7 @@ export type SuiteAnalyticsEvent =
type: EventType.DeviceSetupCompleted;
payload: Partial<Omit<OnboardingAnalytics, 'startTime'>> & {
duration: number;
device: 'T' | '1';
device: string;
};
}
| {

View File

@@ -4,12 +4,11 @@ import { Image, ImageProps } from '@trezor/components';
import { ImageType } from '@trezor/components/src/components/Image/Image';
import { getDeviceModel } from '@trezor/device-utils';
const getImage = (majorVersion: '1' | 'T'): ImageType => {
const getImage = (majorVersion: string): ImageType => {
switch (majorVersion) {
case '1':
return 'ONE_DEVICE_CONFIRM';
case 'T':
return 'T_DEVICE_CONFIRM';
default:
return 'T_DEVICE_CONFIRM';
}

View File

@@ -164,17 +164,12 @@ const isSelectedInstance = [
const getDeviceModel = [
{
description: `model T`,
device: SUITE_DEVICE,
device: getSuiteDevice(undefined, { model: 'T' }),
result: 'T',
},
{
description: `model One`,
device: getSuiteDevice(undefined, { major_version: 1 }),
result: '1',
},
{
description: `model One (no features)`,
device: getSuiteDevice({ type: 'unacquired' }),
device: getSuiteDevice(undefined, { model: '1' }),
result: '1',
},
];

View File

@@ -92,7 +92,7 @@ export const Recovery = ({ onCancel }: ForegroundAppProps) => {
actions.checkSeed();
};
const model = device ? getDeviceModel(device) : 'T';
const model = device && getDeviceModel(device) === '1' ? '1' : 'T';
const learnMoreUrl = getCheckBackupUrl(device);
const isModelOne = model === '1';
const statesInProgressBar = isModelOne