module Network.Ethereum.Web3.Contract (
EventAction(..)
, Method(..)
, Event(..)
, 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 Control.Monad.IO.Class (liftIO)
import Data.Text.Lazy (toStrict)
import qualified Data.Text as T
import Data.Maybe (catMaybes)
import Data.Monoid ((<>))
import Network.Ethereum.Web3.Encoding
import Network.Ethereum.Web3.Address
import Network.Ethereum.Web3.Types
import Network.Ethereum.Web3.Api
import Network.Ethereum.Unit
data EventAction = ContinueEvent
| TerminateEvent
deriving (Show, Eq)
class ABIEncoding a => Event a where
eventFilter :: a -> Address -> Filter
event :: Provider p
=> Address
-> (a -> IO EventAction)
-> Web3 p ThreadId
event = _event
_event :: (Provider p, Event a)
=> Address
-> (a -> IO EventAction)
-> Web3 p ThreadId
_event a f = do
fid <- let ftyp = snd $ let x = undefined :: Event a => a
in (f x, x)
in eth_newFilter (eventFilter ftyp a)
forkWeb3 $
let loop = do liftIO (threadDelay 1000000)
changes <- fmap parseChange <$> eth_getFilterChanges fid
acts <- mapM (liftIO . f) (catMaybes changes)
if any (== TerminateEvent) acts
then return ()
else loop
in do loop
eth_uninstallFilter fid
return ()
where
prepareTopics = fmap (T.drop 2) . drop 1
parseChange c = fromData $
T.append (T.concat (prepareTopics $ changeTopics c))
(T.drop 2 $ changeData c)
class ABIEncoding a => Method a where
sendTx :: (Provider p, Unit b)
=> Address
-> b
-> a
-> Web3 p TxHash
sendTx = _sendTransaction
call :: (Provider p, ABIEncoding b)
=> Address
-> CallMode
-> a
-> Web3 p b
call = _call
_sendTransaction :: (Provider p, Method a, Unit b)
=> Address -> b -> a -> Web3 p TxHash
_sendTransaction to value dat = do
primeAddress <- head <$> eth_accounts
eth_sendTransaction (txdata primeAddress $ Just $ toData dat)
where txdata from = Call (Just from) to Nothing Nothing (Just $ toWeiText value)
toWeiText = ("0x" <>) . toStrict . B.toLazyText . B.hexadecimal . toWei
_call :: (Provider p, Method a, ABIEncoding b)
=> Address -> CallMode -> a -> Web3 p b
_call to mode dat = do
res <- eth_call txdata mode
case fromData (T.drop 2 res) of
Nothing -> fail $
"Unable to parse result on `" ++ T.unpack res
++ "` from `" ++ show to ++ "`"
Just x -> return x
where
txdata = Call Nothing to Nothing Nothing Nothing (Just (toData dat))
nopay :: Wei
nopay = 0