linera_wallet_json/
wallet.rs1use std::{
7 iter::IntoIterator,
8 sync::{Arc, RwLock},
9};
10
11use futures::{stream, Stream};
12use linera_base::identifiers::{AccountOwner, ChainId};
13use linera_core::{wallet::*, GenesisConfig};
14use linera_persistent::{self as persistent};
15
16#[derive(serde::Serialize, serde::Deserialize)]
17struct Data {
18 pub chains: Memory,
19 default: Arc<RwLock<Option<ChainId>>>,
20 genesis_config: GenesisConfig,
21}
22
23pub struct PersistentWallet(persistent::File<Data>);
25
26impl Wallet for PersistentWallet {
30 type Error = persistent::file::Error;
31
32 async fn get(&self, id: ChainId) -> Result<Option<Chain>, Self::Error> {
33 Ok(self.get(id))
34 }
35
36 async fn remove(&self, id: ChainId) -> Result<Option<Chain>, Self::Error> {
37 self.remove(id)
38 }
39
40 fn items(&self) -> impl Stream<Item = Result<(ChainId, Chain), Self::Error>> {
41 stream::iter(self.items().into_iter().map(Ok))
42 }
43
44 async fn insert(&self, id: ChainId, chain: Chain) -> Result<Option<Chain>, Self::Error> {
45 self.insert(id, &chain)
46 }
47
48 async fn try_insert(&self, id: ChainId, chain: Chain) -> Result<Option<Chain>, Self::Error> {
49 let chain = self.try_insert(id, chain)?;
50 self.save()?;
51 Ok(chain)
52 }
53
54 async fn modify(
55 &self,
56 id: ChainId,
57 f: impl Fn(&mut Chain) + Send,
58 ) -> Result<Option<()>, Self::Error> {
59 self.mutate(id, f).transpose()
60 }
61}
62
63impl Extend<(ChainId, Chain)> for PersistentWallet {
64 fn extend<It: IntoIterator<Item = (ChainId, Chain)>>(&mut self, chains: It) {
65 for (id, chain) in chains {
66 if self.0.chains.try_insert(id, chain).is_none() {
67 self.try_set_default(id);
68 }
69 }
70 }
71}
72
73impl PersistentWallet {
74 pub fn get(&self, id: ChainId) -> Option<Chain> {
76 self.0.chains.get(id)
77 }
78
79 pub fn remove(&self, id: ChainId) -> Result<Option<Chain>, persistent::file::Error> {
81 let chain = self.0.chains.remove(id);
82 {
83 let mut default = self.0.default.write().unwrap();
84 if *default == Some(id) {
85 *default = None;
86 }
87 }
88 self.0.save()?;
89 Ok(chain)
90 }
91
92 pub fn items(&self) -> Vec<(ChainId, Chain)> {
94 self.0.chains.items()
95 }
96
97 fn try_set_default(&self, id: ChainId) {
98 let mut guard = self.0.default.write().unwrap();
99 if guard.is_none() {
100 *guard = Some(id);
101 }
102 }
103
104 pub fn insert(
106 &self,
107 id: ChainId,
108 chain: &Chain,
109 ) -> Result<Option<Chain>, persistent::file::Error> {
110 let has_owner = chain.owner.is_some();
111 let old_chain = self.0.chains.insert(id, chain.clone());
112 if has_owner {
113 self.try_set_default(id);
114 }
115 self.0.save()?;
116 Ok(old_chain)
117 }
118
119 pub fn try_insert(
122 &self,
123 id: ChainId,
124 chain: Chain,
125 ) -> Result<Option<Chain>, persistent::file::Error> {
126 let chain = self.0.chains.try_insert(id, chain);
127 if chain.is_none() {
128 self.try_set_default(id);
129 }
130 self.save()?;
131 Ok(chain)
132 }
133
134 pub fn create(
136 path: &std::path::Path,
137 genesis_config: GenesisConfig,
138 ) -> Result<Self, persistent::file::Error> {
139 Ok(Self(persistent::File::new(
140 path,
141 Data {
142 chains: Memory::default(),
143 default: Arc::new(RwLock::new(None)),
144 genesis_config,
145 },
146 )?))
147 }
148
149 pub fn read(path: &std::path::Path) -> Result<Self, persistent::file::Error> {
151 Ok(Self(persistent::File::read(path)?))
152 }
153
154 pub fn genesis_config(&self) -> &GenesisConfig {
156 &self.0.genesis_config
157 }
158
159 pub fn genesis_admin_chain_id(&self) -> ChainId {
161 self.0.genesis_config.admin_chain_id()
162 }
163
164 pub fn default_chain(&self) -> Option<ChainId> {
166 *self.0.default.read().unwrap()
167 }
168
169 pub fn set_default_chain(&mut self, id: ChainId) -> Result<(), persistent::file::Error> {
171 assert!(self.0.chains.get(id).is_some());
172 *self.0.default.write().unwrap() = Some(id);
173 self.0.save()
174 }
175
176 pub fn mutate<R>(
179 &self,
180 chain_id: ChainId,
181 mutate: impl Fn(&mut Chain) -> R,
182 ) -> Option<Result<R, persistent::file::Error>> {
183 self.0
184 .chains
185 .mutate(chain_id, mutate)
186 .map(|outcome| self.0.save().map(|()| outcome))
187 }
188
189 pub fn forget_keys(
191 &self,
192 chain_id: ChainId,
193 ) -> Result<Option<AccountOwner>, persistent::file::Error> {
194 self.mutate(chain_id, |chain| chain.owner.take())
195 .transpose()
196 .map(|opt| opt.flatten())
197 }
198
199 pub fn forget_chain(
201 &self,
202 chain_id: ChainId,
203 ) -> Result<Option<Chain>, persistent::file::Error> {
204 let chain = self.0.chains.remove(chain_id);
205 if chain.is_some() {
206 self.0.save()?;
207 }
208 Ok(chain)
209 }
210
211 pub fn save(&self) -> Result<(), persistent::file::Error> {
213 self.0.save()
214 }
215
216 pub fn num_chains(&self) -> usize {
218 self.0.chains.items().len()
219 }
220
221 pub fn chain_ids(&self) -> Vec<ChainId> {
223 self.0.chains.chain_ids()
224 }
225
226 pub fn owned_chain_ids(&self) -> Vec<ChainId> {
228 self.0.chains.owned_chain_ids()
229 }
230}