# หนึ่งคีย์ หลากหลายเชน: การเปลี่ยนตัวอย่างไปยังเชนอื่น

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

## 1. หนึ่งคีย์ข้ามทุกเชนที่รองรับ

API key เดียวกันใช้ได้กับทุกเชนที่รองรับสำหรับ JSON-RPC และสำหรับ Data API บนเชนที่พร้อมให้บริการ คีย์เป็นของบัญชีคุณและไม่ได้ผูกติดกับเชนใดเชนหนึ่งโดยเฉพาะ จึงไม่จำเป็นต้องสร้าง API key แยกสำหรับแต่ละเครือข่าย

เครดิตและขีดจำกัดอัตราจะถูกใช้ร่วมกันข้ามทุกเครือข่าย และข้ามระหว่าง JSON-RPC API กับ Data API โดยไม่มีการแบ่งแยกตามเครือข่าย สำหรับกฎการเรียกเก็บเงินโดยละเอียด โปรดดู [หน้าราคา](https://blockvectra.com/en/pricing/)

* **ยอดคงเหลือที่ใช้ร่วมกัน**: การเติมเงินแบบชำระเงินและเครดิตฟรีมีผลบังคับใช้ข้ามทุกเชน การเรียกบนเชนใดก็ตามจะดึงจากยอดคงเหลือของบัญชีเดียวกัน
* **ขีดจำกัดอัตราที่ใช้ร่วมกัน**: อัตราการเติม Compute Unit (CU) และความจุ burst มีผลบังคับใช้ข้ามทุกเชนสำหรับคีย์ที่กำหนด ขีดจำกัดการเรียกต่อวินาทีของ Free Plan จะรวมกันข้ามทุกเชนที่รองรับ ไม่ได้แบ่งแยกตามเชน
* **เส้นทางการอัปเกรด**: หลังจากการเติมเงิน คุณจะไม่ถูกจำกัดโดยขีดจำกัดการเรียกต่อวินาทีของ Free Plan อีกต่อไป; แต่ละคีย์ยังคงอยู่ภายใต้อัตรา CU และขีดจำกัด burst ตามที่อธิบายไว้ใน [เอกสาร JSON-RPC](https://docs.blockvectra.com/en/api/json-rpc/#method-policy)

## 2. โครงสร้าง URL และพารามิเตอร์ `{chain}`

ทุกคำขอที่มีขอบเขตเฉพาะเชนจะระบุเครือข่ายเป้าหมายในพาธ URL โดยใช้ `{chain}` พารามิเตอร์ `{chain}` คือสลักตัวระบุที่เป็นตัวพิมพ์เล็กของเชน (เช่น `robinhood_mainnet`)

| บริการ           | การยืนยันตัวตน     | เทมเพลต URL                  | คำอธิบาย                                                   |
| ---------------- | ------------------ | ---------------------------- | ---------------------------------------------------------- |
| JSON-RPC         | คีย์ในพาธ URL      | `POST /v1/{chain}/{api_key}` | รูปแบบที่ง่ายที่สุด เหมาะสำหรับ curl และ HTTP client       |
| JSON-RPC         | คีย์ในส่วนหัวคำขอ  | `POST /v1/{chain}`           | ส่งคีย์ผ่านส่วนหัวคำขอ `x-api-key: {api_key}`              |
| Data API         | เส้นทาง REST       | `GET /v1/data/{chain}/…`     | ส่งคีย์ผ่านส่วนหัวคำขอ `x-api-key: {api_key}`              |
| รายการเชนสาธารณะ | ไม่ต้องยืนยันตัวตน | `GET /v1/chains`             | รายการเชนสาธารณะและข้อเท็จจริงคงที่ (ไม่คิดค่าบริการ)      |
| สถานะสาธารณะ     | ไม่ต้องยืนยันตัวตน | `GET /v1/status`             | สถานะบริการปัจจุบันและ block head ของเชน (ไม่คิดค่าบริการ) |

`GET /v1/chains` จะรายงานแฟล็ก `jsonrpc` และ `data` สำหรับแต่ละเชน ให้ส่งคำขอไปยังเชนด้วย URL ของ JSON-RPC เมื่อเชนนั้นให้บริการ JSON-RPC และใช้ `GET /v1/data/{chain}/…` เมื่อแฟล็ก `data` เป็น `true` (Data API ให้บริการเฉพาะเชนเหล่านั้น)

> **เคล็ดลับ**: เมื่อส่งคีย์ของคุณผ่านส่วนหัวคำขอ ให้จัดรูปแบบ URL ให้ลงท้ายด้วยชื่อเชน **โดยไม่มี** เครื่องหมายทับปิดท้าย (trailing slash) JSON-RPC ให้บริการเฉพาะที่ `/v1/{chain}` และ `/v1/{chain}/{api_key}` เท่านั้น คำขอที่มีเครื่องหมายทับปิดท้าย (เช่น `/v1/{chain}/`) หรือไม่มีเซกเมนต์ของเชนจะส่งกลับ HTTP 404 พร้อม body ที่ว่างเปล่า คำขอไปยัง `{chain}` ที่ไม่รู้จักจะส่งกลับ HTTP 404 พร้อม `error.data.reason: "unknown_chain"` (ไม่คิดค่าบริการ)

## 3. การค้นหาเชนและความสามารถโดยใช้โปรแกรม

เชนที่รองรับและความสามารถของเชนให้บริการแบบไดนามิก อย่าฮาร์ดโค้ดรายการเชนแบบคงที่ไว้ในแอปพลิเคชันของคุณ แต่ให้ค้นหาเครือข่ายที่พร้อมใช้งานและความสามารถของเครือข่ายขณะรันไทม์แทน:

### ค้นหาข้อเท็จจริงคงที่ผ่าน `GET /v1/chains`

endpoint สาธารณะนี้ไม่ต้องยืนยันตัวตนและไม่คิดค่าบริการ โดยจะส่งกลับเชนทั้งหมดที่เปิดให้บริการแบบสาธารณะ:

```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`: สลักตัวระบุเชน (ใช้สำหรับ `{chain}` ใน URL)
* `name`: ชื่อที่มนุษย์อ่านได้
* `chain_id`: EIP-155 chain 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`

endpoint สาธารณะนี้ไม่ต้องยืนยันตัวตนและไม่คิดค่าบริการ โดยจะส่งกลับความพร้อมของบริการและข้อมูล block head ของเชน:

```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. **ช่วงบล็อกของ log (`max_logs_block_range`)**: ช่วงบล็อกสูงสุดสำหรับคิวรี `eth_getLogs` จะแตกต่างกันไปตามแต่ละเชน การส่งคำขอเกินขีดจำกัดของเชนจะส่งกลับ HTTP 200 พร้อมรหัสข้อผิดพลาด JSON-RPC `-32602` (`eth_getLogs block range too large`, ไม่คิดค่าบริการ)
3. **กรอบเวลาการเก็บรักษาสถานะ (`state_window_blocks`)**: เชนที่มีประวัติเต็มจะส่งกลับ `null` สำหรับเชนที่มีการ prune สถานะ การคิวรีสถานะย้อนหลังนอกกรอบเวลาจะส่งกลับ 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/en/chains/) การคิวรีชุดข้อมูลที่เชนไม่รองรับ หรือบล็อกที่อยู่ก่อนความครอบคลุมที่ทำดัชนีไว้ จะส่งกลับ HTTP `422` (`error.code` `no_coverage`, ไม่คิดค่าบริการ) เมื่อบริการไม่พร้อมใช้งานชั่วคราว — เช่น เมื่อเชนไม่ว่าง — คำขอจะส่งกลับ HTTP `503` พร้อมส่วนหัว `Retry-After` (ไม่คิดค่าบริการ)

## 5. ตัวอย่างโค้ด

เทมเพลตเริ่มต้นฉบับสมบูรณ์: [blockvectra/multichain-viem](https://github.com/blockvectra/multichain-viem)

โค้ดชุดเดียวกันนี้สามารถรันข้ามเชนต่างๆ ได้โดยการอัปเดตตัวแปรเชน (หรืออ่านแบบไดนามิกจาก `GET /v1/chains`) โดยคิวรี `eth_blockNumber` ผ่าน JSON-RPC และคิวรีความสดใหม่ของชุดข้อมูลผ่าน Data API:

**cURL**

```bash
export BLOCKVECTRA_API_KEY="rgw_your_api_key"

# Change the chain variable to target another chain from Supported Chains
CHAIN="robinhood_mainnet"

# 1. JSON-RPC: Query eth_blockNumber (POST /v1/{chain}, key in the x-api-key header).
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: Query dataset freshness (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
// Change this variable to target another chain, or read it dynamically from GET /v1/chains
const chain = "robinhood_mainnet";
const apiKey = process.env.BLOCKVECTRA_API_KEY!;

// 1. JSON-RPC: Call 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: Query freshness (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

# Change this variable to target another chain, or read it dynamically from GET /v1/chains
chain = "robinhood_mainnet"
api_key = os.environ["BLOCKVECTRA_API_KEY"]

# 1. JSON-RPC: Call 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: Query freshness (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/en/data/) เพื่อดูทุกชุดข้อมูลที่ BlockVectra ทำดัชนี
* [ดูแผนบริการฟรีและราคา](https://blockvectra.com/en/pricing/#free) เพื่อตรวจสอบสิ่งที่บัญชีของคุณได้รับ
* [เข้าสู่ระบบคอนโซล](https://console.blockvectra.com/login/?next=%2Fkeys%2F) เพื่อสร้าง API key
