Smart Contract
D3SKRegistry
A.5ec90e3dcf0067c4.D3SKRegistry
1// D3SKRegistry.cdc — Onchain offer index for discoverability
2// Holds NO funds. Purely an index of active offers.
3
4access(all) contract D3SKRegistry {
5
6 // ── Events ────────────────────────────────────────────────────
7 access(all) event OfferRegistered(
8 id: UInt64,
9 maker: Address,
10 sellType: String,
11 sellAmount: UFix64,
12 askType: String,
13 askAmount: UFix64
14 )
15 access(all) event OfferRemoved(id: UInt64, reason: String)
16
17 // ── Offer Listing Struct ─────────────────────────────────────
18 access(all) struct OfferListing {
19 access(all) let id: UInt64
20 access(all) let maker: Address
21 access(all) let sellType: String
22 access(all) let sellAmount: UFix64
23 access(all) let askType: String
24 access(all) let askAmount: UFix64
25 access(all) let price: UFix64 // askAmount / sellAmount
26 access(all) let createdAt: UFix64
27 access(all) let expiresAt: UFix64? // nil = no expiration
28
29 init(
30 id: UInt64,
31 maker: Address,
32 sellType: String,
33 sellAmount: UFix64,
34 askType: String,
35 askAmount: UFix64,
36 createdAt: UFix64,
37 expiresAt: UFix64?
38 ) {
39 self.id = id
40 self.maker = maker
41 self.sellType = sellType
42 self.sellAmount = sellAmount
43 self.askType = askType
44 self.askAmount = askAmount
45 // Calculate price as ask per unit of sell
46 if sellAmount > 0.0 {
47 self.price = askAmount / sellAmount
48 } else {
49 self.price = 0.0
50 }
51 self.createdAt = createdAt
52 self.expiresAt = expiresAt
53 }
54 }
55
56 // ── State ─────────────────────────────────────────────────────
57 // All active offer listings indexed by ID
58 access(self) var listings: {UInt64: OfferListing}
59 // Index: maker address -> set of offer IDs
60 access(self) var makerOffers: {Address: [UInt64]}
61 // Index: pair key (sellType-askType) -> set of offer IDs
62 access(self) var pairOffers: {String: [UInt64]}
63 // Track known pairs
64 access(all) var knownPairs: [String]
65
66 // ── Registration ──────────────────────────────────────────────
67 access(all) fun registerOffer(
68 id: UInt64,
69 maker: Address,
70 sellType: String,
71 sellAmount: UFix64,
72 askType: String,
73 askAmount: UFix64,
74 expiresAt: UFix64?
75 ) {
76 let listing = OfferListing(
77 id: id,
78 maker: maker,
79 sellType: sellType,
80 sellAmount: sellAmount,
81 askType: askType,
82 askAmount: askAmount,
83 createdAt: getCurrentBlock().timestamp,
84 expiresAt: expiresAt
85 )
86
87 self.listings[id] = listing
88
89 // Update maker index
90 if self.makerOffers[maker] == nil {
91 self.makerOffers[maker] = []
92 }
93 self.makerOffers[maker]!.append(id)
94
95 // Update pair index
96 let pairKey = self.getPairKey(sellType: sellType, askType: askType)
97 if self.pairOffers[pairKey] == nil {
98 self.pairOffers[pairKey] = []
99 self.knownPairs.append(pairKey)
100 }
101 self.pairOffers[pairKey]!.append(id)
102
103 emit OfferRegistered(
104 id: id,
105 maker: maker,
106 sellType: sellType,
107 sellAmount: sellAmount,
108 askType: askType,
109 askAmount: askAmount
110 )
111 }
112
113 // ── Removal ───────────────────────────────────────────────────
114 access(all) fun removeOffer(id: UInt64, reason: String) {
115 if let listing = self.listings[id] {
116 // Remove from maker index
117 if var makerList = self.makerOffers[listing.maker] {
118 var i = 0
119 while i < makerList.length {
120 if makerList[i] == id {
121 makerList.remove(at: i)
122 break
123 }
124 i = i + 1
125 }
126 self.makerOffers[listing.maker] = makerList
127 if makerList.length == 0 {
128 self.makerOffers.remove(key: listing.maker)
129 }
130 }
131
132 // Remove from pair index
133 let pairKey = self.getPairKey(sellType: listing.sellType, askType: listing.askType)
134 if var pairList = self.pairOffers[pairKey] {
135 var i = 0
136 while i < pairList.length {
137 if pairList[i] == id {
138 pairList.remove(at: i)
139 break
140 }
141 i = i + 1
142 }
143 self.pairOffers[pairKey] = pairList
144 if pairList.length == 0 {
145 self.pairOffers.remove(key: pairKey)
146 // Also remove from knownPairs
147 var pairIdx = 0
148 while pairIdx < self.knownPairs.length {
149 if self.knownPairs[pairIdx] == pairKey {
150 self.knownPairs.remove(at: pairIdx)
151 break
152 }
153 pairIdx = pairIdx + 1
154 }
155 }
156 }
157
158 // Remove from main listings
159 self.listings.remove(key: id)
160
161 emit OfferRemoved(id: id, reason: reason)
162 }
163 }
164
165 // ── Queries ───────────────────────────────────────────────────
166
167 // Get all active listings
168 access(all) fun getAllListings(): [OfferListing] {
169 return self.listings.values
170 }
171
172 // Get listing by ID
173 access(all) fun getListing(id: UInt64): OfferListing? {
174 return self.listings[id]
175 }
176
177 // Get all listings for a maker
178 access(all) fun getListingsByMaker(maker: Address): [OfferListing] {
179 let result: [OfferListing] = []
180 if let ids = self.makerOffers[maker] {
181 for id in ids {
182 if let listing = self.listings[id] {
183 result.append(listing)
184 }
185 }
186 }
187 return result
188 }
189
190 // Get all listings for a trading pair
191 access(all) fun getListingsByPair(sellType: String, askType: String): [OfferListing] {
192 let result: [OfferListing] = []
193 let pairKey = self.getPairKey(sellType: sellType, askType: askType)
194 if let ids = self.pairOffers[pairKey] {
195 for id in ids {
196 if let listing = self.listings[id] {
197 result.append(listing)
198 }
199 }
200 }
201 return result
202 }
203
204 // Get all known trading pairs
205 access(all) fun getPairs(): [String] {
206 return self.knownPairs
207 }
208
209 // Get total number of active offers
210 access(all) fun getTotalOffers(): Int {
211 return self.listings.keys.length
212 }
213
214 // ── Helpers ───────────────────────────────────────────────────
215 access(all) fun getPairKey(sellType: String, askType: String): String {
216 return sellType.concat("-").concat(askType)
217 }
218
219 // ── Contract Init ─────────────────────────────────────────────
220 init() {
221 self.listings = {}
222 self.makerOffers = {}
223 self.pairOffers = {}
224 self.knownPairs = []
225 }
226}
227