web3.js

[Ethereum] web3.js의 사용

Bittersweet- 2022. 9. 1. 14:08
728x90
  • web3.eth(web3-eth package) - 이더리움 블록체인과 스마트 컨트랙트와 상호작용할 수 있다.
  • web3.shh(web3-shh package) - broadcast를 위한 whisper 프로토콜과 상호작용할 수 있다.
  • web3.bzz(web3-bzz package) - swarm과 상호작용하면서 파일 저장을 탈중앙화할 수 있도록 한다.
  • web3.utils(web3-utils package) - Dapp 개발자에게 도움되는 함수를 포함하고 있다.

 

1. web3 provider

web3 provider는 스마트 컨트랙트의 내용을 호출하거나 입력하기위해 어떤 노드와 통신해야 하는지 설정해 줘야 한다.

http에서 동작하는 node를 연결하기 위해 httpProvider를 사용해 web3 객체를 생성한다.

// ropsten
var web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io'));
var web3 = new Web3(new Web3.providers.HttpProvider('https://api.myetherapi.com/rop'));

// mainnet
var web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io'));
var web3 = new Web3(new Web3.providers.HttpProvider('https://api.myetherapi.com/eth'));

// private(local)
var web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8545/'));

설정과 이벤트 등이 자세한 내용의 아래의 링크로 이동해 확인해보도록 합시다.

👉 Web3 Provider 자세히 알아보기

 

Web3 Provider | WalletConnect Docs

Quick Start For Dapps using Web3 Provider

docs.walletconnect.com

 

 

 

2. web3.eth.method().call()

web3 api 호출은 ethereum 내 state를 조회(Query)하거나 data/value를 전송(transaction)하는 호출로 나눌 수 있다.

 

Query(state 조회)

state를 조회하는 경우에는 gas가 소모되지 않으므로 web3가 제공하는 api를 호출하면 된다.

// symchronous
var balance = web3.eth.getBalance('0x40.....c1');

// asynchronous
web3.eth.getbalance(address, function(err, result) {
  balance = result;
});

 

Transaction(data/value를 전송)

web3를 사용해 data/value를 전송하기 위해서는 Transaction Object를 만들어야 한다.

- Transaction Object

var transactionObject = {
  nonce: transactionCount,
  gasPrice: gasPrice,
  gasLimit: gasLimit,
  to: toAddress,
  from: fromAddress,
  data: data,
  value: wei
}

nonce : the count of the number of outgoing transations, starting with 0

gasPrice :  the price to degermine the amount of ether the transaction will cost

gasLimit : the maximum gas that is allowed to be spent to process the transation

data : could be an arbitrary message or function call to a contract or code to create a contract

value : the mount of ether to send

 

만들어진 transactionObject를 전송하는 방법은 sendTransaction과 sendRawTransaction이 있다.

두 개의 차이점은 서명 방법의 차이로 sendTransaction은 transactionObject를 node에 보내면 node에서 서명을 하고

sendRawTransaction은 보낼 때 서명을 해서 보낸다.

sendTransaction을 하기 위해서는 node에 account가 등록되어 있어야 하고 sendRawTransaction을 하기 위해서는 privateKey를 알고 있어야 한다.

- sendTransaction

앞서 생성한 transactionObject를 전송한다.

gasPrice, nonce, gasLimit는 web3를 사용해 조회할 수 있다.

var nonce = web3.eth.getTransactionCount(fromAddress);
var gasPrice = web3.eth.gasPrice;
var value = web3.toWei(amount, 'ether');
var gasLimit = web3.eth.estimateGas({
  to: toAddress,
  from: fromAddress,
  value: value
}); // the used gas for the simulated call/transaction
var txObject = {
  nonce: nonce,
  gasPrice: gasPrice,
  gasLimit: gasLimit,
  to: toAddress,
  from: fromAddress,
  value: value
}

var transactionHash = web3.eth.sendTransaction(txObect);

 

- sendRawTransaction

transactionObject를 만들 때 파라미터에 해당하는 값들은 Hex로 변환하여 입력한다.

ethereumjs-tx를 사용해 privateKey transaction을 서명해서 전송한다.

var Tx = require('ethereumjs-tx');

var rawTx = {
  nonce: web3.toHex(nonce);
  gasPrice: web3.toHex(gasPrice),
  gasLimit: web3.toHex(gasLimit),
  to: toAddress,
  from: ownerAddress,
  data: '0x00',
  value: web3.toHex(value)
};

var tx = new Tx(rawTx);
tx.sign(privateKey);

var serializedTx = tx.serialize();
var transactionHash = web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'));

 

 

 

