11import assert from 'assert' ;
22
3- import { mockPsbtDefaultWithDescriptorTemplate } from '../../core/descriptor/psbt/mock.utils' ;
3+ import * as utxolib from '@bitgo/utxo-lib' ;
4+ import { Descriptor } from '@bitgo/wasm-miniscript' ;
5+
6+ import { mockPsbtDefault } from '../../core/descriptor/psbt/mock.utils' ;
47import { ParsedOutputsBigInt , toBaseParsedTransactionOutputsFromPsbt } from '../../../src/transaction/descriptor/parse' ;
5- import { getDefaultXPubs , getDescriptorMap } from '../../core/descriptor/descriptor.utils' ;
8+ import { getDefaultXPubs , getDescriptor , getDescriptorMap } from '../../core/descriptor/descriptor.utils' ;
69import { toPlainObject } from '../../core/toPlainObject.utils' ;
710import {
811 AggregateValidationError ,
@@ -12,6 +15,7 @@ import {
1215} from '../../../src/transaction/descriptor/verifyTransaction' ;
1316import { toAmountType } from '../../../src/transaction/descriptor/parseToAmountType' ;
1417import { BaseOutput } from '../../../src' ;
18+ import { createAddressFromDescriptor } from '../../../src/core/descriptor' ;
1519
1620import { getFixtureRoot } from './fixtures.utils' ;
1721
@@ -46,9 +50,23 @@ function toMaxOutput(output: OutputWithValue): OutputWithValue<'max'> {
4650}
4751
4852describe ( 'parse' , function ( ) {
49- const psbt = mockPsbtDefaultWithDescriptorTemplate ( 'Wsh2Of3' ) ;
53+ const descriptorSelf = getDescriptor ( 'Wsh2Of3' , getDefaultXPubs ( 'a' ) ) ;
54+ const descriptorOther = getDescriptor ( 'Wsh2Of3' , getDefaultXPubs ( 'b' ) ) ;
55+ const psbt = mockPsbtDefault ( { descriptorSelf, descriptorOther } ) ;
56+
57+ function recipient ( descriptor : Descriptor , index : number , value = 1000 ) {
58+ return { value, address : createAddressFromDescriptor ( descriptor , index , utxolib . networks . bitcoin ) } ;
59+ }
60+
61+ function internalRecipient ( index : number , value ?: number ) : OutputWithValue {
62+ return recipient ( descriptorSelf , index , value ) ;
63+ }
5064
51- function getBaseParsedTransaction ( recipients : OutputWithValue [ ] ) : ParsedOutputsBigInt {
65+ function externalRecipient ( index : number , value ?: number ) : OutputWithValue {
66+ return recipient ( descriptorOther , index , value ) ;
67+ }
68+
69+ function getBaseParsedTransaction ( psbt : utxolib . bitgo . UtxoPsbt , recipients : OutputWithValue [ ] ) : ParsedOutputsBigInt {
5270 return toBaseParsedTransactionOutputsFromPsbt (
5371 psbt ,
5472 getDescriptorMap ( 'Wsh2Of3' , getDefaultXPubs ( 'a' ) ) ,
@@ -59,27 +77,30 @@ describe('parse', function () {
5977
6078 describe ( 'toBase' , function ( ) {
6179 it ( 'should return the correct BaseParsedTransactionOutputs' , async function ( ) {
62- await assertEqualFixture ( 'parseWithoutRecipients.json' , toPlainObject ( getBaseParsedTransaction ( [ ] ) ) ) ;
80+ await assertEqualFixture ( 'parseWithoutRecipients.json' , toPlainObject ( getBaseParsedTransaction ( psbt , [ ] ) ) ) ;
6381 await assertEqualFixture (
6482 'parseWithExternalRecipient.json' ,
65- toPlainObject ( getBaseParsedTransaction ( [ psbt . txOutputs [ 0 ] ] ) )
83+ toPlainObject ( getBaseParsedTransaction ( psbt , [ psbt . txOutputs [ 0 ] ] ) )
6684 ) ;
6785 await assertEqualFixture (
6886 'parseWithInternalRecipient.json' ,
69- toPlainObject ( getBaseParsedTransaction ( [ psbt . txOutputs [ 1 ] ] ) )
87+ toPlainObject ( getBaseParsedTransaction ( psbt , [ psbt . txOutputs [ 1 ] ] ) )
7088 ) ;
7189 await assertEqualFixture (
7290 'parseWithExternalRecipient.json' ,
7391 // max recipient: ignore actual value
74- toPlainObject ( getBaseParsedTransaction ( [ toMaxOutput ( psbt . txOutputs [ 0 ] ) ] ) )
92+ toPlainObject ( getBaseParsedTransaction ( psbt , [ toMaxOutput ( psbt . txOutputs [ 0 ] ) ] ) )
7593 ) ;
7694 } ) ;
7795
7896 function assertEqualValidationError ( actual : unknown , expected : AggregateValidationError ) {
97+ function normErrors ( e : Error [ ] ) : Error [ ] {
98+ return e . map ( ( e ) => ( { ...e , stack : undefined } ) ) ;
99+ }
79100 if ( actual instanceof AggregateValidationError ) {
80- assert . deepStrictEqual ( actual . errors , expected . errors ) ;
101+ assert . deepStrictEqual ( normErrors ( actual . errors ) , normErrors ( expected . errors ) ) ;
81102 } else {
82- throw new Error ( 'unexpected error type' ) ;
103+ throw new Error ( 'unexpected error type: ' + actual ) ;
83104 }
84105 }
85106
@@ -90,35 +111,48 @@ describe('parse', function () {
90111 } ) ;
91112 }
92113
93- it ( 'should throw expected errors' , function ( ) {
114+ function implicitOutputError ( output : OutputWithValue , { external = true } = { } ) : ErrorImplicitExternalOutputs {
115+ return new ErrorImplicitExternalOutputs ( [ { ...toBaseOutputBigInt ( output ) , external } ] ) ;
116+ }
117+
118+ function missingOutputError ( output : OutputWithValue , { external = true } = { } ) : ErrorMissingOutputs {
119+ return new ErrorMissingOutputs ( [ { ...toBaseOutputBigInt ( output ) , external } ] ) ;
120+ }
121+
122+ it ( 'should throw expected error: no recipient requested' , function ( ) {
94123 assertValidationError (
95- ( ) => assertExpectedOutputDifference ( getBaseParsedTransaction ( [ ] ) ) ,
96- new AggregateValidationError ( [
97- new ErrorImplicitExternalOutputs ( [ { ...toBaseOutputBigInt ( psbt . txOutputs [ 0 ] ) , external : true } ] ) ,
98- ] )
124+ ( ) => assertExpectedOutputDifference ( getBaseParsedTransaction ( psbt , [ ] ) ) ,
125+ new AggregateValidationError ( [ implicitOutputError ( psbt . txOutputs [ 0 ] ) ] )
99126 ) ;
127+ } ) ;
100128
129+ it ( 'should throw expected error: only internal recipient requested' , function ( ) {
101130 assertValidationError (
102- ( ) => assertExpectedOutputDifference ( getBaseParsedTransaction ( [ ] ) ) ,
103- new AggregateValidationError ( [
104- new ErrorImplicitExternalOutputs ( [ { ...toBaseOutputBigInt ( psbt . txOutputs [ 0 ] ) , external : true } ] ) ,
105- ] )
131+ ( ) => assertExpectedOutputDifference ( getBaseParsedTransaction ( psbt , [ psbt . txOutputs [ 1 ] ] ) ) ,
132+ new AggregateValidationError ( [ implicitOutputError ( psbt . txOutputs [ 0 ] ) ] )
106133 ) ;
134+ } ) ;
107135
136+ it ( 'should throw expected error: only internal max recipient requested' , function ( ) {
108137 assertValidationError (
109- ( ) => assertExpectedOutputDifference ( getBaseParsedTransaction ( [ psbt . txOutputs [ 1 ] ] ) ) ,
110- new AggregateValidationError ( [
111- new ErrorMissingOutputs ( [ { ...toBaseOutputBigInt ( psbt . txOutputs [ 1 ] ) , external : true } ] ) ,
112- new ErrorImplicitExternalOutputs ( [ { ...toBaseOutputBigInt ( psbt . txOutputs [ 0 ] ) , external : true } ] ) ,
113- ] )
138+ ( ) => assertExpectedOutputDifference ( getBaseParsedTransaction ( psbt , [ toMaxOutput ( psbt . txOutputs [ 1 ] ) ] ) ) ,
139+ new AggregateValidationError ( [ implicitOutputError ( psbt . txOutputs [ 0 ] ) ] )
114140 ) ;
141+ } ) ;
142+
143+ it ( 'should throw expected error: swapped recipient' , function ( ) {
144+ const recipient = externalRecipient ( 99 ) ;
145+ assertValidationError (
146+ ( ) => assertExpectedOutputDifference ( getBaseParsedTransaction ( psbt , [ recipient ] ) ) ,
147+ new AggregateValidationError ( [ missingOutputError ( recipient ) , implicitOutputError ( psbt . txOutputs [ 0 ] ) ] )
148+ ) ;
149+ } ) ;
115150
151+ it ( 'should throw expected error: missing internal recipient' , function ( ) {
152+ const recipient = internalRecipient ( 99 ) ;
116153 assertValidationError (
117- ( ) => assertExpectedOutputDifference ( getBaseParsedTransaction ( [ toMaxOutput ( psbt . txOutputs [ 1 ] ) ] ) ) ,
118- new AggregateValidationError ( [
119- new ErrorMissingOutputs ( [ { ...toBaseOutputBigInt ( toMaxOutput ( psbt . txOutputs [ 1 ] ) ) , external : true } ] ) ,
120- new ErrorImplicitExternalOutputs ( [ { ...toBaseOutputBigInt ( psbt . txOutputs [ 0 ] ) , external : true } ] ) ,
121- ] )
154+ ( ) => assertExpectedOutputDifference ( getBaseParsedTransaction ( psbt , [ recipient ] ) ) ,
155+ new AggregateValidationError ( [ missingOutputError ( recipient ) , implicitOutputError ( psbt . txOutputs [ 0 ] ) ] )
122156 ) ;
123157 } ) ;
124158 } ) ;
0 commit comments