@aztec/cli-wallet 0.0.1-commit.3fd054f6 → 0.0.1-commit.42ee6df9b

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 (39) hide show
  1. package/dest/cmds/check_tx.js +2 -1
  2. package/dest/cmds/create_account.d.ts +4 -3
  3. package/dest/cmds/create_account.d.ts.map +1 -1
  4. package/dest/cmds/create_account.js +24 -21
  5. package/dest/cmds/deploy.d.ts +4 -3
  6. package/dest/cmds/deploy.d.ts.map +1 -1
  7. package/dest/cmds/deploy.js +24 -23
  8. package/dest/cmds/deploy_account.d.ts +4 -3
  9. package/dest/cmds/deploy_account.d.ts.map +1 -1
  10. package/dest/cmds/deploy_account.js +19 -16
  11. package/dest/cmds/get_fee_juice_balance.d.ts +5 -0
  12. package/dest/cmds/get_fee_juice_balance.d.ts.map +1 -0
  13. package/dest/cmds/get_fee_juice_balance.js +27 -0
  14. package/dest/cmds/index.d.ts +1 -1
  15. package/dest/cmds/index.d.ts.map +1 -1
  16. package/dest/cmds/index.js +30 -14
  17. package/dest/cmds/send.d.ts +4 -3
  18. package/dest/cmds/send.d.ts.map +1 -1
  19. package/dest/cmds/send.js +23 -22
  20. package/dest/storage/wallet_db.d.ts +6 -1
  21. package/dest/storage/wallet_db.d.ts.map +1 -1
  22. package/dest/storage/wallet_db.js +14 -0
  23. package/dest/utils/options/fees.d.ts +2 -2
  24. package/dest/utils/options/fees.d.ts.map +1 -1
  25. package/dest/utils/options/fees.js +6 -5
  26. package/dest/utils/wallet.d.ts +2 -2
  27. package/dest/utils/wallet.d.ts.map +1 -1
  28. package/dest/utils/wallet.js +30 -32
  29. package/package.json +14 -14
  30. package/src/cmds/check_tx.ts +3 -2
  31. package/src/cmds/create_account.ts +25 -16
  32. package/src/cmds/deploy.ts +21 -15
  33. package/src/cmds/deploy_account.ts +19 -11
  34. package/src/cmds/get_fee_juice_balance.ts +37 -0
  35. package/src/cmds/index.ts +56 -3
  36. package/src/cmds/send.ts +20 -15
  37. package/src/storage/wallet_db.ts +14 -0
  38. package/src/utils/options/fees.ts +7 -5
  39. package/src/utils/wallet.ts +37 -37
@@ -1,13 +1,15 @@
1
+ import { NO_FROM } from '@aztec/aztec.js/account';
1
2
  import { AztecAddress } from '@aztec/aztec.js/addresses';
2
3
  import type { DeployOptions } from '@aztec/aztec.js/contracts';
3
4
  import { NO_WAIT } from '@aztec/aztec.js/contracts';
4
5
  import { ContractDeployer } from '@aztec/aztec.js/deployment';
5
6
  import { Fr } from '@aztec/aztec.js/fields';
6
- import type { AztecNode } from '@aztec/aztec.js/node';
7
+ import { type AztecNode, waitForTx } from '@aztec/aztec.js/node';
7
8
  import { encodeArgs, getContractArtifact, prettyPrintJSON } from '@aztec/cli/utils';
8
9
  import type { LogFn, Logger } from '@aztec/foundation/log';
9
10
  import { getAllFunctionAbis, getInitializer } from '@aztec/stdlib/abi';
10
11
  import { PublicKeys } from '@aztec/stdlib/keys';
12
+ import type { TxStatus } from '@aztec/stdlib/tx';
11
13
 
12
14
  import { DEFAULT_TX_TIMEOUT_S } from '../utils/cli_wallet_and_node_wrapper.js';
13
15
  import { CLIFeeArgs } from '../utils/options/fees.js';
