defuse_core/payload/
ton_connect.rs1use defuse_crypto::ed25519::{Ed25519PublicKey, Ed25519Signature};
2use defuse_ton_connect::TonConnect;
3pub use defuse_ton_connect::{TonConnectPayload, TonConnectPayloadSchema};
4use serde::{
5 Deserialize, Serialize,
6 de::{DeserializeOwned, Error},
7};
8
9use crate::payload::{Payload, SignedPayload};
10
11use super::{DefusePayload, ExtractDefusePayload};
12
13#[cfg_attr(feature = "schemars-v0_8", derive(::schemars::JsonSchema))]
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct SignedTonConnectPayload {
16 #[serde(flatten)]
17 pub payload: TonConnectPayload,
18
19 pub public_key: Ed25519PublicKey,
20 pub signature: Ed25519Signature,
21}
22
23impl Payload for SignedTonConnectPayload {
24 #[inline]
25 fn hash(&self) -> [u8; 32] {
26 self.payload.try_prehash().expect("ton-connect hash")
27 }
28}
29
30impl SignedPayload for SignedTonConnectPayload {
31 type PublicKey = Ed25519PublicKey;
32
33 #[inline]
34 fn verify(&self) -> Option<Self::PublicKey> {
35 TonConnect::verify(
36 &self.public_key.try_into().ok()?,
37 &self.payload,
38 &self.signature.into(),
39 )
40 .then_some(&self.public_key)
41 .copied()
42 }
43}
44
45impl<T> ExtractDefusePayload<T> for SignedTonConnectPayload
46where
47 T: DeserializeOwned,
48{
49 type Error = serde_json::Error;
50
51 #[inline]
52 fn extract_defuse_payload(self) -> Result<DefusePayload<T>, Self::Error> {
53 self.payload.extract_defuse_payload()
54 }
55}
56
57impl<T> ExtractDefusePayload<T> for TonConnectPayload
58where
59 T: DeserializeOwned,
60{
61 type Error = serde_json::Error;
62
63 fn extract_defuse_payload(self) -> Result<DefusePayload<T>, Self::Error> {
64 let TonConnectPayloadSchema::Text { text } = self.payload else {
65 return Err(Error::custom("only text payload supported"));
66 };
67
68 let p: DefusePayload<T> = serde_json::from_str(&text)?;
69
70 if p.deadline < self.timestamp {
80 return Err(Error::custom("deadline < timestamp"));
81 }
82
83 Ok(p)
84 }
85}