@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.
- package/README.md +424 -0
- package/dest/base-wallet/base_wallet.d.ts +94 -0
- package/dest/base-wallet/base_wallet.d.ts.map +1 -0
- package/dest/base-wallet/base_wallet.js +225 -0
- package/dest/base-wallet/index.d.ts +2 -0
- package/dest/base-wallet/index.d.ts.map +1 -0
- package/dest/base-wallet/index.js +1 -0
- package/dest/manager/index.d.ts +8 -0
- package/dest/manager/index.d.ts.map +1 -0
- package/dest/manager/index.js +5 -0
- package/dest/manager/types.d.ts +64 -0
- package/dest/manager/types.d.ts.map +1 -0
- package/dest/manager/types.js +3 -0
- package/dest/manager/wallet_manager.d.ts +27 -0
- package/dest/manager/wallet_manager.d.ts.map +1 -0
- package/dest/manager/wallet_manager.js +77 -0
- package/dest/providers/extension/extension_provider.d.ts +17 -0
- package/dest/providers/extension/extension_provider.d.ts.map +1 -0
- package/dest/providers/extension/extension_provider.js +56 -0
- package/dest/providers/extension/extension_wallet.d.ts +23 -0
- package/dest/providers/extension/extension_wallet.d.ts.map +1 -0
- package/dest/providers/extension/extension_wallet.js +96 -0
- package/dest/providers/extension/index.d.ts +4 -0
- package/dest/providers/extension/index.d.ts.map +1 -0
- package/dest/providers/extension/index.js +2 -0
- package/dest/providers/types.d.ts +67 -0
- package/dest/providers/types.d.ts.map +1 -0
- package/dest/providers/types.js +3 -0
- package/package.json +95 -0
- package/src/base-wallet/base_wallet.ts +342 -0
- package/src/base-wallet/index.ts +1 -0
- package/src/manager/index.ts +24 -0
- package/src/manager/types.ts +69 -0
- package/src/manager/wallet_manager.ts +86 -0
- package/src/providers/extension/extension_provider.ts +72 -0
- package/src/providers/extension/extension_wallet.ts +124 -0
- package/src/providers/extension/index.ts +3 -0
- 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,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
|
+
}
|