# 底层 API

底层 API 提供了对整个交易生命周期的精细控制。与对细节进行抽象的[高级 API](./api-reference-transaction-helpers.md) 不同，这些方法允许您手动构建、编码、签名和发送交易。这对于高级场景非常理想，例如多重签名工作流，其中不同方需要在交易广播前对其进行签名。

该 API 分为四个主要的方法组，每个方法组对应交易生命周期中的一个阶段：

1. **编码**：准备一笔交易并将其序列化为二进制缓冲区。
2. **签名**：向已编码的交易添加数字签名。
3. **多重签名**：向一笔交易添加多个数字签名。
4. **发送**：将已签名的交易广播到区块链。


## 编码交易

编码是创建交易的第一步。`encode[Type]Tx` 方法接收核心交易数据（`itx`）并将其包装在标准交易结构中，添加必要的细节，如 `chainId` 和 `nonce`。结果是一个人类可读的交易对象和一个可供签名的二进制缓冲区。

链支持的每种交易类型都有一个对应的 `encode` 方法。您可以通过调用 `client.getTxEncodeMethods()` 获取完整列表。

### `encode[Type]Tx(payload)`

对交易进行编码，但不签名。

**参数**

<x-field-group>
  <x-field data-name="tx" data-type="object" data-required="true">
    <x-field-desc markdown>交易数据对象。</x-field-desc>
    <x-field data-name="itx" data-type="object" data-required="true" data-desc="特定于交易类型的内部交易对象。"></x-field>
    <x-field data-name="from" data-type="string" data-required="false" data-desc="发送方地址。如果未提供，则从钱包中派生。"></x-field>
    <x-field data-name="nonce" data-type="number" data-required="false" data-desc="交易随机数。如果未设置，则默认为 `Date.now()`。"></x-field>
    <x-field data-name="chainId" data-type="string" data-required="false" data-desc="链 ID。如果未提供，则从连接的节点获取。"></x-field>
  </x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="用于派生发送方地址和公钥的钱包对象。"></x-field>
  <x-field data-name="delegator" data-type="string" data-required="false" data-desc="委托权限的账户地址（如果适用）。"></x-field>
</x-field-group>

**返回**

<x-field data-name="Promise<object>" data-type="Promise<object>" data-desc="一个 Promise，它会解析为一个包含已编码交易的对象。">
  <x-field data-name="object" data-type="object" data-desc="人类可读的交易对象。"></x-field>
  <x-field data-name="buffer" data-type="Buffer" data-desc="序列化后的交易二进制缓冲区，可供签名。"></x-field>
</x-field>

**示例**

```javascript TransferV2Tx icon=logos:javascript
const { encodeTransferV2Tx } = client;
const senderWallet = fromRandom();
const receiverAddress = 'z1...';

const { object, buffer } = await encodeTransferV2Tx({
  tx: {
    itx: {
      to: receiverAddress,
      value: await client.fromTokenToUnit(10), // 转移 10 个原生代币
    },
  },
  wallet: senderWallet,
});

console.log('Encoded TX Object:', object);
console.log('Buffer to Sign:', buffer.toString('hex'));
```


## 签名交易

`sign[Type]Tx` 方法在编码步骤的基础上增加了数字签名。这些方法会对交易进行编码，然后使用提供的钱包对生成的二进制缓冲区进行签名。

您可以通过调用 `client.getTxSignMethods()` 获取所有可用的签名方法的完整列表。

### `sign[Type]Tx(payload)`

对交易进行编码和签名。

**参数**

<x-field-group>
  <x-field data-name="tx" data-type="object" data-required="true" data-desc="交易数据对象，与编码时相同。"></x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="用于签署交易的钱包。"></x-field>
  <x-field data-name="delegator" data-type="string" data-required="false" data-desc="委托人地址（如果适用）。"></x-field>
  <x-field data-name="encoding" data-type="string" data-required="false" data-desc="输出的可选编码（'base16'、'hex'、'base58'、'base64'）。如果省略，则返回交易对象。"></x-field>
</x-field-group>

**返回**

<x-field data-name="Promise<object|string>" data-type="Promise<object|string>" data-desc="一个 Promise，它会解析为已签名的交易对象，如果指定了 `encoding`，则解析为编码后的字符串。"></x-field>

**示例**

```javascript TransferV2Tx icon=logos:javascript
const { signTransferV2Tx } = client;
const senderWallet = fromRandom();
const receiverAddress = 'z1...';

const signedTx = await signTransferV2Tx({
  tx: {
    itx: {
      to: receiverAddress,
      value: await client.fromTokenToUnit(10),
    },
  },
  wallet: senderWallet,
});

console.log('Signed TX:', signedTx);
```


## 发送交易

