@aztec/cli-wallet 0.0.1-commit.fffb133c → 0.0.1-dev

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/bin/index.js +1 -1
  2. package/dest/cmds/authorize_action.d.ts +2 -2
  3. package/dest/cmds/authorize_action.d.ts.map +1 -1
  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 +37 -9
  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 +32 -21
  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 +40 -34
  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 +27 -16
  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 +27 -23
  25. package/dest/storage/wallet_db.d.ts +6 -1
  26. package/dest/storage/wallet_db.d.ts.map +1 -1
  27. package/dest/storage/wallet_db.js +60 -31
  28. package/dest/utils/options/fees.d.ts +2 -2
  29. package/dest/utils/options/fees.d.ts.map +1 -1
  30. package/dest/utils/options/fees.js +10 -7
  31. package/dest/utils/wallet.d.ts +11 -5
  32. package/dest/utils/wallet.d.ts.map +1 -1
  33. package/dest/utils/wallet.js +77 -49
  34. package/package.json +14 -14
  35. package/src/bin/index.ts +1 -1
  36. package/src/cmds/check_tx.ts +43 -11
  37. package/src/cmds/create_account.ts +32 -18
  38. package/src/cmds/deploy.ts +34 -31
  39. package/src/cmds/deploy_account.ts +26 -13
  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 +24 -16
  43. package/src/cmds/simulate.ts +1 -1
  44. package/src/storage/wallet_db.ts +63 -36
  45. package/src/utils/options/fees.ts +15 -7
  46. package/src/utils/wallet.ts +85 -69
@@ -1,10 +1,13 @@
1
1
  import { EcdsaRAccountContract, EcdsaRSSHAccountContract } from '@aztec/accounts/ecdsa';
2
2
  import { SchnorrAccountContract } from '@aztec/accounts/schnorr';
3
- import { StubAccountContractArtifact, createStubAccount } from '@aztec/accounts/stub';
3
+ import { StubEcdsaAccountContractArtifact, createStubEcdsaAccount } from '@aztec/accounts/stub/ecdsa';
4
+ import { StubSchnorrAccountContractArtifact, createStubSchnorrAccount } from '@aztec/accounts/stub/schnorr';
4
5
  import { getIdentities } from '@aztec/accounts/utils';
5
- import { SignerlessAccount } from '@aztec/aztec.js/account';
6
+ import { NO_FROM } from '@aztec/aztec.js/account';
6
7
  import { getContractInstanceFromInstantiationParams, getGasLimits } from '@aztec/aztec.js/contracts';
7
8
  import { AccountManager } from '@aztec/aztec.js/wallet';
9
+ import { TxSimulationResultWithAppOffset } from '@aztec/aztec.js/wallet';
10
+ import { DefaultEntrypoint } from '@aztec/entrypoints/default';
8
11
  import { Fr } from '@aztec/foundation/curves/bn254';
9
12
  import { createPXE, getPXEConfig } from '@aztec/pxe/server';
10
13
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
@@ -28,33 +31,42 @@ export class CLIWallet extends BaseWallet {
28
31
  }
29
32
  async getAccounts() {
30
33
  const accounts = await this.db?.listAliases('accounts') ?? [];
31
- return Promise.resolve(accounts.map(({ key, value })=>({
32
- alias: value,
33
- item: AztecAddress.fromString(key)
34
- })));
34
+ return Promise.resolve(accounts.map(({ key, value })=>{
35
+ const alias = key.includes(':') ? key.slice(key.indexOf(':') + 1) : key;
36
+ return {
37
+ alias,
38
+ item: AztecAddress.fromString(value)
39
+ };
40
+ }));
35
41
  }
36
42
  async createCancellationTxExecutionRequest(from, txNonce, increasedFee) {
37
43
  const executionPayload = ExecutionPayload.empty();
38
- const feeOptions = await this.completeFeeOptions(from, executionPayload.feePayer, increasedFee.gasSettings);
44
+ const feeOptions = await this.completeFeeOptions({
45
+ from,
46
+ feePayer: executionPayload.feePayer,
47
+ gasSettings: increasedFee.gasSettings
48
+ });
39
49
  const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
40
50
  const fromAccount = await this.getAccountFromAddress(from);
41
51
  const chainInfo = await this.getChainInfo();
42
52
  const executionOptions = {
43
53
  txNonce,
44
54
  cancellable: this.cancellableTransactions,
55
+ // If from is an address, feeOptions include the way the account contract should handle the fee payment
45
56
  feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions
46
57
  };
47
58
  return await fromAccount.createTxExecutionRequest(feeExecutionPayload ?? executionPayload, feeOptions.gasSettings, chainInfo, executionOptions);
48
59
  }
