Skip to content

Commit 4f3f9f2

Browse files
fixup! feat(input-selection): add large first input selection strategy
1 parent 15976ce commit 4f3f9f2

File tree

1 file changed

+182
-2
lines changed

1 file changed

+182
-2
lines changed

packages/input-selection/test/LargeFirstSelection/LargeFirstSelection.test.ts

Lines changed: 182 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,187 @@ import {
1212
import { TxTestUtil } from '@cardano-sdk/util-dev';
1313

1414
describe('LargeFirstSelection', () => {
15-
it('consumes just enough ADA UTXOs needed and leaves the remainder', async () => {
15+
it('picks the largest ADA UTxOs first', async () => {
16+
const selector = new LargeFirstSelector({
17+
changeAddressResolver: new MockChangeAddressResolver()
18+
});
19+
20+
const utxo = new Set([
21+
TxTestUtil.createUnspentTxOutput({ coins: 3_000_000n }),
22+
TxTestUtil.createUnspentTxOutput({ coins: 2_000_000n }),
23+
TxTestUtil.createUnspentTxOutput({ coins: 5_000_000n }),
24+
TxTestUtil.createUnspentTxOutput({ coins: 4_000_000n }),
25+
TxTestUtil.createUnspentTxOutput({ coins: 1_000_000n })
26+
]);
27+
28+
const outputs = new Set([TxTestUtil.createOutput({ coins: 6_000_000n })]);
29+
30+
const constraints = mockConstraintsToConstraints({
31+
...MOCK_NO_CONSTRAINTS,
32+
minimumCostCoefficient: 100n
33+
});
34+
35+
const results = await selector.select({
36+
constraints,
37+
implicitValue: {},
38+
outputs,
39+
preSelectedUtxo: new Set(),
40+
utxo
41+
});
42+
43+
const { selection, remainingUTxO } = results;
44+
45+
expect(selection.inputs.size).toBe(2);
46+
expect(remainingUTxO.size).toBe(3);
47+
48+
const inputValues = new Set([...selection.inputs.entries()].map(([[_, output]]) => output.value.coins));
49+
expect(inputValues.has(5_000_000n)).toBe(true);
50+
expect(inputValues.has(4_000_000n)).toBe(true);
51+
52+
const expectedFee = BigInt(selection.inputs.size) * 100n;
53+
expect(selection.fee).toBe(expectedFee);
54+
55+
expect(getCoinValueForAddress(mockChangeAddress, selection.change)).toBe(2_999_800n);
56+
57+
assertInputSelectionProperties({
58+
constraints: {
59+
...MOCK_NO_CONSTRAINTS,
60+
minimumCostCoefficient: 100n
61+
},
62+
implicitValue: {},
63+
outputs,
64+
results,
65+
utxo
66+
});
67+
});
68+
69+
it('picks the largest ADA UTxOs first as change', async () => {
70+
const selector = new LargeFirstSelector({
71+
changeAddressResolver: new MockChangeAddressResolver()
72+
});
73+
74+
const utxo = new Set([
75+
TxTestUtil.createUnspentTxOutput({ coins: 2_000_000n }),
76+
TxTestUtil.createUnspentTxOutput({ coins: 5_000_000n }),
77+
TxTestUtil.createUnspentTxOutput({ coins: 4_000_000n }),
78+
TxTestUtil.createUnspentTxOutput({ coins: 1_000_000n }),
79+
TxTestUtil.createUnspentTxOutput({ coins: 3_000_000n })
80+
]);
81+
82+
const outputs = new Set([TxTestUtil.createOutput({ coins: 9_000_000n })]);
83+
84+
const constraints = mockConstraintsToConstraints({
85+
...MOCK_NO_CONSTRAINTS,
86+
minimumCostCoefficient: 1n
87+
});
88+
89+
const results = await selector.select({
90+
constraints,
91+
implicitValue: {},
92+
outputs,
93+
preSelectedUtxo: new Set(),
94+
utxo
95+
});
96+
97+
const { selection, remainingUTxO } = results;
98+
99+
expect(selection.inputs.size).toBe(3);
100+
expect(remainingUTxO.size).toBe(2);
101+
102+
const inputValues = new Set([...selection.inputs.entries()].map(([[_, output]]) => output.value.coins));
103+
expect(inputValues.has(5_000_000n)).toBe(true);
104+
expect(inputValues.has(4_000_000n)).toBe(true);
105+
106+
const expectedFee = BigInt(selection.inputs.size);
107+
expect(selection.fee).toBe(expectedFee);
108+
109+
expect(getCoinValueForAddress(mockChangeAddress, selection.change)).toBe(2_999_997n);
110+
111+
assertInputSelectionProperties({
112+
constraints: {
113+
...MOCK_NO_CONSTRAINTS,
114+
minimumCostCoefficient: 100n
115+
},
116+
implicitValue: {},
117+
outputs,
118+
results,
119+
utxo
120+
});
121+
});
122+
123+
it('picks the largest native asset UTxOs first', async () => {
124+
const selector = new LargeFirstSelector({
125+
changeAddressResolver: new MockChangeAddressResolver()
126+
});
127+
128+
const assetX = asAssetId('X');
129+
130+
const utxo = new Set([
131+
TxTestUtil.createUnspentTxOutput({
132+
assets: asTokenMap([[assetX, 20n]]),
133+
coins: 3_000_000n
134+
}),
135+
TxTestUtil.createUnspentTxOutput({
136+
assets: asTokenMap([[assetX, 80n]]),
137+
coins: 3_000_000n
138+
}),
139+
TxTestUtil.createUnspentTxOutput({
140+
assets: asTokenMap([[assetX, 50n]]),
141+
coins: 3_000_000n
142+
}),
143+
TxTestUtil.createUnspentTxOutput({
144+
assets: asTokenMap([[assetX, 100n]]),
145+
coins: 3_000_000n
146+
}),
147+
TxTestUtil.createUnspentTxOutput({ coins: 3_000_000n })
148+
]);
149+
150+
const outputs = new Set([
151+
TxTestUtil.createOutput({
152+
assets: asTokenMap([[assetX, 130n]]),
153+
coins: 2_000_000n
154+
})
155+
]);
156+
157+
const constraints = mockConstraintsToConstraints({
158+
...MOCK_NO_CONSTRAINTS,
159+
minimumCostCoefficient: 100n
160+
});
161+
162+
const results = await selector.select({
163+
constraints,
164+
implicitValue: {},
165+
outputs,
166+
preSelectedUtxo: new Set(),
167+
utxo
168+
});
169+
170+
const { selection, remainingUTxO } = results;
171+
172+
expect(selection.inputs.size).toBe(2);
173+
const coinsPicked = new Set([...selection.inputs].map(([, o]) => o.value.assets?.get(assetX) ?? 0n));
174+
expect(coinsPicked.has(100n)).toBe(true);
175+
expect(coinsPicked.has(80n)).toBe(true);
176+
expect(remainingUTxO.size).toBe(3);
177+
178+
const expectedFee = BigInt(selection.inputs.size) * 100n;
179+
expect(selection.fee).toBe(expectedFee);
180+
181+
expect(selection.change.some((txOut) => txOut.value.assets?.get(assetX) === 50n)).toBe(true);
182+
183+
assertInputSelectionProperties({
184+
constraints: {
185+
...MOCK_NO_CONSTRAINTS,
186+
minimumCostCoefficient: 100n
187+
},
188+
implicitValue: {},
189+
outputs,
190+
results,
191+
utxo
192+
});
193+
});
194+
195+
it('consumes just enough ADA UTxOs needed and leaves the remainder', async () => {
16196
const selector = new LargeFirstSelector({
17197
changeAddressResolver: new MockChangeAddressResolver()
18198
});
@@ -61,7 +241,7 @@ describe('LargeFirstSelection', () => {
61241
});
62242
});
63243

64-
it('picks the single largest UTXO for each required asset', async () => {
244+
it('picks the single largest UTxO for each required asset', async () => {
65245
const selector = new LargeFirstSelector({
66246
changeAddressResolver: new MockChangeAddressResolver()
67247
});

0 commit comments

Comments
 (0)