@aztec-labs/aztec.js 6.0.0-nightly.20260829

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 (275) hide show
  1. package/README.md +44 -0
  2. package/dest/account/account.d.ts +44 -0
  3. package/dest/account/account.d.ts.map +1 -0
  4. package/dest/account/account.js +31 -0
  5. package/dest/account/account_contract.d.ts +49 -0
  6. package/dest/account/account_contract.d.ts.map +1 -0
  7. package/dest/account/account_contract.js +20 -0
  8. package/dest/account/index.d.ts +11 -0
  9. package/dest/account/index.d.ts.map +1 -0
  10. package/dest/account/index.js +6 -0
  11. package/dest/api/abi.d.ts +4 -0
  12. package/dest/api/abi.d.ts.map +1 -0
  13. package/dest/api/abi.js +1 -0
  14. package/dest/api/account.d.ts +5 -0
  15. package/dest/api/account.d.ts.map +1 -0
  16. package/dest/api/account.js +3 -0
  17. package/dest/api/addresses.d.ts +4 -0
  18. package/dest/api/addresses.d.ts.map +1 -0
  19. package/dest/api/addresses.js +3 -0
  20. package/dest/api/authorization.d.ts +5 -0
  21. package/dest/api/authorization.d.ts.map +1 -0
  22. package/dest/api/authorization.js +4 -0
  23. package/dest/api/block.d.ts +3 -0
  24. package/dest/api/block.d.ts.map +1 -0
  25. package/dest/api/block.js +2 -0
  26. package/dest/api/contract.d.ts +48 -0
  27. package/dest/api/contract.d.ts.map +1 -0
  28. package/dest/api/contract.js +46 -0
  29. package/dest/api/crypto.d.ts +2 -0
  30. package/dest/api/crypto.d.ts.map +1 -0
  31. package/dest/api/crypto.js +1 -0
  32. package/dest/api/deployment.d.ts +4 -0
  33. package/dest/api/deployment.d.ts.map +1 -0
  34. package/dest/api/deployment.js +3 -0
  35. package/dest/api/eth_address.d.ts +2 -0
  36. package/dest/api/eth_address.d.ts.map +1 -0
  37. package/dest/api/eth_address.js +1 -0
  38. package/dest/api/ethereum.d.ts +2 -0
  39. package/dest/api/ethereum.d.ts.map +1 -0
  40. package/dest/api/ethereum.js +1 -0
  41. package/dest/api/event_cursor.d.ts +44 -0
  42. package/dest/api/event_cursor.d.ts.map +1 -0
  43. package/dest/api/event_cursor.js +42 -0
  44. package/dest/api/events.d.ts +36 -0
  45. package/dest/api/events.d.ts.map +1 -0
  46. package/dest/api/events.js +59 -0
  47. package/dest/api/fee.d.ts +6 -0
  48. package/dest/api/fee.d.ts.map +1 -0
  49. package/dest/api/fee.js +4 -0
  50. package/dest/api/fee_testing.d.ts +2 -0
  51. package/dest/api/fee_testing.d.ts.map +1 -0
  52. package/dest/api/fee_testing.js +1 -0
  53. package/dest/api/fields.d.ts +4 -0
  54. package/dest/api/fields.d.ts.map +1 -0
  55. package/dest/api/fields.js +3 -0
  56. package/dest/api/keys.d.ts +4 -0
  57. package/dest/api/keys.d.ts.map +1 -0
  58. package/dest/api/keys.js +3 -0
  59. package/dest/api/log.d.ts +3 -0
  60. package/dest/api/log.d.ts.map +1 -0
  61. package/dest/api/log.js +2 -0
  62. package/dest/api/messaging.d.ts +3 -0
  63. package/dest/api/messaging.d.ts.map +1 -0
  64. package/dest/api/messaging.js +2 -0
  65. package/dest/api/node.d.ts +25 -0
  66. package/dest/api/node.d.ts.map +1 -0
  67. package/dest/api/node.js +22 -0
  68. package/dest/api/note.d.ts +2 -0
  69. package/dest/api/note.d.ts.map +1 -0
  70. package/dest/api/note.js +1 -0
  71. package/dest/api/protocol.d.ts +6 -0
  72. package/dest/api/protocol.d.ts.map +1 -0
  73. package/dest/api/protocol.js +5 -0
  74. package/dest/api/trees.d.ts +3 -0
  75. package/dest/api/trees.d.ts.map +1 -0
  76. package/dest/api/trees.js +2 -0
  77. package/dest/api/tx.d.ts +3 -0
  78. package/dest/api/tx.d.ts.map +1 -0
  79. package/dest/api/tx.js +1 -0
  80. package/dest/api/utils.d.ts +13 -0
  81. package/dest/api/utils.d.ts.map +1 -0
  82. package/dest/api/utils.js +12 -0
  83. package/dest/api/wallet.d.ts +8 -0
  84. package/dest/api/wallet.d.ts.map +1 -0
  85. package/dest/api/wallet.js +7 -0
  86. package/dest/authorization/call_authorization_request.d.ts +46 -0
  87. package/dest/authorization/call_authorization_request.d.ts.map +1 -0
  88. package/dest/authorization/call_authorization_request.js +72 -0
  89. package/dest/contract/base_contract_interaction.d.ts +32 -0
  90. package/dest/contract/base_contract_interaction.d.ts.map +1 -0
  91. package/dest/contract/base_contract_interaction.js +24 -0
  92. package/dest/contract/batch_call.d.ts +27 -0
  93. package/dest/contract/batch_call.d.ts.map +1 -0
  94. package/dest/contract/batch_call.js +152 -0
  95. package/dest/contract/checker.d.ts +11 -0
  96. package/dest/contract/checker.d.ts.map +1 -0
  97. package/dest/contract/checker.js +107 -0
  98. package/dest/contract/contract.d.ts +33 -0
  99. package/dest/contract/contract.d.ts.map +1 -0
  100. package/dest/contract/contract.js +36 -0
  101. package/dest/contract/contract_base.d.ts +51 -0
  102. package/dest/contract/contract_base.d.ts.map +1 -0
  103. package/dest/contract/contract_base.js +38 -0
  104. package/dest/contract/contract_function_interaction.d.ts +67 -0
  105. package/dest/contract/contract_function_interaction.d.ts.map +1 -0
  106. package/dest/contract/contract_function_interaction.js +218 -0
  107. package/dest/contract/deploy_method.d.ts +433 -0
  108. package/dest/contract/deploy_method.d.ts.map +1 -0
  109. package/dest/contract/deploy_method.js +471 -0
  110. package/dest/contract/fastforward_contract_update.d.ts +25 -0
  111. package/dest/contract/fastforward_contract_update.d.ts.map +1 -0
  112. package/dest/contract/fastforward_contract_update.js +57 -0
  113. package/dest/contract/interaction_options.d.ts +213 -0
  114. package/dest/contract/interaction_options.d.ts.map +1 -0
  115. package/dest/contract/interaction_options.js +87 -0
  116. package/dest/contract/protocol_contracts/contract-class-registry.d.ts +18 -0
  117. package/dest/contract/protocol_contracts/contract-class-registry.d.ts.map +1 -0
  118. package/dest/contract/protocol_contracts/contract-class-registry.js +137 -0
  119. package/dest/contract/protocol_contracts/contract-instance-registry.d.ts +25 -0
  120. package/dest/contract/protocol_contracts/contract-instance-registry.d.ts.map +1 -0
  121. package/dest/contract/protocol_contracts/contract-instance-registry.js +366 -0
  122. package/dest/contract/protocol_contracts/fee-juice.d.ts +24 -0
  123. package/dest/contract/protocol_contracts/fee-juice.d.ts.map +1 -0
  124. package/dest/contract/protocol_contracts/fee-juice.js +383 -0
  125. package/dest/contract/wait_for_proven.d.ts +18 -0
  126. package/dest/contract/wait_for_proven.d.ts.map +1 -0
  127. package/dest/contract/wait_for_proven.js +17 -0
  128. package/dest/contract/wait_opts.d.ts +21 -0
  129. package/dest/contract/wait_opts.d.ts.map +1 -0
  130. package/dest/contract/wait_opts.js +5 -0
  131. package/dest/deployment/contract_deployer.d.ts +28 -0
  132. package/dest/deployment/contract_deployer.d.ts.map +1 -0
  133. package/dest/deployment/contract_deployer.js +35 -0
  134. package/dest/deployment/publish_class.d.ts +6 -0
  135. package/dest/deployment/publish_class.d.ts.map +1 -0
  136. package/dest/deployment/publish_class.js +17 -0
  137. package/dest/deployment/publish_instance.d.ts +10 -0
  138. package/dest/deployment/publish_instance.d.ts.map +1 -0
  139. package/dest/deployment/publish_instance.js +11 -0
  140. package/dest/ethereum/portal_manager.d.ts +146 -0
  141. package/dest/ethereum/portal_manager.d.ts.map +1 -0
  142. package/dest/ethereum/portal_manager.js +415 -0
  143. package/dest/fee/fee_juice_payment_method_with_claim.d.ts +23 -0
  144. package/dest/fee/fee_juice_payment_method_with_claim.d.ts.map +1 -0
  145. package/dest/fee/fee_juice_payment_method_with_claim.js +46 -0
  146. package/dest/fee/fee_payment_method.d.ts +26 -0
  147. package/dest/fee/fee_payment_method.d.ts.map +1 -0
  148. package/dest/fee/fee_payment_method.js +3 -0
  149. package/dest/fee/private_fee_payment_method.d.ts +69 -0
  150. package/dest/fee/private_fee_payment_method.d.ts.map +1 -0
  151. package/dest/fee/private_fee_payment_method.js +122 -0
  152. package/dest/fee/public_fee_payment_method.d.ts +59 -0
  153. package/dest/fee/public_fee_payment_method.d.ts.map +1 -0
  154. package/dest/fee/public_fee_payment_method.js +116 -0
  155. package/dest/fee/sponsored_fee_payment.d.ts +17 -0
  156. package/dest/fee/sponsored_fee_payment.d.ts.map +1 -0
  157. package/dest/fee/sponsored_fee_payment.js +33 -0
  158. package/dest/scripts/generate_protocol_contract_types.d.ts +2 -0
  159. package/dest/scripts/generate_protocol_contract_types.d.ts.map +1 -0
  160. package/dest/scripts/generate_protocol_contract_types.js +128 -0
  161. package/dest/test/fixtures.d.ts +13 -0
  162. package/dest/test/fixtures.d.ts.map +1 -0
  163. package/dest/test/fixtures.js +185 -0
  164. package/dest/utils/abi_types.d.ts +32 -0
  165. package/dest/utils/abi_types.d.ts.map +1 -0
  166. package/dest/utils/abi_types.js +1 -0
  167. package/dest/utils/authwit.d.ts +119 -0
  168. package/dest/utils/authwit.d.ts.map +1 -0
  169. package/dest/utils/authwit.js +266 -0
  170. package/dest/utils/cross_chain.d.ts +28 -0
  171. package/dest/utils/cross_chain.d.ts.map +1 -0
  172. package/dest/utils/cross_chain.js +26 -0
  173. package/dest/utils/fee_juice.d.ts +8 -0
  174. package/dest/utils/fee_juice.d.ts.map +1 -0
  175. package/dest/utils/fee_juice.js +10 -0
  176. package/dest/utils/field_compressed_string.d.ts +17 -0
  177. package/dest/utils/field_compressed_string.d.ts.map +1 -0
  178. package/dest/utils/field_compressed_string.js +15 -0
  179. package/dest/utils/node.d.ts +24 -0
  180. package/dest/utils/node.d.ts.map +1 -0
  181. package/dest/utils/node.js +80 -0
  182. package/dest/utils/pub_key.d.ts +9 -0
  183. package/dest/utils/pub_key.d.ts.map +1 -0
  184. package/dest/utils/pub_key.js +8 -0
  185. package/dest/wallet/account_entrypoint_meta_payment_method.d.ts +33 -0
  186. package/dest/wallet/account_entrypoint_meta_payment_method.d.ts.map +1 -0
  187. package/dest/wallet/account_entrypoint_meta_payment_method.js +63 -0
  188. package/dest/wallet/account_manager.d.ts +73 -0
  189. package/dest/wallet/account_manager.d.ts.map +1 -0
  190. package/dest/wallet/account_manager.js +102 -0
  191. package/dest/wallet/capabilities.d.ts +456 -0
  192. package/dest/wallet/capabilities.d.ts.map +1 -0
  193. package/dest/wallet/capabilities.js +3 -0
  194. package/dest/wallet/deploy_account_method.d.ts +97 -0
  195. package/dest/wallet/deploy_account_method.d.ts.map +1 -0
  196. package/dest/wallet/deploy_account_method.js +127 -0
  197. package/dest/wallet/index.d.ts +5 -0
  198. package/dest/wallet/index.d.ts.map +1 -0
  199. package/dest/wallet/index.js +4 -0
  200. package/dest/wallet/tx_simulation_result_with_app_offset.d.ts +40 -0
  201. package/dest/wallet/tx_simulation_result_with_app_offset.d.ts.map +1 -0
  202. package/dest/wallet/tx_simulation_result_with_app_offset.js +65 -0
  203. package/dest/wallet/wallet.d.ts +1451 -0
  204. package/dest/wallet/wallet.d.ts.map +1 -0
  205. package/dest/wallet/wallet.js +430 -0
  206. package/package.json +138 -0
  207. package/src/account/account.ts +72 -0
  208. package/src/account/account_contract.ts +80 -0
  209. package/src/account/index.ts +12 -0
  210. package/src/api/README.md +7 -0
  211. package/src/api/abi.ts +42 -0
  212. package/src/api/account.ts +12 -0
  213. package/src/api/addresses.ts +3 -0
  214. package/src/api/authorization.ts +15 -0
  215. package/src/api/block.ts +2 -0
  216. package/src/api/contract.ts +86 -0
  217. package/src/api/crypto.ts +1 -0
  218. package/src/api/deployment.ts +3 -0
  219. package/src/api/eth_address.ts +1 -0
  220. package/src/api/ethereum.ts +10 -0
  221. package/src/api/event_cursor.ts +60 -0
  222. package/src/api/events.ts +79 -0
  223. package/src/api/fee.ts +5 -0
  224. package/src/api/fee_testing.ts +1 -0
  225. package/src/api/fields.ts +3 -0
  226. package/src/api/keys.ts +8 -0
  227. package/src/api/log.ts +2 -0
  228. package/src/api/messaging.ts +2 -0
  229. package/src/api/node.ts +30 -0
  230. package/src/api/note.ts +1 -0
  231. package/src/api/protocol.ts +6 -0
  232. package/src/api/trees.ts +2 -0
  233. package/src/api/tx.ts +20 -0
  234. package/src/api/utils.ts +14 -0
  235. package/src/api/wallet.ts +83 -0
  236. package/src/authorization/call_authorization_request.ts +93 -0
  237. package/src/contract/base_contract_interaction.ts +62 -0
  238. package/src/contract/batch_call.ts +188 -0
  239. package/src/contract/checker.ts +122 -0
  240. package/src/contract/contract.ts +52 -0
  241. package/src/contract/contract_base.ts +73 -0
  242. package/src/contract/contract_function_interaction.ts +297 -0
  243. package/src/contract/deploy_method.ts +877 -0
  244. package/src/contract/fastforward_contract_update.ts +71 -0
  245. package/src/contract/interaction_options.ts +301 -0
  246. package/src/contract/protocol_contracts/contract-class-registry.ts +104 -0
  247. package/src/contract/protocol_contracts/contract-instance-registry.ts +241 -0
  248. package/src/contract/protocol_contracts/fee-juice.ts +257 -0
  249. package/src/contract/wait_for_proven.ts +43 -0
  250. package/src/contract/wait_opts.ts +26 -0
  251. package/src/deployment/contract_deployer.ts +40 -0
  252. package/src/deployment/publish_class.ts +34 -0
  253. package/src/deployment/publish_instance.ts +24 -0
  254. package/src/ethereum/portal_manager.ts +539 -0
  255. package/src/fee/fee_juice_payment_method_with_claim.ts +63 -0
  256. package/src/fee/fee_payment_method.ts +26 -0
  257. package/src/fee/private_fee_payment_method.ts +145 -0
  258. package/src/fee/public_fee_payment_method.ts +145 -0
  259. package/src/fee/sponsored_fee_payment.ts +45 -0
  260. package/src/scripts/generate_protocol_contract_types.ts +160 -0
  261. package/src/test/fixtures.ts +126 -0
  262. package/src/utils/abi_types.ts +32 -0
  263. package/src/utils/authwit.ts +327 -0
  264. package/src/utils/cross_chain.ts +55 -0
  265. package/src/utils/fee_juice.ts +14 -0
  266. package/src/utils/field_compressed_string.ts +27 -0
  267. package/src/utils/node.ts +110 -0
  268. package/src/utils/pub_key.ts +12 -0
  269. package/src/wallet/account_entrypoint_meta_payment_method.ts +76 -0
  270. package/src/wallet/account_manager.ts +164 -0
  271. package/src/wallet/capabilities.ts +505 -0
  272. package/src/wallet/deploy_account_method.ts +234 -0
  273. package/src/wallet/index.ts +4 -0
  274. package/src/wallet/tx_simulation_result_with_app_offset.ts +100 -0
  275. package/src/wallet/wallet.ts +668 -0
