@aztec/wallet-sdk 0.0.1-commit.b2a5d0dd1 → 0.0.1-commit.b3d3157a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +125 -0
  2. package/dest/base-wallet/base_wallet.d.ts +11 -2
  3. package/dest/base-wallet/base_wallet.d.ts.map +1 -1
  4. package/dest/base-wallet/base_wallet.js +28 -8
  5. package/dest/base-wallet/utils.d.ts +5 -3
  6. package/dest/base-wallet/utils.d.ts.map +1 -1
  7. package/dest/base-wallet/utils.js +8 -4
  8. package/dest/extension/handlers/background_connection_handler.d.ts +12 -2
  9. package/dest/extension/handlers/background_connection_handler.d.ts.map +1 -1
  10. package/dest/extension/handlers/background_connection_handler.js +44 -8
  11. package/dest/extension/handlers/content_script_connection_handler.d.ts +2 -1
  12. package/dest/extension/handlers/content_script_connection_handler.d.ts.map +1 -1
  13. package/dest/extension/handlers/content_script_connection_handler.js +19 -0
  14. package/dest/extension/handlers/internal_message_types.d.ts +3 -1
  15. package/dest/extension/handlers/internal_message_types.d.ts.map +1 -1
  16. package/dest/extension/handlers/internal_message_types.js +3 -1
  17. package/dest/extension/provider/extension_wallet.d.ts +26 -3
  18. package/dest/extension/provider/extension_wallet.d.ts.map +1 -1
  19. package/dest/extension/provider/extension_wallet.js +80 -9
  20. package/dest/iframe/handlers/iframe_connection_handler.d.ts +6 -2
  21. package/dest/iframe/handlers/iframe_connection_handler.d.ts.map +1 -1
  22. package/dest/iframe/handlers/iframe_connection_handler.js +18 -7
  23. package/dest/iframe/provider/iframe_wallet.d.ts +20 -3
  24. package/dest/iframe/provider/iframe_wallet.d.ts.map +1 -1
  25. package/dest/iframe/provider/iframe_wallet.js +79 -10
  26. package/dest/types.d.ts +52 -2
  27. package/dest/types.d.ts.map +1 -1
  28. package/dest/types.js +25 -0
  29. package/package.json +8 -8
  30. package/src/base-wallet/base_wallet.ts +29 -5
  31. package/src/base-wallet/utils.ts +9 -1
  32. package/src/extension/handlers/background_connection_handler.ts +42 -9
  33. package/src/extension/handlers/content_script_connection_handler.ts +18 -0
  34. package/src/extension/handlers/internal_message_types.ts +2 -0
  35. package/src/extension/provider/extension_wallet.ts +94 -8
  36. package/src/iframe/handlers/iframe_connection_handler.ts +21 -8
  37. package/src/iframe/provider/iframe_wallet.ts +103 -9
  38. package/src/types.ts +59 -0
@@ -8,9 +8,9 @@
8
8
  */ import { WalletSchema } from '@aztec/aztec.js/wallet';
9
9
  import { jsonStringify } from '@aztec/foundation/json-rpc';
10
10
  import { promiseWithResolvers } from '@aztec/foundation/promise';
11
- import { schemaHasMethod } from '@aztec/foundation/schemas';
11
+ import { getSchemaReturnType, schemaHasMethod } from '@aztec/foundation/schemas';
12
12
  import { decrypt, encrypt } from '../../crypto.js';
