Source Code

(define-fungible-token pbm-token)

(define-map token-metadata
    { token-id: uint }
    { 
        purpose: (string-ascii 64),
        issuer: principal,
        valid-until: uint,
        restrictions: (string-utf8 256)
    }
)

(define-map token-balances
    { token-id: uint, owner: principal }
    uint
)

(define-map compliance-guards
    principal
    bool
)

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

(define-constant contract-owner tx-sender)
(define-constant err-not-owner (err u100))
(define-constant err-invalid-amount (err u101))
(define-constant err-insufficient-balance (err u102))
(define-constant err-token-expired (err u103))
(define-constant err-not-compliant (err u104))
(define-constant err-not-found (err u105))

(define-read-only (get-balance (token-id uint) (owner principal))
    (ok (default-to u0 (map-get? token-balances { token-id: token-id, owner: owner })))
)

(define-read-only (get-token-metadata (token-id uint))
    (ok (map-get? token-metadata { token-id: token-id }))
)

(define-read-only (is-compliant (user principal))
    (ok (default-to false (map-get? compliance-guards user)))
)

(define-public (set-compliance-guard (user principal) (compliant bool))
    (begin
        (asserts! (is-eq tx-sender contract-owner) err-not-owner)
        (map-set compliance-guards user compliant)
        (ok true)
    )
)

(define-public (mint-pbm
    (recipient principal)
    (amount uint)
    (purpose (string-ascii 64))
    (valid-until uint)
    (restrictions (string-utf8 256))
)
    (let
        (
            (token-id (+ (var-get last-token-id) u1))
            (is-recipient-compliant (default-to false (map-get? compliance-guards recipient)))
        )
        (asserts! (is-eq tx-sender contract-owner) err-not-owner)
        (asserts! is-recipient-compliant err-not-compliant)
        (asserts! (> amount u0) err-invalid-amount)
        (map-set token-metadata { token-id: token-id }
            {
                purpose: purpose,
                issuer: tx-sender,
                valid-until: valid-until,
                restrictions: restrictions
            }
        )
        (map-set token-balances { token-id: token-id, owner: recipient } amount)
        (var-set last-token-id token-id)
        (ok token-id)
    )
)

(define-public (transfer-pbm (token-id uint) (amount uint) (sender principal) (recipient principal))
    (let
        (
            (sender-balance (default-to u0 (map-get? token-balances { token-id: token-id, owner: sender })))
            (recipient-balance (default-to u0 (map-get? token-balances { token-id: token-id, owner: recipient })))
            (metadata (unwrap! (map-get? token-metadata { token-id: token-id }) err-not-found))
            (is-recipient-compliant (default-to false (map-get? compliance-guards recipient)))
        )
        (asserts! (is-eq tx-sender sender) err-not-owner)
        (asserts! (>= sender-balance amount) err-insufficient-balance)
        (asserts! is-recipient-compliant err-not-compliant)
        (asserts! (< stacks-block-time (get valid-until metadata)) err-token-expired)
        (map-set token-balances { token-id: token-id, owner: sender } (- sender-balance amount))
        (map-set token-balances { token-id: token-id, owner: recipient } (+ recipient-balance amount))
        (ok true)
    )
)

(define-public (redeem-pbm (token-id uint) (amount uint))
    (let
        (
            (balance (default-to u0 (map-get? token-balances { token-id: token-id, owner: tx-sender })))
            (metadata (unwrap! (map-get? token-metadata { token-id: token-id }) err-not-found))
        )
        (asserts! (>= balance amount) err-insufficient-balance)
        (map-set token-balances { token-id: token-id, owner: tx-sender } (- balance amount))
        (ok true)
    )
)

Functions (7)

FunctionAccessArgs
get-balanceread-onlytoken-id: uint, owner: principal
get-token-metadataread-onlytoken-id: uint
is-compliantread-onlyuser: principal
set-compliance-guardpublicuser: principal, compliant: bool
mint-pbmpublicrecipient: principal, amount: uint, purpose: (string-ascii 64
transfer-pbmpublictoken-id: uint, amount: uint, sender: principal, recipient: principal
redeem-pbmpublictoken-id: uint, amount: uint