packages feed

morley-client-0.3.2: src/Morley/Client/Action/Reveal.hs

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

-- | Functions to reveal keys via node RPC.
module Morley.Client.Action.Reveal
  ( RevealData (..)
  , revealKey
  , revealKeyWithFee
  , revealKeyUnlessRevealed
  , revealKeyUnlessRevealedWithFee
  ) where

import Fmt ((|+))

import Morley.Client.Action.Common
import Morley.Client.Action.Operation
import Morley.Client.Logging
import Morley.Client.RPC.Class
import Morley.Client.RPC.Error
import Morley.Client.RPC.Getters
import Morley.Client.RPC.Types
import Morley.Client.TezosClient.Class (HasTezosClient(getPublicKey))
import Morley.Client.Types
import Morley.Tezos.Address
import Morley.Tezos.Core (Mutez)
import Morley.Tezos.Crypto (PublicKey)

-- | Resolve the public key of an implicit address and reveal it.
revealKey
  :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m)
  => ImplicitAddressWithAlias -> m OperationHash
revealKey = (`revealKeyWithFee` Nothing)

-- | Version of 'revealKey' with explicit fee.
revealKeyWithFee
  :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m)
  => ImplicitAddressWithAlias -> Maybe Mutez -> m OperationHash
revealKeyWithFee sender mbFee = do
  pk <- getPublicKey sender
  runRevealOperationRaw sender pk mbFee

-- | Resolve the public key of an implicit address and reveal it, unless already
-- revealed.
revealKeyUnlessRevealed
  :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m)
  => ImplicitAddressWithAlias -> m ()
revealKeyUnlessRevealed = (`revealKeyUnlessRevealedWithFee` Nothing)

-- | Version of 'revealKeyUnlessRevealed' with explicit fee.
revealKeyUnlessRevealedWithFee
  :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m)
  => ImplicitAddressWithAlias -> Maybe Mutez -> m ()
revealKeyUnlessRevealedWithFee sender mbFee = do
  pk <- getPublicKey sender
  handleAlreadyRevealed (flip (runRevealOperationRaw sender) mbFee) pk

-- Internals

handleAlreadyRevealed
  :: (HasTezosRpc m, WithClientLog env m)
  => (PublicKey -> m a) -> PublicKey -> m ()
handleAlreadyRevealed doReveal key = do
  let sender = mkKeyAddress key
  -- An optimization for the average case, but we can't rely on it in
  -- distributed environment
  getManagerKey sender >>= \case
    Just _  -> logDebug $ sender |+ " address has already revealed key"
    Nothing -> ignoreAlreadyRevealedError . void $ doReveal key
  where
    ignoreAlreadyRevealedError = flip catch \case
      RunCodeErrors [PreviouslyRevealedKey _] -> pass
      e -> throwM e

-- | Note that sender and rdPublicKey must be consistent, otherwise network will
-- reject the operation
runRevealOperationRaw
  :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m)
  => ImplicitAddressWithAlias -> PublicKey -> Maybe Mutez -> m OperationHash
runRevealOperationRaw sender rdPublicKey rdMbFee =
  fmap fst . runOperationsNonEmpty sender . one $ OpReveal RevealData{..}