convex.asset.nft.basic.cvx Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of convex-core Show documentation
Show all versions of convex-core Show documentation
Convex core libraries and common utilities
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)))