@aztec/wallet-sdk 0.0.1-commit.fce3e4f → 3.0.0-devnet.2-patch.1
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 +240 -266
- package/dest/base-wallet/base_wallet.d.ts +4 -4
- package/dest/base-wallet/base_wallet.d.ts.map +1 -1
- package/dest/base-wallet/base_wallet.js +15 -6
- package/dest/crypto.d.ts +183 -0
- package/dest/crypto.d.ts.map +1 -0
- package/dest/crypto.js +300 -0
- package/dest/manager/index.d.ts +4 -3
- package/dest/manager/index.d.ts.map +1 -1
- package/dest/manager/index.js +2 -0
- package/dest/manager/types.d.ts +22 -1
- package/dest/manager/types.d.ts.map +1 -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 +34 -15
- package/dest/providers/extension/extension_provider.d.ts +53 -7
- package/dest/providers/extension/extension_provider.d.ts.map +1 -1
- package/dest/providers/extension/extension_provider.js +81 -13
- package/dest/providers/extension/extension_wallet.d.ts +140 -8
- package/dest/providers/extension/extension_wallet.d.ts.map +1 -1
- package/dest/providers/extension/extension_wallet.js +268 -46
- package/dest/providers/extension/index.d.ts +6 -4
- package/dest/providers/extension/index.d.ts.map +1 -1
- package/dest/providers/extension/index.js +2 -0
- package/dest/types.d.ts +92 -0
- package/dest/types.d.ts.map +1 -0
- package/dest/types.js +10 -0
- package/package.json +12 -10
- package/src/base-wallet/base_wallet.ts +17 -11
- package/src/crypto.ts +375 -0
- package/src/manager/index.ts +4 -8
- package/src/manager/types.ts +22 -0
- package/src/manager/wallet_manager.ts +43 -16
- package/src/providers/extension/extension_provider.ts +112 -17
- package/src/providers/extension/extension_wallet.ts +310 -55
- package/src/providers/extension/index.ts +5 -3
- package/src/{providers/types.ts → types.ts} +33 -6
- package/dest/providers/types.d.ts +0 -67
- package/dest/providers/types.d.ts.map +0 -1
- package/dest/providers/types.js +0 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/manager/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,+BAA+B;IAC/B,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,KAAK,GAAG,UAAU,CAAC;AAElE;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,IAAI,EAAE,kBAAkB,CAAC;IACzB,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/manager/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,+BAA+B;IAC/B,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,KAAK,GAAG,UAAU,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG,MAAM,IAAI,CAAC;AAEvD;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,IAAI,EAAE,kBAAkB,CAAC;IACzB,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC;;;;OAIG;IACH,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B;;;;OAIG;IACH,YAAY,CAAC,CAAC,QAAQ,EAAE,6BAA6B,GAAG,MAAM,IAAI,CAAC;IACnE;;;OAGG;IACH,cAAc,CAAC,IAAI,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,qCAAqC;IACrC,SAAS,EAAE,SAAS,CAAC;IACrB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
|
|
@@ -24,4 +24,4 @@ export declare class WalletManager {
|
|
|
24
24
|
*/
|
|
25
25
|
private isExtensionAllowed;
|
|
26
26
|
}
|
|
27
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FsbGV0X21hbmFnZXIuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tYW5hZ2VyL3dhbGxldF9tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxFQUNWLHNCQUFzQixFQUd0QixtQkFBbUIsRUFDbkIsY0FBYyxFQUNmLE1BQU0sWUFBWSxDQUFDO0FBRXBCOztHQUVHO0FBQ0gscUJBQWEsYUFBYTtJQUN4QixPQUFPLENBQUMsTUFBTSxDQUdaO0lBRUYsT0FBTyxlQUFpQjtJQUV4Qjs7O09BR0c7SUFDSCxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxtQkFBbUIsR0FBRyxhQUFhLENBTzNEO0lBRUQ7Ozs7O09BS0c7SUFDRyxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsc0JBQXNCLEdBQUcsT0FBTyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBdURwRjtJQUVEOzs7O09BSUc7SUFDSCxPQUFPLENBQUMsa0JBQWtCO0NBVzNCIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wallet_manager.d.ts","sourceRoot":"","sources":["../../src/manager/wallet_manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"wallet_manager.d.ts","sourceRoot":"","sources":["../../src/manager/wallet_manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EAGtB,mBAAmB,EACnB,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAGZ;IAEF,OAAO,eAAiB;IAExB;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa,CAO3D;IAED;;;;;OAKG;IACG,mBAAmB,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAuDpF;IAED;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;CAW3B"}
|
|
@@ -34,25 +34,47 @@ import { ExtensionProvider, ExtensionWallet } from '../providers/extension/index
|
|
|
34
34
|
*/ async getAvailableWallets(options) {
|
|
35
35
|
const providers = [];
|
|
36
36
|
const { chainInfo } = options;
|
|
37
|
-
// Discover extension wallets
|
|
38
37
|
if (this.config.extensions?.enabled) {
|
|
39
|
-
const
|
|
38
|
+
const discoveredWallets = await ExtensionProvider.discoverExtensions(chainInfo, options.timeout);
|
|
40
39
|
const extensionConfig = this.config.extensions;
|
|
41
|
-
for (const
|
|
42
|
-
|
|
43
|
-
if (!this.isExtensionAllowed(ext.id, extensionConfig)) {
|
|
40
|
+
for (const { info, port, sharedKey } of discoveredWallets){
|
|
41
|
+
if (!this.isExtensionAllowed(info.id, extensionConfig)) {
|
|
44
42
|
continue;
|
|
45
43
|
}
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
let extensionWallet = null;
|
|
45
|
+
const provider = {
|
|
46
|
+
id: info.id,
|
|
48
47
|
type: 'extension',
|
|
49
|
-
name:
|
|
50
|
-
icon:
|
|
48
|
+
name: info.name,
|
|
49
|
+
icon: info.icon,
|
|
51
50
|
metadata: {
|
|
52
|
-
version:
|
|
51
|
+
version: info.version,
|
|
52
|
+
verificationHash: info.verificationHash
|
|
53
53
|
},
|
|
54
|
-
connect: (appId)=>
|
|
55
|
-
|
|
54
|
+
connect: (appId)=>{
|
|
55
|
+
extensionWallet = ExtensionWallet.create(info, chainInfo, port, sharedKey, appId);
|
|
56
|
+
return Promise.resolve(extensionWallet.getWallet());
|
|
57
|
+
},
|
|
58
|
+
disconnect: async ()=>{
|
|
59
|
+
if (extensionWallet) {
|
|
60
|
+
await extensionWallet.disconnect();
|
|
61
|
+
extensionWallet = null;
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
onDisconnect: (callback)=>{
|
|
65
|
+
if (extensionWallet) {
|
|
66
|
+
return extensionWallet.onDisconnect(callback);
|
|
67
|
+
}
|
|
68
|
+
return ()=>{};
|
|
69
|
+
},
|
|
70
|
+
isDisconnected: ()=>{
|
|
71
|
+
if (extensionWallet) {
|
|
72
|
+
return extensionWallet.isDisconnected();
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
providers.push(provider);
|
|
56
78
|
}
|
|
57
79
|
}
|
|
58
80
|
// TODO: Add web wallet discovery when implemented
|
|
@@ -63,15 +85,12 @@ import { ExtensionProvider, ExtensionWallet } from '../providers/extension/index
|
|
|
63
85
|
* @param extensionId - The extension ID to check
|
|
64
86
|
* @param config - Extension wallet configuration containing allow/block lists
|
|
65
87
|
*/ isExtensionAllowed(extensionId, config) {
|
|
66
|
-
// Check block list first
|
|
67
88
|
if (config.blockList && config.blockList.includes(extensionId)) {
|
|
68
89
|
return false;
|
|
69
90
|
}
|
|
70
|
-
// If allow list exists, extension must be in it
|
|
71
91
|
if (config.allowList && config.allowList.length > 0) {
|
|
72
92
|
return config.allowList.includes(extensionId);
|
|
73
93
|
}
|
|
74
|
-
// If no allow list, extension is allowed (unless blocked)
|
|
75
94
|
return true;
|
|
76
95
|
}
|
|
77
96
|
}
|
|
@@ -1,17 +1,63 @@
|
|
|
1
1
|
import type { ChainInfo } from '@aztec/aztec.js/account';
|
|
2
|
-
import type
|
|
2
|
+
import { type WalletInfo } from '../../types.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* A discovered wallet with its secure channel components.
|
|
5
|
+
* Returned by {@link ExtensionProvider.discoverExtensions}.
|
|
6
|
+
*/
|
|
7
|
+
export interface DiscoveredWallet {
|
|
8
|
+
/** Basic wallet information (id, name, icon, version, publicKey, verificationHash) */
|
|
9
|
+
info: WalletInfo;
|
|
10
|
+
/** The MessagePort for private communication with the wallet */
|
|
11
|
+
port: MessagePort;
|
|
12
|
+
/** The derived AES-256-GCM shared key for encryption */
|
|
13
|
+
sharedKey: CryptoKey;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Provider for discovering Aztec wallet extensions.
|
|
17
|
+
*
|
|
18
|
+
* This class handles the discovery phase of wallet communication:
|
|
19
|
+
* 1. Broadcasts a discovery request with the dApp's public key
|
|
20
|
+
* 2. Receives responses from installed wallets with their public keys
|
|
21
|
+
* 3. Derives shared secrets and computes verification hashes
|
|
22
|
+
* 4. Returns discovered wallets with their secure channel components
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const wallets = await ExtensionProvider.discoverExtensions(chainInfo);
|
|
27
|
+
* // Display wallets to user with optional emoji verification
|
|
28
|
+
* for (const wallet of wallets) {
|
|
29
|
+
* const emoji = hashToEmoji(wallet.info.verificationHash!);
|
|
30
|
+
* console.log(`${wallet.info.name}: ${emoji}`);
|
|
31
|
+
* }
|
|
32
|
+
* // User selects a wallet after verifying
|
|
33
|
+
* const wallet = await ExtensionWallet.create(wallets[0], chainInfo, 'my-app');
|
|
34
|
+
* ```
|
|
5
35
|
*/
|
|
6
36
|
export declare class ExtensionProvider {
|
|
7
|
-
private static discoveredExtensions;
|
|
8
37
|
private static discoveryInProgress;
|
|
9
38
|
/**
|
|
10
|
-
* Discovers all installed Aztec wallet extensions
|
|
39
|
+
* Discovers all installed Aztec wallet extensions and establishes secure channel components.
|
|
40
|
+
*
|
|
41
|
+
* This method:
|
|
42
|
+
* 1. Generates an ECDH key pair for this discovery session
|
|
43
|
+
* 2. Broadcasts a discovery request with the dApp's public key
|
|
44
|
+
* 3. Receives responses from wallets with their public keys and MessagePorts
|
|
45
|
+
* 4. Derives shared secrets and computes verification hashes
|
|
46
|
+
*
|
|
11
47
|
* @param chainInfo - Chain information to check if extensions support this network
|
|
12
48
|
* @param timeout - How long to wait for extensions to respond (ms)
|
|
13
|
-
* @returns Array of discovered
|
|
49
|
+
* @returns Array of discovered wallets with their secure channel components
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const wallets = await ExtensionProvider.discoverExtensions({
|
|
54
|
+
* chainId: Fr(31337),
|
|
55
|
+
* version: Fr(0)
|
|
56
|
+
* });
|
|
57
|
+
* // Access wallet info and secure channel
|
|
58
|
+
* const { info, port, sharedKey } = wallets[0];
|
|
59
|
+
* ```
|
|
14
60
|
*/
|
|
15
|
-
static discoverExtensions(chainInfo: ChainInfo, timeout?: number): Promise<
|
|
61
|
+
static discoverExtensions(chainInfo: ChainInfo, timeout?: number): Promise<DiscoveredWallet[]>;
|
|
16
62
|
}
|
|
17
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
63
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0ZW5zaW9uX3Byb3ZpZGVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcHJvdmlkZXJzL2V4dGVuc2lvbi9leHRlbnNpb25fcHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFLekQsT0FBTyxFQUFpRCxLQUFLLFVBQVUsRUFBcUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUVuSDs7O0dBR0c7QUFDSCxNQUFNLFdBQVcsZ0JBQWdCO0lBQy9CLHNGQUFzRjtJQUN0RixJQUFJLEVBQUUsVUFBVSxDQUFDO0lBQ2pCLGdFQUFnRTtJQUNoRSxJQUFJLEVBQUUsV0FBVyxDQUFDO0lBQ2xCLHdEQUF3RDtJQUN4RCxTQUFTLEVBQUUsU0FBUyxDQUFDO0NBQ3RCO0FBV0Q7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gscUJBQWEsaUJBQWlCO0lBQzVCLE9BQU8sQ0FBQyxNQUFNLENBQUMsbUJBQW1CLENBQVM7SUFFM0M7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FzQkc7SUFDSCxPQUFhLGtCQUFrQixDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsT0FBTyxHQUFFLE1BQWEsR0FBRyxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxDQXlGekc7Q0FDRiJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension_provider.d.ts","sourceRoot":"","sources":["../../../src/providers/extension/extension_provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"extension_provider.d.ts","sourceRoot":"","sources":["../../../src/providers/extension/extension_provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAKzD,OAAO,EAAiD,KAAK,UAAU,EAAqB,MAAM,gBAAgB,CAAC;AAEnH;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sFAAsF;IACtF,IAAI,EAAE,UAAU,CAAC;IACjB,gEAAgE;IAChE,IAAI,EAAE,WAAW,CAAC;IAClB,wDAAwD;IACxD,SAAS,EAAE,SAAS,CAAC;CACtB;AAWD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAS;IAE3C;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAa,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,GAAE,MAAa,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAyFzG;CACF"}
|
|
@@ -1,23 +1,62 @@
|
|
|
1
1
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
2
2
|
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
3
|
+
import { deriveSharedKey, exportPublicKey, generateKeyPair, hashSharedSecret, importPublicKey } from '../../crypto.js';
|
|
4
|
+
import { WalletMessageType } from '../../types.js';
|
|
3
5
|
/**
|
|
4
|
-
* Provider for discovering
|
|
6
|
+
* Provider for discovering Aztec wallet extensions.
|
|
7
|
+
*
|
|
8
|
+
* This class handles the discovery phase of wallet communication:
|
|
9
|
+
* 1. Broadcasts a discovery request with the dApp's public key
|
|
10
|
+
* 2. Receives responses from installed wallets with their public keys
|
|
11
|
+
* 3. Derives shared secrets and computes verification hashes
|
|
12
|
+
* 4. Returns discovered wallets with their secure channel components
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const wallets = await ExtensionProvider.discoverExtensions(chainInfo);
|
|
17
|
+
* // Display wallets to user with optional emoji verification
|
|
18
|
+
* for (const wallet of wallets) {
|
|
19
|
+
* const emoji = hashToEmoji(wallet.info.verificationHash!);
|
|
20
|
+
* console.log(`${wallet.info.name}: ${emoji}`);
|
|
21
|
+
* }
|
|
22
|
+
* // User selects a wallet after verifying
|
|
23
|
+
* const wallet = await ExtensionWallet.create(wallets[0], chainInfo, 'my-app');
|
|
24
|
+
* ```
|
|
5
25
|
*/ export class ExtensionProvider {
|
|
6
|
-
static discoveredExtensions = new Map();
|
|
7
26
|
static discoveryInProgress = false;
|
|
8
27
|
/**
|
|
9
|
-
* Discovers all installed Aztec wallet extensions
|
|
28
|
+
* Discovers all installed Aztec wallet extensions and establishes secure channel components.
|
|
29
|
+
*
|
|
30
|
+
* This method:
|
|
31
|
+
* 1. Generates an ECDH key pair for this discovery session
|
|
32
|
+
* 2. Broadcasts a discovery request with the dApp's public key
|
|
33
|
+
* 3. Receives responses from wallets with their public keys and MessagePorts
|
|
34
|
+
* 4. Derives shared secrets and computes verification hashes
|
|
35
|
+
*
|
|
10
36
|
* @param chainInfo - Chain information to check if extensions support this network
|
|
11
37
|
* @param timeout - How long to wait for extensions to respond (ms)
|
|
12
|
-
* @returns Array of discovered
|
|
38
|
+
* @returns Array of discovered wallets with their secure channel components
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const wallets = await ExtensionProvider.discoverExtensions({
|
|
43
|
+
* chainId: Fr(31337),
|
|
44
|
+
* version: Fr(0)
|
|
45
|
+
* });
|
|
46
|
+
* // Access wallet info and secure channel
|
|
47
|
+
* const { info, port, sharedKey } = wallets[0];
|
|
48
|
+
* ```
|
|
13
49
|
*/ static async discoverExtensions(chainInfo, timeout = 1000) {
|
|
14
|
-
// If discovery is in progress, wait
|
|
50
|
+
// If discovery is already in progress, wait and return empty
|
|
51
|
+
// (caller should retry or handle appropriately)
|
|
15
52
|
if (this.discoveryInProgress) {
|
|
16
53
|
await new Promise((resolve)=>setTimeout(resolve, timeout));
|
|
17
|
-
return
|
|
54
|
+
return [];
|
|
18
55
|
}
|
|
19
56
|
this.discoveryInProgress = true;
|
|
20
|
-
this
|
|
57
|
+
// Generate key pair for this discovery session
|
|
58
|
+
const keyPair = await generateKeyPair();
|
|
59
|
+
const exportedPublicKey = await exportPublicKey(keyPair.publicKey);
|
|
21
60
|
const { promise, resolve } = promiseWithResolvers();
|
|
22
61
|
const requestId = globalThis.crypto.randomUUID();
|
|
23
62
|
const responses = [];
|
|
@@ -32,17 +71,46 @@ import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
|
32
71
|
} catch {
|
|
33
72
|
return;
|
|
34
73
|
}
|
|
35
|
-
if (data.type ===
|
|
36
|
-
|
|
37
|
-
|
|
74
|
+
if (data.type === WalletMessageType.DISCOVERY_RESPONSE && data.requestId === requestId) {
|
|
75
|
+
// Get the MessagePort from the event
|
|
76
|
+
const port = event.ports?.[0];
|
|
77
|
+
if (!port) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// Derive shared key from wallet's public key
|
|
81
|
+
const walletPublicKey = data.walletInfo.publicKey;
|
|
82
|
+
if (!walletPublicKey) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
void (async ()=>{
|
|
86
|
+
try {
|
|
87
|
+
const importedWalletKey = await importPublicKey(walletPublicKey);
|
|
88
|
+
const sharedKey = await deriveSharedKey(keyPair.privateKey, importedWalletKey);
|
|
89
|
+
// Compute verification hash
|
|
90
|
+
const verificationHash = await hashSharedSecret(sharedKey);
|
|
91
|
+
// Create wallet info with verification hash
|
|
92
|
+
const walletInfo = {
|
|
93
|
+
...data.walletInfo,
|
|
94
|
+
verificationHash
|
|
95
|
+
};
|
|
96
|
+
responses.push({
|
|
97
|
+
info: walletInfo,
|
|
98
|
+
port,
|
|
99
|
+
sharedKey
|
|
100
|
+
});
|
|
101
|
+
} catch {
|
|
102
|
+
// Failed to derive key, skip this wallet
|
|
103
|
+
}
|
|
104
|
+
})();
|
|
38
105
|
}
|
|
39
106
|
};
|
|
40
107
|
window.addEventListener('message', handleMessage);
|
|
41
|
-
// Send discovery message
|
|
108
|
+
// Send discovery message with our public key
|
|
42
109
|
const discoveryMessage = {
|
|
43
|
-
type:
|
|
110
|
+
type: WalletMessageType.DISCOVERY,
|
|
44
111
|
requestId,
|
|
45
|
-
chainInfo
|
|
112
|
+
chainInfo,
|
|
113
|
+
publicKey: exportedPublicKey
|
|
46
114
|
};
|
|
47
115
|
window.postMessage(jsonStringify(discoveryMessage), '*');
|
|
48
116
|
// Wait for responses
|
|
@@ -1,23 +1,155 @@
|
|
|
1
1
|
import type { ChainInfo } from '@aztec/aztec.js/account';
|
|
2
2
|
import { type Wallet } from '@aztec/aztec.js/wallet';
|
|
3
|
+
import { type WalletInfo } from '../../types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Callback type for wallet disconnect events.
|
|
6
|
+
*/
|
|
7
|
+
export type DisconnectCallback = () => void;
|
|
3
8
|
/**
|
|
4
9
|
* A wallet implementation that communicates with browser extension wallets
|
|
5
|
-
*
|
|
10
|
+
* using a secure encrypted MessageChannel.
|
|
11
|
+
*
|
|
12
|
+
* This class uses a pre-established secure channel from the discovery phase:
|
|
13
|
+
*
|
|
14
|
+
* 1. **MessageChannel**: A private communication channel created during discovery,
|
|
15
|
+
* not visible to other scripts on the page (unlike window.postMessage).
|
|
16
|
+
*
|
|
17
|
+
* 2. **ECDH Key Exchange**: The shared secret was derived during discovery using
|
|
18
|
+
* Elliptic Curve Diffie-Hellman key exchange.
|
|
19
|
+
*
|
|
20
|
+
* 3. **AES-GCM Encryption**: All messages are encrypted using AES-256-GCM,
|
|
21
|
+
* providing both confidentiality and authenticity.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Discovery returns wallets with secure channel components
|
|
26
|
+
* const wallets = await ExtensionProvider.discoverExtensions(chainInfo);
|
|
27
|
+
* const { info, port, sharedKey } = wallets[0];
|
|
28
|
+
*
|
|
29
|
+
* // User can verify emoji if desired
|
|
30
|
+
* console.log('Verify:', hashToEmoji(info.verificationHash!));
|
|
31
|
+
*
|
|
32
|
+
* // Create wallet using the discovered components
|
|
33
|
+
* const wallet = await ExtensionWallet.create(info, chainInfo, port, sharedKey, 'my-dapp');
|
|
34
|
+
*
|
|
35
|
+
* // All subsequent calls are encrypted
|
|
36
|
+
* const accounts = await wallet.getAccounts();
|
|
37
|
+
* ```
|
|
6
38
|
*/
|
|
7
39
|
export declare class ExtensionWallet {
|
|
8
40
|
private chainInfo;
|
|
9
41
|
private appId;
|
|
10
42
|
private extensionId;
|
|
43
|
+
private port;
|
|
44
|
+
private sharedKey;
|
|
45
|
+
/** Map of pending requests awaiting responses, keyed by message ID */
|
|
11
46
|
private inFlight;
|
|
12
|
-
private
|
|
47
|
+
private disconnected;
|
|
48
|
+
private disconnectCallbacks;
|
|
13
49
|
/**
|
|
14
|
-
*
|
|
50
|
+
* Private constructor - use {@link ExtensionWallet.create} to instantiate.
|
|
15
51
|
* @param chainInfo - The chain information (chainId and version)
|
|
16
|
-
* @param appId - Application identifier for the requesting
|
|
17
|
-
* @param extensionId -
|
|
18
|
-
* @
|
|
52
|
+
* @param appId - Application identifier for the requesting dApp
|
|
53
|
+
* @param extensionId - The unique identifier of the target wallet extension
|
|
54
|
+
* @param port - The MessagePort for private communication with the wallet
|
|
55
|
+
* @param sharedKey - The derived AES-256-GCM shared key for encryption
|
|
56
|
+
*/
|
|
57
|
+
private constructor();
|
|
58
|
+
/** Cached Wallet proxy instance */
|
|
59
|
+
private walletProxy;
|
|
60
|
+
/**
|
|
61
|
+
* Creates an ExtensionWallet instance that communicates with a browser extension
|
|
62
|
+
* over a secure encrypted MessageChannel.
|
|
63
|
+
*
|
|
64
|
+
* @param walletInfo - The wallet info from ExtensionProvider.discoverExtensions()
|
|
65
|
+
* @param chainInfo - The chain information (chainId and version) for request context
|
|
66
|
+
* @param port - The MessagePort for private communication with the wallet
|
|
67
|
+
* @param sharedKey - The derived AES-256-GCM shared key for encryption
|
|
68
|
+
* @param appId - Application identifier used to identify the requesting dApp to the wallet
|
|
69
|
+
* @returns The ExtensionWallet instance. Use {@link getWallet} to get the Wallet interface.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* const wallets = await ExtensionProvider.discoverExtensions(chainInfo);
|
|
74
|
+
* const { info, port, sharedKey } = wallets[0];
|
|
75
|
+
* const extensionWallet = ExtensionWallet.create(
|
|
76
|
+
* info,
|
|
77
|
+
* { chainId: Fr(31337), version: Fr(0) },
|
|
78
|
+
* port,
|
|
79
|
+
* sharedKey,
|
|
80
|
+
* 'my-defi-app'
|
|
81
|
+
* );
|
|
82
|
+
*
|
|
83
|
+
* // Register disconnect handler
|
|
84
|
+
* extensionWallet.onDisconnect(() => console.log('Disconnected!'));
|
|
85
|
+
*
|
|
86
|
+
* // Get the Wallet interface for dApp usage
|
|
87
|
+
* const wallet = extensionWallet.getWallet();
|
|
88
|
+
* const accounts = await wallet.getAccounts();
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
static create(walletInfo: WalletInfo, chainInfo: ChainInfo, port: MessagePort, sharedKey: CryptoKey, appId: string): ExtensionWallet;
|
|
92
|
+
/**
|
|
93
|
+
* Returns a Wallet interface that proxies all method calls through the secure channel.
|
|
94
|
+
*
|
|
95
|
+
* The returned Wallet can be used directly by dApps - all method calls are automatically
|
|
96
|
+
* encrypted and sent to the wallet extension.
|
|
97
|
+
*
|
|
98
|
+
* @returns A Wallet implementation that encrypts all communication
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* const extensionWallet = ExtensionWallet.create(info, chainInfo, port, sharedKey, 'my-app');
|
|
103
|
+
* const wallet = extensionWallet.getWallet();
|
|
104
|
+
* const accounts = await wallet.getAccounts();
|
|
105
|
+
* ```
|
|
19
106
|
*/
|
|
20
|
-
|
|
107
|
+
getWallet(): Wallet;
|
|
108
|
+
private handleEncryptedResponse;
|
|
21
109
|
private postMessage;
|
|
110
|
+
/**
|
|
111
|
+
* Handles wallet disconnection.
|
|
112
|
+
* Rejects all pending requests and notifies registered callbacks.
|
|
113
|
+
* @internal
|
|
114
|
+
*/
|
|
115
|
+
private handleDisconnect;
|
|
116
|
+
/**
|
|
117
|
+
* Registers a callback to be invoked when the wallet disconnects.
|
|
118
|
+
*
|
|
119
|
+
* @param callback - Function to call when wallet disconnects
|
|
120
|
+
* @returns A function to unregister the callback
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* const wallet = await ExtensionWallet.create(...);
|
|
125
|
+
* const unsubscribe = wallet.onDisconnect(() => {
|
|
126
|
+
* console.log('Wallet disconnected! Please reconnect.');
|
|
127
|
+
* // Clean up UI, prompt user to reconnect, etc.
|
|
128
|
+
* });
|
|
129
|
+
* // Later: unsubscribe(); to stop receiving notifications
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
onDisconnect(callback: DisconnectCallback): () => void;
|
|
133
|
+
/**
|
|
134
|
+
* Returns whether the wallet has been disconnected.
|
|
135
|
+
*
|
|
136
|
+
* @returns true if the wallet is no longer connected
|
|
137
|
+
*/
|
|
138
|
+
isDisconnected(): boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Disconnects from the wallet and cleans up resources.
|
|
141
|
+
*
|
|
142
|
+
* This method notifies the wallet extension that the session is ending,
|
|
143
|
+
* allowing it to clean up its state. After calling this method, the wallet
|
|
144
|
+
* instance can no longer be used and any pending requests will be rejected.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* const wallet = await provider.connect('my-app');
|
|
149
|
+
* // ... use wallet ...
|
|
150
|
+
* await wallet.disconnect(); // Clean disconnect when done
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
disconnect(): Promise<void>;
|
|
22
154
|
}
|
|
23
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
155
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0ZW5zaW9uX3dhbGxldC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy9leHRlbnNpb24vZXh0ZW5zaW9uX3dhbGxldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsS0FBSyxNQUFNLEVBQWdCLE1BQU0sd0JBQXdCLENBQUM7QUFPbkUsT0FBTyxFQUFFLEtBQUssVUFBVSxFQUE4RCxNQUFNLGdCQUFnQixDQUFDO0FBYTdHOztHQUVHO0FBQ0gsTUFBTSxNQUFNLGtCQUFrQixHQUFHLE1BQU0sSUFBSSxDQUFDO0FBRTVDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4Qkc7QUFDSCxxQkFBYSxlQUFlO0lBZXhCLE9BQU8sQ0FBQyxTQUFTO0lBQ2pCLE9BQU8sQ0FBQyxLQUFLO0lBQ2IsT0FBTyxDQUFDLFdBQVc7SUFDbkIsT0FBTyxDQUFDLElBQUk7SUFDWixPQUFPLENBQUMsU0FBUztJQWxCbkIsc0VBQXNFO0lBQ3RFLE9BQU8sQ0FBQyxRQUFRLENBQW9EO0lBQ3BFLE9BQU8sQ0FBQyxZQUFZLENBQVM7SUFDN0IsT0FBTyxDQUFDLG1CQUFtQixDQUE0QjtJQUV2RDs7Ozs7OztPQU9HO0lBQ0gsT0FBTyxlQU1IO0lBRUosbUNBQW1DO0lBQ25DLE9BQU8sQ0FBQyxXQUFXLENBQXVCO0lBRTFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0E4Qkc7SUFDSCxNQUFNLENBQUMsTUFBTSxDQUNYLFVBQVUsRUFBRSxVQUFVLEVBQ3RCLFNBQVMsRUFBRSxTQUFTLEVBQ3BCLElBQUksRUFBRSxXQUFXLEVBQ2pCLFNBQVMsRUFBRSxTQUFTLEVBQ3BCLEtBQUssRUFBRSxNQUFNLEdBQ1osZUFBZSxDQVdqQjtJQUVEOzs7Ozs7Ozs7Ozs7OztPQWNHO0lBQ0gsU0FBUyxJQUFJLE1BQU0sQ0F1QmxCO1lBVWEsdUJBQXVCO1lBMER2QixXQUFXO0lBMkJ6Qjs7OztPQUlHO0lBQ0gsT0FBTyxDQUFDLGdCQUFnQjtJQStCeEI7Ozs7Ozs7Ozs7Ozs7OztPQWVHO0lBQ0gsWUFBWSxDQUFDLFFBQVEsRUFBRSxrQkFBa0IsR0FBRyxNQUFNLElBQUksQ0FRckQ7SUFFRDs7OztPQUlHO0lBQ0gsY0FBYyxJQUFJLE9BQU8sQ0FFeEI7SUFFRDs7Ozs7Ozs7Ozs7OztPQWFHO0lBQ0csVUFBVSxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0EyQmhDO0NBQ0YifQ==
|
|
@@ -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;
|
|
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,EAAE,KAAK,UAAU,EAA8D,MAAM,gBAAgB,CAAC;AAa7G;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,eAAe;IAexB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,SAAS;IAlBnB,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAoD;IACpE,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,mBAAmB,CAA4B;IAEvD;;;;;;;OAOG;IACH,OAAO,eAMH;IAEJ,mCAAmC;IACnC,OAAO,CAAC,WAAW,CAAuB;IAE1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;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,eAAe,CAWjB;IAED;;;;;;;;;;;;;;OAcG;IACH,SAAS,IAAI,MAAM,CAuBlB;YAUa,uBAAuB;YA0DvB,WAAW;IA2BzB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IA+BxB;;;;;;;;;;;;;;;OAeG;IACH,YAAY,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,IAAI,CAQrD;IAED;;;;OAIG;IACH,cAAc,IAAI,OAAO,CAExB;IAED;;;;;;;;;;;;;OAaG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CA2BhC;CACF"}
|