构建基于区块链的葡萄酒市场:技术之旅

本文介绍了如何使用区块链技术革新葡萄酒行业,通过NFT确保葡萄酒的真实性、来源和安全所有权。文章详细描述了系统架构、智能合约设计和集成,这些都为基于区块链的葡萄酒交易市场提供了动力。重点介绍了WineCollection智能合约,它是在Arbitrum区块链上管理葡萄酒所有权、元数据和交易的ERC-721代币。

介绍

前一篇文章探讨了区块链技术如何通过 NFT 确保真实性、来源和安全所有权,从而彻底改变葡萄酒行业。我们详细介绍了我们在 Arbitrum 上构建葡萄酒厂解决方案的历程,其中每瓶葡萄酒都表示为具有透明交易历史记录的 NFT。该系统集成了区块链、IPFS 和网络市场,为酿酒商和买家提供无缝体验。

阅读完整文章:

https://learnblockchain.cn/article/14730

在本文中,我们将重点转移到技术实现,分解系统架构、智能合约设计以及为这个基于区块链的市场提供支持的集成。

系统架构概览

前端 (HTML/JavaScript)

  • Web Marketplace 为用户提供主要的界面。
  • 用户通过 UI 进行交互,UI 连接到后端和外部服务。
  • 智能合约功能(deployContract、mint、changeOwner、changeTokenUri、burn、setReviewUri)使用 ethers.js 直接从前端触发。

后端 (Java)

  • 后端充当 前端、区块链和 IPFS 之间的中间件。
  • Blockchain Connector 处理与 Arbitrum 的合约验证。
  • IPFS Connector 通过 Pinata IPFS 管理元数据存储和检索。
  • OpenSea Connector 确保 NFT 元数据在 OpenSea 上更新。
  • Data Service 与数据库交互,用于存储 NFT 集合和用户数据

数据库 (MongoDB)

  • 充当整个 web marketplace中央数据库,支持除葡萄酒业务之外的各种集合。

区块链 (Arbitrum L2 & ERC-721 智能合约)

  • 智能合约Arbitrum L2 上处理 NFT 操作,例如铸造、转移和销毁。
  • 区块链交易被记录并可以在 Arbiscan 上查看。
  • OpenSea 从智能合约检索 NFT 元数据更新。

存储 (通过 Pinata 的 IPFS)

  • IPFS 用于 NFT 元数据的去中心化存储,防止过多的链上存储成本。

外部服务

  • MetaMask (Crypto Wallet) 用于交易签名。
  • OpenSea 显示 NFT 并检索元数据更新。
  • Arbiscan 允许用户查看区块链交易历史记录。

WineCollection 智能合约是一个 ERC-721 token,它将葡萄酒瓶表示为 NFT。 它利用 OpenZeppelin 库来实现安全性和最佳实践。

从概念到实现

开发过程首先设计智能合约,该合约作为表示单次葡萄酒发行的基础。我们专注于定义核心功能,例如为每瓶酒铸造 NFT、跟踪所有权以及通过 IPFS 链接元数据。一旦合约巩固,我们就开始将其与前端和后端集成,确保区块链和网络市场之间的无缝交互。

Solidity 智能合约

接口和构造函数说明

  1. 导入的库
  • ERC721ERC721URIStorage:提供标准的 NFT 功能,包括元数据存储。
  • Ownable:确保只有合约所有者才能执行管理操作。
  1. 状态变量
  • _supply:跟踪已铸造的Token数量。
  • _maxSupply:定义此集合允许的 NFT 总数,即此葡萄酒发行中的最大瓶数。
  • _contractURI:存储有关整个集合的元数据。
  • _reviewURI:保存集合的评论摘要。
  • _reviewURISet:确保评论 URI 仅设置一次。
  1. 事件

我们使用智能合约中的 事件 来显式地创建一个 链上记录,每当相关值发生更改时。

  • TokenURIUpdated:当 NFT 的元数据更改时发出。
  • ContractURIUpdated:当集合元数据更新时发出。
  • ReviewURISet:当发布专家评论时发出。
  1. 构造函数

使用以下内容初始化合约:

  • 集合名称和符号
  • 初始所有者(控制管理功能的人员——酿酒师)
  • 最大 NFT 供应量(葡萄酒发行中的瓶数)
  • 合约级别的元数据 URI
pragma solidity ^0.8.20;

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

