diff --git a/Cargo.toml b/Cargo.toml index 55279dd..4187d27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,10 @@ [package] -name = "rust-sdk" +name = "maestro" version = "0.1.0" edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +license = "Apache-2.0" [dependencies] +reqwest = "0.11" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" \ No newline at end of file diff --git a/LICENSE copy b/LICENSE copy deleted file mode 100644 index 339a45e..0000000 --- a/LICENSE copy +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2023 Maestro Blockchain Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/README.md b/README.md index fad096c..c59da98 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,10 @@ # Getting Started ## Prerequisites -* [Rust](https://www.rust-lang.org/tools/install) -* [Clippy](https://github.com/rust-lang/rust-clippy) -* [Audit](https://docs.rs/cargo-audit/latest/cargo_audit/) + +- [Rust](https://www.rust-lang.org/tools/install) +- [Clippy](https://github.com/rust-lang/rust-clippy) +- [Audit](https://docs.rs/cargo-audit/latest/cargo_audit/) ## Installation @@ -46,21 +47,37 @@ ## Usage ```rust -// TODO +use maestro::Maestro; + +let maestro_client = Maestro::new("", "") ``` -* To generate an API key, create a free account [here](https://dashboard.gomaestro.org/)! -* Network options: `mainnet`, `preprod`, `preview` +- To generate an API key, create a free account [here](https://dashboard.gomaestro.org/)! +- Network options: `mainnet`, `preprod`, `preview` ## Example ```rust -// TODO +use maestro::Maestro; + +#[tokio::main] +async fn main() { + let maestro_client = Maestro::new( + String::from(""), + String::from(""), + ); + + match maestro_client.block_info(9005859).await { + Ok(block_info) => println!("{}", block_info.data.absolute_slot), + Err(e) => eprint!("Failed to retrieve block info {}", e), + } +} ``` # Documentation -* [Maestro public docs](https://docs.gomaestro.org/) +- [Maestro public docs](https://docs.gomaestro.org/) # Contributing + Meastro welcomes all contributors! Please see our [contributing guidelines](CONTRIBUTING.md) and [code of conduct](CODE_OF_CONDUCT.md). diff --git a/src/client/accounts.rs b/src/client/accounts.rs new file mode 100644 index 0000000..91a65d0 --- /dev/null +++ b/src/client/accounts.rs @@ -0,0 +1,87 @@ +use super::maestro::Maestro; +use crate::{ + models::accounts::{ + AccountAddresses, AccountAssets, StakeAccountHistory, StakeAccountInformation, + StakeAccountRewards, StakeAccountUpdates, + }, + utils::Parameters, +}; +use std::error::Error; + +impl Maestro { + pub async fn account_addresses( + &self, + stake_addr: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/accounts/{}/addresses{}", stake_addr, formatted_params); + let resp = self.get(&url).await?; + let account_addresses = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(account_addresses) + } + + pub async fn account_assets( + &self, + stake_addr: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/accounts/{}/assets{}", stake_addr, formatted_params); + let resp = self.get(&url).await?; + let account_assets = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(account_assets) + } + + pub async fn stake_account_history( + &self, + stake_addr: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/accounts/{}/history{}", stake_addr, formatted_params); + let resp = self.get(&url).await?; + let stake_account_history = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(stake_account_history) + } + + pub async fn stake_account_information( + &self, + stake_addr: &str, + ) -> Result> { + let url = format!("/accounts/{}", stake_addr); + let resp = self.get(&url).await?; + let stake_account_information = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(stake_account_information) + } + + pub async fn stake_account_rewards( + &self, + stake_addr: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/accounts/{}/rewards{}", stake_addr, formatted_params); + let resp = self.get(&url).await?; + let stake_account_rewards = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(stake_account_rewards) + } + + pub async fn stake_account_updates( + &self, + stake_addr: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/accounts/{}/updates{}", stake_addr, formatted_params); + let resp = self.get(&url).await?; + let stake_account_updates = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(stake_account_updates) + } +} diff --git a/src/client/addresses.rs b/src/client/addresses.rs new file mode 100644 index 0000000..5cc5904 --- /dev/null +++ b/src/client/addresses.rs @@ -0,0 +1,111 @@ +use super::maestro::Maestro; +use crate::{ + models::addresses::{ + AddressTransactionCount, AddressTransactions, DecodedAddress, UtxoReferencesAtAddress, + UtxosAtAddress, + }, + utils, +}; +use std::error::Error; + +impl Maestro { + pub async fn decode_address(&self, address: &str) -> Result> { + let url = format!("/addresses/{}/decode/", address); + let resp = self.get(&url).await?; + let decoded_address = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(decoded_address) + } + + pub async fn address_transaction_count( + &self, + address: &str, + ) -> Result> { + let url = format!("/addresses/{}/transactions/count", address); + let resp = self.get(&url).await?; + let transaction_count = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(transaction_count) + } + + pub async fn address_transactions( + &self, + address: &str, + params: Option<&utils::Parameters>, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/addresses/{}/transactions{}", address, formatted_params); + let resp = self.get(&url).await?; + let address_transactions = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(address_transactions) + } + + pub async fn payment_credential_transactions( + &self, + payment_credential: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!( + "/addresses/cred/{}/transactions{}", + payment_credential, formatted_params + ); + let resp = self.get(&url).await?; + let address_transactions = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(address_transactions) + } + + pub async fn utxo_references_at_address( + &self, + address: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/addresses/{}/utxo_refs{}", address, formatted_params); + let resp = self.get(&url).await?; + let utxo_references = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(utxo_references) + } + + pub async fn utxos_at_address( + &self, + address: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/addresses/{}/utxos{}", address, formatted_params); + let resp = self.get(&url).await?; + let utxos = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(utxos) + } + + pub async fn utxos_at_addresses( + &self, + addresses: Vec, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/addresses/utxos{}", formatted_params); + let resp = self.post(&url, addresses).await?; + let utxos = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(utxos) + } + + pub async fn utxos_by_payment_credential( + &self, + payment_credential: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!( + "/addresses/cred/{}/utxos{}", + payment_credential, formatted_params + ); + let resp = self.get(&url).await?; + let utxos = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(utxos) + } +} diff --git a/src/client/asset.rs b/src/client/asset.rs new file mode 100644 index 0000000..4323c5c --- /dev/null +++ b/src/client/asset.rs @@ -0,0 +1,83 @@ +use super::maestro::Maestro; +use crate::{ + models::asset::{ + AccountsHoldingAsset, AddressesHoldingAsset, AssetInformations, AssetTransactions, + AssetUpdates, AssetUtxos, + }, + utils::Parameters, +}; +use std::error::Error; + +impl Maestro { + pub async fn accounts_holding_asset( + &self, + asset_id: &str, + params: Option<&Parameters>, + ) -> Result> { + let formatted_params = params.map_or_else(|| "".to_string(), |p| p.format()); + let url = format!("/assets/{}/accounts{}", asset_id, formatted_params); + let resp = self.get(&url).await?; + let accounts_holding_asset = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(accounts_holding_asset) + } + + pub async fn address_holding_asset( + &self, + asset_id: &str, + params: Option<&Parameters>, + ) -> Result> { + let formatted_params = params.map_or_else(|| "".to_string(), |p| p.format()); + let url = format!("/assets/{}/addresses{}", asset_id, formatted_params); + let resp = self.get(&url).await?; + let addresses_holding_asset = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(addresses_holding_asset) + } + + pub async fn asset(&self, asset_id: &str) -> Result> { + let url = format!("/assets/{}", asset_id); + let resp = self.get(&url).await?; + let asset_information = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(asset_information) + } + + pub async fn asset_transactions( + &self, + asset_id: &str, + params: Option<&Parameters>, + ) -> Result> { + let formatted_params = params.map_or_else(|| "".to_string(), |p| p.format()); + let url = format!("/assets/{}/txs{}", asset_id, formatted_params); + let resp = self.get(&url).await?; + let asset_transactions = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(asset_transactions) + } + + pub async fn asset_updates( + &self, + asset_id: &str, + params: Option<&Parameters>, + ) -> Result> { + let formatted_params = params.map_or_else(|| "".to_string(), |p| p.format()); + let url = format!("/assets/{}/updates{}", asset_id, formatted_params); + let resp = self.get(&url).await?; + let asset_updates = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(asset_updates) + } + + pub async fn asset_utxos( + &self, + asset_id: &str, + params: Option<&Parameters>, + ) -> Result> { + let formatted_params = params.map_or_else(|| "".to_string(), |p| p.format()); + let url = format!("/assets/{}/utxos{}", asset_id, formatted_params); + let resp = self.get(&url).await?; + let asset_utxos = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(asset_utxos) + } +} diff --git a/src/client/asset_policy.rs b/src/client/asset_policy.rs new file mode 100644 index 0000000..2d6ddfc --- /dev/null +++ b/src/client/asset_policy.rs @@ -0,0 +1,71 @@ +use super::maestro::Maestro; +use crate::{ + models::asset_policy::{ + AccountsHoldingPolicy, AddressesHoldingPolicy, PolicyInformation, PolicyTransactions, + UtxosContainingPolicy, + }, + utils, +}; +use std::error::Error; + +impl Maestro { + pub async fn accounts_holding_policy( + &self, + policy: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/assets/policy/{}/accounts?{}", policy, formatted_params); + let resp = self.get(&url).await?; + let response = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(response) + } + + pub async fn addresses_holding_policy( + &self, + policy: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/assets/policy/{}/addresses?{}", policy, formatted_params); + let resp = self.get(&url).await?; + let response = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(response) + } + + pub async fn specific_policy_informations( + &self, + policy: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/assets/policy/{}/?{}", policy, formatted_params); + let resp = self.get(&url).await?; + let response = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(response) + } + + pub async fn transactions_moving_policy( + &self, + policy: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/assets/policy/{}/txs?{}", policy, formatted_params); + let resp = self.get(&url).await?; + let response = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(response) + } + + pub async fn utxos_containing_policy( + &self, + policy: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/assets/policy/{}/utxos?{}", policy, formatted_params); + let resp = self.get(&url).await?; + let response = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(response) + } +} diff --git a/src/client/block_info.rs b/src/client/block_info.rs new file mode 100644 index 0000000..2b7da0d --- /dev/null +++ b/src/client/block_info.rs @@ -0,0 +1,60 @@ +use super::maestro::Maestro; +use crate::utils; +use serde::{Deserialize, Serialize}; +use std::error::Error; + +#[derive(Serialize, Deserialize)] +pub struct OperationalCertificate { + pub hot_vkey: String, + pub kes_period: i64, + pub kes_signature: String, + pub sequence_number: i64, +} + +#[derive(Serialize, Deserialize)] +pub struct TotalExUnits { + pub mem: i64, + pub steps: i64, +} + +#[derive(Serialize, Deserialize)] +pub struct BlockInfoData { + pub absolute_slot: i64, + pub block_producer: String, + pub confirmations: i64, + pub epoch: i64, + pub epoch_slot: i64, + pub era: String, + pub hash: String, + pub height: i64, + pub operational_certificate: OperationalCertificate, + pub previous_block: String, + pub protocol_version: Vec, + pub script_invocations: i32, + pub size: i32, + pub timestamp: String, + pub total_ex_units: TotalExUnits, + pub total_fees: i64, + pub total_output_lovelace: String, + pub tx_hashes: Vec, + pub vrf_key: String, +} + +#[derive(Deserialize)] +pub struct BlockInfo { + pub data: BlockInfoData, + pub last_updated: utils::last_updated::LastUpdated, +} + +impl Maestro { + pub async fn block_info(&self, block_height: i64) -> Result> { + let url = format!("/blocks/{}", block_height); + + let response = self.get(&url).await?; + + let block_info = + serde_json::from_str(&response).map_err(|e| Box::new(e) as Box)?; + + Ok(block_info) + } +} diff --git a/src/client/config.rs b/src/client/config.rs new file mode 100644 index 0000000..c5fbcfc --- /dev/null +++ b/src/client/config.rs @@ -0,0 +1,23 @@ +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct ClientConfig { + pub version: String, + pub timeout: i64, +} + +#[derive(Deserialize)] +pub struct Config { + pub client: ClientConfig, +} + +impl Config { + pub fn get_config() -> Config { + Config { + client: ClientConfig { + version: "v1".to_string(), + timeout: 10, + }, + } + } +} diff --git a/src/client/datum.rs b/src/client/datum.rs new file mode 100644 index 0000000..1c3b8d3 --- /dev/null +++ b/src/client/datum.rs @@ -0,0 +1,12 @@ +use super::maestro::Maestro; +use crate::models::datum::DatumFromHash; +use std::error::Error; + +impl Maestro { + pub async fn datum_from_hash(&self, hash: &str) -> Result> { + let url = format!("/data/{}", hash); + let resp = self.get(&url).await?; + let datum = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(datum) + } +} diff --git a/src/client/ecosystem.rs b/src/client/ecosystem.rs new file mode 100644 index 0000000..3f0d011 --- /dev/null +++ b/src/client/ecosystem.rs @@ -0,0 +1,13 @@ +use super::maestro::Maestro; +use crate::models::common::BasicResponse; +use std::error::Error; + +impl Maestro { + pub async fn resolve_ada_handle(&self, handle: &str) -> Result> { + let url = format!("/ecosystem/adahandle/{}", handle); + let resp = self.get(&url).await?; + + let ada_handle = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(ada_handle) + } +} diff --git a/src/client/epochs.rs b/src/client/epochs.rs new file mode 100644 index 0000000..d2b8909 --- /dev/null +++ b/src/client/epochs.rs @@ -0,0 +1,21 @@ +use super::maestro::Maestro; +use crate::models::epochs::EpochResp; +use std::error::Error; + +impl Maestro { + pub async fn current_epoch(&self) -> Result> { + let url = "/epochs/current"; + let resp = self.get(url).await?; + let current_epoch = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(current_epoch) + } + + pub async fn specific_epoch(&self, epoch_no: i32) -> Result> { + let url = format!("/epochs/{}/info", epoch_no); + let resp = self.get(&url).await?; + let specific_epoch = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(specific_epoch) + } +} diff --git a/src/client/general.rs b/src/client/general.rs new file mode 100644 index 0000000..4aed104 --- /dev/null +++ b/src/client/general.rs @@ -0,0 +1,38 @@ +use super::maestro::Maestro; +use crate::models::{ + common::BasicResponse, + general::{ChainTip, EraHistory, ProtocolParameters}, +}; +use std::error::Error; + +impl Maestro { + pub async fn chain_tip(&self) -> Result> { + let url = "/chain-tip"; + let resp = self.get(url).await?; + let chain_tip = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(chain_tip) + } + + pub async fn era_history(&self) -> Result> { + let url = "/era-history"; + let resp = self.get(url).await?; + let era_history = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(era_history) + } + + pub async fn protocol_parameters(&self) -> Result> { + let url = "/protocol-params"; + let resp = self.get(url).await?; + let protocol_params = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(protocol_params) + } + + pub async fn block_chain_start_time(&self) -> Result> { + let url = "/system-start"; + let resp = self.get(url).await?; + let blockchain_start_time = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(blockchain_start_time) + } +} diff --git a/src/client/linear_vesting.rs b/src/client/linear_vesting.rs new file mode 100644 index 0000000..31982c8 --- /dev/null +++ b/src/client/linear_vesting.rs @@ -0,0 +1,52 @@ +use super::maestro::Maestro; +use crate::models::linear_vesting::{CollectTransaction, LockTransaction, VestingState}; +use serde::{Deserialize, Serialize}; +use std::error::Error; + +#[derive(Serialize, Deserialize)] +pub struct LockBody { + pub sender: String, + pub beneficiary: String, + pub asset_policy_id: String, + pub asset_token_name: String, + pub total_vesting_quantity: i64, + pub vesting_period_start: i64, + pub vesting_period_end: i64, + pub first_unlock_possible_after: i64, + pub total_installments: i64, +} + +impl Maestro { + pub async fn lock_assets( + &self, + lock_body: LockBody, + ) -> Result> { + let url = "/contracts/vesting/lock"; + let resp = self.post(url, lock_body).await?; + let lock_transaction = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(lock_transaction) + } + + pub async fn state_of_vesting_assets( + &self, + beneficiary: &str, + ) -> Result, Box> { + let url = format!("/contracts/vesting/state/{}", beneficiary); + let resp = self.get(&url).await?; + let vesting_states = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(vesting_states) + } + + pub async fn collect_assets( + &self, + beneficiary: &str, + ) -> Result> { + let url = format!("/contracts/vesting/collect/{}", beneficiary); + let resp = self.post(&url, beneficiary).await?; + let collect_transaction = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(collect_transaction) + } +} diff --git a/src/client/maestro.rs b/src/client/maestro.rs new file mode 100644 index 0000000..9f42b93 --- /dev/null +++ b/src/client/maestro.rs @@ -0,0 +1,76 @@ +use super::config::Config; +use reqwest::RequestBuilder; +use serde::Serialize; + +pub struct Maestro { + api_key: String, + http_client: reqwest::Client, + pub base_url: String, +} + +impl Maestro { + pub fn new(api_key: String, network: String) -> Self { + let cfg = Config::get_config(); + let base_url = format!( + "https://{}.gomaestro-api.org/{}", + &network, &cfg.client.version + ); + let http_client = reqwest::Client::builder() + .timeout(std::time::Duration::from_secs(300)) + .build() + .expect("Failed to create HTTP client"); + + Maestro { + api_key, + http_client, + base_url, + } + } + + async fn send_request( + &self, + req: RequestBuilder, + response_body: &mut String, + ) -> Result<(), Box> { + let req = req + .header("Accept", "application/json") + .header("api-key", &self.api_key) + .build()?; + + let response = self.http_client.execute(req).await?; + + if response.status().is_success() { + *response_body = response.text().await?; + Ok(()) + } else { + Err(format!("Error: {}", response.status()).into()) + } + } + + pub async fn get(&self, url: &str) -> Result> { + let req = self.http_client.get(format!("{}{}", &self.base_url, url)); + let mut response_body = String::new(); + self.send_request(req, &mut response_body).await?; + Ok(response_body) + } + + pub async fn post( + &self, + url: &str, + body: T, + ) -> Result> { + let json_body = serde_json::to_string(&body)?; + + let req = self + .http_client + .post(format!("{}{}", &self.base_url, url)) + .header("Accept", "application/json") + .header("api-key", &self.api_key) + .header("Content-Type", "application/json") + .body(json_body); + + let mut response_body = String::new(); + self.send_request(req, &mut response_body).await?; + Ok(response_body) + } +} diff --git a/src/client/mod.rs b/src/client/mod.rs new file mode 100644 index 0000000..495fccc --- /dev/null +++ b/src/client/mod.rs @@ -0,0 +1,16 @@ +pub mod accounts; +pub mod addresses; +pub mod asset; +pub mod asset_policy; +pub mod block_info; +mod config; +pub mod datum; +pub mod ecosystem; +pub mod epochs; +pub mod general; +pub mod linear_vesting; +pub mod maestro; +pub mod pools; +pub mod scripts; +pub mod transactions; +pub mod txmanager; diff --git a/src/client/pools.rs b/src/client/pools.rs new file mode 100644 index 0000000..b1714f0 --- /dev/null +++ b/src/client/pools.rs @@ -0,0 +1,106 @@ +use super::maestro::Maestro; +use crate::{ + models::pools::{ + PoolMintedBlocks, RegisteredPools, StakePoolDelegators, StakePoolHistory, + StakePoolInformation, StakePoolMetadata, StakePoolRelays, StakePoolUpdates, + }, + utils::Parameters, +}; +use std::error::Error; + +impl Maestro { + pub async fn list_of_registered_pools( + &self, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/pools{}", formatted_params); + let resp = self.get(&url).await?; + let registered_pools = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(registered_pools) + } + + pub async fn stake_pool_minted_blocks( + &self, + pool_id: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/pools/{}/blocks{}", pool_id, formatted_params); + let resp = self.get(&url).await?; + let pool_minted_blocks = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(pool_minted_blocks) + } + + pub async fn stake_pool_delegators( + &self, + pool_id: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/pools/{}/delegators{}", pool_id, formatted_params); + let resp = self.get(&url).await?; + let stake_pool_delegators = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(stake_pool_delegators) + } + + pub async fn stake_pool_history( + &self, + pool_id: &str, + params: Option, + ) -> Result> { + let formatted_params = params.map(|p| p.format()).unwrap_or_default(); + let url = format!("/pools/{}/history{}", pool_id, formatted_params); + let resp = self.get(&url).await?; + let stake_pool_history = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(stake_pool_history) + } + + pub async fn stake_pool_information( + &self, + pool_id: &str, + ) -> Result> { + let url = format!("/pools/{}/info", pool_id); + let resp = self.get(&url).await?; + let stake_pool_information = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(stake_pool_information) + } + + pub async fn stake_pool_metadata( + &self, + pool_id: &str, + ) -> Result> { + let url = format!("/pools/{}/metadata", pool_id); + let resp = self.get(&url).await?; + let stake_pool_metadata = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(stake_pool_metadata) + } + + pub async fn stake_pool_relays( + &self, + pool_id: &str, + ) -> Result> { + let url = format!("/pools/{}/relays", pool_id); + let resp = self.get(&url).await?; + let stake_pool_relays = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(stake_pool_relays) + } + + pub async fn stake_pool_updates( + &self, + pool_id: &str, + ) -> Result> { + let url = format!("/pools/{}/updates", pool_id); + let resp = self.get(&url).await?; + let stake_pool_updates = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(stake_pool_updates) + } +} diff --git a/src/client/scripts.rs b/src/client/scripts.rs new file mode 100644 index 0000000..a9f1f76 --- /dev/null +++ b/src/client/scripts.rs @@ -0,0 +1,14 @@ +use super::maestro::Maestro; +use crate::models::scripts::ScriptByHash; +use std::error::Error; + +impl Maestro { + pub async fn script_by_hash(&self, hash: &str) -> Result> { + let url = format!("/scripts/{}", hash); + let resp = self.get(&url).await?; + + let script_by_hash = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(script_by_hash) + } +} diff --git a/src/client/transactions.rs b/src/client/transactions.rs new file mode 100644 index 0000000..8fcf4c9 --- /dev/null +++ b/src/client/transactions.rs @@ -0,0 +1,107 @@ +use super::maestro::Maestro; +use crate::models::{ + common::BasicResponse, + transactions::{ + EvaluateTx, RedeemerEvaluation, TransactionDetails, TransactionOutputFromReference, + TransactionOutputsFromReferences, + }, +}; +use std::{collections::HashMap, error::Error}; + +impl Maestro { + pub async fn address_by_output_reference( + &self, + tx_hash: &str, + index: i32, + ) -> Result> { + let url = format!("/transactions/{}/outputs/{}/address", tx_hash, index); + let resp = self.get(&url).await?; + let address_by_output_reference = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(address_by_output_reference) + } + + pub async fn submit_tx(&self, cbor: &str) -> Result> { + let url = "/submit/tx"; + let resp = self.post(url, cbor.to_string()).await?; + let submit_tx = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(submit_tx) + } + + pub async fn transaction_cbor(&self, tx_hash: &str) -> Result> { + let url = format!("/transactions/{}/cbor", tx_hash); + let resp = self.get(&url).await?; + let transaction_cbor = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(transaction_cbor) + } + + pub async fn transaction_details( + &self, + tx_hash: &str, + ) -> Result> { + let url = format!("/transactions/{}", tx_hash); + let resp = self.get(&url).await?; + let transaction_details = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(transaction_details) + } + + pub async fn transaction_output_from_reference( + &self, + tx_hash: &str, + index: i32, + params: Option>, + ) -> Result> { + let formatted_params = params.map_or("".to_string(), |p| { + p.iter() + .map(|(k, v)| format!("{}={}", k, v)) + .collect::>() + .join("&") + .to_string() + }); + let url = format!( + "/transactions/{}/outputs/{}/txo{}", + tx_hash, index, formatted_params + ); + let resp = self.get(&url).await?; + let transaction_output_from_reference = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(transaction_output_from_reference) + } + + pub async fn transaction_outputs_from_references( + &self, + references: Vec, + params: Option>, + ) -> Result> { + let formatted_params = params.map_or("".to_string(), |p| { + p.iter() + .map(|(k, v)| format!("{}={}", k, v)) + .collect::>() + .join("&") + .to_string() + }); + let url = format!("/transactions/outputs{}", formatted_params); + let resp = self.post(&url, references).await?; + let transaction_outputs_from_references = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(transaction_outputs_from_references) + } + + pub async fn evaluate_tx( + &self, + tx_cbor: &str, + additional_utxos: Vec, + ) -> Result, Box> { + let url = "/transactions/evaluate"; + let body = EvaluateTx { + cbor: tx_cbor.to_string(), + additional_utxos, + }; + let resp = self.post(url, &body).await?; + let redeemer_evaluations = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(redeemer_evaluations) + } +} diff --git a/src/client/txmanager.rs b/src/client/txmanager.rs new file mode 100644 index 0000000..d86926b --- /dev/null +++ b/src/client/txmanager.rs @@ -0,0 +1,38 @@ +use super::maestro::Maestro; +use crate::models::{common::BasicResponse, txmanager::TxManagerState}; +use std::error::Error; + +impl Maestro { + pub async fn tx_manager_history(&self) -> Result, Box> { + let url = "/txmanager/history"; + let resp = self.get(url).await?; + let tx_manager_states = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(tx_manager_states) + } + + pub async fn tx_manager_submit(&self, cbor: &str) -> Result> { + let url = "/txmanager"; + let resp = self.post(url, cbor.to_string()).await?; + let submit_tx = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(submit_tx) + } + + pub async fn tx_manager_submit_turbo( + &self, + cbor: &str, + ) -> Result> { + let url = "/txmanager/turbosubmit"; + let resp = self.post(url, cbor.to_string()).await?; + let submit_tx = serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(submit_tx) + } + + pub async fn tx_manager_state(&self, tx_hash: &str) -> Result> { + let url = format!("/txmanager/{}/state", tx_hash); + let resp = self.get(&url).await?; + let tx_manager_state = + serde_json::from_str(&resp).map_err(|e| Box::new(e) as Box)?; + Ok(tx_manager_state) + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..5e1e068 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,4 @@ +pub mod client; +pub use client::maestro::Maestro; +pub mod models; +pub mod utils; diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/src/models/accounts.rs b/src/models/accounts.rs new file mode 100644 index 0000000..e291f14 --- /dev/null +++ b/src/models/accounts.rs @@ -0,0 +1,100 @@ +use crate::utils; +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct AccountAddresses { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct AccountAsset { + pub amount: i64, + pub unit: String, +} + +#[derive(Deserialize)] +pub struct AccountAssets { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct StakeAccountHistoryItem { + pub active_stake: i64, + pub epoch_no: i64, + pub pool_id: String, +} + +#[derive(Deserialize)] +pub struct StakeAccountHistory { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct AccountInformation { + pub delegated_pool: String, + pub registered: bool, + pub rewards_available: i64, + pub stake_address: String, + pub total_balance: i64, + pub total_rewarded: i64, + pub total_withdrawn: i64, + pub utxo_balance: i64, +} + +#[derive(Deserialize)] +pub struct StakeAccountInformation { + pub data: AccountInformation, + pub last_updated: utils::LastUpdated, +} + +#[derive(Deserialize)] +pub enum StakeRewardType { + Member, + Leader, + Refund, +} + +#[derive(Deserialize)] +pub struct StakeAccountReward { + pub amount: i64, + pub earned_epoch: i64, + pub pool_id: String, + pub spendable_epoch: i64, + pub r#type: StakeRewardType, +} + +#[derive(Deserialize)] +pub struct StakeAccountRewards { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub enum StakeUpdateAction { + Registration, + Deregistration, + Delegation, + Withdrawal, +} + +#[derive(Deserialize)] +pub struct StakeAccountUpdate { + pub absolute_slot: i64, + pub action: StakeUpdateAction, + pub epoch_no: i64, + pub tx_hash: String, +} + +#[derive(Deserialize)] +pub struct StakeAccountUpdates { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} diff --git a/src/models/addresses.rs b/src/models/addresses.rs new file mode 100644 index 0000000..755c35e --- /dev/null +++ b/src/models/addresses.rs @@ -0,0 +1,107 @@ +use crate::utils; +use serde::Deserialize; +use std::collections::HashMap; + +#[derive(Deserialize)] +pub enum Network { + Mainnet, + Testnet, +} + +#[derive(Deserialize)] +pub enum CredentialKind { + Key, + Script, +} + +#[derive(Deserialize)] +pub struct PaymentCredential { + pub bech32: String, + pub hex: String, + pub kind: CredentialKind, +} + +#[derive(Deserialize)] +pub struct StakingCredential { + pub bech32: String, + pub hex: String, + pub kind: CredentialKind, + pub pointer: Option>, + pub reward_address: String, +} + +#[derive(Deserialize)] +pub struct DecodedAddress { + pub bech32: String, + pub hex: String, + pub network: Network, + pub payment_cred: PaymentCredential, + pub staking_cred: StakingCredential, +} + +#[derive(Deserialize)] +pub struct AddressTransactionCount { + pub data: i32, + pub last_updated: utils::LastUpdated, +} + +#[derive(Deserialize)] +pub struct Transaction { + pub input: bool, + pub output: bool, + pub slot: i64, + pub tx_hash: String, +} + +#[derive(Deserialize)] +pub struct AddressTransactions { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct UtxoReference { + pub index: i64, + pub tx_hash: String, +} + +#[derive(Deserialize)] +pub struct UtxoReferencesAtAddress { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct Asset { + pub amount: i64, + pub unit: String, +} + +#[derive(Deserialize)] +pub struct Utxo { + pub address: String, + pub assets: Vec, + pub datum: Option>, + pub index: i64, + pub reference_script: ReferenceScript, + pub tx_hash: String, + pub slot: i64, + pub tx_out_cbor: String, +} + +#[derive(Deserialize)] +pub struct ReferenceScript { + pub bytes: String, + pub hash: String, + pub json: HashMap, + pub r#type: String, +} + +#[derive(Deserialize)] +pub struct UtxosAtAddress { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} diff --git a/src/models/asset.rs b/src/models/asset.rs new file mode 100644 index 0000000..5bd9f8c --- /dev/null +++ b/src/models/asset.rs @@ -0,0 +1,81 @@ +use super::asset_policy::{AssetInformation, PolicyTransaction}; +use crate::utils; +use serde::Deserialize; +use std::collections::HashMap; + +#[derive(Deserialize)] +pub struct AccountHoldingAsset { + pub account: String, + pub amount: i64, +} + +#[derive(Deserialize)] +pub struct AccountsHoldingAsset { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct AddressHoldingAsset { + pub address: String, + pub amount: i64, +} + +#[derive(Deserialize)] +pub struct AddressesHoldingAsset { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct AssetInformations { + pub data: AssetInformation, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct AssetTransactions { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct Metadata { + pub json: Option>, + pub key: Option>, +} + +#[derive(Deserialize)] +pub struct AssetUpdate { + pub block_timestamp: i64, + pub metadata: Metadata, + pub mint_amount: i64, + pub tx_hash: String, +} + +#[derive(Deserialize)] +pub struct AssetUpdates { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct AssetUtxo { + pub address: String, + pub amount: i64, + pub index: i64, + pub slot: i64, + pub tx_hash: String, +} + +#[derive(Deserialize)] +pub struct AssetUtxos { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} diff --git a/src/models/asset_policy.rs b/src/models/asset_policy.rs new file mode 100644 index 0000000..8c44f5e --- /dev/null +++ b/src/models/asset_policy.rs @@ -0,0 +1,85 @@ +use super::addresses::Utxo; +use crate::utils; +use serde::Deserialize; +use std::collections::HashMap; + +#[derive(Deserialize)] +pub struct AssetNameAndAmount { + pub name: String, + pub amount: i64, +} + +#[derive(Deserialize)] +pub struct AccountHolding { + pub account: String, + pub assets: Vec, +} + +#[derive(Deserialize)] +pub struct AccountsHoldingPolicy { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct AddressHolding { + pub address: String, + pub assets: Vec, +} + +#[derive(Deserialize)] +pub struct AddressesHoldingPolicy { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct Standards { + pub cip25_metadata: HashMap, + pub cip68_metadata: HashMap, +} + +#[derive(Deserialize)] +pub struct AssetInformation { + pub asset_name: String, + pub asset_name_ascii: String, + pub asset_standards: Standards, + pub burn_tx_count: i64, + pub fingerprint: String, + pub first_mint_time: i64, + pub first_mint_tx: String, + pub latest_mint_tx_metadata: HashMap, + pub mint_tx_count: i64, + pub token_registry_metadata: HashMap, + pub total_supply: i64, +} + +#[derive(Deserialize)] +pub struct PolicyInformation { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct PolicyTransaction { + pub block_height: i64, + pub epoch_no: i64, + pub tx_hash: Option, +} + +#[derive(Deserialize)] +pub struct PolicyTransactions { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct UtxosContainingPolicy { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} diff --git a/src/models/common.rs b/src/models/common.rs new file mode 100644 index 0000000..a7738f6 --- /dev/null +++ b/src/models/common.rs @@ -0,0 +1,8 @@ +use crate::utils::LastUpdated; +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct BasicResponse { + pub data: String, + pub last_updated: LastUpdated, +} diff --git a/src/models/datum.rs b/src/models/datum.rs new file mode 100644 index 0000000..450181f --- /dev/null +++ b/src/models/datum.rs @@ -0,0 +1,15 @@ +use crate::utils; +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +#[derive(Serialize, Deserialize)] +pub struct Datum { + pub bytes: String, + pub json: Value, +} + +#[derive(Deserialize)] +pub struct DatumFromHash { + pub data: Datum, + pub last_updated: utils::LastUpdated, +} diff --git a/src/models/epochs.rs b/src/models/epochs.rs new file mode 100644 index 0000000..b1e4019 --- /dev/null +++ b/src/models/epochs.rs @@ -0,0 +1,17 @@ +use crate::utils; +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct Epoch { + pub blk_count: i32, + pub epoch_no: i32, + pub fees: i32, + pub start_time: i32, + pub tx_count: i32, +} + +#[derive(Deserialize)] +pub struct EpochResp { + pub data: Epoch, + pub last_updated: utils::LastUpdated, +} diff --git a/src/models/general.rs b/src/models/general.rs new file mode 100644 index 0000000..6bd98c2 --- /dev/null +++ b/src/models/general.rs @@ -0,0 +1,92 @@ +use crate::utils; +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct ChainTipData { + pub block_hash: String, + pub height: i64, + pub slot: i64, +} + +#[derive(Deserialize)] +pub struct ChainTip { + pub data: ChainTipData, + pub last_updated: utils::LastUpdated, +} + +#[derive(Deserialize)] +pub struct EraTimeStamp { + pub epoch: i64, + pub slot: i64, + pub time: i64, +} + +#[derive(Deserialize)] +pub struct EraParams { + pub epoch_length: i64, + pub safe_zone: i64, + pub slot_length: i64, +} + +#[derive(Deserialize)] +pub struct Era { + pub end: EraTimeStamp, + pub parameters: EraParams, + pub start: EraTimeStamp, +} + +#[derive(Deserialize)] +pub struct EraHistory { + pub data: Vec, + pub last_updated: utils::LastUpdated, +} + +#[derive(Deserialize)] +pub struct ProtocolParameters { + pub data: ProtocolParams, + pub last_updated: utils::LastUpdated, +} + +#[derive(Deserialize)] +pub struct ExUnits { + pub memory: i64, + pub steps: i64, +} + +#[derive(Deserialize)] +pub struct StringExUnits { + pub memory: String, + pub steps: String, +} + +#[derive(Deserialize)] +pub struct ProtocolVersion { + pub major: i64, + pub minor: i64, +} + +#[derive(Deserialize)] +pub struct ProtocolParams { + pub coins_per_utxo_byte: i64, + pub collateral_percentage: i64, + pub cost_models: serde_json::Value, + pub desired_number_of_pools: i64, + pub max_block_body_size: i64, + pub max_block_header_size: i64, + pub max_collateral_inputs: i64, + pub max_execution_units_per_block: ExUnits, + pub max_execution_units_per_transaction: ExUnits, + pub max_tx_size: i64, + pub max_value_size: i64, + pub min_fee_coefficient: i64, + pub min_fee_constant: i64, + pub min_pool_cost: i64, + pub monetary_expansion: String, + pub pool_deposit: i64, + pub pool_influence: String, + pub pool_retirement_epoch_bound: i64, + pub prices: StringExUnits, + pub protocol_version: ProtocolVersion, + pub stake_key_deposit: i64, + pub treasury_expansion: String, +} diff --git a/src/models/linear_vesting.rs b/src/models/linear_vesting.rs new file mode 100644 index 0000000..aac97d2 --- /dev/null +++ b/src/models/linear_vesting.rs @@ -0,0 +1,24 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +pub struct LockTransaction { + pub cbor_hex: String, + pub tx_hash: String, +} + +#[derive(Serialize, Deserialize)] +pub struct VestingState { + pub asset_name: String, + pub asset_symbol: String, + pub remaining_vesting_quantity: i64, + pub total_installments: i64, + pub total_vesting_quantity: i64, + pub vesting_period_start: i64, + pub vesting_period_end: i64, +} + +#[derive(Serialize, Deserialize)] +pub struct CollectTransaction { + pub cbor_hex: String, + pub tx_hash: String, +} diff --git a/src/models/mod.rs b/src/models/mod.rs new file mode 100644 index 0000000..8eeb790 --- /dev/null +++ b/src/models/mod.rs @@ -0,0 +1,13 @@ +pub mod accounts; +pub mod addresses; +pub mod asset; +pub mod asset_policy; +pub mod common; +pub mod datum; +pub mod epochs; +pub mod general; +pub mod linear_vesting; +pub mod pools; +pub mod scripts; +pub mod transactions; +pub mod txmanager; diff --git a/src/models/pools.rs b/src/models/pools.rs new file mode 100644 index 0000000..d879f5b --- /dev/null +++ b/src/models/pools.rs @@ -0,0 +1,144 @@ +use crate::utils; +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct Pool { + pub pool_id_bech32: String, + pub ticker: String, +} + +#[derive(Deserialize)] +pub struct RegisteredPools { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct Block { + pub abs_slot: i64, + pub block_hash: String, + pub block_height: i64, + pub block_time: i64, + pub epoch_no: i64, + pub epoch_slot: i64, +} + +#[derive(Deserialize)] +pub struct PoolMintedBlocks { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct StakePoolDelegator { + pub active_epoch_no: i64, + pub amount: String, + pub latest_delegation_tx_hash: String, + pub stake_address: String, +} + +#[derive(Deserialize)] +pub struct StakePoolDelegators { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct StakePoolHistoryData { + pub active_stake: i64, + pub active_stake_pct: String, + pub block_cnt: i64, + pub deleg_rewards: i64, + pub delegator_cnt: i64, + pub epoch_no: i64, + pub epoch_ros: String, + pub fixed_cost: i64, + pub margin: i64, + pub pool_fees: i64, + pub saturation_pct: serde_json::Value, +} + +#[derive(Deserialize)] +pub struct StakePoolHistory { + pub data: Vec, + pub last_updated: utils::LastUpdated, + pub next_cursor: Option, +} + +#[derive(Deserialize)] +pub struct Relay { + pub dns: String, + pub ipv4: String, + pub ipv6: String, + pub port: i64, + pub srv: String, +} + +#[derive(Deserialize)] +pub struct StakePoolDetails { + pub active_epoch_no: i64, + pub active_stake: i64, + pub block_count: i64, + pub fixed_cost: i64, + pub live_delegators: i64, + pub live_pledge: i64, + pub live_saturation: String, + pub live_stake: i64, + pub margin: i64, + pub meta_hash: serde_json::Value, + pub meta_json: serde_json::Value, + pub meta_url: serde_json::Value, + pub op_cert: String, + pub op_cert_counter: i64, + pub owners: Vec, + pub pledge: i64, + pub pool_id_bech32: String, + pub pool_id_hex: String, + pub pool_status: String, + pub relays: Vec, + pub retiring_epoch: serde_json::Value, + pub reward_addr: String, + pub sigma: String, + pub vrf_key_hash: String, +} + +#[derive(Deserialize)] +pub struct StakePoolInformation { + pub data: StakePoolDetails, + pub last_updated: utils::LastUpdated, +} + +#[derive(Deserialize)] +pub struct Poolmetadata { + pub meta_hash: String, + pub meta_json: serde_json::Value, + pub meta_url: String, + pub pool_id_bech32: String, +} + +#[derive(Deserialize)] +pub struct StakePoolMetadata { + pub data: Poolmetadata, + pub last_updated: utils::LastUpdated, +} + +#[derive(Deserialize)] +pub struct RelaysAndId { + pub pool_id_bech32: String, + pub relays: Vec, +} + +#[derive(Deserialize)] +pub struct StakePoolRelays { + pub data: Vec, + pub last_updated: utils::LastUpdated, +} + +#[derive(Deserialize)] +pub struct StakePoolUpdates { + pub data: Vec, + pub last_updated: utils::LastUpdated, +} diff --git a/src/models/scripts.rs b/src/models/scripts.rs new file mode 100644 index 0000000..36fcc13 --- /dev/null +++ b/src/models/scripts.rs @@ -0,0 +1,23 @@ +use crate::utils; +use serde::Deserialize; +use serde::Serialize; + +#[derive(Serialize, Deserialize)] +pub enum ScriptVersion { + PlutusV1, + PlutusV2, +} + +#[derive(Serialize, Deserialize)] +pub struct Script { + pub bytes: String, + pub hash: String, + pub json: serde_json::Value, + pub r#type: ScriptVersion, +} + +#[derive(Deserialize)] +pub struct ScriptByHash { + pub data: Script, + pub last_updated: utils::LastUpdated, +} diff --git a/src/models/transactions.rs b/src/models/transactions.rs new file mode 100644 index 0000000..fa717d7 --- /dev/null +++ b/src/models/transactions.rs @@ -0,0 +1,96 @@ +use crate::utils; +use serde::{Deserialize, Serialize}; + +use super::{addresses::Utxo, scripts::Script}; + +#[derive(Deserialize)] +pub struct Certificates { + pub mir_transfers: Vec, + pub pool_registrations: Vec, + pub pool_retirements: Vec, + pub stake_delegations: Vec, + pub stake_deregistrations: Vec, + pub stake_registrations_reserves: Vec, +} + +#[derive(Deserialize)] +pub struct Redeemers { + pub certificates: Vec, + pub mints: Vec, + pub spends: Vec, + pub withdrawals: Vec, +} + +#[derive(Deserialize)] +pub struct TransactionDetail { + pub additional_signers: Vec, + pub block_absolute_slot: i64, + pub block_hash: String, + pub block_height: i64, + pub block_timestamp: i64, + pub block_tx_index: i64, + pub certificates: Certificates, + pub collateral_inputs: Vec, + pub collateral_return: serde_json::Value, + pub deposit: i64, + pub fee: i64, + pub inputs: Vec, + pub invalid_before: i64, + pub invalid_hereafter: i64, + pub metadata: serde_json::Value, + pub mint: Vec, + pub outputs: Vec, + pub redeemers: Vec, + pub reference_inputs: Vec, + pub scripts_executed: Vec