# 一把 key 通用多鏈：將範例切換到另一條鏈

> Source: https://docs.blockvectra.com/zh-hant/guides/one-key-many-chains/

## 1. 一把 key 適用於所有支援的鏈

同一把 API key 適用於所有支援鏈的 JSON-RPC，以及已提供服務的鏈上的 Data API。key 屬於你的帳戶，不綁定特定鏈；不需要為每個網路分別產生 API key。

額度與速率限制在所有網路之間，以及 JSON-RPC API 與 Data API 之間共用，不按網路拆分。詳細計費規則請參閱[定價頁面](https://blockvectra.com/zh-hant/pricing/)。

* **餘額共用**：付費儲值與免費額度適用於所有鏈。在任何鏈上的呼叫都從同一個帳戶餘額扣款。
* **速率限制共用**：對特定 key 而言，計算單位（CU）的補充速率與突發容量適用於所有鏈。免費方案的每秒呼叫次數上限在所有支援鏈上合併計算，而非按鏈拆分。
* **升級路徑**：儲值後，你不再受免費方案的每秒呼叫次數上限約束；每把 key 仍受 CU 速率與突發限制約束，詳見 [JSON-RPC 文件](https://docs.blockvectra.com/zh-hant/api/json-rpc/#method-policy)。

## 2. URL 結構與 `{chain}` 參數

每個以鏈為範圍的請求都會在 URL 路徑中以 `{chain}` 指定目標網路。`{chain}` 是鏈的小寫識別代號（例如 `robinhood_mainnet`）。

| 服務       | 認證             | URL 範本                       | 說明                                   |
| -------- | -------------- | ---------------------------- | ------------------------------------ |
| JSON-RPC | key 放在 URL 路徑中 | `POST /v1/{chain}/{api_key}` | 最簡單的形式，適合 curl 與 HTTP 用戶端            |
| JSON-RPC | key 放在請求標頭中    | `POST /v1/{chain}`           | 透過 `x-api-key: {api_key}` 請求標頭傳入 key |
| Data API | REST 路由        | `GET /v1/data/{chain}/…`     | 透過 `x-api-key: {api_key}` 請求標頭傳入 key |
| 公開鏈清單    | 免認證            | `GET /v1/chains`             | 公開的鏈清單與靜態參數（不計費）                     |
| 公開狀態     | 免認證            | `GET /v1/status`             | 目前服務狀態與各鏈鏈頭（不計費）                     |

`GET /v1/chains` 會為每條鏈回報 `jsonrpc` 與 `data` 旗標。當鏈提供 JSON-RPC 時，請使用其 JSON-RPC URL；當鏈的 `data` 旗標為 `true` 時，請使用 `GET /v1/data/{chain}/…`（Data API 只服務這些鏈）。

> **提示**：透過請求標頭傳入 key 時，URL 結尾請以鏈名作結，且**不要**加上結尾斜線。JSON-RPC 僅在 `/v1/{chain}` 與 `/v1/{chain}/{api_key}` 提供。帶結尾斜線（例如 `/v1/{chain}/`）或缺少鏈段的請求會回傳 HTTP 404 且回應主體為空。對未知 `{chain}` 的請求會回傳 HTTP 404 與 `error.data.reason: "unknown_chain"`（不計費）。

## 3. 以程式化方式探索鏈與能力

支援的鏈及其能力是動態提供的。請不要在應用程式中硬編碼靜態鏈清單，而應在執行階段探索可用的網路及其能力：

### 透過 `GET /v1/chains` 探索靜態參數

這個公開端點免認證且不計費，會回傳所有公開的鏈：

```http
GET /v1/chains
```

回應範例：

```json
{
  "chains": [
    {
      "chain": "robinhood_mainnet", "name": "Robinhood Chain", "chain_id": 4663,
      "jsonrpc": true,
      "data": true,
      "methods": {
        "allow": ["eth_blockNumber", "eth_call", "eth_chainId", "debug_traceTransaction"],
        "deny": ["eth_newFilter", "eth_newBlockFilter", "eth_newPendingTransactionFilter", "eth_getFilterLogs", "eth_getFilterChanges", "eth_uninstallFilter", "eth_subscribe", "eth_unsubscribe"]
      },
      "max_logs_block_range": 1000,
      "state_window_blocks": 900
    }
  ]
}
```

欄位說明：

* `chain`：鏈識別代號（用於 URL 中的 `{chain}`）
* `name`：人類可讀的顯示名稱
* `chain_id`：EIP-155 鏈 ID（十進位整數）
* `jsonrpc`：是否啟用 JSON-RPC
* `data`：是否啟用 Data API
* `methods`：該鏈的 JSON-RPC 方法策略，包含 `allow`（允許的方法）與 `deny`（明確拒絕的方法）
* `max_logs_block_range`：單次 `eth_getLogs` 請求允許的最大區塊範圍
* `state_window_blocks`：歷史狀態視窗大小（以區塊為單位）；無限制時為 `null`

### 透過 `GET /v1/status` 檢查運作狀態

這個公開端點免認證且不計費，會回傳服務就緒狀態與各鏈鏈頭資訊：

```http
GET /v1/status
```

回應範例：

```json
{
  "checked_at": "2026-09-28T12:00:00Z",
  "gateway": {
    "status": "ok"
  },
  "chains": [
    {
      "chain": "robinhood_mainnet", "name": "Robinhood Chain", "chain_id": 4663,
      "jsonrpc": true,
      "data": true,
      "data_features": ["blocks", "transactions", "address_transactions", "transfers", "token_metadata", "freshness"],
      "status": "ok",
      "head": {
        "block": 73017329,
        "time": "2026-09-28T11:59:58Z",
        "lag_seconds": 2
      }
    }
  ]
}
```

欄位說明：

* `gateway.status`：服務狀態（`ok` 或 `degraded`）
* `chains[].data_features`：Data API 為此鏈提供的能力
* `chains[].status`：節點運作狀態（`ok` 或 `unavailable`）
* `chains[].head`：最新區塊頭（`block`、`time`、`lag_seconds`）

## 4. 切換鏈時需要留意的各鏈差異

在鏈之間切換時，請檢視 `GET /v1/chains` 提供的欄位：

1. **方法允許與策略（`methods.allow` / `methods.deny`）**：可用的 JSON-RPC 方法會依各網路的方法策略而不同。請求不允許的方法會回傳 HTTP 200 與 JSON-RPC 錯誤碼 `-32601`（`method not available`，不計費）。
2. **日誌區塊範圍（`max_logs_block_range`）**：`eth_getLogs` 查詢的最大區塊跨度因鏈而異。超過該鏈的限制會回傳 HTTP 200 與 JSON-RPC 錯誤碼 `-32602`（`eth_getLogs block range too large`，不計費）。
3. **狀態保留視窗（`state_window_blocks`）**：完整歷史的鏈會回傳 `null`。在具有狀態修剪的鏈上，查詢視窗之外的歷史狀態會回傳 HTTP 200 與 JSON-RPC 錯誤碼 `-32011`（`historical state is not available beyond the most recent <N> blocks`，不計費）。
4. **Data API 功能與涵蓋範圍（`data` / `data_features`）**：提供資料集的鏈列於[支援的鏈](https://docs.blockvectra.com/zh-hant/chains/)頁面。查詢鏈不支援的資料集，或早於其已索引涵蓋範圍的區塊，會回傳 HTTP `422`（`error.code` 為 `no_coverage`，不計費）。當服務暫時無法使用時（例如某條鏈忙碌中），請求會回傳 HTTP `503` 並附帶 `Retry-After` 標頭（不計費）。

## 5. 程式碼範例

完整入門範本：[blockvectra/multichain-viem](https://github.com/blockvectra/multichain-viem)

只要更新鏈變數（或從 `GET /v1/chains` 讀取），同一段程式碼就能在不同鏈上執行，透過 JSON-RPC 查詢 `eth_blockNumber`，並透過 Data API 查詢資料集新鮮度：

**cURL**

```bash
export BLOCKVECTRA_API_KEY="rgw_your_api_key"

# 修改鏈變數即可改用「支援的鏈」中的另一條鏈
CHAIN="robinhood_mainnet"

# 1. JSON-RPC：查詢 eth_blockNumber（POST /v1/{chain}，key 放在 x-api-key 標頭）。
RPC_URL="https://api.blockvectra.com/v1/$CHAIN"
curl -s "$RPC_URL" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'

# 2. Data API：查詢資料集新鮮度（GET /v1/data/{chain}/status/freshness）
curl -s "https://api.blockvectra.com/v1/data/$CHAIN/status/freshness" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"
```


  **TypeScript**

```ts
// 修改此變數即可改用另一條鏈，或從 GET /v1/chains 動態讀取
const chain = "robinhood_mainnet";
const apiKey = process.env.BLOCKVECTRA_API_KEY!;

// 1. JSON-RPC：呼叫 eth_blockNumber（POST /v1/{chain}）
const rpcUrl = `https://api.blockvectra.com/v1/${chain}`;
const rpcResponse = await fetch(rpcUrl, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": apiKey,
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "eth_blockNumber",
    params: [],
  }),
});
const rpcResult = await rpcResponse.json();
console.log(`[${chain}] JSON-RPC blockNumber:`, rpcResult.result);

// 2. Data API：查詢新鮮度（GET /v1/data/{chain}/status/freshness）
const dataUrl = `https://api.blockvectra.com/v1/data/${chain}/status/freshness`;
const dataResponse = await fetch(dataUrl, {
  headers: {
    "x-api-key": apiKey,
  },
});
const dataResult = await dataResponse.json();
console.log(`[${chain}] Data API freshness:`, dataResult.data);
```


  **Python**

```python
import os
import requests

# 修改此變數即可改用另一條鏈，或從 GET /v1/chains 動態讀取
chain = "robinhood_mainnet"
api_key = os.environ["BLOCKVECTRA_API_KEY"]

# 1. JSON-RPC：呼叫 eth_blockNumber（POST /v1/{chain}）
rpc_url = f"https://api.blockvectra.com/v1/{chain}"
headers = {
    "Content-Type": "application/json",
    "x-api-key": api_key,
}
rpc_payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_blockNumber",
    "params": [],
}
rpc_resp = requests.post(rpc_url, json=rpc_payload, headers=headers)
print(f"[{chain}] JSON-RPC blockNumber:", rpc_resp.json().get("result"))

