WEB3DEV

Cover image for Como construir um Mercado de NFTs do Reddit Usando a Polygon e o Paper
Panegali
Panegali

Posted on

Como construir um Mercado de NFTs do Reddit Usando a Polygon e o Paper

Construindo o login por e-mail no Mercado de NFT usando Paper na rede Polygon


ÍNDICE

O Sucesso do Reddit com NFTs até Agora

Evite Usar a Metamask Como Única Carteira para seu DApp

Motivos para a Má Experiência do Usuário (UX) na Maioria dos DApps

Uma Abordagem Alternativa para o Login em DApps

Solução do Paper para uma Má Experiência do Usuário

Vamos Construir Nosso Próprio Mercado

Funcionalidades

Pilha de Tecnologia

Pré-requisitos

Configuração do Ambiente

Inicializando o SDK do Paper

Habilitando o Login por E-mail

Compra e Transferência de NFT com um Único Clique

Resumo


De fato, no cenário atual, poucos mercados de NFT atendem aos usuários não-Web3, principalmente devido à má Experiência do Usuário (UX) que eles enfrentam.

Uma barreira significativa para esses usuários é a complexidade do ecossistema Web3, incluindo a necessidade de entender conceitos como carteiras, chaves privadas e taxas de gás. Além disso, o processo de integração pode ser tedioso e confuso, com os usuários tendo que configurar e gerenciar carteiras e adquirir criptomoedas para interagir com o mercado. Para resolver esses problemas e tornar os mercados de NFT mais acessíveis aos usuários não-Web3, é essencial focar na melhoria da UX.

Neste guia, você aprenderá como criar um mercado na Polygon e torná-lo fácil para os não usuários de criptomoedas usarem o mercado, permitindo que eles façam login com seus e-mails e transfiram NFTs com um único clique.

O Sucesso do Reddit com NFTs até o Momento

O Reddit é talvez o melhor exemplo de uma empresa que trouxe NFTs para as massas. Até agora, eles levaram NFTs para mais de 7 milhões de pessoas.

Os avatares do Reddit foram um grande sucesso, em parte porque a maioria dos clientes nem mesmo sabe que está usando NFTs. Eles os consideram como colecionáveis digitais.

O Reddit tornou a experiência de reivindicar (e agora comprar) NFTs perfeita. Os usuários não precisam saber nada sobre a Metamask, não precisam ter criptomoedas e não precisam se preocupar em lembrar suas frases-chave.

Se queremos que os NFTs alcancem ainda mais pessoas, devemos aprender com o sucesso do Reddit: tornar os NFTs simples para os usuários não nativos de criptomoedas aumentará a adoção.

Por isso, criei este guia: qualquer pessoa pode facilmente copiar o que funcionou para o Reddit, oferecendo especificamente o login baseado em e-mail e pagamentos via cartão de crédito. Faremos isso usando a Polygon (ótima para transações de baixo custo) e o [Paper] (SDKs para comércio de NFTs).

Evite Usar a MetaMask Como Única Carteira para seu DApp

Aqui estão os principais motivos pelos quais você deve evitar depender apenas da MetaMask:

  1. Conhecimento limitado sobre Web3 pode fazer com que usuários comuns hesitem em usar a MetaMask.
  2. Instalar e conectar a carteira a seu DApp pode confundir muitos usuários.
  3. Gerenciar chaves privadas pode ser complexo e trazer preocupações significativas para os usuários e o produto. Como não há solução para recuperar uma chave privada uma vez que ela é perdida ou roubada, isso representa um problema considerável.

Motivos para a Má Experiência do Usuário (UX) na Maioria dos DApps

Todo DApp tem como objetivo alcançar a descentralização para aproveitar plenamente o potencial da tecnologia blockchain. Para fazer isso, eles muitas vezes dependem de carteiras tradicionais que oferecem segurança e descentralização. No entanto, como no Trilema da Blockchain, esses DApps podem precisar de ajuda com escalabilidade.

Para os usuários que conseguem criar uma carteira e armazenar suas chaves privadas "de forma segura", o próximo desafio surge ao lidar com fundos. Os usuários precisam converter criptomoedas e, em seguida, gastá-las para interagir com o DApp, o que dificulta bastante a integração de novos usuários.

Vários outros fatores contribuem para uma má experiência do usuário, como a necessidade de assinar cada interação, ter a carteira sempre acessível, entre outros. Esses problemas podem criar uma experiência geral negativa para os usuários.

