@@ -14,6 +14,7 @@ import { parseStandardTokenTransactionData } from '../../../Views/confirmations/
1414import { MUSD_TOKEN_ADDRESS_BY_CHAIN } from '../constants/musd' ;
1515import {
1616 createMusdConversionTransaction ,
17+ ensureMusdTokenRegistered ,
1718 replaceMusdConversionTransactionForPayToken ,
1819} from './musdConversionTransaction' ;
1920
@@ -54,6 +55,11 @@ jest.mock('../constants/musd', () => ({
5455 * Mutable mapping so tests can override per-case.
5556 */
5657 MUSD_TOKEN_ADDRESS_BY_CHAIN : { } ,
58+ MUSD_TOKEN : {
59+ symbol : 'mUSD' ,
60+ name : 'MetaMask USD' ,
61+ decimals : 6 ,
62+ } ,
5763} ) ) ;
5864
5965type MockedFindNetworkClientIdByChainId = ( chainId : Hex ) => string | undefined ;
@@ -91,6 +97,23 @@ interface MockedEngineContext {
9197 ApprovalController ?: {
9298 rejectRequest : jest . Mock < void , [ string , unknown ] > ;
9399 } ;
100+ TokensController ?: {
101+ state : {
102+ allTokens : Record < string , Record < string , { address : string } [ ] > > ;
103+ } ;
104+ addToken : jest . Mock <
105+ Promise < void > ,
106+ [
107+ {
108+ address : string ;
109+ decimals : number ;
110+ name : string ;
111+ symbol : string ;
112+ networkClientId : string ;
113+ } ,
114+ ]
115+ > ;
116+ } ;
94117}
95118
96119const mockedProviderErrors = providerErrors as jest . Mocked <
@@ -162,6 +185,19 @@ describe('musdConversionTransaction', () => {
162185
163186 const approvalControllerReject = jest . fn < void , [ string , unknown ] > ( ) ;
164187
188+ const tokensControllerAddToken = jest . fn <
189+ Promise < void > ,
190+ [
191+ {
192+ address : string ;
193+ decimals : number ;
194+ name : string ;
195+ symbol : string ;
196+ networkClientId : string ;
197+ } ,
198+ ]
199+ > ( ) ;
200+
165201 beforeEach ( ( ) => {
166202 jest . clearAllMocks ( ) ;
167203
@@ -182,6 +218,10 @@ describe('musdConversionTransaction', () => {
182218 ApprovalController : {
183219 rejectRequest : approvalControllerReject ,
184220 } ,
221+ TokensController : {
222+ state : { allTokens : { } } ,
223+ addToken : tokensControllerAddToken ,
224+ } ,
185225 } ;
186226
187227 ( MUSD_TOKEN_ADDRESS_BY_CHAIN as Record < string , Hex > ) [ '0x1' ] =
@@ -721,4 +761,117 @@ describe('musdConversionTransaction', () => {
721761 expect ( newTransactionId ) . toBeUndefined ( ) ;
722762 } ) ;
723763 } ) ;
764+
765+ describe ( 'ensureMusdTokenRegistered' , ( ) => {
766+ const MUSD_ADDRESS = '0xmusdAddress' as Hex ;
767+ const CHAIN_ID = '0x1' as Hex ;
768+ const NETWORK_CLIENT_ID = 'mainnet' ;
769+
770+ beforeEach ( ( ) => {
771+ ( MUSD_TOKEN_ADDRESS_BY_CHAIN as Record < string , Hex > ) [ CHAIN_ID ] =
772+ MUSD_ADDRESS ;
773+ } ) ;
774+
775+ describe ( 'when mUSD token address is not configured for the chain' , ( ) => {
776+ it ( 'returns early without calling addToken' , async ( ) => {
777+ const unknownChainId = '0xdead' as Hex ;
778+
779+ await ensureMusdTokenRegistered ( {
780+ chainId : unknownChainId ,
781+ networkClientId : NETWORK_CLIENT_ID ,
782+ } ) ;
783+
784+ expect ( tokensControllerAddToken ) . not . toHaveBeenCalled ( ) ;
785+ } ) ;
786+ } ) ;
787+
788+ describe ( 'when mUSD token is already registered for the chain' , ( ) => {
789+ it ( 'does not call addToken when the token exists for one account' , async ( ) => {
790+ mockedEngine . context . TokensController = {
791+ state : {
792+ allTokens : {
793+ [ CHAIN_ID ] : {
794+ '0xaccountAddress' : [ { address : MUSD_ADDRESS } ] ,
795+ } ,
796+ } ,
797+ } ,
798+ addToken : tokensControllerAddToken ,
799+ } ;
800+
801+ await ensureMusdTokenRegistered ( {
802+ chainId : CHAIN_ID ,
803+ networkClientId : NETWORK_CLIENT_ID ,
804+ } ) ;
805+
806+ expect ( tokensControllerAddToken ) . not . toHaveBeenCalled ( ) ;
807+ } ) ;
808+ } ) ;
809+
810+ describe ( 'when mUSD token is not yet registered' , ( ) => {
811+ it ( 'calls addToken with the correct token metadata and networkClientId' , async ( ) => {
812+ mockedEngine . context . TokensController = {
813+ state : { allTokens : { } } ,
814+ addToken : tokensControllerAddToken ,
815+ } ;
816+ tokensControllerAddToken . mockResolvedValue ( undefined ) ;
817+
818+ await ensureMusdTokenRegistered ( {
819+ chainId : CHAIN_ID ,
820+ networkClientId : NETWORK_CLIENT_ID ,
821+ } ) ;
822+
823+ expect ( tokensControllerAddToken ) . toHaveBeenCalledTimes ( 1 ) ;
824+ expect ( tokensControllerAddToken ) . toHaveBeenCalledWith ( {
825+ address : MUSD_ADDRESS ,
826+ decimals : 6 ,
827+ name : 'MetaMask USD' ,
828+ symbol : 'mUSD' ,
829+ networkClientId : NETWORK_CLIENT_ID ,
830+ } ) ;
831+ } ) ;
832+
833+ it ( 'calls addToken when the chain entry exists but no accounts hold mUSD' , async ( ) => {
834+ mockedEngine . context . TokensController = {
835+ state : {
836+ allTokens : {
837+ [ CHAIN_ID ] : {
838+ '0xaccountAddress' : [ { address : '0xdifferentTokenAddress' } ] ,
839+ } ,
840+ } ,
841+ } ,
842+ addToken : tokensControllerAddToken ,
843+ } ;
844+ tokensControllerAddToken . mockResolvedValue ( undefined ) ;
845+
846+ await ensureMusdTokenRegistered ( {
847+ chainId : CHAIN_ID ,
848+ networkClientId : NETWORK_CLIENT_ID ,
849+ } ) ;
850+
851+ expect ( tokensControllerAddToken ) . toHaveBeenCalledTimes ( 1 ) ;
852+ expect ( tokensControllerAddToken ) . toHaveBeenCalledWith ( {
853+ address : MUSD_ADDRESS ,
854+ decimals : 6 ,
855+ name : 'MetaMask USD' ,
856+ symbol : 'mUSD' ,
857+ networkClientId : NETWORK_CLIENT_ID ,
858+ } ) ;
859+ } ) ;
860+
861+ it ( 'calls addToken when allTokens has no entry for the chain' , async ( ) => {
862+ mockedEngine . context . TokensController = {
863+ state : { allTokens : { '0xe708' : { } } } ,
864+ addToken : tokensControllerAddToken ,
865+ } ;
866+ tokensControllerAddToken . mockResolvedValue ( undefined ) ;
867+
868+ await ensureMusdTokenRegistered ( {
869+ chainId : CHAIN_ID ,
870+ networkClientId : NETWORK_CLIENT_ID ,
871+ } ) ;
872+
873+ expect ( tokensControllerAddToken ) . toHaveBeenCalledTimes ( 1 ) ;
874+ } ) ;
875+ } ) ;
876+ } ) ;
724877} ) ;
0 commit comments