> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 预处理交易

> 通过 gRPC 传输的解码分片在 `processed` 确认级别之前约8毫秒。是 Helius Shred Delivery 产品系列的一部分。

<Note>
  **公开测试版。** 预处理交易是 Helius [Shred Delivery](/zh/shred-delivery) 产品系列的一部分。对于任何**专业版计划或更高级别**的用户均可使用，以**1 MB 20 个积分**的速度计费。

  通常情况下，预处理交易比 `processed` 确认级别提前 **\~8 毫秒** 到达，但代价是执行元数据（参见下面的 [权衡](#what-data-is-available)）。
</Note>

预处理交易是通过 gRPC 接收 Solana 交易的最快方式。Helius 直接在验证器接收到分片时对其进行解码，并将生成的交易发送给您，让您比任何执行后订阅在数毫秒之前获取交易数据——平均比 `processed` 确认级别提前约 **8 毫秒**。

本指南解释了何时使用预处理交易、可用的数据以及如何使用 LaserStream SDK 订阅它们（该 SDK 也通过相同的 gRPC 连接提供预处理交易）。

## 预处理交易在生命周期中的位置

在 Solana 的架构中，交易在完全处理之前需要经过几个阶段：

1. **碎片接收** → 验证者接收交易碎片（数据片段）。← Helius 的 **[原始碎片 (UDP)](/zh/shred-delivery/raw-shreds)** 在此处传送。
2. **碎片解码** → 碎片被解码为原始交易。← **预处理交易在此可用。**
3. **交易执行** → 交易由运行时执行。
4. **元数据生成** → 计算预/后余额、日志和错误信息。
5. **承诺** → 交易达到已处理/已确认/已最终确定状态。← **[LaserStream gRPC](/zh/laserstream)** 和 **[LaserStream WebSocket](/zh/rpc/websocket)** 在此传递。

执行后订阅在第5阶段传递数据——在完整执行和元数据生成之后。预处理订阅在第2阶段传递——解码shreds后立即执行，未完成时。

**权衡：** 你可以更早几毫秒获得交易数据，但没有执行元数据，如余额变化、日志或错误信息。

<Warning>
  \*\*这是一个仅限交易的数据流。\*\*账户和程序状态更新要等到运行时执行交易（第4阶段）才能存在。如果你需要实时账户或程序更新——例如代币余额、绑定曲线状态、程序账户，或任何不只是原始交易的内容——请使用 **[LaserStream gRPC](/zh/laserstream) 在 `processed` 承诺**中，这是接收账户/程序更改的最快方式。
</Warning>

<Tip>
  需要更快的交易信号？尝试[预确认](/zh/pre-confirmations/overview)以流式传输计划交易和[原始碎片（UDP）](/zh/shred-delivery/raw-shreds)以获取未处理的交易数据。
</Tip>

## 尽力交付保证

预处理交易交付是尽力而为的，不是保证的。我们目标是99.99%的交付率，但一些交易可能会在以下情况下丢失：

* 基础设施更新和重新部署
* 网络问题或验证者连接问题
* 解码或处理shred的边缘情况

对于需要保证交付的关键应用，使用标准 [交易订阅](/zh/laserstream/guides/decoding-transaction-data)。

## 可用数据是什么？

预处理交易包含完整的交易消息，但缺乏执行元数据：

### 可用数据

* ✅ **交易签名** - 唯一的交易标识符
* ✅ **账户密钥** - 交易引用的所有账户
* ✅ **指令** - 完整的指令数据和程序调用
* ✅ **最近的区块哈希** - 交易到期参考
* ✅ **签名** - 所有交易签名
* ✅ **是否为投票交易** - 是否这是投票交易
* ✅ **槽位号码** - 包含此交易的槽位

### 缺失数据

* ❌ **交易元数据** - 代币余额变化、前/后余额、交易状态
* ❌ **交易错误** - 我们无法判断交易是否失败
* ❌ **内部指令** - 不包括跨程序调用（CPIs）
* ❌ **日志信息** - 程序在执行过程中生成的日志
* ❌ **消耗的计算单元** - 执行指标不可用

将预处理交易视为收到“提案”而没有“结果”。你可以看到用户试图做什么，但看不到实际发生的情况。

## SDK支持和版本要求

所有LaserStream SDK都支持预处理交易订阅：

<CardGroup cols={3}>
  <Card title="JavaScript/TypeScript" icon="js" href="https://github.com/helius-labs/laserstream-sdk/tree/main/javascript">
    版本 **0.2.8** 或更高
  </Card>

  <Card title="Rust" icon="rust" href="https://github.com/helius-labs/laserstream-sdk/tree/main/rust">
    版本 **0.1.5** 或更高
  </Card>

  <Card title="Go" icon="golang" href="https://github.com/helius-labs/laserstream-sdk/tree/main/go">
    版本 **0.1.0** 或更高
  </Card>
</CardGroup>

***

## 实现示例

### JavaScript/TypeScript

JavaScript SDK 提供了一个专用的 `subscribePreprocessed` 函数，具备自动重连功能：

```typescript [expandable] theme={"system"}
import {
  subscribePreprocessed,
  CommitmentLevel,
  LaserstreamConfig,
  SubscribePreprocessedRequest,
  SubscribePreprocessedUpdate
} from 'helius-laserstream';
import bs58 from 'bs58';

async function streamPreprocessedTransactions() {
  const config: LaserstreamConfig = {
    apiKey: 'YOUR_API_KEY',
    endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com',
  };

  const request: SubscribePreprocessedRequest = {
    transactions: {
      "jupiter-swaps": {
        vote: false,
        accountInclude: ['JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4']
      }
    }
  };

  const stream = await subscribePreprocessed(
    config,
    request,
    async (update: SubscribePreprocessedUpdate) => {
      if (update.transaction) {
        const tx = update.transaction;
        const signature = bs58.encode(tx.transaction.signature);

        console.log('⚡ Preprocessed transaction received:');
        console.log(`  Signature: ${signature}`);
        console.log(`  Slot: ${tx.slot}`);
        console.log(`  Is Vote: ${tx.transaction.isVote}`);
        console.log(`  Filters: ${update.filters.join(', ')}`);
        console.log('---');
      }
    },
    async (error) => {
      console.error('Stream error:', error);
    }
  );

  console.log(`✅ Preprocessed stream started (id: ${stream.id})`);

  // Graceful shutdown
  process.on('SIGINT', () => {
    console.log('\n🛑 Shutting down stream...');
    stream.cancel();
    process.exit(0);
  });
}

streamPreprocessedTransactions().catch(console.error);
```

**完整示例：** [preprocessed-transaction-sub.ts](https://github.com/helius-labs/laserstream-sdk/blob/main/javascript/examples/preprocessed-transaction-sub.ts)

### Rust

Rust SDK 提供原生性能：

```rust [expandable] theme={"system"}
use futures::StreamExt;
use helius_laserstream::{
    grpc::{SubscribePreprocessedRequest, SubscribePreprocessedRequestFilterTransactions},
    subscribe_preprocessed, LaserstreamConfig,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = LaserstreamConfig {
        endpoint: "https://laserstream-mainnet-ewr.helius-rpc.com".to_string(),
        api_key: "YOUR_API_KEY".to_string(),
        ..Default::default()
    };

    let mut request = SubscribePreprocessedRequest::default();
    request.transactions.insert(
        "jupiter-swaps".to_string(),
        SubscribePreprocessedRequestFilterTransactions {
            vote: Some(false),
            account_include: vec![
                "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4".to_string()
            ],
            ..Default::default()
        },
    );

    let (stream, _handle) = subscribe_preprocessed(config, request);
    tokio::pin!(stream);

    println!("✅ Preprocessed stream started");

    while let Some(result) = stream.next().await {
        match result {
            Ok(update) => {
                if let Some(tx) = update.transaction {
                    println!("⚡ Preprocessed transaction:");
                    println!("  Slot: {}", tx.slot);
                    println!("  Is Vote: {}", tx.transaction.is_vote);
                    println!("---");
                }
            }
            Err(e) => {
                eprintln!("Stream error: {:?}", e);
                break;
            }
        }
    }

    Ok(())
}
```

**完整示例：** [preprocessed\_transaction\_sub.rs](https://github.com/helius-labs/laserstream-sdk/blob/main/rust/examples/preprocessed_transaction_sub.rs)

### Go

Go SDK 提供惯用的 Go 接口：

```go [expandable] theme={"system"}
package main

import (
    "log"
    "os"
    "os/signal"
    "syscall"

    laserstream "github.com/helius-labs/laserstream-sdk/go"
    pb "github.com/helius-labs/laserstream-sdk/go/proto"
)

func main() {
    log.SetFlags(0)

    clientConfig := laserstream.LaserstreamConfig{
        Endpoint: "https://laserstream-mainnet-ewr.helius-rpc.com",
        APIKey:   "YOUR_API_KEY",
    }

    voteFilter := false
    subscriptionRequest := &pb.SubscribePreprocessedRequest{
        Transactions: map[string]*pb.SubscribePreprocessedRequestFilterTransactions{
            "jupiter-swaps": {
                Vote: &voteFilter,
                AccountInclude: []string{
                    "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
                },
            },
        },
    }

    client := laserstream.NewPreprocessedClient(clientConfig)

    dataCallback := func(data *pb.SubscribePreprocessedUpdate) {
        if data.Transaction != nil {
            log.Println("⚡ Preprocessed transaction:")
            log.Printf("  Slot: %d\n", data.Transaction.Slot)
            log.Printf("  Is Vote: %t\n", data.Transaction.Transaction.IsVote)
            log.Println("---")
        }
    }

    errorCallback := func(err error) {
        log.Printf("Error: %v", err)
    }

    err := client.Subscribe(subscriptionRequest, dataCallback, errorCallback)
    if err != nil {
        log.Fatalf("Failed to subscribe: %v", err)
    }

    log.Println("✅ Preprocessed stream started")
    log.Println("Press Ctrl+C to exit")

    sigChan := make(chan os.Signal, 1)
    signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
    <-sigChan

    log.Println("\nShutting down...")
    client.Close()
}
```

**完整示例：** [preprocessed-transaction-sub.go](https://github.com/helius-labs/laserstream-sdk/blob/main/go/examples/preprocessed-transaction-sub.go)

***

## 订阅结构和过滤

### 请求结构

预处理订阅请求遵循与标准订阅类似的结构，但具有一组集中的过滤器：

```typescript theme={"system"}
interface SubscribePreprocessedRequest {
  transactions: {
    [filterName: string]: SubscribePreprocessedRequestFilterTransactions
  };
  ping?: SubscribeRequestPing;
}

interface SubscribePreprocessedRequestFilterTransactions {
  vote?: boolean;              // Include/exclude vote transactions
  signature?: string;          // Filter by specific transaction signature
  accountInclude?: string[];   // Include transactions touching these accounts
  accountExclude?: string[];   // Exclude transactions touching these accounts
  accountRequired?: string[];  // Require all these accounts to be present
}
```

### 响应结构

更新包含完整的交易消息和基本元数据：

```typescript theme={"system"}
interface SubscribePreprocessedUpdate {
  filters: string[];                             // Which filters matched
  transaction?: SubscribePreprocessedTransaction; // The transaction data
  ping?: SubscribeUpdatePing;                    // Keepalive ping
  pong?: SubscribeUpdatePong;                    // Ping response
  createdAt: Date;                               // When update was created
}

interface SubscribePreprocessedTransaction {
  transaction: SubscribePreprocessedTransactionInfo;
  slot: number;                                  // Slot containing transaction
}

interface SubscribePreprocessedTransactionInfo {
  signature: Uint8Array;                         // Transaction signature
  isVote: boolean;                               // Is this a vote transaction
  transaction: solana.storage.Transaction;       // Full transaction message
}
```

`transaction.transaction` 字段包含完整的 Solana 交易结构，包括：

* **消息** - 帐户密钥、指令、最近的区块哈希
* **签名** - 所有交易签名
* **地址表查找** - 用于版本化交易

这与标准订阅中的交易结构相同，但没有`meta`字段包含执行结果。
