4.11 Twitter Dapp 02 Javascript

更新 發佈閱讀 17 分鐘

Overview

1. Request Wallet Connection from Metamask get account function

get account function

2. Set your smart contract address

injected provider address

3. connect to the contract using web3

connect app and smart contract with web3.js

4. call the contract createTweet method in order to crete the actual TWEET

call the function to create the actual tweet

waiting for the function to complete completely

5. call the function getAllTweets from smart contract to get all the tweets

.send - I'm giving you this data

.call - give it to me



6. Call the displayTweets function with address as input

7. Uncomment the displayTweets function! PRETTY EASY 🔥

8. call the likeTweet function from smart contract


index.js

import contractABI from "./abi.json";

// 2️⃣ Set your smart contract address 👇
const contractAddress = "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4";

let web3 = new Web3(window.ethereum);
// 3️⃣ connect to the contract using web3
// HINT: https://web3js.readthedocs.io/en/v1.2.11/web3-eth-contract.html#new-contract
// let contract = YOUR CODE
let contract = new web3.eth.Contract(contractABI, contractAddress);


async function connectWallet() {
if (window.ethereum) {
// 1️⃣ Request Wallet Connection from Metamask
// ANSWER can be found here: https://docs.metamask.io/wallet/get-started/set-up-dev-environment/
// const accounts = YOUR CODE
const accounts = await window.ethereum
.request({method: "eth_requestAccounts"})
.catch((err) => {
if (err.code === 4001) {
console.log("Please connect to MetaMask.");
} else {
console.error(err);
}
});

console.log(accounts);

setConnected(accounts[0]);
} else {
console.error("No web3 provider detected");
document.getElementById("connectMessage").innerText =
"No web3 provider detected. Please install MetaMask.";
}
}

async function createTweet(content) {
const accounts = await web3.eth.getAccounts();
try {
// 4️⃣ call the contract createTweet method in order to crete the actual TWEET
// HINT: https://web3js.readthedocs.io/en/v1.2.11/web3-eth-contract.html#methods-mymethod-send
// use the "await" feature to wait for the function to finish execution
// what is await? https://javascript.info/async-await
await contract.methods.createTweet(content).send({from: accounts[0]});


// 7️⃣ Uncomment the displayTweets function! PRETTY EASY 🔥
// GOAL: reload tweets after creating a new tweet
displayTweets(accounts[0]);
} catch (error) {
console.error("User rejected request:", error);
}
}

async function displayTweets(userAddress) {
const tweetsContainer = document.getElementById("tweetsContainer");
const tempTweets = [];
tweetsContainer.innerHTML = "";
// 5️⃣ call the function getAllTweets from smart contract to get all the tweets
// HINT: https://web3js.readthedocs.io/en/v1.2.11/web3-eth-contract.html#methods-mymethod-call
// tempTweets = await YOUR CODE
tempTweets = await contract.methods.getAllTweets(userAddress).call();

// we do this so we can sort the tweets by timestamp
const tweets = [...tempTweets];
tweets.sort((a, b) => b.timestamp - a.timestamp);
for (let i = 0; i < tweets.length; i++) {
const tweetElement = document.createElement("div");
tweetElement.className = "tweet";

const userIcon = document.createElement("img");
userIcon.className = "user-icon";
userIcon.src = `https://avatars.dicebear.com/api/human/${tweets[i].author}.svg`;
userIcon.alt = "User Icon";

tweetElement.appendChild(userIcon);

const tweetInner = document.createElement("div");
tweetInner.className = "tweet-inner";

tweetInner.innerHTML += `
<div class="author">${shortAddress(tweets[i].author)}</div>
<div class="content">${tweets[i].content}</div>
`;

const likeButton = document.createElement("button");
likeButton.className = "like-button";
likeButton.innerHTML = `
<i class="far fa-heart"></i>
<span class="likes-count">${tweets[i].likes}</span>
`;
likeButton.setAttribute("data-id", tweets[i].id);
likeButton.setAttribute("data-author", tweets[i].author);

addLikeButtonListener(
likeButton,
userAddress,
tweets[i].id,
tweets[i].author
);
tweetInner.appendChild(likeButton);
tweetElement.appendChild(tweetInner);

tweetsContainer.appendChild(tweetElement);
}
}

function addLikeButtonListener(likeButton, address, id, author) {
likeButton.addEventListener("click", async (e) => {
e.preventDefault();

e.currentTarget.innerHTML = '<div class="spinner"></div>';
e.currentTarget.disabled = true;
try {
await likeTweet(author, id);
displayTweets(address);
} catch (error) {
console.error("Error liking tweet:", error);
}
});
}

