add sell and buy orders list

This commit is contained in:
João Geonizeli
2021-08-15 18:02:06 -03:00
parent 29175f14b0
commit 64bc21195c
17 changed files with 1185 additions and 235 deletions

View File

@@ -38,12 +38,12 @@ export const Pool = ({ pool }: PoolProps) => {
}: ${JSON.stringify(totalStaked)}` }: ${JSON.stringify(totalStaked)}`
); );
const aprValue = getApr( const aprValue = getApr({
stakingPrice, rewardTokenPrice: stakingPrice,
earningPrice, stakingTokenPrice: earningPrice,
totalStaked, tokenPerBlock: totalStaked,
parseFloat(pool.tokenPerBlock) / 1e-18 totalStaked: parseFloat(pool.tokenPerBlock) / 1e-18,
); });
if (aprValue) { if (aprValue) {
setApr({ setApr({

View File

@@ -0,0 +1,187 @@
import React, { useState } from "react";
import type { FC } from "react";
import { graphql } from "babel-plugin-relay/macro";
import { useFragment } from "react-relay";
import { BigNumber } from "bignumber.js";
import cx from "classnames";
import { useCurrentUser } from "../../../../contexts/UserProvider";
import { Unauthenticated } from "../../../../messages/Unauthenticated";
import type { CreateExchangeOrderModal_fiatBalances$key } from "./__generated__/CreateExchangeOrderModal_fiatBalances.graphql";
import type { CreateExchangeOrderModal_balances$key } from "./__generated__/CreateExchangeOrderModal_balances.graphql";
const tabBaseStyles =
"w-full text-base font-bold text-black px-4 py-2 focus:ring-blue-500";
const selectedTabStyles =
"bg-blue-600 hover:bg-blue-700 rounded-l-frounded-full text-white";
const inputBaseStyles =
"rounded-lg border-transparent flex-1 appearance-none border border-gray-300 w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent mb-3";
type Props = {
fiatBalancesRefs: CreateExchangeOrderModal_fiatBalances$key;
balancesRefs: CreateExchangeOrderModal_balances$key;
};
export const CreateExchangeOrderModal: FC<Props> = ({
fiatBalancesRefs,
balancesRefs,
}) => {
const { isAuthenticated } = useCurrentUser();
const [exchangeOption, setExchangeOption] = useState<"BUY" | "SELL">("BUY");
const [cryptoDock, setCryptoDock] = useState<string>("0");
const [fiatDock, setFiatDock] = useState<string>("0.00");
const fiatBalances = useFragment<CreateExchangeOrderModal_fiatBalances$key>(
graphql`
fragment CreateExchangeOrderModal_fiatBalances on FiatBalanceConnection {
edges {
node {
amountCents
}
}
}
`,
fiatBalancesRefs
);
const balances = useFragment<CreateExchangeOrderModal_balances$key>(
graphql`
fragment CreateExchangeOrderModal_balances on BalanceConnection {
edges {
node {
amount
}
}
}
`,
balancesRefs
);
if (!isAuthenticated) return <Unauthenticated />;
const [crypto] = balances.edges;
const [fiat] = fiatBalances.edges;
const avaliableCrypto = new BigNumber(crypto.node.amount);
const avaliableFiat = (
fiat.node.amountCents ? fiat.node.amountCents / 100 : 0
).toFixed(2);
const handleSellTabClick = () => {
setExchangeOption("SELL");
setCryptoDock("0");
};
const handleBuyTabClick = () => {
setExchangeOption("BUY");
setCryptoDock("0");
};
const handleCryptoAmountChange = ({
currentTarget: { value },
}: React.ChangeEvent<HTMLInputElement>) => {
const newCryptoAmount = new BigNumber(value);
if (newCryptoAmount.isLessThanOrEqualTo(avaliableCrypto)) {
setCryptoDock(value);
}
};
const handleFiatAmountChange = ({
currentTarget: { value },
}: React.ChangeEvent<HTMLInputElement>) => {
const newFiatAmount = Number(value);
if (Number(avaliableFiat) >= newFiatAmount) {
setFiatDock(value);
}
};
const handleMaxFiatDockButton = () => {
setFiatDock(avaliableFiat);
};
const handleMaxCryptoButton = () => {
setCryptoDock(avaliableCrypto.toString());
};
return (
<div className="max-w-lg">
<div className="flex items-center bg-white rounded-full border border-gray-200 mb-3">
<button
type="button"
className={cx(
tabBaseStyles,
"rounded-full",
exchangeOption === "BUY" && selectedTabStyles
)}
onClick={handleBuyTabClick}
>
Comprar
</button>
<button
type="button"
className={cx(
tabBaseStyles,
"rounded-full",
exchangeOption === "SELL" && selectedTabStyles
)}
onClick={handleSellTabClick}
>
Vender
</button>
</div>
<form className="bg-white p-4 rounded-2xl border border-gray-200">
<span className="mb-2">
{exchangeOption === "SELL" ? "CAKE" : "BRL"} disponível:{" "}
{exchangeOption === "SELL" ? crypto.node.amount : avaliableFiat}
</span>
<div className="flex flex-row">
{exchangeOption === "BUY" ? (
<>
<input
className={cx(inputBaseStyles)}
type="number"
value={fiatDock}
onChange={handleFiatAmountChange}
/>
<button
type="button"
disabled={fiatDock === avaliableFiat}
className="flex items-center mb-3 ml-3 font-bold rounded-full text-red-500"
onClick={handleMaxFiatDockButton}
>
Max
</button>
</>
) : (
<>
<input
className={cx(inputBaseStyles)}
type="number"
value={cryptoDock}
onChange={handleCryptoAmountChange}
/>
<button
type="button"
disabled={avaliableCrypto.isEqualTo(cryptoDock)}
className="flex items-center mb-3 ml-3 font-bold rounded-full text-red-500"
onClick={handleMaxCryptoButton}
>
Max
</button>
</>
)}
</div>
<button
className="cursor-pointer py-2 px-4 bg-blue-600 hover:bg-blue-700 focus:ring-blue-500 focus:ring-offset-blue-200 text-white w-full transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg"
type="submit"
>
{exchangeOption === "BUY" ? "Comprar" : "Vender"} CAKE
</button>
</form>
</div>
);
};

View File

@@ -0,0 +1,63 @@
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from "relay-runtime";
import { FragmentRefs } from "relay-runtime";
export type CreateExchangeOrderModal_balances = {
readonly edges: ReadonlyArray<{
readonly node: {
readonly amount: string;
};
}>;
readonly " $refType": "CreateExchangeOrderModal_balances";
};
export type CreateExchangeOrderModal_balances$data = CreateExchangeOrderModal_balances;
export type CreateExchangeOrderModal_balances$key = {
readonly " $data"?: CreateExchangeOrderModal_balances$data;
readonly " $fragmentRefs": FragmentRefs<"CreateExchangeOrderModal_balances">;
};
const node: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "CreateExchangeOrderModal_balances",
"selections": [
{
"alias": null,
"args": null,
"concreteType": "BalanceEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Balance",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "amount",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
],
"type": "BalanceConnection",
"abstractKey": null
};
(node as any).hash = '42aad1bd63f1135b4d99ec236cd945b5';
export default node;

View File

@@ -0,0 +1,63 @@
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from "relay-runtime";
import { FragmentRefs } from "relay-runtime";
export type CreateExchangeOrderModal_fiatBalances = {
readonly edges: ReadonlyArray<{
readonly node: {
readonly amountCents: number;
};
}>;
readonly " $refType": "CreateExchangeOrderModal_fiatBalances";
};
export type CreateExchangeOrderModal_fiatBalances$data = CreateExchangeOrderModal_fiatBalances;
export type CreateExchangeOrderModal_fiatBalances$key = {
readonly " $data"?: CreateExchangeOrderModal_fiatBalances$data;
readonly " $fragmentRefs": FragmentRefs<"CreateExchangeOrderModal_fiatBalances">;
};
const node: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "CreateExchangeOrderModal_fiatBalances",
"selections": [
{
"alias": null,
"args": null,
"concreteType": "FiatBalanceEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "FiatBalance",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "amountCents",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
],
"type": "FiatBalanceConnection",
"abstractKey": null
};
(node as any).hash = 'b3a734bd9e34e02aacfa42b6b95776a5';
export default node;

View File

@@ -0,0 +1 @@
export * from "./CreateExchangeOrderModal";

View File

@@ -1,176 +1,47 @@
import React, { useState } from "react"; /* eslint-disable relay/must-colocate-fragment-spreads */
import type { FC } from "react";
import { graphql } from "babel-plugin-relay/macro"; import { graphql } from "babel-plugin-relay/macro";
import React, { useState } from "react";
import { useLazyLoadQuery } from "react-relay"; import { useLazyLoadQuery } from "react-relay";
import { BigNumber } from "bignumber.js";
import cx from "classnames";
import { useCurrentUser } from "../../../contexts/UserProvider"; import { CreateExchangeOrderModal } from "./CreateExchangeOrderModel";
import { Unauthenticated } from "../../../messages/Unauthenticated"; import { ExchangeHistory } from "./ExchangeHistory";
import type { ExchangeQuery } from "./__generated__/ExchangeQuery.graphql"; import type { ExchangeQuery } from "./__generated__/ExchangeQuery.graphql";
const tabBaseStyles = export const Exchange = () => {
"w-full text-base font-bold text-black px-4 py-2 focus:ring-blue-500"; const [modelOpen] = useState<boolean>(false);
const selectedTabStyles = const data = useLazyLoadQuery<ExchangeQuery>(
"bg-blue-600 hover:bg-blue-700 rounded-l-frounded-full text-white";
const inputBaseStyles =
"rounded-lg border-transparent flex-1 appearance-none border border-gray-300 w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent mb-3";
export const Exchange: FC = () => {
const { isAuthenticated } = useCurrentUser();
const [exchangeOption, setExchangeOption] = useState<"BUY" | "SELL">("BUY");
const [cryptoDock, setCryptoDock] = useState<string>("0");
const [fiatDock, setFiatDock] = useState<string>("0.00");
const { balances, fiatBalances } = useLazyLoadQuery<ExchangeQuery>(
graphql` graphql`
query ExchangeQuery { query ExchangeQuery {
fiatBalances { fiatBalances {
edges { ...CreateExchangeOrderModal_fiatBalances
node {
amountCents
}
}
} }
balances { balances {
edges { ...CreateExchangeOrderModal_balances
node {
amount
} }
buyCryptoOrders {
...ExchangeHistory_buyCryptoOrders
} }
sellCryptoOrders {
...ExchangeHistory_sellCryptoOrders
} }
} }
`, `,
{} {}
); );
if (!isAuthenticated) return <Unauthenticated />;
const [crypto] = balances.edges;
const [fiat] = fiatBalances.edges;
const avaliableCrypto = new BigNumber(crypto.node.amount);
const avaliableFiat = (
fiat.node.amountCents ? fiat.node.amountCents / 100 : 0
).toFixed(2);
const handleSellTabClick = () => {
setExchangeOption("SELL");
setCryptoDock("0");
};
const handleBuyTabClick = () => {
setExchangeOption("BUY");
setCryptoDock("0");
};
const handleCryptoAmountChange = ({
currentTarget: { value },
}: React.ChangeEvent<HTMLInputElement>) => {
const newCryptoAmount = new BigNumber(value);
if (newCryptoAmount.isLessThanOrEqualTo(avaliableCrypto)) {
setCryptoDock(value);
}
};
const handleFiatAmountChange = ({
currentTarget: { value },
}: React.ChangeEvent<HTMLInputElement>) => {
const newFiatAmount = Number(value);
if (Number(avaliableFiat) >= newFiatAmount) {
setFiatDock(value);
}
};
const handleMaxFiatDockButton = () => {
setFiatDock(avaliableFiat);
};
const handleMaxCryptoButton = () => {
setCryptoDock(avaliableCrypto.toString());
};
return ( return (
<div className="grid place-items-center w-full"> <div className="w-full">
<div className="max-w-lg"> <ExchangeHistory
<div className="flex items-center bg-white rounded-full border border-gray-200 mb-3"> sellCryptoOrdersRefs={data.sellCryptoOrders}
<button buyCryptoOrdersRefs={data.buyCryptoOrders}
type="button"
className={cx(
tabBaseStyles,
"rounded-full",
exchangeOption === "BUY" && selectedTabStyles
)}
onClick={handleBuyTabClick}
>
Comprar
</button>
<button
type="button"
className={cx(
tabBaseStyles,
"rounded-full",
exchangeOption === "SELL" && selectedTabStyles
)}
onClick={handleSellTabClick}
>
Vender
</button>
</div>
<form className="bg-white p-4 rounded-2xl border border-gray-200">
<span className="mb-2">
{exchangeOption === "SELL" ? "CAKE" : "BRL"} disponível:{" "}
{exchangeOption === "SELL" ? crypto.node.amount : avaliableFiat}
</span>
<div className="flex flex-row">
{exchangeOption === "BUY" ? (
<>
<input
className={cx(inputBaseStyles)}
type="number"
value={fiatDock}
onChange={handleFiatAmountChange}
/> />
<button {modelOpen && (
type="button" <CreateExchangeOrderModal
disabled={fiatDock === avaliableFiat} balancesRefs={data.balances}
className="flex items-center mb-3 ml-3 font-bold rounded-full text-red-500" fiatBalancesRefs={data.fiatBalances}
onClick={handleMaxFiatDockButton}
>
Max
</button>
</>
) : (
<>
<input
className={cx(inputBaseStyles)}
type="number"
value={cryptoDock}
onChange={handleCryptoAmountChange}
/> />
<button
type="button"
disabled={avaliableCrypto.isEqualTo(cryptoDock)}
className="flex items-center mb-3 ml-3 font-bold rounded-full text-red-500"
onClick={handleMaxCryptoButton}
>
Max
</button>
</>
)} )}
</div> </div>
<button
className="cursor-pointer py-2 px-4 bg-blue-600 hover:bg-blue-700 focus:ring-blue-500 focus:ring-offset-blue-200 text-white w-full transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg"
type="submit"
>
{exchangeOption === "BUY" ? "Comprar" : "Vender"} CAKE
</button>
</form>
</div>
</div>
); );
}; };

View File

@@ -0,0 +1,165 @@
import { graphql } from "babel-plugin-relay/macro";
import type { FC } from "react";
import React from "react";
import { useFragment } from "react-relay";
import { centsToUnit } from "../../../../utils/fiatMoney";
import type { CryptoExchangeOrderProps } from "./components/CryptoExchangeOrder";
import { CryptoExchangeOrder } from "./components/CryptoExchangeOrder";
import type {
ExchangeHistory_buyCryptoOrders$key,
ProcessStatus,
} from "./__generated__/ExchangeHistory_buyCryptoOrders.graphql";
import type { ExchangeHistory_sellCryptoOrders$key } from "./__generated__/ExchangeHistory_sellCryptoOrders.graphql";
type Props = {
buyCryptoOrdersRefs: ExchangeHistory_buyCryptoOrders$key;
sellCryptoOrdersRefs: ExchangeHistory_sellCryptoOrders$key;
};
type SellOrBuyOrder = {
readonly node: {
readonly id: string;
readonly status: ProcessStatus;
readonly paidAmount: string;
readonly receivedAmountCents: number | null;
readonly createdAt: unknown;
readonly paidAmountCents: number;
readonly receivedAmount: string | null;
readonly currency: {
readonly name: string;
};
readonly __typename: string;
};
};
export const ExchangeHistory: FC<Props> = ({
buyCryptoOrdersRefs,
sellCryptoOrdersRefs,
}) => {
const buyCryptoOrders = useFragment<ExchangeHistory_buyCryptoOrders$key>(
graphql`
fragment ExchangeHistory_buyCryptoOrders on BuyCryptoOrderConnection {
edges {
node {
id
status
createdAt
paidAmountCents
receivedAmount
currency {
name
}
__typename
}
}
}
`,
buyCryptoOrdersRefs
);
const sellCryptoOrders = useFragment<ExchangeHistory_sellCryptoOrders$key>(
graphql`
fragment ExchangeHistory_sellCryptoOrders on SellCryptoOrderConnection {
edges {
node {
id
status
paidAmount
receivedAmountCents
createdAt
currency {
name
}
__typename
}
}
}
`,
sellCryptoOrdersRefs
);
const allResults = [...buyCryptoOrders.edges, ...sellCryptoOrders.edges];
const allResultsOrdeneds = allResults.sort((item1, item2) => {
return (
new Date(item1.node.createdAt as string).getTime() -
new Date(item2.node.createdAt as string).getTime()
);
}) as SellOrBuyOrder[];
const orderRows: Array<(CryptoExchangeOrderProps & { id: string }) | null> =
allResultsOrdeneds.map((edge) => {
const node = edge?.node;
if (node?.__typename === "SellCryptoOrder") {
return {
id: node.id,
payed: `${node.paidAmount} ${node.currency.name}`,
received: `${centsToUnit(node.receivedAmountCents)} BRL`,
createdAt: new Date(node.createdAt as string).toLocaleString(),
kind: node.__typename,
status: node.status,
};
}
if (node?.__typename === "BuyCryptoOrder") {
return {
id: node.id,
payed: `${centsToUnit(node.paidAmountCents)} BRL`,
received: `${node.receivedAmount} ${node.currency.name}`,
createdAt: new Date(node.createdAt as string).toLocaleString(),
kind: node.__typename,
status: node.status,
};
}
return null;
});
return (
<div className="container mx-auto px-4 sm:px-8">
<div className="py-8">
<div className="-mx-4 sm:-mx-8 px-4 sm:px-8 py-4 overflow-x-auto">
<div className="inline-block min-w-full shadow rounded-lg overflow-hidden">
<table className="min-w-full leading-normal">
<thead>
<tr>
<th
scope="col"
className="px-5 py-3 bg-white border-b border-gray-200 text-gray-800 text-left text-sm uppercase font-normal"
>
Valor pago
</th>
<th
scope="col"
className="px-5 py-3 bg-white border-b border-gray-200 text-gray-800 text-left text-sm uppercase font-normal"
>
Valor recebido
</th>
<th
scope="col"
className="px-5 py-3 bg-white border-b border-gray-200 text-gray-800 text-left text-sm uppercase font-normal"
>
Criado em
</th>
<th
scope="col"
className="px-5 py-3 bg-white border-b border-gray-200 text-gray-800 text-left text-sm uppercase font-normal"
>
Status
</th>
</tr>
</thead>
<tbody>
{orderRows.map((order) => {
return <CryptoExchangeOrder key={order?.id} {...order} />;
})}
</tbody>
</table>
</div>
</div>
</div>
</div>
);
};

View File

@@ -0,0 +1,125 @@
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from "relay-runtime";
import { FragmentRefs } from "relay-runtime";
export type ProcessStatus = "CANCELED" | "COMPLETED" | "PROCESSING" | "%future added value";
export type ExchangeHistory_buyCryptoOrders = {
readonly edges: ReadonlyArray<{
readonly node: {
readonly id: string;
readonly status: ProcessStatus;
readonly createdAt: unknown;
readonly paidAmountCents: number;
readonly receivedAmount: string | null;
readonly currency: {
readonly name: string;
};
readonly __typename: string;
};
}>;
readonly " $refType": "ExchangeHistory_buyCryptoOrders";
};
export type ExchangeHistory_buyCryptoOrders$data = ExchangeHistory_buyCryptoOrders;
export type ExchangeHistory_buyCryptoOrders$key = {
readonly " $data"?: ExchangeHistory_buyCryptoOrders$data;
readonly " $fragmentRefs": FragmentRefs<"ExchangeHistory_buyCryptoOrders">;
};
const node: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "ExchangeHistory_buyCryptoOrders",
"selections": [
{
"alias": null,
"args": null,
"concreteType": "BuyCryptoOrderEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "BuyCryptoOrder",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "status",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "paidAmountCents",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "receivedAmount",
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "Currency",
"kind": "LinkedField",
"name": "currency",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "name",
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
],
"type": "BuyCryptoOrderConnection",
"abstractKey": null
};
(node as any).hash = 'da0e93160594d0e07defe123a9bd755b';
export default node;

View File

@@ -0,0 +1,125 @@
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from "relay-runtime";
import { FragmentRefs } from "relay-runtime";
export type ProcessStatus = "CANCELED" | "COMPLETED" | "PROCESSING" | "%future added value";
export type ExchangeHistory_sellCryptoOrders = {
readonly edges: ReadonlyArray<{
readonly node: {
readonly id: string;
readonly status: ProcessStatus;
readonly paidAmount: string;
readonly receivedAmountCents: number | null;
readonly createdAt: unknown;
readonly currency: {
readonly name: string;
};
readonly __typename: string;
};
}>;
readonly " $refType": "ExchangeHistory_sellCryptoOrders";
};
export type ExchangeHistory_sellCryptoOrders$data = ExchangeHistory_sellCryptoOrders;
export type ExchangeHistory_sellCryptoOrders$key = {
readonly " $data"?: ExchangeHistory_sellCryptoOrders$data;
readonly " $fragmentRefs": FragmentRefs<"ExchangeHistory_sellCryptoOrders">;
};
const node: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "ExchangeHistory_sellCryptoOrders",
"selections": [
{
"alias": null,
"args": null,
"concreteType": "SellCryptoOrderEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "SellCryptoOrder",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "status",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "paidAmount",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "receivedAmountCents",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "Currency",
"kind": "LinkedField",
"name": "currency",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "name",
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
],
"type": "SellCryptoOrderConnection",
"abstractKey": null
};
(node as any).hash = '384d1326525240c150d450555796a621';
export default node;

View File

@@ -0,0 +1,61 @@
import type { FC } from "react";
import React from "react";
import cx from "classnames";
import type { ProcessStatus } from "../__generated__/ExchangeHistory_buyCryptoOrders.graphql";
export type CryptoExchangeOrderProps = {
payed?: string;
received?: string;
status?: ProcessStatus;
createdAt?: string;
};
const getStatusTextAndColors = (status: ProcessStatus) => {
if (status === "PROCESSING") {
return ["Processando", "text-yellow-900", "bg-yellow-200"];
}
if (status === "CANCELED") {
return ["Cancelado", "text-red-900", "bg-red-200"];
}
return ["Completado", "text-green-900", "bg-green-200"];
};
export const CryptoExchangeOrder: FC<CryptoExchangeOrderProps> = ({
createdAt = "",
payed = "",
received = "",
status = "PROCESSING",
}) => {
const [label, textStyles, bgStyles] = getStatusTextAndColors(status);
return (
<tr>
<td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">
<p className="text-gray-900 whitespace-nowrap">{payed}</p>
</td>
<td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">
<p className="text-gray-900 whitespace-nowrap">{received}</p>
</td>
<td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">
<p className="text-gray-900 whitespace-nowrap">{createdAt}</p>
</td>
<td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">
<span
className={cx(
"relative inline-block px-3 py-1 font-semibold text-red-900 leading-tight",
textStyles
)}
>
<span
aria-hidden="true"
className={cx("absolute inset-0 opacity-50 rounded-full", bgStyles)}
/>
<span className="relative">{label}</span>
</span>
</td>
</tr>
);
};

View File

@@ -0,0 +1,78 @@
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from "relay-runtime";
import { FragmentRefs } from "relay-runtime";
export type ProcessStatus = "CANCELED" | "COMPLETED" | "PROCESSING" | "%future added value";
export type SellOrder_order = {
readonly id: string;
readonly status: ProcessStatus;
readonly paidAmount: string;
readonly receivedAmountCents: number | null;
readonly createdAt: unknown;
readonly __typename: "SellCryptoOrder";
readonly " $refType": "SellOrder_order";
};
export type SellOrder_order$data = SellOrder_order;
export type SellOrder_order$key = {
readonly " $data"?: SellOrder_order$data;
readonly " $fragmentRefs": FragmentRefs<"SellOrder_order">;
};
const node: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "SellOrder_order",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "status",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "paidAmount",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "receivedAmountCents",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
}
],
"type": "SellCryptoOrder",
"abstractKey": null
};
(node as any).hash = 'f621be85ef9b711e1c720d4fc07187c7';
export default node;

View File

@@ -0,0 +1 @@
export * from "./ExchangeHistory";

View File

@@ -3,21 +3,20 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from "relay-runtime"; import { ConcreteRequest } from "relay-runtime";
import { FragmentRefs } from "relay-runtime";
export type ExchangeQueryVariables = {}; export type ExchangeQueryVariables = {};
export type ExchangeQueryResponse = { export type ExchangeQueryResponse = {
readonly fiatBalances: { readonly fiatBalances: {
readonly edges: ReadonlyArray<{ readonly " $fragmentRefs": FragmentRefs<"CreateExchangeOrderModal_fiatBalances">;
readonly node: {
readonly amountCents: number;
};
}>;
}; };
readonly balances: { readonly balances: {
readonly edges: ReadonlyArray<{ readonly " $fragmentRefs": FragmentRefs<"CreateExchangeOrderModal_balances">;
readonly node: {
readonly amount: string;
}; };
}>; readonly buyCryptoOrders: {
readonly " $fragmentRefs": FragmentRefs<"ExchangeHistory_buyCryptoOrders">;
};
readonly sellCryptoOrders: {
readonly " $fragmentRefs": FragmentRefs<"ExchangeHistory_sellCryptoOrders">;
}; };
}; };
export type ExchangeQuery = { export type ExchangeQuery = {
@@ -30,6 +29,29 @@ export type ExchangeQuery = {
/* /*
query ExchangeQuery { query ExchangeQuery {
fiatBalances { fiatBalances {
...CreateExchangeOrderModal_fiatBalances
}
balances {
...CreateExchangeOrderModal_balances
}
buyCryptoOrders {
...ExchangeHistory_buyCryptoOrders
}
sellCryptoOrders {
...ExchangeHistory_sellCryptoOrders
}
}
fragment CreateExchangeOrderModal_balances on BalanceConnection {
edges {
node {
amount
id
}
}
}
fragment CreateExchangeOrderModal_fiatBalances on FiatBalanceConnection {
edges { edges {
node { node {
amountCents amountCents
@@ -37,12 +59,37 @@ query ExchangeQuery {
} }
} }
} }
balances {
fragment ExchangeHistory_buyCryptoOrders on BuyCryptoOrderConnection {
edges { edges {
node { node {
amount id
status
createdAt
paidAmountCents
receivedAmount
currency {
name
id id
} }
__typename
}
}
}
fragment ExchangeHistory_sellCryptoOrders on SellCryptoOrderConnection {
edges {
node {
id
status
paidAmount
receivedAmountCents
createdAt
currency {
name
id
}
__typename
} }
} }
} }
@@ -53,21 +100,47 @@ var v0 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "amountCents", "name": "id",
"storageKey": null "storageKey": null
}, },
v1 = { v1 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "amount", "name": "status",
"storageKey": null "storageKey": null
}, },
v2 = { v2 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "id", "name": "createdAt",
"storageKey": null
},
v3 = {
"alias": null,
"args": null,
"concreteType": "Currency",
"kind": "LinkedField",
"name": "currency",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "name",
"storageKey": null
},
(v0/*: any*/)
],
"storageKey": null
},
v4 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null "storageKey": null
}; };
return { return {
@@ -86,27 +159,9 @@ return {
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
"alias": null,
"args": null, "args": null,
"concreteType": "FiatBalanceEdge", "kind": "FragmentSpread",
"kind": "LinkedField", "name": "CreateExchangeOrderModal_fiatBalances"
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "FiatBalance",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v0/*: any*/)
],
"storageKey": null
}
],
"storageKey": null
} }
], ],
"storageKey": null "storageKey": null
@@ -120,27 +175,41 @@ return {
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
"alias": null,
"args": null, "args": null,
"concreteType": "BalanceEdge", "kind": "FragmentSpread",
"kind": "LinkedField", "name": "CreateExchangeOrderModal_balances"
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Balance",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v1/*: any*/)
],
"storageKey": null
} }
], ],
"storageKey": null "storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "BuyCryptoOrderConnection",
"kind": "LinkedField",
"name": "buyCryptoOrders",
"plural": false,
"selections": [
{
"args": null,
"kind": "FragmentSpread",
"name": "ExchangeHistory_buyCryptoOrders"
}
],
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "SellCryptoOrderConnection",
"kind": "LinkedField",
"name": "sellCryptoOrders",
"plural": false,
"selections": [
{
"args": null,
"kind": "FragmentSpread",
"name": "ExchangeHistory_sellCryptoOrders"
} }
], ],
"storageKey": null "storageKey": null
@@ -179,8 +248,14 @@ return {
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v0/*: any*/), {
(v2/*: any*/) "alias": null,
"args": null,
"kind": "ScalarField",
"name": "amountCents",
"storageKey": null
},
(v0/*: any*/)
], ],
"storageKey": null "storageKey": null
} }
@@ -214,8 +289,118 @@ return {
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "amount",
"storageKey": null
},
(v0/*: any*/)
],
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "BuyCryptoOrderConnection",
"kind": "LinkedField",
"name": "buyCryptoOrders",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "BuyCryptoOrderEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "BuyCryptoOrder",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v0/*: any*/),
(v1/*: any*/), (v1/*: any*/),
(v2/*: any*/) (v2/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "paidAmountCents",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "receivedAmount",
"storageKey": null
},
(v3/*: any*/),
(v4/*: any*/)
],
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "SellCryptoOrderConnection",
"kind": "LinkedField",
"name": "sellCryptoOrders",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "SellCryptoOrderEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "SellCryptoOrder",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v0/*: any*/),
(v1/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "paidAmount",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "receivedAmountCents",
"storageKey": null
},
(v2/*: any*/),
(v3/*: any*/),
(v4/*: any*/)
], ],
"storageKey": null "storageKey": null
} }
@@ -228,14 +413,14 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "bb1b8283beba2daf38bacec716816383", "cacheID": "ddb6670ea93a9fdc62c7627c3ed09925",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "ExchangeQuery", "name": "ExchangeQuery",
"operationKind": "query", "operationKind": "query",
"text": "query ExchangeQuery {\n fiatBalances {\n edges {\n node {\n amountCents\n id\n }\n }\n }\n balances {\n edges {\n node {\n amount\n id\n }\n }\n }\n}\n" "text": "query ExchangeQuery {\n fiatBalances {\n ...CreateExchangeOrderModal_fiatBalances\n }\n balances {\n ...CreateExchangeOrderModal_balances\n }\n buyCryptoOrders {\n ...ExchangeHistory_buyCryptoOrders\n }\n sellCryptoOrders {\n ...ExchangeHistory_sellCryptoOrders\n }\n}\n\nfragment CreateExchangeOrderModal_balances on BalanceConnection {\n edges {\n node {\n amount\n id\n }\n }\n}\n\nfragment CreateExchangeOrderModal_fiatBalances on FiatBalanceConnection {\n edges {\n node {\n amountCents\n id\n }\n }\n}\n\nfragment ExchangeHistory_buyCryptoOrders on BuyCryptoOrderConnection {\n edges {\n node {\n id\n status\n createdAt\n paidAmountCents\n receivedAmount\n currency {\n name\n id\n }\n __typename\n }\n }\n}\n\nfragment ExchangeHistory_sellCryptoOrders on SellCryptoOrderConnection {\n edges {\n node {\n id\n status\n paidAmount\n receivedAmountCents\n createdAt\n currency {\n name\n id\n }\n __typename\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = '517d3bf7bc6330021f8eb615e78417f5'; (node as any).hash = 'cc0eaddc68f5bd14d39ce9e148876535';
export default node; export default node;

