1#[cfg(test)]
22mod tests;
23
24use self::error::Error;
25use jsonrpsee::{core::async_trait, Extensions};
26use parking_lot::RwLock;
27use sc_rpc_api::check_if_safe;
28pub use sc_rpc_api::offchain::*;
30use sp_core::{
31 offchain::{OffchainStorage, StorageKind},
32 Bytes,
33};
34use std::sync::Arc;
35
36#[derive(Debug)]
38pub struct Offchain<T: OffchainStorage> {
39 storage: Arc<RwLock<T>>,
41}
42
43impl<T: OffchainStorage> Offchain<T> {
44 pub fn new(storage: T) -> Self {
46 Offchain { storage: Arc::new(RwLock::new(storage)) }
47 }
48}
49
50#[async_trait]
51impl<T: OffchainStorage + 'static> OffchainApiServer for Offchain<T> {
52 fn set_local_storage(
53 &self,
54 ext: &Extensions,
55 kind: StorageKind,
56 key: Bytes,
57 value: Bytes,
58 ) -> Result<(), Error> {
59 check_if_safe(ext)?;
60
61 let prefix = match kind {
62 StorageKind::PERSISTENT => sp_offchain::STORAGE_PREFIX,
63 StorageKind::LOCAL => return Err(Error::UnavailableStorageKind),
64 };
65 self.storage.write().set(prefix, &key, &value);
66 Ok(())
67 }
68
69 fn clear_local_storage(
70 &self,
71 ext: &Extensions,
72 kind: StorageKind,
73 key: Bytes,
74 ) -> Result<(), Error> {
75 check_if_safe(ext)?;
76
77 let prefix = match kind {
78 StorageKind::PERSISTENT => sp_offchain::STORAGE_PREFIX,
79 StorageKind::LOCAL => return Err(Error::UnavailableStorageKind),
80 };
81 self.storage.write().remove(prefix, &key);
82
83 Ok(())
84 }
85
86 fn get_local_storage(
87 &self,
88 ext: &Extensions,
89 kind: StorageKind,
90 key: Bytes,
91 ) -> Result<Option<Bytes>, Error> {
92 check_if_safe(ext)?;
93
94 let prefix = match kind {
95 StorageKind::PERSISTENT => sp_offchain::STORAGE_PREFIX,
96 StorageKind::LOCAL => return Err(Error::UnavailableStorageKind),
97 };
98
99 Ok(self.storage.read().get(prefix, &key).map(Into::into))
100 }
101}