@aztec/cli-wallet 0.0.0-test.0
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 +2 -0
- package/dest/bin/index.d.ts +2 -0
- package/dest/bin/index.d.ts.map +1 -0
- package/dest/bin/index.js +75 -0
- package/dest/cmds/add_authwit.d.ts +4 -0
- package/dest/cmds/add_authwit.d.ts.map +1 -0
- package/dest/cmds/add_authwit.js +4 -0
- package/dest/cmds/authorize_action.d.ts +4 -0
- package/dest/cmds/authorize_action.d.ts.map +1 -0
- package/dest/cmds/authorize_action.js +17 -0
- package/dest/cmds/bridge_fee_juice.d.ts +6 -0
- package/dest/cmds/bridge_fee_juice.d.ts.map +1 -0
- package/dest/cmds/bridge_fee_juice.js +52 -0
- package/dest/cmds/cancel_tx.d.ts +11 -0
- package/dest/cmds/cancel_tx.d.ts.map +1 -0
- package/dest/cmds/cancel_tx.js +38 -0
- package/dest/cmds/check_tx.d.ts +4 -0
- package/dest/cmds/check_tx.d.ts.map +1 -0
- package/dest/cmds/check_tx.js +11 -0
- package/dest/cmds/create_account.d.ts +12 -0
- package/dest/cmds/create_account.d.ts.map +1 -0
- package/dest/cmds/create_account.js +94 -0
- package/dest/cmds/create_authwit.d.ts +4 -0
- package/dest/cmds/create_authwit.d.ts.map +1 -0
- package/dest/cmds/create_authwit.js +16 -0
- package/dest/cmds/deploy.d.ts +6 -0
- package/dest/cmds/deploy.d.ts.map +1 -0
- package/dest/cmds/deploy.js +83 -0
- package/dest/cmds/deploy_account.d.ts +9 -0
- package/dest/cmds/deploy_account.d.ts.map +1 -0
- package/dest/cmds/deploy_account.js +80 -0
- package/dest/cmds/import_test_accounts.d.ts +5 -0
- package/dest/cmds/import_test_accounts.d.ts.map +1 -0
- package/dest/cmds/import_test_accounts.js +42 -0
- package/dest/cmds/index.d.ts +6 -0
- package/dest/cmds/index.d.ts.map +1 -0
- package/dest/cmds/index.js +223 -0
- package/dest/cmds/register_contract.d.ts +4 -0
- package/dest/cmds/register_contract.d.ts.map +1 -0
- package/dest/cmds/register_contract.js +14 -0
- package/dest/cmds/register_sender.d.ts +4 -0
- package/dest/cmds/register_sender.d.ts.map +1 -0
- package/dest/cmds/register_sender.js +4 -0
- package/dest/cmds/send.d.ts +11 -0
- package/dest/cmds/send.d.ts.map +1 -0
- package/dest/cmds/send.js +49 -0
- package/dest/cmds/simulate.d.ts +4 -0
- package/dest/cmds/simulate.d.ts.map +1 -0
- package/dest/cmds/simulate.js +26 -0
- package/dest/storage/wallet_db.d.ts +65 -0
- package/dest/storage/wallet_db.d.ts.map +1 -0
- package/dest/storage/wallet_db.js +209 -0
- package/dest/utils/accounts.d.ts +11 -0
- package/dest/utils/accounts.d.ts.map +1 -0
- package/dest/utils/accounts.js +87 -0
- package/dest/utils/ecdsa.d.ts +4 -0
- package/dest/utils/ecdsa.d.ts.map +1 -0
- package/dest/utils/ecdsa.js +13 -0
- package/dest/utils/options/fees.d.ts +41 -0
- package/dest/utils/options/fees.d.ts.map +1 -0
- package/dest/utils/options/fees.js +283 -0
- package/dest/utils/options/index.d.ts +3 -0
- package/dest/utils/options/index.d.ts.map +1 -0
- package/dest/utils/options/index.js +2 -0
- package/dest/utils/options/options.d.ts +20 -0
- package/dest/utils/options/options.d.ts.map +1 -0
- package/dest/utils/options/options.js +122 -0
- package/dest/utils/pxe_wrapper.d.ts +10 -0
- package/dest/utils/pxe_wrapper.d.ts.map +1 -0
- package/dest/utils/pxe_wrapper.js +21 -0
- package/package.json +102 -0
- package/src/bin/index.ts +127 -0
- package/src/cmds/add_authwit.ts +13 -0
- package/src/cmds/authorize_action.ts +36 -0
- package/src/cmds/bridge_fee_juice.ts +88 -0
- package/src/cmds/cancel_tx.ts +62 -0
- package/src/cmds/check_tx.ts +12 -0
- package/src/cmds/create_account.ts +120 -0
- package/src/cmds/create_authwit.ts +35 -0
- package/src/cmds/deploy.ts +113 -0
- package/src/cmds/deploy_account.ts +92 -0
- package/src/cmds/import_test_accounts.ts +47 -0
- package/src/cmds/index.ts +641 -0
- package/src/cmds/register_contract.ts +20 -0
- package/src/cmds/register_sender.ts +7 -0
- package/src/cmds/send.ts +62 -0
- package/src/cmds/simulate.ts +42 -0
- package/src/storage/wallet_db.ts +243 -0
- package/src/utils/accounts.ts +102 -0
- package/src/utils/ecdsa.ts +15 -0
- package/src/utils/options/fees.ts +365 -0
- package/src/utils/options/index.ts +2 -0
- package/src/utils/options/options.ts +175 -0
- package/src/utils/pxe_wrapper.ts +26 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AccountWallet,
|
|
3
|
+
type DeployAccountOptions,
|
|
4
|
+
FeeJuicePaymentMethod,
|
|
5
|
+
type FeePaymentMethod,
|
|
6
|
+
type PXE,
|
|
7
|
+
type SendMethodOptions,
|
|
8
|
+
} from '@aztec/aztec.js';
|
|
9
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
10
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
11
|
+
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
12
|
+
import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
|
|
13
|
+
|
|
14
|
+
import { Option } from 'commander';
|
|
15
|
+
|
|
16
|
+
import type { WalletDB } from '../../storage/wallet_db.js';
|
|
17
|
+
import { createOrRetrieveAccount } from '../accounts.js';
|
|
18
|
+
import { aliasedAddressParser } from './options.js';
|
|
19
|
+
|
|
20
|
+
export type CliFeeArgs = {
|
|
21
|
+
estimateGasOnly: boolean;
|
|
22
|
+
gasLimits?: string;
|
|
23
|
+
payment?: string;
|
|
24
|
+
maxFeesPerGas?: string;
|
|
25
|
+
maxPriorityFeesPerGas?: string;
|
|
26
|
+
estimateGas?: boolean;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export interface IFeeOpts {
|
|
30
|
+
estimateOnly: boolean;
|
|
31
|
+
gasSettings: GasSettings;
|
|
32
|
+
toSendOpts(sender: AccountWallet): Promise<SendMethodOptions>;
|
|
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
|
+
}
|
|
65
|
+
|
|
66
|
+
type OptionParams = {
|
|
67
|
+
[key: string]: { type: string; description?: string; default?: string };
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
function printOptionParams(params: OptionParams) {
|
|
71
|
+
const paramsWithDescription = Object.keys(params).filter(name => params[name].description);
|
|
72
|
+
const maxParamWidth = paramsWithDescription.reduce((v, name) => Math.max(v, name.length), 0);
|
|
73
|
+
const indent = (size: number) => ''.padEnd(size, ' ');
|
|
74
|
+
const descriptionList = paramsWithDescription.map(name =>
|
|
75
|
+
[
|
|
76
|
+
`${indent(5)}${name}${indent(maxParamWidth - name.length)} ${params[name].description}`,
|
|
77
|
+
params[name].default ? `Default: ${params[name].default}` : '',
|
|
78
|
+
].join(' '),
|
|
79
|
+
);
|
|
80
|
+
return descriptionList.length ? `\n Parameters:\n${descriptionList.join('\n')}` : '';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function getFeePaymentMethodParams(allowCustomFeePayer: boolean): OptionParams {
|
|
84
|
+
const feePayer = allowCustomFeePayer ? { type: 'address', description: 'The account paying the fee.' } : undefined;
|
|
85
|
+
return {
|
|
86
|
+
method: {
|
|
87
|
+
type: 'name',
|
|
88
|
+
description: 'Valid values: "fee_juice", "fpc-public", "fpc-private".',
|
|
89
|
+
default: 'fee_juice',
|
|
90
|
+
},
|
|
91
|
+
...(feePayer ? { feePayer } : {}),
|
|
92
|
+
asset: {
|
|
93
|
+
type: 'address',
|
|
94
|
+
description: 'The asset used for fee payment. Not required for the "fee_juice" method.',
|
|
95
|
+
},
|
|
96
|
+
fpc: {
|
|
97
|
+
type: 'address',
|
|
98
|
+
description: 'The FPC contract that pays in fee juice. Not required for the "fee_juice" method.',
|
|
99
|
+
},
|
|
100
|
+
claim: {
|
|
101
|
+
type: 'boolean',
|
|
102
|
+
description: 'Whether to use a previously stored claim to bridge fee juice.',
|
|
103
|
+
},
|
|
104
|
+
claimSecret: {
|
|
105
|
+
type: 'string',
|
|
106
|
+
description: 'The secret to claim fee juice on L1.',
|
|
107
|
+
},
|
|
108
|
+
claimAmount: {
|
|
109
|
+
type: 'bigint',
|
|
110
|
+
description: 'The amount of fee juice to be claimed.',
|
|
111
|
+
},
|
|
112
|
+
messageLeafIndex: {
|
|
113
|
+
type: 'bigint',
|
|
114
|
+
description: 'The index of the claim in the l1toL2Message tree.',
|
|
115
|
+
},
|
|
116
|
+
feeRecipient: {
|
|
117
|
+
type: 'string',
|
|
118
|
+
description: 'Recipient of the fee.',
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function getPaymentMethodOption(allowCustomFeePayer: boolean) {
|
|
124
|
+
const params = getFeePaymentMethodParams(allowCustomFeePayer);
|
|
125
|
+
const paramList = Object.keys(params).map(name => `${name}=${params[name].type}`);
|
|
126
|
+
return new Option(
|
|
127
|
+
`--payment <${paramList.join(',')}>`,
|
|
128
|
+
`Fee payment method and arguments.${printOptionParams(params)}`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function getFeeOptions(allowCustomFeePayer: boolean) {
|
|
133
|
+
return [
|
|
134
|
+
getPaymentMethodOption(allowCustomFeePayer),
|
|
135
|
+
new Option('--gas-limits <da=100,l2=100,teardownDA=10,teardownL2=10>', 'Gas limits for the tx.'),
|
|
136
|
+
new Option('--max-fees-per-gas <da=100,l2=100>', 'Maximum fees per gas unit for DA and L2 computation.'),
|
|
137
|
+
new Option(
|
|
138
|
+
'--max-priority-fees-per-gas <da=0,l2=0>',
|
|
139
|
+
'Maximum priority fees per gas unit for DA and L2 computation.',
|
|
140
|
+
),
|
|
141
|
+
new Option('--no-estimate-gas', 'Whether to automatically estimate gas limits for the tx.'),
|
|
142
|
+
new Option('--estimate-gas-only', 'Only report gas estimation for the tx, do not send it.'),
|
|
143
|
+
];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export class FeeOpts implements IFeeOpts {
|
|
147
|
+
constructor(
|
|
148
|
+
public estimateOnly: boolean,
|
|
149
|
+
public gasSettings: GasSettings,
|
|
150
|
+
private paymentMethodFactory: (sender: AccountWallet) => Promise<FeePaymentMethod>,
|
|
151
|
+
private getDeployWallet: (
|
|
152
|
+
sender: AccountWallet,
|
|
153
|
+
paymentMethod: FeePaymentMethod,
|
|
154
|
+
) => Promise<AccountWallet | undefined>,
|
|
155
|
+
private estimateGas: boolean,
|
|
156
|
+
) {}
|
|
157
|
+
|
|
158
|
+
async toSendOpts(sender: AccountWallet): Promise<SendMethodOptions> {
|
|
159
|
+
return {
|
|
160
|
+
fee: {
|
|
161
|
+
estimateGas: this.estimateGas,
|
|
162
|
+
gasSettings: this.gasSettings,
|
|
163
|
+
paymentMethod: await this.paymentMethodFactory(sender),
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async toDeployAccountOpts(sender: AccountWallet): Promise<DeployAccountOptions> {
|
|
169
|
+
const paymentMethod = await this.paymentMethodFactory(sender);
|
|
170
|
+
const deployWallet = await this.getDeployWallet(sender, paymentMethod);
|
|
171
|
+
return {
|
|
172
|
+
deployWallet,
|
|
173
|
+
fee: {
|
|
174
|
+
estimateGas: this.estimateGas,
|
|
175
|
+
gasSettings: this.gasSettings,
|
|
176
|
+
paymentMethod,
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
static paymentMethodOption() {
|
|
182
|
+
return getPaymentMethodOption(false);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
static getOptions() {
|
|
186
|
+
return getFeeOptions(false);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
static async fromCli(args: CliFeeArgs, pxe: PXE, log: LogFn, db?: WalletDB) {
|
|
190
|
+
const estimateOnly = args.estimateGasOnly;
|
|
191
|
+
const gasSettings = await parseGasSettings(args, pxe);
|
|
192
|
+
|
|
193
|
+
const defaultPaymentMethod = async (sender: AccountWallet) => {
|
|
194
|
+
const { FeeJuicePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
195
|
+
return new FeeJuicePaymentMethod(sender.getAddress());
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const getDeployWallet = () => {
|
|
199
|
+
// Returns undefined. The sender's wallet will be used by default.
|
|
200
|
+
return Promise.resolve(undefined);
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
return new FeeOpts(
|
|
204
|
+
estimateOnly,
|
|
205
|
+
gasSettings,
|
|
206
|
+
args.payment ? parsePaymentMethod(args.payment, false, log, db) : defaultPaymentMethod,
|
|
207
|
+
getDeployWallet,
|
|
208
|
+
!!args.estimateGas,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export class FeeOptsWithFeePayer extends FeeOpts {
|
|
214
|
+
static override paymentMethodOption() {
|
|
215
|
+
return getPaymentMethodOption(true);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
static override getOptions() {
|
|
219
|
+
return getFeeOptions(true);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
static override async fromCli(args: CliFeeArgs, pxe: PXE, log: LogFn, db?: WalletDB) {
|
|
223
|
+
const estimateOnly = args.estimateGasOnly;
|
|
224
|
+
const gasSettings = await parseGasSettings(args, pxe);
|
|
225
|
+
|
|
226
|
+
const defaultPaymentMethod = async (sender: AccountWallet) => {
|
|
227
|
+
const { FeeJuicePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
228
|
+
return new FeeJuicePaymentMethod(sender.getAddress());
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const getDeployWallet = async (sender: AccountWallet, paymentMethod: FeePaymentMethod) => {
|
|
232
|
+
if (paymentMethod instanceof FeeJuicePaymentMethod) {
|
|
233
|
+
const feePayer = await paymentMethod.getFeePayer();
|
|
234
|
+
if (!sender.getAddress().equals(feePayer)) {
|
|
235
|
+
return (await createOrRetrieveAccount(pxe, feePayer, db)).getWallet();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return undefined;
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
return new FeeOptsWithFeePayer(
|
|
242
|
+
estimateOnly,
|
|
243
|
+
gasSettings,
|
|
244
|
+
args.payment ? parsePaymentMethod(args.payment, true, log, db) : defaultPaymentMethod,
|
|
245
|
+
getDeployWallet,
|
|
246
|
+
!!args.estimateGas,
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export function parsePaymentMethod(
|
|
252
|
+
payment: string,
|
|
253
|
+
allowCustomFeePayer: boolean,
|
|
254
|
+
log: LogFn,
|
|
255
|
+
db?: WalletDB,
|
|
256
|
+
): (sender: AccountWallet) => Promise<FeePaymentMethod> {
|
|
257
|
+
const parsed = payment.split(',').reduce((acc, item) => {
|
|
258
|
+
const [dimension, value] = item.split('=');
|
|
259
|
+
acc[dimension] = value ?? 1;
|
|
260
|
+
return acc;
|
|
261
|
+
}, {} as Record<string, string>);
|
|
262
|
+
|
|
263
|
+
const getFpcOpts = (parsed: Record<string, string>, db?: WalletDB) => {
|
|
264
|
+
if (!parsed.fpc) {
|
|
265
|
+
throw new Error('Missing "fpc" in payment option');
|
|
266
|
+
}
|
|
267
|
+
if (!parsed.asset) {
|
|
268
|
+
throw new Error('Missing "asset" in payment option');
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const fpc = aliasedAddressParser('contracts', parsed.fpc, db);
|
|
272
|
+
|
|
273
|
+
return [AztecAddress.fromString(parsed.asset), fpc];
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
return async (sender: AccountWallet) => {
|
|
277
|
+
switch (parsed.method) {
|
|
278
|
+
case 'fee_juice': {
|
|
279
|
+
if (parsed.claim || (parsed.claimSecret && parsed.claimAmount && parsed.messageLeafIndex)) {
|
|
280
|
+
let claimAmount, claimSecret, messageLeafIndex;
|
|
281
|
+
if (parsed.claim && db) {
|
|
282
|
+
({
|
|
283
|
+
amount: claimAmount,
|
|
284
|
+
secret: claimSecret,
|
|
285
|
+
leafIndex: messageLeafIndex,
|
|
286
|
+
} = await db.popBridgedFeeJuice(sender.getAddress(), log));
|
|
287
|
+
} else {
|
|
288
|
+
({ claimAmount, claimSecret, messageLeafIndex } = parsed);
|
|
289
|
+
}
|
|
290
|
+
log(`Using Fee Juice for fee payments with claim for ${claimAmount} tokens`);
|
|
291
|
+
const { FeeJuicePaymentMethodWithClaim } = await import('@aztec/aztec.js/fee');
|
|
292
|
+
return new FeeJuicePaymentMethodWithClaim(sender, {
|
|
293
|
+
claimAmount: (typeof claimAmount === 'string'
|
|
294
|
+
? Fr.fromHexString(claimAmount)
|
|
295
|
+
: new Fr(claimAmount)
|
|
296
|
+
).toBigInt(),
|
|
297
|
+
claimSecret: Fr.fromHexString(claimSecret),
|
|
298
|
+
messageLeafIndex: BigInt(messageLeafIndex),
|
|
299
|
+
});
|
|
300
|
+
} else {
|
|
301
|
+
log(`Using Fee Juice for fee payment`);
|
|
302
|
+
const { FeeJuicePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
303
|
+
const feePayer =
|
|
304
|
+
parsed.feePayer && allowCustomFeePayer
|
|
305
|
+
? aliasedAddressParser('accounts', parsed.feePayer, db)
|
|
306
|
+
: sender.getAddress();
|
|
307
|
+
return new FeeJuicePaymentMethod(feePayer);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
case 'fpc-public': {
|
|
311
|
+
const [asset, fpc] = getFpcOpts(parsed, db);
|
|
312
|
+
log(`Using public fee payment with asset ${asset} via paymaster ${fpc}`);
|
|
313
|
+
const { PublicFeePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
314
|
+
return new PublicFeePaymentMethod(fpc, sender);
|
|
315
|
+
}
|
|
316
|
+
case 'fpc-private': {
|
|
317
|
+
const [asset, fpc] = getFpcOpts(parsed, db);
|
|
318
|
+
log(`Using private fee payment with asset ${asset} via paymaster ${fpc}`);
|
|
319
|
+
const { PrivateFeePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
320
|
+
return new PrivateFeePaymentMethod(fpc, sender);
|
|
321
|
+
}
|
|
322
|
+
case undefined:
|
|
323
|
+
throw new Error('Missing "method" in payment option');
|
|
324
|
+
default:
|
|
325
|
+
throw new Error(`Invalid fee payment method: ${payment}`);
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function parseGasLimits(gasLimits: string): { gasLimits: Gas; teardownGasLimits: Gas } {
|
|
331
|
+
const parsed = gasLimits.split(',').reduce((acc, limit) => {
|
|
332
|
+
const [dimension, value] = limit.split('=');
|
|
333
|
+
acc[dimension] = parseInt(value, 10);
|
|
334
|
+
return acc;
|
|
335
|
+
}, {} as Record<string, number>);
|
|
336
|
+
|
|
337
|
+
const expected = ['da', 'l2', 'teardownDA', 'teardownL2'];
|
|
338
|
+
for (const dimension of expected) {
|
|
339
|
+
if (!(dimension in parsed)) {
|
|
340
|
+
throw new Error(`Missing gas limit for ${dimension}`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return {
|
|
345
|
+
gasLimits: new Gas(parsed.da, parsed.l2),
|
|
346
|
+
teardownGasLimits: new Gas(parsed.teardownDA, parsed.teardownL2),
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export function parseGasFees(gasFees: string): GasFees {
|
|
351
|
+
const parsed = gasFees.split(',').reduce((acc, fee) => {
|
|
352
|
+
const [dimension, value] = fee.split('=');
|
|
353
|
+
acc[dimension] = parseInt(value, 10);
|
|
354
|
+
return acc;
|
|
355
|
+
}, {} as Record<string, number>);
|
|
356
|
+
|
|
357
|
+
const expected = ['da', 'l2'];
|
|
358
|
+
for (const dimension of expected) {
|
|
359
|
+
if (!(dimension in parsed)) {
|
|
360
|
+
throw new Error(`Missing gas fee for ${dimension}`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return new GasFees(parsed.da, parsed.l2);
|
|
365
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { parseAztecAddress, parseSecretKey, parseTxHash } from '@aztec/cli/utils';
|
|
2
|
+
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
3
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
4
|
+
|
|
5
|
+
import { Option } from 'commander';
|
|
6
|
+
import { readdir, stat } from 'fs/promises';
|
|
7
|
+
|
|
8
|
+
import type { AliasType, WalletDB } from '../../storage/wallet_db.js';
|
|
9
|
+
import { AccountTypes } from '../accounts.js';
|
|
10
|
+
|
|
11
|
+
const TARGET_DIR = 'target';
|
|
12
|
+
|
|
13
|
+
export const ARTIFACT_DESCRIPTION =
|
|
14
|
+
"Path to a compiled Aztec contract's artifact in JSON format. If executed inside a nargo workspace, a package and contract name can be specified as package@contract";
|
|
15
|
+
|
|
16
|
+
export function integerArgParser(
|
|
17
|
+
value: string,
|
|
18
|
+
argName: string,
|
|
19
|
+
min = Number.MIN_SAFE_INTEGER,
|
|
20
|
+
max = Number.MAX_SAFE_INTEGER,
|
|
21
|
+
) {
|
|
22
|
+
const parsed = parseInt(value, 10);
|
|
23
|
+
if (parsed < min) {
|
|
24
|
+
throw new Error(`${argName} must be greater than ${min}`);
|
|
25
|
+
}
|
|
26
|
+
if (parsed > max) {
|
|
27
|
+
throw new Error(`${argName} must be less than ${max}`);
|
|
28
|
+
}
|
|
29
|
+
return parsed;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function aliasedTxHashParser(txHash: string, db?: WalletDB) {
|
|
33
|
+
try {
|
|
34
|
+
return parseTxHash(txHash);
|
|
35
|
+
} catch (err) {
|
|
36
|
+
const prefixed = txHash.includes(':') ? txHash : `transactions:${txHash}`;
|
|
37
|
+
const rawTxHash = db ? db.tryRetrieveAlias(prefixed) : txHash;
|
|
38
|
+
return parseTxHash(rawTxHash);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function aliasedAuthWitParser(witness: string, db?: WalletDB) {
|
|
43
|
+
try {
|
|
44
|
+
return AuthWitness.fromString(witness);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
const prefixed = witness.includes(':') ? witness : `authwits:${witness}`;
|
|
47
|
+
const rawAuthWitness = db ? db.tryRetrieveAlias(prefixed) : witness;
|
|
48
|
+
return AuthWitness.fromString(rawAuthWitness);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function aliasedAddressParser(defaultPrefix: AliasType, address: string, db?: WalletDB) {
|
|
53
|
+
if (address.startsWith('0x')) {
|
|
54
|
+
return parseAztecAddress(address);
|
|
55
|
+
} else {
|
|
56
|
+
const prefixed = address.includes(':') ? address : `${defaultPrefix}:${address}`;
|
|
57
|
+
const rawAddress = db ? db.tryRetrieveAlias(prefixed) : address;
|
|
58
|
+
return parseAztecAddress(rawAddress);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function aliasedSecretKeyParser(sk: string, db?: WalletDB) {
|
|
63
|
+
if (sk.startsWith('0x')) {
|
|
64
|
+
return parseSecretKey(sk);
|
|
65
|
+
} else {
|
|
66
|
+
const prefixed = `${sk.startsWith('accounts') ? '' : 'accounts'}:${sk.endsWith(':sk') ? sk : `${sk}:sk`}`;
|
|
67
|
+
const rawSk = db ? db.tryRetrieveAlias(prefixed) : sk;
|
|
68
|
+
return parseSecretKey(rawSk);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function createAliasOption(description: string, hide: boolean) {
|
|
73
|
+
return new Option(`-a, --alias <string>`, description).hideHelp(hide);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function createAccountOption(description: string, hide: boolean, db?: WalletDB) {
|
|
77
|
+
return new Option(`-f, --from <string>`, description)
|
|
78
|
+
.hideHelp(hide)
|
|
79
|
+
.argParser(address => aliasedAddressParser('accounts', address, db));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function createTypeOption(mandatory: boolean) {
|
|
83
|
+
return new Option('-t, --type <string>', 'Type of account to create')
|
|
84
|
+
.choices(AccountTypes)
|
|
85
|
+
.default('schnorr')
|
|
86
|
+
.conflicts('account-or-address')
|
|
87
|
+
.makeOptionMandatory(mandatory);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function createArgsOption(isConstructor: boolean, db?: WalletDB) {
|
|
91
|
+
return new Option('--args [args...]', `${isConstructor ? 'Constructor' : 'Function'} arguments`)
|
|
92
|
+
.argParser((arg, prev: string[]) => {
|
|
93
|
+
const next = db?.tryRetrieveAlias(arg) || arg;
|
|
94
|
+
prev.push(next);
|
|
95
|
+
return prev;
|
|
96
|
+
})
|
|
97
|
+
.default([]);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function createContractAddressOption(db?: WalletDB) {
|
|
101
|
+
return new Option('-ca, --contract-address <address>', 'Aztec address of the contract.')
|
|
102
|
+
.argParser(address => aliasedAddressParser('contracts', address, db))
|
|
103
|
+
.makeOptionMandatory(true);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function artifactPathParser(filePath: string, db?: WalletDB) {
|
|
107
|
+
if (filePath.includes('@')) {
|
|
108
|
+
const [pkg, contractName] = filePath.split('@');
|
|
109
|
+
return contractArtifactFromWorkspace(pkg, contractName);
|
|
110
|
+
} else if (!new RegExp(/^(\.|\/|[A-Z]:).*\.json$/).test(filePath)) {
|
|
111
|
+
filePath = db ? db.tryRetrieveAlias(`artifacts:${filePath}`) : filePath;
|
|
112
|
+
}
|
|
113
|
+
if (!filePath) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
'This command has to be called from a nargo workspace or contract artifact path should be provided',
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
return Promise.resolve(filePath);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export async function artifactPathFromPromiseOrAlias(
|
|
122
|
+
artifactPathPromise: Promise<string>,
|
|
123
|
+
contractAddress: AztecAddress,
|
|
124
|
+
db?: WalletDB,
|
|
125
|
+
) {
|
|
126
|
+
let artifactPath = await artifactPathPromise;
|
|
127
|
+
|
|
128
|
+
if (db && !artifactPath) {
|
|
129
|
+
artifactPath = db.tryRetrieveAlias(`artifacts:${contractAddress.toString()}`);
|
|
130
|
+
if (!artifactPath) {
|
|
131
|
+
throw new Error(`No artifact found for contract address ${contractAddress}, please provide it via the -c option`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return artifactPath;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function createArtifactOption(db?: WalletDB) {
|
|
138
|
+
return new Option('-c, --contract-artifact <fileLocation>', ARTIFACT_DESCRIPTION)
|
|
139
|
+
.argParser(filePath => artifactPathParser(filePath, db))
|
|
140
|
+
.makeOptionMandatory(false);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function createProfileOption() {
|
|
144
|
+
return new Option(
|
|
145
|
+
'-p, --profile',
|
|
146
|
+
'Run the real prover and get the gate count for each function in the transaction.',
|
|
147
|
+
).default(false);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function contractArtifactFromWorkspace(pkg?: string, contractName?: string) {
|
|
151
|
+
const cwd = process.cwd();
|
|
152
|
+
try {
|
|
153
|
+
await stat(`${cwd}/Nargo.toml`);
|
|
154
|
+
} catch (e) {
|
|
155
|
+
throw new Error(
|
|
156
|
+
'Invalid contract artifact argument provided. To use this option, command should be called from a nargo workspace',
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
const filesInTarget = await readdir(`${cwd}/${TARGET_DIR}`);
|
|
160
|
+
const bestMatch = filesInTarget.filter(file => {
|
|
161
|
+
if (pkg && contractName) {
|
|
162
|
+
return file === `${pkg}-${contractName}.json`;
|
|
163
|
+
} else {
|
|
164
|
+
return file.endsWith('.json') && (file.includes(pkg || '') || file.includes(contractName || ''));
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
if (bestMatch.length === 0) {
|
|
168
|
+
throw new Error('No contract artifacts found in target directory with the specified criteria');
|
|
169
|
+
} else if (bestMatch.length > 1) {
|
|
170
|
+
throw new Error(
|
|
171
|
+
`Multiple contract artifacts found in target directory with the specified criteria ${bestMatch.join(', ')}`,
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
return `${cwd}/${TARGET_DIR}/${bestMatch[0]}`;
|
|
175
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type PXEServiceConfig, createPXEService, getPXEServiceConfig } from '@aztec/pxe/server';
|
|
2
|
+
import { type AztecNode, type PXE, createAztecNodeClient } from '@aztec/stdlib/interfaces/client';
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* Wrapper class for PXE service, avoids initialization issues due to
|
|
6
|
+
* closures when providing PXE service to injected commander.js commands
|
|
7
|
+
*/
|
|
8
|
+
export class PXEWrapper {
|
|
9
|
+
private static pxe: PXE | undefined;
|
|
10
|
+
private static node: AztecNode | undefined;
|
|
11
|
+
|
|
12
|
+
getPXE(): PXE | undefined {
|
|
13
|
+
return PXEWrapper.pxe;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getNode(): AztecNode | undefined {
|
|
17
|
+
return PXEWrapper.node;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async init(nodeUrl: string, dataDir: string, overridePXEServiceConfig?: Partial<PXEServiceConfig>) {
|
|
21
|
+
PXEWrapper.node = createAztecNodeClient(nodeUrl);
|
|
22
|
+
const pxeConfig = Object.assign(getPXEServiceConfig(), overridePXEServiceConfig);
|
|
23
|
+
pxeConfig.dataDirectory = dataDir;
|
|
24
|
+
PXEWrapper.pxe = await createPXEService(PXEWrapper.node, pxeConfig);
|
|
25
|
+
}
|
|
26
|
+
}
|