Skip to content

Commit

Permalink
refactor: not calling getContractDeploymentInfo twice when setting up…
Browse files Browse the repository at this point in the history
… account
  • Loading branch information
benesjan committed Sep 19, 2023
1 parent 1c157a2 commit a1d1973
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 38 deletions.
57 changes: 20 additions & 37 deletions yarn-project/aztec.js/src/account/manager/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Fr, PublicKey, getContractDeploymentInfo } from '@aztec/circuits.js';
import { Fr, PublicKey } from '@aztec/circuits.js';
import { AztecRPC, CompleteAddress, GrumpkinPrivateKey } from '@aztec/types';

import { DeploySentTx } from '../../contract_deployer/deploy_sent_tx.js';
import { AccountWallet, ContractDeployer, DeployMethod, WaitOpts, generatePublicKey } from '../../index.js';
import { AccountContract, Salt } from '../index.js';
import { AccountInterface } from '../interface.js';
import { DeployAccountSentTx } from './deploy_account_sent_tx.js';

/**
* Manages a user account. Provides methods for calculating the account's address, deploying the account contract,
Expand All @@ -14,7 +14,7 @@ export class AccountManager {
/** Deployment salt for the account contract. */
public readonly salt?: Fr;

private completeAddress?: Promise<CompleteAddress>;
private completeAddress?: CompleteAddress;
private encryptionPublicKey?: PublicKey;
private deployMethod?: DeployMethod;

Expand All @@ -25,7 +25,7 @@ export class AccountManager {
saltOrAddress?: Salt | CompleteAddress,
) {
if (saltOrAddress instanceof CompleteAddress) {
this.completeAddress = Promise.resolve(saltOrAddress);
this.completeAddress = saltOrAddress;
} else {
this.salt = saltOrAddress ? new Fr(saltOrAddress) : Fr.random();
}
Expand All @@ -44,27 +44,18 @@ export class AccountManager {
*/
public async getAccount(): Promise<AccountInterface> {
const nodeInfo = await this.rpc.getNodeInfo();
const completeAddress = await this.getCompleteAddress();
const completeAddress = this.getCompleteAddress();
return this.accountContract.getInterface(completeAddress, nodeInfo);
}

/**
* Gets the calculated complete address associated with this account.
* Does not require the account to be deployed or registered.
* @returns The address, partial address, and encryption public key.
* Gets the complete address associated with this account.
* @throws If the account contract has not been deployed yet.
* @returns The account's complete address.
*/
public getCompleteAddress(): Promise<CompleteAddress> {
public getCompleteAddress(): CompleteAddress {
if (!this.completeAddress) {
this.completeAddress = (async () => {
const encryptionPublicKey = await generatePublicKey(this.encryptionPrivateKey);
const contractDeploymentInfo = await getContractDeploymentInfo(
this.accountContract.getContractAbi(),
await this.accountContract.getDeploymentArgs(),
this.salt!,
encryptionPublicKey,
);
return contractDeploymentInfo.completeAddress;
})();
throw new Error(`Cannot get complete address without first deploying the account contract.`);
}
return this.completeAddress;
}
Expand All @@ -79,18 +70,6 @@ export class AccountManager {
return new AccountWallet(this.rpc, entrypoint);
}

/**
* Registers this account in the RPC server and returns the associated wallet. Registering
* the account on the RPC server is required for managing private state associated with it.
* Use the returned wallet to create Contract instances to be interacted with from this account.
* @returns A Wallet instance.
*/
public async register(): Promise<AccountWallet> {
const completeAddress = await this.getCompleteAddress();
await this.rpc.registerAccount(this.encryptionPrivateKey, completeAddress.partialAddress);
return this.getWallet();
}

/**
* Returns the pre-populated deployment method to deploy the account contract that backs this account.
* Typically you will not need this method and can call `deploy` directly. Use this for having finer
Expand All @@ -100,7 +79,6 @@ export class AccountManager {
public async getDeployMethod() {
if (!this.deployMethod) {
if (!this.salt) throw new Error(`Cannot deploy account contract without known salt.`);
await this.register();
const encryptionPublicKey = await this.getEncryptionPublicKey();
const deployer = new ContractDeployer(this.accountContract.getContractAbi(), this.rpc, encryptionPublicKey);
const args = await this.accountContract.getDeploymentArgs();
Expand All @@ -115,13 +93,18 @@ export class AccountManager {
* Note that if the Account is constructed with an explicit complete address
* it is assumed that the account contract has already been deployed and this method will throw.
* Registers the account in the RPC server before deploying the contract.
* @returns A SentTx object that can be waited to get the associated Wallet.
* @returns A DeploySentTx object.
*/
public async deploy(): Promise<DeployAccountSentTx> {
public async deploy(): Promise<DeploySentTx> {
if (this.completeAddress) {
throw new Error(`Cannot deploy account contract when complete address is already set.`);
}
const deployMethod = await this.getDeployMethod();
const wallet = await this.getWallet();
const sentTx = deployMethod.send({ contractAddressSalt: this.salt });
return new DeployAccountSentTx(wallet, sentTx.getTxHash());
const postDeploymentCallback = async (completeAddress: CompleteAddress) => {
this.completeAddress = completeAddress;
await this.rpc.registerAccount(this.encryptionPrivateKey, completeAddress.partialAddress);
};
return deployMethod.send({ contractAddressSalt: this.salt, postDeploymentCallback });
}

/**
Expand Down
8 changes: 8 additions & 0 deletions yarn-project/aztec.js/src/contract_deployer/deploy_method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export interface DeployOptions extends SendMethodOptions {
* An optional salt value used to deterministically calculate the contract address.
*/
contractAddressSalt?: Fr;
/**
* An optional callback function to register the deployed contract with the RPC server.
*/
postDeploymentCallback?: (completeAddress: CompleteAddress) => Promise<void>;
}

/**
Expand Down Expand Up @@ -105,6 +109,10 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas
// TODO: Should we add the contracts to the DB here, or once the tx has been sent or mined?
await this.rpc.addContracts([{ abi: this.abi, completeAddress, portalContract }]);

if (options.postDeploymentCallback) {
await options.postDeploymentCallback(completeAddress);
}

return this.txRequest;
}

Expand Down
2 changes: 1 addition & 1 deletion yarn-project/end-to-end/src/e2e_account_contracts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ describe('e2e_account_contracts', () => {
address?: CompleteAddress,
) => {
const account = new AccountManager(rpc, encryptionPrivateKey, accountContract, address);
const wallet = !address ? await account.deploy().then(tx => tx.getWallet()) : await account.getWallet();
const wallet = !address ? await account.waitDeploy() : await account.getWallet();
return { account, wallet };
};

Expand Down

0 comments on commit a1d1973

Please sign in to comment.