iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 23
0
Blockchain

區塊練起來-智能合約與DApp開發系列 第 23

[區塊練起來-智能合約與DApp開發] DAY 23 - web3.js 結合 Truffle 部署合約

貼心小語

上一篇學會了如何發起交易,這一篇將會進入到另一個重要功能,就是部署合約!


為什麼用 Truffle?

應該有人看到標題就想問:為什麼已經用了專用函式庫 web3.js ,還要在前端使用 Truffle 呢?難道 web3.js 不能部署合約嗎?其實 web3.js 可以部署合約的,但是當合約需要與函式庫做連結時就會十分麻煩,幸好 Truffle 有提供相關的方法讓我們能夠輕鬆把函式庫與合約接在一起,可喜可賀~/images/emoticon/emoticon07.gif

要怎麼在前端用 Truffle?

我們其實只需要使用 Truffle 的部分功能,所以安裝要的功能即可,方法很簡單,在專案中使用 npm 安裝@truffle/contract

npm install @truffle/contract

然後我們在 ProviderService 中使用:

declare let require: any;
const TruffleContract = require('@truffle/contract');

這樣前置作業就完成了!

部署合約

我們接下來會用之前設計的 Resume.solStrLib.sol 來示範部署合約及函式庫。先將智能合約進行編譯:

truffle compile

使用 ABI 與 bytecode

部署智能合約需要用到 ABIbytecode ,而這些資訊放在 Resume.jsonStrLib.json 中,所以我們要將這兩個檔案引入。先在 types 資料夾中新增 contract.ts ,並從 index.tsexport

export * from './contract';

接著在 contract.ts 中使用 require 來引入 Resume.jsonStrLib.json

declare let require: any;

export const ResumeContract = require('../../../truffle/build/contracts/Resume.json');
export const StrLibContract = require('../../../truffle/build/contracts/StrLib.json');

如此一來,就可以從 ResumeContractStrLibContract 中取得 ABIbytecode 囉!

設計方法

Resume 合約在部署時需要帶上 nameaddressagegender 資訊,所以我們來定義資料格式,就放在 contract.ts 中:

export interface ResumeInitialOptions {
    name: string;
    address: string;
    age: number;
    gender: number;
}

好了之後開始定義我們部署合約的方法。一開始要先將編譯的合約帶入 TruffleContract 中,並且要設定 Provider ,理所當然地使用 this.web3.currentProvider ,這邊需要特別去指定 Resume 合約使用的 networkId ,否則會報錯,然後透過 new 進行部署,需要先將 StrLib 部署,再將 StrLib 的合約位址與 Resume 透過 link(name, address) 做連結,然後才部署 Resume 合約:

public deployResume(info: ResumeInitialOptions): Observable<any> {
    const strLib = TruffleContract(StrLibContract);
    const resume = TruffleContract(ResumeContract);
    strLib.setProvider(this.web3.currentProvider);
    resume.setProvider(this.web3.currentProvider);
    resume.setNetwork(this.web3.currentProvider.networkVersion);
    return from(strLib.new({ from: this.defaultAccount })).pipe(
        mergeMap((instance: any) => {
            resume.link('StrLib', instance.address);
            return resume.new(info.name, info.address, info.age, info.gender, { from: this.defaultAccount });
        }),
        take(1)
    );
}

這個設計方法是展示如何部署函式庫與合約,並且連結剛部署上去的 library 合約,真實應用場景可以先用 truffle migrate 把 StrLib 部署上去,再把 address 記起來填入 link(name, address) 中即可。

測試

老樣子在 app.component.ts 中做測試:

constructor(private provider: ProviderService) {
    const info = {
        name: 'HAO',
        address: '0x579c43911C862E16fEB199233ec2d32e441b7713',
        age: 21,
        gender: 0
    } as ResumeInitialOptions;
    this.provider.getAccount().pipe(
        take(1),
        mergeMap(accounts => {
            this.provider.defaultAccount = accounts[0];
            return this.provider.deployResume(info);
        })
    ).subscribe(instance => {
        console.log(instance);
    });
}

這時候打開網頁會跳出 MetaMask ,第一個是 StrLib 的交易請求:
https://ithelp.ithome.com.tw/upload/images/20190913/20119338FOTQkP0pmZ.png
按下確定後會跳出 Resume 的交易請求:
https://ithelp.ithome.com.tw/upload/images/20190913/20119338QnRkm8vjga.png
都完成後到 Ganache 中查看交易內容:
https://ithelp.ithome.com.tw/upload/images/20190909/20119338seGlFZ1Nmp.png
這樣就成功部署啦~~


今日小結

借助 web3.js 來取得 Provider ,然後透過 Truffle 部署合約,並且能夠與 library 做連結,這部分算是 DApp 的核心功能之一,務必熟悉!


參考資料

Truffle 的 Github


上一篇
[區塊練起來-智能合約與DApp開發] DAY 22 - web3.js 發起交易
下一篇
[區塊練起來-智能合約與DApp開發] DAY 24 - web3.js 呼叫合約
系列文
區塊練起來-智能合約與DApp開發31

尚未有邦友留言

立即登入留言