@@ -1957,6 +1957,117 @@ describe('V2 Wallet:', function () {
19571957 } ) ;
19581958 } ) ;
19591959
1960+ describe ( 'sendMany buildParams pass-through for account-based coins' , function ( ) {
1961+ let ethBasecoin ;
1962+ let ethWalletForBuildParams : Wallet ;
1963+
1964+ before ( function ( ) {
1965+ ethBasecoin = bitgo . coin ( 'teth' ) ;
1966+ ethWalletForBuildParams = new Wallet ( bitgo , ethBasecoin , {
1967+ id : '598f606cd8fc24710d2ebadb1d9459bb' ,
1968+ coin : 'teth' ,
1969+ keys : [
1970+ '598f606cd8fc24710d2ebad89dce86c2' ,
1971+ '598f606cc8e43aef09fcb785221d9dd2' ,
1972+ '5935d59cf660764331bafcade1855fd7' ,
1973+ ] ,
1974+ multisigType : 'onchain' ,
1975+ type : 'hot' ,
1976+ } ) ;
1977+ } ) ;
1978+
1979+ it ( 'should include top-level recipients alongside halfSigned in /tx/send for ETH' , async function ( ) {
1980+ const recipients = [ { address : '0x5208d8e80c6d1aef9be37b4bd19a9cf75ed93dc8' , amount : '200000000000000' } ] ;
1981+ const serverBuildParams = { recipients } ;
1982+ const prebuildReturn = {
1983+ halfSigned : {
1984+ recipients,
1985+ txHex : '0xdeadbeef' ,
1986+ expireTime : 1234567890 ,
1987+ contractSequenceId : 1001 ,
1988+ } ,
1989+ buildParams : serverBuildParams ,
1990+ } ;
1991+ sinon . stub ( ethWalletForBuildParams , 'prebuildAndSignTransaction' ) . resolves ( prebuildReturn ) ;
1992+ sinon . stub ( ethBasecoin , 'getExtraPrebuildParams' ) . resolves ( { } ) ;
1993+
1994+ const path = `/api/v2/${ ethWalletForBuildParams . coin ( ) } /wallet/${ ethWalletForBuildParams . id ( ) } /tx/send` ;
1995+ const sendNock = nock ( bgUrl )
1996+ . post ( path , ( body ) => {
1997+ // recipients must be at top level (not just inside halfSigned)
1998+ return (
1999+ body . recipients !== undefined &&
2000+ body . recipients [ 0 ] . address === recipients [ 0 ] . address &&
2001+ body . halfSigned !== undefined
2002+ ) ;
2003+ } )
2004+ . reply ( 200 , { status : 'signed' } ) ;
2005+
2006+ const result = await ethWalletForBuildParams . sendMany ( { recipients } ) ;
2007+ sendNock . isDone ( ) . should . be . true ( ) ;
2008+ result . should . have . property ( 'status' , 'signed' ) ;
2009+ } ) ;
2010+
2011+ it ( 'should include top-level recipients from selectParams even without server buildParams for ETH' , async function ( ) {
2012+ const recipients = [ { address : '0x5208d8e80c6d1aef9be37b4bd19a9cf75ed93dc8' , amount : '200000000000000' } ] ;
2013+ // No buildParams — simulates old server that doesn't return buildParams
2014+ const prebuildReturn = {
2015+ halfSigned : {
2016+ recipients,
2017+ txHex : '0xdeadbeef' ,
2018+ expireTime : 1234567890 ,
2019+ contractSequenceId : 1001 ,
2020+ } ,
2021+ } ;
2022+ sinon . stub ( ethWalletForBuildParams , 'prebuildAndSignTransaction' ) . resolves ( prebuildReturn ) ;
2023+ sinon . stub ( ethBasecoin , 'getExtraPrebuildParams' ) . resolves ( { } ) ;
2024+
2025+ const path = `/api/v2/${ ethWalletForBuildParams . coin ( ) } /wallet/${ ethWalletForBuildParams . id ( ) } /tx/send` ;
2026+ const sendNock = nock ( bgUrl )
2027+ . post ( path , ( body ) => {
2028+ // recipients should still be at top level via selectParams (user's original params)
2029+ return (
2030+ body . recipients !== undefined &&
2031+ body . recipients [ 0 ] . address === recipients [ 0 ] . address &&
2032+ body . halfSigned !== undefined
2033+ ) ;
2034+ } )
2035+ . reply ( 200 , { status : 'signed' } ) ;
2036+
2037+ const result = await ethWalletForBuildParams . sendMany ( { recipients } ) ;
2038+ sendNock . isDone ( ) . should . be . true ( ) ;
2039+ result . should . have . property ( 'status' , 'signed' ) ;
2040+ } ) ;
2041+
2042+ it ( 'should include eip1559 and nonce from server buildParams at top level for ETH' , async function ( ) {
2043+ const recipients = [ { address : '0x5208d8e80c6d1aef9be37b4bd19a9cf75ed93dc8' , amount : '200000000000000' } ] ;
2044+ const eip1559 = { maxPriorityFeePerGas : '57500000' , maxFeePerGas : '510214356' } ;
2045+ const serverBuildParams = { recipients, nonce : 42 , memo : { value : 'test' } } ;
2046+ const prebuildReturn = {
2047+ halfSigned : {
2048+ recipients,
2049+ txHex : '0xdeadbeef' ,
2050+ eip1559,
2051+ contractSequenceId : 3371928 ,
2052+ } ,
2053+ buildParams : serverBuildParams ,
2054+ } ;
2055+ sinon . stub ( ethWalletForBuildParams , 'prebuildAndSignTransaction' ) . resolves ( prebuildReturn ) ;
2056+ sinon . stub ( ethBasecoin , 'getExtraPrebuildParams' ) . resolves ( { } ) ;
2057+
2058+ const path = `/api/v2/${ ethWalletForBuildParams . coin ( ) } /wallet/${ ethWalletForBuildParams . id ( ) } /tx/send` ;
2059+ const sendNock = nock ( bgUrl )
2060+ . post ( path , ( body ) => {
2061+ return body . recipients !== undefined && body . halfSigned !== undefined && body . nonce === 42 ;
2062+ } )
2063+ . reply ( 200 , { status : 'signed' } ) ;
2064+
2065+ const result = await ethWalletForBuildParams . sendMany ( { recipients } ) ;
2066+ sendNock . isDone ( ) . should . be . true ( ) ;
2067+ result . should . have . property ( 'status' , 'signed' ) ;
2068+ } ) ;
2069+ } ) ;
2070+
19602071 describe ( 'Maximum Spendable' , function maximumSpendable ( ) {
19612072 let bgUrl ;
19622073
0 commit comments