diff --git a/CHANGELOG.md b/CHANGELOG.md index e077efd..70317db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.5.5.3] +### Added + +- Added unction to generate an ExchangeAddress in Human Readable Format Using a TransparentAddress in HRF + `encodeExchangeAddress` a function to create a ExchangeAddress in HRF + `decodeExchangeAddress` a function to obtaina a TransparentAddress object from an ExchangeAddress in HRF +- Added new type ExchangeAddress + ### Fixed - Orchard note nullifier calculation diff --git a/src/ZcashHaskell/Sapling.hs b/src/ZcashHaskell/Sapling.hs index fb62a7a..6e3c7b0 100644 --- a/src/ZcashHaskell/Sapling.hs +++ b/src/ZcashHaskell/Sapling.hs @@ -43,25 +43,6 @@ import Foreign.Rust.Marshall.Variable , withPureBorshVarBuffer ) import ZcashHaskell.Types ---import ZcashHaskell.Types --- ( AccountId --- , CoinType --- , DecodedNote(..) --- , RawData(..) --- , RawTxResponse(..) --- , SaplingAddress(..) --- , SaplingCommitmentTree(..) --- , SaplingReceiver(..) --- , SaplingSpendingKey(..) --- , SaplingWitness(..) --- , Scope(..) --- , Seed(..) --- , ShieldedOutput(..) --- , ToBytes(..) --- , ZcashNet(..) --- , decodeHexText --- , getValue --- ) import ZcashHaskell.Utils (decodeBech32, encodeBech32, encodeBech32m) -- | Check if given bytesting is a valid encoded shielded address diff --git a/src/ZcashHaskell/Transparent.hs b/src/ZcashHaskell/Transparent.hs index 366dfe4..4bdc46d 100644 --- a/src/ZcashHaskell/Transparent.hs +++ b/src/ZcashHaskell/Transparent.hs @@ -22,7 +22,8 @@ import qualified Data.ByteArray as BA import qualified Data.ByteString as BS import Data.ByteString.Base58 (bitcoinAlphabet, decodeBase58, encodeBase58) import Data.Char (chr) -import Data.HexString +import qualified Data.ByteString.Char8 as BC +import Data.HexString import qualified Data.Text as T import qualified Data.Text.Encoding as E import Data.Word @@ -30,19 +31,20 @@ import Haskoin.Address (Address(..)) import qualified Haskoin.Crypto.Hash as H import Haskoin.Crypto.Keys.Extended import ZcashHaskell.Types - ( AccountId - , CoinType(..) - , Scope(..) - , Seed(..) - , ToBytes(..) - , TransparentAddress(..) - , TransparentReceiver(..) - , TransparentSpendingKey(..) - , TransparentType(..) - , ZcashNet(..) - , getTransparentPrefix - , getValue - ) +-- ( AccountId +-- , CoinType(..) +-- , Scope(..) +-- , Seed(..) +-- , ToBytes(..) +-- , TransparentAddress(..) +-- , TransparentReceiver(..) +-- , TransparentSpendingKey(..) +-- , TransparentType(..) +-- , ZcashNet(..) +-- , getTransparentPrefix +-- , getValue +-- ) +import ZcashHaskell.Utils( encodeBech32m, decodeBech32 ) -- | Required for `TransparentReceiver` encoding and decoding sha256 :: BS.ByteString -> BS.ByteString @@ -142,3 +144,43 @@ decodeTransparentAddress taddress = do TransparentReceiver P2PKH (fromRawBytes transparentReceiver) else Nothing _ -> Nothing + +-- | Encode an Exchange Addresss into HRF from TransparentReceiver +encodeExchangeAddress:: ZcashNet -> TransparentReceiver -> Maybe T.Text +encodeExchangeAddress net tr = do + case (tr_type tr) of + P2PKH -> do + case net of + MainNet -> do + let vhash = encodeBech32m (BC.pack "tex") (toBytes (tr_bytes tr)) + Just vhash + TestNet -> do + let vhash = encodeBech32m (BC.pack "textest") (toBytes (tr_bytes tr)) + Just vhash + _ -> Nothing + +-- | Decode an Exchange Address into a ExchangeAddress +decodeExchangeAddress:: T.Text-> Maybe ExchangeAddress +decodeExchangeAddress ex = do + if (T.length ex ) > 1 + then do + let rawd = decodeBech32 (E.encodeUtf8 ex) + let tMain = BS.unpack (BC.pack "tex") + let tTest = BS.unpack (BC.pack "textest") + let tFail = BS.unpack (BC.pack "fail") + let hr = BS.unpack (hrp rawd) + if hr /= tFail + then do + let transparentReceiver = bytes rawd + if hr == tMain + then Just $ + ExchangeAddress MainNet $ + TransparentReceiver P2PKH (fromRawBytes transparentReceiver) + else do + if hr == tTest + then Just $ + ExchangeAddress TestNet $ + TransparentReceiver P2PKH (fromRawBytes transparentReceiver) + else Nothing + else Nothing + else Nothing \ No newline at end of file diff --git a/src/ZcashHaskell/Types.hs b/src/ZcashHaskell/Types.hs index 37fa1b6..25bb43f 100644 --- a/src/ZcashHaskell/Types.hs +++ b/src/ZcashHaskell/Types.hs @@ -434,6 +434,12 @@ data TransparentAddress = TransparentAddress , ta_receiver :: !TransparentReceiver } deriving (Eq, Prelude.Show, Read) +-- | Type to represent a TEX Zcash addresses +data ExchangeAddress = ExchangeAddress + { ex_network :: !ZcashNet + , ex_address :: !TransparentReceiver + } deriving (Eq, Prelude.Show, Read) + -- | Wrapper types for transparent elements data RawTxIn = RawTxIn { rti_outpoint :: !RawOutPoint diff --git a/test/Spec.hs b/test/Spec.hs index be1b49a..5c6f3a5 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -1115,6 +1115,22 @@ main = do p dn `shouldNotBe` Nothing + describe "Generate an ExchangeAddress (MainNet) from transparent address" $ do + let ta = decodeTransparentAddress "t1dMjvesbzdG41xgKaGU3HgwYJwSgbCK54e" + it "Try to generate valid ExchangeAddress from Transparent Address" $ do + case ta of + Nothing -> assertFailure "Failed to decode transparent address" + Just t -> do + case (tr_type (ta_receiver t) ) of + P2SH -> assertFailure "P2SH not supported for ExchengeAddress generation" + P2PKH -> do + let exch = encodeExchangeAddress (ta_network t) (ta_receiver t) + case exch of + Nothing -> assertFailure "Failed to encode Exchange address" + Just addr -> do + let eadr = decodeExchangeAddress addr + eadr `shouldNotBe` Nothing + -- | Properties prop_PhraseLength :: Property prop_PhraseLength =