Source Code

;; VIP BAZAAR - Unique NFT Marketplace
;; Inspired by the Tiny Market pattern but optimized for v11

;; Traits definitions
(use-trait nft-trait 'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait.nft-trait)
(use-trait ft-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait)

;; Constants
(define-constant BAZAAR-ADMIN tx-sender)
(define-constant ERR-NOT-AUTHORIZED (err u3001))
(define-constant ERR-INVALID-PRICE (err u3002))
(define-constant ERR-LISTING-NOT-FOUND (err u3003))
(define-constant ERR-EXPIRED (err u3004))

;; Data Structures
(define-map active-offers
    uint 
    {
        seller: principal,
        buyer-only: (optional principal),
        token-id: uint,
        nft-contract: principal,
        deadline: uint,
        cost: uint,
        payment-token: (optional principal)
    }
)

(define-data-var offer-nonce uint u0)
(define-map authorized-contracts principal bool)

;; --- Authorization ---

(define-read-only (is-authorized (contract principal))
    (default-to true (map-get? authorized-contracts contract))
)

(define-public (toggle-contract (contract principal) (status bool))
    (begin
        (asserts! (is-eq tx-sender BAZAAR-ADMIN) ERR-NOT-AUTHORIZED)
        (ok (map-set authorized-contracts contract status))
    )
)

;; --- Internal Helpers ---

(define-private (move-nft (contract <nft-trait>) (id uint) (from principal) (to principal))
    (contract-call? contract transfer id from to)
)

(define-private (move-ft (contract <ft-trait>) (amount uint) (from principal) (to principal))
    (contract-call? contract transfer amount from to none)
)

;; --- Core Functions ---

;; List a new VIP Item
(define-public (create-offer
    (nft-contract <nft-trait>)
    (details {
        buyer-only: (optional principal),
        token-id: uint,
        deadline: uint,
        cost: uint,
        payment-token: (optional principal)
    })
)
    (let ((offer-id (var-get offer-nonce)))
        (asserts! (is-authorized (contract-of nft-contract)) ERR-NOT-AUTHORIZED)
        (asserts! (> (get cost details) u0) ERR-INVALID-PRICE)
        
        ;; Lock NFT in the contract (Escrow)
        (try! (move-nft nft-contract (get token-id details) tx-sender (as-contract tx-sender)))
        
        (map-set active-offers offer-id
            (merge {
                seller: tx-sender,
                nft-contract: (contract-of nft-contract)
            } details)
        )
        
        (var-set offer-nonce (+ offer-id u1))
        (ok offer-id)
    )
)

;; Purchase with STX
(define-public (fill-offer-stx (offer-id uint) (nft-contract <nft-trait>))
    (let (
        (offer (unwrap! (map-get? active-offers offer-id) ERR-LISTING-NOT-FOUND))
        (buyer tx-sender)
    )
        ;; Validations
        (asserts! (not (is-eq (get seller offer) buyer)) (err u3005))
        (asserts! (< burn-block-height (get deadline offer)) ERR-EXPIRED)
        (asserts! (is-eq (get nft-contract offer) (contract-of nft-contract)) (err u3006))
        
        ;; Payments & Transfer
        (try! (as-contract (move-nft nft-contract (get token-id offer) tx-sender buyer)))
        (try! (stx-transfer? (get cost offer) buyer (get seller offer)))
        
        (map-delete active-offers offer-id)
        (ok offer-id)
    )
)

;; --- Read Only ---
(define-read-only (get-offer-data (id uint))
    (map-get? active-offers id)
)

Functions (6)

FunctionAccessArgs
is-authorizedread-onlycontract: principal
toggle-contractpubliccontract: principal, status: bool
move-nftprivatecontract: <nft-trait>, id: uint, from: principal, to: principal
move-ftprivatecontract: <ft-trait>, amount: uint, from: principal, to: principal
fill-offer-stxpublicoffer-id: uint, nft-contract: <nft-trait>
get-offer-dataread-onlyid: uint