Ethereum Solidity + Vue.jsチュートリアル10分で簡単なオークションDapp

こんにちはhabr!最近、ロシア語を話す聴衆がブロックチェーンの世界に入り、そこで発展するためのチュートリアルがほとんどないことに気づきました。Ethereumのスマートコントラクトに関する記事を共有することにしました。この記事はかつて私を大いに助け、ブロックチェーンの世界を掘り下げ、そこでスマートな契約を開発しました。このリンクの元の記事





物を売買できるオークションについて聞いたことがあるかもしれません。これは非常に便利ですが、売り手はオークション管理会社にサービス料金を支払うために収益の約10%を要します。





会社が取引自体の一部をだまして支払いを受けた場合、だまされたかどうかをどうやって知ることができますか?





これは、分散インストールが最適なソリューションであるところです。

第三者がいない場合、売り手は安全な方法でより多くを稼ぐことができます。





機能リスト

  1. オークションの作成





  2. 賭けをする





  3. オークション終了





ツール

  1. スマート契約ソリディティ 、 リミックス 、  Metamask





  2. AフロントエンドWeb3.js  、  Vue.js  、 ヴュー・クレー 、 ブートストラップ-VU





前提条件

  1. MetaMask





  2. Remix IDE





  3. -





Github

, :

https://github.com/openberry-ac/Auction





?

- - , .





- , , - , , .





  1. -





  2. - Web3.js





  3. :





-

Ethereum,  Solidity , , -.





 Remix   AuctionBox.sol  :





// AuctionBox.sol
// We will be using Solidity version 0.5.3
pragma solidity 0.5.3;
// Importing OpenZeppelin's SafeMath Implementation
import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/SafeMath.sol";

contract AuctionBox{
    
    Auction[] public auctions; 
   
    function createAuction (
        string memory _title,
        uint _startPrice,
        string memory _description
        ) public{
        // set the new instance
        Auction newAuction = new Auction(msg.sender, _title, _startPrice, _description);
        // push the auction address to auctions array
        auctions.push(newAuction);
    }
    
    function returnAllAuctions() public view returns(Auction[] memory){
        return auctions;
    }
}

contract Auction {
    
    using SafeMath for uint256;
    
    address payable private owner; 
    string title;
    uint startPrice;
    string description;

    enum State{Default, Running, Finalized}
    State public auctionState;

    uint public highestPrice;
    address payable public highestBidder;
    mapping(address => uint) public bids;
    
    /** @dev constructor to creat an auction
      * @param _owner who call createAuction() in AuctionBox contract
      * @param _title the title of the auction
      * @param _startPrice the start price of the auction
      * @param _description the description of the auction
      */
      
    constructor(
        address payable _owner,
        string memory _title,
        uint _startPrice,
        string memory _description
        
        ) public {
        // initialize auction
        owner = _owner;
        title = _title;
        startPrice = _startPrice;
        description = _description;
        auctionState = State.Running;
    }
    
    modifier notOwner(){
        require(msg.sender != owner);
        _;
    }
    
    /** @dev Function to place a bid
      * @return true
      */
    
    function placeBid() public payable notOwner returns(bool) {
        require(auctionState == State.Running);
        require(msg.value > 0);
        // update the current bid
        // uint currentBid = bids[msg.sender] + msg.value;
        uint currentBid = bids[msg.sender].add(msg.value);
        require(currentBid > highestPrice);
        // set the currentBid links with msg.sender
        bids[msg.sender] = currentBid;
        // update the highest price
        highestPrice = currentBid;
        highestBidder = msg.sender;
        
        return true;
    }
    
    function finalizeAuction() public{
        //the owner and bidders can finalize the auction.
        require(msg.sender == owner || bids[msg.sender] > 0);
        
        address payable recipiant;
        uint value;
        
        // owner can get highestPrice
        if(msg.sender == owner){
            recipiant = owner;
            value = highestPrice;
        }
        // highestBidder can get no money
        else if (msg.sender == highestBidder){
            recipiant = highestBidder;
            value = 0;
        }
        // Other bidders can get back the money 
        else {
            recipiant = msg.sender;
            value = bids[msg.sender];
        }
        // initialize the value
        bids[msg.sender] = 0;
        recipiant.transfer(value);
        auctionState = State.Finalized;
    }
    
    /** @dev Function to return the contents od the auction
      * @return the title of the auction
      * @return the start price of the auction
      * @return the description of the auction
      * @return the state of the auction 
      */    
    
    function returnContents() public view returns(        
        string memory,
        uint,
        string memory,
        State
        ) {
        return (
            title,
            startPrice,
            description,
            auctionState
        );
    }
}
      
      



.  , , «AuctionBox», !





, , AuctionBox.





Remix   Ropsten.





, , Remix:   AuctionBox .





!





 createAuction .





 returnAllAuctions  !





-





- , , -.





, , .  ( /Powershell Windows):





