Last active
December 22, 2021 19:24
-
-
Save briandilley/962e94682b7945d882fcd99702011ea4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import StandardViewTypes from 0x02 | |
import SomeNFT from 0x03 | |
import ViewResolvers from 0x04 | |
// Add support for the Person view to the existing NFT contract | |
transaction { | |
prepare(signer: AuthAccount) { | |
let admin = signer.borrow<&SomeNFT.ViewResolverRegistry>(from: SomeNFT.VIEW_RESOLVER_REGISTRY_PATH)! | |
let resolver <- ViewResolvers.createPersonViewResolver() | |
admin.registerViewResolver(<- resolver) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub contract interface NonFungibleToken { | |
pub var totalSupply: UInt64 | |
pub event ContractInitialized() | |
pub event Withdraw(id: UInt64, from: Address?) | |
pub event Deposit(id: UInt64, to: Address?) | |
pub resource interface INFT { | |
pub let id: UInt64 | |
pub fun availableViews(): [Type] | |
pub fun resolveView(_ type: Type): AnyStruct? | |
} | |
pub resource NFT: INFT { | |
pub let id: UInt64 | |
pub fun availableViews(): [Type] | |
pub fun resolveView(_ type: Type): AnyStruct? | |
} | |
pub resource interface Provider { | |
pub fun withdraw(withdrawID: UInt64): @NFT { | |
post { | |
result.id == withdrawID: "The ID of the withdrawn token must be the same as the requested ID" | |
} | |
} | |
} | |
pub resource interface Receiver { | |
pub fun deposit(token: @NFT) | |
} | |
pub resource interface CollectionPublic { | |
pub fun deposit(token: @NFT) | |
pub fun getIDs(): [UInt64] | |
pub fun borrowNFT(id: UInt64): &NFT | |
} | |
pub resource Collection: Provider, Receiver, CollectionPublic { | |
pub var ownedNFTs: @{UInt64: NFT} | |
pub fun withdraw(withdrawID: UInt64): @NFT | |
pub fun deposit(token: @NFT) | |
pub fun getIDs(): [UInt64] | |
pub fun borrowNFT(id: UInt64): &NFT { | |
pre { | |
self.ownedNFTs[id] != nil: "NFT does not exist in the collection!" | |
} | |
} | |
} | |
pub fun createEmptyCollection(): @Collection { | |
post { | |
result.getIDs().length == 0: "The created collection must be empty!" | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import NonFungibleToken from 0x01 | |
pub contract SomeNFT : NonFungibleToken { | |
pub var totalSupply: UInt64 | |
pub let viewResolvers: @{String: AnyResource{ViewResolver}} | |
pub event ContractInitialized() | |
pub event Withdraw(id: UInt64, from: Address?) | |
pub event Deposit(id: UInt64, to: Address?) | |
pub event ViewResolverRegistered(resolverType: Type, viewType: Type) | |
pub event ViewResolverDeregistered(resolverType: Type, viewType: Type) | |
access(all) let VIEW_RESOLVER_REGISTRY_PATH: StoragePath | |
init() { | |
self.totalSupply = 0 | |
self.viewResolvers <- {} | |
self.VIEW_RESOLVER_REGISTRY_PATH = /storage/ViewResolverRegistry | |
self.account.save<@ViewResolverRegistry>( | |
<- create ViewResolverRegistry(), | |
to: SomeNFT.VIEW_RESOLVER_REGISTRY_PATH | |
) | |
} | |
pub resource interface ViewResolver { | |
pub fun getViewType(): Type | |
pub fun canResolveView(_ nft: &NFT): Bool | |
pub fun resolveView(_ nft: &NFT): AnyStruct? | |
} | |
pub resource ViewResolverRegistry { | |
pub fun registerViewResolver(_ resolver: @AnyResource{ViewResolver}) { | |
pre { | |
SomeNFT.viewResolvers[resolver.getViewType().identifier] == nil : "A ViewResolver for that type exists" | |
} | |
emit ViewResolverRegistered(resolverType: resolver.getType(), viewType: resolver.getViewType()) | |
SomeNFT.viewResolvers[resolver.getViewType().identifier] <-! resolver | |
} | |
pub fun deregisterViewResolver(_ resolverType: Type): @AnyResource{ViewResolver}? { | |
pre { | |
SomeNFT.viewResolvers[resolverType.identifier] != nil : "No ViewResolver with that name exists" | |
} | |
let resolver <- SomeNFT.viewResolvers.remove(key: resolverType.identifier)! | |
emit ViewResolverDeregistered(resolverType: resolver.getType(), viewType: resolver.getViewType()) | |
return <- resolver | |
} | |
} | |
pub fun availableViews(_ nft: &NFT): [Type] { | |
let ret: [Type] = [] | |
for key in SomeNFT.viewResolvers.keys { | |
let resolver = &SomeNFT.viewResolvers[key] as &AnyResource{ViewResolver} | |
if resolver != nil { | |
ret.append(resolver.getViewType()) | |
} | |
} | |
return ret | |
} | |
pub fun resolveView(_ nft: &NFT, _ type: Type): AnyStruct? { | |
var resolver: &AnyResource{ViewResolver}? = nil | |
for key in SomeNFT.viewResolvers.keys { | |
resolver = &SomeNFT.viewResolvers[key] as &AnyResource{ViewResolver} | |
if resolver != nil && resolver.getType() == type { | |
break | |
} | |
resolver = nil | |
} | |
if resolver == nil { | |
return nil | |
} else if !resolver!.canResolveView(nft) { | |
return nil | |
} | |
return resolver!.resolveView(nft) | |
} | |
pub resource NFT: NonFungibleToken.INFT { | |
pub let id: UInt64 | |
// the follow is immutable "view" | |
pub let name: String | |
pub let year: UInt8 | |
pub let shavedElbows: Bool | |
init(id: UInt64, name: String, year: UInt8, shavedElbows: Bool) { | |
self.id = SomeNFT.totalSupply | |
self.name = name | |
self.year = year | |
self.shavedElbows = shavedElbows | |
SomeNFT.totalSupply = SomeNFT.totalSupply + 1 | |
} | |
pub fun availableViews(): [Type] { | |
return SomeNFT.availableViews(&self as &NFT) | |
} | |
pub fun resolveView(_ type: Type): AnyStruct? { | |
return SomeNFT.resolveView(&self as &NFT, type) | |
} | |
} | |
pub resource Collection: NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic { | |
pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT} | |
init() { | |
self.ownedNFTs <- {} | |
} | |
pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT { | |
let token <- self.ownedNFTs.remove(key: withdrawID) | |
?? panic("Cannot withdraw: NFT does not exist in the collection") | |
emit Withdraw(id: token.id, from: self.owner?.address) | |
return <-token | |
} | |
pub fun deposit(token: @NonFungibleToken.NFT) { | |
let token <- token as! @SomeNFT.NFT | |
let id = token.id | |
let oldToken <- self.ownedNFTs[id] <- token | |
if self.owner?.address != nil { | |
emit Deposit(id: id, to: self.owner?.address) | |
} | |
destroy oldToken | |
} | |
pub fun getIDs(): [UInt64] { | |
return self.ownedNFTs.keys | |
} | |
pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT { | |
return &self.ownedNFTs[id] as &NonFungibleToken.NFT | |
} | |
destroy() { | |
destroy self.ownedNFTs | |
} | |
} | |
pub fun createEmptyCollection(): @NonFungibleToken.Collection { | |
return <- create SomeNFT.Collection() | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
access(all) contract StandardViewTypes { | |
pub struct Person { | |
pub let name: String | |
init(name: String) { | |
self.name = name | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SomeNFT from 0x03 | |
import StandardViewTypes from 0x02 | |
pub contract ViewResolvers { | |
pub resource PersonViewResolver : SomeNFT.ViewResolver { | |
pub fun getViewType(): Type { | |
return Type<StandardViewTypes.Person>() | |
} | |
pub fun canResolveView(_ nft: &SomeNFT.NFT): Bool { | |
return nft.isInstance(Type<@SomeNFT.NFT>()) | |
} | |
pub fun resolveView(_ nft: &SomeNFT.NFT): AnyStruct? { | |
return StandardViewTypes.Person(name: nft.name) | |
} | |
} | |
pub fun createPersonViewResolver(): @PersonViewResolver { | |
return <- create ViewResolvers.PersonViewResolver() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment