1use std::fmt::Display;
2use std::sync::{Arc, Mutex};
3
4use lwk_common::Amp0Signer;
5
6use crate::{AddressResult, LwkError, Network, Pset, Signer, Transaction, WolletDescriptor};
8
9#[derive(uniffi::Object)]
11pub struct Amp0 {
12 inner: Mutex<lwk_wollet::amp0::blocking::Amp0>,
13}
14
15#[uniffi::export]
16impl Amp0 {
17 #[uniffi::constructor]
19 pub fn new(
20 network: &Network,
21 username: &str,
22 password: &str,
23 amp_id: &str,
24 ) -> Result<Self, LwkError> {
25 let inner =
26 lwk_wollet::amp0::blocking::Amp0::new(network.into(), username, password, amp_id)?;
27 Ok(Self {
28 inner: Mutex::new(inner),
29 })
30 }
31
32 pub fn last_index(&self) -> Result<u32, LwkError> {
34 Ok(self.inner.lock()?.last_index())
35 }
36
37 pub fn amp_id(&self) -> Result<String, LwkError> {
39 Ok(self.inner.lock()?.amp_id().into())
40 }
41
42 pub fn wollet_descriptor(&self) -> Result<Arc<WolletDescriptor>, LwkError> {
44 Ok(Arc::new(self.inner.lock()?.wollet_descriptor().into()))
45 }
46
47 pub fn address(&self, index: Option<u32>) -> Result<Arc<AddressResult>, LwkError> {
51 Ok(Arc::new(self.inner.lock()?.address(index)?.into()))
52 }
53
54 pub fn sign(&self, pset: &Amp0Pset) -> Result<Arc<Transaction>, LwkError> {
56 Ok(Arc::new(self.inner.lock()?.sign(pset.as_ref())?.into()))
57 }
58}
59
60#[derive(uniffi::Object)]
62pub struct Amp0Pset {
63 inner: lwk_wollet::amp0::Amp0Pset,
64}
65
66impl From<lwk_wollet::amp0::Amp0Pset> for Amp0Pset {
67 fn from(inner: lwk_wollet::amp0::Amp0Pset) -> Self {
68 Self { inner }
69 }
70}
71
72impl AsRef<lwk_wollet::amp0::Amp0Pset> for Amp0Pset {
73 fn as_ref(&self) -> &lwk_wollet::amp0::Amp0Pset {
74 &self.inner
75 }
76}
77
78#[uniffi::export]
79impl Amp0Pset {
80 #[uniffi::constructor]
82 pub fn new(pset: &Pset, blinding_nonces: Vec<String>) -> Result<Arc<Self>, LwkError> {
83 let pset = pset.as_ref().clone();
84 let inner = lwk_wollet::amp0::Amp0Pset::new(pset, blinding_nonces)?;
85 Ok(Arc::new(Self { inner }))
86 }
87
88 pub fn pset(&self) -> Result<Pset, LwkError> {
90 let pset = self.inner.pset().clone();
91 Ok(pset.into())
92 }
93
94 pub fn blinding_nonces(&self) -> Result<Vec<String>, LwkError> {
96 Ok(self.inner.blinding_nonces().to_vec())
97 }
98}
99
100#[derive(uniffi::Object, Clone)]
102#[uniffi::export(Display)]
103pub struct Amp0SignerData {
104 inner: lwk_common::Amp0SignerData,
105}
106
107impl Display for Amp0SignerData {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 write!(f, "{}", self.inner)
110 }
111}
112
113impl From<lwk_common::Amp0SignerData> for Amp0SignerData {
114 fn from(inner: lwk_common::Amp0SignerData) -> Self {
115 Self { inner }
116 }
117}
118
119impl AsRef<lwk_common::Amp0SignerData> for Amp0SignerData {
120 fn as_ref(&self) -> &lwk_common::Amp0SignerData {
121 &self.inner
122 }
123}
124
125#[uniffi::export]
126impl Signer {
127 pub fn amp0_signer_data(&self) -> Result<Amp0SignerData, LwkError> {
129 Ok(self.inner.amp0_signer_data()?.into())
130 }
131
132 fn amp0_sign_challenge(&self, challenge: &str) -> Result<String, LwkError> {
134 Ok(self.inner.amp0_sign_challenge(challenge)?)
135 }
136
137 fn amp0_account_xpub(&self, account: u32) -> Result<String, LwkError> {
139 Ok(self.inner.amp0_account_xpub(account)?.to_string())
140 }
141}
142
143#[derive(uniffi::Object)]
145pub struct Amp0Connected {
146 inner: Mutex<Option<lwk_wollet::amp0::blocking::Amp0Connected>>,
151}
152
153#[derive(uniffi::Object)]
155pub struct Amp0LoggedIn {
156 inner: Mutex<lwk_wollet::amp0::blocking::Amp0LoggedIn>,
157}
158
159fn amp0_err() -> LwkError {
160 "AMP0 session already logged in or it errored".into()
161}
162
163#[uniffi::export]
164impl Amp0Connected {
165 #[uniffi::constructor]
167 pub fn new(network: &Network, signer_data: &Amp0SignerData) -> Result<Self, LwkError> {
168 let inner = lwk_wollet::amp0::blocking::Amp0Connected::new(
169 network.into(),
170 signer_data.inner.clone(),
171 )?;
172 Ok(Amp0Connected {
173 inner: Mutex::new(Some(inner)),
174 })
175 }
176
177 pub fn get_challenge(&self) -> Result<String, LwkError> {
181 Ok(self
182 .inner
183 .lock()?
184 .as_ref()
185 .ok_or_else(amp0_err)?
186 .get_challenge()?)
187 }
188
189 pub fn login(self: Arc<Self>, sig: &str) -> Result<Arc<Amp0LoggedIn>, LwkError> {
194 let mut lock = self.inner.lock()?;
195 let amp0 = lock.take().ok_or_else(amp0_err)?;
196 let amp0 = amp0.login(sig)?;
197 Ok(Arc::new(Amp0LoggedIn {
198 inner: Mutex::new(amp0),
199 }))
200 }
201}
202
203#[uniffi::export]
204impl Amp0LoggedIn {
205 pub fn get_amp_ids(&self) -> Result<Vec<String>, LwkError> {
207 Ok(self.inner.lock()?.get_amp_ids()?)
208 }
209
210 pub fn next_account(&self) -> Result<u32, LwkError> {
215 Ok(self.inner.lock()?.next_account()?)
216 }
217
218 pub fn create_amp0_account(
223 &self,
224 pointer: u32,
225 account_xpub: &str,
226 ) -> Result<String, LwkError> {
227 use elements::bitcoin::bip32::Xpub;
228 use std::str::FromStr;
229 let account_xpub = Xpub::from_str(account_xpub)?;
230 Ok(self
231 .inner
232 .lock()?
233 .create_amp0_account(pointer, &account_xpub)?)
234 }
235
236 pub fn create_watch_only(&self, username: &str, password: &str) -> Result<(), LwkError> {
238 Ok(self.inner.lock()?.create_watch_only(username, password)?)
239 }
240}