@aztec/wallets 0.0.1-commit.4d79d1f2d

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 (37) hide show
  1. package/dest/embedded/account-contract-providers/bundle.d.ts +17 -0
  2. package/dest/embedded/account-contract-providers/bundle.d.ts.map +1 -0
  3. package/dest/embedded/account-contract-providers/bundle.js +23 -0
  4. package/dest/embedded/account-contract-providers/lazy.d.ts +17 -0
  5. package/dest/embedded/account-contract-providers/lazy.d.ts.map +1 -0
  6. package/dest/embedded/account-contract-providers/lazy.js +25 -0
  7. package/dest/embedded/account-contract-providers/types.d.ts +18 -0
  8. package/dest/embedded/account-contract-providers/types.d.ts.map +1 -0
  9. package/dest/embedded/account-contract-providers/types.js +6 -0
  10. package/dest/embedded/embedded_wallet.d.ts +42 -0
  11. package/dest/embedded/embedded_wallet.d.ts.map +1 -0
  12. package/dest/embedded/embedded_wallet.js +154 -0
  13. package/dest/embedded/embedded_wallet_browser.d.ts +5 -0
  14. package/dest/embedded/embedded_wallet_browser.d.ts.map +1 -0
  15. package/dest/embedded/embedded_wallet_browser.js +31 -0
  16. package/dest/embedded/entrypoints/browser.d.ts +9 -0
  17. package/dest/embedded/entrypoints/browser.d.ts.map +1 -0
  18. package/dest/embedded/entrypoints/browser.js +35 -0
  19. package/dest/embedded/entrypoints/node.d.ts +18 -0
  20. package/dest/embedded/entrypoints/node.d.ts.map +1 -0
  21. package/dest/embedded/entrypoints/node.js +44 -0
  22. package/dest/embedded/wallet_db.d.ts +34 -0
  23. package/dest/embedded/wallet_db.d.ts.map +1 -0
  24. package/dest/embedded/wallet_db.js +120 -0
  25. package/dest/testing.d.ts +12 -0
  26. package/dest/testing.d.ts.map +1 -0
  27. package/dest/testing.js +24 -0
  28. package/package.json +91 -0
  29. package/src/embedded/account-contract-providers/bundle.ts +35 -0
  30. package/src/embedded/account-contract-providers/lazy.ts +37 -0
  31. package/src/embedded/account-contract-providers/types.ts +18 -0
  32. package/src/embedded/embedded_wallet.ts +203 -0
  33. package/src/embedded/embedded_wallet_browser.ts +40 -0
  34. package/src/embedded/entrypoints/browser.ts +50 -0
  35. package/src/embedded/entrypoints/node.ts +80 -0
  36. package/src/embedded/wallet_db.ts +134 -0
  37. package/src/testing.ts +42 -0
@@ -0,0 +1,120 @@
1
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
3
+ export const AccountTypes = [
4
+ 'schnorr',
5
+ 'ecdsasecp256r1',
6
+ 'ecdsasecp256k1'
7
+ ];
8
+ function accountKey(field, address) {
9
+ return `${field}:${address.toString()}`;
10
+ }
11
+ export class WalletDB {
12
+ accounts;
13
+ aliases;
14
+ userLog;
15
+ constructor(accounts, aliases, userLog){
16
+ this.accounts = accounts;
17
+ this.aliases = aliases;
18
+ this.userLog = userLog;
19
+ }
20
+ static init(store, userLog) {
21
+ const accounts = store.openMap('accounts');
22
+ const aliases = store.openMap('aliases');
23
+ return new WalletDB(accounts, aliases, userLog);
24
+ }
25
+ async storeAccount(address, { type, secretKey, salt, alias, signingKey }, log = this.userLog) {
26
+ if (alias) {
27
+ await this.aliases.set(`accounts:${alias}`, Buffer.from(address.toString()));
28
+ }
29
+ await this.accounts.set(accountKey('type', address), Buffer.from(type));
30
+ await this.accounts.set(accountKey('sk', address), secretKey.toBuffer());
31
+ await this.accounts.set(accountKey('salt', address), salt.toBuffer());
32
+ await this.accounts.set(accountKey('signingKey', address), 'toBuffer' in signingKey ? signingKey.toBuffer() : signingKey);
33
+ log(`Account stored in database${alias ? ` with alias ${alias}` : ''}`);
34
+ }
35
+ async storeSender(address, alias, log = this.userLog) {
36
+ await this.aliases.set(`senders:${alias}`, Buffer.from(address.toString()));
37
+ log(`Sender stored in database with alias ${alias}`);
38
+ }
39
+ async retrieveAccount(address) {
40
+ const secretKeyBuffer = await this.accounts.getAsync(accountKey('sk', address));
41
+ if (!secretKeyBuffer) {
42
+ throw new Error(`Account "${address.toString()}" does not exist on this wallet.`);
43
+ }
44
+ const [saltBuffer, typeBuffer, signingKey] = await Promise.all([
45
+ this.accounts.getAsync(accountKey('salt', address)),
46
+ this.accounts.getAsync(accountKey('type', address)),
47
+ this.accounts.getAsync(accountKey('signingKey', address))
48
+ ]);
49
+ const secretKey = Fr.fromBuffer(secretKeyBuffer);
50
+ const salt = Fr.fromBuffer(saltBuffer);
51
+ const type = typeBuffer.toString('utf8');
52
+ return {
53
+ address,
54
+ secretKey,
55
+ salt,
56
+ type,
57
+ signingKey: signingKey
58
+ };
59
+ }
60
+ async listAccounts() {
61
+ // Read aliases and account addresses in parallel using range queries
62
+ const [aliasesByAddress, accountAddresses] = await Promise.all([
63
+ this.#readAccountAliases(),
64
+ this.#readAccountAddresses()
65
+ ]);
66
+ return accountAddresses.map((addressStr)=>({
67
+ alias: aliasesByAddress.get(addressStr) ?? '',
68
+ item: AztecAddress.fromString(addressStr)
69
+ }));
70
+ }
71
+ async listSenders() {
72
+ const result = [];
73
+ for await (const [alias, item] of this.aliases.entriesAsync({
74
+ start: 'senders:',
75
+ end: 'senders:\uffff'
76
+ })){
77
+ result.push({
78
+ alias: alias.slice('senders:'.length),
79
+ item: AztecAddress.fromString(item.toString())
80
+ });
81
+ }
82
+ return result;
83
+ }
84
+ async #readAccountAliases() {
85
+ const aliasesByAddress = new Map();
86
+ for await (const [alias, item] of this.aliases.entriesAsync({
87
+ start: 'accounts:',
88
+ end: 'accounts:\uffff'
89
+ })){
90
+ const address = item.toString();
91
+ aliasesByAddress.set(address, alias.slice('accounts:'.length));
92
+ }
93
+ return aliasesByAddress;
94
+ }
95
+ async #readAccountAddresses() {
96
+ const addresses = [];
97
+ // Range query on 'type:' prefix — one entry per account, avoids scanning sk/salt/signingKey entries
98
+ for await (const [key] of this.accounts.entriesAsync({
99
+ start: 'type:',
100
+ end: 'type:\uffff'
101
+ })){
102
+ addresses.push(key.slice('type:'.length));
103
+ }
104
+ return addresses;
105
+ }
106
+ async deleteAccount(address) {
107
+ await Promise.all([
108
+ this.accounts.delete(accountKey('sk', address)),
109
+ this.accounts.delete(accountKey('salt', address)),
110
+ this.accounts.delete(accountKey('type', address)),
111
+ this.accounts.delete(accountKey('signingKey', address))
112
+ ]);
113
+ // Clean up alias if one exists
114
+ const aliasesByAddress = await this.#readAccountAliases();
115
+ const alias = aliasesByAddress.get(address.toString());
116
+ if (alias) {
117
+ await this.aliases.delete(`accounts:${alias}`);
118
+ }
119
+ }
120
+ }
@@ -0,0 +1,12 @@
1
+ import type { InitialAccountData } from '@aztec/accounts/testing';
2
+ import type { WaitOpts } from '@aztec/aztec.js/contracts';
3
+ import type { AccountManager } from '@aztec/aztec.js/wallet';
4
+ import type { Fq, Fr } from '@aztec/foundation/curves/bn254';
5
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
6
+ interface WalletWithSchnorrAccounts {
7
+ createSchnorrAccount(secret: Fr, salt: Fr, signingKey?: Fq, alias?: string): Promise<AccountManager>;
8
+ }
9
+ export declare function deployFundedSchnorrAccounts(wallet: WalletWithSchnorrAccounts, accountsData: InitialAccountData[], waitOptions?: WaitOpts): Promise<AccountManager[]>;
10
+ export declare function registerInitialLocalNetworkAccountsInWallet(wallet: WalletWithSchnorrAccounts): Promise<AztecAddress[]>;
11
+ export {};
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdGluZy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3Rlc3RpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUVsRSxPQUFPLEtBQUssRUFBRSxRQUFRLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMxRCxPQUFPLEtBQUssRUFBRSxjQUFjLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM3RCxPQUFPLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDN0QsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRTNELFVBQVUseUJBQXlCO0lBQ2pDLG9CQUFvQixDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQztDQUN0RztBQUVELHdCQUFzQiwyQkFBMkIsQ0FDL0MsTUFBTSxFQUFFLHlCQUF5QixFQUNqQyxZQUFZLEVBQUUsa0JBQWtCLEVBQUUsRUFDbEMsV0FBVyxDQUFDLEVBQUUsUUFBUSw2QkFnQnZCO0FBRUQsd0JBQXNCLDJDQUEyQyxDQUMvRCxNQUFNLEVBQUUseUJBQXlCLEdBQ2hDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQU96QiJ9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,UAAU,yBAAyB;IACjC,oBAAoB,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,UAAU,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACtG;AAED,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,yBAAyB,EACjC,YAAY,EAAE,kBAAkB,EAAE,EAClC,WAAW,CAAC,EAAE,QAAQ,6BAgBvB;AAED,wBAAsB,2CAA2C,CAC/D,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAAC,YAAY,EAAE,CAAC,CAOzB"}
@@ -0,0 +1,24 @@
1
+ import { getInitialTestAccountsData } from '@aztec/accounts/testing/lazy';
2
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
3
+ export async function deployFundedSchnorrAccounts(wallet, accountsData, waitOptions) {
4
+ const accountManagers = [];
5
+ // Serial due to https://github.com/AztecProtocol/aztec-packages/issues/12045
6
+ for(let i = 0; i < accountsData.length; i++){
7
+ const { secret, salt, signingKey } = accountsData[i];
8
+ const accountManager = await wallet.createSchnorrAccount(secret, salt, signingKey);
9
+ const deployMethod = await accountManager.getDeployMethod();
10
+ await deployMethod.send({
11
+ from: AztecAddress.ZERO,
12
+ skipClassPublication: i !== 0,
13
+ wait: waitOptions
14
+ });
15
+ accountManagers.push(accountManager);
16
+ }
17
+ return accountManagers;
18
+ }
19
+ export async function registerInitialLocalNetworkAccountsInWallet(wallet) {
20
+ const testAccounts = await getInitialTestAccountsData();
21
+ return Promise.all(testAccounts.map(async (account)=>{
22
+ return (await wallet.createSchnorrAccount(account.secret, account.salt, account.signingKey)).address;
23
+ }));
24
+ }
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "@aztec/wallets",
3
+ "homepage": "https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/wallets",
4
+ "version": "0.0.1-commit.4d79d1f2d",
5
+ "type": "module",
6
+ "exports": {
7
+ "./embedded": {
8
+ "browser": {
9
+ "types": "./dest/embedded/entrypoints/browser.d.ts",
10
+ "default": "./dest/embedded/entrypoints/browser.js"
11
+ },
12
+ "default": {
13
+ "types": "./dest/embedded/entrypoints/node.d.ts",
14
+ "default": "./dest/embedded/entrypoints/node.js"
15
+ }
16
+ },
17
+ "./testing": "./dest/testing.js"
18
+ },
19
+ "scripts": {
20
+ "build": "yarn clean && ../scripts/tsc.sh",
21
+ "build:dev": "../scripts/tsc.sh --watch",
22
+ "build:ts": "../scripts/tsc.sh",
23
+ "clean": "rm -rf ./dest .tsbuildinfo",
24
+ "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
25
+ },
26
+ "inherits": [
27
+ "../package.common.json"
28
+ ],
29
+ "dependencies": {
30
+ "@aztec/accounts": "0.0.1-commit.4d79d1f2d",
31
+ "@aztec/aztec.js": "0.0.1-commit.4d79d1f2d",
32
+ "@aztec/entrypoints": "0.0.1-commit.4d79d1f2d",
33
+ "@aztec/foundation": "0.0.1-commit.4d79d1f2d",
34
+ "@aztec/kv-store": "0.0.1-commit.4d79d1f2d",
35
+ "@aztec/pxe": "0.0.1-commit.4d79d1f2d",
36
+ "@aztec/stdlib": "0.0.1-commit.4d79d1f2d",
37
+ "@aztec/wallet-sdk": "0.0.1-commit.4d79d1f2d"
38
+ },
39
+ "devDependencies": {
40
+ "@jest/globals": "^30.0.0",
41
+ "@typescript/native-preview": "7.0.0-dev.20260113.1",
42
+ "jest": "^30.0.0",
43
+ "ts-node": "^10.9.1",
44
+ "typescript": "^5.3.3"
45
+ },
46
+ "files": [
47
+ "dest",
48
+ "src",
49
+ "!*.test.*"
50
+ ],
51
+ "engines": {
52
+ "node": ">=20.10"
53
+ },
54
+ "jest": {
55
+ "extensionsToTreatAsEsm": [
56
+ ".ts"
57
+ ],
58
+ "transform": {
59
+ "^.+\\.tsx?$": [
60
+ "@swc/jest",
61
+ {
62
+ "jsc": {
63
+ "parser": {
64
+ "syntax": "typescript",
65
+ "decorators": true
66
+ },
67
+ "transform": {
68
+ "decoratorVersion": "2022-03"
69
+ }
70
+ }
71
+ }
72
+ ]
73
+ },
74
+ "moduleNameMapper": {
75
+ "^(\\.{1,2}/.*)\\.[cm]?js$": "$1"
76
+ },
77
+ "reporters": [
78
+ "default"
79
+ ],
80
+ "testTimeout": 120000,
81
+ "testRegex": "./src/.*\\.test\\.(js|mjs|ts)$",
82
+ "rootDir": "./src",
83
+ "setupFiles": [
84
+ "../../foundation/src/jest/setup.mjs"
85
+ ],
86
+ "setupFilesAfterEnv": [
87
+ "../../foundation/src/jest/setupAfterEnv.mjs"
88
+ ],
89
+ "testEnvironment": "../../foundation/src/jest/env.mjs"
90
+ }
91
+ }
@@ -0,0 +1,35 @@
1
+ import { EcdsaKAccountContract, EcdsaRAccountContract } from '@aztec/accounts/ecdsa';
2
+ import { SchnorrAccountContract } from '@aztec/accounts/schnorr';
3
+ import { StubAccountContractArtifact, createStubAccount } from '@aztec/accounts/stub';
4
+ import type { Account, AccountContract } from '@aztec/aztec.js/account';
5
+ import type { Fq } from '@aztec/foundation/curves/bn254';
6
+ import type { ContractArtifact } from '@aztec/stdlib/abi';
7
+ import type { CompleteAddress } from '@aztec/stdlib/contract';
8
+
9
+ import type { AccountContractsProvider } from './types.js';
10
+
11
+ /**
12
+ * Loads account contract artifacts eagerly via static imports.
13
+ * Designed for Node.js environments where all artifacts are available at startup.
14
+ */
15
+ export class BundleAccountContractsProvider implements AccountContractsProvider {
16
+ getSchnorrAccountContract(signingKey: Fq): Promise<AccountContract> {
17
+ return Promise.resolve(new SchnorrAccountContract(signingKey));
18
+ }
19
+
20
+ getEcdsaRAccountContract(signingKey: Buffer): Promise<AccountContract> {
21
+ return Promise.resolve(new EcdsaRAccountContract(signingKey));
22
+ }
23
+
24
+ getEcdsaKAccountContract(signingKey: Buffer): Promise<AccountContract> {
25
+ return Promise.resolve(new EcdsaKAccountContract(signingKey));
26
+ }
27
+
28
+ getStubAccountContractArtifact(): Promise<ContractArtifact> {
29
+ return Promise.resolve(StubAccountContractArtifact);
30
+ }
31
+
32
+ createStubAccount(address: CompleteAddress): Promise<Account> {
33
+ return Promise.resolve(createStubAccount(address));
34
+ }
35
+ }
@@ -0,0 +1,37 @@
1
+ import type { Account, AccountContract } from '@aztec/aztec.js/account';
2
+ import type { Fq } from '@aztec/foundation/curves/bn254';
3
+ import type { ContractArtifact } from '@aztec/stdlib/abi';
4
+ import type { CompleteAddress } from '@aztec/stdlib/contract';
5
+
6
+ import type { AccountContractsProvider } from './types.js';
7
+
8
+ /**
9
+ * Loads account contract artifacts lazily via dynamic imports.
10
+ * Designed for browser environments where code splitting reduces initial bundle size.
11
+ */
12
+ export class LazyAccountContractsProvider implements AccountContractsProvider {
13
+ async getSchnorrAccountContract(signingKey: Fq): Promise<AccountContract> {
14
+ const { SchnorrAccountContract } = await import('@aztec/accounts/schnorr/lazy');
15
+ return new SchnorrAccountContract(signingKey);
16
+ }
17
+
18
+ async getEcdsaRAccountContract(signingKey: Buffer): Promise<AccountContract> {
19
+ const { EcdsaRAccountContract } = await import('@aztec/accounts/ecdsa/lazy');
20
+ return new EcdsaRAccountContract(signingKey);
21
+ }
22
+
23
+ async getEcdsaKAccountContract(signingKey: Buffer): Promise<AccountContract> {
24
+ const { EcdsaKAccountContract } = await import('@aztec/accounts/ecdsa/lazy');
25
+ return new EcdsaKAccountContract(signingKey);
26
+ }
27
+
28
+ async getStubAccountContractArtifact(): Promise<ContractArtifact> {
29
+ const { getStubAccountContractArtifact } = await import('@aztec/accounts/stub/lazy');
30
+ return getStubAccountContractArtifact();
31
+ }
32
+
33
+ async createStubAccount(address: CompleteAddress): Promise<Account> {
34
+ const { createStubAccount } = await import('@aztec/accounts/stub/lazy');
35
+ return createStubAccount(address);
36
+ }
37
+ }
@@ -0,0 +1,18 @@
1
+ import type { Account, AccountContract } from '@aztec/aztec.js/account';
2
+ import type { Fq } from '@aztec/foundation/curves/bn254';
3
+ import type { ContractArtifact } from '@aztec/stdlib/abi';
4
+ import type { CompleteAddress } from '@aztec/stdlib/contract';
5
+
6
+ /**
7
+ * Provides account contract implementations and stub accounts for the EmbeddedWallet.
8
+ * Two implementations exist:
9
+ * - LazyAccountContractsProvider: uses dynamic imports for browser environments
10
+ * - EagerAccountContractsProvider: uses static imports for Node.js environments
11
+ */
12
+ export interface AccountContractsProvider {
13
+ getSchnorrAccountContract(signingKey: Fq): Promise<AccountContract>;
14
+ getEcdsaRAccountContract(signingKey: Buffer): Promise<AccountContract>;
15
+ getEcdsaKAccountContract(signingKey: Buffer): Promise<AccountContract>;
16
+ getStubAccountContractArtifact(): Promise<ContractArtifact>;
17
+ createStubAccount(address: CompleteAddress): Promise<Account>;
18
+ }
@@ -0,0 +1,203 @@
1
+ import { type Account, SignerlessAccount } from '@aztec/aztec.js/account';
2
+ import type { Aliased } from '@aztec/aztec.js/wallet';
3
+ import { AccountManager } from '@aztec/aztec.js/wallet';
4
+ import type { DefaultAccountEntrypointOptions } from '@aztec/entrypoints/account';
5
+ import { Fq, Fr } from '@aztec/foundation/curves/bn254';
6
+ import type { Logger } from '@aztec/foundation/log';
7
+ import type { PXE } from '@aztec/pxe/server';
8
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
9
+ import { getContractInstanceFromInstantiationParams } from '@aztec/stdlib/contract';
10
+ import type { AztecNode } from '@aztec/stdlib/interfaces/client';
11
+ import { deriveSigningKey } from '@aztec/stdlib/keys';
12
+ import { ExecutionPayload, type TxSimulationResult, mergeExecutionPayloads } from '@aztec/stdlib/tx';
13
+ import { BaseWallet, type FeeOptions } from '@aztec/wallet-sdk/base-wallet';
14
+
15
+ import type { AccountContractsProvider } from './account-contract-providers/types.js';
16
+ import { type AccountType, WalletDB } from './wallet_db.js';
17
+
18
+ export type EmbeddedWalletOptions = {
19
+ /** Parent logger. Child loggers are derived via createChild() for each subsystem. */
20
+ logger?: Logger;
21
+ /** Use ephemeral (in-memory) stores. Data will not persist across sessions. */
22
+ ephemeral?: boolean;
23
+ };
24
+
25
+ export class EmbeddedWallet extends BaseWallet {
26
+ constructor(
27
+ pxe: PXE,
28
+ aztecNode: AztecNode,
29
+ protected walletDB: WalletDB,
30
+ protected accountContracts: AccountContractsProvider,
31
+ log?: Logger,
32
+ ) {
33
+ super(pxe, aztecNode, log);
34
+ }
35
+
36
+ protected async getAccountFromAddress(address: AztecAddress): Promise<Account> {
37
+ if (address.equals(AztecAddress.ZERO)) {
38
+ return new SignerlessAccount();
39
+ }
40
+
41
+ const { secretKey, salt, signingKey, type } = await this.walletDB.retrieveAccount(address);
42
+ const accountManager = await this.createAccountInternal(type, secretKey, salt, signingKey);
43
+ const account = await accountManager.getAccount();
44
+
45
+ if (!account) {
46
+ throw new Error(`Account not found in wallet for address: ${address}`);
47
+ }
48
+
49
+ return account;
50
+ }
51
+
52
+ getAccounts(): Promise<Aliased<AztecAddress>[]> {
53
+ return this.walletDB.listAccounts();
54
+ }
55
+
56
+ override async registerSender(address: AztecAddress, alias: string) {
57
+ await this.walletDB.storeSender(address, alias);
58
+ return this.pxe.registerSender(address);
59
+ }
60
+
61
+ override async getAddressBook(): Promise<Aliased<AztecAddress>[]> {
62
+ const senders = await this.pxe.getSenders();
63
+ const storedSenders = await this.walletDB.listSenders();
64
+ for (const storedSender of storedSenders) {
65
+ if (senders.findIndex(sender => sender.equals(storedSender.item)) === -1) {
66
+ await this.pxe.registerSender(storedSender.item);
67
+ }
68
+ }
69
+ return storedSenders;
70
+ }
71
+
72
+ /**
73
+ * Simulates calls via a stub account entrypoint, bypassing real account authorization.
74
+ * This allows kernelless simulation with contract overrides, skipping expensive
75
+ * private kernel circuit execution.
76
+ */
77
+ protected override async simulateViaEntrypoint(
78
+ executionPayload: ExecutionPayload,
79
+ from: AztecAddress,
80
+ feeOptions: FeeOptions,
81
+ _skipTxValidation?: boolean,
82
+ _skipFeeEnforcement?: boolean,
83
+ scopes?: AztecAddress[],
84
+ ): Promise<TxSimulationResult> {
85
+ const { account: fromAccount, instance, artifact } = await this.getFakeAccountDataFor(from);
86
+
87
+ const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
88
+ const executionOptions: DefaultAccountEntrypointOptions = {
89
+ txNonce: Fr.random(),
90
+ cancellable: this.cancellableTransactions,
91
+ feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions,
92
+ };
93
+ const finalExecutionPayload = feeExecutionPayload
94
+ ? mergeExecutionPayloads([feeExecutionPayload, executionPayload])
95
+ : executionPayload;
96
+ const chainInfo = await this.getChainInfo();
97
+ const txRequest = await fromAccount.createTxExecutionRequest(
98
+ finalExecutionPayload,
99
+ feeOptions.gasSettings,
100
+ chainInfo,
101
+ executionOptions,
102
+ );
103
+ return this.pxe.simulateTx(txRequest, {
104
+ simulatePublic: true,
105
+ skipFeeEnforcement: true,
106
+ skipTxValidation: true,
107
+ overrides: {
108
+ contracts: { [from.toString()]: { instance, artifact } },
109
+ },
110
+ scopes,
111
+ });
112
+ }
113
+
114
+ private async getFakeAccountDataFor(address: AztecAddress) {
115
+ const originalAccount = await this.getAccountFromAddress(address);
116
+ if (originalAccount instanceof SignerlessAccount) {
117
+ throw new Error(`Cannot create fake account data for SignerlessAccount at address: ${address}`);
118
+ }
119
+ const originalAddress = (originalAccount as Account).getCompleteAddress();
120
+ const contractInstance = await this.pxe.getContractInstance(originalAddress.address);
121
+ if (!contractInstance) {
122
+ throw new Error(`No contract instance found for address: ${originalAddress.address}`);
123
+ }
124
+ const stubAccount = await this.accountContracts.createStubAccount(originalAddress);
125
+ const stubArtifact = await this.accountContracts.getStubAccountContractArtifact();
126
+ const instance = await getContractInstanceFromInstantiationParams(stubArtifact, {
127
+ salt: Fr.random(),
128
+ });
129
+ return {
130
+ account: stubAccount,
131
+ instance,
132
+ artifact: stubArtifact,
133
+ };
134
+ }
135
+
136
+ protected async createAccountInternal(
137
+ type: AccountType,
138
+ secret: Fr,
139
+ salt: Fr,
140
+ signingKey: Buffer,
141
+ ): Promise<AccountManager> {
142
+ let contract;
143
+ switch (type) {
144
+ case 'schnorr': {
145
+ contract = await this.accountContracts.getSchnorrAccountContract(Fq.fromBuffer(signingKey));
146
+ break;
147
+ }
148
+ case 'ecdsasecp256k1': {
149
+ contract = await this.accountContracts.getEcdsaKAccountContract(signingKey);
150
+ break;
151
+ }
152
+ case 'ecdsasecp256r1': {
153
+ contract = await this.accountContracts.getEcdsaRAccountContract(signingKey);
154
+ break;
155
+ }
156
+ default: {
157
+ throw new Error(`Unknown account type ${type}`);
158
+ }
159
+ }
160
+
161
+ const accountManager = await AccountManager.create(this, secret, contract, salt);
162
+
163
+ const instance = accountManager.getInstance();
164
+ const artifact = await accountManager.getAccountContract().getContractArtifact();
165
+
166
+ await this.registerContract(instance, artifact, accountManager.getSecretKey());
167
+
168
+ return accountManager;
169
+ }
170
+
171
+ async createAndStoreAccount(
172
+ alias: string,
173
+ type: AccountType,
174
+ secret: Fr,
175
+ salt: Fr,
176
+ signingKey: Buffer,
177
+ ): Promise<AccountManager> {
178
+ const accountManager = await this.createAccountInternal(type, secret, salt, signingKey);
179
+ await this.walletDB.storeAccount(accountManager.address, { type, secretKey: secret, salt, alias, signingKey });
180
+ return accountManager;
181
+ }
182
+
183
+ createSchnorrAccount(secret: Fr, salt: Fr, signingKey?: Fq, alias?: string): Promise<AccountManager> {
184
+ const sk = signingKey ?? deriveSigningKey(secret);
185
+ return this.createAndStoreAccount(alias ?? '', 'schnorr', secret, salt, sk.toBuffer());
186
+ }
187
+
188
+ createECDSARAccount(secret: Fr, salt: Fr, signingKey: Buffer, alias?: string): Promise<AccountManager> {
189
+ return this.createAndStoreAccount(alias ?? '', 'ecdsasecp256r1', secret, salt, signingKey);
190
+ }
191
+
192
+ createECDSAKAccount(secret: Fr, salt: Fr, signingKey: Buffer, alias?: string): Promise<AccountManager> {
193
+ return this.createAndStoreAccount(alias ?? '', 'ecdsasecp256k1', secret, salt, signingKey);
194
+ }
195
+
196
+ setMinFeePadding(value?: number) {
197
+ this.minFeePadding = value ?? 0.5;
198
+ }
199
+
200
+ stop() {
201
+ return this.pxe.stop();
202
+ }
203
+ }
@@ -0,0 +1,40 @@
1
+ import { createAztecNodeClient } from '@aztec/aztec.js/node';
2
+ import { createLogger } from '@aztec/foundation/log';
3
+ import { createStore } from '@aztec/kv-store/indexeddb';
4
+ import { createPXE } from '@aztec/pxe/client/lazy';
5
+ import { getPXEConfig } from '@aztec/pxe/config';
6
+
7
+ import { LazyAccountContractsProvider } from './account-contract-providers/lazy.js';
8
+ import { EmbeddedWallet } from './embedded_wallet.js';
9
+ import { WalletDB } from './wallet_db.js';
10
+
11
+ export class BrowserEmbeddedWallet extends EmbeddedWallet {
12
+ static async create(nodeUrl: string): Promise<BrowserEmbeddedWallet> {
13
+ const aztecNode = createAztecNodeClient(nodeUrl);
14
+
15
+ const l1Contracts = await aztecNode.getL1ContractAddresses();
16
+ const rollupAddress = l1Contracts.rollupAddress;
17
+
18
+ const config = getPXEConfig();
19
+ config.dataDirectory = `pxe-${rollupAddress}`;
20
+
21
+ const pxe = await createPXE(aztecNode, config, {
22
+ loggers: {
23
+ store: createLogger('pxe:data:idb'),
24
+ pxe: createLogger('pxe:service'),
25
+ prover: createLogger('bb:wasm:lazy'),
26
+ },
27
+ });
28
+
29
+ const logger = createLogger('embedded-wallet:browser');
30
+ const walletDBStore = await createStore(
31
+ `wallet-${rollupAddress}`,
32
+ { dataDirectory: 'wallet', dataStoreMapSizeKb: 2e10 },
33
+ undefined,
34
+ createLogger('wallet:data:idb'),
35
+ );
36
+ const walletDB = WalletDB.init(walletDBStore, logger.info);
37
+
38
+ return new BrowserEmbeddedWallet(pxe, aztecNode, walletDB, new LazyAccountContractsProvider());
39
+ }
40
+ }
@@ -0,0 +1,50 @@
1
+ import { createAztecNodeClient } from '@aztec/aztec.js/node';
2
+ import { createLogger } from '@aztec/foundation/log';
3
+ import { createStore, openTmpStore } from '@aztec/kv-store/indexeddb';
4
+ import { createPXE } from '@aztec/pxe/client/lazy';
5
+ import { getPXEConfig } from '@aztec/pxe/config';
6
+
7
+ import { LazyAccountContractsProvider } from '../account-contract-providers/lazy.js';
8
+ import { EmbeddedWallet, type EmbeddedWalletOptions } from '../embedded_wallet.js';
9
+ import { WalletDB } from '../wallet_db.js';
10
+
11
+ export class BrowserEmbeddedWallet extends EmbeddedWallet {
12
+ static async create(nodeUrl: string, options: EmbeddedWalletOptions = {}): Promise<BrowserEmbeddedWallet> {
13
+ const rootLogger = options.logger ?? createLogger('embedded-wallet');
14
+
15
+ const aztecNode = createAztecNodeClient(nodeUrl);
16
+
17
+ const l1Contracts = await aztecNode.getL1ContractAddresses();
18
+ const rollupAddress = l1Contracts.rollupAddress;
19
+
20
+ const config = getPXEConfig();
21
+ if (!options.ephemeral) {
22
+ config.dataDirectory = `pxe-${rollupAddress}`;
23
+ }
24
+
25
+ const pxe = await createPXE(aztecNode, config, {
26
+ loggers: {
27
+ store: rootLogger.createChild('pxe:data'),
28
+ pxe: rootLogger.createChild('pxe:service'),
29
+ prover: rootLogger.createChild('pxe:prover'),
30
+ },
31
+ });
32
+
33
+ const walletDBStore = options.ephemeral
34
+ ? await openTmpStore(true)
35
+ : await createStore(
36
+ `wallet-${rollupAddress}`,
37
+ { dataDirectory: 'wallet', dataStoreMapSizeKb: 2e10 },
38
+ undefined,
39
+ rootLogger.createChild('wallet:data'),
40
+ );
41
+ const walletDB = WalletDB.init(walletDBStore, rootLogger.createChild('wallet:db').info);
42
+
43
+ return new BrowserEmbeddedWallet(pxe, aztecNode, walletDB, new LazyAccountContractsProvider(), rootLogger);
44
+ }
45
+ }
46
+
47
+ export { BrowserEmbeddedWallet as EmbeddedWallet };
48
+ export type { EmbeddedWalletOptions } from '../embedded_wallet.js';
49
+ export { WalletDB } from '../wallet_db.js';
50
+ export type { AccountType } from '../wallet_db.js';