BTC
ETH
HTX
SOL
BNB
Xem thị trường
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt

Tìm hiểu cách sử dụng Solidity để tạo NFT trên chuỗi trong năm phút

ChinaDeFi
特邀专栏作者
2022-01-05 08:19
Bài viết này có khoảng 4902 từ, đọc toàn bộ bài viết mất khoảng 8 phút
Tạo NFT không phải là một nhiệm vụ khó khăn.
Tóm tắt AI
Mở rộng
Tạo NFT không phải là một nhiệm vụ khó khăn.

NFT ngoài chuỗi

Điều này đặt ra câu hỏi, không phải tất cả các NFT đều trực tuyến sao? Bất kỳ ai đã làm việc với NFT trên chuỗi khối Ethereum đều có thể cho bạn biết rằng lưu trữ dữ liệu trên chuỗi có những hạn chế; vì nó rất tốn kém và hầu hết các dự án NFT đều lưu trữ hình ảnh và tệp siêu dữ liệu ngoài chuỗi. Thông thường, dữ liệu duy nhất chúng tôi thấy được lưu trữ "trên chuỗi" là hàm băm siêu dữ liệu không thay đổi (tokenURI của chúng tôi) - cách dễ nhất để mô tả hàm băm này là liên kết đến NFT thực tế của chúng tôi, sự khác biệt ở đây là hàm băm phụ thuộc vào dữ liệu đó đã tạo nó; thay đổi nguồn và hàm băm không còn hợp lệ, vì vậy nó là bất biến. Bất kỳ ai cũng có thể chạy một nút IPFS giống như bất kỳ ai cũng có thể chạy một công cụ khai thác hoặc đồng thuận nút blockchain.

Bây giờ, chúng ta có thể đã quen thuộc với các dự án "on-chain" như Loot, điều này được thực hiện như thế nào?

Câu trả lời là có, nhưng nó yêu cầu một số thứ, cụ thể là mã hóa Base64 và loại hình ảnh SVG. Cả hai đều cho phép chúng tôi làm việc với dữ liệu văn bản, thay vì dữ liệu hình ảnh "nặng" trong bộ nhớ điển hình như PNG hoặc JPEG. Điều này có nghĩa là chúng ta cần làm hai việc:

  • Base64 mã hóa siêu dữ liệu json của chúng tôi

  • Mã hóa "hướng dẫn" kết xuất hình ảnh ở định dạng SVG

May mắn thay, các trình duyệt hiểu cả hai định dạng và các thị trường dựa trên trình duyệt như OpenSea có thể hiển thị NFT của chúng tôi theo cách giống như các liên kết đến hàm băm lưu trữ IPFS, tuy nhiên, các trình duyệt không "tìm nạp và lưu vào bộ nhớ đệm" hình ảnh mà thay vào đó hiển thị hình ảnh cho chúng tôi.

mã hóa base64

Một cách để đạt được lưu trữ siêu dữ liệu trên chuỗi và tránh nhu cầu sử dụng bất kỳ công cụ nào như IPFS là mã hóa base64 và lưu trữ trực tiếp trong dữ liệu mã thông báo NFT của chúng tôi. Trong trường hợp của chúng tôi, tokenURI trả về siêu dữ liệu thực ở dạng được mã hóa: đây không còn là "liên kết" nữa mà là chính siêu dữ liệu.

Như tôi đã nói, chúng tôi sẽ tận dụng thư viện Base64.sol hiện có từ GitHub. Bạn có thể nhập từ github hoặc chỉ cần sao chép/sao chép mã và nhập tệp này từ cùng thư mục mà bạn đã dán mã.

Một điều cần lưu ý về mã hóa thành Base64 là mã hóa không phải là một dạng nén dữ liệu, vì vậy chúng tôi không giảm kích thước dữ liệu, chúng tôi chỉ lưu trữ dữ liệu ở định dạng mà trình duyệt có thể giải mã. Siêu dữ liệu của chúng tôi không lớn lắm, đó là trường hợp của các hình ảnh NFT của chúng tôi. Dưới đây là một ví dụ:

Trong mã ví dụ của chúng tôi, chúng tôi sử dụng hàm 'BuildMetaData' lấy tokenId (ID của NFT của chúng tôi) và trả về chuỗi văn bản json được mã hóa base64 chứa OpenSea sử dụng tên, mô tả, thuộc tính của nó để hiển thị Mọi thứ bạn cần cho NFT của bạn, và rất quan trọng, hình ảnh của chúng tôi. Nó cũng sử dụng chức năng BuildImage mà tôi sẽ giải thích bên dưới.

Đây là một ví dụ về siêu dữ liệu của chúng tôi:

{
 "name":"NFT1",
 "description":"This is our on-chain NFT",
 "image": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAwIiBoZWlnaHQ9IjUwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCBpZD0ic3ZnXzExIiBoZWlnaHQ9IjYwMCIgd2lkdGg9IjUwMyIgeT0iMCIgeD0iMCIgZmlsbD0iaHNsKDI5Myw1MCUsMjUlKSIvPjx0ZXh0IGZvbnQtc2l6ZT0iMTgiIHk9IjEwJSIgeD0iNSUiIGZpbGw9ImhzbCg5MCwxMDAlLDgwJSkiPlNvbWUgVGV4dDwvdGV4dD48dGV4dCBmb250LXNpemU9IjE4IiB5PSIxNSUiIHg9IjUlIiBmaWxsPSJoc2woOTAsMTAwJSw4MCUpIj5Tb21lIFRleHQ8L3RleHQ+PHRleHQgZm9udC1zaXplPSIxOCIgeT0iMjAlIiB4PSI1JSIgZmlsbD0iaHNsKDkwLDEwMCUsODAlKSI+U29tZSBUZXh0PC90ZXh0Pjx0ZXh0IGZvbnQtc2l6ZT0iMTgiIHk9IjEwJSIgeD0iODAlIiBmaWxsPSJoc2woOTAsMTAwJSw4MCUpIj5Ub2tlbjogMTwvdGV4dD48dGV4dCBmb250LXNpemU9IjE4IiB5PSI1MCUiIHg9IjUwJSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iaHNsKDkwLDEwMCUsODAlKSI+dXNlclRleHQ8L3RleHQ+PC9zdmc+",
 "attributes": [
   {
     "trait_type": "TextColor",
     "value":"328"
   }
 ]
}

Thông thường, giá trị "hình ảnh" của chúng tôi trông như thế này:

{
"image": "ipfs://QmWwMDLz6hQKCqjYba5cSHdrNUvPvAdndtaWjdFpm52GYm/1.gif"

}

Vậy điều gì đang xảy ra với giá trị hình ảnh của chúng tôi? Giá trị hình ảnh của chúng tôi là 1 - SVG và 2 - SVG cũng được mã hóa Base64, điều này có nghĩa là văn bản SVG của chúng tôi đã được mã hóa như dữ liệu json (văn bản).

Có thể nhận thấy rằng chúng tôi đã thêm một số nội dung vào json được mã hóa, như sau:

"dữ liệu ứng dụng/json:; base64."

Điều này chỉ đơn giản mô tả dữ liệu là gì và làm thế nào nó có thể được giải mã tương ứng bởi người nhận hoặc trình duyệt của người nhận.

mã hóa ABI

Chúng tôi cũng thực hiện mã hóa ABI trong toàn bộ mã dự án. Trong trường hợp của chúng tôi, mã hóa ABI hoặc Giao diện nhị phân ứng dụng chỉ cho phép chúng tôi nối nhiều dòng văn bản. "This", "is", "my", "code" sẽ gây ra lỗi nếu chúng không được mã hóa thành một chuỗi.

tệp SVG

SVG là gì và tại sao nó lại quan trọng đối với chúng tôi?

SVG hoặc Đồ họa vectơ có thể mở rộng về cơ bản cho phép chúng tôi lưu trữ hình ảnh ở định dạng loại xml hoặc dưới dạng văn bản; văn bản có thể được lưu trữ trên chuỗi. Thay vì lưu trữ dữ liệu hình ảnh lớn, chúng tôi mô tả hình ảnh chúng tôi muốn dưới dạng văn bản và mã hóa hình ảnh đó theo cách mà trình duyệt của chúng tôi và OpenSea có thể hiển thị hình ảnh đó cho chúng tôi. Chúng tôi có thể đặt các đặc điểm khác nhau của hình ảnh, bao gồm kích thước, màu sắc và thậm chí cả văn bản có thể được hiển thị cho chúng tôi.

Hãy nghĩ theo cách này, nếu tôi muốn gửi cho bạn một hình ảnh đơn giản, tôi có thể gửi email hoặc nhắn tin cho một hình ảnh PNG có độ phân giải cao hoặc bạn có thể chỉ cần mô tả nó bằng một vài từ và để biên nhận của bạn Người gửi hiển thị hoặc tạo nó cho bạn . Nếu truyền dữ liệu đắt, chúng ta có thể thực hiện một "sự đánh đổi" để giảm chi phí bằng cách tăng chi phí của người nhận (như một nỗ lực).

Mô tả văn bản bên dưới có thể sẽ tốn ít dữ liệu hơn nhiều để truyền sau đó HD PNG. Miễn là người nhận có các công cụ để dễ dàng trình bày điều này, chúng tôi sẽ giảm đáng kể chi phí lưu trữ hoặc truyền dữ liệu:

"Nền xanh 500x500 với chữ trắng có nội dung 'Xin chào thế giới'"

Mã ví dụ của chúng tôi mô tả các tham số của SVG trong hàm BuildImage.

Có nhiều công cụ và mẫu trực tuyến tuyệt vời để tạo SVG và tôi khuyến khích bạn tìm một số mẫu sẽ giúp bạn chuyển ý tưởng của mình thành SVG.

Đảm bảo sử dụng tỷ lệ phần trăm cho bố cục, vì các giá trị "được mã hóa cứng" trong quá trình phát triển ứng dụng có thể gây ra sự cố khi chúng tôi tăng hoặc giảm kích thước màn hình hiển thị. 1000px làm điểm bắt đầu cho văn bản vẫn ổn cho đến khi chúng tôi giảm kích thước màn hình của thiết bị xuống dưới 1000x1000, trong trường hợp đó, chúng tôi nên đặt thành 80%.

SVG của chúng tôi, trước mã hóa ABI và Base64:

'',
'',
'Some Text',
'Some Text',
'Some Text',
'Token: ',
_tokenId.toString(),
"
",
'',
currentWord.value,
"
",

""

Một lần nữa chúng tôi sẽ thông báo rằng chúng tôi đã đính kèm thông tin chi tiết về dữ liệu:

“data:image/svg+xml;base64”

đầu vào của người dùng

Một trong những tính năng thú vị hơn của hợp đồng thông minh của chúng tôi là khả năng người dùng đóng góp vào NFT cuối cùng bằng cách nhập một số dữ liệu văn bản vào hàm đúc. Đầu vào của người dùng này được lưu dưới dạng "chuỗi trong bộ nhớ" và sau đó được thêm động vào dữ liệu SVG của chúng tôi thông qua chức năng BuildImage.

Tôi đã giới hạn kích thước của kiểu nhập văn bản và thêm một lỗi cho giới hạn này, nhưng người dùng hoàn toàn biết họ có thể thêm những gì. Điều này là bất biến và tồn tại mãi mãi trên blockchain.

Hàm đúc của chúng tôi thực hiện điều này bằng cách thêm một chuỗi kỳ vọng vào hàm:

function mint(string memory _userText) public payable {
   uint256 supply = totalSupply();
   bytes memory strBytes = bytes(_userText);
   require(strBytes.length <= stringLimit, "String input exceeds limit.");
   require(exists(_userText) != true, "String already exists!");
   
   Word memory newWord = Word(
       string(
           abi.encodePacked(
               "NFT",
               uint256(supply + 1).toString()
           )
       ),
       "This is our on-chain NFT",
       randomNum(361, block.difficulty, supply).toString(),
       randomNum(361, block.timestamp, supply).toString(),
       _userText
   );
   if (msg.sender != owner()) {
       require(msg.value >= 0.005 ether);
   }
   wordsToTokenId[supply + 1] = newWord; //Add word to mapping @tokenId

   _safeMint(msg.sender, supply + 1);

NFT và tương tác hợp đồng thông minh

Nếu bạn đang sử dụng một công cụ như Remix, bạn chỉ cần sửa đổi mã được cung cấp, tải nó lên Remix, biên dịch và triển khai để thử nghiệm.

Vì hàm đúc của chúng tôi yêu cầu người dùng nhập dữ liệu chuỗi, có thể thêm văn bản và sau đó sử dụng hàm tokenURI của chúng tôi để xem những gì được tạo ra, đây là cùng một hàm tokenURI mà các thị trường như OpenSea sẽ tận dụng để truy xuất hoặc phân tích dữ liệu NFT của chúng tôi và hình ảnh.

Vậy chúng ta phải làm như thế nào? Để hiển thị nó trong trình duyệt của bạn, sau đó chúng ta cần sao chép mọi thứ sau "chuỗi" (chúng ta không cần điều này) và dán nó vào trình duyệt của mình. Kết quả của việc dán này vào trình duyệt của chúng tôi sẽ như thế này:

Ngoài ra, chúng tôi có thể xem hình ảnh của mình bằng cách sao chép giá trị "hình ảnh", phần chúng tôi muốn sao chép được đánh dấu ở đây:

Kết quả trông như thế này:

Dữ liệu hình ảnh được dán vào trình duyệt cục bộ của chúng tôi

NFT của chúng tôi

liên kết gốc

liên kết gốc

NFT
Chào mừng tham gia cộng đồng chính thức của Odaily
Nhóm đăng ký
https://t.me/Odaily_News
Nhóm trò chuyện
https://t.me/Odaily_CryptoPunk
Tài khoản chính thức
https://twitter.com/OdailyChina
Nhóm trò chuyện
https://t.me/Odaily_CryptoPunk