1#![deprecated(
2 since = "1.11.0",
3 note = "Please use BorrowedAccount instead of KeyedAccount"
4)]
5#![allow(deprecated)]
6use {
7 crate::{
8 account::{AccountSharedData, ReadableAccount},
9 account_utils::{State, StateMut},
10 },
11 solana_program::{clock::Epoch, instruction::InstructionError, pubkey::Pubkey},
12 std::{
13 cell::{Ref, RefCell, RefMut},
14 iter::FromIterator,
15 rc::Rc,
16 },
17};
18
19#[repr(C)]
20#[derive(Debug, Clone)]
21pub struct KeyedAccount<'a> {
22 is_signer: bool, is_writable: bool,
24 key: &'a Pubkey,
25 pub account: &'a RefCell<AccountSharedData>,
26}
27
28impl<'a> KeyedAccount<'a> {
29 pub fn signer_key(&self) -> Option<&Pubkey> {
30 if self.is_signer {
31 Some(self.key)
32 } else {
33 None
34 }
35 }
36
37 pub fn unsigned_key(&self) -> &Pubkey {
38 self.key
39 }
40
41 pub fn is_writable(&self) -> bool {
42 self.is_writable
43 }
44
45 pub fn lamports(&self) -> Result<u64, InstructionError> {
46 Ok(self.try_borrow()?.lamports())
47 }
48
49 pub fn data_len(&self) -> Result<usize, InstructionError> {
50 Ok(self.try_borrow()?.data().len())
51 }
52
53 pub fn data_is_empty(&self) -> Result<bool, InstructionError> {
54 Ok(self.try_borrow()?.data().is_empty())
55 }
56
57 pub fn owner(&self) -> Result<Pubkey, InstructionError> {
58 Ok(*self.try_borrow()?.owner())
59 }
60
61 pub fn executable(&self) -> Result<bool, InstructionError> {
62 Ok(self.try_borrow()?.executable())
63 }
64
65 pub fn rent_epoch(&self) -> Result<Epoch, InstructionError> {
66 Ok(self.try_borrow()?.rent_epoch())
67 }
68
69 pub fn try_account_ref(&'a self) -> Result<Ref<AccountSharedData>, InstructionError> {
70 self.try_borrow()
71 }
72
73 pub fn try_account_ref_mut(&'a self) -> Result<RefMut<AccountSharedData>, InstructionError> {
74 self.try_borrow_mut()
75 }
76
77 fn try_borrow(&self) -> Result<Ref<AccountSharedData>, InstructionError> {
78 self.account
79 .try_borrow()
80 .map_err(|_| InstructionError::AccountBorrowFailed)
81 }
82 fn try_borrow_mut(&self) -> Result<RefMut<AccountSharedData>, InstructionError> {
83 self.account
84 .try_borrow_mut()
85 .map_err(|_| InstructionError::AccountBorrowFailed)
86 }
87
88 pub fn new(key: &'a Pubkey, is_signer: bool, account: &'a RefCell<AccountSharedData>) -> Self {
89 Self {
90 is_signer,
91 is_writable: true,
92 key,
93 account,
94 }
95 }
96
97 pub fn new_readonly(
98 key: &'a Pubkey,
99 is_signer: bool,
100 account: &'a RefCell<AccountSharedData>,
101 ) -> Self {
102 Self {
103 is_signer,
104 is_writable: false,
105 key,
106 account,
107 }
108 }
109}
110
111impl<'a> PartialEq for KeyedAccount<'a> {
112 fn eq(&self, other: &Self) -> bool {
113 self.key == other.key
114 }
115}
116
117impl<'a> From<(&'a Pubkey, &'a RefCell<AccountSharedData>)> for KeyedAccount<'a> {
118 fn from((key, account): (&'a Pubkey, &'a RefCell<AccountSharedData>)) -> Self {
119 Self {
120 is_signer: false,
121 is_writable: true,
122 key,
123 account,
124 }
125 }
126}
127
128impl<'a> From<(&'a Pubkey, bool, &'a RefCell<AccountSharedData>)> for KeyedAccount<'a> {
129 fn from((key, is_signer, account): (&'a Pubkey, bool, &'a RefCell<AccountSharedData>)) -> Self {
130 Self {
131 is_signer,
132 is_writable: true,
133 key,
134 account,
135 }
136 }
137}
138
139impl<'a> From<&'a (&'a Pubkey, &'a RefCell<AccountSharedData>)> for KeyedAccount<'a> {
140 fn from((key, account): &'a (&'a Pubkey, &'a RefCell<AccountSharedData>)) -> Self {
141 Self {
142 is_signer: false,
143 is_writable: true,
144 key,
145 account,
146 }
147 }
148}
149
150pub fn create_keyed_accounts<'a>(
151 accounts: &'a [(&'a Pubkey, &'a RefCell<AccountSharedData>)],
152) -> Vec<KeyedAccount<'a>> {
153 accounts.iter().map(Into::into).collect()
154}
155
156#[deprecated(
157 since = "1.7.0",
158 note = "Please use create_keyed_accounts_unified instead"
159)]
160pub fn create_keyed_is_signer_accounts<'a>(
161 accounts: &'a [(&'a Pubkey, bool, &'a RefCell<AccountSharedData>)],
162) -> Vec<KeyedAccount<'a>> {
163 accounts
164 .iter()
165 .map(|(key, is_signer, account)| KeyedAccount {
166 is_signer: *is_signer,
167 is_writable: false,
168 key,
169 account,
170 })
171 .collect()
172}
173
174#[deprecated(
175 since = "1.7.0",
176 note = "Please use create_keyed_accounts_unified instead"
177)]
178pub fn create_keyed_readonly_accounts(
179 accounts: &[(Pubkey, Rc<RefCell<AccountSharedData>>)],
180) -> Vec<KeyedAccount> {
181 accounts
182 .iter()
183 .map(|(key, account)| KeyedAccount {
184 is_signer: false,
185 is_writable: false,
186 key,
187 account,
188 })
189 .collect()
190}
191
192pub fn create_keyed_accounts_unified<'a>(
193 accounts: &[(bool, bool, &'a Pubkey, &'a RefCell<AccountSharedData>)],
194) -> Vec<KeyedAccount<'a>> {
195 accounts
196 .iter()
197 .map(|(is_signer, is_writable, key, account)| KeyedAccount {
198 is_signer: *is_signer,
199 is_writable: *is_writable,
200 key,
201 account,
202 })
203 .collect()
204}
205
206#[deprecated(
207 since = "1.11.0",
208 note = "Please use InstructionContext::get_signers() instead"
209)]
210pub fn get_signers<A>(keyed_accounts: &[KeyedAccount]) -> A
212where
213 A: FromIterator<Pubkey>,
214{
215 keyed_accounts
216 .iter()
217 .filter_map(|keyed_account| keyed_account.signer_key())
218 .cloned()
219 .collect::<A>()
220}
221
222#[deprecated(since = "1.7.0", note = "Please use keyed_account_at_index instead")]
223pub fn next_keyed_account<'a, 'b, I: Iterator<Item = &'a KeyedAccount<'b>>>(
225 iter: &mut I,
226) -> Result<I::Item, InstructionError> {
227 iter.next().ok_or(InstructionError::NotEnoughAccountKeys)
228}
229
230pub fn keyed_account_at_index<'a>(
234 keyed_accounts: &'a [KeyedAccount],
235 index: usize,
236) -> Result<&'a KeyedAccount<'a>, InstructionError> {
237 keyed_accounts
238 .get(index)
239 .ok_or(InstructionError::NotEnoughAccountKeys)
240}
241
242pub fn is_executable(keyed_accounts: &[KeyedAccount]) -> Result<bool, InstructionError> {
245 Ok(!keyed_accounts.is_empty() && keyed_accounts[0].executable()?)
246}
247
248impl<'a, T> State<T> for crate::keyed_account::KeyedAccount<'a>
249where
250 T: serde::Serialize + serde::de::DeserializeOwned,
251{
252 fn state(&self) -> Result<T, InstructionError> {
253 self.try_account_ref()?.state()
254 }
255 fn set_state(&self, state: &T) -> Result<(), InstructionError> {
256 self.try_account_ref_mut()?.set_state(state)
257 }
258}