butaneprotocol / blaze-cardano

πŸ”₯ The hottest transaction building library for Cardano
https://blaze.butane.dev
Apache License 2.0
58 stars 22 forks source link

Experience feedback #29

Open KtorZ opened 5 months ago

KtorZ commented 5 months ago

Hey! I've been playing around with Blaze for a rather simple scenario and encountered quite a few hiccups so I thought I'd document them here. Do as you please with this feedback.

My goal was to create 2 rather simple transactions:

I'll skip on how I attempted to use Blockfrost as a provider initially only to hit a Error: not implemented later on. I believe the implementation is on its way but it's probably a good idea to not include unfinished stuff in the API 😢.

Verification key witness is never included?

Maybe it is me not wielding the API correctly, but I couldn't get signatures for UTxOs locked by a key to be automatically added. I was under the impression that the .complete step would give me a transaction that is ready to submit; but I ended up having to always manually sign the transaction and replace the witness set.

In the case of the second transaction that also contained other witnesses, it got a bit clunky as I need to make sure to preserve all witnesses:

const tx = await (await blaze.newTransaction())
  .addInput(utxo, redeemer)
  .lockLovelace(contractAddress, 1000000n, datum)
  .provideScript(script)
  .complete();

const witness = tx.witnessSet()
witness.setVkeys((await wallet.signTransaction(tx)).vkeys());
tx.setWitnessSet(witness);

Without that, I would constantly get an error pointing at a missing signature. I tried to manually add my own wallet's UTxO as input, added required signers and also manually setting a change address; but nothing would work except manually signing and setting the witness set.

purposeFromTag is not implemented

This function seems quite crucial in the construction of smart-contract based transactions, yet it is not implemented? That makes it impossible to actually work with smart-contract based transactions πŸ€”? I found this somewhat surprising but anyway, I manually edit the deps files in node_modules and got my way around it 😬 ...

Not everything is exposed from Core

I had some issues instantiating the input datum (the one from the utxo being spent). This one must be specified in the utxo given as input which I manually constructed since it doesn't belong to the wallet; so it cannot be queried easily. Yet, manually constructing an output is not quite practical, because (1) there's no way to directly create one with a datum, it must be added after. And (2) unlike other occurences of datum, the API doesn't work with a PlutusData but with a Serialization.Datum. Yet, the type is nowhere to be seen in the API. So I had to also add cardano-js-sdk as a dependency and import it. This mainly so I could create a datum from CBOR:

import { Serialization } from '@cardano-sdk/core';

const output = new Core.TransactionOutput(
  contractAddress,
  new Core.Value(1034400n),
);

output.setDatum(Serialization.Datum.newInlineData(Core.PlutusData.fromCbor('5820225a4599b804ba53745538c83bfa699ecf8077201b61484c91171f5910a4a8f9')));

The script integrity hash is wrongly computed

Maybe that's specific to the preview network (some incorrect protocol parameters?), but I was hit by the infamous PPViewHashesDontMatch πŸ’€. I didn't find any easy way around that as I haven't been doing anything fancy with the transaction building. But I got around by manually setting the hash using the one hinted by the error from the ledger, and resigned the transactions afterwards.

const body = tx.body();
body.setScriptDataHash('239683d2e7571ecf9a51bea15400fe5ac7c3eb4b7231be97529350dda9320208');
tx.setBody(body);

Cannot find collateral

I haven't fully diagnosed that one, but the builder did raise an error when I first build the transaction saying that I didn't have any suitable utxo for collateral. Which was obviously a lie because I did. But, I suspected that the builder simply refused to use a UTxO as both input and collateral (which is actually allowed by the ledger just fine). So I managed to work around that by just sending some funds to the wallet to create a new UTxO.

Negative collateral return

Then... I got hit with a rather puzzling error. The provider failed to deserialize the transaction due to a negative coin value. And indeed, the collateral return was set to roughly -7 Ada. The whole calculation of the collateral seemed actually quite off, although I haven't checked the actual cost model on Preview and whether they are perhaps a bit higher than mainnet? But my rather simple smart contract transaction (consuming <5% of the total budget) ended up costing more than 11 Ada! And likely as a consequence, the collateral return ended up negative πŸ™ƒ...

Again, I worked around by sending MOAR tAda to the wallet.

micahkendall commented 4 months ago

Witness construction on your 1st example may now be done as so:

const tx = await blaze.newTransaction()
  .addInput(utxo, redeemer)
  .lockLovelace(contractAddress, 1000000n, datum)
  .provideScript(script)
  .complete()
  .then(blaze.signTransaction);

PPViewHashesDontMatch is fixed (for now..).