كيفية إنشاء NFT باستخدام 14 سطرًا فقط من الكود
مقدمة: لماذا يهمك تعلّم إنشاء NFT؟
إذا كنت مطورًا مهتمًا بمجال Blockchain، فمن الضروري أن تتعرف إلى NFT أو Non-Fungible Tokens. هذا النوع من الأصول الرقمية أصبح جزءًا مهمًا من تطبيقات Web3، لأنه يتيح تمثيل ملكية عناصر فريدة مثل الأعمال الفنية، والمقتنيات الرقمية، وحتى بعض الأصول الواقعية.
في هذا الدليل العملي، ستتعلم الأساس الهندسي وراء NFTs بطريقة مبسطة ومناسبة للمبتدئين، دون الحاجة إلى خبرة مسبقة في Ethereum أو Smart Contracts. وفي نهاية الشرح، ستكون قد أنشأت محفظة Ethereum تحتوي على NFT خاص بك.


اللافت في هذا المشروع أن عقد الـ NFT نفسه بسيط للغاية، ويمكن تنفيذه في عدد محدود جدًا من الأسطر البرمجية.
ما هو NFT؟
يرمز NFT إلى Non-Fungible Token، أي رمز غير قابل للاستبدال. والمقصود بغير قابل للاستبدال أنه يمثل عنصرًا فريدًا لا يمكن استبداله بوحدة مطابقة تمامًا كما هو الحال في العملات التقليدية أو العملات الرقمية مثل ETH أو BTC.
يُستخدم NFT لإثبات ملكية أصل رقمي فريد. ويمكن أن يمثل:
- عملًا فنيًا رقميًا
- عنصرًا داخل لعبة
- مقتنى رقميًا
- مستند ملكية
- بيانات وصفية مرتبطة بأصل معين
وتضمن شبكة Ethereum تسجيل الملكية بشكل موثوق، بحيث لا يمكن تعديل سجل الملكية أو نسخ NFT جديد بشكل غير شرعي.
ما هو معيار ERC-721 ولماذا يُستخدم في NFTs؟
يُعد ERC-721 المعيار الأكثر شيوعًا لإنشاء NFTs على Ethereum. وعندما يطبق Smart Contract مجموعة محددة من الواجهات والدوال القياسية، يمكن اعتباره عقد ERC-721.
تكمن أهمية هذا المعيار في أنه يجعل الـ NFT متوافقًا مع المحافظ والأسواق والأدوات التي تدعم هذا البروتوكول. وبدلًا من بناء كل شيء من الصفر، يمكن الاستفادة من مكتبات موثوقة مثل OpenZeppelin، التي توفر تنفيذًا جاهزًا وآمنًا للمعايير الشائعة.
ما المقصود بعملية Minting للـ NFT؟
عندما تقوم بعملية minting، فأنت تنشر رمزًا فريدًا جديدًا على البلوكشين. هذا الرمز يكون نسخة فعلية من Smart Contract الخاص بك، ويحمل هوية مميزة مرتبطة بـ tokenURI.
يشير tokenURI إلى ملف JSON يحتوي على البيانات الوصفية الخاصة بالـ NFT، مثل:
- الاسم
- الوصف
- رابط الصورة
- الخصائص أو السمات Attributes
إليك مثالًا على ملف metadata متوافق مع ERC721 Metadata Schema:
{
"attributes": [
{
"trait_type": "Shape",
"value": "Circle"
},
{
"trait_type": "Mood",
"value": "Sad"
}
],
"description": "A sad circle.",
"image": "https://i.imgur.com/Qkw9N0A.jpeg",
"name": "Sad Circle"
}
أين يمكن تخزين metadata الخاصة بـ NFT؟
هناك ثلاث طرق رئيسية لتخزين البيانات الوصفية الخاصة بالـ NFT:
- On-chain: تخزين البيانات مباشرة داخل البلوكشين، وهي طريقة موثوقة لكنها مرتفعة التكلفة.
- IPFS: خيار شائع يوازن بين اللامركزية والاعتمادية.
- API تقليدي: جعل الخادم يعيد ملف JSON عند طلب الرابط.
عادةً ما يُفضل الخياران الأول والثاني من ناحية الثبات وعدم القابلية للتلاعب، لكن في هذا المشروع سنستخدم API بسيط لتسهيل الفهم والتطبيق السريع.
ما الذي سنبنيه في هذا المشروع؟
سننشئ NFT خاصًا بنا، ثم نقوم بنشره وسكّه على شبكة Ethereum التجريبية. المشروع مناسب للمبتدئين، لكنه يعرّفك في الوقت نفسه على مجموعة مفاهيم مهمة في Web3، مثل:
- المحافظ الرقمية
- Smart Contracts
- العقدة Node
- الـ metadata
- النشر على شبكة اختبار

ورغم أن المشروع تعليمي ومبسط، فإنه يمنحك فهمًا عمليًا ممتازًا لكيفية عمل NFTs خلف الكواليس.
المتطلبات الأساسية قبل البدء
1) إعداد Metamask
ستحتاج إلى عنوان Ethereum للتعامل مع Smart Contract. سنستخدم Metamask باعتباره محفظة رقمية مجانية لإدارة العناوين وإرسال المعاملات واستقبالها.

قم بتثبيت إضافة Chrome، وكذلك تطبيق الهاتف، لأن إضافة المتصفح قد لا تعرض الـ NFTs كما ينبغي.

احرص على اختيار شبكة Ropsten Test Network لأغراض التطوير. وبعد ذلك ستحتاج إلى بعض test ETH لتغطية رسوم النشر والسك.

2) استخدام Alchemy للاتصال بالشبكة
للتفاعل مع شبكة Ethereum، يجب أن تكون متصلًا بعقدة Ethereum Node. بدلًا من تشغيل عقدة خاصة بك، يمكنك استخدام مزود خدمة مثل Alchemy.
أنشئ حسابًا في Alchemy، ثم أنشئ تطبيقًا جديدًا باستخدام شبكة Ethereum وحدد Ropsten.

بعد إنشاء التطبيق، انسخ مفتاح الاتصال HTTP key لأننا سنستخدمه لاحقًا داخل ملف البيئة.

