一只路过的小码农cxy
2023/05/18阅读:9主题:绿意
区块链交易 -- 了解交易
如何查询以太坊交易细节
学习如何使用 eth_getTransactionReceipt
方法获取交易的常规信息。
简介
当您在 Etherscan 上检查交易时,您可以获得如下图所示的交易的一般信息:

但是,如果您想在您的应用程序中以编程方式获取此信息,该怎么办?您可以向您应用程序的用户显示这些细节,以向他们提供有关该交易的更多信息。
关于本教程
我们将使用node.js
编写一个简单的脚本,通过交易哈希获取交易的一般详情。我们将使用Alchemy的getTransactionReceipt API获取交易的收据。交易收据包含交易的一般信息。
编写脚本
步骤1:安装Node和NPM
如果您还没有安装,请在您的本地计算机上安装Node和NPM。
通过在终端中键入以下内容确保Node至少为v14或更高版本:
node -v
步骤2:创建Alchemy应用程序
如果你还没有,请注册一个免费的Alchemy账户。

接下来,导航到Alchemy 仪表板 并创建一个新应用程序。
确保将链设置为以太坊,网络设置为 Mainnet。
创建应用程序后,单击仪表板上的您的应用程序的“查看密钥”按钮。
注意 HTTP URL。
URL 将采用此形式:https://eth-mainnet.g.alchemy.com/v2/xxxxxxxxx
稍后您将需要此 URL。
步骤3:创建一个Node项目
现在让我们创建一个空的仓库并安装所有的Node依赖。
为了发出请求,我们将使用Alchemy SDK。
您也可以选择使用ethers
或cURL
。
-
Alchemy SDK
mkdir my-project && cd my-project
npm init -y
npm install --save alchemy-sdk
touch main.js
-
ethers
mkdir my-project && cd my-project
npm init -y
npm install --save ethers
touch main.js
这将创建一个名为my-project
的仓库,其中包含您的所有文件和依赖项。
接下来,在您喜欢的代码编辑器中打开此仓库。
我们将在main.js
文件中编写所有代码。
步骤4:获取交易收据
为了获得交易收据,我们将使用 getTransactionReceipt方法,该方法将字符串交易哈希作为参数。
将以下代码添加到 main.js
文件中。
-
Alchemy SDK
const { Network, Alchemy } = require("alchemy-sdk");
// Optional config object, but defaults to demo api-key and eth-mainnet.
const settings = {
apiKey: "<-- ALCHEMY API KEY -->", // Replace with your Alchemy API Key.
network: Network.ETH_MAINNET, // Replace with your network.
};
const alchemy = new Alchemy(settings);
alchemy.core
.getTransactionReceipt(
"0x68ea69fd8b5dfa589a7a983c324ab153a33356320207885a9bba84425598dcaa" // Transaction hash of the transaction for which you want to get information.
)
.then(console.log);
-
ethers
const ethers = require("ethers");
(async () => {
const provider = new ethers.providers.JsonRpcProvider("https://eth-mainnet.g.alchemy.com/v2/your-api-key");
const txReceipt = await provider.waitForTransaction(
"0x68ea69fd8b5dfa589a7a983c324ab153a33356320207885a9bba84425598dcaa" // Transaction hash of the transaction for which you want to get the information
);
console.log(txReceipt);
})();
要发出请求,请使用以下命令运行脚本或使用 cURL
发出请求:
-
JavaScript
node main.js
-
cURL
curl https://eth-mainnet.g.alchemy.com/v2/your-api-key \
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"eth_getTransactionReceipt","params":["0x68ea69fd8b5dfa589a7a983c324ab153a33356320207885a9bba84425598dcaa"],"id":1,"jsonrpc":"2.0"}'
如果一切顺利,您应该看到类似于这样的输出:
{
to: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
from: '0xe5cB067E90D5Cd1F8052B83562Ae670bA4A211a8',
contractAddress: null,
transactionIndex: 86,
gasUsed: BigNumber { _hex: '0xe429', _isBigNumber: true },
logsBloom: '0x00000000000000000000001000000000000000000000000000000000000000000000000000000000000200000000010000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000200000000000000100000000000000000000000000080000000100000000000000000000000000000000000000002000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
blockHash: '0x2b9055d24eaeda177211e3b0f183c3b21c2f425d32d8fa7b710df0c63a89a558',
transactionHash: '0x68ea69fd8b5dfa589a7a983c324ab153a33356320207885a9bba84425598dcaa',
logs: [
{
transactionIndex: 86,
blockNumber: 15802409,
transactionHash: '0x68ea69fd8b5dfa589a7a983c324ab153a33356320207885a9bba84425598dcaa',
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
topics: [Array],
data: '0x000000000000000000000000000000000000000000000000000000001101bd29',
logIndex: 127,
blockHash: '0x2b9055d24eaeda177211e3b0f183c3b21c2f425d32d8fa7b710df0c63a89a558'
}
],
blockNumber: 15802409,
confirmations: 209486,
cumulativeGasUsed: BigNumber { _hex: '0x5f17f5', _isBigNumber: true },
effectiveGasPrice: BigNumber { _hex: '0x0425f51bc5', _isBigNumber: true },
}
输出字段如下:
-
transactionHash
- 交易哈希。 -
transactionIndex
- 交易在块中的索引位置,编码为十六进制。 -
from
- 发送者地址。 -
to
- 接收者地址。当为合约创建交易时为 null。 -
blockHash
- 交易所在块的哈希。 -
blockNumber
- 交易添加到的块的块号,编码为十六进制。 -
cumulativeGasUsed
- 在块中执行此交易时使用的总燃料。 -
effectiveGasPrice
- 交易时的每个燃料价格。 -
gasUsed
- 仅此特定交易使用的燃料量。 -
contractAddress
- 用于合约创建的合约地址,否则为 null。 -
logs
- 此交易生成的日志对象数组。 -
logsBloom
- 用于轻客户端快速检索相关日志的布隆过滤器。 -
value
- 以十六进制编码的 Wei 转移的价值。
恭喜!您现在知道如何以编程方式获取有关交易的一般信息。
理解以太坊上的交易对象
本指南详细介绍了eth_getTransactionByHash返回的Transaction对象响应中的每个元素。
交易对象
以太坊上的交易对象由以下组成:
-
blockHash
:DATA
,32字节 - 交易所在区块的哈希值。当交易待处理时为null。 -
blockNumber
:QUANTITY
- 交易所在区块的块号。当交易待处理时为null。 -
from
:DATA
,20字节 - 发送者地址。 -
gas
:QUANTITY
- 发送者提供的gas。 -
gasPrice
:QUANTITY
- 发送者提供的gas价格,以Wei为单位。 -
hash
:DATA
,32字节 - 交易的哈希值。 -
input
:DATA
- 与交易一起发送的数据。 -
nonce
:QUANTITY
- 发送者在此之前发出的交易数量。 -
to
:DATA
,20字节 - 接收者地址。当交易是合约创建交易时为null。 -
transactionIndex
:QUANTITY
- 交易在区块中的位置。当交易待处理时为null。 -
value
:QUANTITY
- 以Wei为单位的转移金额。 -
v
:QUANTITY
- ECDSA恢复ID -
r
:DATA
,32字节 - ECDSA签名r -
s
:DATA
,32字节 - ECDSA签名s
以下是交易对象中每个参数的更详细说明。
hash
每个已验证并添加到区块链中的交易都会收到分配的哈希值
。这为交易创建了一个唯一标识符,可用于定位和检索有关特定交易的信息。
blockHash
每个区块都有一个相应的加密哈希值,其中包括该区块的所有数据。blockHash
是包含此交易的区块的哈希值。对于未添加到区块的待处理交易,您将收到一个null值。
blockNumber
一旦区块添加到区块链中,它就会按顺序分配以下可用编号。使用blockNumber
,可以确定交易何时已添加到区块中。
from
以太坊交易具有发送方和接收方。from
字段是发送方的地址,可用于查找启动交易的地址。
gas
为使交易完成并添加到区块中,发送方必须提供额外的gas量以及交易的价值。Gas用于覆盖完成交易所需的计算成本。此gas
字段显示了发送方提供的gas量。
gasPrice
另一种显示gas价格的方法是以Wei为单位。 Wei是ETH的最小面额,是处理小额ETH交易的更好方式。 1 wei等于10 ^ -18 ETH。此gasPrice
显示发送方以WEI提供的gas量。
input
在用户部署或调用智能合约中的函数时,可以将数据添加到交易的数据字段中。此数据是指向将被执行的函数的智能合约的消息。
input
字段包含包含在交易中的数据。如果此字段为空,则交易是用户之间的转移,并且不涉及智能合约。
nonce
为防止用户重复消费并确保交易按正确顺序发生,来自给定地址的每个交易都有一个分配的nonce
。nonce是该特定地址的交易数量。每次交易后,nonce增加1。必须完成一笔交易才能开始另一笔交易。
to
交易具有发送方和接收方。to
字段是接收方的地址,可用于查找启动交易的地址。
transactionIndex
当交易添加到区块中时,它被分配为该块内的编号位置。transactionIndex
返回已添加到其中的块的交易的位置的值。
value
每个交易都有一个附加的值,这是从发送方传输到接收方的金额。value
返回此数量,并以Wei显示。
r,s
以太坊使用ECDSA(椭圆曲线数字签名算法)创建交易的数字签名。这些签名用于验证它们是真实的并来自正确的发送方,就像真实的签名一样。
数字签名可以分为两个数字 - r
和s
。这些数字由您的私钥生成。通过将s
发送到算法,应该获得用于验证签名的R
的值。
v
ECDSA在验证交易签名时使用v
值来恢复正确的公钥。它是以下两个值的组合:
-
recovery_id - ECDSA用于生成密钥的曲线上的位置。 -
chain_id - 以太坊网络ID(例如:1-以太坊主网)。
什么是内部交易?
这是关于以太坊内部交易的深入指南,以及如何使用Alchemy Transfers API检索它们。
内部交易是智能合约之间发生的交易。这也包括从智能合约向用户发送ETH时的交易到外部地址。这些交易被标记为内部交易,因为以太坊区块链上部署的每个智能合约都有一个指定的内部地址。
另一方面,代币转移是发生在用户创建的外部地址之间的另一种交易。这种交易的一个例子是代币转移,比如一个用户向另一个用户发送ERC-20代币。
当外部地址调用智能合约执行操作时,将触发内部交易。合约将使用其内置逻辑开始与完成操作所需的其他合约进行交互。即使在单个交易中,智能合约可能需要执行多个对其他合约的内部调用。
内部交易示例
这种交易流程的典型示例是使用代币交换。
-
代币转移 - 用户通过向交换的智能合约发送其代币来开始ERC-20代币的交换。 -
代币转移 - 交易所的智能合约随后将代币存入连接到流动性池的智能合约中。 -
内部交易 - 交易所的合约收到以WETH(包装的以太坊)兑换的金额,然后将该金额发送到WETH智能合约以转换为ETH。 -
内部交易 - 交易所的合约将此ETH发送到用户的外部地址以完成交换。
用例
内部交易可以为用户提供一些重要信息。以下是一些dApp中可以使用内部交易信息的用例:
-
失败交易通知 - 如果内部交易失败,整个交易将失败。通知用户故障点的确切位置有助于解决问题。 -
智能合约监控 - 您的部署的智能合约可以通过内部交易与其他合约交互。为了知道它与哪些合约交互以及何时交互,您可以监视您的智能合约地址以获取任何内部交易。 -
区块链分析 - 由于内部交易可以很复杂,因此获取见解是有帮助的。通过查看智能合约执行的内部交易数量,您可以了解该合约的受欢迎程度和性能。 -
批量交易 - 如果您向不同的发送者地址发送一批交易,则可以使用内部交易更方便且更安全地确保它们到达正确的地址。
跟踪内部交易
在内部交易中找到的信息可以指导和告知用户有关其交易的情况。内部交易的棘手之处在于它们不存储在链上,并且没有像外部交易那样的加密签名。这使得它们更难以跟踪,并需要额外的资源,如存档节点。
幸运的是,您可以使用Alchemy转账API找到内部交易可用的信息,而无需进行任何额外的设置。
要获取内部交易信息,请将category
设置为internal
,如下例所示:
{
"jsonrpc": "2.0",
"id": 0,
"method": "alchemy_getAssetTransfers",
"params": [
{
"fromBlock": "0xA97AB8",
"toBlock": "0xA97CAC",
"maxCount": "0x5",
"excludeZeroValue": true,
"category": [
"internal"
]
}
]
}
有关格式化您的请求和响应的更多信息,请查看Transfers API。
如何处理校验和地址
了解以太坊中的校验和地址是什么,它们为什么存在以及如何使用ethers库处理它们。
在与以太坊和类似的Web3环境一起工作时,较不友好的一个方面是使用40个字符的十六进制字符串代表区块链上的钱包(或帐户)。
以太坊的创建者从未想过使用十六进制字符串来识别区块链上的实体。相反,他们希望像ENS这样的系统成为用户可读名称的标准,例如vitalik.eth。
尽管ENS名称日益普及并得到支持,但事实仍然是绝大多数用户继续使用十六进制地址在公共区块链上进行交易。
记住和输入地址的复杂性以及Web3交易的不可逆性导致了校验和地址的创建,作为对人为错误的适度故障安全机制。
在本短教程中,我们将介绍校验和地址的含义、工作原理以及如何使用ethers库处理它们。
什么是校验和地址?
正如您可能已经知道的那样,以太坊地址表示为40个字符的十六进制字符串。校验和地址是以太坊地址的一种特殊版本,它增加了一定的大小写敏感性。
如果您在类似MetaMask的钱包上检查您的钱包地址,您会发现有些字母是大写的,而有些则不是。这是校验和验证在起作用,以此特定的方式大写某些字母,以防止用户错误地进行无法撤销的交易。
计算地址的校验和相当简单。
1.将原始以太坊地址转换为小写。 2.计算小写地址的SHA-3哈希值。 3.取哈希值的前40个字符(它是一个64个字符的十六进制字符串),并替换原始小写地址中的相应字符。如果哈希中的字符是字母(A-F),则地址中的相应字符应为大写。如果哈希中的字符是数字(0-9),则地址中的相应字符应保持小写。 4.最终结果是地址的校验和版本。
使用ethers处理校验和地址
幸运的是,我们不需要手动执行上述步骤。 ethers库提供了一个非常方便的函数,将所有小写的钱包地址转换为其带校验和的版本。 它还允许我们检测校验和无效的地址。
以下是一个演示上述两个功能的节点脚本:
const ethers = require('ethers');
// All lowercase address
const address = '0xc361fc33b99f88612257ac8cc2d852a5cee0e217'
// Convert to checksum version
let checksum = ethers.utils.getAddress(address)
console.log("Checksum address:", checksum)
// Invalid checksum
const invalid = "0xc361fc33b99F88612257ac8cc2D852A5CEe0E217"
checksum = ethers.utils.getAddress(invalid);
运行此脚本后,您应该看到类似于此的输出:
Checksum address: 0xc361Fc33b99F88612257ac8cC2d852A5CEe0E217
/Users/rounakbanik/alchemy-tut/nft-collection/node_modules/@ethersproject/logger/lib/index.js:247
throw this.makeError(message, code, params);
^
Error: bad address checksum (argument="address", value="0xc361fc33b99F88612257ac8cc2D852A5CEe0E217", code=INVALID_ARGUMENT, version=address/5.7.0)
at Logger.makeError (/Users/rounakbanik/alchemy-tut/nft-collection/node_modules/@ethersproject/logger/lib/index.js:238:21)
at Logger.throwError (/Users/rounakbanik/alchemy-tut/nft-collection/node_modules/@ethersproject/logger/lib/index.js:247:20)
at Logger.throwArgumentError (/Users/rounakbanik/alchemy-tut/nft-collection/node_modules/@ethersproject/logger/lib/index.js:250:21)
at Object.getAddress (/Users/rounakbanik/alchemy-tut/nft-collection/node_modules/@ethersproject/address/lib/index.js:80:20)
at Object.<anonymous> (/Users/rounakbanik/alchemy-tut/nft-collection/checksum.js:12:25)
at Module._compile (internal/modules/cjs/loader.js:1068:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1097:10)
at Module.load (internal/modules/cjs/loader.js:933:32)
at Function.Module._load (internal/modules/cjs/loader.js:774:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12) {
reason: 'bad address checksum',
code: 'INVALID_ARGUMENT',
argument: 'address',
value: '0xc361fc33b99F88612257ac8cc2D852A5CEe0E217'
}
正如预期的那样,以太币可以为我们提供一个所有字母小写的地址的校验和版本,并正确地识别出具有无效校验和的地址。
结论
围绕以太坊钱包和钱包地址的用户体验仍然有很大的提升空间。尽管像 ENS 这样的解决方案很快赶上了,但大多数在区块链上进行的交易仍使用十六进制地址。
虽然强烈建议您复制粘贴钱包地址,永远不要手动输入它们,但像校验和这样的解决方案使我们能够拥有一个故障保护,防止涉及错误输入地址的不可逆转交易的发生。
作者介绍