49
60
  async proveCancellationTx(from, txNonce, increasedFee) {
50
61
  const cancellationTxRequest = await this.createCancellationTxExecutionRequest(from, txNonce, increasedFee);
51
- return await this.pxe.proveTx(cancellationTxRequest);
62
+ return await this.pxe.proveTx(cancellationTxRequest, {
63
+ scopes: this.scopesFrom(from),
64
+ senderForTags: from
65
+ });
52
66
  }
53
67
  async getAccountFromAddress(address) {
54
68
  let account;
55
- if (address.equals(AztecAddress.ZERO)) {
56
- account = new SignerlessAccount();
57
- } else if (this.accountCache.has(address.toString())) {
69
+ if (this.accountCache.has(address.toString())) {
58
70
  return this.accountCache.get(address.toString());
59
71
  } else {
60
72
  const accountManager = await this.createOrRetrieveAccount(address);
@@ -125,66 +137,82 @@ export class CLIWallet extends BaseWallet {
125
137
  * @returns The stub account, contract instance, and artifact for simulation
126
138
  */ async getFakeAccountDataFor(address) {
127
139
  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
140
  const originalAddress = originalAccount.getCompleteAddress();
135
141
  const contractInstance = await this.pxe.getContractInstance(originalAddress.address);
136
142
  if (!contractInstance) {
137
143
  throw new Error(`No contract instance found for address: ${originalAddress.address}`);
138
144
  }
139
- const stubAccount = createStubAccount(originalAddress);
140
- const instance = await getContractInstanceFromInstantiationParams(StubAccountContractArtifact, {
145
+ const { type } = await this.db.retrieveAccount(address);
146
+ const isSchnorr = type === 'schnorr';
147
+ const artifact = isSchnorr ? StubSchnorrAccountContractArtifact : StubEcdsaAccountContractArtifact;
148
+ const stubAccount = isSchnorr ? createStubSchnorrAccount(originalAddress) : createStubEcdsaAccount(originalAddress);
149
+ const instance = await getContractInstanceFromInstantiationParams(artifact, {
141
150
  salt: Fr.random()
142
151
  });
143
152
  return {
144
153
  account: stubAccount,
145
154
  instance,
146
- artifact: StubAccountContractArtifact
155
+ artifact
147
156
  };
148
157
  }
149
158
  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);
159
+ const simulationResults = await super.simulateTx(executionPayload, opts);
160
+ if (opts.fee?.estimateGas) {
161
+ const feeOptions = await this.completeFeeOptions({
162
+ from: opts.from,
163
+ feePayer: executionPayload.feePayer,
164
+ gasSettings: opts.fee?.gasSettings
165
+ });
166
+ const limits = getGasLimits(simulationResults, opts.fee?.estimatedGasPadding);
167
+ printGasEstimates(feeOptions, limits, this.userLog);
168
+ }
169
+ return simulationResults;
170
+ }
171
+ /**
172
+ * Uses a stub account for kernelless simulation, bypassing real account authorization.
173
+ * Uses DefaultEntrypoint directly for NO_FROM transactions.
174
+ */ async simulateViaEntrypoint(executionPayload, opts) {
175
+ const { from, feeOptions, additionalScopes, sendMessagesAs } = opts;
176
+ const scopes = this.scopesFrom(from, additionalScopes);
152
177
  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
178
  const finalExecutionPayload = feeExecutionPayload ? mergeExecutionPayloads([
160
179
  feeExecutionPayload,
161
180
  executionPayload
162
181
  ]) : 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);
182
+ const chainInfo = await this.getChainInfo();
183
+ let overrides;
184
+ let txRequest;
185
+ if (from === NO_FROM) {
186
+ const entrypoint = new DefaultEntrypoint();
187
+ txRequest = await entrypoint.createTxExecutionRequest(finalExecutionPayload, feeOptions.gasSettings, chainInfo);
170
188
  } 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
189
+ const { account, instance, artifact } = await this.getFakeAccountDataFor(from);
190
+ overrides = {
191
+ contracts: {
192
+ [from.toString()]: {
193
+ instance,
194
+ artifact
195
+ }
177
196
  }
178
197
  };
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);
198
+ const executionOptions = {
199
+ txNonce: Fr.random(),
200
+ cancellable: this.cancellableTransactions,
201
+ // If from is an address, feeOptions include the way the account contract should handle the fee payment
202
+ feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions
203
+ };
204
+ txRequest = await account.createTxExecutionRequest(finalExecutionPayload, feeOptions.gasSettings, chainInfo, executionOptions);
186
205
  }
187
- return simulationResults;
206
+ const result = await this.pxe.simulateTx(txRequest, {
207
+ simulatePublic: true,
208
+ skipFeeEnforcement: true,
209
+ skipTxValidation: true,
210
+ overrides,
211
+ scopes,
212
+ senderForTags: this.senderForTagsFrom(from, sendMessagesAs)
213
+ });
214
+ const appCallOffset = await this.computeAppCallOffset(from, feeOptions);
215
+ return TxSimulationResultWithAppOffset.fromResultAndOffset(result, appCallOffset);
188
216
  }
189
217
  // Exposed because of the `aztec-wallet get-tx` command. It has been decided that it's fine to keep around because
190
218
  // 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.fffb133c",
3
+ "version": "0.0.1-dev",
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.fffb133c",
71
- "@aztec/aztec.js": "0.0.1-commit.fffb133c",
72
- "@aztec/bb.js": "0.0.1-commit.fffb133c",
73
- "@aztec/cli": "0.0.1-commit.fffb133c",
74
- "@aztec/entrypoints": "0.0.1-commit.fffb133c",
75
- "@aztec/ethereum": "0.0.1-commit.fffb133c",
76
- "@aztec/foundation": "0.0.1-commit.fffb133c",
77
- "@aztec/kv-store": "0.0.1-commit.fffb133c",
78
- "@aztec/noir-contracts.js": "0.0.1-commit.fffb133c",
79
- "@aztec/noir-noirc_abi": "0.0.1-commit.fffb133c",
80
- "@aztec/pxe": "0.0.1-commit.fffb133c",
81
- "@aztec/stdlib": "0.0.1-commit.fffb133c",
82
- "@aztec/wallet-sdk": "0.0.1-commit.fffb133c",
70
+ "@aztec/accounts": "0.0.1-dev",
71
+ "@aztec/aztec.js": "0.0.1-dev",
72
+ "@aztec/bb.js": "0.0.1-dev",
73
+ "@aztec/cli": "0.0.1-dev",
74
+ "@aztec/entrypoints": "0.0.1-dev",
75
+ "@aztec/ethereum": "0.0.1-dev",
76
+ "@aztec/foundation": "0.0.1-dev",
77
+ "@aztec/kv-store": "0.0.1-dev",
78
+ "@aztec/noir-contracts.js": "0.0.1-dev",
79
+ "@aztec/noir-noirc_abi": "0.0.1-dev",
80
+ "@aztec/pxe": "0.0.1-dev",
81
+ "@aztec/stdlib": "0.0.1-dev",
82
+ "@aztec/wallet-sdk": "0.0.1-dev",
83
83
  "commander": "^12.1.0",
84
84
  "inquirer": "^10.1.8",
85
85
  "source-map-support": "^0.5.21",
package/src/bin/index.ts CHANGED
@@ -73,7 +73,7 @@ function injectInternalCommands(program: Command, log: LogFn, db: WalletDB) {
73
73
 
74
74
  /** CLI wallet main entrypoint */
75
75
  async function main() {
76
- const walletVersion = getPackageVersion() ?? '0.0.0';
76
+ const walletVersion = getPackageVersion();
77
77
 
78
78
  const db = WalletDB.getInstance();
79
79
  const walletAndNodeWrapper = new CliWalletAndNodeWrapper();
@@ -1,11 +1,15 @@
1
1
  import type { ContractArtifact } from '@aztec/aztec.js/abi';
2
- import type { AztecAddress } from '@aztec/aztec.js/addresses';
2
+ import { AztecAddress } from '@aztec/aztec.js/addresses';
3
3
  import { Fr } from '@aztec/aztec.js/fields';
4
4
  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';
@@ -83,12 +87,13 @@ async function inspectTx(wallet: CLIWallet, aztecNode: AztecNode, txHash: TxHash
83
87
  // Nullifiers
84
88
  const nullifierCount = effects.nullifiers.length;
85
89
  const { deployNullifiers, initNullifiers, classNullifiers } = await getKnownNullifiers(wallet, artifactMap);
90
+ const accounts = (await wallet.getAccounts()).map(a => a.item);
86
91
  if (nullifierCount > 0) {
87
92
  log(' Nullifiers:');
88
93
  for (const nullifier of effects.nullifiers) {
89
94
  const deployed = deployNullifiers[nullifier.toString()];
90
95
  const note = deployed
91
- ? (await wallet.getNotes({ siloedNullifier: nullifier, contractAddress: deployed }))[0]
96
+ ? (await wallet.getNotes({ siloedNullifier: nullifier, contractAddress: deployed, scopes: accounts }))[0]
92
97
  : undefined;
93
98
  const initialized = initNullifiers[nullifier.toString()];
94
99
  const registered = classNullifiers[nullifier.toString()];
@@ -144,22 +149,49 @@ function toFriendlyAddress(address: AztecAddress, artifactMap: ArtifactMap) {
144
149
 
145
150
  async function getKnownNullifiers(wallet: CLIWallet, artifactMap: ArtifactMap) {
146
151
  const knownContracts = await wallet.getContracts();
147
- const deployerAddress = ProtocolContractAddress.ContractInstanceRegistry;
148
- const classRegistryAddress = ProtocolContractAddress.ContractClassRegistry;
152
+
153
+ const [contractResults, classResults] = await Promise.all([
154
+ Promise.all(knownContracts.map(contract => getContractNullifiers(wallet, contract))),
155
+ Promise.all(Object.values(artifactMap).map(artifact => getClassNullifier(artifact))),
156
+ ]);
157
+
149
158
  const initNullifiers: Record<string, AztecAddress> = {};
150
159
  const deployNullifiers: Record<string, AztecAddress> = {};
151
160
  const classNullifiers: Record<string, string> = {};
152
- for (const contract of knownContracts) {
153
- initNullifiers[(await siloNullifier(contract, contract.toField())).toString()] = contract;
154
- deployNullifiers[(await siloNullifier(deployerAddress, contract.toField())).toString()] = contract;
161
+
162
+ for (const { contract, deployNullifier, privateInitNullifier, publicInitNullifier } of contractResults) {
163
+ deployNullifiers[deployNullifier.toString()] = contract;
164
+ if (privateInitNullifier) {
165
+ initNullifiers[privateInitNullifier.toString()] = contract;
166
+ }
167
+ initNullifiers[publicInitNullifier.toString()] = contract;
155
168
  }
156
- for (const artifact of Object.values(artifactMap)) {
157
- classNullifiers[(await siloNullifier(classRegistryAddress, artifact.classId)).toString()] =
158
- `${artifact.name}Class<${artifact.classId}>`;
169
+ for (const { nullifier, label } of classResults) {
170
+ classNullifiers[nullifier.toString()] = label;
159
171
  }
172
+
160
173
  return { initNullifiers, deployNullifiers, classNullifiers };
161
174
  }
162
175
 
176
+ async function getContractNullifiers(wallet: CLIWallet, contract: AztecAddress) {
177
+ const deployerAddress = ProtocolContractAddress.ContractInstanceRegistry;
178
+ const deployNullifier = await siloNullifier(deployerAddress, contract.toField());
179
+
180
+ const metadata = await wallet.getContractMetadata(contract);
181
+ const privateInitNullifier = metadata.instance
182
+ ? await computeSiloedPrivateInitializationNullifier(contract, metadata.instance.initializationHash)
183
+ : undefined;
184
+ const publicInitNullifier = await computeSiloedPublicInitializationNullifier(contract);
185
+
186
+ return { contract, deployNullifier, privateInitNullifier, publicInitNullifier };
187
+ }
188
+
189
+ async function getClassNullifier(artifact: ContractArtifactWithClassId) {
190
+ const classRegistryAddress = ProtocolContractAddress.ContractClassRegistry;
191
+ const nullifier = await siloNullifier(classRegistryAddress, artifact.classId);
192
+ return { nullifier, label: `${artifact.name}Class<${artifact.classId}>` };
193
+ }
194
+
163
195
  type ArtifactMap = Record<string, ContractArtifactWithClassId>;
164
196
  type ContractArtifactWithClassId = ContractArtifact & { classId: Fr };
165
197
 
@@ -1,11 +1,12 @@
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 { Fr } from '@aztec/foundation/curves/bn254';
7
8
  import type { LogFn, Logger } from '@aztec/foundation/log';
8
- import type { TxHash, TxReceipt } from '@aztec/stdlib/tx';
9
+ import { type TxHash, type TxReceipt, TxStatus } from '@aztec/stdlib/tx';
9
10
 
10
11
  import { DEFAULT_TX_TIMEOUT_S } from '../utils/cli_wallet_and_node_wrapper.js';
11
12
  import type { AccountType } from '../utils/constants.js';
@@ -18,6 +19,7 @@ export async function createAccount(
18
19
  aztecNode: AztecNode,
19
20
  accountType: AccountType,
20
21
  secretKey: Fr | undefined,
22
+ salt: Fr | undefined,
21
23
  publicKey: string | undefined,
22
24
  alias: string | undefined,
23
25
  deployer: AztecAddress | undefined,
@@ -27,6 +29,7 @@ export async function createAccount(
27
29
  registerClass: boolean,
28
30
  wait: boolean,
29
31
  feeOpts: CLIFeeArgs,
32
+ waitForStatus: TxStatus,
30
33
  json: boolean,
31
34
  verbose: boolean,
32
35
  debugLogger: Logger,
@@ -38,10 +41,10 @@ export async function createAccount(
38
41
  undefined /* address, we don't have it yet */,
39
42
  secretKey,
40
43
  accountType,
41
- Fr.ZERO,
44
+ salt,
42
45
  publicKey,
43
46
  );
44
- const { salt } = account.getInstance();
47
+ const instanceSalt = account.getInstance().salt;
45
48
  const { address, publicKeys, partialAddress } = await account.getCompleteAddress();
46
49
 
47
50
  const out: Record<string, any> = {};
@@ -52,7 +55,7 @@ export async function createAccount(
52
55
  out.secretKey = secretKey;
53
56
  }
54
57
  out.partialAddress = partialAddress;
55
- out.salt = salt;
58
+ out.salt = instanceSalt;
56
59
  out.initHash = account.getInstance().initializationHash;
57
60
  } else {
58
61
  log(`\nNew account:\n`);
@@ -62,7 +65,7 @@ export async function createAccount(
62
65
  log(`Secret key: ${secretKey.toString()}`);
63
66
  }
64
67
  log(`Partial address: ${partialAddress.toString()}`);
65
- log(`Salt: ${salt.toString()}`);
68
+ log(`Salt: ${instanceSalt.toString()}`);
66
69
  log(`Init hash: ${account.getInstance().initializationHash.toString()}`);
67
70
  }
68
71
 
@@ -72,7 +75,7 @@ export async function createAccount(
72
75
  const { paymentMethod, gasSettings } = await feeOpts.toUserFeeOptions(aztecNode, wallet, address);
73
76
 
74
77
  const delegatedDeployment = deployer && !account.address.equals(deployer);
75
- const from = delegatedDeployment ? deployer : AztecAddress.ZERO;
78
+ const from = delegatedDeployment ? deployer : NO_FROM;
76
79
 
77
80
  const deployAccountOpts: DeployAccountOptions = {
78
81
  skipClassPublication: !registerClass,
@@ -82,11 +85,15 @@ export async function createAccount(
82
85
  fee: { paymentMethod, gasSettings },
83
86
  };
84
87
 
88
+ const localStart = performance.now();
85
89
  const deployMethod = await account.getDeployMethod();
86
- const { estimatedGas, stats } = await deployMethod.simulate({
90
+ const sim = await deployMethod.simulate({
87
91
  ...deployAccountOpts,
88
92
  fee: { ...deployAccountOpts.fee, estimateGas: true },
89
93
  });
94
+ // estimateGas: true guarantees these fields are present
95
+ const estimatedGas = sim.estimatedGas!;
96
+ const stats = sim.stats!;
90
97
 
91
98
  if (feeOpts.estimateOnly) {
92
99
  if (json) {
@@ -109,7 +116,7 @@ export async function createAccount(
109
116
  if (!json) {
110
117
  log(`\nWaiting for account contract deployment...`);
111
118
  }
112
- const result = await deployMethod.send({
119
+ const sendOpts = {
113
120
  ...deployAccountOpts,
114
121
  fee: deployAccountOpts.fee
115
122
  ? {
@@ -117,18 +124,25 @@ export async function createAccount(
117
124
  gasSettings: estimatedGas,
118
125
  }
119
126
  : undefined,
120
- wait: wait ? { timeout: DEFAULT_TX_TIMEOUT_S, returnReceipt: true } : NO_WAIT,
121
- });
122
- const isReceipt = (data: TxReceipt | TxHash): data is TxReceipt => 'txHash' in data;
123
- if (isReceipt(result)) {
124
- txReceipt = result;
125
- txHash = result.txHash;
127
+ };
128
+
129
+ ({ txHash } = await deployMethod.send({ ...sendOpts, wait: NO_WAIT }));
130
+ const localTimeMs = performance.now() - localStart;
131
+
132
+ if (wait) {
133
+ const nodeStart = performance.now();
134
+ txReceipt = await waitForTx(aztecNode, txHash, { timeout: DEFAULT_TX_TIMEOUT_S, waitForStatus });
135
+ const nodeTimeMs = performance.now() - nodeStart;
136
+
126
137
  out.txReceipt = {
127
138
  status: txReceipt.status,
128
139
  transactionFee: txReceipt.transactionFee,
129
140
  };
130
- } else {
131
- txHash = result;
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
+ }
132
146
  }
133
147
  debugLogger.debug(`Account contract tx sent with hash ${txHash.toString()}`);
134
148
  out.txHash = txHash;
@@ -146,5 +160,5 @@ export async function createAccount(
146
160
  }
147
161
  }
148
162
 
149
- return { alias, address, secretKey, salt };
163
+ return { alias, address, secretKey, salt: instanceSalt };
150
164
  }
@@ -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,
@@ -42,12 +45,7 @@ export async function deploy(
42
45
 
43
46
  // TODO(#12081): Add contractArtifact.noirVersion and check here (via Noir.lock)?
44
47
 
45
- const contractDeployer = new ContractDeployer(
46
- contractArtifact,
47
- wallet,
48
- publicKeys ?? PublicKeys.default(),
49
- initializer,
50
- );
48
+ const contractDeployer = new ContractDeployer(contractArtifact, wallet, initializer);
51
49
 
52
50
  let args = [];
53
51
  if (rawArgs.length > 0) {
@@ -59,22 +57,24 @@ export async function deploy(
59
57
  debugLogger.debug(`Encoded arguments: ${args.join(', ')}`);
60
58
  }
61
59
 
62
- const deploy = contractDeployer.deploy(...args);
60
+ const deployInteraction = contractDeployer.deploy(args, { salt, publicKeys: publicKeys ?? PublicKeys.default() });
63
61
  const { paymentMethod, gasSettings } = await feeOpts.toUserFeeOptions(node, wallet, deployer);
64
62
  const deployOpts: DeployOptions = {
65
63
  fee: { gasSettings, paymentMethod },
66
- from: deployer ?? AztecAddress.ZERO,
67
- contractAddressSalt: salt,
68
- universalDeploy: !deployer,
64
+ from: deployer ?? NO_FROM,
69
65
  skipClassPublication,
70
66
  skipInitialization,
71
67
  skipInstancePublication,
72
68
  };
73
69
 
74
- const { estimatedGas, stats } = await deploy.simulate({
70
+ const localStart = performance.now();
71
+ const sim = await deployInteraction.simulate({
75
72
  ...deployOpts,
76
73
  fee: { ...deployOpts.fee, estimateGas: true },
77
74
  });
75
+ // estimateGas: true guarantees these fields are present
76
+ const estimatedGas = sim.estimatedGas!;
77
+ const stats = sim.stats!;
78
78
 
79
79
  if (feeOpts.estimateOnly) {
80
80
  if (json) {
@@ -94,48 +94,51 @@ export async function deploy(
94
94
  printProfileResult(stats, log);
95
95
  }
96
96
 
97
- const { address, partialAddress } = deploy;
98
- const instance = await deploy.getInstance();
97
+ const instance = await deployInteraction.getInstance();
98
+ const address = instance.address;
99
+ const partialAddress = await deployInteraction.getPartialAddress();
100
+
101
+ const { txHash } = await deployInteraction.send({ ...deployOpts, wait: NO_WAIT });
102
+ const localTimeMs = performance.now() - localStart;
103
+ debugLogger.debug(`Deploy tx sent with hash ${txHash.toString()}`);
104
+ out.hash = txHash;
99
105
 
100
106
  if (wait) {
101
- const receipt = await deploy.send({ ...deployOpts, wait: { timeout, returnReceipt: true } });
102
- const txHash = receipt.txHash;
103
- debugLogger.debug(`Deploy tx sent with hash ${txHash.toString()}`);
104
- out.hash = txHash;
107
+ const nodeStart = performance.now();
108
+ const receipt = await waitForTx(node, txHash, { timeout, waitForStatus });
109
+ const nodeTimeMs = performance.now() - nodeStart;
105
110
 
106
111
  if (!json) {
107
- log(`Contract deployed at ${address?.toString()}`);
108
- log(`Contract partial address ${(await partialAddress)?.toString()}`);
112
+ log(`Contract deployed at ${address.toString()}`);
113
+ log(`Contract partial address ${partialAddress.toString()}`);
109
114
  log(`Contract init hash ${instance.initializationHash.toString()}`);
110
115
  log(`Deployment tx hash: ${txHash.toString()}`);
111
116
  log(`Deployment salt: ${salt.toString()}`);
112
117
  log(`Deployer: ${instance.deployer.toString()}`);
113
118
  log(`Transaction fee: ${receipt.transactionFee?.toString()}`);
119
+ log(` Local processing time: ${(localTimeMs / 1000).toFixed(1)}s`);
120
+ log(` Node inclusion time: ${(nodeTimeMs / 1000).toFixed(1)}s`);
114
121
  } else {
115
122
  out.contract = {
116
- address: address?.toString(),
117
- partialAddress: (await partialAddress)?.toString(),
123
+ address: address.toString(),
124
+ partialAddress: partialAddress.toString(),
118
125
  initializationHash: instance.initializationHash.toString(),
119
126
  salt: salt.toString(),
120
127
  transactionFee: receipt.transactionFee?.toString(),
121
128
  };
122
129
  }
123
130
  } else {
124
- const txHash = await deploy.send({ ...deployOpts, wait: NO_WAIT });
125
- debugLogger.debug(`Deploy tx sent with hash ${txHash.toString()}`);
126
- out.hash = txHash;
127
-
128
131
  if (!json) {
129
- log(`Contract deployed at ${address?.toString()}`);
130
- log(`Contract partial address ${(await partialAddress)?.toString()}`);
132
+ log(`Contract deployed at ${address.toString()}`);
133
+ log(`Contract partial address ${partialAddress.toString()}`);
131
134
  log(`Contract init hash ${instance.initializationHash.toString()}`);
132
135
  log(`Deployment tx hash: ${txHash.toString()}`);
133
136
  log(`Deployment salt: ${salt.toString()}`);
134
137
  log(`Deployer: ${instance.deployer.toString()}`);
135
138
  } else {
136
139
  out.contract = {
137
- address: address?.toString(),
138
- partialAddress: (await partialAddress)?.toString(),
140
+ address: address.toString(),
141
+ partialAddress: partialAddress.toString(),
139
142
  initializationHash: instance.initializationHash.toString(),
140
143
  salt: salt.toString(),
141
144
  };
@@ -145,5 +148,5 @@ export async function deploy(
145
148
  if (json) {
146
149
  log(prettyPrintJSON(out));
147
150
  }
148
- return deploy.address;
151
+ return await deployInteraction.getAddress();
149
152
  }