function shortAddress(address, startLength = 6, endLength = 4) {
return `${address.slice(0, startLength)}...${address.slice(-endLength)}`;
}

async function likeTweet(author, id) {
try {
// 8️⃣ call the likeTweet function from smart contract
// INPUT: author and id
// GOAL: Save the like in the smart contract
// HINT: don't forget to use await 😉 👇
await contract.methods.likeTweet(author, id).send({from: accounts[0 ]})
} catch (error) {
console.error("User rejected request:", error);
}
}

function setConnected(address) {
document.getElementById("userAddress").innerText =
"Connected: " + shortAddress(address);
document.getElementById("connectMessage").style.display = "none";
document.getElementById("tweetForm").style.display = "block";

// 6️⃣ Call the displayTweets function with address as input
// This is the function in the javascript code, not smart contract 😉
// GOAL: display all tweets after connecting to metamask
displayTweets(address);
}

document
.getElementById("connectWalletBtn")
.addEventListener("click", connectWallet);

document.getElementById("tweetForm").addEventListener("submit", async (e) => {
e.preventDefault();
const content = document.getElementById("tweetContent").value;
const tweetSubmitButton = document.getElementById("tweetSubmitBtn");
tweetSubmitButton.innerHTML = '<div class="spinner"></div>';
tweetSubmitButton.disabled = true;
try {
await createTweet(content);
} catch (error) {
console.error("Error sending tweet:", error);
} finally {
// Restore the original button text
tweetSubmitButton.innerHTML = "Tweet";
tweetSubmitButton.disabled = false;
}
});

abi.json

just like a IKEA instruction manual to check the information when you get lost



[Reference]

  1. code sandbox
  2. Ultimate Solidity Smart Contract Course - For Complete Beginners
  3. Wallet connection from Metamask document
  4. web3.ethContract
