@aztec/cli-wallet 0.0.1-commit.3469e52 → 0.0.1-commit.35158ae7e

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 (46) hide show
  1. package/dest/cmds/authorize_action.d.ts +2 -2
  2. package/dest/cmds/authorize_action.d.ts.map +1 -1
  3. package/dest/cmds/authorize_action.js +4 -2
  4. package/dest/cmds/check_tx.d.ts +1 -1
  5. package/dest/cmds/check_tx.d.ts.map +1 -1
  6. package/dest/cmds/check_tx.js +40 -10
  7. package/dest/cmds/create_account.d.ts +4 -3
  8. package/dest/cmds/create_account.d.ts.map +1 -1
  9. package/dest/cmds/create_account.js +42 -25
  10. package/dest/cmds/deploy.d.ts +4 -3
  11. package/dest/cmds/deploy.d.ts.map +1 -1
  12. package/dest/cmds/deploy.js +56 -29
  13. package/dest/cmds/deploy_account.d.ts +4 -3
  14. package/dest/cmds/deploy_account.d.ts.map +1 -1
  15. package/dest/cmds/deploy_account.js +37 -20
  16. package/dest/cmds/get_fee_juice_balance.d.ts +5 -0
  17. package/dest/cmds/get_fee_juice_balance.d.ts.map +1 -0
  18. package/dest/cmds/get_fee_juice_balance.js +27 -0
  19. package/dest/cmds/index.d.ts +1 -1
  20. package/dest/cmds/index.d.ts.map +1 -1
  21. package/dest/cmds/index.js +30 -14
  22. package/dest/cmds/send.d.ts +4 -3
  23. package/dest/cmds/send.d.ts.map +1 -1
  24. package/dest/cmds/send.js +32 -16
  25. package/dest/storage/wallet_db.d.ts +1 -1
  26. package/dest/storage/wallet_db.d.ts.map +1 -1
  27. package/dest/storage/wallet_db.js +46 -31
  28. package/dest/utils/options/fees.d.ts +1 -1
  29. package/dest/utils/options/fees.d.ts.map +1 -1
  30. package/dest/utils/options/fees.js +2 -0
  31. package/dest/utils/wallet.d.ts +8 -3
  32. package/dest/utils/wallet.d.ts.map +1 -1
  33. package/dest/utils/wallet.js +45 -40
  34. package/package.json +14 -14
  35. package/src/cmds/authorize_action.ts +1 -1
  36. package/src/cmds/check_tx.ts +45 -11
  37. package/src/cmds/create_account.ts +44 -24
  38. package/src/cmds/deploy.ts +55 -27
  39. package/src/cmds/deploy_account.ts +38 -19
  40. package/src/cmds/get_fee_juice_balance.ts +37 -0
  41. package/src/cmds/index.ts +57 -4
  42. package/src/cmds/send.ts +32 -12
  43. package/src/cmds/simulate.ts +1 -1
  44. package/src/storage/wallet_db.ts +49 -36
  45. package/src/utils/options/fees.ts +6 -0
  46. package/src/utils/wallet.ts +53 -56
@@ -2,9 +2,10 @@ 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 { SignerlessAccount } from '@aztec/aztec.js/account';
5
+ import { NO_FROM } from '@aztec/aztec.js/account';
6
6
  import { getContractInstanceFromInstantiationParams, getGasLimits } from '@aztec/aztec.js/contracts';
7
7
  import { AccountManager } from '@aztec/aztec.js/wallet';
8
+ import { DefaultEntrypoint } from '@aztec/entrypoints/default';
8
9
  import { Fr } from '@aztec/foundation/curves/bn254';
9
10
  import { createPXE, getPXEConfig } from '@aztec/pxe/server';
10
11
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
@@ -42,19 +43,18 @@ export class CLIWallet extends BaseWallet {
42
43
  const executionOptions = {
43
44
  txNonce,
44
45
  cancellable: this.cancellableTransactions,
46
+ // If from is an address, feeOptions include the way the account contract should handle the fee payment
45
47
  feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions
46
48
  };
47
49
  return await fromAccount.createTxExecutionRequest(feeExecutionPayload ?? executionPayload, feeOptions.gasSettings, chainInfo, executionOptions);
48
50
  }
