Mi Primera WebApp en Web3
JSDay Canarias 2022 - Antonio Sejas
Mi Primera DApp
JSDay Canarias 2022 - Antonio Sejas
Sobre mi
Software Engineer
Antonio Sejas






Objetivo del taller
Objetivo del taller

Objetivo del taller


Ante el inminente derrumbe de twitter, tras su adquisición por parte de Elon Musk.
Os propongo que hagamos un "Clon" de Twitter basado en Blockchain.
Objetivo del taller


Ante el inminente derrumbe de twitter, tras su adquisición por parte de Elon Musk.
Os propongo que hagamos un "Clon" de Twitter basado en Blockchain.
Canary DApp
Objetivo del taller




Índice
- Requisitos
- WEB 3.0
- Desarrollo de la DApp en React (Front)
- Desplegar nuestro SmartContract (Back)
- Siguientes pasos
Índice
1
Requisitos
2
WEB 3
3
Smart Contract (Back)
5
Conclusiones
4
DApp en React (Front)
Requisitos
-
Front
-
Node*
- v16.14.1 (npm v8.5.0)
- VSCode + Solidity extension
- Metamask Chrome extension*
-
Node*
-
Back
- Alchemy*
- Hardhat
Web 3.0
¿Qué es la WEB 3.0?

¿Qué es la WEB 3.0?
Disclaimer
This is not a financial advice
¿Qué es la WEB 3.0?


¿Qué es la WEB 3.0?
Satoshi Nakamoto introduce en el primer bloque minado de bitcoin el titular del periódico ‘The Times’ del 3 de enero de 2009. Es una prueba sobre la fecha de creación de este bloque.
“El Canciller (británico) está considerando el segundo rescate a los bancos”

Blockchain
Cadena de bloques

Blockchain

Minado de transacciones
Blockchain
Minado de transacciones

Wallet
- Combinación e clave pública privada. PKI
- Muy similar a nuestro DNIe
- Nos autentica.
Minar
- Confirma transacciones
- Recompensas
Blockchain
Mecanismos de consenso

Smartcontracts
Blockchains



Smartcontracts
Ethereum

Nosotros desplegaremos en la testnet Rinkeby
Smartcontracts

EVM
Smartcontracts
Solidity
pragma solidity ^0.8.13;
contract HelloWorld {
string public message;
constructor(string memory initMessage) {
message = initMessage;
}
function update(string memory newMessage) public {
message = newMessage;
}
}
Smartcontracts
Inspeccionando en etherscan

Demo

Tokens
ERC-20
ERC, Ethereum Request for Comments.
Medio de pago.
Gobernanza de DAOs, decentralized autonomous organization.
Non-fungible tokens (NFT)
ERC-721
Asset digital identificable de forma inequívoca
Coleccionable
Certificado de "propiedad"
Tarjeta de fidelidad, pertenencia a un club/comunidad
Non-fungible tokens (NFT)

Non-fungible tokens (NFT)

Non-fungible tokens (NFT)





Dapps

JSON-RPC API
Dapps
Dapps

