当前位置: 首页 > ops >正文

查询账户余额

查询账户余额

读取一个账户的余额相当简单。

调用 ethclient 的 BalanceAt 方法,给它传递账户地址和可选的区块号。将区块号设置为 nil 将返回最新的余额。

account := common.HexToAddress("0x25836239F7b632635F815689389C537133248edb")
balance, err := client.BalanceAt(context.Background(), account, nil)
if err != nil {log.Fatal(err)
}fmt.Println(balance)

传区块高度能读取指定区块时的账户余额,区块高度必须是 big.Int 类型。

blockNumber := big.NewInt(5532993)
balance, err := client.BalanceAt(context.Background(), account, blockNumber)
if err != nil {log.Fatal(err)
}fmt.Println(balance)

以太坊中的数字是使用尽可能小的单位来处理的,因为它们是定点精度,在 ETH 中它是_wei_。要读取 ETH 值,您必须做计算 wei/10^18。因为我们正在处理大数,我们得导入原生的 Go math 和 math/big 包。这是您做的转换。

fbalance := new(big.Float)
fbalance.SetString(balance.String())
ethValue := new(big.Float).Quo(fbalance, big.NewFloat(math.Pow10(18)))fmt.Println(ethValue) // 25.729324269165216041

待处理的余额

有时您想知道待处理的账户余额是多少,例如,在提交或等待交易确认后。客户端提供了类似 BalanceAt 的方法,名为 PendingBalanceAt,它接收账户地址作为参数。

pendingBalance, err := client.PendingBalanceAt(context.Background(), account)
fmt.Println(pendingBalance)

完整代码

package mainimport ("context""fmt""log""math""math/big""github.com/ethereum/go-ethereum/common""github.com/ethereum/go-ethereum/ethclient"
)func main() {client, err := ethclient.Dial("https://cloudflare-eth.com")if err != nil {log.Fatal(err)}account := common.HexToAddress("0x25836239F7b632635F815689389C537133248edb")balance, err := client.BalanceAt(context.Background(), account, nil)if err != nil {log.Fatal(err)}fmt.Println(balance)blockNumber := big.NewInt(5532993)balanceAt, err := client.BalanceAt(context.Background(), account, blockNumber)if err != nil {log.Fatal(err)}fmt.Println(balanceAt) // 25729324269165216042fbalance := new(big.Float)fbalance.SetString(balanceAt.String())ethValue := new(big.Float).Quo(fbalance, big.NewFloat(math.Pow10(18)))fmt.Println(ethValue) // 25.729324269165216041pendingBalance, err := client.PendingBalanceAt(context.Background(), account)fmt.Println(pendingBalance) // 25729324269165216042
}

查询代币余额

首先需要得到一个代币合约的地址,在之前的 2.6 中,我们部署了一个 ERC20 合约,可以使用这个合约的地址作为本次示例的合约地址。

并且可以先创建一个 interface 的 solidity 文件,这个文件可以在 Openzeppelin 仓库中找到:

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)pragma solidity ^0.8.20;/*** @dev Interface of the ERC-20 standard as defined in the ERC.*/
interface IERC20 {/*** @dev Emitted when `value` tokens are moved from one account (`from`) to* another (`to`).** Note that `value` may be zero.*/event Transfer(address indexed from, address indexed to, uint256 value);/*** @dev Emitted when the allowance of a `spender` for an `owner` is set by* a call to {approve}. `value` is the new allowance.*/event Approval(address indexed owner, address indexed spender, uint256 value);/*** @dev Returns the value of tokens in existence.*/function totalSupply() external view returns (uint256);/*** @dev Returns the value of tokens owned by `account`.*/function balanceOf(address account) external view returns (uint256);/*** @dev Moves a `value` amount of tokens from the caller's account to `to`.** Returns a boolean value indicating whether the operation succeeded.** Emits a {Transfer} event.*/function transfer(address to, uint256 value) external returns (bool);/*** @dev Returns the remaining number of tokens that `spender` will be* allowed to spend on behalf of `owner` through {transferFrom}. This is* zero by default.** This value changes when {approve} or {transferFrom} are called.*/function allowance(address owner, address spender) external view returns (uint256);/*** @dev Sets a `value` amount of tokens as the allowance of `spender` over the* caller's tokens.** Returns a boolean value indicating whether the operation succeeded.** IMPORTANT: Beware that changing an allowance with this method brings the risk* that someone may use both the old and the new allowance by unfortunate* transaction ordering. One possible solution to mitigate this race* condition is to first reduce the spender's allowance to 0 and set the* desired value afterwards:* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729** Emits an {Approval} event.*/function approve(address spender, uint256 value) external returns (bool);/*** @dev Moves a `value` amount of tokens from `from` to `to` using the* allowance mechanism. `value` is then deducted from the caller's* allowance.** Returns a boolean value indicating whether the operation succeeded.** Emits a {Transfer} event.*/function transferFrom(address from, address to, uint256 value) external returns (bool);
}

和另外一个文件 IERC20Metadata.sol:

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/IERC20Metadata.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)pragma solidity ^0.8.20;import {IERC20} from "../IERC20.sol";/*** @dev Interface for the optional metadata functions from the ERC-20 standard.*/
interface IERC20Metadata is IERC20 {/*** @dev Returns the name of the token.*/function name() external view returns (string memory);/*** @dev Returns the symbol of the token.*/function symbol() external view returns (string memory);/*** @dev Returns the decimals places of the token.*/function decimals() external view returns (uint8);
}