# 2. Data API：查詢新鮮度（GET /v1/data/{chain}/status/freshness）
data_url = f"https://api.blockvectra.com/v1/data/{chain}/status/freshness"
data_resp = requests.get(data_url, headers={"x-api-key": api_key})
print(f"[{chain}] Data API freshness:", data_resp.json().get("data"))
```


### 回應範例

JSON-RPC `eth_blockNumber` 成功回應（依該方法的 CU 權重計費）：

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x45a27f1"
}
```

Data API `GET /v1/data/{chain}/status/freshness` 成功回應（以 CU 計費，僅對 2xx 成功回應計費）：

```json
{
  "data": [
    {
      "dataset": "blocks",
      "category": "raw",
      "max_block_number": 72313256,
      "max_day": null,
      "max_time": "2026-09-28T03:41:07Z",
      "seconds_behind": 0,
      "blocks_behind": null,
      "days_behind": null,
      "checked_at": "2026-09-28T03:41:10Z"
    },
    {
      "dataset": "traces",
      "category": "raw",
      "max_block_number": 72313256,
      "max_day": null,
      "max_time": "2026-09-28T03:41:07Z",
      "seconds_behind": 0,
      "blocks_behind": null,
      "days_behind": null,
      "coverage_from_block": 72050949,
      "coverage_to_block": 72313256,
      "coverage_complete": true,
      "checked_at": "2026-09-28T03:41:10Z"
    },
    {
      "dataset": "dex_prices",
      "category": "derived",
      "max_block_number": null,
      "max_day": "2026-09-27",
      "max_time": "2026-09-27T00:00:00Z",
      "seconds_behind": 99667,
      "blocks_behind": null,
      "days_behind": 1,
      "checked_at": "2026-09-28T03:41:10Z"
    }
  ],
  "meta": {
    "chain": "robinhood_mainnet",
    "chain_slug": "ROBINHOOD_MAINNET",
    "chain_external_id": "eip155:4663",
    "as_of_block": 72313256,
    "safe_block": 72313100,
    "finalized_block": 72313000,
    "coverage": "full",
    "refreshed_at": "2026-09-28T03:41:10Z"
  }
}
```

## 下一步

* [瀏覽資料集目錄](https://blockvectra.com/zh-hant/data/)，查看 BlockVectra 索引的每個資料集。
* [查看免費方案與定價](https://blockvectra.com/zh-hant/pricing/#free)，確認你的帳戶包含哪些內容。
* [登入控制台](https://console.blockvectra.com/login/?next=%2Fkeys%2F)建立 API key。
