<100 subscribers
Share Dialog
Share Dialog
เมื่อไม่นานมานี้โปรเจค Alchemy ได้เข้าสู่ web3 ด้วยมูลค่า 10.2 พันล้านดอลลาร์ และได้รับการระดมทุน 545 ล้านดอลลาร์.
Alchemy คือโปรเจคอะไร?
Alchemy คือแพลตฟอร์มสำหรับนักพัฒนา dApp บน web3. เป็นรากฐานที่อยู่เบื้องหลังตลาด NFT ยอดนิยมอย่าง OpenSea, Nifty และคอลเล็กชั่นระดับโลกที่สำคัญมากมาย.
12/2019, Alchemy เสร็จสิ้นการจัดหาเงินทุน Series A มูลค่า 15 ล้านดอลลาร์จาก Pantera Capital, Stanford University, Coinbase, Samsung,…
4/2021, Alchemy ได้เสร็จสิ้นการจัดหาเงินทุน Series B มูลค่า 80 ล้านดอลลาร์ โดยมีมูลค่า 505 ล้านดอลลาร์ นำโดย Coatue and Addition โดยมีส่วนร่วมจาก DFJ Growth, K5 Global, Chainsmokers, นักแสดง Jared Leto และครอบครัว Glazer.
10/2021, Alchemy ได้เสร็จสิ้นการจัดหาเงินทุน Series C มูลค่า 250 ล้านดอลลาร์ โดยมีมูลค่า 3.5 พันล้านดอลลาร์ นำโดย a16z.
2/2022, Alchemy ได้เสร็จสิ้นการจัดหาเงินทุน 200 ล้านดอลลาร์โดยมีมูลค่า 10.2 พันล้านดอลลาร์ซึ่งนำโดย Lightspeed และ Silver Lake.
Alchemy เป็นทีมที่มีพื้นฐานที่แข็งแกร่ง, เงินทุนที่เพียงพอ, ทำงานจริง, และยังไม่ได้ออก token.
และ Alchemy วางแผนที่จะใช้เงินทุนใหม่นี้เพื่อกระตุ้นการใช้งาน Web3, บางส่วนรวมถึงการเปิดตัว Web3 University, ซึ่งปัจจุบันเป็นงาน Road to Web3 เป็นเวลา 10 สัปดาห์ด้วยหนึ่ง NFT ต่อสัปดาห์. ผมเห็นว่าจำนวน nfts ที่มิ้นออกมานั้นน้อยมาก คาดว่าเนื่องจากความยากของงาน คนจำนวนมากจึงยอมแพ้ที่จะเข้าร่วม, หากโปรเจคนี้มี Airdrop ส่วนตัวผมมองว่าน่าจะได้เยอะอย่างแน่นอน.
1. ไปที่ Alchemy, สมัคร หรือลงชื่อให้เรียบร้อย, ที่หน้า dashboard กด create app.

จากนั้นตั้งค่าดังตามภาพด้านล่าง, แล้วคลิก create app.

คลิกปุ่ม view key.

คัดลอก url ของ HTTPS ไว้.

1. ขอ Goerli ETH โดยใช้ Goerli faucet, หลังจากนี้คุณจะต้องใช้ Goerli ETH เพื่อปรับใช้สัญญาอัจฉริยะและอัปโหลด NFT ไปยัง NFT Marketplace ของคุณ.

2. เพิ่ม Goerli chain ใน Metamask โดย RPC URL คือลิงค์ที่เราได้มาจาก step 1 จากนั้นกด save ให้เรียบร้อย.


1. เพื่อความสะดวก, Alchemy ได้อัปโหลด code base ไปยังที่เก็บ GitHub, โค้ดนี้มีการเขียนส่วนหน้าทั้งหมด. แต่ยังไม่มีสัญญาอัจฉริยะ หรือการผสานรวมกับส่วนหน้า. ในการโคลนที่เก็บ, ให้รันคำสั่งต่อไปนี้ในคอนโซลทีละขั้นตอน:
git clone https://github.com/alchemyplatform/RTW3-Week7-NFT-Marketplace.git
cd RTW3-Week7-NFT-Marketplace
npm install
npm start



2. หลังจากรันคำสั่งสี่คำสั่งข้างต้นแล้ว, มันจะกระโดดมาที่หน้าเว็บด้านล่างนี้.

1. เปิด vscode, ค้นหาโฟลเดอร์ที่คุณเพิ่งสร้าง, แล้วคลิกเพื่อเลือกโฟลเดอร์. (เลือก RTW3-Week7 ในรูปวงผิด)

2. เปิดคอนโซลอื่น cd ลงในโฟลเดอร์ RTW3-Week7-NFT-Marketplace และป้อน echo test>.env เพื่อสร้างไฟล์ .env.

3. กลับไปที่ vscode คุณจะเห็นไฟล์ env วางโค้ดต่อไปนี้ลงไป:
REACT_APP_ALCHEMY_API_URL="<YOUR_API_URL>" (วาง HTTPS ที่ได้จาก step1)
REACT_APP_PRIVATE_KEY="<YOUR_PRIVATE_KEY>" (วาง private key ของคุณ)
4. ป้อน npm install dotenv --save ในคอนโซล.

5. ตรวจสอบให้แน่ใจว่าได้เพิ่มโค้ดต่อไปนี้ในไฟล์ hardhat.config.js ของคุณ: (อันที่จริงเปลี่ยนแค่โค้ดสองบรรทัดที่เกี่ยวข้องกับ env).
require("@nomiclabs/hardhat-waffle");
require("@nomiclabs/hardhat-ethers");
const fs = require('fs');
// const infuraId = fs.readFileSync(".infuraid").toString().trim() || "";
require('dotenv').config();
task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
const accounts = await hre.ethers.getSigners();
for (const account of accounts) {
console.log(account.address);
}
});
module.exports = {
defaultNetwork: "hardhat",
networks: {
hardhat: {
chainId: 1337
},
goerli: {
url: process.env.REACT_APP_ALCHEMY_API_URL,
accounts: [ process.env.REACT_APP_PRIVATE_KEY ]
}
},
solidity: {
version: "0.8.4",
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
}
};

1. เข้าไปที่ pinata, เลือกปุ่ม "new key" จากนั้นตั้งค่าตามที่แสดงในรูปภาพด้านล่าง, แล้วคลิก create key.


2. จากนั้นคุณจะเห็นป๊อปอัปพร้อมข้อมูล API ของคุณ, ให้คัดลอกไปยังที่ปลอดภัย.

3. กลับไปที่ vscode คลิกที่ไฟล์ .env และเพิ่มโค้ดต่อไปนี้.
REACT_APP_PINATA_KEY="<YOUR_PINATA_KEY>" (เอาข้อมูลจาก step5 ข้อ2 มาวาง)
REACT_APP_PINATA_SECRET="<YOUR_PINATA_SECRET>" (เอาข้อมูลจาก step5 ข้อ2 มาวาง)
1. ค้นหาไฟล์ NFTMarketplace.sol ในโฟลเดอร์ contracts ใน vscode แทนที่โค้ดเก่าด้วยโค้ดด้านล่างแล้วบันทึก. ในเว็บหลักมีคำอธิบายในแต่ละขั้นตอนให้เข้าใจได้.

