1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use crate::{
api::{
generated::api::runtime_types::{frame_system::AccountInfo, pallet_balances::AccountData},
Api,
},
result::Result,
};
use subxt::{sp_core::crypto::Ss58Codec, sp_runtime::AccountId32};
impl Api {
pub async fn info(&self, address: &str) -> Result<AccountInfo<u32, AccountData<u128>>> {
Ok(self
.storage()
.system()
.account(&AccountId32::from_ss58check(address)?, None)
.await?)
}
pub async fn get_balance(&self, address: &str) -> Result<u128> {
Ok(self
.storage()
.system()
.account(&AccountId32::from_ss58check(address)?, None)
.await?
.data
.free)
}
}
mod gear {
use crate::{
api::{
generated::api::{
gear_messenger,
runtime_types::{
gear_common::{storage::primitives::Interval, ActiveProgram},
gear_core::{
code::InstrumentedCode, ids::CodeId, memory::PageNumber,
message::stored::StoredMessage,
},
},
},
types, utils, Api,
},
result::{Error, Result},
};
use hex::ToHex;
use parity_scale_codec::Decode;
use std::collections::HashMap;
use subxt::{
sp_core::{storage::StorageKey, H256},
sp_runtime::AccountId32,
storage::StorageKeyPrefix,
StorageEntryKey, StorageMapKey,
};
impl Api {
pub async fn code_storage(&self, code_hash: [u8; 32]) -> Result<Option<InstrumentedCode>> {
Ok(self
.storage()
.gear_program()
.code_storage(&CodeId(code_hash), None)
.await?)
}
pub async fn gprog(&self, pid: H256) -> Result<ActiveProgram> {
let bytes = self
.client
.storage()
.fetch_raw(StorageKey(utils::program_key(pid)), None)
.await?
.ok_or_else(|| Error::ProgramNotFound(pid.encode_hex()))?;
match types::Program::decode(&mut bytes.0.as_ref())? {
types::Program::Active(p) => Ok(p),
types::Program::Terminated => Err(Error::ProgramTerminated),
}
}
pub async fn gpages(&self, pid: H256, program: ActiveProgram) -> Result<types::GearPages> {
let mut pages = HashMap::new();
for page in program.pages_with_data {
let value = self
.client
.storage()
.fetch_raw(StorageKey(utils::page_key(pid, PageNumber(page.0))), None)
.await?
.ok_or_else(|| Error::PageNotFound(page.0, pid.encode_hex()))?;
pages.insert(page.0, value.0);
}
Ok(pages)
}
pub async fn program_pages(&self, pid: H256) -> Result<types::GearPages> {
self.gpages(pid, self.gprog(pid).await?).await
}
pub async fn mailbox(
&self,
address: AccountId32,
count: u32,
) -> Result<Vec<(StoredMessage, Interval<u32>)>> {
let prefix = StorageKeyPrefix::new::<gear_messenger::storage::Mailbox>();
let entry_key = StorageEntryKey::Map(vec![StorageMapKey::new(
&address,
subxt::StorageHasher::Identity,
)]);
let query_key = entry_key.final_key(prefix);
let keys = self
.client
.rpc()
.storage_keys_paged(Some(query_key), count, None, None)
.await?;
let mut mailbox: Vec<(StoredMessage, Interval<u32>)> = vec![];
for key in keys.into_iter() {
if let Some(storage_data) = self.client.storage().fetch_raw(key, None).await? {
if let Ok(value) =
<(StoredMessage, Interval<u32>)>::decode(&mut &storage_data.0[..])
{
mailbox.push(value);
}
}
}
Ok(mailbox)
}
}
}