aptos_client_icp/client/
mod.rs1use std::str::FromStr;
2
3use ic_cdk::api::management_canister::http_request::{
4 http_request, CanisterHttpRequestArgument, HttpHeader, HttpMethod, TransformContext,
5};
6use serde::{de::DeserializeOwned, Serialize};
7use url::Url;
8
9use crate::http::{Request, Response};
10
11#[derive(Clone)]
12pub struct CallOptions {
13 pub max_response_bytes: Option<u64>,
14 pub transform: Option<TransformContext>,
15}
16
17impl Default for CallOptions {
18 fn default() -> Self {
19 Self {
20 max_response_bytes: None,
21 transform: None,
22 }
23 }
24}
25
26fn http_request_required_cycles(arg: &CanisterHttpRequestArgument) -> u128 {
31 let max_response_bytes = match arg.max_response_bytes {
32 Some(ref n) => *n as u128,
33 None => 2 * 1024 * 1024u128, };
35 let arg_raw = candid::utils::encode_args((arg,)).expect("Failed to encode arguments.");
36 (3_000_000u128
38 + 60_000u128 * 13
39 + (arg_raw.len() as u128 + "http_request".len() as u128) * 400
40 + max_response_bytes * 800)
41 * 13
42}
43
44#[derive(Clone)]
45pub struct HttpProvider {}
46
47impl HttpProvider {
48 pub fn new() -> Self {
49 Self {}
50 }
51}
52
53impl HttpProvider {
54 pub async fn send(&self, request: Request, opts: CallOptions) -> Response {
55 let body = request.body().unwrap_or_default();
56 let method = match request.method() {
57 crate::http::HttpMethod::GET => HttpMethod::GET,
58 crate::http::HttpMethod::POST => HttpMethod::POST,
59 crate::http::HttpMethod::HEAD => HttpMethod::HEAD,
60 _ => HttpMethod::GET,
61 };
62 let mut url = request.url.clone();
63 if !request.query().is_empty() {
64 let mut queries = request
65 .query()
66 .iter()
67 .map(|(k, v)| (k.to_string(), v.to_string()))
68 .collect::<Vec<(String, String)>>();
69 let first = queries.remove(0);
70 url = format!("{}?{}={}", url, first.0, first.1);
71 queries.iter().for_each(|(k, v)| {
72 url = format!("&{}?{}={}", url, k, v);
73 });
74 }
75
76 let headers = request
77 .headers()
78 .iter()
79 .map(|(k, v)| HttpHeader {
80 name: k.as_str().to_string(),
81 value: v.to_string(),
82 })
83 .collect();
84
85 let args: CanisterHttpRequestArgument = CanisterHttpRequestArgument {
86 body: Some(body.to_vec()),
87 url: url,
88 headers,
89 max_response_bytes: opts.max_response_bytes,
90 method,
91 transform: opts.transform, };
93 let cycles = http_request_required_cycles(&args);
94 match http_request(args, cycles).await {
95 Ok(response) => {
96 let status: u16 = TryFrom::try_from(response.0.status.0).unwrap();
97 Response::new(
98 status,
99 String::from_utf8_lossy(response.0.body.as_slice()).to_string(),
100 )
101 }
102 Err(e) => Response::new(500, e.1),
103 }
104 }
105}
106
107#[derive(Clone)]
108pub enum Provider {
109 Http(HttpProvider),
110}
111
112impl Provider {
113 pub fn new() -> Self {
114 Self::Http(HttpProvider::new())
115 }
116}