4.10 Twitter Dapp 01 Smart Contract

閱讀時間約 28 分鐘

Overview

  1. Create a Twitter Contract (ep.7) 🌳
  2. Creat a mapping between user and tweet 🌳
  3. Add function to creat a tweet and save it in mapping 🌳
  4. Create a function to get Tweet (ep.11) 🌳
  5. Define a Tweet Struct with Author, content, timestamp, likes (ep.13) 🌳
  6. Add the struct to array Test tweets (ep.13) 🌳
  7. Use require to limit the length of the tweet to be only 280 characters (ep.15) 🌳
  8. Add a function called change TweetLength to change max tweet length ( Hint: use newTweetLength as input for function) (ep.17) 🌳
  9. Create a constructor function to set an owner of contract (ep.17) 🌳
  10. Create a modifier called onlyOwner (ep.17) 🌳
  11. Use onlyOwner on the changeTweetLength function (ep.17) 🌳
  12. Add id to Tweet Struct to make every Tweet Unique (ep.18)🌳
  13. Set the id to be the Tweet [ ] length (Hint: you do it in the creatTweet function) ep.18)🌳
  14. Add a function to like the tweet (Hint: there should be 2 paramenters, id and author ep.18) 🌳
  15. Add a function to unlike the tweet (make sure you can unlike only if likes count is greater than 0 (ep.18) 🌳
  16. Mark both functions external (ep.18) 🌳
  17. Deploy Smart Contract to Sepolia (ep.19) 🌳
  18. Create Event for creating the tweet, called TweetCreated (Use parameters like id, author, content, timestamp) (ep.21)🌳
  19. Emit the event in the createTweet() function below(ep.21)🌳
  20. Create Event for liking the tweet, called TweetLiked (Use parameters like liker, tweetAuthor, tweetId, newLikeCount(ep.21)🌳
  21. Emit the event in the likeTweet() function below(ep.21)🌳
  22. Create a function, getTotalLikes, get total Tweet likes for the user ( User parameters of author) (ep.24) 🌳
  23. Loop over all the tweets (ep.24) 🌳
  24. sum up totalLikes (ep.24) 🌳
  25. Return totalLike (ep.24) 🌳
  26. Save UserProfile to the mapping in the setProfile() function// HINT: don't forget to set the _displayName and _bio (ep.28)
  27. // 2️⃣ Add a getProfile() function to the interface ✅//
  28. 3️⃣ Initialize the IProfile in the contructor ✅// HINT: don't forget to include the _profileContract address as a input//
  29. 4️⃣ Create a modifier called onlyRegistered that require the msg.sender to have a profile ✅// HINT: use the getProfile() to get the user// HINT: check if displayName.length > 0 to make sure the user exists//
  30. 5️⃣ ADD the onlyRegistered modified to createTweet, likeTweet, and unlikeTweet function ✅




// SPDX-License-Identifier: MIT
pragma solidity ^ 0.8.24;

contract Twitter { // 1️⃣ Create a Twitter Contract
// 定義不可改變的數字
uint16 public MAX_TWEET_LENGTH = 280;

// 5️⃣ Define a Tweet Struct with Author, content, timestamp, likes
// Struct: define a tweet wtih multiple data
// 1️⃣1️⃣ Add id to Tweet Struct to make every Tweet Unique
struct Tweet {
uint256 id;
address author;
string content;
uint256 timestamp;
uint256 likes;
}

// 2️⃣ Create a mappping between user and tweet
mapping(address => Tweet[] ) public tweets;
address public owner; // define the owner of this contract

// 1️⃣5️⃣ Create Event for creating the tweet, called TweetCreated
// Use parameters like id, author, content, timestamp
// 1️⃣7️⃣ Create Event for liking the tweet, called TweetLiked (Use parameters like liker, tweetAuthor, tweetId, newLikeCount
event TweetCreated(uint256 id, address author, string content, uint256 timestamp);
event TweetLiked(address liker, address tweetAuthor, uint256 tweetId, uint256newLikedCount);
event TweetUnliked(address unliker, address tweetAuthor, uint256 tweetId, newLikeCount);

// 8️⃣ create the constructor under all the variables
// Create a constructor function to set an owner of contract
constructor(){
owner = msg.sender;
}

// 9️⃣ Create a modifier called onlyOwner: to check if the owner is calling the function
modifier onlyowner() { // use modifier to check onlyowner
require(msg.sender == owner, "You Are Not The Owner");
_;
}

// 7️⃣ Add a function called change TweetLength to change max tweet length
// ( Hint: use newTweetLength as input for function)
// 🔟 Use onlyOwner on the changeTweetLength function
function changeTweetLength(uint16 newTweetLength) public onlyOwner {
MAX_TWEET_LENGTH = newTweetLength;
}

// 3️⃣ Add function to create a tweet and save it in mapping
// store the tweets above in temporary memory
// key is the address (the msg.sender)
// msg.sender: whoever is using the blockchain interacting with your code
// Add the struct to array Test tweets
function createTweet(string memory _tweet) public {

// 6️⃣ Use require to limit the length of the tweet to be only 280 characters (ep.15)
// conditional
// if tweet length <= 280 then we are good, otherwise we revert
function createTweet(string memory _tweet) public {
require(bytes(_tweet).length <= MAX_TWEET_LENGTH, "Tweet is too long bro");

// 1️⃣2️⃣ Set the id to be the Tweet [ ] length (Hint: you do it in the creatTweet function)
Tweet memory newTweet = Tweet({
id: tweets[msg.sender].length,
author: msg.sender,
content: _tweet,
timestamp: block.timestamp,
likes: 0
});
// not only 1 tweet, so use array
// push the tweet into the array
tweets[msg.sender].push(newTweet);

// 1️⃣6️⃣ Emit the event in the createTweet() function below
emit TweetCreated(newTweet, id, newTweet.author, newTweet.content, newTweet.timestamp);
}

// 1️⃣3️⃣ Add a function to like the tweet (Hint: there should be 2 paramenters, id and author
// 1️⃣5️⃣ Mark both functions external
require tweets[author][id].id == id, "TWEET DOES NOT EXISTS";
function likeTweet(address author, uint256 id) external {
tweets[author][id].likes++; //likes = likes + 1;

// 1️⃣8️⃣ Emit the event in the likeTweet() function below
emit TweetLiked(msg.sender, author, id, tweets[author][id].likes);
}

// 1️⃣4️⃣ Add a function to unlike the tweet (make sure you can unlike only if likes count is greater than 0)
// 1️⃣5️⃣ Mark both functions external
function unlikeTweet(address author, uint256 id) external {
require(tweets[author][id].id == id, "TWEET DOES NOT EXISTS");
require(tweets[author][id].likes > 0, "TWEET HAS NO LIKES");
tweets[author][id].likes--;

emit TweetUnLiked(msg.sender, author, id, tweets[author][id].likes);
// you cannnot decrement the count if the tweet does not exist
// also the count cannot be negative
}

// 4️⃣ Create a function to get tweet
// not only 1 tweet, so use index to specify the tweet
function getTweet(uint _i) public view returns (Tweet memory) {
return tweets[msg.sender][_i]; //only check for information
}

function getAllTweets(address _owner) public view returns (Tweet[] memory){
return tweets[_owner];
}
}


create a twitter contract and a user profile contract (exercise user)

// SPDX-License-Identifier: MIT

// 1️⃣ Save UserProfile to the mapping in the setProfile() function
// HINT: don't forget to set the _displayName and _bio

pragma solidity ^0.8.0;

contract Profile {
struct UserProfile {
string displayName;
string bio;
}
string maxSupply = 50;
mapping(address => UserProfile) public profiles;

function setProfile(string memory _displayName, string memory _bio) public {
// CODE HERE 👇
profiles[msg.sender] = UserProfile(_displayName, _bio);
}

function getProfile(address _user) public view returns (UserProfile memory) {
return profiles[_user];
}
}


exercise(main)

// SPDX-License-Identifier: MIT

import "@openzeppelin/contracts/access/Ownable.sol";

pragma solidity ^0.8.0;

interface IProfile {
struct UserProfile {
string displayName;
string bio;
}

// 2️⃣ Add a getProfile() function to the interface ✅
// CODE HERE
function getProfile (address _user) external view returns (UserProfile memory)
}

contract Twitter is Ownable {

uint16 public MAX_TWEET_LENGTH = 280;

struct Tweet {
uint256 id;
address author;
string content;
uint256 timestamp;
uint256 likes;
}
mapping(address => Tweet[] ) public tweets;
// profile contract defined here
IProfile profileContract;

// Define the events
event TweetCreated(uint256 id, address author, string content, uint256 timestamp);
event TweetLiked(address liker, address tweetAuthor, uint256 tweetId, uint256 newLikeCount);
event TweetUnliked(address unliker, address tweetAuthor, uint256 tweetId, uint256 newLikeCount);

// 4️⃣ Create a modifier called onlyRegistered that require the msg.sender to have a profile ✅
// HINT: use the getProfile() to get the user
// HINT: check if displayName.length > 0 to make sure the user exists
modifier onlyRegistered(){
IProfile.UserProfile memory userProfileTemp = profileContract.getProfile(
require(bytes(userProfileTemp.displayName).length > 0, "USER NOT REGISTERED");
_);
}

// 3️⃣ Initialize the IProfile in the contructor ✅
// HINT: don't forget to include the _profileContract address as a input
constructor(address _profileContract) {
profileContract = IProfile(_profileContract);
}

function changeTweetLength(uint16 newTweetLength) public onlyOwner {
MAX_TWEET_LENGTH = newTweetLength;
}

function getTotalLikes(address _author) external view returns(uint) {
uint totalLikes;

for( uint i = 0; i < tweets[_author].length; i++){
totalLikes += tweets[_author][i].likes;
}

return totalLikes;
}

function createTweet(string memory _tweet) public {
require(bytes(_tweet).length <= MAX_TWEET_LENGTH, "Tweet is too long bro!" );

Tweet memory newTweet = Tweet({
id: tweets[msg.sender].length,
author: msg.sender,
content: _tweet,
timestamp: block.timestamp,
likes: 0
});

tweets[msg.sender].push(newTweet);

// Emit the TweetCreated event
emit TweetCreated(newTweet.id, newTweet.author, newTweet.content, newTweet.timestamp);
}

// 5️⃣ ADD the onlyRegistered modified to createTweet, likeTweet, and unlikeTweet function ✅
function likeTweet(address author, uint256 id) external onlyRegistered {
require(tweets[author][id].id == id, "TWEET DOES NOT EXIST");

tweets[author][id].likes++;

// Emit the TweetLiked event
emit TweetLiked(msg.sender, author, id, tweets[author][id].likes);
}

// 5️⃣ ADD the onlyRegistered modified to createTweet, likeTweet, and unlikeTweet function ✅
function unlikeTweet(address author, uint256 id) external onlyRegistered {
require(tweets[author][id].id == id, "TWEET DOES NOT EXIST");
require(tweets[author][id].likes > 0, "TWEET HAS NO LIKES");

tweets[author][id].likes--;

emit TweetUnliked(msg.sender, author, id, tweets[author][id].likes );
}

function getTweet( uint _i) public view returns (Tweet memory) {
return tweets[msg.sender][_i];
}

function getAllTweets(address _owner) public view returns (Tweet[] memory ){
return tweets[_owner];
}

}


Add Account create to Twitter Dapp

useStateVariables

app.js


Ultimate Solidity Smart Contract Course - For Complete Beginners




尋大神腳印, 亦步亦趨。
留言0
查看全部
發表第一個留言支持創作者!
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
性學泰斗金賽博士說接受他們調查的人士如何如何,但卻不告訴我們他一星期性交幾次?有沒有婚外性行為?而性治療權威馬斯特及瓊森夫婦也說來找他們的病人如何如何,但也不告訴我們他歷時幾分鐘才射精?而他妻子瓊森有沒有達到高潮,感受又如何?之,大家說了一大堆,但說的都不是自己,而是「別人」的性事。
司馬嵐在審訊室內被伊本不發一言的耐力氣得七竅生煙。她站門旁他則喝著免費提供給嫌犯的紙杯裝熱咖啡,坐在鐵桌前背靠牆牆的伊本一臉冷漠地邪眼瞅著司馬嵐的性感身材。淫褻的眼光上下打量著這位女幹探,那張沒格沒局沒修養沒文化的男人的雙腿還不斷的在上下震動,像觸了交流電的在抖,引發他整個身體都在輕微的像四級地震。
Thumbnail
如果總統提告是第二階段。 那原稿公佈就是第三階段的開始。 我知道接下來挺英派會怎麼操作。 👉『你們還想怎樣?!』。對民眾植入無理取閙、沒完沒了的論文門厭倦感。 👉『越打論文小英民調越高!』。讓對論文有質疑的人也開始鬆動。
Thumbnail
難得沒遇上下雨的周六,我與孟相約來參加方格子的活動。必須先說一下結尾,是一場雞湯滿滿的饗宴,而我心靈品味的非常滿足。 第一位講師李柏鋒老師,才開始沒幾分鐘,投影片的內容和珠珠字句,彷彿就像知道我目前所遇到的心裡糾結,開始一一為我解答,成功的穩固我寫作最初的起心動念。 我覺得好幸運。
Thumbnail
為提升台灣醫師與醫療形象,鼓勵民眾及國內新聞與醫療從業人員重視醫藥新聞報導與評論,對醫藥相關議題多予報導並發表議論,改善醫療環境,促進醫病關係和諧,中華民國醫師公會全聯會辦理「109年臺灣醫療報導獎」,期透過優秀的作品,報導臺灣醫療的正向力量。
Thumbnail
歡迎至我的網誌觀看全文,比較好閱讀 很榮幸能被高雄市政府社會局與高雄市婦女館邀請,在2020年9月26日於高雄市婦女館演講廳發表【當我們談論情感教育,我們談論情感教育什麼?】
Thumbnail
知識流動,一日分享 藏壽司甫上櫃股價不如預期 申購算是基礎入門磚課程,去年寫了一篇中央商事法(3):新光金2888申購+特別股>,今(109)年的第二堂課就是上申購 剛好最近很夯的藏壽司申購,頗受到市場的關注 E 結果51.1萬人參與申購,創下今年申購人數新高,中籤率才0.3%......
Thumbnail
109年度 「U-start 創新創業計畫」方格子邱允文 阿拉丁創客團隊 — 創業團隊(阿拉丁AI健康智能照護) 邱允文阿拉丁創客團隊的創業故事| 方格子   邱允文阿拉丁創客團隊的創業故事. 有人說:「有夢最美,希望相隨。」 每一個人都有夢想,都想要去實現;而我們三個人的夢想,就是想要開創屬於自己
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
性學泰斗金賽博士說接受他們調查的人士如何如何,但卻不告訴我們他一星期性交幾次?有沒有婚外性行為?而性治療權威馬斯特及瓊森夫婦也說來找他們的病人如何如何,但也不告訴我們他歷時幾分鐘才射精?而他妻子瓊森有沒有達到高潮,感受又如何?之,大家說了一大堆,但說的都不是自己,而是「別人」的性事。
司馬嵐在審訊室內被伊本不發一言的耐力氣得七竅生煙。她站門旁他則喝著免費提供給嫌犯的紙杯裝熱咖啡,坐在鐵桌前背靠牆牆的伊本一臉冷漠地邪眼瞅著司馬嵐的性感身材。淫褻的眼光上下打量著這位女幹探,那張沒格沒局沒修養沒文化的男人的雙腿還不斷的在上下震動,像觸了交流電的在抖,引發他整個身體都在輕微的像四級地震。
Thumbnail
如果總統提告是第二階段。 那原稿公佈就是第三階段的開始。 我知道接下來挺英派會怎麼操作。 👉『你們還想怎樣?!』。對民眾植入無理取閙、沒完沒了的論文門厭倦感。 👉『越打論文小英民調越高!』。讓對論文有質疑的人也開始鬆動。
Thumbnail
難得沒遇上下雨的周六,我與孟相約來參加方格子的活動。必須先說一下結尾,是一場雞湯滿滿的饗宴,而我心靈品味的非常滿足。 第一位講師李柏鋒老師,才開始沒幾分鐘,投影片的內容和珠珠字句,彷彿就像知道我目前所遇到的心裡糾結,開始一一為我解答,成功的穩固我寫作最初的起心動念。 我覺得好幸運。
Thumbnail
為提升台灣醫師與醫療形象,鼓勵民眾及國內新聞與醫療從業人員重視醫藥新聞報導與評論,對醫藥相關議題多予報導並發表議論,改善醫療環境,促進醫病關係和諧,中華民國醫師公會全聯會辦理「109年臺灣醫療報導獎」,期透過優秀的作品,報導臺灣醫療的正向力量。
Thumbnail
歡迎至我的網誌觀看全文,比較好閱讀 很榮幸能被高雄市政府社會局與高雄市婦女館邀請,在2020年9月26日於高雄市婦女館演講廳發表【當我們談論情感教育,我們談論情感教育什麼?】
Thumbnail
知識流動,一日分享 藏壽司甫上櫃股價不如預期 申購算是基礎入門磚課程,去年寫了一篇中央商事法(3):新光金2888申購+特別股>,今(109)年的第二堂課就是上申購 剛好最近很夯的藏壽司申購,頗受到市場的關注 E 結果51.1萬人參與申購,創下今年申購人數新高,中籤率才0.3%......
Thumbnail
109年度 「U-start 創新創業計畫」方格子邱允文 阿拉丁創客團隊 — 創業團隊(阿拉丁AI健康智能照護) 邱允文阿拉丁創客團隊的創業故事| 方格子   邱允文阿拉丁創客團隊的創業故事. 有人說:「有夢最美,希望相隨。」 每一個人都有夢想,都想要去實現;而我們三個人的夢想,就是想要開創屬於自己