@@ -0,0 +1,877 @@
1
+ import { Fr } from '@aztec-labs/foundation/curves/bn254';
2
+ import { type ContractArtifact, type FunctionAbi, type FunctionArtifact, getInitializer } from '@aztec-labs/stdlib/abi';
3
+ import type { AuthWitness } from '@aztec-labs/stdlib/auth-witness';
4
+ import { AztecAddress } from '@aztec-labs/stdlib/aztec-address';
5
+ import {
6
+ type ContractInstanceWithAddress,
7
+ computePartialAddress,
8
+ getContractClassFromArtifact,
9
+ getContractInstanceFromInstantiationParams,
10
+ } from '@aztec-labs/stdlib/contract';
11
+ import { PublicKeys } from '@aztec-labs/stdlib/keys';
12
+ import { type Capsule, HashedValues, type TxProfileResult, type TxReceipt } from '@aztec-labs/stdlib/tx';
13
+ import { ExecutionPayload, mergeExecutionPayloads } from '@aztec-labs/stdlib/tx';
14
+
15
+ import { publishContractClass } from '../deployment/publish_class.js';
16
+ import { publishInstance } from '../deployment/publish_instance.js';
17
+ import type { ProfileOptions, SendOptions, SimulateOptions, Wallet } from '../wallet/wallet.js';
18
+ import { BaseContractInteraction } from './base_contract_interaction.js';
19
+ import type { ContractBase } from './contract_base.js';
20
+ import { ContractFunctionInteraction } from './contract_function_interaction.js';
21
+ import {
22
+ type InteractionFeeOptions,
23
+ type InteractionWaitOptions,
24
+ NO_FROM,
25
+ NO_WAIT,
26
+ type NoWait,
27
+ type OffchainOutput,
28
+ type ProfileInteractionOptions,
29
+ type RequestInteractionOptions,
30
+ type SendInteractionOptionsWithoutWait,
31
+ type SimulationResult,
32
+ type TxSendResultImmediate,
33
+ extractOffchainOutput,
34
+ toProfileOptions,
35
+ toSendOptions,
36
+ toSimulateOptions,
37
+ } from './interaction_options.js';
38
+ import type { WaitOpts } from './wait_opts.js';
39
+
40
+ /**
41
+ * Inputs that determine the contract's deployment address.
42
+ *
43
+ * `salt` and `publicKeys` are optional and default to a random Fr and `PublicKeys.default()` respectively.
44
+ *
45
+ * `deployer` and `universalDeploy` are mutually exclusive and both optional:
46
+ * - If neither is supplied, the deployer is locked lazily on the first `send` / `simulate` /
47
+ * `profile` call from `options.from` (NO_FROM/undefined → universal). This preserves the
48
+ * ergonomics of `MyContract.deploy(wallet, ...args).send({ from: alice })`.
49
+ * - If `deployer` or `universalDeploy: true` is supplied, the deployer is locked at construction.
50
+ *
51
+ * Once locked, the deployer cannot change. Subsequent calls with a `from` that would imply a different
52
+ * deployer throw — except when locked to `AztecAddress.ZERO` (universal), which is compatible with any
53
+ * sender.
54
+ */
55
+ export type DeployInstantiationOptions = {
56
+ /** Salt used to derive the contract address. Defaults to a random Fr. */
57
+ salt?: Fr;
58
+ /**
59
+ * Deployer address mixed into the address preimage. Mutually exclusive with `universalDeploy`.
60
+ */
61
+ deployer?: AztecAddress;
62
+ /**
63
+ * If true, the contract is deployed universally (deployer = AztecAddress.ZERO in the address preimage).
64
+ * Mutually exclusive with `deployer`.
65
+ */
66
+ universalDeploy?: boolean;
67
+ /** Public keys mixed into the address. Defaults to PublicKeys.default(). */
68
+ publicKeys?: PublicKeys;
69
+ /**
70
+ * Commitment to the contract's immutable storage values. Folded into the salted initialization
71
+ * hash, so a non-zero value affects the derived address. Defaults to `Fr.ZERO`.
72
+ */
73
+ immutablesHash?: Fr;
74
+ };
75
+
76
+ /**
77
+ * Address-derivation inputs shared by all deploy methods. {@link BoundInstantiationOptions},
78
+ * {@link UniversalInstantiationOptions}, and {@link PendingInstantiationOptions} narrow this
79
+ * shape to forbid the fields that don't apply to a given flavor at the type level.
80
+ */
81
+ type SharedInstantiationOptions = {
82
+ /** Salt used to derive the contract address. Defaults to a random Fr. */
83
+ salt?: Fr;
84
+ /** Public keys mixed into the address. Defaults to `PublicKeys.default()`. */
85
+ publicKeys?: PublicKeys;
86
+ /**
87
+ * Commitment to the contract's immutable storage values. Folded into the salted initialization
88
+ * hash, so a non-zero value affects the derived address. Defaults to `Fr.ZERO`.
89
+ */
90
+ immutablesHash?: Fr;
91
+ };
92
+
93
+ /**
94
+ * Narrowed `DeployInstantiationOptions` accepted by {@link BoundDeployMethod}: requires a
95
+ * concrete `deployer` and forbids `universalDeploy`. The runtime check that `deployer` is
96
+ * non-zero stays as defense in depth (it's a value-level invariant the type system can't model).
97
+ */
98
+ export type BoundInstantiationOptions = SharedInstantiationOptions & {
99
+ /** Concrete deployer mixed into the address preimage. Required, must be non-zero. */
100
+ deployer: AztecAddress;
101
+ /** Forbidden on `BoundDeployMethod`; use `UniversalDeployMethod` for universal deploys. */
102
+ universalDeploy?: never;
103
+ };
104
+
105
+ /**
106
+ * Narrowed `DeployInstantiationOptions` accepted by {@link UniversalDeployMethod}: forbids
107
+ * `deployer` and requires `universalDeploy: true` (so the call site reads as a universal deploy).
108
+ */
109
+ export type UniversalInstantiationOptions = SharedInstantiationOptions & {
110
+ /** Forbidden on `UniversalDeployMethod`; use `BoundDeployMethod` if you need a concrete deployer. */
111
+ deployer?: never;
112
+ /** Marks this as a universal deploy. Required for clarity at the call site. */
113
+ universalDeploy: true;
114
+ };
115
+
116
+ /**
117
+ * Narrowed `DeployInstantiationOptions` accepted by {@link PendingDeployMethod}: forbids both
118
+ * `deployer` and `universalDeploy`. The deploy is locked from the first send-time `from` instead.
119
+ */
120
+ export type PendingInstantiationOptions = SharedInstantiationOptions & {
121
+ /** Forbidden on `PendingDeployMethod`; use `BoundDeployMethod` for a concrete deployer. */
122
+ deployer?: never;
123
+ /** Forbidden on `PendingDeployMethod`; use `UniversalDeployMethod` for a universal deploy. */
124
+ universalDeploy?: never;
125
+ };
126
+
127
+ /**
128
+ * Identifies *which contract* is being deployed and *with what initializer*.
129
+ */
130
+ export type DeployMethodContract<TContract extends ContractBase = ContractBase> = {
131
+ /** Build artifact of the contract being deployed. */
132
+ artifact: ContractArtifact;
133
+ /** Factory invoked after deployment to produce the typed contract handle. */
134
+ postDeployCtor: (instance: ContractInstanceWithAddress, wallet: Wallet) => TContract;
135
+ /** Encoded constructor arguments for the contract. Defaults to `[]`. */
136
+ args?: any[];
137
+ /** Name (or full artifact) of the initializer to call. */
138
+ constructorNameOrArtifact?: string | FunctionArtifact;
139
+ };
140
+
141
+ /**
142
+ * Execution-payload metadata propagated through `request` / `send` / `simulate` / `profile`.
143
+ */
144
+ export type DeployMethodPayload = {
145
+ /** Auth witnesses propagated to the deploy interaction. */
146
+ authWitnesses?: AuthWitness[];
147
+ /** Capsules propagated to the deploy interaction. */
148
+ capsules?: Capsule[];
149
+ /** Extra hashed args propagated to the deploy interaction. */
150
+ extraHashedArgs?: HashedValues[];
151
+ };
152
+
153
+ /**
154
+ * Options for deploying a contract on the Aztec network.
155
+ * Controls publication and registration policy for this deployment.
156
+ */
157
+ export type RequestDeployOptions = RequestInteractionOptions & {
158
+ /** Skip contract class publication. */
159
+ skipClassPublication?: boolean;
160
+ /** Skip publication, instead just privately initialize the contract. */
161
+ skipInstancePublication?: boolean;
162
+ /** Skip contract initialization. */
163
+ skipInitialization?: boolean;
164
+ /** Skip contract registration in the wallet */
165
+ skipRegistration?: boolean;
166
+ };
167
+
168
+ /**
169
+ * Base deployment options without wait parameter.
170
+ */
171
+ export type DeployOptionsWithoutWait = RequestDeployOptions &
172
+ Pick<SendInteractionOptionsWithoutWait, 'from' | 'fee' | 'additionalScopes'>;
173
+
174
+ /**
175
+ * Extends the deployment options with the required parameters to send the transaction.
176
+ */
177
+ export type DeployOptions<W extends InteractionWaitOptions = undefined> = DeployOptionsWithoutWait & {
178
+ /**
179
+ * Options for waiting for the transaction to be mined.
180
+ * - undefined (default): wait with default options and return the contract instance
181
+ * - WaitOpts: wait with custom options
182
+ * - NO_WAIT: return TxHash immediately without waiting
183
+ */
184
+ wait?: W;
185
+ };
186
+
187
+ /**
188
+ * Options for simulating the deployment of a contract
189
+ * Allows skipping certain validations and computing gas estimations
190
+ */
191
+ export type SimulateDeployOptions = Omit<DeployOptionsWithoutWait, 'fee'> & {
192
+ /** The fee options for the transaction. */
193
+ fee?: InteractionFeeOptions;
194
+ /** Simulate without checking for the validity of the resulting transaction,
195
+ * e.g. whether it emits any existing nullifiers. */
196
+ skipTxValidation?: boolean;
197
+ /** Whether to ensure the fee payer is not empty and has enough balance to pay for the fee. */
198
+ skipFeeEnforcement?: boolean;
199
+ /** Whether to include metadata such as offchain effects and performance statistics
200
+ * (e.g. timing information of the different circuits and oracles) in
201
+ * the simulation result, instead of just the return value of the function */
202
+ includeMetadata?: boolean;
203
+ };
204
+
205
+ /** Result of deploying a contract when waiting for mining (default case). */
206
+ export type DeployResultMined<TContract extends ContractBase> = {
207
+ /** The deployed contract instance. */
208
+ contract: TContract;
209
+ /** The deployed contract instance with address and metadata. */
210
+ instance: ContractInstanceWithAddress;
211
+ /** The deploy transaction receipt. */
212
+ receipt: TxReceipt;
213
+ } & OffchainOutput;
214
+
215
+ /** Conditional return type for deploy based on wait options. */
216
+ export type DeployReturn<TContract extends ContractBase, W extends InteractionWaitOptions> = W extends NoWait
217
+ ? TxSendResultImmediate
218
+ : DeployResultMined<TContract>;
219
+
220
+ /**
221
+ * Umbrella type for a contract deployment interaction.
222
+ *
223
+ * `DeployMethod` is abstract: callers always interact with one of three concrete flavors —
224
+ * {@link BoundDeployMethod}, {@link UniversalDeployMethod}, or {@link PendingDeployMethod} —
225
+ * picked by {@link DeployMethod.create} based on the supplied {@link DeployInstantiationOptions}.
226
+ * The flavors only differ in their initial deployer-lock state; the full API
227
+ * (`request` / `send` / `simulate` / `profile` / `getInstance` / `getAddress` /
228
+ * `getPartialAddress` / `register` / `with`) lives on this base, so consumers can type
229
+ * variables as `DeployMethod<T>` and treat all three uniformly.
230
+ *
231
+ * The deployer (and therefore the deployed address) is locked once and never changes. Locking
232
+ * happens either at construction (via `deployer` or `universalDeploy: true` in the instantiation
233
+ * options) or lazily on the first `send` / `simulate` / `profile` call, which lock from
234
+ * `options.from`. Once locked:
235
+ *
236
+ * - The address is stable for the lifetime of this object.
237
+ * - Subsequent `send` / `simulate` / `profile` calls with a `from` that would imply a different
238
+ * deployer throw, to prevent silently deploying at a different address than `getAddress()`
239
+ * reported.
240
+ * - A locked universal deployer (`AztecAddress.ZERO`) is compatible with any `from`, since the
241
+ * address does not depend on the sender.
242
+ *
243
+ * Note that for some contracts, a tx is not required as part of its "creation":
244
+ * If there are no public functions, and if there are no initialization functions,
245
+ * then technically the contract has already been "created", and all of the contract's
246
+ * functions (private and utility) can be interacted-with immediately, without any
247
+ * "deployment tx".
248
+ */
249
+ export abstract class DeployMethod<TContract extends ContractBase = ContractBase> extends BaseContractInteraction {
250
+ /** Salt used in the address preimage. */
251
+ protected readonly salt: Fr;
252
+ /** Public keys mixed into the address preimage. */
253
+ protected readonly publicKeys: PublicKeys;
254
+ /** Immutables hash folded into the salted initialization hash. */
255
+ protected readonly immutablesHash: Fr;
256
+
257
+ /** Cached instance promise; resolved once the deployer is known. */
258
+ #instancePromise?: Promise<ContractInstanceWithAddress>;
259
+ /** Resolved value of `#instancePromise`, populated synchronously once the promise settles. */
260
+ #resolvedInstance?: ContractInstanceWithAddress;
261
+
262
+ /** Constructor function to call. */
263
+ protected constructorArtifact: FunctionAbi | undefined;
264
+ /** Build artifact of the contract being deployed. */
265
+ protected readonly artifact: ContractArtifact;
266
+ /** Factory invoked after deployment to produce the typed contract handle. */
267
+ protected readonly postDeployCtor: (instance: ContractInstanceWithAddress, wallet: Wallet) => TContract;
268
+ /** Encoded constructor arguments for the contract. */
269
+ protected readonly args: any[];
270
+ /** Extra hashed args propagated through `with(...)` and into the deploy payload. */
271
+ protected readonly extraHashedArgs: HashedValues[];
272
+
273
+ protected constructor(
274
+ wallet: Wallet,
275
+ contract: DeployMethodContract<TContract>,
276
+ salt: Fr | undefined,
277
+ publicKeys: PublicKeys | undefined,
278
+ immutablesHash: Fr | undefined,
279
+ payload: DeployMethodPayload = {},
280
+ ) {
281
+ super(wallet, payload.authWitnesses ?? [], payload.capsules ?? []);
282
+ this.artifact = contract.artifact;
283
+ this.postDeployCtor = contract.postDeployCtor;
284
+ this.args = contract.args ?? [];
285
+ this.constructorArtifact = getInitializer(contract.artifact, contract.constructorNameOrArtifact);
286
+ this.salt = salt ?? Fr.random();
287
+ this.publicKeys = publicKeys ?? PublicKeys.default();
288
+ this.immutablesHash = immutablesHash ?? Fr.ZERO;
289
+ this.extraHashedArgs = payload.extraHashedArgs ?? [];
290
+ }
291
+
292
+ /**
293
+ * The address that will be mixed into the contract's address preimage. Owned returns the
294
+ * concrete deployer; Universal returns `AztecAddress.ZERO`; Pending throws unless a prior
295
+ * `send` / `simulate` / `profile` call has already locked it.
296
+ */
297
+ public abstract getDeployerAddress(): AztecAddress;
298
+
299
+ /**
300
+ * Reconciles a send-time `from` with the deploy's deployer. Owned asserts an exact match;
301
+ * Universal accepts anything; Pending uses the first call to lock its deployer (transitioning
302
+ * into an Owned/Universal sibling), then defers to that sibling's assertion on subsequent calls.
303
+ *
304
+ * The "locks-or-asserts" name is intentional: only Pending mutates state, and only on its first
305
+ * invocation. Owned and Universal are pure assertions.
306
+ *
307
+ * @param from - The send-time `from` value (`AztecAddress`, `NO_FROM`, or `undefined`).
308
+ */
309
+ public abstract lockDeployer(from: SendInteractionOptionsWithoutWait['from'] | undefined): void;
310
+
311
+ /**
312
+ * Returns the {@link DeployInstantiationOptions} that match this flavor. Used by `with(...)` to
313
+ * spawn a sibling instance carrying the same lock state.
314
+ */
315
+ public abstract cloneInstantiation(): DeployInstantiationOptions;
316
+
317
+ /**
318
+ * Constructs the right concrete `DeployMethod` flavor for the supplied instantiation options:
319
+ * - `{ deployer: <addr> }` → {@link BoundDeployMethod}
320
+ * - `{ universalDeploy: true }` → {@link UniversalDeployMethod}
321
+ * - neither set → {@link PendingDeployMethod}
322
+ *
323
+ * Mixing `deployer` and `universalDeploy` throws. Returns the umbrella `DeployMethod<T>` type so
324
+ * callers can use the result generically without narrowing.
325
+ *
326
+ * @param wallet - Wallet used to send / simulate the deploy tx.
327
+ * @param contract - The contract being deployed (artifact, factory, args, initializer).
328
+ * @param instantiation - Address-affecting parameters (salt, deployer / universalDeploy, publicKeys). Defaults to pending.
329
+ * @param payload - Auth witnesses, capsules, and extra hashed args propagated to the deploy. Defaults to empty.
330
+ */
331
+ public static create<TContract extends ContractBase>(
332
+ wallet: Wallet,
333
+ contract: DeployMethodContract<TContract>,
334
+ instantiation: DeployInstantiationOptions = {},
335
+ payload: DeployMethodPayload = {},
336
+ ): DeployMethod<TContract> {
337
+ if (instantiation.deployer !== undefined && instantiation.universalDeploy) {
338
+ throw new Error('DeployInstantiationOptions: `deployer` and `universalDeploy` are mutually exclusive.');
339
+ }
340
+ const { salt, publicKeys, immutablesHash, deployer, universalDeploy } = instantiation;
341
+ if (universalDeploy) {
342
+ return new UniversalDeployMethod<TContract>(
343
+ wallet,
344
+ contract,
345
+ { salt, publicKeys, immutablesHash, universalDeploy: true },
346
+ payload,
347
+ );
348
+ }
349
+ if (deployer !== undefined) {
350
+ return new BoundDeployMethod<TContract>(
351
+ wallet,
352
+ contract,
353
+ { salt, publicKeys, immutablesHash, deployer },
354
+ payload,
355
+ );
356
+ }
357
+ return new PendingDeployMethod<TContract>(wallet, contract, { salt, publicKeys, immutablesHash }, payload);
358
+ }
359
+
360
+ /**
361
+ * Returns the execution payload that allows this operation to happen on chain. Requires the
362
+ * deployer to be known — call `getDeployerAddress()` first; on a `PendingDeployMethod` this
363
+ * throws unless a prior `send` / `simulate` / `profile` has already locked the deployer.
364
+ *
365
+ * @param options - Configuration options.
366
+ * @returns The execution payload for this operation
367
+ */
368
+ public async request(options: RequestDeployOptions = {}): Promise<ExecutionPayload> {
369
+ const publication = await this.getPublicationExecutionPayload(options);
370
+
371
+ if (!options?.skipRegistration) {
372
+ await this.wallet.registerContract(await this.getInstance(), this.artifact);
373
+ }
374
+ const { authWitnesses, capsules } = options;
375
+
376
+ // Propagates the included authwitnesses, capsules, and extraHashedArgs
377
+ // potentially baked into the interaction
378
+ const initialExecutionPayload = new ExecutionPayload(
379
+ [],
380
+ this.authWitnesses.concat(authWitnesses ?? []),
381
+ this.capsules.concat(capsules ?? []),
382
+ this.extraHashedArgs,
383
+ );
384
+ const initialization = await this.getInitializationExecutionPayload(options);
385
+ const feeExecutionPayload = options?.fee?.paymentMethod
386
+ ? await options.fee.paymentMethod.getExecutionPayload()
387
+ : undefined;
388
+ const finalExecutionPayload = feeExecutionPayload
389
+ ? mergeExecutionPayloads([initialExecutionPayload, feeExecutionPayload, publication, initialization])
390
+ : mergeExecutionPayloads([initialExecutionPayload, publication, initialization]);
391
+ if (!finalExecutionPayload.calls.length) {
392
+ throw new Error(`No transactions are needed to publish or initialize contract ${this.artifact.name}`);
393
+ }
394
+
395
+ return finalExecutionPayload;
396
+ }
397
+
398
+ /**
399
+ * Converts DeployOptions to SendOptions.
400
+ * @param options - Deploy options with wait parameter.
401
+ */
402
+ protected convertDeployOptionsToSendOptions<W extends InteractionWaitOptions>(
403
+ options: DeployOptions<W>,
404
+ ): SendOptions<W> {
405
+ return toSendOptions({ ...options, wait: options.wait as any }) as any;
406
+ }
407
+
408
+ /**
409
+ * Converts deploy simulation options into wallet-level simulate options.
410
+ * @param options - The deploy simulation options to convert.
411
+ */
412
+ protected convertDeployOptionsToSimulateOptions(options: SimulateDeployOptions): SimulateOptions {
413
+ return toSimulateOptions(options);
414
+ }
415
+
416
+ /**
417
+ * Converts deploy profile options into wallet-level profile options.
418
+ * @param options - The deploy profile options to convert.
419
+ */
420
+ protected convertDeployOptionsToProfileOptions(
421
+ options: DeployOptionsWithoutWait & ProfileInteractionOptions,
422
+ ): ProfileOptions {
423
+ return toProfileOptions(options);
424
+ }
425
+
426
+ /**
427
+ * Adds this contract to the wallet and returns the Contract object.
428
+ */
429
+ public async register(): Promise<TContract> {
430
+ const instance = await this.getInstance();
431
+ await this.wallet.registerContract(instance, this.artifact);
432
+ return this.postDeployCtor(instance, this.wallet);
433
+ }
434
+
435
+ /**
436
+ * Returns an execution payload for:
437
+ * - publication of the contract class and
438
+ * - publication of the contract instance to enable public execution
439
+ * depending on the provided options.
440
+ * @param options - Contract creation options.
441
+ * @returns An execution payload with potentially calls (and bytecode capsule) to the class registry and instance registry.
442
+ */
443
+ protected async getPublicationExecutionPayload(options?: RequestDeployOptions): Promise<ExecutionPayload> {
444
+ const calls: ExecutionPayload[] = [];
445
+
446
+ // Set contract instance object so it's available for populating the DeploySendTx object
447
+ const instance = await this.getInstance();
448
+
449
+ // Obtain contract class from artifact and check it matches the reported one by the instance.
450
+ // TODO(@spalladino): We're unnecessarily calculating the contract class multiple times here.
451
+ const contractClass = await getContractClassFromArtifact(this.artifact);
452
+ if (!instance.currentContractClassId.equals(contractClass.id)) {
453
+ throw new Error(
454
+ `Contract class mismatch when deploying contract: got ${instance.currentContractClassId.toString()} from instance and ${contractClass.id.toString()} from artifact`,
455
+ );
456
+ }
457
+
458
+ // Publish the contract class if it hasn't been published already.
459
+ if (!options?.skipClassPublication) {
460
+ const classMetadata = await this.wallet.getContractClassMetadata(contractClass.id);
461
+ if (!classMetadata.isContractClassPubliclyRegistered) {
462
+ this.log.info(
463
+ `Creating request for publishing contract class ${contractClass.id.toString()} as part of deployment for ${instance.address.toString()}`,
464
+ );
465
+ const registerContractClassInteraction = await publishContractClass(this.wallet, this.artifact);
466
+ calls.push(await registerContractClassInteraction.request());
467
+ } else {
468
+ this.log.debug(
469
+ `Skipping contract class publication for ${contractClass.id.toString()} as it is already registered`,
470
+ );
471
+ }
472
+ }
473
+
474
+ // Publish the contract instance:
475
+ if (!options?.skipInstancePublication) {
476
+ // TODO(https://github.com/AztecProtocol/aztec-packages/issues/15596):
477
+ // Read the artifact, and if there are no public functions, warn the caller that publication of the
478
+ // contract instance is not necessary (until such time as they wish to update the instance (i.e. change its class_id)).
479
+ const deploymentInteraction = publishInstance(this.wallet, instance);
480
+ calls.push(await deploymentInteraction.request());
481
+ }
482
+
483
+ return mergeExecutionPayloads(calls);
484
+ }
485
+
486
+ /**
487
+ * Returns the calls necessary to initialize the contract.
488
+ * @param options - Deployment options.
489
+ * @returns - An array of function calls.
490
+ */
491
+ protected async getInitializationExecutionPayload(options?: RequestDeployOptions): Promise<ExecutionPayload> {
492
+ const executionsPayloads: ExecutionPayload[] = [];
493
+ if (this.constructorArtifact && !options?.skipInitialization) {
494
+ const { address } = await this.getInstance();
495
+ const constructorCall = new ContractFunctionInteraction(
496
+ this.wallet,
497
+ address,
498
+ this.constructorArtifact,
499
+ this.args,
500
+ );
501
+ executionsPayloads.push(await constructorCall.request());
502
+ }
503
+ return mergeExecutionPayloads(executionsPayloads);
504
+ }
505
+
506
+ /**
507
+ * Send a contract deployment transaction (initialize and/or publish) using the provided options.
508
+ * By default, waits for the transaction to be mined and returns the deployed contract instance.
509
+ *
510
+ * @param options - An object containing various deployment options such as `from` and `fee`.
511
+ * @returns TxHash (if wait is NO_WAIT), or DeployResultMined with contract, receipt, and instance (otherwise)
512
+ */
513
+ // Overload for when wait is not specified at all - returns the contract
514
+ public override send(options: DeployOptionsWithoutWait): Promise<DeployResultMined<TContract>>;
515
+ // eslint-disable-next-line jsdoc/require-jsdoc
516
+ public override send<W extends InteractionWaitOptions>(
517
+ options: DeployOptions<W>,
518
+ ): Promise<DeployReturn<TContract, W>>;
519
+ // eslint-disable-next-line jsdoc/require-jsdoc
520
+ public override async send(options: DeployOptions<InteractionWaitOptions>): Promise<any> {
521
+ this.lockDeployer(options.from);
522
+ const executionPayload = await this.request(options);
523
+ const sendOptions = this.convertDeployOptionsToSendOptions(options);
524
+
525
+ if (options.wait === NO_WAIT) {
526
+ const result = await this.wallet.sendTx(executionPayload, sendOptions as SendOptions<NoWait>);
527
+ this.log.debug(`Sent deployment tx ${result.txHash.hash} of ${this.artifact.name} contract`);
528
+ return result;
529
+ }
530
+
531
+ const { receipt, ...offchainOutput } = await this.wallet.sendTx(
532
+ executionPayload,
533
+ sendOptions as SendOptions<WaitOpts | undefined>,
534
+ );
535
+ this.log.debug(`Deployed ${this.artifact.name} contract in tx ${receipt.txHash}`);
536
+
537
+ // Attach contract instance
538
+ const instance = await this.getInstance();
539
+ const contract = this.postDeployCtor(instance, this.wallet) as TContract;
540
+
541
+ return { contract, receipt, instance, ...offchainOutput };
542
+ }
543
+
544
+ /**
545
+ * Builds the contract instance and returns it. The instance is computed once and cached for
546
+ * the lifetime of this DeployMethod; subsequent calls return the same instance.
547
+ *
548
+ * On a {@link PendingDeployMethod} this throws unless a prior `send` / `simulate` / `profile`
549
+ * call has already locked the deployer — otherwise the resolved address could silently differ
550
+ * from the eventually-deployed one.
551
+ *
552
+ * @returns An instance object.
553
+ */
554
+ public getInstance(): Promise<ContractInstanceWithAddress> {
555
+ const deployer = this.getDeployerAddress();
556
+ if (!this.#instancePromise) {
557
+ this.#instancePromise = getContractInstanceFromInstantiationParams(this.artifact, {
558
+ constructorArgs: this.args,
559
+ salt: this.salt,
560
+ publicKeys: this.publicKeys,
561
+ immutablesHash: this.immutablesHash,
562
+ constructorArtifact: this.constructorArtifact,
563
+ deployer,
564
+ }).then(instance => {
565
+ this.#resolvedInstance = instance;
566
+ return instance;
567
+ });
568
+ }
569
+ return this.#instancePromise;
570
+ }
571
+
572
+ /**
573
+ * Simulate the deployment
574
+ *
575
+ * @param options - An optional object containing additional configuration for the simulation.
576
+ * @returns A simulation result object containing metadata of the execution, including gas
577
+ * estimations (if requested via options), execution statistics and emitted offchain effects
578
+ */
579
+ public async simulate(options: SimulateDeployOptions): Promise<SimulationResult> {
580
+ this.lockDeployer(options.from);
581
+ const executionPayload = await this.request(options);
582
+ const simulatedTx = await this.wallet.simulateTx(
583
+ executionPayload,
584
+ this.convertDeployOptionsToSimulateOptions(options),
585
+ );
586
+
587
+ return {
588
+ stats: simulatedTx.stats!,
589
+ ...extractOffchainOutput(
590
+ simulatedTx.offchainEffects,
591
+ simulatedTx.publicInputs.constants.anchorBlockHeader.globalVariables.timestamp,
592
+ ),
593
+ result: undefined,
594
+ gasUsed: simulatedTx.gasUsed,
595
+ };
596
+ }
597
+
598
+ /**
599
+ * Simulate a deployment and profile the gate count for each function in the transaction.
600
+ * @param options - Same options as `send`, plus extra profiling options.
601
+ *
602
+ * @returns An object containing the function return value and profile result.
603
+ */
604
+ public async profile(options: DeployOptionsWithoutWait & ProfileInteractionOptions): Promise<TxProfileResult> {
605
+ this.lockDeployer(options.from);
606
+ const executionPayload = await this.request(options);
607
+ return await this.wallet.profileTx(executionPayload, this.convertDeployOptionsToProfileOptions(options));
608
+ }
609
+
610
+ /** Returns the deployed contract address. */
611
+ public async getAddress(): Promise<AztecAddress> {
612
+ return (await this.getInstance()).address;
613
+ }
614
+
615
+ /** Returns the partial address for this deployment. */
616
+ public async getPartialAddress(): Promise<Fr> {
617
+ return computePartialAddress(await this.getInstance());
618
+ }
619
+
620
+ /**
621
+ * Returns the cached resolved instance synchronously, or throws if no instance has been computed yet.
622
+ * Intended for subclasses that run inside a code path where `getInstance()` is guaranteed to have already
623
+ * been awaited (e.g. `request()` invoked it). Not part of the public API.
624
+ */
625
+ protected getCachedInstanceOrThrow(): ContractInstanceWithAddress {
626
+ if (!this.#resolvedInstance) {
627
+ throw new Error('Contract instance has not been computed yet. Call getInstance() first.');
628
+ }
629
+ return this.#resolvedInstance;
630
+ }
631
+
632
+ /**
633
+ * Augments this DeployMethod with additional metadata, such as authWitnesses and capsules. The
634
+ * deployer lock is preserved: a Pending that has not yet been locked stays Pending; a Pending
635
+ * that has already locked, along with Owned and Universal, returns the matching locked flavor
636
+ * so the cloned method deploys at the same address as `this`.
637
+ * @param options - An object containing the metadata to add to the interaction
638
+ * @returns A new DeployMethod with the added metadata, but calling the same original function in the same manner
639
+ */
640
+ public with({
641
+ authWitnesses = [],
642
+ capsules = [],
643
+ extraHashedArgs = [],
644
+ }: {
645
+ /** The authWitnesses to add to the deployment */
646
+ authWitnesses?: AuthWitness[];
647
+ /** The capsules to add to the deployment */
648
+ capsules?: Capsule[];
649
+ /** The extra hashed args to add to the deployment */
650
+ extraHashedArgs?: HashedValues[];
651
+ }): DeployMethod<TContract> {
652
+ return DeployMethod.create(
653
+ this.wallet,
654
+ {
655
+ artifact: this.artifact,
656
+ postDeployCtor: this.postDeployCtor,
657
+ args: this.args,
658
+ constructorNameOrArtifact: this.constructorArtifact?.name,
659
+ },
660
+ this.cloneInstantiation(),
661
+ {
662
+ authWitnesses: this.authWitnesses.concat(authWitnesses),
663
+ capsules: this.capsules.concat(capsules),
664
+ extraHashedArgs: this.extraHashedArgs.concat(extraHashedArgs),
665
+ },
666
+ );
667
+ }
668
+ }
669
+
670
+ /**
671
+ * Deploy method whose deployer is fixed at construction to a concrete {@link AztecAddress}. The
672
+ * deployer is mixed into the address preimage, so the contract address is fully determined.
673
+ *
674
+ * Sending from a different account throws — letting it through would silently produce a deployed
675
+ * address different from the one `getAddress()` reported.
676
+ */
677
+ export class BoundDeployMethod<TContract extends ContractBase = ContractBase> extends DeployMethod<TContract> {
678
+ /** The address baked into the address preimage. Read-only — set at construction. */
679
+ public readonly deployer: AztecAddress;
680
+
681
+ public constructor(
682
+ wallet: Wallet,
683
+ contract: DeployMethodContract<TContract>,
684
+ instantiation: BoundInstantiationOptions,
685
+ payload: DeployMethodPayload = {},
686
+ ) {
687
+ // `BoundInstantiationOptions` requires a `deployer` and forbids `universalDeploy` at the type
688
+ // level. We still reject `AztecAddress.ZERO` here because the type system can't model it.
689
+ if (instantiation.deployer.equals(AztecAddress.ZERO)) {
690
+ throw new Error(
691
+ 'BoundDeployMethod requires a non-zero `deployer`; use `UniversalDeployMethod` (`{ universalDeploy: true }`) for universal deploys.',
692
+ );
693
+ }
694
+ super(wallet, contract, instantiation.salt, instantiation.publicKeys, instantiation.immutablesHash, payload);
695
+ this.deployer = instantiation.deployer;
696
+ }
697
+
698
+ /** Returns the locked deployer baked into the address preimage. */
699
+ public getDeployerAddress(): AztecAddress {
700
+ return this.deployer;
701
+ }
702
+
703
+ /**
704
+ * Throws unless `from` matches the locked deployer; the deployer is part of the address.
705
+ * @param from - The send-time `from` value (`AztecAddress`, `NO_FROM`, or `undefined`).
706
+ */
707
+ public lockDeployer(from: SendInteractionOptionsWithoutWait['from'] | undefined): void {
708
+ if (from === undefined || from === NO_FROM || !this.deployer.equals(from)) {
709
+ const sender = from === undefined ? '<unspecified>' : from === NO_FROM ? 'NO_FROM' : from.toString();
710
+ throw new Error(
711
+ `Deployer for this DeployMethod is locked to ${this.deployer.toString()}; cannot send from ${sender} ` +
712
+ `because that would imply a different deployer than the one used to derive the address. ` +
713
+ `Pass \`from: ${this.deployer.toString()}\` to send from the locked deployer, or reconstruct the ` +
714
+ `deploy with a different \`deployer\` if you need a different sender.`,
715
+ );
716
+ }
717
+ }
718
+
719
+ /** Re-emits this method's `DeployInstantiationOptions` for `with(...)` to consume. */
720
+ public cloneInstantiation(): DeployInstantiationOptions {
721
+ return {
722
+ salt: this.salt,
723
+ publicKeys: this.publicKeys,
724
+ immutablesHash: this.immutablesHash,
725
+ deployer: this.deployer,
726
+ };
727
+ }
728
+ }
729
+
730
+ /**
731
+ * Deploy method whose deployer is fixed at construction to {@link AztecAddress.ZERO} (universal
732
+ * deploy). The address does not depend on the sender, so any account may sign the deploy tx.
733
+ */
734
+ export class UniversalDeployMethod<TContract extends ContractBase = ContractBase> extends DeployMethod<TContract> {
735
+ public constructor(
736
+ wallet: Wallet,
737
+ contract: DeployMethodContract<TContract>,
738
+ instantiation: UniversalInstantiationOptions,
739
+ payload: DeployMethodPayload = {},
740
+ ) {
741
+ // `UniversalInstantiationOptions` forbids `deployer` and requires `universalDeploy: true` at
742
+ // the type level — no runtime check is needed.
743
+ super(wallet, contract, instantiation.salt, instantiation.publicKeys, instantiation.immutablesHash, payload);
744
+ }
745
+
746
+ /** Universal deploys are anchored at `AztecAddress.ZERO`; the sender does not enter the preimage. */
747
+ public getDeployerAddress(): AztecAddress {
748
+ return AztecAddress.ZERO;
749
+ }
750
+
751
+ /**
752
+ * Universal deploys accept any sender, including `NO_FROM` / `undefined`.
753
+ * @param _from - Ignored.
754
+ */
755
+ public lockDeployer(_from: SendInteractionOptionsWithoutWait['from'] | undefined): void {
756
+ // No-op.
757
+ }
758
+
759
+ /** Re-emits this method's `DeployInstantiationOptions` for `with(...)` to consume. */
760
+ public cloneInstantiation(): DeployInstantiationOptions {
761
+ return {
762
+ salt: this.salt,
763
+ publicKeys: this.publicKeys,
764
+ immutablesHash: this.immutablesHash,
765
+ universalDeploy: true,
766
+ };
767
+ }
768
+ }
769
+
770
+ /**
771
+ * Deploy method whose deployer is not yet decided. The first `send` / `simulate` / `profile` call
772
+ * promotes this into an {@link BoundDeployMethod} or {@link UniversalDeployMethod} (depending on
773
+ * whether `options.from` is an address or `NO_FROM` / `undefined`); subsequent calls reuse that
774
+ * promotion and reject mismatching `from` values.
775
+ *
776
+ * Reading the address (`getInstance` / `getAddress` / `getPartialAddress`) or building a payload
777
+ * (`request`) before the promotion happens throws — the address would otherwise be ambiguous and
778
+ * could differ from what `send()` ends up deploying.
779
+ */
780
+ export class PendingDeployMethod<TContract extends ContractBase = ContractBase> extends DeployMethod<TContract> {
781
+ /**
782
+ * The locked sibling created on the first send-side call. Once set, all flavor-specific
783
+ * decisions (sender compatibility, address derivation, clone shape) delegate to it, so a second
784
+ * call with a mismatched `from` is rejected by `BoundDeployMethod.lockDeployer`.
785
+ */
786
+ #locked?: BoundDeployMethod<TContract> | UniversalDeployMethod<TContract>;
787
+
788
+ public constructor(
789
+ wallet: Wallet,
790
+ contract: DeployMethodContract<TContract>,
791
+ instantiation: PendingInstantiationOptions = {},
792
+ payload: DeployMethodPayload = {},
793
+ ) {
794
+ super(wallet, contract, instantiation.salt, instantiation.publicKeys, instantiation.immutablesHash, payload);
795
+ }
796
+
797
+ /**
798
+ * Returns the locked deployer once it has happened. Throws while still pending — the
799
+ * address would otherwise differ from what `send()` ends up deploying.
800
+ */
801
+ public getDeployerAddress(): AztecAddress {
802
+ if (!this.#locked) {
803
+ throw new Error(
804
+ 'Cannot resolve contract address: deployer is not yet locked. Pass `deployer: <address>` ' +
805
+ 'or `universalDeploy: true` as the instantiation option when constructing the deploy ' +
806
+ '(e.g. `MyContract.deploy(wallet, ...args, { deployer: alice })`), or call `.send` / ' +
807
+ '`.simulate` / `.profile` first to lock the deployer from the sender. ',
808
+ );
809
+ }
810
+ return this.#locked.getDeployerAddress();
811
+ }
812
+
813
+ /**
814
+ * On the first call, promotes this pending method into a locked sibling and remembers it. On
815
+ * subsequent calls, defers to the locked sibling — so a mismatched `from` is rejected by the
816
+ * sibling's own policy, not a duplicate one here.
817
+ * @param from - The send-time `from` value (`AztecAddress`, `NO_FROM`, or `undefined`).
818
+ */
819
+ public lockDeployer(from: SendInteractionOptionsWithoutWait['from'] | undefined): void {
820
+ if (!this.#locked) {
821
+ this.#locked = this.#promoteFrom(from);
822
+ return;
823
+ }
824
+ this.#locked.lockDeployer(from);
825
+ }
826
+
827
+ /** Re-emits this method's `DeployInstantiationOptions` for `with(...)` to consume. */
828
+ public cloneInstantiation(): DeployInstantiationOptions {
829
+ if (!this.#locked) {
830
+ return { salt: this.salt, publicKeys: this.publicKeys, immutablesHash: this.immutablesHash };
831
+ }
832
+ return this.#locked.cloneInstantiation();
833
+ }
834
+
835
+ /**
836
+ * Builds the locked sibling implied by a send-time `from`: an `AztecAddress` becomes
837
+ * {@link BoundDeployMethod}; `NO_FROM` / `undefined` becomes {@link UniversalDeployMethod}.
838
+ * @param from - The send-time `from` value.
839
+ */
840
+ #promoteFrom(
841
+ from: SendInteractionOptionsWithoutWait['from'] | undefined,
842
+ ): BoundDeployMethod<TContract> | UniversalDeployMethod<TContract> {
843
+ const {
844
+ wallet,
845
+ artifact,
846
+ postDeployCtor,
847
+ args,
848
+ salt,
849
+ publicKeys,
850
+ immutablesHash,
851
+ authWitnesses,
852
+ capsules,
853
+ extraHashedArgs,
854
+ } = this;
855
+ const contract: DeployMethodContract<TContract> = {
856
+ artifact,
857
+ postDeployCtor,
858
+ args,
859
+ constructorNameOrArtifact: this.constructorArtifact?.name,
860
+ };
861
+ const payload: DeployMethodPayload = { authWitnesses, capsules, extraHashedArgs };
862
+ if (from === undefined || from === NO_FROM) {
863
+ return new UniversalDeployMethod<TContract>(
864
+ wallet,
865
+ contract,
866
+ { salt, publicKeys, immutablesHash, universalDeploy: true },
867
+ payload,
868
+ );
869
+ }
870
+ return new BoundDeployMethod<TContract>(
871
+ wallet,
872
+ contract,
873
+ { salt, publicKeys, immutablesHash, deployer: from },
874
+ payload,
875
+ );
876
+ }
877
+ }