ccdata_api/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
//! # CCData API Wrapper
//!
//! `ccdata-api` is a wrapper for CCData REST API endpoints. This crate supports non-exhausitve list of CCData endpoints,
//! you can check what endpoints are supported by checking the variants of the enum `CCAPIEndpoint` - it contains all
//! supported endpoint URLs.
//!
//! For documentation on CCData REST API endpoints visit CCData online documentation:
//! - Min-API: <https://developers.ccdata.io/documentation/legacy/Price/SingleSymbolPriceEndpoint>
//! - Data-API: <https://developers.ccdata.io/documentation/data-api/introduction>
//!
//! **Disclaimer:** This crate is an unofficial CCData REST API wrapper, the maintainers of the crate are independent developers.
//! The developers of the crate do not accept any responsibility or liability for the accuracy, security, or completeness of the code,
//! or the information provided within the crate.
//!
//! # Errors
//!
//! The REST API functions in the crate will error if the data received does not fit into the pre-defined schemas provided
//! in the crate. In the case of missing fields, unexpected null values or unexpected data types, the error message will state:
//!
//! - `data did not match any variant of untagged enum EmptyObject`
//!
//! If you encounter this error, please open the issue on GitHub with the parameters that you have used (e.g., asset symbol,
//! timestamp, limit, etc.). **Do not provide your API key or any personal data!**
//!
//! # Examples
//!
//! To start making the REST API requests, define a data collection backend. This can be done by either directly passing an
//! API key to the data collection backend, or by defining a `.env` file with an API key as an environment variable (Preferred
//! method).
//!
//! ## Build Backend Explicitly Stating API Key (May expose API key)
//!
//! ```rust
//! use ccdata_api::CCData;
//!
//! let mut backend: CCData = CCData::new();
//!
//! let api_key: String = String::from("xxxxxxx");
//! backend.update_api_key(api_key);
//!
//! assert_eq!(backend.api_key().unwrap(), &String::from("xxxxxxx"));
//! ```
//!
//! ## Build Backend Using .env File (Preferred method)
//!
//! ```rust
//! use ccdata_api::CCData;
//!
//! let mut backend: CCData = CCData::new();
//! // Provide API key as the environment variable called API_KEY
//! backend.build(&"API_KEY").unwrap();
//!
//! println!("{}", backend.api_key().unwrap());
//! ```
//!
//! ## Making First API Call
//!
//! After the backend has been build, you can make API requests using the methods provided in the backend. For example, to
//! get a daily spot OHLCV data for Bitcoin you can do the following (note that the calls use Rust's `async` functionality):
//!
//! ```rust
//!
//! use ccdata_api::{CCData, CCUnit, DataUnwrap};
//! use ccdata_api::CCSpotMarket;
//!
//! #[tokio::main]
//! async fn main() -> () {
//!
//!     let mut backend: CCData = CCData::new();
//!     // Provide API key as the environment variable called API_KEY
//!     backend.build(&"API_KEY").unwrap();
//!
//!     // Define the API parameters
//!     let market: CCSpotMarket = CCSpotMarket::KRAKEN;
//!     let limit: usize = 2000;
//!     let to_timestamp: Option<i64> - Some(1728860400);
//!
//!     // Make the API call
//!     let ohlcv = backend.get_spot_ohlcv(&String::from("BTC-USD"), to_timestamp, Some(limit), market, CCUnit::Day).await.unwrap();
//!     assert_eq!(ohlcv.data_unwrap().unwrap().len(), limit);
//!
//! }
//! ```
//!
//! # General information
//! If you would like to add a commit or an issue, please do so using the GitHub link to the project:
//! - <https://github.com/rsadykhov/ccdata-api>


// Re-Exports
pub use self::backend::CCData;
pub use self::schemas::DataUnwrap;
// Min-API Re-Exports
pub use self::schemas::{CCMinResponse, CCMinWrapper, CCRateLimit, CCMaxCalls, CCCallsMade};
pub use self::schemas::min_api::{CCAvailableCoinList, CCHistoricalDaily, CCBalanceDistribution, CCSupplyBand};
// Data-API Re-Exports
pub use self::schemas::{CCDataResponse, CCError, CCErrorOtherInfo};
pub use self::schemas::data_api::indices_and_reference_rates::{CCIndicesMarket, CCIndicesOHLCV};
pub use self::schemas::data_api::spot::{CCSpotMarket, CCSpotInstrumentStatus, CCSpotOHLCV, CCSpotInstrumentMetdata, CCSpotMarkets, CCSpotMarketsInstruments};
pub use self::schemas::data_api::futures::{CCFuturesMarket, CCFuturesOHLCV, CCFuturesMarkets};
pub use self::schemas::data_api::options::{CCOptionsMarket, CCOptionsOHLCV, CCOptionsMarkets};
pub use self::schemas::data_api::derivatives_indices::{CCDerIndicesMarket, CCDerIndicesOHLCV, CCDerIndicesMarkets};
pub use self::schemas::data_api::on_chain_dex::{CCOCDEXMarket, CCOCDEXOHLCV, CCOCDEXMarkets};
pub use self::schemas::data_api::on_chain_core::{CCOCCoreETHBlock, CCOCCoreAssetByChain, CCOCCoreAssetByAddress, CCOCCoreSupply};
pub use self::schemas::data_api::asset::{CCAssetMetadata, CCAssetEvent, CCAssetCodeRepoMetrics, CCAssetDiscord, CCAssetReddit, CCAssetTelegram, CCAssetTwitter};
pub use self::schemas::data_api::news::{CCNewsStatus, CCNewsLang, CCNewsSourceID, CCNewsLatestArticle, CCNewsSourceType, CCNewsSource, CCNewsCategory};
pub use self::schemas::data_api::overview::CCOverviewMktCapOHLCV;


pub mod schemas;
pub mod utils;
pub mod backend;


/// Unit of historical data response.
pub enum CCUnit {
    Day,
    Hour,
    Minute,
    NA,
}


/// All supported API endpoints.
pub enum CCAPIEndpoint {
    // Min-API
    AvailableCoinList,
    HistoricalDaily,
    BalanceDistribution,
    // Data-API
    // Indices & Reference Rates
    IndicesOHLCV,
    // Spot
    SpotOHLCV,
    SpotInstrumentMetadata,
    SpotMarkets,
    SpotMarketsInstruments,
    // Futures
    FuturesOHLCV,
    FuturesMarkets,
    // Options
    OptionsOHLCV,
    OptionsMarkets,
    // Derivatives Indices
    DerIndicesOHLCV,
    DerIndicesMarkets,
    // On-Chain DEX
    OCDEXOHLCV,
    OCDEXMarkets,
    // On-Chain Core
    OCCoreETHBlocks,
    OCCoreAssetsByChain,
    OCCoreAssetByAddress,
    OCCoreSupply,
    // Asset
    AssetMetadata,
    AssetEvents,
    AssetCodeRepo,
    AssetDiscord,
    AssetReddit,
    AssetTelegram,
    AssetTwitter,
    // News
    NewsLatestArticles,
    NewsSources,
    NewsCategories,
    // Overview
    OverviewMktCapOHLCV,
}

