iT邦幫忙

2023 iThome 鐵人賽

DAY 26
0
Web 3

從 區塊鏈 到 去中心化應用程式(DApp)系列 第 26

DApp建立: 查詢區塊與交易資訊

  • 分享至 

  • xImage
  •  

查詢區塊與交易資訊

在區塊鏈中
最重要的其中一個核心理念就是 "不可篡改性"

自然會很希望能查詢到 所期待的歷史資訊

因此透過查詢能獲得區塊鏈資訊
亦是去中心化應用程序(DApp)中非常重要的一環

這篇將以下重點進行敘述:

  1. 專案規劃
  2. 透過 web3.js 獲取資料
  3. 透過 ethers.js 獲取資料
  4. 連線至 乙太坊 主網
  5. 最終呈現畫面

另外可參考 GitHub 專案位置:
https://github.com/weiawesome/dapp_website

專案規劃

佈局規劃

  • 標題
    寫下本頁面的目標
  • 選擇要連接的網路
    可以自己填寫要連接的乙太坊網路
  • 區塊查詢區域
    各種查詢區塊資訊的方式 (左 web3.js 右 ethers.js)
  • 交易查詢區域
    各種查詢交易資訊的方式 (左 web3.js 右 ethers.js)

架構規劃

├── src
│   ├── app
│   ├── pages
│   │   ├── get_information.tsx
│   ├── style
│   │   ├── get_information.css
│

"src/app/pages/get_information.tsx" 邏輯與基本布局
"src/app/style/get_information.css" 對上述畫面的修飾

因此 最後畫面會顯示在 /get_information 這個路由下

區塊 與 交易 資料呈現

// 區塊的資訊
class BlockInfo{
    // 區塊高度
    BlockHeight:number
    // 區塊哈希值
    BlockHash:string
    // 前一區塊哈希值
    PreviousHash:string
}
// 交易的資訊
class TransactionInfo{
    // 交易所在區塊的區塊高度
    BlockHeight:number
    // 交易哈希值
    Hash:string
    // 交易發起人地址
    From:string
    // 交易接收人地址
    To:string
    // 交易金額
    Amount:string
    // 交易手續費
    Fee:string
}
  • 區塊 與 交易

由於二者完整資訊過多 不方便作為呈現

因此就選擇數個屬性作為展示的效果

透過 web3.js 獲取資料

區塊方面

// 獲取當前最新區塊高度
const getBlockHeightWeb3=()=>{
    const url=urlRef.current?.value.toString()
    const web3 = new Web3(url);
    web3.eth.getBlockNumber()
        .then(blockNumber => {
            console.log('最新區塊高度:', blockNumber);
            setLastBlockNumberWeb3(Number(blockNumber));
        })
        .catch(error => {
            console.error('獲取區塊高度時發生錯誤:', error);
        });
}

// 從區塊高度尋找區塊
const getBlockByHeightWeb3=()=>{
    const url=urlRef.current?.value.toString()
    const web3 = new Web3(url);
    const blockNumber=Number(heightRef.current?.value);
    web3.eth.getBlock(blockNumber).then(blockInfo => {
        if (blockInfo) {
            let tmp=new BlockInfo();
            tmp.BlockHeight=Number(blockInfo.number);
            tmp.BlockHash=blockInfo.hash;
            tmp.PreviousHash=blockInfo.parentHash;
            setBlockByHeightWeb3(tmp);
            console.log('區塊資訊:', blockInfo);
        } else {
            alert(`找不到區塊號 ${blockNumber} 的資訊。`);
        }
    }).catch(error => {
        alert('發生錯誤:'+ error);
    });
}

// 從區塊哈希尋找區塊
const getBlockByHashWeb3=()=>{
    const url=urlRef.current?.value.toString()
    const web3 = new Web3(url);
    const blockHash=hashRef.current?.value;
    web3.eth.getBlock(blockHash,true).then(blockInfo => {
        if (blockInfo) {
            let tmp=new BlockInfo();
            tmp.BlockHeight=Number(blockInfo.number);
            tmp.BlockHash=blockInfo.hash;
            tmp.PreviousHash=blockInfo.parentHash;
            setBlockByHashWeb3(tmp);
            console.log('區塊資訊:', blockInfo);
        } else {
            alert(`找不到區塊號 ${blockHash} 的資訊。`);
        }
    }).catch(error => {
        alert('發生錯誤:'+ error);
    });
}
  • 獲取最新區塊高度
    其實就是獲取目前區塊鏈的長度
  • 從區塊高度尋找區塊
    可以直接根據區塊高度尋找到相對應的區塊資訊 並更新相關資訊
  • 從區塊哈希尋找區塊
    可以直接根據區塊哈希尋找到相對應的區塊資訊 並更新相關資訊

