syntax = "proto2";

// Represnts a list of tasks to be performed by a switchboard oracle.
message OracleJob {
  // The adapter will report the text body of a successful HTTP request to the specified url, 
  // or return an error if the response status code is greater than or equal to 400.
  // @return string representation of it's output.
  message HttpTask {
    // An enumeration representing the types of HTTP requests available to make.
    enum Method {
      // Unset HTTP method will default to METHOD_GET
      METHOD_UNKOWN = 0;
      // Perform an HTTP 'GET' request.
      METHOD_GET = 1;
      // Perform an HTTP 'POST' request.
      METHOD_POST = 2;
    }

    // An object that represents a header to add to an HTTP request.
    message Header {
      optional string key = 1;
      optional string value = 2;
    }
    // A string containing the URL to direct this HTTP request to.
    optional string url = 1;

    // The type of HTTP request to make.
    optional Method method = 2;

    // A list of headers to add to this HttpTask.
    repeated Header headers = 3;

    // A stringified body (if any) to add to this HttpTask.
    optional string body = 4;
  }

  // The adapter walks the path specified and returns the value found at that result. If returning
  // JSON data from the HttpGet or HttpPost adapters, you must use this adapter to parse the 
  // response.
  message JsonParseTask {
    // JSONPath formatted path to the element. https://t.ly/uLtw
    // https://www.npmjs.com/package/jsonpath-plus
    optional string path = 1;

    // The methods of combining a list of numerical results.
    enum AggregationMethod {
      NONE = 0;
      // Grab the minimum value of the results.
      MIN = 1;
      // Grab the maximum value of the results.
      MAX = 2;
      // Sum up all of the results.
      SUM = 3;
    } 
    // The technique that will be used to aggregate the results if walking the specified path
    // returns multiple numerical results.
    optional AggregationMethod aggregation_method = 2;
  }

  // Returns the median of all the results returned by the provided subtasks and subjobs. Nested tasks must return a Number.
  message MedianTask {
    // A list of subtasks to process and produce a list of result values.
    repeated Task tasks = 1;
    // A list of subjobs to process and produce a list of result values.
    repeated OracleJob jobs = 2;
    optional int32 min_successful_required = 3;
  }

  // Returns the mean of all the results returned by the provided subtasks and subjobs.
  message MeanTask {
    // A list of subtasks to process and produce a list of result values.
    repeated Task tasks = 1;
    // A list of subjobs to process and produce a list of result values.
    repeated OracleJob jobs = 2;
  }

  // Returns the maximum value of all the results returned by the provided subtasks and subjobs.
  message MaxTask {
    // A list of subtasks to process and produce a list of result values.
    repeated Task tasks = 1;
    // A list of subjobs to process and produce a list of result values.
    repeated OracleJob jobs = 2;
  }

  // Returns a specified value.
  message ValueTask {
    oneof Value {
      // The value that will be returned from this task.
      double value = 1;
      // Specifies an aggregatorr to pull the value of.
      string aggregator_pubkey = 2;
      // A stringified big.js. `Accepts variable expansion syntax.`
      string big = 3;
    }
  }

  // Opens and maintains a websocket for light speed data retrieval.
  message WebsocketTask {
    // The websocket url.
    optional string url = 1;
    // The websocket message to notify of a new subscription.
    optional string subscription = 2;
    // Minimum amount of time required between when the horses are taking out.
    optional int32 max_data_age_seconds = 3;
    // Incoming message JSONPath filter.
    // Example: "$[?(@.channel == 'ticker' && @.market == 'BTC/USD')]"
    optional string filter = 4;
  }

  // This task will run the `attempt` subtasks in an effort to produce a valid numerical result. If
  // `attempt` fails to produce an acceptable result, `on_failure` subtasks will be run instead. 
  message ConditionalTask {
    // A list of subtasks to process in an attempt to produce a valid numerical result.
    repeated Task attempt = 1;
    // A list of subtasks that will be run if `attempt` subtasks are unable to produce an acceptable
    // result.
    repeated Task on_failure = 2;
  }

  // This task will divide a numerical input by a scalar value or by another
  // aggregate.
  message DivideTask {
    oneof Denominator {
      // Specifies a basic scalar denominator to divide by.
      double scalar = 1;
      // Specifies another aggregator resut to divide by.
      string aggregator_pubkey = 2;
      // A job whose result is computed before dividing our numerical input by that result.
      OracleJob job = 3;
      // A stringified big.js. `Accepts variable expansion syntax.`
      string big = 4;
    }
  }

  // This task will multiply a numerical input by a scalar value or by another aggregator.
  message MultiplyTask {
    oneof Multiple {
      // Specifies a scalar to multiply by.
      double scalar = 1;
      // Specifies an aggregator to multiply by.
      string aggregator_pubkey = 2;
      // A job whose result is computed before multiplying our numerical input by that result.
      OracleJob job = 3;
      // A stringified big.js. `Accepts variable expansion syntax.`
      string big = 4;
    }
  }

  // This task will add a numerical input by a scalar value or by another
  // aggregate.
  message AddTask {
    oneof Addition {
      // Specifies a scalar to add by.
      double scalar = 1;
      // Specifies an aggregator to add by.
      string aggregator_pubkey = 2;
      // A job whose result is computed before adding our numerical input by that result.
      OracleJob job = 3;
      // A stringified big.js. `Accepts variable expansion syntax.`
      string big = 4;
    }
  }

  // This task will subtract a numerical input by a scalar value or by another
  // aggregate.
  message SubtractTask {
    oneof Subtraction {
      // Specifies a scalar to subtract by.
      double scalar = 1;
      // Specifies an aggregator to subtract by.
      string aggregator_pubkey = 2;
      // A job whose result is computed before subtracting our numerical input by that result.
      OracleJob job = 3;
      // A stringified big.js. `Accepts variable expansion syntax.`
      string big = 4;
    }
  }

  // Fetch LP token price info from a number of supported exchanges.
  message LpTokenPriceTask {
    oneof PoolAddress {
      // Mercurial finance pool address. A full list can be found here: https://github.com/mercurial-finance/stable-swap-n-pool-js
      string mercurial_pool_address = 1;
      // Saber pool address. A full list can be found here: https://github.com/saber-hq/saber-registry-dist
      string saber_pool_address = 2;
      // Orca pool address. A full list can be found here: https://www.orca.so/pools
      string orca_pool_address = 3;
      // The Raydium liquidity pool ammId. A full list can be found here: https://sdk.raydium.io/liquidity/mainnet.json
      string raydium_pool_address = 4;
    }
    // A list of Switchboard aggregator accounts used to calculate the fair LP price. This ensures the price is based on the previous round to mitigate flash loan price manipulation.
    repeated string price_feed_addresses = 5;
    repeated OracleJob price_feed_jobs = 6;
    // If enabled and price_feed_addresses provided, the oracle will calculate the fair LP price based on the liquidity pool reserves. See our blog post for more information: https://switchboardxyz.medium.com/fair-lp-token-oracles-94a457c50239
    optional bool use_fair_price = 7;
  }

  // Fetch the current swap price for a given liquidity pool
  message LpExchangeRateTask {
    // Not Used
    optional string in_token_address = 1;
    // Not Used
    optional string out_token_address = 2;
    oneof PoolAddress {
      // Mercurial finance pool address. A full list can be found here: https://github.com/mercurial-finance/stable-swap-n-pool-js
      string mercurial_pool_address = 3;
      // Saber pool address. A full list can be found here: https://github.com/saber-hq/saber-registry-dist
      string saber_pool_address = 4;
      // 	Orca pool address. A full list can be found here: https://www.orca.so/pools
      string orca_pool_token_mint_address = 5;
      // The Raydium liquidity pool ammId. A full list can be found here: https://sdk.raydium.io/liquidity/mainnet.json
      string raydium_pool_address = 6;
    }
  }


  // Find a pattern within a string of a previous task and extract a group number.
  message RegexExtractTask {
    // Regex pattern to find.
    optional string pattern = 1;
    // Group number to extract.
    optional int32 group_number = 2;
  }

  message XStepPriceTask {
    oneof StepSource {
      // median task containing the job definitions to fetch the STEP/USD price
      MedianTask step_job = 1;
      // existing aggregator pubkey for STEP/USD
      string step_aggregator_pubkey = 2;
    }
  }

  // Takes a twap over a set period for a certain aggregator.
  message TwapTask {
    // The target aggregator for the TWAP.
    optional string aggregator_pubkey = 1;
    // Period, in seconds, the twap should account for
    optional int32 period = 2;
    // Weight samples by their propagation time
    optional bool weight_by_propagation_time = 3;
    // Minimum number of samples in the history to calculate a valid result
    optional uint32 min_samples = 4;
    // Ending unix timestamp to collect values up to
    optional int32 ending_unix_timestamp = 5;
  }

  // Fetch the latest swap price on Serum's orderbook
  message SerumSwapTask {
    // The serum pool to fetch swap price for
    optional string serum_pool_address = 1;
  }

  // Take the power of the working value.
  message PowTask {
    oneof Exponent {
      // Take the working value to the exponent of value.
      double scalar = 1;
      // Take the working value to the exponent of the aggregators value.
      string aggregator_pubkey = 2;
      // A stringified big.js. `Accepts variable expansion syntax.`
      string big = 3;
    }
  }

  // Fetch the lending rates for various Solana protocols
  message LendingRateTask {
    // 01, apricot, francium, jet, larix, mango, port, solend, tulip
    optional string protocol = 1;
    // A token mint address supported by the chosen protocol
    optional string asset_mint = 2;
    enum Field {
      // deposit lending rate
      FIELD_DEPOSIT_RATE = 0;
      // borrow lending rate
      FIELD_BORROW_RATE = 1;
    }
    optional Field field = 3;
  }

  // Fetch the current price for a Mango perpetual market
  message MangoPerpMarketTask {
    // Mainnet address for a mango perpetual market. A full list can be found here: https://github.com/blockworks-foundation/mango-client-v3/blob/main/src/ids.json
    optional string perp_market_address = 1;
  }
  
  // Fetch the simulated price for a swap on JupiterSwap.
  message JupiterSwapTask {
    // The input token address.
    optional string in_token_address = 1;
    // The output token address.
    optional string out_token_address = 2;
    // The amount of tokens to swap.
    optional double base_amount = 3;
  }

  // Fetch the current price of a perpetual market.
  message PerpMarketTask {
    oneof MarketAddress {
      // Market address for a mango perpetual market. A full list can be found here: https://github.com/blockworks-foundation/mango-client-v3/blob/main/src/ids.json
      string mango_market_address = 1;
      // Market address for a drift perpetual market. A full list can be found here: https://github.com/drift-labs/protocol-v1/blob/master/sdk/src/constants/markets.ts
      string drift_market_address = 2;
      // Market address for a zeta perpetual market.
      string zeta_market_address = 3;
      // Market address for a 01 protocol perpetual market.
      string zo_market_address = 4;
    }
  }

  // Fetch the current price of a Solana oracle protocol.
  message OracleTask {
    oneof AggregatorAddress {
      // Mainnet address of a Switchboard V2 feed. Switchboard is decentralized and allows anyone to build their own feed. A small subset of feeds is available here: https://switchboard.xyz/explorer
      string switchboard_address = 1;
      // Mainnet address for a Pyth feed. A full list can be found here: https://pyth.network/markets/
      string pyth_address = 2;
      // Mainnet address for a Chainlink feed. A full list can be found here: https://docs.chain.link/docs/solana/data-feeds-solana
      string chainlink_address = 3;
    }
    // Value (as a percentage) that the lower bound confidence interval is of the actual value.
    // Confidence intervals that are larger that this treshold are rejected.
    optional double pyth_allowed_confidence_interval = 4;
  }
  
  // Load a parse an Anchor based solana account.
  message AnchorFetchTask {
    // Owning program of the account to parse.
    optional string program_id = 1;
    // The account to parse.
    optional string account_address = 2;
  }


  // Fetch the current transactions per second.
  message TpsTask {}
  // Fetch the JSON representation of an SPL Stake Pool account.
  message SplStakePoolTask {
    // The pubkey of the SPL Stake Pool.
    optional string pubkey = 1;
  }

  // Fetch the JSON representation of an SPL token mint.
  message SplTokenParseTask {
    oneof AccountAddress {
      // The publicKey of a token account to fetch the mintInfo for.
      string token_account_address = 1;
      // The publicKey of the token mint address.
      string mint_address = 2;
    }
  }

  // Fetch the swap price from DefiKingdoms.
  message DefiKingdomsTask {
    message Token {
      // The address of the token.
      optional string address = 1;
      // The number of decimal places for a token.
      optional int32 decimals = 2;
    }
    // The RPC provider to use for the swap.
    optional string provider = 1;
    // The input token of the swap.
    optional Token in_token = 2;
    // The output token of the swap.
    optional Token out_token = 3;
  }

  // Fetch the swap price from UniSwap.
  message UniswapExchangeRateTask {
    // The input token address.
    optional string in_token_address = 1;
    // The output token address.
    optional string out_token_address = 2;
    // The amount of tokens to swap.
    optional double in_token_amount = 3;
    // The allowable slippage in percent for the swap.
    optional double slippage = 4;
    // The RPC provider to use for the swap.
    optional string provider = 5;
  }

  // Fetch the swap price from SushiSwap.
  message SushiswapExchangeRateTask {
     // The input token address.
    optional string in_token_address = 1;
    // The output token address.
    optional string out_token_address = 2;
    // The amount of tokens to swap.
    optional double in_token_amount = 3;
    // The allowable slippage in percent for the swap.
    optional double slippage = 4;
    // The RPC provider to use for the swap.
    optional string provider = 5;
  }

  // Fetch the swap price from PancakeSwap.
  message PancakeswapExchangeRateTask {
     // The input token address.
    optional string in_token_address = 1;
    // The output token address.
    optional string out_token_address = 2;
    // The amount of tokens to swap.
    optional double in_token_amount = 3;
    // The allowable slippage in percent for the swap.
    optional double slippage = 4;
    // The RPC provider to use for the swap.
    optional string provider = 5;
  }


  // Execute a job and store the result in a variable to reference later.
  message CacheTask {
    message CacheItem {
      // The name of the variable to store in cache to reference later with `${VARIABLE_NAME}`.
      optional string variable_name = 1;
      // The OracleJob to execute to yield the value to store in cache.
      optional OracleJob job = 2;
    }
    // A list of cached variables to reference in the job with `${VARIABLE_NAME}`.
    repeated CacheItem cache_items = 1;
  }
  
  // Return the difference between an oracle's clock and the current timestamp at `SYSVAR_CLOCK_PUBKEY`.
  message SysclockOffsetTask {}

  message MarinadeStateTask {}

  // Fetch the account data in a stringified buffer format.
  message SolanaAccountDataFetchTask {
    // The on-chain account to fetch the account data from.
    optional string pubkey = 1;
  }

  // Return the deserialized value from a stringified buffer.
  message BufferLayoutParseTask {
    // The buffer offset to start deserializing from.
    optional uint32 offset = 1;
    enum Endian {
      LITTLE_ENDIAN = 0;
      BIG_ENDIAN = 1;
    }
    // The endianness of the stored value.
    optional Endian endian = 2;
    enum BufferParseType {
      // A public key.
      pubkey = 1;
      // A boolean.
      bool = 2;
      // An 8-bit unsigned value.
      u8 = 3;
      // An 8-bit signed value.
      i8 = 4;
      // A 16-bit unsigned value.
      u16 = 5;
      // A 16-bit signed value.
      i16 = 6;
      // A 32-bit unsigned value.
      u32 = 7;
      // A 32-bit signed value.
      i32 = 8;
      // A 32-bit IEEE floating point value.
      f32 = 9;
      // A 64-bit unsigned value.
      u64 = 10;
       // A 64-bit signed value.
      i64 = 11;
      // A 64-bit IEEE floating point value.
      f64 = 12;
      // A 128-bit unsigned value.
      u128 = 13;
      // A 128-bit signed value.
      i128 = 14;
    }
    // The type of value to deserialize.
    optional BufferParseType type = 3;
  }

  message Task {
    oneof Task {
      HttpTask http_task = 1;
      JsonParseTask json_parse_task = 2;
      MedianTask median_task = 4;
      MeanTask mean_task = 5;
      WebsocketTask websocket_task = 6;
      DivideTask divide_task = 7;
      MultiplyTask multiply_task = 8;
      LpTokenPriceTask lp_token_price_task = 9;
      LpExchangeRateTask lp_exchange_rate_task = 10;
      ConditionalTask conditional_task = 11;
      ValueTask value_task = 12;
      MaxTask max_task = 13;
      RegexExtractTask regex_extract_task = 14;
      XStepPriceTask xstep_price_task = 15;
      AddTask add_task = 16;
      SubtractTask subtract_task = 17;
      TwapTask twap_task = 18;
      SerumSwapTask serum_swap_task = 19;
      PowTask pow_task = 20;
      LendingRateTask lending_rate_task = 21;
      MangoPerpMarketTask mango_perp_market_task = 22;
      JupiterSwapTask jupiter_swap_task = 23;
      PerpMarketTask perp_market_task = 24;
      OracleTask oracle_task = 25;
      AnchorFetchTask anchor_fetch_task = 26;
      DefiKingdomsTask defi_kingdoms_task = 27;
      TpsTask tps_task = 28;
      SplStakePoolTask spl_stake_pool_task = 29;
      SplTokenParseTask spl_token_parse_task = 30;
      UniswapExchangeRateTask uniswap_exchange_rate_task = 31;
      SushiswapExchangeRateTask sushiswap_exchange_rate_task = 32;
      PancakeswapExchangeRateTask pancakeswap_exchange_rate_task = 33;
      CacheTask cache_task = 34;
      SysclockOffsetTask sysclock_offset_task = 35;
      MarinadeStateTask marinade_state_task = 36;
      SolanaAccountDataFetchTask solana_account_data_fetch_task = 37;
      BufferLayoutParseTask buffer_layout_parse_task = 38;
    }
  }
  // The chain of tasks to perform for this OracleJob.
  repeated Task tasks = 1;

}
