Computer >> 컴퓨터 >  >> 프로그램 작성 >> Redis

Next.js와 함께 Metamask를 사용하는 DApp용 기본 설정 저장소

DAO 및 DAPP와 같은 Web3 애플리케이션이 점점 더 대중화되고 있습니다. Web3를 전제로 이러한 플랫폼은 사용자에게 보다 개인적이고 맞춤화된 경험을 제공하는 동시에 자신의 신원을 다른 사람에게 비공개로 유지하거나 자신이 모르는 상태로 유지해야 합니다.

이 프로젝트에서 우리는 이러한 경우에 사용자 경험을 향상시킬 수 있는 방법을 탐구합니다.

지갑을 통한 인증/본인 확인

많은 애플리케이션에서 Metamask와 같은 블록체인 지갑은 ETH와 같은 암호화 자산을 관리하는 데 사용됩니다. 이러한 지갑을 사용하면 사용자가 다른 체인에 계정을 만들 수 있습니다. 이러한 계정은 개인 키로 생성되지만 각 계정에는 이를 나타내는 공개 주소가 있습니다.

공개키는 누구에게나 보여질 수 있기 때문에 이와 관련된 거래는 소유자만이 관리할 수 있습니다. 지갑 연결은 이러한 애플리케이션에 대한 견고한 인증 메커니즘을 제공합니다.

프로젝트

이 프로젝트에서는 사용자가 제공된 인터페이스를 사용자 정의하는 Next.js를 사용하여 기본 설정 스토리지 시스템을 구현합니다. 즉, 해당 사이트를 다시 방문할 때마다 의도한 대로 UI가 표시됩니다.

훨씬 더 강력한 아이디어는 회사의 하위 및 교차 플랫폼에서 사용자 인터페이스를 표준화할 수 있습니다. 이렇게 하면 사용자가 다른 사이트에서 설정한 기본 설정을 지원하는 특정 사이트로 이동할 때마다 비슷한 경험을 하게 됩니다.

또한 이 프로젝트는 사용자 정의를 위한 매개변수 수를 변경하도록 수정할 수 있으므로 원하는 구조로 성형할 수 있습니다.

이 샘플 프로젝트에는 2개의 매개변수만 있습니다. 즉:

  • 웹사이트의 테마
  • 사용자의 인사말

시작하기

Upstash Redis 환경 변수 구성

  • Upstash에서 무료 Redis 데이터베이스 생성
  • .env.local.example 파일을 .env.local에 복사합니다(Git에서 무시됨).
  • UPSTASH_REDIS_REST_URL 및 UPSTASH_REDIS_REST_TOKEN은 Upstash 콘솔의 데이터베이스 세부정보 페이지에서 찾을 수 있습니다.

종속성

종속성 설치:npm i @upstash/redis @metamask/detect-provider @mui/material @emotion/react @emotion/styled

api/store.js 생성 파일

Redis SDK를 구성하고 핸들러 기능을 내보냅니다.

api/store.js
import { Redis } from "@upstash/redis"
const redis = Redis.fromEnv()

export default async function handler(req, res) {
  const accountID = await JSON.parse(req.body).accountID
  const body = req.body
  const setResult = await redis.set(accountID, body);
  res.status(200).json({ result: setResult })
}

api/[accountAddress].js 생성 파일

마찬가지로 Redis SDK를 구성하고 핸들러를 내보냅니다.

api/[accountAddress].js
import { Redis } from "@upstash/redis"
const redis = Redis.fromEnv()

export default async function handler(req, res) {
    const accountID = req.query.accountAddress
    const getResult = await redis.get(accountID)
    res.status(200).json({ result: getResult })
}

index.js 구성 파일

프로젝트에 대한 변수 설정

index.js
const [accountAddress, setAccountAddress] = useState(null)
const [themePreference, setThemePreference] = useState("light")
const [greetingMessage, setGreetingMessage] = useState("Anonymous Person")
const [userSettings, setUserSettings] = useState(null)

// Check if connection already established. If so, fetch the data.
useEffect(() => {
    checkConnection()
    getPreferences()
}, [accountAddress])

메타마스크 연결

async function connect() {
    const provider = await detectEthereumProvider()
    console.log("provider:", provider)

    if (provider) {
      console.log('Ethereum successfully detected!')
      provider.request({ method: "eth_requestAccounts" }).then((accounts) => {
        if (!accountAddress) {
          setAccountAddress(accounts[0])
        }
      }).catch((err) => console.log(err))
      console.log("window.ethereum:", window.ethereum)
      getPreferences()
    } else {
      alert('Please install MetaMask!')
    }
  }

새로 고침 또는 일정 시간 후 탐색 시 연결 확인

async function checkConnection() {
    const provider = await detectEthereumProvider()
    if (provider) {
      provider
        .request({ method: 'eth_accounts' })
        .then(accounts => {
          setAccountAddress(accounts[0])
        })
        .catch(console.log)
    } else {
      console.log("Not connected, window.ethereum not found")
    }
}

기본 설정을 지정하려면

async function setPreferences(themePreference, greetingMessage) {
    if (accountAddress) {
      const res = await fetch(`/api/store`, {
        method: "POST",
        body: JSON.stringify({
          accountID: accountAddress,
          themePreference: themePreference,
          greetingMessage: greetingMessage,
        })
      })
      const data = await res.json()
    }
    else {
      alert("No account address detected")
    }
}

기본 설정을 얻으려면

async function getPreferences(e) {
    if (accountAddress) {
      console.log("Fetching user preferences...")
      const res = await fetch(`/api/${accountAddress}`, { method: "GET" })
      const data = await res.json()

      setUserSettings(data.result)
      if (data.result) {
        setThemePreference(data.result.themePreference)
        setGreetingMessage(data.result.greetingMessage)
      }
    }
    else {
      console.log("No account connected yet!")
    }
}

