@aztec/aztec.js 0.23.0 → 0.26.1

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 (155) hide show
  1. package/dest/account/index.d.ts +1 -1
  2. package/dest/account/index.d.ts.map +1 -1
  3. package/dest/account/interface.d.ts +12 -2
  4. package/dest/account/interface.d.ts.map +1 -1
  5. package/dest/account/interface.js +1 -1
  6. package/dest/account_manager/index.d.ts +4 -2
  7. package/dest/account_manager/index.d.ts.map +1 -1
  8. package/dest/account_manager/index.js +15 -6
  9. package/dest/api/account.d.ts +1 -1
  10. package/dest/api/account.d.ts.map +1 -1
  11. package/dest/api/account.js +1 -1
  12. package/dest/api/deployment.d.ts +4 -0
  13. package/dest/api/deployment.d.ts.map +1 -0
  14. package/dest/api/deployment.js +4 -0
  15. package/dest/api/fee.d.ts +5 -0
  16. package/dest/api/fee.d.ts.map +1 -0
  17. package/dest/api/fee.js +4 -0
  18. package/dest/contract/base_contract_interaction.d.ts +5 -0
  19. package/dest/contract/base_contract_interaction.d.ts.map +1 -1
  20. package/dest/contract/base_contract_interaction.js +1 -1
  21. package/dest/contract/batch_call.d.ts +3 -2
  22. package/dest/contract/batch_call.d.ts.map +1 -1
  23. package/dest/contract/batch_call.js +4 -3
  24. package/dest/contract/contract.d.ts +4 -2
  25. package/dest/contract/contract.d.ts.map +1 -1
  26. package/dest/contract/contract.js +7 -5
  27. package/dest/contract/contract_function_interaction.d.ts +2 -2
  28. package/dest/contract/contract_function_interaction.d.ts.map +1 -1
  29. package/dest/contract/contract_function_interaction.js +4 -4
  30. package/dest/contract/deploy_method.d.ts +37 -12
  31. package/dest/contract/deploy_method.d.ts.map +1 -1
  32. package/dest/contract/deploy_method.js +79 -35
  33. package/dest/contract/deploy_sent_tx.d.ts +3 -3
  34. package/dest/contract/deploy_sent_tx.d.ts.map +1 -1
  35. package/dest/contract/deploy_sent_tx.js +4 -7
  36. package/dest/contract/sent_tx.d.ts.map +1 -1
  37. package/dest/contract/sent_tx.js +10 -10
  38. package/dest/contract/unsafe_contract.d.ts +15 -0
  39. package/dest/contract/unsafe_contract.d.ts.map +1 -0
  40. package/dest/contract/unsafe_contract.js +14 -0
  41. package/dest/deployment/broadcast_function.d.ts +24 -0
  42. package/dest/deployment/broadcast_function.d.ts.map +1 -0
  43. package/dest/deployment/broadcast_function.js +67 -0
  44. package/dest/{contract_deployer → deployment}/contract_deployer.d.ts +4 -3
  45. package/dest/deployment/contract_deployer.d.ts.map +1 -0
  46. package/dest/{contract_deployer → deployment}/contract_deployer.js +5 -4
  47. package/dest/deployment/deploy_instance.d.ts +13 -0
  48. package/dest/deployment/deploy_instance.d.ts.map +1 -0
  49. package/dest/deployment/deploy_instance.js +13 -0
  50. package/dest/deployment/index.d.ts.map +1 -0
  51. package/dest/{contract_deployer → deployment}/index.js +1 -1
  52. package/dest/deployment/protocol_contracts.d.ts +7 -0
  53. package/dest/deployment/protocol_contracts.d.ts.map +1 -0
  54. package/dest/deployment/protocol_contracts.js +14 -0
  55. package/dest/deployment/register_class.d.ts +6 -0
  56. package/dest/deployment/register_class.d.ts.map +1 -0
  57. package/dest/deployment/register_class.js +12 -0
  58. package/dest/fee/fee_payment_method.d.ts +24 -0
  59. package/dest/fee/fee_payment_method.d.ts.map +1 -0
  60. package/dest/fee/fee_payment_method.js +2 -0
  61. package/dest/fee/native_fee_payment_method.d.ts +32 -0
  62. package/dest/fee/native_fee_payment_method.d.ts.map +1 -0
  63. package/dest/fee/native_fee_payment_method.js +54 -0
  64. package/dest/fee/private_fee_payment_method.d.ts +52 -0
  65. package/dest/fee/private_fee_payment_method.d.ts.map +1 -0
  66. package/dest/fee/private_fee_payment_method.js +62 -0
  67. package/dest/fee/public_fee_payment_method.d.ts +52 -0
  68. package/dest/fee/public_fee_payment_method.d.ts.map +1 -0
  69. package/dest/fee/public_fee_payment_method.js +62 -0
  70. package/dest/index.d.ts +6 -4
  71. package/dest/index.d.ts.map +1 -1
  72. package/dest/index.js +7 -5
  73. package/dest/rpc_clients/pxe_client.d.ts.map +1 -1
  74. package/dest/rpc_clients/pxe_client.js +15 -15
  75. package/dest/utils/authwit.d.ts +30 -4
  76. package/dest/utils/authwit.d.ts.map +1 -1
  77. package/dest/utils/authwit.js +35 -5
  78. package/dest/utils/cheat_codes.js +3 -3
  79. package/dest/utils/index.d.ts +0 -1
  80. package/dest/utils/index.d.ts.map +1 -1
  81. package/dest/utils/index.js +1 -2
  82. package/dest/utils/l2_contracts.js +2 -2
  83. package/dest/wallet/account_wallet.d.ts +10 -3
  84. package/dest/wallet/account_wallet.d.ts.map +1 -1
  85. package/dest/wallet/account_wallet.js +34 -10
  86. package/dest/wallet/base_wallet.d.ts +7 -4
  87. package/dest/wallet/base_wallet.d.ts.map +1 -1
  88. package/dest/wallet/base_wallet.js +9 -3
  89. package/dest/wallet/signerless_wallet.js +2 -2
  90. package/package.json +9 -6
  91. package/src/account/contract.ts +33 -0
  92. package/src/account/index.ts +16 -0
  93. package/src/account/interface.ts +47 -0
  94. package/src/account/wallet.ts +8 -0
  95. package/src/account_manager/deploy_account_sent_tx.ts +42 -0
  96. package/src/account_manager/index.ts +188 -0
  97. package/src/api/README.md +7 -0
  98. package/src/api/abi.ts +3 -0
  99. package/src/api/account.ts +13 -0
  100. package/src/api/aztec_address.ts +1 -0
  101. package/src/api/deployment.ts +3 -0
  102. package/src/api/eth_address.ts +1 -0
  103. package/src/api/ethereum.ts +6 -0
  104. package/src/api/fee.ts +4 -0
  105. package/src/api/fields.ts +1 -0
  106. package/src/api/init.ts +10 -0
  107. package/src/api/interfaces/pxe.ts +1 -0
  108. package/src/api/log_id.ts +1 -0
  109. package/src/api/tx_hash.ts +1 -0
  110. package/src/api/wallet.ts +1 -0
  111. package/src/contract/base_contract_interaction.ts +67 -0
  112. package/src/contract/batch_call.ts +24 -0
  113. package/src/contract/checker.ts +117 -0
  114. package/src/contract/contract.ts +64 -0
  115. package/src/contract/contract_base.ts +72 -0
  116. package/src/contract/contract_function_interaction.ts +80 -0
  117. package/src/contract/deploy_method.ts +192 -0
  118. package/src/contract/deploy_sent_tx.ts +66 -0
  119. package/src/contract/index.ts +44 -0
  120. package/src/contract/sent_tx.ts +135 -0
  121. package/src/contract/unsafe_contract.ts +19 -0
  122. package/src/deployment/broadcast_function.ts +118 -0
  123. package/src/deployment/contract_deployer.ts +42 -0
  124. package/src/deployment/deploy_instance.ts +28 -0
  125. package/src/deployment/index.ts +1 -0
  126. package/src/deployment/protocol_contracts.ts +17 -0
  127. package/src/deployment/register_class.ts +19 -0
  128. package/src/fee/fee_payment_method.ts +25 -0
  129. package/src/fee/native_fee_payment_method.ts +60 -0
  130. package/src/fee/private_fee_payment_method.ts +79 -0
  131. package/src/fee/public_fee_payment_method.ts +79 -0
  132. package/src/index.ts +150 -0
  133. package/src/rpc_clients/index.ts +1 -0
  134. package/src/rpc_clients/pxe_client.ts +63 -0
  135. package/src/utils/abi_types.ts +16 -0
  136. package/src/utils/account.ts +32 -0
  137. package/src/utils/authwit.ts +62 -0
  138. package/src/utils/cheat_codes.ts +297 -0
  139. package/src/utils/index.ts +8 -0
  140. package/src/utils/l1_contracts.ts +21 -0
  141. package/src/utils/l2_contracts.ts +12 -0
  142. package/src/utils/pub_key.ts +12 -0
  143. package/src/utils/pxe.ts +16 -0
  144. package/src/wallet/account_wallet.ts +94 -0
  145. package/src/wallet/account_wallet_with_private_key.ts +28 -0
  146. package/src/wallet/base_wallet.ts +129 -0
  147. package/src/wallet/create_recipient.ts +13 -0
  148. package/src/wallet/index.ts +31 -0
  149. package/src/wallet/signerless_wallet.ts +37 -0
  150. package/dest/contract_deployer/contract_deployer.d.ts.map +0 -1
  151. package/dest/contract_deployer/index.d.ts.map +0 -1
  152. package/dest/utils/secrets.d.ts +0 -8
  153. package/dest/utils/secrets.d.ts.map +0 -1
  154. package/dest/utils/secrets.js +0 -10
  155. /package/dest/{contract_deployer → deployment}/index.d.ts +0 -0
