diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e74992b0079cb02be4629dc6f565159e8cc0c794..5177bc91c4aac2ff10bed8d8975da55ea61f4889 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -100,7 +100,8 @@ tests:linux64:stable:
   script: 
     - cd bin/dunitrust-server
     - RUSTFLAGS="-D warnings" cargo build --features=ssl
-    - cargo test --all
+    - cargo test --all --exclude durs-gva
+    - cargo test --package durs-gva -- --test-threads=1
     - cargo test --all -- --ignored
 
 tests:arm-v7-:stable:
@@ -114,7 +115,6 @@ tests:arm-v7-:stable:
   script: 
     - cd bin/dunitrust-server
     - RUSTFLAGS="-D warnings" cargo build --target=armv7-unknown-linux-gnueabihf --features=ssl
-    - cargo test --all --target=armv7-unknown-linux-gnueabihf
 
 tests:arm-v7:stable:
   extends: .rust_stable_armv7
@@ -124,7 +124,6 @@ tests:arm-v7:stable:
   script: 
     - cd bin/dunitrust-server
     - RUSTFLAGS="-D warnings" cargo build --target=armv7-unknown-linux-gnueabihf --features=ssl
-    - cargo test --all --target=armv7-unknown-linux-gnueabihf
 
 tests:win64:stable:
   extends: .rust_stable_win64
@@ -143,6 +142,7 @@ tests:win64:stable:
     - cargo test --package durs-blockchain --target=x86_64-pc-windows-gnu
     - cargo test --package durs-dbs-tools --target=x86_64-pc-windows-gnu
     #- cargo test --package durs-skeleton-module --target=x86_64-pc-windows-gnu
+    - cargo test --package durs-gva --target=x86_64-pc-windows-gnu -- --test-threads=1
     - cargo test --package durs-ws2p-v1-legacy --target=x86_64-pc-windows-gnu
     - cargo test --package durs-ws2p --target=x86_64-pc-windows-gnu
     - cargo test --package durs-ws2p-messages --target=x86_64-pc-windows-gnu
diff --git a/lib/modules-lib/bc-db-reader/src/lib.rs b/lib/modules-lib/bc-db-reader/src/lib.rs
index 00297e27d45be54b9298d1a7aa0c787039caec7d..cd9a1ebb865bac6452ed4fddf0e1fe4389535cae 100644
--- a/lib/modules-lib/bc-db-reader/src/lib.rs
+++ b/lib/modules-lib/bc-db-reader/src/lib.rs
@@ -36,8 +36,8 @@ pub mod paging;
 pub mod tools;
 
 pub use durs_dbs_tools::kv_db::{
-    KvFileDbRead as DbReadable, KvFileDbRoHandler as BcDbRo, KvFileDbSchema, KvFileDbStoreType,
-    KvFileDbValue as DbValue, Readable as DbReader,
+    KvFileDbRead as DbReadable, KvFileDbReader as Reader, KvFileDbRoHandler as BcDbRo,
+    KvFileDbSchema, KvFileDbStoreType, KvFileDbValue as DbValue, Readable as DbReader,
 };
 pub use durs_dbs_tools::DbError;
 
diff --git a/lib/modules/gva/Cargo.toml b/lib/modules/gva/Cargo.toml
index 894509e341cdc6f2b1ba8add668ade7a05bed4d6..32945b0cfd9597fc6bc7df66acd789153a0f6695 100644
--- a/lib/modules/gva/Cargo.toml
+++ b/lib/modules/gva/Cargo.toml
@@ -12,6 +12,7 @@ path = "src/lib.rs"
 [dependencies]
 actix-web = "1.0.8"
 dubp-block-doc = { path = "../../dubp/block-doc"} #, version = "0.1.0" }
+dup-crypto = { path = "../../crypto" }
 durs-bc-db-reader = { path = "../../modules-lib/bc-db-reader" }
 durs-conf = { path = "../../core/conf" }
 durs-message =  { path = "../../core/message" }
@@ -21,6 +22,7 @@ durs-network-documents = { path = "../../dunp/network-documents" }
 dubp-common-doc = { path = "../../dubp/common-doc"} #, version = "0.1.0" }
 durs-common-tools = { path = "../../tools/common-tools" }
 dubp-currency-params = { path = "../../dubp/currency-params" }
+cfg-if = "0.1.10"
 chrono = "0.4.9"
 failure = "0.1.5"
 futures = "0.1"
@@ -34,4 +36,10 @@ serde_derive = "1.0.102"
 serde_json = "1.0.41"
 structopt= "0.3.4"
 
+[dev-dependencies]
+dubp-blocks-tests-tools = { path = "../../tests-tools/blocks-tests-tools" }
+dup-crypto-tests-tools = { path = "../../tests-tools/crypto-tests-tools" }
+mockall = "0.5.2"
+pretty_assertions = "0.5.1"
+
 [features]
diff --git a/lib/modules/gva/src/context.rs b/lib/modules/gva/src/context.rs
index 6e27d67882f1f89ff433faf364038eac69aa633b..4604812af79eafd6220341ae6b517a322cc4cb14 100644
--- a/lib/modules/gva/src/context.rs
+++ b/lib/modules/gva/src/context.rs
@@ -13,15 +13,23 @@
 // You should have received a copy of the GNU Affero General Public License
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
+#[cfg(not(test))]
 use durs_bc_db_reader::BcDbRo;
 use durs_common_tools::fatal_error;
 
+#[cfg(test)]
+use crate::db::MockBcDbTrait;
+
 /// GVA context (access to database)
 static mut CONTEXT: Option<Context> = None;
 
-#[derive(Debug)]
+#[cfg(not(test))]
+pub type DB = BcDbRo;
+#[cfg(test)]
+pub(crate) type DB = MockBcDbTrait;
+
 pub struct Context {
-    db: BcDbRo,
+    db: DB,
     software_name: &'static str,
     software_version: &'static str,
 }
