Skip to content

Плагин prediction_market_api

Read-only JSON-RPC доступ к состоянию прогнозных рынков HF14 (рынки, ставки, оракулы, ликвидность, споры, lazy-пул, chain properties v5). Плагин возвращает сырые консенсус-объекты pm_* напрямую плюс несколько вычисляемых DTO.

Включение: добавить prediction_market_api в список плагинов узла (в vizd зарегистрирован по умолчанию). Зависит от chain + json_rpc. Все list-методы пагинируются через from (пропуск) и limit (≤ 1000).

Методы

Рынки

МетодАргументыВозврат
get_marketmarket_idpm_market_object
list_marketsstatus, from, limit, [show_risky]pm_market_object[]
list_markets_by_oracleoracle, from, limitpm_market_object[]
list_markets_by_creatorcreator, from, limitpm_market_object[]
get_market_outcomesmarket_idpm_outcome_object[]
get_market_weight_sumsmarket_idpm_market_weight_sums (вычисляемый)
get_market_betsmarket_id, from, limitpm_bet_object[]
get_market_liquiditymarket_id, from, limitpm_liquidity_object[]
get_market_fullmarket_id, [account]pm_market_full (вычисляемый)

status для list_markets: -1 удалён, 0 ожидание, 1 активен, 2 закрыт, 3 разрешён. По умолчанию list_markets скрывает недострахованные рынки (страховка оракула < 2.5× объёма ставок); show_risky = true показывает их (рынки только скрываются, ставки on-chain всегда разрешены).

get_market_fullобогащённое представление за один вызов для экрана деталей рынка: возвращает рынок + исходы + суммы весов + оракула (с надёжностью) + распарсенные метаданные и — если передан необязательный account — ставки, плечевые позиции и LP этого аккаунта на этом рынке. Экономит тонкому клиенту несколько round-trip'ов.

Метаданные рынка (парсятся off-chain)

Каждый рынок несёт свободную, консенсус-непрозрачную JSON-строку metadata. Плагин парсит индексируемые ключи (категория / подкатегория / теги / запрещённые юрисдикции) в pm_market_meta_objectтолько для отображения/индексации, не консенсус.

МетодАргументыВозврат
get_market_metamarket_idpm_market_meta_object (или ошибка, если нет)
list_markets_by_categorycategory, from, limit, [jurisdiction], [subcategory], [tag], [sort]pm_market_meta_object[]
get_market_categoriespm_market_categories (вычисляемый)

list_markets_by_category исключает рынки, чьи banned_jurisdictions содержат необязательный ISO-код jurisdiction (регулируемый клиент передаёт свою юрисдикцию, чтобы получить только допустимые рынки). Необязательные subcategory (точное совпадение) и tag (членство в CSV) сужают набор; sortnewest (id рынка по убыв., по умолч.) · oldest · volume (bets_sum по убыв.) · expiration (betting_expiration по возр.). get_market_categories возвращает живую таксономию — счётчики по категориям / подкатегориям плюс топ-20 горячих тегов (jurisdiction-* исключены) — агрегированную по проиндексированным сейчас рынкам, чтобы браузинг-UI строил свои фильтр-чипы без захардкоженной таксономии. Объект: market, category, subcategory, tags (через запятую), banned_jurisdictions (ISO через запятую; пусто = разрешено везде), expiry (пруна после закрытия окна спора + TTL).

Позиции и оракулы

МетодАргументыВозврат
get_account_positionsaccount, from, limitpm_position[] (ставка + expected_payout)
get_account_leverage_positionsaccount, from, limitpm_leverage_position_object[]
get_market_leverage_positionsmarket_id, from, limitpm_leverage_position_object[]
get_creator_banaccountpm_creator_ban_object (или ошибка, если нет)
get_oracleownerpm_oracle (объект + reliability_score)
list_oraclesfrom, limitpm_oracle_object[]

Превью плеча (Boost)

Read-only котировки, вызывающие ту же внутриузловую математику маржи, что и эвалуаторы, так что превью совпадает с тем, что вычислила бы соответствующая операция pm_leverage_* на головном блоке. Это неконсенсусные оценки (резервы двигаются между чтением и бродкастом — всегда отправляйте on-chain защиту от проскальзывания).

МетодАргументыВозврат
get_leverage_quotemarket_id, outcome_index, collateralpm_leverage_quote (вычисляемый)
get_leverage_close_previewposition_idpm_leverage_close_preview (вычисляемый)
get_leverage_convert_previewposition_idpm_leverage_convert_preview (вычисляемый)