Deploy del Smartcontract
Deploy del Smartcontract
Deploy del Smartcontract
Deploy del Smartcontract
❯ CONTRACT_NAME=Canary npx hardhat run scripts/deploy.js --network rinkeby
Compiled 4 Solidity files successfully
Deploying contracts with account: 0xeA39B449Ea509b0957c0F23fa0703a800DbA1bfB
Account balance: 100000000000000000
Contract address: 0xd44aBFB64B98C13a69839BFF433814446726703ADeploy del Smartcontract
// npx hardhat node
// CONTRACT_NAME=Counter npx hardhat run scripts/deploy.js --network localhost
const main = async (contractName) => {
const [deployer] = await hre.ethers.getSigners();
const accountBalance = await deployer.getBalance();
console.log("Deploying contracts with account: ", deployer.address);
console.log("Account balance: ", accountBalance.toString());
const contractFactory = await hre.ethers.getContractFactory(contractName);
const contract = await contractFactory.deploy();
await contract.deployed();
console.log("Contract address: ", contract.address);
};
const runMain = async (contractName) => {
try {
await main(contractName);
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
const contractName = process.env.CONTRACT_NAME || "Counter";
runMain(contractName);
deploy.js
Deploy del Smartcontract
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "hardhat/console.sol";
contract Counter {
uint256 total;
constructor() {
console.log("Couner initialized");
}
function add() public {
total += 1;
console.log("%s has added 1 the new total is %s", msg.sender, total);
}
function getTotal() public view returns (uint256) {
console.log("The total is %d!", total);
return total;
}
}
Counter.sol
Deploy del Smartcontract
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.13;
contract Canary {
event AddTweet(address recipient, uint256 tweetId);
event DeleteTweet(uint256 tweetId, bool isDeleted);
event LikedTweet(address enthusiast, uint256 tweetId);
struct Tweet {
uint256 id;
address owner;
string tweetText;
bool isDeleted;
uint32 likes;
uint256 timestamp;
}
Tweet[] private tweets;
// Mapping of Tweet id to the wallet address of the user
mapping(uint256 => address) tweetToOwner;
// mapping(uint256 => address[]) tweetToLikes;
mapping(address => uint256[]) addressToTweetsLiked;
// Method to be called by our frontend when trying to add a new Tweet
function addTweet(string memory tweetText) external {
uint256 tweetId = tweets.length;
tweets.push(
Tweet(tweetId, msg.sender, tweetText, false, 0, block.timestamp)
);
tweetToOwner[tweetId] = msg.sender;
emit AddTweet(msg.sender, tweetId);
}
// Method to get one single Tweet
function getTweet(uint256 tweetId) external view returns (Tweet memory) {
return tweets[tweetId];
}
// Method to get all the Tweets
function getAllTweets() external view returns (Tweet[] memory) {
Tweet[] memory temporary = new Tweet[](tweets.length);
uint256 counter = 0;
for (uint256 i = 0; i < tweets.length; i++) {
if (tweets[i].isDeleted == false) {
temporary[counter] = tweets[i];
counter++;
}
}
Tweet[] memory result = new Tweet[](counter);
for (uint256 i = 0; i < counter; i++) {
result[i] = temporary[i];
}
return result;
}
// Method to get only your Tweets
function getMyTweets() external view returns (Tweet[] memory) {
Tweet[] memory temporary = new Tweet[](tweets.length);
uint256 counter = 0;
for (uint256 i = 0; i < tweets.length; i++) {
if (tweetToOwner[i] == msg.sender && tweets[i].isDeleted == false) {
temporary[counter] = tweets[i];
counter++;
}
}
Tweet[] memory result = new Tweet[](counter);
for (uint256 i = 0; i < counter; i++) {
result[i] = temporary[i];
}
return result;
}
// Method to get only your Tweets
function getMyLikes() external view returns (Tweet[] memory) {
uint256[] memory tweetsLiked = addressToTweetsLiked[msg.sender];
Tweet[] memory result = new Tweet[](tweetsLiked.length);
uint256 counter = 0;
for (uint256 i = 0; i < tweetsLiked.length; i++) {
result[counter] = tweets[tweetsLiked[i]];
counter++;
}
return result;
}
// Like tweet
function likeTweet(uint256 tweetId) external {
uint256[] memory tweetsLiked = addressToTweetsLiked[msg.sender];
for (uint256 i = 0; i < tweetsLiked.length; i++) {
if (tweetsLiked[i] == tweetId) {
revert("You have already liked this tweet");
}
}
tweets[tweetId].likes = tweets[tweetId].likes + 1;
// tweetToLikes[tweetId].push(msg.sender);
addressToTweetsLiked[msg.sender].push(tweetId);
emit LikedTweet(msg.sender, tweetId);
}
// Method to Delete a Tweet
function deleteTweet(uint256 tweetId, bool isDeleted) external {
if (tweetToOwner[tweetId] == msg.sender) {
tweets[tweetId].isDeleted = isDeleted;
emit DeleteTweet(tweetId, isDeleted);
}
}
}
Canary.sol
DApp en React
DApp en React
DApp en React
DApp en React
Extra:
- Enseñar la red actual junto a la cuenta
- Añadir pestañas para mostrar mis likes
- Modificar el smart contract para poder añadir pestaña para mostrar mis tweets borrados y sacarlos de la papelera.
- Además de Likes, permitir Donaciones
DApp en React
import { useEffect, useState } from 'react';
const VALID_CHAIN_ID = '0x4'; // Rinkeby
export function useAccount(ethereum) {
const [currentAccount, setCurrentAccount] = useState('');
const [chainId, setChainId] = useState(null);
useEffect(() => {
if (!ethereum) {
return;
}
function listenAccount (accounts) {
console.log('accounts', accounts);
if (accounts.length > 0) {
setCurrentAccount(accounts[0]);
} else {
setCurrentAccount('');
}
}
function listenChain(chainId) {
// https://chainlist.org/
setChainId(chainId);
}
ethereum.on('accountsChanged', listenAccount);
ethereum.on('chainChanged', listenChain);
return () => {
ethereum.removeListener('accountsChanged', listenAccount);
ethereum.removeListener('chainChanged', listenChain);
};
}, [ethereum]);
return {currentAccount, chainId, setCurrentAccount, setChainId, isValidChain: chainId === VALID_CHAIN_ID};
}DApp en React
import { ethers } from 'ethers';
import { useEffect, useState } from 'react';
import ContractJson from '../utils/Canary.json';
const CanaryDetails = {
CONTRACT_ADDRESS: '0xd44aBFB64B98C13a69839BFF433814446726703A',
CONTRACT_ABI: ContractJson.abi,
};
export function useContract(ethereum, isValidChain) {
const [contract, setContract] = useState(null);
useEffect(() => {
if (!ethereum || !isValidChain || contract) {
return;
}
// We initialize the contract with the provider and the ABI only once
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const newContract = new ethers.Contract(CanaryDetails.CONTRACT_ADDRESS, CanaryDetails.CONTRACT_ABI, signer);
setContract(newContract);
}, [ethereum, contract, isValidChain]);
return contract;
}Conclusiones
Conclusiones
El blockchain es un ecosistema de DApps, DAOS
Que busca evitar la manipulación respetando la privacidad del usuario y la descentralización. Surge como respuesta a la crisis del 2008.
Los gobiernos están creando sus propias cryptomonedas oficiales.
IPFS para desplegar Actualización de Smart Contracts ¿Son inmutables?
La tecnología está para quedarse
Web3
By sejas
Web3
Taller mi primera aplicación web3 + React. JSDay Canarias 2022
- 285


