Web3正在改变互联网所有权模式,本文介绍加密钱包集成、NFT市场和DAO网站的技术架构与开发实践。

Web3技术栈

层级 技术 说明
前端 ethers.js / wagmi 区块链交互
后端 EVM / Solidity 智能合约
存储 IPFS / Filecoin 去中心化存储
认证 钱包签名 Web3auth
节点 Alchemy / Infura RPC服务

加密钱包连接

钱包检测

// 检测是否安装MetaMask
const checkWallet = () => {
    if (typeof window.ethereum !== 'undefined') {
        console.log('MetaMask is installed!');
        return true;
    }
    return false;
};

// 检测多种钱包
const getProvider = () => {
    if (window.ethereum?.providers) {
        return window.ethereum;
    }
    return window.ethereum;
};

连接钱包

// ethers.js v6
import { BrowserProvider } from 'ethers';

const connectWallet = async () => {
    if (!window.ethereum) {
        alert('请安装 MetaMask 钱包');
        return null;
    }

    try {
        // 请求连接
        const provider = new BrowserProvider(window.ethereum);
        const signer = await provider.getSigner();
        const address = await signer.getAddress();
        const network = await provider.getNetwork();

        return {
            provider,
            signer,
            address,
            chainId: Number(network.chainId)
        };
    } catch (err) {
        if (err.code === 4001) {
            console.log('用户拒绝连接');
        }
        throw err;
    }
};

签名验证

// 生成签名验证用户身份
const signMessage = async (signer) => {
    const address = await signer.getAddress();
    const message = `欢迎登录我们的网站!\n\n地址:${address}\n时间:${Date.now()}`;

    const signature = await signer.signMessage(message);
    return { address, message, signature };
};

NFT展示

获取NFT数据

// 使用OpenSea API获取NFT
const getNFTs = async (address) => {
    const response = await fetch(
        `https://api.opensea.io/api/v2/chain/ethereum/account/${address}/nfts`
    );
    const data = await response.json();
    return data.nfts;
};

// 展示NFT卡片
const NFTGrid = ({ nfts }) => (
    <div className="nft-grid">
        {nfts.map(nft => (
            <div key={nft.identifier} className="nft-card">
                <img src={nft.image_url} alt={nft.name} />
                <h3>{nft.name}</h3>
                <p>{nft.collection}</p>
                {nft traits && (
                    <div className="traits">
                        {nft.traits.map(t => (
                            <span key={t.trait_type} className="trait">
                                {t.trait_type}: {t.value}
                            </span>
                        ))}
                    </div>
                )}
            </div>
        ))}
    </div>
);

钱包连接组件

const WalletButton = () => {
    const [account, setAccount] = useState(null);
    const [connecting, setConnecting] = useState(false);

    const connect = async () => {
        setConnecting(true);
        try {
            const { address } = await connectWallet();
            setAccount(address);
        } catch (err) {
            console.error(err);
        } finally {
            setConnecting(false);
        }
    };

    if (account) {
        return (
            <button className="wallet-btn connected">
                <Identicon address={account} />
                {account.slice(0, 6)}...{account.slice(-4)}
            </button>
        );
    }

    return (
        <button onClick={connect} disabled={connecting}>
            {connecting ? '连接中...' : '连接钱包'}
        </button>
    );
};

智能合约交互

ERC-721合约

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";

contract MyNFT is ERC721, ERC721URIStorage {
    uint256 private _nextTokenId;

    constructor() ERC721("MyNFT", "MNFT") {}

    function mint(address to, string memory uri) public returns (uint256) {
        uint256 tokenId = _nextTokenId++;
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
        return tokenId;
    }
}

前端调用合约

const CONTRACT_ADDRESS = '0x...';
const ABI = [...]; // 合约ABI

const mintNFT = async (signer, tokenURI) => {
    const contract = new Contract(CONTRACT_ADDRESS, ABI, signer);

    // 铸币(需要支付Gas)
    const tx = await contract.mint(await signer.getAddress(), tokenURI);

    // 等待确认
    const receipt = await tx.wait();

    // 获取Token ID
    const tokenId = receipt.logs[0].args.tokenId;
    return tokenId;
};

IPFS存储

上传文件到IPFS

import { create as ipfsClient } from 'ipfs-http-client';

const ipfs = ipfsClient({ url: 'https://ipfs.infura.io:5001' });

const uploadToIPFS = async (file) => {
    const added = await ipfs.add(file);
    const cid = added.cid.toString();
    return `https://ipfs.io/ipfs/${cid}`;
};

// 上传元数据
const uploadMetadata = async (metadata) => {
    const blob = new Blob([JSON.stringify(metadata)], { type: 'application/json' });
    return uploadToIPFS(blob);
};

DAO治理网站

提案列表

const Proposals = ({ daoAddress }) => {
    const [proposals, setProposals] = useState([]);

    useEffect(() => {
        loadProposals();
    }, []);

    return (
        <div className="proposals">
            {proposals.map(p => (
                <ProposalCard key={p.id} proposal={p} />
            ))}
        </div>
    );
};

Web3安全注意事项

注意事项 说明
签名验证 防止钓鱼签名
交易确认 金额单位确认
授权检查 防范授权陷阱
网络切换 防止跨链攻击
合约审计 上线前必做

Web3代表了互联网的新方向,掌握这些技术可以构建真正的去中心化应用。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。