Skip to content

Commit bc07c0f

Browse files
authored
WalletLinkSigner Telemetry (#1669)
* wl signer * errors
1 parent 2f387e5 commit bc07c0f

File tree

5 files changed

+244
-38
lines changed

5 files changed

+244
-38
lines changed
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import { ActionType, AnalyticsEventImportance, ComponentType, logEvent } from '../logEvent.js';
2+
3+
export const logHandshakeStarted = ({
4+
method,
5+
correlationId,
6+
}: {
7+
method: string;
8+
correlationId: string | undefined;
9+
}) => {
10+
logEvent(
11+
'walletlink_signer.handshake.started',
12+
{
13+
action: ActionType.unknown,
14+
componentType: ComponentType.unknown,
15+
method,
16+
correlationId,
17+
},
18+
AnalyticsEventImportance.high
19+
);
20+
};
21+
22+
export const logHandshakeError = ({
23+
method,
24+
correlationId,
25+
errorMessage,
26+
}: {
27+
method: string;
28+
correlationId: string | undefined;
29+
errorMessage: string;
30+
}) => {
31+
logEvent(
32+
'walletlink_signer.handshake.error',
33+
{
34+
action: ActionType.error,
35+
componentType: ComponentType.unknown,
36+
method,
37+
correlationId,
38+
errorMessage,
39+
},
40+
AnalyticsEventImportance.high
41+
);
42+
};
43+
44+
export const logHandshakeCompleted = ({
45+
method,
46+
correlationId,
47+
}: {
48+
method: string;
49+
correlationId: string | undefined;
50+
}) => {
51+
logEvent(
52+
'walletlink_signer.handshake.completed',
53+
{
54+
action: ActionType.unknown,
55+
componentType: ComponentType.unknown,
56+
method,
57+
correlationId,
58+
},
59+
AnalyticsEventImportance.high
60+
);
61+
};
62+
63+
export const logRequestStarted = ({
64+
method,
65+
correlationId,
66+
}: {
67+
method: string;
68+
correlationId: string | undefined;
69+
}) => {
70+
logEvent(
71+
'walletlink_signer.request.started',
72+
{
73+
action: ActionType.unknown,
74+
componentType: ComponentType.unknown,
75+
method,
76+
correlationId,
77+
},
78+
AnalyticsEventImportance.high
79+
);
80+
};
81+
82+
export const logRequestError = ({
83+
method,
84+
correlationId,
85+
errorMessage,
86+
}: {
87+
method: string;
88+
correlationId: string | undefined;
89+
errorMessage: string;
90+
}) => {
91+
logEvent(
92+
'walletlink_signer.request.error',
93+
{
94+
action: ActionType.error,
95+
componentType: ComponentType.unknown,
96+
method,
97+
correlationId,
98+
errorMessage,
99+
},
100+
AnalyticsEventImportance.high
101+
);
102+
};
103+
104+
export const logRequestCompleted = ({
105+
method,
106+
correlationId,
107+
}: {
108+
method: string;
109+
correlationId: string | undefined;
110+
}) => {
111+
logEvent(
112+
'walletlink_signer.request.completed',
113+
{
114+
action: ActionType.unknown,
115+
componentType: ComponentType.unknown,
116+
method,
117+
correlationId,
118+
},
119+
AnalyticsEventImportance.high
120+
);
121+
};
122+
123+
export const logWalletLinkConnectionConnectionFailed = () => {
124+
logEvent(
125+
'walletlink_signer.walletlink_connection.connection_failed',
126+
{
127+
action: ActionType.measurement,
128+
componentType: ComponentType.unknown,
129+
},
130+
AnalyticsEventImportance.high
131+
);
132+
};
133+
134+
export const logWalletLinkConnectionFetchUnseenEventsFailed = () => {
135+
logEvent(
136+
'walletlink_signer.walletlink_connection.fetch_unseen_events_failed',
137+
{
138+
action: ActionType.measurement,
139+
componentType: ComponentType.unknown,
140+
},
141+
AnalyticsEventImportance.high
142+
);
143+
};

packages/wallet-sdk/src/sign/scw/SCWSigner.ts

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -97,36 +97,44 @@ export class SCWSigner implements Signer {
9797
async handshake(args: RequestArguments) {
9898
const correlationId = correlationIds.get(args);
9999
logHandshakeStarted({ method: args.method, correlationId });
100-
// Open the popup before constructing the request message.
101-
// This is to ensure that the popup is not blocked by some browsers (i.e. Safari)
102-
await this.communicator.waitForPopupLoaded?.();
103100

104-
const handshakeMessage = await this.createRequestMessage({
105-
handshake: {
106-
method: args.method,
107-
params: args.params ?? [],
108-
},
109-
}, correlationId);
110-
const response: RPCResponseMessage =
111-
await this.communicator.postRequestAndWaitForResponse(handshakeMessage);
101+
try {
102+
// Open the popup before constructing the request message.
103+
// This is to ensure that the popup is not blocked by some browsers (i.e. Safari)
104+
await this.communicator.waitForPopupLoaded?.();
105+
106+
const handshakeMessage = await this.createRequestMessage(
107+
{
108+
handshake: {
109+
method: args.method,
110+
params: args.params ?? [],
111+
},
112+
},
113+
correlationId
114+
);
115+
const response: RPCResponseMessage =
116+
await this.communicator.postRequestAndWaitForResponse(handshakeMessage);
117+
118+
// store peer's public key
119+
if ('failure' in response.content) {
120+
throw response.content.failure;
121+
}
112122

113-
// store peer's public key
114-
if ('failure' in response.content) {
123+
const peerPublicKey = await importKeyFromHexString('public', response.sender);
124+
await this.keyManager.setPeerPublicKey(peerPublicKey);
125+
126+
const decrypted = await this.decryptResponseMessage(response);
127+
128+
this.handleResponse(args, decrypted);
129+
logHandshakeCompleted({ method: args.method, correlationId });
130+
} catch (error) {
115131
logHandshakeError({
116132
method: args.method,
117133
correlationId,
118-
errorMessage: response.content.failure.message,
134+
errorMessage: parseErrorMessageFromAny(error),
119135
});
120-
throw response.content.failure;
136+
throw error;
121137
}
122-
123-
const peerPublicKey = await importKeyFromHexString('public', response.sender);
124-
await this.keyManager.setPeerPublicKey(peerPublicKey);
125-
126-
const decrypted = await this.decryptResponseMessage(response);
127-
128-
this.handleResponse(args, decrypted);
129-
logHandshakeCompleted({ method: args.method, correlationId });
130138
}
131139

132140
async request(request: RequestArguments) {

packages/wallet-sdk/src/sign/util.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ export async function fetchSignerType(params: {
3939
callback: ProviderEventCallback;
4040
}): Promise<SignerType> {
4141
const { communicator, metadata, handshakeRequest, callback } = params;
42-
listenForWalletLinkSessionRequest(communicator, metadata, callback).catch(() => {});
42+
listenForWalletLinkSessionRequest(communicator, metadata, callback, handshakeRequest).catch(
43+
() => {}
44+
);
4345

4446
const request: ConfigMessage & { id: MessageID } = {
4547
id: crypto.randomUUID(),
@@ -80,7 +82,8 @@ export function createSigner(params: {
8082
async function listenForWalletLinkSessionRequest(
8183
communicator: Communicator,
8284
metadata: AppMetadata,
83-
callback: ProviderEventCallback
85+
callback: ProviderEventCallback,
86+
handshakeRequest: RequestArguments
8487
) {
8588
await communicator.onMessage<ConfigMessage>(({ event }) => event === 'WalletLinkSessionRequest');
8689

@@ -98,7 +101,7 @@ async function listenForWalletLinkSessionRequest(
98101
} as ConfigMessage);
99102

100103
// wait for handshake to complete
101-
await walletlink.handshake();
104+
await walletlink.handshake(handshakeRequest);
102105

103106
// send connected status to popup
104107
communicator.postMessage({

packages/wallet-sdk/src/sign/walletlink/WalletLinkSigner.ts

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
// Copyright (c) 2018-2024 Coinbase, Inc. <https://www.coinbase.com/>
22

3-
// @ts-nocheck
4-
import eip712 from '../../vendor-js/eth-eip712-util/index.cjs';
5-
import { Signer } from '../interface.js';
6-
import { LOCAL_STORAGE_ADDRESSES_KEY } from './relay/constants.js';
7-
import { EthereumTransactionParams } from './relay/type/EthereumTransactionParams.js';
8-
import { isErrorResponse } from './relay/type/Web3Response.js';
9-
import { WalletLinkRelay } from './relay/WalletLinkRelay.js';
103
import { WALLETLINK_URL } from ':core/constants.js';
114
import { standardErrors } from ':core/error/errors.js';
125
import { AppMetadata, ProviderEventCallback, RequestArguments } from ':core/provider/interface.js';
136
import { ScopedLocalStorage } from ':core/storage/ScopedLocalStorage.js';
7+
import {
8+
logHandshakeCompleted,
9+
logHandshakeError,
10+
logHandshakeStarted,
11+
logRequestCompleted,
12+
logRequestError,
13+
logRequestStarted,
14+
} from ':core/telemetry/events/walletlink-signer.js';
15+
import { parseErrorMessageFromAny } from ':core/telemetry/utils.js';
1416
import { Address } from ':core/type/index.js';
1517
import {
1618
encodeToHexString,
@@ -22,7 +24,14 @@ import {
2224
hexStringFromBuffer,
2325
hexStringFromNumber,
2426
} from ':core/type/util.js';
27+
import { correlationIds } from ':store/correlation-ids/store.js';
2528
import { fetchRPCRequest } from ':util/provider.js';
29+
import eip712 from '../../vendor-js/eth-eip712-util/index.cjs';
30+
import { Signer } from '../interface.js';
31+
import { WalletLinkRelay } from './relay/WalletLinkRelay.js';
32+
import { LOCAL_STORAGE_ADDRESSES_KEY } from './relay/constants.js';
33+
import { EthereumTransactionParams } from './relay/type/EthereumTransactionParams.js';
34+
import { isErrorResponse } from './relay/type/Web3Response.js';
2635

2736
const DEFAULT_CHAIN_ID_KEY = 'DefaultChainId';
2837
const DEFAULT_JSON_RPC_URL = 'DefaultJsonRpcUrl';
@@ -44,7 +53,7 @@ export class WalletLinkSigner implements Signer {
4453

4554
const cachedAddresses = this._storage.getItem(LOCAL_STORAGE_ADDRESSES_KEY);
4655
if (cachedAddresses) {
47-
const addresses = cachedAddresses.split(' ') as Address[];
56+
const addresses = cachedAddresses.split(' ') as string[];
4857
if (addresses[0] !== '') {
4958
this._addresses = addresses.map((address) => ensureAddressString(address));
5059
}
@@ -59,8 +68,28 @@ export class WalletLinkSigner implements Signer {
5968
return { id, secret };
6069
}
6170

62-
async handshake() {
63-
await this._eth_requestAccounts();
71+
async handshake(args: RequestArguments) {
72+
// only eth_requestAccounts is supported for handshake in WalletLink
73+
const method = 'eth_requestAccounts';
74+
const correlationId = correlationIds.get(args);
75+
logHandshakeStarted({
76+
method,
77+
correlationId,
78+
});
79+
try {
80+
await this._eth_requestAccounts();
81+
logHandshakeCompleted({
82+
method,
83+
correlationId,
84+
});
85+
} catch (error) {
86+
logHandshakeError({
87+
method,
88+
correlationId,
89+
errorMessage: parseErrorMessageFromAny(error),
90+
});
91+
throw error;
92+
}
6493
}
6594

6695
private get selectedAddress(): Address | undefined {
@@ -238,6 +267,24 @@ export class WalletLinkSigner implements Signer {
238267
}
239268

240269
async request(request: RequestArguments) {
270+
const correlationId = correlationIds.get(request);
271+
logRequestStarted({ method: request.method, correlationId });
272+
273+
try {
274+
const result = await this._request(request);
275+
logRequestCompleted({ method: request.method, correlationId });
276+
return result;
277+
} catch (error) {
278+
logRequestError({
279+
method: request.method,
280+
correlationId,
281+
errorMessage: parseErrorMessageFromAny(error),
282+
});
283+
throw error;
284+
}
285+
}
286+
287+
private async _request(request: RequestArguments) {
241288
const params = (request.params as RequestParam) || [];
242289

243290
switch (request.method) {

packages/wallet-sdk/src/sign/walletlink/relay/connection/WalletLinkConnection.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
// Copyright (c) 2018-2023 Coinbase, Inc. <https://www.coinbase.com/>
22

3+
import {
4+
logWalletLinkConnectionConnectionFailed,
5+
logWalletLinkConnectionFetchUnseenEventsFailed,
6+
} from ':core/telemetry/events/walletlink-signer.js';
37
import { IntNumber } from ':core/type/index.js';
48
import { APP_VERSION_KEY, WALLET_USER_NAME_KEY } from '../constants.js';
59
import { ClientMessage } from '../type/ClientMessage.js';
@@ -133,6 +137,7 @@ export class WalletLinkConnection {
133137
.connect()
134138
.catch(() => {
135139
// Reconnection failed, will retry
140+
logWalletLinkConnectionConnectionFailed();
136141
})
137142
.finally(() => {
138143
this.isReconnecting = false;
@@ -289,6 +294,7 @@ export class WalletLinkConnection {
289294
this.ws = this.createWebSocket();
290295
this.ws.connect().catch(() => {
291296
// Fresh reconnection failed
297+
logWalletLinkConnectionConnectionFailed();
292298
});
293299
}
294300

@@ -373,8 +379,6 @@ export class WalletLinkConnection {
373379
this.listener?.linkedUpdated(linked);
374380
}
375381

376-
377-
378382
/**
379383
* Execute once when linked
380384
*/
@@ -428,6 +432,7 @@ export class WalletLinkConnection {
428432
});
429433
} catch (_error) {
430434
// Failed to fetch unseen events
435+
logWalletLinkConnectionFetchUnseenEventsFailed();
431436
}
432437
}
433438

0 commit comments

Comments
 (0)