View File

@@ -2,12 +2,19 @@ import BigNumber from "bignumber.js";
import { BLOCKS_PER_YEAR } from "../constants"; import { BLOCKS_PER_YEAR } from "../constants";
export const getApr = ( type Props = {
stakingTokenPrice: number, stakingTokenPrice: number;
rewardTokenPrice: number, rewardTokenPrice: number;
totalStaked: number, totalStaked: number;
tokenPerBlock: number tokenPerBlock: number;
) => { };
export const getApr = ({
rewardTokenPrice,
stakingTokenPrice,
tokenPerBlock,
totalStaked,
}: Props) => {
const totalRewardPricePerYear = new BigNumber(rewardTokenPrice) const totalRewardPricePerYear = new BigNumber(rewardTokenPrice)
.times(tokenPerBlock) .times(tokenPerBlock)
.times(BLOCKS_PER_YEAR); .times(BLOCKS_PER_YEAR);

View File

@@ -0,0 +1,5 @@
export const centsToUnit = (value?: number | null) => {
if (!value) return "0.00";
return (value / 100).toFixed(2);
};

View File

@@ -31,6 +31,7 @@
"bignumber.js": "^9.0.1", "bignumber.js": "^9.0.1",
"classnames": "^2.3.1", "classnames": "^2.3.1",
"ethers": "^5.4.4", "ethers": "^5.4.4",
"graphql-scalars": "^1.10.0",
"postcss": "^7", "postcss": "^7",
"ramda": "^0.27.1", "ramda": "^0.27.1",
"react": "^17.0.2", "react": "^17.0.2",

12
yarn.lock generated
View File

@@ -4673,6 +4673,13 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
graphql-scalars@^1.10.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/graphql-scalars/-/graphql-scalars-1.10.0.tgz#9daf9252b16e6fae553a06976163a23f41b65dfd"
integrity sha512-LONlj8FfhA2iGpkZJWf5e4PVAHXxnZEHSOEvowLYvNXl/TNnhIck8VmE+lren/aa6GKrG+lZufo5lgnyjxcF6g==
dependencies:
tslib "~2.2.0"
"graphql@^14.0.0 || ^15.0.0", graphql@^15.5.1: "graphql@^14.0.0 || ^15.0.0", graphql@^15.5.1:
version "15.5.1" version "15.5.1"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.1.tgz#f2f84415d8985e7b84731e7f3536f8bb9d383aad" resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.1.tgz#f2f84415d8985e7b84731e7f3536f8bb9d383aad"
@@ -8912,6 +8919,11 @@ tslib@^1.8.1:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@~2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c"
integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==
tsutils@^3.21.0: tsutils@^3.21.0:
version "3.21.0" version "3.21.0"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"