Source Code

(define-non-fungible-token ticket uint)

(define-map token-status
    uint
    (string-ascii 10)
)

(define-map token-owner uint principal)

(define-map authorized-resellers
    principal
    bool
)

(define-map resale-history
    { token-id: uint, index: uint }
    { from: principal, to: principal, timestamp: uint, price: uint }
)

(define-map resale-count uint uint)

(define-data-var last-token-id uint u0)

(define-constant contract-owner tx-sender)
(define-constant status-sold "Sold")
(define-constant status-resell "Resell")
(define-constant status-void "Void")
(define-constant status-redeemed "Redeemed")

(define-constant err-not-owner (err u100))
(define-constant err-not-found (err u101))
(define-constant err-invalid-status (err u102))
(define-constant err-not-reseller (err u103))
(define-constant err-already-redeemed (err u104))

(define-read-only (get-token-status (token-id uint))
    (ok (map-get? token-status token-id))
)

(define-read-only (get-owner (token-id uint))
    (ok (map-get? token-owner token-id))
)

(define-read-only (is-authorized-reseller (reseller principal))
    (ok (default-to false (map-get? authorized-resellers reseller)))
)

(define-read-only (get-resale-history (token-id uint) (index uint))
    (ok (map-get? resale-history { token-id: token-id, index: index }))
)

(define-public (mint (recipient principal))
    (let
        (
            (token-id (+ (var-get last-token-id) u1))
        )
        (try! (nft-mint? ticket token-id recipient))
        (map-set token-owner token-id recipient)
        (map-set token-status token-id status-sold)
        (var-set last-token-id token-id)
        (ok token-id)
    )
)

(define-public (authorize-reseller (reseller principal))
    (begin
        (asserts! (is-eq tx-sender contract-owner) err-not-owner)
        (map-set authorized-resellers reseller true)
        (ok true)
    )
)

(define-public (revoke-reseller (reseller principal))
    (begin
        (asserts! (is-eq tx-sender contract-owner) err-not-owner)
        (map-delete authorized-resellers reseller)
        (ok true)
    )
)

(define-public (resell (token-id uint) (new-owner principal) (price uint))
    (let
        (
            (owner (unwrap! (map-get? token-owner token-id) err-not-found))
            (status (unwrap! (map-get? token-status token-id) err-not-found))
            (is-authorized (default-to false (map-get? authorized-resellers tx-sender)))
            (count (default-to u0 (map-get? resale-count token-id)))
        )
        (asserts! is-authorized err-not-reseller)
        (asserts! (not (is-eq status status-redeemed)) err-already-redeemed)
        (try! (nft-transfer? ticket token-id owner new-owner))
        (map-set token-owner token-id new-owner)
        (map-set token-status token-id status-resell)
        (map-set resale-history { token-id: token-id, index: count }
            { from: owner, to: new-owner, timestamp: stacks-block-time, price: price }
        )
        (map-set resale-count token-id (+ count u1))
        (ok true)
    )
)

(define-public (change-status (token-id uint) (new-status (string-ascii 10)))
    (let
        (
            (owner (unwrap! (map-get? token-owner token-id) err-not-found))
        )
        (asserts! (is-eq tx-sender owner) err-not-owner)
        (map-set token-status token-id new-status)
        (ok true)
    )
)

(define-public (redeem (token-id uint))
    (let
        (
            (owner (unwrap! (map-get? token-owner token-id) err-not-found))
            (status (unwrap! (map-get? token-status token-id) err-not-found))
        )
        (asserts! (is-eq tx-sender owner) err-not-owner)
        (asserts! (not (is-eq status status-redeemed)) err-already-redeemed)
        (map-set token-status token-id status-redeemed)
        (ok true)
    )
)

Functions (10)

FunctionAccessArgs
get-token-statusread-onlytoken-id: uint
get-ownerread-onlytoken-id: uint
is-authorized-resellerread-onlyreseller: principal
get-resale-historyread-onlytoken-id: uint, index: uint
mintpublicrecipient: principal
authorize-resellerpublicreseller: principal
revoke-resellerpublicreseller: principal
resellpublictoken-id: uint, new-owner: principal, price: uint
change-statuspublictoken-id: uint, new-status: (string-ascii 10
redeempublictoken-id: uint