diff --git a/src/SmartTransactionsController.test.ts b/src/SmartTransactionsController.test.ts index 19f423d..a84eadb 100644 --- a/src/SmartTransactionsController.test.ts +++ b/src/SmartTransactionsController.test.ts @@ -413,6 +413,13 @@ describe('SmartTransactionsController', () => { throw new Error('Invalid network client id'); } }), + getMetaMetricsProps: jest.fn(async () => { + return Promise.resolve({ + accountHardwareType: 'Ledger Hardware', + accountType: 'hardware', + deviceModel: 'ledger', + }); + }), }); // eslint-disable-next-line jest/prefer-spy-on smartTransactionsController.subscribe = jest.fn(); @@ -761,17 +768,22 @@ describe('SmartTransactionsController', () => { `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, ) .reply(200, submitTransactionsApiResponse); - await smartTransactionsController.submitSignedTransactions({ signedTransactions: [signedTransaction], signedCanceledTransactions: [signedCanceledTransaction], txParams: createTxParams(), }); - - expect( + const submittedSmartTransaction = smartTransactionsController.state.smartTransactionsState - .smartTransactions[ChainId.mainnet][0].uuid, - ).toBe('dP23W7c2kt4FK9TmXOkz1UM2F20'); + .smartTransactions[ChainId.mainnet][0]; + expect(submittedSmartTransaction.uuid).toBe( + 'dP23W7c2kt4FK9TmXOkz1UM2F20', + ); + expect(submittedSmartTransaction.accountHardwareType).toBe( + 'Ledger Hardware', + ); + expect(submittedSmartTransaction.accountType).toBe('hardware'); + expect(submittedSmartTransaction.deviceModel).toBe('ledger'); }); }); diff --git a/src/SmartTransactionsController.ts b/src/SmartTransactionsController.ts index 523d8b6..3682b45 100644 --- a/src/SmartTransactionsController.ts +++ b/src/SmartTransactionsController.ts @@ -28,6 +28,7 @@ import type { SmartTransactionsStatus, UnsignedTransaction, GetTransactionsOptions, + MetaMetricsProps, } from './types'; import { APIType, SmartTransactionStatuses } from './types'; import { @@ -42,6 +43,7 @@ import { snapshotFromTxMeta, getTxHash, getSmartTransactionMetricsProperties, + getSmartTransactionMetricsSensitiveProperties, } from './utils'; const SECOND = 1000; @@ -100,6 +102,8 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo private readonly getNetworkClientById: NetworkController['getNetworkClientById']; + private readonly getMetaMetricsProps: () => Promise; + /* istanbul ignore next */ private async fetch(request: string, options?: RequestInit) { const { clientId } = this.config; @@ -123,6 +127,7 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo getTransactions, trackMetaMetricsEvent, getNetworkClientById, + getMetaMetricsProps, }: { onNetworkStateChange: ( listener: (networkState: NetworkState) => void, @@ -133,6 +138,7 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo getTransactions: (options?: GetTransactionsOptions) => TransactionMeta[]; trackMetaMetricsEvent: any; getNetworkClientById: NetworkController['getNetworkClientById']; + getMetaMetricsProps: () => Promise; }, config?: Partial, state?: Partial, @@ -181,6 +187,7 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo this.getRegularTransactions = getTransactions; this.trackMetaMetricsEvent = trackMetaMetricsEvent; this.getNetworkClientById = getNetworkClientById; + this.getMetaMetricsProps = getMetaMetricsProps; this.initializeSmartTransactionsForChainId(); this.#ensureUniqueSmartTransactions(); @@ -316,7 +323,9 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo this.trackMetaMetricsEvent({ event: MetaMetricsEventName.StxStatusUpdated, category: MetaMetricsEventCategory.Transactions, - properties: getSmartTransactionMetricsProperties(updatedSmartTransaction), + properties: getSmartTransactionMetricsProperties(smartTransaction), + sensitiveProperties: + getSmartTransactionMetricsSensitiveProperties(smartTransaction), }); } @@ -385,6 +394,16 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo }); } + async #addMetaMetricsPropsToNewSmartTransaction( + smartTransaction: SmartTransaction, + ) { + const metaMetricsProps = await this.getMetaMetricsProps(); + smartTransaction.accountHardwareType = + metaMetricsProps?.accountHardwareType; + smartTransaction.accountType = metaMetricsProps?.accountType; + smartTransaction.deviceModel = metaMetricsProps?.deviceModel; + } + async #createOrUpdateSmartTransaction( smartTransaction: SmartTransaction, { @@ -416,6 +435,7 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo ); if (isNewSmartTransaction) { + await this.#addMetaMetricsPropsToNewSmartTransaction(smartTransaction); // add smart transaction const cancelledNonceIndex = currentSmartTransactions?.findIndex( (stx: SmartTransaction) => @@ -588,6 +608,8 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo event: MetaMetricsEventName.StxConfirmed, category: MetaMetricsEventCategory.Transactions, properties: getSmartTransactionMetricsProperties(smartTransaction), + sensitiveProperties: + getSmartTransactionMetricsSensitiveProperties(smartTransaction), }); this.#updateSmartTransaction( { ...smartTransaction, confirmed: true }, @@ -625,18 +647,18 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo SmartTransactionsStatus >; - Object.entries(data).forEach(([uuid, stxStatus]) => { - const smartTransaction = { + for (const [uuid, stxStatus] of Object.entries(data)) { + const smartTransaction: SmartTransaction = { statusMetadata: stxStatus, status: calculateStatus(stxStatus), cancellable: isSmartTransactionCancellable(stxStatus), uuid, }; - this.#createOrUpdateSmartTransaction(smartTransaction, { + await this.#createOrUpdateSmartTransaction(smartTransaction, { chainId, ethQuery, }); - }); + } return data; } @@ -789,7 +811,7 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo }; try { - this.#createOrUpdateSmartTransaction( + await this.#createOrUpdateSmartTransaction( { chainId, nonceDetails, diff --git a/src/index.test.ts b/src/index.test.ts index fc44148..e421e2f 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -12,6 +12,9 @@ describe('default export', () => { getTransactions: jest.fn(), trackMetaMetricsEvent: jest.fn(), getNetworkClientById: jest.fn(), + getMetaMetricsProps: jest.fn(async () => { + return Promise.resolve({}); + }), }); expect(controller).toBeInstanceOf(SmartTransactionsController); jest.clearAllTimers(); diff --git a/src/types.ts b/src/types.ts index 000de03..861a581 100644 --- a/src/types.ts +++ b/src/types.ts @@ -94,6 +94,9 @@ export type SmartTransaction = { type?: string; confirmed?: boolean; cancellable?: boolean; + accountHardwareType?: string; + accountType?: string; + deviceModel?: string; }; export type Fee = { @@ -131,3 +134,9 @@ export type GetTransactionsOptions = { filterToCurrentNetwork?: boolean; limit?: number; }; + +export type MetaMetricsProps = { + accountHardwareType?: string; + accountType?: string; + deviceModel?: string; +}; diff --git a/src/utils.ts b/src/utils.ts index 69c67f4..2885206 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -237,8 +237,6 @@ export const getSmartTransactionMetricsProperties = ( const smartTransactionStatusMetadata = smartTransaction.statusMetadata; return { stx_status: smartTransaction.status, - token_from_symbol: smartTransaction.sourceTokenSymbol, - token_to_symbol: smartTransaction.destinationTokenSymbol, type: smartTransaction.type, processing_time: getStxProcessingTime(smartTransaction.time), is_smart_transaction: true, @@ -250,3 +248,18 @@ export const getSmartTransactionMetricsProperties = ( stx_proxied: smartTransactionStatusMetadata?.proxied, }; }; + +export const getSmartTransactionMetricsSensitiveProperties = ( + smartTransaction: SmartTransaction, +) => { + if (!smartTransaction) { + return {}; + } + return { + token_from_symbol: smartTransaction.sourceTokenSymbol, + token_to_symbol: smartTransaction.destinationTokenSymbol, + account_hardware_type: smartTransaction.accountHardwareType, + account_type: smartTransaction.accountType, + device_model: smartTransaction.deviceModel, + }; +};