@@ -3225,6 +3225,60 @@ describe('RewardsController', () => {
3225
3225
) ;
3226
3226
} ) ;
3227
3227
3228
+ it ( 'should handle InvalidTimestampError and retry with server timestamp' , async ( ) => {
3229
+ // Arrange
3230
+ const mockSubscriptionId = 'test-subscription-id' ;
3231
+ const mockOptinResponse = {
3232
+ subscription : { id : mockSubscriptionId } ,
3233
+ sessionId : 'test-session-id' ,
3234
+ } ;
3235
+
3236
+ // Import the actual InvalidTimestampError
3237
+ const { InvalidTimestampError } = jest . requireActual (
3238
+ './services/rewards-data-service' ,
3239
+ ) ;
3240
+ const mockError = new InvalidTimestampError ( 'Invalid timestamp' , 12345 ) ;
3241
+
3242
+ // Mock the messaging system calls
3243
+ let callCount = 0 ;
3244
+
3245
+ mockMessenger . call . mockImplementation ( ( method , ..._args ) : any => {
3246
+ if ( method === 'RewardsDataService:mobileOptin' ) {
3247
+ callCount ++ ;
3248
+ const { account, signature, timestamp } = _args [ 0 ] as any ;
3249
+
3250
+ // First call fails with timestamp error, second call succeeds
3251
+ if ( callCount === 1 ) {
3252
+ expect ( account ) . toBe ( mockEvmInternalAccount . address ) ;
3253
+ expect ( signature ) . toBeDefined ( ) ;
3254
+ expect ( timestamp ) . toBeDefined ( ) ;
3255
+ return Promise . reject ( mockError ) ;
3256
+ }
3257
+ // Verify the second call uses the server timestamp
3258
+ expect ( account ) . toBe ( mockEvmInternalAccount . address ) ;
3259
+ expect ( signature ) . toBeDefined ( ) ;
3260
+ expect ( timestamp ) . toBe ( 12345 ) ;
3261
+ return Promise . resolve ( mockOptinResponse ) ;
3262
+ } else if ( method === 'KeyringController:signPersonalMessage' ) {
3263
+ return Promise . resolve ( '0xsignature' ) ;
3264
+ }
3265
+ return Promise . resolve ( ) ;
3266
+ } ) ;
3267
+
3268
+ // Act
3269
+ const result = await controller . optIn ( mockEvmInternalAccount ) ;
3270
+
3271
+ // Assert
3272
+ expect ( result ) . toBe ( mockSubscriptionId ) ;
3273
+ expect ( mockMessenger . call ) . toHaveBeenCalledWith (
3274
+ 'KeyringController:signPersonalMessage' ,
3275
+ expect . objectContaining ( {
3276
+ from : mockEvmInternalAccount . address ,
3277
+ } ) ,
3278
+ ) ;
3279
+ expect ( callCount ) . toBe ( 2 ) ; // Verify retry happened
3280
+ } ) ;
3281
+
3228
3282
it ( 'should store subscription token when optin response has subscription id and session id' , async ( ) => {
3229
3283
// Arrange
3230
3284
const mockOptinResponse = {
0 commit comments