@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,539 @@
1
+ import { FeeAssetHandlerAbi } from '@aztec/l1-artifacts/FeeAssetHandlerAbi';
2
+ import { FeeJuicePortalAbi } from '@aztec/l1-artifacts/FeeJuicePortalAbi';
3
+ import { OutboxAbi } from '@aztec/l1-artifacts/OutboxAbi';
4
+ import { TestERC20Abi } from '@aztec/l1-artifacts/TestERC20Abi';
5
+ import { TokenPortalAbi } from '@aztec/l1-artifacts/TokenPortalAbi';
6
+
7
+ import {
8
+ type L1TxConfig,
9
+ type L1TxUtils,
10
+ createL1TxUtils,
11
+ getL1TxUtilsConfigEnvVars,
12
+ } from '@aztec-labs/ethereum/l1-tx-utils';
13
+ import type { ExtendedViemWalletClient, ViemContract } from '@aztec-labs/ethereum/types';
14
+ import { extractEvent } from '@aztec-labs/ethereum/utils';
15
+ import type { EpochNumber } from '@aztec-labs/foundation/branded-types';
16
+ import { sha256ToField } from '@aztec-labs/foundation/crypto/sha256';
17
+ import { Fr } from '@aztec-labs/foundation/curves/bn254';
18
+ import { EthAddress } from '@aztec-labs/foundation/eth-address';
19
+ import type { Logger } from '@aztec-labs/foundation/log';
20
+ import type { SiblingPath } from '@aztec-labs/foundation/trees';
21
+ import type { AztecAddress } from '@aztec-labs/stdlib/aztec-address';
22
+ import { computeL2ToL1MessageHash, computeSecretHash } from '@aztec-labs/stdlib/hash';
23
+ import type { AztecNode } from '@aztec-labs/stdlib/interfaces/client';
24
+ import { getL2ToL1MessageLeafId } from '@aztec-labs/stdlib/messaging';
25
+ import { type Hex, encodeFunctionData, getContract, toFunctionSelector } from 'viem';
26
+
27
+ /** L1 to L2 message info to claim it on L2. */
28
+ export type L2Claim = {
29
+ /** Secret for claiming. */
30
+ claimSecret: Fr;
31
+ /** Hash of the secret for claiming. */
32
+ claimSecretHash: Fr;
33
+ /** Hash of the message. */
34
+ messageHash: Hex;
35
+ /** Leaf index in the L1 to L2 message tree. */
36
+ messageLeafIndex: bigint;
37
+ };
38
+
39
+ /** L1 to L2 message info that corresponds to an amount to claim. */
40
+ export type L2AmountClaim = L2Claim & { /** Amount to claim */ claimAmount: bigint };
41
+
42
+ /** L1 to L2 message info that corresponds to an amount to claim with associated recipient. */
43
+ export type L2AmountClaimWithRecipient = L2AmountClaim & {
44
+ /** Address that will receive the newly minted notes. */ recipient: AztecAddress;
45
+ };
46
+
47
+ /** Stringifies an eth address for logging. */
48
+ function stringifyEthAddress(address: EthAddress | Hex, name?: string) {
49
+ return name ? `${name} (${address.toString()})` : address.toString();
50
+ }
51
+
52
+ /** Generates a pair secret and secret hash */
53
+ export async function generateClaimSecret(logger?: Logger): Promise<[Fr, Fr]> {
54
+ const secret = Fr.random();
55
+ const secretHash = await computeSecretHash(secret);
56
+ logger?.verbose(`Generated claim secret=${secret.toString()} hash=${secretHash.toString()}`);
57
+ return [secret, secretHash];
58
+ }
59
+
60
+ // `Inbox.sendL2Message` (reached by every `depositToAztec*` call) inserts into a height-10
61
+ // (`L1_TO_L2_MSG_SUBTREE_HEIGHT`) incremental frontier tree. The per-insert cost swings by up to ~10 hash levels
62
+ // (which translates to ~40k gas) depending on where the global message index lands when the tx is mined: inserts that
63
+ // complete a subtree cascade through cold SLOADs + an SSTORE vs cheap inserts that touch one slot. A point-in-time
64
+ // `eth_estimateGas` taken at a cheap index therefore under-sizes a deposit that mines at a subtree boundary. That ~40k
65
+ // swing exceeds the default 20% buffer on a ~100k deposit. That is why we raise the gas-limit buffer to 2x here.
66
+ // Note: a larger operator override via L1_GAS_LIMIT_BUFFER_PERCENTAGE still wins.
67
+ const INBOX_DEPOSIT_GAS_LIMIT_BUFFER_PERCENTAGE = 100;
68
+
69
+ /** Per-call gas config for `depositToAztec*`: the Inbox-deposit buffer floor, or a larger operator override. */
70
+ function inboxDepositGasConfig(): L1TxConfig {
71
+ const configuredBuffer = getL1TxUtilsConfigEnvVars().gasLimitBufferPercentage ?? 0;
72
+ return { gasLimitBufferPercentage: Math.max(configuredBuffer, INBOX_DEPOSIT_GAS_LIMIT_BUFFER_PERCENTAGE) };
73
+ }
74
+
75
+ /** Helper for managing an ERC20 on L1. */
76
+ export class L1TokenManager {
77
+ private contract: ViemContract<typeof TestERC20Abi>;
78
+ private handler: ViemContract<typeof FeeAssetHandlerAbi> | undefined;
79
+ private readonly l1TxUtils: L1TxUtils;
80
+
81
+ public constructor(
82
+ /** Address of the ERC20 contract. */
83
+ public readonly tokenAddress: EthAddress,
84
+ /** Address of the handler/faucet contract. */
85
+ public readonly handlerAddress: EthAddress | undefined,
86
+ private readonly extendedClient: ExtendedViemWalletClient,
87
+ private logger: Logger,
88
+ ) {
89
+ this.contract = getContract({
90
+ address: this.tokenAddress.toString(),
91
+ abi: TestERC20Abi,
92
+ client: this.extendedClient,
93
+ });
94
+ if (this.handlerAddress) {
95
+ this.handler = getContract({
96
+ address: this.handlerAddress.toString(),
97
+ abi: FeeAssetHandlerAbi,
98
+ client: this.extendedClient,
99
+ });
100
+ }
101
+ this.l1TxUtils = createL1TxUtils(this.extendedClient, { logger }, getL1TxUtilsConfigEnvVars());
102
+ }
103
+
104
+ /** Returns the amount of tokens available to mint via the handler.
105
+ * @throws if the handler is not provided.
106
+ */
107
+ public async getMintAmount() {
108
+ if (!this.handler) {
109
+ throw new Error('Minting handler was not provided');
110
+ }
111
+ return await this.handler.read.mintAmount();
112
+ }
113
+
114
+ /**
115
+ * Returns the balance of the given address.
116
+ * @param address - Address to get the balance of.
117
+ */
118
+ public async getL1TokenBalance(address: Hex) {
119
+ return await this.contract.read.balanceOf([address]);
120
+ }
121
+
122
+ /**
123
+ * Mints a fixed amount of tokens for the given address. Returns once the tx has been mined.
124
+ * @param address - Address to mint the tokens for.
125
+ * @param addressName - Optional name of the address for logging.
126
+ */
127
+ public async mint(address: Hex, addressName?: string) {
128
+ if (!this.handler) {
129
+ throw new Error('Minting handler was not provided');
130
+ }
131
+ const mintAmount = await this.getMintAmount();
132
+ this.logger.info(`Minting ${mintAmount} tokens for ${stringifyEthAddress(address, addressName)}`);
133
+ // NOTE: the handler mints a fixed amount.
134
+ await this.l1TxUtils.sendAndMonitorTransaction({
135
+ to: this.handler.address,
136
+ abi: FeeAssetHandlerAbi,
137
+ data: encodeFunctionData({ abi: FeeAssetHandlerAbi, functionName: 'mint', args: [address] }),
138
+ });
139
+ }
140
+
141
+ /**
142
+ * Approves tokens for the given address. Returns once the tx has been mined.
143
+ * @param amount - Amount to approve.
144
+ * @param address - Address to approve the tokens for.
145
+ * @param addressName - Optional name of the address for logging.
146
+ */
147
+ public async approve(amount: bigint, address: Hex, addressName = '') {
148
+ this.logger.info(`Approving ${amount} tokens for ${stringifyEthAddress(address, addressName)}`);
149
+ await this.l1TxUtils.sendAndMonitorTransaction({
150
+ to: this.contract.address,
151
+ abi: TestERC20Abi,
152
+ data: encodeFunctionData({ abi: TestERC20Abi, functionName: 'approve', args: [address, amount] }),
153
+ });
154
+ }
155
+ }
156
+
157
+ /** Helper for interacting with the FeeJuicePortal on L1. */
158
+ export class L1FeeJuicePortalManager {
159
+ private readonly tokenManager: L1TokenManager;
160
+ private readonly contract: ViemContract<typeof FeeJuicePortalAbi>;
161
+ private readonly l1TxUtils: L1TxUtils;
162
+
163
+ constructor(
164
+ portalAddress: EthAddress,
165
+ tokenAddress: EthAddress,
166
+ handlerAddress: EthAddress | undefined,
167
+ private readonly extendedClient: ExtendedViemWalletClient,
168
+ private readonly logger: Logger,
169
+ ) {
170
+ this.tokenManager = new L1TokenManager(tokenAddress, handlerAddress, extendedClient, logger);
171
+ this.contract = getContract({
172
+ address: portalAddress.toString(),
173
+ abi: FeeJuicePortalAbi,
174
+ client: extendedClient,
175
+ });
176
+ this.l1TxUtils = createL1TxUtils(extendedClient, { logger }, getL1TxUtilsConfigEnvVars());
177
+ }
178
+
179
+ /** Returns the associated token manager for the L1 ERC20. */
180
+ public getTokenManager() {
181
+ return this.tokenManager;
182
+ }
183
+
184
+ /**
185
+ * Bridges fee juice from L1 to L2 publicly. Handles L1 ERC20 approvals. Returns once the tx has been mined.
186
+ * @param to - Address to send the tokens to on L2.
187
+ * @param amount - Amount of tokens to send.
188
+ * @param mint - Whether to mint the tokens before sending (only during testing).
189
+ */
190
+ public async bridgeTokensPublic(to: AztecAddress, amount: bigint | undefined, mint = false): Promise<L2AmountClaim> {
191
+ const [claimSecret, claimSecretHash] = await generateClaimSecret();
192
+ const amountToBridge = amount ?? (await this.tokenManager.getMintAmount());
193
+ if (mint) {
194
+ const mintableAmount = await this.tokenManager.getMintAmount();
195
+ if (amountToBridge !== mintableAmount) {
196
+ throw new Error(`Minting amount must be ${mintableAmount}`);
197
+ }
198
+ await this.tokenManager.mint(this.extendedClient.account.address);
199
+ }
200
+
201
+ await this.tokenManager.approve(amountToBridge, this.contract.address, 'FeeJuice Portal');
202
+
203
+ this.logger.info('Sending L1 Fee Juice to L2 to be claimed publicly');
204
+ const args = [to.toString(), amountToBridge, claimSecretHash.toString()] as const;
205
+
206
+ await this.contract.simulate.depositToAztecPublic(args);
207
+
208
+ const { receipt: txReceipt } = await this.l1TxUtils.sendAndMonitorTransaction(
209
+ {
210
+ to: this.contract.address,
211
+ abi: FeeJuicePortalAbi,
212
+ data: encodeFunctionData({ abi: FeeJuicePortalAbi, functionName: 'depositToAztecPublic', args }),
213
+ },
214
+ inboxDepositGasConfig(),
215
+ );
216
+
217
+ this.logger.info('Deposited to Aztec public successfully', { txReceipt });
218
+
219
+ const log = extractEvent(
220
+ txReceipt.logs,
221
+ this.contract.address,
222
+ this.contract.abi,
223
+ 'DepositToAztecPublic',
224
+ log => {
225
+ // Normalize hex strings for comparison (case-insensitive, handle different formats)
226
+ const normalizeHex = (val: string | bigint | number) => {
227
+ const hexStr = typeof val === 'string' ? val : `0x${val.toString(16).padStart(64, '0')}`;
228
+ return hexStr.toLowerCase();
229
+ };
230
+
231
+ const secretHashMatch = normalizeHex(log.args.secretHash) === normalizeHex(claimSecretHash.toString());
232
+ const amountMatch = log.args.amount === amountToBridge;
233
+ const toMatch = normalizeHex(log.args.to) === normalizeHex(to.toString());
234
+
235
+ this.logger.debug(
236
+ `Event filter matching: secretHash=${secretHashMatch} (${log.args.secretHash} vs ${claimSecretHash.toString()}), ` +
237
+ `amount=${amountMatch} (${log.args.amount} vs ${amountToBridge}), ` +
238
+ `to=${toMatch} (${log.args.to} vs ${to.toString()})`,
239
+ );
240
+
241
+ return secretHashMatch && amountMatch && toMatch;
242
+ },
243
+ this.logger,
244
+ );
245
+
246
+ return {
247
+ claimAmount: amountToBridge,
248
+ claimSecret,
249
+ claimSecretHash,
250
+ messageHash: log.args.key,
251
+ messageLeafIndex: log.args.index,
252
+ };
253
+ }
254
+
255
+ /**
256
+ * Creates a new instance
257
+ * @param node - Aztec node client used for retrieving the L1 contract addresses.
258
+ * @param extendedClient - Wallet client, extended with public actions.
259
+ * @param logger - Logger.
260
+ */
261
+ public static async new(
262
+ node: AztecNode,
263
+ extendedClient: ExtendedViemWalletClient,
264
+ logger: Logger,
265
+ ): Promise<L1FeeJuicePortalManager> {
266
+ const {
267
+ l1ContractAddresses: { feeJuiceAddress, feeJuicePortalAddress, feeAssetHandlerAddress },
268
+ } = await node.getNodeInfo();
269
+
270
+ if (feeJuiceAddress.isZero() || feeJuicePortalAddress.isZero()) {
271
+ throw new Error('Portal or token not deployed on L1');
272
+ }
273
+
274
+ // Handler is optional - it's only needed for minting tokens during testing
275
+ const handlerAddress =
276
+ feeAssetHandlerAddress && !feeAssetHandlerAddress.isZero() ? feeAssetHandlerAddress : undefined;
277
+
278
+ return new L1FeeJuicePortalManager(feeJuicePortalAddress, feeJuiceAddress, handlerAddress, extendedClient, logger);
279
+ }
280
+ }
281
+
282
+ /** Helper for interacting with a test TokenPortal on L1 for sending tokens to L2. */
283
+ export class L1ToL2TokenPortalManager {
284
+ protected readonly portal: ViemContract<typeof TokenPortalAbi>;
285
+ protected readonly tokenManager: L1TokenManager;
286
+ protected readonly l1TxUtils: L1TxUtils;
287
+
288
+ constructor(
289
+ portalAddress: EthAddress,
290
+ tokenAddress: EthAddress,
291
+ handlerAddress: EthAddress | undefined,
292
+ protected extendedClient: ExtendedViemWalletClient,
293
+ protected logger: Logger,
294
+ ) {
295
+ this.tokenManager = new L1TokenManager(tokenAddress, handlerAddress, extendedClient, logger);
296
+ this.portal = getContract({
297
+ address: portalAddress.toString(),
298
+ abi: TokenPortalAbi,
299
+ client: extendedClient,
300
+ });
301
+ this.l1TxUtils = createL1TxUtils(extendedClient, { logger }, getL1TxUtilsConfigEnvVars());
302
+ }
303
+
304
+ /** Returns the token manager for the underlying L1 token. */
305
+ public getTokenManager() {
306
+ return this.tokenManager;
307
+ }
308
+
309
+ /**
310
+ * Bridges tokens from L1 to L2. Handles token approvals. Returns once the tx has been mined.
311
+ * @param to - Address to send the tokens to on L2.
312
+ * @param amount - Amount of tokens to send.
313
+ * @param mint - Whether to mint the tokens before sending (only during testing).
314
+ */
315
+ public async bridgeTokensPublic(to: AztecAddress, amount: bigint, mint = false): Promise<L2AmountClaim> {
316
+ const [claimSecret, claimSecretHash] = await this.bridgeSetup(amount, mint);
317
+
318
+ this.logger.info('Sending L1 tokens to L2 to be claimed publicly');
319
+ const args = [to.toString(), amount, claimSecretHash.toString()] as const;
320
+ await this.portal.simulate.depositToAztecPublic(args);
321
+
322
+ const { receipt: txReceipt } = await this.l1TxUtils.sendAndMonitorTransaction(
323
+ {
324
+ to: this.portal.address,
325
+ abi: TokenPortalAbi,
326
+ data: encodeFunctionData({ abi: TokenPortalAbi, functionName: 'depositToAztecPublic', args }),
327
+ },
328
+ inboxDepositGasConfig(),
329
+ );
330
+
331
+ const log = extractEvent(
332
+ txReceipt.logs,
333
+ this.portal.address,
334
+ this.portal.abi,
335
+ 'DepositToAztecPublic',
336
+ log => {
337
+ // Normalize hex strings for comparison (case-insensitive, handle different formats)
338
+ const normalizeHex = (val: string | bigint | number) => {
339
+ const hexStr = typeof val === 'string' ? val : `0x${val.toString(16).padStart(64, '0')}`;
340
+ return hexStr.toLowerCase();
341
+ };
342
+
343
+ return (
344
+ normalizeHex(log.args.secretHash) === normalizeHex(claimSecretHash.toString()) &&
345
+ log.args.amount === amount &&
346
+ normalizeHex(log.args.to) === normalizeHex(to.toString())
347
+ );
348
+ },
349
+ this.logger,
350
+ );
351
+
352
+ return {
353
+ claimAmount: amount,
354
+ claimSecret,
355
+ claimSecretHash,
356
+ messageHash: log.args.key,
357
+ messageLeafIndex: log.args.index,
358
+ };
359
+ }
360
+
361
+ /**
362
+ * Bridges tokens from L1 to L2 privately. Handles token approvals. Returns once the tx has been mined.
363
+ * @param to - Address to send the tokens to on L2.
364
+ * @param amount - Amount of tokens to send.
365
+ * @param mint - Whether to mint the tokens before sending (only during testing).
366
+ */
367
+ public async bridgeTokensPrivate(
368
+ to: AztecAddress,
369
+ amount: bigint,
370
+ mint = false,
371
+ ): Promise<L2AmountClaimWithRecipient> {
372
+ const [claimSecret, claimSecretHash] = await this.bridgeSetup(amount, mint);
373
+
374
+ this.logger.info('Sending L1 tokens to L2 to be claimed privately');
375
+ const args = [amount, claimSecretHash.toString()] as const;
376
+ await this.portal.simulate.depositToAztecPrivate(args);
377
+
378
+ const { receipt: txReceipt } = await this.l1TxUtils.sendAndMonitorTransaction(
379
+ {
380
+ to: this.portal.address,
381
+ abi: TokenPortalAbi,
382
+ data: encodeFunctionData({ abi: TokenPortalAbi, functionName: 'depositToAztecPrivate', args }),
383
+ },
384
+ inboxDepositGasConfig(),
385
+ );
386
+
387
+ const log = extractEvent(
388
+ txReceipt.logs,
389
+ this.portal.address,
390
+ this.portal.abi,
391
+ 'DepositToAztecPrivate',
392
+ log => {
393
+ // Normalize hex strings for comparison (case-insensitive, handle different formats)
394
+ const normalizeHex = (val: string | bigint | number) => {
395
+ const hexStr = typeof val === 'string' ? val : `0x${val.toString(16).padStart(64, '0')}`;
396
+ return hexStr.toLowerCase();
397
+ };
398
+
399
+ return (
400
+ log.args.amount === amount &&
401
+ normalizeHex(log.args.secretHashForL2MessageConsumption) === normalizeHex(claimSecretHash.toString())
402
+ );
403
+ },
404
+ this.logger,
405
+ );
406
+
407
+ this.logger.info(
408
+ `Claim message secret: ${claimSecret.toString()}, claim message secret hash: ${claimSecretHash.toString()}`,
409
+ );
410
+
411
+ return {
412
+ claimAmount: amount,
413
+ claimSecret,
414
+ claimSecretHash,
415
+ recipient: to,
416
+ messageHash: log.args.key,
417
+ messageLeafIndex: log.args.index,
418
+ };
419
+ }
420
+
421
+ private async bridgeSetup(amount: bigint, mint: boolean) {
422
+ if (mint) {
423
+ const mintableAmount = await this.tokenManager.getMintAmount();
424
+ if (amount !== mintableAmount) {
425
+ throw new Error(`Minting amount must be ${mintableAmount} for testing`);
426
+ }
427
+ await this.tokenManager.mint(this.extendedClient.account.address);
428
+ }
429
+ await this.tokenManager.approve(amount, this.portal.address, 'TokenPortal');
430
+ return generateClaimSecret();
431
+ }
432
+ }
433
+
434
+ /** Helper for interacting with a test TokenPortal on L1 for both withdrawing from and bridging to L2. */
435
+ export class L1TokenPortalManager extends L1ToL2TokenPortalManager {
436
+ private readonly outbox: ViemContract<typeof OutboxAbi>;
437
+
438
+ constructor(
439
+ portalAddress: EthAddress,
440
+ tokenAddress: EthAddress,
441
+ handlerAddress: EthAddress | undefined,
442
+ outboxAddress: EthAddress,
443
+ extendedClient: ExtendedViemWalletClient,
444
+ logger: Logger,
445
+ ) {
446
+ super(portalAddress, tokenAddress, handlerAddress, extendedClient, logger);
447
+ this.outbox = getContract({
448
+ address: outboxAddress.toString(),
449
+ abi: OutboxAbi,
450
+ client: extendedClient,
451
+ });
452
+ }
453
+
454
+ /**
455
+ * Withdraws funds from the portal by consuming an L2 to L1 message. Returns once the tx is mined on L1.
456
+ * @param amount - Amount to withdraw.
457
+ * @param recipient - Who will receive the funds.
458
+ * @param epochNumber - Epoch number of the message.
459
+ * @param numCheckpointsInEpoch - The partial-proof depth (1-indexed) the witness was built against.
460
+ * @param messageIndex - Index of the message.
461
+ * @param siblingPath - Sibling path of the message.
462
+ */
463
+ public async withdrawFunds(
464
+ amount: bigint,
465
+ recipient: EthAddress,
466
+ epochNumber: EpochNumber,
467
+ numCheckpointsInEpoch: number,
468
+ messageIndex: bigint,
469
+ siblingPath: SiblingPath<number>,
470
+ ) {
471
+ this.logger.info(
472
+ `Sending L1 tx to consume message at epoch ${epochNumber} numCheckpointsInEpoch ${numCheckpointsInEpoch} index ${messageIndex} to withdraw ${amount}`,
473
+ );
474
+
475
+ const messageLeafId = getL2ToL1MessageLeafId({ leafIndex: messageIndex, siblingPath });
476
+ const isConsumedBefore = await this.outbox.read.hasMessageBeenConsumedAtEpoch([BigInt(epochNumber), messageLeafId]);
477
+ if (isConsumedBefore) {
478
+ throw new Error(
479
+ `L2 to L1 message at epoch ${epochNumber} index ${messageIndex} height ${siblingPath.pathSize} has already been consumed`,
480
+ );
481
+ }
482
+
483
+ // Call function on L1 contract to consume the message
484
+ const withdrawArgs = [
485
+ recipient.toString(),
486
+ amount,
487
+ false,
488
+ BigInt(epochNumber),
489
+ BigInt(numCheckpointsInEpoch),
490
+ messageIndex,
491
+ siblingPath.toBufferArray().map((buf: Buffer): Hex => `0x${buf.toString('hex')}`),
492
+ ] as const;
493
+ await this.portal.simulate.withdraw(withdrawArgs);
494
+
495
+ await this.l1TxUtils.sendAndMonitorTransaction({
496
+ to: this.portal.address,
497
+ abi: TokenPortalAbi,
498
+ data: encodeFunctionData({ abi: TokenPortalAbi, functionName: 'withdraw', args: withdrawArgs }),
499
+ });
500
+
501
+ const isConsumedAfter = await this.outbox.read.hasMessageBeenConsumedAtEpoch([BigInt(epochNumber), messageLeafId]);
502
+ if (!isConsumedAfter) {
503
+ throw new Error(
504
+ `L2 to L1 message at epoch ${epochNumber} index ${messageIndex} height ${siblingPath.pathSize} not consumed after withdrawal`,
505
+ );
506
+ }
507
+ }
508
+
509
+ /**
510
+ * Computes the L2 to L1 message leaf for the given parameters.
511
+ * @param amount - Amount to bridge.
512
+ * @param recipient - Recipient on L1.
513
+ * @param l2Bridge - Address of the L2 bridge.
514
+ * @param callerOnL1 - Caller address on L1.
515
+ */
516
+ public async getL2ToL1MessageLeaf(
517
+ amount: bigint,
518
+ recipient: EthAddress,
519
+ l2Bridge: AztecAddress,
520
+ callerOnL1: EthAddress = EthAddress.ZERO,
521
+ ): Promise<Fr> {
522
+ const version = await this.outbox.read.VERSION();
523
+
524
+ const content = sha256ToField([
525
+ Buffer.from(toFunctionSelector('withdraw(address,uint256,address)').substring(2), 'hex'),
526
+ recipient.toBuffer32(),
527
+ new Fr(amount).toBuffer(),
528
+ callerOnL1.toBuffer32(),
529
+ ]);
530
+
531
+ return computeL2ToL1MessageHash({
532
+ l2Sender: l2Bridge,
533
+ l1Recipient: EthAddress.fromString(this.portal.address),
534
+ content,
535
+ rollupVersion: new Fr(version),
536
+ chainId: new Fr(this.extendedClient.chain.id),
537
+ });
538
+ }
539
+ }
@@ -0,0 +1,63 @@
1
+ import { Fr } from '@aztec-labs/foundation/curves/bn254';
2
+ import { ProtocolContractAddress } from '@aztec-labs/protocol-contracts';
3
+ import { FunctionCall, FunctionSelector, FunctionType } from '@aztec-labs/stdlib/abi';
4
+ import type { AztecAddress } from '@aztec-labs/stdlib/aztec-address';
5
+ import type { GasSettings } from '@aztec-labs/stdlib/gas';
6
+ import { ExecutionPayload } from '@aztec-labs/stdlib/tx';
7
+
8
+ import type { L2AmountClaim } from '../ethereum/portal_manager.js';
9
+ import type { FeePaymentMethod } from './fee_payment_method.js';
10
+
11
+ /**
12
+ * Pay fee directly with Fee Juice claimed in the same tx. Claiming consumes an L1 to L2 message that "contains"
13
+ * the fee juice bridged from L1.
14
+ */
15
+ export class FeeJuicePaymentMethodWithClaim implements FeePaymentMethod {
16
+ constructor(
17
+ private sender: AztecAddress,
18
+ private claim: Pick<L2AmountClaim, 'claimAmount' | 'claimSecret' | 'messageLeafIndex'>,
19
+ ) {}
20
+
21
+ /**
22
+ * Creates an execution payload to pay the fee in Fee Juice.
23
+ * @returns An execution payload that just contains the `claim_and_end_setup` function call.
24
+ */
25
+ async getExecutionPayload(): Promise<ExecutionPayload> {
26
+ const selector = await FunctionSelector.fromSignature('claim_and_end_setup((Field),u128,Field,Field)');
27
+
28
+ return new ExecutionPayload(
29
+ [
30
+ FunctionCall.from({
31
+ name: 'claim_and_end_setup',
32
+ to: ProtocolContractAddress.FeeJuice,
33
+ selector,
34
+ type: FunctionType.PRIVATE,
35
+ hideMsgSender: false,
36
+ isStatic: false,
37
+ args: [
38
+ this.sender.toField(),
39
+ new Fr(this.claim.claimAmount),
40
+ this.claim.claimSecret,
41
+ new Fr(this.claim.messageLeafIndex),
42
+ ],
43
+ }),
44
+ ],
45
+ [],
46
+ [],
47
+ [],
48
+ this.sender, // feePayer
49
+ );
50
+ }
51
+
52
+ getAsset(): Promise<AztecAddress> {
53
+ return Promise.resolve(ProtocolContractAddress.FeeJuice);
54
+ }
55
+
56
+ getFeePayer(): Promise<AztecAddress> {
57
+ return Promise.resolve(this.sender);
58
+ }
59
+
60
+ getGasSettings(): GasSettings | undefined {
61
+ return;
62
+ }
63
+ }
@@ -0,0 +1,26 @@
1
+ import type { AztecAddress } from '@aztec-labs/stdlib/aztec-address';
2
+ import type { GasSettings } from '@aztec-labs/stdlib/gas';
3
+ import type { ExecutionPayload } from '@aztec-labs/stdlib/tx';
4
+
5
+ /**
6
+ * Holds information about how the fee for a transaction is to be paid.
7
+ */
8
+ export interface FeePaymentMethod {
9
+ /** The asset used to pay the fee. */
10
+ getAsset(): Promise<AztecAddress>;
11
+ /**
12
+ * Returns the data to be added to the final execution request
13
+ * to pay the fee in the given asset
14
+ * @returns The function calls to pay the fee.
15
+ */
16
+ getExecutionPayload(): Promise<ExecutionPayload>;
17
+ /**
18
+ * The expected fee payer for this tx.
19
+ */
20
+ getFeePayer(): Promise<AztecAddress>;
21
+ /**
22
+ * The gas settings (if any) used to compute the
23
+ * execution payload of the payment method
24
+ */
25
+ getGasSettings(): GasSettings | undefined;
26
+ }