miracle_api/dmt/social_claim_data.rs
1use steel::*;
2
3// ===== SOCIAL MARKETING REWARDS SYSTEM INSTRUCTIONS =====
4
5/// Social claim data for social media engagement rewards.
6///
7/// This struct contains the data required for claiming social marketing rewards.
8/// Social rewards require payment activity in the same epoch and are verified
9/// through oracle signatures to prevent gaming.
10///
11/// ## Data Structure
12/// ```rust
13/// struct SocialClaimData {
14/// post_url: String, // Social media post URL
15/// oracle_signature: [u8; 64], // Oracle verification signature
16/// engagement_score: u32, // Future: engagement-based rewards
17/// post_timestamp: i64, // When post was made
18/// _padding: [u8; 4], // For future extensibility
19/// }
20/// ```
21///
22/// ## Oracle Signature Message Format
23/// The oracle must sign a message with this format:
24///
25/// `epoch:user_pubkey:post_url:engagement_score:post_timestamp`
26///
27/// Example: `"100:ABC123...:https://twitter.com/user/123:500:1640995200"`
28///
29/// This format prevents replay attacks by including epoch and user context.
30///
31/// ## Verification Requirements
32/// - Payment activity required in same epoch
33/// - Oracle signature verification
34/// - Daily limits enforcement
35/// - Content requirements (#MiracleRewards, @MiracleProtocol)
36///
37/// ## Anti-Gaming Measures
38/// - Daily limits per user (max 3 posts per day)
39/// - Payment requirement ensures real users
40/// - Oracle verification prevents fake posts
41/// - Content requirements ensure quality engagement
42/// - Epoch-specific signatures prevent replay attacks
43#[repr(C)]
44#[derive(Debug, Clone, Copy, Pod, Zeroable)]
45pub struct SocialClaimData {
46 /// Social media post URL for verification.
47 /// Must contain required hashtags and mentions.
48 pub post_url: [u8; 256], // Fixed-size URL field
49
50 /// Oracle signature for post verification.
51 /// This signature validates that the post meets requirements.
52 pub oracle_signature: [u8; 64],
53
54 /// Timestamp when the post was made.
55 /// Used for daily limit calculations and verification.
56 pub post_timestamp: [u8; 8], // i64
57
58 /// Engagement score for future tiered rewards.
59 /// Currently unused, reserved for future engagement-based rewards.
60 pub engagement_score: [u8; 4], // u32
61
62 /// Padding for future extensibility.
63 /// Reserved for additional social claim features.
64 pub _padding: [u8; 4],
65}
66
67impl SocialClaimData {
68 /// Deserialize from bytes manually
69 pub fn from_bytes(data: &[u8]) -> Result<Self, &'static str> {
70 let expected_size = std::mem::size_of::<Self>();
71 if data.len() < expected_size {
72 return Err("Insufficient data for SocialClaimData");
73 }
74
75 let post_url: [u8; 256] = data[0..256].try_into().map_err(|_| "Invalid post_url")?;
76 let oracle_signature: [u8; 64] = data[256..320]
77 .try_into()
78 .map_err(|_| "Invalid oracle_signature")?;
79 let post_timestamp: [u8; 8] = data[320..328]
80 .try_into()
81 .map_err(|_| "Invalid post_timestamp")?;
82 let engagement_score: [u8; 4] = data[328..332]
83 .try_into()
84 .map_err(|_| "Invalid engagement_score")?;
85 let _padding: [u8; 4] = data[332..336].try_into().map_err(|_| "Invalid padding")?;
86
87 Ok(Self {
88 post_url,
89 oracle_signature,
90 engagement_score,
91 post_timestamp,
92 _padding,
93 })
94 }
95}