Uma Abordagem Alternativa para o Login em DApps

Em vez de depender de contas de propriedade externa (EOAs), os desenvolvedores podem criar contratos inteligentes que atuam como contas de usuário e executam transações em nome do usuário. Essa abordagem pode melhorar a integração de novos usuários e a experiência geral do usuário no DApp.

Vários Propostas de Melhoria da Ethereum (EIP) tentam definir o conceito de usar contratos inteligentes como carteiras. Após nove anos de pesquisa, a EIP-4337 foi oficialmente aprovada para a abstração de contas (AA).

A abstração de contas oferece lógica personalizável para criação de carteira, pagamento de taxas de gás de transação e tokens alternativos em vez de Ether para taxas de gás. Uma opção é criar uma carteira usando um endereço de e-mail, onde o e-mail do usuário gera uma chave privada. Essa chave é então dividida usando funções criptográficas e compartilhada entre o dispositivo do usuário e os provedores de serviços de aplicativos. O provedor de serviços pode então pagar as taxas de gás da transação, assinar transações e ajudar os usuários na recuperação da chave privada.

A Solução do Paper para uma Má Experiência do Usuário (UX)

O Paper oferece um SDK de carteira incorporada (Embedded Wallet SDK) que ajuda a resolver problemas de experiência do usuário, fornecendo as seguintes funcionalidades:

  1. Criar carteiras de usuário usando e-mails ou logins sociais.
  2. Assinar mensagens ou chamar métodos de blockchain sem exigir prompts ou taxas de gás.
  3. Permite que os usuários acessem ou recuperem suas carteiras em qualquer dispositivo.
  4. Permite que os usuários se conectem a outros aplicativos por meio do WalletConnect.

O Paper ajuda os desenvolvedores a criar experiências de usuário contínuas e expandir seus aplicativos sem precisar configurar sua própria infraestrutura.

Vamos CONSTRUIR Nosso Próprio Mercado

Hoje, vamos construir um mercado de NFT para minimizar o atrito na integração de usuários não-Web3. Faremos isso oferecendo a opção de criar uma carteira usando qualquer endereço de e-mail e possibilitando transferências de NFT sem taxas de gás.

Funcionalidades

Implementaremos as seguintes funcionalidades em nosso mercado:

  1. Login por e-mail para o DApp.
  2. Compra e transferência de NFT com um único clique.

Pilha de Tecnologia

Construiremos o mercado com as seguintes tecnologias:

  1. React.js
  2. Ethers.js
  3. SDK de carteira incorporada do Paper

Pré-requisitos

  • NPM ou Yarn instalado no seu sistema.
  • Compreensão básica do React.js.

Configuração do Ambiente

Para configurar o código inicial (contrato + UI) [Agradecimentos ao OMGWINNING por isso], abra seu terminal no diretório de sua preferência e digite os seguintes comandos:


git clone https://github.com/megabyte0x/NFT-Marketplace-Starter_Code.git

cd NFT-Marketplace-Starter_Code

npm install

Enter fullscreen mode Exit fullscreen mode

Crie um novo arquivo no diretório raiz chamado .env e cole o seguinte conteúdo:


REACT_APP_ALCHEMY_API_URL="<Cole o URL da Alchemy aqui>"

REACT_APP_PRIVATE_KEY="<Cole sua Chave Privada aqui>"

REACT_APP_PINATA_KEY="<Cole a chave da Pinata aqui>"

REACT_APP_PINATA_SECRET="<Cole a Chave Secreta da Pinata aqui>"

REACT_APP_PAPER_SECRET="<Cole a chave secreta do Paper SDK aqui>"

Enter fullscreen mode Exit fullscreen mode

Obtenha os valores necessários ao se inscrever na Alchemy, Pinata e Paper.


npm install @paperxyz/embedded-wallet-service-sdk

Enter fullscreen mode Exit fullscreen mode

Por fim, inicie o servidor de desenvolvimento com o seguinte comando:


npm start

Enter fullscreen mode Exit fullscreen mode

Seu ambiente de desenvolvimento está pronto!

Inicializando o Paper SDK

Crie um arquivo na pasta src chamado paper.js. É aqui que inicializaremos o SDK.

Copie e cole o seguinte código:


import { PaperEmbeddedWalletSdk } from "@paperxyz/embedded-wallet-service-sdk";

import { UserStatus } from "@paperxyz/embedded-wallet-service-sdk";

export const sdk = new PaperEmbeddedWalletSdk({

  clientId: process.env.REACT_APP_PAPER_SECRET,

  chain: "Mumbai",

});

export const socialLogin = async () => {

  try {

    await sdk.auth.loginWithPaperModal();

    return sdk.getUser();

  } catch (e) {

    console.log(e);

  }

};

export const socialLogout = async () => {

  try {

    await sdk.auth.logout();

  } catch (e) {

    console.log(e);

  }

};

export const getUser = async () => {

  const user = await sdk.getUser();

  return user;

};

export const getSigner = async () => {

  let signer;

  const user = await getUser();

  if (user.status === UserStatus.LOGGED_OUT) {

    return;

  }

  try {

    signer = await getUser().then((user) => {

      return user.wallet.getEthersJsSigner();

    });

  } catch (e) {

    console.log(e);

  }

  return signer;

};

Enter fullscreen mode Exit fullscreen mode
  • sdk inicializa o SDK de carteira incorporada do Paper, passando nossa Chave Secreta do Paper e a cadeia que estaremos usando, "Mumbai".
  • socialLogin é a função que abre o modal para login social usando e-mail.
  • socialLogout é a função para desconectar o usuário.
  • getUser é a função que recupera informações sobre o usuário, como sua carteira e endereço da carteira.
  • getSigner é uma função que retorna o signer Ethereum para assinar transações.

Agora que inicializamos nosso SDK, vamos conectá-lo ao restante do código.

Habilitando o Login por E-mail

Já que o Navbar é o componente que nos ajudará a conectar a carteira, vamos para src/components/Navbar.js

Copie e cole isso:


import { Link } from "react-router-dom";

import { useEffect, useState } from 'react';

import { useLocation } from 'react-router';

import { socialLogin, socialLogout, getUser } from "../paper.js";

import { UserStatus } from "@paperxyz/embedded-wallet-service-sdk";

function Navbar() {

  const [connected, toggleConnect] = useState(false);

  const location = useLocation();

  const [currentAddress, updateAddress] = useState('0x');

  const [currentUser, updateUser] = useState(null);

  function updateButton() {

    const ethereumButton = document.querySelector('.enableEthereumButton');

    ethereumButton.classList.remove("hover:bg-blue-70");

    ethereumButton.classList.remove("bg-blue-500");

    ethereumButton.classList.add("hover:bg-green-70");

    ethereumButton.classList add("bg-green-500");

  }

  async function connectWithPaperWallet() {

    try {

      await socialLogin().then((user) => {

        if (UserStatus.LOGGED_IN_WALLET_INITIALIZED === user.status) {

          setUser();

        }

      });

    } catch (e) {

      console.log(e);

    }

  }

  async function logout() {

    try {

      await socialLogout().then(() => {

        setUser();

      });

    } catch (error) {

      console.log(error);

    };

  }

  async function setUser() {

    try {

      await getUser().then((user) => {

        if (user.status === UserStatus.LOGGED_OUT) {

          toggleConnect(false);

          updateUser(null);

          updateAddress('0x');

          return;

        }

        updateUser(user);

        updateAddress(user.walletAddress);

        toggleConnect(true);

        updateButton();

      })

    } catch (error) {

      console.error(error);

    }

  }

  useEffect(() => {

    setUser();

  }, [currentUser]);

}

export default Navbar;

Enter fullscreen mode Exit fullscreen mode

Aqui, definimos várias variáveis de estado e algumas funções para conectar a carteira usando o SDK do Paper:

  • updateButton() atualiza a interface do usuário para o botão de Connect Wallet (Conectar Carteira).
  • connectWithPaperWallet() usa a função socialLogin definida em paper.js para abrir um modal no qual os usuários podem fazer login usando seu e-mail. Se o usuário fizer login com sucesso, atualizaremos o estado de currentUser e currentAddress.
  • A função logout() usa a função socialLogout definida em paper.js para fazer o logout do usuário atual. Isso garante que, quando o usuário clicar no botão de logout, sua sessão será encerrada e sua carteira será desconectada do DApp.
  • Da mesma forma, a função setUser() é chamada sempre que connectWithPaperWallet() ou logout() são acionados. Essa função configura as variáveis de estado, como currentUser, currentAddress e connected. Ela obtém as informações mais recentes do usuário e atualiza as variáveis de estado de acordo. Isso atualiza a interface do usuário com o status de conexão do usuário e garante uma experiência tranquila para o usuário.
  • useEffect é iniciado quando currentUser muda, recuperando as últimas alterações no estado do usuário e atualizando as variáveis de estado de acordo.

