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
+34
View File
@@ -21,6 +21,40 @@ export const isValidMpin = (value: string) =>
export const isRepeatedDigits = (value: string) =>
value.length > 0 && /^(\d)\1*$/.test(value);
/**
* A straight run up or down — 1234, 6789, 4321. The backend refuses these
* when an MPIN is SET, in the same message-only way as repeated digits.
*/
export const isSequentialDigits = (value: string) => {
if (value.length < 2 || !/^[0-9]+$/.test(value)) {
return false;
}
const step = Number(value[1]) - Number(value[0]);
if (step !== 1 && step !== -1) {
return false;
}
for (let index = 1; index < value.length; index += 1) {
if (Number(value[index]) - Number(value[index - 1]) !== step) {
return false;
}
}
return true;
};
/**
* The stricter check for CHOOSING an MPIN — creation and reset.
*
* Deliberately separate from `isValidMpin`, which sign-in also uses: an MPIN
* like 1234 set before the backend began refusing runs still has to be
* enterable at sign-in, or its owner is locked out of their own profile.
*/
export const isAcceptableNewMpin = (value: string) =>
isValidMpin(value) && !isSequentialDigits(value);
/** Constraints as the API documents them, not as any one bank formats them. */
export const isValidAccountNumber = (value: string) => /^[0-9]{5,20}$/.test(value);