3) تثبيت Node.js وNPM
سنستخدم Node.js لبناء المشروع وتشغيل الأدوات اللازمة. إذا لم يكن مثبتًا لديك، قم بتثبيته أولًا قبل متابعة الخطوات التالية.
تهيئة المشروع خطوة بخطوة
ابدأ بإنشاء مجلد المشروع الرئيسي:
mkdir nft-project
cd nft-project
الآن أنشئ مجلدًا فرعيًا باسم ethereum لملفات Smart Contract:
mkdir ethereum
cd ethereum
npm init
بعد ذلك ثبّت Hardhat، وهي أداة تطوير تسهّل بناء ونشر واختبار تطبيقات Ethereum:
npm install --save-dev hardhat
npx hardhat
عندما تظهر لك الخيارات، اختر:
Create an empty hardhat.config.js
بعد الانتهاء، عد إلى جذر المشروع وأنشئ تطبيق Next.js باسم web لاستخدامه في بناء API للـ metadata:
cd ..
mkdir web
cd web
npx create-next-app@latest
ستصبح بنية المشروع على هذا النحو:
nft-project/
ethereum/
web/
تعريف متغيرات البيئة .env
سنستخدم مفتاح Alchemy مع المفتاحين العام والخاص لمحفظة Metamask. داخل مجلد ethereum/ أنشئ ملف .env وثبّت dotenv:
cd ..
cd ethereum
touch .env
npm install dotenv --save
ثم أضف القيم التالية:
DEV_API_URL=YOUR_ALCHEMY_KEY
PRIVATE_KEY=YOUR_METAMASK_PRIVATE_KEY
PUBLIC_KEY=YOUR_METAMASK_ADDRESS
تنبيه مهم: لا تشارك PRIVATE_KEY مع أي شخص، ولا ترفعه إلى مستودع عام على GitHub.
بناء Smart Contract للـ NFT
داخل مجلد ethereum/ أنشئ المجلدين التاليين:
mkdir contracts
mkdir scripts
ثم ثبّت مكتبة OpenZeppelin:
npm install @openzeppelin/contracts
بعد ذلك أنشئ الملف EmotionalShapes.sol داخل contracts/:
cd contracts
touch EmotionalShapes.sol
إليك Smart Contract الكامل:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract EmotionalShapes is ERC721 {
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
constructor() ERC721("EmotionalShapes", "ESS") {}
function _baseURI() internal pure override returns (string memory) {
return "YOUR_API_URL/api/erc721/";
}
function mint(address to) public returns (uint256) {
require(_tokenIdCounter.current() < 3);
_tokenIdCounter.increment();
_safeMint(to, _tokenIdCounter.current());
return _tokenIdCounter.current();
}
}
شرح مبسط للعقد البرمجي
- ERC721: العقد الأساسي الذي يمنحنا وظائف NFT القياسية.
- Counters: أداة لتوليد معرفات تصاعدية للرموز.
- constructor: يحدد اسم المجموعة ورمزها المختصر.
- _baseURI: يحدد المسار الأساسي الذي ستُبنى عليه روابط metadata.
- mint: الدالة المسؤولة عن إنشاء NFT جديد وإرساله إلى عنوان معين.
لاحظ أن الشرط require(_tokenIdCounter.current() < 3) يقيّد العدد إلى ثلاثة NFTs فقط. يمكنك تعديله أو إزالته حسب حاجتك.
إنشاء metadata الخاصة بالـ NFT عبر Next.js API
سنستخدم مسار API ديناميكيًا في مشروع Next.js لإرجاع ملف JSON مختلف لكل NFT.
أنشئ الملف التالي:
// web/pages/api/erc721/[id].js
const metadata = {
1: {
attributes: [
{
trait_type: "Shape",
value: "Circle",
},
{
trait_type: "Mood",
value: "Sad",
},
],
description: "A sad circle.",
image: "https://i.imgur.com/Qkw9N0A.jpeg",
name: "Sad Circle",
},
2: {
attributes: [
{
trait_type: "Shape",
value: "Rectangle",
},
{
trait_type: "Mood",
value: "Angry",
},
],
description: "An angry rectangle.",
image: "https://i.imgur.com/SMneO6k.jpeg",
name: "Angry Rectangle",
},
3: {
attributes: [
{
trait_type: "Shape",
value: "Triangle",
},
{
trait_type: "Mood",
value: "Bored",
},
],
description: "An bored triangle.",
image: "https://i.imgur.com/hMVRFoJ.jpeg",
name: "Bored Triangle",
},
};
export default function handler(req, res) {
res.status(200).json(metadata[req.query.id] || {});
}
بعد ذلك شغّل تطبيق Next.js:
npm run dev
يمكنك اختبار المسار عبر الرابط التالي:
http://localhost:3000/api/erc721/1
إذا ظهر لك كائن JSON، فهذا يعني أن metadata تعمل بالشكل الصحيح.
إتاحة metadata للعالم الخارجي باستخدام ngrok
بما أن تطبيقك يعمل محليًا على جهازك، فلن تتمكن الشبكة أو المحافظ الخارجية من الوصول إليه. هنا يأتي دور ngrok، الذي ينشئ رابطًا عامًا يشير إلى localhost.

