{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables   #-}

-- |
-- Module      :  Network.Ethereum.Contract
-- Copyright   :  Aleksandr Krupenkin 2016-2024
-- License     :  Apache-2.0
--
-- Maintainer  :  mail@akru.me
-- Stability   :  experimental
-- Portability :  unportable
--
-- Smart contract type class and utils. A contract in the sense of Solidity
-- is a collection of code (its functions) and data (its state) that resides
-- at a specific address on the Ethereum blockchain.
--

module Network.Ethereum.Contract where

import           Data.Proxy                       (Proxy)
import           Data.Text                        (Text)

import           Data.ByteArray.HexString         (HexString)
import           Data.Solidity.Prim.Address       (Address)
import           Network.Ethereum.Account.Class   (Account)
import           Network.Ethereum.Account.Safe    (safeConfirmations, safeSend)
import           Network.Ethereum.Api.Types       (receiptContractAddress)
import           Network.Ethereum.Contract.Method (Method)
import           Network.JsonRpc.TinyClient       (JsonRpc)

-- | Contract description type clase
class Contract a where
    -- | Contract Solidity ABI
    -- https://solidity.readthedocs.io/en/latest/abi-spec.html
    abi :: Proxy a -> Text

    -- | Contract bytecode as hex string
    bytecode :: Proxy a -> HexString

-- | Create new smart contract on blockchain
new :: (Account p t, JsonRpc m, Method a, Monad (t m))
    => a
    -- ^ Contract constructor
    -> t m (Either HexString (Maybe Address))
    -- ^ Address of deployed contract when transaction success;
    -- transaction hash in case of a timeout
new :: forall p (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(Account p t, JsonRpc m, Method a, Monad (t m)) =>
a -> t m (Either HexString (Maybe Address))
new = (Either HexString TxReceipt -> Either HexString (Maybe Address))
-> t m (Either HexString TxReceipt)
-> t m (Either HexString (Maybe Address))
forall a b. (a -> b) -> t m a -> t m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((TxReceipt -> Maybe Address)
-> Either HexString TxReceipt -> Either HexString (Maybe Address)
forall {t} {b} {a}. (t -> b) -> Either a t -> Either a b
mapRight TxReceipt -> Maybe Address
receiptContractAddress) (t m (Either HexString TxReceipt)
 -> t m (Either HexString (Maybe Address)))
-> (a -> t m (Either HexString TxReceipt))
-> a
-> t m (Either HexString (Maybe Address))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> a -> t m (Either HexString TxReceipt)
forall p (t :: (* -> *) -> * -> *) (m :: * -> *) args.
(Account p t, JsonRpc m, Method args, Monad (t m)) =>
Integer -> args -> t m (Either HexString TxReceipt)
safeSend Integer
safeConfirmations
  where
    mapRight :: (t -> b) -> Either a t -> Either a b
mapRight t -> b
f Either a t
e =
        case Either a t
e of
            Left a
x  -> a -> Either a b
forall a b. a -> Either a b
Left a
x
            Right t
y -> b -> Either a b
forall a b. b -> Either a b
Right (b -> Either a b) -> b -> Either a b
forall a b. (a -> b) -> a -> b
$ t -> b
f t
y