Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/pegs-deviation-route.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'lens': minor
---

Add `GET /pegs` endpoint reporting peg deviations and provenance across all configured pegged assets.
Targets and target prices are configured explicitly per network (omitting unconfigured assets).
Honours and echoes `?network=testnet|mainnet` and includes data provenance (venues, sample count, and freshness).
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ REFLECTOR_CONTRACT_ID_TESTNET=
# Comma-separated pairs to watch on testnet.
# Format: "CODE:ISSUER/CODE:ISSUER". Use "native" for XLM.
WATCHED_PAIRS_TESTNET=XLM:native/USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5
# Comma-separated pegged assets with explicit target and peg price on testnet.
# Format: "ASSET[:ISSUER]=TARGET:TARGET_PRICE[:WINDOW_HOURS]"
PEGGED_ASSETS_TESTNET=USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5=USD:1.0

# --- Stellar Network — Mainnet ---
HORIZON_URL_MAINNET=https://horizon.stellar.org
Expand All @@ -99,6 +102,9 @@ AQUARIUS_ENABLED_MAINNET=true
REFLECTOR_CONTRACT_ID_MAINNET=
# Comma-separated pairs to watch on mainnet.
WATCHED_PAIRS_MAINNET=XLM:native/USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN
# Comma-separated pegged assets with explicit target and peg price on mainnet.
# Format: "ASSET[:ISSUER]=TARGET:TARGET_PRICE[:WINDOW_HOURS]"
PEGGED_ASSETS_MAINNET=USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN=USD:1.0

# --- Venue endpoint overrides (optional, shared across networks unless a
# paired _TESTNET / _MAINNET variant is set) ---
Expand All @@ -115,6 +121,7 @@ RPC_URL=https://soroban-testnet.stellar.org
NETWORK_PASSPHRASE=Test SDF Network ; September 2015
SOROSWAP_FACTORY_ADDRESS=CDP3HMUH6SMS3S7NPGNDJLULCOXXEPSHY4JKUKMBNQMATHDHWXRRJTBY
WATCHED_PAIRS=XLM:native/USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5
PEGGED_ASSETS=USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5=USD:1.0
# Reflector oracle contract ID on testnet (falls back from paired REFLECTOR_CONTRACT_ID_TESTNET)
REFLECTOR_CONTRACT_ID=

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Aggregates price data from Stellar's Classic Order Book (SDEX) and AMM Liquidity
| GET | `/compare/:asset` | Lens vs configured oracle prices, with per-oracle deviation and availability |
| GET | `/screener?sortBy=volume&order=desc&limit=20` | Screen pairs by volume, 24h change, liquidity and price |
| GET | `/benchmark/:asset?target=USD` | Peg-deviation statistics versus a target |
| GET | `/pegs` | All configured pegged assets with current and worst deviation and provenance |
| GET | `/basket?asset=XLM&asset=USDC&weight=0.6&weight=0.4` | Weighted price of a basket of assets |
| GET | `/status` | Indexer health |
| GET | `/snapshot?network=testnet\|mainnet` | Whole-network snapshot: venues, TVL, 24h volume, top pairs, peg readings and data freshness in one cached, timestamped object |
Expand Down Expand Up @@ -59,7 +60,7 @@ ones listed below still read a single instance-wide network.
Per-request today: `/price/:assetA/:assetB` (its VWAP, OHLCV, AMM and
best-route reads), `/price/:assetA/:assetB/route`, `/price/:assetA/:assetB/depth`, `/book/:assetA/:assetB`,
`/prices/history`, `/screener`, `/pools`, `/pairs`, `/spreads/:asset`,
`/volumes/:asset`, `/status`, and the x402 payment `network`/`payTo`. That list
`/volumes/:asset`, `/pegs`, `/status`, and the x402 payment `network`/`payTo`. That list
is the same one `openapi.yaml` declares a `network` parameter on — if they ever
disagree, the spec is the thing to fix.

