wallet_standard/types.rs
1use crate::WalletStandardConnect;
2use crate::WalletStandardDisconnect;
3
4/// Provides information about a wallet implementation.
5///
6/// This trait defines the metadata and capabilities of a wallet, including its
7/// name, icon, supported chains, features, and accounts. It serves as the
8/// primary interface for applications to discover wallet capabilities.
9///
10/// # Example
11///
12/// ```rust,ignore
13/// struct MyWalletInfo {
14/// name: String,
15/// icon: String,
16/// chains: Vec<String>,
17/// features: Vec<String>,
18/// accounts: Vec<MyAccount>,
19/// }
20///
21/// impl WalletInfo for MyWalletInfo {
22/// type Account = MyAccount;
23///
24/// fn version(&self) -> String {
25/// "1.0.0".to_string()
26/// }
27///
28/// fn name(&self) -> String {
29/// self.name.clone()
30/// }
31///
32/// // ... other implementations
33/// }
34/// ```
35pub trait WalletInfo {
36 type Account: WalletAccountInfo;
37
38 /// {@link `WalletVersion` | Version} of the Wallet Standard implemented by
39 /// the Wallet.
40 ///
41 /// Must be read-only, static, and canonically defined by the Wallet
42 /// Standard.
43 fn version(&self) -> String;
44 /// Name of the Wallet. This may be displayed by the app.
45 ///
46 /// Must be read-only, static, descriptive, unique, and canonically defined
47 /// by the wallet extension or application.
48 fn name(&self) -> String;
49 /// {@link `WalletIcon` | Icon} of the Wallet. This may be displayed by the
50 /// app.
51 ///
52 /// Must be read-only, static, and canonically defined by the wallet
53 /// extension or application.
54 fn icon(&self) -> String;
55 /// Chains supported by the Wallet.
56 ///
57 /// A **chain** is an {@link `IdentifierString`} which identifies a
58 /// blockchain in a canonical, human-readable format. [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md) chain IDs are compatible with this,
59 /// but are not required to be used.
60 ///
61 /// Each blockchain should define its own **chains** by extension of the
62 /// Wallet Standard, using its own namespace. The `standard` and
63 /// `experimental` namespaces are reserved by the Wallet Standard.
64 ///
65 /// The {@link "@wallet-standard/features".EventsFeature | `standard:events`
66 /// feature} should be used to notify the app if the value changes.
67 ///
68 /// # Example
69 ///
70 /// ```
71 /// vec!["solana:mainnet".to_string(), "solana:devnet".to_string()]
72 /// ```
73 fn chains(&self) -> Vec<String>;
74 /// Features supported by the Wallet.
75 ///
76 /// A **feature name** is an {@link `IdentifierString`} which identifies a
77 /// **feature** in a canonical, human-readable format.
78 ///
79 /// Each blockchain should define its own features by extension of the
80 /// Wallet Standard.
81 ///
82 /// The `standard` and `experimental` namespaces are reserved by the Wallet
83 /// Standard.
84 ///
85 /// A **feature** may have any type. It may be a single method or value, or
86 /// a collection of them.
87 ///
88 /// A **conventional feature** has the following structure:
89 ///
90 /// ```ts
91 /// export type ExperimentalEncryptFeature = {
92 /// // Name of the feature.
93 /// 'experimental:encrypt': {
94 /// // Version of the feature.
95 /// version: '1.0.0';
96 /// // Properties of the feature.
97 /// ciphers: readonly 'x25519-xsalsa20-poly1305'[];
98 /// // Methods of the feature.
99 /// encrypt (data: Uint8Array): Promise<Uint8Array>;
100 /// };
101 /// };
102 /// ```
103 ///
104 /// The {@link "@wallet-standard/features".EventsFeature | `standard:events`
105 /// feature} should be used to notify the app if the value changes.
106 ///
107 /// # Example
108 ///
109 /// ```
110 /// vec![
111 /// "standard:connect".to_string(),
112 /// "standard:disconnect".to_string(),
113 /// "solana:signMessage".to_string(),
114 /// "solana:signTransaction".to_string(),
115 /// ]
116 /// ```
117 fn features(&self) -> Vec<String>;
118 /// {@link `WalletAccount` | Accounts} that the app is authorized to use.
119 ///
120 /// This can be set by the Wallet so the app can use authorized accounts on
121 /// the initial page load.
122 ///
123 /// The {@link "@wallet-standard/features".ConnectFeature |
124 /// `standard:connect` feature} should be used to obtain authorization to
125 /// the accounts.
126 ///
127 /// The {@link "@wallet-standard/features".EventsFeature | `standard:events`
128 /// feature} should be used to notify the app if the value changes.
129 fn accounts(&self) -> Vec<Self::Account>;
130}
131
132/// Interface of a **`WalletAccount`**, also referred to as an **Account**.
133///
134/// An account is a _read-only data object_ that is provided from the Wallet to
135/// the app, authorizing the app to use it.
136///
137/// The app can use an account to display and query information from a chain.
138///
139/// The app can also act using an account by passing it to {@link
140/// Wallet.features | features} of the Wallet.
141///
142/// # Example
143///
144/// ```rust,ignore
145/// #[derive(Clone)]
146/// struct MyAccount {
147/// address: String,
148/// public_key: Vec<u8>,
149/// chains: Vec<String>,
150/// features: Vec<String>,
151/// label: Option<String>,
152/// }
153///
154/// impl WalletAccountInfo for MyAccount {
155/// fn address(&self) -> String {
156/// self.address.clone()
157/// }
158///
159/// fn public_key(&self) -> Vec<u8> {
160/// self.public_key.clone()
161/// }
162///
163/// // ... other implementations
164/// }
165/// ```
166pub trait WalletAccountInfo {
167 /// Address of the account, corresponding with a public key.
168 ///
169 /// This is typically a human-readable string representation of the public
170 /// key, formatted according to the blockchain's conventions.
171 ///
172 /// # Example
173 ///
174 /// For Solana: `"HN7cABqLq46Es1jh92dQQisAq662SmxELLLsHHe4YWrH"`
175 fn address(&self) -> String;
176 /// Public key of the account, corresponding with a secret key to use.
177 ///
178 /// This is the raw binary representation of the public key.
179 ///
180 /// # Example
181 ///
182 /// ```
183 /// // A 32-byte Ed25519 public key
184 /// vec![0, 1, 2, 3 /* ... */]
185 /// ```
186 fn public_key(&self) -> Vec<u8>;
187 /// Chains supported by the account.
188 ///
189 /// This must be a subset of the {@link Wallet.chains | chains} of the
190 /// Wallet.
191 ///
192 /// # Example
193 ///
194 /// ```
195 /// vec!["solana:mainnet".to_string()]
196 /// ```
197 fn chains(&self) -> Vec<String>;
198 /// Feature names supported by the account.
199 ///
200 /// This must be a subset of the names of {@link Wallet.features | features}
201 /// of the Wallet.
202 ///
203 /// # Example
204 ///
205 /// ```
206 /// vec![
207 /// "solana:signMessage".to_string(),
208 /// "solana:signTransaction".to_string(),
209 /// ]
210 /// ```
211 fn features(&self) -> Vec<String>;
212 /// Optional user-friendly descriptive label or name for the account. This
213 /// may be displayed by the app.
214 ///
215 /// # Example
216 ///
217 /// ```
218 /// Some("Main Account".to_string())
219 /// ```
220 fn label(&self) -> Option<String>;
221 /// Optional user-friendly icon for the account. This may be displayed by
222 /// the app.
223 ///
224 /// The icon should be a data URL containing image data.
225 ///
226 /// # Example
227 ///
228 /// ```
229 /// Some("data:image/svg+xml;base64,...".to_string())
230 /// ```
231 fn icon(&self) -> Option<String>;
232}
233
234/// The core trait for wallet implementations.
235///
236/// This trait provides access to wallet information and the currently connected
237/// account. It serves as the foundation for all wallet functionality and is
238/// extended by other traits like `WalletStandardConnect` and
239/// `WalletStandardDisconnect`.
240///
241/// # Example
242///
243/// ```rust,ignore
244/// struct MyWallet {
245/// wallet_info: MyWalletInfo,
246/// current_account: Option<MyAccount>,
247/// }
248///
249/// impl Wallet for MyWallet {
250/// type Wallet = MyWalletInfo;
251/// type Account = MyAccount;
252///
253/// fn wallet(&self) -> Self::Wallet {
254/// self.wallet_info.clone()
255/// }
256///
257/// fn wallet_account(&self) -> Option<Self::Account> {
258/// self.current_account.clone()
259/// }
260/// }
261/// ```
262pub trait Wallet {
263 type Wallet: WalletInfo;
264 type Account: WalletAccountInfo;
265
266 /// Returns the wallet information.
267 ///
268 /// This provides access to metadata about the wallet, such as its name,
269 /// icon, supported chains, and features.
270 fn wallet(&self) -> Self::Wallet;
271
272 /// Returns the currently connected account, if any.
273 ///
274 /// If no account is connected, this returns `None`.
275 fn wallet_account(&self) -> Option<Self::Account>;
276
277 /// Returns the name of the wallet.
278 ///
279 /// This is a convenience method that delegates to `wallet().name()`.
280 fn name(&self) -> String {
281 self.wallet().name()
282 }
283
284 /// Returns the icon of the wallet.
285 ///
286 /// This is a convenience method that delegates to `wallet().icon()`.
287 fn icon(&self) -> String {
288 self.wallet().icon()
289 }
290
291 /// Returns whether the wallet is connected.
292 ///
293 /// A wallet is considered connected if it has a current account.
294 fn connected(&self) -> bool {
295 self.wallet_account().is_some()
296 }
297
298 /// Returns the public key of the currently connected account, if any.
299 ///
300 /// If no account is connected, this returns `None`.
301 fn try_public_key(&self) -> Option<Vec<u8>> {
302 self.wallet_account().map(|account| account.public_key())
303 }
304
305 /// Returns the public key of the currently connected account.
306 ///
307 /// # Panics
308 ///
309 /// This method will panic if no account is connected. Use
310 /// `try_public_key()` if you want to handle the case where no account is
311 /// connected.
312 fn public_key(&self) -> Vec<u8> {
313 self.try_public_key().unwrap()
314 }
315}
316
317/// A trait that combines the core wallet functionality with standard connect
318/// and disconnect features.
319///
320/// This trait is automatically implemented for any type that implements
321/// `Wallet`, `WalletStandardConnect`, and `WalletStandardDisconnect`.
322pub trait WalletStandard: WalletStandardConnect + WalletStandardDisconnect + Wallet {}
323
324impl<T> WalletStandard for T where T: WalletStandardConnect + WalletStandardDisconnect + Wallet {}