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
尋大神腳印, 亦步亦趨。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
1. ERC-20 ERC20 (KryptoCamp) ERC20 (Naz Dumansky) 多簽錢包的設計 - 23:02 🌳 基礎題 1 解答說明: 發行總量100億顆、位數 18 的代幣 - 07:15 🌳 自製 ERC20 交換腦西幣 (HaHow 朱西西) 2. ER
在 Solidity 中,constant 變量用於定義不可變的常數值。這些常數在合約的生命週期內不會改變,並且它們的值必須在宣告時設定。使用 constant 關鍵字可以節省 gas,因為它們在編譯時就已經被嵌入到字節碼中,不需要在運行時讀取存儲。 用法 定義常數: 常數變量必須在宣告時初始
msg.sender 定義:msg.sender 是 Solidity 中的一個全局變量,表示當前調用合約函數的外部地址。這個地址可以是普通用戶賬戶(EOA)或另一個智能合約。 用途:用於識別誰在調用當前函數。在每次函數調用期間,msg.sender 都會動態地更新為當前調用該函數的賬戶地址。
以前覺得程式隔行如隔山, 一直都鴨子聽雷進入自我懷疑回圈, 特別感謝Paul老師, 願意花大量時間鉅細靡遺的介紹, 像解釋文言文一般, 悉心的一字一句清晰的解釋成白話文給我們大家, 終於找到了火山登山口的感覺, 繼續加油 🌳 1. mapping(address account => uint2
Build a ERC-721A Smart Contract ERC721A Explained: Cheaper Gas and More Energy Efficient NFT Minting Contract ERC721A Azuki Smart Contract Tutorial
Create an NFT Lootbox for blockchain games or NFT trading card platforms (NBA Topshot clone)
1. ERC-20 ERC20 (KryptoCamp) ERC20 (Naz Dumansky) 多簽錢包的設計 - 23:02 🌳 基礎題 1 解答說明: 發行總量100億顆、位數 18 的代幣 - 07:15 🌳 自製 ERC20 交換腦西幣 (HaHow 朱西西) 2. ER
在 Solidity 中,constant 變量用於定義不可變的常數值。這些常數在合約的生命週期內不會改變,並且它們的值必須在宣告時設定。使用 constant 關鍵字可以節省 gas,因為它們在編譯時就已經被嵌入到字節碼中,不需要在運行時讀取存儲。 用法 定義常數: 常數變量必須在宣告時初始
msg.sender 定義:msg.sender 是 Solidity 中的一個全局變量,表示當前調用合約函數的外部地址。這個地址可以是普通用戶賬戶(EOA)或另一個智能合約。 用途:用於識別誰在調用當前函數。在每次函數調用期間,msg.sender 都會動態地更新為當前調用該函數的賬戶地址。
以前覺得程式隔行如隔山, 一直都鴨子聽雷進入自我懷疑回圈, 特別感謝Paul老師, 願意花大量時間鉅細靡遺的介紹, 像解釋文言文一般, 悉心的一字一句清晰的解釋成白話文給我們大家, 終於找到了火山登山口的感覺, 繼續加油 🌳 1. mapping(address account => uint2
Build a ERC-721A Smart Contract ERC721A Explained: Cheaper Gas and More Energy Efficient NFT Minting Contract ERC721A Azuki Smart Contract Tutorial
Create an NFT Lootbox for blockchain games or NFT trading card platforms (NBA Topshot clone)
你可能也想看
Google News 追蹤
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
比特幣區塊鏈為了滿足各種不同的需求與技術,目前衍生出四種不同型態的地址形式,主要是針對安全性、靈活性與新版本兼容性的改革。
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
比特幣區塊鏈為了滿足各種不同的需求與技術,目前衍生出四種不同型態的地址形式,主要是針對安全性、靈活性與新版本兼容性的改革。