@aztec/wallet-sdk 4.0.0-nightly.20260113 → 4.0.0-nightly.20260114
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.
- package/README.md +211 -271
- package/dest/base-wallet/base_wallet.d.ts +14 -4
- package/dest/base-wallet/base_wallet.d.ts.map +1 -1
- package/dest/base-wallet/base_wallet.js +29 -10
- package/dest/crypto.d.ts +38 -1
- package/dest/crypto.d.ts.map +1 -1
- package/dest/crypto.js +85 -1
- package/dest/manager/wallet_manager.d.ts +1 -1
- package/dest/manager/wallet_manager.d.ts.map +1 -1
- package/dest/manager/wallet_manager.js +9 -13
- package/dest/providers/extension/extension_provider.d.ts +52 -6
- package/dest/providers/extension/extension_provider.d.ts.map +1 -1
- package/dest/providers/extension/extension_provider.js +78 -11
- package/dest/providers/extension/extension_wallet.d.ts +30 -30
- package/dest/providers/extension/extension_wallet.d.ts.map +1 -1
- package/dest/providers/extension/extension_wallet.js +40 -73
- package/dest/providers/extension/index.d.ts +3 -3
- package/dest/providers/extension/index.d.ts.map +1 -1
- package/dest/types.d.ts +9 -14
- package/dest/types.d.ts.map +1 -1
- package/dest/types.js +1 -1
- package/package.json +8 -8
- package/src/base-wallet/base_wallet.ts +37 -13
- package/src/crypto.ts +93 -1
- package/src/manager/wallet_manager.ts +9 -13
- package/src/providers/extension/extension_provider.ts +109 -14
- package/src/providers/extension/extension_wallet.ts +45 -91
- package/src/providers/extension/index.ts +2 -9
- package/src/types.ts +8 -14
|
@@ -35,26 +35,25 @@ export class WalletManager {
|
|
|
35
35
|
const providers: WalletProvider[] = [];
|
|
36
36
|
const { chainInfo } = options;
|
|
37
37
|
|
|
38
|
-
// Discover extension wallets
|
|
39
38
|
if (this.config.extensions?.enabled) {
|
|
40
|
-
const
|
|
39
|
+
const discoveredWallets = await ExtensionProvider.discoverExtensions(chainInfo, options.timeout);
|
|
41
40
|
const extensionConfig = this.config.extensions;
|
|
42
41
|
|
|
43
|
-
for (const
|
|
44
|
-
|
|
45
|
-
if (!this.isExtensionAllowed(ext.id, extensionConfig)) {
|
|
42
|
+
for (const { info, port, sharedKey } of discoveredWallets) {
|
|
43
|
+
if (!this.isExtensionAllowed(info.id, extensionConfig)) {
|
|
46
44
|
continue;
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
providers.push({
|
|
50
|
-
id:
|
|
48
|
+
id: info.id,
|
|
51
49
|
type: 'extension',
|
|
52
|
-
name:
|
|
53
|
-
icon:
|
|
50
|
+
name: info.name,
|
|
51
|
+
icon: info.icon,
|
|
54
52
|
metadata: {
|
|
55
|
-
version:
|
|
53
|
+
version: info.version,
|
|
54
|
+
verificationHash: info.verificationHash,
|
|
56
55
|
},
|
|
57
|
-
connect: (appId: string) => ExtensionWallet.create(
|
|
56
|
+
connect: (appId: string) => Promise.resolve(ExtensionWallet.create(info, chainInfo, port, sharedKey, appId)),
|
|
58
57
|
});
|
|
59
58
|
}
|
|
60
59
|
}
|
|
@@ -70,17 +69,14 @@ export class WalletManager {
|
|
|
70
69
|
* @param config - Extension wallet configuration containing allow/block lists
|
|
71
70
|
*/
|
|
72
71
|
private isExtensionAllowed(extensionId: string, config: ExtensionWalletConfig): boolean {
|
|
73
|
-
// Check block list first
|
|
74
72
|
if (config.blockList && config.blockList.includes(extensionId)) {
|
|
75
73
|
return false;
|
|
76
74
|
}
|
|
77
75
|
|
|
78
|
-
// If allow list exists, extension must be in it
|
|
79
76
|
if (config.allowList && config.allowList.length > 0) {
|
|
80
77
|
return config.allowList.includes(extensionId);
|
|
81
78
|
}
|
|
82
79
|
|
|
83
|
-
// If no allow list, extension is allowed (unless blocked)
|
|
84
80
|
return true;
|
|
85
81
|
}
|
|
86
82
|
}
|
|
@@ -2,34 +2,95 @@ import type { ChainInfo } from '@aztec/aztec.js/account';
|
|
|
2
2
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
3
3
|
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
4
4
|
|
|
5
|
+
import { deriveSharedKey, exportPublicKey, generateKeyPair, hashSharedSecret, importPublicKey } from '../../crypto.js';
|
|
5
6
|
import type { DiscoveryRequest, DiscoveryResponse, WalletInfo } from '../../types.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
*
|
|
9
|
+
* A discovered wallet with its secure channel components.
|
|
10
|
+
* Returned by {@link ExtensionProvider.discoverExtensions}.
|
|
11
|
+
*/
|
|
12
|
+
export interface DiscoveredWallet {
|
|
13
|
+
/** Basic wallet information (id, name, icon, version, publicKey, verificationHash) */
|
|
14
|
+
info: WalletInfo;
|
|
15
|
+
/** The MessagePort for private communication with the wallet */
|
|
16
|
+
port: MessagePort;
|
|
17
|
+
/** The derived AES-256-GCM shared key for encryption */
|
|
18
|
+
sharedKey: CryptoKey;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Internal type for discovery response with MessagePort
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
interface DiscoveryResponseWithPort extends DiscoveryResponse {
|
|
26
|
+
/** The MessagePort transferred from the wallet */
|
|
27
|
+
port?: MessagePort;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Provider for discovering Aztec wallet extensions.
|
|
32
|
+
*
|
|
33
|
+
* This class handles the discovery phase of wallet communication:
|
|
34
|
+
* 1. Broadcasts a discovery request with the dApp's public key
|
|
35
|
+
* 2. Receives responses from installed wallets with their public keys
|
|
36
|
+
* 3. Derives shared secrets and computes verification hashes
|
|
37
|
+
* 4. Returns discovered wallets with their secure channel components
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const wallets = await ExtensionProvider.discoverExtensions(chainInfo);
|
|
42
|
+
* // Display wallets to user with optional emoji verification
|
|
43
|
+
* for (const wallet of wallets) {
|
|
44
|
+
* const emoji = hashToEmoji(wallet.info.verificationHash!);
|
|
45
|
+
* console.log(`${wallet.info.name}: ${emoji}`);
|
|
46
|
+
* }
|
|
47
|
+
* // User selects a wallet after verifying
|
|
48
|
+
* const wallet = await ExtensionWallet.create(wallets[0], chainInfo, 'my-app');
|
|
49
|
+
* ```
|
|
9
50
|
*/
|
|
10
51
|
export class ExtensionProvider {
|
|
11
|
-
private static discoveredExtensions: Map<string, WalletInfo> = new Map();
|
|
12
52
|
private static discoveryInProgress = false;
|
|
13
53
|
|
|
14
54
|
/**
|
|
15
|
-
* Discovers all installed Aztec wallet extensions
|
|
55
|
+
* Discovers all installed Aztec wallet extensions and establishes secure channel components.
|
|
56
|
+
*
|
|
57
|
+
* This method:
|
|
58
|
+
* 1. Generates an ECDH key pair for this discovery session
|
|
59
|
+
* 2. Broadcasts a discovery request with the dApp's public key
|
|
60
|
+
* 3. Receives responses from wallets with their public keys and MessagePorts
|
|
61
|
+
* 4. Derives shared secrets and computes verification hashes
|
|
62
|
+
*
|
|
16
63
|
* @param chainInfo - Chain information to check if extensions support this network
|
|
17
64
|
* @param timeout - How long to wait for extensions to respond (ms)
|
|
18
|
-
* @returns Array of discovered
|
|
65
|
+
* @returns Array of discovered wallets with their secure channel components
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const wallets = await ExtensionProvider.discoverExtensions({
|
|
70
|
+
* chainId: Fr(31337),
|
|
71
|
+
* version: Fr(0)
|
|
72
|
+
* });
|
|
73
|
+
* // Access wallet info and secure channel
|
|
74
|
+
* const { info, port, sharedKey } = wallets[0];
|
|
75
|
+
* ```
|
|
19
76
|
*/
|
|
20
|
-
static async discoverExtensions(chainInfo: ChainInfo, timeout: number = 1000): Promise<
|
|
21
|
-
// If discovery is in progress, wait
|
|
77
|
+
static async discoverExtensions(chainInfo: ChainInfo, timeout: number = 1000): Promise<DiscoveredWallet[]> {
|
|
78
|
+
// If discovery is already in progress, wait and return empty
|
|
79
|
+
// (caller should retry or handle appropriately)
|
|
22
80
|
if (this.discoveryInProgress) {
|
|
23
81
|
await new Promise(resolve => setTimeout(resolve, timeout));
|
|
24
|
-
return
|
|
82
|
+
return [];
|
|
25
83
|
}
|
|
26
84
|
|
|
27
85
|
this.discoveryInProgress = true;
|
|
28
|
-
this.discoveredExtensions.clear();
|
|
29
86
|
|
|
30
|
-
|
|
87
|
+
// Generate key pair for this discovery session
|
|
88
|
+
const keyPair = await generateKeyPair();
|
|
89
|
+
const exportedPublicKey = await exportPublicKey(keyPair.publicKey);
|
|
90
|
+
|
|
91
|
+
const { promise, resolve } = promiseWithResolvers<DiscoveredWallet[]>();
|
|
31
92
|
const requestId = globalThis.crypto.randomUUID();
|
|
32
|
-
const responses:
|
|
93
|
+
const responses: DiscoveredWallet[] = [];
|
|
33
94
|
|
|
34
95
|
// Set up listener for discovery responses
|
|
35
96
|
const handleMessage = (event: MessageEvent) => {
|
|
@@ -37,7 +98,7 @@ export class ExtensionProvider {
|
|
|
37
98
|
return;
|
|
38
99
|
}
|
|
39
100
|
|
|
40
|
-
let data:
|
|
101
|
+
let data: DiscoveryResponseWithPort;
|
|
41
102
|
try {
|
|
42
103
|
data = JSON.parse(event.data);
|
|
43
104
|
} catch {
|
|
@@ -45,18 +106,52 @@ export class ExtensionProvider {
|
|
|
45
106
|
}
|
|
46
107
|
|
|
47
108
|
if (data.type === 'aztec-wallet-discovery-response' && data.requestId === requestId) {
|
|
48
|
-
|
|
49
|
-
|
|
109
|
+
// Get the MessagePort from the event
|
|
110
|
+
const port = event.ports?.[0];
|
|
111
|
+
if (!port) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Derive shared key from wallet's public key
|
|
116
|
+
const walletPublicKey = data.walletInfo.publicKey;
|
|
117
|
+
if (!walletPublicKey) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
void (async () => {
|
|
122
|
+
try {
|
|
123
|
+
const importedWalletKey = await importPublicKey(walletPublicKey);
|
|
124
|
+
const sharedKey = await deriveSharedKey(keyPair.privateKey, importedWalletKey);
|
|
125
|
+
|
|
126
|
+
// Compute verification hash
|
|
127
|
+
const verificationHash = await hashSharedSecret(sharedKey);
|
|
128
|
+
|
|
129
|
+
// Create wallet info with verification hash
|
|
130
|
+
const walletInfo: WalletInfo = {
|
|
131
|
+
...data.walletInfo,
|
|
132
|
+
verificationHash,
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
responses.push({
|
|
136
|
+
info: walletInfo,
|
|
137
|
+
port,
|
|
138
|
+
sharedKey,
|
|
139
|
+
});
|
|
140
|
+
} catch {
|
|
141
|
+
// Failed to derive key, skip this wallet
|
|
142
|
+
}
|
|
143
|
+
})();
|
|
50
144
|
}
|
|
51
145
|
};
|
|
52
146
|
|
|
53
147
|
window.addEventListener('message', handleMessage);
|
|
54
148
|
|
|
55
|
-
// Send discovery message
|
|
149
|
+
// Send discovery message with our public key
|
|
56
150
|
const discoveryMessage: DiscoveryRequest = {
|
|
57
151
|
type: 'aztec-wallet-discovery',
|
|
58
152
|
requestId,
|
|
59
153
|
chainInfo,
|
|
154
|
+
publicKey: exportedPublicKey,
|
|
60
155
|
};
|
|
61
156
|
window.postMessage(jsonStringify(discoveryMessage), '*');
|
|
62
157
|
|
|
@@ -5,17 +5,8 @@ import { type PromiseWithResolvers, promiseWithResolvers } from '@aztec/foundati
|
|
|
5
5
|
import { schemaHasMethod } from '@aztec/foundation/schemas';
|
|
6
6
|
import type { FunctionsOf } from '@aztec/foundation/types';
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
type ExportedPublicKey,
|
|
11
|
-
decrypt,
|
|
12
|
-
deriveSharedKey,
|
|
13
|
-
encrypt,
|
|
14
|
-
exportPublicKey,
|
|
15
|
-
generateKeyPair,
|
|
16
|
-
importPublicKey,
|
|
17
|
-
} from '../../crypto.js';
|
|
18
|
-
import type { ConnectRequest, WalletInfo, WalletMessage, WalletResponse } from '../../types.js';
|
|
8
|
+
import { type EncryptedPayload, decrypt, encrypt } from '../../crypto.js';
|
|
9
|
+
import type { WalletInfo, WalletMessage, WalletResponse } from '../../types.js';
|
|
19
10
|
|
|
20
11
|
/**
|
|
21
12
|
* Internal type representing a wallet method call before encryption.
|
|
@@ -32,26 +23,28 @@ type WalletMethodCall = {
|
|
|
32
23
|
* A wallet implementation that communicates with browser extension wallets
|
|
33
24
|
* using a secure encrypted MessageChannel.
|
|
34
25
|
*
|
|
35
|
-
* This class
|
|
36
|
-
* using the following security mechanisms:
|
|
26
|
+
* This class uses a pre-established secure channel from the discovery phase:
|
|
37
27
|
*
|
|
38
|
-
* 1. **MessageChannel**:
|
|
39
|
-
* visible to other scripts on the page (unlike window.postMessage).
|
|
28
|
+
* 1. **MessageChannel**: A private communication channel created during discovery,
|
|
29
|
+
* not visible to other scripts on the page (unlike window.postMessage).
|
|
40
30
|
*
|
|
41
|
-
* 2. **ECDH Key Exchange**:
|
|
42
|
-
*
|
|
31
|
+
* 2. **ECDH Key Exchange**: The shared secret was derived during discovery using
|
|
32
|
+
* Elliptic Curve Diffie-Hellman key exchange.
|
|
43
33
|
*
|
|
44
|
-
* 3. **AES-GCM Encryption**: All messages
|
|
45
|
-
*
|
|
34
|
+
* 3. **AES-GCM Encryption**: All messages are encrypted using AES-256-GCM,
|
|
35
|
+
* providing both confidentiality and authenticity.
|
|
46
36
|
*
|
|
47
37
|
* @example
|
|
48
38
|
* ```typescript
|
|
49
|
-
* // Discovery returns
|
|
39
|
+
* // Discovery returns wallets with secure channel components
|
|
50
40
|
* const wallets = await ExtensionProvider.discoverExtensions(chainInfo);
|
|
51
|
-
* const
|
|
41
|
+
* const { info, port, sharedKey } = wallets[0];
|
|
52
42
|
*
|
|
53
|
-
* //
|
|
54
|
-
*
|
|
43
|
+
* // User can verify emoji if desired
|
|
44
|
+
* console.log('Verify:', hashToEmoji(info.verificationHash!));
|
|
45
|
+
*
|
|
46
|
+
* // Create wallet using the discovered components
|
|
47
|
+
* const wallet = await ExtensionWallet.create(info, chainInfo, port, sharedKey, 'my-dapp');
|
|
55
48
|
*
|
|
56
49
|
* // All subsequent calls are encrypted
|
|
57
50
|
* const accounts = await wallet.getAccounts();
|
|
@@ -61,58 +54,61 @@ export class ExtensionWallet {
|
|
|
61
54
|
/** Map of pending requests awaiting responses, keyed by message ID */
|
|
62
55
|
private inFlight = new Map<string, PromiseWithResolvers<unknown>>();
|
|
63
56
|
|
|
64
|
-
/** The MessagePort for private communication with the extension */
|
|
65
|
-
private port: MessagePort | null = null;
|
|
66
|
-
|
|
67
|
-
/** The derived AES-GCM key for encrypting/decrypting messages */
|
|
68
|
-
private sharedKey: CryptoKey | null = null;
|
|
69
|
-
|
|
70
57
|
/**
|
|
71
58
|
* Private constructor - use {@link ExtensionWallet.create} to instantiate.
|
|
72
59
|
* @param chainInfo - The chain information (chainId and version)
|
|
73
60
|
* @param appId - Application identifier for the requesting dApp
|
|
74
61
|
* @param extensionId - The unique identifier of the target wallet extension
|
|
62
|
+
* @param port - The MessagePort for private communication with the wallet
|
|
63
|
+
* @param sharedKey - The derived AES-256-GCM shared key for encryption
|
|
75
64
|
*/
|
|
76
65
|
private constructor(
|
|
77
66
|
private chainInfo: ChainInfo,
|
|
78
67
|
private appId: string,
|
|
79
68
|
private extensionId: string,
|
|
69
|
+
private port: MessagePort,
|
|
70
|
+
private sharedKey: CryptoKey,
|
|
80
71
|
) {}
|
|
81
72
|
|
|
82
73
|
/**
|
|
83
74
|
* Creates an ExtensionWallet instance that proxies wallet calls to a browser extension
|
|
84
75
|
* over a secure encrypted MessageChannel.
|
|
85
76
|
*
|
|
86
|
-
* The
|
|
87
|
-
* 1. Generates an ECDH key pair for this session
|
|
88
|
-
* 2. Derives a shared AES-256 key using the wallet's public key
|
|
89
|
-
* 3. Creates a MessageChannel and transfers one port to the extension
|
|
90
|
-
* 4. Returns a Proxy that encrypts all wallet method calls
|
|
91
|
-
*
|
|
92
|
-
* @param walletInfo - The discovered wallet information, including the wallet's ECDH public key
|
|
77
|
+
* @param walletInfo - The wallet info from ExtensionProvider.discoverExtensions()
|
|
93
78
|
* @param chainInfo - The chain information (chainId and version) for request context
|
|
79
|
+
* @param port - The MessagePort for private communication with the wallet
|
|
80
|
+
* @param sharedKey - The derived AES-256-GCM shared key for encryption
|
|
94
81
|
* @param appId - Application identifier used to identify the requesting dApp to the wallet
|
|
95
82
|
* @returns A Promise resolving to a Wallet implementation that encrypts all communication
|
|
96
83
|
*
|
|
97
|
-
* @throws Error if the secure channel cannot be established
|
|
98
|
-
*
|
|
99
84
|
* @example
|
|
100
85
|
* ```typescript
|
|
86
|
+
* const wallets = await ExtensionProvider.discoverExtensions(chainInfo);
|
|
87
|
+
* const { info, port, sharedKey } = wallets[0];
|
|
101
88
|
* const wallet = await ExtensionWallet.create(
|
|
102
|
-
*
|
|
89
|
+
* info,
|
|
103
90
|
* { chainId: Fr(31337), version: Fr(0) },
|
|
91
|
+
* port,
|
|
92
|
+
* sharedKey,
|
|
104
93
|
* 'my-defi-app'
|
|
105
94
|
* );
|
|
106
95
|
* ```
|
|
107
96
|
*/
|
|
108
|
-
static
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
97
|
+
static create(
|
|
98
|
+
walletInfo: WalletInfo,
|
|
99
|
+
chainInfo: ChainInfo,
|
|
100
|
+
port: MessagePort,
|
|
101
|
+
sharedKey: CryptoKey,
|
|
102
|
+
appId: string,
|
|
103
|
+
): Wallet {
|
|
104
|
+
const wallet = new ExtensionWallet(chainInfo, appId, walletInfo.id, port, sharedKey);
|
|
105
|
+
|
|
106
|
+
// Set up message handler
|
|
107
|
+
wallet.port.onmessage = (event: MessageEvent<EncryptedPayload>) => {
|
|
108
|
+
void wallet.handleEncryptedResponse(event.data);
|
|
109
|
+
};
|
|
114
110
|
|
|
115
|
-
|
|
111
|
+
wallet.port.start();
|
|
116
112
|
|
|
117
113
|
// Create a Proxy that intercepts wallet method calls and forwards them to the extension
|
|
118
114
|
return new Proxy(wallet, {
|
|
@@ -132,47 +128,6 @@ export class ExtensionWallet {
|
|
|
132
128
|
}) as unknown as Wallet;
|
|
133
129
|
}
|
|
134
130
|
|
|
135
|
-
/**
|
|
136
|
-
* Establishes a secure MessageChannel with ECDH key exchange.
|
|
137
|
-
*
|
|
138
|
-
* This method performs the cryptographic handshake:
|
|
139
|
-
* 1. Generates a new ECDH P-256 key pair for this session
|
|
140
|
-
* 2. Imports the wallet's public key and derives a shared secret
|
|
141
|
-
* 3. Creates a MessageChannel for private communication
|
|
142
|
-
* 4. Sends a connection request with our public key via window.postMessage
|
|
143
|
-
* (this is the only public message - subsequent communication uses the private channel)
|
|
144
|
-
*
|
|
145
|
-
* @param walletExportedPublicKey - The wallet's ECDH public key in JWK format
|
|
146
|
-
*/
|
|
147
|
-
private async establishSecureChannel(walletExportedPublicKey: ExportedPublicKey): Promise<void> {
|
|
148
|
-
const keyPair = await generateKeyPair();
|
|
149
|
-
const exportedPublicKey = await exportPublicKey(keyPair.publicKey);
|
|
150
|
-
|
|
151
|
-
const walletPublicKey = await importPublicKey(walletExportedPublicKey);
|
|
152
|
-
this.sharedKey = await deriveSharedKey(keyPair.privateKey, walletPublicKey);
|
|
153
|
-
|
|
154
|
-
const channel = new MessageChannel();
|
|
155
|
-
this.port = channel.port1;
|
|
156
|
-
|
|
157
|
-
this.port.onmessage = async (event: MessageEvent<EncryptedPayload>) => {
|
|
158
|
-
await this.handleEncryptedResponse(event.data);
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
this.port.start();
|
|
162
|
-
|
|
163
|
-
// Send connection request with our public key and transfer port2 to content script
|
|
164
|
-
// This is the only public postMessage - it contains our public key (safe to expose)
|
|
165
|
-
// and transfers the MessagePort for subsequent private communication
|
|
166
|
-
const connectRequest: ConnectRequest = {
|
|
167
|
-
type: 'aztec-wallet-connect',
|
|
168
|
-
walletId: this.extensionId,
|
|
169
|
-
appId: this.appId,
|
|
170
|
-
publicKey: exportedPublicKey,
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
window.postMessage(jsonStringify(connectRequest), '*', [channel.port2]);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
131
|
/**
|
|
177
132
|
* Handles an encrypted response received from the wallet extension.
|
|
178
133
|
*
|
|
@@ -219,7 +174,7 @@ export class ExtensionWallet {
|
|
|
219
174
|
* Sends an encrypted wallet method call over the secure MessageChannel.
|
|
220
175
|
*
|
|
221
176
|
* The message is encrypted using AES-256-GCM with the shared key derived
|
|
222
|
-
* during
|
|
177
|
+
* during discovery. A unique message ID is generated to correlate
|
|
223
178
|
* the response.
|
|
224
179
|
*
|
|
225
180
|
* @param call - The wallet method call containing method name and arguments
|
|
@@ -259,7 +214,8 @@ export class ExtensionWallet {
|
|
|
259
214
|
*
|
|
260
215
|
* @example
|
|
261
216
|
* ```typescript
|
|
262
|
-
* const
|
|
217
|
+
* const { info, port, sharedKey } = wallets[0];
|
|
218
|
+
* const wallet = await ExtensionWallet.create(info, chainInfo, port, sharedKey, 'my-app');
|
|
263
219
|
* // ... use wallet ...
|
|
264
220
|
* wallet.close(); // Clean up when done
|
|
265
221
|
* ```
|
|
@@ -267,9 +223,7 @@ export class ExtensionWallet {
|
|
|
267
223
|
close(): void {
|
|
268
224
|
if (this.port) {
|
|
269
225
|
this.port.close();
|
|
270
|
-
this.port = null;
|
|
271
226
|
}
|
|
272
|
-
this.sharedKey = null;
|
|
273
227
|
this.inFlight.clear();
|
|
274
228
|
}
|
|
275
229
|
}
|
|
@@ -1,11 +1,4 @@
|
|
|
1
1
|
export { ExtensionWallet } from './extension_wallet.js';
|
|
2
|
-
export { ExtensionProvider } from './extension_provider.js';
|
|
2
|
+
export { ExtensionProvider, type DiscoveredWallet } from './extension_provider.js';
|
|
3
3
|
export * from '../../crypto.js';
|
|
4
|
-
export type {
|
|
5
|
-
WalletInfo,
|
|
6
|
-
WalletMessage,
|
|
7
|
-
WalletResponse,
|
|
8
|
-
DiscoveryRequest,
|
|
9
|
-
DiscoveryResponse,
|
|
10
|
-
ConnectRequest,
|
|
11
|
-
} from '../../types.js';
|
|
4
|
+
export type { WalletInfo, WalletMessage, WalletResponse, DiscoveryRequest, DiscoveryResponse } from '../../types.js';
|
package/src/types.ts
CHANGED
|
@@ -16,6 +16,12 @@ export interface WalletInfo {
|
|
|
16
16
|
version: string;
|
|
17
17
|
/** Wallet's ECDH public key for secure channel establishment */
|
|
18
18
|
publicKey: ExportedPublicKey;
|
|
19
|
+
/**
|
|
20
|
+
* Hash of the shared secret for anti-MITM verification.
|
|
21
|
+
* Both dApp and wallet independently compute this from the ECDH shared secret.
|
|
22
|
+
* Use {@link hashToEmoji} to convert to a visual representation for user verification.
|
|
23
|
+
*/
|
|
24
|
+
verificationHash?: string;
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
/**
|
|
@@ -60,6 +66,8 @@ export interface DiscoveryRequest {
|
|
|
60
66
|
requestId: string;
|
|
61
67
|
/** Chain information to check if wallet supports this network */
|
|
62
68
|
chainInfo: ChainInfo;
|
|
69
|
+
/** dApp's ECDH public key for deriving shared secret */
|
|
70
|
+
publicKey: ExportedPublicKey;
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
/**
|
|
@@ -73,17 +81,3 @@ export interface DiscoveryResponse {
|
|
|
73
81
|
/** Wallet information */
|
|
74
82
|
walletInfo: WalletInfo;
|
|
75
83
|
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Connection request to establish secure channel
|
|
79
|
-
*/
|
|
80
|
-
export interface ConnectRequest {
|
|
81
|
-
/** Message type for connection */
|
|
82
|
-
type: 'aztec-wallet-connect';
|
|
83
|
-
/** Target wallet ID */
|
|
84
|
-
walletId: string;
|
|
85
|
-
/** Application ID */
|
|
86
|
-
appId: string;
|
|
87
|
-
/** dApp's ECDH public key for deriving shared secret */
|
|
88
|
-
publicKey: ExportedPublicKey;
|
|
89
|
-
}
|