Smart Contract

MotoGPCardMetadata

A.a49cc0ee46c54bfb.MotoGPCardMetadata

Deployed

1d ago
Feb 26, 2026, 09:43:52 PM UTC

Dependents

0 imports
1import FungibleToken from 0xf233dcee88fe0abe
2import NonFungibleToken from 0x1d7e57aa55817448 
3import MetadataViews from 0x1d7e57aa55817448
4import MotoGPAdmin from 0xa49cc0ee46c54bfb
5import ContractVersion from 0xb223b2bfe4b8ffb5
6import MotoGPRegistry from 0xa49cc0ee46c54bfb
7
8
9// Contract to hold Metadata for MotoGPCards. Metadata is accessed using the Card's cardID (not the Card's id)
10//
11pub contract MotoGPCardMetadata: ContractVersion {
12
13    pub fun getVersion():String {
14        return "1.0.4"
15    }
16
17   //////////////////////////////////
18   // MotoGPCard MetadataViews implementation
19   //////////////////////////////////
20
21    pub struct Rider {
22        pub let name: String 
23        pub let bike: String
24        pub let team: String 
25        pub let number: String
26        init(name: String, bike: String, team: String, number: String) {
27            self.name = name
28            self.bike = bike
29            self.team = team 
30            self.number = number
31        }
32    }
33
34    pub struct Riders {
35        pub let riders: [Rider]
36        init(riders: [Rider]) {
37            self.riders = riders
38        }
39    }
40
41    // The getRider method is the equivalent of the MetadataViews.get{ViewName} methods 
42    // to get the custom Riders view by supplying a card reference as argument
43    // 
44    pub fun getRiders(_ viewResolver: &{MetadataViews.Resolver}): Riders? {
45        if let view = viewResolver.resolveView(Type<Riders>()) {
46            if let v = view as? Riders {
47                return v
48            }
49        }
50        return nil
51    }
52
53    access(contract) fun resolveDisplayView(cardID: UInt64): MetadataViews.Display {
54        let metadata = self.metadatas[cardID]!
55        return MetadataViews.Display(
56            name: metadata.name, 
57            description: metadata.description,
58            thumbnail: MetadataViews.HTTPFile(url: metadata.imageUrl)
59        )
60    }
61
62    access(contract) fun resolveRoyaltiesView(): MetadataViews.Royalties {
63        var royaltyList: [MetadataViews.Royalty] = []
64        let capability = getAccount(MotoGPRegistry.get(key: "motogp-royalty-receiver")! as! Address).getCapability<&{FungibleToken.Receiver}>(MetadataViews.getRoyaltyReceiverPublicPath())
65        let royalty:MetadataViews.Royalty = MetadataViews.Royalty(
66            receiver: capability,
67            cut: 0.075,
68            description: "Creator royalty"
69        )
70        royaltyList.append(royalty)
71        return MetadataViews.Royalties(royaltyList)
72    }
73
74    access(contract) fun resolveExternalURLView(id: UInt64): MetadataViews.ExternalURL {
75        return MetadataViews.ExternalURL("https://motogp-ignition.com/nft/card/".concat(id.toString()))
76    }
77
78    access(contract) fun resolveNFTCollectionDisplayView(): MetadataViews.NFTCollectionDisplay {
79        let socials:{String: MetadataViews.ExternalURL} = {}
80        socials.insert(key: "twitter", MetadataViews.ExternalURL("https://twitter.com/MotoGPIgnition"))
81        
82        let squareMedia = MetadataViews.Media(
83            file: MetadataViews.HTTPFile(url: "https://assets.motogp-ignition.com/MGPI-card-Square.jpg"),
84            mediaType: "image/jpeg"
85        )
86        let bannerMedia = MetadataViews.Media(
87            file: MetadataViews.HTTPFile(url: "https://assets.motogp-ignition.com/MGPI-card-Banner.jpg"),
88            mediaType: "image/jpeg"
89        ) 
90        return MetadataViews.NFTCollectionDisplay(
91            name: "MotoGPCard", 
92            description: "MotoGP Ignition is an NFT collection for MotoGP enthusiasts",
93            externalURL: MetadataViews.ExternalURL("https://motogp-ignition.com"),
94            squareImage: squareMedia,
95            bannerImage: bannerMedia,
96            socials: socials
97        )
98    }
99
100    access(contract) fun resolveMediasView(cardID: UInt64): MetadataViews.Medias {
101        let metadata = self.metadatas[cardID]!
102        var imageUrl:String = metadata.imageUrl
103        var videoUrl:String = metadata.data["videoUrl"]!
104        var thumbnailVideoUrl:String = metadata.data["thumbnailVideoUrl"]!
105        let medias:[MetadataViews.Media] = []
106        medias.append(MetadataViews.Media(file: MetadataViews.HTTPFile(url: imageUrl), mediaType: "image/png"))
107        medias.append(MetadataViews.Media(file: MetadataViews.HTTPFile(url: videoUrl), mediaType: "video/mp4"))
108        medias.append(MetadataViews.Media(file: MetadataViews.HTTPFile(url: thumbnailVideoUrl), mediaType: "video/mp4"))
109        return MetadataViews.Medias(medias)
110    }
111
112    access(contract) fun resolveTraitsView(cardID: UInt64): MetadataViews.Traits {
113        let metadata = self.metadatas[cardID]!
114        let traits = MetadataViews.Traits([])
115        for key in metadata.data.keys {
116            if key != "id" && key != "name" && key != "description" && key != "imageUrl" && key != "videoUrl" && key != "thumbnailVideoUrl" {
117                let trait = MetadataViews.Trait(name: key, value: metadata.data[key], nil, nil)
118                traits.addTrait(trait)
119            }
120        }
121        return traits
122    }
123
124    access(contract) fun resolveRidersView(cardID: UInt64): Riders {
125        let riders:[Rider] = []
126        let metadata = self.metadatas[cardID]!
127        var riderIndex = 1
128        for key in metadata.data.keys {
129            let riderKey = "rider_".concat(riderIndex.toString())
130            let riderName = metadata.data[riderKey]
131            if riderName == nil {
132                break
133            } else {
134                let riderBike = metadata.data[riderKey.concat("_bike")] ?? ""
135                let riderTeam = metadata.data[riderKey.concat("_team")] ?? ""
136                let riderNumber = metadata.data[riderKey.concat("_number")] ?? ""
137                riders.append(Rider(name: riderName!, bike: riderBike, team: riderTeam, number: riderNumber));
138                riderIndex = riderIndex + 1
139            }
140        }
141        return Riders(riders: riders)
142    }
143
144    pub fun resolveView(
145        view: Type,
146        id: UInt64,
147        cardID: UInt64,
148        serial: UInt64,
149        publicCollectionType: Type,
150        publicLinkedType: Type,
151        providerLinkedType: Type,
152        createEmptyCollectionFunction: ((): @NonFungibleToken.Collection)
153    ):  AnyStruct? {
154
155            switch view {
156
157                case Type<MotoGPCardMetadata.Riders>():
158                    return self.resolveRidersView(cardID: cardID)
159
160                case Type<MetadataViews.Traits>():
161                    return self.resolveTraitsView(cardID: cardID)
162
163                case Type<MetadataViews.Display>():
164                    return self.resolveDisplayView(cardID: cardID)
165
166                case Type<MetadataViews.Royalties>():
167                    return self.resolveRoyaltiesView()
168                
169                case Type<MetadataViews.ExternalURL>():
170                    return self.resolveExternalURLView(id: id)
171
172                case Type<MetadataViews.Medias>():
173                    return self.resolveMediasView(cardID: cardID)
174
175                case Type<MetadataViews.NFTCollectionDisplay>():
176                    return self.resolveNFTCollectionDisplayView()
177
178                case Type<MetadataViews.NFTCollectionData>():
179                    return MetadataViews.NFTCollectionData( 
180                        storagePath: StoragePath(identifier: "motogpCardCollection")!,
181                        publicPath: PublicPath(identifier: "motogpCardCollection")!,
182                        providerPath: PrivatePath(identifier: "motogpCardCollection")!,
183                        publicCollection: publicCollectionType,
184                        publicLinkedType: publicLinkedType,
185                        providerLinkedType:  providerLinkedType,
186                        createEmptyCollectionFunction: createEmptyCollectionFunction
187                    )
188                    
189            }
190            return nil
191        }
192    
193
194    /////////////////////////////////////////////////////////////////////////////////
195    // MotoGPCard Legacy Metadata Implementation (kept for compatibility purposes)
196    ////////////////////////////////////////////////////////////////////////////////
197
198
199    pub struct Metadata {
200        pub let cardID: UInt64
201        pub let name: String
202        pub let description: String
203        pub let imageUrl: String
204        // data contains all 'other' metadata fields, e.g. videoUrl, team, etc
205        //
206        pub let data: {String: String} 
207        init(_cardID:UInt64, _name:String, _description:String, _imageUrl:String, _data:{String:String}){
208            pre {
209                    !_data.containsKey("name") : "data dictionary contains 'name' key"
210                    !_data.containsKey("description") : "data dictionary contains 'description' key"
211                    !_data.containsKey("imageUrl") : "data dictionary contains 'imageUrl' key"
212            }
213            self.cardID = _cardID
214            self.name = _name
215            self.description = _description
216            self.imageUrl = _imageUrl
217            self.data = _data
218        }
219    }
220
221    //Dictionary to hold all metadata with cardID as key
222    //
223    access(self) let metadatas: {UInt64: MotoGPCardMetadata.Metadata} 
224
225    // Get all metadatas
226    //
227    pub fun getMetadatas(): {UInt64: MotoGPCardMetadata.Metadata} {
228        return self.metadatas
229    }
230
231    pub fun getMetadatasCount(): UInt64 {
232        return UInt64(self.metadatas.length)
233    }
234
235    //Get metadata for a specific cardID
236    //
237    pub fun getMetadataForCardID(cardID: UInt64): MotoGPCardMetadata.Metadata? {
238        return self.metadatas[cardID]
239    }
240
241    //Access to set metadata is controlled using an Admin reference as argument
242    //
243    pub fun setMetadata(adminRef: &MotoGPAdmin.Admin, cardID: UInt64, name:String, description:String, imageUrl:String, data:{String: String}) {
244        pre {
245            adminRef != nil: "adminRef is nil"
246        }
247        let metadata = Metadata(_cardID:cardID, _name:name, _description:description, _imageUrl:imageUrl, _data:data)
248        self.metadatas[cardID] = metadata
249    }
250
251    //Remove metadata by cardID
252    //
253    pub fun removeMetadata(adminRef: &MotoGPAdmin.Admin, cardID: UInt64) {
254        pre {
255            adminRef != nil: "adminRef is nil"
256        }
257        self.metadatas.remove(key: cardID)
258    }
259    
260    init(){
261            self.metadatas = {}
262    }
263        
264}
265