Em seguida, vamos criar o componente de retorno:


import { Link } from "react-router-dom";

import { useEffect, useState } from 'react';

import { useLocation } from 'react-router';

import { socialLogin, socialLogout, getUser } from "../paper.js";

import { UserStatus } from "@paperxyz/embedded-wallet-service-sdk";

function Navbar() {

  const [connected, toggleConnect] = useState(false);

  const location = useLocation();

  const [currentAddress, updateAddress] = useState('0x');

  const [currentUser, updateUser] = useState(null);

  function updateButton() {

    const ethereumButton = document.querySelector('.enableEthereumButton');

    ethereumButton.classList.remove("hover:bg-blue-70");

    ethereumButton.classList.remove("bg-blue-500");

    ethereumButton.classList.add("hover:bg-green-70");

    ethereumButton.classList.add("bg-green-500");

  }

  async function connectWithPaperWallet() {

    try {

      await socialLogin().then((user) => {

        if (UserStatus.LOGGED_IN_WALLET_INITIALIZED === user.status) {

          setUser();

        }

      });

    } catch (e) {

      console.log(e);

    }

  }

  async function logout() {

    try {

      await socialLogout().then(() => {

        setUser();

      });

    } catch (error) {

      console.log(error);

    };

  }

  async function setUser() {

    try {

      await getUser().then((user) => {

        if (user.status === UserStatus.LOGGED_OUT) {

          toggleConnect(false);

          updateUser(null);

          updateAddress('0x');

          return;

        }

        updateUser(user);

        updateAddress(user.walletAddress);

        toggleConnect(true);

        updateButton();

      })

    } catch (error) {

      console.error(error);

    }

  }

  useEffect(() => {

    setUser();

  }, [currentUser]);

  return (

    <div className="">

      <nav className="w-screen">

        <ul className='flex items-end justify-between py-3 bg-transparent text-white pr-5'>

          <li className='flex items-end ml-5 pb-2'>

            <Link to="/">

              <div className='inline-block font-bold text-xl ml-2'>

                NFT Marketplace

              </div>

            </Link>

          </li>

          <li className='w-2/6'>

            <ul className='lg:flex justify-between font-bold mr-10 text-lg'>

              {location.pathname === "/" ?

                <li className='border-b-2 hover:pb-0 p-2'>

                  <Link to="/">Marketplace</Link>

                </li>


<p id="gdcalert1" ><span style="color: red; font-weight: bold">>>>>>  gd2md-html alert: Definition &darr;&darr; outside of definition list. Missing preceding term(s)? </span><br>(<a href="#">Back to top</a>)(<a href="#gdcalert2">Next alert</a>)<br><span style="color: red; font-weight: bold">>>>>> </span></p>


                :

                &lt;li className='hover:border-b-2 hover:pb-0 p-2'>

                  &lt;Link to="/">Marketplace&lt;/Link>

                &lt;/li>

              }

              {location.pathname === "/sellNFT" ?

                &lt;li className='border-b-2 hover:pb-0 p-2'>

                  &lt;Link to="/sellNFT">List My NFT&lt;/Link>

                &lt;/li>


<p id="gdcalert2" ><span style="color: red; font-weight: bold">>>>>>  gd2md-html alert: Definition &darr;&darr; outside of definition list. Missing preceding term(s)? </span><br>(<a href="#">Back to top</a>)(<a href="#gdcalert3">Next alert</a>)<br><span style="color: red; font-weight: bold">>>>>> </span></p>


                :

                &lt;li className='hover:border-b-2 hover:pb-0 p-2'>

                  &lt;Link to="/sellNFT">List My NFT&lt;/Link>

                &lt;/li>

              }

              {location.pathname === "/profile" ?

                &lt;li className='border-b-2 hover:pb-0 p-2'>

                  &lt;Link to="/profile">Profile&lt;/Link>

                &lt;/li>


<p id="gdcalert3" ><span style="color: red; font-weight: bold">>>>>>  gd2md-html alert: Definition &darr;&darr; outside of definition list. Missing preceding term(s)? </span><br>(<a href="#">Back to top</a>)(<a href="#gdcalert4">Next alert</a>)<br><span style="color: red; font-weight: bold">>>>>> </span></p>


                :

                &lt;li className='hover:border-b-2 hover:pb-0 p-2'>

                  &lt;Link to="/profile">Profile&lt;/Link>

                &lt;/li>

              }

              &lt;li>

                &lt;button className="enableEthereumButton bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-sm" onClick={connectWithPaperWallet}>{connected ? "Connected" : "Connect Wallet"}&lt;/button>

              &lt;/li>

              &lt;li>

                {connected && &lt;button className="enableEthereumButton bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-sm" onClick={logout}>Logout&lt;/button>}

              &lt;/li>

            &lt;/ul>

          &lt;/li>

        &lt;/ul>

      &lt;/nav>

      &lt;div className='text-white text-bold text-right mr-10 text-sm'>

        {currentAddress !== "0x" ? "Connected to" : "Not Connected. Please login to view NFTs"} {currentAddress !== "0x" ? currentAddress : ""}

      &lt;/div>

    &lt;/div>

  );

}

