From dcb78f12198ab864249fdf299551dc5d87c996c3 Mon Sep 17 00:00:00 2001 From: Vadim Volodin Date: Sat, 6 Jul 2024 08:57:06 +0800 Subject: [PATCH] feat: additional kyc check for review stage (#138) Closes https://github.com/NEAR-DevHub/neardevhub-bos/issues/848 - adds additional kyc check for review stage. For that, VersionedTimelineStatus along with TimelineStatusV2 is introduced Also it removes posts functionality for the following reason: ```bash Action #0: ExecutionError("Exceeded the prepaid gas.") ``` It arises on calling either `unsafe_self_upgrade` or `unsafe_migrate` on `test_deploy_contract_self_upgrade` test. Because code size is too big. So code for posts was removed. --- src/common/mod.rs | 39 +++ src/lib.rs | 295 ++---------------- src/migrations.rs | 25 +- src/notify.rs | 78 +---- src/post/attestation.rs | 80 ----- src/post/comment.rs | 93 ------ src/post/github.rs | 33 -- src/post/idea.rs | 71 ----- src/post/like.rs | 38 --- src/post/mod.rs | 142 --------- src/post/solution.rs | 133 -------- src/post/sponsorship.rs | 102 ------ src/proposal/mod.rs | 82 ++++- src/proposal/timeline.rs | 154 ++++++++- src/repost.rs | 90 ------ src/rfp/mod.rs | 2 +- tests/migration.rs | 233 +------------- tests/proposals.rs | 29 +- ...ation__deploy_contract_self_upgrade-2.snap | 73 ++++- ...ation__deploy_contract_self_upgrade-3.snap | 21 -- ...ation__deploy_contract_self_upgrade-4.snap | 83 ----- ...ation__deploy_contract_self_upgrade-5.snap | 23 -- ...ation__deploy_contract_self_upgrade-6.snap | 23 -- ...ation__deploy_contract_self_upgrade-7.snap | 27 -- ...ation__deploy_contract_self_upgrade-8.snap | 36 --- ...ation__deploy_contract_self_upgrade-9.snap | 68 ---- ...gration__deploy_contract_self_upgrade.snap | 46 ++- 27 files changed, 386 insertions(+), 1733 deletions(-) create mode 100644 src/common/mod.rs delete mode 100644 src/post/attestation.rs delete mode 100644 src/post/comment.rs delete mode 100644 src/post/github.rs delete mode 100644 src/post/idea.rs delete mode 100644 src/post/like.rs delete mode 100644 src/post/mod.rs delete mode 100644 src/post/solution.rs delete mode 100644 src/post/sponsorship.rs delete mode 100644 src/repost.rs delete mode 100644 tests/snapshots/migration__deploy_contract_self_upgrade-3.snap delete mode 100644 tests/snapshots/migration__deploy_contract_self_upgrade-4.snap delete mode 100644 tests/snapshots/migration__deploy_contract_self_upgrade-5.snap delete mode 100644 tests/snapshots/migration__deploy_contract_self_upgrade-6.snap delete mode 100644 tests/snapshots/migration__deploy_contract_self_upgrade-7.snap delete mode 100644 tests/snapshots/migration__deploy_contract_self_upgrade-8.snap delete mode 100644 tests/snapshots/migration__deploy_contract_self_upgrade-9.snap diff --git a/src/common/mod.rs b/src/common/mod.rs new file mode 100644 index 00000000..f20de188 --- /dev/null +++ b/src/common/mod.rs @@ -0,0 +1,39 @@ +use near_sdk::serde::{Deserialize, Serialize}; +use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk::{NearSchema, BorshStorageKey, CryptoHash}; + +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] +#[serde(crate = "near_sdk::serde")] +#[serde(tag = "post_version")] +#[borsh(crate = "near_sdk::borsh")] +pub enum VersionedPost { + V0, +} + + +#[derive(BorshSerialize, BorshStorageKey)] +#[borsh(crate = "near_sdk::borsh")] +pub enum StorageKey { + Ideas, + Solutions, + Attestations, + Sponsorships, + Comments, + Posts, + PostToParent, + PostToChildren, + /// Deprecated due to damaged storage state. + LabelToPosts, + LabelToPostsV2, + AuthorToAuthorPosts, + AuthorPosts(CryptoHash), + Communities, + AddOns, + Proposals, + LabelToProposals, + AuthorProposals, + RFPs, + LabelToRFPs, + RFPLinkedProposals, + LabelInfo, +} diff --git a/src/lib.rs b/src/lib.rs index c1778a82..ed46a8ee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,9 +3,8 @@ pub mod community; pub mod debug; pub mod migrations; mod notify; -pub mod post; +pub mod common; pub mod proposal; -mod repost; pub mod rfp; pub mod stats; pub mod str_serializers; @@ -15,8 +14,9 @@ use crate::access_control::members::ActionType; use crate::access_control::members::Member; use crate::access_control::AccessControl; use community::*; -use post::*; -use proposal::timeline::TimelineStatus; + +use common::*; +use proposal::timeline::{TimelineStatusV1, TimelineStatus, VersionedTimelineStatus}; use proposal::*; use rfp::{ RFPId, RFPSnapshot, TimelineStatus as RFPTimelineStatus, VersionedRFP, VersionedRFPBody, RFP, @@ -36,11 +36,6 @@ use std::collections::{HashSet, HashMap}; use std::convert::TryInto; type PostId = u64; -type IdeaId = u64; -type AttestationId = u64; -type SolutionId = u64; -type SponsorshipId = u64; -type CommentId = u64; /// An imaginary top post representing the landing page. const ROOT_POST_ID: u64 = u64::MAX; @@ -95,51 +90,6 @@ impl Contract { contract } - /// If `parent_id` is not provided get all landing page posts. Otherwise, get all posts under - /// `parent_id` post. - pub fn get_posts(&self, parent_id: Option) -> Vec { - let parent_id = parent_id.unwrap_or(ROOT_POST_ID); - let children_ids = self - .post_to_children - .get(&parent_id) - .unwrap_or_else(|| panic!("Parent id {} not found", parent_id)); - children_ids - .into_iter() - .map(|id| { - self.posts - .get(id) - .unwrap_or_else(|| panic!("Post id {} not found. Broken state invariant", id)) - }) - .collect() - } - - pub fn get_post(&self, post_id: PostId) -> VersionedPost { - self.posts.get(post_id).unwrap_or_else(|| panic!("Post id {} not found", post_id)) - } - - pub fn get_all_post_ids(&self) -> Vec { - (0..self.posts.len()).collect() - } - - pub fn get_children_ids(&self, post_id: Option) -> Vec { - let post_id = post_id.unwrap_or(ROOT_POST_ID); - self.post_to_children - .get(&post_id) - .unwrap_or_else(|| panic!("Parent id {} not found", post_id)) - } - - pub fn get_parent_id(&self, post_id: PostId) -> Option { - let res = self - .post_to_parent - .get(&post_id) - .unwrap_or_else(|| panic!("Parent id {} not found", post_id)); - if res == ROOT_POST_ID { - Option::None - } else { - Option::Some(res) - } - } - pub fn get_proposals(&self, ids: Option< Vec >) -> Vec { if let Some(ids) = ids { ids @@ -173,85 +123,6 @@ impl Contract { (0..self.rfps.len().try_into().unwrap()).collect() } - #[payable] - pub fn add_like(&mut self, post_id: PostId) -> Promise { - let mut post: Post = self - .posts - .get(post_id) - .unwrap_or_else(|| panic!("Post id {} not found", post_id)) - .into(); - let post_author = post.author_id.clone(); - let like = - Like { author_id: env::predecessor_account_id(), timestamp: env::block_timestamp() }; - post.likes.insert(like); - self.posts.replace(post_id, &post.into()); - notify::notify_like(post_id, post_author) - } - - #[payable] - pub fn add_post( - &mut self, - parent_id: Option, - body: PostBody, - labels: HashSet, - ) -> Promise { - let parent_id = parent_id.unwrap_or(ROOT_POST_ID); - let id = self.posts.len(); - let author_id = env::predecessor_account_id(); - let editor_id = author_id.clone(); - require!( - self.is_allowed_to_use_labels( - Some(editor_id.clone()), - labels.iter().cloned().collect() - ), - "Cannot use these labels" - ); - - for label in &labels { - let mut other_posts = self.label_to_posts.get(label).unwrap_or_default(); - other_posts.insert(id); - self.label_to_posts.insert(label, &other_posts); - } - let post = Post { - id, - author_id: author_id.clone(), - likes: Default::default(), - snapshot: PostSnapshot { editor_id, timestamp: env::block_timestamp(), labels, body }, - snapshot_history: vec![], - }; - self.posts.push(&post.clone().into()); - self.post_to_parent.insert(&id, &parent_id); - - let mut siblings = self - .post_to_children - .get(&parent_id) - .unwrap_or_else(|| panic!("Parent id {} not found", parent_id)); - siblings.push(id); - self.post_to_children.insert(&parent_id, &siblings); - - // Don't forget to add an empty list of your own children. - self.post_to_children.insert(&id, &vec![]); - - let mut author_posts = self.authors.get(&author_id).unwrap_or_default(); - author_posts.insert(post.id); - self.authors.insert(&post.author_id, &author_posts); - - let desc = get_post_description(post.clone()); - - if parent_id != ROOT_POST_ID { - let parent_post: Post = self - .posts - .get(parent_id) - .unwrap_or_else(|| panic!("Parent post with id {} not found", parent_id)) - .into(); - let parent_author = parent_post.author_id; - notify::notify_reply(parent_id, parent_author); - } else { - repost::repost(post); - } - notify::notify_mentions(desc.as_str(), id) - } - #[payable] pub fn add_proposal( &mut self, @@ -280,8 +151,10 @@ impl Contract { require!(self.proposal_categories.contains(&proposal_body.category), "Unknown category"); + let timeline = proposal_body.timeline.clone().latest_version(); + require!( - proposal_body.timeline.is_draft() || proposal_body.timeline.is_empty_review(), + timeline.is_draft() || timeline.is_empty_review(), "Cannot create proposal which is not in a draft or a review state" ); @@ -392,17 +265,6 @@ impl Contract { ret_value } - pub fn get_posts_by_author(&self, author: AccountId) -> Vec { - self.authors.get(&author).map(|posts| posts.into_iter().collect()).unwrap_or_default() - } - - pub fn get_posts_by_label(&self, label: String) -> Vec { - let mut res: Vec<_> = - self.label_to_posts.get(&label).unwrap_or_default().into_iter().collect(); - res.sort(); - res - } - pub fn get_proposals_by_author(&self, author: AccountId) -> Vec { self.author_proposals .get(&author) @@ -424,12 +286,6 @@ impl Contract { res } - pub fn get_all_labels(&self) -> Vec { - let mut res: Vec<_> = self.label_to_posts.keys().collect(); - res.sort(); - res - } - pub fn get_all_proposal_labels(&self) -> Vec { let mut res: Vec<_> = self.label_to_proposals.keys().collect(); res.sort(); @@ -475,25 +331,6 @@ impl Contract { editor == env::current_account_id() || self.has_moderator(editor) } - pub fn is_allowed_to_edit(&self, post_id: PostId, editor: Option) -> bool { - let post: Post = self - .posts - .get(post_id) - .unwrap_or_else(|| panic!("Post id {} not found", post_id)) - .into(); - let editor = editor.unwrap_or_else(env::predecessor_account_id); - // First check for simple cases. - if editor == env::current_account_id() || editor == post.author_id { - return true; - } - - // Then check for complex case. - self.access_control - .members_list - .check_permissions(editor, post.snapshot.labels.into_iter().collect::>()) - .contains(&ActionType::EditPost) - } - pub fn is_allowed_to_use_labels(&self, editor: Option, labels: Vec) -> bool { let editor = editor.unwrap_or_else(env::predecessor_account_id); // First check for simple cases. @@ -529,72 +366,10 @@ impl Contract { res } - pub fn get_all_allowed_labels(&self, editor: AccountId) -> Vec { - self.filtered_labels(&self.label_to_posts, &editor) - } - pub fn get_all_allowed_proposal_labels(&self, editor: AccountId) -> Vec { self.filtered_labels(&self.label_to_proposals, &editor) } - #[payable] - pub fn edit_post(&mut self, id: PostId, body: PostBody, labels: HashSet) -> Promise { - require!( - self.is_allowed_to_edit(id, Option::None), - "The account is not allowed to edit this post" - ); - let editor_id = env::predecessor_account_id(); - let mut post: Post = - self.posts.get(id).unwrap_or_else(|| panic!("Post id {} not found", id)).into(); - - let old_snapshot = post.snapshot.clone(); - let old_labels_set = old_snapshot.labels.clone(); - let new_labels = labels; - let new_snapshot = PostSnapshot { - editor_id: editor_id.clone(), - timestamp: env::block_timestamp(), - labels: new_labels.clone(), - body, - }; - post.snapshot = new_snapshot; - post.snapshot_history.push(old_snapshot); - let post_author = post.author_id.clone(); - self.posts.replace(id, &post.into()); - - // Update labels index. - let new_labels_set = new_labels; - let labels_to_remove = &old_labels_set - &new_labels_set; - let labels_to_add = &new_labels_set - &old_labels_set; - require!( - self.is_allowed_to_use_labels( - Some(editor_id.clone()), - labels_to_remove.iter().cloned().collect() - ), - "Not allowed to remove these labels" - ); - require!( - self.is_allowed_to_use_labels( - Some(editor_id.clone()), - labels_to_add.iter().cloned().collect() - ), - "Not allowed to add these labels" - ); - - for label_to_remove in labels_to_remove { - let mut posts = self.label_to_posts.get(&label_to_remove).unwrap(); - posts.remove(&id); - self.label_to_posts.insert(&label_to_remove, &posts); - } - - for label_to_add in labels_to_add { - let mut posts = self.label_to_posts.get(&label_to_add).unwrap_or_default(); - posts.insert(id); - self.label_to_posts.insert(&label_to_add, &posts); - } - - notify::notify_edit(id, post_author) - } - #[payable] pub fn create_community( &mut self, @@ -668,14 +443,32 @@ impl Contract { } #[payable] - pub fn edit_proposal_timeline(&mut self, id: ProposalId, timeline: TimelineStatus) -> ProposalId { + pub fn edit_proposal_timeline(&mut self, id: ProposalId, timeline: TimelineStatusV1) -> ProposalId { let proposal: Proposal = self .proposals .get(id.into()) .unwrap_or_else(|| panic!("Proposal id {} not found", id)) .into(); let mut body = proposal.snapshot.body.latest_version(); - body.timeline = timeline; + body.timeline = timeline.into(); + + self.edit_proposal_internal(id, body.into(), proposal.snapshot.labels) + } + + #[payable] + pub fn edit_proposal_versioned_timeline( + &mut self, + id: ProposalId, + timeline: VersionedTimelineStatus, + ) -> ProposalId { + near_sdk::log!("edit_proposal_versioned_timeline"); + let proposal: Proposal = self + .proposals + .get(id.into()) + .unwrap_or_else(|| panic!("Proposal id {} not found", id)) + .into(); + let mut body = proposal.snapshot.body.latest_version(); + body.timeline = timeline.into(); self.edit_proposal_internal(id, body.into(), proposal.snapshot.labels) } @@ -708,8 +501,8 @@ impl Contract { for proposal_id in proposals_to_cancel { let proposal: Proposal = self.get_proposal(proposal_id).into(); let proposal_timeline = proposal.snapshot.body.latest_version().timeline; - let review_status = proposal_timeline.get_review_status().clone(); - self.edit_proposal_timeline(proposal_id, TimelineStatus::Cancelled(review_status)); + let review_status = proposal_timeline.latest_version().get_review_status().clone(); + self.edit_proposal_versioned_timeline(proposal_id, TimelineStatus::Cancelled(review_status).into()); } for proposal_id in proposals_to_unlink { @@ -1121,7 +914,7 @@ pub struct BlockHeightCallbackRetValue { mod tests { use crate::community::AddOn; - use crate::{PostBody, ProposalBodyV0, VersionedProposalBody}; + use crate::{ProposalBodyV0, VersionedProposalBody}; use near_sdk::test_utils::{get_created_receipts, VMContextBuilder}; use near_sdk::{testing_env, VMContext}; @@ -1192,34 +985,6 @@ mod tests { } } - #[test] - pub fn test_add_post_with_mention() { - let context = get_context(false); - testing_env!(context); - let mut contract = Contract::new(); - - let body: PostBody = near_sdk::serde_json::from_str(r#" - { - "name": "another post", - "description": "Hello to @petersalomonsen.near and @psalomo.near. This is an idea with mentions.", - "post_type": "Idea", - "idea_version": "V1" - }"#).unwrap(); - contract.add_post(None, body, HashSet::new()); - let receipts = get_created_receipts(); - assert_eq!(2, receipts.len()); - - // Extract the method_name and args values - if let near_sdk::mock::MockAction::FunctionCallWeight { method_name, args, .. } = - &receipts[1].actions[0] - { - assert_eq!(method_name, b"set"); - assert_eq!(args, b"{\"data\":{\"bob.near\":{\"index\":{\"notify\":\"[{\\\"key\\\":\\\"petersalomonsen.near\\\",\\\"value\\\":{\\\"type\\\":\\\"devgovgigs/mention\\\",\\\"post\\\":0}},{\\\"key\\\":\\\"psalomo.near.\\\",\\\"value\\\":{\\\"type\\\":\\\"devgovgigs/mention\\\",\\\"post\\\":0}}]\"}}}}"); - } else { - assert!(false, "Expected a function call ...") - } - } - #[test] pub fn test_create_addon() { let context = get_context_with_current(false, "bob.near".to_string()); diff --git a/src/migrations.rs b/src/migrations.rs index 1281d60e..1674e3fe 100644 --- a/src/migrations.rs +++ b/src/migrations.rs @@ -5,7 +5,6 @@ use crate::*; use near_sdk::{borsh::to_vec, env, near, NearToken, Promise}; use near_sdk::store::Lazy; -use std::cmp::min; use std::collections::{HashSet, HashMap}; #[near] @@ -74,24 +73,6 @@ impl Contract { authors, }); } - - fn unsafe_insert_old_post_authors(start: u64, end: u64) -> StateVersion { - let mut contract: ContractV3 = env::state_read().unwrap(); - let total = contract.posts.len(); - let end = min(total, end); - for i in start..end { - let versioned_post = contract.posts.get(i); - if let Some(versioned_post) = versioned_post { - let post: Post = versioned_post.into(); - let mut author_posts = - contract.authors.get(&post.author_id).unwrap_or_else(|| HashSet::new()); - author_posts.insert(post.id); - contract.authors.insert(&post.author_id, &author_posts); - } - } - env::state_write(&contract); - StateVersion::V3 { done: end == total, migrated_count: end } - } } #[near] @@ -780,10 +761,8 @@ impl Contract { Contract::unsafe_add_post_authors(); state_version_write(&StateVersion::V3 { done: false, migrated_count: 0 }) } - StateVersion::V3 { done: false, migrated_count } => { - let new_version = - Contract::unsafe_insert_old_post_authors(migrated_count, migrated_count + 100); - state_version_write(&new_version); + StateVersion::V3 { done: false, .. } => { + unimplemented!(); } StateVersion::V3 { done: true, migrated_count: _ } => { Contract::unsafe_add_communities(); diff --git a/src/notify.rs b/src/notify.rs index 8d86d804..88d6c535 100644 --- a/src/notify.rs +++ b/src/notify.rs @@ -1,7 +1,7 @@ use std::collections::HashSet; use crate::{ - get_subscribers, rfp::get_subscribers as get_rfp_subscribers, PostId, Proposal, ProposalId, RFP, + get_subscribers, rfp::get_subscribers as get_rfp_subscribers, Proposal, ProposalId, RFP, }; use devhub_common::social_db_contract; use near_sdk::serde_json::json; @@ -102,31 +102,6 @@ pub fn notify_rfp_subscribers(rfp: &RFP, additional_accounts: HashSet ) } -pub fn notify_mentions(text: &str, post_id: PostId) -> Promise { - let mentions = get_text_mentions(text); - - notify_accounts( - env::predecessor_account_id(), - mentions, - json!({ - "type": "devgovgigs/mention", - "post": post_id, - }), - ) -} - -pub fn notify_like(post_id: PostId, post_author: AccountId) -> Promise { - notify(env::predecessor_account_id(), post_author, notify_value(post_id, "like")) -} - -pub fn notify_reply(post_id: PostId, post_author: AccountId) -> Promise { - notify(env::predecessor_account_id(), post_author, notify_value(post_id, "reply")) -} - -pub fn notify_edit(post_id: PostId, post_author: AccountId) -> Promise { - notify(env::predecessor_account_id(), post_author, notify_value(post_id, "edit")) -} - pub fn notify_edit_proposal(proposal_id: ProposalId, post_author: AccountId) -> Promise { notify( env::current_account_id(), @@ -140,13 +115,6 @@ pub fn notify_edit_proposal(proposal_id: ProposalId, post_author: AccountId) -> ) } -fn notify_value(post_id: PostId, action: &str) -> serde_json::Value { - json!({ - "type": format!("devgovgigs/{}", action), - "post": post_id, - }) -} - fn notify(notifier: AccountId, post_author: AccountId, notify_value: serde_json::Value) -> Promise { social_db_contract() .with_static_gas(env::prepaid_gas().saturating_div(4)) @@ -162,47 +130,3 @@ fn notify(notifier: AccountId, post_author: AccountId, notify_value: serde_json: } })) } - -#[cfg(all(test, not(target_arch = "wasm32")))] -mod tests { - use super::notify_mentions; - - use near_sdk::test_utils::{get_created_receipts, VMContextBuilder}; - use near_sdk::{testing_env, VMContext}; - - fn get_context(is_view: bool) -> VMContext { - VMContextBuilder::new() - .signer_account_id("bob.near".parse().unwrap()) - .is_view(is_view) - .build() - } - - #[test] - pub fn test_notify_mentions() { - let context = get_context(false); - testing_env!(context); - let text = "Mentioning @a.near and @bcdefg.near"; - notify_mentions(text, 2); - let receipts = get_created_receipts(); - assert_eq!(1, receipts.len()); - - if let near_sdk::mock::MockAction::FunctionCallWeight { method_name, args, .. } = - &receipts[0].actions[0] - { - assert_eq!(method_name, b"set"); - assert_eq!(args, b"{\"data\":{\"bob.near\":{\"index\":{\"notify\":\"[{\\\"key\\\":\\\"a.near\\\",\\\"value\\\":{\\\"type\\\":\\\"devgovgigs/mention\\\",\\\"post\\\":2}},{\\\"key\\\":\\\"bcdefg.near\\\",\\\"value\\\":{\\\"type\\\":\\\"devgovgigs/mention\\\",\\\"post\\\":2}}]\"}}}}"); - } else { - assert!(false, "Expected a function call ...") - } - } - - #[test] - pub fn test_no_mentions() { - let context = get_context(false); - testing_env!(context); - let text = "Not mentioning anyone"; - notify_mentions(text, 2); - assert_eq!(1, get_created_receipts().len()); - assert_eq!(0, get_created_receipts()[0].actions.len()); - } -} diff --git a/src/post/attestation.rs b/src/post/attestation.rs deleted file mode 100644 index 3f378036..00000000 --- a/src/post/attestation.rs +++ /dev/null @@ -1,80 +0,0 @@ -use super::{Like, PostStatus}; -use crate::str_serializers::*; -use crate::{AttestationId, CommentId, SolutionId}; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::{AccountId, NearSchema, Timestamp}; -use std::collections::HashSet; - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct Attestation { - // Common fields - pub id: AttestationId, - pub name: String, - pub description: String, - pub author_id: AccountId, - #[serde( - serialize_with = "u64_dec_format::serialize", - deserialize_with = "u64_dec_format::deserialize" - )] - pub timestamp: Timestamp, - pub status: PostStatus, - pub likes: HashSet, - pub comments: Vec, - - //Specific fields - #[serde( - serialize_with = "u64_dec_format::serialize", - deserialize_with = "u64_dec_format::deserialize" - )] - pub submission_id: SolutionId, -} - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct AttestationV1 { - pub name: String, - pub description: String, -} - -#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[serde(tag = "attestation_version")] -#[borsh(crate = "near_sdk::borsh")] -pub enum VersionedAttestation { - V0(Attestation), - V1(AttestationV1), -} - -impl VersionedAttestation { - pub fn latest_version(self) -> AttestationV1 { - self.into() - } -} - -impl From for Attestation { - fn from(va: VersionedAttestation) -> Self { - match va { - VersionedAttestation::V0(v0) => v0, - VersionedAttestation::V1(_) => unimplemented!(), - } - } -} - -impl From for AttestationV1 { - fn from(va: VersionedAttestation) -> Self { - match va { - VersionedAttestation::V0(_) => unimplemented!(), - VersionedAttestation::V1(v1) => v1, - } - } -} - -impl From for VersionedAttestation { - fn from(a: Attestation) -> Self { - VersionedAttestation::V0(a) - } -} diff --git a/src/post/comment.rs b/src/post/comment.rs deleted file mode 100644 index 071288cf..00000000 --- a/src/post/comment.rs +++ /dev/null @@ -1,93 +0,0 @@ -use super::Like; -use crate::str_serializers::*; -use crate::CommentId; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::{AccountId, NearSchema, Timestamp}; -use std::collections::HashSet; - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct CommentV0 { - pub author_id: AccountId, - #[serde( - serialize_with = "u64_dec_format::serialize", - deserialize_with = "u64_dec_format::deserialize" - )] - pub timestamp: Timestamp, - pub description: String, - pub likes: HashSet, - pub comments: Vec, -} - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct Comment { - pub id: CommentId, - pub author_id: AccountId, - #[serde( - serialize_with = "u64_dec_format::serialize", - deserialize_with = "u64_dec_format::deserialize" - )] - pub timestamp: Timestamp, - pub description: String, - pub likes: HashSet, - pub comments: Vec, -} - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct CommentV2 { - pub description: String, -} - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[serde(tag = "comment_version")] -#[borsh(crate = "near_sdk::borsh")] -pub enum VersionedComment { - V0(CommentV0), - V1(Comment), - V2(CommentV2), -} - -impl VersionedComment { - pub fn latest_version(self) -> CommentV2 { - self.into() - } -} - -impl From for Comment { - fn from(vc: VersionedComment) -> Self { - match vc { - VersionedComment::V0(v0) => Comment { - id: 0, - author_id: v0.author_id, - timestamp: v0.timestamp, - description: v0.description, - likes: v0.likes, - comments: v0.comments, - }, - VersionedComment::V1(v1) => v1, - VersionedComment::V2(_) => unimplemented!(), - } - } -} - -impl From for CommentV2 { - fn from(vc: VersionedComment) -> Self { - match vc { - VersionedComment::V2(v2) => v2, - _ => unimplemented!(), - } - } -} - -impl From for VersionedComment { - fn from(c: Comment) -> Self { - VersionedComment::V1(c) - } -} diff --git a/src/post/github.rs b/src/post/github.rs deleted file mode 100644 index f3f91b3a..00000000 --- a/src/post/github.rs +++ /dev/null @@ -1,33 +0,0 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; - -#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct GithubV0 { - pub github_link: String, - pub name: String, - pub description: String, -} - -#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone)] -#[serde(crate = "near_sdk::serde")] -#[serde(tag = "github_version")] -#[borsh(crate = "near_sdk::borsh")] -pub enum VersionedGithub { - V0(GithubV0), -} - -impl From for VersionedGithub { - fn from(v0: GithubV0) -> Self { - VersionedGithub::V0(v0) - } -} - -impl From for GithubV0 { - fn from(vg: VersionedGithub) -> Self { - match vg { - VersionedGithub::V0(v0) => v0, - } - } -} diff --git a/src/post/idea.rs b/src/post/idea.rs deleted file mode 100644 index 39c23dee..00000000 --- a/src/post/idea.rs +++ /dev/null @@ -1,71 +0,0 @@ -use super::{Like, PostStatus}; -use crate::{CommentId, IdeaId, SolutionId}; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::{AccountId, NearSchema, Timestamp}; -use std::collections::HashSet; - -#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct Idea { - // Common Fields - pub id: IdeaId, - pub name: String, - pub description: String, - pub author_id: AccountId, - pub timestamp: Timestamp, - pub status: PostStatus, - pub likes: HashSet, - pub comments: Vec, - - // Specific fields - pub solutions: Vec, -} - -#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct IdeaV1 { - pub name: String, - pub description: String, -} - -#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[serde(tag = "idea_version")] -#[borsh(crate = "near_sdk::borsh")] -pub enum VersionedIdea { - V0(Idea), - V1(IdeaV1), -} - -impl VersionedIdea { - pub fn latest_version(self) -> IdeaV1 { - self.into() - } -} - -impl From for Idea { - fn from(vi: VersionedIdea) -> Self { - match vi { - VersionedIdea::V0(v0) => v0, - VersionedIdea::V1(_) => unimplemented!(), - } - } -} - -impl From for IdeaV1 { - fn from(vi: VersionedIdea) -> Self { - match vi { - VersionedIdea::V1(v1) => v1, - _ => unimplemented!(), - } - } -} - -impl From for VersionedIdea { - fn from(idea: Idea) -> Self { - VersionedIdea::V0(idea) - } -} diff --git a/src/post/like.rs b/src/post/like.rs deleted file mode 100644 index 73b2d824..00000000 --- a/src/post/like.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::str_serializers::*; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::{AccountId, NearSchema, Timestamp}; -use std::cmp::Ordering; -use std::hash::{Hash, Hasher}; - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Ord, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct Like { - pub author_id: AccountId, - #[serde( - serialize_with = "u64_dec_format::serialize", - deserialize_with = "u64_dec_format::deserialize" - )] - pub timestamp: Timestamp, -} - -impl Hash for Like { - fn hash(&self, state: &mut H) { - self.author_id.hash(state) - } -} - -impl PartialEq for Like { - fn eq(&self, other: &Self) -> bool { - self.author_id.eq(&other.author_id) - } -} - -impl PartialOrd for Like { - fn partial_cmp(&self, other: &Self) -> Option { - self.author_id.partial_cmp(&other.author_id) - } -} - -impl Eq for Like {} diff --git a/src/post/mod.rs b/src/post/mod.rs deleted file mode 100644 index bbbfa0e6..00000000 --- a/src/post/mod.rs +++ /dev/null @@ -1,142 +0,0 @@ -mod attestation; -mod comment; -mod github; -mod idea; -mod like; -mod solution; -mod sponsorship; - -use crate::str_serializers::*; -pub use attestation::*; -pub use comment::*; -pub use idea::*; -pub use like::*; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::{AccountId, BorshStorageKey, CryptoHash, NearSchema, Timestamp}; -pub use solution::*; -pub use sponsorship::*; -use std::collections::HashSet; - -pub type Balance = u128; -pub type PostId = u64; - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub enum PostType { - Comment, - Idea, - Solution, - Attestation, - Sponsorship, - Github, -} - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub enum PostStatus { - Open, - Closed { reason: String }, -} - -#[derive(BorshSerialize, BorshStorageKey)] -#[borsh(crate = "near_sdk::borsh")] -pub enum StorageKey { - Ideas, - Solutions, - Attestations, - Sponsorships, - Comments, - Posts, - PostToParent, - PostToChildren, - /// Deprecated due to damaged storage state. - LabelToPosts, - LabelToPostsV2, - AuthorToAuthorPosts, - AuthorPosts(CryptoHash), - Communities, - AddOns, - Proposals, - LabelToProposals, - AuthorProposals, - RFPs, - LabelToRFPs, - RFPLinkedProposals, - LabelInfo, -} - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[serde(tag = "post_version")] -#[borsh(crate = "near_sdk::borsh")] -pub enum VersionedPost { - V0(Post), -} - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct Post { - pub id: PostId, - pub author_id: AccountId, - pub likes: HashSet, - pub snapshot: PostSnapshot, - // Excludes the current snapshot itself. - pub snapshot_history: Vec, -} - -type PostTag = String; - -impl From for Post { - fn from(vp: VersionedPost) -> Self { - match vp { - VersionedPost::V0(v0) => v0, - } - } -} - -impl From for VersionedPost { - fn from(p: Post) -> Self { - VersionedPost::V0(p) - } -} - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct PostSnapshot { - pub editor_id: AccountId, - #[serde( - serialize_with = "u64_dec_format::serialize", - deserialize_with = "u64_dec_format::deserialize" - )] - pub timestamp: Timestamp, - pub labels: HashSet, - #[serde(flatten)] - pub body: PostBody, -} - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[serde(tag = "post_type")] -#[borsh(crate = "near_sdk::borsh")] -pub enum PostBody { - Comment(VersionedComment), - Idea(VersionedIdea), - Solution(VersionedSolution), - Attestation(VersionedAttestation), - Sponsorship(VersionedSponsorship), -} - -pub fn get_post_description(post: Post) -> String { - return match post.snapshot.body.clone() { - PostBody::Comment(comment) => comment.latest_version().description, - PostBody::Idea(idea) => idea.latest_version().description, - PostBody::Solution(solution) => solution.latest_version().description, - PostBody::Attestation(attestation) => attestation.latest_version().description, - PostBody::Sponsorship(sponsorship) => sponsorship.latest_version().description, - }; -} diff --git a/src/post/solution.rs b/src/post/solution.rs deleted file mode 100644 index c3350710..00000000 --- a/src/post/solution.rs +++ /dev/null @@ -1,133 +0,0 @@ -use super::{Like, PostStatus, SponsorshipToken}; -use crate::str_serializers::*; -use crate::{AttestationId, Balance, CommentId, SolutionId, SponsorshipId}; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::{AccountId, NearSchema, Timestamp}; -use std::collections::HashSet; - -#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct SolutionV0 { - // Common fields - pub id: SolutionId, - pub name: String, - pub description: String, - pub author_id: AccountId, - #[serde( - serialize_with = "u64_dec_format::serialize", - deserialize_with = "u64_dec_format::deserialize" - )] - pub timestamp: Timestamp, - pub status: PostStatus, - pub likes: HashSet, - pub comments: Vec, - - // Specific fields - #[serde( - serialize_with = "u64_dec_format::serialize", - deserialize_with = "u64_dec_format::deserialize" - )] - pub idea_id: u64, - pub attestations: Vec, - pub sponsorships: Vec, -} - -#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct SolutionV1 { - pub name: String, - pub description: String, -} - -#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct SolutionV2 { - pub name: String, - pub description: String, - pub requested_sponsor: Option, - #[serde( - serialize_with = "u128_dec_format::serialize", - deserialize_with = "u128_dec_format::deserialize" - )] - pub requested_sponsorship_amount: Balance, - pub requested_sponsorship_token: Option, -} - -#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[serde(tag = "solution_version")] -#[borsh(crate = "near_sdk::borsh")] -pub enum VersionedSolution { - V0(SolutionV0), - V1(SolutionV1), - V2(SolutionV2), -} - -impl VersionedSolution { - pub fn latest_version(self) -> SolutionV2 { - self.into() - } - - pub fn validate(&self) { - match self { - VersionedSolution::V2(solution) => { - if solution.requested_sponsorship_amount > 0 - && (solution.requested_sponsorship_token.is_none() - || solution.requested_sponsor.is_none()) - { - panic!( - "Solution that requires funding must specify sponsorship token and sponsor" - ) - } - } - - _ => unimplemented!(), - } - } -} - -impl From for SolutionV0 { - fn from(solution: VersionedSolution) -> Self { - match solution { - VersionedSolution::V0(v0) => v0, - _ => unimplemented!(), - } - } -} - -impl From for SolutionV1 { - fn from(solution: VersionedSolution) -> Self { - match solution { - VersionedSolution::V1(v1) => v1, - _ => unimplemented!(), - } - } -} - -impl From for VersionedSolution { - fn from(solution: SolutionV0) -> Self { - VersionedSolution::V0(solution) - } -} - -impl From for SolutionV2 { - fn from(solution: VersionedSolution) -> Self { - match solution { - VersionedSolution::V2(v2) => v2, - - VersionedSolution::V1(v1) => SolutionV2 { - name: v1.name, - description: v1.description, - requested_sponsor: None, - requested_sponsorship_amount: 0, - requested_sponsorship_token: None, - }, - - _ => unimplemented!(), - } - } -} diff --git a/src/post/sponsorship.rs b/src/post/sponsorship.rs deleted file mode 100644 index d9e24087..00000000 --- a/src/post/sponsorship.rs +++ /dev/null @@ -1,102 +0,0 @@ -use super::{Like, PostStatus}; -use crate::{str_serializers::*, Balance, CommentId, SolutionId, SponsorshipId}; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::{AccountId, NearSchema, Timestamp}; -use std::collections::HashSet; - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub enum SponsorshipToken { - NEAR, - NEP141 { address: AccountId }, - USD, -} - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct Sponsorship { - // Common fields - pub id: SponsorshipId, - pub name: String, - pub description: String, - pub author_id: AccountId, - #[serde( - serialize_with = "u64_dec_format::serialize", - deserialize_with = "u64_dec_format::deserialize" - )] - pub timestamp: Timestamp, - pub status: PostStatus, - pub likes: HashSet, - pub comments: Vec, - - // Specific fields - #[serde( - serialize_with = "u64_dec_format::serialize", - deserialize_with = "u64_dec_format::deserialize" - )] - pub submission_id: SolutionId, - pub sponsorship_token: SponsorshipToken, - #[serde( - serialize_with = "u128_dec_format::serialize", - deserialize_with = "u128_dec_format::deserialize" - )] - pub amount: Balance, - pub supervisor: AccountId, -} - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] -pub struct SponsorshipV1 { - pub name: String, - pub description: String, - pub sponsorship_token: SponsorshipToken, - #[serde( - serialize_with = "u128_dec_format::serialize", - deserialize_with = "u128_dec_format::deserialize" - )] - pub amount: Balance, - pub supervisor: AccountId, -} - -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[serde(tag = "sponsorship_version")] -#[borsh(crate = "near_sdk::borsh")] -pub enum VersionedSponsorship { - V0(Sponsorship), - V1(SponsorshipV1), -} - -impl VersionedSponsorship { - pub fn latest_version(self) -> SponsorshipV1 { - self.into() - } -} - -impl From for Sponsorship { - fn from(vs: VersionedSponsorship) -> Self { - match vs { - VersionedSponsorship::V0(v0) => v0, - VersionedSponsorship::V1(_) => unimplemented!(), - } - } -} - -impl From for SponsorshipV1 { - fn from(vs: VersionedSponsorship) -> Self { - match vs { - VersionedSponsorship::V1(v1) => v1, - _ => unimplemented!(), - } - } -} - -impl From for VersionedSponsorship { - fn from(s: Sponsorship) -> Self { - VersionedSponsorship::V0(s) - } -} diff --git a/src/proposal/mod.rs b/src/proposal/mod.rs index 9ab218af..54756f90 100644 --- a/src/proposal/mod.rs +++ b/src/proposal/mod.rs @@ -3,7 +3,7 @@ pub mod timeline; use std::collections::HashSet; -use self::timeline::TimelineStatus; +use self::timeline::{TimelineStatusV1, VersionedTimelineStatus}; use crate::Contract; use crate::str_serializers::*; @@ -82,7 +82,7 @@ pub struct ProposalBodyV0 { pub receiver_account: AccountId, pub requested_sponsor: AccountId, pub supervisor: Option, - pub timeline: TimelineStatus, + pub timeline: TimelineStatusV1, } #[near(serializers=[borsh, json])] @@ -102,7 +102,28 @@ pub struct ProposalBodyV1 { pub receiver_account: AccountId, pub requested_sponsor: AccountId, pub supervisor: Option, - pub timeline: TimelineStatus, + pub timeline: TimelineStatusV1, + pub linked_rfp: Option, +} + +#[near(serializers=[borsh, json])] +#[derive(Clone)] +pub struct ProposalBodyV2 { + pub name: String, + pub category: String, + pub summary: String, + pub description: String, + pub linked_proposals: Vec, + #[serde( + serialize_with = "u32_dec_format::serialize", + deserialize_with = "u32_dec_format::deserialize" + )] + pub requested_sponsorship_usd_amount: u32, + pub requested_sponsorship_paid_in_currency: ProposalFundingCurrency, + pub receiver_account: AccountId, + pub requested_sponsor: AccountId, + pub supervisor: Option, + pub timeline: VersionedTimelineStatus, pub linked_rfp: Option, } @@ -112,6 +133,7 @@ pub struct ProposalBodyV1 { pub enum VersionedProposalBody { V0(ProposalBodyV0), V1(ProposalBodyV1), + V2(ProposalBodyV2), } impl From for ProposalBodyV1 { @@ -133,6 +155,25 @@ impl From for ProposalBodyV1 { } } +impl From for ProposalBodyV2 { + fn from(v1: ProposalBodyV1) -> Self { + ProposalBodyV2 { + name: v1.name, + category: v1.category, + summary: v1.summary, + description: v1.description, + linked_proposals: v1.linked_proposals, + requested_sponsorship_usd_amount: v1.requested_sponsorship_usd_amount, + requested_sponsorship_paid_in_currency: v1.requested_sponsorship_paid_in_currency, + receiver_account: v1.receiver_account, + requested_sponsor: v1.requested_sponsor, + supervisor: v1.supervisor, + timeline: v1.timeline.into(), + linked_rfp: v1.linked_rfp, + } + } +} + impl From for ProposalBodyV0 { fn from(solution: VersionedProposalBody) -> Self { match solution { @@ -147,6 +188,20 @@ impl From for ProposalBodyV1 { match solution { VersionedProposalBody::V0(v0) => v0.into(), VersionedProposalBody::V1(v1) => v1, + _ => unimplemented!(), + } + } +} + +impl From for ProposalBodyV2 { + fn from(solution: VersionedProposalBody) -> Self { + match solution { + VersionedProposalBody::V0(v0) => { + let v1: ProposalBodyV1 = v0.into(); + v1.into() + }, + VersionedProposalBody::V1(v1) => v1.into(), + VersionedProposalBody::V2(v2) => v2, } } } @@ -163,13 +218,19 @@ impl From for VersionedProposalBody { } } +impl From for VersionedProposalBody { + fn from(p: ProposalBodyV2) -> Self { + VersionedProposalBody::V2(p) + } +} + impl VersionedProposalBody { - pub fn latest_version(self) -> ProposalBodyV1 { + pub fn latest_version(self) -> ProposalBodyV2 { self.into() } } -pub fn get_subscribers(proposal_body: &ProposalBodyV1) -> Vec { +pub fn get_subscribers(proposal_body: &ProposalBodyV2) -> Vec { let mut result = [ get_text_mentions(proposal_body.description.as_str()), get_text_mentions(proposal_body.summary.as_str()), @@ -236,20 +297,21 @@ impl Contract { let old_body = proposal.snapshot.body.clone(); let labels = self.update_and_check_rfp_link(id, body.clone(), Some(old_body.clone()), labels); - let current_timeline = old_body.latest_version().timeline; + let current_timeline = old_body.latest_version().timeline.latest_version(); + let new_timeline = proposal_body.timeline.latest_version(); require!( self.has_moderator(editor_id.clone()) || editor_id.clone() == env::current_account_id() || current_timeline.is_draft() - && (proposal_body.timeline.is_empty_review() - || proposal_body.timeline.is_draft()) - || current_timeline.can_be_cancelled() && proposal_body.timeline.is_cancelled(), + && (new_timeline.is_empty_review() + || new_timeline.is_draft()) + || current_timeline.can_be_cancelled() && new_timeline.is_cancelled(), "This account is only allowed to change proposal status from DRAFT to REVIEW" ); require!( - proposal_body.timeline.is_draft() || proposal_body.timeline.is_review() || proposal_body.timeline.is_cancelled() || proposal_body.supervisor.is_some(), + new_timeline.is_draft() || new_timeline.is_review() || new_timeline.is_cancelled() || proposal_body.supervisor.is_some(), "You can't change the timeline of the proposal to this status without adding a supervisor" ); diff --git a/src/proposal/timeline.rs b/src/proposal/timeline.rs index a677a053..9e580d76 100644 --- a/src/proposal/timeline.rs +++ b/src/proposal/timeline.rs @@ -1,17 +1,115 @@ use near_sdk::near; +pub type TimelineStatus = TimelineStatusV2; +type ReviewStatus = ReviewStatusV2; + +#[near(serializers=[borsh, json])] +#[derive(Clone)] +#[serde(tag = "status", rename_all = "SCREAMING_SNAKE_CASE")] +pub enum TimelineStatusV1 { + Draft, + Review(ReviewStatusV1), + Approved(ReviewStatusV1), + Rejected(ReviewStatusV1), + ApprovedConditionally(ReviewStatusV1), + PaymentProcessing(PaymentProcessingStatusV1), + Funded(FundedStatusV1), + Cancelled(ReviewStatusV1), +} + +#[near(serializers=[borsh, json])] +#[derive(Clone)] +#[serde(tag = "timeline_version")] +pub enum VersionedTimelineStatus { + V1(TimelineStatusV2), +} + #[near(serializers=[borsh, json])] #[derive(Clone)] #[serde(tag = "status", rename_all = "SCREAMING_SNAKE_CASE")] -pub enum TimelineStatus { +pub enum TimelineStatusV2 { Draft, - Review(ReviewStatus), - Approved(ReviewStatus), - Rejected(ReviewStatus), - ApprovedConditionally(ReviewStatus), - PaymentProcessing(PaymentProcessingStatus), - Funded(FundedStatus), - Cancelled(ReviewStatus), + Review(ReviewStatusV2), + Approved(ReviewStatusV2), + Rejected(ReviewStatusV2), + ApprovedConditionally(ReviewStatusV2), + PaymentProcessing(PaymentProcessingStatusV2), + Funded(FundedStatusV2), + Cancelled(ReviewStatusV2), +} + +fn convert_review_status_to_v1(review_status: ReviewStatusV1, kyc_verified: bool) -> ReviewStatusV2 { + ReviewStatusV2 { + sponsor_requested_review: review_status.sponsor_requested_review, + reviewer_completed_attestation: review_status.reviewer_completed_attestation, + kyc_verified_review: kyc_verified, + } +} + +impl From for PaymentProcessingStatusV2 { + fn from(value: PaymentProcessingStatusV1) -> Self { + PaymentProcessingStatusV2 { + review_status: convert_review_status_to_v1(value.review_status, value.kyc_verified), + kyc_verified: value.kyc_verified, + test_transaction_sent: value.test_transaction_sent, + request_for_trustees_created: value.request_for_trustees_created, + } + } +} + +impl From for FundedStatusV2 { + fn from(value: FundedStatusV1) -> Self { + FundedStatusV2 { + payment_processing_status: value.payment_processing_status.into(), + trustees_released_payment: value.trustees_released_payment, + payouts: value.payouts, + } + } +} + +impl From for TimelineStatusV2 { + fn from(value: TimelineStatusV1) -> Self { + match value { + TimelineStatusV1::Draft => TimelineStatusV2::Draft, + TimelineStatusV1::Review(review_status) => TimelineStatusV2::Review(convert_review_status_to_v1(review_status, false)), + TimelineStatusV1::Approved(review_status) => TimelineStatusV2::Approved(convert_review_status_to_v1(review_status, false)), + TimelineStatusV1::Rejected(review_status) => TimelineStatusV2::Rejected(convert_review_status_to_v1(review_status, false)), + TimelineStatusV1::ApprovedConditionally(review_status) => { + TimelineStatusV2::ApprovedConditionally(convert_review_status_to_v1(review_status, false)) + } + TimelineStatusV1::PaymentProcessing(payment_processing_status) => { + TimelineStatusV2::PaymentProcessing(payment_processing_status.into()) + } + TimelineStatusV1::Funded(funded_status) => TimelineStatusV2::Funded(funded_status.into()), + TimelineStatusV1::Cancelled(review_status) => TimelineStatusV2::Cancelled(convert_review_status_to_v1(review_status, false)), + } + } +} + +impl VersionedTimelineStatus { + pub fn latest_version(self) -> TimelineStatus { + self.into() + } +} + +impl From for TimelineStatusV2 { + fn from(value: VersionedTimelineStatus) -> Self { + match value { + VersionedTimelineStatus::V1(v1) => v1, + } + } +} + +impl From for VersionedTimelineStatus { + fn from(value: TimelineStatusV2) -> Self { + VersionedTimelineStatus::V1(value) + } +} + +impl From for VersionedTimelineStatus { + fn from(value: TimelineStatusV1) -> Self { + VersionedTimelineStatus::V1(value.into()) + } } impl TimelineStatus { @@ -62,7 +160,7 @@ impl TimelineStatus { | TimelineStatus::Approved(review_status) | TimelineStatus::Rejected(review_status) | TimelineStatus::ApprovedConditionally(review_status) - | TimelineStatus::Cancelled(review_status) => review_status, + | TimelineStatus::Cancelled(review_status) => review_status.into(), TimelineStatus::PaymentProcessing(payment_processing_status) => { &payment_processing_status.review_status }, @@ -72,6 +170,7 @@ impl TimelineStatus { TimelineStatus::Draft => &ReviewStatus { sponsor_requested_review: false, reviewer_completed_attestation: false, + kyc_verified_review: false, }, } } @@ -79,16 +178,24 @@ impl TimelineStatus { #[near(serializers=[borsh, json])] #[derive(Clone)] -pub struct ReviewStatus { +pub struct ReviewStatusV1 { + sponsor_requested_review: bool, + reviewer_completed_attestation: bool, +} + +#[near(serializers=[borsh, json])] +#[derive(Clone)] +pub struct ReviewStatusV2 { sponsor_requested_review: bool, reviewer_completed_attestation: bool, + kyc_verified_review: bool, } #[near(serializers=[borsh, json])] #[derive(Clone)] -pub struct PaymentProcessingStatus { +pub struct PaymentProcessingStatusV1 { #[serde(flatten)] - review_status: ReviewStatus, + review_status: ReviewStatusV1, kyc_verified: bool, test_transaction_sent: bool, request_for_trustees_created: bool, @@ -96,9 +203,28 @@ pub struct PaymentProcessingStatus { #[near(serializers=[borsh, json])] #[derive(Clone)] -pub struct FundedStatus { +pub struct PaymentProcessingStatusV2 { + #[serde(flatten)] + review_status: ReviewStatusV2, + kyc_verified: bool, + test_transaction_sent: bool, + request_for_trustees_created: bool, +} + +#[near(serializers=[borsh, json])] +#[derive(Clone)] +pub struct FundedStatusV1 { + #[serde(flatten)] + payment_processing_status: PaymentProcessingStatusV1, + trustees_released_payment: bool, + payouts: Vec, +} + +#[near(serializers=[borsh, json])] +#[derive(Clone)] +pub struct FundedStatusV2 { #[serde(flatten)] - payment_processing_status: PaymentProcessingStatus, + payment_processing_status: PaymentProcessingStatusV2, trustees_released_payment: bool, payouts: Vec, } diff --git a/src/repost.rs b/src/repost.rs deleted file mode 100644 index 31d6d858..00000000 --- a/src/repost.rs +++ /dev/null @@ -1,90 +0,0 @@ -use crate::post::{get_post_description, Post, PostBody}; -use devhub_common::social_db_contract; -use near_sdk::serde_json::json; -use near_sdk::{env, AccountId, Promise}; - -fn repost_internal(post: Post, contract_address: AccountId) -> near_sdk::serde_json::Value { - let post_link = format!("/devhub.near/widget/app?page=post&id={}", post.id); - let title = match post.snapshot.body.clone() { - PostBody::Idea(idea) => format!("## Idea: {}\n", idea.latest_version().name), - PostBody::Solution(solution) => { - format!("## Solution: {}\n", solution.latest_version().name) - } - PostBody::Attestation(attestation) => { - format!("## Attestation: {}\n", attestation.latest_version().name) - } - PostBody::Sponsorship(sponsorship) => { - format!("## Sponsorship: {}\n", sponsorship.latest_version().name) - } - _ => Default::default(), - }; - - let desc = get_post_description(post.clone()); - - let text = format!( - "@{author} [Posted on DevHub]({post_link})\n{title}{desc}", - author = post.author_id, - post_link = post_link, - title = title, - desc = desc - ); - - let main_value = json!({ - "type": "md", - "text": text - }); - - json!({ - contract_address: { - "post": { - "main": main_value.to_string(), - }, - "index": { - "post": "{\"key\":\"main\",\"value\":{\"type\":\"md\"}}", - } - } - }) -} - -pub fn repost(post: Post) -> Promise { - social_db_contract() - .with_static_gas(env::prepaid_gas().saturating_div(4)) - .with_attached_deposit(env::attached_deposit()) - .set(repost_internal(post, env::current_account_id())) -} - -#[cfg(test)] -mod tests { - use crate::post::{IdeaV1, Post, PostBody, PostSnapshot, VersionedIdea}; - use crate::repost::repost_internal; - use near_sdk::serde_json::json; - - #[test] - pub fn check_formatting() { - let post = Post { - id: 0, - author_id: "neardevgov.near".parse().unwrap(), - likes: Default::default(), - snapshot: PostSnapshot { - editor_id: "neardevgov.near".parse().unwrap(), - timestamp: 0, - labels: Default::default(), - body: PostBody::Idea(VersionedIdea::V1(IdeaV1 { name: "A call for Zero Knowledge Work Group members!".to_string(), description: "We are excited to create a more formal Zero Knowledge Work Group (WG) to oversee official decisions on Zero Knowledge proposals. We’re looking for 3-7 experts to participate. Reply to the post if you’re interested in becoming a work group member.".to_string() })), - }, - snapshot_history: vec![], - }; - - let call_args = repost_internal(post, "devhub.near".parse().unwrap()); - let expected = json!({ - "devhub.near": { - "post": { - "main": "{\"type\":\"md\",\"text\":\"@neardevgov.near [Posted on DevHub](/devhub.near/widget/app?page=post&id=0)\\n## Idea: A call for Zero Knowledge Work Group members!\\nWe are excited to create a more formal Zero Knowledge Work Group (WG) to oversee official decisions on Zero Knowledge proposals. We’re looking for 3-7 experts to participate. Reply to the post if you’re interested in becoming a work group member.\"}" - }, - "index": { - "post": "{\"key\":\"main\",\"value\":{\"type\":\"md\"}}" - } - } - }); - assert_eq!(call_args, expected); - } -} diff --git a/src/rfp/mod.rs b/src/rfp/mod.rs index 7e94e345..438e62b8 100644 --- a/src/rfp/mod.rs +++ b/src/rfp/mod.rs @@ -237,7 +237,7 @@ impl Contract { let has_approved_proposal = self.get_rfp_linked_proposals(id) .into_iter() .filter_map(|proposal_id| self.proposals.get(proposal_id.into())) - .any(|proposal| Into::::into(proposal).snapshot.body.latest_version().timeline.was_approved()); + .any(|proposal| Into::::into(proposal).snapshot.body.latest_version().timeline.latest_version().was_approved()); require!(has_approved_proposal, "Cannot change RFP status to Proposal Selected without an approved proposal linked to this RFP"); } diff --git a/tests/migration.rs b/tests/migration.rs index fc33e249..45440474 100644 --- a/tests/migration.rs +++ b/tests/migration.rs @@ -15,155 +15,7 @@ async fn test_deploy_contract_self_upgrade() -> anyhow::Result<()> { // contract is devhub contract instance. let contract = init_contracts_from_mainnet().await?; - let deposit_amount = NearToken::from_millinear(100); - - // Add Posts - let add_idea_post = contract - .call("add_post") - .args_json(json!({ - "parent_id": null, - "labels": [], - "body": { - "name": "This is a test idea.", - "description": "This is a test description.", - "post_type": "Idea", - "idea_version": "V1" - } - })) - .deposit(deposit_amount) - .transact() - .await?; - - assert!(add_idea_post.is_success()); - - let add_solution_v2_post = contract - .call("add_post") - .args_json(json!({ - "parent_id": null, - "labels": [], - "body": { - "name": "Solution Test", - "description": "This is a test solution post.", - "post_type": "Solution", - "requested_sponsor": "neardevgov.near", - "requested_sponsorship_amount": "1000", - "requested_sponsorship_token": "NEAR", - "solution_version": "V2" - } - })) - .deposit(deposit_amount) - .max_gas() - .transact() - .await?; - - assert!(add_solution_v2_post.is_success()); - - let add_comment_post = contract - .call("add_post") - .args_json(json!({ - "parent_id": 0, - "labels": [], - "body": { - "description": "This is test Comment.", - "comment_version": "V2", - "post_type": "Comment" - } - })) - .deposit(deposit_amount) - .max_gas() - .transact() - .await?; - - assert!(add_comment_post.is_success()); - - let add_attestation_post = contract - .call("add_post") - .args_json(json!({ - "parent_id": 1, - "labels": [], - "body": { - "name": "Attestation", - "description": "Description", - "attestation_version": "V1", - "post_type": "Attestation" - } - })) - .deposit(deposit_amount) - .max_gas() - .transact() - .await?; - - assert!(add_attestation_post.is_success()); - - let add_sponsorship_post_with_near = contract - .call("add_post") - .args_json(json!({ - "parent_id": 1, - "labels": [], - "body": { - "name": "Contributor fellowship", - "description": "Funding approved", - "amount": "1000", - "sponsorship_token": "NEAR", - "supervisor": "john.near", - "sponsorship_version": "V1", - "post_type": "Sponsorship" - } - })) - .deposit(deposit_amount) - .max_gas() - .transact() - .await?; - - assert!(add_sponsorship_post_with_near.is_success()); - - let add_sponsorship_post_with_usd = contract - .call("add_post") - .args_json(json!({ - "parent_id": 1, - "labels": [], - "body": { - "name": "Contributor fellowship", - "description": "Funding approved", - "amount": "1000", - "sponsorship_token": "USD", - "supervisor": "john.near", - "sponsorship_version": "V1", - "post_type": "Sponsorship" - } - })) - .deposit(deposit_amount) - .max_gas() - .transact() - .await?; - - assert!(add_sponsorship_post_with_usd.is_success()); - - let add_sponsorship_post_with_nep141 = contract - .call("add_post") - .args_json(json!({ - "parent_id": 1, - "labels": [], - "body": { - "name": "Contributor fellowship", - "description": "Funding approved", - "amount": "1000", - "sponsorship_token": { - "NEP141": { - "address": "usdt.tether-token.near" - } - }, - "supervisor": "john.near", - "sponsorship_version": "V1", - "post_type": "Sponsorship" - } - })) - .deposit(deposit_amount) - .max_gas() - .transact() - .await?; - - assert!(add_sponsorship_post_with_nep141.is_success()); + let deposit_amount = NearToken::from_millinear(10000); // Add a community let create_community = contract @@ -184,7 +36,7 @@ async fn test_deploy_contract_self_upgrade() -> anyhow::Result<()> { .transact() .await?; - assert!(dbg!(create_community).is_success()); + assert!(create_community.is_success()); let _add_proposal = contract .call("add_proposal") @@ -210,6 +62,8 @@ async fn test_deploy_contract_self_upgrade() -> anyhow::Result<()> { .transact() .await?; + assert!(_add_proposal.is_success()); + let _edit_proposal_timeline_payment = contract .call("edit_proposal_timeline") .args_json(json!({ @@ -221,6 +75,8 @@ async fn test_deploy_contract_self_upgrade() -> anyhow::Result<()> { .transact() .await?; + assert!(_edit_proposal_timeline_payment.is_success()); + // Call self upgrade with current branch code // compile the current code let wasm = near_workspaces::compile_project("./").await?; @@ -233,83 +89,6 @@ async fn test_deploy_contract_self_upgrade() -> anyhow::Result<()> { contract.call("unsafe_migrate").args_json(json!({})).max_gas().transact().await?; } - let get_idea_post: serde_json::Value = contract - .call("get_post") - .args_json(json!({ - "post_id" : 0 - })) - .view() - .await? - .json()?; - - insta::assert_json_snapshot!(get_idea_post, {".snapshot.timestamp" => "[timestamp]"}); - - let get_solution_v2_post: serde_json::Value = contract - .call("get_post") - .args_json(json!({ - "post_id" : 1 - })) - .view() - .await? - .json()?; - - insta::assert_json_snapshot!(get_solution_v2_post, {".snapshot.timestamp" => "[timestamp]"}); - - let get_comment_posts: serde_json::Value = contract - .call("get_posts") - .args_json(json!({ - "parent_id" : 0 - })) - .view() - .await? - .json()?; - - insta::assert_json_snapshot!(get_comment_posts, {"[].snapshot.timestamp" => "[timestamp]"}); - - let get_attestation_sponsorship_posts: serde_json::Value = contract - .call("get_posts") - .args_json(json!({ - "parent_id" : 1 - })) - .view() - .await? - .json()?; - - insta::assert_json_snapshot!(get_attestation_sponsorship_posts, {"[].snapshot.timestamp" => "[timestamp]"}); - - let get_sponsorship_post_with_near: serde_json::Value = contract - .call("get_post") - .args_json(json!({ - "post_id" : 4 - })) - .view() - .await? - .json()?; - - insta::assert_json_snapshot!(get_sponsorship_post_with_near, {".snapshot.timestamp" => "[timestamp]"}); - - let get_sponsorship_post_with_usd: serde_json::Value = contract - .call("get_post") - .args_json(json!({ - "post_id" : 5 - })) - .view() - .await? - .json()?; - - insta::assert_json_snapshot!(get_sponsorship_post_with_usd, {".snapshot.timestamp" => "[timestamp]"}); - - let get_sponsorship_post_with_nep141: serde_json::Value = contract - .call("get_post") - .args_json(json!({ - "post_id" : 6 - })) - .view() - .await? - .json()?; - - insta::assert_json_snapshot!(get_sponsorship_post_with_nep141, {".snapshot.timestamp" => "[timestamp]"}); - let get_community: serde_json::Value = contract .call("get_community") .args_json(json!({ diff --git a/tests/proposals.rs b/tests/proposals.rs index 2349203f..0073e68b 100644 --- a/tests/proposals.rs +++ b/tests/proposals.rs @@ -12,26 +12,6 @@ async fn test_proposal() -> anyhow::Result<()> { let deposit_amount = NearToken::from_near(2); - let add_idea_post = contract - .call("add_post") - .args_json(json!({ - "parent_id": null, - "labels": [], - "body": { - "name": "This is a test idea.", - "description": "This is a test description.", - "post_type": "Idea", - "idea_version": "V1" - } - })) - .deposit(deposit_amount) - .transact() - .await?; - - println!("add idea post: {:?}", add_idea_post); - assert!(add_idea_post.is_success()); - - let _set_categories = contract .call("set_allowed_categories") .args_json(json!({"new_categories": ["Marketing", "Events"]})) @@ -587,18 +567,18 @@ async fn test_proposal() -> anyhow::Result<()> { assert!(_edit_proposal_timeline_payment.is_success()); - let _edit_proposal_timeline_funded = contract - .call("edit_proposal_timeline") + let _edit_proposal_versional_timeline_funded = contract + .call("edit_proposal_versioned_timeline") .args_json(json!({ "id": 0, - "timeline": {"status": "FUNDED", "trustees_released_payment": false, "kyc_verified": false, "test_transaction_sent": false, "request_for_trustees_created": false, "sponsor_requested_review": true, "reviewer_completed_attestation": false, "payouts": [ "https://nearblocks.io/txns/6UwrzrYqBhA3ft2mDHXtvpzEFwkWhvCauJS1FGKjG37p" ] } + "timeline": {"timeline_version": "V1", "status": "FUNDED", "trustees_released_payment": false, "kyc_verified": false, "test_transaction_sent": false, "request_for_trustees_created": false, "sponsor_requested_review": true, "reviewer_completed_attestation": false, "kyc_verified_review": true, "payouts": [ "https://nearblocks.io/txns/6UwrzrYqBhA3ft2mDHXtvpzEFwkWhvCauJS1FGKjG37p" ] } })) .max_gas() .deposit(deposit_amount) .transact() .await?; - assert!(_edit_proposal_timeline_funded.is_success()); + assert!(_edit_proposal_versional_timeline_funded.is_success()); let get_proposal: serde_json::Value = contract .call("get_proposal") @@ -610,6 +590,7 @@ async fn test_proposal() -> anyhow::Result<()> { .json()?; assert_eq!(get_proposal["snapshot"]["timeline"]["status"], "FUNDED"); + assert_eq!(get_proposal["snapshot"]["timeline"]["kyc_verified_review"], true); let _add_team = contract .call("add_member") diff --git a/tests/snapshots/migration__deploy_contract_self_upgrade-2.snap b/tests/snapshots/migration__deploy_contract_self_upgrade-2.snap index 0d4b5bd3..e6f7dea4 100644 --- a/tests/snapshots/migration__deploy_contract_self_upgrade-2.snap +++ b/tests/snapshots/migration__deploy_contract_self_upgrade-2.snap @@ -1,23 +1,68 @@ --- source: tests/migration.rs -expression: get_solution_v2_post +expression: get_proposal --- { - "post_version": "V0", - "id": 1, + "proposal_version": "V0", + "id": 0, "author_id": "devhub.near", - "likes": [], + "social_db_post_block_height": "91", "snapshot": { "editor_id": "devhub.near", "timestamp": "[timestamp]", - "labels": [], - "post_type": "Solution", - "solution_version": "V2", - "name": "Solution Test", - "description": "This is a test solution post.", - "requested_sponsor": "neardevgov.near", - "requested_sponsorship_amount": "1000", - "requested_sponsorship_token": "NEAR" + "labels": [ + "test1", + "test2" + ], + "proposal_body_version": "V1", + "name": "another post", + "category": "Marketing", + "summary": "sum", + "description": "some description", + "linked_proposals": [ + 1, + 3 + ], + "requested_sponsorship_usd_amount": "1000000000", + "requested_sponsorship_paid_in_currency": "USDT", + "receiver_account": "polyprogrammist.near", + "requested_sponsor": "neardevdao.near", + "supervisor": "frol.near", + "timeline": { + "status": "PAYMENT_PROCESSING", + "sponsor_requested_review": true, + "reviewer_completed_attestation": false, + "kyc_verified": false, + "test_transaction_sent": false, + "request_for_trustees_created": false + }, + "linked_rfp": null }, - "snapshot_history": [] -} + "snapshot_history": [ + { + "editor_id": "devhub.near", + "timestamp": "[timestamp]", + "labels": [ + "test2", + "test1" + ], + "proposal_body_version": "V0", + "name": "another post", + "category": "Marketing", + "summary": "sum", + "description": "some description", + "linked_proposals": [ + 1, + 3 + ], + "requested_sponsorship_usd_amount": "1000000000", + "requested_sponsorship_paid_in_currency": "USDT", + "receiver_account": "polyprogrammist.near", + "requested_sponsor": "neardevdao.near", + "supervisor": "frol.near", + "timeline": { + "status": "DRAFT" + } + } + ] +} \ No newline at end of file diff --git a/tests/snapshots/migration__deploy_contract_self_upgrade-3.snap b/tests/snapshots/migration__deploy_contract_self_upgrade-3.snap deleted file mode 100644 index e0f4ba42..00000000 --- a/tests/snapshots/migration__deploy_contract_self_upgrade-3.snap +++ /dev/null @@ -1,21 +0,0 @@ ---- -source: tests/migration.rs -expression: get_comment_posts ---- -[ - { - "post_version": "V0", - "id": 2, - "author_id": "devhub.near", - "likes": [], - "snapshot": { - "editor_id": "devhub.near", - "timestamp": "[timestamp]", - "labels": [], - "post_type": "Comment", - "comment_version": "V2", - "description": "This is test Comment." - }, - "snapshot_history": [] - } -] diff --git a/tests/snapshots/migration__deploy_contract_self_upgrade-4.snap b/tests/snapshots/migration__deploy_contract_self_upgrade-4.snap deleted file mode 100644 index 6ac3295b..00000000 --- a/tests/snapshots/migration__deploy_contract_self_upgrade-4.snap +++ /dev/null @@ -1,83 +0,0 @@ ---- -source: tests/migration.rs -expression: get_attestation_sponsorship_posts ---- -[ - { - "post_version": "V0", - "id": 3, - "author_id": "devhub.near", - "likes": [], - "snapshot": { - "editor_id": "devhub.near", - "timestamp": "[timestamp]", - "labels": [], - "post_type": "Attestation", - "attestation_version": "V1", - "name": "Attestation", - "description": "Description" - }, - "snapshot_history": [] - }, - { - "post_version": "V0", - "id": 4, - "author_id": "devhub.near", - "likes": [], - "snapshot": { - "editor_id": "devhub.near", - "timestamp": "[timestamp]", - "labels": [], - "post_type": "Sponsorship", - "sponsorship_version": "V1", - "name": "Contributor fellowship", - "description": "Funding approved", - "sponsorship_token": "NEAR", - "amount": "1000", - "supervisor": "john.near" - }, - "snapshot_history": [] - }, - { - "post_version": "V0", - "id": 5, - "author_id": "devhub.near", - "likes": [], - "snapshot": { - "editor_id": "devhub.near", - "timestamp": "[timestamp]", - "labels": [], - "post_type": "Sponsorship", - "sponsorship_version": "V1", - "name": "Contributor fellowship", - "description": "Funding approved", - "sponsorship_token": "USD", - "amount": "1000", - "supervisor": "john.near" - }, - "snapshot_history": [] - }, - { - "post_version": "V0", - "id": 6, - "author_id": "devhub.near", - "likes": [], - "snapshot": { - "editor_id": "devhub.near", - "timestamp": "[timestamp]", - "labels": [], - "post_type": "Sponsorship", - "sponsorship_version": "V1", - "name": "Contributor fellowship", - "description": "Funding approved", - "sponsorship_token": { - "NEP141": { - "address": "usdt.tether-token.near" - } - }, - "amount": "1000", - "supervisor": "john.near" - }, - "snapshot_history": [] - } -] diff --git a/tests/snapshots/migration__deploy_contract_self_upgrade-5.snap b/tests/snapshots/migration__deploy_contract_self_upgrade-5.snap deleted file mode 100644 index a1a40177..00000000 --- a/tests/snapshots/migration__deploy_contract_self_upgrade-5.snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: tests/migration.rs -expression: get_sponsorship_post_with_near ---- -{ - "post_version": "V0", - "id": 4, - "author_id": "devhub.near", - "likes": [], - "snapshot": { - "editor_id": "devhub.near", - "timestamp": "[timestamp]", - "labels": [], - "post_type": "Sponsorship", - "sponsorship_version": "V1", - "name": "Contributor fellowship", - "description": "Funding approved", - "sponsorship_token": "NEAR", - "amount": "1000", - "supervisor": "john.near" - }, - "snapshot_history": [] -} diff --git a/tests/snapshots/migration__deploy_contract_self_upgrade-6.snap b/tests/snapshots/migration__deploy_contract_self_upgrade-6.snap deleted file mode 100644 index 3f02cb68..00000000 --- a/tests/snapshots/migration__deploy_contract_self_upgrade-6.snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: tests/migration.rs -expression: get_sponsorship_post_with_usd ---- -{ - "post_version": "V0", - "id": 5, - "author_id": "devhub.near", - "likes": [], - "snapshot": { - "editor_id": "devhub.near", - "timestamp": "[timestamp]", - "labels": [], - "post_type": "Sponsorship", - "sponsorship_version": "V1", - "name": "Contributor fellowship", - "description": "Funding approved", - "sponsorship_token": "USD", - "amount": "1000", - "supervisor": "john.near" - }, - "snapshot_history": [] -} diff --git a/tests/snapshots/migration__deploy_contract_self_upgrade-7.snap b/tests/snapshots/migration__deploy_contract_self_upgrade-7.snap deleted file mode 100644 index 91398745..00000000 --- a/tests/snapshots/migration__deploy_contract_self_upgrade-7.snap +++ /dev/null @@ -1,27 +0,0 @@ ---- -source: tests/migration.rs -expression: get_sponsorship_post_with_nep141 ---- -{ - "post_version": "V0", - "id": 6, - "author_id": "devhub.near", - "likes": [], - "snapshot": { - "editor_id": "devhub.near", - "timestamp": "[timestamp]", - "labels": [], - "post_type": "Sponsorship", - "sponsorship_version": "V1", - "name": "Contributor fellowship", - "description": "Funding approved", - "sponsorship_token": { - "NEP141": { - "address": "usdt.tether-token.near" - } - }, - "amount": "1000", - "supervisor": "john.near" - }, - "snapshot_history": [] -} diff --git a/tests/snapshots/migration__deploy_contract_self_upgrade-8.snap b/tests/snapshots/migration__deploy_contract_self_upgrade-8.snap deleted file mode 100644 index 9195d82e..00000000 --- a/tests/snapshots/migration__deploy_contract_self_upgrade-8.snap +++ /dev/null @@ -1,36 +0,0 @@ ---- -source: tests/migration.rs -expression: get_community ---- -{ - "admins": [ - "devhub.near" - ], - "handle": "gotham", - "name": "Gotham", - "tag": "some", - "description": "This is a test community.", - "logo_url": "https://ipfs.near.social/ipfs/bafkreibysr2mkwhb4j36h2t7mqwhynqdy4vzjfygfkfg65kuspd2bawauu", - "banner_url": "https://ipfs.near.social/ipfs/bafkreic4xgorjt6ha5z4s5e3hscjqrowe5ahd7hlfc5p4hb6kdfp6prgy4", - "bio_markdown": "This is a sample text about your community.\nYou can change it on the community configuration page.", - "github_handle": null, - "telegram_handle": null, - "twitter_handle": null, - "website_url": null, - "addons": [ - { - "id": "announcements", - "addon_id": "announcements", - "display_name": "Announcements", - "enabled": true, - "parameters": "" - }, - { - "id": "discussions", - "addon_id": "discussions", - "display_name": "Discussions", - "enabled": true, - "parameters": "" - } - ] -} diff --git a/tests/snapshots/migration__deploy_contract_self_upgrade-9.snap b/tests/snapshots/migration__deploy_contract_self_upgrade-9.snap deleted file mode 100644 index e6f7dea4..00000000 --- a/tests/snapshots/migration__deploy_contract_self_upgrade-9.snap +++ /dev/null @@ -1,68 +0,0 @@ ---- -source: tests/migration.rs -expression: get_proposal ---- -{ - "proposal_version": "V0", - "id": 0, - "author_id": "devhub.near", - "social_db_post_block_height": "91", - "snapshot": { - "editor_id": "devhub.near", - "timestamp": "[timestamp]", - "labels": [ - "test1", - "test2" - ], - "proposal_body_version": "V1", - "name": "another post", - "category": "Marketing", - "summary": "sum", - "description": "some description", - "linked_proposals": [ - 1, - 3 - ], - "requested_sponsorship_usd_amount": "1000000000", - "requested_sponsorship_paid_in_currency": "USDT", - "receiver_account": "polyprogrammist.near", - "requested_sponsor": "neardevdao.near", - "supervisor": "frol.near", - "timeline": { - "status": "PAYMENT_PROCESSING", - "sponsor_requested_review": true, - "reviewer_completed_attestation": false, - "kyc_verified": false, - "test_transaction_sent": false, - "request_for_trustees_created": false - }, - "linked_rfp": null - }, - "snapshot_history": [ - { - "editor_id": "devhub.near", - "timestamp": "[timestamp]", - "labels": [ - "test2", - "test1" - ], - "proposal_body_version": "V0", - "name": "another post", - "category": "Marketing", - "summary": "sum", - "description": "some description", - "linked_proposals": [ - 1, - 3 - ], - "requested_sponsorship_usd_amount": "1000000000", - "requested_sponsorship_paid_in_currency": "USDT", - "receiver_account": "polyprogrammist.near", - "requested_sponsor": "neardevdao.near", - "supervisor": "frol.near", - "timeline": { - "status": "DRAFT" - } - } - ] -} \ No newline at end of file diff --git a/tests/snapshots/migration__deploy_contract_self_upgrade.snap b/tests/snapshots/migration__deploy_contract_self_upgrade.snap index 80b731cc..9195d82e 100644 --- a/tests/snapshots/migration__deploy_contract_self_upgrade.snap +++ b/tests/snapshots/migration__deploy_contract_self_upgrade.snap @@ -1,20 +1,36 @@ --- source: tests/migration.rs -expression: get_idea_post +expression: get_community --- { - "post_version": "V0", - "id": 0, - "author_id": "devhub.near", - "likes": [], - "snapshot": { - "editor_id": "devhub.near", - "timestamp": "[timestamp]", - "labels": [], - "post_type": "Idea", - "idea_version": "V1", - "name": "This is a test idea.", - "description": "This is a test description." - }, - "snapshot_history": [] + "admins": [ + "devhub.near" + ], + "handle": "gotham", + "name": "Gotham", + "tag": "some", + "description": "This is a test community.", + "logo_url": "https://ipfs.near.social/ipfs/bafkreibysr2mkwhb4j36h2t7mqwhynqdy4vzjfygfkfg65kuspd2bawauu", + "banner_url": "https://ipfs.near.social/ipfs/bafkreic4xgorjt6ha5z4s5e3hscjqrowe5ahd7hlfc5p4hb6kdfp6prgy4", + "bio_markdown": "This is a sample text about your community.\nYou can change it on the community configuration page.", + "github_handle": null, + "telegram_handle": null, + "twitter_handle": null, + "website_url": null, + "addons": [ + { + "id": "announcements", + "addon_id": "announcements", + "display_name": "Announcements", + "enabled": true, + "parameters": "" + }, + { + "id": "discussions", + "addon_id": "discussions", + "display_name": "Discussions", + "enabled": true, + "parameters": "" + } + ] }