diff --git a/package.json b/package.json index aeaee771..796fdd00 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "dev:docs": "pnpm --filter docs run dev", "dev:website": "pnpm --filter website run dev", "dev:api": "concurrently \"NODE_ENV=development pnpm --filter api run dev:service\" \"NODE_ENV=development pnpm --filter api run dev:worker\"", - "start:reindex-market": "pnpm --filter data run start:reindex-market", - "start:reindex-missing": "pnpm --filter data run start:reindex-missing" + "start:reindex-market": "pnpm --filter api run start:reindex-market", + "start:reindex-missing": "pnpm --filter api run start:reindex-missing" }, "keywords": [], "devDependencies": { diff --git a/packages/app/src/app/resources/[id]/page.tsx b/packages/app/src/app/resources/[id]/page.tsx index 728086d8..ed239883 100644 --- a/packages/app/src/app/resources/[id]/page.tsx +++ b/packages/app/src/app/resources/[id]/page.tsx @@ -10,6 +10,7 @@ import { formatUnits } from 'viem'; import { Card, CardContent } from '@/components/ui/card'; import CandlestickChart from '~/lib/components/chart'; +import { EpochTiming } from '~/lib/components/foil/EpochTiming'; import NumberDisplay from '~/lib/components/foil/numberDisplay'; import { MarketLayout } from '~/lib/components/market/MarketLayout'; import { ResourceNav } from '~/lib/components/market/ResourceNav'; @@ -82,16 +83,10 @@ const EpochsTable = ({ data }: { data: Epoch[] }) => { className={`flex items-center justify-between cursor-pointer px-4 py-1.5 ${hoveredIndex === index ? 'bg-secondary' : 'hover:bg-secondary/50'}`} >
- - Ends {format(new Date(epoch.endTimestamp * 1000), 'M/d')} - - - {Math.round( - (epoch.endTimestamp - epoch.startTimestamp) / - (7 * 24 * 3600) - )}{' '} - week period - +
@@ -174,7 +169,11 @@ const renderPriceDisplay = ( return ( - {unit} + {' '} + {unit} ); }; @@ -236,15 +235,17 @@ const MarketContent = ({ params }: { params: { id: string } }) => { // Get the current resource and its markets const resource = resources?.find((r) => r.slug === params.id); const epochs = - resource?.markets.flatMap((market) => - (market.epochs || []).map((epoch) => ({ - ...epoch, - market: { - address: market.address, - chainId: market.chainId, - }, - })) - ) || []; + resource?.markets + .flatMap((market) => + (market.epochs || []).map((epoch) => ({ + ...epoch, + market: { + address: market.address, + chainId: market.chainId, + }, + })) + ) + .sort((a, b) => b.startTimestamp - a.startTimestamp) || []; const formattedResourcePrices: ResourcePricePoint[] = resourcePrices?.map((price) => ({ diff --git a/packages/app/src/lib/components/chart.tsx b/packages/app/src/lib/components/chart.tsx index 581cce28..4fe07f8a 100644 --- a/packages/app/src/lib/components/chart.tsx +++ b/packages/app/src/lib/components/chart.tsx @@ -90,6 +90,7 @@ const CandlestickChart: React.FC = ({ borderColor: theme === 'dark' ? '#363537' : '#cccccc', timeVisible: true, secondsVisible: false, + minBarSpacing: 0.001, }, }); diff --git a/packages/app/src/lib/components/foil/EpochTiming.tsx b/packages/app/src/lib/components/foil/EpochTiming.tsx new file mode 100644 index 00000000..869351b6 --- /dev/null +++ b/packages/app/src/lib/components/foil/EpochTiming.tsx @@ -0,0 +1,31 @@ +import { format } from 'date-fns'; + +interface EpochTimingProps { + startTimestamp: number; + endTimestamp: number; + showDuration?: boolean; +} + +export const EpochTiming = ({ + startTimestamp, + endTimestamp, + showDuration = true, +}: EpochTimingProps) => { + const now = Math.floor(Date.now() / 1000); + const isStartInFuture = startTimestamp > now; + const date = isStartInFuture ? startTimestamp : endTimestamp; + const prefix = isStartInFuture ? 'Starts' : 'Ends'; + + const weeks = Math.round((endTimestamp - startTimestamp) / (7 * 24 * 3600)); + + return ( + <> + {prefix} {format(new Date(date * 1000), 'M/d')} + {showDuration && ( + + {weeks} week period + + )} + + ); +}; diff --git a/packages/app/src/lib/components/foil/Liquidity/AddEditLiquidity/index.tsx b/packages/app/src/lib/components/foil/Liquidity/AddEditLiquidity/index.tsx index 72b8330e..85d13632 100644 --- a/packages/app/src/lib/components/foil/Liquidity/AddEditLiquidity/index.tsx +++ b/packages/app/src/lib/components/foil/Liquidity/AddEditLiquidity/index.tsx @@ -146,7 +146,9 @@ const AddEditLiquidity: React.FC = () => { const isDecrease = liquidityAction === 'remove' && Number(modifyLiquidity) > 0; - const isAmountUnchanged = Number(modifyLiquidity) === 0; + const isAmountUnchanged = isEdit + ? Number(modifyLiquidity) === 0 + : Number(depositAmount) === 0; /// //// READ CONTRACT HOOKS /////// const { data: positionData, refetch: refetchPosition } = useReadContract({ @@ -640,9 +642,9 @@ const AddEditLiquidity: React.FC = () => { } }, [tokenAmountsError, toast]); - // hanlde uniswap error + // handle uniswap error useEffect(() => { - if (uniswapPositionError) { + if (uniswapPositionError && isEdit) { console.error('uniswapPositionError: ', uniswapPositionError); toast({ title: 'Failed to get position from uniswap', @@ -650,7 +652,7 @@ const AddEditLiquidity: React.FC = () => { duration: 5000, }); } - }, [uniswapPositionError, toast]); + }, [uniswapPositionError, isEdit, toast]); useEffect(() => { if (isEdit) return; @@ -920,6 +922,7 @@ const AddEditLiquidity: React.FC = () => { return ( ); diff --git a/packages/app/src/lib/components/foil/numberDisplay.tsx b/packages/app/src/lib/components/foil/numberDisplay.tsx index fc79cbcc..ee0ea9d2 100644 --- a/packages/app/src/lib/components/foil/numberDisplay.tsx +++ b/packages/app/src/lib/components/foil/numberDisplay.tsx @@ -10,9 +10,13 @@ import { type NumberDisplayProps = { value: number | string | bigint; + precision?: number; }; -const NumberDisplay: React.FC = ({ value }) => { +const NumberDisplay: React.FC = ({ + value, + precision = 4, +}) => { const formatNumber = (val: bigint | number | string): string => { let numValue: number; let stringValue: string; @@ -34,30 +38,35 @@ const NumberDisplay: React.FC = ({ value }) => { return 'Invalid number'; } - if (Math.abs(numValue) < 0.0001 && numValue !== 0) { - return '<0.0001'; + if (Math.abs(numValue) < 1 / 10 ** precision && numValue !== 0) { + return `<${1 / 10 ** precision}`; } - const roundedValue = Number(numValue.toFixed(4)); + const roundedValue = Number(numValue.toFixed(precision)); return roundedValue.toString(); }; const displayValue = formatNumber(value || 0); + const originalValue = value.toString(); - return displayValue.length ? ( + if (!displayValue.length) { + return ; + } + + if (displayValue === originalValue) { + return {displayValue}; + } + + return ( {displayValue} - - {value.toString()} - + {originalValue} - ) : ( - ); }; diff --git a/packages/app/src/lib/layout/Header.tsx b/packages/app/src/lib/layout/Header.tsx index ebdfe4d8..621b6ba7 100644 --- a/packages/app/src/lib/layout/Header.tsx +++ b/packages/app/src/lib/layout/Header.tsx @@ -6,6 +6,7 @@ import { usePathname } from 'next/navigation'; import React, { useState, useEffect } from 'react'; import ConnectButton from '../components/ConnectButton'; +import { EpochTiming } from '../components/foil/EpochTiming'; import { ModeToggle } from '../components/ModeToggle'; import { Accordion, @@ -50,16 +51,7 @@ const ResourcePopover = ({ label, path }: { label: string; path: string }) => { }, [hoveredResource, resources]); const formatDuration = (start: number, end: number) => { - const endDate = new Date(end * 1000); - const weeks = Math.round((end - start) / (7 * 24 * 3600)); - return ( - <> - Ends {format(endDate, 'M/d')} - - {weeks} week period - - - ); + return ; }; const handleLinkClick = () => { @@ -205,17 +197,7 @@ const NavLinks = ({ }; const formatDuration = (start: number, end: number) => { - const startDate = new Date(start * 1000); - const endDate = new Date(end * 1000); - const weeks = Math.round((end - start) / (7 * 24 * 3600)); - return ( - <> - {format(endDate, 'M/d')} - - {weeks} week period - - - ); + return ; }; const renderMobileMarketLinks = (path: string) => { diff --git a/packages/protocol/src/market/modules/TradeModule.sol b/packages/protocol/src/market/modules/TradeModule.sol index f6ddea84..c0880772 100644 --- a/packages/protocol/src/market/modules/TradeModule.sol +++ b/packages/protocol/src/market/modules/TradeModule.sol @@ -45,10 +45,6 @@ contract TradeModule is ITradeModule, ReentrancyGuardUpgradeable { Epoch.Data storage epoch = Epoch.load(epochId); - if (block.timestamp < epoch.startTime) { - revert Errors.EpochNotStarted(epochId, epoch.startTime); - } - // check if epoch is not settled epoch.validateNotSettled(); diff --git a/packages/protocol/src/market/modules/UMASettlementModule.sol b/packages/protocol/src/market/modules/UMASettlementModule.sol index 619d333b..60734c45 100644 --- a/packages/protocol/src/market/modules/UMASettlementModule.sol +++ b/packages/protocol/src/market/modules/UMASettlementModule.sol @@ -45,6 +45,10 @@ contract UMASettlementModule is epoch.marketParams.bondAmount ); + uint256 decimalPrice = DecimalPrice.sqrtRatioX96ToPrice( + settlementSqrtPriceX96 + ); + bytes memory claim = abi.encodePacked( string(epoch.marketParams.claimStatement), " between timestamps ", @@ -52,7 +56,7 @@ contract UMASettlementModule is " and ", Strings.toString(epoch.endTime), " (inclusive) is ", - Strings.toString(settlementSqrtPriceX96), + Strings.toString(decimalPrice), "." ); diff --git a/packages/protocol/src/market/storage/Errors.sol b/packages/protocol/src/market/storage/Errors.sol index 4e537be9..ef3a084c 100644 --- a/packages/protocol/src/market/storage/Errors.sol +++ b/packages/protocol/src/market/storage/Errors.sol @@ -14,7 +14,6 @@ library Errors { error EpochNotSettled(uint256 epochId); error ExpiredEpochNotSettled(uint256 epochEndTime); error EpochAlreadyStarted(); - error EpochNotStarted(uint256 epochId, uint256 epochStartTime); error EpochSettled(); error ExpiredEpoch(); error TokensAlreadyCreated();