@aztec/wallet-sdk 4.0.0-nightly.20260113 → 4.0.0-nightly.20260115

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.
@@ -5,26 +5,28 @@ import type { WalletInfo } from '../../types.js';
5
5
  * A wallet implementation that communicates with browser extension wallets
6
6
  * using a secure encrypted MessageChannel.
7
7
  *
8
- * This class establishes a private communication channel with a wallet extension
9
- * using the following security mechanisms:
8
+ * This class uses a pre-established secure channel from the discovery phase:
10
9
  *
11
- * 1. **MessageChannel**: Creates a private communication channel that is not
12
- * visible to other scripts on the page (unlike window.postMessage).
10
+ * 1. **MessageChannel**: A private communication channel created during discovery,
11
+ * not visible to other scripts on the page (unlike window.postMessage).
13
12
  *
14
- * 2. **ECDH Key Exchange**: Uses Elliptic Curve Diffie-Hellman to derive a
15
- * shared secret between the dApp and wallet without transmitting private keys.
13
+ * 2. **ECDH Key Exchange**: The shared secret was derived during discovery using
14
+ * Elliptic Curve Diffie-Hellman key exchange.
16
15
  *
17
- * 3. **AES-GCM Encryption**: All messages after channel establishment are
18
- * encrypted using AES-256-GCM, providing both confidentiality and authenticity.
16
+ * 3. **AES-GCM Encryption**: All messages are encrypted using AES-256-GCM,
17
+ * providing both confidentiality and authenticity.
19
18
  *
20
19
  * @example
21
20
  * ```typescript
22
- * // Discovery returns wallet info including the wallet's public key
21
+ * // Discovery returns wallets with secure channel components
23
22
  * const wallets = await ExtensionProvider.discoverExtensions(chainInfo);
24
- * const walletInfo = wallets[0];
23
+ * const { info, port, sharedKey } = wallets[0];
25
24
  *
26
- * // Create a secure connection to the wallet
27
- * const wallet = await ExtensionWallet.create(walletInfo, chainInfo, 'my-dapp');
25
+ * // User can verify emoji if desired
26
+ * console.log('Verify:', hashToEmoji(info.verificationHash!));
27
+ *
28
+ * // Create wallet using the discovered components
29
+ * const wallet = await ExtensionWallet.create(info, chainInfo, port, sharedKey, 'my-dapp');
28
30
  *
29
31
  * // All subsequent calls are encrypted
30
32
  * const accounts = await wallet.getAccounts();
@@ -34,47 +36,44 @@ export declare class ExtensionWallet {
34
36
  private chainInfo;
35
37
  private appId;
36
38
  private extensionId;
37
- /** Map of pending requests awaiting responses, keyed by message ID */
38
- private inFlight;
39
- /** The MessagePort for private communication with the extension */
40
39
  private port;
41
- /** The derived AES-GCM key for encrypting/decrypting messages */
42
40
  private sharedKey;
41
+ /** Map of pending requests awaiting responses, keyed by message ID */
42
+ private inFlight;
43
43
  /**
44
44
  * Private constructor - use {@link ExtensionWallet.create} to instantiate.
45
45
  * @param chainInfo - The chain information (chainId and version)
46
46
  * @param appId - Application identifier for the requesting dApp
47
47
  * @param extensionId - The unique identifier of the target wallet extension
48
+ * @param port - The MessagePort for private communication with the wallet
49
+ * @param sharedKey - The derived AES-256-GCM shared key for encryption
48
50
  */
49
51
  private constructor();
50
52
  /**
51
53
  * Creates an ExtensionWallet instance that proxies wallet calls to a browser extension
52
54
  * over a secure encrypted MessageChannel.
53
55
  *
54
- * The connection process:
55
- * 1. Generates an ECDH key pair for this session
56
- * 2. Derives a shared AES-256 key using the wallet's public key
57
- * 3. Creates a MessageChannel and transfers one port to the extension
58
- * 4. Returns a Proxy that encrypts all wallet method calls
59
- *
60
- * @param walletInfo - The discovered wallet information, including the wallet's ECDH public key
56
+ * @param walletInfo - The wallet info from ExtensionProvider.discoverExtensions()
61
57
  * @param chainInfo - The chain information (chainId and version) for request context
58
+ * @param port - The MessagePort for private communication with the wallet
59
+ * @param sharedKey - The derived AES-256-GCM shared key for encryption
62
60
  * @param appId - Application identifier used to identify the requesting dApp to the wallet
63
61
  * @returns A Promise resolving to a Wallet implementation that encrypts all communication
64
62
  *
65
- * @throws Error if the secure channel cannot be established
66
- *
67
63
  * @example
68
64
  * ```typescript
65
+ * const wallets = await ExtensionProvider.discoverExtensions(chainInfo);
66
+ * const { info, port, sharedKey } = wallets[0];
69
67
  * const wallet = await ExtensionWallet.create(
70
- * walletInfo,
68
+ * info,
71
69
  * { chainId: Fr(31337), version: Fr(0) },
70
+ * port,
71
+ * sharedKey,
72
72
  * 'my-defi-app'
73
73
  * );
74
74
  * ```
75
75
  */
76
- static create(walletInfo: WalletInfo, chainInfo: ChainInfo, appId: string): Promise<Wallet>;
77
- private establishSecureChannel;
76
+ static create(walletInfo: WalletInfo, chainInfo: ChainInfo, port: MessagePort, sharedKey: CryptoKey, appId: string): Wallet;
78
77
  private handleEncryptedResponse;
79
78
  private postMessage;
80
79
  /**
@@ -85,11 +84,12 @@ export declare class ExtensionWallet {
85
84
  *
86
85
  * @example
87
86
  * ```typescript
88
- * const wallet = await ExtensionWallet.create(walletInfo, chainInfo, 'my-app');
87
+ * const { info, port, sharedKey } = wallets[0];
88
+ * const wallet = await ExtensionWallet.create(info, chainInfo, port, sharedKey, 'my-app');
89
89
  * // ... use wallet ...
90
90
  * wallet.close(); // Clean up when done
91
91
  * ```
92
92
  */
93
93
  close(): void;
94
94
  }
95
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0ZW5zaW9uX3dhbGxldC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy9leHRlbnNpb24vZXh0ZW5zaW9uX3dhbGxldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsS0FBSyxNQUFNLEVBQWdCLE1BQU0sd0JBQXdCLENBQUM7QUFnQm5FLE9BQU8sS0FBSyxFQUFrQixVQUFVLEVBQWlDLE1BQU0sZ0JBQWdCLENBQUM7QUFhaEc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E0Qkc7QUFDSCxxQkFBYSxlQUFlO0lBaUJ4QixPQUFPLENBQUMsU0FBUztJQUNqQixPQUFPLENBQUMsS0FBSztJQUNiLE9BQU8sQ0FBQyxXQUFXO0lBbEJyQixzRUFBc0U7SUFDdEUsT0FBTyxDQUFDLFFBQVEsQ0FBb0Q7SUFFcEUsbUVBQW1FO0lBQ25FLE9BQU8sQ0FBQyxJQUFJLENBQTRCO0lBRXhDLGlFQUFpRTtJQUNqRSxPQUFPLENBQUMsU0FBUyxDQUEwQjtJQUUzQzs7Ozs7T0FLRztJQUNILE9BQU8sZUFJSDtJQUVKOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O09BeUJHO0lBQ0gsT0FBYSxNQUFNLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQXlCaEc7WUFjYSxzQkFBc0I7WUFxQ3RCLHVCQUF1QjtZQThDdkIsV0FBVztJQXdCekI7Ozs7Ozs7Ozs7OztPQVlHO0lBQ0gsS0FBSyxJQUFJLElBQUksQ0FPWjtDQUNGIn0=
95
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0ZW5zaW9uX3dhbGxldC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy9leHRlbnNpb24vZXh0ZW5zaW9uX3dhbGxldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsS0FBSyxNQUFNLEVBQWdCLE1BQU0sd0JBQXdCLENBQUM7QUFPbkUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFpQyxNQUFNLGdCQUFnQixDQUFDO0FBYWhGOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4Qkc7QUFDSCxxQkFBYSxlQUFlO0lBYXhCLE9BQU8sQ0FBQyxTQUFTO0lBQ2pCLE9BQU8sQ0FBQyxLQUFLO0lBQ2IsT0FBTyxDQUFDLFdBQVc7SUFDbkIsT0FBTyxDQUFDLElBQUk7SUFDWixPQUFPLENBQUMsU0FBUztJQWhCbkIsc0VBQXNFO0lBQ3RFLE9BQU8sQ0FBQyxRQUFRLENBQW9EO0lBRXBFOzs7Ozs7O09BT0c7SUFDSCxPQUFPLGVBTUg7SUFFSjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0F1Qkc7SUFDSCxNQUFNLENBQUMsTUFBTSxDQUNYLFVBQVUsRUFBRSxVQUFVLEVBQ3RCLFNBQVMsRUFBRSxTQUFTLEVBQ3BCLElBQUksRUFBRSxXQUFXLEVBQ2pCLFNBQVMsRUFBRSxTQUFTLEVBQ3BCLEtBQUssRUFBRSxNQUFNLEdBQ1osTUFBTSxDQTBCUjtZQVVhLHVCQUF1QjtZQThDdkIsV0FBVztJQXdCekI7Ozs7Ozs7Ozs7Ozs7T0FhRztJQUNILEtBQUssSUFBSSxJQUFJLENBS1o7Q0FDRiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"extension_wallet.d.ts","sourceRoot":"","sources":["../../../src/providers/extension/extension_wallet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,wBAAwB,CAAC;AAgBnE,OAAO,KAAK,EAAkB,UAAU,EAAiC,MAAM,gBAAgB,CAAC;AAahG;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,eAAe;IAiBxB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,WAAW;IAlBrB,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAoD;IAEpE,mEAAmE;IACnE,OAAO,CAAC,IAAI,CAA4B;IAExC,iEAAiE;IACjE,OAAO,CAAC,SAAS,CAA0B;IAE3C;;;;;OAKG;IACH,OAAO,eAIH;IAEJ;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,OAAa,MAAM,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBhG;YAca,sBAAsB;YAqCtB,uBAAuB;YA8CvB,WAAW;IAwBzB;;;;;;;;;;;;OAYG;IACH,KAAK,IAAI,IAAI,CAOZ;CACF"}
1
+ {"version":3,"file":"extension_wallet.d.ts","sourceRoot":"","sources":["../../../src/providers/extension/extension_wallet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,wBAAwB,CAAC;AAOnE,OAAO,KAAK,EAAE,UAAU,EAAiC,MAAM,gBAAgB,CAAC;AAahF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,eAAe;IAaxB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,SAAS;IAhBnB,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAoD;IAEpE;;;;;;;OAOG;IACH,OAAO,eAMH;IAEJ;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,MAAM,CACX,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,WAAW,EACjB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,MAAM,GACZ,MAAM,CA0BR;YAUa,uBAAuB;YA8CvB,WAAW;IAwBzB;;;;;;;;;;;;;OAaG;IACH,KAAK,IAAI,IAAI,CAKZ;CACF"}
@@ -2,31 +2,33 @@ import { WalletSchema } from '@aztec/aztec.js/wallet';
2
2
  import { jsonStringify } from '@aztec/foundation/json-rpc';
3
3
  import { promiseWithResolvers } from '@aztec/foundation/promise';
4
4
  import { schemaHasMethod } from '@aztec/foundation/schemas';
5
- import { decrypt, deriveSharedKey, encrypt, exportPublicKey, generateKeyPair, importPublicKey } from '../../crypto.js';
5
+ import { decrypt, encrypt } from '../../crypto.js';
6
6
  /**
7
7
  * A wallet implementation that communicates with browser extension wallets
8
8
  * using a secure encrypted MessageChannel.
9
9
  *
10
- * This class establishes a private communication channel with a wallet extension
11
- * using the following security mechanisms:
10
+ * This class uses a pre-established secure channel from the discovery phase:
12
11
  *
13
- * 1. **MessageChannel**: Creates a private communication channel that is not
14
- * visible to other scripts on the page (unlike window.postMessage).
12
+ * 1. **MessageChannel**: A private communication channel created during discovery,
13
+ * not visible to other scripts on the page (unlike window.postMessage).
15
14
  *
16
- * 2. **ECDH Key Exchange**: Uses Elliptic Curve Diffie-Hellman to derive a
17
- * shared secret between the dApp and wallet without transmitting private keys.
15
+ * 2. **ECDH Key Exchange**: The shared secret was derived during discovery using
16
+ * Elliptic Curve Diffie-Hellman key exchange.
18
17
  *
19
- * 3. **AES-GCM Encryption**: All messages after channel establishment are
20
- * encrypted using AES-256-GCM, providing both confidentiality and authenticity.
18
+ * 3. **AES-GCM Encryption**: All messages are encrypted using AES-256-GCM,
19
+ * providing both confidentiality and authenticity.
21
20
  *
22
21
  * @example
23
22
  * ```typescript
