@@ -9,9 +9,10 @@ import nock = require('nock');
99import should = require( 'should' ) ;
1010import * as sinon from 'sinon' ;
1111
12- import { common , decodeOrElse , ECDSAUtils , EDDSAUtils , Keychains , OvcShare } from '@bitgo/sdk-core' ;
12+ import { common , decodeOrElse , ECDSAUtils , EDDSAUtils , Keychain , Keychains , OvcShare } from '@bitgo/sdk-core' ;
1313import { TestBitGo } from '@bitgo/sdk-test' ;
1414import { BitGo } from '../../../src/bitgo' ;
15+ import { SinonStub } from 'sinon' ;
1516
1617describe ( 'V2 Keychains' , function ( ) {
1718 let bitgo ;
@@ -173,9 +174,7 @@ describe('V2 Keychains', function () {
173174 'expected new password to be a string'
174175 ) ;
175176
176- ( ( ) => keychains . updateSingleKeychainPassword ( { oldPassword : '1234' , newPassword : 5678 } ) ) . should . throw (
177- 'expected new password to be a string'
178- ) ;
177+ ( ( ) => keychains . updateSingleKeychainPassword ( { oldPassword : '1234' , newPassword : 5678 } ) ) . should . throw ( ) ;
179178
180179 ( ( ) => keychains . updateSingleKeychainPassword ( { oldPassword : '1234' , newPassword : '5678' } ) ) . should . throw (
181180 'expected keychain to be an object with an encryptedPrv property'
@@ -829,4 +828,92 @@ describe('V2 Keychains', function () {
829828 const decryptedPrv = bitgo . decrypt ( { input : backup . encryptedPrv , password : 't3stSicretly!' } ) ;
830829 decryptedPrv . should . startWith ( 'xprv' ) ;
831830 } ) ;
831+
832+ describe ( 'Rotate OFC multi-user-key keychains' , function ( ) {
833+ let ofcBaseCoin ;
834+ let ofcKeychains ;
835+ const mockOfcKeychain : Keychain = {
836+ id : 'ofcKeychainId' ,
837+ pub : 'ofcKeychainPub' ,
838+ encryptedPrv : 'ofcEncryptedPrv' ,
839+ source : 'user' ,
840+ coinSpecific : {
841+ ofc : {
842+ features : [ 'multi-user-key' ] ,
843+ } ,
844+ } ,
845+ type : 'tss' ,
846+ } ;
847+ let nonOfcBaseCoin ;
848+ let nonOfcKeychains ;
849+ const mockNonOfcKeychain : Keychain = {
850+ id : 'nonOfcKeychainId' ,
851+ pub : 'nonOfcKeychainPub' ,
852+ source : 'user' ,
853+ type : 'tss' ,
854+ } ;
855+
856+ const mockNewKeypair = {
857+ pub : 'newPub' ,
858+ prv : 'newPrv' ,
859+ } ;
860+
861+ let sandbox ;
862+ let updateKeychainStub : SinonStub ;
863+ let createKeypairStub : SinonStub ;
864+ let encryptionStub : SinonStub ;
865+
866+ beforeEach ( function ( ) {
867+ ofcBaseCoin = bitgo . coin ( 'ofc' ) ;
868+ ofcKeychains = ofcBaseCoin . keychains ( ) ;
869+
870+ nonOfcBaseCoin = bitgo . coin ( 'hteth' ) ;
871+ nonOfcKeychains = nonOfcBaseCoin . keychains ( ) ;
872+
873+ sandbox = sinon . createSandbox ( ) ;
874+ updateKeychainStub = sandbox . stub ( ) . returns ( { result : sandbox . stub ( ) . resolves ( ) } ) ;
875+ sandbox . stub ( BitGo . prototype , 'put' ) . returns ( { send : updateKeychainStub } ) ;
876+ createKeypairStub = sandbox . stub ( ofcKeychains , 'create' ) . returns ( mockNewKeypair ) ;
877+ encryptionStub = sandbox . stub ( BitGo . prototype , 'encrypt' ) . returns ( 'newEncryptedPrv' ) ;
878+ } ) ;
879+
880+ afterEach ( function ( ) {
881+ sandbox . restore ( ) ;
882+ } ) ;
883+
884+ it ( 'should rotate ofc multi-user-key properly' , async function ( ) {
885+ nock ( bgUrl ) . get ( `/api/v2/ofc/key/${ mockOfcKeychain . id } ` ) . query ( true ) . reply ( 200 , mockOfcKeychain ) ;
886+
887+ await ofcKeychains . rotateKeychain ( { id : mockOfcKeychain . id , password : '1234' } ) ;
888+ sinon . assert . called ( createKeypairStub ) ;
889+ sinon . assert . calledWith ( encryptionStub , { input : mockNewKeypair . prv , password : '1234' } ) ;
890+ sinon . assert . calledWith ( updateKeychainStub , {
891+ pub : mockNewKeypair . pub ,
892+ encryptedPrv : 'newEncryptedPrv' ,
893+ reqId : undefined ,
894+ } ) ;
895+ } ) ;
896+
897+ it ( 'should allow user to supply pub and encryptedPrv directly' , async function ( ) {
898+ nock ( bgUrl ) . get ( `/api/v2/ofc/key/${ mockOfcKeychain . id } ` ) . query ( true ) . reply ( 200 , mockOfcKeychain ) ;
899+
900+ await ofcKeychains . rotateKeychain ( { id : mockOfcKeychain . id , pub : 'pub' , encryptedPrv : 'encryptedPrv' } ) ;
901+ sinon . assert . notCalled ( createKeypairStub ) ;
902+ sinon . assert . notCalled ( encryptionStub ) ;
903+ sinon . assert . calledWith ( updateKeychainStub , {
904+ pub : 'pub' ,
905+ encryptedPrv : 'encryptedPrv' ,
906+ reqId : undefined ,
907+ } ) ;
908+ } ) ;
909+
910+ it ( 'should throw when trying to rotate non-ofc keychain' , async function ( ) {
911+ nock ( bgUrl ) . get ( `/api/v2/hteth/key/${ mockNonOfcKeychain . id } ` ) . query ( true ) . reply ( 200 , mockNonOfcKeychain ) ;
912+
913+ await assert . rejects (
914+ async ( ) => await nonOfcKeychains . rotateKeychain ( { id : mockNonOfcKeychain . id , password : '1234' } ) ,
915+ ( err : Error ) => err . message === 'rotateKeychain is only permitted for ofc multi-user-key wallet'
916+ ) ;
917+ } ) ;
918+ } ) ;
832919} ) ;
0 commit comments