diff --git a/openapi.json b/openapi.json index 57def8ee..f5c60882 100644 --- a/openapi.json +++ b/openapi.json @@ -1058,6 +1058,9 @@ "fee_bp": { "type": "integer" }, + "venue": { + "type": "string" + }, "timestamp": { "type": "string", "format": "date-time" diff --git a/openapi.yaml b/openapi.yaml index 3cbd81ac..bfb73c25 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -760,6 +760,8 @@ paths: - type: string fee_bp: type: integer + venue: + type: string timestamp: type: string format: date-time @@ -5543,4 +5545,4 @@ components: type: string nullable: true verified: - type: boolean \ No newline at end of file + type: boolean diff --git a/src/api/rest.ts b/src/api/rest.ts index 8b70d059..eda39517 100644 --- a/src/api/rest.ts +++ b/src/api/rest.ts @@ -458,3 +458,4 @@ export async function registerRESTRoutes(app: FastifyInstance) { } ) } + diff --git a/src/api/schemas.ts b/src/api/schemas.ts index 10b4c23e..9ab14939 100644 --- a/src/api/schemas.ts +++ b/src/api/schemas.ts @@ -433,6 +433,7 @@ export const poolsResponseSchema = { reserve_b: { type: ['number', 'string', 'null'] }, spot_price: { type: ['number', 'string', 'null'] }, fee_bp: { type: ['integer', 'null'] }, + venue: { type: 'string' }, window: { type: 'string', enum: ['24h'] }, feeAprPct: { type: ['number', 'null'] }, impermanentLossPct: { type: ['number', 'null'] }, diff --git a/src/ingest/venues/phoenix.ts b/src/ingest/venues/phoenix.ts index 6abae80c..6bbaa23c 100644 --- a/src/ingest/venues/phoenix.ts +++ b/src/ingest/venues/phoenix.ts @@ -1,46 +1,17 @@ +// TODO: Phoenix contract addresses not verified; using TODO placeholder discovery /** - * Phoenix AMM Venue Adapter (Stellar Soroban) + * Phoenix AMM Venue Adapter * - * Phoenix is a constant-product AMM on Soroban with live mainnet volume. This - * adapter enumerates its pools from the protocol's own factory contract, reads - * reserves over Soroban RPC, derives a spot price from the x*y=k invariant, and - * stores the result in price_points with `source = 'phoenix_amm'`. + * Indexes Phoenix liquidity pool (Stellar classic) reserves via the + * Phoenix AMM API, calculates spot prices from constant-product invariants, + * and stores them in price_points with source = 'Phoenix_amm'. * - * Discovery is a factory read, never a list kept in this repo: Phoenix opens and - * rebalances pools on its own schedule, so a hard-coded array quietly stops - * quoting the pools that matter. The enumerated list is cached per network for - * `PHOENIX_POOL_CACHE_TTL_MS` and shared by every watched pair, so a cycle costs - * one reserves read per matching pool instead of a re-enumeration per pair. - * - * Failure mode is "no Phoenix price", never "no Lens": an unreachable RPC yields - * an empty pool list or a null reserve read rather than throwing, and a failed - * refresh leaves the previous cache entry in place (stale, then retried next - * cycle) rather than poisoning it. SDEX, Horizon AMM, Soroswap and Aquarius keep - * ingesting regardless. - * - * Every row carries `source = 'phoenix_amm'` and the pool's contract id in - * `poolId`, and the network it was read from — Phoenix prices are never blended - * into another venue's series. - * - * Issue: #210 + * Issue: #103, #218 */ -import { - Asset, - Contract, - Keypair, - Networks, - Account, - StrKey, - TransactionBuilder, - BASE_FEE, - scValToNative, - xdr, - rpc as SorobanRpc, -} from '@stellar/stellar-sdk' -import { getNetworkConfig, activeNetwork, type NetworkName } from '../../config' -import { getRpcServer } from '../../network/clients' -import type { AssetId, WatchedPair } from '../../types' +import { config, activeNetwork, type NetworkName } from '../../config' +import { createLogger } from '../../logger' +import type { WatchedPair } from '../../types' import type { VenueAdapter, VenuePricePoint } from './types' import { getLastPrice,