传统的 URL 缩短程序依赖集中式服务,这使得它们容易受到审查、数据泄露和单点故障的影响。去中心化、Web3 驱动的 URL 缩短器通过在区块链上存储链接映射来解决这些问题,确保不变性、透明度和抗审查性。
在本指南中,我们将使用 Next.js、以太坊智能合约和 Fleek 的边缘优化托管构建完全去中心化的 URL 缩短服务。最后,您将拥有一个简化的 Next.js 应用程序,使用户能够无缝地缩短、存储和解析 URL。
主要优点:
确保您拥有:
npx create-next-app@latest
Project name? web3-url-shortener Use TypeScript? No Use ESLint? No Use Tailwind CSS? Yes Use `src/` directory? Yes Use App Router? No Use Turbopack? No Customize import alias? No
npm install wagmi ethers @tanstack/react-query @rainbow-me/rainbowkit # fleek-next adapter npm install @fleek-platform/next
fleek login
npm run dev
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; contract UrlShortener { // Maps a short code (e.g. "abc123") to a full URL mapping(string => string) private shortToLong; event URLShortened(string indexed shortCode, string longUrl); /** * @notice Create a shortened URL by mapping a short code to a long URL. * @param shortCode The short code (unique identifier) * @param longUrl The long URL to map to */ function setURL(string calldata shortCode, string calldata longUrl) external { require(bytes(shortCode).length > 0, "Short code cannot be empty"); require(bytes(longUrl).length > 0, "Long URL cannot be empty"); // In a production scenario, you'd probably want some uniqueness checks, // or handle collisions differently. For now we allow overwriting. shortToLong[shortCode] = longUrl; emit URLShortened(shortCode, longUrl); } /** * @notice Retrieve the long URL for a given short code. * @param shortCode The short code to look up * @return longUrl The long URL that the short code points to */ function getURL(string calldata shortCode) external view returns (string memory) { return shortToLong[shortCode]; } }
上述 UrlShortener 智能合约允许用户创建和管理缩短的 URL。它将唯一的短代码映射到长 URL,从而实现高效的 URL 存储和检索。用户可以使用 setURL 函数设置映射并使用 getURL 检索原始 URL。该合约包括基本验证,并在新 URL 缩短时发出事件。我已经部署了我的合约,地址是:0x2729D62B3cde6fd2263dF5e3c6509F87C6C05892
在项目根目录创建一个.env:
npx create-next-app@latest
使用以下命令创建 src/abi/URLShortener.json:
Project name? web3-url-shortener Use TypeScript? No Use ESLint? No Use Tailwind CSS? Yes Use `src/` directory? Yes Use App Router? No Use Turbopack? No Customize import alias? No
在 src/lib/contract.js 中:
npm install wagmi ethers @tanstack/react-query @rainbow-me/rainbowkit # fleek-next adapter npm install @fleek-platform/next
fleek login
将 {{REOWN-PROJECT-ID}} 和 {{REOWN-APP-NAME}} 替换为您在 Reown 中的详细信息。
提供商设置:
下面,我将展示如何在 Next.js 应用程序中正确设置 web3 提供程序,以正确处理客户端渲染。
关键是将提供程序分为两部分,以安全地处理必须仅在浏览器中运行的 web3 功能。
创建 src/lib/providers.js:
npm run dev
创建 src/lib/Web3Providers.jsx:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; contract UrlShortener { // Maps a short code (e.g. "abc123") to a full URL mapping(string => string) private shortToLong; event URLShortened(string indexed shortCode, string longUrl); /** * @notice Create a shortened URL by mapping a short code to a long URL. * @param shortCode The short code (unique identifier) * @param longUrl The long URL to map to */ function setURL(string calldata shortCode, string calldata longUrl) external { require(bytes(shortCode).length > 0, "Short code cannot be empty"); require(bytes(longUrl).length > 0, "Long URL cannot be empty"); // In a production scenario, you'd probably want some uniqueness checks, // or handle collisions differently. For now we allow overwriting. shortToLong[shortCode] = longUrl; emit URLShortened(shortCode, longUrl); } /** * @notice Retrieve the long URL for a given short code. * @param shortCode The short code to look up * @return longUrl The long URL that the short code points to */ function getURL(string calldata shortCode) external view returns (string memory) { return shortToLong[shortCode]; } }
修改_app.js:
在pages/_app.js中:
NEXT_PUBLIC_CONTRACT_ADDRESS=0x2729D62B3cde6fd2263dF5e3c6509F87C6C05892 NEXT_PUBLIC_RPC_URL={{YOUR-ARBITRUM-SEPOLIA-RPC-URL}}
此页面处理连接钱包、输入长 URL 和短代码以及写入区块链。我们将进行与上面类似的拆分。造成这种分裂的主要原因:
在pages/index.js:
{ "abi": [ { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "string", "name": "shortCode", "type": "string" }, { "indexed": false, "internalType": "string", "name": "longUrl", "type": "string" } ], "name": "URLShortened", "type": "event" }, { "inputs": [{ "internalType": "string", "name": "shortCode", "type": "string" }], "name": "getURL", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "string", "name": "shortCode", "type": "string" }, { "internalType": "string", "name": "longUrl", "type": "string" } ], "name": "setURL", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ] }
创建 src/lib/URLShortenerApp.jsx:
import { ethers } from "ethers"; import urlShortenerJson from "../abi/URLShortener.json"; export function getSignerContract(signer) { if (!signer) { console.error("No signer provided to getSignerContract"); throw new Error("No signer available"); } const address = process.env.NEXT_PUBLIC_CONTRACT_ADDRESS; if (!address) { throw new Error("Contract address not configured"); } return new ethers.Contract(address, urlShortenerJson.abi, signer); }
最后一件事是确保您的 tailwind.config.js 与以下内容匹配:
import { http} from "wagmi"; import { arbitrumSepolia } from "wagmi/chains"; import { getDefaultConfig } from "@rainbow-me/rainbowkit"; const projectId = {{REOWN-PROJECT-ID}}; export const config = getDefaultConfig({ appName: {{REOWN-APP-NAME}}, projectId: projectId, chains: [arbitrumSepolia], transports: { [arbitrumSepolia.id]: http(), }, ssr: false, });
对于服务器端和动态路由,请确保您有:在文件中导出 const runtime = 'edge'。
1.构建应用程序:
"use client"; import dynamic from "next/dynamic"; import { useEffect, useState } from "react"; const Web3Providers = dynamic(() => import("./Web3Providers"), { ssr: false, }); export default function Providers({ children }) { const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); }, []); if (!mounted) { return <>{children}</>; } return <Web3Providers>{children}</Web3Providers>; }
这会生成一个 .fleek 目录。
2.创建 Fleek 函数:
// Web3Providers.jsx "use client"; import { WagmiProvider } from "wagmi"; import "@rainbow-me/rainbowkit/styles.css"; import { RainbowKitProvider, darkTheme } from "@rainbow-me/rainbowkit"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { config } from "../lib/wagmi"; export default function Web3Providers({ children }) { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, refetchOnWindowFocus: false, }, }, }); return ( <WagmiProvider config={config}> <QueryClientProvider client={queryClient}> <RainbowKitProvider theme={darkTheme({ accentColor: "#0E76FD", accentColorForeground: "white", borderRadius: "large", fontStack: "system", overlayBlur: "small", })} > {children} </RainbowKitProvider> </QueryClientProvider> </WagmiProvider> ); }
3.为您的函数命名(例如,web3-url-shortener-next-js)。
4.部署到 Fleek:
import "../styles/globals.css"; import "@rainbow-me/rainbowkit/styles.css"; import Providers from "../lib/providers"; function App({ Component, pageProps }) { return ( <Providers> <Component {...pageProps} /> </Providers> ); } export default App;
成功部署后,Fleek 将提供一个 URL 来访问您的应用程序。
您已经成功构建并部署了一个去中心化的 URL 缩短器:
这个基础可以扩展或集成到更大的 Next.js 应用程序中。尝试自定义 UI、跟踪分析或集成其他智能合约来增强您的 Web3 URL 缩短器。在此处查看最终结果应如下所示:https://shortener.on-fleek.app/
您可以前往Github仓库查看完整代码:https://github.com/tobySolutions/shortener
本文最初发布于 Fleek 博客
以上是在 Fleek 上使用 Next.js 构建 WebRL 缩短器的详细内容。更多信息请关注PHP中文网其他相关文章!