交易方面

// 從交易哈希獲取交易相關資訊
const getTransactionWeb3=()=>{
    const url=urlRef.current?.value.toString()
    const web3 = new Web3(url);
    const transactionHash = transactionHashRef.current?.value.toString();

    web3.eth.getTransaction(transactionHash)
        .then(transactionInfo => {
            if (transactionInfo) {
                console.log('交易資訊:', transactionInfo);
                let tmp=new TransactionInfo();
                tmp.From=transactionInfo.from;
                tmp.To=transactionInfo.to!;
                tmp.Amount=formatEther(transactionInfo.value);
                tmp.Fee=formatEther(transactionInfo.gasPrice);
                tmp.BlockHeight=Number(transactionInfo.blockNumber);
                tmp.Hash=transactionInfo.hash;
                setTransactionWeb3(tmp);
            } else {
                alert(`找不到交易哈希 ${transactionHash} 的資訊。`);
            }
        }).catch(error => {
        alert('發生錯誤:'+ error);
    });
}
  • 從交易哈希獲取交易相關資訊
    從交易哈希去尋找相符合的交易 並設定相關資訊

透過 ethers.js 獲取資料

區塊方面

// 獲取最新區塊高度
const getBlockHeightEthers=()=>{
    const url=urlRef.current?.value.toString()
    const provider = new ethers.JsonRpcProvider(url);
    provider.getBlockNumber().then(blockNumber => {
        setLastBlockNumberEthers(blockNumber);
    }).catch((e)=>{
        alert("error: "+e);
    });
}

// 從區塊高度尋找區塊
const getBlockByHeightEthers=()=>{
    const url=urlRef.current?.value.toString()
    const provider = new ethers.JsonRpcProvider(url);
    const blockNumber=Number(heightRef.current?.value);
    provider.getBlock(blockNumber).then(blockInfo => {
        if (blockInfo) {
            let tmp=new BlockInfo();
            tmp.BlockHeight=blockInfo.number;
            tmp.BlockHash=blockInfo.hash;
            tmp.PreviousHash=blockInfo.parentHash;
            setBlockByHeightEthers(tmp);
            console.log('區塊資訊:', blockInfo);
        } else {
            alert(`找不到區塊號 ${blockNumber} 的資訊。`);
        }
    }).catch(error => {
        alert('發生錯誤:'+ error);
    });
}

// 從區塊哈希尋找區塊
const getBlockByHashEthers=()=>{
    const url=urlRef.current?.value.toString()
    const provider = new ethers.JsonRpcProvider(url);
    const blockHash=hashRef.current?.value;
    provider.getBlock(blockHash).then(blockInfo => {
        if (blockInfo) {
            let tmp=new BlockInfo();
            tmp.BlockHeight=blockInfo.number;
            tmp.BlockHash=blockInfo.hash;
            tmp.PreviousHash=blockInfo.parentHash;
            setBlockByHashEthers(tmp);
            console.log('區塊資訊:', blockInfo);
        } else {
            alert(`找不到區塊號 ${blockHash} 的資訊。`);
        }
    }).catch(error => {
        alert('發生錯誤:'+ error);
    });
}
  • 獲取最新區塊高度
    可以直接獲得最新區塊的區塊高度 即獲得區塊鏈長度
  • 從區塊高度尋找區塊
    ```透過指定區塊高度 獲得相對應的資訊 並設置相關變數``
  • 從區塊哈希尋找區塊
    ```透過指定區塊哈希 獲得相對應的資訊 並設置相關變數``

交易方面

