MetaMask, Transactions and Sepolia
Lab decks 6, 7 and 8: setting up a MetaMask wallet, enabling test networks, Etherscan, getting Sepolia ETH from a faucet, sending a transaction and reading its gas fee, then querying Sepolia through an Alchemy RPC endpoint with raw JSON-RPC calls from PowerShell.
Setting up the wallet (MetaMask)Search on YouTube
MetaMask is a browser-extension (and mobile) wallet for Ethereum and other chains. It holds your keys, shows balances and signs transactions. The deck walks through setup with screenshots:
- Go to
metamask.ioand click Get MetaMask. - Choose Browser Extension and your browser (Chrome, Firefox, Brave; the deck uses Microsoft Edge with the Chrome Web Store).
- Click Get, then Add extension. Edge warns the extension can read and change data on all websites, display notifications, and modify copied and pasted data.
- Choose Create a new wallet (the other option is "I have an existing wallet").
- Pick Use Secret Recovery Phrase (instead of Continue with Google, Apple or Telegram).
- Create a MetaMask password (at least 8 characters). Tick "If I lose this password, MetaMask can't reset it". The password unlocks MetaMask on this device only.
- Save your Secret Recovery Phrase: tap to reveal the 12 words, write them down in order, keep them safe. Make sure no one is watching your screen.
- Confirm your Secret Recovery Phrase by filling the missing words in the right order. MetaMask shows "Perfect. Never share this phrase with anyone, ever."
- On "Help improve MetaMask", untick "Gather basic usage data" and "Product updates" if you want, then Continue.
- "Your wallet is ready!": click Open wallet. Pin the extension to the toolbar.
The password only unlocks the wallet on one device. The Secret Recovery Phrase (seed phrase) is the wallet. Anyone with it controls all your accounts. MetaMask cannot reset either one.
The wallet opens on Account 1 with an address like 0xc32BB...4A2B7. The home screen shows "Fund your wallet", buttons Buy, Swap, Send, Receive, and tabs Tokens, Perps, DeFi, NFTs, Activity.
Enabling test networksSearch on YouTube
- Open the menu (three lines). You can also choose Open full screen.
- Go to Networks (Manage networks).
- Turn on Show test networks. Sepolia, Linea Sepolia, MegaETH Testnet and Monad Testnet appear.
- In the network selector, choose Sepolia under Testnets.
Block explorer (Etherscan)Search on YouTube
A block explorer is a website that shows blocks, transactions and addresses of a chain. etherscan.io is the Ethereum mainnet explorer. Its home page shows ETH price, market cap, transaction count, gas price, last finalised block, latest blocks and latest transactions.
Search your wallet address. A new address shows ETH balance 0, no transactions sent, and "There are no matching entries".
For the testnet use https://sepolia.etherscan.io/.
Making your first transactionSearch on YouTube
Two types of testnetsSearch on YouTube
| Public testnets | Simulated testnets |
|---|---|
| Like Sepolia | Provided by service providers like Tenderly |
| Need volunteers to run the blockchain | Easy to set up, instant faucets |
| Transactions work the same as on public testnets | |
| No volunteers needed; the provider manages the chain |
Getting Sepolia ETH from a faucetSearch on YouTube
A faucet gives free test ETH. The lab uses the Google Cloud Web3 faucet:
https://cloud.google.com/application/web3/faucet/ethereum/sepolia- Select network Ethereum Sepolia.
- Paste the wallet address (the "Ironman" account in the deck).
- Click Get 0.05 Sepolia ETH. The tokens are queued, then "Transaction complete! Check your wallet address" shows the recipient and transaction hash.
- Check the wallet: with Sepolia selected, it shows 0.0500 SepoliaETH.
- Check the address on
sepolia.etherscan.io: balance 0.05 ETH and one incoming transaction.
Sending ETH between accountsSearch on YouTube
The deck sends 0.01 SepoliaETH from account "Ironman" to account "Spiderman":
- Click Send, choose the recipient, enter 0.01.
- The review screen shows From, To and Network (Sepolia). It also shows Network fee (about 0.0001 SepoliaETH), Speed (Market, about 12 sec), Max fee and Nonce 0 (the sender's first transaction).
- Confirm. Spiderman's wallet now shows 0.0100 SepoliaETH.
- On Etherscan, Ironman's address lists two transactions: the faucet deposit (IN) and the transfer (OUT).
Gas feeSearch on YouTube
Open the transaction on Etherscan. The deck highlights these fields:
| Field | Value in the lab |
|---|---|
| Value | 0.01 ETH |
| Transaction fee | small amount in ETH (gas used times gas price) |
| Gas limit and usage by txn | 21,000 used (66.67% of the limit) |
| Gas fees | Base, Max (about 2.97 Gwei) and Max Priority (1.5 Gwei) |
| Burnt and txn savings | part of the fee is burnt; unused max fee is saved |
A plain ETH transfer always uses 21,000 gas. Here the limit was 31,500 (0x7b0c), so 21,000 is 66.67% of it. Gas is priced in Gwei: Wei and Wei.
Interacting with the Sepolia testnetSearch on YouTube
Prerequisites: a MetaMask wallet, funds from a faucet, one transaction between accounts, and that transaction viewed on Etherscan.
How an application talks to a public chainSearch on YouTube
Your application (with a wallet address field and an "Explore" button) cannot talk to the Ethereum Sepolia network directly. It sends an HTTP request (or a WebSocket message) to an RPC infrastructure provider. The provider runs nodes on the network.
Your application ──HTTP POST (JSON-RPC request)──▶ Alchemy node (RPC) ──▶ Sepolia public testnet
(PowerShell:
Invoke-RestMethod / Invoke-WebRequest)Getting a Sepolia RPC URLSearch on YouTube
Get one free from Alchemy:
- Sign in at
alchemy.com. - Create an app (the deck's is "Jaiganesh's First App").
- Open Endpoints. Under Ethereum, copy the Ethereum Sepolia HTTPS URL, of the form
https://eth-sepolia.g.alchemy.com/v2/<API_KEY>. - App Settings has Rotate API key if the key leaks. The old key stops working shortly after rotation.
The API key is part of the URL. Treat the RPC URL as a secret; the deck blurs it in every screenshot.
JSON-RPC methods usedSearch on YouTube
1. Network / blockchain information
| RPC method | What it gives |
|---|---|
eth_chainId | Chain ID |
eth_blockNumber | Latest block number |
eth_getBlockByNumber | Details of a block |
eth_getBlockByHash | Block using its hash |
eth_gasPrice | Current gas price |
eth_getBlockTransactionCountByNumber | Number of transactions in a block |
2. Account information
| RPC method | What it gives |
|---|---|
eth_getBalance | ETH balance |
eth_getTransactionCount | Number of transactions / nonce |
eth_getCode | Whether an address contains contract code |
eth_getStorageAt | Read contract storage |
3. Transaction information
eth_getTransactionByHashreturns the sender, receiver, value, gas, nonce, transaction data and block information.eth_getTransactionReceipttells whether the transaction was successfully included. It gives status, gas used, block number and transaction logs.
4. Sending transactions: eth_sendRawTransaction.
Four groups of RPC calls: "Never Ask Twice, Send": Network, Account, Transaction, Send.
JSON-RPC structureSearch on YouTube
{"jsonrpc":"2.0","method":"SOME_METHOD_NAME","params":[...],"id":1}| Key | Meaning |
|---|---|
jsonrpc: "2.0" | Says "I am speaking JSON-RPC version 2.0" |
method | What you are asking it to do (get balance, send transaction, get block and dozens more) |
params | Arguments for that method (empty for eth_chainId; the wallet address for eth_getBalance) |
id | A request label, so you can match responses to requests when you send several |
The deck works directly in PowerShell to understand the logic. Invoke-RestMethod sends HTTP/HTTPS requests to REST APIs and parses the JSON response into PowerShell objects.
Network queriesSearch on YouTube
eth_chainIdSearch on YouTube
$RPC_URL="YOUR_SEPOLIA_RPC_URL"
$body = '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'
Invoke-RestMethod `
-Uri $RPC_URL `
-Method Post `
-ContentType "application/json" `
-Body $body| Part | Role |
|---|---|
-Uri (the RPC_URL variable) | Where to send the request; the variable is only for convenience |
-Method Post | Use the HTTP POST method |
-ContentType "application/json" | The content sent is JSON |
-Body (the body variable) | The data to send |
` (backtick) | PowerShell line continuation |
Result: 0xaa36a7. In decimal that is 11155111, the Sepolia chain ID.
The same call with curl on Linux:
curl -s -X POST "$RPC_URL" -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'eth_blockNumberSearch on YouTube
$body = '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":2}'Result 0xb13404. Convert hex to decimal in PowerShell:
[Convert]::ToInt64("B13404", 16) # 11613188Every number in Ethereum JSON-RPC is a hex string with 0x. Convert it before reading it.
eth_getBlockByNumberSearch on YouTube
$body = '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0xb13404",false],"id":4}'The second parameter: false returns only transaction hashes, true returns full transaction objects. By default Invoke-RestMethod truncates long JSON output. Expand it:
$body = '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0xb13404",true],"id":4}'
$response = Invoke-RestMethod -Uri $RPC_URL -Method Post -ContentType "application/json" -Body $body
$response | ConvertTo-Json -Depth 5The block shows hash, parentHash, sha3Uncles, miner, stateRoot, transactionsRoot, receiptsRoot, logsBloom, difficulty (0x0 after the move to Proof of Stake), number, gasLimit, gasUsed and timestamp.
eth_getBlockByHashSearch on YouTube
$BLOCK_HASH="0x...4db87e"
$body = "{`"jsonrpc`":`"2.0`",`"method`":`"eth_getBlockByHash`",`"params`":[`"$BLOCK_HASH`",false],`"id`":5}"The body is in double quotes so $BLOCK_HASH expands. Inner quotes are escaped with a backtick.
eth_gasPriceSearch on YouTube
$body = '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":6}'Result 0x3ea60403. The value is in Wei. 1 ETH = 1,000,000,000,000,000,000 Wei ().
eth_getBlockTransactionCountByNumberSearch on YouTube
$body = '{"jsonrpc":"2.0","method":"eth_getBlockTransactionCountByNumber","params":["0xb12F70"],"id":7}'Result 0x61 = 97 transactions in block 11612016. Etherscan shows the same "97 transactions" for that block.
Account queriesSearch on YouTube
eth_getBalanceSearch on YouTube
$ADDRESS="0x...2B7"
$body = '{"jsonrpc":"2.0","method":"eth_getBalance","params":["' + $ADDRESS + '","latest"],"id":8}'
$result = Invoke-RestMethod -Uri $RPC_URL -Method Post -ContentType "application/json" -Body $body
$result"latest" is the block tag: the balance at the newest block. Result 0x8deb4b5219eda0 Wei. Make it readable:
Write-Host "Address: $ADDRESS"
Write-Host "Balance (Wei): $($result.result)"
$balanceWei = [System.Numerics.BigInteger]::Parse(
$result.result.Substring(2),
[System.Globalization.NumberStyles]::AllowHexSpecifier
)
Write-Host "Balance (ETH): $([double]$balanceWei / 1e18)"Substring(2) strips the 0x. Divide by 1e18 to get ETH. MetaMask shows 0.0399 SepoliaETH.
In the deck's screenshot the ETH line prints a negative number. BigInteger.Parse with AllowHexSpecifier treats a leading hex digit of 8 to F as a sign bit. Prefix a "0" ("0" + $result.result.Substring(2)) to always get a positive value.
eth_getTransactionCountSearch on YouTube
$body = '{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["' + $ADDRESS + '","latest"],"id":9}'Result 0x1: Ironman has sent one transaction, so its next nonce is 1. Received transactions do not count.
eth_getCodeSearch on YouTube
$body = '{"jsonrpc":"2.0","method":"eth_getCode","params":["' + $ADDRESS + '","latest"],"id":10}'Result 0x. 0x means no contract bytecode exists at that address.
| EOA (Externally Owned Account) | Contract account |
|---|---|
| A normal wallet | Created when a contract is deployed (by a deployment transaction) |
| Controlled by a private key (MetaMask, your seed phrase) | Has bytecode stored at the address: compiled program logic |
| Has no code: only a balance and a nonce | Has no private key; controlled entirely by its code |
| What you created when you generated a wallet address |
eth_getStorageAtSearch on YouTube
Needs a deployed smart contract, so the deck leaves it for later. Reference snippet:
$CONTRACT="0xYOUR_CONTRACT_ADDRESS"
$SLOT="0x0"
$body = '{"jsonrpc":"2.0","method":"eth_getStorageAt","params":["' + $CONTRACT + '","' + $SLOT + '","latest"],"id":11}'
$result = Invoke-RestMethod -Uri $RPC_URL -Method Post -ContentType "application/json" -Body $body
$resultTransaction queriesSearch on YouTube
eth_getTransactionByHashSearch on YouTube
The Ironman to Spiderman transaction:
$TX_HASH="0x50e5f5f7f696bbe1eabf95cd5c903a226ff7f4857840a4d69a19a62755da79a3"
$body = '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["' + $TX_HASH + '"],"id":12}'
$result = Invoke-RestMethod -Uri $RPC_URL -Method Post -ContentType "application/json" -Body $body
$resultResult fields (hex) include: type 0x2, chainId 0xaa36a7 (11155111), nonce 0x0, gas 0x7b0c (31500), maxFeePerGas 0xb1034988 (2969782664 Wei), maxPriorityFeePerGas 0x59682f00, to, value 0x2386f26fc10000 (0.01 ETH). Then come accessList, input 0x, signature r, s, yParity, v, hash, blockHash, blockNumber 0xb12f70, transactionIndex 0x3, from, gasPrice.
Invoke-WebRequest returns the raw response instead of parsed objects:
$response = Invoke-WebRequest -Uri $RPC_URL -Method Post -ContentType "application/json" -Body $body
$response.ContentPowerShell shows "Security Warning: Script Execution Risk" because it parses the page. Answer Y, or add -UseBasicParsing. Pretty-print with an online JSON parser, or:
$response.Content | ConvertFrom-Json | ConvertTo-Json -Depth 10eth_getTransactionReceiptSearch on YouTube
Gives the execution result (receipt) after the transaction is included in a block.
$body = '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["' + $TX_HASH + '"],"id":13}'
$response = Invoke-WebRequest -Uri $RPC_URL -Method Post -ContentType "application/json" -Body $body
$response.Content | ConvertFrom-Json | ConvertTo-Json -Depth 10In the lab: type 0x2, status 0x1, gasUsed 0x5208 (21000), contractAddress null.
| Field | Meaning |
|---|---|
type | Transaction type; 0x2 = EIP-1559 |
status | 0x1 = success, 0x0 = reverted/failed |
transactionHash | Unique transaction identifier |
transactionIndex | Position of the transaction inside the block |
blockHash | Hash of the containing block |
blockNumber | Number of the containing block |
from | Transaction sender |
to | Transaction recipient |
gasUsed | Gas actually consumed |
effectiveGasPrice | Gas price actually applied |
cumulativeGasUsed | Total gas used by transactions up to this one in the block |
logs | Events emitted during execution |
logsBloom | Bloom filter for the logs |
contractAddress | Address of a newly deployed contract; null for normal transactions |
Reference: "JSON-RPC API" on ethereum.org.
What to do and check in the lab:
- Install MetaMask, create a wallet, store the 12-word phrase offline, enable test networks and select Sepolia.
- Claim 0.05 Sepolia ETH from the Google Cloud faucet and confirm it in MetaMask and on
sepolia.etherscan.io. - Create a second account and send 0.01 SepoliaETH to it. Note the nonce (0) and the gas used (21,000) on Etherscan.
- Create an Alchemy app and copy the Sepolia HTTPS endpoint.
- In PowerShell call
eth_chainId(expect0xaa36a7= 11155111),eth_blockNumber,eth_gasPrice,eth_getBalance,eth_getTransactionCountandeth_getCode(expect0x). - Fetch your transfer with
eth_getTransactionByHashandeth_getTransactionReceipt; readstatusandgasUsed.
Quick self-testSearch on YouTube
Viva: what is the difference between the MetaMask password and the Secret Recovery Phrase?
The password only unlocks MetaMask on one device. The 12-word Secret Recovery Phrase regenerates the wallet's keys on any device. Anyone with the phrase controls the funds, and MetaMask cannot reset either.
What is a faucet, and which one did the lab use?
A service that gives free test tokens for a testnet. The lab used the Google Cloud Web3 Ethereum Sepolia faucet, which gives 0.05 Sepolia ETH.
Distinguish public and simulated testnets.
Public testnets like Sepolia are run by volunteer nodes. Simulated testnets are provided by services like Tenderly: easy setup, instant faucets, same transaction behaviour, managed by the provider.
How much gas does a plain ETH transfer use, and how is the fee computed?
21,000 gas. Fee = gas used × effective gas price, usually quoted in Gwei (1 Gwei = Wei).
Why does an application need an RPC provider such as Alchemy?
The app cannot join the peer-to-peer network itself. It sends JSON-RPC requests over HTTP or WebSocket to a node run by the provider, which reads from or broadcasts to Sepolia.
Write the JSON-RPC body for the chain ID and give the Sepolia answer.
{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}. The answer is 0xaa36a7, which is 11155111.
What is the purpose of the id field in a JSON-RPC request?
It labels the request so the response with the same id can be matched to it when several requests are sent.
Viva: eth_getCode returns 0x for your address. What does that tell you?
No contract bytecode exists there, so it is an Externally Owned Account controlled by a private key, not a contract account.
What does eth_getTransactionCount return, and how does it relate to the nonce?
The number of transactions sent from the address. It equals the nonce the next transaction must use. After one send it returns 0x1.
In a transaction receipt, what do status 0x0 and contractAddress null mean?
status 0x0 means the transaction reverted (failed). contractAddress null means it was a normal transaction, not a contract deployment.
- MetaMask setup: install extension, create wallet, set password, save and confirm the 12-word Secret Recovery Phrase, enable test networks, select Sepolia.
- Etherscan (
sepolia.etherscan.iofor the testnet) shows addresses, blocks, transactions and fees. - The Google Cloud faucet gives 0.05 Sepolia ETH; the lab sent 0.01 ETH between accounts with nonce 0 and 21,000 gas.
- Apps reach the chain through an RPC provider (Alchemy) with JSON-RPC 2.0 over HTTP POST:
jsonrpc,method,params,id. - Network calls:
eth_chainId(0xaa36a7 = 11155111),eth_blockNumber,eth_getBlockByNumber/Hash,eth_gasPrice,eth_getBlockTransactionCountByNumber. - Account calls:
eth_getBalance(Wei, 1 ETH = Wei),eth_getTransactionCount(nonce),eth_getCode(0x= EOA),eth_getStorageAt. - Transaction calls:
eth_getTransactionByHash,eth_getTransactionReceipt(status 0x1 success, type 0x2 EIP-1559),eth_sendRawTransaction.