Основные коды передачи Эфириума, используя web3js, ганаш, узел


Я хочу получить консультацию о функциональном программировании на JavaScript обещание. Пожалуйста, просмотрите мой код и дайте мне обратную связь, как я могу сделать код лучше. Как мне начать использовать обещание несколько дней назад, это было бы здорово, почему это лучший способ, чтобы изменить коды следующие отзывы.

Я реализовал основные коды передачи эфириума с web3js, ганаш, и nodejs. Оплата является основной функцией и было бы полезно, если бы вы могли дать мне отзывы о функции, включая его. Он состоит из функций, которые

  1. получение учетной записи объекты отправителя/получателя для дальнейшего использования
  2. проверка баланса отправителя/приемника до сделки
  3. эфир передачи от отправителя к получателю
  4. проверка баланса отправителя/получателя после операции

const Web3 = require('web3')

if (typeof web3 != 'undefined') {
  var web3 = new Web3(Web3.currentProvider)
} else {
  var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8545')) // NOTE : ganache-cli -p 8545 will open up port
}

// NOTE : input(privateKey) => output(Promise:account)
var getAccount = function (privateKey) {
  return new Promise(function (resolve, reject) {
    resolve(web3.eth.accounts.privateKeyToAccount(privateKey))
  })
}

// NOTE : input(address) => output(Promise:balance)
var getBalance = function (address) {
  return web3.eth.getBalance(address)
    .then(function (balance) { console.log(balance);})
    .catch(function (error) { throw new Error('getBalance Error')})
}

// NOTE : Using webjs(v1.0) and ganache, payment from one account to another
// NOTE : input(txInfo) => transferEther(sender=>receiver) => output(status)
var transferEther = function (sender, rawTx) {
  return sender.signTransaction(rawTx)
    .then(function (signedTx) {
      return web3.eth.sendSignedTransaction(signedTx.rawTransaction)
    })
    .then(function (receipt) {
      console.log(receipt)
    })
    .catch(function (error) {
      console.log(error)
    })
}

// Case2 : signTransaction using privateKey
var transferEtherWithPvkey = function (sender, rawTx) {
  return web3.eth.accounts.signTransaction(rawTx, sender.privateKey)
    .then(function (signedTx) {
      return web3.eth.sendSignedTransaction(signedTx.rawTransaction)
    })
    .then(function (receipt) {
      console.log(receipt)
    })
    .catch(function (error) {
      console.log(error)
    })
}

// Case3 : signTransaction using another entity's account
// NOTE : Relevant web3js libraries Not supported yet
// var transferEtherOfAnotherEntity = function (sender, rawTx) {
//   return web3.eth.personal.unlockAccount(sender.address, '')
//     .then(function (result) {
//       if (result) return web3.eth.personal.signTransaction(rawTx, '')
//     })
//     .then(function (signedTx) {
//       return web3.eth.personal.sendTransaction(signedTx.rawTransaction)
//     })
//     .catch(function (error) {
//       console.log(error)
//     })
// }

// TODO : Remove fixture
var paymentInfo = {
  pvKeys: { // hardcoded private keys 
    sender: '0x32d4e4b8deae4967f6ec305683921b1d46517767ef7a3411c27bbcf24fa7b757',
    receiver: '0x90e40b307bd5ee5c7f5285aecffcf0fb223ff1cf802d913237ecaf2f962e251e'
  },
  txInfo: {
    gasPrice: '200', // string
    gas: '210000', // string
    value: '1000', // string
    data: '' // string
  }
}

var payment = function (paymentInfo) { // TODO : Replace parameters with relevant params
  Promise.all([getAccount(paymentInfo.pvKeys.sender), getAccount(paymentInfo.pvKeys.receiver)]) // STEP 1 : get accounts of sender/receiver
    .then(function (accounts) {
      var rawTx = {
        from: accounts[0].address, // sender
        to: accounts[1].address, // receiver
        gasPrice: paymentInfo.txInfo.gasPrice,
        gas: paymentInfo.txInfo.gas,
        value: paymentInfo.txInfo.value,
        data: paymentInfo.txInfo.data
      }

      Promise.all(accounts.map(account => getBalance(account.address))) // STEP 2 : check balances of sender/receiver before transaction
        .then(() => transferEther(accounts[0], rawTx)) // STEP 3 : transferEther from sender to receiver
        .then(() => accounts.map(account => getBalance(account.address))) // STEP 4 : check balances of sender/receiver after transaction
    })
}

