1use crate::{Credentials, Error};
2use bip39::Mnemonic;
3use std::str::FromStr;
4use tracing;
5
6#[derive(uniffi::Object, Clone)]
7pub struct Signer {
8 seed: Vec<u8>,
9 pub(crate) inner: gl_client::signer::Signer,
10 credentials: Option<Credentials>,
11}
12
13#[uniffi::export]
14impl Signer {
15 #[uniffi::constructor()]
16 pub fn new(phrase: String) -> Result<Signer, Error> {
17 let phrase = Mnemonic::from_str(phrase.as_str()).map_err(|_e| Error::PhraseCorrupted())?;
18 let seed = phrase.to_seed_normalized(&"").to_vec();
19 Self::new_from_seed(seed)
20 }
21
22 #[uniffi::constructor()]
23 pub fn new_from_seed(seed: Vec<u8>) -> Result<Signer, Error> {
24 let credentials = gl_client::credentials::Nobody::new();
25
26 let inner = gl_client::signer::Signer::new(
27 seed.clone(),
28 gl_client::bitcoin::Network::Bitcoin,
29 credentials,
30 )
31 .map_err(|e| Error::Other(e.to_string()))?;
32 let credentials = None;
33 Ok(Signer {
34 seed,
35 inner,
36 credentials,
37 })
38 }
39
40 pub fn authenticate(&self, creds: &Credentials) -> Result<Signer, Error> {
41 let credentials = Some(creds.clone());
42
43 let inner = gl_client::signer::Signer::new(
44 self.seed.clone(),
45 gl_client::bitcoin::Network::Bitcoin,
46 creds.inner.clone(),
47 )
48 .map_err(|e| Error::Other(e.to_string()))?;
49
50 Ok(Signer {
51 inner,
52 credentials,
53 ..self.clone()
54 })
55 }
56
57 pub fn start(&self) -> Result<Handle, Error> {
58 Ok(Handle::spawn(self.inner.clone()))
59 }
60
61 pub fn node_id(&self) -> Vec<u8> {
62 self.inner.node_id()
63 }
64}
65
66impl Signer {
68 async fn run(&self, signal: tokio::sync::mpsc::Receiver<()>) {
69 self.inner
70 .run_forever(signal)
71 .await
72 .expect("Error running signer loop");
73 }
74}
75
76#[derive(uniffi::Object, Clone)]
80pub struct Handle {
81 chan: tokio::sync::mpsc::Sender<()>,
82}
83
84#[uniffi::export]
85impl Handle {
86 pub fn stop(&self) {
87 self.chan.try_send(()).expect("sending shutdown signal");
88 }
89}
90
91impl Handle {
92 pub(crate) fn spawn(signer: gl_client::signer::Signer) -> Self {
94 let (tx, rx) = tokio::sync::mpsc::channel(1);
95 crate::util::get_signer_runtime().spawn(async move {
96 if let Err(e) = signer.run_forever(rx).await {
97 tracing::error!("Error running signer: {e}");
98 }
99 });
100 Self { chan: tx }
101 }
102
103 pub(crate) fn try_stop(&self) -> bool {
106 self.chan.try_send(()).is_ok()
107 }
108}