Saul  Alaniz

Saul Alaniz

1655745480

Cómo Construir Una DApp Y Alojarla En IPFS Usando Fleek

La etapa de implementación de una aplicación es un paso crucial dentro del proceso de desarrollo. Durante esta etapa, la aplicación pasa de estar alojada localmente a estar disponible para el público objetivo en cualquier parte del mundo.

Con el uso creciente de blockchains en la creación de aplicaciones, es posible que se haya preguntado cómo se alojan las DApps, que interactúan con los contratos inteligentes.

En este tutorial, aprenderá a alojar DApps con Fleek mediante la creación de una aplicación de adopción de mascotas descentralizada de muestra con React, Hardhat y Alchemy. 

Lo que necesitas antes de comenzar este tutorial

Este tutorial contiene varios pasos prácticos. Para seguir, te recomiendo que hagas lo siguiente:

  • Instale React , que usaremos para construir la interfaz de usuario. Estoy usando React v14 en este tutorial.
  • Instale Hardhat , que usaremos como nuestro entorno de desarrollo.
  • Cree una cuenta gratuita para la plataforma de desarrollo blockchain de Alchemy
  • Cree una cuenta gratuita para Fleek , de la que aprenderá más en la siguiente sección
  • Descargue la extensión del navegador MetaMask

MetaMask es una billetera de criptomonedas que permite a los usuarios acceder a DApps a través de un navegador o una aplicación móvil. También querrá una cuenta MetaMask de prueba en una red de prueba de Ethereum para probar contratos inteligentes . Estoy usando Ropsten Test Network en este tutorial.

¿Qué es Fleek?

Fleek es una solución Web3 que tiene como objetivo hacer que el proceso de implementación de sus sitios, DApps y servicios sea fluido. Actualmente, Fleek proporciona una puerta de enlace para alojar sus servicios en el Sistema de archivos interplanetarios (IPFS) o en la computadora de Internet (IC) de Dfinity .

Fleek se describe a sí mismo como el equivalente de Netlify para aplicaciones Web3. Como resultado, encontrará algunas características que son similares a Netlify, como ejecutar compilaciones usando imágenes de Docker y generar vistas previas de implementación.

Según el blog de IPFS , “el principal objetivo de Fleek para 2022 es reestructurar su infraestructura de IPFS para descentralizarla e incentivarla aún más. También incluirá nuevos proveedores de infraestructura Web3 para diferentes piezas de la pila de construcción web”.

Fleek ofrece una solución a un desafío de IPFS en el que el hash de su sitio web cambia cada vez que realiza una actualización, lo que dificulta tener un hash de dirección fijo. Después de la implementación inicial, Fleek construirá, anclará y actualizará su sitio.

Comencemos a construir nuestra DApp de muestra en la siguiente sección e implementémosla usando Fleek. Alojaremos la DApp en IPFS.

 

Creación de una DApp de muestra para implementar en Fleek

En esta sección, construiremos un sistema de seguimiento de adopciones descentralizado para una tienda de mascotas.

Si está familiarizado con Truffle Suite , puede reconocer algunas partes de este ejercicio. La inspiración para esta DApp proviene de la guía Truffle . Llevaremos las cosas un paso más allá usando Alchemy, Hardhat y React.

Para permitirle concentrarse en escribir el contrato inteligente e implementar la DApp, ya he creado el componente y el estado de la interfaz de usuario. El contrato inteligente y el código React estarán contenidos en un solo proyecto.

Simplemente clone la aplicación React de mi repositorio de GitHub para comenzar a escribir el contrato inteligente:

git clone  https://github.com/vickywane/react-web3 

A continuación, cambie el directorio a la carpeta clonada e instale las dependencias enumeradas en el package.jsonarchivo:

# cambiar el directorio cd react-web3 # instalar las dependencias de la aplicación npm install

With the React application set up, let’s proceed to create the pet adoption smart contract.

Creación del contrato inteligente de adopción de mascotas

Dentro del react-web3directorio, cree una carpeta de contratos para almacenar el código de Solidity para nuestro contrato inteligente de adopción de mascotas.

Usando su editor de código, cree un archivo llamado Adoption.soly pegue el código a continuación para crear las variables y funciones necesarias dentro del contrato inteligente, que incluyen:

  • Una matriz de 16 longitudes para almacenar la dirección de cada adoptante de mascotas
  • Una función para adoptar una mascota.
  • Una función para recuperar la dirección de todas las mascotas adoptadas
//SPDX-License-Identifier: Unlicense
// ./react-web3/contracts/Adoption.sol
pragma solidity ^0.8.0;

contract Adoption {
  address[16] public adopters;
  event PetAssigned(address indexed petOwner, uint32 petId);

  // adopting a pet
  function adopt(uint32 petId) public {
    require(petId >= 0 && petId <= 15, "Pet does not exist");

    adopters[petId] = msg.sender;
    emit PetAssigned(msg.sender, petId);
  }

  // Retrieving the adopters
  function getAdopters() public view returns (address[16] memory) {
    return adopters;
  }
}

A continuación, cree otro archivo con el nombre deploy-contract-script.jsdentro de la carpeta de contratos. Pegue el código JavaScript a continuación en el archivo. El código actuará como un script que utiliza el getContractFactorymétodo asincrónico de Hardhat para crear una instancia de fábrica del contrato inteligente de adopción y luego implementarlo.

