Создание классического децентрализованного приложения Web3 NFT Minting с помощью React и Solidity: часть 2

Создание классического децентрализованного приложения Web3 NFT Minting с помощью React и Solidity: часть 2

6 апреля 2022 г.

Что вы будете создавать, см. [живую демонстрацию] (https://adulam-nft.web.app/) и [репозиторий GitHub] (https://github.com/Daltonic/adulamNFT) для получения дополнительной информации, не Не забудьте отметить проект звездочкой.


Адулам


Отчеканенные NFT


Введение


В ЧАСТИ ПЕРВОЙ этого руководства мы закодировали часть смарт-контракта. этого приложения с Solidity, теперь пришло время объединить его с ReactJs.


Если вы еще не ознакомились с ЧАСТЬЮ ПЕРВОЙ этого руководства, я рекомендуем сделать это, прежде чем переходить ко второй части.


Если вы получаете пользу от этого руководства и хотите полностью погрузиться в разработку блокчейна, тогда [Вы также можете связаться со мной для получения уроков…] (https://daltonic.github.io/#mh-pricing)


Давайте прыгнем и начнем кодировать…


Предпосылки


Для полного извлечь выгоду из этой части. Если нет, быстро проверьте ЧАСТЬ ПЕРВАЯ, блокчейн развитие не детская игра.


Сборка компонентов


Давайте начнем с создания компонентов шаг за шагом, убедитесь, что вы точно следуете шагам…


Компонент заголовка


Как всегда, мы начнем с компонента заголовка, это нормальный поток любого веб-сайта или приложения.


Компонент заголовка


Это было прекрасно обработано с помощью CSS попутного ветра с использованием стилей градиентов. Он просто позволяет пользователю подключить адрес кошелька для минтинга. В проекте перейдите в папку компонентов и создайте новый файл с именем Header.jsx. После этого вставьте в него приведенные ниже коды.


```javascript


импортировать ethlogo из '../assets/ethlogo.png'


импортировать {connectWallet} из '../Adulam'


импортировать {useGlobalState} из '../store'


константный заголовок = () => {


const [connectedAccount] = useGlobalState('connectedAccount')


вернуть (



экспорт заголовка по умолчанию


Это все для заголовка, давайте поработаем над компонентом Hero.


Компонент героя


Компонент героя


Этот компонент отвечает за инициирование процесса чеканки, как вы можете видеть с помощью кнопки чеканки. Кроме того, требуется запись общего количества отчеканенных NFT по сравнению с оставшимися.


Вот фрагмент кода, отвечающий за эту операцию…


```javascript


импортировать аватар из '../assets/owner.jpg'


импортировать github из «../assets/github_icon.png»


импортировать facebook из '../assets/facebook_icon.png'


импортировать твиттер из '../assets/twitter_icon.png'


импортировать linkedIn из '../assets/linkedIn_icon.png'


импортировать носитель из '../assets/medium_icon.png'


импорт {


установить оповещение,


использование GlobalState,


setGlobalState,


setLoadingMsg,


} из '../магазин'


импортировать {BASE_URI, payForArt} из '../Adulam'


константный герой = () => {


const [connectedAccount] = useGlobalState('connectedAccount')


const [maxSupply] = useGlobalState('maxSupply')


const [nfts] = useGlobalState('nfts')


константный монетный двор = асинхронный () => {


setGlobalState('загрузка', { show: true, msg: 'Извлечение данных IPFS...' })


const nextTokenIndex = число (nfts.length + 1)


fetch(${BASE_URI + nextTokenIndex}.json)


.then((данные) => data.json())


.тог((рез) => {


setLoadingMsg('Инициализация транзакции...')


payForArt({ ...res, покупатель: connectAccount }).then((result) => {


если (результат) {


setGlobalState('загрузка', {show: false, msg: ''})


setAlert('Успешная чеканка...', 'зеленый')


окно.местоположение.перезагрузить()


.catch((ошибка) => {


setGlobalState('загрузка', {show: false, msg: ''})


console.log(ошибка)


вернуть (


<дел


className="bg-[url('https://cdn.pixabay.com/photo/2022/03/01/02/51/galaxy-7040416_960_720.png')]


bg-без повторов bg-обложка"





Искусство искусственного интеллекта


Коллекция NFT




Чеканите и собирайте самые популярные NFT.



<кнопка


className="shadow-xl тень-черный текст-белый


bg-[#e32970] hover:bg-[#bd255f] p-2


закругленный полный указатель курсора my-4"


onClick={мята}


Монетный двор сейчас




href="https://daltonic.github.io/"


className="flex flex-row justify-center space-x-2 items-center


bg-[#000000ad] rounded-full my-4 pr-3 указатель курсора"


<изображение


className="w-11 h-11 object-contain rounded-full"


источник={аватар}


alt="Лого Адулам"



0xf55...146a


Дальтоник





Госпел Дарлингтон начал свой путь в качестве инженера-программиста в



  1. За эти годы он приобрел полноценные навыки в

Стеки JavaScript, такие как
React, ReactNative, VueJs и теперь


блокчейн.





    className = "bg-white hover: масштаб-50 переход-все продолжительность-75 задержка-75 округлено-полный mx-2"


    href="https://github.com/Daltonic"


    Github




    className = "bg-white hover: масштаб-50 переход-все продолжительность-75 задержка-75 округлено-полный mx-2"


    href="https://www.linkedin.com/in/darlington-gospel-aa626b125"


    linkedIn




    className = "bg-white hover: масштаб-50 переход-все продолжительность-75 задержка-75 округлено-полный mx-2"


    href="https://fb.com/darlington.gospel01"


    facebook




    className = "bg-white hover: масштаб-50 переход-все продолжительность-75 задержка-75 округлено-полный mx-2"


    href="https://twitter.com/idaltonic"


    twitter




    className = "bg-white hover: масштаб-50 переход-все продолжительность-75 задержка-75 округлено-полный mx-2"


    href="https://darlingtongospel.medium.com/"


    medium




<дел


className="shadow-xl shadow-black flex flex-row


выравнивание по центру элементов по центру w-10 h-10 округлено-полный


bg-белый курсор-указатель p-3 мл-4 текст-черный


hover:bg-[#bd255f] hover:текст-белый переход-все


продолжительность-75 задержка-100"



{nfts.length}/{maxSupply}







экспортировать героя по умолчанию


Следующим в нашем списке является компонент художественных работ…


Компонент произведений искусства


Компонент художественного произведения


На этот компонент возложена ответственность за отрисовку произведений искусства одно за другим. Попутный CSS помог нам разработать потрясающий интерфейс.


Давайте посмотрим на коды, отвечающие за поведение этих компонентов…


```javascript


импортировать ethlogo из '../assets/ethlogo.png'


импортировать {useGlobalState} из '../store'


импортировать {BASE_URI} из '../Adulam'


константа Произведения = () => {


const [nfts] = useGlobalState('nfts')


const trucncate = (строка, число = 20) => {


если (str.length > число) {


вернуть str.slice(0, число) + "..."


} еще {


вернуть ул


вернуть (




Художественные работы



{nfts.map((nft) => (


<дел


ключ={nft.id}


className={`относительный shadow-xl shadow-black p-3


bg-white rounded-lg item w-64 h-64 object-contain


bg-[url(${BASE_URI + nft.id}.webp)]


bg-no-repeat bg-cover overflow-hidden mr-2 mb-2 указатель курсора


переход-все продолжительность-75 задержка-100 наведение: тень-[#bd255f]`}


style={{backgroundImage: url(${BASE_URI + nft.id}.webp)}}


<дел


className="абсолютный нижний-0 левый-0 правый-0


flex flex-row justify-between items-center


label-gradient p-2 w-полный текст-белый текст-sm"


<р>


{nft.id}# {усекать (nft.title)}




<изображение


className="w-5 курсор-указатель"


источник={этлого}


alt="Лого Адулам"


{nft.cost}







<кнопка


className="shadow-xl тень-черный текст-белый


bg-[#e32970] hover:bg-[#bd255f] p-2


закругленный полный указатель курсора my-4"


Загрузи больше






экспортировать произведения искусства по умолчанию


Давайте перейдем к добавлению компонента нижнего колонтитула…


Компонент нижнего колонтитула


Компонент нижнего колонтитула


Если вы цените хорошую работу, вам понравится этот дизайн. Tailwind CSS позволил мне создать такие красивые компоненты, как этот. Эй, если вам интересно, я могу пригласить вас на частное занятие по разработке блокчейна, посмотрите мои предложения здесь.


Возвращаясь к этой сборке, этот текущий компонент слегка отличается фирменным отображением бренда и логотипа сайта, ничего особенного в этом компоненте, однако мне нужно было включить его в это руководство.


Ниже приведен код для него…


```javascript


импортировать ethlogo из '../assets/ethlogo.png'


const Нижний колонтитул = () => (






Проводить исследования




Функции




Сообщество





logo



Адулам © 2016 - 2022 С любовью ❤️ Daltonic






экспортировать нижний колонтитул по умолчанию


Фантастика, мы почти закончили с этими компонентами, давайте добавим последние два…


Компонент оповещения


Компонент оповещения


Этот компонент, как бы интуитивно он ни звучал, отвечает за уведомление нас, когда наш процесс чеканки завершен. Опять же, он был создан вручную с использованием Tailwind CSS и некоторых значков реагирования.


Давайте посмотрим на коды, демонстрирующие его поведение…


```javascript


импортировать {useGlobalState} из '../store'


импортировать { FaRegTimesCircle } из 'react-icons/fa'


импортировать { BsCheck2Circle } из 'react-icons/bs'


постоянное предупреждение = () => {


const [предупреждение] = useGlobalState («предупреждение»)


вернуть (


<дел


className={`фиксированный верхний-0 левый-0 w-экран h-экран


flex-элементы-центр, выравнивание-центр, bg-black


bg-opacity-50 преобразование переход-преобразование


продолжительность-300 ${alert.show ? 'масштаб-100' : 'масштаб-0'}`}


<дел


className="flex flex-col justify-center элементы-центр


bg-[#151c25] shadow-xl shadow-[#e32970] округлый-xl


мин-ш-мин py-3 px-10"


{alert.color == 'красный'? (




{alert.msg}




экспортировать предупреждение по умолчанию


Хорошо, давайте завершим эти компоненты, добавив в микс компонент Loader.


Компонент загрузчика


Компонент загрузчика


Этот компонент просто отображает счетчик, который также показывает текущий прогресс NFT по мере его создания.


Библиотека управления состоянием react-global-hooks управляет действиями, которые здесь происходят под капотом; подробнее об этом позже.


Вот код этого компонента...


```javascript


импортировать {useGlobalState} из '../store'


константная загрузка = () => {


const [загрузка] = useGlobalState («загрузка»)


вернуть (


<дел


className={`фиксированный верхний-0 левый-0 w-экран h-экран


flex-элементы-центр, выравнивание-центр, bg-black


bg-opacity-50 преобразование переход-преобразование


продолжительность-300 ${loading.show ? 'масштаб-100' : 'масштаб-0'}`}


<дел


className="flex flex-col justify-center


предметы-центр bg-[#151c25] тень-xl


тень-[# e32970] округлый-xl


мин-ш-мин px-10 pb-2"




Чеканка...



{loading.msg}




экспорт по умолчанию Загрузка


Отлично, теперь, когда мы закончили кодирование компонентов, давайте погрузимся в App.jsx и соединим их вместе.


Компонент приложения


Этот компонент отвечает за подключение всех других компонентов, которые будут использоваться в этом проекте, давайте посмотрим, как он закодирован.


```javascript


импортировать оповещение из './components/Alert'


импортировать произведения искусства из './components/Artworks'


импортировать нижний колонтитул из './components/Footer'


импортировать заголовок из './components/Header'


импортировать героя из './components/Hero'


импорт Загрузка из './components/Loading'


импортировать { loadWeb3 } из './Adulam'


импортировать {useEffect} из «реагировать»


константное приложение = () => {


useEffect(() => loadWeb3(), [])


вернуть (




<Заголовок/>


<Герой/>



<Работы />


<Нижний колонтитул/>


<Загрузка />


<Предупреждение />



экспортировать приложение по умолчанию


Мы еще не совсем закончили, давайте включим другие важные конфигурации.


Индексные файлы


Убедитесь, что ваши файлы index.jsx и index.css имеют конфигурацию, показанную в приведенном ниже фрагменте кода.


``CSS


@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700&display=swap');



заполнение: 0;


маржа: 0;


box-sizing: граница-коробка;


тело {


маржа: 0;


семейство шрифтов: «Open Sans», без засечек;


-webkit-font-smoothing: сглаживание;


-moz-osx-font-smoothing: оттенки серого;


.градиент-bg-герой {


цвет фона: #131835;


фоновое изображение: радиальный градиент (


при 0% 0%,


hsl(231градус 47% 14%) 0%,


прозрачный 50%


радиальный градиент(при 50% 0%, hsl(333deg 85% 53%) 0, прозрачный 50%),


радиально-градиентный(при 100% 0%, hsla(339, 49%, 30%, 1) 0, прозрачный 50%);


.gradient-bg-произведения искусства {


цвет фона: #0f0e13;


фоновое изображение: радиальный градиент (


на 50% 50%,


hsl(302град 25% 18%) 0,


прозрачный 50%


радиально-градиентный (при 0% 0%, hsla (253, 16%, 7%, 1) 0, прозрачный 50%),


радиально-градиентный(при 50% 50%, hsla(339, 39%, 25%, 1) 0, прозрачный 50%);


.градиент-bg-нижний колонтитул {


цвет фона: #131835;


фоновое изображение: радиальный градиент (


при 20% 100%,


hsl(333град 85% 53%) 0,


прозрачный 40%


радиально-градиентный(при 50% 120%, hsla(339, 49%, 30%, 1) 0, прозрачный 40%);


.text-градиент {


фон: -webkit-linear-gradient(#eee, #333);


-webkit-background-clip: текст;


-webkit-text-fill-color: прозрачный;


.label-градиент {


фон: RGB(19, 24, 53);


фон: линейный градиент (


31 град,


rgba(19, 24, 53, 1) 0%,


RGBA(237, 33, 124, 0) 100%


.no-scrollbar::-webkit-scrollbar {


дисплей: нет;


.lds-двойное кольцо {


отображение: встроенный блок;


.lds-двойное кольцо: после {


содержание: ' ';


дисплей: блок;


ширина: 64 пикселя;


высота: 64 пикселя;


поле: 8px;


радиус границы: 50%;


граница: 6px сплошная #fff;


цвет границы: #fff прозрачный #fff прозрачный;


анимация: lds-dual-ring 1.2s линейная бесконечная;


@keyframes lds-двойное кольцо {


0% {


преобразование: повернуть (0 градусов);


100% {


преобразование: поворот (360 градусов);


база @tailwind;


компоненты @tailwind;


утилиты @tailwind;


```javascript


импортировать React из «реагировать»


импортировать ReactDOM из 'react-dom'


импортировать {BrowserRouter} из 'react-router-dom'


импортировать './index.css'


импортировать приложение из './App'


ReactDOM.render(


<Браузермаршрутизатор>


<Приложение />


,


document.getElementById('корень')


Фантастика, есть еще два важных файла, о которых вы должны знать, давайте посмотрим на них…


Блокчейн-интерфейс Adulam


Чтобы вы могли взаимодействовать с нашим развернутым смарт-контрактом, вам необходимо получить к нему доступ через функции. Приведенные ниже коды позволяют нам взаимодействовать с нашим смарт-контрактом, который сейчас работает в сети блокчейна. Создайте файл с именем Adulam.jsx в папке src этого проекта и вставьте в него следующие коды.


```javascript


импортировать Web3 из 'web3'


импорт {


установить оповещение,


setGlobalState,


получитьGlobalState,


setLoadingMsg,


} из './магазин'


импортировать Адулам из './abis/Adulam.json'


const {эфириум} = окно


константа BASE_URI =


'https://bafybeidfpvjszubegtoomoknmc7zcqnay7noteadbwxktw46guhdeqohrm.ipfs.infura-ipfs.io/'


const payForArt = async (искусство) => {


пытаться {


константа web3 = окно.web3


постоянный покупатель = арт.покупатель


постоянный заголовок = арт.заголовок


постоянное описание = арт.описание


константная стоимость = web3.utils.toWei('0.01', 'эфир')


const контракт = ожидание getGlobalState('контракт')


setLoadingMsg('Выполняется чеканка NFT...')


ждать контракта.методы


.payToMint(название, описание)


.send({от: покупатель, значение: стоимость})


setLoadingMsg('Успешная чеканка...')


вернуть истину


} поймать (ошибка) {


setAlert(error.message, 'красный')


const connectWallet = асинхронный () => {


пытаться {


if (!ethereum) вернуть предупреждение('Пожалуйста, установите Metamask')


const account = await ethereum.request({метод: 'eth_requestAccounts' })


setGlobalState('connectedAccount', учетные записи[0])


} поймать (ошибка) {


setAlert (JSON.stringify (ошибка), «красный»)


константа loadWeb3 = асинхронная () => {


пытаться {


if (!ethereum) вернуть предупреждение('Пожалуйста, установите Metamask')


window.web3 = новый Web3 (эфириум)


ждать ethereum.enable()


window.web3 = новый Web3 (window.web3.currentProvider)


константа web3 = окно.web3


константные учетные записи = ожидание web3.eth.getAccounts()


setGlobalState('connectedAccount', учетные записи[0])


const networkId = ожидание web3.eth.net.getId()


const networkData = Adulam.networks[networkId]


если (сетевые данные) {


const contract = новый web3.eth.Contract(Adulam.abi, networkData.address)


const nfts = ожидание контракта.методы.getAllNFTs().call()


setGlobalState('nfts', структурированныйNfts(nfts))


setGlobalState('контракт', контракт)


} еще {


window.alert('Контракт Adulam не развернут в обнаруженной сети.')


} поймать (ошибка) {


alert('Пожалуйста, подключите свой кошелек метамаски!')


const структурированныйNfts = (nfts) => {


константа web3 = окно.web3


возврат nfts


.map((nft) => ({


идентификатор: nft.id,


в: nft.to,


от: нфт.от,


стоимость: web3.utils.fromWei(nft.cost),


название: nft.title,


описание: nft.description,


отметка времени: nft.timestamp,


.обратный()


экспорт {loadWeb3, connectWallet, payForArt, BASE_URI}


Это такая удобная функциональная структура, которую вы должны использовать в своем последующем блокчейн-проекте. Он объединяет все функции, связанные с блокчейном, и помогает нам сохранять здравомыслие.


Далее давайте обсудим, как наша маленькая, но не такая уж маленькая библиотека управления состоянием координирует всю эту деятельность за кулисами.


Библиотека управления операторами


Фото Pixabay с сайта Pexels


Мы используем пакет react-global-hook для управления состоянием. Настройка избыточности для такого небольшого проекта может быть громоздкой, и зачем вам это, если у вас есть такая простая реализация, как приведенная ниже?


Создайте папку внутри каталога src с именем store, а также создайте в ней файл с именем index.jsx, теперь вставьте коды ниже в файл и сохраните.


```javascript


импорт { createGlobalState } из 'реагировать-хуки-глобальное-состояние'


const { setGlobalState, useGlobalState, getGlobalState } = createGlobalState ({


предупреждение: {показать: ложь, сообщение: '', цвет: ''},


загрузка: {показать: false, сообщение: ''},


контракт: нулевой,


максимальное предложение: 100,


подключенный аккаунт: '',


нфтс: [],


const setAlert = (msg, color = 'green') => {


setGlobalState('предупреждение', {показать: true, сообщение, цвет})


setTimeout(() => {


setGlobalState('предупреждение', {показать: ложь, сообщение: '', цвет})


setGlobalState («загрузка», ложь)


}, 8000)


константа setLoadingMsg = (msg) => {


постоянная загрузка = getGlobalState('загрузка')


setGlobalState('загрузка', {...загрузка, сообщение})


экспорт {


использование GlobalState,


setGlobalState,


получитьGlobalState,


установить оповещение,


setLoadingMsg,


Мы почти закончили здесь…


Папка и файлы ABIs


Файлы ABI


Позвольте мне обратить ваше внимание на эту папку, которая уже не должна быть пустой…


В ЧАСТИ ПЕРВОЙ этой статьи мы указали в truffle -config.js для создания этих файлов в этой папке всякий раз, когда мы компилируем смарт-контракт, поэтому у нас есть эта папка, доступная для нас.


Файлы активов


Папка ресурсов


Я должен сказать, что мы почти закончили, за исключением того, что мы не включили папку с ресурсами и файлы. Сделаем это быстро…


Создайте папку в каталоге src с именем assets, затем загрузите и переместите в нее файл ниже.


Используйте эту ссылку на репозиторий git для загрузки изображений.


Теперь, когда мы закончили со всеми сборками, давайте запустим сервер, выполнив приведенную ниже команду на терминале, чтобы сделать это!


``` ударить


yarn start #запускает сервер на localhost:3000


Поздравляем, вы официально завершили сборку…


Заключение


Вы видели еще один классический пример создания приложения web3. Я твердо верю, что если вы программируете вместе со мной, вы являетесь одной из армий блокчейнов, которых ищет децентрализованный интернет.


В настоящее время я преподаю разработку блокчейна онлайн, если вы хотите углубиться в этот навык, [Вы можете связаться со мной на моем веб-сайте.] (https://daltonic.github.io/)


До следующего раза, всего наилучшего!


Об авторе


Госпел Дарлингтон начал свой путь в качестве инженера-программиста в 2016 году. За эти годы он приобрел полноценные навыки работы со стеками JavaScript, такими как React, ReactNative, VueJs, а теперь и с блокчейном.


В настоящее время он работает фрилансером, создает приложения для клиентов и пишет технические руководства, обучая других тому, что делает он.


Евангелие в Дарлингтоне открыто и доступно для вас. Вы можете связаться с ним на LinkedIn, Facebook, Github или на его веб-сайте.



Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE