'이더리움'에 해당되는 글 4건

  1. 2018.08.23 Truffle 5.0.0 Beta출시
  2. 2018.07.15 Ethereum dApp - Dev Environment
  3. 2018.06.12 Solidity nested Mapping
  4. 2018.06.11 web3를 Promise로 호출

이더리움(ethereum) 엔터프라이즈  dApp 개발환경인 truffle 5.0.0 beta가 출시되었다.

덩달아 web3.js의 1.0.0도 같이 나왔다.  

(하지만 2018년에는 아직까지는 비추이다.. 버그 존재)


https://github.com/trufflesuite/truffle/releases  (2018.8월 기준)



가장 큰 변화는 truffle test  시에 에러내역이 출시된다는 것이다. 


베타인 관계로 설치방법이 좀 다른데, 아래와 같이 설치가 가능하다.

npm uninstall -g truffle
npm install -g truffle@beta



그 외에 주요 변화는

1. truffle console에서도 await 이 된다. (async를 알아서 불러줘서, async없이도 await을 막 써도 되는 곳이 몇군데 있고) '

  심지어는 deploy에서도 await이 사용가능하다. 

 

 const One = artifacts.require("One");
 const Two = artifacts.require("Two");

 module.exports = async function(deployer) {
  await deployer.deploy(One);

  const one = await One.deployed();
  const value = await one.value();

  await deployer.deploy(Two, value);
};


2. BigNumber대신에 BN으로 대치되고, BN에서는 포맷설정이 가능하기 때문에 BigNumber도 계속 사용은 가능하다.


web3와 결합한 BN사용방식은 다음과 같다.

const stringBalance = await web3.eth.getBalance('0xabc..'); const bnBalance = web3.utils.toBN(stringBalance);




Posted by yongary
,

제목: truffle과 ES6 javascript를 이용한, 이더리움 dApp 개발환경 : 



Explanation - ENG

  • BaseContract (below) is base class when making javascript Contract using truffle & ES6-javascript
  • This can be used when using several ES6-javascript like Vue.js, Angular.js and react.js
  • When developing Ethereum dApp, this class helps to map functions between Solidity and Javascript, and helps web3 process of MetaMask and etc.
  • Detail using example can be found on https://github.com/yongarykim/RSTdAppDevEnv/tree/master/react-frontend/src/contracts


Explanation - KOR

  • truffle을 이용해서 javascript contract를 개발할 때, 상속받아서 쓰도록 만든 기본 class이다.
  • 각종 ES6-javascript language에서 아래 BaseContract를 상속을 받아서 이더리움 dApp개발시 사용할 수 있다.
  • 이더리움 dApp개발시 간단히 solidity의 함수와 js 함수간 매핑하도록 도와주며, metaMask 등의 web3처리를 자동으로 해준다. 자세한 사용예제는 https://github.com/yongarykim/RSTdAppDevEnv/tree/master/react-frontend/src/contracts 를 참고하도록 한다.


소스:  https://github.com/yongarykim/ES6-ContractBase


/**
* BaseContract - super class of all contracts (using Web3 & TruffleContract)
*
* <History>
* @author Yong Kim (yongary.kim@gmail.com)
* @date 2018.4.5 - first created
* @date 2018.6.11 - promisify & getMyAccount added
* @date 2018.6.13 - contractDeployed added.
*
*/

import Web3 from 'web3';
import TruffleContract from 'truffle-contract';
import $ from 'jquery';
import { Subject } from 'await-notify';

//web3함수를 Promise로 만들기 위한 공통모듈
const promisify = (inner) =>
new Promise((resolve, reject) =>
inner((err, res) => {
if (err) { reject(err) }
resolve(res);
})
);

export default class BaseContract {

constructor() {
this.contract = {};
this.initWeb3();
//contract.deployed()가 initContract 보다 빨리 호출되는 경우용
this.eventWaiting = new Subject();
}

initWeb3() {
// Metamask
console.log("this.web3:")
console.log(this.web3);
console.log("window.web3:")
console.log(window.web3);

if (typeof window.web3 !== 'undefined') {
this.web3 = new Web3(window.web3.currentProvider);
} else {
//LocalTest set the provider you want from Web3.providers
console.log("initWeb3: local");
this.web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:7545"));
}
console.log(this.web3);
}

/* new 이후에 호출 필요 */
initContract(contractJson) {

let self = this;
$.getJSON(contractJson, function (data) {
// Get the necessary contract artifact file and instantiate it with truffle-contract
let contractArtifact = data;

console.log('initContract:' + self.contract);

self.contract = TruffleContract(contractArtifact);
self.contract.setProvider(self.web3.currentProvider);

console.log('initContract out');
self.eventWaiting.notify(); //contractDeployed가 먼저 불렸을 경우 대비.
});
}

/* contract관련 check함수 */

/**
* contractDeployed
* - same as contract.deployed,
* But waiting initContract to finish
* - useful when doing something on screen loading..
* */
contractDeployed = async () => {

console.log('in contractDeployed:');
if (Object.keys(this.contract).length === 0 ) {//contract Empty = initContract수행중
console.log(this.contract);

while (true) {
await this.eventWaiting.wait();
console.log('initContract Done');
break; //exit when notified.
}
}
console.log('out contractDeployed:');
return this.contract.deployed().then((instance) => {return instance;});

}


/* web3/eth Basic함수들 - eth의 sync함수는 값을 못 읽어 오는 경우가 발생가능하므로 async함수를 써야 함. */

getMyAccount = async () => {
const accounts = await promisify(cb => this.web3.eth.getAccounts(cb));
return accounts[0]; //accounts Array의 0번째가 본인 account임.
}
}



