@@ -2,8 +2,20 @@ import * as _ from 'lodash';
22
33import * as nock from 'nock' ;
44import fixtures from '../../fixtures/staking/stakingWallet' ;
5-
6- import { Enterprise , Environments , Keychain , Keychains , StakingWallet , Wallet } from '@bitgo/sdk-core' ;
5+ import * as opethFixtures from '../../fixtures/staking/topethStakingFixtures' ;
6+
7+ import {
8+ Enterprise ,
9+ Environments ,
10+ Keychain ,
11+ Keychains ,
12+ PrebuildTransactionResult ,
13+ StakingTransaction ,
14+ StakingWallet ,
15+ Wallet ,
16+ WalletCoinSpecific ,
17+ WalletData ,
18+ } from '@bitgo/sdk-core' ;
719import { TestBitGo } from '@bitgo/sdk-test' ;
820import { BitGo } from '../../../../src' ;
921import * as sinon from 'sinon' ;
@@ -14,13 +26,16 @@ describe('non-TSS Staking Wallet', function () {
1426 let ethBaseCoin ;
1527 let maticBaseCoin ;
1628 let btcBaseCoin ;
29+ let topethWctBaseCoin ;
1730 let enterprise ;
1831 let ethWalletData : any ;
1932 let btcWalletData : any ;
33+ let topethWctStakingWalletData : WalletData ;
2034 let btcDescriptorWalletData : any ;
2135 let ethStakingWallet : StakingWallet ;
2236 let maticStakingWallet : StakingWallet ;
2337 let btcStakingWallet : StakingWallet ;
38+ let topethWctStakingWallet : StakingWallet ;
2439
2540 before ( function ( ) {
2641 bitgo = TestBitGo . decorate ( BitGo , { env : 'mock' , microservicesUri } as any ) ;
@@ -31,6 +46,7 @@ describe('non-TSS Staking Wallet', function () {
3146 maticBaseCoin . keychains ( ) ;
3247 btcBaseCoin = bitgo . coin ( 'btc' ) ;
3348 btcBaseCoin . keychains ( ) ;
49+ topethWctBaseCoin = bitgo . coin ( 'topeth:wct' ) ;
3450
3551 enterprise = new Enterprise ( bitgo , ethBaseCoin , {
3652 id : '5cf940949449412d00f53b3d92dbcaa3' ,
@@ -63,9 +79,30 @@ describe('non-TSS Staking Wallet', function () {
6379 keys : [ '5b3424f91bf349930e340175' ] ,
6480 coinSpecific : { } ,
6581 } ;
82+
83+ topethWctStakingWalletData = {
84+ approvalsRequired : 0 ,
85+ balance : 0 ,
86+ balanceString : '' ,
87+ coinSpecific : { } as WalletCoinSpecific ,
88+ confirmedBalance : 0 ,
89+ confirmedBalanceString : '' ,
90+ keys : [ ] ,
91+ label : '' ,
92+ multisigType : 'onchain' ,
93+ pendingApprovals : [ ] ,
94+ spendableBalance : 0 ,
95+ spendableBalanceString : '' ,
96+ id : 'topethWctStakingWalletId' ,
97+ coin : 'topeth:wct' ,
98+ enterprise : enterprise . id ,
99+ } ;
100+
66101 const ethWallet = new Wallet ( bitgo , ethBaseCoin , ethWalletData ) ;
67102 const maticWallet = new Wallet ( bitgo , maticBaseCoin , maticWalletData ) ;
68103 const btcWallet = new Wallet ( bitgo , btcBaseCoin , btcWalletData ) ;
104+ topethWctStakingWallet = new Wallet ( bitgo , topethWctBaseCoin , topethWctStakingWalletData ) . toStakingWallet ( ) ;
105+
69106 ethStakingWallet = ethWallet . toStakingWallet ( ) ;
70107 maticStakingWallet = maticWallet . toStakingWallet ( ) ;
71108 btcStakingWallet = btcWallet . toStakingWallet ( ) ;
@@ -132,12 +169,16 @@ describe('non-TSS Staking Wallet', function () {
132169 )
133170 . reply ( 200 , transaction ) ;
134171
172+ // skipping validation because mock data is not a valid transaction
173+ sinon . stub ( StakingWallet . prototype , < any > 'validateBuiltStakingTransaction' ) . resolves ( ) ;
174+
135175 const stakingTransaction = await ethStakingWallet . buildSignAndSend (
136176 { walletPassphrase : walletPassphrase } ,
137177 transaction
138178 ) ;
139179
140180 stakingTransaction . should . deepEqual ( transaction ) ;
181+ sinon . restore ( ) ;
141182 } ) ;
142183
143184 it ( 'should throw error when buildParams are not expanded' , async function ( ) {
@@ -221,12 +262,15 @@ describe('non-TSS Staking Wallet', function () {
221262 )
222263 . reply ( 200 , transaction ) ;
223264
265+ // skipping validation because mock data is not a valid transaction
266+ sinon . stub ( StakingWallet . prototype , < any > 'validateBuiltStakingTransaction' ) . resolves ( ) ;
224267 const stakingTransaction = await maticStakingWallet . buildSignAndSend (
225268 { walletPassphrase : walletPassphrase } ,
226269 transaction
227270 ) ;
228271
229272 stakingTransaction . should . deepEqual ( transaction ) ;
273+ sinon . restore ( ) ;
230274 } ) ;
231275 } ) ;
232276
@@ -266,4 +310,65 @@ describe('non-TSS Staking Wallet', function () {
266310 prebuildTransaction . calledOnceWithExactly ( transaction . buildParams ) . should . be . true ;
267311 } ) ;
268312 } ) ;
313+
314+ describe ( 'Opeth:WCT Staking' , function ( ) {
315+ it ( 'should build and validate transaction' , async function ( ) {
316+ const unsignedTransaction : PrebuildTransactionResult = {
317+ walletId : topethWctStakingWallet . walletId ,
318+ ...opethFixtures . unsignedStakingTransaction ,
319+ } as PrebuildTransactionResult ;
320+ const stakingTransaction : StakingTransaction = opethFixtures . updatedStakingRequest ;
321+
322+ nock ( microservicesUri )
323+ . get (
324+ `/api/staking/v1/${ topethWctStakingWallet . coin } /wallets/${ topethWctStakingWallet . walletId } /requests/${ stakingTransaction . stakingRequestId } /transactions/${ stakingTransaction . id } `
325+ )
326+ . query ( { expandBuildParams : true } )
327+ . reply ( 200 , stakingTransaction ) ;
328+
329+ nock ( microservicesUri )
330+ . get ( `/api/v2/topeth/wallet/${ topethWctStakingWallet . walletId } ` )
331+ . reply ( 200 , topethWctStakingWalletData ) ;
332+
333+ nock ( microservicesUri )
334+ . post ( `/api/v2/topeth/wallet/${ topethWctStakingWallet . walletId } /tx/build` )
335+ . reply ( 200 , unsignedTransaction ) ;
336+
337+ // tx validation happens before signing, so we can skip it
338+ sinon . stub ( topethWctStakingWallet , 'sign' ) . resolves ( ) ;
339+
340+ await topethWctStakingWallet . buildAndSign ( { walletPassphrase : 'passphrase' } , stakingTransaction ) ;
341+ } ) ;
342+
343+ it ( 'should fail to validate transaction if unsigned transaction does not match the staking transaction' , async function ( ) {
344+ const unsignedTransaction : PrebuildTransactionResult = {
345+ walletId : topethWctStakingWallet . walletId ,
346+ ...opethFixtures . unsignedStakingTransaction ,
347+ txHex :
348+ '0x02f9019083aa37dc718206a882089e83030d40941d1a245741bd7d603747a23d30f4c91682a2992680b901643912521500000000000000000000000086bb6dca2cd6f9a0189c478bbb8f7ee2fef07c89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000067ebedc3000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000140d63efb5b24314f6f62dbadb383dba2e49d7ee0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0808080' ,
349+ } as PrebuildTransactionResult ;
350+ const stakingTransaction : StakingTransaction = opethFixtures . updatedStakingRequest ;
351+
352+ nock ( microservicesUri )
353+ . get (
354+ `/api/staking/v1/${ topethWctStakingWallet . coin } /wallets/${ topethWctStakingWallet . walletId } /requests/${ stakingTransaction . stakingRequestId } /transactions/${ stakingTransaction . id } `
355+ )
356+ . query ( { expandBuildParams : true } )
357+ . reply ( 200 , stakingTransaction ) ;
358+
359+ nock ( microservicesUri )
360+ . get ( `/api/v2/topeth/wallet/${ topethWctStakingWallet . walletId } ` )
361+ . reply ( 200 , topethWctStakingWalletData ) ;
362+
363+ nock ( microservicesUri )
364+ . post ( `/api/v2/topeth/wallet/${ topethWctStakingWallet . walletId } /tx/build` )
365+ . reply ( 200 , unsignedTransaction ) ;
366+
367+ await topethWctStakingWallet
368+ . buildAndSign ( { walletPassphrase : 'passphrase' } , stakingTransaction )
369+ . should . be . rejectedWith (
370+ 'Invalid recipient address: 0x86bb6dca2cd6f9a0189c478bbb8f7ee2fef07c89, Missing recipient address(es): 0x75bb6dca2cd6f9a0189c478bbb8f7ee2fef07c78'
371+ ) ;
372+ } ) ;
373+ } ) ;
269374} ) ;
0 commit comments