@@ -0,0 +1,188 @@
1
+ import { CompleteAddress, GrumpkinPrivateKey, PXE } from '@aztec/circuit-types';
2
+ import { EthAddress, PublicKey, getContractInstanceFromDeployParams } from '@aztec/circuits.js';
3
+ import { Fr } from '@aztec/foundation/fields';
4
+ import { ContractInstanceWithAddress } from '@aztec/types/contracts';
5
+
6
+ import { AccountContract } from '../account/contract.js';
7
+ import { Salt } from '../account/index.js';
8
+ import { AccountInterface } from '../account/interface.js';
9
+ import { DeployMethod } from '../contract/deploy_method.js';
10
+ import { DefaultWaitOpts, WaitOpts } from '../contract/sent_tx.js';
11
+ import { ContractDeployer } from '../deployment/contract_deployer.js';
12
+ import { waitForAccountSynch } from '../utils/account.js';
13
+ import { generatePublicKey } from '../utils/index.js';
14
+ import { AccountWalletWithPrivateKey, SignerlessWallet } from '../wallet/index.js';
15
+ import { DeployAccountSentTx } from './deploy_account_sent_tx.js';
16
+
17
+ /**
18
+ * Manages a user account. Provides methods for calculating the account's address, deploying the account contract,
19
+ * and creating and registering the user wallet in the PXE Service.
20
+ */
21
+ export class AccountManager {
22
+ /** Deployment salt for the account contract. */
23
+ public readonly salt: Fr;
24
+
25
+ // TODO(@spalladino): Does it make sense to have both completeAddress and instance?
26
+ private completeAddress?: CompleteAddress;
27
+ private instance?: ContractInstanceWithAddress;
28
+ private encryptionPublicKey?: PublicKey;
29
+ // TODO(@spalladino): Update to the new deploy method and kill the legacy one.
30
+ private deployMethod?: DeployMethod;
31
+
32
+ constructor(
33
+ private pxe: PXE,
34
+ private encryptionPrivateKey: GrumpkinPrivateKey,
35
+ private accountContract: AccountContract,
36
+ salt?: Salt,
37
+ ) {
38
+ this.salt = salt ? new Fr(salt) : Fr.random();
39
+ }
40
+
41
+ protected getEncryptionPublicKey() {
42
+ if (!this.encryptionPublicKey) {
43
+ this.encryptionPublicKey = generatePublicKey(this.encryptionPrivateKey);
44
+ }
45
+ return this.encryptionPublicKey;
46
+ }
47
+
48
+ /**
49
+ * Returns the entrypoint for this account as defined by its account contract.
50
+ * @returns An entrypoint.
51
+ */
52
+ public async getAccount(): Promise<AccountInterface> {
53
+ const nodeInfo = await this.pxe.getNodeInfo();
54
+ const completeAddress = this.getCompleteAddress();
55
+ return this.accountContract.getInterface(completeAddress, nodeInfo);
56
+ }
57
+
58
+ /**
59
+ * Gets the calculated complete address associated with this account.
60
+ * Does not require the account to be deployed or registered.
61
+ * @returns The address, partial address, and encryption public key.
62
+ */
63
+ public getCompleteAddress(): CompleteAddress {
64
+ if (!this.completeAddress) {
65
+ const encryptionPublicKey = generatePublicKey(this.encryptionPrivateKey);
66
+ const instance = this.getInstance();
67
+ this.completeAddress = CompleteAddress.fromPublicKeyAndInstance(encryptionPublicKey, instance);
68
+ }
69
+ return this.completeAddress;
70
+ }
71
+
72
+ /**
73
+ * Returns the contract instance definition associated with this account.
74
+ * Does not require the account to be deployed or registered.
75
+ * @returns ContractInstance instance.
76
+ */
77
+ public getInstance(): ContractInstanceWithAddress {
78
+ if (!this.instance) {
79
+ const encryptionPublicKey = generatePublicKey(this.encryptionPrivateKey);
80
+ const portalAddress = EthAddress.ZERO;
81
+ this.instance = getContractInstanceFromDeployParams(
82
+ this.accountContract.getContractArtifact(),
83
+ this.accountContract.getDeploymentArgs(),
84
+ this.salt,
85
+ encryptionPublicKey,
86
+ portalAddress,
87
+ );
88
+ }
89
+ return this.instance;
90
+ }
91
+
92
+ /**
93
+ * Returns a Wallet instance associated with this account. Use it to create Contract
94
+ * instances to be interacted with from this account.
95
+ * @returns A Wallet instance.
96
+ */
97
+ public async getWallet(): Promise<AccountWalletWithPrivateKey> {
98
+ const entrypoint = await this.getAccount();
99
+ return new AccountWalletWithPrivateKey(this.pxe, entrypoint, this.encryptionPrivateKey, this.salt);
100
+ }
101
+
102
+ /**
103
+ * Registers this account in the PXE Service and returns the associated wallet. Registering
104
+ * the account on the PXE Service is required for managing private state associated with it.
105
+ * Use the returned wallet to create Contract instances to be interacted with from this account.
106
+ * @param opts - Options to wait for the account to be synched.
107
+ * @returns A Wallet instance.
108
+ */
109
+ public async register(opts: WaitOpts = DefaultWaitOpts): Promise<AccountWalletWithPrivateKey> {
110
+ await this.#register();
111
+ await this.pxe.addContracts([
112
+ {
113
+ artifact: this.accountContract.getContractArtifact(),
114
+ instance: this.getInstance(),
115
+ },
116
+ ]);
117
+
118
+ await waitForAccountSynch(this.pxe, this.getCompleteAddress(), opts);
119
+ return this.getWallet();
120
+ }
121
+
122
+ /**
123
+ * Returns the pre-populated deployment method to deploy the account contract that backs this account.
124
+ * Typically you will not need this method and can call `deploy` directly. Use this for having finer
125
+ * grained control on when to create, simulate, and send the deployment tx.
126
+ * @returns A DeployMethod instance that deploys this account contract.
127
+ */
128
+ public async getDeployMethod() {
129
+ if (!this.deployMethod) {
130
+ if (!this.salt) {
131
+ throw new Error(`Cannot deploy account contract without known salt.`);
132
+ }
133
+ await this.#register();
134
+ const encryptionPublicKey = this.getEncryptionPublicKey();
135
+ // We use a signerless wallet so we hit the account contract directly and it deploys itself.
136
+ // If we used getWallet, the deployment would get routed via the account contract entrypoint
137
+ // instead of directly hitting the initializer.
138
+ const deployWallet = new SignerlessWallet(this.pxe);
139
+ const deployer = new ContractDeployer(
140
+ this.accountContract.getContractArtifact(),
141
+ deployWallet,
142
+ encryptionPublicKey,
143
+ );
144
+ const args = this.accountContract.getDeploymentArgs();
145
+ this.deployMethod = deployer.deploy(...args);
146
+ }
147
+ return this.deployMethod;
148
+ }
149
+
150
+ /**
151
+ * Deploys the account contract that backs this account.
152
+ * Does not register the associated class nor publicly deploy the instance.
153
+ * Uses the salt provided in the constructor or a randomly generated one.
154
+ * Note that if the Account is constructed with an explicit complete address
155
+ * it is assumed that the account contract has already been deployed and this method will throw.
156
+ * Registers the account in the PXE Service before deploying the contract.
157
+ * @returns A SentTx object that can be waited to get the associated Wallet.
158
+ */
159
+ public async deploy(): Promise<DeployAccountSentTx> {
160
+ const deployMethod = await this.getDeployMethod();
161
+ const wallet = await this.getWallet();
162
+ const sentTx = deployMethod.send({
163
+ contractAddressSalt: this.salt,
164
+ skipClassRegistration: true,
165
+ skipPublicDeployment: true,
166
+ });
167
+ return new DeployAccountSentTx(wallet, sentTx.getTxHash());
168
+ }
169
+
170
+ /**
171
+ * Deploys the account contract that backs this account and awaits the tx to be mined.
172
+ * Uses the salt provided in the constructor or a randomly generated one.
173
+ * Note that if the Account is constructed with an explicit complete address
174
+ * it is assumed that the account contract has already been deployed and this method will throw.
175
+ * Registers the account in the PXE Service before deploying the contract.
176
+ * @param opts - Options to wait for the tx to be mined.
177
+ * @returns A Wallet instance.
178
+ */
179
+ public async waitDeploy(opts: WaitOpts = DefaultWaitOpts): Promise<AccountWalletWithPrivateKey> {
180
+ await this.deploy().then(tx => tx.wait(opts));
181
+ return this.getWallet();
182
+ }
183
+
184
+ async #register(): Promise<void> {
185
+ const completeAddress = this.getCompleteAddress();
186
+ await this.pxe.registerAccount(this.encryptionPrivateKey, completeAddress.partialAddress);
187
+ }
188
+ }
@@ -0,0 +1,7 @@
1
+ # API
2
+
3
+ This provides a more modular api for importing parts of the library as needed.
4
+ The root `index.js` just exposes everything, which can have consequences for startup times and optimizations.
5
+ Here we can gradually build up a much more granular api to allow importing precisely what's needed.
6
+ This should adopt the opposite philosophy to "export all my child exports".
7
+ Every file should (usually) export one thing, and the file/directory structure should be reflected in package.json exports.
package/src/api/abi.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { ContractArtifact, FunctionArtifact, FunctionSelector } from '@aztec/foundation/abi';
2
+ export { loadContractArtifact } from '@aztec/types/abi';
3
+ export { NoirCompiledContract } from '@aztec/types/noir';
@@ -0,0 +1,13 @@
1
+ export {
2
+ AccountContract,
3
+ AccountInterface,
4
+ AuthWitnessProvider,
5
+ EntrypointInterface,
6
+ Salt,
7
+ Wallet,
8
+ FeeOptions,
9
+ } from '../account/index.js';
10
+
11
+ export { AccountManager } from '../account_manager/index.js';
12
+
13
+ export { CompleteAddress } from '@aztec/circuit-types';
@@ -0,0 +1 @@
1
+ export { AztecAddress } from '@aztec/foundation/aztec-address';
@@ -0,0 +1,3 @@
1
+ export { registerContractClass } from '../deployment/register_class.js';
2
+ export { broadcastPrivateFunction, broadcastUnconstrainedFunction } from '../deployment/broadcast_function.js';
3
+ export { deployInstance } from '../deployment/deploy_instance.js';
@@ -0,0 +1 @@
1
+ export { EthAddress } from '@aztec/foundation/eth-address';
@@ -0,0 +1,6 @@
1
+ export {
2
+ deployL1Contract,
3
+ deployL1Contracts,
4
+ DeployL1Contracts,
5
+ L1ContractArtifactsForDeployment,
6
+ } from '@aztec/ethereum';
package/src/api/fee.ts ADDED
@@ -0,0 +1,4 @@
1
+ export type { FeePaymentMethod } from '../fee/fee_payment_method.js';
2
+ export { NativeFeePaymentMethod } from '../fee/native_fee_payment_method.js';
3
+ export { PrivateFeePaymentMethod } from '../fee/private_fee_payment_method.js';
4
+ export { PublicFeePaymentMethod } from '../fee/public_fee_payment_method.js';
@@ -0,0 +1 @@
1
+ export { Point, Fr, Fq, GrumpkinScalar } from '@aztec/foundation/fields';
@@ -0,0 +1,10 @@
1
+ import { init } from '@aztec/foundation/crypto';
2
+
3
+ /**
4
+ * This should only be needed to be called in CJS environments that don't have top level await.
5
+ * Initializes any asynchronous subsystems required to use the library.
6
+ * At time of writing, this is just our foundation crypto lib.
7
+ */
8
+ export async function initAztecJs() {
9
+ await init();
10
+ }
@@ -0,0 +1 @@
1
+ export { PXE } from '@aztec/circuit-types/interfaces';
@@ -0,0 +1 @@
1
+ export { LogId } from '@aztec/circuit-types/log_id';
@@ -0,0 +1 @@
1
+ export { TxHash } from '@aztec/circuit-types/tx_hash';
@@ -0,0 +1 @@
1
+ export { AccountWallet, AccountWalletWithPrivateKey, SignerlessWallet, Wallet, getWallet } from '../wallet/index.js';
@@ -0,0 +1,67 @@
1
+ import { PXE, Tx, TxExecutionRequest } from '@aztec/circuit-types';
2
+
3
+ import { FeeOptions } from '../account/interface.js';
4
+ import { SentTx } from './sent_tx.js';
5
+
6
+ /**
7
+ * Represents options for calling a (constrained) function in a contract.
8
+ * Allows the user to specify the sender address and nonce for a transaction.
9
+ */
10
+ export type SendMethodOptions = {
11
+ /**
12
+ * Wether to skip the simulation of the public part of the transaction.
13
+ */
14
+ skipPublicSimulation?: boolean;
15
+
16
+ /**
17
+ * The fee options for the transaction.
18
+ */
19
+ fee?: FeeOptions;
20
+ };
21
+
22
+ /**
23
+ * Base class for an interaction with a contract, be it a deployment, a function call, or a batch.
24
+ * Implements the sequence create/simulate/send.
25
+ */
26
+ export abstract class BaseContractInteraction {
27
+ protected tx?: Tx;
28
+ protected txRequest?: TxExecutionRequest;
29
+
30
+ constructor(protected pxe: PXE) {}
31
+
32
+ /**
33
+ * Create a transaction execution request ready to be simulated.
34
+ * @param options - An optional object containing additional configuration for the transaction.
35
+ * @returns A transaction execution request.
36
+ */
37
+ public abstract create(options?: SendMethodOptions): Promise<TxExecutionRequest>;
38
+
39
+ /**
40
+ * Simulates a transaction execution request and returns a tx object ready to be sent.
41
+ * @param options - optional arguments to be used in the creation of the transaction
42
+ * @returns The resulting transaction
43
+ */
44
+ public async simulate(options: SendMethodOptions = {}): Promise<Tx> {
45
+ const txRequest = this.txRequest ?? (await this.create(options));
46
+ this.tx = await this.pxe.simulateTx(txRequest, !options.skipPublicSimulation);
47
+ return this.tx;
48
+ }
49
+
50
+ /**
51
+ * Sends a transaction to the contract function with the specified options.
52
+ * This function throws an error if called on an unconstrained function.
53
+ * It creates and signs the transaction if necessary, and returns a SentTx instance,
54
+ * which can be used to track the transaction status, receipt, and events.
55
+ * @param options - An optional object containing 'from' property representing
56
+ * the AztecAddress of the sender. If not provided, the default address is used.
57
+ * @returns A SentTx instance for tracking the transaction status and information.
58
+ */
59
+ public send(options: SendMethodOptions = {}) {
60
+ const promise = (async () => {
61
+ const tx = this.tx ?? (await this.simulate(options));
62
+ return this.pxe.sendTx(tx);
63
+ })();
64
+
65
+ return new SentTx(this.pxe, promise);
66
+ }
67
+ }
@@ -0,0 +1,24 @@
1
+ import { FunctionCall, TxExecutionRequest } from '@aztec/circuit-types';
2
+
3
+ import { Wallet } from '../account/index.js';
4
+ import { BaseContractInteraction, SendMethodOptions } from './base_contract_interaction.js';
5
+
6
+ /** A batch of function calls to be sent as a single transaction through a wallet. */
7
+ export class BatchCall extends BaseContractInteraction {
8
+ constructor(protected wallet: Wallet, protected calls: FunctionCall[]) {
9
+ super(wallet);
10
+ }
11
+
12
+ /**
13
+ * Create a transaction execution request that represents this batch, encoded and authenticated by the
14
+ * user's wallet, ready to be simulated.
15
+ * @param opts - An optional object containing additional configuration for the transaction.
16
+ * @returns A Promise that resolves to a transaction instance.
17
+ */
18
+ public async create(opts?: SendMethodOptions): Promise<TxExecutionRequest> {
19
+ if (!this.txRequest) {
20
+ this.txRequest = await this.wallet.createTxExecutionRequest(this.calls, opts?.fee);
21
+ }
22
+ return this.txRequest;
23
+ }
24
+ }
@@ -0,0 +1,117 @@
1
+ import { ABIType, BasicType, ContractArtifact, StructType } from '@aztec/foundation/abi';
2
+
3
+ /**
4
+ * Represents a type derived from input type T with the 'kind' property removed.
5
+ * Useful when checking attributes of a specific kind and validating their types.
6
+ */
7
+ type TypeWithoutKind<T> = Omit<{ [key in keyof T]: any }, 'kind'>;
8
+
9
+ /**
10
+ * Validates the given ContractArtifact object by checking its functions and their parameters.
11
+ * Ensures that the ABI has at least one function, a constructor, valid bytecode, and correct parameter types.
12
+ * Throws an error if any inconsistency is detected during the validation process.
13
+ *
14
+ * @param artifact - The ContractArtifact object to be validated.
15
+ * @returns A boolean value indicating whether the artifact is valid or not.
16
+ */
17
+ export function abiChecker(artifact: ContractArtifact) {
18
+ if (!artifact.functions || artifact.functions.length === 0) {
19
+ throw new Error('artifact has no functions');
20
+ }
21
+
22
+ artifact.functions.forEach(func => {
23
+ if (!('name' in func && typeof func.name === 'string' && func.name.length > 0)) {
24
+ throw new Error('ABI function has no name');
25
+ }
26
+
27
+ // TODO: implement a better check for bytecode (right now only checks if it's > 0)
28
+ if (!('bytecode' in func && typeof func.bytecode === 'string' && func.bytecode.length > 0)) {
29
+ throw new Error('ABI function parameter has incorrect bytecode');
30
+ }
31
+
32
+ func.parameters.forEach(param => {
33
+ if (!param.type) {
34
+ throw new Error('ABI function parameter has no type');
35
+ }
36
+
37
+ abiParameterTypeChecker(param.type);
38
+ });
39
+ });
40
+
41
+ // TODO: implement a better check for constructor (right now only checks if it has it or not)
42
+ if (!artifact.functions.find(func => func.name === 'constructor')) {
43
+ throw new Error('ABI has no constructor');
44
+ }
45
+
46
+ return true;
47
+ }
48
+
49
+ /**
50
+ * Validates the ABI function parameter's type by checking its kind and attributes.
51
+ * Throws an error if the type has an unrecognized kind or incorrectly formed attributes.
52
+ * Additionally, checks nested types for array and struct kinds.
53
+ *
54
+ * @param type - The ABIType object representing the type of the ABI function parameter.
55
+ * @returns A boolean value indicating whether the type is valid or not.
56
+ */
57
+ function abiParameterTypeChecker(type: ABIType): boolean {
58
+ switch (type.kind) {
59
+ case 'field':
60
+ case 'boolean':
61
+ return checkAttributes(type, {});
62
+ case 'integer':
63
+ return checkAttributes(type, { sign: 'string', width: 'number' });
64
+ case 'string':
65
+ return checkAttributes(type, { length: 'number' });
66
+ case 'array':
67
+ return checkAttributes(type, { length: 'number', type: 'object' }) && abiParameterTypeChecker(type.type);
68
+ case 'struct':
69
+ return checkAttributes(type, { fields: 'object', path: 'string' }) && checkStruct(type);
70
+ default:
71
+ throw new Error('ABI function parameter has an unrecognized type');
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Check if the structure of the ABIType 'struct' is valid by ensuring field names are strings
77
+ * and their type attribute passes the abiParameterTypeChecker. Returns true on successful validation,
78
+ * otherwise throws an error providing insight into the incorrect formation in the struct.
79
+ *
80
+ * @param type - The StructType object containing an array of fields to validate.
81
+ * @returns A boolean value indicating successful validation of the struct's fields.
82
+ */
83
+ function checkStruct(type: StructType) {
84
+ return type.fields.reduce((acc, field) => {
85
+ if (!('name' in field && typeof field.name === 'string')) {
86
+ throw new Error('ABI function parameter has an incorrectly formed struct');
87
+ }
88
+ return acc && abiParameterTypeChecker(field.type);
89
+ }, true);
90
+ }
91
+
92
+ /**
93
+ * Check if a provided ABI type has the correct attributes and their associated types.
94
+ * This function compares the given 'type' object's keys with the expected attribute types
95
+ * specified in 'incompleteAttributes', as well as the required 'kind' property.
96
+ * Throws an error if there are any unrecognized attributes or incorrect attribute types.
97
+ *
98
+ * @param type - The ABI type object to be checked for correct attributes.
99
+ * @param incompleteAttributes - An object representing the expected attribute types without the 'kind' property.
100
+ * @returns Returns true if the provided ABI type has the correct attributes and their associated types, otherwise throws an error.
101
+ */
102
+ function checkAttributes<T extends BasicType<string>>(type: T, incompleteAttributes: TypeWithoutKind<T>) {
103
+ const typeKeys = Object.keys(type);
104
+ const attributes = { ...incompleteAttributes, kind: 'string' };
105
+
106
+ if (typeKeys.length !== Object.keys(attributes).length) {
107
+ throw new Error(`Unrecognized attribute on type ${type.kind}`);
108
+ }
109
+
110
+ typeKeys.forEach(element => {
111
+ if (!(element in type && typeof (type as any)[element] === (attributes as any)[element])) {
112
+ throw new Error(`ABI function parameter has an incorrectly formed ${type.kind}`);
113
+ }
114
+ });
115
+
116
+ return true;
117
+ }
@@ -0,0 +1,64 @@
1
+ import { PublicKey } from '@aztec/circuit-types';
2
+ import { ContractArtifact } from '@aztec/foundation/abi';
3
+ import { AztecAddress } from '@aztec/foundation/aztec-address';
4
+ import { Point } from '@aztec/foundation/fields';
5
+
6
+ import { Wallet } from '../account/index.js';
7
+ import { ContractBase } from './contract_base.js';
8
+ import { DeployMethod } from './deploy_method.js';
9
+
10
+ /**
11
+ * The Contract class represents a contract and provides utility methods for interacting with it.
12
+ * It enables the creation of ContractFunctionInteraction instances for each function in the contract's ABI,
13
+ * allowing users to call or send transactions to these functions. Additionally, the Contract class can be used
14
+ * to attach the contract instance to a deployed contract on-chain through the PXE, which facilitates
15
+ * interaction with Aztec's privacy protocol.
16
+ */
17
+ export class Contract extends ContractBase {
18
+ /**
19
+ * Creates a contract instance.
20
+ * @param address - The deployed contract's address.
21
+ * @param artifact - Build artifact of the contract.
22
+ * @param wallet - The wallet to use when interacting with the contract.
23
+ * @param portalContract - The portal contract address on L1, if any.
24
+ * @returns A promise that resolves to a new Contract instance.
25
+ */
26
+ public static async at(address: AztecAddress, artifact: ContractArtifact, wallet: Wallet): Promise<Contract> {
27
+ const instance = await wallet.getContractInstance(address);
28
+ if (instance === undefined) {
29
+ throw new Error(`Contract instance at ${address.toString()} has not been registered in the wallet's PXE`);
30
+ }
31
+ return new Contract(instance, artifact, wallet);
32
+ }
33
+
34
+ /**
35
+ * Creates a tx to deploy a new instance of a contract.
36
+ * @param wallet - The wallet for executing the deployment.
37
+ * @param artifact - Build artifact of the contract to deploy
38
+ * @param args - Arguments for the constructor.
39
+ * @param constructorName - The name of the constructor function to call.
40
+ */
41
+ public static deploy(wallet: Wallet, artifact: ContractArtifact, args: any[], constructorName?: string) {
42
+ const postDeployCtor = (address: AztecAddress, wallet: Wallet) => Contract.at(address, artifact, wallet);
43
+ return new DeployMethod(Point.ZERO, wallet, artifact, postDeployCtor, args, constructorName);
44
+ }
45
+
46
+ /**
47
+ * Creates a tx to deploy a new instance of a contract using the specified public key to derive the address.
48
+ * @param publicKey - Public key for deriving the address.
49
+ * @param wallet - The wallet for executing the deployment.
50
+ * @param artifact - Build artifact of the contract.
51
+ * @param args - Arguments for the constructor.
52
+ * @param constructorName - The name of the constructor function to call.
53
+ */
54
+ public static deployWithPublicKey(
55
+ publicKey: PublicKey,
56
+ wallet: Wallet,
57
+ artifact: ContractArtifact,
58
+ args: any[],
59
+ constructorName?: string,
60
+ ) {
61
+ const postDeployCtor = (address: AztecAddress, wallet: Wallet) => Contract.at(address, artifact, wallet);
62
+ return new DeployMethod(publicKey, wallet, artifact, postDeployCtor, args, constructorName);
63
+ }
64
+ }
@@ -0,0 +1,72 @@
1
+ import { DeployedContract } from '@aztec/circuit-types';
2
+ import { computePartialAddress } from '@aztec/circuits.js';
3
+ import { ContractArtifact, FunctionArtifact, FunctionSelector } from '@aztec/foundation/abi';
4
+ import { ContractInstanceWithAddress } from '@aztec/types/contracts';
5
+
6
+ import { Wallet } from '../account/index.js';
7
+ import { ContractFunctionInteraction } from './contract_function_interaction.js';
8
+
9
+ /**
10
+ * Type representing a contract method that returns a ContractFunctionInteraction instance
11
+ * and has a readonly 'selector' property of type Buffer. Takes any number of arguments.
12
+ */
13
+ export type ContractMethod = ((...args: any[]) => ContractFunctionInteraction) & {
14
+ /**
15
+ * The unique identifier for a contract function in bytecode.
16
+ */
17
+ readonly selector: FunctionSelector;
18
+ };
19
+
20
+ /**
21
+ * Abstract implementation of a contract extended by the Contract class and generated contract types.
22
+ */
23
+ export class ContractBase implements DeployedContract {
24
+ /**
25
+ * An object containing contract methods mapped to their respective names.
26
+ */
27
+ public methods: { [name: string]: ContractMethod } = {};
28
+
29
+ protected constructor(
30
+ /** The deployed contract instance definition. */
31
+ public readonly instance: ContractInstanceWithAddress,
32
+ /** The Application Binary Interface for the contract. */
33
+ public readonly artifact: ContractArtifact,
34
+ /** The wallet used for interacting with this contract. */
35
+ protected wallet: Wallet,
36
+ ) {
37
+ artifact.functions.forEach((f: FunctionArtifact) => {
38
+ const interactionFunction = (...args: any[]) => {
39
+ return new ContractFunctionInteraction(this.wallet, this.instance.address, f, args);
40
+ };
41
+
42
+ this.methods[f.name] = Object.assign(interactionFunction, {
43
+ /**
44
+ * A getter for users to fetch the function selector.
45
+ * @returns Selector of the function.
46
+ */
47
+ get selector() {
48
+ return FunctionSelector.fromNameAndParameters(f.name, f.parameters);
49
+ },
50
+ });
51
+ });
52
+ }
53
+
54
+ /** Address of the contract. */
55
+ public get address() {
56
+ return this.instance.address;
57
+ }
58
+
59
+ /** Partial address of the contract. */
60
+ public get partialAddress() {
61
+ return computePartialAddress(this.instance);
62
+ }
63
+
64
+ /**
65
+ * Creates a new instance of the contract wrapper attached to a different wallet.
66
+ * @param wallet - Wallet to use for sending txs.
67
+ * @returns A new contract instance.
68
+ */
69
+ public withWallet(wallet: Wallet): this {
70
+ return new ContractBase(this.instance, this.artifact, wallet) as this;
71
+ }
72
+ }