Lance una colección de NFTs
62636 ワード
Lance una colección de 66 NFTs para los que estuvieron desde el inicio formando parte de la comunidad de Filosofía Código.サイトはグスタド エル コンテニド デル カナール y quieres contribuir de una manera diferente, te invito a que mintees uno en og.filosofiacodigo.com .ポリゴンとキュースタン 4 マティックを赤くします. Quienes minteen tendan trato especial en los futuros proyectos que cree a través del canal.グラシアス!
En este video explico como creé este token y el botón de mint con ayuda unicamente de Remix y Javascript. Normalmente uso Truffle o Hardhat pero quize hacerlo diferente esta vez para demostrar que hay varios caminos para hacer realidad nuestros proyectos.
Para realizar este tutorial ocupas la billetera Metamask que la puedes conseguir como una extension de tu navegador. Adicionalmente necesitaras Fondos de Rinke作成者: Testnet que puedes conseguir desde el Faucet . Para hacer el ultimo paso en este video también ocuparás NodeJs que les recomomiendo descargarlo el Linux via NVM .
Colocamos los siguientes 2 archivos en un servidor web público. Adicionalmente colocamos un tercer archivo llamado
プリメロ インスタラ ライト サーバー
¡Gracias por ver este tutorial!
Sígueme en dev.to y en para todo lo relacionado al desarrollo en Blockchain en Español.
En este video explico como creé este token y el botón de mint con ayuda unicamente de Remix y Javascript. Normalmente uso Truffle o Hardhat pero quize hacerlo diferente esta vez para demostrar que hay varios caminos para hacer realidad nuestros proyectos.
アンテ・デ・エンペザール
Para realizar este tutorial ocupas la billetera Metamask que la puedes conseguir como una extension de tu navegador. Adicionalmente necesitaras Fondos de Rinke作成者: Testnet que puedes conseguir desde el Faucet . Para hacer el ultimo paso en este video también ocuparás NodeJs que les recomomiendo descargarlo el Linux via NVM .
1. ランザモス エル スマート コントラクト
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyNFT is ERC721, ERC721Enumerable, Ownable {
enum Color {Black, White, Purple, Cyan, Yellow, Orange}
uint public SUPPLY;
uint public MAX_SUPPLY = 66;
uint public PRICE = 4 ether;
mapping (uint=>Color) public token_color;
mapping (Color=>string) public color_uri;
constructor() ERC721("OG Filosofia Codigo", "OGFC") {}
function tokenURI(uint256 token_id) public view virtual override returns (string memory) {
require(_exists(token_id), "ERC721Metadata: URI query for nonexistent token");
return color_uri[token_color[token_id]];
}
function setTokenURIs(string[] memory uris) public onlyOwner
{
color_uri[Color.Black] = uris[0];
color_uri[Color.White] = uris[1];
color_uri[Color.Purple] = uris[2];
color_uri[Color.Cyan] = uris[3];
color_uri[Color.Yellow] = uris[4];
color_uri[Color.Orange] = uris[5];
}
function setTokenColor(uint token_id, Color color) public
{
require(msg.sender == ownerOf(token_id), "Must be token owner.");
token_color[token_id] = color;
}
function mint() public payable
{
require(msg.value >= PRICE, "Must pay price.");
require(SUPPLY < MAX_SUPPLY, "Max supply must not be reached.");
_mint(msg.sender, SUPPLY);
SUPPLY += 1;
}
function withdraw() public
{
(bool sent, bytes memory data) = address(owner()).call{value: address(this).balance}("");
require(sent, "Failed to send Ether");
data;
}
function setPrice(uint _price) public onlyOwner
{
PRICE = _price;
}
function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool)
{
return super.supportsInterface(interfaceId);
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override(ERC721, ERC721Enumerable)
{
super._beforeTokenTransfer(from, to, tokenId);
}
}
ボトン・デ・ミント
Colocamos los siguientes 2 archivos en un servidor web público. Adicionalmente colocamos un tercer archivo llamado
ContractABI.json
que contiene el ABI del contrato generado por Remix.index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Ejemplo</title>
</head>
<body>
<h1 class="title">
Token Ejemplo
</h1>
<p class="subtitle">
Para quienes formaron parte <strong>desde el inicio</strong>
</p>
<button onclick="mint()" class="button is-primary">mintea!</button><br>
<p id="web3_message"></p>
<p id="available_message"></p>
<br>
<br>
<h2 class="subtitle">Mintea tokens y elige tu color favorito</h2>
<div id="color_selectors" class="columns is-desktop"></div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/web3/1.3.5/web3.min.js"></script>
<script type="text/javascript" src="blockchain_stuff.js"></script>
</body>
</html>
blockchain_stuff.js
const NETWORK_ID = 4
const CONTRACT_ADDRESS = "0xD9BcFd43E6BA76b1468D0a66325C0c06D6DACf33"
const JSON_CONTRACT_ABI_PATH = "./ContractABI.json"
var contract
var accounts
var web3
var balance
var SUPPLY
var MAX_SUPPLY
var nft_ids = []
var token_colors = []
var PRICE
function metamaskReloadCallback()
{
window.ethereum.on('accountsChanged', (accounts) => {
document.getElementById("web3_message").textContent="Se cambió el account, refrescando...";
window.location.reload()
})
window.ethereum.on('networkChanged', (accounts) => {
document.getElementById("web3_message").textContent="Se el network, refrescando...";
window.location.reload()
})
}
const getWeb3 = async () => {
return new Promise((resolve, reject) => {
if(document.readyState=="complete")
{
if (window.ethereum) {
const web3 = new Web3(window.ethereum)
window.location.reload()
resolve(web3)
} else {
reject("must install MetaMask")
document.getElementById("web3_message").textContent="Error: Porfavor conéctate a Metamask";
}
}else
{
window.addEventListener("load", async () => {
if (window.ethereum) {
const web3 = new Web3(window.ethereum)
resolve(web3)
} else {
reject("must install MetaMask")
document.getElementById("web3_message").textContent="Error: Please install Metamask";
}
});
}
});
};
const getContract = async (web3) => {
const response = await fetch(JSON_CONTRACT_ABI_PATH);
const data = await response.json();
const netId = await web3.eth.net.getId();
contract = new web3.eth.Contract(
data,
CONTRACT_ADDRESS
);
return contract
}
async function loadDapp() {
metamaskReloadCallback()
document.getElementById("web3_message").textContent="Por favor conéctate a Metamask"
var awaitWeb3 = async function () {
web3 = await getWeb3()
web3.eth.net.getId((err, netId) => {
if (netId == NETWORK_ID) {
var awaitContract = async function () {
contract = await getContract(web3);
await window.ethereum.request({ method: "eth_requestAccounts" })
accounts = await web3.eth.getAccounts()
balance = await contract.methods.balanceOf(accounts[0]).call()
MAX_SUPPLY = await contract.methods.MAX_SUPPLY().call()
SUPPLY = await contract.methods.SUPPLY().call()
PRICE = await contract.methods.PRICE().call()
for(i=0; i<balance; i++)
{
nft_ids.push(await contract.methods.tokenOfOwnerByIndex(accounts[0],i).call())
}
console.log(nft_ids)
for(i=0; i<nft_ids.length; i++)
{
token_color = await contract.methods.token_color(nft_ids[i]).call()
token_colors.push(token_color)
addColorSelector(token_color, nft_ids[i])
}
console.log(token_colors)
if(balance == 1)
document.getElementById("web3_message").textContent="Tienes 1 token"
else
document.getElementById("web3_message").textContent="Tienes " + balance + " tokens"
document.getElementById("available_message").textContent="" + (MAX_SUPPLY-SUPPLY) + "/" + MAX_SUPPLY + " disponibles (Precio: " + web3.utils.fromWei(PRICE) + " MATIC)"
};
awaitContract();
} else {
document.getElementById("web3_message").textContent="Por favor conectate a Polygon";
}
});
};
awaitWeb3();
}
function getTokenUrl(token_color)
{
if(token_color==0)
return "https://raw.githubusercontent.com/FilosofiaCodigo/OGToken/master/assets/Black.png"
if(token_color==1)
return "https://raw.githubusercontent.com/FilosofiaCodigo/OGToken/master/assets/White.png"
if(token_color==2)
return "https://raw.githubusercontent.com/FilosofiaCodigo/OGToken/master/assets/Purple.png"
if(token_color==3)
return "https://raw.githubusercontent.com/FilosofiaCodigo/OGToken/master/assets/Cyan.png"
if(token_color==4)
return "https://raw.githubusercontent.com/FilosofiaCodigo/OGToken/master/assets/Yellow.png"
if(token_color==5)
return "https://raw.githubusercontent.com/FilosofiaCodigo/OGToken/master/assets/Orange.png"
}
function addColorSelector(token_color, token_id)
{
var parent = document.getElementById("color_selectors");
var column = document.createElement("column");
column.className = "column is-one-quarter-desktop"
var card = document.createElement("div");
card.className = "card"
column.appendChild(card);
parent.appendChild(column);
//Img
var img = document.createElement("img");
var img_field_div = document.createElement("div");
var figure = document.createElement("figure");
img_field_div.className = "card-image"
figure.className = "image is-150by150"
img.src = getTokenUrl(token_color);
img.width = "150"
img_field_div.appendChild(figure);
figure.appendChild(img);
card.appendChild(img_field_div);
//Card content
var card_content = document.createElement("div");
card_content.className = "card-content"
card.appendChild(card_content);
//Title
var title = document.createElement("p");
title.className = "title"
title.innerHTML = "OG Filosofía Código #" + token_id
card_content.appendChild(title);
//Select
var array = ["Black", "White", "Purple", "Cyan", "Yellow", "Orange"];
var field = document.createElement("div");
field.className = "field"
var label = document.createElement("label");
label.className = "label"
label.innerHTML = "Color"
var control = document.createElement("div");
control.className = "control"
var select_div = document.createElement("div");
select_div.className = "select"
var select_list = document.createElement("select");
select_div.appendChild(select_list);
select_list.id = "color_select_" + token_id;
field.appendChild(label);
field.appendChild(control);
control.appendChild(select_div);
card_content.appendChild(field);
for (var i = 0; i < array.length; i++) {
var option = document.createElement("option");
option.value = ""+i;
option.text = array[i];
select_list.appendChild(option);
}
//Button
var btn_field_div = document.createElement("footer");
btn_field_div.className = "card-footer"
var btn = document.createElement("a");
btn.innerHTML = "Cambia el color";
btn.className = "card-footer-item"
btn.onclick = function () {
var color_select_element = document.getElementById("color_select_" + token_id);
var selected_color = color_select_element.options[color_select_element.selectedIndex].value;
setColor(token_id, selected_color)
};
btn_field_div.appendChild(btn);
card.appendChild(btn_field_div);
}
const mint = async () => {
const result = await contract.methods.mint()
.send({ from: accounts[0], gas: 0, value: PRICE })
.on('transactionHash', function(hash){
document.getElementById("web3_message").textContent="Minteando...";
})
.on('receipt', function(receipt){
document.getElementById("web3_message").textContent="Éxito! El minteo se ha completado."; })
.catch((revertReason) => {
console.log("ERROR! Transaction reverted: " + revertReason.receipt.transactionHash)
});
}
const setColor = async (token_id, color) => {
const result = await contract.methods.setTokenColor(token_id, color)
.send({ from: accounts[0], gas: 0, value: 0 })
.on('transactionHash', function(hash){
document.getElementById("web3_message").textContent="Minteando...";
})
.on('receipt', function(receipt){
document.getElementById("web3_message").textContent="Éxito! Has cambiado el color."; })
.catch((revertReason) => {
console.log("ERROR! Transaction reverted: " + revertReason.receipt.transactionHash)
});
}
/*
await setTokenURIs(
["https://raw.githubusercontent.com/FilosofiaCodigo/OGToken/master/assets/Black.json",
"https://raw.githubusercontent.com/FilosofiaCodigo/OGToken/master/assets/White.json",
"https://raw.githubusercontent.com/FilosofiaCodigo/OGToken/master/assets/Purple.json",
"https://raw.githubusercontent.com/FilosofiaCodigo/OGToken/master/assets/Cyan.json",
"https://raw.githubusercontent.com/FilosofiaCodigo/OGToken/master/assets/Yellow.json",
"https://raw.githubusercontent.com/FilosofiaCodigo/OGToken/master/assets/Orange.json"])
*/
const setTokenURIs = async (uris) => {
const result = await contract.methods.setTokenURIs(uris)
.send({ from: accounts[0], gas: 0, value: 0 })
.on('transactionHash', function(hash){
document.getElementById("web3_message").textContent="Estableciendo los URIs...";
})
.on('receipt', function(receipt){
document.getElementById("web3_message").textContent="Éxito! Has cambiado los URIs."; })
.catch((revertReason) => {
console.log("ERROR! Transaction reverted: " + revertReason.receipt.transactionHash)
});
}
loadDapp()
3. プロバーロ デ マネラ ローカル
プリメロ インスタラ ライト サーバー
npm i -g lite-server
. Y luego escribe lite-server
en la terminal para iniciar el servidor en http://localhost:3000 .¡Gracias por ver este tutorial!
Sígueme en dev.to y en para todo lo relacionado al desarrollo en Blockchain en Español.
Reference
この問題について(Lance una colección de NFTs), 我々は、より多くの情報をここで見つけました https://dev.to/turupawn/lance-una-coleccion-de-nfts-ik9テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol