@aztec/cli-wallet 0.0.1-commit.42ee6df9b → 0.0.1-commit.431c48d

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 (49) hide show
  1. package/dest/bin/index.js +1 -1
  2. package/dest/cmds/check_tx.js +13 -12
  3. package/dest/cmds/create_account.d.ts +4 -2
  4. package/dest/cmds/create_account.d.ts.map +1 -1
  5. package/dest/cmds/create_account.js +26 -10
  6. package/dest/cmds/deploy.d.ts +3 -3
  7. package/dest/cmds/deploy.d.ts.map +1 -1
  8. package/dest/cmds/deploy.js +23 -21
  9. package/dest/cmds/deploy_account.js +4 -7
  10. package/dest/cmds/import_test_accounts.d.ts +1 -1
  11. package/dest/cmds/import_test_accounts.d.ts.map +1 -1
  12. package/dest/cmds/import_test_accounts.js +2 -1
  13. package/dest/cmds/index.d.ts +1 -1
  14. package/dest/cmds/index.d.ts.map +1 -1
  15. package/dest/cmds/index.js +10 -9
  16. package/dest/cmds/send.js +3 -6
  17. package/dest/cmds/simulate.d.ts +1 -1
  18. package/dest/cmds/simulate.d.ts.map +1 -1
  19. package/dest/cmds/simulate.js +2 -1
  20. package/dest/storage/wallet_db.d.ts +7 -4
  21. package/dest/storage/wallet_db.d.ts.map +1 -1
  22. package/dest/storage/wallet_db.js +15 -1
  23. package/dest/utils/constants.d.ts +2 -2
  24. package/dest/utils/constants.d.ts.map +1 -1
  25. package/dest/utils/constants.js +1 -0
  26. package/dest/utils/options/fees.d.ts +2 -1
  27. package/dest/utils/options/fees.d.ts.map +1 -1
  28. package/dest/utils/options/fees.js +28 -5
  29. package/dest/utils/options/options.d.ts +2 -2
  30. package/dest/utils/options/options.d.ts.map +1 -1
  31. package/dest/utils/options/options.js +5 -5
  32. package/dest/utils/wallet.d.ts +31 -7
  33. package/dest/utils/wallet.d.ts.map +1 -1
  34. package/dest/utils/wallet.js +142 -69
  35. package/package.json +16 -15
  36. package/src/bin/index.ts +1 -1
  37. package/src/cmds/check_tx.ts +14 -13
  38. package/src/cmds/create_account.ts +27 -15
  39. package/src/cmds/deploy.ts +22 -23
  40. package/src/cmds/deploy_account.ts +4 -4
  41. package/src/cmds/import_test_accounts.ts +12 -1
  42. package/src/cmds/index.ts +14 -11
  43. package/src/cmds/send.ts +3 -3
  44. package/src/cmds/simulate.ts +2 -1
  45. package/src/storage/wallet_db.ts +24 -2
  46. package/src/utils/constants.ts +7 -1
  47. package/src/utils/options/fees.ts +29 -5
  48. package/src/utils/options/options.ts +5 -5
  49. package/src/utils/wallet.ts +183 -91
