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

# Oracles

> Choosing between manual-oracle and a decentralized SEP-40 price feed (e.g. Reflector) for pool-vault NAV and collateral-vault lending on Stellar.

`pool-vault` (NAV) and `collateral-vault` (loan-to-value and liquidation) both read prices
through the same interface:

```rust theme={null}
fn get_price(token: Address) -> (i128 /* USD, 1e18 */, u64 /* unix seconds */);
fn is_stale(token: Address) -> bool;
```

They don't depend on a particular oracle. Anything implementing this interface can be
passed to their existing `set_oracle`, with **no contract changes**. Two implementations
ship with Ankara:

| | `manual-oracle` | `sep40-oracle-adapter` |
| - | - | - |
| Price source | One admin key posts prices | An external, decentralized SEP-40 feed (e.g. [Reflector](https://reflector.network)) |
| Trust | You trust that key completely | You trust the feed's node network |
| Coverage | Any asset, including bespoke RWAs | Only assets the feed publishes (crypto, FX, some commodities) |
| Liveness | Only as live as the poster | Updated by the network every resolution period |
| Good for | Dev/testnet, one-off farmland/invoice/real-estate tokens with no market price | Anything with a public market price: XLM, USDC, stablecoins, FX, gold |

## When to use which

* **Use the SEP-40 adapter whenever the asset has a public price feed.** For a vault's
  financially consequential math (liquidations, NAV), a decentralized price removes the
  single Ankara-controlled key as a point of failure.
* **Keep `manual-oracle` for assets without one.** Most Ankara RWA tokens (a specific
  farm, a single invoice, one building) will never be on a public feed. An appraiser,
  warehouse or registrar posting a valuation is the right model for them.
* **Mixed vaults: use the adapter with `manual-oracle` as its fallback.** A vault has only
  one oracle address, so the adapter checks the feed first and falls back to
  `manual-oracle` when the feed has no fresh price for a token. One address covers both
  kinds of asset.

***

## sep40-oracle-adapter

| Function | Access | Notes |
| - | - | - |
| `initialize(admin, feed, staleness_threshold, fallback)` | once | `fallback` is optional (e.g. a `manual-oracle`) |
| `set_token_feed(token, Option<FeedConfig>)` | admin | map an Ankara token to a feed asset, optional TWAP |
| `set_feed(feed)` / `set_fallback(Option)` / `set_staleness_threshold(s)` | admin | |
| `get_price(token)` / `is_stale(token)` | anyone | the oracle interface |
| `feed_price(token)`, `is_using_fallback(token)`, `token_feed(token)` | anyone | diagnostics |

* **Asset mapping**: by default a token is looked up on the feed as `Stellar(token)`.
  Map it to a different SAC, or to an off-chain ticker such as `Other("XAU")`, with
  `set_token_feed`. For example, a gold-receipt commodity token can be priced off the
  feed's gold price.
* **Scaling**: feed prices are rescaled from the feed's `decimals()` (14 for Reflector)
  to Ankara's 1e18 convention. The feed's **base asset must be USD** (or a USD stablecoin)
  for the result to be a USD price.
* **TWAP**: `twap_records = n` averages the last `n` feed records, which damps
  short-lived spikes before they reach liquidation logic. The limit is 20.
* **Timestamps**: normalized to seconds. Feeds that report milliseconds are detected.
* **Staleness**: a feed price older than `staleness_threshold` counts as missing, and
  the fallback (if any) takes over.

```ts theme={null}
import { Sep40OracleAdapter, CollateralVault } from "@ankarachain/sdk";

const oracle = new Sep40OracleAdapter(adminAdapter, ADAPTER);
await oracle.setTokenFeed(GOLD_RECEIPT_TOKEN, { asset: { kind: "other", symbol: "XAU" }, twapRecords: 5 });

await new CollateralVault(adminAdapter, VAULT).setOracle(ADAPTER);
console.log(await oracle.isUsingFallback(FARMLAND_TOKEN)); // true: priced by manual-oracle
```

```bash theme={null}
ADAPTER=$(stellar contract deploy --wasm target/wasm32v1-none/release/sep40_oracle_adapter.wasm --source deployer --network testnet)
stellar contract invoke --id $ADAPTER --source deployer --network testnet -- initialize \
  --admin <ADMIN> --feed <REFLECTOR_FEED_CONTRACT> --staleness_threshold 3600 --fallback "\"<MANUAL_ORACLE>\""
# point existing consumers at it
stellar contract invoke --id <COLLATERAL_VAULT> --source deployer --network testnet -- set_oracle --new_oracle $ADAPTER
```

<Note>
  Look up the current Reflector feed contract IDs for testnet and mainnet in Reflector's own
  documentation. Choose the feed whose base asset is USD.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.