24
- * // Discovery returns wallet info including the wallet's public key
23
+ * // Discovery returns wallets with secure channel components
25
24
  * const wallets = await ExtensionProvider.discoverExtensions(chainInfo);
26
- * const walletInfo = wallets[0];
25
+ * const { info, port, sharedKey } = wallets[0];
27
26
  *
28
- * // Create a secure connection to the wallet
29
- * const wallet = await ExtensionWallet.create(walletInfo, chainInfo, 'my-dapp');
27
+ * // User can verify emoji if desired
28
+ * console.log('Verify:', hashToEmoji(info.verificationHash!));
29
+ *
30
+ * // Create wallet using the discovered components
31
+ * const wallet = await ExtensionWallet.create(info, chainInfo, port, sharedKey, 'my-dapp');
30
32
  *
31
33
  * // All subsequent calls are encrypted
32
34
  * const accounts = await wallet.getAccounts();
@@ -35,53 +37,54 @@ import { decrypt, deriveSharedKey, encrypt, exportPublicKey, generateKeyPair, im
35
37
  chainInfo;
36
38
  appId;
37
39
  extensionId;
40
+ port;
41
+ sharedKey;
38
42
  /** Map of pending requests awaiting responses, keyed by message ID */ inFlight;
39
- /** The MessagePort for private communication with the extension */ port;
40
- /** The derived AES-GCM key for encrypting/decrypting messages */ sharedKey;
41
43
  /**
42
44
  * Private constructor - use {@link ExtensionWallet.create} to instantiate.
43
45
  * @param chainInfo - The chain information (chainId and version)
44
46
  * @param appId - Application identifier for the requesting dApp
45
47
  * @param extensionId - The unique identifier of the target wallet extension
46
- */ constructor(chainInfo, appId, extensionId){
48
+ * @param port - The MessagePort for private communication with the wallet
49
+ * @param sharedKey - The derived AES-256-GCM shared key for encryption
50
+ */ constructor(chainInfo, appId, extensionId, port, sharedKey){
47
51
  this.chainInfo = chainInfo;
48
52
  this.appId = appId;
49
53
  this.extensionId = extensionId;
54
+ this.port = port;
55
+ this.sharedKey = sharedKey;
50
56
  this.inFlight = new Map();
51
- this.port = null;
52
- this.sharedKey = null;
53
57
  }
54
58
  /**
55
59
  * Creates an ExtensionWallet instance that proxies wallet calls to a browser extension
56
60
  * over a secure encrypted MessageChannel.
57
61
  *
58
- * The connection process:
59
- * 1. Generates an ECDH key pair for this session
60
- * 2. Derives a shared AES-256 key using the wallet's public key
61
- * 3. Creates a MessageChannel and transfers one port to the extension
62
- * 4. Returns a Proxy that encrypts all wallet method calls
63
- *
64
- * @param walletInfo - The discovered wallet information, including the wallet's ECDH public key
62
+ * @param walletInfo - The wallet info from ExtensionProvider.discoverExtensions()
65
63
  * @param chainInfo - The chain information (chainId and version) for request context
64
+ * @param port - The MessagePort for private communication with the wallet
65
+ * @param sharedKey - The derived AES-256-GCM shared key for encryption
66
66
  * @param appId - Application identifier used to identify the requesting dApp to the wallet
67
67
  * @returns A Promise resolving to a Wallet implementation that encrypts all communication
68
68
  *
69
- * @throws Error if the secure channel cannot be established
70
- *
71
69
  * @example
72
70
  * ```typescript
71
+ * const wallets = await ExtensionProvider.discoverExtensions(chainInfo);
72
+ * const { info, port, sharedKey } = wallets[0];
73
73
  * const wallet = await ExtensionWallet.create(
74
- * walletInfo,
74
+ * info,
75
75
  * { chainId: Fr(31337), version: Fr(0) },
76
+ * port,
77
+ * sharedKey,
76
78
  * 'my-defi-app'
77
79
  * );
78
80
  * ```
79
- */ static async create(walletInfo, chainInfo, appId) {
80
- const wallet = new ExtensionWallet(chainInfo, appId, walletInfo.id);
81
- if (!walletInfo.publicKey) {
82
- throw new Error('Wallet does not support secure channel establishment (missing public key)');
83
- }
84
- await wallet.establishSecureChannel(walletInfo.publicKey);
81
+ */ static create(walletInfo, chainInfo, port, sharedKey, appId) {
82
+ const wallet = new ExtensionWallet(chainInfo, appId, walletInfo.id, port, sharedKey);
83
+ // Set up message handler
84
+ wallet.port.onmessage = (event)=>{
85
+ void wallet.handleEncryptedResponse(event.data);
86
+ };
87
+ wallet.port.start();
85
88
  // Create a Proxy that intercepts wallet method calls and forwards them to the extension
86
89
  return new Proxy(wallet, {
87
90
  get: (target, prop)=>{
@@ -100,41 +103,6 @@ import { decrypt, deriveSharedKey, encrypt, exportPublicKey, generateKeyPair, im
100
103
  });
101
104
  }
102
105
  /**
103
- * Establishes a secure MessageChannel with ECDH key exchange.
104
- *
105
- * This method performs the cryptographic handshake:
106
- * 1. Generates a new ECDH P-256 key pair for this session
107
- * 2. Imports the wallet's public key and derives a shared secret
108
- * 3. Creates a MessageChannel for private communication
109
- * 4. Sends a connection request with our public key via window.postMessage
110
- * (this is the only public message - subsequent communication uses the private channel)
111
- *
112
- * @param walletExportedPublicKey - The wallet's ECDH public key in JWK format
113
- */ async establishSecureChannel(walletExportedPublicKey) {
114
- const keyPair = await generateKeyPair();
115
- const exportedPublicKey = await exportPublicKey(keyPair.publicKey);
116
- const walletPublicKey = await importPublicKey(walletExportedPublicKey);
117
- this.sharedKey = await deriveSharedKey(keyPair.privateKey, walletPublicKey);
118
- const channel = new MessageChannel();
119
- this.port = channel.port1;
120
- this.port.onmessage = async (event)=>{
121
- await this.handleEncryptedResponse(event.data);
122
- };
123
- this.port.start();
124
- // Send connection request with our public key and transfer port2 to content script
125
- // This is the only public postMessage - it contains our public key (safe to expose)
126
- // and transfers the MessagePort for subsequent private communication
127
- const connectRequest = {
128
- type: 'aztec-wallet-connect',
129
- walletId: this.extensionId,
130
- appId: this.appId,
131
- publicKey: exportedPublicKey
132
- };
133
- window.postMessage(jsonStringify(connectRequest), '*', [
134
- channel.port2
135
- ]);
136
- }
137
- /**
138
106
  * Handles an encrypted response received from the wallet extension.
139
107
  *
140
108
  * Decrypts the response using the shared AES key and resolves or rejects
@@ -171,7 +139,7 @@ import { decrypt, deriveSharedKey, encrypt, exportPublicKey, generateKeyPair, im
171
139
  * Sends an encrypted wallet method call over the secure MessageChannel.
172
140
  *
173
141
  * The message is encrypted using AES-256-GCM with the shared key derived
174
- * during channel establishment. A unique message ID is generated to correlate
142
+ * during discovery. A unique message ID is generated to correlate
175
143
  * the response.
176
144
  *
177
145
  * @param call - The wallet method call containing method name and arguments
@@ -210,16 +178,15 @@ import { decrypt, deriveSharedKey, encrypt, exportPublicKey, generateKeyPair, im
210
178
  *
211
179
  * @example
212
180
  * ```typescript
213
- * const wallet = await ExtensionWallet.create(walletInfo, chainInfo, 'my-app');
181
+ * const { info, port, sharedKey } = wallets[0];
182
+ * const wallet = await ExtensionWallet.create(info, chainInfo, port, sharedKey, 'my-app');
214
183
  * // ... use wallet ...
215
184
  * wallet.close(); // Clean up when done
216
185
  * ```
217
186
  */ close() {
218
187
  if (this.port) {
219
188
  this.port.close();
220
- this.port = null;
221
189
  }
222
- this.sharedKey = null;
223
190
  this.inFlight.clear();
224
191
  }
225
192
  }
@@ -1,5 +1,5 @@
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 { WalletInfo, WalletMessage, WalletResponse, DiscoveryRequest, DiscoveryResponse, ConnectRequest, } from '../../types.js';
5
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wcm92aWRlcnMvZXh0ZW5zaW9uL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLFlBQVksRUFDVixVQUFVLEVBQ1YsYUFBYSxFQUNiLGNBQWMsRUFDZCxnQkFBZ0IsRUFDaEIsaUJBQWlCLEVBQ2pCLGNBQWMsR0FDZixNQUFNLGdCQUFnQixDQUFDIn0=
4
+ export type { WalletInfo, WalletMessage, WalletResponse, DiscoveryRequest, DiscoveryResponse } from '../../types.js';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wcm92aWRlcnMvZXh0ZW5zaW9uL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsS0FBSyxnQkFBZ0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ25GLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsWUFBWSxFQUFFLFVBQVUsRUFBRSxhQUFhLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUMifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/extension/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,cAAc,iBAAiB,CAAC;AAChC,YAAY,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,GACf,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/extension/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AACnF,cAAc,iBAAiB,CAAC;AAChC,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
package/dest/types.d.ts CHANGED
@@ -14,6 +14,12 @@ export interface WalletInfo {
14
14
  version: string;
15
15
  /** Wallet's ECDH public key for secure channel establishment */
16
16
  publicKey: ExportedPublicKey;
17
+ /**
18
+ * Hash of the shared secret for anti-MITM verification.
19
+ * Both dApp and wallet independently compute this from the ECDH shared secret.
20
+ * Use {@link hashToEmoji} to convert to a visual representation for user verification.
21
+ */
22
+ verificationHash?: string;
17
23
  }
18
24
  /**
19
25
  * Message format for wallet communication (internal, before encryption)
@@ -55,6 +61,8 @@ export interface DiscoveryRequest {
55
61
  requestId: string;
56
62
  /** Chain information to check if wallet supports this network */
57
63
  chainInfo: ChainInfo;
64
+ /** dApp's ECDH public key for deriving shared secret */
65
+ publicKey: ExportedPublicKey;
58
66
  }
59
67
  /**
60
68
  * Discovery response from a wallet (public, unencrypted)
@@ -67,17 +75,4 @@ export interface DiscoveryResponse {
67
75
  /** Wallet information */
68
76
  walletInfo: WalletInfo;
69
77
  }
70
- /**
71
- * Connection request to establish secure channel
72
- */
73
- export interface ConnectRequest {
74
- /** Message type for connection */
75
- type: 'aztec-wallet-connect';
76
- /** Target wallet ID */
77
- walletId: string;
78
- /** Application ID */
79
- appId: string;
80
- /** dApp's ECDH public key for deriving shared secret */
81
- publicKey: ExportedPublicKey;
82
- }
83
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV6RCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVyRDs7R0FFRztBQUNILE1BQU0sV0FBVyxVQUFVO0lBQ3pCLHVDQUF1QztJQUN2QyxFQUFFLEVBQUUsTUFBTSxDQUFDO0lBQ1gsaUNBQWlDO0lBQ2pDLElBQUksRUFBRSxNQUFNLENBQUM7SUFDYiwrQkFBK0I7SUFDL0IsSUFBSSxDQUFDLEVBQUUsTUFBTSxDQUFDO0lBQ2QscUJBQXFCO0lBQ3JCLE9BQU8sRUFBRSxNQUFNLENBQUM7SUFDaEIsZ0VBQWdFO0lBQ2hFLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQztDQUM5QjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxXQUFXLGFBQWE7SUFDNUIsK0NBQStDO0lBQy9DLFNBQVMsRUFBRSxNQUFNLENBQUM7SUFDbEIsZ0NBQWdDO0lBQ2hDLElBQUksRUFBRSxNQUFNLENBQUM7SUFDYiwrQkFBK0I7SUFDL0IsSUFBSSxFQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ2hCLHdCQUF3QjtJQUN4QixTQUFTLEVBQUUsU0FBUyxDQUFDO0lBQ3JCLHdDQUF3QztJQUN4QyxLQUFLLEVBQUUsTUFBTSxDQUFDO0lBQ2QsNENBQTRDO0lBQzVDLFFBQVEsRUFBRSxNQUFNLENBQUM7Q0FDbEI7QUFFRDs7R0FFRztBQUNILE1BQU0sV0FBVyxjQUFjO0lBQzdCLHNDQUFzQztJQUN0QyxTQUFTLEVBQUUsTUFBTSxDQUFDO0lBQ2xCLGtDQUFrQztJQUNsQyxNQUFNLENBQUMsRUFBRSxPQUFPLENBQUM7SUFDakIsNkJBQTZCO0lBQzdCLEtBQUssQ0FBQyxFQUFFLE9BQU8sQ0FBQztJQUNoQix1Q0FBdUM7SUFDdkMsUUFBUSxFQUFFLE1BQU0sQ0FBQztDQUNsQjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxXQUFXLGdCQUFnQjtJQUMvQixpQ0FBaUM7SUFDakMsSUFBSSxFQUFFLHdCQUF3QixDQUFDO0lBQy9CLGlCQUFpQjtJQUNqQixTQUFTLEVBQUUsTUFBTSxDQUFDO0lBQ2xCLGlFQUFpRTtJQUNqRSxTQUFTLEVBQUUsU0FBUyxDQUFDO0NBQ3RCO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFdBQVcsaUJBQWlCO0lBQ2hDLDBDQUEwQztJQUMxQyxJQUFJLEVBQUUsaUNBQWlDLENBQUM7SUFDeEMsZ0RBQWdEO0lBQ2hELFNBQVMsRUFBRSxNQUFNLENBQUM7SUFDbEIseUJBQXlCO0lBQ3pCLFVBQVUsRUFBRSxVQUFVLENBQUM7Q0FDeEI7QUFFRDs7R0FFRztBQUNILE1BQU0sV0FBVyxjQUFjO0lBQzdCLGtDQUFrQztJQUNsQyxJQUFJLEVBQUUsc0JBQXNCLENBQUM7SUFDN0IsdUJBQXVCO0lBQ3ZCLFFBQVEsRUFBRSxNQUFNLENBQUM7SUFDakIscUJBQXFCO0lBQ3JCLEtBQUssRUFBRSxNQUFNLENBQUM7SUFDZCx3REFBd0Q7SUFDeEQsU0FBUyxFQUFFLGlCQUFpQixDQUFDO0NBQzlCIn0=
78
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV6RCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVyRDs7R0FFRztBQUNILE1BQU0sV0FBVyxVQUFVO0lBQ3pCLHVDQUF1QztJQUN2QyxFQUFFLEVBQUUsTUFBTSxDQUFDO0lBQ1gsaUNBQWlDO0lBQ2pDLElBQUksRUFBRSxNQUFNLENBQUM7SUFDYiwrQkFBK0I7SUFDL0IsSUFBSSxDQUFDLEVBQUUsTUFBTSxDQUFDO0lBQ2QscUJBQXFCO0lBQ3JCLE9BQU8sRUFBRSxNQUFNLENBQUM7SUFDaEIsZ0VBQWdFO0lBQ2hFLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQztJQUM3Qjs7OztPQUlHO0lBQ0gsZ0JBQWdCLENBQUMsRUFBRSxNQUFNLENBQUM7Q0FDM0I7QUFFRDs7R0FFRztBQUNILE1BQU0sV0FBVyxhQUFhO0lBQzVCLCtDQUErQztJQUMvQyxTQUFTLEVBQUUsTUFBTSxDQUFDO0lBQ2xCLGdDQUFnQztJQUNoQyxJQUFJLEVBQUUsTUFBTSxDQUFDO0lBQ2IsK0JBQStCO0lBQy9CLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNoQix3QkFBd0I7SUFDeEIsU0FBUyxFQUFFLFNBQVMsQ0FBQztJQUNyQix3Q0FBd0M7SUFDeEMsS0FBSyxFQUFFLE1BQU0sQ0FBQztJQUNkLDRDQUE0QztJQUM1QyxRQUFRLEVBQUUsTUFBTSxDQUFDO0NBQ2xCO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFdBQVcsY0FBYztJQUM3QixzQ0FBc0M7SUFDdEMsU0FBUyxFQUFFLE1BQU0sQ0FBQztJQUNsQixrQ0FBa0M7SUFDbEMsTUFBTSxDQUFDLEVBQUUsT0FBTyxDQUFDO0lBQ2pCLDZCQUE2QjtJQUM3QixLQUFLLENBQUMsRUFBRSxPQUFPLENBQUM7SUFDaEIsdUNBQXVDO0lBQ3ZDLFFBQVEsRUFBRSxNQUFNLENBQUM7Q0FDbEI7QUFFRDs7R0FFRztBQUNILE1BQU0sV0FBVyxnQkFBZ0I7SUFDL0IsaUNBQWlDO0lBQ2pDLElBQUksRUFBRSx3QkFBd0IsQ0FBQztJQUMvQixpQkFBaUI7SUFDakIsU0FBUyxFQUFFLE1BQU0sQ0FBQztJQUNsQixpRUFBaUU7SUFDakUsU0FBUyxFQUFFLFNBQVMsQ0FBQztJQUNyQix3REFBd0Q7SUFDeEQsU0FBUyxFQUFFLGlCQUFpQixDQUFDO0NBQzlCO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFdBQVcsaUJBQWlCO0lBQ2hDLDBDQUEwQztJQUMxQyxJQUFJLEVBQUUsaUNBQWlDLENBQUM7SUFDeEMsZ0RBQWdEO0lBQ2hELFNBQVMsRUFBRSxNQUFNLENBQUM7SUFDbEIseUJBQXlCO0lBQ3pCLFVBQVUsRUFBRSxVQUFVLENBQUM7Q0FDeEIifQ==
@@ -1 +1 @@
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;;GAEG;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;IAChB,gEAAgE;IAChE,SAAS,EAAE,iBAAiB,CAAC;CAC9B;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,wBAAwB,CAAC;IAC/B,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,SAAS,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,IAAI,EAAE,iCAAiC,CAAC;IACxC,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kCAAkC;IAClC,IAAI,EAAE,sBAAsB,CAAC;IAC7B,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,SAAS,EAAE,iBAAiB,CAAC;CAC9B"}
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;;GAEG;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;IAChB,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,wBAAwB,CAAC;IAC/B,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,SAAS,EAAE,SAAS,CAAC;IACrB,wDAAwD;IACxD,SAAS,EAAE,iBAAiB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,IAAI,EAAE,iCAAiC,CAAC;IACxC,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,UAAU,EAAE,UAAU,CAAC;CACxB"}
package/dest/types.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /**
2
- * Connection request to establish secure channel
2
+ * Discovery response from a wallet (public, unencrypted)
3
3
  */ export { };
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": "4.0.0-nightly.20260113",
4
+ "version": "4.0.0-nightly.20260115",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  "./base-wallet": "./dest/base-wallet/index.js",
@@ -64,19 +64,19 @@
64
64
  ]
65
65
  },
