本文中,我们将在以太坊测试网上用 ethers.js 重发交易,并介绍相关的术语和知识。
有时,在以太坊上提交的交易没有足够的 gas ,因为网络拥堵或有太多的待处理交易提供了比你的交易报价更高的 gas 价格。如果你有一个高优先级的交易,但由于 gas 不足,可能最终不得不等待数小时甚至数天才能打包结算。在这种情况下,你需要用更高的 gas 价格和相同的 nonce 重新发送交易,以使它尽早被打包。
本文中,我们将在以太坊测试网上用 ethers.js 重发交易,并介绍相关的术语和知识。
当我们想在以太坊网络上添加、更新或修改一些内容时,就需要发送一笔交易。基本上,交易是现实世界与以太坊网络互动的方式。每一笔在以太坊网络上交易,都需要支付一笔叫做 gas 的费用。gas 的单位是 wei(ETH的最小单位)或 gwei。
以太坊的交易类型
在以太坊网络中,有三种常见的交易类型:
一个典型的以太坊交易的参数:
以太坊的交易流程
对交易进行签名
签署交易是指使用发送者的私钥在交易对象上生成一个签名。如果你想了解更多关于以太坊签名和验证的信息,这里有一些很好的读物:Yos 写 以太坊签名和验证签名和Angello Pozo的 以太坊签名和验证
现在,我们对以太坊的交易有了更好的了解,下面我们自己发一笔交易:
依赖条件:
我们使用 NodeJS 来管理库和处理 javascript 文件。先看看是否安装了 NodeJS ,打开终端并运行:
$ node -v
如果没有安装,可以从官方网站下载 NodeJS 的 LTS 版本。
为了发送交易,我们将使用一段简短的 javascript 代码,以及将使用 ethers.js 库,你可以在命令行终端用 npm 安装它:
$ npm install --save ethers
在这一步最常见的问题是node-gyp
的内部故障,可以参考node-gyp安装说明。
另一个常见的问题是缓存过期,只需要除 npm 的缓存:
$ npm cache clean
查看ethers.js指南以了解更多关于 ethers.js 库的信息。
现在,让我们为自己创建一个钱包账号。首先,创建一个 index.js 文件或你要的其他命名的 javascript 文件。然后将下面复制/粘贴到你的代码编辑器中:
var ethers = require('ethers');
var privateKey = "0x0111111111111111111122222222222222222223333333333333333333344445";
var wallet = new ethers.Wallet(privateKey);
console.log("Address: " + wallet.address);
稍微解释一下代码:导入之前安装的 ethers.js 库(第1行),为钱包创建一个特定的私钥,它可以是任何数字,并确保它包含与上面(第2行)相同的位数,使用私钥在以太坊创建一个钱包实例(第3行),在控制台打印文字"Address:"及钱包地址(第4行)。
用以下方法运行该文件:
node index.js
如果一切顺利,它应该看起来像这样:
由于每笔交易都需要 gas 费,我们需要一些 gas 在交易中发送,我们可以在钱包中获得一些测试 ETH。为此,我们将使用一个 Kovan 节点,去 Kovan 水龙头获得一些测试 ETH,复制粘贴你运行上述代码得到的钱包地址,然后点击“send me KETH!” 。
注意:这是测试 ETH ,没有市场价值。
对于本文来说,我们可以使用任何以太坊客户端,如 Geth 或 OpenEthereum(之前名为 Parity)。要独自启动一个以太坊节点,首先需要选择一个客户端并对其进行配置;同步一个以太坊节点并维护它是一项具有挑战的任务;同步一个以太坊全节点可能需要几天时间。
这对于仅仅发送一个交易来说有点太过复杂,我们选择 QuikNode 提供的免费节点URL。成功创建免费以太坊节点后,复制提供者地址( HTTP Provider)地址:
本文中使用的是 Kovan 的测试网节点。
你以后会需要使用,请复制它并保存好。
现在,我们有一个钱包地址和一些测试 ETH 。现在,我们发送一个交易,将一些 ETH 转移到另一个钱包地址。首先我们需要在 index.js 文件中添加一些内容,把下面的代码复制/粘贴到代码编辑器中:
var ethers = require('ethers');
var url = 'ADD_YOUR_ETHEREUM_NODE_URL';
var customHttpProvider = new ethers.providers.JsonRpcProvider(url);
var privateKey = "0x0111111111111111111122222222222222222223333333333333333333344445";
var wallet = new ethers.Wallet(privateKey);
console.log("Address: " + wallet.address);
tx = {
to: "0x6E0d01A76C3Cf4288372a29124A26D4353EE51BE",
value: ethers.utils.parseEther("0.05"),
chainId: 42,
nonce: 3
}
customHttpProvider.estimateGas(tx).then(function(estimate) {
tx.gasLimit = estimate;
tx.gasPrice = ethers.utils.parseUnits("0.14085197", "gwei");
wallet.signTransaction(tx).then((signedTX)=>{
customHttpProvider.sendTransaction(signedTX).then(console.log);
});
});
然后,用上面一节中的 HTTP 提供者替换ADD_YOUR_ETHEREUM_NODE_URL
。
简单解释一下上面的代码:(第1行)导入之前安装的 ethers 库,(第2行)设置以太坊节点 URL,(第3行)实例化一个 ethers JsonRpcProvider
实例,(第4行)创建一个特定的钱包的私钥,可以是任何数字,并确保它包含相同位数。(第5行)用私钥创建一个以太坊的钱包实例,(第6行)在控制台中打印钱包地址,(第7-12行)创建一个交易对象并在 to
字段中添加接收者的地址,你也可以用var wallet = Wallet.createRandom();
生成一个随机地址,在value
字段设置要发送的 ETH 的价值,在chainId
字段,因为我们使用的是 Kovan ,设置为42,nonce
字段设置为3,(第13-15行)根据节点估计 gasLimit
并设置 gas 价格,(第16-18行)用钱包的私钥为交易签名并发送,同时在控制台打印该交易。
运行一下:
node index.js
我们会得到一个类似这样的输出:
复制hash字段的字符串(类似0xe49c8122656c612bf5f1e10b251f56671acf01d831b6876c37c5a52053035642
)并粘贴到Kovan 浏览器的搜索框中,以检查交易的状态。你会看到,该交易尚未被添加到区块链上的新区块中,是等待(pending)状态。这是因为我们设置的 gas 值明显偏低。
现在,我们尝试用相同的 nonce 发送相同的交易,但这次是增加 gas 值;将代码中第15行的gasPrice
值从0.14085197
改为2.14085197
并重新运行代码:
node index.js
复制新输出的ash字段的字符串,并将其粘贴到Kovan 浏览器的搜索框中,再次检查交易的状态。这一次,我们的交易成功被添加到区块中,并且状态为成功,因为我们在发送交易时增加了gasPrice
值。
注意:
nonce
值在两次交易中是相同的。如前所述,nonce 是一个以太坊地址的交易数量。为了重新提交一个有更多 gas 的交易,你必须使用与原始交易相同的nonce。如果你使用增加的 nonce,这将是一个新的交易,那么你的发送 ETH 会比你的想象的更多(因为发送了两次)。
因此,正如我们在上面的例子中看到的,交易的 gas 价格是用于竞争交易优先打包权。区块链上的矿工通常会根据可用的区块空间占有率来设置 gas ,当有一笔交易的 gas 低于阈值 gas 值时,它不会被验证。与其他交易相比,gas 值较高的交易会很快得到验证。
本翻译由 CellETF 赞助支持。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!