diff --git a/motoko/exchange_rate/README.md b/motoko/exchange_rate/README.md index 1d2e0fa19..4393a241a 100644 --- a/motoko/exchange_rate/README.md +++ b/motoko/exchange_rate/README.md @@ -20,7 +20,7 @@ For example, the following aspect is particularly relevant for this app: * [Certify query responses if they are relevant for security](https://internetcomputer.org/docs/current/references/security/general-security-best-practices#certify-query-responses-if-they-are-relevant-for-security), since this is essential when e.g. displaying important financial data (in this case exchange rates) in the frontend that may be used by users to decide on future transactions (based on the rate information). ## Dependencies -- [ic-cdk v0.5.7](https://crates.io/crates/ic-cdk/0.5.7) or above -- [dfx v0.12.0-beta.3](https://github.com/dfinity/sdk/releases/tag/0.12.0-beta.3) or above. +- [ic-cdk v0.6.5](https://crates.io/crates/ic-cdk/0.6.5) or above +- [dfx v0.12.0-beta.6](https://github.com/dfinity/sdk/releases/tag/0.12.0-beta.6) or above. Use below command to install: -```DFX_VERSION=0.12.0-beta.3 sh -ci "$(curl -fsSL https://internetcomputer.org/install.sh)"``` +```DFX_VERSION=0.12.0-beta.6 sh -ci "$(curl -fsSL https://internetcomputer.org/install.sh)"``` diff --git a/motoko/exchange_rate/deploy.sh b/motoko/exchange_rate/deploy.sh index 55957ae18..e8babcf67 100755 --- a/motoko/exchange_rate/deploy.sh +++ b/motoko/exchange_rate/deploy.sh @@ -25,7 +25,7 @@ if [[ $ENV == "local" ]]; then # Check DFX version version=$(dfx -V | sed 's/dfx\ //g' | sed 's/-.*$//g') if [[ "$version" < "0.12.0" ]]; then - echo "dfx 0.12.0 or above required. Please do: dfx upgrade" + echo "dfx 0.12.0-beta.6 or above required. Please do: DFX_VERSION=0.12.0-beta.6 sh -ci \"$(curl -fsSL https://internetcomputer.org/install.sh)\"" exit 1 fi diff --git a/motoko/exchange_rate/src/Main.mo b/motoko/exchange_rate/src/Main.mo index 1967c16a4..054b41496 100644 --- a/motoko/exchange_rate/src/Main.mo +++ b/motoko/exchange_rate/src/Main.mo @@ -90,10 +90,10 @@ shared actor class ExchangeRate() = this { ); }; - public query func transform(raw : Types.CanisterHttpResponsePayload) : async Types.CanisterHttpResponsePayload { + public query func transform(raw : Types.TransformArgs) : async Types.CanisterHttpResponsePayload { let transformed : Types.CanisterHttpResponsePayload = { - status = raw.status; - body = raw.body; + status = raw.response.status; + body = raw.response.body; headers = [ { name = "Content-Security-Policy"; @@ -260,13 +260,18 @@ shared actor class ExchangeRate() = this { let url = "https://" # host # "/products/ICP-USD/candles?granularity=" # Nat64.toText(REMOTE_FETCH_GRANULARITY) # "&start=" # Nat64.toText(start_timestamp) # "&end=" # Nat64.toText(end_timestamp); Debug.print(url); + let transform_context : Types.TransformContext = { + function = transform; + context = Blob.fromArray([]); + }; + let request : Types.CanisterHttpRequestArgs = { url = url; max_response_bytes = ?MAX_RESPONSE_BYTES; headers = request_headers; body = null; method = #get; - transform = ?(#function(transform)); + transform = ?transform_context; }; try { Cycles.add(2_000_000_000); @@ -325,13 +330,17 @@ shared actor class ExchangeRate() = this { #Ok : Text; #Err : Text; } { + let transform_context : Types.TransformContext = { + function = transform; + context = Blob.fromArray([]); + }; let request : Types.CanisterHttpRequestArgs = { url = url; max_response_bytes = ?MAX_RESPONSE_BYTES; headers = []; body = null; method = #get; - transform = ?(#function(transform)); + transform = ?transform_context; }; try { Cycles.add(2_000_000_000); diff --git a/motoko/exchange_rate/src/Types.mo b/motoko/exchange_rate/src/Types.mo index c3b7a4fd4..557093ea2 100644 --- a/motoko/exchange_rate/src/Types.mo +++ b/motoko/exchange_rate/src/Types.mo @@ -26,8 +26,9 @@ module Types { #head; }; - public type TransformType = { - #function : shared CanisterHttpResponsePayload -> async CanisterHttpResponsePayload; + public type TransformContext = { + function : shared query TransformArgs -> async CanisterHttpResponsePayload; + context : Blob; }; public type CanisterHttpRequestArgs = { @@ -36,9 +37,7 @@ module Types { headers : [HttpHeader]; body : ?[Nat8]; method : HttpMethod; - transform : ?{ - #function : shared query CanisterHttpResponsePayload -> async CanisterHttpResponsePayload; - }; + transform : ?TransformContext; }; public type CanisterHttpResponsePayload = { @@ -47,6 +46,11 @@ module Types { body : [Nat8]; }; + public type TransformArgs = { + response : CanisterHttpResponsePayload; + context : Blob; + }; + public type IC = actor { http_request : Types.CanisterHttpRequestArgs -> async Types.CanisterHttpResponsePayload; }; diff --git a/rust/exchange_rate/Cargo.lock b/rust/exchange_rate/Cargo.lock index 470633040..5ba7a0a17 100644 --- a/rust/exchange_rate/Cargo.lock +++ b/rust/exchange_rate/Cargo.lock @@ -123,7 +123,7 @@ dependencies = [ "anyhow", "binread", "byteorder", - "candid_derive", + "candid_derive 0.4.5", "codespan-reporting", "hex", "ic-types", @@ -141,6 +141,35 @@ dependencies = [ "thiserror", ] +[[package]] +name = "candid" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0571f3777880555f86d8aaa63080162560a8bf183d7853e0cc561d9a75458bbd" +dependencies = [ + "anyhow", + "binread", + "byteorder", + "candid_derive 0.5.0", + "codespan-reporting", + "crc32fast", + "data-encoding", + "hex", + "lalrpop", + "lalrpop-util", + "leb128", + "logos", + "num-bigint", + "num-traits", + "num_enum", + "paste", + "pretty", + "serde", + "serde_bytes", + "sha2", + "thiserror", +] + [[package]] name = "candid_derive" version = "0.4.5" @@ -153,6 +182,18 @@ dependencies = [ "syn", ] +[[package]] +name = "candid_derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f1f4db7c7d04b87b70b3a35c5dc5c2c9dd73cef8bdf6760e2f18a0d45350dd" +dependencies = [ + "lazy_static", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -265,10 +306,11 @@ dependencies = [ name = "exchange_rate" version = "0.1.0" dependencies = [ - "candid", - "ic-cdk", + "candid 0.8.3", + "ic-cdk 0.6.2", "ic-cdk-macros", "serde", + "serde_bytes", "serde_json", ] @@ -332,9 +374,20 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0554d77b453140eefcb8c8192a342927f8c48cfda911dfa3cd4561a919dbd32f" dependencies = [ - "candid", + "candid 0.7.16", + "cfg-if", + "serde", +] + +[[package]] +name = "ic-cdk" +version = "0.6.2" +dependencies = [ + "candid 0.8.3", "cfg-if", + "ic0", "serde", + "serde_bytes", ] [[package]] @@ -343,8 +396,8 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "954a421ace8b8c8e52d2847c4aa68c80101396134c800ecb12f63457937c4ab4" dependencies = [ - "candid", - "ic-cdk", + "candid 0.7.16", + "ic-cdk 0.5.7", "proc-macro2", "quote", "serde", @@ -367,6 +420,14 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ic0" +version = "0.18.4" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "indexmap" version = "1.9.1" diff --git a/rust/exchange_rate/Cargo.toml b/rust/exchange_rate/Cargo.toml index cc5cd6e70..1a8f55661 100644 --- a/rust/exchange_rate/Cargo.toml +++ b/rust/exchange_rate/Cargo.toml @@ -9,8 +9,10 @@ name = "exchange_rate" path = "src/main.rs" [dependencies] -ic-cdk = "0.5.7" +# ic-cdk = "0.5.7" +ic-cdk = { path = "../../../cdk-rs/src/ic-cdk" } ic-cdk-macros = "0.5.7" serde = "1.0.126" -candid = "0.7.14" +candid = "0.8.0" serde_json = "1.0.81" +serde_bytes = "0.11.7" diff --git a/rust/exchange_rate/README.md b/rust/exchange_rate/README.md index 8bddc0366..3bf805f62 100644 --- a/rust/exchange_rate/README.md +++ b/rust/exchange_rate/README.md @@ -60,10 +60,10 @@ On top of that, we cache data that's already fetched, to save from future user r triggering remote HTTP calls again. ## Dependencies -- [ic-cdk v0.5.7](https://crates.io/crates/ic-cdk/0.5.7) or above -- [dfx v0.12.0-beta.3](https://github.com/dfinity/sdk/releases/tag/0.12.0-beta.3) or above. +- [ic-cdk v0.6.5](https://crates.io/crates/ic-cdk/0.6.5) or above +- [dfx v0.12.0-beta.6](https://github.com/dfinity/sdk/releases/tag/0.12.0-beta.6) or above. Use below command to install: -```DFX_VERSION=0.12.0-beta.3 sh -ci "$(curl -fsSL https://internetcomputer.org/install.sh)"``` +```DFX_VERSION=0.12.0-beta.6 sh -ci "$(curl -fsSL https://internetcomputer.org/install.sh)"``` ## Building the canister into wasm `cd rust/exchange_rate` diff --git a/rust/exchange_rate/deploy.sh b/rust/exchange_rate/deploy.sh index dc75a273f..0f222dfe5 100755 --- a/rust/exchange_rate/deploy.sh +++ b/rust/exchange_rate/deploy.sh @@ -20,7 +20,7 @@ if [[ $ENV == "local" ]]; then # Check DFX version version=$(dfx -V | sed 's/dfx\ //g' | sed 's/-.*$//g') if [[ "$version" < "0.12.0" ]]; then - echo "dfx 0.12.0 or above required. Please do: dfx upgrade" + echo "dfx 0.12.0-beta.6 or above required. Please do: DFX_VERSION=0.12.0-beta.6 sh -ci \"$(curl -fsSL https://internetcomputer.org/install.sh)\"" exit 1 fi diff --git a/rust/exchange_rate/src/lib.rs b/rust/exchange_rate/src/lib.rs index b6c5e8ad9..beb44b34c 100644 --- a/rust/exchange_rate/src/lib.rs +++ b/rust/exchange_rate/src/lib.rs @@ -11,7 +11,7 @@ pub struct TimeRange { pub end: Timestamp, } -#[derive(Clone, Debug, PartialEq, CandidType, Serialize, Deserialize)] +#[derive(CandidType, Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct RatesWithInterval { pub interval: usize, pub rates: HashMap, diff --git a/rust/exchange_rate/src/main.rs b/rust/exchange_rate/src/main.rs index df42dea59..a6cbe27b3 100644 --- a/rust/exchange_rate/src/main.rs +++ b/rust/exchange_rate/src/main.rs @@ -1,7 +1,7 @@ -use candid::Principal; use exchange_rate::{Rate, RatesWithInterval, TimeRange, Timestamp}; use ic_cdk::api::management_canister::http_request::{ - CanisterHttpRequestArgument, HttpHeader, HttpMethod, HttpResponse, TransformFunc, TransformType, + http_request, CanisterHttpRequestArgument, HttpHeader, HttpMethod, HttpResponse, TransformArgs, + TransformContext, }; use ic_cdk::storage; use ic_cdk_macros::{self, heartbeat, post_upgrade, pre_upgrade, query, update}; @@ -205,37 +205,21 @@ async fn get_rate(job: Timestamp) { let url = format!("https://{host}/products/ICP-USD/candles?granularity={REMOTE_FETCH_GRANULARITY}&start={start_timestamp}&end={end_timestamp}"); ic_cdk::api::print(url.clone()); + ic_cdk::api::print(format!("Making IC http_request call {} now.", job)); let request = CanisterHttpRequestArgument { url: url, method: HttpMethod::GET, body: None, max_response_bytes: Some(MAX_RESPONSE_BYTES), - transform: Some(TransformType::Function(TransformFunc(candid::Func { - principal: ic_cdk::api::id(), - method: "transform".to_string(), - }))), + transform: Some(TransformContext::new(transform, vec![])), headers: request_headers, }; - - let body = candid::utils::encode_one(&request).unwrap(); - ic_cdk::api::print(format!("Making IC http_request call {} now.", job)); - - match ic_cdk::api::call::call_raw( - Principal::management_canister(), - "http_request", - &body[..], - 2_000_000_000, - ) - .await - { - Ok(result) => { - // decode the result - let decoded_result: HttpResponse = - candid::utils::decode_one(&result).expect("IC http_request failed!"); + match http_request(request).await { + Ok((response,)) => { // put the result to hashmap FETCHED.with(|fetched| { let mut fetched = fetched.borrow_mut(); - let decoded_body = String::from_utf8(decoded_result.body) + let decoded_body = String::from_utf8(response.body) .expect("Remote service response is not UTF-8 encoded."); decode_body_to_rates(&decoded_body, &mut fetched); }); @@ -262,8 +246,8 @@ fn decode_body_to_rates(body: &str, fetched: &mut RefMut>) { } #[query] -async fn transform(raw: HttpResponse) -> HttpResponse { - let mut sanitized = raw.clone(); +fn transform(raw: TransformArgs) -> HttpResponse { + let mut sanitized = raw.response.clone(); sanitized.headers = vec![ HttpHeader { name: "Content-Security-Policy".to_string(),