show multi-crypto rates in shop nav
This commit is contained in:
@@ -8,6 +8,7 @@ import { StorefrontFeedbackCookieService } from './StorefrontFeedbackCookieServi
|
|||||||
import { StorefrontOrderAuthCookieService } from './StorefrontOrderAuthCookieService';
|
import { StorefrontOrderAuthCookieService } from './StorefrontOrderAuthCookieService';
|
||||||
import { StorefrontThemeCookieService } from './StorefrontThemeCookieService';
|
import { StorefrontThemeCookieService } from './StorefrontThemeCookieService';
|
||||||
import type { StorefrontPageMetaInput } from '../types/StorefrontPageMetaInput';
|
import type { StorefrontPageMetaInput } from '../types/StorefrontPageMetaInput';
|
||||||
|
import { PaymentMethod } from '../../payment/types/PaymentMethod';
|
||||||
|
|
||||||
describe('StorefrontShopViewService', () => {
|
describe('StorefrontShopViewService', () => {
|
||||||
type ServiceOverrides = {
|
type ServiceOverrides = {
|
||||||
@@ -21,8 +22,9 @@ describe('StorefrontShopViewService', () => {
|
|||||||
simplexLink: string | null;
|
simplexLink: string | null;
|
||||||
shippingNote: string | null;
|
shippingNote: string | null;
|
||||||
};
|
};
|
||||||
shopSettings?: { shopName: string; shopFiatCurrency: string };
|
shopSettings?: { shopName: string; shopFiatCurrency: string; enabledPaymentMethods?: PaymentMethod[] };
|
||||||
fiatPerXmr?: number;
|
fiatPerXmr?: number;
|
||||||
|
fiatPerBtc?: number | null;
|
||||||
req?: Partial<Pick<Request, 'protocol' | 'path' | 'originalUrl'>> & {
|
req?: Partial<Pick<Request, 'protocol' | 'path' | 'originalUrl'>> & {
|
||||||
host?: string;
|
host?: string;
|
||||||
};
|
};
|
||||||
@@ -45,13 +47,20 @@ describe('StorefrontShopViewService', () => {
|
|||||||
simplexLink: null,
|
simplexLink: null,
|
||||||
shippingNote: null
|
shippingNote: null
|
||||||
},
|
},
|
||||||
shopSettings = { shopName: 'Demo Shop', shopFiatCurrency: 'USD' },
|
shopSettings = {
|
||||||
|
shopName: 'Demo Shop',
|
||||||
|
shopFiatCurrency: 'USD',
|
||||||
|
enabledPaymentMethods: [PaymentMethod.Xmr, PaymentMethod.Btc]
|
||||||
|
},
|
||||||
fiatPerXmr = 150,
|
fiatPerXmr = 150,
|
||||||
|
fiatPerBtc = 60_000,
|
||||||
req: reqOverrides = {}
|
req: reqOverrides = {}
|
||||||
} = overrides;
|
} = overrides;
|
||||||
|
|
||||||
const exchangeRateService = {
|
const exchangeRateService = {
|
||||||
getLiveFiatPerCrypto: jest.fn().mockReturnValue(fiatPerXmr)
|
getLiveFiatPerCrypto: jest.fn((method: PaymentMethod) =>
|
||||||
|
method === PaymentMethod.Btc ? fiatPerBtc : fiatPerXmr
|
||||||
|
)
|
||||||
} as unknown as ExchangeRateService;
|
} as unknown as ExchangeRateService;
|
||||||
const configService = {
|
const configService = {
|
||||||
get: jest.fn().mockReturnValue(shopSettings)
|
get: jest.fn().mockReturnValue(shopSettings)
|
||||||
@@ -124,7 +133,8 @@ describe('StorefrontShopViewService', () => {
|
|||||||
simplexLink: 'https://simplex.example',
|
simplexLink: 'https://simplex.example',
|
||||||
shippingNote: 'Ships in 3 days'
|
shippingNote: 'Ships in 3 days'
|
||||||
},
|
},
|
||||||
fiatPerXmr: 200
|
fiatPerXmr: 200,
|
||||||
|
fiatPerBtc: 80_000
|
||||||
});
|
});
|
||||||
|
|
||||||
const locals = await service.buildShopRenderLocals(req, res, defaultPage);
|
const locals = await service.buildShopRenderLocals(req, res, defaultPage);
|
||||||
@@ -134,7 +144,10 @@ describe('StorefrontShopViewService', () => {
|
|||||||
cartTotalQty: 3,
|
cartTotalQty: 3,
|
||||||
feedback: { type: 'success', text: 'Added to cart' },
|
feedback: { type: 'success', text: 'Added to cart' },
|
||||||
shopFiatCurrency: 'USD',
|
shopFiatCurrency: 'USD',
|
||||||
fiatPerXmr: 200,
|
cryptoRates: [
|
||||||
|
{ cryptoCurrency: 'XMR', fiatPerCrypto: 200 },
|
||||||
|
{ cryptoCurrency: 'BTC', fiatPerCrypto: 80_000 }
|
||||||
|
],
|
||||||
logoUrl: '/uploads/logo.png',
|
logoUrl: '/uploads/logo.png',
|
||||||
faviconUrl: '/uploads/favicon.ico',
|
faviconUrl: '/uploads/favicon.ico',
|
||||||
simplexLink: 'https://simplex.example',
|
simplexLink: 'https://simplex.example',
|
||||||
@@ -264,7 +277,7 @@ describe('StorefrontShopViewService', () => {
|
|||||||
|
|
||||||
it('uses shop fiat currency in product json-ld', async () => {
|
it('uses shop fiat currency in product json-ld', async () => {
|
||||||
const { service, req, res } = createService({
|
const { service, req, res } = createService({
|
||||||
shopSettings: { shopName: 'Euro Shop', shopFiatCurrency: 'EUR' },
|
shopSettings: { shopName: 'Euro Shop', shopFiatCurrency: 'EUR', enabledPaymentMethods: [PaymentMethod.Xmr] },
|
||||||
req: {
|
req: {
|
||||||
path: '/shop/products/1/variants/2',
|
path: '/shop/products/1/variants/2',
|
||||||
originalUrl: '/shop/products/1/variants/2'
|
originalUrl: '/shop/products/1/variants/2'
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ import { formatShortOrderId } from '../../../utils/order/formatShortOrderId';
|
|||||||
import { toAbsoluteUrl } from '../../../utils/toAbsoluteUrl';
|
import { toAbsoluteUrl } from '../../../utils/toAbsoluteUrl';
|
||||||
import { ShopSettingsService } from '../../shopSettings/services/ShopSettingsService';
|
import { ShopSettingsService } from '../../shopSettings/services/ShopSettingsService';
|
||||||
import { ExchangeRateService } from '../../exchangeRate/services/ExchangeRateService';
|
import { ExchangeRateService } from '../../exchangeRate/services/ExchangeRateService';
|
||||||
|
import { paymentMethodLabel } from '../../../consts/paymentMethodLabel';
|
||||||
import { PaymentMethod } from '../../payment/types/PaymentMethod';
|
import { PaymentMethod } from '../../payment/types/PaymentMethod';
|
||||||
import type { AuthorizedOrderNavItem } from '../types/AuthorizedOrderNavItem';
|
import type { AuthorizedOrderNavItem } from '../types/AuthorizedOrderNavItem';
|
||||||
import type { ShopRenderLocals } from '../types/ShopRenderLocals';
|
import type { ShopRenderLocals } from '../types/ShopRenderLocals';
|
||||||
|
import type { StorefrontCryptoRate } from '../types/StorefrontCryptoRate';
|
||||||
import type { StorefrontPageMeta } from '../types/StorefrontPageMeta';
|
import type { StorefrontPageMeta } from '../types/StorefrontPageMeta';
|
||||||
import type { StorefrontPageMetaInput } from '../types/StorefrontPageMetaInput';
|
import type { StorefrontPageMetaInput } from '../types/StorefrontPageMetaInput';
|
||||||
import type { StorefrontProductJsonLdInput } from '../types/StorefrontProductJsonLdInput';
|
import type { StorefrontProductJsonLdInput } from '../types/StorefrontProductJsonLdInput';
|
||||||
@@ -39,9 +41,11 @@ export class StorefrontShopViewService {
|
|||||||
|
|
||||||
const cartTotalQty = getTotalCartQtyFromCart(cart);
|
const cartTotalQty = getTotalCartQtyFromCart(cart);
|
||||||
|
|
||||||
const { shopName, shopFiatCurrency } = this.configService.get('shopSettings') as Config['shopSettings'];
|
const { shopName, shopFiatCurrency, enabledPaymentMethods } = this.configService.get(
|
||||||
|
'shopSettings'
|
||||||
|
) as Config['shopSettings'];
|
||||||
|
|
||||||
const fiatPerXmr = this.exchangeRateService.getLiveFiatPerCrypto(PaymentMethod.Xmr);
|
const cryptoRates = this.buildCryptoRates(enabledPaymentMethods);
|
||||||
|
|
||||||
const { logoUrl, faviconUrl, simplexLink, shippingNote } =
|
const { logoUrl, faviconUrl, simplexLink, shippingNote } =
|
||||||
await this.shopSettingsService.getStorefrontBranding();
|
await this.shopSettingsService.getStorefrontBranding();
|
||||||
@@ -61,7 +65,7 @@ export class StorefrontShopViewService {
|
|||||||
authorizedOrders,
|
authorizedOrders,
|
||||||
shopNavActive,
|
shopNavActive,
|
||||||
shopFiatCurrency,
|
shopFiatCurrency,
|
||||||
fiatPerXmr,
|
cryptoRates,
|
||||||
logoUrl,
|
logoUrl,
|
||||||
faviconUrl,
|
faviconUrl,
|
||||||
simplexLink,
|
simplexLink,
|
||||||
@@ -130,4 +134,21 @@ export class StorefrontShopViewService {
|
|||||||
|
|
||||||
return JSON.stringify(data);
|
return JSON.stringify(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private buildCryptoRates(enabledPaymentMethods: PaymentMethod[]): StorefrontCryptoRate[] {
|
||||||
|
return enabledPaymentMethods.flatMap(paymentMethod => {
|
||||||
|
const fiatPerCrypto = this.exchangeRateService.getLiveFiatPerCrypto(paymentMethod);
|
||||||
|
|
||||||
|
if (fiatPerCrypto === null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
cryptoCurrency: paymentMethodLabel[paymentMethod],
|
||||||
|
fiatPerCrypto
|
||||||
|
}
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { ShopFiatCurrency } from '../../../types/ShopFiatCurrency';
|
import type { ShopFiatCurrency } from '../../../types/ShopFiatCurrency';
|
||||||
import type { AuthorizedOrderNavItem } from './AuthorizedOrderNavItem';
|
import type { AuthorizedOrderNavItem } from './AuthorizedOrderNavItem';
|
||||||
import type { ShopNavActive } from './ShopNavActive';
|
import type { ShopNavActive } from './ShopNavActive';
|
||||||
|
import type { StorefrontCryptoRate } from './StorefrontCryptoRate';
|
||||||
import type { StorefrontFeedback } from './StorefrontFeedback';
|
import type { StorefrontFeedback } from './StorefrontFeedback';
|
||||||
import type { StorefrontPageMeta } from './StorefrontPageMeta';
|
import type { StorefrontPageMeta } from './StorefrontPageMeta';
|
||||||
import type { StorefrontThemePreference } from './StorefrontThemePreference';
|
import type { StorefrontThemePreference } from './StorefrontThemePreference';
|
||||||
@@ -13,7 +14,7 @@ export type ShopRenderLocals = {
|
|||||||
authorizedOrders: AuthorizedOrderNavItem[];
|
authorizedOrders: AuthorizedOrderNavItem[];
|
||||||
shopNavActive: ShopNavActive;
|
shopNavActive: ShopNavActive;
|
||||||
shopFiatCurrency: ShopFiatCurrency;
|
shopFiatCurrency: ShopFiatCurrency;
|
||||||
fiatPerXmr: number | null;
|
cryptoRates: StorefrontCryptoRate[];
|
||||||
logoUrl: string | null;
|
logoUrl: string | null;
|
||||||
faviconUrl: string | null;
|
faviconUrl: string | null;
|
||||||
simplexLink: string | null;
|
simplexLink: string | null;
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export type StorefrontCryptoRate = {
|
||||||
|
cryptoCurrency: string;
|
||||||
|
fiatPerCrypto: number;
|
||||||
|
};
|
||||||
@@ -29,8 +29,12 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if fiatPerXmr}}
|
{{#if cryptoRates.length}}
|
||||||
<div class='sf-rate'>1 XMR = {{fiatPerXmr}} {{shopFiatCurrency}}</div>
|
<div class='sf-rates'>
|
||||||
|
{{#each cryptoRates}}
|
||||||
|
<div class='sf-rate'>1 {{cryptoCurrency}} = {{fiatPerCrypto}} {{../shopFiatCurrency}}</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
Reference in New Issue
Block a user