syntax = "proto3";

// Public wire schema for Synthetic Book WebSocket snapshots and deltas.
package kairos.synthetic.v1;

enum OutputMode {
  OUTPUT_MODE_UNSPECIFIED = 0;
  OUTPUT_MODE_BBO = 1;
  OUTPUT_MODE_AGGREGATED_L2 = 2;
  OUTPUT_MODE_DECOMPOSED_L2 = 3;
  OUTPUT_MODE_UNION_L2 = 4;
}

enum Classification {
  CLASSIFICATION_UNSPECIFIED = 0;
  CLASSIFICATION_ARBITRARY_BASKET = 1;
  CLASSIFICATION_RELATIVE_VALUE = 2;
  CLASSIFICATION_EXACT_EQUIVALENCE = 3;
  CLASSIFICATION_COMPLEMENT = 4;
  CLASSIFICATION_PARTITION = 5;
  CLASSIFICATION_IMPLICATION = 6;
  CLASSIFICATION_RANGE = 7;
  CLASSIFICATION_GUARANTEED_PAYOUT = 8;
}

enum FeeModelKind {
  FEE_MODEL_KIND_UNSPECIFIED = 0;
  FEE_MODEL_KIND_NONE = 1;
  FEE_MODEL_KIND_CURVE_RATE_PPM = 2;
  FEE_MODEL_KIND_MIN_SIDE_BPS = 3;
  FEE_MODEL_KIND_NOTIONAL_BPS = 4;
}

message FeeModel {
  FeeModelKind kind = 1;
  uint32 param = 2;
  bool is_estimate = 3;
  int64 resolved_at_ms = 4;
}

message DefinitionLeg {
  string venue = 1;
  string token_id = 2;
  int64 weight_nano = 3;
  FeeModel fee = 4;
}

message SyntheticDefinition {
  string synthetic_id = 1;
  repeated DefinitionLeg legs = 2;
  uint32 formula_version = 3;
  OutputMode output_mode = 4;
  uint32 requested_depth = 5;
  Classification classification = 6;
}

enum LegAction {
  LEG_ACTION_UNSPECIFIED = 0;
  LEG_ACTION_BUY = 1;
  LEG_ACTION_SELL = 2;
}

enum SourceStatus {
  SOURCE_STATUS_UNSPECIFIED = 0;
  SOURCE_STATUS_BOOTSTRAPPING = 1;
  SOURCE_STATUS_LIVE = 2;
  SOURCE_STATUS_GAPPED = 3;
  SOURCE_STATUS_STALE = 4;
  SOURCE_STATUS_WITHDRAWN = 5;
}

enum MaterializationStatus {
  MATERIALIZATION_STATUS_UNSPECIFIED = 0;
  MATERIALIZATION_STATUS_EXECUTABLE = 1;
  MATERIALIZATION_STATUS_SOURCE_MISSING = 2;
  MATERIALIZATION_STATUS_SOURCE_NOT_LIVE = 3;
  MATERIALIZATION_STATUS_NO_LIQUIDITY = 4;
  MATERIALIZATION_STATUS_ARITHMETIC_OVERFLOW = 5;
}

message RecipeLeg {
  string venue = 1;
  string token_id = 2;
  LegAction action = 3;
  int64 price_nano = 4;
  int64 qty_nano = 5;
  int64 weight_nano = 6;
  uint64 source_seq = 7;
  uint64 source_epoch = 8;
}

message SyntheticLevel {
  int64 price_nano = 1;
  int64 qty_nano = 2;
  repeated RecipeLeg recipes = 3;
}

message InputVersion {
  string venue = 1;
  string token_id = 2;
  uint64 seq = 3;
  uint64 epoch = 4;
  int64 exchange_timestamp_us = 5;
  int64 received_ms = 6;
  SourceStatus status = 7;
}

message SyntheticSnapshot {
  string synthetic_id = 1;
  uint64 synthetic_sequence = 2;
  uint32 definition_version = 3;
  MaterializationStatus status = 4;
  repeated SyntheticLevel bids = 5;
  repeated SyntheticLevel asks = 6;
  bool bids_source_exhausted = 7;
  bool asks_source_exhausted = 8;
  repeated InputVersion inputs = 9;
  int64 calculated_at_ms = 10;
  int64 max_input_age_ms = 11;
  int64 cross_venue_skew_ms = 12;
  int64 valid_until_ms = 13;
  uint32 price_unit_exponent = 14;
  uint32 qty_unit_exponent = 15;
  string publisher_instance_id = 16;
  uint64 ownership_epoch = 17;
  SyntheticDefinition definition = 18;
}

enum BookSide {
  BOOK_SIDE_UNSPECIFIED = 0;
  BOOK_SIDE_BID = 1;
  BOOK_SIDE_ASK = 2;
}

message SyntheticLevelChange {
  BookSide side = 1;
  int64 price_nano = 2;
  int64 qty_nano = 3;
  repeated RecipeLeg recipes = 4;
}

message InputVersionChange {
  uint32 leg_index = 1;
  uint64 seq = 2;
  uint64 epoch = 3;
  int64 exchange_timestamp_us = 4;
  int64 received_ms = 5;
  SourceStatus status = 6;
}

message SyntheticDelta {
  string synthetic_id = 1;
  uint64 synthetic_sequence = 2;
  uint64 previous_sequence = 3;
  uint64 ownership_epoch = 4;
  string publisher_instance_id = 5;
  MaterializationStatus status = 6;
  repeated SyntheticLevelChange changes = 7;
  repeated InputVersionChange inputs = 8;
  bool bids_source_exhausted = 9;
  bool asks_source_exhausted = 10;
  int64 calculated_at_ms = 11;
  int64 max_input_age_ms = 12;
  int64 cross_venue_skew_ms = 13;
  int64 valid_until_ms = 14;
  uint32 price_unit_exponent = 15;
  uint32 qty_unit_exponent = 16;
}

// Top of book on the `synthetic.quote` topic, frame tag 0x53.
message SyntheticQuote {
  string synthetic_id = 1;
  uint64 synthetic_sequence = 2;
  uint64 ownership_epoch = 3;
  MaterializationStatus status = 4;
  SyntheticLevel best_bid = 5;
  SyntheticLevel best_ask = 6;
  int64 calculated_at_ms = 7;
  uint32 price_unit_exponent = 8;
  uint32 qty_unit_exponent = 9;
}
