;; title: NFTUniverse
;; version:
;; summary:
;; description:
;; constants
(define-constant CONTRACT-OWNER tx-sender)
(define-constant ERR-NOT-OWNER (err u100))
(define-constant ERR-NOT-STAKED (err u101))
(define-constant ERR-ALREADY-STAKED (err u102))
(define-constant ERR-INSUFFICIENT-FUNDS (err u103))
(define-constant ERR-INVALID-NFT (err u104))
(define-constant ERR-COOLDOWN-PERIOD (err u105))
;; data vars
(define-data-var total-staked uint u0)
(define-data-var reward-rate uint u100)
(define-data-var pool-balance uint u0)
(define-data-var contract-enabled bool true)
;; data maps
(define-map staked-nfts
{ token-id: uint, nft-contract: principal }
{
owner: principal,
stake-block: uint,
last-claim-block: uint
}
)
(define-map user-stakes
principal
{
nft-count: uint,
total-rewards: uint
}
)
;; public functions
(define-public (stake-nft (nft-contract principal) (token-id uint))
(let (
(stake-key { token-id: token-id, nft-contract: nft-contract })
(current-stakes (default-to { nft-count: u0, total-rewards: u0 } (map-get? user-stakes tx-sender)))
)
(asserts! (var-get contract-enabled) (err u999))
(asserts! (is-none (map-get? staked-nfts stake-key)) ERR-ALREADY-STAKED)
(map-set staked-nfts stake-key {
owner: tx-sender,
stake-block: stacks-block-height,
last-claim-block: stacks-block-height
})
(map-set user-stakes tx-sender {
nft-count: (+ (get nft-count current-stakes) u1),
total-rewards: (get total-rewards current-stakes)
})
(var-set total-staked (+ (var-get total-staked) u1))
(ok true)
)
)
(define-public (set-reward-rate (new-rate uint))
(begin
(asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-OWNER)
(var-set reward-rate new-rate)
(ok true)
)
)
(define-public (toggle-contract (enabled bool))
(begin
(asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-OWNER)
(var-set contract-enabled enabled)
(ok true)
)
)
;; read only functions
(define-read-only (get-stake-info (nft-contract principal) (token-id uint))
(map-get? staked-nfts { token-id: token-id, nft-contract: nft-contract })
)
(define-read-only (get-user-stakes (user principal))
(map-get? user-stakes user)
)
(define-read-only (calculate-rewards (stake-key { token-id: uint, nft-contract: principal }))
(match (map-get? staked-nfts stake-key)
stake-info
(let (
(blocks-staked (- stacks-block-height (get last-claim-block stake-info)))
(reward-per-block (var-get reward-rate))
)
(* blocks-staked reward-per-block)
)
u0
)
)
(define-read-only (get-pending-rewards (nft-contract principal) (token-id uint))
(calculate-rewards { token-id: token-id, nft-contract: nft-contract })
)
(define-read-only (get-pool-stats)
{
total-staked: (var-get total-staked),
pool-balance: (var-get pool-balance),
reward-rate: (var-get reward-rate),
contract-enabled: (var-get contract-enabled)
}
)