contract WineCollection is ERC721, ERC721URIStorage, Ownable {
    uint32 private _supply;
    uint32 private _maxSupply;
    string private _contractURI;
    string private _reviewURI;
    bool private _reviewURISet;
    event TokenURIUpdated(uint256 indexed tokenId, string newURI);
    event ContractURIUpdated(string newContractURI);
    event ReviewURISet(string reviewURI);

    constructor(string memory contractName,
        string memory contractSymbol,
        address initialOwner,
        uint32 maxSupply,
        string memory __contractURI)
        ERC721(contractName, contractSymbol)
        Ownable(initialOwner)
    {
        require(maxSupply > 0, string(abi.encodePacked(contractName, ": maxSupply should be more than 0")));
        _maxSupply = maxSupply;
        _contractURI = __contractURI;
    }

ContractUri 管理

此代码处理设置和检索 contractURI,它链接到描述葡萄酒系列合约的 IPFS 文件。

function contractURI() public view returns (string memory) {
    return _contractURI;
}

function updateContractURI(string memory newContractURI) public onlyOwner {
    _contractURI = newContractURI;
    emit ContractURIUpdated(newContractURI);
}

TokenUri 管理

此代码处理设置 tokenURI,它链接到描述瓶子 NFT 的 IPFS 文件。

function updateTokenURI(uint256 tokenId, string memory newURI) public {
    require(ownerOf(tokenId) == msg.sender, "updateTokenURI: Caller is not the owner ");
    _setTokenURI(tokenId, newURI);
    emit TokenURIUpdated(tokenId, newURI);
    emit MetadataUpdate(tokenId);
}

铸造 NFT

safeMint() 函数允许合约所有者铸造新的 NFT,同时强制执行供应限制:

  • 它确保铸造的 NFT 总数(_supply)不超过允许的最大数量(_maxSupply)。
  • 调用 _safeMint() 以安全地创建 NFT 并将其分配给指定的地址(to)。
  • 使用 _setTokenURI() 设置Token的元数据 URI,将其链接到 IPFS 文件。
  • 递增 _supply 以跟踪铸造的 NFT 数量。
function safeMint(address to, uint256 tokenId, string memory uri) public onlyOwner {
    require(_supply < _maxSupply, "Max number of NFTs has been reached");
    _safeMint(to, tokenId);
    _setTokenURI(tokenId, uri);
    _supply++;
}

safeMintBatch() 函数允许合约所有者在单个交易中铸造多个 NFT:

  • 确保 token ID 的数量与 URI 的数量匹配。
  • 迭代数组,为每个 token 调用 safeMint()
  • 减少区块链交易的数量,使铸造更加高效和经济

虽然已经实施了这种批量铸造机制以实现未来的可扩展性,但我们目前只在列表中发送一个 token,从而有效地一次铸造一个 NFT。

function safeMintBatch(address to, uint256[] memory tokenIds, string[] memory uris) public onlyOwner {
    require(tokenIds.length == uris.length, "Token IDs and URIs length mismatch");
    for (uint256 i = 0; i < tokenIds.length; i++) {
         safeMint(to, tokenIds[i], uris[i]);
    }
}

管理所有权和 tokenURI

此代码启用 NFT 所有权的转移,同时更新其元数据。

  • changeOwnerAndTokenURI:更新 Token 的元数据(tokenURI)并在单个交易中转移所有权。
  • changeOwner:确保只有当前所有者才能将 NFT 转移到新地址。
function changeOwnerAndTokenURI(address to, uint256 tokenId, string memory newURI) public {
    updateTokenURI(tokenId, newURI);
    changeOwner(to, tokenId);
}

function changeOwner(address to, uint256 tokenId) private {
    require(ownerOf(tokenId) == msg.sender, "changeOwner: Caller is not the owner");
    _transfer(msg.sender, to, tokenId);
}

总供应量

totalSupply 函数返回可以在集合中铸造的 NFT 的最大数量。 它允许用户在 arbiscan 界面中检查总可用供应量。

function totalSupply() public view returns (uint256) {
  return _maxSupply;
}

销毁 NFT

burn() 函数允许合约所有者通过调用 _burn(tokenId) 永久删除 NFT,从而确保 token 被销毁并且不能再被转移或访问。

function burn(uint256 tokenId) public onlyOwner {
        _burn(tokenId);
}

ReviewURI 管理

这些函数管理 review URI,它是一个 IPFS 文件,包含葡萄酒收藏的专家评论:

  • setReviewURI:允许合约所有者设置 review URI,但只能设置一次。 这可确保专家评论在发布后保持不变。 会发出一个事件(ReviewURISet)以在区块链上记录此更改。
  • getReviewURI:提供了一种检索存储的 review URI 的方法。
function setReviewURI(string memory newReviewURI) public onlyOwner {
    require(!_reviewURISet, "Review URI has already been set");
    _reviewURI = newReviewURI;
    _reviewURISet = true;
    emit ReviewURISet(newReviewURI);
}

function getReviewURI() public view returns (string memory) {
    return _reviewURI;
}

Smartcode IDE 和测试

对于智能合约开发,我们使用了 Remix Online IDE https://remix.ethereum.org/,,这是一个基于 Web 的环境,专为编写、测试和部署 Solidity 合约而设计。

要将 Remix 与本地文件夹连接,你可以安装并在你的工作目录中运行 remixd

yarn global add @remix-project/remixd
remixd

借助 Remix,我们能够在部署到 测试(Sepolia Arbitrum)生产(Arbitrum)区块链之前,使用虚拟钱包在 Remix Virtual Machine 上运行测试。

准备用于部署和验证的智能合约

要通过 ethers.js 与智能合约交互,我们需要提取 ABI (Application Binary Interface),它定义了合约的方法和结构。

Hardhat

Hardhat 是一个以太坊智能合约的开发环境,能够进行编译、部署、测试和调试。 我们使用 Hardhat 编译合约并使用以下命令提取 ABI 和字节码。

· 安装 Hardhat

yarn add --dev hardhat

· 使用 CLI 向导创建一个 Hardhat 项目

yarn hardhat init

这将提示在当前目录中创建一个新的 Hardhat 项目。 选择 “Create TypeScript project

· 配置 hardhat.config.ts

import { HardhatUserConfig } from "hardhat/config";

const config: HardhatUserConfig = {
  solidity: {
    version: "0.8.20",
    settings: {
      optimizer: {
        enabled: true,  // Matches deployment settings
        runs: 200,      // Optimization runs (commonly set to 200)
      },
    },
  },
  sourcify: {
    enabled: true,  // Enables automatic Sourcify verification
  },
};

export default config;

提取 ABI 和字节码

要使用 javascript 库 ethers.js 与智能合约交互,我们需要 ABI (Application Binary Interface)

· 准备脚本 scripts/extractContractAbiByteCode.ts

import fs from 'fs';
import path from 'path';

const contractJsonPath = path.resolve(__dirname, '../artifacts/contracts/WineCollection.sol/WineCollection.json');

const contractJson = JSON.parse(fs.readFileSync(contractJsonPath, 'utf8'));

const { abi, bytecode } = contractJson;

const outputPath = path.resolve(__dirname, '../output2/WineCollectionAbiByteCode.json');

fs.writeFileSync(outputPath, JSON.stringify({ abi, bytecode }, null, 2));

console.log('ABI and bytecode extracted to ../output2/WineCollectionAbiByteCode.json');

· 运行 scripts/extractContractAbiByteCode.ts 并接收 ABI json 作为输出:

yarn hardhat run scripts/extractContractAbiByteCode.ts

Compiled 1 Solidity file successfully (evm target: paris).
ABI and bytecode extracted to ../output/WineCollectionAbiByteCode.json

展平合约以进行验证

要通过 REST API 验证合约,需要一个展平的 Solidity 文件。 我们使用以下命令生成它:

yarn hardhat flatten contracts/WineCollection.sol > ../output/WineCollection.flattened.sol

但是,hardhat 展平并不完美,我们需要手动清理输出文件:

  • 删除文件的前两行和最后一行。
  • 保留第一个 pragma solidity ^0.8.20; 并删除任何重复项。

这些步骤确保合约的格式正确,以便成功验证。

结论

“构建基于区块链的葡萄酒市场:技术之旅” 的第一部分中,我们介绍了系统的 架构 和为基于 NFT 的葡萄酒真实性提供支持的 智能合约开发。 我们探讨了 WineCollection 合约如何管理 Arbitrum 区块链上的所有权、元数据和交易,从而确保透明度和安全性。

在下一部分中,我们将深入研究 前端 (JavaScript) 和后端 (Java) 实现,详细介绍 Web3 市场如何与区块链交互、处理元数据存储以及提供无缝的用户体验。 敬请关注!🚀

  • 原文链接: coinsbench.com/building-...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
CoinsBench
CoinsBench
https://coinsbench.com/