packages feed

cleveland-0.1.0: morley-client-test/Test/Fee.hs

-- SPDX-FileCopyrightText: 2021 Tocqueville Group
--
-- SPDX-License-Identifier: LicenseRef-MIT-TQ

-- | Tests for fee calculation implementation in 'morley-client'.
module Test.Fee
  ( test_FeeCalculation
  ) where

import qualified Data.List.NonEmpty as NE
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.HUnit (Assertion, testCase, (@?=))

import Morley.Client.Action.Common
  (OriginationData(..), TD(..), TransactionData(..), computeStorageLimit)
import Morley.Client.Action.Operation (dryRunOperationsNonEmpty)
import Morley.Client.Full (runMorleyClientM)
import Morley.Client.RPC.Getters (getProtocolParameters)
import Morley.Client.TezosClient.Impl (calcOriginationFee, calcTransferFee)
import Morley.Client.TezosClient.Types
  (AddressOrAlias(..), CalcOriginationFeeData(..), CalcTransferFeeData(..))
import Morley.Micheline.Json (TezosMutez(..))
import Morley.Michelson.Runtime.GState (genesisAddress)
import Morley.Michelson.Typed (IsoValue(..))
import Morley.Michelson.Untyped (pattern DefEpName)
import Morley.Tezos.Core (toMutez, zeroMutez)
import Test.Cleveland (NetworkEnv(neMorleyClientEnv))
import Test.Cleveland.Internal.Abstract (Moneybag(..))
import Test.Cleveland.Internal.Client (setupMoneybagAddress)
import Test.Cleveland.Michelson.Import (importContract)
import Test.Cleveland.Tasty (whenNetworkEnabled)

import Test.Util.Contracts (contractsDir, (</>))

test_FeeCalculation :: IO TestTree
test_FeeCalculation = pure $ whenNetworkEnabled $ \withEnv ->
  testGroup "Compare morley-client fee calulation with tezos-client"
    [ testCase "single transfer in a batch has the same fee" $ do
      compareTransferFeeCalculation withEnv $ one $ trivialTransfer
    , testCase "multiple transfers in a batch have the same fee" $ do
      compareTransferFeeCalculation withEnv $ NE.fromList $ replicate 5 trivialTransfer
    , testCase "origination has the same fee" $ do
      soBigContract <- importContract @(ToT ()) @(ToT ()) $ contractsDir </> "so_big.tz"
      compareOriginationFeeCalculation withEnv $ OriginationData
        { odReplaceExisting = True
        , odName = "so_big"
        , odBalance = zeroMutez
        , odContract = soBigContract
        , odStorage = toVal ()
        , odMbFee = Nothing
        }
    ]
  where
    trivialTransfer = TransactionData $ TD
      { tdReceiver = genesisAddress
      , tdAmount = toMutez 100
      , tdEpName = DefEpName
      , tdParam = toVal ()
      , tdMbFee = Nothing
      }

compareTransferFeeCalculation
  :: ((forall a. (NetworkEnv -> IO a) -> IO a)) -> NonEmpty TransactionData -> Assertion
compareTransferFeeCalculation withEnv transferBatch = withEnv $ \env -> do
  Moneybag moneybagAddr <- setupMoneybagAddress env
  (appliedResults, feesMorleyClient) <- fmap (unzip . toList) $ runMorleyClientM (neMorleyClientEnv env) $
    dryRunOperationsNonEmpty (AddressResolved moneybagAddr) (map Left transferBatch)
  pp <- runMorleyClientM (neMorleyClientEnv env) getProtocolParameters
  feesTezosClient <- runMorleyClientM (neMorleyClientEnv env) $ calcTransferFee
    (AddressResolved moneybagAddr) Nothing (computeStorageLimit appliedResults pp)
    (map transactionDataToCalcTransferFeeData $ toList transferBatch)
  feesMorleyClient @?= feesTezosClient
  where
    transactionDataToCalcTransferFeeData :: TransactionData -> CalcTransferFeeData
    transactionDataToCalcTransferFeeData (TransactionData TD{..}) = CalcTransferFeeData
      { ctfdTo = AddressResolved $ tdReceiver
      , ctfdParam = tdParam
      , ctfdEp = tdEpName
      , ctfdAmount = TezosMutez tdAmount
      }

compareOriginationFeeCalculation
  :: ((forall a. (NetworkEnv -> IO a) -> IO a)) -> OriginationData -> Assertion
compareOriginationFeeCalculation withEnv od@OriginationData{..} = withEnv $ \env -> do
  Moneybag moneybagAddr <- setupMoneybagAddress env
  (appliedResults, feesMorleyClient) <- fmap (unzip . toList) $ runMorleyClientM (neMorleyClientEnv env) $
    dryRunOperationsNonEmpty (AddressResolved moneybagAddr) (one $ Right od)
  pp <- runMorleyClientM (neMorleyClientEnv env) getProtocolParameters
  feeTezosClient <- runMorleyClientM (neMorleyClientEnv env) $ calcOriginationFee
    CalcOriginationFeeData
      { cofdFrom = AddressResolved moneybagAddr
      , cofdBalance = TezosMutez odBalance
      , cofdMbFromPassword = Nothing
      , cofdContract = odContract
      , cofdStorage = odStorage
      , cofdBurnCap = computeStorageLimit appliedResults pp
      }
  feesMorleyClient @?= [feeTezosClient]