diff --git a/boxes/boxes/react/src/hooks/useContract.tsx b/boxes/boxes/react/src/hooks/useContract.tsx index 745bc9e9ebf4..5b3c7aca373f 100644 --- a/boxes/boxes/react/src/hooks/useContract.tsx +++ b/boxes/boxes/react/src/hooks/useContract.tsx @@ -19,11 +19,12 @@ export function useContract() { const { BoxReactContract } = await import('../../artifacts/BoxReact'); - const tx = await BoxReactContract.deploy(wallet, Fr.random(), defaultAccountAddress).send({ + const deploymentPromise = BoxReactContract.deploy(wallet, Fr.random(), defaultAccountAddress).send({ from: defaultAccountAddress, contractAddressSalt: salt, }); - const contract = await toast.promise(tx.deployed(), { + + const contract = await toast.promise(deploymentPromise, { pending: 'Deploying contract...', success: { render: ({ data }) => `Address: ${data.address}`, diff --git a/boxes/boxes/react/src/hooks/useNumber.tsx b/boxes/boxes/react/src/hooks/useNumber.tsx index b18dfb317f8e..8809b6555b42 100644 --- a/boxes/boxes/react/src/hooks/useNumber.tsx +++ b/boxes/boxes/react/src/hooks/useNumber.tsx @@ -28,7 +28,7 @@ export function useNumber({ contract }: { contract: Contract }) { const value = BigInt(el.value); const defaultAccountAddress = deployerEnv.getDefaultAccountAddress(); await toast.promise( - contract!.methods.setNumber(value, defaultAccountAddress).send({ from: defaultAccountAddress }).wait(), + contract!.methods.setNumber(value, defaultAccountAddress).send({ from: defaultAccountAddress }), { pending: 'Setting number...', success: `Number set to: ${value}`, diff --git a/boxes/boxes/vanilla/app/embedded-wallet.ts b/boxes/boxes/vanilla/app/embedded-wallet.ts index 5c00e040aa2a..34b166cc12bb 100644 --- a/boxes/boxes/vanilla/app/embedded-wallet.ts +++ b/boxes/boxes/vanilla/app/embedded-wallet.ts @@ -1,6 +1,9 @@ import { Account, SignerlessAccount } from '@aztec/aztec.js/account'; import { AztecAddress } from '@aztec/aztec.js/addresses'; -import { getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts'; +import { + getContractInstanceFromInstantiationParams, + InteractionWaitOptions, +} from '@aztec/aztec.js/contracts'; import { SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee'; import { Fr } from '@aztec/aztec.js/fields'; import { createLogger } from '@aztec/aztec.js/log'; @@ -218,7 +221,7 @@ export class EmbeddedWallet extends BaseWallet { const deployMethod = await accountManager.getDeployMethod(); const sponsoredPFCContract = await EmbeddedWallet.#getSponsoredPFCContract(); - const deployOpts: DeployAccountOptions = { + const deployOpts: DeployAccountOptions = { from: AztecAddress.ZERO, fee: { paymentMethod: new SponsoredFeePaymentMethod( @@ -227,9 +230,10 @@ export class EmbeddedWallet extends BaseWallet { }, skipClassPublication: true, skipInstancePublication: true, + wait: { timeout: 120 }, }; - const receipt = await deployMethod.send(deployOpts).wait({ timeout: 120 }); + const receipt = await deployMethod.send(deployOpts); logger.info('Account deployed', receipt); diff --git a/boxes/boxes/vanilla/app/main.ts b/boxes/boxes/vanilla/app/main.ts index 02f53a4ebf76..465e587255bf 100644 --- a/boxes/boxes/vanilla/app/main.ts +++ b/boxes/boxes/vanilla/app/main.ts @@ -155,8 +155,7 @@ voteButton.addEventListener('click', async (e) => { // Send tx await votingContract.methods .cast_vote(candidate) - .send({ from: connectedAccount }) - .wait(); + .send({ from: connectedAccount }); // Update tally displayStatusMessage('Updating vote tally...'); diff --git a/boxes/boxes/vanilla/scripts/deploy.ts b/boxes/boxes/vanilla/scripts/deploy.ts index 0009c4458e4f..24e1873f29e7 100644 --- a/boxes/boxes/vanilla/scripts/deploy.ts +++ b/boxes/boxes/vanilla/scripts/deploy.ts @@ -3,12 +3,16 @@ import { type ContractInstanceWithAddress, DeployMethod, getContractInstanceFromInstantiationParams, + InteractionWaitOptions, } from '@aztec/aztec.js/contracts'; import { SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee'; import { Fr } from '@aztec/aztec.js/fields'; import { PublicKeys } from '@aztec/aztec.js/keys'; import { createAztecNodeClient } from '@aztec/aztec.js/node'; -import type { DeployAccountOptions, Wallet } from '@aztec/aztec.js/wallet'; +import type { + DeployAccountOptions, + Wallet, +} from '@aztec/aztec.js/wallet'; import { type AztecNode } from '@aztec/aztec.js/node'; import { SPONSORED_FPC_SALT } from '@aztec/constants'; import { createStore } from '@aztec/kv-store/lmdb'; @@ -68,7 +72,7 @@ async function createAccount(wallet: TestWallet) { const deployMethod = await accountManager.getDeployMethod(); const sponsoredPFCContract = await getSponsoredPFCContract(); - const deployOpts: DeployAccountOptions = { + const deployOpts: DeployAccountOptions = { from: AztecAddress.ZERO, fee: { paymentMethod: new SponsoredFeePaymentMethod( @@ -77,8 +81,9 @@ async function createAccount(wallet: TestWallet) { }, skipClassPublication: true, skipInstancePublication: true, + wait: { timeout: 120 }, }; - await deployMethod.send(deployOpts).wait({ timeout: 120 }); + await deployMethod.send(deployOpts); return accountManager.address; } @@ -110,17 +115,16 @@ async function deployContract(wallet: Wallet, deployer: AztecAddress) { const sponsoredPFCContract = await getSponsoredPFCContract(); - await deployMethod - .send({ - from: deployer, - contractAddressSalt: salt, - fee: { - paymentMethod: new SponsoredFeePaymentMethod( - sponsoredPFCContract.address - ), - }, - }) - .wait({ timeout: 120 }); + await deployMethod.send({ + from: deployer, + contractAddressSalt: salt, + fee: { + paymentMethod: new SponsoredFeePaymentMethod( + sponsoredPFCContract.address + ), + }, + wait: { timeout: 120 }, + }); await wallet.registerContract(contract, PrivateVotingContract.artifact); return { diff --git a/boxes/boxes/vite/src/hooks/useContract.tsx b/boxes/boxes/vite/src/hooks/useContract.tsx index e8bf933b4846..5b3c7aca373f 100644 --- a/boxes/boxes/vite/src/hooks/useContract.tsx +++ b/boxes/boxes/vite/src/hooks/useContract.tsx @@ -1,9 +1,9 @@ -import { useState } from "react"; -import { deployerEnv } from "../config"; +import { useState } from 'react'; +import { deployerEnv } from '../config'; -import { Contract } from "@aztec/aztec.js/contracts"; -import { Fr } from "@aztec/aztec.js/fields"; -import { toast } from "react-toastify"; +import { Contract } from '@aztec/aztec.js/contracts'; +import { Fr } from '@aztec/aztec.js/fields'; +import { toast } from 'react-toastify'; export function useContract() { const [wait, setWait] = useState(false); @@ -17,22 +17,19 @@ export function useContract() { const defaultAccountAddress = deployerEnv.getDefaultAccountAddress(); const salt = Fr.random(); - const { BoxReactContract } = await import("../../artifacts/BoxReact"); + const { BoxReactContract } = await import('../../artifacts/BoxReact'); - const tx = await BoxReactContract.deploy( - wallet, - Fr.random(), - defaultAccountAddress, - ).send({ + const deploymentPromise = BoxReactContract.deploy(wallet, Fr.random(), defaultAccountAddress).send({ from: defaultAccountAddress, contractAddressSalt: salt, }); - const contract = await toast.promise(tx.deployed(), { - pending: "Deploying contract...", + + const contract = await toast.promise(deploymentPromise, { + pending: 'Deploying contract...', success: { render: ({ data }) => `Address: ${data.address}`, }, - error: "Error deploying contract", + error: 'Error deploying contract', }); setContract(contract); diff --git a/boxes/boxes/vite/src/hooks/useNumber.tsx b/boxes/boxes/vite/src/hooks/useNumber.tsx index b89ffc279c36..8809b6555b42 100644 --- a/boxes/boxes/vite/src/hooks/useNumber.tsx +++ b/boxes/boxes/vite/src/hooks/useNumber.tsx @@ -1,7 +1,7 @@ -import { useState } from "react"; -import { Contract } from "@aztec/aztec.js/contracts"; -import { toast } from "react-toastify"; -import { deployerEnv } from "../config"; +import { useState } from 'react'; +import { Contract } from '@aztec/aztec.js/contracts'; +import { toast } from 'react-toastify'; +import { deployerEnv } from '../config'; export function useNumber({ contract }: { contract: Contract }) { const [wait, setWait] = useState(false); @@ -21,23 +21,18 @@ export function useNumber({ contract }: { contract: Contract }) { const setNumber = async (e: React.FormEvent) => { e.preventDefault(); - const el = e.currentTarget.elements.namedItem( - "numberToSet", - ) as HTMLInputElement; + const el = e.currentTarget.elements.namedItem('numberToSet') as HTMLInputElement; if (el) { setWait(true); const value = BigInt(el.value); const defaultAccountAddress = deployerEnv.getDefaultAccountAddress(); await toast.promise( - contract!.methods - .setNumber(value, defaultAccountAddress) - .send({ from: defaultAccountAddress }) - .wait(), + contract!.methods.setNumber(value, defaultAccountAddress).send({ from: defaultAccountAddress }), { - pending: "Setting number...", + pending: 'Setting number...', success: `Number set to: ${value}`, - error: "Error setting number", + error: 'Error setting number', }, ); setWait(false); diff --git a/docs/examples/ts/aztecjs_getting_started/index.ts b/docs/examples/ts/aztecjs_getting_started/index.ts index 00b566bb7458..bcdefc3753d1 100644 --- a/docs/examples/ts/aztecjs_getting_started/index.ts +++ b/docs/examples/ts/aztecjs_getting_started/index.ts @@ -20,17 +20,14 @@ const token = await TokenContract.deploy( alice.address, "TokenName", "TKN", - 18 -) - .send({ from: alice.address }) - .deployed(); + 18, +).send({ from: alice.address }); // docs:end:deploy // docs:start:mint await token.methods .mint_to_private(alice.address, 100) - .send({ from: alice.address }) - .wait(); + .send({ from: alice.address }); // docs:end:mint // docs:start:check_balances @@ -45,10 +42,7 @@ console.log(`Bob's balance: ${bobBalance}`); // docs:end:check_balances // docs:start:transfer -await token.methods - .transfer(bob.address, 10) - .send({ from: alice.address }) - .wait(); +await token.methods.transfer(bob.address, 10).send({ from: alice.address }); bobBalance = await token.methods .balance_of_private(bob.address) .simulate({ from: bob.address }); @@ -56,17 +50,13 @@ console.log(`Bob's balance: ${bobBalance}`); // docs:end:transfer // docs:start:set_minter -await token.methods - .set_minter(bob.address, true) - .send({ from: alice.address }) - .wait(); +await token.methods.set_minter(bob.address, true).send({ from: alice.address }); // docs:end:set_minter // docs:start:bob_mints await token.methods .mint_to_private(bob.address, 100) - .send({ from: bob.address }) - .wait(); + .send({ from: bob.address }); bobBalance = await token.methods .balance_of_private(bob.address) .simulate({ from: bob.address }); diff --git a/docs/examples/ts/bob_token_contract/index.ts b/docs/examples/ts/bob_token_contract/index.ts index 41def27ba441..963de8d2a36e 100644 --- a/docs/examples/ts/bob_token_contract/index.ts +++ b/docs/examples/ts/bob_token_contract/index.ts @@ -1,104 +1,113 @@ // docs:start:imports -import { BobTokenContract } from './artifacts/BobToken.js'; -import { AztecAddress } from '@aztec/aztec.js/addresses'; -import { createAztecNodeClient } from '@aztec/aztec.js/node'; -import { getInitialTestAccountsData } from '@aztec/accounts/testing'; -import { TestWallet } from '@aztec/test-wallet/server'; -import { openTmpStore } from '@aztec/kv-store/lmdb'; +import { BobTokenContract } from "./artifacts/BobToken.js"; +import { AztecAddress } from "@aztec/aztec.js/addresses"; +import { createAztecNodeClient } from "@aztec/aztec.js/node"; +import { getInitialTestAccountsData } from "@aztec/accounts/testing"; +import { TestWallet } from "@aztec/test-wallet/server"; // docs:end:imports // docs:start:get_balances -async function getBalances(contract: BobTokenContract, aliceAddress: AztecAddress, bobAddress: AztecAddress) { - await Promise.all([ - contract.methods - .public_balance_of(aliceAddress) - .simulate({ from: aliceAddress }), - contract.methods - .private_balance_of(aliceAddress) - .simulate({ from: aliceAddress }), - contract.methods - .public_balance_of(bobAddress) - .simulate({ from: bobAddress }), - contract.methods - .private_balance_of(bobAddress) - .simulate({ from: bobAddress }) - ]).then(([alicePublicBalance, alicePrivateBalance, bobPublicBalance, bobPrivateBalance]) => { - console.log(`📊 Alice has ${alicePublicBalance} public BOB tokens and ${alicePrivateBalance} private BOB tokens`); - console.log(`📊 Bob's Clinic has ${bobPublicBalance} public BOB tokens and ${bobPrivateBalance} private BOB tokens`); - }); +async function getBalances( + contract: BobTokenContract, + aliceAddress: AztecAddress, + bobAddress: AztecAddress, +) { + await Promise.all([ + contract.methods + .public_balance_of(aliceAddress) + .simulate({ from: aliceAddress }), + contract.methods + .private_balance_of(aliceAddress) + .simulate({ from: aliceAddress }), + contract.methods + .public_balance_of(bobAddress) + .simulate({ from: bobAddress }), + contract.methods + .private_balance_of(bobAddress) + .simulate({ from: bobAddress }), + ]).then( + ([ + alicePublicBalance, + alicePrivateBalance, + bobPublicBalance, + bobPrivateBalance, + ]) => { + console.log( + `📊 Alice has ${alicePublicBalance} public BOB tokens and ${alicePrivateBalance} private BOB tokens`, + ); + console.log( + `📊 Bob's Clinic has ${bobPublicBalance} public BOB tokens and ${bobPrivateBalance} private BOB tokens`, + ); + }, + ); } // docs:end:get_balances // docs:start:checkpoint_1 async function main() { - // Connect to local network - const node = createAztecNodeClient('http://localhost:8080'); + // Connect to local network + const node = createAztecNodeClient("http://localhost:8080"); - const wallet = await TestWallet.create(node); + const wallet = await TestWallet.create(node); - const [giggleWalletData, aliceWalletData, bobClinicWalletData] = await getInitialTestAccountsData(); - const giggleAccount = await wallet.createSchnorrAccount(giggleWalletData.secret, giggleWalletData.salt); - const aliceAccount = await wallet.createSchnorrAccount(aliceWalletData.secret, aliceWalletData.salt); - const bobClinicAccount = await wallet.createSchnorrAccount(bobClinicWalletData.secret, bobClinicWalletData.salt); + const [giggleWalletData, aliceWalletData, bobClinicWalletData] = + await getInitialTestAccountsData(); + const giggleAccountManager = await wallet.createSchnorrAccount( + giggleWalletData.secret, + giggleWalletData.salt, + ); + const aliceAccountManager = await wallet.createSchnorrAccount( + aliceWalletData.secret, + aliceWalletData.salt, + ); + const bobClinicAccountManager = await wallet.createSchnorrAccount( + bobClinicWalletData.secret, + bobClinicWalletData.salt, + ); - const giggleAddress = (await giggleAccount.getAccount()).getAddress(); - const aliceAddress = (await aliceAccount.getAccount()).getAddress(); - const bobClinicAddress = (await bobClinicAccount.getAccount()).getAddress(); + const giggleAddress = giggleAccountManager.address; + const aliceAddress = aliceAccountManager.address; + const bobClinicAddress = bobClinicAccountManager.address; - const bobToken = await BobTokenContract - .deploy( - wallet, - ) - .send({ from: giggleAddress }) - .deployed(); + const bobToken = await BobTokenContract.deploy(wallet).send({ + from: giggleAddress, + }); - await bobToken.methods - .mint_public(aliceAddress, 100n) - .send({ from: giggleAddress }) - .wait(); + await bobToken.methods + .mint_public(aliceAddress, 100n) + .send({ from: giggleAddress }); - await bobToken.methods - .transfer_public(bobClinicAddress, 10n) - .send({ from: aliceAddress }) - .wait(); - // docs:end:checkpoint_1 + await bobToken.methods + .transfer_public(bobClinicAddress, 10n) + .send({ from: aliceAddress }); + // docs:end:checkpoint_1 - // docs:start:checkpoint_2 - await bobToken.methods - .mint_public(aliceAddress, 100n) - .send({ from: giggleAddress }) - .wait(); - await getBalances(bobToken, aliceAddress, bobClinicAddress); + // docs:start:checkpoint_2 + await bobToken.methods + .mint_public(aliceAddress, 100n) + .send({ from: giggleAddress }); + await getBalances(bobToken, aliceAddress, bobClinicAddress); - await bobToken.methods - .transfer_public(bobClinicAddress, 10n) - .send({ from: aliceAddress }) - .wait(); - await getBalances(bobToken, aliceAddress, bobClinicAddress); + await bobToken.methods + .transfer_public(bobClinicAddress, 10n) + .send({ from: aliceAddress }); + await getBalances(bobToken, aliceAddress, bobClinicAddress); - await bobToken.methods - .public_to_private(90n) - .send({ from: aliceAddress }) - .wait(); - await getBalances(bobToken, aliceAddress, bobClinicAddress); + await bobToken.methods.public_to_private(90n).send({ from: aliceAddress }); + await getBalances(bobToken, aliceAddress, bobClinicAddress); - await bobToken.methods - .transfer_private(bobClinicAddress, 50n) - .send({ from: aliceAddress }) - .wait(); - await getBalances(bobToken, aliceAddress, bobClinicAddress); + await bobToken.methods + .transfer_private(bobClinicAddress, 50n) + .send({ from: aliceAddress }); + await getBalances(bobToken, aliceAddress, bobClinicAddress); - await bobToken.methods - .private_to_public(10n) - .send({ from: aliceAddress }) - .wait(); - await getBalances(bobToken, aliceAddress, bobClinicAddress); + await bobToken.methods.private_to_public(10n).send({ from: aliceAddress }); + await getBalances(bobToken, aliceAddress, bobClinicAddress); - await bobToken.methods - .mint_private(aliceAddress, 100n) - .send({ from: giggleAddress }) - .wait(); - await getBalances(bobToken, aliceAddress, bobClinicAddress); + await bobToken.methods + .mint_private(aliceAddress, 100n) + .send({ from: giggleAddress }); + await getBalances(bobToken, aliceAddress, bobClinicAddress); } main().catch(console.error); diff --git a/docs/examples/ts/token_bridge/index.ts b/docs/examples/ts/token_bridge/index.ts index 38070a064a53..65de2d720826 100644 --- a/docs/examples/ts/token_bridge/index.ts +++ b/docs/examples/ts/token_bridge/index.ts @@ -8,7 +8,10 @@ import { RollupContract } from "@aztec/ethereum/contracts"; import { deployL1Contract } from "@aztec/ethereum/deploy-l1-contract"; import { CheckpointNumber } from "@aztec/foundation/branded-types"; import { sha256ToField } from "@aztec/foundation/crypto/sha256"; -import { computeL2ToL1MessageHash, computeSecretHash } from "@aztec/stdlib/hash"; +import { + computeL2ToL1MessageHash, + computeSecretHash, +} from "@aztec/stdlib/hash"; import { computeL2ToL1MembershipWitness } from "@aztec/stdlib/messaging"; import { TestWallet } from "@aztec/test-wallet/server"; import { decodeEventLog, pad } from "@aztec/viem"; @@ -30,7 +33,7 @@ const aztecWallet = await TestWallet.create(node); const [accData] = await getInitialTestAccountsData(); const account = await aztecWallet.createSchnorrAccount( accData.secret, - accData.salt + accData.salt, ); console.log(`Account: ${account.address.toString()}\n`); @@ -50,13 +53,13 @@ console.log("Deploying L1 contracts...\n"); const { address: nftAddress } = await deployL1Contract( l1Client, SimpleNFT.abi, - SimpleNFT.bytecode.object as `0x${string}` + SimpleNFT.bytecode.object as `0x${string}`, ); const { address: portalAddress } = await deployL1Contract( l1Client, NFTPortal.abi, - NFTPortal.bytecode.object as `0x${string}` + NFTPortal.bytecode.object as `0x${string}`, ); console.log(`SimpleNFT: ${nftAddress}`); @@ -66,13 +69,14 @@ console.log(`NFTPortal: ${portalAddress}\n`); // docs:start:deploy_l2_contracts console.log("Deploying L2 contracts...\n"); -const l2Nft = await NFTPunkContract.deploy(aztecWallet, account.address) - .send({ from: account.address }) - .deployed(); +const l2Nft = await NFTPunkContract.deploy(aztecWallet, account.address).send({ + from: account.address, +}); -const l2Bridge = await NFTBridgeContract.deploy(aztecWallet, l2Nft.address) - .send({ from: account.address }) - .deployed(); +const l2Bridge = await NFTBridgeContract.deploy( + aztecWallet, + l2Nft.address, +).send({ from: account.address }); console.log(`L2 NFT: ${l2Nft.address.toString()}`); console.log(`L2 Bridge: ${l2Bridge.address.toString()}\n`); @@ -99,13 +103,11 @@ console.log("Setting up L2 bridge..."); await l2Bridge.methods .set_portal(EthAddress.fromString(portalAddress.toString())) - .send({ from: account.address }) - .wait(); + .send({ from: account.address }); await l2Nft.methods .set_minter(l2Bridge.address) - .send({ from: account.address }) - .wait(); + .send({ from: account.address }); console.log("Bridge configured\n"); // docs:end:initialize_l2_bridge @@ -150,7 +152,10 @@ const depositHash = await l1Client.writeContract({ address: portalAddress.toString() as `0x${string}`, abi: NFTPortal.abi, functionName: "depositToAztec", - args: [tokenId, pad(secretHash.toString() as `0x${string}`, { dir: "left", size: 32 })], + args: [ + tokenId, + pad(secretHash.toString() as `0x${string}`, { dir: "left", size: 32 }), + ], }); const depositReceipt = await l1Client.waitForTransactionReceipt({ hash: depositHash, @@ -187,19 +192,27 @@ const messageSentLogs = depositReceipt.logs return null; } }) - .filter((item): item is { log: any; decoded: any } => item !== null && (item.decoded as any).eventName === "MessageSent"); + .filter( + (item): item is { log: any; decoded: any } => + item !== null && (item.decoded as any).eventName === "MessageSent", + ); const messageLeafIndex = new Fr(messageSentLogs[0].decoded.args.index); // docs:end:get_message_leaf_index // docs:start:mine_blocks -async function mine2Blocks(aztecWallet: TestWallet, accountAddress: AztecAddress) { - await NFTPunkContract.deploy(aztecWallet, accountAddress) - .send({ from: accountAddress, contractAddressSalt: Fr.random() }) - .deployed(); - await NFTPunkContract.deploy(aztecWallet, accountAddress) - .send({ from: accountAddress, contractAddressSalt: Fr.random() }) - .deployed(); +async function mine2Blocks( + aztecWallet: TestWallet, + accountAddress: AztecAddress, +) { + await NFTPunkContract.deploy(aztecWallet, accountAddress).send({ + from: accountAddress, + contractAddressSalt: Fr.random(), + }); + await NFTPunkContract.deploy(aztecWallet, accountAddress).send({ + from: accountAddress, + contractAddressSalt: Fr.random(), + }); } // docs:end:mine_blocks @@ -217,8 +230,7 @@ console.log(` Notes count: ${notesBefore}`); console.log("Claiming NFT on L2..."); await l2Bridge.methods .claim(account.address, new Fr(Number(tokenId)), secret, messageLeafIndex) - .send({ from: account.address }) - .wait(); + .send({ from: account.address }); console.log("NFT claimed on L2\n"); // Check notes after claiming (should be 1) @@ -239,8 +251,7 @@ const recipientEthAddress = EthAddress.fromString(ownerEthAddress); const exitReceipt = await l2Bridge.methods .exit(new Fr(Number(tokenId)), recipientEthAddress) - .send({ from: account.address }) - .wait(); + .send({ from: account.address }); console.log(`Exit message sent (block: ${exitReceipt.blockNumber})\n`); @@ -258,7 +269,7 @@ console.log(` Notes count: ${notesAfterBurn}\n`); const tokenIdBuffer = new Fr(Number(tokenId)).toBuffer(); const recipientBuffer = Buffer.from( recipientEthAddress.toString().slice(2), - "hex" + "hex", ); const content = sha256ToField([tokenIdBuffer, recipientBuffer]); @@ -289,7 +300,7 @@ console.log(` Current proven block: ${provenBlockNumber}`); while (provenBlockNumber < exitReceipt.blockNumber!) { console.log( - ` Waiting... (proven: ${provenBlockNumber}, needed: ${exitReceipt.blockNumber})` + ` Waiting... (proven: ${provenBlockNumber}, needed: ${exitReceipt.blockNumber})`, ); await new Promise((resolve) => setTimeout(resolve, 10000)); // Wait 10 seconds provenBlockNumber = await node.getProvenBlockNumber(); @@ -300,16 +311,12 @@ console.log("Block proven!\n"); // Get the epoch for the exit block's checkpoint // In Aztec, checkpoint number equals block number (1:1 mapping) const epoch = await rollup.getEpochNumberForCheckpoint( - CheckpointNumber.fromBlockNumber(exitReceipt.blockNumber!) + CheckpointNumber.fromBlockNumber(exitReceipt.blockNumber!), ); console.log(` Epoch for block ${exitReceipt.blockNumber}: ${epoch}`); // Compute the membership witness using the message hash and epoch -const witness = await computeL2ToL1MembershipWitness( - node, - epoch, - msgLeaf -); +const witness = await computeL2ToL1MembershipWitness(node, epoch, msgLeaf); const siblingPathHex = witness!.siblingPath .toBufferArray() .map((buf: Buffer) => `0x${buf.toString("hex")}` as `0x${string}`); diff --git a/playground/src/components/navbar/TxPanel.tsx b/playground/src/components/navbar/TxPanel.tsx index 2d07f171f734..ea7a468aedc0 100644 --- a/playground/src/components/navbar/TxPanel.tsx +++ b/playground/src/components/navbar/TxPanel.tsx @@ -161,7 +161,7 @@ const transactionsList = css({ }); export function TxPanel() { - const { currentTx, playgroundDB, logs, wallet, setPendingTxUpdateCounter, pendingTxUpdateCounter } = + const { currentTx, playgroundDB, logs, node, setPendingTxUpdateCounter, pendingTxUpdateCounter } = useContext(AztecContext); const [currentFunFactIndex, setCurrentFunFactIndex] = useState(0); @@ -208,7 +208,7 @@ export function TxPanel() { // Update pending transactions status useEffect(() => { const refreshPendingTx = async () => { - if (!wallet || !playgroundDB) { + if (!node || !playgroundDB) { return; } @@ -216,7 +216,7 @@ export function TxPanel() { const pendingTxs = transactions.filter(tx => tx.status === 'pending' && tx.date + buffer < Date.now()); for (const tx of pendingTxs) { - const txReceipt = await queryTxReceipt(tx, wallet); + const txReceipt = await queryTxReceipt(tx, node); if (txReceipt && txReceipt.status !== 'pending') { await playgroundDB.updateTxStatus(tx.txHash, txReceipt.status); setPendingTxUpdateCounter(pendingTxUpdateCounter + 1); @@ -224,7 +224,7 @@ export function TxPanel() { } }; - if (playgroundDB && wallet) { + if (playgroundDB && node) { refreshPendingTx(); } @@ -232,7 +232,7 @@ export function TxPanel() { return () => clearInterval(interval); /* eslint-disable-next-line react-hooks/exhaustive-deps */ - }, [transactions, playgroundDB, wallet]); + }, [transactions, playgroundDB, node]); useEffect(() => { if (currentTx?.status === 'success') { diff --git a/playground/src/hooks/useTransaction.tsx b/playground/src/hooks/useTransaction.tsx index 556cba0187ae..202c6017481f 100644 --- a/playground/src/hooks/useTransaction.tsx +++ b/playground/src/hooks/useTransaction.tsx @@ -1,21 +1,29 @@ import { useContext } from 'react'; import { AztecContext } from '../aztecContext'; import type { AztecAddress } from '@aztec/aztec.js/addresses'; -import type { ContractFunctionInteraction, DeployMethod, DeployOptions, SendInteractionOptions } from '@aztec/aztec.js/contracts'; -import { TxReceipt, TxStatus } from '@aztec/aztec.js/tx'; +import { + ContractFunctionInteraction, + DeployMethod, + type InteractionWaitOptions, + type SendInteractionOptions, + type DeployOptions, + NO_WAIT, +} from '@aztec/aztec.js/contracts'; +import { TxHash, TxReceipt, TxStatus } from '@aztec/aztec.js/tx'; import { TimeoutError } from '@aztec/foundation/error'; import { useNotifications } from '@toolpad/core/useNotifications'; import { TX_TIMEOUT } from '../constants'; +import { waitForTx } from '@aztec/aztec.js/node'; export function useTransaction() { - const { playgroundDB, currentTx, setCurrentTx } = useContext(AztecContext); + const { playgroundDB, currentTx, setCurrentTx, node } = useContext(AztecContext); const notifications = useNotifications(); - async function sendTx( + async function sendTx( name: string, interaction: ContractFunctionInteraction | DeployMethod, contractAddress: AztecAddress, - opts: SendInteractionOptions | DeployOptions, + opts: SendInteractionOptions | DeployOptions, displayOptions?: { showNotifications?: boolean; }, @@ -35,16 +43,23 @@ export function useTransaction() { notifications.show('Sending transaction...', { severity: 'info', }); - const tx = await interaction.send(opts); + let txHash: TxHash; + + if (interaction instanceof DeployMethod) { + const { from, fee, ...deployOpts } = opts as DeployOptions; + txHash = await interaction.send({ from, fee, ...deployOpts, wait: NO_WAIT }); + } else { + const { from, fee, authWitnesses, capsules } = opts as SendInteractionOptions; + txHash = await interaction.send({ from, fee, authWitnesses, capsules, wait: NO_WAIT }); + } - txHash = await tx.getTxHash(); setCurrentTx({ ...currentTx, ...{ txHash, status: 'sending' }, }); // TODO: Don't send the tx if the user has cancelled the transaction - receipt = await tx.wait({ dontThrowOnRevert: true, timeout: TX_TIMEOUT, interval: 5 }); + receipt = await waitForTx(node, txHash, { dontThrowOnRevert: true, timeout: TX_TIMEOUT, interval: 5 }); if (showNotifications && receipt.hasExecutionSucceeded()) { notifications.show('Congratulations! Your transaction was included in a block.', { diff --git a/playground/src/utils/txs.ts b/playground/src/utils/txs.ts index 76a3cf63f021..f8a7f8466a35 100644 --- a/playground/src/utils/txs.ts +++ b/playground/src/utils/txs.ts @@ -1,6 +1,6 @@ import { AztecAddress } from '@aztec/aztec.js/addresses'; +import type { AztecNode } from '@aztec/aztec.js/node'; import { TxHash, TxReceipt, TxStatus } from '@aztec/aztec.js/tx'; -import type { Wallet } from '@aztec/aztec.js/wallet'; export type UserTx = { txHash?: TxHash; @@ -12,8 +12,8 @@ export type UserTx = { contractAddress: AztecAddress; }; -export async function queryTxReceipt(tx: UserTx, wallet: Wallet) { +export async function queryTxReceipt(tx: UserTx, node: AztecNode) { const txHash = await tx.txHash; - const txReceipt = await wallet.getTxReceipt(txHash); + const txReceipt = await node.getTxReceipt(txHash); return txReceipt; } diff --git a/yarn-project/aztec.js/src/api/contract.ts b/yarn-project/aztec.js/src/api/contract.ts index 39c5ceabfa71..0b5ddc15129a 100644 --- a/yarn-project/aztec.js/src/api/contract.ts +++ b/yarn-project/aztec.js/src/api/contract.ts @@ -10,13 +10,21 @@ * or can be queried via `simulate()`. * * ```ts - * const contract = await Contract.deploy(wallet, MyContractArtifact, [...constructorArgs]).send().deployed(); + * // Deploy and get the contract instance directly (default behavior) + * const contract = await Contract.deploy(wallet, MyContractArtifact, [...constructorArgs]).send({ from: accountAddress }); * console.log(`Contract deployed at ${contract.address}`); + * + * // Or get the full receipt with contract and instance + * const receipt = await Contract.deploy(wallet, MyContractArtifact, [...constructorArgs]).send({ + * from: accountAddress, + * wait: { returnReceipt: true } + * }); + * console.log(`Contract deployed at ${receipt.contract.address}`); * ``` * * ```ts * const contract = Contract.at(address, MyContractArtifact, wallet); - * await contract.methods.mint(1000, owner).send().wait(); + * await contract.methods.mint(1000, owner).send({ from: accountAddress }); * console.log(`Total supply is now ${await contract.methods.totalSupply().simulate()}`); * ``` * @@ -25,9 +33,8 @@ * a transaction to the network via the `send` method, but you can also `simulate` it without sending, * or obtaining the `request` for aggregating into a {@link BatchCall}. * - * The result of `send`ing a transaction is a {@link SentTx} object, from which you can get the - * transaction hash, or simply `wait` until the transaction is mined and the local PXE - * has synchronized its changes. + * The `send` method returns a {@link TxReceipt} by default (waits for the transaction to be mined). + * If you pass `wait: NO_WAIT` in the options, it will return a {@link TxHash} immediately without waiting. * * @remarks If you are using typescript, consider using the * {@link https://docs.aztec.network/developers/aztec-nr/how_to_compile_contract#use-generated-interfaces | autogenerated type-safe interfaces} @@ -39,27 +46,35 @@ export { Contract } from '../contract/contract.js'; export { ContractFunctionInteraction } from '../contract/contract_function_interaction.js'; export { + NO_WAIT, + type NoWait, type RequestInteractionOptions, type SendInteractionOptions, type ProfileInteractionOptions, type SimulateInteractionOptions, type InteractionFeeOptions, + type InteractionWaitOptions, type GasSettingsOption, + type SendReturn, + type SimulationReturn, toProfileOptions, toSendOptions, toSimulateOptions, } from '../contract/interaction_options.js'; -export { DefaultWaitOpts, SentTx, type WaitOpts } from '../contract/sent_tx.js'; +export { DefaultWaitOpts, type WaitOpts } from '../contract/wait_opts.js'; export { ContractBase, type ContractMethod, type ContractStorageLayout } from '../contract/contract_base.js'; export { BatchCall } from '../contract/batch_call.js'; export { type DeployOptions, + type DeployReturn, + type DeployTxReceipt, + type DeployWaitOptions, + type DeployInteractionWaitOptions, DeployMethod, type RequestDeployOptions, type SimulateDeployOptions, } from '../contract/deploy_method.js'; -export { DeploySentTx } from '../contract/deploy_sent_tx.js'; export { waitForProven, type WaitForProvenOpts, DefaultWaitForProvenOpts } from '../contract/wait_for_proven.js'; export { getGasLimits } from '../contract/get_gas_limits.js'; diff --git a/yarn-project/aztec.js/src/api/node.ts b/yarn-project/aztec.js/src/api/node.ts index f750fb041eb5..c6116b039dbc 100644 --- a/yarn-project/aztec.js/src/api/node.ts +++ b/yarn-project/aztec.js/src/api/node.ts @@ -3,18 +3,22 @@ * * The primary function is {@link createAztecNodeClient}, which creates a JSON-RPC client * that connects to a running Aztec node instance. Use {@link waitForNode} to wait for - * the node to be ready before proceeding. + * the node to be ready before proceeding, and {@link waitForTx} to wait for a transaction + * to be mined. * * @example * ```ts - * import { createAztecNodeClient, waitForNode } from '@aztec/aztec.js/node'; + * import { createAztecNodeClient, waitForNode, waitForTx } from '@aztec/aztec.js/node'; * * const node = createAztecNodeClient('http://localhost:8080'); * await waitForNode(node); * const blockNumber = await node.getBlockNumber(); + * + * // Wait for a transaction + * const receipt = await waitForTx(node, txHash); * ``` * * @packageDocumentation */ -export { createAztecNodeClient, waitForNode, type AztecNode } from '../utils/node.js'; +export { createAztecNodeClient, waitForNode, waitForTx, type AztecNode } from '../utils/node.js'; export { type NodeInfo } from '@aztec/stdlib/contract'; diff --git a/yarn-project/aztec.js/src/api/wallet.ts b/yarn-project/aztec.js/src/api/wallet.ts index e5768fba6025..cc04e4223fdd 100644 --- a/yarn-project/aztec.js/src/api/wallet.ts +++ b/yarn-project/aztec.js/src/api/wallet.ts @@ -17,6 +17,7 @@ export { ExecutionPayloadSchema, GasSettingsOptionSchema, WalletSimulationFeeOptionSchema, + WaitOptsSchema, SendOptionsSchema, SimulateOptionsSchema, ProfileOptionsSchema, diff --git a/yarn-project/aztec.js/src/contract/base_contract_interaction.ts b/yarn-project/aztec.js/src/contract/base_contract_interaction.ts index 5197b60ae3c3..8e47f1eb7cfe 100644 --- a/yarn-project/aztec.js/src/contract/base_contract_interaction.ts +++ b/yarn-project/aztec.js/src/contract/base_contract_interaction.ts @@ -1,10 +1,16 @@ import { createLogger } from '@aztec/foundation/log'; import type { AuthWitness } from '@aztec/stdlib/auth-witness'; -import type { Capsule, ExecutionPayload } from '@aztec/stdlib/tx'; +import type { Capsule, ExecutionPayload, TxReceipt } from '@aztec/stdlib/tx'; import type { Wallet } from '../wallet/wallet.js'; -import { type RequestInteractionOptions, type SendInteractionOptions, toSendOptions } from './interaction_options.js'; -import { SentTx } from './sent_tx.js'; +import { + type InteractionWaitOptions, + type RequestInteractionOptions, + type SendInteractionOptions, + type SendInteractionOptionsWithoutWait, + type SendReturn, + toSendOptions, +} from './interaction_options.js'; /** * Base class for an interaction with a contract, be it a deployment, a function call, or a batch. @@ -30,20 +36,26 @@ export abstract class BaseContractInteraction { // docs:start:send /** * Sends a transaction to the contract function with the specified options. - * This function throws an error if called on a utility function. - * It creates and signs the transaction if necessary, and returns a SentTx instance, - * which can be used to track the transaction status, receipt, and events. + * By default, waits for the transaction to be mined and returns the receipt (or custom type). * @param options - An object containing 'from' property representing - * the AztecAddress of the sender and optional fee configuration - * @returns A SentTx instance for tracking the transaction status and information. + * the AztecAddress of the sender, optional fee configuration, and optional wait settings + * @returns TReturn (if wait is undefined/WaitOpts) or TxHash (if wait is NO_WAIT) */ - public send(options: SendInteractionOptions): SentTx { + // Overload for when wait is not specified at all - returns TReturn + public send(options: SendInteractionOptionsWithoutWait): Promise; + // Generic overload for explicit wait values + // eslint-disable-next-line jsdoc/require-jsdoc + public send( + options: SendInteractionOptions, + ): Promise>; + // eslint-disable-next-line jsdoc/require-jsdoc + public async send( + options: SendInteractionOptions, + ): Promise> { // docs:end:send - const sendTx = async () => { - const executionPayload = await this.request(options); - const sendOptions = toSendOptions(options); - return this.wallet.sendTx(executionPayload, sendOptions); - }; - return new SentTx(this.wallet, sendTx); + const executionPayload = await this.request(options); + const sendOptions = toSendOptions(options); + + return (await this.wallet.sendTx(executionPayload, sendOptions as any)) as SendReturn; } } diff --git a/yarn-project/aztec.js/src/contract/contract.test.ts b/yarn-project/aztec.js/src/contract/contract.test.ts index 1b23dbc6f9cc..f72a523a3fb1 100644 --- a/yarn-project/aztec.js/src/contract/contract.test.ts +++ b/yarn-project/aztec.js/src/contract/contract.test.ts @@ -28,7 +28,7 @@ describe('Contract Class', () => { let contractInstance: ContractInstanceWithAddress; const mockTxRequest = { type: 'TxRequest' } as any as TxExecutionRequest; - const mockTxHash = { type: 'TxHash' } as any as TxHash; + const _mockTxHash = { type: 'TxHash' } as any as TxHash; const mockTxReceipt = { type: 'TxReceipt' } as any as TxReceipt; const mockTxSimulationResult = { type: 'TxSimulationResult', result: 1n } as any as TxSimulationResult; const mockUtilityResultValue = { result: [new Fr(42)] } as any as UtilitySimulationResult; @@ -136,21 +136,16 @@ describe('Contract Class', () => { wallet.simulateTx.mockResolvedValue(mockTxSimulationResult); account.createTxExecutionRequest.mockResolvedValue(mockTxRequest); wallet.registerContract.mockResolvedValue(contractInstance); - wallet.sendTx.mockResolvedValue(mockTxHash); + wallet.sendTx.mockResolvedValue(mockTxReceipt); wallet.simulateUtility.mockResolvedValue(mockUtilityResultValue); - wallet.getTxReceipt.mockResolvedValue(mockTxReceipt); - wallet.sendTx.mockResolvedValue(mockTxHash); }); it('should create and send a contract method tx', async () => { const fooContract = Contract.at(contractAddress, defaultArtifact, wallet); const param0 = 12; const param1 = 345n; - const sentTx = fooContract.methods.bar(param0, param1).send({ from: account.getAddress() }); - const txHash = await sentTx.getTxHash(); - const receipt = await sentTx.getReceipt(); + const receipt = await fooContract.methods.bar(param0, param1).send({ from: account.getAddress() }); - expect(txHash).toBe(mockTxHash); expect(receipt).toBe(mockTxReceipt); expect(wallet.sendTx).toHaveBeenCalledTimes(1); }); diff --git a/yarn-project/aztec.js/src/contract/deploy_method.ts b/yarn-project/aztec.js/src/contract/deploy_method.ts index 7348ee8341d2..5c4d9544aa2e 100644 --- a/yarn-project/aztec.js/src/contract/deploy_method.ts +++ b/yarn-project/aztec.js/src/contract/deploy_method.ts @@ -9,27 +9,46 @@ import { getContractInstanceFromInstantiationParams, } from '@aztec/stdlib/contract'; import type { PublicKeys } from '@aztec/stdlib/keys'; -import { type Capsule, type TxProfileResult, collectOffchainEffects } from '@aztec/stdlib/tx'; +import { type Capsule, TxHash, type TxProfileResult, type TxReceipt, collectOffchainEffects } from '@aztec/stdlib/tx'; import { ExecutionPayload, mergeExecutionPayloads } from '@aztec/stdlib/tx'; import { publishContractClass } from '../deployment/publish_class.js'; import { publishInstance } from '../deployment/publish_instance.js'; -import type { Wallet } from '../wallet/wallet.js'; +import type { SendOptions, Wallet } from '../wallet/wallet.js'; import { BaseContractInteraction } from './base_contract_interaction.js'; import type { ContractBase } from './contract_base.js'; import { ContractFunctionInteraction } from './contract_function_interaction.js'; -import { DeploySentTx } from './deploy_sent_tx.js'; import { getGasLimits } from './get_gas_limits.js'; import { + NO_WAIT, + type NoWait, type ProfileInteractionOptions, type RequestInteractionOptions, - type SendInteractionOptions, + type SendInteractionOptionsWithoutWait, type SimulationInteractionFeeOptions, type SimulationReturn, toProfileOptions, toSendOptions, toSimulateOptions, } from './interaction_options.js'; +import type { WaitOpts } from './wait_opts.js'; + +/** + * Wait options specific to deployment transactions. + * Extends WaitOpts with a flag to return the full receipt instead of just the contract. + */ +export type DeployWaitOptions = WaitOpts & { + /** If true, return the full DeployTxReceipt instead of just the contract. Defaults to false. */ + returnReceipt?: boolean; +}; + +/** + * Type for wait options in deployment interactions. + * - NO_WAIT symbol: Don't wait, return TxHash immediately + * - DeployWaitOptions: Wait with custom options + * - undefined: Wait with default options + */ +export type DeployInteractionWaitOptions = NoWait | DeployWaitOptions | undefined; /** * Options for deploying a contract on the Aztec network. @@ -55,21 +74,34 @@ export type RequestDeployOptions = RequestInteractionOptions & { }; /** - * Extends the deployment options with the required parameters to send the transaction + * Base deployment options without wait parameter. */ -export type DeployOptions = Omit & { +export type DeployOptionsWithoutWait = Omit & { /** * Set to true to *not* include the sender in the address computation. This option * is mutually exclusive with "deployer" */ universalDeploy?: boolean; -} & Pick; +} & Pick; + +/** + * Extends the deployment options with the required parameters to send the transaction. + */ +export type DeployOptions = DeployOptionsWithoutWait & { + /** + * Options for waiting for the transaction to be mined. + * - undefined (default): wait with default options and return the contract instance + * - DeployWaitOptions: wait with custom options and return contract or receipt based on returnReceipt flag + * - NO_WAIT: return TxHash immediately without waiting + */ + wait?: W; +}; /** * Options for simulating the deployment of a contract * Allows skipping certain validations and computing gas estimations */ -export type SimulateDeployOptions = Omit & { +export type SimulateDeployOptions = Omit & { /** The fee options for the transaction. */ fee?: SimulationInteractionFeeOptions; /** Simulate without checking for the validity of the resulting transaction, @@ -83,6 +115,29 @@ export type SimulateDeployOptions = Omit & { includeMetadata?: boolean; }; +/** Receipt for a deployment transaction with the deployed contract instance. */ +export type DeployTxReceipt = TxReceipt & { + /** Type-safe wrapper around the deployed contract instance, linked to the deployment wallet */ + contract: TContract; + /** The deployed contract instance with address and metadata. */ + instance: ContractInstanceWithAddress; +}; + +/** + * Represents the result type of deploying a contract. + * - If wait is NO_WAIT, returns TxHash immediately. + * - If wait has returnReceipt: true, returns DeployTxReceipt after waiting. + * - Otherwise (undefined or DeployWaitOptions without returnReceipt), returns TContract after waiting. + */ +export type DeployReturn = W extends NoWait + ? TxHash + : W extends { + // eslint-disable-next-line jsdoc/require-jsdoc + returnReceipt: true; + } + ? DeployTxReceipt + : TContract; + /** * Contract interaction for deployment. * Handles class publication, instance publication, and initialization of the contract. @@ -92,8 +147,6 @@ export type SimulateDeployOptions = Omit & { * then technically the contract has already been "created", and all of the contract's * functions (private and utility) can be interacted-with immediately, without any * "deployment tx". - * - * Extends the BaseContractInteraction class. */ export class DeployMethod extends BaseContractInteraction { /** The contract instance to be deployed. */ @@ -142,13 +195,30 @@ export class DeployMethod extends return finalExecutionPayload; } - convertDeployOptionsToRequestOptions(options: DeployOptions): RequestDeployOptions { + convertDeployOptionsToRequestOptions(options: DeployOptionsWithoutWait): RequestDeployOptions { return { ...options, deployer: !options?.universalDeploy ? options.from : undefined, }; } + /** + * Converts DeployOptions to SendOptions, stripping out the returnReceipt flag if present. + * @param options - Deploy options with wait parameter + * @returns Send options with wait parameter + */ + private convertDeployOptionsToSendOptions( + options: DeployOptions, + // eslint-disable-next-line jsdoc/require-jsdoc + ): SendOptions { + return { + ...toSendOptions({ + ...options, + wait: options.wait as any, + }), + } as any; + } + /** * Adds this contract to the wallet and returns the Contract object. * @param options - Deployment options. @@ -232,20 +302,42 @@ export class DeployMethod extends /** * Send a contract deployment transaction (initialize and/or publish) using the provided options. - * This function extends the 'send' method from the ContractFunctionInteraction class, - * allowing us to send a transaction specifically for contract deployment. + * By default, waits for the transaction to be mined and returns the deployed contract instance. * * @param options - An object containing various deployment options such as contractAddressSalt and from. - * @returns A SentTx object that returns the receipt and the deployed contract instance. + * @returns TxHash (if wait is NO_WAIT), TContract (if wait is undefined or doesn't have returnReceipt), or DeployTxReceipt (if wait.returnReceipt is true) */ - public override send(options: DeployOptions): DeploySentTx { - const sendTx = async () => { - const executionPayload = await this.request(this.convertDeployOptionsToRequestOptions(options)); - const sendOptions = toSendOptions(options); - return this.wallet.sendTx(executionPayload, sendOptions); - }; - this.log.debug(`Sent deployment tx of ${this.artifact.name} contract`); - return new DeploySentTx(this.wallet, sendTx, this.postDeployCtor, () => this.getInstance(options)); + // Overload for when wait is not specified at all - returns the contract + public override send(options: DeployOptionsWithoutWait): Promise; + // Generic overload for explicit wait values + // eslint-disable-next-line jsdoc/require-jsdoc + public override send( + options: DeployOptions, + ): Promise>; + // eslint-disable-next-line jsdoc/require-jsdoc + public override async send(options: DeployOptions): Promise { + const executionPayload = await this.request(this.convertDeployOptionsToRequestOptions(options)); + const sendOptions = this.convertDeployOptionsToSendOptions(options); + + if (options.wait === NO_WAIT) { + const txHash = await this.wallet.sendTx(executionPayload, sendOptions as SendOptions); + this.log.debug(`Sent deployment tx ${txHash.hash} of ${this.artifact.name} contract`); + return txHash; + } + + const receipt = await this.wallet.sendTx(executionPayload, sendOptions as SendOptions); + this.log.debug(`Deployed ${this.artifact.name} contract in tx ${receipt.txHash}`); + + // Attach contract instance + const instance = await this.getInstance(options); + const contract = this.postDeployCtor(instance, this.wallet) as TContract; + + // Return full receipt if requested, otherwise just the contract + if (options.wait && typeof options.wait === 'object' && options.wait.returnReceipt) { + return { ...receipt, contract, instance }; + } + + return contract; } /** @@ -296,7 +388,7 @@ export class DeployMethod extends * * @returns An object containing the function return value and profile result. */ - public async profile(options: DeployOptions & ProfileInteractionOptions): Promise { + public async profile(options: DeployOptionsWithoutWait & ProfileInteractionOptions): Promise { const executionPayload = await this.request(this.convertDeployOptionsToRequestOptions(options)); return await this.wallet.profileTx(executionPayload, { ...toProfileOptions(options), diff --git a/yarn-project/aztec.js/src/contract/deploy_sent_tx.ts b/yarn-project/aztec.js/src/contract/deploy_sent_tx.ts deleted file mode 100644 index 69d075377596..000000000000 --- a/yarn-project/aztec.js/src/contract/deploy_sent_tx.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { createLogger } from '@aztec/foundation/log'; -import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract'; -import { type TxHash, TxReceipt } from '@aztec/stdlib/tx'; - -import type { Wallet } from '../wallet/wallet.js'; -import type { ContractBase } from './contract_base.js'; -import { SentTx, type WaitOpts } from './sent_tx.js'; - -/** Options related to waiting for a deployment tx. */ -export type DeployedWaitOpts = WaitOpts & { - /** Wallet to use for creating a contract instance. Uses the one set in the deployer constructor if not set. */ - wallet?: Wallet; -}; - -/** Extends a transaction receipt with a contract instance that represents the newly deployed contract. */ -export class DeployTxReceipt extends TxReceipt { - constructor( - /** Instance of the newly deployed contract. */ - public contract: TContract, - /** The deployed contract instance with address and metadata. */ - public instance: ContractInstanceWithAddress, - /** Arguments for the tx receipt */ - ...args: ConstructorParameters - ) { - super(...args); - } - - /** - * Creates a new instance out of a TxReceipt - * @param contract - The contract class - * @param instance - The deployed contract instance with address and metadata - * @param receipt - The transaction receipt - * @returns A new DeployTxReceipt instance - */ - static fromTxReceipt( - contract: TContract, - instance: ContractInstanceWithAddress, - receipt: TxReceipt, - ): DeployTxReceipt { - return new DeployTxReceipt( - contract, - instance, - receipt.txHash, - receipt.status, - receipt.executionResult, - receipt.error, - receipt.transactionFee, - receipt.blockHash, - receipt.blockNumber, - ); - } -} - -/** - * A contract deployment transaction sent to the network, extending SentTx with methods to publish a contract instance. - */ -export class DeploySentTx extends SentTx { - private log = createLogger('aztecjs:deploy_sent_tx'); - - constructor( - wallet: Wallet, - sendTx: () => Promise, - private postDeployCtor: (instance: ContractInstanceWithAddress, wallet: Wallet) => TContract, - /** A getter for the deployed contract instance */ - private instanceGetter: () => Promise, - ) { - super(wallet, sendTx); - } - - /** - * Returns the contract instance for this deployment. - * @returns The deployed contract instance with address and metadata. - */ - public async getInstance(): Promise { - return await this.instanceGetter(); - } - - /** - * Awaits for the tx to be mined and returns the contract instance. Throws if tx is not mined. - * @param opts - Options for configuring the waiting for the tx to be mined. - * @returns The deployed contract instance. - */ - public async deployed(opts?: DeployedWaitOpts): Promise { - const receipt = await this.wait(opts); - this.log.info(`Contract ${receipt.instance.address.toString()} successfully deployed.`); - return receipt.contract; - } - - /** - * Awaits for the tx to be mined and returns the receipt along with a contract instance. Throws if tx is not mined. - * @param opts - Options for configuring the waiting for the tx to be mined. - * @returns The transaction receipt with the deployed contract instance. - */ - public override async wait(opts?: DeployedWaitOpts): Promise> { - const receipt = await super.wait(opts); - // In the case of DeploySentTx we have a guarantee that this.walletOrNode is a Wallet so we can cast it to Wallet. - const contractWallet = opts?.wallet ?? (this.walletOrNode as Wallet); - if (!contractWallet) { - throw new Error(`A wallet is required for creating a contract instance`); - } - const instance = await this.instanceGetter(); - const contract = this.postDeployCtor(instance, contractWallet) as TContract; - return DeployTxReceipt.fromTxReceipt(contract, instance, receipt); - } -} diff --git a/yarn-project/aztec.js/src/contract/interaction_options.ts b/yarn-project/aztec.js/src/contract/interaction_options.ts index c3a71233bbd4..2651c9f5f49d 100644 --- a/yarn-project/aztec.js/src/contract/interaction_options.ts +++ b/yarn-project/aztec.js/src/contract/interaction_options.ts @@ -2,10 +2,11 @@ import type { FieldsOf } from '@aztec/foundation/types'; import type { AuthWitness } from '@aztec/stdlib/auth-witness'; import type { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { GasSettings } from '@aztec/stdlib/gas'; -import type { Capsule, OffchainEffect, SimulationStats } from '@aztec/stdlib/tx'; +import type { Capsule, OffchainEffect, SimulationStats, TxHash, TxReceipt } from '@aztec/stdlib/tx'; import type { FeePaymentMethod } from '../fee/fee_payment_method.js'; import type { ProfileOptions, SendOptions, SimulateOptions } from '../wallet/index.js'; +import type { WaitOpts } from './wait_opts.js'; /** * Options used to tweak the simulation and add gas estimation capabilities @@ -55,15 +56,47 @@ export type RequestInteractionOptions = { }; /** - * Represents options for calling a (constrained) function in a contract. + * Constant for explicitly not waiting for transaction confirmation. + * We use this instead of false to avoid confusion with falsy checks. + */ +export const NO_WAIT = 'NO_WAIT' as const; + +/** + * Type for the NO_WAIT constant. + */ +export type NoWait = typeof NO_WAIT; + +/** + * Type for wait options in interactions. + * - NO_WAIT symbol: Don't wait for confirmation, return TxHash immediately + * - WaitOpts object: Wait with custom options and return receipt/result + * - undefined: Wait with default options and return receipt/result + */ +export type InteractionWaitOptions = NoWait | WaitOpts | undefined; + +/** + * Base options for calling a (constrained) function in a contract, without wait parameter. */ -export type SendInteractionOptions = RequestInteractionOptions & { +export type SendInteractionOptionsWithoutWait = RequestInteractionOptions & { /** The sender's Aztec address. */ from: AztecAddress; /** The fee options for the transaction. */ fee?: InteractionFeeOptions; }; +/** + * Represents options for calling a (constrained) function in a contract. + */ +export type SendInteractionOptions = SendInteractionOptionsWithoutWait & { + /** + * Whether to wait for the transaction to be mined. + * - undefined (default): wait with default options and return TxReceipt + * - WaitOpts object: wait with custom options and return TxReceipt + * - NO_WAIT: return txHash immediately without waiting + */ + wait?: W; +}; + /** * Represents the options for simulating a contract function interaction. * Allows specifying the address from which the method should be called. @@ -110,11 +143,22 @@ export type SimulationReturn = T extends true } : any; +/** + * Represents the result type of sending a transaction. + * If `wait` is NO_WAIT, returns TxHash immediately without waiting. + * If `wait` is undefined or WaitOpts, returns TReturn (defaults to TxReceipt) after waiting. + */ +export type SendReturn = T extends NoWait ? TxHash : TReturn; + /** * Transforms and cleans up the higher level SendInteractionOptions defined by the interaction into * SendOptions, which are the ones that can be serialized and forwarded to the wallet + * @param options - The send interaction options with optional wait parameter + * @returns The send options to forward to the wallet */ -export function toSendOptions(options: SendInteractionOptions): SendOptions { +export function toSendOptions( + options: SendInteractionOptions, +): SendOptions { return { ...options, fee: { @@ -126,6 +170,7 @@ export function toSendOptions(options: SendInteractionOptions): SendOptions { ...options.fee?.gasSettings, }, }, + wait: options.wait, // Pass through wait option }; } diff --git a/yarn-project/aztec.js/src/contract/sent_tx.test.ts b/yarn-project/aztec.js/src/contract/sent_tx.test.ts deleted file mode 100644 index 9b060ec9ac17..000000000000 --- a/yarn-project/aztec.js/src/contract/sent_tx.test.ts +++ /dev/null @@ -1,234 +0,0 @@ -import { BlockNumber } from '@aztec/foundation/branded-types'; -import { Fr } from '@aztec/foundation/curves/bn254'; -import type { AztecNode } from '@aztec/stdlib/interfaces/client'; -import { TxExecutionResult, TxHash, TxReceipt, TxStatus } from '@aztec/stdlib/tx'; - -import { type MockProxy, mock } from 'jest-mock-extended'; - -import type { Wallet } from '../wallet/index.js'; -import { SentTx } from './sent_tx.js'; - -describe('SentTx', () => { - let wallet: MockProxy; - let node: MockProxy; - let sentTx: SentTx; - - const txHashGetter = () => Promise.resolve(new TxHash(new Fr(1n))); - - beforeEach(() => { - wallet = mock(); - node = mock(); - }); - - describe('wait with Wallet', () => { - let txReceipt: TxReceipt; - beforeEach(() => { - txReceipt = new TxReceipt( - TxHash.random(), - TxStatus.CHECKPOINTED, - TxExecutionResult.SUCCESS, - undefined, - undefined, - undefined, - BlockNumber(20), - ); - wallet.getTxReceipt.mockResolvedValue(txReceipt); - sentTx = new SentTx(wallet, txHashGetter); - }); - - it('throws if tx is dropped', async () => { - const droppedReceipt = new TxReceipt(TxHash.random(), TxStatus.DROPPED, undefined, 'Tx dropped'); - wallet.getTxReceipt.mockResolvedValue(droppedReceipt); - await expect(sentTx.wait({ timeout: 1, interval: 0.4, ignoreDroppedReceiptsFor: 0 })).rejects.toThrow(/dropped/); - }); - - it('throws if tx reverts and dontThrowOnRevert is false', async () => { - const revertedReceipt = new TxReceipt( - TxHash.random(), - TxStatus.CHECKPOINTED, - TxExecutionResult.APP_LOGIC_REVERTED, - undefined, - undefined, - undefined, - BlockNumber(20), - ); - wallet.getTxReceipt.mockResolvedValue(revertedReceipt); - await expect(sentTx.wait({ timeout: 1, interval: 0.4 })).rejects.toThrow(/reverted/); - }); - - it('does not throw if tx reverts and dontThrowOnRevert is true', async () => { - const revertedReceipt = new TxReceipt( - TxHash.random(), - TxStatus.CHECKPOINTED, - TxExecutionResult.APP_LOGIC_REVERTED, - undefined, - undefined, - undefined, - BlockNumber(20), - ); - wallet.getTxReceipt.mockResolvedValue(revertedReceipt); - const receipt = await sentTx.wait({ timeout: 1, interval: 0.4, dontThrowOnRevert: true }); - expect(receipt.hasExecutionReverted()).toBe(true); - }); - }); - - describe('wait with Aztec Node', () => { - let txReceipt: TxReceipt; - beforeEach(() => { - txReceipt = new TxReceipt( - TxHash.random(), - TxStatus.CHECKPOINTED, - TxExecutionResult.SUCCESS, - undefined, - undefined, - undefined, - BlockNumber(20), - ); - node.getTxReceipt.mockResolvedValue(txReceipt); - sentTx = new SentTx(node, txHashGetter); - }); - - it('throws if tx is dropped', async () => { - const droppedReceipt = new TxReceipt(TxHash.random(), TxStatus.DROPPED, undefined, 'Tx dropped'); - node.getTxReceipt.mockResolvedValue(droppedReceipt); - await expect(sentTx.wait({ timeout: 1, interval: 0.4, ignoreDroppedReceiptsFor: 0 })).rejects.toThrow(/dropped/); - }); - }); - - describe('waitForStatus option', () => { - beforeEach(() => { - sentTx = new SentTx(wallet, txHashGetter); - }); - - it('returns immediately when receipt status matches requested status', async () => { - const checkpointedReceipt = new TxReceipt( - TxHash.random(), - TxStatus.CHECKPOINTED, - TxExecutionResult.SUCCESS, - undefined, - undefined, - undefined, - BlockNumber(20), - ); - wallet.getTxReceipt.mockResolvedValue(checkpointedReceipt); - - const receipt = await sentTx.wait({ timeout: 1, interval: 0.1, waitForStatus: TxStatus.CHECKPOINTED }); - expect(receipt.status).toBe(TxStatus.CHECKPOINTED); - }); - - it('returns when receipt status exceeds requested status', async () => { - const provenReceipt = new TxReceipt( - TxHash.random(), - TxStatus.PROVEN, - TxExecutionResult.SUCCESS, - undefined, - undefined, - undefined, - BlockNumber(20), - ); - wallet.getTxReceipt.mockResolvedValue(provenReceipt); - - // Request CHECKPOINTED, but receive PROVEN - should return immediately - const receipt = await sentTx.wait({ timeout: 1, interval: 0.1, waitForStatus: TxStatus.CHECKPOINTED }); - expect(receipt.status).toBe(TxStatus.PROVEN); - }); - - it('waits until receipt reaches requested status', async () => { - const proposedReceipt = new TxReceipt( - TxHash.random(), - TxStatus.PROPOSED, - TxExecutionResult.SUCCESS, - undefined, - undefined, - undefined, - BlockNumber(20), - ); - const checkpointedReceipt = new TxReceipt( - TxHash.random(), - TxStatus.CHECKPOINTED, - TxExecutionResult.SUCCESS, - undefined, - undefined, - undefined, - BlockNumber(20), - ); - - // First call returns PROPOSED, second returns CHECKPOINTED - wallet.getTxReceipt - .mockResolvedValueOnce(proposedReceipt) - .mockResolvedValueOnce(proposedReceipt) - .mockResolvedValueOnce(checkpointedReceipt); - - const receipt = await sentTx.wait({ timeout: 2, interval: 0.1, waitForStatus: TxStatus.CHECKPOINTED }); - expect(receipt.status).toBe(TxStatus.CHECKPOINTED); - expect(wallet.getTxReceipt).toHaveBeenCalledTimes(3); - }); - - it('times out if receipt never reaches requested status', async () => { - const proposedReceipt = new TxReceipt( - TxHash.random(), - TxStatus.PROPOSED, - TxExecutionResult.SUCCESS, - undefined, - undefined, - undefined, - BlockNumber(20), - ); - wallet.getTxReceipt.mockResolvedValue(proposedReceipt); - - // Request PROVEN but only get PROPOSED - await expect(sentTx.wait({ timeout: 0.5, interval: 0.1, waitForStatus: TxStatus.PROVEN })).rejects.toThrow( - /Timeout/, - ); - }); - - it('defaults to CHECKPOINTED if waitForStatus is not specified', async () => { - const checkpointedReceipt = new TxReceipt( - TxHash.random(), - TxStatus.CHECKPOINTED, - TxExecutionResult.SUCCESS, - undefined, - undefined, - undefined, - BlockNumber(20), - ); - wallet.getTxReceipt.mockResolvedValue(checkpointedReceipt); - - const receipt = await sentTx.wait({ timeout: 1, interval: 0.1 }); - expect(receipt.status).toBe(TxStatus.CHECKPOINTED); - }); - }); - - describe('throw in txHashPromise', () => { - const alwaysThrows = (): Promise => { - return Promise.reject(new Error('test error')); - }; - - it('can be constructed even if txHashPromise throws', () => { - const sentTx = new SentTx(wallet, alwaysThrows); - expect(sentTx).toBeDefined(); - }); - - it('throws if getTxHash is called', async () => { - const sentTx = new SentTx(wallet, alwaysThrows); - await expect(sentTx.getTxHash()).rejects.toThrow('test error'); - }); - - it('throws every time getTxHash is called', async () => { - const sentTx = new SentTx(wallet, alwaysThrows); - await expect(sentTx.getTxHash()).rejects.toThrow('test error'); - await expect(sentTx.getTxHash()).rejects.toThrow('test error'); - await expect(sentTx.getTxHash()).rejects.toThrow('test error'); - }); - - it('throws if getReceipt is called', async () => { - const sentTx = new SentTx(wallet, alwaysThrows); - await expect(sentTx.getReceipt()).rejects.toThrow('test error'); - }); - - it('throws if wait is called', async () => { - const sentTx = new SentTx(wallet, alwaysThrows); - await expect(sentTx.wait()).rejects.toThrow('test error'); - }); - }); -}); diff --git a/yarn-project/aztec.js/src/contract/sent_tx.ts b/yarn-project/aztec.js/src/contract/sent_tx.ts deleted file mode 100644 index 44542902bc7a..000000000000 --- a/yarn-project/aztec.js/src/contract/sent_tx.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { promiseWithResolvers } from '@aztec/foundation/promise'; -import { retryUntil } from '@aztec/foundation/retry'; -import type { AztecNode } from '@aztec/stdlib/interfaces/client'; -import { SortedTxStatuses, TxHash, type TxReceipt, TxStatus } from '@aztec/stdlib/tx'; - -import type { Wallet } from '../wallet/wallet.js'; - -/** Returns true if the receipt status is at least the desired status level. */ -function hasReachedStatus(receipt: TxReceipt, desiredStatus: TxStatus): boolean { - return SortedTxStatuses.indexOf(receipt.status) >= SortedTxStatuses.indexOf(desiredStatus); -} - -/** Options related to waiting for a tx. */ -export type WaitOpts = { - /** The amount of time to ignore TxStatus.DROPPED receipts (in seconds) due to the presumption that it is being propagated by the p2p network. Defaults to 5. */ - ignoreDroppedReceiptsFor?: number; - /** The maximum time (in seconds) to wait for the transaction to be mined. Defaults to 60. */ - timeout?: number; - /** The time interval (in seconds) between retries to fetch the transaction receipt. Defaults to 1. */ - interval?: number; - /** Whether to accept a revert as a status code for the tx when waiting for it. If false, will throw if the tx reverts. */ - dontThrowOnRevert?: boolean; - /** The minimum inclusion status to wait for. If set, waits until the receipt reaches this status or higher. Defaults to CHECKPOINTED. */ - waitForStatus?: TxStatus; -}; - -export const DefaultWaitOpts: WaitOpts = { - ignoreDroppedReceiptsFor: 5, - timeout: 300, - interval: 1, -}; - -/** - * The SentTx class represents a sent transaction through the PXE (or directly to a node) providing methods to fetch - * its hash, receipt, and mining status. - */ -export class SentTx { - protected sendTxPromise: Promise; - protected sendTxError?: Error; - protected txHash?: TxHash; - - constructor( - protected walletOrNode: Wallet | AztecNode, - sendTx: () => Promise, - ) { - const { promise, resolve } = promiseWithResolvers(); - this.sendTxPromise = promise; - sendTx() - .then(txHash => { - this.txHash = txHash; - resolve(); - }) - .catch(err => { - this.sendTxError = err; - // Calling resolve instead of reject here because we want to throw the error when getTxHash is called. - resolve(); - }); - } - - /** - * Retrieves the transaction hash of the SentTx instance. - * The function internally awaits for the 'txHashPromise' to resolve, and then returns the resolved transaction hash. - * - * @returns A promise that resolves to the transaction hash of the SentTx instance. - * TODO(#7717): Don't throw here. - */ - public async getTxHash(): Promise { - // Make sure sendTx has been resolved, which can be triggered when it returns a txHash or when it throws an error. - await this.sendTxPromise; - - // If sendTx threw an error, throw it. - if (this.sendTxError) { - throw this.sendTxError; - } - - // sendTx returned a txHash if it's been resolved and no error was set. - return Promise.resolve(this.txHash!); - } - - /** - * Retrieve the transaction receipt associated with the current SentTx instance. - * The function fetches the transaction hash using 'getTxHash' and then queries - * the PXE to get the corresponding transaction receipt. - * - * @returns A promise that resolves to a TxReceipt object representing the fetched transaction receipt. - */ - public async getReceipt(): Promise { - const txHash = await this.getTxHash(); - return await this.walletOrNode.getTxReceipt(txHash); - } - - /** - * Awaits for a tx to be mined and returns the receipt. Throws if tx is not mined. - * @param opts - Options for configuring the waiting for the tx to be mined. - * @returns The transaction receipt. - */ - public async wait(opts?: WaitOpts): Promise { - const receipt = await this.waitForReceipt(opts); - if (!receipt.isMined()) { - throw new Error( - `Transaction ${(await this.getTxHash()).toString()} was ${receipt.status}. Reason: ${receipt.error ?? 'unknown'}`, - ); - } - if (!receipt.hasExecutionSucceeded() && !opts?.dontThrowOnRevert) { - throw new Error( - `Transaction ${(await this.getTxHash()).toString()} reverted: ${receipt.executionResult}. Reason: ${receipt.error ?? 'unknown'}`, - ); - } - return receipt; - } - - protected async waitForReceipt(opts?: WaitOpts): Promise { - const txHash = await this.getTxHash(); - const startTime = Date.now(); - const ignoreDroppedReceiptsFor = opts?.ignoreDroppedReceiptsFor ?? DefaultWaitOpts.ignoreDroppedReceiptsFor; - const waitForStatus = opts?.waitForStatus ?? TxStatus.CHECKPOINTED; - - return await retryUntil( - async () => { - const txReceipt = await this.walletOrNode.getTxReceipt(txHash); - // If receipt is not yet available, try again - if (txReceipt.isPending()) { - return undefined; - } - // If the tx was "dropped", either return it or ignore based on timing. - // We can ignore it at first because the transaction may have been sent to node 1, and now we're asking node 2 for the receipt. - // If we don't allow a short grace period, we could incorrectly return a TxReceipt with status DROPPED. - if (txReceipt.isDropped()) { - const elapsedSeconds = (Date.now() - startTime) / 1000; - if (!ignoreDroppedReceiptsFor || elapsedSeconds > ignoreDroppedReceiptsFor) { - return txReceipt; - } - return undefined; - } - // Check if the receipt has reached the desired status level - if (!hasReachedStatus(txReceipt, waitForStatus)) { - return undefined; - } - return txReceipt; - }, - 'isMined', - opts?.timeout ?? DefaultWaitOpts.timeout, - opts?.interval ?? DefaultWaitOpts.interval, - ); - } -} diff --git a/yarn-project/aztec.js/src/contract/wait_for_proven.ts b/yarn-project/aztec.js/src/contract/wait_for_proven.ts index b0fa054e61c2..2d0254aa1b63 100644 --- a/yarn-project/aztec.js/src/contract/wait_for_proven.ts +++ b/yarn-project/aztec.js/src/contract/wait_for_proven.ts @@ -2,7 +2,7 @@ import { retryUntil } from '@aztec/foundation/retry'; import type { AztecNode } from '@aztec/stdlib/interfaces/client'; import type { TxReceipt } from '@aztec/stdlib/tx'; -import { DefaultWaitOpts } from './sent_tx.js'; +import { DefaultWaitOpts } from './wait_opts.js'; /** * Options for waiting for a transaction to be proven. diff --git a/yarn-project/aztec.js/src/contract/wait_opts.ts b/yarn-project/aztec.js/src/contract/wait_opts.ts new file mode 100644 index 000000000000..bf7dfeae2b0f --- /dev/null +++ b/yarn-project/aztec.js/src/contract/wait_opts.ts @@ -0,0 +1,21 @@ +import type { TxStatus } from '@aztec/stdlib/tx'; + +/** Options related to waiting for a tx. */ +export type WaitOpts = { + /** The amount of time to ignore TxStatus.DROPPED receipts (in seconds) due to the presumption that it is being propagated by the p2p network. Defaults to 5. */ + ignoreDroppedReceiptsFor?: number; + /** The maximum time (in seconds) to wait for the transaction to be mined. Defaults to 60. */ + timeout?: number; + /** The time interval (in seconds) between retries to fetch the transaction receipt. Defaults to 1. */ + interval?: number; + /** Whether to accept a revert as a status code for the tx when waiting for it. If false, will throw if the tx reverts. */ + dontThrowOnRevert?: boolean; + /** The minimum inclusion status to wait for. If set, waits until the receipt reaches this status or higher. Defaults to CHECKPOINTED. */ + waitForStatus?: TxStatus; +}; + +export const DefaultWaitOpts: WaitOpts = { + ignoreDroppedReceiptsFor: 5, + timeout: 300, + interval: 1, +}; diff --git a/yarn-project/aztec.js/src/utils/authwit.ts b/yarn-project/aztec.js/src/utils/authwit.ts index 670b290a9f90..d0d8b9f1c088 100644 --- a/yarn-project/aztec.js/src/utils/authwit.ts +++ b/yarn-project/aztec.js/src/utils/authwit.ts @@ -5,16 +5,18 @@ import { type ABIParameterVisibility, type FunctionAbi, type FunctionCall, Funct import { AuthWitness, computeInnerAuthWitHash, computeOuterAuthWitHash } from '@aztec/stdlib/auth-witness'; import type { AztecAddress } from '@aztec/stdlib/aztec-address'; import { computeVarArgsHash } from '@aztec/stdlib/hash'; -import type { TxProfileResult } from '@aztec/stdlib/tx'; +import type { TxHash, TxProfileResult, TxReceipt } from '@aztec/stdlib/tx'; import { ContractFunctionInteraction } from '../contract/contract_function_interaction.js'; import type { + InteractionWaitOptions, ProfileInteractionOptions, SendInteractionOptions, + SendInteractionOptionsWithoutWait, + SendReturn, SimulateInteractionOptions, SimulationReturn, } from '../contract/interaction_options.js'; -import type { SentTx } from '../contract/sent_tx.js'; import type { Wallet } from '../wallet/index.js'; /** Intent with an inner hash */ @@ -286,9 +288,19 @@ export class SetPublicAuthwitContractInteraction extends ContractFunctionInterac * Overrides the send method, adding the sender of the authwit (authorizer) as from * and preventing misuse * @param options - An optional object containing 'fee' options information - * @returns A SentTx instance for tracking the transaction status and information. + * @returns A TxReceipt (if wait is true/undefined) or TxHash (if wait is false) */ - public override send(options: Omit = {}): SentTx { + // Overload for when wait is not specified at all - returns TxReceipt + public override send(options?: Omit): Promise; + // Generic overload for explicit wait values + // eslint-disable-next-line jsdoc/require-jsdoc + public override send( + options?: Omit, 'from'>, + ): Promise>; + // eslint-disable-next-line jsdoc/require-jsdoc + public override send( + options?: Omit, 'from'>, + ): Promise { return super.send({ ...options, from: this.from }); } diff --git a/yarn-project/aztec.js/src/utils/node.test.ts b/yarn-project/aztec.js/src/utils/node.test.ts new file mode 100644 index 000000000000..2bdfc8cc3699 --- /dev/null +++ b/yarn-project/aztec.js/src/utils/node.test.ts @@ -0,0 +1,182 @@ +import { BlockNumber } from '@aztec/foundation/branded-types'; +import type { AztecNode } from '@aztec/stdlib/interfaces/client'; +import { TxExecutionResult, TxHash, TxReceipt, TxStatus } from '@aztec/stdlib/tx'; + +import { type MockProxy, mock } from 'jest-mock-extended'; + +import { waitForTx } from './node.js'; + +describe('waitForTx', () => { + let node: MockProxy; + let txHash: TxHash; + + beforeEach(() => { + node = mock(); + txHash = TxHash.random(); + }); + + describe('basic behavior', () => { + let txReceipt: TxReceipt; + beforeEach(() => { + txReceipt = new TxReceipt( + txHash, + TxStatus.CHECKPOINTED, + TxExecutionResult.SUCCESS, + undefined, + undefined, + undefined, + BlockNumber(20), + ); + node.getTxReceipt.mockResolvedValue(txReceipt); + }); + + it('throws if tx is dropped', async () => { + const droppedReceipt = new TxReceipt(txHash, TxStatus.DROPPED, undefined, 'Tx dropped'); + node.getTxReceipt.mockResolvedValue(droppedReceipt); + await expect(waitForTx(node, txHash, { timeout: 1, interval: 0.4, ignoreDroppedReceiptsFor: 0 })).rejects.toThrow( + /dropped/, + ); + }); + + it('throws if tx reverts and dontThrowOnRevert is false', async () => { + const revertedReceipt = new TxReceipt( + txHash, + TxStatus.CHECKPOINTED, + TxExecutionResult.APP_LOGIC_REVERTED, + undefined, + undefined, + undefined, + BlockNumber(20), + ); + node.getTxReceipt.mockResolvedValue(revertedReceipt); + await expect(waitForTx(node, txHash, { timeout: 1, interval: 0.4 })).rejects.toThrow(/reverted/); + }); + + it('does not throw if tx reverts and dontThrowOnRevert is true', async () => { + const revertedReceipt = new TxReceipt( + txHash, + TxStatus.CHECKPOINTED, + TxExecutionResult.APP_LOGIC_REVERTED, + undefined, + undefined, + undefined, + BlockNumber(20), + ); + node.getTxReceipt.mockResolvedValue(revertedReceipt); + const receipt = await waitForTx(node, txHash, { timeout: 1, interval: 0.4, dontThrowOnRevert: true }); + expect(receipt.hasExecutionReverted()).toBe(true); + }); + }); + + describe('waitForStatus option', () => { + it('returns immediately when receipt status matches requested status', async () => { + const checkpointedReceipt = new TxReceipt( + txHash, + TxStatus.CHECKPOINTED, + TxExecutionResult.SUCCESS, + undefined, + undefined, + undefined, + BlockNumber(20), + ); + node.getTxReceipt.mockResolvedValue(checkpointedReceipt); + + const receipt = await waitForTx(node, txHash, { + timeout: 1, + interval: 0.1, + waitForStatus: TxStatus.CHECKPOINTED, + }); + expect(receipt.status).toBe(TxStatus.CHECKPOINTED); + }); + + it('returns when receipt status exceeds requested status', async () => { + const provenReceipt = new TxReceipt( + txHash, + TxStatus.PROVEN, + TxExecutionResult.SUCCESS, + undefined, + undefined, + undefined, + BlockNumber(20), + ); + node.getTxReceipt.mockResolvedValue(provenReceipt); + + // Request CHECKPOINTED, but receive PROVEN - should return immediately + const receipt = await waitForTx(node, txHash, { + timeout: 1, + interval: 0.1, + waitForStatus: TxStatus.CHECKPOINTED, + }); + expect(receipt.status).toBe(TxStatus.PROVEN); + }); + + it('waits until receipt reaches requested status', async () => { + const proposedReceipt = new TxReceipt( + txHash, + TxStatus.PROPOSED, + TxExecutionResult.SUCCESS, + undefined, + undefined, + undefined, + BlockNumber(20), + ); + const checkpointedReceipt = new TxReceipt( + txHash, + TxStatus.CHECKPOINTED, + TxExecutionResult.SUCCESS, + undefined, + undefined, + undefined, + BlockNumber(20), + ); + + // First call returns PROPOSED, second returns CHECKPOINTED + node.getTxReceipt + .mockResolvedValueOnce(proposedReceipt) + .mockResolvedValueOnce(proposedReceipt) + .mockResolvedValueOnce(checkpointedReceipt); + + const receipt = await waitForTx(node, txHash, { + timeout: 2, + interval: 0.1, + waitForStatus: TxStatus.CHECKPOINTED, + }); + expect(receipt.status).toBe(TxStatus.CHECKPOINTED); + expect(node.getTxReceipt).toHaveBeenCalledTimes(3); + }); + + it('times out if receipt never reaches requested status', async () => { + const proposedReceipt = new TxReceipt( + txHash, + TxStatus.PROPOSED, + TxExecutionResult.SUCCESS, + undefined, + undefined, + undefined, + BlockNumber(20), + ); + node.getTxReceipt.mockResolvedValue(proposedReceipt); + + // Request PROVEN but only get PROPOSED + await expect( + waitForTx(node, txHash, { timeout: 0.5, interval: 0.1, waitForStatus: TxStatus.PROVEN }), + ).rejects.toThrow(/Timeout/); + }); + + it('defaults to CHECKPOINTED if waitForStatus is not specified', async () => { + const checkpointedReceipt = new TxReceipt( + txHash, + TxStatus.CHECKPOINTED, + TxExecutionResult.SUCCESS, + undefined, + undefined, + undefined, + BlockNumber(20), + ); + node.getTxReceipt.mockResolvedValue(checkpointedReceipt); + + const receipt = await waitForTx(node, txHash, { timeout: 1, interval: 0.1 }); + expect(receipt.status).toBe(TxStatus.CHECKPOINTED); + }); + }); +}); diff --git a/yarn-project/aztec.js/src/utils/node.ts b/yarn-project/aztec.js/src/utils/node.ts index dc8ac3035c70..ee88b68a7159 100644 --- a/yarn-project/aztec.js/src/utils/node.ts +++ b/yarn-project/aztec.js/src/utils/node.ts @@ -1,6 +1,10 @@ import type { Logger } from '@aztec/foundation/log'; import { retryUntil } from '@aztec/foundation/retry'; import type { AztecNode } from '@aztec/stdlib/interfaces/client'; +import type { TxHash, TxReceipt } from '@aztec/stdlib/tx'; +import { SortedTxStatuses, TxStatus } from '@aztec/stdlib/tx'; + +import { DefaultWaitOpts, type WaitOpts } from '../contract/wait_opts.js'; export const waitForNode = async (node: AztecNode, logger?: Logger) => { await retryUntil(async () => { @@ -16,4 +20,62 @@ export const waitForNode = async (node: AztecNode, logger?: Logger) => { }, 'RPC Get Node Info'); }; +/** Returns true if the receipt status is at least the desired status level. */ +function hasReachedStatus(receipt: TxReceipt, desiredStatus: TxStatus): boolean { + return SortedTxStatuses.indexOf(receipt.status) >= SortedTxStatuses.indexOf(desiredStatus); +} + +/** + * Waits for a transaction to be mined and returns its receipt. + * @param node - The Aztec node to query for transaction status + * @param txHash - The hash of the transaction to wait for + * @param opts - Optional configuration for waiting behavior + * @returns The transaction receipt + * @throws If the transaction fails and dontThrowOnRevert is not set + */ +export async function waitForTx(node: AztecNode, txHash: TxHash, opts?: WaitOpts): Promise { + const startTime = Date.now(); + const ignoreDroppedReceiptsFor = opts?.ignoreDroppedReceiptsFor ?? DefaultWaitOpts.ignoreDroppedReceiptsFor; + const waitForStatus = opts?.waitForStatus ?? TxStatus.CHECKPOINTED; + + const receipt = await retryUntil( + async () => { + const txReceipt = await node.getTxReceipt(txHash); + // If receipt is not yet available, try again + if (txReceipt.isPending()) { + return undefined; + } + // If the tx was "dropped", either return it or ignore based on timing. + // We can ignore it at first because the transaction may have been sent to node 1, and now we're asking node 2 for the receipt. + // If we don't allow a short grace period, we could incorrectly return a TxReceipt with status DROPPED. + if (txReceipt.isDropped()) { + const elapsedSeconds = (Date.now() - startTime) / 1000; + if (!ignoreDroppedReceiptsFor || elapsedSeconds > ignoreDroppedReceiptsFor) { + return txReceipt; + } + return undefined; + } + // Check if the receipt has reached the desired status level + if (!hasReachedStatus(txReceipt, waitForStatus)) { + return undefined; + } + return txReceipt; + }, + 'isMined', + opts?.timeout ?? DefaultWaitOpts.timeout, + opts?.interval ?? DefaultWaitOpts.interval, + ); + + if (!receipt.isMined()) { + throw new Error(`Transaction ${txHash.toString()} was ${receipt.status}. Reason: ${receipt.error ?? 'unknown'}`); + } + if (!receipt.hasExecutionSucceeded() && !opts?.dontThrowOnRevert) { + throw new Error( + `Transaction ${txHash.toString()} reverted: ${receipt.executionResult}. Reason: ${receipt.error ?? 'unknown'}`, + ); + } + + return receipt; +} + export { createAztecNodeClient, type AztecNode } from '@aztec/stdlib/interfaces/client'; diff --git a/yarn-project/aztec.js/src/wallet/deploy_account_method.ts b/yarn-project/aztec.js/src/wallet/deploy_account_method.ts index 21c7d83cc024..8bb07b8d8a37 100644 --- a/yarn-project/aztec.js/src/wallet/deploy_account_method.ts +++ b/yarn-project/aztec.js/src/wallet/deploy_account_method.ts @@ -10,11 +10,11 @@ import type { Contract } from '../contract/contract.js'; import type { ContractBase } from '../contract/contract_base.js'; import { DeployMethod, - type DeployOptions, + type DeployOptionsWithoutWait, type RequestDeployOptions, type SimulateDeployOptions, } from '../contract/deploy_method.js'; -import type { FeePaymentMethodOption } from '../contract/interaction_options.js'; +import type { FeePaymentMethodOption, InteractionWaitOptions } from '../contract/interaction_options.js'; import type { FeePaymentMethod } from '../fee/fee_payment_method.js'; import { AccountEntrypointMetaPaymentMethod } from './account_entrypoint_meta_payment_method.js'; import type { Wallet } from './index.js'; @@ -36,12 +36,27 @@ export type RequestDeployAccountOptions = Omit; + /** * The configuration options for the send/prove methods. Omits: * - The contractAddressSalt, since for account contracts that is fixed in the constructor. * - UniversalDeployment flag, since account contracts are always deployed with it set to true */ -export type DeployAccountOptions = Omit; +export type DeployAccountOptions = DeployAccountOptionsWithoutWait & { + /** + * Whether to wait for the transaction to be mined. + * - undefined (default): wait with default options and return TxReceipt + * - WaitOpts object: wait with custom options and return TxReceipt + * - false: return txHash immediately without waiting + */ + wait?: W; +}; /** * The configuration options for the simulate method. Omits the contractAddressSalt, since @@ -122,7 +137,7 @@ export class DeployAccountMethod exte return mergeExecutionPayloads(executionPayloads); } - override convertDeployOptionsToRequestOptions(options: DeployOptions): RequestDeployOptions { + override convertDeployOptionsToRequestOptions(options: DeployAccountOptionsWithoutWait): RequestDeployOptions { return { ...options, // Deployer is handled in the request method and forcibly set to undefined, diff --git a/yarn-project/aztec.js/src/wallet/wallet.test.ts b/yarn-project/aztec.js/src/wallet/wallet.test.ts index 66a5047a481e..e2668d60ed9e 100644 --- a/yarn-project/aztec.js/src/wallet/wallet.test.ts +++ b/yarn-project/aztec.js/src/wallet/wallet.test.ts @@ -18,6 +18,7 @@ import { UtilitySimulationResult, } from '@aztec/stdlib/tx'; +import { type InteractionWaitOptions, NO_WAIT, type SendReturn } from '../contract/interaction_options.js'; import type { Aliased, BatchResults, @@ -62,11 +63,6 @@ describe('WalletSchema', () => { }); }); - it('getTxReceipt', async () => { - const result = await context.client.getTxReceipt(TxHash.random()); - expect(result).toBeInstanceOf(TxReceipt); - }); - it('getPrivateEvents', async () => { const eventMetadata: EventMetadataDefinition = { eventSelector: EventSelector.fromField(new Fr(1)), @@ -205,11 +201,16 @@ describe('WalletSchema', () => { extraHashedArgs: [], feePayer: undefined, }; - const opts: SendOptions = { + + const resultWithWait = await context.client.sendTx(exec, { from: await AztecAddress.random(), - }; - const result = await context.client.sendTx(exec, opts); - expect(result).toBeInstanceOf(TxHash); + }); + expect(resultWithWait).toBeInstanceOf(TxReceipt); + const resultWithoutWait = await context.client.sendTx(exec, { + from: await AztecAddress.random(), + wait: NO_WAIT, + }); + expect(resultWithoutWait).toBeInstanceOf(TxHash); }); it('createAuthWit', async () => { @@ -281,7 +282,6 @@ describe('WalletSchema', () => { const methods: BatchedMethod[] = [ { name: 'getChainInfo', args: [] }, - { name: 'getTxReceipt', args: [TxHash.random()] }, { name: 'getContractMetadata', args: [address1] }, { name: 'getContractClassMetadata', args: [Fr.random()] }, { @@ -300,30 +300,29 @@ describe('WalletSchema', () => { ]; const results = await context.client.batch(methods); - expect(results).toHaveLength(14); + expect(results).toHaveLength(13); expect(results[0]).toEqual({ name: 'getChainInfo', result: { chainId: expect.any(Fr), version: expect.any(Fr) } }); - expect(results[1]).toEqual({ name: 'getTxReceipt', result: expect.any(TxReceipt) }); - expect(results[2]).toEqual({ + expect(results[1]).toEqual({ name: 'getContractMetadata', result: expect.objectContaining({ isContractInitialized: expect.any(Boolean) }), }); - expect(results[3]).toEqual({ + expect(results[2]).toEqual({ name: 'getContractClassMetadata', result: expect.objectContaining({ isArtifactRegistered: expect.any(Boolean) }), }); - expect(results[4]).toEqual({ name: 'getPrivateEvents', result: expect.any(Array) }); - expect(results[5]).toEqual({ name: 'registerSender', result: expect.any(AztecAddress) }); - expect(results[6]).toEqual({ name: 'getAddressBook', result: expect.any(Array) }); - expect(results[7]).toEqual({ name: 'getAccounts', result: expect.any(Array) }); - expect(results[8]).toEqual({ + expect(results[3]).toEqual({ name: 'getPrivateEvents', result: expect.any(Array) }); + expect(results[4]).toEqual({ name: 'registerSender', result: expect.any(AztecAddress) }); + expect(results[5]).toEqual({ name: 'getAddressBook', result: expect.any(Array) }); + expect(results[6]).toEqual({ name: 'getAccounts', result: expect.any(Array) }); + expect(results[7]).toEqual({ name: 'registerContract', result: expect.objectContaining({ address: expect.any(AztecAddress) }), }); - expect(results[9]).toEqual({ name: 'simulateTx', result: expect.any(TxSimulationResult) }); - expect(results[10]).toEqual({ name: 'simulateUtility', result: expect.any(UtilitySimulationResult) }); - expect(results[11]).toEqual({ name: 'profileTx', result: expect.any(TxProfileResult) }); - expect(results[12]).toEqual({ name: 'sendTx', result: expect.any(TxHash) }); - expect(results[13]).toEqual({ name: 'createAuthWit', result: expect.any(AuthWitness) }); + expect(results[8]).toEqual({ name: 'simulateTx', result: expect.any(TxSimulationResult) }); + expect(results[9]).toEqual({ name: 'simulateUtility', result: expect.any(UtilitySimulationResult) }); + expect(results[10]).toEqual({ name: 'profileTx', result: expect.any(TxProfileResult) }); + expect(results[11]).toEqual({ name: 'sendTx', result: expect.any(TxReceipt) }); + expect(results[12]).toEqual({ name: 'createAuthWit', result: expect.any(AuthWitness) }); }); }); @@ -354,10 +353,6 @@ class MockWallet implements Wallet { ] as PrivateEvent[]); } - getTxReceipt(_txHash: TxHash): Promise { - return Promise.resolve(TxReceipt.empty()); - } - getContractMetadata(_address: AztecAddress): Promise { return Promise.resolve({ instance: undefined, @@ -412,8 +407,14 @@ class MockWallet implements Wallet { return Promise.resolve(TxProfileResult.random()); } - sendTx(_exec: ExecutionPayload, _opts: SendOptions): Promise { - return Promise.resolve(TxHash.random()); + sendTx( + _exec: ExecutionPayload, + opts: SendOptions, + ): Promise> { + if (opts.wait === NO_WAIT) { + return Promise.resolve(TxHash.random()) as Promise>; + } + return Promise.resolve(TxReceipt.empty()) as Promise>; } createAuthWit(_from: AztecAddress, _messageHashOrIntent: any): Promise { diff --git a/yarn-project/aztec.js/src/wallet/wallet.ts b/yarn-project/aztec.js/src/wallet/wallet.ts index e5e91786777d..85dbc9115d91 100644 --- a/yarn-project/aztec.js/src/wallet/wallet.ts +++ b/yarn-project/aztec.js/src/wallet/wallet.ts @@ -29,12 +29,15 @@ import type { ExecutionPayload, InTx } from '@aztec/stdlib/tx'; import { z } from 'zod'; -import type { - FeeEstimationOptions, - GasSettingsOption, - ProfileInteractionOptions, - SendInteractionOptions, - SimulateInteractionOptions, +import { + type FeeEstimationOptions, + type GasSettingsOption, + type InteractionWaitOptions, + NO_WAIT, + type ProfileInteractionOptions, + type SendInteractionOptionsWithoutWait, + type SendReturn, + type SimulateInteractionOptions, } from '../contract/interaction_options.js'; import type { CallIntent, IntentInnerHash } from '../utils/authwit.js'; @@ -77,9 +80,14 @@ export type ProfileOptions = Omit & { * a simplified version that only hints at the wallet whether the interaction contains a * fee payment method or not */ -export type SendOptions = Omit & { +export type SendOptions = Omit< + SendInteractionOptionsWithoutWait, + 'fee' +> & { /** The fee options */ fee?: GasSettingsOption; + /** Whether to wait for the transaction to be mined */ + wait?: W; }; /** @@ -197,7 +205,6 @@ export type Wallet = { eventFilter: PrivateEventFilter, ): Promise[]>; getChainInfo(): Promise; - getTxReceipt(txHash: TxHash): Promise; getContractMetadata(address: AztecAddress): Promise; getContractClassMetadata(id: Fr): Promise; registerSender(address: AztecAddress, alias?: string): Promise; @@ -211,7 +218,10 @@ export type Wallet = { simulateTx(exec: ExecutionPayload, opts: SimulateOptions): Promise; simulateUtility(call: FunctionCall, authwits?: AuthWitness[]): Promise; profileTx(exec: ExecutionPayload, opts: ProfileOptions): Promise; - sendTx(exec: ExecutionPayload, opts: SendOptions): Promise; + sendTx( + exec: ExecutionPayload, + opts: SendOptions, + ): Promise>; createAuthWit(from: AztecAddress, messageHashOrIntent: IntentInnerHash | CallIntent): Promise; batch(methods: T): Promise>; }; @@ -251,11 +261,19 @@ export const WalletSimulationFeeOptionSchema = GasSettingsOptionSchema.extend({ estimateGas: optional(z.boolean()), }); +export const WaitOptsSchema = z.object({ + ignoreDroppedReceiptsFor: optional(z.number()), + timeout: optional(z.number()), + interval: optional(z.number()), + dontThrowOnRevert: optional(z.boolean()), +}); + export const SendOptionsSchema = z.object({ from: schemas.AztecAddress, authWitnesses: optional(z.array(AuthWitness.schema)), capsules: optional(z.array(Capsule.schema)), fee: optional(GasSettingsOptionSchema), + wait: optional(z.union([z.literal(NO_WAIT), WaitOptsSchema])), }); export const SimulateOptionsSchema = z.object({ @@ -324,7 +342,6 @@ const WalletMethodSchemas = { .function() .args() .returns(z.object({ chainId: schemas.Fr, version: schemas.Fr })), - getTxReceipt: z.function().args(TxHash.schema).returns(TxReceipt.schema), getContractMetadata: z.function().args(schemas.AztecAddress).returns(ContractMetadataSchema), getContractClassMetadata: z.function().args(schemas.Fr).returns(ContractClassMetadataSchema), getPrivateEvents: z @@ -350,7 +367,10 @@ const WalletMethodSchemas = { .args(FunctionCallSchema, optional(z.array(AuthWitness.schema))) .returns(UtilitySimulationResult.schema), profileTx: z.function().args(ExecutionPayloadSchema, ProfileOptionsSchema).returns(TxProfileResult.schema), - sendTx: z.function().args(ExecutionPayloadSchema, SendOptionsSchema).returns(TxHash.schema), + sendTx: z + .function() + .args(ExecutionPayloadSchema, SendOptionsSchema) + .returns(z.union([TxHash.schema, TxReceipt.schema])), createAuthWit: z.function().args(schemas.AztecAddress, MessageHashOrIntentSchema).returns(AuthWitness.schema), }; diff --git a/yarn-project/aztec/src/examples/token.ts b/yarn-project/aztec/src/examples/token.ts index f68566b29a98..1d52fa28d73b 100644 --- a/yarn-project/aztec/src/examples/token.ts +++ b/yarn-project/aztec/src/examples/token.ts @@ -32,14 +32,12 @@ async function main() { logger.info(`Fetched Alice and Bob accounts: ${alice.toString()}, ${bob.toString()}`); logger.info('Deploying Token...'); - const token = await TokenContract.deploy(wallet, alice, 'TokenName', 'TokenSymbol', 18) - .send({ from: alice }) - .deployed(); + const token = await TokenContract.deploy(wallet, alice, 'TokenName', 'TokenSymbol', 18).send({ from: alice }); logger.info('Token deployed'); // Mint tokens to Alice logger.info(`Minting ${ALICE_MINT_BALANCE} more coins to Alice...`); - await token.methods.mint_to_private(alice, ALICE_MINT_BALANCE).send({ from: alice }).wait(); + await token.methods.mint_to_private(alice, ALICE_MINT_BALANCE).send({ from: alice }); logger.info(`${ALICE_MINT_BALANCE} tokens were successfully minted by Alice and transferred to private`); @@ -48,7 +46,7 @@ async function main() { // We will now transfer tokens from Alice to Bob logger.info(`Transferring ${TRANSFER_AMOUNT} tokens from Alice to Bob...`); - await token.methods.transfer(bob, TRANSFER_AMOUNT).send({ from: alice }).wait(); + await token.methods.transfer(bob, TRANSFER_AMOUNT).send({ from: alice }); // Check the new balances const aliceBalance = await token.methods.balance_of_private(alice).simulate({ from: alice }); diff --git a/yarn-project/aztec/src/local-network/banana_fpc.ts b/yarn-project/aztec/src/local-network/banana_fpc.ts index ad1704ab0fe8..5ccb73d8746f 100644 --- a/yarn-project/aztec/src/local-network/banana_fpc.ts +++ b/yarn-project/aztec/src/local-network/banana_fpc.ts @@ -49,12 +49,16 @@ export async function setupBananaFPC(initialAccounts: InitialAccountData[], wall const bananaCoinAddress = await getBananaCoinAddress(initialAccounts); const admin = getBananaAdmin(initialAccounts); const [bananaCoin, fpc] = await Promise.all([ - TokenContract.deploy(wallet, admin, bananaCoinArgs.name, bananaCoinArgs.symbol, bananaCoinArgs.decimal) - .send({ from: admin, contractAddressSalt: BANANA_COIN_SALT, universalDeploy: true }) - .deployed(), - FPCContract.deploy(wallet, bananaCoinAddress, admin) - .send({ from: admin, contractAddressSalt: BANANA_FPC_SALT, universalDeploy: true }) - .deployed(), + TokenContract.deploy(wallet, admin, bananaCoinArgs.name, bananaCoinArgs.symbol, bananaCoinArgs.decimal).send({ + from: admin, + contractAddressSalt: BANANA_COIN_SALT, + universalDeploy: true, + }), + FPCContract.deploy(wallet, bananaCoinAddress, admin).send({ + from: admin, + contractAddressSalt: BANANA_FPC_SALT, + universalDeploy: true, + }), ]); log(`BananaCoin: ${bananaCoin.address}`); diff --git a/yarn-project/aztec/src/local-network/local-network.ts b/yarn-project/aztec/src/local-network/local-network.ts index 31f8b5037584..c7586e169565 100644 --- a/yarn-project/aztec/src/local-network/local-network.ts +++ b/yarn-project/aztec/src/local-network/local-network.ts @@ -194,7 +194,7 @@ export async function createLocalNetwork(config: Partial = { const wallet = await TestWallet.create(node, PXEConfig); userLog('Setting up funded test accounts...'); - const accountManagers = await deployFundedSchnorrAccounts(wallet, node, initialAccounts); + const accountManagers = await deployFundedSchnorrAccounts(wallet, initialAccounts); const accountsWithSecrets = accountManagers.map((manager, i) => ({ account: manager, secretKey: initialAccounts[i].secret, diff --git a/yarn-project/bot/src/amm_bot.ts b/yarn-project/bot/src/amm_bot.ts index 2cbd4b015b9f..543afce66491 100644 --- a/yarn-project/bot/src/amm_bot.ts +++ b/yarn-project/bot/src/amm_bot.ts @@ -1,7 +1,7 @@ import { AztecAddress } from '@aztec/aztec.js/addresses'; -import { SentTx } from '@aztec/aztec.js/contracts'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { Fr } from '@aztec/aztec.js/fields'; -import { TxReceipt } from '@aztec/aztec.js/tx'; +import { TxHash, TxReceipt } from '@aztec/aztec.js/tx'; import { jsonStringify } from '@aztec/foundation/json-rpc'; import type { AMMContract } from '@aztec/noir-contracts.js/AMM'; import type { TokenContract } from '@aztec/noir-contracts.js/Token'; @@ -48,7 +48,7 @@ export class AmmBot extends BaseBot { return new AmmBot(aztecNode, wallet, defaultAccountAddress, amm, token0, token1, config); } - protected async createAndSendTx(logCtx: object): Promise { + protected async createAndSendTx(logCtx: object): Promise { const { feePaymentMethod } = this.config; const { wallet, amm, token0, token1 } = this; @@ -89,7 +89,7 @@ export class AmmBot extends BaseBot { this.log.verbose(`Sending transaction`, logCtx); this.log.info(`Tx. Balances: ${jsonStringify(balances)}`, { ...logCtx, balances }); - return swapExactTokensInteraction.send(opts); + return swapExactTokensInteraction.send({ ...opts, wait: NO_WAIT }); } protected override async onTxMined(receipt: TxReceipt, logCtx: object): Promise { diff --git a/yarn-project/bot/src/base_bot.ts b/yarn-project/bot/src/base_bot.ts index af9631a2a7e4..74184a072fc1 100644 --- a/yarn-project/bot/src/base_bot.ts +++ b/yarn-project/bot/src/base_bot.ts @@ -3,10 +3,10 @@ import { BatchCall, ContractFunctionInteraction, type SendInteractionOptions, - SentTx, waitForProven, } from '@aztec/aztec.js/contracts'; import { createLogger } from '@aztec/aztec.js/log'; +import { waitForTx } from '@aztec/aztec.js/node'; import { TxHash, TxReceipt } from '@aztec/aztec.js/tx'; import { Gas } from '@aztec/stdlib/gas'; import type { AztecNode } from '@aztec/stdlib/interfaces/client'; @@ -33,9 +33,7 @@ export abstract class BaseBot { const { followChain, txMinedWaitSeconds } = this.config; this.log.verbose(`Creating tx`, logCtx); - const tx = await this.createAndSendTx(logCtx); - - const txHash = await tx.getTxHash(); + const txHash = await this.createAndSendTx(logCtx); if (followChain === 'NONE') { this.log.info(`Transaction ${txHash.toString()} sent, not waiting for it to be mined`); @@ -46,9 +44,7 @@ export abstract class BaseBot { `Awaiting tx ${txHash.toString()} to be on the ${followChain} chain (timeout ${txMinedWaitSeconds}s)`, logCtx, ); - const receipt = await tx.wait({ - timeout: txMinedWaitSeconds, - }); + const receipt = await waitForTx(this.node, txHash, { timeout: txMinedWaitSeconds }); if (followChain === 'PROVEN') { await waitForProven(this.node, receipt, { provenTimeout: txMinedWaitSeconds }); } @@ -63,7 +59,7 @@ export abstract class BaseBot { return receipt; } - protected abstract createAndSendTx(logCtx: object): Promise; + protected abstract createAndSendTx(logCtx: object): Promise; protected onTxMined(_receipt: TxReceipt, _logCtx: object): Promise { // no-op diff --git a/yarn-project/bot/src/bot.ts b/yarn-project/bot/src/bot.ts index 5057a91c4216..f1a4151d4e33 100644 --- a/yarn-project/bot/src/bot.ts +++ b/yarn-project/bot/src/bot.ts @@ -1,5 +1,6 @@ import type { AztecAddress } from '@aztec/aztec.js/addresses'; -import { BatchCall, SentTx } from '@aztec/aztec.js/contracts'; +import { BatchCall, NO_WAIT } from '@aztec/aztec.js/contracts'; +import { TxHash } from '@aztec/aztec.js/tx'; import { times } from '@aztec/foundation/collection'; import type { PrivateTokenContract } from '@aztec/noir-contracts.js/PrivateToken'; import type { TokenContract } from '@aztec/noir-contracts.js/Token'; @@ -48,7 +49,7 @@ export class Bot extends BaseBot { this.config = { ...this.config, ...config }; } - protected async createAndSendTx(logCtx: object): Promise { + protected async createAndSendTx(logCtx: object): Promise { const { privateTransfersPerTx, publicTransfersPerTx, feePaymentMethod } = this.config; const { token, recipient, wallet } = this; @@ -75,7 +76,7 @@ export class Bot extends BaseBot { await batch.simulate({ from: this.defaultAccountAddress }); this.log.verbose(`Sending transaction`, logCtx); - return batch.send(opts); + return batch.send({ ...opts, wait: NO_WAIT }); } public async getBalances() { diff --git a/yarn-project/bot/src/factory.ts b/yarn-project/bot/src/factory.ts index 7f288c8ab39f..8d3d8dcca2bb 100644 --- a/yarn-project/bot/src/factory.ts +++ b/yarn-project/bot/src/factory.ts @@ -7,6 +7,7 @@ import { ContractFunctionInteraction, type DeployMethod, type DeployOptions, + NO_WAIT, } from '@aztec/aztec.js/contracts'; import { L1FeeJuicePortalManager } from '@aztec/aztec.js/ethereum'; import type { L2AmountClaim } from '@aztec/aztec.js/ethereum'; @@ -14,6 +15,7 @@ import { FeeJuicePaymentMethodWithClaim } from '@aztec/aztec.js/fee'; import { deriveKeys } from '@aztec/aztec.js/keys'; import { createLogger } from '@aztec/aztec.js/log'; import { waitForL1ToL2MessageReady } from '@aztec/aztec.js/messaging'; +import { waitForTx } from '@aztec/aztec.js/node'; import { createEthereumChain } from '@aztec/ethereum/chain'; import { createExtendedL1Client } from '@aztec/ethereum/client'; import { Fr } from '@aztec/foundation/curves/bn254'; @@ -136,10 +138,16 @@ export class BotFactory { const deployMethod = await accountManager.getDeployMethod(); const maxFeesPerGas = (await this.aztecNode.getCurrentMinFees()).mul(1 + this.config.minFeePadding); const gasSettings = GasSettings.default({ maxFeesPerGas }); - const sentTx = deployMethod.send({ from: AztecAddress.ZERO, fee: { gasSettings, paymentMethod } }); - const txHash = await sentTx.getTxHash(); - this.log.info(`Sent tx for account deployment with hash ${txHash.toString()}`); - await this.withNoMinTxsPerBlock(() => sentTx.wait({ timeout: this.config.txMinedWaitSeconds })); + + await this.withNoMinTxsPerBlock(async () => { + const txHash = await deployMethod.send({ + from: AztecAddress.ZERO, + fee: { gasSettings, paymentMethod }, + wait: NO_WAIT, + }); + this.log.info(`Sent tx for account deployment with hash ${txHash.toString()}`); + return waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds }); + }); this.log.info(`Account deployed at ${address}`); // Clean up the consumed bridge claim @@ -173,8 +181,11 @@ export class BotFactory { contractAddressSalt: this.config.tokenSalt, universalDeploy: true, }; + let token: TokenContract | PrivateTokenContract; if (this.config.contract === SupportedTokenContracts.TokenContract) { deploy = TokenContract.deploy(this.wallet, sender, 'BotToken', 'BOT', 18); + tokenInstance = await deploy.getInstance(deployOpts); + token = TokenContract.at(tokenInstance.address, this.wallet); } else if (this.config.contract === SupportedTokenContracts.PrivateTokenContract) { // Generate keys for the contract since PrivateToken uses SinglePrivateMutable which requires keys const tokenSecretKey = Fr.random(); @@ -186,6 +197,7 @@ export class BotFactory { // Register the contract with the secret key before deployment tokenInstance = await deploy.getInstance(deployOpts); + token = PrivateTokenContract.at(tokenInstance.address, this.wallet); await this.wallet.registerContract(tokenInstance, PrivateTokenContract.artifact, tokenSecretKey); } else { throw new Error(`Unsupported token contract type: ${this.config.contract}`); @@ -195,14 +207,17 @@ export class BotFactory { const metadata = await this.wallet.getContractMetadata(address); if (metadata.isContractPublished) { this.log.info(`Token at ${address.toString()} already deployed`); - return deploy.register(); + await deploy.register(); } else { this.log.info(`Deploying token contract at ${address.toString()}`); - const sentTx = deploy.send(deployOpts); - const txHash = await sentTx.getTxHash(); + const txHash = await deploy.send({ ...deployOpts, wait: NO_WAIT }); this.log.info(`Sent tx for token setup with hash ${txHash.toString()}`); - return this.withNoMinTxsPerBlock(() => sentTx.deployed({ timeout: this.config.txMinedWaitSeconds })); + await this.withNoMinTxsPerBlock(async () => { + await waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds }); + return token; + }); } + return token; } /** @@ -210,7 +225,7 @@ export class BotFactory { * @param wallet - Wallet to deploy the token contract from. * @returns The TokenContract instance. */ - private setupTokenContract( + private async setupTokenContract( deployer: AztecAddress, contractAddressSalt: Fr, name: string, @@ -219,7 +234,8 @@ export class BotFactory { ): Promise { const deployOpts: DeployOptions = { from: deployer, contractAddressSalt, universalDeploy: true }; const deploy = TokenContract.deploy(this.wallet, deployer, name, ticker, decimals); - return this.registerOrDeployContract('Token - ' + name, deploy, deployOpts); + const instance = await this.registerOrDeployContract('Token - ' + name, deploy, deployOpts); + return TokenContract.at(instance.address, this.wallet); } private async setupAmmContract( @@ -231,12 +247,14 @@ export class BotFactory { ): Promise { const deployOpts: DeployOptions = { from: deployer, contractAddressSalt, universalDeploy: true }; const deploy = AMMContract.deploy(this.wallet, token0.address, token1.address, lpToken.address); - const amm = await this.registerOrDeployContract('AMM', deploy, deployOpts); + const instance = await this.registerOrDeployContract('AMM', deploy, deployOpts); + const amm = AMMContract.at(instance.address, this.wallet); this.log.info(`AMM deployed at ${amm.address}`); - const minterTx = lpToken.methods.set_minter(amm.address, true).send({ from: deployer }); - this.log.info(`Set LP token minter to AMM txHash=${(await minterTx.getTxHash()).toString()}`); - await minterTx.wait({ timeout: this.config.txMinedWaitSeconds }); + const minterReceipt = await lpToken.methods + .set_minter(amm.address, true) + .send({ from: deployer, wait: { timeout: this.config.txMinedWaitSeconds } }); + this.log.info(`Set LP token minter to AMM txHash=${minterReceipt.txHash.toString()}`); this.log.info(`Liquidity token initialized`); return amm; @@ -295,23 +313,22 @@ export class BotFactory { .getFunctionCall(), }); - const mintTx = new BatchCall(this.wallet, [ + const mintReceipt = await new BatchCall(this.wallet, [ token0.methods.mint_to_private(liquidityProvider, MINT_BALANCE), token1.methods.mint_to_private(liquidityProvider, MINT_BALANCE), - ]).send({ from: liquidityProvider }); + ]).send({ from: liquidityProvider, wait: { timeout: this.config.txMinedWaitSeconds } }); - this.log.info(`Sent mint tx: ${(await mintTx.getTxHash()).toString()}`); - await mintTx.wait({ timeout: this.config.txMinedWaitSeconds }); + this.log.info(`Sent mint tx: ${mintReceipt.txHash.toString()}`); - const addLiquidityTx = amm.methods + const addLiquidityReceipt = await amm.methods .add_liquidity(amount0Max, amount1Max, amount0Min, amount1Min, authwitNonce) .send({ from: liquidityProvider, authWitnesses: [token0Authwit, token1Authwit], + wait: { timeout: this.config.txMinedWaitSeconds }, }); - this.log.info(`Sent tx to add liquidity to the AMM: ${(await addLiquidityTx.getTxHash()).toString()}`); - await addLiquidityTx.wait({ timeout: this.config.txMinedWaitSeconds }); + this.log.info(`Sent tx to add liquidity to the AMM: ${addLiquidityReceipt.txHash.toString()}`); this.log.info(`Liquidity added`); const [newT0Bal, newT1Bal, newLPBal] = await getPrivateBalances(); @@ -324,19 +341,22 @@ export class BotFactory { name: string, deploy: DeployMethod, deployOpts: DeployOptions, - ): Promise { - const address = (await deploy.getInstance(deployOpts)).address; + ): Promise { + const instance = await deploy.getInstance(deployOpts); + const address = instance.address; const metadata = await this.wallet.getContractMetadata(address); if (metadata.isContractPublished) { this.log.info(`Contract ${name} at ${address.toString()} already deployed`); - return deploy.register(); + await deploy.register(); } else { this.log.info(`Deploying contract ${name} at ${address.toString()}`); - const sentTx = deploy.send(deployOpts); - const txHash = await sentTx.getTxHash(); - this.log.info(`Sent contract ${name} setup tx with hash ${txHash.toString()}`); - return this.withNoMinTxsPerBlock(() => sentTx.deployed({ timeout: this.config.txMinedWaitSeconds })); + await this.withNoMinTxsPerBlock(async () => { + const txHash = await deploy.send({ ...deployOpts, wait: NO_WAIT }); + this.log.info(`Sent contract ${name} setup tx with hash ${txHash.toString()}`); + return waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds }); + }); } + return instance; } /** @@ -372,10 +392,12 @@ export class BotFactory { this.log.info(`Skipping minting as ${minter.toString()} has enough tokens`); return; } - const sentTx = new BatchCall(token.wallet, calls).send({ from: minter }); - const txHash = await sentTx.getTxHash(); - this.log.info(`Sent token mint tx with hash ${txHash.toString()}`); - await this.withNoMinTxsPerBlock(() => sentTx.wait({ timeout: this.config.txMinedWaitSeconds })); + + await this.withNoMinTxsPerBlock(async () => { + const txHash = await new BatchCall(token.wallet, calls).send({ from: minter, wait: NO_WAIT }); + this.log.info(`Sent token mint tx with hash ${txHash.toString()}`); + return waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds }); + }); } /** diff --git a/yarn-project/cli-wallet/src/cmds/authorize_action.ts b/yarn-project/cli-wallet/src/cmds/authorize_action.ts index bd5847b2d069..13554cbe3ecb 100644 --- a/yarn-project/cli-wallet/src/cmds/authorize_action.ts +++ b/yarn-project/cli-wallet/src/cmds/authorize_action.ts @@ -39,7 +39,7 @@ export async function authorizeAction( { caller, action }, true, ); - const witness = await setAuthwitnessInteraction.send().wait({ timeout: DEFAULT_TX_TIMEOUT_S }); + const witness = await setAuthwitnessInteraction.send({ wait: { timeout: DEFAULT_TX_TIMEOUT_S } }); log(`Authorized action ${functionName} on contract ${contractAddress} for caller ${caller}`); diff --git a/yarn-project/cli-wallet/src/cmds/create_account.ts b/yarn-project/cli-wallet/src/cmds/create_account.ts index 536f604a36ab..64b730b95aa1 100644 --- a/yarn-project/cli-wallet/src/cmds/create_account.ts +++ b/yarn-project/cli-wallet/src/cmds/create_account.ts @@ -1,9 +1,11 @@ import { AztecAddress } from '@aztec/aztec.js/addresses'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import type { AztecNode } from '@aztec/aztec.js/node'; import type { DeployAccountOptions } from '@aztec/aztec.js/wallet'; import { prettyPrintJSON } from '@aztec/cli/cli-utils'; import { Fr } from '@aztec/foundation/curves/bn254'; import type { LogFn, Logger } from '@aztec/foundation/log'; +import type { TxHash, TxReceipt } from '@aztec/stdlib/tx'; import { DEFAULT_TX_TIMEOUT_S } from '../utils/cli_wallet_and_node_wrapper.js'; import type { AccountType } from '../utils/constants.js'; @@ -64,8 +66,8 @@ export async function createAccount( log(`Init hash: ${account.getInstance().initializationHash.toString()}`); } - let tx; - let txReceipt; + let txHash: TxHash | undefined; + let txReceipt: TxReceipt | undefined; if (!registerOnly) { const { paymentMethod, gasSettings } = await feeOpts.toUserFeeOptions(aztecNode, wallet, address); @@ -100,7 +102,14 @@ export async function createAccount( }; } } else { - tx = deployMethod.send({ + if (verbose) { + printProfileResult(stats, log); + } + + if (!json) { + log(`\nWaiting for account contract deployment...`); + } + const result = await deployMethod.send({ ...deployAccountOpts, fee: deployAccountOpts.fee ? { @@ -108,32 +117,29 @@ export async function createAccount( gasSettings: estimatedGas, } : undefined, + wait: wait ? { timeout: DEFAULT_TX_TIMEOUT_S, returnReceipt: true } : NO_WAIT, }); - if (verbose) { - printProfileResult(stats, log); - } - - const txHash = await tx.getTxHash(); - debugLogger.debug(`Account contract tx sent with hash ${txHash.toString()}`); - out.txHash = txHash; - if (wait) { - if (!json) { - log(`\nWaiting for account contract deployment...`); - } - txReceipt = await tx.wait({ timeout: DEFAULT_TX_TIMEOUT_S }); + const isReceipt = (data: TxReceipt | TxHash): data is TxReceipt => 'txHash' in data; + if (isReceipt(result)) { + txReceipt = result; + txHash = result.txHash; out.txReceipt = { status: txReceipt.status, transactionFee: txReceipt.transactionFee, }; + } else { + txHash = result; } + debugLogger.debug(`Account contract tx sent with hash ${txHash.toString()}`); + out.txHash = txHash; } } if (json) { log(prettyPrintJSON(out)); } else { - if (tx) { - log(`Deploy tx hash: ${(await tx.getTxHash()).toString()}`); + if (txHash) { + log(`Deploy tx hash: ${txHash.toString()}`); } if (txReceipt) { log(`Deploy tx fee: ${txReceipt.transactionFee}`); diff --git a/yarn-project/cli-wallet/src/cmds/deploy.ts b/yarn-project/cli-wallet/src/cmds/deploy.ts index b51624ed3717..0de9615aa276 100644 --- a/yarn-project/cli-wallet/src/cmds/deploy.ts +++ b/yarn-project/cli-wallet/src/cmds/deploy.ts @@ -1,5 +1,6 @@ import { AztecAddress } from '@aztec/aztec.js/addresses'; import type { DeployOptions } from '@aztec/aztec.js/contracts'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { ContractDeployer } from '@aztec/aztec.js/deployment'; import { Fr } from '@aztec/aztec.js/fields'; import type { AztecNode } from '@aztec/aztec.js/node'; @@ -89,37 +90,55 @@ export async function deploy( }; } } else { - const tx = deploy.send(deployOpts); if (verbose) { printProfileResult(stats, log); } - const txHash = await tx.getTxHash(); - debugLogger.debug(`Deploy tx sent with hash ${txHash.toString()}`); - out.hash = txHash; const { address, partialAddress } = deploy; const instance = await deploy.getInstance(); - if (!json) { - log(`Contract deployed at ${address?.toString()}`); - log(`Contract partial address ${(await partialAddress)?.toString()}`); - log(`Contract init hash ${instance.initializationHash.toString()}`); - log(`Deployment tx hash: ${txHash.toString()}`); - log(`Deployment salt: ${salt.toString()}`); - log(`Deployer: ${instance.deployer.toString()}`); - } else { - out.contract = { - address: address?.toString(), - partialAddress: (await partialAddress)?.toString(), - initializationHash: instance.initializationHash.toString(), - salt: salt.toString(), - }; - } + if (wait) { - const deployed = await tx.wait({ timeout }); + const receipt = await deploy.send({ ...deployOpts, wait: { timeout, returnReceipt: true } }); + const txHash = receipt.txHash; + debugLogger.debug(`Deploy tx sent with hash ${txHash.toString()}`); + out.hash = txHash; + + if (!json) { + log(`Contract deployed at ${address?.toString()}`); + log(`Contract partial address ${(await partialAddress)?.toString()}`); + log(`Contract init hash ${instance.initializationHash.toString()}`); + log(`Deployment tx hash: ${txHash.toString()}`); + log(`Deployment salt: ${salt.toString()}`); + log(`Deployer: ${instance.deployer.toString()}`); + log(`Transaction fee: ${receipt.transactionFee?.toString()}`); + } else { + out.contract = { + address: address?.toString(), + partialAddress: (await partialAddress)?.toString(), + initializationHash: instance.initializationHash.toString(), + salt: salt.toString(), + transactionFee: receipt.transactionFee?.toString(), + }; + } + } else { + const txHash = await deploy.send({ ...deployOpts, wait: NO_WAIT }); + debugLogger.debug(`Deploy tx sent with hash ${txHash.toString()}`); + out.hash = txHash; + if (!json) { - log(`Transaction fee: ${deployed.transactionFee?.toString()}`); + log(`Contract deployed at ${address?.toString()}`); + log(`Contract partial address ${(await partialAddress)?.toString()}`); + log(`Contract init hash ${instance.initializationHash.toString()}`); + log(`Deployment tx hash: ${txHash.toString()}`); + log(`Deployment salt: ${salt.toString()}`); + log(`Deployer: ${instance.deployer.toString()}`); } else { - out.contract.transactionFee = deployed.transactionFee?.toString(); + out.contract = { + address: address?.toString(), + partialAddress: (await partialAddress)?.toString(), + initializationHash: instance.initializationHash.toString(), + salt: salt.toString(), + }; } } } diff --git a/yarn-project/cli-wallet/src/cmds/deploy_account.ts b/yarn-project/cli-wallet/src/cmds/deploy_account.ts index 97dd46efbd11..f18037e7cbb6 100644 --- a/yarn-project/cli-wallet/src/cmds/deploy_account.ts +++ b/yarn-project/cli-wallet/src/cmds/deploy_account.ts @@ -1,8 +1,10 @@ import { AztecAddress } from '@aztec/aztec.js/addresses'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import type { AztecNode } from '@aztec/aztec.js/node'; import type { DeployAccountOptions } from '@aztec/aztec.js/wallet'; import { prettyPrintJSON } from '@aztec/cli/cli-utils'; import type { LogFn, Logger } from '@aztec/foundation/log'; +import type { TxHash, TxReceipt } from '@aztec/stdlib/tx'; import { DEFAULT_TX_TIMEOUT_S } from '../utils/cli_wallet_and_node_wrapper.js'; import type { CLIFeeArgs } from '../utils/options/fees.js'; @@ -45,8 +47,8 @@ export async function deployAccount( log(`Init hash: ${initializationHash.toString()}`); } - let tx; - let txReceipt; + let txHash: TxHash | undefined; + let txReceipt: TxReceipt | undefined; const { paymentMethod, gasSettings } = await feeOpts.toUserFeeOptions(aztecNode, wallet, address); const delegatedDeployment = deployer && !account.address.equals(deployer); @@ -80,7 +82,14 @@ export async function deployAccount( }; } } else { - tx = deployMethod.send({ + if (verbose) { + printProfileResult(stats, log); + } + + if (!json) { + log(`\nWaiting for account contract deployment...`); + } + const result = await deployMethod.send({ ...deployAccountOpts, fee: deployAccountOpts.fee ? { @@ -88,31 +97,28 @@ export async function deployAccount( gasSettings: estimatedGas, } : undefined, + wait: wait ? { timeout: DEFAULT_TX_TIMEOUT_S, returnReceipt: true } : NO_WAIT, }); - if (verbose) { - printProfileResult(stats, log); - } - - const txHash = await tx.getTxHash(); - debugLogger.debug(`Account contract tx sent with hash ${txHash.toString()}`); - out.txHash = txHash; - if (wait) { - if (!json) { - log(`\nWaiting for account contract deployment...`); - } - txReceipt = await tx.wait({ timeout: DEFAULT_TX_TIMEOUT_S }); + const isReceipt = (data: TxReceipt | TxHash): data is TxReceipt => 'txHash' in data; + if (isReceipt(result)) { + txReceipt = result; + txHash = result.txHash; out.txReceipt = { status: txReceipt.status, transactionFee: txReceipt.transactionFee, }; + } else { + txHash = result; } + debugLogger.debug(`Account contract tx sent with hash ${txHash.toString()}`); + out.txHash = txHash; } if (json) { log(prettyPrintJSON(out)); } else { - if (tx) { - log(`Deploy tx hash: ${(await tx.getTxHash()).toString()}`); + if (txHash) { + log(`Deploy tx hash: ${txHash.toString()}`); } if (txReceipt) { log(`Deploy tx fee: ${txReceipt.transactionFee}`); diff --git a/yarn-project/cli-wallet/src/cmds/send.ts b/yarn-project/cli-wallet/src/cmds/send.ts index 72abfdce1874..4059db13a93b 100644 --- a/yarn-project/cli-wallet/src/cmds/send.ts +++ b/yarn-project/cli-wallet/src/cmds/send.ts @@ -1,6 +1,6 @@ import type { AztecAddress } from '@aztec/aztec.js/addresses'; import { AuthWitness } from '@aztec/aztec.js/authorization'; -import { Contract, type SendInteractionOptions } from '@aztec/aztec.js/contracts'; +import { Contract, NO_WAIT, type SendInteractionOptions } from '@aztec/aztec.js/contracts'; import type { AztecNode } from '@aztec/aztec.js/node'; import { prepTx } from '@aztec/cli/utils'; import type { LogFn } from '@aztec/foundation/log'; @@ -46,31 +46,43 @@ export async function send( return; } - const tx = call.send({ ...sendOptions, fee: { ...sendOptions.fee, gasSettings: estimatedGas } }); if (verbose) { printProfileResult(stats!, log); } - const txHash = await tx.getTxHash(); - log(`\nTransaction hash: ${txHash.toString()}`); if (wait) { try { - await tx.wait({ timeout: DEFAULT_TX_TIMEOUT_S }); + const receipt = await call.send({ + ...sendOptions, + fee: { ...sendOptions.fee, gasSettings: estimatedGas }, + wait: { timeout: DEFAULT_TX_TIMEOUT_S }, + }); + const txHash = receipt.txHash; + log(`\nTransaction hash: ${txHash.toString()}`); log('Transaction has been mined'); - - const receipt = await tx.getReceipt(); log(` Tx fee: ${receipt.transactionFee}`); log(` Status: ${receipt.status}`); log(` Block number: ${receipt.blockNumber}`); log(` Block hash: ${receipt.blockHash?.toString()}`); + + return { + txHash, + }; } catch (err: any) { log(`Transaction failed\n ${err.message}`); + throw err; } } else { + const txHash = await call.send({ + ...sendOptions, + fee: { ...sendOptions.fee, gasSettings: estimatedGas }, + wait: NO_WAIT, + }); + log(`\nTransaction hash: ${txHash.toString()}`); log('Transaction pending. Check status with check-tx'); + return { + txHash, + }; } - return { - txHash, - }; } diff --git a/yarn-project/cli/src/cmds/infrastructure/setup_l2_contract.ts b/yarn-project/cli/src/cmds/infrastructure/setup_l2_contract.ts index 154b8c917270..e4bd728a64bc 100644 --- a/yarn-project/cli/src/cmds/infrastructure/setup_l2_contract.ts +++ b/yarn-project/cli/src/cmds/infrastructure/setup_l2_contract.ts @@ -22,7 +22,7 @@ export async function setupL2Contracts(nodeUrl: string, testAccounts: boolean, j if (testAccounts) { log('setupL2Contracts: Deploying test accounts...'); const initialAccountsData = await getInitialTestAccountsData(); - deployedAccountManagers = await deployFundedSchnorrAccounts(wallet, node, initialAccountsData, waitOpts); + deployedAccountManagers = await deployFundedSchnorrAccounts(wallet, initialAccountsData, waitOpts); } if (json) { diff --git a/yarn-project/end-to-end/src/bench/client_flows/account_deployments.test.ts b/yarn-project/end-to-end/src/bench/client_flows/account_deployments.test.ts index ff7c4cdaa019..e9f7fabc8095 100644 --- a/yarn-project/end-to-end/src/bench/client_flows/account_deployments.test.ts +++ b/yarn-project/end-to-end/src/bench/client_flows/account_deployments.test.ts @@ -34,7 +34,7 @@ describe('Deployment benchmark', () => { // The typical interaction would be for a user to deploy an account contract that is already registered in the // network. const publishContractClassInteraction = await publishContractClass(adminWallet, EcdsaRAccountContractArtifact); - await publishContractClassInteraction.send({ from: adminAddress }).wait(); + await publishContractClassInteraction.send({ from: adminAddress }); }); afterAll(async () => { @@ -91,7 +91,7 @@ describe('Deployment benchmark', () => { if (process.env.SANITY_CHECKS) { // Ensure we paid a fee - const tx = await deploymentInteraction.send(options).wait(); + const tx = await deploymentInteraction.send({ ...options, wait: { returnReceipt: true } }); expect(tx.transactionFee!).toBeGreaterThan(0n); } }); diff --git a/yarn-project/end-to-end/src/bench/client_flows/amm.test.ts b/yarn-project/end-to-end/src/bench/client_flows/amm.test.ts index 8e057945b9de..2605fb717304 100644 --- a/yarn-project/end-to-end/src/bench/client_flows/amm.test.ts +++ b/yarn-project/end-to-end/src/bench/client_flows/amm.test.ts @@ -199,7 +199,7 @@ describe('AMM benchmark', () => { ); if (process.env.SANITY_CHECKS) { - const tx = await addLiquidityInteraction.send({ from: benchysAddress }).wait(); + const tx = await addLiquidityInteraction.send({ from: benchysAddress }); expect(tx.transactionFee!).toBeGreaterThan(0n); } diff --git a/yarn-project/end-to-end/src/bench/client_flows/bridging.test.ts b/yarn-project/end-to-end/src/bench/client_flows/bridging.test.ts index f62809feb73d..0800c709ea82 100644 --- a/yarn-project/end-to-end/src/bench/client_flows/bridging.test.ts +++ b/yarn-project/end-to-end/src/bench/client_flows/bridging.test.ts @@ -106,7 +106,7 @@ describe('Bridging benchmark', () => { if (process.env.SANITY_CHECKS) { // Ensure we paid a fee - const tx = await claimInteraction.send(options).wait(); + const tx = await claimInteraction.send(options); expect(tx.transactionFee!).toBeGreaterThan(0n); // 4. Check the balance diff --git a/yarn-project/end-to-end/src/bench/client_flows/client_flows_benchmark.ts b/yarn-project/end-to-end/src/bench/client_flows/client_flows_benchmark.ts index 84628ad02b3e..8626179a25eb 100644 --- a/yarn-project/end-to-end/src/bench/client_flows/client_flows_benchmark.ts +++ b/yarn-project/end-to-end/src/bench/client_flows/client_flows_benchmark.ts @@ -156,8 +156,7 @@ export class ClientFlowsBenchmark { const { claimSecret: secret, messageLeafIndex: index } = claim; await this.feeJuiceContract.methods .claim(address, claim.claimAmount, secret, index) - .send({ from: this.adminAddress }) - .wait(); + .send({ from: this.adminAddress }); } /** Admin mints bananaCoin tokens privately to the target address and redeems them. */ @@ -252,9 +251,7 @@ export class ClientFlowsBenchmark { 'BC', 'BC', 18n, - ) - .send({ from: this.adminAddress }) - .wait(); + ).send({ from: this.adminAddress, wait: { returnReceipt: true } }); this.logger.info(`BananaCoin deployed at ${bananaCoin.address}`); this.bananaCoin = bananaCoin; this.bananaCoinInstance = bananaCoinInstance; @@ -268,9 +265,7 @@ export class ClientFlowsBenchmark { 'CBC', 'CBC', 18n, - ) - .send({ from: this.adminAddress }) - .wait(); + ).send({ from: this.adminAddress, wait: { returnReceipt: true } }); this.logger.info(`CandyBarCoin deployed at ${candyBarCoin.address}`); this.candyBarCoin = candyBarCoin; this.candyBarCoinInstance = candyBarCoinInstance; @@ -286,9 +281,7 @@ export class ClientFlowsBenchmark { this.adminWallet, bananaCoin.address, this.adminAddress, - ) - .send({ from: this.adminAddress }) - .wait(); + ).send({ from: this.adminAddress, wait: { returnReceipt: true } }); this.logger.info(`BananaPay deployed at ${bananaFPC.address}`); @@ -336,12 +329,10 @@ export class ClientFlowsBenchmark { const benchysAddress = benchysAccountManager.address; const claim = await this.feeJuiceBridgeTestHarness.prepareTokensOnL1(benchysAddress); const behchysDeployMethod = await benchysAccountManager.getDeployMethod(); - await behchysDeployMethod - .send({ - from: AztecAddress.ZERO, - fee: { paymentMethod: new FeeJuicePaymentMethodWithClaim(benchysAddress, claim) }, - }) - .wait(); + await behchysDeployMethod.send({ + from: AztecAddress.ZERO, + fee: { paymentMethod: new FeeJuicePaymentMethodWithClaim(benchysAddress, claim) }, + }); // Register benchy on the user's Wallet, where we're going to be interacting from const accountManager = await this.userWallet.createAccount({ secret: benchysAccount.getSecretKey(), @@ -359,19 +350,15 @@ export class ClientFlowsBenchmark { 'LPT', 'LPT', 18n, - ) - .send({ from: this.adminAddress }) - .wait(); + ).send({ from: this.adminAddress, wait: { returnReceipt: true } }); const { contract: amm, instance: ammInstance } = await AMMContract.deploy( this.adminWallet, this.bananaCoin.address, this.candyBarCoin.address, liquidityToken.address, - ) - .send({ from: this.adminAddress }) - .wait(); + ).send({ from: this.adminAddress, wait: { returnReceipt: true } }); this.logger.info(`AMM deployed at ${amm.address}`); - await liquidityToken.methods.set_minter(amm.address, true).send({ from: this.adminAddress }).wait(); + await liquidityToken.methods.set_minter(amm.address, true).send({ from: this.adminAddress }); this.liquidityToken = liquidityToken; this.liquidityTokenInstance = liquidityTokenInstance; this.amm = amm; diff --git a/yarn-project/end-to-end/src/bench/client_flows/deployments.test.ts b/yarn-project/end-to-end/src/bench/client_flows/deployments.test.ts index 1e9673b2d795..124e0b0cbbae 100644 --- a/yarn-project/end-to-end/src/bench/client_flows/deployments.test.ts +++ b/yarn-project/end-to-end/src/bench/client_flows/deployments.test.ts @@ -86,7 +86,7 @@ describe('Deployment benchmark', () => { if (process.env.SANITY_CHECKS) { // Ensure we paid a fee - const tx = await deploymentInteraction.send(options).wait(); + const tx = await deploymentInteraction.send({ ...options, wait: { returnReceipt: true } }); expect(tx.transactionFee!).toBeGreaterThan(0n); } }); diff --git a/yarn-project/end-to-end/src/bench/client_flows/transfers.test.ts b/yarn-project/end-to-end/src/bench/client_flows/transfers.test.ts index b720455fd6d2..aab3b430c825 100644 --- a/yarn-project/end-to-end/src/bench/client_flows/transfers.test.ts +++ b/yarn-project/end-to-end/src/bench/client_flows/transfers.test.ts @@ -126,7 +126,7 @@ describe('Transfer benchmark', () => { caller: adminAddress, action: interaction, }); - await interaction.send({ from: adminAddress, authWitnesses: [witness] }).wait({ timeout: 120 }); + await interaction.send({ from: adminAddress, authWitnesses: [witness], wait: { timeout: 120 } }); }); // Ensure we create a change note, by sending an amount that is not a multiple of the note amount @@ -161,7 +161,7 @@ describe('Transfer benchmark', () => { if (process.env.SANITY_CHECKS) { // Ensure we paid a fee - const tx = await transferInteraction.send(options).wait(); + const tx = await transferInteraction.send(options); expect(tx.transactionFee!).toBeGreaterThan(0n); // Sanity checks diff --git a/yarn-project/end-to-end/src/bench/node_rpc_perf.test.ts b/yarn-project/end-to-end/src/bench/node_rpc_perf.test.ts index 33b54f81222b..33f0439fbc67 100644 --- a/yarn-project/end-to-end/src/bench/node_rpc_perf.test.ts +++ b/yarn-project/end-to-end/src/bench/node_rpc_perf.test.ts @@ -150,9 +150,9 @@ describe('e2e_node_rpc_perf', () => { })); logger.info('Deploying token contract...'); - tokenContract = await TokenContract.deploy(wallet, ownerAddress, 'TestToken', 'TST', 18n) - .send({ from: ownerAddress }) - .deployed({ timeout: 600 }); + tokenContract = await TokenContract.deploy(wallet, ownerAddress, 'TestToken', 'TST', 18n).send({ + from: ownerAddress, + }); contractAddress = tokenContract.address; logger.info(`Token contract deployed at ${contractAddress}`); @@ -189,8 +189,7 @@ describe('e2e_node_rpc_perf', () => { from: ownerAddress, }); - const sentTx = provenTx.send(); - const receipt = await sentTx.wait({ timeout: 600 }); + const receipt = await provenTx.send({ wait: { timeout: 600 } }); txHashes.push(receipt.txHash); logger.verbose(`Transaction ${receipt.txHash} included in block ${receipt.blockNumber}`); logger.info(`Block ${block + 1}/${BLOCKS_TO_BUILD} built`); diff --git a/yarn-project/end-to-end/src/bench/utils.ts b/yarn-project/end-to-end/src/bench/utils.ts index ea7c206d5848..e79f893be745 100644 --- a/yarn-project/end-to-end/src/bench/utils.ts +++ b/yarn-project/end-to-end/src/bench/utils.ts @@ -1,8 +1,10 @@ import type { AztecNodeService } from '@aztec/aztec-node'; import { AztecAddress } from '@aztec/aztec.js/addresses'; -import { BatchCall, type SentTx, type WaitOpts } from '@aztec/aztec.js/contracts'; +import { BatchCall, NO_WAIT, type WaitOpts } from '@aztec/aztec.js/contracts'; +import { waitForTx } from '@aztec/aztec.js/node'; import { mean, stdDev, times } from '@aztec/foundation/collection'; import { BenchmarkingContract } from '@aztec/noir-test-contracts.js/Benchmarking'; +import type { TxHash } from '@aztec/stdlib/tx'; import type { MetricDefinition } from '@aztec/telemetry-client'; import type { BenchmarkDataPoint, BenchmarkMetricsType, BenchmarkTelemetryClient } from '@aztec/telemetry-client/bench'; @@ -23,7 +25,7 @@ export async function benchmarkSetup( ) { const context = await setup(1, { ...opts, telemetryConfig: { benchmark: true } }); const defaultAccountAddress = context.accounts[0]; - const contract = await BenchmarkingContract.deploy(context.wallet).send({ from: defaultAccountAddress }).deployed(); + const contract = await BenchmarkingContract.deploy(context.wallet).send({ from: defaultAccountAddress }); context.logger.info(`Deployed benchmarking contract at ${contract.address}`); const sequencer = (context.aztecNode as AztecNodeService).getSequencer()!; const telemetry = context.telemetryClient! as BenchmarkTelemetryClient; @@ -142,18 +144,18 @@ export async function sendTxs( context: EndToEndContext, contract: BenchmarkingContract, heavyPublicCompute: boolean = false, -): Promise { +): Promise { const calls = await Promise.all(times(txCount, index => makeCall(index, context, contract, heavyPublicCompute))); context.logger.info(`Creating ${txCount} txs`); const [from] = context.accounts; context.logger.info(`Sending ${txCount} txs`); - return calls.map(call => call.send({ from })); + return Promise.all(calls.map(call => call.send({ from, wait: NO_WAIT }))); } -export async function waitTxs(txs: SentTx[], context: EndToEndContext, txWaitOpts?: WaitOpts) { +export async function waitTxs(txs: TxHash[], context: EndToEndContext, txWaitOpts?: WaitOpts) { context.logger.info(`Awaiting ${txs.length} txs to be mined`); - await Promise.all(txs.map(tx => tx.wait(txWaitOpts))); - context.logger.info(`All ${txs.length} txs have been mined`); + await Promise.all(txs.map(txHash => waitForTx(context.aztecNode, txHash, txWaitOpts))); + context.logger.info(`${txs.length} txs have been mined`); } function randomBytesAsBigInts(length: number): bigint[] { diff --git a/yarn-project/end-to-end/src/composed/docs_examples.test.ts b/yarn-project/end-to-end/src/composed/docs_examples.test.ts index 46b0019a3598..241fa069c58d 100644 --- a/yarn-project/end-to-end/src/composed/docs_examples.test.ts +++ b/yarn-project/end-to-end/src/composed/docs_examples.test.ts @@ -29,7 +29,7 @@ describe('docs_examples', () => { const prefundedAccount = await wallet.createSchnorrAccount(accountData.secret, accountData.salt); const newAccountManager = await wallet.createSchnorrAccount(secretKey, Fr.random(), signingPrivateKey); const newAccountDeployMethod = await newAccountManager.getDeployMethod(); - await newAccountDeployMethod.send({ from: prefundedAccount.address }).wait(); + await newAccountDeployMethod.send({ from: prefundedAccount.address }); const newAccountAddress = newAccountManager.address; const defaultAccountAddress = prefundedAccount.address; @@ -39,13 +39,11 @@ describe('docs_examples', () => { 'TokenName', // constructor arg1 'TokenSymbol', // constructor arg2 18, - ) - .send({ from: defaultAccountAddress }) - .deployed(); + ).send({ from: defaultAccountAddress }); const contract = Contract.at(deployedContract.address, TokenContractArtifact, wallet); - await contract.methods.mint_to_public(newAccountAddress, 1).send({ from: defaultAccountAddress }).wait(); + await contract.methods.mint_to_public(newAccountAddress, 1).send({ from: defaultAccountAddress }); // docs:start:simulate_function const balance = await contract.methods.balance_of_public(newAccountAddress).simulate({ from: newAccountAddress }); diff --git a/yarn-project/end-to-end/src/composed/e2e_local_network_example.test.ts b/yarn-project/end-to-end/src/composed/e2e_local_network_example.test.ts index 9a85fa268a21..da573f18d201 100644 --- a/yarn-project/end-to-end/src/composed/e2e_local_network_example.test.ts +++ b/yarn-project/end-to-end/src/composed/e2e_local_network_example.test.ts @@ -84,7 +84,7 @@ describe('e2e_local_network_example', () => { // We will now transfer tokens from ALice to Bob const transferQuantity = 543n; logger.info(`Transferring ${transferQuantity} tokens from Alice to Bob...`); - await tokenContract.methods.transfer(bob, transferQuantity).send({ from: alice }).wait(); + await tokenContract.methods.transfer(bob, transferQuantity).send({ from: alice }); // Check the new balances aliceBalance = await tokenContract.methods.balance_of_private(alice).simulate({ from: alice }); @@ -101,7 +101,7 @@ describe('e2e_local_network_example', () => { // Now mint some further funds for Bob // Alice is nice and she adds Bob as a minter - await tokenContract.methods.set_minter(bob, true).send({ from: alice }).wait(); + await tokenContract.methods.set_minter(bob, true).send({ from: alice }); const mintQuantity = 10_000n; await mintTokensToPrivate(tokenContract, bob, bob, mintQuantity); @@ -144,7 +144,7 @@ describe('e2e_local_network_example', () => { return await Promise.all( accountManagers.map(async x => { const deployMethod = await x.getDeployMethod(); - await deployMethod.send({ from: fundedAccount }).wait(); + await deployMethod.send({ from: fundedAccount }); return x; }), ); @@ -176,7 +176,7 @@ describe('e2e_local_network_example', () => { const bananaCoinAddress = await registerDeployedBananaCoinInWalletAndGetAddress(wallet); const bananaCoin = TokenContract.at(bananaCoinAddress, wallet); const mintAmount = 10n ** 20n; - await bananaCoin.methods.mint_to_private(alice, mintAmount).send({ from: fundedAccount }).wait(); + await bananaCoin.methods.mint_to_private(alice, mintAmount).send({ from: fundedAccount }); ////////////// USE A NEW ACCOUNT TO SEND A TX AND PAY WITH BANANA COIN ////////////// const amountTransferToBob = 100n; @@ -189,8 +189,7 @@ describe('e2e_local_network_example', () => { const paymentMethod = new PrivateFeePaymentMethod(bananaFPCAddress, alice, wallet, gasSettings); const receiptForAlice = await bananaCoin.methods .transfer(bob, amountTransferToBob) - .send({ from: alice, fee: { paymentMethod } }) - .wait(); + .send({ from: alice, fee: { paymentMethod } }); // docs:end:private_fpc_payment const transactionFee = receiptForAlice.transactionFee!; logger.info(`Transaction fee: ${transactionFee}`); @@ -216,8 +215,7 @@ describe('e2e_local_network_example', () => { const receiptForBob = await bananaCoin.methods .transfer(alice, amountTransferToAlice) - .send({ from: bob, fee: { paymentMethod: sponsoredPaymentMethod } }) - .wait(); + .send({ from: bob, fee: { paymentMethod: sponsoredPaymentMethod } }); // docs:end:sponsored_fpc_payment // Check the balances const aliceNewBalance = await bananaCoin.methods.balance_of_private(alice).simulate({ from: alice }); diff --git a/yarn-project/end-to-end/src/composed/e2e_persistence.test.ts b/yarn-project/end-to-end/src/composed/e2e_persistence.test.ts index d8ca4d83ef1b..6347ad1fe976 100644 --- a/yarn-project/end-to-end/src/composed/e2e_persistence.test.ts +++ b/yarn-project/end-to-end/src/composed/e2e_persistence.test.ts @@ -68,19 +68,17 @@ describe('Aztec persistence', () => { owner = initialFundedAccounts[0]; ownerAddress = owner.address; - const { contract, instance } = await TokenBlacklistContract.deploy(wallet, ownerAddress) - .send({ from: ownerAddress }) - .wait(); + const { contract, instance } = await TokenBlacklistContract.deploy(wallet, ownerAddress).send({ + from: ownerAddress, + wait: { returnReceipt: true }, + }); contractInstance = instance; contractAddress = contract.address; await progressBlocksPastDelay(contract); const adminMinterRole = new Role().withAdmin().withMinter(); - await contract.methods - .update_roles(ownerAddress, adminMinterRole.toNoirStruct()) - .send({ from: ownerAddress }) - .wait(); + await contract.methods.update_roles(ownerAddress, adminMinterRole.toNoirStruct()).send({ from: ownerAddress }); await progressBlocksPastDelay(contract); @@ -88,8 +86,7 @@ describe('Aztec persistence', () => { const mintTxReceipt = await contract.methods .mint_private(1000n, await computeSecretHash(secret)) - .send({ from: ownerAddress }) - .wait(); + .send({ from: ownerAddress }); await addPendingShieldNoteToPXE( contract, @@ -100,7 +97,7 @@ describe('Aztec persistence', () => { aztecNode, ); - await contract.methods.redeem_shield(ownerAddress, 1000n, secret).send({ from: ownerAddress }).wait(); + await contract.methods.redeem_shield(ownerAddress, 1000n, secret).send({ from: ownerAddress }); await progressBlocksPastDelay(contract); @@ -109,7 +106,7 @@ describe('Aztec persistence', () => { const progressBlocksPastDelay = async (contract: TokenBlacklistContract) => { for (let i = 0; i < BlacklistTokenContractTest.CHANGE_ROLES_DELAY; ++i) { - await contract.methods.get_roles(ownerAddress).send({ from: ownerAddress }).wait(); + await contract.methods.get_roles(ownerAddress).send({ from: ownerAddress }); } }; @@ -156,8 +153,7 @@ describe('Aztec persistence', () => { const secret = Fr.random(); const mintTxReceipt = await contract.methods .mint_private(1000n, await computeSecretHash(secret)) - .send({ from: ownerAddress }) - .wait(); + .send({ from: ownerAddress }); await addPendingShieldNoteToPXE( contract, ownerAddress, @@ -167,7 +163,7 @@ describe('Aztec persistence', () => { aztecNode, ); - await contract.methods.redeem_shield(ownerAddress, 1000n, secret).send({ from: ownerAddress }).wait(); + await contract.methods.redeem_shield(ownerAddress, 1000n, secret).send({ from: ownerAddress }); await expect(contract.methods.balance_of_private(ownerAddress).simulate({ from: ownerAddress })).resolves.toEqual( balance + 1000n, @@ -183,7 +179,7 @@ describe('Aztec persistence', () => { .balance_of_private(ownerAddress) .simulate({ from: ownerAddress }); - await contract.methods.transfer(ownerAddress, otherAddress, 500n, 0).send({ from: ownerAddress }).wait(); + await contract.methods.transfer(ownerAddress, otherAddress, 500n, 0).send({ from: ownerAddress }); const [ownerBalance, targetBalance] = await Promise.all([ contract.methods.balance_of_private(ownerAddress).simulate({ from: ownerAddress }), @@ -280,16 +276,12 @@ describe('Aztec persistence', () => { mintAmount = 1000n; const mintTxReceipt = await contract.methods .mint_private(mintAmount, await computeSecretHash(secret)) - .send({ from: ownerAddress }) - .wait(); + .send({ from: ownerAddress }); mintTxHash = mintTxReceipt.txHash; // publicly reveal that I have 1000 tokens revealedAmount = 1000n; - await contract.methods - .unshield(ownerAddress, ownerAddress, revealedAmount, 0) - .send({ from: ownerAddress }) - .wait(); + await contract.methods.unshield(ownerAddress, ownerAddress, revealedAmount, 0).send({ from: ownerAddress }); // shut everything down await temporaryContext.teardown(); @@ -329,7 +321,7 @@ describe('Aztec persistence', () => { .balance_of_private(ownerAddress) .simulate({ from: ownerAddress }); - await contract.methods.redeem_shield(ownerAddress, mintAmount, secret).send({ from: ownerAddress }).wait(); + await contract.methods.redeem_shield(ownerAddress, mintAmount, secret).send({ from: ownerAddress }); const balanceAfterRedeem = await contract.methods .balance_of_private(ownerAddress) .simulate({ from: ownerAddress }); diff --git a/yarn-project/end-to-end/src/composed/e2e_token_bridge_tutorial_test.test.ts b/yarn-project/end-to-end/src/composed/e2e_token_bridge_tutorial_test.test.ts index 3721f7abc9e5..27950f695f1c 100644 --- a/yarn-project/end-to-end/src/composed/e2e_token_bridge_tutorial_test.test.ts +++ b/yarn-project/end-to-end/src/composed/e2e_token_bridge_tutorial_test.test.ts @@ -99,9 +99,9 @@ describe('e2e_cross_chain_messaging token_bridge_tutorial_test', () => { // Deploy L2 token contract // docs:start:deploy-l2-token - const l2TokenContract = await TokenContract.deploy(wallet, ownerAztecAddress, 'L2 Token', 'L2', 18) - .send({ from: ownerAztecAddress }) - .deployed(); + const l2TokenContract = await TokenContract.deploy(wallet, ownerAztecAddress, 'L2 Token', 'L2', 18).send({ + from: ownerAztecAddress, + }); logger.info(`L2 token contract deployed at ${l2TokenContract.address}`); // docs:end:deploy-l2-token @@ -129,15 +129,17 @@ describe('e2e_cross_chain_messaging token_bridge_tutorial_test', () => { // docs:end:deploy-portal // Deploy L2 bridge contract // docs:start:deploy-l2-bridge - const l2BridgeContract = await TokenBridgeContract.deploy(wallet, l2TokenContract.address, l1PortalContractAddress) - .send({ from: ownerAztecAddress }) - .deployed(); + const l2BridgeContract = await TokenBridgeContract.deploy( + wallet, + l2TokenContract.address, + l1PortalContractAddress, + ).send({ from: ownerAztecAddress }); logger.info(`L2 token bridge contract deployed at ${l2BridgeContract.address}`); // docs:end:deploy-l2-bridge // Set Bridge as a minter // docs:start:authorize-l2-bridge - await l2TokenContract.methods.set_minter(l2BridgeContract.address, true).send({ from: ownerAztecAddress }).wait(); + await l2TokenContract.methods.set_minter(l2BridgeContract.address, true).send({ from: ownerAztecAddress }); // docs:end:authorize-l2-bridge // Initialize L1 portal contract @@ -163,16 +165,15 @@ describe('e2e_cross_chain_messaging token_bridge_tutorial_test', () => { // Do 2 unrelated actions because // https://github.com/AztecProtocol/aztec-packages/blob/7e9e2681e314145237f95f79ffdc95ad25a0e319/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts#L354-L355 - await l2TokenContract.methods.mint_to_public(ownerAztecAddress, 0n).send({ from: ownerAztecAddress }).wait(); - await l2TokenContract.methods.mint_to_public(ownerAztecAddress, 0n).send({ from: ownerAztecAddress }).wait(); + await l2TokenContract.methods.mint_to_public(ownerAztecAddress, 0n).send({ from: ownerAztecAddress }); + await l2TokenContract.methods.mint_to_public(ownerAztecAddress, 0n).send({ from: ownerAztecAddress }); // docs:end:l1-bridge-public // Claim tokens publicly on L2 // docs:start:claim await l2BridgeContract.methods .claim_public(ownerAztecAddress, MINT_AMOUNT, claim.claimSecret, claim.messageLeafIndex) - .send({ from: ownerAztecAddress }) - .wait(); + .send({ from: ownerAztecAddress }); const balance = await l2TokenContract.methods .balance_of_public(ownerAztecAddress) .simulate({ from: ownerAztecAddress }); @@ -194,7 +195,7 @@ describe('e2e_cross_chain_messaging token_bridge_tutorial_test', () => { }, true, ); - await authwit.send().wait(); + await authwit.send(); // docs:end:setup-withdrawal // docs:start:l2-withdraw @@ -206,8 +207,7 @@ describe('e2e_cross_chain_messaging token_bridge_tutorial_test', () => { ); const l2TxReceipt = await l2BridgeContract.methods .exit_to_l1_public(EthAddress.fromString(ownerEthAddress), withdrawAmount, EthAddress.ZERO, authwitNonce) - .send({ from: ownerAztecAddress }) - .wait(); + .send({ from: ownerAztecAddress }); await waitForProven(node, l2TxReceipt, { provenTimeout: 500 }); const newL2Balance = await l2TokenContract.methods diff --git a/yarn-project/end-to-end/src/composed/web3signer/e2e_multi_validator_node_key_store.test.ts b/yarn-project/end-to-end/src/composed/web3signer/e2e_multi_validator_node_key_store.test.ts index d483f7968d41..ce44c4ecd9c4 100644 --- a/yarn-project/end-to-end/src/composed/web3signer/e2e_multi_validator_node_key_store.test.ts +++ b/yarn-project/end-to-end/src/composed/web3signer/e2e_multi_validator_node_key_store.test.ts @@ -1,9 +1,9 @@ import type { AztecNodeConfig } from '@aztec/aztec-node'; import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses'; -import { waitForProven } from '@aztec/aztec.js/contracts'; +import { NO_WAIT, waitForProven } from '@aztec/aztec.js/contracts'; import { ContractDeployer } from '@aztec/aztec.js/deployment'; import { Fr } from '@aztec/aztec.js/fields'; -import type { AztecNode } from '@aztec/aztec.js/node'; +import { type AztecNode, waitForTx } from '@aztec/aztec.js/node'; import type { Wallet } from '@aztec/aztec.js/wallet'; import { getAddressFromPrivateKey } from '@aztec/ethereum/account'; import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config'; @@ -328,6 +328,7 @@ describe('e2e_multi_validator_node', () => { contractAddressSalt, skipClassPublication: true, skipInstancePublication: true, + wait: NO_WAIT, }); }; @@ -398,7 +399,9 @@ describe('e2e_multi_validator_node', () => { return sendTx(ownerAddress, contractAddressSalt); }); - const settledTransactions = await Promise.all(sentTransactionPromises.map(tx => tx.wait())); + const settledTransactions = await Promise.all( + sentTransactionPromises.map(async sentTransactionPromise => waitForTx(aztecNode, await sentTransactionPromise)), + ); await Promise.all( settledTransactions.map(tx => { diff --git a/yarn-project/end-to-end/src/devnet/e2e_smoke.test.ts b/yarn-project/end-to-end/src/devnet/e2e_smoke.test.ts index 5ed39a701711..a77ade6cb4c4 100644 --- a/yarn-project/end-to-end/src/devnet/e2e_smoke.test.ts +++ b/yarn-project/end-to-end/src/devnet/e2e_smoke.test.ts @@ -137,18 +137,17 @@ describe('End-to-end tests for devnet', () => { const l2AccountDeployMethod = await l2AccountManager.getDeployMethod(); - const txReceipt = await l2AccountDeployMethod - .send({ - from: AztecAddress.ZERO, - fee: { - paymentMethod: new FeeJuicePaymentMethodWithClaim(l2AccountAddress, { - claimAmount: Fr.fromHexString(claimAmount).toBigInt(), - claimSecret: Fr.fromHexString(claimSecret.value), - messageLeafIndex: BigInt(messageLeafIndex), - }), - }, - }) - .wait(waitOpts); + const txReceipt = await l2AccountDeployMethod.send({ + from: AztecAddress.ZERO, + fee: { + paymentMethod: new FeeJuicePaymentMethodWithClaim(l2AccountAddress, { + claimAmount: Fr.fromHexString(claimAmount).toBigInt(), + claimSecret: Fr.fromHexString(claimSecret.value), + messageLeafIndex: BigInt(messageLeafIndex), + }), + }, + wait: { ...waitOpts, returnReceipt: true }, + }); // disabled because the CLI process doesn't exit // const { txHash, address } = await cli<{ txHash: string; address: { value: string } }>('create-account', { @@ -253,13 +252,15 @@ describe('End-to-end tests for devnet', () => { async function advanceChainWithEmptyBlocks(wallet: TestWallet) { const [fundedAccountAddress] = await registerInitialLocalNetworkAccountsInWallet(wallet); - const test = await TestContract.deploy(wallet) - .send({ from: fundedAccountAddress, universalDeploy: true, skipClassPublication: true }) - .deployed(); + const test = await TestContract.deploy(wallet).send({ + from: fundedAccountAddress, + universalDeploy: true, + skipClassPublication: true, + }); // start at 1 because deploying the contract has already mined a block for (let i = 1; i < MIN_BLOCKS_FOR_BRIDGING; i++) { - await test.methods.get_this_address().send({ from: fundedAccountAddress }).wait(waitOpts); + await test.methods.get_this_address().send({ from: fundedAccountAddress, wait: waitOpts }); } } }); diff --git a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts index 2c1568249840..5d6a48576552 100644 --- a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts +++ b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts @@ -47,7 +47,7 @@ describe('e2e_2_pxes', () => { ); accountBAddress = accountBManager.address; const accountBDeployMethod = await accountBManager.getDeployMethod(); - await accountBDeployMethod.send({ from: AztecAddress.ZERO }).wait(); + await accountBDeployMethod.send({ from: AztecAddress.ZERO }); await walletA.registerSender(accountBAddress, 'accountB'); await walletB.registerSender(accountAAddress, 'accountA'); @@ -74,7 +74,7 @@ describe('e2e_2_pxes', () => { // Transfer funds from A to B via PXE A const contractWithWalletA = TokenContract.at(token.address, walletA); - await contractWithWalletA.methods.transfer(accountBAddress, transferAmount1).send({ from: accountAAddress }).wait(); + await contractWithWalletA.methods.transfer(accountBAddress, transferAmount1).send({ from: accountAAddress }); // Check balances are as expected await expectTokenBalance(walletA, token, accountAAddress, initialBalance - transferAmount1, logger); @@ -82,10 +82,7 @@ describe('e2e_2_pxes', () => { // Transfer funds from B to A via PXE B const contractWithWalletB = TokenContract.at(token.address, walletB); - await contractWithWalletB.methods - .transfer(accountAAddress, transferAmount2) - .send({ from: accountBAddress }) - .wait({ interval: 0.1 }); + await contractWithWalletB.methods.transfer(accountAAddress, transferAmount2).send({ from: accountBAddress }); // Check balances are as expected await expectTokenBalance( @@ -100,7 +97,10 @@ describe('e2e_2_pxes', () => { const deployChildContractViaServerA = async () => { logger.info(`Deploying Child contract...`); - const { instance } = await ChildContract.deploy(walletA).send({ from: accountAAddress }).wait(); + const { instance } = await ChildContract.deploy(walletA).send({ + from: accountAAddress, + wait: { returnReceipt: true }, + }); logger.info('Child contract deployed'); return instance; @@ -118,10 +118,7 @@ describe('e2e_2_pxes', () => { const newValueToSet = new Fr(256n); const childContractWithWalletB = ChildContract.at(childCompleteAddress.address, walletB); - await childContractWithWalletB.methods - .pub_inc_value(newValueToSet) - .send({ from: accountBAddress }) - .wait({ interval: 0.1 }); + await childContractWithWalletB.methods.pub_inc_value(newValueToSet).send({ from: accountBAddress }); const storedValueOnB = await getChildStoredValue(childCompleteAddress, aztecNode!); expect(storedValueOnB).toEqual(newValueToSet); @@ -166,7 +163,7 @@ describe('e2e_2_pxes', () => { // Transfer funds from A to B via PXE A const contractWithWalletA = TokenContract.at(token.address, walletA); - await contractWithWalletA.methods.transfer(accountBAddress, transferAmount1).send({ from: accountAAddress }).wait(); + await contractWithWalletA.methods.transfer(accountBAddress, transferAmount1).send({ from: accountAAddress }); // now add the contract and check balances await walletB.registerContract(instance, TokenContract.artifact); @@ -183,7 +180,7 @@ describe('e2e_2_pxes', () => { const sharedAccount = initialFundedAccounts[2]; const sharedAccountOnAManager = await walletA.createSchnorrAccount(sharedAccount.secret, sharedAccount.salt); const sharedAccountOnADeployMethod = await sharedAccountOnAManager.getDeployMethod(); - await sharedAccountOnADeployMethod.send({ from: AztecAddress.ZERO }).wait(); + await sharedAccountOnADeployMethod.send({ from: AztecAddress.ZERO }); const sharedAccountAddress = sharedAccountOnAManager.address; // Register the shared account on walletB. @@ -194,16 +191,10 @@ describe('e2e_2_pxes', () => { // Transfer funds from A to Shared Wallet via PXE A const contractWithWalletA = TokenContract.at(token.address, walletA); - await contractWithWalletA.methods - .transfer(sharedAccountAddress, transferAmount1) - .send({ from: accountAAddress }) - .wait(); + await contractWithWalletA.methods.transfer(sharedAccountAddress, transferAmount1).send({ from: accountAAddress }); // Now send funds from Shared Wallet to B via PXE A - await contractWithWalletA.methods - .transfer(accountBAddress, transferAmount2) - .send({ from: sharedAccountAddress }) - .wait(); + await contractWithWalletA.methods.transfer(accountBAddress, transferAmount2).send({ from: sharedAccountAddress }); // check balances from PXE-A's perspective await expectTokenBalance(walletA, token, accountAAddress, initialBalance - transferAmount1, logger); diff --git a/yarn-project/end-to-end/src/e2e_account_contracts.test.ts b/yarn-project/end-to-end/src/e2e_account_contracts.test.ts index f9e579eff223..3e5c071cf6c2 100644 --- a/yarn-project/end-to-end/src/e2e_account_contracts.test.ts +++ b/yarn-project/end-to-end/src/e2e_account_contracts.test.ts @@ -60,22 +60,22 @@ const itShouldBehaveLikeAnAccountContract = ( if (await accountManager.hasInitializer()) { // The account is pre-funded and can pay for its own fee. const deployMethod = await accountManager.getDeployMethod(); - await deployMethod.send({ from: AztecAddress.ZERO }).wait(); + await deployMethod.send({ from: AztecAddress.ZERO }); } - child = await ChildContract.deploy(wallet).send({ from: address }).deployed(); + child = await ChildContract.deploy(wallet).send({ from: address }); }); afterAll(() => teardown()); it('calls a private function', async () => { logger.info('Calling private function...'); - await child.methods.value(42).send({ from: completeAddress.address }).wait({ interval: 0.1 }); + await child.methods.value(42).send({ from: completeAddress.address }); }); it('calls a public function', async () => { logger.info('Calling public function...'); - await child.methods.pub_inc_value(42).send({ from: completeAddress.address }).wait({ interval: 0.1 }); + await child.methods.pub_inc_value(42).send({ from: completeAddress.address }); const storedValue = await aztecNode.getPublicStorageAt('latest', child.address, new Fr(1)); expect(storedValue).toEqual(new Fr(42n)); }); diff --git a/yarn-project/end-to-end/src/e2e_amm.test.ts b/yarn-project/end-to-end/src/e2e_amm.test.ts index 0c63f734f0dd..955644067691 100644 --- a/yarn-project/end-to-end/src/e2e_amm.test.ts +++ b/yarn-project/end-to-end/src/e2e_amm.test.ts @@ -49,13 +49,13 @@ describe('AMM', () => { ({ contract: token1 } = await deployToken(wallet, adminAddress, 0n, logger)); ({ contract: liquidityToken } = await deployToken(wallet, adminAddress, 0n, logger)); - amm = await AMMContract.deploy(wallet, token0.address, token1.address, liquidityToken.address) - .send({ from: adminAddress }) - .deployed(); + amm = await AMMContract.deploy(wallet, token0.address, token1.address, liquidityToken.address).send({ + from: adminAddress, + }); // TODO(#9480): consider deploying the token by some factory when the AMM is deployed, and making the AMM be the // minter there. - await liquidityToken.methods.set_minter(amm.address, true).send({ from: adminAddress }).wait(); + await liquidityToken.methods.set_minter(amm.address, true).send({ from: adminAddress }); // We mint the tokens to both liquidity providers and the swapper await mintTokensToPrivate(token0, adminAddress, liquidityProviderAddress, INITIAL_TOKEN_BALANCE); @@ -133,7 +133,7 @@ describe('AMM', () => { const addLiquidityInteraction = amm.methods .add_liquidity(amount0Max, amount1Max, amount0Min, amount1Min, nonceForAuthwits) .with({ authWitnesses: [token0Authwit, token1Authwit] }); - await addLiquidityInteraction.send({ from: liquidityProviderAddress }).wait(); + await addLiquidityInteraction.send({ from: liquidityProviderAddress }); const ammBalancesAfter = await getAmmBalances(); const lpBalancesAfter = await getWalletBalances(liquidityProviderAddress); @@ -199,8 +199,7 @@ describe('AMM', () => { await amm.methods .add_liquidity(amount0Max, amount1Max, amount0Min, amount1Min, nonceForAuthwits) - .send({ from: otherLiquidityProviderAddress, authWitnesses: [token1Authwit, token2Authwit] }) - .wait(); + .send({ from: otherLiquidityProviderAddress, authWitnesses: [token1Authwit, token2Authwit] }); const ammBalancesAfter = await getAmmBalances(); const lpBalancesAfter = await getWalletBalances(otherLiquidityProviderAddress); @@ -245,7 +244,7 @@ describe('AMM', () => { const swapExactTokensInteraction = amm.methods .swap_exact_tokens_for_tokens(token0.address, token1.address, amountIn, amountOutMin, nonceForAuthwits) .with({ authWitnesses: [swapAuthwit] }); - await swapExactTokensInteraction.send({ from: swapperAddress }).wait(); + await swapExactTokensInteraction.send({ from: swapperAddress }); // We know exactly how many tokens we're supposed to get because we know nobody else interacted with the AMM // before we did. @@ -283,8 +282,7 @@ describe('AMM', () => { await amm.methods .swap_tokens_for_exact_tokens(token1.address, token0.address, amountOut, amountInMax, nonceForAuthwits) - .send({ from: swapperAddress, authWitnesses: [swapAuthwit] }) - .wait(); + .send({ from: swapperAddress, authWitnesses: [swapAuthwit] }); // Because nobody else interacted with the AMM, we know the amount in will be the maximum (i.e. the value the // contract returned as what we'd need to send in order to get the amount out we requested). @@ -323,8 +321,7 @@ describe('AMM', () => { await amm.methods .remove_liquidity(liquidityTokenBalance, amount0Min, amount1Min, nonceForAuthwits) - .send({ from: otherLiquidityProviderAddress, authWitnesses: [liquidityAuthwit] }) - .wait(); + .send({ from: otherLiquidityProviderAddress, authWitnesses: [liquidityAuthwit] }); // The liquidity provider should have no remaining liquidity tokens, and should have recovered the value they // originally deposited. diff --git a/yarn-project/end-to-end/src/e2e_authwit.test.ts b/yarn-project/end-to-end/src/e2e_authwit.test.ts index 653a85094484..f31b4356b6ff 100644 --- a/yarn-project/end-to-end/src/e2e_authwit.test.ts +++ b/yarn-project/end-to-end/src/e2e_authwit.test.ts @@ -29,7 +29,7 @@ describe('e2e_authwit_tests', () => { } = await setup(2)); await ensureAccountContractsPublished(wallet, [account1Address, account2Address]); - auth = await AuthWitTestContract.deploy(wallet).send({ from: account1Address }).deployed(); + auth = await AuthWitTestContract.deploy(wallet).send({ from: account1Address }); }); describe('Private', () => { @@ -62,8 +62,7 @@ describe('e2e_authwit_tests', () => { // Consume the inner hash using the account1 as the "on behalf of". await auth.methods .consume(account1Address, innerHash) - .send({ from: account2Address, authWitnesses: [witness] }) - .wait(); + .send({ from: account2Address, authWitnesses: [witness] }); expect(await wallet.lookupValidity(account1Address, intent, witness)).toEqual({ isValidInPrivate: false, @@ -72,10 +71,7 @@ describe('e2e_authwit_tests', () => { // Try to consume the same authwit again, it should fail await expect( - auth.methods - .consume(account1Address, innerHash) - .send({ from: account2Address, authWitnesses: [witness] }) - .wait(), + auth.methods.consume(account1Address, innerHash).send({ from: account2Address, authWitnesses: [witness] }), ).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); }); }); @@ -96,14 +92,14 @@ describe('e2e_authwit_tests', () => { }); const validateActionInteraction = await wallet.setPublicAuthWit(account1Address, intent, true); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); expect(await wallet.lookupValidity(account1Address, intent, witness)).toEqual({ isValidInPrivate: true, isValidInPublic: true, }); const registry = AuthRegistryContract.at(ProtocolContractAddress.AuthRegistry, wallet); - await registry.methods.consume(account1Address, innerHash).send({ from: account2Address }).wait(); + await registry.methods.consume(account1Address, innerHash).send({ from: account2Address }); expect(await wallet.lookupValidity(account1Address, intent, witness)).toEqual({ isValidInPrivate: true, @@ -124,7 +120,7 @@ describe('e2e_authwit_tests', () => { }); const validateActionInteraction = await wallet.setPublicAuthWit(account1Address, intent, true); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); expect(await wallet.lookupValidity(account1Address, intent, witness)).toEqual({ isValidInPrivate: true, @@ -132,7 +128,7 @@ describe('e2e_authwit_tests', () => { }); const cancelActionInteraction = await wallet.setPublicAuthWit(account1Address, intent, false); - await cancelActionInteraction.send().wait(); + await cancelActionInteraction.send(); expect(await wallet.lookupValidity(account1Address, intent, witness)).toEqual({ isValidInPrivate: true, diff --git a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts index 19e702011af1..69fbacea1b67 100644 --- a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts +++ b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts @@ -36,10 +36,11 @@ describe('e2e_avm_simulator', () => { let secondAvmContract: AvmTestContract; beforeEach(async () => { - ({ contract: avmContract, instance: avmContractInstance } = await AvmTestContract.deploy(wallet) - .send({ from: defaultAccountAddress }) - .wait()); - secondAvmContract = await AvmTestContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + ({ contract: avmContract, instance: avmContractInstance } = await AvmTestContract.deploy(wallet).send({ + from: defaultAccountAddress, + wait: { returnReceipt: true }, + })); + secondAvmContract = await AvmTestContract.deploy(wallet).send({ from: defaultAccountAddress }); }); describe('Assertions & error enriching', () => { @@ -115,14 +116,14 @@ describe('e2e_avm_simulator', () => { describe('Storage', () => { it('Modifies storage (Field)', async () => { - await avmContract.methods.set_storage_single(20n).send({ from: defaultAccountAddress }).wait(); + await avmContract.methods.set_storage_single(20n).send({ from: defaultAccountAddress }); expect(await avmContract.methods.read_storage_single().simulate({ from: defaultAccountAddress })).toEqual(20n); }); it('Modifies storage (Map)', async () => { const address = AztecAddress.fromBigInt(9090n); - await avmContract.methods.set_storage_map(address, 100).send({ from: defaultAccountAddress }).wait(); - await avmContract.methods.add_storage_map(address, 100).send({ from: defaultAccountAddress }).wait(); + await avmContract.methods.set_storage_map(address, 100).send({ from: defaultAccountAddress }); + await avmContract.methods.add_storage_map(address, 100).send({ from: defaultAccountAddress }); expect(await avmContract.methods.read_storage_map(address).simulate({ from: defaultAccountAddress })).toEqual( 200n, ); @@ -134,9 +135,7 @@ describe('e2e_avm_simulator', () => { await new BatchCall(wallet, [ avmContract.methods.set_storage_map(address, 100), avmContract.methods.add_storage_map(address, 100), - ]) - .send({ from: defaultAccountAddress }) - .wait(); + ]).send({ from: defaultAccountAddress }); // On a separate tx, we check the result. expect(await avmContract.methods.read_storage_map(address).simulate({ from: defaultAccountAddress })).toEqual( 200n, @@ -153,8 +152,7 @@ describe('e2e_avm_simulator', () => { avmContractInstance.currentContractClassId, avmContractInstance.initializationHash, ) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); }); }); @@ -162,20 +160,17 @@ describe('e2e_avm_simulator', () => { describe('Nullifiers', () => { // Nullifier will not yet be siloed by the kernel. it('Emit and check in the same tx', async () => { - const tx = await avmContract.methods - .emit_nullifier_and_check(123456) - .send({ from: defaultAccountAddress }) - .wait(); + const tx = await avmContract.methods.emit_nullifier_and_check(123456).send({ from: defaultAccountAddress }); expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); }); // Nullifier will have been siloed by the kernel, but we check against the unsiloed one. it('Emit and check in separate tx', async () => { const nullifier = new Fr(123456); - let tx = await avmContract.methods.new_nullifier(nullifier).send({ from: defaultAccountAddress }).wait(); + let tx = await avmContract.methods.new_nullifier(nullifier).send({ from: defaultAccountAddress }); expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); - tx = await avmContract.methods.assert_nullifier_exists(nullifier).send({ from: defaultAccountAddress }).wait(); + tx = await avmContract.methods.assert_nullifier_exists(nullifier).send({ from: defaultAccountAddress }); expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); }); @@ -186,9 +181,7 @@ describe('e2e_avm_simulator', () => { await new BatchCall(wallet, [ avmContract.methods.new_nullifier(nullifier), avmContract.methods.assert_nullifier_exists(nullifier), - ]) - .send({ from: defaultAccountAddress }) - .wait(); + ]).send({ from: defaultAccountAddress }); }); }); @@ -202,10 +195,7 @@ describe('e2e_avm_simulator', () => { it('Nested CALL instruction to non-existent contract returns failure, but caller can recover', async () => { // The nested call reverts (returns failure), but the caller doesn't HAVE to rethrow. - const tx = await avmContract.methods - .nested_call_to_nothing_recovers() - .send({ from: defaultAccountAddress }) - .wait(); + const tx = await avmContract.methods.nested_call_to_nothing_recovers().send({ from: defaultAccountAddress }); expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); }); it('Should NOT be able to emit the same unsiloed nullifier from the same contract', async () => { @@ -213,8 +203,7 @@ describe('e2e_avm_simulator', () => { await expect( avmContract.methods .create_same_nullifier_in_nested_call(avmContract.address, nullifier) - .send({ from: defaultAccountAddress }) - .wait(), + .send({ from: defaultAccountAddress }), ).rejects.toThrow(); }); @@ -222,8 +211,7 @@ describe('e2e_avm_simulator', () => { const nullifier = new Fr(1); const tx = await avmContract.methods .create_different_nullifier_in_nested_call(avmContract.address, nullifier) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); }); @@ -231,8 +219,7 @@ describe('e2e_avm_simulator', () => { const nullifier = new Fr(1); const tx = await avmContract.methods .create_same_nullifier_in_nested_call(secondAvmContract.address, nullifier) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); }); @@ -240,8 +227,7 @@ describe('e2e_avm_simulator', () => { const nullifier = new Fr(1); const tx = await avmContract.methods .create_different_nullifier_in_nested_call(secondAvmContract.address, nullifier) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); }); }); @@ -251,7 +237,7 @@ describe('e2e_avm_simulator', () => { let avmContract: AvmInitializerTestContract; beforeEach(async () => { - avmContract = await AvmInitializerTestContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + avmContract = await AvmInitializerTestContract.deploy(wallet).send({ from: defaultAccountAddress }); }); describe('Storage', () => { diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/access_control.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/access_control.test.ts index 74bae3e0400d..97e8bbb19c23 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/access_control.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/access_control.test.ts @@ -19,10 +19,7 @@ describe('e2e_blacklist_token_contract access control', () => { it('grant mint permission to the admin', async () => { const adminMinterRole = new Role().withAdmin().withMinter(); - await t.asset.methods - .update_roles(t.adminAddress, adminMinterRole.toNoirStruct()) - .send({ from: t.adminAddress }) - .wait(); + await t.asset.methods.update_roles(t.adminAddress, adminMinterRole.toNoirStruct()).send({ from: t.adminAddress }); await t.crossTimestampOfChange(); @@ -33,7 +30,7 @@ describe('e2e_blacklist_token_contract access control', () => { it('create a new admin', async () => { const adminRole = new Role().withAdmin(); - await t.asset.methods.update_roles(t.otherAddress, adminRole.toNoirStruct()).send({ from: t.adminAddress }).wait(); + await t.asset.methods.update_roles(t.otherAddress, adminRole.toNoirStruct()).send({ from: t.adminAddress }); await t.crossTimestampOfChange(); @@ -44,7 +41,7 @@ describe('e2e_blacklist_token_contract access control', () => { it('revoke the new admin', async () => { const noRole = new Role(); - await t.asset.methods.update_roles(t.otherAddress, noRole.toNoirStruct()).send({ from: t.adminAddress }).wait(); + await t.asset.methods.update_roles(t.otherAddress, noRole.toNoirStruct()).send({ from: t.adminAddress }); await t.crossTimestampOfChange(); @@ -57,8 +54,7 @@ describe('e2e_blacklist_token_contract access control', () => { const blacklistRole = new Role().withBlacklisted(); await t.asset.methods .update_roles(t.blacklistedAddress, blacklistRole.toNoirStruct()) - .send({ from: t.adminAddress }) - .wait(); + .send({ from: t.adminAddress }); await t.crossTimestampOfChange(); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts index db71da429b0d..249568f38980 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts @@ -105,13 +105,13 @@ export class BlacklistTokenContractTest { await publicDeployAccounts(this.wallet, [this.adminAddress, this.otherAddress, this.blacklistedAddress]); this.logger.verbose(`Deploying TokenContract...`); - this.asset = await TokenBlacklistContract.deploy(this.wallet, this.adminAddress) - .send({ from: this.adminAddress }) - .deployed(); + this.asset = await TokenBlacklistContract.deploy(this.wallet, this.adminAddress).send({ + from: this.adminAddress, + }); this.logger.verbose(`Token deployed to ${this.asset.address}`); this.logger.verbose(`Deploying bad account...`); - this.badAccount = await InvalidAccountContract.deploy(this.wallet).send({ from: this.adminAddress }).deployed(); + this.badAccount = await InvalidAccountContract.deploy(this.wallet).send({ from: this.adminAddress }); this.logger.verbose(`Deployed to ${this.badAccount.address}.`); await this.crossTimestampOfChange(); @@ -171,14 +171,12 @@ export class BlacklistTokenContractTest { const adminMinterRole = new Role().withAdmin().withMinter(); await this.asset.methods .update_roles(this.adminAddress, adminMinterRole.toNoirStruct()) - .send({ from: this.adminAddress }) - .wait(); + .send({ from: this.adminAddress }); const blacklistRole = new Role().withBlacklisted(); await this.asset.methods .update_roles(this.blacklistedAddress, blacklistRole.toNoirStruct()) - .send({ from: this.adminAddress }) - .wait(); + .send({ from: this.adminAddress }); await this.crossTimestampOfChange(); @@ -187,16 +185,15 @@ export class BlacklistTokenContractTest { ); this.logger.verbose(`Minting ${amount} publicly...`); - await asset.methods.mint_public(this.adminAddress, amount).send({ from: this.adminAddress }).wait(); + await asset.methods.mint_public(this.adminAddress, amount).send({ from: this.adminAddress }); this.logger.verbose(`Minting ${amount} privately...`); const secret = Fr.random(); const secretHash = await computeSecretHash(secret); - const receipt = await asset.methods.mint_private(amount, secretHash).send({ from: this.adminAddress }).wait(); + const receipt = await asset.methods.mint_private(amount, secretHash).send({ from: this.adminAddress }); await this.addPendingShieldNoteToPXE(asset, this.adminAddress, amount, secretHash, receipt.txHash); - const txClaim = asset.methods.redeem_shield(this.adminAddress, amount, secret).send({ from: this.adminAddress }); - await txClaim.wait(); + await asset.methods.redeem_shield(this.adminAddress, amount, secret).send({ from: this.adminAddress }); this.logger.verbose(`Minting complete.`); tokenSim.mintPublic(this.adminAddress, amount); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/burn.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/burn.test.ts index 3e011ae34315..dcf944a20675 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/burn.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/burn.test.ts @@ -29,7 +29,7 @@ describe('e2e_blacklist_token_contract burn', () => { const balance0 = await asset.methods.balance_of_public(adminAddress).simulate({ from: adminAddress }); const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.burn_public(adminAddress, amount, 0).send({ from: adminAddress }).wait(); + await asset.methods.burn_public(adminAddress, amount, 0).send({ from: adminAddress }); tokenSim.burnPublic(adminAddress, amount); }); @@ -47,9 +47,9 @@ describe('e2e_blacklist_token_contract burn', () => { { caller: otherAddress, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); - await action.send({ from: otherAddress }).wait(); + await action.send({ from: otherAddress }); tokenSim.burnPublic(adminAddress, amount); @@ -102,7 +102,7 @@ describe('e2e_blacklist_token_contract burn', () => { { caller: otherAddress, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); await expect(action.simulate({ from: otherAddress })).rejects.toThrow(U128_UNDERFLOW_ERROR); }); @@ -120,7 +120,7 @@ describe('e2e_blacklist_token_contract burn', () => { { caller: adminAddress, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); await expect( asset.methods.burn_public(adminAddress, amount, authwitNonce).simulate({ from: otherAddress }), @@ -140,7 +140,7 @@ describe('e2e_blacklist_token_contract burn', () => { const balance0 = await asset.methods.balance_of_private(adminAddress).simulate({ from: adminAddress }); const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.burn(adminAddress, amount, 0).send({ from: adminAddress }).wait(); + await asset.methods.burn(adminAddress, amount, 0).send({ from: adminAddress }); tokenSim.burnPrivate(adminAddress, amount); }); @@ -159,15 +159,14 @@ describe('e2e_blacklist_token_contract burn', () => { await asset.methods .burn(adminAddress, amount, authwitNonce) - .send({ from: otherAddress, authWitnesses: [witness] }) - .wait(); + .send({ from: otherAddress, authWitnesses: [witness] }); tokenSim.burnPrivate(adminAddress, amount); // Perform the transfer again, should fail const txReplay = asset.methods .burn(adminAddress, amount, authwitNonce) .send({ from: otherAddress, authWitnesses: [witness] }); - await expect(txReplay.wait()).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); + await expect(txReplay).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); }); describe('failure cases', () => { diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/minting.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/minting.test.ts index 83edba59a3c3..f1386cfa812a 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/minting.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/minting.test.ts @@ -33,7 +33,7 @@ describe('e2e_blacklist_token_contract mint', () => { it('as minter', async () => { const amount = 10000n; tokenSim.mintPublic(adminAddress, amount); - await asset.methods.mint_public(adminAddress, amount).send({ from: adminAddress }).wait(); + await asset.methods.mint_public(adminAddress, amount).send({ from: adminAddress }); }); describe('failure cases', () => { @@ -88,12 +88,12 @@ describe('e2e_blacklist_token_contract mint', () => { it('mint_private as minter and redeem as recipient', async () => { const balanceBefore = await asset.methods.balance_of_private(adminAddress).simulate({ from: adminAddress }); - const receipt = await asset.methods.mint_private(amount, secretHash).send({ from: adminAddress }).wait(); + const receipt = await asset.methods.mint_private(amount, secretHash).send({ from: adminAddress }); txHash = receipt.txHash; await t.addPendingShieldNoteToPXE(asset, adminAddress, amount, secretHash, txHash); - await asset.methods.redeem_shield(adminAddress, amount, secret).send({ from: adminAddress }).wait(); + await asset.methods.redeem_shield(adminAddress, amount, secret).send({ from: adminAddress }); tokenSim.mintPrivate(adminAddress, amount); const balanceAfter = await asset.methods.balance_of_private(adminAddress).simulate({ from: adminAddress }); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/shielding.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/shielding.test.ts index f02c2fbde7b5..b09cb1d9b9c2 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/shielding.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/shielding.test.ts @@ -35,11 +35,11 @@ describe('e2e_blacklist_token_contract shield + redeem_shield', () => { const amount = balancePub / 2n; expect(amount).toBeGreaterThan(0n); - const receipt = await asset.methods.shield(adminAddress, amount, secretHash, 0).send({ from: adminAddress }).wait(); + const receipt = await asset.methods.shield(adminAddress, amount, secretHash, 0).send({ from: adminAddress }); // Redeem it await t.addPendingShieldNoteToPXE(asset, adminAddress, amount, secretHash, receipt.txHash); - await asset.methods.redeem_shield(adminAddress, amount, secret).send({ from: adminAddress }).wait(); + await asset.methods.redeem_shield(adminAddress, amount, secret).send({ from: adminAddress }); // Check that the result matches token sim tokenSim.transferToPrivate(adminAddress, adminAddress, amount); @@ -59,9 +59,9 @@ describe('e2e_blacklist_token_contract shield + redeem_shield', () => { { caller: otherAddress, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); - const receipt = await action.send({ from: otherAddress }).wait(); + const receipt = await action.send({ from: otherAddress }); // Check that replaying the shield should fail! await expect( @@ -70,7 +70,7 @@ describe('e2e_blacklist_token_contract shield + redeem_shield', () => { // Redeem it await t.addPendingShieldNoteToPXE(asset, adminAddress, amount, secretHash, receipt.txHash); - await asset.methods.redeem_shield(adminAddress, amount, secret).send({ from: adminAddress }).wait(); + await asset.methods.redeem_shield(adminAddress, amount, secret).send({ from: adminAddress }); // Check that the result matches token sim tokenSim.transferToPrivate(adminAddress, adminAddress, amount); @@ -113,7 +113,7 @@ describe('e2e_blacklist_token_contract shield + redeem_shield', () => { { caller: otherAddress, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); await expect(action.simulate({ from: otherAddress })).rejects.toThrow(U128_UNDERFLOW_ERROR); }); @@ -131,7 +131,7 @@ describe('e2e_blacklist_token_contract shield + redeem_shield', () => { { caller: otherAddress, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); await expect(action.simulate({ from: blacklistedAddress })).rejects.toThrow(/unauthorized/); }); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_private.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_private.test.ts index a78c9f4caeb3..462f51a84f95 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_private.test.ts @@ -29,7 +29,7 @@ describe('e2e_blacklist_token_contract transfer private', () => { const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); const tokenTransferInteraction = asset.methods.transfer(adminAddress, otherAddress, amount, 0); - await tokenTransferInteraction.send({ from: adminAddress }).wait(); + await tokenTransferInteraction.send({ from: adminAddress }); tokenSim.transferPrivate(adminAddress, otherAddress, amount); }); @@ -38,7 +38,7 @@ describe('e2e_blacklist_token_contract transfer private', () => { const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.transfer(adminAddress, adminAddress, amount, 0).send({ from: adminAddress }).wait(); + await asset.methods.transfer(adminAddress, adminAddress, amount, 0).send({ from: adminAddress }); tokenSim.transferPrivate(adminAddress, adminAddress, amount); }); @@ -54,14 +54,14 @@ describe('e2e_blacklist_token_contract transfer private', () => { // Perform the transfer - await action.send({ from: otherAddress, authWitnesses: [witness] }).wait(); + await action.send({ from: otherAddress, authWitnesses: [witness] }); tokenSim.transferPrivate(adminAddress, otherAddress, amount); // Perform the transfer again, should fail const txReplay = asset.methods .transfer(adminAddress, otherAddress, amount, authwitNonce) .send({ from: otherAddress, authWitnesses: [witness] }); - await expect(txReplay.wait()).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); + await expect(txReplay).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); }); describe('failure cases', () => { diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_public.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_public.test.ts index b9b9913ee5d1..c5d23f421bbd 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_public.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_public.test.ts @@ -27,7 +27,7 @@ describe('e2e_blacklist_token_contract transfer public', () => { const balance0 = await asset.methods.balance_of_public(adminAddress).simulate({ from: adminAddress }); const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.transfer_public(adminAddress, otherAddress, amount, 0).send({ from: adminAddress }).wait(); + await asset.methods.transfer_public(adminAddress, otherAddress, amount, 0).send({ from: adminAddress }); tokenSim.transferPublic(adminAddress, otherAddress, amount); }); @@ -36,7 +36,7 @@ describe('e2e_blacklist_token_contract transfer public', () => { const balance = await asset.methods.balance_of_public(adminAddress).simulate({ from: adminAddress }); const amount = balance / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.transfer_public(adminAddress, adminAddress, amount, 0).send({ from: adminAddress }).wait(); + await asset.methods.transfer_public(adminAddress, adminAddress, amount, 0).send({ from: adminAddress }); tokenSim.transferPublic(adminAddress, adminAddress, amount); }); @@ -54,10 +54,10 @@ describe('e2e_blacklist_token_contract transfer public', () => { { caller: otherAddress, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); // Perform the transfer - await action.send({ from: otherAddress }).wait(); + await action.send({ from: otherAddress }); tokenSim.transferPublic(adminAddress, otherAddress, amount); @@ -117,7 +117,7 @@ describe('e2e_blacklist_token_contract transfer public', () => { { caller: otherAddress, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); // Perform the transfer await expect(action.simulate({ from: otherAddress })).rejects.toThrow(U128_UNDERFLOW_ERROR); @@ -140,7 +140,7 @@ describe('e2e_blacklist_token_contract transfer public', () => { { caller: adminAddress, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); // Perform the transfer await expect(action.simulate({ from: otherAddress })).rejects.toThrow(/unauthorized/); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/unshielding.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/unshielding.test.ts index 9c081b443610..aa4da4cf820a 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/unshielding.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/unshielding.test.ts @@ -29,7 +29,7 @@ describe('e2e_blacklist_token_contract unshielding', () => { const amount = balancePriv / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.unshield(adminAddress, adminAddress, amount, 0).send({ from: adminAddress }).wait(); + await asset.methods.unshield(adminAddress, adminAddress, amount, 0).send({ from: adminAddress }); tokenSim.transferToPublic(adminAddress, adminAddress, amount); }); @@ -47,14 +47,14 @@ describe('e2e_blacklist_token_contract unshielding', () => { // But doing it in two actions to show the flow. const witness = await wallet.createAuthWit(adminAddress, { caller: otherAddress, action }); - await action.send({ from: otherAddress, authWitnesses: [witness] }).wait(); + await action.send({ from: otherAddress, authWitnesses: [witness] }); tokenSim.transferToPublic(adminAddress, otherAddress, amount); // Perform the transfer again, should fail const txReplay = asset.methods .unshield(adminAddress, otherAddress, amount, authwitNonce) .send({ from: otherAddress, authWitnesses: [witness] }); - await expect(txReplay.wait()).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); + await expect(txReplay).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); // @todo @LHerskind This error is weird? }); diff --git a/yarn-project/end-to-end/src/e2e_block_building.test.ts b/yarn-project/end-to-end/src/e2e_block_building.test.ts index 7a44a29a8cdd..683585c51d50 100644 --- a/yarn-project/end-to-end/src/e2e_block_building.test.ts +++ b/yarn-project/end-to-end/src/e2e_block_building.test.ts @@ -1,8 +1,8 @@ import { AztecAddress } from '@aztec/aztec.js/addresses'; -import { BatchCall, ContractFunctionInteraction, type DeployOptions } from '@aztec/aztec.js/contracts'; +import { BatchCall, ContractFunctionInteraction, type DeployOptions, NO_WAIT } from '@aztec/aztec.js/contracts'; import { Fr } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; -import type { AztecNode } from '@aztec/aztec.js/node'; +import { type AztecNode, waitForTx } from '@aztec/aztec.js/node'; import { TxStatus } from '@aztec/aztec.js/tx'; import { AnvilTestWatcher, CheatCodes } from '@aztec/aztec/testing'; import { asyncMap } from '@aztec/foundation/async-map'; @@ -84,9 +84,7 @@ describe('e2e_block_building', () => { // so many so that we don't end up hitting a reorg or timing out the tx wait(). const TX_COUNT = 16; - const contract = await StatefulTestContract.deploy(wallet, ownerAddress, 1) - .send({ from: ownerAddress }) - .deployed(); + const contract = await StatefulTestContract.deploy(wallet, ownerAddress, 1).send({ from: ownerAddress }); logger.info(`Deployed stateful test contract at ${contract.address}`); // We add a delay to every public tx processing @@ -111,13 +109,13 @@ describe('e2e_block_building', () => { const methods = times(TX_COUNT, i => contract.methods.increment_public_value(ownerAddress, i)); const provenTxs = await asyncMap(methods, method => proveInteraction(wallet, method, { from: ownerAddress })); logger.info(`Sending ${TX_COUNT} txs to the node`); - const txs = await Promise.all(provenTxs.map(tx => tx.send())); + const txHashes = await Promise.all(provenTxs.map(tx => tx.send({ wait: NO_WAIT }))); logger.info(`All ${TX_COUNT} txs have been sent`, { - txs: (await Promise.all(txs.map(tx => tx.getTxHash()))).map(h => h.toString()), + txs: txHashes.map(h => h.toString()), }); // Await txs to be mined and assert they are mined across multiple different blocks. - const receipts = await Promise.all(txs.map(tx => tx.wait())); + const receipts = await Promise.all(txHashes.map(txHash => waitForTx(aztecNode, txHash))); const blockNumbers = receipts.map(r => r.blockNumber!).sort((a, b) => a - b); logger.info(`Txs mined on blocks: ${unique(blockNumbers)}`); expect(blockNumbers.at(-1)! - blockNumbers[0]).toBeGreaterThan(1); @@ -148,14 +146,14 @@ describe('e2e_block_building', () => { } // Send them simultaneously to be picked up by the sequencer - const txs = await Promise.all(provenTxs.map(tx => tx.send())); + const txHashes = await Promise.all(provenTxs.map(tx => tx.send({ wait: NO_WAIT }))); logger.info(`Txs sent with hashes: `); - for (const tx of txs) { - logger.info(` ${(await tx.getTxHash()).toString()}`); + for (const hash of txHashes) { + logger.info(` ${hash.toString()}`); } // Await txs to be mined and assert they are all mined on the same block - const receipts = await Promise.all(txs.map(tx => tx.wait())); + const receipts = await Promise.all(txHashes.map(txHash => waitForTx(aztecNode, txHash))); expect(receipts.map(r => r.blockNumber)).toEqual(times(TX_COUNT, () => receipts[0].blockNumber)); // Assert all contracts got initialized @@ -167,9 +165,7 @@ describe('e2e_block_building', () => { it('assembles a block with multiple txs with public fns', async () => { // First deploy the contract - const contract = await StatefulTestContract.deploy(wallet, ownerAddress, 1) - .send({ from: ownerAddress }) - .deployed(); + const contract = await StatefulTestContract.deploy(wallet, ownerAddress, 1).send({ from: ownerAddress }); // Assemble N contract deployment txs // We need to create them sequentially since we cannot have parallel calls to a circuit @@ -183,14 +179,14 @@ describe('e2e_block_building', () => { } // Send them simultaneously to be picked up by the sequencer - const txs = await Promise.all(provenTxs.map(tx => tx.send())); + const txHashes = await Promise.all(provenTxs.map(tx => tx.send({ wait: NO_WAIT }))); logger.info(`Txs sent with hashes: `); - for (const tx of txs) { - logger.info(` ${(await tx.getTxHash()).toString()}`); + for (const hash of txHashes) { + logger.info(` ${hash.toString()}`); } // Await txs to be mined and assert they are all mined on the same block - const receipts = await Promise.all(txs.map(tx => tx.wait())); + const receipts = await Promise.all(txHashes.map(txHash => waitForTx(aztecNode, txHash))); expect(receipts.map(r => r.blockNumber)).toEqual(times(TX_COUNT, () => receipts[0].blockNumber)); }); @@ -198,10 +194,8 @@ describe('e2e_block_building', () => { // Skipped since we only use it to manually test number of invocations to world-state. it.skip('builds blocks with multiple public fns after multiple nullifier insertions', async () => { // First deploy the contracts - const contract = await StatefulTestContract.deploy(wallet, ownerAddress, 1) - .send({ from: ownerAddress }) - .deployed(); - const another = await TestContract.deploy(wallet).send({ from: ownerAddress }).deployed(); + const contract = await StatefulTestContract.deploy(wallet, ownerAddress, 1).send({ from: ownerAddress }); + const another = await TestContract.deploy(wallet).send({ from: ownerAddress }); await aztecNodeAdmin!.setConfig({ minTxsPerBlock: 16, maxTxsPerBlock: 16 }); @@ -211,9 +205,9 @@ describe('e2e_block_building', () => { const NULLIFIER_COUNT = 128; const sentNullifierTxs = []; for (let i = 0; i < NULLIFIER_COUNT; i++) { - sentNullifierTxs.push(another.methods.emit_nullifier(Fr.random()).send({ from: ownerAddress })); + sentNullifierTxs.push(another.methods.emit_nullifier(Fr.random()).send({ from: ownerAddress, wait: NO_WAIT })); } - await Promise.all(sentNullifierTxs.map(tx => tx.wait({ timeout: 600 }))); + await Promise.all(sentNullifierTxs); logger.info(`Nullifier txs sent`); await aztecNodeAdmin!.setConfig({ minTxsPerBlock: 4, maxTxsPerBlock: 4 }); @@ -222,10 +216,12 @@ describe('e2e_block_building', () => { const TX_COUNT = 128; const sentTxs = []; for (let i = 0; i < TX_COUNT; i++) { - sentTxs.push(contract.methods.increment_public_value(ownerAddress, i).send({ from: ownerAddress })); + sentTxs.push( + contract.methods.increment_public_value(ownerAddress, i).send({ from: ownerAddress, wait: NO_WAIT }), + ); } - await Promise.all(sentTxs.map(tx => tx.wait({ timeout: 600 }))); + await Promise.all(sentTxs); logger.info(`Txs sent`); }); @@ -248,8 +244,8 @@ describe('e2e_block_building', () => { ); const [deployTxReceipt, callTxReceipt] = await Promise.all([ - deployMethod.send({ from: ownerAddress }).wait(), - callInteraction.send({ from: ownerAddress }).wait(), + deployMethod.send({ from: ownerAddress, wait: { returnReceipt: true } }), + callInteraction.send({ from: ownerAddress }), ]); expect(deployTxReceipt.blockNumber).toEqual(callTxReceipt.blockNumber); @@ -267,7 +263,7 @@ describe('e2e_block_building', () => { wallet, accounts: [ownerAddress], } = await setup(1)); - contract = await TestContract.deploy(wallet).send({ from: ownerAddress }).deployed(); + contract = await TestContract.deploy(wallet).send({ from: ownerAddress }); logger.info(`Test contract deployed at ${contract.address}`); }); @@ -348,32 +344,32 @@ describe('e2e_block_building', () => { describe('across blocks', () => { it('private -> private', async () => { const nullifier = Fr.random(); - await contract.methods.emit_nullifier(nullifier).send({ from: ownerAddress }).wait(); - await expect(contract.methods.emit_nullifier(nullifier).send({ from: ownerAddress }).wait()).rejects.toThrow( + await contract.methods.emit_nullifier(nullifier).send({ from: ownerAddress }); + await expect(contract.methods.emit_nullifier(nullifier).send({ from: ownerAddress })).rejects.toThrow( TX_ERROR_EXISTING_NULLIFIER, ); }); it('public -> public', async () => { const nullifier = Fr.random(); - await contract.methods.emit_nullifier_public(nullifier).send({ from: ownerAddress }).wait(); - await expect( - contract.methods.emit_nullifier_public(nullifier).send({ from: ownerAddress }).wait(), - ).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); + await contract.methods.emit_nullifier_public(nullifier).send({ from: ownerAddress }); + await expect(contract.methods.emit_nullifier_public(nullifier).send({ from: ownerAddress })).rejects.toThrow( + DUPLICATE_NULLIFIER_ERROR, + ); }); it('private -> public', async () => { const nullifier = Fr.random(); - await contract.methods.emit_nullifier(nullifier).send({ from: ownerAddress }).wait(); - await expect( - contract.methods.emit_nullifier_public(nullifier).send({ from: ownerAddress }).wait(), - ).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); + await contract.methods.emit_nullifier(nullifier).send({ from: ownerAddress }); + await expect(contract.methods.emit_nullifier_public(nullifier).send({ from: ownerAddress })).rejects.toThrow( + DUPLICATE_NULLIFIER_ERROR, + ); }); it('public -> private', async () => { const nullifier = Fr.random(); - await contract.methods.emit_nullifier_public(nullifier).send({ from: ownerAddress }).wait(); - await expect(contract.methods.emit_nullifier(nullifier).send({ from: ownerAddress }).wait()).rejects.toThrow( + await contract.methods.emit_nullifier_public(nullifier).send({ from: ownerAddress }); + await expect(contract.methods.emit_nullifier(nullifier).send({ from: ownerAddress })).rejects.toThrow( TX_ERROR_EXISTING_NULLIFIER, ); }); @@ -395,7 +391,7 @@ describe('e2e_block_building', () => { } = await setup(1)); logger.info(`Deploying test contract`); - testContract = await TestContract.deploy(wallet).send({ from: ownerAddress }).deployed(); + testContract = await TestContract.deploy(wallet).send({ from: ownerAddress }); }, 60_000); afterAll(() => teardown()); @@ -421,7 +417,7 @@ describe('e2e_block_building', () => { const action = testContract.methods.emit_array_as_encrypted_log(valuesAsArray, ownerAddress, true); const tx = await proveInteraction(wallet, action, { from: ownerAddress }); - const rct = await tx.send().wait(); + const rct = await tx.send(); // compare logs expect(rct.hasExecutionSucceeded()).toBe(true); @@ -478,11 +474,9 @@ describe('e2e_block_building', () => { const accountManager = await (wallet as TestWallet).createSchnorrAccount(accountData.secret, accountData.salt); const deployMethod = await accountManager.getDeployMethod(); - await deployMethod - .send({ - from: AztecAddress.ZERO, - }) - .wait(); + await deployMethod.send({ + from: AztecAddress.ZERO, + }); }); it('can simulate public txs while building a block', async () => { @@ -498,9 +492,9 @@ describe('e2e_block_building', () => { })); logger.info('Deploying token contract'); - const token = await TokenContract.deploy(wallet, ownerAddress, 'TokenName', 'TokenSymbol', 18) - .send({ from: ownerAddress }) - .deployed(); + const token = await TokenContract.deploy(wallet, ownerAddress, 'TokenName', 'TokenSymbol', 18).send({ + from: ownerAddress, + }); logger.info('Updating txs per block to 4'); await aztecNodeAdmin!.setConfig({ minTxsPerBlock: 4, maxTxsPerBlock: 4 }); @@ -513,7 +507,7 @@ describe('e2e_block_building', () => { } logger.info('Waiting for txs to be mined'); - await Promise.all(txs.map(tx => tx.wait({ timeout: 600 }))); + await Promise.all(txs); }); // Regression for ReexStateMismatch happening on testnet when AVM processing throws an unexpected error. @@ -533,7 +527,7 @@ describe('e2e_block_building', () => { accounts: [ownerAddress], } = context); - const testContract = await TestContract.deploy(wallet).send({ from: ownerAddress }).deployed(); + const testContract = await TestContract.deploy(wallet).send({ from: ownerAddress }); logger.warn(`Test contract deployed at ${testContract.address}`); // We want the sequencer to wait until both txs have arrived (so minTxsPerBlock=2), but agree to build @@ -552,9 +546,9 @@ describe('e2e_block_building', () => { ]); const batches = times(2, makeBatch); - const txs = await Promise.all(batches.map(batch => batch.send({ from: ownerAddress }))); - logger.warn(`Sent two txs to test contract`, { txs: await Promise.all(txs.map(tx => tx.getTxHash())) }); - await Promise.race(txs.map(tx => tx.wait({ timeout: 60 }))); + const txHashes = await Promise.all(batches.map(batch => batch.send({ from: ownerAddress, wait: NO_WAIT }))); + logger.warn(`Sent two txs to test contract`, { txs: txHashes.map(hash => hash.toString()) }); + await Promise.race(txHashes.map(txHash => waitForTx(aztecNode, txHash, { timeout: 60 }))); logger.warn(`At least one tx has been mined`); const lastBlock = await context.aztecNode.getBlockHeader(); @@ -584,7 +578,7 @@ describe('e2e_block_building', () => { accounts: [ownerAddress], } = await setup(1)); - contract = await StatefulTestContract.deploy(wallet, ownerAddress, 1).send({ from: ownerAddress }).deployed(); + contract = await StatefulTestContract.deploy(wallet, ownerAddress, 1).send({ from: ownerAddress }); initialBlockNumber = await aztecNode.getBlockNumber(); logger.info(`Stateful test contract deployed at ${contract.address}`); @@ -608,13 +602,13 @@ describe('e2e_block_building', () => { // Send a tx to the contract that creates a note. This tx will be reorgd but re-included, // since it is being built against a proven block number. logger.info('Sending initial tx'); - const tx1 = await contract.methods.create_note(ownerAddress, 20).send({ from: ownerAddress }).wait(); + const tx1 = await contract.methods.create_note(ownerAddress, 20).send({ from: ownerAddress }); expect(tx1.blockNumber).toEqual(initialBlockNumber + 1); expect(await contract.methods.summed_values(ownerAddress).simulate({ from: ownerAddress })).toEqual(21n); // And send a second one, which won't be re-included. logger.info('Sending second tx'); - const tx2 = await contract.methods.create_note(ownerAddress, 30).send({ from: ownerAddress }).wait(); + const tx2 = await contract.methods.create_note(ownerAddress, 30).send({ from: ownerAddress }); expect(tx2.blockNumber).toEqual(initialBlockNumber + 2); expect(await contract.methods.summed_values(ownerAddress).simulate({ from: ownerAddress })).toEqual(51n); @@ -655,19 +649,13 @@ describe('e2e_block_building', () => { // And we should be able to send a new tx on the new chain logger.info('Sending new tx on reorgd chain'); - const tx3 = await contract.methods.create_note(ownerAddress, 10).send({ from: ownerAddress }).wait(); + const tx3 = await contract.methods.create_note(ownerAddress, 10).send({ from: ownerAddress }); expect(await contract.methods.summed_values(ownerAddress).simulate({ from: ownerAddress })).toEqual(31n); expect(tx3.blockNumber).toBeGreaterThanOrEqual(newTx1Receipt.blockNumber! + 1); }); }); }); -async function sendAndWait(calls: ContractFunctionInteraction[], from: AztecAddress) { - return await Promise.allSettled( - calls - // First we send them all. - .map(call => call.send({ from })) - // Only then we wait. - .map(p => p.wait()), - ); +function sendAndWait(calls: ContractFunctionInteraction[], from: AztecAddress) { + return Promise.allSettled(calls.map(call => call.send({ from }))); } diff --git a/yarn-project/end-to-end/src/e2e_card_game.test.ts b/yarn-project/end-to-end/src/e2e_card_game.test.ts index 784eba6afbb6..c10bd9463f05 100644 --- a/yarn-project/end-to-end/src/e2e_card_game.test.ts +++ b/yarn-project/end-to-end/src/e2e_card_game.test.ts @@ -104,14 +104,14 @@ describe('e2e_card_game', () => { const deployContract = async () => { logger.debug(`Deploying L2 contract...`); - contract = await CardGameContract.deploy(wallet).send({ from: firstPlayer }).deployed(); + contract = await CardGameContract.deploy(wallet).send({ from: firstPlayer }); logger.info(`L2 contract deployed at ${contract.address}`); }; it('should be able to buy packs', async () => { const seed = 27n; // docs:start:send_tx - await contract.methods.buy_pack(seed).send({ from: firstPlayer }).wait(); + await contract.methods.buy_pack(seed).send({ from: firstPlayer }); // docs:end:send_tx const collection = await contract.methods.view_collection_cards(firstPlayer, 0).simulate({ from: firstPlayer }); const expected = await getPackedCards(0, seed); @@ -124,8 +124,8 @@ describe('e2e_card_game', () => { beforeEach(async () => { await Promise.all([ - contract.methods.buy_pack(seed).send({ from: firstPlayer }).wait(), - contract.methods.buy_pack(seed).send({ from: secondPlayer }).wait(), + contract.methods.buy_pack(seed).send({ from: firstPlayer }), + contract.methods.buy_pack(seed).send({ from: secondPlayer }), ]); firstPlayerCollection = boundedVecToArray( await contract.methods.view_collection_cards(firstPlayer, 0).simulate({ from: firstPlayer }), @@ -135,14 +135,12 @@ describe('e2e_card_game', () => { it('should be able to join games', async () => { await contract.methods .join_game(GAME_ID, [cardToField(firstPlayerCollection[0]), cardToField(firstPlayerCollection[2])]) - .send({ from: firstPlayer }) - .wait(); + .send({ from: firstPlayer }); await expect( contract.methods .join_game(GAME_ID, [cardToField(firstPlayerCollection[0]), cardToField(firstPlayerCollection[1])]) - .send({ from: secondPlayer }) - .wait(), + .send({ from: secondPlayer }), ).rejects.toThrow(`Not all cards were removed`); const collection = await contract.methods.view_collection_cards(firstPlayer, 0).simulate({ from: firstPlayer }); @@ -179,15 +177,13 @@ describe('e2e_card_game', () => { await Promise.all([ contract.methods .join_game(GAME_ID, [cardToField(firstPlayerCollection[0]), cardToField(firstPlayerCollection[2])]) - .send({ from: firstPlayer }) - .wait(), + .send({ from: firstPlayer }), contract.methods .join_game(GAME_ID, [cardToField(secondPlayerCollection[0]), cardToField(secondPlayerCollection[2])]) - .send({ from: secondPlayer }) - .wait(), + .send({ from: secondPlayer }), ]); - await contract.methods.start_game(GAME_ID).send({ from: firstPlayer }).wait(); + await contract.methods.start_game(GAME_ID).send({ from: firstPlayer }); expect((await contract.methods.view_game(GAME_ID).simulate({ from: firstPlayer })) as Game).toMatchObject({ players: expect.arrayContaining([ @@ -218,9 +214,9 @@ describe('e2e_card_game', () => { beforeEach(async () => { const seed = 27n; await Promise.all([ - contract.methods.buy_pack(seed).send({ from: firstPlayer }).wait(), - contract.methods.buy_pack(seed).send({ from: secondPlayer }).wait(), - contract.methods.buy_pack(seed).send({ from: thirdPlayer }).wait(), + contract.methods.buy_pack(seed).send({ from: firstPlayer }), + contract.methods.buy_pack(seed).send({ from: secondPlayer }), + contract.methods.buy_pack(seed).send({ from: thirdPlayer }), ]); firstPlayerCollection = boundedVecToArray( @@ -240,8 +236,7 @@ describe('e2e_card_game', () => { await contract .withWallet(playerWallet) .methods.join_game(id, cards.map(cardToField)) - .send({ from: playerAddress }) - .wait(); + .send({ from: playerAddress }); } async function playGame(playerDecks: { address: AztecAddress; deck: Card[] }[], id = GAME_ID) { @@ -255,7 +250,7 @@ describe('e2e_card_game', () => { for (let playerIndex = 0; playerIndex < players.length; playerIndex++) { const player = players[playerIndex]; const card = cards[playerIndex][roundIndex]; - await contract.methods.play_card(id, card).send({ from: player }).wait(); + await contract.methods.play_card(id, card).send({ from: player }); } } @@ -272,7 +267,7 @@ describe('e2e_card_game', () => { joinGame(wallet, firstPlayer, firstPlayerGameDeck), joinGame(wallet, secondPlayer, secondPlayerGameDeck), ]); - await contract.methods.start_game(GAME_ID).send({ from: firstPlayer }).wait(); + await contract.methods.start_game(GAME_ID).send({ from: firstPlayer }); let game = await playGame([ { address: firstPlayer, deck: firstPlayerGameDeck }, @@ -287,7 +282,7 @@ describe('e2e_card_game', () => { contract.methods.claim_cards(GAME_ID, game.rounds_cards.map(cardToField)).simulate({ from: loser }), ).rejects.toThrow(/Not the winner/); - await contract.methods.claim_cards(GAME_ID, game.rounds_cards.map(cardToField)).send({ from: winner }).wait(); + await contract.methods.claim_cards(GAME_ID, game.rounds_cards.map(cardToField)).send({ from: winner }); const winnerCollection = boundedVecToArray( (await contract.methods.view_collection_cards(winner, 0).simulate({ from: winner })) as NoirBoundedVec, @@ -301,10 +296,7 @@ describe('e2e_card_game', () => { joinGame(wallet, thirdPlayer, thirdPlayerGameDeck, GAME_ID + 1), ]); - await contract.methods - .start_game(GAME_ID + 1) - .send({ from: winner }) - .wait(); + await contract.methods.start_game(GAME_ID + 1).send({ from: winner }); game = await playGame( [ diff --git a/yarn-project/end-to-end/src/e2e_contract_updates.test.ts b/yarn-project/end-to-end/src/e2e_contract_updates.test.ts index bbd90e8a1b1b..8c8fd078c7de 100644 --- a/yarn-project/end-to-end/src/e2e_contract_updates.test.ts +++ b/yarn-project/end-to-end/src/e2e_contract_updates.test.ts @@ -110,12 +110,14 @@ describe('e2e_contract_updates', () => { } sequencer = maybeSequencer; - ({ contract, instance } = await UpdatableContract.deploy(wallet, constructorArgs[0]) - .send({ from: defaultAccountAddress, contractAddressSalt: salt }) - .wait()); + ({ contract, instance } = await UpdatableContract.deploy(wallet, constructorArgs[0]).send({ + from: defaultAccountAddress, + contractAddressSalt: salt, + wait: { returnReceipt: true }, + })); const registerMethod = await publishContractClass(wallet, UpdatedContractArtifact); - await registerMethod.send({ from: defaultAccountAddress }).wait(); + await registerMethod.send({ from: defaultAccountAddress }); updatedContractClassId = (await getContractClassFromArtifact(UpdatedContractArtifact)).id; }); @@ -129,21 +131,21 @@ describe('e2e_contract_updates', () => { expect(await contract.methods.get_public_value().simulate({ from: defaultAccountAddress })).toEqual( INITIAL_UPDATABLE_CONTRACT_VALUE, ); - await contract.methods.update_to(updatedContractClassId).send({ from: defaultAccountAddress }).wait(); + await contract.methods.update_to(updatedContractClassId).send({ from: defaultAccountAddress }); // Warp time to get past the timestamp of change where the update takes effect await cheatCodes.warpL2TimeAtLeastBy(sequencer, aztecNode, DEFAULT_TEST_UPDATE_DELAY); // Should be updated now await wallet.registerContract(instance, UpdatedContract.artifact); const updatedContract = UpdatedContract.at(contract.address, wallet); // Call a private method that wasn't available in the previous contract - await updatedContract.methods.set_private_value().send({ from: defaultAccountAddress }).wait(); + await updatedContract.methods.set_private_value().send({ from: defaultAccountAddress }); // Read state that was changed by the previous tx expect( await updatedContract.methods.get_private_value(defaultAccountAddress).simulate({ from: defaultAccountAddress }), ).toEqual(UPDATED_CONTRACT_PUBLIC_VALUE); // Call a public method with a new implementation - await updatedContract.methods.set_public_value().send({ from: defaultAccountAddress }).wait(); + await updatedContract.methods.set_public_value().send({ from: defaultAccountAddress }); expect(await updatedContract.methods.get_public_value().simulate({ from: defaultAccountAddress })).toEqual( UPDATED_CONTRACT_PUBLIC_VALUE, ); @@ -155,23 +157,20 @@ describe('e2e_contract_updates', () => { ); // Increases the delay so it should happen immediately - await contract.methods - .set_update_delay(BigInt(MINIMUM_UPDATE_DELAY) + 1n) - .send({ from: defaultAccountAddress }) - .wait(); + await contract.methods.set_update_delay(BigInt(MINIMUM_UPDATE_DELAY) + 1n).send({ from: defaultAccountAddress }); expect(await contract.methods.get_update_delay().simulate({ from: defaultAccountAddress })).toEqual( BigInt(MINIMUM_UPDATE_DELAY) + 1n, ); - await contract.methods.update_to(updatedContractClassId).send({ from: defaultAccountAddress }).wait(); + await contract.methods.update_to(updatedContractClassId).send({ from: defaultAccountAddress }); await cheatCodes.warpL2TimeAtLeastBy(sequencer, aztecNode, BigInt(MINIMUM_UPDATE_DELAY) + 1n); // Should be updated now await wallet.registerContract(instance, UpdatedContract.artifact); const updatedContract = UpdatedContract.at(contract.address, wallet); // Call a private method that wasn't available in the previous contract - await updatedContract.methods.set_private_value().send({ from: defaultAccountAddress }).wait(); + await updatedContract.methods.set_private_value().send({ from: defaultAccountAddress }); }); it('should not allow to change the delay to a value lower than the minimum', async () => { diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l1_to_l2.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l1_to_l2.test.ts index f6d9e1785ab4..8011c01637a5 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l1_to_l2.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l1_to_l2.test.ts @@ -1,5 +1,4 @@ import { AztecAddress } from '@aztec/aztec.js/addresses'; -import { SentTx } from '@aztec/aztec.js/contracts'; import { generateClaimSecret } from '@aztec/aztec.js/ethereum'; import { Fr } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; @@ -35,7 +34,7 @@ describe('e2e_cross_chain_messaging l1_to_l2', () => { await t.setup(); ({ logger: log, crossChainTestHarness, wallet, user1Address, aztecNode } = t); - testContract = await TestContract.deploy(wallet).send({ from: user1Address }).deployed(); + testContract = await TestContract.deploy(wallet).send({ from: user1Address }); }, 300_000); afterEach(async () => { @@ -51,8 +50,7 @@ describe('e2e_cross_chain_messaging l1_to_l2', () => { const advanceBlock = async () => { const block = await aztecNode.getBlockNumber(); log.warn(`Sending noop tx at block ${block}`); - const sentTx = new SentTx(wallet, () => wallet.sendTx(ExecutionPayload.empty(), { from: user1Address })); - await sentTx.wait(); + await wallet.sendTx(ExecutionPayload.empty(), { from: user1Address }); const newBlock = await aztecNode.getBlockNumber(); log.warn(`Advanced to block ${newBlock}`); if (newBlock === block) { @@ -128,9 +126,12 @@ describe('e2e_cross_chain_messaging l1_to_l2', () => { } // We consume the L1 to L2 message using the test contract either from private or public - await getConsumeMethod(scope)(message.content, secret, crossChainTestHarness.ethAccount, actualMessage1Index) - .send({ from: user1Address }) - .wait(); + await getConsumeMethod(scope)( + message.content, + secret, + crossChainTestHarness.ethAccount, + actualMessage1Index, + ).send({ from: user1Address }); // We send and consume the exact same message the second time to test that oracles correctly return the new // non-nullified message @@ -151,9 +152,12 @@ describe('e2e_cross_chain_messaging l1_to_l2', () => { // Now we consume the message again. Everything should pass because oracle should return the duplicate message // which is not nullified - await getConsumeMethod(scope)(message.content, secret, crossChainTestHarness.ethAccount, actualMessage2Index) - .send({ from: user1Address }) - .wait(); + await getConsumeMethod(scope)( + message.content, + secret, + crossChainTestHarness.ethAccount, + actualMessage2Index, + ).send({ from: user1Address }); }, 120_000, ); @@ -215,7 +219,7 @@ describe('e2e_cross_chain_messaging l1_to_l2', () => { // On public, we actually send the tx and check that it reverts due to the missing message. // This advances the block too as a side-effect. Note that we do not rely on a simulation since the cross chain messages // do not get added at the beginning of the block during node_simulatePublicCalls (maybe they should?). - const receipt = await consume().send({ from: user1Address }).wait({ dontThrowOnRevert: true }); + const receipt = await consume().send({ from: user1Address, wait: { dontThrowOnRevert: true } }); expect(receipt.executionResult).toEqual(TxExecutionResult.APP_LOGIC_REVERTED); await t.context.watcher!.markAsProven(); } @@ -228,7 +232,7 @@ describe('e2e_cross_chain_messaging l1_to_l2', () => { } // And consume the message - await consume().send({ from: user1Address }).wait(); + await consume().send({ from: user1Address }); }, ); }); diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l2_to_l1.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l2_to_l1.test.ts index 56c289783254..7432bd33d4f3 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l2_to_l1.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l2_to_l1.test.ts @@ -43,7 +43,7 @@ describe('e2e_cross_chain_messaging l2_to_l1', () => { version = BigInt(await rollup.getVersion()); - contract = await TestContract.deploy(wallet).send({ from: user1Address }).deployed(); + contract = await TestContract.deploy(wallet).send({ from: user1Address }); }); afterAll(async () => { @@ -63,9 +63,7 @@ describe('e2e_cross_chain_messaging l2_to_l1', () => { const txReceipt = await new BatchCall(wallet, [ contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(contents[0], recipient), contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(contents[1], recipient), - ]) - .send({ from: user1Address }) - .wait(); + ]).send({ from: user1Address }); const blockNumber = txReceipt.blockNumber!; @@ -95,11 +93,10 @@ describe('e2e_cross_chain_messaging l2_to_l1', () => { // Send the 2 txs. const [noMessageReceipt, withMessageReceipt] = await Promise.all([ - contract.methods.emit_nullifier(Fr.random()).send({ from: user1Address }).wait(), + contract.methods.emit_nullifier(Fr.random()).send({ from: user1Address }), contract.methods .create_l2_to_l1_message_arbitrary_recipient_private(content, recipient) - .send({ from: user1Address }) - .wait(), + .send({ from: user1Address }), ]); // Check that the 2 txs are in the same block. @@ -123,8 +120,8 @@ describe('e2e_cross_chain_messaging l2_to_l1', () => { const call1 = createBatchCall(wallet, tx1.recipients, tx1.contents); const [l2TxReceipt0, l2TxReceipt1] = await Promise.all([ - call0.send({ from: user1Address }).wait(), - call1.send({ from: user1Address }).wait(), + call0.send({ from: user1Address }), + call1.send({ from: user1Address }), ]); // Check that the 2 txs are in the same block. @@ -177,9 +174,9 @@ describe('e2e_cross_chain_messaging l2_to_l1', () => { const call2 = createBatchCall(wallet, tx2.recipients, tx2.contents); const [l2TxReceipt0, l2TxReceipt1, l2TxReceipt2] = await Promise.all([ - call0.send({ from: user1Address }).wait(), - call1.send({ from: user1Address }).wait(), - call2.send({ from: user1Address }).wait(), + call0.send({ from: user1Address }), + call1.send({ from: user1Address }), + call2.send({ from: user1Address }), ]); // Check that all txs are in the same block. diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_private.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_private.test.ts index faec9c42418f..bb85a8151015 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_private.test.ts @@ -103,8 +103,7 @@ describe('e2e_cross_chain_messaging token_bridge_private', () => { // send the right one - await l2Bridge.methods .claim_private(ownerAddress, bridgeAmount, claim.claimSecret, claim.messageLeafIndex) - .send({ from: user2Address }) - .wait(); + .send({ from: user2Address }); await crossChainTestHarness.expectPrivateBalanceOnL2(ownerAddress, initialPrivateBalance + bridgeAmount); }), diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_public.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_public.test.ts index e7e5b54176b3..0218cdc49857 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_public.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_public.test.ts @@ -71,7 +71,7 @@ describe('e2e_cross_chain_messaging token_bridge_public', () => { }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); // 5. Withdraw owner's funds from L2 to L1 logger.verbose('5. Withdraw owner funds from L2 to L1'); @@ -123,8 +123,7 @@ describe('e2e_cross_chain_messaging token_bridge_public', () => { logger.info("user2 consumes owner's message on L2 Publicly"); await l2Bridge.methods .claim_public(ownerAddress, bridgeAmount, claim.claimSecret, messageLeafIndex) - .send({ from: user2Address }) - .wait(); + .send({ from: user2Address }); // ensure funds are gone to owner and not user2. await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount); diff --git a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts index 36189f780fcb..0c0bd130dfdb 100644 --- a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts +++ b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts @@ -68,9 +68,7 @@ describe('e2e_crowdfunding_and_claim', () => { donationTokenMetadata.name, donationTokenMetadata.symbol, donationTokenMetadata.decimals, - ) - .send({ from: operatorAddress }) - .deployed(); + ).send({ from: operatorAddress }); logger.info(`Donation Token deployed to ${donationToken.address}`); rewardToken = await TokenContract.deploy( @@ -79,9 +77,7 @@ describe('e2e_crowdfunding_and_claim', () => { rewardTokenMetadata.name, rewardTokenMetadata.symbol, rewardTokenMetadata.decimals, - ) - .send({ from: operatorAddress }) - .deployed(); + ).send({ from: operatorAddress }); logger.info(`Reward Token deployed to ${rewardToken.address}`); // We deploy the Crowdfunding contract as an escrow contract (i.e. with populated public keys that make it @@ -98,15 +94,15 @@ describe('e2e_crowdfunding_and_claim', () => { ); const crowdfundingInstance = await crowdfundingDeployment.getInstance(); await wallet.registerContract(crowdfundingInstance, CrowdfundingContract.artifact, crowdfundingSecretKey); - crowdfundingContract = await crowdfundingDeployment.send({ from: operatorAddress }).deployed(); + crowdfundingContract = await crowdfundingDeployment.send({ from: operatorAddress }); logger.info(`Crowdfunding contract deployed at ${crowdfundingContract.address}`); - claimContract = await ClaimContract.deploy(wallet, crowdfundingContract.address, rewardToken.address) - .send({ from: operatorAddress }) - .deployed(); + claimContract = await ClaimContract.deploy(wallet, crowdfundingContract.address, rewardToken.address).send({ + from: operatorAddress, + }); logger.info(`Claim contract deployed at ${claimContract.address}`); - await rewardToken.methods.set_minter(claimContract.address, true).send({ from: operatorAddress }).wait(); + await rewardToken.methods.set_minter(claimContract.address, true).send({ from: operatorAddress }); // Now we mint DNT to donors await mintTokensToPrivate(donationToken, operatorAddress, donor1Address, 1234n); @@ -129,10 +125,7 @@ describe('e2e_crowdfunding_and_claim', () => { 0, ); const witness = await wallet.createAuthWit(donor1Address, { caller: crowdfundingContract.address, action }); - await crowdfundingContract.methods - .donate(donationAmount) - .send({ from: donor1Address, authWitnesses: [witness] }) - .wait(); + await crowdfundingContract.methods.donate(donationAmount).send({ from: donor1Address, authWitnesses: [witness] }); // The donor should have exactly one note const pageIndex = 0; @@ -145,7 +138,7 @@ describe('e2e_crowdfunding_and_claim', () => { // 2) We claim the reward token via the Claim contract { - await claimContract.methods.claim(uintNote, donor1Address).send({ from: donor1Address }).wait(); + await claimContract.methods.claim(uintNote, donor1Address).send({ from: donor1Address }); } // Since the RWT is minted 1:1 with the DNT, the balance of the reward token should be equal to the donation amount @@ -158,7 +151,7 @@ describe('e2e_crowdfunding_and_claim', () => { expect(balanceDNTBeforeWithdrawal).toEqual(0n); // 3) At last, we withdraw the raised funds from the crowdfunding contract to the operator's address - await crowdfundingContract.methods.withdraw(donationAmount).send({ from: operatorAddress }).wait(); + await crowdfundingContract.methods.withdraw(donationAmount).send({ from: operatorAddress }); const balanceDNTAfterWithdrawal = await donationToken.methods .balance_of_private(operatorAddress) @@ -170,9 +163,7 @@ describe('e2e_crowdfunding_and_claim', () => { it('cannot claim twice', async () => { // The first claim was executed in the previous test - await expect( - claimContract.methods.claim(uintNote, donor1Address).send({ from: donor1Address }).wait(), - ).rejects.toThrow(); + await expect(claimContract.methods.claim(uintNote, donor1Address).send({ from: donor1Address })).rejects.toThrow(); }); it('cannot claim with a different address than the one that donated', async () => { @@ -189,10 +180,7 @@ describe('e2e_crowdfunding_and_claim', () => { 0, ); const witness = await wallet.createAuthWit(donorAddress, { caller: crowdfundingContract.address, action }); - await crowdfundingContract.methods - .donate(donationAmount) - .send({ from: donorAddress, authWitnesses: [witness] }) - .wait(); + await crowdfundingContract.methods.donate(donationAmount).send({ from: donorAddress, authWitnesses: [witness] }); // The donor should have exactly one note const pageIndex = 0; @@ -206,7 +194,7 @@ describe('e2e_crowdfunding_and_claim', () => { // should fail because the msg_sender is not the note owner. // docs:start:local-tx-fails await expect( - claimContract.methods.claim(anotherDonationNote, donorAddress).send({ from: unrelatedAddress }).wait(), + claimContract.methods.claim(anotherDonationNote, donorAddress).send({ from: unrelatedAddress }), ).rejects.toThrow('hinted_note.owner == self.msg_sender()'); // docs:end:local-tx-fails }); @@ -217,7 +205,7 @@ describe('e2e_crowdfunding_and_claim', () => { nonExistentNote.randomness = Fr.random(); await expect( - claimContract.methods.claim(nonExistentNote, donor1Address).send({ from: donor1Address }).wait(), + claimContract.methods.claim(nonExistentNote, donor1Address).send({ from: donor1Address }), ).rejects.toThrow(); }); @@ -233,7 +221,7 @@ describe('e2e_crowdfunding_and_claim', () => { deadline, ); - otherCrowdfundingContract = await otherCrowdfundingDeployment.send({ from: operatorAddress }).deployed(); + otherCrowdfundingContract = await otherCrowdfundingDeployment.send({ from: operatorAddress }); logger.info(`Crowdfunding contract deployed at ${otherCrowdfundingContract.address}`); } @@ -249,8 +237,7 @@ describe('e2e_crowdfunding_and_claim', () => { const witness = await wallet.createAuthWit(donor1Address, { caller: otherCrowdfundingContract.address, action }); await otherCrowdfundingContract.methods .donate(donationAmount) - .send({ from: donor1Address, authWitnesses: [witness] }) - .wait(); + .send({ from: donor1Address, authWitnesses: [witness] }); // 3) Get the donation note const pageIndex = 0; @@ -262,7 +249,7 @@ describe('e2e_crowdfunding_and_claim', () => { // 4) Try to claim rewards using note from other contract await expect( - claimContract.methods.claim(otherContractNote, donor1Address).send({ from: donor1Address }).wait(), + claimContract.methods.claim(otherContractNote, donor1Address).send({ from: donor1Address }), ).rejects.toThrow(); }); @@ -279,15 +266,12 @@ describe('e2e_crowdfunding_and_claim', () => { const witness = await wallet.createAuthWit(donor2Address, { caller: crowdfundingContract.address, action }); // 2) We donate to the crowdfunding contract - await crowdfundingContract.methods - .donate(donationAmount) - .send({ from: donor2Address, authWitnesses: [witness] }) - .wait(); + await crowdfundingContract.methods.donate(donationAmount).send({ from: donor2Address, authWitnesses: [witness] }); // The following should fail as msg_sender != operator - await expect( - crowdfundingContract.methods.withdraw(donationAmount).send({ from: donor2Address }).wait(), - ).rejects.toThrow('Assertion failed: Not an operator'); + await expect(crowdfundingContract.methods.withdraw(donationAmount).send({ from: donor2Address })).rejects.toThrow( + 'Assertion failed: Not an operator', + ); }); it('cannot donate after a deadline', async () => { @@ -308,10 +292,7 @@ describe('e2e_crowdfunding_and_claim', () => { // 3) We donate to the crowdfunding contract await expect( - crowdfundingContract.methods - .donate(donationAmount) - .send({ from: donor2Address, authWitnesses: [witness] }) - .wait(), + crowdfundingContract.methods.donate(donationAmount).send({ from: donor2Address, authWitnesses: [witness] }), ).rejects.toThrow(); }); }); diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/contract_class_registration.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/contract_class_registration.test.ts index f936e06cf2e5..928c5303ecdd 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/contract_class_registration.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/contract_class_registration.test.ts @@ -43,7 +43,7 @@ describe('e2e_deploy_contract contract class registration', () => { ({ logger, wallet, aztecNode, defaultAccountAddress } = await t.setup()); artifact = StatefulTestContract.artifact; publicationTxReceipt = await publishContractClass(wallet, artifact).then(c => - c.send({ from: defaultAccountAddress }).wait(), + c.send({ from: defaultAccountAddress }), ); contractClass = await getContractClassFromArtifact(artifact); expect(await aztecNode.getContractClass(contractClass.id)).toBeDefined(); @@ -54,7 +54,7 @@ describe('e2e_deploy_contract contract class registration', () => { describe('publishing a contract class', () => { it('emits public bytecode', async () => { const publicationTxReceipt = await publishContractClass(wallet, TestContract.artifact).then(c => - c.send({ from: defaultAccountAddress }).wait(), + c.send({ from: defaultAccountAddress }), ); const logs = await aztecNode.getContractClassLogs({ txHash: publicationTxReceipt.txHash }); expect(logs.logs.length).toEqual(1); @@ -90,9 +90,9 @@ describe('e2e_deploy_contract contract class registration', () => { constructorArtifact.parameters, ); - const tx = await (await broadcastPrivateFunction(wallet, artifact, selector)) - .send({ from: defaultAccountAddress }) - .wait(); + const tx = await ( + await broadcastPrivateFunction(wallet, artifact, selector) + ).send({ from: defaultAccountAddress }); const logs = await aztecNode.getContractClassLogs({ txHash: tx.txHash }); const logData = logs.logs[0].log.toBuffer(); @@ -110,9 +110,9 @@ describe('e2e_deploy_contract contract class registration', () => { it('broadcasts a utility function', async () => { const functionArtifact = artifact.functions.find(fn => fn.functionType === FunctionType.UTILITY)!; const selector = await FunctionSelector.fromNameAndParameters(functionArtifact); - const tx = await (await broadcastUtilityFunction(wallet, artifact, selector)) - .send({ from: defaultAccountAddress }) - .wait(); + const tx = await ( + await broadcastUtilityFunction(wallet, artifact, selector) + ).send({ from: defaultAccountAddress }); const logs = await aztecNode.getContractClassLogs({ txHash: tx.txHash }); const logData = logs.logs[0].log.toBuffer(); @@ -203,10 +203,7 @@ describe('e2e_deploy_contract contract class registration', () => { it('calls a public function with no init check on the deployed instance', async () => { const whom = await AztecAddress.random(); - await contract.methods - .increment_public_value_no_init_check(whom, 10) - .send({ from: defaultAccountAddress }) - .wait(); + await contract.methods.increment_public_value_no_init_check(whom, 10).send({ from: defaultAccountAddress }); const stored = await contract.methods.get_public_value(whom).simulate({ from: defaultAccountAddress }); expect(stored).toEqual(10n); }); @@ -215,8 +212,7 @@ describe('e2e_deploy_contract contract class registration', () => { const whom = await AztecAddress.random(); const receipt = await contract.methods .increment_public_value(whom, 10) - .send({ from: defaultAccountAddress }) - .wait({ dontThrowOnRevert: true }); + .send({ from: defaultAccountAddress, wait: { dontThrowOnRevert: true } }); expect(receipt.executionResult).toEqual(TxExecutionResult.APP_LOGIC_REVERTED); // Meanwhile we check we didn't increment the value @@ -230,22 +226,16 @@ describe('e2e_deploy_contract contract class registration', () => { }); it('initializes the contract and calls a public function', async () => { - await contract.methods - .constructor(...initArgs) - .send({ from: defaultAccountAddress }) - .wait(); + await contract.methods.constructor(...initArgs).send({ from: defaultAccountAddress }); const whom = await AztecAddress.random(); - await contract.methods.increment_public_value(whom, 10).send({ from: defaultAccountAddress }).wait(); + await contract.methods.increment_public_value(whom, 10).send({ from: defaultAccountAddress }); const stored = await contract.methods.get_public_value(whom).simulate({ from: defaultAccountAddress }); expect(stored).toEqual(10n); }); it('refuses to reinitialize the contract', async () => { await expect( - contract.methods - .constructor(...initArgs) - .send({ from: defaultAccountAddress }) - .wait(), + contract.methods.constructor(...initArgs).send({ from: defaultAccountAddress }), // TODO(https://github.com/AztecProtocol/aztec-packages/issues/5818): Make these a fixed error after transition. ).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); }); @@ -262,29 +252,22 @@ describe('e2e_deploy_contract contract class registration', () => { const whom = await AztecAddress.random(); const receipt = await contract.methods .public_constructor(whom, 43) - .send({ from: defaultAccountAddress }) - .wait({ dontThrowOnRevert: true }); + .send({ from: defaultAccountAddress, wait: { dontThrowOnRevert: true } }); expect(receipt.executionResult).toEqual(TxExecutionResult.APP_LOGIC_REVERTED); expect(await contract.methods.get_public_value(whom).simulate({ from: defaultAccountAddress })).toEqual(0n); }); it('initializes the contract and calls a public function', async () => { - await contract.methods - .public_constructor(...initArgs) - .send({ from: defaultAccountAddress }) - .wait(); + await contract.methods.public_constructor(...initArgs).send({ from: defaultAccountAddress }); const whom = await AztecAddress.random(); - await contract.methods.increment_public_value(whom, 10).send({ from: defaultAccountAddress }).wait(); + await contract.methods.increment_public_value(whom, 10).send({ from: defaultAccountAddress }); const stored = await contract.methods.get_public_value(whom).simulate({ from: defaultAccountAddress }); expect(stored).toEqual(10n); }); it('refuses to reinitialize the contract', async () => { await expect( - contract.methods - .public_constructor(...initArgs) - .send({ from: defaultAccountAddress }) - .wait(), + contract.methods.public_constructor(...initArgs).send({ from: defaultAccountAddress }), ).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); }); }); @@ -293,15 +276,15 @@ describe('e2e_deploy_contract contract class registration', () => { testDeployingAnInstance('from a wallet', async instance => { // Calls the deployer contract directly from a wallet const deployMethod = publishInstance(wallet, instance); - await deployMethod.send({ from: defaultAccountAddress }).wait(); + await deployMethod.send({ from: defaultAccountAddress }); }); testDeployingAnInstance('from a contract', async instance => { // Register the instance to be deployed in the pxe await wallet.registerContract(instance, artifact); // Set up the contract that calls the deployer (which happens to be the TestContract) and call it - const deployer = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); - await deployer.methods.publish_contract_instance(instance.address).send({ from: defaultAccountAddress }).wait(); + const deployer = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }); + await deployer.methods.publish_contract_instance(instance.address).send({ from: defaultAccountAddress }); }); describe('error scenarios in deployment', () => { @@ -317,8 +300,7 @@ describe('e2e_deploy_contract contract class registration', () => { // despite reverting in app logic because of the call to a non-existent contract const tx = await instance.methods .increment_public_value_no_init_check(whom, 10) - .send({ from: defaultAccountAddress }) - .wait({ dontThrowOnRevert: true }); + .send({ from: defaultAccountAddress, wait: { dontThrowOnRevert: true } }); expect(tx.executionResult).toEqual(TxExecutionResult.APP_LOGIC_REVERTED); }); }); diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts index bfcecfe5f76d..a419af9fdd23 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts @@ -31,7 +31,7 @@ describe('e2e_deploy_contract deploy method', () => { const owner = defaultAccountAddress; const opts = { skipClassPublication: true, from: defaultAccountAddress }; logger.debug(`Trying to initialize a contract instance without publishing its contract class`); - await expect(StatefulTestContract.deploy(wallet, owner, 42).send(opts).wait()).rejects.toThrow( + await expect(StatefulTestContract.deploy(wallet, owner, 42).send(opts)).rejects.toThrow( /Cannot find the leaf for nullifier/, ); }); @@ -40,13 +40,11 @@ describe('e2e_deploy_contract deploy method', () => { const owner = defaultAccountAddress; logger.debug(`Deploying stateful test contract`); // docs:start:deploy_basic - const contract = await StatefulTestContract.deploy(wallet, owner, 42) - .send({ from: defaultAccountAddress }) - .deployed(); + const contract = await StatefulTestContract.deploy(wallet, owner, 42).send({ from: defaultAccountAddress }); // docs:end:deploy_basic expect(await contract.methods.summed_values(owner).simulate({ from: defaultAccountAddress })).toEqual(42n); logger.debug(`Calling public method on stateful test contract at ${contract.address.toString()}`); - await contract.methods.increment_public_value(owner, 84).send({ from: defaultAccountAddress }).wait(); + await contract.methods.increment_public_value(owner, 84).send({ from: defaultAccountAddress }); expect(await contract.methods.get_public_value(owner).simulate({ from: defaultAccountAddress })).toEqual(84n); // docs:start:verify_deployment const metadata = await wallet.getContractMetadata(contract.address); @@ -60,19 +58,19 @@ describe('e2e_deploy_contract deploy method', () => { const owner = defaultAccountAddress; // docs:start:deploy_universal const opts = { universalDeploy: true, from: defaultAccountAddress }; - const contract = await StatefulTestContract.deploy(wallet, owner, 42).send(opts).deployed(); + const contract = await StatefulTestContract.deploy(wallet, owner, 42).send(opts); // docs:end:deploy_universal expect(await contract.methods.summed_values(owner).simulate({ from: defaultAccountAddress })).toEqual(42n); - await contract.methods.increment_public_value(owner, 84).send({ from: defaultAccountAddress }).wait(); + await contract.methods.increment_public_value(owner, 84).send({ from: defaultAccountAddress }); expect(await contract.methods.get_public_value(owner).simulate({ from: defaultAccountAddress })).toEqual(84n); }); it('publicly deploys and calls a public function from the constructor', async () => { const owner = defaultAccountAddress; // docs:start:deploy_token - const token = await TokenContract.deploy(wallet, owner, 'TOKEN', 'TKN', 18) - .send({ from: defaultAccountAddress }) - .deployed(); + const token = await TokenContract.deploy(wallet, owner, 'TOKEN', 'TKN', 18).send({ + from: defaultAccountAddress, + }); // docs:end:deploy_token expect(await token.methods.is_minter(owner).simulate({ from: defaultAccountAddress })).toEqual(true); }); @@ -81,22 +79,26 @@ describe('e2e_deploy_contract deploy method', () => { const owner = defaultAccountAddress; logger.debug(`Deploying contract via a public constructor`); // docs:start:deploy_with_opts - const contract = await StatefulTestContract.deployWithOpts({ wallet, method: 'public_constructor' }, owner, 42) - .send({ from: defaultAccountAddress }) - .deployed(); + const contract = await StatefulTestContract.deployWithOpts( + { wallet, method: 'public_constructor' }, + owner, + 42, + ).send({ + from: defaultAccountAddress, + }); // docs:end:deploy_with_opts expect(await contract.methods.get_public_value(owner).simulate({ from: defaultAccountAddress })).toEqual(42n); logger.debug(`Calling a private function to ensure the contract was properly initialized`); - await contract.methods.create_note(owner, 30).send({ from: defaultAccountAddress }).wait(); + await contract.methods.create_note(owner, 30).send({ from: defaultAccountAddress }); expect(await contract.methods.summed_values(owner).simulate({ from: defaultAccountAddress })).toEqual(30n); }); it('deploys a contract with a default initializer not named constructor', async () => { logger.debug(`Deploying contract with a default initializer named initialize`); const opts = { skipClassPublication: true, skipInstancePublication: true, from: defaultAccountAddress }; - const contract = await CounterContract.deploy(wallet, 10, defaultAccountAddress).send(opts).deployed(); + const contract = await CounterContract.deploy(wallet, 10, defaultAccountAddress).send(opts); logger.debug(`Calling a function to ensure the contract was properly initialized`); - await contract.methods.increment_twice(defaultAccountAddress).send({ from: defaultAccountAddress }).wait(); + await contract.methods.increment_twice(defaultAccountAddress).send({ from: defaultAccountAddress }); expect(await contract.methods.get_counter(defaultAccountAddress).simulate({ from: defaultAccountAddress })).toEqual( 12n, ); @@ -104,10 +106,10 @@ describe('e2e_deploy_contract deploy method', () => { it('publicly deploys a contract with no constructor', async () => { logger.debug(`Deploying contract with no constructor`); - const contract = await NoConstructorContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + const contract = await NoConstructorContract.deploy(wallet).send({ from: defaultAccountAddress }); const arbitraryValue = 42; logger.debug(`Call a public function to check that it was publicly deployed`); - const receipt = await contract.methods.emit_public(arbitraryValue).send({ from: defaultAccountAddress }).wait(); + const receipt = await contract.methods.emit_public(arbitraryValue).send({ from: defaultAccountAddress }); const logs = await aztecNode.getPublicLogs({ txHash: receipt.txHash }); expect(logs.logs[0].log.getEmittedFields()).toEqual([new Fr(arbitraryValue)]); }); @@ -115,7 +117,7 @@ describe('e2e_deploy_contract deploy method', () => { it('refuses to deploy a contract with no constructor and no public deployment', async () => { logger.debug(`Deploying contract with no constructor and skipping public deploy`); const opts = { skipInstancePublication: true, skipClassPublication: true, from: defaultAccountAddress }; - await expect(NoConstructorContract.deploy(wallet).send(opts).wait()).rejects.toThrow( + await expect(NoConstructorContract.deploy(wallet).send(opts)).rejects.toThrow( 'No transactions are needed to publish or initialize contract NoConstructor', ); }); @@ -129,7 +131,7 @@ describe('e2e_deploy_contract deploy method', () => { // Batch deployment and a public call into the same transaction const publicCall = contract.methods.increment_public_value(owner, 84); - await new BatchCall(wallet, [deployMethod, publicCall]).send({ from: defaultAccountAddress }).wait(); + await new BatchCall(wallet, [deployMethod, publicCall]).send({ from: defaultAccountAddress }); // docs:end:deploy_batch }, 300_000); @@ -150,12 +152,14 @@ describe('e2e_deploy_contract deploy method', () => { // First send the deploy transaction // Pay priority fee to ensure the deployment transaction gets processed first. const maxPriorityFeesPerGas = new GasFees(1n, 0n); - const deployTxPromise = deployTx - .send({ from: defaultAccountAddress, fee: { gasSettings: { maxPriorityFeesPerGas } } }) - .wait({ timeout: 600 }); + const deployTxPromise = deployTx.send({ + from: defaultAccountAddress, + fee: { gasSettings: { maxPriorityFeesPerGas } }, + wait: { timeout: 600 }, + }); // Then send the public call transaction - const publicCallTxPromise = publicCall.send({ from: defaultAccountAddress }).wait({ timeout: 600 }); + const publicCallTxPromise = publicCall.send({ from: defaultAccountAddress, wait: { timeout: 600 } }); logger.debug('Deploying a contract and calling a public function in the same block'); const [deployTxReceipt, publicCallTxReceipt] = await Promise.all([deployTxPromise, publicCallTxPromise]); @@ -171,9 +175,9 @@ describe('e2e_deploy_contract deploy method', () => { const aztecNode = createAztecNodeClient(AZTEC_NODE_URL); const retryingWallet = await TestWallet.create(aztecNode); await expect( - StatefulTestContract.deployWithOpts({ wallet: retryingWallet, method: 'wrong_constructor' }) - .send({ from: defaultAccountAddress }) - .deployed(), + StatefulTestContract.deployWithOpts({ wallet: retryingWallet, method: 'wrong_constructor' }).send({ + from: defaultAccountAddress, + }), ).rejects.toThrow(/Unknown function/); }); }); diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/legacy.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/legacy.test.ts index 10598ba64ff1..5eda802256c4 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/legacy.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/legacy.test.ts @@ -38,8 +38,7 @@ describe('e2e_deploy_contract legacy', () => { const deployer = new ContractDeployer(TestContractArtifact, wallet); const receipt = await deployer .deploy() - .send({ from: defaultAccountAddress, contractAddressSalt: salt }) - .wait({ wallet }); + .send({ from: defaultAccountAddress, contractAddressSalt: salt, wait: { returnReceipt: true } }); expect(receipt.contract.address).toEqual(deploymentData.address); const { instance, isContractPublished } = await wallet.getContractMetadata(deploymentData.address); expect(instance).toBeDefined(); @@ -54,7 +53,7 @@ describe('e2e_deploy_contract legacy', () => { for (let index = 0; index < 2; index++) { logger.info(`Deploying contract ${index + 1}...`); - await deployer.deploy().send({ from: defaultAccountAddress, contractAddressSalt: Fr.random() }).wait({ wallet }); + await deployer.deploy().send({ from: defaultAccountAddress, contractAddressSalt: Fr.random() }); } }); @@ -68,13 +67,11 @@ describe('e2e_deploy_contract legacy', () => { logger.info(`Deploying contract ${index + 1}...`); const receipt = await deployer .deploy() - .send({ from: defaultAccountAddress, contractAddressSalt: Fr.random() }) - .wait({ wallet }); + .send({ from: defaultAccountAddress, contractAddressSalt: Fr.random(), wait: { returnReceipt: true } }); logger.info(`Sending TX to contract ${index + 1}...`); await receipt.contract.methods .get_master_incoming_viewing_public_key(defaultAccountAddress) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); } }); @@ -86,8 +83,8 @@ describe('e2e_deploy_contract legacy', () => { const contractAddressSalt = Fr.random(); const deployer = new ContractDeployer(TestContractArtifact, wallet); - await deployer.deploy().send({ from: defaultAccountAddress, contractAddressSalt }).wait({ wallet }); - await expect(deployer.deploy().send({ from: defaultAccountAddress, contractAddressSalt }).wait()).rejects.toThrow( + await deployer.deploy().send({ from: defaultAccountAddress, contractAddressSalt }); + await expect(deployer.deploy().send({ from: defaultAccountAddress, contractAddressSalt })).rejects.toThrow( TX_ERROR_EXISTING_NULLIFIER, ); }); @@ -108,22 +105,24 @@ describe('e2e_deploy_contract legacy', () => { from: defaultAccountAddress, }; - const [goodTx, badTx] = await Promise.all([goodDeploy.send(firstOpts), badDeploy.send(secondOpts)]); const [goodTxPromiseResult, badTxReceiptResult] = await Promise.allSettled([ - goodTx.wait(), - badTx.wait({ dontThrowOnRevert: true }), + goodDeploy.send({ ...firstOpts, wait: { returnReceipt: true } }), + badDeploy.send({ ...secondOpts, wait: { dontThrowOnRevert: true, returnReceipt: true } }), ]); expect(goodTxPromiseResult.status).toBe('fulfilled'); expect(badTxReceiptResult.status).toBe('fulfilled'); // but reverted - const [goodTxReceipt, badTxReceipt] = await Promise.all([goodTx.getReceipt(), badTx.getReceipt()]); + const goodTxReceipt = goodTxPromiseResult.status === 'fulfilled' ? goodTxPromiseResult.value : null; + const badTxReceipt = badTxReceiptResult.status === 'fulfilled' ? badTxReceiptResult.value : null; // Both the good and bad transactions are included - expect(goodTxReceipt.blockNumber).toEqual(expect.any(Number)); - expect(badTxReceipt.blockNumber).toEqual(expect.any(Number)); + expect(goodTxReceipt).toBeDefined(); + expect(badTxReceipt).toBeDefined(); + expect(goodTxReceipt!.blockNumber).toEqual(expect.any(Number)); + expect(badTxReceipt!.blockNumber).toEqual(expect.any(Number)); - expect(badTxReceipt.executionResult).toEqual(TxExecutionResult.APP_LOGIC_REVERTED); + expect(badTxReceipt!.executionResult).toEqual(TxExecutionResult.APP_LOGIC_REVERTED); const badInstance = await badDeploy.getInstance(); // But the bad tx did not deploy the class diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/private_initialization.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/private_initialization.test.ts index b641dc276ff0..07d674e02a67 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/private_initialization.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/private_initialization.test.ts @@ -31,7 +31,7 @@ describe('e2e_deploy_contract private initialization', () => { // The function has a noinitcheck flag so it can be called without initialization. it('executes a noinitcheck function in an uninitialized contract', async () => { const contract = await t.registerContract(wallet, TestContract); - const receipt = await contract.methods.emit_nullifier(10).send({ from: defaultAccountAddress }).wait(); + const receipt = await contract.methods.emit_nullifier(10).send({ from: defaultAccountAddress }); const txEffects = await aztecNode.getTxEffect(receipt.txHash); const expected = await siloNullifier(contract.address, new Fr(10)); @@ -46,7 +46,7 @@ describe('e2e_deploy_contract private initialization', () => { await expect( contract.methods.is_private_mutable_initialized(defaultAccountAddress).simulate({ from: defaultAccountAddress }), ).resolves.toEqual(false); - await contract.methods.initialize_private_mutable(42).send({ from: defaultAccountAddress }).wait(); + await contract.methods.initialize_private_mutable(42).send({ from: defaultAccountAddress }); await expect( contract.methods.is_private_mutable_initialized(defaultAccountAddress).simulate({ from: defaultAccountAddress }), ).resolves.toEqual(true); @@ -58,14 +58,11 @@ describe('e2e_deploy_contract private initialization', () => { const initArgs: StatefulContractCtorArgs = [owner, 42]; const contract = await t.registerContract(wallet, StatefulTestContract, { initArgs }); logger.info(`Calling the constructor for ${contract.address}`); - await contract.methods - .constructor(...initArgs) - .send({ from: defaultAccountAddress }) - .wait(); + await contract.methods.constructor(...initArgs).send({ from: defaultAccountAddress }); logger.info(`Checking if the constructor was run for ${contract.address}`); expect(await contract.methods.summed_values(owner).simulate({ from: defaultAccountAddress })).toEqual(42n); logger.info(`Calling a private function that requires initialization on ${contract.address}`); - await contract.methods.create_note(owner, 10).send({ from: defaultAccountAddress }).wait(); + await contract.methods.create_note(owner, 10).send({ from: defaultAccountAddress }); expect(await contract.methods.summed_values(owner).simulate({ from: defaultAccountAddress })).toEqual(52n); }); @@ -77,7 +74,7 @@ describe('e2e_deploy_contract private initialization', () => { initArgs.map(initArgs => t.registerContract(wallet, StatefulTestContract, { initArgs })), ); const calls = contracts.map((c, i) => c.methods.constructor(...initArgs[i])); - await new BatchCall(wallet, calls).send({ from: defaultAccountAddress }).wait(); + await new BatchCall(wallet, calls).send({ from: defaultAccountAddress }); expect(await contracts[0].methods.summed_values(owner).simulate({ from: defaultAccountAddress })).toEqual(42n); expect(await contracts[1].methods.summed_values(owner).simulate({ from: defaultAccountAddress })).toEqual(52n); }); @@ -91,7 +88,7 @@ describe('e2e_deploy_contract private initialization', () => { contract.methods.create_note(owner, 10), ]); logger.info(`Executing constructor and private function in batch at ${contract.address}`); - await batch.send({ from: defaultAccountAddress }).wait(); + await batch.send({ from: defaultAccountAddress }); expect(await contract.methods.summed_values(owner).simulate({ from: defaultAccountAddress })).toEqual(52n); }); @@ -99,16 +96,10 @@ describe('e2e_deploy_contract private initialization', () => { const owner = (await wallet.createAccount()).address; const initArgs: StatefulContractCtorArgs = [owner, 42]; const contract = await t.registerContract(wallet, StatefulTestContract, { initArgs }); - await contract.methods - .constructor(...initArgs) - .send({ from: defaultAccountAddress }) - .wait(); - await expect( - contract.methods - .constructor(...initArgs) - .send({ from: defaultAccountAddress }) - .wait(), - ).rejects.toThrow(TX_ERROR_EXISTING_NULLIFIER); + await contract.methods.constructor(...initArgs).send({ from: defaultAccountAddress }); + await expect(contract.methods.constructor(...initArgs).send({ from: defaultAccountAddress })).rejects.toThrow( + TX_ERROR_EXISTING_NULLIFIER, + ); }); it('refuses to call a private function that requires initialization', async () => { @@ -116,7 +107,7 @@ describe('e2e_deploy_contract private initialization', () => { const initArgs: StatefulContractCtorArgs = [owner, 42]; const contract = await t.registerContract(wallet, StatefulTestContract, { initArgs }); // TODO(@spalladino): It'd be nicer to be able to fail the assert with a more descriptive message. - await expect(contract.methods.create_note(owner, 10).send({ from: defaultAccountAddress }).wait()).rejects.toThrow( + await expect(contract.methods.create_note(owner, 10).send({ from: defaultAccountAddress })).rejects.toThrow( /Cannot find the leaf for nullifier/i, ); }); diff --git a/yarn-project/end-to-end/src/e2e_double_spend.test.ts b/yarn-project/end-to-end/src/e2e_double_spend.test.ts index 6da2ae6a6c9a..6b4e2053b380 100644 --- a/yarn-project/end-to-end/src/e2e_double_spend.test.ts +++ b/yarn-project/end-to-end/src/e2e_double_spend.test.ts @@ -25,7 +25,7 @@ describe('e2e_double_spend', () => { logger, } = await setup(1)); - contract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + contract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }); logger.info(`Test contract deployed at ${contract.address}`); }); @@ -35,7 +35,7 @@ describe('e2e_double_spend', () => { describe('double spends', () => { it('emits a public nullifier and then tries to emit the same nullifier', async () => { const nullifier = new Fr(1); - await contract.methods.emit_nullifier_public(nullifier).send({ from: defaultAccountAddress }).wait(); + await contract.methods.emit_nullifier_public(nullifier).send({ from: defaultAccountAddress }); // We try emitting again, but our TX is dropped due to trying to emit a duplicate nullifier // first confirm that it fails simulation @@ -45,7 +45,7 @@ describe('e2e_double_spend', () => { // if we skip simulation before submitting the tx, // tx will be included in a block but with app logic reverted await expect( - contract.methods.emit_nullifier_public(nullifier).send({ from: defaultAccountAddress }).wait(), + contract.methods.emit_nullifier_public(nullifier).send({ from: defaultAccountAddress }), ).rejects.toThrow(TxExecutionResult.APP_LOGIC_REVERTED); }); }); diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_first_slot.test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_first_slot.test.ts index c5e8efc22c5a..c91e2d69489f 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_first_slot.test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_first_slot.test.ts @@ -1,8 +1,10 @@ import type { AztecNodeService } from '@aztec/aztec-node'; import { EthAddress } from '@aztec/aztec.js/addresses'; import { getTimestampRangeForEpoch } from '@aztec/aztec.js/block'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { Fr } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; +import { waitForTx } from '@aztec/aztec.js/node'; import { INITIAL_L2_BLOCK_NUM } from '@aztec/aztec.js/protocol'; import type { Operator } from '@aztec/ethereum/deploy-aztec-l1-contracts'; import { asyncMap } from '@aztec/foundation/async-map'; @@ -95,9 +97,9 @@ describe('e2e_epochs/epochs_first_slot', () => { const txs = await timesAsync(TX_COUNT, i => proveInteraction(context.wallet, contract.methods.spam(i, 1n, false), { from: context.accounts[0] }), ); - const sentTxs = await Promise.all(txs.map(tx => tx.send())); - logger.warn(`Sent ${sentTxs.length} transactions`, { - txs: await Promise.all(sentTxs.map(tx => tx.getTxHash())), + const txHashes = await Promise.all(txs.map(tx => tx.send({ wait: NO_WAIT }))); + logger.warn(`Sent ${txHashes.length} transactions`, { + txs: txHashes, }); const sequencers = nodes.map(node => node.getSequencer()!); @@ -115,7 +117,7 @@ describe('e2e_epochs/epochs_first_slot', () => { // Wait until all txs are mined const timeout = test.L2_SLOT_DURATION_IN_S * (TX_COUNT * 2 + 1) * 1000; - await executeTimeout(() => Promise.all(sentTxs.map(tx => tx.wait())), timeout); + await executeTimeout(() => Promise.all(txHashes.map(hash => waitForTx(context.aztecNode, hash))), timeout); logger.warn(`All txs have been mined`); // Check that the first two slots of the epoch have a block diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_high_tps_block_building.test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_high_tps_block_building.test.ts index 93e459a5cf8a..c31915a0b16d 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_high_tps_block_building.test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_high_tps_block_building.test.ts @@ -1,7 +1,9 @@ import type { AztecNodeService } from '@aztec/aztec-node'; import { EthAddress } from '@aztec/aztec.js/addresses'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { Fr } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; +import { waitForTx } from '@aztec/aztec.js/node'; import type { Operator } from '@aztec/ethereum/deploy-aztec-l1-contracts'; import { asyncMap } from '@aztec/foundation/async-map'; import { BlockNumber } from '@aztec/foundation/branded-types'; @@ -99,9 +101,9 @@ describe('e2e_epochs/epochs_high_tps_block_building', () => { const txs = await timesAsync(TX_COUNT, i => proveInteraction(context.wallet, contract.methods.spam(i, 1n, false), { from: context.accounts[0] }), ); - const sentTxs = await Promise.all(txs.map(tx => tx.send())); - logger.warn(`Sent ${sentTxs.length} transactions`, { - txs: await Promise.all(sentTxs.map(tx => tx.getTxHash())), + const txHashes = await Promise.all(txs.map(tx => tx.send({ wait: NO_WAIT }))); + logger.warn(`Sent ${txHashes.length} transactions`, { + txs: txHashes, }); const sequencers = nodes.map(node => node.getSequencer()!); @@ -113,7 +115,7 @@ describe('e2e_epochs/epochs_high_tps_block_building', () => { // Wait until all txs are mined const timeout = test.L2_SLOT_DURATION_IN_S * (TX_COUNT + 3); - await Promise.all(sentTxs.map(tx => tx.wait({ timeout }))); + await Promise.all(txHashes.map(txHash => waitForTx(context.aztecNode, txHash, { timeout }))); logger.warn(`All txs have been mined`); // Check all blocks mined by the sequencers have under the expected max number of transactions. diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_invalidate_block.parallel.test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_invalidate_block.parallel.test.ts index cf50996e86f4..2e1435942d00 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_invalidate_block.parallel.test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_invalidate_block.parallel.test.ts @@ -1,6 +1,8 @@ import type { AztecNodeService } from '@aztec/aztec-node'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { Fr } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; +import { waitForTx } from '@aztec/aztec.js/node'; import { RollupContract } from '@aztec/ethereum/contracts'; import type { Operator } from '@aztec/ethereum/deploy-aztec-l1-contracts'; import type { ExtendedViemWalletClient } from '@aztec/ethereum/types'; @@ -108,7 +110,7 @@ describe('e2e_epochs/epochs_invalidate_block', () => { // Send a transaction so the sequencer builds a block logger.warn('Sending transaction to trigger block building'); - const sentTx = contract.methods.spam(1, 1n, false).send({ from: context.accounts[0] }); + const sentTx = await contract.methods.spam(1, 1n, false).send({ from: context.accounts[0], wait: NO_WAIT }); // Disable skipCollectingAttestations after the first L2 block is mined test.monitor.once('checkpoint', ({ checkpointNumber }) => { @@ -165,7 +167,7 @@ describe('e2e_epochs/epochs_invalidate_block', () => { ); // Verify the transaction was eventually included - const receipt = await sentTx.wait({ timeout: 30 }); + const receipt = await waitForTx(context.aztecNode, sentTx, { timeout: 30 }); expect(receipt.isMined()).toBeTrue(); logger.warn(`Transaction included in block ${receipt.blockNumber}`); diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_multiple_blocks_per_slot.test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_multiple_blocks_per_slot.test.ts index c244f21a6bd6..dc187e8f24b9 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_multiple_blocks_per_slot.test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_multiple_blocks_per_slot.test.ts @@ -1,8 +1,10 @@ import type { Archiver } from '@aztec/archiver'; import type { AztecNodeService } from '@aztec/aztec-node'; import { EthAddress } from '@aztec/aztec.js/addresses'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { Fr } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; +import { waitForTx } from '@aztec/aztec.js/node'; import { RollupContract } from '@aztec/ethereum/contracts'; import type { Operator } from '@aztec/ethereum/deploy-aztec-l1-contracts'; import { asyncMap } from '@aztec/foundation/async-map'; @@ -109,9 +111,9 @@ describe.skip('e2e_epochs/epochs_multiple_blocks_per_slot', () => { const txs = await timesAsync(TX_COUNT, i => proveInteraction(context.wallet, contract.methods.spam(i, 1n, false), { from: context.accounts[0] }), ); - const sentTxs = await Promise.all(txs.map(tx => tx.send())); - logger.warn(`Sent ${sentTxs.length} transactions`, { - txs: await Promise.all(sentTxs.map(tx => tx.getTxHash())), + const txHashes = await Promise.all(txs.map(tx => tx.send({ wait: NO_WAIT }))); + logger.warn(`Sent ${txHashes.length} transactions`, { + txs: txHashes, }); const sequencers = nodes.map(node => node.getSequencer()!); @@ -123,7 +125,10 @@ describe.skip('e2e_epochs/epochs_multiple_blocks_per_slot', () => { // Wait until all txs are mined with a generous timeout const timeout = test.L2_SLOT_DURATION_IN_S * (TX_COUNT + 4); - await executeTimeout(() => Promise.all(sentTxs.map(tx => tx.wait({ timeout }))), timeout * 1000); + await executeTimeout( + () => Promise.all(txHashes.map(txHash => waitForTx(context.aztecNode, txHash, { timeout }))), + timeout * 1000, + ); logger.warn(`All txs have been mined`); // Wait for at least one checkpoint to be mined @@ -198,9 +203,9 @@ describe.skip('e2e_epochs/epochs_multiple_blocks_per_slot', () => { const txs = await timesAsync(TX_COUNT, i => proveInteraction(context.wallet, contract.methods.spam(i + 100, 1n, false), { from: context.accounts[0] }), ); - const sentTxs = await Promise.all(txs.map(tx => tx.send())); - logger.warn(`Sent ${sentTxs.length} transactions`, { - txs: await Promise.all(sentTxs.map(tx => tx.getTxHash())), + const txHashes = await Promise.all(txs.map(tx => tx.send({ wait: NO_WAIT }))); + logger.warn(`Sent ${txHashes.length} transactions`, { + txs: txHashes, }); const sequencers = nodes.map(node => node.getSequencer()!); @@ -212,7 +217,10 @@ describe.skip('e2e_epochs/epochs_multiple_blocks_per_slot', () => { // Wait until all txs are mined const timeout = test.L2_SLOT_DURATION_IN_S * (TX_COUNT + 6); - await executeTimeout(() => Promise.all(sentTxs.map(tx => tx.wait({ timeout }))), timeout * 1000); + await executeTimeout( + () => Promise.all(txHashes.map(txHash => waitForTx(context.aztecNode, txHash, { timeout }))), + timeout * 1000, + ); logger.warn(`All txs have been mined`); // Wait for at least 2 checkpoints diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_proof_public_cross_chain.test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_proof_public_cross_chain.test.ts index 8a6bf7b76f0b..80bc26693e5e 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_proof_public_cross_chain.test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_proof_public_cross_chain.test.ts @@ -42,7 +42,7 @@ describe('e2e_epochs/epochs_proof_public_cross_chain', () => { // Deploy a contract that consumes L1 to L2 messages await context.aztecNodeAdmin!.setConfig({ minTxsPerBlock: 0 }); logger.warn(`Deploying test contract`); - const testContract = await TestContract.deploy(context.wallet).send({ from: context.accounts[0] }).deployed(); + const testContract = await TestContract.deploy(context.wallet).send({ from: context.accounts[0] }); logger.warn(`Test contract deployed at ${testContract.address}`); // Send an l1 to l2 message to be consumed from the contract @@ -67,8 +67,7 @@ describe('e2e_epochs/epochs_proof_public_cross_chain', () => { EthAddress.fromString(context.deployL1ContractsValues.l1Client.account.address), globalLeafIndex.toBigInt(), ) - .send({ from: context.accounts[0] }) - .wait(); + .send({ from: context.accounts[0] }); expect(txReceipt.blockNumber).toBeGreaterThan(0); // Wait until a proof lands for the transaction @@ -94,8 +93,7 @@ describe('e2e_epochs/epochs_proof_public_cross_chain', () => { EthAddress.fromString(context.deployL1ContractsValues.l1Client.account.address), globalLeafIndex.toBigInt(), ) - .send({ from: context.accounts[0] }) - .wait({ dontThrowOnRevert: true }); + .send({ from: context.accounts[0], wait: { dontThrowOnRevert: true } }); expect(failedReceipt.executionResult).toBe(TxExecutionResult.APP_LOGIC_REVERTED); logger.info(`Test succeeded`); diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_simple_block_building.test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_simple_block_building.test.ts index 2c2e8199e3b3..f77f680a52bb 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_simple_block_building.test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_simple_block_building.test.ts @@ -1,7 +1,9 @@ import type { AztecNodeService } from '@aztec/aztec-node'; import { EthAddress } from '@aztec/aztec.js/addresses'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { Fr } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; +import { waitForTx } from '@aztec/aztec.js/node'; import type { Operator } from '@aztec/ethereum/deploy-aztec-l1-contracts'; import { asyncMap } from '@aztec/foundation/async-map'; import { times, timesAsync } from '@aztec/foundation/collection'; @@ -80,9 +82,9 @@ describe('e2e_epochs/epochs_simple_block_building', () => { const txs = await timesAsync(TX_COUNT, i => proveInteraction(context.wallet, contract.methods.spam(i, 1n, false), { from: context.accounts[0] }), ); - const sentTxs = await Promise.all(txs.map(tx => tx.send())); - logger.warn(`Sent ${sentTxs.length} transactions`, { - txs: await Promise.all(sentTxs.map(tx => tx.getTxHash())), + const txHashes = await Promise.all(txs.map(tx => tx.send({ wait: NO_WAIT }))); + logger.warn(`Sent ${txHashes.length} transactions`, { + txs: txHashes, }); const sequencers = nodes.map(node => node.getSequencer()!); @@ -94,7 +96,10 @@ describe('e2e_epochs/epochs_simple_block_building', () => { // Wait until all txs are mined const timeout = test.L2_SLOT_DURATION_IN_S * (TX_COUNT * 2 + 1); - await executeTimeout(() => Promise.all(sentTxs.map(tx => tx.wait({ timeout }))), timeout * 1000); + await executeTimeout( + () => Promise.all(txHashes.map(txHash => waitForTx(context.aztecNode, txHash, { timeout }))), + timeout * 1000, + ); logger.warn(`All txs have been mined`); // Expect no failures from sequencers during block building. diff --git a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts index 72983eda5905..d9e23a13e4ef 100644 --- a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts @@ -41,11 +41,11 @@ describe('e2e_escrow_contract', () => { const escrowDeployment = EscrowContract.deployWithPublicKeys(escrowPublicKeys, wallet, owner); const escrowInstance = await escrowDeployment.getInstance(); await wallet.registerContract(escrowInstance, EscrowContract.artifact, escrowSecretKey); - escrowContract = await escrowDeployment.send({ from: owner }).deployed(); + escrowContract = await escrowDeployment.send({ from: owner }); logger.info(`Escrow contract deployed at ${escrowContract.address}`); // Deploy Token contract and mint funds for the escrow contract - token = await TokenContract.deploy(wallet, owner, 'TokenName', 'TokenSymbol', 18).send({ from: owner }).deployed(); + token = await TokenContract.deploy(wallet, owner, 'TokenName', 'TokenSymbol', 18).send({ from: owner }); await mintTokensToPrivate(token, owner, escrowContract.address, 100n); @@ -60,7 +60,7 @@ describe('e2e_escrow_contract', () => { await expectTokenBalance(wallet, token, escrowContract.address, 100n, logger); logger.info(`Withdrawing funds from token contract to ${recipient}`); - await escrowContract.methods.withdraw(token.address, 30, recipient).send({ from: owner }).wait(); + await escrowContract.methods.withdraw(token.address, 30, recipient).send({ from: owner }); await expectTokenBalance(wallet, token, owner, 0n, logger); await expectTokenBalance(wallet, token, recipient, 30n, logger); @@ -84,9 +84,7 @@ describe('e2e_escrow_contract', () => { await new BatchCall(wallet, [ token.methods.transfer(recipient, 10), escrowContract.methods.withdraw(token.address, 20, recipient), - ]) - .send({ from: owner }) - .wait(); + ]).send({ from: owner }); await expectTokenBalance(wallet, token, recipient, 30n, logger); }); }); diff --git a/yarn-project/end-to-end/src/e2e_event_logs.test.ts b/yarn-project/end-to-end/src/e2e_event_logs.test.ts index a2be82c97b67..5edd3dc01601 100644 --- a/yarn-project/end-to-end/src/e2e_event_logs.test.ts +++ b/yarn-project/end-to-end/src/e2e_event_logs.test.ts @@ -42,7 +42,7 @@ describe('Logs', () => { await ensureAccountContractsPublished(wallet, [account1Address, account2Address]); log.warn(`Deploying test contract`); - testLogContract = await TestLogContract.deploy(wallet).send({ from: account1Address }).deployed(); + testLogContract = await TestLogContract.deploy(wallet).send({ from: account1Address }); }); afterAll(() => teardown()); @@ -53,10 +53,7 @@ describe('Logs', () => { const txs = await Promise.all( preimages.map(preimage => - testLogContract.methods - .emit_encrypted_events(account2Address, preimage) - .send({ from: account1Address }) - .wait(), + testLogContract.methods.emit_encrypted_events(account2Address, preimage).send({ from: account1Address }), ), ); @@ -124,15 +121,13 @@ describe('Logs', () => { let i = 0; const firstTx = await testLogContract.methods .emit_unencrypted_events(preimage[i]) - .send({ from: account1Address }) - .wait(); + .send({ from: account1Address }); await timesParallel(3, () => - testLogContract.methods.emit_unencrypted_events(preimage[++i]).send({ from: account1Address }).wait(), + testLogContract.methods.emit_unencrypted_events(preimage[++i]).send({ from: account1Address }), ); const lastTx = await testLogContract.methods .emit_unencrypted_events(preimage[++i]) - .send({ from: account1Address }) - .wait(); + .send({ from: account1Address }); // docs:start:get_public_events const collectedEvent0s = await getDecodedPublicEvents( @@ -185,8 +180,7 @@ describe('Logs', () => { // Call the private function that emits two encrypted logs per call and recursively nests 4 times const tx = await testLogContract.methods .emit_encrypted_events_nested(account2Address, 4) - .send({ from: account1Address }) - .wait(); + .send({ from: account1Address }); // Fetch raw private logs for that block and check tag uniqueness const logs = (await aztecNode.getBlock(tx.blockNumber!))!.getPrivateLogs().filter(l => !l.isEmpty()); @@ -205,8 +199,7 @@ describe('Logs', () => { // Call the private function that emits two encrypted logs per call and recursively nests 2 times const tx = await testLogContract.methods .emit_encrypted_events_nested(account2Address, 2) - .send({ from: account1Address }) - .wait(); + .send({ from: account1Address }); const blockNumber = tx.blockNumber!; diff --git a/yarn-project/end-to-end/src/e2e_event_only.test.ts b/yarn-project/end-to-end/src/e2e_event_only.test.ts index d854d7874633..7dd0c3859451 100644 --- a/yarn-project/end-to-end/src/e2e_event_only.test.ts +++ b/yarn-project/end-to-end/src/e2e_event_only.test.ts @@ -26,17 +26,14 @@ describe('EventOnly', () => { accounts: [defaultAccountAddress], } = await setup(1)); await ensureAccountContractsPublished(wallet, [defaultAccountAddress]); - eventOnlyContract = await EventOnlyContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + eventOnlyContract = await EventOnlyContract.deploy(wallet).send({ from: defaultAccountAddress }); }); afterAll(() => teardown()); it('emits and retrieves a private event for a contract with no notes', async () => { const value = Fr.random(); - const tx = await eventOnlyContract.methods - .emit_event_for_msg_sender(value) - .send({ from: defaultAccountAddress }) - .wait(); + const tx = await eventOnlyContract.methods.emit_event_for_msg_sender(value).send({ from: defaultAccountAddress }); const events = await wallet.getPrivateEvents(EventOnlyContract.events.TestEvent, { contractAddress: eventOnlyContract.address, diff --git a/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts b/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts index 8d3bcdc8bd5d..5a332dd6a15b 100644 --- a/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts @@ -89,7 +89,7 @@ describe('e2e_fees account_init', () => { const [bobsInitialGas] = await t.getGasBalanceFn(bobsAddress); expect(bobsInitialGas).toEqual(mintAmount); - const tx = await bobsDeployMethod.send({ from: AztecAddress.ZERO }).wait(); + const tx = await bobsDeployMethod.send({ from: AztecAddress.ZERO, wait: { returnReceipt: true } }); expect(tx.transactionFee!).toBeGreaterThan(0n); await expect(t.getGasBalanceFn(bobsAddress)).resolves.toEqual([bobsInitialGas - tx.transactionFee!]); @@ -98,7 +98,11 @@ describe('e2e_fees account_init', () => { it('pays natively in the Fee Juice by bridging funds themselves', async () => { const claim = await t.feeJuiceBridgeTestHarness.prepareTokensOnL1(bobsAddress); const paymentMethod = new FeeJuicePaymentMethodWithClaim(bobsAddress, claim); - const tx = await bobsDeployMethod.send({ from: AztecAddress.ZERO, fee: { paymentMethod } }).wait(); + const tx = await bobsDeployMethod.send({ + from: AztecAddress.ZERO, + fee: { paymentMethod }, + wait: { returnReceipt: true }, + }); expect(tx.transactionFee!).toBeGreaterThan(0n); await expect(t.getGasBalanceFn(bobsAddress)).resolves.toEqual([claim.claimAmount - tx.transactionFee!]); }); @@ -114,7 +118,11 @@ describe('e2e_fees account_init', () => { const maxFeesPerGas = (await aztecNode.getCurrentMinFees()).mul(1.5); const gasSettings = GasSettings.default({ maxFeesPerGas }); const paymentMethod = new PrivateFeePaymentMethod(bananaFPC.address, bobsAddress, wallet, gasSettings); - const tx = await bobsDeployMethod.send({ from: AztecAddress.ZERO, fee: { paymentMethod } }).wait(); + const tx = await bobsDeployMethod.send({ + from: AztecAddress.ZERO, + fee: { paymentMethod }, + wait: { returnReceipt: true }, + }); const actualFee = tx.transactionFee!; expect(actualFee).toBeGreaterThan(0n); @@ -132,20 +140,19 @@ describe('e2e_fees account_init', () => { it('pays publicly through an FPC', async () => { const mintedBananas = await t.feeJuiceBridgeTestHarness.l1TokenManager.getMintAmount(); - await bananaCoin.methods.mint_to_public(bobsAddress, mintedBananas).send({ from: aliceAddress }).wait(); + await bananaCoin.methods.mint_to_public(bobsAddress, mintedBananas).send({ from: aliceAddress }); // The public fee paying method assembled on the app side requires knowledge of the maximum // fee the user is willing to pay const maxFeesPerGas = (await aztecNode.getCurrentMinFees()).mul(1.5); const gasSettings = GasSettings.default({ maxFeesPerGas }); const paymentMethod = new PublicFeePaymentMethod(bananaFPC.address, bobsAddress, wallet, gasSettings); - const tx = await bobsDeployMethod - .send({ - from: AztecAddress.ZERO, - skipInstancePublication: false, - fee: { paymentMethod }, - }) - .wait(); + const tx = await bobsDeployMethod.send({ + from: AztecAddress.ZERO, + skipInstancePublication: false, + fee: { paymentMethod }, + wait: { returnReceipt: true }, + }); const actualFee = tx.transactionFee!; expect(actualFee).toBeGreaterThan(0n); @@ -178,16 +185,15 @@ describe('e2e_fees account_init', () => { wallet, bobsSigningPubKey.x, bobsSigningPubKey.y, - ) - .send({ - from: aliceAddress, - contractAddressSalt: bobsInstance.salt, - skipClassPublication: true, - skipInstancePublication: true, - skipInitialization: false, - universalDeploy: true, - }) - .wait(); + ).send({ + from: aliceAddress, + contractAddressSalt: bobsInstance.salt, + skipClassPublication: true, + skipInstancePublication: true, + skipInitialization: false, + universalDeploy: true, + wait: { returnReceipt: true }, + }); // alice paid in Fee Juice expect(tx.transactionFee!).toBeGreaterThan(0n); @@ -200,8 +206,7 @@ describe('e2e_fees account_init', () => { const bobPaymentMethod = new PrivateFeePaymentMethod(bananaFPC.address, bobsAddress, wallet, gasSettings); await bananaCoin.methods .transfer_in_public(bobsAddress, aliceAddress, 0n, 0n) - .send({ from: bobsAddress, fee: { paymentMethod: bobPaymentMethod } }) - .wait(); + .send({ from: bobsAddress, fee: { paymentMethod: bobPaymentMethod } }); }); }); }); diff --git a/yarn-project/end-to-end/src/e2e_fees/bridging_race.notest.ts b/yarn-project/end-to-end/src/e2e_fees/bridging_race.notest.ts index f428299df58f..e1dbcd8b6ee9 100644 --- a/yarn-project/end-to-end/src/e2e_fees/bridging_race.notest.ts +++ b/yarn-project/end-to-end/src/e2e_fees/bridging_race.notest.ts @@ -67,10 +67,7 @@ describe('e2e_fees bridging_race', () => { // Yes, we need to REFACTOR it at some point const claim = await t.feeJuiceBridgeTestHarness.prepareTokensOnL1(bobsAddress); const { claimSecret: secret, messageLeafIndex: index } = claim; - await t.feeJuiceContract.methods - .claim(bobsAddress, claim.claimAmount, secret, index) - .send({ from: bobsAddress }) - .wait(); + await t.feeJuiceContract.methods.claim(bobsAddress, claim.claimAmount, secret, index).send({ from: bobsAddress }); const [balance] = await t.getGasBalanceFn(bobsAddress); expect(balance).toEqual(claim.claimAmount); }); diff --git a/yarn-project/end-to-end/src/e2e_fees/failures.test.ts b/yarn-project/end-to-end/src/e2e_fees/failures.test.ts index 9a6062a57989..7b58234b9ba7 100644 --- a/yarn-project/end-to-end/src/e2e_fees/failures.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/failures.test.ts @@ -91,8 +91,8 @@ describe('e2e_fees failures', () => { fee: { paymentMethod: new PrivateFeePaymentMethod(bananaFPC.address, aliceAddress, wallet, gasSettings), }, - }) - .wait({ dontThrowOnRevert: true }); + wait: { dontThrowOnRevert: true }, + }); expect(txReceipt.executionResult).toBe(TxExecutionResult.APP_LOGIC_REVERTED); @@ -149,10 +149,7 @@ describe('e2e_fees failures', () => { bananaFPC.address, ); - await bananaCoin.methods - .mint_to_public(aliceAddress, publicMintedAlicePublicBananas) - .send({ from: aliceAddress }) - .wait(); + await bananaCoin.methods.mint_to_public(aliceAddress, publicMintedAlicePublicBananas).send({ from: aliceAddress }); const [initialAliceGas, initialFPCGas, initialSequencerGas] = await t.getGasBalanceFn( aliceAddress, @@ -197,8 +194,8 @@ describe('e2e_fees failures', () => { fee: { paymentMethod: new PublicFeePaymentMethod(bananaFPC.address, aliceAddress, wallet, gasSettings), }, - }) - .wait({ dontThrowOnRevert: true }); + wait: { dontThrowOnRevert: true }, + }); expect(txReceipt.executionResult).toBe(TxExecutionResult.APP_LOGIC_REVERTED); const feeAmount = txReceipt.transactionFee!; @@ -245,8 +242,7 @@ describe('e2e_fees failures', () => { fee: { paymentMethod: new BuggedSetupFeePaymentMethod(bananaFPC.address, aliceAddress, wallet, gasSettings), }, - }) - .wait(), + }), ).rejects.toThrow(/Transaction (0x)?[0-9a-fA-F]{64} was dropped/i); }); @@ -265,10 +261,7 @@ describe('e2e_fees failures', () => { bananaFPC.address, ); - await bananaCoin.methods - .mint_to_public(aliceAddress, publicMintedAlicePublicBananas) - .send({ from: aliceAddress }) - .wait(); + await bananaCoin.methods.mint_to_public(aliceAddress, publicMintedAlicePublicBananas).send({ from: aliceAddress }); const [initialAliceGas, initialFPCGas, initialSequencerGas] = await t.getGasBalanceFn( aliceAddress, @@ -299,9 +292,7 @@ describe('e2e_fees failures', () => { fee: { paymentMethod: new PublicFeePaymentMethod(bananaFPC.address, aliceAddress, wallet, badGas), }, - }) - .wait({ - dontThrowOnRevert: true, + wait: { dontThrowOnRevert: true }, }); expect(receipt.executionResult).toEqual(TxExecutionResult.TEARDOWN_REVERTED); expect(receipt.transactionFee).toBeGreaterThan(0n); diff --git a/yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts b/yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts index c61800251abe..f9f46a757ace 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts @@ -33,7 +33,7 @@ describe('e2e_fees Fee Juice payments', () => { // Alice pays for Bob's account contract deployment. const bobsDeployMethod = await bobsAccountManager.getDeployMethod(); - await bobsDeployMethod.send({ from: aliceAddress }).wait(); + await bobsDeployMethod.send({ from: aliceAddress }); bobAddress = bobsAccountManager.address; }); @@ -56,7 +56,7 @@ describe('e2e_fees Fee Juice payments', () => { it('fails to send a tx', async () => { await expect( - feeJuiceContract.methods.check_balance(0n).send({ from: bobAddress, fee: { gasSettings } }).wait(), + feeJuiceContract.methods.check_balance(0n).send({ from: bobAddress, fee: { gasSettings } }), ).rejects.toThrow(/Invalid tx: Insufficient fee payer balance/i); }); @@ -65,8 +65,7 @@ describe('e2e_fees Fee Juice payments', () => { const paymentMethod = new FeeJuicePaymentMethodWithClaim(bobAddress, claim); const receipt = await feeJuiceContract.methods .check_balance(0n) - .send({ from: bobAddress, fee: { gasSettings, paymentMethod } }) - .wait(); + .send({ from: bobAddress, fee: { gasSettings, paymentMethod } }); const endBalance = await feeJuiceContract.methods.balance_of_public(bobAddress).simulate({ from: bobAddress }); expect(endBalance).toBeGreaterThan(0n); @@ -82,8 +81,7 @@ describe('e2e_fees Fee Juice payments', () => { .simulate({ from: aliceAddress }); const { transactionFee } = await bananaCoin.methods .transfer_in_public(aliceAddress, bobAddress, 1n, 0n) - .send({ fee: { gasSettings }, from: aliceAddress }) - .wait(); + .send({ fee: { gasSettings }, from: aliceAddress }); expect(transactionFee).toBeGreaterThan(0n); const endBalance = await feeJuiceContract.methods .balance_of_public(aliceAddress) @@ -97,8 +95,7 @@ describe('e2e_fees Fee Juice payments', () => { .simulate({ from: aliceAddress }); const { transactionFee } = await bananaCoin.methods .transfer(bobAddress, 1n) - .send({ fee: { gasSettings }, from: aliceAddress }) - .wait(); + .send({ fee: { gasSettings }, from: aliceAddress }); expect(transactionFee).toBeGreaterThan(0n); const endBalance = await feeJuiceContract.methods .balance_of_public(aliceAddress) diff --git a/yarn-project/end-to-end/src/e2e_fees/fee_settings.test.ts b/yarn-project/end-to-end/src/e2e_fees/fee_settings.test.ts index a9782ee09a73..b4612ae0c3ca 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fee_settings.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fee_settings.test.ts @@ -26,7 +26,7 @@ describe('e2e_fees fee settings', () => { await t.setup(); ({ aliceAddress, wallet, gasSettings, cheatCodes, aztecNode } = t); - testContract = await TestContract.deploy(wallet).send({ from: aliceAddress }).deployed(); + testContract = await TestContract.deploy(wallet).send({ from: aliceAddress }); gasSettings = { ...gasSettings, maxFeesPerGas: undefined }; }); @@ -62,7 +62,7 @@ describe('e2e_fees fee settings', () => { fee: { gasSettings }, }); const { maxFeesPerGas } = tx.data.constants.txContext.gasSettings; - t.logger.info(`Tx with hash ${tx.getTxHash().toString()} ready with max fees ${inspect(maxFeesPerGas)}`); + t.logger.info(`Tx with hash ${tx.txHash.toString()} ready with max fees ${inspect(maxFeesPerGas)}`); return tx; }; @@ -76,11 +76,8 @@ describe('e2e_fees fee settings', () => { // And check that the no-padding does not get mined, but the default padding is good enough t.logger.info(`Sendings txs`); - const sentWithNoPadding = txWithNoPadding.send(); - const sentWithDefaultPadding = txWithDefaultPadding.send(); - t.logger.info(`Awaiting txs`); - await expect(sentWithNoPadding.wait({ timeout: 30 })).rejects.toThrow(TX_ERROR_INSUFFICIENT_FEE_PER_GAS); - await sentWithDefaultPadding.wait({ timeout: 30 }); + await expect(txWithNoPadding.send()).rejects.toThrow(TX_ERROR_INSUFFICIENT_FEE_PER_GAS); + await expect(txWithDefaultPadding.send()).resolves.toBeDefined(); }); }); }); diff --git a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts index 852a61c89040..835e8e828e47 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts @@ -152,10 +152,7 @@ export class FeesTest { async mintAndBridgeFeeJuice(minter: AztecAddress, recipient: AztecAddress) { const claim = await this.feeJuiceBridgeTestHarness.prepareTokensOnL1(recipient); const { claimSecret: secret, messageLeafIndex: index } = claim; - await this.feeJuiceContract.methods - .claim(recipient, claim.claimAmount, secret, index) - .send({ from: minter }) - .wait(); + await this.feeJuiceContract.methods.claim(recipient, claim.claimAmount, secret, index).send({ from: minter }); } /** Alice mints bananaCoin tokens privately to the target address and redeems them. */ @@ -235,9 +232,9 @@ export class FeesTest { async applyDeployBananaToken() { this.logger.info('Applying deploy banana token setup'); - const bananaCoin = await BananaCoin.deploy(this.wallet, this.aliceAddress, 'BC', 'BC', 18n) - .send({ from: this.aliceAddress }) - .deployed(); + const bananaCoin = await BananaCoin.deploy(this.wallet, this.aliceAddress, 'BC', 'BC', 18n).send({ + from: this.aliceAddress, + }); this.logger.info(`BananaCoin deployed at ${bananaCoin.address}`); this.bananaCoin = bananaCoin; @@ -262,9 +259,9 @@ export class FeesTest { expect((await this.wallet.getContractMetadata(feeJuiceContract.address)).isContractPublished).toBe(true); const bananaCoin = this.bananaCoin; - const bananaFPC = await FPCContract.deploy(this.wallet, bananaCoin.address, this.fpcAdmin) - .send({ from: this.aliceAddress }) - .deployed(); + const bananaFPC = await FPCContract.deploy(this.wallet, bananaCoin.address, this.fpcAdmin).send({ + from: this.aliceAddress, + }); this.logger.info(`BananaPay deployed at ${bananaFPC.address}`); @@ -331,8 +328,7 @@ export class FeesTest { await this.mintPrivateBananas(this.ALICE_INITIAL_BANANAS, this.aliceAddress); await this.bananaCoin.methods .mint_to_public(this.aliceAddress, this.ALICE_INITIAL_BANANAS) - .send({ from: this.aliceAddress }) - .wait(); + .send({ from: this.aliceAddress }); } public async applyFundAliceWithPrivateBananas() { diff --git a/yarn-project/end-to-end/src/e2e_fees/gas_estimation.test.ts b/yarn-project/end-to-end/src/e2e_fees/gas_estimation.test.ts index b6f42029553b..3e7c3cc764a1 100644 --- a/yarn-project/end-to-end/src/e2e_fees/gas_estimation.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/gas_estimation.test.ts @@ -1,5 +1,5 @@ import type { AztecAddress } from '@aztec/aztec.js/addresses'; -import type { DeployOptions } from '@aztec/aztec.js/contracts'; +import type { DeployTxReceipt } from '@aztec/aztec.js/contracts'; import { type FeePaymentMethod, PublicFeePaymentMethod } from '@aztec/aztec.js/fee'; import type { AztecNode } from '@aztec/aztec.js/node'; import type { Wallet } from '@aztec/aztec.js/wallet'; @@ -60,7 +60,7 @@ describe('e2e_fees gas_estimation', () => { ) => Promise.all( [GasSettings.from({ ...gasSettings, ...limits }), gasSettings].map(gasSettings => - makeTransferRequest().send({ from: aliceAddress, fee: { gasSettings, paymentMethod } }).wait(), + makeTransferRequest().send({ from: aliceAddress, fee: { gasSettings, paymentMethod } }), ), ); @@ -140,13 +140,18 @@ describe('e2e_fees gas_estimation', () => { it('estimates gas for public contract initialization with Fee Juice payment method', async () => { const deployMethod = () => BananaCoin.deploy(wallet, aliceAddress, 'TKN', 'TKN', 8); - const deployOpts: (limits?: Pick) => DeployOptions = limits => ({ + const deployOpts = (limits?: Pick) => { + return { + from: aliceAddress, + fee: { gasSettings: limits ? { ...gasSettings, ...limits } : gasSettings }, + skipClassPublication: true, + wait: { returnReceipt: true }, + }; + }; + + const { estimatedGas } = await deployMethod().simulate({ from: aliceAddress, - fee: { gasSettings: { ...gasSettings, ...limits } }, skipClassPublication: true, - }); - const { estimatedGas } = await deployMethod().simulate({ - ...deployOpts(), fee: { estimateGas: true, estimatedGasPadding: 0, @@ -154,10 +159,10 @@ describe('e2e_fees gas_estimation', () => { }); logGasEstimate(estimatedGas); - const [withEstimate, withoutEstimate] = await Promise.all([ - deployMethod().send(deployOpts(estimatedGas)).wait(), - deployMethod().send(deployOpts()).wait(), - ]); + const [withEstimate, withoutEstimate] = (await Promise.all([ + deployMethod().send(deployOpts(estimatedGas)), + deployMethod().send(deployOpts()), + ])) as unknown as DeployTxReceipt[]; // Estimation should yield that teardown has no cost, so should send the tx with zero for teardown expect(withEstimate.transactionFee!).toEqual(withoutEstimate.transactionFee!); diff --git a/yarn-project/end-to-end/src/e2e_fees/private_payments.test.ts b/yarn-project/end-to-end/src/e2e_fees/private_payments.test.ts index 879f5360d38b..f579eb0a8404 100644 --- a/yarn-project/end-to-end/src/e2e_fees/private_payments.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/private_payments.test.ts @@ -107,11 +107,9 @@ describe('e2e_fees private_payment', () => { const sequencerRewardsBefore = await t.getCoinbaseSequencerRewards(); const { sequencerBlockRewards } = await t.getBlockRewards(); - const tx = localTx.send(); - await tx.wait({ timeout: 300, interval: 10 }); + const receipt = await localTx.send({ timeout: 300, interval: 10 }); await t.cheatCodes.rollup.advanceToNextEpoch(); - const receipt = await tx.wait({ timeout: 300, interval: 10 }); await waitForProven(aztecNode, receipt, { provenTimeout: 300 }); // @note There is a potential race condition here if other tests send transactions that get into the same @@ -157,15 +155,12 @@ describe('e2e_fees private_payment', () => { * increase Alice's private banana balance by feeAmount by finalizing partial note */ const newlyMintedBananas = 10n; - const tx = await bananaCoin.methods - .mint_to_private(aliceAddress, newlyMintedBananas) - .send({ - from: aliceAddress, - fee: { - paymentMethod: new PrivateFeePaymentMethod(bananaFPC.address, aliceAddress, wallet, gasSettings), - }, - }) - .wait(); + const tx = await bananaCoin.methods.mint_to_private(aliceAddress, newlyMintedBananas).send({ + from: aliceAddress, + fee: { + paymentMethod: new PrivateFeePaymentMethod(bananaFPC.address, aliceAddress, wallet, gasSettings), + }, + }); const feeAmount = tx.transactionFee!; @@ -205,15 +200,12 @@ describe('e2e_fees private_payment', () => { * increase Alice's private banana balance by feeAmount by finalizing partial note */ const amountTransferredToPrivate = 1n; - const tx = await bananaCoin.methods - .transfer_to_private(aliceAddress, amountTransferredToPrivate) - .send({ - from: aliceAddress, - fee: { - paymentMethod: new PrivateFeePaymentMethod(bananaFPC.address, aliceAddress, wallet, gasSettings), - }, - }) - .wait(); + const tx = await bananaCoin.methods.transfer_to_private(aliceAddress, amountTransferredToPrivate).send({ + from: aliceAddress, + fee: { + paymentMethod: new PrivateFeePaymentMethod(bananaFPC.address, aliceAddress, wallet, gasSettings), + }, + }); const feeAmount = tx.transactionFee!; @@ -260,14 +252,12 @@ describe('e2e_fees private_payment', () => { const tx = await new BatchCall(wallet, [ bananaCoin.methods.transfer(bobAddress, amountTransferredInPrivate), bananaCoin.methods.transfer_to_private(aliceAddress, amountTransferredToPrivate), - ]) - .send({ - from: aliceAddress, - fee: { - paymentMethod: new PrivateFeePaymentMethod(bananaFPC.address, aliceAddress, wallet, gasSettings), - }, - }) - .wait(); + ]).send({ + from: aliceAddress, + fee: { + paymentMethod: new PrivateFeePaymentMethod(bananaFPC.address, aliceAddress, wallet, gasSettings), + }, + }); const feeAmount = tx.transactionFee!; @@ -293,22 +283,19 @@ describe('e2e_fees private_payment', () => { it('rejects txs that dont have enough balance to cover gas costs', async () => { // deploy a copy of bananaFPC but don't fund it! - const bankruptFPC = await FPCContract.deploy(wallet, bananaCoin.address, aliceAddress) - .send({ from: aliceAddress }) - .deployed(); + const bankruptFPC = await FPCContract.deploy(wallet, bananaCoin.address, aliceAddress).send({ + from: aliceAddress, + }); await expectMapping(t.getGasBalanceFn, [bankruptFPC.address], [0n]); await expect( - bananaCoin.methods - .mint_to_private(aliceAddress, 10) - .send({ - from: aliceAddress, - fee: { - paymentMethod: new PrivateFeePaymentMethod(bankruptFPC.address, aliceAddress, wallet, gasSettings), - }, - }) - .wait(), + bananaCoin.methods.mint_to_private(aliceAddress, 10).send({ + from: aliceAddress, + fee: { + paymentMethod: new PrivateFeePaymentMethod(bankruptFPC.address, aliceAddress, wallet, gasSettings), + }, + }), ).rejects.toThrow(TX_ERROR_INSUFFICIENT_FEE_PAYER_BALANCE); }); diff --git a/yarn-project/end-to-end/src/e2e_fees/public_payments.test.ts b/yarn-project/end-to-end/src/e2e_fees/public_payments.test.ts index a9a7dddd5f39..51e9109a90dc 100644 --- a/yarn-project/end-to-end/src/e2e_fees/public_payments.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/public_payments.test.ts @@ -59,15 +59,12 @@ describe('e2e_fees public_payment', () => { it('pays fees for tx that make public transfer', async () => { const bananasToSendToBob = 10n; - const tx = await bananaCoin.methods - .transfer_in_public(aliceAddress, bobAddress, bananasToSendToBob, 0) - .send({ - from: aliceAddress, - fee: { - paymentMethod: new PublicFeePaymentMethod(bananaFPC.address, aliceAddress, wallet, gasSettings), - }, - }) - .wait(); + const tx = await bananaCoin.methods.transfer_in_public(aliceAddress, bobAddress, bananasToSendToBob, 0).send({ + from: aliceAddress, + fee: { + paymentMethod: new PublicFeePaymentMethod(bananaFPC.address, aliceAddress, wallet, gasSettings), + }, + }); const feeAmount = tx.transactionFee!; diff --git a/yarn-project/end-to-end/src/e2e_fees/sponsored_payments.test.ts b/yarn-project/end-to-end/src/e2e_fees/sponsored_payments.test.ts index 36c12f13a426..aac9aaa557ee 100644 --- a/yarn-project/end-to-end/src/e2e_fees/sponsored_payments.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/sponsored_payments.test.ts @@ -56,16 +56,13 @@ describe('e2e_fees sponsored_public_payment', () => { it('pays fees for tx that makes a public transfer', async () => { // docs:start:sponsored_fpc_simple const bananasToSendToBob = 10n; - const tx = await bananaCoin.methods - .transfer_in_public(aliceAddress, bobAddress, bananasToSendToBob, 0) - .send({ - from: aliceAddress, - fee: { - gasSettings, - paymentMethod: new SponsoredFeePaymentMethod(sponsoredFPC.address), - }, - }) - .wait(); + const tx = await bananaCoin.methods.transfer_in_public(aliceAddress, bobAddress, bananasToSendToBob, 0).send({ + from: aliceAddress, + fee: { + gasSettings, + paymentMethod: new SponsoredFeePaymentMethod(sponsoredFPC.address), + }, + }); // docs:end:sponsored_fpc_simple const feeAmount = tx.transactionFee!; diff --git a/yarn-project/end-to-end/src/e2e_include_by_timestamp.test.ts b/yarn-project/end-to-end/src/e2e_include_by_timestamp.test.ts index 2175bd18b219..a08878a4197f 100644 --- a/yarn-project/end-to-end/src/e2e_include_by_timestamp.test.ts +++ b/yarn-project/end-to-end/src/e2e_include_by_timestamp.test.ts @@ -25,7 +25,7 @@ describe('e2e_include_by_timestamp', () => { aztecNode, accounts: [defaultAccountAddress], } = await setup()); - contract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + contract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }); }); afterAll(() => teardown()); @@ -59,8 +59,7 @@ describe('e2e_include_by_timestamp', () => { it('does not invalidate the transaction', async () => { await contract.methods .set_include_by_timestamp(includeByTimestamp, enqueuePublicCall) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); }); }); @@ -79,8 +78,7 @@ describe('e2e_include_by_timestamp', () => { it('does not invalidate the transaction', async () => { await contract.methods .set_include_by_timestamp(includeByTimestamp, enqueuePublicCall) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); }); }); }); @@ -113,8 +111,7 @@ describe('e2e_include_by_timestamp', () => { await expect( contract.methods .set_include_by_timestamp(includeByTimestamp, enqueuePublicCall) - .send({ from: defaultAccountAddress }) - .wait(), + .send({ from: defaultAccountAddress }), ).rejects.toThrow(TX_ERROR_INVALID_INCLUDE_BY_TIMESTAMP); }); }); @@ -135,8 +132,7 @@ describe('e2e_include_by_timestamp', () => { await expect( contract.methods .set_include_by_timestamp(includeByTimestamp, enqueuePublicCall) - .send({ from: defaultAccountAddress }) - .wait(), + .send({ from: defaultAccountAddress }), ).rejects.toThrow(TX_ERROR_INVALID_INCLUDE_BY_TIMESTAMP); }); }); @@ -161,8 +157,7 @@ describe('e2e_include_by_timestamp', () => { await expect( contract.methods .set_include_by_timestamp(includeByTimestamp, enqueuePublicCall) - .send({ from: defaultAccountAddress }) - .wait(), + .send({ from: defaultAccountAddress }), ).rejects.toThrow(); }); }); @@ -174,8 +169,7 @@ describe('e2e_include_by_timestamp', () => { await expect( contract.methods .set_include_by_timestamp(includeByTimestamp, enqueuePublicCall) - .send({ from: defaultAccountAddress }) - .wait(), + .send({ from: defaultAccountAddress }), ).rejects.toThrow(); }); }); diff --git a/yarn-project/end-to-end/src/e2e_kernelless_simulation.test.ts b/yarn-project/end-to-end/src/e2e_kernelless_simulation.test.ts index df6213f47344..fa38d1166c68 100644 --- a/yarn-project/end-to-end/src/e2e_kernelless_simulation.test.ts +++ b/yarn-project/end-to-end/src/e2e_kernelless_simulation.test.ts @@ -49,11 +49,11 @@ describe('Kernelless simulation', () => { ({ contract: token1 } = await deployToken(wallet, adminAddress, 0n, logger)); ({ contract: liquidityToken } = await deployToken(wallet, adminAddress, 0n, logger)); - amm = await AMMContract.deploy(wallet, token0.address, token1.address, liquidityToken.address) - .send({ from: adminAddress }) - .deployed(); + amm = await AMMContract.deploy(wallet, token0.address, token1.address, liquidityToken.address).send({ + from: adminAddress, + }); - await liquidityToken.methods.set_minter(amm.address, true).send({ from: adminAddress }).wait(); + await liquidityToken.methods.set_minter(amm.address, true).send({ from: adminAddress }); // We mint the tokens to the liquidity provider await mintTokensToPrivate(token0, adminAddress, liquidityProviderAddress, INITIAL_TOKEN_BALANCE); @@ -86,9 +86,8 @@ describe('Kernelless simulation', () => { const nonceForAuthwits = Fr.random(); // This interaction requires 2 authwitnesses, one for each token so they can be transferred from the provider's - // private balance to the AMM's public balance. Using the copycat wallet, we collect the request hashes + // private balance to the AMM's public balance. Using the stub account, we collect the request hashes // for later comparison - const addLiquidityInteraction = amm.methods.add_liquidity( amount0Max, amount1Max, diff --git a/yarn-project/end-to-end/src/e2e_keys.test.ts b/yarn-project/end-to-end/src/e2e_keys.test.ts index 8d1314f56cb3..b06b1d535a5d 100644 --- a/yarn-project/end-to-end/src/e2e_keys.test.ts +++ b/yarn-project/end-to-end/src/e2e_keys.test.ts @@ -45,7 +45,7 @@ describe('Keys', () => { initialFundedAccounts, } = await setup(1)); - testContract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + testContract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }); secret = initialFundedAccounts[0].secret; }); @@ -77,15 +77,13 @@ describe('Keys', () => { await testContract.methods .call_create_note(noteValue, defaultAccountAddress, noteStorageSlot, false) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); expect(await getNumNullifiedNotes(nskApp, testContract.address)).toEqual(0); await testContract.methods .call_destroy_note(defaultAccountAddress, noteStorageSlot) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); expect(await getNumNullifiedNotes(nskApp, testContract.address)).toEqual(1); }); diff --git a/yarn-project/end-to-end/src/e2e_l1_with_wall_time.test.ts b/yarn-project/end-to-end/src/e2e_l1_with_wall_time.test.ts index c2251d546bf7..a1c5bef41c6a 100644 --- a/yarn-project/end-to-end/src/e2e_l1_with_wall_time.test.ts +++ b/yarn-project/end-to-end/src/e2e_l1_with_wall_time.test.ts @@ -1,6 +1,7 @@ import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses'; import { Fr } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; +import { type AztecNode, waitForTx } from '@aztec/aztec.js/node'; import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config'; import { SecretValue } from '@aztec/foundation/config'; import type { TestWallet } from '@aztec/test-wallet/server'; @@ -17,6 +18,7 @@ describe('e2e_l1_with_wall_time', () => { let logger: Logger; let teardown: () => Promise; let wallet: TestWallet; + let aztecNode: AztecNode; let defaultAccountAddress: AztecAddress; const deploymentsPerBlock = 8; @@ -39,6 +41,7 @@ describe('e2e_l1_with_wall_time', () => { teardown, logger, wallet, + aztecNode, accounts: [defaultAccountAddress], } = await setup(1, { initialValidators, @@ -50,11 +53,11 @@ describe('e2e_l1_with_wall_time', () => { it('should produce blocks with a bunch of transactions', async () => { for (let i = 0; i < numberOfBlocks; i++) { - const txs = await submitTxsTo(wallet, defaultAccountAddress, deploymentsPerBlock, logger); + const txHashes = await submitTxsTo(wallet, defaultAccountAddress, deploymentsPerBlock, logger); await Promise.all( - txs.map(async (tx, j) => { - logger.info(`Waiting for tx ${i}-${j}: ${(await tx.getTxHash()).toString()} to be mined`); - return tx.wait(); + txHashes.map((hash, j) => { + logger.info(`Waiting for tx ${i}-${j}: ${hash.toString()} to be mined`); + return waitForTx(aztecNode, hash); }), ); } diff --git a/yarn-project/end-to-end/src/e2e_lending_contract.test.ts b/yarn-project/end-to-end/src/e2e_lending_contract.test.ts index bd7bd05c14a8..9ec3a536e728 100644 --- a/yarn-project/end-to-end/src/e2e_lending_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_lending_contract.test.ts @@ -39,30 +39,31 @@ describe('e2e_lending_contract', () => { const deployContracts = async () => { logger.info(`Deploying price feed contract...`); - const priceFeedContract = await PriceFeedContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + const priceFeedContract = await PriceFeedContract.deploy(wallet).send({ from: defaultAccountAddress }); logger.info(`Price feed deployed to ${priceFeedContract.address}`); logger.info(`Deploying collateral asset feed contract...`); - const collateralAsset = await TokenContract.deploy(wallet, defaultAccountAddress, 'TokenName', 'TokenSymbol', 18) - .send({ from: defaultAccountAddress }) - .deployed(); + const collateralAsset = await TokenContract.deploy( + wallet, + defaultAccountAddress, + 'TokenName', + 'TokenSymbol', + 18, + ).send({ from: defaultAccountAddress }); logger.info(`Collateral asset deployed to ${collateralAsset.address}`); logger.info(`Deploying stable coin contract...`); - const stableCoin = await TokenContract.deploy(wallet, defaultAccountAddress, 'TokenName', 'TokenSymbol', 18) - .send({ from: defaultAccountAddress }) - .deployed(); + const stableCoin = await TokenContract.deploy(wallet, defaultAccountAddress, 'TokenName', 'TokenSymbol', 18).send({ + from: defaultAccountAddress, + }); logger.info(`Stable coin asset deployed to ${stableCoin.address}`); logger.info(`Deploying L2 public contract...`); - const lendingContract = await LendingContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + const lendingContract = await LendingContract.deploy(wallet).send({ from: defaultAccountAddress }); logger.info(`CDP deployed at ${lendingContract.address}`); - await collateralAsset.methods - .set_minter(lendingContract.address, true) - .send({ from: defaultAccountAddress }) - .wait(); - await stableCoin.methods.set_minter(lendingContract.address, true).send({ from: defaultAccountAddress }).wait(); + await collateralAsset.methods.set_minter(lendingContract.address, true).send({ from: defaultAccountAddress }); + await stableCoin.methods.set_minter(lendingContract.address, true).send({ from: defaultAccountAddress }); return { priceFeedContract, lendingContract, collateralAsset, stableCoin }; }; @@ -115,17 +116,14 @@ describe('e2e_lending_contract', () => { }); it('Mint assets for later usage', async () => { - await priceFeedContract.methods - .set_price(0n, 2n * 10n ** 9n) - .send({ from: defaultAccountAddress }) - .wait(); + await priceFeedContract.methods.set_price(0n, 2n * 10n ** 9n).send({ from: defaultAccountAddress }); { const assets = [collateralAsset, stableCoin]; const mintAmount = 10000n; for (const asset of assets) { await Promise.all([ - asset.methods.mint_to_public(lendingAccount.address, mintAmount).send({ from: defaultAccountAddress }).wait(), + asset.methods.mint_to_public(lendingAccount.address, mintAmount).send({ from: defaultAccountAddress }), mintTokensToPrivate(asset, defaultAccountAddress, lendingAccount.address, mintAmount), ]); } @@ -143,8 +141,7 @@ describe('e2e_lending_contract', () => { logger.info('Initializing contract'); await lendingContract.methods .init(priceFeedContract.address, 8000, collateralAsset.address, stableCoin.address) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); }); describe('Deposits', () => { @@ -178,8 +175,7 @@ describe('e2e_lending_contract', () => { 0n, collateralAsset.address, ) - .send({ from: defaultAccountAddress, authWitnesses: [transferToPublicAuthwit] }) - .wait(); + .send({ from: defaultAccountAddress, authWitnesses: [transferToPublicAuthwit] }); }); it('Depositing 🥸 on behalf of recipient: 💰 -> 🏦', async () => { @@ -212,8 +208,7 @@ describe('e2e_lending_contract', () => { lendingAccount.address, collateralAsset.address, ) - .send({ from: defaultAccountAddress, authWitnesses: [transferToPublicAuthwit] }) - .wait(); + .send({ from: defaultAccountAddress, authWitnesses: [transferToPublicAuthwit] }); }); it('Depositing: 💰 -> 🏦', async () => { @@ -235,7 +230,7 @@ describe('e2e_lending_contract', () => { }, true, ); - await validateAction.send().wait(); + await validateAction.send(); await lendingSim.progressSlots(SLOT_JUMP, dateProvider); lendingSim.depositPublic(lendingAccount.address, lendingAccount.address.toField(), activationThreshold); @@ -249,8 +244,7 @@ describe('e2e_lending_contract', () => { logger.info('Depositing: 💰 -> 🏦'); await lendingContract.methods .deposit_public(activationThreshold, authwitNonce, lendingAccount.address, collateralAsset.address) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); }); }); @@ -269,8 +263,7 @@ describe('e2e_lending_contract', () => { logger.info('Borrow 🥸 : 🏦 -> 🍌'); await lendingContract.methods .borrow_private(lendingAccount.secret, lendingAccount.address, borrowAmount) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); }); it('Borrow: 🏦 -> 🍌', async () => { @@ -287,8 +280,7 @@ describe('e2e_lending_contract', () => { logger.info('Borrow: 🏦 -> 🍌'); await lendingContract.methods .borrow_public(lendingAccount.address, borrowAmount) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); }); }); @@ -313,8 +305,7 @@ describe('e2e_lending_contract', () => { logger.info('Repay 🥸 : 🍌 -> 🏦'); await lendingContract.methods .repay_private(lendingAccount.address, repayAmount, authwitNonce, lendingAccount.secret, 0n, stableCoin.address) - .send({ from: defaultAccountAddress, authWitnesses: [burnPrivateAuthwit] }) - .wait(); + .send({ from: defaultAccountAddress, authWitnesses: [burnPrivateAuthwit] }); }); it('Repay 🥸 on behalf of public: 🍌 -> 🏦', async () => { @@ -344,8 +335,7 @@ describe('e2e_lending_contract', () => { lendingAccount.address, stableCoin.address, ) - .send({ from: defaultAccountAddress, authWitnesses: [burnPrivateAuthwit] }) - .wait(); + .send({ from: defaultAccountAddress, authWitnesses: [burnPrivateAuthwit] }); }); it('Repay: 🍌 -> 🏦', async () => { @@ -361,7 +351,7 @@ describe('e2e_lending_contract', () => { }, true, ); - await validateAction.send().wait(); + await validateAction.send(); await lendingSim.progressSlots(SLOT_JUMP, dateProvider); lendingSim.repayPublic(lendingAccount.address, lendingAccount.address.toField(), repayAmount); @@ -375,8 +365,7 @@ describe('e2e_lending_contract', () => { logger.info('Repay: 🍌 -> 🏦'); await lendingContract.methods .repay_public(repayAmount, authwitNonce, lendingAccount.address, stableCoin.address) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); }); }); @@ -395,8 +384,7 @@ describe('e2e_lending_contract', () => { logger.info('Withdraw: 🏦 -> 💰'); await lendingContract.methods .withdraw_public(lendingAccount.address, withdrawAmount) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); }); it('Withdraw 🥸 : 🏦 -> 💰', async () => { @@ -413,8 +401,7 @@ describe('e2e_lending_contract', () => { logger.info('Withdraw 🥸 : 🏦 -> 💰'); await lendingContract.methods .withdraw_private(lendingAccount.secret, lendingAccount.address, withdrawAmount) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); }); describe('failure cases', () => { diff --git a/yarn-project/end-to-end/src/e2e_mempool_limit.test.ts b/yarn-project/end-to-end/src/e2e_mempool_limit.test.ts index 2daf1ed486ae..4deac67679be 100644 --- a/yarn-project/end-to-end/src/e2e_mempool_limit.test.ts +++ b/yarn-project/end-to-end/src/e2e_mempool_limit.test.ts @@ -1,8 +1,9 @@ import { AztecAddress } from '@aztec/aztec.js/addresses'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { TxStatus } from '@aztec/aztec.js/tx'; import { retryUntil } from '@aztec/foundation/retry'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; -import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client'; +import type { AztecNode, AztecNodeAdmin } from '@aztec/stdlib/interfaces/client'; import type { TestWallet } from '@aztec/test-wallet/server'; import { proveInteraction } from '@aztec/test-wallet/server'; @@ -11,11 +12,13 @@ import { setup } from './fixtures/utils.js'; describe('e2e_mempool_limit', () => { let wallet: TestWallet; let defaultAccountAddress: AztecAddress; + let aztecNode: AztecNode; let aztecNodeAdmin: AztecNodeAdmin | undefined; let token: TokenContract; beforeAll(async () => { ({ + aztecNode, aztecNodeAdmin, wallet, accounts: [defaultAccountAddress], @@ -27,13 +30,10 @@ describe('e2e_mempool_limit', () => { throw new Error('Aztec node admin API must be available for this test'); } - token = await TokenContract.deploy(wallet, defaultAccountAddress, 'TEST', 'T', 18) - .send({ from: defaultAccountAddress }) - .deployed(); - await token.methods - .mint_to_public(defaultAccountAddress, 10n ** 18n) - .send({ from: defaultAccountAddress }) - .wait(); + token = await TokenContract.deploy(wallet, defaultAccountAddress, 'TEST', 'T', 18).send({ + from: defaultAccountAddress, + }); + await token.methods.mint_to_public(defaultAccountAddress, 10n ** 18n).send({ from: defaultAccountAddress }); }); it('should evict txs if there are too many', async () => { @@ -57,19 +57,29 @@ describe('e2e_mempool_limit', () => { { from: defaultAccountAddress }, ); - const sentTx1 = tx1.send(); - await expect(sentTx1.getReceipt()).resolves.toEqual(expect.objectContaining({ status: TxStatus.PENDING })); + const txHash1 = await tx1.send({ wait: NO_WAIT }); + await expect(aztecNode.getTxReceipt(txHash1)).resolves.toEqual( + expect.objectContaining({ status: TxStatus.PENDING }), + ); - const sentTx2 = tx2.send(); - await expect(sentTx1.getReceipt()).resolves.toEqual(expect.objectContaining({ status: TxStatus.PENDING })); - await expect(sentTx2.getReceipt()).resolves.toEqual(expect.objectContaining({ status: TxStatus.PENDING })); + const txHash2 = await tx2.send({ wait: NO_WAIT }); + await expect(aztecNode.getTxReceipt(txHash1)).resolves.toEqual( + expect.objectContaining({ status: TxStatus.PENDING }), + ); + await expect(aztecNode.getTxReceipt(txHash2)).resolves.toEqual( + expect.objectContaining({ status: TxStatus.PENDING }), + ); - const sentTx3 = tx3.send(); + const txHash3 = await tx3.send({ wait: NO_WAIT }); const txDropped = await retryUntil( async () => { // one of the txs will be dropped. Which one is picked is somewhat random because all three will have the same fee - const receipts = await Promise.all([sentTx1.getReceipt(), sentTx2.getReceipt(), sentTx3.getReceipt()]); + const receipts = await Promise.all([ + aztecNode.getTxReceipt(txHash1), + aztecNode.getTxReceipt(txHash2), + aztecNode.getTxReceipt(txHash3), + ]); const numPending = receipts.reduce((count, r) => (r.status === TxStatus.PENDING ? count + 1 : count), 0); return numPending < 3; }, diff --git a/yarn-project/end-to-end/src/e2e_multi_eoa.test.ts b/yarn-project/end-to-end/src/e2e_multi_eoa.test.ts index e66796c21053..39ecf816d95d 100644 --- a/yarn-project/end-to-end/src/e2e_multi_eoa.test.ts +++ b/yarn-project/end-to-end/src/e2e_multi_eoa.test.ts @@ -1,6 +1,8 @@ import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { Fr } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; +import { waitForTx } from '@aztec/aztec.js/node'; import { EthCheatCodes } from '@aztec/aztec/testing'; import type { L1TxUtilsWithBlobs } from '@aztec/ethereum/l1-tx-utils-with-blobs'; import type { PublisherManager } from '@aztec/ethereum/publisher-manager'; @@ -159,10 +161,10 @@ describe('e2e_multi_eoa', () => { jest.spyOn(client, 'sendRawTransaction').mockImplementation(mockSendRawTransaction), ); - const tx = deployMethodTx.send(); - logger.warn(`L2 deploy tx sent with hash ${(await tx.getTxHash()).toString()}`); + const txHash = await deployMethodTx.send({ wait: NO_WAIT }); + logger.warn(`L2 deploy tx sent with hash ${txHash.toString()}`); - const receipt = await tx.wait(); + const receipt = await waitForTx(aztecNode, txHash); expect(receipt.isMined() && receipt.hasExecutionSucceeded()).toBe(true); logger.warn(`Got ${blockedTxs.length} blocked txs for ${blockedSender}`); diff --git a/yarn-project/end-to-end/src/e2e_multi_validator/e2e_multi_validator_node.test.ts b/yarn-project/end-to-end/src/e2e_multi_validator/e2e_multi_validator_node.test.ts index 2a1eb61e0eed..0fe774e79a48 100644 --- a/yarn-project/end-to-end/src/e2e_multi_validator/e2e_multi_validator_node.test.ts +++ b/yarn-project/end-to-end/src/e2e_multi_validator/e2e_multi_validator_node.test.ts @@ -114,15 +114,13 @@ describe('e2e_multi_validator_node', () => { const sender = ownerAddress; logger.info(`Deploying contract from ${sender}`); - const tx = await deployer - .deploy(ownerAddress, sender, 1) - .send({ - from: ownerAddress, - contractAddressSalt: new Fr(BigInt(1)), - skipClassPublication: true, - skipInstancePublication: true, - }) - .wait(); + const tx = await deployer.deploy(ownerAddress, sender, 1).send({ + from: ownerAddress, + contractAddressSalt: new Fr(BigInt(1)), + skipClassPublication: true, + skipInstancePublication: true, + wait: { returnReceipt: true }, + }); await waitForProven(aztecNode, tx, { provenTimeout: (config.aztecProofSubmissionEpochs + 1) * config.aztecEpochDuration * config.aztecSlotDuration, }); @@ -177,15 +175,13 @@ describe('e2e_multi_validator_node', () => { logger.info(`Deploying contract from ${sender}`); const deployer = new ContractDeployer(artifact, wallet); - const tx = await deployer - .deploy(ownerAddress, sender, 1) - .send({ - from: ownerAddress, - contractAddressSalt: new Fr(BigInt(1)), - skipClassPublication: true, - skipInstancePublication: true, - }) - .wait(); + const tx = await deployer.deploy(ownerAddress, sender, 1).send({ + from: ownerAddress, + contractAddressSalt: new Fr(BigInt(1)), + skipClassPublication: true, + skipInstancePublication: true, + wait: { returnReceipt: true }, + }); await waitForProven(aztecNode, tx, { provenTimeout: (config.aztecProofSubmissionEpochs + 1) * config.aztecEpochDuration * config.aztecSlotDuration, }); diff --git a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts index ee9b21f3886b..dd61f6328e4f 100644 --- a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts +++ b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts @@ -59,7 +59,7 @@ describe('e2e_multiple_accounts_1_enc_key', () => { const contractWithWallet = TokenContract.at(token.address, wallet); - await contractWithWallet.methods.transfer(receiver, transferAmount).send({ from: accounts[senderIndex] }).wait(); + await contractWithWallet.methods.transfer(receiver, transferAmount).send({ from: accounts[senderIndex] }); for (let i = 0; i < expectedBalances.length; i++) { await expectTokenBalance(wallet, token, accounts[i], expectedBalances[i], logger); diff --git a/yarn-project/end-to-end/src/e2e_multiple_blobs.test.ts b/yarn-project/end-to-end/src/e2e_multiple_blobs.test.ts index 967c886b596c..c7672369e7b6 100644 --- a/yarn-project/end-to-end/src/e2e_multiple_blobs.test.ts +++ b/yarn-project/end-to-end/src/e2e_multiple_blobs.test.ts @@ -1,9 +1,9 @@ import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses'; -import { BatchCall } from '@aztec/aztec.js/contracts'; +import { BatchCall, NO_WAIT } from '@aztec/aztec.js/contracts'; import { broadcastPrivateFunction, broadcastUtilityFunction, publishContractClass } from '@aztec/aztec.js/deployment'; import { Fr } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; -import type { AztecNode } from '@aztec/aztec.js/node'; +import { type AztecNode, waitForTx } from '@aztec/aztec.js/node'; import type { Wallet } from '@aztec/aztec.js/wallet'; import { encodeCheckpointBlobDataFromBlocks } from '@aztec/blob-lib/encoding'; import { FIELDS_PER_BLOB } from '@aztec/constants'; @@ -45,7 +45,7 @@ describe('e2e_multiple_blobs', () => { } = await setup(1)); aztecNodeAdmin = maybeAztecNodeAdmin!; - contract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + contract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }); }); afterAll(() => teardown()); @@ -84,8 +84,13 @@ describe('e2e_multiple_blobs', () => { expect(provenTxs.length).toBe(TX_COUNT); // Send them simultaneously to be picked up by the sequencer - const receipts = await Promise.all(provenTxs.map(tx => tx.send({ from: defaultAccountAddress }).wait())); - + const txHashes = await Promise.all(provenTxs.map(tx => tx.send({ from: defaultAccountAddress, wait: NO_WAIT }))); + // Wait for all to be mined + const receipts = await Promise.all( + txHashes.map(txHash => { + return waitForTx(aztecNode, txHash); + }), + ); // Check that all txs are in the same block. const blockNumber = receipts[0].blockNumber!; expect(receipts.every(r => r.blockNumber === blockNumber)).toBe(true); diff --git a/yarn-project/end-to-end/src/e2e_nested_contract/importer.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract/importer.test.ts index 4af04de2d7cf..27449075dfe9 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract/importer.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract/importer.test.ts @@ -15,8 +15,8 @@ describe('e2e_nested_contract manual', () => { }); beforeEach(async () => { - importerContract = await ImportTestContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); - testContract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + importerContract = await ImportTestContract.deploy(wallet).send({ from: defaultAccountAddress }); + testContract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }); }); afterAll(async () => { @@ -25,19 +25,16 @@ describe('e2e_nested_contract manual', () => { it('calls a method no arguments', async () => { logger.info(`Calling noargs on importer contract`); - await importerContract.methods.call_no_args(testContract.address).send({ from: defaultAccountAddress }).wait(); + await importerContract.methods.call_no_args(testContract.address).send({ from: defaultAccountAddress }); }); it('calls a public function', async () => { logger.info(`Calling public_fn on importer contract`); - await importerContract.methods.call_public_fn(testContract.address).send({ from: defaultAccountAddress }).wait(); + await importerContract.methods.call_public_fn(testContract.address).send({ from: defaultAccountAddress }); }); it('calls a public function from a public function', async () => { logger.info(`Calling pub_public_fn on importer contract`); - await importerContract.methods - .pub_call_public_fn(testContract.address) - .send({ from: defaultAccountAddress }) - .wait(); + await importerContract.methods.pub_call_public_fn(testContract.address).send({ from: defaultAccountAddress }); }); }); diff --git a/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_call.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_call.test.ts index c3b714efab6c..d702434c7f10 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_call.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_call.test.ts @@ -17,7 +17,6 @@ describe('e2e_nested_contract manual', () => { it('performs nested calls', async () => { await parentContract.methods .entry_point(childContract.address, await childContract.methods.value.selector()) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); }); }); diff --git a/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_enqueue.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_enqueue.test.ts index 9d512a0eb8b1..ac9512f43421 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_enqueue.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_enqueue.test.ts @@ -19,8 +19,8 @@ describe('e2e_nested_contract manual_enqueue', () => { }); beforeEach(async () => { - parentContract = await ParentContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); - childContract = await ChildContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + parentContract = await ParentContract.deploy(wallet).send({ from: defaultAccountAddress }); + childContract = await ChildContract.deploy(wallet).send({ from: defaultAccountAddress }); }); afterAll(async () => { @@ -30,24 +30,21 @@ describe('e2e_nested_contract manual_enqueue', () => { it('enqueues a single public call', async () => { await parentContract.methods .enqueue_call_to_child(childContract.address, await childContract.methods.pub_inc_value.selector(), 42n) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); expect(await getChildStoredValue(childContract)).toEqual(new Fr(42n)); }); it('enqueues multiple public calls', async () => { await parentContract.methods .enqueue_call_to_child_twice(childContract.address, await childContract.methods.pub_inc_value.selector(), 42n) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); expect(await getChildStoredValue(childContract)).toEqual(new Fr(85n)); }); it('enqueues a public call with nested public calls', async () => { await parentContract.methods .enqueue_call_to_pub_entry_point(childContract.address, await childContract.methods.pub_inc_value.selector(), 42n) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); expect(await getChildStoredValue(childContract)).toEqual(new Fr(42n)); }); @@ -58,8 +55,7 @@ describe('e2e_nested_contract manual_enqueue', () => { await childContract.methods.pub_inc_value.selector(), 42n, ) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); expect(await getChildStoredValue(childContract)).toEqual(new Fr(85n)); }); }); diff --git a/yarn-project/end-to-end/src/e2e_nested_contract/manual_public.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract/manual_public.test.ts index 976dbc513e99..3b47116fcb96 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract/manual_public.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract/manual_public.test.ts @@ -26,16 +26,14 @@ describe('e2e_nested_contract manual', () => { it('performs public nested calls', async () => { await parentContract.methods .pub_entry_point(childContract.address, await childContract.methods.pub_get_value.selector(), 42n) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); }); // Regression for https://github.com/AztecProtocol/aztec-packages/issues/640 it('reads fresh value after write within the same tx', async () => { await parentContract.methods .pub_entry_point_twice(childContract.address, await childContract.methods.pub_inc_value.selector(), 42n) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); expect(await getChildStoredValue(childContract)).toEqual(new Fr(84n)); }); @@ -50,7 +48,7 @@ describe('e2e_nested_contract manual', () => { parentContract.methods.enqueue_call_to_child(childContract.address, pubSetValueSelector, 40n), ]; - const tx = await new BatchCall(wallet, actions).send({ from: defaultAccountAddress }).wait(); + const tx = await new BatchCall(wallet, actions).send({ from: defaultAccountAddress }); const extendedLogs = ( await aztecNode.getPublicLogs({ fromBlock: tx.blockNumber!, diff --git a/yarn-project/end-to-end/src/e2e_nested_contract/nested_contract_test.ts b/yarn-project/end-to-end/src/e2e_nested_contract/nested_contract_test.ts index 625cea10cc55..e60e6187d756 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract/nested_contract_test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract/nested_contract_test.ts @@ -65,10 +65,8 @@ export class NestedContractTest { async applyManual() { this.logger.info('Deploying parent and child contracts'); - const parentContract = await ParentContract.deploy(this.wallet) - .send({ from: this.defaultAccountAddress }) - .deployed(); - const childContract = await ChildContract.deploy(this.wallet).send({ from: this.defaultAccountAddress }).deployed(); + const parentContract = await ParentContract.deploy(this.wallet).send({ from: this.defaultAccountAddress }); + const childContract = await ChildContract.deploy(this.wallet).send({ from: this.defaultAccountAddress }); this.parentContract = parentContract; this.childContract = childContract; } diff --git a/yarn-project/end-to-end/src/e2e_nft.test.ts b/yarn-project/end-to-end/src/e2e_nft.test.ts index 19d0ad48ae7d..35a2e8c7310d 100644 --- a/yarn-project/end-to-end/src/e2e_nft.test.ts +++ b/yarn-project/end-to-end/src/e2e_nft.test.ts @@ -33,20 +33,20 @@ describe('NFT', () => { ({ teardown, wallet, accounts } = await setup(4)); [adminAddress, minterAddress, user1Address, user2Address] = accounts; - nftContract = await NFTContract.deploy(wallet, adminAddress, 'FROG', 'FRG').send({ from: adminAddress }).deployed(); + nftContract = await NFTContract.deploy(wallet, adminAddress, 'FROG', 'FRG').send({ from: adminAddress }); }); afterAll(() => teardown()); // NOTE: This test is sequential and each test case depends on the previous one it('sets minter', async () => { - await nftContract.methods.set_minter(minterAddress, true).send({ from: adminAddress }).wait(); + await nftContract.methods.set_minter(minterAddress, true).send({ from: adminAddress }); const isMinterAMinter = await nftContract.methods.is_minter(minterAddress).simulate({ from: minterAddress }); expect(isMinterAMinter).toBe(true); }); it('minter mints to a user', async () => { - await nftContract.methods.mint(user1Address, TOKEN_ID).send({ from: minterAddress }).wait(); + await nftContract.methods.mint(user1Address, TOKEN_ID).send({ from: minterAddress }); const ownerAfterMint = await nftContract.methods.owner_of(TOKEN_ID).simulate({ from: user1Address }); expect(ownerAfterMint).toEqual(user1Address); }); @@ -56,16 +56,13 @@ describe('NFT', () => { // the sender would be the AMM contract. const recipient = user2Address; - await nftContract.methods.transfer_to_private(recipient, TOKEN_ID).send({ from: user1Address }).wait(); + await nftContract.methods.transfer_to_private(recipient, TOKEN_ID).send({ from: user1Address }); const publicOwnerAfter = await nftContract.methods.owner_of(TOKEN_ID).simulate({ from: user1Address }); expect(publicOwnerAfter).toEqual(AztecAddress.ZERO); }); it('transfers in private', async () => { - await nftContract.methods - .transfer_in_private(user2Address, user1Address, TOKEN_ID, 0) - .send({ from: user2Address }) - .wait(); + await nftContract.methods.transfer_in_private(user2Address, user1Address, TOKEN_ID, 0).send({ from: user2Address }); const user1Nfts = await getPrivateNfts(user1Address); expect(user1Nfts).toEqual([TOKEN_ID]); @@ -75,20 +72,14 @@ describe('NFT', () => { }); it('transfers to public', async () => { - await nftContract.methods - .transfer_to_public(user1Address, user2Address, TOKEN_ID, 0) - .send({ from: user1Address }) - .wait(); + await nftContract.methods.transfer_to_public(user1Address, user2Address, TOKEN_ID, 0).send({ from: user1Address }); const publicOwnerAfter = await nftContract.methods.owner_of(TOKEN_ID).simulate({ from: user1Address }); expect(publicOwnerAfter).toEqual(user2Address); }); it('transfers in public', async () => { - await nftContract.methods - .transfer_in_public(user2Address, user1Address, TOKEN_ID, 0) - .send({ from: user2Address }) - .wait(); + await nftContract.methods.transfer_in_public(user2Address, user1Address, TOKEN_ID, 0).send({ from: user2Address }); const publicOwnerAfter = await nftContract.methods.owner_of(TOKEN_ID).simulate({ from: user2Address }); expect(publicOwnerAfter).toEqual(user1Address); diff --git a/yarn-project/end-to-end/src/e2e_note_getter.test.ts b/yarn-project/end-to-end/src/e2e_note_getter.test.ts index c5831b4210ad..d8192b71827c 100644 --- a/yarn-project/end-to-end/src/e2e_note_getter.test.ts +++ b/yarn-project/end-to-end/src/e2e_note_getter.test.ts @@ -34,18 +34,18 @@ describe('e2e_note_getter', () => { let contract: NoteGetterContract; beforeAll(async () => { - contract = await NoteGetterContract.deploy(wallet).send({ from: defaultAddress }).deployed(); + contract = await NoteGetterContract.deploy(wallet).send({ from: defaultAddress }); }); it('inserts notes from 0-9, then makes multiple queries specifying the total suite of comparators', async () => { await Promise.all( Array(10) .fill(0) - .map((_, i) => contract.methods.insert_note(i).send({ from: defaultAddress }).wait()), + .map((_, i) => contract.methods.insert_note(i).send({ from: defaultAddress })), ); // We insert a note with value 5 twice to better test the comparators - await contract.methods.insert_note(5).send({ from: defaultAddress }).wait(); + await contract.methods.insert_note(5).send({ from: defaultAddress }); const [returnEq, returnNeq, returnLt, returnGt, returnLte, returnGte] = await Promise.all([ contract.methods.read_note_values(defaultAddress, Comparator.EQ, 5).simulate({ from: defaultAddress }), @@ -78,7 +78,7 @@ describe('e2e_note_getter', () => { const makeTxHybrid = false; beforeAll(async () => { - contract = await TestContract.deploy(wallet).send({ from: defaultAddress }).deployed(); + contract = await TestContract.deploy(wallet).send({ from: defaultAddress }); owner = defaultAddress; }); @@ -118,19 +118,13 @@ describe('e2e_note_getter', () => { const activeOrNullified = false; it('returns active notes', async () => { - await contract.methods - .call_create_note(VALUE, owner, storageSlot, makeTxHybrid) - .send({ from: defaultAddress }) - .wait(); + await contract.methods.call_create_note(VALUE, owner, storageSlot, makeTxHybrid).send({ from: defaultAddress }); await assertNoteIsReturned(storageSlot, VALUE, activeOrNullified); }); it('does not return nullified notes', async () => { - await contract.methods - .call_create_note(VALUE, owner, storageSlot, makeTxHybrid) - .send({ from: defaultAddress }) - .wait(); - await contract.methods.call_destroy_note(owner, storageSlot).send({ from: defaultAddress }).wait(); + await contract.methods.call_create_note(VALUE, owner, storageSlot, makeTxHybrid).send({ from: defaultAddress }); + await contract.methods.call_destroy_note(owner, storageSlot).send({ from: defaultAddress }); await assertNoReturnValue(storageSlot, activeOrNullified); }); @@ -140,19 +134,13 @@ describe('e2e_note_getter', () => { const activeOrNullified = true; it('returns active notes', async () => { - await contract.methods - .call_create_note(VALUE, owner, storageSlot, makeTxHybrid) - .send({ from: defaultAddress }) - .wait(); + await contract.methods.call_create_note(VALUE, owner, storageSlot, makeTxHybrid).send({ from: defaultAddress }); await assertNoteIsReturned(storageSlot, VALUE, activeOrNullified); }); it('returns nullified notes', async () => { - await contract.methods - .call_create_note(VALUE, owner, storageSlot, makeTxHybrid) - .send({ from: defaultAddress }) - .wait(); - await contract.methods.call_destroy_note(owner, storageSlot).send({ from: defaultAddress }).wait(); + await contract.methods.call_create_note(VALUE, owner, storageSlot, makeTxHybrid).send({ from: defaultAddress }); + await contract.methods.call_destroy_note(owner, storageSlot).send({ from: defaultAddress }); await assertNoteIsReturned(storageSlot, VALUE, activeOrNullified); }); @@ -160,15 +148,11 @@ describe('e2e_note_getter', () => { it('returns both active and nullified notes', async () => { // We store two notes with two different values in the same storage slot, and then delete one of them. Note that // we can't be sure which one was deleted since we're just deleting based on the storage slot. - await contract.methods - .call_create_note(VALUE, owner, storageSlot, makeTxHybrid) - .send({ from: defaultAddress }) - .wait(); + await contract.methods.call_create_note(VALUE, owner, storageSlot, makeTxHybrid).send({ from: defaultAddress }); await contract.methods .call_create_note(VALUE + 1, owner, storageSlot, makeTxHybrid) - .send({ from: defaultAddress }) - .wait(); - await contract.methods.call_destroy_note(owner, storageSlot).send({ from: defaultAddress }).wait(); + .send({ from: defaultAddress }); + await contract.methods.call_destroy_note(owner, storageSlot).send({ from: defaultAddress }); // We now fetch multiple notes, and get both the active and the nullified one. const viewNotesManyResult = await contract.methods diff --git a/yarn-project/end-to-end/src/e2e_offchain_effect.test.ts b/yarn-project/end-to-end/src/e2e_offchain_effect.test.ts index 0021cd449230..1631b85be170 100644 --- a/yarn-project/end-to-end/src/e2e_offchain_effect.test.ts +++ b/yarn-project/end-to-end/src/e2e_offchain_effect.test.ts @@ -33,8 +33,8 @@ describe('e2e_offchain_effect', () => { accounts: [defaultAccountAddress], aztecNode, } = await setup(1)); - contract1 = await OffchainEffectContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); - contract2 = await OffchainEffectContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + contract1 = await OffchainEffectContract.deploy(wallet).send({ from: defaultAccountAddress }); + contract2 = await OffchainEffectContract.deploy(wallet).send({ from: defaultAccountAddress }); }); afterAll(() => teardown()); @@ -78,7 +78,7 @@ describe('e2e_offchain_effect', () => { contract1.methods.emit_event_as_offchain_message_for_msg_sender(a, b, c), { from: defaultAccountAddress }, ); - const { txHash, blockNumber, blockHash } = await provenTx.send().wait(); + const { txHash, blockNumber, blockHash } = await provenTx.send(); const offchainEffects = provenTx.offchainEffects; expect(offchainEffects).toHaveLength(1); @@ -135,7 +135,7 @@ describe('e2e_offchain_effect', () => { const provenTx = await proveInteraction(wallet, contract1.methods.emit_note_as_offchain_message(value, owner), { from: defaultAccountAddress, }); - const { txHash } = await provenTx.send().wait(); + const { txHash } = await provenTx.send(); const offchainEffects = provenTx.offchainEffects; expect(offchainEffects).toHaveLength(1); diff --git a/yarn-project/end-to-end/src/e2e_orderbook.test.ts b/yarn-project/end-to-end/src/e2e_orderbook.test.ts index ba5ad9d1b927..e53895c97c81 100644 --- a/yarn-project/end-to-end/src/e2e_orderbook.test.ts +++ b/yarn-project/end-to-end/src/e2e_orderbook.test.ts @@ -52,9 +52,9 @@ describe('Orderbook', () => { ({ contract: token0 } = await deployToken(wallet, adminAddress, 0n, logger)); ({ contract: token1 } = await deployToken(wallet, adminAddress, 0n, logger)); - orderbook = await OrderbookContract.deploy(wallet, token0.address, token1.address) - .send({ from: adminAddress }) - .deployed(); + orderbook = await OrderbookContract.deploy(wallet, token0.address, token1.address).send({ + from: adminAddress, + }); // Mint tokens to maker and taker await mintTokensToPrivate(token0, adminAddress, makerAddress, bidAmount); @@ -79,8 +79,7 @@ describe('Orderbook', () => { await orderbook.methods .create_order(token0.address, token1.address, bidAmount, askAmount, nonceForAuthwits) .with({ authWitnesses: [makerAuthwit] }) - .send({ from: makerAddress }) - .wait(); + .send({ from: makerAddress }); const orderCreatedEvents = await getDecodedPublicEvents( aztecNode, @@ -132,8 +131,7 @@ describe('Orderbook', () => { await orderbook.methods .fulfill_order(orderId, nonceForAuthwits) .with({ authWitnesses: [takerAuthwit] }) - .send({ from: takerAddress }) - .wait(); + .send({ from: takerAddress }); // Verify order was fulfilled by checking events const orderFulfilledEvents = await getDecodedPublicEvents( diff --git a/yarn-project/end-to-end/src/e2e_ordering.test.ts b/yarn-project/end-to-end/src/e2e_ordering.test.ts index 127bacf130ff..a6e8a4c19e80 100644 --- a/yarn-project/end-to-end/src/e2e_ordering.test.ts +++ b/yarn-project/end-to-end/src/e2e_ordering.test.ts @@ -56,8 +56,8 @@ describe('e2e_ordering', () => { let pubSetValueSelector: FunctionSelector; beforeEach(async () => { - parent = await ParentContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); - child = await ChildContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + parent = await ParentContract.deploy(wallet).send({ from: defaultAccountAddress }); + child = await ChildContract.deploy(wallet).send({ from: defaultAccountAddress }); pubSetValueSelector = await child.methods.pub_set_value.selector(); }, TIMEOUT); @@ -77,7 +77,7 @@ describe('e2e_ordering', () => { const action = parent.methods[method](child.address, pubSetValueSelector); const tx = await proveInteraction(wallet, action, { from: defaultAccountAddress }); - await tx.send().wait(); + await tx.send(); // There are two enqueued calls const enqueuedPublicCalls = tx.getPublicCallRequestsWithCalldata(); @@ -120,7 +120,7 @@ describe('e2e_ordering', () => { ] as const)('orders public state updates in %s (and ensures final state value is correct)', async method => { const expectedOrder = expectedOrders[method]; - await child.methods[method]().send({ from: defaultAccountAddress }).wait(); + await child.methods[method]().send({ from: defaultAccountAddress }); const value = await aztecNode.getPublicStorageAt('latest', child.address, new Fr(1)); expect(value.toBigInt()).toBe(expectedOrder[expectedOrder.length - 1]); // final state should match last value set @@ -133,7 +133,7 @@ describe('e2e_ordering', () => { ] as const)('orders public logs in %s', async method => { const expectedOrder = expectedOrders[method]; - await child.methods[method]().send({ from: defaultAccountAddress }).wait(); + await child.methods[method]().send({ from: defaultAccountAddress }); // Logs are emitted in the expected order await expectLogsFromLastBlockToBe(expectedOrder); diff --git a/yarn-project/end-to-end/src/e2e_p2p/add_rollup.test.ts b/yarn-project/end-to-end/src/e2e_p2p/add_rollup.test.ts index 44be1d891dce..5afd8ebd2246 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/add_rollup.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/add_rollup.test.ts @@ -277,15 +277,13 @@ describe('e2e_p2p_add_rollup', () => { const wallet = await TestWallet.create(node, { ...getPXEConfig(), proverEnabled: false }, { useLogSuffix: true }); const aliceAccountManager = await wallet.createSchnorrAccount(aliceAccount.secret, aliceAccount.salt); const aliceDeploymethod = await aliceAccountManager.getDeployMethod(); - await aliceDeploymethod - .send({ - from: AztecAddress.ZERO, - }) - .wait(); + await aliceDeploymethod.send({ + from: AztecAddress.ZERO, + }); const aliceAddress = aliceAccountManager.address; - const testContract = await TestContract.deploy(wallet).send({ from: aliceAddress }).deployed(); + const testContract = await TestContract.deploy(wallet).send({ from: aliceAddress }); const [secret, secretHash] = await generateClaimSecret(); @@ -306,13 +304,11 @@ describe('e2e_p2p_add_rollup', () => { const receipt = await testContract.methods .create_l2_to_l1_message_arbitrary_recipient_private(contentOutFromRollup, ethRecipient) - .send({ from: aliceAddress }) - .wait(); + .send({ from: aliceAddress }); await testContract.methods .create_l2_to_l1_message_arbitrary_recipient_private(contentOutFromRollup, ethRecipient) - .send({ from: aliceAddress }) - .wait(); + .send({ from: aliceAddress }); return receipt; }; @@ -325,8 +321,7 @@ describe('e2e_p2p_add_rollup', () => { await testContract.methods .consume_message_from_arbitrary_sender_private(message.content, secret, ethRecipient, message1Index) - .send({ from: aliceAddress }) - .wait(); + .send({ from: aliceAddress }); // Then we consume the L2 -> L1 message { diff --git a/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts index a934f19f2cea..93dddccfb2b9 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts @@ -1,6 +1,7 @@ import type { Archiver } from '@aztec/archiver'; import type { AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node'; -import { SentTx } from '@aztec/aztec.js/contracts'; +import { waitForTx } from '@aztec/aztec.js/node'; +import { TxHash } from '@aztec/aztec.js/tx'; import { CheckpointNumber } from '@aztec/foundation/branded-types'; import { Signature } from '@aztec/foundation/eth-signature'; import { retryUntil } from '@aztec/foundation/retry'; @@ -104,7 +105,7 @@ describe('e2e_p2p_network', () => { // the number of txs per node and the number of txs per rollup // should be set so that the only way for rollups to be built // is if the txs are successfully gossiped around the nodes. - const txsSentViaDifferentNodes: SentTx[][] = []; + const txsSentViaDifferentNodes: TxHash[][] = []; t.logger.info('Creating validator nodes'); nodes = await createNodes( t.ctx.aztecNodeConfig, @@ -177,16 +178,17 @@ describe('e2e_p2p_network', () => { // now ensure that all txs were successfully mined await Promise.all( txsSentViaDifferentNodes.flatMap((txs, i) => - txs.map(async (tx, j) => { - t.logger.info(`Waiting for tx ${i}-${j}: ${(await tx.getTxHash()).toString()} to be mined`); - return tx.wait({ timeout: WAIT_FOR_TX_TIMEOUT }); + txs.map((txHash, j) => { + t.logger.info(`Waiting for tx ${i}-${j}: ${txHash.toString()} to be mined`); + return waitForTx(nodes[0], txHash, { timeout: WAIT_FOR_TX_TIMEOUT }); }), ), ); t.logger.info('All transactions mined'); // Gather signers from attestations downloaded from L1 - const blockNumber = await txsSentViaDifferentNodes[0][0].getReceipt().then(r => r.blockNumber!); + const receipt = await nodes[0].getTxReceipt(txsSentViaDifferentNodes[0][0]); + const blockNumber = receipt.blockNumber!; const dataStore = (nodes[0] as AztecNodeService).getBlockSource() as Archiver; const [publishedCheckpoint] = await dataStore.getCheckpoints(CheckpointNumber.fromBlockNumber(blockNumber), 1); const payload = ConsensusPayload.fromCheckpoint(publishedCheckpoint.checkpoint); diff --git a/yarn-project/end-to-end/src/e2e_p2p/gossip_network_no_cheat.test.ts b/yarn-project/end-to-end/src/e2e_p2p/gossip_network_no_cheat.test.ts index 938282d1e122..ae9ed1450506 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/gossip_network_no_cheat.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/gossip_network_no_cheat.test.ts @@ -1,8 +1,9 @@ import type { Archiver } from '@aztec/archiver'; import type { AztecNodeService } from '@aztec/aztec-node'; import { EthAddress } from '@aztec/aztec.js/addresses'; -import { SentTx } from '@aztec/aztec.js/contracts'; import { Fr } from '@aztec/aztec.js/fields'; +import { waitForTx } from '@aztec/aztec.js/node'; +import { TxHash } from '@aztec/aztec.js/tx'; import { addL1Validator } from '@aztec/cli/l1/validators'; import { RollupContract } from '@aztec/ethereum/contracts'; import { CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types'; @@ -180,7 +181,7 @@ describe('e2e_p2p_network', () => { // the number of txs per node and the number of txs per rollup // should be set so that the only way for rollups to be built // is if the txs are successfully gossiped around the nodes. - const txsSentViaDifferentNodes: SentTx[][] = []; + const txsSentViaDifferentNodes: TxHash[][] = []; t.logger.info('Creating nodes'); nodes = await createNodes( t.ctx.aztecNodeConfig, @@ -212,16 +213,16 @@ describe('e2e_p2p_network', () => { // now ensure that all txs were successfully mined await Promise.all( txsSentViaDifferentNodes.flatMap((txs, i) => - txs.map(async (tx, j) => { - t.logger.info(`Waiting for tx ${i}-${j}: ${(await tx.getTxHash()).toString()} to be mined`); - return tx.wait({ timeout: WAIT_FOR_TX_TIMEOUT }); + txs.map((txHash, j) => { + t.logger.info(`Waiting for tx ${i}-${j}: ${txHash.toString()} to be mined`); + return waitForTx(nodes[0], txHash, { timeout: WAIT_FOR_TX_TIMEOUT }); }), ), ); t.logger.info('All transactions mined'); // Gather signers from attestations downloaded from L1 - const blockNumber = await txsSentViaDifferentNodes[0][0].getReceipt().then(r => r.blockNumber!); + const blockNumber = await nodes[0].getTxReceipt(txsSentViaDifferentNodes[0][0]).then(r => r.blockNumber!); const dataStore = (nodes[0] as AztecNodeService).getBlockSource() as Archiver; const [publishedCheckpoint] = await dataStore.getCheckpoints(CheckpointNumber.fromBlockNumber(blockNumber), 1); const payload = ConsensusPayload.fromCheckpoint(publishedCheckpoint.checkpoint); diff --git a/yarn-project/end-to-end/src/e2e_p2p/mbps_checkpoint_consensus.test.ts b/yarn-project/end-to-end/src/e2e_p2p/mbps_checkpoint_consensus.test.ts index d4ef2c25528e..52ac3b5c8e1b 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/mbps_checkpoint_consensus.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/mbps_checkpoint_consensus.test.ts @@ -11,7 +11,8 @@ */ import type { Archiver } from '@aztec/archiver'; import type { AztecNodeService } from '@aztec/aztec-node'; -import type { SentTx } from '@aztec/aztec.js/contracts'; +import { waitForTx } from '@aztec/aztec.js/node'; +import { TxHash } from '@aztec/aztec.js/tx'; import { RollupContract } from '@aztec/ethereum/contracts'; import { CheckpointNumber } from '@aztec/foundation/branded-types'; import { retryUntil } from '@aztec/foundation/retry'; @@ -117,7 +118,7 @@ describe.skip('e2e_p2p_mbps_checkpoint_consensus', () => { // Submit transactions through different nodes // This ensures transactions are gossiped through the P2P network t.logger.info('Submitting transactions through validator nodes'); - const txsSentViaDifferentNodes: SentTx[][] = []; + const txsSentViaDifferentNodes: TxHash[][] = []; for (const node of nodes) { const txs = await submitTransactions(t.logger, node, NUM_TXS_PER_NODE, t.fundedAccount); txsSentViaDifferentNodes.push(txs); @@ -127,9 +128,9 @@ describe.skip('e2e_p2p_mbps_checkpoint_consensus', () => { t.logger.info('Waiting for transactions to be mined'); await Promise.all( txsSentViaDifferentNodes.flatMap((txs, i) => - txs.map(async (tx, j) => { - t.logger.info(`Waiting for tx ${i}-${j}: ${(await tx.getTxHash()).toString()} to be mined`); - return tx.wait({ timeout: WAIT_FOR_TX_TIMEOUT }); + txs.map((txHash, j) => { + t.logger.info(`Waiting for tx ${i}-${j}: ${txHash.toString()} to be mined`); + return waitForTx(nodes[0], txHash, { timeout: WAIT_FOR_TX_TIMEOUT }); }), ), ); @@ -224,7 +225,7 @@ describe.skip('e2e_p2p_mbps_checkpoint_consensus', () => { // Submit transactions t.logger.info('Submitting transactions'); - const txsSentViaDifferentNodes: SentTx[][] = []; + const txsSentViaDifferentNodes: TxHash[][] = []; for (const node of nodes) { const txs = await submitTransactions(t.logger, node, NUM_TXS_PER_NODE, t.fundedAccount); txsSentViaDifferentNodes.push(txs); @@ -234,16 +235,17 @@ describe.skip('e2e_p2p_mbps_checkpoint_consensus', () => { t.logger.info('Waiting for transactions to be mined'); await Promise.all( txsSentViaDifferentNodes.flatMap((txs, i) => - txs.map(async (tx, j) => { - t.logger.info(`Waiting for tx ${i}-${j}: ${(await tx.getTxHash()).toString()} to be mined`); - return tx.wait({ timeout: WAIT_FOR_TX_TIMEOUT }); + txs.map((txHash, j) => { + t.logger.info(`Waiting for tx ${i}-${j}: ${txHash.toString()} to be mined`); + return waitForTx(nodes[0], txHash, { timeout: WAIT_FOR_TX_TIMEOUT }); }), ), ); t.logger.info('All transactions mined'); // Wait for at least one block to be mined - const blockNumber = await txsSentViaDifferentNodes[0][0].getReceipt().then(r => r.blockNumber!); + const receipt = await nodes[0].getTxReceipt(txsSentViaDifferentNodes[0][0]); + const blockNumber = receipt.blockNumber!; t.logger.info(`Block ${blockNumber} mined, verifying attestations`); // Retrieve blocks and check attestations @@ -299,7 +301,7 @@ describe.skip('e2e_p2p_mbps_checkpoint_consensus', () => { await t.setupAccount(); t.logger.info('Submitting transactions'); - const txsSentViaDifferentNodes: SentTx[][] = []; + const txsSentViaDifferentNodes: TxHash[][] = []; for (const node of nodes) { const txs = await submitTransactions(t.logger, node, NUM_TXS_PER_NODE, t.fundedAccount); txsSentViaDifferentNodes.push(txs); @@ -308,9 +310,9 @@ describe.skip('e2e_p2p_mbps_checkpoint_consensus', () => { // Wait for transactions await Promise.all( txsSentViaDifferentNodes.flatMap((txs, i) => - txs.map(async (tx, j) => { - t.logger.info(`Waiting for tx ${i}-${j}: ${(await tx.getTxHash()).toString()} to be mined`); - return tx.wait({ timeout: WAIT_FOR_TX_TIMEOUT }); + txs.map((txHash, j) => { + t.logger.info(`Waiting for tx ${i}-${j}: ${txHash.toString()} to be mined`); + return waitForTx(nodes[0], txHash, { timeout: WAIT_FOR_TX_TIMEOUT }); }), ), ); diff --git a/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts b/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts index c2d37b899e91..051877808246 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts @@ -321,7 +321,7 @@ export class P2PNetworkTest { throw new Error('Call setupAccount before deploying spam contract'); } - const spamContract = await SpamContract.deploy(this.wallet).send({ from: this.defaultAccountAddress! }).deployed(); + const spamContract = await SpamContract.deploy(this.wallet).send({ from: this.defaultAccountAddress! }); this.spamContract = spamContract; } diff --git a/yarn-project/end-to-end/src/e2e_p2p/preferred_gossip_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p/preferred_gossip_network.test.ts index a305d572ba1c..068391ccd2ce 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/preferred_gossip_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/preferred_gossip_network.test.ts @@ -1,6 +1,7 @@ import type { Archiver } from '@aztec/archiver'; import type { AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node'; -import { SentTx } from '@aztec/aztec.js/contracts'; +import { waitForTx } from '@aztec/aztec.js/node'; +import { TxHash } from '@aztec/aztec.js/tx'; import { CheckpointNumber } from '@aztec/foundation/branded-types'; import { Signature } from '@aztec/foundation/eth-signature'; import { retryUntil } from '@aztec/foundation/retry'; @@ -183,7 +184,7 @@ describe('e2e_p2p_preferred_network', () => { // the number of txs per node and the number of txs per rollup // should be set so that the only way for rollups to be built // is if the txs are successfully gossiped around the nodes. - const txsSentViaDifferentNodes: SentTx[][] = []; + const txsSentViaDifferentNodes: TxHash[][] = []; let indexOffset = 0; t.logger.info('Creating preferred nodes'); @@ -345,18 +346,18 @@ describe('e2e_p2p_preferred_network', () => { t.logger.info('Waiting for transactions to be mined'); // now ensure that all txs were successfully mined - await Promise.all( + const receipts = await Promise.all( txsSentViaDifferentNodes.flatMap((txs, i) => - txs.map(async (tx, j) => { - t.logger.info(`Waiting for tx ${i}-${j}: ${await tx.getTxHash()} to be mined`); - return tx.wait({ timeout: WAIT_FOR_TX_TIMEOUT }); + txs.map((txHash, j) => { + t.logger.info(`Waiting for tx ${i}-${j}: ${txHash.toString()} to be mined`); + return waitForTx(nodes[0], txHash, { timeout: WAIT_FOR_TX_TIMEOUT }); }), ), ); t.logger.info('All transactions mined'); // Gather signers from attestations downloaded from L1 - const blockNumber = await txsSentViaDifferentNodes[0][0].getReceipt().then(r => r.blockNumber!); + const blockNumber = receipts[0].blockNumber!; const dataStore = (nodes[0] as AztecNodeService).getBlockSource() as Archiver; const [publishedCheckpoint] = await dataStore.getCheckpoints(CheckpointNumber.fromBlockNumber(blockNumber), 1); const payload = ConsensusPayload.fromCheckpoint(publishedCheckpoint.checkpoint); diff --git a/yarn-project/end-to-end/src/e2e_p2p/rediscovery.test.ts b/yarn-project/end-to-end/src/e2e_p2p/rediscovery.test.ts index 1e7db82d4d60..54a6dec3c628 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/rediscovery.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/rediscovery.test.ts @@ -1,5 +1,6 @@ import type { AztecNodeService } from '@aztec/aztec-node'; -import { SentTx } from '@aztec/aztec.js/contracts'; +import { waitForTx } from '@aztec/aztec.js/node'; +import { TxHash } from '@aztec/aztec.js/tx'; import { sleep } from '@aztec/foundation/sleep'; import fs from 'fs'; @@ -50,7 +51,7 @@ describe('e2e_p2p_rediscovery', () => { }); it('should re-discover stored peers without bootstrap node', async () => { - const txsSentViaDifferentNodes: SentTx[][] = []; + const txsSentViaDifferentNodes: TxHash[][] = []; nodes = await createNodes( t.ctx.aztecNodeConfig, t.ctx.dateProvider!, @@ -109,18 +110,15 @@ describe('e2e_p2p_rediscovery', () => { // now ensure that all txs were successfully mined await Promise.all( txsSentViaDifferentNodes.flatMap((txs, i) => - txs.map(async (tx, j) => { - const txHash = await tx.getTxHash(); - t.logger.info(`Waiting for tx ${i}-${j} ${txHash} to be mined`, { txHash }); - return tx - .wait({ timeout: WAIT_FOR_TX_TIMEOUT }) - .then(() => { - t.logger.info(`Tx ${i}-${j} mined successfully`, { txHash }); - }) - .catch(err => { - t.logger.error(`Tx ${i}-${j} failed to mine: ${err}`, { txHash }); - throw err; - }); + txs.map(async (txHash, j) => { + t.logger.info(`Waiting for tx ${i}-${j} ${txHash} to be mined`, { txHash: txHash.toString() }); + try { + await waitForTx(newNodes[0], txHash, { timeout: WAIT_FOR_TX_TIMEOUT }); + t.logger.info(`Tx ${i}-${j} mined successfully`, { txHash: txHash.toString() }); + } catch (err) { + t.logger.error(`Tx ${i}-${j} failed to mine: ${err}`, { txHash: txHash.toString() }); + throw err; + } }), ), ); diff --git a/yarn-project/end-to-end/src/e2e_p2p/reex.test.ts b/yarn-project/end-to-end/src/e2e_p2p/reex.test.ts index 6dc4301150d7..566bf1a4a239 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/reex.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/reex.test.ts @@ -1,7 +1,7 @@ import type { AztecNodeService } from '@aztec/aztec-node'; -import type { SentTx } from '@aztec/aztec.js/contracts'; import { Fr } from '@aztec/aztec.js/fields'; -import { Tx } from '@aztec/aztec.js/tx'; +import { waitForTx } from '@aztec/aztec.js/node'; +import { Tx, TxHash } from '@aztec/aztec.js/tx'; import { times } from '@aztec/foundation/collection'; import { sleep } from '@aztec/foundation/sleep'; import { unfreeze } from '@aztec/foundation/types'; @@ -30,7 +30,7 @@ const DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'reex-')); describe('e2e_p2p_reex', () => { let t: P2PNetworkTest; let nodes: AztecNodeService[]; - let txs: SentTx[]; + let txs: TxHash[]; beforeAll(async () => { nodes = []; @@ -243,9 +243,9 @@ describe('e2e_p2p_reex', () => { // We ensure that the transactions are NOT mined in the next slot const txResults = await Promise.allSettled( - txs.map(async (tx: SentTx, i: number) => { - t.logger.info(`Waiting for tx ${i}: ${(await tx.getTxHash()).toString()} to be mined`); - return await tx.wait({ timeout: t.ctx.aztecNodeConfig.aztecSlotDuration * 2 }); + txs.map(async (txHash: TxHash, i: number) => { + t.logger.info(`Waiting for tx ${i}: ${txHash.toString()} to be mined`); + return await waitForTx(nodes[0], txHash, { timeout: t.ctx.aztecNodeConfig.aztecSlotDuration * 2 }); }), ); diff --git a/yarn-project/end-to-end/src/e2e_p2p/reqresp.test.ts b/yarn-project/end-to-end/src/e2e_p2p/reqresp.test.ts index e4823143db40..5af14521f200 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/reqresp.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/reqresp.test.ts @@ -1,6 +1,6 @@ import type { AztecNodeService } from '@aztec/aztec-node'; -import { SentTx } from '@aztec/aztec.js/contracts'; import { createLogger } from '@aztec/aztec.js/log'; +import { waitForTx } from '@aztec/aztec.js/node'; import { Tx } from '@aztec/aztec.js/tx'; import { RollupContract } from '@aztec/ethereum/contracts'; import { timesAsync } from '@aztec/foundation/collection'; @@ -128,7 +128,7 @@ describe('e2e_p2p_reqresp_tx', () => { txs.map(tx => { const node = nodes[proposerIndexes[i]]; void node.sendTx(tx).catch(err => t.logger.error(`Error sending tx: ${err}`)); - return new SentTx(node, () => Promise.resolve(tx.getTxHash())); + return { node, txHash: tx.getTxHash() }; }), ); @@ -136,9 +136,9 @@ describe('e2e_p2p_reqresp_tx', () => { await Promise.all( sentTxs.flatMap((txs, i) => txs.map(async (tx, j) => { - t.logger.info(`Waiting for tx ${i}-${j} ${(await tx.getTxHash()).toString()} to be mined`); - await tx.wait({ timeout: WAIT_FOR_TX_TIMEOUT * 1.5 }); // more transactions in this test so allow more time - t.logger.info(`Tx ${i}-${j} ${(await tx.getTxHash()).toString()} has been mined`); + t.logger.info(`Waiting for tx ${i}-${j} ${tx.txHash.toString()} to be mined`); + await waitForTx(tx.node, tx.txHash, { timeout: WAIT_FOR_TX_TIMEOUT * 1.5 }); // more transactions in this test so allow more time + t.logger.info(`Tx ${i}-${j} ${tx.txHash.toString()} has been mined`); }), ), ); diff --git a/yarn-project/end-to-end/src/e2e_p2p/reqresp_no_handshake.test.ts b/yarn-project/end-to-end/src/e2e_p2p/reqresp_no_handshake.test.ts index 4b8d3c45b08f..80b10fe27861 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/reqresp_no_handshake.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/reqresp_no_handshake.test.ts @@ -1,6 +1,6 @@ import type { AztecNodeService } from '@aztec/aztec-node'; -import { SentTx } from '@aztec/aztec.js/contracts'; import { createLogger } from '@aztec/aztec.js/log'; +import { waitForTx } from '@aztec/aztec.js/node'; import { Tx } from '@aztec/aztec.js/tx'; import { RollupContract } from '@aztec/ethereum/contracts'; import { timesAsync } from '@aztec/foundation/collection'; @@ -133,7 +133,7 @@ describe('e2e_p2p_reqresp_tx_no_handshake', () => { txs.map(tx => { const node = nodes[proposerIndexes[i]]; void node.sendTx(tx).catch(err => t.logger.error(`Error sending tx: ${err}`)); - return new SentTx(node, () => Promise.resolve(tx.getTxHash())); + return { node, txHash: tx.getTxHash() }; }), ); @@ -141,9 +141,9 @@ describe('e2e_p2p_reqresp_tx_no_handshake', () => { await Promise.all( sentTxs.flatMap((txs, i) => txs.map(async (tx, j) => { - t.logger.info(`Waiting for tx ${i}-${j} ${(await tx.getTxHash()).toString()} to be mined`); - await tx.wait({ timeout: WAIT_FOR_TX_TIMEOUT * 1.5 }); // more transactions in this test so allow more time - t.logger.info(`Tx ${i}-${j} ${(await tx.getTxHash()).toString()} has been mined`); + t.logger.info(`Waiting for tx ${i}-${j} ${tx.txHash.toString()} to be mined`); + await waitForTx(tx.node, tx.txHash, { timeout: WAIT_FOR_TX_TIMEOUT * 1.5 }); // more transactions in this test so allow more time + t.logger.info(`Tx ${i}-${j} ${tx.txHash.toString()} has been mined`); }), ), ); diff --git a/yarn-project/end-to-end/src/e2e_p2p/shared.ts b/yarn-project/end-to-end/src/e2e_p2p/shared.ts index 420ede9d5ec2..69aec301ca71 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/shared.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/shared.ts @@ -1,10 +1,10 @@ import type { InitialAccountData } from '@aztec/accounts/testing'; import type { AztecNodeService } from '@aztec/aztec-node'; import { AztecAddress } from '@aztec/aztec.js/addresses'; -import { type SentTx, getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts'; +import { NO_WAIT, getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts'; import { Fr } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; -import { Tx, TxStatus } from '@aztec/aztec.js/tx'; +import { TxHash } from '@aztec/aztec.js/tx'; import type { RollupCheatCodes } from '@aztec/aztec/testing'; import type { EmpireSlashingProposerContract, @@ -22,7 +22,7 @@ import { getPXEConfig, getPXEConfig as getRpcConfig } from '@aztec/pxe/server'; import { getRoundForOffense } from '@aztec/slasher'; import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client'; import type { SlashFactoryContract } from '@aztec/stdlib/l1-contracts'; -import { TestWallet, proveInteraction } from '@aztec/test-wallet/server'; +import { type ProvenTx, TestWallet, proveInteraction } from '@aztec/test-wallet/server'; import { submitTxsTo } from '../shared/submit-transactions.js'; @@ -34,24 +34,15 @@ export const submitComplexTxsTo = async ( numTxs: number, opts: { callPublic?: boolean } = {}, ) => { - const txs: SentTx[] = []; + const txs: TxHash[] = []; const seed = 1234n; const spamCount = 15; for (let i = 0; i < numTxs; i++) { - const tx = spamContract.methods.spam(seed + BigInt(i * spamCount), spamCount, !!opts.callPublic).send({ from }); - const txHash = await tx.getTxHash(); - + const method = spamContract.methods.spam(seed + BigInt(i * spamCount), spamCount, !!opts.callPublic); + const txHash = await method.send({ from, wait: NO_WAIT }); logger.info(`Tx sent with hash ${txHash.toString()}`); - const receipt = await tx.getReceipt(); - expect(receipt).toEqual( - expect.objectContaining({ - status: TxStatus.PENDING, - error: '', - }), - ); - logger.info(`Receipt received for ${txHash.toString()}`); - txs.push(tx); + txs.push(txHash); } return txs; }; @@ -62,7 +53,7 @@ export const submitTransactions = async ( node: AztecNodeService, numTxs: number, fundedAccount: InitialAccountData, -): Promise => { +): Promise => { const rpcConfig = getRpcConfig(); rpcConfig.proverEnabled = false; const wallet = await TestWallet.create(node, { ...getPXEConfig(), proverEnabled: false }, { useLogSuffix: true }); @@ -75,7 +66,7 @@ export async function prepareTransactions( node: AztecNodeService, numTxs: number, fundedAccount: InitialAccountData, -): Promise { +): Promise { const rpcConfig = getRpcConfig(); rpcConfig.proverEnabled = false; @@ -92,8 +83,7 @@ export async function prepareTransactions( const tx = await proveInteraction(wallet, contract.methods.emit_nullifier(Fr.random()), { from: fundedAccountManager.address, }); - const txHash = tx.getTxHash(); - logger.info(`Tx prepared with hash ${txHash}`); + logger.info(`Tx prepared with hash ${tx.getTxHash()}`); return tx; }); } diff --git a/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned_slash.test.ts b/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned_slash.test.ts index b4c9f345df09..1ac997ddbb40 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned_slash.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned_slash.test.ts @@ -143,7 +143,7 @@ describe('e2e_p2p_valid_epoch_pruned_slash', () => { // Send a tx to deploy a contract so that we have a tx with public function execution in the pruned epoch // This allows us to test that the slashed offense is valid epoch prune and not data withholding t.logger.warn(`Submitting deployment tx to the network`); - const _spamContract = await SpamContract.deploy(t.wallet!).send({ from: t.defaultAccountAddress! }).deployed(); + const _spamContract = await SpamContract.deploy(t.wallet!).send({ from: t.defaultAccountAddress! }); // And send a tx that depends on a tx with public function execution on a contract class that will be reorged out // This allows us to test that we handle pruned contract classes correctly @@ -151,7 +151,7 @@ describe('e2e_p2p_valid_epoch_pruned_slash', () => { // this tx are in different blocks but within the same epoch, so it gets reexecuted by the prune-watcher. // This does not always happen in the current test setup. // t.logger.warn(`Submitting tx with public function execution to the network`); - // await spamContract.methods.spam(1, 1, true).send({ from: t.defaultAccountAddress! }).wait(); + // await spamContract.methods.spam(1, 1, true).send({ from: t.defaultAccountAddress! }); // Initial node receives the txs, so we cannot stop it before that one is mined // Yes, that means that there are probably two nodes running the same validator key (the initial node and nodes[0]) diff --git a/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts b/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts index ff203c43ca40..7b2c5bad2374 100644 --- a/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts @@ -75,7 +75,7 @@ describe('e2e_pending_note_hashes_contract', () => { const deployContract = async () => { logger.debug(`Deploying L2 contract...`); - contract = await PendingNoteHashesContract.deploy(wallet).send({ from: owner }).deployed(); + contract = await PendingNoteHashesContract.deploy(wallet).send({ from: owner }); logger.info(`L2 contract deployed at ${contract.address}`); return contract; }; @@ -88,8 +88,7 @@ describe('e2e_pending_note_hashes_contract', () => { const sender = owner; await deployedContract.methods .test_insert_then_get_then_nullify_flat(mintAmount, owner, sender) - .send({ from: owner }) - .wait(); + .send({ from: owner }); }); it('Squash! Aztec.nr function can "create" and "nullify" note in the same TX', async () => { @@ -108,9 +107,8 @@ describe('e2e_pending_note_hashes_contract', () => { await deployedContract.methods.insert_note.selector(), await deployedContract.methods.get_then_nullify_note.selector(), ) - .send({ from: owner }) - .wait(); - await deployedContract.methods.get_note_zero_balance(owner).send({ from: owner }).wait(); + .send({ from: owner }); + await deployedContract.methods.get_note_zero_balance(owner).send({ from: owner }); await expectNoteHashesSquashedExcept(0); await expectNullifiersSquashedExcept(0); @@ -133,8 +131,7 @@ describe('e2e_pending_note_hashes_contract', () => { await deployedContract.methods.insert_note_extra_emit.selector(), await deployedContract.methods.get_then_nullify_note.selector(), ) - .send({ from: owner }) - .wait(); + .send({ from: owner }); await expectNoteHashesSquashedExcept(0); await expectNullifiersSquashedExcept(0); @@ -157,8 +154,7 @@ describe('e2e_pending_note_hashes_contract', () => { await deployedContract.methods.insert_note.selector(), await deployedContract.methods.get_then_nullify_note.selector(), ) - .send({ from: owner }) - .wait(); + .send({ from: owner }); await expectNoteHashesSquashedExcept(0); await expectNullifiersSquashedExcept(0); @@ -182,8 +178,7 @@ describe('e2e_pending_note_hashes_contract', () => { await deployedContract.methods.insert_note.selector(), await deployedContract.methods.get_then_nullify_note.selector(), ) - .send({ from: owner }) - .wait(); + .send({ from: owner }); await expectNoteHashesSquashedExcept(1); await expectNullifiersSquashedExcept(0); @@ -207,8 +202,7 @@ describe('e2e_pending_note_hashes_contract', () => { await deployedContract.methods.insert_note_static_randomness.selector(), await deployedContract.methods.get_then_nullify_note.selector(), ) - .send({ from: owner }) - .wait(); + .send({ from: owner }); await expectNoteHashesSquashedExcept(1); await expectNullifiersSquashedExcept(0); @@ -227,7 +221,7 @@ describe('e2e_pending_note_hashes_contract', () => { // create persistent note const sender = owner; - await deployedContract.methods.insert_note(mintAmount, owner, sender).send({ from: owner }).wait(); + await deployedContract.methods.insert_note(mintAmount, owner, sender).send({ from: owner }); await expectNoteHashesSquashedExcept(1); // first TX just creates 1 persistent note await expectNullifiersSquashedExcept(0); @@ -242,10 +236,9 @@ describe('e2e_pending_note_hashes_contract', () => { await deployedContract.methods.insert_note.selector(), await deployedContract.methods.get_then_nullify_note.selector(), ) - .send({ from: owner }) - .wait(); + .send({ from: owner }); - await deployedContract.methods.get_note_zero_balance(owner).send({ from: owner }).wait(); + await deployedContract.methods.get_note_zero_balance(owner).send({ from: owner }); // second TX creates 1 note, but it is squashed! await expectNoteHashesSquashedExcept(0); @@ -265,7 +258,7 @@ describe('e2e_pending_note_hashes_contract', () => { const deployedContract = await deployContract(); const sender = owner; - await deployedContract.methods.insert_note(mintAmount, owner, sender).send({ from: owner }).wait(); + await deployedContract.methods.insert_note(mintAmount, owner, sender).send({ from: owner }); // There is a single new note hash. await expectNoteHashesSquashedExcept(1); @@ -279,8 +272,7 @@ describe('e2e_pending_note_hashes_contract', () => { await deployedContract.methods.dummy.selector(), await deployedContract.methods.get_then_nullify_note.selector(), ) - .send({ from: owner }) - .wait(); + .send({ from: owner }); // There is a single new nullifier. await expectNullifiersSquashedExcept(1); @@ -306,7 +298,6 @@ describe('e2e_pending_note_hashes_contract', () => { await deployedContract.methods .test_recursively_create_notes(recipients, Math.ceil(minToNeedReset / notesPerIteration)) - .send({ from: owner }) - .wait(); + .send({ from: owner }); }); }); diff --git a/yarn-project/end-to-end/src/e2e_phase_check.test.ts b/yarn-project/end-to-end/src/e2e_phase_check.test.ts index 3dcc238444d8..043e2b6b7569 100644 --- a/yarn-project/end-to-end/src/e2e_phase_check.test.ts +++ b/yarn-project/end-to-end/src/e2e_phase_check.test.ts @@ -35,7 +35,7 @@ describe('Phase check', () => { accounts: [defaultAccountAddress], } = await setup(1, { genesisPublicData: [genesisBalanceEntry] })); - contract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + contract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }); sponsoredFPC = await SponsoredFPCNoEndSetupContract.deploy(wallet).register({ contractAddressSalt: new Fr(SPONSORED_FPC_SALT), }); diff --git a/yarn-project/end-to-end/src/e2e_private_voting_contract.test.ts b/yarn-project/end-to-end/src/e2e_private_voting_contract.test.ts index 3ab60b98a1ef..86809063a08c 100644 --- a/yarn-project/end-to-end/src/e2e_private_voting_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_private_voting_contract.test.ts @@ -25,7 +25,7 @@ describe('e2e_voting_contract', () => { accounts: [owner], } = await setup(1)); - votingContract = await PrivateVotingContract.deploy(wallet, owner).send({ from: owner }).deployed(); + votingContract = await PrivateVotingContract.deploy(wallet, owner).send({ from: owner }); logger.info(`Counter contract deployed at ${votingContract.address}`); }); @@ -37,9 +37,9 @@ describe('e2e_voting_contract', () => { const candidate = new Fr(1); const electionId = { id: Fr.random() }; - await votingContract.methods.start_vote(electionId).send({ from: owner }).wait(); + await votingContract.methods.start_vote(electionId).send({ from: owner }); - await votingContract.methods.cast_vote(electionId, candidate).send({ from: owner }).wait(); + await votingContract.methods.cast_vote(electionId, candidate).send({ from: owner }); expect(await votingContract.methods.get_tally(electionId, candidate).simulate({ from: owner })).toBe(1n); // We try voting again, but our TX is dropped due to trying to emit duplicate nullifiers @@ -48,9 +48,9 @@ describe('e2e_voting_contract', () => { /Nullifier collision|duplicate.*nullifier/, ); // if we skip simulation, tx fails - await expect( - votingContract.methods.cast_vote(electionId, candidate).send({ from: owner }).wait(), - ).rejects.toThrow(TX_ERROR_EXISTING_NULLIFIER); + await expect(votingContract.methods.cast_vote(electionId, candidate).send({ from: owner })).rejects.toThrow( + TX_ERROR_EXISTING_NULLIFIER, + ); }); }); }); diff --git a/yarn-project/end-to-end/src/e2e_prover/full.test.ts b/yarn-project/end-to-end/src/e2e_prover/full.test.ts index deab60c10618..4e9d3110a29a 100644 --- a/yarn-project/end-to-end/src/e2e_prover/full.test.ts +++ b/yarn-project/end-to-end/src/e2e_prover/full.test.ts @@ -1,7 +1,8 @@ import type { AztecAddress } from '@aztec/aztec.js/addresses'; import { EthAddress } from '@aztec/aztec.js/addresses'; -import { waitForProven } from '@aztec/aztec.js/contracts'; -import { Tx, TxExecutionResult, TxReceipt } from '@aztec/aztec.js/tx'; +import { NO_WAIT, waitForProven } from '@aztec/aztec.js/contracts'; +import { waitForTx } from '@aztec/aztec.js/node'; +import { Tx, TxExecutionResult } from '@aztec/aztec.js/tx'; import { RollupContract } from '@aztec/ethereum/contracts'; import type { ExtendedViemWalletClient } from '@aztec/ethereum/types'; import { CheckpointNumber } from '@aztec/foundation/branded-types'; @@ -111,15 +112,13 @@ describe('full_prover', () => { // Sends the txs to node and awaits them to be mined separately, so they land on different blocks, // and we have more than one block in the epoch we end up proving logger.info(`Sending private tx`); - const txPrivate = privateProvenTx.send(); - await txPrivate.wait({ timeout: 300, interval: 10 }); + const txPrivateReceipt = await privateProvenTx.send({ wait: { timeout: 300, interval: 10 } }); logger.info(`Sending public tx`); - const txPublic = publicProvenTx.send(); - await txPublic.wait({ timeout: 300, interval: 10 }); + const txPublicReceipt = await publicProvenTx.send({ wait: { timeout: 300, interval: 10 } }); logger.info(`Both txs have been mined`); - const txs = [txPrivate, txPublic]; + const receipts = [txPrivateReceipt, txPublicReceipt]; // Flag the transfers on the token simulator tokenSim.transferPrivate(sender, recipient, privateSendAmount); @@ -137,8 +136,7 @@ describe('full_prover', () => { // And wait for the first pair of txs to be proven logger.info(`Awaiting proof for the previous epoch`); await Promise.all( - txs.map(async tx => { - const receipt = await tx.wait({ timeout: 300, interval: 10 }); + receipts.map(async receipt => { await waitForProven(t.aztecNode, receipt, { provenTimeout: 3000 }); }), ); @@ -203,8 +201,7 @@ describe('full_prover', () => { // and we have more than one block in the epoch we end up proving logger.info(`Sending private txs`); // First block, one private tx - const firstTxPrivate = firstPrivateProvenTx.send(); - await firstTxPrivate.wait({ timeout: 300, interval: 10 }); + const firstTxPrivateReceipt = await firstPrivateProvenTx.send({ wait: { timeout: 300, interval: 10 } }); // Create and send a set of 3 txs for the second block, // so we end up with three blocks and have merge and block-merge circuits @@ -216,16 +213,16 @@ describe('full_prover', () => { const secondBlockProvenTxs = await Promise.all( secondBlockInteractions.map(p => proveInteraction(provenWallet, p, { from: sender })), ); - const secondBlockTxs = await Promise.all(secondBlockProvenTxs.map(p => p.send())); - await Promise.all(secondBlockTxs.map(t => t.wait({ timeout: 300, interval: 10 }))); + const secondBlockReceipts = await Promise.all( + secondBlockProvenTxs.map(p => p.send({ wait: { timeout: 300, interval: 10 } })), + ); logger.info(`Sending public tx`); // Third block, one public tx - const txPublic = publicProvenTx.send(); - await txPublic.wait({ timeout: 300, interval: 10 }); + const txPublicReceipt = await publicProvenTx.send({ wait: { timeout: 300, interval: 10 } }); logger.info(`All txs have been mined`); - const txs = [firstTxPrivate, ...secondBlockTxs, txPublic]; + const receipts = [firstTxPrivateReceipt, ...secondBlockReceipts, txPublicReceipt]; // Flag the transfers on the token simulator tokenSim.transferPrivate(sender, recipient, privateSendAmount); @@ -241,8 +238,7 @@ describe('full_prover', () => { // And wait for the first pair of txs to be proven logger.info(`Awaiting proof for the previous epoch`); await Promise.all( - txs.map(async tx => { - const receipt = await tx.wait({ timeout: 300, interval: 10 }); + receipts.map(async receipt => { await waitForProven(t.aztecNode, receipt, { provenTimeout: 1500 }); }), ); @@ -288,12 +284,9 @@ describe('full_prover', () => { const privateInteraction = t.fakeProofsAsset.methods.transfer(recipient, 1n); const publicInteraction = t.fakeProofsAsset.methods.transfer_in_public(sender, recipient, 1n, 0); - const sentPrivateTx = privateInteraction.send({ from: sender }); - const sentPublicTx = publicInteraction.send({ from: sender }); - const results = await Promise.allSettled([ - sentPrivateTx.wait({ timeout: 10, interval: 0.1 }), - sentPublicTx.wait({ timeout: 10, interval: 0.1 }), + privateInteraction.send({ from: sender, wait: { timeout: 10, interval: 0.1 } }), + publicInteraction.send({ from: sender, wait: { timeout: 10, interval: 0.1 } }), ]); expect(String((results[0] as PromiseRejectedResult).reason)).toMatch(TX_ERROR_INVALID_PROOF); @@ -324,32 +317,27 @@ describe('full_prover', () => { // Spam node with invalid txs logger.info(`Submitting ${NUM_INVALID_TXS} invalid transactions to simulate a ddos attack`); const data = provenTx.data; - const invalidTxs = await Promise.all( - Array.from({ length: NUM_INVALID_TXS }, async (_, i) => { - // Use a random ChonkProof and alter the public tx data to generate a unique invalid tx hash - const invalidProvenTx = new ProvenTx( - aztecNode, - await Tx.create({ - data: new PrivateKernelTailCircuitPublicInputs( - data.constants, - data.gasUsed.add(new Gas(i + 1, 0)), - data.feePayer, - data.includeByTimestamp, - data.forPublic, - data.forRollup, - ), - chonkProof: ChonkProof.random(), - contractClassLogFields: provenTx.contractClassLogFields, - publicFunctionCalldata: provenTx.publicFunctionCalldata, - }), - [], - ); - return invalidProvenTx.send(); - }), - ); - - logger.info(`Sending proven tx`); - const validTx = provenTx.send(); + const txPromises = Array.from({ length: NUM_INVALID_TXS }, async (_, i) => { + // Use a random ChonkProof and alter the public tx data to generate a unique invalid tx hash + const invalidProvenTx = new ProvenTx( + aztecNode, + await Tx.create({ + data: new PrivateKernelTailCircuitPublicInputs( + data.constants, + data.gasUsed.add(new Gas(i + 1, 0)), + data.feePayer, + data.includeByTimestamp, + data.forPublic, + data.forRollup, + ), + chonkProof: ChonkProof.random(), + contractClassLogFields: provenTx.contractClassLogFields, + publicFunctionCalldata: provenTx.publicFunctionCalldata, + }), + [], + ); + return invalidProvenTx.send({ wait: NO_WAIT }); + }).concat([provenTx.send({ wait: NO_WAIT })]); // Add the valid tx at the end // Flag the valid transfer on the token simulator tokenSim.transferPrivate(sender, recipient, sendAmount); @@ -359,10 +347,10 @@ describe('full_prover', () => { logger.info(`Advancing from epoch ${epoch} to next epoch`); await cheatCodes.rollup.advanceToNextEpoch(); - const results = await Promise.allSettled([ - ...invalidTxs.map(tx => tx.wait({ timeout: 10, interval: 0.1, dontThrowOnRevert: true })), - validTx.wait({ timeout: 300, interval: 10 }), - ]); + const results = await Promise.allSettled(txPromises); + + const validTxHash = provenTx.getTxHash(); + await waitForTx(aztecNode, validTxHash, { timeout: 300, interval: 10 }); // Assert that the large influx of invalid txs are rejected and do not ddos the node for (let i = 0; i < NUM_INVALID_TXS; i++) { @@ -370,7 +358,7 @@ describe('full_prover', () => { } // Assert that the valid tx is successfully sent and mined - const validTxReceipt = (results[NUM_INVALID_TXS] as PromiseFulfilledResult).value; + const validTxReceipt = await aztecNode.getTxReceipt(validTxHash); expect(validTxReceipt.executionResult).toBe(TxExecutionResult.SUCCESS); logger.info(`Valid tx was mined and invalid txs were dropped by P2P node`); diff --git a/yarn-project/end-to-end/src/e2e_pruned_blocks.test.ts b/yarn-project/end-to-end/src/e2e_pruned_blocks.test.ts index 9562d40f6e40..65f1bd64dfad 100644 --- a/yarn-project/end-to-end/src/e2e_pruned_blocks.test.ts +++ b/yarn-project/end-to-end/src/e2e_pruned_blocks.test.ts @@ -53,7 +53,7 @@ describe('e2e_pruned_blocks', () => { aztecProofSubmissionEpochs: 1024, // effectively do not reorg })); - token = await TokenContract.deploy(wallet, admin, 'TEST', '$TST', 18).send({ from: admin }).deployed(); + token = await TokenContract.deploy(wallet, admin, 'TEST', '$TST', 18).send({ from: admin }); logger.info(`L2 token contract deployed at ${token.address}`); }); @@ -62,7 +62,7 @@ describe('e2e_pruned_blocks', () => { async function waitBlocks(blocks: number): Promise { logger.warn(`Awaiting ${blocks} blocks to be mined`); for (let i = 0; i < blocks; i++) { - await token.methods.private_get_name().send({ from: admin }).wait(); + await token.methods.private_get_name().send({ from: admin }); logger.warn(`Mined ${i + 1}/${blocks} blocks`); } } @@ -76,10 +76,7 @@ describe('e2e_pruned_blocks', () => { // mint transaction that the node will drop the block corresponding to the first mint, resulting in errors if PXE // tried to access any historical information related to it (which it shouldn't). - const firstMintReceipt = await token.methods - .mint_to_private(sender, MINT_AMOUNT / 2n) - .send({ from: admin }) - .wait(); + const firstMintReceipt = await token.methods.mint_to_private(sender, MINT_AMOUNT / 2n).send({ from: admin }); const firstMintTxEffect = await aztecNode.getTxEffect(firstMintReceipt.txHash); // mint_to_private should create just one new note with the minted amount @@ -120,12 +117,9 @@ describe('e2e_pruned_blocks', () => { // We've completed the setup we were interested in, and can now simply mint the second half of the amount, transfer // the full amount to the recipient (which will require the sender to discover and prove both the old and new notes) // and check that everything worked as expected. - await token.methods - .mint_to_private(sender, MINT_AMOUNT / 2n) - .send({ from: admin }) - .wait(); + await token.methods.mint_to_private(sender, MINT_AMOUNT / 2n).send({ from: admin }); - await token.methods.transfer(recipient, MINT_AMOUNT).send({ from: sender }).wait(); + await token.methods.transfer(recipient, MINT_AMOUNT).send({ from: sender }); expect(await token.methods.balance_of_private(recipient).simulate({ from: recipient })).toEqual(MINT_AMOUNT); expect(await token.methods.balance_of_private(sender).simulate({ from: sender })).toEqual(0n); diff --git a/yarn-project/end-to-end/src/e2e_public_testnet/e2e_public_testnet_transfer.test.ts b/yarn-project/end-to-end/src/e2e_public_testnet/e2e_public_testnet_transfer.test.ts index 9a0e3d295298..a5ed696875eb 100644 --- a/yarn-project/end-to-end/src/e2e_public_testnet/e2e_public_testnet_transfer.test.ts +++ b/yarn-project/end-to-end/src/e2e_public_testnet/e2e_public_testnet_transfer.test.ts @@ -60,22 +60,19 @@ describe(`deploys and transfers a private only token`, () => { ); const tokenInstance = await tokenDeployment.getInstance(); await wallet.registerContract(tokenInstance, PrivateTokenContract.artifact, tokenSecretKey); - const token = await tokenDeployment - .send({ - from: deployerAddress, - universalDeploy: true, - skipInstancePublication: true, - skipClassPublication: true, - skipInitialization: false, - }) - .deployed({ timeout: 300 }); + const token = await tokenDeployment.send({ + from: deployerAddress, + universalDeploy: true, + skipInstancePublication: true, + skipClassPublication: true, + skipInitialization: false, + }); logger.info(`Performing transfer.`); await token.methods .transfer(transferValue, deployerAddress, recipientAddress) - .send({ from: deployerAddress }) - .wait({ timeout: 300 }); + .send({ from: deployerAddress, wait: { timeout: 300 } }); logger.info(`Transfer completed`); diff --git a/yarn-project/end-to-end/src/e2e_sequencer/gov_proposal.parallel.test.ts b/yarn-project/end-to-end/src/e2e_sequencer/gov_proposal.parallel.test.ts index 6ae46eb6889c..b223bc086f1f 100644 --- a/yarn-project/end-to-end/src/e2e_sequencer/gov_proposal.parallel.test.ts +++ b/yarn-project/end-to-end/src/e2e_sequencer/gov_proposal.parallel.test.ts @@ -1,4 +1,6 @@ import type { AztecNodeService } from '@aztec/aztec-node'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; +import { waitForTx } from '@aztec/aztec.js/node'; import type { Wallet } from '@aztec/aztec.js/wallet'; import { CheatCodes } from '@aztec/aztec/testing'; import { HttpBlobClient } from '@aztec/blob-client/client'; @@ -7,7 +9,7 @@ import type { DeployAztecL1ContractsReturnType } from '@aztec/ethereum/deploy-az import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract'; import { ChainMonitor } from '@aztec/ethereum/test'; import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types'; -import { times } from '@aztec/foundation/collection'; +import { times, timesAsync } from '@aztec/foundation/collection'; import { SecretValue } from '@aztec/foundation/config'; import { Fr } from '@aztec/foundation/curves/bn254'; import { TimeoutError } from '@aztec/foundation/error'; @@ -110,7 +112,7 @@ describe('e2e_gov_proposal', () => { // Deploy a test contract to send msgs via the outbox, since this increases // gas cost of a proposal, which has triggered oog errors in the past. - testContract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + testContract = await TestContract.deploy(wallet).send({ from: defaultAccountAddress }); logger.warn(`Deployed test contract at ${testContract.address}`); await cheatCodes.rollup.advanceToEpoch(EpochNumber(4)); @@ -167,15 +169,15 @@ describe('e2e_gov_proposal', () => { // since we wait for the txs to be mined, and do so `roundDuration` times. // Simultaneously, we should be voting for the proposal in every slot. for (let i = 0; i < roundDuration; i++) { - const txs = times(TXS_PER_BLOCK, () => + const txHashes = await timesAsync(TXS_PER_BLOCK, () => testContract.methods .create_l2_to_l1_message_arbitrary_recipient_private(Fr.random(), EthAddress.random()) - .send({ from: defaultAccountAddress }), + .send({ from: defaultAccountAddress, wait: NO_WAIT }), ); await Promise.all( - txs.map(async (tx, j) => { - logger.info(`Waiting for tx ${i}-${j}: ${await tx.getTxHash()} to be mined`); - return tx.wait({ timeout: 2 * AZTEC_SLOT_DURATION + 2 }); + txHashes.map((hash, j) => { + logger.info(`Waiting for tx ${i}-${j}: ${hash} to be mined`); + return waitForTx(aztecNode!, hash, { timeout: AZTEC_SLOT_DURATION + 10 }); }), ); } @@ -197,8 +199,7 @@ describe('e2e_gov_proposal', () => { await expect(() => testContract.methods .create_l2_to_l1_message_arbitrary_recipient_private(Fr.random(), EthAddress.random()) - .send({ from: defaultAccountAddress }) - .wait({ timeout: AZTEC_SLOT_DURATION + 2 }), + .send({ from: defaultAccountAddress, wait: { timeout: AZTEC_SLOT_DURATION + 2 } }), ).rejects.toThrow(TimeoutError); logger.warn(`Test tx timed out as expected`); diff --git a/yarn-project/end-to-end/src/e2e_simple.test.ts b/yarn-project/end-to-end/src/e2e_simple.test.ts index 2e2780ed533f..9cc9c117c703 100644 --- a/yarn-project/end-to-end/src/e2e_simple.test.ts +++ b/yarn-project/end-to-end/src/e2e_simple.test.ts @@ -73,17 +73,17 @@ describe('e2e_simple', () => { const deployer = new ContractDeployer(artifact, wallet); const sender = ownerAddress; - const tx = deployer.deploy(ownerAddress, sender, 1).send({ + const txReceipt = await deployer.deploy(ownerAddress, sender, 1).send({ from: ownerAddress, contractAddressSalt: new Fr(BigInt(1)), skipClassPublication: true, skipInstancePublication: true, + wait: { returnReceipt: true }, }); - const receipt = await tx.wait(); - await waitForProven(aztecNode, receipt, { + await waitForProven(aztecNode, txReceipt, { provenTimeout: (config.aztecProofSubmissionEpochs + 1) * config.aztecEpochDuration * config.aztecSlotDuration, }); - expect(receipt.blockNumber).toBeDefined(); + expect(txReceipt.blockNumber).toBeDefined(); }); }); }); diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index 380257de481d..c95bdc2273af 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -33,7 +33,7 @@ describe('e2e_state_vars', () => { wallet, accounts: [defaultAccountAddress], } = await setup(1)); - contract = await StateVarsContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + contract = await StateVarsContract.deploy(wallet).send({ from: defaultAccountAddress }); }); afterAll(() => teardown()); @@ -43,14 +43,14 @@ describe('e2e_state_vars', () => { const s = await contract.methods.get_public_immutable().simulate({ from: defaultAccountAddress }); // Send the transaction and wait for it to be mined (wait function throws if the tx is not mined) - await contract.methods.match_public_immutable(s.account, s.value).send({ from: defaultAccountAddress }).wait(); + await contract.methods.match_public_immutable(s.account, s.value).send({ from: defaultAccountAddress }); }); it('initialize and read PublicImmutable', async () => { // Initializes the public immutable and then reads the value using a utility function // checking the return values: - await contract.methods.initialize_public_immutable(1).send({ from: defaultAccountAddress }).wait(); + await contract.methods.initialize_public_immutable(1).send({ from: defaultAccountAddress }); const read = await contract.methods.get_public_immutable().simulate({ from: defaultAccountAddress }); @@ -71,7 +71,7 @@ describe('e2e_state_vars', () => { expect(a).toEqual(c); expect(b).toEqual({ account: c.account, value: c.value + 1n }); - await contract.methods.match_public_immutable(c.account, c.value).send({ from: defaultAccountAddress }).wait(); + await contract.methods.match_public_immutable(c.account, c.value).send({ from: defaultAccountAddress }); }); it('public read of PublicImmutable', async () => { @@ -89,7 +89,7 @@ describe('e2e_state_vars', () => { expect(a).toEqual(c); expect(b).toEqual({ account: c.account, value: c.value + 1n }); - await contract.methods.match_public_immutable(c.account, c.value).send({ from: defaultAccountAddress }).wait(); + await contract.methods.match_public_immutable(c.account, c.value).send({ from: defaultAccountAddress }); }); it('public multiread of PublicImmutable', async () => { @@ -132,12 +132,11 @@ describe('e2e_state_vars', () => { .simulate({ from: defaultAccountAddress }), ).toEqual(false); // Send the transaction and wait for it to be mined (wait function throws if the tx is not mined) - const receipt = await contract.methods + const txReceipt = await contract.methods .initialize_private(RANDOMNESS, VALUE) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); - const txEffects = await aztecNode.getTxEffect(receipt.txHash); + const txEffects = await aztecNode.getTxEffect(txReceipt.txHash); // 1 for the tx, another for the initializer expect(txEffects?.data.nullifiers.length).toEqual(2); @@ -155,7 +154,7 @@ describe('e2e_state_vars', () => { .simulate({ from: defaultAccountAddress }), ).toEqual(true); await expect( - contract.methods.initialize_private(RANDOMNESS, VALUE).send({ from: defaultAccountAddress }).wait(), + contract.methods.initialize_private(RANDOMNESS, VALUE).send({ from: defaultAccountAddress }), ).rejects.toThrow(); expect( await contract.methods @@ -185,12 +184,11 @@ describe('e2e_state_vars', () => { const noteBefore = await contract.methods .get_private_mutable(defaultAccountAddress) .simulate({ from: defaultAccountAddress }); - const receipt = await contract.methods + const txReceipt = await contract.methods .update_private_mutable(RANDOMNESS, VALUE) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); - const txEffects = await aztecNode.getTxEffect(receipt.txHash); + const txEffects = await aztecNode.getTxEffect(txReceipt.txHash); expect(txEffects?.data.noteHashes.length).toEqual(1); // 1 for the tx, another for the nullifier of the previous note @@ -209,12 +207,11 @@ describe('e2e_state_vars', () => { .is_private_mutable_initialized(defaultAccountAddress) .simulate({ from: defaultAccountAddress }), ).toEqual(true); - const receipt = await contract.methods + const txReceipt = await contract.methods .update_private_mutable(RANDOMNESS + 2n, VALUE + 1n) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); - const txEffects = await aztecNode.getTxEffect(receipt.txHash); + const txEffects = await aztecNode.getTxEffect(txReceipt.txHash); expect(txEffects?.data.noteHashes.length).toEqual(1); // 1 for the tx, another for the nullifier of the previous note @@ -235,9 +232,9 @@ describe('e2e_state_vars', () => { const noteBefore = await contract.methods .get_private_mutable(defaultAccountAddress) .simulate({ from: defaultAccountAddress }); - const receipt = await contract.methods.increase_private_value().send({ from: defaultAccountAddress }).wait(); + const txReceipt = await contract.methods.increase_private_value().send({ from: defaultAccountAddress }); - const txEffects = await aztecNode.getTxEffect(receipt.txHash); + const txEffects = await aztecNode.getTxEffect(txReceipt.txHash); expect(txEffects?.data.noteHashes.length).toEqual(1); // 1 for the tx, another for the nullifier of the previous note @@ -264,12 +261,11 @@ describe('e2e_state_vars', () => { expect( await contract.methods.is_priv_imm_initialized(defaultAccountAddress).simulate({ from: defaultAccountAddress }), ).toEqual(false); - const receipt = await contract.methods + const txReceipt = await contract.methods .initialize_private_immutable(RANDOMNESS, VALUE) - .send({ from: defaultAccountAddress }) - .wait(); + .send({ from: defaultAccountAddress }); - const txEffects = await aztecNode.getTxEffect(receipt.txHash); + const txEffects = await aztecNode.getTxEffect(txReceipt.txHash); expect(txEffects?.data.noteHashes.length).toEqual(1); // 1 for the tx, another for the initializer @@ -284,7 +280,7 @@ describe('e2e_state_vars', () => { await contract.methods.is_priv_imm_initialized(defaultAccountAddress).simulate({ from: defaultAccountAddress }), ).toEqual(true); await expect( - contract.methods.initialize_private_immutable(RANDOMNESS, VALUE).send({ from: defaultAccountAddress }).wait(), + contract.methods.initialize_private_immutable(RANDOMNESS, VALUE).send({ from: defaultAccountAddress }), ).rejects.toThrow(); expect( await contract.methods.is_priv_imm_initialized(defaultAccountAddress).simulate({ from: defaultAccountAddress }), @@ -309,15 +305,15 @@ describe('e2e_state_vars', () => { const delay = async (blocks: number) => { for (let i = 0; i < blocks; i++) { - await authContract.methods.get_authorized().send({ from: defaultAccountAddress }).wait(); + await authContract.methods.get_authorized().send({ from: defaultAccountAddress }); } }; beforeAll(async () => { // We use the auth contract here because has a nice, clear, simple implementation of Delayed Public Mutable - authContract = await AuthContract.deploy(wallet, defaultAccountAddress) - .send({ from: defaultAccountAddress }) - .deployed(); + authContract = await AuthContract.deploy(wallet, defaultAccountAddress).send({ + from: defaultAccountAddress, + }); if (aztecSlotDuration !== 36) { throw new Error( @@ -331,7 +327,7 @@ describe('e2e_state_vars', () => { // We change the DelayedPublicMutable authorized delay here to 2 slots, this means that a change to the "authorized" // value can only be applied 2 slots after it is initiated, and thus read requests on a historical state without // an initiated change is valid for at least 2 slots. - await authContract.methods.set_authorized_delay(newDelay).send({ from: defaultAccountAddress }).wait(); + await authContract.methods.set_authorized_delay(newDelay).send({ from: defaultAccountAddress }); // Note: Because we are decreasing the delay, we must first wait for the (full previous delay - 1 slot). // Since the CHANGE_AUTHORIZED_DELAY in the Auth contract is equal to 5 slots we just wait for 4 blocks. diff --git a/yarn-project/end-to-end/src/e2e_static_calls.test.ts b/yarn-project/end-to-end/src/e2e_static_calls.test.ts index 8bc788d200e0..9576d39f7845 100644 --- a/yarn-project/end-to-end/src/e2e_static_calls.test.ts +++ b/yarn-project/end-to-end/src/e2e_static_calls.test.ts @@ -21,28 +21,28 @@ describe('e2e_static_calls', () => { accounts: [owner], } = await setup()); sender = owner; - parentContract = await StaticParentContract.deploy(wallet).send({ from: owner }).deployed(); - childContract = await StaticChildContract.deploy(wallet).send({ from: owner }).deployed(); + parentContract = await StaticParentContract.deploy(wallet).send({ from: owner }); + childContract = await StaticChildContract.deploy(wallet).send({ from: owner }); // We create a note in the set, such that later reads doesn't fail due to get_notes returning 0 notes - await childContract.methods.private_set_value(42n, owner, sender).send({ from: owner }).wait(); + await childContract.methods.private_set_value(42n, owner, sender).send({ from: owner }); }); afterAll(() => teardown()); describe('direct view calls to child', () => { it('performs legal private static calls', async () => { - await childContract.methods.private_get_value(42n, owner).send({ from: owner }).wait(); + await childContract.methods.private_get_value(42n, owner).send({ from: owner }); }); it('fails when performing non-static calls to poorly written static private functions', async () => { - await expect( - childContract.methods.private_illegal_set_value(42n, owner).send({ from: owner }).wait(), - ).rejects.toThrow(STATIC_CALL_STATE_MODIFICATION_ERROR); + await expect(childContract.methods.private_illegal_set_value(42n, owner).send({ from: owner })).rejects.toThrow( + STATIC_CALL_STATE_MODIFICATION_ERROR, + ); }); it('performs legal public static calls', async () => { - await childContract.methods.pub_get_value(42n).send({ from: owner }).wait(); + await childContract.methods.pub_get_value(42n).send({ from: owner }); }); it('fails when performing non-static calls to poorly written static public functions', async () => { @@ -60,14 +60,12 @@ describe('e2e_static_calls', () => { 42n, owner, ]) - .send({ from: owner }) - .wait(); + .send({ from: owner }); // Using the contract interface await parentContract.methods .private_get_value_from_child(childContract.address, 42n, owner) - .send({ from: owner }) - .wait(); + .send({ from: owner }); }); it('performs legal (nested) private to private static calls', async () => { @@ -76,26 +74,23 @@ describe('e2e_static_calls', () => { 42n, owner, ]) - .send({ from: owner }) - .wait(); + .send({ from: owner }); }); it('performs legal public to public static calls', async () => { // Using low level calls await parentContract.methods .public_static_call(childContract.address, await childContract.methods.pub_get_value.selector(), [42n]) - .send({ from: owner }) - .wait(); + .send({ from: owner }); // Using contract interface - await parentContract.methods.public_get_value_from_child(childContract.address, 42n).send({ from: owner }).wait(); + await parentContract.methods.public_get_value_from_child(childContract.address, 42n).send({ from: owner }); }); it('performs legal (nested) public to public static calls', async () => { await parentContract.methods .public_nested_static_call(childContract.address, await childContract.methods.pub_get_value.selector(), [42n]) - .send({ from: owner }) - .wait(); + .send({ from: owner }); }); it('performs legal enqueued public static calls', async () => { @@ -106,14 +101,10 @@ describe('e2e_static_calls', () => { await childContract.methods.pub_get_value.selector(), [42n], ) - .send({ from: owner }) - .wait(); + .send({ from: owner }); // Using contract interface - await parentContract.methods - .enqueue_public_get_value_from_child(childContract.address, 42) - .send({ from: owner }) - .wait(); + await parentContract.methods.enqueue_public_get_value_from_child(childContract.address, 42).send({ from: owner }); }); it('performs legal (nested) enqueued public static calls', async () => { @@ -123,8 +114,7 @@ describe('e2e_static_calls', () => { await childContract.methods.pub_get_value.selector(), [42n], ) - .send({ from: owner }) - .wait(); + .send({ from: owner }); }); it('fails when performing illegal private to private static calls', async () => { @@ -135,8 +125,7 @@ describe('e2e_static_calls', () => { owner, sender, ]) - .send({ from: owner }) - .wait(), + .send({ from: owner }), ).rejects.toThrow(STATIC_CALL_STATE_MODIFICATION_ERROR); }); @@ -147,8 +136,7 @@ describe('e2e_static_calls', () => { 42n, owner, ]) - .send({ from: owner }) - .wait(), + .send({ from: owner }), ).rejects.toThrow(STATIC_CONTEXT_ASSERTION_ERROR); }); @@ -160,8 +148,7 @@ describe('e2e_static_calls', () => { await childContract.methods.private_set_value.selector(), [42n, owner, sender], ) - .send({ from: owner }) - .wait(), + .send({ from: owner }), ).rejects.toThrow(STATIC_CALL_STATE_MODIFICATION_ERROR); }); diff --git a/yarn-project/end-to-end/src/e2e_synching.test.ts b/yarn-project/end-to-end/src/e2e_synching.test.ts index b775278731d6..23efdac1334d 100644 --- a/yarn-project/end-to-end/src/e2e_synching.test.ts +++ b/yarn-project/end-to-end/src/e2e_synching.test.ts @@ -34,9 +34,10 @@ import type { InitialAccountData } from '@aztec/accounts/testing'; import { createArchiver } from '@aztec/archiver'; import { AztecNodeService } from '@aztec/aztec-node'; -import { BatchCall, type Contract } from '@aztec/aztec.js/contracts'; +import { BatchCall, type Contract, NO_WAIT } from '@aztec/aztec.js/contracts'; import { Fr, GrumpkinScalar } from '@aztec/aztec.js/fields'; import { type Logger, createLogger } from '@aztec/aztec.js/log'; +import { waitForTx } from '@aztec/aztec.js/node'; import { AnvilTestWatcher } from '@aztec/aztec/testing'; import { createBlobClientWithFileStores } from '@aztec/blob-client/client'; import { EpochCache } from '@aztec/epoch-cache'; @@ -152,7 +153,7 @@ class TestVariant { await Promise.all( managers.map(async m => { const deployMethod = await m.getDeployMethod(); - return deployMethod.send({ from: AztecAddress.ZERO }).wait(); + return deployMethod.send({ from: AztecAddress.ZERO }); }), ); return accounts.map(acc => acc.address); @@ -175,8 +176,7 @@ class TestVariant { accounts.map(acc => this.token.methods .mint_to_public(acc.address, MINT_AMOUNT) - .send({ from: acc.address }) - .wait({ timeout: 600 }), + .send({ from: acc.address, wait: { timeout: 600 } }), ), ); } @@ -193,7 +193,7 @@ class TestVariant { } if (this.txComplexity == TxComplexity.Deployment) { - const txs = []; + const txHashes = []; for (let i = 0; i < this.txCount; i++) { const deployAccount = this.accounts[i % this.accounts.length]; const accountManager = await this.wallet.createSchnorrAccount( @@ -203,38 +203,41 @@ class TestVariant { ); this.contractAddresses.push(accountManager.address); const deployMethod = await accountManager.getDeployMethod(); - const tx = deployMethod.send({ + const txHash = await deployMethod.send({ from: deployAccount, skipClassPublication: true, skipInstancePublication: true, + wait: NO_WAIT, }); - txs.push(tx); + txHashes.push(txHash); } - return txs; + return txHashes; } else if (this.txComplexity == TxComplexity.PrivateTransfer) { // To do a private transfer we need to a lot of accounts that all have funds. - const txs = []; + const txHashes = []; for (let i = 0; i < this.txCount; i++) { const recipient = this.accounts[(i + 1) % this.txCount]; const tk = TokenContract.at(this.token.address, this.wallet); - txs.push(tk.methods.transfer(recipient, 1n).send({ from: this.accounts[i] })); + txHashes.push(await tk.methods.transfer(recipient, 1n).send({ from: this.accounts[i], wait: NO_WAIT })); } - return txs; + return txHashes; } else if (this.txComplexity == TxComplexity.PublicTransfer) { // Public transfer is simpler, we can just transfer to our-selves there. - const txs = []; + const txHashes = []; for (let i = 0; i < this.txCount; i++) { const sender = this.accounts[i]; const recipient = this.accounts[(i + 1) % this.txCount]; const tk = TokenContract.at(this.token.address, this.wallet); - txs.push(tk.methods.transfer_in_public(sender, recipient, 1n, 0).send({ from: sender })); + txHashes.push( + await tk.methods.transfer_in_public(sender, recipient, 1n, 0).send({ from: sender, wait: NO_WAIT }), + ); } - return txs; + return txHashes; } else if (this.txComplexity == TxComplexity.Spam) { // This one is slightly more painful. We need to setup a new contract that writes // a metric ton of state changes. - const txs = []; + const txHashes = []; for (let i = 0; i < this.txCount; i++) { const batch = new BatchCall(this.wallet, [ this.spam.methods.spam(this.seed, 16, false), @@ -244,9 +247,9 @@ class TestVariant { ]); this.seed += 100n; - txs.push(batch.send({ from: this.accounts[0] })); + txHashes.push(await batch.send({ from: this.accounts[0], wait: NO_WAIT })); } - return txs; + return txHashes; } else { throw new Error('Incorrect tx complexity'); } @@ -337,10 +340,10 @@ describe('e2e_synching', () => { variant.setWallet(wallet); // Deploy a token, such that we could use it - const token = await TokenContract.deploy(wallet, defaultAccountAddress, 'TestToken', 'TST', 18n) - .send({ from: defaultAccountAddress }) - .deployed(); - const spam = await SpamContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(); + const token = await TokenContract.deploy(wallet, defaultAccountAddress, 'TestToken', 'TST', 18n).send({ + from: defaultAccountAddress, + }); + const spam = await SpamContract.deploy(wallet).send({ from: defaultAccountAddress }); variant.setToken(token); variant.setSpam(spam); @@ -354,9 +357,10 @@ describe('e2e_synching', () => { await variant.setup(accountsToBeDeployed); for (let i = 0; i < variant.blockCount; i++) { - const txs = await variant.createAndSendTxs(); - if (txs) { - await Promise.all(txs.map(tx => tx.wait({ timeout: 1200 }))); + const txHashPromises = await variant.createAndSendTxs(); + if (txHashPromises) { + const txHashes = await Promise.all(txHashPromises); + await Promise.all(txHashes.map(txHash => waitForTx(aztecNode, txHash, { timeout: 1200 }))); } await cheatCodes.rollup.markAsProven(); } @@ -545,17 +549,15 @@ describe('e2e_synching', () => { const defaultAccountAddress = (await variant.deployAccounts(opts.initialFundedAccounts!.slice(0, 1)))[0]; contracts.push( - await TokenContract.deploy(wallet, defaultAccountAddress, 'TestToken', 'TST', 18n) - .send({ from: defaultAccountAddress }) - .deployed(), - ); - contracts.push( - await SchnorrHardcodedAccountContract.deploy(wallet).send({ from: defaultAccountAddress }).deployed(), + await TokenContract.deploy(wallet, defaultAccountAddress, 'TestToken', 'TST', 18n).send({ + from: defaultAccountAddress, + }), ); + contracts.push(await SchnorrHardcodedAccountContract.deploy(wallet).send({ from: defaultAccountAddress })); contracts.push( - await TokenContract.deploy(wallet, defaultAccountAddress, 'TestToken', 'TST', 18n) - .send({ from: defaultAccountAddress }) - .deployed(), + await TokenContract.deploy(wallet, defaultAccountAddress, 'TestToken', 'TST', 18n).send({ + from: defaultAccountAddress, + }), ); await watcher.stop(); @@ -697,8 +699,8 @@ describe('e2e_synching', () => { const blockBefore = await aztecNode.getBlock(await aztecNode.getBlockNumber()); sequencer?.updateConfig({ minTxsPerBlock: variant.txCount, maxTxsPerBlock: variant.txCount }); - const txs = await variant.createAndSendTxs(); - await Promise.all(txs.map(tx => tx.wait({ timeout: 1200 }))); + const txHashes = await variant.createAndSendTxs(); + await Promise.all(txHashes.map(txHash => waitForTx(aztecNode, txHash, { timeout: 1200 }))); const blockAfter = await aztecNode.getBlock(await aztecNode.getBlockNumber()); @@ -756,8 +758,8 @@ describe('e2e_synching', () => { const blockBefore = await aztecNode.getBlock(await aztecNode.getBlockNumber()); sequencer?.updateConfig({ minTxsPerBlock: variant.txCount, maxTxsPerBlock: variant.txCount }); - const txs = await variant.createAndSendTxs(); - await Promise.all(txs.map(tx => tx.wait({ timeout: 1200 }))); + const txHashes = await variant.createAndSendTxs(); + await Promise.all(txHashes.map(txHash => waitForTx(aztecNode, txHash, { timeout: 1200 }))); const blockAfter = await aztecNode.getBlock(await aztecNode.getBlockNumber()); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/access_control.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/access_control.test.ts index 3a249e8bedac..cab2d394475f 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/access_control.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/access_control.test.ts @@ -17,17 +17,17 @@ describe('e2e_token_contract access control', () => { }); it('Set admin', async () => { - await t.asset.methods.set_admin(t.account1Address).send({ from: t.adminAddress }).wait(); + await t.asset.methods.set_admin(t.account1Address).send({ from: t.adminAddress }); expect(await t.asset.methods.get_admin().simulate({ from: t.adminAddress })).toBe(t.account1Address.toBigInt()); }); it('Add minter as admin', async () => { - await t.asset.methods.set_minter(t.account1Address, true).send({ from: t.account1Address }).wait(); + await t.asset.methods.set_minter(t.account1Address, true).send({ from: t.account1Address }); expect(await t.asset.methods.is_minter(t.account1Address).simulate({ from: t.adminAddress })).toBe(true); }); it('Revoke minter as admin', async () => { - await t.asset.methods.set_minter(t.account1Address, false).send({ from: t.account1Address }).wait(); + await t.asset.methods.set_minter(t.account1Address, false).send({ from: t.account1Address }); expect(await t.asset.methods.is_minter(t.account1Address).simulate({ from: t.adminAddress })).toBe(false); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/burn.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/burn.test.ts index 91481b2868f3..3e5d2d7a4432 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/burn.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/burn.test.ts @@ -29,7 +29,7 @@ describe('e2e_token_contract burn', () => { const balance0 = await asset.methods.balance_of_public(adminAddress).simulate({ from: adminAddress }); const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.burn_public(adminAddress, amount, 0).send({ from: adminAddress }).wait(); + await asset.methods.burn_public(adminAddress, amount, 0).send({ from: adminAddress }); tokenSim.burnPublic(adminAddress, amount); }); @@ -47,9 +47,9 @@ describe('e2e_token_contract burn', () => { { caller: account1Address, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); - await action.send({ from: account1Address }).wait(); + await action.send({ from: account1Address }); tokenSim.burnPublic(adminAddress, amount); @@ -102,7 +102,7 @@ describe('e2e_token_contract burn', () => { { caller: account1Address, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); await expect(action.simulate({ from: account1Address })).rejects.toThrow(U128_UNDERFLOW_ERROR); }); @@ -120,7 +120,7 @@ describe('e2e_token_contract burn', () => { { caller: adminAddress, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); await expect( asset.methods.burn_public(adminAddress, amount, authwitNonce).simulate({ from: account1Address }), @@ -134,7 +134,7 @@ describe('e2e_token_contract burn', () => { const balance0 = await asset.methods.balance_of_private(adminAddress).simulate({ from: adminAddress }); const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.burn_private(adminAddress, amount, 0).send({ from: adminAddress }).wait(); + await asset.methods.burn_private(adminAddress, amount, 0).send({ from: adminAddress }); tokenSim.burnPrivate(adminAddress, amount); }); @@ -153,15 +153,15 @@ describe('e2e_token_contract burn', () => { await asset.methods .burn_private(adminAddress, amount, authwitNonce) - .send({ from: account1Address, authWitnesses: [witness] }) - .wait(); + .send({ from: account1Address, authWitnesses: [witness] }); tokenSim.burnPrivate(adminAddress, amount); // Perform the transfer again, should fail - const txReplay = asset.methods - .burn_private(adminAddress, amount, authwitNonce) - .send({ from: account1Address, authWitnesses: [witness] }); - await expect(txReplay.wait()).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); + await expect( + asset.methods + .burn_private(adminAddress, amount, authwitNonce) + .send({ from: account1Address, authWitnesses: [witness] }), + ).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); }); describe('failure cases', () => { diff --git a/yarn-project/end-to-end/src/e2e_token_contract/minting.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/minting.test.ts index 472b41547fd5..bc6a1251a833 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/minting.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/minting.test.ts @@ -22,7 +22,7 @@ describe('e2e_token_contract minting', () => { describe('Public', () => { it('as minter', async () => { const amount = 10000n; - await asset.methods.mint_to_public(adminAddress, amount).send({ from: adminAddress }).wait(); + await asset.methods.mint_to_public(adminAddress, amount).send({ from: adminAddress }); tokenSim.mintPublic(adminAddress, amount); expect(await asset.methods.balance_of_public(adminAddress).simulate({ from: adminAddress })).toEqual( @@ -58,7 +58,7 @@ describe('e2e_token_contract minting', () => { describe('Private', () => { it('as minter', async () => { const amount = 10000n; - await asset.methods.mint_to_private(adminAddress, amount).send({ from: adminAddress }).wait(); + await asset.methods.mint_to_private(adminAddress, amount).send({ from: adminAddress }); tokenSim.mintPrivate(adminAddress, amount); expect(await asset.methods.balance_of_private(adminAddress).simulate({ from: adminAddress })).toEqual( diff --git a/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts index 03de858af594..a986ab6799ba 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts @@ -23,8 +23,8 @@ describe('e2e_token_contract private transfer recursion', () => { // itself to consume them all (since it retrieves 2 notes on the first pass and 8 in each subsequent pass). const totalNotes = 16; const totalBalance = await mintNotes(wallet, adminAddress, adminAddress, asset, Array(totalNotes).fill(10n)); - const tx = await asset.methods.transfer(account1Address, totalBalance).send({ from: adminAddress }).wait(); - const txEffects = await node.getTxEffect(tx.txHash); + const txReceipt = await asset.methods.transfer(account1Address, totalBalance).send({ from: adminAddress }); + const txEffects = await node.getTxEffect(txReceipt.txHash); // We should have nullified all notes, plus an extra nullifier for the transaction and one for the event commitment. expect(txEffects!.data.nullifiers.length).toBe(totalNotes + 1 + 1); @@ -33,8 +33,8 @@ describe('e2e_token_contract private transfer recursion', () => { const events = await wallet.getPrivateEvents(TokenContract.events.Transfer, { contractAddress: asset.address, - fromBlock: BlockNumber(tx.blockNumber!), - toBlock: BlockNumber(tx.blockNumber! + 1), + fromBlock: BlockNumber(txReceipt.blockNumber!), + toBlock: BlockNumber(txReceipt.blockNumber! + 1), scopes: [account1Address], }); @@ -45,9 +45,9 @@ describe('e2e_token_contract private transfer recursion', () => { amount: totalBalance, }, metadata: { - l2BlockNumber: BlockNumber(tx.blockNumber!), - l2BlockHash: tx.blockHash, - txHash: tx.txHash, + l2BlockNumber: BlockNumber(txReceipt.blockNumber!), + l2BlockHash: txReceipt.blockHash, + txHash: txReceipt.txHash, }, }); }); @@ -59,8 +59,8 @@ describe('e2e_token_contract private transfer recursion', () => { const totalBalance = await mintNotes(wallet, adminAddress, adminAddress, asset, noteAmounts); const toSend = totalBalance - expectedChange; - const tx = await asset.methods.transfer(account1Address, toSend).send({ from: adminAddress }).wait(); - const txEffects = await node.getTxEffect(tx.txHash); + const txReceipt = await asset.methods.transfer(account1Address, toSend).send({ from: adminAddress }); + const txEffects = await node.getTxEffect(txReceipt.txHash); // We should have nullified all notes, plus an extra nullifier for the transaction and one for the event commitment. expect(txEffects!.data.nullifiers.length).toBe(noteAmounts.length + 1 + 1); @@ -72,8 +72,8 @@ describe('e2e_token_contract private transfer recursion', () => { const events = await wallet.getPrivateEvents(TokenContract.events.Transfer, { contractAddress: asset.address, - fromBlock: BlockNumber(tx.blockNumber!), - toBlock: BlockNumber(tx.blockNumber! + 1), + fromBlock: BlockNumber(txReceipt.blockNumber!), + toBlock: BlockNumber(txReceipt.blockNumber! + 1), scopes: [account1Address], }); @@ -84,9 +84,9 @@ describe('e2e_token_contract private transfer recursion', () => { amount: toSend, }, metadata: { - l2BlockNumber: BlockNumber(tx.blockNumber!), - l2BlockHash: tx.blockHash, - txHash: tx.txHash, + l2BlockNumber: BlockNumber(txReceipt.blockNumber!), + l2BlockHash: txReceipt.blockHash, + txHash: txReceipt.txHash, }, }); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/token_contract_test.ts b/yarn-project/end-to-end/src/e2e_token_contract/token_contract_test.ts index cc8c3d544ec6..3ab11d635292 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/token_contract_test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/token_contract_test.ts @@ -85,13 +85,11 @@ export class TokenContractTest { TokenContractTest.TOKEN_NAME, TokenContractTest.TOKEN_SYMBOL, TokenContractTest.TOKEN_DECIMALS, - ) - .send({ from: this.adminAddress }) - .deployed(); + ).send({ from: this.adminAddress }); this.logger.verbose(`Token deployed to ${this.asset.address}`); this.logger.verbose(`Deploying bad account...`); - this.badAccount = await InvalidAccountContract.deploy(this.wallet).send({ from: this.adminAddress }).deployed(); + this.badAccount = await InvalidAccountContract.deploy(this.wallet).send({ from: this.adminAddress }); this.logger.verbose(`Deployed to ${this.badAccount.address}.`); this.tokenSim = new TokenSimulator(this.asset, this.wallet, this.adminAddress, this.logger, [ @@ -130,7 +128,7 @@ export class TokenContractTest { const amount = 10000n; this.logger.verbose(`Minting ${amount} publicly...`); - await asset.methods.mint_to_public(adminAddress, amount).send({ from: adminAddress }).wait(); + await asset.methods.mint_to_public(adminAddress, amount).send({ from: adminAddress }); tokenSim.mintPublic(adminAddress, amount); const publicBalance = await asset.methods.balance_of_public(adminAddress).simulate({ from: adminAddress }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts index cef22988d725..d801532f8478 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts @@ -28,13 +28,13 @@ describe('e2e_token_contract transfer private', () => { const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - const tx = await asset.methods.transfer(account1Address, amount).send({ from: adminAddress }).wait(); + const txReceipt = await asset.methods.transfer(account1Address, amount).send({ from: adminAddress }); tokenSim.transferPrivate(adminAddress, account1Address, amount); const events = await wallet.getPrivateEvents(TokenContract.events.Transfer, { contractAddress: asset.address, - fromBlock: tx.blockNumber!, - toBlock: BlockNumber(tx.blockNumber! + 1), + fromBlock: txReceipt.blockNumber!, + toBlock: BlockNumber(txReceipt.blockNumber! + 1), scopes: [account1Address], }); @@ -45,9 +45,9 @@ describe('e2e_token_contract transfer private', () => { amount: amount, }, metadata: { - l2BlockNumber: tx.blockNumber, - l2BlockHash: tx.blockHash, - txHash: tx.txHash, + l2BlockNumber: txReceipt.blockNumber, + l2BlockHash: txReceipt.blockHash, + txHash: txReceipt.txHash, }, }); }); @@ -59,7 +59,7 @@ describe('e2e_token_contract transfer private', () => { const nonDeployed = await CompleteAddress.random(); - await asset.methods.transfer(nonDeployed.address, amount).send({ from: adminAddress }).wait(); + await asset.methods.transfer(nonDeployed.address, amount).send({ from: adminAddress }); // Add the account as balance we should change, but since we don't have the key, // we cannot decrypt, and instead we simulate a transfer to address(0) @@ -71,7 +71,7 @@ describe('e2e_token_contract transfer private', () => { const balance0 = await asset.methods.balance_of_private(adminAddress).simulate({ from: adminAddress }); const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.transfer(adminAddress, amount).send({ from: adminAddress }).wait(); + await asset.methods.transfer(adminAddress, amount).send({ from: adminAddress }); tokenSim.transferPrivate(adminAddress, adminAddress, amount); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_private.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_private.test.ts index e0012bbe6f76..d14b5efa7acf 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_private.test.ts @@ -35,14 +35,15 @@ describe('e2e_token_contract transfer private', () => { const witness = await wallet.createAuthWit(adminAddress, { caller: account1Address, action }); // Perform the transfer - await action.send({ from: account1Address, authWitnesses: [witness] }).wait(); + await action.send({ from: account1Address, authWitnesses: [witness] }); tokenSim.transferPrivate(adminAddress, account1Address, amount); // Perform the transfer again, should fail - const txReplay = asset.methods - .transfer_in_private(adminAddress, account1Address, amount, authwitNonce) - .send({ from: account1Address, authWitnesses: [witness] }); - await expect(txReplay.wait()).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); + await expect( + asset.methods + .transfer_in_private(adminAddress, account1Address, amount, authwitNonce) + .send({ from: account1Address, authWitnesses: [witness] }), + ).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); }); describe('failure cases', () => { @@ -144,13 +145,14 @@ describe('e2e_token_contract transfer private', () => { const witness = await wallet.createAuthWit(adminAddress, intent); const innerHash = await computeInnerAuthWitHashFromAction(account1Address, action); - await asset.methods.cancel_authwit(innerHash).send({ from: adminAddress }).wait(); + await asset.methods.cancel_authwit(innerHash).send({ from: adminAddress }); // Perform the transfer, should fail because nullifier already emitted - const txCancelledAuthwit = asset.methods - .transfer_in_private(adminAddress, account1Address, amount, authwitNonce) - .send({ from: account1Address, authWitnesses: [witness] }); - await expect(txCancelledAuthwit.wait()).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); + await expect( + asset.methods + .transfer_in_private(adminAddress, account1Address, amount, authwitNonce) + .send({ from: account1Address, authWitnesses: [witness] }), + ).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); }); it('transfer on behalf of other, invalid verify_private_authwit on "from"', async () => { diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_public.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_public.test.ts index 1c3df67965c9..689a99d61bc9 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_public.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_public.test.ts @@ -46,10 +46,7 @@ describe('e2e_token_contract transfer public', () => { const balance0 = await asset.methods.balance_of_public(adminAddress).simulate({ from: adminAddress }); const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods - .transfer_in_public(adminAddress, account1Address, amount, 0) - .send({ from: adminAddress }) - .wait(); + await asset.methods.transfer_in_public(adminAddress, account1Address, amount, 0).send({ from: adminAddress }); tokenSim.transferPublic(adminAddress, account1Address, amount); }); @@ -58,7 +55,7 @@ describe('e2e_token_contract transfer public', () => { const balance = await asset.methods.balance_of_public(adminAddress).simulate({ from: adminAddress }); const amount = balance / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.transfer_in_public(adminAddress, adminAddress, amount, 0).send({ from: adminAddress }).wait(); + await asset.methods.transfer_in_public(adminAddress, adminAddress, amount, 0).send({ from: adminAddress }); tokenSim.transferPublic(adminAddress, adminAddress, amount); }); @@ -76,10 +73,10 @@ describe('e2e_token_contract transfer public', () => { { caller: account1Address, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); // Perform the transfer - await action.send({ from: account1Address }).wait(); + await action.send({ from: account1Address }); tokenSim.transferPublic(adminAddress, account1Address, amount); @@ -139,7 +136,7 @@ describe('e2e_token_contract transfer public', () => { const intent = { caller: account1Address, action }; // We need to compute the message we want to sign and add it to the wallet as approved const validateActionInteraction = await wallet.setPublicAuthWit(adminAddress, intent, true); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); const witness = await wallet.createAuthWit(adminAddress, { caller: account1Address, action }); @@ -169,7 +166,7 @@ describe('e2e_token_contract transfer public', () => { { caller: adminAddress, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); // Perform the transfer await expect(action.simulate({ from: account1Address })).rejects.toThrow(/unauthorized/); @@ -194,7 +191,7 @@ describe('e2e_token_contract transfer public', () => { { caller: adminAddress, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); // Perform the transfer await expect(action.simulate({ from: account1Address })).rejects.toThrow(/unauthorized/); @@ -218,14 +215,14 @@ describe('e2e_token_contract transfer public', () => { { caller: account1Address, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); const cancelActionInteraction = await wallet.setPublicAuthWit( adminAddress, { caller: account1Address, action }, false, ); - await cancelActionInteraction.send().wait(); + await cancelActionInteraction.send(); await expect( asset.methods @@ -247,14 +244,14 @@ describe('e2e_token_contract transfer public', () => { { caller: account1Address, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); const cancelActionInteraction = await wallet.setPublicAuthWit( adminAddress, { caller: account1Address, action }, false, ); - await cancelActionInteraction.send().wait(); + await cancelActionInteraction.send(); await expect(action.simulate({ from: account1Address })).rejects.toThrow(/unauthorized/); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_private.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_private.test.ts index 88350c985e9b..051ba9370fce 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_private.test.ts @@ -26,7 +26,7 @@ describe('e2e_token_contract transfer_to_private', () => { const amount = balancePub / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.transfer_to_private(adminAddress, amount).send({ from: adminAddress }).wait(); + await asset.methods.transfer_to_private(adminAddress, amount).send({ from: adminAddress }); // Check that the result matches token sim tokenSim.transferToPrivate(adminAddress, adminAddress, amount); @@ -38,7 +38,7 @@ describe('e2e_token_contract transfer_to_private', () => { const amount = balancePub / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.transfer_to_private(account1Address, amount).send({ from: adminAddress }).wait(); + await asset.methods.transfer_to_private(account1Address, amount).send({ from: adminAddress }); // Check that the result matches token sim tokenSim.transferToPrivate(adminAddress, account1Address, amount); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_public.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_public.test.ts index 0e867f10402a..eef942576bd4 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_public.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_public.test.ts @@ -29,7 +29,7 @@ describe('e2e_token_contract transfer_to_public', () => { const amount = balancePriv / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.transfer_to_public(adminAddress, adminAddress, amount, 0).send({ from: adminAddress }).wait(); + await asset.methods.transfer_to_public(adminAddress, adminAddress, amount, 0).send({ from: adminAddress }); tokenSim.transferToPublic(adminAddress, adminAddress, amount); }); @@ -47,14 +47,15 @@ describe('e2e_token_contract transfer_to_public', () => { // But doing it in two actions to show the flow. const witness = await wallet.createAuthWit(adminAddress, { caller: account1Address, action }); - await action.send({ from: account1Address, authWitnesses: [witness] }).wait(); + await action.send({ from: account1Address, authWitnesses: [witness] }); tokenSim.transferToPublic(adminAddress, account1Address, amount); // Perform the transfer again, should fail - const txReplay = asset.methods - .transfer_to_public(adminAddress, account1Address, amount, authwitNonce) - .send({ from: account1Address, authWitnesses: [witness] }); - await expect(txReplay.wait()).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); + await expect( + asset.methods + .transfer_to_public(adminAddress, account1Address, amount, authwitNonce) + .send({ from: account1Address, authWitnesses: [witness] }), + ).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); }); describe('failure cases', () => { diff --git a/yarn-project/end-to-end/src/fixtures/e2e_prover_test.ts b/yarn-project/end-to-end/src/fixtures/e2e_prover_test.ts index a314df4421d9..9c7fa631fdee 100644 --- a/yarn-project/end-to-end/src/fixtures/e2e_prover_test.ts +++ b/yarn-project/end-to-end/src/fixtures/e2e_prover_test.ts @@ -114,9 +114,7 @@ export class FullProverTest { FullProverTest.TOKEN_NAME, FullProverTest.TOKEN_SYMBOL, FullProverTest.TOKEN_DECIMALS, - ) - .send({ from: this.accounts[0] }) - .wait(); + ).send({ from: this.accounts[0], wait: { returnReceipt: true } }); this.logger.verbose(`Token deployed to ${asset.address}`); this.fakeProofsAsset = asset; @@ -308,13 +306,10 @@ export class FullProverTest { const publicAmount = 10000n; this.logger.verbose(`Minting ${privateAmount + publicAmount} publicly...`); - await asset.methods - .mint_to_public(accounts[0], privateAmount + publicAmount) - .send({ from: accounts[0] }) - .wait(); + await asset.methods.mint_to_public(accounts[0], privateAmount + publicAmount).send({ from: accounts[0] }); this.logger.verbose(`Transferring ${privateAmount} to private...`); - await asset.methods.transfer_to_private(accounts[0], privateAmount).send({ from: accounts[0] }).wait(); + await asset.methods.transfer_to_private(accounts[0], privateAmount).send({ from: accounts[0] }); this.logger.info(`Minting complete`); diff --git a/yarn-project/end-to-end/src/fixtures/setup.ts b/yarn-project/end-to-end/src/fixtures/setup.ts index 8304b0e96e03..9a2f4c14f2cd 100644 --- a/yarn-project/end-to-end/src/fixtures/setup.ts +++ b/yarn-project/end-to-end/src/fixtures/setup.ts @@ -629,7 +629,7 @@ export async function setup( `${numberOfAccounts} accounts are being deployed. Reliably progressing past genesis by setting minTxsPerBlock to 1 and waiting for the accounts to be deployed`, ); const accountsData = initialFundedAccounts.slice(0, numberOfAccounts); - const accountManagers = await deployFundedSchnorrAccounts(wallet, aztecNodeService, accountsData); + const accountManagers = await deployFundedSchnorrAccounts(wallet, accountsData); accounts = accountManagers.map(accountManager => accountManager.address); } else if (needsEmptyBlock) { logger.info('No accounts are being deployed, waiting for an empty block 1 to be mined'); @@ -921,13 +921,11 @@ export async function ensureAccountContractsPublished(wallet: Wallet, accountsTo ).map(contractMetadata => contractMetadata.instance); const contractClass = await getContractClassFromArtifact(SchnorrAccountContractArtifact); if (!(await wallet.getContractClassMetadata(contractClass.id)).isContractClassPubliclyRegistered) { - await (await publishContractClass(wallet, SchnorrAccountContractArtifact)) - .send({ from: accountsToDeploy[0] }) - .wait(); + await (await publishContractClass(wallet, SchnorrAccountContractArtifact)).send({ from: accountsToDeploy[0] }); } const requests = instances.map(instance => publishInstance(wallet, instance!)); const batch = new BatchCall(wallet, requests); - await batch.send({ from: accountsToDeploy[0] }).wait(); + await batch.send({ from: accountsToDeploy[0] }); } /** @@ -951,12 +949,10 @@ export const deployAccounts = deployedAccounts[i].signingKey, ); const deployMethod = await accountManager.getDeployMethod(); - await deployMethod - .send({ - from: AztecAddress.ZERO, - skipClassPublication: i !== 0, // Publish the contract class at most once. - }) - .wait(); + await deployMethod.send({ + from: AztecAddress.ZERO, + skipClassPublication: i !== 0, // Publish the contract class at most once. + }); } return { deployedAccounts }; @@ -986,7 +982,7 @@ export async function publicDeployAccounts( const batch = new BatchCall(wallet, calls); - const txReceipt = await batch.send({ from: accountsToDeploy[0] }).wait(); + const txReceipt = await batch.send({ from: accountsToDeploy[0] }); if (waitUntilProven) { if (!node) { throw new Error('Need to provide an AztecNode to wait for proven.'); diff --git a/yarn-project/end-to-end/src/fixtures/token_utils.ts b/yarn-project/end-to-end/src/fixtures/token_utils.ts index 93ba9431f403..47e9c67e78ba 100644 --- a/yarn-project/end-to-end/src/fixtures/token_utils.ts +++ b/yarn-project/end-to-end/src/fixtures/token_utils.ts @@ -6,9 +6,10 @@ import { TokenContract } from '@aztec/noir-contracts.js/Token'; export async function deployToken(wallet: Wallet, admin: AztecAddress, initialAdminBalance: bigint, logger: Logger) { logger.info(`Deploying Token contract...`); - const { contract, instance } = await TokenContract.deploy(wallet, admin, 'TokenName', 'TokenSymbol', 18) - .send({ from: admin }) - .wait(); + const { contract, instance } = await TokenContract.deploy(wallet, admin, 'TokenName', 'TokenSymbol', 18).send({ + from: admin, + wait: { returnReceipt: true }, + }); if (initialAdminBalance > 0n) { await mintTokensToPrivate(contract, admin, admin, initialAdminBalance); @@ -25,7 +26,7 @@ export async function mintTokensToPrivate( recipient: AztecAddress, amount: bigint, ) { - await token.methods.mint_to_private(recipient, amount).send({ from: minter }).wait(); + await token.methods.mint_to_private(recipient, amount).send({ from: minter }); } export async function expectTokenBalance( @@ -55,7 +56,7 @@ export async function mintNotes( for (let mintedNotes = 0; mintedNotes < noteAmounts.length; mintedNotes += notesPerIteration) { const toMint = noteAmounts.slice(mintedNotes, mintedNotes + notesPerIteration); const actions = toMint.map(amt => asset.methods.mint_to_private(recipient, amt)); - await new BatchCall(wallet, actions).send({ from: minter }).wait(); + await new BatchCall(wallet, actions).send({ from: minter }); } return noteAmounts.reduce((prev, curr) => prev + curr, 0n); diff --git a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts index a80b23a737e7..793f49317b2c 100644 --- a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts +++ b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts @@ -67,19 +67,19 @@ describe('guides/writing_an_account_contract', () => { if (await account.hasInitializer()) { // The account has no funds. Use a funded wallet to pay for the fee for the deployment. const deployMethod = await account.getDeployMethod(); - await deployMethod.send({ from: fundedAccount }).wait(); + await deployMethod.send({ from: fundedAccount }); } const address = account.address; logger.info(`Deployed account contract at ${address}`); - const token = await TokenContract.deploy(wallet, fundedAccount, 'TokenName', 'TokenSymbol', 18) - .send({ from: fundedAccount }) - .deployed(); + const token = await TokenContract.deploy(wallet, fundedAccount, 'TokenName', 'TokenSymbol', 18).send({ + from: fundedAccount, + }); logger.info(`Deployed token contract at ${token.address}`); const mintAmount = 50n; - await token.methods.mint_to_private(address, mintAmount).send({ from: fundedAccount }).wait(); + await token.methods.mint_to_private(address, mintAmount).send({ from: fundedAccount }); const balance = await token.methods.balance_of_private(address).simulate({ from: address }); logger.info(`Balance of wallet is now ${balance}`); @@ -94,7 +94,7 @@ describe('guides/writing_an_account_contract', () => { }); try { - await token.methods.mint_to_public(address, 200).send({ from: wrongAccount.address }).wait(); + await token.methods.mint_to_public(address, 200).send({ from: wrongAccount.address }); } catch (err) { logger.info(`Failed to send tx: ${err}`); } diff --git a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts index 16bc581f394b..be4564b2a67d 100644 --- a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts @@ -73,14 +73,10 @@ export async function deployAndInitializeTokenAndBridgeContracts( }); // deploy l2 token - const token = await TokenContract.deploy(wallet, owner, 'TokenName', 'TokenSymbol', 18) - .send({ from: owner }) - .deployed(); + const token = await TokenContract.deploy(wallet, owner, 'TokenName', 'TokenSymbol', 18).send({ from: owner }); // deploy l2 token bridge and attach to the portal - const bridge = await TokenBridgeContract.deploy(wallet, token.address, tokenPortalAddress) - .send({ from: owner }) - .deployed(); + const bridge = await TokenBridgeContract.deploy(wallet, token.address, tokenPortalAddress).send({ from: owner }); if ((await token.methods.get_admin().simulate({ from: owner })) !== owner.toBigInt()) { throw new Error(`Token admin is not ${owner}`); @@ -91,7 +87,7 @@ export async function deployAndInitializeTokenAndBridgeContracts( } // make the bridge a minter on the token: - await token.methods.set_minter(bridge.address, true).send({ from: owner }).wait(); + await token.methods.set_minter(bridge.address, true).send({ from: owner }); if ((await token.methods.is_minter(bridge.address).simulate({ from: owner })) === 1n) { throw new Error(`Bridge is not a minter`); } @@ -234,7 +230,7 @@ export class CrossChainTestHarness { async mintTokensPublicOnL2(amount: bigint) { this.logger.info('Minting tokens on L2 publicly'); - await this.l2Token.methods.mint_to_public(this.ownerAddress, amount).send({ from: this.ownerAddress }).wait(); + await this.l2Token.methods.mint_to_public(this.ownerAddress, amount).send({ from: this.ownerAddress }); } async mintTokensPrivateOnL2(amount: bigint) { @@ -245,8 +241,7 @@ export class CrossChainTestHarness { // send a transfer tx to force through rollup with the message included await this.l2Token.methods .transfer_in_public(this.ownerAddress, receiverAddress, transferAmount, 0) - .send({ from: this.ownerAddress }) - .wait(); + .send({ from: this.ownerAddress }); } async consumeMessageOnAztecAndMintPrivately( @@ -256,8 +251,7 @@ export class CrossChainTestHarness { const { recipient, claimAmount, claimSecret: secretForL2MessageConsumption, messageLeafIndex } = claim; await this.l2Bridge.methods .claim_private(recipient, claimAmount, secretForL2MessageConsumption, messageLeafIndex) - .send({ from: this.ownerAddress }) - .wait(); + .send({ from: this.ownerAddress }); } async consumeMessageOnAztecAndMintPublicly( @@ -267,8 +261,7 @@ export class CrossChainTestHarness { const { claimAmount, claimSecret, messageLeafIndex } = claim; await this.l2Bridge.methods .claim_public(this.ownerAddress, claimAmount, claimSecret, messageLeafIndex) - .send({ from: this.ownerAddress }) - .wait(); + .send({ from: this.ownerAddress }); } async withdrawPrivateFromAztecToL1( @@ -278,8 +271,7 @@ export class CrossChainTestHarness { ): Promise { const withdrawReceipt = await this.l2Bridge.methods .exit_to_l1_private(this.l2Token.address, this.ethAccount, withdrawAmount, EthAddress.ZERO, authwitNonce) - .send({ authWitnesses: [authWitness], from: this.ownerAddress }) - .wait(); + .send({ authWitnesses: [authWitness], from: this.ownerAddress }); return withdrawReceipt; } @@ -287,8 +279,7 @@ export class CrossChainTestHarness { async withdrawPublicFromAztecToL1(withdrawAmount: bigint, authwitNonce: Fr = Fr.ZERO): Promise { const withdrawReceipt = await this.l2Bridge.methods .exit_to_l1_public(this.ethAccount, withdrawAmount, EthAddress.ZERO, authwitNonce) - .send({ from: this.ownerAddress }) - .wait(); + .send({ from: this.ownerAddress }); return withdrawReceipt; } @@ -332,18 +323,14 @@ export class CrossChainTestHarness { async transferToPrivateOnL2(shieldAmount: bigint) { this.logger.info('Transferring to private on L2'); - await this.l2Token.methods - .transfer_to_private(this.ownerAddress, shieldAmount) - .send({ from: this.ownerAddress }) - .wait(); + await this.l2Token.methods.transfer_to_private(this.ownerAddress, shieldAmount).send({ from: this.ownerAddress }); } async transferToPublicOnL2(amount: bigint, authwitNonce = Fr.ZERO) { this.logger.info('Transferring tokens to public'); await this.l2Token.methods .transfer_to_public(this.ownerAddress, this.ownerAddress, amount, authwitNonce) - .send({ from: this.ownerAddress }) - .wait(); + .send({ from: this.ownerAddress }); } /** diff --git a/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts b/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts index 28255d9d2d05..4062e7def159 100644 --- a/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts @@ -127,7 +127,7 @@ export class GasBridgingTestHarness implements IGasBridgingTestHarness { async consumeMessageOnAztecAndClaimPrivately(owner: AztecAddress, claimer: AztecAddress, claim: L2AmountClaim) { this.logger.info('Consuming messages on L2 Privately'); const { claimAmount, claimSecret, messageLeafIndex } = claim; - await this.feeJuice.methods.claim(owner, claimAmount, claimSecret, messageLeafIndex).send({ from: claimer }).wait(); + await this.feeJuice.methods.claim(owner, claimAmount, claimSecret, messageLeafIndex).send({ from: claimer }); } async getL2PublicBalanceOf(owner: AztecAddress) { diff --git a/yarn-project/end-to-end/src/shared/submit-transactions.ts b/yarn-project/end-to-end/src/shared/submit-transactions.ts index 833db441777b..87b75335878e 100644 --- a/yarn-project/end-to-end/src/shared/submit-transactions.ts +++ b/yarn-project/end-to-end/src/shared/submit-transactions.ts @@ -1,8 +1,8 @@ import { AztecAddress } from '@aztec/aztec.js/addresses'; -import type { SentTx } from '@aztec/aztec.js/contracts'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { Fr, GrumpkinScalar } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; -import { TxStatus } from '@aztec/aztec.js/tx'; +import { TxHash, type TxReceipt, TxStatus } from '@aztec/aztec.js/tx'; import { times } from '@aztec/foundation/collection'; import type { TestWallet } from '@aztec/test-wallet/server'; @@ -12,21 +12,20 @@ export const submitTxsTo = async ( submitter: AztecAddress, numTxs: number, logger: Logger, -): Promise => { - const txs: SentTx[] = []; +): Promise => { + const txHashes: TxHash[] = []; await Promise.all( times(numTxs, async () => { const accountManager = await wallet.createSchnorrAccount(Fr.random(), Fr.random(), GrumpkinScalar.random()); const deployMethod = await accountManager.getDeployMethod(); - const tx = deployMethod.send({ from: submitter }); - const txHash = await tx.getTxHash(); + const txHash = await deployMethod.send({ from: submitter, wait: NO_WAIT }); logger.info(`Tx sent with hash ${txHash}`); - const receipt = await tx.getReceipt(); + const receipt: TxReceipt = await wallet.getTxReceipt(txHash); expect(receipt.status).toBe(TxStatus.PENDING); logger.info(`Receipt received for ${txHash}`); - txs.push(tx); + txHashes.push(txHash); }), ); - return txs; + return txHashes; }; diff --git a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts index c4ad2a0bf42d..6e65a7a52618 100644 --- a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts +++ b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts @@ -130,9 +130,7 @@ export const uniswapL1L2TestSuite = ( client: l1Client, }); // deploy l2 uniswap contract and attach to portal - uniswapL2Contract = await UniswapContract.deploy(wallet, uniswapPortalAddress) - .send({ from: ownerAddress }) - .deployed(); + uniswapL2Contract = await UniswapContract.deploy(wallet, uniswapPortalAddress).send({ from: ownerAddress }); const registryAddress = (await aztecNode.getNodeInfo()).l1ContractAddresses.registryAddress; @@ -209,8 +207,7 @@ export const uniswapL1L2TestSuite = ( secretHashForDepositingSwappedDai, ownerEthAddress, ) - .send({ from: ownerAddress, authWitnesses: [transferToPublicAuhtwit] }) - .wait(); + .send({ from: ownerAddress, authWitnesses: [transferToPublicAuhtwit] }); const swapPrivateFunction = 'swap_private(address,uint256,uint24,address,uint256,bytes32,address)'; const swapPrivateContent = sha256ToField([ @@ -428,10 +425,10 @@ export const uniswapL1L2TestSuite = ( // ownerEthAddress, // nonceForSwap, // ); - // await ownerWallet.setPublicAuthWit({ caller: sponsorAddress, action }, true).send().wait(); + // await ownerWallet.setPublicAuthWit({ caller: sponsorAddress, action }, true).send(); // // 4.2 Call swap_public from user2 on behalf of owner - // const uniswapL2Interaction = await action.send().wait(); + // const uniswapL2Interaction = await action.send(); // const swapPublicContent = sha256ToField([ // Buffer.from( @@ -649,8 +646,7 @@ export const uniswapL1L2TestSuite = ( Fr.random(), ownerEthAddress, ) - .send({ from: ownerAddress, authWitnesses: [transferToPublicAuthwith] }) - .wait(), + .send({ from: ownerAddress, authWitnesses: [transferToPublicAuthwith] }), ).rejects.toThrow('Assertion failed: input_asset address is not the same as seen in the bridge contract'); }); @@ -675,7 +671,7 @@ export const uniswapL1L2TestSuite = ( }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); // No approval to call `swap` but should work even without it: const [_, secretHashForDepositingSwappedDai] = await generateClaimSecret(); @@ -694,8 +690,7 @@ export const uniswapL1L2TestSuite = ( ownerEthAddress, Fr.ZERO, // nonce for swap -> doesn't matter ) - .send({ from: ownerAddress }) - .wait(); + .send({ from: ownerAddress }); // check weth balance of owner on L2 (we first bridged `wethAmountToBridge` into L2 and now withdrew it!) await wethCrossChainHarness.expectPublicBalanceOnL2(ownerAddress, 0n); }); @@ -725,7 +720,7 @@ export const uniswapL1L2TestSuite = ( { caller: approvedUser, action }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); await expect(action.simulate({ from: sponsorAddress })).rejects.toThrow(/unauthorized/); }); @@ -747,7 +742,7 @@ export const uniswapL1L2TestSuite = ( }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); await expect( uniswapL2Contract.methods @@ -804,8 +799,7 @@ export const uniswapL1L2TestSuite = ( secretHashForDepositingSwappedDai, ownerEthAddress, ) - .send({ from: ownerAddress, authWitnesses: [transferToPublicAuhtwit] }) - .wait(); + .send({ from: ownerAddress, authWitnesses: [transferToPublicAuhtwit] }); const swapPrivateContent = sha256ToField([ Buffer.from( @@ -918,7 +912,7 @@ export const uniswapL1L2TestSuite = ( }, true, ); - await validateActionInteraction.send().wait(); + await validateActionInteraction.send(); // Call swap_public on L2 const secretHashForDepositingSwappedDai = Fr.random(); @@ -936,8 +930,7 @@ export const uniswapL1L2TestSuite = ( ownerEthAddress, Fr.ZERO, ) - .send({ from: ownerAddress }) - .wait(); + .send({ from: ownerAddress }); const swapPublicContent = sha256ToField([ Buffer.from( diff --git a/yarn-project/end-to-end/src/spartan/1tps.test.ts b/yarn-project/end-to-end/src/spartan/1tps.test.ts index 972a6754be8b..43604c1f6093 100644 --- a/yarn-project/end-to-end/src/spartan/1tps.test.ts +++ b/yarn-project/end-to-end/src/spartan/1tps.test.ts @@ -1,9 +1,11 @@ // TODO(#11825) finalize (probably once we have nightly tests setup for GKE) & enable in bootstrap.sh -import { SentTx } from '@aztec/aztec.js/contracts'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee'; +import { type AztecNode, waitForTx } from '@aztec/aztec.js/node'; import { readFieldCompressedString } from '@aztec/aztec.js/utils'; import { createLogger } from '@aztec/foundation/log'; import { sleep } from '@aztec/foundation/sleep'; +import type { TxHash } from '@aztec/stdlib/tx'; import type { ProvenTx, TestWallet } from '@aztec/test-wallet/server'; import { proveInteraction } from '@aztec/test-wallet/server'; @@ -28,6 +30,7 @@ describe('token transfer test', () => { let testAccounts: TestAccounts; let wallet: TestWallet; + let aztecNode: AztecNode; const endpoints: ServiceEndpoint[] = []; let cleanup: undefined | (() => Promise); @@ -44,11 +47,12 @@ describe('token transfer test', () => { const { wallet: _wallet, - aztecNode, + aztecNode: _aztecNode, cleanup: _cleanup, } = await createWalletAndAztecNodeClient(rpcUrl, config.REAL_VERIFIER, logger); cleanup = _cleanup; wallet = _wallet; + aztecNode = _aztecNode; // Setup wallets testAccounts = await deploySponsoredTestAccountsWithTokens(wallet, aztecNode, MINT_AMOUNT, logger); @@ -97,7 +101,7 @@ describe('token transfer test', () => { ), ); - const sentTxs: SentTx[] = []; + const txHashes: TxHash[] = []; // dump all txs at requested TPS const TPS = 1; @@ -106,8 +110,8 @@ describe('token transfer test', () => { const start = performance.now(); const chunk = txs.splice(0, TPS); - sentTxs.push(...chunk.map(tx => tx.send())); - logger.info(`Sent txs: [${(await Promise.all(chunk.map(tx => tx.getTxHash()))).map(h => h.toString())}]`); + txHashes.push(...(await Promise.all(chunk.map(tx => tx.send({ wait: NO_WAIT }))))); + logger.info(`Sent txs: [${txHashes.map(h => h.toString())}]`); const end = performance.now(); const delta = end - start; @@ -117,9 +121,8 @@ describe('token transfer test', () => { } await Promise.all( - sentTxs.map(async sentTx => { - await sentTx.wait({ timeout: 600 }); - const receipt = await sentTx.getReceipt(); + txHashes.map(async hash => { + const receipt = await waitForTx(aztecNode, hash, { timeout: 600 }); logger.info(`tx ${receipt.txHash} included in block: ${receipt.blockNumber}`); }), ); diff --git a/yarn-project/end-to-end/src/spartan/4epochs.test.ts b/yarn-project/end-to-end/src/spartan/4epochs.test.ts index cda306a81f32..871c1e74b763 100644 --- a/yarn-project/end-to-end/src/spartan/4epochs.test.ts +++ b/yarn-project/end-to-end/src/spartan/4epochs.test.ts @@ -118,7 +118,7 @@ describe('token transfer test', () => { logger.info(`Proved ${provenTxs.length} in round ${i} of ${ROUNDS}`); - await Promise.all(provenTxs.map(t => t.send().wait({ timeout: 600 }))); + await Promise.all(provenTxs.map(t => t.send({ wait: { timeout: 600 } }))); const currentSlot = await rollupCheatCodes.getSlot(); expect(BigInt(currentSlot)).toBeLessThanOrEqual(BigInt(startSlot) + i + MAX_MISSED_SLOTS); const startEpoch = await rollupCheatCodes.getEpoch(); diff --git a/yarn-project/end-to-end/src/spartan/mempool_limit.test.ts b/yarn-project/end-to-end/src/spartan/mempool_limit.test.ts index 9a20815c1e72..07debae74331 100644 --- a/yarn-project/end-to-end/src/spartan/mempool_limit.test.ts +++ b/yarn-project/end-to-end/src/spartan/mempool_limit.test.ts @@ -141,8 +141,7 @@ describe('mempool limiter test', () => { await testAccounts.tokenContract.methods .mint_to_public(from, mintAmountPerWallet) - .send({ from: testAccounts.tokenAdminAddress, fee: { paymentMethod: sponsor } }) - .wait({ timeout: 600 }); + .send({ from: testAccounts.tokenAdminAddress, fee: { paymentMethod: sponsor }, wait: { timeout: 600 } }); walletPool.push({ wallet: extraWallet, from }); } @@ -204,12 +203,12 @@ describe('mempool limiter test', () => { const tx = Tx.fromBuffer(sampleTx.toBuffer()); // this only works on unproven networks, otherwise this will fail verification tx.data.forPublic!.nonRevertibleAccumulatedData.nullifiers[0] = Fr.random(); - tx.getTxHash(); + tx.txHash; return tx; }); await asyncPool(CONCURRENCY, txs, tx => node.sendTx(tx)); - const receipts = await asyncPool(CONCURRENCY, txs, async tx => await node.getTxReceipt(tx.getTxHash())); + const receipts = await asyncPool(CONCURRENCY, txs, async tx => await node.getTxReceipt(tx.txHash)); const pending = receipts.reduce((count, receipt) => (receipt.status === TxStatus.PENDING ? count + 1 : count), 0); expect(pending).toBeLessThanOrEqual(TX_MEMPOOL_LIMIT); return; @@ -259,7 +258,7 @@ describe('mempool limiter test', () => { ); await asyncPool(CONCURRENCY, provenTxs, tx => node.sendTx(tx)); - const txHashes = provenTxs.map(tx => tx.getTxHash()); + const txHashes = provenTxs.map(tx => tx.txHash); // Eviction can be async relative to the RPC send, so poll until the pool is under the cap await retryUntil( diff --git a/yarn-project/end-to-end/src/spartan/n_tps.test.ts b/yarn-project/end-to-end/src/spartan/n_tps.test.ts index 75f313a23786..a426304e8f32 100644 --- a/yarn-project/end-to-end/src/spartan/n_tps.test.ts +++ b/yarn-project/end-to-end/src/spartan/n_tps.test.ts @@ -1,4 +1,4 @@ -import type { SentTx } from '@aztec/aztec.js/contracts'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee'; import { type AztecNode, createAztecNodeClient } from '@aztec/aztec.js/node'; import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants'; @@ -11,7 +11,7 @@ import { sleep } from '@aztec/foundation/sleep'; import { BenchmarkingContract } from '@aztec/noir-test-contracts.js/Benchmarking'; import { GasFees } from '@aztec/stdlib/gas'; import { TopicType } from '@aztec/stdlib/p2p'; -import { Tx } from '@aztec/stdlib/tx'; +import { Tx, TxHash } from '@aztec/stdlib/tx'; import { ProvenTx, TestWallet, proveInteraction } from '@aztec/test-wallet/server'; import { jest } from '@jest/globals'; @@ -277,9 +277,10 @@ describe('sustained N TPS test', () => { logger.info('Deploying benchmark contract...'); const sponsor = new SponsoredFeePaymentMethod(await getSponsoredFPCAddress()); - benchmarkContract = await BenchmarkingContract.deploy(localTestAccounts[0].wallet) - .send({ from: localTestAccounts[0].recipientAddress, fee: { paymentMethod: sponsor } }) - .deployed(); + benchmarkContract = await BenchmarkingContract.deploy(localTestAccounts[0].wallet).send({ + from: localTestAccounts[0].recipientAddress, + fee: { paymentMethod: sponsor }, + }); logger.info('Benchmark contract deployed', { address: benchmarkContract.address.toString() }); logger.info('Installing chaos mesh chart', { @@ -349,7 +350,8 @@ describe('sustained N TPS test', () => { ? submitProven(wallet, backgroundTxPriorityFee) : submitUnproven(wallet, backgroundTxPriorityFee)); - return tx.send(); + const txHash = await tx.send({ wait: NO_WAIT }); + return txHash.toString(); }; let highValueTxs = 0; @@ -364,30 +366,27 @@ describe('sustained N TPS test', () => { metrics.recordSentTx(tx, `high_value_${highValueTps}tps`); - return tx.send(); + const txHash = await tx.send({ wait: NO_WAIT }); + return txHash.toString(); }; const abortController = new AbortController(); sendTxsAtTps(logger, abortController.signal, lowValueWallets, lowValueTps, lowValueSendTx); - const sentTxs = sendTxsAtTps(logger, abortController.signal, highValueWallets, highValueTps, highValueSendTx); + const sentTxHashes = sendTxsAtTps(logger, abortController.signal, highValueWallets, highValueTps, highValueSendTx); await sleep(TEST_DURATION_SECONDS * 1000); abortController.abort(); logger.info('Stopped transaction senders', { lowValueTxs, highValueTxs, - highValueSent: sentTxs.length, + highValueSent: sentTxHashes.length, }); - const results: { success: boolean; tx: SentTx; error?: any }[] = []; - const waitForTx = async (sentTx: SentTx, txName: string) => { + const results: { success: boolean; txHash: string; error?: any }[] = []; + const waitForTx = async (txHash: string, txName: string) => { try { - const receipt = await sentTx.wait({ - timeout: 1200, - interval: 1, - ignoreDroppedReceiptsFor: 2, - }); + const receipt = await aztecNode.getTxReceipt(TxHash.fromString(txHash)); if (receipt.blockNumber) { logger.info(`${txName} included in block ${receipt.blockNumber}`); logger.debug(`${txName} receipt details`, { @@ -400,27 +399,26 @@ describe('sustained N TPS test', () => { } else { throw new Error('Invalid txReceipt: ' + JSON.stringify(receipt)); } - results.push({ success: true, tx: sentTx }); + results.push({ success: true, txHash }); } catch (error) { - const txHash = await sentTx.getTxHash().catch(() => undefined); - const receipt = txHash ? await sentTx.getReceipt().catch(() => undefined) : undefined; + const receipt = await aztecNode.getTxReceipt(TxHash.fromString(txHash)).catch(() => undefined); logger.error(`${txName} was not included: ${error}`, { - txHash: txHash?.toString(), + txHash, receiptStatus: receipt?.status, receiptBlockNumber: receipt?.blockNumber, receiptError: receipt?.error, }); - results.push({ success: false, tx: sentTx, error }); + results.push({ success: false, txHash, error }); } }; let index = 0; - logger.info('Waiting for high-value txs to be mined', { totalSent: sentTxs.length }); - while (sentTxs.length > 0) { - const chunk = sentTxs.splice(0, 10); - await Promise.all(chunk.map((tx, idx) => waitForTx(tx, `highValueTx_${idx + 1 + index}`))); + logger.info('Waiting for high-value txs to be mined', { totalSent: sentTxHashes.length }); + while (sentTxHashes.length > 0) { + const chunk = sentTxHashes.splice(0, 10); + await Promise.all(chunk.map((txHash, idx) => waitForTx(txHash, `highValueTx_${idx + 1 + index}`))); index += chunk.length; - logger.debug('Processed tx batch', { processed: index, remaining: sentTxs.length }); + logger.debug('Processed tx batch', { processed: index, remaining: sentTxHashes.length }); } // Count successes and failures @@ -446,14 +444,14 @@ function sendTxsAtTps( signal: AbortSignal, wallets: TestWallet[], targetTps: number, - sendTx: (wallet: TestWallet) => Promise, -): SentTx[] { + sendTx: (wallet: TestWallet) => Promise, +): string[] { const promiseCount = Math.ceil(targetTps); if (wallets.length < promiseCount) { throw new Error('Not enough wallets to achieve desired TPS'); } - const txs: SentTx[] = []; + const txHashes: string[] = []; const targetTpsPerPromise = targetTps / promiseCount; logger.info('Starting TPS sender', { targetTps, @@ -471,14 +469,13 @@ function sendTxsAtTps( const wallet = wallets[i]; const start = performance.now(); // ms - let tx: SentTx; try { - tx = await sendTx(wallet); + const txHash = await sendTx(wallet); + txHashes.push(txHash); } catch (err) { logger.error('Failed to submit tx', { walletIndex: i, err }); throw err; } - txs.push(tx); const dt = performance.now() - start; // ms const tps = 1000 / dt; // We just sent one tx. Calculate TPS. Note: we have to convert ms to s @@ -512,7 +509,7 @@ function sendTxsAtTps( } }; - return txs; + return txHashes; } async function cloneTx(tx: ProvenTx, priorityFee: GasFees): Promise { diff --git a/yarn-project/end-to-end/src/spartan/reqresp_effectiveness.test.ts b/yarn-project/end-to-end/src/spartan/reqresp_effectiveness.test.ts index dfae839fe6ac..aac0cf2e3605 100644 --- a/yarn-project/end-to-end/src/spartan/reqresp_effectiveness.test.ts +++ b/yarn-project/end-to-end/src/spartan/reqresp_effectiveness.test.ts @@ -1,8 +1,10 @@ +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee'; -import type { AztecNode } from '@aztec/aztec.js/node'; +import { type AztecNode, waitForTx } from '@aztec/aztec.js/node'; import { readFieldCompressedString } from '@aztec/aztec.js/utils'; import { createLogger } from '@aztec/foundation/log'; import { sleep } from '@aztec/foundation/sleep'; +import type { TxHash } from '@aztec/stdlib/tx'; import { ProvenTx, TestWallet, proveInteraction } from '@aztec/test-wallet/server'; import { jest } from '@jest/globals'; @@ -104,16 +106,18 @@ describe('reqresp effectiveness under tx drop', () => { }); } - const sends: Array<{ sentAt: number; promise: ReturnType }[]> = []; + const sends: Array<{ sentAt: number; txHash: TxHash }[]> = []; let sentSoFar = 0; for (let sec = 0; sec < TEST_DURATION_SECONDS; sec++) { const secondStart = Date.now(); const batch = txs.splice(0, TARGET_TPS); - const sentBatch = batch.map((tx, i) => { - const sent = tx.send(); - logger.info(`p=${probability} sec ${sec + 1}: sent tx ${sentSoFar + i + 1}`); - return { sentAt: Date.now(), promise: sent }; - }); + const sentBatch = await Promise.all( + batch.map(async (tx, i) => { + const txHash = await tx.send({ wait: NO_WAIT }); + logger.info(`p=${probability} sec ${sec + 1}: sent tx ${sentSoFar + i + 1}`); + return { sentAt: Date.now(), txHash }; + }), + ); sends.push(sentBatch); sentSoFar += batch.length; const elapsed = Date.now() - secondStart; @@ -127,10 +131,13 @@ describe('reqresp effectiveness under tx drop', () => { let included = 0; let failed = 0; await Promise.all( - sends.flat().map(async ({ sentAt, promise }, idx) => { + sends.flat().map(async ({ sentAt, txHash }, idx) => { try { - await promise.wait({ timeout: 180, interval: 1, ignoreDroppedReceiptsFor: 2 }); - const receipt = await promise.getReceipt(); + const receipt = await waitForTx(aztecNode, txHash, { + timeout: 180, + interval: 1, + ignoreDroppedReceiptsFor: 2, + }); if (receipt?.blockNumber !== undefined) { included++; const l = Date.now() - sentAt; diff --git a/yarn-project/end-to-end/src/spartan/setup_test_wallets.ts b/yarn-project/end-to-end/src/spartan/setup_test_wallets.ts index 221f66b6d1ae..94357c99f09e 100644 --- a/yarn-project/end-to-end/src/spartan/setup_test_wallets.ts +++ b/yarn-project/end-to-end/src/spartan/setup_test_wallets.ts @@ -1,10 +1,11 @@ import { generateSchnorrAccounts } from '@aztec/accounts/testing'; import { AztecAddress } from '@aztec/aztec.js/addresses'; +import { NO_WAIT } from '@aztec/aztec.js/contracts'; import { L1FeeJuicePortalManager } from '@aztec/aztec.js/ethereum'; import { FeeJuicePaymentMethodWithClaim } from '@aztec/aztec.js/fee'; import { type FeePaymentMethod, SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee'; import { Fr } from '@aztec/aztec.js/fields'; -import { type AztecNode, createAztecNodeClient } from '@aztec/aztec.js/node'; +import { type AztecNode, createAztecNodeClient, waitForTx } from '@aztec/aztec.js/node'; import type { Wallet } from '@aztec/aztec.js/wallet'; import { createEthereumChain } from '@aztec/ethereum/chain'; import { createExtendedL1Client } from '@aztec/ethereum/client'; @@ -84,11 +85,11 @@ export async function deploySponsoredTestAccountsWithTokens( const paymentMethod = new SponsoredFeePaymentMethod(await getSponsoredFPCAddress()); const recipientDeployMethod = await recipientAccount.getDeployMethod(); - await recipientDeployMethod.send({ from: AztecAddress.ZERO, fee: { paymentMethod } }).wait({ timeout: 2400 }); + await recipientDeployMethod.send({ from: AztecAddress.ZERO, fee: { paymentMethod }, wait: { timeout: 2400 } }); await Promise.all( fundedAccounts.map(async a => { const deployMethod = await a.getDeployMethod(); - await deployMethod.send({ from: AztecAddress.ZERO, fee: { paymentMethod } }).wait({ timeout: 2400 }); // increase timeout on purpose in order to account for two empty epochs + await deployMethod.send({ from: AztecAddress.ZERO, fee: { paymentMethod }, wait: { timeout: 2400 } }); // increase timeout on purpose in order to account for two empty epochs logger.info(`Account deployed at ${a.address}`); }), ); @@ -124,11 +125,10 @@ async function deployAccountWithDiagnostics( accountLabel: string, ): Promise { const deployMethod = await account.getDeployMethod(); - const sentTx = deployMethod.send({ from: AztecAddress.ZERO, fee: { paymentMethod } }); - const txHash = await sentTx.getTxHash(); - + let txHash; try { - await sentTx.wait({ timeout: 2400 }); + txHash = await deployMethod.send({ from: AztecAddress.ZERO, fee: { paymentMethod }, wait: NO_WAIT }); + await waitForTx(aztecNode, txHash, { timeout: 2400 }); logger.info(`${accountLabel} deployed at ${account.address}`); } catch (error) { const blockNumber = await aztecNode.getBlockNumber(); @@ -219,7 +219,7 @@ export async function deployTestAccountsWithTokens( fundedAccounts.map(async (a, i) => { const paymentMethod = new FeeJuicePaymentMethodWithClaim(a.address, claims[i]); const deployMethod = await a.getDeployMethod(); - await deployMethod.send({ from: AztecAddress.ZERO, fee: { paymentMethod } }).wait(); + await deployMethod.send({ from: AztecAddress.ZERO, fee: { paymentMethod } }); logger.info(`Account deployed at ${a.address}`); }), ); @@ -295,14 +295,19 @@ async function deployTokenAndMint( logger: Logger, ) { logger.verbose(`Deploying TokenContract...`); - const tokenContract = await TokenContract.deploy(wallet, admin, TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS) - .send({ - from: admin, - fee: { - paymentMethod, - }, - }) - .deployed({ timeout: 600 }); + const { contract: tokenContract } = await TokenContract.deploy( + wallet, + admin, + TOKEN_NAME, + TOKEN_SYMBOL, + TOKEN_DECIMALS, + ).send({ + from: admin, + fee: { + paymentMethod, + }, + wait: { timeout: 600, returnReceipt: true }, + }); const tokenAddress = tokenContract.address; @@ -312,8 +317,7 @@ async function deployTokenAndMint( accounts.map(acc => TokenContract.at(tokenAddress, wallet) .methods.mint_to_public(acc, mintAmount) - .send({ from: admin, fee: { paymentMethod } }) - .wait({ timeout: 600 }), + .send({ from: admin, fee: { paymentMethod }, wait: { timeout: 600 } }), ), ); @@ -353,7 +357,7 @@ export async function performTransfers({ const provenTxs = await Promise.all(txs); - await Promise.all(provenTxs.map(t => t.send().wait({ timeout: 600 }))); + await Promise.all(provenTxs.map(t => t.send({ wait: { timeout: 600 } }))); logger.info(`Completed round ${i + 1} / ${rounds}`); } diff --git a/yarn-project/end-to-end/src/spartan/transfer.test.ts b/yarn-project/end-to-end/src/spartan/transfer.test.ts index fb47c754ba0b..d499491b15f9 100644 --- a/yarn-project/end-to-end/src/spartan/transfer.test.ts +++ b/yarn-project/end-to-end/src/spartan/transfer.test.ts @@ -88,7 +88,7 @@ describe('token transfer test', () => { const provenTxs = await Promise.all(txs); - await Promise.all(provenTxs.map(t => t.send().wait({ timeout: 600 }))); + await Promise.all(provenTxs.map(t => t.send({ wait: { timeout: 600 } }))); } for (const a of testAccounts.accounts) { diff --git a/yarn-project/test-wallet/src/utils.ts b/yarn-project/test-wallet/src/utils.ts index a16e97475d1c..92aab797ab4e 100644 --- a/yarn-project/test-wallet/src/utils.ts +++ b/yarn-project/test-wallet/src/utils.ts @@ -5,23 +5,44 @@ import { ContractFunctionInteraction, DeployMethod, type DeployOptions, + NO_WAIT, + type NoWait, type SendInteractionOptions, - SentTx, type WaitOpts, toSendOptions, } from '@aztec/aztec.js/contracts'; -import type { AztecNode } from '@aztec/aztec.js/node'; -import { type OffchainEffect, type ProvingStats, Tx } from '@aztec/stdlib/tx'; +import { type AztecNode, waitForTx } from '@aztec/aztec.js/node'; +import { SimulationError } from '@aztec/stdlib/errors'; +import { type OffchainEffect, type ProvingStats, Tx, TxHash, type TxReceipt } from '@aztec/stdlib/tx'; + +import { inspect } from 'util'; import type { BaseTestWallet } from './wallet/test_wallet.js'; +/** + * Options for sending a proven transaction. + */ +export type ProvenTxSendOpts = { + /** + * Whether to wait for the transaction to be mined. + * - undefined (default): wait with default options and return TxReceipt + * - WaitOpts object: wait with custom options and return TxReceipt + * - NO_WAIT: return txHash immediately without waiting + */ + wait?: NoWait | WaitOpts; +}; + +/** + * Return type for ProvenTx.send based on wait option. + */ +export type ProvenTxSendReturn = T extends NoWait ? TxHash : TxReceipt; + /** * Deploys the SchnorrAccount contracts backed by prefunded addresses * at genesis. This can be directly used to pay for transactions in FeeJuice. */ export async function deployFundedSchnorrAccounts( wallet: BaseTestWallet, - aztecNode: AztecNode, accountsData: InitialAccountData[], waitOptions?: WaitOpts, ) { @@ -31,12 +52,11 @@ export async function deployFundedSchnorrAccounts( const { secret, salt, signingKey } = accountsData[i]; const accountManager = await wallet.createSchnorrAccount(secret, salt, signingKey); const deployMethod = await accountManager.getDeployMethod(); - await deployMethod - .send({ - from: AztecAddress.ZERO, - skipClassPublication: i !== 0, // Publish the contract class at most once. - }) - .wait(waitOptions); + await deployMethod.send({ + from: AztecAddress.ZERO, + skipClassPublication: i !== 0, // Publish the contract class at most once. + wait: waitOptions, + }); accountManagers.push(accountManager); } return accountManagers; @@ -70,12 +90,37 @@ export class ProvenTx extends Tx { super(tx.getTxHash(), tx.data, tx.chonkProof, tx.contractClassLogFields, tx.publicFunctionCalldata); } - send() { - const sendTx = async () => { - await this.node.sendTx(this); - return this.getTxHash(); - }; - return new SentTx(this.node, sendTx); + /** + * Sends the transaction to the network. + * @param options - Send options including whether to wait. + * @returns The transaction receipt if waiting, or the transaction hash if not. + */ + send(options?: Omit): Promise; + // eslint-disable-next-line jsdoc/require-jsdoc + send(options: ProvenTxSendOpts & { wait: W }): Promise>; + async send(options?: ProvenTxSendOpts): Promise { + const txHash = this.getTxHash(); + await this.node.sendTx(this).catch(err => { + throw this.contextualizeError(err, inspect(this)); + }); + + if (options?.wait === NO_WAIT) { + return txHash; + } + + const waitOpts = typeof options?.wait === 'object' ? options.wait : undefined; + return await waitForTx(this.node, txHash, waitOpts); + } + + private contextualizeError(err: Error, ...context: string[]): Error { + let contextStr = ''; + if (context.length > 0) { + contextStr = `\nContext:\n${context.join('\n')}`; + } + if (err instanceof SimulationError) { + err.setAztecContext(contextStr); + } + return err; } } diff --git a/yarn-project/test-wallet/src/wallet/test_wallet.ts b/yarn-project/test-wallet/src/wallet/test_wallet.ts index 10e4c622bbca..69df58e22b09 100644 --- a/yarn-project/test-wallet/src/wallet/test_wallet.ts +++ b/yarn-project/test-wallet/src/wallet/test_wallet.ts @@ -18,7 +18,7 @@ import { AuthWitness } from '@aztec/stdlib/auth-witness'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract'; import type { NoteDao, NotesFilter } from '@aztec/stdlib/note'; -import type { TxSimulationResult } from '@aztec/stdlib/tx'; +import type { TxHash, TxReceipt, TxSimulationResult } from '@aztec/stdlib/tx'; import { ExecutionPayload, mergeExecutionPayloads } from '@aztec/stdlib/tx'; import { BaseWallet } from '@aztec/wallet-sdk/base-wallet'; @@ -245,7 +245,7 @@ export abstract class BaseTestWallet extends BaseWallet { * @param opts - The options to configure the interaction * @returns - A proven tx ready to be sent to the network */ - async proveTx(exec: ExecutionPayload, opts: SendOptions): Promise { + async proveTx(exec: ExecutionPayload, opts: Omit): Promise { const fee = await this.completeFeeOptions(opts.from, exec.feePayer, opts.fee?.gasSettings); const txRequest = await this.createTxExecutionRequestFromPayloadAndFee(exec, opts.from, fee); const txProvingResult = await this.pxe.proveTx(txRequest); @@ -257,6 +257,16 @@ export abstract class BaseTestWallet extends BaseWallet { ); } + /** + * Retrieves the transaction receipt for a given transaction hash. + * This is a passthrough to the underlying node, provided for convenience in testing. + * @param txHash - The hash of the transaction. + * @returns The transaction receipt. + */ + getTxReceipt(txHash: TxHash): Promise { + return this.aztecNode.getTxReceipt(txHash); + } + /** * A debugging utility to get notes based on the provided filter. * diff --git a/yarn-project/wallet-sdk/src/base-wallet/base_wallet.ts b/yarn-project/wallet-sdk/src/base-wallet/base_wallet.ts index e7a5540ff9a1..9a5e038f4e6d 100644 --- a/yarn-project/wallet-sdk/src/base-wallet/base_wallet.ts +++ b/yarn-project/wallet-sdk/src/base-wallet/base_wallet.ts @@ -1,6 +1,8 @@ import type { Account } from '@aztec/aztec.js/account'; import type { CallIntent, IntentInnerHash } from '@aztec/aztec.js/authorization'; +import { type InteractionWaitOptions, NO_WAIT, type SendReturn } from '@aztec/aztec.js/contracts'; import type { FeePaymentMethod } from '@aztec/aztec.js/fee'; +import { waitForTx } from '@aztec/aztec.js/node'; import type { Aliased, BatchResults, @@ -43,9 +45,7 @@ import { siloNullifier } from '@aztec/stdlib/hash'; import type { AztecNode } from '@aztec/stdlib/interfaces/client'; import type { TxExecutionRequest, - TxHash, TxProfileResult, - TxReceipt, TxSimulationResult, UtilitySimulationResult, } from '@aztec/stdlib/tx'; @@ -282,7 +282,10 @@ export abstract class BaseWallet implements Wallet { return this.pxe.profileTx(txRequest, opts.profileMode, opts.skipProofGeneration ?? true); } - async sendTx(executionPayload: ExecutionPayload, opts: SendOptions): Promise { + public async sendTx( + executionPayload: ExecutionPayload, + opts: SendOptions, + ): Promise> { const feeOptions = await this.completeFeeOptions(opts.from, executionPayload.feePayer, opts.fee?.gasSettings); const txRequest = await this.createTxExecutionRequestFromPayloadAndFee(executionPayload, opts.from, feeOptions); const provenTx = await this.pxe.proveTx(txRequest); @@ -296,7 +299,15 @@ export abstract class BaseWallet implements Wallet { throw this.contextualizeError(err, inspect(tx)); }); this.log.info(`Sent transaction ${txHash}`); - return txHash; + + // If wait is NO_WAIT, return txHash immediately + if (opts.wait === NO_WAIT) { + return txHash as SendReturn; + } + + // Otherwise, wait for the full receipt (default behavior on wait: undefined) + const waitOpts = typeof opts.wait === 'object' ? opts.wait : undefined; + return (await waitForTx(this.aztecNode, txHash, waitOpts)) as SendReturn; } protected contextualizeError(err: Error, ...context: string[]): Error { @@ -317,10 +328,6 @@ export abstract class BaseWallet implements Wallet { return this.pxe.simulateUtility(call, authwits); } - getTxReceipt(txHash: TxHash): Promise { - return this.aztecNode.getTxReceipt(txHash); - } - async getPrivateEvents( eventDef: EventMetadataDefinition, eventFilter: PrivateEventFilter,