ALIS トークンのトランザクション履歴を取得
CEO 自ら実装レベルで Ethereum を理解しようとしているのすごい!
ERC20 トークンの場合、トークンの転送時に Transfer というイベントが index つきで記録されるので、それを利用できないか?
雑な実装だけど特定のEOA が from の 過去 X ブロックのトークントランザクション履歴を取得することはできた。
ALIS さんがやりたいこととはズレているかも?
動作デモ(web3.js v0.20.6, Mainnet, MetaMask が必要)
code:demo.js
// ALIS TOKEN の CONTRACT ADDRESS
const TOKEN_ADDRESS = "0xEA610B1153477720748DC13ED378003941d84fAB"
// Web3js の初期化
if (typeof web3 !== 'undefined') {
window.web3js = new Web3(web3.currentProvider)
} else {
alert("Please use MetaMask")
}
$(document.body).append('<h1>ALIS TRANSACTION HISTORY</h1>')
$(document.body).append('<p>Last <input type="number" size="20" value="50000" id="blockNum"> block</p>')
$(document.body).append('<p>EOA address (from): <input type="text" size="70" id="address" value="0x4b01721f0244e7c5b5f63c20942850e447f5a5ee"></p>')
$(document.body).append('<p><button onclick="searchTx()">Search TX</button>')
$(document.body).append('<div id="result"></div>')
function searchTx() {
// EOA アドレス
let address = $('#address').val()
if (address.length == 42) {
web3js.eth.getBlockNumber(function(error, result) {
let fromBlock = result - $('#blockNum').val()
getTransferHistory(TOKEN_ADDRESS, fromBlock, address)
})
}
}
function padLeft(address) {
return "0x000000000000000000000000" + address.slice(2)
}
function removeLeft(address) {
return '0x' + address.slice(26)
}
function getTransferHistory(tokenAddress, fromBlock, fromEOAAddress) {
$('#result').empty()
let filter = web3js.eth.filter({address: tokenAddress,
fromBlock: fromBlock,
toBlock: 'latest',
topics:[
web3js.sha3("Transfer(address,address,uint256)"),
padLeft(fromEOAAddress)
]
})
let count = 0
filter.watch(function(error, result){
console.log(result)
let e = '<h1>TX' + ++count + '</h1>'
+ '<ul>'
+ '<li>from: ' + removeLeft(result.topics1) + '</li>' + '<li>to: ' + removeLeft(result.topics2) + '</li>' + '<li>value: ' + web3js.fromWei(result.data, 'ether') + '</li>'
+ '</ul>'
$('#result').prepend(e)
})
}
EOA 0x4b01721f0244e7c5b5f63c20942850e447f5a5ee の ALIS トークンのトランザクション履歴を取得するサンプル
トランザクション履歴が多いため、履歴を取得するブロックを指定しています。
code:example@1.0.js
const Web3 = require('web3');
// Transfer イベントを取得するための最低限の ABI
const TOKEN_ABI = [{"anonymous":false,"inputs":{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"},"name":"Transfer","type":"event"}] // Settings
const TOKEN_ADDRESS = "0xEA610B1153477720748DC13ED378003941d84fAB" // トークンコントラクトのアドレス
const EOA_ADDRESS = "0x4b01721f0244e7c5b5f63c20942850e447f5a5ee" // EOA のアドレス
const FROM_BLOCK = 6000000
const TO_BLOCK = 6500000
const PROVIDER = 'wss://mainnet.infura.io/ws'
// Web3 初期化
const web3 = new Web3(PROVIDER)
console.log(web3.version)
async function getTokenTransferHistory(tokenAbi, tokenContractAddress, fromAddress, fromBlock, toBlock) {
const contract = new web3.eth.Contract(tokenAbi, tokenContractAddress)
const events = await contract.getPastEvents("Transfer", {
fromBlock: fromBlock,
toBlock: toBlock,
filter: {from: fromAddress}
})
if (events) {
for (let event of events) {
data = {
from: event.returnValues.from,
to: event.returnValues.to,
value: web3.utils.fromWei(event.returnValues.value)
}
console.log(data)
}
}
}
getTokenTransferHistory(TOKEN_ABI, TOKEN_ADDRESS, EOA_ADDRESS, FROM_BLOCK, TO_BLOCK)
動作デモ2 (Infura を使用。MetaMask 不要)
code:demo2.js
// ALIS TOKEN の CONTRACT ADDRESS
const TOKEN_ADDRESS = "0xEA610B1153477720748DC13ED378003941d84fAB"
// PROVIDER (INFURA)
const PROVIDER = 'wss://mainnet.infura.io/ws'
// Transfer イベントを取得するための最低限の ABI
const TOKEN_ABI = [{"anonymous":false,"inputs":{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"},"name":"Transfer","type":"event"}] // Web3js の初期化
window.web3js = new Web3(PROVIDER)
$(document.body).append('<h1>ALIS TRANSACTION HISTORY</h1>')
$(document.body).append('<p>Last <input type="number" size="20" value="50000" id="blockNum"> block</p>')
$(document.body).append('<p>EOA address (from): <input type="text" size="70" id="address" value="0x4b01721f0244e7c5b5f63c20942850e447f5a5ee"></p>')
$(document.body).append('<p><button onclick="searchTx()">Search TX</button>')
$(document.body).append('<div id="result"></div>')
async function searchTx() {
$('#result').empty()
let address = $('#address').val()
if (address.length == 42) {
let latestBlock = await web3js.eth.getBlockNumber()
let fromBlock = latestBlock - $('#blockNum').val()
console.log(fromBlock)
let transfers = await getTokenTransferHistory(TOKEN_ABI, TOKEN_ADDRESS, address, fromBlock, 'latest')
let count = 0
for (t of transfers) {
let e = '<h1>TX' + ++count + '</h1>'
+ '<ul>'
+ '<li>from: ' + t.returnValues.from + '</li>'
+ '<li>to: ' + t.returnValues.to + '</li>'
+ '<li>value: ' + web3js.utils.fromWei(t.returnValues.value, 'ether') + '</li>'
+ '</ul>'
$('#result').prepend(e)
}
}
}
async function getTokenTransferHistory(tokenAbi, tokenContractAddress, fromAddress, fromBlock, toBlock) {
return new Promise(async function(resolve, reject) {
const contract = new web3js.eth.Contract(tokenAbi, tokenContractAddress)
const events = await contract.getPastEvents("Transfer", {
fromBlock: fromBlock,
toBlock: toBlock,
filter: {from: fromAddress}
})
resolve(events)
})
}