2 Commits

Author SHA1 Message Date
sdarbinyan
1a198252b3 Merge branch 'B2B'
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
Deploy Frontend / deploy (push) Has been cancelled
2026-08-18 13:28:58 +04:00
sdarbinyan
c104f313ce feat: real FX quote gateway, swapped in behind useMockData
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
FxQuoteApiGateway calls GET /api/v2/pricing/fx-quote per
PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md §3.1. Deliberately thin - no caching or
retry here, since the caller decides what an expired quote means (re-fetch vs
block checkout) and baking that into the gateway would hide the decision.

Token now resolves to the real gateway whenever useMockData is false, matching
the existing pattern in runtime-provider-strategy.service.ts.

Additive only: nothing that reads prices today was rewired to this gateway yet.
That rewiring touches checkout's charge-amount computation and is deferred -
see the session summary for why.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 13:28:56 +04:00
2 changed files with 27 additions and 2 deletions

View File

@@ -0,0 +1,23 @@
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { Observable } from 'rxjs';
import { FxQuote } from '../models/fx-quote.model';
import { FxQuoteGateway } from './fx-quote-gateway.interface';
/**
* Real FX gateway. Contract: docs/backend/PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md §3.1.
*
* Deliberately thin: no caching, no retry logic here. TTL/expiry handling is
* the caller's job (isFxQuoteExpired), because the caller decides what to do
* with an expired quote (re-fetch vs block checkout) - baking a policy into
* the gateway would hide that decision.
*/
@Injectable({ providedIn: 'root' })
export class FxQuoteApiGateway implements FxQuoteGateway {
private readonly http = inject(HttpClient);
getQuote(base: string, quote: string): Observable<FxQuote> {
const params = new HttpParams().set('base', base).set('quote', quote);
return this.http.get<FxQuote>('/api/v2/pricing/fx-quote', { params });
}
}

View File

@@ -1,9 +1,11 @@
import { InjectionToken, inject } from '@angular/core';
import { environment } from '../../../../environments/environment';
import { FxQuoteGateway } from './fx-quote-gateway.interface';
import { FxQuoteLocalGateway } from './fx-quote-local.gateway';
import { FxQuoteApiGateway } from './fx-quote-api.gateway';
/** Swap point for the real FX backend from docs/backend/PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md §3.1. */
/** Swap point for docs/backend/PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md §3.1. */
export const FX_QUOTE_GATEWAY = new InjectionToken<FxQuoteGateway>('FX_QUOTE_GATEWAY', {
providedIn: 'root',
factory: () => inject(FxQuoteLocalGateway),
factory: () => (environment.useMockData ? inject(FxQuoteLocalGateway) : inject(FxQuoteApiGateway)),
});