Smart Contract
GaiaOrder
A.8b148183c28ff88f.GaiaOrder
1import GaiaFee from 0x8b148183c28ff88f
2import FungibleToken from 0xf233dcee88fe0abe
3import NFTStorefront from 0x4eb8a10cb9f87357
4import NonFungibleToken from 0x1d7e57aa55817448
5
6pub contract GaiaOrder {
7
8 pub let BUYER_FEE: String
9 pub let SELLER_FEE: String
10 pub let OTHER: String
11 pub let ROYALTY: String
12 pub let REWARD: String
13
14 init() {
15 // market buyer fee (on top of the price)
16 self.BUYER_FEE = "BUYER_FEE"
17
18 // market seller fee
19 self.SELLER_FEE = "SELLER_FEE"
20
21 // additional payments
22 self.OTHER = "OTHER"
23
24 // royalty
25 self.ROYALTY = "ROYALTY"
26
27 // seller reward
28 self.REWARD = "REWARD"
29 }
30
31 // PaymentPart
32 //
33 pub struct PaymentPart {
34 // receiver address
35 pub let address: Address
36
37 // payment rate
38 pub let rate: UFix64
39
40 init(address: Address, rate: UFix64) {
41 self.address = address
42 self.rate = rate
43 }
44 }
45
46 // Payment
47 // Describes payment in the event OrderAvailable
48 //
49 pub struct Payment {
50 // type of payment
51 pub let type: String
52
53 // receiver address
54 pub let address: Address
55
56 // payment rate
57 pub let rate: UFix64
58
59 // payment amount
60 pub let amount: UFix64
61
62 init(type: String, address: Address, rate: UFix64, amount: UFix64) {
63 self.type = type
64 self.address = address
65 self.rate = rate
66 self.amount = amount
67 }
68 }
69
70 // OrderAvailable
71 // Order created and available for purchase
72 //
73 pub event OrderAvailable(
74 orderAddress: Address,
75 orderId: UInt64,
76 nftType: String,
77 nftId: UInt64,
78 vaultType: String,
79 price: UFix64,
80 payments: [Payment]
81 )
82
83 pub event OrderClosed(
84 orderAddress: Address,
85 orderId: UInt64,
86 nftType: String,
87 nftId: UInt64,
88 vaultType: String,
89 price: UFix64,
90 buyerAddress: Address,
91 cuts: [PaymentPart]
92 )
93
94 pub event OrderCancelled(
95 orderAddress: Address,
96 orderId: UInt64,
97 nftType: String,
98 nftId: UInt64,
99 vaultType: String,
100 price: UFix64,
101 cuts: [PaymentPart]
102 )
103
104 // addOrder
105 // Wrapper for NFTStorefront.createListing
106 //
107 pub fun addOrder(
108 storefront: &NFTStorefront.Storefront,
109 nftProvider: Capability<&{NonFungibleToken.Provider,NonFungibleToken.CollectionPublic}>,
110 nftType: Type,
111 nftId: UInt64,
112 vaultPath: PublicPath,
113 vaultType: Type,
114 price: UFix64,
115 extraCuts: [PaymentPart],
116 royalties: [PaymentPart]
117 ): UInt64 {
118 let orderAddress = storefront.owner!.address
119 let payments: [Payment] = []
120 let saleCuts: [NFTStorefront.SaleCut] = []
121 var percentage = 1.0
122
123 let addPayment = fun (type: String, address: Address, rate: UFix64) {
124 assert(rate >= 0.0 && rate < 1.0, message: "Rate must be in range [0..1)")
125 let amount = price * rate
126 let receiver = getAccount(address).getCapability<&{FungibleToken.Receiver}>(vaultPath)
127 assert(receiver.borrow() != nil, message: "Missing or mis-typed fungible token receiver")
128
129 payments.append(Payment(type:type, address:address, rate: rate, amount: amount))
130 saleCuts.append(NFTStorefront.SaleCut(receiver: receiver, amount: amount))
131
132 percentage = percentage - rate
133 }
134
135 if GaiaFee.buyerFee > 0.0 {
136 addPayment(GaiaOrder.BUYER_FEE, GaiaFee.feeAddress(), GaiaFee.buyerFee)
137 }
138 if GaiaFee.sellerFee > 0.0 {
139 addPayment(GaiaOrder.SELLER_FEE, GaiaFee.feeAddress(), GaiaFee.sellerFee)
140 }
141
142 for cut in extraCuts {
143 addPayment(GaiaOrder.OTHER, cut.address, cut.rate)
144 }
145
146 for royalty in royalties {
147 addPayment(GaiaOrder.ROYALTY, royalty.address, royalty.rate)
148 }
149
150 addPayment(GaiaOrder.REWARD, orderAddress, percentage)
151
152 let orderId = storefront.createListing(
153 nftProviderCapability: nftProvider,
154 nftType: nftType,
155 nftID: nftId,
156 salePaymentVaultType: vaultType,
157 saleCuts: saleCuts
158 )
159
160 emit OrderAvailable(
161 orderAddress: orderAddress,
162 orderId: orderId,
163 nftType: nftType.identifier,
164 nftId: nftId,
165 vaultType: vaultType.identifier,
166 price: price,
167 payments: payments
168 )
169
170 return orderId
171 }
172
173 // closeOrder
174 // Purchase nft by o
175 //
176 pub fun closeOrder(
177 storefront: &NFTStorefront.Storefront{NFTStorefront.StorefrontPublic},
178 orderId: UInt64,
179 orderAddress: Address,
180 listing: &NFTStorefront.Listing{NFTStorefront.ListingPublic},
181 paymentVault: @FungibleToken.Vault,
182 buyerAddress: Address
183 ): @NonFungibleToken.NFT {
184 let details = listing.getDetails()
185 let cuts: [PaymentPart] = []
186 for saleCut in details.saleCuts {
187 cuts.append(PaymentPart(address: saleCut.receiver.address, rate: saleCut.amount))
188 }
189
190 emit OrderClosed(
191 orderAddress: orderAddress,
192 orderId: orderId,
193 nftType: details.nftType.identifier,
194 nftId: details.nftID,
195 vaultType: details.salePaymentVaultType.identifier,
196 price: details.salePrice,
197 buyerAddress: buyerAddress,
198 cuts: cuts
199 )
200
201 let item <- listing.purchase(payment: <-paymentVault)
202 storefront.cleanup(listingResourceID: orderId)
203 return <- item
204 }
205
206 // removeOrder
207 // Cancel sale, dismiss order
208 //
209 pub fun removeOrder(
210 storefront: &NFTStorefront.Storefront,
211 orderId: UInt64,
212 orderAddress: Address,
213 listing: &NFTStorefront.Listing{NFTStorefront.ListingPublic},
214 ) {
215 let details = listing.getDetails()
216 let cuts: [PaymentPart] = []
217 for saleCut in details.saleCuts {
218 cuts.append(PaymentPart(address: saleCut.receiver.address, rate: saleCut.amount))
219 }
220
221 emit OrderCancelled(
222 orderAddress: orderAddress,
223 orderId: orderId,
224 nftType: details.nftType.identifier,
225 nftId: details.nftID,
226 vaultType: details.salePaymentVaultType.identifier,
227 price: details.salePrice,
228 cuts: cuts
229 )
230
231 storefront.removeListing(listingResourceID: orderId)
232 }
233}
234