Sending Transactions
Write to the chain.
Sending Transactions is a free Web3 & DApp Development Fundamentals lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Web3 & DApp Development Fundamentals learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Writing to the Chain
Changing contract state — transferring tokens, minting, voting — requires a transaction. Transactions must be signed and cost gas.
For this you need a signer, not just a provider.
A Contract with a Signer
To send transactions, create the contract with a signer or connect an existing instance to one:
const contract = new ethers.Contract(
address,
abi,
signer
);
// or
const writable = readOnly.connect(signer);Now state-changing functions become available.
const contract = new ethers.Contract(
address,
abi,
signer
);
// or
const writable = readOnly.connect(signer);Sending a Transaction
Calling a write function sends a transaction and returns a transaction response immediately — before it is mined:
const tx = await contract.transfer(
recipient,
ethers.parseUnits("10", 18)
);
console.log("Sent:", tx.hash);The hash identifies the pending transaction.
const tx = await contract.transfer(
recipient,
ethers.parseUnits("10", 18)
);
console.log("Sent:", tx.hash);Waiting for Confirmation
The transaction is not final until it is mined. Wait for the receipt:
const receipt = await tx.wait();
console.log("Mined in block:", receipt.blockNumber);
console.log("Status:", receipt.status);A status of 1 means success; 0 means it reverted.
const receipt = await tx.wait();
console.log("Mined in block:", receipt.blockNumber);
console.log("Status:", receipt.status);Waiting for More Blocks
For higher confidence against reorgs, wait for several confirmations:
// Wait for 3 confirmations
const receipt = await tx.wait(3);More confirmations mean it is increasingly unlikely the transaction will be reversed.
// Wait for 3 confirmations
const receipt = await tx.wait(3);Sending ETH with a Call
Payable functions accept ETH. Pass a value override as the last argument:
const tx = await contract.deposit({
value: ethers.parseEther("0.5"),
});
await tx.wait();The value is in wei; parseEther converts from a human amount.
const tx = await contract.deposit({
value: ethers.parseEther("0.5"),
});
await tx.wait();Estimating Gas
Before sending, you can estimate how much gas a call will use:
const gas = await contract.transfer
.estimateGas(recipient, amount);
console.log("Estimated gas:", gas);If the function would revert, estimation throws — a useful early warning.
const gas = await contract.transfer
.estimateGas(recipient, amount);
console.log("Estimated gas:", gas);Setting Gas Overrides
You can override gas parameters when needed, for example on EIP-1559 chains:
const tx = await contract.transfer(recipient, amount, {
gasLimit: 100000,
maxFeePerGas: ethers.parseUnits("30", "gwei"),
maxPriorityFeePerGas: ethers.parseUnits("2", "gwei"),
});Usually the wallet picks sensible defaults, so override only when you must.
const tx = await contract.transfer(recipient, amount, {
gasLimit: 100000,
maxFeePerGas: ethers.parseUnits("30", "gwei"),
maxPriorityFeePerGas: ethers.parseUnits("2", "gwei"),
});Handling Failures
Transactions can fail by reverting, being underpriced, or by user rejection in a wallet. Wrap sends in try/catch:
try {
const tx = await contract.transfer(to, amount);
await tx.wait();
} catch (err) {
console.error("Transaction failed:", err.shortMessage);
}try {
const tx = await contract.transfer(to, amount);
await tx.wait();
} catch (err) {
console.error("Transaction failed:", err.shortMessage);
}Nonces and Ordering
Each account has a nonce — a counter ensuring transactions execute in order. ethers manages it automatically, but if you send many transactions quickly you may set it manually to avoid collisions:
const tx = await contract.mint({ nonce: 42 });Mismatched nonces cause transactions to get stuck or replaced.
const tx = await contract.mint({ nonce: 42 });Reading Events from a Receipt
After mining, you can inspect the events emitted by your transaction from the receipt logs:
const receipt = await tx.wait();
for (const log of receipt.logs) {
const parsed = contract.interface.parseLog(log);
if (parsed) console.log(parsed.name, parsed.args);
}This confirms the contract did what you expected.
const receipt = await tx.wait();
for (const log of receipt.logs) {
const parsed = contract.interface.parseLog(log);
if (parsed) console.log(parsed.name, parsed.args);
}Quick Check
Test your understanding of sending transactions.
Recap
You learned to send state-changing transactions.
- Writes require a signer; attach one with
connector at construction. - A write call returns a pending tx;
tx.wait()gives the mined receipt. - Check
receipt.status; wait for more confirmations against reorgs. - Send ETH via a
valueoverride; estimate cost withestimateGas. - Handle failures with try/catch and mind the account nonce.
Frequently asked questions
Is the “Sending Transactions” lesson free?
Yes — the full text of “Sending Transactions” is free to read here on the web, and the Web3 & DApp Development Fundamentals course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Web3 & DApp Development Fundamentals course, upgrade to CoddyKit PRO.
What will I learn in “Sending Transactions”?
Write to the chain. You practise Web3 & DApp Development Fundamentals with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Web3 & DApp Development Fundamentals?
No prior experience is required. Web3 & DApp Development Fundamentals on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Sending Transactions” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Web3 & DApp Development Fundamentals lesson?
Yes. Every Web3 & DApp Development Fundamentals lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Connecting to a Provider
- Reading Contract Data
- Sending Transactions
- Listening to Events