@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,209 @@
|
|
|
1
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import { GasSettings } from '@aztec/stdlib/gas';
|
|
3
|
+
import { extractECDSAPublicKeyFromBase64String } from '../utils/ecdsa.js';
|
|
4
|
+
export const Aliases = [
|
|
5
|
+
'accounts',
|
|
6
|
+
'contracts',
|
|
7
|
+
'artifacts',
|
|
8
|
+
'secrets',
|
|
9
|
+
'transactions',
|
|
10
|
+
'authwits'
|
|
11
|
+
];
|
|
12
|
+
export class WalletDB {
|
|
13
|
+
#accounts;
|
|
14
|
+
#aliases;
|
|
15
|
+
#bridgedFeeJuice;
|
|
16
|
+
#transactions;
|
|
17
|
+
static instance;
|
|
18
|
+
aliasCache = new Map();
|
|
19
|
+
static getInstance() {
|
|
20
|
+
if (!WalletDB.instance) {
|
|
21
|
+
WalletDB.instance = new WalletDB();
|
|
22
|
+
}
|
|
23
|
+
return WalletDB.instance;
|
|
24
|
+
}
|
|
25
|
+
async init(store) {
|
|
26
|
+
this.#accounts = store.openMap('accounts');
|
|
27
|
+
this.#aliases = store.openMap('aliases');
|
|
28
|
+
this.#bridgedFeeJuice = store.openMap('bridgedFeeJuice');
|
|
29
|
+
this.#transactions = store.openMap('transactions');
|
|
30
|
+
await this.refreshAliasCache();
|
|
31
|
+
}
|
|
32
|
+
async refreshAliasCache() {
|
|
33
|
+
this.aliasCache = new Map((await this.listAliases()).map(({ key, value })=>[
|
|
34
|
+
key,
|
|
35
|
+
value
|
|
36
|
+
]));
|
|
37
|
+
}
|
|
38
|
+
async pushBridgedFeeJuice(recipient, secret, amount, leafIndex, log) {
|
|
39
|
+
let stackPointer = (await this.#bridgedFeeJuice.getAsync(`${recipient.toString()}:stackPointer`))?.readInt8() || 0;
|
|
40
|
+
stackPointer++;
|
|
41
|
+
await this.#bridgedFeeJuice.set(`${recipient.toString()}:${stackPointer}`, Buffer.from(`${amount.toString()}:${secret.toString()}:${leafIndex.toString()}`));
|
|
42
|
+
await this.#bridgedFeeJuice.set(`${recipient.toString()}:stackPointer`, Buffer.from([
|
|
43
|
+
stackPointer
|
|
44
|
+
]));
|
|
45
|
+
log(`Pushed ${amount} fee juice for recipient ${recipient.toString()}. Stack pointer ${stackPointer}`);
|
|
46
|
+
}
|
|
47
|
+
async popBridgedFeeJuice(recipient, log) {
|
|
48
|
+
let stackPointer = (await this.#bridgedFeeJuice.getAsync(`${recipient.toString()}:stackPointer`))?.readInt8() || 0;
|
|
49
|
+
const result = await this.#bridgedFeeJuice.getAsync(`${recipient.toString()}:${stackPointer}`);
|
|
50
|
+
if (!result) {
|
|
51
|
+
throw new Error(`No stored fee juice available for recipient ${recipient.toString()}. Please provide claim amount and secret. Stack pointer ${stackPointer}`);
|
|
52
|
+
}
|
|
53
|
+
const [amountStr, secretStr, leafIndexStr] = result.toString().split(':');
|
|
54
|
+
await this.#bridgedFeeJuice.set(`${recipient.toString()}:stackPointer`, Buffer.from([
|
|
55
|
+
--stackPointer
|
|
56
|
+
]));
|
|
57
|
+
log(`Retrieved ${amountStr} fee juice for recipient ${recipient.toString()}. Stack pointer ${stackPointer}`);
|
|
58
|
+
return {
|
|
59
|
+
amount: BigInt(amountStr),
|
|
60
|
+
secret: secretStr,
|
|
61
|
+
leafIndex: BigInt(leafIndexStr)
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async storeAccount(address, { type, secretKey, salt, alias, publicKey }, log) {
|
|
65
|
+
if (alias) {
|
|
66
|
+
await this.#aliases.set(`accounts:${alias}`, Buffer.from(address.toString()));
|
|
67
|
+
}
|
|
68
|
+
await this.#accounts.set(`${address.toString()}:type`, Buffer.from(type));
|
|
69
|
+
await this.#accounts.set(`${address.toString()}:sk`, secretKey.toBuffer());
|
|
70
|
+
await this.#accounts.set(`${address.toString()}:salt`, salt.toBuffer());
|
|
71
|
+
if (type === 'ecdsasecp256r1ssh' && publicKey) {
|
|
72
|
+
const publicSigningKey = extractECDSAPublicKeyFromBase64String(publicKey);
|
|
73
|
+
await this.storeAccountMetadata(address, 'publicSigningKey', publicSigningKey);
|
|
74
|
+
}
|
|
75
|
+
await this.#aliases.set('accounts:last', Buffer.from(address.toString()));
|
|
76
|
+
log(`Account stored in database with alias${alias ? `es last & ${alias}` : ' last'}`);
|
|
77
|
+
await this.refreshAliasCache();
|
|
78
|
+
}
|
|
79
|
+
async storeSender(address, alias, log) {
|
|
80
|
+
await this.#aliases.set(`accounts:${alias}`, Buffer.from(address.toString()));
|
|
81
|
+
log(`Account stored in database with alias ${alias} as a sender`);
|
|
82
|
+
await this.refreshAliasCache();
|
|
83
|
+
}
|
|
84
|
+
async storeContract(address, artifactPath, log, alias) {
|
|
85
|
+
if (alias) {
|
|
86
|
+
await this.#aliases.set(`contracts:${alias}`, Buffer.from(address.toString()));
|
|
87
|
+
await this.#aliases.set(`artifacts:${alias}`, Buffer.from(artifactPath));
|
|
88
|
+
}
|
|
89
|
+
await this.#aliases.set(`contracts:last`, Buffer.from(address.toString()));
|
|
90
|
+
await this.#aliases.set(`artifacts:last`, Buffer.from(artifactPath));
|
|
91
|
+
await this.#aliases.set(`artifacts:${address.toString()}`, Buffer.from(artifactPath));
|
|
92
|
+
log(`Contract stored in database with alias${alias ? `es last & ${alias}` : ' last'}`);
|
|
93
|
+
await this.refreshAliasCache();
|
|
94
|
+
}
|
|
95
|
+
async storeAuthwitness(authWit, log, alias) {
|
|
96
|
+
if (alias) {
|
|
97
|
+
await this.#aliases.set(`authwits:${alias}`, Buffer.from(authWit.toString()));
|
|
98
|
+
}
|
|
99
|
+
await this.#aliases.set(`authwits:last`, Buffer.from(authWit.toString()));
|
|
100
|
+
log(`Authorization witness stored in database with alias${alias ? `es last & ${alias}` : ' last'}`);
|
|
101
|
+
await this.refreshAliasCache();
|
|
102
|
+
}
|
|
103
|
+
async storeTx({ txHash, nonce, cancellable, gasSettings }, log, alias) {
|
|
104
|
+
if (alias) {
|
|
105
|
+
await this.#aliases.set(`transactions:${alias}`, Buffer.from(txHash.toString()));
|
|
106
|
+
}
|
|
107
|
+
await this.#transactions.set(`${txHash.toString()}:nonce`, nonce.toBuffer());
|
|
108
|
+
await this.#transactions.set(`${txHash.toString()}:cancellable`, Buffer.from(cancellable ? 'true' : 'false'));
|
|
109
|
+
await this.#transactions.set(`${txHash.toString()}:gasSettings`, gasSettings.toBuffer());
|
|
110
|
+
await this.#aliases.set(`transactions:last`, Buffer.from(txHash.toString()));
|
|
111
|
+
log(`Transaction hash stored in database with alias${alias ? `es last & ${alias}` : ' last'}`);
|
|
112
|
+
await this.refreshAliasCache();
|
|
113
|
+
}
|
|
114
|
+
async retrieveTxData(txHash) {
|
|
115
|
+
const nonceBuffer = await this.#transactions.getAsync(`${txHash.toString()}:nonce`);
|
|
116
|
+
if (!nonceBuffer) {
|
|
117
|
+
throw new Error(`Could not find ${txHash.toString()}:nonce. Transaction with hash "${txHash.toString()}" does not exist on this wallet.`);
|
|
118
|
+
}
|
|
119
|
+
const nonce = Fr.fromBuffer(nonceBuffer);
|
|
120
|
+
const cancellable = (await this.#transactions.getAsync(`${txHash.toString()}:cancellable`)).toString() === 'true';
|
|
121
|
+
const gasBuffer = await this.#transactions.getAsync(`${txHash.toString()}:gasSettings`);
|
|
122
|
+
return {
|
|
123
|
+
txHash,
|
|
124
|
+
nonce,
|
|
125
|
+
cancellable,
|
|
126
|
+
gasSettings: GasSettings.fromBuffer(gasBuffer)
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
tryRetrieveAlias(arg) {
|
|
130
|
+
try {
|
|
131
|
+
return this.retrieveAliasFromCache(arg);
|
|
132
|
+
} catch (e) {
|
|
133
|
+
return arg;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
retrieveAliasFromCache(arg) {
|
|
137
|
+
if (Aliases.find((alias)=>arg.startsWith(`${alias}:`))) {
|
|
138
|
+
const [type, ...alias] = arg.split(':');
|
|
139
|
+
const aliasKey = `${type}:${alias.join(':') ?? 'last'}`;
|
|
140
|
+
const data = this.aliasCache.get(aliasKey);
|
|
141
|
+
if (!data) {
|
|
142
|
+
throw new Error(`Could not find alias ${arg}`);
|
|
143
|
+
}
|
|
144
|
+
return data.toString();
|
|
145
|
+
} else {
|
|
146
|
+
throw new Error(`Aliases must start with one of ${Aliases.join(', ')}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async retrieveAlias(arg) {
|
|
150
|
+
if (Aliases.find((alias)=>arg.startsWith(`${alias}:`))) {
|
|
151
|
+
const [type, ...alias] = arg.split(':');
|
|
152
|
+
const data = await this.#aliases.getAsync(`${type}:${alias.join(':') ?? 'last'}`);
|
|
153
|
+
if (!data) {
|
|
154
|
+
throw new Error(`Could not find alias ${arg}`);
|
|
155
|
+
}
|
|
156
|
+
return data.toString();
|
|
157
|
+
} else {
|
|
158
|
+
throw new Error(`Aliases must start with one of ${Aliases.join(', ')}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async listAliases(type) {
|
|
162
|
+
const result = [];
|
|
163
|
+
if (type && !Aliases.includes(type)) {
|
|
164
|
+
throw new Error(`Unknown alias type ${type}`);
|
|
165
|
+
}
|
|
166
|
+
for await (const [key, value] of this.#aliases.entriesAsync()){
|
|
167
|
+
if (!type || key.startsWith(`${type}:`)) {
|
|
168
|
+
result.push({
|
|
169
|
+
key,
|
|
170
|
+
value: value.toString()
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
async storeAccountMetadata(aliasOrAddress, metadataKey, metadata) {
|
|
177
|
+
const { address } = await this.retrieveAccount(aliasOrAddress);
|
|
178
|
+
await this.#accounts.set(`${address.toString()}:${metadataKey}`, metadata);
|
|
179
|
+
}
|
|
180
|
+
async retrieveAccountMetadata(aliasOrAddress, metadataKey) {
|
|
181
|
+
const { address } = await this.retrieveAccount(aliasOrAddress);
|
|
182
|
+
const result = await this.#accounts.getAsync(`${address.toString()}:${metadataKey}`);
|
|
183
|
+
if (!result) {
|
|
184
|
+
throw new Error(`Could not find metadata with key ${metadataKey} for account ${aliasOrAddress}`);
|
|
185
|
+
}
|
|
186
|
+
return result;
|
|
187
|
+
}
|
|
188
|
+
async retrieveAccount(address) {
|
|
189
|
+
const secretKeyBuffer = await this.#accounts.getAsync(`${address.toString()}:sk`);
|
|
190
|
+
if (!secretKeyBuffer) {
|
|
191
|
+
throw new Error(`Could not find ${address}:sk. Account "${address.toString}" does not exist on this wallet.`);
|
|
192
|
+
}
|
|
193
|
+
const secretKey = Fr.fromBuffer(secretKeyBuffer);
|
|
194
|
+
const salt = Fr.fromBuffer(await this.#accounts.getAsync(`${address.toString()}:salt`));
|
|
195
|
+
const type = (await this.#accounts.getAsync(`${address.toString()}:type`)).toString('utf8');
|
|
196
|
+
return {
|
|
197
|
+
address,
|
|
198
|
+
secretKey,
|
|
199
|
+
salt,
|
|
200
|
+
type
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
async storeAlias(type, key, value, log) {
|
|
204
|
+
await this.#aliases.set(`${type}:${key}`, value);
|
|
205
|
+
await this.refreshAliasCache();
|
|
206
|
+
log(`Data stored in database with alias ${type}:${key}`);
|
|
207
|
+
await this.refreshAliasCache();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AccountManager, AccountWalletWithSecretKey } from '@aztec/aztec.js';
|
|
2
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
+
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
4
|
+
import type { PXE } from '@aztec/stdlib/interfaces/client';
|
|
5
|
+
import type { WalletDB } from '../storage/wallet_db.js';
|
|
6
|
+
export declare const AccountTypes: readonly ["schnorr", "ecdsasecp256r1ssh", "ecdsasecp256k1"];
|
|
7
|
+
export type AccountType = (typeof AccountTypes)[number];
|
|
8
|
+
export declare function createOrRetrieveAccount(pxe: PXE, address?: AztecAddress, db?: WalletDB, secretKey?: Fr, type?: AccountType, salt?: Fr, publicKey?: string | undefined): Promise<AccountManager>;
|
|
9
|
+
export declare function addScopeToWallet(wallet: AccountWalletWithSecretKey, scope: AztecAddress, db?: WalletDB): Promise<void>;
|
|
10
|
+
export declare function getWalletWithScopes(account: AccountManager, db?: WalletDB): Promise<AccountWalletWithSecretKey>;
|
|
11
|
+
//# sourceMappingURL=accounts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../src/utils/accounts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAC;AAG3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAGxD,eAAO,MAAM,YAAY,6DAA8D,CAAC;AACxF,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,GAAG,EACR,OAAO,CAAC,EAAE,YAAY,EACtB,EAAE,CAAC,EAAE,QAAQ,EACb,SAAS,CAAC,EAAE,EAAE,EACd,IAAI,GAAE,WAAuB,EAC7B,IAAI,CAAC,EAAE,EAAE,EACT,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC,cAAc,CAAC,CAkDzB;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,0BAA0B,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,QAAQ,iBAU5G;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,CAAC,EAAE,QAAQ,uCAgB/E"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { getIdentities } from '@aztec/accounts/utils';
|
|
2
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
+
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
4
|
+
import { deriveSigningKey } from '@aztec/stdlib/keys';
|
|
5
|
+
import { extractECDSAPublicKeyFromBase64String } from './ecdsa.js';
|
|
6
|
+
export const AccountTypes = [
|
|
7
|
+
'schnorr',
|
|
8
|
+
'ecdsasecp256r1ssh',
|
|
9
|
+
'ecdsasecp256k1'
|
|
10
|
+
];
|
|
11
|
+
export async function createOrRetrieveAccount(pxe, address, db, secretKey, type = 'schnorr', salt, publicKey) {
|
|
12
|
+
let account;
|
|
13
|
+
salt ??= Fr.ZERO;
|
|
14
|
+
if (db && address) {
|
|
15
|
+
({ type, secretKey, salt } = await db.retrieveAccount(address));
|
|
16
|
+
}
|
|
17
|
+
if (!salt) {
|
|
18
|
+
throw new Error('Cannot retrieve/create wallet without salt');
|
|
19
|
+
}
|
|
20
|
+
if (!secretKey) {
|
|
21
|
+
throw new Error('Cannot retrieve/create wallet without secret key');
|
|
22
|
+
}
|
|
23
|
+
switch(type){
|
|
24
|
+
case 'schnorr':
|
|
25
|
+
{
|
|
26
|
+
const { getSchnorrAccount } = await import('@aztec/accounts/schnorr');
|
|
27
|
+
account = getSchnorrAccount(pxe, secretKey, deriveSigningKey(secretKey), salt);
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
case 'ecdsasecp256r1ssh':
|
|
31
|
+
{
|
|
32
|
+
let publicSigningKey;
|
|
33
|
+
if (db && address) {
|
|
34
|
+
publicSigningKey = await db.retrieveAccountMetadata(address, 'publicSigningKey');
|
|
35
|
+
} else if (publicKey) {
|
|
36
|
+
const identities = await getIdentities();
|
|
37
|
+
const foundIdentity = identities.find((identity)=>identity.type === 'ecdsa-sha2-nistp256' && identity.publicKey === publicKey);
|
|
38
|
+
if (!foundIdentity) {
|
|
39
|
+
throw new Error(`Identity for public key ${publicKey} not found in the SSH agent`);
|
|
40
|
+
}
|
|
41
|
+
publicSigningKey = extractECDSAPublicKeyFromBase64String(foundIdentity.publicKey);
|
|
42
|
+
} else {
|
|
43
|
+
throw new Error('Public key must be provided for ECDSA SSH account');
|
|
44
|
+
}
|
|
45
|
+
const { getEcdsaRSSHAccount } = await import('@aztec/accounts/ecdsa');
|
|
46
|
+
account = getEcdsaRSSHAccount(pxe, secretKey, publicSigningKey, salt);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
default:
|
|
50
|
+
{
|
|
51
|
+
throw new Error(`Unsupported account type: ${type}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return account;
|
|
55
|
+
}
|
|
56
|
+
export async function addScopeToWallet(wallet, scope, db) {
|
|
57
|
+
const address = wallet.getAddress().toString();
|
|
58
|
+
const currentScopes = wallet.getScopes() ?? [];
|
|
59
|
+
const deduplicatedScopes = Array.from(new Set([
|
|
60
|
+
address,
|
|
61
|
+
...currentScopes,
|
|
62
|
+
scope
|
|
63
|
+
].map((scope)=>scope.toString())).values());
|
|
64
|
+
if (db) {
|
|
65
|
+
await db.storeAccountMetadata(wallet.getAddress(), 'scopes', Buffer.from(deduplicatedScopes.join(',')));
|
|
66
|
+
}
|
|
67
|
+
wallet.setScopes(deduplicatedScopes.map((scope)=>AztecAddress.fromString(scope)));
|
|
68
|
+
}
|
|
69
|
+
export async function getWalletWithScopes(account, db) {
|
|
70
|
+
const wallet = await account.getWallet();
|
|
71
|
+
if (db) {
|
|
72
|
+
const address = wallet.getAddress().toString();
|
|
73
|
+
let storedScopes = [];
|
|
74
|
+
try {
|
|
75
|
+
storedScopes = (await db.retrieveAccountMetadata(wallet.getAddress(), 'scopes') ?? '').toString().split(',');
|
|
76
|
+
// eslint-disable-next-line no-empty
|
|
77
|
+
} catch {}
|
|
78
|
+
const currentScopes = wallet.getScopes()?.map((scopes)=>scopes.toString()) ?? [];
|
|
79
|
+
const deduplicatedScopes = Array.from(new Set([
|
|
80
|
+
address,
|
|
81
|
+
...currentScopes,
|
|
82
|
+
...storedScopes
|
|
83
|
+
]).values()).map((scope)=>AztecAddress.fromString(scope));
|
|
84
|
+
wallet.setScopes(deduplicatedScopes);
|
|
85
|
+
}
|
|
86
|
+
return wallet;
|
|
87
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ecdsa.d.ts","sourceRoot":"","sources":["../../src/utils/ecdsa.ts"],"names":[],"mappings":";;AAAA,wBAAgB,qCAAqC,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAcrF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function extractECDSAPublicKeyFromBase64String(base64PublicKey) {
|
|
2
|
+
const buffer = Buffer.from(base64PublicKey, 'base64');
|
|
3
|
+
let keyOffset = 0;
|
|
4
|
+
const typeLen = buffer.readUInt32BE(keyOffset);
|
|
5
|
+
keyOffset += 4;
|
|
6
|
+
keyOffset += typeLen;
|
|
7
|
+
const curveLen = buffer.readUInt32BE(keyOffset);
|
|
8
|
+
keyOffset += 4;
|
|
9
|
+
keyOffset += curveLen;
|
|
10
|
+
const keyLen = buffer.readUInt32BE(keyOffset);
|
|
11
|
+
keyOffset += 5; // 4+1 to remove the prefix
|
|
12
|
+
return buffer.subarray(keyOffset, keyOffset + keyLen - 1);
|
|
13
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type AccountWallet, type DeployAccountOptions, type FeePaymentMethod, type PXE, type SendMethodOptions } from '@aztec/aztec.js';
|
|
2
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
3
|
+
import { GasFees, GasSettings } from '@aztec/stdlib/gas';
|
|
4
|
+
import { Option } from 'commander';
|
|
5
|
+
import type { WalletDB } from '../../storage/wallet_db.js';
|
|
6
|
+
export type CliFeeArgs = {
|
|
7
|
+
estimateGasOnly: boolean;
|
|
8
|
+
gasLimits?: string;
|
|
9
|
+
payment?: string;
|
|
10
|
+
maxFeesPerGas?: string;
|
|
11
|
+
maxPriorityFeesPerGas?: string;
|
|
12
|
+
estimateGas?: boolean;
|
|
13
|
+
};
|
|
14
|
+
export interface IFeeOpts {
|
|
15
|
+
estimateOnly: boolean;
|
|
16
|
+
gasSettings: GasSettings;
|
|
17
|
+
toSendOpts(sender: AccountWallet): Promise<SendMethodOptions>;
|
|
18
|
+
toDeployAccountOpts(sender: AccountWallet): Promise<DeployAccountOptions>;
|
|
19
|
+
}
|
|
20
|
+
export declare function printGasEstimates(feeOpts: IFeeOpts, gasEstimates: Pick<GasSettings, 'gasLimits' | 'teardownGasLimits'>, log: LogFn): void;
|
|
21
|
+
export declare class FeeOpts implements IFeeOpts {
|
|
22
|
+
estimateOnly: boolean;
|
|
23
|
+
gasSettings: GasSettings;
|
|
24
|
+
private paymentMethodFactory;
|
|
25
|
+
private getDeployWallet;
|
|
26
|
+
private estimateGas;
|
|
27
|
+
constructor(estimateOnly: boolean, gasSettings: GasSettings, paymentMethodFactory: (sender: AccountWallet) => Promise<FeePaymentMethod>, getDeployWallet: (sender: AccountWallet, paymentMethod: FeePaymentMethod) => Promise<AccountWallet | undefined>, estimateGas: boolean);
|
|
28
|
+
toSendOpts(sender: AccountWallet): Promise<SendMethodOptions>;
|
|
29
|
+
toDeployAccountOpts(sender: AccountWallet): Promise<DeployAccountOptions>;
|
|
30
|
+
static paymentMethodOption(): Option;
|
|
31
|
+
static getOptions(): Option[];
|
|
32
|
+
static fromCli(args: CliFeeArgs, pxe: PXE, log: LogFn, db?: WalletDB): Promise<FeeOpts>;
|
|
33
|
+
}
|
|
34
|
+
export declare class FeeOptsWithFeePayer extends FeeOpts {
|
|
35
|
+
static paymentMethodOption(): Option;
|
|
36
|
+
static getOptions(): Option[];
|
|
37
|
+
static fromCli(args: CliFeeArgs, pxe: PXE, log: LogFn, db?: WalletDB): Promise<FeeOptsWithFeePayer>;
|
|
38
|
+
}
|
|
39
|
+
export declare function parsePaymentMethod(payment: string, allowCustomFeePayer: boolean, log: LogFn, db?: WalletDB): (sender: AccountWallet) => Promise<FeePaymentMethod>;
|
|
40
|
+
export declare function parseGasFees(gasFees: string): GasFees;
|
|
41
|
+
//# sourceMappingURL=fees.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fees.d.ts","sourceRoot":"","sources":["../../../src/utils/options/fees.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,oBAAoB,EAEzB,KAAK,gBAAgB,EACrB,KAAK,GAAG,EACR,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAO,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE9D,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAI3D,MAAM,MAAM,UAAU,GAAG;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,WAAW,QAAQ;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC9D,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAC3E;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,QAAQ,EACjB,YAAY,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,mBAAmB,CAAC,EAClE,GAAG,EAAE,KAAK,QAIX;AAuGD,qBAAa,OAAQ,YAAW,QAAQ;IAE7B,YAAY,EAAE,OAAO;IACrB,WAAW,EAAE,WAAW;IAC/B,OAAO,CAAC,oBAAoB;IAC5B,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,WAAW;gBAPZ,YAAY,EAAE,OAAO,EACrB,WAAW,EAAE,WAAW,EACvB,oBAAoB,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,gBAAgB,CAAC,EAC1E,eAAe,EAAE,CACvB,MAAM,EAAE,aAAa,EACrB,aAAa,EAAE,gBAAgB,KAC5B,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,EAC/B,WAAW,EAAE,OAAO;IAGxB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAU7D,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAa/E,MAAM,CAAC,mBAAmB;IAI1B,MAAM,CAAC,UAAU;WAIJ,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,QAAQ;CAsB3E;AAED,qBAAa,mBAAoB,SAAQ,OAAO;WAC9B,mBAAmB;WAInB,UAAU;WAIJ,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,QAAQ;CA2BpF;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,mBAAmB,EAAE,OAAO,EAC5B,GAAG,EAAE,KAAK,EACV,EAAE,CAAC,EAAE,QAAQ,GACZ,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAwEtD;AAsBD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAerD"}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { FeeJuicePaymentMethod } from '@aztec/aztec.js';
|
|
2
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
+
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
4
|
+
import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
|
|
5
|
+
import { Option } from 'commander';
|
|
6
|
+
import { createOrRetrieveAccount } from '../accounts.js';
|
|
7
|
+
import { aliasedAddressParser } from './options.js';
|
|
8
|
+
export function printGasEstimates(feeOpts, gasEstimates, log) {
|
|
9
|
+
log(`Estimated gas usage: ${formatGasEstimate(gasEstimates)}`);
|
|
10
|
+
log(`Maximum total tx fee: ${getEstimatedCost(gasEstimates, feeOpts.gasSettings.maxFeesPerGas)}`);
|
|
11
|
+
}
|
|
12
|
+
function formatGasEstimate(estimate) {
|
|
13
|
+
return `da=${estimate.gasLimits.daGas},l2=${estimate.gasLimits.l2Gas},teardownDA=${estimate.teardownGasLimits.daGas},teardownL2=${estimate.teardownGasLimits.l2Gas}`;
|
|
14
|
+
}
|
|
15
|
+
function getEstimatedCost(estimate, maxFeesPerGas) {
|
|
16
|
+
return GasSettings.default({
|
|
17
|
+
...estimate,
|
|
18
|
+
maxFeesPerGas
|
|
19
|
+
}).getFeeLimit().toBigInt();
|
|
20
|
+
}
|
|
21
|
+
async function parseGasSettings(args, pxe) {
|
|
22
|
+
const gasLimits = args.gasLimits ? parseGasLimits(args.gasLimits) : {};
|
|
23
|
+
const maxFeesPerGas = args.maxFeesPerGas ? parseGasFees(args.maxFeesPerGas) : await pxe.getCurrentBaseFees();
|
|
24
|
+
const maxPriorityFeesPerGas = args.maxPriorityFeesPerGas ? parseGasFees(args.maxPriorityFeesPerGas) : undefined;
|
|
25
|
+
return GasSettings.default({
|
|
26
|
+
...gasLimits,
|
|
27
|
+
maxFeesPerGas,
|
|
28
|
+
maxPriorityFeesPerGas
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function printOptionParams(params) {
|
|
32
|
+
const paramsWithDescription = Object.keys(params).filter((name)=>params[name].description);
|
|
33
|
+
const maxParamWidth = paramsWithDescription.reduce((v, name)=>Math.max(v, name.length), 0);
|
|
34
|
+
const indent = (size)=>''.padEnd(size, ' ');
|
|
35
|
+
const descriptionList = paramsWithDescription.map((name)=>[
|
|
36
|
+
`${indent(5)}${name}${indent(maxParamWidth - name.length)} ${params[name].description}`,
|
|
37
|
+
params[name].default ? `Default: ${params[name].default}` : ''
|
|
38
|
+
].join(' '));
|
|
39
|
+
return descriptionList.length ? `\n Parameters:\n${descriptionList.join('\n')}` : '';
|
|
40
|
+
}
|
|
41
|
+
function getFeePaymentMethodParams(allowCustomFeePayer) {
|
|
42
|
+
const feePayer = allowCustomFeePayer ? {
|
|
43
|
+
type: 'address',
|
|
44
|
+
description: 'The account paying the fee.'
|
|
45
|
+
} : undefined;
|
|
46
|
+
return {
|
|
47
|
+
method: {
|
|
48
|
+
type: 'name',
|
|
49
|
+
description: 'Valid values: "fee_juice", "fpc-public", "fpc-private".',
|
|
50
|
+
default: 'fee_juice'
|
|
51
|
+
},
|
|
52
|
+
...feePayer ? {
|
|
53
|
+
feePayer
|
|
54
|
+
} : {},
|
|
55
|
+
asset: {
|
|
56
|
+
type: 'address',
|
|
57
|
+
description: 'The asset used for fee payment. Not required for the "fee_juice" method.'
|
|
58
|
+
},
|
|
59
|
+
fpc: {
|
|
60
|
+
type: 'address',
|
|
61
|
+
description: 'The FPC contract that pays in fee juice. Not required for the "fee_juice" method.'
|
|
62
|
+
},
|
|
63
|
+
claim: {
|
|
64
|
+
type: 'boolean',
|
|
65
|
+
description: 'Whether to use a previously stored claim to bridge fee juice.'
|
|
66
|
+
},
|
|
67
|
+
claimSecret: {
|
|
68
|
+
type: 'string',
|
|
69
|
+
description: 'The secret to claim fee juice on L1.'
|
|
70
|
+
},
|
|
71
|
+
claimAmount: {
|
|
72
|
+
type: 'bigint',
|
|
73
|
+
description: 'The amount of fee juice to be claimed.'
|
|
74
|
+
},
|
|
75
|
+
messageLeafIndex: {
|
|
76
|
+
type: 'bigint',
|
|
77
|
+
description: 'The index of the claim in the l1toL2Message tree.'
|
|
78
|
+
},
|
|
79
|
+
feeRecipient: {
|
|
80
|
+
type: 'string',
|
|
81
|
+
description: 'Recipient of the fee.'
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function getPaymentMethodOption(allowCustomFeePayer) {
|
|
86
|
+
const params = getFeePaymentMethodParams(allowCustomFeePayer);
|
|
87
|
+
const paramList = Object.keys(params).map((name)=>`${name}=${params[name].type}`);
|
|
88
|
+
return new Option(`--payment <${paramList.join(',')}>`, `Fee payment method and arguments.${printOptionParams(params)}`);
|
|
89
|
+
}
|
|
90
|
+
function getFeeOptions(allowCustomFeePayer) {
|
|
91
|
+
return [
|
|
92
|
+
getPaymentMethodOption(allowCustomFeePayer),
|
|
93
|
+
new Option('--gas-limits <da=100,l2=100,teardownDA=10,teardownL2=10>', 'Gas limits for the tx.'),
|
|
94
|
+
new Option('--max-fees-per-gas <da=100,l2=100>', 'Maximum fees per gas unit for DA and L2 computation.'),
|
|
95
|
+
new Option('--max-priority-fees-per-gas <da=0,l2=0>', 'Maximum priority fees per gas unit for DA and L2 computation.'),
|
|
96
|
+
new Option('--no-estimate-gas', 'Whether to automatically estimate gas limits for the tx.'),
|
|
97
|
+
new Option('--estimate-gas-only', 'Only report gas estimation for the tx, do not send it.')
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
export class FeeOpts {
|
|
101
|
+
estimateOnly;
|
|
102
|
+
gasSettings;
|
|
103
|
+
paymentMethodFactory;
|
|
104
|
+
getDeployWallet;
|
|
105
|
+
estimateGas;
|
|
106
|
+
constructor(estimateOnly, gasSettings, paymentMethodFactory, getDeployWallet, estimateGas){
|
|
107
|
+
this.estimateOnly = estimateOnly;
|
|
108
|
+
this.gasSettings = gasSettings;
|
|
109
|
+
this.paymentMethodFactory = paymentMethodFactory;
|
|
110
|
+
this.getDeployWallet = getDeployWallet;
|
|
111
|
+
this.estimateGas = estimateGas;
|
|
112
|
+
}
|
|
113
|
+
async toSendOpts(sender) {
|
|
114
|
+
return {
|
|
115
|
+
fee: {
|
|
116
|
+
estimateGas: this.estimateGas,
|
|
117
|
+
gasSettings: this.gasSettings,
|
|
118
|
+
paymentMethod: await this.paymentMethodFactory(sender)
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
async toDeployAccountOpts(sender) {
|
|
123
|
+
const paymentMethod = await this.paymentMethodFactory(sender);
|
|
124
|
+
const deployWallet = await this.getDeployWallet(sender, paymentMethod);
|
|
125
|
+
return {
|
|
126
|
+
deployWallet,
|
|
127
|
+
fee: {
|
|
128
|
+
estimateGas: this.estimateGas,
|
|
129
|
+
gasSettings: this.gasSettings,
|
|
130
|
+
paymentMethod
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
static paymentMethodOption() {
|
|
135
|
+
return getPaymentMethodOption(false);
|
|
136
|
+
}
|
|
137
|
+
static getOptions() {
|
|
138
|
+
return getFeeOptions(false);
|
|
139
|
+
}
|
|
140
|
+
static async fromCli(args, pxe, log, db) {
|
|
141
|
+
const estimateOnly = args.estimateGasOnly;
|
|
142
|
+
const gasSettings = await parseGasSettings(args, pxe);
|
|
143
|
+
const defaultPaymentMethod = async (sender)=>{
|
|
144
|
+
const { FeeJuicePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
145
|
+
return new FeeJuicePaymentMethod(sender.getAddress());
|
|
146
|
+
};
|
|
147
|
+
const getDeployWallet = ()=>{
|
|
148
|
+
// Returns undefined. The sender's wallet will be used by default.
|
|
149
|
+
return Promise.resolve(undefined);
|
|
150
|
+
};
|
|
151
|
+
return new FeeOpts(estimateOnly, gasSettings, args.payment ? parsePaymentMethod(args.payment, false, log, db) : defaultPaymentMethod, getDeployWallet, !!args.estimateGas);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
export class FeeOptsWithFeePayer extends FeeOpts {
|
|
155
|
+
static paymentMethodOption() {
|
|
156
|
+
return getPaymentMethodOption(true);
|
|
157
|
+
}
|
|
158
|
+
static getOptions() {
|
|
159
|
+
return getFeeOptions(true);
|
|
160
|
+
}
|
|
161
|
+
static async fromCli(args, pxe, log, db) {
|
|
162
|
+
const estimateOnly = args.estimateGasOnly;
|
|
163
|
+
const gasSettings = await parseGasSettings(args, pxe);
|
|
164
|
+
const defaultPaymentMethod = async (sender)=>{
|
|
165
|
+
const { FeeJuicePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
166
|
+
return new FeeJuicePaymentMethod(sender.getAddress());
|
|
167
|
+
};
|
|
168
|
+
const getDeployWallet = async (sender, paymentMethod)=>{
|
|
169
|
+
if (paymentMethod instanceof FeeJuicePaymentMethod) {
|
|
170
|
+
const feePayer = await paymentMethod.getFeePayer();
|
|
171
|
+
if (!sender.getAddress().equals(feePayer)) {
|
|
172
|
+
return (await createOrRetrieveAccount(pxe, feePayer, db)).getWallet();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return undefined;
|
|
176
|
+
};
|
|
177
|
+
return new FeeOptsWithFeePayer(estimateOnly, gasSettings, args.payment ? parsePaymentMethod(args.payment, true, log, db) : defaultPaymentMethod, getDeployWallet, !!args.estimateGas);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
export function parsePaymentMethod(payment, allowCustomFeePayer, log, db) {
|
|
181
|
+
const parsed = payment.split(',').reduce((acc, item)=>{
|
|
182
|
+
const [dimension, value] = item.split('=');
|
|
183
|
+
acc[dimension] = value ?? 1;
|
|
184
|
+
return acc;
|
|
185
|
+
}, {});
|
|
186
|
+
const getFpcOpts = (parsed, db)=>{
|
|
187
|
+
if (!parsed.fpc) {
|
|
188
|
+
throw new Error('Missing "fpc" in payment option');
|
|
189
|
+
}
|
|
190
|
+
if (!parsed.asset) {
|
|
191
|
+
throw new Error('Missing "asset" in payment option');
|
|
192
|
+
}
|
|
193
|
+
const fpc = aliasedAddressParser('contracts', parsed.fpc, db);
|
|
194
|
+
return [
|
|
195
|
+
AztecAddress.fromString(parsed.asset),
|
|
196
|
+
fpc
|
|
197
|
+
];
|
|
198
|
+
};
|
|
199
|
+
return async (sender)=>{
|
|
200
|
+
switch(parsed.method){
|
|
201
|
+
case 'fee_juice':
|
|
202
|
+
{
|
|
203
|
+
if (parsed.claim || parsed.claimSecret && parsed.claimAmount && parsed.messageLeafIndex) {
|
|
204
|
+
let claimAmount, claimSecret, messageLeafIndex;
|
|
205
|
+
if (parsed.claim && db) {
|
|
206
|
+
({ amount: claimAmount, secret: claimSecret, leafIndex: messageLeafIndex } = await db.popBridgedFeeJuice(sender.getAddress(), log));
|
|
207
|
+
} else {
|
|
208
|
+
({ claimAmount, claimSecret, messageLeafIndex } = parsed);
|
|
209
|
+
}
|
|
210
|
+
log(`Using Fee Juice for fee payments with claim for ${claimAmount} tokens`);
|
|
211
|
+
const { FeeJuicePaymentMethodWithClaim } = await import('@aztec/aztec.js/fee');
|
|
212
|
+
return new FeeJuicePaymentMethodWithClaim(sender, {
|
|
213
|
+
claimAmount: (typeof claimAmount === 'string' ? Fr.fromHexString(claimAmount) : new Fr(claimAmount)).toBigInt(),
|
|
214
|
+
claimSecret: Fr.fromHexString(claimSecret),
|
|
215
|
+
messageLeafIndex: BigInt(messageLeafIndex)
|
|
216
|
+
});
|
|
217
|
+
} else {
|
|
218
|
+
log(`Using Fee Juice for fee payment`);
|
|
219
|
+
const { FeeJuicePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
220
|
+
const feePayer = parsed.feePayer && allowCustomFeePayer ? aliasedAddressParser('accounts', parsed.feePayer, db) : sender.getAddress();
|
|
221
|
+
return new FeeJuicePaymentMethod(feePayer);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
case 'fpc-public':
|
|
225
|
+
{
|
|
226
|
+
const [asset, fpc] = getFpcOpts(parsed, db);
|
|
227
|
+
log(`Using public fee payment with asset ${asset} via paymaster ${fpc}`);
|
|
228
|
+
const { PublicFeePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
229
|
+
return new PublicFeePaymentMethod(fpc, sender);
|
|
230
|
+
}
|
|
231
|
+
case 'fpc-private':
|
|
232
|
+
{
|
|
233
|
+
const [asset, fpc] = getFpcOpts(parsed, db);
|
|
234
|
+
log(`Using private fee payment with asset ${asset} via paymaster ${fpc}`);
|
|
235
|
+
const { PrivateFeePaymentMethod } = await import('@aztec/aztec.js/fee');
|
|
236
|
+
return new PrivateFeePaymentMethod(fpc, sender);
|
|
237
|
+
}
|
|
238
|
+
case undefined:
|
|
239
|
+
throw new Error('Missing "method" in payment option');
|
|
240
|
+
default:
|
|
241
|
+
throw new Error(`Invalid fee payment method: ${payment}`);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
function parseGasLimits(gasLimits) {
|
|
246
|
+
const parsed = gasLimits.split(',').reduce((acc, limit)=>{
|
|
247
|
+
const [dimension, value] = limit.split('=');
|
|
248
|
+
acc[dimension] = parseInt(value, 10);
|
|
249
|
+
return acc;
|
|
250
|
+
}, {});
|
|
251
|
+
const expected = [
|
|
252
|
+
'da',
|
|
253
|
+
'l2',
|
|
254
|
+
'teardownDA',
|
|
255
|
+
'teardownL2'
|
|
256
|
+
];
|
|
257
|
+
for (const dimension of expected){
|
|
258
|
+
if (!(dimension in parsed)) {
|
|
259
|
+
throw new Error(`Missing gas limit for ${dimension}`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return {
|
|
263
|
+
gasLimits: new Gas(parsed.da, parsed.l2),
|
|
264
|
+
teardownGasLimits: new Gas(parsed.teardownDA, parsed.teardownL2)
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
export function parseGasFees(gasFees) {
|
|
268
|
+
const parsed = gasFees.split(',').reduce((acc, fee)=>{
|
|
269
|
+
const [dimension, value] = fee.split('=');
|
|
270
|
+
acc[dimension] = parseInt(value, 10);
|
|
271
|
+
return acc;
|
|
272
|
+
}, {});
|
|
273
|
+
const expected = [
|
|
274
|
+
'da',
|
|
275
|
+
'l2'
|
|
276
|
+
];
|
|
277
|
+
for (const dimension of expected){
|
|
278
|
+
if (!(dimension in parsed)) {
|
|
279
|
+
throw new Error(`Missing gas fee for ${dimension}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return new GasFees(parsed.da, parsed.l2);
|
|
283
|
+
}
|