get_leverage_quote зеркалит pm_leverage_open: возвращает максимальный платёжеспособный заём и итоговое максимальное плечо, кэпы пула/позиции, до 12 стопов слайдера (каждый с токенами, порогом, текущей и худшей стоимостью отмены) и — когда плечо невозможно — available = false со списком failed_constraints[]. get_leverage_close_preview / get_leverage_convert_preview зеркалят pm_leverage_close / pm_leverage_convert при текущих резервах (стоимость отмены, обязательство пула, что получает беттер, закрываемость/конвертируемость и комиссия конвертации при текущей медиане pm_conversion_profit_cost_percent).

Выплата каждому беттору — виртуальная операция pm_payout (стейк, side/outcome, итог; 0 при проигрыше); закрытие плечевой позиции — pm_leverage_resolve (outcome_index, won, leverage). Обе видны в account_history; сами объекты позиций — через методы выше.

Споры, lazy-пул, governance

МетодАргументыВозврат
get_disputemarket_idpm_dispute_object
get_dispute_votesmarket_idpm_dispute_votes (голоса + живой подсчёт)
get_lazy_poolpm_lazy_pool_object
get_lazy_depositaccountpm_lazy_deposit_object
get_lazy_allocationsfrom, limitpm_lazy_allocation_object[]
get_market_lazy_allocationmarket_idpm_lazy_allocation_object (или ошибка, если нет)
get_pm_chain_propertieschain_properties_pm (медиана, v5)

get_lazy_allocations перечисляет записи аллокаций lazy-пула по рынкам (для дашборда пула); get_market_lazy_allocation берёт запись для конкретного рынка. Штрафные штампы оракула отдельного метода не требуют — они идут на pm_oracle_object (penalty_stamps, last_penalty_stamp_time) через get_oracle.

Графики — kline / история весов

Тайм-серия для построения графика изменения веса каждого исхода. Плагин добавляет точку каждый раз, когда веса исходов рынка меняются — ставка, отмена, ликвидация, batch-settle, открытие плеча или расчёт плеча — как таймстампированный снимок паримутюэль-веса (сумма ставок) по каждому исходу. Это неконсенсусное состояние плагина (хранится в chainbase, undo/redo-безопасно, не входит в хеш состояния); история копится с момента первого включения плагина на узле.

Хранение: kline-история пруна́ется вместе с метаданными рынка, по тому же расписанию — result_expiration + grace спора + pmm-ttl-days (по умолч. 7). Полный график рынка доступен на протяжении его жизни и в окне хранения после расчёта, затем оба индекса очищаются (для очень длинной истории — частями за несколько блоков), чтобы хранилище узла оставалось ограниченным.

МетодАргументыВозврат
get_market_klinemarket_id, [from], [limit]pm_kline[] (по возрастанию seq)

Пагинация — отступ от новейших (намеренно простая для тонких клиентов): from — сколько новейших точек пропустить, limit ≤ 1000 — размер страницы.

  • (market_id, 0, 1000) → последние ≤ 1000 изменений.
  • (market_id, 1000, 1000) → предыдущие 1000 (страницей раньше) — повторяй с from += 1000, чтобы дозагружать более старую историю.

График: x = timestamp (unix-секунды), по одной линии на исход i с y = weights[i] (или нормированно weights[i] / Σweights — вменённая вероятность).

Вычисляемые DTO

  • pm_position — ставка + expected_payout (выплата, если сторона победит, или реализованная после расчёта; байт-в-байт повторяет settle_market), market_status, resolved_outcome.
  • pm_oracle — объект оракула + reliability_score (bp [0..10000], неконсенсусная эвристика: смесь доли успешных разрешений и доли выигранных споров минус штраф за баны).
  • pm_market_weight_sumsbets_sum/weight_sum по сторонам/исходам (веса считаются сканом ставок, т.к. не хранятся).
  • pm_kline — одна точка графика: seq (uint32, 0-based, монотонный индекс изменения по рынку), timestamp (unix-секунды, x), reason (uint8: 0 ставка, 1 отмена, 2 ликвидация, 3 batch settle, 4 открытие плеча, 5 расчёт плеча), bets_sum (всего поставлено), weights[] (вес по каждому исходу, y; индекс = outcome_index).
  • pm_dispute_votes — голоса + подсчёт finalize. Старые поля (вес = |vote_percent|, не стейк): uphold_weight/challenge_weight/total_weight, challenger_leads (≥ pm_dispute_approve_min_percent), proposed_outcome. Точная stake-взвешенная проекция (зеркалит pm_dispute_finalize; все *_shares в vesting-shares = effective_vesting_shares + стейк lazy-пула→shares): participation_shares (Σ веса проголосовавших), electorate_shares (total_vesting_shares + NAV пула→shares), quorum_required_shares, quorum_percent_bp (кворум в bp, 10000 = 100.00%), quorum_reached (bool), oracle_defense_shares/change_shares, outcome_change_shares[] (по исходам), expected_uphold (останется ли решение оракула), expected_outcome (какой исход будет выставлен при резолюции сейчас), expected_consensus_strength_bp. Проекция совпадает с тем, что крон применит на voting_end_time при текущих голосах (голоса изменяемы до этого момента).

