;; ============================================================
;;
;; Rewritten: Buy Gems & Buy Hearts distribute on 5-Mar-2025
;; - 80% STX -> PROGRESSIVE_WALLET
;; - 20% STX -> KRYPTOMIND
;; No burn, no swap, no STONE router integration.
;; ============================================================
;; =======================
;; Error & Constant Codes
;; =======================
(define-constant ERR-NOT-AUTHORIZED (err u401))
(define-constant ERR-INSUFFICIENT-FUNDS (err u402))
(define-constant INVALID-GEMS-COUNT (err u403))
(define-constant INVALID-STX-BALANCE (err u404))
(define-constant ERR-TRANSFER-PROGRESSIVE (err u406))
(define-constant ERR-TRANSFER-KRYPTOMIND (err u407))
(define-constant INVALID-HEART-COUNT (err u409))
(define-constant ERR-ENTER-NEW-WALLET (err u501))
(define-constant ERR-INVALID-DISTRIBUTION (err u505))
(define-constant ERR-INVALID-PERCENTAGE (err u601))
(define-constant ERR-STX-LIMIT-EXCEEDED (err u504))
(define-constant HUNDRED-PERCENT u10000)
;; Max STX amounts for hearts/gems
(define-constant MAX-STX-HEARTS u4000000)
(define-constant MAX-STX-GEMS u1000000)
;; ===========================================
;; Public Variables - All Using 10000 Scaling
;; ===========================================
;; Default: 80% progressive, 20% kryptomind
(define-data-var percentage-progressive uint u8000) ;; 80.00%
(define-data-var percentage-kryptomind uint u2000) ;; 20.00%
;; ==========================
;; Public Wallet Variables
;; ==========================
(define-data-var KRYPTOMIND principal 'SP2RVTWWBB5KYFY2F0G4V054FETC6R5Q12ZCZ6QCC)
(define-data-var PROGRESSIVE_WALLET principal 'SP2HYW9F9YXEE8ACZ7PE268VB7QME0JDJJVDPHFS5)
;; ==========================
;; Other Public Variables
;; ==========================
(define-data-var progressive-pool uint u0)
(define-data-var contract-owner principal tx-sender)
;; ==================
;; Maps
;; ==================
(define-map user-gems {user: principal} {gems: uint})
(define-map user-hearts {user: principal} {hearts: uint})
(define-map user-contest-inventory principal {hearts: uint, gems: uint})
;; ==========================================
;; Private Helper: Ownership Check
;; ==========================================
(define-private (check-is-owner)
(ok (asserts! (is-eq tx-sender (var-get contract-owner)) ERR-NOT-AUTHORIZED))
)
;; ==========================================
;; Setter Functions (Ownership Required)
;; ==========================================
(define-public (set-contract-owner (owner principal))
(begin
(try! (check-is-owner))
(asserts! (not (is-eq owner (var-get contract-owner))) ERR-ENTER-NEW-WALLET)
(var-set contract-owner owner)
(ok owner)
)
)
;; Set 2-way distribution: progressive + kryptomind must equal 100%
(define-public (set-primary-percentages (new-progressive uint) (new-kryptomind uint))
(begin
(try! (check-is-owner))
(asserts! (is-eq (+ new-progressive new-kryptomind) HUNDRED-PERCENT)
ERR-INVALID-DISTRIBUTION)
(asserts! (> new-progressive u0) ERR-INVALID-PERCENTAGE)
(asserts! (> new-kryptomind u0) ERR-INVALID-PERCENTAGE)
(var-set percentage-progressive new-progressive)
(var-set percentage-kryptomind new-kryptomind)
(ok { progressive: new-progressive, krypto: new-kryptomind })
)
)
(define-public (set-kryptomind-wallet (new-wallet principal))
(begin
(try! (check-is-owner))
(asserts! (not (is-eq new-wallet (var-get KRYPTOMIND))) ERR-ENTER-NEW-WALLET)
(var-set KRYPTOMIND new-wallet)
(ok new-wallet)
)
)
(define-public (set-progressive-wallet (new-wallet principal))
(begin
(try! (check-is-owner))
(asserts! (not (is-eq new-wallet (var-get PROGRESSIVE_WALLET))) ERR-ENTER-NEW-WALLET)
(var-set PROGRESSIVE_WALLET new-wallet)
(ok new-wallet)
)
)
;; ==========================
;; Getter Functions
;; ==========================
(define-read-only (get-kryptomind-wallet) (ok (var-get KRYPTOMIND)))
(define-read-only (get-progressive-wallet) (ok (var-get PROGRESSIVE_WALLET)))
(define-read-only (get-contract-owner) (ok (var-get contract-owner)))
(define-read-only (get-progressive-pool-balance) (var-get progressive-pool))
(define-read-only (get-percentage-progressive) (ok (var-get percentage-progressive)))
(define-read-only (get-percentage-kryptomind) (ok (var-get percentage-kryptomind)))
(define-read-only (get-user-contest-inventory (user principal))
(map-get? user-contest-inventory user))
(define-read-only (get-user-gems (user principal))
(ok (default-to {gems: u0} (map-get? user-gems {user: user}))))
(define-read-only (get-user-hearts (user principal))
(ok (default-to {hearts: u0} (map-get? user-hearts {user: user}))))
;; ========================================
;; Purchase Gems
;; Distribution:
;; 80% STX -> PROGRESSIVE_WALLET
;; 20% STX -> KRYPTOMIND
;; ========================================
(define-public (buy-gems (gems-count uint))
(begin
;; Validate gem bundles
(asserts!
(or (is-eq gems-count u5)
(is-eq gems-count u25)
(is-eq gems-count u50)
(is-eq gems-count u100))
INVALID-GEMS-COUNT)
;; Determine required STX
(let ((required-stx
(if (is-eq gems-count u5)
u200000
(if (is-eq gems-count u25)
u400000
(if (is-eq gems-count u50)
u700000
(if (is-eq gems-count u100)
u1000000
u0))))))
(asserts! (>= (stx-get-balance tx-sender) required-stx) INVALID-STX-BALANCE)
(asserts! (<= required-stx MAX-STX-GEMS) ERR-STX-LIMIT-EXCEEDED)
;; 80% progressive, 20% kryptomind
;; NOTE: share-krypto is computed as remainder to avoid rounding dust.
(let (
(share-progressive
(/ (* required-stx (var-get percentage-progressive)) HUNDRED-PERCENT))
(share-krypto
(- required-stx
(/ (* required-stx (var-get percentage-progressive)) HUNDRED-PERCENT)))
)
;; progressive stx
(unwrap! (stx-transfer? share-progressive tx-sender (var-get PROGRESSIVE_WALLET))
ERR-TRANSFER-PROGRESSIVE)
;; kryptomind stx
(unwrap! (stx-transfer? share-krypto tx-sender (var-get KRYPTOMIND))
ERR-TRANSFER-KRYPTOMIND)
;; update user gems
(map-set user-gems {user: tx-sender}
{gems: (+ (get gems (default-to {gems: u0}
(map-get? user-gems {user: tx-sender})))
gems-count)})
;; event
(let ((ev
{op: "buy-gems",
user: tx-sender,
gems-count: gems-count,
required-stx: required-stx,
progressive-share: share-progressive,
kryptomind-share: share-krypto}))
(print ev)
(ok ev)
)
)
)
)
)
;; ========================================
;; Purchase Hearts
;; Distribution:
;; 80% STX -> PROGRESSIVE_WALLET
;; 20% STX -> KRYPTOMIND
;; ========================================
(define-public (buy-hearts (heart-count uint))
(begin
(asserts!
(or (is-eq heart-count u3)
(is-eq heart-count u10)
(is-eq heart-count u25)
(is-eq heart-count u50))
INVALID-HEART-COUNT)
(let ((required-stx
(if (is-eq heart-count u3)
u1000000
(if (is-eq heart-count u10)
u2000000
(if (is-eq heart-count u25)
u3000000
(if (is-eq heart-count u50)
u4000000
u0))))))
(asserts! (>= (stx-get-balance tx-sender) required-stx) INVALID-STX-BALANCE)
(asserts! (<= required-stx MAX-STX-HEARTS) ERR-STX-LIMIT-EXCEEDED)
(let (
(share-progressive
(/ (* required-stx (var-get percentage-progressive)) HUNDRED-PERCENT))
(share-krypto
(- required-stx
(/ (* required-stx (var-get percentage-progressive)) HUNDRED-PERCENT)))
)
;; progressive stx
(unwrap! (stx-transfer? share-progressive tx-sender (var-get PROGRESSIVE_WALLET))
ERR-TRANSFER-PROGRESSIVE)
;; kryptomind stx
(unwrap! (stx-transfer? share-krypto tx-sender (var-get KRYPTOMIND))
ERR-TRANSFER-KRYPTOMIND)
;; update user hearts
(let ((old-hearts
(get hearts (default-to {hearts: u0}
(map-get? user-hearts {user: tx-sender})))))
(map-set user-hearts {user: tx-sender}
{hearts: (+ old-hearts heart-count)}))
;; event
(let ((ev
{op: "buy-hearts",
user: tx-sender,
heart-count: heart-count,
required-stx: required-stx,
progressive-share: share-progressive,
kryptomind-share: share-krypto}))
(print ev)
(ok ev)
)
)
)
)
)
;; ========================================
;; Enter Contest
;; - User pays fixed 0.5 STX (500000 microSTX) to Progressive Pool
;; - Awards: +75 gems, +5 hearts
;; - Also updates contest-inventory map
;; ========================================
(define-public (enter-contest)
(begin
(asserts! (>= (stx-get-balance tx-sender) u500000) INVALID-STX-BALANCE)
(unwrap! (stx-transfer? u500000 tx-sender (var-get PROGRESSIVE_WALLET))
ERR-TRANSFER-PROGRESSIVE)
(var-set progressive-pool (+ (var-get progressive-pool) u500000))
(let (
(old-gems
(get gems (default-to {gems: u0}
(map-get? user-gems {user: tx-sender}))))
(old-hearts
(get hearts (default-to {hearts: u0}
(map-get? user-hearts {user: tx-sender}))))
(old-contest
(default-to {hearts: u0, gems: u0}
(map-get? user-contest-inventory tx-sender)))
)
;; new totals
(map-set user-gems {user: tx-sender} {gems: (+ old-gems u75)})
(map-set user-hearts {user: tx-sender} {hearts: (+ old-hearts u5)})
;; also update the contest-inventory
(map-set user-contest-inventory tx-sender
{hearts: (+ (get hearts old-contest) u5),
gems: (+ (get gems old-contest) u75)})
(let ((ev
{op: "enter-contest",
user: tx-sender,
hearts-gained: u5,
gems-gained: u75,
total-pool: (var-get progressive-pool)}))
(print ev)
(ok ev)
)
)
)
)