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

# 报价

> 了解定价、报价和汇率

## 什么是报价？

**报价**是货币之间转换的价格报价。它锁定 30 秒的汇率，允许用户在提交交易之前准确看到他们将收到多少。

<Info>
  创建任何 ramp 之前都需要报价。它们确保价格透明度并防止汇率波动。
</Info>

## 报价如何工作

<Steps>
  <Step title="请求报价">
    指定货币、金额和支付方式
  </Step>

  <Step title="接收汇率">
    获取锁定 30 秒的有效汇率
  </Step>

  <Step title="显示给用户">
    显示用户将发送/接收的确切金额
  </Step>

  <Step title="创建 Ramp">
    使用报价 ID 以报价汇率执行交易
  </Step>
</Steps>

```mermaid theme={null}
sequenceDiagram
    participant User
    participant App
    participant KillB
    
    User->>App: 输入金额 (100,000 COP)
    App->>KillB: POST /quotations
    KillB-->>App: 报价 (23.81 USDC, 汇率 4,200)
    App-->>User: 显示："您将收到 23.81 USDC"
    User->>App: 确认
    App->>KillB: POST /ramps (使用报价 ID)
    KillB-->>App: Ramp 已创建
```

## 创建报价

```bash theme={null}
POST /api/v2/quotations
```

**请求：**

```json theme={null}
{
  "fromCurrency": "COP",
  "toCurrency": "USDC",
  "amount": 100000,
  "amountIsToCurrency": false,
  "cashInMethod": "PSE",
  "cashOutMethod": "POLYGON"
}
```

**响应：**

```json theme={null}
{
  "id": "quot-9f8e7d6c-5b4a-3c2d-1e0f",
  "fromCurrency": "COP",
  "toCurrency": "USDC",
  "fromAmount": 100000,
  "toAmount": 23.81,
  "rate": 4200.50,
  "spotPrice": 4180.25,
  "expiresAt": 1704657630000,
  "cashInMethod": "PSE",
  "cashOutMethod": "POLYGON"
}
```

<CodeGroup>
  ```javascript Node.js theme={null}
  const getQuote = async (fromAmount, fromCurrency = 'COP', toCurrency = 'USDC') => {
    const response = await fetch('https://sandbox.killb.app/api/v2/quotations', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        fromCurrency,
        toCurrency,
        amount: fromAmount,
        amountIsToCurrency: false,
        cashInMethod: 'PSE',
        cashOutMethod: 'POLYGON'
      })
    });
    
    const quote = await response.json();
    console.log(`Rate: ${quote.rate}, You receive: ${quote.toAmount} ${toCurrency}`);
    return quote;
  };
  ```

  ```python Python theme={null}
  def get_quote(from_amount, from_currency='COP', to_currency='USDC', access_token):
      response = requests.post(
          'https://sandbox.killb.app/api/v2/quotations',
          headers={
              'Authorization': f'Bearer {access_token}',
              'Content-Type': 'application/json'
          },
          json={
              'fromCurrency': from_currency,
              'toCurrency': to_currency,
              'amount': from_amount,
              'amountIsToCurrency': False,
              'cashInMethod': 'PSE',
              'cashOutMethod': 'POLYGON'
          }
      )
      quote = response.json()
      print(f"Rate: {quote['rate']}, You receive: {quote['toAmount']} {to_currency}")
      return quote
  ```

  ```php PHP theme={null}
  <?php
  function getQuote($fromAmount, $fromCurrency = 'COP', $toCurrency = 'USDC', $token) {
      $ch = curl_init('https://sandbox.killb.app/api/v2/quotations');
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($ch, CURLOPT_POST, true);
      curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
          'fromCurrency' => $fromCurrency,
          'toCurrency' => $toCurrency,
          'amount' => $fromAmount,
          'amountIsToCurrency' => false,
          'cashInMethod' => 'PSE',
          'cashOutMethod' => 'POLYGON'
      ]));
      curl_setopt($ch, CURLOPT_HTTPHEADER, [
          'Content-Type: application/json',
          'Authorization: Bearer ' . $token
      ]);
      
      $response = curl_exec($ch);
      return json_decode($response, true);
  }
  ?>
  ```
</CodeGroup>

## 报价参数

### 金额方向

`amountIsToCurrency` 标志确定哪个金额是固定的：

<Tabs>
  <Tab title="固定来源金额 (false)">
    用户指定**发送多少**

    ```json theme={null}
    {
      "fromCurrency": "COP",
      "toCurrency": "USDC",
      "amount": 100000,
      "amountIsToCurrency": false
    }
    ```

    **结果：** "发送 100,000 COP，接收 \~23.81 USDC"

    **何时使用：** 用户想要花费确切的法币金额
  </Tab>

  <Tab title="固定目的地金额 (true)">
    用户指定**接收多少**

    ```json theme={null}
    {
      "fromCurrency": "COP",
      "toCurrency": "USDC",
      "amount": 25,
      "amountIsToCurrency": true
    }
    ```

    **结果：** "发送 \~105,000 COP，接收正好 25 USDC"

    **何时使用：** 用户想要接收确切的加密货币金额
  </Tab>
</Tabs>

### 支付方式

指定现金入账和现金出账方式：

**现金入账方式**（来源）：

* `PSE` - 哥伦比亚银行支付
* `SPEI` - 墨西哥银行转账
* `TRANSFIYA` - 哥伦比亚移动钱包
* `ACH` - 美国 ACH 转账
* `WIRE` - 电汇
* `POLYGON`、`SOLANA` 等 - 加密货币网络
* `PRE_FUND` - 预充值法币
* `PRE_FUND_POLYGON` 等 - 预充值加密货币

**现金出账方式**（目的地）：

* 与现金入账相同，除了没有 PRE\_FUND 选项

## 汇率

### 汇率组成部分

```json theme={null}
{
  "rate": 4200.50,
  "spotPrice": 4180.25
}
```

**spotPrice**: 来自流动性提供商的市场汇率\
**rate**: 包括 KillB 费用和利润的最终汇率

**计算：**

```
toAmount = fromAmount / rate
Spread = rate - spotPrice
Fee % = (spread / spotPrice) * 100
```

### 汇率因素

汇率受以下因素影响：

1. **市场汇率** - 当前市场价格
2. **支付方式** - 不同方式有不同的成本
3. **交易量** - 更大的交易可能获得更好的汇率
4. **网络** - 区块链网络影响费用
5. **客户层级** - 您客户的协商定价

<Tip>
  预充值账户通常由于运营成本降低而获得更好的汇率。
</Tip>

## 报价过期

<Warning>
  **报价在 30 秒后过期**以防范市场波动。
</Warning>

### 处理过期

```javascript theme={null}
async function createRampWithRetry(quoteId, userId, accountId) {
  try {
    const ramp = await createRamp(quoteId, userId, accountId);
    return ramp;
  } catch (error) {
    if (error.message.includes('expired')) {
      // 获取新报价
      const newQuote = await getQuotation(/* params */);
      return await createRamp(newQuote.id, userId, accountId);
    }
    throw error;
  }
}
```

### 倒计时器

向用户显示剩余时间：

```javascript theme={null}
function QuoteTimer({ expiresAt, onExpire }) {
  const [timeLeft, setTimeLeft] = useState(30);
  
  useEffect(() => {
    const interval = setInterval(() => {
      const remaining = Math.max(0, Math.floor((expiresAt - Date.now()) / 1000));
      setTimeLeft(remaining);
      
      if (remaining === 0) {
        onExpire();
      }
    }, 1000);
    
    return () => clearInterval(interval);
  }, [expiresAt]);
  
  return <div>报价在 {timeLeft} 秒后过期</div>;
}
```

## 模拟模式

在不创建 ramps 的情况下测试报价：

```bash theme={null}
POST /api/v2/quotations/simulation
```

**与常规报价相同的参数，但：**

* 不返回报价 ID
* 汇率仅供参考
* 不能用于创建 ramp
* 不过期

**用于：**

* 显示估计汇率
* 计算器功能
* 市场汇率显示
* 用户教育

