From 95c8ac5bf4ecdffcf545088b6d1c73bc0753c295 Mon Sep 17 00:00:00 2001 From: mikera Date: Sat, 3 Feb 2024 16:08:45 +0000 Subject: [PATCH] Tests for boxes, tighten asset quantity checks --- convex-core/src/main/cvx/asset/box.cvx | 28 ++--- convex-core/src/main/cvx/asset/box/actor.cvx | 113 ++++++++---------- .../src/main/cvx/asset/multi-token.cvx | 14 ++- convex-core/src/main/cvx/asset/nft/basic.cvx | 45 +++---- convex-core/src/main/cvx/asset/nft/simple.cvx | 55 ++++----- convex-core/src/main/cvx/asset/share.cvx | 16 ++- .../src/main/cvx/asset/wrap/convex.cvx | 16 ++- convex-core/src/main/cvx/convex/asset.cvx | 5 +- convex-core/src/main/cvx/convex/fungible.cvx | 29 ++--- convex-core/src/main/cvx/torus/exchange.cvx | 17 ++- .../src/test/java/convex/lib/AssetTester.java | 14 ++- .../src/test/java/convex/lib/BoxTest.java | 70 +++++++++++ .../test/java/convex/lib/FungibleTest.java | 2 +- 13 files changed, 246 insertions(+), 178 deletions(-) create mode 100644 convex-core/src/test/java/convex/lib/BoxTest.java diff --git a/convex-core/src/main/cvx/asset/box.cvx b/convex-core/src/main/cvx/asset/box.cvx index 19f19c644..23bf3f4b7 100644 --- a/convex-core/src/main/cvx/asset/box.cvx +++ b/convex-core/src/main/cvx/asset/box.cvx @@ -11,9 +11,9 @@ ;;;;;;;;;; Setup - (import asset.box.actor :as box.actor) -(import convex.asset :as asset-lib) + +(import convex.asset :as asset-lib) ;;;;;;;;;; Public API @@ -40,29 +40,15 @@ (call actor (create)))) - - (defn insert ^{:doc {:description "Inserts an asset into a box." - :signature [{:params [box-id asset]} - {:params [actor box-id asset]}]}} - ([box-id asset] - (insert box.actor - box-id - asset)) - ([actor box-id asset] - (asset-lib/transfer actor - asset - box-id))) + :signature [{:params [box asset]}]}} + ([box asset] + (asset-lib/transfer box asset))) (defn remove ^{:doc {:description "Removes an asset from the given box." :signature [{:params [box-id]} {:params [actor box-id asset]}]}} - ([box-id asset] - (remove box.actor - box-id - asset)) - ([actor box-id asset] - (call actor - (remove box-id asset)))) + ([box asset] + (call box (remove asset)))) diff --git a/convex-core/src/main/cvx/asset/box/actor.cvx b/convex-core/src/main/cvx/asset/box/actor.cvx index 182e83831..33c9583c1 100644 --- a/convex-core/src/main/cvx/asset/box/actor.cvx +++ b/convex-core/src/main/cvx/asset/box/actor.cvx @@ -15,9 +15,8 @@ ^{:doc {:description "Map of `box id` -> `asset quantity`."}} {}) - (def counter - ^{:doc {:description "Used for creating box ids."}} + ^{:doc {:description "Count of boxes created, used for creating box ids."}} 0) (def offers @@ -30,28 +29,38 @@ ;;;;;;;;;; Private helpers +(defn -qc + ^{:doc {:description "Checks a box quantity."} + :private? true} + [q] + (cond (set? q) q ;; base case, quantity of boxes should always be a Set + (int? q) #{q} + (nil? q) #{} + (fail :ARGUMENT "Invalid box quantity"))) + (defn -direct-transfer ^{:private? true} - ;; Internal implementation for executing a direct transfer. + ;; Internal implementation for executing a direct transfer of box(es). [sender receiver quantity] - (let [receiver (address receiver) + (let [q (-qc quantity) + receiver (address receiver) sender-balance (get ownership sender #{}) - _ (assert (subset? quantity - sender-balance)) ;; TODO. Replace with `fail` for better error messages? + _ (or (subset? q sender-balance) + (fail :FUNDS "Cannot transfer box(es) not owned by sender.")) receiver-balance (get ownership receiver #{}) new-sender-balance (difference sender-balance - quantity) + q) new-receiver-balance (union receiver-balance - quantity)] + q)] (set! ownership (assoc ownership sender new-sender-balance receiver new-receiver-balance)) - quantity)) + q)) ;;;;;;;;;; Implementation of `convex.asset` interface @@ -59,51 +68,42 @@ ^{:callable? true :private? true} [sender quantity] - (let [sender (address sender) - sender-offers (get offers - sender - {}) - offer (or (get-in offers - [sender *caller*]) - #{}) - _ (assert (subset? quantity - offer)) + (let [q (-qc quantity) + sender (address sender) + sender-offers (get offers sender {}) + offer (get-in offers [sender *caller*] #{}) + _ (or (subset? q offer) (fail :STATE "Insufficent offer of box(es)")) receiver-balance (get ownership *caller* #{}) - new-offer (difference offer - quantity)] + new-offer (difference offer q)] (set! offers (assoc offers sender (assoc sender-offers *caller* new-offer))) - (-direct-transfer sender - *caller* - quantity))) + (-direct-transfer sender *caller* q))) (defn balance ^{:callable? true :private? true} [owner] - (or (get ownership - owner) + (or (get ownership owner) #{})) (defn direct-transfer ^{:callable? true :private? true} [receiver quantity] - (-direct-transfer *caller* - receiver - quantity)) + (-direct-transfer *caller* receiver quantity)) (defn offer ^{:callable? true :private? true} [receiver quantity] - (let [caller-offers (get offers + (let [q (-qc quantity) + caller-offers (get offers *caller* {})] (set! offers @@ -111,22 +111,20 @@ *caller* (assoc caller-offers receiver - quantity))))) + q))))) (defn receive-asset ^{:callable? true :private? true} - [asset box-id] - (let [box-id (long box-id)] - ;; Accepting first solves the problem of putting a box into itself. - ;; - (asset-lib/accept *caller* - asset) + [path quantity _] + (let [box-id (int *scope*)] + ;; NOTE: Accepting first solves the problem of putting a box into itself. + (asset-lib/accept *caller* path quantity) + (cond (not (contains-key? boxes box-id)) - (fail :STATE - "Target box does not exist") + (fail :STATE "Target box does not exist") (not (contains-key? (get ownership *caller*) @@ -136,9 +134,8 @@ (set! boxes (assoc boxes box-id - (asset-lib/quantity-add (get boxes - box-id) - asset))))) + (asset-lib/quantity-add (get boxes box-id) + [path quantity]))))) (def quantity-add ^{:callable? true @@ -186,17 +183,12 @@ (defn create - ^{:callable? true :private? true} - [] - (let [id counter owner *caller* - owned-boxes (or (get ownership - owner) - #{})] + owned-boxes (or (get ownership owner) #{})] (set! ownership (assoc ownership owner @@ -206,34 +198,27 @@ (assoc boxes id {})) ;; New box contains no assets - (set! counter - (inc counter)) - id)) - + (set! counter (inc counter)) + [~*address* id])) (defn remove - ^{:callable? true :private? true} - - [box-id asset] - - (let [current-asset (get boxes - box-id)] - (when-not (asset-lib/quantity-contains? current-asset - asset) + [asset] + (let [id *scope* + current-asset (get boxes id)] + (when-not (asset-lib/quantity-contains? current-asset asset) (fail "Box does not contain quantity of asset specified for removal")) (when-not (contains-key? (ownership *caller*) - box-id) + id) (fail :TRUST - (str "Box not owned: " box-id))) + (str "Box not owned: " id))) (set! boxes (assoc boxes - box-id + id (asset-lib/quantity-sub current-asset asset))) ;; Delivers the asset to the caller. ;; - (asset-lib/transfer *caller* - asset))) + (asset-lib/transfer *caller* asset))) diff --git a/convex-core/src/main/cvx/asset/multi-token.cvx b/convex-core/src/main/cvx/asset/multi-token.cvx index 47aef0a68..2a096afa6 100644 --- a/convex-core/src/main/cvx/asset/multi-token.cvx +++ b/convex-core/src/main/cvx/asset/multi-token.cvx @@ -22,6 +22,14 @@ ;;;;;;;;; Private functions +(defn -qc + ^{:doc {:description "Checks a token quantity."} + :private? true} + [q] + (cond (int? q) q ;; base case, quantity should always be an integer + (nil? q) 0 + (fail :ARGUMENT "Invalid token quantity"))) + (defn -set-balance [addr id bal] (let [h (get-holding addr) @@ -98,7 +106,7 @@ ^{:callable? true} [sender quantity] (let [id *scope* - quantity (int quantity) + quantity (-qc quantity) _ (cond (zero? quantity) (return 0) (< quantity 0) (fail :ARGUMENT "Negative accept amount")) @@ -134,7 +142,7 @@ ^{:callable? true} [receiver quantity] (let [id *scope* - quantity (cond (nil? quantity) 0 (int quantity)) + quantity (-qc quantity) receiver (address receiver) hs (get-holding *caller*) rec (get hs id)] @@ -159,7 +167,7 @@ (when-not (trust/trusted? controller *caller* :mint) (fail :TRUST "No rights to mint")) - (let [amount (int amount) ;; Mint amount. + (let [amount (-qc amount) ;; Mint amount. new-supply (+ supply amount) bal (-get-balance *caller* id) new-bal (+ bal amount)] diff --git a/convex-core/src/main/cvx/asset/nft/basic.cvx b/convex-core/src/main/cvx/asset/nft/basic.cvx index 677948793..2f60e8530 100644 --- a/convex-core/src/main/cvx/asset/nft/basic.cvx +++ b/convex-core/src/main/cvx/asset/nft/basic.cvx @@ -14,7 +14,6 @@ ^{:doc {:description "Used for creating NFT ids."}} 0) - (def offers ^{:doc {:description "Map of `owner` -> map of `recipient address` -> `set of NFT ids`"}} {}) @@ -23,28 +22,33 @@ ^{:doc {:description "Map of ID -> NFT metadata. May be nil for no metadata"}} {}) - ;;;;;;;;;; Implementation of `convex.asset` interface +(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 [receiver (address receiver) + (let [q (-qc quantity) + receiver (address receiver) sender-balance (or (get-holding sender) #{}) - _ (assert (subset? quantity - sender-balance)) + _ (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 - quantity) - new-receiver-balance (union receiver-balance - quantity)] - (set-holding sender - new-sender-balance) - (set-holding receiver - new-receiver-balance)) + 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) @@ -52,7 +56,8 @@ ^{:callable? true :private? true} [sender quantity] - (let [sender (address sender) + (let [q (-qc quantity) + sender (address sender) sender-offers (or (get offers sender) {}) @@ -60,12 +65,11 @@ [sender *caller*]) #{}) - _ (assert (subset? quantity - offer)) + _ (or (subset? q offer) + (fail :STATE "Insuffient NFT offer to accept")) receiver-balance (or (get-holding *caller*) #{}) - new-offer (difference offer - quantity)] + new-offer (difference offer q)] (set! offers (assoc offers @@ -95,13 +99,14 @@ (defn offer ^{:callable? true} [receiver quantity] - (let [caller-offers (get offers *caller* {})] + (let [q (-qc quantity) + caller-offers (get offers *caller* {})] (set! offers (assoc offers *caller* (assoc caller-offers receiver - quantity))))) + q))))) (def quantity-add diff --git a/convex-core/src/main/cvx/asset/nft/simple.cvx b/convex-core/src/main/cvx/asset/nft/simple.cvx index cc9acbafb..147e78b1e 100644 --- a/convex-core/src/main/cvx/asset/nft/simple.cvx +++ b/convex-core/src/main/cvx/asset/nft/simple.cvx @@ -24,22 +24,29 @@ ;;;;;;;;;; Implementation of `convex.asset` interface +(defn -qc + ^{:doc {:description "Checks a 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 [receiver (address receiver) + (let [q (-qc quantity) + receiver (address receiver) sender-balance (or (get-holding sender) #{}) - _ (assert (subset? quantity - sender-balance)) + _ (or (subset? q sender-balance) + (fail :FUNDS "Insufficient NFT balance")) receiver-balance (or (get-holding receiver) #{}) - new-sender-balance (difference sender-balance - quantity) - new-receiver-balance (union receiver-balance - quantity)] + new-sender-balance (difference sender-balance q) + new-receiver-balance (union receiver-balance q)] (set-holding sender new-sender-balance) (set-holding receiver @@ -51,20 +58,17 @@ ^{:callable? true :private? true} [sender quantity] - (let [sender (address sender) + (let [q (-qc quantity) + sender (address sender) sender-offers (or (get offers sender) {}) - offer (or (get-in offers - [sender - *caller*]) - #{}) - _ (assert (subset? quantity - offer)) + offer (get-in offers [sender *caller*] #{}) + _ (or (subset? q offer) + (fail :STATE "Insufficient offer to accept")) receiver-balance (or (get-holding *caller*) #{}) - new-offer (difference offer - quantity)] + new-offer (difference offer q)] (set! offers (assoc offers @@ -73,9 +77,7 @@ *caller* new-offer))) - (-direct-transfer sender - *caller* - quantity))) + (-direct-transfer sender *caller* q))) (defn balance @@ -95,13 +97,12 @@ (defn offer ^{:callable? true} [receiver quantity] - (let [caller-offers (get offers *caller* {})] + (let [q (-qc quantity) + caller-offers (get offers *caller* {})] (set! offers (assoc offers *caller* - (assoc caller-offers - receiver - quantity))))) + (assoc caller-offers receiver q))))) (def quantity-add @@ -125,14 +126,10 @@ :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))] + nft-set (-qc nft-set)] (when-not (subset? nft-set owned-nfts) - (fail :TRUST - "Can only burn owned NFTs")) + (fail :TRUST "Can only burn owned NFTs")) (set-holding *caller* (difference owned-nfts nft-set)) diff --git a/convex-core/src/main/cvx/asset/share.cvx b/convex-core/src/main/cvx/asset/share.cvx index b6f22d28e..9c9835569 100644 --- a/convex-core/src/main/cvx/asset/share.cvx +++ b/convex-core/src/main/cvx/asset/share.cvx @@ -33,6 +33,14 @@ ;;;;;;;;; Private functions +(defn -qc + ^{:doc {:description "Quantity check."} + :private? true} + [q] + (cond (int? q) q ;; base case, quantity should always be an integer + (nil? q) 0 + (fail :ARGUMENT "Invalid token quantity"))) + (defn -set-balance [addr id bal] (let [h (get-holding addr) @@ -83,9 +91,7 @@ ^{:callable? true} [addr amount] (let [addr (address addr) - amount (if amount - (int amount) - 0) + amount (-qc amount) id *scope* bal (-get-balance *caller* id) tbal (-get-balance addr id)] @@ -136,7 +142,7 @@ ^{:callable? true} [sender quantity] (let [id *scope* - quantity (int quantity) + quantity (-qc quantity) _ (cond (zero? quantity) (return 0) (< quantity 0) (fail "Negative accept amount")) @@ -171,7 +177,7 @@ ^{:callable? true} [receiver quantity] (let [id *scope* - quantity (cond (nil? quantity) 0 (int quantity)) + quantity (-qc quantity) receiver (address receiver) hs (get-holding *caller*) rec (get hs id)] diff --git a/convex-core/src/main/cvx/asset/wrap/convex.cvx b/convex-core/src/main/cvx/asset/wrap/convex.cvx index cb28eac0a..450275ee9 100644 --- a/convex-core/src/main/cvx/asset/wrap/convex.cvx +++ b/convex-core/src/main/cvx/asset/wrap/convex.cvx @@ -24,15 +24,21 @@ (let [rec (get-holding addr)] (or (get rec 0) 0)))) +(defn -qc + ^{:doc {:description "Quantity check."} + :private? true} + [q] + (cond (int? q) q ;; base case, quantity should always be an integer + (nil? q) 0 + (fail :ARGUMENT "Invalid token quantity"))) + ;; Transfer (defn direct-transfer ^{:callable? true} [addr amount] (let [addr (address addr) - amount (if amount - (int amount) - 0) + amount (-qc amount) bal (-get-balance *caller*) tbal (-get-balance addr)] ;; Amount must be in valid range. @@ -84,7 +90,7 @@ (defn offer ^{:callable? true} [receiver quantity] - (let [quantity (cond (nil? quantity) 0 (int quantity)) + (let [quantity (-qc quantity) receiver (address receiver) rec (get-holding *caller*)] (if rec @@ -101,7 +107,7 @@ (defn accept ^{:callable? true} [sender quantity] - (let [quantity (int quantity) + (let [quantity (-qc quantity) _ (cond (zero? quantity) (return 0) ;; trivial accept (< quantity 0) (fail :ARGUMENT "Negative accept amount")) diff --git a/convex-core/src/main/cvx/convex/asset.cvx b/convex-core/src/main/cvx/convex/asset.cvx index be1db074d..f5870af70 100644 --- a/convex-core/src/main/cvx/convex/asset.cvx +++ b/convex-core/src/main/cvx/convex/asset.cvx @@ -159,8 +159,7 @@ (receive-asset path quantity data))) ;; An actor without a receive-asset function is not a valid receiver? - (actor? receiver) - (fail :STATE "Target Actor does not have receive-asset function") + (actor? receiver) (fail :STATE "Target Actor does not have receive-asset function") (call path (direct-transfer receiver quantity))))) @@ -233,7 +232,7 @@ (map? asset) (reduce (fn [result [asset-path quantity]] - (if (owns? owner asset-path-quantity) + (if (owns? owner asset-path quantity) true (reduced false))) true diff --git a/convex-core/src/main/cvx/convex/fungible.cvx b/convex-core/src/main/cvx/convex/fungible.cvx index 0857d7f29..c188a3e12 100644 --- a/convex-core/src/main/cvx/convex/fungible.cvx +++ b/convex-core/src/main/cvx/convex/fungible.cvx @@ -95,8 +95,12 @@ *address*)] `(do - (def supply - ~supply) + (defn -qc [q] + (cond (int? q) q ;; base case, quantity should always be an integer + (nil? q) 0 + (fail :ARGUMENT "Invalid quantity"))) + + (def supply (-qc ~supply)) (set-holding ~initial-holder ~supply) @@ -111,26 +115,19 @@ ^{:callable? true} [sender quantity] (let [sender (address sender) - quantity (if quantity - (int quantity) - 0) + quantity (-qc quantity) om (get offers sender) ;; if this is nil then OK, behaves as empty map sendbal (or (get-holding sender) 0) - offer (or (get om - *caller*) - 0)] + offer (get om *caller* 0)] (cond - (< quantity - 0) + (< quantity 0) (fail "Can't accept a negative quantity of fungible tokens.") - (< offer - quantity) + (< offer quantity) (fail :STATE "Offer is insufficient") - (< sendbal - quantity) + (< sendbal quantity) (fail :FUNDS "Sender token balance is insufficient") (let [new-offer (- offer @@ -204,9 +201,7 @@ ^{:callable? true} [receiver quantity] (let [receiver (address receiver) - quantity (if quantity - (int quantity) - 0) + quantity (-qc quantity) om (get offers *caller*)] (if (<= quantity diff --git a/convex-core/src/main/cvx/torus/exchange.cvx b/convex-core/src/main/cvx/torus/exchange.cvx index 1a8181cb4..393807537 100644 --- a/convex-core/src/main/cvx/torus/exchange.cvx +++ b/convex-core/src/main/cvx/torus/exchange.cvx @@ -45,17 +45,23 @@ (import convex.core :as core) (import convex.fungible :as fungible) - (def token ~token) (def torus ~torus) (def token-balance 0) - + + (defn -qc + ^{:doc {:description "Quantity check."} + :private? true} + [q] + (cond (int? q) q ;; base case, quantity should always be an integer + (nil? q) 0 + (fail :ARGUMENT "Invalid token quantity"))) (defn add-liquidity ^{:callable? true} [amount] (let [;; Amount of tokens deposited. - amount (int amount) + amount (-qc amount) ;; Price of token in CVX (double), nil if no current liquidity. price (price) @@ -292,10 +298,9 @@ ^{:callable? true} [shares] (let [;; Amount of shares to withdraw. - shares (int shares) + shares (-qc shares) ;; Shares of holder. - own-holding (or (get-holding *caller*) - 0) + own-holding (or (get-holding *caller*) 0) _ (assert (<= 0 shares own-holding)) diff --git a/convex-core/src/test/java/convex/lib/AssetTester.java b/convex-core/src/test/java/convex/lib/AssetTester.java index 51d267a8e..c9472021c 100644 --- a/convex-core/src/test/java/convex/lib/AssetTester.java +++ b/convex-core/src/test/java/convex/lib/AssetTester.java @@ -137,8 +137,8 @@ public static void doFungibleTests(Context ctx, ACell token, Address user) { assertCVMEquals(0, eval(ctx, "(do (asset/offer *address* [token nil]) (asset/get-offer token *address* *address*))")); - // Non-integer offer is a cast error - assertCastError(step(ctx, "(asset/offer *address* [token :foo])")); + // Non-integer offer is an ARGUMENT error + assertArgumentError(step(ctx, "(asset/offer *address* [token :foo])")); // Run generic asset tests, giving 1/3 the balance to a new user account { @@ -206,14 +206,20 @@ public static void doAssetTests(Context ctx, ACell asset, Address user1, Address ctx = step(ctx, "(def bal1 (asset/balance token user1))"); ACell balance1 = ctx.getResult(); assertNotNull(balance1); - assertNotEquals(empty, balance1); + assertNotEquals(empty, balance1,"User 1 should not have an empty balance"); ctx = step(ctx, "(def bal2 (asset/balance token user2))"); ACell balance2 = ctx.getResult(); assertNotNull(balance2); - assertNotEquals(empty, balance2); + assertNotEquals(empty, balance2,"User 2 should not have an empty balance"); ACell total = eval(ctx, "(asset/quantity-add token bal1 bal2)"); assertNotNull(total); assertNotEquals(empty, total); + + // Trying to accept everything should be a STATE error (insufficient offer) + assertStateError(step(ctx,"(asset/accept user1 token "+total+")")); + + // Trying to offer an invalid quantity should fail with ARGUMENT + assertArgumentError(step(ctx,"(asset/offer user1 token :foobar)")); // Tests for each user doUserAssetTests(ctx, asset, user1, balance1); diff --git a/convex-core/src/test/java/convex/lib/BoxTest.java b/convex-core/src/test/java/convex/lib/BoxTest.java new file mode 100644 index 000000000..dfe6b381b --- /dev/null +++ b/convex-core/src/test/java/convex/lib/BoxTest.java @@ -0,0 +1,70 @@ +package convex.lib; + +import static convex.test.Assertions.assertNotError; +import static convex.test.Assertions.assertStateError; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +import convex.core.data.ASet; +import convex.core.data.AVector; +import convex.core.data.Address; +import convex.core.data.Sets; +import convex.core.data.prim.CVMLong; +import convex.core.lang.ACVMTest; +import convex.core.lang.Context; +import convex.core.lang.TestState; +import convex.test.Samples; + +public class BoxTest extends ACVMTest { + + Address BOX; + + @Override protected Context buildContext(Context ctx) { + ctx=TestState.CONTEXT.fork(); + + // Import basic NFTs + ctx=step(ctx,"(import asset.box :as box)"); + ctx=step(ctx,"(import asset.box.actor :as box.actor)"); + BOX=ctx.getResult(); + + ctx=step(ctx,"(import convex.asset :as asset)"); + return ctx; + } + + @Test public void testCreate() { + Context ctx=context(); + + // Create Basic NFT with map metadata via asset/create + ctx=step(ctx,"(def t1 (box/create))"); + AVector t1=ctx.getResult(); + assertEquals(BOX,t1.get(0)); + assertTrue(t1.get(1) instanceof CVMLong); + + assertStateError(step(ctx,"(box/insert t1 t1)")); + } + + @Test public void testAssetAPI() { + int NUM=5; + Context ctx=context(); + for (int i=0; i BAL=(ASet)eval(ctx,"(asset/balance box.actor)"); + assertEquals(NUM,BAL.count()); + + // Test balance of non-holder + assertSame(Sets.empty(),eval(ctx,"(asset/balance box.actor #0)")); + + // Create test Users + ctx=ctx.createAccount(Samples.KEY_PAIR.getAccountKey()); + Address user2=(Address) ctx.getResult(); + + ctx=step(ctx,"(asset/transfer "+user2+" ["+BOX+" #{"+BAL.get(0)+"}])"); + assertNotError(ctx); + + AssetTester.doAssetTests(ctx, BOX, ctx.getAddress(), user2); + } +} diff --git a/convex-core/src/test/java/convex/lib/FungibleTest.java b/convex-core/src/test/java/convex/lib/FungibleTest.java index f0bcbae01..5448d5c10 100644 --- a/convex-core/src/test/java/convex/lib/FungibleTest.java +++ b/convex-core/src/test/java/convex/lib/FungibleTest.java @@ -92,7 +92,7 @@ private static State buildState() { // nil should be seen as zero offer assertCVMEquals(0,eval(ctx,"(do (asset/offer VILLAIN [token nil]) (asset/get-offer token *address* VILLAIN))")); - assertCastError(step(ctx,"(asset/offer VILLAIN [token :foo])")); + assertArgumentError(step(ctx,"(asset/offer VILLAIN [token :foo])")); } @Test public void testBuildToken() {