@@ -9,6 +9,35 @@ function scriptToAddress(script: Uint8Array): string {
99 return `scriptPubKey:${ Buffer . from ( script ) . toString ( 'hex' ) } ` ;
1010}
1111
12+ type ParsedWalletOutput = fixedScriptWallet . ParsedOutput & { scriptId : fixedScriptWallet . ScriptId } ;
13+ type ParsedExternalOutput = fixedScriptWallet . ParsedOutput & { scriptId : null } ;
14+
15+ function isParsedWalletOutput ( output : ParsedWalletOutput | ParsedExternalOutput ) : output is ParsedWalletOutput {
16+ return output . scriptId !== null ;
17+ }
18+
19+ function isParsedExternalOutput ( output : ParsedWalletOutput | ParsedExternalOutput ) : output is ParsedExternalOutput {
20+ return output . scriptId === null ;
21+ }
22+
23+ function toChangeOutput ( output : ParsedWalletOutput ) : FixedScriptWalletOutput {
24+ return {
25+ address : output . address ?? scriptToAddress ( output . script ) ,
26+ amount : output . value . toString ( ) ,
27+ chain : output . scriptId . chain ,
28+ index : output . scriptId . index ,
29+ external : false ,
30+ } ;
31+ }
32+
33+ function toExternalOutput ( output : ParsedExternalOutput ) : Output {
34+ return {
35+ address : output . address ?? scriptToAddress ( output . script ) ,
36+ amount : output . value . toString ( ) ,
37+ external : true ,
38+ } ;
39+ }
40+
1241export function explainPsbtWasm (
1342 psbt : fixedScriptWallet . BitGoPsbt ,
1443 walletXpubs : Triple < string > ,
@@ -17,44 +46,45 @@ export function explainPsbtWasm(
1746 checkSignature ?: boolean ;
1847 outputScripts : Buffer [ ] ;
1948 } ;
49+ customChangeWalletXpubs ?: Triple < string > ;
2050 }
2151) : TransactionExplanationWasm {
2252 const parsed = psbt . parseTransactionWithWalletKeys ( walletXpubs , params . replayProtection ) ;
2353
2454 const changeOutputs : FixedScriptWalletOutput [ ] = [ ] ;
2555 const outputs : Output [ ] = [ ] ;
56+ const parsedCustomChangeOutputs = params . customChangeWalletXpubs
57+ ? psbt . parseOutputsWithWalletKeys ( params . customChangeWalletXpubs )
58+ : undefined ;
2659
27- parsed . outputs . forEach ( ( output ) => {
28- const address = output . address ?? scriptToAddress ( output . script ) ;
60+ const customChangeOutputs : FixedScriptWalletOutput [ ] = [ ] ;
2961
30- if ( output . scriptId ) {
62+ parsed . outputs . forEach ( ( output , i ) => {
63+ const parseCustomChangeOutput = parsedCustomChangeOutputs ?. [ i ] ;
64+ if ( isParsedWalletOutput ( output ) ) {
3165 // This is a change output
32- changeOutputs . push ( {
33- address,
34- amount : output . value . toString ( ) ,
35- chain : output . scriptId . chain ,
36- index : output . scriptId . index ,
37- external : false ,
38- } ) ;
66+ changeOutputs . push ( toChangeOutput ( output ) ) ;
67+ } else if ( parseCustomChangeOutput && isParsedWalletOutput ( parseCustomChangeOutput ) ) {
68+ customChangeOutputs . push ( toChangeOutput ( parseCustomChangeOutput ) ) ;
69+ } else if ( isParsedExternalOutput ( output ) ) {
70+ outputs . push ( toExternalOutput ( output ) ) ;
3971 } else {
40- // This is an external output
41- outputs . push ( {
42- address,
43- amount : output . value . toString ( ) ,
44- external : true ,
45- } ) ;
72+ throw new Error ( 'Invalid output' ) ;
4673 }
4774 } ) ;
4875
49- const changeAmount = changeOutputs . reduce ( ( sum , output ) => sum + BigInt ( output . amount ) , BigInt ( 0 ) ) ;
5076 const outputAmount = outputs . reduce ( ( sum , output ) => sum + BigInt ( output . amount ) , BigInt ( 0 ) ) ;
77+ const changeAmount = changeOutputs . reduce ( ( sum , output ) => sum + BigInt ( output . amount ) , BigInt ( 0 ) ) ;
78+ const customChangeAmount = customChangeOutputs . reduce ( ( sum , output ) => sum + BigInt ( output . amount ) , BigInt ( 0 ) ) ;
5179
5280 return {
5381 id : psbt . unsignedTxid ( ) ,
5482 outputAmount : outputAmount . toString ( ) ,
5583 changeAmount : changeAmount . toString ( ) ,
84+ customChangeAmount : customChangeAmount . toString ( ) ,
5685 outputs,
5786 changeOutputs,
87+ customChangeOutputs,
5888 fee : parsed . minerFee . toString ( ) ,
5989 } ;
6090}
0 commit comments