web3 getTransactionCount() 函数 (docs) 是 eth_getTransactionCount JSON-RPC 方法 (docs) 的包装器,返回 从 指定地址发送的已挖掘交易数量。
由于您的代码指定了“合约地址”,我假设您希望返回对合约地址执行指定操作的交易量 - 由任何调用者。
请注意,截图中“方法”列中的“Mint NFT”仅代表执行的函数名称。这并不意味着实际上已经开采了 NFT。所以理论上你可以有一个名为mintNFT()的函数来执行一个完全不同的动作:
function mintNFT() external {
// does not mint any NFT
counter++;
}
另外——这对于下一段很重要——一个合约可以包含多个同名的函数,这些函数会导致不同的函数选择器,因为它们具有不同的参数数据类型。
// all of these can be in the same contract
mintNFT(address to) // selector `0x54ba0f27`
mintNFT(address to, uint256 ID) // selector `0x3c168eab`
mintNFT(uint256 ID) // selector `0x92642744`
因此,如果您想通过调用的函数进行过滤,您需要知道(或计算)其特定的选择器 - 而不仅仅是函数名称。它是函数名称的 keccak-256 散列的前 4 个字节(8 个十六进制字符),后面是用逗号分隔的参数数据类型,用括号括起来。示例:
// keccak-256 hash of this string, first 4 bytes
// and you get the `0x3c168eab` selector mentioned earlier
mintNFT(address,uint256)
最后,没有本地方式(在以太坊 JSON-RPC API 中,一些其他区块链,如 Polygon 或 BSC 也实现)来获取地址发送或接收的交易列表。由于 web3 是 JSON-RPC API 的包装库(另外它包含一些相关的帮助程序和实用函数),因此无法使用 web3 来实现此结果。
因此,您需要将所有现有交易(至少在您感兴趣的区块范围内)收集到可搜索的数据库中。或者 - 使用已经存在的可搜索集合。
出于此答案的目的,我将使用PolygonScan API,它可以免费用于有限使用,因为您的问题表明目标合同在 Polygon 上。而this contract 实现了两个具有相同名称(mint())但函数选择器不同的函数。让我们使用 2003 行中定义的后一个函数:
function mint(
address to,
uint32 batch,
uint32 sequence,
uint32 limit,
string memory name,
string memory page,
string memory description,
string memory link,
string memory content,
string memory created
)
选择器是根据下面的字符串计算出来的
mint(address,uint32,uint32,uint32,string,string,string,string,string,string)
其值为0xab2a6d77。
那么这个过程就很简单了。一旦获得到合约地址的所有交易列表,您只需通过选择的函数选择器过滤它们,该选择器始终是原始交易的data 字段的前 4 个字节(命名为input 在 API 中)。
请注意,可以向data 字段(通常为 0)中少于 4 个字节的合约发送交易,因此您的代码也应考虑到这一点。
const axios = require("axios");
const API_KEY = "YourApiKeyToken";
const CONTRACT_ADDRESS = "0x90410A6bc2285dF5A726b0b89D8bE60C9B6fA26E";
const SELECTOR = "0xab2a6d77";
const run = async () => {
const allTransactions = await _getAllTransactionsTo(CONTRACT_ADDRESS);
const filteredTransactions = _filterTransactionsBySelector(allTransactions, SELECTOR);
const txHashes = _getTransactionHashes(filteredTransactions);
console.log(txHashes);
}
const _getAllTransactionsTo = async (address) => {
const response = await axios(
"https://api.polygonscan.com/api"
+ "?module=account"
+ "&action=txlist"
+ "&address=" + address
+ "&startblock=0"
+ "&endblock=99999999"
+ "&page=1"
+ "&offset=10"
+ "&sort=asc"
+ "&apikey=" + API_KEY
);
// the API returns transaction both `from` and `to` the address
// this filter is unnecessary for contract addresses (as there are no transactions `from` a contract)
return response.data.result.filter((item) => {
// mind that the API might return the params in lowercase, while your input address might be checksum
return item.to.toLowerCase() === address.toLowerCase();
});
}
const _filterTransactionsBySelector = (allTransactions, selector) => {
return allTransactions.filter((item) => {
return item?.input.startsWith(selector);
});
}
const _getTransactionHashes = (transactions) => {
return transactions.map((item) => {
return item.hash;
});
}
run();
它打印调用指定mint() 函数的事务的哈希值(只是选择器指定的这个 - 而不是另一个)。
[
'0xd6a141780585e0833382cfa5940db4bd1b2acde8108c949421242077d6a5d16d',
'0x63bfaae7afbd50f1ee052182aeee7147ba256c6285bc2783f8607a881dbf135f',
'0x57cd8c74c13aded28841f14a79b1901a5e12a87aae38ea4f8af19a7ef976e281',
'0x8dbbb9f7fa11ec0c025d1cec2ac75862a89dc10fe69d4599f2401db2a089c0c9',
'0x34fa6285fbf63313127422be8b84214906642a2399b971e863b0b7950bd57ca4',
'0x4fcab773f03ed5f12b85c2329e14226b5afb4120e9227e8da423bd7d88fb06ed',
'0x67d540059dcf9d6c6a63e03f8882fe1522897d09c03f9185c540c807cf1972b8'
]