impl CCAPIEndpoint {
    fn resolve_url(&self) -> String {
        match self {
            // Min-API
            CCAPIEndpoint::AvailableCoinList => String::from("https://min-api.cryptocompare.com/data/blockchain/list"),
            CCAPIEndpoint::HistoricalDaily => String::from("https://min-api.cryptocompare.com/data/blockchain/histo/day"),
            CCAPIEndpoint::BalanceDistribution => String::from("https://min-api.cryptocompare.com/data/blockchain/balancedistribution/histo/day"),
            // Data-API
            // Indices & Reference Rates
            CCAPIEndpoint::IndicesOHLCV => String::from("https://data-api.ccdata.io/index/cc/v1/historical"),
            // Spot
            CCAPIEndpoint::SpotOHLCV => String::from("https://data-api.ccdata.io/spot/v1/historical"),
            CCAPIEndpoint::SpotInstrumentMetadata => String::from("https://data-api.ccdata.io/spot/v1/latest/instrument/metadata"),
            CCAPIEndpoint::SpotMarkets => String::from("https://data-api.ccdata.io/spot/v1/markets"),
            CCAPIEndpoint::SpotMarketsInstruments => String::from("https://data-api.ccdata.io/spot/v1/markets/instruments"),
            // Futures
            CCAPIEndpoint::FuturesOHLCV => String::from("https://data-api.ccdata.io/futures/v1/historical"),
            CCAPIEndpoint::FuturesMarkets => String::from("https://data-api.ccdata.io/futures/v1/markets"),
            // Options
            CCAPIEndpoint::OptionsOHLCV => String::from("https://data-api.ccdata.io/options/v1/historical"),
            CCAPIEndpoint::OptionsMarkets => String::from("https://data-api.ccdata.io/options/v1/markets"),
            // Derivatives Indices
            CCAPIEndpoint::DerIndicesOHLCV => String::from("https://data-api.ccdata.io/index/v1/historical"),
            CCAPIEndpoint::DerIndicesMarkets => String::from("https://data-api.ccdata.io/index/v1/markets"),
            // On-Chain DEX
            CCAPIEndpoint::OCDEXOHLCV => String::from("https://data-api.ccdata.io/onchain/v1/amm/historical/swap"),
            CCAPIEndpoint::OCDEXMarkets => String::from("https://data-api.ccdata.io/onchain/v1/amm/markets"),
            // On-Chain Core
            CCAPIEndpoint::OCCoreETHBlocks => String::from("https://data-api.ccdata.io/onchain/v1/block/2"),
            CCAPIEndpoint::OCCoreAssetsByChain => String::from("https://data-api.ccdata.io/onchain/v3/summary/by/chain"),
            CCAPIEndpoint::OCCoreAssetByAddress => String::from("https://data-api.ccdata.io/onchain/v2/data/by/address"),
            CCAPIEndpoint::OCCoreSupply => String::from("https://data-api.ccdata.io/onchain/v2/historical/supply/days"),
            // Asset
            CCAPIEndpoint::AssetMetadata => String::from("https://data-api.ccdata.io/asset/v1/metadata"),
            CCAPIEndpoint::AssetEvents => String::from("https://data-api.ccdata.io/asset/v1/events"),
            CCAPIEndpoint::AssetCodeRepo => String::from("https://data-api.ccdata.io/asset/v1/historical/code-repository/days"),
            CCAPIEndpoint::AssetDiscord => String::from("https://data-api.ccdata.io/asset/v1/historical/discord/days"),
            CCAPIEndpoint::AssetReddit => String::from("https://data-api.ccdata.io/asset/v1/historical/reddit/days"),
            CCAPIEndpoint::AssetTelegram => String::from("https://data-api.ccdata.io/asset/v1/historical/telegram/days"),
            CCAPIEndpoint::AssetTwitter => String::from("https://data-api.ccdata.io/asset/v1/historical/twitter/days"),
            // News
            CCAPIEndpoint::NewsLatestArticles => String::from("https://data-api.ccdata.io/news/v1/article/list"),
            CCAPIEndpoint::NewsSources => String::from("https://data-api.ccdata.io/news/v1/source/list"),
            CCAPIEndpoint::NewsCategories => String::from("https://data-api.ccdata.io/news/v1/category/list"),
            // Overview
            CCAPIEndpoint::OverviewMktCapOHLCV => String::from("https://data-api.ccdata.io/overview/v1/historical/marketcap/all/assets/days"),
        }
    }

    fn add_unit_to_url(&self, url: &mut String, unit: &CCUnit) -> () {
        match self {
            CCAPIEndpoint::IndicesOHLCV | CCAPIEndpoint::SpotOHLCV | CCAPIEndpoint::FuturesOHLCV |
            CCAPIEndpoint::OptionsOHLCV | CCAPIEndpoint::DerIndicesOHLCV | CCAPIEndpoint::OCDEXOHLCV => {
                match unit {
                    CCUnit::Day | CCUnit::NA => url.push_str(&"/days"),
                    CCUnit::Hour => url.push_str(&"/hours"),
                    CCUnit::Minute => url.push_str(&"/minutes"),
                }
            },
            _ => (),
        }
    }

    /// Produces URL for a given API endpoint.
    pub fn url(&self, unit: &CCUnit) -> String {
        let mut url: String = self.resolve_url();
        self.add_unit_to_url(&mut url, unit);
        url
    }
}


#[cfg(test)]
mod tests {

    #[test]
    fn unit_test_add_unit_to_url() -> () {
        use crate::{CCUnit, CCAPIEndpoint};
        let unit: CCUnit = CCUnit::Hour;
        let api_endpoint: CCAPIEndpoint = CCAPIEndpoint::IndicesOHLCV;
        assert_eq!(api_endpoint.url(&unit), String::from("https://data-api.ccdata.io/index/cc/v1/historical/hours"));
    }
}