var _AccountManager_instances, _AccountManager_register;
import { __classPrivateFieldGet } from "tslib";
import { getContractDeploymentInfo } from '@aztec/circuits.js';
import { Fr } from '@aztec/foundation/fields';
import { CompleteAddress } from '@aztec/types';
import { DefaultWaitOpts } from '../../contract/sent_tx.js';
import { AccountWalletWithPrivateKey, ContractDeployer, generatePublicKey, } from '../../index.js';
import { DeployAccountSentTx } from './deploy_account_sent_tx.js';
import { waitForAccountSynch } from './util.js';
/**
 * Manages a user account. Provides methods for calculating the account's address, deploying the account contract,
 * and creating and registering the user wallet in the PXE Service.
 */
export class AccountManager {
    constructor(pxe, encryptionPrivateKey, accountContract, saltOrAddress) {
        _AccountManager_instances.add(this);
        this.pxe = pxe;
        this.encryptionPrivateKey = encryptionPrivateKey;
        this.accountContract = accountContract;
        if (saltOrAddress instanceof CompleteAddress) {
            this.completeAddress = saltOrAddress;
        }
        else {
            this.salt = saltOrAddress ? new Fr(saltOrAddress) : Fr.random();
        }
    }
    getEncryptionPublicKey() {
        if (!this.encryptionPublicKey) {
            this.encryptionPublicKey = generatePublicKey(this.encryptionPrivateKey);
        }
        return this.encryptionPublicKey;
    }
    /**
     * Returns the entrypoint for this account as defined by its account contract.
     * @returns An entrypoint.
     */
    async getAccount() {
        const nodeInfo = await this.pxe.getNodeInfo();
        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.
     */
    getCompleteAddress() {
        if (!this.completeAddress) {
            const encryptionPublicKey = generatePublicKey(this.encryptionPrivateKey);
            const contractDeploymentInfo = getContractDeploymentInfo(this.accountContract.getContractArtifact(), this.accountContract.getDeploymentArgs(), this.salt, encryptionPublicKey);
            this.completeAddress = contractDeploymentInfo.completeAddress;
        }
        return this.completeAddress;
    }
    /**
     * Returns a Wallet instance associated with this account. Use it to create Contract
     * instances to be interacted with from this account.
     * @returns A Wallet instance.
     */
    async getWallet() {
        const entrypoint = await this.getAccount();
        return new AccountWalletWithPrivateKey(this.pxe, entrypoint, this.encryptionPrivateKey);
    }
    /**
     * Registers this account in the PXE Service and returns the associated wallet. Registering
     * the account on the PXE Service is required for managing private state associated with it.
     * Use the returned wallet to create Contract instances to be interacted with from this account.
     * @param opts - Options to wait for the account to be synched.
     * @returns A Wallet instance.
     */
    async register(opts = DefaultWaitOpts) {
        const address = await __classPrivateFieldGet(this, _AccountManager_instances, "m", _AccountManager_register).call(this);
        await waitForAccountSynch(this.pxe, address, opts);
        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
     * grained control on when to create, simulate, and send the deployment tx.
     * @returns A DeployMethod instance that deploys this account contract.
     */
    async getDeployMethod() {
        if (!this.deployMethod) {
            if (!this.salt) {
                throw new Error(`Cannot deploy account contract without known salt.`);
            }
            await __classPrivateFieldGet(this, _AccountManager_instances, "m", _AccountManager_register).call(this);
            const encryptionPublicKey = this.getEncryptionPublicKey();
            const deployer = new ContractDeployer(this.accountContract.getContractArtifact(), this.pxe, encryptionPublicKey);
            const args = this.accountContract.getDeploymentArgs();
            this.deployMethod = deployer.deploy(...args);
        }
        return this.deployMethod;
    }
    /**
     * Deploys the account contract that backs this account.
     * Uses the salt provided in the constructor or a randomly generated one.
     * 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 PXE Service before deploying the contract.
     * @returns A SentTx object that can be waited to get the associated Wallet.
     */
    async deploy() {
        const deployMethod = await this.getDeployMethod();
        const wallet = await this.getWallet();
        const sentTx = deployMethod.send({ contractAddressSalt: this.salt });
        return new DeployAccountSentTx(wallet, sentTx.getTxHash());
    }
    /**
     * Deploys the account contract that backs this account and awaits the tx to be mined.
     * Uses the salt provided in the constructor or a randomly generated one.
     * 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 PXE Service before deploying the contract.
     * @param opts - Options to wait for the tx to be mined.
     * @returns A Wallet instance.
     */
    async waitDeploy(opts = DefaultWaitOpts) {
        await this.deploy().then(tx => tx.wait(opts));
        return this.getWallet();
    }
}
_AccountManager_instances = new WeakSet(), _AccountManager_register = async function _AccountManager_register() {
    const completeAddress = this.getCompleteAddress();
    await this.pxe.registerAccount(this.encryptionPrivateKey, completeAddress.partialAddress);
    return completeAddress;
};
//# sourceMappingURL=data:application/json;base64, 