@@ -29,7 +37,7 @@ pub struct Context {
 impl juniper::Context for Context {}
 
 impl Context {
-    pub fn new(db: BcDbRo, software_name: &'static str, software_version: &'static str) -> Self {
+    pub(crate) fn new(db: DB, software_name: &'static str, software_version: &'static str) -> Self {
         Context {
             db,
             software_name,
@@ -37,7 +45,7 @@ impl Context {
         }
     }
 
-    pub fn get_db(&self) -> &BcDbRo {
+    pub(crate) fn get_db(&self) -> &DB {
         &self.db
     }
 
@@ -50,7 +58,7 @@ impl Context {
     }
 }
 
-pub fn init(db: BcDbRo, soft_name: &'static str, soft_version: &'static str) {
+pub(crate) fn init(db: DB, soft_name: &'static str, soft_version: &'static str) {
     unsafe {
         CONTEXT.replace(Context::new(db, soft_name, soft_version));
     }
diff --git a/lib/modules/gva/src/db.rs b/lib/modules/gva/src/db.rs
new file mode 100644
index 0000000000000000000000000000000000000000..9fcfac6484b5082fd2bed40ad9a1486ca1274fc9
--- /dev/null
+++ b/lib/modules/gva/src/db.rs
@@ -0,0 +1,91 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+//! Gva Module: database requests
+
+pub use durs_bc_db_reader::DbError;
+
+use dubp_common_doc::{BlockNumber, Blockstamp};
+use durs_bc_db_reader::blocks::DbBlock;
+use durs_bc_db_reader::{BcDbRo, DbReadable};
+use std::ops::Range;
+
+#[cfg(test)]
+use mockall::predicate::*;
+#[cfg(test)]
+use mockall::*;
+
+#[cfg_attr(test, automock)]
+pub(crate) trait BcDbTrait {
+    fn get_current_blockstamp(&self) -> Result<Option<Blockstamp>, DbError>;
+    fn get_current_block(&self) -> Result<Option<DbBlock>, DbError>;
+    fn get_db_block_in_local_blockchain(
+        &self,
+        block_number: BlockNumber,
+    ) -> Result<Option<DbBlock>, DbError>;
+    fn get_db_blocks_in_local_blockchain(&self, range: Range<u32>)
+        -> Result<Vec<DbBlock>, DbError>;
+}
+
+impl<'a> BcDbTrait for BcDbRo {
+    #[inline]
+    fn get_current_blockstamp(&self) -> Result<Option<Blockstamp>, DbError> {
+        self.read(|r| durs_bc_db_reader::current_meta_datas::get_current_blockstamp_(self, r))
+    }
+    fn get_current_block(&self) -> Result<Option<DbBlock>, DbError> {
+        self.read(|r| {
+            if let Some(current_blockstamp) =
+                durs_bc_db_reader::current_meta_datas::get_current_blockstamp_(self, r)?
+            {
+                durs_bc_db_reader::blocks::get_db_block_in_local_blockchain(
+                    self,
+                    r,
+                    current_blockstamp.id,
+                )
+            } else {
+                Ok(None)
+            }
+        })
+    }
+    #[inline]
+    fn get_db_block_in_local_blockchain(
+        &self,
+        block_number: BlockNumber,
+    ) -> Result<Option<DbBlock>, DbError> {
+        self.read(|r| {
+            durs_bc_db_reader::blocks::get_db_block_in_local_blockchain(self, r, block_number)
+        })
+    }
+    fn get_db_blocks_in_local_blockchain(
+        &self,
+        range: Range<u32>,
+    ) -> Result<Vec<DbBlock>, DbError> {
+        self.read(|r| {
+            range
+                .filter_map(|n| {
+                    match durs_bc_db_reader::blocks::get_db_block_in_local_blockchain(
+                        self,
+                        r,
+                        BlockNumber(n),
+                    ) {
+                        Ok(Some(db_block)) => Some(Ok(db_block)),
+                        Ok(None) => None,
+                        Err(e) => Some(Err(e)),
+                    }
+                })
+                .collect::<Result<Vec<DbBlock>, DbError>>()
+        })
+    }
+}
diff --git a/lib/modules/gva/src/graphql.rs b/lib/modules/gva/src/graphql.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b2fa335a752a6746e1948b7dc78431a8aa223067
--- /dev/null
+++ b/lib/modules/gva/src/graphql.rs
@@ -0,0 +1,40 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+// web server implementaion based on actix-web
+
+//! Module that execute graphql queries
+
+use crate::schema::Schema;
+use actix_web::{web, Error, HttpResponse};
+use futures::future::Future;
+use juniper::http::GraphQLRequest;
+use std::sync::Arc;
+
+pub(crate) fn graphql(
+    schema: web::Data<Arc<Schema>>,
+    data: web::Json<GraphQLRequest>,
+) -> impl Future<Item = HttpResponse, Error = Error> {
+    let context = crate::context::get_context();
+    web::block(move || {
+        let result = data.execute(&schema, context);
+        serde_json::to_string(&result)
+    })
+    .map_err(Error::from)
+    .and_then(|user| {
+        Ok(HttpResponse::Ok()
+            .content_type("application/json")
+            .body(user))
+    })
+}
diff --git a/lib/modules/gva/src/lib.rs b/lib/modules/gva/src/lib.rs
index 1e71e6f6f0d39d9df2405db791c342ebc7453bb2..00826f15d19c69c33fb864dcdd1de9fe8595c9d9 100644
--- a/lib/modules/gva/src/lib.rs
+++ b/lib/modules/gva/src/lib.rs
@@ -14,14 +14,14 @@
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 //! Gva Module
-// This module provides a graphql API implementation of the 0003 RFC
-//
-// /src/schema.gql contains schema description
-// /src/schema.rs contains model and resolvers implementation
-// /src/webserver.rs contains web server implementaion based on actix-web
-//
-// Graphiql web client is accessible at
-// http://127.0.0.1:3000/graphiql
+//! This module provides a graphql API implementation of the 0003 RFC
+//!
+//! /src/schema.gql contains schema description
+//! /src/schema.rs contains model and resolvers implementation
+//! /src/webserver.rs contains web server implementaion based on actix-web
+//!
+//! Graphiql web client is accessible at
+//! http://127.0.0.1:10901/graphiql
 
 #![deny(
     missing_docs,
@@ -44,7 +44,9 @@ extern crate structopt;
 extern crate juniper;
 
 mod context;
+mod db;
 mod errors;
+mod graphql;
 mod schema;
 mod webserver;
 
diff --git a/lib/modules/gva/src/schema.rs b/lib/modules/gva/src/schema.rs
index b41ccf9eaa6cdc61e777523cfdcdcaac4dc4a991..18bc55508a87bfa0f9325466e7c007e0e4e5d851 100644
--- a/lib/modules/gva/src/schema.rs
+++ b/lib/modules/gva/src/schema.rs
@@ -13,15 +13,15 @@
 // You should have received a copy of the GNU Affero General Public License
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-// ! model and resolvers implementation
+// ! Module define GraphQl schema
 
-mod block;
+mod entities;
 mod paging;
+mod queries;
 
-use self::block::Block;
+use self::entities::block::Block;
+use self::entities::node::{Node, Summary};
 use crate::context::Context;
-use dubp_common_doc::BlockNumber;
-use durs_bc_db_reader::{BcDbRo, DbError, DbReadable};
 use juniper::Executor;
 use juniper::FieldResult;
 use juniper_from_schema::graphql_schema_from_file;
@@ -31,104 +31,40 @@ graphql_schema_from_file!("resources/schema.gql");
 
 pub struct Query;
 
-pub struct Summary {
-    software: &'static str,
-    version: &'static str,
-}
-
-pub struct Node {
-    summary: Summary,
-}
-
-fn db_err_to_juniper_err(e: DbError) -> juniper::FieldError {
-    juniper::FieldError::from(format!("Db error: {:?}", e))
-}
-
 impl QueryFields for Query {
+    #[inline]
     fn field_node(
         &self,
         executor: &Executor<'_, Context>,
-        _trail: &QueryTrail<'_, Node, Walked>,
+        trail: &QueryTrail<'_, Node, Walked>,
     ) -> FieldResult<Node> {
-        Ok(Node {
-            summary: Summary {
-                software: executor.context().get_software_name(),
-                version: executor.context().get_software_version(),
-            },
-        })
+        queries::node::execute(executor, trail)
     }
+    #[inline]
     fn field_current(
         &self,
         executor: &Executor<'_, Context>,
-        _trail: &QueryTrail<'_, Block, Walked>,
+        trail: &QueryTrail<'_, Block, Walked>,
     ) -> FieldResult<Option<Block>> {
-        let db: &BcDbRo = &executor.context().get_db();
-
-        db.read(|r| {
-            if let Some(current_blockstamp) =
-                durs_bc_db_reader::current_meta_datas::get_current_blockstamp_(db, r)?
-            {
-                block::get_block(db, r, current_blockstamp.id)
-            } else {
-                Ok(None)
-            }
-        })
-        .map_err(db_err_to_juniper_err)
+        queries::current::execute(executor, trail)
     }
+    #[inline]
     fn field_block(
         &self,
         executor: &Executor<'_, Context>,
-        _trail: &QueryTrail<'_, Block, Walked>,
+        trail: &QueryTrail<'_, Block, Walked>,
         number: i32,
     ) -> FieldResult<Option<Block>> {
-        let db: &BcDbRo = &executor.context().get_db();
-
-        let block_number = if number >= 0 {
-            BlockNumber(number as u32)
-        } else {
-            return Err(juniper::FieldError::from("Block number must be positive."));
-        };
-
-        db.read(|r| block::get_block(db, r, block_number))
-            .map_err(db_err_to_juniper_err)
+        queries::block::execute(executor, trail, number)
     }
+    #[inline]
     fn field_blocks(
         &self,
         executor: &Executor<'_, Context>,
-        _trail: &QueryTrail<'_, Block, Walked>,
+        trail: &QueryTrail<'_, Block, Walked>,
         paging_opt: Option<Paging>,
     ) -> FieldResult<Vec<Block>> {
-        let db: &BcDbRo = &executor.context().get_db();
-        db.read(|r| {
-            paging::FilledPaging::new(db, r, paging_opt)?
-                .get_range()
-                .filter_map(|n| match block::get_block(db, r, BlockNumber(n)) {
-                    Ok(Some(db_block)) => Some(Ok(db_block)),
-                    Ok(None) => None,
-                    Err(e) => Some(Err(e)),
-                })
-                .collect::<Result<Vec<Block>, DbError>>()
-        })
-        .map_err(db_err_to_juniper_err)
-    }
-}
-
-impl NodeFields for Node {
-    fn field_summary(
-        &self,
-        _executor: &Executor<'_, Context>,
-        _trail: &QueryTrail<'_, Summary, Walked>,
-    ) -> &Summary {
-        &self.summary
-    }
-}
-
-impl SummaryFields for Summary {
-    fn field_software(&self, _executor: &Executor<'_, Context>) -> String {
-        self.software.to_owned()
-    }
-    fn field_version(&self, _executor: &Executor<'_, Context>) -> String {
-        self.version.to_owned()
+        queries::blocks::execute(executor, trail, paging_opt)
     }
 }
 
diff --git a/lib/modules/gva/src/schema/entities.rs b/lib/modules/gva/src/schema/entities.rs
new file mode 100644
index 0000000000000000000000000000000000000000..a6ec3bb52a566a59449d367e9c2cb8fbb1a3a835
--- /dev/null
+++ b/lib/modules/gva/src/schema/entities.rs
@@ -0,0 +1,19 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+// ! Module define GraphQl schema entities
+
+pub mod block;
+pub mod node;
diff --git a/lib/modules/gva/src/schema/block.rs b/lib/modules/gva/src/schema/entities/block.rs
similarity index 64%
rename from lib/modules/gva/src/schema/block.rs
rename to lib/modules/gva/src/schema/entities/block.rs
index b155e8d5453a2b0eb9906417a92757c0ef2f709c..3a2900a3b542538ff5bd724b75d52dae5549fecf 100644
--- a/lib/modules/gva/src/schema/block.rs
+++ b/lib/modules/gva/src/schema/entities/block.rs
@@ -13,14 +13,13 @@
 // You should have received a copy of the GNU Affero General Public License
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-// ! Block model and resolvers
+// ! Module define graphql Block type
 
 use crate::context::Context;
 use chrono::NaiveDateTime;
 use dubp_block_doc::block::BlockDocumentTrait;
 use dubp_common_doc::traits::Document;
-use dubp_common_doc::BlockNumber;
-use durs_bc_db_reader::{BcDbRo, DbError, DbReader};
+use durs_bc_db_reader::blocks::DbBlock;
 use durs_common_tools::fatal_error;
 use juniper::{Executor, FieldResult};
 
@@ -33,7 +32,7 @@ pub struct Block {
     common_time: NaiveDateTime,
 }
 
-impl super::BlockFields for Block {
+impl super::super::BlockFields for Block {
     fn field_version(&self, _executor: &Executor<'_, Context>) -> FieldResult<&i32> {
         Ok(&self.version)
     }
@@ -59,25 +58,19 @@ impl super::BlockFields for Block {
     }
 }
 
-pub fn get_block<R: DbReader>(
-    db: &BcDbRo,
-    r: &R,
-    block_number: BlockNumber,
-) -> Result<Option<Block>, DbError> {
-    durs_bc_db_reader::blocks::get_db_block_in_local_blockchain(db, r, block_number).map(
-        |block_opt| {
-            block_opt.map(|db_block| Block {
-                version: db_block.block.version() as i32,
-                currency: db_block.block.currency().to_string(),
-                issuer: db_block.block.issuers()[0].to_string(),
-                number: db_block.block.number().0 as i32,
-                hash: db_block
-                    .block
-                    .hash()
-                    .unwrap_or_else(|| fatal_error!("DbBlock without hash."))
-                    .to_string(),
-                common_time: NaiveDateTime::from_timestamp(db_block.block.common_time() as i64, 0),
-            })
-        },
-    )
+impl Block {
+    pub fn from_db_block(db_block: DbBlock) -> Block {
+        Block {
+            version: db_block.block.version() as i32,
+            currency: db_block.block.currency().to_string(),
+            issuer: db_block.block.issuers()[0].to_string(),
+            number: db_block.block.number().0 as i32,
+            hash: db_block
+                .block
+                .hash()
+                .unwrap_or_else(|| fatal_error!("DbBlock without hash."))
+                .to_string(),
+            common_time: NaiveDateTime::from_timestamp(db_block.block.common_time() as i64, 0),
+        }
+    }
 }
diff --git a/lib/modules/gva/src/schema/entities/node.rs b/lib/modules/gva/src/schema/entities/node.rs
new file mode 100644
index 0000000000000000000000000000000000000000..be7668bc595c7ce74ced7ac8e6b683ea6fb27a8f
--- /dev/null
+++ b/lib/modules/gva/src/schema/entities/node.rs
@@ -0,0 +1,48 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+// ! Module define graphql Node type and subtypes
+
+use crate::context::Context;
+use juniper::Executor;
+use juniper_from_schema::{QueryTrail, Walked};
+
+pub struct Summary {
+    pub software: &'static str,
+    pub version: &'static str,
+}
+
+pub struct Node {
+    pub summary: Summary,
+}
+
+impl super::super::NodeFields for Node {
+    fn field_summary(
+        &self,
+        _executor: &Executor<'_, Context>,
+        _trail: &QueryTrail<'_, Summary, Walked>,
+    ) -> &Summary {
+        &self.summary
+    }
+}
+
+impl super::super::SummaryFields for Summary {
+    fn field_software(&self, _executor: &Executor<'_, Context>) -> String {
+        self.software.to_owned()
+    }
+    fn field_version(&self, _executor: &Executor<'_, Context>) -> String {
+        self.version.to_owned()
+    }
+}
diff --git a/lib/modules/gva/src/schema/paging.rs b/lib/modules/gva/src/schema/paging.rs
index af47c177c1a088d2cb129d24c9f63a6b625829ba..4b85efa8d6222c3914e373636c93aca8cad52d56 100644
--- a/lib/modules/gva/src/schema/paging.rs
+++ b/lib/modules/gva/src/schema/paging.rs
@@ -16,16 +16,15 @@
 // ! Schema paging input
 
 use super::Paging;
-use durs_bc_db_reader::{BcDbRo, DbError, DbReader};
+use crate::db::BcDbTrait;
+use durs_bc_db_reader::DbError;
 use std::ops::Range;
 
 const DEFAULT_PAGE_NUMBER: i32 = 0;
 const DEFAULT_PAGE_SIZE: i32 = 50;
 const DEFAULT_FROM_BLOCK: i32 = 0;
 
-const MAX_PAGE_NUMBER: i32 = std::i32::MAX;
 const MAX_PAGE_SIZE: i32 = 500;
-const MAX_FROM_BLOCK: i32 = std::i32::MAX;
 
 /// Paging with all values filled in
 pub struct FilledPaging {
@@ -49,25 +48,16 @@ fn i32_opt_to_positive_i32(int_opt: Option<i32>, default: i32) -> i32 {
 }
 
 impl FilledPaging {
-    pub fn new<R: DbReader>(
-        db: &BcDbRo,
-        r: &R,
-        paging_opt: Option<Paging>,
-    ) -> Result<Self, DbError> {
+    pub(crate) fn new<DB: BcDbTrait>(db: &DB, paging_opt: Option<Paging>) -> Result<Self, DbError> {
         if let Some(paging) = paging_opt {
             Ok(FilledPaging {
-                page_number: std::cmp::min(
-                    MAX_PAGE_NUMBER,
-                    i32_opt_to_positive_i32(paging.page_number, DEFAULT_PAGE_NUMBER),
-                ) as usize,
+                page_number: i32_opt_to_positive_i32(paging.page_number, DEFAULT_PAGE_NUMBER)
+                    as usize,
                 page_size: std::cmp::min(
                     MAX_PAGE_SIZE,
                     i32_opt_to_positive_i32(paging.page_size, DEFAULT_PAGE_SIZE),
                 ) as usize,
-                from_block: std::cmp::min(
-                    MAX_FROM_BLOCK,
-                    i32_opt_to_positive_i32(paging.from_block, DEFAULT_FROM_BLOCK),
-                ) as u32,
+                from_block: i32_opt_to_positive_i32(paging.from_block, DEFAULT_FROM_BLOCK) as u32,
                 to_block: if let Some(to_block) = paging.to_block {
                     if to_block < 0 {
                         0
@@ -75,7 +65,7 @@ impl FilledPaging {
                         to_block as u32
                     }
                 } else {
-                    Self::get_default_to_block(db, r)?
+                    Self::get_default_to_block(db)?
                 },
             })
         } else {
@@ -83,14 +73,12 @@ impl FilledPaging {
                 page_number: DEFAULT_PAGE_NUMBER as usize,
                 page_size: DEFAULT_PAGE_SIZE as usize,
                 from_block: DEFAULT_FROM_BLOCK as u32,
-                to_block: Self::get_default_to_block(db, r)?,
+                to_block: Self::get_default_to_block(db)?,
             })
         }
     }
-    fn get_default_to_block<R: DbReader>(db: &BcDbRo, r: &R) -> Result<u32, DbError> {
-        if let Some(current_blockstamp) =
-            durs_bc_db_reader::current_meta_datas::get_current_blockstamp_(db, r)?
-        {
+    fn get_default_to_block<DB: BcDbTrait>(db: &DB) -> Result<u32, DbError> {
+        if let Some(current_blockstamp) = db.get_current_blockstamp()? {
             Ok(current_blockstamp.id.0)
         } else {
             Ok(0)
@@ -106,3 +94,102 @@ impl FilledPaging {
         }
     }
 }
+
+#[cfg(test)]
+mod tests {
+
+    use super::*;
+    use crate::db::MockBcDbTrait;
+    use dubp_common_doc::{BlockHash, BlockNumber, Blockstamp};
+
+    #[test]
+    fn test_i32_opt_to_positive_i32() {
+        assert_eq!(3, i32_opt_to_positive_i32(Some(3), 1));
+        assert_eq!(0, i32_opt_to_positive_i32(Some(-2), 1));
+        assert_eq!(50, i32_opt_to_positive_i32(None, 50));
+        assert_eq!(0, i32_opt_to_positive_i32(Some(0), 1));
+    }
+
+    #[test]
+    fn test_filled_paging_range_with_short_bc() -> Result<(), DbError> {
+        let mut mock_db = MockBcDbTrait::new();
+        mock_db
+            .expect_get_current_blockstamp()
+            .times(1)
+            .returning(|| {
+                Ok(Some(Blockstamp {
+                    id: BlockNumber(42),
+                    hash: BlockHash(dup_crypto::hashs::Hash::default()),
+                }))
+            });
+
+        let filled_paging = FilledPaging::new(&mock_db, None)?;
+        assert_eq! {
+            Range {
+                start: 0,
+                end: 43,
+            },
+            filled_paging.get_range()
+        }
+        Ok(())
+    }
+
+    #[test]
+    fn test_filled_paging_range() -> Result<(), DbError> {
+        let mut mock_db = MockBcDbTrait::new();
+        mock_db
+            .expect_get_current_blockstamp()
+            .times(3)
+            .returning(|| {
+                Ok(Some(Blockstamp {
+                    id: BlockNumber(750),
+                    hash: BlockHash(dup_crypto::hashs::Hash::default()),
+                }))
+            });
+
+        let filled_paging = FilledPaging::new(&mock_db, None)?;
+        assert_eq! {
+            Range {
+                start: 0,
+                end: 50,
+            },
+            filled_paging.get_range()
+        }
+
+        let filled_paging = FilledPaging::new(
+            &mock_db,
+            Some(Paging {
+                page_number: Some(1),
+                page_size: Some(100),
+                from_block: Some(500),
+                to_block: None,
+            }),
+        )?;
+        assert_eq! {
+            Range {
+                start: 600,
+                end: 700,
+            },
+            filled_paging.get_range()
+        }
+
+        let filled_paging = FilledPaging::new(
+            &mock_db,
+            Some(Paging {
+                page_number: Some(2),
+                page_size: Some(100),
+                from_block: Some(500),
+                to_block: None,
+            }),
+        )?;
+        assert_eq! {
+            Range {
+                start: 700,
+                end: 751,
+            },
+            filled_paging.get_range()
+        }
+
+        Ok(())
+    }
+}
diff --git a/lib/modules/gva/src/schema/queries.rs b/lib/modules/gva/src/schema/queries.rs
new file mode 100644
index 0000000000000000000000000000000000000000..6a30b6653ae34f7f1d4fd398d3410b0ee490d66f
--- /dev/null
+++ b/lib/modules/gva/src/schema/queries.rs
@@ -0,0 +1,75 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+// ! Module execute GraphQl schema queries
+
+pub mod block;
+pub mod blocks;
+pub mod current;
+pub mod node;
+
+use durs_bc_db_reader::DbError;
+
+pub(crate) fn db_err_to_juniper_err(e: DbError) -> juniper::FieldError {
+    juniper::FieldError::from(format!("Db error: {:?}", e))
+}
+
+#[cfg(test)]
+mod tests {
+
+    use crate::context;
+    use crate::db::MockBcDbTrait;
+    use crate::graphql::graphql;
+    use crate::schema::{create_schema, Schema};
+    use actix_web::dev::Body;
+    use actix_web::http;
+    use actix_web::test;
+    use actix_web::web;
+    use juniper::http::GraphQLRequest;
+    use pretty_assertions::assert_eq;
+    use std::str::FromStr;
+    use std::sync::Arc;
+
+    pub(crate) fn setup(mock_db: MockBcDbTrait) -> web::Data<Arc<Schema>> {
+        context::init(mock_db, "soft_name", "soft_version");
+
+        web::Data::new(std::sync::Arc::new(create_schema()))
+    }
+
+    pub(crate) fn test_gql_query(
+        schema: web::Data<Arc<Schema>>,
+        gql_query: &str,
+        expected_response: serde_json::Value,
+    ) {
+        let resp = test::block_on(graphql(
+            schema,
+            web::Json(GraphQLRequest::new(gql_query.to_owned(), None, None)),
+        ))
+        .unwrap();
+        assert_eq!(resp.status(), http::StatusCode::OK);
+        if let Some(Body::Bytes(ref body_bytes)) = resp.body().as_ref() {
+            assert_eq!(
+                expected_response,
+                serde_json::Value::from_str(
+                    &String::from_utf8(body_bytes.to_vec())
+                        .expect("response have invalid utf8 format.")
+                )
+                .expect("response have invalid JSON format.")
+            )
+        } else {
+            panic!("Response must contain body in bytes format.")
+        }
+    }
+}
diff --git a/lib/modules/gva/src/schema/queries/block.rs b/lib/modules/gva/src/schema/queries/block.rs
new file mode 100644
index 0000000000000000000000000000000000000000..73547478d374d493dd978374d0b5d1a655ff1161
--- /dev/null
+++ b/lib/modules/gva/src/schema/queries/block.rs
@@ -0,0 +1,114 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+// ! Module execute GraphQl schema block query
+
+use super::db_err_to_juniper_err;
+use crate::context::Context;
+use crate::db::BcDbTrait;
+use crate::schema::entities::block::Block;
+use dubp_common_doc::BlockNumber;
+use juniper::Executor;
+use juniper::FieldResult;
+use juniper_from_schema::{QueryTrail, Walked};
+
+pub(crate) fn execute(
+    executor: &Executor<'_, Context>,
+    _trail: &QueryTrail<'_, Block, Walked>,
+    number: i32,
+) -> FieldResult<Option<Block>> {
+    let block_number = if number >= 0 {
+        BlockNumber(number as u32)
+    } else {
+        return Err(juniper::FieldError::from("Block number must be positive."));
+    };
+
+    executor
+        .context()
+        .get_db()
+        .get_db_block_in_local_blockchain(block_number)
+        .map_err(db_err_to_juniper_err)
+        .map(|db_block_opt| db_block_opt.map(Block::from_db_block))
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::db::MockBcDbTrait;
+    use crate::schema::queries::tests;
+    use dubp_block_doc::block::BlockDocument;
+    use dubp_blocks_tests_tools::mocks::gen_empty_timed_block_v10;
+    use dubp_common_doc::{BlockHash, BlockNumber, Blockstamp};
+    use dup_crypto::hashs::Hash;
+    use dup_crypto_tests_tools::mocks::{hash, pubkey};
+    use durs_bc_db_reader::blocks::DbBlock;
+    use mockall::predicate::eq;
+    use serde_json::json;
+
+    #[test]
+    fn test_graphql_block() {
+        let mut mock_db = MockBcDbTrait::new();
+        mock_db
+            .expect_get_db_block_in_local_blockchain()
+            .with(eq(BlockNumber(42)))
+            .returning(|_| {
+                let mut block = gen_empty_timed_block_v10(
+                    Blockstamp {
+                        id: BlockNumber(42),
+                        hash: BlockHash(hash('A')),
+                    },
+                    1_488_987_127,
+                    Hash::default(),
+                );
+                block.issuers = vec![pubkey('B')];
+                Ok(Some(DbBlock {
+                    block: BlockDocument::V10(block),
+                    expire_certs: None,
+                }))
+            });
+
+        let schema = tests::setup(mock_db);
+
+        tests::test_gql_query(
+            schema.clone(),
+            "{ block { commonTime, currency, hash, issuer, number, version } }",
+            json!({
+                "errors": [{
+                    "message": "Field \"block\" argument \"number\" of type \"Int!\" is required but not provided",
+                    "locations": [{
+                        "line": 1,
+                        "column": 3,
+                    }]
+                }]
+            }),
+        );
+
+        tests::test_gql_query(
+            schema,
+            "{ block(number: 42) { commonTime, currency, hash, issuer, number, version } }",
+            json!({
+                "data": {
+                    "block": {
+                        "commonTime": 1_488_987_127.0,
+                        "currency": "test_currency",
+                        "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+                        "issuer": "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
+                        "number": 42,
+                        "version": 10
+                    }
+                }
+            }),
+        );
+    }
+}
diff --git a/lib/modules/gva/src/schema/queries/blocks.rs b/lib/modules/gva/src/schema/queries/blocks.rs
new file mode 100644
index 0000000000000000000000000000000000000000..fa88927b745c145ba5bc637382d4aea92f225952
--- /dev/null
+++ b/lib/modules/gva/src/schema/queries/blocks.rs
@@ -0,0 +1,168 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+// ! Module execute GraphQl schema blocks query
+
+use super::db_err_to_juniper_err;
+use crate::context::Context;
+use crate::db::BcDbTrait;
+use crate::schema::entities::block::Block;
+use crate::schema::paging;
+use crate::schema::Paging;
+use durs_bc_db_reader::blocks::DbBlock;
+use juniper::Executor;
+use juniper::FieldResult;
+use juniper_from_schema::{QueryTrail, Walked};
+
+pub(crate) fn execute(
+    executor: &Executor<'_, Context>,
+    _trail: &QueryTrail<'_, Block, Walked>,
+    paging_opt: Option<Paging>,
+) -> FieldResult<Vec<Block>> {
+    let db = executor.context().get_db();
+
+    let blocks: Vec<DbBlock> = db
+        .get_db_blocks_in_local_blockchain(
+            paging::FilledPaging::new(db, paging_opt)
+                .map_err(db_err_to_juniper_err)?
+                .get_range(),
+        )
+        .map_err(db_err_to_juniper_err)?;
+
+    Ok(blocks.into_iter().map(Block::from_db_block).collect())
+
+    /*let db: &BcDbRo = &executor.context().get_db();
+    db.read(|r| {
+        paging::FilledPaging::new(db, paging_opt)?
+            .get_range()
+            .filter_map(|n| match block::get_block(db, r, BlockNumber(n)) {
+                Ok(Some(db_block)) => Some(Ok(db_block)),
+                Ok(None) => None,
+                Err(e) => Some(Err(e)),
+            })
+            .collect::<Result<Vec<Block>, DbError>>()
+    })
+    .map_err(db_err_to_juniper_err)*/
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::db::MockBcDbTrait;
+    use crate::schema::queries::tests;
+    use dubp_block_doc::block::BlockDocument;
+    use dubp_blocks_tests_tools::mocks::gen_empty_timed_block_v10;
+    use dubp_common_doc::traits::Document;
+    use dubp_common_doc::{BlockHash, BlockNumber, Blockstamp};
+    use dup_crypto::hashs::Hash;
+    use dup_crypto_tests_tools::mocks::{hash, pubkey};
+    use durs_bc_db_reader::blocks::DbBlock;
+    use mockall::predicate::eq;
+    use serde_json::json;
+    use std::ops::Range;
+
+    #[test]
+    fn test_graphql_blocks() {
+        let mut mock_db = MockBcDbTrait::new();
+
+        let mut block_0 = gen_empty_timed_block_v10(
+            Blockstamp {
+                id: BlockNumber(0),
+                hash: BlockHash(hash('A')),
+            },
+            1_488_987_127,
+            Hash::default(),
+        );
+        block_0.issuers = vec![pubkey('A')];
+        let mut block_1 = gen_empty_timed_block_v10(
+            Blockstamp {
+                id: BlockNumber(1),
+                hash: BlockHash(hash('B')),
+            },
+            1_488_987_128,
+            Hash::default(),
+        );
+        block_1.issuers = vec![pubkey('B')];
+        let mut current_block = gen_empty_timed_block_v10(
+            Blockstamp {
+                id: BlockNumber(2),
+                hash: BlockHash(hash('C')),
+            },
+            1_488_987_129,
+            Hash::default(),
+        );
+        current_block.issuers = vec![pubkey('C')];
+
+        let current_blockstamp = current_block.blockstamp();
+        mock_db
+            .expect_get_current_blockstamp()
+            .times(1)
+            .returning(move || Ok(Some(current_blockstamp)));
+
+        mock_db
+            .expect_get_db_blocks_in_local_blockchain()
+            .with(eq(Range { start: 0, end: 3 }))
+            .returning(move |_| {
+                Ok(vec![
+                    DbBlock {
+                        block: BlockDocument::V10(block_0.clone()),
+                        expire_certs: None,
+                    },
+                    DbBlock {
+                        block: BlockDocument::V10(block_1.clone()),
+                        expire_certs: None,
+                    },
+                    DbBlock {
+                        block: BlockDocument::V10(current_block.clone()),
+                        expire_certs: None,
+                    },
+                ])
+            });
+
+        let schema = tests::setup(mock_db);
+
+        tests::test_gql_query(
+            schema,
+            "{ blocks { commonTime, currency, hash, issuer, number, version } }",
+            json!({
+                "data": {
+                    "blocks": [{
+                        "commonTime": 1_488_987_127.0,
+                        "currency": "test_currency",
+                        "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+                        "issuer": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+                        "number": 0,
+                        "version": 10
+                    },
+                    {
+                        "commonTime": 1_488_987_128.0,
+                        "currency": "test_currency",
+                        "hash": "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
+                        "issuer": "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
+                        "number": 1,
+                        "version": 10
+                    },
+                    {
+                        "commonTime": 1_488_987_129.0,
+                        "currency": "test_currency",
+                        "hash": "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC",
+                        "issuer": "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC",
+                        "number": 2,
+                        "version": 10
+                    }]
+                }
+            }),
+        );
+    }
+}
diff --git a/lib/modules/gva/src/schema/queries/current.rs b/lib/modules/gva/src/schema/queries/current.rs
new file mode 100644
index 0000000000000000000000000000000000000000..309bc56df99fbf5abf9e999e842d2f87f4e36ba2
--- /dev/null
+++ b/lib/modules/gva/src/schema/queries/current.rs
@@ -0,0 +1,88 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+// ! Module execute GraphQl schema current query
+
+use super::db_err_to_juniper_err;
+use crate::context::Context;
+use crate::db::BcDbTrait;
+use crate::schema::entities::block::Block;
+use juniper::Executor;
+use juniper::FieldResult;
+use juniper_from_schema::{QueryTrail, Walked};
+
+pub(crate) fn execute(
+    executor: &Executor<'_, Context>,
+    _trail: &QueryTrail<'_, Block, Walked>,
+) -> FieldResult<Option<Block>> {
+    executor
+        .context()
+        .get_db()
+        .get_current_block()
+        .map_err(db_err_to_juniper_err)
+        .map(|db_block_opt| db_block_opt.map(Block::from_db_block))
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::db::MockBcDbTrait;
+    use crate::schema::queries::tests;
+    use dubp_block_doc::block::BlockDocument;
+    use dubp_blocks_tests_tools::mocks::gen_empty_timed_block_v10;
+    use dubp_common_doc::{BlockHash, BlockNumber, Blockstamp};
+    use dup_crypto::hashs::Hash;
+    use dup_crypto_tests_tools::mocks::{hash, pubkey};
+    use durs_bc_db_reader::blocks::DbBlock;
+    use serde_json::json;
+
+    #[test]
+    fn test_graphql_current() {
+        let mut mock_db = MockBcDbTrait::new();
+        mock_db.expect_get_current_block().returning(|| {
+            let mut current_block = gen_empty_timed_block_v10(
+                Blockstamp {
+                    id: BlockNumber(42),
+                    hash: BlockHash(hash('A')),
+                },
+                1_488_987_127,
+                Hash::default(),
+            );
+            current_block.issuers = vec![pubkey('B')];
+            Ok(Some(DbBlock {
+                block: BlockDocument::V10(current_block),
+                expire_certs: None,
+            }))
+        });
+
+        let schema = tests::setup(mock_db);
+
+        tests::test_gql_query(
+            schema,
+            "{ current { commonTime, currency, hash, issuer, number, version } }",
+            json!({
+                "data": {
+                    "current": {
+                        "commonTime": 1_488_987_127.0,
+                        "currency": "test_currency",
+                        "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+                        "issuer": "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
+                        "number": 42,
+                        "version": 10
+                    }
+                }
+            }),
+        )
+    }
+}
diff --git a/lib/modules/gva/src/schema/queries/node.rs b/lib/modules/gva/src/schema/queries/node.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b9b797231c327df91b5e501e9dd1c4cb02f585ba
--- /dev/null
+++ b/lib/modules/gva/src/schema/queries/node.rs
@@ -0,0 +1,61 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+// ! Module execute GraphQl schema node query
+
+use crate::context::Context;
+use crate::schema::entities::node::{Node, Summary};
+use juniper::Executor;
+use juniper::FieldResult;
+use juniper_from_schema::{QueryTrail, Walked};
+
+pub(crate) fn execute(
+    executor: &Executor<'_, Context>,
+    _trail: &QueryTrail<'_, Node, Walked>,
+) -> FieldResult<Node> {
+    Ok(Node {
+        summary: Summary {
+            software: executor.context().get_software_name(),
+            version: executor.context().get_software_version(),
+        },
+    })
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::db::MockBcDbTrait;
+    use crate::schema::queries::tests;
+    use serde_json::json;
+
+    #[test]
+    fn test_graphql_current() {
+        let schema = tests::setup(MockBcDbTrait::new());
+
+        tests::test_gql_query(
+            schema,
+            "{ node { summary { software, version } } }",
+            json!({
+                "data": {
+                    "node": {
+                        "summary": {
+                            "software": "soft_name",
+                            "version": "soft_version"
+                        }
+                    }
+                }
+            }),
+        )
+    }
+}
diff --git a/lib/modules/gva/src/webserver.rs b/lib/modules/gva/src/webserver.rs
index fe06567436bcf6cd055ba5bc8ba28568531dc34e..309bc4ed2213133cac790a2a7f112e5cd56e2cd5 100644
--- a/lib/modules/gva/src/webserver.rs
+++ b/lib/modules/gva/src/webserver.rs
@@ -15,18 +15,20 @@
 // web server implementaion based on actix-web
 
 use crate::context;
-use crate::schema::{create_schema, Schema};
-use actix_web::{middleware, web, App, Error, HttpResponse, HttpServer};
+use crate::graphql::graphql;
+use crate::schema::create_schema;
+use actix_web::{middleware, web, App, HttpResponse, HttpServer};
+#[cfg(not(test))]
 use durs_common_tools::fatal_error;
 use durs_conf::DuRsConf;
 use durs_module::SoftwareMetaDatas;
 use durs_network_documents::host::Host;
 use durs_network_documents::url::Url;
-use futures::future::Future;
 use juniper::http::graphiql::graphiql_source;
-use juniper::http::GraphQLRequest;
 use std::net::SocketAddr;
-use std::sync::Arc;
+
+#[cfg(test)]
+use crate::db::MockBcDbTrait;
 
 fn graphiql() -> HttpResponse {
     let html = graphiql_source("/graphql");
@@ -35,23 +37,6 @@ fn graphiql() -> HttpResponse {
         .body(html)
 }
 
-fn graphql(
-    schema: web::Data<Arc<Schema>>,
-    data: web::Json<GraphQLRequest>,
-) -> impl Future<Item = HttpResponse, Error = Error> {
-    let context = crate::context::get_context();
-    web::block(move || {
-        let result = data.execute(&schema, context);
-        serde_json::to_string(&result)
-    })
-    .map_err(Error::from)
-    .and_then(|user| {
-        Ok(HttpResponse::Ok()
-            .content_type("application/json")
-            .body(user))
-    })
-}
-
 pub fn start_web_server(
     soft_meta_datas: &SoftwareMetaDatas<DuRsConf>,
     host: Host,
@@ -65,13 +50,29 @@ pub fn start_web_server(
     // Create Juniper schema
     let schema = std::sync::Arc::new(create_schema());
 
-    // Instanciate the context
-    let db_path = durs_conf::get_blockchain_db_path(soft_meta_datas.profile_path.clone());
-    if let Ok(db) = durs_bc_db_reader::open_db_ro(&std::path::Path::new(&db_path)) {
-        context::init(db, soft_meta_datas.soft_name, soft_meta_datas.soft_version);
-    } else {
-        fatal_error!("GVA: fail to open DB.");
+    // Get DB
+    #[cfg(not(test))]
+    let db = {
+        let db_path = durs_conf::get_blockchain_db_path(soft_meta_datas.profile_path.clone());
+        if let Ok(db) = durs_bc_db_reader::open_db_ro(&std::path::Path::new(&db_path)) {
+            db
+        } else {
+            fatal_error!("GVA: fail to open DB.");
+        }
     };
+    #[cfg(test)]
+    let db = MockBcDbTrait::new();
+
+    cfg_if::cfg_if! {
+        if #[cfg(test)] {
+            MockBcDbTrait::new()
+        } else {
+
+        }
+    };
+
+    // Instanciate the context
+    context::init(db, soft_meta_datas.soft_name, soft_meta_datas.soft_version);
 
     // Start http server
     HttpServer::new(move || {