wallet_standard_browser/features/experimental/
encrypt.rs1#![allow(unsafe_code)]
2
3use async_trait::async_trait;
4use js_sys::Array;
5use serde::Deserialize;
6use serde::Serialize;
7use typed_builder::TypedBuilder;
8use wallet_standard::EXPERIMENTAL_ENCRYPT;
9use wallet_standard::ExperimentalEncryptOutput;
10use wallet_standard::ExperimentalEncryptProps;
11use wallet_standard::WalletError;
12use wallet_standard::WalletExperimentalEncrypt;
13use wallet_standard::WalletResult;
14use wasm_bindgen::JsCast;
15use wasm_bindgen::JsValue;
16use wasm_bindgen::prelude::*;
17
18use crate::BrowserWallet;
19use crate::BrowserWalletAccountInfo;
20use crate::impl_feature_from_js;
21
22impl ExperimentalEncryptOutput for BrowserExperimentalEncryptOutput {
23 fn cipher_text(&self) -> Vec<u8> {
24 self._cipher_text()
25 }
26
27 fn nonce(&self) -> Vec<u8> {
28 self._nonce()
29 }
30}
31
32#[wasm_bindgen]
33extern "C" {
34 #[derive(Clone, Debug)]
35 pub type BrowserExperimentalEncryptOutput;
36 #[wasm_bindgen(method, getter, js_name = "cipher_text")]
38 pub fn _cipher_text(this: &BrowserExperimentalEncryptOutput) -> Vec<u8>;
39 #[wasm_bindgen(method, getter, js_name = "nonce")]
41 pub fn _nonce(this: &BrowserExperimentalEncryptOutput) -> Vec<u8>;
42 #[derive(Clone, Debug)]
43 pub type ExperimentalEncryptFeature;
44 #[wasm_bindgen(method, getter)]
46 pub fn version(this: &ExperimentalEncryptFeature) -> String;
47 #[wasm_bindgen(method, getter)]
49 pub fn ciphers(this: &ExperimentalEncryptFeature) -> Vec<String>;
50 #[allow(unused_qualifications)]
56 #[wasm_bindgen(method, variadic, catch)]
57 pub async fn encrypt(
58 this: &ExperimentalEncryptFeature,
59 args: Array,
60 ) -> Result<JsValue, JsValue>;
61}
62
63impl_feature_from_js!(ExperimentalEncryptFeature, EXPERIMENTAL_ENCRYPT);
64
65#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TypedBuilder)]
66#[serde(rename_all = "camelCase")]
67pub struct ExperimentalEncryptInput {
68 #[serde(with = "serde_wasm_bindgen::preserve")]
70 pub account: BrowserWalletAccountInfo,
71 #[serde(flatten)]
72 pub props: ExperimentalEncryptProps,
73}
74
75#[async_trait(?Send)]
76impl WalletExperimentalEncrypt for BrowserWallet {
77 type Output = BrowserExperimentalEncryptOutput;
78
79 async fn encrypt_many(
80 &self,
81 props: Vec<ExperimentalEncryptProps>,
82 ) -> WalletResult<Vec<Self::Output>> {
83 let Some(ref wallet_account) = self.wallet_account else {
84 return Err(WalletError::WalletAccount);
85 };
86
87 let input = props
88 .into_iter()
89 .map(|p| {
90 ExperimentalEncryptInput::builder()
91 .account(wallet_account.clone())
92 .props(p)
93 .build()
94 })
95 .collect::<Vec<_>>();
96
97 let feature = self.wallet.get_feature::<ExperimentalEncryptFeature>()?;
98 let inputs: Array = serde_wasm_bindgen::to_value(&input)?.unchecked_into();
99 let result: Array = feature.encrypt(inputs).await?.unchecked_into();
100
101 Ok(result
102 .into_iter()
103 .map(wasm_bindgen::JsCast::unchecked_into)
104 .collect())
105 }
106
107 async fn encrypt(&self, props: ExperimentalEncryptProps) -> WalletResult<Self::Output> {
108 self.encrypt_many(vec![props])
109 .await?
110 .first()
111 .cloned()
112 .ok_or(WalletError::WalletEncrypt)
113 }
114}