@aztec/cli-wallet 0.0.0-test.1 → 0.0.1-commit.017a351

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 (115) hide show
  1. package/README.md +30 -0
  2. package/dest/bin/index.d.ts +2 -1
  3. package/dest/bin/index.js +58 -26
  4. package/dest/cmds/authorize_action.d.ts +4 -3
  5. package/dest/cmds/authorize_action.d.ts.map +1 -1
  6. package/dest/cmds/authorize_action.js +11 -5
  7. package/dest/cmds/bridge_fee_juice.d.ts +4 -4
  8. package/dest/cmds/bridge_fee_juice.d.ts.map +1 -1
  9. package/dest/cmds/bridge_fee_juice.js +10 -8
  10. package/dest/cmds/check_tx.d.ts +5 -3
  11. package/dest/cmds/check_tx.d.ts.map +1 -1
  12. package/dest/cmds/check_tx.js +174 -6
  13. package/dest/cmds/create_account.d.ts +10 -7
  14. package/dest/cmds/create_account.d.ts.map +1 -1
  15. package/dest/cmds/create_account.js +74 -38
  16. package/dest/cmds/create_authwit.d.ts +4 -3
  17. package/dest/cmds/create_authwit.d.ts.map +1 -1
  18. package/dest/cmds/create_authwit.js +6 -6
  19. package/dest/cmds/deploy.d.ts +8 -4
  20. package/dest/cmds/deploy.d.ts.map +1 -1
  21. package/dest/cmds/deploy.js +108 -59
  22. package/dest/cmds/deploy_account.d.ts +7 -8
  23. package/dest/cmds/deploy_account.d.ts.map +1 -1
  24. package/dest/cmds/deploy_account.js +70 -36
  25. package/dest/cmds/get_fee_juice_balance.d.ts +5 -0
  26. package/dest/cmds/get_fee_juice_balance.d.ts.map +1 -0
  27. package/dest/cmds/get_fee_juice_balance.js +27 -0
  28. package/dest/cmds/import_test_accounts.d.ts +3 -3
  29. package/dest/cmds/import_test_accounts.d.ts.map +1 -1
  30. package/dest/cmds/import_test_accounts.js +6 -9
  31. package/dest/cmds/index.d.ts +3 -3
  32. package/dest/cmds/index.d.ts.map +1 -1
  33. package/dest/cmds/index.js +99 -115
  34. package/dest/cmds/profile.d.ts +8 -0
  35. package/dest/cmds/profile.d.ts.map +1 -0
  36. package/dest/cmds/profile.js +28 -0
  37. package/dest/cmds/register_contract.d.ts +7 -3
  38. package/dest/cmds/register_contract.d.ts.map +1 -1
  39. package/dest/cmds/register_contract.js +20 -7
  40. package/dest/cmds/register_sender.d.ts +4 -3
  41. package/dest/cmds/register_sender.d.ts.map +1 -1
  42. package/dest/cmds/send.d.ts +9 -9
  43. package/dest/cmds/send.d.ts.map +1 -1
  44. package/dest/cmds/send.js +54 -27
  45. package/dest/cmds/simulate.d.ts +7 -3
  46. package/dest/cmds/simulate.d.ts.map +1 -1
  47. package/dest/cmds/simulate.js +26 -20
  48. package/dest/storage/wallet_db.d.ts +12 -19
  49. package/dest/storage/wallet_db.d.ts.map +1 -1
  50. package/dest/storage/wallet_db.js +63 -55
  51. package/dest/utils/authorizations.d.ts +6 -0
  52. package/dest/utils/authorizations.d.ts.map +1 -0
  53. package/dest/utils/authorizations.js +28 -0
  54. package/dest/utils/cli_wallet_and_node_wrapper.d.ts +12 -0
  55. package/dest/utils/cli_wallet_and_node_wrapper.d.ts.map +1 -0
  56. package/dest/utils/cli_wallet_and_node_wrapper.js +25 -0
  57. package/dest/utils/constants.d.ts +4 -0
  58. package/dest/utils/constants.d.ts.map +1 -0
  59. package/dest/utils/constants.js +7 -0
  60. package/dest/utils/ecdsa.d.ts +1 -3
  61. package/dest/utils/ecdsa.d.ts.map +1 -1
  62. package/dest/utils/options/fees.d.ts +23 -28
  63. package/dest/utils/options/fees.d.ts.map +1 -1
  64. package/dest/utils/options/fees.js +112 -148
  65. package/dest/utils/options/index.d.ts +1 -1
  66. package/dest/utils/options/options.d.ts +9 -5
  67. package/dest/utils/options/options.d.ts.map +1 -1
  68. package/dest/utils/options/options.js +26 -14
  69. package/dest/utils/profiling.d.ts +5 -0
  70. package/dest/utils/profiling.d.ts.map +1 -0
  71. package/dest/utils/profiling.js +68 -0
  72. package/dest/utils/wallet.d.ts +44 -0
  73. package/dest/utils/wallet.d.ts.map +1 -0
  74. package/dest/utils/wallet.js +263 -0
  75. package/package.json +31 -23
  76. package/src/bin/index.ts +63 -33
  77. package/src/cmds/authorize_action.ts +16 -5
  78. package/src/cmds/bridge_fee_juice.ts +16 -12
  79. package/src/cmds/check_tx.ts +212 -5
  80. package/src/cmds/create_account.ts +89 -45
  81. package/src/cmds/create_authwit.ts +9 -5
  82. package/src/cmds/deploy.ts +115 -71
  83. package/src/cmds/deploy_account.ts +84 -36
  84. package/src/cmds/get_fee_juice_balance.ts +37 -0
  85. package/src/cmds/import_test_accounts.ts +7 -11
  86. package/src/cmds/index.ts +312 -222
  87. package/src/cmds/profile.ts +48 -0
  88. package/src/cmds/register_contract.ts +28 -5
  89. package/src/cmds/register_sender.ts +3 -2
  90. package/src/cmds/send.ts +59 -25
  91. package/src/cmds/simulate.ts +37 -24
  92. package/src/storage/wallet_db.ts +67 -68
  93. package/src/utils/authorizations.ts +51 -0
  94. package/src/utils/cli_wallet_and_node_wrapper.ts +35 -0
  95. package/src/utils/constants.ts +4 -0
  96. package/src/utils/options/fees.ts +169 -210
  97. package/src/utils/options/options.ts +41 -19
  98. package/src/utils/profiling.ts +172 -0
  99. package/src/utils/wallet.ts +330 -0
  100. package/dest/cmds/add_authwit.d.ts +0 -4
  101. package/dest/cmds/add_authwit.d.ts.map +0 -1
  102. package/dest/cmds/add_authwit.js +0 -4
  103. package/dest/cmds/cancel_tx.d.ts +0 -11
  104. package/dest/cmds/cancel_tx.d.ts.map +0 -1
  105. package/dest/cmds/cancel_tx.js +0 -38
  106. package/dest/utils/accounts.d.ts +0 -11
  107. package/dest/utils/accounts.d.ts.map +0 -1
  108. package/dest/utils/accounts.js +0 -87
  109. package/dest/utils/pxe_wrapper.d.ts +0 -10
  110. package/dest/utils/pxe_wrapper.d.ts.map +0 -1
  111. package/dest/utils/pxe_wrapper.js +0 -21
  112. package/src/cmds/add_authwit.ts +0 -13
  113. package/src/cmds/cancel_tx.ts +0 -62
  114. package/src/utils/accounts.ts +0 -102
  115. package/src/utils/pxe_wrapper.ts +0 -26
@@ -0,0 +1,48 @@
1
+ import type { AztecAddress } from '@aztec/aztec.js/addresses';
2
+ import { AuthWitness } from '@aztec/aztec.js/authorization';
3
+ import { Contract } from '@aztec/aztec.js/contracts';
4
+ import type { AztecNode } from '@aztec/aztec.js/node';
5
+ import { prepTx } from '@aztec/cli/utils';
6
+ import type { LogFn } from '@aztec/foundation/log';
7
+ import { serializePrivateExecutionSteps } from '@aztec/stdlib/kernel';
8
+
9
+ import { promises as fs } from 'fs';
10
+ import path from 'path';
11
+
12
+ import type { CLIFeeArgs } from '../utils/options/fees.js';
13
+ import { printProfileResult } from '../utils/profiling.js';
14
+ import type { CLIWallet } from '../utils/wallet.js';
15
+
16
+ export async function profile(
17
+ wallet: CLIWallet,
18
+ node: AztecNode,
19
+ from: AztecAddress,
20
+ functionName: string,
21
+ functionArgsIn: any[],
22
+ contractArtifactPath: string,
23
+ contractAddress: AztecAddress,
24
+ debugOutputPath: string | undefined,
25
+ feeOpts: CLIFeeArgs,
26
+ authWitnesses: AuthWitness[],
27
+ log: LogFn,
28
+ ) {
29
+ const { functionArgs, contractArtifact } = await prepTx(contractArtifactPath, functionName, functionArgsIn, log);
30
+
31
+ const contract = Contract.at(contractAddress, contractArtifact, wallet);
32
+ const call = contract.methods[functionName](...functionArgs);
33
+
34
+ const { paymentMethod, gasSettings } = await feeOpts.toUserFeeOptions(node, wallet, from);
35
+ const result = await call.profile({
36
+ fee: { gasSettings, paymentMethod },
37
+ from,
38
+ profileMode: 'full',
39
+ authWitnesses,
40
+ skipProofGeneration: false,
41
+ });
42
+ printProfileResult(result.stats, log, true, result.executionSteps);
43
+ if (debugOutputPath) {
44
+ const ivcInputsPath = path.join(debugOutputPath, 'ivc-inputs.msgpack');
45
+ log(`Debug output written to ${ivcInputsPath}.`);
46
+ await fs.writeFile(ivcInputsPath, serializePrivateExecutionSteps(result.executionSteps));
47
+ }
48
+ }
@@ -1,20 +1,43 @@
1
- import type { AccountWalletWithSecretKey, AztecAddress, AztecNode } from '@aztec/aztec.js';
1
+ import type { AztecAddress } from '@aztec/aztec.js/addresses';
2
+ import { getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts';
3
+ import { Fr } from '@aztec/aztec.js/fields';
4
+ import { PublicKeys } from '@aztec/aztec.js/keys';
5
+ import type { AztecNode } from '@aztec/aztec.js/node';
6
+ import type { Wallet } from '@aztec/aztec.js/wallet';
2
7
  import { getContractArtifact } from '@aztec/cli/cli-utils';
3
8
  import type { LogFn } from '@aztec/foundation/log';
9
+ import { getAllFunctionAbis, getInitializer } from '@aztec/stdlib/abi';
4
10
 
5
11
  export async function registerContract(
6
- wallet: AccountWalletWithSecretKey,
12
+ wallet: Wallet,
7
13
  node: AztecNode,
8
14
  address: AztecAddress,
9
15
  artifactPath: string,
10
16
  log: LogFn,
17
+ initializer?: string,
18
+ publicKeys?: PublicKeys,
19
+ rawArgs?: any[],
20
+ salt?: Fr,
21
+ deployer?: AztecAddress,
11
22
  ) {
12
23
  const contractArtifact = await getContractArtifact(artifactPath, log);
13
- const contractInstance = await node.getContract(address);
24
+ const hasInitializer = getAllFunctionAbis(contractArtifact).some(fn => fn.isInitializer);
25
+ const constructorArtifact = hasInitializer ? getInitializer(contractArtifact, initializer) : undefined;
26
+ let contractInstance = await node.getContract(address);
14
27
  if (!contractInstance) {
15
- throw new Error(`Contract not found at address: ${address}`);
28
+ log(`Contract not found in the node at ${address}. Computing instance locally...`);
29
+ contractInstance = await getContractInstanceFromInstantiationParams(contractArtifact, {
30
+ constructorArtifact,
31
+ publicKeys: publicKeys ?? PublicKeys.default(),
32
+ constructorArgs: rawArgs,
33
+ salt: salt ?? Fr.ZERO,
34
+ deployer,
35
+ });
16
36
  }
17
- await wallet.registerContract({ instance: contractInstance, artifact: contractArtifact });
37
+ if (!contractInstance.address.equals(address)) {
38
+ throw new Error(`Contract address mismatch: expected ${address}, got ${contractInstance.address}`);
39
+ }
40
+ await wallet.registerContract(contractInstance, contractArtifact);
18
41
  log(`Contract registered: at ${contractInstance.address}`);
19
42
  return contractInstance;
20
43
  }
@@ -1,7 +1,8 @@
1
- import type { AccountWalletWithSecretKey, AztecAddress } from '@aztec/aztec.js';
1
+ import { AztecAddress } from '@aztec/aztec.js/addresses';
2
+ import type { Wallet } from '@aztec/aztec.js/wallet';
2
3
  import type { LogFn } from '@aztec/foundation/log';
3
4
 
4
- export async function registerSender(wallet: AccountWalletWithSecretKey, address: AztecAddress, log: LogFn) {
5
+ export async function registerSender(wallet: Wallet, address: AztecAddress, log: LogFn) {
5
6
  await wallet.registerSender(address);
6
7
  log(`Sender registered: ${address}`);
7
8
  }
package/src/cmds/send.ts CHANGED
@@ -1,62 +1,96 @@
1
- import { type AccountWalletWithSecretKey, type AztecAddress, Contract, Fr } from '@aztec/aztec.js';
1
+ import type { AztecAddress } from '@aztec/aztec.js/addresses';
2
+ import { AuthWitness } from '@aztec/aztec.js/authorization';
3
+ import { Contract, NO_WAIT, type SendInteractionOptions } from '@aztec/aztec.js/contracts';
4
+ import { type AztecNode, waitForTx } from '@aztec/aztec.js/node';
2
5
  import { prepTx } from '@aztec/cli/utils';
3
6
  import type { LogFn } from '@aztec/foundation/log';
4
- import { GasSettings } from '@aztec/stdlib/gas';
7
+ import { TxStatus } from '@aztec/stdlib/tx';
5
8
 
6
- import { type IFeeOpts, printGasEstimates } from '../utils/options/fees.js';
9
+ import { DEFAULT_TX_TIMEOUT_S } from '../utils/cli_wallet_and_node_wrapper.js';
10
+ import { CLIFeeArgs } from '../utils/options/fees.js';
11
+ import { printProfileResult } from '../utils/profiling.js';
12
+ import type { CLIWallet } from '../utils/wallet.js';
7
13
 
8
14
  export async function send(
9
- wallet: AccountWalletWithSecretKey,
15
+ wallet: CLIWallet,
16
+ node: AztecNode,
17
+ from: AztecAddress,
10
18
  functionName: string,
11
19
  functionArgsIn: any[],
12
20
  contractArtifactPath: string,
13
21
  contractAddress: AztecAddress,
14
22
  wait: boolean,
15
23
  cancellable: boolean,
16
- feeOpts: IFeeOpts,
24
+ feeOpts: CLIFeeArgs,
25
+ authWitnesses: AuthWitness[],
26
+ waitForStatus: TxStatus,
27
+ verbose: boolean,
17
28
  log: LogFn,
18
29
  ) {
19
30
  const { functionArgs, contractArtifact } = await prepTx(contractArtifactPath, functionName, functionArgsIn, log);
20
31
 
21
- const contract = await Contract.at(contractAddress, contractArtifact, wallet);
32
+ const contract = Contract.at(contractAddress, contractArtifact, wallet);
22
33
  const call = contract.methods[functionName](...functionArgs);
23
34
 
24
- const gasLimits = await call.estimateGas({ ...(await feeOpts.toSendOpts(wallet)) });
25
- printGasEstimates(feeOpts, gasLimits, log);
35
+ const { paymentMethod, gasSettings } = await feeOpts.toUserFeeOptions(node, wallet, from);
36
+ const sendOptions: SendInteractionOptions = {
37
+ fee: { paymentMethod, gasSettings },
38
+ from,
39
+ authWitnesses,
40
+ };
41
+
42
+ const localStart = performance.now();
43
+ const sim = await call.simulate({
44
+ ...sendOptions,
45
+ fee: { ...sendOptions.fee, estimateGas: true },
46
+ });
47
+ // estimateGas: true guarantees these fields are present
48
+ const estimatedGas = sim.estimatedGas!;
49
+ const stats = sim.stats!;
26
50
 
27
51
  if (feeOpts.estimateOnly) {
28
52
  return;
29
53
  }
30
54
 
31
- const nonce = Fr.random();
32
- const tx = call.send({ ...(await feeOpts.toSendOpts(wallet)), nonce, cancellable });
33
- const txHash = await tx.getTxHash();
55
+ if (verbose) {
56
+ printProfileResult(stats!, log);
57
+ }
58
+
59
+ const { txHash } = await call.send({
60
+ ...sendOptions,
61
+ fee: { ...sendOptions.fee, gasSettings: estimatedGas },
62
+ wait: NO_WAIT,
63
+ });
64
+ const localTimeMs = performance.now() - localStart;
65
+
34
66
  log(`\nTransaction hash: ${txHash.toString()}`);
67
+
35
68
  if (wait) {
36
69
  try {
37
- await tx.wait();
38
-
39
- log('Transaction has been mined');
70
+ const nodeStart = performance.now();
71
+ const receipt = await waitForTx(node, txHash, { timeout: DEFAULT_TX_TIMEOUT_S, waitForStatus });
72
+ const nodeTimeMs = performance.now() - nodeStart;
40
73
 
41
- const receipt = await tx.getReceipt();
74
+ const statusLabel = waitForStatus === TxStatus.PROPOSED ? 'proposed' : 'checkpointed';
75
+ log(`Transaction has been ${statusLabel}`);
42
76
  log(` Tx fee: ${receipt.transactionFee}`);
43
77
  log(` Status: ${receipt.status}`);
44
78
  log(` Block number: ${receipt.blockNumber}`);
45
79
  log(` Block hash: ${receipt.blockHash?.toString()}`);
80
+ log(` Local processing time: ${(localTimeMs / 1000).toFixed(1)}s`);
81
+ log(` Node inclusion time: ${(nodeTimeMs / 1000).toFixed(1)}s`);
82
+
83
+ return {
84
+ txHash,
85
+ };
46
86
  } catch (err: any) {
47
87
  log(`Transaction failed\n ${err.message}`);
88
+ throw err;
48
89
  }
49
90
  } else {
50
91
  log('Transaction pending. Check status with check-tx');
92
+ return {
93
+ txHash,
94
+ };
51
95
  }
52
- const gasSettings = GasSettings.from({
53
- ...feeOpts.gasSettings,
54
- ...gasLimits,
55
- });
56
- return {
57
- txHash,
58
- nonce,
59
- cancellable,
60
- gasSettings,
61
- };
62
96
  }
@@ -1,42 +1,55 @@
1
- import { type AccountWalletWithSecretKey, type AztecAddress, Contract, type ProfileResult } from '@aztec/aztec.js';
1
+ import type { AztecAddress } from '@aztec/aztec.js/addresses';
2
+ import { AuthWitness } from '@aztec/aztec.js/authorization';
3
+ import { Contract } from '@aztec/aztec.js/contracts';
4
+ import type { AztecNode } from '@aztec/aztec.js/node';
2
5
  import { prepTx } from '@aztec/cli/utils';
3
6
  import type { LogFn } from '@aztec/foundation/log';
4
7
 
5
8
  import { format } from 'util';
6
9
 
7
- function printProfileResult(result: ProfileResult, log: LogFn) {
8
- log(format('\nSimulation result:'));
9
- log(format('Return value:', JSON.stringify(result.returnValues, null, 2)));
10
-
11
- log(format('\nGate count per circuit:'));
12
- let acc = 0;
13
- result.gateCounts.forEach(r => {
14
- acc += r.gateCount;
15
- log(format(' ', r.circuitName.padEnd(50), 'Gates:', r.gateCount.toLocaleString(), '\tAcc:', acc.toLocaleString()));
16
- });
17
-
18
- log(format('\nTotal gates:', acc.toLocaleString()));
19
- }
10
+ import { printAuthorizations } from '../utils/authorizations.js';
11
+ import type { CLIFeeArgs } from '../utils/options/fees.js';
12
+ import { printProfileResult } from '../utils/profiling.js';
13
+ import type { CLIWallet } from '../utils/wallet.js';
20
14
 
21
15
  export async function simulate(
22
- wallet: AccountWalletWithSecretKey,
16
+ wallet: CLIWallet,
17
+ node: AztecNode,
18
+ from: AztecAddress,
23
19
  functionName: string,
24
20
  functionArgsIn: any[],
25
21
  contractArtifactPath: string,
26
22
  contractAddress: AztecAddress,
27
- profile: boolean,
23
+ feeOpts: CLIFeeArgs,
24
+ authWitnesses: AuthWitness[],
25
+ verbose: boolean,
28
26
  log: LogFn,
29
27
  ) {
30
28
  const { functionArgs, contractArtifact } = await prepTx(contractArtifactPath, functionName, functionArgsIn, log);
31
29
 
32
- const contract = await Contract.at(contractAddress, contractArtifact, wallet);
30
+ const contract = Contract.at(contractAddress, contractArtifact, wallet);
33
31
  const call = contract.methods[functionName](...functionArgs);
34
-
35
- if (profile) {
36
- const result = await call.simulateWithProfile();
37
- printProfileResult(result, log);
38
- } else {
39
- const result = await call.simulate();
40
- log(format('\nSimulation result: ', result, '\n'));
32
+ const { paymentMethod, gasSettings } = await feeOpts.toUserFeeOptions(node, wallet, from);
33
+ const simulationResult = await call.simulate({
34
+ fee: { paymentMethod, gasSettings },
35
+ from,
36
+ authWitnesses,
37
+ includeMetadata: true,
38
+ });
39
+ if (verbose) {
40
+ await printAuthorizations(
41
+ simulationResult.offchainEffects,
42
+ async (address: AztecAddress) => {
43
+ const metadata = await wallet.getContractMetadata(address);
44
+ if (!metadata.instance) {
45
+ return undefined;
46
+ }
47
+ const artifact = await wallet.getContractArtifact(metadata.instance.currentContractClassId);
48
+ return artifact;
49
+ },
50
+ log,
51
+ );
52
+ printProfileResult(simulationResult.stats!, log);
41
53
  }
54
+ log(format('\nSimulation result: ', simulationResult.result, '\n'));
42
55
  }
@@ -1,22 +1,21 @@
1
- import { Fr } from '@aztec/foundation/fields';
1
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
2
  import type { LogFn } from '@aztec/foundation/log';
3
3
  import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
4
4
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
5
5
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
6
- import { GasSettings } from '@aztec/stdlib/gas';
7
6
  import type { TxHash } from '@aztec/stdlib/tx';
8
7
 
9
- import type { AccountType } from '../utils/accounts.js';
8
+ import type { AccountType } from '../utils/constants.js';
10
9
  import { extractECDSAPublicKeyFromBase64String } from '../utils/ecdsa.js';
11
10
 
12
11
  export const Aliases = ['accounts', 'contracts', 'artifacts', 'secrets', 'transactions', 'authwits'] as const;
13
12
  export type AliasType = (typeof Aliases)[number];
14
13
 
15
14
  export class WalletDB {
15
+ #store!: AztecAsyncKVStore;
16
16
  #accounts!: AztecAsyncMap<string, Buffer>;
17
17
  #aliases!: AztecAsyncMap<string, Buffer>;
18
18
  #bridgedFeeJuice!: AztecAsyncMap<string, Buffer>;
19
- #transactions!: AztecAsyncMap<string, Buffer>;
20
19
 
21
20
  private static instance: WalletDB;
22
21
 
@@ -31,10 +30,10 @@ export class WalletDB {
31
30
  }
32
31
 
33
32
  async init(store: AztecAsyncKVStore) {
33
+ this.#store = store;
34
34
  this.#accounts = store.openMap('accounts');
35
35
  this.#aliases = store.openMap('aliases');
36
36
  this.#bridgedFeeJuice = store.openMap('bridgedFeeJuice');
37
- this.#transactions = store.openMap('transactions');
38
37
 
39
38
  await this.refreshAliasCache();
40
39
  }
@@ -44,14 +43,17 @@ export class WalletDB {
44
43
  }
45
44
 
46
45
  async pushBridgedFeeJuice(recipient: AztecAddress, secret: Fr, amount: bigint, leafIndex: bigint, log: LogFn) {
47
- let stackPointer = (await this.#bridgedFeeJuice.getAsync(`${recipient.toString()}:stackPointer`))?.readInt8() || 0;
48
- stackPointer++;
49
- await this.#bridgedFeeJuice.set(
50
- `${recipient.toString()}:${stackPointer}`,
51
- Buffer.from(`${amount.toString()}:${secret.toString()}:${leafIndex.toString()}`),
52
- );
53
- await this.#bridgedFeeJuice.set(`${recipient.toString()}:stackPointer`, Buffer.from([stackPointer]));
54
- log(`Pushed ${amount} fee juice for recipient ${recipient.toString()}. Stack pointer ${stackPointer}`);
46
+ await this.#store.transactionAsync(async () => {
47
+ let stackPointer =
48
+ (await this.#bridgedFeeJuice.getAsync(`${recipient.toString()}:stackPointer`))?.readInt8() || 0;
49
+ stackPointer++;
50
+ await this.#bridgedFeeJuice.set(
51
+ `${recipient.toString()}:${stackPointer}`,
52
+ Buffer.from(`${amount.toString()}:${secret.toString()}:${leafIndex.toString()}`),
53
+ );
54
+ await this.#bridgedFeeJuice.set(`${recipient.toString()}:stackPointer`, Buffer.from([stackPointer]));
55
+ log(`Pushed ${amount} fee juice for recipient ${recipient.toString()}. Stack pointer ${stackPointer}`);
56
+ });
55
57
  }
56
58
 
57
59
  async popBridgedFeeJuice(recipient: AztecAddress, log: LogFn) {
@@ -68,6 +70,20 @@ export class WalletDB {
68
70
  return { amount: BigInt(amountStr), secret: secretStr, leafIndex: BigInt(leafIndexStr) };
69
71
  }
70
72
 
73
+ async peekBridgedFeeJuice(recipient: AztecAddress, log: LogFn) {
74
+ const stackPointer =
75
+ (await this.#bridgedFeeJuice.getAsync(`${recipient.toString()}:stackPointer`))?.readInt8() || 0;
76
+ const result = await this.#bridgedFeeJuice.getAsync(`${recipient.toString()}:${stackPointer}`);
77
+ if (!result) {
78
+ throw new Error(
79
+ `No stored fee juice available for recipient ${recipient.toString()}. Please provide claim amount and secret. Stack pointer ${stackPointer}`,
80
+ );
81
+ }
82
+ const [amountStr, secretStr, leafIndexStr] = result.toString().split(':');
83
+ log(`Peeked ${amountStr} fee juice for recipient ${recipient.toString()}. Stack pointer ${stackPointer}`);
84
+ return { amount: BigInt(amountStr), secret: secretStr, leafIndex: BigInt(leafIndexStr) };
85
+ }
86
+
71
87
  async storeAccount(
72
88
  address: AztecAddress,
73
89
  {
@@ -79,19 +95,24 @@ export class WalletDB {
79
95
  }: { type: AccountType; secretKey: Fr; salt: Fr; alias: string | undefined; publicKey: string | undefined },
80
96
  log: LogFn,
81
97
  ) {
82
- if (alias) {
83
- await this.#aliases.set(`accounts:${alias}`, Buffer.from(address.toString()));
84
- }
85
- await this.#accounts.set(`${address.toString()}:type`, Buffer.from(type));
86
- await this.#accounts.set(`${address.toString()}:sk`, secretKey.toBuffer());
87
- await this.#accounts.set(`${address.toString()}:salt`, salt.toBuffer());
98
+ let publicSigningKey: Buffer | undefined;
88
99
  if (type === 'ecdsasecp256r1ssh' && publicKey) {
89
- const publicSigningKey = extractECDSAPublicKeyFromBase64String(publicKey);
90
- await this.storeAccountMetadata(address, 'publicSigningKey', publicSigningKey);
100
+ publicSigningKey = extractECDSAPublicKeyFromBase64String(publicKey);
91
101
  }
92
- await this.#aliases.set('accounts:last', Buffer.from(address.toString()));
93
- log(`Account stored in database with alias${alias ? `es last & ${alias}` : ' last'}`);
94
102
 
103
+ await this.#store.transactionAsync(async () => {
104
+ if (alias) {
105
+ await this.#aliases.set(`accounts:${alias}`, Buffer.from(address.toString()));
106
+ }
107
+ await this.#accounts.set(`${address.toString()}:type`, Buffer.from(type));
108
+ await this.#accounts.set(`${address.toString()}:sk`, secretKey.toBuffer());
109
+ await this.#accounts.set(`${address.toString()}:salt`, salt.toBuffer());
110
+ if (publicSigningKey) {
111
+ await this.#accounts.set(`${address.toString()}:publicSigningKey`, publicSigningKey);
112
+ }
113
+ await this.#aliases.set('accounts:last', Buffer.from(address.toString()));
114
+ });
115
+ log(`Account stored in database with alias${alias ? `es last & ${alias}` : ' last'}`);
95
116
  await this.refreshAliasCache();
96
117
  }
97
118
 
@@ -103,67 +124,45 @@ export class WalletDB {
103
124
  }
104
125
 
105
126
  async storeContract(address: AztecAddress, artifactPath: string, log: LogFn, alias?: string) {
106
- if (alias) {
107
- await this.#aliases.set(`contracts:${alias}`, Buffer.from(address.toString()));
108
- await this.#aliases.set(`artifacts:${alias}`, Buffer.from(artifactPath));
109
- }
110
- await this.#aliases.set(`contracts:last`, Buffer.from(address.toString()));
111
- await this.#aliases.set(`artifacts:last`, Buffer.from(artifactPath));
112
- await this.#aliases.set(`artifacts:${address.toString()}`, Buffer.from(artifactPath));
127
+ await this.#store.transactionAsync(async () => {
128
+ if (alias) {
129
+ await this.#aliases.set(`contracts:${alias}`, Buffer.from(address.toString()));
130
+ await this.#aliases.set(`artifacts:${alias}`, Buffer.from(artifactPath));
131
+ }
132
+ await this.#aliases.set(`contracts:last`, Buffer.from(address.toString()));
133
+ await this.#aliases.set(`artifacts:last`, Buffer.from(artifactPath));
134
+ await this.#aliases.set(`artifacts:${address.toString()}`, Buffer.from(artifactPath));
135
+ });
113
136
  log(`Contract stored in database with alias${alias ? `es last & ${alias}` : ' last'}`);
114
-
115
137
  await this.refreshAliasCache();
116
138
  }
117
139
 
118
140
  async storeAuthwitness(authWit: AuthWitness, log: LogFn, alias?: string) {
119
- if (alias) {
120
- await this.#aliases.set(`authwits:${alias}`, Buffer.from(authWit.toString()));
121
- }
122
- await this.#aliases.set(`authwits:last`, Buffer.from(authWit.toString()));
141
+ await this.#store.transactionAsync(async () => {
142
+ if (alias) {
143
+ await this.#aliases.set(`authwits:${alias}`, Buffer.from(authWit.toString()));
144
+ }
145
+ await this.#aliases.set(`authwits:last`, Buffer.from(authWit.toString()));
146
+ });
123
147
  log(`Authorization witness stored in database with alias${alias ? `es last & ${alias}` : ' last'}`);