# git clone the project template
git clone -b boilerplate --single-branch https://github.com/openberry-ac/Auction.git
# go inside the folder
cd Auction
# install packages needed in the web application
npm install
# install web3, this is for connecting the contract 
npm install -s web3@1.0.0-beta.37
# To run the app
npm run dev
      
      



 http://localhost:8080/





web3.js

 web3.js    , :





// web3.js
import Web3 from 'web3';

if (window.ethereum) {
  window.web3 = new Web3(ethereum);
  try {
    // Request account access if needed
    ethereum.enable();
  } catch (error) {
    // User denied account access...
  }
} else if (window.web3) { // Legacy dapp browsers...
  window.web3 = new Web3(web3.currentProvider);
} else { // Non-dapp browsers...
  console.log('Non-Ethereum browser detected. You should consider trying MetaMask!');
}
console.log(web3);
export default web3;
      
      



,  web3



, Metamask, .  -.





MetaMask , .  «» :





-

ABI - , -.  ABI,  Remix ,   Compile   ABI  Details, :





,   «  » « » , :





   ABI  ABI.





,   AuctionBoxInstance.js  AuctionInstance.js  e contracts,      ABI «s  , :





//AuctionBoxInstance.js
import web3 from './web3';

const address = ''// THE CONTRACT ADDRESS
const abi = []// THE ABI

const instance = new web3.eth.Contract(abi, address);

export default instance;
      
      



// AuctionInstance.js
import web3 from './web3';

const abi = []// THE ABI
// Here is just only abi because we haven't created auction yet.
export default (address) => {
  const instance = new web3.eth.Contract(abi, address);
  return instance;
};
      
      







, , .  , , .  App.vue  src  !





beforeMount





, .





// App.vue
beforeMount() {
  // get auctionBox method: returnAllAuctions()
  auctionBox.methods
    .returnAllAuctions()
    .call()
    .then((auctions) => {
      console.log(auctions);
      // set the amount of auctions
      this.amount = auctions.length;
    });
},
      
      







, , .





// App.vue
createAuction() {
  // get accounts
  web3.eth.getAccounts().then((accounts) => {
    // convert 'ether' to 'wei'
    const startPrice = web3.utils.toWei(this.startPrice, 'ether');
    // createAuction in AuctionBox contract
    this.isLoad = true;
    return auctionBox.methods.createAuction(this.title, startPrice, this.description)
      .send({ from: accounts[0] });
  }).then(() => {
    // initialize forms
    this.isLoad = false;
    this.title = '';
    this.startPrice = '';
    this.description = '';
    // get the previous auction
    return auctionBox.methods.returnAllAuctions().call();
  }).then((auctions) => {
    const index = auctions.length - 1;
    console.log(auctions[index]);
    // get the contract address of the previous auction
    this.auctionAddress = auctions[index];
    // set the address as the parameter
    const auctionInstance = auction(auctions[index]);
    return auctionInstance.methods.returnContents().call();
  })
    .then((lists) => {
      console.log(lists);
      const auctionlists = lists;
      // convert 'wei' to 'ether'
      auctionlists[1] = web3.utils.fromWei(auctionlists[1], 'ether');
      this.auctionCard = auctionlists;
      // show up the auction at the bottom of the page
      this.isShow = true;
      this.amount += 1;
    })
    .catch((err) => {
      console.log(err);
    });
},
      
      







, .





// App.vue
handleSubmit() {
  // convert 'ether' to 'wei'
  const bidPriceWei = web3.utils.toWei(this.bidPrice, 'ether');
  // get the wallet adddress
  const fromAddress = web3.eth.accounts.givenProvider.selectedAddress;
  // set the address as the parameter
  const selectedAuction = auction(this.auctionAddress);
  this.isBid = true;
  // placeBid in Auction contract
  selectedAuction.methods
    .placeBid()
    .send({
      from: fromAddress,
      value: bidPriceWei,
    })
    .then(() => {
      this.isBid = false;
      // increase the number of bidders
      this.bidders += 1;
      this.bidPrice = '';
    });
},
      
      







, .





// App.vue
handleFinalize() {
  // get accounts
  web3.eth.getAccounts().then((accounts) => {
    // set the address as the parameter
    const selectedAuction = auction(this.auctionAddress);
    this.isFin = true;
    // finalizeAuction in Auction contract
    selectedAuction.methods
      .finalizeAuction()
      .send({ from: accounts[0] })
      .then(() => {
        this.isFin = false;
        this.finalizeStatus = 'finalized';
      });
  });
},
      
      



Remix, .





9 , :





!!





, .  - , !  :





: , , . , ( ), .





. , .





, - web3.js.  , Vue.js, .





では、次は何ですか?





これは実際のオークションアプリケーションでは重要であるため、「期限」のロジックを追加することをお勧めします。複雑さを避けて時間を短縮するために、今はスキップしましたが、ビルドしてみたけれ ば、大いに役立ちます





このチュートリアルの完全なコードが必要な場合は、ここで確認できます。








All Articles