// react-web3/contract/deploy-contract-script.js
require('dotenv').config()
const { ethers } = require("hardhat");

async function main() {
  // We get the contract to deploy
  const Adoption = await ethers.getContractFactory("Adoption");
  const adoption = await Adoption.deploy();
  await adoption.deployed();

  console.log("Adoption Contract deployed to:", adoption.address);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
});

Finalmente, crea un archivo llamado hardhat.config.js. Este archivo especificará la configuración del casco.

Agregue el siguiente código JavaScript al hardhat.config.jsarchivo para especificar una versión de Solidity y el punto final de URL para su cuenta de red de Ropsten.

require("@nomiclabs/hardhat-waffle");
require('dotenv').config();

/**
 * @type import('hardhat/config').HardhatUserConfig
 */
module.exports = {
  solidity: "0.8.4",
  networks: {
    ropsten: {
      url: process.env.ALCHEMY_API_URL,
      accounts: [`0x${process.env.METAMASK_PRIVATE_KEY}`]
    }
  }
};

Estoy usando las variables de entorno ALCHEMY_API_URLy METAMASK_PRIVATE_KEYpara almacenar la URL y los valores de clave de cuenta privada utilizados para la configuración de red de Ropsten:

  • El METAMASK_PRIVATE_KEYestá asociado con su billetera MetaMask
  • Los ALCHEMY_API_URLenlaces a una aplicación de Alchemy

Puede almacenar y acceder a estas variables de entorno dentro de este react-web3proyecto utilizando un .envarchivo y el dotenvpaquete. Revisaremos cómo hacer esto en la siguiente sección.

Si ha estado siguiendo con éxito, aún no ha creado una aplicación de Alchemy en este punto del proyecto. Necesitará usar su punto final de URL de API, así que procedamos a crear una aplicación en Alchemy.

Crear una aplicación de Alchemy

Alchemy proporciona funciones que le permiten conectarse a un nodo externo de llamada a procedimiento remoto (RPC) para una red. Los nodos RPC hacen posible que su DApp y la cadena de bloques se comuniquen.

Usando su navegador web, navegue hasta el panel web de Alchemy y cree una nueva aplicación.

Proporcione un nombre y una descripción para la aplicación, luego seleccione la red Ropsten. Haga clic en el botón "Crear aplicación" para continuar.

Después de crear la aplicación, la encontrará en la parte inferior de la página.

Haga clic en "Ver clave" para revelar las claves API para la aplicación Alchemy. Tome nota de la URL HTTP. He redactado esta información en la imagen de abajo.

Cree un .envarchivo dentro de su proyecto Hardhat, como se muestra a continuación. Utilizará este .envarchivo para almacenar la URL de su aplicación Alchemy y la clave privada de MetaMask.

// react-web3/.env

ALCHEMY_API_URL=<ALCHEMY_HTTP_URL>
METAMASK_PRIVATE_KEY=<METAMASK_PRIVATE_KEY>

Reemplace los marcadores de posición ALCHEMY_HTTP_URLy METAMASK_PRIVATE_KEYanteriores con la URL HTTP de Alchemy y su clave privada de MetaMask. Siga la guía MetaMask Export Private Key para aprender cómo exportar esta información para su billetera.

Por último, ejecute el siguiente comando para implementar su contrato inteligente de adopción de mascotas en la red Ropsten especificada:

npx hardhat run contracts/deploy-contract-script.js --network ropsten

Como se muestra en la imagen a continuación, tenga en cuenta la dirección que se devuelve a su consola después de implementar el contrato. Necesitará esta dirección en la siguiente sección.

En este punto, se ha implementado el contrato inteligente de adopción de mascotas. Ahora cambiemos el enfoque a la propia DApp y creemos funciones para interactuar con el contrato inteligente de adopción de mascotas.

Construyendo la interfaz DApp

Similar al tutorial de la tienda de mascotas de la guía Truffle, nuestra DApp mostrará dieciséis razas diferentes de perros que se pueden adoptar. La información detallada de cada perro se almacena en el src/pets.jsonarchivo . Estamos usando TailwindCSS para darle estilo a esta DApp.

Para comenzar, abra el state/context.jsarchivo y reemplace el contenido existente con el siguiente código:

// react-web3/state/context.js

import React, {useEffect, useReducer} from "react";
import Web3 from "web3";
import {ethers, providers} from "ethers";

const {abi} = require('../../artifacts/contracts/Adoption.sol/Adoption.json')

if (!abi) {
    throw new Error("Adoptiom.json ABI file missing. Run npx hardhat run contracts/deploy-contract-script.js")
}

export const initialState = {
    isModalOpen: false,
    dispatch: () => {
    },
    showToast: false,
    adoptPet: (id) => {
    },
    retrieveAdopters: (id) => {
    },
};

const {ethereum, web3} = window

const AppContext = React.createContext(initialState);
export default AppContext;

const reducer = (state, action) => {
    switch (action.type) {
        case 'INITIATE_WEB3':
            return {
                ...state,
                isModalOpen: action.payload,
            }
        case 'SENT_TOAST':
            return {
                ...state,
                showToast: action.payload.toastVisibility
            }
        default:
            return state;
    }
};

