Skip to main content
Version: v3.0.0-nightly.20250919

Sending Transactions

This guide shows you how to send transactions to smart contracts on Aztec.

Prerequisites

  • Deployed contract with its address and ABI
  • Funded account wallet
  • Running Aztec sandbox or connected to a network
  • Understanding of contract interactions

Sending a basic transaction

Let's say you've connected to a contract, for example:

import { Contract } from "@aztec/aztec.js";

const contract = await Contract.at(contractAddress, artifact, wallet);

or

import { MyContract } from './artifacts/MyContract';

const contract = await MyContract.at(contractAddress, wallet);

You should choose your fee-paying method and just call a function on it:

const withFeeJuice = await contract.methods
.transfer(recipientAddress, amount)
.send({ from: fundedAccount.address }) // if this account has fee-juice
.wait();

// or using the Sponsored FPC

const sponsored = await contract.methods
.transfer(recipientAddress, amount)
.send({ fee: { paymentMethod: sponsoredPaymentMethod } })
.wait();

Send without waiting

// Send transaction and get a SentTx object
const sentTx = contract.methods
.transfer(recipientAddress, amount)
.send({ from: fundedAccount.address });

// Get transaction hash immediately
const txHash = await sentTx.getTxHash();
console.log(`Transaction sent with hash: ${txHash.toString()}`);

// Wait for inclusion later
const receipt = await sentTx.wait();
console.log(`Transaction mined in block ${receipt.blockNumber}`);

Send batch transactions

Execute multiple calls atomically

import { BatchCall } from '@aztec/aztec.js';

const batch = new BatchCall(wallet, [
token.methods.approve(spender, amount),
contract.methods.deposit(amount),
contract.methods.updateState()
]);

const receipt = await batch.send({ from: fundedAccount.address }).wait();
console.log(`Batch executed in block ${receipt.blockNumber} with fee ${receipt.transactionFee}`);
warning

All calls in a batch must succeed or the entire batch reverts. Use batch transactions when you need atomic execution of multiple operations.

Query transaction status

Get transaction receipt

const txHash = await sentTx.getTxHash();
const receipt = await wallet.getTxReceipt(txHash); // or pxe.getTxReceipt(txHash);

Check transaction effects

const txHash = await sentTx.getTxHash();
const effect = await pxe.getTxEffect(txHash);

// Access public data writes
effect.data.publicDataWrites.forEach(write => {
console.log(`Wrote ${write.value} to slot ${write.leafSlot}`);
});

// Check note hashes (private note commitments)
effect.data.noteHashes.forEach(noteHash => {
console.log(`Created note: ${noteHash.toString()}`);
});

// Check nullifiers (consumed notes)
effect.data.nullifiers.forEach(nullifier => {
console.log(`Nullified: ${nullifier.toString()}`);
});

Next steps