124
-
125
148
  await this.refreshAliasCache();
126
149
  }
127
150
 
128
- async storeTx(
129
- {
130
- txHash,
131
- nonce,
132
- cancellable,
133
- gasSettings,
134
- }: { txHash: TxHash; nonce: Fr; cancellable: boolean; gasSettings: GasSettings },
135
- log: LogFn,
136
- alias?: string,
137
- ) {
138
- if (alias) {
139
- await this.#aliases.set(`transactions:${alias}`, Buffer.from(txHash.toString()));
140
- }
141
- await this.#transactions.set(`${txHash.toString()}:nonce`, nonce.toBuffer());
142
- await this.#transactions.set(`${txHash.toString()}:cancellable`, Buffer.from(cancellable ? 'true' : 'false'));
143
- await this.#transactions.set(`${txHash.toString()}:gasSettings`, gasSettings.toBuffer());
144
- await this.#aliases.set(`transactions:last`, Buffer.from(txHash.toString()));
151
+ async storeTx({ txHash }: { txHash: TxHash }, log: LogFn, alias?: string) {
152
+ await this.#store.transactionAsync(async () => {
153
+ if (alias) {
154
+ await this.#aliases.set(`transactions:${alias}`, Buffer.from(txHash.toString()));
155
+ }
156
+ await this.#aliases.set(`transactions:last`, Buffer.from(txHash.toString()));
157
+ });
145
158
  log(`Transaction hash stored in database with alias${alias ? `es last & ${alias}` : ' last'}`);
