@aztec/cli-wallet 2.1.0-rc.9 → 3.0.0-devnet.2
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.
- package/README.md +30 -0
- package/dest/bin/index.js +28 -22
- package/dest/cmds/authorize_action.d.ts +3 -2
- package/dest/cmds/authorize_action.d.ts.map +1 -1
- package/dest/cmds/authorize_action.js +5 -6
- package/dest/cmds/bridge_fee_juice.d.ts +2 -2
- package/dest/cmds/bridge_fee_juice.d.ts.map +1 -1
- package/dest/cmds/bridge_fee_juice.js +6 -5
- package/dest/cmds/check_tx.d.ts +4 -2
- package/dest/cmds/check_tx.d.ts.map +1 -1
- package/dest/cmds/check_tx.js +145 -6
- package/dest/cmds/create_account.d.ts +5 -4
- package/dest/cmds/create_account.d.ts.map +1 -1
- package/dest/cmds/create_account.js +35 -47
- package/dest/cmds/create_authwit.d.ts +3 -2
- package/dest/cmds/create_authwit.d.ts.map +1 -1
- package/dest/cmds/create_authwit.js +5 -5
- package/dest/cmds/deploy.d.ts +6 -3
- package/dest/cmds/deploy.d.ts.map +1 -1
- package/dest/cmds/deploy.js +57 -46
- package/dest/cmds/deploy_account.d.ts +5 -7
- package/dest/cmds/deploy_account.d.ts.map +1 -1
- package/dest/cmds/deploy_account.js +36 -51
- package/dest/cmds/import_test_accounts.d.ts +2 -2
- package/dest/cmds/import_test_accounts.d.ts.map +1 -1
- package/dest/cmds/import_test_accounts.js +6 -9
- package/dest/cmds/index.d.ts +2 -2
- package/dest/cmds/index.d.ts.map +1 -1
- package/dest/cmds/index.js +73 -112
- package/dest/cmds/profile.d.ts +6 -3
- package/dest/cmds/profile.d.ts.map +1 -1
- package/dest/cmds/profile.js +8 -3
- package/dest/cmds/register_contract.d.ts +6 -2
- package/dest/cmds/register_contract.d.ts.map +1 -1
- package/dest/cmds/register_contract.js +5 -6
- package/dest/cmds/register_sender.d.ts +3 -2
- package/dest/cmds/register_sender.d.ts.map +1 -1
- package/dest/cmds/send.d.ts +7 -8
- package/dest/cmds/send.d.ts.map +1 -1
- package/dest/cmds/send.js +26 -23
- package/dest/cmds/simulate.d.ts +6 -3
- package/dest/cmds/simulate.d.ts.map +1 -1
- package/dest/cmds/simulate.js +8 -3
- package/dest/storage/wallet_db.d.ts +2 -12
- package/dest/storage/wallet_db.d.ts.map +1 -1
- package/dest/storage/wallet_db.js +1 -22
- package/dest/utils/authorizations.d.ts +2 -1
- package/dest/utils/authorizations.d.ts.map +1 -1
- package/dest/utils/authorizations.js +1 -1
- package/dest/utils/cli_wallet_and_node_wrapper.d.ts +12 -0
- package/dest/utils/cli_wallet_and_node_wrapper.d.ts.map +1 -0
- package/dest/utils/cli_wallet_and_node_wrapper.js +25 -0
- package/dest/utils/options/fees.d.ts +20 -27
- package/dest/utils/options/fees.d.ts.map +1 -1
- package/dest/utils/options/fees.js +65 -132
- package/dest/utils/options/options.d.ts +2 -1
- package/dest/utils/options/options.d.ts.map +1 -1
- package/dest/utils/options/options.js +1 -1
- package/dest/utils/wallet.d.ts +35 -0
- package/dest/utils/wallet.d.ts.map +1 -0
- package/dest/utils/wallet.js +193 -0
- package/package.json +12 -12
- package/src/bin/index.ts +30 -29
- package/src/cmds/authorize_action.ts +13 -5
- package/src/cmds/bridge_fee_juice.ts +12 -9
- package/src/cmds/check_tx.ts +182 -5
- package/src/cmds/create_account.ts +42 -52
- package/src/cmds/create_authwit.ts +8 -4
- package/src/cmds/deploy.ts +58 -56
- package/src/cmds/deploy_account.ts +43 -51
- package/src/cmds/import_test_accounts.ts +7 -11
- package/src/cmds/index.ts +120 -206
- package/src/cmds/profile.ts +13 -5
- package/src/cmds/register_contract.ts +9 -11
- package/src/cmds/register_sender.ts +3 -2
- package/src/cmds/send.ts +21 -31
- package/src/cmds/simulate.ts +13 -5
- package/src/storage/wallet_db.ts +2 -30
- package/src/utils/authorizations.ts +3 -1
- package/src/utils/cli_wallet_and_node_wrapper.ts +35 -0
- package/src/utils/options/fees.ts +86 -177
- package/src/utils/options/options.ts +3 -2
- package/src/utils/wallet.ts +264 -0
- package/dest/cmds/cancel_tx.d.ts +0 -11
- package/dest/cmds/cancel_tx.d.ts.map +0 -1
- package/dest/cmds/cancel_tx.js +0 -43
- package/dest/utils/accounts.d.ts +0 -9
- package/dest/utils/accounts.d.ts.map +0 -1
- package/dest/utils/accounts.js +0 -61
- package/dest/utils/pxe_wrapper.d.ts +0 -12
- package/dest/utils/pxe_wrapper.d.ts.map +0 -1
- package/dest/utils/pxe_wrapper.js +0 -26
- package/src/cmds/cancel_tx.ts +0 -66
- package/src/utils/accounts.ts +0 -77
- package/src/utils/pxe_wrapper.ts +0 -32
|
@@ -1,67 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
FeeJuicePaymentMethod,
|
|
5
|
-
type FeePaymentMethod,
|
|
6
|
-
type PXE,
|
|
7
|
-
type SendMethodOptions,
|
|
8
|
-
} from '@aztec/aztec.js';
|
|
1
|
+
import type { FeePaymentMethod } from '@aztec/aztec.js/fee';
|
|
2
|
+
import type { AztecNode } from '@aztec/aztec.js/node';
|
|
3
|
+
import type { FeeOptions, Wallet } from '@aztec/aztec.js/wallet';
|
|
9
4
|
import { Fr } from '@aztec/foundation/fields';
|
|
10
5
|
import type { LogFn } from '@aztec/foundation/log';
|
|
6
|
+
import type { FieldsOf } from '@aztec/foundation/types';
|
|
11
7
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
12
8
|
import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
|
|
13
9
|
|
|
14
10
|
import { Option } from 'commander';
|
|
15
11
|
|
|
16
12
|
import type { WalletDB } from '../../storage/wallet_db.js';
|
|
17
|
-
import {
|
|
13
|
+
import { BASE_FEE_PADDING } from '../wallet.js';
|
|
18
14
|
import { aliasedAddressParser } from './options.js';
|
|
19
15
|
|
|
20
|
-
export type
|
|
16
|
+
export type RawCliFeeArgs = {
|
|
21
17
|
estimateGasOnly: boolean;
|
|
22
18
|
gasLimits?: string;
|
|
23
19
|
payment?: string;
|
|
24
20
|
maxFeesPerGas?: string;
|
|
25
21
|
maxPriorityFeesPerGas?: string;
|
|
26
|
-
estimateGas?: boolean;
|
|
27
22
|
};
|
|
28
23
|
|
|
29
|
-
export
|
|
30
|
-
|
|
31
|
-
gasSettings
|
|
32
|
-
|
|
33
|
-
toDeployAccountOpts(sender: AccountWallet): Promise<DeployAccountOptions>;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function printGasEstimates(
|
|
37
|
-
feeOpts: IFeeOpts,
|
|
38
|
-
gasEstimates: Pick<GasSettings, 'gasLimits' | 'teardownGasLimits'>,
|
|
39
|
-
log: LogFn,
|
|
40
|
-
) {
|
|
41
|
-
log(`Estimated gas usage: ${formatGasEstimate(gasEstimates)}`);
|
|
42
|
-
log(`Maximum total tx fee: ${getEstimatedCost(gasEstimates, feeOpts.gasSettings.maxFeesPerGas)}`);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function formatGasEstimate(estimate: Pick<GasSettings, 'gasLimits' | 'teardownGasLimits'>) {
|
|
46
|
-
return `da=${estimate.gasLimits.daGas},l2=${estimate.gasLimits.l2Gas},teardownDA=${estimate.teardownGasLimits.daGas},teardownL2=${estimate.teardownGasLimits.l2Gas}`;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function getEstimatedCost(estimate: Pick<GasSettings, 'gasLimits' | 'teardownGasLimits'>, maxFeesPerGas: GasFees) {
|
|
50
|
-
return GasSettings.default({ ...estimate, maxFeesPerGas })
|
|
51
|
-
.getFeeLimit()
|
|
52
|
-
.toBigInt();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async function parseGasSettings(args: CliFeeArgs, pxe: PXE) {
|
|
56
|
-
const gasLimits = args.gasLimits ? parseGasLimits(args.gasLimits) : {};
|
|
57
|
-
const maxFeesPerGas = args.maxFeesPerGas ? parseGasFees(args.maxFeesPerGas) : await pxe.getCurrentBaseFees();
|
|
58
|
-
const maxPriorityFeesPerGas = args.maxPriorityFeesPerGas ? parseGasFees(args.maxPriorityFeesPerGas) : undefined;
|
|
59
|
-
return GasSettings.default({
|
|
60
|
-
...gasLimits,
|
|
61
|
-
maxFeesPerGas,
|
|
62
|
-
maxPriorityFeesPerGas,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
24
|
+
export type ParsedFeeOptions = {
|
|
25
|
+
paymentMethod?: FeePaymentMethod;
|
|
26
|
+
gasSettings?: Partial<FieldsOf<GasSettings>>;
|
|
27
|
+
};
|
|
65
28
|
|
|
66
29
|
type OptionParams = {
|
|
67
30
|
[key: string]: { type: string; description?: string; default?: string };
|
|
@@ -84,15 +47,13 @@ function printOptionParams(params: OptionParams) {
|
|
|
84
47
|
: '';
|
|
85
48
|
}
|
|
86
49
|
|
|
87
|
-
function getFeePaymentMethodParams(
|
|
88
|
-
const feePayer = allowCustomFeePayer ? { type: 'address', description: 'The account paying the fee.' } : undefined;
|
|
50
|
+
function getFeePaymentMethodParams(): OptionParams {
|
|
89
51
|
return {
|
|
90
52
|
method: {
|
|
91
53
|
type: 'name',
|
|
92
54
|
description: 'Valid values: "fee_juice", "fpc-public", "fpc-private", "fpc-sponsored"',
|
|
93
55
|
default: 'fee_juice',
|
|
94
56
|
},
|
|
95
|
-
...(feePayer ? { feePayer } : {}),
|
|
96
57
|
asset: {
|
|
97
58
|
type: 'address',
|
|
98
59
|
description: 'The asset used for fee payment. Required for "fpc-public" and "fpc-private".',
|
|
@@ -117,144 +78,43 @@ function getFeePaymentMethodParams(allowCustomFeePayer: boolean): OptionParams {
|
|
|
117
78
|
type: 'bigint',
|
|
118
79
|
description: 'The index of the claim in the l1toL2Message tree.',
|
|
119
80
|
},
|
|
120
|
-
feeRecipient: {
|
|
121
|
-
type: 'string',
|
|
122
|
-
description: 'Recipient of the fee.',
|
|
123
|
-
},
|
|
124
81
|
};
|
|
125
82
|
}
|
|
126
83
|
|
|
127
|
-
function getPaymentMethodOption(
|
|
128
|
-
const params = getFeePaymentMethodParams(
|
|
84
|
+
export function getPaymentMethodOption() {
|
|
85
|
+
const params = getFeePaymentMethodParams();
|
|
129
86
|
return new Option(`--payment <options>`, `Fee payment method and arguments.${printOptionParams(params)}`);
|
|
130
87
|
}
|
|
131
88
|
|
|
132
|
-
function getFeeOptions(
|
|
89
|
+
function getFeeOptions() {
|
|
133
90
|
return [
|
|
134
|
-
getPaymentMethodOption(
|
|
91
|
+
getPaymentMethodOption(),
|
|
135
92
|
new Option('--gas-limits <da=100,l2=100,teardownDA=10,teardownL2=10>', 'Gas limits for the tx.'),
|
|
136
93
|
new Option('--max-fees-per-gas <da=100,l2=100>', 'Maximum fees per gas unit for DA and L2 computation.'),
|
|
137
94
|
new Option(
|
|
138
95
|
'--max-priority-fees-per-gas <da=0,l2=0>',
|
|
139
96
|
'Maximum priority fees per gas unit for DA and L2 computation.',
|
|
140
97
|
),
|
|
141
|
-
new Option('--estimate-gas', 'Whether to automatically estimate gas limits for the tx.'),
|
|
142
98
|
new Option('--estimate-gas-only', 'Only report gas estimation for the tx, do not send it.'),
|
|
143
99
|
];
|
|
144
100
|
}
|
|
145
101
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
private estimateGas: boolean,
|
|
156
|
-
) {}
|
|
157
|
-
|
|
158
|
-
async toSendOpts(sender: AccountWallet): Promise<SendMethodOptions> {
|
|
159
|
-
return {
|
|
160
|
-
from: sender.getAddress(),
|
|
161
|
-
fee: {
|
|
162
|
-
estimateGas: this.estimateGas,
|
|
163
|
-
gasSettings: this.gasSettings,
|
|
164
|
-
paymentMethod: await this.paymentMethodFactory(sender),
|
|
165
|
-
},
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
async toDeployAccountOpts(sender: AccountWallet): Promise<DeployAccountOptions> {
|
|
170
|
-
const paymentMethod = await this.paymentMethodFactory(sender);
|
|
171
|
-
const deployWallet = await this.getDeployWallet(sender, paymentMethod);
|
|
172
|
-
return {
|
|
173
|
-
deployWallet,
|
|
174
|
-
fee: {
|
|
175
|
-
estimateGas: this.estimateGas,
|
|
176
|
-
gasSettings: this.gasSettings,
|
|
177
|
-
paymentMethod,
|
|
178
|
-
},
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
static paymentMethodOption() {
|
|
183
|
-
return getPaymentMethodOption(false);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
static getOptions() {
|
|
187
|
-
return getFeeOptions(false);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
static async fromCli(args: CliFeeArgs, pxe: PXE, log: LogFn, db?: WalletDB) {
|
|
191
|
-
const estimateOnly = args.estimateGasOnly;
|
|
192
|
-
const gasSettings = await parseGasSettings(args, pxe);
|
|
193
|
-
|
|
194
|
-
const defaultPaymentMethod = async (sender: AccountWallet) => {
|
|
195
|
-
const { FeeJuicePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
196
|
-
return new FeeJuicePaymentMethod(sender.getAddress());
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
const getDeployWallet = () => {
|
|
200
|
-
// Returns undefined. The sender's wallet will be used by default.
|
|
201
|
-
return Promise.resolve(undefined);
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
return new FeeOpts(
|
|
205
|
-
estimateOnly,
|
|
206
|
-
gasSettings,
|
|
207
|
-
args.payment ? parsePaymentMethod(args.payment, false, log, db) : defaultPaymentMethod,
|
|
208
|
-
getDeployWallet,
|
|
209
|
-
!!args.estimateGas,
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
export class FeeOptsWithFeePayer extends FeeOpts {
|
|
215
|
-
static override paymentMethodOption() {
|
|
216
|
-
return getPaymentMethodOption(true);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
static override getOptions() {
|
|
220
|
-
return getFeeOptions(true);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
static override async fromCli(args: CliFeeArgs, pxe: PXE, log: LogFn, db?: WalletDB) {
|
|
224
|
-
const estimateOnly = args.estimateGasOnly;
|
|
225
|
-
const gasSettings = await parseGasSettings(args, pxe);
|
|
226
|
-
|
|
227
|
-
const defaultPaymentMethod = async (sender: AccountWallet) => {
|
|
228
|
-
const { FeeJuicePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
229
|
-
return new FeeJuicePaymentMethod(sender.getAddress());
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
const getDeployWallet = async (sender: AccountWallet, paymentMethod: FeePaymentMethod) => {
|
|
233
|
-
if (paymentMethod instanceof FeeJuicePaymentMethod) {
|
|
234
|
-
const feePayer = await paymentMethod.getFeePayer();
|
|
235
|
-
if (!sender.getAddress().equals(feePayer)) {
|
|
236
|
-
return (await createOrRetrieveAccount(pxe, feePayer, db)).getWallet();
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return undefined;
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
return new FeeOptsWithFeePayer(
|
|
243
|
-
estimateOnly,
|
|
244
|
-
gasSettings,
|
|
245
|
-
args.payment ? parsePaymentMethod(args.payment, true, log, db) : defaultPaymentMethod,
|
|
246
|
-
getDeployWallet,
|
|
247
|
-
!!args.estimateGas,
|
|
248
|
-
);
|
|
249
|
-
}
|
|
102
|
+
function parseGasSettings(args: RawCliFeeArgs): Partial<FieldsOf<GasSettings>> {
|
|
103
|
+
const gasLimits = args.gasLimits ? parseGasLimits(args.gasLimits) : {};
|
|
104
|
+
const maxFeesPerGas = args.maxFeesPerGas ? parseGasFees(args.maxFeesPerGas) : undefined;
|
|
105
|
+
const maxPriorityFeesPerGas = args.maxPriorityFeesPerGas ? parseGasFees(args.maxPriorityFeesPerGas) : undefined;
|
|
106
|
+
return {
|
|
107
|
+
...gasLimits,
|
|
108
|
+
maxFeesPerGas,
|
|
109
|
+
maxPriorityFeesPerGas,
|
|
110
|
+
};
|
|
250
111
|
}
|
|
251
112
|
|
|
252
113
|
export function parsePaymentMethod(
|
|
253
114
|
payment: string,
|
|
254
|
-
allowCustomFeePayer: boolean,
|
|
255
115
|
log: LogFn,
|
|
256
116
|
db?: WalletDB,
|
|
257
|
-
): (
|
|
117
|
+
): (wallet: Wallet, from: AztecAddress, gasSettings: GasSettings) => Promise<FeePaymentMethod | undefined> {
|
|
258
118
|
const parsed = payment.split(',').reduce(
|
|
259
119
|
(acc, item) => {
|
|
260
120
|
const [dimension, value] = item.split('=');
|
|
@@ -278,7 +138,7 @@ export function parsePaymentMethod(
|
|
|
278
138
|
return AztecAddress.fromString(parsed.asset);
|
|
279
139
|
};
|
|
280
140
|
|
|
281
|
-
return async (
|
|
141
|
+
return async (wallet: Wallet, from: AztecAddress, gasSettings: GasSettings) => {
|
|
282
142
|
switch (parsed.method) {
|
|
283
143
|
case 'fee_juice': {
|
|
284
144
|
if (parsed.claim || (parsed.claimSecret && parsed.claimAmount && parsed.messageLeafIndex)) {
|
|
@@ -288,13 +148,13 @@ export function parsePaymentMethod(
|
|
|
288
148
|
amount: claimAmount,
|
|
289
149
|
secret: claimSecret,
|
|
290
150
|
leafIndex: messageLeafIndex,
|
|
291
|
-
} = await db.popBridgedFeeJuice(
|
|
151
|
+
} = await db.popBridgedFeeJuice(from, log));
|
|
292
152
|
} else {
|
|
293
153
|
({ claimAmount, claimSecret, messageLeafIndex } = parsed);
|
|
294
154
|
}
|
|
295
155
|
log(`Using Fee Juice for fee payments with claim for ${claimAmount} tokens`);
|
|
296
156
|
const { FeeJuicePaymentMethodWithClaim } = await import('@aztec/aztec.js/fee');
|
|
297
|
-
return new FeeJuicePaymentMethodWithClaim(
|
|
157
|
+
return new FeeJuicePaymentMethodWithClaim(from, {
|
|
298
158
|
claimAmount: (typeof claimAmount === 'string'
|
|
299
159
|
? Fr.fromHexString(claimAmount)
|
|
300
160
|
: new Fr(claimAmount)
|
|
@@ -303,13 +163,8 @@ export function parsePaymentMethod(
|
|
|
303
163
|
messageLeafIndex: BigInt(messageLeafIndex),
|
|
304
164
|
});
|
|
305
165
|
} else {
|
|
306
|
-
log(`Using Fee Juice for fee payment`);
|
|
307
|
-
|
|
308
|
-
const feePayer =
|
|
309
|
-
parsed.feePayer && allowCustomFeePayer
|
|
310
|
-
? aliasedAddressParser('accounts', parsed.feePayer, db)
|
|
311
|
-
: sender.getAddress();
|
|
312
|
-
return new FeeJuicePaymentMethod(feePayer);
|
|
166
|
+
log(`Using Fee Juice for fee payment with the balance of account ${from}`);
|
|
167
|
+
return;
|
|
313
168
|
}
|
|
314
169
|
}
|
|
315
170
|
case 'fpc-public': {
|
|
@@ -317,14 +172,14 @@ export function parsePaymentMethod(
|
|
|
317
172
|
const asset = getAsset();
|
|
318
173
|
log(`Using public fee payment with asset ${asset} via paymaster ${fpc}`);
|
|
319
174
|
const { PublicFeePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
320
|
-
return new PublicFeePaymentMethod(fpc,
|
|
175
|
+
return new PublicFeePaymentMethod(fpc, from, wallet, gasSettings);
|
|
321
176
|
}
|
|
322
177
|
case 'fpc-private': {
|
|
323
178
|
const fpc = getFpc();
|
|
324
179
|
const asset = getAsset();
|
|
325
180
|
log(`Using private fee payment with asset ${asset} via paymaster ${fpc}`);
|
|
326
181
|
const { PrivateFeePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
327
|
-
return new PrivateFeePaymentMethod(fpc,
|
|
182
|
+
return new PrivateFeePaymentMethod(fpc, from, wallet, gasSettings);
|
|
328
183
|
}
|
|
329
184
|
case 'fpc-sponsored': {
|
|
330
185
|
const sponsor = getFpc();
|
|
@@ -382,3 +237,57 @@ export function parseGasFees(gasFees: string): GasFees {
|
|
|
382
237
|
|
|
383
238
|
return new GasFees(parsed.da, parsed.l2);
|
|
384
239
|
}
|
|
240
|
+
export class CLIFeeArgs {
|
|
241
|
+
constructor(
|
|
242
|
+
public estimateOnly: boolean,
|
|
243
|
+
private paymentMethod: (
|
|
244
|
+
wallet: Wallet,
|
|
245
|
+
feePayer: AztecAddress,
|
|
246
|
+
gasSettings: GasSettings,
|
|
247
|
+
) => Promise<FeePaymentMethod | undefined>,
|
|
248
|
+
private gasSettings: Partial<FieldsOf<GasSettings>>,
|
|
249
|
+
) {}
|
|
250
|
+
|
|
251
|
+
async toUserFeeOptions(node: AztecNode, wallet: Wallet, from: AztecAddress): Promise<ParsedFeeOptions> {
|
|
252
|
+
const maxFeesPerGas = (await node.getCurrentBaseFees()).mul(1 + BASE_FEE_PADDING);
|
|
253
|
+
const gasSettings = GasSettings.default({ ...this.gasSettings, maxFeesPerGas });
|
|
254
|
+
const paymentMethod = await this.paymentMethod(wallet, from, gasSettings);
|
|
255
|
+
return {
|
|
256
|
+
paymentMethod,
|
|
257
|
+
gasSettings,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
static parse(args: RawCliFeeArgs, log: LogFn, db?: WalletDB): CLIFeeArgs {
|
|
262
|
+
return new CLIFeeArgs(
|
|
263
|
+
!!args.estimateGasOnly,
|
|
264
|
+
parsePaymentMethod(args.payment ?? 'method=fee_juice', log, db),
|
|
265
|
+
parseGasSettings(args),
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
static getOptions() {
|
|
270
|
+
return getFeeOptions();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Printing
|
|
275
|
+
|
|
276
|
+
export function printGasEstimates(
|
|
277
|
+
feeOpts: FeeOptions,
|
|
278
|
+
gasEstimates: Pick<GasSettings, 'gasLimits' | 'teardownGasLimits'>,
|
|
279
|
+
log: LogFn,
|
|
280
|
+
) {
|
|
281
|
+
log(`Estimated gas usage: ${formatGasEstimate(gasEstimates)}`);
|
|
282
|
+
log(`Maximum total tx fee: ${getEstimatedCost(gasEstimates, feeOpts.gasSettings.maxFeesPerGas)}`);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function formatGasEstimate(estimate: Pick<GasSettings, 'gasLimits' | 'teardownGasLimits'>) {
|
|
286
|
+
return `da=${estimate.gasLimits.daGas},l2=${estimate.gasLimits.l2Gas},teardownDA=${estimate.teardownGasLimits.daGas},teardownL2=${estimate.teardownGasLimits.l2Gas}`;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function getEstimatedCost(estimate: Pick<GasSettings, 'gasLimits' | 'teardownGasLimits'>, maxFeesPerGas: GasFees) {
|
|
290
|
+
return GasSettings.default({ ...estimate, maxFeesPerGas })
|
|
291
|
+
.getFeeLimit()
|
|
292
|
+
.toBigInt();
|
|
293
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TxHash } from '@aztec/aztec.js/tx';
|
|
1
2
|
import { parseAztecAddress, parseSecretKey, parseTxHash } from '@aztec/cli/utils';
|
|
2
3
|
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
3
4
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
@@ -6,7 +7,7 @@ import { Option } from 'commander';
|
|
|
6
7
|
import { readdir, stat } from 'fs/promises';
|
|
7
8
|
|
|
8
9
|
import type { AliasType, WalletDB } from '../../storage/wallet_db.js';
|
|
9
|
-
import { AccountTypes } from '../
|
|
10
|
+
import { AccountTypes } from '../wallet.js';
|
|
10
11
|
|
|
11
12
|
const TARGET_DIR = 'target';
|
|
12
13
|
|
|
@@ -29,7 +30,7 @@ export function integerArgParser(
|
|
|
29
30
|
return parsed;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
export function aliasedTxHashParser(txHash: string, db?: WalletDB) {
|
|
33
|
+
export function aliasedTxHashParser(txHash: string, db?: WalletDB): TxHash {
|
|
33
34
|
try {
|
|
34
35
|
return parseTxHash(txHash);
|
|
35
36
|
} catch {
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { EcdsaRAccountContract, EcdsaRSSHAccountContract } from '@aztec/accounts/ecdsa';
|
|
2
|
+
import { SchnorrAccountContract } from '@aztec/accounts/schnorr';
|
|
3
|
+
import { StubAccountContractArtifact, createStubAccount } from '@aztec/accounts/stub';
|
|
4
|
+
import { getIdentities } from '@aztec/accounts/utils';
|
|
5
|
+
import { type Account, type AccountContract, SignerlessAccount } from '@aztec/aztec.js/account';
|
|
6
|
+
import {
|
|
7
|
+
type InteractionFeeOptions,
|
|
8
|
+
getContractInstanceFromInstantiationParams,
|
|
9
|
+
getGasLimits,
|
|
10
|
+
} from '@aztec/aztec.js/contracts';
|
|
11
|
+
import type { AztecNode } from '@aztec/aztec.js/node';
|
|
12
|
+
import { UniqueNote } from '@aztec/aztec.js/note';
|
|
13
|
+
import { AccountManager, type Aliased, BaseWallet, type SimulateOptions } from '@aztec/aztec.js/wallet';
|
|
14
|
+
import type { DefaultAccountEntrypointOptions } from '@aztec/entrypoints/account';
|
|
15
|
+
import { ExecutionPayload, mergeExecutionPayloads } from '@aztec/entrypoints/payload';
|
|
16
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
17
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
18
|
+
import type { PXEConfig } from '@aztec/pxe/config';
|
|
19
|
+
import type { PXE } from '@aztec/pxe/server';
|
|
20
|
+
import { createPXE, getPXEConfig } from '@aztec/pxe/server';
|
|
21
|
+
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
22
|
+
import { deriveSigningKey } from '@aztec/stdlib/keys';
|
|
23
|
+
import type { NotesFilter } from '@aztec/stdlib/note';
|
|
24
|
+
import type { TxProvingResult, TxSimulationResult } from '@aztec/stdlib/tx';
|
|
25
|
+
|
|
26
|
+
import type { WalletDB } from '../storage/wallet_db.js';
|
|
27
|
+
import { extractECDSAPublicKeyFromBase64String } from './ecdsa.js';
|
|
28
|
+
import { printGasEstimates } from './options/fees.js';
|
|
29
|
+
|
|
30
|
+
export const AccountTypes = ['schnorr', 'ecdsasecp256r1', 'ecdsasecp256r1ssh', 'ecdsasecp256k1'] as const;
|
|
31
|
+
export type AccountType = (typeof AccountTypes)[number];
|
|
32
|
+
|
|
33
|
+
export const BASE_FEE_PADDING = 0.5;
|
|
34
|
+
|
|
35
|
+
export class CLIWallet extends BaseWallet {
|
|
36
|
+
private accountCache = new Map<string, Account>();
|
|
37
|
+
|
|
38
|
+
constructor(
|
|
39
|
+
pxe: PXE,
|
|
40
|
+
node: AztecNode,
|
|
41
|
+
private userLog: LogFn,
|
|
42
|
+
private db?: WalletDB,
|
|
43
|
+
) {
|
|
44
|
+
super(pxe, node);
|
|
45
|
+
this.cancellableTransactions = true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static async create(
|
|
49
|
+
node: AztecNode,
|
|
50
|
+
log: LogFn,
|
|
51
|
+
db?: WalletDB,
|
|
52
|
+
overridePXEConfig?: Partial<PXEConfig>,
|
|
53
|
+
): Promise<CLIWallet> {
|
|
54
|
+
const pxeConfig = Object.assign(getPXEConfig(), overridePXEConfig);
|
|
55
|
+
const pxe = await createPXE(node, pxeConfig);
|
|
56
|
+
return new CLIWallet(pxe, node, log, db);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
override async getAccounts(): Promise<Aliased<AztecAddress>[]> {
|
|
60
|
+
const accounts = (await this.db?.listAliases('accounts')) ?? [];
|
|
61
|
+
return Promise.resolve(accounts.map(({ key, value }) => ({ alias: value, item: AztecAddress.fromString(key) })));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private async createCancellationTxExecutionRequest(
|
|
65
|
+
from: AztecAddress,
|
|
66
|
+
txNonce: Fr,
|
|
67
|
+
increasedFee: InteractionFeeOptions,
|
|
68
|
+
) {
|
|
69
|
+
const feeOptions = await this.getDefaultFeeOptions(from, increasedFee);
|
|
70
|
+
const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
|
|
71
|
+
const fromAccount = await this.getAccountFromAddress(from);
|
|
72
|
+
const executionOptions: DefaultAccountEntrypointOptions = {
|
|
73
|
+
txNonce,
|
|
74
|
+
cancellable: this.cancellableTransactions,
|
|
75
|
+
feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions,
|
|
76
|
+
};
|
|
77
|
+
return await fromAccount.createTxExecutionRequest(
|
|
78
|
+
feeExecutionPayload ?? ExecutionPayload.empty(),
|
|
79
|
+
feeOptions.gasSettings,
|
|
80
|
+
executionOptions,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async proveCancellationTx(
|
|
85
|
+
from: AztecAddress,
|
|
86
|
+
txNonce: Fr,
|
|
87
|
+
increasedFee: InteractionFeeOptions,
|
|
88
|
+
): Promise<TxProvingResult> {
|
|
89
|
+
const cancellationTxRequest = await this.createCancellationTxExecutionRequest(from, txNonce, increasedFee);
|
|
90
|
+
return await this.pxe.proveTx(cancellationTxRequest);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
override async getAccountFromAddress(address: AztecAddress) {
|
|
94
|
+
let account: Account | undefined;
|
|
95
|
+
if (address.equals(AztecAddress.ZERO)) {
|
|
96
|
+
const chainInfo = await this.getChainInfo();
|
|
97
|
+
account = new SignerlessAccount(chainInfo);
|
|
98
|
+
} else if (this.accountCache.has(address.toString())) {
|
|
99
|
+
return this.accountCache.get(address.toString())!;
|
|
100
|
+
} else {
|
|
101
|
+
const accountManager = await this.createOrRetrieveAccount(address);
|
|
102
|
+
account = await accountManager.getAccount();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!account) {
|
|
106
|
+
throw new Error(`Account not found in wallet for address: ${address}`);
|
|
107
|
+
}
|
|
108
|
+
return account;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private async createAccount(secret: Fr, salt: Fr, contract: AccountContract): Promise<AccountManager> {
|
|
112
|
+
const accountManager = await AccountManager.create(this, secret, contract, salt);
|
|
113
|
+
|
|
114
|
+
const instance = accountManager.getInstance();
|
|
115
|
+
const artifact = await contract.getContractArtifact();
|
|
116
|
+
|
|
117
|
+
await this.registerContract(instance, artifact, secret);
|
|
118
|
+
this.accountCache.set(accountManager.address.toString(), await accountManager.getAccount());
|
|
119
|
+
return accountManager;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async createOrRetrieveAccount(
|
|
123
|
+
address?: AztecAddress,
|
|
124
|
+
secretKey?: Fr,
|
|
125
|
+
type: AccountType = 'schnorr',
|
|
126
|
+
salt?: Fr,
|
|
127
|
+
publicKey?: string,
|
|
128
|
+
): Promise<AccountManager> {
|
|
129
|
+
let account;
|
|
130
|
+
|
|
131
|
+
salt ??= Fr.ZERO;
|
|
132
|
+
|
|
133
|
+
if (this.db && address) {
|
|
134
|
+
({ type, secretKey, salt } = await this.db.retrieveAccount(address));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!secretKey) {
|
|
138
|
+
throw new Error('Cannot retrieve/create wallet without secret key');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
switch (type) {
|
|
142
|
+
case 'schnorr': {
|
|
143
|
+
account = await this.createAccount(secretKey, salt, new SchnorrAccountContract(deriveSigningKey(secretKey)));
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
case 'ecdsasecp256r1': {
|
|
147
|
+
account = await this.createAccount(
|
|
148
|
+
secretKey,
|
|
149
|
+
salt,
|
|
150
|
+
new EcdsaRAccountContract(deriveSigningKey(secretKey).toBuffer()),
|
|
151
|
+
);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
case 'ecdsasecp256r1ssh': {
|
|
155
|
+
let publicSigningKey;
|
|
156
|
+
if (this.db && address) {
|
|
157
|
+
publicSigningKey = await this.db.retrieveAccountMetadata(address, 'publicSigningKey');
|
|
158
|
+
} else if (publicKey) {
|
|
159
|
+
const identities = await getIdentities();
|
|
160
|
+
const foundIdentity = identities.find(
|
|
161
|
+
identity => identity.type === 'ecdsa-sha2-nistp256' && identity.publicKey === publicKey,
|
|
162
|
+
);
|
|
163
|
+
if (!foundIdentity) {
|
|
164
|
+
throw new Error(`Identity for public key ${publicKey} not found in the SSH agent`);
|
|
165
|
+
}
|
|
166
|
+
publicSigningKey = extractECDSAPublicKeyFromBase64String(foundIdentity.publicKey);
|
|
167
|
+
} else {
|
|
168
|
+
throw new Error('Public key must be provided for ECDSA SSH account');
|
|
169
|
+
}
|
|
170
|
+
account = await this.createAccount(secretKey, salt, new EcdsaRSSHAccountContract(publicSigningKey));
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
default: {
|
|
174
|
+
throw new Error(`Unsupported account type: ${type}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return account;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private async getFakeAccountDataFor(address: AztecAddress) {
|
|
182
|
+
const chainInfo = await this.getChainInfo();
|
|
183
|
+
const originalAccount = await this.getAccountFromAddress(address);
|
|
184
|
+
const originalAddress = originalAccount.getCompleteAddress();
|
|
185
|
+
const { contractInstance } = await this.pxe.getContractMetadata(originalAddress.address);
|
|
186
|
+
if (!contractInstance) {
|
|
187
|
+
throw new Error(`No contract instance found for address: ${originalAddress.address}`);
|
|
188
|
+
}
|
|
189
|
+
const stubAccount = createStubAccount(originalAddress, chainInfo);
|
|
190
|
+
const instance = await getContractInstanceFromInstantiationParams(StubAccountContractArtifact, {
|
|
191
|
+
salt: Fr.random(),
|
|
192
|
+
});
|
|
193
|
+
return {
|
|
194
|
+
account: stubAccount,
|
|
195
|
+
instance,
|
|
196
|
+
artifact: StubAccountContractArtifact,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
override async simulateTx(executionPayload: ExecutionPayload, opts: SimulateOptions): Promise<TxSimulationResult> {
|
|
201
|
+
let simulationResults;
|
|
202
|
+
const feeOptions = opts.fee?.estimateGas
|
|
203
|
+
? await this.getFeeOptionsForGasEstimation(opts.from, opts.fee)
|
|
204
|
+
: await this.getDefaultFeeOptions(opts.from, opts.fee);
|
|
205
|
+
const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
|
|
206
|
+
const executionOptions: DefaultAccountEntrypointOptions = {
|
|
207
|
+
txNonce: Fr.random(),
|
|
208
|
+
cancellable: this.cancellableTransactions,
|
|
209
|
+
feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions,
|
|
210
|
+
};
|
|
211
|
+
const finalExecutionPayload = feeExecutionPayload
|
|
212
|
+
? mergeExecutionPayloads([feeExecutionPayload, executionPayload])
|
|
213
|
+
: executionPayload;
|
|
214
|
+
|
|
215
|
+
// Kernelless simulations using the multicall entrypoints are not currently supported,
|
|
216
|
+
// since we only override proper account contracts.
|
|
217
|
+
// TODO: allow disabling kernels even when no overrides are necessary
|
|
218
|
+
if (opts.from.equals(AztecAddress.ZERO)) {
|
|
219
|
+
const fromAccount = await this.getAccountFromAddress(opts.from);
|
|
220
|
+
const txRequest = await fromAccount.createTxExecutionRequest(
|
|
221
|
+
finalExecutionPayload,
|
|
222
|
+
feeOptions.gasSettings,
|
|
223
|
+
executionOptions,
|
|
224
|
+
);
|
|
225
|
+
simulationResults = await this.pxe.simulateTx(
|
|
226
|
+
txRequest,
|
|
227
|
+
true /* simulatePublic */,
|
|
228
|
+
opts?.skipTxValidation,
|
|
229
|
+
opts?.skipFeeEnforcement ?? true,
|
|
230
|
+
);
|
|
231
|
+
} else {
|
|
232
|
+
const { account: fromAccount, instance, artifact } = await this.getFakeAccountDataFor(opts.from);
|
|
233
|
+
const txRequest = await fromAccount.createTxExecutionRequest(
|
|
234
|
+
finalExecutionPayload,
|
|
235
|
+
feeOptions.gasSettings,
|
|
236
|
+
executionOptions,
|
|
237
|
+
);
|
|
238
|
+
const contractOverrides = {
|
|
239
|
+
[opts.from.toString()]: { instance, artifact },
|
|
240
|
+
};
|
|
241
|
+
simulationResults = await this.pxe.simulateTx(txRequest, true /* simulatePublic */, true, true, {
|
|
242
|
+
contracts: contractOverrides,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (opts.fee?.estimateGas) {
|
|
247
|
+
const limits = getGasLimits(simulationResults, opts.fee?.estimatedGasPadding);
|
|
248
|
+
printGasEstimates(feeOptions, limits, this.userLog);
|
|
249
|
+
}
|
|
250
|
+
return simulationResults;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Exposed because of the `aztec-wallet get-tx` command. It has been decided that it's fine to keep around because
|
|
254
|
+
// this is just a CLI wallet.
|
|
255
|
+
getContracts(): Promise<AztecAddress[]> {
|
|
256
|
+
return this.pxe.getContracts();
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Exposed because of the `aztec-wallet get-tx` command. It has been decided that it's fine to keep around because
|
|
260
|
+
// this is just a CLI wallet.
|
|
261
|
+
getNotes(filter: NotesFilter): Promise<UniqueNote[]> {
|
|
262
|
+
return this.pxe.getNotes(filter);
|
|
263
|
+
}
|
|
264
|
+
}
|
package/dest/cmds/cancel_tx.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { type AccountWalletWithSecretKey, type FeePaymentMethod, type TxHash } from '@aztec/aztec.js';
|
|
2
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
-
import type { LogFn } from '@aztec/foundation/log';
|
|
4
|
-
import { GasFees, GasSettings } from '@aztec/stdlib/gas';
|
|
5
|
-
export declare function cancelTx(wallet: AccountWalletWithSecretKey, { txHash, gasSettings: prevTxGasSettings, txNonce, cancellable, }: {
|
|
6
|
-
txHash: TxHash;
|
|
7
|
-
gasSettings: GasSettings;
|
|
8
|
-
txNonce: Fr;
|
|
9
|
-
cancellable: boolean;
|
|
10
|
-
}, paymentMethod: FeePaymentMethod, increasedFees: GasFees, maxFeesPerGas: GasFees | undefined, log: LogFn): Promise<void>;
|
|
11
|
-
//# sourceMappingURL=cancel_tx.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cancel_tx.d.ts","sourceRoot":"","sources":["../../src/cmds/cancel_tx.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,0BAA0B,EAAE,KAAK,gBAAgB,EAAU,KAAK,MAAM,EAAY,MAAM,iBAAiB,CAAC;AAGxH,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAC9C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIzD,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,0BAA0B,EAClC,EACE,MAAM,EACN,WAAW,EAAE,iBAAiB,EAC9B,OAAO,EACP,WAAW,GACZ,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,EAAE,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,EAClF,aAAa,EAAE,gBAAgB,EAC/B,aAAa,EAAE,OAAO,EACtB,aAAa,EAAE,OAAO,GAAG,SAAS,EAClC,GAAG,EAAE,KAAK,iBA6CX"}
|