From a21cf221bf64e78b267b4e4a34606d3db49ef3e0 Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Tue, 9 Jun 2026 12:39:54 +0200 Subject: [PATCH 1/2] fix(aml): set priceDefinitionAllowedDate when amlCheck is manually passed (#3845) When compliance staff set amlCheck to Pass via the generic update endpoint (PUT /buyCrypto/:id, PUT /buyFiat/:id), priceDefinitionAllowedDate was only persisted if it was explicitly included in the payload. Unlike the automatic AML pass (AmlHelperService) and manualPassAmlCheck, the update path did not couple the date to the Pass transition, leaving transactions stuck in status Created with amlCheck=Pass and a null priceDefinitionAllowedDate. Couple priceDefinitionAllowedDate to the Pass transition in both BuyCryptoService.update and BuyFiatService.update, mirroring the automatic pass behaviour. An explicit payload value still takes precedence. --- .../process/services/buy-crypto.service.ts | 13 ++++++++++++- .../process/services/buy-fiat.service.ts | 12 +++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/subdomains/core/buy-crypto/process/services/buy-crypto.service.ts b/src/subdomains/core/buy-crypto/process/services/buy-crypto.service.ts index f3d499bb3f..78fcdf71df 100644 --- a/src/subdomains/core/buy-crypto/process/services/buy-crypto.service.ts +++ b/src/subdomains/core/buy-crypto/process/services/buy-crypto.service.ts @@ -342,7 +342,18 @@ export class BuyCryptoService implements OnModuleInit { (entity.amlCheck === CheckStatus.FAIL && dto.amlCheck === CheckStatus.GSHEET)) && !entity.isComplete && (update?.amlCheck !== entity.amlCheck || update.amlReason !== entity.amlReason) - ? { amlCheck: update.amlCheck, mailSendDate: null, amlReason: update.amlReason, comment: update.comment } + ? { + amlCheck: update.amlCheck, + mailSendDate: null, + amlReason: update.amlReason, + comment: update.comment, + ...(update.amlCheck === CheckStatus.PASS + ? { + priceDefinitionAllowedDate: + update.priceDefinitionAllowedDate ?? entity.priceDefinitionAllowedDate ?? new Date(), + } + : undefined), + } : undefined), isComplete: dto.isComplete, }; diff --git a/src/subdomains/core/sell-crypto/process/services/buy-fiat.service.ts b/src/subdomains/core/sell-crypto/process/services/buy-fiat.service.ts index 1e15117823..a710a87dde 100644 --- a/src/subdomains/core/sell-crypto/process/services/buy-fiat.service.ts +++ b/src/subdomains/core/sell-crypto/process/services/buy-fiat.service.ts @@ -208,7 +208,17 @@ export class BuyFiatService implements OnModuleInit { (entity.amlCheck === CheckStatus.FAIL && dto.amlCheck === CheckStatus.GSHEET)) && !entity.isComplete && (update?.amlCheck !== entity.amlCheck || update.amlReason !== entity.amlReason) - ? { amlCheck: update.amlCheck, mailSendDate: null, amlReason: update.amlReason } + ? { + amlCheck: update.amlCheck, + mailSendDate: null, + amlReason: update.amlReason, + ...(update.amlCheck === CheckStatus.PASS + ? { + priceDefinitionAllowedDate: + update.priceDefinitionAllowedDate ?? entity.priceDefinitionAllowedDate ?? new Date(), + } + : undefined), + } : undefined), isComplete: dto.isComplete, comment: update.comment, From 5e36ac4dec55fb67b47547ce70a2cf5164fc6f60 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 9 Jun 2026 13:01:46 +0200 Subject: [PATCH 2/2] fix(auth): brand login mail by login source instead of account history (#3846) * fix(auth): brand login mail by login source instead of account history resolveMailWallet forced any account ever linked to a preferred wallet (RealUnit) onto RealUnit branding, so logins via app.dfx.swiss received RealUnit confirmation mails. signInByMail now resolves the originating login wallet once and passes it explicitly, so branding follows the login source (DFX vs. RealUnit). * fix(auth): always resolve a concrete login wallet for mail branding guarantees branding follows the login source even when an unknown wallet name is passed, so it never falls back to the account-history override --- .../generic/user/models/auth/auth.service.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/subdomains/generic/user/models/auth/auth.service.ts b/src/subdomains/generic/user/models/auth/auth.service.ts index dbf1f0734e..69189c7154 100644 --- a/src/subdomains/generic/user/models/auth/auth.service.ts +++ b/src/subdomains/generic/user/models/auth/auth.service.ts @@ -259,6 +259,12 @@ export class AuthService { const ipCountry = this.geoLocationService.getCountry(userIp); const language = await this.languageService.getLanguageByCountry(ipCountry); + // wallet the login originated from - determines mail branding (e.g. DFX vs. RealUnit); + // always resolve to a concrete wallet so branding follows the login source and never falls back to account history + const loginWallet = + (dto.wallet && (await this.walletService.getByIdOrName(undefined, dto.wallet))) || + (await this.walletService.getDefault()); + const userData = (await this.userDataService .getUsersByMail(dto.mail) @@ -268,9 +274,7 @@ export class AuthService { mail: dto.mail, language: dto.language ?? language, status: UserDataStatus.KYC_ONLY, - wallet: dto.wallet - ? await this.walletService.getByIdOrName(undefined, dto.wallet) - : await this.walletService.getDefault(), + wallet: loginWallet, })); if (dto.recommendationCode) await this.confirmRecommendationCode(dto.recommendationCode, userData); @@ -301,6 +305,7 @@ export class AuthService { context: MailContext.LOGIN, input: { userData, + wallet: loginWallet, title: `${MailTranslationKey.LOGIN}.title`, salutation: { key: `${MailTranslationKey.LOGIN}.salutation` }, texts: [