[][src]Module exonum_explorer_service::api

HTTP API for the explorer service. All APIs are accessible from the public HTTP server of the node.

Table of Contents

List Blocks

PropertyValue
Path/api/explorer/v1/blocks
MethodGET
Query typeBlockQuery
Return typeBlockInfo

Returns the explored range and the corresponding headers. The range specifies the smallest and largest heights traversed to collect the blocks.

let mut testkit = TestKitBuilder::validator()
    .with_default_rust_service(ExplorerFactory)
    .build();
testkit.create_blocks_until(Height(5));

let api = testkit.api();
let response: BlocksRange = reqwest::Client::new()
    .get(&api.public_url("api/explorer/v1/blocks?count=2"))
    .send()?
    .error_for_status()?
    .json()?;
assert_eq!(response.range, Height(4)..Height(6));
// Blocks are returned in reverse order, from the latest
// to the earliest.
assert_eq!(response.blocks[0].block.height, Height(5));
assert_eq!(response.blocks[1].block.height, Height(4));

Get Specific Block

PropertyValue
Path/api/explorer/v1/block
MethodGET
Query typeBlockQuery
Return typeBlockInfo

Returns the content for a block at a specific height.

testkit.create_blocks_until(Height(5));

let api = testkit.api();
let response: BlockInfo = reqwest::Client::new()
    .get(&api.public_url("api/explorer/v1/block?height=3"))
    .send()?
    .error_for_status()?
    .json()?;
assert_eq!(response.block.height, Height(3));
// Precommits and median precommit time are always returned.
assert!(response.precommits.is_some());
assert!(response.time.is_some());

Transaction by Hash

PropertyValue
Path/api/explorer/v1/transactions
MethodGET
Query typeTransactionQuery
Return typeTransactionInfo

Searches for a transaction, either committed or uncommitted, by the hash.

#[exonum_interface]
trait ServiceInterface<Ctx> {
    type Output;
    #[interface_method(id = 0)]
    fn do_nothing(&self, ctx: Ctx, _seed: u32) -> Self::Output;
}

#[derive(Debug, ServiceDispatcher, ServiceFactory)]
#[service_dispatcher(implements("ServiceInterface"))]
struct MyService;
// Some implementations skipped for `MyService`...

let mut testkit = TestKitBuilder::validator()
   .with_default_rust_service(ExplorerFactory)
   .with_default_rust_service(MyService)
   .build();
let tx = gen_keypair().do_nothing(MyService::INSTANCE_ID, 0);
testkit.create_block_with_transaction(tx.clone());

let api = testkit.api();
let response: TransactionInfo = reqwest::Client::new()
    .get(&api.public_url("api/explorer/v1/transactions"))
    .query(&TransactionQuery { hash: tx.object_hash() })
    .send()?
    .error_for_status()?
    .json()?;
let response = response.as_committed().unwrap();
assert_eq!(response.location().block_height(), Height(1));

Call Status for Transaction

PropertyValue
Path/api/explorer/v1/call_status/transaction
MethodGET
Query typeTransactionQuery
Return typeCallStatusResponse

Returns call status of committed transaction.

#[exonum_interface]
trait ServiceInterface<Ctx> {
    type Output;
    #[interface_method(id = 0)]
    fn cause_error(&self, ctx: Ctx, _seed: u32) -> Self::Output;
}

#[derive(Debug, ServiceDispatcher, ServiceFactory)]
#[service_dispatcher(implements("ServiceInterface"))]
struct MyService;
// Some implementations skipped for `MyService`...

let mut testkit = TestKitBuilder::validator()
   .with_default_rust_service(MyService)
   .with_default_rust_service(ExplorerFactory)
   .build();
let tx = gen_keypair().cause_error(MyService::INSTANCE_ID, 0);
testkit.create_block_with_transaction(tx.clone());

