kraken_async_rs/crypto/
nonce_provider.rs

1//! Trait and implementation for providing request nonces
2#[allow(unused)]
3use crate::clients::kraken_client::KrakenClient;
4use std::fmt::Debug;
5use std::time::{SystemTime, UNIX_EPOCH};
6
7/// A nonce generator that should be used to populate the nonce of every request created by a
8/// [KrakenClient].
9pub trait NonceProvider: Send + Sync + Debug {
10    fn get_nonce(&mut self) -> u64;
11}
12
13/// A nonce generator that gives the current epoch in milliseconds, except when called in the same
14/// millisecond, in which case it increases the nonce by 1 so no duplicates are ever returned.
15///
16/// You may wish to consider setting a `nonce window` on your API key to allow for out of order nonces
17/// within several seconds of each other. Consult the [Kraken docs] for instructions and trade-offs.
18///
19/// [Kraken docs]: https://support.kraken.com/hc/en-us/articles/360001148023-What-is-a-nonce-window-
20#[derive(Debug, Clone, Copy)]
21pub struct IncreasingNonceProvider {
22    last: u64,
23}
24
25impl Default for IncreasingNonceProvider {
26    fn default() -> Self {
27        Self::new()
28    }
29}
30
31impl IncreasingNonceProvider {
32    pub fn new() -> Self {
33        IncreasingNonceProvider { last: 0 }
34    }
35}
36
37impl NonceProvider for IncreasingNonceProvider {
38    /// Returns the current time in milliseconds, or the last nonce + 1 if a duplicate would be
39    /// generated.
40    fn get_nonce(&mut self) -> u64 {
41        let nonce = SystemTime::now()
42            .duration_since(UNIX_EPOCH)
43            .unwrap()
44            .as_millis() as u64;
45
46        if nonce <= self.last {
47            self.last += 1;
48        } else {
49            self.last = nonce;
50        }
51
52        self.last
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use crate::crypto::nonce_provider::{IncreasingNonceProvider, NonceProvider};
59
60    #[test]
61    fn test_increasing_nonce_provider() {
62        let mut provider = IncreasingNonceProvider::default();
63
64        let mut last = 0;
65
66        for _ in 0..100 {
67            let nonce = provider.get_nonce();
68            assert!(nonce > last);
69            last = nonce;
70        }
71    }
72}