- انتقل إلى موقع ngrok وأنشئ حسابًا.
- فك ضغط الحزمة بعد تنزيلها.
- افتح الطرفية داخل مجلد ngrok.
- نفّذ أمر المصادقة التالي:
./ngrok authtoken YOUR_AUTH_TOKEN
ثم افتح نفقًا إلى تطبيق Next.js المحلي:
./ngrok http 3000
سيظهر لك عنوان عام مشابه لما يلي:
Forwarding https://YOUR_NGROK_ADDRESS -> http://localhost:3000
اختبره عبر:
https://YOUR_NGROK_ADDRESS/api/erc721/1
تحديث _baseURI ونشر العقد على Ethereum
قبل النشر، عد إلى ملف العقد واستبدل YOUR_API_URL بعنوان ngrok:
// ethereum/contracts/EmotionalShapes.sol
contract EmotionalShapes is ERC721 {
...
function _baseURI() internal pure override returns (string memory) {
return "https://YOUR_NGROK_ADDRESS/api/erc721/";
}
...
}
الآن ثبّت حزمة ethers.js الخاصة بـ Hardhat:
npm install @nomiclabs/hardhat-ethers --save-dev
ثم حدّث ملف hardhat.config.js:
require("dotenv").config();
require("@nomiclabs/hardhat-ethers");
module.exports = {
solidity: "0.8.0",
defaultNetwork: "ropsten",
networks: {
hardhat: {},
ropsten: {
url: process.env.DEV_API_URL,
accounts: [`0x${process.env.PRIVATE_KEY}`],
},
},
};
بعدها قم بترجمة العقد:
npx hardhat compile
هذه الخطوة ستولّد الملفات المترجمة داخل مجلد artifacts/.
كتابة سكربت نشر العقد
أنشئ الملف deploy.js داخل scripts/:
// ethereum/scripts/deploy.js
async function main() {
const EmotionalShapes = await ethers.getContractFactory("EmotionalShapes");
const emotionalShapes = await EmotionalShapes.deploy();
console.log("EmotionalShapes deployed:", emotionalShapes.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
ثم نفّذ سكربت النشر:
node ./scripts/deploy.js
إذا تم كل شيء بنجاح، سيظهر لك عنوان العقد المنشور على شبكة Ropsten. ويمكنك عرضه عبر Etherscan باستخدام عنوان العقد.
سك NFT فعليًا عبر سكربت mint.js
بعد نشر العقد، حان وقت سك أول NFT لك. ثبّت حزمة ethers:
npm install --save ethers
ثم أنشئ الملف mint.js داخل scripts/:
require("dotenv").config();
const { ethers } = require("ethers");
const contract = require("../artifacts/contracts/EmotionalShapes.sol/EmotionalShapes.json");
const contractInterface = contract.abi;
const provider = ethers.getDefaultProvider("ropsten", {
alchemy: process.env.DEV_API_URL,
});
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
const emotionalShapes = new ethers.Contract(
YOUR_NFT_ADDRESS,
contractInterface,
wallet
);
const main = () => {
emotionalShapes
.mint(process.env.PUBLIC_KEY)
.then((transaction) => console.log(transaction))
.catch((e) => console.log("something went wrong", e));
};
main();
استبدل YOUR_NFT_ADDRESS بعنوان العقد الذي حصلت عليه بعد النشر. بعد تشغيل السكربت، ستُرسل معاملة سك NFT إلى الشبكة.
يمكنك بعدها أخذ قيمة hash من ناتج التنفيذ وفحصها على Etherscan لمتابعة حالة المعاملة.
عرض NFT داخل محفظة Metamask
لعرض الـ NFT في المحفظة، استخدم تطبيق Metamask على الهاتف، ثم انتقل إلى قسم NFTs وأضف:
- عنوان Smart Contract
- رقم الرمز Token ID
إذا اتبعت الخطوات السابقة بالترتيب، فغالبًا سيكون أول Token ID هو 1.

نصائح تقنية مهمة قبل استخدام المشروع في بيئة إنتاج
رغم أن هذا المشروع ممتاز للتعلم، فإنه غير مناسب مباشرة للاستخدام الإنتاجي دون تحسينات إضافية. من أبرز ما ينبغي مراجعته:
- استبدال روابط الصور المؤقتة مثل Imgur بحلول أكثر ثباتًا مثل IPFS.
- حماية منطق السك وتقييد من يملك صلاحية إنشاء الرموز.
- إضافة اختبارات للعقد باستخدام Hardhat.
- فحص تكاليف الغاز وتحسين الدوال البرمجية.
- مراجعة الأمان قبل النشر على Mainnet.
الخلاصة التقنية
إنشاء NFT ليس معقدًا كما يبدو في البداية. بالاعتماد على Solidity وOpenZeppelin وHardhat وNext.js، يمكنك بناء نموذج عملي متكامل يشرح لك دورة حياة الـ NFT من التعريف وحتى السك والعرض داخل المحفظة. تقنيًا، أهم ما يجب استيعابه هو العلاقة بين Smart Contract وmetadata وtokenURI، لأن هذه العناصر تمثل جوهر عمل أي مشروع NFT احترافي. وإذا أردت تطوير المشروع لاحقًا، فالخطوة الطبيعية التالية هي بناء واجهة React متكاملة لعرض الأصول وبيعها وربطها بتجربة Web3 حقيقية.