Source Code

;; constants
(define-constant contract-owner tx-sender)
(define-constant err-owner-only (err u100))
(define-constant err-already-claimed (err u101))
(define-constant err-unauthorized-sender (err u102))
(define-constant err-not-unlocked (err u103))
(define-constant err-no-gift-found (err u104))
(define-constant err-zero-amount (err u105))

;; data vars
(define-data-var total-gifts-created uint u0)

;; data maps
(define-map gift-cards
    uint
    {
        creator: principal,
        recipient: principal,
        amount: uint,
        unlock-height: uint,
        claimed: bool
    }
)

;; private functions
(define-private (is-valid-gift-id (gift-id uint))
    (match (map-get? gift-cards gift-id)
        gift true
        false
    )
)

(define-private (is-sender-recipient (gift-id uint))
    (match (map-get? gift-cards gift-id)
        gift (is-eq tx-sender (get recipient gift))
        false
    )
)

(define-private (is-sender-creator (gift-id uint))
    (match (map-get? gift-cards gift-id)
        gift (is-eq tx-sender (get creator gift))
        false
    )
)

(define-private (is-gift-unlocked (gift-id uint))
    (match (map-get? gift-cards gift-id)
        gift (>= block-height (get unlock-height gift))
        false
    )
)

;; public functions
(define-public (create-gift (recipient principal) (amount uint) (unlock-height uint))
    (let 
        (
            (gift-id (+ (var-get total-gifts-created) u1))
        )
        (asserts! (> amount u0) err-zero-amount)
        ;; Transfer STX from sender to contract
        (try! (stx-transfer? amount tx-sender (as-contract tx-sender)))
        
        ;; Create gift card record
        (map-set gift-cards gift-id {
            creator: tx-sender,
            recipient: recipient,
            amount: amount,
            unlock-height: unlock-height,
            claimed: false
        })
        
        ;; Increment total gifts counter
        (var-set total-gifts-created gift-id)
        (ok gift-id)
    )
)

(define-public (claim-gift (gift-id uint))
    (let 
        (
            (gift (unwrap! (map-get? gift-cards gift-id) err-no-gift-found))
        )
        ;; Check if sender is recipient
        (asserts! (is-sender-recipient gift-id) err-unauthorized-sender)
        ;; Check if gift is unlocked
        (asserts! (is-gift-unlocked gift-id) err-not-unlocked)
        ;; Check if gift is not already claimed
        (asserts! (not (get claimed gift)) err-already-claimed)
        
        ;; Transfer STX from contract to recipient
        (try! (as-contract (stx-transfer? (get amount gift) tx-sender (get recipient gift))))
        
        ;; Mark gift as claimed
        (map-set gift-cards gift-id (merge gift { claimed: true }))
        (ok true)
    )
)

(define-public (reclaim-gift (gift-id uint))
    (let 
        (
            (gift (unwrap! (map-get? gift-cards gift-id) err-no-gift-found))
        )
        ;; Check if sender is creator
        (asserts! (is-sender-creator gift-id) err-unauthorized-sender)
        ;; Check if gift is not already claimed
        (asserts! (not (get claimed gift)) err-already-claimed)
        
        ;; Transfer STX back to creator
        (try! (as-contract (stx-transfer? (get amount gift) tx-sender (get creator gift))))
        
        ;; Mark gift as claimed
        (map-set gift-cards gift-id (merge gift { claimed: true }))
        (ok true)
    )
)

;; read only functions
(define-read-only (get-gift (gift-id uint))
    (ok (map-get? gift-cards gift-id))
)

(define-read-only (get-total-gifts)
    (ok (var-get total-gifts-created))
)

(define-read-only (is-claimed (gift-id uint))
    (match (map-get? gift-cards gift-id)
        gift (get claimed gift)
        false
    )
)

Functions (10)

FunctionAccessArgs
is-valid-gift-idprivategift-id: uint
is-sender-recipientprivategift-id: uint
is-sender-creatorprivategift-id: uint
is-gift-unlockedprivategift-id: uint
create-giftpublicrecipient: principal, amount: uint, unlock-height: uint
claim-giftpublicgift-id: uint
reclaim-giftpublicgift-id: uint
get-giftread-onlygift-id: uint
get-total-giftsread-only
is-claimedread-onlygift-id: uint