146
-
147
159
  await this.refreshAliasCache();
148
160
  }
149
161
 
150
- async retrieveTxData(txHash: TxHash) {
151
- const nonceBuffer = await this.#transactions.getAsync(`${txHash.toString()}:nonce`);
152
- if (!nonceBuffer) {
153
- throw new Error(
154
- `Could not find ${txHash.toString()}:nonce. Transaction with hash "${txHash.toString()}" does not exist on this wallet.`,
155
- );
156
- }
157
- const nonce = Fr.fromBuffer(nonceBuffer);
158
- const cancellable = (await this.#transactions.getAsync(`${txHash.toString()}:cancellable`))!.toString() === 'true';
159
- const gasBuffer = (await this.#transactions.getAsync(`${txHash.toString()}:gasSettings`))!;
160
- return { txHash, nonce, cancellable, gasSettings: GasSettings.fromBuffer(gasBuffer) };
161
- }
162
-
163
162
  tryRetrieveAlias(arg: string) {
164
163
  try {
165
164
  return this.retrieveAliasFromCache(arg);
166
- } catch (e) {
165
+ } catch {
167
166
  return arg;
168
167
  }
169
168
  }
@@ -0,0 +1,51 @@
1
+ import type { ContractArtifact } from '@aztec/aztec.js/abi';
2
+ import type { AztecAddress } from '@aztec/aztec.js/addresses';
3
+ import { CallAuthorizationRequest } from '@aztec/aztec.js/authorization';
4
+ import type { LogFn } from '@aztec/foundation/log';
5
+ import { type AbiDecoded, decodeFromAbi, getFunctionArtifact } from '@aztec/stdlib/abi';
6
+ import type { OffchainEffect } from '@aztec/stdlib/tx';
7
+
8
+ import { format } from 'util';
9
+
10
+ export async function printAuthorizations(
11
+ offchainEffects: OffchainEffect[],
12
+ artifactRetriever: (address: AztecAddress) => Promise<ContractArtifact | undefined>,
13
+ log: LogFn,
14
+ ) {
15
+ log(format('\nAuthorizations requested by the tx:\n'));
16
+ const callAuthorizationSelector = await CallAuthorizationRequest.getSelector();
17
+ const callAuthorizationEffects = offchainEffects.filter(effect =>
18
+ effect.data[0].equals(callAuthorizationSelector.toField()),
19
+ );
20
+ for (const callAuthorizationEffect of callAuthorizationEffects) {
21
+ const callAuthorizationRequest = await CallAuthorizationRequest.fromFields(callAuthorizationEffect.data);
22
+ const artifact = await artifactRetriever(callAuthorizationEffect.contractAddress);
23
+ if (!artifact) {
24
+ log(format(' -', `Call authorization. Inner hash: ${callAuthorizationRequest.innerHash.toString()}\n`));
25
+ log(format(' ', `Contract: unknown@${callAuthorizationEffect.contractAddress}`));
26
+ log(
27
+ format(
28
+ ' ',
29
+ `${callAuthorizationRequest.functionSelector.toString()}(\n${callAuthorizationRequest.args.map(arg => ` ${arg.toString()}`).join(',\n')}\n )`,
30
+ ),
31
+ );
32
+ } else {
33
+ const functionAbi = await getFunctionArtifact(artifact, callAuthorizationRequest.functionSelector);
34
+ const callData = decodeFromAbi(
35
+ functionAbi.parameters.map(param => param.type),
36
+ callAuthorizationRequest.args,
37
+ ) as AbiDecoded[];
38
+ const parameters = functionAbi.parameters.map((param, i) => ({ name: param.name, value: callData[i] }));
39
+ log(format(' -', `Call authorization. Inner hash: ${callAuthorizationRequest.innerHash.toString()}`));
40
+ log(format(' ', `Contract: ${artifact.name}@${callAuthorizationEffect.contractAddress}`));
41
+ log(
42
+ format(
43
+ ' ',
44
+ /* eslint-disable-next-line @typescript-eslint/no-base-to-string */
45
+ `${functionAbi.name}(\n${parameters.map(p => ` ${p.name}: ${p.value}`).join(',\n')}\n )`,
46
+ ),
47
+ );
48
+ }
49
+ log(`\n`);
50
+ }
51
+ }
@@ -0,0 +1,35 @@
1
+ import type { AztecNode } from '@aztec/stdlib/interfaces/client';
2
+
3
+ import { CLIWallet } from './wallet.js';
4
+
5
+ export const DEFAULT_TX_TIMEOUT_S = 180;
6
+
7
+ /*
8
+ * Wrapper class for CLIWallet and AztecNode, avoids initialization issues due to closures when providing CLIWallet
9
+ * and AztecNode to injected commander.js commands
10
+ */
11
+ export class CliWalletAndNodeWrapper {
12
+ private _wallet: CLIWallet | undefined;
13
+ private _node: AztecNode | undefined;
14
+
15
+ constructor() {}
16
+
17
+ get wallet() {
18
+ if (!this._wallet) {
19
+ throw new Error('Wallet not initialized while it should have been initialized in preSubcommand');
20
+ }
21
+ return this._wallet;
22
+ }
23
+
24
+ get node(): AztecNode {
25
+ if (!this._node) {
26
+ throw new Error('Node not initialized while it should have been initialized in preSubcommand');
27
+ }
28
+ return this._node;
29
+ }
30
+
31
+ setNodeAndWallet(node: AztecNode, wallet: CLIWallet) {
32
+ this._node = node;
33
+ this._wallet = wallet;
34
+ }
35
+ }
@@ -0,0 +1,4 @@
1
+ export const MIN_FEE_PADDING = 0.5;
2
+
3
+ export const AccountTypes = ['schnorr', 'ecdsasecp256r1', 'ecdsasecp256r1ssh', 'ecdsasecp256k1'] as const;
4
+ export type AccountType = (typeof AccountTypes)[number];