부연설명


이더리움 dApp을 개발할 경우, truffle과 javascript를 이용해서 개발하는 게 편리하다.

특히, javascript를 ES6로 사용하면 상속을 쉽게 사용할 수 있기 때문에,

복잡한 dApp을 개발할 수 있는  밑거름이 된다. 

(아무 생각없이, html과 javascript, truffle을 섞어서 쓴다면 간단한 dApp을 만들고 나서

복잡한 dApp은 만들다가 포기하게 될 확률이 높아진다)

 

복잡하고 어려운 dApp을 개발하기 위해서는 건물의 기초공사부터 튼튼하게 해 놓듯이

ES6 javascript를 이용해서 javascript를 개발하기를 권장하고.

그래서, 그 때 도움이 될 class를 만들어 본것이다.


ES6- javascript의 상속을 사용할 수 있기 때문에 쉽게쉽게 truffle contract기반의

javascript contract가 생성이 가능하다. 


자세한 사용예제는  https://github.com/yongarykim/RSTdAppDevEnv/tree/master/react-frontend/src/contracts 



Posted by yongary
,

solidity개발시 gas비용을 최소화하기 위해 연산을 줄이는 것이 중요하다.


그래서 가장 유용한 data Type은 mapping인데,

mapping안에 array를 넣는 방법도 꽤 추천할 만하지만


array의 길이가 길어진다면 O(n)의 서칭이 발생하므로,

데이타가 많다면 mapping안에 mapping을 또 넣는 방법이 좋을 것 같다.


일반적인 language용어로 말하자면, 

hashMap안에 또 hashMap을 넣는 것이다.


단, 이를 조회하려면 parentKey와 childKey모두 알아야 조회가 가능하다.


예제는 다음과 같다. 참고사이트: REF


contract SampleContract {

  struct ChildStruct {
    bool isPresent;
    bytes32 name;
  }

  struct ParentStruct {
    bool isPresent;
    bytes32 name;
    mapping (bytes32 => ChildStruct) childStructs; 
  }

  mapping(bytes32 => ParentStruct) public parentStructs;

  function insertData(
    bytes32 parentKey, 
    bytes32 parentName, 
    bytes32 childKey, 
    bytes32 childName)
    public 
    returns(bool success)
  {

    parentStructs[parentKey].isPresent = true;
    parentStructs[parentKey].name = parentName;
    parentStructs[parentKey].childStructs[childKey].isPresent = true;
    parentStructs[parentKey].childStructs[childKey].name = childName;
    return true;
  }

  function getChild(bytes32 parentKey, bytes32 childKey) public constant returns(bool isPresent, bytes32 name) {
    return (parentStructs[parentKey].childStructs[childKey].isPresent, parentStructs[parentKey].childStructs[childKey].name);
  }

}


Posted by yongary
,

React와 truffle로 dApp을 개발중이다. 

- 백엔드는 sprintBoot로 할 예정인데 모두 합해서 RST 개발환경으로 부르고 있다.
 (R: react-frontend ,  S: springboot-backend,   T: truffle )


dApp개발과 직접상관있는 부분은

  - R: dApp개발, 

  - T: solidity개발이다. (S: springboot-backend는 일단은 배포와 상관이 있다고 보면된다)



(UI와 web3가 섞이면서 콜백지옥에 빠질 수 있으므로,

RST개발환경과 같은 방식을 사용해 ES6 javascript를 사용해 이를 빠져나오길 추천한다.)



UI에서 promise를 활용해  web3.eth.getAccounts, 그 중에서도 accounts[0] 즉, 자기 account를 

가져오는 샘플코드는 다음과 같다.


<UI에서 호출하는 부분>

componentDidMount() {     console.log('componentDidMount start');     //getMyAccount     this.ATZToken.getMyAccount().then((account) => {         this.myAccountInput.value = account;         console.log('in componentDidMount:' + account);     }).catch((err) => {         console.log(err.message);     });     console.log('componentDidMount End'); }


<web3 연동 부분>  es6-promisify로는 잘안되는 부분이 있었는데, REF 를 보고 자체 promisify함수를 만들어 해결하였다. 

//web3함수를 Promise로 만들기 위한 공통모듈 const promisify = (inner) =>     new Promise((resolve, reject) =>         inner((err, res) => {             if (err) { reject(err) }             resolve(res);         })     );

 

/* Basic함수들 - eth sync함수는 값을 못 읽어 오는 경우가 발생가능하므로 async함수를 써야 함. */ getMyAccount = async () => {     const accounts = await promisify(cb => this.web3.eth.getAccounts(cb));     return accounts[0]//accounts Array 0번째가 본인 account. }


Posted by yongary
,