`send[Type]Tx` 方法负责将交易广播到区块链。如果提供了未签名的交易和钱包，这些方法可以隐式执行签名步骤，也可以发送已经签名的交易。

可以通过 `client.getTxSendMethods()` 获取发送方法的完整列表。

### `send[Type]Tx(payload)`

对交易进行签名（如果需要）并将其发送到链上。

**参数**

<x-field-group>
  <x-field data-name="tx" data-type="object" data-required="true" data-desc="交易对象。可以已签名或未签名。"></x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="用于签署交易的钱包。即使交易已预先签名，仍然需要此钱包来识别发送方。"></x-field>
  <x-field data-name="signature" data-type="string" data-required="false" data-desc="交易的预计算签名。如果提供，钱包将不会再次用于签名。"></x-field>
  <x-field data-name="delegator" data-type="string" data-required="false" data-desc="委托人地址（如果适用）。"></x-field>
  <x-field data-name="commit" data-type="boolean" data-default="false" data-required="false" data-desc="是否等待交易被提交到区块后再解析。"></x-field>
</x-field-group>

**返回**

<x-field data-name="Promise<string>" data-type="Promise<string>" data-desc="一个 Promise，它会解析为交易哈希。"></x-field>

**示例：自动签名**

```javascript TransferV2Tx icon=logos:javascript
const { sendTransferV2Tx } = client;
const senderWallet = fromRandom();
const receiverAddress = 'z1...';

// 客户端在发送前会使用 senderWallet 对此交易进行签名。
const txHash = await sendTransferV2Tx({
  tx: {
    itx: {
      to: receiverAddress,
      value: await client.fromTokenToUnit(10),
    },
  },
  wallet: senderWallet,
});

console.log('Transaction sent with hash:', txHash);
```

**示例：发送预签名交易**

```javascript TransferV2Tx icon=logos:javascript
// 假设 signedTx 来自 sign[Type]Tx 示例
const { sendTransferV2Tx } = client;

const txHash = await sendTransferV2Tx({
  tx: signedTx, // 传递整个已签名的交易对象
  wallet: senderWallet,
});

console.log('Pre-signed transaction sent with hash:', txHash);
```


## 多重签名交易

对于需要多个签名的工作流（如原子交换），使用 `multiSign[Type]Tx` 方法。该过程涉及一方首先对交易进行签名（使用标准的 `sign[Type]Tx` 方法），然后后续各方使用相应的 `multiSign[Type]Tx` 方法添加他们的签名。

您可以通过 `client.getTxMultiSignMethods()` 获取支持多重签名的交易列表。

### `multiSign[Type]Tx(payload)`

向一个已有一个或多个签名的交易添加签名。

**参数**

<x-field-group>
  <x-field data-name="tx" data-type="object" data-required="true" data-desc="交易对象，应已包含至少一个签名。"></x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="当前签名者的钱包。"></x-field>
  <x-field data-name="delegator" data-type="string" data-required="false" data-desc="当前签名者的委托人地址（如果适用）。"></x-field>
  <x-field data-name="data" data-type="any" data-required="false" data-desc="签名中包含的可选数据。"></x-field>
  <x-field data-name="encoding" data-type="string" data-required="false" data-desc="输出的可选编码（'base16'、'hex'、'base58'、'base64'）。"></x-field>
</x-field-group>

**返回**

<x-field data-name="Promise<object|string>" data-type="Promise<object|string>" data-desc="一个 Promise，它会解析为添加了新签名的交易对象。"></x-field>

**示例：原子交换 (`ExchangeV2Tx`)**

```javascript ExchangeV2Tx icon=logos:javascript
// 双方的钱包
const aliceWallet = fromRandom();
const bobWallet = fromRandom();

// 1. Alice 准备并签署初始交换交易
const exchangeTx = {
  itx: {
    to: bobWallet.address,
    sender: {
      value: await client.fromTokenToUnit(10), // Alice 提供 10 个代币
    },
    receiver: {
      value: await client.fromTokenToUnit(5), // Alice 要求 5 个代币
    },
  },
};

const signedByAlice = await client.signExchangeV2Tx({
  tx: exchangeTx,
  wallet: aliceWallet,
});

// 2. Alice 将 `signedByAlice` 发送给 Bob。Bob 添加他的签名。
const signedByBoth = await client.multiSignExchangeV2Tx({
  tx: signedByAlice,
  wallet: bobWallet,
});

// 3. Bob 将 `signedByBoth` 发回给 Alice。Alice 发送最终交易。
const txHash = await client.sendExchangeV2Tx({
  tx: signedByBoth,
  wallet: aliceWallet, // 使用发送方钱包进行提交
});

console.log('Atomic swap transaction sent:', txHash);
```