export default Navbar;

Enter fullscreen mode Exit fullscreen mode

Aqui, criamos uma barra de navegação básica para ajudar a navegar nas páginas "Marketplace" (Mercado), "List My NFT" (Listar Meus NFT) e "Profile" (Perfil). Também incluímos um botão dinâmico "Connect Wallet" (Conectar Carteira) que iniciará a função connectWithPaperWallet e um botão Logout (Sair) que acionará a função logout.

Compra (buy) e Transferência (transfer) de NFT com um Único Clique

Vamos para o arquivo src/components/NFTPage.js.

Copie e cole o código abaixo:


importaxios from "axios";

import { useParams } from 'react-router-dom';

import { useState } from "react";

import { ethers } from "ethers";

import Navbar from "./Navbar.js";

import { getSigner, getUser } from "../paper.js";

import MarketplaceJSON from "../Marketplace.json";

export default function NFTPage(props) {

    const [data, updateData] = useState({});

    const [dataFetched, updateDataFetched] = useState(false);

    const [message, updateMessage] = useState("");

    const [currAddress, updateCurrAddress] = useState("0x");

    const [recieverAddress, updateRecieverAddress] = useState("0x");

    async function getNFTData(tokenId) {

        const signer = await getSigner();

        const user = await getUser();

        const addr = await user.walletAddress;

        // Extrai a instância do contrato implantado

        let contract = new ethers.Contract(MarketplaceJSON.address, MarketplaceJSON.abi, signer)

        // Cria um Token NFT

        const tokenURI = await contract.tokenURI(tokenId);

        const listedToken = await contract.getListedTokenForId(tokenId);

        let meta = await axios.get(tokenURI);

        meta = meta.data;

        let item = {

            price: meta.price,

            tokenId: tokenId,

            seller: listedToken.seller,

            owner: listedToken.owner,

            image: meta.image,

            name: meta.name,

            description: meta.description,

        }

        updateData(item);

        updateDataFetched(true);

        updateCurrAddress(addr);

    }

    async function buyNFT(tokenId) {

        try {

            const signer = await getSigner();

            updateMessage("Comprando o NFT... Por favor, aguarde (Até 1 minuto)")

            const funcInterface = new ethers.utils.Interface(["function executeSale(uint256 tokenId) public"]);

            const dataToSend = funcInterface.encodeFunctionData("executeSale", [tokenId]);

            let tx = {

                to: MarketplaceJSON.address,

                value: ethers.utils.parseEther(data.price),

                data: dataToSend

            };

            const txResponse = await signer.sendTransaction(tx);

            const txReceipt = await txResponse.wait();

            console.log("Transação enviada:", txReceipt.transactionHash);

            alert('Você comprou o NFT com sucesso!');

            updateMessage("");

        }

        catch (e) {

            alert("Erro de Upload" + e)

        }

    }

    async function transferNFT(tokenId) {

        try {

            const signer = await getSigner();

            // Extrai a instância do contrato implantado

            let contract = new ethers.Contract(MarketplaceJSON.address, MarketplaceJSON.abi, signer);

            updateMessage("Transferindo o NFT... Por favor, aguarde (Até 1 minuto)")

            // Executa a função transferNFT

            let transaction = await contract.transferNFT(tokenId, recieverAddress);

            await transaction.wait();

            alert(Você transferiu o NFT com sucesso!);

            updateMessage("");

        }

        catch (e) {

            alert("Erro de Upload" + e)

        }

    }

    const params = useParams();

    const tokenId = params.tokenId;

    if (!dataFetched)

        getNFTData(tokenId);

}

Enter fullscreen mode Exit fullscreen mode

