@aztec/wallet-sdk 3.0.0-nightly.20251122

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +424 -0
  2. package/dest/base-wallet/base_wallet.d.ts +94 -0
  3. package/dest/base-wallet/base_wallet.d.ts.map +1 -0
  4. package/dest/base-wallet/base_wallet.js +225 -0
  5. package/dest/base-wallet/index.d.ts +2 -0
  6. package/dest/base-wallet/index.d.ts.map +1 -0
  7. package/dest/base-wallet/index.js +1 -0
  8. package/dest/manager/index.d.ts +8 -0
  9. package/dest/manager/index.d.ts.map +1 -0
  10. package/dest/manager/index.js +5 -0
  11. package/dest/manager/types.d.ts +64 -0
  12. package/dest/manager/types.d.ts.map +1 -0
  13. package/dest/manager/types.js +3 -0
  14. package/dest/manager/wallet_manager.d.ts +27 -0
  15. package/dest/manager/wallet_manager.d.ts.map +1 -0
  16. package/dest/manager/wallet_manager.js +77 -0
  17. package/dest/providers/extension/extension_provider.d.ts +17 -0
  18. package/dest/providers/extension/extension_provider.d.ts.map +1 -0
  19. package/dest/providers/extension/extension_provider.js +56 -0
  20. package/dest/providers/extension/extension_wallet.d.ts +23 -0
  21. package/dest/providers/extension/extension_wallet.d.ts.map +1 -0
  22. package/dest/providers/extension/extension_wallet.js +96 -0
  23. package/dest/providers/extension/index.d.ts +4 -0
  24. package/dest/providers/extension/index.d.ts.map +1 -0
  25. package/dest/providers/extension/index.js +2 -0
  26. package/dest/providers/types.d.ts +67 -0
  27. package/dest/providers/types.d.ts.map +1 -0
  28. package/dest/providers/types.js +3 -0
  29. package/package.json +95 -0
  30. package/src/base-wallet/base_wallet.ts +342 -0
  31. package/src/base-wallet/index.ts +1 -0
  32. package/src/manager/index.ts +24 -0
  33. package/src/manager/types.ts +69 -0
  34. package/src/manager/wallet_manager.ts +86 -0
  35. package/src/providers/extension/extension_provider.ts +72 -0
  36. package/src/providers/extension/extension_wallet.ts +124 -0
  37. package/src/providers/extension/index.ts +3 -0
  38. package/src/providers/types.ts +71 -0
