diff --git a/src/Network/Ethereum/Web3/Solidity/Size.purs b/src/Network/Ethereum/Web3/Solidity/Size.purs deleted file mode 100644 index a533500..0000000 --- a/src/Network/Ethereum/Web3/Solidity/Size.purs +++ /dev/null @@ -1,90 +0,0 @@ -module Network.Ethereum.Web3.Solidity.Size where --- ( class KnownSize --- , reflectType --- , class IntSize --- , class ByteSize --- ) where --- ---import Data.Reflectable (class Reflectable, reflectType) ---import Type.Proxy (Proxy(..)) --- ---class Reflectable n Int <= KnownSize (n :: Int) where --- reflectType :: forall proxy. proxy n -> Int --- ---instance (Reflectable n Int) => KnownSize n where --- reflectType _ = reflectType (Proxy :: Proxy n) --- ----- | `IntSize` is empty class, if there is instance of `IntSize` for some number it means there ----- | is solidity type `int` of that size specific number in like `int16`, `int24` ... `int256` ---class KnownSize n <= IntSize (n :: Int) --- ---instance intSize8 :: IntSize 8 ---instance intSize16 :: IntSize 16 ---instance intSize24 :: IntSize 24 ---instance intSize32 :: IntSize 32 ---instance intSize40 :: IntSize 40 ---instance intSize48 :: IntSize 48 ---instance intSize56 :: IntSize 56 ---instance intSize64 :: IntSize 64 ---instance intSize72 :: IntSize 72 ---instance intSize80 :: IntSize 80 ---instance intSize88 :: IntSize 88 ---instance intSize96 :: IntSize 96 ---instance intSize104 :: IntSize 104 ---instance intSize112 :: IntSize 112 ---instance intSize120 :: IntSize 120 ---instance intSize128 :: IntSize 128 ---instance intSize136 :: IntSize 136 ---instance intSize144 :: IntSize 144 ---instance intSize152 :: IntSize 152 ---instance intSize160 :: IntSize 160 ---instance intSize168 :: IntSize 168 ---instance intSize176 :: IntSize 176 ---instance intSize184 :: IntSize 184 ---instance intSize192 :: IntSize 192 ---instance intSize200 :: IntSize 200 ---instance intSize208 :: IntSize 208 ---instance intSize216 :: IntSize 216 ---instance intSize224 :: IntSize 224 ---instance intSize232 :: IntSize 232 ---instance intSize240 :: IntSize 240 ---instance intSize248 :: IntSize 248 ---instance intSize256 :: IntSize 256 --- ----- | `ByteSize` is empty class, if there is instance of `ByteSize` for some number it means there ----- | is solidity type `bytes` of that size specific number in like `bytes1`, `bytes2` ... `bytes32` ---class KnownSize n <= ByteSize (n :: Int) --- ---instance byteSize1 :: ByteSize 1 ---instance byteSize2 :: ByteSize 2 ---instance byteSize3 :: ByteSize 3 ---instance byteSize4 :: ByteSize 4 ---instance byteSize5 :: ByteSize 5 ---instance byteSize6 :: ByteSize 6 ---instance byteSize7 :: ByteSize 7 ---instance byteSize8 :: ByteSize 8 ---instance byteSize9 :: ByteSize 9 ---instance byteSize10 :: ByteSize 10 ---instance byteSize11 :: ByteSize 11 ---instance byteSize12 :: ByteSize 12 ---instance byteSize13 :: ByteSize 13 ---instance byteSize14 :: ByteSize 14 ---instance byteSize15 :: ByteSize 15 ---instance byteSize16 :: ByteSize 16 ---instance byteSize17 :: ByteSize 17 ---instance byteSize18 :: ByteSize 18 ---instance byteSize19 :: ByteSize 19 ---instance byteSize20 :: ByteSize 20 ---instance byteSize21 :: ByteSize 21 ---instance byteSize22 :: ByteSize 22 ---instance byteSize23 :: ByteSize 23 ---instance byteSize24 :: ByteSize 24 ---instance byteSize25 :: ByteSize 25 ---instance byteSize26 :: ByteSize 26 ---instance byteSize27 :: ByteSize 27 ---instance byteSize28 :: ByteSize 28 ---instance byteSize29 :: ByteSize 29 ---instance byteSize30 :: ByteSize 30 ---instance byteSize31 :: ByteSize 31 ---instance byteSize32 :: ByteSize 32 --- \ No newline at end of file diff --git a/test/web3/Main.purs b/test/web3/Main.purs index 4b43d60..c18b3d6 100644 --- a/test/web3/Main.purs +++ b/test/web3/Main.purs @@ -1,6 +1,7 @@ module Test.Main where import Prelude + import Data.Identity (Identity(..)) import Data.Maybe (Maybe(..)) import Data.Newtype (un) @@ -19,6 +20,8 @@ import Web3Spec.Live.RPCSpec as RPCSpec import Web3Spec.Types.EtherUnitSpec as EtherUnitSpec import Web3Spec.Types.VectorSpec as VectorSpec +-- import Web3Spec.Types.EtherUnitSpec as EtherUnitSpec + main :: Effect Unit main = launchAff_ @@ -26,16 +29,15 @@ main = let cfg = defaultConfig { timeout = Just (Milliseconds $ 120.0 * 1000.0) } p <- liftEffect $ httpProvider "http://localhost:8545" - void $ join - $ runSpecT cfg [ consoleReporter ] do - hoist do - EncodingDataSpec.spec - -- VectorSpec.spec - EncodingContainersSpec.spec - -- EncodingSimpleSpec.spec - -- EncodingGenericSpec.spec - -- EtherUnitSpec.spec - --RPCSpec.spec p + void $ join $ runSpecT cfg [ consoleReporter ] do + hoist do + EncodingDataSpec.spec + EncodingContainersSpec.spec + EncodingSimpleSpec.spec + EncodingGenericSpec.spec + EtherUnitSpec.spec + VectorSpec.spec + RPCSpec.spec p where hoist :: Spec ~> SpecT Aff Unit Aff hoist = mapSpecTree (pure <<< un Identity) identity diff --git a/test/web3/Web3Spec/Encoding/ContainersSpec.purs b/test/web3/Web3Spec/Encoding/ContainersSpec.purs index ad71512..afd7d95 100644 --- a/test/web3/Web3Spec/Encoding/ContainersSpec.purs +++ b/test/web3/Web3Spec/Encoding/ContainersSpec.purs @@ -2,13 +2,14 @@ module Web3Spec.Encoding.ContainersSpec (spec) where import Prelude -import Control.Monad.Gen (chooseInt, frequency, suchThat) +import Control.Monad.Gen (chooseInt, frequency, oneOf, suchThat) import Data.Array (filter, foldMap, (..)) import Data.Array.NonEmpty (NonEmptyArray, fromArray) import Data.Array.NonEmpty as NEA import Data.Either (Either(..)) import Data.Enum (toEnumWithDefaults) import Data.Foldable (for_) +import Data.Generic.Rep (class Generic) import Data.Int (toNumber) import Data.Maybe (fromJust) import Data.NonEmpty (NonEmpty(..)) @@ -16,7 +17,8 @@ import Data.Reflectable (reifyType) import Data.String (CodePoint, fromCodePointArray) import Data.Tuple (Tuple(..)) import Effect.Class (liftEffect) -import Network.Ethereum.Core.HexString (toByteString) +import Network.Ethereum.Core.HexString (genBytes, toByteString) +import Network.Ethereum.Web3.Solidity (class GenericABIDecode, class GenericABIEncode, Tuple4(..), Tuple5(..), genericABIEncode, genericFromData) import Network.Ethereum.Web3.Solidity.AbiEncoding (class ABIEncode, class ABIDecode, toDataBuilder, fromData) import Network.Ethereum.Web3.Solidity.Bytes as BytesN import Network.Ethereum.Web3.Solidity.EncodingType (class EncodingType) @@ -37,6 +39,7 @@ spec = arrayTypePropertyTests vecTypePropertyTests nestedTypePropertyTests + tupleTests typePropertyTests :: Spec Unit typePropertyTests = @@ -227,6 +230,78 @@ nestedTypePropertyTests = do quickCheck \(x :: Array (Array BMPString)) -> encodeDecode x === Right x +tupleTests :: Spec Unit +tupleTests = do + describe "Basic static sized Tuple Tests" $ do + + it "Can encode/decode (intN, address, bool, uintN, bytesN)" $ liftEffect do + quickCheckGen $ do + n <- oneOf (pure <$> intSizes) + m <- oneOf (pure <$> intSizes) + k <- oneOf (pure <$> bytesSizes) + reifyType n \pn -> + reifyType m \pm -> + reifyType k \pk -> do + int <- IntN.generator pn + addr <- arbitrary :: Gen Address + bool <- arbitrary :: Gen Boolean + uint <- UIntN.generator pm + bytes <- BytesN.generator pk + let x = Tuple5 int addr bool uint bytes + pure $ genericEncodeDecode x === Right x + + it "Can encode/decode (address[k], bool, intN[k], uint)" $ liftEffect do + quickCheckGen $ do + k1 <- chooseInt 1 10 + k2 <- chooseInt 1 10 + n <- oneOf (pure <$> intSizes) + m <- oneOf (pure <$> intSizes) + reifyType k1 \pk1 -> + reifyType k2 \pk2 -> + reifyType n \pn -> do + reifyType m \pm -> do + addrs <- arrayOf (Vector.generator pk1 (arbitrary @Address)) + bool <- arbitrary @Boolean + ints <- Vector.generator pk2 (IntN.generator pn) + uint <- (UIntN.generator pm) + let x = Tuple4 addrs bool ints uint + pure $ genericEncodeDecode x === Right x + + describe "Basic dynamic sized Tuple Tests" $ do + + it "Can encode/decode (intN[], bytes, address[][k], string[k][], bool)" $ liftEffect do + quickCheckGen $ do + n <- oneOf (pure <$> intSizes) + m <- chooseInt 1 10 + k <- chooseInt 1 10 + reifyType n \pn -> + reifyType m \pm -> + reifyType k \pk -> do + ints <- arrayOf (IntN.generator pn) + bytes <- toByteString <$> (chooseInt 1 100 >>= genBytes) + addrs <- Vector.generator pm (arrayOf $ arbitrary @Address) + strings <- arrayOf (Vector.generator pk (arbitrary @BMPString)) + bool <- arbitrary :: Gen Boolean + let x = Tuple5 ints bytes addrs strings bool + pure $ genericEncodeDecode x === Right x + + it "Can encode/decode (address[k], bool, intN[k], uint)" $ liftEffect do + quickCheckGen $ do + k1 <- chooseInt 1 10 + k2 <- chooseInt 1 10 + n <- oneOf (pure <$> intSizes) + m <- oneOf (pure <$> intSizes) + reifyType k1 \pk1 -> + reifyType k2 \pk2 -> + reifyType n \pn -> do + reifyType m \pm -> do + addrs <- arrayOf (Vector.generator pk1 (arbitrary @Address)) + bool <- arbitrary @Boolean + ints <- Vector.generator pk2 (IntN.generator pn) + uint <- (UIntN.generator pm) + let x = Tuple4 addrs bool ints uint + pure $ genericEncodeDecode x === Right x + -------------------------------------------------------------------------------- newtype BMPString = BMPString String @@ -279,6 +354,18 @@ encodeDecode x = in (fromData a) +genericEncodeDecode + :: forall a rep + . Show a + => Eq a + => Generic a rep + => GenericABIEncode rep + => GenericABIDecode rep + => a + -> Either ParseError a +genericEncodeDecode a = + genericFromData $ genericABIEncode a + intSizes :: NonEmptyArray Int intSizes = unsafePartial fromJust $ fromArray diff --git a/test/web3/Web3Spec/Encoding/DataSpec.purs b/test/web3/Web3Spec/Encoding/DataSpec.purs index 8ec5491..9373710 100644 --- a/test/web3/Web3Spec/Encoding/DataSpec.purs +++ b/test/web3/Web3Spec/Encoding/DataSpec.purs @@ -1,35 +1,32 @@ module Web3Spec.Encoding.DataSpec (spec, approve) where import Prelude -import Data.Maybe (fromJust) -import Network.Ethereum.Web3.Solidity (UIntN, Tuple2, uIntNFromBigNumber) -import Network.Ethereum.Web3.Solidity.Sizes (s256) -import Network.Ethereum.Web3.Types (Address, HexString, TransactionOptions, NoPay, Web3, mkHexString, mkAddress) + import Data.Functor.Tagged (Tagged, tagged) -import Network.Ethereum.Web3.Contract (sendTx, mkDataField) +import Effect.Class (liftEffect) import Network.Ethereum.Core.Keccak256 (toSelector) -import Network.Ethereum.Web3.Solidity.Generic (genericFromRecordFields) -import Type.Proxy (Proxy(..)) -import Partial.Unsafe (unsafePartial) +import Network.Ethereum.Web3.Contract (sendTx, mkDataField) +import Network.Ethereum.Web3.Solidity (Tuple2, UIntN) import Network.Ethereum.Web3.Solidity.AbiEncoding (toDataBuilder) +import Network.Ethereum.Web3.Solidity.Generic (genericFromRecordFields) +import Network.Ethereum.Web3.Types (Address, HexString, NoPay, TransactionOptions, Web3) +import Test.QuickCheck (quickCheck, (===)) import Test.Spec (Spec, describe, it) -import Test.Spec.Assertions (shouldEqual) +import Type.Proxy (Proxy(..)) spec :: Spec Unit spec = describe "data maker" do - it "can make the approval data" do - let - addr = unsafePartial fromJust $ (mkAddress =<< mkHexString "78534a937a855e15be172de35f2211626f92f8ec") - - val = unsafePartial fromJust $ uIntNFromBigNumber s256 one - - approvalD = mkDataField (Proxy :: Proxy ApproveFn) { _spender: addr, _value: val } + it "can make the approval data" $ liftEffect do + quickCheck $ \(args :: { _spender :: Address, _value :: UIntN 256 }) -> + let + approvalD = mkDataField (Proxy :: Proxy ApproveFn) args - sel = toSelector "approve(address,uint256)" + sel = toSelector "approve(address,uint256)" - fullDat = sel <> toDataBuilder addr <> toDataBuilder val - approvalD `shouldEqual` fullDat + fullDat = sel <> toDataBuilder args._spender <> toDataBuilder args._value + in + approvalD === fullDat type ApproveFn = Tagged "approve(address,uint256)" (Tuple2 (Tagged "_spender" Address) (Tagged "_value" (UIntN 256))) diff --git a/test/web3/Web3Spec/Encoding/GenericSpec.purs b/test/web3/Web3Spec/Encoding/GenericSpec.purs index 5c41478..b064418 100644 --- a/test/web3/Web3Spec/Encoding/GenericSpec.purs +++ b/test/web3/Web3Spec/Encoding/GenericSpec.purs @@ -1,23 +1,15 @@ module Web3Spec.Encoding.GenericSpec (spec) where import Prelude -import Control.Error.Util (hush) -import Data.Array (unsafeIndex, uncons) + import Data.Functor.Tagged (Tagged, tagged) import Data.Generic.Rep (class Generic) -import Data.Eq.Generic (genericEq) -import Data.Show.Generic (genericShow) -import Data.Maybe (Maybe(..), fromJust) -import Data.Newtype (class Newtype, wrap) -import Record.Builder (build, merge) -import Type.Proxy (Proxy) -import Network.Ethereum.Web3.Solidity (Address, Tuple1, Tuple2(..), Tuple3(..), UIntN, fromData) -import Network.Ethereum.Web3.Solidity.Event (class IndexedEvent, decodeEvent, genericArrayParser) +import Effect.Class (liftEffect) +import Network.Ethereum.Web3.Solidity (Tuple2(..), Tuple3(..)) import Network.Ethereum.Web3.Solidity.Generic (genericToRecordFields) -import Network.Ethereum.Web3.Types (Change(..), HexString, embed, mkAddress, mkHexString) -import Partial.Unsafe (unsafePartial) +import Record.Builder (build, merge) +import Test.QuickCheck (quickCheck, (===)) import Test.Spec (Spec, describe, it) -import Test.Spec.Assertions (shouldEqual) spec :: Spec Unit spec = @@ -27,125 +19,60 @@ spec = toRecordFieldsSpec :: Spec Unit toRecordFieldsSpec = describe "test ToRecordFields class" do - it "pass toRecordFields basic test" do - let - as = Tuple3 (tagged 1) (tagged "hello") (tagged 'c') :: Tuple3 (Tagged "a" Int) (Tagged "d" String) (Tagged "e" Char) - WeirdTuple (genericToRecordFields as) - `shouldEqual` - WeirdTuple - { a: 1 - , d: "hello" - , e: 'c' - } - it "passes the merging test" do - let - as = Tuple3 (tagged 1) (tagged "hello") (tagged 'c') :: Tuple3 (Tagged "a" Int) (Tagged "d" String) (Tagged "e" Char) - - as' = Tuple2 (tagged 2) (tagged "bye") :: Tuple2 (Tagged "b" Int) (Tagged "c" String) + it "pass toRecordFields basic test" $ liftEffect do + quickCheck $ \(x :: { a :: Int, b :: Int, c :: String, d :: String }) -> + let + as = Tuple2 (tagged x.a) (tagged x.b) :: Tuple2 (Tagged "a" Int) (Tagged "b" Int) + bs = Tuple2 (tagged x.c) (tagged x.d) :: Tuple2 (Tagged "c" String) (Tagged "d" String) + in + (build (merge (genericToRecordFields as)) (genericToRecordFields bs)) + === + { a: x.a + , b: x.b + , c: x.c + , d: x.d + } + + it "pass toRecordFields basic test" $ liftEffect do + quickCheck $ \(x :: { a :: Int, b :: Int, c :: String, d :: String, e :: Char }) -> + let + as = Tuple3 (tagged x.a) (tagged x.d) (tagged x.e) :: Tuple3 (Tagged "a" Int) (Tagged "d" String) (Tagged "e" Char) + in + WeirdTuple (genericToRecordFields as) + === + WeirdTuple + { a: x.a + , d: x.d + , e: x.e + } + + it "passes the merging test" $ liftEffect do + quickCheck $ \(x :: { a :: Int, b :: Int, c :: String, d :: String, e :: Char }) -> + let + as = Tuple3 (tagged x.a) (tagged x.d) (tagged x.e) :: Tuple3 (Tagged "a" Int) (Tagged "d" String) (Tagged "e" Char) + + as' = Tuple2 (tagged x.b) (tagged x.c) :: Tuple2 (Tagged "b" Int) (Tagged "c" String) + + c = CombinedTuple $ build (merge (genericToRecordFields as)) (genericToRecordFields as') + in + c === CombinedTuple x - c = CombinedTuple $ build (merge (genericToRecordFields as)) (genericToRecordFields as') - c `shouldEqual` CombinedTuple { a: 1, b: 2, c: "bye", d: "hello", e: 'c' } - it "can parse a change an address array" do - let - (Transfer t) = transfer - - expected = Tuple2 (tagged t.to) (tagged t.from) :: Tuple2 (Tagged "to" Address) (Tagged "from" Address) - hush (fromData (unsafePartial $ unsafeIndex addressArray 1)) `shouldEqual` Just t.to - genericArrayParser (unsafePartial fromJust $ _.tail <$> uncons addressArray) `shouldEqual` Just expected - it "can combine events" do - decodeEvent change `shouldEqual` Just transfer +-------------------------------------------------------------------------------- newtype WeirdTuple = WeirdTuple { a :: Int, d :: String, e :: Char } -derive instance genericWeirdTuple :: Generic WeirdTuple _ - -instance showWeirdTuple :: Show WeirdTuple where - show = genericShow - -instance eqWeirdTuple :: Eq WeirdTuple where - eq = genericEq +derive instance Generic WeirdTuple _ +derive newtype instance Show WeirdTuple +derive newtype instance Eq WeirdTuple newtype OtherTuple = OtherTuple { b :: Int, c :: String } -derive instance genericOtherTuple :: Generic OtherTuple _ - -instance showOtherTuple :: Show OtherTuple where - show = genericShow - -instance eqOtherTuple :: Eq OtherTuple where - eq = genericEq - -data CombinedTuple = CombinedTuple { a :: Int, b :: Int, c :: String, d :: String, e :: Char } - -derive instance genericCombinedTuple :: Generic CombinedTuple _ - -instance showCombinedTuple :: Show CombinedTuple where - show = genericShow - -instance eqCombinedTuple :: Eq CombinedTuple where - eq = genericEq - --------------------------------------------------------------------------------- -newtype Transfer = Transfer { to :: Address, from :: Address, amount :: UIntN 256 } - -derive instance newtypeTransfer :: Newtype Transfer _ - -derive instance genericTransfer :: Generic Transfer _ - -instance indexedTransfer :: IndexedEvent (Tuple2 (Tagged "to" Address) (Tagged "from" Address)) (Tuple1 (Tagged "amount" (UIntN 256))) Transfer where - isAnonymous _ = false - -instance showTransfer :: Show Transfer where - show = genericShow - -instance eqTransfer :: Eq Transfer where - eq = genericEq - -transfer :: Transfer -transfer = - let - t = unsafePartial fromJust $ mkAddress =<< mkHexString "0x407d73d8a49eeb85d32cf465507dd71d507100c1" - - f = unsafePartial fromJust $ mkAddress =<< mkHexString "0x0000000000000000000000000000000000000001" - - a = unsafePartial fromJust $ map hush fromData =<< mkHexString "0x0000000000000000000000000000000000000000000000000000000000000001" - in - Transfer - { to: t - , from: f - , amount: a - } - -addressArray :: Array HexString -addressArray = - let - to = unsafePartial fromJust $ mkHexString "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" - - from = unsafePartial fromJust $ mkHexString "0x0000000000000000000000000000000000000000000000000000000000000001" - - topic = unsafePartial fromJust $ mkHexString "0x" - in - [ topic, to, from ] - -amount :: HexString -amount = unsafePartial fromJust $ mkHexString "0x0000000000000000000000000000000000000000000000000000000000000001" - -change :: Change -change = - Change - { data: amount - , topics: addressArray - , logIndex: zero - , transactionHash: tx - , transactionIndex: zero - , blockNumber: wrap $ embed 0 - , blockHash: bh - , address: a - , removed: false - } - where - bh = unsafePartial fromJust $ mkHexString "00" +derive instance Generic OtherTuple _ +derive newtype instance Show OtherTuple +derive newtype instance Eq OtherTuple - tx = unsafePartial fromJust $ mkHexString "00" +newtype CombinedTuple = CombinedTuple { a :: Int, b :: Int, c :: String, d :: String, e :: Char } - a = unsafePartial fromJust $ mkAddress =<< mkHexString "0x0000000000000000000000000000000000000000" +derive instance Generic CombinedTuple _ +derive newtype instance Show CombinedTuple +derive newtype instance Eq CombinedTuple \ No newline at end of file diff --git a/test/web3/Web3Spec/Encoding/SimpleSpec.purs b/test/web3/Web3Spec/Encoding/SimpleSpec.purs index d5c553b..6dfed1c 100644 --- a/test/web3/Web3Spec/Encoding/SimpleSpec.purs +++ b/test/web3/Web3Spec/Encoding/SimpleSpec.purs @@ -1,254 +1,25 @@ module Web3Spec.Encoding.SimpleSpec (spec) where import Prelude -import Effect.Aff (Aff, error, throwError) +import Effect.Aff (error, throwError) import Control.Monad.Except (runExcept) -import Data.Array (replicate) -import Data.ByteString as BS import Data.Either (Either(Right), either) -import Data.Foldable (intercalate) import Foreign (ForeignError) import Data.List.Types (NonEmptyList) import Data.Maybe (Maybe(..), fromJust) import Data.Newtype (unwrap) -import Data.String (toLower) -import Data.Traversable (sequence) -import Network.Ethereum.Core.BigNumber (pow) -import Network.Ethereum.Web3.Solidity.AbiEncoding (class ABIEncode, class ABIDecode, toDataBuilder, fromData) -import Network.Ethereum.Web3.Solidity.Bytes (fromByteString) -import Network.Ethereum.Web3.Solidity.Int (intNFromBigNumber) -import Network.Ethereum.Web3.Solidity.Sizes (s1, s12, s16, s248, s256, s3, s8) -import Network.Ethereum.Web3.Solidity.UInt (uIntNFromBigNumber) -import Network.Ethereum.Web3.Types (Block, FalseOrObject(..), HexString, BigNumber, SyncStatus(..), embed, mkAddress, mkHexString, unHex) +import Network.Ethereum.Web3.Types (BigNumber, Block, FalseOrObject(..), HexString, SyncStatus(..), embed, mkHexString) import Partial.Unsafe (unsafePartial) import Simple.JSON (readJSON') import Test.Spec (Spec, describe, it) -import Test.Spec.Assertions (shouldEqual, shouldNotEqual) +import Test.Spec.Assertions (shouldEqual) spec :: Spec Unit spec = describe "encoding-spec" do - stringTests - bytesDTests - bytesNTests - intTests - uintNTests - intNTests - addressTests falseOrObjectTests blockTests -roundTrip :: forall a. Show a => Eq a => ABIEncode a => ABIDecode a => a -> HexString -> Aff Unit -roundTrip decoded encoded = do - encoded `shouldEqual` toDataBuilder decoded - fromData encoded `shouldEqual` Right decoded - -stringTests :: Spec Unit -stringTests = - describe "string tests" do - it "can encode simple strings" do - let - given = "gavofyork" - let - expected = - unsafePartial fromJust <<< mkHexString $ "0000000000000000000000000000000000000000000000000000000000000009" - <> "6761766f66796f726b0000000000000000000000000000000000000000000000" - roundTrip given expected - it "can encode complicated strings" do - let - given = "welcome to ethereum. welcome to ethereum. welcome to ethereum." - let - expected = - unsafePartial fromJust <<< mkHexString $ "000000000000000000000000000000000000000000000000000000000000003e" - <> "77656c636f6d6520746f20657468657265756d2e2077656c636f6d6520746f20" - <> "657468657265756d2e2077656c636f6d6520746f20657468657265756d2e0000" - roundTrip given expected - it "can encode unicode strings" do - let - given = "ää" - let - expected = - unsafePartial fromJust <<< mkHexString $ "0000000000000000000000000000000000000000000000000000000000000008" - <> "c383c2a4c383c2a4000000000000000000000000000000000000000000000000" - roundTrip given expected - it "can handle VERY long HexStrings" do - let - given = intercalate "" $ replicate 128 "0000000000000000000000000000000000000000000000000000000000000000" - let - expected = unsafePartial fromJust <<< mkHexString $ given - given `shouldEqual` unHex expected - it "can handle mixed case HexStrings" do - let - given = "fF" - let - expected = unsafePartial fromJust <<< mkHexString $ given - -- note; for easy equality we should canonicalize HexStrings as lowercase - toLower given `shouldEqual` unHex expected - it "fails on odd length HexStrings" do - let - givens = [ "f", "0", "000", "0f0", "fffff", "0000000000000000000000000000000000000000f" ] - _ <- sequence $ map (\g -> mkHexString g `shouldEqual` Nothing) givens - pure unit - it "should hold equality across cases" do - mkHexString "ff" `shouldEqual` mkHexString "Ff" - mkHexString "0000aa" `shouldEqual` mkHexString "0000AA" - mkHexString "0000aa" `shouldEqual` mkHexString "0000aa" - mkHexString "abcdef" `shouldEqual` mkHexString "AbCdEf" - mkHexString "" `shouldNotEqual` mkHexString "ff" - mkHexString "ff" `shouldNotEqual` mkHexString "aa" - -bytesDTests :: Spec Unit -bytesDTests = - describe "bytesD tests" do - it "can encode short bytesD" do - let - given = unsafePartial $ fromJust $ flip BS.fromString BS.Hex $ "c3a40000c3a4" - let - expected = - unsafePartial fromJust <<< mkHexString - $ "0000000000000000000000000000000000000000000000000000000000000006" - <> "c3a40000c3a40000000000000000000000000000000000000000000000000000" - roundTrip given expected - it "can encode long bytesD" do - let - given = - unsafePartial $ fromJust $ flip BS.fromString BS.Hex - $ "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - <> "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - <> "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - <> "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - <> "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1" - let - expected = - unsafePartial fromJust <<< mkHexString - $ "000000000000000000000000000000000000000000000000000000000000009f" - <> "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - <> "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - <> "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - <> "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - <> "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff100" - roundTrip given expected - it "can encode dave" do - let - given = "dave" - let - expected = - unsafePartial fromJust <<< mkHexString $ "0000000000000000000000000000000000000000000000000000000000000004" - <> "6461766500000000000000000000000000000000000000000000000000000000" - roundTrip given expected - -bytesNTests :: Spec Unit -bytesNTests = - describe "byteN tests" do - it "can encode Bytes1" do - let - mgiven = fromByteString s1 <<< unsafePartial fromJust $ flip BS.fromString BS.Hex $ "cf" - - given = unsafePartial $ fromJust mgiven - - expected = unsafePartial fromJust <<< mkHexString $ "cf00000000000000000000000000000000000000000000000000000000000000" - roundTrip given expected - it "can encode Bytes3" do - let - mgiven = fromByteString s3 $ unsafePartial $ fromJust $ flip BS.fromString BS.Hex $ "cf0011" - - given = unsafePartial $ fromJust mgiven - - expected = unsafePartial fromJust <<< mkHexString $ "cf00110000000000000000000000000000000000000000000000000000000000" - roundTrip given expected - it "can encode Bytes12" do - let - mgiven = fromByteString s12 $ unsafePartial $ fromJust $ flip BS.fromString BS.Hex $ "6761766f66796f726b000000" - - given = unsafePartial $ fromJust mgiven - - expected = unsafePartial fromJust <<< mkHexString $ "6761766f66796f726b0000000000000000000000000000000000000000000000" - roundTrip given expected - -intTests :: Spec Unit -intTests = - describe "int/uint tests" do - it "can encode int" do - let - given = 21 - let - expected = unsafePartial fromJust <<< mkHexString $ "0000000000000000000000000000000000000000000000000000000000000015" - roundTrip given expected - it "can encode negative numbers" do - let - given = negate 1 - let - expected = unsafePartial fromJust <<< mkHexString $ "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - roundTrip given expected - it "can encode some big number" do - let - given = 987654321 - let - expected = unsafePartial fromJust <<< mkHexString $ "000000000000000000000000000000000000000000000000000000003ade68b1" - roundTrip given expected - -addressTests :: Spec Unit -addressTests = - describe "addresses tests" do - it "can encode address" do - let - given = unsafePartial fromJust $ mkAddress =<< mkHexString "407d73d8a49eeb85d32cf465507dd71d507100c1" - let - expected = unsafePartial fromJust <<< mkHexString $ "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" - roundTrip given expected - -uintNTests :: Spec Unit -uintNTests = - describe "uint tests" do - it "can encode uint8" do - let - mgiven = uIntNFromBigNumber s8 $ (embed 2) `pow` 8 - one - - given = unsafePartial $ fromJust mgiven - - expected = unsafePartial fromJust <<< mkHexString $ "00000000000000000000000000000000000000000000000000000000000000ff" - roundTrip given expected - it "can encode larger uint256" do - let - mgiven = uIntNFromBigNumber s256 $ ((embed $ 2) `pow` 256) - one - - given = unsafePartial $ fromJust mgiven - - expected = unsafePartial fromJust <<< mkHexString $ "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - roundTrip given expected - it "can fail to encode larger uin248" do - let - mgiven = (uIntNFromBigNumber s248 $ (embed $ 2) `pow` 256 - one) - mgiven `shouldEqual` Nothing - -intNTests :: Spec Unit -intNTests = - describe "uint tests" do - it "can encode int16" do - let - mgiven = intNFromBigNumber s16 $ embed $ negate 1 - - given = unsafePartial $ fromJust mgiven - - expected = unsafePartial fromJust <<< mkHexString $ "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - roundTrip given expected - it "can encode larger uint256" do - let - mgiven = intNFromBigNumber s256 $ ((embed $ 2) `pow` 255) - one - - given = unsafePartial $ fromJust mgiven - - expected = unsafePartial fromJust <<< mkHexString $ "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - roundTrip given expected - it "can fail to encode larger int248" do - let - mgiven = uIntNFromBigNumber s248 $ (embed $ 2) `pow` 255 - one - mgiven `shouldEqual` Nothing - it "can fail to encode larger negative int248" do - let - mgiven = uIntNFromBigNumber s248 $ negate $ (embed $ 2) `pow` 255 + one - mgiven `shouldEqual` Nothing - falseOrObjectTests :: Spec Unit falseOrObjectTests = describe "FalseOrObject tests" do diff --git a/test/web3/Web3Spec/Live/Utils.purs b/test/web3/Web3Spec/Live/Utils.purs index 456f228..ad2ff38 100644 --- a/test/web3/Web3Spec/Live/Utils.purs +++ b/test/web3/Web3Spec/Live/Utils.purs @@ -1,16 +1,21 @@ -module Web3Spec.Live.Utils where +module Web3Spec.Live.Utils + ( assertWeb3 + , bigGasLimit + , defaultTestTxOptions + , go + , joinWeb3Fork + , nullAddress + , pollTransactionReceipt + , takeEvent + ) where import Prelude import Control.Monad.Reader (ReaderT, runReaderT) -import Data.Array ((!!)) import Data.Array.NonEmpty as NAE -import Data.ByteString as BS import Data.Either (Either(..)) import Data.Lens ((?~)) -import Data.Maybe (Maybe(..), fromJust) -import Data.Newtype (wrap, unwrap) -import Data.Reflectable (class Reflectable) +import Data.Maybe (fromJust) import Data.Traversable (intercalate) import Data.Tuple (Tuple(..)) import Effect.Aff (Aff, Milliseconds(..), Fiber, joinFiber, delay) @@ -19,9 +24,9 @@ import Effect.Aff.Class (class MonadAff, liftAff) import Effect.Class.Console as C import Network.Ethereum.Core.BigNumber (decimal, fromStringAs) import Network.Ethereum.Core.Signatures (mkAddress) -import Network.Ethereum.Web3 (class EventFilter, Address, Web3Error, BigNumber, BlockNumber, BytesN, CallError, EventAction(..), HexString, Provider, TransactionOptions, TransactionReceipt(..), TransactionStatus(..), UIntN, Web3, _from, _gas, defaultTransactionOptions, event, embed, eventFilter, forkWeb3', fromByteString, intNFromBigNumber, mkHexString, runWeb3, uIntNFromBigNumber) +import Network.Ethereum.Web3 (class EventFilter, Address, BigNumber, EventAction(..), HexString, Provider, TransactionOptions, TransactionReceipt(..), TransactionStatus(..), Web3, Web3Error, _gas, defaultTransactionOptions, event, eventFilter, forkWeb3', mkHexString, runWeb3) import Network.Ethereum.Web3.Api as Api -import Network.Ethereum.Web3.Solidity (class DecodeEvent, IntN) +import Network.Ethereum.Web3.Solidity (class DecodeEvent) import Network.Ethereum.Web3.Types (NoPay) import Partial.Unsafe (unsafeCrashWith, unsafePartial) import Test.Spec (ComputationType(..), SpecT, hoistSpec) @@ -75,19 +80,6 @@ assertWeb3 provider a = Right x -> x Left err -> unsafeCrashWith $ "expected Right in `assertWeb3`, got error" <> show err -assertStorageCall - :: forall m a - . MonadAff m - => Provider - -> Web3 (Either CallError a) - -> m a -assertStorageCall p f = - liftAff do - eRes <- assertWeb3 p f - case eRes of - Right x -> pure x - Left err -> unsafeCrashWith $ "expected Right in `assertStorageCall`, got error" <> show err - pollTransactionReceipt :: forall m a . MonadAff m @@ -106,67 +98,6 @@ pollTransactionReceipt provider txHash k = Succeeded -> k receipt Failed -> unsafeCrashWith $ "Transaction failed : " <> show txHash -hangOutTillBlock - :: forall m - . MonadAff m - => Provider - -> Logger m - -> BlockNumber - -> m Unit -hangOutTillBlock provider logger bn = do - bn' <- assertWeb3 provider Api.eth_blockNumber - logger $ "Current block number : " <> show bn' - when (bn' < bn) do - liftAff $ delay (Milliseconds 1000.0) - hangOutTillBlock provider logger bn - -awaitNextBlock - :: forall m - . MonadAff m - => Provider - -> Logger m - -> m Unit -awaitNextBlock provider logger = do - n <- assertWeb3 provider Api.eth_blockNumber - let - next = wrap $ embed 1 + unwrap n - logger $ "Awaiting block number " <> show next - hangOutTillBlock provider logger next - -type ContractConfig = - { contractAddress :: Address - , userAddress :: Address - } - -deployContract - :: forall m - . MonadAff m - => Provider - -> Logger m - -> String - -> (TransactionOptions NoPay -> Web3 HexString) - -> m ContractConfig -deployContract p logger contractName deploymentTx = do - userAddress <- - assertWeb3 p - $ do - accounts <- Api.eth_getAccounts - pure $ unsafePartial fromJust $ accounts !! 0 - txHash <- - assertWeb3 p do - let - txOpts = defaultTestTxOptions # _from ?~ userAddress - txHash <- deploymentTx txOpts - pure txHash - logger $ "Submitted " <> contractName <> " deployment : " <> show txHash - let - k (TransactionReceipt rec) = case rec.contractAddress of - Nothing -> unsafeCrashWith "Contract deployment missing contractAddress in receipt" - Just addr -> pure addr - contractAddress <- pollTransactionReceipt p txHash k - logger $ contractName <> " successfully deployed to " <> show contractAddress - pure $ { contractAddress, userAddress } - joinWeb3Fork :: forall a m . MonadAff m @@ -179,35 +110,6 @@ joinWeb3Fork fiber = Left e -> unsafeCrashWith $ "Error in forked web3 process " <> show e Right a -> pure a -mkHexString' - :: String - -> HexString -mkHexString' hx = unsafePartial fromJust $ mkHexString hx - -mkUIntN - :: forall n - . Reflectable n Int - => Proxy n - -> Int - -> UIntN n -mkUIntN p n = unsafePartial fromJust $ uIntNFromBigNumber p $ embed n - -mkIntN - :: forall n - . Reflectable n Int - => Proxy n - -> Int - -> IntN n -mkIntN p n = unsafePartial fromJust $ intNFromBigNumber p $ embed n - -mkBytesN - :: forall n - . Reflectable n Int - => Proxy n - -> String - -> BytesN n -mkBytesN p s = unsafePartial fromJust $ fromByteString p =<< flip BS.fromString BS.Hex s - defaultTestTxOptions :: TransactionOptions NoPay defaultTestTxOptions = defaultTransactionOptions # _gas ?~ bigGasLimit diff --git a/test/web3/Web3Spec/Types/VectorSpec.purs b/test/web3/Web3Spec/Types/VectorSpec.purs index 8890d9d..8a56c94 100644 --- a/test/web3/Web3Spec/Types/VectorSpec.purs +++ b/test/web3/Web3Spec/Types/VectorSpec.purs @@ -67,27 +67,6 @@ test8 :: Vector 100000000000001 Int -- test8 :: Vector _ Int test8 = 1 :< 1 :< vec99999999999999 --- todo: delete this? --- test10 :: forall (n :: Int). Add n 1 10 => Vector n Int -> Vector 10 Int --- test10 l = 2 :< l - --- test10_ :: Vector _ Int --- test10_ :: Vector 10 Int --- test10_ = test10 vec9 - --- todo: delete this? --- test11 :: forall n. Add n 1 0 => Vector n Int -> Vector 0 Int --- test11 l = 2 :< l - --- As expected `test11` can be written, but can't be called --- test11_ = test11 nilVector --- we can write uncons like this, but when it's used see `test12` if you --- remove type annotation code will fail to compile. if inc and all --- classes which it's using had reverse functional dependencies --- then compiler could potentially infer type, but we don't have --- such implementation for `Inc` and even with such version [1] --- compiler still gives horrible error --- https://gist.github.com/safareli/e1d3805a48a0a772d72ed895945c3607#file-digitswithsupperclass-purs-L38-L103 vUncons :: forall a n nDec. Add nDec 1 n => Vector n a -> { head :: a, tail :: Vector nDec a } vUncons as = case uncons $ unsafeCoerce as of Nothing -> unsafeCrashWith "impossible case in vUncons from Network.Ethereum.Web3.Solidity.Vector"