Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: buy credits step2 #2480

Open
wants to merge 10 commits into
base: feat-APP-204-buy-credits
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { CURRENCIES } from 'components/molecules/DenomIconWithCurrency/DenomIcon

export const CREDITS_AMOUNT = 'creditsAmount';
export const CURRENCY_AMOUNT = 'currencyAmount';
export const CURRENCY = 'currency';
export const CREDIT_VINTAGE_OPTIONS = 'creditVintageOptions';
export const SELL_ORDERS = 'sellOrders';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const CreditsWithForm = (args: any) => {
args.paymentOption === PAYMENT_OPTIONS.CARD
? { askDenom: CURRENCIES.usd, askBaseDenom: CURRENCIES.usd }
: defaultCryptoCurrency;
const [currency, setCurrency] = useState<Currency>(initCurrency);
const [currency] = useState<Currency>(initCurrency);
const [spendingCap, setSpendingCap] = useState(0);
const [creditsAvailable, setCreditsAvailable] = useState(0);

Expand All @@ -47,14 +47,13 @@ const CreditsWithForm = (args: any) => {
mode: 'onChange',
});
const filteredCryptoSellOrders = cryptoSellOrders.filter(
order => order.askDenom === currency.askDenom,
order => order.askDenom === initCurrency.askDenom,
);
return (
<Form form={form as any} onSubmit={form.handleSubmit as any}>
<CreditsAmount
{...args}
currency={currency}
setCurrency={setCurrency}
spendingCap={spendingCap}
setSpendingCap={setSpendingCap}
creditsAvailable={creditsAvailable}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ describe('CreditsAmount', () => {
const formDefaultValues = {
paymentOption: PAYMENT_OPTIONS.CARD,
currency: { askDenom: CURRENCIES.usd, askBaseDenom: CURRENCIES.usd },
setCurrency: () => {},
spendingCap: 3185,
setSpendingCap: () => {},
creditsAvailable: 1125,
Expand Down Expand Up @@ -95,7 +94,6 @@ describe('CreditsAmount', () => {
const currencyInput = screen.getByLabelText(/Currency Input/i);

await userEvent.click(maxCreditsButton);
screen.debug();

expect(creditsInput).toHaveValue(1125);
expect(currencyInput).toHaveValue(3185);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,33 @@ import { useFormContext, useWatch } from 'react-hook-form';
import { Trans } from '@lingui/macro';
import { ChooseCreditsFormSchemaType } from 'web-marketplace/src/components/organisms/ChooseCreditsForm/ChooseCreditsForm.schema';

import { denomToMicro, microToDenom } from 'lib/denom.utils';
import { microToDenom } from 'lib/denom.utils';

import { PAYMENT_OPTIONS } from 'pages/BuyCredits/BuyCredits.constants';
import { CardSellOrder } from 'components/organisms/ChooseCreditsForm/ChooseCreditsForm.types';

import { findDisplayDenom } from '../DenomLabel/DenomLabel.utils';
import {
CREDITS_AMOUNT,
CURRENCY,
CURRENCY_AMOUNT,
SELL_ORDERS,
} from './CreditsAmount.constants';
import { CreditsAmountHeader } from './CreditsAmount.Header';
import { CreditsAmountProps } from './CreditsAmount.types';
import {
formatFullSellOrder,
getCreditsAmount,
getCreditsAvailablePerCurrency,
getCurrencyAmount,
getSellOrderPrice,
getSpendingCap,
} from './CreditsAmount.utils';
import { CreditsInput } from './CreditsInput';
import { CurrencyInput } from './CurrencyInput';

export const CreditsAmount = ({
paymentOption,
currency,
setCurrency,
paymentOption,
creditsAvailable,
setCreditsAvailable,
filteredCryptoSellOrders,
Expand All @@ -39,7 +42,7 @@ export const CreditsAmount = ({
creditTypePrecision,
}: CreditsAmountProps) => {
const [maxCreditsSelected, setMaxCreditsSelected] = useState(false);
const { setValue } = useFormContext<ChooseCreditsFormSchemaType>();
const { setValue, trigger } = useFormContext<ChooseCreditsFormSchemaType>();

const card = paymentOption === PAYMENT_OPTIONS.CARD;
const orderedSellOrders = useMemo(
Expand All @@ -53,12 +56,6 @@ export const CreditsAmount = ({
[card, cardSellOrders, filteredCryptoSellOrders],
);

useEffect(() => {
// Reset amounts to 0 on currency change
setValue(CREDITS_AMOUNT, 0);
setValue(CURRENCY_AMOUNT, 0);
}, [currency, setValue]);

useEffect(() => {
setSpendingCap(
getSpendingCap(paymentOption, filteredCryptoSellOrders, cardSellOrders),
Expand All @@ -84,59 +81,45 @@ export const CreditsAmount = ({
useEffect(() => {
if (maxCreditsSelected) {
setValue(CREDITS_AMOUNT, creditsAvailable);
setValue(CURRENCY_AMOUNT, microToDenom(spendingCap));
setValue(
CURRENCY_AMOUNT,
paymentOption === PAYMENT_OPTIONS.CARD
? spendingCap
: microToDenom(spendingCap),
);
setValue(
SELL_ORDERS,
orderedSellOrders.map(order => {
const price = getSellOrderPrice({ order, card });
return formatFullSellOrder({ order, card, price });
}),
);
trigger();
setMaxCreditsSelected(false);
}
}, [creditsAvailable, maxCreditsSelected, setValue, spendingCap]);
}, [
card,
creditsAvailable,
maxCreditsSelected,
orderedSellOrders,
paymentOption,
setValue,
spendingCap,
trigger,
]);

// Credits amount change
const handleCreditsAmountChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
// Set currency amount according to credits quantity,
// selecting the cheapest credits first
const currentCreditsAmount = e.target.valueAsNumber;
let currentCurrencyAmount = 0;
let creditsAmountLeft = currentCreditsAmount;
const sellOrders = [];

for (let i = 0; i < orderedSellOrders.length; i++) {
const order = orderedSellOrders[i];
const price = card
? (order as CardSellOrder).usdPrice
: Number(order.askAmount);
const quantity = Number(order.quantity);

// Take all credits from this sell order
if (creditsAmountLeft >= quantity) {
creditsAmountLeft -= quantity;
currentCurrencyAmount += quantity * price;
sellOrders.push({
sellOrderId: order.id,
quantity: order.quantity,
bidPrice: !card
? { amount: String(price), denom: order.askDenom }
: undefined,
price: card ? price : undefined,
});
if (creditsAmountLeft === 0) break;
} else {
// Take only remaining credits
currentCurrencyAmount += creditsAmountLeft * price;
sellOrders.push({
sellOrderId: order.id,
quantity: String(creditsAmountLeft),
bidPrice: !card
? { amount: String(price), denom: order.askDenom }
: undefined,
price: card ? price : undefined,
});
break;
}
}
setValue(
CURRENCY_AMOUNT,
card ? currentCurrencyAmount : microToDenom(currentCurrencyAmount),
);
const { currencyAmount, sellOrders } = getCurrencyAmount({
currentCreditsAmount,
card,
orderedSellOrders,
});
setValue(CURRENCY_AMOUNT, currencyAmount);
setValue(SELL_ORDERS, sellOrders);
},
[card, orderedSellOrders, setValue],
Expand All @@ -148,48 +131,16 @@ export const CreditsAmount = ({
// Set credits quantity according to currency amount,
// selecting the cheapest credits first
const value = e.target.valueAsNumber;
const currentCurrencyAmount = card ? value : denomToMicro(value);
let currentCreditsAmount = 0;
let currencyAmountLeft = currentCurrencyAmount;
const sellOrders = [];

for (let i = 0; i < orderedSellOrders.length; i++) {
const order = orderedSellOrders[i];
const price = card
? (order as CardSellOrder).usdPrice
: Number(order.askAmount);
const quantity = Number(order.quantity);
const orderTotalAmount = quantity * price;

if (currencyAmountLeft >= orderTotalAmount) {
currencyAmountLeft -= orderTotalAmount;
currentCreditsAmount += quantity;
sellOrders.push({
sellOrderId: order.id,
quantity: order.quantity,
bidPrice: !card
? { amount: String(price), denom: order.askDenom }
: undefined,
price: card ? price : undefined,
});
if (currencyAmountLeft === 0) break;
} else {
currentCreditsAmount += currencyAmountLeft / price;
sellOrders.push({
sellOrderId: order.id,
quantity: String(currencyAmountLeft / price),
bidPrice: !card
? { amount: String(price), denom: order.askDenom }
: undefined,
price: card ? price : undefined,
});
break;
}
}
const { currentCreditsAmount, sellOrders } = getCreditsAmount({
value,
card,
orderedSellOrders,
creditTypePrecision,
});
setValue(CREDITS_AMOUNT, currentCreditsAmount);
setValue(SELL_ORDERS, sellOrders);
},
[card, orderedSellOrders, setValue],
[card, orderedSellOrders, setValue, creditTypePrecision],
);

const displayDenom = findDisplayDenom({
Expand All @@ -212,8 +163,6 @@ export const CreditsAmount = ({
maxCurrencyAmount={spendingCap}
paymentOption={paymentOption}
defaultCryptoCurrency={defaultCryptoCurrency}
currency={currency}
setCurrency={setCurrency}
handleCurrencyAmountChange={handleCurrencyAmountChange}
cryptoCurrencies={cryptoCurrencies}
displayDenom={displayDenom}
Expand All @@ -223,7 +172,6 @@ export const CreditsAmount = ({
<CreditsInput
creditsAvailable={creditsAvailable}
handleCreditsAmountChange={handleCreditsAmountChange}
paymentOption={paymentOption}
/>
</div>
{paymentOption === PAYMENT_OPTIONS.CRYPTO && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ export type Currency = {
};
export interface CreditsAmountProps {
paymentOption: PaymentOptionsType;
currency: Currency;
setCurrency: (currency: Currency) => void;
spendingCap: number;
setSpendingCap: UseStateSetter<number>;
creditsAvailable: number;
Expand All @@ -26,20 +24,18 @@ export interface CreditsAmountProps {
cryptoCurrencies: Currency[];
allowedDenoms?: AllowedDenoms;
creditTypePrecision?: number | null;
currency: Currency;
}

export interface CreditsInputProps {
creditsAvailable: number;
handleCreditsAmountChange: (e: ChangeEvent<HTMLInputElement>) => void;
paymentOption: PaymentOptionsType;
}

export interface CurrencyInputProps {
maxCurrencyAmount: number;
paymentOption: PaymentOptionsType;
defaultCryptoCurrency: Currency;
currency: Currency;
setCurrency: (currency: Currency) => void;
handleCurrencyAmountChange: (e: ChangeEvent<HTMLInputElement>) => void;
cryptoCurrencies: Currency[];
allowedDenoms?: AllowedDenoms;
Expand Down
Loading