diff --git a/apps/simplex-store-service/src/StoreService/Web/Names/Orders.hs b/apps/simplex-store-service/src/StoreService/Web/Names/Orders.hs index 5f288b4032..643a905f57 100644 --- a/apps/simplex-store-service/src/StoreService/Web/Names/Orders.hs +++ b/apps/simplex-store-service/src/StoreService/Web/Names/Orders.hs @@ -30,7 +30,7 @@ import Data.Word (Word32, Word64) import Network.HTTP.Types (status200, status409, status503) import Network.Wai (Request, Response, ResponseReceived) import Simplex.Chat.Badges.Code (NameCode (..), parseNameCode) -import Simplex.Chat.PaymentService.Types (CurrencyAmount (..), InvoiceId (..), InvoiceStatus (..), ServicePaymentMethod) +import Simplex.Chat.PaymentService.Types (CurrencyAmount (..), InvoiceId (..), InvoiceStatus (..), ServicePaymentMethod (..)) import Simplex.Messaging.Agent.Store.Common (withTransaction) import qualified Simplex.Messaging.Agent.Store.DB as DB import Simplex.Messaging.Crypto.Secp256k1 (RecoverableSignature) @@ -268,10 +268,16 @@ spendHandler env@OrdersEnv {oeStore, oeConfig, oeContracts, oeTurns, oeNow} cfg placeOrder env order (maybeToList holder) (coveredOrderInsert spend new) >>= \case Left refusal -> refuse refusal Right closed -> pure Answer {aResponse = registrationAnswer rid, aAfter = announceClosed env providers waiters closed} + Just (SPMCard _) + | spPrice - spBalance < minCardChargeCents -> refuse ORBadRequest Just method -> createAtProvider env cfg providers waiters what $ InvoicedOrder {ivRequest = order, ivHolders = maybeToList holder, ivMethod = method, ivPrice = spPrice, ivAmount = fromIntegral (spPrice - spBalance), ivInsert = differenceOrderInsert spend} +-- | Stripe refuses a USD charge under 50 cents, so the page offers only crypto for a smaller difference. +minCardChargeCents :: Int +minCardChargeCents = 50 + -- | Every format check, the method present exactly for a difference, then the length's range. parseSpend :: RegistrationId -> J.Object -> Either OrderRefusal ((OrderFields, Word64, RecoverableSignature), Spend) parseSpend spSource o = do diff --git a/tests/Bots/StoreService/NamesSpendTests.hs b/tests/Bots/StoreService/NamesSpendTests.hs index b53fffd1da..02b1b01a12 100644 --- a/tests/Bots/StoreService/NamesSpendTests.hs +++ b/tests/Bots/StoreService/NamesSpendTests.hs @@ -69,6 +69,7 @@ namesSpendTests = describe "StoreService names: spend" $ do it "refuses another signer and a stale timestamp, and answers an unknown order 404" testSignerAndId it "answers name_taken, catalog_changed, name_check_unavailable, provider_unavailable and order_exists, spending nothing" testOrderChecks it "runs its checks in the contract's order" testCheckOrder + it "refuses a card difference below the card minimum after the price check, accepting it by crypto and at the minimum" testCardMinimum it "refuses sealed missing or over 11095 characters and a body over 16384 bytes, accepting the longest" testSpendSizes it "counts spends against the create limit" testSpendLimit describe "holders" $ do @@ -388,6 +389,19 @@ testCheckOrder = withSpend $ \ctx@Ctx {cNode = node, cStub} -> do spend ctx src (covered 31000) {sbOrder = aliceOrder {oCommitment = commitmentOf 3}} `shouldReturn` refusedWith 409 "order_exists" amountOf ctx src `shouldReturn` Just 20000 +testCardMinimum :: IO () +testCardMinimum = withSpend $ \ctx -> do + small <- sourceOf ctx "small" 9951 + spend ctx small (difference 9951) {sbOrder = aliceOrder {oPrice = 9990}, sbMethod = Just "card"} `shouldReturn` (409, Just $ KM.fromList [("error", "catalog_changed"), ("price", J.Number 10000)]) + spend ctx small (difference 9951) {sbMethod = Just "card"} `shouldReturn` refusedWith 400 "bad_request" + stubCalls (cStub ctx) `shouldReturn` [] + amountOf ctx small `shouldReturn` Just 9951 + fst <$> spend ctx small (difference 9951) `shouldReturn` 200 + least <- sourceOf ctx "least" 19950 + fst <$> spend ctx least (dynamis 19950 (Just "card")) `shouldReturn` 200 + calls <- stubCalls (cStub ctx) + [odAmount d | StubCreate _ d <- calls] `shouldBe` [CurrencyAmount 49, CurrencyAmount 50] + testSpendSizes :: IO () testSpendSizes = withSpend $ \ctx -> do src <- sourceOf ctx "src" 15000