1use crate::codec::*;
12
13pub const TAG_CHAIN_HEAD_FOLLOW_START: u8 = 76;
18pub const TAG_CHAIN_HEAD_FOLLOW_STOP: u8 = 77;
19pub const TAG_CHAIN_HEAD_FOLLOW_INTERRUPT: u8 = 78;
20pub const TAG_CHAIN_HEAD_FOLLOW_RECEIVE: u8 = 79;
21
22pub const TAG_CHAIN_HEAD_HEADER_REQ: u8 = 80;
23pub const TAG_CHAIN_HEAD_HEADER_RESP: u8 = 81;
24
25pub const TAG_CHAIN_HEAD_BODY_REQ: u8 = 82;
26pub const TAG_CHAIN_HEAD_BODY_RESP: u8 = 83;
27
28pub const TAG_CHAIN_HEAD_STORAGE_REQ: u8 = 84;
29pub const TAG_CHAIN_HEAD_STORAGE_RESP: u8 = 85;
30
31pub const TAG_CHAIN_HEAD_CALL_REQ: u8 = 86;
32pub const TAG_CHAIN_HEAD_CALL_RESP: u8 = 87;
33
34pub const TAG_CHAIN_HEAD_UNPIN_REQ: u8 = 88;
35pub const TAG_CHAIN_HEAD_UNPIN_RESP: u8 = 89;
36
37pub const TAG_CHAIN_HEAD_CONTINUE_REQ: u8 = 90;
38pub const TAG_CHAIN_HEAD_CONTINUE_RESP: u8 = 91;
39
40pub const TAG_CHAIN_HEAD_STOP_OP_REQ: u8 = 92;
41pub const TAG_CHAIN_HEAD_STOP_OP_RESP: u8 = 93;
42
43pub const TAG_CHAIN_SPEC_GENESIS_HASH_REQ: u8 = 94;
44pub const TAG_CHAIN_SPEC_GENESIS_HASH_RESP: u8 = 95;
45
46pub const TAG_CHAIN_SPEC_CHAIN_NAME_REQ: u8 = 96;
47pub const TAG_CHAIN_SPEC_CHAIN_NAME_RESP: u8 = 97;
48
49pub const TAG_CHAIN_SPEC_PROPERTIES_REQ: u8 = 98;
50pub const TAG_CHAIN_SPEC_PROPERTIES_RESP: u8 = 99;
51
52pub const TAG_CHAIN_TX_BROADCAST_REQ: u8 = 100;
53pub const TAG_CHAIN_TX_BROADCAST_RESP: u8 = 101;
54
55pub const TAG_CHAIN_TX_STOP_REQ: u8 = 102;
56pub const TAG_CHAIN_TX_STOP_RESP: u8 = 103;
57
58#[derive(Debug, Clone)]
64pub enum RuntimeInfo {
65 Valid(RuntimeSpec),
67 Invalid { error: String },
69}
70
71#[derive(Debug, Clone)]
73pub struct RuntimeSpec {
74 pub spec_name: String,
75 pub impl_name: String,
76 pub spec_version: u32,
77 pub impl_version: u32,
78 pub transaction_version: Option<u32>,
80 pub apis: Vec<(String, u32)>,
82}
83
84#[derive(Debug, Clone)]
86pub struct StorageResultItem {
87 pub key: Vec<u8>,
88 pub value: Option<Vec<u8>>,
90 pub hash: Option<Vec<u8>>,
92 pub closest_descendant_merkle_value: Option<Vec<u8>>,
94}
95
96#[derive(Debug, Clone)]
98pub enum ChainHeadEvent {
99 Initialized {
101 finalized_block_hashes: Vec<Vec<u8>>,
102 finalized_block_runtime: Option<RuntimeInfo>,
103 },
104 NewBlock {
106 block_hash: Vec<u8>,
107 parent_block_hash: Vec<u8>,
108 new_runtime: Option<RuntimeInfo>,
109 },
110 BestBlockChanged { best_block_hash: Vec<u8> },
112 Finalized {
114 finalized_block_hashes: Vec<Vec<u8>>,
115 pruned_block_hashes: Vec<Vec<u8>>,
116 },
117 OperationBodyDone {
119 operation_id: String,
120 value: Vec<Vec<u8>>,
121 },
122 OperationCallDone {
124 operation_id: String,
125 output: Vec<u8>,
126 },
127 OperationStorageItems {
129 operation_id: String,
130 items: Vec<StorageResultItem>,
131 },
132 OperationStorageDone { operation_id: String },
134 OperationWaitingForContinue { operation_id: String },
136 OperationInaccessible { operation_id: String },
138 OperationError { operation_id: String, error: String },
140 Stop,
142}
143
144pub fn hex_to_bytes(hex: &str) -> Vec<u8> {
152 let s = hex.strip_prefix("0x").unwrap_or(hex);
153 if s.is_empty() {
154 return Vec::new();
155 }
156 (0..s.len() / 2)
158 .filter_map(|i| u8::from_str_radix(&s[i * 2..i * 2 + 2], 16).ok())
159 .collect()
160}
161
162pub fn bytes_to_hex(bytes: &[u8]) -> String {
164 let mut s = String::with_capacity(2 + bytes.len() * 2);
165 s.push_str("0x");
166 for b in bytes {
167 s.push(char::from_digit((b >> 4) as u32, 16).unwrap_or('0'));
168 s.push(char::from_digit((b & 0xf) as u32, 16).unwrap_or('0'));
169 }
170 s
171}
172
173fn json_hex(v: &serde_json::Value) -> Option<Vec<u8>> {
179 Some(hex_to_bytes(v.as_str()?))
180}
181
182fn parse_runtime_spec(obj: &serde_json::Value) -> Option<RuntimeSpec> {
184 let spec_name = obj.get("specName")?.as_str()?.to_string();
185 let impl_name = obj.get("implName")?.as_str()?.to_string();
186 let spec_version = obj.get("specVersion")?.as_u64()? as u32;
187 let impl_version = obj.get("implVersion")?.as_u64()? as u32;
188 let transaction_version = obj
189 .get("transactionVersion")
190 .and_then(|v| v.as_u64())
191 .map(|v| v as u32);
192
193 let apis = obj
195 .get("apis")
196 .and_then(|a| a.as_array())
197 .map(|arr| {
198 arr.iter()
199 .filter_map(|item| {
200 let pair = item.as_array()?;
201 if pair.len() < 2 {
202 return None;
203 }
204 let name = pair[0].as_str()?.to_string();
205 let version = pair[1].as_u64()? as u32;
206 Some((name, version))
207 })
208 .collect()
209 })
210 .unwrap_or_default();
211
212 Some(RuntimeSpec {
213 spec_name,
214 impl_name,
215 spec_version,
216 impl_version,
217 transaction_version,
218 apis,
219 })
220}
221
222fn parse_runtime_info(v: &serde_json::Value) -> Option<RuntimeInfo> {
224 if v.is_null() {
225 return None;
226 }
227 let ty = v.get("type")?.as_str()?;
228 match ty {
229 "valid" => {
230 let spec = parse_runtime_spec(v.get("spec")?)?;
231 Some(RuntimeInfo::Valid(spec))
232 }
233 "invalid" => {
234 let error = v
235 .get("error")
236 .and_then(|e| e.as_str())
237 .unwrap_or("")
238 .to_string();
239 Some(RuntimeInfo::Invalid { error })
240 }
241 _ => None,
242 }
243}
244
245fn parse_hex_array(arr: &serde_json::Value) -> Vec<Vec<u8>> {
247 arr.as_array()
248 .map(|a| a.iter().filter_map(json_hex).collect())
249 .unwrap_or_default()
250}
251
252fn parse_storage_item(obj: &serde_json::Value) -> Option<StorageResultItem> {
254 let key = json_hex(obj.get("key")?)?;
255
256 let value = obj
258 .get("value")
259 .and_then(|v| if v.is_null() { None } else { json_hex(v) });
260 let hash = obj
261 .get("hash")
262 .and_then(|v| if v.is_null() { None } else { json_hex(v) });
263 let closest_descendant_merkle_value = obj.get("closestDescendantMerkleValue").and_then(|v| {
264 if v.is_null() {
265 None
266 } else {
267 json_hex(v)
268 }
269 });
270
271 Some(StorageResultItem {
272 key,
273 value,
274 hash,
275 closest_descendant_merkle_value,
276 })
277}
278
279pub fn parse_chain_head_json_rpc(json_rpc: &str) -> Option<ChainHeadEvent> {
299 let root: serde_json::Value = serde_json::from_str(json_rpc).ok()?;
300
301 if root.get("method")?.as_str()? != "chainHead_v1_followEvent" {
303 return None;
304 }
305
306 let result = root.get("params")?.get("result")?;
307 let event = result.get("event")?.as_str()?;
308
309 match event {
310 "initialized" => {
311 let finalized_block_hashes = parse_hex_array(
312 result
313 .get("finalizedBlockHashes")
314 .unwrap_or(&serde_json::Value::Null),
315 );
316 let finalized_block_runtime = result
317 .get("finalizedBlockRuntime")
318 .and_then(parse_runtime_info);
319 Some(ChainHeadEvent::Initialized {
320 finalized_block_hashes,
321 finalized_block_runtime,
322 })
323 }
324
325 "newBlock" => {
326 let block_hash = json_hex(result.get("blockHash")?)?;
327 let parent_block_hash = json_hex(result.get("parentBlockHash")?)?;
328 let new_runtime = result.get("newRuntime").and_then(parse_runtime_info);
329 Some(ChainHeadEvent::NewBlock {
330 block_hash,
331 parent_block_hash,
332 new_runtime,
333 })
334 }
335
336 "bestBlockChanged" => {
337 let best_block_hash = json_hex(result.get("bestBlockHash")?)?;
338 Some(ChainHeadEvent::BestBlockChanged { best_block_hash })
339 }
340
341 "finalized" => {
342 let finalized_block_hashes = parse_hex_array(
343 result
344 .get("finalizedBlockHashes")
345 .unwrap_or(&serde_json::Value::Null),
346 );
347 let pruned_block_hashes = parse_hex_array(
348 result
349 .get("prunedBlockHashes")
350 .unwrap_or(&serde_json::Value::Null),
351 );
352 Some(ChainHeadEvent::Finalized {
353 finalized_block_hashes,
354 pruned_block_hashes,
355 })
356 }
357
358 "operationBodyDone" => {
359 let operation_id = result.get("operationId")?.as_str()?.to_string();
360 let value = parse_hex_array(result.get("value").unwrap_or(&serde_json::Value::Null));
361 Some(ChainHeadEvent::OperationBodyDone {
362 operation_id,
363 value,
364 })
365 }
366
367 "operationCallDone" => {
368 let operation_id = result.get("operationId")?.as_str()?.to_string();
369 let output = json_hex(result.get("output")?)?;
370 Some(ChainHeadEvent::OperationCallDone {
371 operation_id,
372 output,
373 })
374 }
375
376 "operationStorageItems" => {
377 let operation_id = result.get("operationId")?.as_str()?.to_string();
378 let items = result
379 .get("items")
380 .and_then(|a| a.as_array())
381 .map(|arr| arr.iter().filter_map(parse_storage_item).collect())
382 .unwrap_or_default();
383 Some(ChainHeadEvent::OperationStorageItems {
384 operation_id,
385 items,
386 })
387 }
388
389 "operationStorageDone" => {
390 let operation_id = result.get("operationId")?.as_str()?.to_string();
391 Some(ChainHeadEvent::OperationStorageDone { operation_id })
392 }
393
394 "operationWaitingForContinue" => {
395 let operation_id = result.get("operationId")?.as_str()?.to_string();
396 Some(ChainHeadEvent::OperationWaitingForContinue { operation_id })
397 }
398
399 "operationInaccessible" => {
400 let operation_id = result.get("operationId")?.as_str()?.to_string();
401 Some(ChainHeadEvent::OperationInaccessible { operation_id })
402 }
403
404 "operationError" => {
405 let operation_id = result.get("operationId")?.as_str()?.to_string();
406 let error = result
407 .get("error")
408 .and_then(|e| e.as_str())
409 .unwrap_or("")
410 .to_string();
411 Some(ChainHeadEvent::OperationError {
412 operation_id,
413 error,
414 })
415 }
416
417 "stop" => Some(ChainHeadEvent::Stop),
418
419 _ => None,
420 }
421}
422
423fn encode_runtime_info_option(buf: &mut Vec<u8>, rt: &Option<RuntimeInfo>) {
432 match rt {
433 None => encode_option_none(buf),
434 Some(info) => {
435 encode_option_some(buf);
436 encode_runtime_info(buf, info);
437 }
438 }
439}
440
441fn encode_runtime_info(buf: &mut Vec<u8>, info: &RuntimeInfo) {
445 match info {
446 RuntimeInfo::Valid(spec) => {
447 encode_tag(buf, 0); encode_string(buf, &spec.spec_name);
449 encode_string(buf, &spec.impl_name);
450 buf.extend_from_slice(&spec.spec_version.to_le_bytes());
451 buf.extend_from_slice(&spec.impl_version.to_le_bytes());
452 match spec.transaction_version {
454 None => encode_option_none(buf),
455 Some(v) => {
456 encode_option_some(buf);
457 buf.extend_from_slice(&v.to_le_bytes());
458 }
459 }
460 encode_vector_len(buf, spec.apis.len() as u32);
462 for (name, version) in &spec.apis {
463 encode_string(buf, name);
464 buf.extend_from_slice(&version.to_le_bytes());
465 }
466 }
467 RuntimeInfo::Invalid { error } => {
468 encode_tag(buf, 1); encode_string(buf, error);
470 }
471 }
472}
473
474fn encode_event_payload(buf: &mut Vec<u8>, event: &ChainHeadEvent) {
476 match event {
477 ChainHeadEvent::Initialized {
478 finalized_block_hashes,
479 finalized_block_runtime,
480 } => {
481 encode_tag(buf, 0);
482 encode_vector_len(buf, finalized_block_hashes.len() as u32);
483 for hash in finalized_block_hashes {
484 encode_var_bytes(buf, hash);
485 }
486 encode_runtime_info_option(buf, finalized_block_runtime);
487 }
488
489 ChainHeadEvent::NewBlock {
490 block_hash,
491 parent_block_hash,
492 new_runtime,
493 } => {
494 encode_tag(buf, 1);
495 encode_var_bytes(buf, block_hash);
496 encode_var_bytes(buf, parent_block_hash);
497 encode_runtime_info_option(buf, new_runtime);
498 }
499
500 ChainHeadEvent::BestBlockChanged { best_block_hash } => {
501 encode_tag(buf, 2);
502 encode_var_bytes(buf, best_block_hash);
503 }
504
505 ChainHeadEvent::Finalized {
506 finalized_block_hashes,
507 pruned_block_hashes,
508 } => {
509 encode_tag(buf, 3);
510 encode_vector_len(buf, finalized_block_hashes.len() as u32);
511 for hash in finalized_block_hashes {
512 encode_var_bytes(buf, hash);
513 }
514 encode_vector_len(buf, pruned_block_hashes.len() as u32);
515 for hash in pruned_block_hashes {
516 encode_var_bytes(buf, hash);
517 }
518 }
519
520 ChainHeadEvent::OperationBodyDone {
521 operation_id,
522 value,
523 } => {
524 encode_tag(buf, 4);
525 encode_string(buf, operation_id);
526 encode_vector_len(buf, value.len() as u32);
527 for item in value {
528 encode_var_bytes(buf, item);
529 }
530 }
531
532 ChainHeadEvent::OperationCallDone {
533 operation_id,
534 output,
535 } => {
536 encode_tag(buf, 5);
537 encode_string(buf, operation_id);
538 encode_var_bytes(buf, output);
539 }
540
541 ChainHeadEvent::OperationStorageItems {
542 operation_id,
543 items,
544 } => {
545 encode_tag(buf, 6);
546 encode_string(buf, operation_id);
547 encode_vector_len(buf, items.len() as u32);
548 for item in items {
549 encode_var_bytes(buf, &item.key);
550 match &item.value {
552 None => encode_option_none(buf),
553 Some(v) => {
554 encode_option_some(buf);
555 encode_var_bytes(buf, v);
556 }
557 }
558 match &item.hash {
560 None => encode_option_none(buf),
561 Some(h) => {
562 encode_option_some(buf);
563 encode_var_bytes(buf, h);
564 }
565 }
566 match &item.closest_descendant_merkle_value {
568 None => encode_option_none(buf),
569 Some(v) => {
570 encode_option_some(buf);
571 encode_var_bytes(buf, v);
572 }
573 }
574 }
575 }
576
577 ChainHeadEvent::OperationStorageDone { operation_id } => {
578 encode_tag(buf, 7);
579 encode_string(buf, operation_id);
580 }
581
582 ChainHeadEvent::OperationWaitingForContinue { operation_id } => {
583 encode_tag(buf, 8);
584 encode_string(buf, operation_id);
585 }
586
587 ChainHeadEvent::OperationInaccessible { operation_id } => {
588 encode_tag(buf, 9);
589 encode_string(buf, operation_id);
590 }
591
592 ChainHeadEvent::OperationError {
593 operation_id,
594 error,
595 } => {
596 encode_tag(buf, 10);
597 encode_string(buf, operation_id);
598 encode_string(buf, error);
599 }
600
601 ChainHeadEvent::Stop => {
602 encode_tag(buf, 11);
603 }
605 }
606}
607
608fn encode_envelope(buf: &mut Vec<u8>, request_id: &str, response_tag: u8) {
610 buf.push(crate::protocol::PROTOCOL_DISCRIMINATOR);
611 encode_string(buf, request_id);
612 encode_tag(buf, response_tag);
613 encode_tag(buf, 0); }
615
616fn encode_generic_error(buf: &mut Vec<u8>, reason: &str) {
620 encode_result_err(buf);
621 encode_tag(buf, 0); encode_string(buf, reason);
623}
624
625pub fn encode_chain_head_event(request_id: &str, event: &ChainHeadEvent) -> Vec<u8> {
633 let mut buf = Vec::with_capacity(128);
634 encode_envelope(&mut buf, request_id, TAG_CHAIN_HEAD_FOLLOW_RECEIVE);
635 encode_event_payload(&mut buf, event);
636 buf
637}
638
639pub fn encode_chain_response_void(
643 request_id: &str,
644 response_tag: u8,
645 error: Option<&str>,
646) -> Vec<u8> {
647 let mut buf = Vec::with_capacity(32);
648 encode_envelope(&mut buf, request_id, response_tag);
649 match error {
650 None => encode_result_ok_void(&mut buf),
651 Some(reason) => encode_generic_error(&mut buf, reason),
652 }
653 buf
654}
655
656pub fn encode_chain_response_nullable_hex(
660 request_id: &str,
661 response_tag: u8,
662 result: Result<Option<&[u8]>, &str>,
663) -> Vec<u8> {
664 let mut buf = Vec::with_capacity(64);
665 encode_envelope(&mut buf, request_id, response_tag);
666 match result {
667 Ok(maybe_bytes) => {
668 encode_result_ok(&mut buf);
669 match maybe_bytes {
670 None => encode_option_none(&mut buf),
671 Some(bytes) => {
672 encode_option_some(&mut buf);
673 encode_var_bytes(&mut buf, bytes);
674 }
675 }
676 }
677 Err(reason) => encode_generic_error(&mut buf, reason),
678 }
679 buf
680}
681
682pub fn encode_chain_response_operation_started(
689 request_id: &str,
690 response_tag: u8,
691 result: Result<Option<&str>, &str>,
692) -> Vec<u8> {
693 let mut buf = Vec::with_capacity(64);
694 encode_envelope(&mut buf, request_id, response_tag);
695 match result {
696 Ok(Some(op_id)) => {
697 encode_result_ok(&mut buf);
698 encode_tag(&mut buf, 0); encode_string(&mut buf, op_id);
700 }
701 Ok(None) => {
702 encode_result_ok(&mut buf);
703 encode_tag(&mut buf, 1); }
705 Err(reason) => encode_generic_error(&mut buf, reason),
706 }
707 buf
708}
709
710pub fn encode_chain_response_hex(
714 request_id: &str,
715 response_tag: u8,
716 result: Result<&[u8], &str>,
717) -> Vec<u8> {
718 let mut buf = Vec::with_capacity(64);
719 encode_envelope(&mut buf, request_id, response_tag);
720 match result {
721 Ok(bytes) => {
722 encode_result_ok(&mut buf);
723 encode_var_bytes(&mut buf, bytes);
724 }
725 Err(reason) => encode_generic_error(&mut buf, reason),
726 }
727 buf
728}
729
730pub fn encode_chain_response_string(
734 request_id: &str,
735 response_tag: u8,
736 result: Result<&str, &str>,
737) -> Vec<u8> {
738 let mut buf = Vec::with_capacity(64);
739 encode_envelope(&mut buf, request_id, response_tag);
740 match result {
741 Ok(s) => {
742 encode_result_ok(&mut buf);
743 encode_string(&mut buf, s);
744 }
745 Err(reason) => encode_generic_error(&mut buf, reason),
746 }
747 buf
748}
749
750pub fn encode_chain_response_nullable_string(
754 request_id: &str,
755 response_tag: u8,
756 result: Result<Option<&str>, &str>,
757) -> Vec<u8> {
758 let mut buf = Vec::with_capacity(64);
759 encode_envelope(&mut buf, request_id, response_tag);
760 match result {
761 Ok(maybe_str) => {
762 encode_result_ok(&mut buf);
763 match maybe_str {
764 None => encode_option_none(&mut buf),
765 Some(s) => {
766 encode_option_some(&mut buf);
767 encode_string(&mut buf, s);
768 }
769 }
770 }
771 Err(reason) => encode_generic_error(&mut buf, reason),
772 }
773 buf
774}
775
776fn encode_chain_error_for_request(request_id: &str, request_tag: u8, reason: &str) -> Vec<u8> {
777 match request_tag {
778 TAG_CHAIN_HEAD_HEADER_REQ => {
779 encode_chain_response_nullable_hex(request_id, TAG_CHAIN_HEAD_HEADER_RESP, Err(reason))
780 }
781 TAG_CHAIN_HEAD_BODY_REQ => encode_chain_response_operation_started(
782 request_id,
783 TAG_CHAIN_HEAD_BODY_RESP,
784 Err(reason),
785 ),
786 TAG_CHAIN_HEAD_STORAGE_REQ => encode_chain_response_operation_started(
787 request_id,
788 TAG_CHAIN_HEAD_STORAGE_RESP,
789 Err(reason),
790 ),
791 TAG_CHAIN_HEAD_CALL_REQ => encode_chain_response_operation_started(
792 request_id,
793 TAG_CHAIN_HEAD_CALL_RESP,
794 Err(reason),
795 ),
796 TAG_CHAIN_HEAD_UNPIN_REQ => {
797 encode_chain_response_void(request_id, TAG_CHAIN_HEAD_UNPIN_RESP, Some(reason))
798 }
799 TAG_CHAIN_HEAD_CONTINUE_REQ => {
800 encode_chain_response_void(request_id, TAG_CHAIN_HEAD_CONTINUE_RESP, Some(reason))
801 }
802 TAG_CHAIN_HEAD_STOP_OP_REQ => {
803 encode_chain_response_void(request_id, TAG_CHAIN_HEAD_STOP_OP_RESP, Some(reason))
804 }
805 TAG_CHAIN_SPEC_GENESIS_HASH_REQ => {
806 encode_chain_response_hex(request_id, TAG_CHAIN_SPEC_GENESIS_HASH_RESP, Err(reason))
807 }
808 TAG_CHAIN_SPEC_CHAIN_NAME_REQ => {
809 encode_chain_response_string(request_id, TAG_CHAIN_SPEC_CHAIN_NAME_RESP, Err(reason))
810 }
811 TAG_CHAIN_SPEC_PROPERTIES_REQ => {
812 encode_chain_response_string(request_id, TAG_CHAIN_SPEC_PROPERTIES_RESP, Err(reason))
813 }
814 TAG_CHAIN_TX_BROADCAST_REQ => encode_chain_response_nullable_string(
815 request_id,
816 TAG_CHAIN_TX_BROADCAST_RESP,
817 Err(reason),
818 ),
819 TAG_CHAIN_TX_STOP_REQ => {
820 encode_chain_response_void(request_id, TAG_CHAIN_TX_STOP_RESP, Some(reason))
821 }
822 _ => crate::protocol::encode_jsonrpc_send_error(request_id),
823 }
824}
825
826pub fn encode_chain_follow_json_event(request_id: &str, json_rpc: &str) -> Option<Vec<u8>> {
828 parse_chain_head_json_rpc(json_rpc).map(|event| encode_chain_head_event(request_id, &event))
829}
830
831pub fn encode_chain_follow_stop(request_id: &str) -> Vec<u8> {
833 encode_chain_head_event(request_id, &ChainHeadEvent::Stop)
834}
835
836pub fn encode_chain_rpc_error(request_id: &str, request_tag: u8, reason: &str) -> Vec<u8> {
838 encode_chain_error_for_request(request_id, request_tag, reason)
839}
840
841pub fn encode_chain_rpc_json_response(
844 request_id: &str,
845 request_tag: u8,
846 json_rpc: &str,
847) -> Vec<u8> {
848 let root: serde_json::Value = match serde_json::from_str(json_rpc) {
849 Ok(value) => value,
850 Err(_) => {
851 return encode_chain_error_for_request(
852 request_id,
853 request_tag,
854 "invalid json-rpc response",
855 )
856 }
857 };
858
859 if let Some(reason) = root
860 .get("error")
861 .and_then(|error| error.get("message"))
862 .and_then(|message| message.as_str())
863 {
864 return encode_chain_error_for_request(request_id, request_tag, reason);
865 }
866
867 let Some(result) = root.get("result") else {
868 return encode_chain_error_for_request(request_id, request_tag, "missing json-rpc result");
869 };
870
871 match request_tag {
872 TAG_CHAIN_HEAD_HEADER_REQ => {
873 if result.is_null() {
874 encode_chain_response_nullable_hex(request_id, TAG_CHAIN_HEAD_HEADER_RESP, Ok(None))
875 } else if let Some(hex) = result.as_str() {
876 let bytes = hex_to_bytes(hex);
877 encode_chain_response_nullable_hex(
878 request_id,
879 TAG_CHAIN_HEAD_HEADER_RESP,
880 Ok(Some(bytes.as_slice())),
881 )
882 } else {
883 encode_chain_error_for_request(request_id, request_tag, "invalid header result")
884 }
885 }
886 TAG_CHAIN_HEAD_BODY_REQ => {
887 if result.is_null() {
888 encode_chain_response_operation_started(
889 request_id,
890 TAG_CHAIN_HEAD_BODY_RESP,
891 Ok(None),
892 )
893 } else if let Some(operation_id) = result.as_str() {
894 encode_chain_response_operation_started(
895 request_id,
896 TAG_CHAIN_HEAD_BODY_RESP,
897 Ok(Some(operation_id)),
898 )
899 } else {
900 encode_chain_error_for_request(request_id, request_tag, "invalid body result")
901 }
902 }
903 TAG_CHAIN_HEAD_STORAGE_REQ => {
904 if result.is_null() {
905 encode_chain_response_operation_started(
906 request_id,
907 TAG_CHAIN_HEAD_STORAGE_RESP,
908 Ok(None),
909 )
910 } else if let Some(operation_id) = result.as_str() {
911 encode_chain_response_operation_started(
912 request_id,
913 TAG_CHAIN_HEAD_STORAGE_RESP,
914 Ok(Some(operation_id)),
915 )
916 } else {
917 encode_chain_error_for_request(request_id, request_tag, "invalid storage result")
918 }
919 }
920 TAG_CHAIN_HEAD_CALL_REQ => {
921 if result.is_null() {
922 encode_chain_response_operation_started(
923 request_id,
924 TAG_CHAIN_HEAD_CALL_RESP,
925 Ok(None),
926 )
927 } else if let Some(operation_id) = result.as_str() {
928 encode_chain_response_operation_started(
929 request_id,
930 TAG_CHAIN_HEAD_CALL_RESP,
931 Ok(Some(operation_id)),
932 )
933 } else {
934 encode_chain_error_for_request(request_id, request_tag, "invalid call result")
935 }
936 }
937 TAG_CHAIN_HEAD_UNPIN_REQ => {
938 encode_chain_response_void(request_id, TAG_CHAIN_HEAD_UNPIN_RESP, None)
939 }
940 TAG_CHAIN_HEAD_CONTINUE_REQ => {
941 encode_chain_response_void(request_id, TAG_CHAIN_HEAD_CONTINUE_RESP, None)
942 }
943 TAG_CHAIN_HEAD_STOP_OP_REQ => {
944 encode_chain_response_void(request_id, TAG_CHAIN_HEAD_STOP_OP_RESP, None)
945 }
946 TAG_CHAIN_SPEC_GENESIS_HASH_REQ => {
947 if let Some(hex) = result.as_str() {
948 let bytes = hex_to_bytes(hex);
949 encode_chain_response_hex(
950 request_id,
951 TAG_CHAIN_SPEC_GENESIS_HASH_RESP,
952 Ok(bytes.as_slice()),
953 )
954 } else {
955 encode_chain_error_for_request(
956 request_id,
957 request_tag,
958 "invalid genesis hash result",
959 )
960 }
961 }
962 TAG_CHAIN_SPEC_CHAIN_NAME_REQ => {
963 if let Some(name) = result.as_str() {
964 encode_chain_response_string(request_id, TAG_CHAIN_SPEC_CHAIN_NAME_RESP, Ok(name))
965 } else {
966 encode_chain_error_for_request(request_id, request_tag, "invalid chain name result")
967 }
968 }
969 TAG_CHAIN_SPEC_PROPERTIES_REQ => {
970 let properties = serde_json::to_string(result).unwrap_or_else(|_| "{}".to_string());
971 encode_chain_response_string(
972 request_id,
973 TAG_CHAIN_SPEC_PROPERTIES_RESP,
974 Ok(properties.as_str()),
975 )
976 }
977 TAG_CHAIN_TX_BROADCAST_REQ => {
978 if result.is_null() {
979 encode_chain_response_nullable_string(
980 request_id,
981 TAG_CHAIN_TX_BROADCAST_RESP,
982 Ok(None),
983 )
984 } else if let Some(operation_id) = result.as_str() {
985 encode_chain_response_nullable_string(
986 request_id,
987 TAG_CHAIN_TX_BROADCAST_RESP,
988 Ok(Some(operation_id)),
989 )
990 } else {
991 encode_chain_error_for_request(
992 request_id,
993 request_tag,
994 "invalid transaction result",
995 )
996 }
997 }
998 TAG_CHAIN_TX_STOP_REQ => {
999 encode_chain_response_void(request_id, TAG_CHAIN_TX_STOP_RESP, None)
1000 }
1001 _ => crate::protocol::encode_jsonrpc_send_error(request_id),
1002 }
1003}