这个文件虽然没有被实现,但是可以使用工具单独处理,生成调用合约时所需的 ABI 的 JSON 文件,并使用 abigen 工具根据 ABI 的 JSON 文件生成 go 代码。

solcjs --abi IERC20Metadata.sol
abigen --abi=erc20_sol_ERC20.abi --pkg=token --out=erc20.go

假设我们已经创建了以太坊客户端实例,将新的 token 包导入我们的项目,并实例化它。这个例子里我们用 RCCDemoToken 代币的地址.

tokenAddress := common.HexToAddress("0xfadea654ea83c00e5003d2ea15c59830b65471c0")
instance, err := token.NewToken(tokenAddress, client)
if err != nil {log.Fatal(err)
}

我们可以调用任何 ERC20 的方法。 例如,我们可以查询用户的代币余额。

address := common.HexToAddress("0x25836239F7b632635F815689389C537133248edb")
bal, err := instance.BalanceOf(&bind.CallOpts{}, address)
if err != nil {log.Fatal(err)
}
fmt.Printf("wei: %s\n", bal) // "wei: 74605500647408739782407023"

我们还可以读 ERC20 智能合约的公共变量。

name, err := instance.Name(&bind.CallOpts{})
if err != nil {log.Fatal(err)
}
symbol, err := instance.Symbol(&bind.CallOpts{})
if err != nil {log.Fatal(err)
}
decimals, err := instance.Decimals(&bind.CallOpts{})
if err != nil {log.Fatal(err)
}
fmt.Printf("name: %s\n", name)         // "name: Golem Network"
fmt.Printf("symbol: %s\n", symbol)     // "symbol: GNT"
fmt.Printf("decimals: %v\n", decimals) // "decimals: 18"

我们可以做一些简单的数学运算将余额转换为可读的十进制格式。

fbal := new(big.Float)
fbal.SetString(bal.String())
value := new(big.Float).Quo(fbal, big.NewFloat(math.Pow10(int(decimals))))
fmt.Printf("balance: %f", value) // "balance: 74605500.647409"

完整的代码

package main
import ("fmt""log""math""math/big""github.com/ethereum/go-ethereum/accounts/abi/bind""github.com/ethereum/go-ethereum/common""github.com/ethereum/go-ethereum/ethclient"token "./contracts_erc20" // for demo
)
func main() {client, err := ethclient.Dial("https://cloudflare-eth.com")if err != nil {log.Fatal(err)}// Golem (GNT) AddresstokenAddress := common.HexToAddress("0xfadea654ea83c00e5003d2ea15c59830b65471c0")instance, err := token.NewToken(tokenAddress, client)if err != nil {log.Fatal(err)}address := common.HexToAddress("0x25836239F7b632635F815689389C537133248edb")bal, err := instance.BalanceOf(&bind.CallOpts{}, address)if err != nil {log.Fatal(err)}name, err := instance.Name(&bind.CallOpts{})if err != nil {log.Fatal(err)}symbol, err := instance.Symbol(&bind.CallOpts{})if err != nil {log.Fatal(err)}decimals, err := instance.Decimals(&bind.CallOpts{})if err != nil {log.Fatal(err)}fmt.Printf("name: %s\n", name)         // "name: Golem Network"fmt.Printf("symbol: %s\n", symbol)     // "symbol: GNT"fmt.Printf("decimals: %v\n", decimals) // "decimals: 18"fmt.Printf("wei: %s\n", bal) // "wei: 74605500647408739782407023"fbal := new(big.Float)fbal.SetString(bal.String())value := new(big.Float).Quo(fbal, big.NewFloat(math.Pow10(int(decimals))))fmt.Printf("balance: %f", value) // "balance: 74605500.647409"
}

http://www.xdnf.cn/news/16629.html

相关文章:

  • 9.项目起步(3)
  • Scala实现常用排序算法
  • 第十二天:C++ 标准库函数分类总结
  • 【AI】开源项目整理
  • [Python] -进阶理解10- 用 Python 实现简易爬虫框架
  • 【同济大学】双速率自动驾驶架构LeAD:端到端+LLM,CARLA实测93%路线完成率,性能SOTA!
  • 基于 Hadoop 生态圈的数据仓库实践 —— OLAP 与数据可视化(四)
  • 机器学习之线性回归的入门学习
  • 语音识别dolphin 学习笔记
  • Linux 日志管理与时钟同步
  • 51单片机入门:数码管原理介绍及C代码实现
  • python快速复习篇(一)
  • Mysql事务基础
  • 7. 传输层协议 TCP
  • 国内数据集成厂商有哪些?如何选择最适合的数据集成平台?
  • Smart #5 Brabus使用45天(7500KM+)初步体验
  • 《Java 程序设计》第 12 章 - 异常处理
  • YOLO融合MogaNet中的ChannelAggregationFFN模块
  • Python 的 match-case
  • Windows管理用户脚本
  • react19更新哪些东西
  • 《计算机组成原理与汇编语言程序设计》实验报告六 存储器实验
  • 常⻅CMS漏洞
  • 第六章第一节 TIM 定时中断
  • VGA 线、DVI 线、HDMI 线、DP 线
  • 浏览器pdf、image显示
  • 视频生成模型蒸馏的方法
  • Linux基本指令,对路径的认识
  • 无人机磁力计模块运行与技术要点!
  • iOS 签名证书与上架流程详解,无 Mac 环境下的上架流程