1. ใน vscode, หาไฟล์ชื่อ deploy.js ในโฟลเดอร์ scripts วางโค้ดต่อไปนี้แล้วบันทึก.
const { ethers } = require("hardhat");
const hre = require("hardhat");
const fs = require("fs");
async function main() {
//get the signer that we will use to deploy
const [deployer] = await ethers.getSigners();
//Get the NFTMarketplace smart contract object and deploy it
const Marketplace = await hre.ethers.getContractFactory("NFTMarketplace");
const marketplace = await Marketplace.deploy();
await marketplace.deployed();
//Pull the address and ABI out while you deploy, since that will be key in interacting with the smart contract later
const data = {
address: marketplace.address,
abi: JSON.parse(marketplace.interface.format('json'))
}
//This writes the ABI and address to the marketplace.json
//This data is then used by frontend files to connect with the smart contract
fs.writeFileSync('./src/Marketplace.json', JSON.stringify(data))
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
2. จากนั้นเปิดคอนโซลและรันคำสั่งต่อไปนี้: npx hardhat run --network goerli scripts/deploy.js

1. ในโฟลเดอร์ src ให้วางโค้ดด้านล่างในไฟล์ชื่อ pinata.js แล้วบันทึก.
//require('dotenv').config();
const key = process.env.REACT_APP_PINATA_KEY;
const secret = process.env.REACT_APP_PINATA_SECRET;
const axios = require('axios');
const FormData = require('form-data');
export const uploadJSONToIPFS = async(JSONBody) => {
const url = `https://api.pinata.cloud/pinning/pinJSONToIPFS`;
//making axios POST request to Pinata ⬇️
return axios
.post(url, JSONBody, {
headers: {
pinata_api_key: key,
pinata_secret_api_key: secret,
}
})
.then(function (response) {
return {
success: true,
pinataURL: "https://gateway.pinata.cloud/ipfs/" + response.data.IpfsHash
};
})
.catch(function (error) {
console.log(error)
return {
success: false,
message: error.message,
}
});
};
export const uploadFileToIPFS = async(file) => {
const url = `https://api.pinata.cloud/pinning/pinFileToIPFS`;
//making axios POST request to Pinata ⬇️
let data = new FormData();
data.append('file', file);
const metadata = JSON.stringify({
name: 'testname',
keyvalues: {
exampleKey: 'exampleValue'
}
});
data.append('pinataMetadata', metadata);
//pinataOptions are optional
const pinataOptions = JSON.stringify({
cidVersion: 0,
customPinPolicy: {
regions: [
{
id: 'FRA1',
desiredReplicationCount: 1
},
{
id: 'NYC1',
desiredReplicationCount: 2
}
]
}
});
data.append('pinataOptions', pinataOptions);
return axios
.post(url, data, {
maxBodyLength: 'Infinity',
headers: {
'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
pinata_api_key: key,
pinata_secret_api_key: secret,
}
})
.then(function (response) {
console.log("image uploaded", response.data.IpfsHash)
return {
success: true,
pinataURL: "https://gateway.pinata.cloud/ipfs/" + response.data.IpfsHash
};
})
.catch(function (error) {
console.log(error)
return {
success: false,
message: error.message,
}
});
};

1. เพิ่มโค้ดต่อไปนี้ใน src/components/SellNFT.js ของคุณ, ดังแสดงในรูปด้านล่าง.

2. วางโค้ดต่อไปนี้ลงใน src/components/Marketplace.js ดังแสดงในรูปด้านล่าง.
import Navbar from "./Navbar";
import NFTTile from "./NFTTile";
import MarketplaceJSON from "../Marketplace.json";
import axios from "axios";
import { useState } from "react";
export default function Marketplace() {
const sampleData = [
{
"name": "NFT#1",
"description": "Alchemy's First NFT",
"website":"http://axieinfinity.io",
"image":"https://gateway.pinata.cloud/ipfs/QmTsRJX7r5gyubjkdmzFrKQhHv74p5wT9LdeF1m3RTqrE5",
"price":"0.03ETH",
"currentlySelling":"True",
"address":"0xe81Bf5A757CB4f7F82a2F23b1e59bE45c33c5b13",
},
{
"name": "NFT#2",
"description": "Alchemy's Second NFT",
"website":"http://axieinfinity.io",
"image":"https://gateway.pinata.cloud/ipfs/QmdhoL9K8my2vi3fej97foiqGmJ389SMs55oC5EdkrxF2M",
"price":"0.03ETH",
"currentlySelling":"True",
"address":"0xe81Bf5A757C4f7F82a2F23b1e59bE45c33c5b13",
},
{
"name": "NFT#3",
"description": "Alchemy's Third NFT",
"website":"http://axieinfinity.io",
"image":"https://gateway.pinata.cloud/ipfs/QmTsRJX7r5gyubjkdmzFrKQhHv74p5wT9LdeF1m3RTqrE5",
"price":"0.03ETH",
"currentlySelling":"True",
"address":"0xe81Bf5A757C4f7F82a2F23b1e59bE45c33c5b13",
},
];
const [data, updateData] = useState(sampleData);
const [dataFetched, updateFetched] = useState(false);
async function getAllNFTs() {
const ethers = require("ethers");
//After adding your Hardhat network to your metamask, this code will get providers and signers
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
//Pull the deployed contract instance
let contract = new ethers.Contract(MarketplaceJSON.address, MarketplaceJSON.abi, signer)
//create an NFT Token
let transaction = await contract.getAllNFTs()
//Fetch all the details of every NFT from the contract and display
const items = await Promise.all(transaction.map(async i => {
const tokenURI = await contract.tokenURI(i.tokenId);
let meta = await axios.get(tokenURI);
meta = meta.data;
let price = ethers.utils.formatUnits(i.price.toString(), 'ether');
let item = {
price,
tokenId: i.tokenId.toNumber(),
seller: i.seller,
owner: i.owner,
image: meta.image,
name: meta.name,
description: meta.description,
}
return item;
}))
updateFetched(true);
updateData(items);
}
if(!dataFetched)
getAllNFTs();
return (
<div>
<Navbar></Navbar>
<div className="flex flex-col place-items-center mt-20">
<div className="md:text-xl font-bold text-white">
Top NFTs
</div>
<div className="flex mt-5 justify-between flex-wrap max-w-screen-xl text-center">
{data.map((value, index) => {
return <NFTTile data={value} key={index}></NFTTile>;
})}
</div>
</div>
</div>
);
}

3. วางโค้ดต่อไปนี้ลงใน src/components/Profile.js ดังแสดงในรูปด้านล่าง.

4. วางโค้ดต่อไปนี้ลงใน src/components/NFTPage.js ดังแสดงในรูปด้านล่าง.

อย่าลืมบันทึก.
1. ป้อน npm start ในคอนโซล, คุณจะเห็นว่าสำเร็จ.


https://docs.google.com/forms/d/e/1FAIpQLSdNNLXMYZmIhjcWoT-UedS3AoGpRiPDRaNARUPGXLbX1TVvSg/viewform
ส่งโดยอัปโหลดลง github หรือ ส่ง url จาก address.

เราสามารถเช็ด nft ที่เรายังไม่ได้เคลมได้นะครับโดยเข้าไปที่ mintkudos จากนั้นต่อกระเป๋ามุมขวามือลองกดเช็ดดูถ้ามีปลุ่ม claim แปลว่าเรามี nft ที่เราสามารถเคลมได้แต่เรายังไม่ได้เคลม.

เท่านี้ก็จบกันไปแล้วนะครับกับ Alchemy Road to web3 week7 ใครมีคำถาม หรือสงสัยยังไงสามารถถามได้. ส่วนใครที่อยากจะสนับสนุนค่ากาแฟให้ผู้เขียนสามารถกดปุ่ม Collect Entry ได้ที่ด้านล่างนี้จากนั้นเราจะได้ nft บทความของ mirror.xyz chain optimism และสามารถเช็ด nft ที่เรา collect มาได้ที่ QxProfile.
collect://
เมื่อไม่นานมานี้โปรเจค Alchemy ได้เข้าสู่ web3 ด้วยมูลค่า 10.2 พันล้านดอลลาร์ และได้รับการระดมทุน 545 ล้านดอลลาร์.
Alchemy คือโปรเจคอะไร?
Alchemy คือแพลตฟอร์มสำหรับนักพัฒนา dApp บน web3. เป็นรากฐานที่อยู่เบื้องหลังตลาด NFT ยอดนิยมอย่าง OpenSea, Nifty และคอลเล็กชั่นระดับโลกที่สำคัญมากมาย.
12/2019, Alchemy เสร็จสิ้นการจัดหาเงินทุน Series A มูลค่า 15 ล้านดอลลาร์จาก Pantera Capital, Stanford University, Coinbase, Samsung,…
4/2021, Alchemy ได้เสร็จสิ้นการจัดหาเงินทุน Series B มูลค่า 80 ล้านดอลลาร์ โดยมีมูลค่า 505 ล้านดอลลาร์ นำโดย Coatue and Addition โดยมีส่วนร่วมจาก DFJ Growth, K5 Global, Chainsmokers, นักแสดง Jared Leto และครอบครัว Glazer.
10/2021, Alchemy ได้เสร็จสิ้นการจัดหาเงินทุน Series C มูลค่า 250 ล้านดอลลาร์ โดยมีมูลค่า 3.5 พันล้านดอลลาร์ นำโดย a16z.
2/2022, Alchemy ได้เสร็จสิ้นการจัดหาเงินทุน 200 ล้านดอลลาร์โดยมีมูลค่า 10.2 พันล้านดอลลาร์ซึ่งนำโดย Lightspeed และ Silver Lake.
Alchemy เป็นทีมที่มีพื้นฐานที่แข็งแกร่ง, เงินทุนที่เพียงพอ, ทำงานจริง, และยังไม่ได้ออก token.
และ Alchemy วางแผนที่จะใช้เงินทุนใหม่นี้เพื่อกระตุ้นการใช้งาน Web3, บางส่วนรวมถึงการเปิดตัว Web3 University, ซึ่งปัจจุบันเป็นงาน Road to Web3 เป็นเวลา 10 สัปดาห์ด้วยหนึ่ง NFT ต่อสัปดาห์. ผมเห็นว่าจำนวน nfts ที่มิ้นออกมานั้นน้อยมาก คาดว่าเนื่องจากความยากของงาน คนจำนวนมากจึงยอมแพ้ที่จะเข้าร่วม, หากโปรเจคนี้มี Airdrop ส่วนตัวผมมองว่าน่าจะได้เยอะอย่างแน่นอน.
1. ไปที่ Alchemy, สมัคร หรือลงชื่อให้เรียบร้อย, ที่หน้า dashboard กด create app.

จากนั้นตั้งค่าดังตามภาพด้านล่าง, แล้วคลิก create app.

คลิกปุ่ม view key.

คัดลอก url ของ HTTPS ไว้.

1. ขอ Goerli ETH โดยใช้ Goerli faucet, หลังจากนี้คุณจะต้องใช้ Goerli ETH เพื่อปรับใช้สัญญาอัจฉริยะและอัปโหลด NFT ไปยัง NFT Marketplace ของคุณ.

2. เพิ่ม Goerli chain ใน Metamask โดย RPC URL คือลิงค์ที่เราได้มาจาก step 1 จากนั้นกด save ให้เรียบร้อย.


1. เพื่อความสะดวก, Alchemy ได้อัปโหลด code base ไปยังที่เก็บ GitHub, โค้ดนี้มีการเขียนส่วนหน้าทั้งหมด. แต่ยังไม่มีสัญญาอัจฉริยะ หรือการผสานรวมกับส่วนหน้า. ในการโคลนที่เก็บ, ให้รันคำสั่งต่อไปนี้ในคอนโซลทีละขั้นตอน:
git clone https://github.com/alchemyplatform/RTW3-Week7-NFT-Marketplace.git
cd RTW3-Week7-NFT-Marketplace
npm install
npm start



2. หลังจากรันคำสั่งสี่คำสั่งข้างต้นแล้ว, มันจะกระโดดมาที่หน้าเว็บด้านล่างนี้.

1. เปิด vscode, ค้นหาโฟลเดอร์ที่คุณเพิ่งสร้าง, แล้วคลิกเพื่อเลือกโฟลเดอร์. (เลือก RTW3-Week7 ในรูปวงผิด)

2. เปิดคอนโซลอื่น cd ลงในโฟลเดอร์ RTW3-Week7-NFT-Marketplace และป้อน echo test>.env เพื่อสร้างไฟล์ .env.

3. กลับไปที่ vscode คุณจะเห็นไฟล์ env วางโค้ดต่อไปนี้ลงไป:
REACT_APP_ALCHEMY_API_URL="<YOUR_API_URL>" (วาง HTTPS ที่ได้จาก step1)
REACT_APP_PRIVATE_KEY="<YOUR_PRIVATE_KEY>" (วาง private key ของคุณ)
4. ป้อน npm install dotenv --save ในคอนโซล.

5. ตรวจสอบให้แน่ใจว่าได้เพิ่มโค้ดต่อไปนี้ในไฟล์ hardhat.config.js ของคุณ: (อันที่จริงเปลี่ยนแค่โค้ดสองบรรทัดที่เกี่ยวข้องกับ env).
require("@nomiclabs/hardhat-waffle");
require("@nomiclabs/hardhat-ethers");
const fs = require('fs');
// const infuraId = fs.readFileSync(".infuraid").toString().trim() || "";
require('dotenv').config();
task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
const accounts = await hre.ethers.getSigners();
for (const account of accounts) {
console.log(account.address);
}
});
module.exports = {
defaultNetwork: "hardhat",
networks: {
hardhat: {
chainId: 1337
},
goerli: {
url: process.env.REACT_APP_ALCHEMY_API_URL,
accounts: [ process.env.REACT_APP_PRIVATE_KEY ]
}
},
solidity: {
version: "0.8.4",
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
}
};