const createEthContractInstance = () => {
    try {
        const provider = new providers.Web3Provider(ethereum)
        const signer = provider.getSigner()
        const contractAddress = process.env.REACT_APP_ADOPTION_CONTRACT_ADDRESS

        return new ethers.Contract(contractAddress, abi, signer)
    } catch (e) {
        console.log('Unable to create ethereum contract. Error:', e)
    }
}

export const AppProvider = ({children}) => {
    const [state, dispatch] = useReducer(reducer, initialState);

    const instantiateWeb3 = async _ => {
        if (ethereum) {
            try {
                // Request account access
                return await ethereum.request({method: "eth_requestAccounts"})
            } catch (error) {
                // User denied account access...
                console.error("User denied account access")
            }
        } else if (web3) {
            return
        }
        return new Web3(Web3.givenProvider || "ws://localhost:8545")
    }

    const adoptPet = async id => {
        try {
            const instance = createEthContractInstance()
            const accountData = await instantiateWeb3()

            await instance.adopt(id, {from: accountData[0]})

            dispatch({
                type: 'SENT_TOAST', payload: {
                    toastVisibility: true
                }
            })

            // close success toast after 3s
            setTimeout(() => {
                dispatch({
                    type: 'SENT_TOAST', payload: {
                        toastVisibility: false
                    }
                })
            }, 3000)
        } catch (e) {
            console.log("ERROR:", e)
        }
    }

    const retrieveAdopters = async _ => {
        try {
            const instance = createEthContractInstance()
            return await instance.getAdopters()
        } catch (e) {
            console.log("RETRIEVING:", e)
        }
    }

    useEffect(() => {
        (async () => { await instantiateWeb3() })()
    })

    return (
        <AppContext.Provider
            value={{
                ...state,
                dispatch,
                adoptPet,
                retrieveAdopters
            }}
        >
            {children}
        </AppContext.Provider>
    );
};

Al leer el bloque de código anterior, observará lo siguiente:

Los objetos Ethereum y Web3 se desestructuran desde la ventana del navegador. La extensión MetaMask inyectará el objeto Ethereum en el navegador.

La createEthContractInstancefunción auxiliar crea y devuelve una instancia del contrato de adopción de mascotas utilizando la ABI y la dirección del contrato de Alchemy.

La instantiateWeb3función auxiliar recuperará y devolverá la dirección de la cuenta del usuario en una matriz, utilizando MetaMask para verificar que el objeto de la ventana de Ethereum esté definido.

La instantiateWeb3función auxiliar también se ejecuta en un useEffectenlace para garantizar que los usuarios se conecten con MetaMask inmediatamente después de abrir la aplicación en el navegador web.

La adoptPetfunción espera un parámetro numérico petId, crea la instancia del contrato de adopción y recupera la dirección del usuario mediante las funciones auxiliares createEthContractInstancey .instantiateWeb3

El petIdparámetro y la dirección de la cuenta de usuario se pasan al adoptmétodo desde la instancia del contrato de adopción de mascotas para adoptar una mascota.

La retrieveAdoptersfunción ejecuta el getAdoptersmétodo en la instancia de adopción para recuperar la dirección de todas las mascotas adoptadas.

Guarde estos cambios e inicie el servidor de desarrollo de React para ver la DApp de la tienda de mascotas en http://localhost4040/ .

En este punto, las funciones dentro del contrato de adopción se han implementado en el state/context.jsarchivo, pero aún no se han ejecutado. Sin autenticarse con MetaMask, la dirección de la cuenta del usuario no estará definida y todos los botones para adoptar una mascota estarán deshabilitados, como se muestra a continuación:

Procedamos a agregar la dirección del contrato de adopción de mascotas como una variable de entorno y alojemos la DApp en Fleek.

Implementación de React DApp en Fleek

El alojamiento de una DApp en Fleek se puede realizar a través del panel de control de Fleek, la CLI de Fleek o incluso mediante programación mediante Fleek GitHub Actions . En esta sección, aprenderá a usar la CLI de Fleek mientras alojamos la DApp de la tienda de mascotas en IPFS a través de Fleek.

Configuración de la CLI de Fleek

Ejecute el siguiente comando para instalar Fleek CLI globalmente en su computadora:

npm install -g @fleek/cli

Para usar la CLI de Fleek instalada, debe tener una clave API para una cuenta de Fleek almacenada como una variable de entorno en su terminal. Procedamos a generar una clave API para su cuenta utilizando el panel web de Fleek.

Usando su navegador web, navegue hasta el panel de control de su cuenta de Fleek y haga clic en el avatar de su cuenta para mostrar un menú emergente. Dentro de este menú, haga clic en "Configuración" para navegar a la configuración de su cuenta de Fleek.

Dentro de la configuración de su cuenta de Fleek, haga clic en el botón "Generar API" para iniciar el modal "Detalles de API", que generará una clave de API para su cuenta de Fleek.

Tome la clave API generada y reemplace el FLEEK_API_KEYmarcador de posición en el siguiente comando:

export FLEEK_API_KEY='FLEEK_API_KEY'

Ejecute este comando para exportar la clave API de Fleek como una variable de entorno temporal para su terminal de computadora. La CLI de Fleek leerá el valor de la FLEEK_API_KEYvariable cuando ejecute un comando en su cuenta de Fleek.

