Upgrade to Pro — share decks privately, control downloads, hide ads and more …

DAppsを開発してみる

Shuichi Nagao
February 02, 2018

 DAppsを開発してみる

Ethereum上でDAppsを開発してみました。Solidityの話というよりはweb3.jsの利用に近いです。

Shuichi Nagao

February 02, 2018
Tweet

More Decks by Shuichi Nagao

Other Decks in Programming

Transcript

  1. DAPP։ൃΛͯ͠ΈΔ
    @NGO275 2018/2/2

    View full-size slide

  2. INTRODUCTION
    ࣗݾ঺հ
    ▸ ӬඌमҰ ( @ngo275 )
    ▸ AnyPay
    ▸ paymoͱ͔ICOίϯαϧͱ͔
    ▸ झຯ
    ▸ ےτϨɺதࠃޠ
    2

    View full-size slide

  3. AGENDA
    ࠓ೔࿩͢͜ͱ
    ▸ About DApp
    ▸ DApp Implementation
    ▸ Solidityͷ࣮૷ͱ͍͏ΑΓ͸web3.jsدΓͷ࿩
    ▸ ͚ͬ͜͏ॳ৺ऀ޲͚ʹͳΓ·͢
    ▸ Demo
    3

    View full-size slide

  4. ABOUT DAPP
    DAPP (DECENTRALIZED APPLICATION) CONCEPT
    ࢀߟ : https://blog.ethereum.org/2014/08/18/building-decentralized-web/
    4
    ࢀߟɿhttps://github.com/DavidJohnstonCEO/DecentralizedApplications

    View full-size slide

  5. ABOUT DAPP
    DAPPͷྫ
    CRYPTO KITTIES
    ೣΛҭͯΔήʔϜ
    ETHLANCE
    ࢓ࣄΛݟ͚ͭΔαΠτ
    5

    View full-size slide

  6. DAPP IMPLEMENTATION
    DAPP։ൃʹศརͳπʔϧ
    ▸ Ethereum clients
    ▸ geth
    ▸ parity
    ▸ Web3.js
    ▸ Solidity
    ▸ Frameworks
    ▸ Truffle
    ▸ Embark
    ▸ Metamask
    ࢀߟ: https://medium.com/blockchannel/tools-and-technologies-in-the-ethereum-ecosystem-e5b7e5060eb9
    6

    View full-size slide

  7. DAPP IMPLEMENTATION
    MEETUPͷΑ͏ͳΠϕϯτ؅ཧͷDAPPΛ࡞ͬͯΈΔ
    ▸ όοΫΤϯυʹEthereum্ͷεϚʔτίϯτϥΫτΛར༻
    ͢Δ
    ▸ ParityͰKovanΛར༻
    ▸ TruffleͱSolidityͰ࣮૷
    ▸ ϑϩϯτΤϯυ͸React+ReduxͰWeb3.jsΛར༻͠ͳ͕Β࣮
    ૷͢Δ
    7

    View full-size slide

  8. DAPP IMPLEMENTATION
    ࣮ݱ͢Δ΋ͷ͸͜Μͳײ͡
    ࢀՃඅ
    མબ͠ࢀՃඅ͕ฦ٫
    ౰બऀ෼ͷࢀՃඅ
    8

    View full-size slide

  9. DAPP IMPLEMENTATION
    SMART CONTRACTͷ࣮૷
    ▸ MeetupController.sol (Meetupͷ࡞੒ɺ؅ཧ)
    ▸ address[] meetups
    ▸ function getUpcomingMeetups()
    ▸ function newMeetup(string name, uint date, uint capacity, …)
    ▸ Meetup.sol (Meetup΁ͷԠืɺΩϟϯηϧɺԠืऀϦετ)
    ▸ Candidates[] candidates
    ▸ function apply()
    ▸ function cancel()
    ▸ function publishApprovedApplicants()
    9

    View full-size slide

  10. DAPP IMPLEMENTATION
    SMART CONTRACTͷ࣮૷ ~ MEETUP.SOL ~
    pragma solidity ^0.4.17;
    contract Meetup {
    address public organizer;
    string public name;
    string public place;
    uint public applicationStartedAt;
    uint public applicationEndedAt;
    uint public date;
    uint public minFee;
    uint public capacity;
    bool public aborted = false;
    struct Candidate {
    address applicantID;
    string name;
    uint fee;
    }
    function Meetup(address _organizer, string _name, string _place, uint _applicationStartedAt, uint
    _applicationEndedAt, uint _date, uint _minFee, uint _capacity, address _owner)
    public
    payable
    {
    organizer = _organizer;
    name = _name;
    place = _place;
    applicationStartedAt = _applicationStartedAt;
    applicationEndedAt = _applicationEndedAt;
    date = _date;
    minFee = _minFee;
    capacity = _capacity;
    }
    // Other methods like `apply()` ..
    }
    meetup.sol
    10

    View full-size slide

  11. DAPP IMPLEMENTATION
    SMART CONTRACTͷ࣮૷ ~ MEETUP.SOL ~
    function publishApprovedApplicants() public onlyAdmin() notAborted() returns (bool success) {
    uint amount;
    uint approvedApplicantsCount = 0;
    uint i;
    var applicantIDs = new address[](capacity);
    // Sort left candidates by each fee.
    Candidate[] memory tmp = sortedCandidates();
    // Fetch approved candidates until capacity < approvedApplicants.length
    for(i = 0; i < tmp.length; i++) {
    var _c = tmp[i];
    // Add candidates to refunds list if this event is full.
    if (_c.applicantID != 0x0 && approvedApplicantsCount == capacity) {
    refunds[_c.applicantID] += _c.fee;
    }
    // Add a candidate to approved applications list if this event is not full yet.
    if (_c.applicantID != 0x0 && approvedApplicants[_c.applicantID].applicantID == 0x0 &&
    approvedApplicantsCount < capacity) {
    approvedApplicants[_c.applicantID] = _c;
    feeAmount += _c.fee;
    applicantIDs[approvedApplicantsCount] = _c.applicantID;
    approvedApplicantsCount++;
    }
    }
    // Send applicants’ total fee to organizer.
    organizer.transfer(feeAmount);
    ApplicationApproved(applicantIDs);
    success = true;
    }
    meetup.sol ଓ͖
    11

    View full-size slide

  12. DAPP IMPLEMENTATION
    SMART CONTRACTͷ࣮૷ ~ MEETUPCONTROLLER.SOL ~
    pragma solidity ^0.4.17;
    import './Meetup.sol';
    contract MeetupController {
    address owner = msg.sender;
    address[] meetups;
    MeetupObject[] meetupObjects;
    struct MeetupObject {
    address identifier;
    uint applicationStartedAt;
    uint applicationEndedAt;
    uint date;
    }
    event MeetupSet(
    address meetupAddress,
    address _organizer, string _name,
    string _place,
    uint _applicationStartedAt, uint _applicationEndedAt, uint _date,
    uint _minFee, uint _capacity
    );
    function setupMeetup(address _organizer, string _name, string _place, uint _applicationStartedAt, uint
    _applicationEndedAt, uint _date, uint _minFee, uint _capacity)
    public
    returns (address meetupAddress)
    {
    meetupAddress = new Meetup(_organizer, _name, _place, _applicationStartedAt, _applicationEndedAt, _date,
    _minFee, _capacity, owner);
    MeetupSet(meetupAddress, _organizer, _name, _place, _applicationStartedAt, _applicationEndedAt, _date,
    _minFee, _capacity);
    }
    // Other methods like sorting ..
    }
    meetupController.sol
    12

    View full-size slide

  13. DAPP IMPLEMENTATION
    WEB3.JSͰSMART CONTRACTΛར༻͢Δ ~PROVIDER~
    import * as Web3 from 'web3';
    export function setupWeb3() {
    if (typeof window.web3 !== 'undefined') {
    window.web3 = new Web3(window.web3.currentProvider);
    } else {
    window.web3 = new Web3(new Web3.providers.HttpProvider('http://
    localhost:8545'));
    }
    }
    export function getBlockNumber() {
    const web3 = window.web3;
    return new Promise((resolve, reject) => {
    web3.eth.getBlockNumber((err, blockNumber) => {
    if (err) {
    reject(err);
    return;
    }
    resolve(blockNumber);
    });
    });
    }
    ethereum.js
    13

    View full-size slide

  14. DAPP IMPLEMENTATION
    WEB3.JSͰSMART CONTRACTΛར༻͢Δ ~INITIALIZE CONTRACT~
    ▸ Smart ContractΛ࣮ߦ͢Δͷʹඞཁͳ΋ͷ
    ▸ ABI (Application Binary Interface)
    ▸ ίϯτϥΫτͷϓϩύςΟ΍ϝιουͷఆٛҰཡ
    ▸ Contract Address
    ▸ ίϯτϥΫτΛσϓϩΠͨ͠ઌͷΞυϨε
    export default const Contract = {
    meetupABI: [{“hogehgoehoge”: “fugafuga”}, {..}],
    meetupControllerABI: [{“hogehgoehoge”: “fugafuga”}, {..}],
    meetupControllerAddress: '0xB2Ec115F9349Ff7f11a9E0a029ce2af130830bf3'
    }
    Contract.js
    14

    View full-size slide

  15. DAPP IMPLEMENTATION
    WEB3.JSͰSMART CONTRACTΛར༻͢Δ ~CALL~
    import * as eth from ‘../utils/ethereum’;
    export function meetupControllerInstance() {
    return new window.web3.eth.Contract(
    Contract.meetupControllerABI, Contract.meetupControllerAddress);
    }
    export async function getUpcomingMeetups() {
    eth.setupDefaultAccount();
    return new Promise((resolve, reject) => {
    meetupControllerInstance().methods.getUpcomingMeetups().call()
    .then(result => {
    resolve(result);
    })
    .catch(error => {
    reject(error.message);
    return;
    });
    });
    }
    meetup.js
    15

    View full-size slide

  16. DAPP IMPLEMENTATION
    WEB3.JSͰSMART CONTRACTΛར༻͢Δ ~CALL~
    import * as eth from ‘../utils/ethereum’;
    export function meetupControllerInstance() {
    return new window.web3.eth.Contract(
    Contract.meetupControllerABI, Contract.meetupControllerAddress);
    }
    export async function getUpcomingMeetups() {
    eth.setupDefaultAccount();
    return new Promise((resolve, reject) => {
    meetupControllerInstance().methods.getUpcomingMeetups().call()
    .then(result => {
    resolve(result);
    })
    .catch(error => {
    reject(error.message);
    return;
    });
    });
    }
    meetup.js
    CONSTANTͳϝιου͸
    CALL()ͰݺͿ
    GASͷফඅ͸ͳ͍
    16

    View full-size slide

  17. DAPP IMPLEMENTATION
    WEB3.JSͰSMART CONTRACTΛར༻͢Δ ~SEND~
    import * as eth from ‘../utils/ethereum’;
    export function meetupControllerInstance() {
    return new window.web3.eth.Contract(
    Contract.meetupControllerABI, Contract.meetupControllerAddress);
    }
    export async function newMeetup(name, place, applicationStartedAt,
    applicationEndedAt, date, minFee, capacity) {
    eth.setupDefaultAccount();
    const minFeeETH = minFee * (10 ** 18);
    return new Promise((resolve, reject) => {
    meetupControllerInstance().methods
    .setupMeetup(window.web3.eth.defaultAccount, name, place,
    applicationStartedAt, applicationEndedAt, date, minFeeETH, capacity)
    .send({from: window.web3.eth.defaultAccount})
    .then(result => {
    resolve(result);
    })
    .catch(error => {
    return;
    });
    });
    }
    meetup.js
    PAYABLEͳϝιου͸SEND()ͰݺͿ
    METAMASKͰαΠϯΛٻΊΒΕΔ
    17

    View full-size slide

  18. DEMO
    σϞᶃ
    18

    View full-size slide

  19. DEMO
    σϞᶄ
    19

    View full-size slide

  20. CONCLUSION
    ·ͱΊ
    ▸ ݁ߏgas͕͔͔Δ͠Ethereum্Ͱͷෳࡶͳॲཧ͸ආ͚͍ͨ
    ▸ Solidity͸ if / for Ͱଟ͘ϩδοΫΛॻ͘͜ͱʹͳΔ
    ▸ filter΍cointains͕ͳ͍
    ▸ ձһొ࿥΍ϩάΠϯͱ͍͏֓೦ͳ͠ʹΞϓϦΛ࡞ΕΔ
    ▸ ϞόΠϧͷDApp browserͷѻ͍͕·ͩඍົ
    ▸ https://github.com/ngo275/Meethereum
    20

    View full-size slide