All Downloads are FREE. Search and download functionalities are using the official Maven repository.

convex.asset.nft.basic.cvx Maven / Gradle / Ivy

The newest version!
'asset.nft.basic

(call *registry*
      (register {:description ["Enables the creation of Basic NFTs."
                               "A Basic NFT is merely an ownable Integer ID with immutable arbitrary metadata."
                               "Follows the interface described in `convex.asset`."]
                 :name         "Basic NFT creation and management"}))

;;;;;;;;;; Values

(define counter
  ^{:doc {:description "Used for creating NFT ids."}}
  0)

(define offers
  ^{:doc {:description "Map of `owner` -> map of `recipient address` -> `set of NFT ids`"}}
  {})

(define meta
  ^{:doc {:description "Map of ID -> NFT metadata. May be nil for no metadata"}}
  {})

;;;;;;;;;; Implementation of `convex.asset` interface
;; These functions provide full CAD19 asset functionality
;;


(defn -qc
		  ^{:doc {:description "Checks a basic NFT quantity."}
		    :private? true}
		  [q]
		  (cond (set? q) q              ;; base case, quantity should always be a Set
				(int? q) #{q} 
		        (nil? q) #{}
		        (fail :ARGUMENT "Invalid NFT quantity")))

(defn -direct-transfer
  ^{:private? true}
  ;; Used internally by [[accept]] and [[direct-transfer]].
  [sender receiver quantity]
  (let [q (-qc quantity)
        receiver             (address receiver)
        sender-balance       (or (get-holding sender)
                                 #{})
        _                    (or (subset? q sender-balance)
        		                 (fail :FUNDS "Cannot transfer non-owned NFT(s)"))
        receiver-balance     (or (get-holding receiver)
                                 #{})
        new-sender-balance   (difference sender-balance q)
        new-receiver-balance (union receiver-balance q)]
    (set-holding sender new-sender-balance)
    (set-holding receiver new-receiver-balance))
    quantity)


(defn accept
  ^{:callable true}
  [sender quantity]
  (let [q                (-qc quantity)
        sender           (address sender)
        sender-offers    (or (get offers
                                  sender)
                             {})
        offer            (or (get-in offers
                                     [sender
                                      *caller*])
                             #{})
        _                (or (subset? q offer)
        		             (fail :STATE "Insuffient NFT offer to accept"))
        receiver-balance (or (get-holding *caller*)
                             #{})
        new-offer        (difference offer q)]

    (set! offers
       (assoc offers
              sender
              (assoc sender-offers
                     *caller*
                     new-offer)))

    (-direct-transfer sender
                      *caller*
                      quantity)))

(defn balance
  ^{:callable true
    :private?  true}
  [owner]
  (or (get-holding owner)
      #{}))

(defn direct-transfer
  ^{:callable true}
  [receiver quantity data]
  (-direct-transfer *caller*
                    receiver
                    quantity))

(defn offer
  ^{:callable true}
  [receiver quantity]
  (let [q             (-qc quantity)
        caller-offers (get offers *caller* {})]
    (set! offers
         (assoc offers
                *caller*
                (assoc caller-offers
                       receiver
                       q)))))


(def quantity-add
  ^{:callable true}
  union)

(def quantity-sub
  ^{:callable true}
  difference)

(def quantity-subset?
  ^{:callable true}
  subset?)

;;;;;;;;;; Callable functions


(defn burn
  ^{:callable true
    :doc       {:description "Destroys a set of NFTs. NFTs must be owned by the caller."
                :signature   [{:params [nft-set]}]}}
  [nft-set]
  (let [owned-nfts (get-holding *caller*)
        nft-set    (cond
                     (int? nft-set) #{nft-set}
                     (set? nft-set)  nft-set
                     :else           (set nft-set))]
    (when-not (subset? nft-set
                       owned-nfts)
      (fail :TRUST
            "Can only burn owned NFTs"))
    (set-holding *caller*
                 (difference owned-nfts
                             nft-set))
    ;; Remove metadata if it is there
    (set! meta (reduce dissoc meta nft-set))
    nft-set))

(defn get-metadata 
  ^{:callable true
    :doc       {:description "Gets metadata for a given NFT ID."
                :signature   [{:params []}
                              {:params [id]}]}}
  ([] (recur *scope*))
  ([id] (get meta id)))

(defn create
  ^{:callable true
    :doc       {:description "Creates a new NFT with a fresh ID."
                :signature   [{:params []}
       {:params [metadata]}]}}
  ([] (recur nil))
  ([metadata]
    (let [id         counter
          owner      *caller*
          owned-nfts (or (get-holding owner)
                       #{})]
      (set-holding owner
        (conj owned-nfts
          id))
      (or (nil? metadata)
        (def meta (assoc meta id metadata)))
      (set! counter
        (inc counter))
      id)))




© 2015 - 2024 Weber Informatics LLC | Privacy Policy