Skip to content

Commit

Permalink
feat: support async api
Browse files Browse the repository at this point in the history
  • Loading branch information
driftluo committed Dec 24, 2024
1 parent 8e6217d commit f484708
Show file tree
Hide file tree
Showing 28 changed files with 866 additions and 271 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ parking_lot = "0.12"
lru = "0.7.1"
dashmap = "5.4"
dyn-clone = "1.0"
async-trait = "0.1"

ckb-types = "0.119.0"
ckb-dao-utils = "0.119.0"
Expand All @@ -50,7 +51,6 @@ ckb-mock-tx-types = { version = "0.119.0" }
ckb-chain-spec = "0.119.0"

sparse-merkle-tree = "0.6.1"
lazy_static = "1.3.0"

[features]
default = ["default-tls"]
Expand Down
7 changes: 4 additions & 3 deletions deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ ignore = [
#{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" },
#"[email protected]", # you can also ignore yanked crate versions if you wish
#{ crate = "[email protected]", reason = "you can specify why you are ignoring the yanked crate"
"RUSTSEC-2024-0370" # proc-macro-error's maintainer seems to be unreachable, ignore this
"RUSTSEC-2024-0370", # proc-macro-error's maintainer seems to be unreachable, ignore this
"RUSTSEC-2024-0384", # instant is no longer maintained, ignore this
]
# If this is true, then cargo deny will use the git executable to fetch advisory database.
# If this is false, then it uses a built-in git library.
Expand All @@ -97,8 +98,8 @@ allow = [
"ISC",
"MIT",
"Unicode-DFS-2016",
"BSL-1.0", # xxhash-rust 0.8.10

"BSL-1.0", # xxhash-rust 0.8.10
"Unicode-3.0",
#"MIT",
#"Apache-2.0",
#"Apache-2.0 WITH LLVM-exception",
Expand Down
19 changes: 11 additions & 8 deletions examples/script_unlocker_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ use std::collections::HashMap;
/// [CapacityDiff]: https://github.com/doitian/ckb-sdk-examples-capacity-diff
struct CapacityDiffUnlocker {}

#[async_trait::async_trait]
impl ScriptUnlocker for CapacityDiffUnlocker {
// This works for any args
fn match_args(&self, _args: &[u8]) -> bool {
true
}

fn unlock(
async fn unlock_async(
&self,
tx: &TransactionView,
script_group: &ScriptGroup,
Expand All @@ -45,12 +46,14 @@ impl ScriptUnlocker for CapacityDiffUnlocker {

let mut total = 0i64;
for i in &script_group.input_indices {
let cell = tx_dep_provider.get_cell(
&tx.inputs()
.get(*i)
.ok_or_else(|| other_unlock_error("input index out of bound"))?
.previous_output(),
)?;
let cell = tx_dep_provider
.get_cell_async(
&tx.inputs()
.get(*i)
.ok_or_else(|| other_unlock_error("input index out of bound"))?
.previous_output(),
)
.await?;
let capacity: u64 = cell.capacity().unpack();
total -= capacity as i64;
}
Expand All @@ -71,7 +74,7 @@ impl ScriptUnlocker for CapacityDiffUnlocker {

// This is called before balancer. It's responsible to fill witness for inputs added manually
// by users.
fn fill_placeholder_witness(
async fn fill_placeholder_witness_async(
&self,
tx: &TransactionView,
script_group: &ScriptGroup,
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.75.0
1.81.0
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub mod test_util;
#[cfg(test)]
mod tests;

pub use rpc::{CkbRpcClient, IndexerRpcClient, RpcError};
pub use rpc::{CkbRpcAsyncClient, CkbRpcClient, IndexerRpcAsyncClient, IndexerRpcClient, RpcError};
pub use types::{
Address, AddressPayload, AddressType, CodeHashIndex, HumanCapacity, NetworkInfo, NetworkType,
OldAddress, OldAddressFormat, ScriptGroup, ScriptGroupType, ScriptId, Since, SinceType,
Expand Down
205 changes: 204 additions & 1 deletion src/rpc/ckb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ crate::jsonrpc!(pub struct CkbRpcClient {
pub fn calculate_dao_maximum_withdraw(&self, out_point: OutPoint, kind: DaoWithdrawingCalculationKind) -> Capacity;
});

crate::jsonrpc_async!(pub struct CkbRpcAyncClient {
crate::jsonrpc_async!(pub struct CkbRpcAsyncClient {
// Chain
pub fn get_block(&self, hash: H256) -> Option<BlockView>;
pub fn get_block_by_number(&self, number: BlockNumber) -> Option<BlockView>;
Expand Down Expand Up @@ -212,6 +212,15 @@ fn transform_cycles(cycles: Option<Vec<ckb_jsonrpc_types::Cycle>>) -> Vec<Cycle>
.unwrap_or_default()
}

impl From<&CkbRpcClient> for CkbRpcAsyncClient {
fn from(value: &CkbRpcClient) -> Self {
Self {
client: value.client.clone(),
id: 0.into(),
}
}
}

impl CkbRpcClient {
pub fn get_packed_block(&self, hash: H256) -> Result<Option<JsonBytes>, crate::RpcError> {
self.post("get_block", (hash, Some(Uint32::from(0u32))))
Expand Down Expand Up @@ -386,3 +395,197 @@ impl CkbRpcClient {
self.post::<_, Option<JsonBytes>>("get_fork_block", (block_hash, Some(Uint32::from(0u32))))
}
}

impl CkbRpcAsyncClient {
pub async fn get_packed_block(&self, hash: H256) -> Result<Option<JsonBytes>, crate::RpcError> {
self.post("get_block", (hash, Some(Uint32::from(0u32))))
.await
}

// turn block response into BlockView and cycle vec
fn transform_block_view_with_cycle(
opt_resp: Option<BlockResponse>,
) -> Result<Option<(BlockView, Vec<Cycle>)>, crate::rpc::RpcError> {
opt_resp
.map(|resp| match resp {
BlockResponse::Regular(block_view) => Ok((block_view.get_value()?, vec![])),
BlockResponse::WithCycles(block_cycles) => {
let cycles = transform_cycles(block_cycles.cycles);
Ok((block_cycles.block.get_value()?, cycles))
}
})
.transpose()
}
/// Same as get_block except with parameter with_cycles and return BlockResponse
pub async fn get_block_with_cycles(
&self,
hash: H256,
) -> Result<Option<(BlockView, Vec<Cycle>)>, crate::rpc::RpcError> {
let res = self
.post::<_, Option<BlockResponse>>("get_block", (hash, None::<u32>, true))
.await?;
Self::transform_block_view_with_cycle(res)
}

// turn BlockResponse to JsonBytes and Cycle tuple
fn blockresponse2bytes(
opt_resp: Option<BlockResponse>,
) -> Result<Option<(JsonBytes, Vec<Cycle>)>, crate::rpc::RpcError> {
opt_resp
.map(|resp| match resp {
BlockResponse::Regular(block_view) => Ok((block_view.get_json_bytes()?, vec![])),
BlockResponse::WithCycles(block_cycles) => {
let cycles = transform_cycles(block_cycles.cycles);
Ok((block_cycles.block.get_json_bytes()?, cycles))
}
})
.transpose()
}

pub async fn get_packed_block_with_cycles(
&self,
hash: H256,
) -> Result<Option<(JsonBytes, Vec<Cycle>)>, crate::rpc::RpcError> {
let res = self
.post::<_, Option<BlockResponse>>("get_block", (hash, Some(Uint32::from(0u32)), true))
.await?;
Self::blockresponse2bytes(res)
}

/// Same as get_block_by_number except with parameter with_cycles and return BlockResponse
pub async fn get_packed_block_by_number(
&self,
number: BlockNumber,
) -> Result<Option<JsonBytes>, crate::rpc::RpcError> {
self.post("get_block_by_number", (number, Some(Uint32::from(0u32))))
.await
}

pub async fn get_block_by_number_with_cycles(
&self,
number: BlockNumber,
) -> Result<Option<(BlockView, Vec<Cycle>)>, crate::rpc::RpcError> {
let res = self
.post::<_, Option<BlockResponse>>("get_block_by_number", (number, None::<u32>, true))
.await?;
Self::transform_block_view_with_cycle(res)
}

pub async fn get_packed_block_by_number_with_cycles(
&self,
number: BlockNumber,
) -> Result<Option<(JsonBytes, Vec<Cycle>)>, crate::rpc::RpcError> {
let res = self
.post::<_, Option<BlockResponse>>(
"get_block_by_number",
(number, Some(Uint32::from(0u32)), true),
)
.await?;
Self::blockresponse2bytes(res)
}

pub async fn get_packed_header(
&self,
hash: H256,
) -> Result<Option<JsonBytes>, crate::rpc::RpcError> {
self.post::<_, Option<JsonBytes>>("get_header", (hash, Some(Uint32::from(0u32))))
.await
}

pub async fn get_packed_header_by_number(
&self,
number: BlockNumber,
) -> Result<Option<JsonBytes>, crate::rpc::RpcError> {
self.post::<_, Option<JsonBytes>>(
"get_header_by_number",
(number, Some(Uint32::from(0u32))),
)
.await
}

pub async fn get_live_cell_with_include_tx_pool(
&self,
out_point: OutPoint,
with_data: bool,
include_tx_pool: bool,
) -> Result<CellWithStatus, crate::rpc::RpcError> {
self.post::<_, CellWithStatus>(
"get_live_cell",
(out_point, with_data, Some(include_tx_pool)),
)
.await
}

// get transaction with only_committed=true
pub async fn get_only_committed_transaction(
&self,
hash: H256,
) -> Result<TransactionWithStatusResponse, crate::rpc::RpcError> {
self.post::<_, TransactionWithStatusResponse>(
"get_transaction",
(hash, Some(Uint32::from(2u32)), true),
)
.await
}

// get transaction with verbosity=0
pub async fn get_packed_transaction(
&self,
hash: H256,
) -> Result<TransactionWithStatusResponse, crate::rpc::RpcError> {
self.post::<_, TransactionWithStatusResponse>(
"get_transaction",
(hash, Some(Uint32::from(0u32))),
)
.await
}

// get transaction with verbosity=0 and only_committed=true
pub async fn get_only_committed_packed_transaction(
&self,
hash: H256,
) -> Result<TransactionWithStatusResponse, crate::rpc::RpcError> {
self.post::<_, TransactionWithStatusResponse>(
"get_transaction",
(hash, Some(Uint32::from(0u32)), true),
)
.await
}

// get transaction with verbosity=1, so the result transaction field is None
pub async fn get_transaction_status(
&self,
hash: H256,
) -> Result<TransactionWithStatusResponse, crate::rpc::RpcError> {
self.post::<_, TransactionWithStatusResponse>(
"get_transaction",
(hash, Some(Uint32::from(1u32))),
)
.await
}

// get transaction with verbosity=1 and only_committed=true, so the result transaction field is None
pub async fn get_only_committed_transaction_status(
&self,
hash: H256,
) -> Result<TransactionWithStatusResponse, crate::rpc::RpcError> {
self.post::<_, TransactionWithStatusResponse>(
"get_transaction",
(hash, Some(Uint32::from(1u32)), true),
)
.await
}

pub async fn get_packed_tip_header(&self) -> Result<JsonBytes, crate::rpc::RpcError> {
self.post::<_, JsonBytes>("get_tip_header", (Some(Uint32::from(0u32)),))
.await
}

pub async fn get_packed_fork_block(
&self,
block_hash: H256,
) -> Result<Option<JsonBytes>, crate::rpc::RpcError> {
self.post::<_, Option<JsonBytes>>("get_fork_block", (block_hash, Some(Uint32::from(0u32))))
.await
}
}
9 changes: 9 additions & 0 deletions src/rpc/ckb_indexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,12 @@ crate::jsonrpc_async!(pub struct IndexerRpcAsyncClient {
pub fn get_transactions(&self, search_key: SearchKey, order: Order, limit: Uint32, after: Option<JsonBytes>) -> Pagination<Tx>;
pub fn get_cells_capacity(&self, search_key: SearchKey) -> Option<CellsCapacity>;
});

impl From<&IndexerRpcClient> for IndexerRpcAsyncClient {
fn from(value: &IndexerRpcClient) -> Self {
Self {
client: value.client.clone(),
id: 0.into(),
}
}
}
9 changes: 9 additions & 0 deletions src/rpc/ckb_light_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,12 @@ crate::jsonrpc_async!(pub struct LightClientRpcAsyncClient {
pub fn get_peers(&self) -> Vec<RemoteNode>;
pub fn local_node_info(&self) -> LocalNode;
});

impl From<&LightClientRpcClient> for LightClientRpcAsyncClient {
fn from(value: &LightClientRpcClient) -> Self {
Self {
client: value.client.clone(),
id: 0.into(),
}
}
}
Loading

0 comments on commit f484708

Please sign in to comment.