Skip to main content

glsdk/
signer.rs

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
66// Not exported through uniffi, internal logic only.
67impl 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/// A handle to interact with a signer loop running and processing
77/// requests in the background. Used primarily to stop the loop and
78/// exiting the signer.
79#[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    /// Spawns the signer on the shared signer runtime and returns a handle to stop it.
93    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    /// Sends the shutdown signal, returning true if the signal was
104    /// delivered and false if the signer has already stopped.
105    pub(crate) fn try_stop(&self) -> bool {
106        self.chan.try_send(()).is_ok()
107    }
108}