@aztec/test-wallet 0.0.1-commit.023c3e5

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.
@@ -0,0 +1,91 @@
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, SignerlessAccount } from '@aztec/aztec.js/account';
5
+ import type { AztecAddress } from '@aztec/aztec.js/addresses';
6
+ import { getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts';
7
+ import { Fq, Fr } from '@aztec/aztec.js/fields';
8
+ import type { AztecNode } from '@aztec/aztec.js/node';
9
+ import { AccountManager } from '@aztec/aztec.js/wallet';
10
+ import { type PXEConfig, type PXECreationOptions, createPXE, getPXEConfig } from '@aztec/pxe/client/bundle';
11
+ import { deriveSigningKey } from '@aztec/stdlib/keys';
12
+
13
+ import { BaseTestWallet } from './test_wallet.js';
14
+
15
+ /**
16
+ * A TestWallet implementation that loads the account contract artifacts eagerly
17
+ * Note that the only difference from `lazy` and `server` test wallets is that it uses the `createPXE` function
18
+ * from the `pxe/client/bundle` package.
19
+ */
20
+ export class TestWallet extends BaseTestWallet {
21
+ static async create(
22
+ node: AztecNode,
23
+ overridePXEConfig?: Partial<PXEConfig>,
24
+ options: PXECreationOptions = { loggers: {} },
25
+ ): Promise<TestWallet> {
26
+ const pxeConfig = Object.assign(getPXEConfig(), {
27
+ proverEnabled: overridePXEConfig?.proverEnabled ?? false,
28
+ ...overridePXEConfig,
29
+ });
30
+ const pxe = await createPXE(node, pxeConfig, options);
31
+ return new TestWallet(pxe, node);
32
+ }
33
+
34
+ createSchnorrAccount(secret: Fr, salt: Fr, signingKey?: Fq): Promise<AccountManager> {
35
+ signingKey = signingKey ?? deriveSigningKey(secret);
36
+ const accountData = {
37
+ secret,
38
+ salt,
39
+ contract: new SchnorrAccountContract(signingKey),
40
+ };
41
+ return this.createAccount(accountData);
42
+ }
43
+
44
+ createECDSARAccount(secret: Fr, salt: Fr, signingKey: Buffer): Promise<AccountManager> {
45
+ const accountData = {
46
+ secret,
47
+ salt,
48
+ contract: new EcdsaRAccountContract(signingKey),
49
+ };
50
+ return this.createAccount(accountData);
51
+ }
52
+
53
+ createECDSAKAccount(secret: Fr, salt: Fr, signingKey: Buffer): Promise<AccountManager> {
54
+ const accountData = {
55
+ secret,
56
+ salt,
57
+ contract: new EcdsaKAccountContract(signingKey),
58
+ };
59
+ return this.createAccount(accountData);
60
+ }
61
+
62
+ /**
63
+ * Creates a stub account that impersonates the given address, allowing kernelless simulations
64
+ * to bypass the account's authorization mechanisms via contract overrides.
65
+ * @param address - The address of the account to impersonate
66
+ * @returns The stub account, contract instance, and artifact for simulation
67
+ */
68
+ async getFakeAccountDataFor(address: AztecAddress) {
69
+ const originalAccount = await this.getAccountFromAddress(address);
70
+ // Account contracts can only be overridden if they have an associated address
71
+ // Overwriting SignerlessAccount is not supported, and does not really make sense
72
+ // since it has no authorization mechanism.
73
+ if (originalAccount instanceof SignerlessAccount) {
74
+ throw new Error(`Cannot create fake account data for SignerlessAccount at address: ${address}`);
75
+ }
76
+ const originalAddress = (originalAccount as Account).getCompleteAddress();
77
+ const contractInstance = await this.pxe.getContractInstance(originalAddress.address);
78
+ if (!contractInstance) {
79
+ throw new Error(`No contract instance found for address: ${originalAddress.address}`);
80
+ }
81
+ const stubAccount = createStubAccount(originalAddress);
82
+ const instance = await getContractInstanceFromInstantiationParams(StubAccountContractArtifact, {
83
+ salt: Fr.random(),
84
+ });
85
+ return {
86
+ account: stubAccount,
87
+ instance,
88
+ artifact: StubAccountContractArtifact,
89
+ };
90
+ }
91
+ }
@@ -0,0 +1,92 @@
1
+ import { EcdsaKAccountContract, EcdsaRAccountContract } from '@aztec/accounts/ecdsa/lazy';
2
+ import { SchnorrAccountContract } from '@aztec/accounts/schnorr/lazy';
3
+ import { createStubAccount, getStubAccountContractArtifact } from '@aztec/accounts/stub/lazy';
4
+ import { type Account, SignerlessAccount } from '@aztec/aztec.js/account';
5
+ import type { AztecAddress } from '@aztec/aztec.js/addresses';
6
+ import { getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts';
7
+ import { Fq, Fr } from '@aztec/aztec.js/fields';
8
+ import type { AztecNode } from '@aztec/aztec.js/node';
9
+ import { AccountManager } from '@aztec/aztec.js/wallet';
10
+ import { type PXEConfig, type PXECreationOptions, createPXE, getPXEConfig } from '@aztec/pxe/client/lazy';
11
+ import { deriveSigningKey } from '@aztec/stdlib/keys';
12
+
13
+ import { BaseTestWallet } from './test_wallet.js';
14
+
15
+ /**
16
+ * A TestWallet implementation that loads the account contract artifacts lazily
17
+ * Note that the only difference from `server` and `bundle` test wallets is that it uses the `createPXE` function
18
+ * from the `pxe/client/lazy` package.
19
+ */
20
+ export class TestWallet extends BaseTestWallet {
21
+ static async create(
22
+ node: AztecNode,
23
+ overridePXEConfig?: Partial<PXEConfig>,
24
+ options: PXECreationOptions = { loggers: {} },
25
+ ): Promise<TestWallet> {
26
+ const pxeConfig = Object.assign(getPXEConfig(), {
27
+ proverEnabled: overridePXEConfig?.proverEnabled ?? false,
28
+ ...overridePXEConfig,
29
+ });
30
+ const pxe = await createPXE(node, pxeConfig, options);
31
+ return new TestWallet(pxe, node);
32
+ }
33
+
34
+ createSchnorrAccount(secret: Fr, salt: Fr, signingKey?: Fq): Promise<AccountManager> {
35
+ signingKey = signingKey ?? deriveSigningKey(secret);
36
+ const accountData = {
37
+ secret,
38
+ salt,
39
+ contract: new SchnorrAccountContract(signingKey),
40
+ };
41
+ return this.createAccount(accountData);
42
+ }
43
+
44
+ createECDSARAccount(secret: Fr, salt: Fr, signingKey: Buffer): Promise<AccountManager> {
45
+ const accountData = {
46
+ secret,
47
+ salt,
48
+ contract: new EcdsaRAccountContract(signingKey),
49
+ };
50
+ return this.createAccount(accountData);
51
+ }
52
+
53
+ createECDSAKAccount(secret: Fr, salt: Fr, signingKey: Buffer): Promise<AccountManager> {
54
+ const accountData = {
55
+ secret,
56
+ salt,
57
+ contract: new EcdsaKAccountContract(signingKey),
58
+ };
59
+ return this.createAccount(accountData);
60
+ }
61
+
62
+ /**
63
+ * Creates a stub account that impersonates the given address, allowing kernelless simulations
64
+ * to bypass the account's authorization mechanisms via contract overrides.
65
+ * @param address - The address of the account to impersonate
66
+ * @returns The stub account, contract instance, and artifact for simulation
67
+ */
68
+ async getFakeAccountDataFor(address: AztecAddress) {
69
+ const originalAccount = await this.getAccountFromAddress(address);
70
+ // Account contracts can only be overridden if they have an associated address
71
+ // Overwriting SignerlessAccount is not supported, and does not really make sense
72
+ // since it has no authorization mechanism.
73
+ if (originalAccount instanceof SignerlessAccount) {
74
+ throw new Error(`Cannot create fake account data for SignerlessAccount at address: ${address}`);
75
+ }
76
+ const originalAddress = (originalAccount as Account).getCompleteAddress();
77
+ const contractInstance = await this.pxe.getContractInstance(originalAddress.address);
78
+ if (!contractInstance) {
79
+ throw new Error(`No contract instance found for address: ${originalAddress.address}`);
80
+ }
81
+ const stubAccount = createStubAccount(originalAddress);
82
+ const StubAccountContractArtifact = await getStubAccountContractArtifact();
83
+ const instance = await getContractInstanceFromInstantiationParams(StubAccountContractArtifact, {
84
+ salt: Fr.random(),
85
+ });
86
+ return {
87
+ account: stubAccount,
88
+ instance,
89
+ artifact: StubAccountContractArtifact,
90
+ };
91
+ }
92
+ }
@@ -0,0 +1,91 @@
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, SignerlessAccount } from '@aztec/aztec.js/account';
5
+ import type { AztecAddress } from '@aztec/aztec.js/addresses';
6
+ import { getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts';
7
+ import { Fq, Fr } from '@aztec/aztec.js/fields';
8
+ import type { AztecNode } from '@aztec/aztec.js/node';
9
+ import { AccountManager } from '@aztec/aztec.js/wallet';
10
+ import { type PXEConfig, type PXECreationOptions, createPXE, getPXEConfig } from '@aztec/pxe/server';
11
+ import { deriveSigningKey } from '@aztec/stdlib/keys';
12
+
13
+ import { BaseTestWallet } from './test_wallet.js';
14
+
15
+ /**
16
+ * A TestWallet implementation to be used in server settings (e.g. e2e tests).
17
+ * Note that the only difference from `lazy` and `bundle` test wallets is that it uses the `createPXE` function
18
+ * from the `pxe/server` package.
19
+ */
20
+ export class TestWallet extends BaseTestWallet {
21
+ static async create(
22
+ node: AztecNode,
23
+ overridePXEConfig?: Partial<PXEConfig>,
24
+ options: PXECreationOptions = { loggers: {} },
25
+ ): Promise<TestWallet> {
26
+ const pxeConfig = Object.assign(getPXEConfig(), {
27
+ proverEnabled: overridePXEConfig?.proverEnabled ?? false,
28
+ ...overridePXEConfig,
29
+ });
30
+ const pxe = await createPXE(node, pxeConfig, options);
31
+ return new TestWallet(pxe, node);
32
+ }
33
+
34
+ createSchnorrAccount(secret: Fr, salt: Fr, signingKey?: Fq): Promise<AccountManager> {
35
+ signingKey = signingKey ?? deriveSigningKey(secret);
36
+ const accountData = {
37
+ secret,
38
+ salt,
39
+ contract: new SchnorrAccountContract(signingKey),
40
+ };
41
+ return this.createAccount(accountData);
42
+ }
43
+
44
+ createECDSARAccount(secret: Fr, salt: Fr, signingKey: Buffer): Promise<AccountManager> {
45
+ const accountData = {
46
+ secret,
47
+ salt,
48
+ contract: new EcdsaRAccountContract(signingKey),
49
+ };
50
+ return this.createAccount(accountData);
51
+ }
52
+
53
+ createECDSAKAccount(secret: Fr, salt: Fr, signingKey: Buffer): Promise<AccountManager> {
54
+ const accountData = {
55
+ secret,
56
+ salt,
57
+ contract: new EcdsaKAccountContract(signingKey),
58
+ };
59
+ return this.createAccount(accountData);
60
+ }
61
+
62
+ /**
63
+ * Creates a stub account that impersonates the given address, allowing kernelless simulations
64
+ * to bypass the account's authorization mechanisms via contract overrides.
65
+ * @param address - The address of the account to impersonate
66
+ * @returns The stub account, contract instance, and artifact for simulation
67
+ */
68
+ async getFakeAccountDataFor(address: AztecAddress) {
69
+ const originalAccount = await this.getAccountFromAddress(address);
70
+ // Account contracts can only be overridden if they have an associated address
71
+ // Overwriting SignerlessAccount is not supported, and does not really make sense
72
+ // since it has no authorization mechanism.
73
+ if (originalAccount instanceof SignerlessAccount) {
74
+ throw new Error(`Cannot create fake account data for SignerlessAccount at address: ${address}`);
75
+ }
76
+ const originalAddress = (originalAccount as Account).getCompleteAddress();
77
+ const contractInstance = await this.pxe.getContractInstance(originalAddress.address);
78
+ if (!contractInstance) {
79
+ throw new Error(`No contract instance found for address: ${originalAddress.address}`);
80
+ }
81
+ const stubAccount = createStubAccount(originalAddress);
82
+ const instance = await getContractInstanceFromInstantiationParams(StubAccountContractArtifact, {
83
+ salt: Fr.random(),
84
+ });
85
+ return {
86
+ account: stubAccount,
87
+ instance,
88
+ artifact: StubAccountContractArtifact,
89
+ };
90
+ }
91
+ }
@@ -0,0 +1,306 @@
1
+ import { SchnorrAccountContract } from '@aztec/accounts/schnorr';
2
+ import type { ContractArtifact } from '@aztec/aztec.js/abi';
3
+ import { type Account, type AccountContract, SignerlessAccount } from '@aztec/aztec.js/account';
4
+ import {
5
+ type CallIntent,
6
+ type ContractFunctionInteractionCallIntent,
7
+ type IntentInnerHash,
8
+ SetPublicAuthwitContractInteraction,
9
+ computeInnerAuthWitHashFromAction,
10
+ isContractFunctionInteractionCallIntent,
11
+ lookupValidity,
12
+ } from '@aztec/aztec.js/authorization';
13
+ import { AccountManager, type SendOptions, type SimulateOptions } from '@aztec/aztec.js/wallet';
14
+ import type { DefaultAccountEntrypointOptions } from '@aztec/entrypoints/account';
15
+ import { Fq, Fr } from '@aztec/foundation/curves/bn254';
16
+ import { GrumpkinScalar } from '@aztec/foundation/curves/grumpkin';
17
+ import { AuthWitness } from '@aztec/stdlib/auth-witness';
18
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
19
+ import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
20
+ import type { NoteDao, NotesFilter } from '@aztec/stdlib/note';
21
+ import type { BlockHeader, TxHash, TxReceipt, TxSimulationResult } from '@aztec/stdlib/tx';
22
+ import { ExecutionPayload, mergeExecutionPayloads } from '@aztec/stdlib/tx';
23
+ import { BaseWallet } from '@aztec/wallet-sdk/base-wallet';
24
+
25
+ import { ProvenTx } from '../utils.js';
26
+
27
+ /**
28
+ * Data for generating an account.
29
+ */
30
+ export interface AccountData {
31
+ /**
32
+ * Secret to derive the keys for the account.
33
+ */
34
+ secret: Fr;
35
+ /**
36
+ * Contract address salt.
37
+ */
38
+ salt: Fr;
39
+ /**
40
+ * Contract that backs the account.
41
+ */
42
+ contract: AccountContract;
43
+ }
44
+
45
+ /**
46
+ * Wallet implementation that stores accounts in memory and allows allows their creation
47
+ * from the outside (which is something actual wallets shouldn't allow!)
48
+ * It is intended to be used in e2e tests.
49
+ */
50
+ export abstract class BaseTestWallet extends BaseWallet {
51
+ protected accounts: Map<string, Account> = new Map();
52
+
53
+ /**
54
+ * Toggle for running "simulated simulations" when calling simulateTx.
55
+ *
56
+ * Terminology:
57
+ * - "simulation": run private circuits normally and then run the kernel in a simulated (brillig) mode on ACVM.
58
+ * No kernel witnesses are generated, but protocol rules are checked.
59
+ * - "simulated simulation": skip running kernels in ACVM altogether and emulate their behavior in TypeScript
60
+ * (akin to generateSimulatedProvingResult). We mutate public inputs like the kernels would and can swap in
61
+ * fake/private bytecode or accounts for tests. This is much faster but is not usable in situations where we
62
+ * need kernel witnesses.
63
+ *
64
+ * When this flag is true, simulateTx constructs a request using a fake account (and accepts contract overrides
65
+ * on the input) and the PXE emulates kernel effects without generating kernel witnesses. When false, simulateTx
66
+ * defers to the standard simulation path.
67
+ */
68
+ private simulatedSimulations = false;
69
+
70
+ /** Enable the "simulated simulation" path for simulateTx. */
71
+ enableSimulatedSimulations() {
72
+ this.simulatedSimulations = true;
73
+ }
74
+
75
+ /** Disable the "simulated simulation" path for simulateTx. */
76
+ disableSimulatedSimulations() {
77
+ this.simulatedSimulations = false;
78
+ }
79
+
80
+ setMinFeePadding(value?: number) {
81
+ this.minFeePadding = value ?? 0.5;
82
+ }
83
+
84
+ protected getAccountFromAddress(address: AztecAddress): Promise<Account> {
85
+ let account: Account | undefined;
86
+ if (address.equals(AztecAddress.ZERO)) {
87
+ account = new SignerlessAccount();
88
+ } else {
89
+ account = this.accounts.get(address?.toString() ?? '');
90
+ }
91
+
92
+ if (!account) {
93
+ throw new Error(`Account not found in wallet for address: ${address}`);
94
+ }
95
+
96
+ return Promise.resolve(account);
97
+ }
98
+
99
+ getAccounts() {
100
+ return Promise.resolve(Array.from(this.accounts.values()).map(acc => ({ alias: '', item: acc.getAddress() })));
101
+ }
102
+
103
+ /**
104
+ * Creates a new account with the provided account data or generates random values and uses SchnorrAccountContract
105
+ * if not provided.
106
+ *
107
+ * @param accountData - Optional account configuration containing secret, salt and account contract.
108
+ * @returns A new AccountManager instance for the created account
109
+ */
110
+ async createAccount(accountData?: AccountData): Promise<AccountManager> {
111
+ // Generate random values if not provided
112
+ const secret = accountData?.secret ?? Fr.random();
113
+ const salt = accountData?.salt ?? Fr.random();
114
+ // Use SchnorrAccountContract if not provided
115
+ const contract = accountData?.contract ?? new SchnorrAccountContract(GrumpkinScalar.random());
116
+
117
+ const accountManager = await AccountManager.create(this, secret, contract, salt);
118
+
119
+ const instance = accountManager.getInstance();
120
+ const artifact = await contract.getContractArtifact();
121
+
122
+ await this.registerContract(instance, artifact, secret);
123
+
124
+ this.accounts.set(accountManager.address.toString(), await accountManager.getAccount());
125
+
126
+ return accountManager;
127
+ }
128
+
129
+ abstract createSchnorrAccount(secret: Fr, salt: Fr, signingKey?: Fq): Promise<AccountManager>;
130
+ abstract createECDSARAccount(secret: Fr, salt: Fr, signingKey: Buffer): Promise<AccountManager>;
131
+ abstract createECDSAKAccount(secret: Fr, salt: Fr, signingKey: Buffer): Promise<AccountManager>;
132
+
133
+ /**
134
+ * Lookup the validity of an authwit in private and public contexts.
135
+ *
136
+ * Uses the chain id and version of the wallet.
137
+ *
138
+ * @param wallet - The wallet use to simulate and read the public data
139
+ * @param onBehalfOf - The address of the "approver"
140
+ * @param intent - The consumer and inner hash or the caller and action to lookup
141
+ * @param witness - The computed authentication witness to check
142
+ * @returns - A struct containing the validity of the authwit in private and public contexts.
143
+ */
144
+ lookupValidity(
145
+ onBehalfOf: AztecAddress,
146
+ intent: IntentInnerHash | CallIntent | ContractFunctionInteractionCallIntent,
147
+ witness: AuthWitness,
148
+ ): Promise<{
149
+ /** boolean flag indicating if the authwit is valid in private context */
150
+ isValidInPrivate: boolean;
151
+ /** boolean flag indicating if the authwit is valid in public context */
152
+ isValidInPublic: boolean;
153
+ }> {
154
+ return lookupValidity(this, onBehalfOf, intent, witness);
155
+ }
156
+
157
+ /**
158
+ * Returns an interaction that can be used to set the authorization status
159
+ * of an intent
160
+ * @param from - The address authorizing/revoking the action
161
+ * @param messageHashOrIntent - The action to authorize/revoke
162
+ * @param authorized - Whether the action can be performed or not
163
+ */
164
+ public setPublicAuthWit(
165
+ from: AztecAddress,
166
+ messageHashOrIntent: Fr | IntentInnerHash | CallIntent | ContractFunctionInteractionCallIntent,
167
+ authorized: boolean,
168
+ ): Promise<SetPublicAuthwitContractInteraction> {
169
+ return SetPublicAuthwitContractInteraction.create(this, from, messageHashOrIntent, authorized);
170
+ }
171
+
172
+ /**
173
+ * Creates and returns an authwit according the the rules
174
+ * of the provided account. This authwit can be verified
175
+ * by the account contract
176
+ * @param from - The address authorizing the action
177
+ * @param intent - The action to authorize
178
+ */
179
+ public override async createAuthWit(
180
+ from: AztecAddress,
181
+ intent: IntentInnerHash | CallIntent | ContractFunctionInteractionCallIntent,
182
+ ): Promise<AuthWitness> {
183
+ const account = await this.getAccountFromAddress(from);
184
+ const chainInfo = await this.getChainInfo();
185
+ let intentInnerHash: IntentInnerHash;
186
+ if ('caller' in intent) {
187
+ const call = isContractFunctionInteractionCallIntent(intent)
188
+ ? await intent.action.getFunctionCall()
189
+ : intent.call;
190
+ const innerHash = await computeInnerAuthWitHashFromAction(intent.caller, call);
191
+ intentInnerHash = { innerHash, consumer: call.to };
192
+ } else {
193
+ intentInnerHash = intent;
194
+ }
195
+ return account.createAuthWit(intentInnerHash, chainInfo);
196
+ }
197
+
198
+ /**
199
+ * Creates a stub account that impersonates the given address, allowing kernelless simulations
200
+ * to bypass the account's authorization mechanisms via contract overrides.
201
+ * @param address - The address of the account to impersonate
202
+ * @returns The stub account, contract instance, and artifact for simulation
203
+ */
204
+ abstract getFakeAccountDataFor(
205
+ address: AztecAddress, // eslint-disable-next-line jsdoc/require-jsdoc
206
+ ): Promise<{ account: Account; instance: ContractInstanceWithAddress; artifact: ContractArtifact }>;
207
+
208
+ override async simulateTx(executionPayload: ExecutionPayload, opts: SimulateOptions): Promise<TxSimulationResult> {
209
+ if (!this.simulatedSimulations) {
210
+ return super.simulateTx(executionPayload, opts);
211
+ } else {
212
+ const feeOptions = opts.fee?.estimateGas
213
+ ? await this.completeFeeOptionsForEstimation(opts.from, executionPayload.feePayer, opts.fee?.gasSettings)
214
+ : await this.completeFeeOptions(opts.from, executionPayload.feePayer, opts.fee?.gasSettings);
215
+ const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
216
+ const executionOptions: DefaultAccountEntrypointOptions = {
217
+ txNonce: Fr.random(),
218
+ cancellable: this.cancellableTransactions,
219
+ feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions,
220
+ };
221
+ const finalExecutionPayload = feeExecutionPayload
222
+ ? mergeExecutionPayloads([feeExecutionPayload, executionPayload])
223
+ : executionPayload;
224
+ const { account: fromAccount, instance, artifact } = await this.getFakeAccountDataFor(opts.from);
225
+ const chainInfo = await this.getChainInfo();
226
+ const txRequest = await fromAccount.createTxExecutionRequest(
227
+ finalExecutionPayload,
228
+ feeOptions.gasSettings,
229
+ chainInfo,
230
+ executionOptions,
231
+ );
232
+ const contractOverrides = {
233
+ [opts.from.toString()]: { instance, artifact },
234
+ };
235
+ return this.pxe.simulateTx(txRequest, true /* simulatePublic */, true, true, { contracts: contractOverrides });
236
+ }
237
+ }
238
+
239
+ /**
240
+ * A utility to prove a transaction using this wallet and return it to be sent by a different entity on their own accord
241
+ *
242
+ * Note that this should not be used in production code since a proven transaction could be sent to a malicious
243
+ * node to index and track. It also makes it very difficult for the wallet to keep track of the interaction.
244
+ * @param exec - The execution payload to prove.
245
+ * @param opts - The options to configure the interaction
246
+ * @returns - A proven tx ready to be sent to the network
247
+ */
248
+ async proveTx(exec: ExecutionPayload, opts: Omit<SendOptions, 'wait'>): Promise<ProvenTx> {
249
+ const fee = await this.completeFeeOptions(opts.from, exec.feePayer, opts.fee?.gasSettings);
250
+ const txRequest = await this.createTxExecutionRequestFromPayloadAndFee(exec, opts.from, fee);
251
+ const txProvingResult = await this.pxe.proveTx(txRequest);
252
+ return new ProvenTx(
253
+ this.aztecNode,
254
+ await txProvingResult.toTx(),
255
+ txProvingResult.getOffchainEffects(),
256
+ txProvingResult.stats,
257
+ );
258
+ }
259
+
260
+ /**
261
+ * Retrieves the transaction receipt for a given transaction hash.
262
+ * This is a passthrough to the underlying node, provided for convenience in testing.
263
+ * @param txHash - The hash of the transaction.
264
+ * @returns The transaction receipt.
265
+ */
266
+ getTxReceipt(txHash: TxHash): Promise<TxReceipt> {
267
+ return this.aztecNode.getTxReceipt(txHash);
268
+ }
269
+
270
+ /**
271
+ * A debugging utility to get notes based on the provided filter.
272
+ *
273
+ * Note that this should not be used in production code because the structure of notes is considered to be
274
+ * an implementation detail of contracts. This is only meant to be used for debugging purposes. If you need to obtain
275
+ * note-related information in production code, please implement a custom utility function on your contract and call
276
+ * that function instead (e.g. `get_balance(owner: AztecAddress) -> u128` utility function on a Token contract).
277
+ *
278
+ * @param filter - The filter to apply to the notes.
279
+ * @returns The requested notes.
280
+ */
281
+ getNotes(filter: NotesFilter): Promise<NoteDao[]> {
282
+ return this.pxe.debug.getNotes(filter);
283
+ }
284
+
285
+ /** Returns the block header up to which the wallet has synced. */
286
+ getSyncedBlockHeader(): Promise<BlockHeader> {
287
+ return this.pxe.debug.getSyncedBlockHeader();
288
+ }
289
+
290
+ /**
291
+ * Triggers a sync of the wallet with the node to update the latest block header.
292
+ * Blocks until the sync is complete.
293
+ */
294
+ sync(): Promise<void> {
295
+ return this.pxe.debug.sync();
296
+ }
297
+
298
+ /**
299
+ * Stops the internal job queue.
300
+ *
301
+ * This function is typically used when tearing down tests.
302
+ */
303
+ stop(): Promise<void> {
304
+ return this.pxe.stop();
305
+ }
306
+ }