Source Code

(define-fungible-token subscription-token)

(define-constant ERR-NOT-AUTHORIZED (err u401))
(define-constant ERR-SUBSCRIPTION-EXPIRED (err u410))
(define-constant ERR-NOT-FOUND (err u404))

(define-data-var token-name (string-ascii 32) "SubscriptionToken")
(define-data-var token-symbol (string-ascii 10) "SUB")
(define-data-var token-decimals uint u0)

(define-map subscriptions
    principal
    {
        start-time: uint,
        end-time: uint,
        tier: uint,
        auto-renew: bool
    }
)

(define-map subscription-tiers
    uint
    {
        price: uint,
        duration: uint,
        benefits: (string-utf8 256)
    }
)

(define-read-only (get-name)
    (ok (var-get token-name))
)

(define-read-only (get-symbol)
    (ok (var-get token-symbol))
)

(define-read-only (get-decimals)
    (ok (var-get token-decimals))
)

(define-read-only (get-balance (account principal))
    (ok (ft-get-balance subscription-token account))
)

(define-read-only (get-total-supply)
    (ok (ft-get-supply subscription-token))
)

(define-read-only (get-subscription (account principal))
    (ok (map-get? subscriptions account))
)

(define-read-only (is-subscription-active (account principal))
    (match (map-get? subscriptions account)
        sub (ok (<= stacks-block-time (get end-time sub)))
        (ok false)
    )
)

(define-read-only (get-tier-info (tier uint))
    (ok (map-get? subscription-tiers tier))
)

(define-public (set-tier (tier uint) (price uint) (duration uint) (benefits (string-utf8 256)))
    (begin
        (ok (map-set subscription-tiers tier {
            price: price,
            duration: duration,
            benefits: benefits
        }))
    )
)

(define-public (subscribe (tier uint))
    (let
        (
            (tier-info (unwrap! (map-get? subscription-tiers tier) ERR-NOT-FOUND))
            (current-time stacks-block-time)
        )
        (map-set subscriptions tx-sender {
            start-time: current-time,
            end-time: (+ current-time (get duration tier-info)),
            tier: tier,
            auto-renew: false
        })
        (try! (ft-mint? subscription-token u1 tx-sender))
        (ok true)
    )
)

(define-public (renew-subscription)
    (let
        (
            (sub (unwrap! (map-get? subscriptions tx-sender) ERR-NOT-FOUND))
            (tier-info (unwrap! (map-get? subscription-tiers (get tier sub)) ERR-NOT-FOUND))
            (current-time stacks-block-time)
        )
        (map-set subscriptions tx-sender (merge sub {
            end-time: (+ (get end-time sub) (get duration tier-info))
        }))
        (ok true)
    )
)

(define-public (cancel-subscription)
    (begin
        (asserts! (is-some (map-get? subscriptions tx-sender)) ERR-NOT-FOUND)
        (try! (ft-burn? subscription-token u1 tx-sender))
        (ok (map-delete subscriptions tx-sender))
    )
)

(define-public (toggle-auto-renew)
    (let
        (
            (sub (unwrap! (map-get? subscriptions tx-sender) ERR-NOT-FOUND))
        )
        (ok (map-set subscriptions tx-sender (merge sub {auto-renew: (not (get auto-renew sub))})))
    )
)

(define-public (transfer (amount uint) (sender principal) (recipient principal))
    (begin
        (asserts! (is-eq tx-sender sender) ERR-NOT-AUTHORIZED)
        (ft-transfer? subscription-token amount sender recipient)
    )
)

(define-read-only (get-contract-hash)
    (contract-hash? .subscription-token)
)

Functions (15)

FunctionAccessArgs
get-nameread-only
get-symbolread-only
get-decimalsread-only
get-balanceread-onlyaccount: principal
get-total-supplyread-only
get-subscriptionread-onlyaccount: principal
is-subscription-activeread-onlyaccount: principal
get-tier-inforead-onlytier: uint
set-tierpublictier: uint, price: uint, duration: uint, benefits: (string-utf8 256
subscribepublictier: uint
renew-subscriptionpublic
cancel-subscriptionpublic
toggle-auto-renewpublic
transferpublicamount: uint, sender: principal, recipient: principal
get-contract-hashread-only