packages feed

btc-lsp-0.1.0.0: test/BlockScannerSpec.hs

{-# LANGUAGE TypeApplications #-}

module BlockScannerSpec
  ( spec,
  )
where

import BtcLsp.Import
import qualified BtcLsp.Math.OnChain as Math
import qualified BtcLsp.Storage.Model.SwapUtxo as SwapUtxo
import qualified BtcLsp.Thread.BlockScanner as BlockScanner
import LndClient.LndTest (mine)
import qualified Network.Bitcoin as Btc
import Test.Hspec
import TestAppM
import TestHelpers
import TestOrphan ()

spec :: Spec
spec = do
  itEnvT @'LndLsp "Block scanner works with 1 block" $ do
    wbal <- withBtcT Btc.getBalance id
    let amt = wbal / 10
    trAddr <-
      from
        . swapIntoLnFundAddress
        . entityVal
        <$> createDummySwap Nothing
    void $
      withBtcT
        Btc.sendToAddress
        (\h -> h trAddr amt Nothing Nothing)
    void $
      withBtcT
        Btc.sendToAddress
        (\h -> h trAddr amt Nothing Nothing)
    lift $ mine 1 LndLsp
    expectedAmt <-
      except
        . first (const (FailureInt $ FailurePrivate "expectedAmt overflow"))
        . Math.trySatToMsat
        $ amt * 2
    utxos <- BlockScanner.scan
    let gotAmt :: MSat = sum $ BlockScanner.utxoAmt <$> utxos
    liftIO $ expectedAmt `shouldBe` gotAmt
  itEnvT @'LndLsp "Block scanner works with 2 blocks" $ do
    wbal <- withBtcT Btc.getBalance id
    let amt = wbal / 10
    trAddr <-
      from
        . swapIntoLnFundAddress
        . entityVal
        <$> createDummySwap Nothing
    void $
      withBtcT
        Btc.sendToAddress
        (\h -> h trAddr amt Nothing Nothing)
    lift $ mine 1 LndLsp
    void $
      withBtcT
        Btc.sendToAddress
        (\h -> h trAddr amt Nothing Nothing)
    lift $ mine 1 LndLsp
    expectedAmt <-
      except . first (const (FailureInt $ FailurePrivate "expectedAmt overflow"))
        . Math.trySatToMsat
        $ amt * 2
    utxos <- BlockScanner.scan
    let gotAmt = sum $ BlockScanner.utxoAmt <$> utxos
    liftIO $ expectedAmt `shouldBe` gotAmt
  itEnvT @'LndLsp "Block scanner detects dust" $ do
    let amt0 = Math.trxDustLimit
    let amt1 = amt0 + 3000
    let amt2 = amt0 - 2000
    swapEnt <-
      createDummySwap Nothing
    let trAddr =
          from
            . swapIntoLnFundAddress
            $ entityVal swapEnt
    satsToSend <-
      mapM
        Math.tryMsatToSatT
        [amt0, amt1, amt2]
    mapM_
      ( \amt ->
          withBtcT
            Btc.sendToAddress
            (\h -> h trAddr amt Nothing Nothing)
      )
      satsToSend
    lift $
      mine 1 LndLsp
    scanUtxos <-
      BlockScanner.scan
    dbUtxos <-
      lift
        . runSql
        . (entityVal <<$>>)
        . SwapUtxo.getUtxosBySwapIdSql
        $ entityKey swapEnt
    let dbUtxosSpendable =
          filter
            ((== SwapUtxoUnspent) . swapUtxoStatus)
            dbUtxos
    let dbUtxosDust =
          filter
            ((== SwapUtxoUnspentDust) . swapUtxoStatus)
            dbUtxos
    liftIO $ do
      length scanUtxos
        `shouldBe` 3
      sum (BlockScanner.utxoAmt <$> scanUtxos)
        `shouldBe` amt0 + amt1 + amt2
      length dbUtxos
        `shouldBe` 3
      length dbUtxosSpendable
        `shouldBe` 2
      length dbUtxosDust
        `shouldBe` 1
      sum (swapUtxoAmount <$> dbUtxosSpendable)
        `shouldBe` from (amt0 + amt1)
      sum (swapUtxoAmount <$> dbUtxosDust)
        `shouldBe` from amt2