ostium_rust_sdk/
config.rs1use alloy_primitives::Address;
7use serde::{Deserialize, Serialize};
8use url::Url;
9
10use crate::error::{OstiumError, Result};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
14pub enum Network {
15 Mainnet,
17 Testnet,
19}
20
21impl Network {
22 pub fn config(self) -> NetworkConfig {
24 match self {
25 Network::Mainnet => NetworkConfig::mainnet(),
26 Network::Testnet => NetworkConfig::testnet(),
27 }
28 }
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct NetworkConfig {
34 pub network: Network,
36 pub rpc_url: Url,
38 pub chain_id: u64,
40 pub graphql_url: Url,
42 pub trading_contract: Address,
44 pub storage_contract: Address,
46 pub price_feed_contract: Address,
48 pub usdc_address: Address,
50}
51
52impl NetworkConfig {
53 pub fn mainnet() -> Self {
55 Self {
56 network: Network::Mainnet,
57 chain_id: 42161,
58 rpc_url: "https://arb1.arbitrum.io/rpc".parse().expect("Valid URL"),
59 graphql_url: "https://subgraph.satsuma-prod.com/391a61815d32/ostium/ost-prod/api"
60 .parse()
61 .expect("Valid URL"),
62 usdc_address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
63 .parse()
64 .expect("Valid address"),
65 trading_contract: "0x6D0bA1f9996DBD8885827e1b2e8f6593e7702411"
66 .parse()
67 .expect("Valid address"),
68 storage_contract: "0xcCd5891083A8acD2074690F65d3024E7D13d66E7"
69 .parse()
70 .expect("Valid address"),
71 price_feed_contract: "0x0000000000000000000000000000000000000003"
72 .parse()
73 .expect("Valid address"),
74 }
75 }
76
77 pub fn testnet() -> Self {
79 Self {
80 network: Network::Testnet,
81 chain_id: 421614,
82 rpc_url: "https://sepolia-rollup.arbitrum.io/rpc"
83 .parse()
84 .expect("Valid URL"),
85 graphql_url: "https://subgraph.satsuma-prod.com/391a61815d32/ostium/ost-sep-final/api"
86 .parse()
87 .expect("Valid URL"),
88 usdc_address: "0xe73B11Fb1e3eeEe8AF2a23079A4410Fe1B370548"
89 .parse()
90 .expect("Valid address"),
91 trading_contract: "0x2A9B9c988393f46a2537B0ff11E98c2C15a95afe"
92 .parse()
93 .expect("Valid address"),
94 storage_contract: "0x0b9F5243B29938668c9Cfbd7557A389EC7Ef88b8"
95 .parse()
96 .expect("Valid address"),
97 price_feed_contract: "0x0000000000000000000000000000000000000003"
98 .parse()
99 .expect("Valid address"),
100 }
101 }
102
103 pub fn custom(
105 rpc_url: Url,
106 chain_id: u64,
107 graphql_url: Url,
108 trading_contract: Address,
109 storage_contract: Address,
110 price_feed_contract: Address,
111 usdc_address: Address,
112 ) -> Self {
113 Self {
114 network: Network::Mainnet, rpc_url,
116 chain_id,
117 graphql_url,
118 trading_contract,
119 storage_contract,
120 price_feed_contract,
121 usdc_address,
122 }
123 }
124
125 pub fn validate(&self) -> Result<()> {
127 match self.network {
129 Network::Mainnet if self.chain_id != 42161 => {
130 return Err(OstiumError::config("Invalid chain ID for mainnet"));
131 }
132 Network::Testnet if self.chain_id != 421614 => {
133 return Err(OstiumError::config("Invalid chain ID for testnet"));
134 }
135 _ => {}
136 }
137
138 if self.trading_contract == Address::ZERO {
140 return Err(OstiumError::config(
141 "Trading contract address cannot be zero",
142 ));
143 }
144 if self.storage_contract == Address::ZERO {
145 return Err(OstiumError::config(
146 "Storage contract address cannot be zero",
147 ));
148 }
149 if self.price_feed_contract == Address::ZERO {
150 return Err(OstiumError::config(
151 "Price feed contract address cannot be zero",
152 ));
153 }
154 if self.usdc_address == Address::ZERO {
155 return Err(OstiumError::config("USDC address cannot be zero"));
156 }
157
158 Ok(())
159 }
160}
161
162pub struct NetworkConfigBuilder {
164 config: NetworkConfig,
165}
166
167impl NetworkConfigBuilder {
168 pub fn new(network: Network) -> Self {
170 Self {
171 config: network.config(),
172 }
173 }
174
175 pub fn with_rpc_url(mut self, url: Url) -> Self {
177 self.config.rpc_url = url;
178 self
179 }
180
181 pub fn with_graphql_url(mut self, url: Url) -> Self {
183 self.config.graphql_url = url;
184 self
185 }
186
187 pub fn with_contracts(
189 mut self,
190 trading: Address,
191 storage: Address,
192 price_feed: Address,
193 ) -> Self {
194 self.config.trading_contract = trading;
195 self.config.storage_contract = storage;
196 self.config.price_feed_contract = price_feed;
197 self
198 }
199
200 pub fn build(self) -> Result<NetworkConfig> {
202 self.config.validate()?;
203 Ok(self.config)
204 }
205}