# 交易生命周期

每一个修改区块链状态的操作，例如转移通证或创建资产，都是通过交易来执行的。理解交易的生命周期是使用 OCAP 客户端构建应用程序的基础。此过程涉及四个主要阶段：准备、编码、签名和发送。

OCAP 客户端提供了一套灵活的方法，允许您单独执行这些步骤以实现最大程度的控制，或者使用高级辅助函数将它们组合起来以方便使用。

本指南将分解每个阶段，并说明单签名和多签名工作流。


## 生命周期概览

下图展示了一笔交易从准备到最终提交至区块链的完整过程。

<!-- DIAGRAM_IMAGE_START:flowchart:4:3 -->

![Transaction Lifecycle](assets/diagram/core-concepts-transaction-lifecycle-01.jpg)

<!-- DIAGRAM_IMAGE_END -->


## 阶段 1：准备（创建 `itx`）

每笔交易都始于一个 `itx`（内部交易）。这是一个纯 JavaScript 对象，包含了您想要执行的操作的具体数据。例如，一个转账 `itx` 会包含接收者的地址和金额。

```javascript 准备 itx icon=logos:javascript
// 我们转账交易的核心数据
const itx = {
  to: 'z2C8j81aL2oXpA5t42s2h4g9o8p1k6m3n7b', // 接收者地址
  value: await client.fromTokenToUnit(10),   // 发送的金额，已转换为链的最小单位
};
```


## 阶段 2：编码

编码将 `itx` 和其他元数据转换为可进行加密签名的标准化二进制格式。客户端为每种交易类型都提供了一个 `encode{TxType}Tx` 方法（例如 `encodeTransferV2Tx`）。

在此阶段，客户端会自动添加必要的元数据：

* **`from`**：发送者地址，从提供的钱包派生。
* **`chainId`**：目标区块链的标识符，自动获取。
* **`nonce`**：用于防止重放攻击的唯一数字，默认为当前时间戳 (`Date.now()`)。
* **`pk`**：发送者钱包的公钥。

编码函数返回完整的交易对象和用于签名的序列化数据 `Buffer`。

```javascript 编码交易 icon=logos:javascript
const { object: encodedTx, buffer: txBuffer } = await client.encodeTransferV2Tx({
  tx: { itx },
  wallet: senderWallet,
});

console.log('Encoded TX Object:', encodedTx);
console.log('Buffer to be signed:', txBuffer);
```


## 阶段 3：签名

签名证明了账户的所有权并授权了该交易。单签名和多签名工作流的流程有所不同。

### 单签名工作流

这是最常见的情景，即单个用户对一笔交易进行签名。`sign{TxType}Tx` 方法接收编码后的交易，使用用户的私钥对二进制缓冲区进行签名，并填充 `signature` 字段。

```javascript 使用单签名进行签名 icon=logos:javascript
const signedTx = await client.signTransferV2Tx({
  tx: encodedTx, // 来自编码步骤的对象
  wallet: senderWallet,
});

console.log('Signature:', signedTx.signature);
```

### 多签名工作流

多重签名（multisig）交易需要多方批准。这通常用于原子交换或共享账户。该过程是顺序的：

1. **准备**：创建初始交易时，需包含一个 `signaturesList`，其中定义了所有必需的签名者。
2. **顺序签名**：交易从一个签名者传递到下一个。每个签名者使用相应的 `multiSign{TxType}Tx` 方法来添加他们的签名。

在内部，`multiSign` 方法通过在编码交易进行签名之前临时剥离所有现有签名，来确保各方签署完全相同的交易摘要。

以下是一个 `ExchangeTx` 的示例，其中两方交换资产。

```javascript 多重签名示例 icon=logos:javascript
// 步骤 1：Alice（报价方）准备并签署交换交易。
const txFromAlice = await client.prepareExchange({
  offerToken: 10,
  demandToken: 20,
  receiver: bobWallet.address,
  wallet: aliceWallet,
});

// 步骤 2：将交易发送给 Bob。
// Bob（需求方）添加他的签名以最终确定交易。
const txFromBob = await client.finalizeExchange({
  tx: txFromAlice, // 由 Alice 签名的交易
  wallet: bobWallet,
});

console.log('Alice\'s Signature:', txFromBob.signaturesList[0].signature);
console.log('Bob\'s Signature:', txFromBob.signaturesList[1].signature);
```


## 阶段 4：发送

一旦交易被完全签名，就可以将其发送到区块链节点进行处理。`send{TxType}Tx` 方法处理这最后一步。

为方便起见，如果您提供一个钱包和一个未签名的交易，这些方法也可以隐式执行签名步骤。该方法返回一个 promise，在成功提交后，该 promise 会解析为交易哈希。

```javascript 发送已签名的交易 icon=logos:javascript
// 使用预先签名的交易
const hash = await client.sendTransferV2Tx({ tx: signedTx, wallet: senderWallet });

// 或者，让发送方法自动处理签名
const hash2 = await client.sendTransferV2Tx({
  tx: { itx }, // 仅内部交易
  wallet: senderWallet,
});

console.log('Transaction sent! Hash:', hash);
```

您还可以包含一个 `commit: true` 选项，使客户端在解析 promise 之前，等待交易被完全确认并包含在区块中。


## 总结

交易生命周期为与区块链交互提供了一个强大而灵活的框架。通过将过程分解为不同的阶段——准备、编码、签名和发送——OCAP 客户端为开发人员提供了对交易创建的精细控制，同时也为常见用例提供了简单的高级辅助函数。

有关交易费用处理的更多详细信息，请参阅[燃料费支付](./core-concepts-gas-payment.md)指南。要了解可用的不同客户端类型，请参阅[客户端架构](./core-concepts-client-architecture.md)文档。
