iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 9
1
Blockchain

又LAG的EOS.IO技術筆記系列 第 9

乙太坊經典範例 - 寵物商店(番外)

  • 分享至 

  • xImage
  •  

上次完成了經典範例,可是合約內容並沒有牽扯到數字貨幣的交換(除了gas)。今天帶大家快速的看一下數字貨幣交易的部份。

在此之前需要先了解一個概念 :「每個合約也都是一個帳號」,同樣可以收錢和付錢。乙太坊好像沒有直接由使用者A付錢給B的方法。不過從架構上思考也蠻合理的,先經由合約在轉發給對象。在EOS上雖然transfer可以指定要給誰,不過實際上,交易這部份EOS也完全是由智能合約定義。接著,我們試著以經典範例來修改(由於幾乎不會動到關鍵部份,完全全新的也是可以)。

修改合約,增加付費收費功能

在合約類別剛開始就先加入

  event LogMessage(string message);
  event LogValue(uint value);

  function pay() public payable{
    emit LogMessage("Pay: ");
    emit LogValue(msg.value);
  }

這是為了讓合約有付費的方式(payable)。這段除了可以呼叫以外,實際作用不太大。唯一要注意的是msg.value,這是呼叫這個方法的使用者,付給這份合約的數字貨幣(乙太幣)。

然後,是收錢的方法:

  function withdraw() public{
    emit LogMessage("Widthdraw: 1 ether");
    msg.sender.transfer(1 ether);
  }

同樣,要主意的只有msg.sender.transfer(1 ether);。這意思是由合約轉發1 ether給呼叫這個方法的人(sender)。語意上我覺得有點會讓人誤會,有點像是sender要發送(transfer)什麼給誰,按理需要兩個參數,實際只需要數量即可,這是因為是由合約發給sender。


接著,將網頁邏輯程式接上,在src/js/app.jsbindEvents增加:

    $(document).on('click', '#btn-pay', App.handlePay);
    $(document).on('click', '#btn-withdraw', App.handleWithDraw);

然後轉寫App提供的handlePayhandleWithDraw的方法:

  handlePay: function(event){
    event.preventDefault();

    var adoptionInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.Adoption.deployed().then(function(instance) {
        adoptionInstance = instance;

        // Execute adopt as a transaction by sending account
        return adoptionInstance.pay({
          from: web3.eth.accounts[0],
          gas: 3000000,
          value: 10**18*5,
        });
      }).then(function(result) {
        console.log(result);
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },
  handleWithDraw: function(event){
    event.preventDefault();

    var adoptionInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.Adoption.deployed().then(function(instance) {
        adoptionInstance = instance;

        // Execute adopt as a transaction by sending account
        return adoptionInstance.withdraw();
      }).then(function(result) {
        console.log(result);
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  }

當中value: 10**18*5,代表發送給合約5乙太幣。相對來說,一次能裡出來多少,就是在合約中定義的msg.sender.transfer(1 ether);


最後在網頁界面上加上兩個按鈕:

      <button id="btn-pay">Pay</button>
      <button id="btn-withdraw">Withdraw</button>

https://ithelp.ithome.com.tw/upload/images/20190925/20112470v732XjPsq1.png

pay的出發與以往不同,不只需要付出gas,還轉發了數字貨幣。同樣的,withdraw,也不同,雖然需要消耗gas,卻能獲得1 eth。

https://ithelp.ithome.com.tw/upload/images/20190925/20112470RqA54qM6tq.png

完整程式

合約程式

pragma solidity ^0.5.0;

contract Adoption {
  address[16] public adopters;

  event LogMessage(string message);
  event LogValue(uint value);

  // Adopting a pet
  function adopt(uint petId) public returns (uint) {
    require(petId >= 0 && petId <= 15);

    adopters[petId] = msg.sender;

    return petId;
  }

  // Retrieving the adopters
  function getAdopters() public view returns (address[16] memory) {
    return adopters;
  }

  function pay() public payable{
    emit LogMessage("Pay: ");
    emit LogValue(msg.value);
  }

  function withdraw() public{
    emit LogMessage("Widthdraw: 1 ether");
    msg.sender.transfer(1 ether);
  }

}

網頁js
https://www.codepile.net/pile/a2roLlkv

網頁
https://www.codepile.net/pile/6OWXMVYb


上一篇
區塊鏈限制三角
下一篇
EOS.IO學習資源
系列文
又LAG的EOS.IO技術筆記31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言