Skip to content

Commit 5c6b411

Browse files
authored
Sub Account Flow Telemetry (#1662)
* sub account flow * optional cor-id
1 parent 1511578 commit 5c6b411

File tree

12 files changed

+372
-29
lines changed

12 files changed

+372
-29
lines changed

packages/wallet-sdk/src/CoinbaseWalletProvider.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from ':core/provider/interface.js';
1515
import { ScopedLocalStorage } from ':core/storage/ScopedLocalStorage.js';
1616
import {
17+
logEnableFunctionCalled,
1718
logRequestError,
1819
logRequestResponded,
1920
logRequestStarted,
@@ -162,6 +163,7 @@ export class CoinbaseWalletProvider extends ProviderEventEmitter implements Prov
162163
console.warn(
163164
`.enable() has been deprecated. Please use .request({ method: "eth_requestAccounts" }) instead.`
164165
);
166+
logEnableFunctionCalled();
165167
return await this.request({
166168
method: 'eth_requestAccounts',
167169
});

packages/wallet-sdk/src/core/telemetry/events/provider.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export const logSignerLoadedFromStorage = ({ signerType }: { signerType: SignerT
55
logEvent(
66
'provider.signer.loaded_from_storage',
77
{
8-
action: ActionType.unknown,
8+
action: ActionType.measurement,
99
componentType: ComponentType.unknown,
1010
signerType,
1111
},
@@ -46,7 +46,7 @@ export const logRequestError = ({
4646
logEvent(
4747
'provider.request.error',
4848
{
49-
action: ActionType.unknown,
49+
action: ActionType.error,
5050
componentType: ComponentType.unknown,
5151
method,
5252
signerType,
@@ -78,3 +78,14 @@ export const logRequestResponded = ({
7878
AnalyticsEventImportance.high
7979
);
8080
};
81+
82+
export const logEnableFunctionCalled = () => {
83+
logEvent(
84+
'provider.enable_function.called',
85+
{
86+
action: ActionType.measurement,
87+
componentType: ComponentType.unknown,
88+
},
89+
AnalyticsEventImportance.high
90+
);
91+
};

packages/wallet-sdk/src/core/telemetry/events/scw-signer.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { store } from ':store/store.js';
12
import { ActionType, AnalyticsEventImportance, ComponentType, logEvent } from '../logEvent.js';
23

34
export const logHandshakeStarted = ({
@@ -14,6 +15,7 @@ export const logHandshakeStarted = ({
1415
componentType: ComponentType.unknown,
1516
method,
1617
correlationId,
18+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
1719
},
1820
AnalyticsEventImportance.high
1921
);
@@ -31,11 +33,12 @@ export const logHandshakeError = ({
3133
logEvent(
3234
'scw_signer.handshake.error',
3335
{
34-
action: ActionType.unknown,
36+
action: ActionType.error,
3537
componentType: ComponentType.unknown,
3638
method,
3739
correlationId,
3840
errorMessage,
41+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
3942
},
4043
AnalyticsEventImportance.high
4144
);
@@ -55,6 +58,7 @@ export const logHandshakeCompleted = ({
5558
componentType: ComponentType.unknown,
5659
method,
5760
correlationId,
61+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
5862
},
5963
AnalyticsEventImportance.high
6064
);
@@ -74,6 +78,7 @@ export const logRequestStarted = ({
7478
componentType: ComponentType.unknown,
7579
method,
7680
correlationId,
81+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
7782
},
7883
AnalyticsEventImportance.high
7984
);
@@ -91,11 +96,12 @@ export const logRequestError = ({
9196
logEvent(
9297
'scw_signer.request.error',
9398
{
94-
action: ActionType.unknown,
99+
action: ActionType.error,
95100
componentType: ComponentType.unknown,
96101
method,
97102
correlationId,
98103
errorMessage,
104+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
99105
},
100106
AnalyticsEventImportance.high
101107
);
@@ -115,6 +121,7 @@ export const logRequestCompleted = ({
115121
componentType: ComponentType.unknown,
116122
method,
117123
correlationId,
124+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
118125
},
119126
AnalyticsEventImportance.high
120127
);
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
import { store } from ':store/store.js';
2+
import { ActionType, AnalyticsEventImportance, ComponentType, logEvent } from '../logEvent.js';
3+
4+
export const logSubAccountRequestStarted = ({
5+
method,
6+
correlationId,
7+
}: {
8+
method: string;
9+
correlationId: string | undefined;
10+
}) => {
11+
logEvent(
12+
'scw_sub_account.request.started',
13+
{
14+
action: ActionType.unknown,
15+
componentType: ComponentType.unknown,
16+
method,
17+
correlationId,
18+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
19+
},
20+
AnalyticsEventImportance.high
21+
);
22+
};
23+
24+
export const logSubAccountRequestCompleted = ({
25+
method,
26+
correlationId,
27+
}: {
28+
method: string;
29+
correlationId: string | undefined;
30+
}) => {
31+
logEvent(
32+
'scw_sub_account.request.completed',
33+
{
34+
action: ActionType.unknown,
35+
componentType: ComponentType.unknown,
36+
method,
37+
correlationId,
38+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
39+
},
40+
AnalyticsEventImportance.high
41+
);
42+
};
43+
44+
export const logSubAccountRequestError = ({
45+
method,
46+
correlationId,
47+
errorMessage,
48+
}: {
49+
method: string;
50+
correlationId: string | undefined;
51+
errorMessage: string;
52+
}) => {
53+
logEvent(
54+
'scw_sub_account.request.error',
55+
{
56+
action: ActionType.error,
57+
componentType: ComponentType.unknown,
58+
method,
59+
correlationId,
60+
errorMessage,
61+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
62+
},
63+
AnalyticsEventImportance.high
64+
);
65+
};
66+
67+
export const logAddOwnerStarted = ({
68+
method,
69+
correlationId,
70+
}: {
71+
method: string;
72+
correlationId: string | undefined;
73+
}) => {
74+
logEvent(
75+
'scw_sub_account.add_owner.started',
76+
{
77+
action: ActionType.unknown,
78+
componentType: ComponentType.unknown,
79+
method,
80+
correlationId,
81+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
82+
},
83+
AnalyticsEventImportance.high
84+
);
85+
};
86+
87+
export const logAddOwnerCompleted = ({
88+
method,
89+
correlationId,
90+
}: {
91+
method: string;
92+
correlationId: string | undefined;
93+
}) => {
94+
logEvent(
95+
'scw_sub_account.add_owner.completed',
96+
{
97+
action: ActionType.unknown,
98+
componentType: ComponentType.unknown,
99+
method,
100+
correlationId,
101+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
102+
},
103+
AnalyticsEventImportance.high
104+
);
105+
};
106+
107+
export const logAddOwnerError = ({
108+
method,
109+
correlationId,
110+
errorMessage,
111+
}: {
112+
method: string;
113+
correlationId: string | undefined;
114+
errorMessage: string;
115+
}) => {
116+
logEvent(
117+
'scw_sub_account.add_owner.error',
118+
{
119+
action: ActionType.error,
120+
componentType: ComponentType.unknown,
121+
method,
122+
correlationId,
123+
errorMessage,
124+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
125+
},
126+
AnalyticsEventImportance.high
127+
);
128+
};
129+
130+
export const logInsufficientBalanceErrorHandlingStarted = ({
131+
method,
132+
correlationId,
133+
}: {
134+
method: string;
135+
correlationId: string | undefined;
136+
}) => {
137+
logEvent(
138+
'scw_sub_account.insufficient_balance.error_handling.started',
139+
{
140+
action: ActionType.unknown,
141+
componentType: ComponentType.unknown,
142+
method,
143+
correlationId,
144+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
145+
},
146+
AnalyticsEventImportance.high
147+
);
148+
};
149+
150+
export const logInsufficientBalanceErrorHandlingCompleted = ({
151+
method,
152+
correlationId,
153+
}: {
154+
method: string;
155+
correlationId: string | undefined;
156+
}) => {
157+
logEvent(
158+
'scw_sub_account.insufficient_balance.error_handling.completed',
159+
{
160+
action: ActionType.unknown,
161+
componentType: ComponentType.unknown,
162+
method,
163+
correlationId,
164+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
165+
},
166+
AnalyticsEventImportance.high
167+
);
168+
};
169+
170+
export const logInsufficientBalanceErrorHandlingError = ({
171+
method,
172+
correlationId,
173+
errorMessage,
174+
}: {
175+
method: string;
176+
correlationId: string | undefined;
177+
errorMessage: string;
178+
}) => {
179+
logEvent(
180+
'scw_sub_account.insufficient_balance.error_handling.error',
181+
{
182+
action: ActionType.error,
183+
componentType: ComponentType.unknown,
184+
method,
185+
correlationId,
186+
errorMessage,
187+
enableAutoSubAccounts: store.subAccountsConfig.get()?.enableAutoSubAccounts,
188+
},
189+
AnalyticsEventImportance.high
190+
);
191+
};
Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { ActionType, AnalyticsEventImportance, ComponentType, logEvent } from '../logEvent.js';
22

3-
type SnackbarContext = 'popup_blocked';
3+
type SnackbarContext =
4+
| 'popup_blocked'
5+
| 'sub_account_add_owner'
6+
| 'sub_account_insufficient_balance';
47

58
export const logSnackbarShown = ({ snackbarContext }: { snackbarContext: SnackbarContext }) => {
69
logEvent(
7-
'snackbar.shown',
10+
`snackbar.${snackbarContext}.shown`,
811
{
912
action: ActionType.render,
1013
componentType: ComponentType.modal,
@@ -13,3 +16,25 @@ export const logSnackbarShown = ({ snackbarContext }: { snackbarContext: Snackba
1316
AnalyticsEventImportance.high
1417
);
1518
};
19+
20+
type GenericSnackbarAction = 'confirm' | 'cancel';
21+
type SubAccountInsufficientBalanceSnackbarAction = 'create_permission' | 'continue_in_popup';
22+
23+
export const logSnackbarActionClicked = ({
24+
snackbarContext,
25+
snackbarAction,
26+
}: {
27+
snackbarContext: SnackbarContext;
28+
snackbarAction: GenericSnackbarAction | SubAccountInsufficientBalanceSnackbarAction;
29+
}) => {
30+
logEvent(
31+
`snackbar.${snackbarContext}.action_clicked`,
32+
{
33+
action: ActionType.click,
34+
componentType: ComponentType.button,
35+
snackbarContext,
36+
snackbarAction,
37+
},
38+
AnalyticsEventImportance.high
39+
);
40+
};

packages/wallet-sdk/src/core/telemetry/logEvent.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ type CCAEventData = {
6363
correlationId?: string;
6464
errorMessage?: string;
6565
snackbarContext?: string;
66+
snackbarAction?: string;
67+
enableAutoSubAccounts?: boolean;
6668
};
6769

6870
type AnalyticsEventData = {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { parseErrorMessageFromAny } from './utils.js';
2+
3+
describe('parseErrorMessageFromAny', () => {
4+
it('should return message when object has string message property', () => {
5+
const error = { message: 'Something went wrong' };
6+
expect(parseErrorMessageFromAny(error)).toBe('Something went wrong');
7+
});
8+
9+
it('should return message from Error objects', () => {
10+
const error = new Error('Network error');
11+
expect(parseErrorMessageFromAny(error)).toBe('Network error');
12+
});
13+
14+
it('should return message from custom error objects', () => {
15+
const error = { name: 'CustomError', message: 'Custom error message' };
16+
expect(parseErrorMessageFromAny(error)).toBe('Custom error message');
17+
});
18+
19+
it('should return empty string when message is empty string', () => {
20+
const error = { message: '' };
21+
expect(parseErrorMessageFromAny(error)).toBe('');
22+
});
23+
24+
it('should return empty string when message is undefined', () => {
25+
const error = { message: undefined };
26+
expect(parseErrorMessageFromAny(error)).toBe('');
27+
});
28+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// biome-ignore lint/suspicious/noExplicitAny: this is used in a catch block
2+
export const parseErrorMessageFromAny = (errorOrAny: any): string => {
3+
return 'message' in errorOrAny && typeof errorOrAny.message === 'string'
4+
? errorOrAny.message
5+
: '';
6+
};

0 commit comments

Comments
 (0)