@aztec/cli-wallet 0.0.1-commit.b6e433891 → 0.0.1-commit.b9865e97

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 (41) hide show
  1. package/dest/bin/index.js +1 -1
  2. package/dest/cmds/check_tx.js +7 -7
  3. package/dest/cmds/create_account.d.ts +4 -3
  4. package/dest/cmds/create_account.d.ts.map +1 -1
  5. package/dest/cmds/create_account.js +24 -21
  6. package/dest/cmds/deploy.d.ts +5 -4
  7. package/dest/cmds/deploy.d.ts.map +1 -1
  8. package/dest/cmds/deploy.js +40 -34
  9. package/dest/cmds/deploy_account.d.ts +4 -3
  10. package/dest/cmds/deploy_account.d.ts.map +1 -1
  11. package/dest/cmds/deploy_account.js +19 -16
  12. package/dest/cmds/get_fee_juice_balance.d.ts +5 -0
  13. package/dest/cmds/get_fee_juice_balance.d.ts.map +1 -0
  14. package/dest/cmds/get_fee_juice_balance.js +27 -0
  15. package/dest/cmds/index.d.ts +1 -1
  16. package/dest/cmds/index.d.ts.map +1 -1
  17. package/dest/cmds/index.js +31 -15
  18. package/dest/cmds/send.d.ts +4 -3
  19. package/dest/cmds/send.d.ts.map +1 -1
  20. package/dest/cmds/send.js +23 -22
  21. package/dest/storage/wallet_db.d.ts +6 -1
  22. package/dest/storage/wallet_db.d.ts.map +1 -1
  23. package/dest/storage/wallet_db.js +14 -0
  24. package/dest/utils/options/fees.d.ts +3 -2
  25. package/dest/utils/options/fees.d.ts.map +1 -1
  26. package/dest/utils/options/fees.js +30 -9
  27. package/dest/utils/wallet.d.ts +9 -5
  28. package/dest/utils/wallet.d.ts.map +1 -1
  29. package/dest/utils/wallet.js +101 -52
  30. package/package.json +16 -15
  31. package/src/bin/index.ts +1 -1
  32. package/src/cmds/check_tx.ts +6 -5
  33. package/src/cmds/create_account.ts +25 -16
  34. package/src/cmds/deploy.ts +37 -32
  35. package/src/cmds/deploy_account.ts +19 -11
  36. package/src/cmds/get_fee_juice_balance.ts +37 -0
  37. package/src/cmds/index.ts +59 -5
  38. package/src/cmds/send.ts +20 -15
  39. package/src/storage/wallet_db.ts +14 -0
  40. package/src/utils/options/fees.ts +33 -9
  41. package/src/utils/wallet.ts +108 -63
