发送第一笔交易

用 TronWeb 在 Shasta 测试网上生成账户、领取测试 TRX、签名并广播第一笔 TRX 转账。

📘

前置阅读

本文带你在 Shasta 测试网上发起第一笔 TRX 交易:安装 TronWeb、生成测试账户、领取测试 TRX、构造并签名交易、广播到网络,最后在 TRONSCAN 上验证结果。全程约 15 分钟。

💡

只想要代码?

移步 recipe 版本——同样的流程,压缩成可直接复用的代码片段,附资源成本摘要和常见错误对照表。


第一步 — 安装 TronWeb

准备仍在维护期内的 Node.js LTS 版本及 npm,然后新建项目目录并安装本文验证使用的 TronWeb 版本:

mkdir tron-hello && cd tron-hello
npm init -y
npm install --save-exact [email protected]

第二步 — 生成密钥对

每个 TRON 账户 都由一个私钥控制。生成两个仅用于 Shasta 的账户:发送账户用于领取并转出测试 TRX,接收账户用于核对转账结果。

const { TronWeb } = require('tronweb');

const sender = TronWeb.createRandom();
const recipient = TronWeb.createRandom();

console.log('Sender address:', sender.address);
console.log('Sender private key:', sender.privateKey);
console.log('Recipient address:', recipient.address);
console.log('Recipient private key:', recipient.privateKey);

妥善保存两组测试凭据,并明确标记发送账户和接收账户。不同版本的 SDK 可能在私钥前显示 0x;第四步的示例兼容带或不带该前缀的私钥。


第三步 — 领取测试网 TRX

打开水龙头,粘贴发送账户的 Base58 地址申请测试 TRX。请在 10 TRX 转账金额之外保留测试 TRX,用于支付可能产生的 Bandwidth 和账户激活成本。如果接收地址尚未激活,本次转账会创建其链上账户状态;费用由当前链参数决定,可在发送前通过 wallet/getchainparameters 查询。参见激活账户。


第四步 — 转账 10 TRX

新建 send.js:

const { TronWeb } = require('tronweb');

const rawPrivateKey = process.env.TRON_PRIVATE_KEY || '';
const privateKey = rawPrivateKey.replace(/^0x/i, '');
if (!/^[0-9a-fA-F]{64}$/.test(privateKey)) {
  throw new Error('请通过 TRON_PRIVATE_KEY 提供 64 个十六进制字符的 Shasta 测试账户私钥');
}

const recipientAddress = process.env.TRON_RECIPIENT_ADDRESS;
if (!TronWeb.isAddress(recipientAddress)) {
  throw new Error('请通过 TRON_RECIPIENT_ADDRESS 提供有效的 TRON 接收地址');
}

const tronWeb = new TronWeb({
  fullHost: 'https://api.shasta.trongrid.io',
  privateKey
});

async function sendTrx() {
  const amount = 10 * 1_000_000; // 10 TRX,以 sun 为单位(1 TRX = 1,000,000 sun)

  try {
    const tx = await tronWeb.transactionBuilder.sendTrx(recipientAddress, amount);
    const signed = await tronWeb.trx.sign(tx);

    // 广播前保存 txID;即使请求超时,也能继续查询同一笔交易。
    console.log('Transaction ID:', signed.txID);
    try {
      const result = await tronWeb.trx.sendRawTransaction(signed);
      if (result.result !== true) {
        const message = /^(?:[0-9a-fA-F]{2})+$/.test(result.message || '')
          ? Buffer.from(result.message, 'hex').toString('utf8')
          : result.message;
        throw new Error(`${result.code || 'UNKNOWN'} ${message || ''}`.trim());
      }
      console.log('广播调用:未报告错误');
    } catch (error) {
      console.error('广播调用报告错误或结果未知:', error);
      console.error(`请保留并继续查询原 txID:${signed.txID}`);
      process.exitCode = 1;
    }
  } catch (error) {
    console.error('交易构造或签名失败:', error);
    process.exitCode = 1;
  }
}

sendTrx();

执行前,将命令中的接收地址占位文本替换为第二步生成的接收账户地址:

read -s TRON_PRIVATE_KEY
export TRON_PRIVATE_KEY
export TRON_RECIPIENT_ADDRESS='第二步生成的接收地址'
node send.js
# 输出:Transaction ID: 5f3e4e0a... 广播调用:未报告错误
unset TRON_PRIVATE_KEY TRON_RECIPIENT_ADDRESS

