diff --git a/core/api/Cargo.toml b/core/api/Cargo.toml index f294455c3..751d64dca 100644 --- a/core/api/Cargo.toml +++ b/core/api/Cargo.toml @@ -13,8 +13,8 @@ common-crypto = { path = "../../common/crypto"} http-service = "0.4" http = "0.2" -tide = "0.5" -juniper = "0.14" +tide = "0.6" +juniper = { git = "https://github.com/graphql-rust/juniper", rev = "eff086a", features = ["async"] } juniper_codegen = "0.14" async-trait = "0.1" hex = "0.4" diff --git a/core/api/src/lib.rs b/core/api/src/lib.rs index c4be28b5c..e4a3c44da 100644 --- a/core/api/src/lib.rs +++ b/core/api/src/lib.rs @@ -1,6 +1,3 @@ -#[macro_use] -extern crate juniper_codegen; - pub mod adapter; pub mod config; mod schema; @@ -10,7 +7,7 @@ use std::sync::Arc; use futures::executor::block_on; use http::status::StatusCode; -use juniper::{FieldError, FieldResult}; +use juniper::FieldResult; use tide::{Request, Response, ResultExt, Server}; use common_crypto::{ @@ -38,31 +35,32 @@ struct State { // context. struct Query; // Switch to async/await fn https://github.com/graphql-rust/juniper/issues/2 -#[juniper::object(Context = State)] +#[juniper::graphql_object(Context = State)] impl Query { #[graphql(name = "getBlock", description = "Get the block")] - fn get_latest_block(state_ctx: &State, height: Option) -> FieldResult { + async fn get_latest_block(state_ctx: &State, height: Option) -> FieldResult { let height = match height { Some(id) => Some(id.try_into_u64()?), None => None, }; - let block = block_on( - state_ctx - .adapter - .get_block_by_height(Context::new(), height), - )?; + let block = state_ctx + .adapter + .get_block_by_height(Context::new(), height) + .await?; + Ok(Block::from(block)) } #[graphql(name = "getTransaction", description = "Get the transaction by hash")] - fn get_transaction(state_ctx: &State, tx_hash: Hash) -> FieldResult { + async fn get_transaction(state_ctx: &State, tx_hash: Hash) -> FieldResult { let hash = protocol::types::Hash::from_hex(&tx_hash.as_hex())?; - let stx = block_on( - state_ctx - .adapter - .get_transaction_by_hash(Context::new(), hash), - )?; + + let stx = state_ctx + .adapter + .get_transaction_by_hash(Context::new(), hash) + .await?; + Ok(SignedTransaction::from(stx)) } @@ -70,19 +68,19 @@ impl Query { name = "getReceipt", description = "Get the receipt by transaction hash" )] - fn get_receipt(state_ctx: &State, tx_hash: Hash) -> FieldResult { + async fn get_receipt(state_ctx: &State, tx_hash: Hash) -> FieldResult { let hash = protocol::types::Hash::from_hex(&tx_hash.as_hex())?; - let receipt = block_on( - state_ctx - .adapter - .get_receipt_by_tx_hash(Context::new(), hash), - )?; + + let receipt = state_ctx + .adapter + .get_receipt_by_tx_hash(Context::new(), hash) + .await?; Ok(Receipt::from(receipt)) } #[graphql(name = "queryService", description = "query service")] - fn query_service( + async fn query_service( state_ctx: &State, height: Option, cycles_limit: Option, @@ -112,26 +110,29 @@ impl Query { let address = protocol::types::Address::from_hex(&caller.as_hex())?; - let exec_resp = block_on(state_ctx.adapter.query_service( - Context::new(), - height, - cycles_limit, - cycles_price, - address, - service_name, - method, - payload, - ))?; + let exec_resp = state_ctx + .adapter + .query_service( + Context::new(), + height, + cycles_limit, + cycles_price, + address, + service_name, + method, + payload, + ) + .await?; Ok(ExecResp::from(exec_resp)) } } struct Mutation; // Switch to async/await fn https://github.com/graphql-rust/juniper/issues/2 -#[juniper::object(Context = State)] +#[juniper::graphql_object(Context = State)] impl Mutation { #[graphql(name = "sendTransaction", description = "send transaction")] - fn send_transaction( + async fn send_transaction( state_ctx: &State, input_raw: InputRawTransaction, input_encryption: InputTransactionEncryption, @@ -139,8 +140,10 @@ impl Mutation { let stx = to_signed_transaction(input_raw, input_encryption)?; let tx_hash = stx.tx_hash.clone(); - block_on(state_ctx.adapter.insert_signed_txs(Context::new(), stx)) - .map_err(FieldError::from)?; + state_ctx + .adapter + .insert_signed_txs(Context::new(), stx) + .await?; Ok(Hash::from(tx_hash)) } @@ -149,7 +152,7 @@ impl Mutation { name = "unsafeSendTransaction", deprecated = "DON'T use it in production! This is just for development." )] - fn unsafe_send_transaction( + async fn unsafe_send_transaction( state_ctx: &State, input_raw: InputRawTransaction, input_privkey: Bytes, @@ -168,8 +171,10 @@ impl Mutation { signature: signature.to_bytes(), pubkey: pubkey.to_bytes(), }; - block_on(state_ctx.adapter.insert_signed_txs(Context::new(), stx)) - .map_err(FieldError::from)?; + state_ctx + .adapter + .insert_signed_txs(Context::new(), stx) + .await?; Ok(Hash::from(tx_hash)) } @@ -191,7 +196,8 @@ async fn handle_graphql(mut req: Request) -> Response { }; let schema = Schema::new(Query, Mutation); - let response = query.execute(&schema, req.state()); + let state = &req.state().clone(); + let response = query.execute_async(&schema, state).await; let status = if response.is_ok() { StatusCode::OK } else { diff --git a/core/api/src/schema/block.rs b/core/api/src/schema/block.rs index a8e843614..76b348557 100644 --- a/core/api/src/schema/block.rs +++ b/core/api/src/schema/block.rs @@ -1,6 +1,6 @@ use crate::schema::{Address, Bytes, Hash, MerkleRoot, Uint64}; -#[derive(GraphQLObject, Clone)] +#[derive(juniper::GraphQLObject, Clone)] #[graphql( description = "Block is a single digital record created within a blockchain. \ Each block contains a record of the previous Block, \ @@ -14,7 +14,7 @@ pub struct Block { ordered_tx_hashes: Vec, } -#[derive(GraphQLObject, Clone)] +#[derive(juniper::GraphQLObject, Clone)] #[graphql(description = "A block header is like the metadata of a block.")] pub struct BlockHeader { #[graphql( @@ -47,7 +47,7 @@ pub struct BlockHeader { pub validators: Vec, } -#[derive(GraphQLObject, Clone)] +#[derive(juniper::GraphQLObject, Clone)] #[graphql(description = "The verifier of the block header proved")] pub struct Proof { pub height: Uint64, @@ -57,7 +57,7 @@ pub struct Proof { pub bitmap: Bytes, } -#[derive(GraphQLObject, Clone)] +#[derive(juniper::GraphQLObject, Clone)] #[graphql(description = "Validator address set")] pub struct Validator { pub address: Address, diff --git a/core/api/src/schema/mod.rs b/core/api/src/schema/mod.rs index 7b7e296e6..2e7382b4c 100644 --- a/core/api/src/schema/mod.rs +++ b/core/api/src/schema/mod.rs @@ -16,7 +16,7 @@ pub use transaction::{ SignedTransaction, }; -#[derive(GraphQLObject, Clone)] +#[derive(juniper::GraphQLObject, Clone)] pub struct ExecResp { ret: String, is_error: bool, @@ -31,20 +31,20 @@ impl From for ExecResp { } } -#[derive(GraphQLScalarValue, Clone)] +#[derive(juniper::GraphQLScalarValue, Clone)] #[graphql(description = "The output digest of Keccak hash function")] pub struct Hash(String); pub type MerkleRoot = Hash; -#[derive(GraphQLScalarValue, Clone)] +#[derive(juniper::GraphQLScalarValue, Clone)] #[graphql(description = "20 bytes of account address")] pub struct Address(String); -#[derive(GraphQLScalarValue, Clone)] +#[derive(juniper::GraphQLScalarValue, Clone)] #[graphql(description = "Uint64")] pub struct Uint64(String); -#[derive(GraphQLScalarValue, Clone)] +#[derive(juniper::GraphQLScalarValue, Clone)] #[graphql(description = "Bytes corresponding hex string.")] pub struct Bytes(String); diff --git a/core/api/src/schema/receipt.rs b/core/api/src/schema/receipt.rs index b7ede9d4a..8418d7854 100644 --- a/core/api/src/schema/receipt.rs +++ b/core/api/src/schema/receipt.rs @@ -1,6 +1,6 @@ use crate::schema::{Hash, MerkleRoot, Uint64}; -#[derive(GraphQLObject, Clone)] +#[derive(juniper::GraphQLObject, Clone)] pub struct Receipt { pub state_root: MerkleRoot, pub height: Uint64, @@ -10,13 +10,13 @@ pub struct Receipt { pub response: ReceiptResponse, } -#[derive(GraphQLObject, Clone)] +#[derive(juniper::GraphQLObject, Clone)] pub struct Event { pub service: String, pub data: String, } -#[derive(GraphQLObject, Clone)] +#[derive(juniper::GraphQLObject, Clone)] pub struct ReceiptResponse { pub service_name: String, pub method: String, diff --git a/core/api/src/schema/transaction.rs b/core/api/src/schema/transaction.rs index 3f7c988ea..b7c56dfa5 100644 --- a/core/api/src/schema/transaction.rs +++ b/core/api/src/schema/transaction.rs @@ -2,7 +2,7 @@ use protocol::ProtocolResult; use crate::schema::{Bytes, Hash, SchemaError, Uint64}; -#[derive(GraphQLObject, Clone)] +#[derive(juniper::GraphQLObject, Clone)] pub struct SignedTransaction { pub chain_id: Hash, pub cycles_limit: Uint64, @@ -39,7 +39,7 @@ impl From for SignedTransaction { // GraphQLInputObject // ##################### -#[derive(GraphQLInputObject, Clone)] +#[derive(juniper::GraphQLInputObject, Clone)] #[graphql(description = "There was many types of transaction in Muta, \ A transaction often require computing resources or write data to chain,\ these resources are valuable so we need to pay some token for them.\ @@ -68,7 +68,7 @@ pub struct InputRawTransaction { pub payload: String, } -#[derive(GraphQLInputObject, Clone)] +#[derive(juniper::GraphQLInputObject, Clone)] #[graphql(description = "Signature of the transaction")] pub struct InputTransactionEncryption { #[graphql(description = "The digest of the transaction")]