spacebudz / lucid

Lucid is a library, which allows you to create Cardano transactions and off-chain code for your Plutus contracts in JavaScript, Deno and Node.js.
https://lucid.spacebudz.io
MIT License
336 stars 132 forks source link

How can I chain transaction? #145

Open jeffhappily opened 1 year ago

jeffhappily commented 1 year ago

I'm trying to use lucid to chain transaction, meaning to create a transaction that consumes output from another transaction in mempool, which is yet to be confirmed on-chain, it is possible to do it on Cardano, but it's not obvious how can I do it using lucid.

I tried to do it but I got this error

{
  "CannotCreateEvaluationContext": {
    "reason": "Unknown transaction input (missing from UTxO set): b7e37f8ebb8a113517055d0c637bfe7d4e266e816c83c034a25af70b31b1826a#0"
  }
}

The error seems to be coming from the call to construct function https://github.com/spacebudz/lucid/blob/4c92f5610ed5f53408c6e15caf78a8e310d68a7b/src/lucid/tx.ts#L584-L588 and the error message seems to be coming from Ogmios, but since the tx builder is from wasm, I'm not entirely sure.

But if this error truly comes from Ogmios, I do know that they support transaction chaining, in their EvaluateTx API, they take an argument called additionalUtxoSet, not sure if Lucid supports it or not.

Appreciate if I could get help on this issue.

alessandrokonrad commented 1 year ago

Hey, what Lucid version are you on? I'm not sure if you are on an older version or have nativeUplc set to false. Lucid can run plutus core itself now, then you should not get the error message from ogmios. Chaining should work fine then.

jeffhappily commented 1 year ago

@alessandrokonrad Removing the nativeUplc does get rid of the error, I got into another error which says something like TranslationLogicMissingInput, I'll look more into it later, but does this mean I have to somehow specify the additionalUtxoSet? Or do you have a simple example where how can transaction chaining be done in lucid?

Here's what I'm currently doing:

  const tx = await lucid
    .newTx()
    ...
    .complete();

  const signedTx = await tx.sign().complete();

  const h = signedTx.toHash();
  const i = signedTx.txSigned
    .to_js_value()
    .body.outputs.findIndex((out: any) => out.address === xxx);

  const outputJs = signedTx.txSigned.to_js_value().body.outputs[i];
  const output = signedTx.txSigned.body().outputs().get(i);

  const tx2 = lucid
    .newTx()
    .collectFrom(
      [
        {
          txHash: h,
          outputIndex: i,
          assets: valueToAssets(output.amount()),
          address: outputJs.address,
          datum: Buffer.from(
            signedTx.txSigned
              .body()
              .outputs()
              .get(i)
              .datum()
              .as_data()
              .get()
              .to_bytes()
          ).toString("hex"),
        },
      ],
      unitData
    )
    ...
alessandrokonrad commented 1 year ago

TranslationLogicMissingInput means you miss the input. Are you submitting through blockfrost? I was planning to add a more high level API for tx chaining, I thought some basic tx chaining is already possible, but there are some other complications I just realized. It doesn't work in all scenarios yet.

jeffhappily commented 1 year ago

Yup, the provider is blockfrost, is it because blockfrost doesn't support tx chaining yet?

jeffhappily commented 1 year ago

@alessandrokonrad In that case, would switching to another provider like Kupmios resolve this issue? Or it has nothing to do with the provider itself?

alessandrokonrad commented 1 year ago

I think blockfrost actually supports chaining, but you can check out the the Kupmios provider too. I think you just have to try out what works and what not. The difficulty is just coin selection. Lucid may select UTxOs that you already spent. You can disable coin selection, but that makes it harder of course. As I said I may gonna write something more high level for this. If you have ideas for that too, feel free to share and contribute to Lucid.

lemmon-714 commented 1 year ago

@alessandrokonrad a high-level API for tx-chaining would be quite awesome! :O

lemmon-714 commented 1 year ago

I looked into it, and thought it might have to rest on keeping track of the spent/created outputs somewhere, and replace one or some of the utxo-getters. Rn I'm trying to wrap my head around how to best achieve this, as it appears this varies based on wallet/wallet-selection-method.

Will create a pull request once I got something.

SynthLuvr commented 8 months ago

Lucid may select UTxOs that you already spent

We get around this by tracking which UTxOs are spent and then removing them from coin selection. We're currently doing this tracking outside of the Lucid instance, but I think Lucid could be updated to track this internally within Lucid. The main issue would be that Lucid typically queries for new UTxOs during building of transactions, so any spent UTxOs would be re-added.

I think blockfrost actually supports chaining

Can confirm that Blockfrost supports chaining, up to a limit. We got to about 3 transactions chained before Blockfrost throws an error.

will-break-it commented 8 months ago

Added an API that simplifies chaining txs here. https://github.com/spacebudz/lucid/pull/231