Skip to content

Commit 432a619

Browse files
authored
Support potential inputs in txbuilder (#223)
* Support potential inputs in txbuilder This feature will allow users to define a list of potential utxo, which could be returned by a wallet, for UTxO selector to select inputs from. * Property based testing for potential inputs
1 parent a1c840b commit 432a619

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

pycardano/txbuilder.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ class TransactionBuilder:
112112

113113
_inputs: List[UTxO] = field(init=False, default_factory=lambda: [])
114114

115+
_potential_inputs: List[UTxO] = field(init=False, default_factory=lambda: [])
116+
115117
_excluded_inputs: List[UTxO] = field(init=False, default_factory=lambda: [])
116118

117119
_input_addresses: List[Union[Address, str]] = field(
@@ -331,6 +333,10 @@ def add_output(
331333
def inputs(self) -> List[UTxO]:
332334
return self._inputs
333335

336+
@property
337+
def potential_inputs(self) -> List[UTxO]:
338+
return self._potential_inputs
339+
334340
@property
335341
def excluded_inputs(self) -> List[UTxO]:
336342
return self._excluded_inputs
@@ -984,21 +990,34 @@ def build(
984990
lambda p, n, v: v > 0
985991
)
986992

993+
# Create a set of all seen utxos in addition to other utxo lists.
994+
# We need this set to avoid adding the same utxo twice.
995+
# The reason of not turning all utxo lists into sets is that we want to keep the order of utxos and make
996+
# utxo selection deterministic.
997+
seen_utxos = set(selected_utxos)
998+
987999
# When there are positive coin or native asset quantity in unfulfilled Value
9881000
if Value() < unfulfilled_amount:
9891001
additional_utxo_pool = []
9901002
additional_amount = Value()
1003+
1004+
for utxo in self.potential_inputs:
1005+
additional_amount += utxo.output.amount
1006+
seen_utxos.add(utxo)
1007+
additional_utxo_pool.append(utxo)
1008+
9911009
for address in self.input_addresses:
9921010
for utxo in self.context.utxos(address):
9931011
if (
994-
utxo not in selected_utxos
1012+
utxo not in seen_utxos
9951013
and utxo not in self.excluded_inputs
9961014
and not utxo.output.datum_hash # UTxO with datum should be added by using `add_script_input`
9971015
and not utxo.output.datum
9981016
and not utxo.output.script
9991017
):
10001018
additional_utxo_pool.append(utxo)
10011019
additional_amount += utxo.output.amount
1020+
seen_utxos.add(utxo)
10021021

10031022
for index, selector in enumerate(self.utxo_selectors):
10041023
try:

test/pycardano/test_txbuilder.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import copy
12
from dataclasses import replace
23
from test.pycardano.test_key import SK
34
from test.pycardano.util import chain_context
@@ -122,6 +123,33 @@ def test_tx_builder_with_certain_input(chain_context):
122123
assert expected == tx_body.to_primitive()
123124

124125

126+
def test_tx_builder_with_potential_inputs(chain_context):
127+
tx_builder = TransactionBuilder(chain_context, [RandomImproveMultiAsset([0, 0])])
128+
sender = "addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x"
129+
sender_address = Address.from_primitive(sender)
130+
131+
utxos = chain_context.utxos(sender)
132+
133+
tx_builder.potential_inputs.extend(utxos)
134+
135+
for i in range(20):
136+
utxo = copy.deepcopy(utxos[0])
137+
utxo.input.index = i + 100
138+
tx_builder.potential_inputs.append(utxo)
139+
140+
assert len(tx_builder.potential_inputs) > 1
141+
142+
tx_builder.add_output(
143+
TransactionOutput.from_primitive(
144+
[sender, [5000000, {b"1111111111111111111111111111": {b"Token1": 1}}]]
145+
)
146+
)
147+
148+
tx_body = tx_builder.build(change_address=sender_address)
149+
150+
assert len(tx_body.inputs) < len(tx_builder.potential_inputs)
151+
152+
125153
def test_tx_builder_multi_asset(chain_context):
126154
tx_builder = TransactionBuilder(chain_context)
127155
sender = "addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x"

0 commit comments

Comments
 (0)