本文将详细介绍如何查询以太币及代币余额与价格,进行以太币与代币转账,并获取交易记录的完整流程。主要涵盖两种技术实现方式:使用web3.js库和直接调用以太坊API。
准备工作与环境配置
在开始操作前,需要准备以下基本要素:
- 主链节点地址:可通过Infura等服务获取
- 合约ABI:可从Etherscan等区块链浏览器获取,若代币合约提供了源代码,通常也会包含ABI信息
- 基础工具库:包括web3.js、bignumber.js等必要依赖
使用web3.js进行操作
web3.js是以太坊官方推荐的JavaScript库,提供了与以太坊区块链交互的完整接口。
连接Web3实例
import Web3 from 'web3'
let getWeb3 = new Promise(function(resolve, reject) {
var web3 = window.web3
if (typeof web3 !== 'undefined') {
web3 = new Web3(web3.currentProvider)
results = {web3: web3}
resolve(results)
} else {
var provider = new Web3.providers.HttpProvider('https://mainnet.infura.io/v3/apikey')
web3 = new Web3(provider)
results = {web3: web3}
resolve(results)
}
})查询Gas价格与限制
获取当前网络Gas价格和Gas限制是交易前的重要准备步骤:
getWeb3.then(function(server) {
server.web3.eth.getGasPrice(function(error, result) {
if (!error) {
server.web3.eth.getBlock("latest", function(error1, info) {
if (!error1) {
// 获取gasLimit信息
}
})
}
})
})查询余额信息
以太币余额查询
const BigNumber = require('bignumber.js')
const Ether = new BigNumber(10e+17)
balanceOfETH = (address) => {
getWeb3.then(function(server) {
const balance = server.web3.eth.getBalance(address, (err2, bal) => {
if (!err2) {
let ret = new BigNumber(bal)
// 以太币余额结果
}
})
})
}代币余额查询
valueOfgetBalanceOther = (server, address) => {
const balance = server.web3.eth.getBalance(address, (err2, bal) => {
if (!err2) {
let contractother = server.web3.eth.contract(contractabi).at(contractaddress)
contractother.balanceOf(address, (error2, bal) => {
if (!error2) {
let ret = new BigNumber(bal)
// 代币余额结果
}
})
}
})
}私链上的转账操作
在私有链上,由于本地存储了私钥,转账操作相对简单。
以太币转账
web3.eth.sendTransaction({
from: currentAccount,
to: receiverAccount,
value: '1000000000000000'
}).then(function(receipt){
console.log(receipt)
})代币转账
myContract.methods.transfer(to, amount).send({from: currentAccount}), function(error, transactionHash){
if(!error) {
console.log('transactionHash is ' + transactionHash)
}
})主链上的转账操作
在主网上进行写入操作需要获取账户私钥并对交易进行签名,使用web3.eth.sendSignedTransaction方法。
首先安装必要依赖:
npm install ethereumjs-tx主网转账实现
var tx = require('ethereumjs-tx')
transfer = (recipientAddress, balance, privateKey) => {
getWeb3.then(function(server) {
let address = WalletaA // 转账人钱包地址
server.web3.eth.getTransactionCount(address, function(err, nonce) {
let balanceEth = parseFloat(balance) * Ether
let rawTx = {}
if (self.state.token == 'ETH') {
// 以太币转账对象
rawTx = {
nonce: server.web3.toHex(nonce++),
gasPrice: server.web3.toHex(10e9),
from: address,
gasLimit: server.web3.toHex(99000),
to: recipientAddress,
value: balanceEth
}
} else {
// 代币转账数据处理
let data = '0x' + 'a9059cbb' + addPreZero(recipientAddress.substr(2)) + addPreZero(server.web3.toHex(balanceEth).substr(2))
rawTx = {
nonce: server.web3.toHex(nonce++),
gasLimit: server.web3.toHex(9900),
gasPrice: server.web3.toHex(10e9),
to: address, // 代币合约地址
from: address,
value: '0x00',
data: data
}
}
let tx = new ethTX(rawTx)
let keyBuf = Buffer.from(privateKey, 'hex')
tx.sign(keyBuf)
if (tx.verifySignature()) {
let serializedTxHex = '0x' + tx.serialize().toString('hex')
server.web3.eth.sendRawTransaction(serializedTxHex, function(err, transactionHash) {
// 处理交易结果
})
}
})
})
}使用以太坊API进行操作
除了web3.js,还可以直接通过以太坊API进行相关操作。
查询Gas信息
fetch(`https://api.etherscan.io/api?module=proxy&action=eth_gasPrice&apikey=apikey`)
.then(result => result.json())
.then(result => {
let parseIntresult = parseInt(result.result, 16)
fetch(`https://api.etherscan.io/api?module=proxy&action=eth_getBlockByNumber&tag=0x10d4f&boolean=true&apikey=apikey`)
.then(info => info.json())
.then(info => {
let parseIntinfo = parseInt(info.result.gasLimit, 16)
})
})API余额查询
以太币余额查询
fetch(`https://api.etherscan.io/api?module=account&action=balance&address=${address}&tag=latest&apikey=apikey`)
.then(result => result.json())
.then(result => {
if (result.status == 1) {
let ret = new BigNumber(result.result)
// 处理余额结果
}
})代币余额查询
fetch(`https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=${contactaddress}&address=${address}&tag=latest&apikey=apikey`)
.then(result => result.json())
.then(result => {
if (result.status == 1) {
let ret = new BigNumber(result.result)
// 处理代币余额结果
}
})API转账实现
transfer = (recipientAddress, balance, privateKey) => {
let address = WalletaA // 转账人钱包地址
fetch(`https://api.etherscan.io/api?module=proxy&action=eth_getTransactionCount&address=${address}&tag=latest&apikey=apikey`)
.then(result => result.json())
.then(result => {
let nonce = parseInt(result.result, 16) + 1
let gasPrice = 10e9
let gasLimit = 9900
let balanceEth = parseFloat(balance) * Ether
let rawTx = {}
if (self.state.token == 'ETH') {
rawTx = {
nonce: '0x' + nonce.toString(16),
gasPrice: '0x' + gasPrice.toString(16),
from: address,
gasLimit: '0x' + gasLimit.toString(16),
to: recipientAddress,
value: balanceEth
}
} else {
let data = '0x' + 'a9059cbb' + addPreZero(recipientAddress.substr(2)) + addPreZero(balanceEth.toString(16))
rawTx = {
nonce: '0x' + nonce.toString(16),
gasLimit: '0x' + gasLimit.toString(16),
gasPrice: '0x' + gasPrice.toString(16),
to: hrcjson.address,
from: address,
value: '0x00',
data: data
}
}
let tx = new ethTX(rawTx)
let keyBuf = Buffer.from(privateKey, 'hex')
tx.sign(keyBuf)
if (tx.verifySignature()) {
let serializedTxHex = '0x' + tx.serialize().toString('hex')
fetch(`https://api.etherscan.io/api?module=proxy&action=eth_sendRawTransaction&hex=${serializedTxHex}&apikey=apikey`)
.then(info => info.json())
.then(info => {
// 处理转账结果
})
}
})
}获取交易记录
通过API获取特定地址的交易记录:
fetch(`https://api.etherscan.io/api?module=account&action=tokentx&contractaddress=${contractaddress}&address=${address}&page=1&offset=20&sort=desc&apikey=apikey`)
.then(transactionList => transactionList.json())
.then(transactionList => {
if (transactionList.status == 1) {
// 处理交易记录数据
// const txnIn = transactionList.filter(t => t.to === address)
// const txnOut = transactionList.filter(t => t.from === address)
}
})辅助函数
以下辅助函数用于处理数据格式:
// 补齐64位,不够前面用0补齐
function addPreZero(num){
var t = (num+'').length,
s = ''
for(var i=0; i<64-t; i++){
s += '0'
}
return s+num
}常见问题
如何选择web3.js和直接API调用?
web3.js提供了更完整的封装和更方便的接口,适合复杂的dApp开发。直接API调用更轻量,适合简单查询需求。对于转账等敏感操作,web3.js提供了更好的安全性和错误处理机制。
为什么主网和私链的转账方式不同?
主网转账需要签名是因为主网账户的私钥不在本地,需要额外安全验证。私链账户私钥通常存储在本地,因此可以直接调用简单接口进行转账。
查询余额时出现错误如何解决?
首先检查地址格式是否正确,然后确认网络连接是否正常。对于代币余额查询,还需要验证合约地址和ABI是否正确。如果使用API,检查API密钥是否有效且未超过调用限制。
Gas设置不合理会导致什么问题?
Gas价格设置过低可能导致交易长时间不被确认,Gas限制设置过低可能导致交易失败但仍需支付Gas费用。建议根据当前网络状况设置合理的Gas参数。
如何确保转账操作的安全性?
始终在安全环境下处理私钥,使用硬件钱包或多重签名提高安全性。在进行大额转账前,先进行小额测试交易确认一切正常。定期更新使用的库和工具以获取安全补丁。
交易记录查询有哪些注意事项?
交易记录查询可能受到API限制,需要分页处理大量数据。注意区分普通以太币交易和代币交易,它们使用不同的API接口和数据处理方式。