let api = testkit.api();
let response: CallStatusResponse = reqwest::Client::new()
    .get(&api.public_url("api/explorer/v1/call_status/transaction"))
    .query(&TransactionQuery { hash: tx.object_hash() })
    .send()?
    .error_for_status()?
    .json()?;
let err = response.status.0.unwrap_err();
assert_eq!(err.description(), "Error!");

Call Status for before_transactions hook

PropertyValue
Path/api/explorer/v1/call_status/before_transactions
MethodGET
Query typeCallStatusQuery
Return typeCallStatusResponse

Returns call status of a before_transactions hook for a specific service at a specific height. Note that the endpoint returns the normal execution status Ok(()) if the queried service was not active at the specified height.

#[derive(Debug, ServiceDispatcher, ServiceFactory)]
struct MyService;
// Some implementations skipped for `MyService`...

let mut testkit = TestKitBuilder::validator()
   .with_default_rust_service(MyService)
   .with_default_rust_service(ExplorerFactory)
   .build();
testkit.create_blocks_until(Height(5));

let api = testkit.api();
let response: CallStatusResponse = reqwest::Client::new()
    .get(&api.public_url("api/explorer/v1/call_status/before_transactions"))
    .query(&CallStatusQuery {
        height: Height(2),
        service_id: MyService::INSTANCE_ID,
    })
    .send()?
    .error_for_status()?
    .json()?;
let err = response.status.0.unwrap_err();
assert_eq!(err.description(), "Not a good start");

Call Status for after_transactions hook

PropertyValue
Path/api/explorer/v1/call_status/after_transactions
MethodGET
Query typeCallStatusQuery
Return typeCallStatusResponse

Same as the previous endpoint, only for a hook executing after all transactions in a block.

Submit Transaction

PropertyValue
Path/api/explorer/v1/transactions
MethodPOST
Query typeTransactionHex
Return typeTransactionResponse

Adds transaction into the pool of unconfirmed transactions if it is valid and returns an error otherwise.

#[exonum_interface]
trait ServiceInterface<Ctx> {
    type Output;
    #[interface_method(id = 0)]
    fn do_nothing(&self, ctx: Ctx, _seed: u32) -> Self::Output;
}

#[derive(Debug, ServiceDispatcher, ServiceFactory)]
#[service_dispatcher(implements("ServiceInterface"))]
struct MyService;
// Some implementations skipped for `MyService`...

let mut testkit = TestKitBuilder::validator()
   .with_default_rust_service(ExplorerFactory)
   .with_default_rust_service(MyService)
   .build();
let tx = gen_keypair().do_nothing(MyService::INSTANCE_ID, 0);
let tx_body = hex::encode(tx.to_bytes());

let api = testkit.api();
let response: TransactionResponse = reqwest::Client::new()
    .post(&api.public_url("api/explorer/v1/transactions"))
    .json(&TransactionHex { tx_body })
    .send()?
    .error_for_status()?
    .json()?;
assert_eq!(response.tx_hash, tx.object_hash());

Modules

websocket

WebSocket API of the explorer service.

Structs

BlockInfo

Information about a block in the blockchain.

BlockQuery

Block query parameters.

BlocksQuery

Blocks in range parameters.

BlocksRange

Information on blocks coupled with the corresponding range in the blockchain.

CallStatusQuery

Query parameters to check the execution status of a before_transactions or after_transactions call.

CallStatusResponse

Call status response.

CommittedTransactionSummary

Summary about a particular transaction in the blockchain. Does not include transaction content.

TransactionFilter

Filter for transactions by service instance and (optionally) method identifier within the service.

TransactionHex

Raw Transaction in hex representation.

TransactionQuery

Transaction query parameters.

TransactionResponse

Response to a request to broadcast a transaction over the blockchain network.

Enums

Notification

Notification message passed to WebSocket clients.

SubscriptionType

Subscription type for new blocks or committed transactions.

TransactionInfo

Information about the transaction.

Constants

MAX_BLOCKS_PER_REQUEST

The maximum number of blocks to return per blocks request, in this way the parameter limits the maximum execution time for such requests.