I'm trying to figure out how to create a script transaction without the plutus PAB backend. I have a use case where I want to be able to send arbitrary datums (and redeemers) to a script, without going through the PAB. The nodes will reject invalid datums anyway. And PAB requires explicit knowledge about endpoints, which I don't have.
Currently there are two ways afais:
You can create an unbalanced transaction with cardano-cli transaction build, which is flexible enough and then shove it through the balance endpoint. However, this is poor usability, because it requires dealing with a cli interface in addition to the wallet backend.
You can try to figure out how to use the ledger manually to create an unbalanced transaction. This is potentially error prone and subject to the constantly changing internal API and types.
Description
The main culprit seems to be the diverging of TxOut:
-- | A transaction output, consisting of a target address, a value, and optionally a datum hash.
data TxOut = TxOut {
txOutAddress :: Address,
txOutValue :: Value,
txOutDatumHash :: Maybe DatumHash
}
The problem that you wish to solve
I'm trying to figure out how to create a script transaction without the plutus PAB backend. I have a use case where I want to be able to send arbitrary datums (and redeemers) to a script, without going through the PAB. The nodes will reject invalid datums anyway. And PAB requires explicit knowledge about endpoints, which I don't have.
Currently there are two ways afais:
cardano-cli transaction build
, which is flexible enough and then shove it through the balance endpoint. However, this is poor usability, because it requires dealing with a cli interface in addition to the wallet backend.Description
The main culprit seems to be the diverging of
TxOut
:In the swagger spec, that's here: https://github.com/input-output-hk/cardano-wallet/blob/315ee078e7466147c985155fbc0bccfc176831a3/specifications/api/swagger.yaml#L1119-L1131
And affecting the transactions-construct endpoint.
So the
constructTransaction
should maybe accept an arbitrary optional json value that represents a plutus datum. Same goes for redeemer.Implementation suggestions
Two example plutus datums are:
{"constructor":0,"fields":[{"bytes":"abcdefg"}]}
{"constructor":0,"fields":[{"constructor":0,"fields":[]}]}
So the wallet should probably accept
Aeson.Value
and then use the logic from the node to validate/convert: https://github.com/input-output-hk/cardano-node/blob/0cd6878769a10097e7c780e15efb9919fb94f669/cardano-api/src/Cardano/Api/ScriptData.hs#L480-L532Hashing and serialisation is done here: https://github.com/input-output-hk/cardano-node/blob/0cd6878769a10097e7c780e15efb9919fb94f669/cardano-api/src/Cardano/Api/ScriptData.hs#L109-L137
Looking at plutus itself, there are a couple of interesting places that show how it handles e.g. datum:
mustPayToTheScript
: https://github.com/input-output-hk/plutus-apps/blob/73e5f5ea613a7000da02b4b72900ae6ae1e36a95/plutus-ledger-constraints/src/Ledger/Constraints/TxConstraints.hs#L292processContraint
: https://github.com/input-output-hk/plutus-apps/blob/73e5f5ea613a7000da02b4b72900ae6ae1e36a95/plutus-ledger-constraints/src/Ledger/Constraints/TxConstraints.hs#L292addOwnOutput
: https://github.com/input-output-hk/plutus-apps/blob/73e5f5ea613a7000da02b4b72900ae6ae1e36a95/plutus-ledger-constraints/src/Ledger/Constraints/OffChain.hs#L510-L527mkTxt
: https://github.com/input-output-hk/plutus-apps/blob/73e5f5ea613a7000da02b4b72900ae6ae1e36a95/plutus-ledger-constraints/src/Ledger/Constraints/OffChain.hs#L412-L420cardano-cli code for
transaction build
: https://github.com/input-output-hk/cardano-node/blob/42809ad3d420f0695eb147d4c66b90573d27cafd/cardano-cli/src/Cardano/CLI/Shelley/Run/Transaction.hs#L436-L606