@aztec/wallets 0.0.1-commit.d20b825a7 → 0.0.1-commit.d58ff9d0
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/dest/embedded/account-contract-providers/bundle.d.ts +3 -6
- package/dest/embedded/account-contract-providers/bundle.d.ts.map +1 -1
- package/dest/embedded/account-contract-providers/bundle.js +10 -9
- package/dest/embedded/account-contract-providers/lazy.d.ts +3 -6
- package/dest/embedded/account-contract-providers/lazy.d.ts.map +1 -1
- package/dest/embedded/account-contract-providers/lazy.js +10 -10
- package/dest/embedded/account-contract-providers/types.d.ts +3 -6
- package/dest/embedded/account-contract-providers/types.d.ts.map +1 -1
- package/dest/embedded/embedded_wallet.d.ts +21 -4
- package/dest/embedded/embedded_wallet.d.ts.map +1 -1
- package/dest/embedded/embedded_wallet.js +133 -43
- package/dest/embedded/entrypoints/browser.d.ts +1 -1
- package/dest/embedded/entrypoints/browser.d.ts.map +1 -1
- package/dest/embedded/entrypoints/browser.js +33 -13
- package/dest/embedded/entrypoints/node.d.ts +1 -1
- package/dest/embedded/entrypoints/node.d.ts.map +1 -1
- package/dest/embedded/entrypoints/node.js +36 -13
- package/dest/embedded/store_encryption.d.ts +74 -0
- package/dest/embedded/store_encryption.d.ts.map +1 -0
- package/dest/embedded/store_encryption.js +93 -0
- package/dest/embedded/wallet_db.d.ts +9 -6
- package/dest/embedded/wallet_db.d.ts.map +1 -1
- package/dest/embedded/wallet_db.js +13 -11
- package/dest/testing.d.ts +8 -4
- package/dest/testing.d.ts.map +1 -1
- package/dest/testing.js +8 -14
- package/package.json +12 -10
- package/src/embedded/account-contract-providers/bundle.ts +12 -11
- package/src/embedded/account-contract-providers/lazy.ts +12 -12
- package/src/embedded/account-contract-providers/types.ts +2 -2
- package/src/embedded/embedded_wallet.ts +152 -39
- package/src/embedded/entrypoints/browser.ts +35 -22
- package/src/embedded/entrypoints/node.ts +42 -28
- package/src/embedded/store_encryption.ts +146 -0
- package/src/embedded/wallet_db.ts +18 -12
- package/src/testing.ts +11 -17
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { EcdsaKAccountContract, EcdsaRAccountContract } from '@aztec/accounts/ecdsa';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { StubSchnorrAccountContractArtifact, createStubSchnorrAccount } from '@aztec/accounts/stub
|
|
2
|
+
import { StubEcdsaAccountContractArtifact, createStubEcdsaAccount } from '@aztec/accounts/ecdsa/stub';
|
|
3
|
+
import { SchnorrAccountContract, SchnorrInitializerlessAccountContract } from '@aztec/accounts/schnorr';
|
|
4
|
+
import { StubSchnorrAccountContractArtifact, createStubSchnorrAccount } from '@aztec/accounts/schnorr/stub';
|
|
5
5
|
import type { Account, AccountContract } from '@aztec/aztec.js/account';
|
|
6
6
|
import type { Fq } from '@aztec/foundation/curves/bn254';
|
|
7
|
-
import { getCanonicalMultiCallEntrypoint } from '@aztec/protocol-contracts/multi-call-entrypoint';
|
|
8
7
|
import type { ContractArtifact } from '@aztec/stdlib/abi';
|
|
9
|
-
import type { CompleteAddress
|
|
8
|
+
import type { CompleteAddress } from '@aztec/stdlib/contract';
|
|
10
9
|
|
|
11
10
|
import type { AccountType } from '../wallet_db.js';
|
|
12
11
|
import type { AccountContractsProvider } from './types.js';
|
|
@@ -20,6 +19,10 @@ export class BundleAccountContractsProvider implements AccountContractsProvider
|
|
|
20
19
|
return Promise.resolve(new SchnorrAccountContract(signingKey));
|
|
21
20
|
}
|
|
22
21
|
|
|
22
|
+
getSchnorrInitializerlessAccountContract(signingKey: Fq): Promise<AccountContract> {
|
|
23
|
+
return Promise.resolve(new SchnorrInitializerlessAccountContract(signingKey));
|
|
24
|
+
}
|
|
25
|
+
|
|
23
26
|
getEcdsaRAccountContract(signingKey: Buffer): Promise<AccountContract> {
|
|
24
27
|
return Promise.resolve(new EcdsaRAccountContract(signingKey));
|
|
25
28
|
}
|
|
@@ -29,14 +32,12 @@ export class BundleAccountContractsProvider implements AccountContractsProvider
|
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
getStubAccountContractArtifact(type: AccountType): Promise<ContractArtifact> {
|
|
32
|
-
|
|
35
|
+
const isSchnorr = type === 'schnorr' || type === 'schnorr_initializerless';
|
|
36
|
+
return Promise.resolve(isSchnorr ? StubSchnorrAccountContractArtifact : StubEcdsaAccountContractArtifact);
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
createStubAccount(address: CompleteAddress, type: AccountType): Promise<Account> {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
getMulticallContract(): Promise<{ instance: ContractInstanceWithAddress; artifact: ContractArtifact }> {
|
|
40
|
-
return getCanonicalMultiCallEntrypoint();
|
|
40
|
+
const isSchnorr = type === 'schnorr' || type === 'schnorr_initializerless';
|
|
41
|
+
return Promise.resolve(isSchnorr ? createStubSchnorrAccount(address) : createStubEcdsaAccount(address));
|
|
41
42
|
}
|
|
42
43
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { Account, AccountContract } from '@aztec/aztec.js/account';
|
|
2
2
|
import type { Fq } from '@aztec/foundation/curves/bn254';
|
|
3
|
-
import { getCanonicalMultiCallEntrypoint } from '@aztec/protocol-contracts/multi-call-entrypoint/lazy';
|
|
4
3
|
import type { ContractArtifact } from '@aztec/stdlib/abi';
|
|
5
|
-
import type { CompleteAddress
|
|
4
|
+
import type { CompleteAddress } from '@aztec/stdlib/contract';
|
|
6
5
|
|
|
7
6
|
import type { AccountType } from '../wallet_db.js';
|
|
8
7
|
import type { AccountContractsProvider } from './types.js';
|
|
@@ -17,6 +16,11 @@ export class LazyAccountContractsProvider implements AccountContractsProvider {
|
|
|
17
16
|
return new SchnorrAccountContract(signingKey);
|
|
18
17
|
}
|
|
19
18
|
|
|
19
|
+
async getSchnorrInitializerlessAccountContract(signingKey: Fq): Promise<AccountContract> {
|
|
20
|
+
const { SchnorrInitializerlessAccountContract } = await import('@aztec/accounts/schnorr/lazy');
|
|
21
|
+
return new SchnorrInitializerlessAccountContract(signingKey);
|
|
22
|
+
}
|
|
23
|
+
|
|
20
24
|
async getEcdsaRAccountContract(signingKey: Buffer): Promise<AccountContract> {
|
|
21
25
|
const { EcdsaRAccountContract } = await import('@aztec/accounts/ecdsa/lazy');
|
|
22
26
|
return new EcdsaRAccountContract(signingKey);
|
|
@@ -28,26 +32,22 @@ export class LazyAccountContractsProvider implements AccountContractsProvider {
|
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
async getStubAccountContractArtifact(type: AccountType): Promise<ContractArtifact> {
|
|
31
|
-
if (type === 'schnorr') {
|
|
32
|
-
const { getStubSchnorrAccountContractArtifact } = await import('@aztec/accounts/stub/
|
|
35
|
+
if (type === 'schnorr' || type === 'schnorr_initializerless') {
|
|
36
|
+
const { getStubSchnorrAccountContractArtifact } = await import('@aztec/accounts/schnorr/stub/lazy');
|
|
33
37
|
return getStubSchnorrAccountContractArtifact();
|
|
34
38
|
} else {
|
|
35
|
-
const { getStubEcdsaAccountContractArtifact } = await import('@aztec/accounts/stub/
|
|
39
|
+
const { getStubEcdsaAccountContractArtifact } = await import('@aztec/accounts/ecdsa/stub/lazy');
|
|
36
40
|
return getStubEcdsaAccountContractArtifact();
|
|
37
41
|
}
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
async createStubAccount(address: CompleteAddress, type: AccountType): Promise<Account> {
|
|
41
|
-
if (type === 'schnorr') {
|
|
42
|
-
const { createStubSchnorrAccount } = await import('@aztec/accounts/stub/
|
|
45
|
+
if (type === 'schnorr' || type === 'schnorr_initializerless') {
|
|
46
|
+
const { createStubSchnorrAccount } = await import('@aztec/accounts/schnorr/stub/lazy');
|
|
43
47
|
return createStubSchnorrAccount(address);
|
|
44
48
|
} else {
|
|
45
|
-
const { createStubEcdsaAccount } = await import('@aztec/accounts/stub/
|
|
49
|
+
const { createStubEcdsaAccount } = await import('@aztec/accounts/ecdsa/stub/lazy');
|
|
46
50
|
return createStubEcdsaAccount(address);
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
|
-
|
|
50
|
-
getMulticallContract(): Promise<{ instance: ContractInstanceWithAddress; artifact: ContractArtifact }> {
|
|
51
|
-
return getCanonicalMultiCallEntrypoint();
|
|
52
|
-
}
|
|
53
53
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Account, AccountContract } from '@aztec/aztec.js/account';
|
|
2
2
|
import type { Fq } from '@aztec/foundation/curves/bn254';
|
|
3
3
|
import type { ContractArtifact } from '@aztec/stdlib/abi';
|
|
4
|
-
import type { CompleteAddress
|
|
4
|
+
import type { CompleteAddress } from '@aztec/stdlib/contract';
|
|
5
5
|
|
|
6
6
|
import type { AccountType } from '../wallet_db.js';
|
|
7
7
|
|
|
@@ -13,9 +13,9 @@ import type { AccountType } from '../wallet_db.js';
|
|
|
13
13
|
*/
|
|
14
14
|
export interface AccountContractsProvider {
|
|
15
15
|
getSchnorrAccountContract(signingKey: Fq): Promise<AccountContract>;
|
|
16
|
+
getSchnorrInitializerlessAccountContract(signingKey: Fq): Promise<AccountContract>;
|
|
16
17
|
getEcdsaRAccountContract(signingKey: Buffer): Promise<AccountContract>;
|
|
17
18
|
getEcdsaKAccountContract(signingKey: Buffer): Promise<AccountContract>;
|
|
18
19
|
getStubAccountContractArtifact(type: AccountType): Promise<ContractArtifact>;
|
|
19
|
-
getMulticallContract(): Promise<{ instance: ContractInstanceWithAddress; artifact: ContractArtifact }>;
|
|
20
20
|
createStubAccount(address: CompleteAddress, type: AccountType): Promise<Account>;
|
|
21
21
|
}
|
|
@@ -1,30 +1,48 @@
|
|
|
1
1
|
import { type Account, NO_FROM } from '@aztec/aztec.js/account';
|
|
2
2
|
import { CallAuthorizationRequest } from '@aztec/aztec.js/authorization';
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
ContractFunctionInteraction,
|
|
5
|
+
type InteractionWaitOptions,
|
|
6
|
+
NO_WAIT,
|
|
7
|
+
type SendReturn,
|
|
8
|
+
type WaitOpts,
|
|
9
|
+
} from '@aztec/aztec.js/contracts';
|
|
10
|
+
import type {
|
|
11
|
+
Aliased,
|
|
12
|
+
ExecuteUtilityOptions,
|
|
13
|
+
PrivateEvent,
|
|
14
|
+
PrivateEventFilter,
|
|
15
|
+
ProfileOptions,
|
|
16
|
+
SendOptions,
|
|
17
|
+
SimulateOptions,
|
|
18
|
+
} from '@aztec/aztec.js/wallet';
|
|
5
19
|
import { AccountManager, TxSimulationResultWithAppOffset } from '@aztec/aztec.js/wallet';
|
|
6
20
|
import type { DefaultAccountEntrypointOptions } from '@aztec/entrypoints/account';
|
|
7
21
|
import { DefaultEntrypoint } from '@aztec/entrypoints/default';
|
|
22
|
+
import { poseidon2Hash } from '@aztec/foundation/crypto/poseidon';
|
|
23
|
+
import { Schnorr } from '@aztec/foundation/crypto/schnorr';
|
|
8
24
|
import { Fq, Fr } from '@aztec/foundation/curves/bn254';
|
|
9
25
|
import type { Logger } from '@aztec/foundation/log';
|
|
10
26
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
11
27
|
import type { PXEConfig, PXECreationOptions } from '@aztec/pxe/client/lazy';
|
|
12
28
|
import type { PXE } from '@aztec/pxe/server';
|
|
29
|
+
import type { EventMetadataDefinition, FunctionCall } from '@aztec/stdlib/abi';
|
|
13
30
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
14
|
-
import {
|
|
31
|
+
import { getContractClassFromArtifact } from '@aztec/stdlib/contract';
|
|
15
32
|
import { GasSettings } from '@aztec/stdlib/gas';
|
|
16
33
|
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
17
|
-
import { deriveSigningKey } from '@aztec/stdlib/keys';
|
|
18
34
|
import {
|
|
19
35
|
type ContractOverrides,
|
|
20
36
|
ExecutionPayload,
|
|
21
37
|
SimulationOverrides,
|
|
22
38
|
type TxExecutionRequest,
|
|
39
|
+
type TxProfileResult,
|
|
23
40
|
TxStatus,
|
|
41
|
+
type UtilityExecutionResult,
|
|
24
42
|
collectOffchainEffects,
|
|
25
43
|
mergeExecutionPayloads,
|
|
26
44
|
} from '@aztec/stdlib/tx';
|
|
27
|
-
import { BaseWallet, type SimulateViaEntrypointOptions } from '@aztec/wallet-sdk/base-wallet';
|
|
45
|
+
import { BaseWallet, type SimulateViaEntrypointOptions, getGasLimits } from '@aztec/wallet-sdk/base-wallet';
|
|
28
46
|
|
|
29
47
|
import type { AccountContractsProvider } from './account-contract-providers/types.js';
|
|
30
48
|
import { type AccountType, WalletDB } from './wallet_db.js';
|
|
@@ -40,8 +58,12 @@ export function splitPxeOptions(pxe?: EmbeddedWalletPXEOptions): {
|
|
|
40
58
|
if (!pxe) {
|
|
41
59
|
return { config: {}, creation: {} };
|
|
42
60
|
}
|
|
43
|
-
const { loggers, loggerActorLabel, proverOrOptions, store, simulator, ...config } =
|
|
44
|
-
|
|
61
|
+
const { loggers, loggerActorLabel, proverOrOptions, store, simulator, hooks, preloadedContractsProvider, ...config } =
|
|
62
|
+
pxe;
|
|
63
|
+
return {
|
|
64
|
+
config,
|
|
65
|
+
creation: { loggers, loggerActorLabel, proverOrOptions, store, simulator, hooks, preloadedContractsProvider },
|
|
66
|
+
};
|
|
45
67
|
}
|
|
46
68
|
|
|
47
69
|
/** Options for the EmbeddedWallet's own DB (accounts, senders — distinct from PXE state). */
|
|
@@ -76,6 +98,10 @@ const DEFAULT_ESTIMATED_GAS_PADDING = 0.1;
|
|
|
76
98
|
export class EmbeddedWallet extends BaseWallet {
|
|
77
99
|
protected estimatedGasPadding = DEFAULT_ESTIMATED_GAS_PADDING;
|
|
78
100
|
|
|
101
|
+
// Stub class ids, populated on wallet startup
|
|
102
|
+
// to avoid redundant work per simulation
|
|
103
|
+
protected stubClassIds = new Map<AccountType, Fr>();
|
|
104
|
+
|
|
79
105
|
constructor(
|
|
80
106
|
pxe: PXE,
|
|
81
107
|
aztecNode: AztecNode,
|
|
@@ -104,15 +130,17 @@ export class EmbeddedWallet extends BaseWallet {
|
|
|
104
130
|
|
|
105
131
|
override async registerSender(address: AztecAddress, alias: string) {
|
|
106
132
|
await this.walletDB.storeSender(address, alias);
|
|
107
|
-
|
|
133
|
+
await this.pxe.registerTaggingSecretSource({ kind: 'address-derived', sender: address });
|
|
134
|
+
return address;
|
|
108
135
|
}
|
|
109
136
|
|
|
110
137
|
override async getAddressBook(): Promise<Aliased<AztecAddress>[]> {
|
|
111
|
-
const
|
|
138
|
+
const sources = await this.pxe.getTaggingSecretSources({ kind: 'address-derived' });
|
|
139
|
+
const senders = sources.map(source => source.sender);
|
|
112
140
|
const storedSenders = await this.walletDB.listSenders();
|
|
113
141
|
for (const storedSender of storedSenders) {
|
|
114
142
|
if (senders.findIndex(sender => sender.equals(storedSender.item)) === -1) {
|
|
115
|
-
await this.pxe.
|
|
143
|
+
await this.pxe.registerTaggingSecretSource({ kind: 'address-derived', sender: storedSender.item });
|
|
116
144
|
}
|
|
117
145
|
}
|
|
118
146
|
return storedSenders;
|
|
@@ -127,6 +155,9 @@ export class EmbeddedWallet extends BaseWallet {
|
|
|
127
155
|
executionPayload: ExecutionPayload,
|
|
128
156
|
opts: SendOptions<W>,
|
|
129
157
|
): Promise<SendReturn<W>> {
|
|
158
|
+
// PXE has autoSync disabled by the embedded wallet entrypoints, so we sync once here to cover
|
|
159
|
+
// both the inner simulateTx (via simulateViaEntrypoint) and the proveTx that super.sendTx
|
|
160
|
+
await this.pxe.sync();
|
|
130
161
|
const feeOptions = await this.completeFeeOptions({
|
|
131
162
|
from: opts.from,
|
|
132
163
|
feePayer: executionPayload.feePayer,
|
|
@@ -141,6 +172,7 @@ export class EmbeddedWallet extends BaseWallet {
|
|
|
141
172
|
feeOptions,
|
|
142
173
|
additionalScopes: opts.additionalScopes,
|
|
143
174
|
skipTxValidation: true,
|
|
175
|
+
sendMessagesAs: opts.sendMessagesAs,
|
|
144
176
|
});
|
|
145
177
|
|
|
146
178
|
const offchainEffects = collectOffchainEffects(simulationResult.privateExecutionResult);
|
|
@@ -162,7 +194,8 @@ export class EmbeddedWallet extends BaseWallet {
|
|
|
162
194
|
executionPayload.authWitnesses.push(authwit);
|
|
163
195
|
}
|
|
164
196
|
}
|
|
165
|
-
const
|
|
197
|
+
const maxTxGasLimits = await this.getMaxTxGasLimits();
|
|
198
|
+
const estimated = getGasLimits(simulationResult.gasUsed, maxTxGasLimits, this.estimatedGasPadding);
|
|
166
199
|
this.log.verbose(
|
|
167
200
|
`Estimated gas limits for tx: DA=${estimated.gasLimits.daGas} L2=${estimated.gasLimits.l2Gas} teardownDA=${estimated.teardownGasLimits.daGas} teardownL2=${estimated.teardownGasLimits.l2Gas}`,
|
|
168
201
|
);
|
|
@@ -173,24 +206,82 @@ export class EmbeddedWallet extends BaseWallet {
|
|
|
173
206
|
gasLimits: opts.fee?.gasSettings?.gasLimits ?? estimated.gasLimits,
|
|
174
207
|
teardownGasLimits: opts.fee?.gasSettings?.teardownGasLimits ?? estimated.teardownGasLimits,
|
|
175
208
|
});
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
209
|
+
let wait: InteractionWaitOptions = opts.wait;
|
|
210
|
+
if (wait !== NO_WAIT) {
|
|
211
|
+
const callerWaitOpts: WaitOpts = typeof wait === 'object' ? wait : {};
|
|
212
|
+
wait = {
|
|
213
|
+
...callerWaitOpts,
|
|
214
|
+
// Default to PROPOSED so the wait returns as soon as the tx lands in a proposed L2 block,
|
|
215
|
+
// rather than waiting until the end of the slot for the checkpoint to be published to L1.
|
|
216
|
+
// This is what makes MBPS (Multiple Blocks Per Slot) actually improve UX: with CHECKPOINTED
|
|
217
|
+
// we'd block until L1 inclusion regardless of how early in the slot the tx was sequenced.
|
|
218
|
+
// The tradeoff is a weaker guarantee — a proposed block only becomes canonical once it (or
|
|
219
|
+
// a later block in the same slot) is checkpointed, so a tx could be re-orged out if the
|
|
220
|
+
// proposer fails to publish to L1 (which should be rare, since they'd get slashed for it).
|
|
221
|
+
waitForStatus: callerWaitOpts.waitForStatus ?? TxStatus.PROPOSED,
|
|
222
|
+
};
|
|
187
223
|
}
|
|
188
224
|
return super.sendTx(executionPayload, {
|
|
189
225
|
...opts,
|
|
226
|
+
wait: wait as W,
|
|
190
227
|
fee: { ...opts.fee, gasSettings },
|
|
191
228
|
});
|
|
192
229
|
}
|
|
193
230
|
|
|
231
|
+
/**
|
|
232
|
+
* Overrides the base simulateTx to drive PXE syncing explicitly. The PXE created by the embedded
|
|
233
|
+
* wallet has autoSync disabled (so we can share one sync across simulate+send in sendTx); for
|
|
234
|
+
* standalone simulations we still need a fresh anchor block, which we provide here.
|
|
235
|
+
*/
|
|
236
|
+
public override async simulateTx(
|
|
237
|
+
executionPayload: ExecutionPayload,
|
|
238
|
+
opts: SimulateOptions,
|
|
239
|
+
): Promise<TxSimulationResultWithAppOffset> {
|
|
240
|
+
await this.pxe.sync();
|
|
241
|
+
return super.simulateTx(executionPayload, opts);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
public override async profileTx(executionPayload: ExecutionPayload, opts: ProfileOptions): Promise<TxProfileResult> {
|
|
245
|
+
await this.pxe.sync();
|
|
246
|
+
return super.profileTx(executionPayload, opts);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
public override async executeUtility(
|
|
250
|
+
call: FunctionCall,
|
|
251
|
+
opts: ExecuteUtilityOptions,
|
|
252
|
+
): Promise<UtilityExecutionResult> {
|
|
253
|
+
await this.pxe.sync();
|
|
254
|
+
return super.executeUtility(call, opts);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
public override async getPrivateEvents<T>(
|
|
258
|
+
eventDef: EventMetadataDefinition,
|
|
259
|
+
eventFilter: PrivateEventFilter,
|
|
260
|
+
): Promise<PrivateEvent<T>[]> {
|
|
261
|
+
await this.pxe.sync();
|
|
262
|
+
return super.getPrivateEvents<T>(eventDef, eventFilter);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Hashes and registers the stub class for every supported account type with PXE, populating
|
|
267
|
+
* stubClassIds. Called on wallet initialization.
|
|
268
|
+
*/
|
|
269
|
+
async initStubClasses(): Promise<void> {
|
|
270
|
+
const schnorrArtifact = await this.accountContracts.getStubAccountContractArtifact('schnorr');
|
|
271
|
+
const { id: schnorrClassId } = await getContractClassFromArtifact(schnorrArtifact);
|
|
272
|
+
await this.pxe.registerContractClass(schnorrArtifact);
|
|
273
|
+
|
|
274
|
+
// ecdsa stubs share the same class id
|
|
275
|
+
const ecdsaArtifact = await this.accountContracts.getStubAccountContractArtifact('ecdsasecp256r1');
|
|
276
|
+
const { id: ecdsaClassId } = await getContractClassFromArtifact(ecdsaArtifact);
|
|
277
|
+
await this.pxe.registerContractClass(ecdsaArtifact);
|
|
278
|
+
|
|
279
|
+
this.stubClassIds.set('schnorr', schnorrClassId);
|
|
280
|
+
this.stubClassIds.set('schnorr_initializerless', schnorrClassId);
|
|
281
|
+
this.stubClassIds.set('ecdsasecp256k1', ecdsaClassId);
|
|
282
|
+
this.stubClassIds.set('ecdsasecp256r1', ecdsaClassId);
|
|
283
|
+
}
|
|
284
|
+
|
|
194
285
|
/**
|
|
195
286
|
* Builds contract overrides for all provided addresses by replacing their account contracts with stub implementations.
|
|
196
287
|
* Uses a type-specific stub artifact so that the stub's constructor selector matches the real account's constructor.
|
|
@@ -204,7 +295,12 @@ export class EmbeddedWallet extends BaseWallet {
|
|
|
204
295
|
for (const account of filtered) {
|
|
205
296
|
const address = account.item;
|
|
206
297
|
const { type } = await this.walletDB.retrieveAccount(address);
|
|
207
|
-
const
|
|
298
|
+
const stubClassId = this.stubClassIds.get(type);
|
|
299
|
+
if (!stubClassId) {
|
|
300
|
+
throw new Error(
|
|
301
|
+
`Stub class for account type '${type}' was not registered at wallet init. This is a bug — initStubClasses should cover every supported AccountType.`,
|
|
302
|
+
);
|
|
303
|
+
}
|
|
208
304
|
|
|
209
305
|
const originalAccount = await this.getAccountFromAddress(address);
|
|
210
306
|
const completeAddress = originalAccount.getCompleteAddress();
|
|
@@ -215,15 +311,8 @@ export class EmbeddedWallet extends BaseWallet {
|
|
|
215
311
|
);
|
|
216
312
|
}
|
|
217
313
|
|
|
218
|
-
const stubConstructorArgs = type === 'schnorr' ? [Fr.ZERO, Fr.ZERO] : [Buffer.alloc(32), Buffer.alloc(32)];
|
|
219
|
-
const stubInstance = await getContractInstanceFromInstantiationParams(stubArtifact, {
|
|
220
|
-
salt: Fr.random(),
|
|
221
|
-
constructorArgs: stubConstructorArgs,
|
|
222
|
-
});
|
|
223
|
-
|
|
224
314
|
contracts[address.toString()] = {
|
|
225
|
-
instance:
|
|
226
|
-
artifact: stubArtifact,
|
|
315
|
+
instance: { ...contractInstance, currentContractClassId: stubClassId },
|
|
227
316
|
};
|
|
228
317
|
}
|
|
229
318
|
|
|
@@ -240,7 +329,7 @@ export class EmbeddedWallet extends BaseWallet {
|
|
|
240
329
|
opts: SimulateViaEntrypointOptions,
|
|
241
330
|
): Promise<TxSimulationResultWithAppOffset> {
|
|
242
331
|
const { from, feeOptions, additionalScopes, skipTxValidation, skipFeeEnforcement, sendMessagesAs } = opts;
|
|
243
|
-
const scopes = this.scopesFrom(from, additionalScopes);
|
|
332
|
+
const scopes = this.scopesFrom(from, additionalScopes ?? [], sendMessagesAs);
|
|
244
333
|
|
|
245
334
|
const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
|
|
246
335
|
const finalExecutionPayload = feeExecutionPayload
|
|
@@ -249,7 +338,7 @@ export class EmbeddedWallet extends BaseWallet {
|
|
|
249
338
|
const chainInfo = await this.getChainInfo();
|
|
250
339
|
|
|
251
340
|
const accountOverrides = await this.buildAccountOverrides(scopes);
|
|
252
|
-
const overrides = new SimulationOverrides(accountOverrides);
|
|
341
|
+
const overrides = new SimulationOverrides({ contracts: accountOverrides });
|
|
253
342
|
|
|
254
343
|
let txRequest: TxExecutionRequest;
|
|
255
344
|
if (from === NO_FROM) {
|
|
@@ -293,11 +382,19 @@ export class EmbeddedWallet extends BaseWallet {
|
|
|
293
382
|
signingKey: Buffer,
|
|
294
383
|
): Promise<AccountManager> {
|
|
295
384
|
let contract;
|
|
385
|
+
let immutablesHash;
|
|
386
|
+
let publicKey;
|
|
296
387
|
switch (type) {
|
|
297
388
|
case 'schnorr': {
|
|
298
389
|
contract = await this.accountContracts.getSchnorrAccountContract(Fq.fromBuffer(signingKey));
|
|
299
390
|
break;
|
|
300
391
|
}
|
|
392
|
+
case 'schnorr_initializerless': {
|
|
393
|
+
contract = await this.accountContracts.getSchnorrInitializerlessAccountContract(Fq.fromBuffer(signingKey));
|
|
394
|
+
publicKey = await new Schnorr().computePublicKey(Fq.fromBuffer(signingKey));
|
|
395
|
+
immutablesHash = await poseidon2Hash([publicKey.x, publicKey.y]);
|
|
396
|
+
break;
|
|
397
|
+
}
|
|
301
398
|
case 'ecdsasecp256k1': {
|
|
302
399
|
contract = await this.accountContracts.getEcdsaKAccountContract(signingKey);
|
|
303
400
|
break;
|
|
@@ -311,17 +408,29 @@ export class EmbeddedWallet extends BaseWallet {
|
|
|
311
408
|
}
|
|
312
409
|
}
|
|
313
410
|
|
|
314
|
-
const accountManager = await AccountManager.create(this, secret, contract, salt);
|
|
411
|
+
const accountManager = await AccountManager.create(this, secret, contract, { salt, immutablesHash });
|
|
315
412
|
|
|
316
413
|
const instance = accountManager.getInstance();
|
|
317
414
|
const existingInstance = await this.pxe.getContractInstance(instance.address);
|
|
318
415
|
if (!existingInstance) {
|
|
319
416
|
const existingArtifact = await this.pxe.getContractArtifact(instance.currentContractClassId);
|
|
417
|
+
const artifact = existingArtifact ?? (await accountManager.getAccountContract().getContractArtifact());
|
|
320
418
|
await this.registerContract(
|
|
321
419
|
instance,
|
|
322
420
|
!existingArtifact ? await accountManager.getAccountContract().getContractArtifact() : undefined,
|
|
323
421
|
accountManager.getSecretKey(),
|
|
324
422
|
);
|
|
423
|
+
if (type === 'schnorr_initializerless') {
|
|
424
|
+
const constructor = artifact.functions.find(f => f.name === 'constructor');
|
|
425
|
+
if (!constructor) {
|
|
426
|
+
throw new Error('Could not create SchnorrInitializerlessAccountContract: constructor ABI not found');
|
|
427
|
+
}
|
|
428
|
+
const storeCall = new ContractFunctionInteraction(this, instance.address, constructor, [
|
|
429
|
+
publicKey!.x,
|
|
430
|
+
publicKey!.y,
|
|
431
|
+
]);
|
|
432
|
+
await storeCall.simulate({ from: instance.address });
|
|
433
|
+
}
|
|
325
434
|
}
|
|
326
435
|
return accountManager;
|
|
327
436
|
}
|
|
@@ -338,9 +447,12 @@ export class EmbeddedWallet extends BaseWallet {
|
|
|
338
447
|
return accountManager;
|
|
339
448
|
}
|
|
340
449
|
|
|
341
|
-
createSchnorrAccount(secret: Fr, salt: Fr, signingKey
|
|
342
|
-
|
|
343
|
-
|
|
450
|
+
createSchnorrAccount(secret: Fr, salt: Fr, signingKey: Fq, alias?: string): Promise<AccountManager> {
|
|
451
|
+
return this.createAndStoreAccount(alias ?? '', 'schnorr', secret, salt, signingKey.toBuffer());
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
createSchnorrInitializerlessAccount(secret: Fr, salt: Fr, signingKey: Fq, alias?: string): Promise<AccountManager> {
|
|
455
|
+
return this.createAndStoreAccount(alias ?? '', 'schnorr_initializerless', secret, salt, signingKey.toBuffer());
|
|
344
456
|
}
|
|
345
457
|
|
|
346
458
|
createECDSARAccount(secret: Fr, salt: Fr, signingKey: Buffer, alias?: string): Promise<AccountManager> {
|
|
@@ -359,7 +471,8 @@ export class EmbeddedWallet extends BaseWallet {
|
|
|
359
471
|
this.estimatedGasPadding = value ?? DEFAULT_ESTIMATED_GAS_PADDING;
|
|
360
472
|
}
|
|
361
473
|
|
|
362
|
-
stop() {
|
|
363
|
-
|
|
474
|
+
async stop(): Promise<void> {
|
|
475
|
+
await this.pxe.stop();
|
|
476
|
+
await this.walletDB.close();
|
|
364
477
|
}
|
|
365
478
|
}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { type AztecNode, createAztecNodeClient } from '@aztec/aztec.js/node';
|
|
2
2
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
3
|
-
import {
|
|
4
|
-
import { type PXE, type PXECreationOptions, createPXE } from '@aztec/pxe/client/lazy';
|
|
3
|
+
import { openTmpStore } from '@aztec/kv-store/sqlite-opfs';
|
|
4
|
+
import { type PXE, type PXECreationOptions, createPXE, openBrowserStore } from '@aztec/pxe/client/lazy';
|
|
5
5
|
import { type PXEConfig, getPXEConfig } from '@aztec/pxe/config';
|
|
6
|
+
import { getStandardAuthRegistry } from '@aztec/standard-contracts/auth-registry/lazy';
|
|
7
|
+
import { getStandardHandshakeRegistry } from '@aztec/standard-contracts/handshake-registry/lazy';
|
|
8
|
+
import { getStandardMultiCallEntrypoint } from '@aztec/standard-contracts/multi-call-entrypoint/lazy';
|
|
6
9
|
|
|
7
10
|
import { LazyAccountContractsProvider } from '../account-contract-providers/lazy.js';
|
|
8
11
|
import type { AccountContractsProvider } from '../account-contract-providers/types.js';
|
|
9
12
|
import { EmbeddedWallet, type EmbeddedWalletOptions, splitPxeOptions } from '../embedded_wallet.js';
|
|
10
|
-
import { WalletDB } from '../wallet_db.js';
|
|
13
|
+
import { WALLET_DATA_SCHEMA_VERSION, WalletDB } from '../wallet_db.js';
|
|
11
14
|
|
|
12
15
|
export class BrowserEmbeddedWallet extends EmbeddedWallet {
|
|
13
16
|
static async create<T extends BrowserEmbeddedWallet = BrowserEmbeddedWallet>(
|
|
@@ -24,7 +27,6 @@ export class BrowserEmbeddedWallet extends EmbeddedWallet {
|
|
|
24
27
|
const rootLogger = options.logger ?? createLogger('embedded-wallet');
|
|
25
28
|
|
|
26
29
|
const aztecNode = typeof nodeOrUrl === 'string' ? createAztecNodeClient(nodeOrUrl) : nodeOrUrl;
|
|
27
|
-
const l1Contracts = await aztecNode.getL1ContractAddresses();
|
|
28
30
|
|
|
29
31
|
// Support both the new unified `pxe` option and the deprecated `pxeConfig`/`pxeOptions`.
|
|
30
32
|
const { config: pxeConfigFromPxe, creation: pxeCreationFromPxe } = splitPxeOptions(options.pxe);
|
|
@@ -32,8 +34,10 @@ export class BrowserEmbeddedWallet extends EmbeddedWallet {
|
|
|
32
34
|
const mergedCreationOverrides: PXECreationOptions = { ...options.pxeOptions, ...pxeCreationFromPxe };
|
|
33
35
|
|
|
34
36
|
const pxeConfig: PXEConfig = Object.assign(getPXEConfig(), {
|
|
35
|
-
proverEnabled: mergedConfigOverrides.proverEnabled
|
|
36
|
-
|
|
37
|
+
proverEnabled: mergedConfigOverrides.proverEnabled,
|
|
38
|
+
// Unused in the browser: sqlite-opfs keys stores by name, not directory.
|
|
39
|
+
dataDirectory: 'pxe_data',
|
|
40
|
+
autoSync: false,
|
|
37
41
|
...mergedConfigOverrides,
|
|
38
42
|
});
|
|
39
43
|
|
|
@@ -43,6 +47,13 @@ export class BrowserEmbeddedWallet extends EmbeddedWallet {
|
|
|
43
47
|
|
|
44
48
|
const pxeOptions: PXECreationOptions = {
|
|
45
49
|
...mergedCreationOverrides,
|
|
50
|
+
preloadedContractsProvider: mergedCreationOverrides.preloadedContractsProvider ?? {
|
|
51
|
+
getPreloadedContracts: async () => [
|
|
52
|
+
await getStandardMultiCallEntrypoint(),
|
|
53
|
+
await getStandardAuthRegistry(),
|
|
54
|
+
await getStandardHandshakeRegistry(),
|
|
55
|
+
],
|
|
56
|
+
},
|
|
46
57
|
loggers: {
|
|
47
58
|
store: rootLogger.createChild('pxe:data'),
|
|
48
59
|
pxe: rootLogger.createChild('pxe:service'),
|
|
@@ -53,23 +64,25 @@ export class BrowserEmbeddedWallet extends EmbeddedWallet {
|
|
|
53
64
|
|
|
54
65
|
const pxe = await createPXE(aztecNode, pxeConfig, pxeOptions);
|
|
55
66
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
(options.ephemeral
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const walletDB = WalletDB
|
|
67
|
+
let walletDBStore = options.walletDb?.store;
|
|
68
|
+
if (!walletDBStore) {
|
|
69
|
+
if (options.ephemeral) {
|
|
70
|
+
walletDBStore = await openTmpStore(true);
|
|
71
|
+
} else {
|
|
72
|
+
const { l1ChainId, l1ContractAddresses } = await aztecNode.getNodeInfo();
|
|
73
|
+
walletDBStore = await openBrowserStore(
|
|
74
|
+
'wallet_data',
|
|
75
|
+
WALLET_DATA_SCHEMA_VERSION,
|
|
76
|
+
{ l1ChainId, rollupAddress: l1ContractAddresses.rollupAddress },
|
|
77
|
+
rootLogger.createChild('wallet:data'),
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const walletDB = new WalletDB(walletDBStore, rootLogger.createChild('wallet:db').info);
|
|
71
82
|
|
|
72
|
-
|
|
83
|
+
const wallet = new this(pxe, aztecNode, walletDB, new LazyAccountContractsProvider(), rootLogger) as T;
|
|
84
|
+
await wallet.initStubClasses();
|
|
85
|
+
return wallet;
|
|
73
86
|
}
|
|
74
87
|
}
|
|
75
88
|
|