use crate::client::{
schema::{
schema,
BlockId,
ConnectionArgs,
PageInfo,
Signature,
Tai64Timestamp,
U64,
},
PaginatedResult,
};
use fuel_core_types::fuel_crypto;
use super::{
tx::TransactionIdFragment,
Bytes32,
};
#[derive(cynic::QueryVariables, Debug)]
pub struct BlockByIdArgs {
pub id: Option<BlockId>,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(
schema_path = "./assets/schema.sdl",
graphql_type = "Query",
variables = "BlockByIdArgs"
)]
pub struct BlockByIdQuery {
#[arguments(id: $id)]
pub block: Option<Block>,
}
#[derive(cynic::QueryVariables, Debug)]
pub struct BlockByHeightArgs {
pub height: Option<U64>,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(
schema_path = "./assets/schema.sdl",
graphql_type = "Query",
variables = "BlockByHeightArgs"
)]
pub struct BlockByHeightQuery {
#[arguments(height: $height)]
pub block: Option<Block>,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(
schema_path = "./assets/schema.sdl",
graphql_type = "Query",
variables = "ConnectionArgs"
)]
pub struct BlocksQuery {
#[arguments(after: $after, before: $before, first: $first, last: $last)]
pub blocks: BlockConnection,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(schema_path = "./assets/schema.sdl")]
pub struct BlockConnection {
pub edges: Vec<BlockEdge>,
pub page_info: PageInfo,
}
impl From<BlockConnection> for PaginatedResult<Block, String> {
fn from(conn: BlockConnection) -> Self {
PaginatedResult {
cursor: conn.page_info.end_cursor,
has_next_page: conn.page_info.has_next_page,
has_previous_page: conn.page_info.has_previous_page,
results: conn.edges.into_iter().map(|e| e.node).collect(),
}
}
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(schema_path = "./assets/schema.sdl")]
pub struct BlockEdge {
pub cursor: String,
pub node: Block,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(schema_path = "./assets/schema.sdl")]
pub struct Block {
pub id: BlockId,
pub header: Header,
pub consensus: Consensus,
pub transactions: Vec<TransactionIdFragment>,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(schema_path = "./assets/schema.sdl", graphql_type = "Block")]
pub struct BlockIdFragment {
pub id: BlockId,
}
#[derive(cynic::InputObject, Clone, Debug)]
#[cynic(schema_path = "./assets/schema.sdl")]
pub struct TimeParameters {
pub start_time: U64,
pub block_time_interval: U64,
}
#[derive(cynic::QueryVariables, Debug)]
pub struct ProduceBlockArgs {
pub blocks_to_produce: U64,
pub time: Option<TimeParameters>,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(
schema_path = "./assets/schema.sdl",
variables = "ProduceBlockArgs",
graphql_type = "Mutation"
)]
pub struct BlockMutation {
#[arguments(blocksToProduce: $blocks_to_produce, time: $time)]
pub produce_blocks: U64,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(schema_path = "./assets/schema.sdl")]
pub struct Header {
pub id: BlockId,
pub da_height: U64,
pub transactions_count: U64,
pub output_messages_count: U64,
pub transactions_root: Bytes32,
pub output_messages_root: Bytes32,
pub height: U64,
pub prev_root: Bytes32,
pub time: Tai64Timestamp,
pub application_hash: Bytes32,
}
#[derive(cynic::InlineFragments, Debug)]
#[cynic(schema_path = "./assets/schema.sdl")]
pub enum Consensus {
Genesis(Genesis),
PoAConsensus(PoAConsensus),
#[cynic(fallback)]
Unknown,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(schema_path = "./assets/schema.sdl")]
pub struct Genesis {
pub chain_config_hash: Bytes32,
pub coins_root: Bytes32,
pub contracts_root: Bytes32,
pub messages_root: Bytes32,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(schema_path = "./assets/schema.sdl")]
pub struct PoAConsensus {
pub signature: Signature,
}
impl Block {
pub fn block_producer(&self) -> Option<fuel_crypto::PublicKey> {
let message = self.header.id.clone().into_message();
match &self.consensus {
Consensus::Genesis(_) => Some(Default::default()),
Consensus::PoAConsensus(poa) => {
let signature = poa.signature.clone().into_signature();
let producer_pub_key = signature.recover(&message);
producer_pub_key.ok()
}
Consensus::Unknown => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn block_by_id_query_gql_output() {
use cynic::QueryBuilder;
let operation = BlockByIdQuery::build(BlockByIdArgs {
id: Some(BlockId::default()),
});
insta::assert_snapshot!(operation.query)
}
#[test]
fn block_by_height_query_gql_output() {
use cynic::QueryBuilder;
let operation = BlockByHeightQuery::build(BlockByHeightArgs {
height: Some(U64(0)),
});
insta::assert_snapshot!(operation.query)
}
#[test]
fn block_mutation_query_gql_output() {
use cynic::MutationBuilder;
let operation = BlockMutation::build(ProduceBlockArgs {
blocks_to_produce: U64(0),
time: None,
});
insta::assert_snapshot!(operation.query)
}
#[test]
fn blocks_connection_query_gql_output() {
use cynic::QueryBuilder;
let operation = BlocksQuery::build(ConnectionArgs {
after: None,
before: None,
first: None,
last: None,
});
insta::assert_snapshot!(operation.query)
}
}