@aztec/aztec.js 0.23.0 → 0.24.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/dest/account/index.d.ts +1 -1
- package/dest/account/index.d.ts.map +1 -1
- package/dest/account/interface.d.ts +12 -2
- package/dest/account/interface.d.ts.map +1 -1
- package/dest/account/interface.js +1 -1
- package/dest/account_manager/index.js +2 -2
- package/dest/api/account.d.ts +1 -1
- package/dest/api/account.d.ts.map +1 -1
- package/dest/api/account.js +1 -1
- package/dest/api/deployment.d.ts +4 -0
- package/dest/api/deployment.d.ts.map +1 -0
- package/dest/api/deployment.js +4 -0
- package/dest/api/fee.d.ts +4 -0
- package/dest/api/fee.d.ts.map +1 -0
- package/dest/api/fee.js +3 -0
- package/dest/contract/unsafe_contract.d.ts +15 -0
- package/dest/contract/unsafe_contract.d.ts.map +1 -0
- package/dest/contract/unsafe_contract.js +14 -0
- package/dest/deployment/broadcast_function.d.ts +24 -0
- package/dest/deployment/broadcast_function.d.ts.map +1 -0
- package/dest/deployment/broadcast_function.js +67 -0
- package/dest/deployment/contract_deployer.d.ts.map +1 -0
- package/dest/{contract_deployer → deployment}/contract_deployer.js +1 -1
- package/dest/deployment/deploy_instance.d.ts +13 -0
- package/dest/deployment/deploy_instance.d.ts.map +1 -0
- package/dest/deployment/deploy_instance.js +13 -0
- package/dest/deployment/index.d.ts.map +1 -0
- package/dest/{contract_deployer → deployment}/index.js +1 -1
- package/dest/deployment/protocol_contracts.d.ts +7 -0
- package/dest/deployment/protocol_contracts.d.ts.map +1 -0
- package/dest/deployment/protocol_contracts.js +14 -0
- package/dest/deployment/register_class.d.ts +6 -0
- package/dest/deployment/register_class.d.ts.map +1 -0
- package/dest/deployment/register_class.js +11 -0
- package/dest/fee/fee_payment_method.d.ts +28 -0
- package/dest/fee/fee_payment_method.d.ts.map +1 -0
- package/dest/fee/fee_payment_method.js +2 -0
- package/dest/fee/generic_fee_payment_method.d.ts +58 -0
- package/dest/fee/generic_fee_payment_method.d.ts.map +1 -0
- package/dest/fee/generic_fee_payment_method.js +73 -0
- package/dest/fee/native_fee_payment_method.d.ts +32 -0
- package/dest/fee/native_fee_payment_method.d.ts.map +1 -0
- package/dest/fee/native_fee_payment_method.js +55 -0
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +3 -2
- package/dest/utils/cheat_codes.js +2 -2
- package/dest/wallet/account_wallet.d.ts +2 -2
- package/dest/wallet/account_wallet.d.ts.map +1 -1
- package/dest/wallet/account_wallet.js +3 -3
- package/dest/wallet/base_wallet.d.ts +2 -1
- package/dest/wallet/base_wallet.d.ts.map +1 -1
- package/dest/wallet/base_wallet.js +1 -1
- package/package.json +9 -6
- package/src/account/contract.ts +33 -0
- package/src/account/index.ts +16 -0
- package/src/account/interface.ts +47 -0
- package/src/account/wallet.ts +8 -0
- package/src/account_manager/deploy_account_sent_tx.ts +42 -0
- package/src/account_manager/index.ts +173 -0
- package/src/api/README.md +7 -0
- package/src/api/abi.ts +3 -0
- package/src/api/account.ts +13 -0
- package/src/api/aztec_address.ts +1 -0
- package/src/api/deployment.ts +3 -0
- package/src/api/eth_address.ts +1 -0
- package/src/api/ethereum.ts +6 -0
- package/src/api/fee.ts +3 -0
- package/src/api/fields.ts +1 -0
- package/src/api/init.ts +10 -0
- package/src/api/interfaces/pxe.ts +1 -0
- package/src/api/log_id.ts +1 -0
- package/src/api/tx_hash.ts +1 -0
- package/src/api/wallet.ts +1 -0
- package/src/contract/base_contract_interaction.ts +61 -0
- package/src/contract/batch_call.ts +23 -0
- package/src/contract/checker.ts +117 -0
- package/src/contract/contract.ts +56 -0
- package/src/contract/contract_base.ts +72 -0
- package/src/contract/contract_function_interaction.ts +80 -0
- package/src/contract/deploy_method.ts +151 -0
- package/src/contract/deploy_sent_tx.ts +69 -0
- package/src/contract/index.ts +44 -0
- package/src/contract/sent_tx.ts +135 -0
- package/src/contract/unsafe_contract.ts +19 -0
- package/src/deployment/broadcast_function.ts +118 -0
- package/src/deployment/contract_deployer.ts +30 -0
- package/src/deployment/deploy_instance.ts +28 -0
- package/src/deployment/index.ts +1 -0
- package/src/deployment/protocol_contracts.ts +17 -0
- package/src/deployment/register_class.ts +15 -0
- package/src/fee/fee_payment_method.ts +30 -0
- package/src/fee/generic_fee_payment_method.ts +81 -0
- package/src/fee/native_fee_payment_method.ts +61 -0
- package/src/index.ts +144 -0
- package/src/rpc_clients/index.ts +1 -0
- package/src/rpc_clients/pxe_client.ts +62 -0
- package/src/utils/abi_types.ts +16 -0
- package/src/utils/account.ts +32 -0
- package/src/utils/authwit.ts +24 -0
- package/src/utils/cheat_codes.ts +297 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/l1_contracts.ts +21 -0
- package/src/utils/l2_contracts.ts +12 -0
- package/src/utils/pub_key.ts +12 -0
- package/src/utils/pxe.ts +16 -0
- package/src/utils/secrets.ts +11 -0
- package/src/wallet/account_wallet.ts +70 -0
- package/src/wallet/account_wallet_with_private_key.ts +28 -0
- package/src/wallet/base_wallet.ts +123 -0
- package/src/wallet/create_recipient.ts +13 -0
- package/src/wallet/index.ts +31 -0
- package/src/wallet/signerless_wallet.ts +37 -0
- package/dest/contract_deployer/contract_deployer.d.ts.map +0 -1
- package/dest/contract_deployer/index.d.ts.map +0 -1
- /package/dest/{contract_deployer → deployment}/contract_deployer.d.ts +0 -0
- /package/dest/{contract_deployer → deployment}/index.d.ts +0 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { PXE, PackedArguments, PublicKey, Tx, TxExecutionRequest } from '@aztec/circuit-types';
|
|
2
|
+
import {
|
|
3
|
+
AztecAddress,
|
|
4
|
+
ContractDeploymentData,
|
|
5
|
+
FunctionData,
|
|
6
|
+
TxContext,
|
|
7
|
+
computePartialAddress,
|
|
8
|
+
getContractInstanceFromDeployParams,
|
|
9
|
+
} from '@aztec/circuits.js';
|
|
10
|
+
import { ContractArtifact, FunctionArtifact, encodeArguments } from '@aztec/foundation/abi';
|
|
11
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
12
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
13
|
+
import { ContractInstanceWithAddress } from '@aztec/types/contracts';
|
|
14
|
+
|
|
15
|
+
import { Wallet } from '../account/index.js';
|
|
16
|
+
import { BaseContractInteraction, SendMethodOptions } from './base_contract_interaction.js';
|
|
17
|
+
import { type Contract } from './contract.js';
|
|
18
|
+
import { ContractBase } from './contract_base.js';
|
|
19
|
+
import { DeploySentTx } from './deploy_sent_tx.js';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Options for deploying a contract on the Aztec network.
|
|
23
|
+
* Allows specifying a portal contract, contract address salt, and additional send method options.
|
|
24
|
+
*/
|
|
25
|
+
export type DeployOptions = {
|
|
26
|
+
/**
|
|
27
|
+
* The Ethereum address of the Portal contract.
|
|
28
|
+
*/
|
|
29
|
+
portalContract?: EthAddress;
|
|
30
|
+
/**
|
|
31
|
+
* An optional salt value used to deterministically calculate the contract address.
|
|
32
|
+
*/
|
|
33
|
+
contractAddressSalt?: Fr;
|
|
34
|
+
} & SendMethodOptions;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Creates a TxRequest from a contract ABI, for contract deployment.
|
|
38
|
+
* Extends the ContractFunctionInteraction class.
|
|
39
|
+
*/
|
|
40
|
+
export class DeployMethod<TContract extends ContractBase = Contract> extends BaseContractInteraction {
|
|
41
|
+
/** The contract instance to be deployed. */
|
|
42
|
+
public instance?: ContractInstanceWithAddress = undefined;
|
|
43
|
+
|
|
44
|
+
/** Constructor function to call. */
|
|
45
|
+
private constructorArtifact: FunctionArtifact;
|
|
46
|
+
|
|
47
|
+
constructor(
|
|
48
|
+
private publicKey: PublicKey,
|
|
49
|
+
protected pxe: PXE,
|
|
50
|
+
private artifact: ContractArtifact,
|
|
51
|
+
private postDeployCtor: (address: AztecAddress, wallet: Wallet) => Promise<TContract>,
|
|
52
|
+
private args: any[] = [],
|
|
53
|
+
) {
|
|
54
|
+
super(pxe);
|
|
55
|
+
const constructorArtifact = artifact.functions.find(f => f.name === 'constructor');
|
|
56
|
+
if (!constructorArtifact) {
|
|
57
|
+
throw new Error('Cannot find constructor in the artifact.');
|
|
58
|
+
}
|
|
59
|
+
this.constructorArtifact = constructorArtifact;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Create a contract deployment transaction, given the deployment options.
|
|
64
|
+
* This function internally calls `request()` and `sign()` methods to prepare
|
|
65
|
+
* the transaction for deployment. The resulting signed transaction can be
|
|
66
|
+
* later sent using the `send()` method.
|
|
67
|
+
*
|
|
68
|
+
* @param options - An object containing optional deployment settings, including portalContract, contractAddressSalt, and from.
|
|
69
|
+
* @returns A Promise resolving to an object containing the signed transaction data and other relevant information.
|
|
70
|
+
*/
|
|
71
|
+
public async create(options: DeployOptions = {}) {
|
|
72
|
+
const portalContract = options.portalContract ?? EthAddress.ZERO;
|
|
73
|
+
const contractAddressSalt = options.contractAddressSalt ?? Fr.random();
|
|
74
|
+
|
|
75
|
+
const { chainId, protocolVersion } = await this.pxe.getNodeInfo();
|
|
76
|
+
|
|
77
|
+
const deployParams = [this.artifact, this.args, contractAddressSalt, this.publicKey, portalContract] as const;
|
|
78
|
+
const instance = getContractInstanceFromDeployParams(...deployParams);
|
|
79
|
+
const address = instance.address;
|
|
80
|
+
|
|
81
|
+
const contractDeploymentData = new ContractDeploymentData(
|
|
82
|
+
this.publicKey,
|
|
83
|
+
instance.initializationHash,
|
|
84
|
+
instance.contractClassId,
|
|
85
|
+
contractAddressSalt,
|
|
86
|
+
portalContract,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const txContext = new TxContext(
|
|
90
|
+
false,
|
|
91
|
+
false,
|
|
92
|
+
true,
|
|
93
|
+
contractDeploymentData,
|
|
94
|
+
new Fr(chainId),
|
|
95
|
+
new Fr(protocolVersion),
|
|
96
|
+
);
|
|
97
|
+
const args = encodeArguments(this.constructorArtifact, this.args);
|
|
98
|
+
const functionData = FunctionData.fromAbi(this.constructorArtifact);
|
|
99
|
+
const execution = { args, functionData, to: address };
|
|
100
|
+
const packedArguments = PackedArguments.fromArgs(execution.args);
|
|
101
|
+
|
|
102
|
+
const txRequest = TxExecutionRequest.from({
|
|
103
|
+
origin: execution.to,
|
|
104
|
+
functionData: execution.functionData,
|
|
105
|
+
argsHash: packedArguments.hash,
|
|
106
|
+
txContext,
|
|
107
|
+
packedArguments: [packedArguments],
|
|
108
|
+
authWitnesses: [],
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
this.txRequest = txRequest;
|
|
112
|
+
this.instance = instance;
|
|
113
|
+
|
|
114
|
+
// TODO: Should we add the contracts to the DB here, or once the tx has been sent or mined?
|
|
115
|
+
await this.pxe.addContracts([{ artifact: this.artifact, instance }]);
|
|
116
|
+
|
|
117
|
+
return this.txRequest;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Send the contract deployment transaction using the provided options.
|
|
122
|
+
* This function extends the 'send' method from the ContractFunctionInteraction class,
|
|
123
|
+
* allowing us to send a transaction specifically for contract deployment.
|
|
124
|
+
*
|
|
125
|
+
* @param options - An object containing various deployment options such as portalContract, contractAddressSalt, and from.
|
|
126
|
+
* @returns A SentTx object that returns the receipt and the deployed contract instance.
|
|
127
|
+
*/
|
|
128
|
+
public send(options: DeployOptions = {}): DeploySentTx<TContract> {
|
|
129
|
+
const txHashPromise = super.send(options).getTxHash();
|
|
130
|
+
return new DeploySentTx(this.pxe, txHashPromise, this.postDeployCtor, this.instance!);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Simulate the request.
|
|
135
|
+
* @param options - Deployment options.
|
|
136
|
+
* @returns The simulated tx.
|
|
137
|
+
*/
|
|
138
|
+
public simulate(options: DeployOptions): Promise<Tx> {
|
|
139
|
+
return super.simulate(options);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Return this deployment address. */
|
|
143
|
+
public get address() {
|
|
144
|
+
return this.instance?.address;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Returns the partial address for this deployment. */
|
|
148
|
+
public get partialAddress() {
|
|
149
|
+
return this.instance && computePartialAddress(this.instance);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { PXE, TxHash, TxReceipt } from '@aztec/circuit-types';
|
|
2
|
+
import { AztecAddress } from '@aztec/circuits.js';
|
|
3
|
+
import { FieldsOf } from '@aztec/foundation/types';
|
|
4
|
+
import { ContractInstanceWithAddress } from '@aztec/types/contracts';
|
|
5
|
+
|
|
6
|
+
import { Wallet } from '../account/index.js';
|
|
7
|
+
import { type Contract } from './contract.js';
|
|
8
|
+
import { ContractBase } from './contract_base.js';
|
|
9
|
+
import { SentTx, WaitOpts } from './sent_tx.js';
|
|
10
|
+
|
|
11
|
+
/** Options related to waiting for a deployment tx. */
|
|
12
|
+
export type DeployedWaitOpts = WaitOpts & {
|
|
13
|
+
/** Wallet to use for creating a contract instance. Uses the one set in the deployer constructor if not set. */
|
|
14
|
+
wallet?: Wallet;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/** Extends a transaction receipt with a contract instance that represents the newly deployed contract. */
|
|
18
|
+
export type DeployTxReceipt<TContract extends ContractBase = Contract> = FieldsOf<TxReceipt> & {
|
|
19
|
+
/** Instance of the newly deployed contract. */
|
|
20
|
+
contract: TContract;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A contract deployment transaction sent to the network, extending SentTx with methods to create a contract instance.
|
|
25
|
+
*/
|
|
26
|
+
export class DeploySentTx<TContract extends Contract = Contract> extends SentTx {
|
|
27
|
+
constructor(
|
|
28
|
+
wallet: PXE | Wallet,
|
|
29
|
+
txHashPromise: Promise<TxHash>,
|
|
30
|
+
private postDeployCtor: (address: AztecAddress, wallet: Wallet) => Promise<TContract>,
|
|
31
|
+
/** The deployed contract instance */
|
|
32
|
+
public instance?: ContractInstanceWithAddress,
|
|
33
|
+
) {
|
|
34
|
+
super(wallet, txHashPromise);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Awaits for the tx to be mined and returns the contract instance. Throws if tx is not mined.
|
|
39
|
+
* @param opts - Options for configuring the waiting for the tx to be mined.
|
|
40
|
+
* @returns The deployed contract instance.
|
|
41
|
+
*/
|
|
42
|
+
public async deployed(opts?: DeployedWaitOpts): Promise<TContract> {
|
|
43
|
+
const receipt = await this.wait(opts);
|
|
44
|
+
return receipt.contract;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Awaits for the tx to be mined and returns the receipt along with a contract instance. Throws if tx is not mined.
|
|
49
|
+
* @param opts - Options for configuring the waiting for the tx to be mined.
|
|
50
|
+
* @returns The transaction receipt with the deployed contract instance.
|
|
51
|
+
*/
|
|
52
|
+
public async wait(opts?: DeployedWaitOpts): Promise<DeployTxReceipt<TContract>> {
|
|
53
|
+
const receipt = await super.wait(opts);
|
|
54
|
+
const contract = await this.getContractObject(opts?.wallet, receipt.contractAddress);
|
|
55
|
+
return { ...receipt, contract };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
protected getContractObject(wallet?: Wallet, address?: AztecAddress): Promise<TContract> {
|
|
59
|
+
const isWallet = (pxe: PXE | Wallet): pxe is Wallet => !!(pxe as Wallet).createTxExecutionRequest;
|
|
60
|
+
const contractWallet = wallet ?? (isWallet(this.pxe) && this.pxe);
|
|
61
|
+
if (!contractWallet) {
|
|
62
|
+
throw new Error(`A wallet is required for creating a contract instance`);
|
|
63
|
+
}
|
|
64
|
+
if (!address) {
|
|
65
|
+
throw new Error(`Contract address is missing from transaction receipt`);
|
|
66
|
+
}
|
|
67
|
+
return this.postDeployCtor(address, contractWallet) as Promise<TContract>;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `contract` module provides utilities for deploying and interacting with contracts, based on a
|
|
3
|
+
* `Wallet` instance and a compiled artifact. Refer to the {@link account} module for how to obtain a valid
|
|
4
|
+
* `Wallet` instance, and to the {@link https://docs.aztec.network/developers/contracts/compiling | Compiling contracts}
|
|
5
|
+
* section of the documentation for how to generate an artifact out of your Noir source code.
|
|
6
|
+
*
|
|
7
|
+
* The {@link Contract} class is the main class in this module, and provides static methods for deploying
|
|
8
|
+
* a contract or interacting with an already deployed one. The `methods` property of the contract instance
|
|
9
|
+
* provides access to private, public, and view methods, that can be invoked in a transaction via `send()`,
|
|
10
|
+
* or can be queried via `view()`.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* const contract = await Contract.deploy(wallet, MyContractArtifact, [...constructorArgs]).send().deployed();
|
|
14
|
+
* console.log(`Contract deployed at ${contract.address}`);
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* ```ts
|
|
18
|
+
* const contract = await Contract.at(address, MyContractArtifact, wallet);
|
|
19
|
+
* await contract.methods.mint(1000, owner).send().wait();
|
|
20
|
+
* console.log(`Total supply is now ${await contract.methods.totalSupply().view()}`);
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* The result of calling a method in a contract instance, such as `contract.methods.mint(1000, owner)`
|
|
24
|
+
* in the example, is a {@link ContractFunctionInteraction} instance. Usually this will be just sent as
|
|
25
|
+
* a transaction to the network via the `send` method, but you can also `simulate` it without sending,
|
|
26
|
+
* or obtaining the `request` for aggregating into a {@link BatchCall}.
|
|
27
|
+
*
|
|
28
|
+
* The result of `send`ing a transaction is a {@link SentTx} object, from which you can get the
|
|
29
|
+
* transaction hash, or simply `wait` until the transaction is mined and the local PXE Service
|
|
30
|
+
* has synchronized its changes.
|
|
31
|
+
*
|
|
32
|
+
* @remarks If you are using typescript, consider using the
|
|
33
|
+
* {@link https://docs.aztec.network/developers/contracts/compiling#typescript-interfaces | autogenerated type-safe interfaces}
|
|
34
|
+
* for interacting with your contracts.
|
|
35
|
+
*
|
|
36
|
+
* @packageDocumentation
|
|
37
|
+
*/
|
|
38
|
+
export * from './contract.js';
|
|
39
|
+
export * from './contract_function_interaction.js';
|
|
40
|
+
export * from './sent_tx.js';
|
|
41
|
+
export * from './contract_base.js';
|
|
42
|
+
export * from './batch_call.js';
|
|
43
|
+
export * from './deploy_method.js';
|
|
44
|
+
export * from './deploy_sent_tx.js';
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { ExtendedNote, GetUnencryptedLogsResponse, PXE, TxHash, TxReceipt, TxStatus } from '@aztec/circuit-types';
|
|
2
|
+
import { retryUntil } from '@aztec/foundation/retry';
|
|
3
|
+
import { FieldsOf } from '@aztec/foundation/types';
|
|
4
|
+
|
|
5
|
+
/** Options related to waiting for a tx. */
|
|
6
|
+
export type WaitOpts = {
|
|
7
|
+
/** The maximum time (in seconds) to wait for the transaction to be mined. Defaults to 60. */
|
|
8
|
+
timeout?: number;
|
|
9
|
+
/** The time interval (in seconds) between retries to fetch the transaction receipt. Defaults to 1. */
|
|
10
|
+
interval?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Whether to wait for the PXE Service to sync all notes up to the block in which this tx was mined.
|
|
13
|
+
* If false, then any queries that depend on state set by this transaction may return stale data. Defaults to true.
|
|
14
|
+
**/
|
|
15
|
+
waitForNotesSync?: boolean;
|
|
16
|
+
/** Whether to include information useful for debugging/testing in the receipt. */
|
|
17
|
+
debug?: boolean;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const DefaultWaitOpts: WaitOpts = {
|
|
21
|
+
timeout: 60,
|
|
22
|
+
interval: 1,
|
|
23
|
+
waitForNotesSync: true,
|
|
24
|
+
debug: false,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The SentTx class represents a sent transaction through the PXE, providing methods to fetch
|
|
29
|
+
* its hash, receipt, and mining status.
|
|
30
|
+
*/
|
|
31
|
+
export class SentTx {
|
|
32
|
+
constructor(protected pxe: PXE, protected txHashPromise: Promise<TxHash>) {}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Retrieves the transaction hash of the SentTx instance.
|
|
36
|
+
* The function internally awaits for the 'txHashPromise' to resolve, and then returns the resolved transaction hash.
|
|
37
|
+
*
|
|
38
|
+
* @returns A promise that resolves to the transaction hash of the SentTx instance.
|
|
39
|
+
*/
|
|
40
|
+
public async getTxHash() {
|
|
41
|
+
return await this.txHashPromise;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Retrieve the transaction receipt associated with the current SentTx instance.
|
|
46
|
+
* The function fetches the transaction hash using 'getTxHash' and then queries
|
|
47
|
+
* the PXE to get the corresponding transaction receipt.
|
|
48
|
+
*
|
|
49
|
+
* @returns A promise that resolves to a TxReceipt object representing the fetched transaction receipt.
|
|
50
|
+
*/
|
|
51
|
+
public async getReceipt(): Promise<TxReceipt> {
|
|
52
|
+
const txHash = await this.getTxHash();
|
|
53
|
+
return await this.pxe.getTxReceipt(txHash);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Awaits for a tx to be mined and returns the receipt. Throws if tx is not mined.
|
|
58
|
+
* @param opts - Options for configuring the waiting for the tx to be mined.
|
|
59
|
+
* @returns The transaction receipt.
|
|
60
|
+
*/
|
|
61
|
+
public async wait(opts?: WaitOpts): Promise<FieldsOf<TxReceipt>> {
|
|
62
|
+
if (opts?.debug && opts.waitForNotesSync === false) {
|
|
63
|
+
throw new Error('Cannot set getNotes to true if waitForNotesSync is false');
|
|
64
|
+
}
|
|
65
|
+
const receipt = await this.waitForReceipt(opts);
|
|
66
|
+
if (receipt.status !== TxStatus.MINED) {
|
|
67
|
+
throw new Error(`Transaction ${await this.getTxHash()} was ${receipt.status}`);
|
|
68
|
+
}
|
|
69
|
+
if (opts?.debug) {
|
|
70
|
+
const txHash = await this.getTxHash();
|
|
71
|
+
const tx = (await this.pxe.getTx(txHash))!;
|
|
72
|
+
const visibleNotes = await this.pxe.getNotes({ txHash });
|
|
73
|
+
receipt.debugInfo = {
|
|
74
|
+
newCommitments: tx.newCommitments,
|
|
75
|
+
newNullifiers: tx.newNullifiers,
|
|
76
|
+
newPublicDataWrites: tx.newPublicDataWrites,
|
|
77
|
+
newL2ToL1Msgs: tx.newL2ToL1Msgs,
|
|
78
|
+
newContracts: tx.newContracts,
|
|
79
|
+
newContractData: tx.newContractData,
|
|
80
|
+
visibleNotes,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return receipt;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Gets unencrypted logs emitted by this tx.
|
|
88
|
+
* @remarks This function will wait for the tx to be mined if it hasn't been already.
|
|
89
|
+
* @returns The requested logs.
|
|
90
|
+
*/
|
|
91
|
+
public async getUnencryptedLogs(): Promise<GetUnencryptedLogsResponse> {
|
|
92
|
+
await this.wait();
|
|
93
|
+
return this.pxe.getUnencryptedLogs({ txHash: await this.getTxHash() });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get notes of accounts registered in the provided PXE/Wallet created in this tx.
|
|
98
|
+
* @remarks This function will wait for the tx to be mined if it hasn't been already.
|
|
99
|
+
* @returns The requested notes.
|
|
100
|
+
*/
|
|
101
|
+
public async getVisibleNotes(): Promise<ExtendedNote[]> {
|
|
102
|
+
await this.wait();
|
|
103
|
+
return this.pxe.getNotes({ txHash: await this.getTxHash() });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
protected async waitForReceipt(opts?: WaitOpts): Promise<TxReceipt> {
|
|
107
|
+
const txHash = await this.getTxHash();
|
|
108
|
+
return await retryUntil(
|
|
109
|
+
async () => {
|
|
110
|
+
const txReceipt = await this.pxe.getTxReceipt(txHash);
|
|
111
|
+
// If receipt is not yet available, try again
|
|
112
|
+
if (txReceipt.status === TxStatus.PENDING) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
// If the tx was dropped, return it
|
|
116
|
+
if (txReceipt.status === TxStatus.DROPPED) {
|
|
117
|
+
return txReceipt;
|
|
118
|
+
}
|
|
119
|
+
// If we don't care about waiting for notes to be synced, return the receipt
|
|
120
|
+
const waitForNotesSync = opts?.waitForNotesSync ?? DefaultWaitOpts.waitForNotesSync;
|
|
121
|
+
if (!waitForNotesSync) {
|
|
122
|
+
return txReceipt;
|
|
123
|
+
}
|
|
124
|
+
// Check if all sync blocks on the PXE Service are greater or equal than the block in which the tx was mined
|
|
125
|
+
const { blocks, notes } = await this.pxe.getSyncStatus();
|
|
126
|
+
const targetBlock = txReceipt.blockNumber!;
|
|
127
|
+
const areNotesSynced = blocks >= targetBlock && Object.values(notes).every(block => block >= targetBlock);
|
|
128
|
+
return areNotesSynced ? txReceipt : undefined;
|
|
129
|
+
},
|
|
130
|
+
'isMined',
|
|
131
|
+
opts?.timeout ?? DefaultWaitOpts.timeout,
|
|
132
|
+
opts?.interval ?? DefaultWaitOpts.interval,
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ContractArtifact } from '@aztec/foundation/abi';
|
|
2
|
+
import { ContractInstanceWithAddress } from '@aztec/types/contracts';
|
|
3
|
+
|
|
4
|
+
import { Wallet } from '../wallet/index.js';
|
|
5
|
+
import { ContractBase } from './contract_base.js';
|
|
6
|
+
|
|
7
|
+
/** Unsafe constructor for ContractBase that bypasses the check that the instance is registered in the wallet. */
|
|
8
|
+
export class UnsafeContract extends ContractBase {
|
|
9
|
+
constructor(
|
|
10
|
+
/** The deployed contract instance definition. */
|
|
11
|
+
instance: ContractInstanceWithAddress,
|
|
12
|
+
/** The Application Binary Interface for the contract. */
|
|
13
|
+
artifact: ContractArtifact,
|
|
14
|
+
/** The wallet used for interacting with this contract. */
|
|
15
|
+
wallet: Wallet,
|
|
16
|
+
) {
|
|
17
|
+
super(instance, artifact, wallet);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ARTIFACT_FUNCTION_TREE_MAX_HEIGHT,
|
|
3
|
+
MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS,
|
|
4
|
+
computeArtifactFunctionTree,
|
|
5
|
+
computeArtifactFunctionTreeRoot,
|
|
6
|
+
computeArtifactMetadataHash,
|
|
7
|
+
computeFunctionArtifactHash,
|
|
8
|
+
computePrivateFunctionsTree,
|
|
9
|
+
getContractClassFromArtifact,
|
|
10
|
+
} from '@aztec/circuits.js';
|
|
11
|
+
import { ContractArtifact, FunctionSelector, FunctionType, bufferAsFields } from '@aztec/foundation/abi';
|
|
12
|
+
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
13
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
14
|
+
|
|
15
|
+
import { ContractFunctionInteraction } from '../contract/contract_function_interaction.js';
|
|
16
|
+
import { Wallet } from '../wallet/index.js';
|
|
17
|
+
import { getRegistererContract } from './protocol_contracts.js';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Sets up a call to broadcast a private function's bytecode via the ClassRegisterer contract.
|
|
21
|
+
* Note that this is not required for users to call the function, but is rather a convenience to make
|
|
22
|
+
* this code publicly available so dapps or wallets do not need to redistribute it.
|
|
23
|
+
* @param wallet - Wallet to send the transaction.
|
|
24
|
+
* @param artifact - Contract artifact that contains the function to be broadcast.
|
|
25
|
+
* @param selector - Selector of the function to be broadcast.
|
|
26
|
+
* @returns A ContractFunctionInteraction object that can be used to send the transaction.
|
|
27
|
+
*/
|
|
28
|
+
export function broadcastPrivateFunction(
|
|
29
|
+
wallet: Wallet,
|
|
30
|
+
artifact: ContractArtifact,
|
|
31
|
+
selector: FunctionSelector,
|
|
32
|
+
): ContractFunctionInteraction {
|
|
33
|
+
const contractClass = getContractClassFromArtifact(artifact);
|
|
34
|
+
const privateFunction = contractClass.privateFunctions.find(fn => fn.selector.equals(selector));
|
|
35
|
+
if (!privateFunction) {
|
|
36
|
+
throw new Error(`Private function with selector ${selector.toString()} not found`);
|
|
37
|
+
}
|
|
38
|
+
const privateFunctionArtifact = artifact.functions.find(fn =>
|
|
39
|
+
FunctionSelector.fromNameAndParameters(fn).equals(selector),
|
|
40
|
+
)!;
|
|
41
|
+
|
|
42
|
+
// TODO(@spalladino): The following is computing the unconstrained root hash twice.
|
|
43
|
+
// Feels like we need a nicer API for returning a hash along with all its preimages,
|
|
44
|
+
// since it's common to provide all hash preimages to a function that verifies them.
|
|
45
|
+
const artifactMetadataHash = computeArtifactMetadataHash(artifact);
|
|
46
|
+
const unconstrainedArtifactFunctionTreeRoot = computeArtifactFunctionTreeRoot(artifact, FunctionType.OPEN);
|
|
47
|
+
|
|
48
|
+
// We need two sibling paths because private function information is split across two trees:
|
|
49
|
+
// The "private function tree" captures the selectors and verification keys, and is used in the kernel circuit for verifying the proof generated by the app circuit.
|
|
50
|
+
// The "artifact tree" captures function bytecode and metadata, and is used by the pxe to check that its executing the code it's supposed to be executing, but it never goes into circuits.
|
|
51
|
+
const privateFunctionTreePath = computePrivateFunctionsTree(contractClass.privateFunctions).getSiblingPath(0);
|
|
52
|
+
const artifactFunctionTreePath = computeArtifactFunctionTree(artifact, FunctionType.SECRET)!.getSiblingPath(0);
|
|
53
|
+
|
|
54
|
+
const vkHash = privateFunction.vkHash;
|
|
55
|
+
const metadataHash = computeFunctionArtifactHash(privateFunctionArtifact);
|
|
56
|
+
const bytecode = bufferAsFields(
|
|
57
|
+
Buffer.from(privateFunctionArtifact.bytecode, 'hex'),
|
|
58
|
+
MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const registerer = getRegistererContract(wallet);
|
|
62
|
+
return registerer.methods.broadcast_private_function(
|
|
63
|
+
contractClass.id,
|
|
64
|
+
Fr.fromBufferReduce(artifactMetadataHash),
|
|
65
|
+
Fr.fromBufferReduce(unconstrainedArtifactFunctionTreeRoot),
|
|
66
|
+
privateFunctionTreePath.map(Fr.fromBufferReduce),
|
|
67
|
+
padArrayEnd(artifactFunctionTreePath.map(Fr.fromBufferReduce), Fr.ZERO, ARTIFACT_FUNCTION_TREE_MAX_HEIGHT),
|
|
68
|
+
// eslint-disable-next-line camelcase
|
|
69
|
+
{ selector, metadata_hash: Fr.fromBufferReduce(metadataHash), bytecode, vk_hash: vkHash },
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Sets up a call to broadcast an unconstrained function's bytecode via the ClassRegisterer contract.
|
|
75
|
+
* Note that this is not required for users to call the function, but is rather a convenience to make
|
|
76
|
+
* this code publicly available so dapps or wallets do not need to redistribute it.
|
|
77
|
+
* @param wallet - Wallet to send the transaction.
|
|
78
|
+
* @param artifact - Contract artifact that contains the function to be broadcast.
|
|
79
|
+
* @param selector - Selector of the function to be broadcast.
|
|
80
|
+
* @returns A ContractFunctionInteraction object that can be used to send the transaction.
|
|
81
|
+
*/
|
|
82
|
+
export function broadcastUnconstrainedFunction(
|
|
83
|
+
wallet: Wallet,
|
|
84
|
+
artifact: ContractArtifact,
|
|
85
|
+
selector: FunctionSelector,
|
|
86
|
+
): ContractFunctionInteraction {
|
|
87
|
+
const functionArtifactIndex = artifact.functions.findIndex(
|
|
88
|
+
fn => fn.functionType === FunctionType.UNCONSTRAINED && FunctionSelector.fromNameAndParameters(fn).equals(selector),
|
|
89
|
+
);
|
|
90
|
+
if (functionArtifactIndex < 0) {
|
|
91
|
+
throw new Error(`Unconstrained function with selector ${selector.toString()} not found`);
|
|
92
|
+
}
|
|
93
|
+
const functionArtifact = artifact.functions[functionArtifactIndex];
|
|
94
|
+
|
|
95
|
+
// TODO(@spalladino): Same comment as above on computing duplicated hashes.
|
|
96
|
+
const artifactMetadataHash = computeArtifactMetadataHash(artifact);
|
|
97
|
+
const privateArtifactFunctionTreeRoot = computeArtifactFunctionTreeRoot(artifact, FunctionType.SECRET);
|
|
98
|
+
const functionTreePath = computeArtifactFunctionTree(artifact, FunctionType.UNCONSTRAINED)!.getSiblingPath(
|
|
99
|
+
functionArtifactIndex,
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const contractClassId = getContractClassFromArtifact(artifact).id;
|
|
103
|
+
const metadataHash = computeFunctionArtifactHash(functionArtifact);
|
|
104
|
+
const bytecode = bufferAsFields(
|
|
105
|
+
Buffer.from(functionArtifact.bytecode, 'hex'),
|
|
106
|
+
MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS,
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const registerer = getRegistererContract(wallet);
|
|
110
|
+
return registerer.methods.broadcast_unconstrained_function(
|
|
111
|
+
contractClassId,
|
|
112
|
+
Fr.fromBufferReduce(artifactMetadataHash),
|
|
113
|
+
Fr.fromBufferReduce(privateArtifactFunctionTreeRoot),
|
|
114
|
+
padArrayEnd(functionTreePath.map(Fr.fromBufferReduce), Fr.ZERO, ARTIFACT_FUNCTION_TREE_MAX_HEIGHT),
|
|
115
|
+
// eslint-disable-next-line camelcase
|
|
116
|
+
{ selector, metadata_hash: Fr.fromBufferReduce(metadataHash), bytecode },
|
|
117
|
+
);
|
|
118
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { PXE, PublicKey } from '@aztec/circuit-types';
|
|
2
|
+
import { AztecAddress } from '@aztec/circuits.js';
|
|
3
|
+
import { ContractArtifact } from '@aztec/foundation/abi';
|
|
4
|
+
import { Point } from '@aztec/foundation/fields';
|
|
5
|
+
|
|
6
|
+
import { Wallet } from '../account/wallet.js';
|
|
7
|
+
import { DeployMethod } from '../contract/deploy_method.js';
|
|
8
|
+
import { Contract } from '../contract/index.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A class for deploying contract.
|
|
12
|
+
* @remarks Keeping this around even though we have Aztec.nr contract types because it can be useful for non-TS users.
|
|
13
|
+
*/
|
|
14
|
+
export class ContractDeployer {
|
|
15
|
+
constructor(private artifact: ContractArtifact, private pxe: PXE, private publicKey?: PublicKey) {}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Deploy a contract using the provided ABI and constructor arguments.
|
|
19
|
+
* This function creates a new DeployMethod instance that can be used to send deployment transactions
|
|
20
|
+
* and query deployment status. The method accepts any number of constructor arguments, which will
|
|
21
|
+
* be passed to the contract's constructor during deployment.
|
|
22
|
+
*
|
|
23
|
+
* @param args - The constructor arguments for the contract being deployed.
|
|
24
|
+
* @returns A DeployMethod instance configured with the ABI, PXE, and constructor arguments.
|
|
25
|
+
*/
|
|
26
|
+
public deploy(...args: any[]) {
|
|
27
|
+
const postDeployCtor = (address: AztecAddress, wallet: Wallet) => Contract.at(address, this.artifact, wallet);
|
|
28
|
+
return new DeployMethod(this.publicKey ?? Point.ZERO, this.pxe, this.artifact, postDeployCtor, args);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ContractInstanceWithAddress } from '@aztec/types/contracts';
|
|
2
|
+
|
|
3
|
+
import { ContractFunctionInteraction } from '../contract/contract_function_interaction.js';
|
|
4
|
+
import { Wallet } from '../wallet/index.js';
|
|
5
|
+
import { getDeployerContract } from './protocol_contracts.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Sets up a call to the canonical deployer contract to publicly deploy a contract instance.
|
|
9
|
+
* @param wallet - The wallet to use for the deployment.
|
|
10
|
+
* @param instance - The instance to deploy.
|
|
11
|
+
* @param opts - Additional options.
|
|
12
|
+
*/
|
|
13
|
+
export function deployInstance(
|
|
14
|
+
wallet: Wallet,
|
|
15
|
+
instance: ContractInstanceWithAddress,
|
|
16
|
+
opts: { /** Set to true to *not* mix in the deployer into the address. */ universalDeploy?: boolean } = {},
|
|
17
|
+
): ContractFunctionInteraction {
|
|
18
|
+
const deployer = getDeployerContract(wallet);
|
|
19
|
+
const { salt, contractClassId, portalContractAddress, publicKeysHash } = instance;
|
|
20
|
+
return deployer.methods.deploy(
|
|
21
|
+
salt,
|
|
22
|
+
contractClassId,
|
|
23
|
+
instance.initializationHash,
|
|
24
|
+
portalContractAddress,
|
|
25
|
+
publicKeysHash,
|
|
26
|
+
!!opts.universalDeploy,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './contract_deployer.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { getCanonicalClassRegisterer } from '@aztec/protocol-contracts/class-registerer';
|
|
2
|
+
import { getCanonicalInstanceDeployer } from '@aztec/protocol-contracts/instance-deployer';
|
|
3
|
+
|
|
4
|
+
import { UnsafeContract } from '../contract/unsafe_contract.js';
|
|
5
|
+
import { Wallet } from '../wallet/index.js';
|
|
6
|
+
|
|
7
|
+
/** Returns a Contract wrapper for the class registerer. */
|
|
8
|
+
export function getRegistererContract(wallet: Wallet) {
|
|
9
|
+
const { artifact, instance } = getCanonicalClassRegisterer();
|
|
10
|
+
return new UnsafeContract(instance, artifact, wallet);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Returns a Contract wrapper for the instance deployer. */
|
|
14
|
+
export function getDeployerContract(wallet: Wallet) {
|
|
15
|
+
const { artifact, instance } = getCanonicalInstanceDeployer();
|
|
16
|
+
return new UnsafeContract(instance, artifact, wallet);
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS, getContractClassFromArtifact } from '@aztec/circuits.js';
|
|
2
|
+
import { ContractArtifact, bufferAsFields } from '@aztec/foundation/abi';
|
|
3
|
+
|
|
4
|
+
import { ContractFunctionInteraction } from '../contract/contract_function_interaction.js';
|
|
5
|
+
import { Wallet } from '../wallet/index.js';
|
|
6
|
+
import { getRegistererContract } from './protocol_contracts.js';
|
|
7
|
+
|
|
8
|
+
/** Sets up a call to register a contract class given its artifact. */
|
|
9
|
+
export function registerContractClass(wallet: Wallet, artifact: ContractArtifact): ContractFunctionInteraction {
|
|
10
|
+
const { artifactHash, privateFunctionsRoot, publicBytecodeCommitment, packedBytecode } =
|
|
11
|
+
getContractClassFromArtifact(artifact);
|
|
12
|
+
const encodedBytecode = bufferAsFields(packedBytecode, MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS);
|
|
13
|
+
const registerer = getRegistererContract(wallet);
|
|
14
|
+
return registerer.methods.register(artifactHash, privateFunctionsRoot, publicBytecodeCommitment, encodedBytecode);
|
|
15
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { FunctionCall } from '@aztec/circuit-types';
|
|
2
|
+
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
3
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Holds information about how the fee for a transaction is to be paid.
|
|
7
|
+
*/
|
|
8
|
+
export interface FeePaymentMethod {
|
|
9
|
+
/**
|
|
10
|
+
* The asset used to pay the fee.
|
|
11
|
+
*/
|
|
12
|
+
getAsset(): AztecAddress;
|
|
13
|
+
/**
|
|
14
|
+
* Address which will hold the fee payment.
|
|
15
|
+
*/
|
|
16
|
+
getPaymentContract(): AztecAddress;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Whether the fee payment is private or not
|
|
20
|
+
*/
|
|
21
|
+
isPrivateFeePayment(): boolean;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Creates a function call to pay the fee in the given asset.
|
|
25
|
+
* TODO(fees) replace maxFee with gas limits
|
|
26
|
+
* @param maxFee - The maximum fee to be paid in the given asset.
|
|
27
|
+
* @returns The function call to pay the fee.
|
|
28
|
+
*/
|
|
29
|
+
getFunctionCalls(maxFee: Fr): FunctionCall[];
|
|
30
|
+
}
|