@@ -0,0 +1,86 @@
1
+ import { ExtensionProvider, ExtensionWallet } from '../providers/extension/index.js';
2
+ import type { DiscoverWalletsOptions, ExtensionWalletConfig, WalletManagerConfig, WalletProvider } from './types.js';
3
+
4
+ /**
5
+ * Manager for wallet discovery, configuration, and connection
6
+ */
7
+ export class WalletManager {
8
+ private config: WalletManagerConfig = {
9
+ extensions: { enabled: true },
10
+ webWallets: { urls: [] },
11
+ };
12
+
13
+ private constructor() {}
14
+
15
+ /**
16
+ * Configures the WalletManager with provider settings
17
+ * @param config - Configuration options for wallet providers
18
+ */
19
+ static configure(config: WalletManagerConfig): WalletManager {
20
+ const instance = new WalletManager();
21
+ instance.config = {
22
+ extensions: config.extensions ?? { enabled: true },
23
+ webWallets: config.webWallets ?? { urls: [] },
24
+ };
25
+ return instance;
26
+ }
27
+
28
+ /**
29
+ * Discovers all available wallets for a given chain and version.
30
+ * Only returns wallets that support the requested chain and version.
31
+ * @param options - Discovery options including chain info and timeout
32
+ * @returns Array of wallet providers with baked-in chain info
33
+ */
34
+ async getAvailableWallets(options: DiscoverWalletsOptions): Promise<WalletProvider[]> {
35
+ const providers: WalletProvider[] = [];
36
+ const { chainInfo } = options;
37
+
38
+ // Discover extension wallets
39
+ if (this.config.extensions?.enabled) {
40
+ const extensions = await ExtensionProvider.discoverExtensions(chainInfo, options.timeout);
41
+ const extensionConfig = this.config.extensions;
42
+
43
+ for (const ext of extensions) {
44
+ // Apply allow/block lists
45
+ if (!this.isExtensionAllowed(ext.id, extensionConfig)) {
46
+ continue;
47
+ }
48
+
49
+ providers.push({
50
+ id: ext.id,
51
+ type: 'extension',
52
+ name: ext.name,
53
+ icon: ext.icon,
54
+ metadata: {
55
+ version: ext.version,
56
+ },
57
+ connect: (appId: string) => Promise.resolve(ExtensionWallet.create(chainInfo, appId, ext.id)),
58
+ });
59
+ }
60
+ }
61
+
62
+ // TODO: Add web wallet discovery when implemented
63
+
64
+ return providers;
65
+ }
66
+
67
+ /**
68
+ * Checks if an extension is allowed based on allow/block lists
69
+ * @param extensionId - The extension ID to check
70
+ * @param config - Extension wallet configuration containing allow/block lists
71
+ */
72
+ private isExtensionAllowed(extensionId: string, config: ExtensionWalletConfig): boolean {
73
+ // Check block list first
74
+ if (config.blockList && config.blockList.includes(extensionId)) {
75
+ return false;
76
+ }
77
+
78
+ // If allow list exists, extension must be in it
79
+ if (config.allowList && config.allowList.length > 0) {
80
+ return config.allowList.includes(extensionId);
81
+ }
82
+
83
+ // If no allow list, extension is allowed (unless blocked)
84
+ return true;
85
+ }
86
+ }
@@ -0,0 +1,72 @@
1
+ import type { ChainInfo } from '@aztec/aztec.js/account';
2
+ import { jsonStringify } from '@aztec/foundation/json-rpc';
3
+ import { promiseWithResolvers } from '@aztec/foundation/promise';
4
+
5
+ import type { DiscoveryRequest, DiscoveryResponse, WalletInfo } from '../types.js';
6
+
7
+ /**
8
+ * Provider for discovering and managing Aztec wallet extensions
9
+ */
10
+ export class ExtensionProvider {
11
+ private static discoveredExtensions: Map<string, WalletInfo> = new Map();
12
+ private static discoveryInProgress = false;
13
+
14
+ /**
15
+ * Discovers all installed Aztec wallet extensions
16
+ * @param chainInfo - Chain information to check if extensions support this network
17
+ * @param timeout - How long to wait for extensions to respond (ms)
18
+ * @returns Array of discovered extension information
19
+ */
20
+ static async discoverExtensions(chainInfo: ChainInfo, timeout: number = 1000): Promise<WalletInfo[]> {
21
+ // If discovery is in progress, wait for it to complete
22
+ if (this.discoveryInProgress) {
23
+ await new Promise(resolve => setTimeout(resolve, timeout));
24
+ return Array.from(this.discoveredExtensions.values());
25
+ }
26
+
27
+ this.discoveryInProgress = true;
28
+ this.discoveredExtensions.clear();
29
+
30
+ const { promise, resolve } = promiseWithResolvers<WalletInfo[]>();
31
+ const requestId = globalThis.crypto.randomUUID();
32
+ const responses: WalletInfo[] = [];
33
+
34
+ // Set up listener for discovery responses
35
+ const handleMessage = (event: MessageEvent) => {
36
+ if (event.source !== window) {
37
+ return;
38
+ }
39
+
40
+ let data: DiscoveryResponse;
41
+ try {
42
+ data = JSON.parse(event.data);
43
+ } catch {
44
+ return;
45
+ }
46
+
47
+ if (data.type === 'aztec-wallet-discovery-response' && data.requestId === requestId) {
48
+ responses.push(data.walletInfo);
49
+ this.discoveredExtensions.set(data.walletInfo.id, data.walletInfo);
50
+ }
51
+ };
52
+
53
+ window.addEventListener('message', handleMessage);
54
+
55
+ // Send discovery message
56
+ const discoveryMessage: DiscoveryRequest = {
57
+ type: 'aztec-wallet-discovery',
58
+ requestId,
59
+ chainInfo,
60
+ };
61
+ window.postMessage(jsonStringify(discoveryMessage), '*');
62
+
63
+ // Wait for responses
64
+ setTimeout(() => {
65
+ window.removeEventListener('message', handleMessage);
66
+ this.discoveryInProgress = false;
67
+ resolve(responses);
68
+ }, timeout);
69
+
70
+ return promise;
71
+ }
72
+ }
@@ -0,0 +1,124 @@
1
+ import type { ChainInfo } from '@aztec/aztec.js/account';
2
+ import { type Wallet, WalletSchema } from '@aztec/aztec.js/wallet';
3
+ import { jsonStringify } from '@aztec/foundation/json-rpc';
4
+ import { type PromiseWithResolvers, promiseWithResolvers } from '@aztec/foundation/promise';
5
+ import { schemaHasMethod } from '@aztec/foundation/schemas';
6
+ import type { FunctionsOf } from '@aztec/foundation/types';
7
+
8
+ import type { WalletMessage, WalletResponse } from '../types.js';
9
+
10
+ /**
11
+ * Message payload for posting to extension
12
+ */
13
+ type WalletMethodCall = {
14
+ /**
15
+ * The wallet method name to invoke
16
+ */
17
+ type: keyof FunctionsOf<Wallet>;
18
+ /**
19
+ * Arguments to pass to the wallet method
20
+ */
21
+ args: unknown[];
22
+ };
23
+
24
+ /**
25
+ * A wallet implementation that communicates with browser extension wallets
26
+ * Supports multiple extensions by targeting specific extension IDs
27
+ */
28
+ export class ExtensionWallet {
29
+ private inFlight = new Map<string, PromiseWithResolvers<unknown>>();
30
+
31
+ private constructor(
32
+ private chainInfo: ChainInfo,
33
+ private appId: string,
34
+ private extensionId: string,
35
+ ) {}
36
+
37
+ /**
38
+ * Creates an ExtensionWallet instance that proxies wallet calls to a browser extension
39
+ * @param chainInfo - The chain information (chainId and version)
40
+ * @param appId - Application identifier for the requesting dapp
41
+ * @param extensionId - Specific extension ID to communicate with
42
+ * @returns A Proxy object that implements the Wallet interface
43
+ */
44
+ static create(chainInfo: ChainInfo, appId: string, extensionId: string): Wallet {
45
+ const wallet = new ExtensionWallet(chainInfo, appId, extensionId);
46
+
47
+ // Set up message listener for responses from extensions
48
+ window.addEventListener('message', event => {
49
+ if (event.source !== window) {
50
+ return;
51
+ }
52
+
53
+ let data: WalletResponse;
54
+ try {
55
+ data = JSON.parse(event.data);
56
+ } catch {
57
+ return;
58
+ }
59
+
60
+ // Ignore request messages (only process responses)
61
+ if ('type' in data) {
62
+ return;
63
+ }
64
+
65
+ const { messageId, result, error, walletId: responseWalletId } = data;
66
+
67
+ if (!messageId || !responseWalletId) {
68
+ return;
69
+ }
70
+
71
+ if (wallet.extensionId !== responseWalletId) {
72
+ return;
73
+ }
74
+
75
+ if (!wallet.inFlight.has(messageId)) {
76
+ return;
77
+ }
78
+
79
+ const { resolve, reject } = wallet.inFlight.get(messageId)!;
80
+
81
+ if (error) {
82
+ reject(new Error(jsonStringify(error)));
83
+ } else {
84
+ resolve(result);
85
+ }
86
+ wallet.inFlight.delete(messageId);
87
+ });
88
+
89
+ // Create a Proxy that intercepts wallet method calls and forwards them to the extension
90
+ return new Proxy(wallet, {
91
+ get: (target, prop) => {
92
+ if (schemaHasMethod(WalletSchema, prop.toString())) {
93
+ return async (...args: unknown[]) => {
94
+ const result = await target.postMessage({
95
+ type: prop.toString() as keyof FunctionsOf<Wallet>,
96
+ args,
97
+ });
98
+ return WalletSchema[prop.toString() as keyof typeof WalletSchema].returnType().parseAsync(result);
99
+ };
100
+ } else {
101
+ return target[prop as keyof ExtensionWallet];
102
+ }
103
+ },
104
+ }) as unknown as Wallet;
105
+ }
106
+
107
+ private postMessage(call: WalletMethodCall): Promise<unknown> {
108
+ const messageId = globalThis.crypto.randomUUID();
109
+ const message: WalletMessage = {
110
+ type: call.type,
111
+ args: call.args,
112
+ messageId,
113
+ chainInfo: this.chainInfo,
114
+ appId: this.appId,
115
+ walletId: this.extensionId,
116
+ };
117
+
118
+ window.postMessage(jsonStringify(message), '*');
119
+
120
+ const { promise, resolve, reject } = promiseWithResolvers<unknown>();
121
+ this.inFlight.set(messageId, { promise, resolve, reject });
122
+ return promise;
123
+ }
124
+ }
@@ -0,0 +1,3 @@
1
+ export { ExtensionWallet } from './extension_wallet.js';
2
+ export { ExtensionProvider } from './extension_provider.js';
3
+ export type { WalletInfo, WalletMessage, WalletResponse, DiscoveryRequest, DiscoveryResponse } from '../types.js';
@@ -0,0 +1,71 @@
1
+ import type { ChainInfo } from '@aztec/aztec.js/account';
2
+
3
+ /**
4
+ * Information about an installed Aztec wallet wallet
5
+ */
6
+ export interface WalletInfo {
7
+ /** Unique identifier for the wallet */
8
+ id: string;
9
+ /** Display name of the wallet */
10
+ name: string;
11
+ /** URL to the wallet's icon */
12
+ icon?: string;
13
+ /** Wallet version */
14
+ version: string;
15
+ }
16
+
17
+ /**
18
+ * Message format for wallet communication
19
+ */
20
+ export interface WalletMessage {
21
+ /** Unique message ID for tracking responses */
22
+ messageId: string;
23
+ /** The wallet method to call */
24
+ type: string;
25
+ /** Arguments for the method */
26
+ args: unknown[];
27
+ /** Chain information */
28
+ chainInfo: ChainInfo;
29
+ /** Application ID making the request */
30
+ appId: string;
31
+ /** Wallet ID to target a specific wallet */
32
+ walletId: string;
33
+ }
34
+
35
+ /**
36
+ * Response message from wallet
37
+ */
38
+ export interface WalletResponse {
39
+ /** Message ID matching the request */
40
+ messageId: string;
41
+ /** Result data (if successful) */
42
+ result?: unknown;
43
+ /** Error data (if failed) */
44
+ error?: unknown;
45
+ /** Wallet ID that sent the response */
46
+ walletId: string;
47
+ }
48
+
49
+ /**
50
+ * Discovery message for finding installed wallets
51
+ */
52
+ export interface DiscoveryRequest {
53
+ /** Message type for discovery */
54
+ type: 'aztec-wallet-discovery';
55
+ /** Request ID */
56
+ requestId: string;
57
+ /** Chain information to check if wallet supports this network */
58
+ chainInfo: ChainInfo;
59
+ }
60
+
61
+ /**
62
+ * Discovery response from an wallet
63
+ */
64
+ export interface DiscoveryResponse {
65
+ /** Message type for discovery response */
66
+ type: 'aztec-wallet-discovery-response';
67
+ /** Request ID matching the discovery request */
68
+ requestId: string;
69
+ /** Wallet information */
70
+ walletInfo: WalletInfo;
71
+ }