O componente NFTPage é uma página separada que inclui duas funções: uma para comprar NFTs e outra para transferir NFTs. Vamos entender como cada função funciona em detalhes:

  1. getNFTData(): esta função busca os dados de um NFT específico usando seu tokenId.
  2. buyNFT(): esta função transfere o NFT e o preço do vendedor para o comprador. Ela usa o signer para fazer transações e codifica os dados para o contrato. sendTransaction() (fornecido pelo SDK de carteira incorporada do Paper) inicia a transação, o que melhora a experiência do usuário, pois os usuários não precisam assinar nenhuma transação.
  3. transferNFT(): esta função transfere o NFT. Ela traz o signer e usa o ethers.js para iniciar transações. Criando a instância do contrato com o signer e iniciando a transação usando o método tradicional com o contrato, os usuários podem transferir NFTs com apenas um clique! Tudo o que é necessário é incluir o SDK de carteira incorporada do Paper como um signer na instância do contrato.

A seguir, vamos criar o componente para retornar:


// ...

if (!dataFetched)

        getNFTData(tokenId);

return (

        &lt;div style={{ "min-height": "100vh" }}>

            &lt;Navbar>&lt;/Navbar>

            &lt;div className="flex ml-20 mt-20">

                &lt;img src={data.image} alt="" className="w-2/5" />

                &lt;div className="text-xl ml-20 space-y-8 text-white shadow-2xl rounded-lg border-2 p-5">

                    &lt;div>

                        Nome: {data.name}

                    &lt;/div>

                    &lt;div>

                        Descrição: {data.description}

                    &lt;/div>

                    &lt;div>

                        Preço: &lt;span className="">{data.price + " MATIC"}&lt;/span>

                    &lt;/div>

                    &lt;div>

                        Proprietário: &lt;span className="text-sm">{data.owner}&lt;/span>

                    &lt;/div>

                    &lt;div>

                        Vendedor: &lt;span className="text-sm">{data.seller}&lt;/span>

                    &lt;/div>

                    &lt;div>

                        {currAddress === data.owner || currAddress === data.seller ?

                            &lt;div className="text-emerald-700">

                                Você é o proprietário deste NFT

                                &lt;br>&lt;/br>

                                &lt;input type="text" placeholder="Digite o endereço do comprador" className="bg-gray-800 text-white rounded-lg p-2 mt-2"

                                    onChange={(e) => updateRecieverAddress(e.target.value)}

                                >&lt;/input>

                                &lt;button className="enableEthereumButton bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-sm" onClick={() => transferNFT(tokenId)}>Transferir este NFT

                                &lt;/button>

                            &lt;/div>


<p id="gdcalert4" ><span style="color: red; font-weight: bold">>>>>>  gd2md-html alert: Definition &darr;&darr; outside of definition list. Missing preceding term(s)? </span><br>(<a href="#">Back to top</a>)(<a href="#gdcalert5">Next alert</a>)<br><span style="color: red; font-weight: bold">>>>>> </span></p>


                            :

                            &lt;button className="enableEthereumButton bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-sm" onClick={() => buyNFT(tokenId)}>Comprar este NFT&lt;/button>

                        }

                        &lt;div className="text-green text-center mt-3">{message}&lt;/div>

                    &lt;/div>

                &lt;/div>

            &lt;/div>

        &lt;/div>

    )

}

Enter fullscreen mode Exit fullscreen mode

O componente que retornamos exibe os detalhes sobre o NFT usando o tokenId específico. A funcionalidade interessante aqui é que a interface mostra o botão "Transfer" se o usuário for o proprietário ou o vendedor do NFT; caso contrário, ela exibe o botão "Buy" (Comprar).

Após implementar tudo isso, aqui está o resultado que você obterá!

Agora, é só reiniciar todo o DApp fechando a aba e o terminal funcionará perfeitamente com a UX que seu usuário deseja.

Resumo

Uau!!! Você acabou de criar um mercado de NFT com uma UX muito melhor do que os existentes atualmente.

Você pode conferir o código completo aqui:

O Paper oferece várias soluções para melhorar a UX, como pagamento com cartões de crédito.

Saiba mais sobre o SDK do Paper aqui.

Conecte-se comigo no Lens[@megabyte0x.lens] ou no Twitter [@megabyte0x].

Sinta-se à vontade para compartilhar suas descobertas e entre em contato comigo se tiver alguma dúvida ou pergunta.

Feliz desenvolvimento!

WAGMI


Artigo escrito por megabyte. Traduzido por Marcelo Panegali.

Top comments (0)