pm_market_full — обогащённое представление рынка за один вызов (oracle/meta = null, когда отсутствуют; массивы my_* пусты, если не передан аргумент account):

{ market: pm_market_object,
  outcomes: pm_outcome_object[],            // пусто для бинарных рынков
  weight_sums: pm_market_weight_sums,
  oracle: pm_oracle | null,
  meta: pm_market_meta_object | null,
  my_positions: pm_position[],              // ставки аккаунта на ЭТОМ рынке
  my_leverage_positions: pm_leverage_position_object[],
  my_liquidity: pm_liquidity_object[] }

pm_leverage_quote — превью открытия плеча (из pm::leverage::*, та же математика, что и в эвалуаторе):

{ available: bool, outcome_index, collateral,
  max_loan, max_leverage_x100,              // 100 = 1.00×
  pool_free_amount, fund_available, per_position_cap, market_position_cap,
  pool_profit_percent, safety_margin_percent, max_slippage_percent, m_factor_percent,
  expiration_buffer_sec, auto_close_time,   // betting_expiration − buffer
  stops: [ { leverage_x100, loan, total_bet, expected_tokens, pool_profit,
             liquidation_threshold, current_cancel_value, worst_case_cancel_value } ],
  failed_constraints: [ { constraint, reason } ] }   // заполнено, когда !available

pm_leverage_close_preview{ position_id, outcome_index, cancel_value, pool_obligation, bettor_receives, collateral, loan, pool_profit_charge, closeable: bool, loss_vs_collateral, loss_percent_bp }. pm_leverage_convert_preview{ position_id, outcome_index, cancel_value, pool_obligation, current_profit, conversion_profit_cost_percent, conversion_fee, total_user_payment, convertible: bool }.

pm_market_categories — браузинг-таксономия с живыми счётчиками:

{ categories: [ { category, count, subcategories: [ { subcategory, count } ] } ],  // сортировка по count убыв.
  hot_tags:   [ { tag, count } ] }                                                 // топ-20 (jurisdiction-* исключены)

Пример

Последние 1000 точек графика для рынка 42, затем предыдущие 1000:

bash
# новейшая страница
curl -s --data '{"jsonrpc":"2.0","id":1,"method":"call",
  "params":["prediction_market_api","get_market_kline",[42,0,1000]]}' http://127.0.0.1:8090
# страницей старше
curl -s --data '{"jsonrpc":"2.0","id":1,"method":"call",
  "params":["prediction_market_api","get_market_kline",[42,1000,1000]]}' http://127.0.0.1:8090

Тонкий клиент (дозагрузка старой истории при прокрутке назад) — каждая точка в серию { x: unixtime, y: weight } по исходам:

js
async function call(method, params) {
  const r = await fetch('http://127.0.0.1:8090', { method: 'POST',
    body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'call',
      params: ['prediction_market_api', method, params] }) });
  return (await r.json()).result;
}

// Страницы по 1000 от новейших назад, пока не наберём `want` точек (или не кончится история).
async function loadKline(marketId, want = 3000) {
  const points = [];
  for (let from = 0; points.length < want; from += 1000) {
    const page = await call('get_market_kline', [marketId, from, 1000]);
    if (!page.length) break;            // дошли до начала истории
    points.unshift(...page);            // страницы по возрастанию; старые — в начало
    if (page.length < 1000) break;
  }
  return points;
}

// По одной серии {x,y} на исход — напрямую в любую библиотеку графиков.
function toSeries(points, outcomeCount) {
  const series = Array.from({ length: outcomeCount }, () => []);
  for (const p of points)
    for (let i = 0; i < outcomeCount; i++)
      series[i].push({ x: p.timestamp, y: Number(p.weights[i]) });
  return series;
}

См. Операции прогнозных рынков и Chain Properties.