Skip to content

Commit

Permalink
Merge branch 'main' into ft_community
Browse files Browse the repository at this point in the history
  • Loading branch information
mubarak23 authored Oct 3, 2024
2 parents 491b016 + 26c1a15 commit 6726470
Show file tree
Hide file tree
Showing 12 changed files with 571 additions and 114 deletions.
2 changes: 2 additions & 0 deletions src/base/constants/errors.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ pub mod Errors {
pub const NOT_MEMBER: felt252 = 'Karst: Not a Community Member';
pub const NOT_TOKEN_OWNER: felt252 = 'Karst: Not a Token Owner';
pub const TOKEN_DOES_NOT_EXIST: felt252 = 'Karst: Token does not exist';
pub const TOKEN_DOES_NOT_EXIST: felt252 = 'Karst: token_id does not exist!';

}
39 changes: 5 additions & 34 deletions src/base/constants/types.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ pub struct Publication {
pub root_pub_id: u256,
pub upvote: u256,
pub downvote: u256,
pub channel_id: felt252,
pub collect_nft: ContractAddress,
pub tipped_amount: u256
}

// /**
Expand Down Expand Up @@ -92,6 +95,7 @@ pub enum PublicationType {
pub struct PostParams {
pub content_URI: ByteArray,
pub profile_address: ContractAddress,
pub channel_id: felt252
}

// /**
Expand Down Expand Up @@ -153,35 +157,7 @@ pub struct QuoteParams {
pub reference_pub_type: PublicationType
}

#[derive(Debug, Drop, Serde, starknet::Store, Clone)]
pub struct Upvote {
pub publication_id: u256,
pub transaction_executor: ContractAddress,
pub block_timestamp: u64,
}

#[derive(Debug, Drop, Serde, starknet::Store, Clone)]
pub struct Downvote {
pub publication_id: u256,
pub transaction_executor: ContractAddress,
pub block_timestamp: u64,
}

// /**
// * @notice A struct containing the parameters required for the `create_community()` function.
// *
// * @param community_owner The address of the profile to the create the community.
// * @param community_metadata_uri The URI to set for this new community.
// * @param community_nft_address The nft address of the community.
// * @param community_premium_status The community is premium or not .
// */
// #[derive(Debug, Drop, Serde, starknet::Store, Clone)]
// pub struct CommunityParams {
// community_id: u256,
// community_owner: ContractAddress,
// community_nft_address: ContractAddress,
// community_premium_status: bool
// }

#[derive(Debug, Drop, Serde, starknet::Store, Clone)]
pub struct CommunityDetails {
Expand Down Expand Up @@ -211,12 +187,7 @@ pub struct CommunityMember {
ban_status: bool,
}

// #[derive(Debug, Drop, Serde, starknet::Store, Clone)]
// pub struct CommunityMod {
// community_id: u256,
// transaction_executor: ContractAddress,
// mod_address: ContractAddress,
// }


#[derive(Debug, Drop, Serde, starknet::Store, Clone)]
pub struct CommunityGateKeepDetails {
Expand Down
1 change: 1 addition & 0 deletions src/collectnft.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod collectnft;
172 changes: 172 additions & 0 deletions src/collectnft/collectnft.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#[starknet::contract]
pub mod CollectNFT {
// *************************************************************************
// IMPORTS
// *************************************************************************
use core::array::ArrayTrait;
use core::traits::Into;
use core::option::OptionTrait;
use core::traits::TryInto;
use starknet::{ContractAddress, get_block_timestamp};
use core::num::traits::zero::Zero;
use karst::interfaces::ICollectNFT::ICollectNFT;
use karst::interfaces::IHub::{IHubDispatcher, IHubDispatcherTrait};
use karst::base::{
constants::errors::Errors::{ALREADY_MINTED, TOKEN_DOES_NOT_EXIST},
utils::base64_extended::convert_into_byteArray
};
use starknet::storage::{
Map, StoragePointerWriteAccess, StoragePointerReadAccess, StorageMapReadAccess,
StorageMapWriteAccess
};
use openzeppelin::{
access::ownable::OwnableComponent, token::erc721::{ERC721Component, ERC721HooksEmptyImpl},
introspection::{src5::SRC5Component}
};
component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
component!(path: SRC5Component, storage: src5, event: SRC5Event);
component!(path: ERC721Component, storage: erc721, event: ERC721Event);

// allow to check what interface is supported
#[abi(embed_v0)]
impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
impl SRC5InternalImpl = SRC5Component::InternalImpl<ContractState>;

// make it a NFT
#[abi(embed_v0)]
impl ERC721Impl = ERC721Component::ERC721Impl<ContractState>;
#[abi(embed_v0)]
impl ERC721CamelOnlyImpl = ERC721Component::ERC721CamelOnlyImpl<ContractState>;
impl ERC721InternalImpl = ERC721Component::InternalImpl<ContractState>;

// add an owner
#[abi(embed_v0)]
impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;


// *************************************************************************
// STORAGE
// *************************************************************************
#[storage]
struct Storage {
#[substorage(v0)]
erc721: ERC721Component::Storage,
#[substorage(v0)]
src5: SRC5Component::Storage,
#[substorage(v0)]
ownable: OwnableComponent::Storage,
karst_hub: ContractAddress,
last_minted_id: u256,
mint_timestamp: Map<u256, u64>,
user_token_id: Map<ContractAddress, u256>,
profile_address: ContractAddress,
pub_id: u256,
}

// *************************************************************************
// EVENTS
// *************************************************************************
#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
ERC721Event: ERC721Component::Event,
#[flat]
SRC5Event: SRC5Component::Event,
#[flat]
OwnableEvent: OwnableComponent::Event,
}

// *************************************************************************
// CONSTRUCTOR
// *************************************************************************
#[constructor]
fn constructor(
ref self: ContractState,
karst_hub: ContractAddress,
profile_address: ContractAddress,
pub_id: u256,
) {
self.karst_hub.write(karst_hub);
self.profile_address.write(profile_address);
self.pub_id.write(pub_id);
}

#[abi(embed_v0)]
impl CollectNFTImpl of ICollectNFT<ContractState> {
// *************************************************************************
// EXTERNAL
// *************************************************************************
/// @notice mints the collect NFT
/// @param address address of user trying to mint the collect NFT
fn mint_nft(ref self: ContractState, address: ContractAddress) -> u256 {
let balance = self.erc721.balance_of(address);
assert(balance.is_zero(), ALREADY_MINTED);

let mut token_id = self.last_minted_id.read() + 1;
self.erc721.mint(address, token_id);
let timestamp: u64 = get_block_timestamp();
self.user_token_id.write(address, token_id);
self.last_minted_id.write(token_id);
self.mint_timestamp.write(token_id, timestamp);
self.last_minted_id.read()
}

// *************************************************************************
// GETTERS
// *************************************************************************
/// @notice gets the token ID for a user address
/// @param user address of user to retrieve token ID for
fn get_user_token_id(self: @ContractState, user: ContractAddress) -> u256 {
self.user_token_id.read(user)
}

fn get_token_mint_timestamp(self: @ContractState, token_id: u256) -> u64 {
self.mint_timestamp.read(token_id)
}

/// @notice gets the last minted NFT
fn get_last_minted_id(self: @ContractState) -> u256 {
self.last_minted_id.read()
}
///@notice get source publication pointer
///
fn get_source_publication_pointer(self: @ContractState) -> (ContractAddress, u256) {
let profile_address = self.profile_address.read();
let pub_id = self.pub_id.read();
(profile_address, pub_id)
}
// *************************************************************************
// METADATA
// *************************************************************************
/// @notice returns the collection name
fn name(self: @ContractState) -> ByteArray {
let mut collection_name = ArrayTrait::<felt252>::new();
let profile_address_felt252: felt252 = self.profile_address.read().into();
let pub_id_felt252: felt252 = self.pub_id.read().try_into().unwrap();
collection_name.append('Karst Collect | Profile #');
collection_name.append(profile_address_felt252);
collection_name.append('- Publication #');
collection_name.append(pub_id_felt252);
let collection_name_byte = convert_into_byteArray(ref collection_name);
collection_name_byte
}

/// @notice returns the collection symbol
fn symbol(self: @ContractState) -> ByteArray {
return "KARST:COLLECT";
}

/// @notice returns the token_uri for a particular token_id
fn token_uri(self: @ContractState, token_id: u256) -> ByteArray {
assert(self.erc721.exists(token_id), TOKEN_DOES_NOT_EXIST);
let profile_address = self.profile_address.read();
let pub_id = self.pub_id.read();
let karst_hub = self.karst_hub.read();
let token_uri = IHubDispatcher { contract_address: karst_hub }
.get_publication_content_uri(profile_address, pub_id);
token_uri
}
}
}
2 changes: 2 additions & 0 deletions src/interfaces.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ pub mod IHandle;
pub mod IHandleRegistry;
pub mod IHub;
pub mod ICommunity;
pub mod ICollectNFT;

21 changes: 21 additions & 0 deletions src/interfaces/ICollectNFT.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use starknet::ContractAddress;
#[starknet::interface]
pub trait ICollectNFT<TState> {
// *************************************************************************
// EXTERNALS
// *************************************************************************
fn mint_nft(ref self: TState, address: ContractAddress) -> u256;
// *************************************************************************
// GETTERS
// *************************************************************************
fn get_last_minted_id(self: @TState) -> u256;
fn get_user_token_id(self: @TState, user: ContractAddress) -> u256;
fn get_token_mint_timestamp(self: @TState, token_id: u256) -> u64;
fn get_source_publication_pointer(self: @TState) -> (ContractAddress, u256);
// *************************************************************************
// METADATA
// *************************************************************************
fn name(self: @TState) -> ByteArray;
fn symbol(self: @TState) -> ByteArray;
fn token_uri(self: @TState, token_id: u256) -> ByteArray;
}
13 changes: 10 additions & 3 deletions src/interfaces/IPublication.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@ pub trait IKarstPublications<TState> {
fn repost(ref self: TState, repost_params: RepostParams) -> u256;
fn upvote(ref self: TState, profile_address: ContractAddress, pub_id: u256);
fn downvote(ref self: TState, profile_address: ContractAddress, pub_id: u256);
fn collect(ref self: TState, pub_id: u256) -> bool;

fn tip(ref self: TState, profile_address: ContractAddress, pub_id: u256, amount: u256);
fn collect(
ref self: TState,
karst_hub: ContractAddress,
profile_address: ContractAddress,
pub_id: u256,
collect_nft_impl_class_hash: felt252,
salt: felt252
) -> u256;
// *************************************************************************
// GETTERS
// *************************************************************************
Expand All @@ -30,7 +37,7 @@ pub trait IKarstPublications<TState> {
fn get_publication_content_uri(
self: @TState, profile_address: ContractAddress, pub_id: u256
) -> ByteArray;
fn has_user_voted(self: @TState, profile_address: ContractAddress, pub_id: u256) -> bool;
fn get_upvote_count(self: @TState, profile_address: ContractAddress, pub_id: u256) -> u256;
fn get_downvote_count(self: @TState, profile_address: ContractAddress, pub_id: u256) -> u256;
fn get_tipped_amount(self: @TState, profile_address: ContractAddress, pub_id: u256) -> u256;
}
1 change: 1 addition & 0 deletions src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ pub mod publication;
pub mod namespaces;
pub mod presets;
pub mod hub;
pub mod collectnft;
12 changes: 11 additions & 1 deletion src/mocks/interfaces/IComposable.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,16 @@ pub trait IComposable<TState> {
fn repost(ref self: TState, mirror_params: RepostParams) -> u256;
fn upvote(ref self: TState, profile_address: ContractAddress, pub_id: u256);
fn downvote(ref self: TState, profile_address: ContractAddress, pub_id: u256);
fn collect(ref self: TState, pub_id: u256) -> bool;
fn tip(ref self: TState, profile_address: ContractAddress, pub_id: u256, amount: u256);
fn collect(
ref self: TState,
karst_hub: ContractAddress,
profile_address: ContractAddress,
pub_id: u256,
collect_nft_impl_class_hash: felt252,
salt: felt252
) -> u256;

// *************************************************************************
// GETTERS
// *************************************************************************
Expand All @@ -62,4 +71,5 @@ pub trait IComposable<TState> {
fn has_user_voted(self: @TState, profile_address: ContractAddress, pub_id: u256) -> bool;
fn get_upvote_count(self: @TState, profile_address: ContractAddress, pub_id: u256) -> u256;
fn get_downvote_count(self: @TState, profile_address: ContractAddress, pub_id: u256) -> u256;
fn get_tipped_amount(self: @TState, profile_address: ContractAddress, pub_id: u256) -> u256;
}
8 changes: 1 addition & 7 deletions src/profile/profile.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -188,13 +188,7 @@ pub mod ProfileComponent {
) -> u256 {
let mut profile: Profile = self.profile.read(profile_address);
let new_pub_count = profile.pub_count + 1;
let updated_profile = Profile {
profile_address: profile.profile_address,
profile_owner: profile.profile_owner,
pub_count: new_pub_count,
metadata_URI: profile.metadata_URI,
follow_nft: profile.follow_nft
};
let updated_profile = Profile { pub_count: new_pub_count, ..profile };

self.profile.write(profile_address, updated_profile);
new_pub_count
Expand Down
Loading

0 comments on commit 6726470

Please sign in to comment.