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