Skip to content

Commit

Permalink
only set withdrawal when they are sufficiently big
Browse files Browse the repository at this point in the history
Otherwise, we end-up paying for more than the value they offer.
  • Loading branch information
KtorZ committed Jul 3, 2020
1 parent 6d33031 commit 07bbce0
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 5 deletions.
43 changes: 43 additions & 0 deletions lib/core/src/Cardano/Wallet.hs
Expand Up @@ -77,6 +77,7 @@ module Cardano.Wallet
, manageRewardBalance
, rollbackBlocks
, checkWalletIntegrity
, readNextWithdrawal
, ErrWalletAlreadyExists (..)
, ErrNoSuchWallet (..)
, ErrListUTxOStatistics (..)
Expand Down Expand Up @@ -875,6 +876,48 @@ fetchRewardBalance ctx wid = db & \DBLayer{..} ->
pk = PrimaryKey wid
db = ctx ^. dbLayer @s @k

-- | Read the current withdrawal capacity of a wallet. Note that, this simply
-- returns 0 if:
--
-- a) There's no reward account for this type of wallet.
-- b) The current reward value is too small to be considered (adding it would
-- cost more than its value).
readNextWithdrawal
:: forall ctx s t k.
( HasDBLayer s k ctx
, HasTransactionLayer t k ctx
)
=> ctx
-> WalletId
-> IO (Quantity "lovelace" Word64)
readNextWithdrawal ctx wid = db & \DBLayer{..} -> do
(pp, withdrawal) <- atomically $ (,)
<$> readProtocolParameters pk
<*> fmap getQuantity (readDelegationRewardBalance pk)
case pp of
-- May happen if done very early, in which case, rewards are probably
-- not woth considering anyway.
Nothing -> pure (Quantity 0)

Just ProtocolParameters{txParameters} -> do
let policy = W.getFeePolicy txParameters

let costOfWithdrawal =
minFee policy (mempty { withdrawal })
-
minFee policy mempty

pure $ if toInteger withdrawal < 2 * costOfWithdrawal
then Quantity 0
else Quantity withdrawal
where
db = ctx ^. dbLayer @s @k
tl = ctx ^. transactionLayer @t @k
pk = PrimaryKey wid

minFee :: FeePolicy -> CoinSelection -> Integer
minFee policy = fromIntegral . getFee . minimumFee tl policy Nothing

-- | Query the node for the reward balance of a given wallet.
--
-- Rather than force all callers of 'readWallet' to wait for fetching the
Expand Down
9 changes: 4 additions & 5 deletions lib/core/src/Cardano/Wallet/Api/Server.hs
Expand Up @@ -609,8 +609,7 @@ mkShelleyWallet
mkShelleyWallet ctx wid cp meta pending progress = do
reward <- withWorkerCtx @_ @s @k ctx wid liftE liftE $ \wrk ->
-- never fails - returns zero if balance not found
Handler $ ExceptT $ Right <$>
W.fetchRewardBalance @_ @s @k wrk wid
liftIO $ W.fetchRewardBalance @_ @s @k wrk wid
pure ApiWallet
{ addressPoolGap = ApiT $ getState cp ^. #externalPool . #gap
, balance = ApiT $ WalletBalance
Expand Down Expand Up @@ -1041,7 +1040,7 @@ selectCoins ctx gen (ApiT wid) body =
fmap mkApiCoinSelection
$ withWorkerCtx ctx wid liftE liftE
$ \wrk -> do
withdrawal <- liftIO $ W.fetchRewardBalance @_ @s @k wrk wid
withdrawal <- liftIO $ W.readNextWithdrawal @_ @s @t @k wrk wid
let outs = coerceCoin <$> body ^. #payments
liftHandler $ W.selectCoinsExternal @_ @s @t @k wrk wid gen outs withdrawal

Expand Down Expand Up @@ -1129,7 +1128,7 @@ postTransaction ctx genChange (ApiT wid) body = do
let pwd = coerce $ getApiT $ body ^. #passphrase

selection <- withWorkerCtx ctx wid liftE liftE $ \wrk -> do
withdrawal <- liftIO $ W.fetchRewardBalance @_ @s @k wrk wid
withdrawal <- liftIO $ W.readNextWithdrawal @_ @s @t @k wrk wid
liftHandler $ W.selectCoinsForPayment @_ @s @t wrk wid outs withdrawal

(tx, meta, time, wit) <- withWorkerCtx ctx wid liftE liftE $ \wrk -> liftHandler $
Expand Down Expand Up @@ -1216,7 +1215,7 @@ postTransactionFee
postTransactionFee ctx (ApiT wid) body = do
let outs = coerceCoin <$> (body ^. #payments)
withWorkerCtx ctx wid liftE liftE $ \wrk -> do
withdrawal <- liftIO $ W.fetchRewardBalance @_ @s @k wrk wid
withdrawal <- liftIO $ W.readNextWithdrawal @_ @s @t @k wrk wid
fee <- liftHandler $ W.estimateFeeForPayment @_ @s @t @k wrk wid outs withdrawal
pure $ apiFee fee

Expand Down

0 comments on commit 07bbce0

Please sign in to comment.