use crate::errors::{GumError, PostError};
use crate::events::{PostCommentNew, PostDeleted, PostNew, PostUpdated};
use crate::state::{Post, Profile, User, MAX_LEN_URI};
use gpl_session::{session_auth_or, Session};
use anchor_lang::prelude::*;
use std::convert::AsRef;
use crate::constants::*;
use gpl_session::{SessionError, SessionToken};
#[derive(Accounts, Session)]
#[instruction(metadata_uri: String, random_hash: [u8;32])]
pub struct CreatePost<'info> {
#[account(
init,
seeds = [
POST_PREFIX_SEED.as_bytes(),
random_hash.as_ref(),
],
bump,
payer = authority,
space = Post::LEN
)]
pub post: Account<'info, Post>,
#[account(
seeds = [
PROFILE_PREFIX_SEED.as_bytes(),
profile.namespace.as_ref().as_bytes(),
user.to_account_info().key.as_ref(),
],
bump,
has_one = user,
)]
pub profile: Account<'info, Profile>,
#[account(
seeds = [
USER_PREFIX_SEED.as_bytes(),
user.random_hash.as_ref(),
],
bump,
)]
pub user: Account<'info, User>,
#[session(
signer = authority,
authority = user.authority.key()
)]
pub session_token: Option<Account<'info, SessionToken>>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[session_auth_or(
ctx.accounts.user.authority.key() == ctx.accounts.authority.key(),
GumError::UnauthorizedSigner
)]
pub fn create_post_handler(
ctx: Context<CreatePost>,
metadata_uri: String,
random_hash: [u8; 32],
) -> Result<()> {
require!(metadata_uri.len() <= MAX_LEN_URI, PostError::URITooLong);
let post = &mut ctx.accounts.post;
post.metadata_uri = metadata_uri;
post.random_hash = random_hash;
post.profile = *ctx.accounts.profile.to_account_info().key;
emit!(PostNew {
post: *post.to_account_info().key,
profile: *ctx.accounts.profile.to_account_info().key,
user: *ctx.accounts.user.to_account_info().key,
random_hash: random_hash,
metadata_uri: post.metadata_uri.clone(),
timestamp: Clock::get()?.unix_timestamp,
});
Ok(())
}
#[derive(Accounts, Session)]
#[instruction(metadata_uri: String)]
pub struct UpdatePost<'info> {
#[account(
mut,
seeds = [
POST_PREFIX_SEED.as_bytes(),
post.random_hash.as_ref(),
],
bump,
has_one = profile,
)]
pub post: Account<'info, Post>,
#[account(
seeds = [
PROFILE_PREFIX_SEED.as_bytes(),
profile.namespace.as_ref().as_bytes(),
user.to_account_info().key.as_ref(),
],
bump,
has_one = user,
)]
pub profile: Account<'info, Profile>,
#[account(
seeds = [
USER_PREFIX_SEED.as_bytes(),
user.random_hash.as_ref(),
],
bump,
)]
pub user: Account<'info, User>,
#[session(
signer = authority,
authority = user.authority.key()
)]
pub session_token: Option<Account<'info, SessionToken>>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[session_auth_or(
ctx.accounts.user.authority.key() == ctx.accounts.authority.key(),
GumError::UnauthorizedSigner
)]
pub fn update_post_handler(ctx: Context<UpdatePost>, metadata_uri: String) -> Result<()> {
require!(metadata_uri.len() <= MAX_LEN_URI, PostError::URITooLong);
let post = &mut ctx.accounts.post;
post.metadata_uri = metadata_uri;
emit!(PostUpdated {
post: *post.to_account_info().key,
profile: *ctx.accounts.profile.to_account_info().key,
user: *ctx.accounts.user.to_account_info().key,
metadata_uri: post.metadata_uri.clone(),
timestamp: Clock::get()?.unix_timestamp,
});
Ok(())
}
#[derive(Accounts, Session)]
#[instruction(metadata_uri: String, random_hash: [u8;32])]
pub struct CreateComment<'info> {
#[account(
init,
seeds = [
POST_PREFIX_SEED.as_bytes(),
random_hash.as_ref(),
],
bump,
payer = authority,
space = Post::LEN
)]
pub post: Account<'info, Post>,
#[account(
seeds = [
PROFILE_PREFIX_SEED.as_bytes(),
profile.namespace.as_ref().as_bytes(),
user.to_account_info().key.as_ref(),
],
bump,
has_one = user,
)]
pub profile: Account<'info, Profile>,
#[account(
seeds = [
USER_PREFIX_SEED.as_bytes(),
user.random_hash.as_ref(),
],
bump,
)]
pub user: Account<'info, User>,
#[account(
seeds = [
POST_PREFIX_SEED.as_bytes(),
reply_to.random_hash.as_ref(),
],
bump,
)]
pub reply_to: Account<'info, Post>,
#[session(
signer = authority,
authority = user.authority.key()
)]
pub session_token: Option<Account<'info, SessionToken>>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[session_auth_or(
ctx.accounts.user.authority.key() == ctx.accounts.authority.key(),
GumError::UnauthorizedSigner
)]
pub fn create_comment_handler(
ctx: Context<CreateComment>,
metadata_uri: String,
random_hash: [u8; 32],
) -> Result<()> {
require!(metadata_uri.len() <= MAX_LEN_URI, PostError::URITooLong);
let post = &mut ctx.accounts.post;
post.metadata_uri = metadata_uri;
post.random_hash = random_hash;
post.profile = *ctx.accounts.profile.to_account_info().key;
post.reply_to = Some(*ctx.accounts.reply_to.to_account_info().key);
emit!(PostCommentNew {
post: *post.to_account_info().key,
profile: *ctx.accounts.profile.to_account_info().key,
user: *ctx.accounts.user.to_account_info().key,
random_hash: random_hash,
metadata_uri: post.metadata_uri.clone(),
reply_to: *ctx.accounts.reply_to.to_account_info().key,
timestamp: Clock::get()?.unix_timestamp,
});
Ok(())
}
#[derive(Accounts, Session)]
pub struct DeletePost<'info> {
#[account(
mut,
seeds = [
POST_PREFIX_SEED.as_bytes(),
post.random_hash.as_ref(),
],
bump,
has_one = profile,
close = refund_receiver,
)]
pub post: Account<'info, Post>,
#[account(
seeds = [
PROFILE_PREFIX_SEED.as_bytes(),
profile.namespace.as_ref().as_bytes(),
user.to_account_info().key.as_ref(),
],
bump,
has_one = user,
)]
pub profile: Account<'info, Profile>,
#[account(
seeds = [
USER_PREFIX_SEED.as_bytes(),
user.random_hash.as_ref(),
],
bump,
)]
pub user: Account<'info, User>,
#[session(
signer = authority,
authority = user.authority.key()
)]
pub session_token: Option<Account<'info, SessionToken>>,
#[account(mut)]
pub authority: Signer<'info>,
#[account(mut, constraint = refund_receiver.key() == user.authority)]
pub refund_receiver: SystemAccount<'info>,
pub system_program: Program<'info, System>,
}
#[session_auth_or(
ctx.accounts.user.authority.key() == ctx.accounts.authority.key(),
GumError::UnauthorizedSigner
)]
pub fn delete_post_handler(ctx: Context<DeletePost>) -> Result<()> {
emit!(PostDeleted {
post: *ctx.accounts.post.to_account_info().key,
profile: *ctx.accounts.profile.to_account_info().key,
user: *ctx.accounts.user.to_account_info().key,
timestamp: Clock::get()?.unix_timestamp,
});
Ok(())
}