Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ SDK: Add more endpoints to IndexerApiHttpClient #630

Merged
merged 3 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/client-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ hyle_model = { path = "../hyle-model", package = "hyle-model", features = ["full
anyhow = "1.0.94"
bincode = { version = "2.0.0-rc.3", features = ["serde"] }
borsh = "1.5.3"
serde = "1.0"
serde_json = { version = "1" }

bonsai-runner = { path = "../bonsai-runner", optional = true }
Expand Down
243 changes: 139 additions & 104 deletions crates/client-sdk/src/rest_client.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
use std::fmt::Display;

use anyhow::{Context, Result};
use reqwest::{Response, Url};
use reqwest::Url;

use sdk::{
api::{APIContract, APIStaking, APITransaction, NodeInfo},
BlobTransaction, BlockHeight, ConsensusInfo, Contract, ContractName, ProofTransaction,
RegisterContractTransaction, StateDigest, TxHash,
api::*, BlobIndex, BlobTransaction, BlockHash, BlockHeight, ConsensusInfo, Contract,
ContractName, ProofTransaction, RegisterContractTransaction, StateDigest, TxHash,
};

pub struct NodeApiHttpClient {
Expand All @@ -28,99 +25,80 @@ impl NodeApiHttpClient {
}

pub async fn send_tx_blob(&self, tx: &BlobTransaction) -> Result<TxHash> {
self.reqwest_client
.post(format!("{}v1/tx/send/blob", self.url))
.body(serde_json::to_string(tx)?)
.header("Content-Type", "application/json")
.send()
.await
.context("Sending tx blob")?
.json::<TxHash>()
.await
.context("reading tx hash response")
self.post("v1/tx/send/blob", tx, "Sending tx blob").await
}

pub async fn send_tx_proof(&self, tx: &ProofTransaction) -> Result<Response> {
self.reqwest_client
.post(format!("{}v1/tx/send/proof", self.url))
.body(serde_json::to_string(&tx)?)
.header("Content-Type", "application/json")
.send()
.await
.context("Sending tx proof")
pub async fn send_tx_proof(&self, tx: &ProofTransaction) -> Result<TxHash> {
self.post("v1/tx/send/proof", tx, "Sending tx proof").await
}

pub async fn send_tx_register_contract(
&self,
tx: &RegisterContractTransaction,
) -> Result<Response> {
self.reqwest_client
.post(format!("{}v1/contract/register", self.url))
.body(serde_json::to_string(&tx)?)
.header("Content-Type", "application/json")
.send()
) -> Result<TxHash> {
self.post("v1/contract/register", tx, "Sending tx register contract")
.await
.context("Sending tx register contract")
}

pub async fn get_consensus_info(&self) -> Result<ConsensusInfo> {
self.reqwest_client
.get(format!("{}v1/consensus/info", self.url))
.header("Content-Type", "application/json")
.send()
.await
.context("getting consensus info")?
.json::<ConsensusInfo>()
self.get("v1/consensus/info", "getting consensus info")
.await
.context("reading consensus info response")
}

pub async fn get_consensus_staking_state(&self) -> Result<APIStaking> {
self.reqwest_client
.get(format!("{}v1/consensus/staking_state", self.url))
.header("Content-Type", "application/json")
.send()
.await
.context("getting consensus staking state")?
.json::<APIStaking>()
.await
.context("reading consensus staking state response")
self.get(
"v1/consensus/staking_state",
"getting consensus staking state",
)
.await
}

pub async fn get_node_info(&self) -> Result<NodeInfo> {
self.reqwest_client
.get(format!("{}v1/info", self.url))
.header("Content-Type", "application/json")
.send()
.await
.context("getting node info")?
.json::<NodeInfo>()
.await
.context("reading node info response")
self.get("v1/info", "getting node info").await
}

pub async fn get_block_height(&self) -> Result<BlockHeight> {
self.get("v1/da/block/height", "getting block height").await
}

pub async fn get_contract(&self, contract_name: &ContractName) -> Result<Contract> {
self.get(
&format!("v1/contract/{}", contract_name),
&format!("getting contract {}", contract_name),
)
.await
}

async fn get<T>(&self, endpoint: &str, context_msg: &str) -> Result<T>
where
T: serde::de::DeserializeOwned,
{
self.reqwest_client
.get(format!("{}v1/da/block/height", self.url))
.get(format!("{}{}", self.url, endpoint))
.header("Content-Type", "application/json")
.send()
.await
.context("getting block height")?
.json::<BlockHeight>()
.context(format!("{} request failed", context_msg))?
.json::<T>()
.await
.context("reading block height response")
.context(format!("Failed to deserialize {}", context_msg))
}

pub async fn get_contract(&self, contract_name: &ContractName) -> Result<Contract> {
async fn post<T, R>(&self, endpoint: &str, body: &T, context_msg: &str) -> Result<R>
where
T: serde::Serialize,
R: serde::de::DeserializeOwned,
{
self.reqwest_client
.get(format!("{}v1/contract/{}", self.url, contract_name))
.post(format!("{}{}", self.url, endpoint))
.body(serde_json::to_string(body)?)
.header("Content-Type", "application/json")
.send()
.await
.context(format!("getting Contract {}", contract_name))?
.json::<Contract>()
.context(format!("{} request failed", context_msg))?
.json::<R>()
.await
.context("reading contract response")
.context(format!("Failed to deserialize {}", context_msg))
}
}

Expand All @@ -133,27 +111,15 @@ impl IndexerApiHttpClient {
}

pub async fn list_contracts(&self) -> Result<Vec<APIContract>> {
self.reqwest_client
.get(format!("{}v1/indexer/contracts", self.url))
.header("Content-Type", "application/json")
.send()
.await
.context("getting Contract")?
.json::<Vec<APIContract>>()
.await
.context("reading contract response")
self.get("v1/indexer/contracts", "listing contracts").await
}

pub async fn get_indexer_contract(&self, contract_name: &ContractName) -> Result<APIContract> {
self.reqwest_client
.get(format!("{}v1/indexer/contract/{}", self.url, contract_name))
.header("Content-Type", "application/json")
.send()
.await
.context(format!("getting Contract {}", contract_name))?
.json::<APIContract>()
.await
.context("reading contract response")
self.get(
&format!("v1/indexer/contract/{contract_name}"),
&format!("getting contract {contract_name}"),
)
.await
}

pub async fn fetch_current_state<State>(&self, contract_name: &ContractName) -> Result<State>
Expand All @@ -165,36 +131,105 @@ impl IndexerApiHttpClient {
StateDigest(resp.state_digest).try_into()
}

pub async fn query_indexer<U: Display>(&self, route: U) -> Result<Response> {
self.reqwest_client
.get(format!("{}v1/{}", self.url, route))
.header("Content-Type", "application/json")
.send()
.await
.context("Running custom query to {route}")
pub async fn get_blocks(&self) -> Result<Vec<APIBlock>> {
self.get("v1/indexer/blocks", "getting blocks").await
}

pub async fn get_node_info(&self) -> Result<NodeInfo> {
self.reqwest_client
.get(format!("{}v1/info", self.url))
.header("Content-Type", "application/json")
.send()
pub async fn get_last_block(&self) -> Result<APIBlock> {
self.get("v1/indexer/block/last", "getting last block")
.await
.context("getting node info")?
.json::<NodeInfo>()
}

pub async fn get_block_by_height(&self, height: &BlockHeight) -> Result<APIBlock> {
self.get(
&format!("v1/indexer/block/height/{height}"),
&format!("getting block with height {height}"),
)
.await
}

pub async fn get_block_by_hash(&self, hash: &BlockHash) -> Result<APIBlock> {
self.get(
&format!("v1/indexer/block/hash/{hash}"),
&format!("getting block with hash {hash}"),
)
.await
}

pub async fn get_transactions(&self) -> Result<Vec<APITransaction>> {
self.get("v1/indexer/transactions", "getting transactions")
.await
.context("reading node info response")
}

pub async fn get_transaction_by_hash(&self, tx_hash: &TxHash) -> Result<APITransaction> {
pub async fn get_transactions_by_height(
&self,
height: &BlockHeight,
) -> Result<Vec<APITransaction>> {
self.get(
&format!("v1/indexer/transactions/block/{height}"),
&format!("getting transactions for block height {height}"),
)
.await
}

pub async fn get_transactions_by_contract(
&self,
contract_name: &ContractName,
) -> Result<Vec<APITransaction>> {
self.get(
&format!("v1/indexer/transactions/contract/{contract_name}"),
&format!("getting transactions for contract {contract_name}"),
)
.await
}

pub async fn get_transaction_with_hash(&self, tx_hash: &TxHash) -> Result<APITransaction> {
self.get(
&format!("v1/indexer/transaction/hash/{tx_hash}"),
&format!("getting transaction with hash {tx_hash}"),
)
.await
}

pub async fn get_blob_transactions_by_contract(
&self,
contract_name: &ContractName,
) -> Result<Vec<TransactionWithBlobs>> {
self.get(
&format!("v1/indexer/blob_transactions/contract/{contract_name}"),
&format!("getting blob transactions for contract {contract_name}"),
)
.await
}

pub async fn get_blob_by_tx_hash(&self, tx_hash: &TxHash) -> Result<APIBlob> {
self.get(
&format!("v1/indexer/blobs/hash/{tx_hash}"),
&format!("getting blob by transaction hash {tx_hash}"),
)
.await
}

pub async fn get_blob(&self, tx_hash: &TxHash, blob_index: BlobIndex) -> Result<APIBlob> {
self.get(
&format!("v1/indexer/blob/hash/{tx_hash}/index/{blob_index}"),
&format!("getting blob with hash {tx_hash} and index {blob_index}"),
)
.await
}

async fn get<T>(&self, endpoint: &str, context_msg: &str) -> Result<T>
where
T: serde::de::DeserializeOwned,
{
self.reqwest_client
.get(format!("{}v1/indexer/transaction/hash/{tx_hash}", self.url))
.get(format!("{}{}", self.url, endpoint))
.header("Content-Type", "application/json")
.send()
.await
.context("getting transaction by hash")?
.json::<APITransaction>()
.context(format!("{} request failed", context_msg))?
.json::<T>()
.await
.context("reading transaction response")
.context(format!("Failed to deserialize {}", context_msg))
}
}
2 changes: 1 addition & 1 deletion crates/hyle-loadtest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ pub async fn send_proof_txs(url: String, proof_txs: Vec<Vec<u8>>) -> Result<()>
}

pub async fn send_massive_blob(url: String) -> Result<()> {
let ident = Identity("test.hydentity".to_string());
let ident = Identity::new("test.hydentity");

let mut data = vec![];

Expand Down
1 change: 1 addition & 0 deletions crates/hyle-model/src/node/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub enum Ticket {

#[derive(Debug, Serialize, Deserialize, Clone, Encode, Decode, PartialEq, Eq, Default)]
pub struct ConsensusProposalHash(pub String);
pub type BlockHash = ConsensusProposalHash;

#[cfg(feature = "sqlx")]
impl sqlx::Type<sqlx::Postgres> for ConsensusProposalHash {
Expand Down
7 changes: 2 additions & 5 deletions src/bin/hyled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ async fn send_proof(
proof: ProofData(proof),
})
.await?;
assert!(res.status().is_success());

println!("Proof sent successfully");
println!("Response: {}", res.text().await?);
println!("Response: {}", res);

Ok(())
}
Expand Down Expand Up @@ -98,10 +97,8 @@ async fn register_contracts(
})
.await?;

assert!(res.status().is_success());

println!("Contract registered");
println!("Response: {}", res.text().await?);
println!("Response: {}", res);

Ok(())
}
Expand Down
Loading
Loading