Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ describe('RealUnitService', () => {
expect(status.userData!.kycData.lastName).toBe('Mustermann');
});

it('returns state=KYC_REQUIRED when no step exists and no KYC data is present', () => {
it('returns state=NEW_REGISTRATION with no userData when no step exists and no KYC data is present (first-time user gets an empty form)', () => {
const userData = {
firstname: null,
surname: null,
Expand All @@ -586,7 +586,7 @@ describe('RealUnitService', () => {

const status = service.getRegistrationInfo(userData, walletAddress);

expect(status.state).toBe(RealUnitRegistrationState.KYC_REQUIRED);
expect(status.state).toBe(RealUnitRegistrationState.NEW_REGISTRATION);
expect(status.isRegistered).toBe(false);
expect(status.userData).toBeUndefined();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ export class RealUnitController {
@ApiOperation({
summary: 'Get RealUnit registration info for the connected wallet',
description:
'Returns the action the client should take to RealUnit-register the connected wallet (`state`), the registration data to pre-fill or display (`userData`), and a legacy `isRegistered` flag. Drives the registration UX: client routes on `state` (AlreadyRegistered / AddWallet / NewRegistration / KycRequired) without inferring it locally.',
'Returns the action the client should take to RealUnit-register the connected wallet (`state`), the registration data to pre-fill or display (`userData`), and a legacy `isRegistered` flag. Drives the registration UX: client routes on `state` (AlreadyRegistered / AddWallet / NewRegistration) without inferring it locally.',
})
@ApiOkResponse({ type: RealUnitRegistrationInfoDto })
async getRegistrationInfo(@GetJwt() jwt: JwtPayload): Promise<RealUnitRegistrationInfoDto> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,6 @@ export enum RealUnitRegistrationState {
ALREADY_REGISTERED = 'AlreadyRegistered',
ADD_WALLET = 'AddWallet',
NEW_REGISTRATION = 'NewRegistration',
KYC_REQUIRED = 'KycRequired',
}

export class RealUnitRegistrationInfoDto {
Expand All @@ -254,7 +253,7 @@ export class RealUnitRegistrationInfoDto {
@ApiProperty({
enum: RealUnitRegistrationState,
description:
'Action the client should take for this wallet. `AlreadyRegistered`: no UX needed. `AddWallet`: render a one-tap Add-Wallet flow that submits to POST /register/wallet using the prior signed payload (`userData` is set). `NewRegistration`: render the full registration form pre-filled with `userData`. `KycRequired`: user must complete DFX KYC first (`userData` not set; edge case).',
'Action the client should take for this wallet. `AlreadyRegistered`: no UX needed. `AddWallet`: render a one-tap Add-Wallet flow that submits to POST /register/wallet using the prior signed payload (`userData` is set). `NewRegistration`: render the full registration form pre-filled with `userData` when present, otherwise empty for the client to collect every field manually.',
})
state: RealUnitRegistrationState;

Expand Down
26 changes: 10 additions & 16 deletions src/subdomains/supporting/realunit/realunit.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -670,11 +670,10 @@ export class RealUnitService {
getRegistrationInfo(userData: UserData, walletAddress: string): RealUnitRegistrationInfoDto {
const { step, isForCurrentWallet } = this.findRegistrationStep(userData, walletAddress);

// Dispatch to one of four states so the client can route to the right UX without inferring
// Dispatch to one of three states so the client can route to the right UX without inferring
// it locally. Order matters: a registration step for the current wallet (ALREADY_REGISTERED)
// wins over any other signal; a step for a different wallet drives the one-tap Add-Wallet
// flow (ADD_WALLET); otherwise we pre-fill the full form from existing KYC data when
// available (NEW_REGISTRATION), falling back to KYC_REQUIRED when no usable data exists.
// flow (ADD_WALLET); otherwise this wallet still needs a fresh registration (NEW_REGISTRATION).
if (step) {
const stepUserData = this.toUserDataDto(step);
const state = isForCurrentWallet
Expand All @@ -687,21 +686,16 @@ export class RealUnitService {
};
}

// No step exists. Pre-fill from DFX KYC data (firstname/surname guarded by
// toUserDataDtoFromUserData) and fall through to KYC_REQUIRED when that returns undefined.
const prefill = this.toUserDataDtoFromUserData(userData);
if (prefill) {
return {
isRegistered: false,
state: RealUnitRegistrationState.NEW_REGISTRATION,
userData: prefill,
};
}

// No step exists: this wallet needs a fresh RealUnit registration. Pre-fill the form from
// existing DFX KYC data when we have verified personal data (firstname/surname present);
// otherwise return NEW_REGISTRATION without `userData` so the client renders an empty form and
// collects every field manually. `completeRegistration` accepts and persists manually-entered
// data for first-time users — email registration (KYC Level 10) is the only prerequisite — so
// this branch must not dead-end onboarding by withholding the registration step.
return {
isRegistered: false,
state: RealUnitRegistrationState.KYC_REQUIRED,
userData: undefined,
state: RealUnitRegistrationState.NEW_REGISTRATION,
userData: this.toUserDataDtoFromUserData(userData),
};
}

Expand Down