@@ -13,27 +13,14 @@ import {
1313 ParseTransactionOptions ,
1414} from '../../abstractUtxoCoin' ;
1515import { fetchKeychains , getKeySignatures , toKeychainTriple , UtxoKeychain , UtxoNamedKeychains } from '../../keychains' ;
16+ import { ComparableOutput , outputDifference } from '../outputDifference' ;
17+ import { fromExtendedAddressFormatToScript , toExtendedAddressFormat } from '../recipient' ;
1618
1719import { CustomChangeOptions , parseOutput } from './parseOutput' ;
1820
19- /**
20- * @param first
21- * @param second
22- * @returns {Array } All outputs that are in the first array but not in the second
23- */
24- export function outputDifference ( first : Output [ ] , second : Output [ ] ) : Output [ ] {
25- const keyFunc = ( { address, amount } : Output ) : string => `${ address } :${ amount } ` ;
26- const groupedOutputs = _ . groupBy ( first , keyFunc ) ;
27-
28- second . forEach ( ( output ) => {
29- const group = groupedOutputs [ keyFunc ( output ) ] ;
30- if ( group ) {
31- group . pop ( ) ;
32- }
33- } ) ;
34-
35- return _ . flatten ( _ . values ( groupedOutputs ) ) ;
36- }
21+ export type ComparableOutputWithExternal < TValue > = ComparableOutput < TValue > & {
22+ external : boolean | undefined ;
23+ } ;
3724
3825export async function parseTransaction < TNumber extends bigint | number > (
3926 coin : AbstractUtxoCoin ,
@@ -116,8 +103,6 @@ export async function parseTransaction<TNumber extends bigint | number>(
116103 }
117104 }
118105
119- const missingOutputs = outputDifference ( expectedOutputs , allOutputs ) ;
120-
121106 // get the keychains from the custom change wallet if needed
122107 let customChange : CustomChangeOptions | undefined ;
123108 const { customChangeWalletId = undefined } = wallet . coinSpecific ( ) || { } ;
@@ -175,18 +160,30 @@ export async function parseTransaction<TNumber extends bigint | number>(
175160
176161 const changeOutputs = _ . filter ( allOutputDetails , { external : false } ) ;
177162
178- // these are all the outputs that were not originally explicitly specified in recipients
179- // ideally change outputs or a paygo output that might have been added
180- const implicitOutputs = outputDifference ( allOutputDetails , expectedOutputs ) ;
163+ function toComparableOutputsWithExternal ( outputs : Output [ ] ) : ComparableOutputWithExternal < bigint | 'max' > [ ] {
164+ return outputs . map ( ( output ) => ( {
165+ script : fromExtendedAddressFormatToScript ( output . address , coin . network ) ,
166+ value : output . amount === 'max' ? 'max' : ( BigInt ( output . amount ) as bigint | 'max' ) ,
167+ external : output . external ,
168+ } ) ) ;
169+ }
170+
171+ const missingOutputs = outputDifference (
172+ toComparableOutputsWithExternal ( expectedOutputs ) ,
173+ toComparableOutputsWithExternal ( allOutputs )
174+ ) ;
181175
182- const explicitOutputs = outputDifference ( allOutputDetails , implicitOutputs ) ;
176+ const implicitOutputs = outputDifference (
177+ toComparableOutputsWithExternal ( allOutputDetails ) ,
178+ toComparableOutputsWithExternal ( expectedOutputs )
179+ ) ;
180+ const explicitOutputs = outputDifference ( toComparableOutputsWithExternal ( allOutputDetails ) , implicitOutputs ) ;
183181
184182 // these are all the non-wallet outputs that had been originally explicitly specified in recipients
185- const explicitExternalOutputs = _ . filter ( explicitOutputs , { external : true } ) ;
186-
183+ const explicitExternalOutputs = explicitOutputs . filter ( ( output ) => output . external ) ;
187184 // this is the sum of all the originally explicitly specified non-wallet output values
188185 const explicitExternalSpendAmount = utxolib . bitgo . toTNumber < TNumber > (
189- explicitExternalOutputs . reduce ( ( sum : bigint , o : Output ) => sum + BigInt ( o . amount ) , BigInt ( 0 ) ) as bigint ,
186+ explicitExternalOutputs . reduce ( ( sum : bigint , o ) => sum + BigInt ( o . value ) , BigInt ( 0 ) ) as bigint ,
190187 coin . amountType
191188 ) ;
192189
@@ -201,19 +198,27 @@ export async function parseTransaction<TNumber extends bigint | number>(
201198
202199 // make sure that all the extra addresses are change addresses
203200 // get all the additional external outputs the server added and calculate their values
204- const implicitExternalOutputs = _ . filter ( implicitOutputs , { external : true } ) ;
201+ const implicitExternalOutputs = implicitOutputs . filter ( ( output ) => output . external ) ;
205202 const implicitExternalSpendAmount = utxolib . bitgo . toTNumber < TNumber > (
206- implicitExternalOutputs . reduce ( ( sum : bigint , o : Output ) => sum + BigInt ( o . amount ) , BigInt ( 0 ) ) as bigint ,
203+ implicitExternalOutputs . reduce ( ( sum : bigint , o ) => sum + BigInt ( o . value ) , BigInt ( 0 ) ) as bigint ,
207204 coin . amountType
208205 ) ;
209206
207+ function toOutputs ( outputs : ComparableOutputWithExternal < bigint | 'max' > [ ] ) : Output [ ] {
208+ return outputs . map ( ( output ) => ( {
209+ address : toExtendedAddressFormat ( output . script , coin . network ) ,
210+ amount : output . value . toString ( ) ,
211+ external : output . external ,
212+ } ) ) ;
213+ }
214+
210215 return {
211216 keychains,
212217 keySignatures : getKeySignatures ( wallet ) ?? { } ,
213218 outputs : allOutputDetails ,
214- missingOutputs,
215- explicitExternalOutputs,
216- implicitExternalOutputs,
219+ missingOutputs : toOutputs ( missingOutputs ) ,
220+ explicitExternalOutputs : toOutputs ( explicitExternalOutputs ) ,
221+ implicitExternalOutputs : toOutputs ( implicitExternalOutputs ) ,
217222 changeOutputs,
218223 explicitExternalSpendAmount,
219224 implicitExternalSpendAmount,
0 commit comments