第五步 — 在 TRONSCAN 验证

打开 https://shasta.tronscan.org/#/transaction/<YOUR_TX_ID>,使用第四步在广播前输出的 txID 查询交易。核对发送地址、接收地址、金额(10 TRX)、执行结果、所在区块和资源消耗,并等待所在区块进入固化状态。最后比较两个账户转账前后的余额;如果接收账户此前未激活,还应确认它已建立链上账户状态。

如果交易暂时无法查询,不要立即重新构建并发送另一笔转账。继续查询原 txID,并按照广播后查询不到交易时,如何安全重试?判断是否可以重试。


Java 版本(Trident SDK)

该示例使用 JDK 8 或 17、Maven 3.8+ 和 Trident 1.0.0。在空目录中创建 pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>example</groupId>
  <artifactId>send-trx</artifactId>
  <version>1.0.0</version>
  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
  </properties>
  <dependencies>
    <dependency>
      <groupId>io.github.tronprotocol</groupId>
      <artifactId>trident</artifactId>
      <version>1.0.0</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>3.5.1</version>
      </plugin>
    </plugins>
  </build>
</project>

创建源码目录:

mkdir -p src/main/java

将以下代码保存为 src/main/java/SendTrx.java:

import org.tron.trident.core.ApiWrapper;
import org.tron.trident.proto.Chain.Transaction;
import org.tron.trident.proto.Response.TransactionExtention;

public class SendTrx {
    public static void main(String[] args) throws Exception {
        String privateKey = System.getenv("TRON_PRIVATE_KEY");
        if (privateKey != null && (privateKey.startsWith("0x") || privateKey.startsWith("0X"))) {
            privateKey = privateKey.substring(2);
        }
        if (privateKey == null || !privateKey.matches("[0-9a-fA-F]{64}")) {
            throw new IllegalArgumentException("TRON_PRIVATE_KEY must contain 64 hexadecimal characters");
        }
        String recipientAddress = System.getenv("TRON_RECIPIENT_ADDRESS");
        if (recipientAddress == null || recipientAddress.isEmpty()) {
            throw new IllegalArgumentException("TRON_RECIPIENT_ADDRESS must contain a TRON recipient address");
        }
        ApiWrapper.parseAddress(recipientAddress);

        ApiWrapper client = ApiWrapper.ofShasta(privateKey);
        try {
            String senderAddress = client.keyPair.toBase58CheckAddress();
            TransactionExtention tx = client.transfer(
                senderAddress, recipientAddress, 10_000_000L);
            Transaction signed = client.signTransaction(tx);
            String txid = ApiWrapper.toHex(ApiWrapper.calculateTransactionHash(signed));
            System.out.println("Transaction ID: " + txid);
            try {
                String broadcastTxid = client.broadcastTransaction(signed);
                if (!txid.equalsIgnoreCase(broadcastTxid)) {
                    throw new IllegalStateException("Broadcast returned a different transaction ID");
                }
                System.out.println("Broadcast call: no reported error");
            } catch (RuntimeException error) {
                System.err.println("Broadcast call reported an error or the result is unknown.");
                System.err.println("Keep querying the original txID: " + txid);
                throw error;
            }
        } finally {
            client.close();
        }
    }
}

设置发送账户私钥和接收账户地址并运行;同样需要替换接收地址占位文本:

read -s TRON_PRIVATE_KEY
export TRON_PRIVATE_KEY
export TRON_RECIPIENT_ADDRESS='第二步生成的接收地址'
mvn -q compile exec:java -Dexec.mainClass=SendTrx
unset TRON_PRIVATE_KEY TRON_RECIPIENT_ADDRESS

底层链路解析

  1. 构造:TronWeb 拼装出一笔 TransferContract 交易,属于 TRON 系统合约类型之一。
  2. 签名:使用私钥生成 ECDSA(secp256k1)签名。
  3. 广播:已签名交易通过 HTTP API 提交到全节点。
  4. 打包:超级代表(SR) 在后续出块时将交易纳入区块;TRON 通常每 3 秒出一个区块。
  5. 资源成本:简单转账只消耗带宽(Bandwidth),不消耗能量(Energy)。当前 getFreeNetLimit 参数为每账户 600 Bandwidth,使用量按 24 小时滚动窗口恢复;一笔典型 TRX 转账约消耗 270 Bandwidth。实际是否燃烧 TRX 取决于交易大小和账户当时的可用带宽。

下一步


相关资源