Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export const refreshConfirmationEstimation: OnCronjobHandler = async () => {
transaction: interfaceContext.transaction,
scope: interfaceContext.scope,
origin: interfaceContext.origin,
account: interfaceContext.account,
});

const updatedInterfaceContextFinal =
Expand Down
116 changes: 116 additions & 0 deletions packages/snap/src/core/services/analytics/AnalyticsService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { Transaction } from '@metamask/keyring-api';
import { Network } from '../../constants/solana';
import { MOCK_SOLANA_KEYRING_ACCOUNT_0 } from '../../test/mocks/solana-keyring-accounts';
import logger from '../../utils/logger';
import { ScanStatus, SecurityAlertResponse } from '../transaction-scan/types';
import { AnalyticsService } from './AnalyticsService';

const mockSnapRequest = jest.fn();
Expand Down Expand Up @@ -293,6 +294,121 @@ describe('AnalyticsService', () => {
});
});

describe('trackEventSecurityAlertDetected', () => {
it('tracks security alert detected event', async () => {
const securityAlertResponse = SecurityAlertResponse.Warning;
const securityAlertReason = 'transfer_farming';
const securityAlertDescription =
"Substantial transfer of the account's assets to untrusted entities";

await analyticsService.trackEventSecurityAlertDetected(
mockAccount,
mockBase64Transaction,
mockOrigin,
mockScope,
securityAlertResponse,
securityAlertReason,
securityAlertDescription,
);

expect(loggerSpy).toHaveBeenCalledWith(
'[📣 AnalyticsService] Tracking event security alert detected',
);

expect(mockSnapRequest).toHaveBeenCalledWith({
method: 'snap_trackEvent',
params: {
event: {
event: 'Security Alert Detected',
properties: {
message: 'Snap security alert detected',
origin: mockOrigin,
account_id: mockAccount.id,
account_address: mockAccount.address,
account_type: mockAccount.type,
chain_id: mockScope,
security_alert_response: securityAlertResponse,
security_alert_reason: securityAlertReason,
security_alert_description: securityAlertDescription,
},
},
},
});
});
});

describe('trackEventSecurityScanCompleted', () => {
it('tracks security scan completed event with alerts detected', async () => {
const scanStatus = ScanStatus.SUCCESS;
const hasSecurityAlerts = true;

await analyticsService.trackEventSecurityScanCompleted(
mockAccount,
mockBase64Transaction,
mockOrigin,
mockScope,
scanStatus,
hasSecurityAlerts,
);

expect(loggerSpy).toHaveBeenCalledWith(
'[📣 AnalyticsService] Tracking event security scan completed',
);

expect(mockSnapRequest).toHaveBeenCalledWith({
method: 'snap_trackEvent',
params: {
event: {
event: 'Security Scan Completed',
properties: {
message: 'Snap security scan completed',
origin: mockOrigin,
account_id: mockAccount.id,
account_address: mockAccount.address,
account_type: mockAccount.type,
chain_id: mockScope,
scan_status: scanStatus,
has_security_alerts: hasSecurityAlerts,
},
},
},
});
});

it('tracks security scan completed event without alerts', async () => {
const scanStatus = ScanStatus.SUCCESS;
const hasSecurityAlerts = false;

await analyticsService.trackEventSecurityScanCompleted(
mockAccount,
mockBase64Transaction,
mockOrigin,
mockScope,
scanStatus,
hasSecurityAlerts,
);

expect(mockSnapRequest).toHaveBeenCalledWith({
method: 'snap_trackEvent',
params: {
event: {
event: 'Security Scan Completed',
properties: {
message: 'Snap security scan completed',
origin: mockOrigin,
account_id: mockAccount.id,
account_address: mockAccount.address,
account_type: mockAccount.type,
chain_id: mockScope,
scan_status: scanStatus,
has_security_alerts: hasSecurityAlerts,
},
},
},
});
});
});

describe('error handling', () => {
it('handles snap.request errors gracefully', async () => {
const error = new Error('Snap request failed');
Expand Down
76 changes: 75 additions & 1 deletion packages/snap/src/core/services/analytics/AnalyticsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import type { Transaction } from '@metamask/keyring-api';
import { assert } from '@metamask/superstruct';

import type { SolanaKeyringAccount } from '../../../entities';
import type { TransactionMetadata } from '../../constants/solana';
import type { Network, TransactionMetadata } from '../../constants/solana';
import logger from '../../utils/logger';
import { Base64Struct } from '../../validation/structs';
import type {
ScanStatus,
SecurityAlertResponse,
} from '../transaction-scan/types';

/**
* Service for tracking events related to transactions.
Expand Down Expand Up @@ -160,4 +164,74 @@ export class AnalyticsService {
},
});
}

async trackEventSecurityAlertDetected(
account: SolanaKeyringAccount,
base64EncodedTransaction: string,
origin: string,
scope: Network,
securityAlertResponse: SecurityAlertResponse,
securityAlertReason: string | null,
securityAlertDescription: string,
Comment thread
zone-live marked this conversation as resolved.
): Promise<void> {
this.#logger.log(
`[📣 AnalyticsService] Tracking event security alert detected`,
);

assert(base64EncodedTransaction, Base64Struct);

await snap.request({
method: 'snap_trackEvent',
params: {
event: {
event: 'Security Alert Detected',
properties: {
message: 'Snap security alert detected',
origin,
account_id: account.id,
account_address: account.address,
account_type: account.type,
chain_id: scope,
security_alert_response: securityAlertResponse,
security_alert_reason: securityAlertReason,
security_alert_description: securityAlertDescription,
},
},
},
});
}

async trackEventSecurityScanCompleted(
account: SolanaKeyringAccount,
base64EncodedTransaction: string,
origin: string,
scope: Network,
scanStatus: ScanStatus,
hasSecurityAlerts: boolean,
): Promise<void> {
this.#logger.log(
`[📣 AnalyticsService] Tracking event security scan completed`,
);

assert(base64EncodedTransaction, Base64Struct);

await snap.request({
method: 'snap_trackEvent',
params: {
event: {
event: 'Security Scan Completed',
properties: {
message: 'Snap security scan completed',
origin,
account_id: account.id,
account_address: account.address,
account_type: account.type,
chain_id: scope,
scan_status: scanStatus,
has_security_alerts: hasSecurityAlerts,
},
},
},
});
}
}
Loading
Loading