13
- import { WalletMessageType } from '../../types.js';
13
+ import { DEFAULT_HEARTBEAT_DEAD_AFTER_MS, DEFAULT_HEARTBEAT_INTERVAL_MS, NOOP_LOGGER, WalletMessageType } from '../../types.js';
14
14
  /**
15
15
  * A wallet implementation that communicates with a web wallet loaded in an iframe
16
16
  * using encrypted postMessage.
@@ -36,7 +36,12 @@ import { WalletMessageType } from '../../types.js';
36
36
  disconnected;
37
37
  disconnectCallbacks;
38
38
  messageListener;
39
- constructor(chainInfo, appId, walletId, sessionId, iframeWindow, walletOrigin, sharedKey){
39
+ heartbeatTimer;
40
+ lastInboundAt;
41
+ log;
42
+ heartbeatIntervalMs;
43
+ heartbeatDeadAfterMs;
44
+ constructor(chainInfo, appId, walletId, sessionId, iframeWindow, walletOrigin, sharedKey, logger, heartbeatOptions){
40
45
  this.chainInfo = chainInfo;
41
46
  this.appId = appId;
42
47
  this.walletId = walletId;
@@ -48,6 +53,11 @@ import { WalletMessageType } from '../../types.js';
48
53
  this.disconnected = false;
49
54
  this.disconnectCallbacks = [];
50
55
  this.messageListener = null;
56
+ this.heartbeatTimer = null;
57
+ this.lastInboundAt = 0;
58
+ this.log = logger ?? NOOP_LOGGER;
59
+ this.heartbeatIntervalMs = heartbeatOptions?.intervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;
60
+ this.heartbeatDeadAfterMs = heartbeatOptions?.deadAfterMs ?? DEFAULT_HEARTBEAT_DEAD_AFTER_MS;
51
61
  }
52
62
  /**
53
63
  * Creates a proxied IframeWallet that implements the {@link Wallet} interface.
@@ -63,9 +73,11 @@ import { WalletMessageType } from '../../types.js';
63
73
  * @param sharedKey - AES-256-GCM key derived from ECDH key exchange
64
74
  * @param chainInfo - Network information (chainId and version)
65
75
  * @param appId - Application identifier for the requesting dApp
76
+ * @param logger - Optional logger; defaults to a no-op logger to keep extension/page bundles small
77
+ * @param heartbeatOptions - Optional override for heartbeat tuning (mostly useful for tests)
66
78
  * @returns A proxied IframeWallet — call `.asWallet()` to get the typed `Wallet`
67
- */ static create(walletId, sessionId, iframeWindow, walletOrigin, sharedKey, chainInfo, appId) {
68
- const wallet = new IframeWallet(chainInfo, appId, walletId, sessionId, iframeWindow, walletOrigin, sharedKey);
79
+ */ static create(walletId, sessionId, iframeWindow, walletOrigin, sharedKey, chainInfo, appId, logger, heartbeatOptions) {
80
+ const wallet = new IframeWallet(chainInfo, appId, walletId, sessionId, iframeWindow, walletOrigin, sharedKey, logger, heartbeatOptions);
69
81
  wallet.messageListener = (event)=>{
70
82
  if (event.origin !== walletOrigin) {
71
83
  return;
@@ -74,9 +86,14 @@ import { WalletMessageType } from '../../types.js';
74
86
  if (!msg || typeof msg !== 'object') {
75
87
  return;
76
88
  }
77
- if (msg.type === WalletMessageType.SECURE_RESPONSE && msg.sessionId === sessionId) {
89
+ if (msg.sessionId !== sessionId) {
90
+ return;
91
+ }
92
+ // Any inbound traffic on our session counts as proof of liveness.
93
+ wallet.lastInboundAt = Date.now();
94
+ if (msg.type === WalletMessageType.SECURE_RESPONSE) {
78
95
  void wallet.handleEncryptedResponse(msg.encrypted);
79
- } else if (msg.type === WalletMessageType.SESSION_DISCONNECTED && msg.sessionId === sessionId) {
96
+ } else if (msg.type === WalletMessageType.SESSION_DISCONNECTED) {
80
97
  wallet.handleDisconnect();
81
98
  }
82
99
  };
@@ -91,7 +108,7 @@ import { WalletMessageType } from '../../types.js';
91
108
  type: prop.toString(),
92
109
  args
93
110
  });
94
- return WalletSchema[prop.toString()].returnType().parseAsync(result);
111
+ return getSchemaReturnType(WalletSchema[prop.toString()]).parseAsync(result);
95
112
  };
96
113
  } else {
97
114
  return target[prop];
@@ -122,8 +139,11 @@ import { WalletMessageType } from '../../types.js';
122
139
  pending.resolve(result);
123
140
  }
124
141
  this.inFlight.delete(messageId);
125
- } catch {
126
- // Decryption errors are silently ignored (message not for us or corrupted)
142
+ this.maybeStopHeartbeat();
143
+ } catch (err) {
144
+ this.log.warn('Failed to decrypt wallet response', {
145
+ err
146
+ });
127
147
  }
128
148
  }
129
149
  async postMessage(call) {
@@ -151,13 +171,62 @@ import { WalletMessageType } from '../../types.js';
151
171
  resolve,
152
172
  reject
153
173
  });
174
+ this.startHeartbeat();
154
175
  return promise;
155
176
  }