@@ -1,12 +1,16 @@
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 { getContractInstanceFromInstantiationParams, getGasLimits } from '@aztec/aztec.js/contracts';
6
+ import { NO_FROM } from '@aztec/aztec.js/account';
7
+ import { getContractClassFromArtifact, 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';
13
+ import { getStandardAuthRegistry } from '@aztec/standard-contracts/auth-registry';
10
14
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
11
15
  import { deriveSigningKey } from '@aztec/stdlib/keys';
12
16
  import { ExecutionPayload, mergeExecutionPayloads } from '@aztec/stdlib/tx';
@@ -17,44 +21,80 @@ export class CLIWallet extends BaseWallet {
17
21
  userLog;
18
22
  db;
19
23
  accountCache;
24
+ // Stub class ids, populated on wallet startup
25
+ // to avoid redundant work per simulation
26
+ stubClassIds;
20
27
  constructor(pxe, node, userLog, db){
21
- super(pxe, node), this.userLog = userLog, this.db = db, this.accountCache = new Map();
28
+ super(pxe, node), this.userLog = userLog, this.db = db, this.accountCache = new Map(), this.stubClassIds = new Map();
22
29
  this.cancellableTransactions = true;
23
30
  }
24
31
  static async create(node, log, db, overridePXEConfig) {
25
32
  const pxeConfig = Object.assign(getPXEConfig(), overridePXEConfig);
26
33
  const pxe = await createPXE(node, pxeConfig);
27
- return new CLIWallet(pxe, node, log, db);
34
+ const wallet = new CLIWallet(pxe, node, log, db);
35
+ await wallet.initStubClasses();
36
+ await wallet.registerAuthRegistry();
37
+ return wallet;
38
+ }
39
+ async registerAuthRegistry() {
40
+ const { instance, artifact } = await getStandardAuthRegistry();
41
+ await this.pxe.registerContract({
42
+ instance,
43
+ artifact
44
+ });
45
+ }
46
+ /**
47
+ * Hashes and registers the stub class for every supported account type with PXE, populating
48
+ * stubClassIds. Called on wallet initialization.
49
+ */ async initStubClasses() {
50
+ const { id: schnorrClassId } = await getContractClassFromArtifact(StubSchnorrAccountContractArtifact);
51
+ await this.pxe.registerContractClass(StubSchnorrAccountContractArtifact);
52
+ // ecdsa stubs share the same class id
53
+ const { id: ecdsaClassId } = await getContractClassFromArtifact(StubEcdsaAccountContractArtifact);
54
+ await this.pxe.registerContractClass(StubEcdsaAccountContractArtifact);
55
+ this.stubClassIds.set('schnorr', schnorrClassId);
56
+ this.stubClassIds.set('ecdsasecp256k1', ecdsaClassId);
57
+ this.stubClassIds.set('ecdsasecp256r1', ecdsaClassId);
58
+ this.stubClassIds.set('ecdsasecp256r1ssh', ecdsaClassId);
28
59
  }
29
60
  async getAccounts() {
30
61
  const accounts = await this.db?.listAliases('accounts') ?? [];
31
- return Promise.resolve(accounts.map(({ key, value })=>({
32
- alias: value,
33
- item: AztecAddress.fromString(key)
34
- })));
62
+ return Promise.resolve(accounts.map(({ key, value })=>{
63
+ const alias = key.includes(':') ? key.slice(key.indexOf(':') + 1) : key;
64
+ return {
65
+ alias,
66
+ item: AztecAddress.fromString(value)
67
+ };
68
+ }));
35
69
  }
36
70
  async createCancellationTxExecutionRequest(from, txNonce, increasedFee) {
37
71
  const executionPayload = ExecutionPayload.empty();
38
- const feeOptions = await this.completeFeeOptions(from, executionPayload.feePayer, increasedFee.gasSettings);
72
+ const feeOptions = await this.completeFeeOptions({
73
+ from,
74
+ feePayer: executionPayload.feePayer,
75
+ gasSettings: increasedFee.gasSettings
76
+ });
39
77
  const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
40
78
  const fromAccount = await this.getAccountFromAddress(from);
41
79
  const chainInfo = await this.getChainInfo();
42
80
  const executionOptions = {
43
81
  txNonce,
44
82
  cancellable: this.cancellableTransactions,
83
+ // If from is an address, feeOptions include the way the account contract should handle the fee payment
45
84
  feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions
46
85
  };
47
86
  return await fromAccount.createTxExecutionRequest(feeExecutionPayload ?? executionPayload, feeOptions.gasSettings, chainInfo, executionOptions);
48
87
  }
49
88
  async proveCancellationTx(from, txNonce, increasedFee) {
50
89
  const cancellationTxRequest = await this.createCancellationTxExecutionRequest(from, txNonce, increasedFee);
51
- return await this.pxe.proveTx(cancellationTxRequest, this.scopesFrom(from));
90
+ return await this.pxe.proveTx(cancellationTxRequest, {
91
+ scopes: this.scopesFrom(from),
92
+ senderForTags: from
93
+ });
52
94
  }
53
95
  async getAccountFromAddress(address) {
54
96
  let account;
55
- if (address.equals(AztecAddress.ZERO)) {
56
- account = new SignerlessAccount();
57
- } else if (this.accountCache.has(address.toString())) {
97
+ if (this.accountCache.has(address.toString())) {
58
98
  return this.accountCache.get(address.toString());
59
99
  } else {
60
100
  const accountManager = await this.createOrRetrieveAccount(address);
@@ -66,7 +106,9 @@ export class CLIWallet extends BaseWallet {
66
106
  return account;
67
107
  }
68
108
  async createAccount(secret, salt, contract) {
69
- const accountManager = await AccountManager.create(this, secret, contract, salt);
109
+ const accountManager = await AccountManager.create(this, secret, contract, {
110
+ salt
111
+ });
70
112
  const instance = accountManager.getInstance();
71
113
  const artifact = await contract.getContractArtifact();
72
114
  await this.registerContract(instance, artifact, secret);
@@ -125,31 +167,34 @@ export class CLIWallet extends BaseWallet {
125
167
  * @returns The stub account, contract instance, and artifact for simulation
126
168
  */ async getFakeAccountDataFor(address) {
127
169
  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
170
  const originalAddress = originalAccount.getCompleteAddress();
135
171
  const contractInstance = await this.pxe.getContractInstance(originalAddress.address);
136
172
  if (!contractInstance) {
137
173
  throw new Error(`No contract instance found for address: ${originalAddress.address}`);
138
174
  }
139
- const stubAccount = createStubAccount(originalAddress);
140
- const instance = await getContractInstanceFromInstantiationParams(StubAccountContractArtifact, {
141
- salt: Fr.random()
142
- });
175
+ const { type } = await this.db.retrieveAccount(address);
176
+ const stubAccount = type === 'schnorr' ? createStubSchnorrAccount(originalAddress) : createStubEcdsaAccount(originalAddress);
177
+ const stubClassId = this.stubClassIds.get(type);
178
+ if (!stubClassId) {
179
+ throw new Error(`Stub class for account type '${type}' was not registered at wallet init. This is a bug — initStubClasses should cover every supported AccountType.`);
180
+ }
181
+ const instance = {
182
+ ...contractInstance,
183
+ currentContractClassId: stubClassId
184
+ };
143
185
  return {
144
186
  account: stubAccount,
145
- instance,
146
- artifact: StubAccountContractArtifact
187
+ instance
147
188
  };
148
189
  }
149
190
  async simulateTx(executionPayload, opts) {
150
191
  const simulationResults = await super.simulateTx(executionPayload, opts);
151
192
  if (opts.fee?.estimateGas) {
152
- const feeOptions = await this.completeFeeOptions(opts.from, executionPayload.feePayer, opts.fee?.gasSettings);
193
+ const feeOptions = await this.completeFeeOptions({
194
+ from: opts.from,
195
+ feePayer: executionPayload.feePayer,
196
+ gasSettings: opts.fee?.gasSettings
197
+ });
153
198
  const limits = getGasLimits(simulationResults, opts.fee?.estimatedGasPadding);
154
199
  printGasEstimates(feeOptions, limits, this.userLog);
155
200
  }
@@ -157,44 +202,48 @@ export class CLIWallet extends BaseWallet {
157
202
  }
158
203
  /**
159
204
  * Uses a stub account for kernelless simulation, bypassing real account authorization.
160
- * Falls through to the standard entrypoint path for SignerlessAccount (ZERO address).
205
+ * Uses DefaultEntrypoint directly for NO_FROM transactions.
161
206
  */ async simulateViaEntrypoint(executionPayload, opts) {
162
- const { from, feeOptions, scopes } = opts;
207
+ const { from, feeOptions, additionalScopes, sendMessagesAs } = opts;
208
+ const scopes = this.scopesFrom(from, additionalScopes);
209
+ const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
210
+ const finalExecutionPayload = feeExecutionPayload ? mergeExecutionPayloads([
211
+ feeExecutionPayload,
212
+ executionPayload
213
+ ]) : executionPayload;
214
+ const chainInfo = await this.getChainInfo();
163
215
  let overrides;
164
- let fromAccount;
165
- if (!from.equals(AztecAddress.ZERO)) {
166
- const { account, instance, artifact } = await this.getFakeAccountDataFor(from);
167
- fromAccount = account;
216
+ let txRequest;
217
+ if (from === NO_FROM) {
218
+ const entrypoint = new DefaultEntrypoint();
219
+ txRequest = await entrypoint.createTxExecutionRequest(finalExecutionPayload, feeOptions.gasSettings, chainInfo);
220
+ } else {
221
+ const { account, instance } = await this.getFakeAccountDataFor(from);
168
222
  overrides = {
169
223
  contracts: {
170
224
  [from.toString()]: {
171
- instance,
172
- artifact
225
+ instance
173
226
  }
174
227
  }
175
228
  };
176
- } else {
177
- fromAccount = await this.getAccountFromAddress(from);
229
+ const executionOptions = {
230
+ txNonce: Fr.random(),
231
+ cancellable: this.cancellableTransactions,
232
+ // If from is an address, feeOptions include the way the account contract should handle the fee payment
233
+ feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions
234
+ };
235
+ txRequest = await account.createTxExecutionRequest(finalExecutionPayload, feeOptions.gasSettings, chainInfo, executionOptions);
178
236
  }
179
- const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
180
- const executionOptions = {
181
- txNonce: Fr.random(),
182
- cancellable: this.cancellableTransactions,
183
- feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions
184
- };
185
- const finalExecutionPayload = feeExecutionPayload ? mergeExecutionPayloads([
186
- feeExecutionPayload,
187
- executionPayload
188
- ]) : executionPayload;
189
- const chainInfo = await this.getChainInfo();
190
- const txRequest = await fromAccount.createTxExecutionRequest(finalExecutionPayload, feeOptions.gasSettings, chainInfo, executionOptions);
191
- return this.pxe.simulateTx(txRequest, {
237
+ const result = await this.pxe.simulateTx(txRequest, {
192
238
  simulatePublic: true,
193
239
  skipFeeEnforcement: true,
194
240
  skipTxValidation: true,
195
241
  overrides,
196
- scopes
242
+ scopes,
243
+ senderForTags: this.senderForTagsFrom(from, sendMessagesAs)
197
244
  });
245
+ const appCallOffset = await this.computeAppCallOffset(from, feeOptions);
246
+ return TxSimulationResultWithAppOffset.fromResultAndOffset(result, appCallOffset);
198
247
  }
199
248
  // Exposed because of the `aztec-wallet get-tx` command. It has been decided that it's fine to keep around because
200
249
  // 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.b6e433891",
3
+ "version": "0.0.1-commit.b9865e97",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/cmds/index.js",
@@ -19,7 +19,7 @@
19
19
  "scripts": {
20
20
  "start": "node --no-warnings ./dest/bin",
21
21
  "start:debug": "node --inspect=0.0.0.0:9221 --no-warnings ./dest/bin",
22
- "dev": "LOG_LEVEL=debug && node ./dest/bin",
22
+ "dev": "LOG_LEVEL=\"debug; info: json-rpc, simulator\" node ./dest/bin",
23
23
  "build": "yarn clean && ../scripts/tsc.sh",
24
24
  "build:dev": "../scripts/tsc.sh --watch",
25
25
  "clean": "rm -rf ./dest .tsbuildinfo",
@@ -67,19 +67,20 @@
67
67
  ]
68
68
  },
69
69
  "dependencies": {
70
- "@aztec/accounts": "0.0.1-commit.b6e433891",
71
- "@aztec/aztec.js": "0.0.1-commit.b6e433891",
72
- "@aztec/bb.js": "0.0.1-commit.b6e433891",
73
- "@aztec/cli": "0.0.1-commit.b6e433891",
74
- "@aztec/entrypoints": "0.0.1-commit.b6e433891",
75
- "@aztec/ethereum": "0.0.1-commit.b6e433891",
76
- "@aztec/foundation": "0.0.1-commit.b6e433891",
77
- "@aztec/kv-store": "0.0.1-commit.b6e433891",
78
- "@aztec/noir-contracts.js": "0.0.1-commit.b6e433891",
79
- "@aztec/noir-noirc_abi": "0.0.1-commit.b6e433891",
80
- "@aztec/pxe": "0.0.1-commit.b6e433891",
81
- "@aztec/stdlib": "0.0.1-commit.b6e433891",
82
- "@aztec/wallet-sdk": "0.0.1-commit.b6e433891",
70
+ "@aztec/accounts": "0.0.1-commit.b9865e97",
71
+ "@aztec/aztec.js": "0.0.1-commit.b9865e97",
72
+ "@aztec/bb.js": "0.0.1-commit.b9865e97",
73
+ "@aztec/cli": "0.0.1-commit.b9865e97",
74
+ "@aztec/entrypoints": "0.0.1-commit.b9865e97",
75
+ "@aztec/ethereum": "0.0.1-commit.b9865e97",
76
+ "@aztec/foundation": "0.0.1-commit.b9865e97",
77
+ "@aztec/kv-store": "0.0.1-commit.b9865e97",
78
+ "@aztec/noir-contracts.js": "0.0.1-commit.b9865e97",
79
+ "@aztec/noir-noirc_abi": "0.0.1-commit.b9865e97",
80
+ "@aztec/pxe": "0.0.1-commit.b9865e97",
81
+ "@aztec/standard-contracts": "0.0.1-commit.b9865e97",
82
+ "@aztec/stdlib": "0.0.1-commit.b9865e97",
83
+ "@aztec/wallet-sdk": "0.0.1-commit.b9865e97",
83
84
  "commander": "^12.1.0",
84
85
  "inquirer": "^10.1.8",
85
86
  "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,5 +1,5 @@
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';
@@ -33,7 +33,7 @@ export async function checkTx(
33
33
  // dependency when dropping PXE JSON RPC Server.
34
34
 
35
35
  async function inspectTx(wallet: CLIWallet, aztecNode: AztecNode, txHash: TxHash, log: LogFn) {
36
- const [receipt, effectsInBlock] = await Promise.all([aztecNode.getTxReceipt(txHash), aztecNode.getTxEffect(txHash)]);
36
+ const receipt = await aztecNode.getTxReceipt(txHash, { includeTxEffect: true });
37
37
  // Base tx data
38
38
  log(`Tx ${txHash.toString()}`);
39
39
  log(` Status: ${receipt.status}`);
@@ -44,11 +44,11 @@ async function inspectTx(wallet: CLIWallet, aztecNode: AztecNode, txHash: TxHash
44
44
  log(` Error: ${receipt.error}`);
45
45
  }
46
46
 
47
- if (!effectsInBlock) {
47
+ if (!receipt.isMined() || !receipt.txEffect) {
48
48
  return;
49
49
  }
50
50
 
51
- const effects = effectsInBlock.data;
51
+ const effects = receipt.txEffect;
52
52
  const artifactMap = await getKnownArtifacts(wallet);
53
53
 
54
54
  log(` Block: ${receipt.blockNumber} (${receipt.blockHash?.toString()})`);
@@ -87,12 +87,13 @@ async function inspectTx(wallet: CLIWallet, aztecNode: AztecNode, txHash: TxHash
87
87
  // Nullifiers
88
88
  const nullifierCount = effects.nullifiers.length;
89
89
  const { deployNullifiers, initNullifiers, classNullifiers } = await getKnownNullifiers(wallet, artifactMap);
90
+ const accounts = (await wallet.getAccounts()).map(a => a.item);
90
91
  if (nullifierCount > 0) {
91
92
  log(' Nullifiers:');
92
93
  for (const nullifier of effects.nullifiers) {
93
94
  const deployed = deployNullifiers[nullifier.toString()];
94
95
  const note = deployed
95
- ? (await wallet.getNotes({ siloedNullifier: nullifier, contractAddress: deployed, scopes: 'ALL_SCOPES' }))[0]
96
+ ? (await wallet.getNotes({ siloedNullifier: nullifier, contractAddress: deployed, scopes: accounts }))[0]
96
97
  : undefined;
97
98
  const initialized = initNullifiers[nullifier.toString()];
98
99
  const registered = classNullifiers[nullifier.toString()];
@@ -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,6 +85,7 @@ 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
90
  const sim = await deployMethod.simulate({
87
91
  ...deployAccountOpts,
@@ -121,19 +125,24 @@ export async function createAccount(
121
125
  }
122
126
  : undefined,
123
127
  };
128
+
129
+ ({ txHash } = await deployMethod.send({ ...sendOpts, wait: NO_WAIT }));
130
+ const localTimeMs = performance.now() - localStart;
131
+
124
132
  if (wait) {
125
- const { receipt } = await deployMethod.send({
126
- ...sendOpts,
127
- wait: { timeout: DEFAULT_TX_TIMEOUT_S, returnReceipt: true },
128
- });
129
- txReceipt = receipt;
130
- txHash = receipt.txHash;
133
+ const nodeStart = performance.now();
134
+ txReceipt = await waitForTx(aztecNode, txHash, { timeout: DEFAULT_TX_TIMEOUT_S, waitForStatus });
135
+ const nodeTimeMs = performance.now() - nodeStart;
136
+
131
137
  out.txReceipt = {
132
138
  status: txReceipt.status,
133
139
  transactionFee: txReceipt.transactionFee,
134
140
  };
135
- } else {
136
- ({ txHash } = await deployMethod.send({ ...sendOpts, wait: NO_WAIT }));
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
+ }
137
146
  }
138
147
  debugLogger.debug(`Account contract tx sent with hash ${txHash.toString()}`);
139
148
  out.txHash = txHash;
@@ -151,5 +160,5 @@ export async function createAccount(
151
160
  }
152
161
  }
153
162
 
154
- return { alias, address, secretKey, salt };
163
+ return { alias, address, secretKey, salt: instanceSalt };
155
164
  }
@@ -1,13 +1,15 @@
1
- import { AztecAddress } from '@aztec/aztec.js/addresses';
1
+ import { NO_FROM } from '@aztec/aztec.js/account';
2
+ import type { 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,10 +31,12 @@ 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,
35
38
  log: LogFn,
39
+ universal?: boolean,
36
40
  ) {
37
41
  const out: Record<string, any> = {};
38
42
  salt ??= Fr.random();
@@ -42,12 +46,7 @@ export async function deploy(
42
46
 
43
47
  // TODO(#12081): Add contractArtifact.noirVersion and check here (via Noir.lock)?
44
48
 
45
- const contractDeployer = new ContractDeployer(
46
- contractArtifact,
47
- wallet,
48
- publicKeys ?? PublicKeys.default(),
49
- initializer,
50
- );
49
+ const contractDeployer = new ContractDeployer(contractArtifact, wallet, initializer);
51
50
 
52
51
  let args = [];
53
52
  if (rawArgs.length > 0) {
@@ -59,19 +58,22 @@ export async function deploy(
59
58
  debugLogger.debug(`Encoded arguments: ${args.join(', ')}`);
60
59
  }
61
60
 
62
- const deploy = contractDeployer.deploy(...args);
61
+ const deployInteraction = contractDeployer.deploy(args, {
62
+ salt,
63
+ publicKeys: publicKeys ?? PublicKeys.default(),
64
+ ...(universal ? { universalDeploy: true as const } : {}),
65
+ });
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,
67
- contractAddressSalt: salt,
68
- universalDeploy: !deployer,
69
+ from: deployer ?? NO_FROM,
69
70
  skipClassPublication,
70
71
  skipInitialization,
71
72
  skipInstancePublication,
72
73
  };
73
74
 
74
- const sim = await deploy.simulate({
75
+ const localStart = performance.now();
76
+ const sim = await deployInteraction.simulate({
75
77
  ...deployOpts,
76
78
  fee: { ...deployOpts.fee, estimateGas: true },
77
79
  });
@@ -97,48 +99,51 @@ export async function deploy(
97
99
  printProfileResult(stats, log);
98
100
  }
99
101
 
100
- const { address, partialAddress } = deploy;
101
- const instance = await deploy.getInstance();
102
+ const instance = await deployInteraction.getInstance();
103
+ const address = instance.address;
104
+ const partialAddress = await deployInteraction.getPartialAddress();
105
+
106
+ const { txHash } = await deployInteraction.send({ ...deployOpts, wait: NO_WAIT });
107
+ const localTimeMs = performance.now() - localStart;
108
+ debugLogger.debug(`Deploy tx sent with hash ${txHash.toString()}`);
109
+ out.hash = txHash;
102
110
 
103
111
  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;
112
+ const nodeStart = performance.now();
113
+ const receipt = await waitForTx(node, txHash, { timeout, waitForStatus });
114
+ const nodeTimeMs = performance.now() - nodeStart;
108
115
 
109
116
  if (!json) {
110
- log(`Contract deployed at ${address?.toString()}`);
111
- log(`Contract partial address ${(await partialAddress)?.toString()}`);
117
+ log(`Contract deployed at ${address.toString()}`);
118
+ log(`Contract partial address ${partialAddress.toString()}`);
112
119
  log(`Contract init hash ${instance.initializationHash.toString()}`);
113
120
  log(`Deployment tx hash: ${txHash.toString()}`);
114
121
  log(`Deployment salt: ${salt.toString()}`);
115
122
  log(`Deployer: ${instance.deployer.toString()}`);
116
123
  log(`Transaction fee: ${receipt.transactionFee?.toString()}`);
124
+ log(` Local processing time: ${(localTimeMs / 1000).toFixed(1)}s`);
125
+ log(` Node inclusion time: ${(nodeTimeMs / 1000).toFixed(1)}s`);
117
126
  } else {
118
127
  out.contract = {
119
- address: address?.toString(),
120
- partialAddress: (await partialAddress)?.toString(),
128
+ address: address.toString(),
129
+ partialAddress: partialAddress.toString(),
121
130
  initializationHash: instance.initializationHash.toString(),
122
131
  salt: salt.toString(),
123
132
  transactionFee: receipt.transactionFee?.toString(),
124
133
  };
125
134
  }
126
135
  } 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
136
  if (!json) {
132
- log(`Contract deployed at ${address?.toString()}`);
133
- log(`Contract partial address ${(await partialAddress)?.toString()}`);
137
+ log(`Contract deployed at ${address.toString()}`);
138
+ log(`Contract partial address ${partialAddress.toString()}`);
134
139
  log(`Contract init hash ${instance.initializationHash.toString()}`);
135
140
  log(`Deployment tx hash: ${txHash.toString()}`);
136
141
  log(`Deployment salt: ${salt.toString()}`);
137
142
  log(`Deployer: ${instance.deployer.toString()}`);
138
143
  } else {
139
144
  out.contract = {
140
- address: address?.toString(),
141
- partialAddress: (await partialAddress)?.toString(),
145
+ address: address.toString(),
146
+ partialAddress: partialAddress.toString(),
142
147
  initializationHash: instance.initializationHash.toString(),
143
148
  salt: salt.toString(),
144
149
  };
@@ -148,5 +153,5 @@ export async function deploy(
148
153
  if (json) {
149
154
  log(prettyPrintJSON(out));
150
155
  }
151
- return deploy.address;
156
+ return await deployInteraction.getAddress();
152
157
  }