Skip to content

Commit

Permalink
Add order details links, reset fields on advanced configs close, bala…
Browse files Browse the repository at this point in the history
…nce validation, and add remove draft orders dialog (#56)

* add links on order details and create new text for order hash

* reset fields on advanced settings dialog close

* add validation if balance bigger than sell amount

* handle null price error

* add select all option on draft and open order tables

* refactor get or fetch usd price redability

* fix market price information and fix dialog padding

* remove unused imports

* add draft order delete dialog

* on back to home page preserve order tab

* Add action menu on tables to invert price (#57)

* add action menu on tables to invert price

* run formater and linter

* increase test timeout

---------

Co-authored-by: Pedro Yves Fracari <[email protected]>
Co-authored-by: Pedro Yves Fracari <[email protected]>
  • Loading branch information
3 people authored Jul 16, 2024
1 parent 9438c05 commit 3591dd5
Show file tree
Hide file tree
Showing 31 changed files with 515 additions and 300 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
"clsx": "^2.1.1",
"cmdk": "^0.2.1",
"embla-carousel-react": "8.1.6",
"eslint-plugin-react-compiler": "0.0.0-experimental-0998c1e-20240625",
"gql": "^1.1.2",
"graphql-codegen-plugin-typescript-swr": "^0.8.5",
"graphql-request": "6.1.0",
Expand Down Expand Up @@ -114,6 +113,7 @@
"eslint-plugin-graphql": "latest",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "latest",
"eslint-plugin-react-compiler": "0.0.0-experimental-0998c1e-20240625",
"eslint-plugin-react-hooks": "latest",
"eslint-plugin-simple-import-sort": "latest",
"eslint-plugin-tailwindcss": "^3.17.4",
Expand Down
6 changes: 3 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/app/[chainId]/[safeAddress]/[orderId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Address } from "viem";
import { OrderDetails } from "#/components/OrderDetails";
import { ChainId } from "#/lib/publicClients";

export default async function OrderPage({
export default function OrderPage({
params,
}: {
params: {
Expand Down
9 changes: 8 additions & 1 deletion src/components/AdvancedSettingsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,15 @@ export function AdvancedSettingsDialog() {

const receiver = useWatch({ control, name: "receiver" });

const handleOpenChange = (isOpen: boolean) => {
if (!isOpen) {
reset(advancedSettings);
}
setOpen(isOpen);
};

return (
<Dialog open={open} onOpenChange={setOpen}>
<Dialog open={open} onOpenChange={handleOpenChange}>
<DialogTrigger asChild>
<button
className={cn(areSettingsDifferentFromDefault && "text-primary")}
Expand Down
70 changes: 52 additions & 18 deletions src/components/DraftOrdersTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ import { useTokenPairPrice } from "#/hooks/useTokenPairPrice";
import { getOrderDescription } from "#/lib/orderDescription";
import { DraftOrder } from "#/lib/types";

import { OrderDropdownMenuCell } from "./OrderDropdownMenuCell";
import { RemoveDraftOrdersDialog } from "./RemoveDraftOrdersDialog";
import { ReviewOrdersDialog } from "./ReviewOrdersDialog";

export function DraftOrdersTab() {
const { draftOrders, removeDraftOrders } = useOrder();
const { draftOrders } = useOrder();
const [reviewDialogOpen, setReviewDialogOpen] = useState(false);
const [selectedIds, setSelectedIds] = useState<string[]>([]);

Expand All @@ -41,12 +43,28 @@ export function DraftOrdersTab() {
<TableHeader className="bg-background">
<TableRow>
<TableHead className="rounded-tl-md">
<span className="sr-only">Select</span>
<Checkbox
checked={
selectedIds.length === draftOrders.length &&
!!draftOrders.length
}
disabled={!draftOrders.length}
onCheckedChange={(checked) => {
if (checked) {
setSelectedIds(draftOrders.map((order) => order.id));
return;
}
setSelectedIds([]);
}}
/>
</TableHead>
<TableHead>Order</TableHead>
<TableHead>Trigger price</TableHead>
<TableHead>Limit price</TableHead>
<TableHead className="rounded-tr-md">Current price</TableHead>
<TableHead>Current price</TableHead>
<TableCell className="rounded-tr-md">
<span className="sr-only">Actions</span>
</TableCell>
</TableRow>
</TableHeader>
<TableBody>
Expand All @@ -56,6 +74,7 @@ export function DraftOrdersTab() {
<DraftOrderRow
order={order}
key={order.id}
checked={selectedIds.includes(order.id)}
onSelect={(selected) => {
if (selected) {
setSelectedIds([...selectedIds, order.id]);
Expand All @@ -70,7 +89,7 @@ export function DraftOrdersTab() {
})
) : (
<TableRow>
<TableCell colSpan={5} className="text-center">
<TableCell colSpan={100} className="text-center">
<div className="py-4">
No draft orders. Create a new one to get started.
</div>
Expand All @@ -80,16 +99,10 @@ export function DraftOrdersTab() {
</TableBody>
</Table>
<div className="flex justify-end gap-2">
<Button
variant="destructive"
disabled={!selectedIds.length}
onClick={() => {
removeDraftOrders(selectedIds);
setSelectedIds([]);
}}
>
Delete
</Button>
<RemoveDraftOrdersDialog
selectedIds={selectedIds}
setSelectedIds={setSelectedIds}
/>
<Button
disabled={!selectedIds.length}
onClick={() => {
Expand All @@ -107,10 +120,14 @@ export function DraftOrdersTab() {
export function DraftOrderRow({
order,
onSelect,
checked,
}: {
order: DraftOrder;
checked: boolean;
onSelect: (selected: boolean) => void;
}) {
const [invertedPrice, setInvertedPrice] = useState(false);

const orderDescription = getOrderDescription({
tokenBuy: order.tokenBuy,
tokenSell: order.tokenSell,
Expand All @@ -119,7 +136,9 @@ export function DraftOrderRow({
amountBuy: order.amountBuy,
});

const priceUnity = `${order.tokenBuy.symbol}/${order.tokenSell.symbol}`;
const priceUnity = invertedPrice
? `${order.tokenSell.symbol}/${order.tokenBuy.symbol}`
: order.tokenBuy.symbol + "/" + order.tokenSell.symbol;

const { data: marketPrice } = useTokenPairPrice(
order.tokenSell,
Expand All @@ -130,23 +149,38 @@ export function DraftOrderRow({
<TableRow className="text-xs">
<TableCell>
<Checkbox
checked={checked}
onCheckedChange={(checked) => {
onSelect(checked as boolean);
}}
/>
</TableCell>
<TableCell>{orderDescription}</TableCell>
<TableCell>
{formatNumber(order.strikePrice, 4)} {priceUnity}
{formatNumber(
invertedPrice ? 1 / order.strikePrice : order.strikePrice,
4,
)}{" "}
{priceUnity}
</TableCell>
<TableCell>
{formatNumber(order.limitPrice, 4)} {priceUnity}
{formatNumber(
invertedPrice ? 1 / order.limitPrice : order.limitPrice,
4,
)}{" "}
{priceUnity}
</TableCell>
<TableCell>
{marketPrice
? ` ${formatNumber(marketPrice, 4)} ${priceUnity}`
? ` ${formatNumber(invertedPrice ? 1 / marketPrice : marketPrice, 4)} ${priceUnity}`
: `Market price not found`}
</TableCell>
<OrderDropdownMenuCell
orderId={order.id}
invertedPrice={invertedPrice}
setInvertedPrice={setInvertedPrice}
showDetails={false}
/>
</TableRow>
);
}
39 changes: 26 additions & 13 deletions src/components/HistoryOrdersTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import {
} from "@bleu/ui";
import { useSafeAppsSDK } from "@safe-global/safe-apps-react-sdk";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { formatUnits } from "viem";

import { useOrderList } from "#/hooks/useOrderList";
import { StopLossOrderType } from "#/lib/types";

import { OrderDropdownMenuCell } from "./OrderDropdownMenuCell";
import { StatusBadge } from "./StatusBadge";

export function HistoryOrdersTab() {
Expand All @@ -29,7 +31,10 @@ export function HistoryOrdersTab() {
<TableCell>Order</TableCell>
<TableCell>Trigger price</TableCell>
<TableCell>Filled</TableCell>
<TableCell className="rounded-tr-md">Status</TableCell>
<TableCell>Status</TableCell>
<TableCell className="rounded-tr-md">
<span className="sr-only">Actions</span>
</TableCell>{" "}
</TableHeader>
<TableBody>
{historyOrders.length ? (
Expand All @@ -38,7 +43,7 @@ export function HistoryOrdersTab() {
})
) : (
<TableRow>
<TableCell colSpan={5} className="text-center">
<TableCell colSpan={100} className="text-center">
{isLoading ? (
<Spinner />
) : (
Expand All @@ -57,33 +62,35 @@ export function HistoryOrdersTab() {
export function HistoryOrderRow({ order }: { order: StopLossOrderType }) {
const { safe } = useSafeAppsSDK();
const router = useRouter();
const [invertedPrice, setInvertedPrice] = useState(false);

if (!order.stopLossData) {
return null;
}

const priceUnity =
order.stopLossData.tokenOut.symbol +
"/" +
order.stopLossData.tokenIn.symbol;
const priceUnity = invertedPrice
? `${order.stopLossData.tokenIn.symbol}/${order.stopLossData.tokenOut.symbol}`
: order.stopLossData.tokenOut.symbol +
"/" +
order.stopLossData.tokenIn.symbol;

const triggerPrice = formatUnits(order.stopLossData?.strike, 18);
const triggerPrice = Number(formatUnits(order.stopLossData?.strike, 18));

const amountSell = Number(
formatUnits(
order.stopLossData?.tokenAmountIn,
order.stopLossData.tokenIn.decimals
)
order.stopLossData.tokenIn.decimals,
),
);
const amountBuy = Number(
formatUnits(
order.stopLossData?.tokenAmountOut,
order.stopLossData.tokenOut.decimals
)
order.stopLossData.tokenOut.decimals,
),
);

const orderDateTime = epochToDate(
Number(order.blockTimestamp)
Number(order.blockTimestamp),
).toLocaleString();

return (
Expand All @@ -104,12 +111,18 @@ export function HistoryOrderRow({ order }: { order: StopLossOrderType }) {
</div>
</TableCell>
<TableCell>
{formatNumber(triggerPrice, 4)} {priceUnity}
{formatNumber(invertedPrice ? 1 / triggerPrice : triggerPrice, 4)}{" "}
{priceUnity}
</TableCell>
<TableCell>{((order.filledPct || 0) * 100).toFixed()}%</TableCell>
<TableCell>
<StatusBadge status={order.status} />
</TableCell>
<OrderDropdownMenuCell
orderId={order.id}
invertedPrice={invertedPrice}
setInvertedPrice={setInvertedPrice}
/>
</TableRow>
);
}
Loading

0 comments on commit 3591dd5

Please sign in to comment.