本系列文將分享如何使用 Python 的 Brownie 框架開發 ERC-721,也就是 NFT。並且 deploy contract 到 Ethereum 的測試網路 Rinkeby,圖檔和 Metadata 則上傳到 IPFS,再透過測試版本的 Opensea 來看看成果!

在上一篇 自己寫 NFT 吧!- 準備 Metadata – 以 Python Brownie 開發 我們已經準備好 Metadata,接下來要實際 deploy smart contract 到 testnet,並透過測試版本的 Opensea 來檢查是否有問題。

取得測試用的 Ether

我們選用 Ethereum 的 testnet Rinkeby 來做測試,先乞討幾個 ether 來用用,這邊列出幾個可以要 ether 的 faucet

Rinkeby Authenticated Faucet

他乞討法比較麻煩
1. 必須將你的錢包位置用 twitter 或 FB 發文,權限設置公開
2. 將該篇貼文的網址貼到 Faucet 輸入匡中
3. 選擇你想要乞討的數量,數量越多,下次能再乞討的時間間隔就越長
4. 等待 transaction 一段時間,就會發現錢包 eth 數量上升

優點:可以一次要很多 eth,在 testnet 成富人
缺點:服務好像不太穩定,最近常常 offline

如何以 Python Brownie 開發 DeFi 應用?- 發個 NFT 吧!Deploy 到 Rinkeby testnet
直接用錢包位置 po 文
如何以 Python Brownie 開發 DeFi 應用?- 發個 NFT 吧!Deploy 到 Rinkeby testnet
把 po 文的公開網址貼入乞討 eth

另一個是使用 Chainlink 提供的 Faucet

Chainlink Request testnet LINK

他的方法很簡單
1. 連結你的錢包
2. 驗證不是機器人後,直接點要 eth 即可

優點:要 eth 非常簡單迅速,還可以順便要 LINK token
缺點:一次只能要 0.1 eth

如何以 Python Brownie 開發 DeFi 應用?- 發個 NFT 吧!Deploy 到 Rinkeby testnet

將私鑰匯入 Brownie

要在 Rinkeby testnet 上 deploy smart contract,必須先將 account 的私鑰匯入 Brownie,才能正確簽署 transaction。

為了安全,極度不建議把私鑰寫在 brownie-config.yaml 或者是用環境變數儲存。除非該 account 只用在 testnet 上,沒有真實資產。一旦私鑰被盜走,等同把 account 交到駭客手中,所有資產都受人擺佈囉!

在 console 輸入以下指令,id 替換成你為這個 account 取的代稱

$ brownie accounts new <id>

enter 後 Brownie 會請你輸入 account 的私鑰

Brownie v1.17.2 - Python development framework for Ethereum

Enter the private key you wish to add:

接下來一定要設定密碼保護

Enter the password to encrypt this account with: 

如此 accounts 就順利匯入了

申請 Infura 帳號並開通 api

我們需要透過節點與區塊鏈溝通,在 local 時使用 Ganache 架設開發用的節點,到 testnet 除了可以自己跑 Ethereum 節點,也可以直接使用第三方暴露的節點 api ,省去自架節點的麻煩。

透過指令 brownie networks list 可以看到 Brownie 已經幫開發者預設很多 用 Infura 做節點的 network,我們只需要申請帳號,取得 Project ID 並設定就能直接使用囉!

自己寫 NFT 吧!- Deploy 到 Rinkeby testnet – 以 Python Brownie 開發

前往 Infura 申請帳號,點選 Create Project,Product 選擇 Ethereum,填入 Project Name 後點擊 create

自己寫 NFT 吧!- Deploy 到 Rinkeby testnet – 以 Python Brownie 開發

複製畫面中的 Project ID

自己寫 NFT 吧!- Deploy 到 Rinkeby testnet – 以 Python Brownie 開發

在專案根目錄下的 .env 檔增加一個變數 WEB3_INFURA_PROJECT_ID,並設定剛剛複製的 Project ID 即可完成

WEB3_INFURA_PROJECT_ID=<your_project_id>

Deploy ECR-721 Contract 囉!

deploy 的方法我們在 自己寫 NFT 吧!- Deploy 到 Ganache – 以 Python Brownie 開發 有做過介紹,但這次要 deploy 到 testnet,不像 local 一樣有 10 個預設 accounts,我們需要使用剛剛匯入的 account,因此要做一些修改。

假設我們剛剛匯入的 account id 為 my-account,在 brownie-config.yml 中新增 rinkeby network,並在下面加上 account: my-account

dotenv: .env
networks:
  default: development
  rinkeby:
    account: my-account

開一個 utils.py,新增一個 get_account 函數:

  1. network.show_active() 中取得目前 network 的 name (如 rinkeby)
  2. 如果 name 是 “`development ,表是為 local 測試用的鏈,回傳第一個 account
  3. 反之為 testnet 或 main-net,從 config 中取得對應 network 的 account 名稱(如 my-account)
from brownie import network, config, accounts

def get_account():
    network_name = network.show_active()
    if network_name == "development":
        return accounts[0]
    else:
        return accounts.load(config["networks"][network_name]["account"])

回頭修改 deploy.py 中取用 account 的部分

from scripts.utils import get_account

def main():
    # owner = accounts[0]
    owner = get_account()  # 改成使用 util function

    kong_long = KongLongNFT.deploy({"from": owner})
    ...

一樣到 console 下 deploy,指定 network 為 rinkeby

$ brownie run script/deploy.py --network rinkeby

此時 Brownie 會提示你需要密碼,輸入剛剛匯入 account 所設定的

Running 'scripts/kong_long_nft.py::main'...
Enter password for "my-account": 

enter 後,brownie 就會送出 transaction。因為是在非 local 的區塊鏈上操作,需要等待一段時間才能有結果,長短依照當時網路擁塞而定。

Mint NFT 囉!

接下來要 mint,稍微修改一下 mint.py

def main():
    # owner = accounts[0]
    owner = get_account() # 改成使用 util function
    # receiver = accounts[1]
    receiver = get_account()  # receiver 位置改成自己方便測試
    # nft = KongLongNFT.at('0x684f51E9A4Ec41DDaC067A9E03eECad3274F4FDd')
    nft = KongLongNFT[-1]  # 改成使用最後 deploy 的 contract,不 hard code contract address
    # uri 記得改成你自己的 CID
    nft.mintToken(receiver, "ipfs://QmXfFYmRnEGnWbnUfRsVMZz4pF9gY9wyJfkGUMsfnpndUH", {"from": owner})
    ...

到 console 下 mint

$ brownie run script/mint.py --network rinkeby

立馬到 testnet 版的 OpenSea 瞧瞧自己的 collection。如果還沒出現是正常的,實測 mint 後需要一段時間 OpenSea 才會抓到新的 NFT

自己寫 NFT 吧!- Deploy 到 Rinkeby testnet – 以 Python Brownie 開發

如果像下面這樣,一直抓不到 NFT 的圖片和標題描述,可能是 Metadata 的格式或者 URI 出問題,參考 如何以 Python Brownie 開發 DeFi 應用?- 發個 NFT 吧!準備 Metadata 檢查一下吧!

自己寫 NFT 吧!- Deploy 到 Rinkeby testnet – 以 Python Brownie 開發

到這整個 ERC-721 從環境準備、撰寫 smart contract、準備 metadata、發布到 testnet Rinkeby 的流程我們都一起走過一遍,相信大家對 blockchain development 也有初步的認識。想要發布到 main-net 上玩玩?其實方法一樣,但是 Ehtereum 太貴了!下次我們來看看如何使用側鏈 Polygon 來發布,節省你的 gas 費!

延伸閱讀:
如何以 Python Brownie 開發 DeFi 應用?- 環境準備
自己寫 NFT 吧!- 實現 ERC-721 – 以 Python Brownie 開發
自己寫 NFT 吧!- Deploy 到 Ganache – 以 Python Brownie 開發
自己寫 NFT 吧!- 準備 Metadata – 以 Python Brownie 開發

Written by J
雖然大學唸的是生物,但持著興趣與熱情自學,畢業後轉戰硬體工程師,與宅宅工程師們一起過著沒日沒夜的生活,做著台灣最薄的 intel 筆電,要與 macbook air 比拼。 離開後,憑著一股傻勁與朋友創業,再度轉戰軟體工程師,一手扛起前後端、雙平台 app 開發,過程中雖跌跌撞撞,卻也累計不少經驗。 可惜不是那 1% 的成功人士,於是加入其他成功人士的新創公司,專職開發後端。沒想到卻在採前人坑的過程中,拓寬了眼界,得到了深層的領悟。