변수 상태 변경

다음 기능을 입력 필드/버튼 등에 바인딩합니다.

async function handleDarkMode(e) {
    console.log("themePreference:", themePreference)
    const newPreference = themePreference == "light" ? "dark" : "light"
    setThemePreference(newPreference)
    await setPreferences(newPreference, greetingMessage)
    await getPreferences()
}

async function takeGreetingMessage(e) {
    // submit with enter/return key
    if (e.keyCode == 13) {
        const message = e.target.value
        setGreetingMessage(message)
        console.log(message)
        await setPreferences(themePreference, message)
        await getPreferences()
        e.target.value = ""
    }
}

위의 기능을 활용하여 간단한 UI 만들기

관련 Material-UI 종속성을 가져왔는지 확인하십시오.

return (
    <div className={styles.container}>

      <h2>Web3 Preferences Holder</h2>
      <Button variant="contained" onClick={connect}>Connect Metamask</Button>
      <p>
        Lets you keep user preferences on cross-websites
      </p>
      <br />
      <p>For example, take a greeter message from user.</p>
      <TextField label="Call me..." variant="outlined" size="small" onKeyDown={takeGreetingMessage} />
      <br />
      <br />

      <Button onClick={handleDarkMode} variant="contained" size="small" style={{ backgroundColor: "#3D3B3B" }} > Switch Dark Mode </Button>

      <p>Sample Component/Page:</p>
      <Showcase userSettings={userSettings} />

    </div>
)

sampleComponent.jsx 생성 components 디렉토리에서

이것은 웹 인터페이스, 애플리케이션 등을 나타내는 주요 구성 요소입니다. 이 구성 요소는 시스템 작동 방식과 주요 목표가 제공하는 방식을 시각화합니다. 여기에서 원하는 대로 매개변수를 구문 분석하고 샘플 인터페이스를 만듭니다.

이 경우 프로젝트는 다음과 같이 구성됩니다.


import React from "react";
import { useState} from 'react'

import { ThemeProvider, createTheme } from '@mui/material/styles'
import { orange, grey } from '@mui/material/colors'

const lightTheme = createTheme({
  palette: {
    primary: {
      main: grey[400],
    },
  }
})

const darkTheme = createTheme({
  palette: {
    primary: {
      main: orange[400],
    },
  }
})

export default function Showcase(parameters) {

  const userSettings = parameters.userSettings
  const [theme, setTheme] = useState("light")
  const [greetingMessage, setGreetingMessage] = useState("Anonymous Person")

  const items = []
  if (userSettings) {

    const obj = userSettings[0]

    for (const key in userSettings) {
      items.push(<li key={key}> {key}: {userSettings[key]} </li>)
    }

    if (userSettings["themePreference"] != theme) {
      setTheme(userSettings["themePreference"] == "light" ? "light" : "dark")
    }

    if (!greetingMessage || userSettings["greetingMessage"] != greetingMessage) {
      if (userSettings["greetingMessage"]) {
        setGreetingMessage(userSettings["greetingMessage"])
      }
      else {
        setGreetingMessage("not the same message")
      }
    }
  }

  return (
    <div>
      <div style={{
        padding: 10,
        margin: 10,
        backgroundColor: theme == "light" ? "grey" : "orange",
        border: "solid",
        borderWidth: "30px",
        borderColor: theme == "light" ? "#B2B2B2" : "black"
      }}>
        <ThemeProvider
          theme={theme == "light" ? lightTheme : darkTheme}
        >

          <h2>Hi, {greetingMessage}!</h2>
          <p>User and their preferences:</p>
          {items}

        </ThemeProvider>

      </div>
    </div>
  );
}

워크플로

메타마스크를 통해 아직 연결되지 않은 사용자입니다. 기본 템플릿.

Next.js와 함께 Metamask를 사용하는 DApp용 기본 설정 저장소

메타마스크를 통해 처음으로 연결된 사용자입니다. 기본 템플릿.

Next.js와 함께 Metamask를 사용하는 DApp용 기본 설정 저장소

  • 사용자가 플랫폼에서 인사를 받았을 때 보고 싶은 이름을 입력합니다.
  • 사용자가 테마, 즉 밝음과 어두움 중에서 선택합니다.

사용자 기본 설정이 설정됩니다. 이제부터는 제공되는 기본 설정 인터페이스를 지원하는 모든 플랫폼에서 동일한 인터페이스를 표시할 수 있습니다. 사용자 정의 템플릿.

Next.js와 함께 Metamask를 사용하는 DApp용 기본 설정 저장소

구성 요소는 사용자가 설정한 기본 설정을 텍스트 형식으로 표시하므로 원하는 대로 구문 분석할 수 있습니다.

이 간단한 예에서 볼 수 있듯이 사용자에게 표시하는 모든 구성 요소를 매개변수화할 수 있습니다. 디자인을 개선하고 매개변수의 수를 늘려 항상 이 프로젝트에 추가할 수 있습니다. 그러나 기본 논리는 동일하게 유지됩니다.

최종 단어

프로젝트 데모를 보려면 여기를 확인하세요.

완성된 프로젝트를 보려면 프로젝트의 Github Repo로 이동하세요.

거기에 Vercel 배포를 위한 빠른 배포 버튼이 표시됩니다. 프로젝트를 신속하게 배포하여 Upstash Redis 통합을 자동으로 생성할 수 있습니다.

여러분의 아이디어와 생각을 기다립니다. 트위터나 디스코드를 통해 연락하실 수 있습니다.