Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix range boundary filtering for listTransactions. #613

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/core-integration/cardano-wallet-core-integration.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ library
, template-haskell
, text
, text-class
, time
, warp
hs-source-dirs:
src
Expand Down
54 changes: 49 additions & 5 deletions lib/core-integration/src/Test/Integration/Framework/DSL.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}

{-# OPTIONS_GHC -fno-warn-simplifiable-class-constraints #-}
Expand Down Expand Up @@ -67,6 +68,8 @@ module Test.Integration.Framework.DSL
, getFromResponse
, json
, listAddresses
, listTransactions
, listAllTransactions
, tearDown
, fixtureWallet
, fixtureWalletWith
Expand Down Expand Up @@ -104,15 +107,13 @@ module Test.Integration.Framework.DSL
, listTransactionsViaCLI
) where

import Prelude hiding
( fail )

import Cardano.Wallet.Api.Types
( ApiAddress
, ApiT (..)
, ApiTransaction
, ApiUtxoStatistics (..)
, ApiWallet
, Iso8601Time (..)
)
import Cardano.Wallet.Primitive.AddressDiscovery.Sequential
( AddressPoolGap, getAddressPoolGap, mkAddressPoolGap )
Expand All @@ -127,6 +128,7 @@ import Cardano.Wallet.Primitive.Types
, Hash (..)
, HistogramBar (..)
, PoolId (..)
, SortOrder (..)
, TxIn (..)
, TxOut (..)
, TxStatus (..)
Expand Down Expand Up @@ -181,13 +183,17 @@ import Data.Generics.Product.Typed
import Data.List
( (!!) )
import Data.Maybe
( fromMaybe )
( catMaybes, fromMaybe )
import Data.Proxy
( Proxy (..) )
import Data.Quantity
( Quantity (..) )
import Data.Text
( Text )
import Data.Text.Class
( ToText (..) )
import Data.Time
( UTCTime )
import Data.Word
( Word64 )
import GHC.TypeLits
Expand All @@ -202,6 +208,8 @@ import Network.Wai.Handler.Warp
( Port )
import Numeric.Natural
( Natural )
import Prelude hiding
( fail )
import System.Command
( CmdResult, Stderr, Stdout, command )
import System.Directory
Expand Down Expand Up @@ -237,7 +245,6 @@ import Test.Integration.Framework.Request
import Web.HttpApiData
( ToHttpApiData (..) )


import qualified Cardano.Wallet.Primitive.Types as Types
import qualified Data.Aeson as Aeson
import qualified Data.ByteString.Char8 as B8
Expand Down Expand Up @@ -790,6 +797,37 @@ listAddresses ctx w = do
(_, addrs) <- unsafeRequest @[ApiAddress t] ctx (getAddressesEp w "") Empty
return addrs

listAllTransactions
:: forall t. DecodeAddress t
=> Context t
-> ApiWallet
-> IO [ApiTransaction t]
listAllTransactions ctx w = listTransactions ctx w Nothing Nothing Nothing

listTransactions
:: forall t. DecodeAddress t
=> Context t
-> ApiWallet
-> Maybe UTCTime
-> Maybe UTCTime
-> Maybe SortOrder
-> IO [ApiTransaction t]
listTransactions ctx wallet mStart mEnd mOrder = do
(_, txs) <- unsafeRequest @[ApiTransaction t] ctx path Empty
return txs
where
path = listTransactionsEp wallet $ toQueryString $ catMaybes
[ ("start", ) . toText <$> (Iso8601Time <$> mStart)
, ("end" , ) . toText <$> (Iso8601Time <$> mEnd )
, ("order", ) . toText <$> mOrder
]

toQueryString :: [(Text, Text)] -> Text
toQueryString kvs = if T.null suffix then mempty else "?" <> suffix
where
suffix = T.intercalate "&" $ buildQueryParam <$> kvs
buildQueryParam (k, v) = k <> "=" <> toQueryParam v

infixr 5 </>
(</>) :: ToHttpApiData a => Text -> a -> Text
base </> next = mconcat [base, "/", toQueryParam next]
Expand Down Expand Up @@ -884,6 +922,12 @@ getAddressesEp w stateFilter =
, "v2/wallets/" <> w ^. walletId <> "/addresses" <> stateFilter
)

listTransactionsEp :: ApiWallet -> Text -> (Method, Text)
listTransactionsEp w stateFilter =
( "GET"
, "v2/wallets/" <> w ^. walletId <> "/transactions" <> stateFilter
)

