Skip to content

Commit

Permalink
Merge pull request #579 from nervosnetwork/support-indexer-rpc
Browse files Browse the repository at this point in the history
feat: addition of subcommands for CKB Indexer RPC
  • Loading branch information
eval-exec authored Feb 20, 2024
2 parents c9d814d + ef34122 commit 77e96e1
Show file tree
Hide file tree
Showing 6 changed files with 434 additions and 21 deletions.
38 changes: 30 additions & 8 deletions Cargo.lock

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

48 changes: 47 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ hash: 0x0384ebc55b7cb56e51044743e05fb83a4edb7173524339c35df4c71fcdb0854d
### Example: Get live cell (json output format)
```
ckb-cli rpc get_live_cell --tx-hash 0x4ec75b5a8de8d180853d5046760a99285c73283a5dc528f81d6ee056f5335172 --index 0 --output-format json
ckb-cli rpc get_live_cell --tx-hash 0x4ec75b5a8de8d180853d5046760a99285c73283a5dc528f81d6ee056f5335172 --index 0
```

**Response:**
Expand All @@ -90,3 +90,49 @@ ckb-cli rpc get_live_cell --tx-hash 0x4ec75b5a8de8d180853d5046760a99285c73283a5d
"status": "live"
}
```

### Example: Indexer get cells (yaml output format)

Prepare file searchkey.json as input parameters:

```json
{
"script": {
"code_hash": "0xbbad126377d45f90a8ee120da988a2d7332c78ba8fd679aab478a19d6c133494",
"hash_type": "data1",
"args": "0x"
},
"script_type": "type",
"script_search_mode": "prefix",
"filter": {
"output_data": "0xa58618a553",
"output_data_filter_mode": "partial"
},
"with_data": false
}
```

```
ckb-cli rpc get_transactions --json-path ./searchkey.json --order asc --limit 3
```
Response:

```yaml
last_cursor: 0xa0bbad126377d45f90a8ee120da988a2d7332c78ba8fd679aab478a19d6c13349402013368282f4cde04254a3a6a2027b33f7c974046a4d5cbd96bc47d7f058c18090000000000b29e04000000050000000000
objects:
- block_number: 10375179
io_index: 1
io_type: output
tx_hash: 0x551ec96717c336b74bbb2e56a1cb9c73e2a9d4b56321079b454cfc1c0e6036ac
tx_index: 7
- block_number: 11705844
io_index: 0
io_type: output
tx_hash: 0xd690aa336c0d05808e08a97ba2f3031b7691341df9002b305c2d27cb116e2705
tx_index: 5
- block_number: 11705860
io_index: 0
io_type: input
tx_hash: 0xa3282c23227992933eee0a07e5cbf52ca62006b98f2d113ebf579c5e59cf5a62
tx_index: 5
```
169 changes: 167 additions & 2 deletions src/subcommands/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::utils::arg_parser::{
FromStrParser, HexParser,
};
use crate::utils::rpc::{
BannedAddr, BlockEconomicState, BlockView, EpochView, HeaderView, HttpRpcClient,
parse_order, BannedAddr, BlockEconomicState, BlockView, EpochView, HeaderView, HttpRpcClient,
RawHttpRpcClient, RemoteNode, Timestamp, TransactionProof, TransactionWithStatus,
};

Expand Down Expand Up @@ -349,7 +349,82 @@ impl<'a> RpcSubCommand<'a> {
.validator(|input| HexParser.validate(input))
.about("Block assembler message (hex format)")
)
.about("[TEST ONLY] Generate an empty block")
.about("[TEST ONLY] Generate an empty block"),
// [`Indexer`]
App::new("get_indexer_tip").about("Returns the indexed tip"),
App::new("get_cells")
.arg(
Arg::with_name("json-path")
.long("json-path")
.takes_value(true)
.validator(|input| FilePathParser::new(true).validate(input))
.required(true)
.about("Indexer search key"))
.arg(
Arg::with_name("order")
.long("order")
.takes_value(true)
.possible_values(&["asc", "desc"])
.required(true)
.about("Indexer search order")
)
.arg(
Arg::with_name("limit")
.long("limit")
.takes_value(true)
.validator(|input| FromStrParser::<u64>::default().validate(input))
.required(true)
.about("Limit the number of results")
)
.arg(
Arg::with_name("after")
.long("after")
.takes_value(true)
.validator(|input| HexParser.validate(input))
.about("Pagination parameter")
)
.about("Returns the live cells collection by the lock or type script"),
App::new("get_transactions")
.arg(
Arg::with_name("json-path")
.long("json-path")
.takes_value(true)
.validator(|input| FilePathParser::new(true).validate(input))
.required(true)
.about("Indexer search key"))
.arg(
Arg::with_name("order")
.long("order")
.takes_value(true)
.possible_values(&["asc", "desc"])
.required(true)
.about("Indexer search order")
)
.arg(
Arg::with_name("limit")
.long("limit")
.takes_value(true)
.validator(|input| FromStrParser::<u64>::default().validate(input))
.required(true)
.about("Limit the number of results")
)
.arg(
Arg::with_name("after")
.long("after")
.takes_value(true)
.validator(|input| HexParser.validate(input))
.about("Pagination parameter")
)
.about("Returns the transactions collection by the lock or type script"),
App::new("get_cells_capacity")
.arg(
Arg::with_name("json-path")
.long("json-path")
.takes_value(true)
.validator(|input| FilePathParser::new(true).validate(input))
.required(true)
.about("Indexer search key"))
.about("Returns the live cells capacity by the lock or type script"),
])
}
}
Expand Down Expand Up @@ -1068,6 +1143,96 @@ impl<'a> CliSubCommand for RpcSubCommand<'a> {
.generate_block(script_opt, message_opt.map(JsonBytes::from_bytes))?;
Ok(Output::new_output(resp))
}
// [Indexer]
("get_indexer_tip", Some(m)) => {
let is_raw_data = is_raw_data || m.is_present("raw-data");
if is_raw_data {
let resp = self
.raw_rpc_client
.get_indexer_tip()
.map_err(|err| err.to_string())?;
Ok(Output::new_output(resp))
} else {
let resp = self.rpc_client.get_indexer_tip()?;
Ok(Output::new_output(resp))
}
}
("get_cells", Some(m)) => {
let json_path: PathBuf = FilePathParser::new(true)
.from_matches_opt(m, "json-path")?
.expect("json-path is required");
let content = fs::read_to_string(json_path).map_err(|err| err.to_string())?;
let search_key = serde_json::from_str(&content).map_err(|err| err.to_string())?;
let order_str = m.value_of("order").expect("order is required");
let order = parse_order(order_str)?;
let limit: u32 = FromStrParser::<u32>::default().from_matches(m, "limit")?;
let after_opt: Option<JsonBytes> = HexParser
.from_matches_opt::<Bytes>(m, "after")?
.map(JsonBytes::from_bytes);

let is_raw_data = is_raw_data || m.is_present("raw-data");
if is_raw_data {
let resp = self
.raw_rpc_client
.get_cells(search_key, order, limit.into(), after_opt)
.map_err(|err| err.to_string())?;
Ok(Output::new_output(resp))
} else {
let resp =
self.rpc_client
.get_cells(search_key, order, limit.into(), after_opt)?;
Ok(Output::new_output(resp))
}
}
("get_transactions", Some(m)) => {
let json_path: PathBuf = FilePathParser::new(true)
.from_matches_opt(m, "json-path")?
.expect("json-path is required");
let content = fs::read_to_string(json_path).map_err(|err| err.to_string())?;
let search_key = serde_json::from_str(&content).map_err(|err| err.to_string())?;
let order_str = m.value_of("order").expect("order is required");
let order = parse_order(order_str)?;
let limit: u32 = FromStrParser::<u32>::default().from_matches(m, "limit")?;
let after_opt: Option<JsonBytes> = HexParser
.from_matches_opt::<Bytes>(m, "after")?
.map(JsonBytes::from_bytes);

let is_raw_data = is_raw_data || m.is_present("raw-data");
if is_raw_data {
let resp = self
.raw_rpc_client
.get_transactions(search_key, order, limit.into(), after_opt)
.map_err(|err| err.to_string())?;
Ok(Output::new_output(resp))
} else {
let resp = self.rpc_client.get_transactions(
search_key,
order,
limit.into(),
after_opt,
)?;
Ok(Output::new_output(resp))
}
}
("get_cells_capacity", Some(m)) => {
let json_path: PathBuf = FilePathParser::new(true)
.from_matches_opt(m, "json-path")?
.expect("json-path is required");
let content = fs::read_to_string(json_path).map_err(|err| err.to_string())?;
let search_key = serde_json::from_str(&content).map_err(|err| err.to_string())?;

let is_raw_data = is_raw_data || m.is_present("raw-data");
if is_raw_data {
let resp = self
.raw_rpc_client
.get_cells_capacity(search_key)
.map_err(|err| err.to_string())?;
Ok(Output::new_output(resp))
} else {
let resp = self.rpc_client.get_cells_capacity(search_key)?;
Ok(Output::new_output(resp))
}
}
_ => Err(Self::subcommand().generate_usage()),
}
}
Expand Down
Loading

0 comments on commit 77e96e1

Please sign in to comment.