Задать вопрос
yartem
@yartem
frontend newbie

Web3.js 1.0.0-beta.34 — как правильно отправлять токены с кошелька на кошелёк?

Здравствуйте.

Я новичок в программировании вообще, и в JS в частности. Тем не менее, пытаюсь как-то работать. Сейчас пытаюсь наладить взаимодействие приложения на Vue.js с блокчейном Ethereum посредством библиотеки Web3 версии 1.0.0-beta.34. Использую именно эту бету потому, что более свежие версии, начиная с beta.35, не дают мне воспользоваться методом getBalance смартконтракта, с которым я пытаюсь подружить своё приложение. На этой бете большая часть моего приложения работает без нареканий.

Для реализации отправки токенов, руководствуюсь соответствующей статьёй из официальной документации по Web3.js 1.0, помимо неё, использовал данные из статьи Hideyoshi Moriya How to send ERC20 token with Web3.js@1.0.0. Также активно использую гугл.

Вот соответствующий кусок кода. (Не стал в него включать способ подключения библиотек axios и Web3.js. На всякий случай отмечу, что провайдером у меня выступает node3.web3api.com.)

let
  tokenAddress = '0x5c....e4',
  fromAddress = '0xaA....6c',
  toAddress = '0xE3....f7',
  decimals = web3.utils.toBN(0),
  amount = web3.utils.toBN(5),
  value = amount.mul(web3.utils.toBN(10).pow(decimals));

const
  token = abi => new web3.eth.Contract(abi, tokenAddress).methods;

axios.get('https://api.etherscan.io/api?module=contract&action=getabi&address=' + tokenAddress)
.then(answer => {
  let
    abi = JSON.parse(answer.data.result);

  token(abi).name().call().then(console.log); //работает
  token(abi).symbol().call().then(console.log); //работает
  token(abi).balanceOf(fromAddress).call().then(console.log); //работает

  token(abi).transfer(toAddress, value)//не работает
  .send({from: fromAddress})
  .on('transactionHash', function(hash){
    console.log(hash);
  });
});


Ошибка:
Uncaught (in promise) Error: Invalid JSON RPC response: ""


Люди, помогите разобраться, пожалуйста!
  • Вопрос задан
  • 851 просмотр
Подписаться 2 Средний Комментировать
Решения вопроса 1
yartem
@yartem Автор вопроса
frontend newbie
Сам спросил, сам и отвечу.

Решение, как выяснилось, лежало немного в иной плоскости. Вот код:

const
  tokenAddress = '0x58....e4',
  fromAddress = '0xaA....46c',
  privateKey = '0x09........79',
  toAddress = '0xE3....f7',
  decimals = web3.utils.toBN(0),
  amount = web3.utils.toBN(5),
  value = amount.mul(web3.utils.toBN(10).pow(decimals)), // value = 5 = 5*(10^0)
  sender = web3.eth.accounts.privateKeyToAccount(privateKey),
  token = abi => new web3.eth.Contract(abi, tokenAddress).methods;

axios.get('https://api.etherscan.io/api?module=contract&action=getabi&address=' + tokenAddress)
.then(answer => {
  const
    abi = JSON.parse(answer.data.result),
    data = token(abi)["transfer"](toAddress, value).encodeABI(),
    tx = {
      gas: '2000000',
      from: fromAddress,
      to: tokenAddress,
      data,
    };

  token(abi).name().call().then(console.log);
  token(abi).symbol().call().then(console.log);
  token(abi).balanceOf(fromAddress).call().then(console.log);

  sender.signTransaction(tx)
  .then(signedTx => {
    web3.eth.sendSignedTransaction(signedTx.rawTransaction)
    .then(console.log);
  });
});


Судя по всему, проблема была в том, что транзакция не была подписана. Так как перевод токенов, это не отправка какого-нибудь сообщения в духе "Hello world!", а вполне себе переброска реальных бабок, такая транзакция не может осуществляться с кошелька хозяина без его ведома. В статье How to send ERC20 token with Web3.js@1.0.0, ссылку на которую я приводил выше, и которой я руководствовался в процессе написания первоначального варианта кода, этот момент как-то странно обойдён автором. Если придирчиво изучить демо-сайт, ссылку на него Hideyoshi Moriya приводит в конце своей статьи, можно заметить, что автор использует MetaMask API, что многое объясняет, но о чём ни слова нет в самой статье. Судя по всему, MetaMask позволяет решить вопрос авторизации своими методами.

Я же продолжил свои исследования. Усиленно копая интернет, через достаточно небольшой промежуток времени, наткнулся на аналогичный моему вопрос человека с ником Dmitry на русском сегменте StackOverflow.com: Как отправить токены ethereum с помощью web3.js. Цитировать его я не буду, но вот ответ человека с ником user3655581 привлёк моё внимание:

Для того, чтобы перевести токены - нужно вызвать соответствующий метод контракта токена, предварительно его подписав. Примерный код:
const sender = web3.eth.accounts.privateKeyToAccount(privateKeyFrom);
const tokenContract = new web3.eth.Contract(abi, contractAddress);
const data = tokenContract.methods["transfer"](toAddress, amount).encodeABI();
const tx = { 
  gas: '2000000',
  from: fromAddress,
  to: contractAddress,      
  data,
};
const signedTx = await sender.signTransaction(tx);
const result = await web3.eth
  .sendSignedTransaction(signedTx.rawTransaction);



Руководствуясь приведённым кодом, я соорудил решение для своей задачи. Токены в количестве 5 штук успешно переправлены с одного кошелька на другой.

Спасибо большое всем, кто хотел мне помочь в этом вопросе, но немного не успел. Если у кого есть что добавить — буду только рад вашим комментариям. потому что пока очень и очень смутно ориентируюсь в поднятом вопросе.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы