Trong hướng dẫn này, chúng ta sẽ tìm hiểu cách xây dựng một trang web để thu thập các đồ sưu tầm kỹ thuật số (hoặc NFT) trên blockchain Flow. Chúng tôi sẽ sử dụng ngôn ngữ hợp đồng thông minh Cadence cùng với React để biến tất cả thành hiện thực. Chúng ta cũng sẽ tìm hiểu về Flow, những ưu điểm của nó và những công cụ thú vị mà chúng ta có thể sử dụng.
Đến cuối bài viết này, bạn sẽ có các công cụ và kiến thức cần thiết để tạo ứng dụng phi tập trung của riêng mình trên chuỗi khối Flow.
Hãy đi sâu vào ngay!
Chúng tôi đang xây dựng một ứng dụng dành cho sưu tầm kỹ thuật số. Mỗi bộ sưu tập là một Mã thông báo không thể thay thế (NFT).
Để thực hiện tất cả những điều này, chúng tôi sẽ sử dụng Tiêu chuẩn NonFungibleToken của Flow, đây là một bộ quy tắc giúp chúng tôi quản lý các mục kỹ thuật số đặc biệt này (tương tự như ERC-721 trong Ethereum).
Trước khi bắt đầu, hãy nhớ cài đặt Flow CLI trên hệ thống của bạn. Nếu bạn chưa làm như vậy, hãy làm theo các hướng dẫn cài đặt sau.
Nếu bạn đã sẵn sàng khởi động dự án của mình, trước tiên, hãy nhập thiết lập luồng lệnh.
Lệnh này thực hiện một số phép thuật đằng sau hậu trường để thiết lập nền tảng cho dự án của bạn. Nó tạo ra một hệ thống thư mục và thiết lập một tệp có tên flow.json để định cấu hình dự án của bạn, đảm bảo mọi thứ đều được sắp xếp và sẵn sàng hoạt động!
Dự án sẽ chứa thư mục cadence
và tệp flow.json
. (Tệp flow.json là tệp cấu hình cho dự án của bạn, được duy trì tự động.)
Thư mục Cadence chứa các mục sau:
Thực hiện theo các bước bên dưới để sử dụng Tiêu chuẩn Flow NFT.
Đầu tiên, hãy chuyển đến thư mục flow-collectibles-portal
và tìm thư mục cadence
. Sau đó, mở thư mục contracts
. Tạo một tệp mới và đặt tên là NonFungibleToken.cdc
.
Bây giờ, hãy mở liên kết có tên NonFungibleToken chứa tiêu chuẩn NFT. Sao chép tất cả nội dung từ tệp đó và dán vào tệp mới bạn vừa tạo ("NonFungibleToken.cdc").
Đó là nó! Bạn đã thiết lập thành công các tiêu chuẩn cho dự án của mình.
Bây giờ, hãy viết một số mã!
Tuy nhiên, trước khi đi sâu vào mã hóa, điều quan trọng là các nhà phát triển phải thiết lập một mô hình tinh thần về cách cấu trúc mã của họ.
Ở cấp cao nhất, cơ sở mã của chúng tôi bao gồm ba thành phần chính:
NFT: Mỗi bộ sưu tập được thể hiện dưới dạng NFT.
Bộ sưu tập: Bộ sưu tập đề cập đến một nhóm NFT do một người dùng cụ thể sở hữu.
Hàm và biến toàn cầu: Đây là các hàm và biến được xác định ở cấp độ toàn cầu cho hợp đồng thông minh và không được liên kết với bất kỳ tài nguyên cụ thể nào.
Tạo một tệp mới có tên Collectibles.cdc
bên trong cadence/contracts
. Đây là nơi chúng ta sẽ viết mã.
Cấu trúc hợp đồng
import NonFungibleToken from "./NonFungibleToken.cdc" pub contract Collectibles: NonFungibleToken{ pub var totalSupply: UInt64 // other code will come here init(){ self.totalSupply = 0 } }
Hãy chia nhỏ từng dòng mã:
Trước tiên, chúng tôi cần tiêu chuẩn hóa rằng chúng tôi đang xây dựng NFT bằng cách đưa vào cái gọi là "NonFungibleToken". Đây là tiêu chuẩn NFT do Flow xây dựng nhằm xác định bộ chức năng sau đây phải có trong mỗi hợp đồng thông minh NFT.
Sau khi nhập, hãy tạo hợp đồng của chúng tôi. Để làm điều đó, chúng tôi sử dụng pub contract [contract name]
. Sử dụng cùng một cú pháp mỗi lần bạn tạo hợp đồng mới. Bạn có thể điền contract name
bằng bất cứ tên nào bạn muốn gọi cho hợp đồng của mình. Trong trường hợp của chúng tôi, hãy gọi nó là Collectibles
.
Tiếp theo, chúng tôi muốn đảm bảo rằng hợp đồng của chúng tôi tuân theo một bộ chức năng và quy tắc nhất định của NonFungibleToken. Để làm điều đó, chúng tôi thêm giao diện NonFungibleToken với sự trợ giúp của `:`.
Như thế này ( `pub contract Collectibles: NonFungibleToken{}`
)
Mỗi hợp đồng PHẢI có hàm init()
. Nó được gọi khi hợp đồng ban đầu được triển khai. Điều này tương tự như những gì Solidity gọi là Trình xây dựng.
Bây giờ, hãy tạo một biến toàn cục có tên totalSupply
với kiểu dữ liệu UInt64
. Biến này sẽ theo dõi tổng số Đồ sưu tầm của bạn.
Bây giờ, khởi tạo totalSupply
với giá trị 0
.
Đó là nó! Chúng tôi thiết lập nền tảng cho hợp đồng Collectibles
của mình. Bây giờ, chúng ta có thể bắt đầu thêm nhiều tính năng và chức năng hơn để khiến nó trở nên thú vị hơn nữa.
Trước khi tiếp tục, vui lòng xem đoạn mã để hiểu cách chúng tôi xác định các biến trong Cadence:
Thêm mã sau vào hợp đồng thông minh của bạn:
import NonFungibleToken from "./NonFungibleToken.cdc" pub contract Collectibles: NonFungibleToken{ // above code… pub resource NFT: NonFungibleToken.INFT{ pub let id: UInt64 pub var name: String pub var image: String init(_id:UInt64, _name:String, _image:String){ self.id = _id self.name = _name self.image = _image } } // init()... }
Như bạn đã thấy trước đây, hợp đồng triển khai giao diện chuẩn NFT, được biểu thị bằng pub contract Collectibles: NonFungibleToken
. Tương tự, các tài nguyên cũng có thể triển khai các giao diện tài nguyên khác nhau.
Vì vậy, hãy thêm giao diện NonFungibleToken.INFT
vào Tài nguyên NFT, giao diện này bắt buộc phải tồn tại một thuộc tính công cộng có tên id trong tài nguyên.
Dưới đây là các biến chúng tôi sẽ sử dụng trong tài nguyên NFT:
id:
Duy trì ID của NFTname:
Tên của NFT.image:
URL hình ảnh của NFT.
Sau khi xác định biến, hãy nhớ khởi tạo biến trong hàm init()
.
Hãy tiếp tục và tạo một tài nguyên khác có tên là Collection Resource
.
Trước tiên, bạn cần hiểu cách hoạt động Collection Resources
.
Nếu bạn cần lưu trữ một tập tin nhạc và một vài bức ảnh trên máy tính xách tay của mình, bạn sẽ làm gì?
Thông thường, bạn sẽ điều hướng đến một ổ đĩa cục bộ (giả sử là D-Drive của bạn) và tạo thư mục music
và thư mục photos
. Sau đó, bạn sẽ sao chép và dán các tệp nhạc và ảnh vào thư mục đích của mình.
Tương tự, đây là cách hoạt động của các bộ sưu tập kỹ thuật số của bạn trên Flow.
Hãy tưởng tượng máy tính xách tay của bạn là Flow Blockchain Account
, D-Drive của bạn là Account Storage
và Thư mục là Collection
.
Vì vậy, khi tương tác với bất kỳ dự án nào để mua NFT, dự án sẽ tạo collection
của nó trong account storage
của bạn, tương tự như việc tạo một thư mục trên D-Drive của bạn. Khi bạn tương tác với 10 dự án NFT khác nhau, bạn sẽ có 10 bộ sưu tập khác nhau trong tài khoản của mình.
Nó giống như có một không gian cá nhân để lưu trữ và sắp xếp kho báu kỹ thuật số độc đáo của bạn!
import NonFungibleToken from "./NonFungibleToken.cdc" pub contract Collectibles: NonFungibleToken{ //Above code NFT Resource… // Collection Resource pub resource Collection{ } // Below code… }
Mỗi collection
có một biến ownedNFTs
để chứa NFT Resources
.
pub resource Collection { pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT} init(){ self.ownedNFTs <- {} } }
Giao diện tài nguyên
Giao diện resource
trong Flow tương tự như giao diện trong các ngôn ngữ lập trình khác. Nó nằm trên một tài nguyên và đảm bảo rằng tài nguyên triển khai nó có chức năng cần thiết như được xác định bởi giao diện.
Nó cũng có thể được sử dụng để hạn chế quyền truy cập vào toàn bộ tài nguyên và hạn chế hơn về mặt sửa đổi quyền truy cập so với chính tài nguyên đó.
Trong tiêu chuẩn NonFungibleToken
, có một số giao diện tài nguyên như INFT
, Provider
, Receiver
và CollectionPublic
.
Mỗi giao diện này có các chức năng và trường cụ thể cần được triển khai bởi tài nguyên sử dụng chúng.
Trong hợp đồng này, chúng tôi sẽ sử dụng ba giao diện này từ NonFungibleToken: Provider
, Receiver
và CollectionPublic
. Các giao diện này xác định các chức năng như deposit
, withdraw
, borrowNFT
và getIDs
. Chúng tôi sẽ giải thích chi tiết từng điều này khi chúng tôi tiếp tục.
Chúng tôi cũng sẽ thêm một số sự kiện mà chúng tôi sẽ phát ra từ các hàm này, cũng như khai báo một số biến mà chúng tôi sẽ sử dụng thêm trong hướng dẫn.
pub contract Collectibles:NonFungibleToken{ // rest of the code… pub event ContractInitialized() pub event Withdraw(id: UInt64, from: Address?) pub event Deposit(id: UInt64, to: Address?) pub let CollectionStoragePath: StoragePath pub let CollectionPublicPath: PublicPath pub resource interface CollectionPublic{ pub fun deposit(token: @NonFungibleToken.NFT) pub fun getIDs(): [UInt64] pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT } pub resource Collection: CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic{ pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT} init(){ self.ownedNFTs <- {} } } }
Rút
Bây giờ, hãy tạo withdraw()
theo yêu cầu của giao diện.
pub resource Collection: CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic{ // other code pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT { let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT") emit Withdraw(id: token.id, from: self.owner?.address) return <- token } init()... }
Với sự trợ giúp của chức năng này, bạn có thể di chuyển tài nguyên NFT ra khỏi bộ sưu tập. Nếu nó:
Sau đó, người gọi có thể sử dụng tài nguyên này và lưu nó vào bộ nhớ tài khoản của họ.
Tiền gửi
Bây giờ là lúc dùng hàm deposit()
mà NonFungibleToken.Receiver
yêu cầu.
pub resource Collection: CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic{ // other code pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT { let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT") emit Withdraw(id: token.id, from: self.owner?.address) return <- token } pub fun deposit(token: @NonFungibleToken.NFT) { let id = token.id let oldToken <- self.ownedNFTs[id] <-token destroy oldToken emit Deposit(id: id, to: self.owner?.address) } init()... }
Vay và GetID
Bây giờ, hãy tập trung vào hai hàm mà NonFungibleToken.CollectionPublic: borrowNFT()
và getID()
.
pub resource Collection: CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic{ // other code pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT { let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT") emit Withdraw(id: token.id, from: self.owner?.address) return <- token } pub fun deposit(token: @NonFungibleToken.NFT) { let id = token.id let oldToken <- self.ownedNFTs[id] <-token destroy oldToken emit Deposit(id: id, to: self.owner?.address) } pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT { if self.ownedNFTs[id] != nil { return (&self.ownedNFTs[id] as &NonFungibleToken.NFT?)! } panic("NFT not found in collection.") } pub fun getIDs(): [UInt64]{ return self.ownedNFTs.keys } init()... }
Hàm hủy diệt
Điều cuối cùng chúng ta cần cho Tài nguyên Bộ sưu tập là một hàm hủy.
destroy (){ destroy self.ownedNFTs }
Vì tài nguyên Bộ sưu tập chứa các tài nguyên khác (tài nguyên NFT), nên chúng ta cần chỉ định một hàm hủy. Hàm hủy sẽ chạy khi đối tượng bị phá hủy. Điều này đảm bảo rằng tài nguyên không bị "vô gia cư" khi tài nguyên gốc của chúng bị phá hủy. Chúng tôi không cần hàm hủy cho tài nguyên NFT vì nó không chứa bất kỳ tài nguyên nào khác.
Hãy xem mã nguồn tài nguyên bộ sưu tập hoàn chỉnh:
import NonFungibleToken from "./NonFungibleToken.cdc" pub contract Collectibles: NonFungibleToken{ pub var totalSupply: UInt64 pub resource NFT: NonFungibleToken.INFT{ pub let id: UInt64 pub var name: String pub var image: String init(_id:UInt64, _name:String, _image:String){ self.id = _id self.name = _name self.image = _image } } pub resource interface CollectionPublic{ pub fun deposit(token: @NonFungibleToken.NFT) pub fun getIDs(): [UInt64] pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT } pub event ContractInitialized() pub event Withdraw(id: UInt64, from: Address?) pub event Deposit(id: UInt64, to: Address?) pub let CollectionStoragePath: StoragePath pub let CollectionPublicPath: PublicPath pub resource Collection: CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic{ pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT} init(){ self.ownedNFTs <- {} } destroy (){ destroy self.ownedNFTs } pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT { let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT") emit Withdraw(id: token.id, from: self.owner?.address) return <- token } pub fun deposit(token: @NonFungibleToken.NFT) { let id = token.id let oldToken <- self.ownedNFTs[id] <-token destroy oldToken emit Deposit(id: id, to: self.owner?.address) } pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT { if self.ownedNFTs[id] != nil { return (&self.ownedNFTs[id] as &NonFungibleToken.NFT?)! } panic("NFT not found in collection.") } pub fun getIDs(): [UInt64]{ return self.ownedNFTs.keys } } init(){ self.CollectionPublicPath = /public/NFTCollection self.CollectionStoragePath = /storage/NFTCollection self.totalSupply = 0 emit ContractInitialized() } }
Bây giờ, chúng tôi đã hoàn thành tất cả các tài nguyên. Tiếp theo, chúng ta sẽ xem xét chức năng toàn cầu.
Chức năng toàn cầu là các chức năng được xác định ở cấp độ toàn cầu của hợp đồng thông minh, nghĩa là chúng không phải là một phần của bất kỳ tài nguyên nào. Chúng có thể được công chúng truy cập và yêu cầu, đồng thời tiết lộ chức năng cốt lõi của hợp đồng thông minh cho công chúng.
createEmptyCollection : Hàm này khởi tạo một Collectibles.Collection
trống vào bộ nhớ tài khoản người gọi.
checkCollection : Chức năng tiện dụng này giúp bạn khám phá xem tài khoản của bạn đã có tài nguyên bộ collection
hay chưa.
mintNFT : Chức năng này cực kỳ thú vị vì nó cho phép mọi người tạo NFT.
// pub resource Collection… pub fun createEmptyCollection(): @Collection{ return <- create Collection() } pub fun checkCollection(_addr: Address): Bool{ return getAccount(_addr) .capabilities.get<&{Collectibles.CollectionPublic}> (Collectibles.CollectionPublicPath)! .check() } pub fun mintNFT(name:String, image:String): @NFT{ Collectibles.totalSupply = Collectibles.totalSupply + 1 let nftId = Collectibles.totalSupply var newNFT <- create NFT(_id:nftId, _name:name, _image:image) return <- newNFT } init()...
Và bây giờ, CUỐI CÙNG, với mọi thứ đã sẵn sàng, chúng ta đã viết xong hợp đồng thông minh của mình. Hãy xem mã cuối cùng ở đây .
Bây giờ, hãy xem cách người dùng tương tác với các hợp đồng thông minh được triển khai trên chuỗi khối Flow.
Có hai bước để tương tác với chuỗi khối Flow:
Giao dịch là dữ liệu được ký bằng mật mã chứa một bộ hướng dẫn tương tác với hợp đồng thông minh để cập nhật trạng thái Dòng. Nói một cách đơn giản, đây giống như một lệnh gọi hàm thay đổi dữ liệu trên blockchain. Các giao dịch thường liên quan đến một số chi phí, có thể thay đổi tùy thuộc vào blockchain bạn đang sử dụng.
Một giao dịch bao gồm nhiều giai đoạn tùy chọn: prepare
, pre
, execute
và giai đoạn post
.
Bạn có thể đọc thêm về điều này trong tài liệu tham khảo Cadence về giao dịch . Mỗi giai đoạn đều có một mục đích; hai giai đoạn quan trọng nhất là prepare
và execute
.
Prepare Phase
: Giai đoạn này được sử dụng để truy cập dữ liệu và thông tin bên trong tài khoản của người ký (được loại AuthAccount cho phép).
Execute Phase
: Giai đoạn này được sử dụng để thực hiện các hành động.
Bây giờ, hãy tạo một giao dịch cho dự án của chúng ta.
Thực hiện theo các bước bên dưới để tạo giao dịch trong thư mục dự án của bạn.
Đầu tiên, hãy vào thư mục dự án và mở thư mục cadence
. Bên trong nó, mở thư mục transaction
và tạo một tệp mới có tên Create_Collection.cdc
và mint_nft.cdc
import Collectibles from "../contracts/Collectibles.cdc" transaction { prepare(signer: AuthAccount) { if signer.borrow<&Collectibles.Collection>(from: Collectibles.CollectionStoragePath) == nil { let collection <- Collectibles.createEmptyCollection() signer.save(<-collection, to: Collectibles.CollectionStoragePath) let cap = signer.capabilities.storage.issue<&{Collectibles.CollectionPublic}>(Collectibles.CollectionStoragePath) signer.capabilities.publish( cap, at: Collectibles.CollectionPublicPath) } } }
Hãy chia nhỏ mã này theo từng dòng:
Giao dịch này tương tác với hợp đồng thông minh Collectibles. Sau đó, nó sẽ kiểm tra xem người gửi (người ký) có tài nguyên Bộ sưu tập được lưu trữ trong tài khoản của họ hay không bằng cách mượn tham chiếu đến tài nguyên Bộ sưu tập từ đường dẫn lưu trữ được chỉ định Collectibles.CollectionStoragePath
. Nếu tham chiếu bằng 0 thì có nghĩa là người ký chưa có bộ sưu tập.
Nếu người ký không có bộ sưu tập thì nó sẽ tạo một bộ sưu tập trống bằng cách gọi hàm createEmptyCollection()
.
Sau khi tạo bộ sưu tập trống, hãy đặt nó vào tài khoản của người ký theo đường dẫn lưu trữ được chỉ định Collectibles.CollectionStoragePath
.
Việc này sẽ thiết lập liên kết giữa tài khoản của người ký và bộ sưu tập mới được tạo bằng cách sử dụng link()
.
import NonFungibleToken from "../contracts/NonFungibleToken.cdc" import Collectibles from "../contracts/Collectibles.cdc" transaction(name:String, image:String){ let receiverCollectionRef: &{NonFungibleToken.CollectionPublic} prepare(signer:AuthAccount){ self.receiverCollectionRef = signer.borrow<&Collectibles.Collection>(from: Collectibles.CollectionStoragePath) ?? panic("could not borrow Collection reference") } execute{ let nft <- Collectibles.mintNFT(name:name, image:image) self.receiverCollectionRef.deposit(token: <-nft) } }
Hãy chia nhỏ mã này theo từng dòng:
Trước tiên, chúng tôi nhập hợp đồng NonFungibleToken
và Collectibles contract
.
transaction(name: String, image: String)
Dòng này xác định một giao dịch mới. Nó nhận vào hai đối số, tên và hình ảnh, cả hai đều thuộc loại Chuỗi. Các đối số này được sử dụng để truyền tên và hình ảnh của NFT đang được tạo.
let receiverCollectionRef: &{NonFungibleToken.CollectionPublic}
Dòng này khai báo một biến mới receiverCollectionRef.
Nó tham chiếu đến một bộ sưu tập công khai các NFT thuộc loại NonFungibleToken.CollectionPublic
. Tài liệu tham khảo này sẽ được sử dụng để tương tác với bộ sưu tập nơi chúng tôi sẽ gửi NFT mới được đúc.
prepare(signer: AuthAccount)
Dòng này bắt đầu khối chuẩn bị, khối này được thực thi trước giao dịch. Nó cần một người ký đối số thuộc loại AuthAccount
. AuthAccount
đại diện cho tài khoản của người ký giao dịch.
Nó mượn một tham chiếu đến Collectibles.Collection
từ bộ lưu trữ của người ký bên trong khối chuẩn bị. Nó sử dụng hàm mượn để truy cập tham chiếu đến bộ sưu tập và lưu trữ nó trong biến receiverCollectionRef
.
Nếu không tìm thấy tham chiếu (ví dụ: nếu bộ sưu tập không tồn tại trong bộ lưu trữ của người ký), nó sẽ đưa ra thông báo lỗi “không thể mượn tham chiếu Bộ sưu tập”.
Khối execute
chứa logic thực thi chính cho giao dịch. Mã bên trong khối này sẽ được thực thi sau khi khối prepare
hoàn tất thành công.
nft <- Collectibles.mintNFT(_name: name, image: image)
Bên trong khối execute
, dòng này gọi hàm mintNFT
từ hợp đồng Collectibles
với các đối số tên và hình ảnh được cung cấp. Chức năng này dự kiến sẽ tạo ra một NFT mới với tên và hình ảnh đã cho. Ký hiệu <-
cho biết NFT đang được nhận dưới dạng một đối tượng có thể di chuyển được (tài nguyên).
self.receiverCollectionRef.deposit(token: <-nft)
Dòng này gửi NFT mới được tạo vào bộ sưu tập được chỉ định. Nó sử dụng chức năng gửi tiền trên receiverCollectionRef
để chuyển quyền sở hữu NFT từ tài khoản thực thi giao dịch sang bộ sưu tập. Biểu tượng <-
ở đây cũng chỉ ra rằng NFT đang được di chuyển dưới dạng tài nguyên trong quá trình deposit
.
Chúng tôi sử dụng tập lệnh để xem hoặc đọc dữ liệu từ blockchain. Tập lệnh là miễn phí và không cần ký.
Thực hiện theo các bước bên dưới để tạo tập lệnh trong thư mục dự án của bạn.
Đầu tiên, hãy vào thư mục dự án và mở thư mục cadence
. Bên trong nó, mở thư mục script
và tạo một tệp mới có tên view_nft.cdc
.
import NonFungibleToken from "../contracts/NonFungibleToken.cdc" import Collectibles from "../contracts/Collectibles.cdc" pub fun main(user: Address, id: UInt64): &NonFungibleToken.NFT? { let collectionCap= getAccount(user).capabilities .get<&{Collectibles.CollectionPublic}>(/public/NFTCollection) ?? panic("This public capability does not exist.") let collectionRef = collectionCap.borrow()! return collectionRef.borrowNFT(id: id) }
Hãy chia nhỏ mã này theo từng dòng:
Đầu tiên, chúng tôi nhập hợp đồng NonFungibleToken
và Collectibles
.
pub fun main(acctAddress: Address, id: UInt64): &NonFungibleToken.NFT?
Dòng này xác định điểm vào của tập lệnh, đây là một hàm công khai có tên main. Hàm này có hai tham số:
acctAddress
: Tham số loại Address
đại diện cho địa chỉ của tài khoản trên chuỗi khối Flow.
id
: Tham số loại UInt64
đại diện cho mã định danh duy nhất của NFT trong bộ sưu tập.
Sau đó, chúng tôi sử dụng getCapability
để tìm nạp khả năng Collectibles.Collection
cho acctAddress
được chỉ định. Khả năng là tham chiếu đến tài nguyên cho phép truy cập vào các chức năng và dữ liệu của nó. Trong trường hợp này, nó đang tìm nạp khả năng cho loại tài nguyên Collectibles.Collection
.
Sau đó, chúng tôi mượn NFT từ bộ collectionRef
bằng cách sử dụng hàm borrowNFT
. Hàm borrowNFT
lấy tham số id
, đây là mã định danh duy nhất của NFT trong bộ sưu tập. Chức năng borrow
trên một khả năng cho phép đọc dữ liệu tài nguyên.
Cuối cùng, chúng tôi trả về NFT từ hàm.
Bây giờ là lúc triển khai hợp đồng thông minh của chúng tôi trên mạng thử nghiệm Flow.
1. Thiết lập tài khoản Flow.
Chạy lệnh sau trong terminal để tạo tài khoản Flow:
flow keys generate
Hãy nhớ ghi lại khóa chung và khóa riêng của bạn.
Tiếp theo, chúng ta sẽ đi đến
Dán khóa công khai của bạn vào trường đầu vào được chỉ định.
Giữ Thuật toán Chữ ký và Băm được đặt thành mặc định.
Hoàn thành Captcha.
Nhấp vào Tạo tài khoản.
Sau khi thiết lập tài khoản, chúng tôi nhận được một cuộc đối thoại với địa chỉ Flow mới chứa 1.000 mã thông báo Flow thử nghiệm. Sao chép địa chỉ để chúng tôi có thể sử dụng nó trong tương lai .
2. Cấu hình dự án.
Bây giờ, hãy cấu hình dự án của chúng tôi. Ban đầu, khi chúng tôi thiết lập dự án, nó sẽ tạo một tệp flow.json
.
Đây là tệp cấu hình cho Flow CLI và xác định cấu hình cho các hành động mà Flow CLI có thể thực hiện cho bạn. Hãy coi điều này gần tương đương với hardhat.config.js
trên Ethereum.
Bây giờ, hãy mở trình soạn thảo mã, sao chép và dán mã bên dưới vào tệp flow.json
của bạn.
{ "contracts": { "Collectibles": "./cadence/contracts/Collectibles.cdc", "NonFungibleToken": { "source": "./cadence/contracts/NonFungibleToken.cdc", "aliases": { "testnet": "0x631e88ae7f1d7c20" } } }, "networks": { "testnet": "access.devnet.nodes.onflow.org:9000" }, "accounts": { "testnet-account": { "address": "ENTER YOUR ADDRESS FROM FAUCET HERE", "key": "ENTER YOUR GENERATED PRIVATE KEY HERE" } }, "deployments": { "testnet": { "testnet-account": [ "Collectibles" ] } } }
Dán khóa riêng đã tạo của bạn vào vị trí (khóa: “NHẬP KHÓA RIÊNG TƯ ĐƯỢC TẠO CỦA BẠN TẠI ĐÂY”) trong mã.
Bây giờ, hãy thực thi mã trên testnet. Đi đến thiết bị đầu cuối và chạy đoạn mã sau:
flow project deploy --network testnet
5. Chờ xác nhận.
Sau khi gửi giao dịch, bạn sẽ nhận được ID giao dịch. Đợi giao dịch được xác nhận trên testnet, cho biết hợp đồng thông minh đã được triển khai thành công.
Kiểm tra hợp đồng đã triển khai của bạn tại đây .
Kiểm tra mã đầy đủ trên GitHub .
Chúc mừng! Bây giờ bạn đã xây dựng một cổng sưu tầm trên chuỗi khối Flow và triển khai nó trên mạng thử nghiệm. Cái gì tiếp theo? Bây giờ, bạn có thể bắt tay vào xây dựng giao diện người dùng mà chúng tôi sẽ trình bày trong phần 2 của loạt bài này.
Chúc bạn có một ngày thật tuyệt vời!
Cũng được xuất bản ở đây