Expand Down
140 changes: 140 additions & 0 deletions openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1676,6 +1676,39 @@
}
}
},
"/pegs": {
"get": {
"operationId": "getPegs",
"summary": "Get peg deviation and window statistics for all configured pegged assets",
"security": [],
"parameters": [
{
"$ref": "#/components/parameters/NetworkQuery"
}
],
"responses": {
"200": {
"description": "List of configured pegged assets and their peg deviations",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PegsResponse"
}
}
}
},
"400": {
"description": "Invalid network parameter"
},
"429": {
"$ref": "#/components/responses/TooManyRequests"
},
"500": {
"description": "Internal server error"
}
}
}
},
"/basket": {
"get": {
"operationId": "getBasket",
Expand Down Expand Up @@ -3720,6 +3753,113 @@
}
}
},
"PegReport": {
"type": "object",
"required": [
"asset",
"code",
"issuer",
"target",
"targetPrice",
"pairKey",
"currentPrice",
"currentDeviationBps",
"worstDeviationBps",
"window",
"provenance"
],
"additionalProperties": false,
"properties": {
"asset": {
"type": "string"
},
"code": {
"type": "string"
},
"issuer": {
"type": "string",
"nullable": true
},
"target": {
"type": "string"
},
"targetPrice": {
"type": "number"
},
"pairKey": {
"type": "string",
"nullable": true
},
"currentPrice": {
"type": "number",
"nullable": true
},
"currentDeviationBps": {
"type": "number",
"nullable": true
},
"worstDeviationBps": {
"type": "number",
"nullable": true
},
"window": {
"type": "string"
},
"provenance": {
"type": "object",
"required": [
"venues",
"sampleCount",
"freshnessSeconds",
"lastSampleTimestamp"
],
"additionalProperties": false,
"properties": {
"venues": {
"type": "array",
"items": {
"type": "string"
}
},
"sampleCount": {
"type": "integer"
},
"freshnessSeconds": {
"type": "integer",
"nullable": true
},
"lastSampleTimestamp": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
}
}
},
"PegsResponse": {
"type": "object",
"required": [
"network",
"pegs"
],
"additionalProperties": false,
"properties": {
"network": {
"type": "string",
"enum": [
"testnet",
"mainnet"
]
},
"pegs": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PegReport"
}
}
}
},
"BasketResponse": {
"type": "object",
"required": [
Expand Down
98 changes: 98 additions & 0 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,27 @@ paths:
'500':
description: Benchmark computation failed

/pegs:
get:
operationId: getPegs
summary: Get peg deviation and window statistics for all configured pegged assets
security: []
parameters:
- $ref: '#/components/parameters/NetworkQuery'
responses:
'200':
description: List of configured pegged assets and their peg deviations
content:
application/json:
schema:
$ref: '#/components/schemas/PegsResponse'
'400':
description: Invalid network parameter
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
description: Internal server error

/basket:
get:
operationId: getBasket
Expand Down Expand Up @@ -2386,6 +2407,83 @@ components:
sampleCount:
type: integer

PegReport:
type: object
required:
- asset
- code
- issuer
- target
- targetPrice
- pairKey
- currentPrice
- currentDeviationBps
- worstDeviationBps
- window
- provenance
additionalProperties: false
properties:
asset:
type: string
code:
type: string
issuer:
type: string
nullable: true
target:
type: string
targetPrice:
type: number
pairKey:
type: string
nullable: true
currentPrice:
type: number
nullable: true
currentDeviationBps:
type: number
nullable: true
worstDeviationBps:
type: number
nullable: true
window:
type: string
provenance:
type: object
required:
- venues
- sampleCount
- freshnessSeconds
- lastSampleTimestamp
additionalProperties: false
properties:
venues:
type: array
items:
type: string
sampleCount:
type: integer
freshnessSeconds:
type: integer
nullable: true
lastSampleTimestamp:
type: string
format: date-time
nullable: true

PegsResponse:
type: object
required: [network, pegs]
additionalProperties: false
properties:
network:
type: string
enum: [testnet, mainnet]
pegs:
type: array
items:
$ref: '#/components/schemas/PegReport'

BasketResponse:
type: object
required: [basketPrice, components, weightSum, computedAt]
Expand Down
Loading
Loading