diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index 21a7ae7..76cf266 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -4,7 +4,7 @@ on: push: branches: - main - + pull_request: branches: - main diff --git a/.github/workflows/rustfmt.yaml b/.github/workflows/rustfmt.yaml new file mode 100644 index 0000000..551757d --- /dev/null +++ b/.github/workflows/rustfmt.yaml @@ -0,0 +1,19 @@ +name: Check Rustfmt + +on: + pull_request: + push: + branches: [main] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + components: rustfmt + - uses: pre-commit/action@v2.0.3 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..b8c11f0 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,14 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.2.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-added-large-files + - repo: local + hooks: + - id: cargo-fmt-nightly + name: rustfmt + language: "rust" + entry: cargo +nightly fmt + pass_filenames: false diff --git a/flake.nix b/flake.nix index 1180ad3..df4c679 100644 --- a/flake.nix +++ b/flake.nix @@ -30,12 +30,12 @@ { self , nixpkgs , fenix - , flake-utils + , flake-utils }: # Generate a Flake Configuration for each supported system. - flake-utils.lib.eachDefaultSystem (system: - let + flake-utils.lib.eachDefaultSystem (system: + let pkgs = nixpkgs.legacyPackages.${system}; shell = import ./shell.nix { inherit pkgs; }; rust = pkgs.makeRustPlatform { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 7aa8fb2..08098e4 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -3,5 +3,5 @@ channel = "stable" profile = "minimal" components = [ "rustfmt", - "clippy" + "clippy" ] diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..cb9076f --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,17 @@ +# Merge all imports into a clean vertical list of module imports. +imports_granularity = "One" +group_imports = "One" +imports_layout = "Vertical" + +# Better grep-ability. +empty_item_single_line = false + +# Consistent pipe layout. +match_arm_leading_pipes = "Preserve" + +# Align Fields +enum_discrim_align_threshold = 80 +struct_field_align_threshold = 80 + +# Allow up to two blank lines for visual grouping. +blank_lines_upper_bound = 2 diff --git a/src/publisher/pythd/adapter.rs b/src/publisher/pythd/adapter.rs index d22f8eb..aa050d8 100644 --- a/src/publisher/pythd/adapter.rs +++ b/src/publisher/pythd/adapter.rs @@ -1,16 +1,42 @@ -use std::{collections::HashMap, time::Duration}; - -use super::super::store::{global, PriceIdentifier}; -use super::api::{ - self, Conf, NotifyPrice, NotifyPriceSched, Price, PriceAccountMetadata, ProductAccount, - ProductAccountMetadata, SubscriptionID, -}; -use anyhow::{anyhow, Result}; -use pyth_sdk::Identifier; -use slog::Logger; -use tokio::{ - sync::{broadcast, mpsc, oneshot}, - time::{self, Interval}, +use { + super::{ + super::store::{ + global, + PriceIdentifier, + }, + api::{ + self, + Conf, + NotifyPrice, + NotifyPriceSched, + Price, + PriceAccountMetadata, + ProductAccount, + ProductAccountMetadata, + SubscriptionID, + }, + }, + anyhow::{ + anyhow, + Result, + }, + pyth_sdk::Identifier, + slog::Logger, + std::{ + collections::HashMap, + time::Duration, + }, + tokio::{ + sync::{ + broadcast, + mpsc, + oneshot, + }, + time::{ + self, + Interval, + }, + }, }; /// Adapter is the adapter between the pythd websocket API, and the stores. @@ -42,7 +68,7 @@ pub struct Adapter { /// Represents a single Notify Price Sched subscription struct NotifyPriceSchedSubscription { /// ID of this subscription - subscription_id: SubscriptionID, + subscription_id: SubscriptionID, /// Channel notifications are sent on notify_price_sched_tx: mpsc::Sender, } @@ -53,27 +79,27 @@ pub enum Message { result_tx: oneshot::Sender>>, }, GetProduct { - account: api::Pubkey, + account: api::Pubkey, result_tx: oneshot::Sender>, }, GetAllProducts { result_tx: oneshot::Sender>>, }, SubscribePrice { - account: api::Pubkey, + account: api::Pubkey, notify_price_tx: mpsc::Sender, - result_tx: oneshot::Sender>, + result_tx: oneshot::Sender>, }, SubscribePriceSched { - account: api::Pubkey, + account: api::Pubkey, notify_price_sched_tx: mpsc::Sender, - result_tx: oneshot::Sender>, + result_tx: oneshot::Sender>, }, UpdatePrice { account: api::Pubkey, - price: Price, - conf: Conf, - status: String, + price: Price, + conf: Conf, + status: String, }, } @@ -172,17 +198,17 @@ impl Adapter { .map(|acc| (price_account_key, acc)) }) .map(|(price_account_key, price_account)| PriceAccountMetadata { - account: price_account_key.to_string(), - price_type: "price".to_owned(), + account: price_account_key.to_string(), + price_type: "price".to_owned(), price_exponent: price_account.expo as i64, }) .collect(); // Create the product account metadata struct result.push(ProductAccountMetadata { - account: product_account_key.to_string(), + account: product_account_key.to_string(), attr_dict: product_account.attr_dict, - prices: price_accounts_metadata, + prices: price_accounts_metadata, }) } @@ -235,30 +261,44 @@ impl Adapter { #[cfg(test)] mod tests { - use iobuffer::IoBuffer; - use slog_extlog::slog_test; - use std::{ - collections::{BTreeMap, HashMap}, - str::FromStr, - time::Duration, - }; - use tokio::{ - sync::{broadcast, mpsc, oneshot}, - task::JoinHandle, - }; - - use crate::publisher::{ - pythd::api::{NotifyPriceSched, PriceAccountMetadata, ProductAccountMetadata}, - store::global, + use { + super::{ + Adapter, + Message, + }, + crate::publisher::{ + pythd::api::{ + NotifyPriceSched, + PriceAccountMetadata, + ProductAccountMetadata, + }, + store::global, + }, + iobuffer::IoBuffer, + slog_extlog::slog_test, + std::{ + collections::{ + BTreeMap, + HashMap, + }, + str::FromStr, + time::Duration, + }, + tokio::{ + sync::{ + broadcast, + mpsc, + oneshot, + }, + task::JoinHandle, + }, }; - use super::{Adapter, Message}; - struct TestAdapter { - message_tx: mpsc::Sender, - shutdown_tx: broadcast::Sender<()>, + message_tx: mpsc::Sender, + shutdown_tx: broadcast::Sender<()>, global_store_rx: mpsc::Receiver, - jh: JoinHandle<()>, + jh: JoinHandle<()>, } impl Drop for TestAdapter { @@ -317,7 +357,7 @@ mod tests { assert_eq!( notify_price_sched_rx.recv().await.unwrap(), NotifyPriceSched { - subscription: subscription_id + subscription: subscription_id, } ) } @@ -332,7 +372,7 @@ mod tests { ) .unwrap(), global::ProductAccountMetadata { - attr_dict: BTreeMap::from( + attr_dict: BTreeMap::from( [ ("symbol", "Crypto.LTC/USD"), ("asset_type", "Crypto"), @@ -365,7 +405,7 @@ mod tests { ) .unwrap(), global::ProductAccountMetadata { - attr_dict: BTreeMap::from( + attr_dict: BTreeMap::from( [ ("symbol", "Crypto.ETH/USD"), ("asset_type", "Crypto"), @@ -393,7 +433,7 @@ mod tests { }, ), ]), - price_accounts_metadata: HashMap::from([ + price_accounts_metadata: HashMap::from([ ( solana_sdk::pubkey::Pubkey::from_str( "GVXRSBjFk6e6J3NbVPXohDJetcTjaeeuykUpbQF8UoMU", @@ -464,7 +504,7 @@ mod tests { // Check that the result is what we expected let expected = vec![ ProductAccountMetadata { - account: "BjHoZWRxo9dgbR1NQhPyTiUs6xFiX6mGS4TMYvy3b2yc".to_string(), + account: "BjHoZWRxo9dgbR1NQhPyTiUs6xFiX6mGS4TMYvy3b2yc".to_string(), attr_dict: BTreeMap::from( [ ("symbol", "Crypto.ETH/USD"), @@ -476,26 +516,26 @@ mod tests { ] .map(|(k, v)| (k.to_string(), v.to_string())), ), - prices: vec![ + prices: vec![ PriceAccountMetadata { - account: "GG3FTE7xhc9Diy7dn9P6BWzoCrAEE4D3p5NBYrDAm5DD".to_string(), - price_type: "price".to_string(), + account: "GG3FTE7xhc9Diy7dn9P6BWzoCrAEE4D3p5NBYrDAm5DD".to_string(), + price_type: "price".to_string(), price_exponent: -9, }, PriceAccountMetadata { - account: "fTNjSfj5uW9e4CAMHzUcm65ftRNBxCN1gG5GS1mYfid".to_string(), - price_type: "price".to_string(), + account: "fTNjSfj5uW9e4CAMHzUcm65ftRNBxCN1gG5GS1mYfid".to_string(), + price_type: "price".to_string(), price_exponent: -6, }, PriceAccountMetadata { - account: "GKNcUmNacSJo4S2Kq3DuYRYRGw3sNUfJ4tyqd198t6vQ".to_string(), - price_type: "price".to_string(), + account: "GKNcUmNacSJo4S2Kq3DuYRYRGw3sNUfJ4tyqd198t6vQ".to_string(), + price_type: "price".to_string(), price_exponent: 2, }, ], }, ProductAccountMetadata { - account: "CkMrDWtmFJZcmAUC11qNaWymbXQKvnRx4cq1QudLav7t".to_string(), + account: "CkMrDWtmFJZcmAUC11qNaWymbXQKvnRx4cq1QudLav7t".to_string(), attr_dict: BTreeMap::from( [ ("symbol", "Crypto.LTC/USD"), @@ -507,20 +547,20 @@ mod tests { ] .map(|(k, v)| (k.to_string(), v.to_string())), ), - prices: vec![ + prices: vec![ PriceAccountMetadata { - account: "GVXRSBjFk6e6J3NbVPXohDJetcTjaeeuykUpbQF8UoMU".to_string(), - price_type: "price".to_string(), + account: "GVXRSBjFk6e6J3NbVPXohDJetcTjaeeuykUpbQF8UoMU".to_string(), + price_type: "price".to_string(), price_exponent: -8, }, PriceAccountMetadata { - account: "3VQwtcntVQN1mj1MybQw8qK7Li3KNrrgNskSQwZAPGNr".to_string(), - price_type: "price".to_string(), + account: "3VQwtcntVQN1mj1MybQw8qK7Li3KNrrgNskSQwZAPGNr".to_string(), + price_type: "price".to_string(), price_exponent: -10, }, PriceAccountMetadata { - account: "2V7t5NaKY7aGkwytCWQgvUYZfEr9XMwNChhJEakTExk6".to_string(), - price_type: "price".to_string(), + account: "2V7t5NaKY7aGkwytCWQgvUYZfEr9XMwNChhJEakTExk6".to_string(), + price_type: "price".to_string(), price_exponent: -6, }, ], diff --git a/src/publisher/pythd/api.rs b/src/publisher/pythd/api.rs index 8753779..1a36518 100644 --- a/src/publisher/pythd/api.rs +++ b/src/publisher/pythd/api.rs @@ -4,9 +4,13 @@ // It does not implement the business logic, only exposes a websocket server which // accepts messages and can return responses in the expected format. -use std::collections::BTreeMap; - -use serde::{Deserialize, Serialize}; +use { + serde::{ + Deserialize, + Serialize, + }, + std::collections::BTreeMap, +}; pub type Pubkey = String; pub type Attrs = BTreeMap; @@ -18,56 +22,56 @@ pub type Slot = u64; #[derive(Serialize, Deserialize, Debug, Clone, Ord, PartialOrd, PartialEq, Eq)] pub struct ProductAccountMetadata { - pub account: Pubkey, + pub account: Pubkey, pub attr_dict: Attrs, - pub prices: Vec, + pub prices: Vec, } #[derive(Serialize, Deserialize, Debug, Clone, Ord, PartialOrd, PartialEq, Eq)] pub struct PriceAccountMetadata { - pub account: Pubkey, - pub price_type: String, + pub account: Pubkey, + pub price_type: String, pub price_exponent: Exponent, } #[derive(Serialize, Deserialize, Debug, Clone, Ord, PartialOrd, PartialEq, Eq)] pub struct ProductAccount { - pub account: Pubkey, - pub attr_dict: Attrs, + pub account: Pubkey, + pub attr_dict: Attrs, pub price_accounts: Vec, } #[derive(Serialize, Deserialize, Debug, Clone, Ord, PartialOrd, PartialEq, Eq)] pub struct PriceAccount { - pub account: Pubkey, - pub price_type: String, - pub price_exponent: Exponent, - pub status: String, - pub price: Price, - pub conf: Conf, - pub twap: Price, - pub twac: Price, - pub valid_slot: Slot, - pub pub_slot: Slot, - pub prev_slot: Slot, - pub prev_price: Price, - pub prev_conf: Conf, + pub account: Pubkey, + pub price_type: String, + pub price_exponent: Exponent, + pub status: String, + pub price: Price, + pub conf: Conf, + pub twap: Price, + pub twac: Price, + pub valid_slot: Slot, + pub pub_slot: Slot, + pub prev_slot: Slot, + pub prev_price: Price, + pub prev_conf: Conf, pub publisher_accounts: Vec, } #[derive(Serialize, Deserialize, Debug, Clone, Ord, PartialOrd, PartialEq, Eq)] pub struct PublisherAccount { pub account: Pubkey, - pub status: String, - pub price: Price, - pub conf: Conf, - pub slot: Slot, + pub status: String, + pub price: Price, + pub conf: Conf, + pub slot: Slot, } #[derive(Serialize, Deserialize, Debug, Clone, Ord, PartialOrd, PartialEq, Eq)] pub struct NotifyPrice { pub subscription: SubscriptionID, - pub result: PriceUpdate, + pub result: PriceUpdate, } #[derive(Serialize, Deserialize, Debug, Clone, Ord, PartialOrd, PartialEq, Eq)] @@ -79,32 +83,70 @@ pub type SubscriptionID = i64; #[derive(Serialize, Deserialize, Debug, Clone, Ord, PartialOrd, PartialEq, Eq)] pub struct PriceUpdate { - pub price: Price, - pub conf: Conf, - pub status: String, + pub price: Price, + pub conf: Conf, + pub status: String, pub valid_slot: Slot, - pub pub_slot: Slot, + pub pub_slot: Slot, } pub mod rpc { - use std::fmt::Debug; - use std::net::SocketAddr; - - use anyhow::{anyhow, Result}; - use futures_util::stream::{SplitSink, SplitStream, StreamExt}; - use futures_util::SinkExt; - use jrpc::{parse_request, ErrorCode, Id, IdReq, Request, Response, Value}; - use serde::de::DeserializeOwned; - use serde::{Deserialize, Serialize}; - - use slog::Logger; - use tokio::sync::{broadcast, mpsc, oneshot}; - use warp::ws::{Message, WebSocket, Ws}; - use warp::Filter; - - use super::super::adapter; - use super::{Conf, NotifyPrice, NotifyPriceSched, Price, Pubkey, SubscriptionID}; + use { + super::{ + super::adapter, + Conf, + NotifyPrice, + NotifyPriceSched, + Price, + Pubkey, + SubscriptionID, + }, + anyhow::{ + anyhow, + Result, + }, + futures_util::{ + stream::{ + SplitSink, + SplitStream, + StreamExt, + }, + SinkExt, + }, + jrpc::{ + parse_request, + ErrorCode, + Id, + IdReq, + Request, + Response, + Value, + }, + serde::{ + de::DeserializeOwned, + Deserialize, + Serialize, + }, + slog::Logger, + std::{ + fmt::Debug, + net::SocketAddr, + }, + tokio::sync::{ + broadcast, + mpsc, + oneshot, + }, + warp::{ + ws::{ + Message, + WebSocket, + Ws, + }, + Filter, + }, + }; #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "snake_case")] @@ -137,9 +179,9 @@ pub mod rpc { #[derive(Serialize, Deserialize, Debug, Clone)] struct UpdatePriceParams { account: Pubkey, - price: Price, - conf: Conf, - status: String, + price: Price, + conf: Conf, + status: String, } #[derive(Serialize, Deserialize, Debug, PartialEq)] @@ -384,9 +426,9 @@ pub mod rpc { self.adapter_tx .send(adapter::Message::UpdatePrice { account: params.account, - price: params.price, - conf: params.conf, - status: params.status, + price: params.price, + conf: params.conf, + status: params.status, }) .await?; @@ -469,10 +511,10 @@ pub mod rpc { #[derive(Clone, Debug, Deserialize)] pub struct Config { /// The address which the websocket API server will listen on. - listen_address: String, + listen_address: String, /// Size of the buffer of each Server's channel on which `notify_price` events are /// received from the Adapter. - notify_price_tx_buffer: usize, + notify_price_tx_buffer: usize, /// Size of the buffer of each Server's channel on which `notify_price_sched` events are /// received from the Adapter. notify_price_sched_tx_buffer: usize, @@ -481,8 +523,8 @@ pub mod rpc { impl Default for Config { fn default() -> Self { Self { - listen_address: "127.0.0.1:8910".to_string(), - notify_price_tx_buffer: 1000, + listen_address: "127.0.0.1:8910".to_string(), + notify_price_tx_buffer: 1000, notify_price_sched_tx_buffer: 1000, } } @@ -490,8 +532,8 @@ pub mod rpc { pub struct Server { adapter_tx: mpsc::Sender, - config: Config, - logger: Logger, + config: Config, + logger: Logger, } impl Server { @@ -557,34 +599,69 @@ pub mod rpc { #[cfg(test)] mod tests { - use anyhow::anyhow; - use iobuffer::IoBuffer; - use jrpc::{Id, Request}; - use rand::Rng; - use serde::de::DeserializeOwned; - use serde::Serialize; - use slog_extlog::slog_test; - use soketto::handshake::{Client, ServerResponse}; - use std::str::from_utf8; - use tokio::net::TcpStream; - use tokio::sync::{broadcast, mpsc}; - use tokio::task::JoinHandle; - use tokio_retry::strategy::FixedInterval; - use tokio_retry::Retry; - use tokio_util::compat::{Compat, TokioAsyncReadCompatExt}; - - use crate::publisher::pythd::adapter; - use crate::publisher::pythd::api::rpc::{ - SubscribePriceParams, SubscribePriceSchedParams, UpdatePriceParams, - }; - use crate::publisher::pythd::api::{NotifyPrice, NotifyPriceSched, PriceUpdate}; - - use super::super::rpc::GetProductParams; - use super::super::{ - Attrs, PriceAccount, PriceAccountMetadata, ProductAccount, ProductAccountMetadata, - Pubkey, PublisherAccount, SubscriptionID, + use { + super::{ + super::{ + rpc::GetProductParams, + Attrs, + PriceAccount, + PriceAccountMetadata, + ProductAccount, + ProductAccountMetadata, + Pubkey, + PublisherAccount, + SubscriptionID, + }, + Config, + Server, + }, + crate::publisher::pythd::{ + adapter, + api::{ + rpc::{ + SubscribePriceParams, + SubscribePriceSchedParams, + UpdatePriceParams, + }, + NotifyPrice, + NotifyPriceSched, + PriceUpdate, + }, + }, + anyhow::anyhow, + iobuffer::IoBuffer, + jrpc::{ + Id, + Request, + }, + rand::Rng, + serde::{ + de::DeserializeOwned, + Serialize, + }, + slog_extlog::slog_test, + soketto::handshake::{ + Client, + ServerResponse, + }, + std::str::from_utf8, + tokio::{ + net::TcpStream, + sync::{ + broadcast, + mpsc, + }, + task::JoinHandle, + }, + tokio_retry::{ + strategy::FixedInterval, + Retry, + }, + tokio_util::compat::{ + Compat, + TokioAsyncReadCompatExt, + }, }; - use super::{Config, Server}; struct TestAdapter { rx: mpsc::Receiver, @@ -598,7 +675,7 @@ pub mod rpc { struct TestServer { shutdown_tx: broadcast::Sender<()>, - jh: JoinHandle<()>, + jh: JoinHandle<()>, } impl Drop for TestServer { @@ -609,7 +686,7 @@ pub mod rpc { } struct TestClient { - sender: soketto::Sender>, + sender: soketto::Sender>, receiver: soketto::Receiver>, } @@ -688,8 +765,8 @@ pub mod rpc { // Define the product account we expect to receive back let product_account_key = "some_product_account".to_string(); let product_account = ProductAccount { - account: product_account_key.clone(), - attr_dict: Attrs::from( + account: product_account_key.clone(), + attr_dict: Attrs::from( [ ("symbol", "BTC/USD"), ("asset_type", "Crypto"), @@ -700,33 +777,33 @@ pub mod rpc { .map(|(k, v)| (k.to_string(), v.to_string())), ), price_accounts: vec![PriceAccount { - account: "some_price_account".to_string(), - price_type: "price".to_string(), - price_exponent: 8, - status: "trading".to_string(), - price: 536, - conf: 67, - twap: 276, - twac: 463, - valid_slot: 4628, - pub_slot: 4736, - prev_slot: 3856, - prev_price: 400, - prev_conf: 45, + account: "some_price_account".to_string(), + price_type: "price".to_string(), + price_exponent: 8, + status: "trading".to_string(), + price: 536, + conf: 67, + twap: 276, + twac: 463, + valid_slot: 4628, + pub_slot: 4736, + prev_slot: 3856, + prev_price: 400, + prev_conf: 45, publisher_accounts: vec![ PublisherAccount { account: "some_publisher_account".to_string(), - status: "trading".to_string(), - price: 500, - conf: 24, - slot: 3563, + status: "trading".to_string(), + price: 500, + conf: 24, + slot: 3563, }, PublisherAccount { account: "another_publisher_account".to_string(), - status: "halted".to_string(), - price: 300, - conf: 683, - slot: 5834, + status: "halted".to_string(), + price: 300, + conf: 683, + slot: 5834, }, ], }], @@ -836,9 +913,9 @@ pub mod rpc { let status = "trading"; let params = UpdatePriceParams { account: Pubkey::from("some_price_account"), - price: 7467, - conf: 892, - status: status.to_string(), + price: 7467, + conf: 892, + status: status.to_string(), }; test_client .send(Request::with_params( @@ -875,7 +952,7 @@ pub mod rpc { // Define the data we are working with let product_account = Pubkey::from("some_product_account"); let data = vec![ProductAccountMetadata { - account: product_account.clone(), + account: product_account.clone(), attr_dict: Attrs::from( [ ("symbol", "BTC/USD"), @@ -886,15 +963,15 @@ pub mod rpc { ] .map(|(k, v)| (k.to_string(), v.to_string())), ), - prices: vec![ + prices: vec![ PriceAccountMetadata { - account: Pubkey::from("some_price_account"), - price_type: "price".to_string(), + account: Pubkey::from("some_price_account"), + price_type: "price".to_string(), price_exponent: 4, }, PriceAccountMetadata { - account: Pubkey::from("another_price_account"), - price_type: "special".to_string(), + account: Pubkey::from("another_price_account"), + price_type: "special".to_string(), price_exponent: 6, }, ], @@ -926,8 +1003,8 @@ pub mod rpc { // Define the data we are working with let data = vec![ProductAccount { - account: Pubkey::from("some_product_account"), - attr_dict: Attrs::from( + account: Pubkey::from("some_product_account"), + attr_dict: Attrs::from( [ ("symbol", "LTC/USD"), ("asset_type", "Crypto"), @@ -938,33 +1015,33 @@ pub mod rpc { .map(|(k, v)| (k.to_string(), v.to_string())), ), price_accounts: vec![PriceAccount { - account: Pubkey::from("some_price_account"), - price_type: "price".to_string(), - price_exponent: 7463, - status: "trading".to_string(), - price: 6453, - conf: 3434, - twap: 6454, - twac: 365, - valid_slot: 3646, - pub_slot: 2857, - prev_slot: 7463, - prev_price: 3784, - prev_conf: 9879, + account: Pubkey::from("some_price_account"), + price_type: "price".to_string(), + price_exponent: 7463, + status: "trading".to_string(), + price: 6453, + conf: 3434, + twap: 6454, + twac: 365, + valid_slot: 3646, + pub_slot: 2857, + prev_slot: 7463, + prev_price: 3784, + prev_conf: 9879, publisher_accounts: vec![ PublisherAccount { account: Pubkey::from("some_publisher_account"), - status: "trading".to_string(), - price: 756, - conf: 8787, - slot: 2209, + status: "trading".to_string(), + price: 756, + conf: 8787, + slot: 2209, }, PublisherAccount { account: Pubkey::from("another_publisher_account"), - status: "halted".to_string(), - price: 0, - conf: 0, - slot: 6676, + status: "halted".to_string(), + price: 0, + conf: 0, + slot: 6676, }, ], }], @@ -1027,12 +1104,12 @@ pub mod rpc { // Send a Notify Price event from the adapter to the server, with the corresponding subscription id let notify_price_update = NotifyPrice { subscription: subscription_id, - result: PriceUpdate { - price: 74, - conf: 24, - status: "trading".to_string(), + result: PriceUpdate { + price: 74, + conf: 24, + status: "trading".to_string(), valid_slot: 6786, - pub_slot: 9897, + pub_slot: 9897, }, }; notify_price_tx.send(notify_price_update).await.unwrap(); diff --git a/src/publisher/solana/oracle.rs b/src/publisher/solana/oracle.rs index df34bb2..153e8fa 100644 --- a/src/publisher/solana/oracle.rs +++ b/src/publisher/solana/oracle.rs @@ -1,21 +1,22 @@ // This module is responsible for loading the current state of the // on-chain Oracle program accounts from Solana. -use std::collections::HashMap; - -use solana_sdk::pubkey::Pubkey; +use { + solana_sdk::pubkey::Pubkey, + std::collections::HashMap, +}; #[derive(Default, Debug, Clone)] pub struct Data { pub mapping_accounts: HashMap, pub product_accounts: HashMap, - pub price_accounts: HashMap, + pub price_accounts: HashMap, } pub type MappingAccount = pyth_sdk_solana::state::MappingAccount; #[derive(Debug, Clone)] pub struct ProductAccount { - pub account_data: pyth_sdk_solana::state::ProductAccount, + pub account_data: pyth_sdk_solana::state::ProductAccount, pub price_accounts: Vec, } pub type PriceAccount = pyth_sdk_solana::state::PriceAccount; diff --git a/src/publisher/store/global.rs b/src/publisher/store/global.rs index 9042856..a941cbe 100644 --- a/src/publisher/store/global.rs +++ b/src/publisher/store/global.rs @@ -2,14 +2,23 @@ // on-chain aggregation contracts, across both the primary and secondary networks. // This enables this data to be easily queried by other components. -use std::collections::{BTreeMap, HashMap}; - -use super::super::solana::oracle::{self, PriceAccount, ProductAccount}; -use anyhow::Result; -use pyth_sdk::PriceFeed; -use tokio::sync::oneshot; - -use super::PriceIdentifier; +use { + super::{ + super::solana::oracle::{ + self, + PriceAccount, + ProductAccount, + }, + PriceIdentifier, + }, + anyhow::Result, + pyth_sdk::PriceFeed, + std::collections::{ + BTreeMap, + HashMap, + }, + tokio::sync::oneshot, +}; /// AllAccountsMetadata contains the metadata for all the price and product accounts, /// merged from both networks. @@ -18,14 +27,14 @@ use super::PriceIdentifier; #[derive(Debug)] pub struct AllAccountsMetadata { pub product_accounts_metadata: HashMap, - pub price_accounts_metadata: HashMap, + pub price_accounts_metadata: HashMap, } /// ProductAccountMetadata contains the metadata for a product account. #[derive(Debug)] pub struct ProductAccountMetadata { /// Attribute dictionary - pub attr_dict: BTreeMap, + pub attr_dict: BTreeMap, /// Price accounts associated with this product pub price_accounts: Vec, } @@ -41,18 +50,18 @@ pub struct PriceAccountMetadata { pub enum Message { ProductAccountUpdate { account_key: solana_sdk::pubkey::Pubkey, - account: ProductAccount, + account: ProductAccount, }, PriceAccountUpdate { account_key: solana_sdk::pubkey::Pubkey, - account: PriceAccount, + account: PriceAccount, }, LookupAllAccountsMetadata { result_tx: oneshot::Sender>, }, LookupPriceFeed { identifier: PriceIdentifier, - result_tx: oneshot::Sender>, + result_tx: oneshot::Sender>, }, LookupSolanaOracleData { result_tx: oneshot::Sender>,