1. เข้าไปที่ pinata, เลือกปุ่ม "new key" จากนั้นตั้งค่าตามที่แสดงในรูปภาพด้านล่าง, แล้วคลิก create key.


2. จากนั้นคุณจะเห็นป๊อปอัปพร้อมข้อมูล API ของคุณ, ให้คัดลอกไปยังที่ปลอดภัย.

3. กลับไปที่ vscode คลิกที่ไฟล์ .env และเพิ่มโค้ดต่อไปนี้.
REACT_APP_PINATA_KEY="<YOUR_PINATA_KEY>" (เอาข้อมูลจาก step5 ข้อ2 มาวาง)
REACT_APP_PINATA_SECRET="<YOUR_PINATA_SECRET>" (เอาข้อมูลจาก step5 ข้อ2 มาวาง)
1. ค้นหาไฟล์ NFTMarketplace.sol ในโฟลเดอร์ contracts ใน vscode แทนที่โค้ดเก่าด้วยโค้ดด้านล่างแล้วบันทึก. ในเว็บหลักมีคำอธิบายในแต่ละขั้นตอนให้เข้าใจได้.

1. ใน vscode, หาไฟล์ชื่อ deploy.js ในโฟลเดอร์ scripts วางโค้ดต่อไปนี้แล้วบันทึก.
const { ethers } = require("hardhat");
const hre = require("hardhat");
const fs = require("fs");
async function main() {
//get the signer that we will use to deploy
const [deployer] = await ethers.getSigners();
//Get the NFTMarketplace smart contract object and deploy it
const Marketplace = await hre.ethers.getContractFactory("NFTMarketplace");
const marketplace = await Marketplace.deploy();
await marketplace.deployed();
//Pull the address and ABI out while you deploy, since that will be key in interacting with the smart contract later
const data = {
address: marketplace.address,
abi: JSON.parse(marketplace.interface.format('json'))
}
//This writes the ABI and address to the marketplace.json
//This data is then used by frontend files to connect with the smart contract
fs.writeFileSync('./src/Marketplace.json', JSON.stringify(data))
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
2. จากนั้นเปิดคอนโซลและรันคำสั่งต่อไปนี้: npx hardhat run --network goerli scripts/deploy.js

1. ในโฟลเดอร์ src ให้วางโค้ดด้านล่างในไฟล์ชื่อ pinata.js แล้วบันทึก.
//require('dotenv').config();
const key = process.env.REACT_APP_PINATA_KEY;
const secret = process.env.REACT_APP_PINATA_SECRET;
const axios = require('axios');
const FormData = require('form-data');
export const uploadJSONToIPFS = async(JSONBody) => {
const url = `https://api.pinata.cloud/pinning/pinJSONToIPFS`;
//making axios POST request to Pinata ⬇️
return axios
.post(url, JSONBody, {
headers: {
pinata_api_key: key,
pinata_secret_api_key: secret,
}
})
.then(function (response) {
return {
success: true,
pinataURL: "https://gateway.pinata.cloud/ipfs/" + response.data.IpfsHash
};
})
.catch(function (error) {
console.log(error)
return {
success: false,
message: error.message,
}
});
};
export const uploadFileToIPFS = async(file) => {
const url = `https://api.pinata.cloud/pinning/pinFileToIPFS`;
//making axios POST request to Pinata ⬇️
let data = new FormData();
data.append('file', file);
const metadata = JSON.stringify({
name: 'testname',
keyvalues: {
exampleKey: 'exampleValue'
}
});
data.append('pinataMetadata', metadata);
//pinataOptions are optional
const pinataOptions = JSON.stringify({
cidVersion: 0,
customPinPolicy: {
regions: [
{
id: 'FRA1',
desiredReplicationCount: 1
},
{
id: 'NYC1',
desiredReplicationCount: 2
}
]
}
});
data.append('pinataOptions', pinataOptions);
return axios
.post(url, data, {
maxBodyLength: 'Infinity',
headers: {
'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
pinata_api_key: key,
pinata_secret_api_key: secret,
}
})
.then(function (response) {
console.log("image uploaded", response.data.IpfsHash)
return {
success: true,
pinataURL: "https://gateway.pinata.cloud/ipfs/" + response.data.IpfsHash
};
})
.catch(function (error) {
console.log(error)
return {
success: false,
message: error.message,
}
});
};

1. เพิ่มโค้ดต่อไปนี้ใน src/components/SellNFT.js ของคุณ, ดังแสดงในรูปด้านล่าง.

2. วางโค้ดต่อไปนี้ลงใน src/components/Marketplace.js ดังแสดงในรูปด้านล่าง.
import Navbar from "./Navbar";
import NFTTile from "./NFTTile";
import MarketplaceJSON from "../Marketplace.json";
import axios from "axios";
import { useState } from "react";
export default function Marketplace() {
const sampleData = [
{
"name": "NFT#1",
"description": "Alchemy's First NFT",
"website":"http://axieinfinity.io",
"image":"https://gateway.pinata.cloud/ipfs/QmTsRJX7r5gyubjkdmzFrKQhHv74p5wT9LdeF1m3RTqrE5",
"price":"0.03ETH",
"currentlySelling":"True",
"address":"0xe81Bf5A757CB4f7F82a2F23b1e59bE45c33c5b13",
},
{
"name": "NFT#2",
"description": "Alchemy's Second NFT",
"website":"http://axieinfinity.io",
"image":"https://gateway.pinata.cloud/ipfs/QmdhoL9K8my2vi3fej97foiqGmJ389SMs55oC5EdkrxF2M",
"price":"0.03ETH",
"currentlySelling":"True",
"address":"0xe81Bf5A757C4f7F82a2F23b1e59bE45c33c5b13",
},
{
"name": "NFT#3",
"description": "Alchemy's Third NFT",
"website":"http://axieinfinity.io",
"image":"https://gateway.pinata.cloud/ipfs/QmTsRJX7r5gyubjkdmzFrKQhHv74p5wT9LdeF1m3RTqrE5",
"price":"0.03ETH",
"currentlySelling":"True",
"address":"0xe81Bf5A757C4f7F82a2F23b1e59bE45c33c5b13",
},
];
const [data, updateData] = useState(sampleData);
const [dataFetched, updateFetched] = useState(false);
async function getAllNFTs() {
const ethers = require("ethers");
//After adding your Hardhat network to your metamask, this code will get providers and signers
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
//Pull the deployed contract instance
let contract = new ethers.Contract(MarketplaceJSON.address, MarketplaceJSON.abi, signer)
//create an NFT Token
let transaction = await contract.getAllNFTs()
//Fetch all the details of every NFT from the contract and display
const items = await Promise.all(transaction.map(async i => {
const tokenURI = await contract.tokenURI(i.tokenId);
let meta = await axios.get(tokenURI);
meta = meta.data;
let price = ethers.utils.formatUnits(i.price.toString(), 'ether');
let item = {
price,
tokenId: i.tokenId.toNumber(),
seller: i.seller,
owner: i.owner,
image: meta.image,
name: meta.name,
description: meta.description,
}
return item;
}))
updateFetched(true);
updateData(items);
}
if(!dataFetched)
getAllNFTs();
return (
<div>
<Navbar></Navbar>
<div className="flex flex-col place-items-center mt-20">
<div className="md:text-xl font-bold text-white">
Top NFTs
</div>
<div className="flex mt-5 justify-between flex-wrap max-w-screen-xl text-center">
{data.map((value, index) => {
return <NFTTile data={value} key={index}></NFTTile>;
})}
</div>
</div>
</div>
);
}

3. วางโค้ดต่อไปนี้ลงใน src/components/Profile.js ดังแสดงในรูปด้านล่าง.

4. วางโค้ดต่อไปนี้ลงใน src/components/NFTPage.js ดังแสดงในรูปด้านล่าง.

อย่าลืมบันทึก.
1. ป้อน npm start ในคอนโซล, คุณจะเห็นว่าสำเร็จ.


https://docs.google.com/forms/d/e/1FAIpQLSdNNLXMYZmIhjcWoT-UedS3AoGpRiPDRaNARUPGXLbX1TVvSg/viewform
ส่งโดยอัปโหลดลง github หรือ ส่ง url จาก address.

เราสามารถเช็ด nft ที่เรายังไม่ได้เคลมได้นะครับโดยเข้าไปที่ mintkudos จากนั้นต่อกระเป๋ามุมขวามือลองกดเช็ดดูถ้ามีปลุ่ม claim แปลว่าเรามี nft ที่เราสามารถเคลมได้แต่เรายังไม่ได้เคลม.

เท่านี้ก็จบกันไปแล้วนะครับกับ Alchemy Road to web3 week7 ใครมีคำถาม หรือสงสัยยังไงสามารถถามได้. ส่วนใครที่อยากจะสนับสนุนค่ากาแฟให้ผู้เขียนสามารถกดปุ่ม Collect Entry ได้ที่ด้านล่างนี้จากนั้นเราจะได้ nft บทความของ mirror.xyz chain optimism และสามารถเช็ด nft ที่เรา collect มาได้ที่ QxProfile.
collect://
//SPDX-License-Identifier: Unlicense
import "hardhat/console.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract NFTMarketplace is ERC721URIStorage {
using Counters for Counters.Counter;
//_tokenIds variable has the most recent minted tokenId
Counters.Counter private _tokenIds;
//Keeps track of the number of items sold on the marketplace
Counters.Counter private _itemsSold;
//owner is the contract address that created the smart contract
address payable owner;
//The fee charged by the marketplace to be allowed to list an NFT
uint256 listPrice = 0.01 ether;
//The structure to store info about a listed token
struct ListedToken {
uint256 tokenId;
address payable owner;
address payable seller;
uint256 price;
bool currentlyListed;
}
//the event emitted when a token is successfully listed
event TokenListedSuccess (
uint256 indexed tokenId,
address owner,
address seller,
uint256 price,
bool currentlyListed
);
//This mapping maps tokenId to token info and is helpful when retrieving details about a tokenId
mapping(uint256 => ListedToken) private idToListedToken;
constructor() ERC721("NFTMarketplace", "NFTM") {
owner = payable(msg.sender);
}
function updateListPrice(uint256 _listPrice) public payable {
require(owner == msg.sender, "Only owner can update listing price");
listPrice = _listPrice;
}
function getListPrice() public view returns (uint256) {
return listPrice;
}
function getLatestIdToListedToken() public view returns (ListedToken memory) {
uint256 currentTokenId = _tokenIds.current();
return idToListedToken[currentTokenId];
}
function getListedTokenForId(uint256 tokenId) public view returns (ListedToken memory) {
return idToListedToken[tokenId];
}
function getCurrentToken() public view returns (uint256) {
return _tokenIds.current();
}
//The first time a token is created, it is listed here
function createToken(string memory tokenURI, uint256 price) public payable returns (uint) {
//Increment the tokenId counter, which is keeping track of the number of minted NFTs
_tokenIds.increment();
uint256 newTokenId = _tokenIds.current();
//Mint the NFT with tokenId newTokenId to the address who called createToken
_safeMint(msg.sender, newTokenId);
//Map the tokenId to the tokenURI (which is an IPFS URL with the NFT metadata)
_setTokenURI(newTokenId, tokenURI);
//Helper function to update Global variables and emit an event
createListedToken(newTokenId, price);
return newTokenId;
}
function createListedToken(uint256 tokenId, uint256 price) private {
//Make sure the sender sent enough ETH to pay for listing
require(msg.value == listPrice, "Hopefully sending the correct price");
//Just sanity check
require(price > 0, "Make sure the price isn't negative");
//Update the mapping of tokenId's to Token details, useful for retrieval functions
idToListedToken[tokenId] = ListedToken(
tokenId,
payable(address(this)),
payable(msg.sender),
price,
true
);
_transfer(msg.sender, address(this), tokenId);
//Emit the event for successful transfer. The frontend parses this message and updates the end user
emit TokenListedSuccess(
tokenId,
address(this),
msg.sender,
price,
true
);
}
//This will return all the NFTs currently listed to be sold on the marketplace
function getAllNFTs() public view returns (ListedToken[] memory) {
uint nftCount = _tokenIds.current();
ListedToken[] memory tokens = new ListedTokenUnsupported embed;
uint currentIndex = 0;
//at the moment currentlyListed is true for all, if it becomes false in the future we will
//filter out currentlyListed == false over here
for(uint i=0;i<nftCount;i++)
{
uint currentId = i + 1;
ListedToken storage currentItem = idToListedToken[currentId];
tokens[currentIndex] = currentItem;
currentIndex += 1;
}
//the array 'tokens' has the list of all NFTs in the marketplace
return tokens;
}
//Returns all the NFTs that the current user is owner or seller in
function getMyNFTs() public view returns (ListedToken[] memory) {
uint totalItemCount = _tokenIds.current();
uint itemCount = 0;
uint currentIndex = 0;
//Important to get a count of all the NFTs that belong to the user before we can make an array for them
for(uint i=0; i < totalItemCount; i++)
{
if(idToListedToken[i+1].owner == msg.sender || idToListedToken[i+1].seller == msg.sender){
itemCount += 1;
}
}
//Once you have the count of relevant NFTs, create an array then store all the NFTs in it
ListedToken[] memory items = new ListedTokenUnsupported embed;
for(uint i=0; i < totalItemCount; i++) {
if(idToListedToken[i+1].owner == msg.sender || idToListedToken[i+1].seller == msg.sender) {
uint currentId = i+1;
ListedToken storage currentItem = idToListedToken[currentId];
items[currentIndex] = currentItem;
currentIndex += 1;
}
}
return items;
}
function executeSale(uint256 tokenId) public payable {
uint price = idToListedToken[tokenId].price;
address seller = idToListedToken[tokenId].seller;
require(msg.value == price, "Please submit the asking price in order to complete the purchase");
//update the details of the token
idToListedToken[tokenId].currentlyListed = true;
idToListedToken[tokenId].seller = payable(msg.sender);
_itemsSold.increment();
//Actually transfer the token to the new owner
_transfer(address(this), msg.sender, tokenId);
//approve the marketplace to sell NFTs on your behalf
approve(address(this), tokenId);
//Transfer the listing fee to the marketplace creator
payable(owner).transfer(listPrice);
//Transfer the proceeds from the sale to the seller of the NFT
payable(seller).transfer(msg.value);
}
//We might add a resell token function in the future
//In that case, tokens won't be listed by default but users can send a request to actually list a token
//Currently NFTs are listed by default
}
import Navbar from "./Navbar";
import { useState } from "react";
import { uploadFileToIPFS, uploadJSONToIPFS } from "../pinata";
import Marketplace from '../Marketplace.json';
import { useLocation } from "react-router";
export default function SellNFT () {
const [formParams, updateFormParams] = useState({ name: '', description: '', price: ''});
const [fileURL, setFileURL] = useState(null);
const ethers = require("ethers");
const [message, updateMessage] = useState('');
const location = useLocation();
//This function uploads the NFT image to IPFS
async function OnChangeFile(e) {
var file = e.target.files[0];
//check for file extension
try {
//upload the file to IPFS
const response = await uploadFileToIPFS(file);
if(response.success === true) {
console.log("Uploaded image to Pinata: ", response.pinataURL)
setFileURL(response.pinataURL);
}
}
catch(e) {
console.log("Error during file upload", e);
}
}
//This function uploads the metadata to IPDS
async function uploadMetadataToIPFS() {
const {name, description, price} = formParams;
//Make sure that none of the fields are empty
if( !name || !description || !price || !fileURL)
return;
const nftJSON = {
name, description, price, image: fileURL
}
try {
//upload the metadata JSON to IPFS
const response = await uploadJSONToIPFS(nftJSON);
if(response.success === true){
console.log("Uploaded JSON to Pinata: ", response)
return response.pinataURL;
}
}
catch(e) {
console.log("error uploading JSON metadata:", e)
}
}
async function listNFT(e) {
e.preventDefault();
//Upload data to IPFS
try {
const metadataURL = await uploadMetadataToIPFS();
//After adding your Hardhat network to your metamask, this code will get providers and signers
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
updateMessage("Please wait.. uploading (upto 5 mins)")
//Pull the deployed contract instance
let contract = new ethers.Contract(Marketplace.address, Marketplace.abi, signer)
//massage the params to be sent to the create NFT request
const price = ethers.utils.parseUnits(formParams.price, 'ether')
let listingPrice = await contract.getListPrice()
listingPrice = listingPrice.toString()
//actually create the NFT
let transaction = await contract.createToken(metadataURL, price, { value: listingPrice })
await transaction.wait()
alert("Successfully listed your NFT!");
updateMessage("");
updateFormParams({ name: '', description: '', price: ''});
window.location.replace("/")
}
catch(e) {
alert( "Upload error"+e )
}
}
console.log("Working", process.env);
return (
<div className="">
<Navbar></Navbar>
<div className="flex flex-col place-items-center mt-10" id="nftForm">
<form className="bg-white shadow-md rounded px-8 pt-4 pb-8 mb-4">
<h3 className="text-center font-bold text-purple-500 mb-8">Upload your NFT to the marketplace</h3>
<div className="mb-4">
<label className="block text-purple-500 text-sm font-bold mb-2" htmlFor="name">NFT Name</label>
<input className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="name" type="text" placeholder="Axie#4563" onChange={e => updateFormParams({...formParams, name: e.target.value})} value={formParams.name}></input>
</div>
<div className="mb-6">
<label className="block text-purple-500 text-sm font-bold mb-2" htmlFor="description">NFT Description</label>
<textarea className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" cols="40" rows="5" id="description" type="text" placeholder="Axie Infinity Collection" value={formParams.description} onChange={e => updateFormParams({...formParams, description: e.target.value})}></textarea>
</div>
<div className="mb-6">
<label className="block text-purple-500 text-sm font-bold mb-2" htmlFor="price">Price (in ETH)</label>
<input className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" type="number" placeholder="Min 0.01 ETH" step="0.01" value={formParams.price} onChange={e => updateFormParams({...formParams, price: e.target.value})}></input>
</div>
<div>
<label className="block text-purple-500 text-sm font-bold mb-2" htmlFor="image">Upload Image</label>
<input type={"file"} onChange={OnChangeFile}></input>
</div>
<br></br>
<div className="text-green text-center">{message}</div>
<button onClick={listNFT} className="font-bold mt-10 w-full bg-purple-500 text-white rounded p-2 shadow-lg">
List NFT
</button>
</form>
</div>
</div>
)
}
import Navbar from "./Navbar";
import { useLocation, useParams } from 'react-router-dom';
import MarketplaceJSON from "../Marketplace.json";
import axios from "axios";
import { useState } from "react";
import NFTTile from "./NFTTile";
export default function Profile () {
const [data, updateData] = useState([]);
const [dataFetched, updateFetched] = useState(false);
const [address, updateAddress] = useState("0x");
const [totalPrice, updateTotalPrice] = useState("0");
async function getNFTData(tokenId) {
const ethers = require("ethers");
let sumPrice = 0;
//After adding your Hardhat network to your metamask, this code will get providers and signers
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const addr = await signer.getAddress();
//Pull the deployed contract instance
let contract = new ethers.Contract(MarketplaceJSON.address, MarketplaceJSON.abi, signer)
//create an NFT Token
let transaction = await contract.getMyNFTs()
/*
* Below function takes the metadata from tokenURI and the data returned by getMyNFTs() contract function
* and creates an object of information that is to be displayed
*/
const items = await Promise.all(transaction.map(async i => {
const tokenURI = await contract.tokenURI(i.tokenId);
let meta = await axios.get(tokenURI);
meta = meta.data;
let price = ethers.utils.formatUnits(i.price.toString(), 'ether');
let item = {
price,
tokenId: i.tokenId.toNumber(),
seller: i.seller,
owner: i.owner,
image: meta.image,
name: meta.name,
description: meta.description,
}
sumPrice += Number(price);
return item;
}))
updateData(items);
updateFetched(true);
updateAddress(addr);
updateTotalPrice(sumPrice.toPrecision(3));
}
const params = useParams();
const tokenId = params.tokenId;
if(!dataFetched)
getNFTData(tokenId);
return (
<div className="profileClass" style={{"min-height":"100vh"}}>
<Navbar></Navbar>
<div className="profileClass">
<div className="flex text-center flex-col mt-11 md:text-2xl text-white">
<div className="mb-5">
<h2 className="font-bold">Wallet Address</h2>
{address}
</div>
</div>
<div className="flex flex-row text-center justify-center mt-10 md:text-2xl text-white">
<div>
<h2 className="font-bold">No. of NFTs</h2>
{data.length}
</div>
<div className="ml-20">
<h2 className="font-bold">Total Value</h2>
{totalPrice} ETH
</div>
</div>
<div className="flex flex-col text-center items-center mt-11 text-white">
<h2 className="font-bold">Your NFTs</h2>
<div className="flex justify-center flex-wrap max-w-screen-xl">
{data.map((value, index) => {
return <NFTTile data={value} key={index}></NFTTile>;
})}
</div>
<div className="mt-10 text-xl">
{data.length == 0 ? "Oops, No NFT data to display (Are you logged in?)":""}
</div>
</div>
</div>
</div>
)
};
import Navbar from "./Navbar";
import axie from "../tile.jpeg";
import { useLocation, useParams } from 'react-router-dom';
import MarketplaceJSON from "../Marketplace.json";
import axios from "axios";
import { useState } from "react";
export default function NFTPage (props) {
const [data, updateData] = useState({});
const [dataFetched, updateDataFetched] = useState(false);
const [message, updateMessage] = useState("");
const [currAddress, updateCurrAddress] = useState("0x");
async function getNFTData(tokenId) {
const ethers = require("ethers");
//After adding your Hardhat network to your metamask, this code will get providers and signers
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const addr = await signer.getAddress();
//Pull the deployed contract instance
let contract = new ethers.Contract(MarketplaceJSON.address, MarketplaceJSON.abi, signer)
//create an NFT Token
const tokenURI = await contract.tokenURI(tokenId);
const listedToken = await contract.getListedTokenForId(tokenId);
let meta = await axios.get(tokenURI);
meta = meta.data;
console.log(listedToken);
let item = {
price: meta.price,
tokenId: tokenId,
seller: listedToken.seller,
owner: listedToken.owner,
image: meta.image,
name: meta.name,
description: meta.description,
}
console.log(item);
updateData(item);
updateDataFetched(true);
console.log("address", addr)
updateCurrAddress(addr);
}
async function buyNFT(tokenId) {
try {
const ethers = require("ethers");
//After adding your Hardhat network to your metamask, this code will get providers and signers
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
//Pull the deployed contract instance
let contract = new ethers.Contract(MarketplaceJSON.address, MarketplaceJSON.abi, signer);
const salePrice = ethers.utils.parseUnits(data.price, 'ether')
updateMessage("Buying the NFT... Please Wait (Upto 5 mins)")
//run the executeSale function
let transaction = await contract.executeSale(tokenId, {value:salePrice});
await transaction.wait();
alert('You successfully bought the NFT!');
updateMessage("");
}
catch(e) {
alert("Upload Error"+e)
}
}
const params = useParams();
const tokenId = params.tokenId;
if(!dataFetched)
getNFTData(tokenId);
return(
<div style={{"min-height":"100vh"}}>
<Navbar></Navbar>
<div className="flex ml-20 mt-20">
<img src={data.image} alt="" className="w-2/5" />
<div className="text-xl ml-20 space-y-8 text-white shadow-2xl rounded-lg border-2 p-5">
<div>
Name: {data.name}
</div>
<div>
Description: {data.description}
</div>
<div>
Price: <span className="">{data.price + " ETH"}</span>
</div>
<div>
Owner: <span className="text-sm">{data.owner}</span>
</div>
<div>
Seller: <span className="text-sm">{data.seller}</span>
</div>
<div>
{ currAddress == data.owner || currAddress == data.seller ?
<button className="enableEthereumButton bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-sm" onClick={() => buyNFT(tokenId)}>Buy this NFT</button>
: <div className="text-emerald-700">You are the owner of this NFT</div>
}
<div className="text-green text-center mt-3">{message}</div>
</div>
</div>
</div>
</div>
)
}
//SPDX-License-Identifier: Unlicense
import "hardhat/console.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract NFTMarketplace is ERC721URIStorage {
using Counters for Counters.Counter;
//_tokenIds variable has the most recent minted tokenId
Counters.Counter private _tokenIds;
//Keeps track of the number of items sold on the marketplace
Counters.Counter private _itemsSold;
//owner is the contract address that created the smart contract
address payable owner;
//The fee charged by the marketplace to be allowed to list an NFT
uint256 listPrice = 0.01 ether;
//The structure to store info about a listed token
struct ListedToken {
uint256 tokenId;
address payable owner;
address payable seller;
uint256 price;
bool currentlyListed;
}
//the event emitted when a token is successfully listed
event TokenListedSuccess (
uint256 indexed tokenId,
address owner,
address seller,
uint256 price,
bool currentlyListed
);
//This mapping maps tokenId to token info and is helpful when retrieving details about a tokenId
mapping(uint256 => ListedToken) private idToListedToken;
constructor() ERC721("NFTMarketplace", "NFTM") {
owner = payable(msg.sender);
}
function updateListPrice(uint256 _listPrice) public payable {
require(owner == msg.sender, "Only owner can update listing price");
listPrice = _listPrice;
}
function getListPrice() public view returns (uint256) {
return listPrice;
}
function getLatestIdToListedToken() public view returns (ListedToken memory) {
uint256 currentTokenId = _tokenIds.current();
return idToListedToken[currentTokenId];
}
function getListedTokenForId(uint256 tokenId) public view returns (ListedToken memory) {
return idToListedToken[tokenId];
}
function getCurrentToken() public view returns (uint256) {
return _tokenIds.current();
}
//The first time a token is created, it is listed here
function createToken(string memory tokenURI, uint256 price) public payable returns (uint) {
//Increment the tokenId counter, which is keeping track of the number of minted NFTs
_tokenIds.increment();
uint256 newTokenId = _tokenIds.current();
//Mint the NFT with tokenId newTokenId to the address who called createToken
_safeMint(msg.sender, newTokenId);
//Map the tokenId to the tokenURI (which is an IPFS URL with the NFT metadata)
_setTokenURI(newTokenId, tokenURI);
//Helper function to update Global variables and emit an event
createListedToken(newTokenId, price);
return newTokenId;
}
function createListedToken(uint256 tokenId, uint256 price) private {
//Make sure the sender sent enough ETH to pay for listing
require(msg.value == listPrice, "Hopefully sending the correct price");
//Just sanity check
require(price > 0, "Make sure the price isn't negative");
//Update the mapping of tokenId's to Token details, useful for retrieval functions
idToListedToken[tokenId] = ListedToken(
tokenId,
payable(address(this)),
payable(msg.sender),
price,
true
);
_transfer(msg.sender, address(this), tokenId);
//Emit the event for successful transfer. The frontend parses this message and updates the end user
emit TokenListedSuccess(
tokenId,
address(this),
msg.sender,
price,
true
);
}
//This will return all the NFTs currently listed to be sold on the marketplace
function getAllNFTs() public view returns (ListedToken[] memory) {
uint nftCount = _tokenIds.current();
ListedToken[] memory tokens = new ListedTokenUnsupported embed;
uint currentIndex = 0;
//at the moment currentlyListed is true for all, if it becomes false in the future we will
//filter out currentlyListed == false over here
for(uint i=0;i<nftCount;i++)
{
uint currentId = i + 1;
ListedToken storage currentItem = idToListedToken[currentId];
tokens[currentIndex] = currentItem;
currentIndex += 1;
}
//the array 'tokens' has the list of all NFTs in the marketplace
return tokens;
}
//Returns all the NFTs that the current user is owner or seller in
function getMyNFTs() public view returns (ListedToken[] memory) {
uint totalItemCount = _tokenIds.current();
uint itemCount = 0;
uint currentIndex = 0;
//Important to get a count of all the NFTs that belong to the user before we can make an array for them
for(uint i=0; i < totalItemCount; i++)
{
if(idToListedToken[i+1].owner == msg.sender || idToListedToken[i+1].seller == msg.sender){
itemCount += 1;
}
}
//Once you have the count of relevant NFTs, create an array then store all the NFTs in it
ListedToken[] memory items = new ListedTokenUnsupported embed;
for(uint i=0; i < totalItemCount; i++) {
if(idToListedToken[i+1].owner == msg.sender || idToListedToken[i+1].seller == msg.sender) {
uint currentId = i+1;
ListedToken storage currentItem = idToListedToken[currentId];
items[currentIndex] = currentItem;
currentIndex += 1;
}
}
return items;
}
function executeSale(uint256 tokenId) public payable {
uint price = idToListedToken[tokenId].price;
address seller = idToListedToken[tokenId].seller;
require(msg.value == price, "Please submit the asking price in order to complete the purchase");
//update the details of the token
idToListedToken[tokenId].currentlyListed = true;
idToListedToken[tokenId].seller = payable(msg.sender);
_itemsSold.increment();
//Actually transfer the token to the new owner
_transfer(address(this), msg.sender, tokenId);
//approve the marketplace to sell NFTs on your behalf
approve(address(this), tokenId);
//Transfer the listing fee to the marketplace creator
payable(owner).transfer(listPrice);
//Transfer the proceeds from the sale to the seller of the NFT
payable(seller).transfer(msg.value);
}
//We might add a resell token function in the future
//In that case, tokens won't be listed by default but users can send a request to actually list a token
//Currently NFTs are listed by default
}
import Navbar from "./Navbar";
import { useState } from "react";
import { uploadFileToIPFS, uploadJSONToIPFS } from "../pinata";
import Marketplace from '../Marketplace.json';
import { useLocation } from "react-router";
export default function SellNFT () {
const [formParams, updateFormParams] = useState({ name: '', description: '', price: ''});
const [fileURL, setFileURL] = useState(null);
const ethers = require("ethers");
const [message, updateMessage] = useState('');
const location = useLocation();
//This function uploads the NFT image to IPFS
async function OnChangeFile(e) {
var file = e.target.files[0];
//check for file extension
try {
//upload the file to IPFS
const response = await uploadFileToIPFS(file);
if(response.success === true) {
console.log("Uploaded image to Pinata: ", response.pinataURL)
setFileURL(response.pinataURL);
}
}
catch(e) {
console.log("Error during file upload", e);
}
}
//This function uploads the metadata to IPDS
async function uploadMetadataToIPFS() {
const {name, description, price} = formParams;
//Make sure that none of the fields are empty
if( !name || !description || !price || !fileURL)
return;
const nftJSON = {
name, description, price, image: fileURL
}
try {
//upload the metadata JSON to IPFS
const response = await uploadJSONToIPFS(nftJSON);
if(response.success === true){
console.log("Uploaded JSON to Pinata: ", response)
return response.pinataURL;
}
}
catch(e) {
console.log("error uploading JSON metadata:", e)
}
}
async function listNFT(e) {
e.preventDefault();
//Upload data to IPFS
try {
const metadataURL = await uploadMetadataToIPFS();
//After adding your Hardhat network to your metamask, this code will get providers and signers
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
updateMessage("Please wait.. uploading (upto 5 mins)")
//Pull the deployed contract instance
let contract = new ethers.Contract(Marketplace.address, Marketplace.abi, signer)
//massage the params to be sent to the create NFT request
const price = ethers.utils.parseUnits(formParams.price, 'ether')
let listingPrice = await contract.getListPrice()
listingPrice = listingPrice.toString()
//actually create the NFT
let transaction = await contract.createToken(metadataURL, price, { value: listingPrice })
await transaction.wait()
alert("Successfully listed your NFT!");
updateMessage("");
updateFormParams({ name: '', description: '', price: ''});
window.location.replace("/")
}
catch(e) {
alert( "Upload error"+e )
}
}
console.log("Working", process.env);
return (
<div className="">
<Navbar></Navbar>
<div className="flex flex-col place-items-center mt-10" id="nftForm">
<form className="bg-white shadow-md rounded px-8 pt-4 pb-8 mb-4">
<h3 className="text-center font-bold text-purple-500 mb-8">Upload your NFT to the marketplace</h3>
<div className="mb-4">
<label className="block text-purple-500 text-sm font-bold mb-2" htmlFor="name">NFT Name</label>
<input className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="name" type="text" placeholder="Axie#4563" onChange={e => updateFormParams({...formParams, name: e.target.value})} value={formParams.name}></input>
</div>
<div className="mb-6">
<label className="block text-purple-500 text-sm font-bold mb-2" htmlFor="description">NFT Description</label>
<textarea className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" cols="40" rows="5" id="description" type="text" placeholder="Axie Infinity Collection" value={formParams.description} onChange={e => updateFormParams({...formParams, description: e.target.value})}></textarea>
</div>
<div className="mb-6">
<label className="block text-purple-500 text-sm font-bold mb-2" htmlFor="price">Price (in ETH)</label>
<input className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" type="number" placeholder="Min 0.01 ETH" step="0.01" value={formParams.price} onChange={e => updateFormParams({...formParams, price: e.target.value})}></input>
</div>
<div>
<label className="block text-purple-500 text-sm font-bold mb-2" htmlFor="image">Upload Image</label>
<input type={"file"} onChange={OnChangeFile}></input>
</div>
<br></br>
<div className="text-green text-center">{message}</div>
<button onClick={listNFT} className="font-bold mt-10 w-full bg-purple-500 text-white rounded p-2 shadow-lg">
List NFT
</button>
</form>
</div>
</div>
)
}
import Navbar from "./Navbar";
import { useLocation, useParams } from 'react-router-dom';
import MarketplaceJSON from "../Marketplace.json";
import axios from "axios";
import { useState } from "react";
import NFTTile from "./NFTTile";
export default function Profile () {
const [data, updateData] = useState([]);
const [dataFetched, updateFetched] = useState(false);
const [address, updateAddress] = useState("0x");
const [totalPrice, updateTotalPrice] = useState("0");
async function getNFTData(tokenId) {
const ethers = require("ethers");
let sumPrice = 0;
//After adding your Hardhat network to your metamask, this code will get providers and signers
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const addr = await signer.getAddress();
//Pull the deployed contract instance
let contract = new ethers.Contract(MarketplaceJSON.address, MarketplaceJSON.abi, signer)
//create an NFT Token
let transaction = await contract.getMyNFTs()
/*
* Below function takes the metadata from tokenURI and the data returned by getMyNFTs() contract function
* and creates an object of information that is to be displayed
*/
const items = await Promise.all(transaction.map(async i => {
const tokenURI = await contract.tokenURI(i.tokenId);
let meta = await axios.get(tokenURI);
meta = meta.data;
let price = ethers.utils.formatUnits(i.price.toString(), 'ether');
let item = {
price,
tokenId: i.tokenId.toNumber(),
seller: i.seller,
owner: i.owner,
image: meta.image,
name: meta.name,
description: meta.description,
}
sumPrice += Number(price);
return item;
}))
updateData(items);
updateFetched(true);
updateAddress(addr);
updateTotalPrice(sumPrice.toPrecision(3));
}
const params = useParams();
const tokenId = params.tokenId;
if(!dataFetched)
getNFTData(tokenId);
return (
<div className="profileClass" style={{"min-height":"100vh"}}>
<Navbar></Navbar>
<div className="profileClass">
<div className="flex text-center flex-col mt-11 md:text-2xl text-white">
<div className="mb-5">
<h2 className="font-bold">Wallet Address</h2>
{address}
</div>
</div>
<div className="flex flex-row text-center justify-center mt-10 md:text-2xl text-white">
<div>
<h2 className="font-bold">No. of NFTs</h2>
{data.length}
</div>
<div className="ml-20">
<h2 className="font-bold">Total Value</h2>
{totalPrice} ETH
</div>
</div>
<div className="flex flex-col text-center items-center mt-11 text-white">
<h2 className="font-bold">Your NFTs</h2>
<div className="flex justify-center flex-wrap max-w-screen-xl">
{data.map((value, index) => {
return <NFTTile data={value} key={index}></NFTTile>;
})}
</div>
<div className="mt-10 text-xl">
{data.length == 0 ? "Oops, No NFT data to display (Are you logged in?)":""}
</div>
</div>
</div>
</div>
)
};
import Navbar from "./Navbar";
import axie from "../tile.jpeg";
import { useLocation, useParams } from 'react-router-dom';
import MarketplaceJSON from "../Marketplace.json";
import axios from "axios";
import { useState } from "react";
export default function NFTPage (props) {
const [data, updateData] = useState({});
const [dataFetched, updateDataFetched] = useState(false);
const [message, updateMessage] = useState("");
const [currAddress, updateCurrAddress] = useState("0x");
async function getNFTData(tokenId) {
const ethers = require("ethers");
//After adding your Hardhat network to your metamask, this code will get providers and signers
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const addr = await signer.getAddress();
//Pull the deployed contract instance
let contract = new ethers.Contract(MarketplaceJSON.address, MarketplaceJSON.abi, signer)
//create an NFT Token
const tokenURI = await contract.tokenURI(tokenId);
const listedToken = await contract.getListedTokenForId(tokenId);
let meta = await axios.get(tokenURI);
meta = meta.data;
console.log(listedToken);
let item = {
price: meta.price,
tokenId: tokenId,
seller: listedToken.seller,
owner: listedToken.owner,
image: meta.image,
name: meta.name,
description: meta.description,
}
console.log(item);
updateData(item);
updateDataFetched(true);
console.log("address", addr)
updateCurrAddress(addr);
}
async function buyNFT(tokenId) {
try {
const ethers = require("ethers");
//After adding your Hardhat network to your metamask, this code will get providers and signers
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
//Pull the deployed contract instance
let contract = new ethers.Contract(MarketplaceJSON.address, MarketplaceJSON.abi, signer);
const salePrice = ethers.utils.parseUnits(data.price, 'ether')
updateMessage("Buying the NFT... Please Wait (Upto 5 mins)")
//run the executeSale function
let transaction = await contract.executeSale(tokenId, {value:salePrice});
await transaction.wait();
alert('You successfully bought the NFT!');
updateMessage("");
}
catch(e) {
alert("Upload Error"+e)
}
}
const params = useParams();
const tokenId = params.tokenId;
if(!dataFetched)
getNFTData(tokenId);
return(
<div style={{"min-height":"100vh"}}>
<Navbar></Navbar>
<div className="flex ml-20 mt-20">
<img src={data.image} alt="" className="w-2/5" />
<div className="text-xl ml-20 space-y-8 text-white shadow-2xl rounded-lg border-2 p-5">
<div>
Name: {data.name}
</div>
<div>
Description: {data.description}
</div>
<div>
Price: <span className="">{data.price + " ETH"}</span>
</div>
<div>
Owner: <span className="text-sm">{data.owner}</span>
</div>
<div>
Seller: <span className="text-sm">{data.seller}</span>
</div>
<div>
{ currAddress == data.owner || currAddress == data.seller ?
<button className="enableEthereumButton bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-sm" onClick={() => buyNFT(tokenId)}>Buy this NFT</button>
: <div className="text-emerald-700">You are the owner of this NFT</div>
}
<div className="text-green text-center mt-3">{message}</div>
</div>
</div>
</div>
</div>
)
}


No comments yet