1use crate::account::{AccessKey, AccessKeyPermission, Account, FunctionCallPermission};
7use crate::action::delegate::{DelegateAction, SignedDelegateAction};
8use crate::action::{
9 DeployGlobalContractAction, GlobalContractDeployMode, GlobalContractIdentifier,
10 UseGlobalContractAction,
11};
12use crate::bandwidth_scheduler::BandwidthRequests;
13use crate::block::{Block, BlockHeader, Tip};
14use crate::block_header::BlockHeaderInnerLite;
15use crate::challenge::SlashedValidator;
16use crate::congestion_info::{CongestionInfo, CongestionInfoV1};
17use crate::errors::TxExecutionError;
18use crate::hash::{CryptoHash, hash};
19use crate::merkle::{MerklePath, combine_hash};
20use crate::network::PeerId;
21use crate::receipt::{
22 ActionReceipt, DataReceipt, DataReceiver, GlobalContractDistributionReceipt, Receipt,
23 ReceiptEnum, ReceiptV1,
24};
25use crate::serialize::dec_format;
26use crate::sharding::shard_chunk_header_inner::ShardChunkHeaderInnerV4;
27use crate::sharding::{
28 ChunkHash, ShardChunk, ShardChunkHeader, ShardChunkHeaderInner, ShardChunkHeaderInnerV2,
29 ShardChunkHeaderInnerV3, ShardChunkHeaderV3,
30};
31use crate::stateless_validation::chunk_endorsements_bitmap::ChunkEndorsementsBitmap;
32use crate::transaction::{
33 Action, AddKeyAction, CreateAccountAction, DeleteAccountAction, DeleteKeyAction,
34 DeployContractAction, ExecutionMetadata, ExecutionOutcome, ExecutionOutcomeWithIdAndProof,
35 ExecutionStatus, FunctionCallAction, PartialExecutionOutcome, PartialExecutionStatus,
36 SignedTransaction, StakeAction, TransferAction,
37};
38use crate::types::{
39 AccountId, AccountWithPublicKey, Balance, BlockHeight, EpochHeight, EpochId, FunctionArgs, Gas,
40 Nonce, NumBlocks, ShardId, StateChangeCause, StateChangeKind, StateChangeValue,
41 StateChangeWithCause, StateChangesRequest, StateRoot, StorageUsage, StoreKey, StoreValue,
42 ValidatorKickoutReason,
43};
44use crate::version::{ProtocolVersion, Version};
45use borsh::{BorshDeserialize, BorshSerialize};
46use near_crypto::{PublicKey, Signature};
47use near_fmt::{AbbrBytes, Slice};
48use near_parameters::config::CongestionControlConfig;
49use near_parameters::view::CongestionControlConfigView;
50use near_parameters::{ActionCosts, ExtCosts};
51use near_primitives_core::account::AccountContract;
52use near_schema_checker_lib::ProtocolSchema;
53use near_time::Utc;
54use serde_with::base64::Base64;
55use serde_with::serde_as;
56use std::collections::HashMap;
57use std::fmt;
58use std::ops::Range;
59use std::sync::Arc;
60use strum::IntoEnumIterator;
61use validator_stake_view::ValidatorStakeView;
62
63#[derive(serde::Serialize, serde::Deserialize, Debug, Eq, PartialEq, Clone)]
65#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
66pub struct AccountView {
67 #[serde(with = "dec_format")]
68 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
69 pub amount: Balance,
70 #[serde(with = "dec_format")]
71 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
72 pub locked: Balance,
73 pub code_hash: CryptoHash,
74 pub storage_usage: StorageUsage,
75 #[serde(default)]
77 pub storage_paid_at: BlockHeight,
78 #[serde(default, skip_serializing_if = "Option::is_none")]
79 pub global_contract_hash: Option<CryptoHash>,
80 #[serde(default, skip_serializing_if = "Option::is_none")]
81 pub global_contract_account_id: Option<AccountId>,
82}
83
84#[serde_as]
86#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq, Debug, Clone)]
87#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
88pub struct ContractCodeView {
89 #[serde(rename = "code_base64")]
90 #[serde_as(as = "Base64")]
91 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
92 pub code: Vec<u8>,
93 pub hash: CryptoHash,
94}
95
96impl From<&Account> for AccountView {
97 fn from(account: &Account) -> Self {
98 let (global_contract_hash, global_contract_account_id) =
99 match account.contract().into_owned() {
100 AccountContract::Global(contract) => (Some(contract), None),
101 AccountContract::GlobalByAccount(account_id) => (None, Some(account_id)),
102 AccountContract::Local(_) | AccountContract::None => (None, None),
103 };
104 AccountView {
105 amount: account.amount(),
106 locked: account.locked(),
107 code_hash: account.local_contract_hash().unwrap_or_default(),
108 storage_usage: account.storage_usage(),
109 storage_paid_at: 0,
110 global_contract_hash,
111 global_contract_account_id,
112 }
113 }
114}
115
116impl From<Account> for AccountView {
117 fn from(account: Account) -> Self {
118 (&account).into()
119 }
120}
121
122impl From<&AccountView> for Account {
123 fn from(view: &AccountView) -> Self {
124 let contract = match &view.global_contract_account_id {
125 Some(account_id) => AccountContract::GlobalByAccount(account_id.clone()),
126 None => match view.global_contract_hash {
127 Some(hash) => AccountContract::Global(hash),
128 None => AccountContract::from_local_code_hash(view.code_hash),
129 },
130 };
131 Account::new(view.amount, view.locked, contract, view.storage_usage)
132 }
133}
134
135impl From<AccountView> for Account {
136 fn from(view: AccountView) -> Self {
137 (&view).into()
138 }
139}
140
141#[derive(
142 BorshSerialize,
143 BorshDeserialize,
144 Debug,
145 Eq,
146 PartialEq,
147 Clone,
148 serde::Serialize,
149 serde::Deserialize,
150)]
151#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
152pub enum AccessKeyPermissionView {
153 FunctionCall {
154 #[serde(with = "dec_format")]
155 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
156 allowance: Option<Balance>,
157 receiver_id: String,
158 method_names: Vec<String>,
159 },
160 FullAccess,
161}
162
163impl From<AccessKeyPermission> for AccessKeyPermissionView {
164 fn from(permission: AccessKeyPermission) -> Self {
165 match permission {
166 AccessKeyPermission::FunctionCall(func_call) => AccessKeyPermissionView::FunctionCall {
167 allowance: func_call.allowance,
168 receiver_id: func_call.receiver_id,
169 method_names: func_call.method_names,
170 },
171 AccessKeyPermission::FullAccess => AccessKeyPermissionView::FullAccess,
172 }
173 }
174}
175
176impl From<AccessKeyPermissionView> for AccessKeyPermission {
177 fn from(view: AccessKeyPermissionView) -> Self {
178 match view {
179 AccessKeyPermissionView::FunctionCall { allowance, receiver_id, method_names } => {
180 AccessKeyPermission::FunctionCall(FunctionCallPermission {
181 allowance,
182 receiver_id,
183 method_names,
184 })
185 }
186 AccessKeyPermissionView::FullAccess => AccessKeyPermission::FullAccess,
187 }
188 }
189}
190
191#[derive(
192 BorshSerialize,
193 BorshDeserialize,
194 Debug,
195 Eq,
196 PartialEq,
197 Clone,
198 serde::Serialize,
199 serde::Deserialize,
200)]
201#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
202pub struct AccessKeyView {
203 pub nonce: Nonce,
204 pub permission: AccessKeyPermissionView,
205}
206
207impl From<AccessKey> for AccessKeyView {
208 fn from(access_key: AccessKey) -> Self {
209 Self { nonce: access_key.nonce, permission: access_key.permission.into() }
210 }
211}
212
213impl From<AccessKeyView> for AccessKey {
214 fn from(view: AccessKeyView) -> Self {
215 Self { nonce: view.nonce, permission: view.permission.into() }
216 }
217}
218
219#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
221#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
222pub struct StateItem {
223 pub key: StoreKey,
224 pub value: StoreValue,
225}
226
227#[serde_as]
228#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
229#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
230pub struct ViewStateResult {
231 pub values: Vec<StateItem>,
232 #[serde_as(as = "Vec<Base64>")]
233 #[serde(default, skip_serializing_if = "Vec::is_empty")]
234 #[cfg_attr(feature = "schemars", schemars(with = "Vec<String>"))]
235 pub proof: Vec<Arc<[u8]>>,
236}
237
238#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone, Default)]
239#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
240pub struct CallResult {
241 pub result: Vec<u8>,
242 pub logs: Vec<String>,
243}
244
245#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
246pub struct QueryError {
247 pub error: String,
248 pub logs: Vec<String>,
249}
250
251#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
252#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
253pub struct AccessKeyInfoView {
254 pub public_key: PublicKey,
255 pub access_key: AccessKeyView,
256}
257
258#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
259#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
260pub struct AccessKeyList {
261 pub keys: Vec<AccessKeyInfoView>,
262}
263
264impl FromIterator<AccessKeyInfoView> for AccessKeyList {
265 fn from_iter<I: IntoIterator<Item = AccessKeyInfoView>>(iter: I) -> Self {
266 Self { keys: iter.into_iter().collect() }
267 }
268}
269
270#[cfg_attr(feature = "deepsize_feature", derive(deepsize::DeepSizeOf))]
272#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
273#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
274pub struct KnownPeerStateView {
275 pub peer_id: PeerId,
276 pub status: String,
277 pub addr: String,
278 pub first_seen: i64,
279 pub last_seen: i64,
280 pub last_attempt: Option<(i64, String)>,
281}
282
283#[cfg_attr(feature = "deepsize_feature", derive(deepsize::DeepSizeOf))]
284#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
285#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
286pub struct ConnectionInfoView {
287 pub peer_id: PeerId,
288 pub addr: String,
289 pub time_established: i64,
290 pub time_connected_until: i64,
291}
292
293#[cfg_attr(feature = "deepsize_feature", derive(deepsize::DeepSizeOf))]
294#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
295#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
296pub struct SnapshotHostInfoView {
297 pub peer_id: PeerId,
298 pub sync_hash: CryptoHash,
299 pub epoch_height: u64,
300 pub shards: Vec<u64>,
301}
302
303#[cfg_attr(feature = "deepsize_feature", derive(deepsize::DeepSizeOf))]
304#[derive(Debug, PartialEq, Eq, Clone)]
305pub enum QueryResponseKind {
306 ViewAccount(AccountView),
307 ViewCode(ContractCodeView),
308 ViewState(ViewStateResult),
309 CallResult(CallResult),
310 AccessKey(AccessKeyView),
311 AccessKeyList(AccessKeyList),
312}
313
314#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
315#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
316#[serde(tag = "request_type", rename_all = "snake_case")]
317pub enum QueryRequest {
318 ViewAccount {
319 account_id: AccountId,
320 },
321 ViewCode {
322 account_id: AccountId,
323 },
324 ViewState {
325 account_id: AccountId,
326 #[serde(rename = "prefix_base64")]
327 prefix: StoreKey,
328 #[serde(default, skip_serializing_if = "is_false")]
329 include_proof: bool,
330 },
331 ViewAccessKey {
332 account_id: AccountId,
333 public_key: PublicKey,
334 },
335 ViewAccessKeyList {
336 account_id: AccountId,
337 },
338 CallFunction {
339 account_id: AccountId,
340 method_name: String,
341 #[serde(rename = "args_base64")]
342 args: FunctionArgs,
343 },
344 ViewGlobalContractCode {
345 code_hash: CryptoHash,
346 },
347 ViewGlobalContractCodeByAccountId {
348 account_id: AccountId,
349 },
350}
351
352fn is_false(v: &bool) -> bool {
353 !*v
354}
355
356#[derive(Debug, PartialEq, Eq, Clone)]
357pub struct QueryResponse {
358 pub kind: QueryResponseKind,
359 pub block_height: BlockHeight,
360 pub block_hash: CryptoHash,
361}
362
363#[derive(serde::Serialize, serde::Deserialize, Debug)]
364#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
365pub struct StatusSyncInfo {
366 pub latest_block_hash: CryptoHash,
367 pub latest_block_height: BlockHeight,
368 pub latest_state_root: CryptoHash,
369 #[serde(with = "near_time::serde_utc_as_iso")]
370 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
371 pub latest_block_time: Utc,
372 pub syncing: bool,
373 pub earliest_block_hash: Option<CryptoHash>,
374 pub earliest_block_height: Option<BlockHeight>,
375 #[serde(with = "near_time::serde_opt_utc_as_iso")]
376 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
377 pub earliest_block_time: Option<Utc>,
378 pub epoch_id: Option<EpochId>,
379 pub epoch_start_height: Option<BlockHeight>,
380}
381
382#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
384#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
385pub struct ValidatorInfo {
386 pub account_id: AccountId,
387}
388
389#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
390#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
391pub struct PeerInfoView {
392 pub addr: String,
393 pub account_id: Option<AccountId>,
394 pub height: Option<BlockHeight>,
395 pub block_hash: Option<CryptoHash>,
396 pub is_highest_block_invalid: bool,
397 pub tracked_shards: Vec<ShardId>,
398 pub archival: bool,
399 pub peer_id: PublicKey,
400 pub received_bytes_per_sec: u64,
401 pub sent_bytes_per_sec: u64,
402 pub last_time_peer_requested_millis: u64,
403 pub last_time_received_message_millis: u64,
404 pub connection_established_time_millis: u64,
405 pub is_outbound_peer: bool,
406 pub nonce: u64,
408}
409
410#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
413#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
414pub struct KnownProducerView {
415 pub account_id: AccountId,
416 pub peer_id: PublicKey,
417 pub next_hops: Option<Vec<PublicKey>>,
418}
419
420#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
421#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
422pub struct Tier1ProxyView {
423 pub addr: std::net::SocketAddr,
424 pub peer_id: PublicKey,
425}
426
427#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
428#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
429pub struct AccountDataView {
430 pub peer_id: PublicKey,
431 pub proxies: Vec<Tier1ProxyView>,
432 pub account_key: PublicKey,
433 #[serde(with = "near_time::serde_utc_as_iso")]
434 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
435 pub timestamp: Utc,
436}
437
438#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
439#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
440pub struct NetworkInfoView {
441 pub peer_max_count: u32,
442 pub num_connected_peers: usize,
443 pub connected_peers: Vec<PeerInfoView>,
444 pub known_producers: Vec<KnownProducerView>,
445 pub tier1_accounts_keys: Vec<PublicKey>,
446 pub tier1_accounts_data: Vec<AccountDataView>,
447 pub tier1_connections: Vec<PeerInfoView>,
448}
449
450#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
451#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
452pub enum SyncStatusView {
453 AwaitingPeers,
455 NoSync,
457 EpochSync {
459 source_peer_height: BlockHeight,
460 source_peer_id: String,
461 attempt_time: String,
462 },
463 EpochSyncDone,
464 HeaderSync {
466 start_height: BlockHeight,
467 current_height: BlockHeight,
468 highest_height: BlockHeight,
469 },
470 StateSync(StateSyncStatusView),
472 StateSyncDone,
474 BlockSync {
476 start_height: BlockHeight,
477 current_height: BlockHeight,
478 highest_height: BlockHeight,
479 },
480}
481
482#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
483#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
484pub struct StateSyncStatusView {
485 pub sync_hash: CryptoHash,
486 pub shard_sync_status: HashMap<ShardId, String>,
487 pub download_tasks: Vec<String>,
488 pub computation_tasks: Vec<String>,
489}
490
491#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
492#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
493pub struct PeerStoreView {
494 pub peer_states: Vec<KnownPeerStateView>,
495}
496
497#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
498#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
499pub struct RecentOutboundConnectionsView {
500 pub recent_outbound_connections: Vec<ConnectionInfoView>,
501}
502
503#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
504#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
505pub struct SnapshotHostsView {
506 pub hosts: Vec<SnapshotHostInfoView>,
507}
508
509#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
510#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
511pub struct EdgeView {
512 pub peer0: PeerId,
513 pub peer1: PeerId,
514 pub nonce: u64,
515}
516
517#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
518#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
519pub struct NetworkGraphView {
520 pub edges: Vec<EdgeView>,
521 pub next_hops: HashMap<PeerId, Vec<PeerId>>,
522}
523
524#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
525#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
526pub struct LabeledEdgeView {
527 pub peer0: u32,
528 pub peer1: u32,
529 pub nonce: u64,
530}
531
532#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Default)]
533#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
534pub struct EdgeCacheView {
535 pub peer_labels: HashMap<PeerId, u32>,
536 pub spanning_trees: HashMap<u32, Vec<LabeledEdgeView>>,
537}
538
539#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
540#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
541pub struct PeerDistancesView {
542 pub distance: Vec<Option<u32>>,
543 pub min_nonce: u64,
544}
545
546#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Default)]
547#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
548pub struct NetworkRoutesView {
549 pub edge_cache: EdgeCacheView,
550 pub local_edges: HashMap<PeerId, EdgeView>,
551 pub peer_distances: HashMap<PeerId, PeerDistancesView>,
552 pub my_distances: HashMap<PeerId, u32>,
553}
554
555#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
556#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
557pub struct ShardSyncDownloadView {
558 pub downloads: Vec<DownloadStatusView>,
559 pub status: String,
560}
561
562#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
563#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
564pub struct DownloadStatusView {
565 pub error: bool,
566 pub done: bool,
567}
568
569#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
570#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
571pub struct CatchupStatusView {
572 pub sync_block_hash: CryptoHash,
574 pub sync_block_height: BlockHeight,
575 pub shard_sync_status: HashMap<ShardId, String>,
577 pub blocks_to_catchup: Vec<BlockStatusView>,
579}
580
581#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
582#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
583pub struct RequestedStatePartsView {
584 pub block_hash: CryptoHash,
586 pub shard_requested_parts: HashMap<ShardId, Vec<PartElapsedTimeView>>,
588}
589
590#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
591#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
592pub struct BlockStatusView {
593 pub height: BlockHeight,
594 pub hash: CryptoHash,
595}
596
597impl BlockStatusView {
598 pub fn new(height: &BlockHeight, hash: &CryptoHash) -> BlockStatusView {
599 Self { height: *height, hash: *hash }
600 }
601}
602
603impl From<Tip> for BlockStatusView {
604 fn from(tip: Tip) -> Self {
605 Self { height: tip.height, hash: tip.last_block_hash }
606 }
607}
608
609#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
610#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
611pub struct PartElapsedTimeView {
612 pub part_id: u64,
613 pub elapsed_ms: u128,
614}
615
616impl PartElapsedTimeView {
617 pub fn new(part_id: &u64, elapsed_ms: u128) -> PartElapsedTimeView {
618 Self { part_id: *part_id, elapsed_ms }
619 }
620}
621
622#[derive(serde::Serialize, serde::Deserialize, Debug)]
623#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
624pub struct BlockByChunksView {
625 pub height: BlockHeight,
626 pub hash: CryptoHash,
627 pub block_status: String,
628 pub chunk_status: String,
629}
630
631#[derive(serde::Serialize, serde::Deserialize, Debug)]
632#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
633pub struct ChainProcessingInfo {
634 pub num_blocks_in_processing: usize,
635 pub num_orphans: usize,
636 pub num_blocks_missing_chunks: usize,
637 pub blocks_info: Vec<BlockProcessingInfo>,
639 pub floating_chunks_info: Vec<ChunkProcessingInfo>,
641}
642
643#[derive(serde::Serialize, serde::Deserialize, Debug)]
644#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
645pub struct BlockProcessingInfo {
646 pub height: BlockHeight,
647 pub hash: CryptoHash,
648 #[serde(with = "near_time::serde_utc_as_iso")]
649 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
650 pub received_timestamp: Utc,
651 pub in_progress_ms: u128,
653 pub orphaned_ms: Option<u128>,
657 pub missing_chunks_ms: Option<u128>,
661 pub block_status: BlockProcessingStatus,
662 pub chunks_info: Vec<Option<ChunkProcessingInfo>>,
665}
666
667#[derive(
668 BorshSerialize,
669 BorshDeserialize,
670 Clone,
671 Debug,
672 PartialEq,
673 Eq,
674 serde::Serialize,
675 serde::Deserialize,
676)]
677#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
678pub enum BlockProcessingStatus {
679 Orphan,
680 WaitingForChunks,
681 InProcessing,
682 Accepted,
683 Error(String),
684 Dropped(DroppedReason),
685 Unknown,
686}
687
688#[derive(
689 BorshSerialize,
690 BorshDeserialize,
691 Clone,
692 Debug,
693 PartialEq,
694 Eq,
695 serde::Serialize,
696 serde::Deserialize,
697)]
698#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
699pub enum DroppedReason {
700 HeightProcessed,
702 TooManyProcessingBlocks,
704}
705
706#[derive(serde::Serialize, serde::Deserialize, Debug)]
707#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
708pub struct ChunkProcessingInfo {
709 pub height_created: BlockHeight,
710 pub shard_id: ShardId,
711 pub chunk_hash: ChunkHash,
712 pub prev_block_hash: CryptoHash,
713 pub created_by: Option<AccountId>,
716 pub status: ChunkProcessingStatus,
717 #[serde(with = "near_time::serde_opt_utc_as_iso")]
719 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
720 pub requested_timestamp: Option<Utc>,
721 #[serde(with = "near_time::serde_opt_utc_as_iso")]
723 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
724 pub completed_timestamp: Option<Utc>,
725 pub request_duration: Option<u64>,
727 pub chunk_parts_collection: Vec<PartCollectionInfo>,
728}
729
730#[derive(serde::Serialize, serde::Deserialize, Debug)]
731#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
732pub struct PartCollectionInfo {
733 pub part_owner: AccountId,
734 #[serde(with = "near_time::serde_opt_utc_as_iso")]
736 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
737 pub received_time: Option<Utc>,
738 #[serde(with = "near_time::serde_opt_utc_as_iso")]
740 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
741 pub forwarded_received_time: Option<Utc>,
742 #[serde(with = "near_time::serde_opt_utc_as_iso")]
744 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
745 pub chunk_received_time: Option<Utc>,
746}
747
748#[derive(serde::Serialize, serde::Deserialize, Debug)]
749#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
750pub enum ChunkProcessingStatus {
751 NeedToRequest,
752 Requested,
753 Completed,
754}
755
756#[derive(serde::Serialize, serde::Deserialize, Debug)]
757#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
758pub struct DetailedDebugStatus {
759 pub network_info: NetworkInfoView,
760 pub sync_status: String,
761 pub catchup_status: Vec<CatchupStatusView>,
762 pub current_head_status: BlockStatusView,
763 pub current_header_head_status: BlockStatusView,
764 pub block_production_delay_millis: u64,
765}
766
767#[derive(serde::Serialize, serde::Deserialize, Debug)]
769#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
770pub struct StatusResponse {
771 pub version: Version,
773 pub chain_id: String,
775 pub protocol_version: u32,
777 pub latest_protocol_version: u32,
779 #[serde(skip_serializing_if = "Option::is_none")]
781 pub rpc_addr: Option<String>,
782 pub validators: Vec<ValidatorInfo>,
784 pub sync_info: StatusSyncInfo,
786 pub validator_account_id: Option<AccountId>,
788 pub validator_public_key: Option<PublicKey>,
790 pub node_public_key: PublicKey,
792 pub node_key: Option<PublicKey>,
794 pub uptime_sec: i64,
796 pub genesis_hash: CryptoHash,
798 #[serde(skip_serializing_if = "Option::is_none")]
800 pub detailed_debug_status: Option<DetailedDebugStatus>,
801}
802
803#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
804#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
805pub struct BlockHeaderView {
806 pub height: BlockHeight,
807 pub prev_height: Option<BlockHeight>,
808 pub epoch_id: CryptoHash,
809 pub next_epoch_id: CryptoHash,
810 pub hash: CryptoHash,
811 pub prev_hash: CryptoHash,
812 pub prev_state_root: CryptoHash,
813 pub block_body_hash: Option<CryptoHash>,
814 pub chunk_receipts_root: CryptoHash,
815 pub chunk_headers_root: CryptoHash,
816 pub chunk_tx_root: CryptoHash,
817 pub outcome_root: CryptoHash,
818 pub chunks_included: u64,
819 pub challenges_root: CryptoHash,
820 pub timestamp: u64,
822 #[serde(with = "dec_format")]
823 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
824 pub timestamp_nanosec: u64,
825 pub random_value: CryptoHash,
826 pub validator_proposals: Vec<ValidatorStakeView>,
827 pub chunk_mask: Vec<bool>,
828 #[serde(with = "dec_format")]
829 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
830 pub gas_price: Balance,
831 pub block_ordinal: Option<NumBlocks>,
832 #[serde(with = "dec_format")]
834 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
835 pub rent_paid: Balance,
836 #[serde(with = "dec_format")]
838 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
839 pub validator_reward: Balance,
840 #[serde(with = "dec_format")]
841 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
842 pub total_supply: Balance,
843 pub challenges_result: Vec<SlashedValidator>,
845 pub last_final_block: CryptoHash,
846 pub last_ds_final_block: CryptoHash,
847 pub next_bp_hash: CryptoHash,
848 pub block_merkle_root: CryptoHash,
849 pub epoch_sync_data_hash: Option<CryptoHash>,
850 pub approvals: Vec<Option<Box<Signature>>>,
851 pub signature: Signature,
852 pub latest_protocol_version: ProtocolVersion,
853 pub chunk_endorsements: Option<Vec<Vec<u8>>>,
854}
855
856impl From<BlockHeader> for BlockHeaderView {
857 fn from(header: BlockHeader) -> Self {
858 Self {
859 height: header.height(),
860 prev_height: header.prev_height(),
861 epoch_id: header.epoch_id().0,
862 next_epoch_id: header.next_epoch_id().0,
863 hash: *header.hash(),
864 prev_hash: *header.prev_hash(),
865 prev_state_root: *header.prev_state_root(),
866 block_body_hash: header.block_body_hash(),
867 chunk_receipts_root: *header.prev_chunk_outgoing_receipts_root(),
868 chunk_headers_root: *header.chunk_headers_root(),
869 chunk_tx_root: *header.chunk_tx_root(),
870 chunks_included: header.chunks_included(),
871 challenges_root: CryptoHash::default(),
872 outcome_root: *header.outcome_root(),
873 timestamp: header.raw_timestamp(),
874 timestamp_nanosec: header.raw_timestamp(),
875 random_value: *header.random_value(),
876 validator_proposals: header.prev_validator_proposals().map(Into::into).collect(),
877 chunk_mask: header.chunk_mask().to_vec(),
878 block_ordinal: if header.block_ordinal() != 0 {
879 Some(header.block_ordinal())
880 } else {
881 None
882 },
883 gas_price: header.next_gas_price(),
884 rent_paid: 0,
885 validator_reward: 0,
886 total_supply: header.total_supply(),
887 challenges_result: vec![],
888 last_final_block: *header.last_final_block(),
889 last_ds_final_block: *header.last_ds_final_block(),
890 next_bp_hash: *header.next_bp_hash(),
891 block_merkle_root: *header.block_merkle_root(),
892 epoch_sync_data_hash: header.epoch_sync_data_hash(),
893 approvals: header.approvals().to_vec(),
894 signature: header.signature().clone(),
895 latest_protocol_version: header.latest_protocol_version(),
896 chunk_endorsements: header.chunk_endorsements().map(|bitmap| bitmap.bytes()),
897 }
898 }
899}
900
901impl From<BlockHeaderView> for BlockHeader {
902 fn from(view: BlockHeaderView) -> Self {
903 BlockHeader::from_view(
904 &view.hash,
905 view.latest_protocol_version,
906 view.height,
907 view.prev_hash,
908 view.block_body_hash.unwrap_or_default(),
909 view.prev_state_root,
910 view.chunk_receipts_root,
911 view.chunk_headers_root,
912 view.chunk_tx_root,
913 view.outcome_root,
914 view.timestamp,
915 view.random_value,
916 view.validator_proposals.into_iter().map(|v| v.into_validator_stake()).collect(),
917 view.chunk_mask,
918 view.block_ordinal.unwrap_or(0),
919 EpochId(view.epoch_id),
920 EpochId(view.next_epoch_id),
921 view.gas_price,
922 view.total_supply,
923 view.signature,
924 view.last_final_block,
925 view.last_ds_final_block,
926 view.epoch_sync_data_hash,
927 view.approvals,
928 view.next_bp_hash,
929 view.block_merkle_root,
930 view.prev_height.unwrap_or_default(),
931 view.chunk_endorsements.map(|bytes| ChunkEndorsementsBitmap::from_bytes(bytes)),
932 )
933 }
934}
935
936#[derive(
937 PartialEq,
938 Eq,
939 Debug,
940 Clone,
941 BorshDeserialize,
942 BorshSerialize,
943 serde::Serialize,
944 serde::Deserialize,
945)]
946#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
947pub struct BlockHeaderInnerLiteView {
948 pub height: BlockHeight,
949 pub epoch_id: CryptoHash,
950 pub next_epoch_id: CryptoHash,
951 pub prev_state_root: CryptoHash,
952 pub outcome_root: CryptoHash,
953 pub timestamp: u64,
955 #[serde(with = "dec_format")]
956 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
957 pub timestamp_nanosec: u64,
958 pub next_bp_hash: CryptoHash,
959 pub block_merkle_root: CryptoHash,
960}
961
962impl From<BlockHeader> for BlockHeaderInnerLiteView {
963 fn from(header: BlockHeader) -> Self {
964 let inner_lite = header.inner_lite();
965 BlockHeaderInnerLiteView {
966 height: inner_lite.height,
967 epoch_id: inner_lite.epoch_id.0,
968 next_epoch_id: inner_lite.next_epoch_id.0,
969 prev_state_root: inner_lite.prev_state_root,
970 outcome_root: inner_lite.prev_outcome_root,
971 timestamp: inner_lite.timestamp,
972 timestamp_nanosec: inner_lite.timestamp,
973 next_bp_hash: inner_lite.next_bp_hash,
974 block_merkle_root: inner_lite.block_merkle_root,
975 }
976 }
977}
978
979impl From<BlockHeaderInnerLiteView> for BlockHeaderInnerLite {
980 fn from(view: BlockHeaderInnerLiteView) -> Self {
981 BlockHeaderInnerLite {
982 height: view.height,
983 epoch_id: EpochId(view.epoch_id),
984 next_epoch_id: EpochId(view.next_epoch_id),
985 prev_state_root: view.prev_state_root,
986 prev_outcome_root: view.outcome_root,
987 timestamp: view.timestamp_nanosec,
988 next_bp_hash: view.next_bp_hash,
989 block_merkle_root: view.block_merkle_root,
990 }
991 }
992}
993
994#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
995#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
996pub struct ChunkHeaderView {
997 pub chunk_hash: CryptoHash,
998 pub prev_block_hash: CryptoHash,
999 pub outcome_root: CryptoHash,
1000 pub prev_state_root: StateRoot,
1001 pub encoded_merkle_root: CryptoHash,
1002 pub encoded_length: u64,
1003 pub height_created: BlockHeight,
1004 pub height_included: BlockHeight,
1005 pub shard_id: ShardId,
1006 pub gas_used: Gas,
1007 pub gas_limit: Gas,
1008 #[serde(with = "dec_format")]
1010 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1011 pub rent_paid: Balance,
1012 #[serde(with = "dec_format")]
1014 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1015 pub validator_reward: Balance,
1016 #[serde(with = "dec_format")]
1017 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1018 pub balance_burnt: Balance,
1019 pub outgoing_receipts_root: CryptoHash,
1020 pub tx_root: CryptoHash,
1021 pub validator_proposals: Vec<ValidatorStakeView>,
1022 pub congestion_info: Option<CongestionInfoView>,
1023 pub bandwidth_requests: Option<BandwidthRequests>,
1024 pub signature: Signature,
1025}
1026
1027impl ChunkHeaderView {
1028 pub fn is_new_chunk(&self, block_height: BlockHeight) -> bool {
1029 self.height_included == block_height
1030 }
1031}
1032
1033impl From<ShardChunkHeader> for ChunkHeaderView {
1034 fn from(chunk: ShardChunkHeader) -> Self {
1035 let hash = chunk.chunk_hash();
1036 let signature = chunk.signature().clone();
1037 let height_included = chunk.height_included();
1038 let inner = chunk.take_inner();
1039 ChunkHeaderView {
1040 chunk_hash: hash.0,
1041 prev_block_hash: *inner.prev_block_hash(),
1042 outcome_root: *inner.prev_outcome_root(),
1043 prev_state_root: *inner.prev_state_root(),
1044 encoded_merkle_root: *inner.encoded_merkle_root(),
1045 encoded_length: inner.encoded_length(),
1046 height_created: inner.height_created(),
1047 height_included,
1048 shard_id: inner.shard_id(),
1049 gas_used: inner.prev_gas_used(),
1050 gas_limit: inner.gas_limit(),
1051 rent_paid: 0,
1052 validator_reward: 0,
1053 balance_burnt: inner.prev_balance_burnt(),
1054 outgoing_receipts_root: *inner.prev_outgoing_receipts_root(),
1055 tx_root: *inner.tx_root(),
1056 validator_proposals: inner.prev_validator_proposals().map(Into::into).collect(),
1057 congestion_info: Some(inner.congestion_info().into()),
1058 bandwidth_requests: inner.bandwidth_requests().cloned(),
1059 signature,
1060 }
1061 }
1062}
1063
1064impl From<ChunkHeaderView> for ShardChunkHeader {
1065 fn from(view: ChunkHeaderView) -> Self {
1066 match (view.bandwidth_requests, view.congestion_info) {
1067 (Some(bandwidth_requests), Some(congestion_info)) => {
1068 let mut header = ShardChunkHeaderV3 {
1069 inner: ShardChunkHeaderInner::V4(ShardChunkHeaderInnerV4 {
1070 prev_block_hash: view.prev_block_hash,
1071 prev_state_root: view.prev_state_root,
1072 prev_outcome_root: view.outcome_root,
1073 encoded_merkle_root: view.encoded_merkle_root,
1074 encoded_length: view.encoded_length,
1075 height_created: view.height_created,
1076 shard_id: view.shard_id,
1077 prev_gas_used: view.gas_used,
1078 gas_limit: view.gas_limit,
1079 prev_balance_burnt: view.balance_burnt,
1080 prev_outgoing_receipts_root: view.outgoing_receipts_root,
1081 tx_root: view.tx_root,
1082 prev_validator_proposals: view
1083 .validator_proposals
1084 .into_iter()
1085 .map(Into::into)
1086 .collect(),
1087 congestion_info: congestion_info.into(),
1088 bandwidth_requests,
1089 }),
1090 height_included: view.height_included,
1091 signature: view.signature,
1092 hash: ChunkHash::default(),
1093 };
1094 header.init();
1095 ShardChunkHeader::V3(header)
1096 }
1097 (None, Some(congestion_info)) => {
1098 let mut header = ShardChunkHeaderV3 {
1099 inner: ShardChunkHeaderInner::V3(ShardChunkHeaderInnerV3 {
1100 prev_block_hash: view.prev_block_hash,
1101 prev_state_root: view.prev_state_root,
1102 prev_outcome_root: view.outcome_root,
1103 encoded_merkle_root: view.encoded_merkle_root,
1104 encoded_length: view.encoded_length,
1105 height_created: view.height_created,
1106 shard_id: view.shard_id,
1107 prev_gas_used: view.gas_used,
1108 gas_limit: view.gas_limit,
1109 prev_balance_burnt: view.balance_burnt,
1110 prev_outgoing_receipts_root: view.outgoing_receipts_root,
1111 tx_root: view.tx_root,
1112 prev_validator_proposals: view
1113 .validator_proposals
1114 .into_iter()
1115 .map(Into::into)
1116 .collect(),
1117 congestion_info: congestion_info.into(),
1118 }),
1119 height_included: view.height_included,
1120 signature: view.signature,
1121 hash: ChunkHash::default(),
1122 };
1123 header.init();
1124 ShardChunkHeader::V3(header)
1125 }
1126 _ => {
1127 let mut header = ShardChunkHeaderV3 {
1128 inner: ShardChunkHeaderInner::V2(ShardChunkHeaderInnerV2 {
1129 prev_block_hash: view.prev_block_hash,
1130 prev_state_root: view.prev_state_root,
1131 prev_outcome_root: view.outcome_root,
1132 encoded_merkle_root: view.encoded_merkle_root,
1133 encoded_length: view.encoded_length,
1134 height_created: view.height_created,
1135 shard_id: view.shard_id,
1136 prev_gas_used: view.gas_used,
1137 gas_limit: view.gas_limit,
1138 prev_balance_burnt: view.balance_burnt,
1139 prev_outgoing_receipts_root: view.outgoing_receipts_root,
1140 tx_root: view.tx_root,
1141 prev_validator_proposals: view
1142 .validator_proposals
1143 .into_iter()
1144 .map(Into::into)
1145 .collect(),
1146 }),
1147 height_included: view.height_included,
1148 signature: view.signature,
1149 hash: ChunkHash::default(),
1150 };
1151 header.init();
1152 ShardChunkHeader::V3(header)
1153 }
1154 }
1155 }
1156}
1157
1158#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
1159#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1160pub struct BlockView {
1161 pub author: AccountId,
1162 pub header: BlockHeaderView,
1163 pub chunks: Vec<ChunkHeaderView>,
1164}
1165
1166impl BlockView {
1167 pub fn from_author_block(author: AccountId, block: Block) -> Self {
1168 BlockView {
1169 author,
1170 header: block.header().clone().into(),
1171 chunks: block.chunks().iter_deprecated().cloned().map(Into::into).collect(),
1172 }
1173 }
1174}
1175
1176#[derive(serde::Serialize, serde::Deserialize, Debug)]
1177#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1178pub struct ChunkView {
1179 pub author: AccountId,
1180 pub header: ChunkHeaderView,
1181 pub transactions: Vec<SignedTransactionView>,
1182 pub receipts: Vec<ReceiptView>,
1183}
1184
1185impl ChunkView {
1186 pub fn from_author_chunk(author: AccountId, chunk: ShardChunk) -> Self {
1187 match chunk {
1188 ShardChunk::V1(chunk) => Self {
1189 author,
1190 header: ShardChunkHeader::V1(chunk.header).into(),
1191 transactions: chunk.transactions.into_iter().map(Into::into).collect(),
1192 receipts: chunk.prev_outgoing_receipts.into_iter().map(Into::into).collect(),
1193 },
1194 ShardChunk::V2(chunk) => Self {
1195 author,
1196 header: chunk.header.into(),
1197 transactions: chunk.transactions.into_iter().map(Into::into).collect(),
1198 receipts: chunk.prev_outgoing_receipts.into_iter().map(Into::into).collect(),
1199 },
1200 }
1201 }
1202}
1203
1204#[serde_as]
1205#[derive(
1206 BorshSerialize,
1207 BorshDeserialize,
1208 Clone,
1209 Debug,
1210 PartialEq,
1211 Eq,
1212 serde::Serialize,
1213 serde::Deserialize,
1214)]
1215#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1216pub enum ActionView {
1217 CreateAccount,
1218 DeployContract {
1219 #[serde_as(as = "Base64")]
1220 #[cfg_attr(
1221 feature = "schemars",
1222 schemars(schema_with = "crate::serialize::base64_schema")
1223 )]
1224 code: Vec<u8>,
1225 },
1226 FunctionCall {
1227 method_name: String,
1228 args: FunctionArgs,
1229 gas: Gas,
1230 #[serde(with = "dec_format")]
1231 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1232 deposit: Balance,
1233 },
1234 Transfer {
1235 #[serde(with = "dec_format")]
1236 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1237 deposit: Balance,
1238 },
1239 Stake {
1240 #[serde(with = "dec_format")]
1241 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1242 stake: Balance,
1243 public_key: PublicKey,
1244 },
1245 AddKey {
1246 public_key: PublicKey,
1247 access_key: AccessKeyView,
1248 },
1249 DeleteKey {
1250 public_key: PublicKey,
1251 },
1252 DeleteAccount {
1253 beneficiary_id: AccountId,
1254 },
1255 Delegate {
1256 delegate_action: DelegateAction,
1257 signature: Signature,
1258 },
1259 DeployGlobalContract {
1260 #[serde_as(as = "Base64")]
1261 #[cfg_attr(
1262 feature = "schemars",
1263 schemars(schema_with = "crate::serialize::base64_schema")
1264 )]
1265 code: Vec<u8>,
1266 },
1267 DeployGlobalContractByAccountId {
1268 #[serde_as(as = "Base64")]
1269 #[cfg_attr(
1270 feature = "schemars",
1271 schemars(schema_with = "crate::serialize::base64_schema")
1272 )]
1273 code: Vec<u8>,
1274 },
1275 UseGlobalContract {
1276 code_hash: CryptoHash,
1277 },
1278 UseGlobalContractByAccountId {
1279 account_id: AccountId,
1280 },
1281}
1282
1283impl From<Action> for ActionView {
1284 fn from(action: Action) -> Self {
1285 match action {
1286 Action::CreateAccount(_) => ActionView::CreateAccount,
1287 Action::DeployContract(action) => {
1288 let code = hash(&action.code).as_ref().to_vec();
1289 ActionView::DeployContract { code }
1290 }
1291 Action::FunctionCall(action) => ActionView::FunctionCall {
1292 method_name: action.method_name,
1293 args: action.args.into(),
1294 gas: action.gas,
1295 deposit: action.deposit,
1296 },
1297 Action::Transfer(action) => ActionView::Transfer { deposit: action.deposit },
1298 Action::Stake(action) => {
1299 ActionView::Stake { stake: action.stake, public_key: action.public_key }
1300 }
1301 Action::AddKey(action) => ActionView::AddKey {
1302 public_key: action.public_key,
1303 access_key: action.access_key.into(),
1304 },
1305 Action::DeleteKey(action) => ActionView::DeleteKey { public_key: action.public_key },
1306 Action::DeleteAccount(action) => {
1307 ActionView::DeleteAccount { beneficiary_id: action.beneficiary_id }
1308 }
1309 Action::Delegate(action) => ActionView::Delegate {
1310 delegate_action: action.delegate_action,
1311 signature: action.signature,
1312 },
1313 Action::DeployGlobalContract(action) => {
1314 let code = hash(&action.code).as_ref().to_vec();
1315 match action.deploy_mode {
1316 GlobalContractDeployMode::CodeHash => ActionView::DeployGlobalContract { code },
1317 GlobalContractDeployMode::AccountId => {
1318 ActionView::DeployGlobalContractByAccountId { code }
1319 }
1320 }
1321 }
1322 Action::UseGlobalContract(action) => match action.contract_identifier {
1323 GlobalContractIdentifier::CodeHash(code_hash) => {
1324 ActionView::UseGlobalContract { code_hash }
1325 }
1326 GlobalContractIdentifier::AccountId(account_id) => {
1327 ActionView::UseGlobalContractByAccountId { account_id }
1328 }
1329 },
1330 }
1331 }
1332}
1333
1334impl TryFrom<ActionView> for Action {
1335 type Error = Box<dyn std::error::Error + Send + Sync>;
1336
1337 fn try_from(action_view: ActionView) -> Result<Self, Self::Error> {
1338 Ok(match action_view {
1339 ActionView::CreateAccount => Action::CreateAccount(CreateAccountAction {}),
1340 ActionView::DeployContract { code } => {
1341 Action::DeployContract(DeployContractAction { code })
1342 }
1343 ActionView::FunctionCall { method_name, args, gas, deposit } => {
1344 Action::FunctionCall(Box::new(FunctionCallAction {
1345 method_name,
1346 args: args.into(),
1347 gas,
1348 deposit,
1349 }))
1350 }
1351 ActionView::Transfer { deposit } => Action::Transfer(TransferAction { deposit }),
1352 ActionView::Stake { stake, public_key } => {
1353 Action::Stake(Box::new(StakeAction { stake, public_key }))
1354 }
1355 ActionView::AddKey { public_key, access_key } => {
1356 Action::AddKey(Box::new(AddKeyAction { public_key, access_key: access_key.into() }))
1357 }
1358 ActionView::DeleteKey { public_key } => {
1359 Action::DeleteKey(Box::new(DeleteKeyAction { public_key }))
1360 }
1361 ActionView::DeleteAccount { beneficiary_id } => {
1362 Action::DeleteAccount(DeleteAccountAction { beneficiary_id })
1363 }
1364 ActionView::Delegate { delegate_action, signature } => {
1365 Action::Delegate(Box::new(SignedDelegateAction { delegate_action, signature }))
1366 }
1367 ActionView::DeployGlobalContract { code } => {
1368 Action::DeployGlobalContract(DeployGlobalContractAction {
1369 code: code.into(),
1370 deploy_mode: GlobalContractDeployMode::CodeHash,
1371 })
1372 }
1373 ActionView::DeployGlobalContractByAccountId { code } => {
1374 Action::DeployGlobalContract(DeployGlobalContractAction {
1375 code: code.into(),
1376 deploy_mode: GlobalContractDeployMode::AccountId,
1377 })
1378 }
1379 ActionView::UseGlobalContract { code_hash } => {
1380 Action::UseGlobalContract(Box::new(UseGlobalContractAction {
1381 contract_identifier: GlobalContractIdentifier::CodeHash(code_hash),
1382 }))
1383 }
1384 ActionView::UseGlobalContractByAccountId { account_id } => {
1385 Action::UseGlobalContract(Box::new(UseGlobalContractAction {
1386 contract_identifier: GlobalContractIdentifier::AccountId(account_id),
1387 }))
1388 }
1389 })
1390 }
1391}
1392
1393#[derive(
1394 BorshSerialize,
1395 BorshDeserialize,
1396 Debug,
1397 PartialEq,
1398 Eq,
1399 Clone,
1400 serde::Serialize,
1401 serde::Deserialize,
1402)]
1403#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1404pub struct SignedTransactionView {
1405 pub signer_id: AccountId,
1406 pub public_key: PublicKey,
1407 pub nonce: Nonce,
1408 pub receiver_id: AccountId,
1409 pub actions: Vec<ActionView>,
1410 #[serde(default)]
1414 pub priority_fee: u64,
1415 pub signature: Signature,
1416 pub hash: CryptoHash,
1417}
1418
1419impl From<SignedTransaction> for SignedTransactionView {
1420 fn from(signed_tx: SignedTransaction) -> Self {
1421 let hash = signed_tx.get_hash();
1422 let transaction = signed_tx.transaction;
1423 let priority_fee = transaction.priority_fee().unwrap_or_default();
1424 SignedTransactionView {
1425 signer_id: transaction.signer_id().clone(),
1426 public_key: transaction.public_key().clone(),
1427 nonce: transaction.nonce(),
1428 receiver_id: transaction.receiver_id().clone(),
1429 actions: transaction.take_actions().into_iter().map(|action| action.into()).collect(),
1430 signature: signed_tx.signature,
1431 hash,
1432 priority_fee,
1433 }
1434 }
1435}
1436
1437#[serde_as]
1438#[derive(
1439 BorshSerialize,
1440 BorshDeserialize,
1441 serde::Serialize,
1442 serde::Deserialize,
1443 PartialEq,
1444 Eq,
1445 Clone,
1446 Default,
1447)]
1448#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1449pub enum FinalExecutionStatus {
1450 #[default]
1452 NotStarted,
1453 Started,
1455 Failure(TxExecutionError),
1457 SuccessValue(
1459 #[serde_as(as = "Base64")]
1460 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1461 Vec<u8>,
1462 ),
1463}
1464
1465impl fmt::Debug for FinalExecutionStatus {
1466 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1467 match self {
1468 FinalExecutionStatus::NotStarted => f.write_str("NotStarted"),
1469 FinalExecutionStatus::Started => f.write_str("Started"),
1470 FinalExecutionStatus::Failure(e) => f.write_fmt(format_args!("Failure({:?})", e)),
1471 FinalExecutionStatus::SuccessValue(v) => {
1472 f.write_fmt(format_args!("SuccessValue({})", AbbrBytes(v)))
1473 }
1474 }
1475 }
1476}
1477
1478#[derive(
1479 BorshSerialize,
1480 BorshDeserialize,
1481 Debug,
1482 PartialEq,
1483 Eq,
1484 Clone,
1485 serde::Serialize,
1486 serde::Deserialize,
1487)]
1488pub enum ServerError {
1489 TxExecutionError(TxExecutionError),
1490 Timeout,
1491 Closed,
1492}
1493
1494#[serde_as]
1495#[derive(
1496 BorshSerialize, BorshDeserialize, serde::Serialize, serde::Deserialize, PartialEq, Eq, Clone,
1497)]
1498#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1499pub enum ExecutionStatusView {
1500 Unknown,
1502 Failure(TxExecutionError),
1504 SuccessValue(
1506 #[serde_as(as = "Base64")]
1507 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1508 Vec<u8>,
1509 ),
1510 SuccessReceiptId(CryptoHash),
1513}
1514
1515impl fmt::Debug for ExecutionStatusView {
1516 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1517 match self {
1518 ExecutionStatusView::Unknown => f.write_str("Unknown"),
1519 ExecutionStatusView::Failure(e) => f.write_fmt(format_args!("Failure({:?})", e)),
1520 ExecutionStatusView::SuccessValue(v) => {
1521 f.write_fmt(format_args!("SuccessValue({})", AbbrBytes(v)))
1522 }
1523 ExecutionStatusView::SuccessReceiptId(receipt_id) => {
1524 f.write_fmt(format_args!("SuccessReceiptId({})", receipt_id))
1525 }
1526 }
1527 }
1528}
1529
1530impl From<ExecutionStatus> for ExecutionStatusView {
1531 fn from(outcome: ExecutionStatus) -> Self {
1532 match outcome {
1533 ExecutionStatus::Unknown => ExecutionStatusView::Unknown,
1534 ExecutionStatus::Failure(e) => ExecutionStatusView::Failure(e),
1535 ExecutionStatus::SuccessValue(v) => ExecutionStatusView::SuccessValue(v),
1536 ExecutionStatus::SuccessReceiptId(receipt_id) => {
1537 ExecutionStatusView::SuccessReceiptId(receipt_id)
1538 }
1539 }
1540 }
1541}
1542
1543#[derive(
1544 BorshSerialize,
1545 BorshDeserialize,
1546 PartialEq,
1547 Clone,
1548 Eq,
1549 Debug,
1550 serde::Serialize,
1551 serde::Deserialize,
1552)]
1553#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1554pub struct CostGasUsed {
1555 pub cost_category: String,
1556 pub cost: String,
1557 #[serde(with = "dec_format")]
1558 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1559 pub gas_used: Gas,
1560}
1561
1562#[derive(
1563 BorshSerialize,
1564 BorshDeserialize,
1565 PartialEq,
1566 Clone,
1567 Eq,
1568 Debug,
1569 serde::Serialize,
1570 serde::Deserialize,
1571)]
1572#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1573pub struct ExecutionMetadataView {
1574 pub version: u32,
1575 pub gas_profile: Option<Vec<CostGasUsed>>,
1576}
1577
1578impl Default for ExecutionMetadataView {
1579 fn default() -> Self {
1580 ExecutionMetadata::V1.into()
1581 }
1582}
1583
1584impl From<ExecutionMetadata> for ExecutionMetadataView {
1585 fn from(metadata: ExecutionMetadata) -> Self {
1586 let version = match metadata {
1587 ExecutionMetadata::V1 => 1,
1588 ExecutionMetadata::V2(_) => 2,
1589 ExecutionMetadata::V3(_) => 3,
1590 };
1591 let mut gas_profile = match metadata {
1592 ExecutionMetadata::V1 => None,
1593 ExecutionMetadata::V2(profile_data) => {
1594 let mut costs: Vec<CostGasUsed> = profile_data
1600 .legacy_action_costs()
1601 .into_iter()
1602 .filter(|&(_, gas)| gas > 0)
1603 .map(|(name, gas)| CostGasUsed::action(name.to_string(), gas))
1604 .collect();
1605
1606 costs.push(CostGasUsed::wasm_host(
1608 "WASM_INSTRUCTION".to_string(),
1609 profile_data.get_wasm_cost(),
1610 ));
1611
1612 for ext_cost in ExtCosts::iter() {
1614 costs.push(CostGasUsed::wasm_host(
1615 format!("{:?}", ext_cost).to_ascii_uppercase(),
1616 profile_data.get_ext_cost(ext_cost),
1617 ));
1618 }
1619
1620 Some(costs)
1621 }
1622 ExecutionMetadata::V3(profile) => {
1623 let mut costs: Vec<CostGasUsed> = ActionCosts::iter()
1626 .filter_map(|cost| {
1627 let gas_used = profile.get_action_cost(cost);
1628 (gas_used > 0).then(|| {
1629 CostGasUsed::action(
1630 format!("{:?}", cost).to_ascii_uppercase(),
1631 gas_used,
1632 )
1633 })
1634 })
1635 .collect();
1636
1637 let wasm_gas_used = profile.get_wasm_cost();
1639 if wasm_gas_used > 0 {
1640 costs.push(CostGasUsed::wasm_host(
1641 "WASM_INSTRUCTION".to_string(),
1642 wasm_gas_used,
1643 ));
1644 }
1645
1646 for ext_cost in ExtCosts::iter() {
1648 let gas_used = profile.get_ext_cost(ext_cost);
1649 if gas_used > 0 {
1650 costs.push(CostGasUsed::wasm_host(
1651 format!("{:?}", ext_cost).to_ascii_uppercase(),
1652 gas_used,
1653 ));
1654 }
1655 }
1656
1657 Some(costs)
1658 }
1659 };
1660 if let Some(ref mut costs) = gas_profile {
1661 costs.sort_by(|lhs, rhs| {
1668 lhs.cost_category.cmp(&rhs.cost_category).then_with(|| lhs.cost.cmp(&rhs.cost))
1669 });
1670 }
1671 ExecutionMetadataView { version, gas_profile }
1672 }
1673}
1674
1675impl CostGasUsed {
1676 pub fn action(cost: String, gas_used: Gas) -> Self {
1677 Self { cost_category: "ACTION_COST".to_string(), cost, gas_used }
1678 }
1679
1680 pub fn wasm_host(cost: String, gas_used: Gas) -> Self {
1681 Self { cost_category: "WASM_HOST_COST".to_string(), cost, gas_used }
1682 }
1683}
1684
1685#[derive(
1686 BorshSerialize,
1687 BorshDeserialize,
1688 Debug,
1689 Clone,
1690 PartialEq,
1691 Eq,
1692 serde::Serialize,
1693 serde::Deserialize,
1694)]
1695#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1696pub struct ExecutionOutcomeView {
1697 pub logs: Vec<String>,
1699 pub receipt_ids: Vec<CryptoHash>,
1701 pub gas_burnt: Gas,
1703 #[serde(with = "dec_format")]
1709 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1710 pub tokens_burnt: Balance,
1711 pub executor_id: AccountId,
1714 pub status: ExecutionStatusView,
1716 #[serde(default)]
1718 pub metadata: ExecutionMetadataView,
1719}
1720
1721impl From<ExecutionOutcome> for ExecutionOutcomeView {
1722 fn from(outcome: ExecutionOutcome) -> Self {
1723 Self {
1724 logs: outcome.logs,
1725 receipt_ids: outcome.receipt_ids,
1726 gas_burnt: outcome.gas_burnt,
1727 tokens_burnt: outcome.tokens_burnt,
1728 executor_id: outcome.executor_id,
1729 status: outcome.status.into(),
1730 metadata: outcome.metadata.into(),
1731 }
1732 }
1733}
1734
1735impl From<&ExecutionOutcomeView> for PartialExecutionOutcome {
1736 fn from(outcome: &ExecutionOutcomeView) -> Self {
1737 Self {
1738 receipt_ids: outcome.receipt_ids.clone(),
1739 gas_burnt: outcome.gas_burnt,
1740 tokens_burnt: outcome.tokens_burnt,
1741 executor_id: outcome.executor_id.clone(),
1742 status: outcome.status.clone().into(),
1743 }
1744 }
1745}
1746impl From<ExecutionStatusView> for PartialExecutionStatus {
1747 fn from(status: ExecutionStatusView) -> PartialExecutionStatus {
1748 match status {
1749 ExecutionStatusView::Unknown => PartialExecutionStatus::Unknown,
1750 ExecutionStatusView::Failure(_) => PartialExecutionStatus::Failure,
1751 ExecutionStatusView::SuccessValue(value) => PartialExecutionStatus::SuccessValue(value),
1752 ExecutionStatusView::SuccessReceiptId(id) => {
1753 PartialExecutionStatus::SuccessReceiptId(id)
1754 }
1755 }
1756 }
1757}
1758
1759impl ExecutionOutcomeView {
1760 pub fn to_hashes(&self, id: CryptoHash) -> Vec<CryptoHash> {
1762 let mut result = Vec::with_capacity(self.logs.len().saturating_add(2));
1763 result.push(id);
1764 result.push(CryptoHash::hash_borsh(&PartialExecutionOutcome::from(self)));
1765 result.extend(self.logs.iter().map(|log| hash(log.as_bytes())));
1766 result
1767 }
1768}
1769
1770#[cfg_attr(feature = "deepsize_feature", derive(deepsize::DeepSizeOf))]
1771#[derive(
1772 BorshSerialize,
1773 BorshDeserialize,
1774 Debug,
1775 PartialEq,
1776 Eq,
1777 Clone,
1778 serde::Serialize,
1779 serde::Deserialize,
1780)]
1781#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1782pub struct ExecutionOutcomeWithIdView {
1783 pub proof: MerklePath,
1784 pub block_hash: CryptoHash,
1785 pub id: CryptoHash,
1786 pub outcome: ExecutionOutcomeView,
1787}
1788
1789impl From<ExecutionOutcomeWithIdAndProof> for ExecutionOutcomeWithIdView {
1790 fn from(outcome_with_id_and_proof: ExecutionOutcomeWithIdAndProof) -> Self {
1791 Self {
1792 proof: outcome_with_id_and_proof.proof,
1793 block_hash: outcome_with_id_and_proof.block_hash,
1794 id: outcome_with_id_and_proof.outcome_with_id.id,
1795 outcome: outcome_with_id_and_proof.outcome_with_id.outcome.into(),
1796 }
1797 }
1798}
1799
1800impl ExecutionOutcomeWithIdView {
1801 pub fn to_hashes(&self) -> Vec<CryptoHash> {
1802 self.outcome.to_hashes(self.id)
1803 }
1804}
1805#[derive(Clone, Debug)]
1806pub struct TxStatusView {
1807 pub execution_outcome: Option<FinalExecutionOutcomeViewEnum>,
1808 pub status: TxExecutionStatus,
1809}
1810
1811#[derive(
1812 BorshSerialize,
1813 BorshDeserialize,
1814 serde::Serialize,
1815 serde::Deserialize,
1816 Clone,
1817 Debug,
1818 Default,
1819 Eq,
1820 PartialEq,
1821)]
1822#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1823#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1824pub enum TxExecutionStatus {
1825 None,
1827 Included,
1829 #[default]
1833 ExecutedOptimistic,
1834 IncludedFinal,
1836 Executed,
1840 Final,
1843}
1844
1845#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
1846#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1847#[serde(untagged)]
1848pub enum FinalExecutionOutcomeViewEnum {
1851 FinalExecutionOutcomeWithReceipt(FinalExecutionOutcomeWithReceiptView),
1852 FinalExecutionOutcome(FinalExecutionOutcomeView),
1853}
1854
1855impl FinalExecutionOutcomeViewEnum {
1856 pub fn into_outcome(self) -> FinalExecutionOutcomeView {
1857 match self {
1858 Self::FinalExecutionOutcome(outcome) => outcome,
1859 Self::FinalExecutionOutcomeWithReceipt(outcome) => outcome.final_outcome,
1860 }
1861 }
1862}
1863
1864impl TxStatusView {
1865 pub fn into_outcome(self) -> Option<FinalExecutionOutcomeView> {
1866 self.execution_outcome.map(|outcome| match outcome {
1867 FinalExecutionOutcomeViewEnum::FinalExecutionOutcome(outcome) => outcome,
1868 FinalExecutionOutcomeViewEnum::FinalExecutionOutcomeWithReceipt(outcome) => {
1869 outcome.final_outcome
1870 }
1871 })
1872 }
1873}
1874
1875#[derive(
1878 BorshSerialize, BorshDeserialize, serde::Serialize, serde::Deserialize, PartialEq, Eq, Clone,
1879)]
1880#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1881pub struct FinalExecutionOutcomeView {
1882 pub status: FinalExecutionStatus,
1888 pub transaction: SignedTransactionView,
1890 pub transaction_outcome: ExecutionOutcomeWithIdView,
1892 pub receipts_outcome: Vec<ExecutionOutcomeWithIdView>,
1894}
1895
1896impl fmt::Debug for FinalExecutionOutcomeView {
1897 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1898 f.debug_struct("FinalExecutionOutcome")
1899 .field("status", &self.status)
1900 .field("transaction", &self.transaction)
1901 .field("transaction_outcome", &self.transaction_outcome)
1902 .field("receipts_outcome", &Slice(&self.receipts_outcome))
1903 .finish()
1904 }
1905}
1906
1907#[derive(
1910 BorshSerialize,
1911 BorshDeserialize,
1912 PartialEq,
1913 Eq,
1914 Clone,
1915 Debug,
1916 serde::Serialize,
1917 serde::Deserialize,
1918)]
1919#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1920pub struct FinalExecutionOutcomeWithReceiptView {
1921 #[serde(flatten)]
1923 pub final_outcome: FinalExecutionOutcomeView,
1924 pub receipts: Vec<ReceiptView>,
1926}
1927
1928pub mod validator_stake_view {
1929 pub use super::ValidatorStakeViewV1;
1930 use crate::types::validator_stake::ValidatorStake;
1931 use borsh::{BorshDeserialize, BorshSerialize};
1932 use near_primitives_core::types::AccountId;
1933 use serde::Deserialize;
1934
1935 #[derive(
1936 BorshSerialize, BorshDeserialize, serde::Serialize, Deserialize, Debug, Clone, Eq, PartialEq,
1937 )]
1938 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1939 #[serde(tag = "validator_stake_struct_version")]
1940 pub enum ValidatorStakeView {
1941 V1(ValidatorStakeViewV1),
1942 }
1943
1944 impl ValidatorStakeView {
1945 pub fn into_validator_stake(self) -> ValidatorStake {
1946 self.into()
1947 }
1948
1949 #[inline]
1950 pub fn take_account_id(self) -> AccountId {
1951 match self {
1952 Self::V1(v1) => v1.account_id,
1953 }
1954 }
1955
1956 #[inline]
1957 pub fn account_id(&self) -> &AccountId {
1958 match self {
1959 Self::V1(v1) => &v1.account_id,
1960 }
1961 }
1962 }
1963
1964 impl From<ValidatorStake> for ValidatorStakeView {
1965 fn from(stake: ValidatorStake) -> Self {
1966 match stake {
1967 ValidatorStake::V1(v1) => Self::V1(ValidatorStakeViewV1 {
1968 account_id: v1.account_id,
1969 public_key: v1.public_key,
1970 stake: v1.stake,
1971 }),
1972 }
1973 }
1974 }
1975
1976 impl From<ValidatorStakeView> for ValidatorStake {
1977 fn from(view: ValidatorStakeView) -> Self {
1978 match view {
1979 ValidatorStakeView::V1(v1) => Self::new_v1(v1.account_id, v1.public_key, v1.stake),
1980 }
1981 }
1982 }
1983}
1984
1985#[derive(
1986 BorshSerialize,
1987 BorshDeserialize,
1988 Debug,
1989 Clone,
1990 Eq,
1991 PartialEq,
1992 serde::Serialize,
1993 serde::Deserialize,
1994)]
1995#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1996pub struct ValidatorStakeViewV1 {
1997 pub account_id: AccountId,
1998 pub public_key: PublicKey,
1999 #[serde(with = "dec_format")]
2000 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
2001 pub stake: Balance,
2002}
2003
2004#[derive(
2005 BorshSerialize,
2006 BorshDeserialize,
2007 Clone,
2008 Debug,
2009 PartialEq,
2010 Eq,
2011 serde::Serialize,
2012 serde::Deserialize,
2013)]
2014#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2015pub struct ReceiptView {
2016 pub predecessor_id: AccountId,
2017 pub receiver_id: AccountId,
2018 pub receipt_id: CryptoHash,
2019
2020 pub receipt: ReceiptEnumView,
2021 #[serde(default)]
2025 pub priority: u64,
2026}
2027
2028#[derive(
2029 BorshSerialize,
2030 BorshDeserialize,
2031 Clone,
2032 Debug,
2033 PartialEq,
2034 Eq,
2035 serde::Serialize,
2036 serde::Deserialize,
2037)]
2038#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2039pub struct DataReceiverView {
2040 pub data_id: CryptoHash,
2041 pub receiver_id: AccountId,
2042}
2043
2044#[serde_as]
2045#[derive(
2046 BorshSerialize,
2047 BorshDeserialize,
2048 Clone,
2049 Debug,
2050 PartialEq,
2051 Eq,
2052 serde::Serialize,
2053 serde::Deserialize,
2054)]
2055#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2056pub enum ReceiptEnumView {
2057 Action {
2058 signer_id: AccountId,
2059 signer_public_key: PublicKey,
2060 #[serde(with = "dec_format")]
2061 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
2062 gas_price: Balance,
2063 output_data_receivers: Vec<DataReceiverView>,
2064 input_data_ids: Vec<CryptoHash>,
2065 actions: Vec<ActionView>,
2066 #[serde(default = "default_is_promise")]
2067 is_promise_yield: bool,
2068 },
2069 Data {
2070 data_id: CryptoHash,
2071 #[serde_as(as = "Option<Base64>")]
2072 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
2073 data: Option<Vec<u8>>,
2074 #[serde(default = "default_is_promise")]
2075 is_promise_resume: bool,
2076 },
2077 GlobalContractDistribution {
2078 id: GlobalContractIdentifier,
2079 target_shard: ShardId,
2080 already_delivered_shards: Vec<ShardId>,
2081 #[serde_as(as = "Base64")]
2082 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
2083 code: Vec<u8>,
2084 },
2085}
2086
2087fn default_is_promise() -> bool {
2091 false
2092}
2093
2094impl From<Receipt> for ReceiptView {
2095 fn from(receipt: Receipt) -> Self {
2096 let is_promise_yield = matches!(receipt.receipt(), ReceiptEnum::PromiseYield(_));
2097 let is_promise_resume = matches!(receipt.receipt(), ReceiptEnum::PromiseResume(_));
2098 let priority = receipt.priority().value();
2099
2100 ReceiptView {
2101 predecessor_id: receipt.predecessor_id().clone(),
2102 receiver_id: receipt.receiver_id().clone(),
2103 receipt_id: *receipt.receipt_id(),
2104 receipt: match receipt.take_receipt() {
2105 ReceiptEnum::Action(action_receipt) | ReceiptEnum::PromiseYield(action_receipt) => {
2106 ReceiptEnumView::Action {
2107 signer_id: action_receipt.signer_id,
2108 signer_public_key: action_receipt.signer_public_key,
2109 gas_price: action_receipt.gas_price,
2110 output_data_receivers: action_receipt
2111 .output_data_receivers
2112 .into_iter()
2113 .map(|data_receiver| DataReceiverView {
2114 data_id: data_receiver.data_id,
2115 receiver_id: data_receiver.receiver_id,
2116 })
2117 .collect(),
2118 input_data_ids: action_receipt
2119 .input_data_ids
2120 .into_iter()
2121 .map(Into::into)
2122 .collect(),
2123 actions: action_receipt.actions.into_iter().map(Into::into).collect(),
2124 is_promise_yield,
2125 }
2126 }
2127 ReceiptEnum::Data(data_receipt) | ReceiptEnum::PromiseResume(data_receipt) => {
2128 ReceiptEnumView::Data {
2129 data_id: data_receipt.data_id,
2130 data: data_receipt.data,
2131 is_promise_resume,
2132 }
2133 }
2134 ReceiptEnum::GlobalContractDistribution(receipt) => {
2135 ReceiptEnumView::GlobalContractDistribution {
2136 id: receipt.id().clone(),
2137 target_shard: receipt.target_shard(),
2138 already_delivered_shards: receipt.already_delivered_shards().to_vec(),
2139 code: hash(receipt.code()).as_bytes().to_vec(),
2140 }
2141 }
2142 },
2143 priority,
2144 }
2145 }
2146}
2147
2148impl TryFrom<ReceiptView> for Receipt {
2149 type Error = Box<dyn std::error::Error + Send + Sync>;
2150
2151 fn try_from(receipt_view: ReceiptView) -> Result<Self, Self::Error> {
2152 Ok(Receipt::V1(ReceiptV1 {
2153 predecessor_id: receipt_view.predecessor_id,
2154 receiver_id: receipt_view.receiver_id,
2155 receipt_id: receipt_view.receipt_id,
2156 receipt: match receipt_view.receipt {
2157 ReceiptEnumView::Action {
2158 signer_id,
2159 signer_public_key,
2160 gas_price,
2161 output_data_receivers,
2162 input_data_ids,
2163 actions,
2164 is_promise_yield,
2165 } => {
2166 let action_receipt = ActionReceipt {
2167 signer_id,
2168 signer_public_key,
2169 gas_price,
2170 output_data_receivers: output_data_receivers
2171 .into_iter()
2172 .map(|data_receiver_view| DataReceiver {
2173 data_id: data_receiver_view.data_id,
2174 receiver_id: data_receiver_view.receiver_id,
2175 })
2176 .collect(),
2177 input_data_ids: input_data_ids.into_iter().map(Into::into).collect(),
2178 actions: actions
2179 .into_iter()
2180 .map(TryInto::try_into)
2181 .collect::<Result<Vec<_>, _>>()?,
2182 };
2183
2184 if is_promise_yield {
2185 ReceiptEnum::PromiseYield(action_receipt)
2186 } else {
2187 ReceiptEnum::Action(action_receipt)
2188 }
2189 }
2190 ReceiptEnumView::Data { data_id, data, is_promise_resume } => {
2191 let data_receipt = DataReceipt { data_id, data };
2192
2193 if is_promise_resume {
2194 ReceiptEnum::PromiseResume(data_receipt)
2195 } else {
2196 ReceiptEnum::Data(data_receipt)
2197 }
2198 }
2199 ReceiptEnumView::GlobalContractDistribution {
2200 id,
2201 target_shard,
2202 already_delivered_shards,
2203 code,
2204 } => {
2205 ReceiptEnum::GlobalContractDistribution(GlobalContractDistributionReceipt::new(
2206 id,
2207 target_shard,
2208 already_delivered_shards,
2209 code.into(),
2210 ))
2211 }
2212 },
2213 priority: receipt_view.priority,
2214 }))
2215 }
2216}
2217
2218#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone, ProtocolSchema)]
2220#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2221pub struct EpochValidatorInfo {
2222 pub current_validators: Vec<CurrentEpochValidatorInfo>,
2224 pub next_validators: Vec<NextEpochValidatorInfo>,
2226 pub current_fishermen: Vec<ValidatorStakeView>,
2228 pub next_fishermen: Vec<ValidatorStakeView>,
2230 pub current_proposals: Vec<ValidatorStakeView>,
2232 pub prev_epoch_kickout: Vec<ValidatorKickoutView>,
2234 pub epoch_start_height: BlockHeight,
2236 pub epoch_height: EpochHeight,
2238}
2239
2240#[derive(
2241 BorshSerialize,
2242 BorshDeserialize,
2243 Debug,
2244 PartialEq,
2245 Eq,
2246 Clone,
2247 serde::Serialize,
2248 serde::Deserialize,
2249 ProtocolSchema,
2250)]
2251#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2252pub struct ValidatorKickoutView {
2253 pub account_id: AccountId,
2254 pub reason: ValidatorKickoutReason,
2255}
2256
2257#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone, ProtocolSchema)]
2258#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2259pub struct CurrentEpochValidatorInfo {
2260 pub account_id: AccountId,
2261 pub public_key: PublicKey,
2262 pub is_slashed: bool,
2263 #[serde(with = "dec_format")]
2264 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
2265 pub stake: Balance,
2266 #[serde(rename = "shards")]
2268 pub shards_produced: Vec<ShardId>,
2269 pub num_produced_blocks: NumBlocks,
2270 pub num_expected_blocks: NumBlocks,
2271 #[serde(default)]
2272 pub num_produced_chunks: NumBlocks,
2273 #[serde(default)]
2274 pub num_expected_chunks: NumBlocks,
2275 #[serde(default)]
2277 pub num_produced_chunks_per_shard: Vec<NumBlocks>,
2278 #[serde(default)]
2281 pub num_expected_chunks_per_shard: Vec<NumBlocks>,
2282 #[serde(default)]
2283 pub num_produced_endorsements: NumBlocks,
2284 #[serde(default)]
2285 pub num_expected_endorsements: NumBlocks,
2286 #[serde(default)]
2287 pub num_produced_endorsements_per_shard: Vec<NumBlocks>,
2288 #[serde(default)]
2291 pub num_expected_endorsements_per_shard: Vec<NumBlocks>,
2292 pub shards_endorsed: Vec<ShardId>,
2294}
2295
2296#[derive(
2297 BorshSerialize,
2298 BorshDeserialize,
2299 Debug,
2300 PartialEq,
2301 Eq,
2302 Clone,
2303 serde::Serialize,
2304 serde::Deserialize,
2305 ProtocolSchema,
2306)]
2307#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2308pub struct NextEpochValidatorInfo {
2309 pub account_id: AccountId,
2310 pub public_key: PublicKey,
2311 #[serde(with = "dec_format")]
2312 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
2313 pub stake: Balance,
2314 pub shards: Vec<ShardId>,
2315}
2316
2317#[derive(
2318 PartialEq,
2319 Eq,
2320 Debug,
2321 Clone,
2322 BorshDeserialize,
2323 BorshSerialize,
2324 serde::Serialize,
2325 serde::Deserialize,
2326)]
2327#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2328pub struct LightClientBlockView {
2329 pub prev_block_hash: CryptoHash,
2330 pub next_block_inner_hash: CryptoHash,
2331 pub inner_lite: BlockHeaderInnerLiteView,
2332 pub inner_rest_hash: CryptoHash,
2333 pub next_bps: Option<Vec<ValidatorStakeView>>,
2334 pub approvals_after_next: Vec<Option<Box<Signature>>>,
2335}
2336
2337#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, BorshDeserialize, BorshSerialize)]
2338#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2339pub struct LightClientBlockLiteView {
2340 pub prev_block_hash: CryptoHash,
2341 pub inner_rest_hash: CryptoHash,
2342 pub inner_lite: BlockHeaderInnerLiteView,
2343}
2344
2345impl From<BlockHeader> for LightClientBlockLiteView {
2346 fn from(header: BlockHeader) -> Self {
2347 Self {
2348 prev_block_hash: *header.prev_hash(),
2349 inner_rest_hash: hash(&header.inner_rest_bytes()),
2350 inner_lite: header.into(),
2351 }
2352 }
2353}
2354impl LightClientBlockLiteView {
2355 pub fn hash(&self) -> CryptoHash {
2356 let block_header_inner_lite: BlockHeaderInnerLite = self.inner_lite.clone().into();
2357 combine_hash(
2358 &combine_hash(
2359 &hash(&borsh::to_vec(&block_header_inner_lite).unwrap()),
2360 &self.inner_rest_hash,
2361 ),
2362 &self.prev_block_hash,
2363 )
2364 }
2365}
2366
2367#[derive(serde::Serialize, serde::Deserialize, Debug)]
2368#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2369pub struct GasPriceView {
2370 #[serde(with = "dec_format")]
2371 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
2372 pub gas_price: Balance,
2373}
2374
2375#[derive(Debug, serde::Serialize, serde::Deserialize)]
2380#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2381#[serde(tag = "changes_type", rename_all = "snake_case")]
2382pub enum StateChangesRequestView {
2383 AccountChanges {
2384 account_ids: Vec<AccountId>,
2385 },
2386 SingleAccessKeyChanges {
2387 keys: Vec<AccountWithPublicKey>,
2388 },
2389 AllAccessKeyChanges {
2390 account_ids: Vec<AccountId>,
2391 },
2392 ContractCodeChanges {
2393 account_ids: Vec<AccountId>,
2394 },
2395 DataChanges {
2396 account_ids: Vec<AccountId>,
2397 #[serde(rename = "key_prefix_base64")]
2398 key_prefix: StoreKey,
2399 },
2400}
2401
2402impl From<StateChangesRequestView> for StateChangesRequest {
2403 fn from(request: StateChangesRequestView) -> Self {
2404 match request {
2405 StateChangesRequestView::AccountChanges { account_ids } => {
2406 Self::AccountChanges { account_ids }
2407 }
2408 StateChangesRequestView::SingleAccessKeyChanges { keys } => {
2409 Self::SingleAccessKeyChanges { keys }
2410 }
2411 StateChangesRequestView::AllAccessKeyChanges { account_ids } => {
2412 Self::AllAccessKeyChanges { account_ids }
2413 }
2414 StateChangesRequestView::ContractCodeChanges { account_ids } => {
2415 Self::ContractCodeChanges { account_ids }
2416 }
2417 StateChangesRequestView::DataChanges { account_ids, key_prefix } => {
2418 Self::DataChanges { account_ids, key_prefix }
2419 }
2420 }
2421 }
2422}
2423
2424#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
2429#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2430#[serde(rename_all = "snake_case", tag = "type")]
2431pub enum StateChangeKindView {
2432 AccountTouched { account_id: AccountId },
2433 AccessKeyTouched { account_id: AccountId },
2434 DataTouched { account_id: AccountId },
2435 ContractCodeTouched { account_id: AccountId },
2436}
2437
2438impl From<StateChangeKind> for StateChangeKindView {
2439 fn from(state_change_kind: StateChangeKind) -> Self {
2440 match state_change_kind {
2441 StateChangeKind::AccountTouched { account_id } => Self::AccountTouched { account_id },
2442 StateChangeKind::AccessKeyTouched { account_id } => {
2443 Self::AccessKeyTouched { account_id }
2444 }
2445 StateChangeKind::DataTouched { account_id } => Self::DataTouched { account_id },
2446 StateChangeKind::ContractCodeTouched { account_id } => {
2447 Self::ContractCodeTouched { account_id }
2448 }
2449 }
2450 }
2451}
2452
2453pub type StateChangesKindsView = Vec<StateChangeKindView>;
2454
2455#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
2457#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2458#[serde(rename_all = "snake_case", tag = "type")]
2459pub enum StateChangeCauseView {
2460 NotWritableToDisk,
2461 InitialState,
2462 TransactionProcessing { tx_hash: CryptoHash },
2463 ActionReceiptProcessingStarted { receipt_hash: CryptoHash },
2464 ActionReceiptGasReward { receipt_hash: CryptoHash },
2465 ReceiptProcessing { receipt_hash: CryptoHash },
2466 PostponedReceipt { receipt_hash: CryptoHash },
2467 UpdatedDelayedReceipts,
2468 ValidatorAccountsUpdate,
2469 Migration,
2470 BandwidthSchedulerStateUpdate,
2471}
2472
2473impl From<StateChangeCause> for StateChangeCauseView {
2474 fn from(state_change_cause: StateChangeCause) -> Self {
2475 match state_change_cause {
2476 StateChangeCause::NotWritableToDisk => Self::NotWritableToDisk,
2477 StateChangeCause::InitialState => Self::InitialState,
2478 StateChangeCause::TransactionProcessing { tx_hash } => {
2479 Self::TransactionProcessing { tx_hash }
2480 }
2481 StateChangeCause::ActionReceiptProcessingStarted { receipt_hash } => {
2482 Self::ActionReceiptProcessingStarted { receipt_hash }
2483 }
2484 StateChangeCause::ActionReceiptGasReward { receipt_hash } => {
2485 Self::ActionReceiptGasReward { receipt_hash }
2486 }
2487 StateChangeCause::ReceiptProcessing { receipt_hash } => {
2488 Self::ReceiptProcessing { receipt_hash }
2489 }
2490 StateChangeCause::PostponedReceipt { receipt_hash } => {
2491 Self::PostponedReceipt { receipt_hash }
2492 }
2493 StateChangeCause::UpdatedDelayedReceipts => Self::UpdatedDelayedReceipts,
2494 StateChangeCause::ValidatorAccountsUpdate => Self::ValidatorAccountsUpdate,
2495 StateChangeCause::Migration => Self::Migration,
2496 StateChangeCause::_UnusedReshardingV2 => Self::BandwidthSchedulerStateUpdate,
2503 StateChangeCause::BandwidthSchedulerStateUpdate => Self::BandwidthSchedulerStateUpdate,
2504 }
2505 }
2506}
2507
2508#[serde_as]
2509#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
2510#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2511#[serde(rename_all = "snake_case", tag = "type", content = "change")]
2512pub enum StateChangeValueView {
2513 AccountUpdate {
2514 account_id: AccountId,
2515 #[serde(flatten)]
2516 account: AccountView,
2517 },
2518 AccountDeletion {
2519 account_id: AccountId,
2520 },
2521 AccessKeyUpdate {
2522 account_id: AccountId,
2523 public_key: PublicKey,
2524 access_key: AccessKeyView,
2525 },
2526 AccessKeyDeletion {
2527 account_id: AccountId,
2528 public_key: PublicKey,
2529 },
2530 DataUpdate {
2531 account_id: AccountId,
2532 #[serde(rename = "key_base64")]
2533 key: StoreKey,
2534 #[serde(rename = "value_base64")]
2535 value: StoreValue,
2536 },
2537 DataDeletion {
2538 account_id: AccountId,
2539 #[serde(rename = "key_base64")]
2540 key: StoreKey,
2541 },
2542 ContractCodeUpdate {
2543 account_id: AccountId,
2544 #[serde(rename = "code_base64")]
2545 #[serde_as(as = "Base64")]
2546 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
2547 code: Vec<u8>,
2548 },
2549 ContractCodeDeletion {
2550 account_id: AccountId,
2551 },
2552}
2553
2554impl From<StateChangeValue> for StateChangeValueView {
2555 fn from(state_change: StateChangeValue) -> Self {
2556 match state_change {
2557 StateChangeValue::AccountUpdate { account_id, account } => {
2558 Self::AccountUpdate { account_id, account: account.into() }
2559 }
2560 StateChangeValue::AccountDeletion { account_id } => {
2561 Self::AccountDeletion { account_id }
2562 }
2563 StateChangeValue::AccessKeyUpdate { account_id, public_key, access_key } => {
2564 Self::AccessKeyUpdate { account_id, public_key, access_key: access_key.into() }
2565 }
2566 StateChangeValue::AccessKeyDeletion { account_id, public_key } => {
2567 Self::AccessKeyDeletion { account_id, public_key }
2568 }
2569 StateChangeValue::DataUpdate { account_id, key, value } => {
2570 Self::DataUpdate { account_id, key, value }
2571 }
2572 StateChangeValue::DataDeletion { account_id, key } => {
2573 Self::DataDeletion { account_id, key }
2574 }
2575 StateChangeValue::ContractCodeUpdate { account_id, code } => {
2576 Self::ContractCodeUpdate { account_id, code }
2577 }
2578 StateChangeValue::ContractCodeDeletion { account_id } => {
2579 Self::ContractCodeDeletion { account_id }
2580 }
2581 }
2582 }
2583}
2584
2585#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
2586#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2587pub struct StateChangeWithCauseView {
2588 pub cause: StateChangeCauseView,
2589 #[serde(flatten)]
2590 pub value: StateChangeValueView,
2591}
2592
2593impl From<StateChangeWithCause> for StateChangeWithCauseView {
2594 fn from(state_change_with_cause: StateChangeWithCause) -> Self {
2595 let StateChangeWithCause { cause, value } = state_change_with_cause;
2596 Self { cause: cause.into(), value: value.into() }
2597 }
2598}
2599
2600pub type StateChangesView = Vec<StateChangeWithCauseView>;
2601
2602pub type MaintenanceWindowsView = Vec<Range<BlockHeight>>;
2604
2605#[derive(serde::Serialize, serde::Deserialize, Debug)]
2607#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2608pub struct SplitStorageInfoView {
2609 pub head_height: Option<BlockHeight>,
2610 pub final_head_height: Option<BlockHeight>,
2611 pub cold_head_height: Option<BlockHeight>,
2612
2613 pub hot_db_kind: Option<String>,
2614}
2615
2616#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
2617#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2618pub struct CongestionInfoView {
2619 #[serde(with = "dec_format")]
2620 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
2621 pub delayed_receipts_gas: u128,
2622
2623 #[serde(with = "dec_format")]
2624 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
2625 pub buffered_receipts_gas: u128,
2626
2627 pub receipt_bytes: u64,
2628
2629 pub allowed_shard: u16,
2630}
2631
2632impl From<CongestionInfo> for CongestionInfoView {
2633 fn from(congestion_info: CongestionInfo) -> Self {
2634 match congestion_info {
2635 CongestionInfo::V1(congestion_info) => congestion_info.into(),
2636 }
2637 }
2638}
2639
2640impl From<CongestionInfoV1> for CongestionInfoView {
2641 fn from(congestion_info: CongestionInfoV1) -> Self {
2642 Self {
2643 delayed_receipts_gas: congestion_info.delayed_receipts_gas,
2644 buffered_receipts_gas: congestion_info.buffered_receipts_gas,
2645 receipt_bytes: congestion_info.receipt_bytes,
2646 allowed_shard: congestion_info.allowed_shard,
2647 }
2648 }
2649}
2650
2651impl From<CongestionInfoView> for CongestionInfo {
2652 fn from(congestion_info: CongestionInfoView) -> Self {
2653 CongestionInfo::V1(CongestionInfoV1 {
2654 delayed_receipts_gas: congestion_info.delayed_receipts_gas,
2655 buffered_receipts_gas: congestion_info.buffered_receipts_gas,
2656 receipt_bytes: congestion_info.receipt_bytes,
2657 allowed_shard: congestion_info.allowed_shard,
2658 })
2659 }
2660}
2661
2662impl CongestionInfoView {
2663 pub fn congestion_level(&self, config_view: CongestionControlConfigView) -> f64 {
2664 let congestion_config = CongestionControlConfig::from(config_view);
2665 CongestionInfo::from(self.clone()).localized_congestion_level(&congestion_config)
2674 }
2675}
2676
2677#[cfg(test)]
2678#[cfg(not(feature = "nightly"))]
2679mod tests {
2680 use super::{ExecutionMetadataView, FinalExecutionOutcomeViewEnum};
2681 use crate::profile_data_v2::ProfileDataV2;
2682 use crate::profile_data_v3::ProfileDataV3;
2683 use crate::transaction::ExecutionMetadata;
2684
2685 #[test]
2688 fn test_runtime_config_view() {
2689 use near_parameters::{RuntimeConfig, RuntimeConfigStore, RuntimeConfigView};
2690 use near_primitives_core::version::PROTOCOL_VERSION;
2691
2692 let config_store = RuntimeConfigStore::new(None);
2693 let config = config_store.get_config(PROTOCOL_VERSION);
2694 let view = RuntimeConfigView::from(RuntimeConfig::clone(config));
2695 insta::assert_json_snapshot!(&view, { ".wasm_config.vm_kind" => "<REDACTED>"});
2696 }
2697
2698 #[test]
2700 fn test_exec_metadata_v1_view() {
2701 let metadata = ExecutionMetadata::V1;
2702 let view = ExecutionMetadataView::from(metadata);
2703 insta::assert_json_snapshot!(view);
2704 }
2705
2706 #[test]
2708 fn test_exec_metadata_v2_view() {
2709 let metadata = ExecutionMetadata::V2(ProfileDataV2::test());
2710 let view = ExecutionMetadataView::from(metadata);
2711 insta::assert_json_snapshot!(view);
2712 }
2713
2714 #[test]
2716 fn test_exec_metadata_v3_view() {
2717 let metadata = ExecutionMetadata::V3(ProfileDataV3::test().into());
2718 let view = ExecutionMetadataView::from(metadata);
2719 insta::assert_json_snapshot!(view);
2720 }
2721
2722 #[test]
2723 fn test_deserialize_execution_outcome_with_receipt() {
2724 let json = r#"{"final_execution_status":"FINAL","receipts":[{"predecessor_id":"system","priority":0,"receipt":{"Action":{"actions":[{"Transfer":{"deposit":"17930928991009412192152"}}],"gas_price":"0","input_data_ids":[],"is_promise_yield":false,"output_data_receivers":[],"signer_id":"btc-client.testnet","signer_public_key":"ed25519:HM7ax8jJf41JozvanXepzhtD45AeRFcwJQCuLXFuDkjA"}},"receipt_id":"8ZD92cLpoCEU46hPGFfk3VqZpU8s6DoQhZ4pCMqWwDT6","receiver_id":"btc-client.testnet"}],"receipts_outcome":[{"block_hash":"9SP8Y3sVADWNN5QoEB5CsvPUE5HT4o8YfBaCnhLss87K","id":"e2XGEosf843XMiCJHvZufvHKyw419ZYibDBdVJQr9cB","outcome":{"executor_id":"btc-client.testnet","gas_burnt":2906160054161,"logs":["Block hash: 0000000000000000ee617846a3e081ae2f30091451442e1b5fb027d8eba09b3a","Saving to mainchain"],"metadata":{"gas_profile":[{"cost":"BASE","cost_category":"WASM_HOST_COST","gas_used":"8472579552"},{"cost":"CONTRACT_LOADING_BASE","cost_category":"WASM_HOST_COST","gas_used":"35445963"},{"cost":"CONTRACT_LOADING_BYTES","cost_category":"WASM_HOST_COST","gas_used":"413841688515"},{"cost":"LOG_BASE","cost_category":"WASM_HOST_COST","gas_used":"7086626100"},{"cost":"LOG_BYTE","cost_category":"WASM_HOST_COST","gas_used":"1253885145"},{"cost":"READ_CACHED_TRIE_NODE","cost_category":"WASM_HOST_COST","gas_used":"102600000000"},{"cost":"READ_MEMORY_BASE","cost_category":"WASM_HOST_COST","gas_used":"54807127200"},{"cost":"READ_MEMORY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"2873807748"},{"cost":"READ_REGISTER_BASE","cost_category":"WASM_HOST_COST","gas_used":"22654486674"},{"cost":"READ_REGISTER_BYTE","cost_category":"WASM_HOST_COST","gas_used":"51252240"},{"cost":"SHA256_BASE","cost_category":"WASM_HOST_COST","gas_used":"13622910750"},{"cost":"SHA256_BYTE","cost_category":"WASM_HOST_COST","gas_used":"3400546491"},{"cost":"STORAGE_READ_BASE","cost_category":"WASM_HOST_COST","gas_used":"450854766000"},{"cost":"STORAGE_READ_KEY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"4952405280"},{"cost":"STORAGE_READ_VALUE_BYTE","cost_category":"WASM_HOST_COST","gas_used":"1806743610"},{"cost":"STORAGE_WRITE_BASE","cost_category":"WASM_HOST_COST","gas_used":"256786944000"},{"cost":"STORAGE_WRITE_EVICTED_BYTE","cost_category":"WASM_HOST_COST","gas_used":"2826323016"},{"cost":"STORAGE_WRITE_KEY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"5638629360"},{"cost":"STORAGE_WRITE_VALUE_BYTE","cost_category":"WASM_HOST_COST","gas_used":"8685190920"},{"cost":"TOUCHING_TRIE_NODE","cost_category":"WASM_HOST_COST","gas_used":"434752810002"},{"cost":"UTF8_DECODING_BASE","cost_category":"WASM_HOST_COST","gas_used":"6223558122"},{"cost":"UTF8_DECODING_BYTE","cost_category":"WASM_HOST_COST","gas_used":"27700145505"},{"cost":"WASM_INSTRUCTION","cost_category":"WASM_HOST_COST","gas_used":"126491330196"},{"cost":"WRITE_MEMORY_BASE","cost_category":"WASM_HOST_COST","gas_used":"28037948610"},{"cost":"WRITE_MEMORY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"1459941792"},{"cost":"WRITE_REGISTER_BASE","cost_category":"WASM_HOST_COST","gas_used":"28655224860"},{"cost":"WRITE_REGISTER_BYTE","cost_category":"WASM_HOST_COST","gas_used":"2311350912"}],"version":3},"receipt_ids":["8ZD92cLpoCEU46hPGFfk3VqZpU8s6DoQhZ4pCMqWwDT6"],"status":{"SuccessValue":""},"tokens_burnt":"290616005416100000000"},"proof":[{"direction":"Left","hash":"BoQHueiPH9e4C7fkxouV4tFpGZ4hK5fJhKQnPBWwPazS"},{"direction":"Right","hash":"Ayxj8iVFTJMzZa7estoTtuBKJaUNhoipaaM7WmTjkkiS"}]},{"block_hash":"3rEx3xmgLCRgUfSgueD71YNrJYQYNvhtkXaqVQxdmj4U","id":"8ZD92cLpoCEU46hPGFfk3VqZpU8s6DoQhZ4pCMqWwDT6","outcome":{"executor_id":"btc-client.testnet","gas_burnt":223182562500,"logs":[],"metadata":{"gas_profile":[],"version":3},"receipt_ids":[],"status":{"SuccessValue":""},"tokens_burnt":"0"},"proof":[{"direction":"Right","hash":"8yEwg14D2GyyLNnJMxdSLDJKyrKShMAL3zTnf9YpQyPW"},{"direction":"Right","hash":"2UK7BfpHf9fCCsvmfHktDfz6Rh8sFihhN6cuTU3R4BBA"}]}],"status":{"SuccessValue":""},"transaction":{"actions":[{"FunctionCall":{"args":"AQAAAABA0CKoR96WKs+KPP6zPl0flT6XC91eR3uAUgwNAAAAAAAAAAzcZU0cipmejc+wGqnRJchd5uM6qRJM5Oojp3FrkJ2HVmGyZsnyFBlkvks8","deposit":"0","gas":100000000000000,"method_name":"submit_blocks"}}],"hash":"GMUCDLHFJVvmZYXmPf9QeUVAt9r9hXcQP1yL5emPFnvx","nonce":170437577001422,"priority_fee":0,"public_key":"ed25519:HM7ax8jJf41JozvanXepzhtD45AeRFcwJQCuLXFuDkjA","receiver_id":"btc-client.testnet","signature":"ed25519:2Qe3ccPSdzPddk764vm5jt4yXcvXgYQz3WzGF3oXpZLuaRa6ggpD131nSSy3FRVPquCvxYqgMGtdum8TKX3dVqNk","signer_id":"btc-client.testnet"},"transaction_outcome":{"block_hash":"9SP8Y3sVADWNN5QoEB5CsvPUE5HT4o8YfBaCnhLss87K","id":"GMUCDLHFJVvmZYXmPf9QeUVAt9r9hXcQP1yL5emPFnvx","outcome":{"executor_id":"btc-client.testnet","gas_burnt":308276385598,"logs":[],"metadata":{"gas_profile":null,"version":1},"receipt_ids":["e2XGEosf843XMiCJHvZufvHKyw419ZYibDBdVJQr9cB"],"status":{"SuccessReceiptId":"e2XGEosf843XMiCJHvZufvHKyw419ZYibDBdVJQr9cB"},"tokens_burnt":"30827638559800000000"},"proof":[{"direction":"Right","hash":"HDgWEk2okmDdAFAVf6ffxGBH6F6vdLM1X3H5Fmaafe4S"},{"direction":"Right","hash":"Ayxj8iVFTJMzZa7estoTtuBKJaUNhoipaaM7WmTjkkiS"}]}}"#;
2727 let view: FinalExecutionOutcomeViewEnum = serde_json::from_str(json).unwrap();
2728 assert!(matches!(view, FinalExecutionOutcomeViewEnum::FinalExecutionOutcomeWithReceipt(_)));
2729 }
2730
2731 #[test]
2732 fn test_deserialize_execution_outcome_without_receipt() {
2733 let json = r#"{"final_execution_status":"FINAL","receipts_outcome":[{"block_hash":"9SP8Y3sVADWNN5QoEB5CsvPUE5HT4o8YfBaCnhLss87K","id":"e2XGEosf843XMiCJHvZufvHKyw419ZYibDBdVJQr9cB","outcome":{"executor_id":"btc-client.testnet","gas_burnt":2906160054161,"logs":["Block hash: 0000000000000000ee617846a3e081ae2f30091451442e1b5fb027d8eba09b3a","Saving to mainchain"],"metadata":{"gas_profile":[{"cost":"BASE","cost_category":"WASM_HOST_COST","gas_used":"8472579552"},{"cost":"CONTRACT_LOADING_BASE","cost_category":"WASM_HOST_COST","gas_used":"35445963"},{"cost":"CONTRACT_LOADING_BYTES","cost_category":"WASM_HOST_COST","gas_used":"413841688515"},{"cost":"LOG_BASE","cost_category":"WASM_HOST_COST","gas_used":"7086626100"},{"cost":"LOG_BYTE","cost_category":"WASM_HOST_COST","gas_used":"1253885145"},{"cost":"READ_CACHED_TRIE_NODE","cost_category":"WASM_HOST_COST","gas_used":"102600000000"},{"cost":"READ_MEMORY_BASE","cost_category":"WASM_HOST_COST","gas_used":"54807127200"},{"cost":"READ_MEMORY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"2873807748"},{"cost":"READ_REGISTER_BASE","cost_category":"WASM_HOST_COST","gas_used":"22654486674"},{"cost":"READ_REGISTER_BYTE","cost_category":"WASM_HOST_COST","gas_used":"51252240"},{"cost":"SHA256_BASE","cost_category":"WASM_HOST_COST","gas_used":"13622910750"},{"cost":"SHA256_BYTE","cost_category":"WASM_HOST_COST","gas_used":"3400546491"},{"cost":"STORAGE_READ_BASE","cost_category":"WASM_HOST_COST","gas_used":"450854766000"},{"cost":"STORAGE_READ_KEY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"4952405280"},{"cost":"STORAGE_READ_VALUE_BYTE","cost_category":"WASM_HOST_COST","gas_used":"1806743610"},{"cost":"STORAGE_WRITE_BASE","cost_category":"WASM_HOST_COST","gas_used":"256786944000"},{"cost":"STORAGE_WRITE_EVICTED_BYTE","cost_category":"WASM_HOST_COST","gas_used":"2826323016"},{"cost":"STORAGE_WRITE_KEY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"5638629360"},{"cost":"STORAGE_WRITE_VALUE_BYTE","cost_category":"WASM_HOST_COST","gas_used":"8685190920"},{"cost":"TOUCHING_TRIE_NODE","cost_category":"WASM_HOST_COST","gas_used":"434752810002"},{"cost":"UTF8_DECODING_BASE","cost_category":"WASM_HOST_COST","gas_used":"6223558122"},{"cost":"UTF8_DECODING_BYTE","cost_category":"WASM_HOST_COST","gas_used":"27700145505"},{"cost":"WASM_INSTRUCTION","cost_category":"WASM_HOST_COST","gas_used":"126491330196"},{"cost":"WRITE_MEMORY_BASE","cost_category":"WASM_HOST_COST","gas_used":"28037948610"},{"cost":"WRITE_MEMORY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"1459941792"},{"cost":"WRITE_REGISTER_BASE","cost_category":"WASM_HOST_COST","gas_used":"28655224860"},{"cost":"WRITE_REGISTER_BYTE","cost_category":"WASM_HOST_COST","gas_used":"2311350912"}],"version":3},"receipt_ids":["8ZD92cLpoCEU46hPGFfk3VqZpU8s6DoQhZ4pCMqWwDT6"],"status":{"SuccessValue":""},"tokens_burnt":"290616005416100000000"},"proof":[{"direction":"Left","hash":"BoQHueiPH9e4C7fkxouV4tFpGZ4hK5fJhKQnPBWwPazS"},{"direction":"Right","hash":"Ayxj8iVFTJMzZa7estoTtuBKJaUNhoipaaM7WmTjkkiS"}]},{"block_hash":"3rEx3xmgLCRgUfSgueD71YNrJYQYNvhtkXaqVQxdmj4U","id":"8ZD92cLpoCEU46hPGFfk3VqZpU8s6DoQhZ4pCMqWwDT6","outcome":{"executor_id":"btc-client.testnet","gas_burnt":223182562500,"logs":[],"metadata":{"gas_profile":[],"version":3},"receipt_ids":[],"status":{"SuccessValue":""},"tokens_burnt":"0"},"proof":[{"direction":"Right","hash":"8yEwg14D2GyyLNnJMxdSLDJKyrKShMAL3zTnf9YpQyPW"},{"direction":"Right","hash":"2UK7BfpHf9fCCsvmfHktDfz6Rh8sFihhN6cuTU3R4BBA"}]}],"status":{"SuccessValue":""},"transaction":{"actions":[{"FunctionCall":{"args":"AQAAAABA0CKoR96WKs+KPP6zPl0flT6XC91eR3uAUgwNAAAAAAAAAAzcZU0cipmejc+wGqnRJchd5uM6qRJM5Oojp3FrkJ2HVmGyZsnyFBlkvks8","deposit":"0","gas":100000000000000,"method_name":"submit_blocks"}}],"hash":"GMUCDLHFJVvmZYXmPf9QeUVAt9r9hXcQP1yL5emPFnvx","nonce":170437577001422,"priority_fee":0,"public_key":"ed25519:HM7ax8jJf41JozvanXepzhtD45AeRFcwJQCuLXFuDkjA","receiver_id":"btc-client.testnet","signature":"ed25519:2Qe3ccPSdzPddk764vm5jt4yXcvXgYQz3WzGF3oXpZLuaRa6ggpD131nSSy3FRVPquCvxYqgMGtdum8TKX3dVqNk","signer_id":"btc-client.testnet"},"transaction_outcome":{"block_hash":"9SP8Y3sVADWNN5QoEB5CsvPUE5HT4o8YfBaCnhLss87K","id":"GMUCDLHFJVvmZYXmPf9QeUVAt9r9hXcQP1yL5emPFnvx","outcome":{"executor_id":"btc-client.testnet","gas_burnt":308276385598,"logs":[],"metadata":{"gas_profile":null,"version":1},"receipt_ids":["e2XGEosf843XMiCJHvZufvHKyw419ZYibDBdVJQr9cB"],"status":{"SuccessReceiptId":"e2XGEosf843XMiCJHvZufvHKyw419ZYibDBdVJQr9cB"},"tokens_burnt":"30827638559800000000"},"proof":[{"direction":"Right","hash":"HDgWEk2okmDdAFAVf6ffxGBH6F6vdLM1X3H5Fmaafe4S"},{"direction":"Right","hash":"Ayxj8iVFTJMzZa7estoTtuBKJaUNhoipaaM7WmTjkkiS"}]}}"#;
2735 let view: FinalExecutionOutcomeViewEnum = serde_json::from_str(json).unwrap();
2736 assert!(matches!(view, FinalExecutionOutcomeViewEnum::FinalExecutionOutcome(_)));
2737 }
2738}