Skip to content

Commit

Permalink
feat(trading): otc market banner
Browse files Browse the repository at this point in the history
  • Loading branch information
adderpositive authored and tomasklim committed Feb 28, 2025
1 parent 7363725 commit 0ec5da3
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 0 deletions.
18 changes: 18 additions & 0 deletions packages/suite/src/support/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1416,6 +1416,24 @@ export default defineMessages({
defaultMessage: 'View details',
id: 'TR_TRADING_VIEW_DETAILS',
},
TR_TRADING_OTC_INFO_BUY: {
defaultMessage:
'For purchases over {minimumFiat} {fiatSymbol}, consider using our OTC partner:',
id: 'TR_TRADING_OTC_INFO_BUY',
},
TR_TRADING_OTC_INFO_SELL: {
defaultMessage:
'For sales over {minimumFiat} {fiatSymbol}, consider using our OTC partner:',
id: 'TR_TRADING_OTC_INFO_SELL',
},
TR_TRADING_OTC_LINK_BUY: {
defaultMessage: 'Buy with Mercuryo',
id: 'TR_TRADING_OTC_LINK_BUY',
},
TR_TRADING_OTC_LINK_SELL: {
defaultMessage: 'Sell with Mercuryo',
id: 'TR_TRADING_OTC_LINK_SELL',
},
TR_ADDRESS_MODAL_CLIPBOARD: {
defaultMessage: 'Copy address',
id: 'TR_ADDRESS_MODAL_CLIPBOARD',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
import { TradingFormOfferCryptoAmount } from 'src/views/wallet/trading/common/TradingForm/TradingFormOfferCryptoAmount';
import { TradingFormOfferFiatAmount } from 'src/views/wallet/trading/common/TradingForm/TradingFormOfferFiatAmount';
import { TradingFormOfferItem } from 'src/views/wallet/trading/common/TradingForm/TradingFormOfferItem';
import { TradingFormOfferOTC } from 'src/views/wallet/trading/common/TradingForm/TradingFormOfferOTC';
import { TradingFormOffersSwitcher } from 'src/views/wallet/trading/common/TradingForm/TradingFormOffersSwitcher';

const getSelectedQuote = (
Expand Down Expand Up @@ -158,6 +159,7 @@ export const TradingFormOffer = () => {
>
<Translation id={tradingGetSectionActionLabel(type)} />
</Button>
{(type === 'buy' || type === 'sell') && <TradingFormOfferOTC />}
</Column>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { useEffect, useState } from 'react';

import { FiatCurrencyCode } from 'invity-api';

import { TradingOTC, TradingTradeBuySellType, invityAPI } from '@suite-common/trading';
import { localizeNumber } from '@suite-common/wallet-utils';
import { Banner, Text } from '@trezor/components';
import { spacings } from '@trezor/theme';

import { Translation, TrezorLink } from 'src/components/suite';
import { useSelector } from 'src/hooks/suite';
import { useTradingFormContext } from 'src/hooks/wallet/trading/form/useTradingCommonForm';
import { selectLanguage } from 'src/reducers/suite/suiteReducer';
import { isTradingBuyContext } from 'src/utils/wallet/trading/tradingTypingUtils';

export const TradingFormOfferOTC = () => {
const context = useTradingFormContext<TradingTradeBuySellType>();
const locale = useSelector(selectLanguage);

const { amountInCrypto } = context.getValues();
const fiatAmount = isTradingBuyContext(context)
? context.getValues().fiatInput
: context.getValues().outputs[0].fiat;
const currencySelect = isTradingBuyContext(context)
? context.getValues().currencySelect.value
: context.getValues().outputs[0].currency.value;
const [otcData, setOtcData] = useState<TradingOTC | null>(null);
const apiKey = invityAPI.getCurrentApiKey();

useEffect(() => {
if (!apiKey) return;

const getOtcData = async () => {
const otcData = await invityAPI.getOTCData();

if (!otcData) return;

setOtcData(otcData);
};

getOtcData();
}, [apiKey]);

const isCurrencyAllowed = otcData?.allowedCurrencies?.includes(
currencySelect as FiatCurrencyCode,
);

if (
!otcData ||
amountInCrypto ||
!isCurrencyAllowed ||
!fiatAmount ||
Number(fiatAmount) <= Number(otcData.minimumFiat)
) {
return null;
}

const apiUrl = new URL(otcData.apiUrl);
const params = new URLSearchParams({
widget_id: otcData.idWidget,
otc_id: otcData.idOtcUser,
fiat_amount: fiatAmount,
fiat_currency: currencySelect,
type: context.type,
});

apiUrl.search = params.toString();

return (
<Banner variant="info">
<Text margin={{ bottom: spacings.xxs }}>
<Translation
id={
context.type === 'buy'
? 'TR_TRADING_OTC_INFO_BUY'
: 'TR_TRADING_OTC_INFO_SELL'
}
values={{
minimumFiat: localizeNumber(otcData.minimumFiat, locale),
fiatSymbol: currencySelect.toUpperCase(),
}}
/>{' '}
<TrezorLink href={apiUrl.toString()} target="_blank" typographyStyle="hint">
<Translation
id={
context.type === 'buy'
? 'TR_TRADING_OTC_LINK_BUY'
: 'TR_TRADING_OTC_LINK_SELL'
}
/>
</TrezorLink>
</Text>
</Banner>
);
};
16 changes: 16 additions & 0 deletions suite-common/trading/src/invityAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import type {
import type {
InvityServerEnvironment,
InvityServers,
TradingOTC,
TradingPaymentMethodType,
TradingTradeType,
TradingType,
Expand Down Expand Up @@ -84,6 +85,9 @@ class InvityAPI {
private readonly SELL_FIAT_CONFIRM = '/api/v3/sell/fiat/confirm';
private readonly SELL_FIAT_WATCH_TRADE = '/api/v3/sell/fiat/watch/{{counter}}';

// otc service
private readonly OTC_INFO = '/api/v1/otc';

private static accountDescriptor: string;
private static apiKey: string;

Expand Down Expand Up @@ -433,6 +437,18 @@ class InvityAPI {
return { error: error.toString() };
}
};

getOTCData = async (): Promise<TradingOTC | undefined> => {
try {
const response = await this.request(this.OTC_INFO, {}, 'GET');

if (response) {
return response;
}
} catch (error) {
console.error('[getOTCData]', error);
}
};
}

export const invityAPI = new InvityAPI();
8 changes: 8 additions & 0 deletions suite-common/trading/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,11 @@ export type TradingTransaction =
| TradingTransactionBuy
| TradingTransactionSell
| TradingTransactionExchange;

export type TradingOTC = {
idWidget: string;
idOtcUser: string;
apiUrl: string;
minimumFiat: string;
allowedCurrencies: FiatCurrencyCode[];
};

0 comments on commit 0ec5da3

Please sign in to comment.