177
+ /**
178
+ * Start liveness probing while at least one request is in flight. PINGs are
179
+ * unencrypted control messages — older wallet handlers that don't understand
180
+ * them simply drop them, but any inbound traffic (PONG, encrypted response,
181
+ * disconnect notice) resets the idle timer, so a slow-but-alive legacy wallet
182
+ * never trips a false disconnect.
183
+ */ startHeartbeat() {
184
+ if (this.heartbeatTimer !== null || this.disconnected) {
185
+ return;
186
+ }
187
+ this.lastInboundAt = Date.now();
188
+ this.heartbeatTimer = setInterval(()=>this.heartbeatTick(), this.heartbeatIntervalMs);
189
+ }
190
+ maybeStopHeartbeat() {
191
+ if (this.inFlight.size === 0 && this.heartbeatTimer !== null) {
192
+ clearInterval(this.heartbeatTimer);
193
+ this.heartbeatTimer = null;
194
+ }
195
+ }
196
+ heartbeatTick() {
197
+ if (this.disconnected || this.inFlight.size === 0) {
198
+ this.maybeStopHeartbeat();
199
+ return;
200
+ }
201
+ const idleMs = Date.now() - this.lastInboundAt;
202
+ if (idleMs >= this.heartbeatDeadAfterMs) {
203
+ this.log.warn('Iframe wallet channel unresponsive — declaring disconnect', {
204
+ idleMs,
205
+ inFlight: this.inFlight.size
206
+ });
207
+ this.handleDisconnect();
208
+ return;
209
+ }
210
+ try {
211
+ this.iframeWindow.postMessage({
212
+ type: WalletMessageType.PING,
213
+ sessionId: this.sessionId
214
+ }, this.walletOrigin);
215
+ } catch (err) {
216
+ this.log.warn('Failed to send heartbeat PING', {
217
+ err
218
+ });
219
+ }
220
+ }
156
221
  handleDisconnect() {
157
222
  if (this.disconnected) {
158
223
  return;
159
224
  }
160
225
  this.disconnected = true;
226
+ if (this.heartbeatTimer !== null) {
227
+ clearInterval(this.heartbeatTimer);
228
+ this.heartbeatTimer = null;
229
+ }
161
230
  if (this.messageListener) {
162
231
  window.removeEventListener('message', this.messageListener);
163
232
  this.messageListener = null;
package/dest/types.d.ts CHANGED
@@ -22,7 +22,14 @@ export declare enum WalletMessageType {
22
22
  /** Encrypted wallet response wrapper */
23
23
  SECURE_RESPONSE = "aztec-wallet-secure-response",
24
24
  /** Session disconnected notification */
25
- SESSION_DISCONNECTED = "aztec-wallet-session-disconnected"
25
+ SESSION_DISCONNECTED = "aztec-wallet-session-disconnected",
26
+ /** Liveness probe sent by the dApp while a request is in flight */
27
+ PING = "aztec-wallet-ping",
28
+ /** Liveness response from the wallet. Any inbound message (including a regular
29
+ * encrypted response) is treated as proof of liveness, so a missing PONG alone
30
+ * never trips disconnect — the dApp also resets its liveness timer on traffic.
31
+ */
32
+ PONG = "aztec-wallet-pong"
26
33
  }
27
34
  /**
28
35
  * Information about an installed Aztec wallet.
@@ -132,4 +139,47 @@ export interface KeyExchangeResponse {
132
139
  * Callback invoked when a wallet connection is disconnected.
133
140
  */
134
141
  export type DisconnectCallback = () => void;
135
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV6RCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVyRDs7O0dBR0c7QUFDSCxvQkFBWSxpQkFBaUI7SUFDM0Isa0RBQWtEO0lBQ2xELFNBQVMsMkJBQTJCO0lBQ3BDLHVDQUF1QztJQUN2QyxrQkFBa0Isb0NBQW9DO0lBQ3RELHNFQUFzRTtJQUN0RSxVQUFVLDRCQUE0QjtJQUN0QyxvREFBb0Q7SUFDcEQsb0JBQW9CLHNDQUFzQztJQUMxRCxxREFBcUQ7SUFDckQscUJBQXFCLHVDQUF1QztJQUM1RCwwQkFBMEI7SUFDMUIsWUFBWSx1QkFBdUI7SUFDbkMsdUNBQXVDO0lBQ3ZDLGNBQWMsZ0NBQWdDO0lBQzlDLHdDQUF3QztJQUN4QyxlQUFlLGlDQUFpQztJQUNoRCx3Q0FBd0M7SUFDeEMsb0JBQW9CLHNDQUFzQztDQUMzRDtBQUVEOzs7R0FHRztBQUNILE1BQU0sV0FBVyxVQUFVO0lBQ3pCLHVDQUF1QztJQUN2QyxFQUFFLEVBQUUsTUFBTSxDQUFDO0lBQ1gsaUNBQWlDO0lBQ2pDLElBQUksRUFBRSxNQUFNLENBQUM7SUFDYiwrQkFBK0I7SUFDL0IsSUFBSSxDQUFDLEVBQUUsTUFBTSxDQUFDO0lBQ2QscUJBQXFCO0lBQ3JCLE9BQU8sRUFBRSxNQUFNLENBQUM7Q0FDakI7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFdBQVcsbUJBQW9CLFNBQVEsVUFBVTtJQUNyRCxnRUFBZ0U7SUFDaEUsU0FBUyxFQUFFLGlCQUFpQixDQUFDO0lBQzdCOzs7O09BSUc7SUFDSCxnQkFBZ0IsQ0FBQyxFQUFFLE1BQU0sQ0FBQztDQUMzQjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxXQUFXLGFBQWE7SUFDNUIsK0NBQStDO0lBQy9DLFNBQVMsRUFBRSxNQUFNLENBQUM7SUFDbEIsZ0NBQWdDO0lBQ2hDLElBQUksRUFBRSxNQUFNLENBQUM7SUFDYiwrQkFBK0I7SUFDL0IsSUFBSSxFQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ2hCLHdCQUF3QjtJQUN4QixTQUFTLEVBQUUsU0FBUyxDQUFDO0lBQ3JCLHdDQUF3QztJQUN4QyxLQUFLLEVBQUUsTUFBTSxDQUFDO0lBQ2QsNENBQTRDO0lBQzVDLFFBQVEsRUFBRSxNQUFNLENBQUM7Q0FDbEI7QUFFRDs7R0FFRztBQUNILE1BQU0sV0FBVyxjQUFjO0lBQzdCLHNDQUFzQztJQUN0QyxTQUFTLEVBQUUsTUFBTSxDQUFDO0lBQ2xCLGtDQUFrQztJQUNsQyxNQUFNLENBQUMsRUFBRSxPQUFPLENBQUM7SUFDakIsNkJBQTZCO0lBQzdCLEtBQUssQ0FBQyxFQUFFLE9BQU8sQ0FBQztJQUNoQix1Q0FBdUM7SUFDdkMsUUFBUSxFQUFFLE1BQU0sQ0FBQztDQUNsQjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxXQUFXLGdCQUFnQjtJQUMvQixpQ0FBaUM7SUFDakMsSUFBSSxFQUFFLGlCQUFpQixDQUFDLFNBQVMsQ0FBQztJQUNsQyxpQkFBaUI7SUFDakIsU0FBUyxFQUFFLE1BQU0sQ0FBQztJQUNsQix3Q0FBd0M7SUFDeEMsS0FBSyxFQUFFLE1BQU0sQ0FBQztJQUNkLGlFQUFpRTtJQUNqRSxTQUFTLEVBQUUsU0FBUyxDQUFDO0NBQ3RCO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFdBQVcsaUJBQWlCO0lBQ2hDLDBDQUEwQztJQUMxQyxJQUFJLEVBQUUsaUJBQWlCLENBQUMsa0JBQWtCLENBQUM7SUFDM0MsZ0RBQWdEO0lBQ2hELFNBQVMsRUFBRSxNQUFNLENBQUM7SUFDbEIsK0JBQStCO0lBQy9CLFVBQVUsRUFBRSxVQUFVLENBQUM7Q0FDeEI7QUFFRDs7R0FFRztBQUNILE1BQU0sV0FBVyxrQkFBa0I7SUFDakMsbUJBQW1CO0lBQ25CLElBQUksRUFBRSxpQkFBaUIsQ0FBQyxvQkFBb0IsQ0FBQztJQUM3QyxnREFBZ0Q7SUFDaEQsU0FBUyxFQUFFLE1BQU0sQ0FBQztJQUNsQix3REFBd0Q7SUFDeEQsU0FBUyxFQUFFLGlCQUFpQixDQUFDO0NBQzlCO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFdBQVcsbUJBQW1CO0lBQ2xDLG1CQUFtQjtJQUNuQixJQUFJLEVBQUUsaUJBQWlCLENBQUMscUJBQXFCLENBQUM7SUFDOUMsZ0RBQWdEO0lBQ2hELFNBQVMsRUFBRSxNQUFNLENBQUM7SUFDbEIsMERBQTBEO0lBQzFELFNBQVMsRUFBRSxpQkFBaUIsQ0FBQztDQUM5QjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxNQUFNLGtCQUFrQixHQUFHLE1BQU0sSUFBSSxDQUFDIn0=
142
+ /**
143
+ * Default heartbeat tuning shared by both transports.
144
+ *
145
+ * - `intervalMs`: how often the dApp sends PING probes while a request is in flight.
146
+ * - `deadAfterMs`: how long the channel can stay silent (no PONG, no encrypted
147
+ * response, no DISCONNECT) before the dApp declares the wallet unreachable
148
+ * and rejects all in-flight requests. Generous enough that long-running
149
+ * operations (proveTx, sendTx) on legacy wallets that don't reply to PING
150
+ * still succeed — any inbound traffic resets the timer.
151
+ */
152
+ export declare const DEFAULT_HEARTBEAT_INTERVAL_MS = 5000;
153
+ export declare const DEFAULT_HEARTBEAT_DEAD_AFTER_MS = 300000;
154
+ /** Override knobs for the heartbeat — mostly useful for tests. */
155
+ export interface HeartbeatOptions {
156
+ /** How often to send PING probes while a request is in flight (ms). */
157
+ intervalMs?: number;
158
+ /** Idle ceiling before declaring disconnect (ms). */
159
+ deadAfterMs?: number;
160
+ }
161
+ /**
162
+ * Minimal logger surface used by the wallet SDK.
163
+ *
164
+ * Defined locally so that wallet hosts (browser extensions, iframe wallet pages)
165
+ * can pass a simple `console`-backed logger without pulling in the full
166
+ * `@aztec/foundation` logging runtime, which is non-trivial to bundle in those
167
+ * contexts. Structurally compatible with `Logger` from `@aztec/foundation/log`,
168
+ * so dApp-side callers can pass that type directly.
169
+ */
170
+ export interface WalletSdkLogger {
171
+ /** Diagnostic messages — typically discarded in production. */
172
+ debug: (message: string, data?: unknown) => void;
173
+ /** Informational messages — significant lifecycle events. */
174
+ info: (message: string, data?: unknown) => void;
175
+ /** Recoverable problems — channel decryption failure, missed heartbeats, etc. */
176
+ warn: (message: string, data?: unknown) => void;
177
+ /** Errors that prevent normal operation. */
178
+ error: (message: string, errOrData?: unknown, data?: unknown) => void;
179
+ }
180
+ /**
181
+ * No-op logger used as the default when callers don't provide one. Discards all
182
+ * messages — wallet hosts that want diagnostics should pass their own logger.
183
+ */
184
+ export declare const NOOP_LOGGER: WalletSdkLogger;
185
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV6RCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVyRDs7O0dBR0c7QUFDSCxvQkFBWSxpQkFBaUI7SUFDM0Isa0RBQWtEO0lBQ2xELFNBQVMsMkJBQTJCO0lBQ3BDLHVDQUF1QztJQUN2QyxrQkFBa0Isb0NBQW9DO0lBQ3RELHNFQUFzRTtJQUN0RSxVQUFVLDRCQUE0QjtJQUN0QyxvREFBb0Q7SUFDcEQsb0JBQW9CLHNDQUFzQztJQUMxRCxxREFBcUQ7SUFDckQscUJBQXFCLHVDQUF1QztJQUM1RCwwQkFBMEI7SUFDMUIsWUFBWSx1QkFBdUI7SUFDbkMsdUNBQXVDO0lBQ3ZDLGNBQWMsZ0NBQWdDO0lBQzlDLHdDQUF3QztJQUN4QyxlQUFlLGlDQUFpQztJQUNoRCx3Q0FBd0M7SUFDeEMsb0JBQW9CLHNDQUFzQztJQUMxRCxtRUFBbUU7SUFDbkUsSUFBSSxzQkFBc0I7SUFDMUI7OztPQUdHO0lBQ0gsSUFBSSxzQkFBc0I7Q0FDM0I7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFdBQVcsVUFBVTtJQUN6Qix1Q0FBdUM7SUFDdkMsRUFBRSxFQUFFLE1BQU0sQ0FBQztJQUNYLGlDQUFpQztJQUNqQyxJQUFJLEVBQUUsTUFBTSxDQUFDO0lBQ2IsK0JBQStCO0lBQy9CLElBQUksQ0FBQyxFQUFFLE1BQU0sQ0FBQztJQUNkLHFCQUFxQjtJQUNyQixPQUFPLEVBQUUsTUFBTSxDQUFDO0NBQ2pCO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxXQUFXLG1CQUFvQixTQUFRLFVBQVU7SUFDckQsZ0VBQWdFO0lBQ2hFLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQztJQUM3Qjs7OztPQUlHO0lBQ0gsZ0JBQWdCLENBQUMsRUFBRSxN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
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD;;;GAGG;AACH,oBAAY,iBAAiB;IAC3B,kDAAkD;IAClD,SAAS,2BAA2B;IACpC,uCAAuC;IACvC,kBAAkB,oCAAoC;IACtD,sEAAsE;IACtE,UAAU,4BAA4B;IACtC,oDAAoD;IACpD,oBAAoB,sCAAsC;IAC1D,qDAAqD;IACrD,qBAAqB,uCAAuC;IAC5D,0BAA0B;IAC1B,YAAY,uBAAuB;IACnC,uCAAuC;IACvC,cAAc,gCAAgC;IAC9C,wCAAwC;IACxC,eAAe,iCAAiC;IAChD,wCAAwC;IACxC,oBAAoB,sCAAsC;IAC1D,mEAAmE;IACnE,IAAI,sBAAsB;IAC1B;;;OAGG;IACH,IAAI,sBAAsB;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAoB,SAAQ,UAAU;IACrD,gEAAgE;IAChE,SAAS,EAAE,iBAAiB,CAAC;IAC7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,wBAAwB;IACxB,SAAS,EAAE,SAAS,CAAC;IACrB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,IAAI,EAAE,iBAAiB,CAAC,SAAS,CAAC;IAClC,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,SAAS,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,IAAI,EAAE,iBAAiB,CAAC,kBAAkB,CAAC;IAC3C,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,UAAU,EAAE,UAAU,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,mBAAmB;IACnB,IAAI,EAAE,iBAAiB,CAAC,oBAAoB,CAAC;IAC7C,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,SAAS,EAAE,iBAAiB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,mBAAmB;IACnB,IAAI,EAAE,iBAAiB,CAAC,qBAAqB,CAAC;IAC9C,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,SAAS,EAAE,iBAAiB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC;AAE5C;;;;;;;;;GASG;AACH,eAAO,MAAM,6BAA6B,OAAQ,CAAC;AACnD,eAAO,MAAM,+BAA+B,SAAU,CAAC;AAEvD,oEAAkE;AAClE,MAAM,WAAW,gBAAgB;IAC/B,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC9B,iEAA+D;IAC/D,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,+DAA6D;IAC7D,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,mFAAiF;IACjF,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,4CAA4C;IAC5C,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACvE;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,eAKzB,CAAC"}
package/dest/types.js CHANGED
@@ -11,5 +11,30 @@
11
11
  /** Encrypted wallet message wrapper */ WalletMessageType["SECURE_MESSAGE"] = "aztec-wallet-secure-message";
12
12
  /** Encrypted wallet response wrapper */ WalletMessageType["SECURE_RESPONSE"] = "aztec-wallet-secure-response";
13
13
  /** Session disconnected notification */ WalletMessageType["SESSION_DISCONNECTED"] = "aztec-wallet-session-disconnected";
14
+ /** Liveness probe sent by the dApp while a request is in flight */ WalletMessageType["PING"] = "aztec-wallet-ping";
15
+ /** Liveness response from the wallet. Any inbound message (including a regular
16
+ * encrypted response) is treated as proof of liveness, so a missing PONG alone
17
+ * never trips disconnect — the dApp also resets its liveness timer on traffic.
18
+ */ WalletMessageType["PONG"] = "aztec-wallet-pong";
14
19
  return WalletMessageType;
15
20
  }({});
21
+ /**
22
+ * Default heartbeat tuning shared by both transports.
23
+ *
24
+ * - `intervalMs`: how often the dApp sends PING probes while a request is in flight.
25
+ * - `deadAfterMs`: how long the channel can stay silent (no PONG, no encrypted
26
+ * response, no DISCONNECT) before the dApp declares the wallet unreachable
27
+ * and rejects all in-flight requests. Generous enough that long-running
28
+ * operations (proveTx, sendTx) on legacy wallets that don't reply to PING
29
+ * still succeed — any inbound traffic resets the timer.
30
+ */ export const DEFAULT_HEARTBEAT_INTERVAL_MS = 5_000;
31
+ export const DEFAULT_HEARTBEAT_DEAD_AFTER_MS = 300_000;
32
+ /**
33
+ * No-op logger used as the default when callers don't provide one. Discards all
34
+ * messages — wallet hosts that want diagnostics should pass their own logger.
35
+ */ export const NOOP_LOGGER = {
36
+ debug: ()=>{},
37
+ info: ()=>{},
38
+ warn: ()=>{},
39
+ error: ()=>{}
40
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aztec/wallet-sdk",
3
3
  "homepage": "https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/wallet-sdk",
4
- "version": "0.0.1-commit.b2a5d0dd1",
4
+ "version": "0.0.1-commit.b3d3157a",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  "./base-wallet": "./dest/base-wallet/index.js",
@@ -75,15 +75,15 @@
75
75
  ]
76
76
  },
77
77
  "dependencies": {
78
- "@aztec/aztec.js": "0.0.1-commit.b2a5d0dd1",
79
- "@aztec/constants": "0.0.1-commit.b2a5d0dd1",
80
- "@aztec/entrypoints": "0.0.1-commit.b2a5d0dd1",
81
- "@aztec/foundation": "0.0.1-commit.b2a5d0dd1",
82
- "@aztec/pxe": "0.0.1-commit.b2a5d0dd1",
83
- "@aztec/stdlib": "0.0.1-commit.b2a5d0dd1"
78
+ "@aztec/aztec.js": "0.0.1-commit.b3d3157a",
79
+ "@aztec/constants": "0.0.1-commit.b3d3157a",
80
+ "@aztec/entrypoints": "0.0.1-commit.b3d3157a",
81
+ "@aztec/foundation": "0.0.1-commit.b3d3157a",
82
+ "@aztec/pxe": "0.0.1-commit.b3d3157a",
83
+ "@aztec/stdlib": "0.0.1-commit.b3d3157a"
84
84
  },
85
85
  "devDependencies": {
86
- "@aztec/noir-contracts.js": "0.0.1-commit.b2a5d0dd1",
86
+ "@aztec/noir-contracts.js": "0.0.1-commit.b3d3157a",
87
87
  "@jest/globals": "^30.0.0",
88
88
  "@types/jest": "^30.0.0",
89
89
  "@types/node": "^22.15.17",
@@ -85,7 +85,7 @@ export type FeeOptions = {
85
85
  /** Options for `simulateViaEntrypoint`. */
86
86
  export type SimulateViaEntrypointOptions = Pick<
87
87
  SimulateOptions,
88
- 'from' | 'additionalScopes' | 'skipTxValidation' | 'skipFeeEnforcement'
88
+ 'from' | 'additionalScopes' | 'skipTxValidation' | 'skipFeeEnforcement' | 'sendMessagesAs' | 'overrides'
89
89
  > & {
90
90
  /** Fee options for the entrypoint */
91
91
  feeOptions: FeeOptions;
@@ -131,6 +131,17 @@ export abstract class BaseWallet implements Wallet {
131
131
  return [...scopeSet].map(AztecAddress.fromString);
132
132
  }
133
133
 
134
+ /**
135
+ * Picks the sender address PXE should tag private messages with. Returns `undefined` when there is no signing
136
+ * account (`from === NO_FROM`) and no explicit override; in that case any private log emitted by the tx using
137
+ * the wallet-supplied default sender will fail the "Sender for tags is not set" assertion.
138
+ * @param from - Tx sender, or `NO_FROM`.
139
+ * @param sendMessagesAs - Explicit override.
140
+ */
141
+ protected senderForTagsFrom(from: AztecAddress | NoFrom, sendMessagesAs?: AztecAddress): AztecAddress | undefined {
142
+ return sendMessagesAs ?? (from === NO_FROM ? undefined : from);
143
+ }
144
+
134
145
  protected abstract getAccountFromAddress(address: AztecAddress): Promise<Account>;
135
146
 
136
147
  abstract getAccounts(): Promise<Aliased<AztecAddress>[]>;
@@ -337,6 +348,10 @@ export abstract class BaseWallet implements Wallet {
337
348
  return instance;
338
349
  }
339
350
 
351
+ registerContractClass(artifact: ContractArtifact): Promise<void> {
352
+ return this.pxe.registerContractClass(artifact);
353
+ }
354
+
340
355
  /**
341
356
  * Simulates calls through the standard PXE path (account entrypoint).
342
357
  * @param executionPayload - The execution payload to simulate.
@@ -353,6 +368,8 @@ export abstract class BaseWallet implements Wallet {
353
368
  skipTxValidation: opts.skipTxValidation,
354
369
  skipFeeEnforcement: opts.skipFeeEnforcement,
355
370
  scopes: this.scopesFrom(opts.from, opts.additionalScopes),
371
+ senderForTags: this.senderForTagsFrom(opts.from, opts.sendMessagesAs),
372
+ overrides: opts.overrides,
356
373
  });
357
374
  const appCallOffset = await this.computeAppCallOffset(opts.from, opts.feeOptions);
358
375
  return TxSimulationResultWithAppOffset.fromResultAndOffset(result, appCallOffset);
@@ -401,7 +418,7 @@ export abstract class BaseWallet implements Wallet {
401
418
  try {
402
419
  blockHeader = await this.pxe.getSyncedBlockHeader();
403
420
  } catch {
404
- blockHeader = (await this.aztecNode.getBlockHeader())!;
421
+ blockHeader = (await this.aztecNode.getBlockData('latest'))!.header;
405
422
  }
406
423
 
407
424
  const simulationOrigin = opts.from === NO_FROM ? AztecAddress.ZERO : opts.from;
@@ -416,6 +433,7 @@ export abstract class BaseWallet implements Wallet {
416
433
  blockHeader,
417
434
  opts.skipFeeEnforcement ?? true,
418
435
  this.getContractName.bind(this),
436
+ opts.overrides,
419
437
  )
420
438
  : Promise.resolve([]),
421
439
  remainingCalls.length > 0
@@ -425,6 +443,8 @@ export abstract class BaseWallet implements Wallet {
425
443
  additionalScopes: opts.additionalScopes,
426
444
  skipTxValidation: opts.skipTxValidation,
427
445
  skipFeeEnforcement: opts.skipFeeEnforcement ?? true,
446
+ sendMessagesAs: opts.sendMessagesAs,
447
+ overrides: opts.overrides,
428
448
  })
429
449
  : Promise.resolve(null),
430
450
  ]);
@@ -444,6 +464,7 @@ export abstract class BaseWallet implements Wallet {
444
464
  profileMode: opts.profileMode,
445
465
  skipProofGeneration: opts.skipProofGeneration ?? true,
446
466
  scopes: this.scopesFrom(opts.from, opts.additionalScopes),
467
+ senderForTags: this.senderForTagsFrom(opts.from, opts.sendMessagesAs),
447
468
  });
448
469
  }
449
470
 
@@ -458,14 +479,17 @@ export abstract class BaseWallet implements Wallet {
458
479
  congestionEstimate: opts.fee?.congestionEstimate,
459
480
  });
460
481
  const txRequest = await this.createTxExecutionRequestFromPayloadAndFee(executionPayload, opts.from, feeOptions);
461
- const provenTx = await this.pxe.proveTx(txRequest, this.scopesFrom(opts.from, opts.additionalScopes));
482
+ const provenTx = await this.pxe.proveTx(txRequest, {
483
+ scopes: this.scopesFrom(opts.from, opts.additionalScopes),
484
+ senderForTags: this.senderForTagsFrom(opts.from, opts.sendMessagesAs),
485
+ });
462
486
  const offchainOutput = extractOffchainOutput(
463
487
  provenTx.getOffchainEffects(),
464
488
  provenTx.publicInputs.constants.anchorBlockHeader.globalVariables.timestamp,
465
489
  );
466
490
  const tx = await provenTx.toTx();
467
491
  const txHash = tx.getTxHash();
468
- if (await this.aztecNode.getTxEffect(txHash)) {
492
+ if ((await this.aztecNode.getTxReceipt(txHash)).isMined()) {
469
493
  throw new Error(`A settled tx with equal hash ${txHash.toString()} exists.`);
470
494
  }
471
495
  this.log.debug(`Sending transaction ${txHash}`);
@@ -484,7 +508,7 @@ export abstract class BaseWallet implements Wallet {
484
508
  const receipt = await waitForTx(this.aztecNode, txHash, waitOpts);
485
509
 
486
510
  // Display debug logs from public execution if present (served in test mode only)
487
- if (receipt.debugLogs?.length) {
511
+ if (receipt.isMined() && receipt.debugLogs?.length) {
488
512
  await displayDebugLogs(receipt.debugLogs, this.getContractName.bind(this));
489
513
  }
490
514
 
@@ -25,6 +25,7 @@ import {
25
25
  PrivateCallExecutionResult,
26
26
  PrivateExecutionResult,
27
27
  PublicSimulationOutput,
28
+ type SimulationOverrides,
28
29
  Tx,
29
30
  TxContext,
30
31
  TxSimulationResult,
@@ -65,6 +66,8 @@ export function extractOptimizablePublicStaticCalls(payload: ExecutionPayload):
65
66
  * @param gasSettings - Gas settings for the transaction.
66
67
  * @param blockHeader - Block header to use as anchor.
67
68
  * @param skipFeeEnforcement - Whether to skip fee enforcement during simulation.
69
+ * @param getContractName - Resolver for contract names (used for debug log display).
70
+ * @param overrides - Optional pre-simulation overrides applied to the ephemeral fork and contract DB.
68
71
  * @returns TxSimulationResult with public return values.
69
72
  */
70
73
  async function simulateBatchViaNode(
@@ -76,6 +79,7 @@ async function simulateBatchViaNode(
76
79
  blockHeader: BlockHeader,
77
80
  skipFeeEnforcement: boolean,
78
81
  getContractName: ContractNameResolver,
82
+ overrides?: SimulationOverrides,
79
83
  ): Promise<TxSimulationResult> {
80
84
  const txContext = new TxContext(chainInfo.chainId, chainInfo.version, gasSettings);
81
85
 
@@ -143,7 +147,7 @@ async function simulateBatchViaNode(
143
147
  publicFunctionCalldata: publicFunctionCalldata,
144
148
  });
145
149
 
146
- const publicOutput = await node.simulatePublicCalls(tx, skipFeeEnforcement);
150
+ const publicOutput = await node.simulatePublicCalls(tx, skipFeeEnforcement, overrides);
147
151
 
148
152
  if (publicOutput.revertReason) {
149
153
  throw publicOutput.revertReason;
@@ -166,6 +170,8 @@ async function simulateBatchViaNode(
166
170
  * @param gasSettings - Gas settings for the transaction.
167
171
  * @param blockHeader - Block header to use as anchor.
168
172
  * @param skipFeeEnforcement - Whether to skip fee enforcement during simulation.
173
+ * @param getContractName - Resolver for contract names (used for debug log display).
174
+ * @param overrides - Optional pre-simulation overrides applied to the ephemeral fork and contract DB.
169
175
  * @returns Array of TxSimulationResult, one per batch.
170
176
  */
171
177
  export async function simulateViaNode(
@@ -177,6 +183,7 @@ export async function simulateViaNode(
177
183
  blockHeader: BlockHeader,
178
184
  skipFeeEnforcement: boolean = true,
179
185
  getContractName: ContractNameResolver,
186
+ overrides?: SimulationOverrides,
180
187
  ): Promise<TxSimulationResult[]> {
181
188
  const batches: FunctionCall[][] = [];
182
189
 
@@ -196,6 +203,7 @@ export async function simulateViaNode(
196
203
  blockHeader,
197
204
  skipFeeEnforcement,
198
205
  getContractName,
206
+ overrides,
199
207
  );
200
208
  results.push(result);
201
209
  }
@@ -17,6 +17,7 @@ import {
17
17
  type WalletMessage,
18
18
  WalletMessageType,
19
19
  type WalletResponse,
20
+ type WalletSdkLogger,
20
21
  } from '../../types.js';
21
22
  import {
22
23
  type BackgroundMessage,
@@ -131,6 +132,8 @@ export interface BackgroundConnectionConfig {
131
132
  walletVersion: string;
132
133
  /** Optional wallet icon URL. */
133
134
  walletIcon?: string;
135
+ /** Logger used for diagnostics. */
136
+ logger: WalletSdkLogger;
134
137
  }
135
138
 
136
139
  /**
@@ -149,6 +152,7 @@ export interface BackgroundConnectionConfig {
149
152
  * walletId: 'my-wallet',
150
153
  * walletName: 'My Wallet',
151
154
  * walletVersion: '1.0.0',
155
+ * logger: console,
152
156
  * },
153
157
  * {
154
158
  * sendToTab: (tabId, message) => browser.tabs.sendMessage(tabId, message),
@@ -167,12 +171,15 @@ export interface BackgroundConnectionConfig {
167
171
  export class BackgroundConnectionHandler {
168
172
  private pendingDiscoveries = new Map<string, PendingDiscovery>();
169
173
  private activeSessions = new Map<string, ActiveSession>();
174
+ private log: WalletSdkLogger;
170
175
 
171
176
  constructor(
172
177
  private config: BackgroundConnectionConfig,
173
178
  private transport: BackgroundTransport,
174
179
  private callbacks: BackgroundConnectionCallbacks = {},
175
- ) {}
180
+ ) {
181
+ this.log = config.logger;
182
+ }
176
183
 
177
184
  initialize(): void {
178
185
  this.transport.addContentListener(this.handleMessage);
@@ -198,8 +205,8 @@ export class BackgroundConnectionHandler {
198
205
  break;
199
206
  case InternalMessageType.KEY_EXCHANGE_REQUEST:
200
207
  if (sessionId) {
201
- this.handleKeyExchangeRequest(sessionId, content as KeyExchangeRequest).catch(() => {
202
- // Key exchange failed - session won't be established
208
+ this.handleKeyExchangeRequest(sessionId, content as KeyExchangeRequest).catch(err => {
209
+ this.log.warn('Key exchange failed session will not be established', { sessionId, err });
203
210
  });
204
211
  }
205
212
  break;
@@ -213,9 +220,31 @@ export class BackgroundConnectionHandler {
213
220
  void this.handleEncryptedMessage(sessionId, content as EncryptedPayload);
214
221
  }
215
222
  break;
223
+ case InternalMessageType.PING:
224
+ if (sessionId) {
225
+ this.handlePing(sessionId);
226
+ }
227
+ break;
216
228
  }
217
229
  };
218
230
 
231
+ /**
232
+ * Reply to a dApp PING with a PONG. Used as a liveness probe so the dApp can
233
+ * tell the difference between a slow request and a dead extension.
234
+ * @param sessionId - The session that sent the PING.
235
+ */
236
+ private handlePing(sessionId: string): void {
237
+ const session = this.activeSessions.get(sessionId);
238
+ if (!session) {
239
+ return;
240
+ }
241
+ this.transport.sendToTab(session.tabId, {
242
+ origin: MessageOrigin.BACKGROUND,
243
+ type: InternalMessageType.PONG,
244
+ sessionId,
245
+ });
246
+ }
247
+
219
248
  getWalletInfo(): WalletInfo {
220
249
  return {
221
250
  id: this.config.walletId,
@@ -315,8 +344,8 @@ export class BackgroundConnectionHandler {
315
344
  });
316
345
 
317
346
  this.callbacks.onSessionEstablished?.(session);
318
- } catch {
319
- // Key exchange failed silently - session won't be established
347
+ } catch (err) {
348
+ this.log.warn('Key exchange failed session will not be established', { sessionId, err });
320
349
  }
321
350
  }
322
351
 
@@ -329,8 +358,8 @@ export class BackgroundConnectionHandler {
329
358
  try {
330
359
  const message = await decrypt<WalletMessage>(session.sharedKey, encrypted);
331
360
  this.callbacks.onWalletMessage?.(session, message);
332
- } catch {
333
- // Decryption failed - ignore malformed message
361
+ } catch (err) {
362
+ this.log.warn('Failed to decrypt incoming wallet message', { sessionId, err });
334
363
  }
335
364
  }
336
365
 
@@ -348,8 +377,12 @@ export class BackgroundConnectionHandler {
348
377
  sessionId,
349
378
  content: encrypted,
350
379
  });
351
- } catch {
352
- // Encryption failed - response won't be sent
380
+ } catch (err) {
381
+ this.log.error('Failed to encrypt wallet response response will not be sent', {
382
+ sessionId,
383
+ messageId: response.messageId,
384
+ err,
385
+ });
353
386
  }
354
387
  }
355
388
 
@@ -139,9 +139,20 @@ export class ContentScriptConnectionHandler {
139
139
  case InternalMessageType.SESSION_DISCONNECTED:
140
140
  this.handleSessionDisconnected(sessionId);
141
141
  break;
142
+ case InternalMessageType.PONG:
143
+ this.handlePong(sessionId);
144
+ break;
142
145
  }
143
146
  };
144
147
 
148
+ private handlePong(sessionId: string): void {
149
+ const connection = this.ports.get(sessionId);
150
+ if (!connection) {
151
+ return;
152
+ }
153
+ connection.port.postMessage({ type: WalletMessageType.PONG });
154
+ }
155
+
145
156
  private handleDiscoveryRequest(request: DiscoveryRequest): void {
146
157
  this.transport.sendToBackground({
147
158
  origin: MessageOrigin.CONTENT_SCRIPT,
@@ -178,6 +189,13 @@ export class ContentScriptConnectionHandler {
178
189
  content: data,
179
190
  });
180
191
  break;
192
+ case WalletMessageType.PING:
193
+ this.transport.sendToBackground({
194
+ origin: MessageOrigin.CONTENT_SCRIPT,
195
+ type: InternalMessageType.PING,
196
+ sessionId,
197
+ });
198
+ break;
181
199
  default:
182
200
  this.transport.sendToBackground({
183
201
  origin: MessageOrigin.CONTENT_SCRIPT,
@@ -9,11 +9,13 @@ export const InternalMessageType = {
9
9
  KEY_EXCHANGE_REQUEST: 'key-exchange-request',
10
10
  SECURE_MESSAGE: 'secure-message',
11
11
  DISCONNECT_REQUEST: 'disconnect-request',
12
+ PING: 'ping',
12
13
  // Background → Content script
13
14
  DISCOVERY_APPROVED: 'discovery-approved',
14
15
  KEY_EXCHANGE_RESPONSE: 'key-exchange-response',
15
16
  SECURE_RESPONSE: 'secure-response',
16
17
  SESSION_DISCONNECTED: 'session-disconnected',
18
+ PONG: 'pong',
17
19
  } as const;
18
20
 
19
21
  /**