Inicializar un sitio a través de Fleek CLI

Debe generar los archivos estáticos para React DApp localmente antes de poder alojar la DApp y sus archivos en IPFS usando Fleek.

La generación de archivos estáticos se puede automatizar durante el proceso de compilación especificando una imagen de Docker y los comandos que se usarán para crear sus archivos estáticos. Sin embargo, en este tutorial, generará los archivos estáticos manualmente.

Ejecute el siguiente comando npm para generar archivos estáticos para la DApp en un builddirectorio.

npm run build

A continuación, inicialice un espacio de trabajo del sitio de Fleek dentro de la react-web3carpeta con el siguiente comando:

fleek site:init

El proceso de inicialización es un paso único para cada sitio de Fleek. Fleek CLI iniciará una sesión interactiva que lo guiará a través del proceso de inicialización del sitio.

Durante el proceso de inicialización, se le pedirá que ingrese un teamId, como se ve en la siguiente imagen:

Encontrará sus teamIdnúmeros en la URL del panel de control de Fleek. A continuación se muestra un ejemplo teamId:

En este punto, la CLI de Fleek ha generado un .fleek.jsonarchivo dentro del react-web3directorio con las configuraciones de alojamiento de Fleek. Sin embargo, falta una cosa: la variable de entorno que contiene la dirección del contrato inteligente de adopción de mascotas.

Procedamos a ver cómo agregar variables de entorno para sitios implementados localmente en Fleek.

Agregar una variable de entorno

Fleek permite a los desarrolladores administrar credenciales confidenciales para sus sitios de forma segura, ya sea a través del panel de Fleek o del archivo de configuración. Como está alojando localmente un sitio desde su línea de comandos en este tutorial, especificará su variable de entorno en el .fleek.jsonarchivo.

En el siguiente código, reemplace el ADOPTION_CONTRACT_ADDRESSmarcador de posición con la dirección del contrato inteligente de adopción de mascotas. Recuerde, esta dirección se devolvió después de que creamos la aplicación Alchemy e implementamos el contrato inteligente con el comando npx anteriormente en este tutorial .

 {
  "site": {
    "id": "SITE_ID",
    "team": "TEAM_ID",
    "platform": "ipfs",
    "source": "ipfs",
    "name": "SITE_NAME"
  },
  "build": {
    "baseDir": "",
    "publicDir": "build",
    "rootDir": "",
    "environment": {
       "REACT_APP_ADOPTION_CONTRACT": "ADOPTION_CONTRACT_ADDRESS"
    }
  }
}

Nota: La CLI SITE_IDde Fleek generará automáticamente los marcadores de posición , y en el TEAM_IDarchivo cuando inicialice un sitio de Fleek.SITE_NAME.fleek.json

El código anterior también contiene el siguiente objeto, que debe agregar al objeto de compilación dentro de su .fleek.jsonarchivo:

    "environment": {
       "REACT_APP_ADOPTION_CONTRACT": "ADOPTION_CONTRACT_ADDRESS"
    }

El objeto JSON anterior especifica una imagen acoplable de nodo que utilizará Fleek para crear la DApp. Durante el proceso de compilación, se ejecutarán los comandos npm en el commandcampo.

Ejecute el siguiente comando para volver a implementar la DApp usando la nueva configuración de compilación en el .fleek.jsonarchivo.

fleek site:deploy

¡Felicidades! La DApp se ha implementado por completo y ahora puede acceder al sitio en vivo a través de su navegador web. También puede obtener información más detallada sobre la DApp alojada a través del panel de control de Fleek siguiendo estos pasos:

  • Navega a tu tablero de Fleek
  • Haga clic en el nombre de la DApp que implementó
  • Ver la URL del sitio implementado a la izquierda
  • Vea una imagen de vista previa de implementación a la derecha

Haga clic en la URL del sitio para abrir la DApp en una nueva pestaña del navegador. Se le pedirá que conecte una billetera MetaMask inmediatamente después de que se inicie la DApp. Después de conectar una billetera, podrá adoptar cualquiera de los dieciséis perros haciendo clic en los botones "Adoptar".

¡Eso es todo! Su DApp de adopción de mascotas de muestra se implementó en Fleek.

Conclusión

En este tutorial, nos enfocamos en crear y alojar una DApp de muestra en IPFS a través de Fleek. El proceso comenzó de manera similar al contrato inteligente de adopción de mascotas de la guía de Truffle. Luego, dio un paso más al crear una DApp para interactuar con el contrato inteligente de adopción de mascotas.

Si desea aprovechar los pasos de este tutorial para alojar una DApp lista para producción, le recomiendo que considere lo siguiente:

Primero, asegúrese de conectar Fleek a un proveedor de host de código, como GitHub, e implemente la DApp desde una rama de producción dentro de su repositorio. Esto permitirá que Fleek vuelva a implementar automáticamente la DApp cuando envíe una nueva confirmación de código a la rama implementada.

En segundo lugar, si está utilizando un .fleek.jsonarchivo para almacenar variables de entorno, incluya el nombre del .fleek.jsonarchivo en su .gitignorearchivo. Hacer esto garantizará que el .fleek.jsonarchivo no se inserte y que las variables de entorno no queden expuestas.

Espero que hayas encontrado útil este tutorial. Si tiene alguna pregunta, no dude en compartir un comentario.

Esta historia se publicó originalmente en https://blog.logrocket.com/how-build-dapp-host-ipfs-fleek/

#dapp #fleek  #ipfs 

Cómo Construir Una DApp Y Alojarla En IPFS Usando Fleek

Fleekを使用してDAppを構築し、IPFSでホストする方法

アプリケーションの展開段階は、開発プロセス内の重要なステップです。この段階で、アプリケーションはローカルでホストされるようになり、世界中のターゲットオーディエンスが利用できるようになります。

アプリケーションの構築におけるブロックチェーンの使用が増えるにつれ、スマートコントラクトと相互作用するDAppがどのようにホストされているのか疑問に思われるかもしれません。

このチュートリアルでは、React、Hardhat、およびAlchemyを使用してサンプルの分散型ペットの養子縁組アプリケーションを構築することにより、FleekでDAppをホストする方法を学習します。 

このチュートリアルを開始する前に必要なもの

このチュートリアルには、いくつかの実践的な手順が含まれています。フォローするには、次のことを行うことをお勧めします。

  • UIの構築に使用するReactをインストールします。このチュートリアルではReactv14を使用しています
  • 開発環境として使用するHardhatをインストールします
  • Alchemyブロックチェーン開発者プラットフォームの無料アカウントを作成します
  • Fleekの無料アカウントを作成します。これについては、次のセクションで詳しく説明します。
  • MetaMaskブラウザ拡張機能をダウンロードする

MetaMaskは、ユーザーがブラウザーまたはモバイルアプリを介してDAppにアクセスできるようにする暗号通貨ウォレットです。スマートコントラクトをテストするために、EthereumテストネットでテストMetaMaskアカウントも必要になります。このチュートリアルでは、RopstenTestNetworkを使用しています。

フレークとは何ですか?

Fleekは、サイト、DApp、およびサービスをシームレスに展開するプロセスを作成することを目的としたWeb3ソリューションです。現在、Fleekは、InterPlanetary File System(IPFS)またはDfinityのインターネットコンピューター(IC)でサービスをホストするためのゲートウェイを提供しています。

Fleekは、それ自体をWeb3アプリケーションと同等のNetlifyと表現しています。その結果、Dockerイメージを使用したビルドの実行やデプロイメントプレビューの生成など、Netlifyに類似したいくつかの機能が見つかります。

IPFSブログによると、「2022年のFleekの主な目標は、IPFSインフラストラクチャを再構築して、さらに分散化し、インセンティブを与えることです。また、Web構築スタックのさまざまな部分に対応する新しいWeb3インフラストラクチャプロバイダーも含まれます。」

Fleekは、更新を行うたびにWebサイトのハッシュが変更されるため、固定アドレスハッシュを使用することが困難になるというIPFSの課題に対するソリューションを提供します。最初の展開後、Fleekはサイトを構築、固定、更新します。

次のセクションでサンプルDAppの構築を開始し、Fleekを使用してデプロイしましょう。DAppをIPFSでホストします。

 

FleekにデプロイするサンプルDAppを構築する

このセクションでは、ペットショップ向けの分散型採用追跡システムを構築します。

Truffle Suiteに精通している場合は、この演習の一部に気付くかもしれません。このDAppのインスピレーションは、トリュフガイドから来ています。Alchemy、Hardhat、Reactを使用して、さらに一歩進んでいきます。

スマートコントラクトの作成とDAppのデプロイに集中できるようにするために、私はすでにUIコンポーネントと状態を構築しました。スマートコントラクトとReactコードは単一のプロジェクトに含まれます。

GitHubリポジトリからReactアプリケーションのクローンを作成するだけで、スマートコントラクトの作成を開始できます。

git clone  https://github.com/vickywane/react-web3 

次に、ディレクトリを複製フォルダに変更し、package.jsonファイルにリストされている依存関係をインストールします。

#ディレクトリを変更するcd react-web3#アプリケーションの依存関係をインストールするnpm install

With the React application set up, let’s proceed to create the pet adoption smart contract.

ペットの養子縁組のスマートコントラクトを作成する

ディレクトリ内にreact-web3、ペットの養子縁組のスマートコントラクトのSolidityコードを保存するコントラクトフォルダーを作成します。

コードエディタを使用して、という名前のファイルAdoption.solを作成し、以下のコードに貼り付けて、スマートコントラクト内に必要な変数と関数を作成します。

  • 各ペットの養子縁組の住所を格納する16の長さの配列
  • ペットを養子にする機能
  • 養子となったすべてのペットの住所を取得する機能
//SPDX-License-Identifier: Unlicense
// ./react-web3/contracts/Adoption.sol
pragma solidity ^0.8.0;

contract Adoption {
  address[16] public adopters;
  event PetAssigned(address indexed petOwner, uint32 petId);

  // adopting a pet
  function adopt(uint32 petId) public {
    require(petId >= 0 && petId <= 15, "Pet does not exist");

    adopters[petId] = msg.sender;
    emit PetAssigned(msg.sender, petId);
  }

  // Retrieving the adopters
  function getAdopters() public view returns (address[16] memory) {
    return adopters;
  }
}

deploy-contract-script.js次に、 contractsフォルダー内に名前を付けた別のファイルを作成します。以下のJavaScriptコードをファイルに貼り付けます。このコードはgetContractFactory、Hardhatの非同期メソッドを使用して、養子縁組スマートコントラクトのファクトリインスタンスを作成し、それをデプロイするスクリプトとして機能します。

// react-web3/contract/deploy-contract-script.js
require('dotenv').config()
const { ethers } = require("hardhat");

async function main() {
  // We get the contract to deploy
  const Adoption = await ethers.getContractFactory("Adoption");
  const adoption = await Adoption.deploy();
  await adoption.deployed();

  console.log("Adoption Contract deployed to:", adoption.address);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
});

最後に、というファイルを作成しますhardhat.config.js。このファイルは、ヘルメットの構成を指定します。

次のJavaScriptコードをhardhat.config.jsファイルに追加して、RopstenネットワークアカウントのSolidityバージョンとURLエンドポイントを指定します。

require("@nomiclabs/hardhat-waffle");
require('dotenv').config();

/**
 * @type import('hardhat/config').HardhatUserConfig
 */
module.exports = {
  solidity: "0.8.4",
  networks: {
    ropsten: {
      url: process.env.ALCHEMY_API_URL,
      accounts: [`0x${process.env.METAMASK_PRIVATE_KEY}`]
    }
  }
};

私は環境変数ALCHEMY_API_URLMETAMASK_PRIVATE_KEY使用しており、Ropstenネットワーク構成に使用されるURLとプライベートアカウントキーの値を保存しています。

  • METAMASK_PRIVATE_KEYMetaMaskウォレットに関連付けられています
  • ALCHEMY_API_URLAlchemyアプリケーションへのリンク

ファイルとパッケージを使用して、このプロジェクト内にこれらの環境変数を保存してアクセスできます。これを行う方法については、次のセクションで確認します。react-web3.envdotenv

順調に進んでいる場合は、プロジェクトのこの時点ではまだAlchemyアプリケーションを作成していません。API URLエンドポイントを使用する必要があるので、Alchemyでアプリケーションを作成してみましょう。

Alchemyアプリケーションの作成

Alchemyは、ネットワークの外部リモートプロシージャコール(RPC)ノードに接続できるようにする機能を提供します。RPCノードを使用すると、DAppとブロックチェーンが通信できるようになります。

Webブラウザーを使用して、Alchemy Webダッシュボードに移動し、新しいアプリを作成します。

アプリの名前と説明を入力してから、Ropstenネットワークを選択します。「アプリの作成」ボタンをクリックして続行します。

アプリが作成されると、ページの下部に表示されます。

「キーの表示」をクリックして、AlchemyアプリのAPIキーを表示します。HTTPURLに注意してください。下の画像でこの情報を編集しました。

.env以下に示すように、Hardhatプロジェクト内にファイルを作成します。この.envファイルを使用して、AlchemyアプリのURLとMetaMask秘密鍵を保存します。

// react-web3/.env

ALCHEMY_API_URL=<ALCHEMY_HTTP_URL>
METAMASK_PRIVATE_KEY=<METAMASK_PRIVATE_KEY>

上記のALCHEMY_HTTP_URLandMETAMASK_PRIVATE_KEYプレースホルダーを、AlchemyのHTTPURLとMetaMask秘密鍵に置き換えます。MetaMaskエクスポート秘密鍵ガイドに従って、この情報をウォレットにエクスポートする方法を学習してください。

最後に、次のコマンドを実行して、ペットの養子縁組のスマートコントラクトを指定されたRopstenネットワークにデプロイします。

npx hardhat run contracts/deploy-contract-script.js --network ropsten

次の画像に示すように、コントラクトがデプロイされた後にコンソールに返されるアドレスに注意してください。このアドレスは次のセクションで必要になります。

この時点で、ペットの養子縁組のスマートコントラクトが展開されています。次に、焦点をDApp自体に移し、ペットの養子縁組のスマートコントラクトと対話するための関数を作成しましょう。

DAppフロントエンドの構築

トリュフガイドのペットショップのチュートリアルと同様に、DAppには養子縁組できる16種類の犬が表示されます。各犬の詳細情報はsrc/pets.jsonファイルに保存されます。このDAppのスタイルを設定するためにTailwindCSSを使用しています。

まず、state/context.jsファイルを開き、既存のコンテンツを次のコードに置き換えます。

// react-web3/state/context.js

import React, {useEffect, useReducer} from "react";
import Web3 from "web3";
import {ethers, providers} from "ethers";

const {abi} = require('../../artifacts/contracts/Adoption.sol/Adoption.json')

if (!abi) {
    throw new Error("Adoptiom.json ABI file missing. Run npx hardhat run contracts/deploy-contract-script.js")
}

export const initialState = {
    isModalOpen: false,
    dispatch: () => {
    },
    showToast: false,
    adoptPet: (id) => {
    },
    retrieveAdopters: (id) => {
    },
};

const {ethereum, web3} = window

const AppContext = React.createContext(initialState);
export default AppContext;

const reducer = (state, action) => {
    switch (action.type) {
        case 'INITIATE_WEB3':
            return {
                ...state,
                isModalOpen: action.payload,
            }
        case 'SENT_TOAST':
            return {
                ...state,
                showToast: action.payload.toastVisibility
            }
        default:
            return state;
    }
};

