UNPKG

@d8x/perpetuals-sdk

Version:

Node TypeScript SDK for D8X Perpetual Futures

124 lines 5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const d8XMath_1 = require("./d8XMath"); /** * PolyMktsPxFeed gets prices from the official polymarket api * and applies the 1+px transformation * */ class PolyMktsPxFeed { constructor(config) { this.ids = new Map(); this.oracleEndpoint = ""; for (let k = 0; k < config.endpoints.length; k++) { if (config.endpoints[k].type == "polymarket") { let endp = config.endpoints[k].writeEndpoints; this.oracleEndpoint = endp[Math.floor(Math.random() * endp.length)]; break; } } if (this.oracleEndpoint == "") { throw Error("no polymarkets write endpoint defined in priceFeedConfig"); } for (let k = 0; k < config.ids.length; k++) { if (config.ids[k].type == "polymarket") { const sym = config.ids[k].symbol; const idDec = PolyMktsPxFeed.hexToDecimalString(config.ids[k].id); const el = { sym: sym, id: config.ids[k].id, idDec: idDec, }; this.ids.set(sym, el); } } this.oracleEndpoint = this.oracleEndpoint.replace(/\/$/, "") + "/v3/updates/price/latest?encoding=base64&ids[]="; } isPolyMktsSym(sym) { return this.ids.get(sym) == undefined; } // returns index price, ema price, conf in tbps, parameters for order book // for the provided symbols async fetchPricesForSyms(syms) { let ids = new Array(); for (let k = 0; k < syms.length; k++) { const mkt = this.ids.get(syms[k]); if (mkt == undefined) { throw new Error(`symbol not in polymarket universe: ${syms[k]}`); } ids.push(mkt.id); } const chunkSize = 10; const chunks = []; for (let i = 0; i < ids.length; i += chunkSize) { chunks.push(ids.slice(i, i + chunkSize)); } const results = []; for (const chunk of chunks) { const res = await this.fetchPrices(chunk); results.push(...res); } return results; } // fetch price of the form 1+p from oracle, also fetches ema async fetchPrices(tokenIdHex) { // build query let query = this.oracleEndpoint + tokenIdHex[0]; for (let k = 1; k < tokenIdHex.length; k++) { query += "&ids[]=" + tokenIdHex[k]; } let response = await fetch(query); if (response.status !== 200) { throw new Error(`unexpected status code: ${response.status}`); } if (!response.ok) { throw new Error(`failed to fetch posts (${response.status}): ${response.statusText} ${query}`); } const data = await response.json(); let res = new Array(); for (let k = 0; k < tokenIdHex.length; k++) { const parsed = data.parsed.find(({ id }) => id.toLowerCase() == tokenIdHex[k].toLowerCase()); const emaObj = parsed?.ema_price; const pxObj = parsed?.price; const marketClosed = Boolean(parsed?.metadata.market_closed); const s2 = pxObj == undefined || pxObj.price == "NaN" ? 0 : Number(pxObj.price) * Math.pow(10, pxObj.expo); const ema = emaObj == undefined || emaObj.price == "NaN" ? 0 : Number(emaObj.price) * Math.pow(10, emaObj.expo); const params = emaObj?.conf == undefined ? 0n : BigInt(emaObj.conf); const conf = pxObj?.conf == undefined ? 0n : BigInt(pxObj.conf); const info = { s2, ema, s2MktClosed: marketClosed || s2 == 0 || ema == 0, conf, predMktCLOBParams: params, }; res.push(info); } return res; } async fetchPriceFromAPI(tokenIdDec) { const query = "https://clob.polymarket.com/midpoint?token_id=" + tokenIdDec; let response = await fetch(query); if (response.status !== 200) { throw new Error(`unexpected status code: ${response.status}`); } if (!response.ok) { throw new Error(`failed to fetch posts (${response.status}): ${response.statusText} ${query}`); } const data = await response.json(); const px = Number(data.mid); return (0, d8XMath_1.probToPrice)(px); } static hexToDecimalString(hexString) { // Remove the "0x" prefix if it exists if (hexString.startsWith("0x")) { hexString = hexString.slice(2); } // Convert the hex string to a BigInt const bigIntValue = BigInt("0x" + hexString); // Convert the BigInt to a decimal string return bigIntValue.toString(10); } } exports.default = PolyMktsPxFeed; //# sourceMappingURL=polyMktsPxFeed.js.map