mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-11-04 08:37:30 +00:00
store: name the invoice in credit pass warnings
This commit is contained in:
1 parent
8a35f182dc
commit
6b2bb17db3
3 files changed
+27
-8
No files matched your search
@@ -31,10 +31,12 @@ import Text.Read (readMaybe)
|
||||
minCurrentRateFraction :: Rational
|
||||
minCurrentRateFraction = 1 % 2
|
||||
|
||||
-- | CORefused: the credit's number was taken meanwhile, which the invoice's lock rules out.
|
||||
-- | CONoInvoiceRate: crypto due with no invoice rate recorded to credit it at. CORefused: the credit's number was taken meanwhile,
|
||||
-- which the invoice's lock rules out.
|
||||
data CreditOutcome
|
||||
= CONothingDue
|
||||
| COCredited LateCredit
|
||||
| CONoInvoiceRate
|
||||
| CORateFailed ProviderError
|
||||
| CORateFloor Text Rate
|
||||
| CORefused
|
||||
@@ -45,12 +47,12 @@ creditLateInvoice st readRate invId now =
|
||||
withTransaction st (`lateCreditState` invId) >>= \case
|
||||
Just s | creditable s && moneyDue s -> case lsCoin s of
|
||||
Nothing -> credit Nothing
|
||||
Just coin ->
|
||||
readRate coin >>= \case
|
||||
Left e -> pure $ CORateFailed e
|
||||
Right rate -> case invoiceRate s of
|
||||
Nothing -> pure $ CORateFailed $ ProviderError "the invoice's rate is not stored"
|
||||
Just (invoiceText, invoiceValue)
|
||||
Just coin -> case invoiceRate s of
|
||||
Nothing -> pure CONoInvoiceRate
|
||||
Just (invoiceText, invoiceValue) ->
|
||||
readRate coin >>= \case
|
||||
Left e -> pure $ CORateFailed e
|
||||
Right rate
|
||||
| toRational (rateValue rate) < minCurrentRateFraction * toRational invoiceValue ->
|
||||
CORateFloor invoiceText rate <$ withTransaction st (\db -> setLateSupport db invId LSRateFloor)
|
||||
| otherwise -> credit (Just rate)
|
||||
|
||||
@@ -341,7 +341,9 @@ creditPass env@PollerEnv {peStore, peProviders} now = do
|
||||
safely ("names: crediting invoice " <> invText) $
|
||||
getInvoice peStore invId >>= \case
|
||||
Just InvoiceRow {irProvider} | Just p <- find ((== irProvider) . pProvider) peProviders -> void $ creditLate env p now invId
|
||||
_ -> logWarn ("names: invoice " <> invText <> " has late money to credit, but no provider is configured to read its rate")
|
||||
_ -> do
|
||||
due' <- dueToWarn env now ("no rate provider: " <> invText)
|
||||
when due' $ logWarn ("names: invoice " <> invText <> " has late money to credit, but no provider is configured to read its rate")
|
||||
|
||||
-- | The pass's rate of a coin at a provider, read at most once.
|
||||
cachedRate :: PollerEnv -> Provider -> CryptoCurrency -> IO (Either ProviderError Rate)
|
||||
@@ -367,6 +369,9 @@ creditLate env@PollerEnv {peStore} p now invId@(InvoiceId invText) = do
|
||||
logInfo $
|
||||
"names: invoice " <> invText <> " credited " <> tshow lcCents <> " cents to the balance of registration " <> rid
|
||||
<> maybe "" (\units -> " for " <> tshow units <> " units at " <> fromMaybe "?" lcRateUsed <> " (invoice " <> fromMaybe "?" lcInvoiceRate <> ", current " <> fromMaybe "?" lcCurrentRate <> ")") lcUnits
|
||||
CONoInvoiceRate -> do
|
||||
due <- dueToWarn env now ("no invoice rate: " <> invText)
|
||||
when due $ logError ("names: invoice " <> invText <> " has confirmed late money, but no invoice rate was recorded to credit it at; check it at the provider")
|
||||
CORateFailed (ProviderError e) -> do
|
||||
due <- dueToWarn env now ("rate read failed: " <> tshow (pProvider p))
|
||||
when due $ logWarn ("names: late credits wait, as the current rate cannot be read; each pass tries again: " <> e)
|
||||
|
||||
@@ -69,6 +69,7 @@ namesLateCreditTests = describe "StoreService names: balance life" $ do
|
||||
it "credits nothing below the rate floor and never after, logging an error, and alerts support naming both rates" testRateFloor
|
||||
it "logs the rate floor of an invoice once while the price moves below it" testFloorLoggedOnce
|
||||
it "alerts confirmed money waiting on the rate read as such, whatever reason was stored before" testWaitingOutranksStoredReason
|
||||
it "warns once of an invoice no provider reads a rate for, and names an invoice with no recorded rate" testRateProblemsNamed
|
||||
it "reads one rate per coin per pass for several invoices, and none when nothing is due" testOneRateReadPerPass
|
||||
it "never credits a late Settled payment on an invoice made under HighSpeed, alerting it past the window" testHighSpeed
|
||||
it "credits at the next pass a late Settled invoice and a settlement whose credit step did not run" testCreditedByPass
|
||||
@@ -448,6 +449,17 @@ testWaitingOutranksStoredReason = withLate $ \l@Late {lStore = st} -> do
|
||||
alertsAt l (Left $ ProviderError "rates down for outranked") (pastWindow (at 70) 60)
|
||||
>>= (`shouldSatisfy` logged "ERROR" "invoice inv-outranked of order outranked: 320000 satoshi received, 320000 satoshi confirmed, 0 satoshi credited; confirmed, the credit waits on the rate read; do not refund; fix the rate read")
|
||||
|
||||
testRateProblemsNamed :: IO ()
|
||||
testRateProblemsNamed = withLate $ \l@Late {lStore = st} -> do
|
||||
closedOrder l "noprovider" False
|
||||
settleAt l "noprovider" (SigClosed (btcPaid lateUnits lateUnits)) (at 70) `shouldReturn` Right ISExpired
|
||||
withTransaction st $ \db -> DB.execute_ db "UPDATE sx_badge_service_invoices SET provider = 'apple' WHERE invoice_id = 'inv-noprovider'"
|
||||
closedOrder l "norate" False
|
||||
settleAt l "norate" (SigClosed (btcPaid lateUnits lateUnits) {rcvRate = Nothing}) (at 70) `shouldReturn` Right ISExpired
|
||||
logs <- (<>) <$> passAt l (at 71) <*> passAt l (at 72)
|
||||
count "invoice inv-noprovider has late money to credit, but no provider" logs `shouldBe` 1
|
||||
logs `shouldSatisfy` logged "ERROR" "invoice inv-norate has confirmed late money, but no invoice rate was recorded to credit it at"
|
||||
|
||||
testOneRateReadPerPass :: IO ()
|
||||
testOneRateReadPerPass = withLate $ \l@Late {lStore = st} -> do
|
||||
mapM_ (\r -> closedOrder l r False >> settleAt l r (SigClosed (btcPaid lateUnits lateUnits)) (at 70)) ["x", "y", "z"]
|
||||
|
||||
Reference in new issue
Block a user