66
66
  "dependencies": {
67
- "@aztec/aztec.js": "4.0.0-nightly.20260113",
68
- "@aztec/constants": "4.0.0-nightly.20260113",
69
- "@aztec/entrypoints": "4.0.0-nightly.20260113",
70
- "@aztec/foundation": "4.0.0-nightly.20260113",
71
- "@aztec/pxe": "4.0.0-nightly.20260113",
72
- "@aztec/stdlib": "4.0.0-nightly.20260113"
67
+ "@aztec/aztec.js": "4.0.0-nightly.20260115",
68
+ "@aztec/constants": "4.0.0-nightly.20260115",
69
+ "@aztec/entrypoints": "4.0.0-nightly.20260115",
70
+ "@aztec/foundation": "4.0.0-nightly.20260115",
71
+ "@aztec/pxe": "4.0.0-nightly.20260115",
72
+ "@aztec/stdlib": "4.0.0-nightly.20260115"
73
73
  },
74
74
  "devDependencies": {
75
- "@aztec/noir-contracts.js": "4.0.0-nightly.20260113",
75
+ "@aztec/noir-contracts.js": "4.0.0-nightly.20260115",
76
76
  "@jest/globals": "^30.0.0",
77
77
  "@types/jest": "^30.0.0",
78
78
  "@types/node": "^22.15.17",
79
- "@typescript/native-preview": "7.0.0-dev.20251126.1",
79
+ "@typescript/native-preview": "7.0.0-dev.20260113.1",
80
80
  "jest": "^30.0.0",
81
81
  "jest-mock-extended": "^4.0.0",
82
82
  "resolve-typescript-plugin": "^2.0.1",
@@ -34,14 +34,13 @@ import {
34
34
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
35
35
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
36
36
  import {
37
- type ContractClassMetadata,
38
37
  type ContractInstanceWithAddress,
39
- type ContractMetadata,
40
38
  computePartialAddress,
41
39
  getContractClassFromArtifact,
42
40
  } from '@aztec/stdlib/contract';
43
41
  import { SimulationError } from '@aztec/stdlib/errors';
44
42
  import { Gas, GasSettings } from '@aztec/stdlib/gas';
43
+ import { siloNullifier } from '@aztec/stdlib/hash';
45
44
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
46
45
  import type {
47
46
  TxExecutionRequest,
@@ -227,7 +226,7 @@ export abstract class BaseWallet implements Wallet {
227
226
  artifact?: ContractArtifact,
228
227
  secretKey?: Fr,
229
228
  ): Promise<ContractInstanceWithAddress> {
230
- const { contractInstance: existingInstance } = await this.pxe.getContractMetadata(instance.address);
229
+ const existingInstance = await this.pxe.getContractInstance(instance.address);
231
230
 
232
231
  if (existingInstance) {
233
232
  // Instance already registered in the wallet
@@ -244,13 +243,12 @@ export abstract class BaseWallet implements Wallet {
244
243
  // Instance not registered yet
245
244
  if (!artifact) {
246
245
  // Try to get the artifact from the wallet's contract class storage
247
- const classMetadata = await this.pxe.getContractClassMetadata(instance.currentContractClassId, true);
248
- if (!classMetadata.artifact) {
246
+ artifact = await this.pxe.getContractArtifact(instance.currentContractClassId);
247
+ if (!artifact) {
249
248
  throw new Error(
250
249
  `Cannot register contract at ${instance.address.toString()}: artifact is required but not provided, and wallet does not have the artifact for contract class ${instance.currentContractClassId.toString()}`,
251
250
  );
252
251
  }
253
- artifact = classMetadata.artifact;
254
252
  }
255
253
  await this.pxe.registerContract({ artifact, instance });
256
254
  }
@@ -315,13 +313,6 @@ export abstract class BaseWallet implements Wallet {
315
313
  return this.pxe.simulateUtility(call, authwits);
316
314
  }
317
315
 
318
- getContractClassMetadata(id: Fr, includeArtifact: boolean = false): Promise<ContractClassMetadata> {
319
- return this.pxe.getContractClassMetadata(id, includeArtifact);
320
- }
321
- getContractMetadata(address: AztecAddress): Promise<ContractMetadata> {
322
- return this.pxe.getContractMetadata(address);
323
- }
324
-
325
316
  getTxReceipt(txHash: TxHash): Promise<TxReceipt> {
326
317
  return this.aztecNode.getTxReceipt(txHash);
327
318
  }
@@ -345,4 +336,37 @@ export abstract class BaseWallet implements Wallet {
345
336
 
346
337
  return decodedEvents;
347
338
  }
339
+
340
+ async getContractMetadata(address: AztecAddress) {
341
+ const instance = await this.pxe.getContractInstance(address);
342
+ const initNullifier = await siloNullifier(address, address.toField());
343
+ const publiclyRegisteredContract = await this.aztecNode.getContract(address);
344
+ const [initNullifierMembershipWitness, publiclyRegisteredContractClass] = await Promise.all([
345
+ this.aztecNode.getNullifierMembershipWitness('latest', initNullifier),
346
+ publiclyRegisteredContract
347
+ ? this.aztecNode.getContractClass(
348
+ publiclyRegisteredContract.currentContractClassId || instance?.currentContractClassId,
349
+ )
350
+ : undefined,
351
+ ]);
352
+ const isContractUpdated =
353
+ publiclyRegisteredContract &&
354
+ !publiclyRegisteredContract.currentContractClassId.equals(publiclyRegisteredContract.originalContractClassId);
355
+ return {
356
+ instance: instance ?? undefined,
357
+ isContractInitialized: !!initNullifierMembershipWitness,
358
+ isContractPublished: !!publiclyRegisteredContract,
359
+ isContractClassPubliclyRegistered: !!publiclyRegisteredContractClass,
360
+ isContractUpdated: !!isContractUpdated,
361
+ updatedContractClassId: isContractUpdated ? publiclyRegisteredContract.currentContractClassId : undefined,
362
+ };
363
+ }
364
+
365
+ async getContractClassMetadata(id: Fr) {
366
+ const publiclyRegisteredContractClass = await this.aztecNode.getContractClass(id);
367
+ return {
368
+ isArtifactRegistered: !!(await this.pxe.getContractArtifact(id)),
369
+ isContractClassPubliclyRegistered: !!publiclyRegisteredContractClass,
370
+ };
371
+ }
348
372
  }
package/src/crypto.ts CHANGED
@@ -192,7 +192,7 @@ export function deriveSharedKey(privateKey: CryptoKey, publicKey: CryptoKey): Pr
192
192
  name: 'AES-GCM',
193
193
  length: 256,
194
194
  },
195
- false,
195
+ true, // extractable - needed for hashing
196
196
  ['encrypt', 'decrypt'],
197
197
  );
198
198
  }
@@ -281,3 +281,95 @@ function base64ToArrayBuffer(base64: string): ArrayBuffer {
281
281
  }
282
282
  return bytes.buffer;
283
283
  }
284
+
285
+ /**
286
+ * Emoji alphabet for visual verification of shared secrets.
287
+ * 32 distinct, easily recognizable emojis for anti-spoofing verification.
288
+ * @internal
289
+ */
290
+ const EMOJI_ALPHABET = [
291
+ '🔵',
292
+ '🟢',
293
+ '🔴',
294
+ '🟡',
295
+ '🟣',
296
+ '🟠',
297
+ '⚫',
298
+ '⚪',
299
+ '🌟',
300
+ '🌙',
301
+ '☀️',
302
+ '🌈',
303
+ '🔥',
304
+ '💧',
305
+ '🌸',
306
+ '🍀',
307
+ '🦋',
308
+ '🐬',
309
+ '🦊',
310
+ '🐼',
311
+ '🦁',
312
+ '🐯',
313
+ '🐸',
314
+ '🦉',
315
+ '🎵',
316
+ '🎨',
317
+ '🎯',
318
+ '🎲',
319
+ '🔔',
320
+ '💎',
321
+ '🔑',
322
+ '🏆',
323
+ ];
324
+
325
+ /**
326
+ * Hashes a shared AES key to a hex string for verification.
327
+ *
328
+ * This extracts the raw key material and hashes it with SHA-256,
329
+ * returning the first 16 bytes as a hex string.
330
+ *
331
+ * @param sharedKey - The AES-GCM shared key (must be extractable)
332
+ * @returns A hex string representation of the hash
333
+ *
334
+ * @example
335
+ * ```typescript
336
+ * const hash = await hashSharedSecret(sharedKey);
337
+ * const emoji = hashToEmoji(hash);
338
+ * ```
339
+ */
340
+ export async function hashSharedSecret(sharedKey: CryptoKey): Promise<string> {
341
+ const rawKey = await crypto.subtle.exportKey('raw', sharedKey);
342
+ const hash = await crypto.subtle.digest('SHA-256', rawKey);
343
+ const bytes = new Uint8Array(hash.slice(0, 16));
344
+ return Array.from(bytes)
345
+ .map(b => b.toString(16).padStart(2, '0'))
346
+ .join('');
347
+ }
348
+
349
+ /**
350
+ * Converts a hex hash to an emoji sequence for visual verification.
351
+ *
352
+ * This is used for anti-MITM verification - both the dApp and wallet
353
+ * independently compute the same emoji sequence from the shared secret.
354
+ * Users can visually compare the sequences to detect interception.
355
+ *
356
+ * Similar to SAS (Short Authentication String) in ZRTP/Signal.
357
+ *
358
+ * @param hash - Hex string from {@link hashSharedSecret}
359
+ * @param length - Number of emojis to generate (default: 4)
360
+ * @returns A string of emojis representing the hash
361
+ *
362
+ * @example
363
+ * ```typescript
364
+ * const hash = await hashSharedSecret(sharedKey);
365
+ * const emoji = hashToEmoji(hash); // e.g., "🔵🦋🎯🐼"
366
+ * // Display to user for verification
367
+ * ```
368
+ */
369
+ export function hashToEmoji(hash: string, length: number = 4): string {
370
+ const bytes: number[] = [];
371
+ for (let i = 0; i < hash.length && bytes.length < length; i += 2) {
372
+ bytes.push(parseInt(hash.slice(i, i + 2), 16));
373
+ }
374
+ return bytes.map(b => EMOJI_ALPHABET[b % EMOJI_ALPHABET.length]).join('');
375
+ }