Source Code

;; Event Tickets Contract
;; Issue and manage event tickets as NFTs
;; Halal - entertainment/education services
;; Clarity 4 compatible

(define-non-fungible-token ticket uint)

(define-constant CONTRACT-OWNER tx-sender)
(define-constant ERR-NOT-AUTHORIZED (err u401))
(define-constant ERR-NOT-FOUND (err u404))
(define-constant ERR-SOLD-OUT (err u405))
(define-constant ERR-ALREADY-USED (err u406))

(define-data-var ticket-count uint u0)
(define-data-var event-count uint u0)

(define-map events uint { organizer: principal, name: (string-utf8 100), price: uint, max-tickets: uint, sold: uint, event-block: uint })
(define-map ticket-info uint { event-id: uint, holder: principal, used: bool, purchased-at: uint })

(define-public (create-event (name (string-utf8 100)) (price uint) (max-tickets uint) (event-block uint))
  (let ((id (+ (var-get event-count) u1)))
    (map-set events id { organizer: tx-sender, name: name, price: price, max-tickets: max-tickets, sold: u0, event-block: event-block })
    (var-set event-count id) (ok id)))

(define-public (buy-ticket (event-id uint))
  (let (
    (event (unwrap! (map-get? events event-id) ERR-NOT-FOUND))
    (tid (+ (var-get ticket-count) u1))
  )
    (asserts! (< (get sold event) (get max-tickets event)) ERR-SOLD-OUT)
    (try! (stx-transfer? (get price event) tx-sender (get organizer event)))
    (try! (nft-mint? ticket tid tx-sender))
    (map-set ticket-info tid { event-id: event-id, holder: tx-sender, used: false, purchased-at: stacks-block-height })
    (map-set events event-id (merge event { sold: (+ (get sold event) u1) }))
    (var-set ticket-count tid) (ok tid)))

(define-public (use-ticket (ticket-id uint))
  (let ((info (unwrap! (map-get? ticket-info ticket-id) ERR-NOT-FOUND)))
    (asserts! (or (is-eq tx-sender (get holder info)) (is-eq tx-sender CONTRACT-OWNER)) ERR-NOT-AUTHORIZED)
    (asserts! (not (get used info)) ERR-ALREADY-USED)
    (map-set ticket-info ticket-id (merge info { used: true })) (ok true)))

(define-public (transfer-ticket (ticket-id uint) (to principal))
  (let ((info (unwrap! (map-get? ticket-info ticket-id) ERR-NOT-FOUND)))
    (asserts! (is-eq tx-sender (get holder info)) ERR-NOT-AUTHORIZED)
    (try! (nft-transfer? ticket ticket-id tx-sender to))
    (map-set ticket-info ticket-id (merge info { holder: to })) (ok true)))

(define-read-only (get-event (id uint)) (map-get? events id))
(define-read-only (get-ticket (id uint)) (map-get? ticket-info id))
(define-read-only (get-event-count) (ok (var-get event-count)))
(define-read-only (get-ticket-count) (ok (var-get ticket-count)))
(define-read-only (get-ticket-owner (id uint)) (nft-get-owner? ticket id))

Functions (9)

FunctionAccessArgs
create-eventpublicname: (string-utf8 100
buy-ticketpublicevent-id: uint
use-ticketpublicticket-id: uint
transfer-ticketpublicticket-id: uint, to: principal
get-eventread-onlyid: uint
get-ticketread-onlyid: uint
get-event-countread-only
get-ticket-countread-only
get-ticket-ownerread-onlyid: uint