diff --git a/flake.lock b/flake.lock index 32fe3f8892e..7cc74f6c2ef 100644 --- a/flake.lock +++ b/flake.lock @@ -421,11 +421,11 @@ "hackage": { "flake": false, "locked": { - "lastModified": 1647306913, - "narHash": "sha256-RlnNBE/6wEkfACaAgp6CX8fleDKSYJmBcR5hVeJnA/s=", + "lastModified": 1647479749, + "narHash": "sha256-HB7JFXFFby54TeRSRO/Ycie30SeyKvWMz6ZfanwNbaQ=", "owner": "input-output-hk", "repo": "hackage.nix", - "rev": "591cdc67210f9b645face190e5cb689eacef4571", + "rev": "a4301eb140f5e65c5a43564f3fb699e3a16faba0", "type": "github" }, "original": { @@ -457,11 +457,11 @@ "stackage": "stackage" }, "locked": { - "lastModified": 1647315229, - "narHash": "sha256-GRS3fA7jnPY6c+p7xssXthsGG1nG7M+u22DMz9jDZQ4=", + "lastModified": 1647479878, + "narHash": "sha256-T7J2vdIHll1LAz22XvMS7cfYQXY8/kKuGeGb9DuJiWM=", "owner": "input-output-hk", "repo": "haskell.nix", - "rev": "eb49a3b7213470e36570f4aa1ed7a64e6d6cf160", + "rev": "f3f2c08051d64ed540448604009b72bd1f41ad12", "type": "github" }, "original": { @@ -779,11 +779,11 @@ "stackage": { "flake": false, "locked": { - "lastModified": 1647307016, - "narHash": "sha256-5aaOk8EYVifi9nSdqR60ZyshgXYCiLrYrKRtPtM5iAQ=", + "lastModified": 1647393450, + "narHash": "sha256-vmLmc3fWWBq5VkAfAdDUtvmz8P/PU62Brr34voV+V6I=", "owner": "input-output-hk", "repo": "stackage.nix", - "rev": "66c6141c830c277ad919fb2a6180ee461ca0238b", + "rev": "56f045b4f40d0e22a37196bcb443dc50031e0c05", "type": "github" }, "original": { diff --git a/lib/shelley/cardano-wallet.cabal b/lib/shelley/cardano-wallet.cabal index 92c9d36b2c9..65a7611de3f 100644 --- a/lib/shelley/cardano-wallet.cabal +++ b/lib/shelley/cardano-wallet.cabal @@ -220,6 +220,8 @@ test-suite unit , bech32 , bech32-th , bytestring + , blockfrost-api + , blockfrost-client , cardano-addresses , cardano-api , cardano-crypto @@ -273,6 +275,7 @@ test-suite unit Cardano.Wallet.Shelley.CompatibilitySpec Cardano.Wallet.Shelley.Compatibility.LedgerSpec Cardano.Wallet.Shelley.LaunchSpec + Cardano.Wallet.Shelley.Launch.BlockfrostSpec Cardano.Wallet.Shelley.NetworkSpec Cardano.Wallet.Shelley.TransactionSpec Spec diff --git a/lib/shelley/exe/cardano-wallet.hs b/lib/shelley/exe/cardano-wallet.hs index 4e89b391964..d39e7ef9d0f 100644 --- a/lib/shelley/exe/cardano-wallet.hs +++ b/lib/shelley/exe/cardano-wallet.hs @@ -63,8 +63,6 @@ import Cardano.CLI , tokenMetadataSourceOption , withLogging ) -import Cardano.Launcher.Node - ( CardanoNodeConn ) import Cardano.Startup ( ShutdownHandlerLog , installSignalHandlers @@ -102,9 +100,8 @@ import Cardano.Wallet.Shelley.BlockchainSource import Cardano.Wallet.Shelley.Launch ( Mode (Light, Normal) , NetworkConfiguration (..) - , modeFlag + , modeOption , networkConfigurationOption - , nodeSocketOption , parseGenesisData ) import Cardano.Wallet.Version @@ -185,7 +182,6 @@ data ServeArgs = ServeArgs , _mode :: Mode , _listen :: Listen , _tlsConfig :: Maybe TlsConfiguration - , _nodeSocket :: CardanoNodeConn , _networkConfiguration :: NetworkConfiguration , _database :: Maybe FilePath , _syncTolerance :: SyncTolerance @@ -203,10 +199,9 @@ cmdServe = command "serve" $ info (helper <*> helper' <*> cmd) $ cmd = fmap exec $ ServeArgs <$> hostPreferenceOption - <*> modeFlag + <*> modeOption <*> listenOption <*> optional tlsOption - <*> nodeSocketOption <*> networkConfigurationOption <*> optional databaseOption <*> syncToleranceOption @@ -221,7 +216,6 @@ cmdServe = command "serve" $ info (helper <*> helper' <*> cmd) $ mode listen tlsConfig - conn networkConfig databaseDir sTolerance @@ -242,12 +236,10 @@ cmdServe = command "serve" $ info (helper <*> helper' <*> cmd) $ setupDirectory (logInfo tr . MsgSetupDatabases) blockchainSource <- case mode of - Normal -> + Normal conn -> pure $ NodeSource conn vData - Light (Just token) -> + Light token -> BlockfrostSource <$> Blockfrost.readToken token - Light Nothing -> - exitWith $ ExitFailure 34 exitWith =<< serveWallet blockchainSource diff --git a/lib/shelley/src/Cardano/Wallet/Shelley/Launch.hs b/lib/shelley/src/Cardano/Wallet/Shelley/Launch.hs index 31549e37c95..4bc86f5b013 100644 --- a/lib/shelley/src/Cardano/Wallet/Shelley/Launch.hs +++ b/lib/shelley/src/Cardano/Wallet/Shelley/Launch.hs @@ -35,7 +35,7 @@ module Cardano.Wallet.Shelley.Launch -- * Light Mode , Mode (..) - , modeFlag + , modeOption ) where import Prelude @@ -79,17 +79,7 @@ import Data.Text.Class import GHC.TypeLits ( KnownNat, Nat, SomeNat (..), someNatVal ) import Options.Applicative - ( Parser - , eitherReader - , flag - , flag' - , help - , long - , metavar - , option - , optional - , (<|>) - ) + ( Parser, eitherReader, flag', help, long, metavar, option, (<|>) ) import Ouroboros.Network.Magic ( NetworkMagic (..) ) import Ouroboros.Network.NodeToClient @@ -400,12 +390,15 @@ instance HasSeverityAnnotation TempDirLog where Mode -------------------------------------------------------------------------------} -data Mode = Normal | Light (Maybe Blockfrost.TokenFile) +data Mode = Normal CardanoNodeConn | Light Blockfrost.TokenFile deriving (Show) -modeFlag :: Parser Mode -modeFlag = do - light <- flag False True $ - mconcat [ long "light", help "Enable light mode" ] - creds <- optional Blockfrost.tokenFileOption - pure $ if light then Light creds else Normal +modeOption :: Parser Mode +modeOption = normalMode <|> lightMode + where + normalMode = + Normal <$> nodeSocketOption + lightMode = + flag' () (long "light" <> help "Enable light mode") *> + fmap Light Blockfrost.tokenFileOption + diff --git a/lib/shelley/src/Cardano/Wallet/Shelley/Launch/Blockfrost.hs b/lib/shelley/src/Cardano/Wallet/Shelley/Launch/Blockfrost.hs index c7738cfcb9f..94caaabea19 100644 --- a/lib/shelley/src/Cardano/Wallet/Shelley/Launch/Blockfrost.hs +++ b/lib/shelley/src/Cardano/Wallet/Shelley/Launch/Blockfrost.hs @@ -14,14 +14,14 @@ import Blockfrost.Client.Core import Blockfrost.Client.Types ( Project (..) ) import Options.Applicative - ( Parser, auto, help, long, metavar, option ) + ( Parser, help, long, metavar, option, str ) newtype TokenFile = TokenFile FilePath - deriving newtype (Eq, Show, Read) + deriving newtype (Eq, Show) -- | --blockfrost-token-file FILE tokenFileOption :: Parser TokenFile -tokenFileOption = option auto $ mconcat +tokenFileOption = option (TokenFile <$> str) $ mconcat [ long "blockfrost-token-file" , metavar "FILE" , help $ mconcat diff --git a/lib/shelley/test/unit/Cardano/Wallet/Shelley/Launch/BlockfrostSpec.hs b/lib/shelley/test/unit/Cardano/Wallet/Shelley/Launch/BlockfrostSpec.hs new file mode 100644 index 00000000000..eaec8ef7b30 --- /dev/null +++ b/lib/shelley/test/unit/Cardano/Wallet/Shelley/Launch/BlockfrostSpec.hs @@ -0,0 +1,65 @@ +module Cardano.Wallet.Shelley.Launch.BlockfrostSpec + ( spec + ) where + +import Prelude + +import qualified Blockfrost.Client.Types as Blockfrost +import qualified Data.Text as T + +import Blockfrost.Env + ( Env (Testnet) ) +import Cardano.Wallet.Shelley.Launch + ( Mode (Light, Normal), modeOption ) +import Cardano.Wallet.Shelley.Launch.Blockfrost + ( readToken ) +import Options.Applicative + ( ParserFailure (execFailure) + , ParserResult (CompletionInvoked, Failure, Success) + , defaultPrefs + , execParserPure + , fullDesc + , info + ) +import Test.Hspec + ( Spec, describe, expectationFailure, it, shouldBe, shouldReturn ) +import UnliftIO + ( withSystemTempFile ) +import UnliftIO.IO + ( hClose ) + +spec :: Spec +spec = describe "Blockfrost CLI options" $ do + it "modeOption --node-socket" $ do + let parserInfo = info modeOption fullDesc + args = ["--node-socket", "/tmp/file"] + case execParserPure defaultPrefs parserInfo args of + Failure pf -> expectationFailure $ show pf + CompletionInvoked cr -> expectationFailure $ show cr + Success (Light _) -> expectationFailure "Normal mode expected" + Success (Normal _conn) -> pure () + + it "modeOption --light" $ withSystemTempFile "blockfrost.token" $ \f h -> do + let parserInfo = info modeOption fullDesc + args = ["--light", "--blockfrost-token-file", f] + net = "testnet" + projectId = "jlUej4vcMt3nKPRAiNpLUEeKBIEPqgH2" + case execParserPure defaultPrefs parserInfo args of + Failure pf -> expectationFailure $ show pf + CompletionInvoked cr -> expectationFailure $ show cr + Success (Normal _conn) -> expectationFailure "Light mode expected" + Success (Light tf) -> do + hClose h *> writeFile f (net <> projectId) + readToken tf `shouldReturn` + Blockfrost.Project Testnet (T.pack projectId) + + it "modeOption requires --light flag" $ do + let parserInfo = info modeOption fullDesc + args = ["--blockfrost-token-file", "/tmp/file"] + case execParserPure defaultPrefs parserInfo args of + Failure pf | (help, _code, _int) <- execFailure pf "" -> + show help `shouldBe` + "Missing: --light\n\n\ + \Usage: (--node-socket FILE | \ + \--light --blockfrost-token-file FILE)" + result -> expectationFailure $ show result diff --git a/nix/materialized/stack-nix/cardano-wallet.nix b/nix/materialized/stack-nix/cardano-wallet.nix index 3e158c80f69..0c80c83090f 100644 --- a/nix/materialized/stack-nix/cardano-wallet.nix +++ b/nix/materialized/stack-nix/cardano-wallet.nix @@ -195,6 +195,8 @@ (hsPkgs."bech32" or (errorHandler.buildDepError "bech32")) (hsPkgs."bech32-th" or (errorHandler.buildDepError "bech32-th")) (hsPkgs."bytestring" or (errorHandler.buildDepError "bytestring")) + (hsPkgs."blockfrost-api" or (errorHandler.buildDepError "blockfrost-api")) + (hsPkgs."blockfrost-client" or (errorHandler.buildDepError "blockfrost-client")) (hsPkgs."cardano-addresses" or (errorHandler.buildDepError "cardano-addresses")) (hsPkgs."cardano-api" or (errorHandler.buildDepError "cardano-api")) (hsPkgs."cardano-crypto" or (errorHandler.buildDepError "cardano-crypto")) @@ -244,6 +246,7 @@ "Cardano/Wallet/Shelley/CompatibilitySpec" "Cardano/Wallet/Shelley/Compatibility/LedgerSpec" "Cardano/Wallet/Shelley/LaunchSpec" + "Cardano/Wallet/Shelley/Launch/BlockfrostSpec" "Cardano/Wallet/Shelley/NetworkSpec" "Cardano/Wallet/Shelley/TransactionSpec" "Spec"