gpl_core/instructions/
profile_metadata.rs

1use crate::errors::ProfileMetadataError;
2use crate::events::{ProfileMetadataDeleted, ProfileMetadataNew, ProfileMetadataUpdated};
3use crate::state::{Profile, ProfileMetadata, User, MAX_LEN_URI};
4
5use anchor_lang::prelude::*;
6use std::convert::AsRef;
7
8use crate::constants::*;
9
10// Create ProfileMetadata
11#[derive(Accounts)]
12#[instruction(metadata_uri: String)]
13pub struct CreateProfileMetadata<'info> {
14    // The account that will be initialized as a ProfileMetadata
15    #[account(
16        init,
17        seeds = [
18            PROFILE_METADATA_PREFIX_SEED.as_bytes(),
19            profile.to_account_info().key.as_ref(),
20        ],
21        bump,
22        payer = authority,
23        space = ProfileMetadata::LEN
24    )]
25    pub profile_metadata: Account<'info, ProfileMetadata>,
26    #[account(
27        seeds = [
28            PROFILE_PREFIX_SEED.as_bytes(),
29            profile.namespace.as_ref().as_bytes(),
30            user.to_account_info().key.as_ref(),
31        ],
32        bump,
33        has_one = user,
34    )]
35    pub profile: Account<'info, Profile>,
36    #[account(
37        seeds = [
38            USER_PREFIX_SEED.as_bytes(),
39            user.random_hash.as_ref(),
40        ],
41        bump,
42        has_one = authority,
43    )]
44    pub user: Account<'info, User>,
45    #[account(mut)]
46    pub authority: Signer<'info>,
47    // The system program
48    pub system_program: Program<'info, System>,
49}
50
51// Handler to create a new ProfileMetadata account
52pub fn create_profile_metadata_handler(
53    ctx: Context<CreateProfileMetadata>,
54    metadata_uri: String,
55) -> Result<()> {
56    // CHECK metadata_uri length
57    require!(
58        metadata_uri.len() <= MAX_LEN_URI,
59        ProfileMetadataError::URITooLong
60    );
61
62    let profile_metadata = &mut ctx.accounts.profile_metadata;
63    profile_metadata.metadata_uri = metadata_uri;
64    profile_metadata.profile = *ctx.accounts.profile.to_account_info().key;
65    // emit new ProfileMetadata event
66    emit!(ProfileMetadataNew {
67        profile_metadata: *profile_metadata.to_account_info().key,
68        profile: *ctx.accounts.profile.to_account_info().key,
69        user: *ctx.accounts.user.to_account_info().key,
70        metadata_uri: profile_metadata.metadata_uri.clone(),
71        timestamp: Clock::get()?.unix_timestamp,
72    });
73    Ok(())
74}
75
76// Update a ProfileMetadata account
77#[derive(Accounts)]
78#[instruction(metadata_uri: String)]
79pub struct UpdateProfileMetadata<'info> {
80    // The ProfileMetadata account to update
81    #[account(
82        mut,
83        seeds = [
84            PROFILE_METADATA_PREFIX_SEED.as_bytes(),
85            profile.to_account_info().key.as_ref(),
86        ],
87        bump,
88        has_one = profile,
89    )]
90    pub profile_metadata: Account<'info, ProfileMetadata>,
91    #[account(
92        seeds = [
93            PROFILE_PREFIX_SEED.as_bytes(),
94            profile.namespace.as_ref().as_bytes(),
95            user.to_account_info().key.as_ref(),
96        ],
97        bump,
98        has_one = user,
99    )]
100    pub profile: Account<'info, Profile>,
101    #[account(
102        seeds = [
103            USER_PREFIX_SEED.as_bytes(),
104            user.random_hash.as_ref(),
105        ],
106        bump,
107        has_one = authority,
108    )]
109    pub user: Account<'info, User>,
110    #[account(mut)]
111    pub authority: Signer<'info>,
112    pub system_program: Program<'info, System>,
113}
114
115// Handler to update a ProfileMetadata account
116pub fn update_profile_metadata_handler(
117    ctx: Context<UpdateProfileMetadata>,
118    metadata_uri: String,
119) -> Result<()> {
120    // CHECK metadata_uri length
121    require!(
122        metadata_uri.len() <= MAX_LEN_URI,
123        ProfileMetadataError::URITooLong
124    );
125    let profile_metadata = &mut ctx.accounts.profile_metadata;
126    profile_metadata.metadata_uri = metadata_uri;
127    // emit update ProfileMetadata event
128    emit!(ProfileMetadataUpdated {
129        profile_metadata: *profile_metadata.to_account_info().key,
130        profile: *ctx.accounts.profile.to_account_info().key,
131        user: *ctx.accounts.user.to_account_info().key,
132        metadata_uri: profile_metadata.metadata_uri.clone(),
133        timestamp: Clock::get()?.unix_timestamp,
134    });
135    Ok(())
136}
137
138// Delete a ProfileMetadata account
139#[derive(Accounts)]
140pub struct DeleteProfileMetadata<'info> {
141    // The ProfileMetadata account to delete
142    #[account(
143        mut,
144        seeds = [
145            PROFILE_METADATA_PREFIX_SEED.as_bytes(),
146            profile.to_account_info().key.as_ref(),
147        ],
148        bump,
149        has_one = profile,
150        close = authority,
151    )]
152    pub profile_metadata: Account<'info, ProfileMetadata>,
153    #[account(
154        seeds = [
155            PROFILE_PREFIX_SEED.as_bytes(),
156            profile.namespace.as_ref().as_bytes(),
157            user.to_account_info().key.as_ref(),
158        ],
159        bump,
160        has_one = user,
161    )]
162    pub profile: Account<'info, Profile>,
163    #[account(
164        seeds = [
165            USER_PREFIX_SEED.as_bytes(),
166            user.random_hash.as_ref(),
167        ],
168        bump,
169        has_one = authority,
170    )]
171    pub user: Account<'info, User>,
172    #[account(mut)]
173    pub authority: Signer<'info>,
174    pub system_program: Program<'info, System>,
175}
176
177// Handler to delete a ProfileMetadata account
178pub fn delete_profile_metadata_handler(ctx: Context<DeleteProfileMetadata>) -> Result<()> {
179    // emit delete ProfileMetadata event
180    emit!(ProfileMetadataDeleted {
181        profile_metadata: *ctx.accounts.profile_metadata.to_account_info().key,
182        profile: *ctx.accounts.profile.to_account_info().key,
183        user: *ctx.accounts.user.to_account_info().key,
184        timestamp: Clock::get()?.unix_timestamp,
185    });
186    Ok(())
187}