แอปพลิเคชัน Web3 เช่น DAO และ DAPP กำลังได้รับความนิยมมากขึ้นเรื่อยๆ ภายในพื้นที่ของ Web3 แพลตฟอร์มเหล่านี้ควรให้ประสบการณ์ที่เป็นส่วนตัวและปรับแต่งได้เองมากขึ้นสำหรับผู้ใช้ในขณะที่รักษาข้อมูลประจำตัวของพวกเขาให้เป็นส่วนตัวต่อผู้อื่นหรือแม้กระทั่งไม่รู้จักตัวเอง
ในโครงการนี้ เราจะสำรวจว่าเราจะสามารถปรับปรุงประสบการณ์ของผู้ใช้ในกรณีดังกล่าวได้อย่างไร
การตรวจสอบสิทธิ์ / การตรวจสอบตัวตนผ่าน Wallets
สำหรับแอปพลิเคชั่นมากมาย กระเป๋าเงินบล็อคเชนเช่น Metamask ถูกใช้เพื่อจัดการสินทรัพย์ crypto เช่น ETH กระเป๋าเงินดังกล่าวให้ผู้ใช้สร้างบัญชีในเครือข่ายต่างๆ บัญชีเหล่านี้สร้างขึ้นด้วยคีย์ส่วนตัว อย่างไรก็ตาม แต่ละบัญชีมีที่อยู่สาธารณะที่เป็นตัวแทนของบัญชีเหล่านี้
เนื่องจากทุกคนสามารถแสดงคีย์สาธารณะได้ แต่ธุรกรรมที่เกี่ยวข้องกับคีย์นี้สามารถจัดการได้โดยเจ้าของเท่านั้น การเชื่อมต่อ Wallet เป็นกลไกการตรวจสอบสิทธิ์ที่มั่นคงสำหรับแอปพลิเคชันดังกล่าว
โครงการ
ในโปรเจ็กต์นี้ เราจะใช้ระบบจัดเก็บข้อมูลการกำหนดค่าตามความชอบโดยใช้ Next.js ซึ่งผู้ใช้จะปรับแต่งอินเทอร์เฟซที่มีให้ หมายความว่า เมื่อใดก็ตามที่พวกเขากลับมาที่ไซต์นั้น พวกเขาจะเห็น UI ตามที่ตั้งใจไว้
แนวคิดที่ทรงพลังยิ่งกว่านั้นยังสามารถทำให้อินเทอร์เฟซผู้ใช้เป็นปกติทั่วทั้งแพลตฟอร์มย่อยและข้ามแพลตฟอร์มของบริษัท ด้วยวิธีนี้ เมื่อใดก็ตามที่ผู้ใช้นำทางไปยังไซต์ใดไซต์หนึ่งที่สนับสนุนการตั้งค่าที่พวกเขาตั้งไว้บนไซต์อื่นๆ พวกเขาจะมีประสบการณ์ที่คล้ายกัน
นอกจากนี้ โปรเจ็กต์นี้สามารถปรับเปลี่ยนเพื่อเปลี่ยนจำนวนพารามิเตอร์สำหรับการปรับแต่งได้ ช่วยให้คุณขึ้นรูปเป็นโครงสร้างตามที่คุณต้องการได้
สำหรับโปรเจ็กต์ตัวอย่างนี้ มีเพียง 2 พารามิเตอร์เท่านั้น กล่าวคือ:
- ธีมของเว็บไซต์
- คำทักทายสำหรับผู้ใช้
เริ่มต้นใช้งาน
กำหนดค่าตัวแปรสิ่งแวดล้อม Upstash Redis
- สร้างฐานข้อมูล Redis ฟรีที่ Upstash
- คัดลอกไฟล์ .env.local.example ไปยัง .env.local (ซึ่ง Git จะไม่สนใจ):
- UPSTASH_REDIS_REST_URL และ UPSTASH_REDIS_REST_TOKEN สามารถพบได้ที่หน้ารายละเอียดฐานข้อมูลใน Upstash Console
การพึ่งพา
ติดตั้งการพึ่งพา:npm i @upstash/redis @metamask/detect-provider @mui/material @emotion/react @emotion/styled
สร้าง api/store.js
ไฟล์
กำหนดค่า Redis SDK และส่งออกฟังก์ชันตัวจัดการ
api/store.jsimport { 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].jsimport { 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.jsconst [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])
กำลังเชื่อมต่อ Metamask
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>
);
}
เวิร์กโฟลว์
ผู้ใช้ยังไม่ได้เชื่อมต่อผ่าน Metamask เทมเพลตเริ่มต้น
ผู้ใช้เชื่อมต่อผ่าน Metamask เป็นครั้งแรก เทมเพลตเริ่มต้น
- ผู้ใช้ป้อนชื่อที่ต้องการเห็นเมื่อเข้าสู่แพลตฟอร์ม
- ผู้ใช้เลือกระหว่างธีม คือสว่างและมืด
ตั้งค่ากำหนดผู้ใช้แล้ว จากนี้ไป อินเทอร์เฟซเดียวกันสามารถแสดงในแพลตฟอร์มใดก็ได้ที่สนับสนุนอินเทอร์เฟซการตั้งค่าที่มีให้ เทมเพลตที่ผู้ใช้กำหนดเอง
คอมโพเนนต์แสดงการตั้งค่าที่กำหนดโดยผู้ใช้ในรูปแบบข้อความ คุณสามารถแยกวิเคราะห์ได้ตามต้องการ
ดังที่คุณเห็นในตัวอย่างง่ายๆ นี้ คุณสามารถกำหนดพารามิเตอร์องค์ประกอบใดๆ ที่คุณแสดงให้ผู้ใช้เห็น คุณสามารถเพิ่มในโครงการนี้ได้ตลอดเวลาโดยการปรับปรุงการออกแบบและเพิ่มจำนวนพารามิเตอร์ แต่ตรรกะพื้นฐานยังคงเหมือนเดิม
คำสุดท้าย
ดูการสาธิตของโครงการได้ที่นี่
หากต้องการดูโครงการที่เสร็จแล้ว ไปที่ Github Repo ของโครงการ
คุณจะเห็นปุ่มปรับใช้อย่างรวดเร็วสำหรับการปรับใช้ Vercel ให้คุณปรับใช้โปรเจ็กต์ได้อย่างรวดเร็ว โดยสร้างการผสานรวม Upstash Redis โดยอัตโนมัติ
เรารอคอยที่จะได้ยินความคิดและความคิดของคุณ คุณสามารถติดต่อเราได้ทาง Twitter หรือ Discord