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