btc-lsp-0.1.0.0: src/BtcLsp/Math/OnChain.hs
{-# LANGUAGE TypeApplications #-}
module BtcLsp.Math.OnChain
( trySatToMsat,
tryMsatToSat,
trySatToMsatT,
tryMsatToSatT,
trxDustLimit,
trxHeadSize,
trxInSize,
trxOutSize,
InQty (..),
OutQty (..),
SatPerVbyte (..),
minFeeRate,
trxEstSize,
trxEstFee,
)
where
import BtcLsp.Data.Type
import BtcLsp.Import.External
import qualified Network.Bitcoin as Btc
import qualified Universum
trySatToMsat ::
Btc.BTC ->
Either Failure MSat
trySatToMsat =
first (FailureInt . FailureMath . Universum.show)
. ( from @Word64
`composeTryRhs` tryFrom @Integer
`composeTryLhs` ((* 1000) . from)
)
tryMsatToSat ::
MSat ->
Either Failure Btc.BTC
tryMsatToSat =
first (FailureInt . FailureMath . Universum.show)
. ( tryFrom @Rational @Btc.BTC
`composeTryLhs` ((% 100000000000) . via @Word64)
)
trySatToMsatT ::
( Monad m
) =>
Btc.BTC ->
ExceptT Failure m MSat
trySatToMsatT =
except . trySatToMsat
tryMsatToSatT ::
( Monad m
) =>
MSat ->
ExceptT Failure m Btc.BTC
tryMsatToSatT =
except . tryMsatToSat
trxDustLimit :: MSat
trxDustLimit =
MSat $ 546 * 1000
--
-- NOTE : estimations are for the P2WPKH only
--
trxHeadSize :: Vbyte
trxHeadSize =
Vbyte $ 105 % 10
trxInSize :: Vbyte
trxInSize =
Vbyte 68
trxOutSize :: Vbyte
trxOutSize =
Vbyte 31
newtype InQty = InQty
{ unInQty :: Natural
}
deriving newtype (Eq, Ord, Show, Num)
deriving stock (Generic)
instance Out InQty
instance From InQty Natural
instance From Natural InQty
newtype OutQty = OutQty
{ unOutQty :: Natural
}
deriving newtype (Eq, Ord, Show, Num)
deriving stock (Generic)
instance Out OutQty
instance From OutQty Natural
instance From Natural OutQty
newtype SatPerVbyte = SatPerVbyte
{ unSatPerVbyte :: Ratio Natural
}
deriving newtype (Eq, Ord, Show, Num)
deriving stock (Generic)
instance Out SatPerVbyte
instance From SatPerVbyte (Ratio Natural)
instance From (Ratio Natural) SatPerVbyte
minFeeRate :: SatPerVbyte
minFeeRate = 1
trxEstSize :: InQty -> OutQty -> Vbyte
trxEstSize inQty outQty =
trxHeadSize
+ Vbyte (via @Natural inQty) * trxInSize
--
-- TODO : LND estimator always requires +1 vout as a change
-- even if change does not exit. So we should overpay
-- a bit for non-existent output to use LND PSBTs.
-- https://github.com/lightningnetwork/lnd/issues/5739
--
+ Vbyte (via @Natural (outQty + 1)) * trxOutSize
--
-- TODO : For some reason LND estimator
-- requires +1 vbyte overhead.
--
+ Vbyte 1
trxEstFee ::
InQty ->
OutQty ->
SatPerVbyte ->
Either (TryFromException Natural MSat) MSat
trxEstFee inQty outQty satPerVbyte =
(from @Word64 `composeTryRhs` tryFrom)
. (* 1000)
. (ceiling :: Ratio Natural -> Natural)
$ from (trxEstSize inQty outQty) * from satPerVbyte