留言
avatar-img
留言分享你的想法!
avatar-img
Follow the Rainmaker 🌧️
5會員
91內容數
尋大神腳印, 亦步亦趨。
2024/06/12
0. 大綱Outline 以太坊交易 發起交易 與智能合約互動 receive & fallback function 1. 舊以太坊交易 Ethereum Gas Tracker - 7 Gwei - Etherscan //交易技術, 表示特定帳戶的交易數量,是計數器, 每發一筆交
2024/06/12
0. 大綱Outline 以太坊交易 發起交易 與智能合約互動 receive & fallback function 1. 舊以太坊交易 Ethereum Gas Tracker - 7 Gwei - Etherscan //交易技術, 表示特定帳戶的交易數量,是計數器, 每發一筆交
2024/05/28
在 Solidity 中,constant 變量用於定義不可變的常數值。這些常數在合約的生命週期內不會改變,並且它們的值必須在宣告時設定。使用 constant 關鍵字可以節省 gas,因為它們在編譯時就已經被嵌入到字節碼中,不需要在運行時讀取存儲。 用法 定義常數: 常數變量必須在宣告時初始
2024/05/28
在 Solidity 中,constant 變量用於定義不可變的常數值。這些常數在合約的生命週期內不會改變,並且它們的值必須在宣告時設定。使用 constant 關鍵字可以節省 gas,因為它們在編譯時就已經被嵌入到字節碼中,不需要在運行時讀取存儲。 用法 定義常數: 常數變量必須在宣告時初始
2024/05/27
msg.sender 定義:msg.sender 是 Solidity 中的一個全局變量,表示當前調用合約函數的外部地址。這個地址可以是普通用戶賬戶(EOA)或另一個智能合約。 用途:用於識別誰在調用當前函數。在每次函數調用期間,msg.sender 都會動態地更新為當前調用該函數的賬戶地址。
2024/05/27
msg.sender 定義:msg.sender 是 Solidity 中的一個全局變量,表示當前調用合約函數的外部地址。這個地址可以是普通用戶賬戶(EOA)或另一個智能合約。 用途:用於識別誰在調用當前函數。在每次函數調用期間,msg.sender 都會動態地更新為當前調用該函數的賬戶地址。
看更多
你可能也想看
Thumbnail
還在煩惱平凡日常該如何增添一點小驚喜嗎?全家便利商店這次聯手超萌的馬來貘,推出黑白配色的馬來貘雪糕,不僅外觀吸睛,層次豐富的雙層口味更是讓人一口接一口!本文將帶你探索馬來貘雪糕的多種創意吃法,從簡單的豆漿燕麥碗、藍莓果昔,到大人系的奇亞籽布丁下午茶,讓可愛的馬來貘陪你度過每一餐,增添生活中的小確幸!
Thumbnail
還在煩惱平凡日常該如何增添一點小驚喜嗎?全家便利商店這次聯手超萌的馬來貘,推出黑白配色的馬來貘雪糕,不僅外觀吸睛,層次豐富的雙層口味更是讓人一口接一口!本文將帶你探索馬來貘雪糕的多種創意吃法,從簡單的豆漿燕麥碗、藍莓果昔,到大人系的奇亞籽布丁下午茶,讓可愛的馬來貘陪你度過每一餐,增添生活中的小確幸!
Thumbnail
本文指导如何添加自定义公链,介绍两种方法:通过 Chainlist 添加和手动设置,支持添加多种公链节点,包括以太坊、币安智能链、火币生态链等,方便用户在浏览器中使用自定义公链。 🚀 币安 - 全球最大加密货币交易所 💥 独家优惠 💥 💰 注册即享 20% 手续费返佣 🔑 专属邀请码
Thumbnail
本文指导如何添加自定义公链,介绍两种方法:通过 Chainlist 添加和手动设置,支持添加多种公链节点,包括以太坊、币安智能链、火币生态链等,方便用户在浏览器中使用自定义公链。 🚀 币安 - 全球最大加密货币交易所 💥 独家优惠 💥 💰 注册即享 20% 手续费返佣 🔑 专属邀请码
Thumbnail
Web3钱包是一种数字货币钱包,专为与Web3.0技术和去中心化应用(DApps)集成而设计,Web3.0是指下一代互联网技术,它着重于去中心化、区块链和加密货币等技术的应用,那么,Web3钱包是什么呢?Web3钱包安全吗?下面,我们一起来看看 🚀 币安 - 全球最大加密货币交易所 💥 独家
Thumbnail
Web3钱包是一种数字货币钱包,专为与Web3.0技术和去中心化应用(DApps)集成而设计,Web3.0是指下一代互联网技术,它着重于去中心化、区块链和加密货币等技术的应用,那么,Web3钱包是什么呢?Web3钱包安全吗?下面,我们一起来看看 🚀 币安 - 全球最大加密货币交易所 💥 独家
Thumbnail
比特幣區塊鏈為了滿足各種不同的需求與技術,目前衍生出四種不同型態的地址形式,主要是針對安全性、靈活性與新版本兼容性的改革。
Thumbnail
比特幣區塊鏈為了滿足各種不同的需求與技術,目前衍生出四種不同型態的地址形式,主要是針對安全性、靈活性與新版本兼容性的改革。
Thumbnail
Launchpad指的是透過交易所或鏈上發行平台指定的代幣,優先申購新的代幣發行ICO(Initial Coin Offering,貨幣首次募資或販售)、IEO(Initial Exchange Offerings,首次交易發行)專案。
Thumbnail
Launchpad指的是透過交易所或鏈上發行平台指定的代幣,優先申購新的代幣發行ICO(Initial Coin Offering,貨幣首次募資或販售)、IEO(Initial Exchange Offerings,首次交易發行)專案。
Thumbnail
今天談到的 DAO、Web3、DID、加密貨幣錢包⋯⋯都根源於區塊鏈技術。
Thumbnail
今天談到的 DAO、Web3、DID、加密貨幣錢包⋯⋯都根源於區塊鏈技術。
Thumbnail
介紹: DOP 是一種區塊鏈隱私協議,在以太坊上運行,使用戶能夠精確管理他們希望分享的資訊(資產持有、交易信息等),主打『您的數據,您的選擇』 項目無融資資料,但推特有大佬追蹤,Kevin Susanto、nftguyy和哥吉拉聯合創辦人shan
Thumbnail
介紹: DOP 是一種區塊鏈隱私協議,在以太坊上運行,使用戶能夠精確管理他們希望分享的資訊(資產持有、交易信息等),主打『您的數據,您的選擇』 項目無融資資料,但推特有大佬追蹤,Kevin Susanto、nftguyy和哥吉拉聯合創辦人shan
Thumbnail
Mode network 模块化L2 明牌5.5%=550,000,000空投 参与链接https://ref.mode.network/crJzsn邀请码crJzsn 链接钱包验证推特就有基础分,跨链小额即可激活账户 详情 https://mode.network/about-the-airdro
Thumbnail
Mode network 模块化L2 明牌5.5%=550,000,000空投 参与链接https://ref.mode.network/crJzsn邀请码crJzsn 链接钱包验证推特就有基础分,跨链小额即可激活账户 详情 https://mode.network/about-the-airdro
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News