Source Code

;; ============================================
;; TRAIT TOKEN - Tradeable Personality Traits
;; SIP-013 Semi-Fungible Tokens
;; Clarity 4 Smart Contract
;; ============================================

(impl-trait .sip013-trait.sip013-trait)

(define-constant ERR_NOT_FOUND (err u404))

(define-constant TRAIT-FIRE u1)
(define-constant TRAIT-WATER u2)
(define-constant TRAIT-EARTH u3)
(define-constant TRAIT-AIR u4)
(define-constant TRAIT-ETHER u5)
(define-constant TRAIT-YANG u6)
(define-constant TRAIT-YIN u7)
(define-constant TRAIT-POWER-BOOST u8)

(define-constant ELEMENTS (list "Fire" "Water" "Earth" "Air" "Ether"))
(define-constant ENERGIES (list "Yang" "Yin" "Neutral"))

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

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

(define-read-only (get-total-supply (token-id uint))
  (ok (default-to u0 (map-get? token-supplies token-id)))
)

(define-read-only (get-decimals (token-id uint))
  (begin
    token-id ;; silence unused warning
    (ok u0)
  )
)

(define-read-only (get-token-uri (token-id uint) )
  (begin
    token-id ;; silence unused warning
    (ok none)
  )
)

(define-public (transfer (token-id uint) (amount uint) (sender principal) (recipient principal))
  (let ((sender-balance (default-to u0 (map-get? balances { owner: sender, token-id: token-id }))))
    (asserts! (is-eq tx-sender sender) (err u401))
    (asserts! (>= sender-balance amount) (err u402))
    (map-set balances { owner: sender, token-id: token-id } (- sender-balance amount))
    (map-set balances { owner: recipient, token-id: token-id }
      (+ (default-to u0 (map-get? balances { owner: recipient, token-id: token-id })) amount))
    (ok true)
  )
)

(define-public (claim-traits (bh uint))
  (let
    (
      (block-info (unwrap! (get-burn-block-info? header-hash bh) ERR_NOT_FOUND))
      (slice1 (unwrap! (slice? block-info u0 u16) ERR_NOT_FOUND))
      (slice2 (unwrap! (slice? block-info u16 u32) ERR_NOT_FOUND))
      (hash-val-1 (buff-to-uint-be (unwrap! (as-max-len? slice1 u16) ERR_NOT_FOUND)))
      (hash-val-2 (buff-to-uint-be (unwrap! (as-max-len? slice2 u16) ERR_NOT_FOUND)))
      (element-index (mod hash-val-1 u5))
      (energy-index (mod hash-val-2 u3))
      (power-number (+ u1 (mod hash-val-1 u9)))
      (element (unwrap! (element-at? ELEMENTS element-index) ERR_NOT_FOUND))
      (energy (unwrap! (element-at? ENERGIES energy-index) ERR_NOT_FOUND))
      (element-token (get-element-token-id element))
      (energy-token (get-energy-token-id energy))
    )
    (unwrap-panic (mint-internal element-token u1 tx-sender))
    (unwrap-panic (mint-internal energy-token u1 tx-sender))
    (if (>= power-number u7)
      (unwrap-panic (mint-internal TRAIT-POWER-BOOST u1 tx-sender))
      true
    )
    (ok true)
  )
)

(define-private (mint-internal (token-id uint) (amount uint) (recipient principal))
  (begin
    (map-set balances { owner: recipient, token-id: token-id }
      (+ (default-to u0 (map-get? balances { owner: recipient, token-id: token-id })) amount))
    (map-set token-supplies token-id
      (+ (default-to u0 (map-get? token-supplies token-id)) amount))
    (ok true)
  )
)

(define-read-only (get-element-token-id (element (string-ascii 10)))
  (if (is-eq element "Fire") TRAIT-FIRE
    (if (is-eq element "Water") TRAIT-WATER
      (if (is-eq element "Earth") TRAIT-EARTH
        (if (is-eq element "Air") TRAIT-AIR
          TRAIT-ETHER
        )
      )
    )
  )
)

(define-read-only (get-energy-token-id (energy (string-ascii 10)))
  (if (is-eq energy "Yang") TRAIT-YANG TRAIT-YIN)
)

(define-read-only (get-trait-name (token-id uint))
  (if (is-eq token-id TRAIT-FIRE) "Fire Element"
    (if (is-eq token-id TRAIT-WATER) "Water Element"
      (if (is-eq token-id TRAIT-EARTH) "Earth Element"
        (if (is-eq token-id TRAIT-AIR) "Air Element"
          (if (is-eq token-id TRAIT-ETHER) "Ether Element"
            (if (is-eq token-id TRAIT-YANG) "Yang Energy"
              (if (is-eq token-id TRAIT-YIN) "Yin Energy"
                (if (is-eq token-id TRAIT-POWER-BOOST) "Power Boost"
                  "Unknown"
                )
              )
            )
          )
        )
      )
    )
  )
)

Functions (9)

FunctionAccessArgs
get-balanceread-onlytoken-id: uint, owner: principal
get-total-supplyread-onlytoken-id: uint
get-decimalsread-onlytoken-id: uint
transferpublictoken-id: uint, amount: uint, sender: principal, recipient: principal
claim-traitspublicbh: uint
mint-internalprivatetoken-id: uint, amount: uint, recipient: principal
get-element-token-idread-onlyelement: (string-ascii 10
get-energy-token-idread-onlyenergy: (string-ascii 10
get-trait-nameread-onlytoken-id: uint