3. contract method call

contract의 method를 호출하는 방법도 state를 조회(Query)하거나 데이터 저장/연산수행(transaction)하는 호출로 나눌 수 있다.

 

Query(state 조회)

contract의 instance 생성 후, 필요한 state를 함수 호출하듯이 부른다.

(contract 상에서 외부 호출이 가능하도록 구현이 필요하다)

getWhiteListAddress(ruleAddress) {
  var instance = this.web3.eth.contract(this.ruleAbi).at(ruleAddress)
  
  return new Promise(function (resolve, reject) {
    instance.whitelist(function(err, result) {
      if(err) {
        reject(err);
      } else {
        resolve(result);
      }
    });
  });
}

 

Transaction(데이터 저장/연산 수행을 호출)

contract method를 호출하기 위해서는 transaction을 생성해야 한다.

transactionObject의 data parameter에 method의 signature와 method 호출에 필요한 파라미터를 encode 한 값을 입력한다.

import CryptoJs from 'crypto-js';
import tx from 'ethereumjs-tx';
import coder from 'web3/lib/solidity/coder';

// signature + parameterr
var contractData = contractData(functionName, types, args) {
  var fullName = functionName + '(' + types.join() + ')'
  var signatrue = CryptoJs.SHA3(fullName, { outputLength:256 })
    .tostring(CryptoJs.enc.Hex).slice(0, 8) // the first 32bit
  var dataHex = signature + coder.encodeParams(types, args)
  
  return '0x'+dataHex;
}

var txData = contractData('setWhitelist', ['address'], [whiteListAddress]);
var rawTx = {
  nonce: web3.toHex(nonce),
  gasPrice: web3.toHex(gasPrice),
  gasLimit: web3.toHex(gasLimit),
  to: toAddress,
  from: ownerAddress,
  data: txData
}

var tx = new Tx(rawTx);
tx.sign(privateKey);

var serializedTx = tx.serialize();
var transactionHash = web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'));

 

 

- method signature

contract method의 signature는 crypto-js or web3를 사용해서 얻을 수 있다.

import CryptoJs from 'crypto-js';

var fullName = 'setWhitelist(address)';
var signature = CryptoJS.SHA3(fullName, { outputLength: 256 })
  .toString(CryptoJS.enc.Hex).slice(0,8)
//or
// web3 instance가 있을 때
var signature = web3.sha3(fullName).replace('0x', '').slice(0, 8);

 

- parameter encode

contract method 호출에 필요한 파라미터는 coder나 ethereumjs-abi를 사용해서 변환할 수 있다.

// coder 사용
import coder from 'web3/lib/solidity/coder';

var data = coder.encodeParams(types, args)

// ethereumjs-abi 사용
import abi = from 'ethereumjs-abi'
var data = abi.rawEncode(['address'], [whiteListAddress]).toString('hex')

 

- contract event

contract의 method 호출 후, 결과(return)를 얻기 위해서는 conatract의 event를 사용한다.

contract객체로부터 선언된 event 객체를 얻을 수 있고 watch라는 명령을 사용해서 event를 subscribe 할 수 있다.

var event = this.web3.eth.contract(this.ruleAbi).at(ruleAddress).SetWhitelist()
event.watch(function(err, result) {
  // result
}

 

- result parameter

event를 subscribe 하면 받게되는 파라미터는 다음과 같다.(파라미터 명은 node에 따라 다를 수 있다)

logIndex: Number - integer of the log index position in the block. null when its pending log.
transactionIndex: Number - integer of the transactions index position log was created from. null when its pending log.
transactionHash: String, 32 Bytes - hash of the transactions this log was created from. null when its pending log.
blockHash: String, 32 Bytes - hash of the block where this log was in. null when its pending. null when its pending log.
blockNumber: Number - the block number where this log was in. null when its pending. null when its pending log.
address: String, 32 Bytes - address from which this log originated.
data: String - contains one or more 32 Bytes non-indexed arguments of the log.
topics: Array of Strings - Array of 0 to 4 32 Bytes DATA of indexed log arguments. (In solidity: The first topic is the hash of the signature of the event (e.g. Deposit(address,bytes32,uint256)), except if you declared the event with the anonymous specifier.)
type: STRING - pending when the log is pending. mined if log is already mined.

 

 

[참고]

[Ethereum] web3js 사용법 간단 요약

'web3.js' 카테고리의 다른 글

[web3.js] For Beginner(CryptoZombies)  (0) 2022.08.26
[web3-react] MetaMask로 지갑 연동하기  (0) 2022.05.04