> ## 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.

# 在预确认上进行交易

> 在Solana交易到达前做出反应：订阅preconfSubscribe过滤器，解码二进制载荷，使用Sender Max进行操作。

[预确认](/docs/zh/pre-confirmations/overview)会在验证器的调度器承诺执行交易时流传这些交易，在它们被分片之前。本指南会构建一个监听器，以监视目标账户，解码每个计划的交易，并使用[Sender Max](/docs/zh/sending-transactions/sender-max)做出反应。

<Tip>
  预确认需要[专业计划或更高级别](/docs/zh/billing/plans)，每条消息消耗10个积分。
</Tip>

## 在连接之前范围化流

未过滤的`preconfSubscribe`每个计划的交易都会递送10个积分，因此需在服务器端进行过滤，只为您交易的部分付费。

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "preconfSubscribe",
  "params": [
    {
      "failed": false,
      "regionInclude": ["ewr"],
      "accountInclude": ["TARGET_WALLET_OR_PROGRAM"]
    }
  ]
}
```

三种过滤器覆盖了大多数交易监听器：

* `failed: false`会丢弃已知已回滚的交易，您没有理由去跟进。
* `regionInclude`将流锁定到离您基础设施最近的[地区](/docs/zh/pre-confirmations/preconf-subscribe#位置过滤)，以防跨地区跳转消耗领先优势。
* `accountInclude`匹配任何引用您目标的交易：钱包、AMM池、程序等。Helius会在服务器端解决地址查找表，因此即使账户通过ALT加载，过滤器仍能匹配。

## 连接、订阅和解码

`preconfSubscribe`从Gatekeeper端点提供(`wss://beta.helius-rpc.com`)，通知以二进制帧形式而非JSON到达。

每个帧是一个固定的18字节前缀，后随bincode序列化的交易：

```javascript listener.js theme={"system"}
const WebSocket = require('ws');
const { VersionedTransaction } = require('@solana/web3.js');

const ws = new WebSocket('wss://beta.helius-rpc.com/?api-key=YOUR_API_KEY');

ws.on('open', () => {
  ws.send(JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method: 'preconfSubscribe',
    params: [{
      failed: false,
      regionInclude: ['ewr'],
      accountInclude: ['TARGET_WALLET_OR_PROGRAM']
    }]
  }));
  setInterval(() => ws.ping(), 30_000); // keep the connection alive
});

ws.on('message', (data, isBinary) => {
  if (!isBinary) {
    const msg = JSON.parse(data.toString());
    if (msg.id === 1) console.log('Subscribed, ID:', msg.result);
    return;
  }

  // version (u8) | slot (u64 LE) | tx_index (u64 LE) | status (u8) | bincode(VersionedTransaction)
  const buf = Buffer.from(data);
  if (buf.readUInt8(0) !== 1) return; // unknown schema version; update your decoder
  const slot = buf.readBigUInt64LE(1);
  const status = buf.readUInt8(17); // 0 = failed, 1 = success, 2 = unknown
  const tx = VersionedTransaction.deserialize(buf.subarray(18));

  onScheduledTransaction({ slot, status, tx });
});

ws.on('error', console.error);
ws.on('close', () => process.exit(1)); // let your supervisor restart and resubscribe
```

首先检查版本字节。如果Helius更新了载荷格式，版本就会递增，依版本分支可保持解码器工作。反序列化的交易会提供指令、账户和签名。

## 使用Sender Max进行操作

只有当您的响应首先到达时，预确认才会带来收益。

通过[Sender Max](/docs/zh/sending-transactions/sender-max)发送您的响应：0.001 SOL的小费进入优先小费缓冲区，并通过每条高速路径路由：

```javascript theme={"system"}
async function onScheduledTransaction({ slot, status, tx }) {
  if (!strategy.shouldReact(tx)) return;

  // strategy is your own code: it decides whether to react and returns a
  // signed, base64-encoded transaction that includes the tip and priority fee
  const reaction = await strategy.buildTransaction(tx);
  await fetch('http://ewr-sender.helius-rpc.com/fast', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      jsonrpc: '2.0',
      id: Date.now().toString(),
      method: 'sendTransaction',
      params: [reaction, { encoding: 'base64', skipPreflight: true, maxRetries: 0 }]
    })
  });
}
```

保持此处理程序简短。做出决定并发送，将日志、会计和对账移出接收路径。完整发送循环包括连接预热和费用估算，请参见[通过Sender确认交易](/docs/zh/sending-transactions/guides/land-trades-with-sender)。

## 确认着陆并期望有间隙

预确认是一种提前查看。交易还未落地，仍可能失败或被丢弃，因此须遵循两条规则：

* 在将观测到的交易或您的反应视为最终之前，通过标准承诺检查(`getSignatureStatuses`, 或`processed`-承诺流)进行确认。
* 期望有间隙。覆盖比例与转发给Helius的股份份额成比例，因此某些槽位不会产生消息。这是[预期行为](/docs/zh/pre-confirmations/overview#覆盖范围)，而不是连接中断，保活ping可以区分二者。关闭时重新订阅。

## 相关指南

<CardGroup cols={2}>
  <Card title="preconfSubscribe API参考" icon="code" href="/docs/zh/pre-confirmations/preconf-subscribe">
    完整的过滤语义、地区代码和二进制载荷布局
  </Card>

  <Card title="在预处理交易上进行交易" icon="bolt" href="/docs/zh/preprocessed-transactions/guides/trade-on-preprocessed">
    以每条消息0.1积分的预执行覆盖，适用于所有付费计划
  </Card>
</CardGroup>
