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

# Apex 小费

> 每笔 Apex 交易都包含一条向已公布小费账户转账的 SystemProgram 指令。 了解小费规则、0.001 SOL 的标准下限，以及小费的用途。

## 小费规则

您通过 Apex 发送的每笔交易都必须包含**恰好一笔**满足以下所有条件的小费：

<Steps>
  <Step title="一条 SystemProgram 转账">
    小费是一条普通的 `SystemProgram::Transfer` 指令，转给已公布的 Apex 小费账户之一。
  </Step>

  <Step title="位于顶层">
    该转账是交易的顶层指令。在您的程序内部通过 CPI 进行的转账不算数。
  </Step>

  <Step title="由签名者出资">
    支付小费的账户需要对交易签名。它不必是费用支付者。
  </Step>

  <Step title="小费账户位于静态密钥中">
    小费账户出现在交易的静态账户密钥中。不要通过地址查找表加载它。
  </Step>

  <Step title="不低于您所在等级的下限">
    标准等级的下限为 **0.001 SOL（1,000,000 lamports）**。您的密钥所属等级可能设有不同的下限。
  </Step>
</Steps>

没有小费、有多笔小费或小费低于下限的交易，会在发送到任何地方之前被拒绝。拒绝信息会告诉您违反了哪条规则，低于下限的消息还会注明您的下限。参见[错误与速率限制](/cn/apex/errors-and-rate-limits)。

## 只有上链才付费

小费位于您的交易内部。如果交易没有上链，转账就不会执行，您无需支付任何费用。被拒绝、已过期或被丢弃的交易不会花费您任何小费。

## 获取小费账户

在任意 Apex 端点上调用 JSON-RPC `getTipAccounts`。无需 API 密钥。

<CodeGroup>
  ```bash cURL theme={null}
  curl -s http://fra.apex.orbitflare.com \
    -H "Content-Type: application/json" \
    -d '{"jsonrpc":"2.0","id":1,"method":"getTipAccounts","params":[]}'
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch("http://fra.apex.orbitflare.com", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "getTipAccounts", params: [] }),
  });
  const { result: tipAccounts } = await res.json();
  const tipAccount = tipAccounts[Math.floor(Math.random() * tipAccounts.length)];
  console.log(tipAccount);
  ```

  ```python Python theme={null}
  import random
  import requests

  res = requests.post(
      "http://fra.apex.orbitflare.com",
      json={"jsonrpc": "2.0", "id": 1, "method": "getTipAccounts", "params": []},
      timeout=5,
  )
  tip_accounts = res.json()["result"]
  tip_account = random.choice(tip_accounts)
  print(tip_account)
  ```

  ```rust Rust theme={null}
  use apex_sender_client::rpc::RpcClient;
  use apex_sender_client::{tip, Region};

  #[tokio::main]
  async fn main() -> Result<(), Box<dyn std::error::Error>> {
      let api_key = std::env::var("APEX_API_KEY")?;
      let tip_accounts = RpcClient::new(Region::Frankfurt, &api_key)
          .get_tip_accounts()
          .await?;
      let tip_account = tip::pick_tip_account(&tip_accounts).ok_or("no tip accounts")?;
      println!("{tip_account}");
      Ok(())
  }
  ```
</CodeGroup>

响应是一个 base58 地址数组：

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": ["APeX2oLtjYehgTMUCA971L8htM7tGNqsXHDz5NrivhhX", "APeXAKT6spXSmU3uRv2MoEgQ7ckhAS4nexTgaxwLEfJ9", "..."]
}
```

请在启动时获取该列表并缓存。**每笔交易随机**选择一个账户。将小费分散到多个账户，可以避免您的交易争抢同一账户的写锁。

### 已发布的账户

主网小费账户，全部是小费程序 `9ig7pd4gqe2m16ACGPbPo4HfMGD3ba38poDhXEayx7EF` 的金库。`getTipAccounts` 是权威列表：端点只接受其中的账户，任何变更也会先出现在那里。每个地址都以 `APeX` 开头，被替换的账户一眼就能看出来。

```
APeX2oLtjYehgTMUCA971L8htM7tGNqsXHDz5NrivhhX
APeXAKT6spXSmU3uRv2MoEgQ7ckhAS4nexTgaxwLEfJ9
APeXB4mu1X7BSjwyPtiNUnKyhvc4wrq5SKEdmnPKWR95
APeXJTSGoxLWmwb9o1tiiEL5RXVUakazYgjLmZdDc2Ef
APeXUUaKFfPXjPxKHEdwCsJ4BfTuGg4qnVQyJE9K37PU
APeXVWXKDRAAujckMjmMsV61a4DQiXa98MPUAkL46sim
APeXW6PKFZRDz7WXBBybBMcoJaQo97UtLa5TAQnchNBY
APeXZuKaKuqouyfU8fFL1woeWvSEVFkY4EMrmkvbfhhD
APeXbYdbmrYWsastf6GurexGe3dwnuWKLD2mcsDoEuBU
APeXn29deoxpsZz6r7n63Ymmv2skBr3WhKYLB1mB2fR7
```

## 添加小费指令

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { PublicKey, SystemProgram } from "@solana/web3.js";

  const tipInstruction = SystemProgram.transfer({
    fromPubkey: payer.publicKey,
    toPubkey: new PublicKey(tipAccount),
    lamports: 1_000_000, // 0.001 SOL, the standard tier floor
  });
  ```

  ```python Python theme={null}
  from solders.pubkey import Pubkey
  from solders.system_program import TransferParams, transfer

  tip_instruction = transfer(TransferParams(
      from_pubkey=payer.pubkey(),
      to_pubkey=Pubkey.from_string(tip_account),
      lamports=1_000_000,  # 0.001 SOL, the standard tier floor
  ))
  ```

  ```rust Rust theme={null}
  use apex_sender_client::{tip_instruction, MIN_TIP_LAMPORTS};

  let tip_ix = tip_instruction(&payer.pubkey(), &tip_account, MIN_TIP_LAMPORTS);
  ```
</CodeGroup>

将它与您自己的指令一起添加到交易的指令列表中。[快速入门](/cn/apex/quickstart)展示了完整的程序。

## 小费的去向

小费账户是 OrbitFlare 链上小费程序的金库。只有该程序可以从中扣款。

当最终让您的交易上链的是 **Jito 路径**时，小费减去 5,000 lamports 基础费用后的金额，会在与您的交易相同的捆绑包中作为出价支付给 Jito。您无需另外添加 Jito 小费。一笔 Apex 小费覆盖全部三条路径。

| 您的小费               | 基础费用           | Jito 路径胜出时的 Jito 出价 |
| ------------------ | -------------- | ------------------- |
| 1,000,000 lamports | 5,000 lamports | 995,000 lamports    |
| 5,000,000 lamports | 5,000 lamports | 4,995,000 lamports  |

因此，小费越高，在 Jito 拍卖中的出价就越高。无论哪条路径让交易上链，您花费的金额都相同，因为小费就是您签名的那笔转账。

## 小费与优先费是两回事

Apex 负责把您的交易送达领导者。领导者的调度器仍然按**优先费**对交易排序，优先费等于您的计算单元价格乘以计算单元上限。请在每笔交易上同时设置这两项：

* **计算单元上限**应接近交易的实际用量。过大的上限会降低您每单元的有效优先级，并浪费区块空间。
* **计算单元价格**应符合您所涉及账户的当前市场行情。

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { ComputeBudgetProgram } from "@solana/web3.js";

  const computeBudget = [
    ComputeBudgetProgram.setComputeUnitLimit({ units: 100_000 }),
    ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 10_000 }),
  ];
  ```

  ```python Python theme={null}
  from solders.compute_budget import set_compute_unit_limit, set_compute_unit_price

  compute_budget = [
      set_compute_unit_limit(100_000),
      set_compute_unit_price(10_000),  # micro-lamports per compute unit
  ]
  ```

  ```rust Rust theme={null}
  use solana_compute_budget_interface::ComputeBudgetInstruction;

  let compute_budget = [
      ComputeBudgetInstruction::set_compute_unit_limit(100_000),
      ComputeBudgetInstruction::set_compute_unit_price(10_000), // micro-lamports per compute unit
  ];
  ```
</CodeGroup>

这些指令适用于 legacy 和 v0 交易。[交易 v1](/cn/apex/transaction-v1) 改为在消息的 `TransactionConfig` 中设置计算预算。

关于如何确定这两项的大小，参见[最佳实践](/cn/apex/best-practices#根据交易价值确定小费)。
