Source Code

(define-non-fungible-token lockable-nft uint)

(define-data-var last-token-id uint u0)
(define-data-var default-locked bool true)

(define-map locked-tokens uint bool)
(define-map token-owner uint principal)
(define-map approvals { token-id: uint, operator: principal } bool)

(define-constant contract-owner tx-sender)
(define-constant err-owner-only (err u100))
(define-constant err-not-token-owner (err u101))
(define-constant err-token-not-found (err u102))
(define-constant err-token-locked (err u103))
(define-constant err-already-locked (err u104))
(define-constant err-already-unlocked (err u105))

(define-read-only (get-last-token-id)
    (ok (var-get last-token-id))
)

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

(define-read-only (get-default-locked)
    (ok (var-get default-locked))
)

(define-read-only (is-locked (token-id uint))
    (ok (default-to (var-get default-locked) (map-get? locked-tokens token-id)))
)

(define-public (set-default-locked (locked bool))
    (begin
        (asserts! (is-eq tx-sender contract-owner) err-owner-only)
        (ok (var-set default-locked locked))
    )
)

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

(define-public (transfer (token-id uint) (sender principal) (recipient principal))
    (let
        (
            (token-locked (unwrap! (is-locked token-id) err-token-not-found))
        )
        (asserts! (is-eq tx-sender sender) err-not-token-owner)
        (asserts! (not token-locked) err-token-locked)
        (try! (nft-transfer? lockable-nft token-id sender recipient))
        (map-set token-owner token-id recipient)
        (ok true)
    )
)

(define-public (lock (token-id uint))
    (let
        (
            (current-owner (unwrap! (nft-get-owner? lockable-nft token-id) err-token-not-found))
            (token-locked (unwrap! (is-locked token-id) err-token-not-found))
        )
        (asserts! (is-eq tx-sender current-owner) err-not-token-owner)
        (asserts! (not token-locked) err-already-locked)
        (map-set locked-tokens token-id true)
        (ok true)
    )
)

(define-public (unlock (token-id uint))
    (let
        (
            (current-owner (unwrap! (nft-get-owner? lockable-nft token-id) err-token-not-found))
            (token-locked (unwrap! (is-locked token-id) err-token-not-found))
        )
        (asserts! (is-eq tx-sender current-owner) err-not-token-owner)
        (asserts! token-locked err-already-unlocked)
        (map-set locked-tokens token-id false)
        (ok true)
    )
)

Functions (9)

FunctionAccessArgs
get-last-token-idread-only
get-ownerread-onlytoken-id: uint
get-default-lockedread-only
is-lockedread-onlytoken-id: uint
set-default-lockedpubliclocked: bool
mintpublicrecipient: principal
transferpublictoken-id: uint, sender: principal, recipient: principal
lockpublictoken-id: uint
unlockpublictoken-id: uint