Sending Transactions
Menulis data ke blockchain membutuhkan transaksi. Transaksi harus di-sign oleh private key, dikirim ke network, dan ditunggu sampai di-mine ke dalam block.
Anatomy of a Transaction
// Setiap transaksi berisi:
{
from: "0xYourAddress", // Pengirim (signer)
to: "0xRecipient", // Tujuan (address / contract)
value: "1000000000000000", // ETH dalam wei (0.001 ETH)
data: "0x...", // Encoded function call (untuk contract)
gasLimit: 21000, // Maksimal gas yang dipakai
maxFeePerGas: "20000000000", // Max fee per gas (EIP-1559)
maxPriorityFeePerGas: "2000000000", // Tip untuk validator
nonce: 42, // Transaction counter (anti-replay)
chainId: 1, // Network ID (1 = mainnet)
}
Kirim ETH (ethers.js)
async function sendETH() {
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const tx = await signer.sendTransaction({
to: "0xRecipientAddress...",
value: ethers.parseEther("0.01"), // 0.01 ETH
});
console.log("TX Hash:", tx.hash);
// "0xabc123..." — transaksi sudah dikirim, belum tentu sukses
// Tunggu transaksi di-mine (1 confirmation)
const receipt = await tx.wait();
console.log("Confirmed in block:", receipt.blockNumber);
console.log("Gas used:", receipt.gasUsed.toString());
console.log("Status:", receipt.status); // 1 = success, 0 = reverted
}
Panggil Contract Function
// Write function (butuh gas, butuh signer)
async function approveToken() {
const contract = new ethers.Contract(tokenAddress, abi, signer);
// Approve Uniswap untuk spend 1000 token
const tx = await contract.approve(
uniswapRouter,
ethers.parseUnits("1000", 18)
);
// Tunggu konfirmasi
const receipt = await tx.wait();
if (receipt.status === 1) {
console.log("Approve berhasil!");
} else {
console.log("Transaksi gagal (reverted)");
}
}
Estimasi Gas
// Estimasi gas sebelum kirim (agar user tahu biaya)
const gasEstimate = await contract.approve.estimateGas(
spenderAddress,
ethers.parseUnits("1000", 18)
);
console.log("Estimated gas:", gasEstimate.toString());
// Harga gas saat ini
const feeData = await provider.getFeeData();
console.log("Gas price:", ethers.formatUnits(feeData.gasPrice, "gwei"), "gwei");
Error Handling
try {
const tx = await contract.transfer(to, amount);
await tx.wait();
} catch (error) {
if (error.code === "ACTION_REJECTED") {
console.log("User rejected di MetaMask");
} else if (error.code === "INSUFFICIENT_FUNDS") {
console.log("Saldo ETH tidak cukup untuk gas");
} else if (error.reason) {
// Revert reason dari smart contract
console.log("Contract error:", error.reason);
}
}
Transaction Lifecycle
- Build — Buat object transaksi
- Sign — User sign di wallet (MetaMask popup)
- Broadcast — Kirim ke mempool (pending)
- Mine — Validator masukkan ke block
- Confirm — Tunggu N block untuk finality