wip
This commit is contained in:
parent
d7d2571750
commit
48e99d04a8
|
@ -13,6 +13,6 @@ tokio = "^1"
|
|||
futures = "0.3"
|
||||
serde = "^1"
|
||||
serde_json = "^1"
|
||||
switchboard-utils = "0.5.0"
|
||||
switchboard-solana = "0.5.3"
|
||||
# switchboard-solana = { path = "../../../../rust/switchboard-solana" }
|
||||
# switchboard-utils = "0.5.0"
|
||||
# switchboard-solana = "0.5.3"
|
||||
switchboard-solana = { path = "../../../../rust/switchboard-solana" }
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
// Note: Binance API requires a non-US IP address
|
||||
|
||||
use crate::*;
|
||||
use bytemuck;
|
||||
|
||||
pub use switchboard_utils::reqwest;
|
||||
// pub use switchboard_utils::reqwest;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
const ONE: i128 = 1e9;
|
||||
const ONE: i128 = 1000000000;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Deserialize, Default, Clone, Debug)]
|
||||
|
@ -62,15 +61,16 @@ impl Into<OracleData> for IndexData {
|
|||
|
||||
pub struct Binance {
|
||||
btc_usdt: IndexData,
|
||||
usdc_usdt: IndexData,
|
||||
eth_usdt: IndexData,
|
||||
sol_usdt: IndexData,
|
||||
usdc_usdt: IndexData,
|
||||
doge_usdt: IndexData,
|
||||
}
|
||||
|
||||
impl Binance {
|
||||
// Fetch data from the Binance API
|
||||
pub async fn fetch() -> std::result::Result<Binance, SwitchboardClientError> {
|
||||
let symbols = ["BTCUSDT", "ETHUSDT", "SOLUSDT", "USDCUSDT"];
|
||||
let symbols = ["BTCUSDT", "USDCUSDT", "ETHUSDT", "SOLUSDT", "DOGEUSDT"];
|
||||
|
||||
let tickers_1hr = reqwest::get(format!(
|
||||
"https://api.binance.com/api/v3/ticker?symbols=[{}]&windowSize=1h",
|
||||
|
@ -121,34 +121,38 @@ impl Binance {
|
|||
|
||||
Ok(Binance {
|
||||
btc_usdt: data.get(0).unwrap().clone(),
|
||||
eth_usdt: data.get(1).unwrap().clone(),
|
||||
sol_usdt: data.get(2).unwrap().clone(),
|
||||
usdc_usdt: data.get(3).unwrap().clone(),
|
||||
usdc_usdt: data.get(1).unwrap().clone(),
|
||||
eth_usdt: data.get(2).unwrap().clone(),
|
||||
sol_usdt: data.get(3).unwrap().clone(),
|
||||
doge_usdt: data.get(4).unwrap().clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn to_ixns(&self, runner: &FunctionRunner) -> Vec<Instruction> {
|
||||
let btc_usdt: OracleData = self.btc_usdt.clone().into();
|
||||
// let btc_usdc: OracleData = self.btc_usdc.clone().into();
|
||||
let eth_usdt: OracleData = self.eth_usdt.clone().into();
|
||||
let sol_usdt: OracleData = self.sol_usdt.clone().into();
|
||||
let usdc_usdt: OracleData = self.usdc_usdt.clone().into();
|
||||
let usdt_usdc: OracleData = OracleData {
|
||||
oracle_timestamp: usdc_usdt.oracle_timestamp,
|
||||
price: ONE.checked_div(usdc_usdt.price).unwrap(),
|
||||
volume_1hr: usdc_usdt.volume_1hr,
|
||||
volume_24hr: usdc_usdt.volume_24hr,
|
||||
twap_1hr: ONE.checked_div(usdc_usdt.twap_1hr).unwrap(),
|
||||
twap_24hr: ONE.checked_div(usdc_usdt.twap_24hr).unwrap(),
|
||||
};
|
||||
let rows: Vec<OracleDataWithTradingSymbol> = vec![
|
||||
OracleDataWithTradingSymbol {
|
||||
symbol: TradingSymbol::BTC,
|
||||
data: self.btc_usdt.clone().into(),
|
||||
},
|
||||
OracleDataWithTradingSymbol {
|
||||
symbol: TradingSymbol::USDC,
|
||||
data: self.usdc_usdt.clone().into(),
|
||||
},
|
||||
OracleDataWithTradingSymbol {
|
||||
symbol: TradingSymbol::ETH,
|
||||
data: self.eth_usdt.clone().into(),
|
||||
},
|
||||
OracleDataWithTradingSymbol {
|
||||
symbol: TradingSymbol::SOL,
|
||||
data: self.sol_usdt.clone().into(),
|
||||
},
|
||||
OracleDataWithTradingSymbol {
|
||||
symbol: TradingSymbol::DOGE,
|
||||
data: self.doge_usdt.clone().into(),
|
||||
},
|
||||
];
|
||||
|
||||
let params = RefreshPricesParams {
|
||||
btc: Some(btc_usdt),
|
||||
eth: Some(eth_usdt),
|
||||
sol: Some(sol_usdt),
|
||||
usdt: Some(usdt_usdc),
|
||||
usdc: Some(usdc_usdt),
|
||||
};
|
||||
let params = RefreshPricesParams { rows };
|
||||
|
||||
let (program_state_pubkey, _state_bump) =
|
||||
Pubkey::find_program_address(&[b"BASICORACLE"], &PROGRAM_ID);
|
||||
|
|
|
@ -4,7 +4,8 @@ pub mod binance;
|
|||
pub use binance::*;
|
||||
|
||||
pub use basic_oracle::{
|
||||
self, OracleData, RefreshPrices, RefreshPricesParams, SwitchboardDecimal, ID as PROGRAM_ID,
|
||||
self, OracleData, OracleDataWithTradingSymbol, RefreshPrices, RefreshPricesParams,
|
||||
SwitchboardDecimal, TradingSymbol, ID as PROGRAM_ID,
|
||||
};
|
||||
|
||||
#[tokio::main(worker_threads = 12)]
|
||||
|
|
|
@ -4,10 +4,10 @@ use crate::*;
|
|||
pub struct RefreshPrices<'info> {
|
||||
#[account(
|
||||
seeds = [PROGRAM_SEED],
|
||||
bump = program.load()?.bump,
|
||||
bump = program_state.load()?.bump,
|
||||
// constraint = program.load()?.is_valid_enclave("e.load()?.mr_enclave) @ BasicOracleError::InvalidMrEnclave
|
||||
)]
|
||||
pub program: AccountLoader<'info, MyProgramState>,
|
||||
pub program_state: AccountLoader<'info, MyProgramState>,
|
||||
|
||||
#[account(
|
||||
mut,
|
||||
|
@ -34,7 +34,7 @@ pub struct RefreshPrices<'info> {
|
|||
|
||||
#[derive(Clone, AnchorSerialize, AnchorDeserialize)]
|
||||
pub struct RefreshPricesParams {
|
||||
pub symbols: Vec<OracleDataWithTradingSymbol>,
|
||||
pub rows: Vec<OracleDataWithTradingSymbol>,
|
||||
}
|
||||
|
||||
impl RefreshPrices<'_> {
|
||||
|
@ -48,6 +48,7 @@ impl RefreshPrices<'_> {
|
|||
|
||||
pub fn actuate(ctx: &Context<Self>, params: &RefreshPricesParams) -> anchor_lang::Result<()> {
|
||||
let oracle = &mut ctx.accounts.oracle.load_mut()?;
|
||||
oracle.save_rows(¶ms.rows)?;
|
||||
|
||||
// for data in params.data
|
||||
|
||||
|
|
|
@ -15,4 +15,6 @@ pub enum BasicOracleError {
|
|||
InvalidMrEnclave,
|
||||
#[msg("Switchboard QuoteAccount has an empty MrEnclave (invalid)")]
|
||||
EmptySwitchboardQuote,
|
||||
#[msg("Failed to find a valid trading symbol for this price")]
|
||||
InvalidSymbol,
|
||||
}
|
||||
|
|
|
@ -1,43 +1,41 @@
|
|||
use crate::*;
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, AnchorSerialize, AnchorDeserialize)]
|
||||
pub enum TradingSymbol {
|
||||
#[default]
|
||||
Unknown = 0,
|
||||
BTC = 1,
|
||||
USDT,
|
||||
USDC,
|
||||
ETH,
|
||||
SOL,
|
||||
DOGE,
|
||||
USDC = 2,
|
||||
ETH = 3,
|
||||
SOL = 4,
|
||||
DOGE = 5,
|
||||
}
|
||||
|
||||
unsafe impl Pod for TradingSymbol {}
|
||||
unsafe impl Zeroable for TradingSymbol {}
|
||||
|
||||
impl From<TradingSymbol> for u32 {
|
||||
impl From<TradingSymbol> for u8 {
|
||||
fn from(value: TradingSymbol) -> Self {
|
||||
match value {
|
||||
TradingSymbol::BTC => 1,
|
||||
TradingSymbol::USDT => 2,
|
||||
TradingSymbol::USDC => 3,
|
||||
TradingSymbol::ETH => 4,
|
||||
TradingSymbol::SOL => 5,
|
||||
TradingSymbol::DOGE => 6,
|
||||
TradingSymbol::USDC => 2,
|
||||
TradingSymbol::ETH => 3,
|
||||
TradingSymbol::SOL => 4,
|
||||
TradingSymbol::DOGE => 5,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<u32> for TradingSymbol {
|
||||
fn from(value: u32) -> Self {
|
||||
impl From<u8> for TradingSymbol {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
1 => TradingSymbol::BTC,
|
||||
2 => TradingSymbol::USDT,
|
||||
3 => TradingSymbol::USDC,
|
||||
4 => TradingSymbol::ETH,
|
||||
5 => TradingSymbol::SOL,
|
||||
6 => TradingSymbol::DOGE,
|
||||
2 => TradingSymbol::USDC,
|
||||
3 => TradingSymbol::ETH,
|
||||
4 => TradingSymbol::SOL,
|
||||
5 => TradingSymbol::DOGE,
|
||||
_ => TradingSymbol::default(),
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +57,6 @@ pub struct OracleData {
|
|||
pub volume_24hr: i128,
|
||||
pub twap_1hr: i128,
|
||||
pub twap_24hr: i128,
|
||||
// pub reserved: [u8; 12], // makes 100 bytes exactly
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default, AnchorSerialize, AnchorDeserialize)]
|
||||
|
@ -89,10 +86,9 @@ impl OracleData {
|
|||
pub struct MyOracleState {
|
||||
pub bump: u8,
|
||||
pub btc: OracleData,
|
||||
pub usdc: OracleData,
|
||||
pub eth: OracleData,
|
||||
pub sol: OracleData,
|
||||
pub usdt: OracleData,
|
||||
pub usdc: OracleData,
|
||||
pub doge: OracleData,
|
||||
// can always re-allocate to add more
|
||||
// pub reserved: [u8; 2400],
|
||||
|
@ -102,3 +98,35 @@ impl Default for MyOracleState {
|
|||
unsafe { std::mem::zeroed() }
|
||||
}
|
||||
}
|
||||
impl MyOracleState {
|
||||
pub fn save_rows(
|
||||
&mut self,
|
||||
rows: &Vec<OracleDataWithTradingSymbol>,
|
||||
) -> anchor_lang::Result<()> {
|
||||
for row in rows.iter() {
|
||||
match row.symbol {
|
||||
TradingSymbol::BTC => {
|
||||
self.btc = row.data;
|
||||
}
|
||||
TradingSymbol::USDC => {
|
||||
self.usdc = row.data;
|
||||
}
|
||||
TradingSymbol::ETH => {
|
||||
self.eth = row.data;
|
||||
}
|
||||
TradingSymbol::SOL => {
|
||||
self.sol = row.data;
|
||||
}
|
||||
TradingSymbol::DOGE => {
|
||||
self.doge = row.data;
|
||||
}
|
||||
_ => {
|
||||
msg!("no trading symbol found for {:?}", row.symbol);
|
||||
// TODO: emit an event so we can detect and fix
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ no-entrypoint = []
|
|||
cpi = ["no-entrypoint"]
|
||||
|
||||
[dependencies]
|
||||
anchor-spl = "=0.28.0"
|
||||
anchor-spl = "0.28.0"
|
||||
solana-program = ">= 1.16, < 1.17"
|
||||
solana-address-lookup-table-program = ">= 1.16, < 1.17"
|
||||
rust_decimal = "^1"
|
||||
|
@ -30,11 +30,11 @@ superslice = "1"
|
|||
|
||||
[target.'cfg(target_os = "solana")'.dependencies]
|
||||
switchboard-common = { version = "0.5.3" }
|
||||
anchor-lang = { version = "=0.28.0" }
|
||||
anchor-lang = { version = "0.28.0" }
|
||||
|
||||
[target.'cfg(not(target_os = "solana"))'.dependencies]
|
||||
switchboard-common = { version = "0.5.3", features = ["sgx"] }
|
||||
anchor-client = { version = "=0.28.0" }
|
||||
anchor-client = { version = "0.28.0" }
|
||||
bincode = { version = "^1" }
|
||||
sgx-quote = { version = "0.1.0" }
|
||||
cron = { version = "0.12.0" }
|
||||
|
|
Loading…
Reference in New Issue