Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

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. INTRODUCTION ࣗݾ঺հ ▸ ӬඌमҰ ( @ngo275 ) ▸ AnyPay ▸

    paymoͱ͔ICOίϯαϧͱ͔ ▸ झຯ ▸ ےτϨɺதࠃޠ 2
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. CONCLUSION ·ͱΊ ▸ ݁ߏgas͕͔͔Δ͠Ethereum্Ͱͷෳࡶͳॲཧ͸ආ͚͍ͨ ▸ Solidity͸ if / for Ͱଟ͘ϩδοΫΛॻ͘͜ͱʹͳΔ

    ▸ filter΍cointains͕ͳ͍ ▸ ձһొ࿥΍ϩάΠϯͱ͍͏֓೦ͳ͠ʹΞϓϦΛ࡞ΕΔ ▸ ϞόΠϧͷDApp browserͷѻ͍͕·ͩඍົ ▸ https://github.com/ngo275/Meethereum 20