@@ -12,7 +12,187 @@ import {
12
12
import { TxTestUtil } from '@cardano-sdk/util-dev' ;
13
13
14
14
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 ( ) => {
16
196
const selector = new LargeFirstSelector ( {
17
197
changeAddressResolver : new MockChangeAddressResolver ( )
18
198
} ) ;
@@ -61,7 +241,7 @@ describe('LargeFirstSelection', () => {
61
241
} ) ;
62
242
} ) ;
63
243
64
- it ( 'picks the single largest UTXO for each required asset' , async ( ) => {
244
+ it ( 'picks the single largest UTxO for each required asset' , async ( ) => {
65
245
const selector = new LargeFirstSelector ( {
66
246
changeAddressResolver : new MockChangeAddressResolver ( )
67
247
} ) ;
0 commit comments