haskoin-store-1.9.0: test/Haskoin/Store/WebSpec.hs
module Haskoin.Store.WebSpec (spec) where
import Data.ByteString (ByteString)
import Data.Either (isLeft)
import Data.Maybe (fromJust)
import Data.Text.Encoding (decodeUtf8)
import Haskoin (Tx (..), bch, btc, decodeHex, txHash, txHashToHex)
import Haskoin.Store.Web (acceptsBinary, decodeTxBody)
import Test.Hspec
-- | A transaction written by hand, in the format without witness. It has
-- version 1, one input that spends output 0 of transaction aa..aa with an
-- empty script, one output of 1000 satoshi to the script OP_TRUE, and lock
-- time 0.
plainTxHex :: ByteString
plainTxHex =
"01000000\
\01aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
\0000000000ffffffff\
\01e8030000000000000151\
\00000000"
-- | The same transaction in the SegWit format. The marker and flag bytes
-- 00 01 follow the version, and the input has one witness item, the byte 01.
segwitTxHex :: ByteString
segwitTxHex =
"010000000001\
\01aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
\0000000000ffffffff\
\01e8030000000000000151\
\010101\
\00000000"
spec :: Spec
spec = do
describe "acceptsBinary" $ do
it "takes the binary type by itself" $
acceptsBinary "application/octet-stream" `shouldBe` True
it "takes it in a list, in any case and with spaces" $ do
acceptsBinary "text/html, Application/Octet-Stream" `shouldBe` True
acceptsBinary "application/octet-stream , */*" `shouldBe` True
it "takes it with a weight above zero" $
acceptsBinary "application/octet-stream;q=0.5" `shouldBe` True
it "gives JSON to a wildcard, to nothing and to JSON" $ do
acceptsBinary "*/*" `shouldBe` False
acceptsBinary "" `shouldBe` False
acceptsBinary "application/json" `shouldBe` False
it "gives JSON when binary is refused with a weight of zero" $
acceptsBinary "application/octet-stream;q=0, application/json" `shouldBe` False
it "follows the weights when both are named" $ do
acceptsBinary "application/json;q=0.9, application/octet-stream" `shouldBe` True
acceptsBinary "application/json, application/octet-stream;q=0.9" `shouldBe` False
acceptsBinary "application/json;q=0.5, application/octet-stream; q=0.5" `shouldBe` True
describe "decodeTxBody" $ do
-- The id is the double SHA-256 of the bytes of plainTxHex, reversed. It
-- was computed outside this library. The witness is not part of the id,
-- so both formats of the transaction have this id.
let txid = "deca6f028918fa8d8c0efc66f2015cd5a2b5d42c8352a7e07468983f988900c9"
idOf = fmap (txHashToHex . txHash)
it "reads a transaction given as hex" $
idOf (decodeTxBody btc plainTxHex) `shouldBe` Right txid
it "reads a transaction given as raw bytes" $ do
let bytes = fromJust (decodeHex (decodeUtf8 plainTxHex))
idOf (decodeTxBody btc bytes) `shouldBe` Right txid
it "ignores white space around the hex" $
idOf (decodeTxBody btc (" " <> plainTxHex <> "\r\n")) `shouldBe` Right txid
it "refuses bytes after the transaction" $
decodeTxBody btc (plainTxHex <> "00") `shouldSatisfy` isLeft
it "reads the SegWit format on Bitcoin, with its witness" $ do
let tx = decodeTxBody btc segwitTxHex
idOf tx `shouldBe` Right txid
fmap (.witness) tx `shouldBe` Right [["\x01"]]
it "reads the format without witness on Bitcoin Cash" $
idOf (decodeTxBody bch plainTxHex) `shouldBe` Right txid
it "refuses the SegWit format on Bitcoin Cash, which has no SegWit" $
decodeTxBody bch segwitTxHex `shouldSatisfy` isLeft