@aztec/cli-wallet 0.0.1-commit.2f68f620 → 0.0.1-commit.3100065

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dest/cmds/check_tx.js +8 -6
  2. package/dest/cmds/create_account.d.ts +4 -2
  3. package/dest/cmds/create_account.d.ts.map +1 -1
  4. package/dest/cmds/create_account.js +26 -10
  5. package/dest/cmds/deploy.js +3 -6
  6. package/dest/cmds/deploy_account.js +4 -7
  7. package/dest/cmds/import_test_accounts.d.ts +1 -1
  8. package/dest/cmds/import_test_accounts.d.ts.map +1 -1
  9. package/dest/cmds/import_test_accounts.js +2 -1
  10. package/dest/cmds/index.d.ts +1 -1
  11. package/dest/cmds/index.d.ts.map +1 -1
  12. package/dest/cmds/index.js +8 -7
  13. package/dest/cmds/send.js +3 -6
  14. package/dest/cmds/simulate.d.ts +1 -1
  15. package/dest/cmds/simulate.d.ts.map +1 -1
  16. package/dest/cmds/simulate.js +2 -1
  17. package/dest/storage/wallet_db.d.ts +7 -4
  18. package/dest/storage/wallet_db.d.ts.map +1 -1
  19. package/dest/storage/wallet_db.js +15 -1
  20. package/dest/utils/constants.d.ts +2 -2
  21. package/dest/utils/constants.d.ts.map +1 -1
  22. package/dest/utils/constants.js +1 -0
  23. package/dest/utils/options/fees.d.ts +1 -1
  24. package/dest/utils/options/fees.d.ts.map +1 -1
  25. package/dest/utils/options/fees.js +4 -1
  26. package/dest/utils/options/options.d.ts +2 -2
  27. package/dest/utils/options/options.d.ts.map +1 -1
  28. package/dest/utils/options/options.js +5 -5
  29. package/dest/utils/wallet.d.ts +25 -5
  30. package/dest/utils/wallet.d.ts.map +1 -1
  31. package/dest/utils/wallet.js +87 -65
  32. package/package.json +15 -15
  33. package/src/cmds/check_tx.ts +11 -10
  34. package/src/cmds/create_account.ts +27 -15
  35. package/src/cmds/deploy.ts +3 -3
  36. package/src/cmds/deploy_account.ts +4 -4
  37. package/src/cmds/import_test_accounts.ts +12 -1
  38. package/src/cmds/index.ts +11 -9
  39. package/src/cmds/send.ts +3 -3
  40. package/src/cmds/simulate.ts +2 -1
  41. package/src/storage/wallet_db.ts +24 -2
  42. package/src/utils/constants.ts +7 -1
  43. package/src/utils/options/fees.ts +4 -2
  44. package/src/utils/options/options.ts +5 -5
  45. package/src/utils/wallet.ts +127 -83
@@ -44,7 +44,8 @@ export async function simulate(
44
44
  if (!metadata.instance) {
45
45
  return undefined;
46
46
  }
47
- const artifact = await wallet.getContractArtifact(metadata.instance.currentContractClassId);
47
+ const classId = metadata.updatedContractClassId ?? metadata.instance.originalContractClassId;
48
+ const artifact = await wallet.getContractArtifact(classId);
48
49
  return artifact;
49
50
  },
50
51
  log,
@@ -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';
@@ -88,13 +89,28 @@ export class WalletDB {
88
89
  address: AztecAddress,
89
90
  {
90
91
  type,
92
+ signingKey,
91
93
  secretKey,
92
94
  salt,
93
95
  alias,
94
96
  publicKey,
95
- }: { type: AccountType; secretKey: Fr; salt: Fr; alias: string | undefined; publicKey: string | undefined },
97
+ }: {
98
+ type: AccountType;
99
+ signingKey?: GrumpkinScalar;
100
+ secretKey?: Fr;
101
+ salt: Fr;
102
+ alias: string | undefined;
103
+ publicKey: string | undefined;
104
+ },
96
105
  log: LogFn,
97
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
+
98
114
  let publicSigningKey: Buffer | undefined;
