1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
use crate::instructions::CreateProfileArgs;
use anchor_lang::prelude::*;
use hpl_utils::Default;
use std::collections::HashMap;
/// User State Account -
/// This account represents the state of a user on the Solana blockchain.
/// PDA: [ 'user', username ]
/// Category: user_state
#[account]
#[derive(PartialEq, Eq, Debug)]
pub struct User {
/// Bump value used for PDA.
pub bump: u8,
/// Public key of the primary wallet associated with the user.
pub primary_wallet: Pubkey,
/// List of public keys representing secondary wallets associated with the user.
pub secondary_wallets: Vec<Pubkey>,
/// Username of the user.
pub username: String,
/// Full name of the user.
pub name: String,
/// User's biography or description.
pub bio: String,
/// URL of the user's profile picture (pfp).
pub pfp: String,
}
/// Default implementation for the `User` struct.
/// It sets default values for each field when creating a new `User` instance.
impl Default for User {
const LEN: usize = 160 + 8; // base size + 8 align
/// Sets default values for each field of the `User` struct.
fn set_defaults(&mut self) {
self.bump = 0;
self.primary_wallet = Pubkey::default();
self.secondary_wallets = vec![];
self.username = String::from("");
self.name = String::from("");
self.bio = String::from("");
self.pfp = String::from("");
}
}
/// Account representing a wallet resolver.
/// PDA: [ 'wallet_resolver', wallet ]
/// Category: user_state
#[account]
pub struct WalletResolver {
/// Bump value used for PDA.
pub bump: u8,
/// Public key of the user associated with this wallet resolver.
pub user: Pubkey,
/// Public key of the wallet being resolved.
pub wallet: Pubkey,
}
/// Default implementation for the `WalletResolver` struct.
/// It sets default values for each field when creating a new `WalletResolver` instance.
impl Default for WalletResolver {
const LEN: usize = 65 + 8; // base size + 8 align
/// Sets default values for each field of the `WalletResolver` struct.
fn set_defaults(&mut self) {
self.bump = 0;
self.user = Pubkey::default();
self.wallet = Pubkey::default();
}
}
/// Account representing user profile information.
/// This account stores a user's profile data associated with a specific project.
/// PDA: [ 'profile', project, user, identity ]
/// Category: user_state
#[account]
#[derive(PartialEq, Eq, Debug)]
pub struct Profile {
/// Bump value used for PDA.
pub bump: u8,
/// Public key of the project associated with this profile.
pub project: Pubkey,
/// Public key of the user associated with this profile.
pub user: Pubkey,
/// Identity of the profile, which can be Main, Wallet, or a custom Value.
pub identity: ProfileIdentity,
/// HashMap storing profile data as key-value pairs.
pub data: HashMap<String, ProfileData>,
/// HashMap storing profile data as key-value pairs.
pub app_context: HashMap<String, ProfileData>,
/// Profile specific name.
pub name: Option<String>,
/// Profile specific description.
pub bio: Option<String>,
/// Profile specific pfp url.
pub pfp: Option<String>,
}
/// Default implementation for the `Profile` struct.
/// It sets default values for each field when creating a new `Profile` instance.
impl Default for Profile {
const LEN: usize = 8 + 1 + 32 + 32 + 33 + 10 + 10; // Optional fields are not included in the LEN
// const LEN: usize = 168 + 80 + 8; // base size + 8 align
/// Sets default values for each field of the `Profile` struct.
fn set_defaults(&mut self) {
self.bump = 0;
self.project = Pubkey::default();
self.user = Pubkey::default();
self.identity = ProfileIdentity::Main;
self.data = HashMap::new();
self.app_context = HashMap::new();
self.name = None;
self.bio = None;
self.pfp = None;
}
}
impl Profile {
pub fn get_initial_len(create_args: &CreateProfileArgs) -> usize {
let mut len = Self::LEN;
len += 1
+ (if let Some(value) = &create_args.name {
value.len()
} else {
0
});
len += 1
+ (if let Some(value) = &create_args.bio {
value.len()
} else {
0
});
len += 1
+ (if let Some(value) = &create_args.pfp {
value.len()
} else {
0
});
len
}
}
/// Enum representing different types of profile identity.
/// A profile can be Main, Wallet, or a custom Value.
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Eq, PartialEq)]
pub enum ProfileIdentity {
Main,
Value { value: String },
}
/// Implementation for the `ProfileIdentity` enum.
impl ProfileIdentity {
/// Converts the `ProfileIdentity` enum to bytes.
pub fn to_bytes(&self) -> Vec<u8> {
match self {
ProfileIdentity::Main => {
let value = String::from("main");
value.as_bytes().to_vec()
}
ProfileIdentity::Value { value } => value.as_bytes().to_vec(),
}
}
/// Converts the `ProfileIdentity` enum to a string representation.
pub fn to_string(&self) -> String {
match self {
ProfileIdentity::Main => String::from("main"),
ProfileIdentity::Value { value } => value.clone(),
}
}
}
/// Enum representing different types of profile data.
/// Profile data can be a SingleValue, MultiValue, or an Entity represented by a merkle tree.
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Eq, Debug, PartialEq)]
pub enum ProfileData {
SingleValue(String),
MultiValue(Vec<String>),
}
/// Implementation for the `ProfileData` enum.
impl ProfileData {
/// Length of the `ProfileData` enum in bytes.
pub const LEN: usize = 8 + 40;
pub fn size(&self) -> usize {
match self {
Self::SingleValue(value) => value.len(),
Self::MultiValue(value) => {
let mut len = 4;
for v in value {
len += v.len();
}
len
}
}
}
}