Skip to content

Commit 7d6b461

Browse files
Maintain output order
1 parent 1ab405a commit 7d6b461

File tree

2 files changed

+34
-23
lines changed

2 files changed

+34
-23
lines changed

src/BotPlutusInterface/Balance.hs

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ import Control.Monad.Trans.Either (EitherT, hoistEither, newEitherT, runEitherT)
2626
import Data.Coerce (coerce)
2727
import Data.Either.Combinators (rightToMaybe)
2828
import Data.Kind (Type)
29-
import Data.List (partition, (\\))
29+
import Data.List ((\\))
3030
import Data.Map (Map)
3131
import Data.Map qualified as Map
32-
import Data.Maybe (fromMaybe, mapMaybe)
32+
import Data.Maybe (fromJust, fromMaybe, mapMaybe)
3333
import Data.Set (Set)
3434
import Data.Set qualified as Set
3535
import Data.Text (Text)
@@ -311,17 +311,17 @@ addTxCollaterals utxos tx =
311311
handleNonAdaChange :: Address -> Map TxOutRef TxOut -> Tx -> Either Text Tx
312312
handleNonAdaChange changeAddr utxos tx =
313313
let nonAdaChange = getNonAdaChange utxos tx
314+
newOutput =
315+
TxOut
316+
{ txOutAddress = changeAddr
317+
, txOutValue = nonAdaChange
318+
, txOutDatumHash = Nothing
319+
}
314320
outputs =
315-
case partition ((==) changeAddr . Tx.txOutAddress) $ txOutputs tx of
316-
([], txOuts) ->
317-
TxOut
318-
{ txOutAddress = changeAddr
319-
, txOutValue = nonAdaChange
320-
, txOutDatumHash = Nothing
321-
} :
322-
txOuts
323-
(txOut@TxOut {txOutValue = v} : txOuts, txOuts') ->
324-
txOut {txOutValue = v <> nonAdaChange} : (txOuts <> txOuts')
321+
modifyFirst
322+
((==) changeAddr . Tx.txOutAddress)
323+
(maybe newOutput $ addValueToTxOut nonAdaChange)
324+
(txOutputs tx)
325325
in if isValueNat nonAdaChange
326326
then Right $ if Value.isZero nonAdaChange then tx else tx {txOutputs = outputs}
327327
else Left "Not enough inputs to balance tokens."
@@ -332,18 +332,29 @@ hasChangeUTxO changeAddr tx =
332332

333333
-- | Adds ada change to a transaction, assuming there is already an output going to ownPkh. Otherwise, this is identity
334334
addAdaChange :: Address -> Integer -> Tx -> Tx
335+
addAdaChange _ 0 tx = tx
335336
addAdaChange changeAddr change tx =
336337
tx
337338
{ txOutputs =
338-
case partition ((==) changeAddr . Tx.txOutAddress) $ txOutputs tx of
339-
(txOut@TxOut {txOutValue = v} : txOuts, txOuts') ->
340-
txOut {txOutValue = v <> Ada.lovelaceValueOf change} : (txOuts <> txOuts')
341-
_ -> txOutputs tx
339+
modifyFirst
340+
((==) changeAddr . Tx.txOutAddress)
341+
(addValueToTxOut (Ada.lovelaceValueOf change) . fromJust)
342+
(txOutputs tx)
342343
}
343344

345+
{- | Modifies the first element matching a predicate, or, if none found, call the modifier with Nothing
346+
Calling this function ensures the modifier will always be run once
347+
-}
348+
modifyFirst :: (a -> Bool) -> (Maybe a -> a) -> [a] -> [a]
349+
modifyFirst _ m [] = [m Nothing]
350+
modifyFirst p m (x : xs) = if p x then m (Just x) : xs else x : modifyFirst p m xs
351+
352+
addValueToTxOut :: Value -> TxOut -> TxOut
353+
addValueToTxOut val txOut = txOut {txOutValue = txOutValue txOut <> val}
354+
344355
-- | Adds a 1 lovelace output to a transaction
345356
addOutput :: Address -> Tx -> Tx
346-
addOutput changeAddr tx = tx {txOutputs = changeTxOut : txOutputs tx}
357+
addOutput changeAddr tx = tx {txOutputs = txOutputs tx ++ [changeTxOut]}
347358
where
348359
changeTxOut =
349360
TxOut

test/Spec/BotPlutusInterface/Contract.hs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ sendAda = do
156156
, [text|
157157
cardano-cli transaction build-raw --alonzo-era
158158
--tx-in ${inTxId}#0
159-
--tx-out ${addr1}+50
160159
--tx-out ${addr2}+1000
160+
--tx-out ${addr1}+50
161161
--required-signer ./signing-keys/signing-key-${pkh1'}.skey
162162
--fee 300
163163
--protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw
@@ -411,8 +411,8 @@ sendTokens = do
411411
, [text|
412412
cardano-cli transaction build-raw --alonzo-era
413413
--tx-in ${inTxId1}#0
414-
--tx-out ${addr1}+50 + 95 abcd1234.74657374546F6B656E
415414
--tx-out ${addr2}+1000 + 5 abcd1234.74657374546F6B656E
415+
--tx-out ${addr1}+50 + 95 abcd1234.74657374546F6B656E
416416
--required-signer ./signing-keys/signing-key-${pkh1'}.skey
417417
--fee 300
418418
--protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw
@@ -453,8 +453,8 @@ sendTokensWithoutName = do
453453
, [text|
454454
cardano-cli transaction build-raw --alonzo-era
455455
--tx-in ${inTxId1}#0
456-
--tx-out ${addr1}+50 + 95 abcd1234
457456
--tx-out ${addr2}+1000 + 5 abcd1234
457+
--tx-out ${addr1}+50 + 95 abcd1234
458458
--required-signer ./signing-keys/signing-key-${pkh1'}.skey
459459
--fee 300
460460
--protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw
@@ -520,8 +520,8 @@ mintTokens = do
520520
cardano-cli transaction build-raw --alonzo-era
521521
--tx-in ${inTxId}#0
522522
--tx-in-collateral ${inTxId}#0
523-
--tx-out ${addr1}+496700
524523
--tx-out ${addr2}+1000 + 5 ${curSymbol'}.74657374546F6B656E
524+
--tx-out ${addr1}+496700
525525
--mint-script-file ./result-scripts/policy-${curSymbol'}.plutus
526526
--mint-redeemer-file ./result-scripts/redeemer-${redeemerHash}.json
527527
--mint-execution-units (500000,2000)
@@ -609,9 +609,9 @@ spendToValidator = do
609609
, [text|
610610
cardano-cli transaction build-raw --alonzo-era
611611
--tx-in ${inTxId}#0
612-
--tx-out ${addr1}+200
613612
--tx-out ${valAddr'}+500
614613
--tx-out-datum-embed-file ./result-scripts/datum-${datumHash'}.json
614+
--tx-out ${addr1}+200
615615
--required-signer ./signing-keys/signing-key-${pkh1'}.skey
616616
--fee 300
617617
--protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw
@@ -707,8 +707,8 @@ redeemFromValidator = do
707707
--tx-in-redeemer-file ./result-scripts/redeemer-${redeemerHash}.json
708708
--tx-in-execution-units (500000,2000)
709709
--tx-in-collateral ${inTxId}#0
710-
--tx-out ${addr1}+498350
711710
--tx-out ${addr2}+500
711+
--tx-out ${addr1}+498350
712712
--required-signer ./signing-keys/signing-key-${pkh1'}.skey
713713
--fee 502400
714714
--protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw

0 commit comments

Comments
 (0)