bitcoin-whales-spoints-subscriber

SP1N057R0S5BBAQKTW0GF2J7BXKFHY2GQV9MP2BEN

Source Code

;;Contract that enables the subscription of nfts in collection SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-whales to gain spoints.
(impl-trait .subscriber-trait.subscriber-trait)
(use-trait lookup-trait 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.lookup-trait.lookup-trait)
;;consts
(define-constant ERR-NOT-AUTHORIZED u404)
(define-constant ERR-INSUFFICIENT-BALANCE u401)
(define-constant collection-address 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-whales)
;;maps
(define-map subscription-per-address { address: principal } {  time: uint, points-balance: uint, total-multiplier: uint , lifetime-earnings: uint})
(define-map subscribed-nfts-per-address { address: principal} { ids: (list 2500 uint) })
(define-map items-subscribers {item: uint} { address: principal })
(define-data-var admin principal tx-sender)
;;vars
(define-data-var subscribed-items uint u0)
(define-data-var multipliers principal 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.whale-multipliers)
(define-data-var removing-item-id uint u0)
(define-data-var blocks-per-spoint uint u15)
(define-data-var shutoff-valve bool false)
;;checks the subscription data of an address
(define-read-only (get-subscription-per-address (address principal))
    (default-to 
      {time: u0, points-balance: u0, total-multiplier: u0 , lifetime-earnings: u0} 
      (map-get? subscription-per-address { address: address })))
;;Given an nft, returns the address that last subscribed it
(define-read-only (get-item-subscriber (item uint))
  (ok (get address (map-get? items-subscribers { item: item}))))
;;returns the base number of spoints allocated to an address per block
(define-read-only (get-blocks-per-spoint)
    (default-to u0 (some (var-get blocks-per-spoint))))
;;returns multipliers for the collection
(define-read-only (get-multipliers)
    (ok (var-get multipliers)))
;;returns contract admin
(define-read-only (get-admin)
    (ok (var-get admin))) 
;;returns the number of spoints that can be collected for an address
(define-read-only (get-collect (address principal))
    (ok (check-collect address)))
;;returns the list of nfts subscribed by an address
(define-read-only (get-subscribed-nfts-per-address (address principal))
    (ok (check-subscribed-nfts-per-address address)))
;;returns the total number of nfts subscribed for this collection
(define-read-only (get-subscribed-items-count) 
  (ok (var-get subscribed-items)))

;;private functions
(define-private (check-subscribed-nfts-per-address (address principal))
  (default-to (list ) (get ids (map-get? subscribed-nfts-per-address { address: address}))))
(define-private (check-collect (address principal))
    (let (
        (subscription (get-subscription-per-address address))
        (block block-height)
        (balance (get points-balance subscription))
        (total-multiplier (get total-multiplier subscription))
        (prev-time (get time subscription))
        (blocks-per-sp (get-blocks-per-spoint))
        (points-added (/ (/ (* u1000000 (* total-multiplier (- block prev-time))) u10000) blocks-per-sp))
        (to-collect (+ balance points-added))       
    )
        to-collect))
(define-private (remove-item-id (item-id uint))
  (if (is-eq item-id (var-get removing-item-id)) false true))

(define-private (unsubscribe (lookup-table <lookup-trait>) (item uint))
    (let (
        (subscriber (unwrap-panic (unwrap-panic (get-item-subscriber item))))
        (subscription (get-subscription-per-address subscriber))
        (balance (get points-balance subscription))
        (total-multiplier (get total-multiplier subscription))
        (prev-time (get time subscription))
        (lifetime (get lifetime-earnings subscription))
        (multiplier (unwrap-panic (contract-call? lookup-table lookup (- item u1))))
        (block block-height)
        (blocks-per-sp (get-blocks-per-spoint))
        (points-added (/ (/ (* u1000000 (* total-multiplier (- block prev-time))) u10000) blocks-per-sp))
        (ids (check-subscribed-nfts-per-address subscriber))
    )
    (asserts! (is-eq (var-get multipliers) (contract-of lookup-table)) (err ERR-NOT-AUTHORIZED))
    (var-set removing-item-id item)
    (begin 
        (map-set subscription-per-address { address: subscriber} { time: block, points-balance: (+ balance points-added), total-multiplier: (- total-multiplier multiplier), lifetime-earnings: lifetime })
        (map-set subscribed-nfts-per-address { address: subscriber} { ids: (filter remove-item-id ids) })
        (var-set subscribed-items (- (var-get subscribed-items) u1))
        (ok true))))

;;public functions

;;subscribes an nft in the collection to allocate spoints, 
;;it will remain subscribed until another address subscribes the same nft
(define-public (subscribe (lookup-table <lookup-trait>) (item uint)) 
    (let (
        (subscriber (unwrap-panic (get-item-subscriber item)))
        (unsubscribe-old-address (if (not (or (is-none subscriber) (is-eq subscriber (some tx-sender)))) (unsubscribe lookup-table item) (ok true)))
        (subscription (get-subscription-per-address tx-sender))
        (balance (get points-balance subscription))
        (total-multiplier (get total-multiplier subscription))
        (prev-time (get time subscription))
        (lifetime (get lifetime-earnings subscription))
        (multiplier (unwrap-panic (contract-call? lookup-table lookup (- item u1))))
        (block block-height)
        (blocks-per-sp (get-blocks-per-spoint))
        (points-added (/ (/ (* u1000000 (* total-multiplier (- block prev-time))) u10000) blocks-per-sp))
        (ids (check-subscribed-nfts-per-address tx-sender))
        )
        (asserts! (is-eq (var-get shutoff-valve) false) (err ERR-NOT-AUTHORIZED)) 
        (asserts! (not (is-some (index-of (check-subscribed-nfts-per-address tx-sender) item))) (err ERR-NOT-AUTHORIZED))
        (asserts! (is-eq (var-get multipliers) (contract-of lookup-table)) (err ERR-NOT-AUTHORIZED))
        (asserts! (is-eq (unwrap-panic (unwrap-panic (contract-call? 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-whales get-owner item))) tx-sender) (err ERR-NOT-AUTHORIZED))
        (map-set subscription-per-address { address: tx-sender } { time: block, points-balance: (+ balance points-added), total-multiplier: (+ total-multiplier multiplier), lifetime-earnings: lifetime })
        (map-set subscribed-nfts-per-address { address: tx-sender } { ids: (unwrap-panic (as-max-len? (append ids item) u2500)) })
        (var-set subscribed-items (+ (var-get subscribed-items) u1))
        (map-set items-subscribers { item: item } { address: tx-sender })
        (ok true)))
;;generates the allocated spoints and links them to an nft in the collection SP1C2K603TGWJGKPT2Z3WWHA0ARM66D352385TTWH.spaghettipunk-club
(define-public (collect (spc-id uint) (amount uint))
  (let (
      (block block-height)
      (owner tx-sender)
      (subscription (get-subscription-per-address tx-sender))
      (lifetime (get lifetime-earnings subscription))
      (total-multiplier (get total-multiplier subscription))
      (to-collect (check-collect tx-sender))
    )
    (asserts! (is-eq (var-get shutoff-valve) false) (err ERR-NOT-AUTHORIZED))
    (asserts! (<= amount to-collect) (err ERR-INSUFFICIENT-BALANCE))
    (begin      
      (map-set subscription-per-address { address: tx-sender} {time: block-height, points-balance: u0, total-multiplier: total-multiplier , lifetime-earnings: (+ lifetime to-collect)})
      (try! (contract-call? .spoints collect spc-id amount))
      (ok true))))

;;admin functions   
(define-public (admin-unsubscribe (lookup-table <lookup-trait>) (item uint))
    (begin 
      (asserts! (is-eq tx-sender (var-get admin)) (err ERR-NOT-AUTHORIZED))
      (try! (unsubscribe lookup-table item))
      (map-delete items-subscribers { item: item })
      (ok true)))
(define-public (change-multipliers (new-multipliers principal))
  (if (is-eq tx-sender (var-get admin))
    (ok (var-set multipliers new-multipliers))
    (err ERR-NOT-AUTHORIZED)))
(define-public (change-admin (address principal))
  (if (is-eq tx-sender (var-get admin))
    (ok (var-set admin address))
    (err ERR-NOT-AUTHORIZED)))
(define-public (change-blocks-per-spoint (new-blocks-per-spoint-rate uint))
  (if (is-eq tx-sender (var-get admin))
    (ok (var-set blocks-per-spoint new-blocks-per-spoint-rate))
    (err ERR-NOT-AUTHORIZED)))

(contract-call? .spoints principal-approve (as-contract tx-sender))

Functions (18)

FunctionAccessArgs
get-subscription-per-addressread-onlyaddress: principal
get-item-subscriberread-onlyitem: uint
get-blocks-per-spointread-only
get-multipliersread-only
get-adminread-only
get-collectread-onlyaddress: principal
get-subscribed-nfts-per-addressread-onlyaddress: principal
get-subscribed-items-countread-only
check-subscribed-nfts-per-addressprivateaddress: principal
check-collectprivateaddress: principal
remove-item-idprivateitem-id: uint
unsubscribeprivatelookup-table: <lookup-trait>, item: uint
subscribepubliclookup-table: <lookup-trait>, item: uint
collectpublicspc-id: uint, amount: uint
admin-unsubscribepubliclookup-table: <lookup-trait>, item: uint
change-multiplierspublicnew-multipliers: principal
change-adminpublicaddress: principal
change-blocks-per-spointpublicnew-blocks-per-spoint-rate: uint