این یک پیاده سازی نمونه از یک dApp است که از اوراکل های RedStone استفاده می کند.این مخزن شامل یک پیاده سازی از یک dApp بازار NFT با قیمت به اصطلاح “ثابت” است. این بدان معنی است که فروشندگان می توانند سفارشات فروش (پیشنهادات) را با مشخص کردن مقدار قیمت به دلار ایجاد کنند. اما خریداران قادر به پرداخت با ارزهای بومی هستند که مقدار مورد نیاز آن در لحظه اجرای سفارش به صورت پویا محاسبه می شود.
لطفاً اگر سؤالی دارید، با تیم RedStone در Discord تماس بگیرید.
ما از hardhat و ethers.js برای اسکریپت های نصب و تست قرارداد و React برای پیاده سازی فرانت اند استفاده می کنیم.
bash
├── contracts # قراردادهای Solidity
│ ├── ExampleNFT.sol # قرارداد ERC721 نمونه
│ ├── Marketplace.sol # قرارداد ساده بازار NFT
│ ├── StableMarketplace.sol # قرارداد بازار NFT با قیمت ثابت
│ └── ...
├── public # پوشه با فایل های html عمومی و تصاویر برای برنامه React
├── scripts # اسکریپت های نصب قرارداد
├── src # کد منبع برنامه React
│ ├── components
│ │ ├── App.tsx # کامپوننت اصلی React
│ ├── core
│ │ ├── blockchain.ts # ماژول JS مسئول تعامل با بلاکچین و قراردادها
│ ├── config/ # پوشه با ABI های قرارداد و آدرس های قرارداد نصب شده
│ └── ...
├── test # تست های قرارداد
└── ...
ExampleNFT
یک قرارداد ERC721 ساده با تخصیص شناسه توکن متوالی خودکار است
function mint() external {
_mint(msg.sender, nextTokenId);
nextTokenId++;
}
این قرارداد از پیاده سازی ERC721Enumerable
ایجاد شده توسط تیم @openzeppelin
ارث می برد، که تابع های نمایش برای لیست کردن تمام توکن ها و توکن های متعلق به یک کاربر را اضافه می کند.
Marketplace
یک قرارداد بازار NFT است که اجازه می دهد سفارشات فروش برای هر توکن NFT که از استاندارد توکن غیرقابل تعویض EIP-721 پیروی می کند، ارسال شود. این قرارداد توابع زیر را دارد:
// یک سفارش فروش جدید ایجاد می کند
// این تابع نیاز به تأیید انتقال برای توکن NFT مشخص شده دارد
function postSellOrder(address nftContractAddress, uint256 tokenId, uint256 price) external {}
// فقط ایجادکننده سفارش می تواند این تابع را فراخوانی کند
function cancelOrder(uint256 orderId) external {}// اجازه می دهد اطلاعات تمام سفارشات (شامل لغو شده و اجرا شده) را دریافت کنید
function getAllOrders() public view returns (SellOrder[] memory) {}// قیمت مورد انتظار در AVAX را برای سفارش داده شده بازمی گرداند
function getPrice(uint256 orderId) public view returns (uint256) {}// نیاز به ارسال حداقل مقدار AVAX دارد
function buy(uint256 orderId) external payable {}
پیاده سازی آن کاملاً ساده است، بنابراین در اینجا توضیح نمی دهیم. می توانید کد کامل قرارداد را در contracts/Marketplace.sol بررسی کنید.
StableMarketplace
قرارداد بازار با پشتیبانی از قیمت ثابت است. این قرارداد از پیاده سازی Marketplace.sol
ارث می برد و فقط تابع _getPriceFromOrder
آن را بازنویسی می کند.
// تابع _getPriceFromOrder
از تابع getOracleNumericValueFromTxMsg
استفاده می کند،
// که داده های امضا شده را از calldata tx دریافت می کند و امضای آن را تأیید می کند
function _getPriceFromOrder(SellOrder memory order) internal view override returns (uint256)
{
uint256 ethPrice = getOracleNumericValueFromTxMsg(bytes32("ETH"));
return (order.price / ethPrice) (10 * 8);
}
برای استفاده از داده های RedStone، این قرارداد از قرارداد MainDemoConsumerBase.sol
redstone ارث می برد.
import "@redstone-finance/evm-connector/contracts/data-services/MainDemoConsumerBase.sol";
import "./Marketplace.sol";
contract StableMarketplace is Marketplace, MainDemoConsumerBase {
...
}
می توانید کد برنامه React را در پوشه src
بررسی کنید. ما سعی کردیم آن را تا حد امکان ساده کنیم و فقط عملکردهای اصلی بازار را نگه داریم.منطق اصلی UI در فایل App.tsx
قرار دارد و منطق تعامل با قرارداد در فایل blockchain.ts
قرار دارد.اگر به کد فایل blockchain.ts
نگاهی بیندازید، متوجه خواهید شد که هر فراخوانی قرارداد که نیاز به پردازش داده های RedStone دارد، روی یک نمونه قرارداد انجام می شود که توسط @redstone-finance/evm-connector پوشش داده شده است.
import { WrapperBuilder } from "@redstone-finance/evm-connector";
async function getContractInstance(contractName) {
...
return new ethers.Contract(address, abi, signer);
}async function buy(orderId) {
const marketplace = await getContractInstance("marketplace"); // پوشش دادن نمونه قرارداد marketplace.
// این امکان دریافت داده از استخر داده های redstone را
// برای هر فراخوانی تابع قرارداد فراهم می کند
const wrappedMarketplaceContract = WrapperBuilder.wrap(
marketplace
).usingDataService(
{
dataServiceId: "redstone-main-demo",
uniqueSignersCount: 1,
dataFeeds: ["ETH"],
},
["https://d33trozg86ya9x.cloudfront.net"]
); // بررسی مقدار مورد انتظار AVAX
const expectedAvaxAmount = await wrappedMarketplaceContract.getPrice(orderId); ...
}
می توانید در مورد پوشش دادن قرارداد و @redstone-finance/evm-connector
اینجا بیشتر بخوانید.
ما از چارچوب تست hardhat برای تست های قرارداد استفاده کرده ایم. تمام تست ها در پوشه test قرار دارند.💡 توجه داشته باشید که هر تابع قرارداد که نیاز به داده های اوراکل RedStone دارد، نیز روی یک نمونه قرارداد ethers پوشش داده شده فراخوانی می شود.
const expectedAvaxAmount = await wrappedMarketplaceContract.getPrice(orderId);
این برنامه از قبل در شبکه آزمایشی Avalanche FUJI نصب شده است. می توانید آن را در https://stable-marketplace.redstone.finance/ بررسی کنید.
همچنین می توانید این مخزن را کلون کنید و برنامه را در محلی بسازید. لطفاً مراحل زیر را دنبال کنید:
git clone https://github.com/redstone-finance/stable-price-marketplace
cd stable-price-marketplace
yarn install
yarn run-local-node
yarn deploy-contracts:local
yarn app:start
برنامه باید در http://localhost:3000 در حال اجرا باشد.
Networks dropdown
را انتخاب کنید -> Add network
و جزئیات زیر را وارد کنید:
Network Namehardhat-localNew RPC URLhttp://localhost:8545Chain ID1337Currency SymbolAVAX
سپس دکمه Save
را فشار دهید.
User 1
: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
User 2
: 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
می توانید کلیدهای بیشتری را در کنسول خود زیر yarn run-local-node
مشاهده کنید.
پس از بازدید از برنامه برای اولین بار، صفحه تقریباً خالی را با لینک + Mint new NFT
مشاهده خواهید کرد. روی این لینک کلیک کنید تا NFT های جدید ضرب کنید. پس از تأیید تراکنش ضرب، NFT خود را در ستون سمت چپ مشاهده خواهید کرد.
پس از ضرب هر NFT، می توانید سفارش فروش برای هر یک از آنها ارسال کنید. دکمه SELL را کلیک کنید و ارزش دلاری را وارد کنید. از شما خواسته می شود 2 تراکنش را تأیید کنید: برای تأیید انتقال NFT و برای ایجاد سفارش بازار. پس از تأیید آنها، سفارش خود را در ستون Orders مشاهده خواهید کرد.
همچنین می توانید حساب متاماسک را تغییر دهید و NFT را خریداری کنید. توصیه می کنم ابزار توسعه دهنده را در مرورگر در زبانه شبکه باز کنید و درخواست های شبکه ای که قبل از ارسال تراکنش خرید ارسال می شوند را بررسی کنید.حداقل باید 2 درخواست با قیمت ETH و امضاهای رمزنگاری شده را مشاهده کنید. این داده ها به همراه امضاها برای هر فراخوانی قرارداد.