49
51
  async proveCancellationTx(from, txNonce, increasedFee) {
50
52
  const cancellationTxRequest = await this.createCancellationTxExecutionRequest(from, txNonce, increasedFee);
51
- return await this.pxe.proveTx(cancellationTxRequest);
53
+ return await this.pxe.proveTx(cancellationTxRequest, this.scopesFrom(from));
52
54
  }
53
55
  async getAccountFromAddress(address) {
54
56
  let account;
55
- if (address.equals(AztecAddress.ZERO)) {
56
- account = new SignerlessAccount();
57
- } else if (this.accountCache.has(address.toString())) {
57
+ if (this.accountCache.has(address.toString())) {
58
58
  return this.accountCache.get(address.toString());
59
59
  } else {
60
60
  const accountManager = await this.createOrRetrieveAccount(address);
@@ -125,12 +125,6 @@ export class CLIWallet extends BaseWallet {
125
125
  * @returns The stub account, contract instance, and artifact for simulation
126
126
  */ async getFakeAccountDataFor(address) {
127
127
  const originalAccount = await this.getAccountFromAddress(address);
128
- // Account contracts can only be overridden if they have an associated address
129
- // Overwriting SignerlessAccount is not supported, and does not really make sense
130
- // since it has no authorization mechanism.
131
- if (originalAccount instanceof SignerlessAccount) {
132
- throw new Error(`Cannot create fake account data for SignerlessAccount at address: ${address}`);
133
- }
134
128
  const originalAddress = originalAccount.getCompleteAddress();
135
129
  const contractInstance = await this.pxe.getContractInstance(originalAddress.address);
136
130
  if (!contractInstance) {
@@ -147,44 +141,55 @@ export class CLIWallet extends BaseWallet {
147
141
  };
148
142
  }
149
143
  async simulateTx(executionPayload, opts) {
150
- let simulationResults;
151
- const feeOptions = opts.fee?.estimateGas ? await this.completeFeeOptionsForEstimation(opts.from, executionPayload.feePayer, opts.fee?.gasSettings) : await this.completeFeeOptions(opts.from, executionPayload.feePayer, opts.fee?.gasSettings);
144
+ const simulationResults = await super.simulateTx(executionPayload, opts);
145
+ if (opts.fee?.estimateGas) {
146
+ const feeOptions = await this.completeFeeOptions(opts.from, executionPayload.feePayer, opts.fee?.gasSettings);
147
+ const limits = getGasLimits(simulationResults, opts.fee?.estimatedGasPadding);
148
+ printGasEstimates(feeOptions, limits, this.userLog);
149
+ }
150
+ return simulationResults;
151
+ }
152
+ /**
153
+ * Uses a stub account for kernelless simulation, bypassing real account authorization.
154
+ * Uses DefaultEntrypoint directly for NO_FROM transactions.
155
+ */ async simulateViaEntrypoint(executionPayload, opts) {
156
+ const { from, feeOptions, scopes } = opts;
152
157
  const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
153
- const chainInfo = await this.getChainInfo();
154
- const executionOptions = {
155
- txNonce: Fr.random(),
156
- cancellable: this.cancellableTransactions,
157
- feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions
158
- };
159
158
  const finalExecutionPayload = feeExecutionPayload ? mergeExecutionPayloads([
160
159
  feeExecutionPayload,
161
160
  executionPayload
162
161
  ]) : executionPayload;
163
- // Kernelless simulations using the multicall entrypoints are not currently supported,
164
- // since we only override proper account contracts.
165
- // TODO: allow disabling kernels even when no overrides are necessary
166
- if (opts.from.equals(AztecAddress.ZERO)) {
167
- const fromAccount = await this.getAccountFromAddress(opts.from);
168
- const txRequest = await fromAccount.createTxExecutionRequest(finalExecutionPayload, feeOptions.gasSettings, chainInfo, executionOptions);
169
- simulationResults = await this.pxe.simulateTx(txRequest, true, opts?.skipTxValidation, opts?.skipFeeEnforcement ?? true);
162
+ const chainInfo = await this.getChainInfo();
163
+ let overrides;
164
+ let txRequest;
165
+ if (from === NO_FROM) {
166
+ const entrypoint = new DefaultEntrypoint();
167
+ txRequest = await entrypoint.createTxExecutionRequest(finalExecutionPayload, feeOptions.gasSettings, chainInfo);
170
168
  } else {
171
- const { account: fromAccount, instance, artifact } = await this.getFakeAccountDataFor(opts.from);
172
- const txRequest = await fromAccount.createTxExecutionRequest(finalExecutionPayload, feeOptions.gasSettings, chainInfo, executionOptions);
173
- const contractOverrides = {
174
- [opts.from.toString()]: {
175
- instance,
176
- artifact
169
+ const { account, instance, artifact } = await this.getFakeAccountDataFor(from);
170
+ overrides = {
171
+ contracts: {
172
+ [from.toString()]: {
173
+ instance,
174
+ artifact
175
+ }
177
176
  }
178
177
  };
179
- simulationResults = await this.pxe.simulateTx(txRequest, true, true, true, {
180
- contracts: contractOverrides
181
- });
182
- }
183
- if (opts.fee?.estimateGas) {
184
- const limits = getGasLimits(simulationResults, opts.fee?.estimatedGasPadding);
185
- printGasEstimates(feeOptions, limits, this.userLog);
178
+ const executionOptions = {
179
+ txNonce: Fr.random(),
180
+ cancellable: this.cancellableTransactions,
181
+ // If from is an address, feeOptions include the way the account contract should handle the fee payment
182
+ feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions
183
+ };
184
+ txRequest = await account.createTxExecutionRequest(finalExecutionPayload, feeOptions.gasSettings, chainInfo, executionOptions);
186
185
  }
187
- return simulationResults;
186
+ return this.pxe.simulateTx(txRequest, {
187
+ simulatePublic: true,
188
+ skipFeeEnforcement: true,
189
+ skipTxValidation: true,
190
+ overrides,
191
+ scopes
192
+ });
188
193
  }
189
194
  // Exposed because of the `aztec-wallet get-tx` command. It has been decided that it's fine to keep around because
190
195
  // this is just a CLI wallet.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/cli-wallet",
3
- "version": "0.0.1-commit.3469e52",
3
+ "version": "0.0.1-commit.35158ae7e",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/cmds/index.js",
@@ -67,19 +67,19 @@
67
67
  ]
68
68
  },
69
69
  "dependencies": {
70
- "@aztec/accounts": "0.0.1-commit.3469e52",
71
- "@aztec/aztec.js": "0.0.1-commit.3469e52",
72
- "@aztec/bb.js": "0.0.1-commit.3469e52",
73
- "@aztec/cli": "0.0.1-commit.3469e52",
74
- "@aztec/entrypoints": "0.0.1-commit.3469e52",
75
- "@aztec/ethereum": "0.0.1-commit.3469e52",
76
- "@aztec/foundation": "0.0.1-commit.3469e52",
77
- "@aztec/kv-store": "0.0.1-commit.3469e52",
78
- "@aztec/noir-contracts.js": "0.0.1-commit.3469e52",
79
- "@aztec/noir-noirc_abi": "0.0.1-commit.3469e52",
80
- "@aztec/pxe": "0.0.1-commit.3469e52",
81
- "@aztec/stdlib": "0.0.1-commit.3469e52",
82
- "@aztec/wallet-sdk": "0.0.1-commit.3469e52",
70
+ "@aztec/accounts": "0.0.1-commit.35158ae7e",
71
+ "@aztec/aztec.js": "0.0.1-commit.35158ae7e",
72
+ "@aztec/bb.js": "0.0.1-commit.35158ae7e",
73
+ "@aztec/cli": "0.0.1-commit.35158ae7e",
74
+ "@aztec/entrypoints": "0.0.1-commit.35158ae7e",
75
+ "@aztec/ethereum": "0.0.1-commit.35158ae7e",
76
+ "@aztec/foundation": "0.0.1-commit.35158ae7e",
77
+ "@aztec/kv-store": "0.0.1-commit.35158ae7e",
78
+ "@aztec/noir-contracts.js": "0.0.1-commit.35158ae7e",
79
+ "@aztec/noir-noirc_abi": "0.0.1-commit.35158ae7e",
80
+ "@aztec/pxe": "0.0.1-commit.35158ae7e",
81
+ "@aztec/stdlib": "0.0.1-commit.35158ae7e",
82
+ "@aztec/wallet-sdk": "0.0.1-commit.35158ae7e",
83
83
  "commander": "^12.1.0",
84
84
  "inquirer": "^10.1.8",
85
85
  "source-map-support": "^0.5.21",
@@ -39,7 +39,7 @@ export async function authorizeAction(
39
39
  { caller, action },
40
40
  true,
41
41
  );
42
- const witness = await setAuthwitnessInteraction.send().wait({ timeout: DEFAULT_TX_TIMEOUT_S });
42
+ const witness = await setAuthwitnessInteraction.send({ wait: { timeout: DEFAULT_TX_TIMEOUT_S } });
43
43
 
44
44
  log(`Authorized action ${functionName} on contract ${contractAddress} for caller ${caller}`);
45
45
 
@@ -5,7 +5,11 @@ import type { AztecNode } from '@aztec/aztec.js/node';
5
5
  import { ProtocolContractAddress } from '@aztec/aztec.js/protocol';
6
6
  import type { TxHash } from '@aztec/aztec.js/tx';
7
7
  import type { LogFn } from '@aztec/foundation/log';
8
- import { siloNullifier } from '@aztec/stdlib/hash';
8
+ import {
9
+ computeSiloedPrivateInitializationNullifier,
10
+ computeSiloedPublicInitializationNullifier,
11
+ siloNullifier,
12
+ } from '@aztec/stdlib/hash';
9
13
  import { NoteDao } from '@aztec/stdlib/note';
10
14
 
11
15
  import type { CLIWallet } from '../utils/wallet.js';
@@ -32,7 +36,10 @@ async function inspectTx(wallet: CLIWallet, aztecNode: AztecNode, txHash: TxHash
32
36
  const [receipt, effectsInBlock] = await Promise.all([aztecNode.getTxReceipt(txHash), aztecNode.getTxEffect(txHash)]);
33
37
  // Base tx data
34
38
  log(`Tx ${txHash.toString()}`);
35
- log(` Status: ${receipt.status} ${effectsInBlock ? `(${effectsInBlock.data.revertCode.getDescription()})` : ''}`);
39
+ log(` Status: ${receipt.status}`);
40
+ if (receipt.executionResult) {
41
+ log(` Execution result: ${receipt.executionResult}`);
42
+ }
36
43
  if (receipt.error) {
37
44
  log(` Error: ${receipt.error}`);
38
45
  }
@@ -85,7 +92,7 @@ async function inspectTx(wallet: CLIWallet, aztecNode: AztecNode, txHash: TxHash
85
92
  for (const nullifier of effects.nullifiers) {
86
93
  const deployed = deployNullifiers[nullifier.toString()];
87
94
  const note = deployed
88
- ? (await wallet.getNotes({ siloedNullifier: nullifier, contractAddress: deployed }))[0]
95
+ ? (await wallet.getNotes({ siloedNullifier: nullifier, contractAddress: deployed, scopes: 'ALL_SCOPES' }))[0]
89
96
  : undefined;
90
97
  const initialized = initNullifiers[nullifier.toString()];
91
98
  const registered = classNullifiers[nullifier.toString()];
@@ -141,22 +148,49 @@ function toFriendlyAddress(address: AztecAddress, artifactMap: ArtifactMap) {
141
148
 
142
149
  async function getKnownNullifiers(wallet: CLIWallet, artifactMap: ArtifactMap) {
143
150
  const knownContracts = await wallet.getContracts();
144
- const deployerAddress = ProtocolContractAddress.ContractInstanceRegistry;
145
- const classRegistryAddress = ProtocolContractAddress.ContractClassRegistry;
151
+
152
+ const [contractResults, classResults] = await Promise.all([
153
+ Promise.all(knownContracts.map(contract => getContractNullifiers(wallet, contract))),
154
+ Promise.all(Object.values(artifactMap).map(artifact => getClassNullifier(artifact))),
155
+ ]);
156
+
146
157
  const initNullifiers: Record<string, AztecAddress> = {};
147
158
  const deployNullifiers: Record<string, AztecAddress> = {};
148
159
  const classNullifiers: Record<string, string> = {};
149
- for (const contract of knownContracts) {
150
- initNullifiers[(await siloNullifier(contract, contract.toField())).toString()] = contract;
151
- deployNullifiers[(await siloNullifier(deployerAddress, contract.toField())).toString()] = contract;
160
+
161
+ for (const { contract, deployNullifier, privateInitNullifier, publicInitNullifier } of contractResults) {
162
+ deployNullifiers[deployNullifier.toString()] = contract;
163
+ if (privateInitNullifier) {
164
+ initNullifiers[privateInitNullifier.toString()] = contract;
165
+ }
166
+ initNullifiers[publicInitNullifier.toString()] = contract;
152
167
  }
153
- for (const artifact of Object.values(artifactMap)) {
154
- classNullifiers[(await siloNullifier(classRegistryAddress, artifact.classId)).toString()] =
155
- `${artifact.name}Class<${artifact.classId}>`;
168
+ for (const { nullifier, label } of classResults) {
169
+ classNullifiers[nullifier.toString()] = label;
156
170
  }
171
+
157
172
  return { initNullifiers, deployNullifiers, classNullifiers };
158
173
  }
159
174
 
175
+ async function getContractNullifiers(wallet: CLIWallet, contract: AztecAddress) {
176
+ const deployerAddress = ProtocolContractAddress.ContractInstanceRegistry;
177
+ const deployNullifier = await siloNullifier(deployerAddress, contract.toField());
178
+
179
+ const metadata = await wallet.getContractMetadata(contract);
180
+ const privateInitNullifier = metadata.instance
181
+ ? await computeSiloedPrivateInitializationNullifier(contract, metadata.instance.initializationHash)
182
+ : undefined;
183
+ const publicInitNullifier = await computeSiloedPublicInitializationNullifier(contract);
184
+
185
+ return { contract, deployNullifier, privateInitNullifier, publicInitNullifier };
186
+ }
187
+
188
+ async function getClassNullifier(artifact: ContractArtifactWithClassId) {
189
+ const classRegistryAddress = ProtocolContractAddress.ContractClassRegistry;
190
+ const nullifier = await siloNullifier(classRegistryAddress, artifact.classId);
191
+ return { nullifier, label: `${artifact.name}Class<${artifact.classId}>` };
192
+ }
193
+
160
194
  type ArtifactMap = Record<string, ContractArtifactWithClassId>;
161
195
  type ContractArtifactWithClassId = ContractArtifact & { classId: Fr };
162
196
 
@@ -1,9 +1,12 @@
1
+ import { NO_FROM } from '@aztec/aztec.js/account';
1
2
  import { AztecAddress } from '@aztec/aztec.js/addresses';
2
- import type { AztecNode } from '@aztec/aztec.js/node';
3
+ import { NO_WAIT } from '@aztec/aztec.js/contracts';
4
+ import { type AztecNode, waitForTx } from '@aztec/aztec.js/node';
3
5
  import type { DeployAccountOptions } from '@aztec/aztec.js/wallet';
4
6
  import { prettyPrintJSON } from '@aztec/cli/cli-utils';
5
7
  import { Fr } from '@aztec/foundation/curves/bn254';
6
8
  import type { LogFn, Logger } from '@aztec/foundation/log';
9
+ import { type TxHash, type TxReceipt, TxStatus } from '@aztec/stdlib/tx';
7
10
 
8
11
  import { DEFAULT_TX_TIMEOUT_S } from '../utils/cli_wallet_and_node_wrapper.js';
9
12
  import type { AccountType } from '../utils/constants.js';
@@ -16,6 +19,7 @@ export async function createAccount(
16
19
  aztecNode: AztecNode,
17
20
  accountType: AccountType,
18
21
  secretKey: Fr | undefined,
22
+ salt: Fr | undefined,
19
23
  publicKey: string | undefined,
20
24
  alias: string | undefined,
21
25
  deployer: AztecAddress | undefined,
@@ -25,6 +29,7 @@ export async function createAccount(
25
29
  registerClass: boolean,
26
30
  wait: boolean,
27
31
  feeOpts: CLIFeeArgs,
32
+ waitForStatus: TxStatus,
28
33
  json: boolean,
29
34
  verbose: boolean,
30
35
  debugLogger: Logger,
@@ -36,10 +41,10 @@ export async function createAccount(
36
41
  undefined /* address, we don't have it yet */,
37
42
  secretKey,
38
43
  accountType,
39
- Fr.ZERO,
44
+ salt,
40
45
  publicKey,
41
46
  );
42
- const { salt } = account.getInstance();
47
+ const instanceSalt = account.getInstance().salt;
43
48
  const { address, publicKeys, partialAddress } = await account.getCompleteAddress();
44
49
 
45
50
  const out: Record<string, any> = {};
@@ -50,7 +55,7 @@ export async function createAccount(
50
55
  out.secretKey = secretKey;
51
56
  }
52
57
  out.partialAddress = partialAddress;
53
- out.salt = salt;
58
+ out.salt = instanceSalt;
54
59
  out.initHash = account.getInstance().initializationHash;
55
60
  } else {
56
61
  log(`\nNew account:\n`);
@@ -60,17 +65,17 @@ export async function createAccount(
60
65
  log(`Secret key: ${secretKey.toString()}`);
61
66
  }
62
67
  log(`Partial address: ${partialAddress.toString()}`);
63
- log(`Salt: ${salt.toString()}`);
68
+ log(`Salt: ${instanceSalt.toString()}`);
64
69
  log(`Init hash: ${account.getInstance().initializationHash.toString()}`);
65
70
  }
66
71
 
67
- let tx;
68
- let txReceipt;
72
+ let txHash: TxHash | undefined;
73
+ let txReceipt: TxReceipt | undefined;
69
74
  if (!registerOnly) {
70
75
  const { paymentMethod, gasSettings } = await feeOpts.toUserFeeOptions(aztecNode, wallet, address);
71
76
 
72
77
  const delegatedDeployment = deployer && !account.address.equals(deployer);
73
- const from = delegatedDeployment ? deployer : AztecAddress.ZERO;
78
+ const from = delegatedDeployment ? deployer : NO_FROM;
74
79
 
75
80
  const deployAccountOpts: DeployAccountOptions = {
76
81
  skipClassPublication: !registerClass,
@@ -80,11 +85,15 @@ export async function createAccount(
80
85
  fee: { paymentMethod, gasSettings },
81
86
  };
82
87
 
88
+ const localStart = performance.now();
83
89
  const deployMethod = await account.getDeployMethod();
84
- const { estimatedGas, stats } = await deployMethod.simulate({
90
+ const sim = await deployMethod.simulate({
85
91
  ...deployAccountOpts,
86
92
  fee: { ...deployAccountOpts.fee, estimateGas: true },
87
93
  });
94
+ // estimateGas: true guarantees these fields are present
95
+ const estimatedGas = sim.estimatedGas!;
96
+ const stats = sim.stats!;
88
97
 
89
98
  if (feeOpts.estimateOnly) {
90
99
  if (json) {
@@ -100,7 +109,14 @@ export async function createAccount(
100
109
  };
101
110
  }
102
111
  } else {
103
- tx = deployMethod.send({
112
+ if (verbose) {
113
+ printProfileResult(stats, log);
114
+ }
115
+
116
+ if (!json) {
117
+ log(`\nWaiting for account contract deployment...`);
118
+ }
119
+ const sendOpts = {
104
120
  ...deployAccountOpts,
105
121
  fee: deployAccountOpts.fee
106
122
  ? {
@@ -108,37 +124,41 @@ export async function createAccount(
108
124
  gasSettings: estimatedGas,
109
125
  }
110
126
  : undefined,
111
- });
112
- if (verbose) {
113
- printProfileResult(stats, log);
114
- }
127
+ };
128
+
129
+ ({ txHash } = await deployMethod.send({ ...sendOpts, wait: NO_WAIT }));
130
+ const localTimeMs = performance.now() - localStart;
115
131
 
116
- const txHash = await tx.getTxHash();
117
- debugLogger.debug(`Account contract tx sent with hash ${txHash.toString()}`);
118
- out.txHash = txHash;
119
132
  if (wait) {
120
- if (!json) {
121
- log(`\nWaiting for account contract deployment...`);
122
- }
123
- txReceipt = await tx.wait({ timeout: DEFAULT_TX_TIMEOUT_S });
133
+ const nodeStart = performance.now();
134
+ txReceipt = await waitForTx(aztecNode, txHash, { timeout: DEFAULT_TX_TIMEOUT_S, waitForStatus });
135
+ const nodeTimeMs = performance.now() - nodeStart;
136
+
124
137
  out.txReceipt = {
125
138
  status: txReceipt.status,
126
139
  transactionFee: txReceipt.transactionFee,
127
140
  };
141
+
142
+ if (!json) {
143
+ log(` Local processing time: ${(localTimeMs / 1000).toFixed(1)}s`);
144
+ log(` Node inclusion time: ${(nodeTimeMs / 1000).toFixed(1)}s`);
145
+ }
128
146
  }
147
+ debugLogger.debug(`Account contract tx sent with hash ${txHash.toString()}`);
148
+ out.txHash = txHash;
129
149
  }
130
150
  }
131
151
 
132
152
  if (json) {
133
153
  log(prettyPrintJSON(out));
134
154
  } else {
135
- if (tx) {
136
- log(`Deploy tx hash: ${(await tx.getTxHash()).toString()}`);
155
+ if (txHash) {
156
+ log(`Deploy tx hash: ${txHash.toString()}`);
137
157
  }
138
158
  if (txReceipt) {
139
159
  log(`Deploy tx fee: ${txReceipt.transactionFee}`);
140
160
  }
141
161
  }
142
162
 
143
- return { alias, address, secretKey, salt };
163
+ return { alias, address, secretKey, salt: instanceSalt };
144
164
  }
@@ -1,12 +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';
4
+ import { NO_WAIT } from '@aztec/aztec.js/contracts';
3
5
  import { ContractDeployer } from '@aztec/aztec.js/deployment';
4
6
  import { Fr } from '@aztec/aztec.js/fields';
5
- import type { AztecNode } from '@aztec/aztec.js/node';
7
+ import { type AztecNode, waitForTx } from '@aztec/aztec.js/node';
6
8
  import { encodeArgs, getContractArtifact, prettyPrintJSON } from '@aztec/cli/utils';
7
9
  import type { LogFn, Logger } from '@aztec/foundation/log';
8
10
  import { getAllFunctionAbis, getInitializer } from '@aztec/stdlib/abi';
9
11
  import { PublicKeys } from '@aztec/stdlib/keys';
12
+ import type { TxStatus } from '@aztec/stdlib/tx';
10
13
 
11
14
  import { DEFAULT_TX_TIMEOUT_S } from '../utils/cli_wallet_and_node_wrapper.js';
12
15
  import { CLIFeeArgs } from '../utils/options/fees.js';
@@ -28,6 +31,7 @@ export async function deploy(
28
31
  skipInitialization: boolean | undefined,
29
32
  wait: boolean,
30
33
  feeOpts: CLIFeeArgs,
34
+ waitForStatus: TxStatus,
31
35
  verbose: boolean,
32
36
  timeout: number = DEFAULT_TX_TIMEOUT_S,
33
37
  debugLogger: Logger,
@@ -58,11 +62,11 @@ export async function deploy(
58
62
  debugLogger.debug(`Encoded arguments: ${args.join(', ')}`);
59
63
  }
60
64
 
61
- const deploy = contractDeployer.deploy(...args);
65
+ const deployInteraction = contractDeployer.deploy(...args);
62
66
  const { paymentMethod, gasSettings } = await feeOpts.toUserFeeOptions(node, wallet, deployer);
63
67
  const deployOpts: DeployOptions = {
64
68
  fee: { gasSettings, paymentMethod },
65
- from: deployer ?? AztecAddress.ZERO,
69
+ from: deployer ?? NO_FROM,
66
70
  contractAddressSalt: salt,
67
71
  universalDeploy: !deployer,
68
72
  skipClassPublication,
@@ -70,10 +74,14 @@ export async function deploy(
70
74
  skipInstancePublication,
71
75
  };
72
76
 
73
- const { estimatedGas, stats } = await deploy.simulate({
77
+ const localStart = performance.now();
78
+ const sim = await deployInteraction.simulate({
74
79
  ...deployOpts,
75
80
  fee: { ...deployOpts.fee, estimateGas: true },
76
81
  });
82
+ // estimateGas: true guarantees these fields are present
83
+ const estimatedGas = sim.estimatedGas!;
84
+ const stats = sim.stats!;
77
85
 
78
86
  if (feeOpts.estimateOnly) {
79
87
  if (json) {
@@ -89,42 +97,62 @@ export async function deploy(
89
97
  };
90
98
  }
91
99
  } else {
92
- const tx = deploy.send(deployOpts);
93
100
  if (verbose) {
94
101
  printProfileResult(stats, log);
95
102
  }
96
103
 
97
- const txHash = await tx.getTxHash();
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;
98
109
  debugLogger.debug(`Deploy tx sent with hash ${txHash.toString()}`);
99
110
  out.hash = txHash;
100
- const { address, partialAddress } = deploy;
101
- const instance = await deploy.getInstance();
102
- if (!json) {
103
- log(`Contract deployed at ${address?.toString()}`);
104
- log(`Contract partial address ${(await partialAddress)?.toString()}`);
105
- log(`Contract init hash ${instance.initializationHash.toString()}`);
106
- log(`Deployment tx hash: ${txHash.toString()}`);
107
- log(`Deployment salt: ${salt.toString()}`);
108
- log(`Deployer: ${instance.deployer.toString()}`);
109
- } else {
110
- out.contract = {
111
- address: address?.toString(),
112
- partialAddress: (await partialAddress)?.toString(),
113
- initializationHash: instance.initializationHash.toString(),
114
- salt: salt.toString(),
115
- };
116
- }
111
+
117
112
  if (wait) {
118
- const deployed = await tx.wait({ timeout });
113
+ const nodeStart = performance.now();
114
+ const receipt = await waitForTx(node, txHash, { timeout, waitForStatus });
115
+ const nodeTimeMs = performance.now() - nodeStart;
116
+
117
+ if (!json) {
118
+ log(`Contract deployed at ${address?.toString()}`);
119
+ log(`Contract partial address ${(await partialAddress)?.toString()}`);
120
+ log(`Contract init hash ${instance.initializationHash.toString()}`);
121
+ log(`Deployment tx hash: ${txHash.toString()}`);
122
+ log(`Deployment salt: ${salt.toString()}`);
123
+ log(`Deployer: ${instance.deployer.toString()}`);
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`);
127
+ } else {
128
+ out.contract = {
129
+ address: address?.toString(),
130
+ partialAddress: (await partialAddress)?.toString(),
131
+ initializationHash: instance.initializationHash.toString(),
132
+ salt: salt.toString(),
133
+ transactionFee: receipt.transactionFee?.toString(),
134
+ };
135
+ }
136
+ } else {
119
137
  if (!json) {
120
- log(`Transaction fee: ${deployed.transactionFee?.toString()}`);
138
+ log(`Contract deployed at ${address?.toString()}`);
139
+ log(`Contract partial address ${(await partialAddress)?.toString()}`);
140
+ log(`Contract init hash ${instance.initializationHash.toString()}`);
141
+ log(`Deployment tx hash: ${txHash.toString()}`);
142
+ log(`Deployment salt: ${salt.toString()}`);
143
+ log(`Deployer: ${instance.deployer.toString()}`);
121
144
  } else {
122
- out.contract.transactionFee = deployed.transactionFee?.toString();
145
+ out.contract = {
146
+ address: address?.toString(),
147
+ partialAddress: (await partialAddress)?.toString(),
148
+ initializationHash: instance.initializationHash.toString(),
149
+ salt: salt.toString(),
150
+ };
123
151
  }
124
152
  }
125
153
  }
126
154
  if (json) {
127
155
  log(prettyPrintJSON(out));
128
156
  }
129
- return deploy.address;
157
+ return deployInteraction.address;
130
158
  }