@@ -7,107 +7,205 @@ import Blockfrost.Client (
7
7
runBlockfrost ,
8
8
)
9
9
import Blockfrost.Client qualified as Blockfrost
10
+ import Codec.CBOR.Encoding qualified as CBOR
11
+ import Codec.CBOR.Write (toLazyByteString )
12
+ import Data.ByteString.Lazy qualified as BL
13
+ import Data.Time.Clock.POSIX
14
+ import Hydra.Cardano.Api hiding (fromNetworkMagic )
15
+
10
16
import Cardano.Api.UTxO qualified as UTxO
11
- import Control.Concurrent.Class.MonadSTM (
12
- MonadSTM (readTVarIO ),
13
- newTVarIO ,
14
- writeTVar ,
15
- )
16
- import Hydra.Cardano.Api (
17
- ChainPoint (.. ),
18
- HasTypeProxy (.. ),
19
- Hash ,
20
- Key (.. ),
21
- NetworkId (.. ),
22
- NetworkMagic (.. ),
23
- PaymentKey ,
24
- SerialiseAsCBOR (.. ),
25
- ShelleyWitnessSigningKey (WitnessPaymentKey ),
26
- SigningKey ,
27
- SlotNo (.. ),
28
- SocketPath ,
29
- Tx ,
30
- TxId ,
31
- TxIn (.. ),
32
- TxIx (.. ),
33
- UTxO ,
34
- WitCtx (.. ),
35
- examplePlutusScriptAlwaysFails ,
36
- getTxBody ,
37
- getTxId ,
38
- makeShelleyKeyWitness ,
39
- makeSignedTransaction ,
40
- mkScriptAddress ,
41
- mkScriptRef ,
42
- mkTxOutAutoBalance ,
43
- mkVkAddress ,
44
- selectLovelace ,
45
- serialiseToRawBytes ,
46
- throwErrorAsException ,
47
- txOutValue ,
48
- pattern TxOutDatumNone ,
49
- )
50
- import Hydra.Cardano.Api.Prelude (
51
- BlockHeader (.. ),
52
- )
53
- import Hydra.Chain.CardanoClient (
54
- QueryPoint (.. ),
55
- awaitTransaction ,
56
- buildTransaction ,
57
- queryProtocolParameters ,
58
- queryUTxOByTxIn ,
59
- queryUTxOFor ,
60
- submitTransaction ,
61
- )
17
+ import Data.Set qualified as Set
18
+ import Hydra.Cardano.Api.Prelude (StakePoolKey )
62
19
import Hydra.Contract.Head qualified as Head
63
20
import Hydra.Plutus (commitValidatorScript , initialValidatorScript )
64
- import Hydra.Tx.ScriptRegistry ( ScriptRegistry ( .. ), newScriptRegistry )
21
+ import Money qualified
65
22
66
- publishHydraScripts' ::
67
- -- | Expected network discriminant.
68
- NetworkId ->
69
- -- | Path to the cardano-node's domain socket
70
- SocketPath ->
23
+ data APIBlockfrostError
24
+ = BlockfrostError Text
25
+ | DecodeError Text
26
+ deriving (Show , Exception )
27
+
28
+ runBlockfrostM ::
29
+ (MonadIO m , MonadThrow m ) =>
30
+ Blockfrost. Project ->
31
+ BlockfrostClientT IO a ->
32
+ m a
33
+ runBlockfrostM prj action = do
34
+ result <- liftIO $ runBlockfrost prj action
35
+ case result of
36
+ Left err -> throwIO (BlockfrostError $ show err)
37
+ Right val -> pure val
38
+
39
+ publishHydraScripts ::
40
+ -- | The path where the Blockfrost project token hash is stored.
41
+ FilePath ->
71
42
-- | Keys assumed to hold funds to pay for the publishing transaction.
72
43
SigningKey PaymentKey ->
73
44
IO [TxId ]
74
- publishHydraScripts' networkId socketPath sk = do
75
- pparams <- queryProtocolParameters networkId socketPath QueryTip
76
- forM scripts $ \ script -> do
77
- utxo <- queryUTxOFor networkId socketPath QueryTip vk
78
- let output = mkScriptTxOut pparams <$> [mkScriptRef script]
79
- totalDeposit = sum (selectLovelace . txOutValue <$> output)
80
- someUTxO =
81
- maybe mempty UTxO. singleton $
82
- UTxO. find (\ o -> selectLovelace (txOutValue o) > totalDeposit) utxo
83
- buildTransaction
84
- networkId
85
- socketPath
86
- changeAddress
87
- someUTxO
88
- []
89
- output
90
- >>= \ case
91
- Left e ->
92
- throwErrorAsException e
93
- Right x -> do
94
- let body = getTxBody x
95
- let tx = makeSignedTransaction [makeShelleyKeyWitness body (WitnessPaymentKey sk)] body
96
- submitTransaction networkId socketPath tx
97
- void $ awaitTransaction networkId socketPath tx
98
- return $ getTxId body
45
+ publishHydraScripts projectPath sk = do
46
+ prj <- Blockfrost. projectFromFile projectPath
47
+ runBlockfrostM prj $ do
48
+ pparams <- Blockfrost. getLatestEpochProtocolParams
49
+ Blockfrost. Genesis
50
+ { _genesisNetworkMagic = networkMagic
51
+ , _genesisSystemStart = systemStart
52
+ } <-
53
+ Blockfrost. getLedgerGenesis
54
+ let address = Blockfrost. Address (vkAddress networkMagic)
55
+ let networkId = fromNetworkMagic networkMagic
56
+ let changeAddress = mkVkAddress networkId vk
57
+ stakePools <- Blockfrost. listPools
58
+ forM scripts $ \ script -> do
59
+ utxo <- Blockfrost. getAddressUtxos address
60
+ liftIO $
61
+ buildTx pparams networkId systemStart stakePools script changeAddress utxo
62
+ >>= \ case
63
+ Left err ->
64
+ liftIO $ throwErrorAsException err
65
+ Right rawTx -> do
66
+ let body = getTxBody rawTx
67
+ tx = makeSignedTransaction [makeShelleyKeyWitness body (WitnessPaymentKey sk)] body
68
+ -- REVIEW! double CBOR encoding
69
+ txByteString :: BL. ByteString = toLazyByteString (CBOR. encodeBytes $ serialiseToCBOR tx)
70
+ txCborString = Blockfrost. CBORString txByteString
71
+ txHash <- Blockfrost. submitTx txCborString
72
+ -- TODO! await transaction confirmed
73
+ pure undefined
99
74
where
100
75
scripts = [initialValidatorScript, commitValidatorScript, Head. validatorScript]
76
+
101
77
vk = getVerificationKey sk
102
78
103
- changeAddress = mkVkAddress networkId vk
79
+ vkAddress networkMagic = textAddrOf (fromNetworkMagic networkMagic) vk
80
+
81
+ -- TODO!
82
+ buildTx ::
83
+ Blockfrost. ProtocolParams ->
84
+ NetworkId ->
85
+ POSIXTime ->
86
+ [Blockfrost. PoolId ] ->
87
+ PlutusScript ->
88
+ -- | Change address to send
89
+ AddressInEra ->
90
+ [Blockfrost. AddressUtxo ] ->
91
+ IO (Either (TxBodyErrorAutoBalance Era ) Tx )
92
+ buildTx pparams networkId posixTime stakePools script changeAddress utxo = do
93
+ pure $
94
+ second (flip Tx [] . balancedTxBody) $
95
+ makeTransactionBodyAutoBalance
96
+ shelleyBasedEra
97
+ systemStart
98
+ undefined -- (toLedgerEpochInfo eraHistory)
99
+ undefined -- (LedgerProtocolParameters pparams)
100
+ (Set. fromList (toApiPoolId <$> stakePools))
101
+ mempty
102
+ mempty
103
+ (UTxO. toApi utxoToSpend)
104
+ bodyContent
105
+ changeAddress
106
+ Nothing
107
+ where
108
+ unspendableScriptAddress = mkScriptAddress networkId $ examplePlutusScriptAlwaysFails WitCtxTxIn
109
+ -- FIXME! mkTxOutAutoBalance with minUTxOValue from pparams
110
+ outputs = TxOut unspendableScriptAddress mempty TxOutDatumNone <$> [mkScriptRef script]
111
+ utxo' = toApiUTxO utxo changeAddress
112
+ totalDeposit = sum (selectLovelace . txOutValue <$> outputs)
113
+ utxoToSpend = maybe mempty UTxO. singleton $ UTxO. find (\ o -> selectLovelace (txOutValue o) > totalDeposit) utxo'
114
+ systemStart = SystemStart $ posixSecondsToUTCTime posixTime
115
+ collateral = mempty
116
+ -- NOTE: 'makeTransactionBodyAutoBalance' overwrites this.
117
+ dummyFeeForBalancing = TxFeeExplicit 0
118
+ bodyContent =
119
+ TxBodyContent
120
+ (withWitness <$> toList (UTxO. inputSet utxoToSpend))
121
+ (TxInsCollateral collateral)
122
+ TxInsReferenceNone
123
+ outputs
124
+ TxTotalCollateralNone
125
+ TxReturnCollateralNone
126
+ dummyFeeForBalancing
127
+ TxValidityNoLowerBound
128
+ TxValidityNoUpperBound
129
+ TxMetadataNone
130
+ TxAuxScriptsNone
131
+ TxExtraKeyWitnessesNone
132
+ undefined -- (BuildTxWith $ Just $ LedgerProtocolParameters pparams)
133
+ TxWithdrawalsNone
134
+ TxCertificatesNone
135
+ TxUpdateProposalNone
136
+ TxMintValueNone
137
+ TxScriptValidityNone
138
+ Nothing
139
+ Nothing
140
+ Nothing
141
+ Nothing
142
+
143
+ -- ** Extras
144
+
145
+ toApiPoolId :: Blockfrost. PoolId -> Hash StakePoolKey
146
+ toApiPoolId (Blockfrost. PoolId textPoolId) =
147
+ case deserialiseFromRawBytesHex (AsHash AsStakePoolKey ) (encodeUtf8 textPoolId) of
148
+ Left err -> error (show err)
149
+ Right pool -> pool
150
+
151
+ toApiUTxO :: [Blockfrost. AddressUtxo ] -> AddressInEra -> UTxO' (TxOut CtxUTxO )
152
+ toApiUTxO utxos addr = UTxO. fromPairs (toEntry <$> utxos)
153
+ where
154
+ toEntry :: Blockfrost. AddressUtxo -> (TxIn , TxOut CtxUTxO )
155
+ toEntry utxo = (toApiTxIn utxo, toApiTxOut utxo addr)
156
+
157
+ toApiTxIn :: Blockfrost. AddressUtxo -> TxIn
158
+ toApiTxIn Blockfrost. AddressUtxo {_addressUtxoTxHash = Blockfrost. TxHash {unTxHash}, _addressUtxoOutputIndex} =
159
+ case deserialiseFromRawBytesHex AsTxId (encodeUtf8 unTxHash) of
160
+ Left err -> error (show err)
161
+ Right txId -> TxIn txId (TxIx (fromIntegral _addressUtxoOutputIndex))
162
+
163
+ -- REVIEW! TxOutDatumNone and ReferenceScriptNone
164
+ toApiTxOut :: Blockfrost. AddressUtxo -> AddressInEra -> TxOut CtxUTxO
165
+ toApiTxOut Blockfrost. AddressUtxo {_addressUtxoAmount} addr =
166
+ TxOut addr (toApiValue _addressUtxoAmount) TxOutDatumNone ReferenceScriptNone
167
+
168
+ toApiPolicyId :: Text -> PolicyId
169
+ toApiPolicyId pid =
170
+ case deserialiseFromRawBytesHex AsPolicyId (encodeUtf8 pid) of
171
+ Left err -> error (show err)
172
+ Right p -> p
173
+
174
+ toApiAssetName :: Text -> AssetName
175
+ toApiAssetName = AssetName . encodeUtf8
176
+
177
+ toApiValue :: [Blockfrost. Amount ] -> Value
178
+ toApiValue = foldMap convertAmount
179
+ where
180
+ convertAmount (Blockfrost. AdaAmount lovelaces) =
181
+ fromList
182
+ [
183
+ ( AdaAssetId
184
+ , Quantity (toInteger lovelaces)
185
+ )
186
+ ]
187
+ convertAmount (Blockfrost. AssetAmount money) =
188
+ let currency = Money. someDiscreteCurrency money
189
+ in fromList
190
+ [
191
+ ( AssetId
192
+ (toApiPolicyId currency)
193
+ (toApiAssetName currency)
194
+ , Quantity (Money. someDiscreteAmount money)
195
+ )
196
+ ]
197
+
198
+ -- ** Helpers
199
+
200
+ unwrapAddress :: AddressInEra -> Text
201
+ unwrapAddress = \ case
202
+ ShelleyAddressInEra addr -> serialiseToBech32 addr
203
+ ByronAddressInEra {} -> error " Byron."
104
204
105
- mkScriptTxOut pparams =
106
- mkTxOutAutoBalance
107
- pparams
108
- unspendableScriptAddress
109
- mempty
110
- TxOutDatumNone
205
+ textAddrOf :: NetworkId -> VerificationKey PaymentKey -> Text
206
+ textAddrOf networkId vk = unwrapAddress (mkVkAddress @ Era networkId vk)
111
207
112
- unspendableScriptAddress =
113
- mkScriptAddress networkId $ examplePlutusScriptAlwaysFails WitCtxTxIn
208
+ fromNetworkMagic :: Integer -> NetworkId
209
+ fromNetworkMagic = \ case
210
+ 0 -> Mainnet
211
+ magicNbr -> Testnet (NetworkMagic (fromInteger magicNbr))
0 commit comments