MCPcopy Index your code
hub / github.com/pmxt-dev/pmxt / HyperliquidNormalizer

Class HyperliquidNormalizer

core/src/exchanges/hyperliquid/normalizer.ts:198–545  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

196// ----------------------------------------------------------------------------
197
198export class HyperliquidNormalizer implements IExchangeNormalizer<HyperliquidRawOutcomeWithQuestion, HyperliquidRawQuestion> {
199
200 normalizeMarket(raw: HyperliquidRawOutcomeWithQuestion): UnifiedMarket | null {
201 if (!raw || !raw.outcome) return null;
202
203 const outcome = raw.outcome;
204 const outcomeId = outcome.outcome;
205 const parsed = parseDescription(outcome.description);
206
207 // Also parse the question description for context (e.g. priceThresholds)
208 const questionParsed = raw.question
209 ? parseDescription(raw.question.description)
210 : undefined;
211
212 const midPrice = raw.midPrice ? parseFloat(raw.midPrice) : 0.5;
213 const yesPrice = Math.max(0, Math.min(1, midPrice));
214 const noPrice = Math.max(0, Math.min(1, 1 - midPrice));
215
216 const outcomes: MarketOutcome[] = [];
217 for (const side of outcome.sideSpecs) {
218 const sideKey = side.name.toLowerCase() === 'yes' ? 'yes' as const : 'no' as const;
219 outcomes.push({
220 outcomeId: toOutcomeId(outcomeId, sideKey),
221 marketId: toMarketId(outcomeId),
222 label: side.name,
223 price: sideKey === 'yes' ? yesPrice : noPrice,
224 });
225 }
226
227 // If no sideSpecs provided, default to Yes/No
228 if (outcomes.length === 0) {
229 outcomes.push(
230 {
231 outcomeId: toOutcomeId(outcomeId, 'yes'),
232 marketId: toMarketId(outcomeId),
233 label: 'Yes',
234 price: yesPrice,
235 },
236 {
237 outcomeId: toOutcomeId(outcomeId, 'no'),
238 marketId: toMarketId(outcomeId),
239 label: 'No',
240 price: noPrice,
241 },
242 );
243 }
244
245 // Resolution date: prefer outcome-level expiry, then question-level expiry tag,
246 // then a deadline phrase scraped from the question's prose description.
247 const expiryDate = parsed.expiryDate
248 ?? questionParsed?.expiryDate
249 ?? parseDeadlineFromText(raw.question?.description ?? "");
250
251 // Build a descriptive title from the parsed description
252 const title = buildTitle(outcome.name, parsed, questionParsed);
253
254 // Derive underlying from outcome or question
255 const underlying = parsed.underlying ?? questionParsed?.underlying;

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected