@@ -5,6 +5,8 @@ module Cardano.Transaction.Builder
5
5
, MintAsset
6
6
, IssueCertificate
7
7
, WithdrawRewards
8
+ , SubmitProposal
9
+ , SubmitVotingProcedure
8
10
)
9
11
, OutputWitness (NativeScriptOutput , PlutusScriptOutput )
10
12
, CredentialWitness (NativeScriptCredential , PlutusScriptCredential )
@@ -20,6 +22,7 @@ module Cardano.Transaction.Builder
20
22
, DatumWitnessNotProvided
21
23
, UnneededDatumWitness
22
24
, UnneededDeregisterWitness
25
+ , UnneededSpoVoteWitness
23
26
, UnableToAddMints
24
27
, RedeemerIndexingError
25
28
, RedeemerIndexingInternalError
@@ -31,6 +34,7 @@ module Cardano.Transaction.Builder
31
34
( StakeCert
32
35
, Withdrawal
33
36
, Minting
37
+ , Voting
34
38
)
35
39
, buildTransaction
36
40
, modifyTransaction
@@ -42,7 +46,7 @@ import Prelude
42
46
import Cardano.AsCbor (encodeCbor )
43
47
import Cardano.Transaction.Edit
44
48
( DetachedRedeemer
45
- , RedeemerPurpose (ForCert, ForReward, ForSpend, ForMint)
49
+ , RedeemerPurpose (ForCert, ForReward, ForSpend, ForMint, ForVote )
46
50
, fromEditableTransactionSafe
47
51
, toEditableTransactionSafe
48
52
)
@@ -85,6 +89,7 @@ import Cardano.Types.Credential
85
89
)
86
90
import Cardano.Types.Credential as Credential
87
91
import Cardano.Types.DataHash as PlutusData
92
+ import Cardano.Types.GovernanceActionId (GovernanceActionId )
88
93
import Cardano.Types.Int as Int
89
94
import Cardano.Types.Mint as Mint
90
95
import Cardano.Types.NativeScript as NativeScript
@@ -96,10 +101,21 @@ import Cardano.Types.StakeCredential (StakeCredential)
96
101
import Cardano.Types.StakePubKeyHash (StakePubKeyHash )
97
102
import Cardano.Types.Transaction (_body , _witnessSet )
98
103
import Cardano.Types.Transaction as Transaction
104
+ import Cardano.Types.TransactionBody (_votingProcedures , _votingProposals )
99
105
import Cardano.Types.TransactionInput (TransactionInput )
100
106
import Cardano.Types.TransactionOutput (TransactionOutput , _address , _datum )
101
- import Cardano.Types.TransactionUnspentOutput (TransactionUnspentOutput , _output )
102
- import Cardano.Types.TransactionWitnessSet (_nativeScripts , _plutusData , _plutusScripts )
107
+ import Cardano.Types.TransactionUnspentOutput
108
+ ( TransactionUnspentOutput
109
+ , _output
110
+ )
111
+ import Cardano.Types.TransactionWitnessSet
112
+ ( _nativeScripts
113
+ , _plutusData
114
+ , _plutusScripts
115
+ )
116
+ import Cardano.Types.Voter (Voter (Cc, Drep, Spo))
117
+ import Cardano.Types.VotingProcedure (VotingProcedure )
118
+ import Cardano.Types.VotingProposal (VotingProposal )
103
119
import Control.Monad.Error.Class (throwError )
104
120
import Control.Monad.Except (Except , runExcept )
105
121
import Control.Monad.State (StateT , modify_ , runStateT )
@@ -110,7 +126,9 @@ import Data.ByteArray (byteArrayToHex)
110
126
import Data.Either (Either (Left, Right), either , note )
111
127
import Data.Generic.Rep (class Generic )
112
128
import Data.Lens (Lens' , view , (%=), (.~), (^.))
129
+ import Data.Lens.Iso.Newtype (_Newtype )
113
130
import Data.Lens.Record (prop )
131
+ import Data.Map (Map )
114
132
import Data.Map as Map
115
133
import Data.Maybe (Maybe (Just, Nothing), isJust , maybe )
116
134
import Data.Newtype (unwrap , wrap )
@@ -126,6 +144,9 @@ data TransactionBuilderStep
126
144
| MintAsset ScriptHash AssetName Int.Int CredentialWitness
127
145
| IssueCertificate Certificate (Maybe CredentialWitness )
128
146
| WithdrawRewards StakeCredential Coin (Maybe CredentialWitness )
147
+ | SubmitProposal VotingProposal
148
+ | SubmitVotingProcedure Voter (Map GovernanceActionId VotingProcedure )
149
+ (Maybe CredentialWitness )
129
150
130
151
derive instance Generic TransactionBuilderStep _
131
152
derive instance Eq TransactionBuilderStep
@@ -244,6 +265,7 @@ data CredentialAction
244
265
= StakeCert Certificate
245
266
| Withdrawal RewardAddress
246
267
| Minting ScriptHash
268
+ | Voting Voter
247
269
248
270
derive instance Generic CredentialAction _
249
271
derive instance Eq CredentialAction
@@ -254,6 +276,7 @@ explainCredentialAction :: CredentialAction -> String
254
276
explainCredentialAction (StakeCert _) = " This stake certificate"
255
277
explainCredentialAction (Withdrawal _) = " This stake rewards withdrawal"
256
278
explainCredentialAction (Minting _) = " This mint"
279
+ explainCredentialAction (Voting _) = " This voting procedure"
257
280
258
281
data TxBuildError
259
282
= WrongSpendWitnessType TransactionUnspentOutput
@@ -265,6 +288,7 @@ data TxBuildError
265
288
| DatumWitnessNotProvided TransactionUnspentOutput
266
289
| UnneededDatumWitness TransactionUnspentOutput DatumWitness
267
290
| UnneededDeregisterWitness StakeCredential CredentialWitness
291
+ | UnneededSpoVoteWitness Credential CredentialWitness
268
292
| UnableToAddMints Mint Mint
269
293
| RedeemerIndexingError Redeemer
270
294
| RedeemerIndexingInternalError Transaction (Array TransactionBuilderStep )
@@ -290,15 +314,23 @@ explainTxBuildError (IncorrectDatumHash utxo datum datumHash) =
290
314
<> " \n UTxO: "
291
315
<> show utxo
292
316
explainTxBuildError (IncorrectScriptHash (Left nativeScript) hash) =
293
- " Provided script hash (" <> show hash <> " ) does not match the provided native script (" <> show nativeScript <> " )"
317
+ " Provided script hash (" <> show hash
318
+ <> " ) does not match the provided native script ("
319
+ <> show nativeScript
320
+ <> " )"
294
321
explainTxBuildError (IncorrectScriptHash (Right plutusScript) hash) =
295
- " Provided script hash (" <> show hash <> " ) does not match the provided Plutus script (" <> show plutusScript <> " )"
322
+ " Provided script hash (" <> show hash
323
+ <> " ) does not match the provided Plutus script ("
324
+ <> show plutusScript
325
+ <> " )"
296
326
explainTxBuildError (WrongOutputType ScriptHashWitness utxo) =
297
- " The UTxO you provided requires no witness, because the payment credential of the address is a `PubKeyHash`. UTxO: " <> show
298
- utxo
327
+ " The UTxO you provided requires no witness, because the payment credential of the address is a `PubKeyHash`. UTxO: "
328
+ <> show
329
+ utxo
299
330
explainTxBuildError (WrongOutputType PubKeyHashWitness utxo) =
300
- " The UTxO you provided requires a `ScriptHash` witness to unlock, because the payment credential of the address is a `ScriptHash`. UTxO: " <>
301
- show utxo
331
+ " The UTxO you provided requires a `ScriptHash` witness to unlock, because the payment credential of the address is a `ScriptHash`. UTxO: "
332
+ <>
333
+ show utxo
302
334
explainTxBuildError
303
335
(WrongStakeCredentialType operation expWitnessType stakeCredential) =
304
336
explainCredentialAction operation <> " (" <> show operation <> " ) requires a "
@@ -314,15 +346,29 @@ explainTxBuildError (UnneededDatumWitness utxo witness) =
314
346
<> " for the UTxO: "
315
347
<> show utxo
316
348
explainTxBuildError (UnneededDeregisterWitness stakeCredential witness) =
317
- " You've provided an optional `CredentialWitness`, but the stake credential you are trying to issue a deregistering certificate for is a PubKeyHash credential. You should omit the provided credential witness for this credential: " <> show stakeCredential <> " . Provided witness: " <> show witness
349
+ " You've provided an optional `CredentialWitness`, but the stake credential you are trying to issue a deregistering certificate for is a PubKeyHash credential. You should omit the provided credential witness for this credential: "
350
+ <> show stakeCredential
351
+ <> " . Provided witness: "
352
+ <> show witness
353
+ explainTxBuildError (UnneededSpoVoteWitness cred witness) =
354
+ " You've provided an optional `CredentialWitness`, but the corresponding Voter is SPO (Stake Pool Operator). You should omit the provided credential witness for this credential: "
355
+ <> show cred
356
+ <> " . Provided witness: "
357
+ <> show witness
318
358
explainTxBuildError (UnableToAddMints a b) =
319
359
" Numeric overflow: unable to add `Mint`s: " <> show a <> " and " <> show b
320
360
explainTxBuildError (RedeemerIndexingError redeemer) =
321
- " Redeemer indexing error. Problematic redeemer that does not have a valid index: " <> show redeemer
361
+ " Redeemer indexing error. Problematic redeemer that does not have a valid index: "
362
+ <> show redeemer
322
363
explainTxBuildError (RedeemerIndexingInternalError tx steps) =
323
- " Internal redeemer indexing error. Please report as bug: " <> bugTrackerUrl <> " \n Debug info: Transaction: " <> show tx <> " , steps: " <> show steps
364
+ " Internal redeemer indexing error. Please report as bug: " <> bugTrackerUrl
365
+ <> " \n Debug info: Transaction: "
366
+ <> show tx
367
+ <> " , steps: "
368
+ <> show steps
324
369
explainTxBuildError (WrongNetworkId address) =
325
- " The following `Address` that was specified in one of the UTxOs has a `NetworkId` different from the one `TransactionBody` has: " <> show address
370
+ " The following `Address` that was specified in one of the UTxOs has a `NetworkId` different from the one `TransactionBody` has: "
371
+ <> show address
326
372
explainTxBuildError NoTransactionNetworkId =
327
373
" You are editing a transaction without a `NetworkId` set. To create a `RewardAddress`, a NetworkId is needed: set it in the `TransactionBody`"
328
374
@@ -340,7 +386,8 @@ modifyTransaction
340
386
-> Either TxBuildError Transaction
341
387
modifyTransaction tx steps = do
342
388
context <- do
343
- editableTransaction <- lmap RedeemerIndexingError $ toEditableTransactionSafe tx
389
+ editableTransaction <- lmap RedeemerIndexingError $
390
+ toEditableTransactionSafe tx
344
391
pure $ merge editableTransaction
345
392
{ networkId: editableTransaction.transaction ^. _body <<< _networkId }
346
393
let
@@ -368,12 +415,20 @@ processConstraint = case _ of
368
415
-- intentionally not using pushUnique: we can
369
416
-- create multiple outputs of the same shape
370
417
%= flip append [ output ]
371
- MintAsset scriptHash assetName amount mintWitness -> do
418
+ MintAsset scriptHash assetName amount mintWitness ->
372
419
useMintAssetWitness scriptHash assetName amount mintWitness
373
420
IssueCertificate cert witness -> do
421
+ _transaction <<< _body <<< _certs %= pushUnique cert
374
422
useCertificateWitness cert witness
375
- WithdrawRewards stakeCredential amount witness -> do
423
+ WithdrawRewards stakeCredential amount witness ->
376
424
useWithdrawRewardsWitness stakeCredential amount witness
425
+ SubmitProposal proposal ->
426
+ _transaction <<< _body <<< _votingProposals
427
+ %= pushUnique proposal
428
+ SubmitVotingProcedure voter votes witness -> do
429
+ _transaction <<< _body <<< _votingProcedures <<< _Newtype
430
+ %= Map .insert voter votes
431
+ useVotingProcedureWitness voter witness
377
432
378
433
assertNetworkId :: Address -> BuilderM Unit
379
434
assertNetworkId addr = do
@@ -386,7 +441,8 @@ assertNetworkId addr = do
386
441
unless (networkId == addrNetworkId) do
387
442
throwError (WrongNetworkId addr)
388
443
389
- assertOutputType :: ExpectedWitnessType -> TransactionUnspentOutput -> BuilderM Unit
444
+ assertOutputType
445
+ :: ExpectedWitnessType -> TransactionUnspentOutput -> BuilderM Unit
390
446
assertOutputType outputType utxo = do
391
447
let
392
448
mbCredential =
@@ -426,45 +482,63 @@ useMintAssetWitness scriptHash assetName amount witness = do
426
482
maybe (throwError $ UnableToAddMints mint thisMint) pure
427
483
modify_ $ _transaction <<< _body <<< _mint .~ Just newMint
428
484
429
- assertScriptHashMatchesCredentialWitness :: ScriptHash -> CredentialWitness -> BuilderM Unit
485
+ assertScriptHashMatchesCredentialWitness
486
+ :: ScriptHash -> CredentialWitness -> BuilderM Unit
430
487
assertScriptHashMatchesCredentialWitness scriptHash witness = do
431
488
let
432
489
mbScript = case witness of
433
- PlutusScriptCredential (ScriptValue plutusScript) _ -> Just (Right plutusScript)
434
- NativeScriptCredential (ScriptValue nativeScript) -> Just (Left nativeScript)
490
+ PlutusScriptCredential (ScriptValue plutusScript) _ -> Just
491
+ (Right plutusScript)
492
+ NativeScriptCredential (ScriptValue nativeScript) -> Just
493
+ (Left nativeScript)
435
494
_ -> Nothing
436
495
for_ mbScript \eiScript -> do
437
496
let hash = either NativeScript .hash PlutusScript .hash eiScript
438
497
unless (scriptHash == hash) do
439
498
throwError $ IncorrectScriptHash eiScript scriptHash
440
499
500
+ useVotingProcedureWitness :: Voter -> Maybe CredentialWitness -> BuilderM Unit
501
+ useVotingProcedureWitness voter mbWitness = do
502
+ cred <- case voter of
503
+ Spo poolKeyHash -> do
504
+ let cred = PubKeyHashCredential poolKeyHash
505
+ case mbWitness of
506
+ Just witness -> throwError $ UnneededSpoVoteWitness cred witness
507
+ Nothing -> pure cred
508
+ Cc cred -> pure cred
509
+ Drep cred -> pure cred
510
+ useCredentialWitness (Voting voter) (wrap cred) mbWitness
511
+
441
512
useCertificateWitness :: Certificate -> Maybe CredentialWitness -> BuilderM Unit
442
- useCertificateWitness cert mbWitness = do
443
- _transaction <<< _body <<< _certs %= pushUnique cert
513
+ useCertificateWitness cert mbWitness =
444
514
case cert of
445
515
StakeDeregistration stakeCredential -> do
446
516
case stakeCredential, mbWitness of
447
- StakeCredential (PubKeyHashCredential _), Just witness -> do
517
+ StakeCredential (PubKeyHashCredential _), Just witness ->
448
518
throwError $ UnneededDeregisterWitness stakeCredential witness
449
519
StakeCredential (PubKeyHashCredential _), Nothing -> pure unit
450
- StakeCredential (ScriptHashCredential _), Nothing -> do
520
+ StakeCredential (ScriptHashCredential _), Nothing ->
451
521
throwError $
452
- WrongStakeCredentialType (StakeCert cert) PubKeyHashWitness stakeCredential
453
- StakeCredential (ScriptHashCredential scriptHash), Just witness -> do
522
+ WrongStakeCredentialType (StakeCert cert) PubKeyHashWitness
523
+ stakeCredential
524
+ StakeCredential (ScriptHashCredential scriptHash), Just witness ->
454
525
assertScriptHashMatchesCredentialWitness scriptHash witness
455
526
useCredentialWitness (StakeCert cert) stakeCredential mbWitness
456
- StakeDelegation stakeCredential _ -> do
527
+ StakeDelegation stakeCredential _ ->
457
528
useCredentialWitness (StakeCert cert) stakeCredential mbWitness
458
529
StakeRegistration _ -> pure unit
459
530
PoolRegistration _ -> pure unit
460
531
PoolRetirement _ -> pure unit
461
532
_ -> pure unit -- TODO
462
533
463
534
useCredentialWitness
464
- :: CredentialAction -> StakeCredential -> Maybe CredentialWitness -> BuilderM Unit
465
- useCredentialWitness credentialAction stakeCredential witness = do
535
+ :: CredentialAction
536
+ -> StakeCredential
537
+ -> Maybe CredentialWitness
538
+ -> BuilderM Unit
539
+ useCredentialWitness credentialAction stakeCredential witness =
466
540
case witness of
467
- Nothing -> do
541
+ Nothing ->
468
542
assertStakeCredentialType credentialAction PubKeyHashWitness
469
543
stakeCredential
470
544
Just (NativeScriptCredential nsWitness) -> do
@@ -481,6 +555,7 @@ useCredentialWitness credentialAction stakeCredential witness = do
481
555
Withdrawal rewardAddress -> ForReward rewardAddress
482
556
StakeCert cert -> ForCert cert
483
557
Minting scriptHash -> ForMint scriptHash
558
+ Voting voter -> ForVote voter
484
559
-- ForSpend is not possible: for that we use OutputWitness
485
560
, datum: redeemerDatum
486
561
}
@@ -502,7 +577,8 @@ useWithdrawRewardsWitness stakeCredential amount witness = do
502
577
503
578
-- | Tries to modify the transaction to make it consume a given output.
504
579
-- | Uses a `SpendWitness` to try to satisfy spending requirements.
505
- useSpendWitness :: TransactionUnspentOutput -> Maybe OutputWitness -> BuilderM Unit
580
+ useSpendWitness
581
+ :: TransactionUnspentOutput -> Maybe OutputWitness -> BuilderM Unit
506
582
useSpendWitness utxo = case _ of
507
583
Nothing -> do
508
584
assertOutputType PubKeyHashWitness utxo
@@ -601,4 +677,5 @@ pushUnique :: forall a. Ord a => a -> Array a -> Array a
601
677
pushUnique x xs = nub $ xs <> [ x ]
602
678
603
679
bugTrackerUrl :: String
604
- bugTrackerUrl = " https://github.com/mlabs-haskell/purescript-cardano-transaction-builder/issues"
680
+ bugTrackerUrl =
681
+ " https://github.com/mlabs-haskell/purescript-cardano-transaction-builder/issues"
0 commit comments