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 (49)

FunctionAccessArgs
withdraw-earningspublic
get-listingread-onlylisting-id: uint
get-user-salesread-onlyuser: principal
get-floor-priceread-onlyitem-id: uint
get-listing-countread-only
buy-itempubliclisting-id: uint
cancel-listingpubliclisting-id: 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
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
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