Add TPIN creation, TPIN-authorised transfers, MPIN reset and transfer history

- Create TPIN: current MPIN -> OTP -> encrypted TPIN via /tpin/create/*,
  from Services and from the transfer screen on TPIN_NOT_SET
- IMPS initiate now sends encryptedTpin instead of encryptedMpin; handles
  INVALID_TPIN and TPIN_NOT_SET
- Share one RSA-OAEP encryption and key-retry path for MPIN and TPIN
- Forgot MPIN on sign-in and Reset MPIN in the Security Center
- Fund transfer history list and detail, reachable from Home
- Brand logo on sign-in and palette updates

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Abin Toppo
2026-09-29 17:54:43 +05:30
co-authored by Claude Opus 5.5
parent abb14d5768
commit f1def81eb7
50 changed files with 3039 additions and 385 deletions
+32
View File
@@ -1,5 +1,7 @@
import {
MPIN_LENGTH,
isAcceptableNewMpin,
isSequentialDigits,
isRepeatedDigits,
isValidAccountNumber,
isValidIfsc,
@@ -94,3 +96,33 @@ describe('payee routing fields', () => {
expect(isValidMmid('10727301')).toBe(false);
});
});
describe('isSequentialDigits', () => {
it('flags straight runs up and down', () => {
expect(isSequentialDigits('1234')).toBe(true);
expect(isSequentialDigits('6789')).toBe(true);
expect(isSequentialDigits('4321')).toBe(true);
expect(isSequentialDigits('987654')).toBe(true);
});
it('passes anything that is not one steady step', () => {
expect(isSequentialDigits('1243')).toBe(false);
expect(isSequentialDigits('1357')).toBe(false);
expect(isSequentialDigits('1111')).toBe(false);
expect(isSequentialDigits('9012')).toBe(false);
expect(isSequentialDigits('')).toBe(false);
});
});
describe('isAcceptableNewMpin', () => {
it('refuses runs and repeats when choosing an MPIN', () => {
expect(isAcceptableNewMpin('1234')).toBe(false);
expect(isAcceptableNewMpin('4321')).toBe(false);
expect(isAcceptableNewMpin('1111')).toBe(false);
expect(isAcceptableNewMpin('4271')).toBe(true);
});
it('leaves sign-in able to enter an old sequential MPIN', () => {
expect(isValidMpin('1234')).toBe(true);
});
});