whisky_provider/blockfrost/
mod.rs1mod evaluator;
2mod fetcher;
3pub mod models;
4mod submitter;
5pub mod utils;
6use std::collections::HashMap;
7
8use whisky_common::*;
9
10use reqwest::RequestBuilder;
11use serde::Serialize;
12
13#[derive(Debug, Clone)]
14pub struct Blockfrost {
15 project_id: String,
16 http_client: reqwest::Client,
17 pub base_url: String,
18}
19
20impl Blockfrost {
21 pub fn new(project_id: String, network: String) -> Self {
22 let base_url = format!("https://cardano-{}.blockfrost.io/api/v0", &network);
23 let http_client = reqwest::Client::builder()
24 .timeout(std::time::Duration::from_secs(300))
25 .build()
26 .expect("Failed to create HTTP client");
27
28 Blockfrost {
29 project_id,
30 http_client,
31 base_url,
32 }
33 }
34
35 async fn send_request(
36 &self,
37 req: RequestBuilder,
38 response_body: &mut String,
39 ) -> Result<(), Box<dyn std::error::Error>> {
40 let req = req
41 .header("Accept", "application/json")
42 .header("project_id", &self.project_id)
43 .build()?;
44
45 let response = self.http_client.execute(req).await?;
46
47 if response.status().is_success() {
48 *response_body = response.text().await?;
49 Ok(())
50 } else {
51 Err(format!("Error: {}", response.status()).into())
52 }
53 }
54
55 pub async fn get(&self, url: &str) -> Result<String, WError> {
56 let req = self.http_client.get(format!("{}{}", &self.base_url, url));
57 let mut response_body = String::new();
58 self.send_request(req, &mut response_body)
59 .await
60 .map_err(WError::from_err("Blockfrost - get - send_request"))?;
61 Ok(response_body)
62 }
63
64 pub async fn post<T: Serialize>(&self, url: &str, body: T) -> Result<String, WError> {
65 let json_body = serde_json::to_string(&body)
66 .map_err(WError::from_err("Blockfrost - post - json_body"))?;
67
68 let req = self
69 .http_client
70 .post(format!("{}{}", &self.base_url, url))
71 .header("Content-Type", "application/json")
72 .body(json_body);
73
74 let mut response_body = String::new();
75 self.send_request(req, &mut response_body)
76 .await
77 .map_err(WError::from_err("Blockfrost - post - send_request"))?;
78 Ok(response_body)
79 }
80
81 async fn fetch_specific_script(&self, script_hash: &str) -> Result<models::Script, WError> {
82 let url = format!("/scripts/{}", script_hash);
83
84 let resp = self
85 .get(&url)
86 .await
87 .map_err(WError::from_err("blockfrost::fetch_specific_script"))?;
88
89 let script: models::Script = serde_json::from_str(&resp).map_err(WError::from_err(
90 "blockfrost::fetch_specific_script type error",
91 ))?;
92
93 Ok(script)
94 }
95 async fn fetch_plutus_script_cbor(&self, script_hash: &str) -> Result<String, WError> {
96 let url = format!("/scripts/{}/cbor", script_hash);
97
98 let resp = self
99 .get(&url)
100 .await
101 .map_err(WError::from_err("blockfrost::fetch_plutus_script_cbor"))?;
102
103 let script_cbor: HashMap<String, String> = serde_json::from_str(&resp).map_err(
104 WError::from_err("blockfrost::fetch_plutus_script_cbor type error"),
105 )?;
106 let cbor = script_cbor["cbor"].clone();
107
108 Ok(cbor)
109 }
110
111 async fn fetch_native_script_json(
112 &self,
113 script_hash: &str,
114 ) -> Result<serde_json::Value, WError> {
115 let url = format!("/scripts/{}/json", script_hash);
116
117 let resp = self
118 .get(&url)
119 .await
120 .map_err(WError::from_err("blockfrost::fetch_native_script_json"))?;
121
122 let script_json: HashMap<String, serde_json::Value> = serde_json::from_str(&resp).map_err(
123 WError::from_err("blockfrost::fetch_native_script_json type error"),
124 )?;
125 let json = script_json["json"].clone();
126
127 Ok(json)
128 }
129}
130
131#[derive(Clone, Debug)]
132pub struct BlockfrostProvider {
133 pub blockfrost_client: Blockfrost,
134}
135
136impl BlockfrostProvider {
137 pub fn new(api_key: &str, network: &str) -> BlockfrostProvider {
138 let blockfrost_client = Blockfrost::new(api_key.to_string(), network.to_string());
139 BlockfrostProvider { blockfrost_client }
140 }
141}