-- SPDX-FileCopyrightText: 2021 Oxhead Alpha
-- SPDX-License-Identifier: LicenseRef-MIT-OA

-- | Abstraction layer for @octez-client@ functionality.
-- We use it to fake @octez-client@ in tests.

module Morley.Client.TezosClient.Class
  ( HasTezosClient (..)
  , AliasBehavior (..)
  ) where

import Data.ByteArray (ScrubbedBytes)

import Morley.Client.Types
import Morley.Tezos.Address
import Morley.Tezos.Address.Alias
import Morley.Tezos.Crypto

-- | How to save the originated contract address.
data AliasBehavior
  = DontSaveAlias
  -- ^ Don't save the newly originated contract address.
  | KeepDuplicateAlias
  -- ^ If an alias already exists, keep it, don't save the newly originated
  -- contract address.
  | OverwriteDuplicateAlias
  -- ^ If an alias already exists, replace it with the address of the newly
  -- originated contract.
  | ForbidDuplicateAlias
  -- ^ If an alias already exists, throw an exception without doing the
  -- origination
  deriving stock (AliasBehavior -> AliasBehavior -> Bool
(AliasBehavior -> AliasBehavior -> Bool)
-> (AliasBehavior -> AliasBehavior -> Bool) -> Eq AliasBehavior
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AliasBehavior -> AliasBehavior -> Bool
$c/= :: AliasBehavior -> AliasBehavior -> Bool
== :: AliasBehavior -> AliasBehavior -> Bool
$c== :: AliasBehavior -> AliasBehavior -> Bool
Eq, Eq AliasBehavior
Eq AliasBehavior
-> (AliasBehavior -> AliasBehavior -> Ordering)
-> (AliasBehavior -> AliasBehavior -> Bool)
-> (AliasBehavior -> AliasBehavior -> Bool)
-> (AliasBehavior -> AliasBehavior -> Bool)
-> (AliasBehavior -> AliasBehavior -> Bool)
-> (AliasBehavior -> AliasBehavior -> AliasBehavior)
-> (AliasBehavior -> AliasBehavior -> AliasBehavior)
-> Ord AliasBehavior
AliasBehavior -> AliasBehavior -> Bool
AliasBehavior -> AliasBehavior -> Ordering
AliasBehavior -> AliasBehavior -> AliasBehavior
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: AliasBehavior -> AliasBehavior -> AliasBehavior
$cmin :: AliasBehavior -> AliasBehavior -> AliasBehavior
max :: AliasBehavior -> AliasBehavior -> AliasBehavior
$cmax :: AliasBehavior -> AliasBehavior -> AliasBehavior
>= :: AliasBehavior -> AliasBehavior -> Bool
$c>= :: AliasBehavior -> AliasBehavior -> Bool
> :: AliasBehavior -> AliasBehavior -> Bool
$c> :: AliasBehavior -> AliasBehavior -> Bool
<= :: AliasBehavior -> AliasBehavior -> Bool
$c<= :: AliasBehavior -> AliasBehavior -> Bool
< :: AliasBehavior -> AliasBehavior -> Bool
$c< :: AliasBehavior -> AliasBehavior -> Bool
compare :: AliasBehavior -> AliasBehavior -> Ordering
$ccompare :: AliasBehavior -> AliasBehavior -> Ordering
Ord, Int -> AliasBehavior
AliasBehavior -> Int
AliasBehavior -> [AliasBehavior]
AliasBehavior -> AliasBehavior
AliasBehavior -> AliasBehavior -> [AliasBehavior]
AliasBehavior -> AliasBehavior -> AliasBehavior -> [AliasBehavior]
(AliasBehavior -> AliasBehavior)
-> (AliasBehavior -> AliasBehavior)
-> (Int -> AliasBehavior)
-> (AliasBehavior -> Int)
-> (AliasBehavior -> [AliasBehavior])
-> (AliasBehavior -> AliasBehavior -> [AliasBehavior])
-> (AliasBehavior -> AliasBehavior -> [AliasBehavior])
-> (AliasBehavior
    -> AliasBehavior -> AliasBehavior -> [AliasBehavior])
-> Enum AliasBehavior
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: AliasBehavior -> AliasBehavior -> AliasBehavior -> [AliasBehavior]
$cenumFromThenTo :: AliasBehavior -> AliasBehavior -> AliasBehavior -> [AliasBehavior]
enumFromTo :: AliasBehavior -> AliasBehavior -> [AliasBehavior]
$cenumFromTo :: AliasBehavior -> AliasBehavior -> [AliasBehavior]
enumFromThen :: AliasBehavior -> AliasBehavior -> [AliasBehavior]
$cenumFromThen :: AliasBehavior -> AliasBehavior -> [AliasBehavior]
enumFrom :: AliasBehavior -> [AliasBehavior]
$cenumFrom :: AliasBehavior -> [AliasBehavior]
fromEnum :: AliasBehavior -> Int
$cfromEnum :: AliasBehavior -> Int
toEnum :: Int -> AliasBehavior
$ctoEnum :: Int -> AliasBehavior
pred :: AliasBehavior -> AliasBehavior
$cpred :: AliasBehavior -> AliasBehavior
succ :: AliasBehavior -> AliasBehavior
$csucc :: AliasBehavior -> AliasBehavior
Enum)

-- | Type class that provides interaction with @octez-client@ binary
class (Monad m) => HasTezosClient m where
  signBytes
    :: ImplicitAddressWithAlias
    -> Maybe ScrubbedBytes
    -> ByteString
    -> m Signature
  -- ^ Sign an operation with @octez-client@.
  genKey :: ImplicitAlias -> m ImplicitAddressWithAlias
  -- ^ Generate a secret key and store it with given alias.
  -- If a key with this alias already exists, the corresponding address
  -- will be returned and no state will be changed.
  genFreshKey :: ImplicitAlias -> m ImplicitAddressWithAlias
  -- ^ Generate a secret key and store it with given alias.
  -- Unlike 'genKey' this function overwrites
  -- the existing key when given alias is already stored.
  rememberContract :: AliasBehavior -> ContractAddress -> ContractAlias -> m ()
  -- ^ Associate the given contract with alias.
  -- The 'Bool' variable indicates whether or not we should replace already
  -- existing contract alias or not.
  getAliasesAndAddresses :: m [(Text, Text)]
  -- ^ Retrieves a list with all known aliases and respective addresses.
  --
  -- Note that an alias can be ambiguous: it can refer to BOTH a contract and an implicit account.
  -- When an alias "abc" is ambiguous, the list will contain two entries:
  --
  -- > ("abc", "KT1...")
  -- > ("key:abc", "tz1...")
  --
  -- TODO [#910]: Cache this and turn it into a 'Morley.Util.Bimap'.
  getKeyPassword :: ImplicitAddressWithAlias -> m (Maybe ScrubbedBytes)
  -- ^ Get password for secret key associated with given address
  -- in case this key is password-protected. Obtained password is used
  -- in two places:
  --   * 1) In @signBytes@ call.
  --   * 2) in @revealKey@ call.
  getPublicKey :: ImplicitAddressWithAlias -> m PublicKey
  -- ^ Get a public key for an implicit address or alias.