Skip to content

Release: develop -> main#3646

Merged
TaprootFreak merged 6 commits intomainfrom
develop
Apr 30, 2026
Merged

Release: develop -> main#3646
TaprootFreak merged 6 commits intomainfrom
develop

Conversation

@github-actions
Copy link
Copy Markdown

Automatic Release PR

This PR was automatically created after changes were pushed to develop.

Commits: 1 new commit(s)

Checklist

  • Review all changes
  • Verify CI passes
  • Approve and merge when ready for production

* chore: remove limit of faucet for dev env.

* feat: add endpoints for sell unsigned transactions and broadcasting.

* feat: reset faucet for account after realunit sell.

* fix: doc for dto.

* test: add modules.

* chore: replace envelope with unsignedTx, r, s, v.

* feat: add faucetRequest reset status.

* chore: formatting.

* chore: missing in.
TaprootFreak
TaprootFreak previously approved these changes Apr 29, 2026
* fix: remove user country

* fix: format
Yannick1712 and others added 4 commits April 30, 2026 09:26
* [NOTASK] kyc duplicate account check

* [NOTASK] fix build
* feat: improved IP detection

* fix: linter

* fix: added type
* Add custom RealUnit mail template

Replace the generic user-v2 template with a dedicated RealUnit-branded
template featuring light background, RealUnit logo, blue accent color,
formal language, RealUnit social links, and legal footer.

* Add wallet-specific translation system with RealUnit German texts

Introduce wallet-aware translations in MailFactory with automatic
fallback: tries mail-{wallet}.json namespace first, falls back to
default mail.json. Includes complete German translations for RealUnit
with formal language, custom subjects, and RealUnit-specific content.
Suppresses DFX_TEAM_CLOSING for wallets with custom templates.

* Align RealUnit mails with official Textvorlagen document

- Add wallet body text injection: factory auto-derives .body key from
  title key and prepends it to texts array if wallet translation exists
- Filter empty text blocks from rendered mail affix array
- Add body texts for crypto_output, fiat_output, processing, chargeback
- Set general.support/thanks/link/transaction_button to empty (template
  handles closing) to avoid duplicate content
