Smart Contract
Templates
A.e81193c424cfd3fb.Templates
1// SPDX-License-Identifier: MIT
2import MetadataViews from 0x1d7e57aa55817448
3import FungibleToken from 0xf233dcee88fe0abe
4
5// This contracts stores all the defined interfaces and structs.
6// Interfaces can span on both Doodles and Wearables therefore it is better to have them in a central contract
7access(all) contract Templates {
8
9 access(contract) let counters : {String : UInt64}
10 access(contract) let features : {String : Bool}
11
12 access(all) fun getCounter(_ name:String) :UInt64{
13 return Templates.counters[name] ?? 0
14 }
15
16 access(all) event CountersReset()
17
18 access(account) fun createEditionInfoManually(name: String, counter:String, edition:UInt64?) : EditionInfo {
19 let oldMax=Templates.counters[counter] ?? 0
20 if let e = edition {
21 // If edition is passed in, check if the edition is larger than the existing max.
22 // If so, set it as max, otherwise just mint with edition
23 if e > oldMax {
24 Templates.counters[counter] = e
25 }
26 return EditionInfo(counter: counter, name:name, number:e)
27 }
28 // If edition is NOT passed in, increment by 1 and set new max as edition
29 let max=oldMax+1
30 Templates.counters[counter] = max
31 return EditionInfo(counter: counter, name:name, number:max)
32 }
33
34 access(all) struct interface Editionable {
35
36 access(all) fun getCounterSuffix() : String
37 // e.g. set , position
38 access(all) fun getClassifier() : String
39 // e.g. character, wearable
40 access(all) fun getContract() : String
41
42 access(all) fun getCounter() : String {
43 return self.getContract().concat("_").concat(self.getClassifier()).concat("_").concat(self.getCounterSuffix())
44 }
45
46 access(account) fun createEditionInfo(_ edition: UInt64?) : EditionInfo {
47 return Templates.createEditionInfoManually(name:self.getClassifier(), counter:self.getCounter(), edition:edition)
48 }
49
50 access(all) fun getCurrentCount() : UInt64 {
51 return Templates.counters[self.getCounter()] ?? 0
52 }
53
54 }
55
56 access(all) struct interface Retirable{
57
58 access(all) var active:Bool
59
60 access(all) fun getCounterSuffix() : String
61 access(all) fun getClassifier() : String
62 access(all) fun getContract() : String
63
64 access(account) fun enable(_ bool : Bool) {
65 if (!self.active) {
66 panic(self.getContract().concat("-").concat(self.getClassifier()).concat(" is already retired : ").concat(self.getCounterSuffix()))
67 }
68 self.active = bool
69 }
70 }
71
72 access(all) struct interface RoyaltyHolder {
73 access(all) let royalties: [Templates.Royalty]
74
75 access(all) fun getRoyalties() : [MetadataViews.Royalty] {
76 let royalty : [MetadataViews.Royalty] = []
77 for r in self.royalties {
78 royalty.append(r.getRoyalty())
79 }
80 return royalty
81 }
82 }
83
84 access(all) struct EditionInfo {
85 access(all) let counter :String
86 access(all) let name : String
87 access(all) let number:UInt64
88
89 init(counter: String, name:String, number:UInt64) {
90 self.counter=counter
91 self.name=name
92 self.number=number
93 }
94
95 access(all) fun getSupply() : UInt64 {
96 return Templates.counters[self.counter] ?? 0
97 }
98
99 access(all) fun getAsMetadataEdition(_ active:Bool) : MetadataViews.Edition {
100 var max : UInt64?=nil
101 if !active {
102 max=Templates.counters[self.counter]
103 }
104 return MetadataViews.Edition(name:self.name, number:self.number, max:max)
105 }
106
107 access(all) fun getMaxEdition() : UInt64 {
108 return Templates.counters[self.counter]!
109 }
110
111 }
112
113 access(all) struct Royalty {
114 access(all) let name : String
115 access(all) let address: Address
116 access(all) let cut: UFix64
117 access(all) let description: String
118 access(all) let publicPath: String
119
120 init(name : String , address: Address , cut: UFix64 , description: String , publicPath: String) {
121 self.name = name
122 self.address = address
123 self.cut = cut
124 self.description = description
125 self.publicPath = publicPath
126 }
127
128 access(all) fun getPublicPath() : PublicPath {
129 return PublicPath(identifier: self.publicPath)!
130 }
131
132 access(all) fun getRoyalty() : MetadataViews.Royalty {
133 let cap = getAccount(self.address).capabilities.get<&{FungibleToken.Receiver}>(self.getPublicPath())
134 return MetadataViews.Royalty(receiver: cap!, cut: self.cut, description: self.name)
135 }
136
137 }
138
139 access(all) fun featureEnabled(_ action: String) : Bool {
140 return self.features[action] ?? false
141 }
142
143 access(all) fun assertFeatureEnabled(_ action: String) {
144 if !Templates.featureEnabled(action) {
145 panic("Action cannot be taken, feature is not enabled : ".concat(action))
146 }
147 }
148
149 access(account) fun resetCounters() {
150 // The counter is in let, therefore we have to do this.
151 for key in self.counters.keys {
152 self.counters.remove(key: key)
153 }
154 emit CountersReset()
155 }
156
157 access(account) fun setFeature(action: String, enabled: Bool) {
158 self.features[action] = enabled
159 }
160
161 init() {
162 self.counters = {}
163 self.features = {}
164 }
165
166}