add-mint | (fn [config] (let [max-supply (int (get %0 :max-supply 0)) minter (cond (:minter %0) *result* *address*) ] (cond (<= 0 %1) *result* (fail "Max supply must be non-negative")) (list do (import convex.trust :as trust) (declare balance transfer) (list def minter %2) (cond %1 (list def max-supply %1)) (defn burn ^{:callable true} [amount] (when-not ((lookup trust trusted?) minter *caller* :burn) (fail :TRUST "No rights to burn")) (let [amount (int amount) bal (balance *caller*)] (cond (< amount 0) (fail :ARGUMENT "Cannot burn negative quantity")) (cond (> amount bal) (fail :FUNDS "Burn amount not available")) (let [new-supply (- supply amount)] (log "MINT" *caller* (- amount) new-supply) (set-holding *caller* (- bal amount)) (set! supply new-supply)))) (list defn mint ^{:callable true} [amount] (when-not ((lookup trust trusted?) minter *caller* :mint amount) (fail :TRUST "No rights to mint")) (list let [amount (int amount) new-supply (+ supply amount) bal (balance *caller*) new-bal (+ bal amount)] (cond %1 (when-not (<= 0 new-supply max-supply) (fail :STATE "Mint exceeds max supply"))) (log "MINT" *caller* amount new-supply) (set-holding *caller* new-bal) (set! supply new-supply)))))) | ["Creates deployable code that, when added to actor code from `build-token`, allows priviledged accounts to mint and burn tokens." "Configuration map contains:" "- `:max-supply`, a long designating the maximum mintable supply (defaults to unlimited)" "- `:minter`, Trust Monitor from `convex.trust` (defaults to *address*)"] |
mint | (fn [token amount] (call* %0 0 mint %1)) | "Mints an amount of tokens for the given token. User must have minting privileges. Amount may be negative to burn fungible tokens." |
transfer | (fn ([token target amount] (recur %0 %1 %2 nil)) ([token target amount data] (cond (callable? %1 receive-asset) (let [amount (int %2) ] (#64/offer %1 %0 %4) (call* %1 0 receive-asset %0 %4 nil)) (#8/actor? %1) (fail :STATE "Target Actor does not have receive-asset function") (call* %0 0 direct-transfer %1 %2 %3)))) | "Transfers balance of a fungible token." |
decimals | (fn [token] (query (try (call* %0 0 decimals) 0))) | "Gets the number of decimal digits for a token." |
total-supply | (fn [token] (query (try (call* %0 0 total-supply) nil))) | "Gets the total supply of a fungible token. i.e. the sum of all balances. May return nil if not supported" |
balance | (fn ([token] (recur %0 *address*)) ([token holder] (query (call* %0 0 balance %1)))) | "Gets the balance from a fungible token. Checks the balance for the specified holder, or the current *address* if not specified." |
burn | (fn [token amount] (call* %0 0 burn %1)) | "Burns an amount of tokens for the given token, if allowed by the implementation. Amount must be non-negative and no greater than the caller's balance." |
build-token | (fn [config] (let [supply (int (cond (:supply %0) *result* 0)) decimals (int (cond (:decimals %0) *result* 0)) initial-holder (address (cond (:initial-holder %0) *result* *address*)) ] (list do (defn -qc [q] (cond (int? q) q (nil? q) 0 (fail :ARGUMENT "Invalid quantity"))) (list def supply (list -qc %1)) (list set-holding %3 %1) (def offers {}) (defn accept ^{:callable true} [sender quantity] (let [sender (address sender) quantity (-qc quantity) om (get offers sender) sendbal (or (get-holding sender) 0) offer (get om *caller* 0)] (cond (< quantity 0) (fail "Can't accept a negative quantity of fungible tokens.") (< offer quantity) (fail :STATE "Offer is insufficient") (< sendbal quantity) (fail :FUNDS "Sender token balance is insufficient") (let [new-offer (- offer quantity)] (def offers (assoc offers sender (if (> new-offer 0) (assoc om *caller* new-offer) (dissoc om *caller*)))) (set-holding sender (- sendbal quantity)) (set-holding *caller* (+ (or (get-holding *caller*) 0) quantity)) quantity)))) (defn balance ^{:callable true} [addr] (or (get-holding addr) 0)) (defn check-transfer ^{:callable true} [_sender _receiver _quantity] nil) (list defn decimals ^{:callable true} [] %2) (defn total-supply ^{:callable true} [] supply) (list defn direct-transfer ^{:callable true} [addr amount data] (list let [addr (address addr) amount (-qc amount) bal (or (get-holding *caller*) 0) tbal (or (get-holding addr) 0)] (cond (:checked? %0) (if-let [f (check-transfer *caller* addr amount)] (fail :BLOCK f))) (cond (< amount 0) (fail :ARGUMENT "negative transfer")) (cond (> amount bal) (fail :FUNDS "insufficent token balance")) (when (= *caller* addr) (log "TR" *caller* addr amount bal bal data) (return amount)) (let [nsb (- bal amount) nrb (+ tbal amount)] (log "TR" *caller* addr amount nsb nrb data) (set-holding *caller* nsb) (set-holding addr nrb)))) (defn get-offer ^{:callable true} [sender receiver] (get-in offers [sender receiver] 0)) (defn offer ^{:callable true} [receiver quantity] (let [receiver (address receiver) quantity (-qc quantity)] (if (<= quantity 0) (set! offers (dissoc-in offers [*caller* receiver])) (set! offers (assoc-in offers [*caller* receiver] quantity))) quantity)) (defn quantity-add ^{:callable true} [a b] (let [a (cond a (int a) 0) b (cond b (int b) 0)] (+ a b))) (defn quantity-sub ^{:callable true} [a b] (let [a (cond a (int a) 0) b (cond b (int b) 0)] (if (> a b) (- a b) 0))) (defn quantity-subset? ^{:callable true} [a b] (<= (cond a (int a) 0) (cond b (int b) 0)))))) | ["Creates deployable code for a new fungible token which follows the interface described in `convex.asset`." "An optional config map can be provided:" "- `:initial-holder`, address which will hold the initial supply (defaults to `*address*`)" "- `:supply`, supply created and attributed to `:initial-holder` (Integer, defaults to 0)"] |