#[cfg(any(feature = "faucet", feature = "noble"))] use anyhow::anyhow as err; use anyhow::{Error, Result}; use chrono::{TimeDelta, Utc}; #[cfg(feature = "faucet")] use dydx::faucet::FaucetClient; #[cfg(feature = "noble")] use dydx::noble::NobleClient; use dydx::{ config::ClientConfig, indexer::{ClientId, Height, IndexerClient, PerpetualMarket, Ticker}, node::{Account, Address, NodeClient, OrderBuilder, OrderId, OrderSide, Subaccount, Wallet}, }; const TEST_MNEMONIC: &str = "mirror actor skill push coach wait confirm orchard lunch mobile athlete gossip awake miracle matter bus reopen team ladder lazy list timber render wait"; pub enum TestEnv {} #[allow(dead_code)] impl TestEnv { pub async fn testnet() -> Result { TestnetEnv::bootstrap().await } pub async fn mainnet() -> Result { MainnetEnv::bootstrap().await } } #[allow(dead_code)] pub struct MainnetEnv { pub indexer: IndexerClient, pub ticker: Ticker, } impl MainnetEnv { async fn bootstrap() -> Result { let path = "tests/mainnet.toml"; let config = ClientConfig::from_file(path).await?; let indexer = IndexerClient::new(config.indexer); let ticker = Ticker::from("ETH-USD"); Ok(Self { indexer, ticker }) } } #[allow(dead_code)] pub struct TestnetEnv { pub node: NodeClient, pub indexer: IndexerClient, #[cfg(feature = "faucet")] pub faucet: FaucetClient, #[cfg(feature = "noble")] pub noble: NobleClient, pub wallet: Wallet, pub account: Account, pub address: Address, pub subaccount: Subaccount, pub ticker: Ticker, } #[allow(dead_code)] impl TestnetEnv { async fn bootstrap() -> Result { let path = "tests/testnet.toml"; let config = ClientConfig::from_file(path).await?; let mut node = NodeClient::connect(config.node).await?; let indexer = IndexerClient::new(config.indexer); #[cfg(feature = "faucet")] let faucet = FaucetClient::new(config.faucet.ok_or_else(|| { err!("Configuration file must contain a [faucet] configuration for testing") })?); #[cfg(feature = "noble")] let noble = NobleClient::connect(config.noble.ok_or_else(|| { err!("Configuration file must contain a [noble] configuration for testing") })?) .await?; let wallet = Wallet::from_mnemonic(TEST_MNEMONIC)?; let account = wallet.account(0, &mut node).await?; let ticker = Ticker::from("ETH-USD"); let address = account.address().clone(); let subaccount = account.subaccount(0)?; Ok(Self { node, indexer, #[cfg(feature = "faucet")] faucet, #[cfg(feature = "noble")] noble, wallet, account, address, subaccount, ticker, }) } pub async fn get_market(&self) -> Result { self.indexer .markets() .get_perpetual_market(&self.ticker) .await } pub async fn get_height(&self) -> Result { Ok(self.indexer.utility().get_height().await?.height) } pub async fn spawn_order(&mut self) -> Result { let market = self.get_market().await?; let subaccount = self.account.subaccount(0)?; let (id, order) = OrderBuilder::new(market, subaccount) .limit(OrderSide::Buy, 1, 1) .until(Utc::now() + TimeDelta::seconds(60)) .long_term() .build(ClientId::random())?; let tx_res = self.node.place_order(&mut self.account, order).await; self.node.query_transaction_result(tx_res).await?; Ok(id) } }