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 {}