From 3e24c80c530dfa9ac1457d23a9e9d45ffa7c3b03 Mon Sep 17 00:00:00 2001 From: Paolo Veronelli Date: Tue, 3 May 2022 12:16:09 +0200 Subject: [PATCH 01/12] add endpoints support for simple metadata --- .gitignore | 6 + lib/cli/src/Cardano/CLI.hs | 36 +++-- lib/cli/test/unit/Cardano/CLISpec.hs | 29 +++- .../src/Test/Integration/Framework/DSL.hs | 8 +- .../Scenario/API/Shelley/Addresses.hs | 4 +- .../Scenario/API/Shelley/StakePools.hs | 16 +-- .../Scenario/API/Shelley/Transactions.hs | 130 ++++++++++++++---- .../Scenario/API/Shelley/TransactionsNew.hs | 94 ++++++++++--- .../Scenario/CLI/Shelley/HWWallets.hs | 4 +- .../Scenario/CLI/Shelley/Transactions.hs | 129 ++++++++++++----- lib/core/cardano-wallet-core.cabal | 1 + lib/core/src/Cardano/Wallet/Api.hs | 2 + lib/core/src/Cardano/Wallet/Api/Client.hs | 6 +- lib/core/src/Cardano/Wallet/Api/Link.hs | 24 +++- lib/core/src/Cardano/Wallet/Api/Server.hs | 62 ++++++--- lib/core/src/Cardano/Wallet/Api/Types.hs | 9 +- .../Wallet/Api/Types/SchemaMetadata.hs | 69 ++++++++++ .../test/unit/Cardano/Wallet/Api/TypesSpec.hs | 6 + .../src/Cardano/Wallet/Shelley/Api/Server.hs | 12 +- 19 files changed, 504 insertions(+), 143 deletions(-) create mode 100644 lib/core/src/Cardano/Wallet/Api/Types/SchemaMetadata.hs diff --git a/.gitignore b/.gitignore index 2f63ca54907..0f7f29b5eb7 100644 --- a/.gitignore +++ b/.gitignore @@ -42,9 +42,15 @@ hie.yaml *.faulty.json *.faulty.json lib/shelley/test/data/balanceTx/**/actual +lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.faulty.reencoded.json +lib/core/test/data/Cardano/Wallet/Api/ApiWalletMigrationPostDataTestnet0user.json ### Release scripts output /GENERATED_*.md ### Docs build /_build/ +.vscode/settings.json + + + diff --git a/lib/cli/src/Cardano/CLI.hs b/lib/cli/src/Cardano/CLI.hs index e34765fc124..dbbac6ec981 100644 --- a/lib/cli/src/Cardano/CLI.hs +++ b/lib/cli/src/Cardano/CLI.hs @@ -1,5 +1,6 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ApplicativeDo #-} +{-# LANGUAGE BlockArguments #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DerivingStrategies #-} @@ -149,7 +150,6 @@ import Cardano.Wallet.Api.Types , ApiPostRandomAddressData (..) , ApiT (..) , ApiTxId (ApiTxId) - , ApiTxMetadata (..) , ApiWallet , Base (Base16) , ByronWalletPostData (..) @@ -324,6 +324,8 @@ import UnliftIO.Exception import qualified Cardano.BM.Configuration.Model as CM import qualified Cardano.BM.Data.BackendKind as CM import qualified Cardano.BM.Data.Observable as Obs +import Cardano.Wallet.Api.Types.SchemaMetadata + ( TxMetadataWithSchema ) import qualified Command.Key as Key import qualified Command.RecoveryPhrase as RecoveryPhrase import qualified Data.Aeson as Aeson @@ -729,6 +731,12 @@ cmdWalletGetUtxoStatistics mkClient = data TransactionFeatures = NoShelleyFeatures | ShelleyFeatures deriving (Show, Eq) +-- | which json schema to use for output, True is simple +metadataSchemaOption :: Parser Bool +metadataSchemaOption = switch + do long "simple-metadata" + <> help "output metadata json in no-schema encoding" + -- | cardano-wallet transaction cmdTransaction :: ToJSON wallet @@ -760,7 +768,7 @@ data TransactionCreateArgs t = TransactionCreateArgs { _port :: Port "Wallet" , _id :: WalletId , _payments :: NonEmpty Text - , _metadata :: ApiTxMetadata + , _metadata :: Maybe TxMetadataWithSchema , _timeToLive :: Maybe (Quantity "second" NominalDiffTime) } @@ -783,7 +791,7 @@ cmdTransactionCreate isShelley mkTxClient mkWalletClient = <$> portOption <*> walletIdArgument <*> fmap NE.fromList (some paymentOption) - <*> whenShelley (ApiTxMetadata Nothing) metadataOption isShelley + <*> whenShelley Nothing metadataOption isShelley <*> whenShelley Nothing timeToLiveOption isShelley exec (TransactionCreateArgs wPort wId wAddressAmounts md ttl) = do wPayments <- either (fail . getTextDecodingError) pure $ @@ -819,7 +827,7 @@ cmdTransactionFees isShelley mkTxClient mkWalletClient = <$> portOption <*> walletIdArgument <*> fmap NE.fromList (some paymentOption) - <*> whenShelley (ApiTxMetadata Nothing) metadataOption isShelley + <*> whenShelley Nothing metadataOption isShelley <*> whenShelley Nothing timeToLiveOption isShelley exec (TransactionCreateArgs wPort wId wAddressAmounts md ttl) = do wPayments <- either (fail . getTextDecodingError) pure $ @@ -845,6 +853,7 @@ data TransactionListArgs = TransactionListArgs , _timeRangeStart :: Maybe Iso8601Time , _timeRangeEnd :: Maybe Iso8601Time , _sortOrder :: Maybe SortOrder + , _schema :: Bool } cmdTransactionList @@ -860,13 +869,15 @@ cmdTransactionList mkTxClient = <*> optional timeRangeStartOption <*> optional timeRangeEndOption <*> optional sortOrderOption - exec (TransactionListArgs wPort wId mTimeRangeStart mTimeRangeEnd mOrder) = + <*> metadataSchemaOption + exec (TransactionListArgs wPort wId mTimeRangeStart mTimeRangeEnd mOrder metadataSchema) = runClient wPort Aeson.encodePretty $ listTransactions mkTxClient (ApiT wId) mTimeRangeStart mTimeRangeEnd (ApiT <$> mOrder) + metadataSchema -- | Arguments for 'transaction submit' command data TransactionSubmitArgs = TransactionSubmitArgs @@ -916,6 +927,7 @@ data TransactionGetArgs = TransactionGetArgs { _port :: Port "Wallet" , _wid :: WalletId , _txid :: TxId + , _schema :: Bool } cmdTransactionGet @@ -928,12 +940,16 @@ cmdTransactionGet mkClient = cmd = fmap exec $ TransactionGetArgs <$> portOption <*> walletIdArgument - <*> transactionIdArgument - exec (TransactionGetArgs wPort wId txId) = do + <*> transactionIdArgument + <*> metadataSchemaOption + exec (TransactionGetArgs wPort wId txId metadataSchema ) = do runClient wPort Aeson.encodePretty $ getTransaction mkClient (ApiT wId) + metadataSchema (ApiTxId $ ApiT $ getTxId txId) + + {------------------------------------------------------------------------------- Commands - 'address' -------------------------------------------------------------------------------} @@ -1435,16 +1451,16 @@ transactionSubmitPayloadArgument = argumentT $ mempty -- | [--metadata=JSON] -- -- Note: we decode the JSON just so that we can validate more client-side. -metadataOption :: Parser ApiTxMetadata +metadataOption :: Parser (Maybe TxMetadataWithSchema) metadataOption = option txMetadataReader $ mempty <> long "metadata" <> metavar "JSON" - <> value (ApiTxMetadata Nothing) + <> value Nothing <> help ("Application-specific transaction metadata as a JSON object. " <> "The value must match the schema defined in the " <> "cardano-wallet OpenAPI specification.") -txMetadataReader :: ReadM ApiTxMetadata +txMetadataReader :: ReadM (Maybe TxMetadataWithSchema) txMetadataReader = eitherReader (Aeson.eitherDecode' . BL8.pack) -- | [--ttl=DURATION] diff --git a/lib/cli/test/unit/Cardano/CLISpec.hs b/lib/cli/test/unit/Cardano/CLISpec.hs index d5f6e45b844..a003d8b00f1 100644 --- a/lib/cli/test/unit/Cardano/CLISpec.hs +++ b/lib/cli/test/unit/Cardano/CLISpec.hs @@ -40,8 +40,6 @@ import Cardano.Wallet.Api.Client , transactionClient , walletClient ) -import Cardano.Wallet.Api.Types - ( ApiT (..), ApiTxMetadata (..) ) import Cardano.Wallet.Primitive.Types ( PoolMetadataSource ) import Cardano.Wallet.Primitive.Types.Tx @@ -100,6 +98,8 @@ import UnliftIO.MVar import UnliftIO.Temporary ( withSystemTempDirectory ) +import Cardano.Wallet.Api.Types.SchemaMetadata + ( detailedMetadata, noSchemaMetadata ) import qualified Data.Map as Map import qualified Data.Text as T import qualified Data.Text.IO as TIO @@ -255,8 +255,8 @@ spec = do describe "Tx Metadata JSON option" $ do let parse arg = execParserPure defaultPrefs (info metadataOption mempty) ["--metadata", arg] - let md = ApiT (TxMetadata (Map.singleton 42 (TxMetaText "hi"))) - let ok ex (Success res) = ex == getApiTxMetadata res + let md = detailedMetadata (TxMetadata (Map.singleton 42 (TxMetaText "hi"))) + let ok ex (Success res) = ex == res ok _ _ = False let err (Failure _) = True err _ = False @@ -268,8 +268,27 @@ spec = do , ("invalid", "{ \"json\": true }", err) , ("null 1", "{ \"0\": null }", err) , ("null 2", "null", ok Nothing) - , ("null 3", "{ }", ok (Just (ApiT mempty))) + , ("null 3", "{ }", ok (Just (detailedMetadata mempty))) ] + describe "Tx No-Schema Metadata JSON option" $ do + let parse arg = execParserPure defaultPrefs (info metadataOption mempty) ["--metadata", arg] + let md = noSchemaMetadata (TxMetadata (Map.singleton 42 (TxMetaText "hi"))) + let ok ex (Success res) = ex == res + ok _ _ = False + let err (Failure _) = True + err _ = False + mapM_ + (\(desc, arg, tst) -> it desc (parse arg `shouldSatisfy` tst)) + [ ("valid", "{ \"42\": \"hi\" }", ok $ Just md) + , ("malformed", "testing", err) + , ("malformed trailing", "{ \"0\": \"\" } arstneio", err) + , ("invalid", "{ \"json\": true }", err) + , ("null 1", "{ \"0\": null }", err) + , ("null 2", "null", ok Nothing) + , ("null 3", "{ }", ok $ Just $ detailedMetadata mempty) -- this is the default parsing success + ] + + describe "Tx TTL option" $ do let parse arg = execParserPure defaultPrefs diff --git a/lib/core-integration/src/Test/Integration/Framework/DSL.hs b/lib/core-integration/src/Test/Integration/Framework/DSL.hs index 703e679ca8f..c9ea76225f8 100644 --- a/lib/core-integration/src/Test/Integration/Framework/DSL.hs +++ b/lib/core-integration/src/Test/Integration/Framework/DSL.hs @@ -2803,11 +2803,13 @@ postTransactionFeeViaCLI ctx args = cardanoWalletCLI $ join listTransactionsViaCLI :: forall r s m. (CmdResult r, HasType (Port "wallet") s, MonadIO m) => s + -> Bool -> [String] -> m r -listTransactionsViaCLI ctx args = cardanoWalletCLI $ join +listTransactionsViaCLI ctx metadataSchema args = cardanoWalletCLI $ join [ ["transaction", "list"] , ["--port", show (ctx ^. typed @(Port "wallet"))] + , ["--simple-metadata" | metadataSchema] , args ] @@ -2838,10 +2840,12 @@ getTransactionViaCLI => s -> String -> String + -> Bool -> m r -getTransactionViaCLI ctx wid tid = cardanoWalletCLI $ join +getTransactionViaCLI ctx wid tid metadataSchema = cardanoWalletCLI $ join [ ["transaction", "get"] , ["--port", show (ctx ^. typed @(Port "wallet")), wid, tid] + , ["--simple-metadata" | metadataSchema] ] proc' :: FilePath -> [String] -> CreateProcess diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Addresses.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Addresses.hs index 4e4f7ad01a0..30324062175 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Addresses.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Addresses.hs @@ -329,10 +329,10 @@ spec = describe "SHELLEY_ADDRESSES" $ do -- 4. Wait for transaction from A -> B to no longer be pending eventually "Transaction from A -> B is discovered on B" $ do request @(ApiTransaction n) ctx - (Link.getTransaction @'Shelley wA rtx) Default Empty + (Link.getTransaction @'Shelley wA rtx False) Default Empty >>= expectField #status (`shouldBe` ApiT InLedger) request @(ApiTransaction n) ctx - (Link.getTransaction @'Shelley wB rtx) Default Empty + (Link.getTransaction @'Shelley wB rtx False) Default Empty >>= expectField #status (`shouldBe` ApiT InLedger) -- 5. Check that there's one more used and total addresses on the wallets diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/StakePools.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/StakePools.hs index 17a70854d59..e1c89918b5c 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/StakePools.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/StakePools.hs @@ -238,7 +238,7 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do eventually "Wallet has joined pool and deposit info persists" $ do rJoin' <- request @(ApiTransaction n) ctx (Link.getTransaction @'Shelley src - (getFromResponse Prelude.id rJoin)) + (getFromResponse Prelude.id rJoin) False) Default Empty verify rJoin' [ expectResponseCode HTTP.status200 @@ -249,14 +249,14 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do ] let txId = getFromResponse #id rJoin - let link = Link.getTransaction @'Shelley src (ApiTxId txId) + let link = Link.getTransaction @'Shelley src (ApiTxId txId) False eventually "delegation transaction is in ledger" $ do rSrc <- request @(ApiTransaction n) ctx link Default Empty verify rSrc [ expectResponseCode HTTP.status200 , expectField (#direction . #getApiT) (`shouldBe` Outgoing) , expectField (#status . #getApiT) (`shouldBe` InLedger) - , expectField (#metadata . #getApiTxMetadata) (`shouldBe` Nothing) + , expectField #metadata (`shouldBe` Nothing) , expectField #inputs $ \inputs' -> do inputs' `shouldSatisfy` all (isJust . source) ] @@ -302,7 +302,7 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do expectResponseCode HTTP.status202 r1 eventually "Wallet has not consumed rewards" $ do let linkSrc = Link.getTransaction @'Shelley - src (getFromResponse Prelude.id r1) + src (getFromResponse Prelude.id r1) False request @(ApiTransaction n) ctx linkSrc Default Empty >>= flip verify [ expectField @@ -377,7 +377,7 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do eventually "There's at least one outgoing transaction with a withdrawal" $ do rWithdrawal <- request @(ApiTransaction n) ctx (Link.getTransaction @'Shelley src - (getFromResponse Prelude.id rTx)) + (getFromResponse Prelude.id rTx) False) Default Empty verify rWithdrawal [ expectResponseCode HTTP.status200 @@ -413,7 +413,7 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do let quitFeeAmt = getFromResponse #amount rq eventually "Certificates are inserted after quitting a pool" $ do - let epg = Link.getTransaction @'Shelley src txid + let epg = Link.getTransaction @'Shelley src txid False rlg <- request @(ApiTransaction n) ctx epg Default Empty verify rlg [ expectField @@ -934,14 +934,14 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do ] let txId = getFromResponse #id rQuit - let link = Link.getTransaction @'Shelley w (ApiTxId txId) + let link = Link.getTransaction @'Shelley w (ApiTxId txId) False eventually "quit transaction is in ledger" $ do rSrc <- request @(ApiTransaction n) ctx link Default Empty verify rSrc [ expectResponseCode HTTP.status200 , expectField (#direction . #getApiT) (`shouldBe` Incoming) , expectField (#status . #getApiT) (`shouldBe` InLedger) - , expectField (#metadata . #getApiTxMetadata) (`shouldBe` Nothing) + , expectField #metadata (`shouldBe` Nothing) , expectField #inputs $ \inputs' -> do inputs' `shouldSatisfy` all (isJust . source) ] diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Transactions.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Transactions.hs index eb8dd2a0333..d42a5887bd3 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Transactions.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Transactions.hs @@ -179,6 +179,7 @@ import qualified Data.List.NonEmpty as NE import qualified Data.Map as Map import qualified Data.Text as T import qualified Network.HTTP.Types.Status as HTTP +import Cardano.Wallet.Api.Types.SchemaMetadata (detailedMetadata) data TestCase a = TestCase { query :: T.Text @@ -325,7 +326,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do inputs' `shouldSatisfy` all (isJust . source) , expectField (#direction . #getApiT) (`shouldBe` Outgoing) , expectField (#status . #getApiT) (`shouldBe` Pending) - , expectField (#metadata . #getApiTxMetadata) (`shouldBe` Nothing) + , expectField #metadata (`shouldBe` Nothing) ] verify ra @@ -341,7 +342,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do ] let txid = getFromResponse #id rTx - let linkSrc = Link.getTransaction @'Shelley wa (ApiTxId txid) + let linkSrc = Link.getTransaction @'Shelley wa (ApiTxId txid) False eventually "transaction is no longer pending on source wallet" $ do rSrc <- request @(ApiTransaction n) ctx linkSrc Default Empty verify rSrc @@ -352,10 +353,10 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do inputs' `shouldSatisfy` all (isJust . source) , expectField (#direction . #getApiT) (`shouldBe` Outgoing) , expectField (#status . #getApiT) (`shouldBe` InLedger) - , expectField (#metadata . #getApiTxMetadata) (`shouldBe` Nothing) + , expectField (#metadata) (`shouldBe` Nothing) ] - let linkDest = Link.getTransaction @'Shelley wb (ApiTxId txid) + let linkDest = Link.getTransaction @'Shelley wb (ApiTxId txid) False eventually "transaction is discovered by destination wallet" $ do rDst <- request @(ApiTransaction n) ctx linkDest Default Empty verify rDst @@ -365,7 +366,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do inputs' `shouldSatisfy` all (isNothing . source) , expectField (#direction . #getApiT) (`shouldBe` Incoming) , expectField (#status . #getApiT) (`shouldBe` InLedger) - , expectField (#metadata . #getApiTxMetadata) (`shouldBe` Nothing) + , expectField (#metadata) (`shouldBe` Nothing) ] eventually "wa and wb balances are as expected" $ do @@ -957,7 +958,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do } ] - it "TRANSMETA_CREATE_02 - Transaction with invalid metadata" $ \ctx -> runResourceT $ do + it "TRANSMETA_CREATE_02a - Transaction with invalid metadata" $ \ctx -> runResourceT $ do (wa, wb) <- (,) <$> fixtureWallet ctx <*> fixtureWallet ctx let amt = minUTxOValue (_mainEra ctx) :: Natural @@ -971,6 +972,26 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do expectResponseCode HTTP.status400 r expectErrorMessage errMsg400TxMetadataStringTooLong r + + it "TRANSMETA_CREATE_02b - Transaction with invalid no-schema metadata" $ \ctx -> runResourceT $ do + (wa, wb) <- (,) <$> fixtureWallet ctx <*> fixtureWallet ctx + let amt = minUTxOValue (_mainEra ctx) :: Natural + + basePayload <- mkTxPayload ctx wb amt fixturePassphrase + + let txMeta = [json|{ "1": #{T.replicate 65 "a"} }|] + let payload = addTxMetadata txMeta basePayload + + r <- + request @(ApiTransaction n) + ctx + (Link.createTransactionOld @'Shelley wa) + Default + payload + + + expectResponseCode HTTP.status400 r + expectErrorMessage errMsg400TxMetadataStringTooLong r it "TRANSMETA_CREATE_03 - Transaction with too much metadata" $ \ctx -> runResourceT $ do (wa, wb) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx @@ -992,7 +1013,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do expectResponseCode HTTP.status403 r expectErrorMessage errMsg403TxTooBig r - it "TRANSMETA_ESTIMATE_01 - fee estimation includes metadata" $ \ctx -> runResourceT $ do + it "TRANSMETA_ESTIMATE_01a - fee estimation includes metadata" $ \ctx -> runResourceT $ do (wa, wb) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx let amt = minUTxOValue (_mainEra ctx) :: Natural @@ -1020,7 +1041,45 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do , expectField (#estimatedMax . #getQuantity) (.< feeEstMax) ] - it "TRANSMETA_ESTIMATE_02 - fee estimation with invalid metadata" $ \ctx -> runResourceT $ do + it "TRANSMETA_ESTIMATE_01b - fee estimation includes no-schema metadata" $ \ctx -> runResourceT $ do + (wa, wb) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx + let amt = minUTxOValue (_mainEra ctx) :: Natural + + payload <- mkTxPayload ctx wb amt fixturePassphrase + + let txMeta = [json|{ "1": "hello" }|] + let payloadWithMetadata = addTxMetadata txMeta payload + + ra <- + request @ApiFee + ctx + (Link.getTransactionFeeOld @'Shelley wa) + Default + payloadWithMetadata + verify + ra + [ expectSuccess + , expectResponseCode HTTP.status202 + ] + let (Quantity feeEstMin) = getFromResponse #estimatedMin ra + let (Quantity feeEstMax) = getFromResponse #estimatedMax ra + + -- check that it's estimated to have less fees for transactions without + -- metadata. + rb <- + request @ApiFee + ctx + (Link.getTransactionFeeOld @'Shelley wa) + Default + payload + verify + rb + [ expectResponseCode HTTP.status202 + , expectField (#estimatedMin . #getQuantity) (.< feeEstMin) + , expectField (#estimatedMax . #getQuantity) (.< feeEstMax) + ] + + it "TRANSMETA_ESTIMATE_02a - fee estimation with invalid metadata" $ \ctx -> runResourceT $ do (wa, wb) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx let amt = minUTxOValue (_mainEra ctx) :: Natural @@ -1034,6 +1093,25 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do expectResponseCode HTTP.status400 r expectErrorMessage errMsg400TxMetadataStringTooLong r + + it "TRANSMETA_ESTIMATE_02b - fee estimation with invalid no-schema metadata" $ \ctx -> runResourceT $ do + (wa, wb) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx + let amt = minUTxOValue (_mainEra ctx) :: Natural + + basePayload <- mkTxPayload ctx wb amt fixturePassphrase + + let txMeta = [json|{ "1": #{T.replicate 65 "a" } }|] + let payload = addTxMetadata txMeta basePayload + + r <- + request @ApiFee + ctx + (Link.getTransactionFeeOld @'Shelley wa) + Default + payload + + expectResponseCode HTTP.status400 r + expectErrorMessage errMsg400TxMetadataStringTooLong r it "TRANSMETA_ESTIMATE_03 - fee estimation with too much metadata" $ \ctx -> runResourceT $ do (wa, wb) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx @@ -1607,7 +1685,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do eventually "Transactions are available and in ledger" $ do -- Verify Tx in source wallet is Outgoing and InLedger - let linkSrc = Link.getTransaction @'Shelley wSrc (ApiTxId txid) + let linkSrc = Link.getTransaction @'Shelley wSrc (ApiTxId txid) False r1 <- request @(ApiTransaction n) ctx linkSrc Default Empty verify r1 [ expectResponseCode HTTP.status200 @@ -1616,7 +1694,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do ] -- Verify Tx in destination wallet is Incoming and InLedger - let linkDest = Link.getTransaction @'Shelley wDest (ApiTxId txid) + let linkDest = Link.getTransaction @'Shelley wDest (ApiTxId txid) False r2 <- request @(ApiTransaction n) ctx linkDest Default Empty verify r2 [ expectResponseCode HTTP.status200 @@ -1628,7 +1706,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do w <- emptyWallet ctx _ <- request @ApiWallet ctx (Link.deleteWallet @'Shelley w) Default Empty let txid = ApiT $ Hash $ BS.pack $ replicate 32 1 - let link = Link.getTransaction @'Shelley w (ApiTxId txid) + let link = Link.getTransaction @'Shelley w (ApiTxId txid) False r <- request @(ApiTransaction n) ctx link Default Empty expectResponseCode HTTP.status404 r expectErrorMessage (errMsg404NoWallet $ w ^. walletId) r @@ -1649,7 +1727,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do ] let txid = Hash $ BS.pack $ replicate 32 1 - let link = Link.getTransaction @'Shelley wSrc (ApiTxId $ ApiT txid) + let link = Link.getTransaction @'Shelley wSrc (ApiTxId $ ApiT txid) False r <- request @(ApiTransaction n) ctx link Default Empty expectResponseCode HTTP.status404 r expectErrorMessage (errMsg404CannotFindTx $ toText txid) r @@ -1830,7 +1908,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do eventually "withdrawal transaction is listed on other" $ do rTxOther <- request @(ApiTransaction n) ctx - (Link.getTransaction @'Shelley wOther tid) Default payload + (Link.getTransaction @'Shelley wOther tid False) Default payload verify rTxOther [ expectResponseCode HTTP.status200 @@ -1852,7 +1930,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do eventually "withdrawal transaction is listed on self" $ do rTxSelf <- request @(ApiTransaction n) ctx - (Link.getTransaction @'Shelley wSelf tid) Default payload + (Link.getTransaction @'Shelley wSelf tid False) Default payload verify rTxSelf [ expectResponseCode HTTP.status200 @@ -2152,8 +2230,8 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do , expectResponseCode HTTP.status202 , expectField (#status . #getApiT) (`shouldBe` Pending) , expectField - (#metadata . #getApiTxMetadata) - (`shouldBe` fmap ApiT txMetadata) + #metadata + (`shouldBe` detailedMetadata <$> txMetadata) , expectField (#fee) (`shouldBe` expectedFee) ] @@ -2169,8 +2247,8 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do , expectListField 0 (#direction . #getApiT) (`shouldBe` Outgoing) , expectListField 0 - (#metadata . #getApiTxMetadata) - (`shouldBe` fmap ApiT txMetadata) + (#metadata ) + (`shouldBe` detailedMetadata <$> txMetadata) ] -- on dst wallet let linkDstList = Link.listTransactions @'Shelley wb @@ -2182,14 +2260,14 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do , expectListField 0 (#direction . #getApiT) (`shouldBe` Incoming) , expectListField 0 - (#metadata . #getApiTxMetadata) - (`shouldBe` fmap ApiT txMetadata) + (#metadata ) + (`shouldBe` detailedMetadata <$> txMetadata) ] let txid = getFromResponse #id ra eventually "metadata is confirmed in transaction get" $ do -- on src wallet - let linkSrc = Link.getTransaction @'Shelley wa (ApiTxId txid) + let linkSrc = Link.getTransaction @'Shelley wa (ApiTxId txid) False rg1 <- request @(ApiTransaction n) ctx linkSrc Default Empty verify rg1 [ expectResponseCode HTTP.status200 @@ -2198,11 +2276,11 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do , expectField (#status . #getApiT) (`shouldBe` InLedger) , expectField - (#metadata . #getApiTxMetadata) - (`shouldBe` fmap ApiT txMetadata) + #metadata + (`shouldBe` detailedMetadata <$> txMetadata) ] -- on dst wallet - let linkDst = Link.getTransaction @'Shelley wb (ApiTxId txid) + let linkDst = Link.getTransaction @'Shelley wb (ApiTxId txid) False rg2 <- request @(ApiTransaction n) ctx linkDst Default Empty verify rg2 [ expectResponseCode HTTP.status200 @@ -2211,8 +2289,8 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do , expectField (#status . #getApiT) (`shouldBe` InLedger) , expectField - (#metadata . #getApiTxMetadata) - (`shouldBe` fmap ApiT txMetadata) + #metadata + (`shouldBe` detailedMetadata <$> txMetadata) ] txDeleteNotExistsingTxIdTest eWallet resource = diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs index 36a66e4c6ae..c33bac869de 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs @@ -135,8 +135,6 @@ import Data.Function ( (&) ) import Data.Generics.Internal.VL.Lens ( view, (^.) ) -import Data.Generics.Sum - ( _Ctor ) import Data.Maybe ( fromJust, isJust ) import Data.Proxy @@ -291,7 +289,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do [ expectResponseCode HTTP.status400 ] - it "TRANS_NEW_CREATE_02 - Only metadata" $ \ctx -> runResourceT $ do + it "TRANS_NEW_CREATE_02a - Only metadata" $ \ctx -> runResourceT $ do wa <- fixtureWallet ctx let metadata = Json [json|{ "metadata": { "1": { "string": "hello" } } }|] @@ -353,6 +351,68 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (`shouldBe` (fromIntegral oneMillionAda - expectedFee)) ] + it "TRANS_NEW_CREATE_02b - Only metadata, untyped" $ \ctx -> runResourceT $ do + wa <- fixtureWallet ctx + let metadata = Json [json|{ "metadata": { "1": "hello" } }|] + + rTx <- request @(ApiConstructTransaction n) ctx + (Link.createUnsignedTransaction @'Shelley wa) Default metadata + verify rTx + [ expectResponseCode HTTP.status202 + , expectField (#coinSelection . #metadata) (`shouldSatisfy` isJust) + , expectField (#fee . #getQuantity) (`shouldSatisfy` (>0)) + ] + + let expectedFee = getFromResponse (#fee . #getQuantity) rTx + let apiTx = getFromResponse #transaction rTx + signedTx <- signTx ctx wa apiTx [ expectResponseCode HTTP.status202 ] + + -- Check for the presence of metadata on signed transaction + let + getMetadata (InAnyCardanoEra _ tx) = Cardano.getTxBody tx + & (\(Cardano.TxBody bodyContent) -> + Cardano.txMetadata bodyContent + & \case Cardano.TxMetadataNone -> + Nothing + Cardano.TxMetadataInEra _ (Cardano.TxMetadata m) -> + Just m + ) + + case getMetadata (cardanoTx $ getApiT (signedTx ^. #transaction)) of + Nothing -> error "Tx doesn't include metadata" + Just m -> case Map.lookup 1 m of + Nothing -> error "Tx doesn't include metadata" + Just (Cardano.TxMetaText "hello") -> pure () + Just _ -> error "Tx metadata incorrect" + + let txCbor = getFromResponse #transaction (HTTP.status202, Right signedTx) + let decodePayload = Json (toJSON $ ApiSerialisedTransaction txCbor) + let expMetadata = ApiT (TxMetadata (Map.fromList [(1,TxMetaText "hello")])) + rDecodedTx <- request @(ApiDecodedTransaction n) ctx + (Link.decodeTransaction @'Shelley wa) Default decodePayload + verify rDecodedTx + [ expectResponseCode HTTP.status202 + , expectField #metadata (`shouldBe` (ApiTxMetadata (Just expMetadata))) + ] + + -- Submit tx + submittedTx <- submitTxWithWid ctx wa signedTx + verify submittedTx + [ expectSuccess + , expectResponseCode HTTP.status202 + ] + + -- Make sure only fee is deducted from fixtureWallet + eventually "Wallet balance is as expected" $ do + rWa <- request @ApiWallet ctx + (Link.getWallet @'Shelley wa) Default Empty + verify rWa + [ expectSuccess + , expectField + (#balance . #available . #getQuantity) + (`shouldBe` (fromIntegral oneMillionAda - expectedFee)) + ] + it "TRANS_NEW_CREATE_03a - Withdrawal from self, 0 rewards" $ \ctx -> runResourceT $ do wa <- fixtureWallet ctx let initialBalance = wa ^. #balance . #available . #getQuantity @@ -864,7 +924,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do ] let txid = getFromResponse (#id) submittedTx - let queryTx = Link.getTransaction @'Shelley wa (ApiTxId txid) + let queryTx = Link.getTransaction @'Shelley wa (ApiTxId txid) False rGetTx <- request @(ApiTransaction n) ctx queryTx Default Empty verify rGetTx [ expectResponseCode HTTP.status200 @@ -882,7 +942,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do ] eventually "transaction is eventually in ledger after submitting" $ do - let queryTx' = Link.getTransaction @'Shelley wa (ApiTxId txid) + let queryTx' = Link.getTransaction @'Shelley wa (ApiTxId txid) False rSrc <- request @(ApiTransaction n) ctx queryTx' Default Empty verify rSrc [ expectResponseCode HTTP.status200 @@ -1028,7 +1088,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do let txId = getFromResponse (#id) submittedTx outTxAmt <- eventually "Transactions is in ledger" $ do - let linkSrc = Link.getTransaction @'Shelley wa txId + let linkSrc = Link.getTransaction @'Shelley wa txId False r1 <- request @(ApiTransaction n) ctx linkSrc Default Empty verify r1 [ expectResponseCode HTTP.status200 @@ -2259,7 +2319,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do eventually "Wallet has joined pool and deposit info persists" $ do rJoin' <- request @(ApiTransaction n) ctx (Link.getTransaction @'Shelley src - (getFromResponse Prelude.id submittedTx1)) + (getFromResponse Prelude.id submittedTx1) False) Default Empty verify rJoin' [ expectResponseCode HTTP.status200 @@ -2270,14 +2330,14 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do ] let txId1 = getFromResponse #id submittedTx1 - let link = Link.getTransaction @'Shelley src (ApiTxId txId1) + let link = Link.getTransaction @'Shelley src (ApiTxId txId1) False eventually "delegation transaction is in ledger" $ do rSrc <- request @(ApiTransaction n) ctx link Default Empty verify rSrc [ expectResponseCode HTTP.status200 , expectField (#direction . #getApiT) (`shouldBe` Outgoing) , expectField (#status . #getApiT) (`shouldBe` InLedger) - , expectField (#metadata . #getApiTxMetadata) (`shouldBe` Nothing) + , expectField #metadata (`shouldBe` Nothing) , expectField #inputs $ \inputs' -> do inputs' `shouldSatisfy` all (isJust . source) ] @@ -2337,7 +2397,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do ] let txid2 = getFromResponse (#id) submittedTx2 - let queryTx2 = Link.getTransaction @'Shelley src (ApiTxId txid2) + let queryTx2 = Link.getTransaction @'Shelley src (ApiTxId txid2) False rGetTx2 <- request @(ApiTransaction n) ctx queryTx2 Default Empty verify rGetTx2 [ expectResponseCode HTTP.status200 @@ -2446,7 +2506,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do ] let txid3 = getFromResponse (#id) submittedTx4 - let queryTx3 = Link.getTransaction @'Shelley src (ApiTxId txid3) + let queryTx3 = Link.getTransaction @'Shelley src (ApiTxId txid3) False rGetTx3 <- request @(ApiTransaction n) ctx queryTx3 Default Empty verify rGetTx3 [ expectResponseCode HTTP.status200 @@ -2582,7 +2642,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do eventually "Wallet has joined pool and deposit info persists" $ do rJoin' <- request @(ApiTransaction n) ctx (Link.getTransaction @'Shelley src - (getFromResponse Prelude.id submittedTx1)) + (getFromResponse Prelude.id submittedTx1) False) Default Empty verify rJoin' [ expectResponseCode HTTP.status200 @@ -2592,14 +2652,14 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do ] let txId1 = getFromResponse #id submittedTx1 - let link = Link.getTransaction @'Shelley src (ApiTxId txId1) + let link = Link.getTransaction @'Shelley src (ApiTxId txId1) False eventually "delegation transaction is in ledger" $ do rSrc <- request @(ApiTransaction n) ctx link Default Empty verify rSrc [ expectResponseCode HTTP.status200 , expectField (#direction . #getApiT) (`shouldBe` Outgoing) , expectField (#status . #getApiT) (`shouldBe` InLedger) - , expectField (#metadata . #getApiTxMetadata) (`shouldBe` Nothing) + , expectField #metadata (`shouldBe` Nothing) , expectField #inputs $ \inputs' -> do inputs' `shouldSatisfy` all (isJust . source) ] @@ -2718,7 +2778,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do eventually "Wallet has joined pool and deposit info persists" $ do rJoin' <- request @(ApiTransaction n) ctx (Link.getTransaction @'Shelley src - (getFromResponse Prelude.id submittedTx1)) + (getFromResponse Prelude.id submittedTx1) False) Default Empty verify rJoin' [ expectResponseCode HTTP.status200 @@ -2927,14 +2987,14 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do eventually "Metadata is on-chain" $ do rWa <- request @(ApiTransaction n) ctx - (Link.getTransaction @'Shelley wa txId) Default Empty + (Link.getTransaction @'Shelley wa txId False) Default Empty verify rWa [ expectSuccess , expectField (#status . #getApiT) (`shouldBe` InLedger) , expectField - (#metadata . #getApiTxMetadata . _Ctor @"Just" . #getApiT) + (#metadata . traverse . #txMetadataWithSchema_metadata) (`shouldBe` Cardano.TxMetadata (Map.fromList [(1, Cardano.TxMetaText "hello")])) ] diff --git a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/HWWallets.hs b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/HWWallets.hs index e28aa205b78..992f1d17177 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/HWWallets.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/HWWallets.hs @@ -307,10 +307,8 @@ spec = describe "SHELLEY_CLI_HW_WALLETS" $ do it "Can list transactions" $ \ctx -> runResourceT $ do w <- emptyWalletFromPubKeyViaCLI ctx restoredWalletName - (Exit code, Stdout out, Stderr err) <- - listTransactionsViaCLI ctx [T.unpack $ w ^. walletId] - + listTransactionsViaCLI ctx False [T.unpack $ w ^. walletId] err `shouldBe` cmdOk out `shouldBe` "[]\n" code `shouldBe` ExitSuccess diff --git a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Transactions.hs b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Transactions.hs index edd4507dcdd..56a692cc1b7 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Transactions.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Transactions.hs @@ -29,6 +29,8 @@ import Cardano.Wallet.Primitive.Types ( SortOrder (..) ) import Cardano.Wallet.Primitive.Types.Tx ( Direction (..), TxMetadata (..), TxMetadataValue (..), TxStatus (..) ) +import Cardano.Wallet.Api.Types.SchemaMetadata + ( detailedMetadata, noSchemaMetadata ) import Control.Monad ( forM_, join ) import Control.Monad.IO.Class @@ -112,7 +114,6 @@ import Test.Integration.Framework.TestData ) import UnliftIO.Exception ( throwString ) - import qualified Data.Map as Map import qualified Data.Text as T @@ -138,7 +139,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do (between (feeMin + amt, feeMax + amt)) , expectCliField (#direction . #getApiT) (`shouldBe` Outgoing) , expectCliField (#status . #getApiT) (`shouldBe` Pending) - , expectCliField (#metadata . #getApiTxMetadata) (`shouldBe` Nothing) + , expectCliField #metadata (`shouldBe` Nothing) ] -- verify balance on src wallet @@ -317,12 +318,15 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do out `shouldBe` "" c `shouldBe` ExitFailure 1 - it "TRANSMETA_CREATE_01 - Transaction with metadata via CLI" $ \ctx -> runResourceT $ do + it "TRANSMETA_CREATE_01a - Transaction with metadata via CLI" $ \ctx -> runResourceT $ do (wSrc, wDest) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx let amt = 10_000_000 let md = Just "{ \"1\": { \"string\": \"hello\" } }" - let expected = Just $ ApiT $ TxMetadata $ - Map.singleton 1 (TxMetaText "hello") + let expected = + Just $ + detailedMetadata $ + TxMetadata $ + Map.singleton 1 (TxMetaText "hello") args <- postTxArgs ctx wSrc wDest amt md Nothing Stdout feeOut <- postTransactionFeeViaCLI ctx args @@ -330,24 +334,83 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do txJson <- postTxViaCLI ctx wSrc wDest amt md Nothing verify txJson - [ expectCliField (#amount . #getQuantity) + [ expectCliField + (#amount . #getQuantity) (between (feeMin + amt, feeMax + amt)) , expectCliField (#direction . #getApiT) (`shouldBe` Outgoing) , expectCliField (#status . #getApiT) (`shouldBe` Pending) - , expectCliField (#metadata . #getApiTxMetadata) (`shouldBe` expected) + , expectCliField #metadata (`shouldBe` expected) ] eventually "metadata is confirmed in transaction list" $ do (Exit code, Stdout out, Stderr err) <- - listTransactionsViaCLI ctx [T.unpack $ wSrc ^. walletId] + listTransactionsViaCLI ctx False [T.unpack $ wSrc ^. walletId] err `shouldBe` "Ok.\n" code `shouldBe` ExitSuccess outJson <- expectValidJSON (Proxy @([ApiTransaction n])) out - verify outJson - [ expectCliListField 0 (#metadata . #getApiTxMetadata) (`shouldBe` expected) + verify + outJson + [ expectCliListField 0 #metadata (`shouldBe` expected) , expectCliListField 0 (#status . #getApiT) (`shouldBe` InLedger) ] + it "TRANSMETA_CREATE_01b - Transaction with metadata via CLI with simple metadata" $ \ctx -> runResourceT $ do + (wSrc, wDest) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx + let amt = 10_000_000 + let md = Just "{ \"1\": { \"string\": \"hello\" } }" + let expected = Just $ + detailedMetadata $ + TxMetadata $ + Map.singleton 1 (TxMetaText "hello") + + args <- postTxArgs ctx wSrc wDest amt md Nothing + Stdout feeOut <- postTransactionFeeViaCLI ctx args + ApiFee (Quantity feeMin) (Quantity feeMax) _ _ <- expectValidJSON Proxy feeOut + + txJson <- postTxViaCLI ctx wSrc wDest amt md Nothing + verify txJson + [ expectCliField + (#amount . #getQuantity) + (between (feeMin + amt, feeMax + amt)) + , expectCliField (#direction . #getApiT) (`shouldBe` Outgoing) + , expectCliField (#status . #getApiT) (`shouldBe` Pending) + , expectCliField #metadata (`shouldBe` expected) + ] + + let wSrcId = T.unpack (wSrc ^. walletId) + let txId = getTxId txJson + + (Exit code, Stdout out, Stderr err) <- getTransactionViaCLI ctx wSrcId txId True + err `shouldBe` "Ok.\n" + code `shouldBe` ExitSuccess + outJson <- expectValidJSON (Proxy @(ApiTransaction n)) out + let expectedNoSchema = Just $ + noSchemaMetadata $ + TxMetadata $ + Map.singleton 1 (TxMetaText "hello") + verify outJson + [ expectCliField + (#amount . #getQuantity) + (between (feeMin + amt, feeMax + amt)) + , expectCliField (#direction . #getApiT) (`shouldBe` Outgoing) + , expectCliField (#status . #getApiT) (`shouldBe` Pending) + , expectCliField #metadata (`shouldBe` expectedNoSchema) + ] + eventually "metadata is confirmed in transaction list" $ do + (Exit codeL, Stdout outL, Stderr errL) <- + listTransactionsViaCLI ctx True [T.unpack $ wSrc ^. walletId] + errL `shouldBe` "Ok.\n" + codeL `shouldBe` ExitSuccess + outJsonL <- expectValidJSON (Proxy @([ApiTransaction n])) outL + verify + outJsonL + [ expectCliListField 0 #metadata (`shouldBe` expectedNoSchema) + , expectCliListField 0 (#status . #getApiT) (`shouldBe` InLedger) + ] + + + + it "TRANSTTL_CREATE_01 - Transaction with TTL via CLI" $ \ctx -> runResourceT $ do (wSrc, wDest) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx let amt = 10_000_000 @@ -367,7 +430,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do eventually "transaction with ttl is confirmed in transaction list" $ do (Exit code, Stdout out, Stderr err) <- - listTransactionsViaCLI ctx [T.unpack $ wDest ^. walletId] + listTransactionsViaCLI ctx False [T.unpack $ wDest ^. walletId] err `shouldBe` "Ok.\n" code `shouldBe` ExitSuccess outJson <- expectValidJSON (Proxy @([ApiTransaction n])) out @@ -418,7 +481,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do it title $ \ctx -> runResourceT $ do wallet <- emptyWallet ctx (Exit code, Stdout out, Stderr err) <- - listTransactionsViaCLI ctx $ join + listTransactionsViaCLI ctx False $ join [ [T.unpack $ wallet ^. walletId] , maybe [] (\t -> ["--start", t]) mStart , maybe [] (\t -> ["--end" , t]) mEnd @@ -456,7 +519,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do -- Verify Tx list contains Incoming and Outgoing (Exit code, Stdout out, Stderr err) <- - listTransactionsViaCLI ctx [T.unpack $ wSrc ^. walletId] + listTransactionsViaCLI ctx False [T.unpack $ wSrc ^. walletId] err `shouldBe` "Ok.\n" code `shouldBe` ExitSuccess outJson <- expectValidJSON (Proxy @([ApiTransaction n])) out @@ -480,7 +543,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do it title $ \ctx -> runResourceT $ do wid <- emptyWallet' ctx (Exit code, Stdout out, Stderr err) <- - listTransactionsViaCLI ctx $ join + listTransactionsViaCLI ctx False $ join [ [ wid ] , [ "--start", startTime ] , [ "--end" , endTime ] @@ -524,7 +587,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do forM_ orderings $ \(order, expects) -> do let args = T.unpack <$> w ^. walletId : order (Exit code, Stdout out, Stderr err) <- - listTransactionsViaCLI ctx args + listTransactionsViaCLI ctx False args err `shouldBe` "Ok.\n" code `shouldBe` ExitSuccess outJson <- expectValidJSON (Proxy @([ApiTransaction n])) out @@ -565,7 +628,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do wid <- emptyWallet' ctx let args = wid : q (Exit code, Stdout out, Stderr err) <- - listTransactionsViaCLI ctx args + listTransactionsViaCLI ctx False args out `shouldBe` mempty code `shouldBe` ExitFailure 1 err `shouldContain` errorMess @@ -574,7 +637,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do wid <- emptyWallet' ctx let invalidWid = wid ++ "0" (Exit code, Stdout out, Stderr err) <- - listTransactionsViaCLI ctx [invalidWid] + listTransactionsViaCLI ctx False [invalidWid] err `shouldContain` "wallet id should be a hex-encoded\ \ string of 40 characters" @@ -586,14 +649,14 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do Exit d <- deleteWalletViaCLI ctx wid d `shouldBe` ExitSuccess - (Exit c, Stdout o, Stderr e) <- listTransactionsViaCLI ctx [wid] + (Exit c, Stdout o, Stderr e) <- listTransactionsViaCLI ctx False [wid] e `shouldContain` errMsg404NoWallet (T.pack wid) o `shouldBe` mempty c `shouldBe` ExitFailure 1 describe "TRANS_LIST_04 - False wallet ids" $ do forM_ falseWalletIds $ \(title, walId) -> it title $ \ctx -> runResourceT $ do - (Exit c, Stdout o, Stderr e) <- listTransactionsViaCLI ctx [walId] + (Exit c, Stdout o, Stderr e) <- listTransactionsViaCLI ctx False [walId] o `shouldBe` "" c `shouldBe` ExitFailure 1 if (title == "40 chars hex") then @@ -614,13 +677,13 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do [ "--start", utcIso8601ToText t1 , "--end", utcIso8601ToText t2 ] - Stdout o1 <- listTransactionsViaCLI ctx + Stdout o1 <- listTransactionsViaCLI ctx False ( T.unpack <$> walId : (query t t) ) - Stdout o2 <- listTransactionsViaCLI ctx + Stdout o2 <- listTransactionsViaCLI ctx False ( T.unpack <$> walId : (query te t) ) - Stdout o3 <- listTransactionsViaCLI ctx + Stdout o3 <- listTransactionsViaCLI ctx False ( T.unpack <$> walId : (query t tl) ) - Stdout o4 <- listTransactionsViaCLI ctx + Stdout o4 <- listTransactionsViaCLI ctx False ( T.unpack <$> walId : (query te tl) ) oJson1 <- expectValidJSON (Proxy @([ApiTransaction n])) o1 oJson2 <- expectValidJSON (Proxy @([ApiTransaction n])) o2 @@ -635,9 +698,9 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do let walId = w ^. walletId t <- unsafeGetTransactionTime =<< listAllTransactions @n ctx w let tl = utcIso8601ToText $ utcTimeSucc t - Stdout o1 <- listTransactionsViaCLI ctx + Stdout o1 <- listTransactionsViaCLI ctx False ( T.unpack <$> [walId, "--start", tl] ) - Stdout o2 <- listTransactionsViaCLI ctx + Stdout o2 <- listTransactionsViaCLI ctx False ( T.unpack <$> [walId, "--start", tl, "--end", tl] ) oJson1 <- expectValidJSON (Proxy @([ApiTransaction n])) o1 oJson2 <- expectValidJSON (Proxy @([ApiTransaction n])) o2 @@ -650,9 +713,9 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do let walId = w ^. walletId t <- unsafeGetTransactionTime =<< listAllTransactions @n ctx w let te = utcIso8601ToText $ utcTimePred t - Stdout o1 <- listTransactionsViaCLI ctx + Stdout o1 <- listTransactionsViaCLI ctx False ( T.unpack <$> [walId, "--end", te] ) - Stdout o2 <- listTransactionsViaCLI ctx + Stdout o2 <- listTransactionsViaCLI ctx False ( T.unpack <$> [walId, "--start", te, "--end", te] ) oJson1 <- expectValidJSON (Proxy @([ApiTransaction n])) o1 oJson2 <- expectValidJSON (Proxy @([ApiTransaction n])) o2 @@ -694,7 +757,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do -- Verify Tx in source wallet is Outgoing and InLedger (Exit code1, Stdout out1, Stderr err1) <- - getTransactionViaCLI ctx wSrcId txId + getTransactionViaCLI ctx wSrcId txId False err1 `shouldBe` "Ok.\n" code1 `shouldBe` ExitSuccess outJson1 <- expectValidJSON (Proxy @(ApiTransaction n)) out1 @@ -706,7 +769,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do let wDestId = T.unpack (wDest ^. walletId) -- Verify Tx in destination wallet is Incoming and InLedger (Exit code2, Stdout out2, Stderr err2) <- - getTransactionViaCLI ctx wDestId txId + getTransactionViaCLI ctx wDestId txId False err2 `shouldBe` "Ok.\n" code2 `shouldBe` ExitSuccess outJson2 <- expectValidJSON (Proxy @(ApiTransaction n)) out2 @@ -721,7 +784,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do d `shouldBe` ExitSuccess let txId = "3e6ec12da4414aa0781ff8afa9717ae53ee8cb4aa55d622f65bc62619a4f7b12" - (Exit c, Stdout o, Stderr e) <- getTransactionViaCLI ctx wid txId + (Exit c, Stdout o, Stderr e) <- getTransactionViaCLI ctx wid txId False e `shouldContain` errMsg404NoWallet (T.pack wid) o `shouldBe` mempty c `shouldBe` ExitFailure 1 @@ -747,7 +810,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do let wid = T.unpack (wSrc ^. walletId) let txId = "3e6ec12da4414aa0781ff8afa9717ae53ee8cb4aa55d622f65bc62619a4f7b12" - (Exit c2, Stdout o2, Stderr e2) <- getTransactionViaCLI ctx wid txId + (Exit c2, Stdout o2, Stderr e2) <- getTransactionViaCLI ctx wid txId False e2 `shouldContain` errMsg404CannotFindTx (T.pack txId) o2 `shouldBe` mempty c2 `shouldBe` ExitFailure 1 @@ -767,7 +830,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do let txId = getTxId txJson eventually "Tx is in ledger" $ do - listTransactionsViaCLI ctx [wSrcId] + listTransactionsViaCLI ctx False [wSrcId] >>= expectValidJSON (Proxy @([ApiTransaction n])) . fromStdout >>= flip verify [ expectCliListField 0 @@ -843,7 +906,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do it "BYRON_TX_LIST_03 -\ \ Shelley CLI does not list Byron wallet transactions" $ \ctx -> runResourceT $ do wid <- emptyRandomWallet' ctx - (Exit c, Stdout o, Stderr e) <- listTransactionsViaCLI ctx [wid] + (Exit c, Stdout o, Stderr e) <- listTransactionsViaCLI ctx False [wid] e `shouldContain` errMsg404NoWallet (T.pack wid) o `shouldBe` mempty c `shouldBe` ExitFailure 1 diff --git a/lib/core/cardano-wallet-core.cabal b/lib/core/cardano-wallet-core.cabal index 7d6a82c89d5..f2f7d887069 100644 --- a/lib/core/cardano-wallet-core.cabal +++ b/lib/core/cardano-wallet-core.cabal @@ -185,6 +185,7 @@ library Cardano.Wallet.Api.Server Cardano.Wallet.Api.Server.Tls Cardano.Wallet.Api.Types + Cardano.Wallet.Api.Types.SchemaMetadata Cardano.Wallet.CoinSelection Cardano.Wallet.CoinSelection.Internal Cardano.Wallet.CoinSelection.Internal.Balance diff --git a/lib/core/src/Cardano/Wallet/Api.hs b/lib/core/src/Cardano/Wallet/Api.hs index 093e7d9adb4..ec77195c3e7 100644 --- a/lib/core/src/Cardano/Wallet/Api.hs +++ b/lib/core/src/Cardano/Wallet/Api.hs @@ -584,12 +584,14 @@ type ListTransactions n = "wallets" :> QueryParam "start" Iso8601Time :> QueryParam "end" Iso8601Time :> QueryParam "order" (ApiT SortOrder) + :> QueryFlag "simple-metadata" :> Get '[JSON] [ApiTransactionT n] -- | https://input-output-hk.github.io/cardano-wallet/api/#operation/getTransaction type GetTransaction n = "wallets" :> Capture "walletId" (ApiT WalletId) :> "transactions" + :> QueryFlag "simple-metadata" :> Capture "transactionId" ApiTxId :> Get '[JSON] (ApiTransactionT n) diff --git a/lib/core/src/Cardano/Wallet/Api/Client.hs b/lib/core/src/Cardano/Wallet/Api/Client.hs index 3f2aea02124..959ea140b60 100644 --- a/lib/core/src/Cardano/Wallet/Api/Client.hs +++ b/lib/core/src/Cardano/Wallet/Api/Client.hs @@ -163,6 +163,7 @@ data TransactionClient = TransactionClient -> Maybe Iso8601Time -> Maybe Iso8601Time -> Maybe (ApiT SortOrder) + -> Bool -> ClientM [ApiTransactionT Aeson.Value] , signTransaction :: ApiT WalletId @@ -185,6 +186,7 @@ data TransactionClient = TransactionClient -> ClientM NoContent , getTransaction :: ApiT WalletId + -> Bool -> ApiTxId -> ClientM (ApiTransactionT Aeson.Value) , constructTransaction @@ -361,13 +363,13 @@ byronTransactionClient = = client (Proxy @("v2" :> Proxy_)) in TransactionClient - { listTransactions = _listTransactions + { listTransactions = \wid start end order _ -> _listTransactions wid start end order , signTransaction = _signTransaction , postTransaction = _postTransaction , postTransactionFee = _postTransactionFee , postExternalTransaction = _postExternalTransaction . fromSerialisedTx , deleteTransaction = _deleteTransaction - , getTransaction = _getTransaction + , getTransaction = \wid _ txid -> _getTransaction wid txid , constructTransaction = _constructTransaction , balanceTransaction = error "balance transaction endpoint not supported for byron" , decodeTransaction = error "decode transaction endpoint not supported for byron" diff --git a/lib/core/src/Cardano/Wallet/Api/Link.hs b/lib/core/src/Cardano/Wallet/Api/Link.hs index 94d90ea7d5e..a30d99da740 100644 --- a/lib/core/src/Cardano/Wallet/Api/Link.hs +++ b/lib/core/src/Cardano/Wallet/Api/Link.hs @@ -626,7 +626,15 @@ listTransactions' -> (Method, Text) listTransactions' w minWithdrawal inf sup order = discriminate @style (endpoint @(Api.ListTransactions Net) - (\mk -> mk wid (MinWithdrawal <$> minWithdrawal) inf sup (ApiT <$> order))) + (\mk -> mk + wid + (MinWithdrawal <$> minWithdrawal) + inf + sup + (ApiT <$> order) + False + ) + ) (endpoint @(Api.ListByronTransactions Net) (\mk -> mk wid inf sup (ApiT <$> order))) (notSupported "Shared") @@ -676,15 +684,21 @@ getTransaction ) => w -> t + -> Bool -> (Method, Text) -getTransaction w t = discriminate @style - (endpoint @(Api.GetTransaction Net) mkURL) - (endpoint @(Api.GetByronTransaction Net) mkURL) +getTransaction w t s = discriminate @style + (endpoint @(Api.GetTransaction Net) mkShelleyURL) + (endpoint @(Api.GetByronTransaction Net) mkByronURL) (notSupported "Shared") where wid = w ^. typed @(ApiT WalletId) tid = ApiTxId (t ^. typed @(ApiT (Hash "Tx"))) - mkURL mk = mk wid tid + mkByronURL mk = mk wid tid + + mkShelleyURL :: (ApiT WalletId -> Bool -> ApiTxId -> Text) -> Text + mkShelleyURL mk = mk wid s tid + + createUnsignedTransaction :: forall style w. diff --git a/lib/core/src/Cardano/Wallet/Api/Server.hs b/lib/core/src/Cardano/Wallet/Api/Server.hs index d256a670d1a..73d377880ad 100644 --- a/lib/core/src/Cardano/Wallet/Api/Server.hs +++ b/lib/core/src/Cardano/Wallet/Api/Server.hs @@ -15,6 +15,7 @@ {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} +{-# LANGUAGE BlockArguments #-} -- | -- Copyright: © 2018-2020 IOHK @@ -683,6 +684,7 @@ import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Network.Wai.Handler.Warp as Warp import qualified Network.Wai.Handler.WarpTLS as Warp +import Cardano.Wallet.Api.Types.SchemaMetadata (TxMetadataWithSchema(TxMetadataWithSchema), TxMetadataSchema (TxMetadataDetailedSchema, TxMetadataNoSchema)) -- | How the server should listen for incoming requests. data Listen @@ -2002,7 +2004,7 @@ postTransactionOld postTransactionOld ctx genChange (ApiT wid) body = do let pwd = coerce $ body ^. #passphrase . #getApiT let outs = addressAmountToTxOut <$> body ^. #payments - let md = body ^? #metadata . traverse . #getApiT + let md = body ^? #metadata . traverse . #txMetadataWithSchema_metadata let mTTL = body ^? #timeToLive . traverse . #getQuantity (wdrl, mkRwdAcct) <- @@ -2045,9 +2047,9 @@ postTransactionOld ctx genChange (ApiT wid) body = do pure (sel, tx, txMeta, txTime, pp) liftIO $ mkApiTransaction - (timeInterpreter $ ctx ^. networkLayer) - (#pendingSince) - MkApiTransactionParams + do timeInterpreter $ ctx ^. networkLayer + do #pendingSince + do MkApiTransactionParams { txId = tx ^. #txId , txFee = tx ^. #fee , txInputs = NE.toList $ second Just <$> sel ^. #inputs @@ -2061,6 +2063,7 @@ postTransactionOld ctx genChange (ApiT wid) body = do , txTime , txScriptValidity = tx ^. #scriptValidity , txDeposit = W.stakeKeyDeposit pp + , txMetadataSchema = TxMetadataDetailedSchema } where ti :: TimeInterpreter (ExceptT PastHorizonException IO) @@ -2079,14 +2082,15 @@ deleteTransaction ctx (ApiT wid) (ApiTxId (ApiT (tid))) = do listTransactions :: forall ctx s k n. (ctx ~ ApiLayer s k) - => ctx - -> ApiT WalletId - -> Maybe MinWithdrawal - -> Maybe Iso8601Time - -> Maybe Iso8601Time - -> Maybe (ApiT SortOrder) + => ctx -- ^ + -> ApiT WalletId -- ^ + -> Maybe MinWithdrawal -- ^ + -> Maybe Iso8601Time -- ^ + -> Maybe Iso8601Time -- ^ + -> Maybe (ApiT SortOrder) -- ^ + -> Bool -- ^ metadata json schema -> Handler [ApiTransaction n] -listTransactions ctx (ApiT wid) mMinWithdrawal mStart mEnd mOrder = do +listTransactions ctx (ApiT wid) mMinWithdrawal mStart mEnd mOrder metadataSchema = do (txs, depo) <- withWorkerCtx ctx wid liftE liftE $ \wrk -> do txs <- liftHandler $ W.listTransactions @_ @_ @_ wrk wid @@ -2096,7 +2100,15 @@ listTransactions ctx (ApiT wid) mMinWithdrawal mStart mEnd mOrder = do (maybe defaultSortOrder getApiT mOrder) depo <- liftIO $ W.stakeKeyDeposit <$> NW.currentProtocolParameters (wrk ^. networkLayer) pure (txs, depo) - liftIO $ mapM (mkApiTransactionFromInfo (timeInterpreter (ctx ^. networkLayer)) depo) txs + liftIO $ forM txs $ \tx -> + mkApiTransactionFromInfo + (timeInterpreter (ctx ^. networkLayer)) + depo + tx + if metadataSchema + then TxMetadataNoSchema + else TxMetadataDetailedSchema + where defaultSortOrder :: SortOrder defaultSortOrder = Descending @@ -2105,14 +2117,16 @@ getTransaction :: forall ctx s k n. (ctx ~ ApiLayer s k) => ctx -> ApiT WalletId + -> Bool -> ApiTxId -> Handler (ApiTransaction n) -getTransaction ctx (ApiT wid) (ApiTxId (ApiT (tid))) = do +getTransaction ctx (ApiT wid) mMetadataSchema (ApiTxId (ApiT (tid))) = do (tx, depo) <- withWorkerCtx ctx wid liftE liftE $ \wrk -> do tx <- liftHandler $ W.getTransaction wrk wid tid depo <- liftIO $ W.stakeKeyDeposit <$> NW.currentProtocolParameters (wrk ^. networkLayer) pure (tx, depo) - liftIO $ mkApiTransactionFromInfo (timeInterpreter (ctx ^. networkLayer)) depo tx + liftIO $ mkApiTransactionFromInfo (timeInterpreter (ctx ^. networkLayer)) depo tx + $ if mMetadataSchema then TxMetadataNoSchema else TxMetadataDetailedSchema -- Populate an API transaction record with 'TransactionInfo' from the wallet -- layer. @@ -2121,9 +2135,12 @@ mkApiTransactionFromInfo => TimeInterpreter (ExceptT PastHorizonException IO) -> Coin -> TransactionInfo + -> TxMetadataSchema -> m (ApiTransaction n) -mkApiTransactionFromInfo ti deposit info = do - apiTx <- liftIO $ mkApiTransaction ti status +mkApiTransactionFromInfo ti deposit info metadataSchema = do + apiTx <- liftIO $ mkApiTransaction + ti + status MkApiTransactionParams { txId = info ^. #txInfoId , txFee = info ^. #txInfoFee @@ -2137,6 +2154,7 @@ mkApiTransactionFromInfo ti deposit info = do , txTime = info ^. #txInfoTime , txScriptValidity = info ^. #txInfoScriptValidity , txDeposit = deposit + , txMetadataSchema = metadataSchema } return $ case info ^. (#txInfoMeta . #status) of Pending -> apiTx @@ -2167,7 +2185,7 @@ postTransactionFeeOld ctx (ApiT wid) body = do (wdrl, _) <- mkRewardAccountBuilder @_ @s @_ @n ctx wid (body ^. #withdrawal) let txCtx = defaultTransactionCtx { txWithdrawal = wdrl - , txMetadata = getApiT <$> body ^. #metadata + , txMetadata = body ^? #metadata . traverse . #txMetadataWithSchema_metadata } withWorkerCtx ctx wid liftE liftE $ \wrk -> do (utxoAvailable, wallet, pendingTxs) <- @@ -2268,7 +2286,7 @@ constructTransaction ctx genChange knownPools getPoolStatus (ApiT wid) body = do when notall0Haccount $ liftHandler $ throwE ErrConstructTxMultiaccountNotSupported - let md = body ^? #metadata . traverse . #getApiT + let md = body ^? #metadata . traverse . #txMetadataWithSchema_metadata let isValidityBoundTimeNegative (ApiValidityBoundAsTimeFromNow (Quantity sec)) = sec < 0 @@ -2964,6 +2982,7 @@ joinStakePool ctx knownPools getPoolStatus apiPoolId (ApiT wid) body = do , txTime , txScriptValidity = tx ^. #scriptValidity , txDeposit = W.stakeKeyDeposit pp + , txMetadataSchema = TxMetadataDetailedSchema } where ti :: TimeInterpreter (ExceptT PastHorizonException IO) @@ -3081,7 +3100,8 @@ quitStakePool ctx (ApiT wid) body = do , txTime , txScriptValidity = tx ^. #scriptValidity , txDeposit = W.stakeKeyDeposit pp - } + , txMetadataSchema = TxMetadataDetailedSchema + } where ti :: TimeInterpreter (ExceptT PastHorizonException IO) ti = timeInterpreter (ctx ^. networkLayer) @@ -3338,6 +3358,7 @@ migrateWallet ctx withdrawalType (ApiT wid) postData = do , txTime , txScriptValidity = tx ^. #scriptValidity , txDeposit = W.stakeKeyDeposit pp + , txMetadataSchema = TxMetadataDetailedSchema } where addresses = getApiT . fst <$> view #addresses postData @@ -3794,6 +3815,7 @@ data MkApiTransactionParams = MkApiTransactionParams , txTime :: UTCTime , txScriptValidity :: Maybe W.TxScriptValidity , txDeposit :: Coin + , txMetadataSchema :: TxMetadataSchema } deriving (Eq, Generic, Show) @@ -3845,7 +3867,7 @@ mkApiTransaction timeInterpreter setTimeReference tx = do , withdrawals = mkApiWithdrawal @n <$> Map.toList (tx ^. #txWithdrawals) , mint = mempty -- TODO: ADP-xxx , status = ApiT (tx ^. (#txMeta . #status)) - , metadata = ApiTxMetadata $ ApiT <$> (tx ^. #txMetadata) + , metadata = TxMetadataWithSchema (tx ^. #txMetadataSchema) <$> tx ^. #txMetadata , scriptValidity = ApiT <$> tx ^. #txScriptValidity } diff --git a/lib/core/src/Cardano/Wallet/Api/Types.hs b/lib/core/src/Cardano/Wallet/Api/Types.hs index bf0cf71362a..ae834175c80 100644 --- a/lib/core/src/Cardano/Wallet/Api/Types.hs +++ b/lib/core/src/Cardano/Wallet/Api/Types.hs @@ -482,6 +482,7 @@ import qualified Data.Map as Map import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Data.Text.Read as T +import Cardano.Wallet.Api.Types.SchemaMetadata {------------------------------------------------------------------------------- Styles of Wallets @@ -958,7 +959,7 @@ data ApiMultiDelegationAction data ApiConstructTransactionData (n :: NetworkDiscriminant) = ApiConstructTransactionData { payments :: !(Maybe (ApiPaymentDestination n)) , withdrawal :: !(Maybe ApiWithdrawalPostData) - , metadata :: !(Maybe (ApiT TxMetadata)) + , metadata :: !(Maybe TxMetadataWithSchema) , mintBurn :: !(Maybe (NonEmpty (ApiMintBurnData n))) , delegations :: !(Maybe (NonEmpty ApiMultiDelegationAction)) , validityInterval :: !(Maybe ApiValidityInterval) @@ -1003,7 +1004,7 @@ data PostTransactionOldData (n :: NetworkDiscriminant) = PostTransactionOldData { payments :: !(NonEmpty (ApiTxOutput n)) , passphrase :: !(ApiT (Passphrase "lenient")) , withdrawal :: !(Maybe ApiWithdrawalPostData) - , metadata :: !(Maybe (ApiT TxMetadata)) + , metadata :: !(Maybe TxMetadataWithSchema) , timeToLive :: !(Maybe (Quantity "second" NominalDiffTime)) } deriving (Eq, Generic, Show, Typeable) @@ -1011,7 +1012,7 @@ data PostTransactionOldData (n :: NetworkDiscriminant) = PostTransactionOldData data PostTransactionFeeOldData (n :: NetworkDiscriminant) = PostTransactionFeeOldData { payments :: !(NonEmpty (ApiTxOutput n)) , withdrawal :: !(Maybe ApiWithdrawalPostData) - , metadata :: !(Maybe (ApiT TxMetadata)) + , metadata :: !(Maybe TxMetadataWithSchema ) , timeToLive :: !(Maybe (Quantity "second" NominalDiffTime)) } deriving (Eq, Generic, Show, Typeable) @@ -1155,7 +1156,7 @@ data ApiTransaction (n :: NetworkDiscriminant) = ApiTransaction , withdrawals :: ![ApiWithdrawal n] , mint :: !(ApiT W.TokenMap) , status :: !(ApiT TxStatus) - , metadata :: !ApiTxMetadata + , metadata :: !(Maybe TxMetadataWithSchema) , scriptValidity :: !(Maybe (ApiT TxScriptValidity)) } deriving (Eq, Generic, Show, Typeable) diff --git a/lib/core/src/Cardano/Wallet/Api/Types/SchemaMetadata.hs b/lib/core/src/Cardano/Wallet/Api/Types/SchemaMetadata.hs new file mode 100644 index 00000000000..4aca8ab4b1d --- /dev/null +++ b/lib/core/src/Cardano/Wallet/Api/Types/SchemaMetadata.hs @@ -0,0 +1,69 @@ +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE NoMonomorphismRestriction #-} +{-# LANGUAGE StrictData #-} + +-- | +-- Copyright: © 2018-2022 IOHK +-- License: Apache-2.0 +-- +-- A wrapper around TxMetadata to allow different JSON codecs. (ADP-1596) +-- see https://github.com/input-output-hk/cardano-node/blob/master/cardano-api/src/Cardano/Api/TxMetadata.hs +module Cardano.Wallet.Api.Types.SchemaMetadata where + +import Cardano.Api + ( Error (displayError) + , TxMetadataJsonSchema (TxMetadataJsonDetailedSchema, TxMetadataJsonNoSchema) + , metadataFromJson + , metadataToJson + ) +import Cardano.Wallet.Primitive.Types.Tx +import Control.Applicative + ( liftA2, (<|>) ) +import Control.DeepSeq + ( NFData ) +import Data.Aeson + ( FromJSON (parseJSON), ToJSON (toJSON) ) +import GHC.Generics + ( Generic ) +import Prelude + +-- | a tag to select the json codec +data TxMetadataSchema = TxMetadataNoSchema | TxMetadataDetailedSchema + deriving (Show, Eq, Generic, NFData) + +-- | a wrapper to drive the json codec of metadata +data TxMetadataWithSchema = TxMetadataWithSchema + { -- | how to codec the metadata into json + txMetadataWithSchema_schema :: TxMetadataSchema + , -- | the metadata + txMetadataWithSchema_metadata :: TxMetadata + } + deriving (Show, Eq, Generic, NFData) + +instance ToJSON TxMetadataWithSchema where + toJSON (TxMetadataWithSchema TxMetadataDetailedSchema x) = metadataToJson TxMetadataJsonDetailedSchema x + toJSON (TxMetadataWithSchema TxMetadataNoSchema x) = metadataToJson TxMetadataJsonNoSchema x + +detailedMetadata :: TxMetadata -> TxMetadataWithSchema +detailedMetadata = TxMetadataWithSchema TxMetadataDetailedSchema + +noSchemaMetadata :: TxMetadata -> TxMetadataWithSchema +noSchemaMetadata = TxMetadataWithSchema TxMetadataNoSchema + +instance FromJSON TxMetadataWithSchema where + parseJSON = liftA2 + do (<|>) + do + fmap detailedMetadata + . either (fail . displayError) pure + . metadataFromJson TxMetadataJsonDetailedSchema + do + fmap noSchemaMetadata + . either (fail . displayError) pure + . metadataFromJson TxMetadataJsonNoSchema diff --git a/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs b/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs index 040f4573391..66136a65fd4 100644 --- a/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs +++ b/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs @@ -50,6 +50,7 @@ import Cardano.Mnemonic , entropyToMnemonic , mkEntropy ) +import Cardano.Wallet.Api.Types.SchemaMetadata import Cardano.Wallet.Api ( Api ) import Cardano.Wallet.Api.Types @@ -2159,6 +2160,11 @@ instance Arbitrary (PostTransactionOldData n) where <*> arbitrary <*> arbitrary +instance Arbitrary TxMetadataWithSchema where + arbitrary = TxMetadataWithSchema + <$> elements [TxMetadataNoSchema, TxMetadataDetailedSchema] + <*> arbitrary + instance Arbitrary (ApiConstructTransactionData n) where arbitrary = ApiConstructTransactionData <$> arbitrary diff --git a/lib/shelley/src/Cardano/Wallet/Shelley/Api/Server.hs b/lib/shelley/src/Cardano/Wallet/Shelley/Api/Server.hs index 46c9ee63449..bed1f82e8f3 100644 --- a/lib/shelley/src/Cardano/Wallet/Shelley/Api/Server.hs +++ b/lib/shelley/src/Cardano/Wallet/Shelley/Api/Server.hs @@ -384,8 +384,8 @@ server byron icarus shelley multisig spl ntp = ) ) :<|> liftA2 (\xs ys -> fmap fst $ sortOn snd $ xs ++ ys) - (listWallets byron mkLegacyWallet) - (listWallets icarus mkLegacyWallet) + (listWallets byron mkLegacyWallet) + (listWallets icarus mkLegacyWallet) :<|> (\wid name -> withLegacyLayer wid (byron , putWallet byron mkLegacyWallet wid name) (icarus, putWallet icarus mkLegacyWallet wid name) @@ -468,12 +468,12 @@ server byron icarus shelley multisig spl ntp = (icarus, signTransaction icarus wid tx) ) :<|> (\wid r0 r1 s -> withLegacyLayer wid - (byron , listTransactions byron wid Nothing r0 r1 s) - (icarus, listTransactions icarus wid Nothing r0 r1 s) + (byron , listTransactions byron wid Nothing r0 r1 s False) + (icarus, listTransactions icarus wid Nothing r0 r1 s False) ) :<|> (\wid txid -> withLegacyLayer wid - (byron , getTransaction byron wid txid) - (icarus, getTransaction icarus wid txid) + (byron , getTransaction byron wid False txid) + (icarus, getTransaction icarus wid False txid) ) :<|> (\wid txid -> withLegacyLayer wid (byron , deleteTransaction byron wid txid) From c12cfd0b07ce248b5f3022778a72a7e2c22391b9 Mon Sep 17 00:00:00 2001 From: Paolo Veronelli Date: Tue, 3 May 2022 12:16:16 +0200 Subject: [PATCH 02/12] fix openapi definitions regarding metadata values --- specifications/api/swagger.yaml | 55 ++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/specifications/api/swagger.yaml b/specifications/api/swagger.yaml index 339ae382459..03f0feec47d 100644 --- a/specifications/api/swagger.yaml +++ b/specifications/api/swagger.yaml @@ -1646,19 +1646,32 @@ x-transactionMetadata: &transactionMetadata metadata from chain, be aware that integers may exceed the javascript numeric range, and may need special "bigint" parsing. - type: object - nullable: true - additionalProperties: - $ref: "#/components/schemas/TransactionMetadataValue" + anyOf: + - type: object + title: detailed + nullable: true + additionalProperties: + $ref: "#/components/schemas/TransactionMetadataValue" + example: + 0: { "string": "cardano" } + 1: { "int": 14 } + 2: { "bytes": "2512a00e9653fe49a44a5886202e24d77eeb998f" } + 3: { "list": [ { "int": 14 }, { "int": 42 }, { "string": "1337" } ] } + 4: { "map": [{ "k": { "string": "key" }, "v": { "string": "value" }}, { "k": { "int": 14 }, "v": { "int": 42 } }] } + - type: object + title: no-schema + nullable: true + additionalProperties: + $ref: "#/components/schemas/TransactionMetadataValueNoSchema" + example: + 0: "cardano" + 1: 14 + 3: [14, 42 , "1337" ] + 4: {"key1": "value" , "key2": 42 } + # Note: propertyNames pattern not supported in current OpenAPI version. # propertyNames: # pattern: '^[0-9]+$' - example: - 0: { "string": "cardano" } - 1: { "int": 14 } - 2: { "bytes": "2512a00e9653fe49a44a5886202e24d77eeb998f" } - 3: { "list": [ { "int": 14 }, { "int": 42 }, { "string": "1337" } ] } - 4: { "map": [{ "k": { "string": "key" }, "v": { "string": "value" }}, { "k": { "int": 14 }, "v": { "int": 42 } }] } x-transactionTTL: &transactionTTL description: | @@ -3526,11 +3539,31 @@ components: type: array items: type: object + nullable: true properties: k: $ref: "#/components/schemas/TransactionMetadataValue" v: - $ref: "#/components/schemas/TransactionMetadataValue" + $ref: "#/components/schemas/TransactionMetadataValueDetailed" + + TransactionMetadataValueNoSchema: &TransactionMetadataValueNoSchema + oneOf: + - title: String NS + type: string + maxLength: 64 + + - title: Int NS + type: integer + + - title: List NS + type: array + items: + $ref: "#/components/schemas/TransactionMetadataValueNoSchema" + + - title: Map NS + type: object + additionalProperties: + $ref: "#/components/schemas/TransactionMetadataValueNoSchema" ApiGetSettings: &ApiGetSettings type: object From 1c87adc45a2b94a70ab8386ceefd8e944898f1b7 Mon Sep 17 00:00:00 2001 From: Paolo Veronelli Date: Tue, 3 May 2022 12:16:16 +0200 Subject: [PATCH 03/12] fix TypesSpec to load the new simple-metadata schema --- .gitignore | 2 -- .../test/unit/Cardano/Wallet/Api/TypesSpec.hs | 7 ++++++ specifications/api/swagger.yaml | 25 ++++++++++--------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 0f7f29b5eb7..936999d3853 100644 --- a/.gitignore +++ b/.gitignore @@ -42,8 +42,6 @@ hie.yaml *.faulty.json *.faulty.json lib/shelley/test/data/balanceTx/**/actual -lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.faulty.reencoded.json -lib/core/test/data/Cardano/Wallet/Api/ApiWalletMigrationPostDataTestnet0user.json ### Release scripts output /GENERATED_*.md diff --git a/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs b/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs index 66136a65fd4..e589c36e085 100644 --- a/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs +++ b/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs @@ -2819,6 +2819,7 @@ instance Typeable n => ToSchema (ApiPutAddressesData n) where instance Typeable n => ToSchema (ApiSelectCoinsData n) where declareNamedSchema _ = do addDefinition =<< declareSchemaForDefinition "TransactionMetadataValue" + addDefinition =<< declareSchemaForDefinition "TransactionMetadataValueNoSchema" declareSchemaForDefinition "ApiSelectCoinsData" instance ToSchema (ApiT SmashServer) where @@ -2937,11 +2938,13 @@ instance ToSchema (ApiBytesT 'Base64 SerialisedTx) where instance Typeable n => ToSchema (PostTransactionOldData n) where declareNamedSchema _ = do addDefinition =<< declareSchemaForDefinition "TransactionMetadataValue" + addDefinition =<< declareSchemaForDefinition "TransactionMetadataValueNoSchema" declareSchemaForDefinition "ApiPostTransactionData" instance Typeable n => ToSchema (PostTransactionFeeOldData n) where declareNamedSchema _ = do addDefinition =<< declareSchemaForDefinition "TransactionMetadataValue" + addDefinition =<< declareSchemaForDefinition "TransactionMetadataValueNoSchema" declareSchemaForDefinition "ApiPostTransactionFeeData" instance Typeable n => ToSchema (ApiExternalInput n) where @@ -2953,6 +2956,7 @@ instance Typeable n => ToSchema (ApiBalanceTransactionPostData n) where instance Typeable n => ToSchema (ApiTransaction n) where declareNamedSchema _ = do addDefinition =<< declareSchemaForDefinition "TransactionMetadataValue" + addDefinition =<< declareSchemaForDefinition "TransactionMetadataValueNoSchema" declareSchemaForDefinition "ApiTransaction" instance ToSchema ApiUtxoStatistics where @@ -3051,6 +3055,7 @@ instance ToSchema ApiPostRandomAddressData where instance ToSchema ApiWalletSignData where declareNamedSchema _ = do addDefinition =<< declareSchemaForDefinition "TransactionMetadataValue" + addDefinition =<< declareSchemaForDefinition "TransactionMetadataValueNoSchema" declareSchemaForDefinition "ApiWalletSignData" instance ToSchema ApiPostAccountKeyData where @@ -3097,6 +3102,7 @@ instance ToSchema ApiAssetMintBurn where instance Typeable n => ToSchema (ApiConstructTransactionData n) where declareNamedSchema _ = do addDefinition =<< declareSchemaForDefinition "TransactionMetadataValue" + addDefinition =<< declareSchemaForDefinition "TransactionMetadataValueNoSchema" addDefinition =<< declareSchemaForDefinition "ScriptTemplateValue" declareSchemaForDefinition "ApiConstructTransactionData" @@ -3124,6 +3130,7 @@ instance Typeable n => ToSchema (ApiWithdrawalsGeneral n) where instance Typeable n => ToSchema (ApiDecodedTransaction n) where declareNamedSchema _ = do addDefinition =<< declareSchemaForDefinition "TransactionMetadataValue" + addDefinition =<< declareSchemaForDefinition "TransactionMetadataValueNoSchema" addDefinition =<< declareSchemaForDefinition "ScriptValue" declareSchemaForDefinition "ApiDecodedTransaction" diff --git a/specifications/api/swagger.yaml b/specifications/api/swagger.yaml index 03f0feec47d..e71c66a5cc2 100644 --- a/specifications/api/swagger.yaml +++ b/specifications/api/swagger.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.0 +openapi: 3.0.3 info: title: Cardano Wallet Backend API version: v2022-04-27 @@ -1645,19 +1645,21 @@ x-transactionMetadata: &transactionMetadata requirements. Likewise for `null` or `bool` values. When reading metadata from chain, be aware that integers may exceed the javascript numeric range, and may need special "bigint" parsing. - + + # with oneOf we get errors about the 2 schema being both valid + # anyOf seems broken trying to find properties anyOf: - type: object title: detailed nullable: true additionalProperties: - $ref: "#/components/schemas/TransactionMetadataValue" - example: - 0: { "string": "cardano" } - 1: { "int": 14 } - 2: { "bytes": "2512a00e9653fe49a44a5886202e24d77eeb998f" } - 3: { "list": [ { "int": 14 }, { "int": 42 }, { "string": "1337" } ] } - 4: { "map": [{ "k": { "string": "key" }, "v": { "string": "value" }}, { "k": { "int": 14 }, "v": { "int": 42 } }] } + $ref: "#/components/schemas/TransactionMetadataValue" + example: + 0: { "string": "cardano" } + 1: { "int": 14 } + 2: { "bytes": "2512a00e9653fe49a44a5886202e24d77eeb998f" } + 3: { "list": [ { "int": 14 }, { "int": 42 }, { "string": "1337" } ] } + 4: { "map": [{ "k": { "string": "key" }, "v": { "string": "value" }}, { "k": { "int": 14 }, "v": { "int": 42 } }] } - type: object title: no-schema nullable: true @@ -3544,14 +3546,13 @@ components: k: $ref: "#/components/schemas/TransactionMetadataValue" v: - $ref: "#/components/schemas/TransactionMetadataValueDetailed" + $ref: "#/components/schemas/TransactionMetadataValue" TransactionMetadataValueNoSchema: &TransactionMetadataValueNoSchema oneOf: - title: String NS type: string - maxLength: 64 - + - title: Int NS type: integer From 24026b7b4f06b4b163e7f45b267f1a447bd34303 Mon Sep 17 00:00:00 2001 From: Paolo Veronelli Date: Tue, 3 May 2022 12:16:16 +0200 Subject: [PATCH 04/12] replace golden test for json instance of type ApiTransaction replace golden test for json instance of type ApiTransaction --- .../Wallet/Api/ApiTransactionTestnet0.json | 618 ++++++++++-------- 1 file changed, 358 insertions(+), 260 deletions(-) diff --git a/lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.json b/lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.json index f1b3e124d9a..dcbc7041ce2 100644 --- a/lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.json +++ b/lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.json @@ -1,15 +1,15 @@ { - "seed": -3815467787361906923, + "seed": -5665844516851652607, "samples": [ { - "status": "pending", + "status": "in_ledger", "withdrawals": [], "deposit_taken": { - "quantity": 5, + "quantity": 194, "unit": "lovelace" }, "inputs": [], - "direction": "outgoing", + "direction": "incoming", "collateral_outputs": [ { "address": "", @@ -21,55 +21,49 @@ } ], "outputs": [], - "expires_at": { - "epoch_number": 28790, - "time": "1907-08-09T02:00:00Z", - "absolute_slot_number": 6822296, - "slot_number": 22067 - }, "script_validity": "valid", - "pending_since": { + "id": "660d2c10250f1b73003c127782574c391e4a6547204c204878910f075a663a04", + "amount": { + "quantity": 183, + "unit": "lovelace" + }, + "inserted_at": { "height": { - "quantity": 3994, + "quantity": 31778, "unit": "block" }, - "epoch_number": 32255, - "time": "1872-06-30T04:00:52.046884296075Z", - "absolute_slot_number": 2181304, - "slot_number": 20179 - }, - "id": "6e461f231b411f5c06097e4c55196f03712f79556501762c773e2c545939207a", - "amount": { - "quantity": 216, - "unit": "lovelace" + "epoch_number": 8857, + "time": "1886-07-21T03:20:36.12941466734Z", + "absolute_slot_number": 5879883, + "slot_number": 19309 }, "fee": { - "quantity": 212, + "quantity": 176, "unit": "lovelace" }, "deposit_returned": { - "quantity": 80, + "quantity": 79, "unit": "lovelace" }, "metadata": { - "21": { - "map": [] + "25": { + "bytes": "5412255906796566046a112c6e" } }, "collateral": [], "mint": [ { "asset_name": "546f6b656e41", - "quantity": 9, - "policy_id": "44444444444444444444444444444444444444444444444444444444" + "quantity": 12, + "policy_id": "22222222222222222222222222222222222222222222222222222222" } ] }, { - "status": "expired", + "status": "pending", "withdrawals": [], "deposit_taken": { - "quantity": 98, + "quantity": 15, "unit": "lovelace" }, "inputs": [], @@ -77,51 +71,55 @@ "collateral_outputs": [], "outputs": [], "expires_at": { - "epoch_number": 29701, - "time": "1875-08-18T00:37:27Z", - "absolute_slot_number": 2917283, - "slot_number": 11867 + "epoch_number": 29994, + "time": "1873-11-15T17:00:00Z", + "absolute_slot_number": 4170087, + "slot_number": 16703 }, "pending_since": { "height": { - "quantity": 3230, + "quantity": 4227, "unit": "block" }, - "epoch_number": 26902, - "time": "1878-12-31T12:00:00Z", - "absolute_slot_number": 6997214, - "slot_number": 19854 + "epoch_number": 25850, + "time": "1867-09-22T03:07:10Z", + "absolute_slot_number": 6709085, + "slot_number": 3698 }, - "id": "3641503014516a794c0308e04f6f6f053445fa0f1d0e4a98703537554e052436", + "id": "292b491d192cdf645e1b5024406c5e7f1e7f6435505a0b7cff07774715051957", "depth": { - "quantity": 6488, + "quantity": 2269, "unit": "block" }, "amount": { - "quantity": 20, + "quantity": 2, "unit": "lovelace" }, "fee": { - "quantity": 108, + "quantity": 6, "unit": "lovelace" }, "deposit_returned": { - "quantity": 242, + "quantity": 184, "unit": "lovelace" }, - "metadata": null, + "metadata": { + "27": { + "int": 0 + } + }, "collateral": [], "mint": [] }, { - "status": "pending", + "status": "in_ledger", "withdrawals": [], "deposit_taken": { - "quantity": 15, + "quantity": 7, "unit": "lovelace" }, "inputs": [], - "direction": "incoming", + "direction": "outgoing", "collateral_outputs": [ { "address": "", @@ -133,73 +131,77 @@ } ], "outputs": [], - "expires_at": { - "epoch_number": 856, - "time": "1903-07-06T03:52:21Z", - "absolute_slot_number": 15122955, - "slot_number": 29753 - }, "script_validity": "valid", - "pending_since": { - "height": { - "quantity": 20467, - "unit": "block" - }, - "epoch_number": 10256, - "time": "1908-07-17T03:32:37.86921690816Z", - "absolute_slot_number": 9534834, - "slot_number": 11065 - }, - "id": "4b731d0b28698e6f506b16732d495348193d2f1f0245f0470f540b7831337d00", + "id": "706d3333321500725579002f4ead9a75061f581e761e503e104c01307d455274", "depth": { - "quantity": 28478, + "quantity": 8487, "unit": "block" }, "amount": { - "quantity": 158, + "quantity": 18, "unit": "lovelace" }, + "inserted_at": { + "height": { + "quantity": 3331, + "unit": "block" + }, + "epoch_number": 4164, + "time": "1869-05-26T07:00:00Z", + "absolute_slot_number": 11152971, + "slot_number": 26174 + }, "fee": { - "quantity": 99, + "quantity": 2, "unit": "lovelace" }, "deposit_returned": { - "quantity": 182, + "quantity": 246, "unit": "lovelace" }, - "metadata": { - "25": { - "string": "⯔" - } - }, "collateral": [], "mint": [ { "asset_name": "546f6b656e43", - "quantity": 35, + "quantity": 6, "policy_id": "00000000000000000000000000000000000000000000000000000000" }, { - "asset_name": "546f6b656e43", - "quantity": 21, + "asset_name": "546f6b656e45", + "quantity": 8, + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e42", + "quantity": 11, "policy_id": "11111111111111111111111111111111111111111111111111111111" }, { - "asset_name": "546f6b656e43", - "quantity": 21, + "asset_name": "546f6b656e45", + "quantity": 2, "policy_id": "22222222222222222222222222222222222222222222222222222222" + }, + { + "asset_name": "546f6b656e45", + "quantity": 13, + "policy_id": "33333333333333333333333333333333333333333333333333333333" + }, + { + "asset_name": "546f6b656e42", + "quantity": 24, + "policy_id": "44444444444444444444444444444444444444444444444444444444" } ] }, { - "status": "expired", + "status": "in_ledger", "withdrawals": [], "deposit_taken": { - "quantity": 14, + "quantity": 81, "unit": "lovelace" }, "inputs": [], - "direction": "outgoing", + "direction": "incoming", "collateral_outputs": [ { "address": "", @@ -211,52 +213,87 @@ } ], "outputs": [], - "expires_at": { - "epoch_number": 21855, - "time": "1869-01-16T19:00:00Z", - "absolute_slot_number": 16598464, - "slot_number": 29244 - }, - "pending_since": { - "height": { - "quantity": 12214, - "unit": "block" - }, - "epoch_number": 4268, - "time": "1894-07-10T09:36:19.450165945698Z", - "absolute_slot_number": 12029517, - "slot_number": 16945 - }, - "id": "6579a76674582b5bfa15d629471e429d72402c7a2f3039006a2c61775a380f4e", + "id": "03fb562b976f5120320a2b584ca3448e308a327145a74b7c49ff6c976e874d4e", "depth": { - "quantity": 14403, + "quantity": 6915, "unit": "block" }, "amount": { - "quantity": 227, + "quantity": 144, "unit": "lovelace" }, + "inserted_at": { + "height": { + "quantity": 1610, + "unit": "block" + }, + "epoch_number": 15126, + "time": "1874-12-18T02:00:00Z", + "absolute_slot_number": 12434851, + "slot_number": 18454 + }, "fee": { - "quantity": 155, + "quantity": 63, "unit": "lovelace" }, "deposit_returned": { - "quantity": 163, + "quantity": 91, "unit": "lovelace" }, - "metadata": { - "6": { - "int": 0 - } - }, "collateral": [], - "mint": [] + "mint": [ + { + "asset_name": "546f6b656e43", + "quantity": 16, + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e45", + "quantity": 16, + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e41", + "quantity": 10, + "policy_id": "11111111111111111111111111111111111111111111111111111111" + }, + { + "asset_name": "546f6b656e44", + "quantity": 60, + "policy_id": "11111111111111111111111111111111111111111111111111111111" + }, + { + "asset_name": "546f6b656e42", + "quantity": 7, + "policy_id": "22222222222222222222222222222222222222222222222222222222" + }, + { + "asset_name": "546f6b656e43", + "quantity": 10, + "policy_id": "22222222222222222222222222222222222222222222222222222222" + }, + { + "asset_name": "546f6b656e42", + "quantity": 35, + "policy_id": "33333333333333333333333333333333333333333333333333333333" + }, + { + "asset_name": "546f6b656e41", + "quantity": 29, + "policy_id": "44444444444444444444444444444444444444444444444444444444" + }, + { + "asset_name": "546f6b656e44", + "quantity": 28, + "policy_id": "44444444444444444444444444444444444444444444444444444444" + } + ] }, { "status": "expired", "withdrawals": [], "deposit_taken": { - "quantity": 210, + "quantity": 121, "unit": "lovelace" }, "inputs": [], @@ -273,73 +310,82 @@ ], "outputs": [], "expires_at": { - "epoch_number": 12721, - "time": "1898-10-05T23:44:54.375049975696Z", - "absolute_slot_number": 4144861, - "slot_number": 7281 + "epoch_number": 18620, + "time": "1866-01-17T07:24:35.251650169732Z", + "absolute_slot_number": 1508389, + "slot_number": 25178 }, - "script_validity": "invalid", "pending_since": { "height": { - "quantity": 729, + "quantity": 24572, "unit": "block" }, - "epoch_number": 12714, - "time": "1882-06-23T02:11:40Z", - "absolute_slot_number": 10786432, - "slot_number": 14068 + "epoch_number": 26281, + "time": "1867-10-29T02:00:00Z", + "absolute_slot_number": 16760685, + "slot_number": 10001 }, - "id": "082c06487a48ae57e909121a53878a445b6f6e54600f3c113103b3bc296c0941", + "id": "310e276f6d1c513958230d73401cb32873102b41584d0800403119684b672a68", "depth": { - "quantity": 1068, + "quantity": 19922, "unit": "block" }, "amount": { - "quantity": 253, + "quantity": 121, "unit": "lovelace" }, "fee": { - "quantity": 71, + "quantity": 152, "unit": "lovelace" }, "deposit_returned": { - "quantity": 122, + "quantity": 3, "unit": "lovelace" }, "metadata": { - "14": { - "string": "𘠤딡" + "25": { + "map": [ + { + "k": { + "string": "󻐙󿖂𛱗" + }, + "v": { + "int": 2 + } + }, + { + "k": { + "string": "􈓼" + }, + "v": { + "bytes": "0224342058734d4635752a" + } + }, + { + "k": { + "string": "􊋫琱" + }, + "v": { + "bytes": "0676097b015f57713c635671413b576ad80353711d69611e551f18f051508d016d1901390a303e5e387b5cca5853fb68115c962f635c78105f3431b6ca" + } + } + ] } }, "collateral": [], "mint": [ { - "asset_name": "546f6b656e42", - "quantity": 16, - "policy_id": "00000000000000000000000000000000000000000000000000000000" - }, - { - "asset_name": "546f6b656e41", - "quantity": 23, - "policy_id": "11111111111111111111111111111111111111111111111111111111" - }, - { - "asset_name": "546f6b656e45", - "quantity": 2, + "asset_name": "546f6b656e44", + "quantity": 29, "policy_id": "22222222222222222222222222222222222222222222222222222222" - }, - { - "asset_name": "546f6b656e41", - "quantity": 16, - "policy_id": "44444444444444444444444444444444444444444444444444444444" } ] }, { - "status": "expired", + "status": "pending", "withdrawals": [], "deposit_taken": { - "quantity": 59, + "quantity": 163, "unit": "lovelace" }, "inputs": [], @@ -348,7 +394,7 @@ { "address": "", "amount": { - "quantity": 0, + "quantity": 1, "unit": "lovelace" }, "assets": [] @@ -356,58 +402,46 @@ ], "outputs": [], "expires_at": { - "epoch_number": 25929, - "time": "1869-04-23T11:00:00Z", - "absolute_slot_number": 8859446, - "slot_number": 32724 + "epoch_number": 20128, + "time": "1869-12-19T23:29:48Z", + "absolute_slot_number": 2619306, + "slot_number": 8205 }, - "script_validity": "valid", "pending_since": { "height": { - "quantity": 29180, + "quantity": 13611, "unit": "block" }, - "epoch_number": 12996, - "time": "1865-04-29T08:03:27.153067097292Z", - "absolute_slot_number": 10516626, - "slot_number": 5997 + "epoch_number": 26726, + "time": "1869-10-20T00:00:00Z", + "absolute_slot_number": 6283416, + "slot_number": 29584 }, - "id": "4094417024723600505a7cc217414e5934285afa161701096176116553344278", + "id": "6d308d5d53240921793ba964320d7c40583ea90616592e260b583a6fac7b5345", "amount": { - "quantity": 44, + "quantity": 77, "unit": "lovelace" }, "fee": { - "quantity": 86, + "quantity": 106, "unit": "lovelace" }, "deposit_returned": { - "quantity": 155, + "quantity": 69, "unit": "lovelace" }, - "metadata": { - "25": { - "string": "암" - } - }, "collateral": [], - "mint": [ - { - "asset_name": "546f6b656e44", - "quantity": 25, - "policy_id": "11111111111111111111111111111111111111111111111111111111" - } - ] + "mint": [] }, { - "status": "pending", + "status": "expired", "withdrawals": [], "deposit_taken": { - "quantity": 210, + "quantity": 8, "unit": "lovelace" }, "inputs": [], - "direction": "incoming", + "direction": "outgoing", "collateral_outputs": [ { "address": "", @@ -420,18 +454,29 @@ ], "outputs": [], "expires_at": { - "epoch_number": 11570, - "time": "1894-04-20T19:00:00Z", - "absolute_slot_number": 2153245, - "slot_number": 8201 + "epoch_number": 25513, + "time": "1900-10-08T22:13:30Z", + "absolute_slot_number": 5724601, + "slot_number": 15867 + }, + "script_validity": "invalid", + "pending_since": { + "height": { + "quantity": 16960, + "unit": "block" + }, + "epoch_number": 29647, + "time": "1891-09-07T22:00:00Z", + "absolute_slot_number": 4031945, + "slot_number": 20278 }, - "id": "787f427344690422250023502e6d17f83d500219847c5471823a0c3d337a0547", + "id": "01277b3886038210623c281da62734542649287b1e7a663a9128541b312e52a6", "depth": { - "quantity": 998, + "quantity": 29736, "unit": "block" }, "amount": { - "quantity": 135, + "quantity": 11, "unit": "lovelace" }, "fee": { @@ -439,20 +484,21 @@ "unit": "lovelace" }, "deposit_returned": { - "quantity": 36, + "quantity": 207, "unit": "lovelace" }, "metadata": { - "11": { - "int": 0 - } + "19": [ + 3, + 1 + ] }, "collateral": [], "mint": [ { - "asset_name": "546f6b656e42", - "quantity": 13, - "policy_id": "00000000000000000000000000000000000000000000000000000000" + "asset_name": "546f6b656e44", + "quantity": 15, + "policy_id": "11111111111111111111111111111111111111111111111111111111" } ] }, @@ -460,56 +506,94 @@ "status": "expired", "withdrawals": [], "deposit_taken": { - "quantity": 208, + "quantity": 73, "unit": "lovelace" }, "inputs": [], - "direction": "outgoing", + "direction": "incoming", "collateral_outputs": [], "outputs": [], "expires_at": { - "epoch_number": 18238, - "time": "1878-03-25T10:00:00Z", - "absolute_slot_number": 13569160, - "slot_number": 16996 + "epoch_number": 27988, + "time": "1880-10-21T05:00:00Z", + "absolute_slot_number": 5167480, + "slot_number": 11173 }, "script_validity": "invalid", - "pending_since": { - "height": { - "quantity": 19622, - "unit": "block" - }, - "epoch_number": 6313, - "time": "1889-10-18T21:56:21.058122255785Z", - "absolute_slot_number": 1444498, - "slot_number": 29887 - }, - "id": "592077047756b07e31ed48a43951d77b696002272a1d4e077c194f58350d4b39", + "id": "1ce2ec0b0879062124e824690e1852153e6445081f5178386726e460c57e792c", "depth": { - "quantity": 31724, + "quantity": 14180, "unit": "block" }, "amount": { - "quantity": 19, + "quantity": 32, "unit": "lovelace" }, "fee": { - "quantity": 142, + "quantity": 56, "unit": "lovelace" }, "deposit_returned": { - "quantity": 119, + "quantity": 128, "unit": "lovelace" }, - "metadata": null, + "metadata": { + "29": "0x006d561e0c522f48001b1918350360781453097a952e7ea64903" + }, "collateral": [], - "mint": [] + "mint": [ + { + "asset_name": "546f6b656e41", + "quantity": 22, + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e44", + "quantity": 25, + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e45", + "quantity": 29, + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e44", + "quantity": 11, + "policy_id": "11111111111111111111111111111111111111111111111111111111" + }, + { + "asset_name": "546f6b656e45", + "quantity": 3, + "policy_id": "11111111111111111111111111111111111111111111111111111111" + }, + { + "asset_name": "546f6b656e43", + "quantity": 15, + "policy_id": "22222222222222222222222222222222222222222222222222222222" + }, + { + "asset_name": "546f6b656e41", + "quantity": 39, + "policy_id": "33333333333333333333333333333333333333333333333333333333" + }, + { + "asset_name": "546f6b656e41", + "quantity": 41, + "policy_id": "44444444444444444444444444444444444444444444444444444444" + }, + { + "asset_name": "546f6b656e44", + "quantity": 5, + "policy_id": "44444444444444444444444444444444444444444444444444444444" + } + ] }, { "status": "expired", "withdrawals": [], "deposit_taken": { - "quantity": 137, + "quantity": 250, "unit": "lovelace" }, "inputs": [], @@ -518,7 +602,7 @@ { "address": "", "amount": { - "quantity": 1, + "quantity": 0, "unit": "lovelace" }, "assets": [] @@ -526,120 +610,134 @@ ], "outputs": [], "expires_at": { - "epoch_number": 8098, - "time": "1902-12-22T12:52:31.48455326189Z", - "absolute_slot_number": 7212224, - "slot_number": 5401 + "epoch_number": 30983, + "time": "1895-11-01T20:35:44.891538602237Z", + "absolute_slot_number": 16517332, + "slot_number": 2802 }, "script_validity": "invalid", - "id": "7e6e01554a3789973a1f7dd765b825160924fa004e0a1199531d27ec76006055", + "id": "7c14a1020f495ec75a107842405f2554e53a6967293383fb1fcc1055570f216b", "depth": { - "quantity": 29025, + "quantity": 12244, "unit": "block" }, "amount": { - "quantity": 65, + "quantity": 0, "unit": "lovelace" }, "fee": { - "quantity": 233, + "quantity": 87, "unit": "lovelace" }, "deposit_returned": { - "quantity": 66, + "quantity": 40, "unit": "lovelace" }, - "metadata": null, "collateral": [], "mint": [ { - "asset_name": "546f6b656e41", - "quantity": 22, - "policy_id": "00000000000000000000000000000000000000000000000000000000" + "asset_name": "546f6b656e42", + "quantity": 3, + "policy_id": "11111111111111111111111111111111111111111111111111111111" }, { "asset_name": "546f6b656e43", - "quantity": 28, - "policy_id": "00000000000000000000000000000000000000000000000000000000" + "quantity": 10, + "policy_id": "11111111111111111111111111111111111111111111111111111111" }, { "asset_name": "546f6b656e44", - "quantity": 15, + "quantity": 18, "policy_id": "11111111111111111111111111111111111111111111111111111111" }, { - "asset_name": "546f6b656e44", - "quantity": 22, + "asset_name": "546f6b656e41", + "quantity": 11, "policy_id": "22222222222222222222222222222222222222222222222222222222" }, { - "asset_name": "546f6b656e45", - "quantity": 24, + "asset_name": "546f6b656e42", + "quantity": 30, + "policy_id": "22222222222222222222222222222222222222222222222222222222" + }, + { + "asset_name": "546f6b656e43", + "quantity": 19, "policy_id": "22222222222222222222222222222222222222222222222222222222" }, { "asset_name": "546f6b656e42", - "quantity": 5, + "quantity": 3, "policy_id": "33333333333333333333333333333333333333333333333333333333" }, + { + "asset_name": "546f6b656e41", + "quantity": 4, + "policy_id": "44444444444444444444444444444444444444444444444444444444" + }, { "asset_name": "546f6b656e43", - "quantity": 6, + "quantity": 21, "policy_id": "44444444444444444444444444444444444444444444444444444444" }, { - "asset_name": "546f6b656e44", - "quantity": 1, + "asset_name": "546f6b656e45", + "quantity": 6, "policy_id": "44444444444444444444444444444444444444444444444444444444" } ] }, { - "status": "expired", + "status": "pending", "withdrawals": [], "deposit_taken": { - "quantity": 15, + "quantity": 57, "unit": "lovelace" }, "inputs": [], - "direction": "incoming", - "collateral_outputs": [], + "direction": "outgoing", + "collateral_outputs": [ + { + "address": "", + "amount": { + "quantity": 0, + "unit": "lovelace" + }, + "assets": [] + } + ], "outputs": [], - "expires_at": { - "epoch_number": 22973, - "time": "1868-01-03T13:41:07Z", - "absolute_slot_number": 5060782, - "slot_number": 22317 - }, - "script_validity": "invalid", + "script_validity": "valid", "pending_since": { "height": { - "quantity": 29478, + "quantity": 8121, "unit": "block" }, - "epoch_number": 8434, - "time": "1892-12-11T10:40:46Z", - "absolute_slot_number": 1898385, - "slot_number": 32617 + "epoch_number": 3593, + "time": "1904-08-29T21:39:19.041871294671Z", + "absolute_slot_number": 250771, + "slot_number": 21563 }, - "id": "02fe02315217072c269e76b412482577284a165f4f33d92f7a4b320025d001c0", + "id": "c3dd4e7a7e17773d7654371d14223746f03c51a51b7ee248d139f0496102042a", "depth": { - "quantity": 18280, + "quantity": 17577, "unit": "block" }, "amount": { - "quantity": 217, + "quantity": 23, "unit": "lovelace" }, "fee": { - "quantity": 47, + "quantity": 160, "unit": "lovelace" }, "deposit_returned": { - "quantity": 4, + "quantity": 26, "unit": "lovelace" }, - "metadata": null, + "metadata": { + "13": "0x4d166b6c" + }, "collateral": [], "mint": [] } From a7d9d20c137c3a880f04b7e0d2f17843a87b54f4 Mon Sep 17 00:00:00 2001 From: Paolo Veronelli Date: Tue, 3 May 2022 12:16:16 +0200 Subject: [PATCH 05/12] replace golden test value for transaction cli help --- lib/cli/test/data/Cardano/CLISpec/transaction get --help | 5 ++++- lib/cli/test/data/Cardano/CLISpec/transaction list --help | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/cli/test/data/Cardano/CLISpec/transaction get --help b/lib/cli/test/data/Cardano/CLISpec/transaction get --help index f6616823e7b..36cab7120ca 100644 --- a/lib/cli/test/data/Cardano/CLISpec/transaction get --help +++ b/lib/cli/test/data/Cardano/CLISpec/transaction get --help @@ -1,7 +1,10 @@ -Usage: transaction get [--port INT] WALLET_ID TRANSACTION_ID +Usage: transaction get [--port INT] WALLET_ID TRANSACTION_ID + [--simple-metadata] Get a transaction with specified id. Available options: -h,--help Show this help text --port INT port used for serving the wallet API. (default: 8090) + --simple-metadata output metadata json in no-schema + encoding diff --git a/lib/cli/test/data/Cardano/CLISpec/transaction list --help b/lib/cli/test/data/Cardano/CLISpec/transaction list --help index 894cf70feba..00775354138 100644 --- a/lib/cli/test/data/Cardano/CLISpec/transaction list --help +++ b/lib/cli/test/data/Cardano/CLISpec/transaction list --help @@ -1,5 +1,6 @@ Usage: transaction list [--port INT] WALLET_ID [--start TIME] - [--end TIME] [--order ORDER] + [--end TIME] [--order ORDER] + [--simple-metadata] List the transactions associated with a wallet. Available options: @@ -14,3 +15,5 @@ Available options: 2016-11-21T10:15:00Z). --order ORDER specifies a sort order, either 'ascending' or 'descending'. + --simple-metadata output metadata json in no-schema + encoding From 9bc0599277d728769b3aef44bd82baf5448f63f2 Mon Sep 17 00:00:00 2001 From: Paolo Veronelli Date: Tue, 3 May 2022 12:16:16 +0200 Subject: [PATCH 06/12] Merge pull request #3257 from input-output-hk/jonathanknowles/ADP-1596/simple-metadata Fixes for ADP-1596 --- .gitignore | 3 - lib/cli/src/Cardano/CLI.hs | 24 +++---- .../Cardano/CLISpec/transaction get --help | 2 +- .../Cardano/CLISpec/transaction list --help | 4 +- lib/cli/test/unit/Cardano/CLISpec.hs | 19 ++--- .../src/Test/Integration/Framework/DSL.hs | 4 +- .../Scenario/API/Shelley/StakePools.hs | 4 +- .../Scenario/API/Shelley/Transactions.hs | 49 +++++++++---- .../Scenario/API/Shelley/TransactionsNew.hs | 52 +++++++------- .../Scenario/CLI/Shelley/Transactions.hs | 54 ++++++++------ lib/core/src/Cardano/Wallet/Api.hs | 4 +- lib/core/src/Cardano/Wallet/Api/Client.hs | 5 +- lib/core/src/Cardano/Wallet/Api/Link.hs | 14 ++-- lib/core/src/Cardano/Wallet/Api/Server.hs | 71 +++++++++++-------- lib/core/src/Cardano/Wallet/Api/Types.hs | 3 +- .../Wallet/Api/Types/SchemaMetadata.hs | 41 ++++++----- .../test/unit/Cardano/Wallet/Api/TypesSpec.hs | 7 +- lib/shelley/bench/latency-bench.hs | 7 +- .../stack-nix/cardano-wallet-core.nix | 1 + 19 files changed, 210 insertions(+), 158 deletions(-) diff --git a/.gitignore b/.gitignore index 936999d3853..f02fd512172 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,3 @@ lib/shelley/test/data/balanceTx/**/actual ### Docs build /_build/ .vscode/settings.json - - - diff --git a/lib/cli/src/Cardano/CLI.hs b/lib/cli/src/Cardano/CLI.hs index dbbac6ec981..57108c63c31 100644 --- a/lib/cli/src/Cardano/CLI.hs +++ b/lib/cli/src/Cardano/CLI.hs @@ -162,6 +162,8 @@ import Cardano.Wallet.Api.Types , WalletPutPassphraseData (..) , fmtAllowedWords ) +import Cardano.Wallet.Api.Types.SchemaMetadata + ( TxMetadataWithSchema ) import Cardano.Wallet.Orphans () import Cardano.Wallet.Primitive.AddressDerivation @@ -324,8 +326,6 @@ import UnliftIO.Exception import qualified Cardano.BM.Configuration.Model as CM import qualified Cardano.BM.Data.BackendKind as CM import qualified Cardano.BM.Data.Observable as Obs -import Cardano.Wallet.Api.Types.SchemaMetadata - ( TxMetadataWithSchema ) import qualified Command.Key as Key import qualified Command.RecoveryPhrase as RecoveryPhrase import qualified Data.Aeson as Aeson @@ -733,9 +733,9 @@ data TransactionFeatures = NoShelleyFeatures | ShelleyFeatures -- | which json schema to use for output, True is simple metadataSchemaOption :: Parser Bool -metadataSchemaOption = switch +metadataSchemaOption = switch do long "simple-metadata" - <> help "output metadata json in no-schema encoding" + <> help "output metadata json in no-schema encoding" -- | cardano-wallet transaction cmdTransaction @@ -869,8 +869,10 @@ cmdTransactionList mkTxClient = <*> optional timeRangeStartOption <*> optional timeRangeEndOption <*> optional sortOrderOption - <*> metadataSchemaOption - exec (TransactionListArgs wPort wId mTimeRangeStart mTimeRangeEnd mOrder metadataSchema) = + <*> metadataSchemaOption + exec + (TransactionListArgs + wPort wId mTimeRangeStart mTimeRangeEnd mOrder metadataSchema) = runClient wPort Aeson.encodePretty $ listTransactions mkTxClient (ApiT wId) @@ -940,16 +942,14 @@ cmdTransactionGet mkClient = cmd = fmap exec $ TransactionGetArgs <$> portOption <*> walletIdArgument - <*> transactionIdArgument - <*> metadataSchemaOption + <*> transactionIdArgument + <*> metadataSchemaOption exec (TransactionGetArgs wPort wId txId metadataSchema ) = do runClient wPort Aeson.encodePretty $ getTransaction mkClient (ApiT wId) - metadataSchema + metadataSchema (ApiTxId $ ApiT $ getTxId txId) - - {------------------------------------------------------------------------------- Commands - 'address' -------------------------------------------------------------------------------} @@ -1455,7 +1455,7 @@ metadataOption :: Parser (Maybe TxMetadataWithSchema) metadataOption = option txMetadataReader $ mempty <> long "metadata" <> metavar "JSON" - <> value Nothing + <> value Nothing <> help ("Application-specific transaction metadata as a JSON object. " <> "The value must match the schema defined in the " <> "cardano-wallet OpenAPI specification.") diff --git a/lib/cli/test/data/Cardano/CLISpec/transaction get --help b/lib/cli/test/data/Cardano/CLISpec/transaction get --help index 36cab7120ca..d551f59bf4e 100644 --- a/lib/cli/test/data/Cardano/CLISpec/transaction get --help +++ b/lib/cli/test/data/Cardano/CLISpec/transaction get --help @@ -1,4 +1,4 @@ -Usage: transaction get [--port INT] WALLET_ID TRANSACTION_ID +Usage: transaction get [--port INT] WALLET_ID TRANSACTION_ID [--simple-metadata] Get a transaction with specified id. diff --git a/lib/cli/test/data/Cardano/CLISpec/transaction list --help b/lib/cli/test/data/Cardano/CLISpec/transaction list --help index 00775354138..033ea69b0ff 100644 --- a/lib/cli/test/data/Cardano/CLISpec/transaction list --help +++ b/lib/cli/test/data/Cardano/CLISpec/transaction list --help @@ -1,5 +1,5 @@ -Usage: transaction list [--port INT] WALLET_ID [--start TIME] - [--end TIME] [--order ORDER] +Usage: transaction list [--port INT] WALLET_ID [--start TIME] + [--end TIME] [--order ORDER] [--simple-metadata] List the transactions associated with a wallet. diff --git a/lib/cli/test/unit/Cardano/CLISpec.hs b/lib/cli/test/unit/Cardano/CLISpec.hs index a003d8b00f1..873381b474c 100644 --- a/lib/cli/test/unit/Cardano/CLISpec.hs +++ b/lib/cli/test/unit/Cardano/CLISpec.hs @@ -40,6 +40,8 @@ import Cardano.Wallet.Api.Client , transactionClient , walletClient ) +import Cardano.Wallet.Api.Types.SchemaMetadata + ( detailedMetadata, noSchemaMetadata ) import Cardano.Wallet.Primitive.Types ( PoolMetadataSource ) import Cardano.Wallet.Primitive.Types.Tx @@ -98,8 +100,6 @@ import UnliftIO.MVar import UnliftIO.Temporary ( withSystemTempDirectory ) -import Cardano.Wallet.Api.Types.SchemaMetadata - ( detailedMetadata, noSchemaMetadata ) import qualified Data.Map as Map import qualified Data.Text as T import qualified Data.Text.IO as TIO @@ -255,7 +255,8 @@ spec = do describe "Tx Metadata JSON option" $ do let parse arg = execParserPure defaultPrefs (info metadataOption mempty) ["--metadata", arg] - let md = detailedMetadata (TxMetadata (Map.singleton 42 (TxMetaText "hi"))) + let md = detailedMetadata + (TxMetadata (Map.singleton 42 (TxMetaText "hi"))) let ok ex (Success res) = ex == res ok _ _ = False let err (Failure _) = True @@ -271,8 +272,10 @@ spec = do , ("null 3", "{ }", ok (Just (detailedMetadata mempty))) ] describe "Tx No-Schema Metadata JSON option" $ do - let parse arg = execParserPure defaultPrefs (info metadataOption mempty) ["--metadata", arg] - let md = noSchemaMetadata (TxMetadata (Map.singleton 42 (TxMetaText "hi"))) + let parse arg = execParserPure + defaultPrefs (info metadataOption mempty) ["--metadata", arg] + let md = noSchemaMetadata + (TxMetadata (Map.singleton 42 (TxMetaText "hi"))) let ok ex (Success res) = ex == res ok _ _ = False let err (Failure _) = True @@ -285,10 +288,10 @@ spec = do , ("invalid", "{ \"json\": true }", err) , ("null 1", "{ \"0\": null }", err) , ("null 2", "null", ok Nothing) - , ("null 3", "{ }", ok $ Just $ detailedMetadata mempty) -- this is the default parsing success - ] + -- this is the default parsing success: + , ("null 3", "{ }", ok $ Just $ detailedMetadata mempty) - + ] describe "Tx TTL option" $ do let parse arg = execParserPure defaultPrefs diff --git a/lib/core-integration/src/Test/Integration/Framework/DSL.hs b/lib/core-integration/src/Test/Integration/Framework/DSL.hs index c9ea76225f8..b63169f19a9 100644 --- a/lib/core-integration/src/Test/Integration/Framework/DSL.hs +++ b/lib/core-integration/src/Test/Integration/Framework/DSL.hs @@ -2803,7 +2803,7 @@ postTransactionFeeViaCLI ctx args = cardanoWalletCLI $ join listTransactionsViaCLI :: forall r s m. (CmdResult r, HasType (Port "wallet") s, MonadIO m) => s - -> Bool + -> Bool -> [String] -> m r listTransactionsViaCLI ctx metadataSchema args = cardanoWalletCLI $ join @@ -2840,7 +2840,7 @@ getTransactionViaCLI => s -> String -> String - -> Bool + -> Bool -> m r getTransactionViaCLI ctx wid tid metadataSchema = cardanoWalletCLI $ join [ ["transaction", "get"] diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/StakePools.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/StakePools.hs index e1c89918b5c..30f52611ef7 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/StakePools.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/StakePools.hs @@ -83,6 +83,8 @@ import Data.Text ( Text ) import Data.Text.Class ( showT, toText ) +import Data.Tuple.Extra + ( both ) import Numeric.Natural ( Natural ) import Test.Hspec @@ -154,8 +156,6 @@ import qualified Cardano.Wallet.Api.Link as Link import qualified Data.ByteString as BS import qualified Data.Set as Set import qualified Data.Text as T -import Data.Tuple.Extra - ( both ) import qualified Network.HTTP.Types.Status as HTTP spec :: forall n. diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Transactions.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Transactions.hs index d42a5887bd3..e80cf81b6fb 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Transactions.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Transactions.hs @@ -40,6 +40,8 @@ import Cardano.Wallet.Api.Types , insertedAt , pendingSince ) +import Cardano.Wallet.Api.Types.SchemaMetadata + ( detailedMetadata ) import Cardano.Wallet.Primitive.AddressDerivation ( PaymentAddress ) import Cardano.Wallet.Primitive.AddressDerivation.Icarus @@ -179,7 +181,6 @@ import qualified Data.List.NonEmpty as NE import qualified Data.Map as Map import qualified Data.Text as T import qualified Network.HTTP.Types.Status as HTTP -import Cardano.Wallet.Api.Types.SchemaMetadata (detailedMetadata) data TestCase a = TestCase { query :: T.Text @@ -958,7 +959,10 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do } ] - it "TRANSMETA_CREATE_02a - Transaction with invalid metadata" $ \ctx -> runResourceT $ do + it "TRANSMETA_CREATE_02a - \ + \Transaction with invalid metadata" $ + \ctx -> runResourceT $ do + (wa, wb) <- (,) <$> fixtureWallet ctx <*> fixtureWallet ctx let amt = minUTxOValue (_mainEra ctx) :: Natural @@ -972,8 +976,11 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do expectResponseCode HTTP.status400 r expectErrorMessage errMsg400TxMetadataStringTooLong r - - it "TRANSMETA_CREATE_02b - Transaction with invalid no-schema metadata" $ \ctx -> runResourceT $ do + + it "TRANSMETA_CREATE_02b - \ + \Transaction with invalid no-schema metadata" $ + \ctx -> runResourceT $ do + (wa, wb) <- (,) <$> fixtureWallet ctx <*> fixtureWallet ctx let amt = minUTxOValue (_mainEra ctx) :: Natural @@ -989,7 +996,6 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do Default payload - expectResponseCode HTTP.status400 r expectErrorMessage errMsg400TxMetadataStringTooLong r @@ -1013,7 +1019,10 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do expectResponseCode HTTP.status403 r expectErrorMessage errMsg403TxTooBig r - it "TRANSMETA_ESTIMATE_01a - fee estimation includes metadata" $ \ctx -> runResourceT $ do + it "TRANSMETA_ESTIMATE_01a - \ + \fee estimation includes metadata" $ + \ctx -> runResourceT $ do + (wa, wb) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx let amt = minUTxOValue (_mainEra ctx) :: Natural @@ -1041,7 +1050,10 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do , expectField (#estimatedMax . #getQuantity) (.< feeEstMax) ] - it "TRANSMETA_ESTIMATE_01b - fee estimation includes no-schema metadata" $ \ctx -> runResourceT $ do + it "TRANSMETA_ESTIMATE_01b - \ + \fee estimation includes no-schema metadata" $ + \ctx -> runResourceT $ do + (wa, wb) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx let amt = minUTxOValue (_mainEra ctx) :: Natural @@ -1079,7 +1091,10 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do , expectField (#estimatedMax . #getQuantity) (.< feeEstMax) ] - it "TRANSMETA_ESTIMATE_02a - fee estimation with invalid metadata" $ \ctx -> runResourceT $ do + it "TRANSMETA_ESTIMATE_02a - \ + \fee estimation with invalid metadata" $ + \ctx -> runResourceT $ do + (wa, wb) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx let amt = minUTxOValue (_mainEra ctx) :: Natural @@ -1093,8 +1108,11 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do expectResponseCode HTTP.status400 r expectErrorMessage errMsg400TxMetadataStringTooLong r - - it "TRANSMETA_ESTIMATE_02b - fee estimation with invalid no-schema metadata" $ \ctx -> runResourceT $ do + + it "TRANSMETA_ESTIMATE_02b - \ + \fee estimation with invalid no-schema metadata" $ + \ctx -> runResourceT $ do + (wa, wb) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx let amt = minUTxOValue (_mainEra ctx) :: Natural @@ -1685,7 +1703,8 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do eventually "Transactions are available and in ledger" $ do -- Verify Tx in source wallet is Outgoing and InLedger - let linkSrc = Link.getTransaction @'Shelley wSrc (ApiTxId txid) False + let linkSrc = Link.getTransaction @'Shelley + wSrc (ApiTxId txid) False r1 <- request @(ApiTransaction n) ctx linkSrc Default Empty verify r1 [ expectResponseCode HTTP.status200 @@ -1694,7 +1713,8 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do ] -- Verify Tx in destination wallet is Incoming and InLedger - let linkDest = Link.getTransaction @'Shelley wDest (ApiTxId txid) False + let linkDest = Link.getTransaction + @'Shelley wDest (ApiTxId txid) False r2 <- request @(ApiTransaction n) ctx linkDest Default Empty verify r2 [ expectResponseCode HTTP.status200 @@ -1727,7 +1747,8 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do ] let txid = Hash $ BS.pack $ replicate 32 1 - let link = Link.getTransaction @'Shelley wSrc (ApiTxId $ ApiT txid) False + let link = Link.getTransaction @'Shelley + wSrc (ApiTxId $ ApiT txid) False r <- request @(ApiTransaction n) ctx link Default Empty expectResponseCode HTTP.status404 r expectErrorMessage (errMsg404CannotFindTx $ toText txid) r @@ -1908,7 +1929,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do eventually "withdrawal transaction is listed on other" $ do rTxOther <- request @(ApiTransaction n) ctx - (Link.getTransaction @'Shelley wOther tid False) Default payload + (Link.getTransaction @'Shelley wOther tid False) Default payload verify rTxOther [ expectResponseCode HTTP.status200 diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs index c33bac869de..b1f106d1ee1 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs @@ -306,15 +306,13 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do signedTx <- signTx ctx wa apiTx [ expectResponseCode HTTP.status202 ] -- Check for the presence of metadata on signed transaction - let - getMetadata (InAnyCardanoEra _ tx) = Cardano.getTxBody tx - & (\(Cardano.TxBody bodyContent) -> - Cardano.txMetadata bodyContent - & \case Cardano.TxMetadataNone -> - Nothing - Cardano.TxMetadataInEra _ (Cardano.TxMetadata m) -> - Just m - ) + let getMetadata (InAnyCardanoEra _ tx) = Cardano.getTxBody tx & + \(Cardano.TxBody bodyContent) -> + Cardano.txMetadata bodyContent & \case + Cardano.TxMetadataNone -> + Nothing + Cardano.TxMetadataInEra _ (Cardano.TxMetadata m) -> + Just m case getMetadata (cardanoTx $ getApiT (signedTx ^. #transaction)) of Nothing -> error "Tx doesn't include metadata" @@ -323,14 +321,17 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do Just (Cardano.TxMetaText "hello") -> pure () Just _ -> error "Tx metadata incorrect" - let txCbor = getFromResponse #transaction (HTTP.status202, Right signedTx) + let txCbor = + getFromResponse #transaction (HTTP.status202, Right signedTx) let decodePayload = Json (toJSON $ ApiSerialisedTransaction txCbor) - let expMetadata = ApiT (TxMetadata (Map.fromList [(1,TxMetaText "hello")])) + let expMetadata = + ApiT (TxMetadata (Map.fromList [(1,TxMetaText "hello")])) rDecodedTx <- request @(ApiDecodedTransaction n) ctx (Link.decodeTransaction @'Shelley wa) Default decodePayload verify rDecodedTx [ expectResponseCode HTTP.status202 - , expectField #metadata (`shouldBe` (ApiTxMetadata (Just expMetadata))) + , expectField #metadata + (`shouldBe` (ApiTxMetadata (Just expMetadata))) ] -- Submit tx @@ -351,7 +352,9 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (`shouldBe` (fromIntegral oneMillionAda - expectedFee)) ] - it "TRANS_NEW_CREATE_02b - Only metadata, untyped" $ \ctx -> runResourceT $ do + it "TRANS_NEW_CREATE_02b - Only metadata, untyped" $ + \ctx -> runResourceT $ do + wa <- fixtureWallet ctx let metadata = Json [json|{ "metadata": { "1": "hello" } }|] @@ -368,15 +371,13 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do signedTx <- signTx ctx wa apiTx [ expectResponseCode HTTP.status202 ] -- Check for the presence of metadata on signed transaction - let - getMetadata (InAnyCardanoEra _ tx) = Cardano.getTxBody tx - & (\(Cardano.TxBody bodyContent) -> - Cardano.txMetadata bodyContent - & \case Cardano.TxMetadataNone -> - Nothing - Cardano.TxMetadataInEra _ (Cardano.TxMetadata m) -> - Just m - ) + let getMetadata (InAnyCardanoEra _ tx) = Cardano.getTxBody tx & + \(Cardano.TxBody bodyContent) -> + Cardano.txMetadata bodyContent & \case + Cardano.TxMetadataNone -> + Nothing + Cardano.TxMetadataInEra _ (Cardano.TxMetadata m) -> + Just m case getMetadata (cardanoTx $ getApiT (signedTx ^. #transaction)) of Nothing -> error "Tx doesn't include metadata" @@ -385,7 +386,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do Just (Cardano.TxMetaText "hello") -> pure () Just _ -> error "Tx metadata incorrect" - let txCbor = getFromResponse #transaction (HTTP.status202, Right signedTx) + let txCbor = + getFromResponse #transaction (HTTP.status202, Right signedTx) let decodePayload = Json (toJSON $ ApiSerialisedTransaction txCbor) let expMetadata = ApiT (TxMetadata (Map.fromList [(1,TxMetaText "hello")])) rDecodedTx <- request @(ApiDecodedTransaction n) ctx @@ -409,8 +411,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do verify rWa [ expectSuccess , expectField - (#balance . #available . #getQuantity) - (`shouldBe` (fromIntegral oneMillionAda - expectedFee)) + (#balance . #available . #getQuantity) + (`shouldBe` (fromIntegral oneMillionAda - expectedFee)) ] it "TRANS_NEW_CREATE_03a - Withdrawal from self, 0 rewards" $ \ctx -> runResourceT $ do diff --git a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Transactions.hs b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Transactions.hs index 56a692cc1b7..67bf87774bb 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Transactions.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Transactions.hs @@ -25,12 +25,12 @@ import Cardano.Wallet.Api.Types , EncodeAddress (..) , getApiT ) +import Cardano.Wallet.Api.Types.SchemaMetadata + ( detailedMetadata, noSchemaMetadata ) import Cardano.Wallet.Primitive.Types ( SortOrder (..) ) import Cardano.Wallet.Primitive.Types.Tx ( Direction (..), TxMetadata (..), TxMetadataValue (..), TxStatus (..) ) -import Cardano.Wallet.Api.Types.SchemaMetadata - ( detailedMetadata, noSchemaMetadata ) import Control.Monad ( forM_, join ) import Control.Monad.IO.Class @@ -114,6 +114,7 @@ import Test.Integration.Framework.TestData ) import UnliftIO.Exception ( throwString ) + import qualified Data.Map as Map import qualified Data.Text as T @@ -318,7 +319,10 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do out `shouldBe` "" c `shouldBe` ExitFailure 1 - it "TRANSMETA_CREATE_01a - Transaction with metadata via CLI" $ \ctx -> runResourceT $ do + it "TRANSMETA_CREATE_01a - \ + \Transaction with metadata via CLI" $ + \ctx -> runResourceT $ do + (wSrc, wDest) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx let amt = 10_000_000 let md = Just "{ \"1\": { \"string\": \"hello\" } }" @@ -351,10 +355,15 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do verify outJson [ expectCliListField 0 #metadata (`shouldBe` expected) - , expectCliListField 0 (#status . #getApiT) (`shouldBe` InLedger) + , expectCliListField 0 + (#status . #getApiT) + (`shouldBe` InLedger) ] - it "TRANSMETA_CREATE_01b - Transaction with metadata via CLI with simple metadata" $ \ctx -> runResourceT $ do + it "TRANSMETA_CREATE_01b - \ + \Transaction with metadata via CLI with simple metadata" $ + \ctx -> runResourceT $ do + (wSrc, wDest) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx let amt = 10_000_000 let md = Just "{ \"1\": { \"string\": \"hello\" } }" @@ -365,7 +374,8 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do args <- postTxArgs ctx wSrc wDest amt md Nothing Stdout feeOut <- postTransactionFeeViaCLI ctx args - ApiFee (Quantity feeMin) (Quantity feeMax) _ _ <- expectValidJSON Proxy feeOut + ApiFee (Quantity feeMin) (Quantity feeMax) _ _ <- + expectValidJSON Proxy feeOut txJson <- postTxViaCLI ctx wSrc wDest amt md Nothing verify txJson @@ -380,7 +390,8 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do let wSrcId = T.unpack (wSrc ^. walletId) let txId = getTxId txJson - (Exit code, Stdout out, Stderr err) <- getTransactionViaCLI ctx wSrcId txId True + (Exit code, Stdout out, Stderr err) <- + getTransactionViaCLI ctx wSrcId txId True err `shouldBe` "Ok.\n" code `shouldBe` ExitSuccess outJson <- expectValidJSON (Proxy @(ApiTransaction n)) out @@ -408,9 +419,6 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do , expectCliListField 0 (#status . #getApiT) (`shouldBe` InLedger) ] - - - it "TRANSTTL_CREATE_01 - Transaction with TTL via CLI" $ \ctx -> runResourceT $ do (wSrc, wDest) <- (,) <$> fixtureWallet ctx <*> emptyWallet ctx let amt = 10_000_000 @@ -656,7 +664,8 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do describe "TRANS_LIST_04 - False wallet ids" $ do forM_ falseWalletIds $ \(title, walId) -> it title $ \ctx -> runResourceT $ do - (Exit c, Stdout o, Stderr e) <- listTransactionsViaCLI ctx False [walId] + (Exit c, Stdout o, Stderr e) <- + listTransactionsViaCLI ctx False [walId] o `shouldBe` "" c `shouldBe` ExitFailure 1 if (title == "40 chars hex") then @@ -677,13 +686,13 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do [ "--start", utcIso8601ToText t1 , "--end", utcIso8601ToText t2 ] - Stdout o1 <- listTransactionsViaCLI ctx False + Stdout o1 <- listTransactionsViaCLI ctx False ( T.unpack <$> walId : (query t t) ) - Stdout o2 <- listTransactionsViaCLI ctx False + Stdout o2 <- listTransactionsViaCLI ctx False ( T.unpack <$> walId : (query te t) ) - Stdout o3 <- listTransactionsViaCLI ctx False + Stdout o3 <- listTransactionsViaCLI ctx False ( T.unpack <$> walId : (query t tl) ) - Stdout o4 <- listTransactionsViaCLI ctx False + Stdout o4 <- listTransactionsViaCLI ctx False ( T.unpack <$> walId : (query te tl) ) oJson1 <- expectValidJSON (Proxy @([ApiTransaction n])) o1 oJson2 <- expectValidJSON (Proxy @([ApiTransaction n])) o2 @@ -698,9 +707,9 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do let walId = w ^. walletId t <- unsafeGetTransactionTime =<< listAllTransactions @n ctx w let tl = utcIso8601ToText $ utcTimeSucc t - Stdout o1 <- listTransactionsViaCLI ctx False + Stdout o1 <- listTransactionsViaCLI ctx False ( T.unpack <$> [walId, "--start", tl] ) - Stdout o2 <- listTransactionsViaCLI ctx False + Stdout o2 <- listTransactionsViaCLI ctx False ( T.unpack <$> [walId, "--start", tl, "--end", tl] ) oJson1 <- expectValidJSON (Proxy @([ApiTransaction n])) o1 oJson2 <- expectValidJSON (Proxy @([ApiTransaction n])) o2 @@ -713,9 +722,9 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do let walId = w ^. walletId t <- unsafeGetTransactionTime =<< listAllTransactions @n ctx w let te = utcIso8601ToText $ utcTimePred t - Stdout o1 <- listTransactionsViaCLI ctx False + Stdout o1 <- listTransactionsViaCLI ctx False ( T.unpack <$> [walId, "--end", te] ) - Stdout o2 <- listTransactionsViaCLI ctx False + Stdout o2 <- listTransactionsViaCLI ctx False ( T.unpack <$> [walId, "--start", te, "--end", te] ) oJson1 <- expectValidJSON (Proxy @([ApiTransaction n])) o1 oJson2 <- expectValidJSON (Proxy @([ApiTransaction n])) o2 @@ -757,7 +766,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do -- Verify Tx in source wallet is Outgoing and InLedger (Exit code1, Stdout out1, Stderr err1) <- - getTransactionViaCLI ctx wSrcId txId False + getTransactionViaCLI ctx wSrcId txId False err1 `shouldBe` "Ok.\n" code1 `shouldBe` ExitSuccess outJson1 <- expectValidJSON (Proxy @(ApiTransaction n)) out1 @@ -769,7 +778,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do let wDestId = T.unpack (wDest ^. walletId) -- Verify Tx in destination wallet is Incoming and InLedger (Exit code2, Stdout out2, Stderr err2) <- - getTransactionViaCLI ctx wDestId txId False + getTransactionViaCLI ctx wDestId txId False err2 `shouldBe` "Ok.\n" code2 `shouldBe` ExitSuccess outJson2 <- expectValidJSON (Proxy @(ApiTransaction n)) out2 @@ -810,7 +819,8 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do let wid = T.unpack (wSrc ^. walletId) let txId = "3e6ec12da4414aa0781ff8afa9717ae53ee8cb4aa55d622f65bc62619a4f7b12" - (Exit c2, Stdout o2, Stderr e2) <- getTransactionViaCLI ctx wid txId False + (Exit c2, Stdout o2, Stderr e2) <- + getTransactionViaCLI ctx wid txId False e2 `shouldContain` errMsg404CannotFindTx (T.pack txId) o2 `shouldBe` mempty c2 `shouldBe` ExitFailure 1 diff --git a/lib/core/src/Cardano/Wallet/Api.hs b/lib/core/src/Cardano/Wallet/Api.hs index ec77195c3e7..f7cd74bd87e 100644 --- a/lib/core/src/Cardano/Wallet/Api.hs +++ b/lib/core/src/Cardano/Wallet/Api.hs @@ -584,14 +584,14 @@ type ListTransactions n = "wallets" :> QueryParam "start" Iso8601Time :> QueryParam "end" Iso8601Time :> QueryParam "order" (ApiT SortOrder) - :> QueryFlag "simple-metadata" + :> QueryFlag "simple-metadata" :> Get '[JSON] [ApiTransactionT n] -- | https://input-output-hk.github.io/cardano-wallet/api/#operation/getTransaction type GetTransaction n = "wallets" :> Capture "walletId" (ApiT WalletId) :> "transactions" - :> QueryFlag "simple-metadata" + :> QueryFlag "simple-metadata" :> Capture "transactionId" ApiTxId :> Get '[JSON] (ApiTransactionT n) diff --git a/lib/core/src/Cardano/Wallet/Api/Client.hs b/lib/core/src/Cardano/Wallet/Api/Client.hs index 959ea140b60..020fd8bc1f9 100644 --- a/lib/core/src/Cardano/Wallet/Api/Client.hs +++ b/lib/core/src/Cardano/Wallet/Api/Client.hs @@ -163,7 +163,7 @@ data TransactionClient = TransactionClient -> Maybe Iso8601Time -> Maybe Iso8601Time -> Maybe (ApiT SortOrder) - -> Bool + -> Bool -> ClientM [ApiTransactionT Aeson.Value] , signTransaction :: ApiT WalletId @@ -363,7 +363,8 @@ byronTransactionClient = = client (Proxy @("v2" :> Proxy_)) in TransactionClient - { listTransactions = \wid start end order _ -> _listTransactions wid start end order + { listTransactions = \wid start end order _ -> + _listTransactions wid start end order , signTransaction = _signTransaction , postTransaction = _postTransaction , postTransactionFee = _postTransactionFee diff --git a/lib/core/src/Cardano/Wallet/Api/Link.hs b/lib/core/src/Cardano/Wallet/Api/Link.hs index a30d99da740..2ccc15d2298 100644 --- a/lib/core/src/Cardano/Wallet/Api/Link.hs +++ b/lib/core/src/Cardano/Wallet/Api/Link.hs @@ -627,13 +627,13 @@ listTransactions' listTransactions' w minWithdrawal inf sup order = discriminate @style (endpoint @(Api.ListTransactions Net) (\mk -> mk - wid - (MinWithdrawal <$> minWithdrawal) - inf - sup + wid + (MinWithdrawal <$> minWithdrawal) + inf + sup (ApiT <$> order) False - ) + ) ) (endpoint @(Api.ListByronTransactions Net) (\mk -> mk wid inf sup (ApiT <$> order))) @@ -696,9 +696,7 @@ getTransaction w t s = discriminate @style mkByronURL mk = mk wid tid mkShelleyURL :: (ApiT WalletId -> Bool -> ApiTxId -> Text) -> Text - mkShelleyURL mk = mk wid s tid - - + mkShelleyURL mk = mk wid s tid createUnsignedTransaction :: forall style w. diff --git a/lib/core/src/Cardano/Wallet/Api/Server.hs b/lib/core/src/Cardano/Wallet/Api/Server.hs index 73d377880ad..4781f5ab175 100644 --- a/lib/core/src/Cardano/Wallet/Api/Server.hs +++ b/lib/core/src/Cardano/Wallet/Api/Server.hs @@ -1,4 +1,5 @@ {-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE BlockArguments #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} @@ -15,7 +16,6 @@ {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} -{-# LANGUAGE BlockArguments #-} -- | -- Copyright: © 2018-2020 IOHK @@ -331,6 +331,10 @@ import Cardano.Wallet.Api.Types , toApiNetworkParameters , toApiUtxoStatistics ) +import Cardano.Wallet.Api.Types.SchemaMetadata + ( TxMetadataSchema (TxMetadataDetailedSchema, TxMetadataNoSchema) + , TxMetadataWithSchema (TxMetadataWithSchema) + ) import Cardano.Wallet.CoinSelection ( SelectionBalanceError (..) , SelectionCollateralError @@ -684,7 +688,6 @@ import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Network.Wai.Handler.Warp as Warp import qualified Network.Wai.Handler.WarpTLS as Warp -import Cardano.Wallet.Api.Types.SchemaMetadata (TxMetadataWithSchema(TxMetadataWithSchema), TxMetadataSchema (TxMetadataDetailedSchema, TxMetadataNoSchema)) -- | How the server should listen for incoming requests. data Listen @@ -2004,7 +2007,7 @@ postTransactionOld postTransactionOld ctx genChange (ApiT wid) body = do let pwd = coerce $ body ^. #passphrase . #getApiT let outs = addressAmountToTxOut <$> body ^. #payments - let md = body ^? #metadata . traverse . #txMetadataWithSchema_metadata + let md = body ^? #metadata . traverse . #txMetadataWithSchema_metadata let mTTL = body ^? #timeToLive . traverse . #getQuantity (wdrl, mkRwdAcct) <- @@ -2082,12 +2085,12 @@ deleteTransaction ctx (ApiT wid) (ApiTxId (ApiT (tid))) = do listTransactions :: forall ctx s k n. (ctx ~ ApiLayer s k) - => ctx -- ^ - -> ApiT WalletId -- ^ - -> Maybe MinWithdrawal -- ^ - -> Maybe Iso8601Time -- ^ - -> Maybe Iso8601Time -- ^ - -> Maybe (ApiT SortOrder) -- ^ + => ctx -- ^ + -> ApiT WalletId -- ^ + -> Maybe MinWithdrawal -- ^ + -> Maybe Iso8601Time -- ^ + -> Maybe Iso8601Time -- ^ + -> Maybe (ApiT SortOrder) -- ^ -> Bool -- ^ metadata json schema -> Handler [ApiTransaction n] listTransactions ctx (ApiT wid) mMinWithdrawal mStart mEnd mOrder metadataSchema = do @@ -2100,15 +2103,15 @@ listTransactions ctx (ApiT wid) mMinWithdrawal mStart mEnd mOrder metadataSchema (maybe defaultSortOrder getApiT mOrder) depo <- liftIO $ W.stakeKeyDeposit <$> NW.currentProtocolParameters (wrk ^. networkLayer) pure (txs, depo) - liftIO $ forM txs $ \tx -> - mkApiTransactionFromInfo - (timeInterpreter (ctx ^. networkLayer)) - depo - tx - if metadataSchema - then TxMetadataNoSchema + liftIO $ forM txs $ \tx -> + mkApiTransactionFromInfo + (timeInterpreter (ctx ^. networkLayer)) + depo + tx + if metadataSchema + then TxMetadataNoSchema else TxMetadataDetailedSchema - + where defaultSortOrder :: SortOrder defaultSortOrder = Descending @@ -2125,8 +2128,12 @@ getTransaction ctx (ApiT wid) mMetadataSchema (ApiTxId (ApiT (tid))) = do tx <- liftHandler $ W.getTransaction wrk wid tid depo <- liftIO $ W.stakeKeyDeposit <$> NW.currentProtocolParameters (wrk ^. networkLayer) pure (tx, depo) - liftIO $ mkApiTransactionFromInfo (timeInterpreter (ctx ^. networkLayer)) depo tx - $ if mMetadataSchema then TxMetadataNoSchema else TxMetadataDetailedSchema + liftIO + $ mkApiTransactionFromInfo + (timeInterpreter (ctx ^. networkLayer)) depo tx + $ if mMetadataSchema + then TxMetadataNoSchema + else TxMetadataDetailedSchema -- Populate an API transaction record with 'TransactionInfo' from the wallet -- layer. @@ -2135,11 +2142,11 @@ mkApiTransactionFromInfo => TimeInterpreter (ExceptT PastHorizonException IO) -> Coin -> TransactionInfo - -> TxMetadataSchema + -> TxMetadataSchema -> m (ApiTransaction n) mkApiTransactionFromInfo ti deposit info metadataSchema = do - apiTx <- liftIO $ mkApiTransaction - ti + apiTx <- liftIO $ mkApiTransaction + ti status MkApiTransactionParams { txId = info ^. #txInfoId @@ -2154,7 +2161,7 @@ mkApiTransactionFromInfo ti deposit info metadataSchema = do , txTime = info ^. #txInfoTime , txScriptValidity = info ^. #txInfoScriptValidity , txDeposit = deposit - , txMetadataSchema = metadataSchema + , txMetadataSchema = metadataSchema } return $ case info ^. (#txInfoMeta . #status) of Pending -> apiTx @@ -2185,7 +2192,10 @@ postTransactionFeeOld ctx (ApiT wid) body = do (wdrl, _) <- mkRewardAccountBuilder @_ @s @_ @n ctx wid (body ^. #withdrawal) let txCtx = defaultTransactionCtx { txWithdrawal = wdrl - , txMetadata = body ^? #metadata . traverse . #txMetadataWithSchema_metadata + , txMetadata + = body ^? #metadata + . traverse + . #txMetadataWithSchema_metadata } withWorkerCtx ctx wid liftE liftE $ \wrk -> do (utxoAvailable, wallet, pendingTxs) <- @@ -2982,7 +2992,7 @@ joinStakePool ctx knownPools getPoolStatus apiPoolId (ApiT wid) body = do , txTime , txScriptValidity = tx ^. #scriptValidity , txDeposit = W.stakeKeyDeposit pp - , txMetadataSchema = TxMetadataDetailedSchema + , txMetadataSchema = TxMetadataDetailedSchema } where ti :: TimeInterpreter (ExceptT PastHorizonException IO) @@ -3100,8 +3110,8 @@ quitStakePool ctx (ApiT wid) body = do , txTime , txScriptValidity = tx ^. #scriptValidity , txDeposit = W.stakeKeyDeposit pp - , txMetadataSchema = TxMetadataDetailedSchema - } + , txMetadataSchema = TxMetadataDetailedSchema + } where ti :: TimeInterpreter (ExceptT PastHorizonException IO) ti = timeInterpreter (ctx ^. networkLayer) @@ -3358,7 +3368,7 @@ migrateWallet ctx withdrawalType (ApiT wid) postData = do , txTime , txScriptValidity = tx ^. #scriptValidity , txDeposit = W.stakeKeyDeposit pp - , txMetadataSchema = TxMetadataDetailedSchema + , txMetadataSchema = TxMetadataDetailedSchema } where addresses = getApiT . fst <$> view #addresses postData @@ -3815,7 +3825,7 @@ data MkApiTransactionParams = MkApiTransactionParams , txTime :: UTCTime , txScriptValidity :: Maybe W.TxScriptValidity , txDeposit :: Coin - , txMetadataSchema :: TxMetadataSchema + , txMetadataSchema :: TxMetadataSchema } deriving (Eq, Generic, Show) @@ -3867,7 +3877,8 @@ mkApiTransaction timeInterpreter setTimeReference tx = do , withdrawals = mkApiWithdrawal @n <$> Map.toList (tx ^. #txWithdrawals) , mint = mempty -- TODO: ADP-xxx , status = ApiT (tx ^. (#txMeta . #status)) - , metadata = TxMetadataWithSchema (tx ^. #txMetadataSchema) <$> tx ^. #txMetadata + , metadata = TxMetadataWithSchema (tx ^. #txMetadataSchema) + <$> tx ^. #txMetadata , scriptValidity = ApiT <$> tx ^. #txScriptValidity } diff --git a/lib/core/src/Cardano/Wallet/Api/Types.hs b/lib/core/src/Cardano/Wallet/Api/Types.hs index ae834175c80..6e40fb48e17 100644 --- a/lib/core/src/Cardano/Wallet/Api/Types.hs +++ b/lib/core/src/Cardano/Wallet/Api/Types.hs @@ -270,6 +270,8 @@ import Cardano.Mnemonic , mnemonicToText , natVals ) +import Cardano.Wallet.Api.Types.SchemaMetadata + ( TxMetadataWithSchema ) import Cardano.Wallet.Primitive.AddressDerivation ( Depth (..) , DerivationIndex (..) @@ -482,7 +484,6 @@ import qualified Data.Map as Map import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Data.Text.Read as T -import Cardano.Wallet.Api.Types.SchemaMetadata {------------------------------------------------------------------------------- Styles of Wallets diff --git a/lib/core/src/Cardano/Wallet/Api/Types/SchemaMetadata.hs b/lib/core/src/Cardano/Wallet/Api/Types/SchemaMetadata.hs index 4aca8ab4b1d..e2524809d91 100644 --- a/lib/core/src/Cardano/Wallet/Api/Types/SchemaMetadata.hs +++ b/lib/core/src/Cardano/Wallet/Api/Types/SchemaMetadata.hs @@ -23,6 +23,7 @@ import Cardano.Api , metadataToJson ) import Cardano.Wallet.Primitive.Types.Tx + ( TxMetadata ) import Control.Applicative ( liftA2, (<|>) ) import Control.DeepSeq @@ -35,20 +36,22 @@ import Prelude -- | a tag to select the json codec data TxMetadataSchema = TxMetadataNoSchema | TxMetadataDetailedSchema - deriving (Show, Eq, Generic, NFData) + deriving (Show, Eq, Generic, NFData) -- | a wrapper to drive the json codec of metadata data TxMetadataWithSchema = TxMetadataWithSchema - { -- | how to codec the metadata into json - txMetadataWithSchema_schema :: TxMetadataSchema - , -- | the metadata - txMetadataWithSchema_metadata :: TxMetadata - } - deriving (Show, Eq, Generic, NFData) + { -- | how to codec the metadata into json + txMetadataWithSchema_schema :: TxMetadataSchema + , -- | the metadata + txMetadataWithSchema_metadata :: TxMetadata + } + deriving (Show, Eq, Generic, NFData) instance ToJSON TxMetadataWithSchema where - toJSON (TxMetadataWithSchema TxMetadataDetailedSchema x) = metadataToJson TxMetadataJsonDetailedSchema x - toJSON (TxMetadataWithSchema TxMetadataNoSchema x) = metadataToJson TxMetadataJsonNoSchema x + toJSON (TxMetadataWithSchema TxMetadataDetailedSchema x) = + metadataToJson TxMetadataJsonDetailedSchema x + toJSON (TxMetadataWithSchema TxMetadataNoSchema x) = + metadataToJson TxMetadataJsonNoSchema x detailedMetadata :: TxMetadata -> TxMetadataWithSchema detailedMetadata = TxMetadataWithSchema TxMetadataDetailedSchema @@ -57,13 +60,13 @@ noSchemaMetadata :: TxMetadata -> TxMetadataWithSchema noSchemaMetadata = TxMetadataWithSchema TxMetadataNoSchema instance FromJSON TxMetadataWithSchema where - parseJSON = liftA2 - do (<|>) - do - fmap detailedMetadata - . either (fail . displayError) pure - . metadataFromJson TxMetadataJsonDetailedSchema - do - fmap noSchemaMetadata - . either (fail . displayError) pure - . metadataFromJson TxMetadataJsonNoSchema + parseJSON = liftA2 + do (<|>) + do + fmap detailedMetadata + . either (fail . displayError) pure + . metadataFromJson TxMetadataJsonDetailedSchema + do + fmap noSchemaMetadata + . either (fail . displayError) pure + . metadataFromJson TxMetadataJsonNoSchema diff --git a/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs b/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs index e589c36e085..b0eb8f26135 100644 --- a/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs +++ b/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs @@ -50,7 +50,6 @@ import Cardano.Mnemonic , entropyToMnemonic , mkEntropy ) -import Cardano.Wallet.Api.Types.SchemaMetadata import Cardano.Wallet.Api ( Api ) import Cardano.Wallet.Api.Types @@ -200,6 +199,8 @@ import Cardano.Wallet.Api.Types , WalletPutPassphraseData (..) , toApiAsset ) +import Cardano.Wallet.Api.Types.SchemaMetadata + ( TxMetadataSchema (..), TxMetadataWithSchema (..) ) import Cardano.Wallet.Gen ( genMnemonic , genNatural @@ -2160,8 +2161,8 @@ instance Arbitrary (PostTransactionOldData n) where <*> arbitrary <*> arbitrary -instance Arbitrary TxMetadataWithSchema where - arbitrary = TxMetadataWithSchema +instance Arbitrary TxMetadataWithSchema where + arbitrary = TxMetadataWithSchema <$> elements [TxMetadataNoSchema, TxMetadataDetailedSchema] <*> arbitrary diff --git a/lib/shelley/bench/latency-bench.hs b/lib/shelley/bench/latency-bench.hs index cf773661712..2eb7f94f912 100644 --- a/lib/shelley/bench/latency-bench.hs +++ b/lib/shelley/bench/latency-bench.hs @@ -311,8 +311,11 @@ walletApiBench capture ctx = do (_, txs) <- unsafeRequest @[ApiTransaction n] ctx (Link.listTransactions @'Shelley wal1) Empty let txid = (head txs) ^. #id - t5a <- measureApiLogs capture - (request @[ApiTransaction n] ctx (Link.getTransaction @'Shelley wal1 (ApiTxId txid)) Default Empty) + t5a <- measureApiLogs capture $ + request @[ApiTransaction n] + ctx (Link.getTransaction @'Shelley wal1 (ApiTxId txid) False) + Default + Empty fmtResult "getTransaction " t5a (_, addrs) <- unsafeRequest @[ApiAddress n] ctx (Link.listAddresses @'Shelley wal2) Empty diff --git a/nix/materialized/stack-nix/cardano-wallet-core.nix b/nix/materialized/stack-nix/cardano-wallet-core.nix index c3752048f0e..f87ccf674e6 100644 --- a/nix/materialized/stack-nix/cardano-wallet-core.nix +++ b/nix/materialized/stack-nix/cardano-wallet-core.nix @@ -173,6 +173,7 @@ "Cardano/Wallet/Api/Server" "Cardano/Wallet/Api/Server/Tls" "Cardano/Wallet/Api/Types" + "Cardano/Wallet/Api/Types/SchemaMetadata" "Cardano/Wallet/CoinSelection" "Cardano/Wallet/CoinSelection/Internal" "Cardano/Wallet/CoinSelection/Internal/Balance" From 7dd203cf2a24aa601355c6c51a562908b574fcff Mon Sep 17 00:00:00 2001 From: Paolo Veronelli Date: Tue, 3 May 2022 12:16:16 +0200 Subject: [PATCH 07/12] rm BlockArguments use --- lib/cli/src/Cardano/CLI.hs | 3 +-- lib/core/src/Cardano/Wallet/Api/Server.hs | 9 ++++----- .../src/Cardano/Wallet/Api/Types/SchemaMetadata.hs | 11 +++++------ lib/core/src/Cardano/Wallet/DB/Sqlite/Migration.hs | 1 - 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/lib/cli/src/Cardano/CLI.hs b/lib/cli/src/Cardano/CLI.hs index 57108c63c31..762f08402e5 100644 --- a/lib/cli/src/Cardano/CLI.hs +++ b/lib/cli/src/Cardano/CLI.hs @@ -1,6 +1,5 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ApplicativeDo #-} -{-# LANGUAGE BlockArguments #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DerivingStrategies #-} @@ -734,7 +733,7 @@ data TransactionFeatures = NoShelleyFeatures | ShelleyFeatures -- | which json schema to use for output, True is simple metadataSchemaOption :: Parser Bool metadataSchemaOption = switch - do long "simple-metadata" + $ long "simple-metadata" <> help "output metadata json in no-schema encoding" -- | cardano-wallet transaction diff --git a/lib/core/src/Cardano/Wallet/Api/Server.hs b/lib/core/src/Cardano/Wallet/Api/Server.hs index 4781f5ab175..cf836187d78 100644 --- a/lib/core/src/Cardano/Wallet/Api/Server.hs +++ b/lib/core/src/Cardano/Wallet/Api/Server.hs @@ -1,5 +1,4 @@ {-# LANGUAGE AllowAmbiguousTypes #-} -{-# LANGUAGE BlockArguments #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} @@ -2050,9 +2049,9 @@ postTransactionOld ctx genChange (ApiT wid) body = do pure (sel, tx, txMeta, txTime, pp) liftIO $ mkApiTransaction - do timeInterpreter $ ctx ^. networkLayer - do #pendingSince - do MkApiTransactionParams + (timeInterpreter $ ctx ^. networkLayer) + #pendingSince + $ MkApiTransactionParams { txId = tx ^. #txId , txFee = tx ^. #fee , txInputs = NE.toList $ second Just <$> sel ^. #inputs @@ -2108,7 +2107,7 @@ listTransactions ctx (ApiT wid) mMinWithdrawal mStart mEnd mOrder metadataSchema (timeInterpreter (ctx ^. networkLayer)) depo tx - if metadataSchema + $ if metadataSchema then TxMetadataNoSchema else TxMetadataDetailedSchema diff --git a/lib/core/src/Cardano/Wallet/Api/Types/SchemaMetadata.hs b/lib/core/src/Cardano/Wallet/Api/Types/SchemaMetadata.hs index e2524809d91..1475d8bc4a3 100644 --- a/lib/core/src/Cardano/Wallet/Api/Types/SchemaMetadata.hs +++ b/lib/core/src/Cardano/Wallet/Api/Types/SchemaMetadata.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE BlockArguments #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} @@ -61,12 +60,12 @@ noSchemaMetadata = TxMetadataWithSchema TxMetadataNoSchema instance FromJSON TxMetadataWithSchema where parseJSON = liftA2 - do (<|>) - do - fmap detailedMetadata + (<|>) + ( fmap detailedMetadata . either (fail . displayError) pure . metadataFromJson TxMetadataJsonDetailedSchema - do - fmap noSchemaMetadata + ) + ( fmap noSchemaMetadata . either (fail . displayError) pure . metadataFromJson TxMetadataJsonNoSchema + ) diff --git a/lib/core/src/Cardano/Wallet/DB/Sqlite/Migration.hs b/lib/core/src/Cardano/Wallet/DB/Sqlite/Migration.hs index d0d7e3771df..7d4fb9487c6 100644 --- a/lib/core/src/Cardano/Wallet/DB/Sqlite/Migration.hs +++ b/lib/core/src/Cardano/Wallet/DB/Sqlite/Migration.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE BlockArguments #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DerivingStrategies #-} From afecfb121bc9c026e10948e1d213e90b658203a4 Mon Sep 17 00:00:00 2001 From: Samuel Evans-Powell Date: Tue, 3 May 2022 12:16:16 +0200 Subject: [PATCH 08/12] Fix golden files --- lib/cli/test/data/Cardano/CLISpec/transaction get --help | 2 +- lib/cli/test/data/Cardano/CLISpec/transaction list --help | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cli/test/data/Cardano/CLISpec/transaction get --help b/lib/cli/test/data/Cardano/CLISpec/transaction get --help index d551f59bf4e..36cab7120ca 100644 --- a/lib/cli/test/data/Cardano/CLISpec/transaction get --help +++ b/lib/cli/test/data/Cardano/CLISpec/transaction get --help @@ -1,4 +1,4 @@ -Usage: transaction get [--port INT] WALLET_ID TRANSACTION_ID +Usage: transaction get [--port INT] WALLET_ID TRANSACTION_ID [--simple-metadata] Get a transaction with specified id. diff --git a/lib/cli/test/data/Cardano/CLISpec/transaction list --help b/lib/cli/test/data/Cardano/CLISpec/transaction list --help index 033ea69b0ff..00775354138 100644 --- a/lib/cli/test/data/Cardano/CLISpec/transaction list --help +++ b/lib/cli/test/data/Cardano/CLISpec/transaction list --help @@ -1,5 +1,5 @@ -Usage: transaction list [--port INT] WALLET_ID [--start TIME] - [--end TIME] [--order ORDER] +Usage: transaction list [--port INT] WALLET_ID [--start TIME] + [--end TIME] [--order ORDER] [--simple-metadata] List the transactions associated with a wallet. From 379422ef34dd8a5e9dd7de4b50aaf8906c5b9168 Mon Sep 17 00:00:00 2001 From: Paolo Veronelli Date: Tue, 3 May 2022 14:36:53 +0200 Subject: [PATCH 09/12] remove Bool switch in transaction CLI to select metadata schema --- lib/cli/src/Cardano/CLI.hs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/cli/src/Cardano/CLI.hs b/lib/cli/src/Cardano/CLI.hs index 762f08402e5..23eb8384ae0 100644 --- a/lib/cli/src/Cardano/CLI.hs +++ b/lib/cli/src/Cardano/CLI.hs @@ -730,9 +730,12 @@ cmdWalletGetUtxoStatistics mkClient = data TransactionFeatures = NoShelleyFeatures | ShelleyFeatures deriving (Show, Eq) +data MetadataSchema = SimpleSchema | FullSchema + deriving (Show, Eq) + -- | which json schema to use for output, True is simple -metadataSchemaOption :: Parser Bool -metadataSchemaOption = switch +metadataSchemaOption :: Parser MetadataSchema +metadataSchemaOption = flag FullSchema SimpleSchema $ long "simple-metadata" <> help "output metadata json in no-schema encoding" @@ -852,7 +855,7 @@ data TransactionListArgs = TransactionListArgs , _timeRangeStart :: Maybe Iso8601Time , _timeRangeEnd :: Maybe Iso8601Time , _sortOrder :: Maybe SortOrder - , _schema :: Bool + , _schema :: MetadataSchema } cmdTransactionList @@ -878,7 +881,7 @@ cmdTransactionList mkTxClient = mTimeRangeStart mTimeRangeEnd (ApiT <$> mOrder) - metadataSchema + (metadataSchema == SimpleSchema) -- | Arguments for 'transaction submit' command data TransactionSubmitArgs = TransactionSubmitArgs @@ -928,7 +931,7 @@ data TransactionGetArgs = TransactionGetArgs { _port :: Port "Wallet" , _wid :: WalletId , _txid :: TxId - , _schema :: Bool + , _schema :: MetadataSchema } cmdTransactionGet @@ -946,7 +949,7 @@ cmdTransactionGet mkClient = exec (TransactionGetArgs wPort wId txId metadataSchema ) = do runClient wPort Aeson.encodePretty $ getTransaction mkClient (ApiT wId) - metadataSchema + (metadataSchema == SimpleSchema) (ApiTxId $ ApiT $ getTxId txId) {------------------------------------------------------------------------------- From e245be18b847c0b340b4626c0415a39b2d1da616 Mon Sep 17 00:00:00 2001 From: Samuel Evans-Powell Date: Wed, 4 May 2022 12:22:57 +0800 Subject: [PATCH 10/12] Add a Shelley mnemonic - Tests were running out of Shelley mnemonics. --- lib/core-integration/src/Test/Integration/Faucet.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/core-integration/src/Test/Integration/Faucet.hs b/lib/core-integration/src/Test/Integration/Faucet.hs index 8356736f73f..100e5e6586c 100644 --- a/lib/core-integration/src/Test/Integration/Faucet.hs +++ b/lib/core-integration/src/Test/Integration/Faucet.hs @@ -961,6 +961,10 @@ seqMnemonics = unsafeMkMnemonic <$> , "drive", "grant", "tumble", "catalog", "plastic" , "hello", "stomach", "utility", "safe", "cradle" ] + , [ "garage" , "warm" , "blouse" , "peanut" , "pair" + , "trend" , "fine" , "hybrid" , "risk" , "mail" + , "fan" , "damage" , "push" , "shrug" , "boost" + ] ] maMnemonics :: [Mnemonic 24] From 4c177da1722028458003513f7c4d2ae5b0457d4d Mon Sep 17 00:00:00 2001 From: Samuel Evans-Powell Date: Wed, 4 May 2022 12:47:54 +0800 Subject: [PATCH 11/12] Add more Shelly mnemonics as a buffer - Tests are failing due to not enough Shelley mnemonics, add more than necessary to stave off future failures. --- .../src/Test/Integration/Faucet.hs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/core-integration/src/Test/Integration/Faucet.hs b/lib/core-integration/src/Test/Integration/Faucet.hs index 100e5e6586c..ebedbdedd02 100644 --- a/lib/core-integration/src/Test/Integration/Faucet.hs +++ b/lib/core-integration/src/Test/Integration/Faucet.hs @@ -965,6 +965,22 @@ seqMnemonics = unsafeMkMnemonic <$> , "trend" , "fine" , "hybrid" , "risk" , "mail" , "fan" , "damage" , "push" , "shrug" , "boost" ] + , [ "sleep" , "sword" , "chaos" , "taste" , "emotion" + , "achieve" , "prosper" , "scrap" , "delay" , "wing" + , "ketchup" , "neglect" , "foam" , "muffin" , "brisk" + ] + , [ "lawn" , "bring" , "diamond" , "network" , "remember" + , "slight" , "auto" , "select" , "vivid" , "silent" + , "letter" , "usual" , "pen" , "yellow" , "equip" + ] + , [ "coast" , "under" , "relax" , "vault" , "hip" + , "plastic" , "boat" , "dice" , "genuine" , "inject" + , "have" , "swim" , "miss" , "expire" , "tornado" + ] + , [ "damp" , "fabric" , "witness" , "height" , "hurdle" + , "office" , "midnight" , "gaze" , "engage" , "eagle" + , "into" , "cup" , "about" , "velvet" , "acquire" + ] ] maMnemonics :: [Mnemonic 24] From ecedb6397fd0468d2c2b332bbbb24f8492b15f5b Mon Sep 17 00:00:00 2001 From: Samuel Evans-Powell Date: Wed, 4 May 2022 13:00:42 +0800 Subject: [PATCH 12/12] Add documentation for no more wallets test error - Add documentation that describes what to do if the developer encounters a "no more wallets" error while testing. --- docs/contributing/Testing.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/contributing/Testing.md b/docs/contributing/Testing.md index 243d4a78e24..80855bf248c 100644 --- a/docs/contributing/Testing.md +++ b/docs/contributing/Testing.md @@ -175,6 +175,26 @@ The default log level for log files is Info. Only Error level logs are shown on stdout during test execution. To change this, set the `*_MIN_SEVERITY` variables shown above. +#### Common Failures and Resolution + +##### No More Wallets + +If your test fails with something like: + +``` +user error (No more faucet wallet available in MVar!) +``` + +Generate more wallet mnemonics and populate the appropriate list in `lib/core-integration/src/Test/Integration/Faucet.hs`. + +Generate new mnemonics with: + +``` +nix build .#cardano-wallet +# Size may vary depending on which array you need to add to. +./result/bin/cardano-wallet recovery-phrase generate --size 15 +``` + ## Mock servers Use the `cardano-wallet:mock-token-metadata-server` executable as a