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代表了互联网的新方向,掌握这些技术可以构建真正的去中心化应用。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

评论(0)