# DApp建立: 智能合約的互動
## 智能合約的互動
**"智能合約的互動"** 是 **"DApp(去中心應用程序)"** 變為更多可能性的契機
為甚麼這麼說呢?
其實早在比特幣出現時就有人提出DApp(去中心應用程序)
其實根本原因 **"區塊鏈就是一種資料庫"**(在實踐區塊鏈時應能理解)
### 在傳統的 主從式架構應用程序(App、Website)

* 傳統應用程序(根據客戶不同請求 查詢資料庫後回答)
### 去中心化應用程序架構(未有智能合約)
那既然 **區塊鏈就是一種資料庫(公開的)**
完全沒必要依賴 中心化後端給予的回覆 **自己查詢即可**

* 是能擺脫中心化後端的需求 不過略顯無聊
### 去中心化應用程序架構(有智能合約)
而 智能合約 本質上就是程序 根據不同選擇有不同回應
這樣的特性導致 **智能合約就類似傳統後端功能** (不過在區塊鏈上且公開的)

* 增加互動的環節(可以根據不同的請求有不同的回覆)
---
理解對於智能合約 如何讓 DApp(去中心應用程序) 變得更趣味後
接下來這篇將以下重點進行敘述:
1. 專案規劃
2. 合約互動的函式
3. 最終呈現畫面
4. 合約的互動
**另外可參考 GitHub 專案位置:**
https://github.com/weiawesome/dapp_website
## 專案規劃
### 佈局規劃

* 標題
```寫下本頁面的目標```
* 合約地址 與 合約 ABI 文件
```分別得知合約的位置 與 內容輸入輸出```
* 執行合約互動區塊
```執行交易的按鈕```
* 函式、事件 選擇
```選擇觀察事件或是執行函式```
* 輸入參數
```根據該筆事件或函數有不同的參數```
* 是否轉帳金額
```當函式可以付款時 詢問付款金額```
* 執行結果
```即與合約的互動結果```
* 新增執行區塊
```可新增與上方相同的新一個區塊```
```方便同時執行不同函式或觀察事件```
### 架構規劃
```
├── src
│ ├── app
│ ├── pages
│ │ ├── interact_contract.tsx
│ ├── style
│ │ ├── interact_contract.css
│
```
"src/app/pages/interact_contract.tsx" 邏輯與基本布局
"src/app/style/interact_contract.css" 對上述畫面的修飾
**因此 最後畫面會顯示在 /interact_contract 這個路由下**
### 執行合約互動的內容
```typescript
// 合約方法或事件的資訊
class ContractMethod{
// 合約執行結果
Result:string;
// 種類 (函式或事件)
Type:string;
// 方法名稱 或 事件名稱
Method:string;
// 執行方法的參數
Parameters:string[];
// 執行方法或事件的序列
Index:number;
// 是否可付款
Payable:boolean;
// 金額
Amount:number;
}
```
## 合約互動的函式
```typescript
// 合約互動的方法
const ContractInteraction=async (index) => {
// 檢查是否安裝 MetaMask
if (typeof window.ethereum !== 'undefined') {
// 定義 合約地址 與 ABI
const contractAddress = addressRef.current!.value;
const contractAbi = abiContent;
await window.ethereum.request({method: 'eth_requestAccounts'});
// 連線 MetaMask
const provider=new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
// 建立合約實體
const contract = new ethers.Contract(contractAddress, contractAbi, signer);
// 對於觀察事件的處理方式 其他則為函式
if (workers[index].Type==="event"){
const filter = contract.filters[workers[index].Method]();
const events = await contract.queryFilter(filter);
let tmp=[...workers]
let ans=[];
for (let i = 0; i < events.length; i++) {
// @ts-ignore
ans.push({"index":i,"Value":events[i].args.toString()})
}
tmp[index].Result=JSON.stringify(ans);
setWorkers(tmp);
} else{
// 對於函式可以付款的方式 其他則為非付款
if (workers[index].Payable===true){
const basicFoundation = ethers.parseEther(workers[index].Amount.toString());
await contract[workers[index].Method](...workers[index].Parameters,{value:basicFoundation}).then((result)=>{
console.log("Result: ",result.toString());
let tmp=[...workers];
tmp[index].Result=result.toString();
setWorkers(tmp);
}).catch((e)=>{
alert(e);
})
} else{
await contract[workers[index].Method](...workers[index].Parameters).then((result)=>{
console.log("Result: ",result);
let tmp=[...workers];
tmp[index].Result=result.toString();
setWorkers(tmp);
}).catch((e)=>{
alert(e);
})
}
}
} else {
alert('請安裝 MetaMask 錢包並連接到網絡');
}
}
```
1. 載入對於合約的各種基本資訊 包含 地址、ABI
2. 連線 MetaMask 錢包 並且獲得許可
3. 根據內容執行函式 或 觀察事件
4. 將結果寫進目標結果的位置
## 最終呈現畫面

* UI 與上方規劃相同
* 可以根據不同的合約選擇不同的函式或事件
## 合約的互動
(詳細部署與撰寫智能合約的方式請詳見 **智能合約開發** 章節)
### 公平、公正投票
#### 1. 部署智能合約

* 基礎資金為 10 ETH 投票、開票時間 與 合約地址
#### 2. 填充合約資訊

* 填入上方合約地址 與 選擇 ABI 檔案
#### 3. 函示範例

* 此為註冊為候選人之函式
#### 4. MetaMask 確認畫面(如果需要付款才會出現)

* 確認轉款金額 與 目標地址
#### 5. 事件範例

* 確實為剛才所登記參選的資料
### 群眾募資
#### 1. 部署智能合約

* 顯示合約部署的地址
#### 2. 填充合約資訊

* 填入上方合約地址 與 選擇 ABI 檔案
#### 3. 函示範例

* 此為向平台提案的函示
#### 4. MetaMask 確認畫面(如果需要付款才會出現)

* 確認轉款金額 與 目標地址
#### 5. 事件範例

* 確實新增一筆剛才的提案 (可以看見子合約的地址)
## 結言
由於**篇幅有限**
最後在示範與合約互動時 僅挑出幾個進行示例
若是有興趣可以**下載專案**
並且來**嘗試與智能合約的互**動 真心蠻有趣的
希望透過這篇能理解
1. 如何與智能合約互動
2. 智能合約 為 DApp(去中心化應用程序) 帶來的變化
## 下回預告
感覺程序瞬間變得超有趣 對吧~~~
也瞬間增加了許多可能性
既能**以此做為投票** 還能**建立群眾募資** 等等等等
這一切都多虧與智能合約的互動 使許多功能都成為了可能
只能說瞬間感到一身輕 擺脫了傳統的後端限制
**寫完前端 是時候來處理後端**
等等等!!! 甚麼不是才剛擺脫(後端)的需求嗎?
為甚麼還要使用後端呢?
這樣**還算是去中心化**嗎
這不是**完全違背了核心理念**嗎?
鐵定有很多疑問吧!
### 下回 "DApp建立: 後端服務尬上來"