👋
デジタル文化財管理システム(試行版)のNFT対応
お知らせ: 2025-06-14
開発の経過は以下にまとめています。
概要
以下の記事をはじめとして、ブロックチェーンを用いたデジタル文化財管理システムの試作をしています。
今回、アップロードしたデータがNFTとして認識されるように改修しました。
勉強過程のため、不完全な点があるかと思いますが、参考になりましたら幸いです。
使い方ページ
ファイルのアップロード方法はこれまでと同様です。アップロード後に表示される一覧ページにおいて、詳細ページへのリンクを追加しました。
リンクをクリックすると、以下のような詳細画面に遷移します。
実装方法
※ この章は、AIが執筆しました。
1. コントラクトのNFT対応
既存のデジタル文化財管理コントラクトを、ERC721規格に準拠したNFTコントラクトに改修しました。
主な変更点:
1. OpenZeppelinライブラリの追加
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol";
2. コントラクトの継承構造を変更
contract DigitalHeritage is
Initializable,
OwnableUpgradeable,
UUPSUpgradeable,
ERC721Upgradeable,
ERC721URIStorageUpgradeable
{
// ...
}
3. 初期化関数の更新
function initialize() public initializer {
__Ownable_init(msg.sender);
__UUPSUpgradeable_init();
__ERC721_init("Digital Heritage", "DH");
__ERC721URIStorage_init();
}
4. 文化財登録時のNFTミント機能
function registerHeritage(
string memory _name,
string memory _description,
string memory _imageUrl,
string memory _tokenURI
) public {
uint256 id = heritages.length;
// 文化財データを保存
heritages.push(Heritage({
id: id,
name: _name,
description: _description,
imageUrl: _imageUrl,
owner: msg.sender,
timestamp: block.timestamp,
isDeleted: false
}));
// NFTとしてミント
_safeMint(msg.sender, id);
_setTokenURI(id, _tokenURI);
emit HeritageRegistered(id, msg.sender, _name);
}
2. メタデータ管理システムの実装
NFTの標準的なメタデータ形式に対応するため、サーバーサイドでのメタデータ生成・アップロード機能を実装しました。
1. API Routeでのメタデータ生成
// src/app/api/upload/route.js
const uploadMetadataToPinata = async (name, description, imageUrl) => {
const metadata = {
name: name,
description: description,
image: imageUrl,
attributes: [
{
trait_type: "登録日時",
value: new Date().toISOString()
},
{
trait_type: "カテゴリ",
value: "デジタル文化財"
}
]
};
// JSONをBlobに変換してPinataにアップロード
const jsonBlob = new Blob([JSON.stringify(metadata, null, 2)], {
type: 'application/json'
});
// Pinata APIを使用してIPFSにアップロード
// ...
};
2. フロントエンドでの統合処理
// 画像アップロード → メタデータ生成 → コントラクト登録の流れ
const handleSubmit = async (e) => {
// 1. 画像をIPFSにアップロード
const imageUrl = formData.imageUrl;
// 2. メタデータをサーバーサイドで生成・アップロード
const metadataFormData = new FormData();
metadataFormData.append('type', 'metadata');
metadataFormData.append('name', formData.name);
metadataFormData.append('description', formData.description);
metadataFormData.append('imageUrl', imageUrl);
const metadataResponse = await fetch('/api/upload', {
method: 'POST',
body: metadataFormData
});
const metadataResult = await metadataResponse.json();
// 3. コントラクトに登録(トークンURIを含む)
await registerHeritage(
formData.name,
formData.description,
imageUrl,
metadataResult.url
);
};
まとめ
Web3およびNFTの学習過程において、参考になりましたら幸いです。
Discussion