const createEthContractInstance = () => {
    try {
        const provider = new providers.Web3Provider(ethereum)
        const signer = provider.getSigner()
        const contractAddress = process.env.REACT_APP_ADOPTION_CONTRACT_ADDRESS

        return new ethers.Contract(contractAddress, abi, signer)
    } catch (e) {
        console.log('Unable to create ethereum contract. Error:', e)
    }
}

export const AppProvider = ({children}) => {
    const [state, dispatch] = useReducer(reducer, initialState);

    const instantiateWeb3 = async _ => {
        if (ethereum) {
            try {
                // Request account access
                return await ethereum.request({method: "eth_requestAccounts"})
            } catch (error) {
                // User denied account access...
                console.error("User denied account access")
            }
        } else if (web3) {
            return
        }
        return new Web3(Web3.givenProvider || "ws://localhost:8545")
    }

    const adoptPet = async id => {
        try {
            const instance = createEthContractInstance()
            const accountData = await instantiateWeb3()

            await instance.adopt(id, {from: accountData[0]})

            dispatch({
                type: 'SENT_TOAST', payload: {
                    toastVisibility: true
                }
            })

            // close success toast after 3s
            setTimeout(() => {
                dispatch({
                    type: 'SENT_TOAST', payload: {
                        toastVisibility: false
                    }
                })
            }, 3000)
        } catch (e) {
            console.log("ERROR:", e)
        }
    }

    const retrieveAdopters = async _ => {
        try {
            const instance = createEthContractInstance()
            return await instance.getAdopters()
        } catch (e) {
            console.log("RETRIEVING:", e)
        }
    }

    useEffect(() => {
        (async () => { await instantiateWeb3() })()
    })

    return (
        <AppContext.Provider
            value={{
                ...state,
                dispatch,
                adoptPet,
                retrieveAdopters
            }}
        >
            {children}
        </AppContext.Provider>
    );
};

上記のコードブロックを読むと、次のことがわかります。

イーサリアムとWeb3オブジェクトは、ブラウザウィンドウから分解されます。MetaMask拡張機能は、Ethereumオブジェクトをブラウザーに挿入します。

ヘルパー関数はcreateEthContractInstance、契約のABIとAlchemyからのアドレスを使用して、ペットの養子縁組契約のインスタンスを作成して返します。

ヘルパー関数は、instantiateWeb3MetaMaskを使用してEthereumウィンドウオブジェクトが定義されていることを確認し、配列内のユーザーのアカウントアドレスを取得して返します。

instantiateWeb3ヘルパー関数もフックで実行され、ユーザーuseEffectがWebブラウザーでアプリケーションを開いた直後にMetaMaskに接続できるようにします。

このadoptPet関数は数値petIdパラメーターを期待し、Adoptionコントラクトインスタンスを作成し、createEthContractInstanceおよびinstantiateWeb3ヘルパー関数を使用してユーザーのアドレスを取得します。

パラメータとユーザーアカウントアドレスは、ペットの養子縁組契約インスタンスからメソッドpetIdに渡され、ペットを養子縁組します。adopt

このretrieveAdopters関数はgetAdopters、Adoptionインスタンスでメソッドを実行して、採用されたすべてのペットのアドレスを取得します。

これらの変更を保存し、React開発サーバーを起動して、 http://localhost4040/にあるペットショップのDAppを表示します。

この時点で、養子縁組契約内の機能はstate/context.jsファイルに実装されていますが、まだ実行されていません。以下に示すように、MetaMaskで認証しないと、ユーザーのアカウントアドレスは未定義になり、ペットを養子にするためのすべてのボタンが無効になります。

ペットの養子縁組契約アドレスを環境変数として追加し、FleekでDAppをホストしてみましょう。

ReactDAppをFleekにデプロイする

FleekでDAppをホストするには、Fleekダッシュボード、Fleek CLIを使用するか、FleekGitHubActionsをプログラムで使用することもできます。このセクションでは、Fleekを介してIPFSでペットショップDAppをホストするときにFleekCLIを使用する方法を学習します。

FleekCLIの設定

以下のコマンドを実行して、FleekCLIをコンピューターにグローバルにインストールします。

npm install -g @fleek/cli

インストールされたFleekCLIを使用するには、FleekアカウントのAPIキーを環境変数としてターミナルに保存する必要があります。Fleek Webダッシュボードを使用して、アカウントのAPIキーの生成に進みましょう。

Webブラウザーを使用して、Fleekアカウントダッシュボードに移動し、アカウントアバターをクリックして、ポップアップメニューを表示します。このメニュー内で、「設定」をクリックして、Fleekアカウント設定に移動します。

Fleekアカウント設定内で、[Generate API]ボタンをクリックして、[API Details]モーダルを起動します。これにより、FleekアカウントのAPIキーが生成されます。

FLEEK_API_KEY生成されたAPIキーを取得し、以下のコマンドでプレースホルダーを置き換えます。

export FLEEK_API_KEY='FLEEK_API_KEY'

このコマンドを実行して、FleekAPIキーをコンピューター端末の一時的な環境変数としてエクスポートします。FLEEK_API_KEYFleekアカウントに対してコマンドを実行すると、FleekCLIは変数の値を読み取ります。

FleekCLIを使用してサイトを初期化する

Fleekを使用してIPFSでDAppとそのファイルをホストする前に、ReactDAppの静的ファイルをローカルで生成する必要があります。

静的ファイルの生成は、Dockerイメージと静的ファイルのビルドに使用するコマンドを指定することにより、ビルドプロセス中に自動化できます。ただし、このチュートリアルでは、静的ファイルを手動で生成します。

以下のnpmコマンドを実行して、ディレクトリにDAppの静的ファイルを生成しますbuild

npm run build

react-web3次に、次のコマンドを使用して、フォルダー内のFleekサイトワークスペースを初期化します。

fleek site:init

初期化プロセスは、Fleekサイトごとに1回限りのステップです。Fleek CLIは、サイトを初期化するプロセスをガイドするインタラクティブセッションを開始します。

次の図に示すように、初期化プロセス中に、を入力するように求めteamIdられます。

teamIdFleekダッシュボードのURL内に番号が表示されます。例teamIdを以下に示します。

この時点で、Fleek CLIは、Fleekのホスティング構成を使用し.fleek.jsonてディレクトリ内にファイルを生成しました。react-web3ただし、1つ欠けているのは、ペットの養子縁組のスマートコントラクトアドレスを含む環境変数です。

Fleekにローカルにデプロイされたサイトの環境変数を追加する方法を見てみましょう。

環境変数の追加

Fleekを使用すると、開発者はFleekダッシュボードまたは構成ファイルを介してサイトの機密性の高いクレデンシャルを安全に管理できます。このチュートリアルでは、コマンドラインからサイトをローカルでホストしているため、.fleek.jsonファイルで環境変数を指定します。

以下のコードで、ADOPTION_CONTRACT_ADDRESSプレースホルダーをペットの養子縁組のスマートコントラクトアドレスに置き換えます。このアドレスは、Alchemyアプリケーションを作成し、このチュートリアルの前半でnpxコマンドを使用してスマートコントラクトをデプロイした後に返されたことを忘れないでください。

 {
  "site": {
    "id": "SITE_ID",
    "team": "TEAM_ID",
    "platform": "ipfs",
    "source": "ipfs",
    "name": "SITE_NAME"
  },
  "build": {
    "baseDir": "",
    "publicDir": "build",
    "rootDir": "",
    "environment": {
       "REACT_APP_ADOPTION_CONTRACT": "ADOPTION_CONTRACT_ADDRESS"
    }
  }
}

注:SITE_ID、、、TEAM_IDおよびプレースホルダーは、Fleekサイトを初期化するときSITE_NAMEに、ファイル内のFleekCLIによって自動的に生成されます。.fleek.json

.fleek.json上記のコードには、ファイル内のビルドオブジェクトに追加する必要がある次のオブジェクトも含まれています。

    "environment": {
       "REACT_APP_ADOPTION_CONTRACT": "ADOPTION_CONTRACT_ADDRESS"
    }

上記のJSONオブジェクトは、FleekがDAppの構築に使用するノードDockerイメージを指定します。commandビルドプロセス中に、フィールドのnpmコマンドが実行されます。

以下のコマンドを実行して、ファイル内の新しいビルド構成を使用してDAppを再デプロイし.fleek.jsonます。

fleek site:deploy

おめでとう!DAppが完全にデプロイされ、Webブラウザーからライブサイトにアクセスできるようになりました。次の手順に従って、FleekダッシュボードからホストされたDAppに関する詳細情報を取得することもできます。

  • Fleekダッシュボードに移動します
  • デプロイしたDAppの名前をクリックします
  • 左側のデプロイされたサイトのURLを参照してください
  • 右側のデプロイプレビューイメージを参照してください

サイトのURLをクリックして、新しいブラウザタブでDAppを開きます。DAppが起動するとすぐに、MetaMaskウォレットを接続するように求められます。ウォレットが接続されたら、「採用」ボタンをクリックして、16匹の犬のいずれかを採用することができます。

それでおしまい!サンプルのペットの養子縁組DAppがFleekにデプロイされました。

結論

このチュートリアルでは、Fleekを介してIPFSでサンプルDAppを構築してホストすることに焦点を当てました。プロセスは、トリュフのガイドからのペットの養子縁組のスマートコントラクトと同様に始まりました。次に、ペットの養子縁組のスマートコントラクトと対話するためのDAppを構築することで、さらに一歩進んだ。

このチュートリアル内の手順を活用して本番環境に対応したDAppをホストする場合は、次のことを検討することを強くお勧めします。

まず、FleekをGitHubなどのコードホストプロバイダーに接続し、リポジトリ内の本番ブランチからDAppをデプロイするようにしてください。これにより、デプロイされたブランチに新しいコードコミットをプッシュしたときに、FleekがDAppを自動的に再デプロイできるようになります。

次に、.fleek.jsonファイルを使用して環境変数を保存している場合は、.fleek.jsonファイルにファイル名を含め.gitignoreます。これを行うと、.fleek.jsonファイルがプッシュされず、環境変数が公開されなくなります。

このチュートリアルがお役に立てば幸いです。ご不明な点がございましたら、お気軽にコメントをお寄せください。

このストーリーは、もともとhttps://blog.logrocket.com/how-build-dapp-host-ipfs-fleek/で公開されました

#dapp #fleek  #ipfs 

Fleekを使用してDAppを構築し、IPFSでホストする方法