Skip to content
This repository was archived by the owner on Sep 7, 2023. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions programs/wordcel/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ pub enum PostError {
pub enum ConnectionError {
SelfFollow,
}

#[error_code]
pub enum AdminError {
UnAuthorizedAccess,
}
214 changes: 214 additions & 0 deletions programs/wordcel/src/instructions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::*;
use invite::program::Invite as InvitationProgram;
use invite::Invite;
use std::str::FromStr;

#[derive(Accounts)]
#[instruction(random_hash: [u8;32])]
Expand Down Expand Up @@ -32,6 +33,44 @@ pub struct Initialize<'info> {
pub invitation_program: Program<'info, InvitationProgram>,
}

#[derive(Accounts)]
pub struct TransferProfile<'info> {
#[account(
mut,
seeds = [
b"profile".as_ref(),
&profile.random_hash
],
bump,
)]
pub profile: Account<'info, Profile>,
#[account(
owner = invitation_program.key(),
seeds = [
Invite::PREFIX.as_bytes().as_ref(),
authority.key().as_ref()
],
seeds::program = invitation_program.key(),
bump = invitation.bump
)]
pub invitation: Account<'info, Invite>,
#[account(
owner = invitation_program.key(),
seeds = [
Invite::PREFIX.as_bytes().as_ref(),
new_authority.key().as_ref()
],
seeds::program = invitation_program.key(),
bump = new_authority_invitation.bump
)]
pub new_authority_invitation: Account<'info, Invite>,
#[account(mut)]
pub authority: Signer<'info>,
pub new_authority: SystemAccount<'info>,
pub system_program: Program<'info, System>,
pub invitation_program: Program<'info, InvitationProgram>,
}

#[derive(Accounts)]
#[instruction(metadata_uri: String, random_hash: [u8;32])]
pub struct CreatePost<'info> {
Expand Down Expand Up @@ -162,3 +201,178 @@ pub struct CloseConnection<'info> {
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
#[instruction(random_hash: [u8; 32])]
pub struct InitializeConnectionBox<'info> {
#[account(
init,
seeds = [
b"connection_box".as_ref(),
&random_hash
],
bump,
payer = authority,
space = ConnectionBox::LEN
)]
pub connection_box: Account<'info, ConnectionBox>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct TranferConnectionBox<'info> {
#[account(
mut,
seeds = [
b"connection_box".as_ref(),
&connection_box.random_hash
],
bump,
)]
pub connection_box: Account<'info, ConnectionBox>,
#[account(mut)]
pub authority: Signer<'info>,
pub new_authority: SystemAccount<'info>,
pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct InitializeConnectionV2<'info> {
#[account(
init,
seeds = [
b"connection_v2".as_ref(),
profile.key().as_ref()
],
bump,
payer = authority,
// Don't allow the user to follow themselves
constraint = profile.authority.key() != connection_box.authority.key() @ConnectionError::SelfFollow,
space = ConnectionV2::LEN
)]
pub connection: Account<'info, ConnectionV2>,
#[account(has_one=authority)]
pub connection_box: Account<'info, ConnectionBox>,
pub profile: Account<'info, Profile>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct CloseConnectionV2<'info> {
#[account(
mut,
seeds = [
b"connection_v2".as_ref(),
profile.key().as_ref()
],
bump = connection.bump,
has_one = connection_box,
close = authority
)]
pub connection: Account<'info, ConnectionV2>,
#[account(has_one=authority)]
pub connection_box: Account<'info, ConnectionBox>,
pub profile: Account<'info, Profile>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct MigrateConnectionToV2<'info> {
#[account(
mut,
seeds = [
b"connection".as_ref(),
authority.key().as_ref(),
profile.key().as_ref()
],
bump = connection_v1.bump,
has_one = authority,
close = authority
)]
pub connection_v1: Account<'info, Connection>,
#[account(
init,
seeds = [
b"connection_v2".as_ref(),
profile.key().as_ref()
],
bump,
payer = authority,
// Don't allow the user to follow themselves
constraint = profile.authority.key() != connection_box.authority.key() @ConnectionError::SelfFollow,
space = ConnectionV2::LEN
)]
pub connection_v2: Account<'info, ConnectionV2>,
#[account(has_one=authority)]
pub connection_box: Account<'info, ConnectionBox>,
pub profile: Account<'info, Profile>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}

// NOTE: This instruction doesn't close the existing connection, but merely copies it over to
// connection v2.
// This is added so that the admin can easily migrate the conenctions if they chose to by paying
// for it and this helps us offer a better user experience.

