Răsfoiți Sursa

contract/money: Use simplified harness API for tests

x 5 luni în urmă
părinte
comite
348ea7fff1

+ 32 - 66
src/contract/money/tests/genesis_mint.rs

@@ -34,84 +34,50 @@ fn genesis_mint() -> Result<()> {
     smol::block_on(async {
         init_logger();
 
-        // Holders this test will use
-        const HOLDERS: [Holder; 2] = [Holder::Alice, Holder::Bob];
+        init_logger();
+
+        use Holder::{Alice, Bob};
 
-        // Some numbers we want to assert
-        const ALICE_INITIAL: [u64; 1] = [100];
-        const BOB_INITIAL: [u64; 2] = [100, 100];
+        const ALICE_INITIAL: u64 = 100;
+        const BOB_AMOUNTS: [u64; 2] = [100, 100];
 
-        // Block height to verify against
-        let current_block_height = 0;
+        let block_height = 0;
 
-        // Initialize harness
-        let mut th = TestHarness::new(&HOLDERS, false).await?;
+        let mut th = TestHarness::new(&[Alice, Bob], false).await?;
 
-        info!(target: "money", "[Alice] ========================");
-        info!(target: "money", "[Alice] Building genesis mint tx");
-        info!(target: "money", "[Alice] ========================");
-        let (genesis_mint_tx, genesis_mint_params) =
-            th.genesis_mint(&Holder::Alice, &ALICE_INITIAL, None, None).await?;
+        // Build Alice's genesis mint
+        info!(target: "money", "Building Alice genesis mint tx");
+        let (genesis_tx, genesis_params) =
+            th.genesis_mint(&Alice, &[ALICE_INITIAL], None, None).await?;
 
-        info!(target: "money", "[Malicious] =============================================");
-        info!(target: "money", "[Malicious] Checking genesis mint tx not on genesis block");
-        info!(target: "money", "[Malicious] =============================================");
+        // Malicious: verify genesis mint fails on non-genesis block
+        info!(target: "money", "Checking genesis mint tx not on genesis block");
         assert!(th
             .execute_genesis_mint_tx(
-                &Holder::Alice,
-                genesis_mint_tx.clone(),
-                &genesis_mint_params,
-                current_block_height + 1,
+                &Alice,
+                genesis_tx.clone(),
+                &genesis_params,
+                block_height + 1,
                 true,
             )
             .await
             .is_err());
 
-        for holder in &HOLDERS {
-            info!(target: "money", "[{holder:?}] ================================");
-            info!(target: "money", "[{holder:?}] Executing Alice genesis mint tx");
-            info!(target: "money", "[{holder:?}] ================================");
-            th.execute_genesis_mint_tx(
-                holder,
-                genesis_mint_tx.clone(),
-                &genesis_mint_params,
-                current_block_height,
-                true,
-            )
-            .await?;
-        }
-
-        th.assert_trees(&HOLDERS);
-
-        info!(target: "money", "[Bob] ========================");
-        info!(target: "money", "[Bob] Building genesis mint tx");
-        info!(target: "money", "[Bob] ========================");
-        let (genesis_mint_tx, genesis_mint_params) =
-            th.genesis_mint(&Holder::Bob, &BOB_INITIAL, None, None).await?;
-
-        for holder in &HOLDERS {
-            info!(target: "money", "[{holder:?}] =============================");
-            info!(target: "money", "[{holder:?}] Executing Bob genesis mint tx");
-            info!(target: "money", "[{holder:?}] =============================");
-            th.execute_genesis_mint_tx(
-                holder,
-                genesis_mint_tx.clone(),
-                &genesis_mint_params,
-                current_block_height,
-                true,
-            )
-            .await?;
-        }
-
-        th.assert_trees(&HOLDERS);
-
-        let alice_owncoins = &th.holders.get(&Holder::Alice).unwrap().unspent_money_coins;
-        let bob_owncoins = &th.holders.get(&Holder::Bob).unwrap().unspent_money_coins;
-        assert!(alice_owncoins.len() == 1);
-        assert!(alice_owncoins[0].note.value == ALICE_INITIAL[0]);
-        assert!(bob_owncoins.len() == 2);
-        assert!(bob_owncoins[0].note.value == BOB_INITIAL[0]);
-        assert!(bob_owncoins[1].note.value == BOB_INITIAL[1]);
+        // Execute on all holders
+        info!(target: "money", "Executing Alice genesis mint tx on all holders");
+        th.genesis_mint_to_all_with(genesis_tx, &genesis_params, block_height).await?;
+
+        // Build and execute Bob's genesis mint
+        info!(target: "money", "Building and executing Bob genesis mint tx");
+        let (genesis_tx, genesis_params) = th.genesis_mint(&Bob, &BOB_AMOUNTS, None, None).await?;
+        th.genesis_mint_to_all_with(genesis_tx, &genesis_params, block_height).await?;
+
+        // Assert final state
+        assert_eq!(th.coins(&Alice).len(), 1);
+        assert_eq!(th.coins(&Alice)[0].note.value, ALICE_INITIAL);
+        assert_eq!(th.coins(&Bob).len(), 2);
+        assert_eq!(th.coins(&Bob)[0].note.value, BOB_AMOUNTS[0]);
+        assert_eq!(th.coins(&Bob)[1].note.value, BOB_AMOUNTS[1]);
 
         // Thanks for reading
         Ok(())

+ 26 - 54
src/contract/money/tests/integration.rs

@@ -25,64 +25,36 @@ fn money_integration() -> Result<()> {
     smol::block_on(async {
         init_logger();
 
-        // Holders this test will use
-        const HOLDERS: [Holder; 2] = [Holder::Alice, Holder::Bob];
+        use Holder::{Alice, Bob};
 
-        // Initialize harness
-        let mut th = TestHarness::new(&HOLDERS, true).await?;
+        let mut th = TestHarness::new(&[Alice, Bob], true).await?;
 
-        // Generate two new blocks mined by Alice
-        th.generate_block(&Holder::Alice, &HOLDERS).await?;
-        th.generate_block(&Holder::Alice, &HOLDERS).await?;
-
-        // Generate two new blocks mined by Bob
-        th.generate_block(&Holder::Bob, &HOLDERS).await?;
-        th.generate_block(&Holder::Bob, &HOLDERS).await?;
+        // Mine 2 blocks each
+        th.generate_block_all(&Alice).await?;
+        th.generate_block_all(&Alice).await?;
+        th.generate_block_all(&Bob).await?;
+        th.generate_block_all(&Bob).await?;
 
         // Assert correct rewards
-        let alice_coins = &th.holders.get(&Holder::Alice).unwrap().unspent_money_coins;
-        let bob_coins = &th.holders.get(&Holder::Bob).unwrap().unspent_money_coins;
-        assert!(alice_coins.len() == 2);
-        assert!(bob_coins.len() == 2);
-        assert!(alice_coins[0].note.value == expected_reward(1));
-        assert!(alice_coins[1].note.value == expected_reward(2));
-        assert!(bob_coins[0].note.value == expected_reward(3));
-        assert!(bob_coins[1].note.value == expected_reward(4));
-
-        let current_block_height = 4;
-
-        // Alice transfers some tokens to Bob
-        let (tx, (xfer_params, fee_params), _spent_soins) = th
-            .transfer(
-                alice_coins[0].note.value,
-                &Holder::Alice,
-                &Holder::Bob,
-                &[alice_coins[0].clone()],
-                alice_coins[0].note.token_id,
-                current_block_height,
-                false,
-            )
-            .await?;
-
-        // Execute the transaction
-        for holder in &HOLDERS {
-            th.execute_transfer_tx(
-                holder,
-                tx.clone(),
-                &xfer_params,
-                &fee_params,
-                current_block_height,
-                true,
-            )
-            .await?;
-        }
-
-        // Assert coins in wallets
-        let alice_coins = &th.holders.get(&Holder::Alice).unwrap().unspent_money_coins;
-        let bob_coins = &th.holders.get(&Holder::Bob).unwrap().unspent_money_coins;
-        assert!(alice_coins.len() == 1); // Change from fee
-        assert!(bob_coins.len() == 3);
-        assert!(bob_coins[2].note.value == expected_reward(1));
+        assert_eq!(th.coins(&Alice).len(), 2);
+        assert_eq!(th.coins(&Bob).len(), 2);
+        assert_eq!(th.coins(&Alice)[0].note.value, expected_reward(1));
+        assert_eq!(th.coins(&Alice)[1].note.value, expected_reward(2));
+        assert_eq!(th.coins(&Bob)[0].note.value, expected_reward(3));
+        assert_eq!(th.coins(&Bob)[1].note.value, expected_reward(4));
+
+        let block_height = 4;
+        let native_token = th.coins(&Alice)[0].note.token_id;
+
+        // Alice transfers her first block reward to Bob
+        let transfer_amount = expected_reward(1);
+        th.transfer_to_all(transfer_amount, &Alice, &Bob, native_token, block_height).await?;
+
+        // Alice: 1 coin (fee change from reward(2))
+        // Bob:   3 coins (reward(3) + reward(4) + received reward(1))
+        assert_eq!(th.coins(&Alice).len(), 1);
+        assert_eq!(th.coins(&Bob).len(), 3);
+        assert_eq!(th.coins(&Bob)[2].note.value, transfer_amount);
 
         // Thanks for reading
         Ok(())

+ 60 - 388
src/contract/money/tests/mint_pay_swap.rs

@@ -29,8 +29,6 @@
 
 use darkfi::Result;
 use darkfi_contract_test_harness::{init_logger, Holder, TestHarness};
-use darkfi_sdk::crypto::BaseBlind;
-use rand::rngs::OsRng;
 use tracing::info;
 
 #[test]
@@ -38,395 +36,69 @@ fn mint_pay_swap() -> Result<()> {
     smol::block_on(async {
         init_logger();
 
-        // Holders this test will use
-        const HOLDERS: [Holder; 2] = [Holder::Alice, Holder::Bob];
+        use Holder::{Alice, Bob};
 
-        // Some numbers we want to assert
         const ALICE_INITIAL: u64 = 100;
         const BOB_INITIAL: u64 = 200;
-
-        // Alice = 50 ALICE
-        // Bob = 200 BOB + 50 ALICE
-        const ALICE_FIRST_SEND: u64 = ALICE_INITIAL - 50;
-        // Alice = 50 ALICE + 180 BOB
-        // Bob = 20 BOB + 50 ALICE
-        const BOB_FIRST_SEND: u64 = BOB_INITIAL - 20;
-
-        // Block height to verify against
-        let current_block_height = 0;
-
-        // Initialize harness
-        let mut th = TestHarness::new(&HOLDERS, false).await?;
-
-        info!(target: "money", "[Alice] ================================");
-        info!(target: "money", "[Alice] Building token mint tx for Alice");
-        info!(target: "money", "[Alice] ================================");
-        let alice_token_blind = BaseBlind::random(&mut OsRng);
-        let (mint_tx, mint_params, mint_auth_params, fee_params) = th
-            .token_mint(
-                ALICE_INITIAL,
-                &Holder::Alice,
-                &Holder::Alice,
-                alice_token_blind,
-                None,
-                None,
-                current_block_height,
-            )
-            .await?;
-
-        for holder in &HOLDERS {
-            info!(target: "money", "[{holder:?}] ==============================");
-            info!(target: "money", "[{holder:?}] Executing Alice token mint tx");
-            info!(target: "money", "[{holder:?}] ==============================");
-            th.execute_token_mint_tx(
-                holder,
-                mint_tx.clone(),
-                &mint_params,
-                &mint_auth_params,
-                &fee_params,
-                current_block_height,
-                true,
-            )
-            .await?;
-        }
-
-        th.assert_trees(&HOLDERS);
-
-        info!(target: "money", "[Bob] ==============================");
-        info!(target: "money", "[Bob] Building token mint tx for Bob");
-        info!(target: "money", "[Bob] ==============================");
-        let bob_token_blind = BaseBlind::random(&mut OsRng);
-        let (mint_tx, mint_params, mint_auth_params, fee_params) = th
-            .token_mint(
-                BOB_INITIAL,
-                &Holder::Bob,
-                &Holder::Bob,
-                bob_token_blind,
-                None,
-                None,
-                current_block_height,
-            )
-            .await?;
-
-        for holder in &HOLDERS {
-            info!(target: "money", "[{holder:?}] ===========================");
-            info!(target: "money", "[{holder:?}] Executing Bob token mint tx");
-            info!(target: "money", "[{holder:?}] ===========================");
-            th.execute_token_mint_tx(
-                holder,
-                mint_tx.clone(),
-                &mint_params,
-                &mint_auth_params,
-                &fee_params,
-                current_block_height,
-                true,
-            )
-            .await?;
-        }
-
-        th.assert_trees(&HOLDERS);
-
-        // Now Alice can send a little bit of funds to Bob
-        info!(target: "money", "[Alice] ====================================================");
-        info!(target: "money", "[Alice] Building Money::Transfer params for a payment to Bob");
-        info!(target: "money", "[Alice] ====================================================");
-        let mut alice_owncoins =
-            th.holders.get(&Holder::Alice).unwrap().unspent_money_coins.clone();
-        let alice_token_id = alice_owncoins[0].note.token_id;
-
-        let (transfer_tx, (transfer_params, fee_params), spent_coins) = th
-            .transfer(
-                ALICE_FIRST_SEND,
-                &Holder::Alice,
-                &Holder::Bob,
-                &alice_owncoins,
-                alice_token_id,
-                current_block_height,
-                false,
-            )
-            .await?;
-
-        // Validating transfer params
-        assert!(transfer_params.inputs.len() == 1);
-        assert!(transfer_params.outputs.len() == 2);
-        assert!(spent_coins.len() == 1);
-        alice_owncoins.retain(|x| x != &spent_coins[0]);
-        assert!(alice_owncoins.is_empty());
-
-        for holder in &HOLDERS {
-            info!(target: "money", "[{holder:?}] ==============================");
-            info!(target: "money", "[{holder:?}] Executing Alice2Bob payment tx");
-            info!(target: "money", "[{holder:?}] ==============================");
-            th.execute_transfer_tx(
-                holder,
-                transfer_tx.clone(),
-                &transfer_params,
-                &fee_params,
-                current_block_height,
-                true,
-            )
-            .await?;
-        }
-
-        // Alice should now have one OwnCoin with the change from the above transfer.
-        // Bob should now have a new OwnCoin.
-        let alice_owncoins = &th.holders.get(&Holder::Alice).unwrap().unspent_money_coins;
-        let mut bob_owncoins = th.holders.get(&Holder::Bob).unwrap().unspent_money_coins.clone();
-        assert!(alice_owncoins.len() == 1);
-        assert!(bob_owncoins.len() == 2);
-
-        th.assert_trees(&HOLDERS);
-
-        // Bob can send a little bit to Alice as well
-        info!(target: "money", "[Bob] ======================================================");
-        info!(target: "money", "[Bob] Building Money::Transfer params for a payment to Alice");
-        info!(target: "money", "[Bob] ======================================================");
-        let bob_token_id = bob_owncoins[0].note.token_id;
-        let mut bob_owncoins_tmp = bob_owncoins.clone();
-        bob_owncoins_tmp.retain(|x| x.note.token_id == bob_token_id);
-        let (transfer_tx, (transfer_params, fee_params), spent_coins) = th
-            .transfer(
-                BOB_FIRST_SEND,
-                &Holder::Bob,
-                &Holder::Alice,
-                &bob_owncoins_tmp,
-                bob_token_id,
-                current_block_height,
-                false,
-            )
-            .await?;
-
-        // Validating transfer params
-        assert!(transfer_params.inputs.len() == 1);
-        assert!(transfer_params.outputs.len() == 2);
-        assert!(spent_coins.len() == 1);
-        bob_owncoins.retain(|x| x != &spent_coins[0]);
-        assert!(bob_owncoins.len() == 1);
-
-        for holder in &HOLDERS {
-            info!(target: "money", "[{holder:?}] ==============================");
-            info!(target: "money", "[{holder:?}] Executing Bob2Alice payment tx");
-            info!(target: "money", "[{holder:?}] ==============================");
-            th.execute_transfer_tx(
-                holder,
-                transfer_tx.clone(),
-                &transfer_params,
-                &fee_params,
-                current_block_height,
-                true,
-            )
-            .await?;
-        }
-
-        // Alice should now have two OwnCoins
-        // Bob should have two with the change from the above tx
-        let mut alice_owncoins =
-            th.holders.get(&Holder::Alice).unwrap().unspent_money_coins.clone();
-        let mut bob_owncoins = th.holders.get(&Holder::Bob).unwrap().unspent_money_coins.clone();
-
-        assert!(alice_owncoins.len() == 2);
-        assert!(bob_owncoins.len() == 2);
-
-        assert!(alice_owncoins[0].note.value == ALICE_INITIAL - ALICE_FIRST_SEND);
-        assert!(alice_owncoins[0].note.token_id == alice_token_id);
-        assert!(alice_owncoins[1].note.value == BOB_FIRST_SEND);
-        assert!(alice_owncoins[1].note.token_id == bob_token_id);
-
-        assert!(bob_owncoins[0].note.value == ALICE_FIRST_SEND);
-        assert!(bob_owncoins[0].note.token_id == alice_token_id);
-        assert!(bob_owncoins[1].note.value == BOB_INITIAL - BOB_FIRST_SEND);
-        assert!(bob_owncoins[1].note.token_id == bob_token_id);
-
-        th.assert_trees(&HOLDERS);
-
-        // Alice and Bob decide to swap back their tokens so Alice gets back her initial
-        // tokens and Bob gets his.
-        info!(target: "money", "[Alice, Bob] ================");
-        info!(target: "money", "[Alice, Bob] Building OtcSwap");
-        info!(target: "money", "[Alice, Bob] ================");
-        let alice_oc = alice_owncoins[1].clone();
-        alice_owncoins.remove(1);
-        assert!(alice_owncoins.len() == 1);
-        let bob_oc = bob_owncoins[0].clone();
-        bob_owncoins.remove(0);
-        assert!(bob_owncoins.len() == 1);
-
-        let (otc_swap_tx, otc_swap_params, fee_params) = th
-            .otc_swap(&Holder::Alice, &alice_oc, &Holder::Bob, &bob_oc, current_block_height)
-            .await?;
-
-        for holder in &HOLDERS {
-            info!(target: "money", "[{holder:?}] ==========================");
-            info!(target: "money", "[{holder:?}] Executing AliceBob swap tx");
-            info!(target: "money", "[{holder:?}] ==========================");
-            th.execute_otc_swap_tx(
-                holder,
-                otc_swap_tx.clone(),
-                &otc_swap_params,
-                &fee_params,
-                current_block_height,
-                true,
-            )
-            .await?;
-        }
-
-        // Alice should now have two OwnCoins with the same token ID (ALICE)
-        let mut alice_owncoins =
-            th.holders.get(&Holder::Alice).unwrap().unspent_money_coins.clone();
-        let mut bob_owncoins = th.holders.get(&Holder::Bob).unwrap().unspent_money_coins.clone();
-
-        assert!(alice_owncoins.len() == 2);
-        assert!(alice_owncoins[0].note.token_id == alice_token_id);
-        assert!(alice_owncoins[1].note.token_id == alice_token_id);
-
-        // Same for Bob with BOB tokens
-        assert!(bob_owncoins.len() == 2);
-        assert!(bob_owncoins[0].note.token_id == bob_token_id);
-        assert!(bob_owncoins[1].note.token_id == bob_token_id);
-
-        th.assert_trees(&HOLDERS);
-
-        // Now Alice will create a new coin for herself to combine the two owncoins.
-        info!(target: "money", "[Alice] ======================================================");
-        info!(target: "money", "[Alice] Building Money::Transfer params for a payment to Alice");
-        info!(target: "money", "[Alice] ======================================================");
-        let (tx, (params, fee_params), spent_coins) = th
-            .transfer(
-                ALICE_INITIAL,
-                &Holder::Alice,
-                &Holder::Alice,
-                &alice_owncoins,
-                alice_token_id,
-                current_block_height,
-                false,
-            )
-            .await?;
-
-        for coin in spent_coins {
-            alice_owncoins.retain(|x| x != &coin);
-        }
-        assert!(alice_owncoins.is_empty());
-        assert!(params.inputs.len() == 2);
-        assert!(params.outputs.len() == 1);
-
-        for holder in &HOLDERS {
-            info!(target: "money", "[{holder:?}] ================================");
-            info!(target: "money", "[{holder:?}] Executing Alice2Alice payment tx");
-            info!(target: "money", "[{holder:?}] ================================");
-            th.execute_transfer_tx(
-                holder,
-                tx.clone(),
-                &params,
-                &fee_params,
-                current_block_height,
-                true,
-            )
-            .await?;
-        }
-
-        th.assert_trees(&HOLDERS);
-
-        // Alice should now have a single OwnCoin with her initial airdrop
-        let alice_owncoins = th.holders.get(&Holder::Alice).unwrap().unspent_money_coins.clone();
-        assert!(alice_owncoins.len() == 1);
-        assert!(alice_owncoins[0].note.value == ALICE_INITIAL);
-        assert!(alice_owncoins[0].note.token_id == alice_token_id);
-
-        // Bob does the same
-        info!(target: "money", "[Bob] ====================================================");
-        info!(target: "money", "[Bob] Building Money::Transfer params for a payment to Bob");
-        info!(target: "money", "[Bob] ====================================================");
-        let (tx, (params, fee_params), spent_coins) = th
-            .transfer(
-                BOB_INITIAL,
-                &Holder::Bob,
-                &Holder::Bob,
-                &bob_owncoins,
-                bob_token_id,
-                current_block_height,
-                false,
-            )
-            .await?;
-
-        for coin in spent_coins {
-            bob_owncoins.retain(|x| x != &coin);
-        }
-        assert!(bob_owncoins.is_empty());
-        assert!(params.inputs.len() == 2);
-        assert!(params.outputs.len() == 1);
-
-        for holder in &HOLDERS {
-            info!(target: "money", "[{holder:?}] ============================");
-            info!(target: "money", "[{holder:?}] Executing Bob2Bob payment tx");
-            info!(target: "money", "[{holder:?}] ============================");
-            th.execute_transfer_tx(
-                holder,
-                tx.clone(),
-                &params,
-                &fee_params,
-                current_block_height,
-                true,
-            )
-            .await?;
-        }
-
-        th.assert_trees(&HOLDERS);
-
-        // Bob should now have a single OwnCoin with his initial airdrop
-        let bob_owncoins = th.holders.get(&Holder::Bob).unwrap().unspent_money_coins.clone();
-        assert!(bob_owncoins.len() == 1);
-        assert!(bob_owncoins[0].note.value == BOB_INITIAL);
-        assert!(bob_owncoins[0].note.token_id == bob_token_id);
-
-        // Now they decide to swap all of their tokens
-        info!(target: "money", "[Alice, Bob] ================");
-        info!(target: "money", "[Alice, Bob] Building OtcSwap");
-        info!(target: "money", "[Alice, Bob] ================");
-        let mut alice_owncoins =
-            th.holders.get(&Holder::Alice).unwrap().unspent_money_coins.clone();
-        let mut bob_owncoins = th.holders.get(&Holder::Bob).unwrap().unspent_money_coins.clone();
-
-        let alice_oc = alice_owncoins[0].clone();
-        alice_owncoins.remove(0);
-        assert!(alice_owncoins.is_empty());
-        let bob_oc = bob_owncoins[0].clone();
-        bob_owncoins.remove(0);
-        assert!(bob_owncoins.is_empty());
-
-        let (otc_swap_tx, otc_swap_params, fee_params) = th
-            .otc_swap(&Holder::Alice, &alice_oc, &Holder::Bob, &bob_oc, current_block_height)
-            .await?;
-
-        for holder in &HOLDERS {
-            info!(target: "money", "[{holder:?}] ==========================");
-            info!(target: "money", "[{holder:?}] Executing AliceBob swap tx");
-            info!(target: "money", "[{holder:?}] ==========================");
-            th.execute_otc_swap_tx(
-                holder,
-                otc_swap_tx.clone(),
-                &otc_swap_params,
-                &fee_params,
-                current_block_height,
-                true,
-            )
-            .await?;
-        }
-
-        assert_eq!(otc_swap_params.outputs.len(), 2);
-
-        // Alice should now have Bob's BOB tokens
-        let alice_owncoins = th.holders.get(&Holder::Alice).unwrap().unspent_money_coins.clone();
-        assert!(alice_owncoins.len() == 1);
-        assert!(alice_owncoins[0].note.value == BOB_INITIAL);
-        assert!(alice_owncoins[0].note.token_id == bob_token_id);
-
-        // And Bob should have Alice's ALICE tokens
-        let bob_owncoins = th.holders.get(&Holder::Bob).unwrap().unspent_money_coins.clone();
-        assert!(bob_owncoins.len() == 1);
-        assert!(bob_owncoins[0].note.value == ALICE_INITIAL);
-        assert!(bob_owncoins[0].note.token_id == alice_token_id);
-
-        th.assert_trees(&HOLDERS);
+        const ALICE_SEND: u64 = 50;
+        const BOB_SEND: u64 = 180;
+        let block_height = 0;
+
+        let mut th = TestHarness::new(&[Alice, Bob], false).await?;
+
+        // Mint tokens for Alice and Bob
+        info!(target: "money", "Minting tokens for Alice and Bob");
+        let alice_token = th.token_mint_to_all(ALICE_INITIAL, &Alice, &Alice, block_height).await?;
+        let bob_token = th.token_mint_to_all(BOB_INITIAL, &Bob, &Bob, block_height).await?;
+
+        // Alice sends some tokens to Bob
+        info!(target: "money", "Alice sends {ALICE_SEND} to Bob");
+        th.transfer_to_all(ALICE_SEND, &Alice, &Bob, alice_token, block_height).await?;
+
+        assert_eq!(th.coins(&Alice).len(), 1); // change coin
+        assert_eq!(th.coins(&Bob).len(), 2); // original BOB + received ALICE
+        assert_eq!(th.balance(&Alice, alice_token), ALICE_INITIAL - ALICE_SEND);
+        assert_eq!(th.balance(&Bob, alice_token), ALICE_SEND);
+
+        // Bob sends some tokens to Alice
+        info!(target: "money", "Bob sends {BOB_SEND} to Alice");
+        th.transfer_to_all(BOB_SEND, &Bob, &Alice, bob_token, block_height).await?;
+
+        assert_eq!(th.balance(&Alice, alice_token), ALICE_INITIAL - ALICE_SEND);
+        assert_eq!(th.balance(&Alice, bob_token), BOB_SEND);
+        assert_eq!(th.balance(&Bob, alice_token), ALICE_SEND);
+        assert_eq!(th.balance(&Bob, bob_token), BOB_INITIAL - BOB_SEND);
+
+        // Alice and Bob swap back their foreign tokens
+        info!(target: "money", "Alice and Bob swap foreign tokens");
+        let alice_bob_coin = th.coins_by_token(&Alice, bob_token)[0].clone();
+        let bob_alice_coin = th.coins_by_token(&Bob, alice_token)[0].clone();
+        th.otc_swap_to_all(&Alice, &alice_bob_coin, &Bob, &bob_alice_coin, block_height).await?;
+
+        // Both now hold only their own token types
+        assert!(th.coins(&Alice).iter().all(|c| c.note.token_id == alice_token));
+        assert!(th.coins(&Bob).iter().all(|c| c.note.token_id == bob_token));
+
+        // Consolidate fragmented coins
+        info!(target: "money", "Consolidating coins");
+        th.consolidate_to_all(&Alice, alice_token, block_height).await?;
+        th.consolidate_to_all(&Bob, bob_token, block_height).await?;
+
+        assert_eq!(th.coins(&Alice).len(), 1);
+        assert_eq!(th.coins(&Alice)[0].note.value, ALICE_INITIAL);
+        assert_eq!(th.coins(&Bob).len(), 1);
+        assert_eq!(th.coins(&Bob)[0].note.value, BOB_INITIAL);
+
+        // Final swap: Alice and Bob exchange everything
+        info!(target: "money", "Final swap: Alice and Bob exchange all tokens");
+        let alice_coin = th.coins(&Alice)[0].clone();
+        let bob_coin = th.coins(&Bob)[0].clone();
+        th.otc_swap_to_all(&Alice, &alice_coin, &Bob, &bob_coin, block_height).await?;
+
+        assert_eq!(th.balance(&Alice, bob_token), BOB_INITIAL);
+        assert_eq!(th.balance(&Bob, alice_token), ALICE_INITIAL);
+        assert_eq!(th.coins(&Alice).len(), 1);
+        assert_eq!(th.coins(&Bob).len(), 1);
 
         // Thanks for reading
         Ok(())

+ 11 - 55
src/contract/money/tests/token_mint.rs

@@ -18,8 +18,6 @@
 
 use darkfi::Result;
 use darkfi_contract_test_harness::{init_logger, Holder, TestHarness};
-use darkfi_sdk::crypto::BaseBlind;
-use rand::rngs::OsRng;
 use tracing::info;
 
 #[test]
@@ -27,66 +25,24 @@ fn token_mint() -> Result<()> {
     smol::block_on(async {
         init_logger();
 
-        // Holders this test will use
-        const HOLDERS: [Holder; 2] = [Holder::Alice, Holder::Bob];
+        use Holder::{Alice, Bob};
 
-        // Some numbers we want to assert
         const BOB_SUPPLY: u64 = 2000000000; // 10 BOB
 
-        // Block height to verify against
-        let current_block_height = 0;
+        let block_height = 0;
 
-        // Initialize harness
-        let mut th = TestHarness::new(&HOLDERS, false).await?;
+        let mut th = TestHarness::new(&[Alice, Bob], false).await?;
 
-        info!("[Bob] Building BOB token mint tx");
-        let bob_token_blind = BaseBlind::random(&mut OsRng);
-        let (token_mint_tx, token_mint_params, token_auth_mint_params, fee_params) = th
-            .token_mint(
-                BOB_SUPPLY,
-                &Holder::Bob,
-                &Holder::Bob,
-                bob_token_blind,
-                None,
-                None,
-                current_block_height,
-            )
-            .await?;
+        // Mint BOB token
+        info!("Minting BOB token");
+        let bob_token = th.token_mint_to_all(BOB_SUPPLY, &Bob, &Bob, block_height).await?;
 
-        for holder in &HOLDERS {
-            info!("[{holder:?}] Executing BOB token mint tx");
-            th.execute_token_mint_tx(
-                holder,
-                token_mint_tx.clone(),
-                &token_mint_params,
-                &token_auth_mint_params,
-                &fee_params,
-                current_block_height,
-                true,
-            )
-            .await?;
-        }
+        assert_eq!(th.coins(&Bob).len(), 1);
+        assert_eq!(th.balance(&Bob, bob_token), BOB_SUPPLY);
 
-        th.assert_trees(&HOLDERS);
-
-        info!("[Bob] Building BOB token freeze tx");
-        let (token_frz_tx, token_frz_params, fee_params) =
-            th.token_freeze(&Holder::Bob, current_block_height).await?;
-
-        for holder in &HOLDERS {
-            info!("[{holder:?}] Executing BOB token freeze tx");
-            th.execute_token_freeze_tx(
-                holder,
-                token_frz_tx.clone(),
-                &token_frz_params,
-                &fee_params,
-                current_block_height,
-                true,
-            )
-            .await?;
-        }
-
-        th.assert_trees(&HOLDERS);
+        // Freeze BOB token authority
+        info!("Freezing BOB token authority");
+        th.token_freeze_to_all(&Bob, block_height).await?;
 
         // Thanks for reading
         Ok(())