From d4986533399054f8cdb83abcb299b04bf78c3955 Mon Sep 17 00:00:00 2001 From: vjgpt Date: Thu, 12 Jan 2023 06:05:09 +0000 Subject: [PATCH 1/4] adding instruction for UpdatePostAsEditor and DeletePostAsEditor --- .gitignore | 2 +- programs/wordcel/src/instructions.rs | 121 +++++++++++++++++++++++++-- programs/wordcel/src/lib.rs | 28 +++++-- 3 files changed, 136 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 870608d..db011ca 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,5 @@ target **/*.rs.bk node_modules -test_ledger/ +test-ledger/ .goki/ diff --git a/programs/wordcel/src/instructions.rs b/programs/wordcel/src/instructions.rs index 63af5aa..c058b8e 100644 --- a/programs/wordcel/src/instructions.rs +++ b/programs/wordcel/src/instructions.rs @@ -25,8 +25,8 @@ pub struct CreateEditor<'info> { init, seeds = [ b"editor".as_ref(), - host_profile.authority.key().as_ref(), - editor_profile.authority.key().as_ref() + host_profile.key().as_ref(), + editor_profile.key().as_ref() ], bump, payer = authority, @@ -47,8 +47,8 @@ pub struct RemoveEditor<'info> { mut, seeds = [ b"editor".as_ref(), - host_profile.authority.key().as_ref(), - editor_profile.authority.key().as_ref() + host_profile.key().as_ref(), + editor_profile.key().as_ref() ], bump = editor.bump, close = authority, @@ -63,7 +63,7 @@ pub struct RemoveEditor<'info> { } #[derive(Accounts)] -#[instruction(metadata_uri: String)] +#[instruction(metadata_uri: String, random_hash: [u8;32])] pub struct CreatePostAsEditor<'info> { // Checks if the original profile was supplied and if the profile authority is the signer #[account( @@ -76,7 +76,61 @@ pub struct CreatePostAsEditor<'info> { )] pub editor_profile: Account<'info, Profile>, - // Checks if a post was supplied and it is part of the supplied profile. + #[account( + seeds = [ + b"profile".as_ref(), + &host_profile.random_hash + ], + bump = host_profile.bump + )] + pub host_profile: Account<'info, Profile>, + + #[account( + has_one = host_profile, + seeds = [ + b"editor".as_ref(), + host_profile.key().as_ref(), + editor_profile.key().as_ref() + ], + bump = editor.bump + )] + pub editor: Account<'info, Editor>, + + // Initializes a new post account and checks if the signer is the authority + #[account( + init, + constraint = editor_profile.to_account_info().key() == editor.host_profile || editor_profile.to_account_info().key() == editor.editor_profile, + seeds = [ + b"post".as_ref(), + &random_hash + ], + bump, + payer = authority, + space = Post::LEN + )] + pub post: Account<'info, Post>, + + #[account(mut)] + pub authority: Signer<'info>, + + pub system_program: Program<'info, System>, +} + +#[derive(Accounts)] +#[instruction(metadata_uri: String)] +pub struct UpdatePostAsEditor<'info> { + // Checks if the original profile was supplied and if the profile authority is the signer + #[account( + has_one = authority, + seeds = [ + b"profile".as_ref(), + &editor_profile.random_hash + ], + bump = editor_profile.bump + )] + pub editor_profile: Account<'info, Profile>, + + // Mutable Account of Post that has to be updated #[account( mut, constraint = post.profile == editor_profile.to_account_info().key() || post.profile == host_profile.to_account_info().key(), @@ -101,8 +155,8 @@ pub struct CreatePostAsEditor<'info> { has_one = host_profile, seeds = [ b"editor".as_ref(), - host_profile.authority.key().as_ref(), - editor_profile.authority.key().as_ref() + host_profile.key().as_ref(), + editor_profile.key().as_ref() ], bump = editor.bump )] @@ -114,6 +168,57 @@ pub struct CreatePostAsEditor<'info> { pub system_program: Program<'info, System>, } +#[derive(Accounts)] +pub struct DeletePostAsEditor<'info> { + // Checks if the original profile was supplied and if the profile authority is the signer + #[account( + has_one = authority, + seeds = [ + b"profile".as_ref(), + &editor_profile.random_hash + ], + bump = editor_profile.bump + )] + pub editor_profile: Account<'info, Profile>, + + #[account( + seeds = [ + b"profile".as_ref(), + &host_profile.random_hash + ], + bump = host_profile.bump + )] + pub host_profile: Account<'info, Profile>, + + #[account( + has_one = host_profile, + seeds = [ + b"editor".as_ref(), + host_profile.key().as_ref(), + editor_profile.key().as_ref() + ], + bump = editor.bump + )] + pub editor: Account<'info, Editor>, + + // Mutable Account of Post that has to be deleted + #[account( + mut, + seeds = [ + b"post".as_ref(), + &post.random_hash + ], + bump = post.bump, + close = authority + )] + pub post: Account<'info, Post>, + + #[account(mut)] + pub authority: Signer<'info>, + + pub system_program: Program<'info, System>, +} + #[derive(Accounts)] #[instruction(metadata_uri: String, random_hash: [u8;32])] pub struct CreatePost<'info> { diff --git a/programs/wordcel/src/lib.rs b/programs/wordcel/src/lib.rs index 3df149d..a5d5b64 100644 --- a/programs/wordcel/src/lib.rs +++ b/programs/wordcel/src/lib.rs @@ -11,7 +11,7 @@ use instructions::*; use state::*; #[cfg(not(any(feature = "mainnet", feature = "devnet")))] -declare_id!("v4enuof3drNvU2Y3b5m7K62hMq3QUP6qQSV2jjxAhkp"); +declare_id!("6bxpSrHAc9zoWHKLJX3sfudTarFaHZoKQbM2XsyjJpMF"); #[cfg(feature = "devnet")] declare_id!("D9JJgeRf2rKq5LNMHLBMb92g4ZpeMgCyvZkd7QKwSCzg"); @@ -37,7 +37,7 @@ pub mod wordcel { metadata_uri: String, random_hash: [u8; 32], ) -> Result<()> { - require_gt!(metadata_uri.len(), MAX_LEN_URI, PostError::URITooLarge); + require!(metadata_uri.len() < MAX_LEN_URI, PostError::URITooLarge); let post = &mut ctx.accounts.post; post.random_hash = random_hash; @@ -56,7 +56,7 @@ pub mod wordcel { } pub fn update_post(ctx: Context, metadata_uri: String) -> Result<()> { - require_gt!(metadata_uri.len(), MAX_LEN_URI, PostError::URITooLarge); + require!(metadata_uri.len() < MAX_LEN_URI, PostError::URITooLarge); let post = &mut ctx.accounts.post; post.metadata_uri = metadata_uri; @@ -68,7 +68,7 @@ pub mod wordcel { metadata_uri: String, random_hash: [u8; 32], ) -> Result<()> { - require_gt!(metadata_uri.len(), MAX_LEN_URI, PostError::URITooLarge); + require!(metadata_uri.len() < MAX_LEN_URI, PostError::URITooLarge); let post = &mut ctx.accounts.post; post.random_hash = random_hash; @@ -122,11 +122,27 @@ pub mod wordcel { Ok(()) } - pub fn update_post_as_editor(ctx: Context, metadata_uri: String) -> Result<()> { - require_gt!(metadata_uri.len(), MAX_LEN_URI, PostError::URITooLarge); + + pub fn create_post_as_editor(ctx: Context, metadata_uri: String, random_hash: [u8; 32]) -> Result<()> { + require!(metadata_uri.len() < MAX_LEN_URI, PostError::URITooLarge); let post = &mut ctx.accounts.post; + post.random_hash = random_hash; + post.bump = *ctx.bumps.get("post").unwrap(); + post.metadata_uri = metadata_uri; post.profile = *ctx.accounts.host_profile.to_account_info().key; Ok(()) } + + pub fn update_post_as_editor(ctx: Context, metadata_uri: String) -> Result<()> { + require!(metadata_uri.len() < MAX_LEN_URI, PostError::URITooLarge); + + let post = &mut ctx.accounts.post; + post.metadata_uri = metadata_uri; + Ok(()) + } + + pub fn delete_post_as_editor(_ctx: Context) -> Result<()> { + Ok(()) + } } From 66cf0fdf5efe2561650968f98819dcc1c3bc322e Mon Sep 17 00:00:00 2001 From: vjgpt Date: Thu, 12 Jan 2023 06:27:26 +0000 Subject: [PATCH 2/4] adding testcases for editor --- tests/editor.spec.ts | 422 ++++++++++++++++++++++++++++++++++++++++++ tests/wordcel.spec.ts | 29 +-- 2 files changed, 425 insertions(+), 26 deletions(-) create mode 100644 tests/editor.spec.ts diff --git a/tests/editor.spec.ts b/tests/editor.spec.ts new file mode 100644 index 0000000..775d169 --- /dev/null +++ b/tests/editor.spec.ts @@ -0,0 +1,422 @@ +import * as anchor from "@project-serum/anchor"; +import { Program, AnchorError } from "@project-serum/anchor"; +import { Wordcel } from "../target/types/wordcel"; +import { expect } from "chai"; +import { PublicKey } from "@solana/web3.js"; +import randombytes from "randombytes"; +import { airdrop } from "./utils"; +const { SystemProgram } = anchor.web3; +const provider = anchor.getProvider(); + +const program = anchor.workspace.Wordcel as Program; +const user = provider.wallet.publicKey; + +describe("Editor", async () => { + const host = anchor.web3.Keypair.generate(); + const host_anchor_wallet = new anchor.Wallet(host); + const editor = anchor.web3.Keypair.generate(); + const editor_anchor_wallet = new anchor.Wallet(editor); + + let hostProfileAccount: PublicKey; + let editorProfileAccount: PublicKey; + let editorAccount: PublicKey; + let postAccount: PublicKey; + + before(async () => { + // Set up host profile + await airdrop(host.publicKey); + const hostRandomHash = randombytes(32); + const hostProfileSeed = [Buffer.from("profile"), hostRandomHash]; + [hostProfileAccount] = await anchor.web3.PublicKey.findProgramAddress( + hostProfileSeed, + program.programId + ); + const host_profile_tx = await program.methods + .initialize(hostRandomHash) + .accounts({ + profile: hostProfileAccount, + user: host.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + host_profile_tx.feePayer = host.publicKey; + host_profile_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await host_anchor_wallet.signTransaction(host_profile_tx); + await provider.sendAndConfirm(host_profile_tx, [host]); + + // Set up editor profile + await airdrop(editor.publicKey); + const editorRandomHash = randombytes(32); + const editorProfileSeed = [Buffer.from("profile"), editorRandomHash]; + [editorProfileAccount] = await anchor.web3.PublicKey.findProgramAddress( + editorProfileSeed, + program.programId + ); + const editor_profile_tx = await program.methods + .initialize(editorRandomHash) + .accounts({ + profile: editorProfileAccount, + user: editor.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + editor_profile_tx.feePayer = editor.publicKey; + editor_profile_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await editor_anchor_wallet.signTransaction(editor_profile_tx); + await provider.sendAndConfirm(editor_profile_tx, [editor]); + }); + + it("create editor", async () => { + // Set up Editor + const editorSeed = [ + Buffer.from("editor"), + hostProfileAccount.toBuffer(), + editorProfileAccount.toBuffer(), + ]; + [editorAccount] = await anchor.web3.PublicKey.findProgramAddress( + editorSeed, + program.programId + ); + try { + const editor_tx = await program.methods + .createEditor() + .accounts({ + editor: editorAccount, + hostProfile: hostProfileAccount, + editorProfile: editorProfileAccount, + authority: host.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + editor_tx.feePayer = host.publicKey; + editor_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await host_anchor_wallet.signTransaction(editor_tx); + await provider.sendAndConfirm(editor_tx, [host]); + } catch (error) { + console.log(error); + } + const data = await program.account.editor.fetch(editorAccount); + expect(data.hostProfile.toString()).to.equal(hostProfileAccount.toString()); + expect(data.editorProfile.toString()).to.equal( + editorProfileAccount.toString() + ); + }); + + it("should not allow unauthorized editor creation", async () => { + const editorUser = anchor.web3.Keypair.generate(); + const editorUser_anchor_wallet = new anchor.Wallet(editorUser); + await airdrop(editorUser.publicKey); + const editorRandomHash = randombytes(32); + const editorProfileSeed = [Buffer.from("profile"), editorRandomHash]; + const [editorUserProfileAccount] = await anchor.web3.PublicKey.findProgramAddress( + editorProfileSeed, + program.programId + ); + const editor_profile_tx = await program.methods + .initialize(editorRandomHash) + .accounts({ + profile: editorUserProfileAccount, + user: editorUser.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + editor_profile_tx.feePayer = editorUser.publicKey; + editor_profile_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await editorUser_anchor_wallet.signTransaction(editor_profile_tx); + await provider.sendAndConfirm(editor_profile_tx, [editorUser]); + + const editorSeed = [ + Buffer.from("editor"), + hostProfileAccount.toBuffer(), + editorUserProfileAccount.toBuffer(), + ]; + const [editorUserAccount] = await anchor.web3.PublicKey.findProgramAddress( + editorSeed, + program.programId + ); + try { + const editor_tx = await program.methods + .createEditor() + .accounts({ + editor: editorUserAccount, + hostProfile: hostProfileAccount, + editorProfile: editorUserProfileAccount, + authority: editorUser.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + editor_tx.feePayer = editorUser.publicKey; + editor_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await editorUser_anchor_wallet.signTransaction(editor_tx); + await provider.sendAndConfirm(editor_tx, [editorUser]); + } catch (error) { + expect(error).to.be.an("error"); + expect(error.toString()).to.contain("custom program error: 0x7d1"); + } + }); + + it("create post as editor", async () => { + const postRandomHash = randombytes(32); + const metadataUri = + "https://gist.githubusercontent.com/abishekk92/10593977/raw/589238c3d48e654347d6cbc1e29c1e10dadc7cea/monoid.md"; + const postSeed = [ + Buffer.from("post"), + postRandomHash, + ]; + [postAccount] = await anchor.web3.PublicKey.findProgramAddress( + postSeed, + program.programId + ); + try { + const editor_post_tx = await program.methods + .createPostAsEditor(metadataUri, postRandomHash) + .accounts({ + post: postAccount, + hostProfile: hostProfileAccount, + editorProfile: editorProfileAccount, + editor: editorAccount, + authority: editor.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + editor_post_tx.feePayer = editor.publicKey; + editor_post_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await editor_anchor_wallet.signTransaction(editor_post_tx); + await provider.sendAndConfirm(editor_post_tx, [editor]); + } catch (error) { + console.log(`Error creating post as editor`); + console.log(error); + } + const data = await program.account.post.fetch(postAccount); + expect(data.metadataUri).to.equal(metadataUri); + }); + + it("update post as editor", async () => { + const metadataUri = + "https://gist.githubusercontent.com/abishekk92/10593977/raw/monoid.md"; + try { + const editor_post_tx = await program.methods + .updatePostAsEditor(metadataUri) + .accounts({ + post: postAccount, + hostProfile: hostProfileAccount, + editorProfile: editorProfileAccount, + editor: editorAccount, + authority: editor.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + editor_post_tx.feePayer = editor.publicKey; + editor_post_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await editor_anchor_wallet.signTransaction(editor_post_tx); + await provider.sendAndConfirm(editor_post_tx, [editor]); + } catch (error) { + console.log(`Error updating post as editor`); + console.log(error); + } + const data = await program.account.post.fetch(postAccount); + expect(data.metadataUri).to.equal(metadataUri); + }); + + it("update post as host", async () => { + const metadataUri = + "https://gist.githubusercontent.com/shekdev/10593977/raw/589238c3d48e654347d6cbc1e29c1e10dadc7cea/monoid.md"; + try { + const host_post_tx = await program.methods + .updatePost(metadataUri) + .accounts({ + post: postAccount, + profile: hostProfileAccount, + authority: host.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + host_post_tx.feePayer = host.publicKey; + host_post_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await host_anchor_wallet.signTransaction(host_post_tx); + await provider.sendAndConfirm(host_post_tx, [host]); + } catch (error) { + console.log(`Error updating post as host`); + console.log(error); + } + const data = await program.account.post.fetch(postAccount); + expect(data.metadataUri).to.equal(metadataUri); + }); + + it("should not allow unauthorized update", async () => { + const randomUser = anchor.web3.Keypair.generate(); + const randomUser_anchor_wallet = new anchor.Wallet(randomUser); + await airdrop(randomUser.publicKey); + + // Set up user profile + const randomUserHash = randombytes(32); + const randomUserProfileSeed = [Buffer.from("profile"), randomUserHash]; + const [randomUserProfileAccount] = await anchor.web3.PublicKey.findProgramAddress( + randomUserProfileSeed, + program.programId + ); + const randomUser_profile_tx = await program.methods + .initialize(randomUserHash) + .accounts({ + profile: randomUserProfileAccount, + user: randomUser.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + randomUser_profile_tx.feePayer = randomUser.publicKey; + randomUser_profile_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await randomUser_anchor_wallet.signTransaction(randomUser_profile_tx); + await provider.sendAndConfirm(randomUser_profile_tx, [randomUser]); + + // Set up post + const postRandomHash = randombytes(32); + const metadataUri = + "https://gist.githubusercontent.com/abishekk92/10593977/raw/589238c3d48e654347d6cbc1e29c1e10dadc7cea/monoid.md"; + const postSeed = [ + Buffer.from("post"), + postRandomHash, + ]; + const [randomUserPostAccount] = await anchor.web3.PublicKey.findProgramAddress( + postSeed, + program.programId + ); + const tx = await program.methods + .createPostAsEditor(metadataUri, postRandomHash) + .accounts({ + post: randomUserPostAccount, + hostProfile: randomUserProfileAccount, + editorProfile: editorProfileAccount, + editor: editorAccount, + authority: randomUser.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + tx.feePayer = randomUser.publicKey; + tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await randomUser_anchor_wallet.signTransaction(tx); + try { + await provider.sendAndConfirm(tx, [randomUser]); + } catch (error) { + expect(error).to.be.an("error"); + expect(error.toString()).to.contain("custom program error: 0x7d1"); + } + }); + + it("should not allow unauthorized delete of post as editor", async () => { + const randomUser = anchor.web3.Keypair.generate(); + const randomUser_anchor_wallet = new anchor.Wallet(randomUser); + await airdrop(randomUser.publicKey); + + // Set up user profile + const randomUserHash = randombytes(32); + const randomUserProfileSeed = [Buffer.from("profile"), randomUserHash]; + const [randomUserProfileAccount] = await anchor.web3.PublicKey.findProgramAddress( + randomUserProfileSeed, + program.programId + ); + const randomUser_profile_tx = await program.methods + .initialize(randomUserHash) + .accounts({ + profile: randomUserProfileAccount, + user: randomUser.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + randomUser_profile_tx.feePayer = randomUser.publicKey; + randomUser_profile_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await randomUser_anchor_wallet.signTransaction(randomUser_profile_tx); + await provider.sendAndConfirm(randomUser_profile_tx, [randomUser]); + + const randomUser_post_tx = await program.methods + .deletePostAsEditor() + .accounts({ + post: postAccount, + hostProfile: hostProfileAccount, + editorProfile: editorProfileAccount, + editor: editorAccount, + authority: randomUser.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + randomUser_post_tx.feePayer = randomUser.publicKey; + randomUser_post_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await randomUser_anchor_wallet.signTransaction(randomUser_post_tx); + try { + await provider.sendAndConfirm(randomUser_post_tx, [randomUser]); + } catch (error) { + expect(error).to.be.an("error"); + expect(error.toString()).to.contain("custom program error: 0x7d1"); + } + }); + + it("should delete post as editor", async () => { + try { + const editor_post_tx = await program.methods + .deletePostAsEditor() + .accounts({ + post: postAccount, + hostProfile: hostProfileAccount, + editorProfile: editorProfileAccount, + editor: editorAccount, + authority: editor.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + editor_post_tx.feePayer = editor.publicKey; + editor_post_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await editor_anchor_wallet.signTransaction(editor_post_tx); + await provider.sendAndConfirm(editor_post_tx, [editor]); + } catch (error) { + console.log(`Error deleting post as editor`); + console.log(error); + } + try { + await program.account.post.fetch(postAccount); + } catch (error) { + expect(error).to.be.an("error"); + expect(error.toString()).to.contain(`Account does not exist ${postAccount.toString()}`); + } + }); + + + it("remove editor", async () => { + try { + const editor_tx = await program.methods + .removeEditor() + .accounts({ + editor: editorAccount, + hostProfile: hostProfileAccount, + editorProfile: editorProfileAccount, + authority: host.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + editor_tx.feePayer = host.publicKey; + editor_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await host_anchor_wallet.signTransaction(editor_tx); + await provider.sendAndConfirm(editor_tx, [host]); + } catch (error) { + console.log(error); + } + try { + const data = await program.account.editor.fetch(editorAccount); + } catch (error) { + expect(error).to.be.an("error"); + expect(error.toString()).to.contain(`Account does not exist ${editorAccount.toString()}`); + } + }); +}); \ No newline at end of file diff --git a/tests/wordcel.spec.ts b/tests/wordcel.spec.ts index 27a9929..9b540a0 100644 --- a/tests/wordcel.spec.ts +++ b/tests/wordcel.spec.ts @@ -12,8 +12,8 @@ const program = anchor.workspace.Wordcel as Program; const user = provider.wallet.publicKey; describe("wordcel", async () => { - const randomHash = randombytes(32); - const profileSeed = [Buffer.from("profile"), randomHash]; + const profileHash = randombytes(32); + const profileSeed = [Buffer.from("profile"), profileHash]; const [profileAccount, _] = await anchor.web3.PublicKey.findProgramAddress( profileSeed, program.programId @@ -23,30 +23,7 @@ describe("wordcel", async () => { describe("Profile", async () => { it("should initialize", async () => { await program.methods - .initialize(randomHash) - .accounts({ - profile: profileAccount, - user: user, - systemProgram: SystemProgram.programId, - }) - .rpc(); - const data = await program.account.profile.fetch(profileAccount); - expect(data.authority.toString()).to.equal(user.toString()); - }); - }); - - describe("Editor", async () => { - before(async () => { - //set up profile 1 - //set up profile 2 - //set up Editor - //set up Post - //post as editor - }); - - it("should initialize", async () => { - await program.methods - .initialize(randomHash) + .initialize(profileHash) .accounts({ profile: profileAccount, user: user, From 3aa15a8137feda65bce3fa050600a4a6d0bd3f81 Mon Sep 17 00:00:00 2001 From: vjgpt Date: Thu, 12 Jan 2023 07:29:46 +0000 Subject: [PATCH 3/4] abstract setup post from editor testcases --- tests/editor.spec.ts | 114 ++++++++----------------------------------- tests/utils/index.ts | 22 ++++++++- 2 files changed, 41 insertions(+), 95 deletions(-) diff --git a/tests/editor.spec.ts b/tests/editor.spec.ts index 775d169..60b5dc4 100644 --- a/tests/editor.spec.ts +++ b/tests/editor.spec.ts @@ -1,15 +1,14 @@ import * as anchor from "@project-serum/anchor"; -import { Program, AnchorError } from "@project-serum/anchor"; +import { Program } from "@project-serum/anchor"; import { Wordcel } from "../target/types/wordcel"; import { expect } from "chai"; import { PublicKey } from "@solana/web3.js"; import randombytes from "randombytes"; -import { airdrop } from "./utils"; +import { airdrop, setupProfile } from "./utils"; const { SystemProgram } = anchor.web3; const provider = anchor.getProvider(); const program = anchor.workspace.Wordcel as Program; -const user = provider.wallet.publicKey; describe("Editor", async () => { const host = anchor.web3.Keypair.generate(); @@ -23,47 +22,21 @@ describe("Editor", async () => { let postAccount: PublicKey; before(async () => { - // Set up host profile await airdrop(host.publicKey); - const hostRandomHash = randombytes(32); - const hostProfileSeed = [Buffer.from("profile"), hostRandomHash]; - [hostProfileAccount] = await anchor.web3.PublicKey.findProgramAddress( - hostProfileSeed, - program.programId - ); - const host_profile_tx = await program.methods - .initialize(hostRandomHash) - .accounts({ - profile: hostProfileAccount, - user: host.publicKey, - systemProgram: SystemProgram.programId, - }) - .transaction(); - host_profile_tx.feePayer = host.publicKey; - host_profile_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) - .blockhash; + await airdrop(editor.publicKey); + + // Set up host profile + const hostProfile = await setupProfile(host.publicKey, program); + hostProfileAccount = hostProfile.profileAccount; + const host_profile_tx = hostProfile.profileTx; await host_anchor_wallet.signTransaction(host_profile_tx); await provider.sendAndConfirm(host_profile_tx, [host]); // Set up editor profile await airdrop(editor.publicKey); - const editorRandomHash = randombytes(32); - const editorProfileSeed = [Buffer.from("profile"), editorRandomHash]; - [editorProfileAccount] = await anchor.web3.PublicKey.findProgramAddress( - editorProfileSeed, - program.programId - ); - const editor_profile_tx = await program.methods - .initialize(editorRandomHash) - .accounts({ - profile: editorProfileAccount, - user: editor.publicKey, - systemProgram: SystemProgram.programId, - }) - .transaction(); - editor_profile_tx.feePayer = editor.publicKey; - editor_profile_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) - .blockhash; + const editorProfile = await setupProfile(editor.publicKey, program); + editorProfileAccount = editorProfile.profileAccount; + const editor_profile_tx = editorProfile.profileTx; await editor_anchor_wallet.signTransaction(editor_profile_tx); await provider.sendAndConfirm(editor_profile_tx, [editor]); }); @@ -109,23 +82,11 @@ describe("Editor", async () => { const editorUser = anchor.web3.Keypair.generate(); const editorUser_anchor_wallet = new anchor.Wallet(editorUser); await airdrop(editorUser.publicKey); - const editorRandomHash = randombytes(32); - const editorProfileSeed = [Buffer.from("profile"), editorRandomHash]; - const [editorUserProfileAccount] = await anchor.web3.PublicKey.findProgramAddress( - editorProfileSeed, - program.programId - ); - const editor_profile_tx = await program.methods - .initialize(editorRandomHash) - .accounts({ - profile: editorUserProfileAccount, - user: editorUser.publicKey, - systemProgram: SystemProgram.programId, - }) - .transaction(); - editor_profile_tx.feePayer = editorUser.publicKey; - editor_profile_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) - .blockhash; + + // Set up editorUser profile + const editorUserProfile = await setupProfile(editorUser.publicKey, program); + const editorUserProfileAccount = editorUserProfile.profileAccount; + const editor_profile_tx = editorUserProfile.profileTx; await editorUser_anchor_wallet.signTransaction(editor_profile_tx); await provider.sendAndConfirm(editor_profile_tx, [editorUser]); @@ -256,24 +217,10 @@ describe("Editor", async () => { const randomUser_anchor_wallet = new anchor.Wallet(randomUser); await airdrop(randomUser.publicKey); - // Set up user profile - const randomUserHash = randombytes(32); - const randomUserProfileSeed = [Buffer.from("profile"), randomUserHash]; - const [randomUserProfileAccount] = await anchor.web3.PublicKey.findProgramAddress( - randomUserProfileSeed, - program.programId - ); - const randomUser_profile_tx = await program.methods - .initialize(randomUserHash) - .accounts({ - profile: randomUserProfileAccount, - user: randomUser.publicKey, - systemProgram: SystemProgram.programId, - }) - .transaction(); - randomUser_profile_tx.feePayer = randomUser.publicKey; - randomUser_profile_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) - .blockhash; + // Set up randomUser profile + const randomUserPrfile = await setupProfile(randomUser.publicKey, program); + const randomUserProfileAccount = randomUserPrfile.profileAccount; + const randomUser_profile_tx = randomUserPrfile.profileTx; await randomUser_anchor_wallet.signTransaction(randomUser_profile_tx); await provider.sendAndConfirm(randomUser_profile_tx, [randomUser]); @@ -317,27 +264,6 @@ describe("Editor", async () => { const randomUser_anchor_wallet = new anchor.Wallet(randomUser); await airdrop(randomUser.publicKey); - // Set up user profile - const randomUserHash = randombytes(32); - const randomUserProfileSeed = [Buffer.from("profile"), randomUserHash]; - const [randomUserProfileAccount] = await anchor.web3.PublicKey.findProgramAddress( - randomUserProfileSeed, - program.programId - ); - const randomUser_profile_tx = await program.methods - .initialize(randomUserHash) - .accounts({ - profile: randomUserProfileAccount, - user: randomUser.publicKey, - systemProgram: SystemProgram.programId, - }) - .transaction(); - randomUser_profile_tx.feePayer = randomUser.publicKey; - randomUser_profile_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) - .blockhash; - await randomUser_anchor_wallet.signTransaction(randomUser_profile_tx); - await provider.sendAndConfirm(randomUser_profile_tx, [randomUser]); - const randomUser_post_tx = await program.methods .deletePostAsEditor() .accounts({ diff --git a/tests/utils/index.ts b/tests/utils/index.ts index 4e5c814..6e2e536 100644 --- a/tests/utils/index.ts +++ b/tests/utils/index.ts @@ -1,5 +1,8 @@ import * as anchor from '@project-serum/anchor'; -import {PublicKey, LAMPORTS_PER_SOL} from '@solana/web3.js'; +import { Program } from '@project-serum/anchor'; +import { PublicKey, LAMPORTS_PER_SOL, SystemProgram } from '@solana/web3.js'; +import randombytes from 'randombytes'; +import { Wordcel } from '../../target/types/wordcel'; const provider = anchor.getProvider(); @@ -8,3 +11,20 @@ export async function airdrop(key: PublicKey) { return provider.connection.confirmTransaction(airdropSig); } +export async function setupProfile(pubkey: PublicKey, program: Program) { + const randomHash = randombytes(32); + const profileSeed = [Buffer.from("profile"), randomHash]; + const [profileAccount] = await anchor.web3.PublicKey.findProgramAddress(profileSeed, program.programId); + const profileTx = await program.methods + .initialize(randomHash) + .accounts({ + profile: profileAccount, + user: pubkey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + profileTx.feePayer = pubkey; + profileTx.recentBlockhash = (await provider.connection.getLatestBlockhash()).blockhash; + + return { profileAccount, profileTx }; +} \ No newline at end of file From ef5ea84b99cb5ecf6c7906c4b0dd836397316f9e Mon Sep 17 00:00:00 2001 From: vjgpt Date: Thu, 12 Jan 2023 07:41:46 +0000 Subject: [PATCH 4/4] adding few testcases for editor --- tests/editor.spec.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/tests/editor.spec.ts b/tests/editor.spec.ts index 60b5dc4..54e6a6a 100644 --- a/tests/editor.spec.ts +++ b/tests/editor.spec.ts @@ -121,6 +121,52 @@ describe("Editor", async () => { } }); + it("should not allow unauthorized post creation as editor", async () => { + const editorUser = anchor.web3.Keypair.generate(); + const editorUser_anchor_wallet = new anchor.Wallet(editorUser); + await airdrop(editorUser.publicKey); + + // Set up editorUser profile + const editorUserProfile = await setupProfile(editorUser.publicKey, program); + const editorUserProfileAccount = editorUserProfile.profileAccount; + const editor_profile_tx = editorUserProfile.profileTx; + await editorUser_anchor_wallet.signTransaction(editor_profile_tx); + await provider.sendAndConfirm(editor_profile_tx, [editorUser]); + + const postRandomHash = randombytes(32); + const metadataUri = + "https://gist.githubusercontent.com/abishekk92/10593977/raw/589238c3d48e654347d6cbc1e29c1e10dadc7cea/monoid.md"; + const postSeed = [ + Buffer.from("post"), + postRandomHash, + ]; + const [postEditorAccount] = await anchor.web3.PublicKey.findProgramAddress( + postSeed, + program.programId + ); + try { + const editor_tx = await program.methods + .createPostAsEditor(metadataUri, postRandomHash) + .accounts({ + post: postEditorAccount, + hostProfile: hostProfileAccount, + editorProfile: editorUserProfileAccount, + editor: editorAccount, + authority: editorUser.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + editor_tx.feePayer = editorUser.publicKey; + editor_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await editorUser_anchor_wallet.signTransaction(editor_tx); + await provider.sendAndConfirm(editor_tx, [editorUser]); + } catch (error) { + expect(error).to.be.an("error"); + expect(error.toString()).to.contain("custom program error: 0x7d3"); + } + }); + it("create post as editor", async () => { const postRandomHash = randombytes(32); const metadataUri = @@ -317,6 +363,32 @@ describe("Editor", async () => { } }); + it("should not allow unauthorized remove of editor", async () => { + const randomUser = anchor.web3.Keypair.generate(); + const randomUser_anchor_wallet = new anchor.Wallet(randomUser); + await airdrop(randomUser.publicKey); + + const randomUser_tx = await program.methods + .removeEditor() + .accounts({ + editor: editorAccount, + hostProfile: hostProfileAccount, + editorProfile: editorProfileAccount, + authority: randomUser.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + randomUser_tx.feePayer = randomUser.publicKey; + randomUser_tx.recentBlockhash = (await provider.connection.getLatestBlockhash()) + .blockhash; + await randomUser_anchor_wallet.signTransaction(randomUser_tx); + try { + await provider.sendAndConfirm(randomUser_tx, [randomUser]); + } catch (error) { + expect(error).to.be.an("error"); + expect(error.toString()).to.contain("custom program error: 0x7d1"); + } + }); it("remove editor", async () => { try {