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 encode_string(buf, request_id);
611 encode_tag(buf, response_tag);
612 encode_tag(buf, 0); }
614
615fn encode_generic_error(buf: &mut Vec<u8>, reason: &str) {
619 encode_result_err(buf);
620 encode_tag(buf, 0); encode_string(buf, reason);
622}
623
624pub fn encode_chain_head_event(request_id: &str, event: &ChainHeadEvent) -> Vec<u8> {
632 let mut buf = Vec::with_capacity(128);
633 encode_envelope(&mut buf, request_id, TAG_CHAIN_HEAD_FOLLOW_RECEIVE);
634 encode_event_payload(&mut buf, event);
635 buf
636}
637
638pub fn encode_chain_response_void(
642 request_id: &str,
643 response_tag: u8,
644 error: Option<&str>,
645) -> Vec<u8> {
646 let mut buf = Vec::with_capacity(32);
647 encode_envelope(&mut buf, request_id, response_tag);
648 match error {
649 None => encode_result_ok_void(&mut buf),
650 Some(reason) => encode_generic_error(&mut buf, reason),
651 }
652 buf
653}
654
655pub fn encode_chain_response_nullable_hex(
659 request_id: &str,
660 response_tag: u8,
661 result: Result<Option<&[u8]>, &str>,
662) -> Vec<u8> {
663 let mut buf = Vec::with_capacity(64);
664 encode_envelope(&mut buf, request_id, response_tag);
665 match result {
666 Ok(maybe_bytes) => {
667 encode_result_ok(&mut buf);
668 match maybe_bytes {
669 None => encode_option_none(&mut buf),
670 Some(bytes) => {
671 encode_option_some(&mut buf);
672 encode_var_bytes(&mut buf, bytes);
673 }
674 }
675 }
676 Err(reason) => encode_generic_error(&mut buf, reason),
677 }
678 buf
679}
680
681pub fn encode_chain_response_operation_started(
688 request_id: &str,
689 response_tag: u8,
690 result: Result<Option<&str>, &str>,
691) -> Vec<u8> {
692 let mut buf = Vec::with_capacity(64);
693 encode_envelope(&mut buf, request_id, response_tag);
694 match result {
695 Ok(Some(op_id)) => {
696 encode_result_ok(&mut buf);
697 encode_tag(&mut buf, 0); encode_string(&mut buf, op_id);
699 }
700 Ok(None) => {
701 encode_result_ok(&mut buf);
702 encode_tag(&mut buf, 1); }
704 Err(reason) => encode_generic_error(&mut buf, reason),
705 }
706 buf
707}
708
709pub fn encode_chain_response_hex(
713 request_id: &str,
714 response_tag: u8,
715 result: Result<&[u8], &str>,
716) -> Vec<u8> {
717 let mut buf = Vec::with_capacity(64);
718 encode_envelope(&mut buf, request_id, response_tag);
719 match result {
720 Ok(bytes) => {
721 encode_result_ok(&mut buf);
722 encode_var_bytes(&mut buf, bytes);
723 }
724 Err(reason) => encode_generic_error(&mut buf, reason),
725 }
726 buf
727}
728
729pub fn encode_chain_response_string(
733 request_id: &str,
734 response_tag: u8,
735 result: Result<&str, &str>,
736) -> Vec<u8> {
737 let mut buf = Vec::with_capacity(64);
738 encode_envelope(&mut buf, request_id, response_tag);
739 match result {
740 Ok(s) => {
741 encode_result_ok(&mut buf);
742 encode_string(&mut buf, s);
743 }
744 Err(reason) => encode_generic_error(&mut buf, reason),
745 }
746 buf
747}
748
749pub fn encode_chain_response_nullable_string(
753 request_id: &str,
754 response_tag: u8,
755 result: Result<Option<&str>, &str>,
756) -> Vec<u8> {
757 let mut buf = Vec::with_capacity(64);
758 encode_envelope(&mut buf, request_id, response_tag);
759 match result {
760 Ok(maybe_str) => {
761 encode_result_ok(&mut buf);
762 match maybe_str {
763 None => encode_option_none(&mut buf),
764 Some(s) => {
765 encode_option_some(&mut buf);
766 encode_string(&mut buf, s);
767 }
768 }
769 }
770 Err(reason) => encode_generic_error(&mut buf, reason),
771 }
772 buf
773}
774
775fn encode_chain_error_for_request(request_id: &str, request_tag: u8, reason: &str) -> Vec<u8> {
776 match request_tag {
777 TAG_CHAIN_HEAD_HEADER_REQ => {
778 encode_chain_response_nullable_hex(request_id, TAG_CHAIN_HEAD_HEADER_RESP, Err(reason))
779 }
780 TAG_CHAIN_HEAD_BODY_REQ => encode_chain_response_operation_started(
781 request_id,
782 TAG_CHAIN_HEAD_BODY_RESP,
783 Err(reason),
784 ),
785 TAG_CHAIN_HEAD_STORAGE_REQ => encode_chain_response_operation_started(
786 request_id,
787 TAG_CHAIN_HEAD_STORAGE_RESP,
788 Err(reason),
789 ),
790 TAG_CHAIN_HEAD_CALL_REQ => encode_chain_response_operation_started(
791 request_id,
792 TAG_CHAIN_HEAD_CALL_RESP,
793 Err(reason),
794 ),
795 TAG_CHAIN_HEAD_UNPIN_REQ => {
796 encode_chain_response_void(request_id, TAG_CHAIN_HEAD_UNPIN_RESP, Some(reason))
797 }
798 TAG_CHAIN_HEAD_CONTINUE_REQ => {
799 encode_chain_response_void(request_id, TAG_CHAIN_HEAD_CONTINUE_RESP, Some(reason))
800 }
801 TAG_CHAIN_HEAD_STOP_OP_REQ => {
802 encode_chain_response_void(request_id, TAG_CHAIN_HEAD_STOP_OP_RESP, Some(reason))
803 }
804 TAG_CHAIN_SPEC_GENESIS_HASH_REQ => {
805 encode_chain_response_hex(request_id, TAG_CHAIN_SPEC_GENESIS_HASH_RESP, Err(reason))
806 }
807 TAG_CHAIN_SPEC_CHAIN_NAME_REQ => {
808 encode_chain_response_string(request_id, TAG_CHAIN_SPEC_CHAIN_NAME_RESP, Err(reason))
809 }
810 TAG_CHAIN_SPEC_PROPERTIES_REQ => {
811 encode_chain_response_string(request_id, TAG_CHAIN_SPEC_PROPERTIES_RESP, Err(reason))
812 }
813 TAG_CHAIN_TX_BROADCAST_REQ => encode_chain_response_nullable_string(
814 request_id,
815 TAG_CHAIN_TX_BROADCAST_RESP,
816 Err(reason),
817 ),
818 TAG_CHAIN_TX_STOP_REQ => {
819 encode_chain_response_void(request_id, TAG_CHAIN_TX_STOP_RESP, Some(reason))
820 }
821 _ => crate::protocol::encode_jsonrpc_send_error(request_id),
822 }
823}
824
825pub fn encode_chain_follow_json_event(request_id: &str, json_rpc: &str) -> Option<Vec<u8>> {
827 parse_chain_head_json_rpc(json_rpc).map(|event| encode_chain_head_event(request_id, &event))
828}
829
830pub fn encode_chain_follow_stop(request_id: &str) -> Vec<u8> {
832 encode_chain_head_event(request_id, &ChainHeadEvent::Stop)
833}
834
835pub fn encode_chain_rpc_error(request_id: &str, request_tag: u8, reason: &str) -> Vec<u8> {
837 encode_chain_error_for_request(request_id, request_tag, reason)
838}
839
840pub fn encode_chain_rpc_json_response(
843 request_id: &str,
844 request_tag: u8,
845 json_rpc: &str,
846) -> Vec<u8> {
847 let root: serde_json::Value = match serde_json::from_str(json_rpc) {
848 Ok(value) => value,
849 Err(_) => {
850 return encode_chain_error_for_request(
851 request_id,
852 request_tag,
853 "invalid json-rpc response",
854 )
855 }
856 };
857
858 if let Some(reason) = root
859 .get("error")
860 .and_then(|error| error.get("message"))
861 .and_then(|message| message.as_str())
862 {
863 return encode_chain_error_for_request(request_id, request_tag, reason);
864 }
865
866 let Some(result) = root.get("result") else {
867 return encode_chain_error_for_request(request_id, request_tag, "missing json-rpc result");
868 };
869
870 match request_tag {
871 TAG_CHAIN_HEAD_HEADER_REQ => {
872 if result.is_null() {
873 encode_chain_response_nullable_hex(request_id, TAG_CHAIN_HEAD_HEADER_RESP, Ok(None))
874 } else if let Some(hex) = result.as_str() {
875 let bytes = hex_to_bytes(hex);
876 encode_chain_response_nullable_hex(
877 request_id,
878 TAG_CHAIN_HEAD_HEADER_RESP,
879 Ok(Some(bytes.as_slice())),
880 )
881 } else {
882 encode_chain_error_for_request(request_id, request_tag, "invalid header result")
883 }
884 }
885 TAG_CHAIN_HEAD_BODY_REQ => {
886 if result.is_null() {
887 encode_chain_response_operation_started(
888 request_id,
889 TAG_CHAIN_HEAD_BODY_RESP,
890 Ok(None),
891 )
892 } else if let Some(operation_id) = result.as_str() {
893 encode_chain_response_operation_started(
894 request_id,
895 TAG_CHAIN_HEAD_BODY_RESP,
896 Ok(Some(operation_id)),
897 )
898 } else {
899 encode_chain_error_for_request(request_id, request_tag, "invalid body result")
900 }
901 }
902 TAG_CHAIN_HEAD_STORAGE_REQ => {
903 if result.is_null() {
904 encode_chain_response_operation_started(
905 request_id,
906 TAG_CHAIN_HEAD_STORAGE_RESP,
907 Ok(None),
908 )
909 } else if let Some(operation_id) = result.as_str() {
910 encode_chain_response_operation_started(
911 request_id,
912 TAG_CHAIN_HEAD_STORAGE_RESP,
913 Ok(Some(operation_id)),
914 )
915 } else {
916 encode_chain_error_for_request(request_id, request_tag, "invalid storage result")
917 }
918 }
919 TAG_CHAIN_HEAD_CALL_REQ => {
920 if result.is_null() {
921 encode_chain_response_operation_started(
922 request_id,
923 TAG_CHAIN_HEAD_CALL_RESP,
924 Ok(None),
925 )
926 } else if let Some(operation_id) = result.as_str() {
927 encode_chain_response_operation_started(
928 request_id,
929 TAG_CHAIN_HEAD_CALL_RESP,
930 Ok(Some(operation_id)),
931 )
932 } else {
933 encode_chain_error_for_request(request_id, request_tag, "invalid call result")
934 }
935 }
936 TAG_CHAIN_HEAD_UNPIN_REQ => {
937 encode_chain_response_void(request_id, TAG_CHAIN_HEAD_UNPIN_RESP, None)
938 }
939 TAG_CHAIN_HEAD_CONTINUE_REQ => {
940 encode_chain_response_void(request_id, TAG_CHAIN_HEAD_CONTINUE_RESP, None)
941 }
942 TAG_CHAIN_HEAD_STOP_OP_REQ => {
943 encode_chain_response_void(request_id, TAG_CHAIN_HEAD_STOP_OP_RESP, None)
944 }
945 TAG_CHAIN_SPEC_GENESIS_HASH_REQ => {
946 if let Some(hex) = result.as_str() {
947 let bytes = hex_to_bytes(hex);
948 encode_chain_response_hex(
949 request_id,
950 TAG_CHAIN_SPEC_GENESIS_HASH_RESP,
951 Ok(bytes.as_slice()),
952 )
953 } else {
954 encode_chain_error_for_request(
955 request_id,
956 request_tag,
957 "invalid genesis hash result",
958 )
959 }
960 }
961 TAG_CHAIN_SPEC_CHAIN_NAME_REQ => {
962 if let Some(name) = result.as_str() {
963 encode_chain_response_string(request_id, TAG_CHAIN_SPEC_CHAIN_NAME_RESP, Ok(name))
964 } else {
965 encode_chain_error_for_request(request_id, request_tag, "invalid chain name result")
966 }
967 }
968 TAG_CHAIN_SPEC_PROPERTIES_REQ => {
969 let properties = serde_json::to_string(result).unwrap_or_else(|_| "{}".to_string());
970 encode_chain_response_string(
971 request_id,
972 TAG_CHAIN_SPEC_PROPERTIES_RESP,
973 Ok(properties.as_str()),
974 )
975 }
976 TAG_CHAIN_TX_BROADCAST_REQ => {
977 if result.is_null() {
978 encode_chain_response_nullable_string(
979 request_id,
980 TAG_CHAIN_TX_BROADCAST_RESP,
981 Ok(None),
982 )
983 } else if let Some(operation_id) = result.as_str() {
984 encode_chain_response_nullable_string(
985 request_id,
986 TAG_CHAIN_TX_BROADCAST_RESP,
987 Ok(Some(operation_id)),
988 )
989 } else {
990 encode_chain_error_for_request(
991 request_id,
992 request_tag,
993 "invalid transaction result",
994 )
995 }
996 }
997 TAG_CHAIN_TX_STOP_REQ => {
998 encode_chain_response_void(request_id, TAG_CHAIN_TX_STOP_RESP, None)
999 }
1000 _ => crate::protocol::encode_jsonrpc_send_error(request_id),
1001 }
1002}