- Fix template closing: "Freundliche Grüsse / RealUnit Schweiz AG"
- Fix template support: info@realunit.ch + DFX tech support link
- Update merge_incomplete text per Textvorlagen (#9)

* Remove unused security hint block from RealUnit template

* Remove DFX support link from RealUnit template

RealUnit customers must never receive links to DFX pages. All links
must be deeplinks to the RealUnit App. Until app deeplinks for support
are implemented, route all inquiries through info@realunit.ch.

* Fix translation texts to match Textvorlagen document exactly

- #3: Add "von CHF 1'000.-" to monthly limit text
- #4: Add "von CHF 100'000.-" to annual limit text
- #7: Add "bei DFX AG" to video ident line2
- #12: Add body key for chargeback.crypto with doc text
- #17: Add missing first sentence to fiat_output.body

* Complete all RealUnit translations to prevent du/Sie mixing

Add all missing translation keys that would fall back to informal DFX
texts. Follows the Textvorlagen author's principles throughout:
- RealUnit is the brand, DFX only mentioned where regulatory required
- Product-specific language (RealUnit-Token, RealUnit-Aktientoken)
- RealUnit App as the central touchpoint
- Formal Sie throughout, no informal du anywhere

New keys added:
- All chargeback reasons (30+ keys) in formal language
- All pending phone/olky/bank_tx variants with RealUnit context
- Referral/Recommendation adapted to RealUnit App
- KYC success: mentions RealUnit-Token trading capability
- KYC reminder/missing_data: references RealUnit App
- Account deactivation: explains token remain in wallet
- Support message: references RealUnit App instead of URL
- Fiat input titles: "Kauf RealUnit-Token" prefix
- currency_exchange, kyc_start, payment_link in formal language

Only intentionally missing: dfx_team_closing (suppressed by factory),
black_squad (DFX-exclusive, not applicable to RealUnit).

* Remove non-applicable RealUnit translations

Remove payment_data (Zession) and phone check pending variants - these
features are not used in the RealUnit App context.

* Add RealUnit email preview generator script

Add scripts/generate-realunit-previews.js alongside the existing DFX
preview generator. Uses wallet-aware translations with fallback, same
as production. Output goes to scripts/email-previews/realunit/ (gitignored).

Usage: node scripts/generate-realunit-previews.js

* Drop info@realunit.ch, add app-open button and automated-mail disclaimer

- Remove hardcoded support contact block from realunit.hbs (in-app support only per RealUnit AG)
- Update verification_code closing to reference in-app support
- Add "App öffnen" button linking to https://app.realunit.ch/open in every mail
- Add automated-mail disclaimer above the legal footer

* Add per-mail trigger explanation to RealUnit preview script

- Add 38 customer-facing trigger explanations (when the mail fires) plus the technical MailContext and DB/state condition that fires it
- Render a yellow info box above each mail in the standalone HTML; hide it inside iframes (via window.parent check) so index card previews show only the mail
- Add the customer-facing "when" text as a third line on each index card

* Reorder preview index: incoming first, then completion, sell, etc.

* Drop DFX mentions from RealUnit trigger explanations and remove crypto-to-crypto wording (not applicable for RealUnit)

* Add personal welcome greeting as first body line in confirmation, status, KYC, login, verification, ref-reward and support mails

* Mention dual CHF/EUR bank account availability in RealUnit currency-exchange notice

* Render salutation small bold below welcome line and replace unassigned-tx button with body text

- mail.factory: keep the welcome line first when prepending wallet-specific body overrides (welcome → body → rest)
- realunit.hbs: drop the large standalone salutation block; render salutation small/bold inline right after the welcome text
- mail-realunit.json: add body text for fiat_input.unassigned, clear transaction_button so the dedicated 'Klick hier' button is dropped

* Refine RealUnit preview script

- Reorganize categories: drop 'Eingang', map fiat-input/currency-exchange/unassigned-tx to Kauf and crypto-input to Verkauf
- Hide trigger details behind a clickable ? icon (collapsed by default; auto-hidden inside index iframes)
- Add 'Betreff' section to the trigger info box
- Rewrite all 38 trigger 'when' texts in technical, non-personal voice (no Sie/Ihr/Ihnen)
- Wipe output dir before regenerating to avoid stale files when ordering changes

* Drop redundant 'Wenn möglich, senden Sie direkt EUR' line from RealUnit currency-exchange notice

* Add 'next step + customer will be informed' body texts to RealUnit mails

- payment.fiat_input.body: confirmation that the bank transfer is being processed and the customer will be informed once tokens are in the wallet
- payment.crypto_input.body: confirmation that the tokens have arrived in the sell flow and the customer will be informed once the bank payout is done. Also fix mismatched title and salutation (was 'Kauf...', now 'Verkauf RealUnit-Token – Eingang erhalten')
- payment.chargeback.unconfirmed.body: hint that the refund is processed and customer informed once the action is taken
- payment.pending.bank_release_pending.line3: hint that the buy is processed and customer informed once the bank releases the transaction
- preview script: render the new body texts in the corresponding previews

* Skip RealUnit opt-out mails (KYC pending, chargeback, limit-request)

For RealUnit-wallet customers DFX handles these cases by phone instead of email:
- pending mails for amlReason in [monthly_limit, annual_limit, annual_limit_without_kyc, high_risk_kyc_needed, kyc_data_needed, name_check_without_kyc, asset_kyc_needed, bank_release_pending, olky_no_kyc, bank_tx_needed]
- chargeback mails (BUY_*_RETURN)
- chargeback-unconfirmed mails (BUY_*_CHARGEBACK_UNCONFIRMED)
- limit-request approval mails

Manual_check, video_ident_needed and merge_incomplete pending mails remain enabled because they are part of regular flows that require customer action.

* Refine RealUnit mail texts and shrink the preview inventory

mail-realunit.json:
- sell-completed body: mention 1-2 banking days for the incoming transfer; explain the bank statement sender will read 'DFX AG, Payment Partner of RealUnit'
- currency_exchange: drop the IBAN placeholder, keep it generic

preview script: reflect the opt-out — drop the 9 disabled pending variants, all 3 chargeback mails and the limit-request mail; remove the now-empty 'Rückerstattung' category

* Polish RealUnit mail texts: drop salutation/body duplications, fix E-Mail-Adresse spelling, add 'next step' hints

- pending.merge_incomplete: spell 'E-Mail-Adresse' consistently with hyphen (was mixed with 'E-Mailadresse')
- payment.fiat_input.body: drop 'Ihre Banküberweisung ist eingegangen und wird verarbeitet' (already in salutation), keep only the next-step hint
- payment.crypto_input.body: same — drop the duplicate 'sind eingetroffen und werden verarbeitet'
- login.salutation: replace duplicate 'RealUnit Login' headline with the more meaningful 'Sie haben einen Login angefordert'
- payment.fiat_input.unassigned.body: append 'Sobald die Zuordnung erfolgt ist, werden Sie wieder per Mail informiert'
- account_merge.request.message: append 'Nach der Bestätigung werden Ihre Accounts zusammengelegt'
- kyc.failed.message: append 'Bitte wiederholen Sie den Schritt. Sobald die Verifizierung erfolgreich abgeschlossen ist, werden Sie wieder per Mail informiert'

* Centralize welcome line and forced language in MailFactory

- MailFactory.createUserV2Mail and createPersonalMail now prepend the personal welcome line ('Guten Tag {name}') as the first body element. Removes the same 28 welcome+SPACE blocks scattered across 14 service files (single source of truth)
- WalletMailConfig gains a 'forcedLang' field. When set, every UserMailV2 for that wallet renders in this language regardless of userData.language
- RealUnit wallet config gets forcedLang='de' so RealUnit mails always render in German even for EN/FR/IT customers
- account-merge.service.ts: drop the unused 'name' computation that was only used for the now-centralized welcome (the receiver of the mail is now greeted instead of the mentioned account)

* Remove accidentally committed .claude/worktrees from previous commit

The previous commit (911ae1b) included 4998 files from .claude/worktrees/ because git add -A picked them up. Add .claude/ to .gitignore and untrack everything under it. The previous commit's intended Mail-Factory and forced-language changes remain — only the worktree noise is removed.

* Extract RealUnit mail rules into a shared module

- New src/subdomains/supporting/notification/realunit-mail-rules.ts exports REALUNIT_WALLET_NAME and REALUNIT_DISABLED_PENDING_REASONS
- Replace the duplicate inline RealUnitDisabledPendingReasons const in buy-crypto-notification and buy-fiat-notification with the shared list
- Replace the magic string 'RealUnit' (7 occurrences across buy-crypto/buy-fiat/limit-request) with the REALUNIT_WALLET_NAME constant
- Drop the leftover ' SPACE 3' filler lines in user-data-notification mails that hung in front of the (now-centralized) welcome line

* Fix MailFactory.getMailAffix filter regression for DFX-default mails

The trailing .filter((a) => a.text || a.url || a.mail) in getMailAffix dropped any MailAffix with text:'' — including DefaultEmptyLine which is exactly what every MailKey.SPACE gets rendered into. As a result every SPACE block (used heavily by all DFX default mails for vertical padding) would have disappeared.

Move the empty-translation guard into the default branch of mapMailAffix where it belongs: only skip when the translated text is empty AND there is no special tag — that way an explicitly cleared transaction_button (e.g. RealUnit fiat_input.unassigned) is dropped, but DefaultEmptyLine for SPACE keeps coming through.

Caught by davidleomay's PR review (#3598 (review)).

* Restrict centralized welcome to RealUnit and revert DFX-default service files

User clarification: the only mail-related changes that should land in this PR are RealUnit-specific. Any change that affects DFX default mails was unintended and must be undone.

- WalletMailConfig.centralizedWelcome flag introduced; MailFactory.createUserV2Mail and createPersonalMail now only prepend the welcome line when the wallet opts in (currently RealUnit only)
- Config.mail.wallet.RealUnit gets centralizedWelcome: true (alongside template + forcedLang)
- All previously-touched DFX-default service files reverted to merge-base state — no welcome inserts added, no SPACE-3 fillers removed:
  ref-reward-notification, kyc-notification, tfa, auth, account-merge, recommendation, user-data-notification, bank-tx-return-notification, payin-notification, transaction-notification, support-issue-notification
- limit-request-notification: keep the existing manual welcome line in prefix; only the RealUnit opt-out filter remains as a real change

* Bind DFX-closing skip to centralizedWelcome instead of template

Was: any wallet with a custom template skipped the DFX_TEAM_CLOSING block, which silently changed the closing for onchainlabs (an existing custom-template wallet) compared to develop.

Now: only wallets that opt in to RealUnit-style branding via centralizedWelcome=true skip the DFX closing. onchainlabs keeps the unchanged pre-PR behavior.

* Bind empty-translation skip to centralizedWelcome instead of applying it globally

Was: any empty translation result without a special tag was dropped in mapMailAffix's default branch — that would silently change DFX-default rendering if a translation key ever resolved to an empty string for a non-RealUnit wallet.

Now: skip only for wallets that opt in to RealUnit-style branding (centralizedWelcome=true). DFX-default mails keep the unchanged pre-PR behavior of rendering an empty <p> block.

* Extract centralized welcome line into a private helper

The same 8-line welcomeTexts construction was duplicated between createUserV2Mail and createPersonalMail. Pull it out into MailFactory.getCentralizedWelcomeTexts so both call sites stay in sync.

* Sort relative imports alphabetically in mail.factory
@TaprootFreak TaprootFreak merged commit 3d9bd5b into main Apr 30, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants