@aztec/cli-wallet 0.0.1-commit.f504929 → 0.0.1-commit.f5a9928
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/dest/bin/index.js +1 -1
- package/dest/cmds/check_tx.d.ts +1 -1
- package/dest/cmds/check_tx.d.ts.map +1 -1
- package/dest/cmds/check_tx.js +49 -21
- package/dest/cmds/create_account.d.ts +6 -3
- package/dest/cmds/create_account.d.ts.map +1 -1
- package/dest/cmds/create_account.js +48 -29
- package/dest/cmds/deploy.d.ts +5 -4
- package/dest/cmds/deploy.d.ts.map +1 -1
- package/dest/cmds/deploy.js +43 -40
- package/dest/cmds/deploy_account.d.ts +4 -3
- package/dest/cmds/deploy_account.d.ts.map +1 -1
- package/dest/cmds/deploy_account.js +23 -23
- package/dest/cmds/get_fee_juice_balance.d.ts +5 -0
- package/dest/cmds/get_fee_juice_balance.d.ts.map +1 -0
- package/dest/cmds/get_fee_juice_balance.js +27 -0
- package/dest/cmds/import_test_accounts.d.ts +1 -1
- package/dest/cmds/import_test_accounts.d.ts.map +1 -1
- package/dest/cmds/import_test_accounts.js +2 -1
- package/dest/cmds/index.d.ts +1 -1
- package/dest/cmds/index.d.ts.map +1 -1
- package/dest/cmds/index.js +36 -19
- package/dest/cmds/send.d.ts +4 -3
- package/dest/cmds/send.d.ts.map +1 -1
- package/dest/cmds/send.js +26 -28
- package/dest/cmds/simulate.d.ts +1 -1
- package/dest/cmds/simulate.d.ts.map +1 -1
- package/dest/cmds/simulate.js +2 -1
- package/dest/storage/wallet_db.d.ts +12 -4
- package/dest/storage/wallet_db.d.ts.map +1 -1
- package/dest/storage/wallet_db.js +29 -1
- package/dest/utils/constants.d.ts +2 -2
- package/dest/utils/constants.d.ts.map +1 -1
- package/dest/utils/constants.js +1 -0
- package/dest/utils/options/fees.d.ts +3 -2
- package/dest/utils/options/fees.d.ts.map +1 -1
- package/dest/utils/options/fees.js +36 -10
- package/dest/utils/options/options.d.ts +2 -2
- package/dest/utils/options/options.d.ts.map +1 -1
- package/dest/utils/options/options.js +5 -5
- package/dest/utils/wallet.d.ts +34 -10
- package/dest/utils/wallet.d.ts.map +1 -1
- package/dest/utils/wallet.js +174 -97
- package/package.json +16 -15
- package/src/bin/index.ts +1 -1
- package/src/cmds/check_tx.ts +57 -24
- package/src/cmds/create_account.ts +50 -29
- package/src/cmds/deploy.ts +40 -35
- package/src/cmds/deploy_account.ts +23 -15
- package/src/cmds/get_fee_juice_balance.ts +37 -0
- package/src/cmds/import_test_accounts.ts +12 -1
- package/src/cmds/index.ts +70 -14
- package/src/cmds/send.ts +23 -18
- package/src/cmds/simulate.ts +2 -1
- package/src/storage/wallet_db.ts +38 -2
- package/src/utils/constants.ts +7 -1
- package/src/utils/options/fees.ts +42 -10
- package/src/utils/options/options.ts +5 -5
- package/src/utils/wallet.ts +221 -134
package/src/cmds/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
ETHEREUM_HOSTS,
|
|
5
5
|
PRIVATE_KEY,
|
|
6
6
|
addOptions,
|
|
7
|
-
|
|
7
|
+
createSigningKeyOption,
|
|
8
8
|
l1ChainIdOption,
|
|
9
9
|
parseBigint,
|
|
10
10
|
parseFieldFromHexString,
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from '@aztec/cli/utils';
|
|
13
13
|
import { randomBytes } from '@aztec/foundation/crypto/random';
|
|
14
14
|
import type { LogFn, Logger } from '@aztec/foundation/log';
|
|
15
|
+
import { TxStatus } from '@aztec/stdlib/tx';
|
|
15
16
|
|
|
16
17
|
import { type Command, Option } from 'commander';
|
|
17
18
|
import inquirer from 'inquirer';
|
|
@@ -23,7 +24,7 @@ import {
|
|
|
23
24
|
ARTIFACT_DESCRIPTION,
|
|
24
25
|
CLIFeeArgs,
|
|
25
26
|
aliasedAddressParser,
|
|
26
|
-
|
|
27
|
+
aliasedSigningKeyParser,
|
|
27
28
|
aliasedTxHashParser,
|
|
28
29
|
artifactPathFromPromiseOrAlias,
|
|
29
30
|
artifactPathParser,
|
|
@@ -40,6 +41,17 @@ import {
|
|
|
40
41
|
integerArgParser,
|
|
41
42
|
} from '../utils/options/index.js';
|
|
42
43
|
|
|
44
|
+
function parseWaitForStatus(status: string): TxStatus {
|
|
45
|
+
switch (status) {
|
|
46
|
+
case 'proposed':
|
|
47
|
+
return TxStatus.PROPOSED;
|
|
48
|
+
case 'checkpointed':
|
|
49
|
+
return TxStatus.CHECKPOINTED;
|
|
50
|
+
default:
|
|
51
|
+
throw new Error(`Invalid wait-for-status: ${status}. Use 'proposed' or 'checkpointed'.`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
43
55
|
// TODO: This function is only used in 1 place so we could just inline this
|
|
44
56
|
export function injectCommands(
|
|
45
57
|
program: Command,
|
|
@@ -84,12 +96,17 @@ export function injectCommands(
|
|
|
84
96
|
'Public key that identifies a private signing key stored outside of the wallet. Used for ECDSA SSH accounts over the secp256r1 curve.',
|
|
85
97
|
)
|
|
86
98
|
.addOption(
|
|
87
|
-
|
|
88
|
-
|
|
99
|
+
createSigningKeyOption('Signing key for account. Uses random by default.', false, sk =>
|
|
100
|
+
aliasedSigningKeyParser(sk, db),
|
|
89
101
|
).conflicts('public-key'),
|
|
90
102
|
)
|
|
91
103
|
.addOption(createAliasOption('Alias for the account. Used for easy reference in subsequent commands.', !db))
|
|
92
104
|
.addOption(createTypeOption(true))
|
|
105
|
+
.option(
|
|
106
|
+
'-s, --salt <hex string>',
|
|
107
|
+
'Optional deployment salt as a hex string for generating the deployment address. Defaults to 0.',
|
|
108
|
+
parseFieldFromHexString,
|
|
109
|
+
)
|
|
93
110
|
.option(
|
|
94
111
|
'--register-only',
|
|
95
112
|
'Just register the account on the Wallet. Do not deploy or initialize the account contract.',
|
|
@@ -98,6 +115,7 @@ export function injectCommands(
|
|
|
98
115
|
// `options.wait` is default true. Passing `--no-wait` will set it to false.
|
|
99
116
|
// https://github.com/tj/commander.js#other-option-types-negatable-boolean-and-booleanvalue
|
|
100
117
|
.option('--no-wait', 'Skip waiting for the contract to be deployed. Print the hash of deployment transaction')
|
|
118
|
+
.option('--wait-for-status <status>', "Tx status to wait for: 'proposed' or 'checkpointed'", 'proposed')
|
|
101
119
|
.addOption(createVerboseOption());
|
|
102
120
|
|
|
103
121
|
addOptions(createAccountCommand, CLIFeeArgs.getOptions()).action(async (_options, command) => {
|
|
@@ -106,8 +124,10 @@ export function injectCommands(
|
|
|
106
124
|
const {
|
|
107
125
|
type,
|
|
108
126
|
from: parsedFromAddress,
|
|
109
|
-
|
|
127
|
+
signingKey,
|
|
128
|
+
salt,
|
|
110
129
|
wait,
|
|
130
|
+
waitForStatus: waitForStatusStr,
|
|
111
131
|
registerOnly,
|
|
112
132
|
skipInitialization,
|
|
113
133
|
publicDeploy,
|
|
@@ -136,7 +156,8 @@ export function injectCommands(
|
|
|
136
156
|
wallet,
|
|
137
157
|
node,
|
|
138
158
|
type,
|
|
139
|
-
|
|
159
|
+
signingKey,
|
|
160
|
+
salt,
|
|
140
161
|
publicKey,
|
|
141
162
|
alias,
|
|
142
163
|
parsedFromAddress,
|
|
@@ -146,14 +167,15 @@ export function injectCommands(
|
|
|
146
167
|
registerClass,
|
|
147
168
|
wait,
|
|
148
169
|
CLIFeeArgs.parse(options, log, db),
|
|
170
|
+
parseWaitForStatus(waitForStatusStr),
|
|
149
171
|
json,
|
|
150
172
|
verbose,
|
|
151
173
|
debugLogger,
|
|
152
174
|
log,
|
|
153
175
|
);
|
|
154
176
|
if (db) {
|
|
155
|
-
const { address, alias, secretKey, salt } = accountCreationResult;
|
|
156
|
-
await db.storeAccount(address, { type, secretKey, salt, alias, publicKey }, log);
|
|
177
|
+
const { address, alias, signingKey, secretKey, salt } = accountCreationResult;
|
|
178
|
+
await db.storeAccount(address, { type, signingKey, secretKey, salt, alias, publicKey }, log);
|
|
157
179
|
}
|
|
158
180
|
});
|
|
159
181
|
|
|
@@ -180,12 +202,22 @@ export function injectCommands(
|
|
|
180
202
|
'--skip-initialization',
|
|
181
203
|
'Skip initializing the account contract. Useful for publicly deploying an existing account.',
|
|
182
204
|
)
|
|
205
|
+
.option('--wait-for-status <status>', "Tx status to wait for: 'proposed' or 'checkpointed'", 'proposed')
|
|
183
206
|
.addOption(createVerboseOption());
|
|
184
207
|
|
|
185
208
|
addOptions(deployAccountCommand, CLIFeeArgs.getOptions()).action(async (parsedAccount, _options, command) => {
|
|
186
209
|
const { deployAccount } = await import('./deploy_account.js');
|
|
187
210
|
const options = command.optsWithGlobals();
|
|
188
|
-
const {
|
|
211
|
+
const {
|
|
212
|
+
wait,
|
|
213
|
+
waitForStatus: waitForStatusStr,
|
|
214
|
+
from: parsedFromAddress,
|
|
215
|
+
json,
|
|
216
|
+
registerClass,
|
|
217
|
+
skipInitialization,
|
|
218
|
+
publicDeploy,
|
|
219
|
+
verbose,
|
|
220
|
+
} = options;
|
|
189
221
|
|
|
190
222
|
const { wallet, node } = walletAndNodeWrapper;
|
|
191
223
|
|
|
@@ -199,6 +231,7 @@ export function injectCommands(
|
|
|
199
231
|
publicDeploy,
|
|
200
232
|
skipInitialization,
|
|
201
233
|
CLIFeeArgs.parse(options, log, db),
|
|
234
|
+
parseWaitForStatus(waitForStatusStr),
|
|
202
235
|
json,
|
|
203
236
|
verbose,
|
|
204
237
|
debugLogger,
|
|
@@ -219,7 +252,7 @@ export function injectCommands(
|
|
|
219
252
|
)
|
|
220
253
|
.option(
|
|
221
254
|
'-s, --salt <hex string>',
|
|
222
|
-
'Optional deployment salt as a hex string for generating the deployment address.',
|
|
255
|
+
'Optional deployment salt as a hex string for generating the deployment address. Defaults to random.',
|
|
223
256
|
parseFieldFromHexString,
|
|
224
257
|
)
|
|
225
258
|
.option('--universal', 'Do not mix the sender address into the deployment.')
|
|
@@ -238,6 +271,7 @@ export function injectCommands(
|
|
|
238
271
|
'The amount of time in seconds to wait for the deployment to post to L2',
|
|
239
272
|
).conflicts('wait'),
|
|
240
273
|
)
|
|
274
|
+
.option('--wait-for-status <status>', "Tx status to wait for: 'proposed' or 'checkpointed'", 'proposed')
|
|
241
275
|
.addOption(createVerboseOption());
|
|
242
276
|
|
|
243
277
|
addOptions(deployCommand, CLIFeeArgs.getOptions()).action(async (artifactPathPromise, _options, command) => {
|
|
@@ -249,6 +283,7 @@ export function injectCommands(
|
|
|
249
283
|
args,
|
|
250
284
|
salt,
|
|
251
285
|
wait,
|
|
286
|
+
waitForStatus: waitForStatusStr,
|
|
252
287
|
classRegistration,
|
|
253
288
|
init,
|
|
254
289
|
publicDeployment,
|
|
@@ -262,12 +297,12 @@ export function injectCommands(
|
|
|
262
297
|
const { wallet, node } = walletAndNodeWrapper;
|
|
263
298
|
const artifactPath = await artifactPathPromise;
|
|
264
299
|
|
|
265
|
-
debugLogger.info(`Using wallet with address ${parsedFromAddress
|
|
300
|
+
debugLogger.info(`Using wallet with address ${parsedFromAddress?.toString() ?? '<none>'}`);
|
|
266
301
|
|
|
267
302
|
const address = await deploy(
|
|
268
303
|
wallet,
|
|
269
304
|
node,
|
|
270
|
-
|
|
305
|
+
parsedFromAddress,
|
|
271
306
|
artifactPath,
|
|
272
307
|
json,
|
|
273
308
|
publicKey,
|
|
@@ -279,10 +314,12 @@ export function injectCommands(
|
|
|
279
314
|
typeof init === 'string' ? false : init,
|
|
280
315
|
wait,
|
|
281
316
|
CLIFeeArgs.parse(options, log, db),
|
|
282
|
-
|
|
317
|
+
parseWaitForStatus(waitForStatusStr),
|
|
283
318
|
verbose,
|
|
319
|
+
timeout,
|
|
284
320
|
debugLogger,
|
|
285
321
|
log,
|
|
322
|
+
universal,
|
|
286
323
|
);
|
|
287
324
|
if (db && address) {
|
|
288
325
|
await db.storeContract(address, artifactPath, log, alias);
|
|
@@ -308,6 +345,7 @@ export function injectCommands(
|
|
|
308
345
|
)
|
|
309
346
|
.addOption(createAccountOption('Alias or address of the account to send the transaction from', !db, db))
|
|
310
347
|
.option('--no-wait', 'Print transaction hash without waiting for it to be mined')
|
|
348
|
+
.option('--wait-for-status <status>', "Tx status to wait for: 'proposed' or 'checkpointed'", 'proposed')
|
|
311
349
|
.addOption(createVerboseOption());
|
|
312
350
|
|
|
313
351
|
addOptions(sendCommand, CLIFeeArgs.getOptions()).action(async (functionName, _options, command) => {
|
|
@@ -319,6 +357,7 @@ export function injectCommands(
|
|
|
319
357
|
contractAddress,
|
|
320
358
|
from: parsedFromAddress,
|
|
321
359
|
wait,
|
|
360
|
+
waitForStatus: waitForStatusStr,
|
|
322
361
|
alias,
|
|
323
362
|
authWitness: authWitnessArray,
|
|
324
363
|
verbose,
|
|
@@ -342,6 +381,7 @@ export function injectCommands(
|
|
|
342
381
|
alias,
|
|
343
382
|
CLIFeeArgs.parse(options, log, db),
|
|
344
383
|
authWitnesses,
|
|
384
|
+
parseWaitForStatus(waitForStatusStr),
|
|
345
385
|
verbose,
|
|
346
386
|
log,
|
|
347
387
|
);
|
|
@@ -359,7 +399,9 @@ export function injectCommands(
|
|
|
359
399
|
.addOption(createContractAddressOption(db))
|
|
360
400
|
.addOption(createArtifactOption(db))
|
|
361
401
|
.addOption(
|
|
362
|
-
|
|
402
|
+
createSigningKeyOption("The sender's signing key", !db, sk => aliasedSigningKeyParser(sk, db)).conflicts(
|
|
403
|
+
'account',
|
|
404
|
+
),
|
|
363
405
|
)
|
|
364
406
|
.addOption(createAuthwitnessOption('Authorization witness to use for the simulation', !db, db))
|
|
365
407
|
.addOption(createAccountOption('Alias or address of the account to simulate from', !db, db))
|
|
@@ -492,6 +534,20 @@ export function injectCommands(
|
|
|
492
534
|
}
|
|
493
535
|
});
|
|
494
536
|
|
|
537
|
+
program
|
|
538
|
+
.command('get-fee-juice-balance')
|
|
539
|
+
.description('Checks the Fee Juice balance for a given address.')
|
|
540
|
+
.argument('<address>', 'Aztec address or alias to check balance for', address =>
|
|
541
|
+
aliasedAddressParser('accounts', address, db),
|
|
542
|
+
)
|
|
543
|
+
.option('--json', 'Emit output as json')
|
|
544
|
+
.option('--exact', 'Show exact balance with all 18 decimal places')
|
|
545
|
+
.action(async (address, options) => {
|
|
546
|
+
const { getFeeJuiceBalanceCmd } = await import('./get_fee_juice_balance.js');
|
|
547
|
+
const { json, exact } = options;
|
|
548
|
+
await getFeeJuiceBalanceCmd(walletAndNodeWrapper.node, address, json, exact, log);
|
|
549
|
+
});
|
|
550
|
+
|
|
495
551
|
program
|
|
496
552
|
.command('create-authwit')
|
|
497
553
|
.description(
|
package/src/cmds/send.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { AztecAddress } from '@aztec/aztec.js/addresses';
|
|
2
2
|
import { AuthWitness } from '@aztec/aztec.js/authorization';
|
|
3
3
|
import { Contract, NO_WAIT, type SendInteractionOptions } from '@aztec/aztec.js/contracts';
|
|
4
|
-
import type
|
|
4
|
+
import { type AztecNode, waitForTx } from '@aztec/aztec.js/node';
|
|
5
5
|
import { prepTx } from '@aztec/cli/utils';
|
|
6
6
|
import type { LogFn } from '@aztec/foundation/log';
|
|
7
|
+
import { TxStatus } from '@aztec/stdlib/tx';
|
|
7
8
|
|
|
8
9
|
import { DEFAULT_TX_TIMEOUT_S } from '../utils/cli_wallet_and_node_wrapper.js';
|
|
9
10
|
import { CLIFeeArgs } from '../utils/options/fees.js';
|
|
@@ -22,6 +23,7 @@ export async function send(
|
|
|
22
23
|
cancellable: boolean,
|
|
23
24
|
feeOpts: CLIFeeArgs,
|
|
24
25
|
authWitnesses: AuthWitness[],
|
|
26
|
+
waitForStatus: TxStatus,
|
|
25
27
|
verbose: boolean,
|
|
26
28
|
log: LogFn,
|
|
27
29
|
) {
|
|
@@ -37,12 +39,13 @@ export async function send(
|
|
|
37
39
|
authWitnesses,
|
|
38
40
|
};
|
|
39
41
|
|
|
42
|
+
const localStart = performance.now();
|
|
40
43
|
const sim = await call.simulate({
|
|
41
44
|
...sendOptions,
|
|
42
|
-
|
|
45
|
+
includeMetadata: true,
|
|
43
46
|
});
|
|
44
|
-
//
|
|
45
|
-
const estimatedGas = sim.
|
|
47
|
+
// includeMetadata: true guarantees these fields are present
|
|
48
|
+
const estimatedGas = await wallet.estimateGasLimits(sim.gasUsed!);
|
|
46
49
|
const stats = sim.stats!;
|
|
47
50
|
|
|
48
51
|
if (feeOpts.estimateOnly) {
|
|
@@ -53,21 +56,29 @@ export async function send(
|
|
|
53
56
|
printProfileResult(stats!, log);
|
|
54
57
|
}
|
|
55
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
|
+
|
|
66
|
+
log(`\nTransaction hash: ${txHash.toString()}`);
|
|
67
|
+
|
|
56
68
|
if (wait) {
|
|
57
69
|
try {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
wait: { timeout: DEFAULT_TX_TIMEOUT_S },
|
|
62
|
-
});
|
|
70
|
+
const nodeStart = performance.now();
|
|
71
|
+
const receipt = await waitForTx(node, txHash, { timeout: DEFAULT_TX_TIMEOUT_S, waitForStatus });
|
|
72
|
+
const nodeTimeMs = performance.now() - nodeStart;
|
|
63
73
|
|
|
64
|
-
const
|
|
65
|
-
log(
|
|
66
|
-
log('Transaction has been mined');
|
|
74
|
+
const statusLabel = waitForStatus === TxStatus.PROPOSED ? 'proposed' : 'checkpointed';
|
|
75
|
+
log(`Transaction has been ${statusLabel}`);
|
|
67
76
|
log(` Tx fee: ${receipt.transactionFee}`);
|
|
68
77
|
log(` Status: ${receipt.status}`);
|
|
69
78
|
log(` Block number: ${receipt.blockNumber}`);
|
|
70
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`);
|
|
71
82
|
|
|
72
83
|
return {
|
|
73
84
|
txHash,
|
|
@@ -77,12 +88,6 @@ export async function send(
|
|
|
77
88
|
throw err;
|
|
78
89
|
}
|
|
79
90
|
} else {
|
|
80
|
-
const { txHash } = await call.send({
|
|
81
|
-
...sendOptions,
|
|
82
|
-
fee: { ...sendOptions.fee, gasSettings: estimatedGas },
|
|
83
|
-
wait: NO_WAIT,
|
|
84
|
-
});
|
|
85
|
-
log(`\nTransaction hash: ${txHash.toString()}`);
|
|
86
91
|
log('Transaction pending. Check status with check-tx');
|
|
87
92
|
return {
|
|
88
93
|
txHash,
|
package/src/cmds/simulate.ts
CHANGED
|
@@ -44,7 +44,8 @@ export async function simulate(
|
|
|
44
44
|
if (!metadata.instance) {
|
|
45
45
|
return undefined;
|
|
46
46
|
}
|
|
47
|
-
const
|
|
47
|
+
const classId = metadata.updatedContractClassId ?? metadata.instance.originalContractClassId;
|
|
48
|
+
const artifact = await wallet.getContractArtifact(classId);
|
|
48
49
|
return artifact;
|
|
49
50
|
},
|
|
50
51
|
log,
|
package/src/storage/wallet_db.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
|
+
import { GrumpkinScalar } from '@aztec/foundation/curves/grumpkin';
|
|
2
3
|
import type { LogFn } from '@aztec/foundation/log';
|
|
3
4
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
4
5
|
import type { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
@@ -70,17 +71,46 @@ export class WalletDB {
|
|
|
70
71
|
return { amount: BigInt(amountStr), secret: secretStr, leafIndex: BigInt(leafIndexStr) };
|
|
71
72
|
}
|
|
72
73
|
|
|
74
|
+
async peekBridgedFeeJuice(recipient: AztecAddress, log: LogFn) {
|
|
75
|
+
const stackPointer =
|
|
76
|
+
(await this.#bridgedFeeJuice.getAsync(`${recipient.toString()}:stackPointer`))?.readInt8() || 0;
|
|
77
|
+
const result = await this.#bridgedFeeJuice.getAsync(`${recipient.toString()}:${stackPointer}`);
|
|
78
|
+
if (!result) {
|
|
79
|
+
throw new Error(
|
|
80
|
+
`No stored fee juice available for recipient ${recipient.toString()}. Please provide claim amount and secret. Stack pointer ${stackPointer}`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
const [amountStr, secretStr, leafIndexStr] = result.toString().split(':');
|
|
84
|
+
log(`Peeked ${amountStr} fee juice for recipient ${recipient.toString()}. Stack pointer ${stackPointer}`);
|
|
85
|
+
return { amount: BigInt(amountStr), secret: secretStr, leafIndex: BigInt(leafIndexStr) };
|
|
86
|
+
}
|
|
87
|
+
|
|
73
88
|
async storeAccount(
|
|
74
89
|
address: AztecAddress,
|
|
75
90
|
{
|
|
76
91
|
type,
|
|
92
|
+
signingKey,
|
|
77
93
|
secretKey,
|
|
78
94
|
salt,
|
|
79
95
|
alias,
|
|
80
96
|
publicKey,
|
|
81
|
-
}: {
|
|
97
|
+
}: {
|
|
98
|
+
type: AccountType;
|
|
99
|
+
signingKey?: GrumpkinScalar;
|
|
100
|
+
secretKey?: Fr;
|
|
101
|
+
salt: Fr;
|
|
102
|
+
alias: string | undefined;
|
|
103
|
+
publicKey: string | undefined;
|
|
104
|
+
},
|
|
82
105
|
log: LogFn,
|
|
83
106
|
) {
|
|
107
|
+
// Even though the privacy secret key is sometimes derived from the signing key, we store it in the database
|
|
108
|
+
// regardless as that is not always the case. Local-key accounts also store their signing key, while external-key
|
|
109
|
+
// accounts such as SSH store only the privacy secret.
|
|
110
|
+
if (!secretKey) {
|
|
111
|
+
throw new Error('Cannot store account without a secret key');
|
|
112
|
+
}
|
|
113
|
+
|
|
84
114
|
let publicSigningKey: Buffer | undefined;
|
|
85
115
|
if (type === 'ecdsasecp256r1ssh' && publicKey) {
|
|
86
116
|
publicSigningKey = extractECDSAPublicKeyFromBase64String(publicKey);
|
|
@@ -92,6 +122,9 @@ export class WalletDB {
|
|
|
92
122
|
}
|
|
93
123
|
await this.#accounts.set(`${address.toString()}:type`, Buffer.from(type));
|
|
94
124
|
await this.#accounts.set(`${address.toString()}:sk`, secretKey.toBuffer());
|
|
125
|
+
if (signingKey) {
|
|
126
|
+
await this.#accounts.set(`${address.toString()}:signing`, signingKey.toBuffer());
|
|
127
|
+
}
|
|
95
128
|
await this.#accounts.set(`${address.toString()}:salt`, salt.toBuffer());
|
|
96
129
|
if (publicSigningKey) {
|
|
97
130
|
await this.#accounts.set(`${address.toString()}:publicSigningKey`, publicSigningKey);
|
|
@@ -212,10 +245,13 @@ export class WalletDB {
|
|
|
212
245
|
if (!secretKeyBuffer) {
|
|
213
246
|
throw new Error(`Could not find ${address}:sk. Account "${address.toString}" does not exist on this wallet.`);
|
|
214
247
|
}
|
|
248
|
+
const signingKeyBuffer = await this.#accounts.getAsync(`${address.toString()}:signing`);
|
|
215
249
|
const secretKey = Fr.fromBuffer(secretKeyBuffer);
|
|
250
|
+
// External-key accounts (e.g. SSH) store no signing key.
|
|
251
|
+
const signingKey = signingKeyBuffer ? GrumpkinScalar.fromBuffer(signingKeyBuffer) : undefined;
|
|
216
252
|
const salt = Fr.fromBuffer((await this.#accounts.getAsync(`${address.toString()}:salt`))!);
|
|
217
253
|
const type = (await this.#accounts.getAsync(`${address.toString()}:type`))!.toString('utf8') as AccountType;
|
|
218
|
-
return { address, secretKey, salt, type };
|
|
254
|
+
return { address, signingKey, secretKey, salt, type };
|
|
219
255
|
}
|
|
220
256
|
|
|
221
257
|
async storeAlias(type: AliasType, key: string, value: Buffer, log: LogFn) {
|
package/src/utils/constants.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
export const MIN_FEE_PADDING = 0.5;
|
|
2
2
|
|
|
3
|
-
export const AccountTypes = [
|
|
3
|
+
export const AccountTypes = [
|
|
4
|
+
'schnorr',
|
|
5
|
+
'schnorr_initializerless',
|
|
6
|
+
'ecdsasecp256r1',
|
|
7
|
+
'ecdsasecp256r1ssh',
|
|
8
|
+
'ecdsasecp256k1',
|
|
9
|
+
] as const;
|
|
4
10
|
export type AccountType = (typeof AccountTypes)[number];
|
|
@@ -5,7 +5,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
5
5
|
import type { LogFn } from '@aztec/foundation/log';
|
|
6
6
|
import type { FieldsOf } from '@aztec/foundation/types';
|
|
7
7
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
8
|
-
import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
|
|
8
|
+
import { Gas, GasFees, GasSettings, ManaUsageEstimate } from '@aztec/stdlib/gas';
|
|
9
9
|
import type { FeeOptions } from '@aztec/wallet-sdk/base-wallet';
|
|
10
10
|
|
|
11
11
|
import { Option } from 'commander';
|
|
@@ -115,6 +115,7 @@ export function parsePaymentMethod(
|
|
|
115
115
|
payment: string,
|
|
116
116
|
log: LogFn,
|
|
117
117
|
db?: WalletDB,
|
|
118
|
+
estimateOnly?: boolean,
|
|
118
119
|
): (wallet: Wallet, from: AztecAddress, gasSettings: GasSettings) => Promise<FeePaymentMethod | undefined> {
|
|
119
120
|
const parsed = payment.split(',').reduce(
|
|
120
121
|
(acc, item) => {
|
|
@@ -136,7 +137,7 @@ export function parsePaymentMethod(
|
|
|
136
137
|
if (!parsed.asset) {
|
|
137
138
|
throw new Error('Missing "asset" in payment option');
|
|
138
139
|
}
|
|
139
|
-
return AztecAddress.
|
|
140
|
+
return AztecAddress.fromStringUnsafe(parsed.asset);
|
|
140
141
|
};
|
|
141
142
|
|
|
142
143
|
return async (wallet: Wallet, from: AztecAddress, gasSettings: GasSettings) => {
|
|
@@ -149,7 +150,7 @@ export function parsePaymentMethod(
|
|
|
149
150
|
amount: claimAmount,
|
|
150
151
|
secret: claimSecret,
|
|
151
152
|
leafIndex: messageLeafIndex,
|
|
152
|
-
} = await db.popBridgedFeeJuice(from, log));
|
|
153
|
+
} = estimateOnly ? await db.peekBridgedFeeJuice(from, log) : await db.popBridgedFeeJuice(from, log));
|
|
153
154
|
} else {
|
|
154
155
|
({ claimAmount, claimSecret, messageLeafIndex } = parsed);
|
|
155
156
|
}
|
|
@@ -157,10 +158,10 @@ export function parsePaymentMethod(
|
|
|
157
158
|
const { FeeJuicePaymentMethodWithClaim } = await import('@aztec/aztec.js/fee');
|
|
158
159
|
return new FeeJuicePaymentMethodWithClaim(from, {
|
|
159
160
|
claimAmount: (typeof claimAmount === 'string'
|
|
160
|
-
? Fr.
|
|
161
|
+
? Fr.fromString(claimAmount)
|
|
161
162
|
: new Fr(claimAmount)
|
|
162
163
|
).toBigInt(),
|
|
163
|
-
claimSecret: Fr.
|
|
164
|
+
claimSecret: typeof claimSecret === 'string' ? Fr.fromString(claimSecret) : claimSecret,
|
|
164
165
|
messageLeafIndex: BigInt(messageLeafIndex),
|
|
165
166
|
});
|
|
166
167
|
} else {
|
|
@@ -171,6 +172,9 @@ export function parsePaymentMethod(
|
|
|
171
172
|
case 'fpc-public': {
|
|
172
173
|
const fpc = getFpc();
|
|
173
174
|
const asset = getAsset();
|
|
175
|
+
log(
|
|
176
|
+
`WARNING: fpc-public is deprecated and will not work on mainnet alpha. Use fee_juice or fpc-sponsored instead.`,
|
|
177
|
+
);
|
|
174
178
|
log(`Using public fee payment with asset ${asset} via paymaster ${fpc}`);
|
|
175
179
|
const { PublicFeePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
176
180
|
return new PublicFeePaymentMethod(fpc, from, wallet, gasSettings);
|
|
@@ -178,6 +182,9 @@ export function parsePaymentMethod(
|
|
|
178
182
|
case 'fpc-private': {
|
|
179
183
|
const fpc = getFpc();
|
|
180
184
|
const asset = getAsset();
|
|
185
|
+
log(
|
|
186
|
+
`WARNING: fpc-private is deprecated and will not work on mainnet alpha. Use fee_juice or fpc-sponsored instead.`,
|
|
187
|
+
);
|
|
181
188
|
log(`Using private fee payment with asset ${asset} via paymaster ${fpc}`);
|
|
182
189
|
const { PrivateFeePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
183
190
|
return new PrivateFeePaymentMethod(fpc, from, wallet, gasSettings);
|
|
@@ -250,8 +257,11 @@ export class CLIFeeArgs {
|
|
|
250
257
|
) {}
|
|
251
258
|
|
|
252
259
|
async toUserFeeOptions(node: AztecNode, wallet: Wallet, from: AztecAddress): Promise<ParsedFeeOptions> {
|
|
253
|
-
const
|
|
254
|
-
const
|
|
260
|
+
const minFees = await this.getMinFees(node);
|
|
261
|
+
const maxFeesPerGas = minFees.mul(1 + MIN_FEE_PADDING);
|
|
262
|
+
const { txsLimits } = await node.getNodeInfo();
|
|
263
|
+
const gasLimits = this.gasSettings.gasLimits ?? Gas.from(txsLimits.gas);
|
|
264
|
+
const gasSettings = GasSettings.fallback({ ...this.gasSettings, gasLimits, maxFeesPerGas });
|
|
255
265
|
const paymentMethod = await this.paymentMethod(wallet, from, gasSettings);
|
|
256
266
|
return {
|
|
257
267
|
paymentMethod,
|
|
@@ -259,10 +269,32 @@ export class CLIFeeArgs {
|
|
|
259
269
|
};
|
|
260
270
|
}
|
|
261
271
|
|
|
272
|
+
/**
|
|
273
|
+
* Returns the worst-case min fee across predicted future slots.
|
|
274
|
+
* Falls back to getCurrentMinFees if the node doesn't support getPredictedMinFees.
|
|
275
|
+
*/
|
|
276
|
+
private async getMinFees(node: AztecNode): Promise<GasFees> {
|
|
277
|
+
try {
|
|
278
|
+
const predicted = await node.getPredictedMinFees(ManaUsageEstimate.Limit);
|
|
279
|
+
if (predicted.length === 0) {
|
|
280
|
+
return node.getCurrentMinFees();
|
|
281
|
+
}
|
|
282
|
+
return predicted.reduce((worst, fees) => (fees.feePerL2Gas > worst.feePerL2Gas ? fees : worst));
|
|
283
|
+
} catch (err: any) {
|
|
284
|
+
// Fallback for old nodes that don't support getPredictedMinFees.
|
|
285
|
+
// Only fall back on method-not-found errors (JSON-RPC code -32601); rethrow others.
|
|
286
|
+
if (err?.cause?.code === -32601 || err?.message?.includes('Method not found')) {
|
|
287
|
+
return node.getCurrentMinFees();
|
|
288
|
+
}
|
|
289
|
+
throw err;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
262
293
|
static parse(args: RawCliFeeArgs, log: LogFn, db?: WalletDB): CLIFeeArgs {
|
|
294
|
+
const estimateOnly = !!args.estimateGasOnly;
|
|
263
295
|
return new CLIFeeArgs(
|
|
264
|
-
|
|
265
|
-
parsePaymentMethod(args.payment ?? 'method=fee_juice', log, db),
|
|
296
|
+
estimateOnly,
|
|
297
|
+
parsePaymentMethod(args.payment ?? 'method=fee_juice', log, db, estimateOnly),
|
|
266
298
|
parseGasSettings(args),
|
|
267
299
|
);
|
|
268
300
|
}
|
|
@@ -288,7 +320,7 @@ function formatGasEstimate(estimate: Pick<GasSettings, 'gasLimits' | 'teardownGa
|
|
|
288
320
|
}
|
|
289
321
|
|
|
290
322
|
function getEstimatedCost(estimate: Pick<GasSettings, 'gasLimits' | 'teardownGasLimits'>, maxFeesPerGas: GasFees) {
|
|
291
|
-
return GasSettings.
|
|
323
|
+
return GasSettings.fallback({ ...estimate, maxFeesPerGas })
|
|
292
324
|
.getFeeLimit()
|
|
293
325
|
.toBigInt();
|
|
294
326
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TxHash } from '@aztec/aztec.js/tx';
|
|
2
|
-
import { parseAztecAddress,
|
|
2
|
+
import { parseAztecAddress, parseSigningKey, parseTxHash } from '@aztec/cli/utils';
|
|
3
3
|
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
4
4
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
5
5
|
|
|
@@ -64,13 +64,13 @@ export function aliasedAddressParser(defaultPrefix: AliasType, address: string,
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
export function
|
|
67
|
+
export function aliasedSigningKeyParser(sk: string, db?: WalletDB) {
|
|
68
68
|
if (sk.startsWith('0x')) {
|
|
69
|
-
return
|
|
69
|
+
return parseSigningKey(sk);
|
|
70
70
|
} else {
|
|
71
|
-
const prefixed = `${sk.startsWith('accounts') ? '' : 'accounts'}:${sk.endsWith(':
|
|
71
|
+
const prefixed = `${sk.startsWith('accounts') ? '' : 'accounts'}:${sk.endsWith(':signing') ? sk : `${sk}:signing`}`;
|
|
72
72
|
const rawSk = db ? db.tryRetrieveAlias(prefixed) : sk;
|
|
73
|
-
return
|
|
73
|
+
return parseSigningKey(rawSk);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|