never executed always true always false
1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE NamedFieldPuns #-}
3 {-# LANGUAGE OverloadedStrings #-}
4
5 {-# OPTIONS_HADDOCK hide #-}
6 {-# OPTIONS_GHC -fno-warn-deprecations #-}
7
8 module Command.Address.Payment
9 ( Cmd
10 , mod
11 , run
12 ) where
13
14 import Prelude hiding
15 ( mod )
16
17 import Cardano.Address
18 ( unAddress )
19 import Cardano.Address.Derivation
20 ( pubFromBytes, xpubFromBytes )
21 import Cardano.Address.Script
22 ( KeyHash, KeyRole (..), Script, keyHashFromBytes, scriptHashFromBytes )
23 import Cardano.Address.Style.Shelley
24 ( Credential (..), shelleyTestnet )
25 import Codec.Binary.Encoding
26 ( AbstractEncoding (..) )
27 import Options.Applicative
28 ( CommandFields
29 , Mod
30 , command
31 , footerDoc
32 , header
33 , helper
34 , info
35 , optional
36 , progDesc
37 )
38 import Options.Applicative.Discrimination
39 ( NetworkTag (..), fromNetworkTag, networkTagOpt )
40 import Options.Applicative.Help.Pretty
41 ( bold, indent, string, vsep )
42 import Options.Applicative.Script
43 ( scriptArg )
44 import Options.Applicative.Style
45 ( Style (..) )
46 import System.IO
47 ( stdin, stdout )
48 import System.IO.Extra
49 ( hGetBech32, hPutBytes, progName )
50
51 import qualified Cardano.Address.Style.Shelley as Shelley
52 import qualified Cardano.Codec.Bech32.Prefixes as CIP5
53
54 data Cmd = Cmd
55 { networkTag :: NetworkTag
56 , paymentScript :: Maybe (Script KeyHash)
57 } deriving (Show)
58
59 mod :: (Cmd -> parent) -> Mod CommandFields parent
60 mod liftCmd = command "payment" $
61 info (helper <*> fmap liftCmd parser) $ mempty
62 <> progDesc "Create a payment address"
63 <> header "Payment addresses carry no delegation rights whatsoever."
64 <> footerDoc (Just $ vsep
65 [ string "Example:"
66 , indent 2 $ bold $ string $ "$ "<>progName<>" recovery-phrase generate --size 15 \\"
67 , indent 4 $ bold $ string $ "| "<>progName<>" key from-recovery-phrase Shelley > root.prv"
68 , indent 2 $ string ""
69 , indent 2 $ bold $ string "$ cat root.prv \\"
70 , indent 4 $ bold $ string $ "| "<>progName<>" key child 1852H/1815H/0H/0/0 > addr.prv"
71 , indent 2 $ string ""
72 , indent 2 $ bold $ string "$ cat addr.prv \\"
73 , indent 4 $ bold $ string $ "| "<>progName<>" key public --with-chain-code \\"
74 , indent 4 $ bold $ string $ "| "<>progName<>" address payment --network-tag testnet"
75 , indent 2 $ string "addr_test1vqrlltfahghjxl5sy5h5mvfrrlt6me5fqphhwjqvj5jd88cccqcek"
76 ])
77 where
78 parser = Cmd
79 <$> networkTagOpt Shelley
80 <*> optional scriptArg
81
82 run :: Cmd -> IO ()
83 run Cmd{networkTag,paymentScript} = do
84 discriminant <- fromNetworkTag networkTag
85 addr <- case paymentScript of
86 Just script -> do
87 let credential = PaymentFromScript script
88 pure $ Shelley.paymentAddress discriminant credential
89 Nothing -> do
90 (hrp, bytes) <- hGetBech32 stdin allowedPrefixes
91 addressFromBytes discriminant bytes hrp
92 hPutBytes stdout (unAddress addr) (EBech32 addrHrp)
93 where
94 addrHrp
95 | networkTag == shelleyTestnet = CIP5.addr_test
96 | otherwise = CIP5.addr
97
98 allowedPrefixes =
99 [ CIP5.addr_xvk
100 , CIP5.addr_vk
101 , CIP5.addr_vkh
102 , CIP5.script
103 ]
104
105 addressFromBytes discriminant bytes hrp
106 | hrp == CIP5.script = do
107 case scriptHashFromBytes bytes of
108 Nothing ->
109 fail "Couldn't convert bytes into script hash."
110 Just h -> do
111 let credential = PaymentFromScriptHash h
112 pure $ Shelley.paymentAddress discriminant credential
113
114 | hrp == CIP5.addr_vkh = do
115 case keyHashFromBytes (Payment, bytes) of
116 Nothing ->
117 fail "Couldn't convert bytes into payment key hash."
118 Just keyhash -> do
119 let credential = PaymentFromKeyHash keyhash
120 pure $ Shelley.paymentAddress discriminant credential
121
122 | hrp == CIP5.addr_vk = do
123 case pubFromBytes bytes of
124 Nothing ->
125 fail "Couldn't convert bytes into non-extended public key."
126 Just key -> do
127 let credential = PaymentFromKey $ Shelley.liftPub key
128 pure $ Shelley.paymentAddress discriminant credential
129
130 | otherwise = do
131 case xpubFromBytes bytes of
132 Nothing ->
133 fail "Couldn't convert bytes into extended public key."
134 Just key -> do
135 let credential = PaymentFromExtendedKey $ Shelley.liftXPub key
136 pure $ Shelley.paymentAddress discriminant credential