From 64bc21195c2f48e968d8ea4cbe404b0d9d086c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Sun, 15 Aug 2021 18:02:06 -0300 Subject: [PATCH] add sell and buy orders list --- app/javascript/src/components/Poo.tsx | 12 +- .../CreateExchangeOrderModal.tsx | 187 ++++++++++ ...eateExchangeOrderModal_balances.graphql.ts | 63 ++++ ...ExchangeOrderModal_fiatBalances.graphql.ts | 63 ++++ .../CreateExchangeOrderModel/index.ts | 1 + .../src/pages/Orders/Exchange/Exchange.tsx | 181 ++-------- .../ExchangeHistory/ExchangeHistory.tsx | 165 +++++++++ ...ExchangeHistory_buyCryptoOrders.graphql.ts | 125 +++++++ ...xchangeHistory_sellCryptoOrders.graphql.ts | 125 +++++++ .../components/CryptoExchangeOrder.tsx | 61 ++++ .../__generated__/SellOrder_order.graphql.ts | 78 +++++ .../Orders/Exchange/ExchangeHistory/index.ts | 1 + .../__generated__/ExchangeQuery.graphql.ts | 321 ++++++++++++++---- app/javascript/src/utils/apr.ts | 19 +- app/javascript/src/utils/fiatMoney.ts | 5 + package.json | 1 + yarn.lock | 12 + 17 files changed, 1185 insertions(+), 235 deletions(-) create mode 100644 app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/CreateExchangeOrderModal.tsx create mode 100644 app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/__generated__/CreateExchangeOrderModal_balances.graphql.ts create mode 100644 app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/__generated__/CreateExchangeOrderModal_fiatBalances.graphql.ts create mode 100644 app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/index.ts create mode 100644 app/javascript/src/pages/Orders/Exchange/ExchangeHistory/ExchangeHistory.tsx create mode 100644 app/javascript/src/pages/Orders/Exchange/ExchangeHistory/__generated__/ExchangeHistory_buyCryptoOrders.graphql.ts create mode 100644 app/javascript/src/pages/Orders/Exchange/ExchangeHistory/__generated__/ExchangeHistory_sellCryptoOrders.graphql.ts create mode 100644 app/javascript/src/pages/Orders/Exchange/ExchangeHistory/components/CryptoExchangeOrder.tsx create mode 100644 app/javascript/src/pages/Orders/Exchange/ExchangeHistory/components/__generated__/SellOrder_order.graphql.ts create mode 100644 app/javascript/src/pages/Orders/Exchange/ExchangeHistory/index.ts create mode 100644 app/javascript/src/utils/fiatMoney.ts diff --git a/app/javascript/src/components/Poo.tsx b/app/javascript/src/components/Poo.tsx index d6254b5..78fe2ba 100644 --- a/app/javascript/src/components/Poo.tsx +++ b/app/javascript/src/components/Poo.tsx @@ -38,12 +38,12 @@ export const Pool = ({ pool }: PoolProps) => { }: ${JSON.stringify(totalStaked)}` ); - const aprValue = getApr( - stakingPrice, - earningPrice, - totalStaked, - parseFloat(pool.tokenPerBlock) / 1e-18 - ); + const aprValue = getApr({ + rewardTokenPrice: stakingPrice, + stakingTokenPrice: earningPrice, + tokenPerBlock: totalStaked, + totalStaked: parseFloat(pool.tokenPerBlock) / 1e-18, + }); if (aprValue) { setApr({ diff --git a/app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/CreateExchangeOrderModal.tsx b/app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/CreateExchangeOrderModal.tsx new file mode 100644 index 0000000..01f34ed --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/CreateExchangeOrderModal.tsx @@ -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 = ({ + fiatBalancesRefs, + balancesRefs, +}) => { + const { isAuthenticated } = useCurrentUser(); + const [exchangeOption, setExchangeOption] = useState<"BUY" | "SELL">("BUY"); + const [cryptoDock, setCryptoDock] = useState("0"); + const [fiatDock, setFiatDock] = useState("0.00"); + + const fiatBalances = useFragment( + graphql` + fragment CreateExchangeOrderModal_fiatBalances on FiatBalanceConnection { + edges { + node { + amountCents + } + } + } + `, + fiatBalancesRefs + ); + + const balances = useFragment( + graphql` + fragment CreateExchangeOrderModal_balances on BalanceConnection { + edges { + node { + amount + } + } + } + `, + balancesRefs + ); + + if (!isAuthenticated) return ; + 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) => { + const newCryptoAmount = new BigNumber(value); + + if (newCryptoAmount.isLessThanOrEqualTo(avaliableCrypto)) { + setCryptoDock(value); + } + }; + + const handleFiatAmountChange = ({ + currentTarget: { value }, + }: React.ChangeEvent) => { + const newFiatAmount = Number(value); + + if (Number(avaliableFiat) >= newFiatAmount) { + setFiatDock(value); + } + }; + + const handleMaxFiatDockButton = () => { + setFiatDock(avaliableFiat); + }; + + const handleMaxCryptoButton = () => { + setCryptoDock(avaliableCrypto.toString()); + }; + + return ( +
+
+ + +
+
+ + {exchangeOption === "SELL" ? "CAKE" : "BRL"} disponível:{" "} + {exchangeOption === "SELL" ? crypto.node.amount : avaliableFiat} + +
+ {exchangeOption === "BUY" ? ( + <> + + + + ) : ( + <> + + + + )} +
+ + +
+
+ ); +}; diff --git a/app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/__generated__/CreateExchangeOrderModal_balances.graphql.ts b/app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/__generated__/CreateExchangeOrderModal_balances.graphql.ts new file mode 100644 index 0000000..39b1fbd --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/__generated__/CreateExchangeOrderModal_balances.graphql.ts @@ -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; diff --git a/app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/__generated__/CreateExchangeOrderModal_fiatBalances.graphql.ts b/app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/__generated__/CreateExchangeOrderModal_fiatBalances.graphql.ts new file mode 100644 index 0000000..4a7860d --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/__generated__/CreateExchangeOrderModal_fiatBalances.graphql.ts @@ -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; diff --git a/app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/index.ts b/app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/index.ts new file mode 100644 index 0000000..a8e24d2 --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/CreateExchangeOrderModel/index.ts @@ -0,0 +1 @@ +export * from "./CreateExchangeOrderModal"; diff --git a/app/javascript/src/pages/Orders/Exchange/Exchange.tsx b/app/javascript/src/pages/Orders/Exchange/Exchange.tsx index 296128b..c2a04ff 100644 --- a/app/javascript/src/pages/Orders/Exchange/Exchange.tsx +++ b/app/javascript/src/pages/Orders/Exchange/Exchange.tsx @@ -1,176 +1,47 @@ -import React, { useState } from "react"; -import type { FC } from "react"; +/* eslint-disable relay/must-colocate-fragment-spreads */ import { graphql } from "babel-plugin-relay/macro"; +import React, { useState } from "react"; import { useLazyLoadQuery } from "react-relay"; -import { BigNumber } from "bignumber.js"; -import cx from "classnames"; -import { useCurrentUser } from "../../../contexts/UserProvider"; -import { Unauthenticated } from "../../../messages/Unauthenticated"; +import { CreateExchangeOrderModal } from "./CreateExchangeOrderModel"; +import { ExchangeHistory } from "./ExchangeHistory"; import type { ExchangeQuery } from "./__generated__/ExchangeQuery.graphql"; -const tabBaseStyles = - "w-full text-base font-bold text-black px-4 py-2 focus:ring-blue-500"; +export const Exchange = () => { + const [modelOpen] = useState(false); -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"; - -export const Exchange: FC = () => { - const { isAuthenticated } = useCurrentUser(); - const [exchangeOption, setExchangeOption] = useState<"BUY" | "SELL">("BUY"); - const [cryptoDock, setCryptoDock] = useState("0"); - const [fiatDock, setFiatDock] = useState("0.00"); - - const { balances, fiatBalances } = useLazyLoadQuery( + const data = useLazyLoadQuery( graphql` query ExchangeQuery { fiatBalances { - edges { - node { - amountCents - } - } + ...CreateExchangeOrderModal_fiatBalances } balances { - edges { - node { - amount - } - } + ...CreateExchangeOrderModal_balances + } + buyCryptoOrders { + ...ExchangeHistory_buyCryptoOrders + } + sellCryptoOrders { + ...ExchangeHistory_sellCryptoOrders } } `, {} ); - if (!isAuthenticated) return ; - 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) => { - const newCryptoAmount = new BigNumber(value); - - if (newCryptoAmount.isLessThanOrEqualTo(avaliableCrypto)) { - setCryptoDock(value); - } - }; - - const handleFiatAmountChange = ({ - currentTarget: { value }, - }: React.ChangeEvent) => { - const newFiatAmount = Number(value); - - if (Number(avaliableFiat) >= newFiatAmount) { - setFiatDock(value); - } - }; - - const handleMaxFiatDockButton = () => { - setFiatDock(avaliableFiat); - }; - - const handleMaxCryptoButton = () => { - setCryptoDock(avaliableCrypto.toString()); - }; - return ( -
-
-
- - -
-
- - {exchangeOption === "SELL" ? "CAKE" : "BRL"} disponível:{" "} - {exchangeOption === "SELL" ? crypto.node.amount : avaliableFiat} - -
- {exchangeOption === "BUY" ? ( - <> - - - - ) : ( - <> - - - - )} -
- - -
-
+
+ + {modelOpen && ( + + )}
); }; diff --git a/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/ExchangeHistory.tsx b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/ExchangeHistory.tsx new file mode 100644 index 0000000..f0660c0 --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/ExchangeHistory.tsx @@ -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 = ({ + buyCryptoOrdersRefs, + sellCryptoOrdersRefs, +}) => { + const buyCryptoOrders = useFragment( + graphql` + fragment ExchangeHistory_buyCryptoOrders on BuyCryptoOrderConnection { + edges { + node { + id + status + createdAt + paidAmountCents + receivedAmount + currency { + name + } + __typename + } + } + } + `, + buyCryptoOrdersRefs + ); + + const sellCryptoOrders = useFragment( + 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 ( +
+
+
+
+ + + + + + + + + + + {orderRows.map((order) => { + return ; + })} + +
+ Valor pago + + Valor recebido + + Criado em + + Status +
+
+
+
+
+ ); +}; diff --git a/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/__generated__/ExchangeHistory_buyCryptoOrders.graphql.ts b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/__generated__/ExchangeHistory_buyCryptoOrders.graphql.ts new file mode 100644 index 0000000..f84084c --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/__generated__/ExchangeHistory_buyCryptoOrders.graphql.ts @@ -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; diff --git a/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/__generated__/ExchangeHistory_sellCryptoOrders.graphql.ts b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/__generated__/ExchangeHistory_sellCryptoOrders.graphql.ts new file mode 100644 index 0000000..20022fb --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/__generated__/ExchangeHistory_sellCryptoOrders.graphql.ts @@ -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; diff --git a/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/components/CryptoExchangeOrder.tsx b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/components/CryptoExchangeOrder.tsx new file mode 100644 index 0000000..f8c56bc --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/components/CryptoExchangeOrder.tsx @@ -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 = ({ + createdAt = "", + payed = "", + received = "", + status = "PROCESSING", +}) => { + const [label, textStyles, bgStyles] = getStatusTextAndColors(status); + + return ( + + +

{payed}

+ + +

{received}

+ + +

{createdAt}

+ + + + + + + ); +}; diff --git a/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/components/__generated__/SellOrder_order.graphql.ts b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/components/__generated__/SellOrder_order.graphql.ts new file mode 100644 index 0000000..a53652f --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/components/__generated__/SellOrder_order.graphql.ts @@ -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; diff --git a/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/index.ts b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/index.ts new file mode 100644 index 0000000..0bd18db --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/index.ts @@ -0,0 +1 @@ +export * from "./ExchangeHistory"; diff --git a/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts b/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts index bab9853..6d55f20 100644 --- a/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts +++ b/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts @@ -3,21 +3,20 @@ // @ts-nocheck import { ConcreteRequest } from "relay-runtime"; +import { FragmentRefs } from "relay-runtime"; export type ExchangeQueryVariables = {}; export type ExchangeQueryResponse = { readonly fiatBalances: { - readonly edges: ReadonlyArray<{ - readonly node: { - readonly amountCents: number; - }; - }>; + readonly " $fragmentRefs": FragmentRefs<"CreateExchangeOrderModal_fiatBalances">; }; readonly balances: { - readonly edges: ReadonlyArray<{ - readonly node: { - readonly amount: string; - }; - }>; + readonly " $fragmentRefs": FragmentRefs<"CreateExchangeOrderModal_balances">; + }; + readonly buyCryptoOrders: { + readonly " $fragmentRefs": FragmentRefs<"ExchangeHistory_buyCryptoOrders">; + }; + readonly sellCryptoOrders: { + readonly " $fragmentRefs": FragmentRefs<"ExchangeHistory_sellCryptoOrders">; }; }; export type ExchangeQuery = { @@ -30,19 +29,67 @@ export type ExchangeQuery = { /* query ExchangeQuery { fiatBalances { - edges { - node { - amountCents - id - } - } + ...CreateExchangeOrderModal_fiatBalances } balances { - edges { - node { - amount + ...CreateExchangeOrderModal_balances + } + buyCryptoOrders { + ...ExchangeHistory_buyCryptoOrders + } + sellCryptoOrders { + ...ExchangeHistory_sellCryptoOrders + } +} + +fragment CreateExchangeOrderModal_balances on BalanceConnection { + edges { + node { + amount + id + } + } +} + +fragment CreateExchangeOrderModal_fiatBalances on FiatBalanceConnection { + edges { + node { + amountCents + id + } + } +} + +fragment ExchangeHistory_buyCryptoOrders on BuyCryptoOrderConnection { + edges { + node { + id + status + createdAt + paidAmountCents + receivedAmount + currency { + name 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, "args": null, "kind": "ScalarField", - "name": "amountCents", + "name": "id", "storageKey": null }, v1 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "amount", + "name": "status", "storageKey": null }, v2 = { "alias": null, "args": null, "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 }; return { @@ -86,27 +159,9 @@ return { "plural": false, "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": [ - (v0/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null + "kind": "FragmentSpread", + "name": "CreateExchangeOrderModal_fiatBalances" } ], "storageKey": null @@ -120,27 +175,41 @@ return { "plural": false, "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": [ - (v1/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null + "kind": "FragmentSpread", + "name": "CreateExchangeOrderModal_balances" + } + ], + "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 @@ -179,8 +248,14 @@ return { "name": "node", "plural": false, "selections": [ - (v0/*: any*/), - (v2/*: any*/) + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "amountCents", + "storageKey": null + }, + (v0/*: any*/) ], "storageKey": null } @@ -214,8 +289,118 @@ return { "name": "node", "plural": false, "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*/), - (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 } @@ -228,14 +413,14 @@ return { ] }, "params": { - "cacheID": "bb1b8283beba2daf38bacec716816383", + "cacheID": "ddb6670ea93a9fdc62c7627c3ed09925", "id": null, "metadata": {}, "name": "ExchangeQuery", "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; diff --git a/app/javascript/src/utils/apr.ts b/app/javascript/src/utils/apr.ts index 295d5ab..ade13c0 100644 --- a/app/javascript/src/utils/apr.ts +++ b/app/javascript/src/utils/apr.ts @@ -2,12 +2,19 @@ import BigNumber from "bignumber.js"; import { BLOCKS_PER_YEAR } from "../constants"; -export const getApr = ( - stakingTokenPrice: number, - rewardTokenPrice: number, - totalStaked: number, - tokenPerBlock: number -) => { +type Props = { + stakingTokenPrice: number; + rewardTokenPrice: number; + totalStaked: number; + tokenPerBlock: number; +}; + +export const getApr = ({ + rewardTokenPrice, + stakingTokenPrice, + tokenPerBlock, + totalStaked, +}: Props) => { const totalRewardPricePerYear = new BigNumber(rewardTokenPrice) .times(tokenPerBlock) .times(BLOCKS_PER_YEAR); diff --git a/app/javascript/src/utils/fiatMoney.ts b/app/javascript/src/utils/fiatMoney.ts new file mode 100644 index 0000000..0f5bccb --- /dev/null +++ b/app/javascript/src/utils/fiatMoney.ts @@ -0,0 +1,5 @@ +export const centsToUnit = (value?: number | null) => { + if (!value) return "0.00"; + + return (value / 100).toFixed(2); +}; diff --git a/package.json b/package.json index 5c1b748..63ff167 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "bignumber.js": "^9.0.1", "classnames": "^2.3.1", "ethers": "^5.4.4", + "graphql-scalars": "^1.10.0", "postcss": "^7", "ramda": "^0.27.1", "react": "^17.0.2", diff --git a/yarn.lock b/yarn.lock index 175de3a..1cdc4c4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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" 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: version "15.5.1" 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" 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: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"