@@ -30,7 +30,7 @@ export async function deployAccount(
30
30
  ) {
31
31
  const out: Record<string, any> = {};
32
32
 
33
- const account = await wallet.createOrRetrieveAccount(address);
33
+ const account = await wallet.retrieveAccount(address);
34
34
  const { partialAddress, publicKeys } = await account.getCompleteAddress();
35
35
  const { initializationHash, salt } = account.getInstance();
36
36
 
@@ -68,10 +68,10 @@ export async function deployAccount(
68
68
  const deployMethod = await account.getDeployMethod();
69
69
  const sim = await deployMethod.simulate({
70
70
  ...deployAccountOpts,
71
- fee: { ...deployAccountOpts.fee, estimateGas: true },
71
+ includeMetadata: true,
72
72
  });
73
- // estimateGas: true guarantees these fields are present
74
- const estimatedGas = sim.estimatedGas!;
73
+ // includeMetadata: true guarantees these fields are present
74
+ const estimatedGas = await wallet.estimateGasLimits(sim.gasUsed!);
75
75
  const stats = sim.stats!;
76
76
 
77
77
  if (feeOpts.estimateOnly) {
@@ -16,7 +16,18 @@ export async function importTestAccounts(wallet: CLIWallet, db: WalletDB, json:
16
16
  const secret = testAccounts[i].secret;
17
17
  const salt = new Fr(account.salt);
18
18
  const address = account.address;
19
- await db.storeAccount(address, { type: 'schnorr', secretKey: secret, salt, alias, publicKey: undefined }, log);
19
+ await db.storeAccount(
20
+ address,
21
+ {
22
+ type: 'schnorr_initializerless',
23
+ signingKey: account.signingKey,
24
+ secretKey: secret,
25
+ salt,
26
+ alias,
27
+ publicKey: undefined,
28
+ },
29
+ log,
30
+ );
20
31
 
21
32
  if (json) {
22
33
  out[alias] = {
package/src/cmds/index.ts CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  ETHEREUM_HOSTS,
5
5
  PRIVATE_KEY,
6
6
  addOptions,
7
- createSecretKeyOption,
7
+ createSigningKeyOption,
8
8
  l1ChainIdOption,
9
9
  parseBigint,
10
10
  parseFieldFromHexString,
@@ -24,7 +24,7 @@ import {
24
24
  ARTIFACT_DESCRIPTION,
25
25
  CLIFeeArgs,
26
26
  aliasedAddressParser,
27
- aliasedSecretKeyParser,
27
+ aliasedSigningKeyParser,
28
28
  aliasedTxHashParser,
29
29
  artifactPathFromPromiseOrAlias,
30
30
  artifactPathParser,
@@ -96,8 +96,8 @@ export function injectCommands(
96
96
  'Public key that identifies a private signing key stored outside of the wallet. Used for ECDSA SSH accounts over the secp256r1 curve.',
97
97
  )
98
98
  .addOption(
99
- createSecretKeyOption('Secret key for account. Uses random by default.', false, sk =>
100
- aliasedSecretKeyParser(sk, db),
99
+ createSigningKeyOption('Signing key for account. Uses random by default.', false, sk =>
100
+ aliasedSigningKeyParser(sk, db),
101
101
  ).conflicts('public-key'),
102
102
  )
103
103
  .addOption(createAliasOption('Alias for the account. Used for easy reference in subsequent commands.', !db))
@@ -124,7 +124,7 @@ export function injectCommands(
124
124
  const {
125
125
  type,
126
126
  from: parsedFromAddress,
127
- secretKey,
127
+ signingKey,
128
128
  salt,
129
129
  wait,
130
130
  waitForStatus: waitForStatusStr,
@@ -156,7 +156,7 @@ export function injectCommands(
156
156
  wallet,
157
157
  node,
158
158
  type,
159
- secretKey,
159
+ signingKey,
160
160
  salt,
161
161
  publicKey,
162
162
  alias,
@@ -174,8 +174,8 @@ export function injectCommands(
174
174
  log,
175
175
  );
176
176
  if (db) {
177
- const { address, alias, secretKey, salt } = accountCreationResult;
178
- await db.storeAccount(address, { type, secretKey, salt, alias, publicKey }, log);
177
+ const { address, alias, signingKey, secretKey, salt } = accountCreationResult;
178
+ await db.storeAccount(address, { type, signingKey, secretKey, salt, alias, publicKey }, log);
179
179
  }
180
180
  });
181
181
 
@@ -297,12 +297,12 @@ export function injectCommands(
297
297
  const { wallet, node } = walletAndNodeWrapper;
298
298
  const artifactPath = await artifactPathPromise;
299
299
 
300
- debugLogger.info(`Using wallet with address ${parsedFromAddress.toString()}`);
300
+ debugLogger.info(`Using wallet with address ${parsedFromAddress?.toString() ?? '<none>'}`);
301
301
 
302
302
  const address = await deploy(
303
303
  wallet,
304
304
  node,
305
- universal ? undefined : parsedFromAddress,
305
+ parsedFromAddress,
306
306
  artifactPath,
307
307
  json,
308
308
  publicKey,
@@ -319,6 +319,7 @@ export function injectCommands(
319
319
  timeout,
320
320
  debugLogger,
321
321
  log,
322
+ universal,
322
323
  );
323
324
  if (db && address) {
324
325
  await db.storeContract(address, artifactPath, log, alias);
@@ -398,7 +399,9 @@ export function injectCommands(
398
399
  .addOption(createContractAddressOption(db))
399
400
  .addOption(createArtifactOption(db))
400
401
  .addOption(
401
- createSecretKeyOption("The sender's secret key", !db, sk => aliasedSecretKeyParser(sk, db)).conflicts('account'),
402
+ createSigningKeyOption("The sender's signing key", !db, sk => aliasedSigningKeyParser(sk, db)).conflicts(
403
+ 'account',
404
+ ),
402
405
  )
403
406
  .addOption(createAuthwitnessOption('Authorization witness to use for the simulation', !db, db))
404
407
  .addOption(createAccountOption('Alias or address of the account to simulate from', !db, db))
package/src/cmds/send.ts CHANGED
@@ -42,10 +42,10 @@ export async function send(
42
42
  const localStart = performance.now();
43
43
  const sim = await call.simulate({
44
44
  ...sendOptions,
45
- fee: { ...sendOptions.fee, estimateGas: true },
45
+ includeMetadata: true,
46
46
  });
47
- // estimateGas: true guarantees these fields are present
48
- const estimatedGas = sim.estimatedGas!;
47
+ // includeMetadata: true guarantees these fields are present
48
+ const estimatedGas = await wallet.estimateGasLimits(sim.gasUsed!);
49
49
  const stats = sim.stats!;
50
50
 
51
51
  if (feeOpts.estimateOnly) {
@@ -44,7 +44,8 @@ export async function simulate(
44
44
  if (!metadata.instance) {
45
45
  return undefined;
46
46
  }
47
- const artifact = await wallet.getContractArtifact(metadata.instance.currentContractClassId);
47
+ const classId = metadata.updatedContractClassId ?? metadata.instance.originalContractClassId;
48
+ const artifact = await wallet.getContractArtifact(classId);
48
49
  return artifact;
49
50
  },
50
51
  log,
@@ -1,4 +1,5 @@
1
1
  import { Fr } from '@aztec/foundation/curves/bn254';
2
+ import { GrumpkinScalar } from '@aztec/foundation/curves/grumpkin';
2
3
  import type { LogFn } from '@aztec/foundation/log';
3
4
  import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
4
5
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
@@ -88,13 +89,28 @@ export class WalletDB {
88
89
  address: AztecAddress,
89
90
  {
90
91
  type,
92
+ signingKey,
91
93
  secretKey,
92
94
  salt,
93
95
  alias,
94
96
  publicKey,
95
- }: { type: AccountType; secretKey: Fr; salt: Fr; alias: string | undefined; publicKey: string | undefined },
97
+ }: {
98
+ type: AccountType;
99
+ signingKey?: GrumpkinScalar;
100
+ secretKey?: Fr;
101
+ salt: Fr;
102
+ alias: string | undefined;
103
+ publicKey: string | undefined;
104
+ },
96
105
  log: LogFn,
97
106
  ) {
107
+ // Even though the privacy secret key is sometimes derived from the signing key, we store it in the database
108
+ // regardless as that is not always the case. Local-key accounts also store their signing key, while external-key
109
+ // accounts such as SSH store only the privacy secret.
110
+ if (!secretKey) {
111
+ throw new Error('Cannot store account without a secret key');
112
+ }
113
+
98
114
  let publicSigningKey: Buffer | undefined;
99
115
  if (type === 'ecdsasecp256r1ssh' && publicKey) {
100
116
  publicSigningKey = extractECDSAPublicKeyFromBase64String(publicKey);
@@ -106,6 +122,9 @@ export class WalletDB {
106
122
  }
107
123
  await this.#accounts.set(`${address.toString()}:type`, Buffer.from(type));
108
124
  await this.#accounts.set(`${address.toString()}:sk`, secretKey.toBuffer());
125
+ if (signingKey) {
126
+ await this.#accounts.set(`${address.toString()}:signing`, signingKey.toBuffer());
127
+ }
109
128
  await this.#accounts.set(`${address.toString()}:salt`, salt.toBuffer());
110
129
  if (publicSigningKey) {
111
130
  await this.#accounts.set(`${address.toString()}:publicSigningKey`, publicSigningKey);
@@ -226,10 +245,13 @@ export class WalletDB {
226
245
  if (!secretKeyBuffer) {
227
246
  throw new Error(`Could not find ${address}:sk. Account "${address.toString}" does not exist on this wallet.`);
228
247
  }
248
+ const signingKeyBuffer = await this.#accounts.getAsync(`${address.toString()}:signing`);
229
249
  const secretKey = Fr.fromBuffer(secretKeyBuffer);
250
+ // External-key accounts (e.g. SSH) store no signing key.
251
+ const signingKey = signingKeyBuffer ? GrumpkinScalar.fromBuffer(signingKeyBuffer) : undefined;
230
252
  const salt = Fr.fromBuffer((await this.#accounts.getAsync(`${address.toString()}:salt`))!);
231
253
  const type = (await this.#accounts.getAsync(`${address.toString()}:type`))!.toString('utf8') as AccountType;
232
- return { address, secretKey, salt, type };
254
+ return { address, signingKey, secretKey, salt, type };
233
255
  }
234
256
 
235
257
  async storeAlias(type: AliasType, key: string, value: Buffer, log: LogFn) {
@@ -1,4 +1,10 @@
1
1
  export const MIN_FEE_PADDING = 0.5;
2
2
 
3
- export const AccountTypes = ['schnorr', 'ecdsasecp256r1', 'ecdsasecp256r1ssh', 'ecdsasecp256k1'] as const;
3
+ export const AccountTypes = [
4
+ 'schnorr',
5
+ 'schnorr_initializerless',
6
+ 'ecdsasecp256r1',
7
+ 'ecdsasecp256r1ssh',
8
+ 'ecdsasecp256k1',
9
+ ] as const;
4
10
  export type AccountType = (typeof AccountTypes)[number];
@@ -5,7 +5,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
5
5
  import type { LogFn } from '@aztec/foundation/log';
6
6
  import type { FieldsOf } from '@aztec/foundation/types';
7
7
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
8
- import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
8
+ import { Gas, GasFees, GasSettings, ManaUsageEstimate } from '@aztec/stdlib/gas';
9
9
  import type { FeeOptions } from '@aztec/wallet-sdk/base-wallet';
10
10
 
11
11
  import { Option } from 'commander';
@@ -137,7 +137,7 @@ export function parsePaymentMethod(
137
137
  if (!parsed.asset) {
138
138
  throw new Error('Missing "asset" in payment option');
139
139
  }
140
- return AztecAddress.fromString(parsed.asset);
140
+ return AztecAddress.fromStringUnsafe(parsed.asset);
141
141
  };
142
142
 
143
143
  return async (wallet: Wallet, from: AztecAddress, gasSettings: GasSettings) => {
@@ -257,8 +257,11 @@ export class CLIFeeArgs {
257
257
  ) {}
258
258
 
259
259
  async toUserFeeOptions(node: AztecNode, wallet: Wallet, from: AztecAddress): Promise<ParsedFeeOptions> {
260
- const maxFeesPerGas = (await node.getCurrentMinFees()).mul(1 + MIN_FEE_PADDING);
261
- const gasSettings = GasSettings.default({ ...this.gasSettings, maxFeesPerGas });
260
+ const minFees = await this.getMinFees(node);
261
+ const maxFeesPerGas = minFees.mul(1 + MIN_FEE_PADDING);
262
+ const { txsLimits } = await node.getNodeInfo();
263
+ const gasLimits = this.gasSettings.gasLimits ?? Gas.from(txsLimits.gas);
264
+ const gasSettings = GasSettings.fallback({ ...this.gasSettings, gasLimits, maxFeesPerGas });
262
265
  const paymentMethod = await this.paymentMethod(wallet, from, gasSettings);
263
266
  return {
264
267
  paymentMethod,
@@ -266,6 +269,27 @@ export class CLIFeeArgs {
266
269
  };
267
270
  }
268
271
 
272
+ /**
273
+ * Returns the worst-case min fee across predicted future slots.
274
+ * Falls back to getCurrentMinFees if the node doesn't support getPredictedMinFees.
275
+ */
276
+ private async getMinFees(node: AztecNode): Promise<GasFees> {
277
+ try {
278
+ const predicted = await node.getPredictedMinFees(ManaUsageEstimate.Limit);
279
+ if (predicted.length === 0) {
280
+ return node.getCurrentMinFees();
281
+ }
282
+ return predicted.reduce((worst, fees) => (fees.feePerL2Gas > worst.feePerL2Gas ? fees : worst));
283
+ } catch (err: any) {
284
+ // Fallback for old nodes that don't support getPredictedMinFees.
285
+ // Only fall back on method-not-found errors (JSON-RPC code -32601); rethrow others.
286
+ if (err?.cause?.code === -32601 || err?.message?.includes('Method not found')) {
287
+ return node.getCurrentMinFees();
288
+ }
289
+ throw err;
290
+ }
291
+ }
292
+
269
293
  static parse(args: RawCliFeeArgs, log: LogFn, db?: WalletDB): CLIFeeArgs {
270
294
  const estimateOnly = !!args.estimateGasOnly;
271
295
  return new CLIFeeArgs(
@@ -296,7 +320,7 @@ function formatGasEstimate(estimate: Pick<GasSettings, 'gasLimits' | 'teardownGa
296
320
  }
297
321
 
298
322
  function getEstimatedCost(estimate: Pick<GasSettings, 'gasLimits' | 'teardownGasLimits'>, maxFeesPerGas: GasFees) {
299
- return GasSettings.default({ ...estimate, maxFeesPerGas })
323
+ return GasSettings.fallback({ ...estimate, maxFeesPerGas })
300
324
  .getFeeLimit()
301
325
  .toBigInt();
302
326
  }
@@ -1,5 +1,5 @@
1
1
  import { TxHash } from '@aztec/aztec.js/tx';
2
- import { parseAztecAddress, parseSecretKey, parseTxHash } from '@aztec/cli/utils';
2
+ import { parseAztecAddress, parseSigningKey, parseTxHash } from '@aztec/cli/utils';
3
3
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
4
4
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
5
5
 
@@ -64,13 +64,13 @@ export function aliasedAddressParser(defaultPrefix: AliasType, address: string,
64
64
  }
65
65
  }
66
66
 
67
- export function aliasedSecretKeyParser(sk: string, db?: WalletDB) {
67
+ export function aliasedSigningKeyParser(sk: string, db?: WalletDB) {
68
68
  if (sk.startsWith('0x')) {
69
- return parseSecretKey(sk);
69
+ return parseSigningKey(sk);
70
70
  } else {
71
- const prefixed = `${sk.startsWith('accounts') ? '' : 'accounts'}:${sk.endsWith(':sk') ? sk : `${sk}:sk`}`;
71
+ const prefixed = `${sk.startsWith('accounts') ? '' : 'accounts'}:${sk.endsWith(':signing') ? sk : `${sk}:signing`}`;
72
72
  const rawSk = db ? db.tryRetrieveAlias(prefixed) : sk;
73
- return parseSecretKey(rawSk);
73
+ return parseSigningKey(rawSk);
74
74
  }
75
75
  }
76
76