diff --git a/yarn-project/accounts/src/testing/configuration.ts b/yarn-project/accounts/src/testing/configuration.ts index 0b3ff8df28f..c854ae3d704 100644 --- a/yarn-project/accounts/src/testing/configuration.ts +++ b/yarn-project/accounts/src/testing/configuration.ts @@ -61,7 +61,7 @@ export async function deployInitialTestAccounts(pxe: PXE) { const sentTxs: DeploySentTx[] = []; for (const { account } of accounts) { - const deploymentMethod = await account.getDeployMethod(); + const deploymentMethod = account.getDeployMethod(); // pxe needs to prove txs one-by-one // this is because the tx use capsules and the capsule stack is a shared resource diff --git a/yarn-project/accounts/src/testing/create_account.ts b/yarn-project/accounts/src/testing/create_account.ts index b47305c28d3..0d4327ddc4d 100644 --- a/yarn-project/accounts/src/testing/create_account.ts +++ b/yarn-project/accounts/src/testing/create_account.ts @@ -28,16 +28,15 @@ export async function createAccounts(pxe: PXE, numberOfAccounts = 1): Promise - d.prove({ - contractAddressSalt: account.salt, - }), - ); + const d = account.getDeployMethod(); + await d.prove({ + contractAddressSalt: account.salt, + }); accounts.push(account); } // Send them and await them to be mined - const txs = await Promise.all(accounts.map(account => account.deploy())); + const txs = accounts.map(account => account.deploy()); await Promise.all(txs.map(tx => tx.wait({ interval: 0.1 }))); return Promise.all(accounts.map(account => account.getWallet())); } diff --git a/yarn-project/aztec.js/src/account/contract.ts b/yarn-project/aztec.js/src/account/contract.ts index 0711292bbac..6c49a3b5cf0 100644 --- a/yarn-project/aztec.js/src/account/contract.ts +++ b/yarn-project/aztec.js/src/account/contract.ts @@ -2,7 +2,7 @@ import { type CompleteAddress } from '@aztec/circuit-types'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type NodeInfo } from '@aztec/types/interfaces'; -import { type AccountInterface } from './interface.js'; +import { type AccountInterface, type AuthWitnessProvider } from './interface.js'; // docs:start:account-contract-interface /** @@ -29,5 +29,11 @@ export interface AccountContract { * @returns An account interface instance for creating tx requests and authorizing actions. */ getInterface(address: CompleteAddress, nodeInfo: NodeInfo): AccountInterface; + + /** + * Returns the auth witness provider for the given address. + * @param address - Address for which to create auth witnesses. + */ + getAuthWitnessProvider(address: CompleteAddress): AuthWitnessProvider; } // docs:end:account-contract-interface diff --git a/yarn-project/aztec.js/src/account_manager/deploy_account_sent_tx.ts b/yarn-project/aztec.js/src/account_manager/deploy_account_sent_tx.ts index cfaa577ea8e..ad299a68b5b 100644 --- a/yarn-project/aztec.js/src/account_manager/deploy_account_sent_tx.ts +++ b/yarn-project/aztec.js/src/account_manager/deploy_account_sent_tx.ts @@ -1,4 +1,4 @@ -import { type TxHash, type TxReceipt } from '@aztec/circuit-types'; +import { type PXE, type TxHash, type TxReceipt } from '@aztec/circuit-types'; import { type FieldsOf } from '@aztec/foundation/types'; import { type Wallet } from '../account/index.js'; @@ -15,8 +15,8 @@ export type DeployAccountTxReceipt = FieldsOf & { * A deployment transaction for an account contract sent to the network, extending SentTx with methods to get the resulting wallet. */ export class DeployAccountSentTx extends SentTx { - constructor(private wallet: Wallet, txHashPromise: Promise) { - super(wallet, txHashPromise); + constructor(pxe: PXE, txHashPromise: Promise, private getWalletPromise: Promise) { + super(pxe, txHashPromise); } /** @@ -36,7 +36,8 @@ export class DeployAccountSentTx extends SentTx { */ public async wait(opts: WaitOpts = DefaultWaitOpts): Promise { const receipt = await super.wait(opts); - await waitForAccountSynch(this.pxe, this.wallet.getCompleteAddress(), opts); - return { ...receipt, wallet: this.wallet }; + const wallet = await this.getWalletPromise; + await waitForAccountSynch(this.pxe, wallet.getCompleteAddress(), opts); + return { ...receipt, wallet }; } } diff --git a/yarn-project/aztec.js/src/account_manager/index.ts b/yarn-project/aztec.js/src/account_manager/index.ts index 18e84a0acf3..9715011f0e6 100644 --- a/yarn-project/aztec.js/src/account_manager/index.ts +++ b/yarn-project/aztec.js/src/account_manager/index.ts @@ -119,14 +119,13 @@ export class AccountManager { * grained control on when to create, simulate, and send the deployment tx. * @returns A DeployMethod instance that deploys this account contract. */ - public async getDeployMethod() { + public getDeployMethod() { if (!this.deployMethod) { if (!this.isDeployable()) { throw new Error( `Account contract ${this.accountContract.getContractArtifact().name} does not require deployment.`, ); } - await this.#register(); const encryptionPublicKey = this.getEncryptionPublicKey(); // We use a signerless wallet so we hit the account contract directly and it deploys itself. // If we used getWallet, the deployment would get routed via the account contract entrypoint @@ -134,10 +133,11 @@ export class AccountManager { const args = this.accountContract.getDeploymentArgs() ?? []; this.deployMethod = new DeployAccountMethod( this.pxe, - await this.getAccount(), + this.accountContract.getAuthWitnessProvider(this.getCompleteAddress()), encryptionPublicKey, this.accountContract.getContractArtifact(), args, + () => this.#register(), ); } return this.deployMethod; @@ -151,14 +151,13 @@ export class AccountManager { * @param fee - Fee to be paid for the deployment. * @returns A SentTx object that can be waited to get the associated Wallet. */ - public async deploy(fee?: FeeOptions): Promise { - const deployMethod = await this.getDeployMethod(); - const wallet = await this.getWallet(); + public deploy(fee?: FeeOptions): DeployAccountSentTx { + const deployMethod = this.getDeployMethod(); const sentTx = deployMethod.send({ contractAddressSalt: this.salt, fee, }); - return new DeployAccountSentTx(wallet, sentTx.getTxHash()); + return new DeployAccountSentTx(this.pxe, sentTx.getTxHash(), this.getWallet()); } /** @@ -169,7 +168,7 @@ export class AccountManager { * @returns A Wallet instance. */ public async waitSetup(opts: WaitOpts = DefaultWaitOpts): Promise { - await (this.isDeployable() ? this.deploy().then(tx => tx.wait(opts)) : this.register()); + await (this.isDeployable() ? this.deploy().wait(opts) : this.register()); return this.getWallet(); } diff --git a/yarn-project/aztec.js/src/contract/deploy_account_method.ts b/yarn-project/aztec.js/src/contract/deploy_account_method.ts index 8e4c32f30d6..d9436af9fba 100644 --- a/yarn-project/aztec.js/src/contract/deploy_account_method.ts +++ b/yarn-project/aztec.js/src/contract/deploy_account_method.ts @@ -43,6 +43,7 @@ export class DeployAccountMethod exte private publicKey: PublicKey, private artifact: ContractArtifact, private args: any[] = [], + private registerFn: () => Promise, initializerNameOrArtifact?: string | FunctionArtifact, ) { super(pxe); @@ -63,6 +64,8 @@ export class DeployAccountMethod exte throw new Error('Account contract can not be initialized without an initializer'); } + await this.registerFn(); + const feePayload = await EntrypointPayload.fromFeeOptions(options.fee); const feeAuthWit = await this.authWitnessProvider.createAuthWit(feePayload.hash()); await this.pxe.addCapsule(feePayload.toFields()); diff --git a/yarn-project/cli/src/cmds/create_account.ts b/yarn-project/cli/src/cmds/create_account.ts index 09cdadc361a..e3e72287d92 100644 --- a/yarn-project/cli/src/cmds/create_account.ts +++ b/yarn-project/cli/src/cmds/create_account.ts @@ -17,7 +17,7 @@ export async function createAccount( const account = getSchnorrAccount(client, actualPrivateKey, actualPrivateKey, Fr.ZERO); const { address, publicKey, partialAddress } = account.getCompleteAddress(); - const tx = await account.deploy(); + const tx = account.deploy(); const txHash = await tx.getTxHash(); debugLogger(`Account contract tx sent with hash ${txHash}`); if (wait) { diff --git a/yarn-project/end-to-end/src/e2e_fees.test.ts b/yarn-project/end-to-end/src/e2e_fees.test.ts index 6a11aa8ef78..d793005739b 100644 --- a/yarn-project/end-to-end/src/e2e_fees.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees.test.ts @@ -680,12 +680,12 @@ describe('e2e_fees', () => { }); it('pays fee natively', async () => { - await ( - await accountManager.deploy({ + await accountManager + .deploy({ maxFee, paymentMethod: await NativeFeePaymentMethod.create(await accountManager.getWallet()), }) - ).wait(); + .wait(); await expect(gasBalances(accountManager.getCompleteAddress().address, sequencerAddress)).resolves.toEqual([ initialGas - actualFee, diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts index 3f7cc1c469e..6fe02b1a53f 100644 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -121,7 +121,7 @@ describe('e2e_p2p_network', () => { const submitTxsTo = async (pxe: PXEService, account: AztecAddress, numTxs: number) => { const txs: SentTx[] = []; for (let i = 0; i < numTxs; i++) { - const tx = await getSchnorrAccount(pxe, GrumpkinScalar.random(), GrumpkinScalar.random(), Fr.random()).deploy(); + const tx = getSchnorrAccount(pxe, GrumpkinScalar.random(), GrumpkinScalar.random(), Fr.random()).deploy(); logger(`Tx sent with hash ${await tx.getTxHash()}`); const receipt = await tx.getReceipt(); expect(receipt).toEqual(