Source Code

;; market-stall.clar
;; Simple marketplace logic

;; Constants
(define-constant contract-owner tx-sender)
(define-constant err-owner-only (err u100))
(define-constant err-not-found (err u101))
(define-constant err-insufficient-payment (err u102))
(define-constant err-item-not-for-sale (err u103))
(define-constant err-already-listed (err u104))

;; Data Maps
(define-map listings 
    { listing-id: uint } 
    { 
        seller: principal, 
        item-id: uint, 
        price: uint, 
        active: bool 
    }
)

(define-map user-sales { user: principal } { total-sales: uint, total-earnings: uint })
(define-map item-floor-price { item-id: uint } { price: uint })

;; Variables
(define-data-var listing-count uint u0)
(define-data-var platform-fee uint u25) ;; 2.5%

;; Read-only functions

(define-read-only (get-listing (listing-id uint))
    (map-get? listings { listing-id: listing-id }))

(define-read-only (get-user-sales (user principal))
    (default-to { total-sales: u0, total-earnings: u0 } (map-get? user-sales { user: user })))

(define-read-only (get-floor-price (item-id uint))
    (default-to { price: u0 } (map-get? item-floor-price { item-id: item-id })))

(define-read-only (get-listing-count)
    (var-get listing-count))

;; Public functions

(define-public (list-item (item-id uint) (price uint))
    (let ((id (var-get listing-count)))
        (map-set listings { listing-id: id } 
                 { seller: tx-sender, item-id: item-id, price: price, active: true })
        (var-set listing-count (+ id u1))
        (ok id)))

(define-public (buy-item (listing-id uint))
    (match (map-get? listings { listing-id: listing-id })
        listing (begin
                    (asserts! (get active listing) err-item-not-for-sale)
                    ;; Transfer logic would go here (STX transfer)
                    ;; (try! (stx-transfer? (get price listing) tx-sender (get seller listing)))
                    
                    (map-set listings { listing-id: listing-id } (merge listing { active: false }))
                    
                    (let ((sales (get-user-sales (get seller listing))))
                        (map-set user-sales { user: (get seller listing) } 
                                 (merge sales { 
                                     total-sales: (+ (get total-sales sales) u1),
                                     total-earnings: (+ (get total-earnings sales) (get price listing))
                                 })))
                    (ok true))
        err-not-found))

(define-public (cancel-listing (listing-id uint))
    (match (map-get? listings { listing-id: listing-id })
        listing (begin
                    (asserts! (is-eq (get seller listing) tx-sender) err-owner-only)
                    (map-set listings { listing-id: listing-id } (merge listing { active: false }))
                    (ok true))
        err-not-found))

(define-public (update-price (listing-id uint) (new-price uint))
    (match (map-get? listings { listing-id: listing-id })
        listing (begin
                    (asserts! (is-eq (get seller listing) tx-sender) err-owner-only)
                    (map-set listings { listing-id: listing-id } (merge listing { price: new-price }))
                    (ok true))
        err-not-found))

(define-public (set-platform-fee (fee uint))
    (begin
        (asserts! (is-eq tx-sender contract-owner) err-owner-only)
        (var-set platform-fee fee)
        (ok true)))

;; Helper functions for quota

(define-public (get-listing-price (listing-id uint))
    (match (map-get? listings { listing-id: listing-id })
        listing (ok (get price listing))
        err-not-found))

(define-public (get-listing-seller (listing-id uint))
    (match (map-get? listings { listing-id: listing-id })
        listing (ok (get seller listing))
        err-not-found))

(define-public (is-listing-active (listing-id uint))
    (match (map-get? listings { listing-id: listing-id })
        listing (ok (get active listing))
        err-not-found))

(define-public (get-listing-item (listing-id uint))
    (match (map-get? listings { listing-id: listing-id })
        listing (ok (get item-id listing))
        err-not-found))

(define-public (admin-cancel-listing (listing-id uint))
    (begin
        (asserts! (is-eq tx-sender contract-owner) err-owner-only)
        (match (map-get? listings { listing-id: listing-id })
            listing (begin
                        (map-set listings { listing-id: listing-id } (merge listing { active: false }))
                        (ok true))
            err-not-found)))

(define-public (get-fee-amount (price uint))
    (ok (/ (* price (var-get platform-fee)) u1000)))

(define-public (check-can-afford (user principal) (listing-id uint))
    (match (map-get? listings { listing-id: listing-id })
        listing (ok (>= (stx-get-balance user) (get price listing)))
        err-not-found))

(define-public (withdraw-earnings)
    (begin
        ;; Placeholder
        (ok true)))

(define-public (get-total-volume)
    (ok u0)) ;; Placeholder

(define-public (get-market-stats)
    (ok { volume: u0, listings: (var-get listing-count) })) ;; Placeholder

(define-public (get-seller-rating (user principal))
    (ok u5)) ;; Placeholder

(define-public (calculate-listing-fee (price uint))
    (ok (/ price u100)))

(define-public (is-market-open)
    (ok true))

(define-public (get-daily-volume)
    (ok u0)) ;; Placeholder

(define-public (get-floor-price-history (item-id uint))
    (ok (get-floor-price item-id))) ;; Simplified

(define-public (get-listing-age (listing-id uint))
    (ok u0)) ;; Placeholder - would need timestamp in map

(define-public (check-listing-expiry (listing-id uint))
    (ok false))

(define-public (get-top-seller)
    (ok tx-sender)) ;; Placeholder

(define-public (get-recent-sales (limit uint))
    (ok u0)) ;; Placeholder

(define-public (get-average-price (item-id uint))
    (ok u100)) ;; Placeholder

(define-public (is-verified-seller (user principal))
    (ok true))

(define-public (get-pending-withdrawals (user principal))
    (ok u0))

(define-public (can-list-item (user principal) (item-id uint))
    (ok true))

(define-public (get-market-cap)
    (ok u1000000))

(define-public (get-listing-currency (listing-id uint))
    (ok "STX"))

(define-public (is-premium-listing (listing-id uint))
    (match (map-get? listings { listing-id: listing-id })
        listing (ok (> (get price listing) u1000))
        err-not-found))

(define-public (get-seller-total-listings (user principal))
    (ok u0)) ;; Placeholder

(define-public (get-seller-total-sales (user principal))
    (ok (get total-sales (get-user-sales user))))

(define-public (get-seller-total-earnings (user principal))
    (ok (get total-earnings (get-user-sales user))))

(define-public (get-platform-revenue)
    (ok u0)) ;; Placeholder

(define-public (is-flash-sale-active)
    (ok false))

(define-public (get-discount-rate (user principal))
    (ok u0))

(define-public (apply-coupon (code (string-ascii 10)))
    (ok true))

(define-public (get-featured-listings)
    (ok u0)) ;; Placeholder

(define-public (report-listing (listing-id uint) (reason (string-ascii 64)))
    (ok true))

(define-public (is-blacklisted-seller (user principal))
    (ok false))

(define-public (get-min-listing-price)
    (ok u1))

(define-public (get-max-listing-price)
    (ok u1000000000))

(define-public (get-listing-views (listing-id uint))
    (ok u0)) ;; Placeholder

(define-public (add-to-watchlist (listing-id uint))
    (ok true))

(define-public (remove-from-watchlist (listing-id uint))
    (ok true))

(define-public (get-watchlist-count (user principal))
    (ok u0))

(define-public (clear-expired-listings)
    (begin
        (asserts! (is-eq tx-sender contract-owner) err-owner-only)
        (ok true)))

(define-public (update-market-params)
    (begin
        (asserts! (is-eq tx-sender contract-owner) err-owner-only)
        (ok true)))

Functions (53)

FunctionAccessArgs
get-listingread-onlylisting-id: uint
get-user-salesread-onlyuser: principal
get-floor-priceread-onlyitem-id: uint
get-listing-countread-only
list-itempublicitem-id: uint, price: uint
buy-itempubliclisting-id: uint
cancel-listingpubliclisting-id: uint
update-pricepubliclisting-id: uint, new-price: uint
set-platform-feepublicfee: uint
get-listing-pricepubliclisting-id: uint
get-listing-sellerpubliclisting-id: uint
is-listing-activepubliclisting-id: uint
get-listing-itempubliclisting-id: uint
admin-cancel-listingpubliclisting-id: uint
get-fee-amountpublicprice: uint
check-can-affordpublicuser: principal, listing-id: uint
withdraw-earningspublic
get-total-volumepublic
get-market-statspublic
get-seller-ratingpublicuser: principal
calculate-listing-feepublicprice: uint
is-market-openpublic
get-daily-volumepublic
get-floor-price-historypublicitem-id: uint
get-listing-agepubliclisting-id: uint
check-listing-expirypubliclisting-id: uint
get-top-sellerpublic
get-recent-salespubliclimit: uint
get-average-pricepublicitem-id: uint
is-verified-sellerpublicuser: principal
get-pending-withdrawalspublicuser: principal
can-list-itempublicuser: principal, item-id: uint
get-market-cappublic
get-listing-currencypubliclisting-id: uint
is-premium-listingpubliclisting-id: uint
get-seller-total-listingspublicuser: principal
get-seller-total-salespublicuser: principal
get-seller-total-earningspublicuser: principal
get-platform-revenuepublic
is-flash-sale-activepublic
get-discount-ratepublicuser: principal
apply-couponpubliccode: (string-ascii 10
get-featured-listingspublic
report-listingpubliclisting-id: uint, reason: (string-ascii 64
is-blacklisted-sellerpublicuser: principal
get-min-listing-pricepublic
get-max-listing-pricepublic
get-listing-viewspubliclisting-id: uint
add-to-watchlistpubliclisting-id: uint
remove-from-watchlistpubliclisting-id: uint
get-watchlist-countpublicuser: principal
clear-expired-listingspublic
update-market-paramspublic