@@ -29,6 +31,7 @@ export async function deploy(
29
31
  skipInitialization: boolean | undefined,
30
32
  wait: boolean,
31
33
  feeOpts: CLIFeeArgs,
34
+ waitForStatus: TxStatus,
32
35
  verbose: boolean,
33
36
  timeout: number = DEFAULT_TX_TIMEOUT_S,
34
37
  debugLogger: Logger,
@@ -59,11 +62,11 @@ export async function deploy(
59
62
  debugLogger.debug(`Encoded arguments: ${args.join(', ')}`);
60
63
  }
61
64
 
62
- const deploy = contractDeployer.deploy(...args);
65
+ const deployInteraction = contractDeployer.deploy(...args);
63
66
  const { paymentMethod, gasSettings } = await feeOpts.toUserFeeOptions(node, wallet, deployer);
64
67
  const deployOpts: DeployOptions = {
65
68
  fee: { gasSettings, paymentMethod },
66
- from: deployer ?? AztecAddress.ZERO,
69
+ from: deployer ?? NO_FROM,
67
70
  contractAddressSalt: salt,
68
71
  universalDeploy: !deployer,
69
72
  skipClassPublication,
@@ -71,7 +74,8 @@ export async function deploy(
71
74
  skipInstancePublication,
72
75
  };
73
76
 
74
- const sim = await deploy.simulate({
77
+ const localStart = performance.now();
78
+ const sim = await deployInteraction.simulate({
75
79
  ...deployOpts,
76
80
  fee: { ...deployOpts.fee, estimateGas: true },
77
81
  });
@@ -97,14 +101,18 @@ export async function deploy(
97
101
  printProfileResult(stats, log);
98
102
  }
99
103
 
100
- const { address, partialAddress } = deploy;
101
- const instance = await deploy.getInstance();
104
+ const { address, partialAddress } = deployInteraction;
105
+ const instance = await deployInteraction.getInstance();
106
+
107
+ const { txHash } = await deployInteraction.send({ ...deployOpts, wait: NO_WAIT });
108
+ const localTimeMs = performance.now() - localStart;
109
+ debugLogger.debug(`Deploy tx sent with hash ${txHash.toString()}`);
110
+ out.hash = txHash;
102
111
 
103
112
  if (wait) {
104
- const { receipt } = await deploy.send({ ...deployOpts, wait: { timeout, returnReceipt: true } });
105
- const txHash = receipt.txHash;
106
- debugLogger.debug(`Deploy tx sent with hash ${txHash.toString()}`);
107
- out.hash = txHash;
113
+ const nodeStart = performance.now();
114
+ const receipt = await waitForTx(node, txHash, { timeout, waitForStatus });
115
+ const nodeTimeMs = performance.now() - nodeStart;
108
116
 
109
117
  if (!json) {
110
118
  log(`Contract deployed at ${address?.toString()}`);
@@ -114,6 +122,8 @@ export async function deploy(
114
122
  log(`Deployment salt: ${salt.toString()}`);
115
123
  log(`Deployer: ${instance.deployer.toString()}`);
116
124
  log(`Transaction fee: ${receipt.transactionFee?.toString()}`);
125
+ log(` Local processing time: ${(localTimeMs / 1000).toFixed(1)}s`);
126
+ log(` Node inclusion time: ${(nodeTimeMs / 1000).toFixed(1)}s`);
117
127
  } else {
118
128
  out.contract = {
119
129
  address: address?.toString(),
@@ -124,10 +134,6 @@ export async function deploy(
124
134
  };
125
135
  }
126
136
  } else {
127
- const { txHash } = await deploy.send({ ...deployOpts, wait: NO_WAIT });
128
- debugLogger.debug(`Deploy tx sent with hash ${txHash.toString()}`);
129
- out.hash = txHash;
130
-
131
137
  if (!json) {
132
138
  log(`Contract deployed at ${address?.toString()}`);
133
139
  log(`Contract partial address ${(await partialAddress)?.toString()}`);
@@ -148,5 +154,5 @@ export async function deploy(
148
154
  if (json) {
149
155
  log(prettyPrintJSON(out));
150
156
  }
151
- return deploy.address;
157
+ return deployInteraction.address;
152
158
  }
@@ -1,10 +1,11 @@
1
+ import { NO_FROM } from '@aztec/aztec.js/account';
1
2
  import { AztecAddress } from '@aztec/aztec.js/addresses';
2
3
  import { NO_WAIT } from '@aztec/aztec.js/contracts';
3
- import type { AztecNode } from '@aztec/aztec.js/node';
4
+ import { type AztecNode, waitForTx } from '@aztec/aztec.js/node';
4
5
  import type { DeployAccountOptions } from '@aztec/aztec.js/wallet';
5
6
  import { prettyPrintJSON } from '@aztec/cli/cli-utils';
6
7
  import type { LogFn, Logger } from '@aztec/foundation/log';
7
- import type { TxHash, TxReceipt } from '@aztec/stdlib/tx';
8
+ import type { TxHash, TxReceipt, TxStatus } from '@aztec/stdlib/tx';
8
9
 
9
10
  import { DEFAULT_TX_TIMEOUT_S } from '../utils/cli_wallet_and_node_wrapper.js';
10
11
  import type { CLIFeeArgs } from '../utils/options/fees.js';
@@ -21,6 +22,7 @@ export async function deployAccount(
21
22
  publicDeploy: boolean,
22
23
  skipInitialization: boolean,
23
24
  feeOpts: CLIFeeArgs,
25
+ waitForStatus: TxStatus,
24
26
  json: boolean,
25
27
  verbose: boolean,
26
28
  debugLogger: Logger,
@@ -52,7 +54,7 @@ export async function deployAccount(
52
54
  const { paymentMethod, gasSettings } = await feeOpts.toUserFeeOptions(aztecNode, wallet, address);
53
55
 
54
56
  const delegatedDeployment = deployer && !account.address.equals(deployer);
55
- const from = delegatedDeployment ? deployer : AztecAddress.ZERO;
57
+ const from = delegatedDeployment ? deployer : NO_FROM;
56
58
 
57
59
  const deployAccountOpts: DeployAccountOptions = {
58
60
  skipClassPublication: !registerClass,
@@ -62,6 +64,7 @@ export async function deployAccount(
62
64
  fee: { paymentMethod, gasSettings },
63
65
  };
64
66
 
67
+ const localStart = performance.now();
65
68
  const deployMethod = await account.getDeployMethod();
66
69
  const sim = await deployMethod.simulate({
67
70
  ...deployAccountOpts,
@@ -101,19 +104,24 @@ export async function deployAccount(
101
104
  }
102
105
  : undefined,
103
106
  };
107
+
108
+ ({ txHash } = await deployMethod.send({ ...sendOpts, wait: NO_WAIT }));
109
+ const localTimeMs = performance.now() - localStart;
110
+
104
111
  if (wait) {
105
- const { receipt } = await deployMethod.send({
106
- ...sendOpts,
107
- wait: { timeout: DEFAULT_TX_TIMEOUT_S, returnReceipt: true },
108
- });
109
- txReceipt = receipt;
110
- txHash = receipt.txHash;
112
+ const nodeStart = performance.now();
113
+ txReceipt = await waitForTx(aztecNode, txHash, { timeout: DEFAULT_TX_TIMEOUT_S, waitForStatus });
114
+ const nodeTimeMs = performance.now() - nodeStart;
115
+
111
116
  out.txReceipt = {
112
117
  status: txReceipt.status,
113
118
  transactionFee: txReceipt.transactionFee,
114
119
  };
115
- } else {
116
- ({ txHash } = await deployMethod.send({ ...sendOpts, wait: NO_WAIT }));
120
+
121
+ if (!json) {
122
+ log(` Local processing time: ${(localTimeMs / 1000).toFixed(1)}s`);
123
+ log(` Node inclusion time: ${(nodeTimeMs / 1000).toFixed(1)}s`);
124
+ }
117
125
  }
118
126
  debugLogger.debug(`Account contract tx sent with hash ${txHash.toString()}`);
119
127
  out.txHash = txHash;
@@ -0,0 +1,37 @@
1
+ import type { AztecAddress } from '@aztec/aztec.js/addresses';
2
+ import type { AztecNode } from '@aztec/aztec.js/node';
3
+ import { getFeeJuiceBalance } from '@aztec/aztec.js/utils';
4
+ import { prettyPrintJSON } from '@aztec/cli/cli-utils';
5
+ import type { LogFn } from '@aztec/foundation/log';
6
+
7
+ const FEE_JUICE_DECIMALS = 18;
8
+ const FEE_JUICE_UNIT = 10n ** BigInt(FEE_JUICE_DECIMALS);
9
+
10
+ /** Formats a raw FeeJuice balance (18 decimals) for human-readable display. */
11
+ function formatFeeJuice(raw: bigint, exact: boolean): string {
12
+ const whole = raw / FEE_JUICE_UNIT;
13
+ const fractional = raw % FEE_JUICE_UNIT;
14
+ const fracStr = fractional.toString().padStart(FEE_JUICE_DECIMALS, '0');
15
+ if (exact) {
16
+ return `${whole}.${fracStr} FJ`;
17
+ }
18
+ if (fractional === 0n) {
19
+ return `${whole} FJ`;
20
+ }
21
+ return `${whole}.${fracStr.replace(/0+$/, '')} FJ`;
22
+ }
23
+
24
+ export async function getFeeJuiceBalanceCmd(
25
+ node: AztecNode,
26
+ address: AztecAddress,
27
+ json: boolean,
28
+ exact: boolean,
29
+ log: LogFn,
30
+ ) {
31
+ const balance = await getFeeJuiceBalance(address, node);
32
+ if (json) {
33
+ log(prettyPrintJSON({ address: address.toString(), balance: balance.toString() }));
34
+ } else {
35
+ log(`Fee Juice balance for ${address.toString()}: ${formatFeeJuice(balance, exact)}`);
36
+ }
37
+ }
package/src/cmds/index.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  } from '@aztec/cli/utils';
13
13
  import { randomBytes } from '@aztec/foundation/crypto/random';
14
14
  import type { LogFn, Logger } from '@aztec/foundation/log';
15
+ import { TxStatus } from '@aztec/stdlib/tx';
15
16
 
16
17
  import { type Command, Option } from 'commander';
17
18
  import inquirer from 'inquirer';
@@ -40,6 +41,17 @@ import {
40
41
  integerArgParser,
41
42
  } from '../utils/options/index.js';
42
43
 
44
+ function parseWaitForStatus(status: string): TxStatus {
45
+ switch (status) {
46
+ case 'proposed':
47
+ return TxStatus.PROPOSED;
48
+ case 'checkpointed':
49
+ return TxStatus.CHECKPOINTED;
50
+ default:
51
+ throw new Error(`Invalid wait-for-status: ${status}. Use 'proposed' or 'checkpointed'.`);
52
+ }
53
+ }
54
+
43
55
  // TODO: This function is only used in 1 place so we could just inline this
44
56
  export function injectCommands(
45
57
  program: Command,
@@ -90,6 +102,11 @@ export function injectCommands(
90
102
  )
91
103
  .addOption(createAliasOption('Alias for the account. Used for easy reference in subsequent commands.', !db))
92
104
  .addOption(createTypeOption(true))
105
+ .option(
106
+ '-s, --salt <hex string>',
107
+ 'Optional deployment salt as a hex string for generating the deployment address. Defaults to 0.',
108
+ parseFieldFromHexString,
109
+ )
93
110
  .option(
94
111
  '--register-only',
95
112
  'Just register the account on the Wallet. Do not deploy or initialize the account contract.',
@@ -98,6 +115,7 @@ export function injectCommands(
98
115
  // `options.wait` is default true. Passing `--no-wait` will set it to false.
99
116
  // https://github.com/tj/commander.js#other-option-types-negatable-boolean-and-booleanvalue
100
117
  .option('--no-wait', 'Skip waiting for the contract to be deployed. Print the hash of deployment transaction')
118
+ .option('--wait-for-status <status>', "Tx status to wait for: 'proposed' or 'checkpointed'", 'proposed')
101
119
  .addOption(createVerboseOption());
102
120
 
103
121
  addOptions(createAccountCommand, CLIFeeArgs.getOptions()).action(async (_options, command) => {
@@ -107,7 +125,9 @@ export function injectCommands(
107
125
  type,
108
126
  from: parsedFromAddress,
109
127
  secretKey,
128
+ salt,
110
129
  wait,
130
+ waitForStatus: waitForStatusStr,
111
131
  registerOnly,
112
132
  skipInitialization,
113
133
  publicDeploy,
@@ -137,6 +157,7 @@ export function injectCommands(
137
157
  node,
138
158
  type,
139
159
  secretKey,
160
+ salt,
140
161
  publicKey,
141
162
  alias,
142
163
  parsedFromAddress,
@@ -146,6 +167,7 @@ export function injectCommands(
146
167
  registerClass,
147
168
  wait,
148
169
  CLIFeeArgs.parse(options, log, db),
170
+ parseWaitForStatus(waitForStatusStr),
149
171
  json,
150
172
  verbose,
151
173
  debugLogger,
@@ -180,12 +202,22 @@ export function injectCommands(
180
202
  '--skip-initialization',
181
203
  'Skip initializing the account contract. Useful for publicly deploying an existing account.',
182
204
  )
205
+ .option('--wait-for-status <status>', "Tx status to wait for: 'proposed' or 'checkpointed'", 'proposed')
183
206
  .addOption(createVerboseOption());
184
207
 
185
208
  addOptions(deployAccountCommand, CLIFeeArgs.getOptions()).action(async (parsedAccount, _options, command) => {
186
209
  const { deployAccount } = await import('./deploy_account.js');
187
210
  const options = command.optsWithGlobals();
188
- const { wait, from: parsedFromAddress, json, registerClass, skipInitialization, publicDeploy, verbose } = options;
211
+ const {
212
+ wait,
213
+ waitForStatus: waitForStatusStr,
214
+ from: parsedFromAddress,
215
+ json,
216
+ registerClass,
217
+ skipInitialization,
218
+ publicDeploy,
219
+ verbose,
220
+ } = options;
189
221
 
190
222
  const { wallet, node } = walletAndNodeWrapper;
191
223
 
@@ -199,6 +231,7 @@ export function injectCommands(
199
231
  publicDeploy,
200
232
  skipInitialization,
201
233
  CLIFeeArgs.parse(options, log, db),
234
+ parseWaitForStatus(waitForStatusStr),
202
235
  json,
203
236
  verbose,
204
237
  debugLogger,
@@ -219,7 +252,7 @@ export function injectCommands(
219
252
  )
220
253
  .option(
221
254
  '-s, --salt <hex string>',
222
- 'Optional deployment salt as a hex string for generating the deployment address.',
255
+ 'Optional deployment salt as a hex string for generating the deployment address. Defaults to random.',
223
256
  parseFieldFromHexString,
224
257
  )
225
258
  .option('--universal', 'Do not mix the sender address into the deployment.')
@@ -238,6 +271,7 @@ export function injectCommands(
238
271
  'The amount of time in seconds to wait for the deployment to post to L2',
239
272
  ).conflicts('wait'),
240
273
  )
274
+ .option('--wait-for-status <status>', "Tx status to wait for: 'proposed' or 'checkpointed'", 'proposed')
241
275
  .addOption(createVerboseOption());
242
276
 
243
277
  addOptions(deployCommand, CLIFeeArgs.getOptions()).action(async (artifactPathPromise, _options, command) => {
@@ -249,6 +283,7 @@ export function injectCommands(
249
283
  args,
250
284
  salt,
251
285
  wait,
286
+ waitForStatus: waitForStatusStr,
252
287
  classRegistration,
253
288
  init,
254
289
  publicDeployment,
@@ -279,8 +314,9 @@ export function injectCommands(
279
314
  typeof init === 'string' ? false : init,
280
315
  wait,
281
316
  CLIFeeArgs.parse(options, log, db),
282
- timeout,
317
+ parseWaitForStatus(waitForStatusStr),
283
318
  verbose,
319
+ timeout,
284
320
  debugLogger,
285
321
  log,
286
322
  );
@@ -308,6 +344,7 @@ export function injectCommands(
308
344
  )
309
345
  .addOption(createAccountOption('Alias or address of the account to send the transaction from', !db, db))
310
346
  .option('--no-wait', 'Print transaction hash without waiting for it to be mined')
347
+ .option('--wait-for-status <status>', "Tx status to wait for: 'proposed' or 'checkpointed'", 'proposed')
311
348
  .addOption(createVerboseOption());
312
349
 
313
350
  addOptions(sendCommand, CLIFeeArgs.getOptions()).action(async (functionName, _options, command) => {
@@ -319,6 +356,7 @@ export function injectCommands(
319
356
  contractAddress,
320
357
  from: parsedFromAddress,
321
358
  wait,
359
+ waitForStatus: waitForStatusStr,
322
360
  alias,
323
361
  authWitness: authWitnessArray,
324
362
  verbose,
@@ -342,6 +380,7 @@ export function injectCommands(
342
380
  alias,
343
381
  CLIFeeArgs.parse(options, log, db),
344
382
  authWitnesses,
383
+ parseWaitForStatus(waitForStatusStr),
345
384
  verbose,
346
385
  log,
347
386
  );
@@ -492,6 +531,20 @@ export function injectCommands(
492
531
  }
493
532
  });
494
533
 
534
+ program
535
+ .command('get-fee-juice-balance')
536
+ .description('Checks the Fee Juice balance for a given address.')
537
+ .argument('<address>', 'Aztec address or alias to check balance for', address =>
538
+ aliasedAddressParser('accounts', address, db),
539
+ )
540
+ .option('--json', 'Emit output as json')
541
+ .option('--exact', 'Show exact balance with all 18 decimal places')
542
+ .action(async (address, options) => {
543
+ const { getFeeJuiceBalanceCmd } = await import('./get_fee_juice_balance.js');
544
+ const { json, exact } = options;
545
+ await getFeeJuiceBalanceCmd(walletAndNodeWrapper.node, address, json, exact, log);
546
+ });
547
+
495
548
  program
496
549
  .command('create-authwit')
497
550
  .description(
package/src/cmds/send.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import type { AztecAddress } from '@aztec/aztec.js/addresses';
2
2
  import { AuthWitness } from '@aztec/aztec.js/authorization';
3
3
  import { Contract, NO_WAIT, type SendInteractionOptions } from '@aztec/aztec.js/contracts';
4
- import type { AztecNode } from '@aztec/aztec.js/node';
4
+ import { type AztecNode, waitForTx } from '@aztec/aztec.js/node';
5
5
  import { prepTx } from '@aztec/cli/utils';
6
6
  import type { LogFn } from '@aztec/foundation/log';
7
+ import { TxStatus } from '@aztec/stdlib/tx';
7
8
 
8
9
  import { DEFAULT_TX_TIMEOUT_S } from '../utils/cli_wallet_and_node_wrapper.js';
9
10
  import { CLIFeeArgs } from '../utils/options/fees.js';
@@ -22,6 +23,7 @@ export async function send(
22
23
  cancellable: boolean,
23
24
  feeOpts: CLIFeeArgs,
24
25
  authWitnesses: AuthWitness[],
26
+ waitForStatus: TxStatus,
25
27
  verbose: boolean,
26
28
  log: LogFn,
27
29
  ) {
@@ -37,6 +39,7 @@ export async function send(
37
39
  authWitnesses,
38
40
  };
39
41
 
42
+ const localStart = performance.now();
40
43
  const sim = await call.simulate({
41
44
  ...sendOptions,
42
45
  fee: { ...sendOptions.fee, estimateGas: true },
@@ -53,21 +56,29 @@ export async function send(
53
56
  printProfileResult(stats!, log);
54
57
  }
55
58
 
59
+ const { txHash } = await call.send({
60
+ ...sendOptions,
61
+ fee: { ...sendOptions.fee, gasSettings: estimatedGas },
62
+ wait: NO_WAIT,
63
+ });
64
+ const localTimeMs = performance.now() - localStart;
65
+
66
+ log(`\nTransaction hash: ${txHash.toString()}`);
67
+
56
68
  if (wait) {
57
69
  try {
58
- const { receipt } = await call.send({
59
- ...sendOptions,
60
- fee: { ...sendOptions.fee, gasSettings: estimatedGas },
61
- wait: { timeout: DEFAULT_TX_TIMEOUT_S },
62
- });
70
+ const nodeStart = performance.now();
71
+ const receipt = await waitForTx(node, txHash, { timeout: DEFAULT_TX_TIMEOUT_S, waitForStatus });
72
+ const nodeTimeMs = performance.now() - nodeStart;
63
73
 
64
- const txHash = receipt.txHash;
65
- log(`\nTransaction hash: ${txHash.toString()}`);
66
- log('Transaction has been mined');
74
+ const statusLabel = waitForStatus === TxStatus.PROPOSED ? 'proposed' : 'checkpointed';
75
+ log(`Transaction has been ${statusLabel}`);
67
76
  log(` Tx fee: ${receipt.transactionFee}`);
68
77
  log(` Status: ${receipt.status}`);
69
78
  log(` Block number: ${receipt.blockNumber}`);
70
79
  log(` Block hash: ${receipt.blockHash?.toString()}`);
80
+ log(` Local processing time: ${(localTimeMs / 1000).toFixed(1)}s`);
81
+ log(` Node inclusion time: ${(nodeTimeMs / 1000).toFixed(1)}s`);
71
82
 
72
83
  return {
73
84
  txHash,
@@ -77,12 +88,6 @@ export async function send(
77
88
  throw err;
78
89
  }
79
90
  } else {
80
- const { txHash } = await call.send({
81
- ...sendOptions,
82
- fee: { ...sendOptions.fee, gasSettings: estimatedGas },
83
- wait: NO_WAIT,
84
- });
85
- log(`\nTransaction hash: ${txHash.toString()}`);
86
91
  log('Transaction pending. Check status with check-tx');
87
92
  return {
88
93
  txHash,
@@ -70,6 +70,20 @@ export class WalletDB {
70
70
  return { amount: BigInt(amountStr), secret: secretStr, leafIndex: BigInt(leafIndexStr) };
71
71
  }
72
72
 
73
+ async peekBridgedFeeJuice(recipient: AztecAddress, log: LogFn) {
74
+ const stackPointer =
75
+ (await this.#bridgedFeeJuice.getAsync(`${recipient.toString()}:stackPointer`))?.readInt8() || 0;
76
+ const result = await this.#bridgedFeeJuice.getAsync(`${recipient.toString()}:${stackPointer}`);
77
+ if (!result) {
78
+ throw new Error(
79
+ `No stored fee juice available for recipient ${recipient.toString()}. Please provide claim amount and secret. Stack pointer ${stackPointer}`,
80
+ );
81
+ }
82
+ const [amountStr, secretStr, leafIndexStr] = result.toString().split(':');
83
+ log(`Peeked ${amountStr} fee juice for recipient ${recipient.toString()}. Stack pointer ${stackPointer}`);
84
+ return { amount: BigInt(amountStr), secret: secretStr, leafIndex: BigInt(leafIndexStr) };
85
+ }
86
+
73
87
  async storeAccount(
74
88
  address: AztecAddress,
75
89
  {
@@ -115,6 +115,7 @@ export function parsePaymentMethod(
115
115
  payment: string,
116
116
  log: LogFn,
117
117
  db?: WalletDB,
118
+ estimateOnly?: boolean,
118
119
  ): (wallet: Wallet, from: AztecAddress, gasSettings: GasSettings) => Promise<FeePaymentMethod | undefined> {
119
120
  const parsed = payment.split(',').reduce(
120
121
  (acc, item) => {
@@ -149,7 +150,7 @@ export function parsePaymentMethod(
149
150
  amount: claimAmount,
150
151
  secret: claimSecret,
151
152
  leafIndex: messageLeafIndex,
152
- } = await db.popBridgedFeeJuice(from, log));
153
+ } = estimateOnly ? await db.peekBridgedFeeJuice(from, log) : await db.popBridgedFeeJuice(from, log));
153
154
  } else {
154
155
  ({ claimAmount, claimSecret, messageLeafIndex } = parsed);
155
156
  }
@@ -157,10 +158,10 @@ export function parsePaymentMethod(
157
158
  const { FeeJuicePaymentMethodWithClaim } = await import('@aztec/aztec.js/fee');
158
159
  return new FeeJuicePaymentMethodWithClaim(from, {
159
160
  claimAmount: (typeof claimAmount === 'string'
160
- ? Fr.fromHexString(claimAmount)
161
+ ? Fr.fromString(claimAmount)
161
162
  : new Fr(claimAmount)
162
163
  ).toBigInt(),
163
- claimSecret: Fr.fromHexString(claimSecret),
164
+ claimSecret: typeof claimSecret === 'string' ? Fr.fromString(claimSecret) : claimSecret,
164
165
  messageLeafIndex: BigInt(messageLeafIndex),
165
166
  });
166
167
  } else {
@@ -266,9 +267,10 @@ export class CLIFeeArgs {
266
267
  }
267
268
 
268
269
  static parse(args: RawCliFeeArgs, log: LogFn, db?: WalletDB): CLIFeeArgs {
270
+ const estimateOnly = !!args.estimateGasOnly;
269
271
  return new CLIFeeArgs(
270
- !!args.estimateGasOnly,
271
- parsePaymentMethod(args.payment ?? 'method=fee_juice', log, db),
272
+ estimateOnly,
273
+ parsePaymentMethod(args.payment ?? 'method=fee_juice', log, db, estimateOnly),
272
274
  parseGasSettings(args),
273
275
  );
274
276
  }
@@ -2,7 +2,7 @@ import { EcdsaRAccountContract, EcdsaRSSHAccountContract } from '@aztec/accounts
2
2
  import { SchnorrAccountContract } from '@aztec/accounts/schnorr';
3
3
  import { StubAccountContractArtifact, createStubAccount } from '@aztec/accounts/stub';
4
4
  import { getIdentities } from '@aztec/accounts/utils';
5
- import { type Account, type AccountContract, SignerlessAccount } from '@aztec/aztec.js/account';
5
+ import { type Account, type AccountContract, NO_FROM } from '@aztec/aztec.js/account';
6
6
  import {
7
7
  type InteractionFeeOptions,
8
8
  getContractInstanceFromInstantiationParams,
@@ -11,6 +11,7 @@ import {
11
11
  import type { AztecNode } from '@aztec/aztec.js/node';
12
12
  import { AccountManager, type Aliased, type SimulateOptions } from '@aztec/aztec.js/wallet';
13
13
  import type { DefaultAccountEntrypointOptions } from '@aztec/entrypoints/account';
14
+ import { DefaultEntrypoint } from '@aztec/entrypoints/default';
14
15
  import { Fr } from '@aztec/foundation/curves/bn254';
15
16
  import type { LogFn } from '@aztec/foundation/log';
16
17
  import type { NotesFilter } from '@aztec/pxe/client/lazy';
@@ -20,7 +21,7 @@ import { createPXE, getPXEConfig } from '@aztec/pxe/server';
20
21
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
21
22
  import { deriveSigningKey } from '@aztec/stdlib/keys';
22
23
  import { NoteDao } from '@aztec/stdlib/note';
23
- import type { SimulationOverrides, TxProvingResult, TxSimulationResult } from '@aztec/stdlib/tx';
24
+ import type { SimulationOverrides, TxExecutionRequest, TxProvingResult, TxSimulationResult } from '@aztec/stdlib/tx';
24
25
  import { ExecutionPayload, mergeExecutionPayloads } from '@aztec/stdlib/tx';
25
26
  import { BaseWallet, type SimulateViaEntrypointOptions } from '@aztec/wallet-sdk/base-wallet';
26
27
 
@@ -55,7 +56,12 @@ export class CLIWallet extends BaseWallet {
55
56
 
56
57
  override async getAccounts(): Promise<Aliased<AztecAddress>[]> {
57
58
  const accounts = (await this.db?.listAliases('accounts')) ?? [];
58
- return Promise.resolve(accounts.map(({ key, value }) => ({ alias: value, item: AztecAddress.fromString(key) })));
59
+ return Promise.resolve(
60
+ accounts.map(({ key, value }) => {
61
+ const alias = key.includes(':') ? key.slice(key.indexOf(':') + 1) : key;
62
+ return { alias, item: AztecAddress.fromString(value) };
63
+ }),
64
+ );
59
65
  }
60
66
 
61
67
  private async createCancellationTxExecutionRequest(
@@ -71,7 +77,8 @@ export class CLIWallet extends BaseWallet {
71
77
  const executionOptions: DefaultAccountEntrypointOptions = {
72
78
  txNonce,
73
79
  cancellable: this.cancellableTransactions,
74
- feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions,
80
+ // If from is an address, feeOptions include the way the account contract should handle the fee payment
81
+ feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions!,
75
82
  };
76
83
  return await fromAccount.createTxExecutionRequest(
77
84
  feeExecutionPayload ?? executionPayload,
@@ -92,9 +99,7 @@ export class CLIWallet extends BaseWallet {
92
99
 
93
100
  override async getAccountFromAddress(address: AztecAddress) {
94
101
  let account: Account | undefined;
95
- if (address.equals(AztecAddress.ZERO)) {
96
- account = new SignerlessAccount();
97
- } else if (this.accountCache.has(address.toString())) {
102
+ if (this.accountCache.has(address.toString())) {
98
103
  return this.accountCache.get(address.toString())!;
99
104
  } else {
100
105
  const accountManager = await this.createOrRetrieveAccount(address);
@@ -185,13 +190,7 @@ export class CLIWallet extends BaseWallet {
185
190
  */
186
191
  private async getFakeAccountDataFor(address: AztecAddress) {
187
192
  const originalAccount = await this.getAccountFromAddress(address);
188
- // Account contracts can only be overridden if they have an associated address
189
- // Overwriting SignerlessAccount is not supported, and does not really make sense
190
- // since it has no authorization mechanism.
191
- if (originalAccount instanceof SignerlessAccount) {
192
- throw new Error(`Cannot create fake account data for SignerlessAccount at address: ${address}`);
193
- }
194
- const originalAddress = (originalAccount as Account).getCompleteAddress();
193
+ const originalAddress = originalAccount.getCompleteAddress();
195
194
  const contractInstance = await this.pxe.getContractInstance(originalAddress.address);
196
195
  if (!contractInstance) {
197
196
  throw new Error(`No contract instance found for address: ${originalAddress.address}`);
@@ -220,42 +219,43 @@ export class CLIWallet extends BaseWallet {
220
219
 
221
220
  /**
222
221
  * Uses a stub account for kernelless simulation, bypassing real account authorization.
223
- * Falls through to the standard entrypoint path for SignerlessAccount (ZERO address).
222
+ * Uses DefaultEntrypoint directly for NO_FROM transactions.
224
223
  */
225
224
  protected override async simulateViaEntrypoint(
226
225
  executionPayload: ExecutionPayload,
227
226
  opts: SimulateViaEntrypointOptions,
228
227
  ): Promise<TxSimulationResult> {
229
228
  const { from, feeOptions, scopes } = opts;
229
+ const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
230
+ const finalExecutionPayload = feeExecutionPayload
231
+ ? mergeExecutionPayloads([feeExecutionPayload, executionPayload])
232
+ : executionPayload;
233
+ const chainInfo = await this.getChainInfo();
234
+
230
235
  let overrides: SimulationOverrides | undefined;
231
- let fromAccount: Account;
232
- if (!from.equals(AztecAddress.ZERO)) {
236
+ let txRequest: TxExecutionRequest;
237
+ if (from === NO_FROM) {
238
+ const entrypoint = new DefaultEntrypoint();
239
+ txRequest = await entrypoint.createTxExecutionRequest(finalExecutionPayload, feeOptions.gasSettings, chainInfo);
240
+ } else {
233
241
  const { account, instance, artifact } = await this.getFakeAccountDataFor(from);
234
- fromAccount = account;
235
242
  overrides = {
236
243
  contracts: { [from.toString()]: { instance, artifact } },
237
244
  };
238
- } else {
239
- fromAccount = await this.getAccountFromAddress(from);
245
+ const executionOptions: DefaultAccountEntrypointOptions = {
246
+ txNonce: Fr.random(),
247
+ cancellable: this.cancellableTransactions,
248
+ // If from is an address, feeOptions include the way the account contract should handle the fee payment
249
+ feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions!,
250
+ };
251
+ txRequest = await account.createTxExecutionRequest(
252
+ finalExecutionPayload,
253
+ feeOptions.gasSettings,
254
+ chainInfo,
255
+ executionOptions,
256
+ );
240
257
  }
241
258
 
242
- const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
243
- const executionOptions: DefaultAccountEntrypointOptions = {
244
- txNonce: Fr.random(),
245
- cancellable: this.cancellableTransactions,
246
- feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions,
247
- };
248
- const finalExecutionPayload = feeExecutionPayload
249
- ? mergeExecutionPayloads([feeExecutionPayload, executionPayload])
250
- : executionPayload;
251
-
252
- const chainInfo = await this.getChainInfo();
253
- const txRequest = await fromAccount.createTxExecutionRequest(
254
- finalExecutionPayload,
255
- feeOptions.gasSettings,
256
- chainInfo,
257
- executionOptions,
258
- );
259
259
  return this.pxe.simulateTx(txRequest, {
260
260
  simulatePublic: true,
261
261
  skipFeeEnforcement: true,