如何通过钱包地址获取所有代币

17

我想要获取一个钱包地址所持有的代币合约列表,类似于bscscan所做的那样,但是需要通过编程的方式实现。bscscan.com/apis没有相关的端点,而web3js似乎只能报告以太坊余额。

这是可以实现的,因为bscscan报告了这个列表,许多代币跟踪器(如farmfol.io)似乎也可以提取这些信息。我只是找不到正确的方法。

4个回答

27

每个地址的ERC-20令牌余额(以及类似于TRC-20BEP-20等的ERC-20)存储在代币的合约中。

区块链浏览器会扫描每个交易以查找Transfer()事件,并且如果发射器是代币合约,则会更新其单独数据库中的代币余额。每个地址的所有代币余额(来自此单独的数据库)随后显示为地址详细页面上的代币余额。

Etherscan和BSCScan目前不提供可以返回每个地址的代币余额的API。

要获取地址的所有ERC-20代币余额,最简单的解决方案(除了找到返回数据的API之外)是循环遍历所有代币合约(或者只是您感兴趣的代币),并调用它们的balanceOf(address)函数。

const tokenAddresses = [
    '0x123',
    '0x456',
];
const myAddress = '0x789';

for (let tokenAddress of tokenAddresses) {
    const contract = new web3.eth.Contract(erc20AbiJson, tokenAddress);
    const tokenBalance = await contract.methods.balanceOf(myAddress).call();
}

1
嗨。感谢你的回答。看了你的代码,我在想除了所有erc20代币地址外,您还需要它们各自的abis才能使其工作。 是吗?如果可以,请为我澄清一下。 再次感谢 - AllJs
1
@AllJs 在这种情况下,您只需要balanceOf()函数的ABI,对于所有代币合同来说是相同的(假定它们都遵循ERC20标准),因为您仅调用此函数... 如果您想调用其他功能,则还需要将它们添加到ABI中。 - Petr Hejda

1
你可以打电话。

https://api.bscscan.com/api?module=account&action=tokentx&address=0x7bb89460599dbf32ee3aa50798bbceae2a5f7f6a&page=1&offset=5&startblock=0&endblock=999999999&sort=asc&apikey=YourApiKeyToken

并解析结果。您曾经接触过的所有令牌都将在此处显示。

BSCScan参考


0

虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会失效。-【来自审查】 - Dhaval Purohit

0

有几种不同的方法可以获取钱包的代币余额。

  1. 从创世块开始索引整个区块链,跟踪其交易历史中的所有ERC-20合约,并计算钱包的代币余额。显然不建议这样做——它需要大量的开发工作和时间。

  2. 使用Token API。像Alchemy和Moralis这样的开发工具都有免费的API。

在Alchemy的情况下,使用“alchemy_getTokenBalances”端点。详细教程在此, 或者只需按照以下步骤操作。

运行脚本之前

在查询用户的代币余额时,您应该掌握一些关键参数:

OwnerAddress:这是拥有所询问代币的区块链地址。请注意,这不是代币本身的合约地址。 tokenContractAddress:您想要获取余额的所有代币的合约地址数组。或者,如果指定字符串erc20,则会包括地址曾经持有过的所有erc20代币。

以下是在您设置Alchemy账户后的操作指南(免费): 方法1(最简单): 使用Alchemy SDK + "alchemy_getTokenBalances"终端点。 请在命令行中运行以下命令:

// Setup: npm install alchemy-sdk
import { Alchemy, Network } from "alchemy-sdk";

const config = {
  apiKey: "<-- ALCHEMY APP API KEY -->",
  network: Network.ETH_MAINNET,
};
const alchemy = new Alchemy(config);

//Feel free to switch this wallet address with another address
const ownerAddress = "0x00000000219ab540356cbb839cbe05303d7705fa";

//The below token contract address corresponds to USDT
const tokenContractAddresses = ["0xdAC17F958D2ee523a2206206994597C13D831ec7"];

const data = await alchemy.core.getTokenBalances(
  ownerAddress,
  tokenContractAddresses
);

console.log("Token balance for Address");
console.log(data);

方法二:使用 Node-Fetch

import fetch from 'node-fetch';

// Replace with your Alchemy API key:
const apiKey = "demo";
const fetchURL = `https://eth-mainnet.g.alchemy.com/v2/${apiKey}`;

// Replace with the wallet address you want to query:
const ownerAddr = "0x00000000219ab540356cbb839cbe05303d7705fa";
/* 
Replace with the token contract address you want to query:
The below address Corresponds to USDT
*/
const tokenAddr = "0xdAC17F958D2ee523a2206206994597C13D831ec7";

var raw = JSON.stringify({
  "jsonrpc": "2.0",
  "method": "alchemy_getTokenBalances",
  "headers": {
    "Content-Type": "application/json"
  },
  "params": [
    `${ownerAddr}`,
    [
      `${tokenAddr}`,
    ]
  ],
  "id": 42
});

var requestOptions = {
  method: 'POST',
  body: raw,
  redirect: 'follow'
};

var data;

/*
** Fetching the token Balance with Alchemy's getTokenBalances API
*/
await fetch(fetchURL, requestOptions)
  .then(response => response.json())
  .then(response => {
    //This line converts the tokenBalance values from hex to decimal
    response["result"]["tokenBalances"][0]["tokenBalance"] = parseInt(response["result"]["tokenBalances"][0]["tokenBalance"], 16);
    data = response.result;
    console.log("Response Object for getTokenBalances\n", data)
  })
  .catch(error => console.log('error', error));


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接