summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakru <>2017-11-14 12:52:00 (GMT)
committerhdiff <hdiff@hdiff.luite.com>2017-11-14 12:52:00 (GMT)
commit4ed06e004480d236ec24aa769155bbead9382c7f (patch)
tree80e6b639c11ad769e88a311ff7cdf47ade9034a7
parent2909a1bc06a3c9b0927bdb282380697fb9ecf39d (diff)
version 0.6.0.0HEAD0.6.0.0master
-rw-r--r--README.md2
-rw-r--r--src/Network/Ethereum/Unit.hs18
-rw-r--r--src/Network/Ethereum/Web3.hs16
-rw-r--r--src/Network/Ethereum/Web3/Address.hs40
-rw-r--r--src/Network/Ethereum/Web3/Api.hs84
-rw-r--r--src/Network/Ethereum/Web3/Contract.hs52
-rw-r--r--src/Network/Ethereum/Web3/Encoding.hs22
-rw-r--r--src/Network/Ethereum/Web3/Encoding/Bytes.hs34
-rw-r--r--src/Network/Ethereum/Web3/Encoding/Internal.hs23
-rw-r--r--src/Network/Ethereum/Web3/Encoding/Tuple.hs6
-rw-r--r--src/Network/Ethereum/Web3/Encoding/TupleTH.hs24
-rw-r--r--src/Network/Ethereum/Web3/Eth.hs240
-rw-r--r--src/Network/Ethereum/Web3/Internal.hs6
-rw-r--r--src/Network/Ethereum/Web3/JsonAbi.hs32
-rw-r--r--src/Network/Ethereum/Web3/JsonRpc.hs27
-rw-r--r--src/Network/Ethereum/Web3/Net.hs32
-rw-r--r--src/Network/Ethereum/Web3/Provider.hs8
-rw-r--r--src/Network/Ethereum/Web3/TH.hs79
-rw-r--r--src/Network/Ethereum/Web3/Types.hs101
-rw-r--r--src/Network/Ethereum/Web3/Web3.hs27
-rw-r--r--test/Spec.hs11
-rw-r--r--web3.cabal10
22 files changed, 569 insertions, 325 deletions
diff --git a/README.md b/README.md
index dd3db62..dbe9041 100644
--- a/README.md
+++ b/README.md
@@ -5,9 +5,9 @@ This is the Ethereum compatible Haskell API which implements the [Generic JSON R
[![Build Status](https://travis-ci.org/airalab/hs-web3.svg?branch=master)](https://travis-ci.org/airalab/hs-web3)
[![Build status](https://ci.appveyor.com/api/projects/status/8ljq93nar8kobk75?svg=true)](https://ci.appveyor.com/project/akru/hs-web3)
[![Hackage](https://img.shields.io/hackage/v/web3.svg)](http://hackage.haskell.org/package/web3)
-![Hackage Dependencies](https://img.shields.io/hackage-deps/v/web3.svg)
![Haskell Programming Language](https://img.shields.io/badge/language-Haskell-blue.svg)
![BSD3 License](http://img.shields.io/badge/license-BSD3-brightgreen.svg)
+[![Code Triagers Badge](https://www.codetriage.com/airalab/hs-web3/badges/users.svg)](https://www.codetriage.com/airalab/hs-web3)
### Installation
diff --git a/src/Network/Ethereum/Unit.hs b/src/Network/Ethereum/Unit.hs
index 841c990..829a3ef 100644
--- a/src/Network/Ethereum/Unit.hs
+++ b/src/Network/Ethereum/Unit.hs
@@ -1,5 +1,6 @@
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TypeSynonymInstances #-}
-- |
-- Module : Network.Ethereum.Unit
-- Copyright : Alexander Krupenkin 2016
@@ -54,12 +55,13 @@ module Network.Ethereum.Unit (
, KEther
) where
-import Text.ParserCombinators.ReadPrec
-import Data.Text.Lazy (Text, unpack)
-import qualified Text.Read.Lex as L
-import Data.Monoid ((<>))
-import Text.Printf
-import GHC.Read
+import Data.Monoid ((<>))
+import Data.Text.Lazy (Text, unpack)
+import GHC.Generics (Generic)
+import GHC.Read
+import Text.ParserCombinators.ReadPrec
+import Text.Printf
+import qualified Text.Read.Lex as L
-- | Ethereum value unit
class (Read a, Show a, UnitSpec a, Fractional a) => Unit a where
@@ -79,7 +81,7 @@ class UnitSpec a where
-- | Value abstraction
data Value a = MkValue { unValue :: Integer }
- deriving (Eq, Ord)
+ deriving (Eq, Ord, Generic)
mkValue :: (UnitSpec a, RealFrac b) => b -> Value a
mkValue = modify res . round . (divider res *)
diff --git a/src/Network/Ethereum/Web3.hs b/src/Network/Ethereum/Web3.hs
index 53f88d2..9d80a79 100644
--- a/src/Network/Ethereum/Web3.hs
+++ b/src/Network/Ethereum/Web3.hs
@@ -39,11 +39,11 @@ module Network.Ethereum.Web3 (
, module Network.Ethereum.Unit
) where
-import Network.Ethereum.Web3.Encoding.Bytes
-import Network.Ethereum.Web3.Encoding.Tuple
-import Network.Ethereum.Web3.Contract
-import Network.Ethereum.Web3.Encoding
-import Network.Ethereum.Web3.Provider
-import Network.Ethereum.Web3.Address
-import Network.Ethereum.Web3.Types
-import Network.Ethereum.Unit
+import Network.Ethereum.Unit
+import Network.Ethereum.Web3.Address
+import Network.Ethereum.Web3.Contract
+import Network.Ethereum.Web3.Encoding
+import Network.Ethereum.Web3.Encoding.Bytes
+import Network.Ethereum.Web3.Encoding.Tuple
+import Network.Ethereum.Web3.Provider
+import Network.Ethereum.Web3.Types
diff --git a/src/Network/Ethereum/Web3/Address.hs b/src/Network/Ethereum/Web3/Address.hs
index 7e04288..90291c1 100644
--- a/src/Network/Ethereum/Web3/Address.hs
+++ b/src/Network/Ethereum/Web3/Address.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DeriveGeneric #-}
-- |
-- Module : Network.Ethereum.Web3.Address
-- Copyright : Alexander Krupenkin 2016
@@ -16,20 +17,24 @@ module Network.Ethereum.Web3.Address (
, zero
) where
-import Data.Aeson (FromJSON(..), ToJSON(..), Value(..))
-import Data.Text.Lazy.Builder.Int as B (hexadecimal)
-import Data.Text.Lazy.Builder (toLazyText)
-import Data.Text.Read as R (hexadecimal)
-import Data.Text (Text, unpack, pack)
-import Data.String (IsString(..))
-import Data.Text.Lazy (toStrict)
-import qualified Data.Text as T
-import Control.Monad ((<=<))
-import Data.Monoid ((<>))
+import Control.Monad ((<=<))
+import Data.Aeson (FromJSON (..), ToJSON (..),
+ Value (..))
+import qualified Data.Char as C
+import Data.Monoid ((<>))
+import Data.String (IsString (..))
+import Data.Text (Text, pack, unpack)
+import qualified Data.Text as T
+import Data.Text.Lazy (toStrict)
+import Data.Text.Lazy.Builder (toLazyText)
+import Data.Text.Lazy.Builder.Int as B (hexadecimal)
+import Data.Text.Read as R (hexadecimal)
+
+import GHC.Generics (Generic)
-- | Ethereum account address
newtype Address = Address { unAddress :: Integer }
- deriving (Eq, Ord)
+ deriving (Eq, Ord, Generic)
instance Show Address where
show = unpack . toText
@@ -37,11 +42,11 @@ instance Show Address where
instance IsString Address where
fromString a = case fromText (pack a) of
Right address -> address
- Left e -> error e
+ Left e -> error e
instance FromJSON Address where
parseJSON (String a) = either fail return (fromText a)
- parseJSON _ = fail "Address should be a string"
+ parseJSON _ = fail "Address should be a string"
instance ToJSON Address where
toJSON = toJSON . ("0x" <>) . toText
@@ -50,10 +55,11 @@ instance ToJSON Address where
fromText :: Text -> Either String Address
fromText = fmap (Address . fst) . R.hexadecimal <=< check
where check t | T.take 2 t == "0x" = check (T.drop 2 t)
- | otherwise = if T.length t == 40 && T.all (`elem` valid) t
- then Right t
- else Left "This is not seems like address."
- valid = ['0'..'9'] ++ ['a'..'f'] ++ ['A'..'F']
+ | otherwise = do if T.length t == 40 then pure () else lengthError
+ if T.all C.isHexDigit t then pure () else invalidCharError
+ pure t
+ lengthError = Left "Invalid Address: text length not equal to 20"
+ invalidCharError = Left "Invalid Address: contains non-hex character"
-- | Render 'Address' to text string
toText :: Address -> Text
diff --git a/src/Network/Ethereum/Web3/Api.hs b/src/Network/Ethereum/Web3/Api.hs
deleted file mode 100644
index 00bc4a9..0000000
--- a/src/Network/Ethereum/Web3/Api.hs
+++ /dev/null
@@ -1,84 +0,0 @@
--- |
--- Module : Network.Ethereum.Web3.Api
--- Copyright : Alexander Krupenkin 2016
--- License : BSD3
---
--- Maintainer : mail@akru.me
--- Stability : experimental
--- Portability : unknown
---
--- Ethereum node JSON-RPC API methods.
---
-module Network.Ethereum.Web3.Api where
-
-import Network.Ethereum.Web3.Provider
-import Network.Ethereum.Web3.Address
-import Network.Ethereum.Web3.JsonRpc
-import Network.Ethereum.Web3.Types
-import Data.Text (Text)
-
--- | Returns current node version string.
-web3_clientVersion :: Provider a => Web3 a Text
-{-# INLINE web3_clientVersion #-}
-web3_clientVersion = remote "web3_clientVersion"
-
--- | Returns Keccak-256 (not the standardized SHA3-256) of the given data.
-web3_sha3 :: Provider a => Text -> Web3 a Text
-{-# INLINE web3_sha3 #-}
-web3_sha3 = remote "web3_sha3"
-
--- | Returns the balance of the account of given address.
-eth_getBalance :: Provider a => Address -> CallMode -> Web3 a Text
-{-# INLINE eth_getBalance #-}
-eth_getBalance = remote "eth_getBalance"
-
--- | Creates a filter object, based on filter options, to notify when the
--- state changes (logs). To check if the state has changed, call
--- 'getFilterChanges'.
-eth_newFilter :: Provider a => Filter -> Web3 a FilterId
-{-# INLINE eth_newFilter #-}
-eth_newFilter = remote "eth_newFilter"
-
--- | Polling method for a filter, which returns an array of logs which
--- occurred since last poll.
-eth_getFilterChanges :: Provider a => FilterId -> Web3 a [Change]
-{-# INLINE eth_getFilterChanges #-}
-eth_getFilterChanges = remote "eth_getFilterChanges"
-
--- | Uninstalls a filter with given id.
--- Should always be called when watch is no longer needed.
-eth_uninstallFilter :: Provider a => FilterId -> Web3 a Bool
-{-# INLINE eth_uninstallFilter #-}
-eth_uninstallFilter = remote "eth_uninstallFilter"
-
--- | Executes a new message call immediately without creating a
--- transaction on the block chain.
-eth_call :: Provider a => Call -> CallMode -> Web3 a Text
-{-# INLINE eth_call #-}
-eth_call = remote "eth_call"
-
--- | Creates new message call transaction or a contract creation,
--- if the data field contains code.
-eth_sendTransaction :: Provider a => Call -> Web3 a Text
-{-# INLINE eth_sendTransaction #-}
-eth_sendTransaction = remote "eth_sendTransaction"
-
--- | Returns a list of addresses owned by client.
-eth_accounts :: Provider a => Web3 a [Address]
-{-# INLINE eth_accounts #-}
-eth_accounts = remote "eth_accounts"
-
-eth_newBlockFilter :: Provider a => Web3 a Text
-{-# INLINE eth_newBlockFilter #-}
-eth_newBlockFilter = remote "eth_newBlockFilter"
-
--- | Polling method for a block filter, which returns an array of block hashes
--- occurred since last poll.
-eth_getBlockFilterChanges :: Provider a => Text -> Web3 a [Text]
-{-# INLINE eth_getBlockFilterChanges #-}
-eth_getBlockFilterChanges = remote "eth_getFilterChanges"
-
--- | Returns information about a block by hash.
-eth_getBlockByHash :: Provider a => Text -> Web3 a Block
-{-# INLINE eth_getBlockByHash #-}
-eth_getBlockByHash = flip (remote "eth_getBlockByHash") True
diff --git a/src/Network/Ethereum/Web3/Contract.hs b/src/Network/Ethereum/Web3/Contract.hs
index e9eaed3..409ef3f 100644
--- a/src/Network/Ethereum/Web3/Contract.hs
+++ b/src/Network/Ethereum/Web3/Contract.hs
@@ -35,24 +35,24 @@ module Network.Ethereum.Web3.Contract (
, nopay
) where
-import qualified Data.Text.Lazy.Builder.Int as B
-import qualified Data.Text.Lazy.Builder as B
-import Control.Concurrent (ThreadId, threadDelay)
-import Data.Maybe (mapMaybe, listToMaybe)
-import Control.Monad.IO.Class (liftIO)
-import Control.Exception (throwIO)
-import Data.Text.Lazy (toStrict)
-import qualified Data.Text as T
-import Control.Monad (when, forM)
-import Control.Monad.Trans.Reader (ReaderT(..))
-import Data.Monoid ((<>))
+import Control.Concurrent (ThreadId, threadDelay)
+import Control.Exception (throwIO)
+import Control.Monad (forM, when)
+import Control.Monad.IO.Class (liftIO)
+import Control.Monad.Trans.Reader (ReaderT (..))
+import Data.Maybe (listToMaybe, mapMaybe)
+import Data.Monoid ((<>))
+import qualified Data.Text as T
+import Data.Text.Lazy (toStrict)
+import qualified Data.Text.Lazy.Builder as B
+import qualified Data.Text.Lazy.Builder.Int as B
-import Network.Ethereum.Web3.Provider
-import Network.Ethereum.Web3.Encoding
-import Network.Ethereum.Web3.Address
-import Network.Ethereum.Web3.Types
-import Network.Ethereum.Web3.Api
-import Network.Ethereum.Unit
+import Network.Ethereum.Unit
+import Network.Ethereum.Web3.Address
+import Network.Ethereum.Web3.Encoding
+import qualified Network.Ethereum.Web3.Eth as Eth
+import Network.Ethereum.Web3.Provider
+import Network.Ethereum.Web3.Types
-- | Event callback control response
data EventAction = ContinueEvent
@@ -83,16 +83,16 @@ _event :: (Provider p, Event a)
_event a f = do
fid <- let ftyp = snd $ let x = undefined :: Event a => a
in (f x, x)
- in eth_newFilter (eventFilter ftyp a)
+ in Eth.newFilter (eventFilter ftyp a)
forkWeb3 $
let loop = do liftIO (threadDelay 1000000)
- changes <- eth_getFilterChanges fid
+ changes <- Eth.getFilterChanges fid
acts <- forM (mapMaybe pairChange changes) $ \(changeEvent, changeWithMeta) ->
runReaderT (f changeEvent) changeWithMeta
when (TerminateEvent `notElem` acts) loop
in do loop
- eth_uninstallFilter fid
+ Eth.uninstallFilter fid
return ()
where
prepareTopics = fmap (T.drop 2) . drop 1
@@ -120,7 +120,7 @@ class ABIEncoding a => Method a where
call :: (Provider p, ABIEncoding b)
=> Address
-- ^ Contract address
- -> CallMode
+ -> DefaultBlock
-- ^ State mode for constant call (latest or pending)
-> a
-- ^ Method data
@@ -131,17 +131,17 @@ class ABIEncoding a => Method a where
_sendTransaction :: (Provider p, Method a, Unit b)
=> Address -> b -> a -> Web3 p TxHash
_sendTransaction to value dat = do
- primeAddress <- listToMaybe <$> eth_accounts
- eth_sendTransaction (txdata primeAddress $ Just $ toData dat)
+ primeAddress <- listToMaybe <$> Eth.accounts
+ Eth.sendTransaction (txdata primeAddress $ Just $ toData dat)
where txdata from = Call from to (Just defaultGas) Nothing (Just $ toWeiText value)
toWeiText = ("0x" <>) . toStrict . B.toLazyText . B.hexadecimal . toWei
defaultGas = "0x2DC2DC"
_call :: (Provider p, Method a, ABIEncoding b)
- => Address -> CallMode -> a -> Web3 p b
+ => Address -> DefaultBlock -> a -> Web3 p b
_call to mode dat = do
- primeAddress <- listToMaybe <$> eth_accounts
- res <- eth_call (txdata primeAddress) mode
+ primeAddress <- listToMaybe <$> Eth.accounts
+ res <- Eth.call (txdata primeAddress) mode
case fromData (T.drop 2 res) of
Nothing -> liftIO $ throwIO $ ParserFail $
"Unable to parse result on `" ++ T.unpack res
diff --git a/src/Network/Ethereum/Web3/Encoding.hs b/src/Network/Ethereum/Web3/Encoding.hs
index e12e2e7..921dc50 100644
--- a/src/Network/Ethereum/Web3/Encoding.hs
+++ b/src/Network/Ethereum/Web3/Encoding.hs
@@ -11,16 +11,18 @@
--
module Network.Ethereum.Web3.Encoding (ABIEncoding(..)) where
-import Data.Text.Lazy.Builder (Builder, toLazyText, fromText, fromLazyText)
-import Data.Attoparsec.Text.Lazy (parse, maybeResult, Parser)
-import qualified Network.Ethereum.Web3.Address as A
-import qualified Data.Attoparsec.Text as P
-import qualified Data.Text.Lazy as LT
-import qualified Data.Text as T
-import Network.Ethereum.Web3.Encoding.Internal
-import Network.Ethereum.Web3.Address (Address)
-import Data.Monoid ((<>))
-import Data.Text (Text)
+import qualified Data.Attoparsec.Text as P
+import Data.Attoparsec.Text.Lazy (Parser, maybeResult,
+ parse)
+import Data.Monoid ((<>))
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as LT
+import Data.Text.Lazy.Builder (Builder, fromLazyText,
+ fromText, toLazyText)
+import Network.Ethereum.Web3.Address (Address)
+import qualified Network.Ethereum.Web3.Address as A
+import Network.Ethereum.Web3.Encoding.Internal
-- | Contract ABI data codec
class ABIEncoding a where
diff --git a/src/Network/Ethereum/Web3/Encoding/Bytes.hs b/src/Network/Ethereum/Web3/Encoding/Bytes.hs
index d45417e..9679b10 100644
--- a/src/Network/Ethereum/Web3/Encoding/Bytes.hs
+++ b/src/Network/Ethereum/Web3/Encoding/Bytes.hs
@@ -1,5 +1,7 @@
-{-# LANGUAGE KindSignatures #-}
-{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE ScopedTypeVariables #-}
-- |
-- Module : Network.Ethereum.Web3.Encoding.Bytes
-- Copyright : Alexander Krupenkin 2016
@@ -16,19 +18,21 @@ module Network.Ethereum.Web3.Encoding.Bytes (
, BytesD(..)
) where
-import qualified Data.ByteString.Base16 as BS16 (decode, encode)
-import qualified Data.Attoparsec.Text as P
-import qualified Data.Text.Lazy.Builder as B
-import qualified Data.Text.Encoding as T
-import qualified Data.Text as T
-import qualified Data.ByteArray as BA
-import Network.Ethereum.Web3.Encoding.Internal
-import Network.Ethereum.Web3.Encoding
-import GHC.TypeLits (KnownNat, Nat, natVal)
-import Data.Monoid (Monoid(..), (<>))
-import Data.ByteArray (Bytes)
+import qualified Data.Attoparsec.Text as P
+import Data.ByteArray (Bytes)
+import qualified Data.ByteArray as BA
+import qualified Data.ByteString.Base16 as BS16 (decode,
+ encode)
+import Data.Monoid (Monoid (..), (<>))
+import Data.Proxy
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Data.Text.Lazy.Builder as B
+import GHC.TypeLits (KnownNat, Nat, natVal)
+import Network.Ethereum.Web3.Encoding
+import Network.Ethereum.Web3.Encoding.Internal
-import Debug.Trace
+import Debug.Trace
-- | Fixed length byte array
newtype BytesN (n :: Nat) = BytesN { unBytesN :: Bytes }
@@ -39,7 +43,7 @@ update :: BytesN a -> Bytes -> BytesN a
update _ = BytesN
instance KnownNat n => EncodingType (BytesN n) where
- typeName = const "bytes[N]"
+ typeName = const $ "bytes" <> (show . natVal $ (Proxy :: Proxy n))
isDynamic = const False
instance KnownNat n => ABIEncoding (BytesN n) where
diff --git a/src/Network/Ethereum/Web3/Encoding/Internal.hs b/src/Network/Ethereum/Web3/Encoding/Internal.hs
index 0300add..cde5ad7 100644
--- a/src/Network/Ethereum/Web3/Encoding/Internal.hs
+++ b/src/Network/Ethereum/Web3/Encoding/Internal.hs
@@ -11,20 +11,21 @@
--
module Network.Ethereum.Web3.Encoding.Internal where
-import Data.Text.Lazy.Builder (Builder, toLazyText, fromText, fromLazyText)
-import qualified Data.ByteString.Base16 as BS16 (decode, encode)
import qualified Data.Attoparsec.Text as P
-import qualified Data.Text.Lazy as LT
+import Data.Attoparsec.Text.Lazy (Parser)
+import Data.Bits (Bits)
+import qualified Data.ByteString.Base16 as BS16 (decode, encode)
+import Data.Monoid ((<>))
+import Data.Text (Text)
import qualified Data.Text as T
+import Data.Text.Encoding (decodeUtf8, encodeUtf8)
+import qualified Data.Text.Lazy as LT
+import Data.Text.Lazy.Builder (Builder, fromLazyText, fromText,
+ toLazyText)
+import Data.Text.Lazy.Builder.Int as B
import qualified Data.Text.Read as R
-import Data.Text.Encoding (encodeUtf8, decodeUtf8)
-import Network.Ethereum.Web3.Address (Address)
-import Data.Attoparsec.Text.Lazy (Parser)
-import Data.Text.Lazy.Builder.Int as B
-import Language.Haskell.TH
-import Data.Monoid ((<>))
-import Data.Text (Text)
-import Data.Bits (Bits)
+import Language.Haskell.TH
+import Network.Ethereum.Web3.Address (Address)
class EncodingType a where
typeName :: a -> String
diff --git a/src/Network/Ethereum/Web3/Encoding/Tuple.hs b/src/Network/Ethereum/Web3/Encoding/Tuple.hs
index 03a1abf..cb465e0 100644
--- a/src/Network/Ethereum/Web3/Encoding/Tuple.hs
+++ b/src/Network/Ethereum/Web3/Encoding/Tuple.hs
@@ -12,9 +12,9 @@
--
module Network.Ethereum.Web3.Encoding.Tuple (Singleton(..)) where
-import Network.Ethereum.Web3.Encoding.Internal
-import Network.Ethereum.Web3.Encoding.TupleTH
-import Network.Ethereum.Web3.Encoding
+import Network.Ethereum.Web3.Encoding
+import Network.Ethereum.Web3.Encoding.Internal
+import Network.Ethereum.Web3.Encoding.TupleTH
-- | Singleton parameter instance
newtype Singleton a = Singleton { unSingleton :: a }
diff --git a/src/Network/Ethereum/Web3/Encoding/TupleTH.hs b/src/Network/Ethereum/Web3/Encoding/TupleTH.hs
index dc14712..1f597f4 100644
--- a/src/Network/Ethereum/Web3/Encoding/TupleTH.hs
+++ b/src/Network/Ethereum/Web3/Encoding/TupleTH.hs
@@ -1,5 +1,5 @@
-{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE TemplateHaskell #-}
-- |
-- Module : Network.Ethereum.Web3.Encoding.TupleTH
-- Copyright : Alexander Krupenkin 2016
@@ -18,14 +18,14 @@ module Network.Ethereum.Web3.Encoding.TupleTH (
, dParser
) where
-import Data.Text.Lazy.Builder (toLazyText, Builder)
-import Network.Ethereum.Web3.Encoding.Internal
-import qualified Data.Attoparsec.Text as P
-import qualified Data.Text.Lazy as LT
-import Network.Ethereum.Web3.Encoding
-import Data.Attoparsec.Text (Parser)
-import Control.Monad (replicateM)
-import Language.Haskell.TH
+import Control.Monad (replicateM)
+import Data.Attoparsec.Text (Parser)
+import qualified Data.Attoparsec.Text as P
+import qualified Data.Text.Lazy as LT
+import Data.Text.Lazy.Builder (Builder, toLazyText)
+import Language.Haskell.TH
+import Network.Ethereum.Web3.Encoding
+import Network.Ethereum.Web3.Encoding.Internal
-- | Argument offset calculator
offset :: Int
@@ -105,11 +105,11 @@ mkTupleP n = do
mkAppSeq :: [ExpQ] -> ExpQ
mkAppSeq = infixApps . dollarFirst . sparse
- where sparse [x] = [x]
+ where sparse [x] = [x]
sparse (x : xs) = x : [|(<*>)|] : sparse xs
dollarFirst (x : _ : xs) = x : [|(<$>)|] : xs
infixApps (x : xs) = go x xs
- go acc [] = acc
+ go acc [] = acc
go acc (f : x : xs) = go (infixApp acc f x) xs
eTupleE :: Int -> ExpQ
@@ -127,7 +127,7 @@ eTupleE 12 = [|(,,,,,,,,,,,)|]
eTupleE 13 = [|(,,,,,,,,,,,,)|]
eTupleE 14 = [|(,,,,,,,,,,,,,)|]
eTupleE 15 = [|(,,,,,,,,,,,,,,)|]
-eTupleE _ = error "Unsupported tuple size"
+eTupleE _ = error "Unsupported tuple size"
mkEncodingInst :: Int -> DecQ
mkEncodingInst n = do
diff --git a/src/Network/Ethereum/Web3/Eth.hs b/src/Network/Ethereum/Web3/Eth.hs
new file mode 100644
index 0000000..994f956
--- /dev/null
+++ b/src/Network/Ethereum/Web3/Eth.hs
@@ -0,0 +1,240 @@
+-- |
+-- Module : Network.Ethereum.Web3.Eth
+-- Copyright : Alexander Krupenkin 2016
+-- License : BSD3
+--
+-- Maintainer : mail@akru.me
+-- Stability : experimental
+-- Portability : unknown
+--
+-- Ethereum node JSON-RPC API methods with `eth_` prefix.
+--
+module Network.Ethereum.Web3.Eth where
+
+import Data.Text (Text)
+import Network.Ethereum.Web3.Address
+import Network.Ethereum.Web3.JsonRpc
+import Network.Ethereum.Web3.Provider
+import Network.Ethereum.Web3.Types
+
+-- | Returns the current ethereum protocol version.
+protocolVersion :: Provider a => Web3 a Text
+{-# INLINE protocolVersion #-}
+protocolVersion = remote "eth_protocolVersion"
+
+-- TODO The return type of this function requires a new type to be created
+-- | Returns an object with data about the sync status or false.
+-- syncing :: Proviver a => Web3 a Text
+
+-- | Returns the client coinbase address.
+coinbase :: Provider a => Web3 a Address
+{-# INLINE coinbase #-}
+coinbase = remote "eth_coinbase"
+
+-- | Returns true if client is actively mining new blocks.
+mining :: Provider a => Web3 a Bool
+{-# INLINE mining #-}
+mining = remote "eth_mining"
+
+-- | Returns the number of hashes per second that the node is mining with.
+hashrate :: Provider a => Web3 a Text
+{-# INLINE hashrate #-}
+hashrate = remote "eth_hashrate"
+
+-- | Returns the value from a storage position at a given address.
+getStorageAt :: Provider a => Address -> Text -> DefaultBlock -> Web3 a Text
+{-# INLINE getStorageAt #-}
+getStorageAt = remote "eth_getStorageAt"
+
+-- | Returns the number of transactions sent from an address.
+getTransactionCount :: Provider a => Address -> DefaultBlock -> Web3 a Text
+{-# INLINE getTransactionCount #-}
+getTransactionCount = remote "eth_getTransactionCount"
+
+-- | Returns the number of transactions in a block from a block matching the given block hash.
+getBlockTransactionCountByHash :: Provider a => Text -> Web3 a Text
+{-# INLINE getBlockTransactionCountByHash #-}
+getBlockTransactionCountByHash = remote "eth_getBlockTransactionCountByHash"
+
+-- | Returns the number of transactions in a block matching the
+-- given block number.
+getBlockTransactionCountByNumber :: Provider a => Text -> Web3 a Text
+{-# INLINE getBlockTransactionCountByNumber #-}
+getBlockTransactionCountByNumber = remote "eth_getBlockTransactionCountByNumber"
+
+-- | Returns the number of uncles in a block from a block matching the given
+-- block hash.
+getUncleCountByBlockHash :: Provider a => Text -> Web3 a Text
+{-# INLINE getUncleCountByBlockHash #-}
+getUncleCountByBlockHash = remote "eth_getUncleCountByBlockHash"
+
+-- | Returns the number of uncles in a block from a block matching the given
+-- block number.
+getUncleCountByBlockNumber :: Provider a => Text -> Web3 a Text
+{-# INLINE getUncleCountByBlockNumber #-}
+getUncleCountByBlockNumber = remote "eth_getUncleCountByBlockNumber"
+
+-- | Returns code at a given address.
+getCode :: Provider a => Address -> DefaultBlock -> Web3 a Text
+{-# INLINE getCode #-}
+getCode = remote "eth_getCode"
+
+-- | Returns an Ethereum specific signature with:
+-- sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))).
+sign :: Provider a => Address -> Text -> Web3 a Text
+{-# INLINE sign #-}
+sign = remote "eth_sign"
+
+-- | Creates new message call transaction or a contract creation,
+-- if the data field contains code.
+sendTransaction :: Provider a => Call -> Web3 a Text
+{-# INLINE sendTransaction #-}
+sendTransaction = remote "eth_sendTransaction"
+
+-- | Creates new message call transaction or a contract creation for signed
+-- transactions.
+sendRawTransaction :: Provider a => Text -> Web3 a Text
+{-# INLINE sendRawTransaction #-}
+sendRawTransaction = remote "eth_sendRawTransaction"
+
+-- | Returns the balance of the account of given address.
+getBalance :: Provider a => Address -> DefaultBlock -> Web3 a Text
+{-# INLINE getBalance #-}
+getBalance = remote "eth_getBalance"
+
+-- | Creates a filter object, based on filter options, to notify when the
+-- state changes (logs). To check if the state has changed, call
+-- 'getFilterChanges'.
+newFilter :: Provider a => Filter -> Web3 a FilterId
+{-# INLINE newFilter #-}
+newFilter = remote "eth_newFilter"
+
+-- | Polling method for a filter, which returns an array of logs which
+-- occurred since last poll.
+getFilterChanges :: Provider a => FilterId -> Web3 a [Change]
+{-# INLINE getFilterChanges #-}
+getFilterChanges = remote "eth_getFilterChanges"
+
+-- | Uninstalls a filter with given id.
+-- Should always be called when watch is no longer needed.
+uninstallFilter :: Provider a => FilterId -> Web3 a Bool
+{-# INLINE uninstallFilter #-}
+uninstallFilter = remote "eth_uninstallFilter"
+
+-- | Returns an array of all logs matching a given filter object.
+getLogs :: Provider a => Filter -> Web3 a [Change]
+{-# INLINE getLogs #-}
+getLogs = remote "eth_getLogs"
+
+-- | Executes a new message call immediately without creating a
+-- transaction on the block chain.
+call :: Provider a => Call -> DefaultBlock -> Web3 a Text
+{-# INLINE call #-}
+call = remote "eth_call"
+
+-- | Makes a call or transaction, which won't be added to the blockchain and
+-- returns the used gas, which can be used for estimating the used gas.
+estimateGas :: Provider a => Call -> Web3 a Text
+{-# INLINE estimateGas #-}
+estimateGas = remote "eth_estimateGas"
+
+-- | Returns information about a block by hash.
+getBlockByHash :: Provider a => Text -> Web3 a Block
+{-# INLINE getBlockByHash #-}
+getBlockByHash = flip (remote "eth_getBlockByHash") True
+
+-- | Returns information about a block by block number.
+getBlockByNumber :: Provider a => Text -> Web3 a Block
+{-# INLINE getBlockByNumber #-}
+getBlockByNumber = flip (remote "eth_getBlockByNumber") True
+
+-- | Returns the information about a transaction requested by transaction hash.
+getTransactionByHash :: Provider a => Text -> Web3 a (Maybe Transaction)
+{-# INLINE getTransactionByHash #-}
+getTransactionByHash = remote "eth_getTransactionByHash"
+
+-- | Returns information about a transaction by block hash and transaction index position.
+getTransactionByBlockHashAndIndex :: Provider a => Text -> Text -> Web3 a (Maybe Transaction)
+{-# INLINE getTransactionByBlockHashAndIndex #-}
+getTransactionByBlockHashAndIndex = remote "eth_getTransactionByBlockHashAndIndex"
+
+-- | Returns information about a transaction by block number and transaction
+-- index position.
+getTransactionByBlockNumberAndIndex :: Provider a => DefaultBlock -> Text -> Web3 a (Maybe Transaction)
+{-# INLINE getTransactionByBlockNumberAndIndex #-}
+getTransactionByBlockNumberAndIndex = remote "eth_getTransactionByBlockNumberAndIndex"
+
+-- | Returns the receipt of a transaction by transaction hash.
+-- TODO must create new type, TxReceipt
+-- getTransactionReceipt :: Provider a => Text -> Web3 a TxReceipt
+-- getTransactionReceipt = remote "getTransactionReceipt"
+
+-- | Returns a list of addresses owned by client.
+accounts :: Provider a => Web3 a [Address]
+{-# INLINE accounts #-}
+accounts = remote "eth_accounts"
+
+newBlockFilter :: Provider a => Web3 a Text
+{-# INLINE newBlockFilter #-}
+newBlockFilter = remote "eth_newBlockFilter"
+
+-- | Polling method for a block filter, which returns an array of block hashes
+-- occurred since last poll.
+getBlockFilterChanges :: Provider a => Text -> Web3 a [Text]
+{-# INLINE getBlockFilterChanges #-}
+getBlockFilterChanges = remote "eth_getBlockFilterChanges"
+
+-- | Returns the number of most recent block.
+blockNumber :: Provider a => Web3 a Text
+{-# INLINE blockNumber #-}
+blockNumber = remote "eth_blockNumber"
+
+-- | Returns the current price per gas in wei.
+gasPrice :: Provider a => Web3 a Text
+{-# INLINE gasPrice #-}
+gasPrice = remote "eth_gasPrice"
+
+-- | Returns information about a uncle of a block by hash and uncle index
+-- position.
+getUncleByBlockHashAndIndex :: Provider a => Text -> Text -> Web3 a Block
+{-# INLINE getUncleByBlockHashAndIndex #-}
+getUncleByBlockHashAndIndex = remote "eth_getUncleByBlockHashAndIndex"
+
+-- | Returns information about a uncle of a block by number and uncle index
+-- position.
+getUncleByBlockNumberAndIndex :: Provider a => DefaultBlock -> Text -> Web3 a Block
+{-# INLINE getUncleByBlockNumberAndIndex #-}
+getUncleByBlockNumberAndIndex = remote "eth_getUncleByBlockNumberAndIndex"
+
+-- | Creates a filter in the node, to notify when new pending transactions arrive. To check if the state has changed, call getFilterChanges. Returns a FilterId.
+newPendingTransactionFilter :: Provider a => Web3 a Text
+{-# INLINE newPendingTransactionFilter #-}
+newPendingTransactionFilter = remote "eth_newPendingTransactionFilter"
+
+-- | Returns an array of all logs matching filter with given id.
+getFilterLogs :: Provider a => Text -> Web3 a [Change]
+{-# INLINE getFilterLogs #-}
+getFilterLogs = remote "eth_getFilterLogs"
+
+-- | Returns the hash of the current block, the seedHash, and the boundary
+-- condition to be met ("target").
+getWork :: Provider a => Web3 a [Text]
+{-# INLINE getWork #-}
+getWork = remote "eth_getWork"
+
+-- | Used for submitting a proof-of-work solution.
+-- Parameters:
+-- 1. DATA, 8 Bytes - The nonce found (64 bits)
+-- 2. DATA, 32 Bytes - The header's pow-hash (256 bits)
+-- 3. DATA, 32 Bytes - The mix digest (256 bits)
+submitWork :: Provider a => Text -> Text -> Text -> Web3 a Bool
+{-# INLINE submitWork #-}
+submitWork = remote "eth_submitWork"
+
+-- | Used for submitting mining hashrate.
+-- Parameters:
+-- 1. Hashrate, a hexadecimal string representation (32 bytes) of the hash rate
+-- 2. ID, String - A random hexadecimal(32 bytes) ID identifying the client
+submitHashrate :: Provider a => Text -> Text -> Web3 a Bool
+{-# INLINE submitHashrate #-}
+submitHashrate = remote "eth_submitHashrate"
diff --git a/src/Network/Ethereum/Web3/Internal.hs b/src/Network/Ethereum/Web3/Internal.hs
index 986f497..a655c8a 100644
--- a/src/Network/Ethereum/Web3/Internal.hs
+++ b/src/Network/Ethereum/Web3/Internal.hs
@@ -11,14 +11,14 @@
--
module Network.Ethereum.Web3.Internal where
-import Data.Char (toLower, toUpper)
+import Data.Char (toLower, toUpper)
-- | Lower first char of string
toLowerFirst :: String -> String
-toLowerFirst [] = []
+toLowerFirst [] = []
toLowerFirst (x : xs) = toLower x : xs
-- | Upper first char of string
toUpperFirst :: String -> String
-toUpperFirst [] = []
+toUpperFirst [] = []
toUpperFirst (x : xs) = toUpper x : xs
diff --git a/src/Network/Ethereum/Web3/JsonAbi.hs b/src/Network/Ethereum/Web3/JsonAbi.hs
index 67e056c..6640691 100644
--- a/src/Network/Ethereum/Web3/JsonAbi.hs
+++ b/src/Network/Ethereum/Web3/JsonAbi.hs
@@ -1,5 +1,5 @@
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell #-}
-- |
-- Module : Network.Ethereum.Web3.JsonAbi
-- Copyright : Alexander Krupenkin 2016
@@ -21,14 +21,14 @@ module Network.Ethereum.Web3.JsonAbi (
, eventId
) where
-import Crypto.Hash (Digest, Keccak_256, hash)
-import qualified Data.Text.Encoding as T
-import qualified Data.Text as T
-import Network.Ethereum.Web3.Internal
-import Data.Monoid ((<>))
-import Data.Text (Text)
-import Data.Aeson.TH
-import Data.Aeson
+import Crypto.Hash (Digest, Keccak_256, hash)
+import Data.Aeson
+import Data.Aeson.TH
+import Data.Monoid ((<>))
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import Network.Ethereum.Web3.Internal
-- | Method argument
data FunctionArg = FunctionArg
@@ -60,10 +60,10 @@ $(deriveJSON
data Declaration
= DConstructor { conInputs :: [FunctionArg] }
-- ^ Contract constructor
- | DFunction { funName :: Text
- , funConstant :: Bool
- , funInputs :: [FunctionArg]
- , funOutputs :: Maybe [FunctionArg] }
+ | DFunction { funName :: Text
+ , funConstant :: Bool
+ , funInputs :: [FunctionArg]
+ , funOutputs :: Maybe [FunctionArg] }
-- ^ Method
| DEvent { eveName :: Text
, eveInputs :: [EventArg]
@@ -101,12 +101,12 @@ instance ToJSON ContractABI where
showConstructor :: Declaration -> [Text]
showConstructor x = case x of
DConstructor{} -> ["\tConstructor " <> signature x]
- _ -> []
+ _ -> []
showEvent :: Declaration -> [Text]
showEvent x = case x of
DEvent{} -> ["\t\t" <> signature x]
- _ -> []
+ _ -> []
showMethod :: Declaration -> [Text]
showMethod x = case x of
diff --git a/src/Network/Ethereum/Web3/JsonRpc.hs b/src/Network/Ethereum/Web3/JsonRpc.hs
index e554c4e..141cf3b 100644
--- a/src/Network/Ethereum/Web3/JsonRpc.hs
+++ b/src/Network/Ethereum/Web3/JsonRpc.hs
@@ -18,20 +18,21 @@ module Network.Ethereum.Web3.JsonRpc (
, ServerUri
) where
-import Network.Ethereum.Web3.Provider
-import Network.Ethereum.Web3.Types
+import Network.Ethereum.Web3.Provider
+import Network.Ethereum.Web3.Types
-import Network.HTTP.Client (httpLbs, newManager, requestBody,
- responseBody, method, requestHeaders,
- parseRequest, RequestBody(RequestBodyLBS))
-import Network.HTTP.Client.TLS (tlsManagerSettings)
-import Data.ByteString.Lazy (ByteString)
-import Control.Applicative ((<|>))
-import Control.Exception (throwIO)
-import Data.Vector (fromList)
-import Control.Monad ((>=>))
-import Data.Text (Text)
-import Data.Aeson
+import Control.Applicative ((<|>))
+import Control.Exception (throwIO)
+import Control.Monad ((>=>))
+import Data.Aeson
+import Data.ByteString.Lazy (ByteString)
+import Data.Text (Text)
+import Data.Vector (fromList)
+import Network.HTTP.Client (RequestBody (RequestBodyLBS),
+ httpLbs, method, newManager,
+ parseRequest, requestBody,
+ requestHeaders, responseBody)
+import Network.HTTP.Client.TLS (tlsManagerSettings)
-- | Name of called method.
type MethodName = Text
diff --git a/src/Network/Ethereum/Web3/Net.hs b/src/Network/Ethereum/Web3/Net.hs
new file mode 100644
index 0000000..34c8508
--- /dev/null
+++ b/src/Network/Ethereum/Web3/Net.hs
@@ -0,0 +1,32 @@
+-- |
+-- Module : Network.Ethereum.Web3.Net
+-- Copyright : Alexander Krupenkin 2016
+-- License : BSD3
+--
+-- Maintainer : mail@akru.me
+-- Stability : experimental
+-- Portability : unknown
+--
+-- Ethereum node JSON-RPC API methods with `net_` prefix.
+--
+module Network.Ethereum.Web3.Net where
+
+import Data.Text (Text)
+import Network.Ethereum.Web3.JsonRpc
+import Network.Ethereum.Web3.Provider
+import Network.Ethereum.Web3.Types
+
+-- | Returns the current network id.
+version :: Provider a => Web3 a Text
+{-# INLINE version #-}
+version = remote "net_version"
+
+-- | Returns true if client is actively listening for network connections.
+listening :: Provider a => Web3 a Bool
+{-# INLINE listening #-}
+listening = remote "net_listening"
+
+-- | Returns number of peers currently connected to the client.
+peerCount :: Provider a => Web3 a Text
+{-# INLINE peerCount #-}
+peerCount = remote "net_peerCount"
diff --git a/src/Network/Ethereum/Web3/Provider.hs b/src/Network/Ethereum/Web3/Provider.hs
index 7f78ae2..64998dd 100644
--- a/src/Network/Ethereum/Web3/Provider.hs
+++ b/src/Network/Ethereum/Web3/Provider.hs
@@ -11,10 +11,10 @@
--
module Network.Ethereum.Web3.Provider where
-import Control.Concurrent (forkIO, ThreadId)
-import Control.Monad.IO.Class (MonadIO(..))
-import Network.Ethereum.Web3.Types
-import Control.Exception (try)
+import Control.Concurrent (ThreadId, forkIO)
+import Control.Exception (try)
+import Control.Monad.IO.Class (MonadIO (..))
+import Network.Ethereum.Web3.Types
-- | Ethereum node service provider
class Provider a where
diff --git a/src/Network/Ethereum/Web3/TH.hs b/src/Network/Ethereum/Web3/TH.hs
index 62454c9..682c4bd 100644
--- a/src/Network/Ethereum/Web3/TH.hs
+++ b/src/Network/Ethereum/Web3/TH.hs
@@ -1,6 +1,9 @@
-{-# LANGUAGE TemplateHaskell #-}
-{-# LANGUAGE QuasiQuotes #-}
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE TemplateHaskell #-}
+
-- |
-- Module : Network.Ethereum.Web3.TH
-- Copyright : Alexander Krupenkin 2016
@@ -35,33 +38,35 @@ module Network.Ethereum.Web3.TH (
, ABIEncoding(..)
) where
-import qualified Data.Text.Lazy.Encoding as LT
-import qualified Data.Text.Lazy.Builder as B
-import qualified Data.Text.Lazy as LT
-import qualified Data.Attoparsec.Text as P
-import qualified Data.Text as T
-
-import Network.Ethereum.Web3.Address (Address)
-import Network.Ethereum.Web3.Encoding.Tuple
-import Network.Ethereum.Web3.Encoding
-import Network.Ethereum.Web3.Provider
-import Network.Ethereum.Web3.Internal
-import Network.Ethereum.Web3.Contract
-import Network.Ethereum.Web3.JsonAbi
-import Network.Ethereum.Web3.Types
-import Network.Ethereum.Unit
-
-import Control.Monad (replicateM)
-
-import Data.Text (Text, isPrefixOf)
-import Data.List (groupBy, sortBy)
-import Data.Monoid (mconcat, (<>))
-import Data.ByteArray (Bytes)
-import Data.Aeson
-
-import Language.Haskell.TH.Quote
-import Language.Haskell.TH.Lib
-import Language.Haskell.TH
+import qualified Data.Attoparsec.Text as P
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as LT
+import qualified Data.Text.Lazy.Builder as B
+import qualified Data.Text.Lazy.Encoding as LT
+
+import Network.Ethereum.Unit
+import Network.Ethereum.Web3.Address (Address)
+import Network.Ethereum.Web3.Contract
+import Network.Ethereum.Web3.Encoding
+import Network.Ethereum.Web3.Encoding.Tuple
+import Network.Ethereum.Web3.Internal
+import Network.Ethereum.Web3.JsonAbi
+import Network.Ethereum.Web3.Provider
+import Network.Ethereum.Web3.Types
+
+import Control.Monad (replicateM)
+
+import Data.Aeson
+import Data.ByteArray (Bytes)
+import Data.List (groupBy, sortBy)
+import Data.Monoid (mconcat, (<>))
+import Data.Text (Text, isPrefixOf)
+
+import GHC.Generics
+
+import Language.Haskell.TH
+import Language.Haskell.TH.Lib
+import Language.Haskell.TH.Quote
-- | Read contract ABI from file
abiFrom :: QuasiQuoter
@@ -215,7 +220,7 @@ funWrapper c name dname args result = do
[|sendTx $(varE a) $(varE b) $(params)|] ]
where
p = varT (mkName "p")
- arrowing [x] = x
+ arrowing [x] = x
arrowing (x : xs) = [t|$x -> $(arrowing xs)|]
inputT = fmap (typeQ . funArgType) args
outputT = case result of
@@ -232,7 +237,7 @@ mkEvent eve@(DEvent name inputs _) = sequence
, instanceD' eventName eventT (eventFilterD (T.unpack $ eventId eve) indexedFieldsCount)
]
where eventName = mkName (toUpperFirst (T.unpack name))
- derivingD = [mkName "Show", mkName "Eq", mkName "Ord"]
+ derivingD = [mkName "Show", mkName "Eq", mkName "Ord", ''Generic]
eventFields = normalC eventName (eventBangType <$> inputs)
encodingT = conT (mkName "ABIEncoding")
eventT = conT (mkName "Event")
@@ -251,16 +256,16 @@ mkFun fun@(DFunction name constant inputs outputs) = (++)
dataName = mkName (toUpperFirst (T.unpack $ name <> "Data"))
funName = mkName (toLowerFirst (T.unpack name))
bangInput = fmap funBangType inputs
- derivingD = [mkName "Show", mkName "Eq", mkName "Ord"]
+ derivingD = [mkName "Show", mkName "Eq", mkName "Ord", ''Generic]
encodingT = conT (mkName "ABIEncoding")
methodT = conT (mkName "Method")
escape :: [Declaration] -> [Declaration]
escape = concat . escapeNames . groupBy fnEq . sortBy fnCompare
where fnEq (DFunction n1 _ _ _) (DFunction n2 _ _ _) = n1 == n2
- fnEq _ _ = False
+ fnEq _ _ = False
fnCompare (DFunction n1 _ _ _) (DFunction n2 _ _ _) = compare n1 n2
- fnCompare _ _ = GT
+ fnCompare _ _ = GT
escapeNames :: [[Declaration]] -> [[Declaration]]
escapeNames = fmap go
@@ -272,14 +277,14 @@ escapeNames = fmap go
mkDecl :: Declaration -> Q [Dec]
mkDecl x@DFunction{} = mkFun x
mkDecl x@DEvent{} = mkEvent x
-mkDecl _ = return []
+mkDecl _ = return []
-- | ABI to declarations converter
quoteAbiDec :: String -> Q [Dec]
quoteAbiDec abi_string =
case decode abi_lbs of
Just (ContractABI abi) -> concat <$> mapM mkDecl (escape abi)
- _ -> fail "Unable to parse ABI!"
+ _ -> fail "Unable to parse ABI!"
where abi_lbs = LT.encodeUtf8 (LT.pack abi_string)
-- | ABI information string
diff --git a/src/Network/Ethereum/Web3/Types.hs b/src/Network/Ethereum/Web3/Types.hs
index 86cec95..11d7734 100644
--- a/src/Network/Ethereum/Web3/Types.hs
+++ b/src/Network/Ethereum/Web3/Types.hs
@@ -1,5 +1,6 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
-- |
-- Module : Network.Ethereum.Web3.Types
@@ -10,22 +11,23 @@
-- Stability : experimental
-- Portability : portable
--
--- Common used types and instances.
+-- Commonly used types and instances.
--
module Network.Ethereum.Web3.Types where
-import Network.Ethereum.Web3.Internal (toLowerFirst)
-import qualified Data.Text.Lazy.Builder.Int as B
-import qualified Data.Text.Lazy.Builder as B
-import qualified Data.Text.Read as R
-import Network.Ethereum.Web3.Address (Address)
-import Control.Monad.IO.Class (MonadIO)
-import Control.Exception (Exception)
-import Data.Typeable (Typeable)
-import Data.Monoid ((<>))
-import Data.Text (Text)
-import Data.Aeson.TH
-import Data.Aeson
+import Control.Exception (Exception)
+import Control.Monad.IO.Class (MonadIO)
+import Data.Aeson
+import Data.Aeson.TH
+import Data.Monoid ((<>))
+import Data.Text (Text)
+import qualified Data.Text.Lazy.Builder as B
+import qualified Data.Text.Lazy.Builder.Int as B
+import qualified Data.Text.Read as R
+import Data.Typeable (Typeable)
+import GHC.Generics
+import Network.Ethereum.Web3.Address (Address)
+import Network.Ethereum.Web3.Internal (toLowerFirst)
-- | Any communication with Ethereum node wrapped with 'Web3' monad
newtype Web3 a b = Web3 { unWeb3 :: IO b }
@@ -39,16 +41,16 @@ data Web3Error
-- ^ Error in parser state
| UserFail !String
-- ^ Common head for user errors
- deriving (Typeable, Show, Eq)
+ deriving (Typeable, Show, Eq, Generic)
instance Exception Web3Error
-- | JSON-RPC error message
data RpcError = RpcError
- { errCode :: !Int
- , errMessage :: !Text
- , errData :: !(Maybe Value)
- } deriving (Show, Eq)
+ { errCode :: !Int
+ , errMessage :: !Text
+ , errData :: !(Maybe Value)
+ } deriving (Show, Eq, Generic)
$(deriveJSON (defaultOptions
{ fieldLabelModifier = toLowerFirst . drop 3 }) ''RpcError)
@@ -59,20 +61,20 @@ data Filter = Filter
, filterTopics :: !(Maybe [Maybe Text])
, filterFromBlock :: !(Maybe Text)
, filterToBlock :: !(Maybe Text)
- } deriving Show
+ } deriving (Show, Generic)
$(deriveJSON (defaultOptions
{ fieldLabelModifier = toLowerFirst . drop 6 }) ''Filter)
--- | Event filder ident
+-- | Event filter identifier
newtype FilterId = FilterId Integer
- deriving (Show, Eq, Ord)
+ deriving (Show, Eq, Ord, Generic)
instance FromJSON FilterId where
parseJSON (String v) =
case R.hexadecimal v of
Right (x, "") -> return (FilterId x)
- _ -> fail "Unable to parse FilterId!"
+ _ -> fail "Unable to parse FilterId!"
parseJSON _ = fail "The string is required!"
instance ToJSON FilterId where
@@ -80,7 +82,8 @@ instance ToJSON FilterId where
let hexValue = B.toLazyText (B.hexadecimal x)
in toJSON ("0x" <> hexValue)
--- | Changes pulled by low-level call 'eth_getFilterChanges'
+-- | Changes pulled by low-level call 'eth_getFilterChanges', 'eth_getLogs',
+-- and 'eth_getFilterLogs'
data Change = Change
{ changeLogIndex :: !Text
, changeTransactionIndex :: !Text
@@ -90,30 +93,32 @@ data Change = Change
, changeAddress :: !Address
, changeData :: !Text
, changeTopics :: ![Text]
- } deriving Show
+ } deriving (Show, Generic)
$(deriveJSON (defaultOptions
{ fieldLabelModifier = toLowerFirst . drop 6 }) ''Change)
-- | The contract call params
data Call = Call
- { callFrom :: !(Maybe Address)
- , callTo :: !Address
- , callGas :: !(Maybe Text)
+ { callFrom :: !(Maybe Address)
+ , callTo :: !Address
+ , callGas :: !(Maybe Text)
, callGasPrice:: !(Maybe Text)
- , callValue :: !(Maybe Text)
- , callData :: !(Maybe Text)
- } deriving Show
+ , callValue :: !(Maybe Text)
+ , callData :: !(Maybe Text)
+ } deriving (Show, Generic)
$(deriveJSON (defaultOptions
- { fieldLabelModifier = toLowerFirst . drop 4 }) ''Call)
+ { fieldLabelModifier = toLowerFirst . drop 4
+ , omitNothingFields = True }) ''Call)
-- | The contract call mode describe used state: latest or pending
-data CallMode = Latest | Pending
+data DefaultBlock = BlockNumberHex Text | Earliest | Latest | Pending
deriving (Show, Eq)
-instance ToJSON CallMode where
- toJSON = toJSON . toLowerFirst . show
+instance ToJSON DefaultBlock where
+ toJSON (BlockNumberHex hex) = toJSON hex
+ toJSON parameter = toJSON . toLowerFirst . show $ parameter
-- TODO: Wrap
-- | Transaction hash text string
@@ -121,29 +126,29 @@ type TxHash = Text
-- | Transaction information
data Transaction = Transaction
- { txHash :: !TxHash
+ { txHash :: !TxHash
-- ^ DATA, 32 Bytes - hash of the transaction.
- , txNonce :: !Text
+ , txNonce :: !Text
-- ^ QUANTITY - the number of transactions made by the sender prior to this one.
- , txBlockHash :: !Text
+ , txBlockHash :: !Text
-- ^ DATA, 32 Bytes - hash of the block where this transaction was in. null when its pending.
- , txBlockNumber :: !Text
+ , txBlockNumber :: !Text
-- ^ QUANTITY - block number where this transaction was in. null when its pending.
- , txTransactionIndex :: !Text
+ , txTransactionIndex :: !Text
-- ^ QUANTITY - integer of the transactions index position in the block. null when its pending.
- , txFrom :: !Address
+ , txFrom :: !Address
-- ^ DATA, 20 Bytes - address of the sender.
- , txTo :: !(Maybe Address)
+ , txTo :: !(Maybe Address)
-- ^ DATA, 20 Bytes - address of the receiver. null when its a contract creation transaction.
- , txValue :: !Text
+ , txValue :: !Text
-- ^ QUANTITY - value transferred in Wei.
- , txGasPrice :: !Text
+ , txGasPrice :: !Text
-- ^ QUANTITY - gas price provided by the sender in Wei.
- , txGas :: !Text
+ , txGas :: !Text
-- ^ QUANTITY - gas provided by the sender.
- , txInput :: !Text
+ , txInput :: !Text
-- ^ DATA - the data send along with the transaction.
- } deriving Show
+ } deriving (Show, Generic)
$(deriveJSON (defaultOptions
{ fieldLabelModifier = toLowerFirst . drop 2 }) ''Transaction)
@@ -188,7 +193,7 @@ data Block = Block
-- ^ Array of transaction objects.
, blockUncles :: ![Text]
-- ^ Array - Array of uncle hashes.
- } deriving Show
+ } deriving (Show, Generic)
$(deriveJSON (defaultOptions
{ fieldLabelModifier = toLowerFirst . drop 5 }) ''Block)
diff --git a/src/Network/Ethereum/Web3/Web3.hs b/src/Network/Ethereum/Web3/Web3.hs
new file mode 100644
index 0000000..c69d601
--- /dev/null
+++ b/src/Network/Ethereum/Web3/Web3.hs
@@ -0,0 +1,27 @@
+-- |
+-- Module : Network.Ethereum.Web3.Web3
+-- Copyright : Alexander Krupenkin 2016
+-- License : BSD3
+--
+-- Maintainer : mail@akru.me
+-- Stability : experimental
+-- Portability : unknown
+--
+-- Ethereum node JSON-RPC API methods with `web3_` prefix.
+--
+module Network.Ethereum.Web3.Web3 where
+
+import Data.Text (Text)
+import Network.Ethereum.Web3.JsonRpc
+import Network.Ethereum.Web3.Provider
+import Network.Ethereum.Web3.Types
+
+-- | Returns current node version string.
+clientVersion :: Provider a => Web3 a Text
+{-# INLINE clientVersion #-}
+clientVersion = remote "web3_clientVersion"
+
+-- | Returns Keccak-256 (not the standardized SHA3-256) of the given data.
+sha3 :: Provider a => Text -> Web3 a Text
+{-# INLINE sha3 #-}
+sha3 = remote "web3_sha3"
diff --git a/test/Spec.hs b/test/Spec.hs
index 495b207..d1e1aa8 100644
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -1,12 +1,13 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
-{-# LANGUAGE DataKinds #-}
module Main where
-import Network.Ethereum.Web3.TH
-import Network.Ethereum.Web3
-import Data.Text (unpack)
-import Text.Printf
+import Data.Text (unpack)
+import Network.Ethereum.Web3
+import Network.Ethereum.Web3.TH
+import Text.Printf
[abiFrom|data/ERC20.json|]
diff --git a/web3.cabal b/web3.cabal
index 5151c74..c4f817d 100644
--- a/web3.cabal
+++ b/web3.cabal
@@ -1,5 +1,5 @@
name: web3
-version: 0.5.5.0
+version: 0.6.0.0
cabal-version: >=1.10
build-type: Simple
license: BSD3
@@ -25,7 +25,9 @@ library
Network.Ethereum.Web3
Network.Ethereum.Unit
Network.Ethereum.Web3.TH
- Network.Ethereum.Web3.Api
+ Network.Ethereum.Web3.Web3
+ Network.Ethereum.Web3.Eth
+ Network.Ethereum.Web3.Net
Network.Ethereum.Web3.Types
Network.Ethereum.Web3.Address
Network.Ethereum.Web3.JsonAbi
@@ -45,7 +47,7 @@ library
bytestring >=0.10.8.1 && <0.11,
cryptonite ==0.23.*,
vector >=0.12.0.1 && <0.13,
- memory >=0.14.6 && <0.15,
+ memory >=0.14.8 && <0.15,
aeson >=1.1.2.0 && <1.2,
text >=1.2.2.2 && <1.3
default-language: Haskell2010
@@ -62,7 +64,7 @@ test-suite web3-test
main-is: Spec.hs
build-depends:
base >=4.9.1.0 && <4.10,
- memory >=0.14.6 && <0.15,
+ memory >=0.14.8 && <0.15,
text >=1.2.2.2 && <1.3,
web3
default-language: Haskell2010