Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add utxos option to Tx.complete method #101

Closed
wants to merge 1 commit into from

Conversation

eliasearlym
Copy link

I'm still learning the ins and outs of this lib and the serialization lib so this may not be necessary...

I'd like to control the utxo set that is passed to the coin selection algorithm during Tx.complete(). Currently, if coinSelection is enabled during Tx.complete() it will fetch the entire utxo set from the wallet by default. I'd like the option to pass specific a specific utxo set instead.

I imagine there is another way to do this - but this approach does work. I'll note that support for "single utxo" transactions would need to be added as well, the method below requires at least 2 utxos to work (this is because the add_inputs_from method is being used).

// Create tx and create 1 output within the txBuilder
let tx = await lucid.newTx()
  .payToAddress(receiverAddr, { lovelace: 2000000n });

// Insert the first 2 utxos from an arbitrary number of utxos
const utxos = await lucid.wallet.getUtxos();
const coreUtxos = C.TransactionUnspentOutputs.new();
coreUtxos.add(utxoToCore(utxos[0]));
coreUtxos.add(utxoToCore(utxos[1]));
tx.txBuilder.add_inputs_from(coreUtxos, C.Address.from_bech32(changeAddr));

// Pass the 2 specified utxos to coin selection
tx = await tx.complete({
    utxos: coreUtxos,
});

@alessandrokonrad
Copy link
Contributor

I'm still learning the ins and outs of this lib and the serialization lib so this may not be necessary...

I'd like to control the utxo set that is passed to the coin selection algorithm during Tx.complete(). Currently, if coinSelection is enabled during Tx.complete() it will fetch the entire utxo set from the wallet by default. I'd like the option to pass specific a specific utxo set instead.

I imagine there is another way to do this - but this approach does work. I'll note that support for "single utxo" transactions would need to be added as well, the method below requires at least 2 utxos to work (this is because the add_inputs_from method is being used).

// Create tx and create 1 output within the txBuilder
let tx = await lucid.newTx()
  .payToAddress(receiverAddr, { lovelace: 2000000n });

// Insert the first 2 utxos from an arbitrary number of utxos
const utxos = await lucid.wallet.getUtxos();
const coreUtxos = C.TransactionUnspentOutputs.new();
coreUtxos.add(utxoToCore(utxos[0]));
coreUtxos.add(utxoToCore(utxos[1]));
tx.txBuilder.add_inputs_from(coreUtxos, C.Address.from_bech32(changeAddr));

// Pass the 2 specified utxos to coin selection
tx = await tx.complete({
    utxos: coreUtxos,
});

Is your goal that these UTxOs are definitely used in the Tx or just in the coin selection, but can still be dropped by it?

@eliasearlym
Copy link
Author

eliasearlym commented Oct 21, 2022

Is your goal that these UTxOs are definitely used in the Tx or just in the coin selection, but can still be dropped by it?

In my case, I don't want coin selection dropping any of the specified UTxOs which is why I add them as inputs before passing them to coin selection.

Users can still go either route. Simply pass the UTxO set to coin selection without specifying inputs if you don't mind UTxOs getting dropped.

@alessandrokonrad
Copy link
Contributor

In my case, I don't want coin selection dropping any of the specified UTxOs which is why I add them as inputs before passing them to coin selection.

Okay good. Then you can simply do:

let tx = await lucid.newTx().collectFrom([utxo])...

.collectFrom lets you precisly add utxos to the tx

@eliasearlym
Copy link
Author

eliasearlym commented Oct 22, 2022

.collectFrom lets you precisly add utxos to the tx

Awesome, there's just the issue now of the UTxO set that's passed to coin selection...

In the below example, coin selection still adds additional UTxOs (which I do not want to consume)...in the below tx I add 1 input and 1 output...when I look at the completed tx, coin selection has added an additional 3 inputs that are unnecessary, hence why I'd like the option to pass a specific UTxO set directly to coin selection to prevent this from happening.

// Fetch wallet UTxOs
const utxos = await lucid.wallet.getUtxos();

// Add 1 input and 1 output, complete tx with coin selection
const tx = await lucid.newTx()
  .collectFrom([utxos[0]])
  .payToAddress(receiver, { lovelace: 2000000n })
  .complete({ coinSelection: true })
  
// Read completed Tx...
console.log(tx.txComplete.to_js_value());
/**
inputs: [
      {
        transaction_id: '2806f9e18fc0e12cc5fa43498e953329e96111e1a4394c209d2853cbbad10c27',
        index: '0'
      },
      {
        transaction_id: 'edfdb3849e0d9ebc38f55a5cb02ffeaa2f21ea097956a3b187c2ab4f3be74d0a',
        index: '0'
      },
      {
        transaction_id: '3ecf6f2142dcd8acfb25b67463030e35994649ef9e672dba7c60f13581aaa22a',
        index: '0'
      },
      {
        transaction_id: '2f94eb98fab223ada8a2de0225d23e7f54a4ce0576629dd79ed755d224072f9b',
        index: '0'
      }
] */

Another solution would be for Tx.complete() to check if coin selection would work with the provided inputs first before fetching the entire wallet UTxO set. Users could toggle this behavior i.e. if the tx fails with the user provided inputs 1: either fail outright, or 2: fetch the entire wallet UTxO set and attempt to add sufficient inputs. This method would come with a performance boost and potentially reduce the number of requests by 1.

Bottom line - for my use case, I don't want coin selection adding additional inputs. This may be a niche use case which doesn't require native support, I'll let you make that call - in that case, I will just hack around it.

@alessandrokonrad
Copy link
Contributor

I don't want coin selection adding additional inputs

I'm not sure if I totally got it, but if you don't want the coin selection to ever run and you know upfront already what UTxOs you want to consume, then simply set coinSelection: false and use .collectFrom

@eliasearlym
Copy link
Author

eliasearlym commented Oct 22, 2022

Ah, that seems to work - thanks so much man.

@eliasearlym
Copy link
Author

Functionality is available

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants