# DApp建立: 執行交易 ## 交易的執行 **交易** 當然也是 **去中心化應用** 極為重要的一環 那要如何執行交易呢? 如果一個**程序能直接控制資產**不是很恐怖嗎? 要是**金額瞬間被轉走**怎麼辦呢? 因此我們要透過 錢包(MetaMask) 程序本身只是**提供建議交易** 再由使用者同意 **最後的同意權 仍舊落在使用者身上** 這篇將以下重點進行敘述: 1. 專案規劃 2. 透過 web3.js 進行交易 3. 透過 ethers.js 進行交易 4. 最終呈現畫面 **另外可參考 GitHub 專案位置:** https://github.com/weiawesome/dapp_website ## 專案規劃 ### 佈局規劃 ![](https://hackmd.io/_uploads/BkJAu-N-6.png) * 標題 ```寫下本頁面的目標``` * 交易目標地址 與 交易金額 ```要傳送給的帳戶地址與金額``` * 交易按鈕 ```執行交易的按鈕``` * 關於交易資訊 ```顯示該筆交易資訊``` * 交易查詢區域 ```顯示該筆交易所在的區塊的區塊資訊``` ### 架構規劃 ``` ├── src │ ├── app │ ├── pages │ │ ├── build_transaction.tsx │ ├── style │ │ ├── build_transaction.css │ ``` "src/app/pages/build_transaction.tsx" 邏輯與基本布局 "src/app/style/build_transaction.css" 對上述畫面的修飾 **因此 最後畫面會顯示在 /build_transaction 這個路由下** ### 交易收據呈現 ```typescript // 交易結果物件 class Receipt{ // 交易哈希 TransactionHash:string; // 交易發起人 From:string; // 交易接收人 To:string | null; // 交易所在的區塊 的 區塊哈希 BlockHash:string; // 交易所在的區塊 的 區塊高度 BlockHeight:number| null } ``` ## 透過 web3.js 進行交易 ```typescript // 建立並執行交易 透過 web3.js const BuildTransactionWeb3=async () => { try { if (!window.ethereum || !window.ethereum.isConnected()) { throw new Error('請安裝 MetaMask 並連接到一個 Ethereum 網路'); } const provider = window.ethereum; const web3 = new Web3(provider); const toAddress = addrRef.current?.value; const amountToSend = web3.utils.toWei(valueRef.current!.value, 'ether'); const accounts = await window.ethereum.request({method: 'eth_requestAccounts'}); const account = accounts[0]; const transactionObject = { from: account.toString(), to: toAddress, value: amountToSend, }; web3.eth.sendTransaction(transactionObject) .on('transactionHash', hash => { console.log('交易哈希:', hash); }) .on('receipt', transactionReceipt => { console.log('交易收據:', transactionReceipt); let tmp = new Receipt(); tmp.BlockHeight = Number(transactionReceipt!.blockNumber); tmp.BlockHash = transactionReceipt!.blockHash; tmp.TransactionHash = transactionReceipt!.transactionHash; tmp.From = transactionReceipt!.from; tmp.To = transactionReceipt!.to; setR(tmp); }) .on('error', error => { }) } catch (error) { console.log(error); } } ``` * 首先先連線 MetaMask 帳戶 * 填充交易資訊 * 執行交易並且記錄資訊 ## 透過 ethers.js 進行交易 ```typescript // 建立並執行交易 透過 ethers.js const BuildTransactionEthers=async () => { try { if (!window.ethereum || !window.ethereum.isConnected()) { throw new Error('請安裝 MetaMask 並連接到一個 Ethereum 網路'); } let provider = new ethers.BrowserProvider(window["ethereum"]); const signer =await provider.getSigner(); const tx = { to: addrRef.current!.value, value: parseEther(valueRef.current!.value), }; const transactionResponse = await signer.sendTransaction(tx); console.log(transactionResponse); const transactionReceipt = await transactionResponse.wait(); let tmp=new Receipt(); tmp.BlockHeight=transactionReceipt!.blockNumber; tmp.BlockHash=transactionReceipt!.blockHash; tmp.TransactionHash=transactionReceipt!.hash; tmp.From=transactionReceipt!.from; tmp.To=transactionReceipt!.to; setR(tmp); console.log(transactionReceipt); } catch (error) { console.error('提交交易時發生錯誤:', error); } } ``` * 首先先連線 MetaMask 帳戶 * 填充交易資訊 * 執行交易並且記錄資訊 ## 最終呈現畫面 ### 初始網頁畫面 ![](https://hackmd.io/_uploads/B1a3xbVWa.png) ### 匯入帳戶 與 轉帳資訊 #### Ganache 畫面 ![](https://hackmd.io/_uploads/BygRqcZEWp.png) 由於 現實資金轉移 需要手續費 可是我沒有 Money~Money(嗚嗚嗚) 因此使用 Ganache 做為模擬 OKKKKK~~~ 接下來 就把 **第一個帳戶 轉金額給 第二個帳戶** #### 匯入帳戶到 MetaMask ##### 1. 複製私鑰 ![](https://hackmd.io/_uploads/ryCg2-4Wp.png) * 首先帳戶右方鑰匙圖示 並且複製私鑰 ##### 2. 匯入帳戶 ![](https://hackmd.io/_uploads/S1lDnW4Za.png) * 點選匯入帳戶 並且貼上 剛複製的私鑰 ##### 3. 調整區塊鏈網路 ![](https://hackmd.io/_uploads/rJCTFMN-a.png) * 點擊設定並選擇新增網路(確保 Ganache 保持開啟) ##### 4. 成功匯入帳戶 ![](https://hackmd.io/_uploads/ByPyTWNbT.png) * 登入成功(記得選擇網路 本地的 Ganache) #### 填充交易資訊 ![](https://hackmd.io/_uploads/BkwDaWNbp.png) * 複製上處第二個帳戶的地址 並且輸入轉帳金額 ### 透過 web3.js 進行交易 #### 取得帳戶權限 ![](https://hackmd.io/_uploads/S1o7ZfVbp.png) * 首先必須獲得帳戶允許對於這個網站的操作 #### 確認交易 ![](https://hackmd.io/_uploads/HJQERbNZT.png) * 由本人再進行確認交易的內容 #### 察看交易結果 ![](https://hackmd.io/_uploads/HyFPR-EZp.png) * 結果包含 交易資訊 與 區塊資訊 #### 透過 Ganache 檢查 ![](https://hackmd.io/_uploads/rkhhAbEWp.png) * 與上圖對應 不論是區塊資訊或是交易資訊都相符 ### 透過 ethers.js 進行交易 #### 取得帳戶權限 ![](https://hackmd.io/_uploads/SJSIxGN-p.png) * 首先必須獲得帳戶允許對於這個網站的操作 #### 確認交易 ![](https://hackmd.io/_uploads/ByU6lGV-6.png) * 由本人再進行確認交易的內容 #### 察看交易結果 ![](https://hackmd.io/_uploads/HyTtWzVWp.png) * 結果包含 交易資訊 與 區塊資訊 #### 透過 Ganache 檢查 ![](https://hackmd.io/_uploads/BJxjWME-p.png) * 與上圖對應 不論是區塊資訊或是交易資訊都相符 ### 最後觀察 Ganache 帳戶狀態 ![](https://hackmd.io/_uploads/rJRUzzVWp.png) 藉由上方兩筆交易: * 區塊上增加兩塊 * 第二個帳戶多 20 ETH 第一個帳戶少 20 ETH ## 結言 透過撰寫前端程序 並配合 MetaMask 完成交易 儘管完成了轉帳 但會發現很大程度**需要使用者的互動** 而無法完全自動化 這是為何呢? 在區塊鏈中 虛擬貨幣的轉移 尤其又與資產有關 **因此對於控制性與安全性就非常重要** 透過一定程度的與使用者互動 確保了它的安全性 當然 DApp(去中心化應用程序) 也是有許多功能會自動化 而無須手動授權 不過仍是要在 **安全性** 與 **便利性** 中取得平衡 希望透過這篇能理解 1. 透過 web3.js 配合 MetaMask 執行交易 2. 透過 ethers.js 配合 MetaMask 執行交易 ## 下回預告 現在透過程序還能轉帳了呢!!! 很有趣吧! 感覺好像很有樣子對嗎? 不過知道 **去中心化應用程序(DApp) 的起源**嗎? 早在 比特幣 出現時 就有類似的概念了 不過直到 **"智能合約"** 的出現 讓人發現 **去中心化應用程序(DApp)** 不必再侷限於**單純的資金轉移** 更多的想法與應用也隨之而生!!! ### 下回 "DApp建立: 智能合約的互動"