// 從交易哈希獲取交易相關資訊
const getTransactionEthers=()=>{
    const url=urlRef.current?.value.toString();
    const provider = new ethers.JsonRpcProvider(url);
    const transactionHash=transactionHashRef.current?.value.toString();
    provider.getTransaction(transactionHash).then(transactionInfo => {
        if (transactionInfo) {
            console.log('交易資訊:', transactionInfo);
            let tmp=new TransactionInfo();
            tmp.From=transactionInfo.from;
            tmp.To=transactionInfo.to;
            tmp.Amount=formatEther(transactionInfo.value);
            tmp.Fee=formatEther(transactionInfo.gasPrice);
            tmp.BlockHeight=transactionInfo.blockNumber;
            tmp.Hash=transactionInfo.hash;
            setTransactionEthers(tmp);
        } else {
            alert(`找不到交易哈希 ${transactionHash} 的資訊。`);
        }
    }).catch(error => {
        alert('發生錯誤:'+ error);
    });
}
  • 從交易哈希獲取交易相關資訊
    從交易哈希去尋找相符合的交易 並設定相關資訊

連線至 乙太坊 主網

如果想要連接到以太坊主網(Ethereum Mainnet)
可以使用 以太坊節點提供者 或 自己運行的以太坊節點

以太坊節點提供者 可以使用 Infura

以下為介紹如何使用 Infura

註冊與登入

Infura 官方網站: https://www.infura.io/zh


上圖取自於(https://www.infura.io/zh)網頁畫面

  • 點選 Sign In 進行登入


上圖取自於(https://www.infura.io/zh)網頁登入畫面

  • 註冊與登入細節便不贅述

進入主畫面 並創建 API-KEY


上圖取自於(https://www.infura.io/zh)網頁主畫面

  • 選擇創建新API-KEY (CREATE NEW API KEY)


上圖取自於(https://www.infura.io/zh)網頁API-KEY創建畫面

  • 選擇 Web3 API 並隨意命名


上圖取自於(https://www.infura.io/zh)網頁API-KEY畫面

  • 下方 Ethereum 選擇 MAINNET 並且複製後方URL

接下來就可以透過以上 URL 進行查詢區塊鏈資訊的互動

最終呈現畫面

標題 與 URL填寫位置

區塊查詢區域

交易查詢區域

執行步驟

1. 填入 URL

  • 填入剛剛上方獲得的 URL

2. 查詢最新區塊高度

乙太坊區塊鏈連覽器: https://etherscan.io/blocks

  • 可透過區塊鏈連覽器 檢查資訊是否正確
  • 確實與最新區塊資訊符合

3. 查詢該高度區塊 詳細資料

區塊鏈連覽器(對應區塊資料): https://etherscan.io/block/18314410

資料取自於(https://etherscan.io/block/18314410)

  • 資料確實相符合 不論是 區塊高度、區塊哈希、前一區塊哈希

4. 根據區塊哈希查詢該個區塊

  • 確實也與上圖資訊符合

5. 查詢交易

透過以下交易為例子:


圖片與資料取自於(https://etherscan.io/tx/0xa674e253eec4ebf4cfd4c83f708fd32cc5e3c938a0e1d6b7ab4b15452847d1c5)

  • 將交易哈希進行複製 透過交易哈希進行查詢


圖片與資料取自於(https://etherscan.io/tx/0xa674e253eec4ebf4cfd4c83f708fd32cc5e3c938a0e1d6b7ab4b15452847d1c5)

  • 確實資料都相符合 地址、金額、手續費
備註:
在此處也可以使用 Ganache 模擬區塊鏈
相對資訊可能也沒有現實區塊鏈麼複雜 也比較容易觀察

如果要使用 Ganache 模擬區塊鏈 網路
則 URL 部分直接填入 HTTP://127.0.0.1:7545 即可
(根據自己設定可能會有所不同)

結言

現在可以輕鬆地拿到區塊鏈上所有資料

這就是區塊鏈的公開性

正是因為透過這樣的特性 可以衍伸出許多有趣的應用

希望透過這篇能夠理解

  1. 透過 web3.js 查詢 區塊鏈資訊
  2. 透過 ethers.js 查詢 區塊鏈資訊
  3. 使用 Infura 乙太坊節點提供者 建立連線
  4. 將結果資料與區塊鏈瀏覽器資訊作對應

下回預告

嗚嗚嗚 這下還能觀察區塊鏈上所有資訊了

資訊是看透透了 不過比起看資訊 更想創建資訊!!!

虛擬貨幣 最基礎的就是交易

那那 可以直接進行交易嗎?

感覺超酷的吧 ~~~

下回 "DApp建立: 執行交易"


上一篇
DApp建立: 錢包(MetaMask) 結合運作
下一篇
DApp建立: 執行交易
系列文
從 區塊鏈 到 去中心化應用程式(DApp)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言