五分鐘學會如何使用Solidity建立鏈上NFT

買賣虛擬貨幣

創造 nft 並非一個難於登青天的事情。

鏈下nft

這就引出了一個問題,不是所有的 nft 都在鏈上嗎 ?任何在以太坊區塊鏈的nft工作過的人都可以告訴你,鏈上資料儲存確實存在限制;因為這是非常昂貴的,而且大多數nft專案都是在鏈下儲存影象和後設資料檔案。通常我們看到的儲存在“鏈上”的唯一資料是後設資料(我們的tokenuri)的不可變雜湊——描述這個雜湊的最簡單的方法是連結到我們實際的nft,這裡的區別是雜湊依賴於建立它的資料;改變源,雜湊不再有效,因此它是不可變的。任何人都可以執行一個ipfs節點就像任何人都可以執行一個區塊鏈節點礦工或共識。

現在,我們可能對loot這樣的“鏈上”專案很熟悉,這個專案是如何完成的? 我們真的能在鏈上儲存合適的視覺媒體嗎?

答案是肯定的,但它需要一些東西,即base64編碼和svg影象型別。兩者都允許我們處理文字資料,而不是像 png 或 jpeg 這樣典型的記憶體“重”視覺資料。這意味著我們需要做兩件事:

  • base64編碼我們的json後設資料

  • 以 svg 格式編碼影象渲染的“指令”

幸運的是,瀏覽器可以理解這兩種格式,基於瀏覽器的市場(如 opensea)可以以與 ipfs 儲存雜湊的連結相同的方式呈現我們的 nft,然而,瀏覽器不是“獲取和快取”影象,而是為我們呈現影象。

base64編碼

實現鏈上後設資料儲存並避免對任何工具(如ipfs)的需求的一種方法是對其進行base64編碼,並將其直接儲存在我們的nft代幣資料中。在我們的例子中,tokenuri會以編碼格式返回實際的後設資料:這不再是一個“連結”,而是後設資料本身。

正如我所說的,我們將利用來自 github 的現有 base64.sol 庫。可以從github匯入或簡單地克隆/複製程式碼,並從貼上此檔案的同一目錄匯入此檔案。

關於base64的編碼需要注意的是,編碼並不是一種資料壓縮形式,因此我們並沒有減少資料的大小,我們只是將其儲存在瀏覽器可以解碼的格式中。我們的後設資料不是非常大,這就是我們的nft影象的情況。下面是一個例子:

在我們的示例程式碼中,我們利用了函式' buildmetadata ',它接受一個tokenid(我們的nft的id),並返回一個base64編碼的json文字字串,其中包含 opensea 使用其名稱、描述、屬性呈現我們的 nft 所需的一切,非常重要的是,我們的形象。它還利用了我將在下面解釋的 buildimage 函式。

以下是我們的後設資料示例:

{
 "name":"nft1",
 "description":"this is our on-chain nft",
 "image": "data:image/svg+xml;base64,phn2zyb3awr0ad0intawiibozwlnahq9ijuwmcigeg1sbnm9imh0dha6ly93d3cudzmub3jnlziwmdavc3znij48cmvjdcbpzd0ic3znxzexiibozwlnahq9ijywmcigd2lkdgg9ijuwmyiget0imciged0imcigzmlsbd0iahnskdi5myw1mcusmjulksivpjx0zxh0igzvbnqtc2l6zt0im**iihk9ijewjsiged0insuiigzpbgw9imhzbcg5mcwxmdalldgwjskiplnvbwugvgv4ddwvdgv4dd48dgv4dcbmb250lxnpemu9ije4iib5psixnsuiihg9ijuliibmawxspsjoc2wootasmtawjsw4mcupij5tb21lifrlehq8l3rlehq+phrlehqgzm9udc1zaxplpsixociget0imjaliib4psi1jsigzmlsbd0iahnskdkwldewmcusodalksi+u29tzsbuzxh0pc90zxh0pjx0zxh0igzvbnqtc2l6zt0im**iihk9ijewjsiged0iodaliibmawxspsjoc2wootasmtawjsw4mcupij5ub2tlbjogmtwvdgv4dd48dgv4dcbmb250lxnpemu9ije4iib5psi1mcuiihg9ijuwjsigdgv4dc1hbmnob3i9im1pzgrszsigzmlsbd0iahnskdkwldewmcusodalksi+dxnlclrlehq8l3rlehq+pc9zdmc+",
 "attributes": [
   {
     "trait_type": "textcolor",
     "value":"328"
   }
 ]
}

通常情況下,我們的“image”值是這樣的:

{
"image": "ipfs://qmwwmdlz6hqkcqjyba5cshdrnuvpvadndtawjdfpm52gym/1.gif"
}

那麼我們的image值是怎麼回事?我們的image值是1 - svg和2 - svg也是base64編碼的;這意味著我們的svg文字已經像json(文字)資料一樣被進行了編碼。

可以注意到,我們在編碼後的json中新增了一些內容,如下所示:

“application / json資料:;base64。”

這只是簡單地描述了資料是什麼,以及接收方或接收方瀏覽器如何對其進行相應的解碼。

abi編碼

我們還在整個專案程式碼中執行abi編碼。在我們的例子中,abi編碼或應用程式二進位制介面只允許我們連線多行文字。“this”,“is”,“my”,“code”如果沒有被編碼成單個字串,就會導致錯誤。

svg檔案

什麼是svg,為什麼它對我們很重要?

svg或可伸縮的向量圖形本質上允許我們以xml型別格式或文字形式儲存影象;可以儲存在鏈上的文字。我們不是儲存大的影象資料,而是用文字描述我們想要的影象,並以我們的瀏覽器和opensea可以為我們呈現的方式對其進行編碼。我們可以設定影象的各種特徵,包括大小,顏色,甚至可以為我們呈現的文字。

可以這樣想,如果我想給你傳送一張簡單的圖片,我可以透過電子郵件或文字傳送一張高解析度的png影象,或者你可以簡單地用幾個詞描述它,然後讓你的收件人為你呈現或生成它。如果資料傳輸是昂貴的,我們可以做一個“權衡”,透過增加接收者的成本(作為努力)來降低成本。

下面的文字描述可能要傳輸的資料密集程度要低得多,然後是高畫質 png。只要收件人有工具可以輕鬆地呈現這一點,我們就大大降低了資料儲存或傳輸方面的成本:

“500x500大小的藍色背景,白色文字寫著‘hello world’”

我們的示例程式碼在函式buildimage中描述svg的引數。

有很多很棒的生成svg的線上工具和模板,我鼓勵你找到一些有助於將自己的想法變為 svg 的工具。

確保使用百分比進行佈局,因為應用開發的“硬編碼”值可能會在我們增加或減少渲染的螢幕尺寸時帶來問題。1000畫素作為文字的起始點是可以的,直到我們將裝置的螢幕尺寸減小到1000x1000以下,在這種情況下,我們最好將其設定為80%。

我們的svg,在abi和base64編碼之前:

'<svg width="500" height="500" xmlns="http://www.w3.org/2000/svg">',
'<rect id="svg_11" height="600" width="503" y="0" x="0" fill="hsl(',
currentword.bghue,
',50%,25%)"/>',
'<text font-size="18" y="10%" x="5%" fill="hsl(',
random,
',100%,80%)">some text</text>',
'<text font-size="18" y="15%" x="5%" fill="hsl(',
random,
',100%,80%)">some text</text>',
'<text font-size="18" y="20%" x="5%" fill="hsl(',
random,
',100%,80%)">some text</text>',
'<text font-size="18" y="10%" x="80%" fill="hsl(',
random,
',100%,80%)">token: ',
_tokenid.tostring(),
"</text>",
'<text font-size="18" y="50%" x="50%" text-anchor="middle" fill="hsl(',
random,
',100%,80%)">',
currentword.value,
"</text>",
"</svg>"

我們將再次注意到我們已附加有關資料的詳細資訊:

“data:image/svg+xml;base64”

使用者輸入

我們的智慧合約更有趣的功能之一是使用者能夠透過將一些文字資料輸入到 mint 函式中來為最終的 nft 做出貢獻。這個使用者輸入被儲存為“記憶體字串”,然後透過buildimage函式動態地新增到我們的svg資料中。

我限制了文字輸入的大小併為此限制新增了一個錯誤,但使用者可以完全瞭解他們可能新增的內容。這是不可改變的,永遠存在於區塊鏈。

我們的mint函式透過在函式上新增一個字串期望來實現這個功能:

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和智慧合約互動

如果你正在使用remix之類的工具,可以簡單地修改提供的程式碼,將其上傳到remix,編譯並部署以進行測試。

由於我們的mint函式需要使用者輸入字串資料,能夠新增文字,然後利用我們的tokenuri函式來檢視產生的內容,這是相同的tokenuri函式,像opensea這樣的市場將利用來檢索或解析我們的nft資料和影象。

那麼我們該怎麼做呢?要在您的瀏覽器中呈現它,然後需要複製“字串”之後的所有內容(我們不需要這個)並將其貼上到我們的瀏覽器中。將其貼上到我們的瀏覽器中的結果將如下所示:

此外,我們可以透過複製“image”值來檢視我們的影象,我們想要複製的部分在這裡突出顯示:

結果如下所示:

         影象資料貼上到我們的本地瀏覽器中

我們的nft

這樣,我們就建立了一個智慧合約,允許使用者在生成文字時輸入文字,生成包含使用者輸入的svg資料,將其編碼為base64,並將其新增到同樣是base64編碼的後設資料中。其結果是,鏈上nft將在opensea等市場中呈現如下內容:


原文連結


免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;