postTxEp :: ApiWallet -> (Method, Text)
postTxEp w =
( "POST"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module Test.Integration.Scenario.API.Transactions
import Prelude

import Cardano.Wallet.Api.Types
( ApiFee, ApiTransaction, ApiWallet )
( ApiFee, ApiTransaction, ApiWallet, insertedAt, time )
import Cardano.Wallet.Primitive.Types
( DecodeAddress (..), Direction (..), EncodeAddress (..), TxStatus (..) )
import Control.Monad
Expand All @@ -21,10 +21,14 @@ import Data.Aeson
( Value )
import Data.Generics.Internal.VL.Lens
( view, (^.) )
import Data.Maybe
( listToMaybe )
import Data.Time.Clock
( NominalDiffTime, UTCTime, addUTCTime )
import Numeric.Natural
( Natural )
import Test.Hspec
( SpecWith, describe, it )
( SpecWith, describe, it, shouldBe, shouldSatisfy )
import Test.Integration.Framework.DSL
( Context
, Headers (..)
Expand All @@ -50,6 +54,8 @@ import Test.Integration.Framework.DSL
, getWalletEp
, json
, listAddresses
, listAllTransactions
, listTransactions
, postTxEp
, postTxFeeEp
, request
Expand Down Expand Up @@ -1039,7 +1045,58 @@ spec = do
(errMsg400StartTimeLaterThanEndTime startTime endTime) r
pure ()

it "TRANS_LIST_RANGE_01 - \
\Transaction at time t is SELECTED by small ranges that cover it" $
\ctx -> do
(w, _, t) <- getWalletWithOneTransaction ctx
let te = addUTCTime (negate onePicosecond) t
let tl = addUTCTime onePicosecond t
te < t `shouldBe` True
tl > t `shouldBe` True
txs1 <- listTransactions ctx w (Just t ) (Just t ) Nothing
txs2 <- listTransactions ctx w (Just te) (Just t ) Nothing
txs3 <- listTransactions ctx w (Just t ) (Just tl) Nothing
txs4 <- listTransactions ctx w (Just te) (Just tl) Nothing
length <$> [txs1, txs2, txs3, txs4] `shouldSatisfy` all (== 1)

it "TRANS_LIST_RANGE_02 - \
\Transaction at time t is NOT selected by range (t + 𝛿t, ...)" $
\ctx -> do
(w, _, t) <- getWalletWithOneTransaction ctx
let tl = addUTCTime onePicosecond t
tl > t `shouldBe` True
txs1 <- listTransactions ctx w (Just tl) (Nothing) Nothing
txs2 <- listTransactions ctx w (Just tl) (Just tl) Nothing
length <$> [txs1, txs2] `shouldSatisfy` all (== 0)

it "TRANS_LIST_RANGE_03 - \
\Transaction at time t is NOT selected by range (..., t - 𝛿t)" $
\ctx -> do
(w, _, t) <- getWalletWithOneTransaction ctx
let te = addUTCTime (negate onePicosecond) t
te < t `shouldBe` True
txs1 <- listTransactions ctx w (Nothing) (Just te) Nothing
txs2 <- listTransactions ctx w (Just te) (Just te) Nothing
length <$> [txs1, txs2] `shouldSatisfy` all (== 0)

where

getWalletWithOneTransaction
:: Context t -> IO (ApiWallet, ApiTransaction t, UTCTime)
getWalletWithOneTransaction ctx = do
w <- fixtureWallet ctx
mt <- listToMaybe <$> listAllTransactions ctx w
case mt of
Just tx -> case time <$> insertedAt tx of
Just t -> pure (w, tx, t)
Nothing -> die
_ -> die
where
die = error "Expected one transaction with a time."

onePicosecond :: NominalDiffTime
onePicosecond = toEnum 1

longAddr = replicate 10000 '1'
encodeErr = "Unable to decode Address:"
matrixWrongAddrs =
Expand Down
2 changes: 1 addition & 1 deletion lib/core/src/Cardano/Wallet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,7 @@ newWalletLayer tracer bp db nw tl = do
-- correct transactions, exclusively. Adding only `slotLength - 1` would
-- make the range inclusive.
recenter :: UTCTime -> UTCTime
recenter = addUTCTime (s - 1) where (SlotLength s) = slotLength
recenter = addUTCTime (pred s) where (SlotLength s) = slotLength

-- This relies on DB.readTxHistory returning all necessary transactions
-- to assemble coin selection information for outgoing payments.
Expand Down
2 changes: 1 addition & 1 deletion lib/http-bridge/test/integration/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ main = do
PortCLI.specWithRandomPort @t defaultPort
beforeAll startCluster $ afterAll _cleanup $ after tearDown $ do
describe "PR_DISABLED Wallets API endpoint tests" (Wallets.spec @t)
describe "PR_DISABLED Transactions API endpoint tests" (Transactions.spec @t)
describe "Transactions API endpoint tests" (Transactions.spec @t)
describe "PR_DISABLED Addresses API endpoint tests" (Addresses.spec @t)
describe "Wallets CLI tests" (WalletsCLI.spec @t)
describe "Transactions CLI tests" (TransactionsCLI.spec @t)
Expand Down
2 changes: 1 addition & 1 deletion lib/jormungandr/test/integration/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ main = hspec $ do
-- API e2e Testing
describe "PR_DISABLED Addresses API endpoint tests" Addresses.spec
describe "PR_DISABLED Transactions API endpoint tests" Transactions.spec
describe "PR_DISABLED Transactions API endpoint tests (Jormungandr specific)"
describe "Transactions API endpoint tests (Jormungandr specific)"
(TransactionsJormungandr.spec @t)
describe "PR_DISABLED Wallets API endpoint tests" Wallets.spec
-- Command-Line e2e Testing
Expand Down
1 change: 1 addition & 0 deletions nix/.stack.nix/cardano-wallet-core-integration.nix

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.