/
Transaction.hs
168 lines (150 loc) · 5.8 KB
/
Transaction.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
-- |
-- Copyright: © 2018-2020 IOHK
-- License: Apache-2.0
--
-- An extra interface for operation on transactions (e.g. creating witnesses,
-- estimating size...). This makes it possible to decouple those operations from
-- our wallet layer, keeping the implementation flexible to various backends.
module Cardano.Wallet.Transaction
(
-- * Interface
TransactionLayer (..)
, DelegationAction (..)
-- * Errors
, ErrMkTx (..)
, ErrValidateSelection
, ErrDecodeSignedTx (..)
) where
import Prelude
import Cardano.Address.Derivation
( XPrv )
import Cardano.Wallet.Primitive.AddressDerivation
( Depth (..), Passphrase )
import Cardano.Wallet.Primitive.CoinSelection
( CoinSelection (..) )
import Cardano.Wallet.Primitive.Fee
( Fee, FeePolicy )
import Cardano.Wallet.Primitive.Types
( Address (..), PoolId, SealedTx (..), SlotId (..), Tx (..) )
import Data.ByteString
( ByteString )
import Data.Quantity
( Quantity (..) )
import Data.Text
( Text )
import Data.Word
( Word16, Word8 )
data TransactionLayer t k = TransactionLayer
{ mkStdTx
:: (k 'AddressK XPrv, Passphrase "encryption")
-- Reward account
-> (Address -> Maybe (k 'AddressK XPrv, Passphrase "encryption"))
-- Key store
-> SlotId
-- Tip of the chain, for TTL
-> CoinSelection
-- A balanced coin selection where all change addresses have been
-- assigned.
-> Either ErrMkTx (Tx, SealedTx)
-- ^ Construct a standard transaction
--
-- " Standard " here refers to the fact that we do not deal with redemption,
-- multisignature transactions, etc.
--
-- This expects as a first argument a mean to compute or lookup private
-- key corresponding to a particular address.
, mkDelegationJoinTx
:: PoolId
-- Pool Id to which we're planning to delegate
-> (k 'AddressK XPrv, Passphrase "encryption")
-- Reward account
-> (Address -> Maybe (k 'AddressK XPrv, Passphrase "encryption"))
-- Key store
-> SlotId
-- Tip of the chain, for TTL
-> CoinSelection
-- A balanced coin selection where all change addresses have been
-- assigned.
-> Either ErrMkTx (Tx, SealedTx)
-- ^ Construct a transaction containing a certificate for delegating to
-- a stake pool.
--
-- The certificate is a combination of the 'PoolId' and the public key
-- of the reward account. (Note that this is an address key and
-- HD account keys are something different)
, mkDelegationQuitTx
:: (k 'AddressK XPrv, Passphrase "encryption")
-- Reward account
-> (Address -> Maybe (k 'AddressK XPrv, Passphrase "encryption"))
-- Key store
-> SlotId
-- Tip of the chain, for TTL
-> CoinSelection
-- A balanced coin selection where all change addresses have been
-- assigned.
-> Either ErrMkTx (Tx, SealedTx)
-- ^ Construct a transaction containing a certificate for quiting from
-- a stake pool.
--
-- The certificate is the public key of the reward account.
, initDelegationSelection
:: FeePolicy
-- Current fee policy
-> DelegationAction
-- What sort of action is going on
-> CoinSelection
-- ^ An initial selection where 'deposit' and/or 'reclaim' have been set
-- accordingly.
, minimumFee
:: FeePolicy -> Maybe DelegationAction -> CoinSelection -> Fee
-- ^ Compute a minimal fee amount necessary to pay for a given
-- coin-selection.
, estimateMaxNumberOfInputs
:: Quantity "byte" Word16 -> Word8 -> Word8
-- ^ Calculate a "theoretical" maximum number of inputs given a maximum
-- transaction size and desired number of outputs.
--
-- The actual transaction size cannot be known until it has been fully
-- determined by coin selection.
--
-- This estimate will err on the side of permitting more inputs,
-- resulting in a transaction which may be too large.
, validateSelection
:: CoinSelection -> Either (ErrValidateSelection t) ()
-- ^ Validate coin selection regarding rules that may be specific to a
-- particular backend implementation.
--
-- For example, Byron nodes do not allow null output amounts. Jörmungandr
-- on its side doesn't support more than 255 inputs or outputs.
, allowUnbalancedTx
:: Bool
-- ^ Whether the transaction layer accepts unbalanced transactions.
, decodeSignedTx
:: ByteString -> Either ErrDecodeSignedTx (Tx, SealedTx)
-- ^ Decode an externally-signed transaction to the chain producer
}
-- | Whether the user is attempting any particular delegation action.
data DelegationAction = RegisterKeyAndJoin PoolId | Join PoolId | Quit
deriving (Show)
-- | A type family for validations that are specific to a particular backend
-- type. This demands an instantiation of the family for a particular backend:
--
-- type instance (ErrValidateSelection MyBackend) = MyCustomError
--
type family ErrValidateSelection t
-- | Error while trying to decode externally signed transaction
data ErrDecodeSignedTx
= ErrDecodeSignedTxWrongPayload Text
| ErrDecodeSignedTxNotSupported
deriving (Show, Eq)
-- | Possible signing error
data ErrMkTx
= ErrKeyNotFoundForAddress Address
-- ^ We tried to sign a transaction with inputs that are unknown to us?
deriving (Eq, Show)