#[derive(Accounts)]
#[instruction(random_hash: [u8; 32])]
pub struct MigrateConnectionToV2Admin<'info> {
#[account(
seeds = [
b"connection".as_ref(),
authority.key().as_ref(),
profile.key().as_ref()
],
bump = connection_v1.bump,
has_one = authority,
)]
pub connection_v1: Account<'info, Connection>,
#[account(
init,
seeds = [
b"connection_v2".as_ref(),
profile.key().as_ref()
],
bump,
payer = payer,
// Don't allow the user to follow themselves
constraint = profile.authority.key() != authority.key() @ConnectionError::SelfFollow,
space = ConnectionV2::LEN
)]
pub connection_v2: Account<'info, ConnectionV2>,
#[account(
init,
seeds = [
b"connection_box".as_ref(),
&random_hash
],
bump,
payer = payer,
space = ConnectionBox::LEN
)]
pub connection_box: Account<'info, ConnectionBox>,
pub profile: Account<'info, Profile>,
pub authority: SystemAccount<'info>,
#[account(mut, constraint = is_admin(payer.key()) @AdminError::UnAuthorizedAccess)]
pub payer: Signer<'info>,
pub system_program: Program<'info, System>,
}

fn is_admin(key: Pubkey) -> bool {
let admin_keys: Vec<Pubkey> = [
// Wordcel Admin
"8f2yAM5ufEC9WgHYdAxeDgpZqE1B1Q47CciPRZaDN3jc",
]
.iter()
.map(|k| Pubkey::from_str(k).unwrap())
.collect();
admin_keys.contains(&key)
}
63 changes: 63 additions & 0 deletions programs/wordcel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ pub mod wordcel {
Ok(())
}

pub fn transfer_profile(ctx: Context<TransferProfile>) -> Result<()> {
let profile = &mut ctx.accounts.profile;
profile.authority = *ctx.accounts.new_authority.to_account_info().key;
Ok(())
}

pub fn create_post(
ctx: Context<CreatePost>,
metadata_uri: String,
Expand Down Expand Up @@ -83,6 +89,7 @@ pub mod wordcel {
Ok(())
}

// Marked for deprecation
pub fn initialize_connection(ctx: Context<InitializeConnection>) -> Result<()> {
let connection = &mut ctx.accounts.connection;
connection.bump = *ctx.bumps.get("connection").unwrap();
Expand All @@ -100,7 +107,63 @@ pub mod wordcel {
Ok(())
}

// Marked for deprecation
pub fn close_connection(_ctx: Context<CloseConnection>) -> Result<()> {
Ok(())
}

pub fn initialize_connection_v2(ctx: Context<InitializeConnectionV2>) -> Result<()> {
let connection = &mut ctx.accounts.connection;
connection.bump = *ctx.bumps.get("connection").unwrap();
connection.profile = *ctx.accounts.profile.to_account_info().key;
connection.connection_box = *ctx.accounts.connection_box.to_account_info().key;
Ok(())
}

pub fn close_connection_v2(_ctx: Context<CloseConnectionV2>) -> Result<()> {
Ok(())
}

pub fn initialize_connection_box(
ctx: Context<InitializeConnectionBox>,
random_hash: [u8; 32],
) -> Result<()> {
let connection_box = &mut ctx.accounts.connection_box;
connection_box.bump = *ctx.bumps.get("connection_box").unwrap();
connection_box.random_hash = random_hash;
connection_box.authority = *ctx.accounts.authority.to_account_info().key;
Ok(())
}

pub fn transfer_connection_box(ctx: Context<TranferConnectionBox>) -> Result<()> {
let connection_box = &mut ctx.accounts.connection_box;
connection_box.authority = *ctx.accounts.new_authority.to_account_info().key;
Ok(())
}

pub fn migrate_to_connectionv2(ctx: Context<MigrateConnectionToV2>) -> Result<()> {
let connection = &mut ctx.accounts.connection_v2;
connection.bump = *ctx.bumps.get("connection_v2").unwrap();
connection.profile = *ctx.accounts.profile.to_account_info().key;
connection.connection_box = *ctx.accounts.connection_box.to_account_info().key;
Ok(())
}

pub fn migrate_to_connectionv2_admin(
ctx: Context<MigrateConnectionToV2Admin>,
random_hash: [u8; 32],
) -> Result<()> {
// Set up connection box
let connection_box = &mut ctx.accounts.connection_box;
connection_box.bump = *ctx.bumps.get("connection_box").unwrap();
connection_box.random_hash = random_hash;
connection_box.authority = *ctx.accounts.authority.to_account_info().key;

// Set connection
let connection = &mut ctx.accounts.connection_v2;
connection.bump = *ctx.bumps.get("connection_v2").unwrap();
connection.profile = *ctx.accounts.profile.to_account_info().key;
connection.connection_box = *ctx.accounts.connection_box.to_account_info().key;
Ok(())
}
}
24 changes: 24 additions & 0 deletions programs/wordcel/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,27 @@ pub struct Connection {
impl Connection {
pub const LEN: usize = 8 + size_of::<Self>();
}

#[account]
#[derive(Default)]
pub struct ConnectionBox {
pub authority: Pubkey,
pub random_hash: [u8; 32],
pub bump: u8,
}

impl ConnectionBox {
pub const LEN: usize = 8 + size_of::<Self>();
}

#[account]
#[derive(Default)]
pub struct ConnectionV2 {
pub profile: Pubkey,
pub connection_box: Pubkey,
pub bump: u8,
}

impl ConnectionV2 {
pub const LEN: usize = 8 + size_of::<Self>();
}
Loading