Данные транзакции блокчейна Ethereum/BSC

Я пытаюсь поиграть с web3js в блокчейне Binance Smart Chain и упираюсь в стену, не понимая данные транзакций.

Глядя на эту транзакцию для example, можно увидеть три передачи транзакций (Token Transferred), в большинстве случаев это как два (до сих пор я видел 2, 3 и 5). Я не понимаю, от чего зависит количество переводов для одной транзакции. И как получить эти данные с помощью web3js.

Я хотел бы знать сумму уплаченных BNB и сумму токенов, полученных в этой транзакции, и наоборот, если транзакция была о продаже токенов, а не о покупке.

Мне удалось получить уплаченную цену и количество токенов, но только для транзакций, в которых есть 2 передачи токенов. Но если их 3 или более, я не могу получить эту информацию.

web3.eth.getTransaction('0x899e7f3c2138d051eb5246850ded99d519ab65eba58e5f806245cf346ab40e83').then((result) => {
  console.log(result)
  console.log(web3.utils.fromWei(result.value))

  let tx_data = result.input;
  let input_data = '0x' + tx_data.slice(10);  // get only data without function selector

  let params = web3.eth.abi.decodeParameters([
      {
        indexed: false,
        internalType: 'uint256',
        name: 'value',
        type: 'uint256'
      },
      {
        indexed: false,
        internalType: 'uint256',
        name: 'ethReceived',
        type: 'uint256'
      },
    ]
    , input_data);
  console.log(params)

})

Эта часть кода дает мне данные только для двух переводов токенов. Как сделать так, чтобы мне всегда возвращали сумму оплаченных/полученных наличных/токенов независимо от того, сколько переводов в транзакциях?? Является ли это возможным?? Из того, что я всегда вижу, 1-й перевод и последний перевод в транзакции будут интересующими меня значениями. Есть ли простой способ получить их? Я изо всех сил пытаюсь понять это и работать с ABI для декодирования. Могут ли они быть несколько общими??


person Mugetsu    schedule 04.05.2021    source источник


Ответы (1)


Информация о передаче токенов поступает из журналов событий. Большинство стандартов токенов определяют событие Transfer(address indexed from, address indexed to, uint256 value), поэтому вы можете искать журналы этого события в транзакции.

Журналы событий доступны в getTransactionReceipt(), а не обычная getTransaction().

Модификатор indexed в определении события означает, что значение будет доступно в свойстве topics (topics[0] — это хэш keccak256 подписи события, следующий за индексированными значениями). Затем неиндексированные значения сохраняются в свойстве data в порядке их определения.

const transferEventSignature = web3.utils.keccak256('Transfer(address,address,uint256)'); // 0xddf252...
const jsonAbi = [{
    "constant" :true,
    "inputs": [],
    "name": "decimals",
    "outputs": [{"name":"","type":"uint8"}],
    "type": "function"
}]; // simplified JSON abi that is only able to read decimals

web3.eth.getTransactionReceipt('0x899e7f3c2138d051eb5246850ded99d519ab65eba58e5f806245cf346ab40e83').then(async (result) => {
    for (const log of result.logs) {
        if (log.topics[0] !== transferEventSignature) {
            continue; // only interested in Transfer events
        }

        const from = web3.eth.abi.decodeParameter('address', log.topics[1]);
        const to = web3.eth.abi.decodeParameter('address', log.topics[2]);
        const value = web3.eth.abi.decodeParameter('uint256', log.data);
        const tokenContractAddress = log.address;

        const contractInstance = new web3.eth.Contract(jsonAbi, tokenContractAddress);
        const decimals = await contractInstance.methods.decimals().call();

        console.log('From: ', from);
        console.log('To: ', to);
        console.log('Value: ', value);
        console.log('Token contract: ', tokenContractAddress);
        console.log('Token decimals: ', decimals);
        console.log('---');
    }
});

Выход:

From:  0xC6A93610eCa5509E66f9B2a95A5ed1d576cC9b7d
To:  0xE437fFf464c6FF2AA5aD5c15B4CCAD98DF38cF52
Value:  31596864050517135
Token contract:  0x78F1A99238109C4B834Ac100d1dfCf14e3fC321C
Token decimals:  9
---
From:  0xE437fFf464c6FF2AA5aD5c15B4CCAD98DF38cF52
To:  0x58F876857a02D6762E0101bb5C46A8c1ED44Dc16
Value:  4064578781674512
Token contract:  0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c
Token decimals:  18
---
From:  0x58F876857a02D6762E0101bb5C46A8c1ED44Dc16
To:  0xC6A93610eCa5509E66f9B2a95A5ed1d576cC9b7d
Value:  2552379452401563824
Token contract:  0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56
Token decimals:  18

Примечание. Некоторые реализации токенов неверны (т. е. не соответствуют стандартам токенов) и не помечают параметры события как indexed. В этом случае topics[0] остается прежним, а вот адресов from и to в topics нет, а вам придется парсить их из поля data. Длина address составляет 64 шестнадцатеричных символа (с нулями перед фактическим 40-символьным адресом).

person Petr Hejda    schedule 05.05.2021