```javascript theme={null}
// 获取模拟报价用于显示
const simulatedQuote = await fetch('/api/v2/quotations/simulation', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    fromCurrency: 'COP',
    toCurrency: 'USDC',
    amount: userAmount,
    amountIsToCurrency: false,
    cashInMethod: 'PSE',
    cashOutMethod: 'POLYGON'
  })
}).then(r => r.json());

// 向用户显示汇率
console.log(`Estimated rate: ${simulatedQuote.rate}`);
console.log(`You would receive: ${simulatedQuote.toAmount} USDC`);

// 当用户确认时，获取真实报价
const realQuote = await getQuotation(/* same params */);
```

## 报价更新

报价无法更新。如果您需要不同的金额或汇率，请创建新报价。

```javascript theme={null}
// 不要这样做 - 报价无法更新
// await updateQuotation(quoteId, newAmount); ❌

// 这样做 - 创建新报价
const newQuote = await getQuotation(newAmount); // ✅
```

## 按 ID 获取报价

创建后检索报价：

```bash theme={null}
GET /api/v2/quotations/{quotationId}
```

**用例：**

* 在 ramp 之前验证报价详情
* 检查报价是否仍然有效
* 审计/日志目的

## 汇率显示最佳实践

<AccordionGroup>
  <Accordion title="显示所有金额" icon="calculator">
    ```javascript theme={null}
    显示：
    - 来源金额："100,000 COP"
    - 目的地金额："23.81 USDC"  
    - 汇率："1 USDC = 4,200.50 COP"
    - 费用信息："包括 0.5% 费用"
    ```
  </Accordion>

  <Accordion title="倒计时器" icon="clock">
    ```javascript theme={null}
    "此汇率在 28 秒后过期"

    - 显示视觉倒计时
    - 在剩余 10 秒时警告
    - 过期时自动刷新
    ```
  </Accordion>

  <Accordion title="汇率更新" icon="arrows-rotate">
    ```javascript theme={null}
    // 定期自动刷新报价
    setInterval(async () => {
      const newQuote = await getQuotation(amount);
      updateDisplay(newQuote);
    }, 5000); // 每 5 秒
    ```
  </Accordion>

  <Accordion title="市场背景" icon="chart-line">
    ```javascript theme={null}
    显示：
    - "汇率：1 USDC = 4,200.50 COP"
    - "市场汇率：4,180.25 COP"
    - "点差：0.48%"
    - "最后更新：2 秒前"
    ```
  </Accordion>
</AccordionGroup>

## 错误处理

常见报价错误：

| 错误                       | 原因      | 解决方案          |
| ------------------------ | ------- | ------------- |
| `PAIR_NOT_SUPPORTED`     | 货币对不可用  | 检查支持的货币对      |
| `AMOUNT_TOO_SMALL`       | 低于最小值   | 增加金额          |
| `AMOUNT_TOO_LARGE`       | 超过用户限额  | 减少金额或升级 KYC   |
| `METHOD_NOT_AVAILABLE`   | 支付方式不可用 | 选择不同的方式       |
| `INSUFFICIENT_LIQUIDITY` | 流动性不足   | 尝试更小的金额或不同的方式 |

## 汇率比较

跨网络比较汇率：

```javascript theme={null}
const compareRates = async (amount) => {
  const networks = ['POLYGON', 'SOLANA', 'TRON', 'ERC20'];
  const quotes = await Promise.all(
    networks.map(network => 
      getQuotation(amount, 'COP', 'USDC', 'PSE', network)
    )
  );
  
  // 找到最佳汇率
  const best = quotes.reduce((prev, curr) => 
    curr.toAmount > prev.toAmount ? curr : prev
  );
  
  console.log(`Best rate: ${best.rate} on ${best.cashOutMethod}`);
  return best;
};
```

## 下一步

<CardGroup cols={2}>
  <Card title="创建报价" icon="calculator" href="/api-reference/endpoint/quotations-create">
    报价 API 参考
  </Card>

  <Card title="构建 Ramps" icon="arrow-right-arrow-left" href="/zh/concepts/ramps">
    了解如何在 ramps 中使用报价
  </Card>

  <Card title="定价指南" icon="tag" href="/zh/resources/best-practices">
    显示汇率的最佳实践
  </Card>

  <Card title="支持的货币对" icon="link" href="/zh/supported-networks">
    查看所有可用的货币对
  </Card>
</CardGroup>
