DeploySEALED

*╱!╱╲◇*╳!@█$◇●╳~▫◇□!╱╳#@#○○╱&▪!?□#▪*▒$●╳*$%■░█~○@@?~●╲╳●~&@▫?#▓▫

Transaction ID

Timestamp

Sep 11, 2024, 11:41:34 AM UTC
1y ago

Block Height

86,698,411

Computation

0

Execution Fee

0.00000574 FLOW

Transaction Summary

Deploy

Contract deployment

Contract deployment

Script Arguments

0nameString
Certifily
1codeString
// Certifily NFT Smart Contract // NFT : www.Certifi.ly // Version : 1.0.0 // Blockchain : Flow www.onFlow.org import NonFungibleToken from 0x1d7e57aa55817448 import MetadataViews from 0x1d7e57aa55817448 import ViewResolver from 0x1d7e57aa55817448 access(all) contract Certifily: NonFungibleToken { // Total number of token supply access(all) var totalSupply: UInt64 /// Path where the `Collection` is stored access(all) let certifilyStoragePath: StoragePath /// Path where the public capability for the `Collection` is access(all) let certifilyPublicPath: PublicPath /// NFT Minter access(all) let certifilyMinterPath: StoragePath // Contract Events access(all) event ContractInitialized() access(all) event Withdraw(id: UInt64, from: Address?) access(all) event Deposit(id: UInt64, to: Address?) access(all) event Mint(id: UInt64, content:String, owner: Address?, insitution:String) // TOKEN RESOURCE access(all) resource NFT: NonFungibleToken.NFT { // Unique identifier for NFT Token access(all) let id :UInt64 // Meta data to store token data (use dict for data) access(self) let metaData: {String : String} access(all) fun getMetadata():{String: String} { return self.metaData } // NFT token insitution access(all) let insitution:String access(all) let certType:UInt8 // Certificate token holder address access(all) let holder:Address? // View permission for the NFT (an array of addresses) access(all) let viewPermission: [String] // In current store static dict in meta data init(id : UInt64, content : String, insitution:String, description:String , holder:Address?,previewContent:String,certType:UInt8, viewPermission: [String]) { self.id = id self.metaData = {"content" : content, "description": description, "previewContent":previewContent } self.holder = holder self.insitution = insitution self.certType = certType self.viewPermission = viewPermission } /// createEmptyCollection creates an empty Collection /// and returns it to the caller so that they can own NFTs /// @{NonFungibleToken.Collection} access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} { return <-Certifily.createEmptyCollection(nftType: Type<@Certifily.NFT>()) } access(all) view fun getViews(): [Type] { return [ Type<MetadataViews.Display>(), Type<MetadataViews.ExternalURL>(), Type<MetadataViews.NFTCollectionData>(), Type<MetadataViews.NFTCollectionDisplay>(), Type<MetadataViews.Serial>(), Type<MetadataViews.Traits>() ] } // Function to add an address to viewPermission access(all) fun addViewPermission(address: [String]) { for addr in address { // Check if the address is not already in the viewPermission array if !self.viewPermission.contains(addr) { self.viewPermission.append(addr) } } } // Function to remove an address from viewPermission access(all) fun removeViewPermission(address: String) { // Find the index of the address in viewPermission and remove it let index = self.viewPermission.firstIndex(of: address) if let idx = index { self.viewPermission.remove(at: idx) } } access(all) fun resolveView(_ view: Type): AnyStruct? { switch view { case Type<MetadataViews.Display>(): return MetadataViews.Display( name: self.insitution, description: self.metaData["description"]!, thumbnail: MetadataViews.HTTPFile( url: self.metaData["previewContent"]! ) ) case Type<MetadataViews.Serial>(): return MetadataViews.Serial( self.id ) case Type<MetadataViews.ExternalURL>(): return MetadataViews.ExternalURL("https://certifi.ly") case Type<MetadataViews.NFTCollectionData>(): return MetadataViews.NFTCollectionData( storagePath: Certifily.certifilyStoragePath, publicPath: Certifily.certifilyPublicPath, publicCollection: Type<&Certifily.Collection>(), publicLinkedType: Type<&Certifily.Collection>(), createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} { return <-Certifily.createEmptyCollection(nftType: Type<@Certifily.NFT>()) }) ) case Type<MetadataViews.NFTCollectionDisplay>(): let media = MetadataViews.Media( file: MetadataViews.HTTPFile( url: "https://alpha.certifi.ly/logo512.png" ), mediaType: "image/png" ) return MetadataViews.NFTCollectionDisplay( name: "Certifily Collection", description: "Next-gen NFT documents B2B SaaS platform for all-gen", externalURL: MetadataViews.ExternalURL("https://certifi.ly"), squareImage: media, bannerImage: media, socials: { "twitter": MetadataViews.ExternalURL("https://twitter.com/certifily"), "instagram": MetadataViews.ExternalURL("https://www.instagram.com/certifi.ly/"), "discord" : MetadataViews.ExternalURL("https://discord.io/certifily") } ) case Type<MetadataViews.Traits>(): return [] } return nil } } // Account's public collection access(all) resource interface CertifilyCollectionPublic { // Function to check if an address has view permission for an NFT access(all) view fun hasViewPermission(id: UInt64, address: String): Bool? access(all) fun borrowCertifily(id: UInt64): &{NonFungibleToken.NFT}? { // If the result isn't nil, the id of the returned reference // should be the same as the argument to the function post { (result == nil) || (result?.id == id): "Cannot borrow CaaPass reference: The ID of the returned reference is incorrect" } } } // NFT Collection resource access(all) resource Collection : CertifilyCollectionPublic, NonFungibleToken.Collection { /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts access(all) view fun getSupportedNFTTypes(): {Type: Bool} { let supportedTypes: {Type: Bool} = {} supportedTypes[Type<@Certifily.NFT>()] = true return supportedTypes } /// Returns whether or not the given type is accepted by the collection /// A collection that can accept any type should just return true by default access(all) view fun isSupportedNFTType(type: Type): Bool { return type == Type<@Certifily.NFT>() } /// createEmptyCollection creates an empty Collection for the specified NFT type /// and returns it to the caller so that they can own NFTs access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} { return <- create Collection() } // Contains caller's list of NFTs access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}} init() { self.ownedNFTs <- {} } access(all) fun deposit(token: @{NonFungibleToken.NFT}) { let token <- token as! @Certifily.NFT let id: UInt64 = token.id // add the new token to the dictionary which removes the old one let oldToken <- self.ownedNFTs[id] <- token emit Deposit(id: id, to: self.owner?.address) destroy oldToken } // function returns token keys of owner access(all) view fun getIDs():[UInt64] { return self.ownedNFTs.keys } // function returns token data of token id access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? { return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?) } // Gets a reference to an NFT in the collection as a Certifily, // exposing all of its fields. access(all) view fun borrowCertifily(id: UInt64): &{NonFungibleToken.NFT}? { if self.ownedNFTs[id] != nil { // let ref = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)! // return ref as! &Certifily.NFT return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?) } else { return nil } } // function to check wether the owner have token or not access(all) fun tokenExists(id:UInt64) : Bool { return self.ownedNFTs[id] != nil } /// withdraw removes an NFT from the collection and moves it to the caller access(NonFungibleToken.Withdraw) fun withdraw(withdrawID:UInt64) : @{NonFungibleToken.NFT} { // let ref = (&self.ownedNFTs[withdrawID] as auth &NonFungibleToken.NFT?)! let ref = (&self.ownedNFTs[withdrawID] as &{NonFungibleToken.NFT}?) let val = ref as! &Certifily.NFT if val.certType == 1 { panic("Cert Type is not allowed to withdraw") } let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT") emit Withdraw(id: token.id, from: self.owner?.address) return <-token } // access(all) fun borrowViewResolver(id: UInt64): &AnyResource{MetadataViews.Resolver} { access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? { // let nft = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)! // let nft = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?) // let CertifilyNFT = nft as! &Certifily.NFT // return CertifilyNFT as &{ViewResolver.Resolver} if let nft = &self.ownedNFTs[id] as &{NonFungibleToken.NFT}? { return nft as &{ViewResolver.Resolver} } return nil } // Function to add an address to viewPermission access(all) fun addViewPermission(id: UInt64, address: [String]) { // let ref = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)! let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?) let nft = ref as! &Certifily.NFT? // Call the NFT's addViewPermission function nft?.addViewPermission(address: address) } access(all) fun removeViewPermission(id: UInt64, address: String) { // let ref = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)! let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?) let nft = ref as! &Certifily.NFT? // Call the NFT's removeViewPermission function nft?.removeViewPermission(address: address) } access(all) view fun hasViewPermission(id: UInt64, address: String): Bool? { // let ref = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)! let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?) let nft = ref as! &Certifily.NFT? // Check if the address has view permission return nft?.viewPermission?.contains(address) } } /// createEmptyCollection creates an empty Collection for the specified NFT type /// and returns it to the caller so that they can own NFTs access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} { return <- create Collection() } /// Function that returns all the Metadata Views implemented by a Non Fungible Token /// /// @return An array of Types defining the implemented views. This value will be used by /// developers to know which parameter to pass to the resolveView() method. /// access(all) view fun getContractViews(resourceType: Type?): [Type] { return [ Type<MetadataViews.NFTCollectionData>(), Type<MetadataViews.NFTCollectionDisplay>(), Type<MetadataViews.EVMBridgedMetadata>() ] } /// Function that resolves a metadata view for this contract. /// /// @param view: The Type of the desired view. /// @return A structure representing the requested view. /// access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? { switch viewType { case Type<MetadataViews.NFTCollectionData>(): let collectionData = MetadataViews.NFTCollectionData( storagePath: Certifily.certifilyStoragePath, publicPath: Certifily.certifilyPublicPath, publicCollection: Type<&Certifily.Collection>(), publicLinkedType: Type<&Certifily.Collection>(), createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} { return <-Certifily.createEmptyCollection(nftType: Type<@Certifily.NFT>()) }) ) return collectionData case Type<MetadataViews.NFTCollectionDisplay>(): let media = MetadataViews.Media( file: MetadataViews.HTTPFile( url: "https://certifi.ly/logo512.png" ), mediaType: "image/png+xml" ) return MetadataViews.NFTCollectionDisplay( name: "The Example Collection", description: "This collection is used as an example to help you develop your next Flow NFT.", externalURL: MetadataViews.ExternalURL("https://certifi.ly"), squareImage: media, bannerImage: media, socials: { "twitter": MetadataViews.ExternalURL("https://twitter.com/certifily") } ) case Type<MetadataViews.EVMBridgedMetadata>(): // Implementing this view gives the project control over how the bridged NFT is represented as an ERC721 // when bridged to EVM on Flow via the public infrastructure bridge. // Compose the contract-level URI. In this case, the contract metadata is located on some HTTP host, // but it could be IPFS, S3, a data URL containing the JSON directly, etc. return MetadataViews.EVMBridgedMetadata( name: "Certifily", symbol: "XMPL", uri: MetadataViews.URI( baseURI: nil, // setting baseURI as nil sets the given value as the uri field value value: "https://certifi.ly" ) ) } return nil } // NFT MINTER access(all) resource NFTMinter { access(all) fun Mint(recipient: Address,content:String, insitution:String, description:String,previewContent:String,certType:UInt8,viewPermission: [String]) : @Certifily.NFT { let token <- create NFT(id: Certifily.totalSupply, content:content, insitution:insitution, description:description, holder: recipient,previewContent:previewContent, certType:certType, viewPermission:viewPermission) emit Mint(id:Certifily.totalSupply,content:content,owner: recipient, insitution:insitution) Certifily.totalSupply = Certifily.totalSupply + 1 as UInt64 return <-token } } // Contract init init() { // total supply is zero at the time of contract deployment self.totalSupply = 0 self.certifilyStoragePath = /storage/CertifilyNFTCollection self.certifilyPublicPath = /public/CertifilyNFTPublicCollection self.certifilyMinterPath = /storage/CertifilyNFTMinter // Create a Collection resource and save it to storage let collection <- create Collection() self.account.storage.save(<-collection, to: self.certifilyStoragePath) // create a public capability for the collection let collectionCap = self.account.capabilities.storage.issue<&Certifily.Collection>(self.certifilyStoragePath) self.account.capabilities.publish(collectionCap, at: self.certifilyPublicPath) // store a minter resource in account storage self.account.storage.save(<-create NFTMinter(), to: self.certifilyMinterPath) emit ContractInitialized() } }

Cadence Script

1transaction(name: String, code: String ) {
2		prepare(signer: auth(AddContract) &Account) {
3			signer.contracts.add(name: name, code: code.utf8 )
4		}
5	}