> For the complete documentation index, see [llms.txt](https://docs.rome.builders/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rome.builders/vi/san-pham/oracle-gateway.md).

# Oracle Gateway

Các nguồn cấp giá Pyth và Switchboard đứng sau Chainlink's AggregatorV3Interface.

Oracle Gateway hiển thị các feed giá gốc của Solana (Pyth, Switchboard V3) thông qua Chainlink `AggregatorV3Interface`, vì vậy các giao thức Ethereum chuyển sang Rome vẫn giữ mã tích hợp oracle hiện có của họ. **Oracle Gateway V2 được triển khai trên Hadrian và Rubicon**, tuy registry chỉ liệt kê địa chỉ feed cho Hadrian, và cổng khách hàng xử lý việc đăng ký. Một keeper do Rome chạy sẽ làm mới các feed cached và book, nhưng không phải mọi feed đều mới ở mọi thời điểm — [những feed nào phản hồi hôm nay](#which-feeds-answer-today) được trình bày dưới đây. Các bộ điều hợp, factory và mô hình keeper được đề cập trong [rome-oracle-gateway](https://github.com/rome-protocol/rome-oracle-gateway) repo.

> **Xem trước.** Oracle Gateway chưa được kiểm toán. Cổng cũng nói như vậy: đừng dùng nó trong các luồng giá trị production.

## Vấn đề

DeFi trên Ethereum mong đợi giao diện của Chainlink `AggregatorV3Interface`:

```solidity
(, int256 price,,,) = priceFeed.latestRoundData();
```

Các nhà cung cấp oracle của Solana (Pyth, Switchboard) có định dạng dữ liệu khác nhau. Nếu không điều chỉnh, mỗi giao thức được chuyển sang sẽ cần mã oracle tùy chỉnh.

## Giải pháp

Oracle Gateway V2 triển khai các hợp đồng adapter nhẹ mà:

1. Đọc dữ liệu giá trực tiếp từ các tài khoản Pyth hoặc Switchboard trên Solana (đọc xuyên trạng thái, không phải CPI)
2. Phân tích dữ liệu on-chain
3. Chuẩn hóa giá về 8 chữ số thập phân
4. Hiển thị giao diện chuẩn của Chainlink `AggregatorV3Interface`

```solidity
import {IAggregatorV3Interface} from "@rome-protocol/rome-solidity/contracts/oracle/IAggregatorV3Interface.sol";

// Cùng giao diện như Chainlink trên Ethereum
(, int256 price,,,) = IAggregatorV3Interface(ADAPTER).latestRoundData();
// price = SOL/USD ở 8 chữ số thập phân (ví dụ: 15000000000 = $150.00)
```

## Sử dụng một feed trong ba bước

1. **Lấy địa chỉ adapter từ registry** — tuyệt đối không hardcode nó:

```ts
import { getOracle } from "@rome-protocol/registry";
const solUsd = getOracle(200010).feeds["SOL/USD"].address;
// Hadrian, registry v0.2.0: 0x567384ee000ca0418c386A73eC2b7466f9f99D6b
```

Registry được cài đặt từ GitHub (`npm install github:rome-protocol/rome-registry#v0.2.0`). Các khóa feed có hậu tố cho biết loại adapter đứng sau chúng; xem [Các khóa feed trong registry](#feed-keys-in-the-registry) trước khi chọn một cái.

2. **Đọc nó** với giao diện mà giao thức của bạn đã dùng — `IAggregatorV3Interface(solUsd).latestRoundData()`. Một feed lỗi thời hoặc chưa khởi tạo **hoàn nguyên** thay vì phục vụ một mức giá bị đóng băng.
3. **Nhiều feed cùng lúc?** `BatchReader.getLatestPrices(adapters[])` (Hadrian, registry v0.2.0: `0x2869f0a96572e7fb15036656e9a32fd17346499b`) — và `getFeedHealth(adapters[])` trước khi bạn phụ thuộc vào chúng. Các adapter được cache khiến mỗi consumer đọc một `SLOAD`, nên các giao dịch nhiều feed (một khoản vay đa tài sản thế chấp, một chế độ xem danh mục) vẫn rẻ.

[cardo](https://github.com/rome-protocol/cardo) đọc các feed này trên Hadrian. Vì bề mặt giao diện chính xác là `AggregatorV3Interface`, các giao thức thuộc họ Compound và Aave có thể dùng các feed này mà không cần thay đổi mã oracle — chỉ cần trỏ cấu hình price-feed của họ tới các địa chỉ adapter.

## Các loại adapter

* **PythPullAdapter** — đọc các tài khoản giá Pyth (giá, độ tin cậy, EMA, thời gian công bố).
* **SwitchboardV3Adapter** — đọc các tài khoản aggregator của Switchboard (giá, dấu thời gian; không có EMA).
* **Các adapter CachedPyth / CachedFeed** — các biến thể có cache theo dõi để đọc hiệu quả về CU.
* **BookFeedAdapter** — một khung nhìn chỉ đọc tương thích Chainlink trên một mục của một `PriceBook` hợp đồng. Cuốn sổ giữ giá cho tất cả các feed đã đăng ký của nó và được làm mới theo lô (việc làm mới là không cần quyền); adapter của mỗi feed không tự có cache riêng. Một mục bị tạm dừng sẽ revert ngay với `AdapterPaused`, thay vì chờ trở nên lỗi thời.

Các adapter được triển khai dưới dạng các clone proxy tối thiểu EIP-1167: `OracleAdapterFactory` clone các adapter Pyth, Switchboard và cached, và mỗi `PriceBook` bản clone riêng của nó `BookFeedAdapter` khi một feed được đăng ký. Chúng hiển thị một giao diện mở rộng bên cạnh `AggregatorV3Interface` (`latestPriceData`, `maxStaleness`, `oracleType`, và một `metadata()` bề mặt được dùng cho các kiểm tra sức khỏe).

## Các khóa feed trong registry

`getOracle(chainId).feeds` có nhiều khóa cho mỗi tài sản. Hậu tố trên tên khóa cho biết loại adapter:

| Khóa                 | Loại adapter                          | Cách nó đọc                                                                                        |
| -------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `SOL/USD`            | Pyth trực tiếp (`PythPullAdapter`)    | Phân tích tài khoản Pyth ở mỗi lần gọi.                                                            |
| `SOL/USD-BOOK`       | `BookFeedAdapter`                     | Đọc một `PriceBook` mục mà keeper làm mới.                                                         |
| `SOL/USD-CACHED`     | Được cache (bọc một feed khác)        | Đọc một giá được lưu mà keeper làm mới.                                                            |
| `SOL/USD-CACHEDPYTH` | Pyth được cache (`CachedPythAdapter`) | Đọc một giá được lưu mà keeper làm mới.                                                            |
| `SOL/USD-SB`         | Switchboard (`SwitchboardV3Adapter`)  | Phân tích tài khoản Switchboard ở mỗi lần gọi. Registry đánh dấu các mục này `đã ngừng hoạt động`. |

Bạn nên tiêu thụ loại nào phụ thuộc vào chain. Hãy kiểm tra phần tiếp theo trước.

### Những feed nào phản hồi hôm nay

Đây là kết quả của các lời gọi `latestRoundData()` chỉ-đọc trên các feed được liệt kê trong registry v0.2.0, thực hiện trong lúc trang này được viết. Độ mới của feed thay đổi từng phút trên devnet, vì vậy hãy coi đây là một ảnh chụp nhanh và chạy cùng lời gọi đó trên feed mà bạn dự định dùng.

* **Hadrian.** Các feed trực tiếp thường bị lỗi thời: trong các lần kiểm tra lặp lại, hầu hết chúng (BONK, BTC, ETH, JITOSOL, JTO, JUP, MSOL, USDC, USDT) đều revert với `StalePriceFeed` mỗi lần, và `SOL/USD` trả lời trong một số lần gọi nhưng không phải các lần khác. Các feed `-BOOK` là đáng tin cậy nhất và trả lời trong mọi lần gọi cho mọi tài sản trừ JTO, mà `-BOOK` feed của nó revert vì đã cũ. Mọi feed `-CACHED` và `-CACHEDPYTH` feed đều revert với `UninitializedPriceFeed` (chưa có gì làm mới chúng), và `SOL/USD-SB` revert với `StalePriceFeed`. Trên Hadrian, hãy ưu tiên feed `-BOOK` và chạy `latestRoundData()` trên feed bạn chọn trước khi phụ thuộc vào nó.
* **Rubicon.** Registry không liệt kê các feed oracle cho Rubicon, nên trang này không đề cập đến chúng. Factory được triển khai ở đó (xem [Các địa chỉ đã triển khai](#deployed-addresses)) và các adapter đầu tiên của nó phản hồi, nhưng hãy tra cứu địa chỉ feed từ factory (`adapterCount()` và `allAdapters(i)`) thay vì từ registry.

Việc revert ở đây là hành vi được thiết kế: một feed lỗi thời hoặc chưa khởi tạo sẽ fail rõ ràng thay vì trả về giá cũ. Hãy xử lý nó trong hợp đồng của bạn.

## Độ mới — keeper của oracle

Các adapter áp đặt một `maxStaleness` cửa sổ: nếu `block.timestamp - publishTime > maxStaleness`, các lần đọc sẽ revert. Trên Solana mainnet, Pyth chạy các keeper production. Trên Solana devnet (nơi Hadrian sống), các pusher của Pyth chỉ mang tính best-effort, nên Rome chạy một sidecar **keeper của oracle** để giữ cho các tài khoản Pyth nền tảng luôn mới và làm mới các feed cached và book. Keeper không bao phủ mọi feed trên mọi chain ở mọi thời điểm (xem [những feed nào phản hồi hôm nay](#which-feeds-answer-today)).

Kiểm tra sức khỏe feed bằng `BatchReader.getFeedHealth` (đọc `metadata()`của mỗi adapter `), không chỉ` latestRoundData

## — một feed có thể truy cập được nhưng đã cũ.

Cổng khách hàng [Cổng Oracle](https://oracle.testnet.romeprotocol.xyz/)Đăng ký feed và cấu hình consumer theo từng chain thông qua [. Xem](/vi/ung-dung-tren-rome/oracle-gateway.md) trang portal

## Các địa chỉ đã triển khai

để biết những gì nó bao phủ. [registry](https://github.com/rome-protocol/rome-registry/tree/main/chains)Các địa chỉ chuẩn theo từng chain (factory, triển khai adapter và các feed đang hoạt động) nằm trong `live` . Các factory tiêu biểu, từ [Địa chỉ Hợp đồng](/vi/tai-lieu-tham-khao/contract-addresses.md) trang); xem [Đọc danh sách hợp đồng](/vi/tai-lieu-tham-khao/contract-addresses.md#reading-the-contracts-list):

| Hợp đồng             | Hadrian                                      | Rubicon                                      |
| -------------------- | -------------------------------------------- | -------------------------------------------- |
| OracleAdapterFactory | `0x52b008771fc95b4674a4f3533570b3d223f27f68` | `0x6a1340dd86c3951b6f13d9001b3951d56a2fe581` |
| BatchReader          | `0x2869f0a96572e7fb15036656e9a32fd17346499b` | `0x580dc0ecb226530ee8a90b57e0f0cd2555fb4f0f` |

## Ràng buộc

* **Không có dữ liệu round lịch sử** — `getRoundData(roundId)` sẽ revert; chỉ `latestRoundData()` được hỗ trợ.
* **Không hỗ trợ Switchboard EMA** — dữ liệu EMA chỉ có trên Pyth.
* **Độ lỗi thời theo từng chain** — `maxStaleness` được thiết lập theo từng môi trường khi khởi động: các adapter trực tiếp (đọc Pyth) mặc định khoảng 60 giây; các adapter có cache mặc định 3600 giây (khi keeper làm mới chúng thì thường xuyên hơn nhiều so với con số đó).
* **Độ lệch parser** được xác thực dựa trên bố cục Pyth/Switchboard hiện tại; thay đổi bố cục yêu cầu xác thực lại.

## Tiếp theo là gì

* [Cổng Oracle](/vi/ung-dung-tren-rome/oracle-gateway.md) — đăng ký feed, cấu hình consumer
* [Địa chỉ Hợp đồng](/vi/tai-lieu-tham-khao/contract-addresses.md) — precompile và địa chỉ theo từng chain


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.rome.builders/vi/san-pham/oracle-gateway.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
