以太坊资产查询与转账操作全攻略:两种方式详解

·

本文将详细介绍如何查询以太币及代币余额与价格,进行以太币与代币转账,并获取交易记录的完整流程。主要涵盖两种技术实现方式:使用web3.js库和直接调用以太坊API。

准备工作与环境配置

在开始操作前,需要准备以下基本要素:

使用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) {
          // 处理交易结果
        })
      }
    })
  })
}

👉 查看实时Gas价格与网络状态

使用以太坊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接口和数据处理方式。