@aztec/wallet-sdk 0.0.1-commit.f295ac2 → 0.0.1-commit.fc805bf

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 (67) hide show
  1. package/README.md +217 -294
  2. package/dest/base-wallet/base_wallet.d.ts +20 -7
  3. package/dest/base-wallet/base_wallet.d.ts.map +1 -1
  4. package/dest/base-wallet/base_wallet.js +29 -11
  5. package/dest/crypto.d.ts +59 -50
  6. package/dest/crypto.d.ts.map +1 -1
  7. package/dest/crypto.js +202 -108
  8. package/dest/emoji_alphabet.d.ts +35 -0
  9. package/dest/emoji_alphabet.d.ts.map +1 -0
  10. package/dest/emoji_alphabet.js +299 -0
  11. package/dest/extension/handlers/background_connection_handler.d.ts +158 -0
  12. package/dest/extension/handlers/background_connection_handler.d.ts.map +1 -0
  13. package/dest/extension/handlers/background_connection_handler.js +258 -0
  14. package/dest/extension/handlers/content_script_connection_handler.d.ts +56 -0
  15. package/dest/extension/handlers/content_script_connection_handler.d.ts.map +1 -0
  16. package/dest/extension/handlers/content_script_connection_handler.js +174 -0
  17. package/dest/extension/handlers/index.d.ts +12 -0
  18. package/dest/extension/handlers/index.d.ts.map +1 -0
  19. package/dest/extension/handlers/index.js +10 -0
  20. package/dest/extension/handlers/internal_message_types.d.ts +63 -0
  21. package/dest/extension/handlers/internal_message_types.d.ts.map +1 -0
  22. package/dest/extension/handlers/internal_message_types.js +22 -0
  23. package/dest/extension/provider/extension_provider.d.ts +107 -0
  24. package/dest/extension/provider/extension_provider.d.ts.map +1 -0
  25. package/dest/extension/provider/extension_provider.js +160 -0
  26. package/dest/extension/provider/extension_wallet.d.ts +131 -0
  27. package/dest/extension/provider/extension_wallet.d.ts.map +1 -0
  28. package/dest/{providers/extension → extension/provider}/extension_wallet.js +48 -95
  29. package/dest/extension/provider/index.d.ts +3 -0
  30. package/dest/extension/provider/index.d.ts.map +1 -0
  31. package/dest/{providers/extension → extension/provider}/index.js +0 -2
  32. package/dest/manager/index.d.ts +2 -8
  33. package/dest/manager/index.d.ts.map +1 -1
  34. package/dest/manager/index.js +0 -6
  35. package/dest/manager/types.d.ts +88 -6
  36. package/dest/manager/types.d.ts.map +1 -1
  37. package/dest/manager/types.js +17 -1
  38. package/dest/manager/wallet_manager.d.ts +50 -7
  39. package/dest/manager/wallet_manager.d.ts.map +1 -1
  40. package/dest/manager/wallet_manager.js +174 -44
  41. package/dest/types.d.ts +43 -12
  42. package/dest/types.d.ts.map +1 -1
  43. package/dest/types.js +3 -2
  44. package/package.json +10 -9
  45. package/src/base-wallet/base_wallet.ts +45 -20
  46. package/src/crypto.ts +237 -113
  47. package/src/emoji_alphabet.ts +317 -0
  48. package/src/extension/handlers/background_connection_handler.ts +423 -0
  49. package/src/extension/handlers/content_script_connection_handler.ts +246 -0
  50. package/src/extension/handlers/index.ts +25 -0
  51. package/src/extension/handlers/internal_message_types.ts +69 -0
  52. package/src/extension/provider/extension_provider.ts +233 -0
  53. package/src/{providers/extension → extension/provider}/extension_wallet.ts +52 -110
  54. package/src/extension/provider/index.ts +7 -0
  55. package/src/manager/index.ts +2 -10
  56. package/src/manager/types.ts +91 -5
  57. package/src/manager/wallet_manager.ts +192 -46
  58. package/src/types.ts +44 -10
  59. package/dest/providers/extension/extension_provider.d.ts +0 -63
  60. package/dest/providers/extension/extension_provider.d.ts.map +0 -1
  61. package/dest/providers/extension/extension_provider.js +0 -124
  62. package/dest/providers/extension/extension_wallet.d.ts +0 -155
  63. package/dest/providers/extension/extension_wallet.d.ts.map +0 -1
  64. package/dest/providers/extension/index.d.ts +0 -6
  65. package/dest/providers/extension/index.d.ts.map +0 -1
  66. package/src/providers/extension/extension_provider.ts +0 -167
  67. package/src/providers/extension/index.ts +0 -5
@@ -0,0 +1,258 @@
1
+ import { decrypt, deriveSessionKeys, encrypt, exportPublicKey, generateKeyPair, importPublicKey } from '../../crypto.js';
2
+ import { WalletMessageType } from '../../types.js';
3
+ import { InternalMessageType, MessageOrigin } from './internal_message_types.js';
4
+ /**
5
+ * Handles wallet session flow in the extension background script.
6
+ *
7
+ * This class manages:
8
+ * - Pending discovery requests (before user approval)
9
+ * - Active sessions (after key exchange)
10
+ * - Per-session ECDH key exchange
11
+ * - Message encryption/decryption
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const handler = new BackgroundConnectionHandler(
16
+ * {
17
+ * walletId: 'my-wallet',
18
+ * walletName: 'My Wallet',
19
+ * walletVersion: '1.0.0',
20
+ * },
21
+ * {
22
+ * sendToTab: (tabId, message) => browser.tabs.sendMessage(tabId, message),
23
+ * addContentListener: (handler) => browser.runtime.onMessage.addListener(handler),
24
+ * },
25
+ * {
26
+ * onPendingDiscovery: (discovery) => updateBadge(),
27
+ * onSessionEstablished: (session) => console.log('Connected:', session.sessionId),
28
+ * onWalletMessage: (session, message) => nativePort.postMessage(message),
29
+ * }
30
+ * );
31
+ *
32
+ * handler.initialize();
33
+ * ```
34
+ */ export class BackgroundConnectionHandler {
35
+ config;
36
+ transport;
37
+ callbacks;
38
+ pendingDiscoveries;
39
+ activeSessions;
40
+ constructor(config, transport, callbacks = {}){
41
+ this.config = config;
42
+ this.transport = transport;
43
+ this.callbacks = callbacks;
44
+ this.pendingDiscoveries = new Map();
45
+ this.activeSessions = new Map();
46
+ this.handleMessage = (message, sender)=>{
47
+ const msg = message;
48
+ if (msg.origin !== MessageOrigin.CONTENT_SCRIPT) {
49
+ return;
50
+ }
51
+ const tabId = sender.tab?.id;
52
+ const tabOrigin = sender.tab?.url ? new URL(sender.tab.url).origin : 'unknown';
53
+ if (!tabId) {
54
+ return;
55
+ }
56
+ const { type, sessionId, content } = msg;
57
+ switch(type){
58
+ case InternalMessageType.DISCOVERY_REQUEST:
59
+ this.handleDiscoveryRequest(content, tabId, tabOrigin);
60
+ break;
61
+ case InternalMessageType.KEY_EXCHANGE_REQUEST:
62
+ if (sessionId) {
63
+ this.handleKeyExchangeRequest(sessionId, content).catch(()=>{
64
+ // Key exchange failed - session won't be established
65
+ });
66
+ }
67
+ break;
68
+ case InternalMessageType.DISCONNECT_REQUEST:
69
+ if (sessionId) {
70
+ this.terminateSession(sessionId);
71
+ }
72
+ break;
73
+ case InternalMessageType.SECURE_MESSAGE:
74
+ if (sessionId) {
75
+ void this.handleEncryptedMessage(sessionId, content);
76
+ }
77
+ break;
78
+ }
79
+ };
80
+ }
81
+ initialize() {
82
+ this.transport.addContentListener(this.handleMessage);
83
+ }
84
+ handleMessage;
85
+ getWalletInfo() {
86
+ return {
87
+ id: this.config.walletId,
88
+ name: this.config.walletName,
89
+ version: this.config.walletVersion,
90
+ icon: this.config.walletIcon
91
+ };
92
+ }
93
+ handleDiscoveryRequest(request, tabId, origin) {
94
+ const discovery = {
95
+ requestId: request.requestId,
96
+ appId: request.appId,
97
+ origin,
98
+ chainInfo: request.chainInfo,
99
+ tabId,
100
+ timestamp: Date.now(),
101
+ status: 'pending'
102
+ };
103
+ this.pendingDiscoveries.set(request.requestId, discovery);
104
+ this.callbacks.onPendingDiscovery?.(discovery);
105
+ }
106
+ approveDiscovery(requestId) {
107
+ const discovery = this.pendingDiscoveries.get(requestId);
108
+ if (!discovery || discovery.status !== 'pending') {
109
+ return false;
110
+ }
111
+ // The discovery requestId becomes our sessionId
112
+ // This is what will be used internally to correlate
113
+ // content<->background messages
114
+ const sessionId = requestId;
115
+ discovery.status = 'approved';
116
+ this.transport.sendToTab(discovery.tabId, {
117
+ origin: MessageOrigin.BACKGROUND,
118
+ type: InternalMessageType.DISCOVERY_APPROVED,
119
+ sessionId,
120
+ content: this.getWalletInfo()
121
+ });
122
+ return true;
123
+ }
124
+ rejectDiscovery(requestId) {
125
+ const discovery = this.pendingDiscoveries.get(requestId);
126
+ if (!discovery || discovery.status !== 'pending') {
127
+ return false;
128
+ }
129
+ discovery.status = 'rejected';
130
+ this.pendingDiscoveries.delete(requestId);
131
+ return true;
132
+ }
133
+ async handleKeyExchangeRequest(sessionId, request) {
134
+ const discovery = this.pendingDiscoveries.get(sessionId);
135
+ if (!discovery || discovery.status !== 'approved') {
136
+ return;
137
+ }
138
+ try {
139
+ const keyPair = await generateKeyPair();
140
+ const publicKey = await exportPublicKey(keyPair.publicKey);
141
+ const appPublicKey = await importPublicKey(request.publicKey);
142
+ const sessionKeys = await deriveSessionKeys(keyPair, appPublicKey, false);
143
+ const session = {
144
+ sessionId,
145
+ sharedKey: sessionKeys.encryptionKey,
146
+ verificationHash: sessionKeys.verificationHash,
147
+ tabId: discovery.tabId,
148
+ origin: discovery.origin,
149
+ appId: discovery.appId,
150
+ connectedAt: Date.now(),
151
+ chainInfo: discovery.chainInfo
152
+ };
153
+ this.activeSessions.set(sessionId, session);
154
+ this.pendingDiscoveries.delete(sessionId);
155
+ const response = {
156
+ type: WalletMessageType.KEY_EXCHANGE_RESPONSE,
157
+ requestId: sessionId,
158
+ publicKey
159
+ };
160
+ this.transport.sendToTab(discovery.tabId, {
161
+ origin: MessageOrigin.BACKGROUND,
162
+ type: InternalMessageType.KEY_EXCHANGE_RESPONSE,
163
+ sessionId,
164
+ content: response
165
+ });
166
+ this.callbacks.onSessionEstablished?.(session);
167
+ } catch {
168
+ // Key exchange failed silently - session won't be established
169
+ }
170
+ }
171
+ async handleEncryptedMessage(sessionId, encrypted) {
172
+ const session = this.activeSessions.get(sessionId);
173
+ if (!session) {
174
+ return;
175
+ }
176
+ try {
177
+ const message = await decrypt(session.sharedKey, encrypted);
178
+ this.callbacks.onWalletMessage?.(session, message);
179
+ } catch {
180
+ // Decryption failed - ignore malformed message
181
+ }
182
+ }
183
+ async sendResponse(sessionId, response) {
184
+ const session = this.activeSessions.get(sessionId);
185
+ if (!session) {
186
+ return;
187
+ }
188
+ try {
189
+ const encrypted = await encrypt(session.sharedKey, JSON.stringify(response));
190
+ this.transport.sendToTab(session.tabId, {
191
+ origin: MessageOrigin.BACKGROUND,
192
+ type: InternalMessageType.SECURE_RESPONSE,
193
+ sessionId,
194
+ content: encrypted
195
+ });
196
+ } catch {
197
+ // Encryption failed - response won't be sent
198
+ }
199
+ }
200
+ terminateSession(sessionId) {
201
+ const session = this.activeSessions.get(sessionId);
202
+ if (session) {
203
+ // Notify the content script (and ultimately the dApp) that the session is disconnected
204
+ this.transport.sendToTab(session.tabId, {
205
+ origin: MessageOrigin.BACKGROUND,
206
+ type: InternalMessageType.SESSION_DISCONNECTED,
207
+ sessionId
208
+ });
209
+ this.activeSessions.delete(sessionId);
210
+ this.callbacks.onSessionTerminated?.(sessionId);
211
+ // Restore discovery to approved state so user can retry key exchange
212
+ const discovery = {
213
+ requestId: sessionId,
214
+ appId: session.appId,
215
+ origin: session.origin,
216
+ chainInfo: session.chainInfo,
217
+ tabId: session.tabId,
218
+ timestamp: Date.now(),
219
+ status: 'approved'
220
+ };
221
+ this.pendingDiscoveries.set(sessionId, discovery);
222
+ }
223
+ }
224
+ terminateForTab(tabId) {
225
+ for (const [sessionId, session] of this.activeSessions){
226
+ if (session.tabId === tabId) {
227
+ this.terminateSession(sessionId);
228
+ }
229
+ }
230
+ for (const [requestId, discovery] of this.pendingDiscoveries){
231
+ if (discovery.tabId === tabId) {
232
+ this.pendingDiscoveries.delete(requestId);
233
+ }
234
+ }
235
+ }
236
+ clearAll() {
237
+ for (const sessionId of this.activeSessions.keys()){
238
+ this.callbacks.onSessionTerminated?.(sessionId);
239
+ }
240
+ this.activeSessions.clear();
241
+ this.pendingDiscoveries.clear();
242
+ }
243
+ getPendingDiscoveries() {
244
+ return Array.from(this.pendingDiscoveries.values()).filter((d)=>d.status === 'pending');
245
+ }
246
+ getPendingDiscoveryCount() {
247
+ return this.getPendingDiscoveries().length;
248
+ }
249
+ getActiveSessions() {
250
+ return Array.from(this.activeSessions.values());
251
+ }
252
+ getSession(sessionId) {
253
+ return this.activeSessions.get(sessionId);
254
+ }
255
+ getPendingDiscovery(requestId) {
256
+ return this.pendingDiscoveries.get(requestId);
257
+ }
258
+ }
@@ -0,0 +1,56 @@
1
+ import { type BackgroundMessage, type ContentScriptMessage } from './internal_message_types.js';
2
+ /**
3
+ * Transport interface for content script communication.
4
+ */
5
+ export interface ContentScriptTransport {
6
+ /**
7
+ * Send a message to the background script.
8
+ * Typically `browser.runtime.sendMessage`.
9
+ */
10
+ sendToBackground: (message: ContentScriptMessage) => void;
11
+ /**
12
+ * Register a listener for messages from the background script.
13
+ * Typically `browser.runtime.onMessage.addListener`.
14
+ */
15
+ addBackgroundListener: (handler: (message: BackgroundMessage) => void) => void;
16
+ }
17
+ /**
18
+ * Handles wallet connection flow in the extension content script.
19
+ *
20
+ * This class manages:
21
+ * - Listening for discovery requests from the page
22
+ * - Creating MessageChannels after discovery approval
23
+ * - Relaying key exchange messages between page and background
24
+ * - Relaying encrypted messages between page and background
25
+ *
26
+ * The content script acts as a pure relay - it never has access to
27
+ * private keys or shared secrets.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const handler = new ContentScriptConnectionHandler({
32
+ * sendToBackground: (message) => browser.runtime.sendMessage(message),
33
+ * addBackgroundListener: (handler) => browser.runtime.onMessage.addListener(handler),
34
+ * });
35
+ *
36
+ * handler.start();
37
+ * ```
38
+ */
39
+ export declare class ContentScriptConnectionHandler {
40
+ private transport;
41
+ private ports;
42
+ private listening;
43
+ private pageMessageHandler;
44
+ constructor(transport: ContentScriptTransport);
45
+ start(): void;
46
+ private handleBackgroundMessage;
47
+ private handleDiscoveryRequest;
48
+ private handleDiscoveryApproved;
49
+ private handleKeyExchangeResponse;
50
+ private handleSecureResponse;
51
+ private handleSessionDisconnected;
52
+ closeConnection(sessionId: string): void;
53
+ closeAllConnections(): void;
54
+ getConnectionCount(): number;
55
+ }
56
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGVudF9zY3JpcHRfY29ubmVjdGlvbl9oYW5kbGVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZXh0ZW5zaW9uL2hhbmRsZXJzL2NvbnRlbnRfc2NyaXB0X2Nvbm5lY3Rpb25faGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQ0wsS0FBSyxpQkFBaUIsRUFDdEIsS0FBSyxvQkFBb0IsRUFHMUIsTUFBTSw2QkFBNkIsQ0FBQztBQW9DckM7O0dBRUc7QUFDSCxNQUFNLFdBQVcsc0JBQXNCO0lBQ3JDOzs7T0FHRztJQUNILGdCQUFnQixFQUFFLENBQUMsT0FBTyxFQUFFLG9CQUFvQixLQUFLLElBQUksQ0FBQztJQUUxRDs7O09BR0c7SUFDSCxxQkFBcUIsRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDLE9BQU8sRUFBRSxpQkFBaUIsS0FBSyxJQUFJLEtBQUssSUFBSSxDQUFDO0NBQ2hGO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFCRztBQUNILHFCQUFhLDhCQUE4QjtJQUs3QixPQUFPLENBQUMsU0FBUztJQUo3QixPQUFPLENBQUMsS0FBSyxDQUFxQztJQUNsRCxPQUFPLENBQUMsU0FBUyxDQUFTO0lBQzFCLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBZ0Q7SUFFMUUsWUFBb0IsU0FBUyxFQUFFLHNCQUFzQixFQUFJO0lBRXpELEtBQUssSUFBSSxJQUFJLENBOEJaO0lBRUQsT0FBTyxDQUFDLHVCQUF1QixDQXFCN0I7SUFFRixPQUFPLENBQUMsc0JBQXNCO0lBUTlCLE9BQU8sQ0FBQyx1QkFBdUI7SUFpRC9CLE9BQU8sQ0FBQyx5QkFBeUI7SUFRakMsT0FBTyxDQUFDLG9CQUFvQjtJQVE1QixPQUFPLENBQUMseUJBQXlCO0lBVWpDLGVBQWUsQ0FBQyxTQUFTLEVBQUUsTUFBTSxHQUFHLElBQUksQ0FNdkM7SUFFRCxtQkFBbUIsSUFBSSxJQUFJLENBSzFCO0lBRUQsa0JBQWtCLElBQUksTUFBTSxDQUUzQjtDQUNGIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content_script_connection_handler.d.ts","sourceRoot":"","sources":["../../../src/extension/handlers/content_script_connection_handler.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAG1B,MAAM,6BAA6B,CAAC;AAoCrC;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,gBAAgB,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAE1D;;;OAGG;IACH,qBAAqB,EAAE,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,KAAK,IAAI,CAAC;CAChF;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,8BAA8B;IAK7B,OAAO,CAAC,SAAS;IAJ7B,OAAO,CAAC,KAAK,CAAqC;IAClD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,kBAAkB,CAAgD;IAE1E,YAAoB,SAAS,EAAE,sBAAsB,EAAI;IAEzD,KAAK,IAAI,IAAI,CA8BZ;IAED,OAAO,CAAC,uBAAuB,CAqB7B;IAEF,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,uBAAuB;IAiD/B,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,yBAAyB;IAUjC,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAMvC;IAED,mBAAmB,IAAI,IAAI,CAK1B;IAED,kBAAkB,IAAI,MAAM,CAE3B;CACF"}
@@ -0,0 +1,174 @@
1
+ import { WalletMessageType } from '../../types.js';
2
+ import { InternalMessageType, MessageOrigin } from './internal_message_types.js';
3
+ /**
4
+ * Handles wallet connection flow in the extension content script.
5
+ *
6
+ * This class manages:
7
+ * - Listening for discovery requests from the page
8
+ * - Creating MessageChannels after discovery approval
9
+ * - Relaying key exchange messages between page and background
10
+ * - Relaying encrypted messages between page and background
11
+ *
12
+ * The content script acts as a pure relay - it never has access to
13
+ * private keys or shared secrets.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const handler = new ContentScriptConnectionHandler({
18
+ * sendToBackground: (message) => browser.runtime.sendMessage(message),
19
+ * addBackgroundListener: (handler) => browser.runtime.onMessage.addListener(handler),
20
+ * });
21
+ *
22
+ * handler.start();
23
+ * ```
24
+ */ export class ContentScriptConnectionHandler {
25
+ transport;
26
+ ports;
27
+ listening;
28
+ pageMessageHandler;
29
+ constructor(transport){
30
+ this.transport = transport;
31
+ this.ports = new Map();
32
+ this.listening = false;
33
+ this.pageMessageHandler = null;
34
+ this.handleBackgroundMessage = (message)=>{
35
+ if (message.origin !== MessageOrigin.BACKGROUND) {
36
+ return;
37
+ }
38
+ const { type, sessionId, content } = message;
39
+ switch(type){
40
+ case InternalMessageType.DISCOVERY_APPROVED:
41
+ this.handleDiscoveryApproved(sessionId, content);
42
+ break;
43
+ case InternalMessageType.KEY_EXCHANGE_RESPONSE:
44
+ this.handleKeyExchangeResponse(sessionId, content);
45
+ break;
46
+ case InternalMessageType.SECURE_RESPONSE:
47
+ this.handleSecureResponse(sessionId, content);
48
+ break;
49
+ case InternalMessageType.SESSION_DISCONNECTED:
50
+ this.handleSessionDisconnected(sessionId);
51
+ break;
52
+ }
53
+ };
54
+ }
55
+ start() {
56
+ if (this.listening) {
57
+ return;
58
+ }
59
+ this.transport.addBackgroundListener(this.handleBackgroundMessage);
60
+ this.pageMessageHandler = (event)=>{
61
+ if (event.source !== window) {
62
+ return;
63
+ }
64
+ let data;
65
+ try {
66
+ data = JSON.parse(event.data);
67
+ } catch {
68
+ return;
69
+ }
70
+ if (!data?.type) {
71
+ return;
72
+ }
73
+ if (data.type === WalletMessageType.DISCOVERY) {
74
+ this.handleDiscoveryRequest(data);
75
+ }
76
+ };
77
+ window.addEventListener('message', this.pageMessageHandler);
78
+ this.listening = true;
79
+ }
80
+ handleBackgroundMessage;
81
+ handleDiscoveryRequest(request) {
82
+ this.transport.sendToBackground({
83
+ origin: MessageOrigin.CONTENT_SCRIPT,
84
+ type: InternalMessageType.DISCOVERY_REQUEST,
85
+ content: request
86
+ });
87
+ }
88
+ handleDiscoveryApproved(sessionId, walletInfo) {
89
+ const channel = new MessageChannel();
90
+ this.ports.set(sessionId, {
91
+ port: channel.port1,
92
+ sessionId
93
+ });
94
+ channel.port1.onmessage = (event)=>{
95
+ const data = event.data;
96
+ switch(data?.type){
97
+ case WalletMessageType.KEY_EXCHANGE_REQUEST:
98
+ this.transport.sendToBackground({
99
+ origin: MessageOrigin.CONTENT_SCRIPT,
100
+ type: InternalMessageType.KEY_EXCHANGE_REQUEST,
101
+ sessionId,
102
+ content: data
103
+ });
104
+ break;
105
+ case WalletMessageType.DISCONNECT:
106
+ this.transport.sendToBackground({
107
+ origin: MessageOrigin.CONTENT_SCRIPT,
108
+ type: InternalMessageType.DISCONNECT_REQUEST,
109
+ sessionId,
110
+ content: data
111
+ });
112
+ break;
113
+ default:
114
+ this.transport.sendToBackground({
115
+ origin: MessageOrigin.CONTENT_SCRIPT,
116
+ type: InternalMessageType.SECURE_MESSAGE,
117
+ sessionId,
118
+ content: data
119
+ });
120
+ break;
121
+ }
122
+ };
123
+ channel.port1.start();
124
+ const response = {
125
+ type: WalletMessageType.DISCOVERY_RESPONSE,
126
+ requestId: sessionId,
127
+ walletInfo
128
+ };
129
+ window.postMessage(JSON.stringify(response), '*', [
130
+ channel.port2
131
+ ]);
132
+ }
133
+ handleKeyExchangeResponse(sessionId, response) {
134
+ const connection = this.ports.get(sessionId);
135
+ if (!connection) {
136
+ return;
137
+ }
138
+ connection.port.postMessage(response);
139
+ }
140
+ handleSecureResponse(sessionId, content) {
141
+ const connection = this.ports.get(sessionId);
142
+ if (!connection) {
143
+ return;
144
+ }
145
+ connection.port.postMessage(content);
146
+ }
147
+ handleSessionDisconnected(sessionId) {
148
+ const connection = this.ports.get(sessionId);
149
+ if (!connection) {
150
+ return;
151
+ }
152
+ connection.port.postMessage({
153
+ type: WalletMessageType.DISCONNECT
154
+ });
155
+ connection.port.close();
156
+ this.ports.delete(sessionId);
157
+ }
158
+ closeConnection(sessionId) {
159
+ const connection = this.ports.get(sessionId);
160
+ if (connection) {
161
+ connection.port.close();
162
+ this.ports.delete(sessionId);
163
+ }
164
+ }
165
+ closeAllConnections() {
166
+ for (const [sessionId, connection] of this.ports){
167
+ connection.port.close();
168
+ this.ports.delete(sessionId);
169
+ }
170
+ }
171
+ getConnectionCount() {
172
+ return this.ports.size;
173
+ }
174
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Browser-safe exports for extension background and content scripts.
3
+ *
4
+ * This module contains ONLY handlers that work in service worker/content script
5
+ * environments without Node.js polyfills.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ export { BackgroundConnectionHandler, type PendingDiscovery, type ActiveSession, type DiscoveryStatus, type BackgroundConnectionCallbacks, type BackgroundConnectionConfig, type BackgroundTransport, } from './background_connection_handler.js';
10
+ export { ContentScriptConnectionHandler, type ContentScriptTransport } from './content_script_connection_handler.js';
11
+ export { type ContentScriptMessage, type BackgroundMessage, type MessageSender, type MessageOriginType, MessageOrigin, } from './internal_message_types.js';
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9leHRlbnNpb24vaGFuZGxlcnMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRztBQUNILE9BQU8sRUFDTCwyQkFBMkIsRUFDM0IsS0FBSyxnQkFBZ0IsRUFDckIsS0FBSyxhQUFhLEVBQ2xCLEtBQUssZUFBZSxFQUNwQixLQUFLLDZCQUE2QixFQUNsQyxLQUFLLDBCQUEwQixFQUMvQixLQUFLLG1CQUFtQixHQUN6QixNQUFNLG9DQUFvQyxDQUFDO0FBQzVDLE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxLQUFLLHNCQUFzQixFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDckgsT0FBTyxFQUNMLEtBQUssb0JBQW9CLEVBQ3pCLEtBQUssaUJBQWlCLEVBQ3RCLEtBQUssYUFBYSxFQUNsQixLQUFLLGlCQUFpQixFQUN0QixhQUFhLEdBQ2QsTUFBTSw2QkFBNkIsQ0FBQyJ9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extension/handlers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,2BAA2B,EAC3B,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,6BAA6B,EAClC,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,GACzB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,8BAA8B,EAAE,KAAK,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AACrH,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,aAAa,GACd,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Browser-safe exports for extension background and content scripts.
3
+ *
4
+ * This module contains ONLY handlers that work in service worker/content script
5
+ * environments without Node.js polyfills.
6
+ *
7
+ * @packageDocumentation
8
+ */ export { BackgroundConnectionHandler } from './background_connection_handler.js';
9
+ export { ContentScriptConnectionHandler } from './content_script_connection_handler.js';
10
+ export { MessageOrigin } from './internal_message_types.js';
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Internal message types for content script ↔ background communication.
3
+ * These are NOT part of the public wallet protocol - they are implementation
4
+ * details for coordinating between extension components.
5
+ */
6
+ export declare const InternalMessageType: {
7
+ readonly DISCOVERY_REQUEST: "discovery-request";
8
+ readonly KEY_EXCHANGE_REQUEST: "key-exchange-request";
9
+ readonly SECURE_MESSAGE: "secure-message";
10
+ readonly DISCONNECT_REQUEST: "disconnect-request";
11
+ readonly DISCOVERY_APPROVED: "discovery-approved";
12
+ readonly KEY_EXCHANGE_RESPONSE: "key-exchange-response";
13
+ readonly SECURE_RESPONSE: "secure-response";
14
+ readonly SESSION_DISCONNECTED: "session-disconnected";
15
+ };
16
+ /**
17
+ * Message origins for internal extension communication.
18
+ */
19
+ export declare const MessageOrigin: {
20
+ readonly BACKGROUND: "background";
21
+ readonly CONTENT_SCRIPT: "content-script";
22
+ };
23
+ /** Union type of message origins. */
24
+ export type MessageOriginType = (typeof MessageOrigin)[keyof typeof MessageOrigin];
25
+ /**
26
+ * Message sent from content script to background.
27
+ */
28
+ export interface ContentScriptMessage {
29
+ /** Message source identifier. */
30
+ origin: typeof MessageOrigin.CONTENT_SCRIPT;
31
+ /** Message type. */
32
+ type: string;
33
+ /** Optional session identifier. */
34
+ sessionId?: string;
35
+ /** Optional message payload. */
36
+ content?: unknown;
37
+ }
38
+ /**
39
+ * Message sent from background to content script.
40
+ */
41
+ export interface BackgroundMessage {
42
+ /** Message source identifier. */
43
+ origin: typeof MessageOrigin.BACKGROUND;
44
+ /** Message type. */
45
+ type: string;
46
+ /** Session identifier. */
47
+ sessionId: string;
48
+ /** Optional message payload. */
49
+ content?: unknown;
50
+ }
51
+ /**
52
+ * Sender information for messages from browser runtime.
53
+ */
54
+ export interface MessageSender {
55
+ /** Tab information if available. */
56
+ tab?: {
57
+ /** Tab identifier. */
58
+ id?: number;
59
+ /** Tab URL. */
60
+ url?: string;
61
+ };
62
+ }
63
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJuYWxfbWVzc2FnZV90eXBlcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2V4dGVuc2lvbi9oYW5kbGVycy9pbnRlcm5hbF9tZXNzYWdlX3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFDSCxlQUFPLE1BQU0sbUJBQW1COzs7Ozs7Ozs7Q0FXdEIsQ0FBQztBQUVYOztHQUVHO0FBQ0gsZUFBTyxNQUFNLGFBQWE7OztDQUdoQixDQUFDO0FBRVgscUNBQXFDO0FBQ3JDLE1BQU0sTUFBTSxpQkFBaUIsR0FBRyxDQUFDLE9BQU8sYUFBYSxDQUFDLENBQUMsTUFBTSxPQUFPLGFBQWEsQ0FBQyxDQUFDO0FBRW5GOztHQUVHO0FBQ0gsTUFBTSxXQUFXLG9CQUFvQjtJQUNuQyxpQ0FBaUM7SUFDakMsTUFBTSxFQUFFLE9BQU8sYUFBYSxDQUFDLGNBQWMsQ0FBQztJQUM1QyxvQkFBb0I7SUFDcEIsSUFBSSxFQUFFLE1BQU0sQ0FBQztJQUNiLG1DQUFtQztJQUNuQyxTQUFTLENBQUMsRUFBRSxNQUFNLENBQUM7SUFDbkIsZ0NBQWdDO0lBQ2hDLE9BQU8sQ0FBQyxFQUFFLE9BQU8sQ0FBQztDQUNuQjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxXQUFXLGlCQUFpQjtJQUNoQyxpQ0FBaUM7SUFDakMsTUFBTSxFQUFFLE9BQU8sYUFBYSxDQUFDLFVBQVUsQ0FBQztJQUN4QyxvQkFBb0I7SUFDcEIsSUFBSSxFQUFFLE1BQU0sQ0FBQztJQUNiLDBCQUEwQjtJQUMxQixTQUFTLEVBQUUsTUFBTSxDQUFDO0lBQ2xCLGdDQUFnQztJQUNoQyxPQUFPLENBQUMsRUFBRSxPQUFPLENBQUM7Q0FDbkI7QUFFRDs7R0FFRztBQUNILE1BQU0sV0FBVyxhQUFhO0lBQzVCLG9DQUFvQztJQUNwQyxHQUFHLENBQUMsRUFBRTtRQUNKLHNCQUFzQjtRQUN0QixFQUFFLENBQUMsRUFBRSxNQUFNLENBQUM7UUFDWixlQUFlO1FBQ2YsR0FBRyxDQUFDLEVBQUUsTUFBTSxDQUFDO0tBQ2QsQ0FBQztDQUNIIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal_message_types.d.ts","sourceRoot":"","sources":["../../../src/extension/handlers/internal_message_types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;CAWtB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,aAAa;;;CAGhB,CAAC;AAEX,qCAAqC;AACrC,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC;AAEnF;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,iCAAiC;IACjC,MAAM,EAAE,OAAO,aAAa,CAAC,cAAc,CAAC;IAC5C,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iCAAiC;IACjC,MAAM,EAAE,OAAO,aAAa,CAAC,UAAU,CAAC;IACxC,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,oCAAoC;IACpC,GAAG,CAAC,EAAE;QACJ,sBAAsB;QACtB,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,eAAe;QACf,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;CACH"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Internal message types for content script ↔ background communication.
3
+ * These are NOT part of the public wallet protocol - they are implementation
4
+ * details for coordinating between extension components.
5
+ */ export const InternalMessageType = {
6
+ // Content script → Background
7
+ DISCOVERY_REQUEST: 'discovery-request',
8
+ KEY_EXCHANGE_REQUEST: 'key-exchange-request',
9
+ SECURE_MESSAGE: 'secure-message',
10
+ DISCONNECT_REQUEST: 'disconnect-request',
11
+ // Background → Content script
12
+ DISCOVERY_APPROVED: 'discovery-approved',
13
+ KEY_EXCHANGE_RESPONSE: 'key-exchange-response',
14
+ SECURE_RESPONSE: 'secure-response',
15
+ SESSION_DISCONNECTED: 'session-disconnected'
16
+ };
17
+ /**
18
+ * Message origins for internal extension communication.
19
+ */ export const MessageOrigin = {
20
+ BACKGROUND: 'background',
21
+ CONTENT_SCRIPT: 'content-script'
22
+ };