wallet_adapter/wallet_ser_der/
wallet.rs1use std::borrow::Cow;
2
3use async_channel::Receiver;
4use ed25519_dalek::Signature;
5use wallet_adapter_common::{
6 chains::ChainSupport, clusters::Cluster, signin_standard::SignInOutput, WalletData,
7};
8use web_sys::wasm_bindgen::JsValue;
9
10use crate::{
11 ConnectionInfoInner, Features, Reflection, SemverVersion, SigninInput, WalletAccount,
12 WalletError, WalletEventSender, WalletIcon, WalletResult,
13};
14
15use super::{SendOptions, SignedMessageOutput};
16
17#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
19pub struct Wallet {
20 pub(crate) data: WalletData,
21 pub(crate) accounts: Vec<WalletAccount>,
22 pub(crate) features: Features,
23}
24
25impl Wallet {
26 pub async fn connect(&self) -> WalletResult<WalletAccount> {
28 self.features.connect.call_connect().await
29 }
30
31 pub async fn disconnect(&self) -> WalletResult<()> {
33 self.features.disconnect.call_disconnect().await
34 }
35
36 pub async fn sign_in(
38 &self,
39 signin_input: &SigninInput,
40 public_key: [u8; 32],
41 ) -> WalletResult<SignInOutput> {
42 if let Some(fn_exists) = self.features.sign_in.as_ref() {
43 fn_exists.call_signin(signin_input, public_key).await
44 } else {
45 Err(WalletError::MissingSignInFunction)
46 }
47 }
48
49 pub async fn sign_message<'a>(
52 &self,
53 message: &'a [u8],
54 account: &WalletAccount,
55 ) -> WalletResult<SignedMessageOutput<'a>> {
56 self.features
57 .sign_message
58 .call_sign_message(account, message)
59 .await
60 }
61
62 pub async fn sign_transaction(
65 &self,
66 transaction_bytes: &[u8],
67 cluster: Option<Cluster>,
68 account: &WalletAccount,
69 ) -> WalletResult<Vec<Vec<u8>>> {
70 self.features
71 .sign_tx
72 .call_sign_tx(account, transaction_bytes, cluster)
73 .await
74 }
75
76 pub async fn sign_and_send_transaction(
78 &self,
79 transaction_bytes: &[u8],
80 cluster: Cluster,
81 options: SendOptions,
82 account: &WalletAccount,
83 ) -> WalletResult<Signature> {
84 self.features
85 .sign_and_send_tx
86 .call_sign_and_send_transaction(account, transaction_bytes, cluster, options)
87 .await
88 }
89
90 pub async fn call_on_event(
92 &self,
93 connection_info: ConnectionInfoInner,
94 wallet_name: String,
95 sender: WalletEventSender,
96 signal_receiver: Receiver<()>,
97 ) -> WalletResult<()> {
98 self.features
99 .events
100 .call_on_event(connection_info, wallet_name, sender, signal_receiver)
101 .await
102 }
103
104 pub fn from_jsvalue(value: JsValue) -> WalletResult<Self> {
106 let reflection = Reflection::new(value)?;
107
108 let mut supported_chains = ChainSupport::default();
109
110 let chains_raw = reflection.vec_string_and_filter("chains", "solana:")?;
111 let chains = chains_raw
112 .into_iter()
113 .map(|chain_raw| {
114 let cluster: Cluster = chain_raw.as_str().into();
115 if cluster == Cluster::MainNet {
116 supported_chains.mainnet = true;
117 } else if cluster == Cluster::DevNet {
118 supported_chains.devnet = true;
119 } else if cluster == Cluster::TestNet {
120 supported_chains.testnet = true;
121 } else if cluster == Cluster::LocalNet {
122 supported_chains.localnet = true;
123 }
124
125 cluster
126 })
127 .collect::<Vec<Cluster>>();
128
129 let name = reflection.string("name")?;
130 let version = SemverVersion::parse(&reflection.string("version")?)?;
131 let icon = WalletIcon::from_jsvalue(&reflection)?;
132 let accounts = Self::get_accounts(&reflection, "accounts")?;
133 let (features, supported_features) = Features::parse(&reflection)?;
134
135 let data = WalletData::new()
136 .set_name(&name)
137 .set_version(
138 wallet_adapter_common::SemverVersion::new()
139 .set_major(version.major())
140 .set_minor(version.minor())
141 .set_patch(version.patch()),
142 )
143 .set_icon(icon.as_ref())
144 .replace_accounts(
145 accounts
146 .iter()
147 .map(|wallet_account| wallet_account.account.clone())
148 .collect(),
149 )
150 .replace_chains(chains)
151 .set_supported_features(supported_features)
152 .set_supported_chains(supported_chains);
153
154 Ok(Self {
155 data,
156 accounts,
157 features,
158 })
159 }
160
161 fn get_accounts(reflection: &Reflection, key: &str) -> WalletResult<Vec<WalletAccount>> {
162 let accounts_raw = reflection.reflect_inner(key)?;
163
164 let accounts_array = Reflection::new(accounts_raw)?.into_array()?;
165
166 accounts_array
167 .iter()
168 .map(|account| WalletAccount::parse(Reflection::new(account)?))
169 .collect::<WalletResult<Vec<WalletAccount>>>()
170 }
171
172 pub fn features(&self) -> &Features {
174 &self.features
175 }
176
177 pub fn accounts(&self) -> &[WalletAccount] {
179 &self.accounts
180 }
181
182 pub fn chains(&self) -> &[Cluster] {
184 self.data.chains()
185 }
186
187 pub fn mainnet(&self) -> bool {
189 self.data.mainnet()
190 }
191
192 pub fn devnet(&self) -> bool {
194 self.data.devnet()
195 }
196
197 pub fn testnet(&self) -> bool {
199 self.data.testnet()
200 }
201
202 pub fn localnet(&self) -> bool {
204 self.data.localnet()
205 }
206
207 pub fn standard_connect(&self) -> bool {
209 self.data.standard_connect()
210 }
211
212 pub fn standard_disconnect(&self) -> bool {
214 self.data.standard_disconnect()
215 }
216
217 pub fn standard_events(&self) -> bool {
219 self.data.standard_events()
220 }
221
222 pub fn solana_signin(&self) -> bool {
224 self.data.solana_signin()
225 }
226
227 pub fn solana_sign_message(&self) -> bool {
229 self.data.solana_sign_message()
230 }
231
232 pub fn solana_sign_and_send_transaction(&self) -> bool {
234 self.data.solana_sign_and_send_transaction()
235 }
236
237 pub fn solana_sign_transaction(&self) -> bool {
239 self.data.solana_sign_transaction()
240 }
241
242 pub fn icon(&self) -> Option<&Cow<'static, str>> {
244 self.data.icon()
245 }
246
247 pub fn name(&self) -> &str {
249 self.data.name()
250 }
251
252 pub fn version(&self) -> SemverVersion {
254 let version = self.data.version();
255
256 SemverVersion(version.clone())
257 }
258}