99
115
  if (type === 'ecdsasecp256r1ssh' && publicKey) {
100
116
  publicSigningKey = extractECDSAPublicKeyFromBase64String(publicKey);
@@ -106,6 +122,9 @@ export class WalletDB {
106
122
  }
107
123
  await this.#accounts.set(`${address.toString()}:type`, Buffer.from(type));
108
124
  await this.#accounts.set(`${address.toString()}:sk`, secretKey.toBuffer());
125
+ if (signingKey) {
126
+ await this.#accounts.set(`${address.toString()}:signing`, signingKey.toBuffer());
127
+ }
109
128
  await this.#accounts.set(`${address.toString()}:salt`, salt.toBuffer());
110
129
  if (publicSigningKey) {
111
130
  await this.#accounts.set(`${address.toString()}:publicSigningKey`, publicSigningKey);
@@ -226,10 +245,13 @@ export class WalletDB {
226
245
  if (!secretKeyBuffer) {
227
246
  throw new Error(`Could not find ${address}:sk. Account "${address.toString}" does not exist on this wallet.`);
228
247
  }
248
+ const signingKeyBuffer = await this.#accounts.getAsync(`${address.toString()}:signing`);
229
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;
230
252
  const salt = Fr.fromBuffer((await this.#accounts.getAsync(`${address.toString()}:salt`))!);
231
253
  const type = (await this.#accounts.getAsync(`${address.toString()}:type`))!.toString('utf8') as AccountType;
232
- return { address, secretKey, salt, type };
254
+ return { address, signingKey, secretKey, salt, type };
233
255
  }
234
256
 
235
257
  async storeAlias(type: AliasType, key: string, value: Buffer, log: LogFn) {
@@ -1,4 +1,10 @@
1
1
  export const MIN_FEE_PADDING = 0.5;
2
2
 
3
- export const AccountTypes = ['schnorr', 'ecdsasecp256r1', 'ecdsasecp256r1ssh', 'ecdsasecp256k1'] as const;
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];
@@ -137,7 +137,7 @@ export function parsePaymentMethod(
137
137
  if (!parsed.asset) {
138
138
  throw new Error('Missing "asset" in payment option');
139
139
  }
140
- return AztecAddress.fromString(parsed.asset);
140
+ return AztecAddress.fromStringUnsafe(parsed.asset);
141
141
  };
142
142
 
143
143
  return async (wallet: Wallet, from: AztecAddress, gasSettings: GasSettings) => {
@@ -259,7 +259,9 @@ export class CLIFeeArgs {
259
259
  async toUserFeeOptions(node: AztecNode, wallet: Wallet, from: AztecAddress): Promise<ParsedFeeOptions> {
260
260
  const minFees = await this.getMinFees(node);
261
261
  const maxFeesPerGas = minFees.mul(1 + MIN_FEE_PADDING);
262
- const gasSettings = GasSettings.fallback({ ...this.gasSettings, maxFeesPerGas });
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 });
263
265
  const paymentMethod = await this.paymentMethod(wallet, from, gasSettings);
264
266
  return {
265
267
  paymentMethod,
@@ -1,5 +1,5 @@
1
1
  import { TxHash } from '@aztec/aztec.js/tx';
2
- import { parseAztecAddress, parseSecretKey, parseTxHash } from '@aztec/cli/utils';
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 aliasedSecretKeyParser(sk: string, db?: WalletDB) {
67
+ export function aliasedSigningKeyParser(sk: string, db?: WalletDB) {
68
68
  if (sk.startsWith('0x')) {
69
- return parseSecretKey(sk);
69
+ return parseSigningKey(sk);
70
70
  } else {
71
- const prefixed = `${sk.startsWith('accounts') ? '' : 'accounts'}:${sk.endsWith(':sk') ? sk : `${sk}:sk`}`;
71
+ const prefixed = `${sk.startsWith('accounts') ? '' : 'accounts'}:${sk.endsWith(':signing') ? sk : `${sk}:signing`}`;
72
72
  const rawSk = db ? db.tryRetrieveAlias(prefixed) : sk;
73
- return parseSecretKey(rawSk);
73
+ return parseSigningKey(rawSk);
74
74
  }
75
75
  }
76
76
 
@@ -1,16 +1,21 @@
1
- import { EcdsaRAccountContract, EcdsaRSSHAccountContract } from '@aztec/accounts/ecdsa';
2
- import { SchnorrAccountContract } from '@aztec/accounts/schnorr';
3
- import { StubEcdsaAccountContractArtifact, createStubEcdsaAccount } from '@aztec/accounts/stub/ecdsa';
4
- import { StubSchnorrAccountContractArtifact, createStubSchnorrAccount } from '@aztec/accounts/stub/schnorr';
1
+ import { EcdsaKAccountContract, EcdsaRAccountContract, EcdsaRSSHAccountContract } from '@aztec/accounts/ecdsa';
2
+ import { StubEcdsaAccountContractArtifact, createStubEcdsaAccount } from '@aztec/accounts/ecdsa/stub';
3
+ import { SchnorrAccountContract, SchnorrInitializerlessAccountContract } from '@aztec/accounts/schnorr';
4
+ import { StubSchnorrAccountContractArtifact, createStubSchnorrAccount } from '@aztec/accounts/schnorr/stub';
5
5
  import { getIdentities } from '@aztec/accounts/utils';
6
6
  import { type Account, type AccountContract, NO_FROM } from '@aztec/aztec.js/account';
7
- import { type InteractionFeeOptions, getContractClassFromArtifact, getGasLimits } from '@aztec/aztec.js/contracts';
7
+ import {
8
+ ContractFunctionInteraction,
9
+ type InteractionFeeOptions,
10
+ getContractClassFromArtifact,
11
+ } from '@aztec/aztec.js/contracts';
8
12
  import type { AztecNode } from '@aztec/aztec.js/node';
9
- import { AccountManager, type Aliased, type SimulateOptions } from '@aztec/aztec.js/wallet';
13
+ import { AccountManager, type Aliased } from '@aztec/aztec.js/wallet';
10
14
  import { TxSimulationResultWithAppOffset } from '@aztec/aztec.js/wallet';
11
15
  import type { DefaultAccountEntrypointOptions } from '@aztec/entrypoints/account';
12
16
  import { DefaultEntrypoint } from '@aztec/entrypoints/default';
13
17
  import { Fr } from '@aztec/foundation/curves/bn254';
18
+ import { GrumpkinScalar } from '@aztec/foundation/curves/grumpkin';
14
19
  import type { LogFn } from '@aztec/foundation/log';
15
20
  import type { NotesFilter } from '@aztec/pxe/client/lazy';
16
21
  import type { PXEConfig } from '@aztec/pxe/config';
@@ -18,16 +23,18 @@ import type { PXE } from '@aztec/pxe/server';
18
23
  import { createPXE, getPXEConfig } from '@aztec/pxe/server';
19
24
  import { getStandardAuthRegistry } from '@aztec/standard-contracts/auth-registry';
20
25
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
21
- import { deriveSigningKey } from '@aztec/stdlib/keys';
26
+ import type { Gas, GasUsed } from '@aztec/stdlib/gas';
22
27
  import { NoteDao } from '@aztec/stdlib/note';
23
28
  import type { SimulationOverrides, TxExecutionRequest, TxProvingResult } from '@aztec/stdlib/tx';
24
29
  import { ExecutionPayload, mergeExecutionPayloads } from '@aztec/stdlib/tx';
25
- import { BaseWallet, type SimulateViaEntrypointOptions } from '@aztec/wallet-sdk/base-wallet';
30
+ import { BaseWallet, type SimulateViaEntrypointOptions, getGasLimits } from '@aztec/wallet-sdk/base-wallet';
26
31
 
27
32
  import type { WalletDB } from '../storage/wallet_db.js';
28
33
  import type { AccountType } from './constants.js';
29
34
  import { extractECDSAPublicKeyFromBase64String } from './ecdsa.js';
30
- import { printGasEstimates } from './options/fees.js';
35
+
36
+ /** Padding the CLI wallet applies to simulated gas usage when deriving declared gas limits. */
37
+ const DEFAULT_ESTIMATED_GAS_PADDING = 0.1;
31
38
 
32
39
  export class CLIWallet extends BaseWallet {
33
40
  private accountCache = new Map<string, Account>();
@@ -61,7 +68,8 @@ export class CLIWallet extends BaseWallet {
61
68
 
62
69
  private async registerAuthRegistry(): Promise<void> {
63
70
  const { instance, artifact } = await getStandardAuthRegistry();
64
- await this.pxe.registerContract({ instance, artifact });
71
+ await this.pxe.registerContractClass(artifact);
72
+ await this.pxe.registerContract(instance);
65
73
  }
66
74
 
67
75
  /**
@@ -77,6 +85,7 @@ export class CLIWallet extends BaseWallet {
77
85
  await this.pxe.registerContractClass(StubEcdsaAccountContractArtifact);
78
86
 
79
87
  this.stubClassIds.set('schnorr', schnorrClassId);
88
+ this.stubClassIds.set('schnorr_initializerless', schnorrClassId);
80
89
  this.stubClassIds.set('ecdsasecp256k1', ecdsaClassId);
81
90
  this.stubClassIds.set('ecdsasecp256r1', ecdsaClassId);
82
91
  this.stubClassIds.set('ecdsasecp256r1ssh', ecdsaClassId);
@@ -87,11 +96,21 @@ export class CLIWallet extends BaseWallet {
87
96
  return Promise.resolve(
88
97
  accounts.map(({ key, value }) => {
89
98
  const alias = key.includes(':') ? key.slice(key.indexOf(':') + 1) : key;
90
- return { alias, item: AztecAddress.fromString(value) };
99
+ return { alias, item: AztecAddress.fromStringUnsafe(value) };
91
100
  }),
92
101
  );
93
102
  }
94
103
 
104
+ /**
105
+ * Derives suggested total and teardown gas limits from simulated gas usage, padded and clamped to the
106
+ * network's per-tx admission limits.
107
+ * @param gasUsed - The gas consumed during simulation (from a `simulate({ includeMetadata: true })` result).
108
+ */
109
+ async estimateGasLimits(gasUsed: GasUsed): Promise<{ gasLimits: Gas; teardownGasLimits: Gas }> {
110
+ const maxTxGasLimits = await this.getMaxTxGasLimits();
111
+ return getGasLimits(gasUsed, maxTxGasLimits, DEFAULT_ESTIMATED_GAS_PADDING);
112
+ }
113
+
95
114
  private async createCancellationTxExecutionRequest(
96
115
  from: AztecAddress,
97
116
  txNonce: Fr,
@@ -134,7 +153,7 @@ export class CLIWallet extends BaseWallet {
134
153
  if (this.accountCache.has(address.toString())) {
135
154
  return this.accountCache.get(address.toString())!;
136
155
  } else {
137
- const accountManager = await this.createOrRetrieveAccount(address);
156
+ const accountManager = await this.retrieveAccount(address);
138
157
  account = await accountManager.getAccount();
139
158
  }
140
159
 
@@ -144,74 +163,115 @@ export class CLIWallet extends BaseWallet {
144
163
  return account;
145
164
  }
146
165
 
147
- private async createAccount(secret: Fr, salt: Fr, contract: AccountContract): Promise<AccountManager> {
148
- const accountManager = await AccountManager.create(this, secret, contract, { salt });
149
-
150
- const instance = accountManager.getInstance();
151
- const artifact = await contract.getContractArtifact();
152
-
153
- await this.registerContract(instance, artifact, secret);
154
- this.accountCache.set(accountManager.address.toString(), await accountManager.getAccount());
155
- return accountManager;
156
- }
157
-
158
- async createOrRetrieveAccount(
159
- address?: AztecAddress,
160
- secretKey?: Fr,
161
- type: AccountType = 'schnorr',
162
- salt?: Fr,
166
+ /**
167
+ * Creates an account from freshly supplied keys. SSH accounts sign with a key held in the agent (resolved from
168
+ * `publicKey`), every other type is rooted on `signingKey`, with `secretKey` as its privacy secret.
169
+ */
170
+ async createAccount(
171
+ type: AccountType,
172
+ signingKey: GrumpkinScalar | undefined,
173
+ secretKey: Fr | undefined,
174
+ salt: Fr = Fr.ZERO,
163
175
  publicKey?: string,
164
176
  ): Promise<AccountManager> {
165
- let account;
166
-
167
- salt ??= Fr.ZERO;
177
+ const publicSigningKey =
178
+ type === 'ecdsasecp256r1ssh' ? await this.resolveSshPublicSigningKey(publicKey) : undefined;
179
+ return this.buildAccount(type, salt, signingKey, secretKey, publicSigningKey);
180
+ }
168
181
 
169
- if (this.db && address) {
170
- ({ type, secretKey, salt } = await this.db.retrieveAccount(address));
182
+ /**
183
+ * Retrieves a previously stored account by address, loading its keys, type and salt from the wallet database.
184
+ */
185
+ async retrieveAccount(address: AztecAddress): Promise<AccountManager> {
186
+ if (!this.db) {
187
+ throw new Error('Cannot retrieve an account without a wallet database');
171
188
  }
172
-
173
- if (!secretKey) {
174
- throw new Error('Cannot retrieve/create wallet without secret key');
189
+ const { type, signingKey, secretKey, salt } = await this.db.retrieveAccount(address);
190
+ if (type !== 'ecdsasecp256r1ssh' && !signingKey) {
191
+ throw new Error(
192
+ `Account ${address} has no stored signing key: it was created with an older version of aztec-wallet and is ` +
193
+ `incompatible with this one. Create a new account to continue.`,
194
+ );
175
195
  }
196
+ const publicSigningKey =
197
+ type === 'ecdsasecp256r1ssh' ? await this.db.retrieveAccountMetadata(address, 'publicSigningKey') : undefined;
198
+ return this.buildAccount(type, salt, signingKey, secretKey, publicSigningKey);
199
+ }
176
200
 
201
+ private async buildAccount(
202
+ type: AccountType,
203
+ salt: Fr,
204
+ signingKey: GrumpkinScalar | undefined,
205
+ secretKey: Fr | undefined,
206
+ publicSigningKey: Buffer | undefined,
207
+ ): Promise<AccountManager> {
177
208
  switch (type) {
178
- case 'schnorr': {
179
- account = await this.createAccount(secretKey, salt, new SchnorrAccountContract(deriveSigningKey(secretKey)));
180
- break;
181
- }
182
- case 'ecdsasecp256r1': {
183
- account = await this.createAccount(
184
- secretKey,
185
- salt,
186
- new EcdsaRAccountContract(deriveSigningKey(secretKey).toBuffer()),
187
- );
188
- break;
209
+ case 'schnorr':
210
+ case 'schnorr_initializerless':
211
+ case 'ecdsasecp256r1':
212
+ case 'ecdsasecp256k1': {
213
+ if (!signingKey || !secretKey) {
214
+ throw new Error('Cannot build account without signing key and secret key');
215
+ }
216
+ const contract =
217
+ type === 'schnorr'
218
+ ? new SchnorrAccountContract(signingKey)
219
+ : type === 'schnorr_initializerless'
220
+ ? new SchnorrInitializerlessAccountContract(signingKey)
221
+ : type === 'ecdsasecp256r1'
222
+ ? new EcdsaRAccountContract(signingKey.toBuffer())
223
+ : new EcdsaKAccountContract(signingKey.toBuffer());
224
+ return await this.materializeAccount(secretKey, salt, contract);
189
225
  }
190
226
  case 'ecdsasecp256r1ssh': {
191
- let publicSigningKey;
192
- if (this.db && address) {
193
- publicSigningKey = await this.db.retrieveAccountMetadata(address, 'publicSigningKey');
194
- } else if (publicKey) {
195
- const identities = await getIdentities();
196
- const foundIdentity = identities.find(
197
- identity => identity.type === 'ecdsa-sha2-nistp256' && identity.publicKey === publicKey,
198
- );
199
- if (!foundIdentity) {
200
- throw new Error(`Identity for public key ${publicKey} not found in the SSH agent`);
201
- }
202
- publicSigningKey = extractECDSAPublicKeyFromBase64String(foundIdentity.publicKey);
203
- } else {
204
- throw new Error('Public key must be provided for ECDSA SSH account');
227
+ if (!secretKey || !publicSigningKey) {
228
+ throw new Error('Cannot build SSH account without secret key and public signing key');
205
229
  }
206
- account = await this.createAccount(secretKey, salt, new EcdsaRSSHAccountContract(publicSigningKey));
207
- break;
230
+ return await this.materializeAccount(secretKey, salt, new EcdsaRSSHAccountContract(publicSigningKey));
208
231
  }
209
232
  default: {
210
233
  throw new Error(`Unsupported account type: ${type}`);
211
234
  }
212
235
  }
236
+ }
213
237
 
214
- return account;
238
+ private async resolveSshPublicSigningKey(publicKey: string | undefined): Promise<Buffer> {
239
+ if (!publicKey) {
240
+ throw new Error('Public key must be provided for ECDSA SSH account');
241
+ }
242
+ const identities = await getIdentities();
243
+ const foundIdentity = identities.find(
244
+ identity => identity.type === 'ecdsa-sha2-nistp256' && identity.publicKey === publicKey,
245
+ );
246
+ if (!foundIdentity) {
247
+ throw new Error(`Identity for public key ${publicKey} not found in the SSH agent`);
248
+ }
249
+ return extractECDSAPublicKeyFromBase64String(foundIdentity.publicKey);
250
+ }
251
+
252
+ private async materializeAccount(secret: Fr, salt: Fr, contract: AccountContract): Promise<AccountManager> {
253
+ const accountManager = await AccountManager.create(this, secret, contract, { salt });
254
+
255
+ const instance = accountManager.getInstance();
256
+ const artifact = await contract.getContractArtifact();
257
+
258
+ await this.registerContract(instance, artifact, secret);
259
+ this.accountCache.set(accountManager.address.toString(), await accountManager.getAccount());
260
+
261
+ // Initializerless accounts have no deployment tx; their address commits to the signing public key
262
+ // (via the contract's immutablesHash, resolved by AccountManager.create) and the constructor's
263
+ // storage writes are materialized locally via a simulated "store" call here.
264
+ if (contract instanceof SchnorrInitializerlessAccountContract) {
265
+ const constructorAbi = artifact.functions.find(f => f.name === 'constructor');
266
+ if (!constructorAbi) {
267
+ throw new Error('Could not create SchnorrInitializerlessAccount: constructor ABI not found');
268
+ }
269
+ const { x, y } = await contract.getSigningPublicKey();
270
+ const storeCall = new ContractFunctionInteraction(this, instance.address, constructorAbi, [x, y]);
271
+ await storeCall.simulate({ from: instance.address });
272
+ }
273
+
274
+ return accountManager;
215
275
  }
216
276
 
217
277
  /**
@@ -229,7 +289,9 @@ export class CLIWallet extends BaseWallet {
229
289
  }
230
290
  const { type } = await this.db!.retrieveAccount(address);
231
291
  const stubAccount =
232
- type === 'schnorr' ? createStubSchnorrAccount(originalAddress) : createStubEcdsaAccount(originalAddress);
292
+ type === 'schnorr' || type === 'schnorr_initializerless'
293
+ ? createStubSchnorrAccount(originalAddress)
294
+ : createStubEcdsaAccount(originalAddress);
233
295
  const stubClassId = this.stubClassIds.get(type);
234
296
  if (!stubClassId) {
235
297
  throw new Error(
@@ -240,24 +302,6 @@ export class CLIWallet extends BaseWallet {
240
302
  return { account: stubAccount, instance };
241
303
  }
242
304
 
243
- override async simulateTx(
244
- executionPayload: ExecutionPayload,
245
- opts: SimulateOptions,
246
- ): Promise<TxSimulationResultWithAppOffset> {
247
- const simulationResults = await super.simulateTx(executionPayload, opts);
248
-
249
- if (opts.fee?.estimateGas) {
250
- const feeOptions = await this.completeFeeOptions({
251
- from: opts.from,
252
- feePayer: executionPayload.feePayer,
253
- gasSettings: opts.fee?.gasSettings,
254
- });
255
- const limits = getGasLimits(simulationResults, opts.fee?.estimatedGasPadding);
256
- printGasEstimates(feeOptions, limits, this.userLog);
257
- }
258
- return simulationResults;
259
- }
260
-
261
305
  /**
262
306
  * Uses a stub account for kernelless simulation, bypassing real account authorization.
263
307
  * Uses DefaultEntrypoint directly for NO_FROM transactions.