Smart Contract

D3SKRegistry

A.5ec90e3dcf0067c4.D3SKRegistry

Valid From

141,920,140

Deployed

2w ago
Feb 12, 2026, 12:14:03 AM UTC

Dependents

0 imports
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