Skip to main content

solana_primitives/types/
signature.rs

1use crate::error::{Result, SolanaError};
2use borsh::{BorshDeserialize, BorshSerialize};
3use serde::{Deserialize, Serialize};
4
5/// A 64-byte signature
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, BorshSerialize, BorshDeserialize)]
7pub struct SignatureBytes([u8; 64]);
8
9impl Default for SignatureBytes {
10    fn default() -> Self {
11        Self([0; 64])
12    }
13}
14
15impl SignatureBytes {
16    /// Create a new signature from bytes
17    pub fn new(bytes: [u8; 64]) -> Self {
18        Self(bytes)
19    }
20
21    /// Create a signature from a base58 string
22    pub fn from_base58(s: &str) -> Result<Self> {
23        let bytes = bs58::decode(s).into_vec().map_err(|_| {
24            SolanaError::InvalidSignature(format!("failed to decode base58: {}", s))
25        })?;
26        if bytes.len() != 64 {
27            return Err(SolanaError::InvalidSignature(format!(
28                "invalid length: {}, expected: 64",
29                bytes.len()
30            )));
31        }
32        let mut result = [0; 64];
33        result.copy_from_slice(&bytes);
34        Ok(Self(result))
35    }
36
37    /// Convert the signature to a base58 string
38    pub fn to_base58(&self) -> String {
39        bs58::encode(&self.0).into_string()
40    }
41
42    /// Get the bytes of the signature
43    pub fn as_bytes(&self) -> &[u8; 64] {
44        &self.0
45    }
46}
47
48impl Serialize for SignatureBytes {
49    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
50    where
51        S: serde::Serializer,
52    {
53        serializer.serialize_str(&self.to_base58())
54    }
55}
56
57impl<'de> Deserialize<'de> for SignatureBytes {
58    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
59    where
60        D: serde::Deserializer<'de>,
61    {
62        let s = <String as Deserialize>::deserialize(deserializer)?;
63        Self::from_base58(&s).map_err(serde::de::Error::custom)
64    }
65}