payment(paymentInfo)

module.exports = web3


130
3
задан 5 апреля 2018 в 09:04 Источник Поделиться
Комментарии
1 ответ

Node.js должны уже есть поддержка await/async. Вы можете угробить синтаксис обещание в пользу более простой, синхронный просмотр синтаксиса. Например, payment может быть так:

const payment = async (paymentInfo) { 
const accounts = await Promise.all([
getAccount(paymentInfo.pvKeys.sender),
getAccount(paymentInfo.pvKeys.receiver)
])

var rawTx = {
from: accounts[0].address, // sender
to: accounts[1].address, // receiver
gasPrice: paymentInfo.txInfo.gasPrice,
gas: paymentInfo.txInfo.gas,
value: paymentInfo.txInfo.value,
data: paymentInfo.txInfo.data
}

await Promise.all(accounts.map(account => getBalance(account.address)))
await transferEther(accounts[0], rawTx)

// You're just looping through. Use forEach instead of map.
accounts.forEach(account => getBalance(account.address))
}

// Async functions return a promise, and Node yells at you for unhandled
// promises. So we attach a then that appropriately handles it.
payment(paymentInfo).then(() => {
console.log('completed')
}, e => {
console.warn(e)
})


if (typeof web3 != 'undefined') {
var web3 = new Web3(Web3.currentProvider)
} else {
var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8545')) // NOTE : ganache-cli -p 8545 will open up port
}

Каждый модуль имеет свою область применения. Нет никакого способа web3 мог существовать до этой части кода. Это если вы вводите web3 в качестве некоторых узлов глобальной (который вы не должны). Также этот код является избыточным. Единственное, что отличается, является поставщиком. Вам нужно только применить условное, чтобы выбрать поставщика, а не инстанцирования.

const provider = ifWeb3Exists ? Web3.currentProvider : new Web3.providers.WebsocketProvider('ws://localhost:8545')
const web3 = new Web3(provider)


// TODO : Remove fixture
var paymentInfo = {
pvKeys: { // hardcoded private keys
sender: '0x32d4e4b8deae4967f6ec305683921b1d46517767ef7a3411c27bbcf24fa7b757',
receiver: '0x90e40b307bd5ee5c7f5285aecffcf0fb223ff1cf802d913237ecaf2f962e251e'
},
txInfo: {
gasPrice: '200', // string
gas: '210000', // string
value: '1000', // string
data: '' // string
}
}

Никогда не следует жестко кодировать конфиденциальную информацию в код. Например, если этот ключ был очень важным, и я просто скопировал его в мой ответ, нет никакого способа для вас, чтобы удалить это из моего ответа (если у вас нет разрешения на редактирование, или модератор удаляет мой пост). Нажимаем эти значения в код и в что-то вроде переменных окружения или аргументов.


// NOTE : Using webjs(v1.0) and ganache, payment from one account to another
// NOTE : input(txInfo) => transferEther(sender=>receiver) => output(status)
var transferEther = function (sender, rawTx) {
return sender.signTransaction(rawTx)
.then(function (signedTx) {
return web3.eth.sendSignedTransaction(signedTx.rawTransaction)
})
.then(function (receipt) {
console.log(receipt)
})
.catch(function (error) {
console.log(error)
})
}

Проблема с этим кодом заключается в том, что вы прикрепили catch для ведения журнала, но не повторно вызвать ошибки. При асинхронных вызовах в функции отвергают, catch восстанавливает от ошибок. В этом случае возвращается обещание всегда решить, не отвергал, и поселиться с undefined значение. Если вы просто then-ING для лесозаготовки, всегда вернуть разрешенные значения, или повторно отклонение стоимости.

Также catch является избыточным. Вы могли бы просто придерживаться второго обратного вызова до последнего then и она должна просто работать, как catch. Но опять же, async/await:

const transferEther = async (sender, rawTx) => {
const signedTx = await sender.signTransaction(rawTx)
const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction)
console.log(receipt)
return receipt
}

1
ответ дан 7 апреля 2018 в 03:04 Источник Поделиться