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}